/**
* @license
* Cesium - https://github.com/CesiumGS/cesium
* Version 1.133
*
* Copyright 2011-2022 Cesium Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Columbus View (Pat. Pend.)
*
* Portions licensed separately.
* See https://github.com/CesiumGS/cesium/blob/main/LICENSE.md for full licensing details.
*/
var Cesium = (() => {
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
get: (a3, b) => (typeof require !== "undefined" ? require : a3)[b]
}) : x)(function(x) {
if (typeof require !== "undefined") return require.apply(this, arguments);
throw Error('Dynamic require of "' + x + '" is not supported');
});
var __commonJS = (cb, mod2) => function __require2() {
return mod2 || (0, cb[__getOwnPropNames(cb)[0]])((mod2 = { exports: {} }).exports, mod2), mod2.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target,
mod2
));
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
// Build/InlineWorkers.js
var require_InlineWorkers = __commonJS({
"Build/InlineWorkers.js"() {
globalThis.CESIUM_WORKERS = atob("dmFyIENlc2l1bVdvcmtlcnMgPSAoKCkgPT4gewogIHZhciBfX2NyZWF0ZSA9IE9iamVjdC5jcmVhdGU7CiAgdmFyIF9fZGVmUHJvcCA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTsKICB2YXIgX19nZXRPd25Qcm9wRGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7CiAgdmFyIF9fZ2V0T3duUHJvcE5hbWVzID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXM7CiAgdmFyIF9fZ2V0UHJvdG9PZiA9IE9iamVjdC5nZXRQcm90b3R5cGVPZjsKICB2YXIgX19oYXNPd25Qcm9wID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTsKICB2YXIgX19yZXF1aXJlID0gLyogQF9fUFVSRV9fICovICgoeCkgPT4gdHlwZW9mIHJlcXVpcmUgIT09ICJ1bmRlZmluZWQiID8gcmVxdWlyZSA6IHR5cGVvZiBQcm94eSAhPT0gInVuZGVmaW5lZCIgPyBuZXcgUHJveHkoeCwgewogICAgZ2V0OiAoYTMsIGIpID0+ICh0eXBlb2YgcmVxdWlyZSAhPT0gInVuZGVmaW5lZCIgPyByZXF1aXJlIDogYTMpW2JdCiAgfSkgOiB4KShmdW5jdGlvbih4KSB7CiAgICBpZiAodHlwZW9mIHJlcXVpcmUgIT09ICJ1bmRlZmluZWQiKSByZXR1cm4gcmVxdWlyZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgdGhyb3cgRXJyb3IoJ0R5bmFtaWMgcmVxdWlyZSBvZiAiJyArIHggKyAnIiBpcyBub3Qgc3VwcG9ydGVkJyk7CiAgfSk7CiAgdmFyIF9fZ2xvYiA9IChtYXApID0+IChwYXRoKSA9PiB7CiAgICB2YXIgZm4gPSBtYXBbcGF0aF07CiAgICBpZiAoZm4pIHJldHVybiBmbigpOwogICAgdGhyb3cgbmV3IEVycm9yKCJNb2R1bGUgbm90IGZvdW5kIGluIGJ1bmRsZTogIiArIHBhdGgpOwogIH07CiAgdmFyIF9fZXNtID0gKGZuLCByZXMpID0+IGZ1bmN0aW9uIF9faW5pdCgpIHsKICAgIHJldHVybiBmbiAmJiAocmVzID0gKDAsIGZuW19fZ2V0T3duUHJvcE5hbWVzKGZuKVswXV0pKGZuID0gMCkpLCByZXM7CiAgfTsKICB2YXIgX19jb21tb25KUyA9IChjYiwgbW9kKSA9PiBmdW5jdGlvbiBfX3JlcXVpcmUyKCkgewogICAgcmV0dXJuIG1vZCB8fCAoMCwgY2JbX19nZXRPd25Qcm9wTmFtZXMoY2IpWzBdXSkoKG1vZCA9IHsgZXhwb3J0czoge30gfSkuZXhwb3J0cywgbW9kKSwgbW9kLmV4cG9ydHM7CiAgfTsKICB2YXIgX19leHBvcnQgPSAodGFyZ2V0LCBhbGwpID0+IHsKICAgIGZvciAodmFyIG5hbWUgaW4gYWxsKQogICAgICBfX2RlZlByb3AodGFyZ2V0LCBuYW1lLCB7IGdldDogYWxsW25hbWVdLCBlbnVtZXJhYmxlOiB0cnVlIH0pOwogIH07CiAgdmFyIF9fY29weVByb3BzID0gKHRvLCBmcm9tLCBleGNlcHQsIGRlc2MpID0+IHsKICAgIGlmIChmcm9tICYmIHR5cGVvZiBmcm9tID09PSAib2JqZWN0IiB8fCB0eXBlb2YgZnJvbSA9PT0gImZ1bmN0aW9uIikgewogICAgICBmb3IgKGxldCBrZXkgb2YgX19nZXRPd25Qcm9wTmFtZXMoZnJvbSkpCiAgICAgICAgaWYgKCFfX2hhc093blByb3AuY2FsbCh0bywga2V5KSAmJiBrZXkgIT09IGV4Y2VwdCkKICAgICAgICAgIF9fZGVmUHJvcCh0bywga2V5LCB7IGdldDogKCkgPT4gZnJvbVtrZXldLCBlbnVtZXJhYmxlOiAhKGRlc2MgPSBfX2dldE93blByb3BEZXNjKGZyb20sIGtleSkpIHx8IGRlc2MuZW51bWVyYWJsZSB9KTsKICAgIH0KICAgIHJldHVybiB0bzsKICB9OwogIHZhciBfX3RvRVNNID0gKG1vZCwgaXNOb2RlTW9kZSwgdGFyZ2V0KSA9PiAodGFyZ2V0ID0gbW9kICE9IG51bGwgPyBfX2NyZWF0ZShfX2dldFByb3RvT2YobW9kKSkgOiB7fSwgX19jb3B5UHJvcHMoCiAgICAvLyBJZiB0aGUgaW1wb3J0ZXIgaXMgaW4gbm9kZSBjb21wYXRpYmlsaXR5IG1vZGUgb3IgdGhpcyBpcyBub3QgYW4gRVNNCiAgICAvLyBmaWxlIHRoYXQgaGFzIGJlZW4gY29udmVydGVkIHRvIGEgQ29tbW9uSlMgZmlsZSB1c2luZyBhIEJhYmVsLQogICAgLy8gY29tcGF0aWJsZSB0cmFuc2Zvcm0gKGkuZS4gIl9fZXNNb2R1bGUiIGhhcyBub3QgYmVlbiBzZXQpLCB0aGVuIHNldAogICAgLy8gImRlZmF1bHQiIHRvIHRoZSBDb21tb25KUyAibW9kdWxlLmV4cG9ydHMiIGZvciBub2RlIGNvbXBhdGliaWxpdHkuCiAgICBpc05vZGVNb2RlIHx8ICFtb2QgfHwgIW1vZC5fX2VzTW9kdWxlID8gX19kZWZQcm9wKHRhcmdldCwgImRlZmF1bHQiLCB7IHZhbHVlOiBtb2QsIGVudW1lcmFibGU6IHRydWUgfSkgOiB0YXJnZXQsCiAgICBtb2QKICApKTsKICB2YXIgX190b0NvbW1vbkpTID0gKG1vZCkgPT4gX19jb3B5UHJvcHMoX19kZWZQcm9wKHt9LCAiX19lc01vZHVsZSIsIHsgdmFsdWU6IHRydWUgfSksIG1vZCk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9kZWZpbmVkLmpzCiAgZnVuY3Rpb24gZGVmaW5lZCh2YWx1ZSkgewogICAgcmV0dXJuIHZhbHVlICE9PSB2b2lkIDAgJiYgdmFsdWUgIT09IG51bGw7CiAgfQogIHZhciBkZWZpbmVkX2RlZmF1bHQ7CiAgdmFyIGluaXRfZGVmaW5lZCA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvZGVmaW5lZC5qcyIoKSB7CiAgICAgIGRlZmluZWRfZGVmYXVsdCA9IGRlZmluZWQ7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9EZXZlbG9wZXJFcnJvci5qcwogIGZ1bmN0aW9uIERldmVsb3BlckVycm9yKG1lc3NhZ2UpIHsKICAgIHRoaXMubmFtZSA9ICJEZXZlbG9wZXJFcnJvciI7CiAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlOwogICAgbGV0IHN0YWNrOwogICAgdHJ5IHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHN0YWNrID0gZS5zdGFjazsKICAgIH0KICAgIHRoaXMuc3RhY2sgPSBzdGFjazsKICB9CiAgdmFyIERldmVsb3BlckVycm9yX2RlZmF1bHQ7CiAgdmFyIGluaXRfRGV2ZWxvcGVyRXJyb3IgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0RldmVsb3BlckVycm9yLmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoT2JqZWN0LmNyZWF0ZSkpIHsKICAgICAgICBEZXZlbG9wZXJFcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEVycm9yLnByb3RvdHlwZSk7CiAgICAgICAgRGV2ZWxvcGVyRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gRGV2ZWxvcGVyRXJyb3I7CiAgICAgIH0KICAgICAgRGV2ZWxvcGVyRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IHN0ciA9IGAke3RoaXMubmFtZX06ICR7dGhpcy5tZXNzYWdlfWA7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdCh0aGlzLnN0YWNrKSkgewogICAgICAgICAgc3RyICs9IGAKJHt0aGlzLnN0YWNrLnRvU3RyaW5nKCl9YDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHN0cjsKICAgICAgfTsKICAgICAgRGV2ZWxvcGVyRXJyb3IudGhyb3dJbnN0YW50aWF0aW9uRXJyb3IgPSBmdW5jdGlvbigpIHsKICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3IoCiAgICAgICAgICAiVGhpcyBmdW5jdGlvbiBkZWZpbmVzIGFuIGludGVyZmFjZSBhbmQgc2hvdWxkIG5vdCBiZSBjYWxsZWQgZGlyZWN0bHkuIgogICAgICAgICk7CiAgICAgIH07CiAgICAgIERldmVsb3BlckVycm9yX2RlZmF1bHQgPSBEZXZlbG9wZXJFcnJvcjsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NoZWNrLmpzCiAgZnVuY3Rpb24gZ2V0VW5kZWZpbmVkRXJyb3JNZXNzYWdlKG5hbWUpIHsKICAgIHJldHVybiBgJHtuYW1lfSBpcyByZXF1aXJlZCwgYWN0dWFsIHZhbHVlIHdhcyB1bmRlZmluZWRgOwogIH0KICBmdW5jdGlvbiBnZXRGYWlsZWRUeXBlRXJyb3JNZXNzYWdlKGFjdHVhbCwgZXhwZWN0ZWQsIG5hbWUpIHsKICAgIHJldHVybiBgRXhwZWN0ZWQgJHtuYW1lfSB0byBiZSB0eXBlb2YgJHtleHBlY3RlZH0sIGFjdHVhbCB0eXBlb2Ygd2FzICR7YWN0dWFsfWA7CiAgfQogIHZhciBDaGVjaywgQ2hlY2tfZGVmYXVsdDsKICB2YXIgaW5pdF9DaGVjayA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ2hlY2suanMiKCkgewogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBDaGVjayA9IHt9OwogICAgICBDaGVjay50eXBlT2YgPSB7fTsKICAgICAgQ2hlY2suZGVmaW5lZCA9IGZ1bmN0aW9uKG5hbWUsIHRlc3QpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh0ZXN0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoZ2V0VW5kZWZpbmVkRXJyb3JNZXNzYWdlKG5hbWUpKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIENoZWNrLnR5cGVPZi5mdW5jID0gZnVuY3Rpb24obmFtZSwgdGVzdCkgewogICAgICAgIGlmICh0eXBlb2YgdGVzdCAhPT0gImZ1bmN0aW9uIikgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgIGdldEZhaWxlZFR5cGVFcnJvck1lc3NhZ2UodHlwZW9mIHRlc3QsICJmdW5jdGlvbiIsIG5hbWUpCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfTsKICAgICAgQ2hlY2sudHlwZU9mLnN0cmluZyA9IGZ1bmN0aW9uKG5hbWUsIHRlc3QpIHsKICAgICAgICBpZiAodHlwZW9mIHRlc3QgIT09ICJzdHJpbmciKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgZ2V0RmFpbGVkVHlwZUVycm9yTWVzc2FnZSh0eXBlb2YgdGVzdCwgInN0cmluZyIsIG5hbWUpCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfTsKICAgICAgQ2hlY2sudHlwZU9mLm51bWJlciA9IGZ1bmN0aW9uKG5hbWUsIHRlc3QpIHsKICAgICAgICBpZiAodHlwZW9mIHRlc3QgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgZ2V0RmFpbGVkVHlwZUVycm9yTWVzc2FnZSh0eXBlb2YgdGVzdCwgIm51bWJlciIsIG5hbWUpCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfTsKICAgICAgQ2hlY2sudHlwZU9mLm51bWJlci5sZXNzVGhhbiA9IGZ1bmN0aW9uKG5hbWUsIHRlc3QsIGxpbWl0KSB7CiAgICAgICAgQ2hlY2sudHlwZU9mLm51bWJlcihuYW1lLCB0ZXN0KTsKICAgICAgICBpZiAodGVzdCA+PSBsaW1pdCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgIGBFeHBlY3RlZCAke25hbWV9IHRvIGJlIGxlc3MgdGhhbiAke2xpbWl0fSwgYWN0dWFsIHZhbHVlIHdhcyAke3Rlc3R9YAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIENoZWNrLnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscyA9IGZ1bmN0aW9uKG5hbWUsIHRlc3QsIGxpbWl0KSB7CiAgICAgICAgQ2hlY2sudHlwZU9mLm51bWJlcihuYW1lLCB0ZXN0KTsKICAgICAgICBpZiAodGVzdCA+IGxpbWl0KSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgYEV4cGVjdGVkICR7bmFtZX0gdG8gYmUgbGVzcyB0aGFuIG9yIGVxdWFsIHRvICR7bGltaXR9LCBhY3R1YWwgdmFsdWUgd2FzICR7dGVzdH1gCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfTsKICAgICAgQ2hlY2sudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbiA9IGZ1bmN0aW9uKG5hbWUsIHRlc3QsIGxpbWl0KSB7CiAgICAgICAgQ2hlY2sudHlwZU9mLm51bWJlcihuYW1lLCB0ZXN0KTsKICAgICAgICBpZiAodGVzdCA8PSBsaW1pdCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgIGBFeHBlY3RlZCAke25hbWV9IHRvIGJlIGdyZWF0ZXIgdGhhbiAke2xpbWl0fSwgYWN0dWFsIHZhbHVlIHdhcyAke3Rlc3R9YAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIENoZWNrLnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscyA9IGZ1bmN0aW9uKG5hbWUsIHRlc3QsIGxpbWl0KSB7CiAgICAgICAgQ2hlY2sudHlwZU9mLm51bWJlcihuYW1lLCB0ZXN0KTsKICAgICAgICBpZiAodGVzdCA8IGxpbWl0KSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgYEV4cGVjdGVkICR7bmFtZX0gdG8gYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvICR7bGltaXR9LCBhY3R1YWwgdmFsdWUgd2FzICR7dGVzdH1gCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfTsKICAgICAgQ2hlY2sudHlwZU9mLm9iamVjdCA9IGZ1bmN0aW9uKG5hbWUsIHRlc3QpIHsKICAgICAgICBpZiAodHlwZW9mIHRlc3QgIT09ICJvYmplY3QiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgZ2V0RmFpbGVkVHlwZUVycm9yTWVzc2FnZSh0eXBlb2YgdGVzdCwgIm9iamVjdCIsIG5hbWUpCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfTsKICAgICAgQ2hlY2sudHlwZU9mLmJvb2wgPSBmdW5jdGlvbihuYW1lLCB0ZXN0KSB7CiAgICAgICAgaWYgKHR5cGVvZiB0ZXN0ICE9PSAiYm9vbGVhbiIpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICBnZXRGYWlsZWRUeXBlRXJyb3JNZXNzYWdlKHR5cGVvZiB0ZXN0LCAiYm9vbGVhbiIsIG5hbWUpCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfTsKICAgICAgQ2hlY2sudHlwZU9mLmJpZ2ludCA9IGZ1bmN0aW9uKG5hbWUsIHRlc3QpIHsKICAgICAgICBpZiAodHlwZW9mIHRlc3QgIT09ICJiaWdpbnQiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgZ2V0RmFpbGVkVHlwZUVycm9yTWVzc2FnZSh0eXBlb2YgdGVzdCwgImJpZ2ludCIsIG5hbWUpCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfTsKICAgICAgQ2hlY2sudHlwZU9mLm51bWJlci5lcXVhbHMgPSBmdW5jdGlvbihuYW1lMSwgbmFtZTIsIHRlc3QxLCB0ZXN0MikgewogICAgICAgIENoZWNrLnR5cGVPZi5udW1iZXIobmFtZTEsIHRlc3QxKTsKICAgICAgICBDaGVjay50eXBlT2YubnVtYmVyKG5hbWUyLCB0ZXN0Mik7CiAgICAgICAgaWYgKHRlc3QxICE9PSB0ZXN0MikgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgIGAke25hbWUxfSBtdXN0IGJlIGVxdWFsIHRvICR7bmFtZTJ9LCB0aGUgYWN0dWFsIHZhbHVlcyBhcmUgJHt0ZXN0MX0gYW5kICR7dGVzdDJ9YAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIENoZWNrX2RlZmF1bHQgPSBDaGVjazsKICAgIH0KICB9KTsKCiAgLy8gbm9kZV9tb2R1bGVzL21lcnNlbm5lLXR3aXN0ZXIvc3JjL21lcnNlbm5lLXR3aXN0ZXIuanMKICB2YXIgcmVxdWlyZV9tZXJzZW5uZV90d2lzdGVyID0gX19jb21tb25KUyh7CiAgICAibm9kZV9tb2R1bGVzL21lcnNlbm5lLXR3aXN0ZXIvc3JjL21lcnNlbm5lLXR3aXN0ZXIuanMiKGV4cG9ydHMyLCBtb2R1bGUpIHsKICAgICAgdmFyIE1lcnNlbm5lVHdpc3RlcjIgPSBmdW5jdGlvbihzZWVkKSB7CiAgICAgICAgaWYgKHNlZWQgPT0gdm9pZCAwKSB7CiAgICAgICAgICBzZWVkID0gKC8qIEBfX1BVUkVfXyAqLyBuZXcgRGF0ZSgpKS5nZXRUaW1lKCk7CiAgICAgICAgfQogICAgICAgIHRoaXMuTiA9IDYyNDsKICAgICAgICB0aGlzLk0gPSAzOTc7CiAgICAgICAgdGhpcy5NQVRSSVhfQSA9IDI1Njc0ODM2MTU7CiAgICAgICAgdGhpcy5VUFBFUl9NQVNLID0gMjE0NzQ4MzY0ODsKICAgICAgICB0aGlzLkxPV0VSX01BU0sgPSAyMTQ3NDgzNjQ3OwogICAgICAgIHRoaXMubXQgPSBuZXcgQXJyYXkodGhpcy5OKTsKICAgICAgICB0aGlzLm10aSA9IHRoaXMuTiArIDE7CiAgICAgICAgaWYgKHNlZWQuY29uc3RydWN0b3IgPT0gQXJyYXkpIHsKICAgICAgICAgIHRoaXMuaW5pdF9ieV9hcnJheShzZWVkLCBzZWVkLmxlbmd0aCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuaW5pdF9zZWVkKHNlZWQpOwogICAgICAgIH0KICAgICAgfTsKICAgICAgTWVyc2VubmVUd2lzdGVyMi5wcm90b3R5cGUuaW5pdF9zZWVkID0gZnVuY3Rpb24ocykgewogICAgICAgIHRoaXMubXRbMF0gPSBzID4+PiAwOwogICAgICAgIGZvciAodGhpcy5tdGkgPSAxOyB0aGlzLm10aSA8IHRoaXMuTjsgdGhpcy5tdGkrKykgewogICAgICAgICAgdmFyIHMgPSB0aGlzLm10W3RoaXMubXRpIC0gMV0gXiB0aGlzLm10W3RoaXMubXRpIC0gMV0gPj4+IDMwOwogICAgICAgICAgdGhpcy5tdFt0aGlzLm10aV0gPSAoKChzICYgNDI5NDkwMTc2MCkgPj4+IDE2KSAqIDE4MTI0MzMyNTMgPDwgMTYpICsgKHMgJiA2NTUzNSkgKiAxODEyNDMzMjUzICsgdGhpcy5tdGk7CiAgICAgICAgICB0aGlzLm10W3RoaXMubXRpXSA+Pj49IDA7CiAgICAgICAgfQogICAgICB9OwogICAgICBNZXJzZW5uZVR3aXN0ZXIyLnByb3RvdHlwZS5pbml0X2J5X2FycmF5ID0gZnVuY3Rpb24oaW5pdF9rZXksIGtleV9sZW5ndGgpIHsKICAgICAgICB2YXIgaSwgaiwgazsKICAgICAgICB0aGlzLmluaXRfc2VlZCgxOTY1MDIxOCk7CiAgICAgICAgaSA9IDE7CiAgICAgICAgaiA9IDA7CiAgICAgICAgayA9IHRoaXMuTiA+IGtleV9sZW5ndGggPyB0aGlzLk4gOiBrZXlfbGVuZ3RoOwogICAgICAgIGZvciAoOyBrOyBrLS0pIHsKICAgICAgICAgIHZhciBzID0gdGhpcy5tdFtpIC0gMV0gXiB0aGlzLm10W2kgLSAxXSA+Pj4gMzA7CiAgICAgICAgICB0aGlzLm10W2ldID0gKHRoaXMubXRbaV0gXiAoKChzICYgNDI5NDkwMTc2MCkgPj4+IDE2KSAqIDE2NjQ1MjUgPDwgMTYpICsgKHMgJiA2NTUzNSkgKiAxNjY0NTI1KSArIGluaXRfa2V5W2pdICsgajsKICAgICAgICAgIHRoaXMubXRbaV0gPj4+PSAwOwogICAgICAgICAgaSsrOwogICAgICAgICAgaisrOwogICAgICAgICAgaWYgKGkgPj0gdGhpcy5OKSB7CiAgICAgICAgICAgIHRoaXMubXRbMF0gPSB0aGlzLm10W3RoaXMuTiAtIDFdOwogICAgICAgICAgICBpID0gMTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChqID49IGtleV9sZW5ndGgpIGogPSAwOwogICAgICAgIH0KICAgICAgICBmb3IgKGsgPSB0aGlzLk4gLSAxOyBrOyBrLS0pIHsKICAgICAgICAgIHZhciBzID0gdGhpcy5tdFtpIC0gMV0gXiB0aGlzLm10W2kgLSAxXSA+Pj4gMzA7CiAgICAgICAgICB0aGlzLm10W2ldID0gKHRoaXMubXRbaV0gXiAoKChzICYgNDI5NDkwMTc2MCkgPj4+IDE2KSAqIDE1NjYwODM5NDEgPDwgMTYpICsgKHMgJiA2NTUzNSkgKiAxNTY2MDgzOTQxKSAtIGk7CiAgICAgICAgICB0aGlzLm10W2ldID4+Pj0gMDsKICAgICAgICAgIGkrKzsKICAgICAgICAgIGlmIChpID49IHRoaXMuTikgewogICAgICAgICAgICB0aGlzLm10WzBdID0gdGhpcy5tdFt0aGlzLk4gLSAxXTsKICAgICAgICAgICAgaSA9IDE7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHRoaXMubXRbMF0gPSAyMTQ3NDgzNjQ4OwogICAgICB9OwogICAgICBNZXJzZW5uZVR3aXN0ZXIyLnByb3RvdHlwZS5yYW5kb21faW50ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgdmFyIHk7CiAgICAgICAgdmFyIG1hZzAxID0gbmV3IEFycmF5KDAsIHRoaXMuTUFUUklYX0EpOwogICAgICAgIGlmICh0aGlzLm10aSA+PSB0aGlzLk4pIHsKICAgICAgICAgIHZhciBrazsKICAgICAgICAgIGlmICh0aGlzLm10aSA9PSB0aGlzLk4gKyAxKQogICAgICAgICAgICB0aGlzLmluaXRfc2VlZCg1NDg5KTsKICAgICAgICAgIGZvciAoa2sgPSAwOyBrayA8IHRoaXMuTiAtIHRoaXMuTTsga2srKykgewogICAgICAgICAgICB5ID0gdGhpcy5tdFtra10gJiB0aGlzLlVQUEVSX01BU0sgfCB0aGlzLm10W2trICsgMV0gJiB0aGlzLkxPV0VSX01BU0s7CiAgICAgICAgICAgIHRoaXMubXRba2tdID0gdGhpcy5tdFtrayArIHRoaXMuTV0gXiB5ID4+PiAxIF4gbWFnMDFbeSAmIDFdOwogICAgICAgICAgfQogICAgICAgICAgZm9yICg7IGtrIDwgdGhpcy5OIC0gMTsga2srKykgewogICAgICAgICAgICB5ID0gdGhpcy5tdFtra10gJiB0aGlzLlVQUEVSX01BU0sgfCB0aGlzLm10W2trICsgMV0gJiB0aGlzLkxPV0VSX01BU0s7CiAgICAgICAgICAgIHRoaXMubXRba2tdID0gdGhpcy5tdFtrayArICh0aGlzLk0gLSB0aGlzLk4pXSBeIHkgPj4+IDEgXiBtYWcwMVt5ICYgMV07CiAgICAgICAgICB9CiAgICAgICAgICB5ID0gdGhpcy5tdFt0aGlzLk4gLSAxXSAmIHRoaXMuVVBQRVJfTUFTSyB8IHRoaXMubXRbMF0gJiB0aGlzLkxPV0VSX01BU0s7CiAgICAgICAgICB0aGlzLm10W3RoaXMuTiAtIDFdID0gdGhpcy5tdFt0aGlzLk0gLSAxXSBeIHkgPj4+IDEgXiBtYWcwMVt5ICYgMV07CiAgICAgICAgICB0aGlzLm10aSA9IDA7CiAgICAgICAgfQogICAgICAgIHkgPSB0aGlzLm10W3RoaXMubXRpKytdOwogICAgICAgIHkgXj0geSA+Pj4gMTE7CiAgICAgICAgeSBePSB5IDw8IDcgJiAyNjM2OTI4NjQwOwogICAgICAgIHkgXj0geSA8PCAxNSAmIDQwMjI3MzA3NTI7CiAgICAgICAgeSBePSB5ID4+PiAxODsKICAgICAgICByZXR1cm4geSA+Pj4gMDsKICAgICAgfTsKICAgICAgTWVyc2VubmVUd2lzdGVyMi5wcm90b3R5cGUucmFuZG9tX2ludDMxID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIHRoaXMucmFuZG9tX2ludCgpID4+PiAxOwogICAgICB9OwogICAgICBNZXJzZW5uZVR3aXN0ZXIyLnByb3RvdHlwZS5yYW5kb21faW5jbCA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiB0aGlzLnJhbmRvbV9pbnQoKSAqICgxIC8gNDI5NDk2NzI5NSk7CiAgICAgIH07CiAgICAgIE1lcnNlbm5lVHdpc3RlcjIucHJvdG90eXBlLnJhbmRvbSA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiB0aGlzLnJhbmRvbV9pbnQoKSAqICgxIC8gNDI5NDk2NzI5Nik7CiAgICAgIH07CiAgICAgIE1lcnNlbm5lVHdpc3RlcjIucHJvdG90eXBlLnJhbmRvbV9leGNsID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuICh0aGlzLnJhbmRvbV9pbnQoKSArIDAuNSkgKiAoMSAvIDQyOTQ5NjcyOTYpOwogICAgICB9OwogICAgICBNZXJzZW5uZVR3aXN0ZXIyLnByb3RvdHlwZS5yYW5kb21fbG9uZyA9IGZ1bmN0aW9uKCkgewogICAgICAgIHZhciBhMyA9IHRoaXMucmFuZG9tX2ludCgpID4+PiA1LCBiID0gdGhpcy5yYW5kb21faW50KCkgPj4+IDY7CiAgICAgICAgcmV0dXJuIChhMyAqIDY3MTA4ODY0ICsgYikgKiAoMSAvIDkwMDcxOTkyNTQ3NDA5OTIpOwogICAgICB9OwogICAgICBtb2R1bGUuZXhwb3J0cyA9IE1lcnNlbm5lVHdpc3RlcjI7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9NYXRoLmpzCiAgdmFyIGltcG9ydF9tZXJzZW5uZV90d2lzdGVyLCBDZXNpdW1NYXRoLCBmYWN0b3JpYWxzLCByYW5kb21OdW1iZXJHZW5lcmF0b3IsIE1hdGhfZGVmYXVsdDsKICB2YXIgaW5pdF9NYXRoID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9NYXRoLmpzIigpIHsKICAgICAgaW1wb3J0X21lcnNlbm5lX3R3aXN0ZXIgPSBfX3RvRVNNKHJlcXVpcmVfbWVyc2VubmVfdHdpc3RlcigpLCAxKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBDZXNpdW1NYXRoID0ge307CiAgICAgIENlc2l1bU1hdGguRVBTSUxPTjEgPSAwLjE7CiAgICAgIENlc2l1bU1hdGguRVBTSUxPTjIgPSAwLjAxOwogICAgICBDZXNpdW1NYXRoLkVQU0lMT04zID0gMWUtMzsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9ONCA9IDFlLTQ7CiAgICAgIENlc2l1bU1hdGguRVBTSUxPTjUgPSAxZS01OwogICAgICBDZXNpdW1NYXRoLkVQU0lMT042ID0gMWUtNjsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9ONyA9IDFlLTc7CiAgICAgIENlc2l1bU1hdGguRVBTSUxPTjggPSAxZS04OwogICAgICBDZXNpdW1NYXRoLkVQU0lMT045ID0gMWUtOTsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMTAgPSAxZS0xMDsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMTEgPSAxZS0xMTsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMTIgPSAxZS0xMjsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMTMgPSAxZS0xMzsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMTQgPSAxZS0xNDsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMTUgPSAxZS0xNTsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMTYgPSAxZS0xNjsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMTcgPSAxZS0xNzsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMTggPSAxZS0xODsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMTkgPSAxZS0xOTsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMjAgPSAxZS0yMDsKICAgICAgQ2VzaXVtTWF0aC5FUFNJTE9OMjEgPSAxZS0yMTsKICAgICAgQ2VzaXVtTWF0aC5HUkFWSVRBVElPTkFMUEFSQU1FVEVSID0gMzk4NjAwNDQxOGU1OwogICAgICBDZXNpdW1NYXRoLlNPTEFSX1JBRElVUyA9IDY5NTVlNTsKICAgICAgQ2VzaXVtTWF0aC5MVU5BUl9SQURJVVMgPSAxNzM3NDAwOwogICAgICBDZXNpdW1NYXRoLlNJWFRZX0ZPVVJfS0lMT0JZVEVTID0gNjQgKiAxMDI0OwogICAgICBDZXNpdW1NYXRoLkZPVVJfR0lHQUJZVEVTID0gNCAqIDEwMjQgKiAxMDI0ICogMTAyNDsKICAgICAgQ2VzaXVtTWF0aC5zaWduID0gTWF0aC5zaWduID8/IGZ1bmN0aW9uIHNpZ24odmFsdWUpIHsKICAgICAgICB2YWx1ZSA9ICt2YWx1ZTsKICAgICAgICBpZiAodmFsdWUgPT09IDAgfHwgdmFsdWUgIT09IHZhbHVlKSB7CiAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiB2YWx1ZSA+IDAgPyAxIDogLTE7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGguc2lnbk5vdFplcm8gPSBmdW5jdGlvbih2YWx1ZSkgewogICAgICAgIHJldHVybiB2YWx1ZSA8IDAgPyAtMSA6IDE7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGgudG9TTm9ybSA9IGZ1bmN0aW9uKHZhbHVlLCByYW5nZU1heGltdW0pIHsKICAgICAgICByYW5nZU1heGltdW0gPSByYW5nZU1heGltdW0gPz8gMjU1OwogICAgICAgIHJldHVybiBNYXRoLnJvdW5kKAogICAgICAgICAgKENlc2l1bU1hdGguY2xhbXAodmFsdWUsIC0xLCAxKSAqIDAuNSArIDAuNSkgKiByYW5nZU1heGltdW0KICAgICAgICApOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLmZyb21TTm9ybSA9IGZ1bmN0aW9uKHZhbHVlLCByYW5nZU1heGltdW0pIHsKICAgICAgICByYW5nZU1heGltdW0gPSByYW5nZU1heGltdW0gPz8gMjU1OwogICAgICAgIHJldHVybiBDZXNpdW1NYXRoLmNsYW1wKHZhbHVlLCAwLCByYW5nZU1heGltdW0pIC8gcmFuZ2VNYXhpbXVtICogMiAtIDE7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGgubm9ybWFsaXplID0gZnVuY3Rpb24odmFsdWUsIHJhbmdlTWluaW11bSwgcmFuZ2VNYXhpbXVtKSB7CiAgICAgICAgcmFuZ2VNYXhpbXVtID0gTWF0aC5tYXgocmFuZ2VNYXhpbXVtIC0gcmFuZ2VNaW5pbXVtLCAwKTsKICAgICAgICByZXR1cm4gcmFuZ2VNYXhpbXVtID09PSAwID8gMCA6IENlc2l1bU1hdGguY2xhbXAoKHZhbHVlIC0gcmFuZ2VNaW5pbXVtKSAvIHJhbmdlTWF4aW11bSwgMCwgMSk7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGguc2luaCA9IE1hdGguc2luaCA/PyBmdW5jdGlvbiBzaW5oKHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIChNYXRoLmV4cCh2YWx1ZSkgLSBNYXRoLmV4cCgtdmFsdWUpKSAvIDI7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGguY29zaCA9IE1hdGguY29zaCA/PyBmdW5jdGlvbiBjb3NoKHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIChNYXRoLmV4cCh2YWx1ZSkgKyBNYXRoLmV4cCgtdmFsdWUpKSAvIDI7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGgubGVycCA9IGZ1bmN0aW9uKHAsIHEsIHRpbWUpIHsKICAgICAgICByZXR1cm4gKDEgLSB0aW1lKSAqIHAgKyB0aW1lICogcTsKICAgICAgfTsKICAgICAgQ2VzaXVtTWF0aC5QSSA9IE1hdGguUEk7CiAgICAgIENlc2l1bU1hdGguT05FX09WRVJfUEkgPSAxIC8gTWF0aC5QSTsKICAgICAgQ2VzaXVtTWF0aC5QSV9PVkVSX1RXTyA9IE1hdGguUEkgLyAyOwogICAgICBDZXNpdW1NYXRoLlBJX09WRVJfVEhSRUUgPSBNYXRoLlBJIC8gMzsKICAgICAgQ2VzaXVtTWF0aC5QSV9PVkVSX0ZPVVIgPSBNYXRoLlBJIC8gNDsKICAgICAgQ2VzaXVtTWF0aC5QSV9PVkVSX1NJWCA9IE1hdGguUEkgLyA2OwogICAgICBDZXNpdW1NYXRoLlRIUkVFX1BJX09WRVJfVFdPID0gMyAqIE1hdGguUEkgLyAyOwogICAgICBDZXNpdW1NYXRoLlRXT19QSSA9IDIgKiBNYXRoLlBJOwogICAgICBDZXNpdW1NYXRoLk9ORV9PVkVSX1RXT19QSSA9IDEgLyAoMiAqIE1hdGguUEkpOwogICAgICBDZXNpdW1NYXRoLlJBRElBTlNfUEVSX0RFR1JFRSA9IE1hdGguUEkgLyAxODA7CiAgICAgIENlc2l1bU1hdGguREVHUkVFU19QRVJfUkFESUFOID0gMTgwIC8gTWF0aC5QSTsKICAgICAgQ2VzaXVtTWF0aC5SQURJQU5TX1BFUl9BUkNTRUNPTkQgPSBDZXNpdW1NYXRoLlJBRElBTlNfUEVSX0RFR1JFRSAvIDM2MDA7CiAgICAgIENlc2l1bU1hdGgudG9SYWRpYW5zID0gZnVuY3Rpb24oZGVncmVlcykgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGRlZ3JlZXMpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZGVncmVlcyBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGRlZ3JlZXMgKiBDZXNpdW1NYXRoLlJBRElBTlNfUEVSX0RFR1JFRTsKICAgICAgfTsKICAgICAgQ2VzaXVtTWF0aC50b0RlZ3JlZXMgPSBmdW5jdGlvbihyYWRpYW5zKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmFkaWFucykpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJyYWRpYW5zIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmFkaWFucyAqIENlc2l1bU1hdGguREVHUkVFU19QRVJfUkFESUFOOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLmNvbnZlcnRMb25naXR1ZGVSYW5nZSA9IGZ1bmN0aW9uKGFuZ2xlKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYW5nbGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYW5nbGUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHR3b1BpID0gQ2VzaXVtTWF0aC5UV09fUEk7CiAgICAgICAgY29uc3Qgc2ltcGxpZmllZCA9IGFuZ2xlIC0gTWF0aC5mbG9vcihhbmdsZSAvIHR3b1BpKSAqIHR3b1BpOwogICAgICAgIGlmIChzaW1wbGlmaWVkIDwgLU1hdGguUEkpIHsKICAgICAgICAgIHJldHVybiBzaW1wbGlmaWVkICsgdHdvUGk7CiAgICAgICAgfQogICAgICAgIGlmIChzaW1wbGlmaWVkID49IE1hdGguUEkpIHsKICAgICAgICAgIHJldHVybiBzaW1wbGlmaWVkIC0gdHdvUGk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzaW1wbGlmaWVkOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLmNsYW1wVG9MYXRpdHVkZVJhbmdlID0gZnVuY3Rpb24oYW5nbGUpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhbmdsZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhbmdsZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIENlc2l1bU1hdGguY2xhbXAoCiAgICAgICAgICBhbmdsZSwKICAgICAgICAgIC0xICogQ2VzaXVtTWF0aC5QSV9PVkVSX1RXTywKICAgICAgICAgIENlc2l1bU1hdGguUElfT1ZFUl9UV08KICAgICAgICApOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLm5lZ2F0aXZlUGlUb1BpID0gZnVuY3Rpb24oYW5nbGUpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhbmdsZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhbmdsZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKGFuZ2xlID49IC1DZXNpdW1NYXRoLlBJICYmIGFuZ2xlIDw9IENlc2l1bU1hdGguUEkpIHsKICAgICAgICAgIHJldHVybiBhbmdsZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIENlc2l1bU1hdGguemVyb1RvVHdvUGkoYW5nbGUgKyBDZXNpdW1NYXRoLlBJKSAtIENlc2l1bU1hdGguUEk7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGguemVyb1RvVHdvUGkgPSBmdW5jdGlvbihhbmdsZSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFuZ2xlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFuZ2xlIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoYW5nbGUgPj0gMCAmJiBhbmdsZSA8PSBDZXNpdW1NYXRoLlRXT19QSSkgewogICAgICAgICAgcmV0dXJuIGFuZ2xlOwogICAgICAgIH0KICAgICAgICBjb25zdCBtb2QgPSBDZXNpdW1NYXRoLm1vZChhbmdsZSwgQ2VzaXVtTWF0aC5UV09fUEkpOwogICAgICAgIGlmIChNYXRoLmFicyhtb2QpIDwgQ2VzaXVtTWF0aC5FUFNJTE9OMTQgJiYgTWF0aC5hYnMoYW5nbGUpID4gQ2VzaXVtTWF0aC5FUFNJTE9OMTQpIHsKICAgICAgICAgIHJldHVybiBDZXNpdW1NYXRoLlRXT19QSTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG1vZDsKICAgICAgfTsKICAgICAgQ2VzaXVtTWF0aC5tb2QgPSBmdW5jdGlvbihtLCBuKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQobSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJtIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChuKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm4gaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmIChuID09PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZGl2aXNvciBjYW5ub3QgYmUgMC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKENlc2l1bU1hdGguc2lnbihtKSA9PT0gQ2VzaXVtTWF0aC5zaWduKG4pICYmIE1hdGguYWJzKG0pIDwgTWF0aC5hYnMobikpIHsKICAgICAgICAgIHJldHVybiBtOwogICAgICAgIH0KICAgICAgICByZXR1cm4gKG0gJSBuICsgbikgJSBuOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLmVxdWFsc0Vwc2lsb24gPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVsYXRpdmVFcHNpbG9uLCBhYnNvbHV0ZUVwc2lsb24pIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChsZWZ0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImxlZnQgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInJpZ2h0IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICByZWxhdGl2ZUVwc2lsb24gPSByZWxhdGl2ZUVwc2lsb24gPz8gMDsKICAgICAgICBhYnNvbHV0ZUVwc2lsb24gPSBhYnNvbHV0ZUVwc2lsb24gPz8gcmVsYXRpdmVFcHNpbG9uOwogICAgICAgIGNvbnN0IGFic0RpZmYgPSBNYXRoLmFicyhsZWZ0IC0gcmlnaHQpOwogICAgICAgIHJldHVybiBhYnNEaWZmIDw9IGFic29sdXRlRXBzaWxvbiB8fCBhYnNEaWZmIDw9IHJlbGF0aXZlRXBzaWxvbiAqIE1hdGgubWF4KE1hdGguYWJzKGxlZnQpLCBNYXRoLmFicyhyaWdodCkpOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLmxlc3NUaGFuID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIGFic29sdXRlRXBzaWxvbikgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGxlZnQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZmlyc3QgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInNlY29uZCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYWJzb2x1dGVFcHNpbG9uKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFic29sdXRlRXBzaWxvbiBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGxlZnQgLSByaWdodCA8IC1hYnNvbHV0ZUVwc2lsb247CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGgubGVzc1RoYW5PckVxdWFscyA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCBhYnNvbHV0ZUVwc2lsb24pIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChsZWZ0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImZpcnN0IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyaWdodCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJzZWNvbmQgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFic29sdXRlRXBzaWxvbikpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhYnNvbHV0ZUVwc2lsb24gaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBsZWZ0IC0gcmlnaHQgPCBhYnNvbHV0ZUVwc2lsb247CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGguZ3JlYXRlclRoYW4gPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgYWJzb2x1dGVFcHNpbG9uKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQobGVmdCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJmaXJzdCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmlnaHQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgic2Vjb25kIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhYnNvbHV0ZUVwc2lsb24pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYWJzb2x1dGVFcHNpbG9uIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbGVmdCAtIHJpZ2h0ID4gYWJzb2x1dGVFcHNpbG9uOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLmdyZWF0ZXJUaGFuT3JFcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgYWJzb2x1dGVFcHNpbG9uKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQobGVmdCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJmaXJzdCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmlnaHQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgic2Vjb25kIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhYnNvbHV0ZUVwc2lsb24pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYWJzb2x1dGVFcHNpbG9uIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbGVmdCAtIHJpZ2h0ID4gLWFic29sdXRlRXBzaWxvbjsKICAgICAgfTsKICAgICAgZmFjdG9yaWFscyA9IFsxXTsKICAgICAgQ2VzaXVtTWF0aC5mYWN0b3JpYWwgPSBmdW5jdGlvbihuKSB7CiAgICAgICAgaWYgKHR5cGVvZiBuICE9PSAibnVtYmVyIiB8fCBuIDwgMCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJBIG51bWJlciBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gMCBpcyByZXF1aXJlZC4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBsZW5ndGggPSBmYWN0b3JpYWxzLmxlbmd0aDsKICAgICAgICBpZiAobiA+PSBsZW5ndGgpIHsKICAgICAgICAgIGxldCBzdW0gPSBmYWN0b3JpYWxzW2xlbmd0aCAtIDFdOwogICAgICAgICAgZm9yIChsZXQgaSA9IGxlbmd0aDsgaSA8PSBuOyBpKyspIHsKICAgICAgICAgICAgY29uc3QgbmV4dCA9IHN1bSAqIGk7CiAgICAgICAgICAgIGZhY3RvcmlhbHMucHVzaChuZXh0KTsKICAgICAgICAgICAgc3VtID0gbmV4dDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGZhY3RvcmlhbHNbbl07CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGguaW5jcmVtZW50V3JhcCA9IGZ1bmN0aW9uKG4sIG1heGltdW1WYWx1ZSwgbWluaW11bVZhbHVlKSB7CiAgICAgICAgbWluaW11bVZhbHVlID0gbWluaW11bVZhbHVlID8/IDA7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQobikpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJuIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAobWF4aW11bVZhbHVlIDw9IG1pbmltdW1WYWx1ZSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm1heGltdW1WYWx1ZSBtdXN0IGJlIGdyZWF0ZXIgdGhhbiBtaW5pbXVtVmFsdWUuIik7CiAgICAgICAgfQogICAgICAgICsrbjsKICAgICAgICBpZiAobiA+IG1heGltdW1WYWx1ZSkgewogICAgICAgICAgbiA9IG1pbmltdW1WYWx1ZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG47CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGguaXNQb3dlck9mVHdvID0gZnVuY3Rpb24obikgewogICAgICAgIGlmICh0eXBlb2YgbiAhPT0gIm51bWJlciIgfHwgbiA8IDAgfHwgbiA+IDQyOTQ5NjcyOTUpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJBIG51bWJlciBiZXR3ZWVuIDAgYW5kICgyXjMyKS0xIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbiAhPT0gMCAmJiAobiAmIG4gLSAxKSA9PT0gMDsKICAgICAgfTsKICAgICAgQ2VzaXVtTWF0aC5uZXh0UG93ZXJPZlR3byA9IGZ1bmN0aW9uKG4pIHsKICAgICAgICBpZiAodHlwZW9mIG4gIT09ICJudW1iZXIiIHx8IG4gPCAwIHx8IG4gPiAyMTQ3NDgzNjQ4KSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiQSBudW1iZXIgYmV0d2VlbiAwIGFuZCAyXjMxIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICAtLW47CiAgICAgICAgbiB8PSBuID4+IDE7CiAgICAgICAgbiB8PSBuID4+IDI7CiAgICAgICAgbiB8PSBuID4+IDQ7CiAgICAgICAgbiB8PSBuID4+IDg7CiAgICAgICAgbiB8PSBuID4+IDE2OwogICAgICAgICsrbjsKICAgICAgICByZXR1cm4gbjsKICAgICAgfTsKICAgICAgQ2VzaXVtTWF0aC5wcmV2aW91c1Bvd2VyT2ZUd28gPSBmdW5jdGlvbihuKSB7CiAgICAgICAgaWYgKHR5cGVvZiBuICE9PSAibnVtYmVyIiB8fCBuIDwgMCB8fCBuID4gNDI5NDk2NzI5NSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIkEgbnVtYmVyIGJldHdlZW4gMCBhbmQgKDJeMzIpLTEgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIG4gfD0gbiA+PiAxOwogICAgICAgIG4gfD0gbiA+PiAyOwogICAgICAgIG4gfD0gbiA+PiA0OwogICAgICAgIG4gfD0gbiA+PiA4OwogICAgICAgIG4gfD0gbiA+PiAxNjsKICAgICAgICBuIHw9IG4gPj4gMzI7CiAgICAgICAgbiA9IChuID4+PiAwKSAtIChuID4+PiAxKTsKICAgICAgICByZXR1cm4gbjsKICAgICAgfTsKICAgICAgQ2VzaXVtTWF0aC5jbGFtcCA9IGZ1bmN0aW9uKHZhbHVlLCBtaW4zLCBtYXgzKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJ2YWx1ZSIsIHZhbHVlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoIm1pbiIsIG1pbjMpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigibWF4IiwgbWF4Myk7CiAgICAgICAgcmV0dXJuIHZhbHVlIDwgbWluMyA/IG1pbjMgOiB2YWx1ZSA+IG1heDMgPyBtYXgzIDogdmFsdWU7CiAgICAgIH07CiAgICAgIHJhbmRvbU51bWJlckdlbmVyYXRvciA9IG5ldyBpbXBvcnRfbWVyc2VubmVfdHdpc3Rlci5kZWZhdWx0KCk7CiAgICAgIENlc2l1bU1hdGguc2V0UmFuZG9tTnVtYmVyU2VlZCA9IGZ1bmN0aW9uKHNlZWQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChzZWVkKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInNlZWQgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIHJhbmRvbU51bWJlckdlbmVyYXRvciA9IG5ldyBpbXBvcnRfbWVyc2VubmVfdHdpc3Rlci5kZWZhdWx0KHNlZWQpOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLm5leHRSYW5kb21OdW1iZXIgPSBmdW5jdGlvbigpIHsKICAgICAgICByZXR1cm4gcmFuZG9tTnVtYmVyR2VuZXJhdG9yLnJhbmRvbSgpOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLnJhbmRvbUJldHdlZW4gPSBmdW5jdGlvbihtaW4zLCBtYXgzKSB7CiAgICAgICAgcmV0dXJuIENlc2l1bU1hdGgubmV4dFJhbmRvbU51bWJlcigpICogKG1heDMgLSBtaW4zKSArIG1pbjM7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGguYWNvc0NsYW1wZWQgPSBmdW5jdGlvbih2YWx1ZSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHZhbHVlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInZhbHVlIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gTWF0aC5hY29zKENlc2l1bU1hdGguY2xhbXAodmFsdWUsIC0xLCAxKSk7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGguYXNpbkNsYW1wZWQgPSBmdW5jdGlvbih2YWx1ZSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHZhbHVlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInZhbHVlIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gTWF0aC5hc2luKENlc2l1bU1hdGguY2xhbXAodmFsdWUsIC0xLCAxKSk7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGguY2hvcmRMZW5ndGggPSBmdW5jdGlvbihhbmdsZSwgcmFkaXVzKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYW5nbGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYW5nbGUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJhZGl1cykpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJyYWRpdXMgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIHJldHVybiAyICogcmFkaXVzICogTWF0aC5zaW4oYW5nbGUgKiAwLjUpOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLmxvZ0Jhc2UgPSBmdW5jdGlvbihudW1iZXIsIGJhc2UpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChudW1iZXIpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgibnVtYmVyIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChiYXNlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImJhc2UgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBNYXRoLmxvZyhudW1iZXIpIC8gTWF0aC5sb2coYmFzZSk7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGguY2JydCA9IE1hdGguY2JydCA/PyBmdW5jdGlvbiBjYnJ0KG51bWJlcikgewogICAgICAgIGNvbnN0IHJlc3VsdCA9IE1hdGgucG93KE1hdGguYWJzKG51bWJlciksIDEgLyAzKTsKICAgICAgICByZXR1cm4gbnVtYmVyIDwgMCA/IC1yZXN1bHQgOiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENlc2l1bU1hdGgubG9nMiA9IE1hdGgubG9nMiA/PyBmdW5jdGlvbiBsb2cyKG51bWJlcikgewogICAgICAgIHJldHVybiBNYXRoLmxvZyhudW1iZXIpICogTWF0aC5MT0cyRTsKICAgICAgfTsKICAgICAgQ2VzaXVtTWF0aC5mb2cgPSBmdW5jdGlvbihkaXN0YW5jZVRvQ2FtZXJhLCBkZW5zaXR5KSB7CiAgICAgICAgY29uc3Qgc2NhbGFyID0gZGlzdGFuY2VUb0NhbWVyYSAqIGRlbnNpdHk7CiAgICAgICAgcmV0dXJuIDEgLSBNYXRoLmV4cCgtKHNjYWxhciAqIHNjYWxhcikpOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLmZhc3RBcHByb3hpbWF0ZUF0YW4gPSBmdW5jdGlvbih4KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJ4IiwgeCk7CiAgICAgICAgcmV0dXJuIHggKiAoLTAuMTc4NCAqIE1hdGguYWJzKHgpIC0gMC4wNjYzICogeCAqIHggKyAxLjAzMDEpOwogICAgICB9OwogICAgICBDZXNpdW1NYXRoLmZhc3RBcHByb3hpbWF0ZUF0YW4yID0gZnVuY3Rpb24oeCwgeSkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigieCIsIHgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigieSIsIHkpOwogICAgICAgIGxldCBvcHBvc2l0ZTsKICAgICAgICBsZXQgdCA9IE1hdGguYWJzKHgpOwogICAgICAgIG9wcG9zaXRlID0gTWF0aC5hYnMoeSk7CiAgICAgICAgY29uc3QgYWRqYWNlbnQgPSBNYXRoLm1heCh0LCBvcHBvc2l0ZSk7CiAgICAgICAgb3Bwb3NpdGUgPSBNYXRoLm1pbih0LCBvcHBvc2l0ZSk7CiAgICAgICAgY29uc3Qgb3Bwb3NpdGVPdmVyQWRqYWNlbnQgPSBvcHBvc2l0ZSAvIGFkamFjZW50OwogICAgICAgIGlmIChpc05hTihvcHBvc2l0ZU92ZXJBZGphY2VudCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJlaXRoZXIgeCBvciB5IG11c3QgYmUgbm9uemVybyIpOwogICAgICAgIH0KICAgICAgICB0ID0gQ2VzaXVtTWF0aC5mYXN0QXBwcm94aW1hdGVBdGFuKG9wcG9zaXRlT3ZlckFkamFjZW50KTsKICAgICAgICB0ID0gTWF0aC5hYnMoeSkgPiBNYXRoLmFicyh4KSA/IENlc2l1bU1hdGguUElfT1ZFUl9UV08gLSB0IDogdDsKICAgICAgICB0ID0geCA8IDAgPyBDZXNpdW1NYXRoLlBJIC0gdCA6IHQ7CiAgICAgICAgdCA9IHkgPCAwID8gLXQgOiB0OwogICAgICAgIHJldHVybiB0OwogICAgICB9OwogICAgICBNYXRoX2RlZmF1bHQgPSBDZXNpdW1NYXRoOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ2FydGVzaWFuMy5qcwogIGZ1bmN0aW9uIENhcnRlc2lhbjMoeCwgeSwgeikgewogICAgdGhpcy54ID0geCA/PyAwOwogICAgdGhpcy55ID0geSA/PyAwOwogICAgdGhpcy56ID0geiA/PyAwOwogIH0KICB2YXIgZGlzdGFuY2VTY3JhdGNoLCBsZXJwU2NyYXRjaCwgYW5nbGVCZXR3ZWVuU2NyYXRjaCwgYW5nbGVCZXR3ZWVuU2NyYXRjaDIsIG1vc3RPcnRob2dvbmFsQXhpc1NjcmF0Y2gsIHNjcmF0Y2hOLCBzY3JhdGNoSywgQ2FydGVzaWFuM19kZWZhdWx0OwogIHZhciBpbml0X0NhcnRlc2lhbjMgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NhcnRlc2lhbjMuanMiKCkgewogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBDYXJ0ZXNpYW4zLmZyb21TcGhlcmljYWwgPSBmdW5jdGlvbihzcGhlcmljYWwsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic3BoZXJpY2FsIiwgc3BoZXJpY2FsKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQ2FydGVzaWFuMygpOwogICAgICAgIH0KICAgICAgICBjb25zdCBjbG9jayA9IHNwaGVyaWNhbC5jbG9jazsKICAgICAgICBjb25zdCBjb25lID0gc3BoZXJpY2FsLmNvbmU7CiAgICAgICAgY29uc3QgbWFnbml0dWRlID0gc3BoZXJpY2FsLm1hZ25pdHVkZSA/PyAxOwogICAgICAgIGNvbnN0IHJhZGlhbCA9IG1hZ25pdHVkZSAqIE1hdGguc2luKGNvbmUpOwogICAgICAgIHJlc3VsdC54ID0gcmFkaWFsICogTWF0aC5jb3MoY2xvY2spOwogICAgICAgIHJlc3VsdC55ID0gcmFkaWFsICogTWF0aC5zaW4oY2xvY2spOwogICAgICAgIHJlc3VsdC56ID0gbWFnbml0dWRlICogTWF0aC5jb3MoY29uZSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5mcm9tRWxlbWVudHMgPSBmdW5jdGlvbih4LCB5LCB6LCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IENhcnRlc2lhbjMoeCwgeSwgeik7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC54ID0geDsKICAgICAgICByZXN1bHQueSA9IHk7CiAgICAgICAgcmVzdWx0LnogPSB6OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjMuY2xvbmUgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoY2FydGVzaWFuMTEpKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IENhcnRlc2lhbjMoY2FydGVzaWFuMTEueCwgY2FydGVzaWFuMTEueSwgY2FydGVzaWFuMTEueik7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC54ID0gY2FydGVzaWFuMTEueDsKICAgICAgICByZXN1bHQueSA9IGNhcnRlc2lhbjExLnk7CiAgICAgICAgcmVzdWx0LnogPSBjYXJ0ZXNpYW4xMS56OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjMuZnJvbUNhcnRlc2lhbjQgPSBDYXJ0ZXNpYW4zLmNsb25lOwogICAgICBDYXJ0ZXNpYW4zLnBhY2tlZExlbmd0aCA9IDM7CiAgICAgIENhcnRlc2lhbjMucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS54OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS55OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXhdID0gdmFsdWUuejsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjMudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQ2FydGVzaWFuMygpOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LnkgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdC56ID0gYXJyYXlbc3RhcnRpbmdJbmRleF07CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5wYWNrQXJyYXkgPSBmdW5jdGlvbihhcnJheSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBjb25zdCBsZW5ndGggPSBhcnJheS5sZW5ndGg7CiAgICAgICAgY29uc3QgcmVzdWx0TGVuZ3RoID0gbGVuZ3RoICogMzsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQXJyYXkocmVzdWx0TGVuZ3RoKTsKICAgICAgICB9IGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KHJlc3VsdCkgJiYgcmVzdWx0Lmxlbmd0aCAhPT0gcmVzdWx0TGVuZ3RoKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgIklmIHJlc3VsdCBpcyBhIHR5cGVkIGFycmF5LCBpdCBtdXN0IGhhdmUgZXhhY3RseSBhcnJheS5sZW5ndGggKiAzIGVsZW1lbnRzIgogICAgICAgICAgKTsKICAgICAgICB9IGVsc2UgaWYgKHJlc3VsdC5sZW5ndGggIT09IHJlc3VsdExlbmd0aCkgewogICAgICAgICAgcmVzdWx0Lmxlbmd0aCA9IHJlc3VsdExlbmd0aDsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgQ2FydGVzaWFuMy5wYWNrKGFycmF5W2ldLCByZXN1bHQsIGkgKiAzKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy51bnBhY2tBcnJheSA9IGZ1bmN0aW9uKGFycmF5LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJhcnJheS5sZW5ndGgiLCBhcnJheS5sZW5ndGgsIDMpOwogICAgICAgIGlmIChhcnJheS5sZW5ndGggJSAzICE9PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYXJyYXkgbGVuZ3RoIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAzLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBsZW5ndGggPSBhcnJheS5sZW5ndGg7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEFycmF5KGxlbmd0aCAvIDMpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQubGVuZ3RoID0gbGVuZ3RoIC8gMzsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMykgewogICAgICAgICAgY29uc3QgaW5kZXggPSBpIC8gMzsKICAgICAgICAgIHJlc3VsdFtpbmRleF0gPSBDYXJ0ZXNpYW4zLnVucGFjayhhcnJheSwgaSwgcmVzdWx0W2luZGV4XSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjMuZnJvbUFycmF5ID0gQ2FydGVzaWFuMy51bnBhY2s7CiAgICAgIENhcnRlc2lhbjMubWF4aW11bUNvbXBvbmVudCA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgcmV0dXJuIE1hdGgubWF4KGNhcnRlc2lhbjExLngsIGNhcnRlc2lhbjExLnksIGNhcnRlc2lhbjExLnopOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4zLm1pbmltdW1Db21wb25lbnQgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIHJldHVybiBNYXRoLm1pbihjYXJ0ZXNpYW4xMS54LCBjYXJ0ZXNpYW4xMS55LCBjYXJ0ZXNpYW4xMS56KTsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5taW5pbXVtQnlDb21wb25lbnQgPSBmdW5jdGlvbihmaXJzdCwgc2Vjb25kLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImZpcnN0IiwgZmlyc3QpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic2Vjb25kIiwgc2Vjb25kKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBNYXRoLm1pbihmaXJzdC54LCBzZWNvbmQueCk7CiAgICAgICAgcmVzdWx0LnkgPSBNYXRoLm1pbihmaXJzdC55LCBzZWNvbmQueSk7CiAgICAgICAgcmVzdWx0LnogPSBNYXRoLm1pbihmaXJzdC56LCBzZWNvbmQueik7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5tYXhpbXVtQnlDb21wb25lbnQgPSBmdW5jdGlvbihmaXJzdCwgc2Vjb25kLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImZpcnN0IiwgZmlyc3QpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic2Vjb25kIiwgc2Vjb25kKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBNYXRoLm1heChmaXJzdC54LCBzZWNvbmQueCk7CiAgICAgICAgcmVzdWx0LnkgPSBNYXRoLm1heChmaXJzdC55LCBzZWNvbmQueSk7CiAgICAgICAgcmVzdWx0LnogPSBNYXRoLm1heChmaXJzdC56LCBzZWNvbmQueik7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5jbGFtcCA9IGZ1bmN0aW9uKHZhbHVlLCBtaW4zLCBtYXgzLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWluIiwgbWluMyk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXgiLCBtYXgzKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgeCA9IE1hdGhfZGVmYXVsdC5jbGFtcCh2YWx1ZS54LCBtaW4zLngsIG1heDMueCk7CiAgICAgICAgY29uc3QgeSA9IE1hdGhfZGVmYXVsdC5jbGFtcCh2YWx1ZS55LCBtaW4zLnksIG1heDMueSk7CiAgICAgICAgY29uc3QgeiA9IE1hdGhfZGVmYXVsdC5jbGFtcCh2YWx1ZS56LCBtaW4zLnosIG1heDMueik7CiAgICAgICAgcmVzdWx0LnggPSB4OwogICAgICAgIHJlc3VsdC55ID0geTsKICAgICAgICByZXN1bHQueiA9IHo7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5tYWduaXR1ZGVTcXVhcmVkID0gZnVuY3Rpb24oY2FydGVzaWFuMTEpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICByZXR1cm4gY2FydGVzaWFuMTEueCAqIGNhcnRlc2lhbjExLnggKyBjYXJ0ZXNpYW4xMS55ICogY2FydGVzaWFuMTEueSArIGNhcnRlc2lhbjExLnogKiBjYXJ0ZXNpYW4xMS56OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4zLm1hZ25pdHVkZSA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExKSB7CiAgICAgICAgcmV0dXJuIE1hdGguc3FydChDYXJ0ZXNpYW4zLm1hZ25pdHVkZVNxdWFyZWQoY2FydGVzaWFuMTEpKTsKICAgICAgfTsKICAgICAgZGlzdGFuY2VTY3JhdGNoID0gbmV3IENhcnRlc2lhbjMoKTsKICAgICAgQ2FydGVzaWFuMy5kaXN0YW5jZSA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDYXJ0ZXNpYW4zLnN1YnRyYWN0KGxlZnQsIHJpZ2h0LCBkaXN0YW5jZVNjcmF0Y2gpOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zLm1hZ25pdHVkZShkaXN0YW5jZVNjcmF0Y2gpOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4zLmRpc3RhbmNlU3F1YXJlZCA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDYXJ0ZXNpYW4zLnN1YnRyYWN0KGxlZnQsIHJpZ2h0LCBkaXN0YW5jZVNjcmF0Y2gpOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zLm1hZ25pdHVkZVNxdWFyZWQoZGlzdGFuY2VTY3JhdGNoKTsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5ub3JtYWxpemUgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IG1hZ25pdHVkZSA9IENhcnRlc2lhbjMubWFnbml0dWRlKGNhcnRlc2lhbjExKTsKICAgICAgICByZXN1bHQueCA9IGNhcnRlc2lhbjExLnggLyBtYWduaXR1ZGU7CiAgICAgICAgcmVzdWx0LnkgPSBjYXJ0ZXNpYW4xMS55IC8gbWFnbml0dWRlOwogICAgICAgIHJlc3VsdC56ID0gY2FydGVzaWFuMTEueiAvIG1hZ25pdHVkZTsKICAgICAgICBpZiAoaXNOYU4ocmVzdWx0LngpIHx8IGlzTmFOKHJlc3VsdC55KSB8fCBpc05hTihyZXN1bHQueikpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJub3JtYWxpemVkIHJlc3VsdCBpcyBub3QgYSBudW1iZXIiKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5kb3QgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgcmV0dXJuIGxlZnQueCAqIHJpZ2h0LnggKyBsZWZ0LnkgKiByaWdodC55ICsgbGVmdC56ICogcmlnaHQuejsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5tdWx0aXBseUNvbXBvbmVudHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBsZWZ0LnggKiByaWdodC54OwogICAgICAgIHJlc3VsdC55ID0gbGVmdC55ICogcmlnaHQueTsKICAgICAgICByZXN1bHQueiA9IGxlZnQueiAqIHJpZ2h0Lno7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5kaXZpZGVDb21wb25lbnRzID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gbGVmdC54IC8gcmlnaHQueDsKICAgICAgICByZXN1bHQueSA9IGxlZnQueSAvIHJpZ2h0Lnk7CiAgICAgICAgcmVzdWx0LnogPSBsZWZ0LnogLyByaWdodC56OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjMuYWRkID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gbGVmdC54ICsgcmlnaHQueDsKICAgICAgICByZXN1bHQueSA9IGxlZnQueSArIHJpZ2h0Lnk7CiAgICAgICAgcmVzdWx0LnogPSBsZWZ0LnogKyByaWdodC56OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjMuc3VidHJhY3QgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBsZWZ0LnggLSByaWdodC54OwogICAgICAgIHJlc3VsdC55ID0gbGVmdC55IC0gcmlnaHQueTsKICAgICAgICByZXN1bHQueiA9IGxlZnQueiAtIHJpZ2h0Lno7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5tdWx0aXBseUJ5U2NhbGFyID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHNjYWxhciwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJzY2FsYXIiLCBzY2FsYXIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQueCA9IGNhcnRlc2lhbjExLnggKiBzY2FsYXI7CiAgICAgICAgcmVzdWx0LnkgPSBjYXJ0ZXNpYW4xMS55ICogc2NhbGFyOwogICAgICAgIHJlc3VsdC56ID0gY2FydGVzaWFuMTEueiAqIHNjYWxhcjsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4zLmRpdmlkZUJ5U2NhbGFyID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHNjYWxhciwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJzY2FsYXIiLCBzY2FsYXIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQueCA9IGNhcnRlc2lhbjExLnggLyBzY2FsYXI7CiAgICAgICAgcmVzdWx0LnkgPSBjYXJ0ZXNpYW4xMS55IC8gc2NhbGFyOwogICAgICAgIHJlc3VsdC56ID0gY2FydGVzaWFuMTEueiAvIHNjYWxhcjsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4zLm5lZ2F0ZSA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSAtY2FydGVzaWFuMTEueDsKICAgICAgICByZXN1bHQueSA9IC1jYXJ0ZXNpYW4xMS55OwogICAgICAgIHJlc3VsdC56ID0gLWNhcnRlc2lhbjExLno7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5hYnMgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gTWF0aC5hYnMoY2FydGVzaWFuMTEueCk7CiAgICAgICAgcmVzdWx0LnkgPSBNYXRoLmFicyhjYXJ0ZXNpYW4xMS55KTsKICAgICAgICByZXN1bHQueiA9IE1hdGguYWJzKGNhcnRlc2lhbjExLnopOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIGxlcnBTY3JhdGNoID0gbmV3IENhcnRlc2lhbjMoKTsKICAgICAgQ2FydGVzaWFuMy5sZXJwID0gZnVuY3Rpb24oc3RhcnQsIGVuZCwgdCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzdGFydCIsIHN0YXJ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImVuZCIsIGVuZCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJ0IiwgdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIENhcnRlc2lhbjMubXVsdGlwbHlCeVNjYWxhcihlbmQsIHQsIGxlcnBTY3JhdGNoKTsKICAgICAgICByZXN1bHQgPSBDYXJ0ZXNpYW4zLm11bHRpcGx5QnlTY2FsYXIoc3RhcnQsIDEgLSB0LCByZXN1bHQpOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zLmFkZChsZXJwU2NyYXRjaCwgcmVzdWx0LCByZXN1bHQpOwogICAgICB9OwogICAgICBhbmdsZUJldHdlZW5TY3JhdGNoID0gbmV3IENhcnRlc2lhbjMoKTsKICAgICAgYW5nbGVCZXR3ZWVuU2NyYXRjaDIgPSBuZXcgQ2FydGVzaWFuMygpOwogICAgICBDYXJ0ZXNpYW4zLmFuZ2xlQmV0d2VlbiA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDYXJ0ZXNpYW4zLm5vcm1hbGl6ZShsZWZ0LCBhbmdsZUJldHdlZW5TY3JhdGNoKTsKICAgICAgICBDYXJ0ZXNpYW4zLm5vcm1hbGl6ZShyaWdodCwgYW5nbGVCZXR3ZWVuU2NyYXRjaDIpOwogICAgICAgIGNvbnN0IGNvc2luZSA9IENhcnRlc2lhbjMuZG90KGFuZ2xlQmV0d2VlblNjcmF0Y2gsIGFuZ2xlQmV0d2VlblNjcmF0Y2gyKTsKICAgICAgICBjb25zdCBzaW5lID0gQ2FydGVzaWFuMy5tYWduaXR1ZGUoCiAgICAgICAgICBDYXJ0ZXNpYW4zLmNyb3NzKAogICAgICAgICAgICBhbmdsZUJldHdlZW5TY3JhdGNoLAogICAgICAgICAgICBhbmdsZUJldHdlZW5TY3JhdGNoMiwKICAgICAgICAgICAgYW5nbGVCZXR3ZWVuU2NyYXRjaAogICAgICAgICAgKQogICAgICAgICk7CiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIoc2luZSwgY29zaW5lKTsKICAgICAgfTsKICAgICAgbW9zdE9ydGhvZ29uYWxBeGlzU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zKCk7CiAgICAgIENhcnRlc2lhbjMubW9zdE9ydGhvZ29uYWxBeGlzID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBmID0gQ2FydGVzaWFuMy5ub3JtYWxpemUoY2FydGVzaWFuMTEsIG1vc3RPcnRob2dvbmFsQXhpc1NjcmF0Y2gpOwogICAgICAgIENhcnRlc2lhbjMuYWJzKGYsIGYpOwogICAgICAgIGlmIChmLnggPD0gZi55KSB7CiAgICAgICAgICBpZiAoZi54IDw9IGYueikgewogICAgICAgICAgICByZXN1bHQgPSBDYXJ0ZXNpYW4zLmNsb25lKENhcnRlc2lhbjMuVU5JVF9YLCByZXN1bHQpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmVzdWx0ID0gQ2FydGVzaWFuMy5jbG9uZShDYXJ0ZXNpYW4zLlVOSVRfWiwgcmVzdWx0KTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGYueSA8PSBmLnopIHsKICAgICAgICAgIHJlc3VsdCA9IENhcnRlc2lhbjMuY2xvbmUoQ2FydGVzaWFuMy5VTklUX1ksIHJlc3VsdCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdCA9IENhcnRlc2lhbjMuY2xvbmUoQ2FydGVzaWFuMy5VTklUX1osIHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjMucHJvamVjdFZlY3RvciA9IGZ1bmN0aW9uKGEzLCBiLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImEiLCBhMyk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJiIiwgYik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHNjYWxhciA9IENhcnRlc2lhbjMuZG90KGEzLCBiKSAvIENhcnRlc2lhbjMuZG90KGIsIGIpOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zLm11bHRpcGx5QnlTY2FsYXIoYiwgc2NhbGFyLCByZXN1bHQpOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4zLmVxdWFscyA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIGxlZnQgPT09IHJpZ2h0IHx8IGRlZmluZWRfZGVmYXVsdChsZWZ0KSAmJiBkZWZpbmVkX2RlZmF1bHQocmlnaHQpICYmIGxlZnQueCA9PT0gcmlnaHQueCAmJiBsZWZ0LnkgPT09IHJpZ2h0LnkgJiYgbGVmdC56ID09PSByaWdodC56OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4zLmVxdWFsc0FycmF5ID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIGFycmF5LCBvZmZzZXQpIHsKICAgICAgICByZXR1cm4gY2FydGVzaWFuMTEueCA9PT0gYXJyYXlbb2Zmc2V0XSAmJiBjYXJ0ZXNpYW4xMS55ID09PSBhcnJheVtvZmZzZXQgKyAxXSAmJiBjYXJ0ZXNpYW4xMS56ID09PSBhcnJheVtvZmZzZXQgKyAyXTsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5lcXVhbHNFcHNpbG9uID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIHJlbGF0aXZlRXBzaWxvbiwgYWJzb2x1dGVFcHNpbG9uKSB7CiAgICAgICAgcmV0dXJuIGxlZnQgPT09IHJpZ2h0IHx8IGRlZmluZWRfZGVmYXVsdChsZWZ0KSAmJiBkZWZpbmVkX2RlZmF1bHQocmlnaHQpICYmIE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgbGVmdC54LAogICAgICAgICAgcmlnaHQueCwKICAgICAgICAgIHJlbGF0aXZlRXBzaWxvbiwKICAgICAgICAgIGFic29sdXRlRXBzaWxvbgogICAgICAgICkgJiYgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICBsZWZ0LnksCiAgICAgICAgICByaWdodC55LAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKSAmJiBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIGxlZnQueiwKICAgICAgICAgIHJpZ2h0LnosCiAgICAgICAgICByZWxhdGl2ZUVwc2lsb24sCiAgICAgICAgICBhYnNvbHV0ZUVwc2lsb24KICAgICAgICApOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4zLmNyb3NzID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IGxlZnRYID0gbGVmdC54OwogICAgICAgIGNvbnN0IGxlZnRZID0gbGVmdC55OwogICAgICAgIGNvbnN0IGxlZnRaID0gbGVmdC56OwogICAgICAgIGNvbnN0IHJpZ2h0WCA9IHJpZ2h0Lng7CiAgICAgICAgY29uc3QgcmlnaHRZID0gcmlnaHQueTsKICAgICAgICBjb25zdCByaWdodFogPSByaWdodC56OwogICAgICAgIGNvbnN0IHggPSBsZWZ0WSAqIHJpZ2h0WiAtIGxlZnRaICogcmlnaHRZOwogICAgICAgIGNvbnN0IHkgPSBsZWZ0WiAqIHJpZ2h0WCAtIGxlZnRYICogcmlnaHRaOwogICAgICAgIGNvbnN0IHogPSBsZWZ0WCAqIHJpZ2h0WSAtIGxlZnRZICogcmlnaHRYOwogICAgICAgIHJlc3VsdC54ID0geDsKICAgICAgICByZXN1bHQueSA9IHk7CiAgICAgICAgcmVzdWx0LnogPSB6OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjMubWlkcG9pbnQgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSAobGVmdC54ICsgcmlnaHQueCkgKiAwLjU7CiAgICAgICAgcmVzdWx0LnkgPSAobGVmdC55ICsgcmlnaHQueSkgKiAwLjU7CiAgICAgICAgcmVzdWx0LnogPSAobGVmdC56ICsgcmlnaHQueikgKiAwLjU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5mcm9tRGVncmVlcyA9IGZ1bmN0aW9uKGxvbmdpdHVkZSwgbGF0aXR1ZGUsIGhlaWdodCwgZWxsaXBzb2lkLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoImxvbmdpdHVkZSIsIGxvbmdpdHVkZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJsYXRpdHVkZSIsIGxhdGl0dWRlKTsKICAgICAgICBsb25naXR1ZGUgPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKGxvbmdpdHVkZSk7CiAgICAgICAgbGF0aXR1ZGUgPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKGxhdGl0dWRlKTsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuMy5mcm9tUmFkaWFucyhsb25naXR1ZGUsIGxhdGl0dWRlLCBoZWlnaHQsIGVsbGlwc29pZCwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgc2NyYXRjaE4gPSBuZXcgQ2FydGVzaWFuMygpOwogICAgICBzY3JhdGNoSyA9IG5ldyBDYXJ0ZXNpYW4zKCk7CiAgICAgIENhcnRlc2lhbjMuX2VsbGlwc29pZFJhZGlpU3F1YXJlZCA9IG5ldyBDYXJ0ZXNpYW4zKAogICAgICAgIDYzNzgxMzcgKiA2Mzc4MTM3LAogICAgICAgIDYzNzgxMzcgKiA2Mzc4MTM3LAogICAgICAgIDYzNTY3NTIzMTQyNDUxNzllLTkgKiA2MzU2NzUyMzE0MjQ1MTc5ZS05CiAgICAgICk7CiAgICAgIENhcnRlc2lhbjMuZnJvbVJhZGlhbnMgPSBmdW5jdGlvbihsb25naXR1ZGUsIGxhdGl0dWRlLCBoZWlnaHQsIGVsbGlwc29pZCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJsb25naXR1ZGUiLCBsb25naXR1ZGUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigibGF0aXR1ZGUiLCBsYXRpdHVkZSk7CiAgICAgICAgaGVpZ2h0ID0gaGVpZ2h0ID8/IDA7CiAgICAgICAgY29uc3QgcmFkaWlTcXVhcmVkID0gIWRlZmluZWRfZGVmYXVsdChlbGxpcHNvaWQpID8gQ2FydGVzaWFuMy5fZWxsaXBzb2lkUmFkaWlTcXVhcmVkIDogZWxsaXBzb2lkLnJhZGlpU3F1YXJlZDsKICAgICAgICBjb25zdCBjb3NMYXRpdHVkZSA9IE1hdGguY29zKGxhdGl0dWRlKTsKICAgICAgICBzY3JhdGNoTi54ID0gY29zTGF0aXR1ZGUgKiBNYXRoLmNvcyhsb25naXR1ZGUpOwogICAgICAgIHNjcmF0Y2hOLnkgPSBjb3NMYXRpdHVkZSAqIE1hdGguc2luKGxvbmdpdHVkZSk7CiAgICAgICAgc2NyYXRjaE4ueiA9IE1hdGguc2luKGxhdGl0dWRlKTsKICAgICAgICBzY3JhdGNoTiA9IENhcnRlc2lhbjMubm9ybWFsaXplKHNjcmF0Y2hOLCBzY3JhdGNoTik7CiAgICAgICAgQ2FydGVzaWFuMy5tdWx0aXBseUNvbXBvbmVudHMocmFkaWlTcXVhcmVkLCBzY3JhdGNoTiwgc2NyYXRjaEspOwogICAgICAgIGNvbnN0IGdhbW1hID0gTWF0aC5zcXJ0KENhcnRlc2lhbjMuZG90KHNjcmF0Y2hOLCBzY3JhdGNoSykpOwogICAgICAgIHNjcmF0Y2hLID0gQ2FydGVzaWFuMy5kaXZpZGVCeVNjYWxhcihzY3JhdGNoSywgZ2FtbWEsIHNjcmF0Y2hLKTsKICAgICAgICBzY3JhdGNoTiA9IENhcnRlc2lhbjMubXVsdGlwbHlCeVNjYWxhcihzY3JhdGNoTiwgaGVpZ2h0LCBzY3JhdGNoTik7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjMoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjMuYWRkKHNjcmF0Y2hLLCBzY3JhdGNoTiwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5mcm9tRGVncmVlc0FycmF5ID0gZnVuY3Rpb24oY29vcmRpbmF0ZXMsIGVsbGlwc29pZCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJjb29yZGluYXRlcyIsIGNvb3JkaW5hdGVzKTsKICAgICAgICBpZiAoY29vcmRpbmF0ZXMubGVuZ3RoIDwgMiB8fCBjb29yZGluYXRlcy5sZW5ndGggJSAyICE9PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgInRoZSBudW1iZXIgb2YgY29vcmRpbmF0ZXMgbXVzdCBiZSBhIG11bHRpcGxlIG9mIDIgYW5kIGF0IGxlYXN0IDIiCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBsZW5ndGggPSBjb29yZGluYXRlcy5sZW5ndGg7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEFycmF5KGxlbmd0aCAvIDIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQubGVuZ3RoID0gbGVuZ3RoIC8gMjsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMikgewogICAgICAgICAgY29uc3QgbG9uZ2l0dWRlID0gY29vcmRpbmF0ZXNbaV07CiAgICAgICAgICBjb25zdCBsYXRpdHVkZSA9IGNvb3JkaW5hdGVzW2kgKyAxXTsKICAgICAgICAgIGNvbnN0IGluZGV4ID0gaSAvIDI7CiAgICAgICAgICByZXN1bHRbaW5kZXhdID0gQ2FydGVzaWFuMy5mcm9tRGVncmVlcygKICAgICAgICAgICAgbG9uZ2l0dWRlLAogICAgICAgICAgICBsYXRpdHVkZSwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICByZXN1bHRbaW5kZXhdCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4zLmZyb21SYWRpYW5zQXJyYXkgPSBmdW5jdGlvbihjb29yZGluYXRlcywgZWxsaXBzb2lkLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImNvb3JkaW5hdGVzIiwgY29vcmRpbmF0ZXMpOwogICAgICAgIGlmIChjb29yZGluYXRlcy5sZW5ndGggPCAyIHx8IGNvb3JkaW5hdGVzLmxlbmd0aCAlIDIgIT09IDApIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICAidGhlIG51bWJlciBvZiBjb29yZGluYXRlcyBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMiBhbmQgYXQgbGVhc3QgMiIKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGxlbmd0aCA9IGNvb3JkaW5hdGVzLmxlbmd0aDsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQXJyYXkobGVuZ3RoIC8gMik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5sZW5ndGggPSBsZW5ndGggLyAyOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgICBjb25zdCBsb25naXR1ZGUgPSBjb29yZGluYXRlc1tpXTsKICAgICAgICAgIGNvbnN0IGxhdGl0dWRlID0gY29vcmRpbmF0ZXNbaSArIDFdOwogICAgICAgICAgY29uc3QgaW5kZXggPSBpIC8gMjsKICAgICAgICAgIHJlc3VsdFtpbmRleF0gPSBDYXJ0ZXNpYW4zLmZyb21SYWRpYW5zKAogICAgICAgICAgICBsb25naXR1ZGUsCiAgICAgICAgICAgIGxhdGl0dWRlLAogICAgICAgICAgICAwLAogICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgIHJlc3VsdFtpbmRleF0KICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjMuZnJvbURlZ3JlZXNBcnJheUhlaWdodHMgPSBmdW5jdGlvbihjb29yZGluYXRlcywgZWxsaXBzb2lkLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImNvb3JkaW5hdGVzIiwgY29vcmRpbmF0ZXMpOwogICAgICAgIGlmIChjb29yZGluYXRlcy5sZW5ndGggPCAzIHx8IGNvb3JkaW5hdGVzLmxlbmd0aCAlIDMgIT09IDApIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICAidGhlIG51bWJlciBvZiBjb29yZGluYXRlcyBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMyBhbmQgYXQgbGVhc3QgMyIKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGxlbmd0aCA9IGNvb3JkaW5hdGVzLmxlbmd0aDsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQXJyYXkobGVuZ3RoIC8gMyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5sZW5ndGggPSBsZW5ndGggLyAzOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAzKSB7CiAgICAgICAgICBjb25zdCBsb25naXR1ZGUgPSBjb29yZGluYXRlc1tpXTsKICAgICAgICAgIGNvbnN0IGxhdGl0dWRlID0gY29vcmRpbmF0ZXNbaSArIDFdOwogICAgICAgICAgY29uc3QgaGVpZ2h0ID0gY29vcmRpbmF0ZXNbaSArIDJdOwogICAgICAgICAgY29uc3QgaW5kZXggPSBpIC8gMzsKICAgICAgICAgIHJlc3VsdFtpbmRleF0gPSBDYXJ0ZXNpYW4zLmZyb21EZWdyZWVzKAogICAgICAgICAgICBsb25naXR1ZGUsCiAgICAgICAgICAgIGxhdGl0dWRlLAogICAgICAgICAgICBoZWlnaHQsCiAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgcmVzdWx0W2luZGV4XQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5mcm9tUmFkaWFuc0FycmF5SGVpZ2h0cyA9IGZ1bmN0aW9uKGNvb3JkaW5hdGVzLCBlbGxpcHNvaWQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiY29vcmRpbmF0ZXMiLCBjb29yZGluYXRlcyk7CiAgICAgICAgaWYgKGNvb3JkaW5hdGVzLmxlbmd0aCA8IDMgfHwgY29vcmRpbmF0ZXMubGVuZ3RoICUgMyAhPT0gMCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJ0aGUgbnVtYmVyIG9mIGNvb3JkaW5hdGVzIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAzIGFuZCBhdCBsZWFzdCAzIgogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbGVuZ3RoID0gY29vcmRpbmF0ZXMubGVuZ3RoOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBBcnJheShsZW5ndGggLyAzKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzdWx0Lmxlbmd0aCA9IGxlbmd0aCAvIDM7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHsKICAgICAgICAgIGNvbnN0IGxvbmdpdHVkZSA9IGNvb3JkaW5hdGVzW2ldOwogICAgICAgICAgY29uc3QgbGF0aXR1ZGUgPSBjb29yZGluYXRlc1tpICsgMV07CiAgICAgICAgICBjb25zdCBoZWlnaHQgPSBjb29yZGluYXRlc1tpICsgMl07CiAgICAgICAgICBjb25zdCBpbmRleCA9IGkgLyAzOwogICAgICAgICAgcmVzdWx0W2luZGV4XSA9IENhcnRlc2lhbjMuZnJvbVJhZGlhbnMoCiAgICAgICAgICAgIGxvbmdpdHVkZSwKICAgICAgICAgICAgbGF0aXR1ZGUsCiAgICAgICAgICAgIGhlaWdodCwKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICByZXN1bHRbaW5kZXhdCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4zLlpFUk8gPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW4zKDAsIDAsIDApKTsKICAgICAgQ2FydGVzaWFuMy5PTkUgPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW4zKDEsIDEsIDEpKTsKICAgICAgQ2FydGVzaWFuMy5VTklUX1ggPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW4zKDEsIDAsIDApKTsKICAgICAgQ2FydGVzaWFuMy5VTklUX1kgPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW4zKDAsIDEsIDApKTsKICAgICAgQ2FydGVzaWFuMy5VTklUX1ogPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW4zKDAsIDAsIDEpKTsKICAgICAgQ2FydGVzaWFuMy5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuMy5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4zLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbihyaWdodCkgewogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zLmVxdWFscyh0aGlzLCByaWdodCk7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjMucHJvdG90eXBlLmVxdWFsc0Vwc2lsb24gPSBmdW5jdGlvbihyaWdodCwgcmVsYXRpdmVFcHNpbG9uLCBhYnNvbHV0ZUVwc2lsb24pIHsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuMy5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgdGhpcywKICAgICAgICAgIHJpZ2h0LAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKTsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMy5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHsKICAgICAgICByZXR1cm4gYCgke3RoaXMueH0sICR7dGhpcy55fSwgJHt0aGlzLnp9KWA7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdCA9IENhcnRlc2lhbjM7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9zY2FsZVRvR2VvZGV0aWNTdXJmYWNlLmpzCiAgZnVuY3Rpb24gc2NhbGVUb0dlb2RldGljU3VyZmFjZShjYXJ0ZXNpYW4xMSwgb25lT3ZlclJhZGlpLCBvbmVPdmVyUmFkaWlTcXVhcmVkLCBjZW50ZXJUb2xlcmFuY2VTcXVhcmVkLCByZXN1bHQpIHsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGNhcnRlc2lhbjExKSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiY2FydGVzaWFuIGlzIHJlcXVpcmVkLiIpOwogICAgfQogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQob25lT3ZlclJhZGlpKSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgib25lT3ZlclJhZGlpIGlzIHJlcXVpcmVkLiIpOwogICAgfQogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQob25lT3ZlclJhZGlpU3F1YXJlZCkpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9uZU92ZXJSYWRpaVNxdWFyZWQgaXMgcmVxdWlyZWQuIik7CiAgICB9CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChjZW50ZXJUb2xlcmFuY2VTcXVhcmVkKSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiY2VudGVyVG9sZXJhbmNlU3F1YXJlZCBpcyByZXF1aXJlZC4iKTsKICAgIH0KICAgIGNvbnN0IHBvc2l0aW9uWCA9IGNhcnRlc2lhbjExLng7CiAgICBjb25zdCBwb3NpdGlvblkgPSBjYXJ0ZXNpYW4xMS55OwogICAgY29uc3QgcG9zaXRpb25aID0gY2FydGVzaWFuMTEuejsKICAgIGNvbnN0IG9uZU92ZXJSYWRpaVggPSBvbmVPdmVyUmFkaWkueDsKICAgIGNvbnN0IG9uZU92ZXJSYWRpaVkgPSBvbmVPdmVyUmFkaWkueTsKICAgIGNvbnN0IG9uZU92ZXJSYWRpaVogPSBvbmVPdmVyUmFkaWkuejsKICAgIGNvbnN0IHgyID0gcG9zaXRpb25YICogcG9zaXRpb25YICogb25lT3ZlclJhZGlpWCAqIG9uZU92ZXJSYWRpaVg7CiAgICBjb25zdCB5MiA9IHBvc2l0aW9uWSAqIHBvc2l0aW9uWSAqIG9uZU92ZXJSYWRpaVkgKiBvbmVPdmVyUmFkaWlZOwogICAgY29uc3QgejIgPSBwb3NpdGlvblogKiBwb3NpdGlvblogKiBvbmVPdmVyUmFkaWlaICogb25lT3ZlclJhZGlpWjsKICAgIGNvbnN0IHNxdWFyZWROb3JtID0geDIgKyB5MiArIHoyOwogICAgY29uc3QgcmF0aW8gPSBNYXRoLnNxcnQoMSAvIHNxdWFyZWROb3JtKTsKICAgIGNvbnN0IGludGVyc2VjdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICBjYXJ0ZXNpYW4xMSwKICAgICAgcmF0aW8sCiAgICAgIHNjYWxlVG9HZW9kZXRpY1N1cmZhY2VJbnRlcnNlY3Rpb24KICAgICk7CiAgICBpZiAoc3F1YXJlZE5vcm0gPCBjZW50ZXJUb2xlcmFuY2VTcXVhcmVkKSB7CiAgICAgIHJldHVybiAhaXNGaW5pdGUocmF0aW8pID8gdm9pZCAwIDogQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGludGVyc2VjdGlvbiwgcmVzdWx0KTsKICAgIH0KICAgIGNvbnN0IG9uZU92ZXJSYWRpaVNxdWFyZWRYID0gb25lT3ZlclJhZGlpU3F1YXJlZC54OwogICAgY29uc3Qgb25lT3ZlclJhZGlpU3F1YXJlZFkgPSBvbmVPdmVyUmFkaWlTcXVhcmVkLnk7CiAgICBjb25zdCBvbmVPdmVyUmFkaWlTcXVhcmVkWiA9IG9uZU92ZXJSYWRpaVNxdWFyZWQuejsKICAgIGNvbnN0IGdyYWRpZW50ID0gc2NhbGVUb0dlb2RldGljU3VyZmFjZUdyYWRpZW50OwogICAgZ3JhZGllbnQueCA9IGludGVyc2VjdGlvbi54ICogb25lT3ZlclJhZGlpU3F1YXJlZFggKiAyOwogICAgZ3JhZGllbnQueSA9IGludGVyc2VjdGlvbi55ICogb25lT3ZlclJhZGlpU3F1YXJlZFkgKiAyOwogICAgZ3JhZGllbnQueiA9IGludGVyc2VjdGlvbi56ICogb25lT3ZlclJhZGlpU3F1YXJlZFogKiAyOwogICAgbGV0IGxhbWJkYSA9ICgxIC0gcmF0aW8pICogQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZShjYXJ0ZXNpYW4xMSkgLyAoMC41ICogQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZShncmFkaWVudCkpOwogICAgbGV0IGNvcnJlY3Rpb24gPSAwOwogICAgbGV0IGZ1bmM7CiAgICBsZXQgZGVub21pbmF0b3I7CiAgICBsZXQgeE11bHRpcGxpZXI7CiAgICBsZXQgeU11bHRpcGxpZXI7CiAgICBsZXQgek11bHRpcGxpZXI7CiAgICBsZXQgeE11bHRpcGxpZXIyOwogICAgbGV0IHlNdWx0aXBsaWVyMjsKICAgIGxldCB6TXVsdGlwbGllcjI7CiAgICBsZXQgeE11bHRpcGxpZXIzOwogICAgbGV0IHlNdWx0aXBsaWVyMzsKICAgIGxldCB6TXVsdGlwbGllcjM7CiAgICBkbyB7CiAgICAgIGxhbWJkYSAtPSBjb3JyZWN0aW9uOwogICAgICB4TXVsdGlwbGllciA9IDEgLyAoMSArIGxhbWJkYSAqIG9uZU92ZXJSYWRpaVNxdWFyZWRYKTsKICAgICAgeU11bHRpcGxpZXIgPSAxIC8gKDEgKyBsYW1iZGEgKiBvbmVPdmVyUmFkaWlTcXVhcmVkWSk7CiAgICAgIHpNdWx0aXBsaWVyID0gMSAvICgxICsgbGFtYmRhICogb25lT3ZlclJhZGlpU3F1YXJlZFopOwogICAgICB4TXVsdGlwbGllcjIgPSB4TXVsdGlwbGllciAqIHhNdWx0aXBsaWVyOwogICAgICB5TXVsdGlwbGllcjIgPSB5TXVsdGlwbGllciAqIHlNdWx0aXBsaWVyOwogICAgICB6TXVsdGlwbGllcjIgPSB6TXVsdGlwbGllciAqIHpNdWx0aXBsaWVyOwogICAgICB4TXVsdGlwbGllcjMgPSB4TXVsdGlwbGllcjIgKiB4TXVsdGlwbGllcjsKICAgICAgeU11bHRpcGxpZXIzID0geU11bHRpcGxpZXIyICogeU11bHRpcGxpZXI7CiAgICAgIHpNdWx0aXBsaWVyMyA9IHpNdWx0aXBsaWVyMiAqIHpNdWx0aXBsaWVyOwogICAgICBmdW5jID0geDIgKiB4TXVsdGlwbGllcjIgKyB5MiAqIHlNdWx0aXBsaWVyMiArIHoyICogek11bHRpcGxpZXIyIC0gMTsKICAgICAgZGVub21pbmF0b3IgPSB4MiAqIHhNdWx0aXBsaWVyMyAqIG9uZU92ZXJSYWRpaVNxdWFyZWRYICsgeTIgKiB5TXVsdGlwbGllcjMgKiBvbmVPdmVyUmFkaWlTcXVhcmVkWSArIHoyICogek11bHRpcGxpZXIzICogb25lT3ZlclJhZGlpU3F1YXJlZFo7CiAgICAgIGNvbnN0IGRlcml2YXRpdmUgPSAtMiAqIGRlbm9taW5hdG9yOwogICAgICBjb3JyZWN0aW9uID0gZnVuYyAvIGRlcml2YXRpdmU7CiAgICB9IHdoaWxlIChNYXRoLmFicyhmdW5jKSA+IE1hdGhfZGVmYXVsdC5FUFNJTE9OMTIpOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICByZXR1cm4gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgKICAgICAgICBwb3NpdGlvblggKiB4TXVsdGlwbGllciwKICAgICAgICBwb3NpdGlvblkgKiB5TXVsdGlwbGllciwKICAgICAgICBwb3NpdGlvblogKiB6TXVsdGlwbGllcgogICAgICApOwogICAgfQogICAgcmVzdWx0LnggPSBwb3NpdGlvblggKiB4TXVsdGlwbGllcjsKICAgIHJlc3VsdC55ID0gcG9zaXRpb25ZICogeU11bHRpcGxpZXI7CiAgICByZXN1bHQueiA9IHBvc2l0aW9uWiAqIHpNdWx0aXBsaWVyOwogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgdmFyIHNjYWxlVG9HZW9kZXRpY1N1cmZhY2VJbnRlcnNlY3Rpb24sIHNjYWxlVG9HZW9kZXRpY1N1cmZhY2VHcmFkaWVudCwgc2NhbGVUb0dlb2RldGljU3VyZmFjZV9kZWZhdWx0OwogIHZhciBpbml0X3NjYWxlVG9HZW9kZXRpY1N1cmZhY2UgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL3NjYWxlVG9HZW9kZXRpY1N1cmZhY2UuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIHNjYWxlVG9HZW9kZXRpY1N1cmZhY2VJbnRlcnNlY3Rpb24gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjYWxlVG9HZW9kZXRpY1N1cmZhY2VHcmFkaWVudCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NhbGVUb0dlb2RldGljU3VyZmFjZV9kZWZhdWx0ID0gc2NhbGVUb0dlb2RldGljU3VyZmFjZTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NhcnRvZ3JhcGhpYy5qcwogIGZ1bmN0aW9uIENhcnRvZ3JhcGhpYyhsb25naXR1ZGUsIGxhdGl0dWRlLCBoZWlnaHQpIHsKICAgIHRoaXMubG9uZ2l0dWRlID0gbG9uZ2l0dWRlID8/IDA7CiAgICB0aGlzLmxhdGl0dWRlID0gbGF0aXR1ZGUgPz8gMDsKICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0ID8/IDA7CiAgfQogIHZhciBjYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpY04sIGNhcnRlc2lhblRvQ2FydG9ncmFwaGljUCwgY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWNILCBDYXJ0b2dyYXBoaWNfZGVmYXVsdDsKICB2YXIgaW5pdF9DYXJ0b2dyYXBoaWMgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NhcnRvZ3JhcGhpYy5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9zY2FsZVRvR2VvZGV0aWNTdXJmYWNlKCk7CiAgICAgIENhcnRvZ3JhcGhpYy5mcm9tUmFkaWFucyA9IGZ1bmN0aW9uKGxvbmdpdHVkZSwgbGF0aXR1ZGUsIGhlaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJsb25naXR1ZGUiLCBsb25naXR1ZGUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigibGF0aXR1ZGUiLCBsYXRpdHVkZSk7CiAgICAgICAgaGVpZ2h0ID0gaGVpZ2h0ID8/IDA7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBDYXJ0b2dyYXBoaWMobG9uZ2l0dWRlLCBsYXRpdHVkZSwgaGVpZ2h0KTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmxvbmdpdHVkZSA9IGxvbmdpdHVkZTsKICAgICAgICByZXN1bHQubGF0aXR1ZGUgPSBsYXRpdHVkZTsKICAgICAgICByZXN1bHQuaGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRvZ3JhcGhpYy5mcm9tRGVncmVlcyA9IGZ1bmN0aW9uKGxvbmdpdHVkZSwgbGF0aXR1ZGUsIGhlaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJsb25naXR1ZGUiLCBsb25naXR1ZGUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigibGF0aXR1ZGUiLCBsYXRpdHVkZSk7CiAgICAgICAgbG9uZ2l0dWRlID0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucyhsb25naXR1ZGUpOwogICAgICAgIGxhdGl0dWRlID0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucyhsYXRpdHVkZSk7CiAgICAgICAgcmV0dXJuIENhcnRvZ3JhcGhpYy5mcm9tUmFkaWFucyhsb25naXR1ZGUsIGxhdGl0dWRlLCBoZWlnaHQsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIGNhcnRlc2lhblRvQ2FydG9ncmFwaGljTiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWNQID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBjYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpY0ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIENhcnRvZ3JhcGhpYy5fZWxsaXBzb2lkT25lT3ZlclJhZGlpID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgKICAgICAgICAxIC8gNjM3ODEzNywKICAgICAgICAxIC8gNjM3ODEzNywKICAgICAgICAxIC8gNjM1Njc1MjMxNDI0NTE3OWUtOQogICAgICApOwogICAgICBDYXJ0b2dyYXBoaWMuX2VsbGlwc29pZE9uZU92ZXJSYWRpaVNxdWFyZWQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KAogICAgICAgIDEgLyAoNjM3ODEzNyAqIDYzNzgxMzcpLAogICAgICAgIDEgLyAoNjM3ODEzNyAqIDYzNzgxMzcpLAogICAgICAgIDEgLyAoNjM1Njc1MjMxNDI0NTE3OWUtOSAqIDYzNTY3NTIzMTQyNDUxNzllLTkpCiAgICAgICk7CiAgICAgIENhcnRvZ3JhcGhpYy5fZWxsaXBzb2lkQ2VudGVyVG9sZXJhbmNlU3F1YXJlZCA9IE1hdGhfZGVmYXVsdC5FUFNJTE9OMTsKICAgICAgQ2FydG9ncmFwaGljLmZyb21DYXJ0ZXNpYW4gPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgZWxsaXBzb2lkLCByZXN1bHQpIHsKICAgICAgICBjb25zdCBvbmVPdmVyUmFkaWkgPSBkZWZpbmVkX2RlZmF1bHQoZWxsaXBzb2lkKSA/IGVsbGlwc29pZC5vbmVPdmVyUmFkaWkgOiBDYXJ0b2dyYXBoaWMuX2VsbGlwc29pZE9uZU92ZXJSYWRpaTsKICAgICAgICBjb25zdCBvbmVPdmVyUmFkaWlTcXVhcmVkID0gZGVmaW5lZF9kZWZhdWx0KGVsbGlwc29pZCkgPyBlbGxpcHNvaWQub25lT3ZlclJhZGlpU3F1YXJlZCA6IENhcnRvZ3JhcGhpYy5fZWxsaXBzb2lkT25lT3ZlclJhZGlpU3F1YXJlZDsKICAgICAgICBjb25zdCBjZW50ZXJUb2xlcmFuY2VTcXVhcmVkID0gZGVmaW5lZF9kZWZhdWx0KGVsbGlwc29pZCkgPyBlbGxpcHNvaWQuX2NlbnRlclRvbGVyYW5jZVNxdWFyZWQgOiBDYXJ0b2dyYXBoaWMuX2VsbGlwc29pZENlbnRlclRvbGVyYW5jZVNxdWFyZWQ7CiAgICAgICAgY29uc3QgcCA9IHNjYWxlVG9HZW9kZXRpY1N1cmZhY2VfZGVmYXVsdCgKICAgICAgICAgIGNhcnRlc2lhbjExLAogICAgICAgICAgb25lT3ZlclJhZGlpLAogICAgICAgICAgb25lT3ZlclJhZGlpU3F1YXJlZCwKICAgICAgICAgIGNlbnRlclRvbGVyYW5jZVNxdWFyZWQsCiAgICAgICAgICBjYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpY1AKICAgICAgICApOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHApKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBsZXQgbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUNvbXBvbmVudHMoCiAgICAgICAgICBwLAogICAgICAgICAgb25lT3ZlclJhZGlpU3F1YXJlZCwKICAgICAgICAgIGNhcnRlc2lhblRvQ2FydG9ncmFwaGljTgogICAgICAgICk7CiAgICAgICAgbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUobiwgbik7CiAgICAgICAgY29uc3QgaCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjYXJ0ZXNpYW4xMSwgcCwgY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWNIKTsKICAgICAgICBjb25zdCBsb25naXR1ZGUgPSBNYXRoLmF0YW4yKG4ueSwgbi54KTsKICAgICAgICBjb25zdCBsYXRpdHVkZSA9IE1hdGguYXNpbihuLnopOwogICAgICAgIGNvbnN0IGhlaWdodCA9IE1hdGhfZGVmYXVsdC5zaWduKENhcnRlc2lhbjNfZGVmYXVsdC5kb3QoaCwgY2FydGVzaWFuMTEpKSAqIENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUoaCk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBDYXJ0b2dyYXBoaWMobG9uZ2l0dWRlLCBsYXRpdHVkZSwgaGVpZ2h0KTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmxvbmdpdHVkZSA9IGxvbmdpdHVkZTsKICAgICAgICByZXN1bHQubGF0aXR1ZGUgPSBsYXRpdHVkZTsKICAgICAgICByZXN1bHQuaGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRvZ3JhcGhpYy50b0NhcnRlc2lhbiA9IGZ1bmN0aW9uKGNhcnRvZ3JhcGhpYzIsIGVsbGlwc29pZCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJjYXJ0b2dyYXBoaWMiLCBjYXJ0b2dyYXBoaWMyKTsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21SYWRpYW5zKAogICAgICAgICAgY2FydG9ncmFwaGljMi5sb25naXR1ZGUsCiAgICAgICAgICBjYXJ0b2dyYXBoaWMyLmxhdGl0dWRlLAogICAgICAgICAgY2FydG9ncmFwaGljMi5oZWlnaHQsCiAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICByZXN1bHQKICAgICAgICApOwogICAgICB9OwogICAgICBDYXJ0b2dyYXBoaWMuY2xvbmUgPSBmdW5jdGlvbihjYXJ0b2dyYXBoaWMyLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChjYXJ0b2dyYXBoaWMyKSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBDYXJ0b2dyYXBoaWMoCiAgICAgICAgICAgIGNhcnRvZ3JhcGhpYzIubG9uZ2l0dWRlLAogICAgICAgICAgICBjYXJ0b2dyYXBoaWMyLmxhdGl0dWRlLAogICAgICAgICAgICBjYXJ0b2dyYXBoaWMyLmhlaWdodAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmxvbmdpdHVkZSA9IGNhcnRvZ3JhcGhpYzIubG9uZ2l0dWRlOwogICAgICAgIHJlc3VsdC5sYXRpdHVkZSA9IGNhcnRvZ3JhcGhpYzIubGF0aXR1ZGU7CiAgICAgICAgcmVzdWx0LmhlaWdodCA9IGNhcnRvZ3JhcGhpYzIuaGVpZ2h0OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRvZ3JhcGhpYy5lcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiBsZWZ0LmxvbmdpdHVkZSA9PT0gcmlnaHQubG9uZ2l0dWRlICYmIGxlZnQubGF0aXR1ZGUgPT09IHJpZ2h0LmxhdGl0dWRlICYmIGxlZnQuaGVpZ2h0ID09PSByaWdodC5oZWlnaHQ7CiAgICAgIH07CiAgICAgIENhcnRvZ3JhcGhpYy5lcXVhbHNFcHNpbG9uID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIGVwc2lsb24pIHsKICAgICAgICBlcHNpbG9uID0gZXBzaWxvbiA/PyAwOwogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiBNYXRoLmFicyhsZWZ0LmxvbmdpdHVkZSAtIHJpZ2h0LmxvbmdpdHVkZSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0LmxhdGl0dWRlIC0gcmlnaHQubGF0aXR1ZGUpIDw9IGVwc2lsb24gJiYgTWF0aC5hYnMobGVmdC5oZWlnaHQgLSByaWdodC5oZWlnaHQpIDw9IGVwc2lsb247CiAgICAgIH07CiAgICAgIENhcnRvZ3JhcGhpYy5aRVJPID0gT2JqZWN0LmZyZWV6ZShuZXcgQ2FydG9ncmFwaGljKDAsIDAsIDApKTsKICAgICAgQ2FydG9ncmFwaGljLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAgIHJldHVybiBDYXJ0b2dyYXBoaWMuY2xvbmUodGhpcywgcmVzdWx0KTsKICAgICAgfTsKICAgICAgQ2FydG9ncmFwaGljLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbihyaWdodCkgewogICAgICAgIHJldHVybiBDYXJ0b2dyYXBoaWMuZXF1YWxzKHRoaXMsIHJpZ2h0KTsKICAgICAgfTsKICAgICAgQ2FydG9ncmFwaGljLnByb3RvdHlwZS5lcXVhbHNFcHNpbG9uID0gZnVuY3Rpb24ocmlnaHQsIGVwc2lsb24pIHsKICAgICAgICByZXR1cm4gQ2FydG9ncmFwaGljLmVxdWFsc0Vwc2lsb24odGhpcywgcmlnaHQsIGVwc2lsb24pOwogICAgICB9OwogICAgICBDYXJ0b2dyYXBoaWMucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIGAoJHt0aGlzLmxvbmdpdHVkZX0sICR7dGhpcy5sYXRpdHVkZX0sICR7dGhpcy5oZWlnaHR9KWA7CiAgICAgIH07CiAgICAgIENhcnRvZ3JhcGhpY19kZWZhdWx0ID0gQ2FydG9ncmFwaGljOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ2FydGVzaWFuMi5qcwogIGZ1bmN0aW9uIENhcnRlc2lhbjIoeCwgeSkgewogICAgdGhpcy54ID0geCA/PyAwOwogICAgdGhpcy55ID0geSA/PyAwOwogIH0KICB2YXIgZGlzdGFuY2VTY3JhdGNoMiwgbGVycFNjcmF0Y2gyLCBhbmdsZUJldHdlZW5TY3JhdGNoMywgYW5nbGVCZXR3ZWVuU2NyYXRjaDIyLCBtb3N0T3J0aG9nb25hbEF4aXNTY3JhdGNoMiwgQ2FydGVzaWFuMl9kZWZhdWx0OwogIHZhciBpbml0X0NhcnRlc2lhbjIgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NhcnRlc2lhbjIuanMiKCkgewogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBDYXJ0ZXNpYW4yLmZyb21FbGVtZW50cyA9IGZ1bmN0aW9uKHgsIHksIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgQ2FydGVzaWFuMih4LCB5KTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnggPSB4OwogICAgICAgIHJlc3VsdC55ID0geTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLmNsb25lID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGNhcnRlc2lhbjExKSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBDYXJ0ZXNpYW4yKGNhcnRlc2lhbjExLngsIGNhcnRlc2lhbjExLnkpOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IGNhcnRlc2lhbjExLng7CiAgICAgICAgcmVzdWx0LnkgPSBjYXJ0ZXNpYW4xMS55OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjIuZnJvbUNhcnRlc2lhbjMgPSBDYXJ0ZXNpYW4yLmNsb25lOwogICAgICBDYXJ0ZXNpYW4yLmZyb21DYXJ0ZXNpYW40ID0gQ2FydGVzaWFuMi5jbG9uZTsKICAgICAgQ2FydGVzaWFuMi5wYWNrZWRMZW5ndGggPSAyOwogICAgICBDYXJ0ZXNpYW4yLnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUueDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLnk7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLnVucGFjayA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydGluZ0luZGV4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjIoKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnggPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdC55ID0gYXJyYXlbc3RhcnRpbmdJbmRleF07CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMi5wYWNrQXJyYXkgPSBmdW5jdGlvbihhcnJheSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBjb25zdCBsZW5ndGggPSBhcnJheS5sZW5ndGg7CiAgICAgICAgY29uc3QgcmVzdWx0TGVuZ3RoID0gbGVuZ3RoICogMjsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQXJyYXkocmVzdWx0TGVuZ3RoKTsKICAgICAgICB9IGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KHJlc3VsdCkgJiYgcmVzdWx0Lmxlbmd0aCAhPT0gcmVzdWx0TGVuZ3RoKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgIklmIHJlc3VsdCBpcyBhIHR5cGVkIGFycmF5LCBpdCBtdXN0IGhhdmUgZXhhY3RseSBhcnJheS5sZW5ndGggKiAyIGVsZW1lbnRzIgogICAgICAgICAgKTsKICAgICAgICB9IGVsc2UgaWYgKHJlc3VsdC5sZW5ndGggIT09IHJlc3VsdExlbmd0aCkgewogICAgICAgICAgcmVzdWx0Lmxlbmd0aCA9IHJlc3VsdExlbmd0aDsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgQ2FydGVzaWFuMi5wYWNrKGFycmF5W2ldLCByZXN1bHQsIGkgKiAyKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMi51bnBhY2tBcnJheSA9IGZ1bmN0aW9uKGFycmF5LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJhcnJheS5sZW5ndGgiLCBhcnJheS5sZW5ndGgsIDIpOwogICAgICAgIGlmIChhcnJheS5sZW5ndGggJSAyICE9PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYXJyYXkgbGVuZ3RoIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAyLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBsZW5ndGggPSBhcnJheS5sZW5ndGg7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEFycmF5KGxlbmd0aCAvIDIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQubGVuZ3RoID0gbGVuZ3RoIC8gMjsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMikgewogICAgICAgICAgY29uc3QgaW5kZXggPSBpIC8gMjsKICAgICAgICAgIHJlc3VsdFtpbmRleF0gPSBDYXJ0ZXNpYW4yLnVucGFjayhhcnJheSwgaSwgcmVzdWx0W2luZGV4XSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjIuZnJvbUFycmF5ID0gQ2FydGVzaWFuMi51bnBhY2s7CiAgICAgIENhcnRlc2lhbjIubWF4aW11bUNvbXBvbmVudCA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgcmV0dXJuIE1hdGgubWF4KGNhcnRlc2lhbjExLngsIGNhcnRlc2lhbjExLnkpOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLm1pbmltdW1Db21wb25lbnQgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIHJldHVybiBNYXRoLm1pbihjYXJ0ZXNpYW4xMS54LCBjYXJ0ZXNpYW4xMS55KTsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMi5taW5pbXVtQnlDb21wb25lbnQgPSBmdW5jdGlvbihmaXJzdCwgc2Vjb25kLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImZpcnN0IiwgZmlyc3QpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic2Vjb25kIiwgc2Vjb25kKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBNYXRoLm1pbihmaXJzdC54LCBzZWNvbmQueCk7CiAgICAgICAgcmVzdWx0LnkgPSBNYXRoLm1pbihmaXJzdC55LCBzZWNvbmQueSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMi5tYXhpbXVtQnlDb21wb25lbnQgPSBmdW5jdGlvbihmaXJzdCwgc2Vjb25kLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImZpcnN0IiwgZmlyc3QpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic2Vjb25kIiwgc2Vjb25kKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBNYXRoLm1heChmaXJzdC54LCBzZWNvbmQueCk7CiAgICAgICAgcmVzdWx0LnkgPSBNYXRoLm1heChmaXJzdC55LCBzZWNvbmQueSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMi5jbGFtcCA9IGZ1bmN0aW9uKHZhbHVlLCBtaW4zLCBtYXgzLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWluIiwgbWluMyk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXgiLCBtYXgzKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgeCA9IE1hdGhfZGVmYXVsdC5jbGFtcCh2YWx1ZS54LCBtaW4zLngsIG1heDMueCk7CiAgICAgICAgY29uc3QgeSA9IE1hdGhfZGVmYXVsdC5jbGFtcCh2YWx1ZS55LCBtaW4zLnksIG1heDMueSk7CiAgICAgICAgcmVzdWx0LnggPSB4OwogICAgICAgIHJlc3VsdC55ID0geTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLm1hZ25pdHVkZVNxdWFyZWQgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIHJldHVybiBjYXJ0ZXNpYW4xMS54ICogY2FydGVzaWFuMTEueCArIGNhcnRlc2lhbjExLnkgKiBjYXJ0ZXNpYW4xMS55OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLm1hZ25pdHVkZSA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExKSB7CiAgICAgICAgcmV0dXJuIE1hdGguc3FydChDYXJ0ZXNpYW4yLm1hZ25pdHVkZVNxdWFyZWQoY2FydGVzaWFuMTEpKTsKICAgICAgfTsKICAgICAgZGlzdGFuY2VTY3JhdGNoMiA9IG5ldyBDYXJ0ZXNpYW4yKCk7CiAgICAgIENhcnRlc2lhbjIuZGlzdGFuY2UgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2FydGVzaWFuMi5zdWJ0cmFjdChsZWZ0LCByaWdodCwgZGlzdGFuY2VTY3JhdGNoMik7CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjIubWFnbml0dWRlKGRpc3RhbmNlU2NyYXRjaDIpOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLmRpc3RhbmNlU3F1YXJlZCA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDYXJ0ZXNpYW4yLnN1YnRyYWN0KGxlZnQsIHJpZ2h0LCBkaXN0YW5jZVNjcmF0Y2gyKTsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuMi5tYWduaXR1ZGVTcXVhcmVkKGRpc3RhbmNlU2NyYXRjaDIpOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLm5vcm1hbGl6ZSA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgbWFnbml0dWRlID0gQ2FydGVzaWFuMi5tYWduaXR1ZGUoY2FydGVzaWFuMTEpOwogICAgICAgIHJlc3VsdC54ID0gY2FydGVzaWFuMTEueCAvIG1hZ25pdHVkZTsKICAgICAgICByZXN1bHQueSA9IGNhcnRlc2lhbjExLnkgLyBtYWduaXR1ZGU7CiAgICAgICAgaWYgKGlzTmFOKHJlc3VsdC54KSB8fCBpc05hTihyZXN1bHQueSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJub3JtYWxpemVkIHJlc3VsdCBpcyBub3QgYSBudW1iZXIiKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMi5kb3QgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgcmV0dXJuIGxlZnQueCAqIHJpZ2h0LnggKyBsZWZ0LnkgKiByaWdodC55OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLmNyb3NzID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImxlZnQiLCBsZWZ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJpZ2h0IiwgcmlnaHQpOwogICAgICAgIHJldHVybiBsZWZ0LnggKiByaWdodC55IC0gbGVmdC55ICogcmlnaHQueDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMi5tdWx0aXBseUNvbXBvbmVudHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBsZWZ0LnggKiByaWdodC54OwogICAgICAgIHJlc3VsdC55ID0gbGVmdC55ICogcmlnaHQueTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLmRpdmlkZUNvbXBvbmVudHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBsZWZ0LnggLyByaWdodC54OwogICAgICAgIHJlc3VsdC55ID0gbGVmdC55IC8gcmlnaHQueTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLmFkZCA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImxlZnQiLCBsZWZ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJpZ2h0IiwgcmlnaHQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQueCA9IGxlZnQueCArIHJpZ2h0Lng7CiAgICAgICAgcmVzdWx0LnkgPSBsZWZ0LnkgKyByaWdodC55OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjIuc3VidHJhY3QgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBsZWZ0LnggLSByaWdodC54OwogICAgICAgIHJlc3VsdC55ID0gbGVmdC55IC0gcmlnaHQueTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLm11bHRpcGx5QnlTY2FsYXIgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgc2NhbGFyLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInNjYWxhciIsIHNjYWxhcik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gY2FydGVzaWFuMTEueCAqIHNjYWxhcjsKICAgICAgICByZXN1bHQueSA9IGNhcnRlc2lhbjExLnkgKiBzY2FsYXI7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMi5kaXZpZGVCeVNjYWxhciA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCBzY2FsYXIsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigic2NhbGFyIiwgc2NhbGFyKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBjYXJ0ZXNpYW4xMS54IC8gc2NhbGFyOwogICAgICAgIHJlc3VsdC55ID0gY2FydGVzaWFuMTEueSAvIHNjYWxhcjsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLm5lZ2F0ZSA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSAtY2FydGVzaWFuMTEueDsKICAgICAgICByZXN1bHQueSA9IC1jYXJ0ZXNpYW4xMS55OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjIuYWJzID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQueCA9IE1hdGguYWJzKGNhcnRlc2lhbjExLngpOwogICAgICAgIHJlc3VsdC55ID0gTWF0aC5hYnMoY2FydGVzaWFuMTEueSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgbGVycFNjcmF0Y2gyID0gbmV3IENhcnRlc2lhbjIoKTsKICAgICAgQ2FydGVzaWFuMi5sZXJwID0gZnVuY3Rpb24oc3RhcnQsIGVuZCwgdCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzdGFydCIsIHN0YXJ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImVuZCIsIGVuZCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJ0IiwgdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIENhcnRlc2lhbjIubXVsdGlwbHlCeVNjYWxhcihlbmQsIHQsIGxlcnBTY3JhdGNoMik7CiAgICAgICAgcmVzdWx0ID0gQ2FydGVzaWFuMi5tdWx0aXBseUJ5U2NhbGFyKHN0YXJ0LCAxIC0gdCwgcmVzdWx0KTsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuMi5hZGQobGVycFNjcmF0Y2gyLCByZXN1bHQsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIGFuZ2xlQmV0d2VlblNjcmF0Y2gzID0gbmV3IENhcnRlc2lhbjIoKTsKICAgICAgYW5nbGVCZXR3ZWVuU2NyYXRjaDIyID0gbmV3IENhcnRlc2lhbjIoKTsKICAgICAgQ2FydGVzaWFuMi5hbmdsZUJldHdlZW4gPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2FydGVzaWFuMi5ub3JtYWxpemUobGVmdCwgYW5nbGVCZXR3ZWVuU2NyYXRjaDMpOwogICAgICAgIENhcnRlc2lhbjIubm9ybWFsaXplKHJpZ2h0LCBhbmdsZUJldHdlZW5TY3JhdGNoMjIpOwogICAgICAgIHJldHVybiBNYXRoX2RlZmF1bHQuYWNvc0NsYW1wZWQoCiAgICAgICAgICBDYXJ0ZXNpYW4yLmRvdChhbmdsZUJldHdlZW5TY3JhdGNoMywgYW5nbGVCZXR3ZWVuU2NyYXRjaDIyKQogICAgICAgICk7CiAgICAgIH07CiAgICAgIG1vc3RPcnRob2dvbmFsQXhpc1NjcmF0Y2gyID0gbmV3IENhcnRlc2lhbjIoKTsKICAgICAgQ2FydGVzaWFuMi5tb3N0T3J0aG9nb25hbEF4aXMgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IGYgPSBDYXJ0ZXNpYW4yLm5vcm1hbGl6ZShjYXJ0ZXNpYW4xMSwgbW9zdE9ydGhvZ29uYWxBeGlzU2NyYXRjaDIpOwogICAgICAgIENhcnRlc2lhbjIuYWJzKGYsIGYpOwogICAgICAgIGlmIChmLnggPD0gZi55KSB7CiAgICAgICAgICByZXN1bHQgPSBDYXJ0ZXNpYW4yLmNsb25lKENhcnRlc2lhbjIuVU5JVF9YLCByZXN1bHQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQgPSBDYXJ0ZXNpYW4yLmNsb25lKENhcnRlc2lhbjIuVU5JVF9ZLCByZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLmVxdWFscyA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIGxlZnQgPT09IHJpZ2h0IHx8IGRlZmluZWRfZGVmYXVsdChsZWZ0KSAmJiBkZWZpbmVkX2RlZmF1bHQocmlnaHQpICYmIGxlZnQueCA9PT0gcmlnaHQueCAmJiBsZWZ0LnkgPT09IHJpZ2h0Lnk7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjIuZXF1YWxzQXJyYXkgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgYXJyYXksIG9mZnNldCkgewogICAgICAgIHJldHVybiBjYXJ0ZXNpYW4xMS54ID09PSBhcnJheVtvZmZzZXRdICYmIGNhcnRlc2lhbjExLnkgPT09IGFycmF5W29mZnNldCArIDFdOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLmVxdWFsc0Vwc2lsb24gPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVsYXRpdmVFcHNpbG9uLCBhYnNvbHV0ZUVwc2lsb24pIHsKICAgICAgICByZXR1cm4gbGVmdCA9PT0gcmlnaHQgfHwgZGVmaW5lZF9kZWZhdWx0KGxlZnQpICYmIGRlZmluZWRfZGVmYXVsdChyaWdodCkgJiYgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICBsZWZ0LngsCiAgICAgICAgICByaWdodC54LAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKSAmJiBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIGxlZnQueSwKICAgICAgICAgIHJpZ2h0LnksCiAgICAgICAgICByZWxhdGl2ZUVwc2lsb24sCiAgICAgICAgICBhYnNvbHV0ZUVwc2lsb24KICAgICAgICApOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLlpFUk8gPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW4yKDAsIDApKTsKICAgICAgQ2FydGVzaWFuMi5PTkUgPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW4yKDEsIDEpKTsKICAgICAgQ2FydGVzaWFuMi5VTklUX1ggPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW4yKDEsIDApKTsKICAgICAgQ2FydGVzaWFuMi5VTklUX1kgPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW4yKDAsIDEpKTsKICAgICAgQ2FydGVzaWFuMi5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuMi5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbihyaWdodCkgewogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4yLmVxdWFscyh0aGlzLCByaWdodCk7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjIucHJvdG90eXBlLmVxdWFsc0Vwc2lsb24gPSBmdW5jdGlvbihyaWdodCwgcmVsYXRpdmVFcHNpbG9uLCBhYnNvbHV0ZUVwc2lsb24pIHsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuMi5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgdGhpcywKICAgICAgICAgIHJpZ2h0LAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKTsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuMi5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHsKICAgICAgICByZXR1cm4gYCgke3RoaXMueH0sICR7dGhpcy55fSlgOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQgPSBDYXJ0ZXNpYW4yOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvRWxsaXBzb2lkLmpzCiAgZnVuY3Rpb24gaW5pdGlhbGl6ZShlbGxpcHNvaWQsIHgsIHksIHopIHsKICAgIHggPSB4ID8/IDA7CiAgICB5ID0geSA/PyAwOwogICAgeiA9IHogPz8gMDsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJ4IiwgeCwgMCk7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygieSIsIHksIDApOwogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoInoiLCB6LCAwKTsKICAgIGVsbGlwc29pZC5fcmFkaWkgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KHgsIHksIHopOwogICAgZWxsaXBzb2lkLl9yYWRpaVNxdWFyZWQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KHggKiB4LCB5ICogeSwgeiAqIHopOwogICAgZWxsaXBzb2lkLl9yYWRpaVRvVGhlRm91cnRoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgKICAgICAgeCAqIHggKiB4ICogeCwKICAgICAgeSAqIHkgKiB5ICogeSwKICAgICAgeiAqIHogKiB6ICogegogICAgKTsKICAgIGVsbGlwc29pZC5fb25lT3ZlclJhZGlpID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgKICAgICAgeCA9PT0gMCA/IDAgOiAxIC8geCwKICAgICAgeSA9PT0gMCA/IDAgOiAxIC8geSwKICAgICAgeiA9PT0gMCA/IDAgOiAxIC8gegogICAgKTsKICAgIGVsbGlwc29pZC5fb25lT3ZlclJhZGlpU3F1YXJlZCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoCiAgICAgIHggPT09IDAgPyAwIDogMSAvICh4ICogeCksCiAgICAgIHkgPT09IDAgPyAwIDogMSAvICh5ICogeSksCiAgICAgIHogPT09IDAgPyAwIDogMSAvICh6ICogeikKICAgICk7CiAgICBlbGxpcHNvaWQuX21pbmltdW1SYWRpdXMgPSBNYXRoLm1pbih4LCB5LCB6KTsKICAgIGVsbGlwc29pZC5fbWF4aW11bVJhZGl1cyA9IE1hdGgubWF4KHgsIHksIHopOwogICAgZWxsaXBzb2lkLl9jZW50ZXJUb2xlcmFuY2VTcXVhcmVkID0gTWF0aF9kZWZhdWx0LkVQU0lMT04xOwogICAgaWYgKGVsbGlwc29pZC5fcmFkaWlTcXVhcmVkLnogIT09IDApIHsKICAgICAgZWxsaXBzb2lkLl9zcXVhcmVkWE92ZXJTcXVhcmVkWiA9IGVsbGlwc29pZC5fcmFkaWlTcXVhcmVkLnggLyBlbGxpcHNvaWQuX3JhZGlpU3F1YXJlZC56OwogICAgfQogIH0KICBmdW5jdGlvbiBFbGxpcHNvaWQoeCwgeSwgeikgewogICAgdGhpcy5fcmFkaWkgPSB2b2lkIDA7CiAgICB0aGlzLl9yYWRpaVNxdWFyZWQgPSB2b2lkIDA7CiAgICB0aGlzLl9yYWRpaVRvVGhlRm91cnRoID0gdm9pZCAwOwogICAgdGhpcy5fb25lT3ZlclJhZGlpID0gdm9pZCAwOwogICAgdGhpcy5fb25lT3ZlclJhZGlpU3F1YXJlZCA9IHZvaWQgMDsKICAgIHRoaXMuX21pbmltdW1SYWRpdXMgPSB2b2lkIDA7CiAgICB0aGlzLl9tYXhpbXVtUmFkaXVzID0gdm9pZCAwOwogICAgdGhpcy5fY2VudGVyVG9sZXJhbmNlU3F1YXJlZCA9IHZvaWQgMDsKICAgIHRoaXMuX3NxdWFyZWRYT3ZlclNxdWFyZWRaID0gdm9pZCAwOwogICAgaW5pdGlhbGl6ZSh0aGlzLCB4LCB5LCB6KTsKICB9CiAgZnVuY3Rpb24gZ2F1c3NMZWdlbmRyZVF1YWRyYXR1cmUoYTMsIGIsIGZ1bmMpIHsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigiYSIsIGEzKTsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigiYiIsIGIpOwogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YuZnVuYygiZnVuYyIsIGZ1bmMpOwogICAgY29uc3QgeE1lYW4gPSAwLjUgKiAoYiArIGEzKTsKICAgIGNvbnN0IHhSYW5nZSA9IDAuNSAqIChiIC0gYTMpOwogICAgbGV0IHN1bSA9IDA7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDU7IGkrKykgewogICAgICBjb25zdCBkeCA9IHhSYW5nZSAqIGFic2Npc3Nhc1tpXTsKICAgICAgc3VtICs9IHdlaWdodHNbaV0gKiAoZnVuYyh4TWVhbiArIGR4KSArIGZ1bmMoeE1lYW4gLSBkeCkpOwogICAgfQogICAgc3VtICo9IHhSYW5nZTsKICAgIHJldHVybiBzdW07CiAgfQogIHZhciBjYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbk5vcm1hbCwgY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW5LLCBjYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpY04yLCBjYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpY1AyLCBjYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpY0gyLCBzY3JhdGNoRW5kcG9pbnQsIGFic2Npc3Nhcywgd2VpZ2h0cywgRWxsaXBzb2lkX2RlZmF1bHQ7CiAgdmFyIGluaXRfRWxsaXBzb2lkID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9FbGxpcHNvaWQuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfc2NhbGVUb0dlb2RldGljU3VyZmFjZSgpOwogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhFbGxpcHNvaWQucHJvdG90eXBlLCB7CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgcmFkaWkgb2YgdGhlIGVsbGlwc29pZC4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtDYXJ0ZXNpYW4zfQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIHJhZGlpOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fcmFkaWk7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBzcXVhcmVkIHJhZGlpIG9mIHRoZSBlbGxpcHNvaWQuCiAgICAgICAgICogQG1lbWJlcm9mIEVsbGlwc29pZC5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7Q2FydGVzaWFuM30KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICByYWRpaVNxdWFyZWQ6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9yYWRpaVNxdWFyZWQ7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSByYWRpaSBvZiB0aGUgZWxsaXBzb2lkIHJhaXNlIHRvIHRoZSBmb3VydGggcG93ZXIuCiAgICAgICAgICogQG1lbWJlcm9mIEVsbGlwc29pZC5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7Q2FydGVzaWFuM30KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICByYWRpaVRvVGhlRm91cnRoOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fcmFkaWlUb1RoZUZvdXJ0aDsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgb25lIG92ZXIgdGhlIHJhZGlpIG9mIHRoZSBlbGxpcHNvaWQuCiAgICAgICAgICogQG1lbWJlcm9mIEVsbGlwc29pZC5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7Q2FydGVzaWFuM30KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBvbmVPdmVyUmFkaWk6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vbmVPdmVyUmFkaWk7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIG9uZSBvdmVyIHRoZSBzcXVhcmVkIHJhZGlpIG9mIHRoZSBlbGxpcHNvaWQuCiAgICAgICAgICogQG1lbWJlcm9mIEVsbGlwc29pZC5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7Q2FydGVzaWFuM30KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBvbmVPdmVyUmFkaWlTcXVhcmVkOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fb25lT3ZlclJhZGlpU3F1YXJlZDsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIG1pbmltdW0gcmFkaXVzIG9mIHRoZSBlbGxpcHNvaWQuCiAgICAgICAgICogQG1lbWJlcm9mIEVsbGlwc29pZC5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIG1pbmltdW1SYWRpdXM6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9taW5pbXVtUmFkaXVzOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgbWF4aW11bSByYWRpdXMgb2YgdGhlIGVsbGlwc29pZC4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgbWF4aW11bVJhZGl1czogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX21heGltdW1SYWRpdXM7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgRWxsaXBzb2lkLmNsb25lID0gZnVuY3Rpb24oZWxsaXBzb2lkLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChlbGxpcHNvaWQpKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBjb25zdCByYWRpaSA9IGVsbGlwc29pZC5fcmFkaWk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBFbGxpcHNvaWQocmFkaWkueCwgcmFkaWkueSwgcmFkaWkueik7CiAgICAgICAgfQogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShyYWRpaSwgcmVzdWx0Ll9yYWRpaSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGVsbGlwc29pZC5fcmFkaWlTcXVhcmVkLCByZXN1bHQuX3JhZGlpU3F1YXJlZCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGVsbGlwc29pZC5fcmFkaWlUb1RoZUZvdXJ0aCwgcmVzdWx0Ll9yYWRpaVRvVGhlRm91cnRoKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoZWxsaXBzb2lkLl9vbmVPdmVyUmFkaWksIHJlc3VsdC5fb25lT3ZlclJhZGlpKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoZWxsaXBzb2lkLl9vbmVPdmVyUmFkaWlTcXVhcmVkLCByZXN1bHQuX29uZU92ZXJSYWRpaVNxdWFyZWQpOwogICAgICAgIHJlc3VsdC5fbWluaW11bVJhZGl1cyA9IGVsbGlwc29pZC5fbWluaW11bVJhZGl1czsKICAgICAgICByZXN1bHQuX21heGltdW1SYWRpdXMgPSBlbGxpcHNvaWQuX21heGltdW1SYWRpdXM7CiAgICAgICAgcmVzdWx0Ll9jZW50ZXJUb2xlcmFuY2VTcXVhcmVkID0gZWxsaXBzb2lkLl9jZW50ZXJUb2xlcmFuY2VTcXVhcmVkOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZC5mcm9tQ2FydGVzaWFuMyA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgRWxsaXBzb2lkKCk7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGNhcnRlc2lhbjExKSkgewogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgaW5pdGlhbGl6ZShyZXN1bHQsIGNhcnRlc2lhbjExLngsIGNhcnRlc2lhbjExLnksIGNhcnRlc2lhbjExLnopOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZC5XR1M4NCA9IE9iamVjdC5mcmVlemUoCiAgICAgICAgbmV3IEVsbGlwc29pZCg2Mzc4MTM3LCA2Mzc4MTM3LCA2MzU2NzUyMzE0MjQ1MTc5ZS05KQogICAgICApOwogICAgICBFbGxpcHNvaWQuVU5JVF9TUEhFUkUgPSBPYmplY3QuZnJlZXplKG5ldyBFbGxpcHNvaWQoMSwgMSwgMSkpOwogICAgICBFbGxpcHNvaWQuTU9PTiA9IE9iamVjdC5mcmVlemUoCiAgICAgICAgbmV3IEVsbGlwc29pZCgKICAgICAgICAgIE1hdGhfZGVmYXVsdC5MVU5BUl9SQURJVVMsCiAgICAgICAgICBNYXRoX2RlZmF1bHQuTFVOQVJfUkFESVVTLAogICAgICAgICAgTWF0aF9kZWZhdWx0LkxVTkFSX1JBRElVUwogICAgICAgICkKICAgICAgKTsKICAgICAgRWxsaXBzb2lkLk1BUlMgPSBPYmplY3QuZnJlZXplKG5ldyBFbGxpcHNvaWQoMzM5NjE5MCwgMzM5NjE5MCwgMzM3NjIwMCkpOwogICAgICBFbGxpcHNvaWQuX2RlZmF1bHQgPSBFbGxpcHNvaWQuV0dTODQ7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKEVsbGlwc29pZCwgewogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBkZWZhdWx0IGVsbGlwc29pZCB1c2VkIHdoZW4gbm90IG90aGVyd2lzZSBzcGVjaWZpZWQuCiAgICAgICAgICogQG1lbWJlcm9mIEVsbGlwc29pZAogICAgICAgICAqIEB0eXBlIHtFbGxpcHNvaWR9CiAgICAgICAgICogQGV4YW1wbGUKICAgICAgICAgKiBDZXNpdW0uRWxsaXBzb2lkLmRlZmF1bHQgPSBDZXNpdW0uRWxsaXBzb2lkLk1PT047CiAgICAgICAgICoKICAgICAgICAgKiAvLyBBcG9sbG8gMTEgbGFuZGluZyBzaXRlCiAgICAgICAgICogY29uc3QgcG9zaXRpb24gPSBDZXNpdW0uQ2FydGVzaWFuMy5mcm9tUmFkaWFucygKICAgICAgICAgKiAgIDAuNjc0MTYsCiAgICAgICAgICogICAyMy40NzMxNSwKICAgICAgICAgKiApOwogICAgICAgICAqLwogICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBFbGxpcHNvaWQuX2RlZmF1bHQ7CiAgICAgICAgICB9LAogICAgICAgICAgc2V0OiBmdW5jdGlvbih2YWx1ZSkgewogICAgICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgICAgICBFbGxpcHNvaWQuX2RlZmF1bHQgPSB2YWx1ZTsKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Ll9lbGxpcHNvaWRSYWRpaVNxdWFyZWQgPSB2YWx1ZS5yYWRpaVNxdWFyZWQ7CiAgICAgICAgICAgIENhcnRvZ3JhcGhpY19kZWZhdWx0Ll9lbGxpcHNvaWRPbmVPdmVyUmFkaWkgPSB2YWx1ZS5vbmVPdmVyUmFkaWk7CiAgICAgICAgICAgIENhcnRvZ3JhcGhpY19kZWZhdWx0Ll9lbGxpcHNvaWRPbmVPdmVyUmFkaWlTcXVhcmVkID0gdmFsdWUub25lT3ZlclJhZGlpU3F1YXJlZDsKICAgICAgICAgICAgQ2FydG9ncmFwaGljX2RlZmF1bHQuX2VsbGlwc29pZENlbnRlclRvbGVyYW5jZVNxdWFyZWQgPSB2YWx1ZS5fY2VudGVyVG9sZXJhbmNlU3F1YXJlZDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBFbGxpcHNvaWQucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgcmV0dXJuIEVsbGlwc29pZC5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBFbGxpcHNvaWQucGFja2VkTGVuZ3RoID0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgRWxsaXBzb2lkLnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayh2YWx1ZS5fcmFkaWksIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZC51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGNvbnN0IHJhZGlpID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgcmV0dXJuIEVsbGlwc29pZC5mcm9tQ2FydGVzaWFuMyhyYWRpaSwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkLnByb3RvdHlwZS5nZW9jZW50cmljU3VyZmFjZU5vcm1hbCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemU7CiAgICAgIEVsbGlwc29pZC5wcm90b3R5cGUuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsQ2FydG9ncmFwaGljID0gZnVuY3Rpb24oY2FydG9ncmFwaGljMiwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0b2dyYXBoaWMiLCBjYXJ0b2dyYXBoaWMyKTsKICAgICAgICBjb25zdCBsb25naXR1ZGUgPSBjYXJ0b2dyYXBoaWMyLmxvbmdpdHVkZTsKICAgICAgICBjb25zdCBsYXRpdHVkZSA9IGNhcnRvZ3JhcGhpYzIubGF0aXR1ZGU7CiAgICAgICAgY29uc3QgY29zTGF0aXR1ZGUgPSBNYXRoLmNvcyhsYXRpdHVkZSk7CiAgICAgICAgY29uc3QgeCA9IGNvc0xhdGl0dWRlICogTWF0aC5jb3MobG9uZ2l0dWRlKTsKICAgICAgICBjb25zdCB5ID0gY29zTGF0aXR1ZGUgKiBNYXRoLnNpbihsb25naXR1ZGUpOwogICAgICAgIGNvbnN0IHogPSBNYXRoLnNpbihsYXRpdHVkZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IHg7CiAgICAgICAgcmVzdWx0LnkgPSB5OwogICAgICAgIHJlc3VsdC56ID0gejsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShyZXN1bHQsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZC5wcm90b3R5cGUuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIGlmIChpc05hTihjYXJ0ZXNpYW4xMS54KSB8fCBpc05hTihjYXJ0ZXNpYW4xMS55KSB8fCBpc05hTihjYXJ0ZXNpYW4xMS56KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImNhcnRlc2lhbiBoYXMgYSBOYU4gY29tcG9uZW50Iik7CiAgICAgICAgfQogICAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihjYXJ0ZXNpYW4xMSwgQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTQpKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUNvbXBvbmVudHMoCiAgICAgICAgICBjYXJ0ZXNpYW4xMSwKICAgICAgICAgIHRoaXMuX29uZU92ZXJSYWRpaVNxdWFyZWQsCiAgICAgICAgICByZXN1bHQKICAgICAgICApOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKHJlc3VsdCwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW5Ob3JtYWwgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuSyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgRWxsaXBzb2lkLnByb3RvdHlwZS5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbiA9IGZ1bmN0aW9uKGNhcnRvZ3JhcGhpYzIsIHJlc3VsdCkgewogICAgICAgIGNvbnN0IG4gPSBjYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbk5vcm1hbDsKICAgICAgICBjb25zdCBrID0gY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW5LOwogICAgICAgIHRoaXMuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsQ2FydG9ncmFwaGljKGNhcnRvZ3JhcGhpYzIsIG4pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUNvbXBvbmVudHModGhpcy5fcmFkaWlTcXVhcmVkLCBuLCBrKTsKICAgICAgICBjb25zdCBnYW1tYSA9IE1hdGguc3FydChDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KG4sIGspKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZGl2aWRlQnlTY2FsYXIoaywgZ2FtbWEsIGspOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKG4sIGNhcnRvZ3JhcGhpYzIuaGVpZ2h0LCBuKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGssIG4sIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZC5wcm90b3R5cGUuY2FydG9ncmFwaGljQXJyYXlUb0NhcnRlc2lhbkFycmF5ID0gZnVuY3Rpb24oY2FydG9ncmFwaGljcywgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJjYXJ0b2dyYXBoaWNzIiwgY2FydG9ncmFwaGljcyk7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gY2FydG9ncmFwaGljcy5sZW5ndGg7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5sZW5ndGggPSBsZW5ndGg7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHJlc3VsdFtpXSA9IHRoaXMuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oY2FydG9ncmFwaGljc1tpXSwgcmVzdWx0W2ldKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWNOMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWNQMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWNIMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgRWxsaXBzb2lkLnByb3RvdHlwZS5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBjb25zdCBwID0gdGhpcy5zY2FsZVRvR2VvZGV0aWNTdXJmYWNlKGNhcnRlc2lhbjExLCBjYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpY1AyKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwKSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgY29uc3QgbiA9IHRoaXMuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKHAsIGNhcnRlc2lhblRvQ2FydG9ncmFwaGljTjIpOwogICAgICAgIGNvbnN0IGggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoY2FydGVzaWFuMTEsIHAsIGNhcnRlc2lhblRvQ2FydG9ncmFwaGljSDIpOwogICAgICAgIGNvbnN0IGxvbmdpdHVkZSA9IE1hdGguYXRhbjIobi55LCBuLngpOwogICAgICAgIGNvbnN0IGxhdGl0dWRlID0gTWF0aC5hc2luKG4ueik7CiAgICAgICAgY29uc3QgaGVpZ2h0ID0gTWF0aF9kZWZhdWx0LnNpZ24oQ2FydGVzaWFuM19kZWZhdWx0LmRvdChoLCBjYXJ0ZXNpYW4xMSkpICogQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZShoKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KGxvbmdpdHVkZSwgbGF0aXR1ZGUsIGhlaWdodCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5sb25naXR1ZGUgPSBsb25naXR1ZGU7CiAgICAgICAgcmVzdWx0LmxhdGl0dWRlID0gbGF0aXR1ZGU7CiAgICAgICAgcmVzdWx0LmhlaWdodCA9IGhlaWdodDsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBFbGxpcHNvaWQucHJvdG90eXBlLmNhcnRlc2lhbkFycmF5VG9DYXJ0b2dyYXBoaWNBcnJheSA9IGZ1bmN0aW9uKGNhcnRlc2lhbnMsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiY2FydGVzaWFucyIsIGNhcnRlc2lhbnMpOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IGNhcnRlc2lhbnMubGVuZ3RoOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQubGVuZ3RoID0gbGVuZ3RoOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICByZXN1bHRbaV0gPSB0aGlzLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKGNhcnRlc2lhbnNbaV0sIHJlc3VsdFtpXSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZC5wcm90b3R5cGUuc2NhbGVUb0dlb2RldGljU3VyZmFjZSA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICByZXR1cm4gc2NhbGVUb0dlb2RldGljU3VyZmFjZV9kZWZhdWx0KAogICAgICAgICAgY2FydGVzaWFuMTEsCiAgICAgICAgICB0aGlzLl9vbmVPdmVyUmFkaWksCiAgICAgICAgICB0aGlzLl9vbmVPdmVyUmFkaWlTcXVhcmVkLAogICAgICAgICAgdGhpcy5fY2VudGVyVG9sZXJhbmNlU3F1YXJlZCwKICAgICAgICAgIHJlc3VsdAogICAgICAgICk7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZC5wcm90b3R5cGUuc2NhbGVUb0dlb2NlbnRyaWNTdXJmYWNlID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcG9zaXRpb25YID0gY2FydGVzaWFuMTEueDsKICAgICAgICBjb25zdCBwb3NpdGlvblkgPSBjYXJ0ZXNpYW4xMS55OwogICAgICAgIGNvbnN0IHBvc2l0aW9uWiA9IGNhcnRlc2lhbjExLno7CiAgICAgICAgY29uc3Qgb25lT3ZlclJhZGlpU3F1YXJlZCA9IHRoaXMuX29uZU92ZXJSYWRpaVNxdWFyZWQ7CiAgICAgICAgY29uc3QgYmV0YSA9IDEgLyBNYXRoLnNxcnQoCiAgICAgICAgICBwb3NpdGlvblggKiBwb3NpdGlvblggKiBvbmVPdmVyUmFkaWlTcXVhcmVkLnggKyBwb3NpdGlvblkgKiBwb3NpdGlvblkgKiBvbmVPdmVyUmFkaWlTcXVhcmVkLnkgKyBwb3NpdGlvblogKiBwb3NpdGlvblogKiBvbmVPdmVyUmFkaWlTcXVhcmVkLnoKICAgICAgICApOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihjYXJ0ZXNpYW4xMSwgYmV0YSwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkLnByb3RvdHlwZS50cmFuc2Zvcm1Qb3NpdGlvblRvU2NhbGVkU3BhY2UgPSBmdW5jdGlvbihwb3NpdGlvbiwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5Q29tcG9uZW50cyhwb3NpdGlvbiwgdGhpcy5fb25lT3ZlclJhZGlpLCByZXN1bHQpOwogICAgICB9OwogICAgICBFbGxpcHNvaWQucHJvdG90eXBlLnRyYW5zZm9ybVBvc2l0aW9uRnJvbVNjYWxlZFNwYWNlID0gZnVuY3Rpb24ocG9zaXRpb24sIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUNvbXBvbmVudHMocG9zaXRpb24sIHRoaXMuX3JhZGlpLCByZXN1bHQpOwogICAgICB9OwogICAgICBFbGxpcHNvaWQucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uKHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIHRoaXMgPT09IHJpZ2h0IHx8IGRlZmluZWRfZGVmYXVsdChyaWdodCkgJiYgQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFscyh0aGlzLl9yYWRpaSwgcmlnaHQuX3JhZGlpKTsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiB0aGlzLl9yYWRpaS50b1N0cmluZygpOwogICAgICB9OwogICAgICBFbGxpcHNvaWQucHJvdG90eXBlLmdldFN1cmZhY2VOb3JtYWxJbnRlcnNlY3Rpb25XaXRoWkF4aXMgPSBmdW5jdGlvbihwb3NpdGlvbiwgYnVmZmVyLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInBvc2l0aW9uIiwgcG9zaXRpb24pOwogICAgICAgIGlmICghTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICB0aGlzLl9yYWRpaS54LAogICAgICAgICAgdGhpcy5fcmFkaWkueSwKICAgICAgICAgIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTUKICAgICAgICApKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgIkVsbGlwc29pZCBtdXN0IGJlIGFuIGVsbGlwc29pZCBvZiByZXZvbHV0aW9uIChyYWRpaS54ID09IHJhZGlpLnkpIgogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuKCJFbGxpcHNvaWQucmFkaWkueiIsIHRoaXMuX3JhZGlpLnosIDApOwogICAgICAgIGJ1ZmZlciA9IGJ1ZmZlciA/PyAwOwogICAgICAgIGNvbnN0IHNxdWFyZWRYT3ZlclNxdWFyZWRaID0gdGhpcy5fc3F1YXJlZFhPdmVyU3F1YXJlZFo7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IDA7CiAgICAgICAgcmVzdWx0LnkgPSAwOwogICAgICAgIHJlc3VsdC56ID0gcG9zaXRpb24ueiAqICgxIC0gc3F1YXJlZFhPdmVyU3F1YXJlZFopOwogICAgICAgIGlmIChNYXRoLmFicyhyZXN1bHQueikgPj0gdGhpcy5fcmFkaWkueiAtIGJ1ZmZlcikgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NyYXRjaEVuZHBvaW50ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBFbGxpcHNvaWQucHJvdG90eXBlLmdldExvY2FsQ3VydmF0dXJlID0gZnVuY3Rpb24oc3VyZmFjZVBvc2l0aW9uLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInN1cmZhY2VQb3NpdGlvbiIsIHN1cmZhY2VQb3NpdGlvbik7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICBjb25zdCBwcmltZVZlcnRpY2FsRW5kcG9pbnQgPSB0aGlzLmdldFN1cmZhY2VOb3JtYWxJbnRlcnNlY3Rpb25XaXRoWkF4aXMoCiAgICAgICAgICBzdXJmYWNlUG9zaXRpb24sCiAgICAgICAgICAwLAogICAgICAgICAgc2NyYXRjaEVuZHBvaW50CiAgICAgICAgKTsKICAgICAgICBjb25zdCBwcmltZVZlcnRpY2FsUmFkaXVzID0gQ2FydGVzaWFuM19kZWZhdWx0LmRpc3RhbmNlKAogICAgICAgICAgc3VyZmFjZVBvc2l0aW9uLAogICAgICAgICAgcHJpbWVWZXJ0aWNhbEVuZHBvaW50CiAgICAgICAgKTsKICAgICAgICBjb25zdCByYWRpdXNSYXRpbyA9IHRoaXMubWluaW11bVJhZGl1cyAqIHByaW1lVmVydGljYWxSYWRpdXMgLyB0aGlzLm1heGltdW1SYWRpdXMgKiogMjsKICAgICAgICBjb25zdCBtZXJpZGlvbmFsUmFkaXVzID0gcHJpbWVWZXJ0aWNhbFJhZGl1cyAqIHJhZGl1c1JhdGlvICoqIDI7CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHMoCiAgICAgICAgICAxIC8gcHJpbWVWZXJ0aWNhbFJhZGl1cywKICAgICAgICAgIDEgLyBtZXJpZGlvbmFsUmFkaXVzLAogICAgICAgICAgcmVzdWx0CiAgICAgICAgKTsKICAgICAgfTsKICAgICAgYWJzY2lzc2FzID0gWwogICAgICAgIDAuMTQ4ODc0MzM4OTgxNjMsCiAgICAgICAgMC40MzMzOTUzOTQxMjkyNSwKICAgICAgICAwLjY3OTQwOTU2ODI5OTAyLAogICAgICAgIDAuODY1MDYzMzY2Njg4OTgsCiAgICAgICAgMC45NzM5MDY1Mjg1MTcxNywKICAgICAgICAwCiAgICAgIF07CiAgICAgIHdlaWdodHMgPSBbCiAgICAgICAgMC4yOTU1MjQyMjQ3MTQ3NSwKICAgICAgICAwLjI2OTI2NjcxOTMwOTk5LAogICAgICAgIDAuMjE5MDg2MzYyNTE1OTgsCiAgICAgICAgMC4xNDk0NTEzNDkxNTA1OCwKICAgICAgICAwLjA2NjY3MTM0NDMwODY4NCwKICAgICAgICAwCiAgICAgIF07CiAgICAgIEVsbGlwc29pZC5wcm90b3R5cGUuc3VyZmFjZUFyZWEgPSBmdW5jdGlvbihyZWN0YW5nbGUpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlY3RhbmdsZSIsIHJlY3RhbmdsZSk7CiAgICAgICAgY29uc3QgbWluTG9uZ2l0dWRlID0gcmVjdGFuZ2xlLndlc3Q7CiAgICAgICAgbGV0IG1heExvbmdpdHVkZSA9IHJlY3RhbmdsZS5lYXN0OwogICAgICAgIGNvbnN0IG1pbkxhdGl0dWRlID0gcmVjdGFuZ2xlLnNvdXRoOwogICAgICAgIGNvbnN0IG1heExhdGl0dWRlID0gcmVjdGFuZ2xlLm5vcnRoOwogICAgICAgIHdoaWxlIChtYXhMb25naXR1ZGUgPCBtaW5Mb25naXR1ZGUpIHsKICAgICAgICAgIG1heExvbmdpdHVkZSArPSBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgICAgIH0KICAgICAgICBjb25zdCByYWRpaVNxdWFyZWQgPSB0aGlzLl9yYWRpaVNxdWFyZWQ7CiAgICAgICAgY29uc3QgYTIyID0gcmFkaWlTcXVhcmVkLng7CiAgICAgICAgY29uc3QgYjIgPSByYWRpaVNxdWFyZWQueTsKICAgICAgICBjb25zdCBjMiA9IHJhZGlpU3F1YXJlZC56OwogICAgICAgIGNvbnN0IGEyYjIgPSBhMjIgKiBiMjsKICAgICAgICByZXR1cm4gZ2F1c3NMZWdlbmRyZVF1YWRyYXR1cmUobWluTGF0aXR1ZGUsIG1heExhdGl0dWRlLCBmdW5jdGlvbihsYXQpIHsKICAgICAgICAgIGNvbnN0IHNpblBoaSA9IE1hdGguY29zKGxhdCk7CiAgICAgICAgICBjb25zdCBjb3NQaGkgPSBNYXRoLnNpbihsYXQpOwogICAgICAgICAgcmV0dXJuIE1hdGguY29zKGxhdCkgKiBnYXVzc0xlZ2VuZHJlUXVhZHJhdHVyZShtaW5Mb25naXR1ZGUsIG1heExvbmdpdHVkZSwgZnVuY3Rpb24obG9uKSB7CiAgICAgICAgICAgIGNvbnN0IGNvc1RoZXRhID0gTWF0aC5jb3MobG9uKTsKICAgICAgICAgICAgY29uc3Qgc2luVGhldGEgPSBNYXRoLnNpbihsb24pOwogICAgICAgICAgICByZXR1cm4gTWF0aC5zcXJ0KAogICAgICAgICAgICAgIGEyYjIgKiBjb3NQaGkgKiBjb3NQaGkgKyBjMiAqIChiMiAqIGNvc1RoZXRhICogY29zVGhldGEgKyBhMjIgKiBzaW5UaGV0YSAqIHNpblRoZXRhKSAqIHNpblBoaSAqIHNpblBoaQogICAgICAgICAgICApOwogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZF9kZWZhdWx0ID0gRWxsaXBzb2lkOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvR2VvZ3JhcGhpY1Byb2plY3Rpb24uanMKICBmdW5jdGlvbiBHZW9ncmFwaGljUHJvamVjdGlvbihlbGxpcHNvaWQpIHsKICAgIHRoaXMuX2VsbGlwc29pZCA9IGVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgdGhpcy5fc2VtaW1ham9yQXhpcyA9IHRoaXMuX2VsbGlwc29pZC5tYXhpbXVtUmFkaXVzOwogICAgdGhpcy5fb25lT3ZlclNlbWltYWpvckF4aXMgPSAxIC8gdGhpcy5fc2VtaW1ham9yQXhpczsKICB9CiAgdmFyIEdlb2dyYXBoaWNQcm9qZWN0aW9uX2RlZmF1bHQ7CiAgdmFyIGluaXRfR2VvZ3JhcGhpY1Byb2plY3Rpb24gPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dlb2dyYXBoaWNQcm9qZWN0aW9uLmpzIigpIHsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKEdlb2dyYXBoaWNQcm9qZWN0aW9uLnByb3RvdHlwZSwgewogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIHtAbGluayBFbGxpcHNvaWR9LgogICAgICAgICAqCiAgICAgICAgICogQG1lbWJlcm9mIEdlb2dyYXBoaWNQcm9qZWN0aW9uLnByb3RvdHlwZQogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge0VsbGlwc29pZH0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBlbGxpcHNvaWQ6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9lbGxpcHNvaWQ7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgR2VvZ3JhcGhpY1Byb2plY3Rpb24ucHJvdG90eXBlLnByb2plY3QgPSBmdW5jdGlvbihjYXJ0b2dyYXBoaWMyLCByZXN1bHQpIHsKICAgICAgICBjb25zdCBzZW1pbWFqb3JBeGlzID0gdGhpcy5fc2VtaW1ham9yQXhpczsKICAgICAgICBjb25zdCB4ID0gY2FydG9ncmFwaGljMi5sb25naXR1ZGUgKiBzZW1pbWFqb3JBeGlzOwogICAgICAgIGNvbnN0IHkgPSBjYXJ0b2dyYXBoaWMyLmxhdGl0dWRlICogc2VtaW1ham9yQXhpczsKICAgICAgICBjb25zdCB6ID0gY2FydG9ncmFwaGljMi5oZWlnaHQ7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoeCwgeSwgeik7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC54ID0geDsKICAgICAgICByZXN1bHQueSA9IHk7CiAgICAgICAgcmVzdWx0LnogPSB6OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEdlb2dyYXBoaWNQcm9qZWN0aW9uLnByb3RvdHlwZS51bnByb2plY3QgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoY2FydGVzaWFuMTEpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiY2FydGVzaWFuIGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG9uZU92ZXJFYXJ0aFNlbWltYWpvckF4aXMgPSB0aGlzLl9vbmVPdmVyU2VtaW1ham9yQXhpczsKICAgICAgICBjb25zdCBsb25naXR1ZGUgPSBjYXJ0ZXNpYW4xMS54ICogb25lT3ZlckVhcnRoU2VtaW1ham9yQXhpczsKICAgICAgICBjb25zdCBsYXRpdHVkZSA9IGNhcnRlc2lhbjExLnkgKiBvbmVPdmVyRWFydGhTZW1pbWFqb3JBeGlzOwogICAgICAgIGNvbnN0IGhlaWdodCA9IGNhcnRlc2lhbjExLno7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdChsb25naXR1ZGUsIGxhdGl0dWRlLCBoZWlnaHQpOwogICAgICAgIH0KICAgICAgICByZXN1bHQubG9uZ2l0dWRlID0gbG9uZ2l0dWRlOwogICAgICAgIHJlc3VsdC5sYXRpdHVkZSA9IGxhdGl0dWRlOwogICAgICAgIHJlc3VsdC5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgR2VvZ3JhcGhpY1Byb2plY3Rpb25fZGVmYXVsdCA9IEdlb2dyYXBoaWNQcm9qZWN0aW9uOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvSW50ZXJzZWN0LmpzCiAgdmFyIEludGVyc2VjdCwgSW50ZXJzZWN0X2RlZmF1bHQ7CiAgdmFyIGluaXRfSW50ZXJzZWN0ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9JbnRlcnNlY3QuanMiKCkgewogICAgICBJbnRlcnNlY3QgPSB7CiAgICAgICAgLyoqCiAgICAgICAgICogUmVwcmVzZW50cyB0aGF0IGFuIG9iamVjdCBpcyBub3QgY29udGFpbmVkIHdpdGhpbiB0aGUgZnJ1c3R1bS4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgT1VUU0lERTogLTEsCiAgICAgICAgLyoqCiAgICAgICAgICogUmVwcmVzZW50cyB0aGF0IGFuIG9iamVjdCBpbnRlcnNlY3RzIG9uZSBvZiB0aGUgZnJ1c3R1bSdzIHBsYW5lcy4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgSU5URVJTRUNUSU5HOiAwLAogICAgICAgIC8qKgogICAgICAgICAqIFJlcHJlc2VudHMgdGhhdCBhbiBvYmplY3QgaXMgZnVsbHkgd2l0aGluIHRoZSBmcnVzdHVtLgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBJTlNJREU6IDEKICAgICAgfTsKICAgICAgSW50ZXJzZWN0X2RlZmF1bHQgPSBPYmplY3QuZnJlZXplKEludGVyc2VjdCk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9JbnRlcnZhbC5qcwogIGZ1bmN0aW9uIEludGVydmFsKHN0YXJ0LCBzdG9wKSB7CiAgICB0aGlzLnN0YXJ0ID0gc3RhcnQgPz8gMDsKICAgIHRoaXMuc3RvcCA9IHN0b3AgPz8gMDsKICB9CiAgdmFyIEludGVydmFsX2RlZmF1bHQ7CiAgdmFyIGluaXRfSW50ZXJ2YWwgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0ludGVydmFsLmpzIigpIHsKICAgICAgSW50ZXJ2YWxfZGVmYXVsdCA9IEludGVydmFsOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvTWF0cml4My5qcwogIGZ1bmN0aW9uIE1hdHJpeDMoY29sdW1uMFJvdzAsIGNvbHVtbjFSb3cwLCBjb2x1bW4yUm93MCwgY29sdW1uMFJvdzEsIGNvbHVtbjFSb3cxLCBjb2x1bW4yUm93MSwgY29sdW1uMFJvdzIsIGNvbHVtbjFSb3cyLCBjb2x1bW4yUm93MikgewogICAgdGhpc1swXSA9IGNvbHVtbjBSb3cwID8/IDA7CiAgICB0aGlzWzFdID0gY29sdW1uMFJvdzEgPz8gMDsKICAgIHRoaXNbMl0gPSBjb2x1bW4wUm93MiA/PyAwOwogICAgdGhpc1szXSA9IGNvbHVtbjFSb3cwID8/IDA7CiAgICB0aGlzWzRdID0gY29sdW1uMVJvdzEgPz8gMDsKICAgIHRoaXNbNV0gPSBjb2x1bW4xUm93MiA/PyAwOwogICAgdGhpc1s2XSA9IGNvbHVtbjJSb3cwID8/IDA7CiAgICB0aGlzWzddID0gY29sdW1uMlJvdzEgPz8gMDsKICAgIHRoaXNbOF0gPSBjb2x1bW4yUm93MiA/PyAwOwogIH0KICBmdW5jdGlvbiBjb21wdXRlRnJvYmVuaXVzTm9ybShtYXRyaXgpIHsKICAgIGxldCBub3JtID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgOTsgKytpKSB7CiAgICAgIGNvbnN0IHRlbXAgPSBtYXRyaXhbaV07CiAgICAgIG5vcm0gKz0gdGVtcCAqIHRlbXA7CiAgICB9CiAgICByZXR1cm4gTWF0aC5zcXJ0KG5vcm0pOwogIH0KICBmdW5jdGlvbiBvZmZEaWFnb25hbEZyb2Jlbml1c05vcm0obWF0cml4KSB7CiAgICBsZXQgbm9ybSA9IDA7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7ICsraSkgewogICAgICBjb25zdCB0ZW1wID0gbWF0cml4W01hdHJpeDMuZ2V0RWxlbWVudEluZGV4KGNvbFZhbFtpXSwgcm93VmFsW2ldKV07CiAgICAgIG5vcm0gKz0gMiAqIHRlbXAgKiB0ZW1wOwogICAgfQogICAgcmV0dXJuIE1hdGguc3FydChub3JtKTsKICB9CiAgZnVuY3Rpb24gc2h1ckRlY29tcG9zaXRpb24obWF0cml4LCByZXN1bHQpIHsKICAgIGNvbnN0IHRvbGVyYW5jZSA9IE1hdGhfZGVmYXVsdC5FUFNJTE9OMTU7CiAgICBsZXQgbWF4RGlhZ29uYWwgPSAwOwogICAgbGV0IHJvdEF4aXMyID0gMTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMzsgKytpKSB7CiAgICAgIGNvbnN0IHRlbXAgPSBNYXRoLmFicygKICAgICAgICBtYXRyaXhbTWF0cml4My5nZXRFbGVtZW50SW5kZXgoY29sVmFsW2ldLCByb3dWYWxbaV0pXQogICAgICApOwogICAgICBpZiAodGVtcCA+IG1heERpYWdvbmFsKSB7CiAgICAgICAgcm90QXhpczIgPSBpOwogICAgICAgIG1heERpYWdvbmFsID0gdGVtcDsKICAgICAgfQogICAgfQogICAgbGV0IGMgPSAxOwogICAgbGV0IHMgPSAwOwogICAgY29uc3QgcCA9IHJvd1ZhbFtyb3RBeGlzMl07CiAgICBjb25zdCBxID0gY29sVmFsW3JvdEF4aXMyXTsKICAgIGlmIChNYXRoLmFicyhtYXRyaXhbTWF0cml4My5nZXRFbGVtZW50SW5kZXgocSwgcCldKSA+IHRvbGVyYW5jZSkgewogICAgICBjb25zdCBxcSA9IG1hdHJpeFtNYXRyaXgzLmdldEVsZW1lbnRJbmRleChxLCBxKV07CiAgICAgIGNvbnN0IHBwID0gbWF0cml4W01hdHJpeDMuZ2V0RWxlbWVudEluZGV4KHAsIHApXTsKICAgICAgY29uc3QgcXAgPSBtYXRyaXhbTWF0cml4My5nZXRFbGVtZW50SW5kZXgocSwgcCldOwogICAgICBjb25zdCB0YXUgPSAocXEgLSBwcCkgLyAyIC8gcXA7CiAgICAgIGxldCB0OwogICAgICBpZiAodGF1IDwgMCkgewogICAgICAgIHQgPSAtMSAvICgtdGF1ICsgTWF0aC5zcXJ0KDEgKyB0YXUgKiB0YXUpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0ID0gMSAvICh0YXUgKyBNYXRoLnNxcnQoMSArIHRhdSAqIHRhdSkpOwogICAgICB9CiAgICAgIGMgPSAxIC8gTWF0aC5zcXJ0KDEgKyB0ICogdCk7CiAgICAgIHMgPSB0ICogYzsKICAgIH0KICAgIHJlc3VsdCA9IE1hdHJpeDMuY2xvbmUoTWF0cml4My5JREVOVElUWSwgcmVzdWx0KTsKICAgIHJlc3VsdFtNYXRyaXgzLmdldEVsZW1lbnRJbmRleChwLCBwKV0gPSByZXN1bHRbTWF0cml4My5nZXRFbGVtZW50SW5kZXgocSwgcSldID0gYzsKICAgIHJlc3VsdFtNYXRyaXgzLmdldEVsZW1lbnRJbmRleChxLCBwKV0gPSBzOwogICAgcmVzdWx0W01hdHJpeDMuZ2V0RWxlbWVudEluZGV4KHAsIHEpXSA9IC1zOwogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgdmFyIHNjYWxlU2NyYXRjaDEsIHNjYWxlU2NyYXRjaDIsIHNjcmF0Y2hDb2x1bW4sIHNjYWxlU2NyYXRjaDMsIHNjYWxlU2NyYXRjaDQsIHNjYWxlU2NyYXRjaDUsIHJvd1ZhbCwgY29sVmFsLCBqTWF0cml4LCBqTWF0cml4VHJhbnNwb3NlLCBzY3JhdGNoVHJhbnNwb3NlTWF0cml4LCBNYXRyaXgzX2RlZmF1bHQ7CiAgdmFyIGluaXRfTWF0cml4MyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvTWF0cml4My5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBNYXRyaXgzLnBhY2tlZExlbmd0aCA9IDk7CiAgICAgIE1hdHJpeDMucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZVswXTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWVbMV07CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlWzJdOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZVszXTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWVbNF07CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlWzVdOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZVs2XTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWVbN107CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlWzhdOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgTWF0cml4My51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBNYXRyaXgzKCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0WzFdID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbMl0gPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdFszXSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0WzRdID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbNV0gPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdFs2XSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0WzddID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbOF0gPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDMucGFja0FycmF5ID0gZnVuY3Rpb24oYXJyYXksIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gYXJyYXkubGVuZ3RoOwogICAgICAgIGNvbnN0IHJlc3VsdExlbmd0aCA9IGxlbmd0aCAqIDk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEFycmF5KHJlc3VsdExlbmd0aCk7CiAgICAgICAgfSBlbHNlIGlmICghQXJyYXkuaXNBcnJheShyZXN1bHQpICYmIHJlc3VsdC5sZW5ndGggIT09IHJlc3VsdExlbmd0aCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJJZiByZXN1bHQgaXMgYSB0eXBlZCBhcnJheSwgaXQgbXVzdCBoYXZlIGV4YWN0bHkgYXJyYXkubGVuZ3RoICogOSBlbGVtZW50cyIKICAgICAgICAgICk7CiAgICAgICAgfSBlbHNlIGlmIChyZXN1bHQubGVuZ3RoICE9PSByZXN1bHRMZW5ndGgpIHsKICAgICAgICAgIHJlc3VsdC5sZW5ndGggPSByZXN1bHRMZW5ndGg7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgIE1hdHJpeDMucGFjayhhcnJheVtpXSwgcmVzdWx0LCBpICogOSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDMudW5wYWNrQXJyYXkgPSBmdW5jdGlvbihhcnJheSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygiYXJyYXkubGVuZ3RoIiwgYXJyYXkubGVuZ3RoLCA5KTsKICAgICAgICBpZiAoYXJyYXkubGVuZ3RoICUgOSAhPT0gMCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGxlbmd0aCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgOS4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbGVuZ3RoID0gYXJyYXkubGVuZ3RoOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBBcnJheShsZW5ndGggLyA5KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzdWx0Lmxlbmd0aCA9IGxlbmd0aCAvIDk7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDkpIHsKICAgICAgICAgIGNvbnN0IGluZGV4ID0gaSAvIDk7CiAgICAgICAgICByZXN1bHRbaW5kZXhdID0gTWF0cml4My51bnBhY2soYXJyYXksIGksIHJlc3VsdFtpbmRleF0pOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgzLmNsb25lID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChtYXRyaXgpKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IE1hdHJpeDMoCiAgICAgICAgICAgIG1hdHJpeFswXSwKICAgICAgICAgICAgbWF0cml4WzNdLAogICAgICAgICAgICBtYXRyaXhbNl0sCiAgICAgICAgICAgIG1hdHJpeFsxXSwKICAgICAgICAgICAgbWF0cml4WzRdLAogICAgICAgICAgICBtYXRyaXhbN10sCiAgICAgICAgICAgIG1hdHJpeFsyXSwKICAgICAgICAgICAgbWF0cml4WzVdLAogICAgICAgICAgICBtYXRyaXhbOF0KICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IG1hdHJpeFswXTsKICAgICAgICByZXN1bHRbMV0gPSBtYXRyaXhbMV07CiAgICAgICAgcmVzdWx0WzJdID0gbWF0cml4WzJdOwogICAgICAgIHJlc3VsdFszXSA9IG1hdHJpeFszXTsKICAgICAgICByZXN1bHRbNF0gPSBtYXRyaXhbNF07CiAgICAgICAgcmVzdWx0WzVdID0gbWF0cml4WzVdOwogICAgICAgIHJlc3VsdFs2XSA9IG1hdHJpeFs2XTsKICAgICAgICByZXN1bHRbN10gPSBtYXRyaXhbN107CiAgICAgICAgcmVzdWx0WzhdID0gbWF0cml4WzhdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDMuZnJvbUFycmF5ID0gTWF0cml4My51bnBhY2s7CiAgICAgIE1hdHJpeDMuZnJvbUNvbHVtbk1ham9yQXJyYXkgPSBmdW5jdGlvbih2YWx1ZXMsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgidmFsdWVzIiwgdmFsdWVzKTsKICAgICAgICByZXR1cm4gTWF0cml4My5jbG9uZSh2YWx1ZXMsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIE1hdHJpeDMuZnJvbVJvd01ham9yQXJyYXkgPSBmdW5jdGlvbih2YWx1ZXMsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgidmFsdWVzIiwgdmFsdWVzKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IE1hdHJpeDMoCiAgICAgICAgICAgIHZhbHVlc1swXSwKICAgICAgICAgICAgdmFsdWVzWzFdLAogICAgICAgICAgICB2YWx1ZXNbMl0sCiAgICAgICAgICAgIHZhbHVlc1szXSwKICAgICAgICAgICAgdmFsdWVzWzRdLAogICAgICAgICAgICB2YWx1ZXNbNV0sCiAgICAgICAgICAgIHZhbHVlc1s2XSwKICAgICAgICAgICAgdmFsdWVzWzddLAogICAgICAgICAgICB2YWx1ZXNbOF0KICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IHZhbHVlc1swXTsKICAgICAgICByZXN1bHRbMV0gPSB2YWx1ZXNbM107CiAgICAgICAgcmVzdWx0WzJdID0gdmFsdWVzWzZdOwogICAgICAgIHJlc3VsdFszXSA9IHZhbHVlc1sxXTsKICAgICAgICByZXN1bHRbNF0gPSB2YWx1ZXNbNF07CiAgICAgICAgcmVzdWx0WzVdID0gdmFsdWVzWzddOwogICAgICAgIHJlc3VsdFs2XSA9IHZhbHVlc1syXTsKICAgICAgICByZXN1bHRbN10gPSB2YWx1ZXNbNV07CiAgICAgICAgcmVzdWx0WzhdID0gdmFsdWVzWzhdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDMuZnJvbVF1YXRlcm5pb24gPSBmdW5jdGlvbihxdWF0ZXJuaW9uLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInF1YXRlcm5pb24iLCBxdWF0ZXJuaW9uKTsKICAgICAgICBjb25zdCB4MiA9IHF1YXRlcm5pb24ueCAqIHF1YXRlcm5pb24ueDsKICAgICAgICBjb25zdCB4eSA9IHF1YXRlcm5pb24ueCAqIHF1YXRlcm5pb24ueTsKICAgICAgICBjb25zdCB4eiA9IHF1YXRlcm5pb24ueCAqIHF1YXRlcm5pb24uejsKICAgICAgICBjb25zdCB4dyA9IHF1YXRlcm5pb24ueCAqIHF1YXRlcm5pb24udzsKICAgICAgICBjb25zdCB5MiA9IHF1YXRlcm5pb24ueSAqIHF1YXRlcm5pb24ueTsKICAgICAgICBjb25zdCB5eiA9IHF1YXRlcm5pb24ueSAqIHF1YXRlcm5pb24uejsKICAgICAgICBjb25zdCB5dyA9IHF1YXRlcm5pb24ueSAqIHF1YXRlcm5pb24udzsKICAgICAgICBjb25zdCB6MiA9IHF1YXRlcm5pb24ueiAqIHF1YXRlcm5pb24uejsKICAgICAgICBjb25zdCB6dyA9IHF1YXRlcm5pb24ueiAqIHF1YXRlcm5pb24udzsKICAgICAgICBjb25zdCB3MiA9IHF1YXRlcm5pb24udyAqIHF1YXRlcm5pb24udzsKICAgICAgICBjb25zdCBtMDAgPSB4MiAtIHkyIC0gejIgKyB3MjsKICAgICAgICBjb25zdCBtMDEgPSAyICogKHh5IC0gencpOwogICAgICAgIGNvbnN0IG0wMiA9IDIgKiAoeHogKyB5dyk7CiAgICAgICAgY29uc3QgbTEwID0gMiAqICh4eSArIHp3KTsKICAgICAgICBjb25zdCBtMTEgPSAteDIgKyB5MiAtIHoyICsgdzI7CiAgICAgICAgY29uc3QgbTEyID0gMiAqICh5eiAtIHh3KTsKICAgICAgICBjb25zdCBtMjAgPSAyICogKHh6IC0geXcpOwogICAgICAgIGNvbnN0IG0yMSA9IDIgKiAoeXogKyB4dyk7CiAgICAgICAgY29uc3QgbTIyID0gLXgyIC0geTIgKyB6MiArIHcyOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgTWF0cml4MyhtMDAsIG0wMSwgbTAyLCBtMTAsIG0xMSwgbTEyLCBtMjAsIG0yMSwgbTIyKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gbTAwOwogICAgICAgIHJlc3VsdFsxXSA9IG0xMDsKICAgICAgICByZXN1bHRbMl0gPSBtMjA7CiAgICAgICAgcmVzdWx0WzNdID0gbTAxOwogICAgICAgIHJlc3VsdFs0XSA9IG0xMTsKICAgICAgICByZXN1bHRbNV0gPSBtMjE7CiAgICAgICAgcmVzdWx0WzZdID0gbTAyOwogICAgICAgIHJlc3VsdFs3XSA9IG0xMjsKICAgICAgICByZXN1bHRbOF0gPSBtMjI7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4My5mcm9tSGVhZGluZ1BpdGNoUm9sbCA9IGZ1bmN0aW9uKGhlYWRpbmdQaXRjaFJvbGwsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiaGVhZGluZ1BpdGNoUm9sbCIsIGhlYWRpbmdQaXRjaFJvbGwpOwogICAgICAgIGNvbnN0IGNvc1RoZXRhID0gTWF0aC5jb3MoLWhlYWRpbmdQaXRjaFJvbGwucGl0Y2gpOwogICAgICAgIGNvbnN0IGNvc1BzaSA9IE1hdGguY29zKC1oZWFkaW5nUGl0Y2hSb2xsLmhlYWRpbmcpOwogICAgICAgIGNvbnN0IGNvc1BoaSA9IE1hdGguY29zKGhlYWRpbmdQaXRjaFJvbGwucm9sbCk7CiAgICAgICAgY29uc3Qgc2luVGhldGEgPSBNYXRoLnNpbigtaGVhZGluZ1BpdGNoUm9sbC5waXRjaCk7CiAgICAgICAgY29uc3Qgc2luUHNpID0gTWF0aC5zaW4oLWhlYWRpbmdQaXRjaFJvbGwuaGVhZGluZyk7CiAgICAgICAgY29uc3Qgc2luUGhpID0gTWF0aC5zaW4oaGVhZGluZ1BpdGNoUm9sbC5yb2xsKTsKICAgICAgICBjb25zdCBtMDAgPSBjb3NUaGV0YSAqIGNvc1BzaTsKICAgICAgICBjb25zdCBtMDEgPSAtY29zUGhpICogc2luUHNpICsgc2luUGhpICogc2luVGhldGEgKiBjb3NQc2k7CiAgICAgICAgY29uc3QgbTAyID0gc2luUGhpICogc2luUHNpICsgY29zUGhpICogc2luVGhldGEgKiBjb3NQc2k7CiAgICAgICAgY29uc3QgbTEwID0gY29zVGhldGEgKiBzaW5Qc2k7CiAgICAgICAgY29uc3QgbTExID0gY29zUGhpICogY29zUHNpICsgc2luUGhpICogc2luVGhldGEgKiBzaW5Qc2k7CiAgICAgICAgY29uc3QgbTEyID0gLXNpblBoaSAqIGNvc1BzaSArIGNvc1BoaSAqIHNpblRoZXRhICogc2luUHNpOwogICAgICAgIGNvbnN0IG0yMCA9IC1zaW5UaGV0YTsKICAgICAgICBjb25zdCBtMjEgPSBzaW5QaGkgKiBjb3NUaGV0YTsKICAgICAgICBjb25zdCBtMjIgPSBjb3NQaGkgKiBjb3NUaGV0YTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IE1hdHJpeDMobTAwLCBtMDEsIG0wMiwgbTEwLCBtMTEsIG0xMiwgbTIwLCBtMjEsIG0yMik7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IG0wMDsKICAgICAgICByZXN1bHRbMV0gPSBtMTA7CiAgICAgICAgcmVzdWx0WzJdID0gbTIwOwogICAgICAgIHJlc3VsdFszXSA9IG0wMTsKICAgICAgICByZXN1bHRbNF0gPSBtMTE7CiAgICAgICAgcmVzdWx0WzVdID0gbTIxOwogICAgICAgIHJlc3VsdFs2XSA9IG0wMjsKICAgICAgICByZXN1bHRbN10gPSBtMTI7CiAgICAgICAgcmVzdWx0WzhdID0gbTIyOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDMuZnJvbVNjYWxlID0gZnVuY3Rpb24oc2NhbGUsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic2NhbGUiLCBzY2FsZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBNYXRyaXgzKHNjYWxlLngsIDAsIDAsIDAsIHNjYWxlLnksIDAsIDAsIDAsIHNjYWxlLnopOwogICAgICAgIH0KICAgICAgICByZXN1bHRbMF0gPSBzY2FsZS54OwogICAgICAgIHJlc3VsdFsxXSA9IDA7CiAgICAgICAgcmVzdWx0WzJdID0gMDsKICAgICAgICByZXN1bHRbM10gPSAwOwogICAgICAgIHJlc3VsdFs0XSA9IHNjYWxlLnk7CiAgICAgICAgcmVzdWx0WzVdID0gMDsKICAgICAgICByZXN1bHRbNl0gPSAwOwogICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgcmVzdWx0WzhdID0gc2NhbGUuejsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgzLmZyb21Vbmlmb3JtU2NhbGUgPSBmdW5jdGlvbihzY2FsZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJzY2FsZSIsIHNjYWxlKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IE1hdHJpeDMoc2NhbGUsIDAsIDAsIDAsIHNjYWxlLCAwLCAwLCAwLCBzY2FsZSk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IHNjYWxlOwogICAgICAgIHJlc3VsdFsxXSA9IDA7CiAgICAgICAgcmVzdWx0WzJdID0gMDsKICAgICAgICByZXN1bHRbM10gPSAwOwogICAgICAgIHJlc3VsdFs0XSA9IHNjYWxlOwogICAgICAgIHJlc3VsdFs1XSA9IDA7CiAgICAgICAgcmVzdWx0WzZdID0gMDsKICAgICAgICByZXN1bHRbN10gPSAwOwogICAgICAgIHJlc3VsdFs4XSA9IHNjYWxlOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDMuZnJvbUNyb3NzUHJvZHVjdCA9IGZ1bmN0aW9uKHZlY3RvciwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJ2ZWN0b3IiLCB2ZWN0b3IpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgTWF0cml4MygKICAgICAgICAgICAgMCwKICAgICAgICAgICAgLXZlY3Rvci56LAogICAgICAgICAgICB2ZWN0b3IueSwKICAgICAgICAgICAgdmVjdG9yLnosCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIC12ZWN0b3IueCwKICAgICAgICAgICAgLXZlY3Rvci55LAogICAgICAgICAgICB2ZWN0b3IueCwKICAgICAgICAgICAgMAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gMDsKICAgICAgICByZXN1bHRbMV0gPSB2ZWN0b3IuejsKICAgICAgICByZXN1bHRbMl0gPSAtdmVjdG9yLnk7CiAgICAgICAgcmVzdWx0WzNdID0gLXZlY3Rvci56OwogICAgICAgIHJlc3VsdFs0XSA9IDA7CiAgICAgICAgcmVzdWx0WzVdID0gdmVjdG9yLng7CiAgICAgICAgcmVzdWx0WzZdID0gdmVjdG9yLnk7CiAgICAgICAgcmVzdWx0WzddID0gLXZlY3Rvci54OwogICAgICAgIHJlc3VsdFs4XSA9IDA7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4My5mcm9tUm90YXRpb25YID0gZnVuY3Rpb24oYW5nbGUsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigiYW5nbGUiLCBhbmdsZSk7CiAgICAgICAgY29uc3QgY29zQW5nbGUgPSBNYXRoLmNvcyhhbmdsZSk7CiAgICAgICAgY29uc3Qgc2luQW5nbGUgPSBNYXRoLnNpbihhbmdsZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBNYXRyaXgzKAogICAgICAgICAgICAxLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICBjb3NBbmdsZSwKICAgICAgICAgICAgLXNpbkFuZ2xlLAogICAgICAgICAgICAwLAogICAgICAgICAgICBzaW5BbmdsZSwKICAgICAgICAgICAgY29zQW5nbGUKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IDE7CiAgICAgICAgcmVzdWx0WzFdID0gMDsKICAgICAgICByZXN1bHRbMl0gPSAwOwogICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgcmVzdWx0WzRdID0gY29zQW5nbGU7CiAgICAgICAgcmVzdWx0WzVdID0gc2luQW5nbGU7CiAgICAgICAgcmVzdWx0WzZdID0gMDsKICAgICAgICByZXN1bHRbN10gPSAtc2luQW5nbGU7CiAgICAgICAgcmVzdWx0WzhdID0gY29zQW5nbGU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4My5mcm9tUm90YXRpb25ZID0gZnVuY3Rpb24oYW5nbGUsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigiYW5nbGUiLCBhbmdsZSk7CiAgICAgICAgY29uc3QgY29zQW5nbGUgPSBNYXRoLmNvcyhhbmdsZSk7CiAgICAgICAgY29uc3Qgc2luQW5nbGUgPSBNYXRoLnNpbihhbmdsZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBNYXRyaXgzKAogICAgICAgICAgICBjb3NBbmdsZSwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgc2luQW5nbGUsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIDEsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIC1zaW5BbmdsZSwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgY29zQW5nbGUKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IGNvc0FuZ2xlOwogICAgICAgIHJlc3VsdFsxXSA9IDA7CiAgICAgICAgcmVzdWx0WzJdID0gLXNpbkFuZ2xlOwogICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgcmVzdWx0WzRdID0gMTsKICAgICAgICByZXN1bHRbNV0gPSAwOwogICAgICAgIHJlc3VsdFs2XSA9IHNpbkFuZ2xlOwogICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgcmVzdWx0WzhdID0gY29zQW5nbGU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4My5mcm9tUm90YXRpb25aID0gZnVuY3Rpb24oYW5nbGUsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigiYW5nbGUiLCBhbmdsZSk7CiAgICAgICAgY29uc3QgY29zQW5nbGUgPSBNYXRoLmNvcyhhbmdsZSk7CiAgICAgICAgY29uc3Qgc2luQW5nbGUgPSBNYXRoLnNpbihhbmdsZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBNYXRyaXgzKAogICAgICAgICAgICBjb3NBbmdsZSwKICAgICAgICAgICAgLXNpbkFuZ2xlLAogICAgICAgICAgICAwLAogICAgICAgICAgICBzaW5BbmdsZSwKICAgICAgICAgICAgY29zQW5nbGUsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIDEKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IGNvc0FuZ2xlOwogICAgICAgIHJlc3VsdFsxXSA9IHNpbkFuZ2xlOwogICAgICAgIHJlc3VsdFsyXSA9IDA7CiAgICAgICAgcmVzdWx0WzNdID0gLXNpbkFuZ2xlOwogICAgICAgIHJlc3VsdFs0XSA9IGNvc0FuZ2xlOwogICAgICAgIHJlc3VsdFs1XSA9IDA7CiAgICAgICAgcmVzdWx0WzZdID0gMDsKICAgICAgICByZXN1bHRbN10gPSAwOwogICAgICAgIHJlc3VsdFs4XSA9IDE7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4My50b0FycmF5ID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIFsKICAgICAgICAgICAgbWF0cml4WzBdLAogICAgICAgICAgICBtYXRyaXhbMV0sCiAgICAgICAgICAgIG1hdHJpeFsyXSwKICAgICAgICAgICAgbWF0cml4WzNdLAogICAgICAgICAgICBtYXRyaXhbNF0sCiAgICAgICAgICAgIG1hdHJpeFs1XSwKICAgICAgICAgICAgbWF0cml4WzZdLAogICAgICAgICAgICBtYXRyaXhbN10sCiAgICAgICAgICAgIG1hdHJpeFs4XQogICAgICAgICAgXTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4WzBdOwogICAgICAgIHJlc3VsdFsxXSA9IG1hdHJpeFsxXTsKICAgICAgICByZXN1bHRbMl0gPSBtYXRyaXhbMl07CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzNdOwogICAgICAgIHJlc3VsdFs0XSA9IG1hdHJpeFs0XTsKICAgICAgICByZXN1bHRbNV0gPSBtYXRyaXhbNV07CiAgICAgICAgcmVzdWx0WzZdID0gbWF0cml4WzZdOwogICAgICAgIHJlc3VsdFs3XSA9IG1hdHJpeFs3XTsKICAgICAgICByZXN1bHRbOF0gPSBtYXRyaXhbOF07CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4My5nZXRFbGVtZW50SW5kZXggPSBmdW5jdGlvbihjb2x1bW4sIHJvdykgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJyb3ciLCByb3csIDApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5sZXNzVGhhbk9yRXF1YWxzKCJyb3ciLCByb3csIDIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJjb2x1bW4iLCBjb2x1bW4sIDApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5sZXNzVGhhbk9yRXF1YWxzKCJjb2x1bW4iLCBjb2x1bW4sIDIpOwogICAgICAgIHJldHVybiBjb2x1bW4gKiAzICsgcm93OwogICAgICB9OwogICAgICBNYXRyaXgzLmdldENvbHVtbiA9IGZ1bmN0aW9uKG1hdHJpeCwgaW5kZXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygiaW5kZXgiLCBpbmRleCwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoImluZGV4IiwgaW5kZXgsIDIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBzdGFydEluZGV4ID0gaW5kZXggKiAzOwogICAgICAgIGNvbnN0IHggPSBtYXRyaXhbc3RhcnRJbmRleF07CiAgICAgICAgY29uc3QgeSA9IG1hdHJpeFtzdGFydEluZGV4ICsgMV07CiAgICAgICAgY29uc3QgeiA9IG1hdHJpeFtzdGFydEluZGV4ICsgMl07CiAgICAgICAgcmVzdWx0LnggPSB4OwogICAgICAgIHJlc3VsdC55ID0geTsKICAgICAgICByZXN1bHQueiA9IHo7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4My5zZXRDb2x1bW4gPSBmdW5jdGlvbihtYXRyaXgsIGluZGV4LCBjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJpbmRleCIsIGluZGV4LCAwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygiaW5kZXgiLCBpbmRleCwgMik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdCA9IE1hdHJpeDMuY2xvbmUobWF0cml4LCByZXN1bHQpOwogICAgICAgIGNvbnN0IHN0YXJ0SW5kZXggPSBpbmRleCAqIDM7CiAgICAgICAgcmVzdWx0W3N0YXJ0SW5kZXhdID0gY2FydGVzaWFuMTEueDsKICAgICAgICByZXN1bHRbc3RhcnRJbmRleCArIDFdID0gY2FydGVzaWFuMTEueTsKICAgICAgICByZXN1bHRbc3RhcnRJbmRleCArIDJdID0gY2FydGVzaWFuMTEuejsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgzLmdldFJvdyA9IGZ1bmN0aW9uKG1hdHJpeCwgaW5kZXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygiaW5kZXgiLCBpbmRleCwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoImluZGV4IiwgaW5kZXgsIDIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCB4ID0gbWF0cml4W2luZGV4XTsKICAgICAgICBjb25zdCB5ID0gbWF0cml4W2luZGV4ICsgM107CiAgICAgICAgY29uc3QgeiA9IG1hdHJpeFtpbmRleCArIDZdOwogICAgICAgIHJlc3VsdC54ID0geDsKICAgICAgICByZXN1bHQueSA9IHk7CiAgICAgICAgcmVzdWx0LnogPSB6OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDMuc2V0Um93ID0gZnVuY3Rpb24obWF0cml4LCBpbmRleCwgY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygiaW5kZXgiLCBpbmRleCwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoImluZGV4IiwgaW5kZXgsIDIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQgPSBNYXRyaXgzLmNsb25lKG1hdHJpeCwgcmVzdWx0KTsKICAgICAgICByZXN1bHRbaW5kZXhdID0gY2FydGVzaWFuMTEueDsKICAgICAgICByZXN1bHRbaW5kZXggKyAzXSA9IGNhcnRlc2lhbjExLnk7CiAgICAgICAgcmVzdWx0W2luZGV4ICsgNl0gPSBjYXJ0ZXNpYW4xMS56OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHNjYWxlU2NyYXRjaDEgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIE1hdHJpeDMuc2V0U2NhbGUgPSBmdW5jdGlvbihtYXRyaXgsIHNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzY2FsZSIsIHNjYWxlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgZXhpc3RpbmdTY2FsZSA9IE1hdHJpeDMuZ2V0U2NhbGUobWF0cml4LCBzY2FsZVNjcmF0Y2gxKTsKICAgICAgICBjb25zdCBzY2FsZVJhdGlvWCA9IHNjYWxlLnggLyBleGlzdGluZ1NjYWxlLng7CiAgICAgICAgY29uc3Qgc2NhbGVSYXRpb1kgPSBzY2FsZS55IC8gZXhpc3RpbmdTY2FsZS55OwogICAgICAgIGNvbnN0IHNjYWxlUmF0aW9aID0gc2NhbGUueiAvIGV4aXN0aW5nU2NhbGUuejsKICAgICAgICByZXN1bHRbMF0gPSBtYXRyaXhbMF0gKiBzY2FsZVJhdGlvWDsKICAgICAgICByZXN1bHRbMV0gPSBtYXRyaXhbMV0gKiBzY2FsZVJhdGlvWDsKICAgICAgICByZXN1bHRbMl0gPSBtYXRyaXhbMl0gKiBzY2FsZVJhdGlvWDsKICAgICAgICByZXN1bHRbM10gPSBtYXRyaXhbM10gKiBzY2FsZVJhdGlvWTsKICAgICAgICByZXN1bHRbNF0gPSBtYXRyaXhbNF0gKiBzY2FsZVJhdGlvWTsKICAgICAgICByZXN1bHRbNV0gPSBtYXRyaXhbNV0gKiBzY2FsZVJhdGlvWTsKICAgICAgICByZXN1bHRbNl0gPSBtYXRyaXhbNl0gKiBzY2FsZVJhdGlvWjsKICAgICAgICByZXN1bHRbN10gPSBtYXRyaXhbN10gKiBzY2FsZVJhdGlvWjsKICAgICAgICByZXN1bHRbOF0gPSBtYXRyaXhbOF0gKiBzY2FsZVJhdGlvWjsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBzY2FsZVNjcmF0Y2gyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBNYXRyaXgzLnNldFVuaWZvcm1TY2FsZSA9IGZ1bmN0aW9uKG1hdHJpeCwgc2NhbGUsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInNjYWxlIiwgc2NhbGUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBleGlzdGluZ1NjYWxlID0gTWF0cml4My5nZXRTY2FsZShtYXRyaXgsIHNjYWxlU2NyYXRjaDIpOwogICAgICAgIGNvbnN0IHNjYWxlUmF0aW9YID0gc2NhbGUgLyBleGlzdGluZ1NjYWxlLng7CiAgICAgICAgY29uc3Qgc2NhbGVSYXRpb1kgPSBzY2FsZSAvIGV4aXN0aW5nU2NhbGUueTsKICAgICAgICBjb25zdCBzY2FsZVJhdGlvWiA9IHNjYWxlIC8gZXhpc3RpbmdTY2FsZS56OwogICAgICAgIHJlc3VsdFswXSA9IG1hdHJpeFswXSAqIHNjYWxlUmF0aW9YOwogICAgICAgIHJlc3VsdFsxXSA9IG1hdHJpeFsxXSAqIHNjYWxlUmF0aW9YOwogICAgICAgIHJlc3VsdFsyXSA9IG1hdHJpeFsyXSAqIHNjYWxlUmF0aW9YOwogICAgICAgIHJlc3VsdFszXSA9IG1hdHJpeFszXSAqIHNjYWxlUmF0aW9ZOwogICAgICAgIHJlc3VsdFs0XSA9IG1hdHJpeFs0XSAqIHNjYWxlUmF0aW9ZOwogICAgICAgIHJlc3VsdFs1XSA9IG1hdHJpeFs1XSAqIHNjYWxlUmF0aW9ZOwogICAgICAgIHJlc3VsdFs2XSA9IG1hdHJpeFs2XSAqIHNjYWxlUmF0aW9aOwogICAgICAgIHJlc3VsdFs3XSA9IG1hdHJpeFs3XSAqIHNjYWxlUmF0aW9aOwogICAgICAgIHJlc3VsdFs4XSA9IG1hdHJpeFs4XSAqIHNjYWxlUmF0aW9aOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hDb2x1bW4gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIE1hdHJpeDMuZ2V0U2NhbGUgPSBmdW5jdGlvbihtYXRyaXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21FbGVtZW50cyhtYXRyaXhbMF0sIG1hdHJpeFsxXSwgbWF0cml4WzJdLCBzY3JhdGNoQ29sdW1uKQogICAgICAgICk7CiAgICAgICAgcmVzdWx0LnkgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21FbGVtZW50cyhtYXRyaXhbM10sIG1hdHJpeFs0XSwgbWF0cml4WzVdLCBzY3JhdGNoQ29sdW1uKQogICAgICAgICk7CiAgICAgICAgcmVzdWx0LnogPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21FbGVtZW50cyhtYXRyaXhbNl0sIG1hdHJpeFs3XSwgbWF0cml4WzhdLCBzY3JhdGNoQ29sdW1uKQogICAgICAgICk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NhbGVTY3JhdGNoMyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgTWF0cml4My5nZXRNYXhpbXVtU2NhbGUgPSBmdW5jdGlvbihtYXRyaXgpIHsKICAgICAgICBNYXRyaXgzLmdldFNjYWxlKG1hdHJpeCwgc2NhbGVTY3JhdGNoMyk7CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjNfZGVmYXVsdC5tYXhpbXVtQ29tcG9uZW50KHNjYWxlU2NyYXRjaDMpOwogICAgICB9OwogICAgICBzY2FsZVNjcmF0Y2g0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBNYXRyaXgzLnNldFJvdGF0aW9uID0gZnVuY3Rpb24obWF0cml4LCByb3RhdGlvbiwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBzY2FsZSA9IE1hdHJpeDMuZ2V0U2NhbGUobWF0cml4LCBzY2FsZVNjcmF0Y2g0KTsKICAgICAgICByZXN1bHRbMF0gPSByb3RhdGlvblswXSAqIHNjYWxlLng7CiAgICAgICAgcmVzdWx0WzFdID0gcm90YXRpb25bMV0gKiBzY2FsZS54OwogICAgICAgIHJlc3VsdFsyXSA9IHJvdGF0aW9uWzJdICogc2NhbGUueDsKICAgICAgICByZXN1bHRbM10gPSByb3RhdGlvblszXSAqIHNjYWxlLnk7CiAgICAgICAgcmVzdWx0WzRdID0gcm90YXRpb25bNF0gKiBzY2FsZS55OwogICAgICAgIHJlc3VsdFs1XSA9IHJvdGF0aW9uWzVdICogc2NhbGUueTsKICAgICAgICByZXN1bHRbNl0gPSByb3RhdGlvbls2XSAqIHNjYWxlLno7CiAgICAgICAgcmVzdWx0WzddID0gcm90YXRpb25bN10gKiBzY2FsZS56OwogICAgICAgIHJlc3VsdFs4XSA9IHJvdGF0aW9uWzhdICogc2NhbGUuejsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBzY2FsZVNjcmF0Y2g1ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBNYXRyaXgzLmdldFJvdGF0aW9uID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHNjYWxlID0gTWF0cml4My5nZXRTY2FsZShtYXRyaXgsIHNjYWxlU2NyYXRjaDUpOwogICAgICAgIHJlc3VsdFswXSA9IG1hdHJpeFswXSAvIHNjYWxlLng7CiAgICAgICAgcmVzdWx0WzFdID0gbWF0cml4WzFdIC8gc2NhbGUueDsKICAgICAgICByZXN1bHRbMl0gPSBtYXRyaXhbMl0gLyBzY2FsZS54OwogICAgICAgIHJlc3VsdFszXSA9IG1hdHJpeFszXSAvIHNjYWxlLnk7CiAgICAgICAgcmVzdWx0WzRdID0gbWF0cml4WzRdIC8gc2NhbGUueTsKICAgICAgICByZXN1bHRbNV0gPSBtYXRyaXhbNV0gLyBzY2FsZS55OwogICAgICAgIHJlc3VsdFs2XSA9IG1hdHJpeFs2XSAvIHNjYWxlLno7CiAgICAgICAgcmVzdWx0WzddID0gbWF0cml4WzddIC8gc2NhbGUuejsKICAgICAgICByZXN1bHRbOF0gPSBtYXRyaXhbOF0gLyBzY2FsZS56OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDMubXVsdGlwbHkgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzAgPSBsZWZ0WzBdICogcmlnaHRbMF0gKyBsZWZ0WzNdICogcmlnaHRbMV0gKyBsZWZ0WzZdICogcmlnaHRbMl07CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzEgPSBsZWZ0WzFdICogcmlnaHRbMF0gKyBsZWZ0WzRdICogcmlnaHRbMV0gKyBsZWZ0WzddICogcmlnaHRbMl07CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzIgPSBsZWZ0WzJdICogcmlnaHRbMF0gKyBsZWZ0WzVdICogcmlnaHRbMV0gKyBsZWZ0WzhdICogcmlnaHRbMl07CiAgICAgICAgY29uc3QgY29sdW1uMVJvdzAgPSBsZWZ0WzBdICogcmlnaHRbM10gKyBsZWZ0WzNdICogcmlnaHRbNF0gKyBsZWZ0WzZdICogcmlnaHRbNV07CiAgICAgICAgY29uc3QgY29sdW1uMVJvdzEgPSBsZWZ0WzFdICogcmlnaHRbM10gKyBsZWZ0WzRdICogcmlnaHRbNF0gKyBsZWZ0WzddICogcmlnaHRbNV07CiAgICAgICAgY29uc3QgY29sdW1uMVJvdzIgPSBsZWZ0WzJdICogcmlnaHRbM10gKyBsZWZ0WzVdICogcmlnaHRbNF0gKyBsZWZ0WzhdICogcmlnaHRbNV07CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzAgPSBsZWZ0WzBdICogcmlnaHRbNl0gKyBsZWZ0WzNdICogcmlnaHRbN10gKyBsZWZ0WzZdICogcmlnaHRbOF07CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzEgPSBsZWZ0WzFdICogcmlnaHRbNl0gKyBsZWZ0WzRdICogcmlnaHRbN10gKyBsZWZ0WzddICogcmlnaHRbOF07CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzIgPSBsZWZ0WzJdICogcmlnaHRbNl0gKyBsZWZ0WzVdICogcmlnaHRbN10gKyBsZWZ0WzhdICogcmlnaHRbOF07CiAgICAgICAgcmVzdWx0WzBdID0gY29sdW1uMFJvdzA7CiAgICAgICAgcmVzdWx0WzFdID0gY29sdW1uMFJvdzE7CiAgICAgICAgcmVzdWx0WzJdID0gY29sdW1uMFJvdzI7CiAgICAgICAgcmVzdWx0WzNdID0gY29sdW1uMVJvdzA7CiAgICAgICAgcmVzdWx0WzRdID0gY29sdW1uMVJvdzE7CiAgICAgICAgcmVzdWx0WzVdID0gY29sdW1uMVJvdzI7CiAgICAgICAgcmVzdWx0WzZdID0gY29sdW1uMlJvdzA7CiAgICAgICAgcmVzdWx0WzddID0gY29sdW1uMlJvdzE7CiAgICAgICAgcmVzdWx0WzhdID0gY29sdW1uMlJvdzI7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4My5hZGQgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0WzBdID0gbGVmdFswXSArIHJpZ2h0WzBdOwogICAgICAgIHJlc3VsdFsxXSA9IGxlZnRbMV0gKyByaWdodFsxXTsKICAgICAgICByZXN1bHRbMl0gPSBsZWZ0WzJdICsgcmlnaHRbMl07CiAgICAgICAgcmVzdWx0WzNdID0gbGVmdFszXSArIHJpZ2h0WzNdOwogICAgICAgIHJlc3VsdFs0XSA9IGxlZnRbNF0gKyByaWdodFs0XTsKICAgICAgICByZXN1bHRbNV0gPSBsZWZ0WzVdICsgcmlnaHRbNV07CiAgICAgICAgcmVzdWx0WzZdID0gbGVmdFs2XSArIHJpZ2h0WzZdOwogICAgICAgIHJlc3VsdFs3XSA9IGxlZnRbN10gKyByaWdodFs3XTsKICAgICAgICByZXN1bHRbOF0gPSBsZWZ0WzhdICsgcmlnaHRbOF07CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4My5zdWJ0cmFjdCA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImxlZnQiLCBsZWZ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJpZ2h0IiwgcmlnaHQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHRbMF0gPSBsZWZ0WzBdIC0gcmlnaHRbMF07CiAgICAgICAgcmVzdWx0WzFdID0gbGVmdFsxXSAtIHJpZ2h0WzFdOwogICAgICAgIHJlc3VsdFsyXSA9IGxlZnRbMl0gLSByaWdodFsyXTsKICAgICAgICByZXN1bHRbM10gPSBsZWZ0WzNdIC0gcmlnaHRbM107CiAgICAgICAgcmVzdWx0WzRdID0gbGVmdFs0XSAtIHJpZ2h0WzRdOwogICAgICAgIHJlc3VsdFs1XSA9IGxlZnRbNV0gLSByaWdodFs1XTsKICAgICAgICByZXN1bHRbNl0gPSBsZWZ0WzZdIC0gcmlnaHRbNl07CiAgICAgICAgcmVzdWx0WzddID0gbGVmdFs3XSAtIHJpZ2h0WzddOwogICAgICAgIHJlc3VsdFs4XSA9IGxlZnRbOF0gLSByaWdodFs4XTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgzLm11bHRpcGx5QnlWZWN0b3IgPSBmdW5jdGlvbihtYXRyaXgsIGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHZYID0gY2FydGVzaWFuMTEueDsKICAgICAgICBjb25zdCB2WSA9IGNhcnRlc2lhbjExLnk7CiAgICAgICAgY29uc3QgdlogPSBjYXJ0ZXNpYW4xMS56OwogICAgICAgIGNvbnN0IHggPSBtYXRyaXhbMF0gKiB2WCArIG1hdHJpeFszXSAqIHZZICsgbWF0cml4WzZdICogdlo7CiAgICAgICAgY29uc3QgeSA9IG1hdHJpeFsxXSAqIHZYICsgbWF0cml4WzRdICogdlkgKyBtYXRyaXhbN10gKiB2WjsKICAgICAgICBjb25zdCB6ID0gbWF0cml4WzJdICogdlggKyBtYXRyaXhbNV0gKiB2WSArIG1hdHJpeFs4XSAqIHZaOwogICAgICAgIHJlc3VsdC54ID0geDsKICAgICAgICByZXN1bHQueSA9IHk7CiAgICAgICAgcmVzdWx0LnogPSB6OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDMubXVsdGlwbHlCeVNjYWxhciA9IGZ1bmN0aW9uKG1hdHJpeCwgc2NhbGFyLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJzY2FsYXIiLCBzY2FsYXIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHRbMF0gPSBtYXRyaXhbMF0gKiBzY2FsYXI7CiAgICAgICAgcmVzdWx0WzFdID0gbWF0cml4WzFdICogc2NhbGFyOwogICAgICAgIHJlc3VsdFsyXSA9IG1hdHJpeFsyXSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbM10gPSBtYXRyaXhbM10gKiBzY2FsYXI7CiAgICAgICAgcmVzdWx0WzRdID0gbWF0cml4WzRdICogc2NhbGFyOwogICAgICAgIHJlc3VsdFs1XSA9IG1hdHJpeFs1XSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbNl0gPSBtYXRyaXhbNl0gKiBzY2FsYXI7CiAgICAgICAgcmVzdWx0WzddID0gbWF0cml4WzddICogc2NhbGFyOwogICAgICAgIHJlc3VsdFs4XSA9IG1hdHJpeFs4XSAqIHNjYWxhcjsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgzLm11bHRpcGx5QnlTY2FsZSA9IGZ1bmN0aW9uKG1hdHJpeCwgc2NhbGUsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInNjYWxlIiwgc2NhbGUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHRbMF0gPSBtYXRyaXhbMF0gKiBzY2FsZS54OwogICAgICAgIHJlc3VsdFsxXSA9IG1hdHJpeFsxXSAqIHNjYWxlLng7CiAgICAgICAgcmVzdWx0WzJdID0gbWF0cml4WzJdICogc2NhbGUueDsKICAgICAgICByZXN1bHRbM10gPSBtYXRyaXhbM10gKiBzY2FsZS55OwogICAgICAgIHJlc3VsdFs0XSA9IG1hdHJpeFs0XSAqIHNjYWxlLnk7CiAgICAgICAgcmVzdWx0WzVdID0gbWF0cml4WzVdICogc2NhbGUueTsKICAgICAgICByZXN1bHRbNl0gPSBtYXRyaXhbNl0gKiBzY2FsZS56OwogICAgICAgIHJlc3VsdFs3XSA9IG1hdHJpeFs3XSAqIHNjYWxlLno7CiAgICAgICAgcmVzdWx0WzhdID0gbWF0cml4WzhdICogc2NhbGUuejsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgzLm11bHRpcGx5QnlVbmlmb3JtU2NhbGUgPSBmdW5jdGlvbihtYXRyaXgsIHNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJzY2FsZSIsIHNjYWxlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4WzBdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzFdID0gbWF0cml4WzFdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzJdID0gbWF0cml4WzJdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzNdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzRdID0gbWF0cml4WzRdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzVdID0gbWF0cml4WzVdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzZdID0gbWF0cml4WzZdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzddID0gbWF0cml4WzddICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzhdID0gbWF0cml4WzhdICogc2NhbGU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4My5uZWdhdGUgPSBmdW5jdGlvbihtYXRyaXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0WzBdID0gLW1hdHJpeFswXTsKICAgICAgICByZXN1bHRbMV0gPSAtbWF0cml4WzFdOwogICAgICAgIHJlc3VsdFsyXSA9IC1tYXRyaXhbMl07CiAgICAgICAgcmVzdWx0WzNdID0gLW1hdHJpeFszXTsKICAgICAgICByZXN1bHRbNF0gPSAtbWF0cml4WzRdOwogICAgICAgIHJlc3VsdFs1XSA9IC1tYXRyaXhbNV07CiAgICAgICAgcmVzdWx0WzZdID0gLW1hdHJpeFs2XTsKICAgICAgICByZXN1bHRbN10gPSAtbWF0cml4WzddOwogICAgICAgIHJlc3VsdFs4XSA9IC1tYXRyaXhbOF07CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4My50cmFuc3Bvc2UgPSBmdW5jdGlvbihtYXRyaXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzAgPSBtYXRyaXhbMF07CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzEgPSBtYXRyaXhbM107CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzIgPSBtYXRyaXhbNl07CiAgICAgICAgY29uc3QgY29sdW1uMVJvdzAgPSBtYXRyaXhbMV07CiAgICAgICAgY29uc3QgY29sdW1uMVJvdzEgPSBtYXRyaXhbNF07CiAgICAgICAgY29uc3QgY29sdW1uMVJvdzIgPSBtYXRyaXhbN107CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzAgPSBtYXRyaXhbMl07CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzEgPSBtYXRyaXhbNV07CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzIgPSBtYXRyaXhbOF07CiAgICAgICAgcmVzdWx0WzBdID0gY29sdW1uMFJvdzA7CiAgICAgICAgcmVzdWx0WzFdID0gY29sdW1uMFJvdzE7CiAgICAgICAgcmVzdWx0WzJdID0gY29sdW1uMFJvdzI7CiAgICAgICAgcmVzdWx0WzNdID0gY29sdW1uMVJvdzA7CiAgICAgICAgcmVzdWx0WzRdID0gY29sdW1uMVJvdzE7CiAgICAgICAgcmVzdWx0WzVdID0gY29sdW1uMVJvdzI7CiAgICAgICAgcmVzdWx0WzZdID0gY29sdW1uMlJvdzA7CiAgICAgICAgcmVzdWx0WzddID0gY29sdW1uMlJvdzE7CiAgICAgICAgcmVzdWx0WzhdID0gY29sdW1uMlJvdzI7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgcm93VmFsID0gWzEsIDAsIDBdOwogICAgICBjb2xWYWwgPSBbMiwgMiwgMV07CiAgICAgIGpNYXRyaXggPSBuZXcgTWF0cml4MygpOwogICAgICBqTWF0cml4VHJhbnNwb3NlID0gbmV3IE1hdHJpeDMoKTsKICAgICAgTWF0cml4My5jb21wdXRlRWlnZW5EZWNvbXBvc2l0aW9uID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgY29uc3QgdG9sZXJhbmNlID0gTWF0aF9kZWZhdWx0LkVQU0lMT04yMDsKICAgICAgICBjb25zdCBtYXhTd2VlcHMgPSAxMDsKICAgICAgICBsZXQgY291bnQgPSAwOwogICAgICAgIGxldCBzd2VlcCA9IDA7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0ge307CiAgICAgICAgfQogICAgICAgIGNvbnN0IHVuaXRhcnlNYXRyaXggPSByZXN1bHQudW5pdGFyeSA9IE1hdHJpeDMuY2xvbmUoCiAgICAgICAgICBNYXRyaXgzLklERU5USVRZLAogICAgICAgICAgcmVzdWx0LnVuaXRhcnkKICAgICAgICApOwogICAgICAgIGNvbnN0IGRpYWdNYXRyaXggPSByZXN1bHQuZGlhZ29uYWwgPSBNYXRyaXgzLmNsb25lKG1hdHJpeCwgcmVzdWx0LmRpYWdvbmFsKTsKICAgICAgICBjb25zdCBlcHNpbG9uID0gdG9sZXJhbmNlICogY29tcHV0ZUZyb2Jlbml1c05vcm0oZGlhZ01hdHJpeCk7CiAgICAgICAgd2hpbGUgKHN3ZWVwIDwgbWF4U3dlZXBzICYmIG9mZkRpYWdvbmFsRnJvYmVuaXVzTm9ybShkaWFnTWF0cml4KSA+IGVwc2lsb24pIHsKICAgICAgICAgIHNodXJEZWNvbXBvc2l0aW9uKGRpYWdNYXRyaXgsIGpNYXRyaXgpOwogICAgICAgICAgTWF0cml4My50cmFuc3Bvc2Uoak1hdHJpeCwgak1hdHJpeFRyYW5zcG9zZSk7CiAgICAgICAgICBNYXRyaXgzLm11bHRpcGx5KGRpYWdNYXRyaXgsIGpNYXRyaXgsIGRpYWdNYXRyaXgpOwogICAgICAgICAgTWF0cml4My5tdWx0aXBseShqTWF0cml4VHJhbnNwb3NlLCBkaWFnTWF0cml4LCBkaWFnTWF0cml4KTsKICAgICAgICAgIE1hdHJpeDMubXVsdGlwbHkodW5pdGFyeU1hdHJpeCwgak1hdHJpeCwgdW5pdGFyeU1hdHJpeCk7CiAgICAgICAgICBpZiAoKytjb3VudCA+IDIpIHsKICAgICAgICAgICAgKytzd2VlcDsKICAgICAgICAgICAgY291bnQgPSAwOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgzLmFicyA9IGZ1bmN0aW9uKG1hdHJpeCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHRbMF0gPSBNYXRoLmFicyhtYXRyaXhbMF0pOwogICAgICAgIHJlc3VsdFsxXSA9IE1hdGguYWJzKG1hdHJpeFsxXSk7CiAgICAgICAgcmVzdWx0WzJdID0gTWF0aC5hYnMobWF0cml4WzJdKTsKICAgICAgICByZXN1bHRbM10gPSBNYXRoLmFicyhtYXRyaXhbM10pOwogICAgICAgIHJlc3VsdFs0XSA9IE1hdGguYWJzKG1hdHJpeFs0XSk7CiAgICAgICAgcmVzdWx0WzVdID0gTWF0aC5hYnMobWF0cml4WzVdKTsKICAgICAgICByZXN1bHRbNl0gPSBNYXRoLmFicyhtYXRyaXhbNl0pOwogICAgICAgIHJlc3VsdFs3XSA9IE1hdGguYWJzKG1hdHJpeFs3XSk7CiAgICAgICAgcmVzdWx0WzhdID0gTWF0aC5hYnMobWF0cml4WzhdKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgzLmRldGVybWluYW50ID0gZnVuY3Rpb24obWF0cml4KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIGNvbnN0IG0xMSA9IG1hdHJpeFswXTsKICAgICAgICBjb25zdCBtMjEgPSBtYXRyaXhbM107CiAgICAgICAgY29uc3QgbTMxID0gbWF0cml4WzZdOwogICAgICAgIGNvbnN0IG0xMiA9IG1hdHJpeFsxXTsKICAgICAgICBjb25zdCBtMjIgPSBtYXRyaXhbNF07CiAgICAgICAgY29uc3QgbTMyID0gbWF0cml4WzddOwogICAgICAgIGNvbnN0IG0xMyA9IG1hdHJpeFsyXTsKICAgICAgICBjb25zdCBtMjMgPSBtYXRyaXhbNV07CiAgICAgICAgY29uc3QgbTMzID0gbWF0cml4WzhdOwogICAgICAgIHJldHVybiBtMTEgKiAobTIyICogbTMzIC0gbTIzICogbTMyKSArIG0xMiAqIChtMjMgKiBtMzEgLSBtMjEgKiBtMzMpICsgbTEzICogKG0yMSAqIG0zMiAtIG0yMiAqIG0zMSk7CiAgICAgIH07CiAgICAgIE1hdHJpeDMuaW52ZXJzZSA9IGZ1bmN0aW9uKG1hdHJpeCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBtMTEgPSBtYXRyaXhbMF07CiAgICAgICAgY29uc3QgbTIxID0gbWF0cml4WzFdOwogICAgICAgIGNvbnN0IG0zMSA9IG1hdHJpeFsyXTsKICAgICAgICBjb25zdCBtMTIgPSBtYXRyaXhbM107CiAgICAgICAgY29uc3QgbTIyID0gbWF0cml4WzRdOwogICAgICAgIGNvbnN0IG0zMiA9IG1hdHJpeFs1XTsKICAgICAgICBjb25zdCBtMTMgPSBtYXRyaXhbNl07CiAgICAgICAgY29uc3QgbTIzID0gbWF0cml4WzddOwogICAgICAgIGNvbnN0IG0zMyA9IG1hdHJpeFs4XTsKICAgICAgICBjb25zdCBkZXRlcm1pbmFudCA9IE1hdHJpeDMuZGV0ZXJtaW5hbnQobWF0cml4KTsKICAgICAgICBpZiAoTWF0aC5hYnMoZGV0ZXJtaW5hbnQpIDw9IE1hdGhfZGVmYXVsdC5FUFNJTE9OMTUpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJtYXRyaXggaXMgbm90IGludmVydGlibGUiKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gbTIyICogbTMzIC0gbTIzICogbTMyOwogICAgICAgIHJlc3VsdFsxXSA9IG0yMyAqIG0zMSAtIG0yMSAqIG0zMzsKICAgICAgICByZXN1bHRbMl0gPSBtMjEgKiBtMzIgLSBtMjIgKiBtMzE7CiAgICAgICAgcmVzdWx0WzNdID0gbTEzICogbTMyIC0gbTEyICogbTMzOwogICAgICAgIHJlc3VsdFs0XSA9IG0xMSAqIG0zMyAtIG0xMyAqIG0zMTsKICAgICAgICByZXN1bHRbNV0gPSBtMTIgKiBtMzEgLSBtMTEgKiBtMzI7CiAgICAgICAgcmVzdWx0WzZdID0gbTEyICogbTIzIC0gbTEzICogbTIyOwogICAgICAgIHJlc3VsdFs3XSA9IG0xMyAqIG0yMSAtIG0xMSAqIG0yMzsKICAgICAgICByZXN1bHRbOF0gPSBtMTEgKiBtMjIgLSBtMTIgKiBtMjE7CiAgICAgICAgY29uc3Qgc2NhbGUgPSAxIC8gZGV0ZXJtaW5hbnQ7CiAgICAgICAgcmV0dXJuIE1hdHJpeDMubXVsdGlwbHlCeVNjYWxhcihyZXN1bHQsIHNjYWxlLCByZXN1bHQpOwogICAgICB9OwogICAgICBzY3JhdGNoVHJhbnNwb3NlTWF0cml4ID0gbmV3IE1hdHJpeDMoKTsKICAgICAgTWF0cml4My5pbnZlcnNlVHJhbnNwb3NlID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJldHVybiBNYXRyaXgzLmludmVyc2UoCiAgICAgICAgICBNYXRyaXgzLnRyYW5zcG9zZShtYXRyaXgsIHNjcmF0Y2hUcmFuc3Bvc2VNYXRyaXgpLAogICAgICAgICAgcmVzdWx0CiAgICAgICAgKTsKICAgICAgfTsKICAgICAgTWF0cml4My5lcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiBsZWZ0WzBdID09PSByaWdodFswXSAmJiBsZWZ0WzFdID09PSByaWdodFsxXSAmJiBsZWZ0WzJdID09PSByaWdodFsyXSAmJiBsZWZ0WzNdID09PSByaWdodFszXSAmJiBsZWZ0WzRdID09PSByaWdodFs0XSAmJiBsZWZ0WzVdID09PSByaWdodFs1XSAmJiBsZWZ0WzZdID09PSByaWdodFs2XSAmJiBsZWZ0WzddID09PSByaWdodFs3XSAmJiBsZWZ0WzhdID09PSByaWdodFs4XTsKICAgICAgfTsKICAgICAgTWF0cml4My5lcXVhbHNFcHNpbG9uID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIGVwc2lsb24pIHsKICAgICAgICBlcHNpbG9uID0gZXBzaWxvbiA/PyAwOwogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiBNYXRoLmFicyhsZWZ0WzBdIC0gcmlnaHRbMF0pIDw9IGVwc2lsb24gJiYgTWF0aC5hYnMobGVmdFsxXSAtIHJpZ2h0WzFdKSA8PSBlcHNpbG9uICYmIE1hdGguYWJzKGxlZnRbMl0gLSByaWdodFsyXSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzNdIC0gcmlnaHRbM10pIDw9IGVwc2lsb24gJiYgTWF0aC5hYnMobGVmdFs0XSAtIHJpZ2h0WzRdKSA8PSBlcHNpbG9uICYmIE1hdGguYWJzKGxlZnRbNV0gLSByaWdodFs1XSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzZdIC0gcmlnaHRbNl0pIDw9IGVwc2lsb24gJiYgTWF0aC5hYnMobGVmdFs3XSAtIHJpZ2h0WzddKSA8PSBlcHNpbG9uICYmIE1hdGguYWJzKGxlZnRbOF0gLSByaWdodFs4XSkgPD0gZXBzaWxvbjsKICAgICAgfTsKICAgICAgTWF0cml4My5JREVOVElUWSA9IE9iamVjdC5mcmVlemUoCiAgICAgICAgbmV3IE1hdHJpeDMoMSwgMCwgMCwgMCwgMSwgMCwgMCwgMCwgMSkKICAgICAgKTsKICAgICAgTWF0cml4My5aRVJPID0gT2JqZWN0LmZyZWV6ZSgKICAgICAgICBuZXcgTWF0cml4MygwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwKQogICAgICApOwogICAgICBNYXRyaXgzLkNPTFVNTjBST1cwID0gMDsKICAgICAgTWF0cml4My5DT0xVTU4wUk9XMSA9IDE7CiAgICAgIE1hdHJpeDMuQ09MVU1OMFJPVzIgPSAyOwogICAgICBNYXRyaXgzLkNPTFVNTjFST1cwID0gMzsKICAgICAgTWF0cml4My5DT0xVTU4xUk9XMSA9IDQ7CiAgICAgIE1hdHJpeDMuQ09MVU1OMVJPVzIgPSA1OwogICAgICBNYXRyaXgzLkNPTFVNTjJST1cwID0gNjsKICAgICAgTWF0cml4My5DT0xVTU4yUk9XMSA9IDc7CiAgICAgIE1hdHJpeDMuQ09MVU1OMlJPVzIgPSA4OwogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhNYXRyaXgzLnByb3RvdHlwZSwgewogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIG51bWJlciBvZiBpdGVtcyBpbiB0aGUgY29sbGVjdGlvbi4KICAgICAgICAgKiBAbWVtYmVyb2YgTWF0cml4My5wcm90b3R5cGUKICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICovCiAgICAgICAgbGVuZ3RoOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gTWF0cml4My5wYWNrZWRMZW5ndGg7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgTWF0cml4My5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICByZXR1cm4gTWF0cml4My5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBNYXRyaXgzLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbihyaWdodCkgewogICAgICAgIHJldHVybiBNYXRyaXgzLmVxdWFscyh0aGlzLCByaWdodCk7CiAgICAgIH07CiAgICAgIE1hdHJpeDMuZXF1YWxzQXJyYXkgPSBmdW5jdGlvbihtYXRyaXgsIGFycmF5LCBvZmZzZXQpIHsKICAgICAgICByZXR1cm4gbWF0cml4WzBdID09PSBhcnJheVtvZmZzZXRdICYmIG1hdHJpeFsxXSA9PT0gYXJyYXlbb2Zmc2V0ICsgMV0gJiYgbWF0cml4WzJdID09PSBhcnJheVtvZmZzZXQgKyAyXSAmJiBtYXRyaXhbM10gPT09IGFycmF5W29mZnNldCArIDNdICYmIG1hdHJpeFs0XSA9PT0gYXJyYXlbb2Zmc2V0ICsgNF0gJiYgbWF0cml4WzVdID09PSBhcnJheVtvZmZzZXQgKyA1XSAmJiBtYXRyaXhbNl0gPT09IGFycmF5W29mZnNldCArIDZdICYmIG1hdHJpeFs3XSA9PT0gYXJyYXlbb2Zmc2V0ICsgN10gJiYgbWF0cml4WzhdID09PSBhcnJheVtvZmZzZXQgKyA4XTsKICAgICAgfTsKICAgICAgTWF0cml4My5wcm90b3R5cGUuZXF1YWxzRXBzaWxvbiA9IGZ1bmN0aW9uKHJpZ2h0LCBlcHNpbG9uKSB7CiAgICAgICAgcmV0dXJuIE1hdHJpeDMuZXF1YWxzRXBzaWxvbih0aGlzLCByaWdodCwgZXBzaWxvbik7CiAgICAgIH07CiAgICAgIE1hdHJpeDMucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIGAoJHt0aGlzWzBdfSwgJHt0aGlzWzNdfSwgJHt0aGlzWzZdfSkKKCR7dGhpc1sxXX0sICR7dGhpc1s0XX0sICR7dGhpc1s3XX0pCigke3RoaXNbMl19LCAke3RoaXNbNV19LCAke3RoaXNbOF19KWA7CiAgICAgIH07CiAgICAgIE1hdHJpeDNfZGVmYXVsdCA9IE1hdHJpeDM7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9DYXJ0ZXNpYW40LmpzCiAgZnVuY3Rpb24gQ2FydGVzaWFuNCh4LCB5LCB6LCB3KSB7CiAgICB0aGlzLnggPSB4ID8/IDA7CiAgICB0aGlzLnkgPSB5ID8/IDA7CiAgICB0aGlzLnogPSB6ID8/IDA7CiAgICB0aGlzLncgPSB3ID8/IDA7CiAgfQogIHZhciBkaXN0YW5jZVNjcmF0Y2gzLCBsZXJwU2NyYXRjaDMsIG1vc3RPcnRob2dvbmFsQXhpc1NjcmF0Y2gzLCBzY3JhdGNoRjMyQXJyYXksIHNjcmF0Y2hVOEFycmF5LCB0ZXN0VTMyLCB0ZXN0VTgsIGxpdHRsZUVuZGlhbiwgQ2FydGVzaWFuNF9kZWZhdWx0OwogIHZhciBpbml0X0NhcnRlc2lhbjQgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NhcnRlc2lhbjQuanMiKCkgewogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBDYXJ0ZXNpYW40LmZyb21FbGVtZW50cyA9IGZ1bmN0aW9uKHgsIHksIHosIHcsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgQ2FydGVzaWFuNCh4LCB5LCB6LCB3KTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnggPSB4OwogICAgICAgIHJlc3VsdC55ID0geTsKICAgICAgICByZXN1bHQueiA9IHo7CiAgICAgICAgcmVzdWx0LncgPSB3OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjQuZnJvbUNvbG9yID0gZnVuY3Rpb24oY29sb3IsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY29sb3IiLCBjb2xvcik7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBDYXJ0ZXNpYW40KGNvbG9yLnJlZCwgY29sb3IuZ3JlZW4sIGNvbG9yLmJsdWUsIGNvbG9yLmFscGhhKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnggPSBjb2xvci5yZWQ7CiAgICAgICAgcmVzdWx0LnkgPSBjb2xvci5ncmVlbjsKICAgICAgICByZXN1bHQueiA9IGNvbG9yLmJsdWU7CiAgICAgICAgcmVzdWx0LncgPSBjb2xvci5hbHBoYTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LmNsb25lID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGNhcnRlc2lhbjExKSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBDYXJ0ZXNpYW40KGNhcnRlc2lhbjExLngsIGNhcnRlc2lhbjExLnksIGNhcnRlc2lhbjExLnosIGNhcnRlc2lhbjExLncpOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IGNhcnRlc2lhbjExLng7CiAgICAgICAgcmVzdWx0LnkgPSBjYXJ0ZXNpYW4xMS55OwogICAgICAgIHJlc3VsdC56ID0gY2FydGVzaWFuMTEuejsKICAgICAgICByZXN1bHQudyA9IGNhcnRlc2lhbjExLnc7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuNC5wYWNrZWRMZW5ndGggPSA0OwogICAgICBDYXJ0ZXNpYW40LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUueDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUueTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuejsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLnc7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LnVucGFjayA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydGluZ0luZGV4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjQoKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnggPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdC55ID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHQueiA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LncgPSBhcnJheVtzdGFydGluZ0luZGV4XTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LnBhY2tBcnJheSA9IGZ1bmN0aW9uKGFycmF5LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IGFycmF5Lmxlbmd0aDsKICAgICAgICBjb25zdCByZXN1bHRMZW5ndGggPSBsZW5ndGggKiA0OwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBBcnJheShyZXN1bHRMZW5ndGgpOwogICAgICAgIH0gZWxzZSBpZiAoIUFycmF5LmlzQXJyYXkocmVzdWx0KSAmJiByZXN1bHQubGVuZ3RoICE9PSByZXN1bHRMZW5ndGgpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICAiSWYgcmVzdWx0IGlzIGEgdHlwZWQgYXJyYXksIGl0IG11c3QgaGF2ZSBleGFjdGx5IGFycmF5Lmxlbmd0aCAqIDQgZWxlbWVudHMiCiAgICAgICAgICApOwogICAgICAgIH0gZWxzZSBpZiAocmVzdWx0Lmxlbmd0aCAhPT0gcmVzdWx0TGVuZ3RoKSB7CiAgICAgICAgICByZXN1bHQubGVuZ3RoID0gcmVzdWx0TGVuZ3RoOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICBDYXJ0ZXNpYW40LnBhY2soYXJyYXlbaV0sIHJlc3VsdCwgaSAqIDQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LnVucGFja0FycmF5ID0gZnVuY3Rpb24oYXJyYXksIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoImFycmF5Lmxlbmd0aCIsIGFycmF5Lmxlbmd0aCwgNCk7CiAgICAgICAgaWYgKGFycmF5Lmxlbmd0aCAlIDQgIT09IDApIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhcnJheSBsZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGxlbmd0aCA9IGFycmF5Lmxlbmd0aDsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQXJyYXkobGVuZ3RoIC8gNCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5sZW5ndGggPSBsZW5ndGggLyA0OwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSA0KSB7CiAgICAgICAgICBjb25zdCBpbmRleCA9IGkgLyA0OwogICAgICAgICAgcmVzdWx0W2luZGV4XSA9IENhcnRlc2lhbjQudW5wYWNrKGFycmF5LCBpLCByZXN1bHRbaW5kZXhdKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuNC5mcm9tQXJyYXkgPSBDYXJ0ZXNpYW40LnVucGFjazsKICAgICAgQ2FydGVzaWFuNC5tYXhpbXVtQ29tcG9uZW50ID0gZnVuY3Rpb24oY2FydGVzaWFuMTEpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICByZXR1cm4gTWF0aC5tYXgoY2FydGVzaWFuMTEueCwgY2FydGVzaWFuMTEueSwgY2FydGVzaWFuMTEueiwgY2FydGVzaWFuMTEudyk7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjQubWluaW11bUNvbXBvbmVudCA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgcmV0dXJuIE1hdGgubWluKGNhcnRlc2lhbjExLngsIGNhcnRlc2lhbjExLnksIGNhcnRlc2lhbjExLnosIGNhcnRlc2lhbjExLncpOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40Lm1pbmltdW1CeUNvbXBvbmVudCA9IGZ1bmN0aW9uKGZpcnN0LCBzZWNvbmQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiZmlyc3QiLCBmaXJzdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzZWNvbmQiLCBzZWNvbmQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQueCA9IE1hdGgubWluKGZpcnN0LngsIHNlY29uZC54KTsKICAgICAgICByZXN1bHQueSA9IE1hdGgubWluKGZpcnN0LnksIHNlY29uZC55KTsKICAgICAgICByZXN1bHQueiA9IE1hdGgubWluKGZpcnN0LnosIHNlY29uZC56KTsKICAgICAgICByZXN1bHQudyA9IE1hdGgubWluKGZpcnN0LncsIHNlY29uZC53KTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40Lm1heGltdW1CeUNvbXBvbmVudCA9IGZ1bmN0aW9uKGZpcnN0LCBzZWNvbmQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiZmlyc3QiLCBmaXJzdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzZWNvbmQiLCBzZWNvbmQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQueCA9IE1hdGgubWF4KGZpcnN0LngsIHNlY29uZC54KTsKICAgICAgICByZXN1bHQueSA9IE1hdGgubWF4KGZpcnN0LnksIHNlY29uZC55KTsKICAgICAgICByZXN1bHQueiA9IE1hdGgubWF4KGZpcnN0LnosIHNlY29uZC56KTsKICAgICAgICByZXN1bHQudyA9IE1hdGgubWF4KGZpcnN0LncsIHNlY29uZC53KTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LmNsYW1wID0gZnVuY3Rpb24odmFsdWUsIG1pbjMsIG1heDMsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtaW4iLCBtaW4zKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1heCIsIG1heDMpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCB4ID0gTWF0aF9kZWZhdWx0LmNsYW1wKHZhbHVlLngsIG1pbjMueCwgbWF4My54KTsKICAgICAgICBjb25zdCB5ID0gTWF0aF9kZWZhdWx0LmNsYW1wKHZhbHVlLnksIG1pbjMueSwgbWF4My55KTsKICAgICAgICBjb25zdCB6ID0gTWF0aF9kZWZhdWx0LmNsYW1wKHZhbHVlLnosIG1pbjMueiwgbWF4My56KTsKICAgICAgICBjb25zdCB3ID0gTWF0aF9kZWZhdWx0LmNsYW1wKHZhbHVlLncsIG1pbjMudywgbWF4My53KTsKICAgICAgICByZXN1bHQueCA9IHg7CiAgICAgICAgcmVzdWx0LnkgPSB5OwogICAgICAgIHJlc3VsdC56ID0gejsKICAgICAgICByZXN1bHQudyA9IHc7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuNC5tYWduaXR1ZGVTcXVhcmVkID0gZnVuY3Rpb24oY2FydGVzaWFuMTEpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICByZXR1cm4gY2FydGVzaWFuMTEueCAqIGNhcnRlc2lhbjExLnggKyBjYXJ0ZXNpYW4xMS55ICogY2FydGVzaWFuMTEueSArIGNhcnRlc2lhbjExLnogKiBjYXJ0ZXNpYW4xMS56ICsgY2FydGVzaWFuMTEudyAqIGNhcnRlc2lhbjExLnc7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjQubWFnbml0dWRlID0gZnVuY3Rpb24oY2FydGVzaWFuMTEpIHsKICAgICAgICByZXR1cm4gTWF0aC5zcXJ0KENhcnRlc2lhbjQubWFnbml0dWRlU3F1YXJlZChjYXJ0ZXNpYW4xMSkpOwogICAgICB9OwogICAgICBkaXN0YW5jZVNjcmF0Y2gzID0gbmV3IENhcnRlc2lhbjQoKTsKICAgICAgQ2FydGVzaWFuNC5kaXN0YW5jZSA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDYXJ0ZXNpYW40LnN1YnRyYWN0KGxlZnQsIHJpZ2h0LCBkaXN0YW5jZVNjcmF0Y2gzKTsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuNC5tYWduaXR1ZGUoZGlzdGFuY2VTY3JhdGNoMyk7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjQuZGlzdGFuY2VTcXVhcmVkID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImxlZnQiLCBsZWZ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJpZ2h0IiwgcmlnaHQpOwogICAgICAgIENhcnRlc2lhbjQuc3VidHJhY3QobGVmdCwgcmlnaHQsIGRpc3RhbmNlU2NyYXRjaDMpOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW40Lm1hZ25pdHVkZVNxdWFyZWQoZGlzdGFuY2VTY3JhdGNoMyk7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjQubm9ybWFsaXplID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBtYWduaXR1ZGUgPSBDYXJ0ZXNpYW40Lm1hZ25pdHVkZShjYXJ0ZXNpYW4xMSk7CiAgICAgICAgcmVzdWx0LnggPSBjYXJ0ZXNpYW4xMS54IC8gbWFnbml0dWRlOwogICAgICAgIHJlc3VsdC55ID0gY2FydGVzaWFuMTEueSAvIG1hZ25pdHVkZTsKICAgICAgICByZXN1bHQueiA9IGNhcnRlc2lhbjExLnogLyBtYWduaXR1ZGU7CiAgICAgICAgcmVzdWx0LncgPSBjYXJ0ZXNpYW4xMS53IC8gbWFnbml0dWRlOwogICAgICAgIGlmIChpc05hTihyZXN1bHQueCkgfHwgaXNOYU4ocmVzdWx0LnkpIHx8IGlzTmFOKHJlc3VsdC56KSB8fCBpc05hTihyZXN1bHQudykpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJub3JtYWxpemVkIHJlc3VsdCBpcyBub3QgYSBudW1iZXIiKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuNC5kb3QgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgcmV0dXJuIGxlZnQueCAqIHJpZ2h0LnggKyBsZWZ0LnkgKiByaWdodC55ICsgbGVmdC56ICogcmlnaHQueiArIGxlZnQudyAqIHJpZ2h0Lnc7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjQubXVsdGlwbHlDb21wb25lbnRzID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gbGVmdC54ICogcmlnaHQueDsKICAgICAgICByZXN1bHQueSA9IGxlZnQueSAqIHJpZ2h0Lnk7CiAgICAgICAgcmVzdWx0LnogPSBsZWZ0LnogKiByaWdodC56OwogICAgICAgIHJlc3VsdC53ID0gbGVmdC53ICogcmlnaHQudzsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LmRpdmlkZUNvbXBvbmVudHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBsZWZ0LnggLyByaWdodC54OwogICAgICAgIHJlc3VsdC55ID0gbGVmdC55IC8gcmlnaHQueTsKICAgICAgICByZXN1bHQueiA9IGxlZnQueiAvIHJpZ2h0Lno7CiAgICAgICAgcmVzdWx0LncgPSBsZWZ0LncgLyByaWdodC53OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjQuYWRkID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gbGVmdC54ICsgcmlnaHQueDsKICAgICAgICByZXN1bHQueSA9IGxlZnQueSArIHJpZ2h0Lnk7CiAgICAgICAgcmVzdWx0LnogPSBsZWZ0LnogKyByaWdodC56OwogICAgICAgIHJlc3VsdC53ID0gbGVmdC53ICsgcmlnaHQudzsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LnN1YnRyYWN0ID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gbGVmdC54IC0gcmlnaHQueDsKICAgICAgICByZXN1bHQueSA9IGxlZnQueSAtIHJpZ2h0Lnk7CiAgICAgICAgcmVzdWx0LnogPSBsZWZ0LnogLSByaWdodC56OwogICAgICAgIHJlc3VsdC53ID0gbGVmdC53IC0gcmlnaHQudzsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40Lm11bHRpcGx5QnlTY2FsYXIgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgc2NhbGFyLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInNjYWxhciIsIHNjYWxhcik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gY2FydGVzaWFuMTEueCAqIHNjYWxhcjsKICAgICAgICByZXN1bHQueSA9IGNhcnRlc2lhbjExLnkgKiBzY2FsYXI7CiAgICAgICAgcmVzdWx0LnogPSBjYXJ0ZXNpYW4xMS56ICogc2NhbGFyOwogICAgICAgIHJlc3VsdC53ID0gY2FydGVzaWFuMTEudyAqIHNjYWxhcjsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LmRpdmlkZUJ5U2NhbGFyID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHNjYWxhciwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJzY2FsYXIiLCBzY2FsYXIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQueCA9IGNhcnRlc2lhbjExLnggLyBzY2FsYXI7CiAgICAgICAgcmVzdWx0LnkgPSBjYXJ0ZXNpYW4xMS55IC8gc2NhbGFyOwogICAgICAgIHJlc3VsdC56ID0gY2FydGVzaWFuMTEueiAvIHNjYWxhcjsKICAgICAgICByZXN1bHQudyA9IGNhcnRlc2lhbjExLncgLyBzY2FsYXI7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuNC5uZWdhdGUgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gLWNhcnRlc2lhbjExLng7CiAgICAgICAgcmVzdWx0LnkgPSAtY2FydGVzaWFuMTEueTsKICAgICAgICByZXN1bHQueiA9IC1jYXJ0ZXNpYW4xMS56OwogICAgICAgIHJlc3VsdC53ID0gLWNhcnRlc2lhbjExLnc7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuNC5hYnMgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gTWF0aC5hYnMoY2FydGVzaWFuMTEueCk7CiAgICAgICAgcmVzdWx0LnkgPSBNYXRoLmFicyhjYXJ0ZXNpYW4xMS55KTsKICAgICAgICByZXN1bHQueiA9IE1hdGguYWJzKGNhcnRlc2lhbjExLnopOwogICAgICAgIHJlc3VsdC53ID0gTWF0aC5hYnMoY2FydGVzaWFuMTEudyk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgbGVycFNjcmF0Y2gzID0gbmV3IENhcnRlc2lhbjQoKTsKICAgICAgQ2FydGVzaWFuNC5sZXJwID0gZnVuY3Rpb24oc3RhcnQsIGVuZCwgdCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzdGFydCIsIHN0YXJ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImVuZCIsIGVuZCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJ0IiwgdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIENhcnRlc2lhbjQubXVsdGlwbHlCeVNjYWxhcihlbmQsIHQsIGxlcnBTY3JhdGNoMyk7CiAgICAgICAgcmVzdWx0ID0gQ2FydGVzaWFuNC5tdWx0aXBseUJ5U2NhbGFyKHN0YXJ0LCAxIC0gdCwgcmVzdWx0KTsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuNC5hZGQobGVycFNjcmF0Y2gzLCByZXN1bHQsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIG1vc3RPcnRob2dvbmFsQXhpc1NjcmF0Y2gzID0gbmV3IENhcnRlc2lhbjQoKTsKICAgICAgQ2FydGVzaWFuNC5tb3N0T3J0aG9nb25hbEF4aXMgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IGYgPSBDYXJ0ZXNpYW40Lm5vcm1hbGl6ZShjYXJ0ZXNpYW4xMSwgbW9zdE9ydGhvZ29uYWxBeGlzU2NyYXRjaDMpOwogICAgICAgIENhcnRlc2lhbjQuYWJzKGYsIGYpOwogICAgICAgIGlmIChmLnggPD0gZi55KSB7CiAgICAgICAgICBpZiAoZi54IDw9IGYueikgewogICAgICAgICAgICBpZiAoZi54IDw9IGYudykgewogICAgICAgICAgICAgIHJlc3VsdCA9IENhcnRlc2lhbjQuY2xvbmUoQ2FydGVzaWFuNC5VTklUX1gsIHJlc3VsdCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmVzdWx0ID0gQ2FydGVzaWFuNC5jbG9uZShDYXJ0ZXNpYW40LlVOSVRfVywgcmVzdWx0KTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIGlmIChmLnogPD0gZi53KSB7CiAgICAgICAgICAgIHJlc3VsdCA9IENhcnRlc2lhbjQuY2xvbmUoQ2FydGVzaWFuNC5VTklUX1osIHJlc3VsdCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXN1bHQgPSBDYXJ0ZXNpYW40LmNsb25lKENhcnRlc2lhbjQuVU5JVF9XLCByZXN1bHQpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoZi55IDw9IGYueikgewogICAgICAgICAgaWYgKGYueSA8PSBmLncpIHsKICAgICAgICAgICAgcmVzdWx0ID0gQ2FydGVzaWFuNC5jbG9uZShDYXJ0ZXNpYW40LlVOSVRfWSwgcmVzdWx0KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJlc3VsdCA9IENhcnRlc2lhbjQuY2xvbmUoQ2FydGVzaWFuNC5VTklUX1csIHJlc3VsdCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChmLnogPD0gZi53KSB7CiAgICAgICAgICByZXN1bHQgPSBDYXJ0ZXNpYW40LmNsb25lKENhcnRlc2lhbjQuVU5JVF9aLCByZXN1bHQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQgPSBDYXJ0ZXNpYW40LmNsb25lKENhcnRlc2lhbjQuVU5JVF9XLCByZXN1bHQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LmVxdWFscyA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIGxlZnQgPT09IHJpZ2h0IHx8IGRlZmluZWRfZGVmYXVsdChsZWZ0KSAmJiBkZWZpbmVkX2RlZmF1bHQocmlnaHQpICYmIGxlZnQueCA9PT0gcmlnaHQueCAmJiBsZWZ0LnkgPT09IHJpZ2h0LnkgJiYgbGVmdC56ID09PSByaWdodC56ICYmIGxlZnQudyA9PT0gcmlnaHQudzsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuNC5lcXVhbHNBcnJheSA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCBhcnJheSwgb2Zmc2V0KSB7CiAgICAgICAgcmV0dXJuIGNhcnRlc2lhbjExLnggPT09IGFycmF5W29mZnNldF0gJiYgY2FydGVzaWFuMTEueSA9PT0gYXJyYXlbb2Zmc2V0ICsgMV0gJiYgY2FydGVzaWFuMTEueiA9PT0gYXJyYXlbb2Zmc2V0ICsgMl0gJiYgY2FydGVzaWFuMTEudyA9PT0gYXJyYXlbb2Zmc2V0ICsgM107CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjQuZXF1YWxzRXBzaWxvbiA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCByZWxhdGl2ZUVwc2lsb24sIGFic29sdXRlRXBzaWxvbikgewogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIGxlZnQueCwKICAgICAgICAgIHJpZ2h0LngsCiAgICAgICAgICByZWxhdGl2ZUVwc2lsb24sCiAgICAgICAgICBhYnNvbHV0ZUVwc2lsb24KICAgICAgICApICYmIE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgbGVmdC55LAogICAgICAgICAgcmlnaHQueSwKICAgICAgICAgIHJlbGF0aXZlRXBzaWxvbiwKICAgICAgICAgIGFic29sdXRlRXBzaWxvbgogICAgICAgICkgJiYgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICBsZWZ0LnosCiAgICAgICAgICByaWdodC56LAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKSAmJiBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIGxlZnQudywKICAgICAgICAgIHJpZ2h0LncsCiAgICAgICAgICByZWxhdGl2ZUVwc2lsb24sCiAgICAgICAgICBhYnNvbHV0ZUVwc2lsb24KICAgICAgICApOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LlpFUk8gPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW40KDAsIDAsIDAsIDApKTsKICAgICAgQ2FydGVzaWFuNC5PTkUgPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW40KDEsIDEsIDEsIDEpKTsKICAgICAgQ2FydGVzaWFuNC5VTklUX1ggPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW40KDEsIDAsIDAsIDApKTsKICAgICAgQ2FydGVzaWFuNC5VTklUX1kgPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW40KDAsIDEsIDAsIDApKTsKICAgICAgQ2FydGVzaWFuNC5VTklUX1ogPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW40KDAsIDAsIDEsIDApKTsKICAgICAgQ2FydGVzaWFuNC5VTklUX1cgPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW40KDAsIDAsIDAsIDEpKTsKICAgICAgQ2FydGVzaWFuNC5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuNC5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbihyaWdodCkgewogICAgICAgIHJldHVybiBDYXJ0ZXNpYW40LmVxdWFscyh0aGlzLCByaWdodCk7CiAgICAgIH07CiAgICAgIENhcnRlc2lhbjQucHJvdG90eXBlLmVxdWFsc0Vwc2lsb24gPSBmdW5jdGlvbihyaWdodCwgcmVsYXRpdmVFcHNpbG9uLCBhYnNvbHV0ZUVwc2lsb24pIHsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuNC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgdGhpcywKICAgICAgICAgIHJpZ2h0LAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKTsKICAgICAgfTsKICAgICAgQ2FydGVzaWFuNC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHsKICAgICAgICByZXR1cm4gYCgke3RoaXMueH0sICR7dGhpcy55fSwgJHt0aGlzLnp9LCAke3RoaXMud30pYDsKICAgICAgfTsKICAgICAgc2NyYXRjaEYzMkFycmF5ID0gbmV3IEZsb2F0MzJBcnJheSgxKTsKICAgICAgc2NyYXRjaFU4QXJyYXkgPSBuZXcgVWludDhBcnJheShzY3JhdGNoRjMyQXJyYXkuYnVmZmVyKTsKICAgICAgdGVzdFUzMiA9IG5ldyBVaW50MzJBcnJheShbMjg3NDU0MDIwXSk7CiAgICAgIHRlc3RVOCA9IG5ldyBVaW50OEFycmF5KHRlc3RVMzIuYnVmZmVyKTsKICAgICAgbGl0dGxlRW5kaWFuID0gdGVzdFU4WzBdID09PSA2ODsKICAgICAgQ2FydGVzaWFuNC5wYWNrRmxvYXQgPSBmdW5jdGlvbih2YWx1ZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJ2YWx1ZSIsIHZhbHVlKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQ2FydGVzaWFuNCgpOwogICAgICAgIH0KICAgICAgICBzY3JhdGNoRjMyQXJyYXlbMF0gPSB2YWx1ZTsKICAgICAgICBpZiAobGl0dGxlRW5kaWFuKSB7CiAgICAgICAgICByZXN1bHQueCA9IHNjcmF0Y2hVOEFycmF5WzBdOwogICAgICAgICAgcmVzdWx0LnkgPSBzY3JhdGNoVThBcnJheVsxXTsKICAgICAgICAgIHJlc3VsdC56ID0gc2NyYXRjaFU4QXJyYXlbMl07CiAgICAgICAgICByZXN1bHQudyA9IHNjcmF0Y2hVOEFycmF5WzNdOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQueCA9IHNjcmF0Y2hVOEFycmF5WzNdOwogICAgICAgICAgcmVzdWx0LnkgPSBzY3JhdGNoVThBcnJheVsyXTsKICAgICAgICAgIHJlc3VsdC56ID0gc2NyYXRjaFU4QXJyYXlbMV07CiAgICAgICAgICByZXN1bHQudyA9IHNjcmF0Y2hVOEFycmF5WzBdOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40LnVucGFja0Zsb2F0ID0gZnVuY3Rpb24ocGFja2VkRmxvYXQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInBhY2tlZEZsb2F0IiwgcGFja2VkRmxvYXQpOwogICAgICAgIGlmIChsaXR0bGVFbmRpYW4pIHsKICAgICAgICAgIHNjcmF0Y2hVOEFycmF5WzBdID0gcGFja2VkRmxvYXQueDsKICAgICAgICAgIHNjcmF0Y2hVOEFycmF5WzFdID0gcGFja2VkRmxvYXQueTsKICAgICAgICAgIHNjcmF0Y2hVOEFycmF5WzJdID0gcGFja2VkRmxvYXQuejsKICAgICAgICAgIHNjcmF0Y2hVOEFycmF5WzNdID0gcGFja2VkRmxvYXQudzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc2NyYXRjaFU4QXJyYXlbMF0gPSBwYWNrZWRGbG9hdC53OwogICAgICAgICAgc2NyYXRjaFU4QXJyYXlbMV0gPSBwYWNrZWRGbG9hdC56OwogICAgICAgICAgc2NyYXRjaFU4QXJyYXlbMl0gPSBwYWNrZWRGbG9hdC55OwogICAgICAgICAgc2NyYXRjaFU4QXJyYXlbM10gPSBwYWNrZWRGbG9hdC54OwogICAgICAgIH0KICAgICAgICByZXR1cm4gc2NyYXRjaEYzMkFycmF5WzBdOwogICAgICB9OwogICAgICBDYXJ0ZXNpYW40X2RlZmF1bHQgPSBDYXJ0ZXNpYW40OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvRnJvemVuLmpzCiAgdmFyIEZyb3plbiwgRnJvemVuX2RlZmF1bHQ7CiAgdmFyIGluaXRfRnJvemVuID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Gcm96ZW4uanMiKCkgewogICAgICBGcm96ZW4gPSB7fTsKICAgICAgRnJvemVuLkVNUFRZX09CSkVDVCA9IE9iamVjdC5mcmVlemUoe30pOwogICAgICBGcm96ZW4uRU1QVFlfQVJSQVkgPSBPYmplY3QuZnJlZXplKFtdKTsKICAgICAgRnJvemVuX2RlZmF1bHQgPSBGcm96ZW47CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9SdW50aW1lRXJyb3IuanMKICBmdW5jdGlvbiBSdW50aW1lRXJyb3IobWVzc2FnZSkgewogICAgdGhpcy5uYW1lID0gIlJ1bnRpbWVFcnJvciI7CiAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlOwogICAgbGV0IHN0YWNrOwogICAgdHJ5IHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCk7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHN0YWNrID0gZS5zdGFjazsKICAgIH0KICAgIHRoaXMuc3RhY2sgPSBzdGFjazsKICB9CiAgdmFyIFJ1bnRpbWVFcnJvcl9kZWZhdWx0OwogIHZhciBpbml0X1J1bnRpbWVFcnJvciA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUnVudGltZUVycm9yLmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoT2JqZWN0LmNyZWF0ZSkpIHsKICAgICAgICBSdW50aW1lRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFcnJvci5wcm90b3R5cGUpOwogICAgICAgIFJ1bnRpbWVFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBSdW50aW1lRXJyb3I7CiAgICAgIH0KICAgICAgUnVudGltZUVycm9yLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkgewogICAgICAgIGxldCBzdHIgPSBgJHt0aGlzLm5hbWV9OiAke3RoaXMubWVzc2FnZX1gOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQodGhpcy5zdGFjaykpIHsKICAgICAgICAgIHN0ciArPSBgCiR7dGhpcy5zdGFjay50b1N0cmluZygpfWA7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzdHI7CiAgICAgIH07CiAgICAgIFJ1bnRpbWVFcnJvcl9kZWZhdWx0ID0gUnVudGltZUVycm9yOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvTWF0cml4NC5qcwogIGZ1bmN0aW9uIE1hdHJpeDQoY29sdW1uMFJvdzAsIGNvbHVtbjFSb3cwLCBjb2x1bW4yUm93MCwgY29sdW1uM1JvdzAsIGNvbHVtbjBSb3cxLCBjb2x1bW4xUm93MSwgY29sdW1uMlJvdzEsIGNvbHVtbjNSb3cxLCBjb2x1bW4wUm93MiwgY29sdW1uMVJvdzIsIGNvbHVtbjJSb3cyLCBjb2x1bW4zUm93MiwgY29sdW1uMFJvdzMsIGNvbHVtbjFSb3czLCBjb2x1bW4yUm93MywgY29sdW1uM1JvdzMpIHsKICAgIHRoaXNbMF0gPSBjb2x1bW4wUm93MCA/PyAwOwogICAgdGhpc1sxXSA9IGNvbHVtbjBSb3cxID8/IDA7CiAgICB0aGlzWzJdID0gY29sdW1uMFJvdzIgPz8gMDsKICAgIHRoaXNbM10gPSBjb2x1bW4wUm93MyA/PyAwOwogICAgdGhpc1s0XSA9IGNvbHVtbjFSb3cwID8/IDA7CiAgICB0aGlzWzVdID0gY29sdW1uMVJvdzEgPz8gMDsKICAgIHRoaXNbNl0gPSBjb2x1bW4xUm93MiA/PyAwOwogICAgdGhpc1s3XSA9IGNvbHVtbjFSb3czID8/IDA7CiAgICB0aGlzWzhdID0gY29sdW1uMlJvdzAgPz8gMDsKICAgIHRoaXNbOV0gPSBjb2x1bW4yUm93MSA/PyAwOwogICAgdGhpc1sxMF0gPSBjb2x1bW4yUm93MiA/PyAwOwogICAgdGhpc1sxMV0gPSBjb2x1bW4yUm93MyA/PyAwOwogICAgdGhpc1sxMl0gPSBjb2x1bW4zUm93MCA/PyAwOwogICAgdGhpc1sxM10gPSBjb2x1bW4zUm93MSA/PyAwOwogICAgdGhpc1sxNF0gPSBjb2x1bW4zUm93MiA/PyAwOwogICAgdGhpc1sxNV0gPSBjb2x1bW4zUm93MyA/PyAwOwogIH0KICB2YXIgZnJvbUNhbWVyYUYsIGZyb21DYW1lcmFSLCBmcm9tQ2FtZXJhVSwgc2NhbGVTY3JhdGNoMTIsIHNjYWxlU2NyYXRjaDIyLCBzY3JhdGNoQ29sdW1uMiwgc2NhbGVTY3JhdGNoMzIsIHNjYWxlU2NyYXRjaDQyLCBzY2FsZVNjcmF0Y2g1Miwgc2NyYXRjaEludmVyc2VSb3RhdGlvbiwgc2NyYXRjaE1hdHJpeDNaZXJvLCBzY3JhdGNoQm90dG9tUm93LCBzY3JhdGNoRXhwZWN0ZWRCb3R0b21Sb3csIHNjcmF0Y2hUcmFuc3Bvc2VNYXRyaXgyLCBNYXRyaXg0X2RlZmF1bHQ7CiAgdmFyIGluaXRfTWF0cml4NCA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvTWF0cml4NC5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRlc2lhbjQoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9NYXRyaXgzKCk7CiAgICAgIGluaXRfUnVudGltZUVycm9yKCk7CiAgICAgIE1hdHJpeDQucGFja2VkTGVuZ3RoID0gMTY7CiAgICAgIE1hdHJpeDQucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZVswXTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWVbMV07CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlWzJdOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZVszXTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWVbNF07CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlWzVdOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZVs2XTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWVbN107CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlWzhdOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZVs5XTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWVbMTBdOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZVsxMV07CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlWzEyXTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWVbMTNdOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZVsxNF07CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleF0gPSB2YWx1ZVsxNV07CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBNYXRyaXg0LnVucGFjayA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydGluZ0luZGV4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IE1hdHJpeDQoKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbMV0gPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdFsyXSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0WzNdID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbNF0gPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdFs1XSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0WzZdID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbN10gPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdFs4XSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0WzldID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbMTBdID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbMTFdID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbMTJdID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbMTNdID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbMTRdID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbMTVdID0gYXJyYXlbc3RhcnRpbmdJbmRleF07CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC5wYWNrQXJyYXkgPSBmdW5jdGlvbihhcnJheSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBjb25zdCBsZW5ndGggPSBhcnJheS5sZW5ndGg7CiAgICAgICAgY29uc3QgcmVzdWx0TGVuZ3RoID0gbGVuZ3RoICogMTY7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEFycmF5KHJlc3VsdExlbmd0aCk7CiAgICAgICAgfSBlbHNlIGlmICghQXJyYXkuaXNBcnJheShyZXN1bHQpICYmIHJlc3VsdC5sZW5ndGggIT09IHJlc3VsdExlbmd0aCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJJZiByZXN1bHQgaXMgYSB0eXBlZCBhcnJheSwgaXQgbXVzdCBoYXZlIGV4YWN0bHkgYXJyYXkubGVuZ3RoICogMTYgZWxlbWVudHMiCiAgICAgICAgICApOwogICAgICAgIH0gZWxzZSBpZiAocmVzdWx0Lmxlbmd0aCAhPT0gcmVzdWx0TGVuZ3RoKSB7CiAgICAgICAgICByZXN1bHQubGVuZ3RoID0gcmVzdWx0TGVuZ3RoOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICBNYXRyaXg0LnBhY2soYXJyYXlbaV0sIHJlc3VsdCwgaSAqIDE2KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC51bnBhY2tBcnJheSA9IGZ1bmN0aW9uKGFycmF5LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJhcnJheS5sZW5ndGgiLCBhcnJheS5sZW5ndGgsIDE2KTsKICAgICAgICBpZiAoYXJyYXkubGVuZ3RoICUgMTYgIT09IDApIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhcnJheSBsZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDE2LiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBsZW5ndGggPSBhcnJheS5sZW5ndGg7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEFycmF5KGxlbmd0aCAvIDE2KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzdWx0Lmxlbmd0aCA9IGxlbmd0aCAvIDE2OwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxNikgewogICAgICAgICAgY29uc3QgaW5kZXggPSBpIC8gMTY7CiAgICAgICAgICByZXN1bHRbaW5kZXhdID0gTWF0cml4NC51bnBhY2soYXJyYXksIGksIHJlc3VsdFtpbmRleF0pOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0LmNsb25lID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChtYXRyaXgpKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IE1hdHJpeDQoCiAgICAgICAgICAgIG1hdHJpeFswXSwKICAgICAgICAgICAgbWF0cml4WzRdLAogICAgICAgICAgICBtYXRyaXhbOF0sCiAgICAgICAgICAgIG1hdHJpeFsxMl0sCiAgICAgICAgICAgIG1hdHJpeFsxXSwKICAgICAgICAgICAgbWF0cml4WzVdLAogICAgICAgICAgICBtYXRyaXhbOV0sCiAgICAgICAgICAgIG1hdHJpeFsxM10sCiAgICAgICAgICAgIG1hdHJpeFsyXSwKICAgICAgICAgICAgbWF0cml4WzZdLAogICAgICAgICAgICBtYXRyaXhbMTBdLAogICAgICAgICAgICBtYXRyaXhbMTRdLAogICAgICAgICAgICBtYXRyaXhbM10sCiAgICAgICAgICAgIG1hdHJpeFs3XSwKICAgICAgICAgICAgbWF0cml4WzExXSwKICAgICAgICAgICAgbWF0cml4WzE1XQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4WzBdOwogICAgICAgIHJlc3VsdFsxXSA9IG1hdHJpeFsxXTsKICAgICAgICByZXN1bHRbMl0gPSBtYXRyaXhbMl07CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzNdOwogICAgICAgIHJlc3VsdFs0XSA9IG1hdHJpeFs0XTsKICAgICAgICByZXN1bHRbNV0gPSBtYXRyaXhbNV07CiAgICAgICAgcmVzdWx0WzZdID0gbWF0cml4WzZdOwogICAgICAgIHJlc3VsdFs3XSA9IG1hdHJpeFs3XTsKICAgICAgICByZXN1bHRbOF0gPSBtYXRyaXhbOF07CiAgICAgICAgcmVzdWx0WzldID0gbWF0cml4WzldOwogICAgICAgIHJlc3VsdFsxMF0gPSBtYXRyaXhbMTBdOwogICAgICAgIHJlc3VsdFsxMV0gPSBtYXRyaXhbMTFdOwogICAgICAgIHJlc3VsdFsxMl0gPSBtYXRyaXhbMTJdOwogICAgICAgIHJlc3VsdFsxM10gPSBtYXRyaXhbMTNdOwogICAgICAgIHJlc3VsdFsxNF0gPSBtYXRyaXhbMTRdOwogICAgICAgIHJlc3VsdFsxNV0gPSBtYXRyaXhbMTVdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQuZnJvbUFycmF5ID0gTWF0cml4NC51bnBhY2s7CiAgICAgIE1hdHJpeDQuZnJvbUNvbHVtbk1ham9yQXJyYXkgPSBmdW5jdGlvbih2YWx1ZXMsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgidmFsdWVzIiwgdmFsdWVzKTsKICAgICAgICByZXR1cm4gTWF0cml4NC5jbG9uZSh2YWx1ZXMsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIE1hdHJpeDQuZnJvbVJvd01ham9yQXJyYXkgPSBmdW5jdGlvbih2YWx1ZXMsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgidmFsdWVzIiwgdmFsdWVzKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IE1hdHJpeDQoCiAgICAgICAgICAgIHZhbHVlc1swXSwKICAgICAgICAgICAgdmFsdWVzWzFdLAogICAgICAgICAgICB2YWx1ZXNbMl0sCiAgICAgICAgICAgIHZhbHVlc1szXSwKICAgICAgICAgICAgdmFsdWVzWzRdLAogICAgICAgICAgICB2YWx1ZXNbNV0sCiAgICAgICAgICAgIHZhbHVlc1s2XSwKICAgICAgICAgICAgdmFsdWVzWzddLAogICAgICAgICAgICB2YWx1ZXNbOF0sCiAgICAgICAgICAgIHZhbHVlc1s5XSwKICAgICAgICAgICAgdmFsdWVzWzEwXSwKICAgICAgICAgICAgdmFsdWVzWzExXSwKICAgICAgICAgICAgdmFsdWVzWzEyXSwKICAgICAgICAgICAgdmFsdWVzWzEzXSwKICAgICAgICAgICAgdmFsdWVzWzE0XSwKICAgICAgICAgICAgdmFsdWVzWzE1XQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gdmFsdWVzWzBdOwogICAgICAgIHJlc3VsdFsxXSA9IHZhbHVlc1s0XTsKICAgICAgICByZXN1bHRbMl0gPSB2YWx1ZXNbOF07CiAgICAgICAgcmVzdWx0WzNdID0gdmFsdWVzWzEyXTsKICAgICAgICByZXN1bHRbNF0gPSB2YWx1ZXNbMV07CiAgICAgICAgcmVzdWx0WzVdID0gdmFsdWVzWzVdOwogICAgICAgIHJlc3VsdFs2XSA9IHZhbHVlc1s5XTsKICAgICAgICByZXN1bHRbN10gPSB2YWx1ZXNbMTNdOwogICAgICAgIHJlc3VsdFs4XSA9IHZhbHVlc1syXTsKICAgICAgICByZXN1bHRbOV0gPSB2YWx1ZXNbNl07CiAgICAgICAgcmVzdWx0WzEwXSA9IHZhbHVlc1sxMF07CiAgICAgICAgcmVzdWx0WzExXSA9IHZhbHVlc1sxNF07CiAgICAgICAgcmVzdWx0WzEyXSA9IHZhbHVlc1szXTsKICAgICAgICByZXN1bHRbMTNdID0gdmFsdWVzWzddOwogICAgICAgIHJlc3VsdFsxNF0gPSB2YWx1ZXNbMTFdOwogICAgICAgIHJlc3VsdFsxNV0gPSB2YWx1ZXNbMTVdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQuZnJvbVJvdGF0aW9uVHJhbnNsYXRpb24gPSBmdW5jdGlvbihyb3RhdGlvbiwgdHJhbnNsYXRpb24yLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJvdGF0aW9uIiwgcm90YXRpb24pOwogICAgICAgIHRyYW5zbGF0aW9uMiA9IHRyYW5zbGF0aW9uMiA/PyBDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTzsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IE1hdHJpeDQoCiAgICAgICAgICAgIHJvdGF0aW9uWzBdLAogICAgICAgICAgICByb3RhdGlvblszXSwKICAgICAgICAgICAgcm90YXRpb25bNl0sCiAgICAgICAgICAgIHRyYW5zbGF0aW9uMi54LAogICAgICAgICAgICByb3RhdGlvblsxXSwKICAgICAgICAgICAgcm90YXRpb25bNF0sCiAgICAgICAgICAgIHJvdGF0aW9uWzddLAogICAgICAgICAgICB0cmFuc2xhdGlvbjIueSwKICAgICAgICAgICAgcm90YXRpb25bMl0sCiAgICAgICAgICAgIHJvdGF0aW9uWzVdLAogICAgICAgICAgICByb3RhdGlvbls4XSwKICAgICAgICAgICAgdHJhbnNsYXRpb24yLnosCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIDEKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IHJvdGF0aW9uWzBdOwogICAgICAgIHJlc3VsdFsxXSA9IHJvdGF0aW9uWzFdOwogICAgICAgIHJlc3VsdFsyXSA9IHJvdGF0aW9uWzJdOwogICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgcmVzdWx0WzRdID0gcm90YXRpb25bM107CiAgICAgICAgcmVzdWx0WzVdID0gcm90YXRpb25bNF07CiAgICAgICAgcmVzdWx0WzZdID0gcm90YXRpb25bNV07CiAgICAgICAgcmVzdWx0WzddID0gMDsKICAgICAgICByZXN1bHRbOF0gPSByb3RhdGlvbls2XTsKICAgICAgICByZXN1bHRbOV0gPSByb3RhdGlvbls3XTsKICAgICAgICByZXN1bHRbMTBdID0gcm90YXRpb25bOF07CiAgICAgICAgcmVzdWx0WzExXSA9IDA7CiAgICAgICAgcmVzdWx0WzEyXSA9IHRyYW5zbGF0aW9uMi54OwogICAgICAgIHJlc3VsdFsxM10gPSB0cmFuc2xhdGlvbjIueTsKICAgICAgICByZXN1bHRbMTRdID0gdHJhbnNsYXRpb24yLno7CiAgICAgICAgcmVzdWx0WzE1XSA9IDE7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC5mcm9tVHJhbnNsYXRpb25RdWF0ZXJuaW9uUm90YXRpb25TY2FsZSA9IGZ1bmN0aW9uKHRyYW5zbGF0aW9uMiwgcm90YXRpb24sIHNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInRyYW5zbGF0aW9uIiwgdHJhbnNsYXRpb24yKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJvdGF0aW9uIiwgcm90YXRpb24pOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic2NhbGUiLCBzY2FsZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IE1hdHJpeDQoKTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc2NhbGVYID0gc2NhbGUueDsKICAgICAgICBjb25zdCBzY2FsZVkgPSBzY2FsZS55OwogICAgICAgIGNvbnN0IHNjYWxlWiA9IHNjYWxlLno7CiAgICAgICAgY29uc3QgeDIgPSByb3RhdGlvbi54ICogcm90YXRpb24ueDsKICAgICAgICBjb25zdCB4eSA9IHJvdGF0aW9uLnggKiByb3RhdGlvbi55OwogICAgICAgIGNvbnN0IHh6ID0gcm90YXRpb24ueCAqIHJvdGF0aW9uLno7CiAgICAgICAgY29uc3QgeHcgPSByb3RhdGlvbi54ICogcm90YXRpb24udzsKICAgICAgICBjb25zdCB5MiA9IHJvdGF0aW9uLnkgKiByb3RhdGlvbi55OwogICAgICAgIGNvbnN0IHl6ID0gcm90YXRpb24ueSAqIHJvdGF0aW9uLno7CiAgICAgICAgY29uc3QgeXcgPSByb3RhdGlvbi55ICogcm90YXRpb24udzsKICAgICAgICBjb25zdCB6MiA9IHJvdGF0aW9uLnogKiByb3RhdGlvbi56OwogICAgICAgIGNvbnN0IHp3ID0gcm90YXRpb24ueiAqIHJvdGF0aW9uLnc7CiAgICAgICAgY29uc3QgdzIgPSByb3RhdGlvbi53ICogcm90YXRpb24udzsKICAgICAgICBjb25zdCBtMDAgPSB4MiAtIHkyIC0gejIgKyB3MjsKICAgICAgICBjb25zdCBtMDEgPSAyICogKHh5IC0gencpOwogICAgICAgIGNvbnN0IG0wMiA9IDIgKiAoeHogKyB5dyk7CiAgICAgICAgY29uc3QgbTEwID0gMiAqICh4eSArIHp3KTsKICAgICAgICBjb25zdCBtMTEgPSAteDIgKyB5MiAtIHoyICsgdzI7CiAgICAgICAgY29uc3QgbTEyID0gMiAqICh5eiAtIHh3KTsKICAgICAgICBjb25zdCBtMjAgPSAyICogKHh6IC0geXcpOwogICAgICAgIGNvbnN0IG0yMSA9IDIgKiAoeXogKyB4dyk7CiAgICAgICAgY29uc3QgbTIyID0gLXgyIC0geTIgKyB6MiArIHcyOwogICAgICAgIHJlc3VsdFswXSA9IG0wMCAqIHNjYWxlWDsKICAgICAgICByZXN1bHRbMV0gPSBtMTAgKiBzY2FsZVg7CiAgICAgICAgcmVzdWx0WzJdID0gbTIwICogc2NhbGVYOwogICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgcmVzdWx0WzRdID0gbTAxICogc2NhbGVZOwogICAgICAgIHJlc3VsdFs1XSA9IG0xMSAqIHNjYWxlWTsKICAgICAgICByZXN1bHRbNl0gPSBtMjEgKiBzY2FsZVk7CiAgICAgICAgcmVzdWx0WzddID0gMDsKICAgICAgICByZXN1bHRbOF0gPSBtMDIgKiBzY2FsZVo7CiAgICAgICAgcmVzdWx0WzldID0gbTEyICogc2NhbGVaOwogICAgICAgIHJlc3VsdFsxMF0gPSBtMjIgKiBzY2FsZVo7CiAgICAgICAgcmVzdWx0WzExXSA9IDA7CiAgICAgICAgcmVzdWx0WzEyXSA9IHRyYW5zbGF0aW9uMi54OwogICAgICAgIHJlc3VsdFsxM10gPSB0cmFuc2xhdGlvbjIueTsKICAgICAgICByZXN1bHRbMTRdID0gdHJhbnNsYXRpb24yLno7CiAgICAgICAgcmVzdWx0WzE1XSA9IDE7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC5mcm9tVHJhbnNsYXRpb25Sb3RhdGlvblNjYWxlID0gZnVuY3Rpb24odHJhbnNsYXRpb25Sb3RhdGlvblNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInRyYW5zbGF0aW9uUm90YXRpb25TY2FsZSIsIHRyYW5zbGF0aW9uUm90YXRpb25TY2FsZSk7CiAgICAgICAgcmV0dXJuIE1hdHJpeDQuZnJvbVRyYW5zbGF0aW9uUXVhdGVybmlvblJvdGF0aW9uU2NhbGUoCiAgICAgICAgICB0cmFuc2xhdGlvblJvdGF0aW9uU2NhbGUudHJhbnNsYXRpb24sCiAgICAgICAgICB0cmFuc2xhdGlvblJvdGF0aW9uU2NhbGUucm90YXRpb24sCiAgICAgICAgICB0cmFuc2xhdGlvblJvdGF0aW9uU2NhbGUuc2NhbGUsCiAgICAgICAgICByZXN1bHQKICAgICAgICApOwogICAgICB9OwogICAgICBNYXRyaXg0LmZyb21UcmFuc2xhdGlvbiA9IGZ1bmN0aW9uKHRyYW5zbGF0aW9uMiwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJ0cmFuc2xhdGlvbiIsIHRyYW5zbGF0aW9uMik7CiAgICAgICAgcmV0dXJuIE1hdHJpeDQuZnJvbVJvdGF0aW9uVHJhbnNsYXRpb24oTWF0cml4M19kZWZhdWx0LklERU5USVRZLCB0cmFuc2xhdGlvbjIsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIE1hdHJpeDQuZnJvbVNjYWxlID0gZnVuY3Rpb24oc2NhbGUsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic2NhbGUiLCBzY2FsZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBNYXRyaXg0KAogICAgICAgICAgICBzY2FsZS54LAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICBzY2FsZS55LAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICBzY2FsZS56LAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAxCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXN1bHRbMF0gPSBzY2FsZS54OwogICAgICAgIHJlc3VsdFsxXSA9IDA7CiAgICAgICAgcmVzdWx0WzJdID0gMDsKICAgICAgICByZXN1bHRbM10gPSAwOwogICAgICAgIHJlc3VsdFs0XSA9IDA7CiAgICAgICAgcmVzdWx0WzVdID0gc2NhbGUueTsKICAgICAgICByZXN1bHRbNl0gPSAwOwogICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgcmVzdWx0WzhdID0gMDsKICAgICAgICByZXN1bHRbOV0gPSAwOwogICAgICAgIHJlc3VsdFsxMF0gPSBzY2FsZS56OwogICAgICAgIHJlc3VsdFsxMV0gPSAwOwogICAgICAgIHJlc3VsdFsxMl0gPSAwOwogICAgICAgIHJlc3VsdFsxM10gPSAwOwogICAgICAgIHJlc3VsdFsxNF0gPSAwOwogICAgICAgIHJlc3VsdFsxNV0gPSAxOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQuZnJvbVVuaWZvcm1TY2FsZSA9IGZ1bmN0aW9uKHNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInNjYWxlIiwgc2NhbGUpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgTWF0cml4NCgKICAgICAgICAgICAgc2NhbGUsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIHNjYWxlLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICBzY2FsZSwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgMQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gc2NhbGU7CiAgICAgICAgcmVzdWx0WzFdID0gMDsKICAgICAgICByZXN1bHRbMl0gPSAwOwogICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgcmVzdWx0WzRdID0gMDsKICAgICAgICByZXN1bHRbNV0gPSBzY2FsZTsKICAgICAgICByZXN1bHRbNl0gPSAwOwogICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgcmVzdWx0WzhdID0gMDsKICAgICAgICByZXN1bHRbOV0gPSAwOwogICAgICAgIHJlc3VsdFsxMF0gPSBzY2FsZTsKICAgICAgICByZXN1bHRbMTFdID0gMDsKICAgICAgICByZXN1bHRbMTJdID0gMDsKICAgICAgICByZXN1bHRbMTNdID0gMDsKICAgICAgICByZXN1bHRbMTRdID0gMDsKICAgICAgICByZXN1bHRbMTVdID0gMTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0LmZyb21Sb3RhdGlvbiA9IGZ1bmN0aW9uKHJvdGF0aW9uLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJvdGF0aW9uIiwgcm90YXRpb24pOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBNYXRyaXg0KCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IHJvdGF0aW9uWzBdOwogICAgICAgIHJlc3VsdFsxXSA9IHJvdGF0aW9uWzFdOwogICAgICAgIHJlc3VsdFsyXSA9IHJvdGF0aW9uWzJdOwogICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgcmVzdWx0WzRdID0gcm90YXRpb25bM107CiAgICAgICAgcmVzdWx0WzVdID0gcm90YXRpb25bNF07CiAgICAgICAgcmVzdWx0WzZdID0gcm90YXRpb25bNV07CiAgICAgICAgcmVzdWx0WzddID0gMDsKICAgICAgICByZXN1bHRbOF0gPSByb3RhdGlvbls2XTsKICAgICAgICByZXN1bHRbOV0gPSByb3RhdGlvbls3XTsKICAgICAgICByZXN1bHRbMTBdID0gcm90YXRpb25bOF07CiAgICAgICAgcmVzdWx0WzExXSA9IDA7CiAgICAgICAgcmVzdWx0WzEyXSA9IDA7CiAgICAgICAgcmVzdWx0WzEzXSA9IDA7CiAgICAgICAgcmVzdWx0WzE0XSA9IDA7CiAgICAgICAgcmVzdWx0WzE1XSA9IDE7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgZnJvbUNhbWVyYUYgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZyb21DYW1lcmFSID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBmcm9tQ2FtZXJhVSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgTWF0cml4NC5mcm9tQ2FtZXJhID0gZnVuY3Rpb24oY2FtZXJhLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhbWVyYSIsIGNhbWVyYSk7CiAgICAgICAgY29uc3QgcG9zaXRpb24gPSBjYW1lcmEucG9zaXRpb247CiAgICAgICAgY29uc3QgZGlyZWN0aW9uMiA9IGNhbWVyYS5kaXJlY3Rpb247CiAgICAgICAgY29uc3QgdXAgPSBjYW1lcmEudXA7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYW1lcmEucG9zaXRpb24iLCBwb3NpdGlvbik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYW1lcmEuZGlyZWN0aW9uIiwgZGlyZWN0aW9uMik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYW1lcmEudXAiLCB1cCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShkaXJlY3Rpb24yLCBmcm9tQ2FtZXJhRik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhmcm9tQ2FtZXJhRiwgdXAsIGZyb21DYW1lcmFSKSwKICAgICAgICAgIGZyb21DYW1lcmFSCiAgICAgICAgKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKGZyb21DYW1lcmFSLCBmcm9tQ2FtZXJhRiwgZnJvbUNhbWVyYVUpLAogICAgICAgICAgZnJvbUNhbWVyYVUKICAgICAgICApOwogICAgICAgIGNvbnN0IHNYID0gZnJvbUNhbWVyYVIueDsKICAgICAgICBjb25zdCBzWSA9IGZyb21DYW1lcmFSLnk7CiAgICAgICAgY29uc3Qgc1ogPSBmcm9tQ2FtZXJhUi56OwogICAgICAgIGNvbnN0IGZYID0gZnJvbUNhbWVyYUYueDsKICAgICAgICBjb25zdCBmWSA9IGZyb21DYW1lcmFGLnk7CiAgICAgICAgY29uc3QgZlogPSBmcm9tQ2FtZXJhRi56OwogICAgICAgIGNvbnN0IHVYID0gZnJvbUNhbWVyYVUueDsKICAgICAgICBjb25zdCB1WSA9IGZyb21DYW1lcmFVLnk7CiAgICAgICAgY29uc3QgdVogPSBmcm9tQ2FtZXJhVS56OwogICAgICAgIGNvbnN0IHBvc2l0aW9uWCA9IHBvc2l0aW9uLng7CiAgICAgICAgY29uc3QgcG9zaXRpb25ZID0gcG9zaXRpb24ueTsKICAgICAgICBjb25zdCBwb3NpdGlvblogPSBwb3NpdGlvbi56OwogICAgICAgIGNvbnN0IHQwID0gc1ggKiAtcG9zaXRpb25YICsgc1kgKiAtcG9zaXRpb25ZICsgc1ogKiAtcG9zaXRpb25aOwogICAgICAgIGNvbnN0IHQxID0gdVggKiAtcG9zaXRpb25YICsgdVkgKiAtcG9zaXRpb25ZICsgdVogKiAtcG9zaXRpb25aOwogICAgICAgIGNvbnN0IHQyID0gZlggKiBwb3NpdGlvblggKyBmWSAqIHBvc2l0aW9uWSArIGZaICogcG9zaXRpb25aOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgTWF0cml4NCgKICAgICAgICAgICAgc1gsCiAgICAgICAgICAgIHNZLAogICAgICAgICAgICBzWiwKICAgICAgICAgICAgdDAsCiAgICAgICAgICAgIHVYLAogICAgICAgICAgICB1WSwKICAgICAgICAgICAgdVosCiAgICAgICAgICAgIHQxLAogICAgICAgICAgICAtZlgsCiAgICAgICAgICAgIC1mWSwKICAgICAgICAgICAgLWZaLAogICAgICAgICAgICB0MiwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgMQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gc1g7CiAgICAgICAgcmVzdWx0WzFdID0gdVg7CiAgICAgICAgcmVzdWx0WzJdID0gLWZYOwogICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgcmVzdWx0WzRdID0gc1k7CiAgICAgICAgcmVzdWx0WzVdID0gdVk7CiAgICAgICAgcmVzdWx0WzZdID0gLWZZOwogICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgcmVzdWx0WzhdID0gc1o7CiAgICAgICAgcmVzdWx0WzldID0gdVo7CiAgICAgICAgcmVzdWx0WzEwXSA9IC1mWjsKICAgICAgICByZXN1bHRbMTFdID0gMDsKICAgICAgICByZXN1bHRbMTJdID0gdDA7CiAgICAgICAgcmVzdWx0WzEzXSA9IHQxOwogICAgICAgIHJlc3VsdFsxNF0gPSB0MjsKICAgICAgICByZXN1bHRbMTVdID0gMTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0LmNvbXB1dGVQZXJzcGVjdGl2ZUZpZWxkT2ZWaWV3ID0gZnVuY3Rpb24oZm92WSwgYXNwZWN0UmF0aW8sIG5lYXIsIGZhciwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuKCJmb3ZZIiwgZm92WSwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuKCJmb3ZZIiwgZm92WSwgTWF0aC5QSSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuKCJuZWFyIiwgbmVhciwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuKCJmYXIiLCBmYXIsIDApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBib3R0b20gPSBNYXRoLnRhbihmb3ZZICogMC41KTsKICAgICAgICBjb25zdCBjb2x1bW4xUm93MSA9IDEgLyBib3R0b207CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzAgPSBjb2x1bW4xUm93MSAvIGFzcGVjdFJhdGlvOwogICAgICAgIGNvbnN0IGNvbHVtbjJSb3cyID0gKGZhciArIG5lYXIpIC8gKG5lYXIgLSBmYXIpOwogICAgICAgIGNvbnN0IGNvbHVtbjNSb3cyID0gMiAqIGZhciAqIG5lYXIgLyAobmVhciAtIGZhcik7CiAgICAgICAgcmVzdWx0WzBdID0gY29sdW1uMFJvdzA7CiAgICAgICAgcmVzdWx0WzFdID0gMDsKICAgICAgICByZXN1bHRbMl0gPSAwOwogICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgcmVzdWx0WzRdID0gMDsKICAgICAgICByZXN1bHRbNV0gPSBjb2x1bW4xUm93MTsKICAgICAgICByZXN1bHRbNl0gPSAwOwogICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgcmVzdWx0WzhdID0gMDsKICAgICAgICByZXN1bHRbOV0gPSAwOwogICAgICAgIHJlc3VsdFsxMF0gPSBjb2x1bW4yUm93MjsKICAgICAgICByZXN1bHRbMTFdID0gLTE7CiAgICAgICAgcmVzdWx0WzEyXSA9IDA7CiAgICAgICAgcmVzdWx0WzEzXSA9IDA7CiAgICAgICAgcmVzdWx0WzE0XSA9IGNvbHVtbjNSb3cyOwogICAgICAgIHJlc3VsdFsxNV0gPSAwOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQuY29tcHV0ZU9ydGhvZ3JhcGhpY09mZkNlbnRlciA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCBib3R0b20sIHRvcCwgbmVhciwgZmFyLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoImxlZnQiLCBsZWZ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInJpZ2h0IiwgcmlnaHQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigiYm90dG9tIiwgYm90dG9tKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInRvcCIsIHRvcCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJuZWFyIiwgbmVhcik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJmYXIiLCBmYXIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBsZXQgYTMgPSAxIC8gKHJpZ2h0IC0gbGVmdCk7CiAgICAgICAgbGV0IGIgPSAxIC8gKHRvcCAtIGJvdHRvbSk7CiAgICAgICAgbGV0IGMgPSAxIC8gKGZhciAtIG5lYXIpOwogICAgICAgIGNvbnN0IHR4ID0gLShyaWdodCArIGxlZnQpICogYTM7CiAgICAgICAgY29uc3QgdHkgPSAtKHRvcCArIGJvdHRvbSkgKiBiOwogICAgICAgIGNvbnN0IHR6ID0gLShmYXIgKyBuZWFyKSAqIGM7CiAgICAgICAgYTMgKj0gMjsKICAgICAgICBiICo9IDI7CiAgICAgICAgYyAqPSAtMjsKICAgICAgICByZXN1bHRbMF0gPSBhMzsKICAgICAgICByZXN1bHRbMV0gPSAwOwogICAgICAgIHJlc3VsdFsyXSA9IDA7CiAgICAgICAgcmVzdWx0WzNdID0gMDsKICAgICAgICByZXN1bHRbNF0gPSAwOwogICAgICAgIHJlc3VsdFs1XSA9IGI7CiAgICAgICAgcmVzdWx0WzZdID0gMDsKICAgICAgICByZXN1bHRbN10gPSAwOwogICAgICAgIHJlc3VsdFs4XSA9IDA7CiAgICAgICAgcmVzdWx0WzldID0gMDsKICAgICAgICByZXN1bHRbMTBdID0gYzsKICAgICAgICByZXN1bHRbMTFdID0gMDsKICAgICAgICByZXN1bHRbMTJdID0gdHg7CiAgICAgICAgcmVzdWx0WzEzXSA9IHR5OwogICAgICAgIHJlc3VsdFsxNF0gPSB0ejsKICAgICAgICByZXN1bHRbMTVdID0gMTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0LmNvbXB1dGVQZXJzcGVjdGl2ZU9mZkNlbnRlciA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCBib3R0b20sIHRvcCwgbmVhciwgZmFyLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoImxlZnQiLCBsZWZ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInJpZ2h0IiwgcmlnaHQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigiYm90dG9tIiwgYm90dG9tKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInRvcCIsIHRvcCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJuZWFyIiwgbmVhcik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJmYXIiLCBmYXIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBjb2x1bW4wUm93MCA9IDIgKiBuZWFyIC8gKHJpZ2h0IC0gbGVmdCk7CiAgICAgICAgY29uc3QgY29sdW1uMVJvdzEgPSAyICogbmVhciAvICh0b3AgLSBib3R0b20pOwogICAgICAgIGNvbnN0IGNvbHVtbjJSb3cwID0gKHJpZ2h0ICsgbGVmdCkgLyAocmlnaHQgLSBsZWZ0KTsKICAgICAgICBjb25zdCBjb2x1bW4yUm93MSA9ICh0b3AgKyBib3R0b20pIC8gKHRvcCAtIGJvdHRvbSk7CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzIgPSAtKGZhciArIG5lYXIpIC8gKGZhciAtIG5lYXIpOwogICAgICAgIGNvbnN0IGNvbHVtbjJSb3czID0gLTE7CiAgICAgICAgY29uc3QgY29sdW1uM1JvdzIgPSAtMiAqIGZhciAqIG5lYXIgLyAoZmFyIC0gbmVhcik7CiAgICAgICAgcmVzdWx0WzBdID0gY29sdW1uMFJvdzA7CiAgICAgICAgcmVzdWx0WzFdID0gMDsKICAgICAgICByZXN1bHRbMl0gPSAwOwogICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgcmVzdWx0WzRdID0gMDsKICAgICAgICByZXN1bHRbNV0gPSBjb2x1bW4xUm93MTsKICAgICAgICByZXN1bHRbNl0gPSAwOwogICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgcmVzdWx0WzhdID0gY29sdW1uMlJvdzA7CiAgICAgICAgcmVzdWx0WzldID0gY29sdW1uMlJvdzE7CiAgICAgICAgcmVzdWx0WzEwXSA9IGNvbHVtbjJSb3cyOwogICAgICAgIHJlc3VsdFsxMV0gPSBjb2x1bW4yUm93MzsKICAgICAgICByZXN1bHRbMTJdID0gMDsKICAgICAgICByZXN1bHRbMTNdID0gMDsKICAgICAgICByZXN1bHRbMTRdID0gY29sdW1uM1JvdzI7CiAgICAgICAgcmVzdWx0WzE1XSA9IDA7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC5jb21wdXRlSW5maW5pdGVQZXJzcGVjdGl2ZU9mZkNlbnRlciA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCBib3R0b20sIHRvcCwgbmVhciwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoImJvdHRvbSIsIGJvdHRvbSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJ0b3AiLCB0b3ApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigibmVhciIsIG5lYXIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBjb2x1bW4wUm93MCA9IDIgKiBuZWFyIC8gKHJpZ2h0IC0gbGVmdCk7CiAgICAgICAgY29uc3QgY29sdW1uMVJvdzEgPSAyICogbmVhciAvICh0b3AgLSBib3R0b20pOwogICAgICAgIGNvbnN0IGNvbHVtbjJSb3cwID0gKHJpZ2h0ICsgbGVmdCkgLyAocmlnaHQgLSBsZWZ0KTsKICAgICAgICBjb25zdCBjb2x1bW4yUm93MSA9ICh0b3AgKyBib3R0b20pIC8gKHRvcCAtIGJvdHRvbSk7CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzIgPSAtMTsKICAgICAgICBjb25zdCBjb2x1bW4yUm93MyA9IC0xOwogICAgICAgIGNvbnN0IGNvbHVtbjNSb3cyID0gLTIgKiBuZWFyOwogICAgICAgIHJlc3VsdFswXSA9IGNvbHVtbjBSb3cwOwogICAgICAgIHJlc3VsdFsxXSA9IDA7CiAgICAgICAgcmVzdWx0WzJdID0gMDsKICAgICAgICByZXN1bHRbM10gPSAwOwogICAgICAgIHJlc3VsdFs0XSA9IDA7CiAgICAgICAgcmVzdWx0WzVdID0gY29sdW1uMVJvdzE7CiAgICAgICAgcmVzdWx0WzZdID0gMDsKICAgICAgICByZXN1bHRbN10gPSAwOwogICAgICAgIHJlc3VsdFs4XSA9IGNvbHVtbjJSb3cwOwogICAgICAgIHJlc3VsdFs5XSA9IGNvbHVtbjJSb3cxOwogICAgICAgIHJlc3VsdFsxMF0gPSBjb2x1bW4yUm93MjsKICAgICAgICByZXN1bHRbMTFdID0gY29sdW1uMlJvdzM7CiAgICAgICAgcmVzdWx0WzEyXSA9IDA7CiAgICAgICAgcmVzdWx0WzEzXSA9IDA7CiAgICAgICAgcmVzdWx0WzE0XSA9IGNvbHVtbjNSb3cyOwogICAgICAgIHJlc3VsdFsxNV0gPSAwOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQuY29tcHV0ZVZpZXdwb3J0VHJhbnNmb3JtYXRpb24gPSBmdW5jdGlvbih2aWV3cG9ydCwgbmVhckRlcHRoUmFuZ2UsIGZhckRlcHRoUmFuZ2UsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBNYXRyaXg0KCk7CiAgICAgICAgfQogICAgICAgIHZpZXdwb3J0ID0gdmlld3BvcnQgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgICAgIGNvbnN0IHggPSB2aWV3cG9ydC54ID8/IDA7CiAgICAgICAgY29uc3QgeSA9IHZpZXdwb3J0LnkgPz8gMDsKICAgICAgICBjb25zdCB3aWR0aCA9IHZpZXdwb3J0LndpZHRoID8/IDA7CiAgICAgICAgY29uc3QgaGVpZ2h0ID0gdmlld3BvcnQuaGVpZ2h0ID8/IDA7CiAgICAgICAgbmVhckRlcHRoUmFuZ2UgPSBuZWFyRGVwdGhSYW5nZSA/PyAwOwogICAgICAgIGZhckRlcHRoUmFuZ2UgPSBmYXJEZXB0aFJhbmdlID8/IDE7CiAgICAgICAgY29uc3QgaGFsZldpZHRoID0gd2lkdGggKiAwLjU7CiAgICAgICAgY29uc3QgaGFsZkhlaWdodCA9IGhlaWdodCAqIDAuNTsKICAgICAgICBjb25zdCBoYWxmRGVwdGggPSAoZmFyRGVwdGhSYW5nZSAtIG5lYXJEZXB0aFJhbmdlKSAqIDAuNTsKICAgICAgICBjb25zdCBjb2x1bW4wUm93MCA9IGhhbGZXaWR0aDsKICAgICAgICBjb25zdCBjb2x1bW4xUm93MSA9IGhhbGZIZWlnaHQ7CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzIgPSBoYWxmRGVwdGg7CiAgICAgICAgY29uc3QgY29sdW1uM1JvdzAgPSB4ICsgaGFsZldpZHRoOwogICAgICAgIGNvbnN0IGNvbHVtbjNSb3cxID0geSArIGhhbGZIZWlnaHQ7CiAgICAgICAgY29uc3QgY29sdW1uM1JvdzIgPSBuZWFyRGVwdGhSYW5nZSArIGhhbGZEZXB0aDsKICAgICAgICBjb25zdCBjb2x1bW4zUm93MyA9IDE7CiAgICAgICAgcmVzdWx0WzBdID0gY29sdW1uMFJvdzA7CiAgICAgICAgcmVzdWx0WzFdID0gMDsKICAgICAgICByZXN1bHRbMl0gPSAwOwogICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgcmVzdWx0WzRdID0gMDsKICAgICAgICByZXN1bHRbNV0gPSBjb2x1bW4xUm93MTsKICAgICAgICByZXN1bHRbNl0gPSAwOwogICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgcmVzdWx0WzhdID0gMDsKICAgICAgICByZXN1bHRbOV0gPSAwOwogICAgICAgIHJlc3VsdFsxMF0gPSBjb2x1bW4yUm93MjsKICAgICAgICByZXN1bHRbMTFdID0gMDsKICAgICAgICByZXN1bHRbMTJdID0gY29sdW1uM1JvdzA7CiAgICAgICAgcmVzdWx0WzEzXSA9IGNvbHVtbjNSb3cxOwogICAgICAgIHJlc3VsdFsxNF0gPSBjb2x1bW4zUm93MjsKICAgICAgICByZXN1bHRbMTVdID0gY29sdW1uM1JvdzM7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC5jb21wdXRlVmlldyA9IGZ1bmN0aW9uKHBvc2l0aW9uLCBkaXJlY3Rpb24yLCB1cCwgcmlnaHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicG9zaXRpb24iLCBwb3NpdGlvbik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJkaXJlY3Rpb24iLCBkaXJlY3Rpb24yKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInVwIiwgdXApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdFswXSA9IHJpZ2h0Lng7CiAgICAgICAgcmVzdWx0WzFdID0gdXAueDsKICAgICAgICByZXN1bHRbMl0gPSAtZGlyZWN0aW9uMi54OwogICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgcmVzdWx0WzRdID0gcmlnaHQueTsKICAgICAgICByZXN1bHRbNV0gPSB1cC55OwogICAgICAgIHJlc3VsdFs2XSA9IC1kaXJlY3Rpb24yLnk7CiAgICAgICAgcmVzdWx0WzddID0gMDsKICAgICAgICByZXN1bHRbOF0gPSByaWdodC56OwogICAgICAgIHJlc3VsdFs5XSA9IHVwLno7CiAgICAgICAgcmVzdWx0WzEwXSA9IC1kaXJlY3Rpb24yLno7CiAgICAgICAgcmVzdWx0WzExXSA9IDA7CiAgICAgICAgcmVzdWx0WzEyXSA9IC1DYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHJpZ2h0LCBwb3NpdGlvbik7CiAgICAgICAgcmVzdWx0WzEzXSA9IC1DYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHVwLCBwb3NpdGlvbik7CiAgICAgICAgcmVzdWx0WzE0XSA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QoZGlyZWN0aW9uMiwgcG9zaXRpb24pOwogICAgICAgIHJlc3VsdFsxNV0gPSAxOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQudG9BcnJheSA9IGZ1bmN0aW9uKG1hdHJpeCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBbCiAgICAgICAgICAgIG1hdHJpeFswXSwKICAgICAgICAgICAgbWF0cml4WzFdLAogICAgICAgICAgICBtYXRyaXhbMl0sCiAgICAgICAgICAgIG1hdHJpeFszXSwKICAgICAgICAgICAgbWF0cml4WzRdLAogICAgICAgICAgICBtYXRyaXhbNV0sCiAgICAgICAgICAgIG1hdHJpeFs2XSwKICAgICAgICAgICAgbWF0cml4WzddLAogICAgICAgICAgICBtYXRyaXhbOF0sCiAgICAgICAgICAgIG1hdHJpeFs5XSwKICAgICAgICAgICAgbWF0cml4WzEwXSwKICAgICAgICAgICAgbWF0cml4WzExXSwKICAgICAgICAgICAgbWF0cml4WzEyXSwKICAgICAgICAgICAgbWF0cml4WzEzXSwKICAgICAgICAgICAgbWF0cml4WzE0XSwKICAgICAgICAgICAgbWF0cml4WzE1XQogICAgICAgICAgXTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4WzBdOwogICAgICAgIHJlc3VsdFsxXSA9IG1hdHJpeFsxXTsKICAgICAgICByZXN1bHRbMl0gPSBtYXRyaXhbMl07CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzNdOwogICAgICAgIHJlc3VsdFs0XSA9IG1hdHJpeFs0XTsKICAgICAgICByZXN1bHRbNV0gPSBtYXRyaXhbNV07CiAgICAgICAgcmVzdWx0WzZdID0gbWF0cml4WzZdOwogICAgICAgIHJlc3VsdFs3XSA9IG1hdHJpeFs3XTsKICAgICAgICByZXN1bHRbOF0gPSBtYXRyaXhbOF07CiAgICAgICAgcmVzdWx0WzldID0gbWF0cml4WzldOwogICAgICAgIHJlc3VsdFsxMF0gPSBtYXRyaXhbMTBdOwogICAgICAgIHJlc3VsdFsxMV0gPSBtYXRyaXhbMTFdOwogICAgICAgIHJlc3VsdFsxMl0gPSBtYXRyaXhbMTJdOwogICAgICAgIHJlc3VsdFsxM10gPSBtYXRyaXhbMTNdOwogICAgICAgIHJlc3VsdFsxNF0gPSBtYXRyaXhbMTRdOwogICAgICAgIHJlc3VsdFsxNV0gPSBtYXRyaXhbMTVdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQuZ2V0RWxlbWVudEluZGV4ID0gZnVuY3Rpb24oY29sdW1uLCByb3cpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygicm93Iiwgcm93LCAwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygicm93Iiwgcm93LCAzKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygiY29sdW1uIiwgY29sdW1uLCAwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygiY29sdW1uIiwgY29sdW1uLCAzKTsKICAgICAgICByZXR1cm4gY29sdW1uICogNCArIHJvdzsKICAgICAgfTsKICAgICAgTWF0cml4NC5nZXRDb2x1bW4gPSBmdW5jdGlvbihtYXRyaXgsIGluZGV4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoImluZGV4IiwgaW5kZXgsIDApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5sZXNzVGhhbk9yRXF1YWxzKCJpbmRleCIsIGluZGV4LCAzKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3Qgc3RhcnRJbmRleCA9IGluZGV4ICogNDsKICAgICAgICBjb25zdCB4ID0gbWF0cml4W3N0YXJ0SW5kZXhdOwogICAgICAgIGNvbnN0IHkgPSBtYXRyaXhbc3RhcnRJbmRleCArIDFdOwogICAgICAgIGNvbnN0IHogPSBtYXRyaXhbc3RhcnRJbmRleCArIDJdOwogICAgICAgIGNvbnN0IHcgPSBtYXRyaXhbc3RhcnRJbmRleCArIDNdOwogICAgICAgIHJlc3VsdC54ID0geDsKICAgICAgICByZXN1bHQueSA9IHk7CiAgICAgICAgcmVzdWx0LnogPSB6OwogICAgICAgIHJlc3VsdC53ID0gdzsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0LnNldENvbHVtbiA9IGZ1bmN0aW9uKG1hdHJpeCwgaW5kZXgsIGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoImluZGV4IiwgaW5kZXgsIDApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5sZXNzVGhhbk9yRXF1YWxzKCJpbmRleCIsIGluZGV4LCAzKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0ID0gTWF0cml4NC5jbG9uZShtYXRyaXgsIHJlc3VsdCk7CiAgICAgICAgY29uc3Qgc3RhcnRJbmRleCA9IGluZGV4ICogNDsKICAgICAgICByZXN1bHRbc3RhcnRJbmRleF0gPSBjYXJ0ZXNpYW4xMS54OwogICAgICAgIHJlc3VsdFtzdGFydEluZGV4ICsgMV0gPSBjYXJ0ZXNpYW4xMS55OwogICAgICAgIHJlc3VsdFtzdGFydEluZGV4ICsgMl0gPSBjYXJ0ZXNpYW4xMS56OwogICAgICAgIHJlc3VsdFtzdGFydEluZGV4ICsgM10gPSBjYXJ0ZXNpYW4xMS53OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQuZ2V0Um93ID0gZnVuY3Rpb24obWF0cml4LCBpbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJpbmRleCIsIGluZGV4LCAwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygiaW5kZXgiLCBpbmRleCwgMyk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHggPSBtYXRyaXhbaW5kZXhdOwogICAgICAgIGNvbnN0IHkgPSBtYXRyaXhbaW5kZXggKyA0XTsKICAgICAgICBjb25zdCB6ID0gbWF0cml4W2luZGV4ICsgOF07CiAgICAgICAgY29uc3QgdyA9IG1hdHJpeFtpbmRleCArIDEyXTsKICAgICAgICByZXN1bHQueCA9IHg7CiAgICAgICAgcmVzdWx0LnkgPSB5OwogICAgICAgIHJlc3VsdC56ID0gejsKICAgICAgICByZXN1bHQudyA9IHc7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC5zZXRSb3cgPSBmdW5jdGlvbihtYXRyaXgsIGluZGV4LCBjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJpbmRleCIsIGluZGV4LCAwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygiaW5kZXgiLCBpbmRleCwgMyk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdCA9IE1hdHJpeDQuY2xvbmUobWF0cml4LCByZXN1bHQpOwogICAgICAgIHJlc3VsdFtpbmRleF0gPSBjYXJ0ZXNpYW4xMS54OwogICAgICAgIHJlc3VsdFtpbmRleCArIDRdID0gY2FydGVzaWFuMTEueTsKICAgICAgICByZXN1bHRbaW5kZXggKyA4XSA9IGNhcnRlc2lhbjExLno7CiAgICAgICAgcmVzdWx0W2luZGV4ICsgMTJdID0gY2FydGVzaWFuMTEudzsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0LnNldFRyYW5zbGF0aW9uID0gZnVuY3Rpb24obWF0cml4LCB0cmFuc2xhdGlvbjIsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInRyYW5zbGF0aW9uIiwgdHJhbnNsYXRpb24yKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4WzBdOwogICAgICAgIHJlc3VsdFsxXSA9IG1hdHJpeFsxXTsKICAgICAgICByZXN1bHRbMl0gPSBtYXRyaXhbMl07CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzNdOwogICAgICAgIHJlc3VsdFs0XSA9IG1hdHJpeFs0XTsKICAgICAgICByZXN1bHRbNV0gPSBtYXRyaXhbNV07CiAgICAgICAgcmVzdWx0WzZdID0gbWF0cml4WzZdOwogICAgICAgIHJlc3VsdFs3XSA9IG1hdHJpeFs3XTsKICAgICAgICByZXN1bHRbOF0gPSBtYXRyaXhbOF07CiAgICAgICAgcmVzdWx0WzldID0gbWF0cml4WzldOwogICAgICAgIHJlc3VsdFsxMF0gPSBtYXRyaXhbMTBdOwogICAgICAgIHJlc3VsdFsxMV0gPSBtYXRyaXhbMTFdOwogICAgICAgIHJlc3VsdFsxMl0gPSB0cmFuc2xhdGlvbjIueDsKICAgICAgICByZXN1bHRbMTNdID0gdHJhbnNsYXRpb24yLnk7CiAgICAgICAgcmVzdWx0WzE0XSA9IHRyYW5zbGF0aW9uMi56OwogICAgICAgIHJlc3VsdFsxNV0gPSBtYXRyaXhbMTVdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHNjYWxlU2NyYXRjaDEyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBNYXRyaXg0LnNldFNjYWxlID0gZnVuY3Rpb24obWF0cml4LCBzY2FsZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic2NhbGUiLCBzY2FsZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IGV4aXN0aW5nU2NhbGUgPSBNYXRyaXg0LmdldFNjYWxlKG1hdHJpeCwgc2NhbGVTY3JhdGNoMTIpOwogICAgICAgIGNvbnN0IHNjYWxlUmF0aW9YID0gc2NhbGUueCAvIGV4aXN0aW5nU2NhbGUueDsKICAgICAgICBjb25zdCBzY2FsZVJhdGlvWSA9IHNjYWxlLnkgLyBleGlzdGluZ1NjYWxlLnk7CiAgICAgICAgY29uc3Qgc2NhbGVSYXRpb1ogPSBzY2FsZS56IC8gZXhpc3RpbmdTY2FsZS56OwogICAgICAgIHJlc3VsdFswXSA9IG1hdHJpeFswXSAqIHNjYWxlUmF0aW9YOwogICAgICAgIHJlc3VsdFsxXSA9IG1hdHJpeFsxXSAqIHNjYWxlUmF0aW9YOwogICAgICAgIHJlc3VsdFsyXSA9IG1hdHJpeFsyXSAqIHNjYWxlUmF0aW9YOwogICAgICAgIHJlc3VsdFszXSA9IG1hdHJpeFszXTsKICAgICAgICByZXN1bHRbNF0gPSBtYXRyaXhbNF0gKiBzY2FsZVJhdGlvWTsKICAgICAgICByZXN1bHRbNV0gPSBtYXRyaXhbNV0gKiBzY2FsZVJhdGlvWTsKICAgICAgICByZXN1bHRbNl0gPSBtYXRyaXhbNl0gKiBzY2FsZVJhdGlvWTsKICAgICAgICByZXN1bHRbN10gPSBtYXRyaXhbN107CiAgICAgICAgcmVzdWx0WzhdID0gbWF0cml4WzhdICogc2NhbGVSYXRpb1o7CiAgICAgICAgcmVzdWx0WzldID0gbWF0cml4WzldICogc2NhbGVSYXRpb1o7CiAgICAgICAgcmVzdWx0WzEwXSA9IG1hdHJpeFsxMF0gKiBzY2FsZVJhdGlvWjsKICAgICAgICByZXN1bHRbMTFdID0gbWF0cml4WzExXTsKICAgICAgICByZXN1bHRbMTJdID0gbWF0cml4WzEyXTsKICAgICAgICByZXN1bHRbMTNdID0gbWF0cml4WzEzXTsKICAgICAgICByZXN1bHRbMTRdID0gbWF0cml4WzE0XTsKICAgICAgICByZXN1bHRbMTVdID0gbWF0cml4WzE1XTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBzY2FsZVNjcmF0Y2gyMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgTWF0cml4NC5zZXRVbmlmb3JtU2NhbGUgPSBmdW5jdGlvbihtYXRyaXgsIHNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJzY2FsZSIsIHNjYWxlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgZXhpc3RpbmdTY2FsZSA9IE1hdHJpeDQuZ2V0U2NhbGUobWF0cml4LCBzY2FsZVNjcmF0Y2gyMik7CiAgICAgICAgY29uc3Qgc2NhbGVSYXRpb1ggPSBzY2FsZSAvIGV4aXN0aW5nU2NhbGUueDsKICAgICAgICBjb25zdCBzY2FsZVJhdGlvWSA9IHNjYWxlIC8gZXhpc3RpbmdTY2FsZS55OwogICAgICAgIGNvbnN0IHNjYWxlUmF0aW9aID0gc2NhbGUgLyBleGlzdGluZ1NjYWxlLno7CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4WzBdICogc2NhbGVSYXRpb1g7CiAgICAgICAgcmVzdWx0WzFdID0gbWF0cml4WzFdICogc2NhbGVSYXRpb1g7CiAgICAgICAgcmVzdWx0WzJdID0gbWF0cml4WzJdICogc2NhbGVSYXRpb1g7CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzNdOwogICAgICAgIHJlc3VsdFs0XSA9IG1hdHJpeFs0XSAqIHNjYWxlUmF0aW9ZOwogICAgICAgIHJlc3VsdFs1XSA9IG1hdHJpeFs1XSAqIHNjYWxlUmF0aW9ZOwogICAgICAgIHJlc3VsdFs2XSA9IG1hdHJpeFs2XSAqIHNjYWxlUmF0aW9ZOwogICAgICAgIHJlc3VsdFs3XSA9IG1hdHJpeFs3XTsKICAgICAgICByZXN1bHRbOF0gPSBtYXRyaXhbOF0gKiBzY2FsZVJhdGlvWjsKICAgICAgICByZXN1bHRbOV0gPSBtYXRyaXhbOV0gKiBzY2FsZVJhdGlvWjsKICAgICAgICByZXN1bHRbMTBdID0gbWF0cml4WzEwXSAqIHNjYWxlUmF0aW9aOwogICAgICAgIHJlc3VsdFsxMV0gPSBtYXRyaXhbMTFdOwogICAgICAgIHJlc3VsdFsxMl0gPSBtYXRyaXhbMTJdOwogICAgICAgIHJlc3VsdFsxM10gPSBtYXRyaXhbMTNdOwogICAgICAgIHJlc3VsdFsxNF0gPSBtYXRyaXhbMTRdOwogICAgICAgIHJlc3VsdFsxNV0gPSBtYXRyaXhbMTVdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hDb2x1bW4yID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBNYXRyaXg0LmdldFNjYWxlID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZSgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tRWxlbWVudHMobWF0cml4WzBdLCBtYXRyaXhbMV0sIG1hdHJpeFsyXSwgc2NyYXRjaENvbHVtbjIpCiAgICAgICAgKTsKICAgICAgICByZXN1bHQueSA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUVsZW1lbnRzKG1hdHJpeFs0XSwgbWF0cml4WzVdLCBtYXRyaXhbNl0sIHNjcmF0Y2hDb2x1bW4yKQogICAgICAgICk7CiAgICAgICAgcmVzdWx0LnogPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21FbGVtZW50cyhtYXRyaXhbOF0sIG1hdHJpeFs5XSwgbWF0cml4WzEwXSwgc2NyYXRjaENvbHVtbjIpCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBzY2FsZVNjcmF0Y2gzMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgTWF0cml4NC5nZXRNYXhpbXVtU2NhbGUgPSBmdW5jdGlvbihtYXRyaXgpIHsKICAgICAgICBNYXRyaXg0LmdldFNjYWxlKG1hdHJpeCwgc2NhbGVTY3JhdGNoMzIpOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQubWF4aW11bUNvbXBvbmVudChzY2FsZVNjcmF0Y2gzMik7CiAgICAgIH07CiAgICAgIHNjYWxlU2NyYXRjaDQyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBNYXRyaXg0LnNldFJvdGF0aW9uID0gZnVuY3Rpb24obWF0cml4LCByb3RhdGlvbiwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBzY2FsZSA9IE1hdHJpeDQuZ2V0U2NhbGUobWF0cml4LCBzY2FsZVNjcmF0Y2g0Mik7CiAgICAgICAgcmVzdWx0WzBdID0gcm90YXRpb25bMF0gKiBzY2FsZS54OwogICAgICAgIHJlc3VsdFsxXSA9IHJvdGF0aW9uWzFdICogc2NhbGUueDsKICAgICAgICByZXN1bHRbMl0gPSByb3RhdGlvblsyXSAqIHNjYWxlLng7CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzNdOwogICAgICAgIHJlc3VsdFs0XSA9IHJvdGF0aW9uWzNdICogc2NhbGUueTsKICAgICAgICByZXN1bHRbNV0gPSByb3RhdGlvbls0XSAqIHNjYWxlLnk7CiAgICAgICAgcmVzdWx0WzZdID0gcm90YXRpb25bNV0gKiBzY2FsZS55OwogICAgICAgIHJlc3VsdFs3XSA9IG1hdHJpeFs3XTsKICAgICAgICByZXN1bHRbOF0gPSByb3RhdGlvbls2XSAqIHNjYWxlLno7CiAgICAgICAgcmVzdWx0WzldID0gcm90YXRpb25bN10gKiBzY2FsZS56OwogICAgICAgIHJlc3VsdFsxMF0gPSByb3RhdGlvbls4XSAqIHNjYWxlLno7CiAgICAgICAgcmVzdWx0WzExXSA9IG1hdHJpeFsxMV07CiAgICAgICAgcmVzdWx0WzEyXSA9IG1hdHJpeFsxMl07CiAgICAgICAgcmVzdWx0WzEzXSA9IG1hdHJpeFsxM107CiAgICAgICAgcmVzdWx0WzE0XSA9IG1hdHJpeFsxNF07CiAgICAgICAgcmVzdWx0WzE1XSA9IG1hdHJpeFsxNV07CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NhbGVTY3JhdGNoNTIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIE1hdHJpeDQuZ2V0Um90YXRpb24gPSBmdW5jdGlvbihtYXRyaXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3Qgc2NhbGUgPSBNYXRyaXg0LmdldFNjYWxlKG1hdHJpeCwgc2NhbGVTY3JhdGNoNTIpOwogICAgICAgIHJlc3VsdFswXSA9IG1hdHJpeFswXSAvIHNjYWxlLng7CiAgICAgICAgcmVzdWx0WzFdID0gbWF0cml4WzFdIC8gc2NhbGUueDsKICAgICAgICByZXN1bHRbMl0gPSBtYXRyaXhbMl0gLyBzY2FsZS54OwogICAgICAgIHJlc3VsdFszXSA9IG1hdHJpeFs0XSAvIHNjYWxlLnk7CiAgICAgICAgcmVzdWx0WzRdID0gbWF0cml4WzVdIC8gc2NhbGUueTsKICAgICAgICByZXN1bHRbNV0gPSBtYXRyaXhbNl0gLyBzY2FsZS55OwogICAgICAgIHJlc3VsdFs2XSA9IG1hdHJpeFs4XSAvIHNjYWxlLno7CiAgICAgICAgcmVzdWx0WzddID0gbWF0cml4WzldIC8gc2NhbGUuejsKICAgICAgICByZXN1bHRbOF0gPSBtYXRyaXhbMTBdIC8gc2NhbGUuejsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0Lm11bHRpcGx5ID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IGxlZnQwID0gbGVmdFswXTsKICAgICAgICBjb25zdCBsZWZ0MSA9IGxlZnRbMV07CiAgICAgICAgY29uc3QgbGVmdDIgPSBsZWZ0WzJdOwogICAgICAgIGNvbnN0IGxlZnQzID0gbGVmdFszXTsKICAgICAgICBjb25zdCBsZWZ0NCA9IGxlZnRbNF07CiAgICAgICAgY29uc3QgbGVmdDUgPSBsZWZ0WzVdOwogICAgICAgIGNvbnN0IGxlZnQ2ID0gbGVmdFs2XTsKICAgICAgICBjb25zdCBsZWZ0NyA9IGxlZnRbN107CiAgICAgICAgY29uc3QgbGVmdDggPSBsZWZ0WzhdOwogICAgICAgIGNvbnN0IGxlZnQ5ID0gbGVmdFs5XTsKICAgICAgICBjb25zdCBsZWZ0MTAgPSBsZWZ0WzEwXTsKICAgICAgICBjb25zdCBsZWZ0MTEgPSBsZWZ0WzExXTsKICAgICAgICBjb25zdCBsZWZ0MTIgPSBsZWZ0WzEyXTsKICAgICAgICBjb25zdCBsZWZ0MTMgPSBsZWZ0WzEzXTsKICAgICAgICBjb25zdCBsZWZ0MTQgPSBsZWZ0WzE0XTsKICAgICAgICBjb25zdCBsZWZ0MTUgPSBsZWZ0WzE1XTsKICAgICAgICBjb25zdCByaWdodDAgPSByaWdodFswXTsKICAgICAgICBjb25zdCByaWdodDEgPSByaWdodFsxXTsKICAgICAgICBjb25zdCByaWdodDIgPSByaWdodFsyXTsKICAgICAgICBjb25zdCByaWdodDMgPSByaWdodFszXTsKICAgICAgICBjb25zdCByaWdodDQgPSByaWdodFs0XTsKICAgICAgICBjb25zdCByaWdodDUgPSByaWdodFs1XTsKICAgICAgICBjb25zdCByaWdodDYgPSByaWdodFs2XTsKICAgICAgICBjb25zdCByaWdodDcgPSByaWdodFs3XTsKICAgICAgICBjb25zdCByaWdodDggPSByaWdodFs4XTsKICAgICAgICBjb25zdCByaWdodDkgPSByaWdodFs5XTsKICAgICAgICBjb25zdCByaWdodDEwID0gcmlnaHRbMTBdOwogICAgICAgIGNvbnN0IHJpZ2h0MTEgPSByaWdodFsxMV07CiAgICAgICAgY29uc3QgcmlnaHQxMiA9IHJpZ2h0WzEyXTsKICAgICAgICBjb25zdCByaWdodDEzID0gcmlnaHRbMTNdOwogICAgICAgIGNvbnN0IHJpZ2h0MTQgPSByaWdodFsxNF07CiAgICAgICAgY29uc3QgcmlnaHQxNSA9IHJpZ2h0WzE1XTsKICAgICAgICBjb25zdCBjb2x1bW4wUm93MCA9IGxlZnQwICogcmlnaHQwICsgbGVmdDQgKiByaWdodDEgKyBsZWZ0OCAqIHJpZ2h0MiArIGxlZnQxMiAqIHJpZ2h0MzsKICAgICAgICBjb25zdCBjb2x1bW4wUm93MSA9IGxlZnQxICogcmlnaHQwICsgbGVmdDUgKiByaWdodDEgKyBsZWZ0OSAqIHJpZ2h0MiArIGxlZnQxMyAqIHJpZ2h0MzsKICAgICAgICBjb25zdCBjb2x1bW4wUm93MiA9IGxlZnQyICogcmlnaHQwICsgbGVmdDYgKiByaWdodDEgKyBsZWZ0MTAgKiByaWdodDIgKyBsZWZ0MTQgKiByaWdodDM7CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzMgPSBsZWZ0MyAqIHJpZ2h0MCArIGxlZnQ3ICogcmlnaHQxICsgbGVmdDExICogcmlnaHQyICsgbGVmdDE1ICogcmlnaHQzOwogICAgICAgIGNvbnN0IGNvbHVtbjFSb3cwID0gbGVmdDAgKiByaWdodDQgKyBsZWZ0NCAqIHJpZ2h0NSArIGxlZnQ4ICogcmlnaHQ2ICsgbGVmdDEyICogcmlnaHQ3OwogICAgICAgIGNvbnN0IGNvbHVtbjFSb3cxID0gbGVmdDEgKiByaWdodDQgKyBsZWZ0NSAqIHJpZ2h0NSArIGxlZnQ5ICogcmlnaHQ2ICsgbGVmdDEzICogcmlnaHQ3OwogICAgICAgIGNvbnN0IGNvbHVtbjFSb3cyID0gbGVmdDIgKiByaWdodDQgKyBsZWZ0NiAqIHJpZ2h0NSArIGxlZnQxMCAqIHJpZ2h0NiArIGxlZnQxNCAqIHJpZ2h0NzsKICAgICAgICBjb25zdCBjb2x1bW4xUm93MyA9IGxlZnQzICogcmlnaHQ0ICsgbGVmdDcgKiByaWdodDUgKyBsZWZ0MTEgKiByaWdodDYgKyBsZWZ0MTUgKiByaWdodDc7CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzAgPSBsZWZ0MCAqIHJpZ2h0OCArIGxlZnQ0ICogcmlnaHQ5ICsgbGVmdDggKiByaWdodDEwICsgbGVmdDEyICogcmlnaHQxMTsKICAgICAgICBjb25zdCBjb2x1bW4yUm93MSA9IGxlZnQxICogcmlnaHQ4ICsgbGVmdDUgKiByaWdodDkgKyBsZWZ0OSAqIHJpZ2h0MTAgKyBsZWZ0MTMgKiByaWdodDExOwogICAgICAgIGNvbnN0IGNvbHVtbjJSb3cyID0gbGVmdDIgKiByaWdodDggKyBsZWZ0NiAqIHJpZ2h0OSArIGxlZnQxMCAqIHJpZ2h0MTAgKyBsZWZ0MTQgKiByaWdodDExOwogICAgICAgIGNvbnN0IGNvbHVtbjJSb3czID0gbGVmdDMgKiByaWdodDggKyBsZWZ0NyAqIHJpZ2h0OSArIGxlZnQxMSAqIHJpZ2h0MTAgKyBsZWZ0MTUgKiByaWdodDExOwogICAgICAgIGNvbnN0IGNvbHVtbjNSb3cwID0gbGVmdDAgKiByaWdodDEyICsgbGVmdDQgKiByaWdodDEzICsgbGVmdDggKiByaWdodDE0ICsgbGVmdDEyICogcmlnaHQxNTsKICAgICAgICBjb25zdCBjb2x1bW4zUm93MSA9IGxlZnQxICogcmlnaHQxMiArIGxlZnQ1ICogcmlnaHQxMyArIGxlZnQ5ICogcmlnaHQxNCArIGxlZnQxMyAqIHJpZ2h0MTU7CiAgICAgICAgY29uc3QgY29sdW1uM1JvdzIgPSBsZWZ0MiAqIHJpZ2h0MTIgKyBsZWZ0NiAqIHJpZ2h0MTMgKyBsZWZ0MTAgKiByaWdodDE0ICsgbGVmdDE0ICogcmlnaHQxNTsKICAgICAgICBjb25zdCBjb2x1bW4zUm93MyA9IGxlZnQzICogcmlnaHQxMiArIGxlZnQ3ICogcmlnaHQxMyArIGxlZnQxMSAqIHJpZ2h0MTQgKyBsZWZ0MTUgKiByaWdodDE1OwogICAgICAgIHJlc3VsdFswXSA9IGNvbHVtbjBSb3cwOwogICAgICAgIHJlc3VsdFsxXSA9IGNvbHVtbjBSb3cxOwogICAgICAgIHJlc3VsdFsyXSA9IGNvbHVtbjBSb3cyOwogICAgICAgIHJlc3VsdFszXSA9IGNvbHVtbjBSb3czOwogICAgICAgIHJlc3VsdFs0XSA9IGNvbHVtbjFSb3cwOwogICAgICAgIHJlc3VsdFs1XSA9IGNvbHVtbjFSb3cxOwogICAgICAgIHJlc3VsdFs2XSA9IGNvbHVtbjFSb3cyOwogICAgICAgIHJlc3VsdFs3XSA9IGNvbHVtbjFSb3czOwogICAgICAgIHJlc3VsdFs4XSA9IGNvbHVtbjJSb3cwOwogICAgICAgIHJlc3VsdFs5XSA9IGNvbHVtbjJSb3cxOwogICAgICAgIHJlc3VsdFsxMF0gPSBjb2x1bW4yUm93MjsKICAgICAgICByZXN1bHRbMTFdID0gY29sdW1uMlJvdzM7CiAgICAgICAgcmVzdWx0WzEyXSA9IGNvbHVtbjNSb3cwOwogICAgICAgIHJlc3VsdFsxM10gPSBjb2x1bW4zUm93MTsKICAgICAgICByZXN1bHRbMTRdID0gY29sdW1uM1JvdzI7CiAgICAgICAgcmVzdWx0WzE1XSA9IGNvbHVtbjNSb3czOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQuYWRkID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdFswXSA9IGxlZnRbMF0gKyByaWdodFswXTsKICAgICAgICByZXN1bHRbMV0gPSBsZWZ0WzFdICsgcmlnaHRbMV07CiAgICAgICAgcmVzdWx0WzJdID0gbGVmdFsyXSArIHJpZ2h0WzJdOwogICAgICAgIHJlc3VsdFszXSA9IGxlZnRbM10gKyByaWdodFszXTsKICAgICAgICByZXN1bHRbNF0gPSBsZWZ0WzRdICsgcmlnaHRbNF07CiAgICAgICAgcmVzdWx0WzVdID0gbGVmdFs1XSArIHJpZ2h0WzVdOwogICAgICAgIHJlc3VsdFs2XSA9IGxlZnRbNl0gKyByaWdodFs2XTsKICAgICAgICByZXN1bHRbN10gPSBsZWZ0WzddICsgcmlnaHRbN107CiAgICAgICAgcmVzdWx0WzhdID0gbGVmdFs4XSArIHJpZ2h0WzhdOwogICAgICAgIHJlc3VsdFs5XSA9IGxlZnRbOV0gKyByaWdodFs5XTsKICAgICAgICByZXN1bHRbMTBdID0gbGVmdFsxMF0gKyByaWdodFsxMF07CiAgICAgICAgcmVzdWx0WzExXSA9IGxlZnRbMTFdICsgcmlnaHRbMTFdOwogICAgICAgIHJlc3VsdFsxMl0gPSBsZWZ0WzEyXSArIHJpZ2h0WzEyXTsKICAgICAgICByZXN1bHRbMTNdID0gbGVmdFsxM10gKyByaWdodFsxM107CiAgICAgICAgcmVzdWx0WzE0XSA9IGxlZnRbMTRdICsgcmlnaHRbMTRdOwogICAgICAgIHJlc3VsdFsxNV0gPSBsZWZ0WzE1XSArIHJpZ2h0WzE1XTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0LnN1YnRyYWN0ID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdFswXSA9IGxlZnRbMF0gLSByaWdodFswXTsKICAgICAgICByZXN1bHRbMV0gPSBsZWZ0WzFdIC0gcmlnaHRbMV07CiAgICAgICAgcmVzdWx0WzJdID0gbGVmdFsyXSAtIHJpZ2h0WzJdOwogICAgICAgIHJlc3VsdFszXSA9IGxlZnRbM10gLSByaWdodFszXTsKICAgICAgICByZXN1bHRbNF0gPSBsZWZ0WzRdIC0gcmlnaHRbNF07CiAgICAgICAgcmVzdWx0WzVdID0gbGVmdFs1XSAtIHJpZ2h0WzVdOwogICAgICAgIHJlc3VsdFs2XSA9IGxlZnRbNl0gLSByaWdodFs2XTsKICAgICAgICByZXN1bHRbN10gPSBsZWZ0WzddIC0gcmlnaHRbN107CiAgICAgICAgcmVzdWx0WzhdID0gbGVmdFs4XSAtIHJpZ2h0WzhdOwogICAgICAgIHJlc3VsdFs5XSA9IGxlZnRbOV0gLSByaWdodFs5XTsKICAgICAgICByZXN1bHRbMTBdID0gbGVmdFsxMF0gLSByaWdodFsxMF07CiAgICAgICAgcmVzdWx0WzExXSA9IGxlZnRbMTFdIC0gcmlnaHRbMTFdOwogICAgICAgIHJlc3VsdFsxMl0gPSBsZWZ0WzEyXSAtIHJpZ2h0WzEyXTsKICAgICAgICByZXN1bHRbMTNdID0gbGVmdFsxM10gLSByaWdodFsxM107CiAgICAgICAgcmVzdWx0WzE0XSA9IGxlZnRbMTRdIC0gcmlnaHRbMTRdOwogICAgICAgIHJlc3VsdFsxNV0gPSBsZWZ0WzE1XSAtIHJpZ2h0WzE1XTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0Lm11bHRpcGx5VHJhbnNmb3JtYXRpb24gPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgbGVmdDAgPSBsZWZ0WzBdOwogICAgICAgIGNvbnN0IGxlZnQxID0gbGVmdFsxXTsKICAgICAgICBjb25zdCBsZWZ0MiA9IGxlZnRbMl07CiAgICAgICAgY29uc3QgbGVmdDQgPSBsZWZ0WzRdOwogICAgICAgIGNvbnN0IGxlZnQ1ID0gbGVmdFs1XTsKICAgICAgICBjb25zdCBsZWZ0NiA9IGxlZnRbNl07CiAgICAgICAgY29uc3QgbGVmdDggPSBsZWZ0WzhdOwogICAgICAgIGNvbnN0IGxlZnQ5ID0gbGVmdFs5XTsKICAgICAgICBjb25zdCBsZWZ0MTAgPSBsZWZ0WzEwXTsKICAgICAgICBjb25zdCBsZWZ0MTIgPSBsZWZ0WzEyXTsKICAgICAgICBjb25zdCBsZWZ0MTMgPSBsZWZ0WzEzXTsKICAgICAgICBjb25zdCBsZWZ0MTQgPSBsZWZ0WzE0XTsKICAgICAgICBjb25zdCByaWdodDAgPSByaWdodFswXTsKICAgICAgICBjb25zdCByaWdodDEgPSByaWdodFsxXTsKICAgICAgICBjb25zdCByaWdodDIgPSByaWdodFsyXTsKICAgICAgICBjb25zdCByaWdodDQgPSByaWdodFs0XTsKICAgICAgICBjb25zdCByaWdodDUgPSByaWdodFs1XTsKICAgICAgICBjb25zdCByaWdodDYgPSByaWdodFs2XTsKICAgICAgICBjb25zdCByaWdodDggPSByaWdodFs4XTsKICAgICAgICBjb25zdCByaWdodDkgPSByaWdodFs5XTsKICAgICAgICBjb25zdCByaWdodDEwID0gcmlnaHRbMTBdOwogICAgICAgIGNvbnN0IHJpZ2h0MTIgPSByaWdodFsxMl07CiAgICAgICAgY29uc3QgcmlnaHQxMyA9IHJpZ2h0WzEzXTsKICAgICAgICBjb25zdCByaWdodDE0ID0gcmlnaHRbMTRdOwogICAgICAgIGNvbnN0IGNvbHVtbjBSb3cwID0gbGVmdDAgKiByaWdodDAgKyBsZWZ0NCAqIHJpZ2h0MSArIGxlZnQ4ICogcmlnaHQyOwogICAgICAgIGNvbnN0IGNvbHVtbjBSb3cxID0gbGVmdDEgKiByaWdodDAgKyBsZWZ0NSAqIHJpZ2h0MSArIGxlZnQ5ICogcmlnaHQyOwogICAgICAgIGNvbnN0IGNvbHVtbjBSb3cyID0gbGVmdDIgKiByaWdodDAgKyBsZWZ0NiAqIHJpZ2h0MSArIGxlZnQxMCAqIHJpZ2h0MjsKICAgICAgICBjb25zdCBjb2x1bW4xUm93MCA9IGxlZnQwICogcmlnaHQ0ICsgbGVmdDQgKiByaWdodDUgKyBsZWZ0OCAqIHJpZ2h0NjsKICAgICAgICBjb25zdCBjb2x1bW4xUm93MSA9IGxlZnQxICogcmlnaHQ0ICsgbGVmdDUgKiByaWdodDUgKyBsZWZ0OSAqIHJpZ2h0NjsKICAgICAgICBjb25zdCBjb2x1bW4xUm93MiA9IGxlZnQyICogcmlnaHQ0ICsgbGVmdDYgKiByaWdodDUgKyBsZWZ0MTAgKiByaWdodDY7CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzAgPSBsZWZ0MCAqIHJpZ2h0OCArIGxlZnQ0ICogcmlnaHQ5ICsgbGVmdDggKiByaWdodDEwOwogICAgICAgIGNvbnN0IGNvbHVtbjJSb3cxID0gbGVmdDEgKiByaWdodDggKyBsZWZ0NSAqIHJpZ2h0OSArIGxlZnQ5ICogcmlnaHQxMDsKICAgICAgICBjb25zdCBjb2x1bW4yUm93MiA9IGxlZnQyICogcmlnaHQ4ICsgbGVmdDYgKiByaWdodDkgKyBsZWZ0MTAgKiByaWdodDEwOwogICAgICAgIGNvbnN0IGNvbHVtbjNSb3cwID0gbGVmdDAgKiByaWdodDEyICsgbGVmdDQgKiByaWdodDEzICsgbGVmdDggKiByaWdodDE0ICsgbGVmdDEyOwogICAgICAgIGNvbnN0IGNvbHVtbjNSb3cxID0gbGVmdDEgKiByaWdodDEyICsgbGVmdDUgKiByaWdodDEzICsgbGVmdDkgKiByaWdodDE0ICsgbGVmdDEzOwogICAgICAgIGNvbnN0IGNvbHVtbjNSb3cyID0gbGVmdDIgKiByaWdodDEyICsgbGVmdDYgKiByaWdodDEzICsgbGVmdDEwICogcmlnaHQxNCArIGxlZnQxNDsKICAgICAgICByZXN1bHRbMF0gPSBjb2x1bW4wUm93MDsKICAgICAgICByZXN1bHRbMV0gPSBjb2x1bW4wUm93MTsKICAgICAgICByZXN1bHRbMl0gPSBjb2x1bW4wUm93MjsKICAgICAgICByZXN1bHRbM10gPSAwOwogICAgICAgIHJlc3VsdFs0XSA9IGNvbHVtbjFSb3cwOwogICAgICAgIHJlc3VsdFs1XSA9IGNvbHVtbjFSb3cxOwogICAgICAgIHJlc3VsdFs2XSA9IGNvbHVtbjFSb3cyOwogICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgcmVzdWx0WzhdID0gY29sdW1uMlJvdzA7CiAgICAgICAgcmVzdWx0WzldID0gY29sdW1uMlJvdzE7CiAgICAgICAgcmVzdWx0WzEwXSA9IGNvbHVtbjJSb3cyOwogICAgICAgIHJlc3VsdFsxMV0gPSAwOwogICAgICAgIHJlc3VsdFsxMl0gPSBjb2x1bW4zUm93MDsKICAgICAgICByZXN1bHRbMTNdID0gY29sdW1uM1JvdzE7CiAgICAgICAgcmVzdWx0WzE0XSA9IGNvbHVtbjNSb3cyOwogICAgICAgIHJlc3VsdFsxNV0gPSAxOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQubXVsdGlwbHlCeU1hdHJpeDMgPSBmdW5jdGlvbihtYXRyaXgsIHJvdGF0aW9uLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyb3RhdGlvbiIsIHJvdGF0aW9uKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgbGVmdDAgPSBtYXRyaXhbMF07CiAgICAgICAgY29uc3QgbGVmdDEgPSBtYXRyaXhbMV07CiAgICAgICAgY29uc3QgbGVmdDIgPSBtYXRyaXhbMl07CiAgICAgICAgY29uc3QgbGVmdDQgPSBtYXRyaXhbNF07CiAgICAgICAgY29uc3QgbGVmdDUgPSBtYXRyaXhbNV07CiAgICAgICAgY29uc3QgbGVmdDYgPSBtYXRyaXhbNl07CiAgICAgICAgY29uc3QgbGVmdDggPSBtYXRyaXhbOF07CiAgICAgICAgY29uc3QgbGVmdDkgPSBtYXRyaXhbOV07CiAgICAgICAgY29uc3QgbGVmdDEwID0gbWF0cml4WzEwXTsKICAgICAgICBjb25zdCByaWdodDAgPSByb3RhdGlvblswXTsKICAgICAgICBjb25zdCByaWdodDEgPSByb3RhdGlvblsxXTsKICAgICAgICBjb25zdCByaWdodDIgPSByb3RhdGlvblsyXTsKICAgICAgICBjb25zdCByaWdodDQgPSByb3RhdGlvblszXTsKICAgICAgICBjb25zdCByaWdodDUgPSByb3RhdGlvbls0XTsKICAgICAgICBjb25zdCByaWdodDYgPSByb3RhdGlvbls1XTsKICAgICAgICBjb25zdCByaWdodDggPSByb3RhdGlvbls2XTsKICAgICAgICBjb25zdCByaWdodDkgPSByb3RhdGlvbls3XTsKICAgICAgICBjb25zdCByaWdodDEwID0gcm90YXRpb25bOF07CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzAgPSBsZWZ0MCAqIHJpZ2h0MCArIGxlZnQ0ICogcmlnaHQxICsgbGVmdDggKiByaWdodDI7CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzEgPSBsZWZ0MSAqIHJpZ2h0MCArIGxlZnQ1ICogcmlnaHQxICsgbGVmdDkgKiByaWdodDI7CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzIgPSBsZWZ0MiAqIHJpZ2h0MCArIGxlZnQ2ICogcmlnaHQxICsgbGVmdDEwICogcmlnaHQyOwogICAgICAgIGNvbnN0IGNvbHVtbjFSb3cwID0gbGVmdDAgKiByaWdodDQgKyBsZWZ0NCAqIHJpZ2h0NSArIGxlZnQ4ICogcmlnaHQ2OwogICAgICAgIGNvbnN0IGNvbHVtbjFSb3cxID0gbGVmdDEgKiByaWdodDQgKyBsZWZ0NSAqIHJpZ2h0NSArIGxlZnQ5ICogcmlnaHQ2OwogICAgICAgIGNvbnN0IGNvbHVtbjFSb3cyID0gbGVmdDIgKiByaWdodDQgKyBsZWZ0NiAqIHJpZ2h0NSArIGxlZnQxMCAqIHJpZ2h0NjsKICAgICAgICBjb25zdCBjb2x1bW4yUm93MCA9IGxlZnQwICogcmlnaHQ4ICsgbGVmdDQgKiByaWdodDkgKyBsZWZ0OCAqIHJpZ2h0MTA7CiAgICAgICAgY29uc3QgY29sdW1uMlJvdzEgPSBsZWZ0MSAqIHJpZ2h0OCArIGxlZnQ1ICogcmlnaHQ5ICsgbGVmdDkgKiByaWdodDEwOwogICAgICAgIGNvbnN0IGNvbHVtbjJSb3cyID0gbGVmdDIgKiByaWdodDggKyBsZWZ0NiAqIHJpZ2h0OSArIGxlZnQxMCAqIHJpZ2h0MTA7CiAgICAgICAgcmVzdWx0WzBdID0gY29sdW1uMFJvdzA7CiAgICAgICAgcmVzdWx0WzFdID0gY29sdW1uMFJvdzE7CiAgICAgICAgcmVzdWx0WzJdID0gY29sdW1uMFJvdzI7CiAgICAgICAgcmVzdWx0WzNdID0gMDsKICAgICAgICByZXN1bHRbNF0gPSBjb2x1bW4xUm93MDsKICAgICAgICByZXN1bHRbNV0gPSBjb2x1bW4xUm93MTsKICAgICAgICByZXN1bHRbNl0gPSBjb2x1bW4xUm93MjsKICAgICAgICByZXN1bHRbN10gPSAwOwogICAgICAgIHJlc3VsdFs4XSA9IGNvbHVtbjJSb3cwOwogICAgICAgIHJlc3VsdFs5XSA9IGNvbHVtbjJSb3cxOwogICAgICAgIHJlc3VsdFsxMF0gPSBjb2x1bW4yUm93MjsKICAgICAgICByZXN1bHRbMTFdID0gMDsKICAgICAgICByZXN1bHRbMTJdID0gbWF0cml4WzEyXTsKICAgICAgICByZXN1bHRbMTNdID0gbWF0cml4WzEzXTsKICAgICAgICByZXN1bHRbMTRdID0gbWF0cml4WzE0XTsKICAgICAgICByZXN1bHRbMTVdID0gbWF0cml4WzE1XTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0Lm11bHRpcGx5QnlUcmFuc2xhdGlvbiA9IGZ1bmN0aW9uKG1hdHJpeCwgdHJhbnNsYXRpb24yLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJ0cmFuc2xhdGlvbiIsIHRyYW5zbGF0aW9uMik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHggPSB0cmFuc2xhdGlvbjIueDsKICAgICAgICBjb25zdCB5ID0gdHJhbnNsYXRpb24yLnk7CiAgICAgICAgY29uc3QgeiA9IHRyYW5zbGF0aW9uMi56OwogICAgICAgIGNvbnN0IHR4ID0geCAqIG1hdHJpeFswXSArIHkgKiBtYXRyaXhbNF0gKyB6ICogbWF0cml4WzhdICsgbWF0cml4WzEyXTsKICAgICAgICBjb25zdCB0eSA9IHggKiBtYXRyaXhbMV0gKyB5ICogbWF0cml4WzVdICsgeiAqIG1hdHJpeFs5XSArIG1hdHJpeFsxM107CiAgICAgICAgY29uc3QgdHogPSB4ICogbWF0cml4WzJdICsgeSAqIG1hdHJpeFs2XSArIHogKiBtYXRyaXhbMTBdICsgbWF0cml4WzE0XTsKICAgICAgICByZXN1bHRbMF0gPSBtYXRyaXhbMF07CiAgICAgICAgcmVzdWx0WzFdID0gbWF0cml4WzFdOwogICAgICAgIHJlc3VsdFsyXSA9IG1hdHJpeFsyXTsKICAgICAgICByZXN1bHRbM10gPSBtYXRyaXhbM107CiAgICAgICAgcmVzdWx0WzRdID0gbWF0cml4WzRdOwogICAgICAgIHJlc3VsdFs1XSA9IG1hdHJpeFs1XTsKICAgICAgICByZXN1bHRbNl0gPSBtYXRyaXhbNl07CiAgICAgICAgcmVzdWx0WzddID0gbWF0cml4WzddOwogICAgICAgIHJlc3VsdFs4XSA9IG1hdHJpeFs4XTsKICAgICAgICByZXN1bHRbOV0gPSBtYXRyaXhbOV07CiAgICAgICAgcmVzdWx0WzEwXSA9IG1hdHJpeFsxMF07CiAgICAgICAgcmVzdWx0WzExXSA9IG1hdHJpeFsxMV07CiAgICAgICAgcmVzdWx0WzEyXSA9IHR4OwogICAgICAgIHJlc3VsdFsxM10gPSB0eTsKICAgICAgICByZXN1bHRbMTRdID0gdHo7CiAgICAgICAgcmVzdWx0WzE1XSA9IG1hdHJpeFsxNV07CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC5tdWx0aXBseUJ5U2NhbGUgPSBmdW5jdGlvbihtYXRyaXgsIHNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzY2FsZSIsIHNjYWxlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3Qgc2NhbGVYID0gc2NhbGUueDsKICAgICAgICBjb25zdCBzY2FsZVkgPSBzY2FsZS55OwogICAgICAgIGNvbnN0IHNjYWxlWiA9IHNjYWxlLno7CiAgICAgICAgaWYgKHNjYWxlWCA9PT0gMSAmJiBzY2FsZVkgPT09IDEgJiYgc2NhbGVaID09PSAxKSB7CiAgICAgICAgICByZXR1cm4gTWF0cml4NC5jbG9uZShtYXRyaXgsIHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IHNjYWxlWCAqIG1hdHJpeFswXTsKICAgICAgICByZXN1bHRbMV0gPSBzY2FsZVggKiBtYXRyaXhbMV07CiAgICAgICAgcmVzdWx0WzJdID0gc2NhbGVYICogbWF0cml4WzJdOwogICAgICAgIHJlc3VsdFszXSA9IG1hdHJpeFszXTsKICAgICAgICByZXN1bHRbNF0gPSBzY2FsZVkgKiBtYXRyaXhbNF07CiAgICAgICAgcmVzdWx0WzVdID0gc2NhbGVZICogbWF0cml4WzVdOwogICAgICAgIHJlc3VsdFs2XSA9IHNjYWxlWSAqIG1hdHJpeFs2XTsKICAgICAgICByZXN1bHRbN10gPSBtYXRyaXhbN107CiAgICAgICAgcmVzdWx0WzhdID0gc2NhbGVaICogbWF0cml4WzhdOwogICAgICAgIHJlc3VsdFs5XSA9IHNjYWxlWiAqIG1hdHJpeFs5XTsKICAgICAgICByZXN1bHRbMTBdID0gc2NhbGVaICogbWF0cml4WzEwXTsKICAgICAgICByZXN1bHRbMTFdID0gbWF0cml4WzExXTsKICAgICAgICByZXN1bHRbMTJdID0gbWF0cml4WzEyXTsKICAgICAgICByZXN1bHRbMTNdID0gbWF0cml4WzEzXTsKICAgICAgICByZXN1bHRbMTRdID0gbWF0cml4WzE0XTsKICAgICAgICByZXN1bHRbMTVdID0gbWF0cml4WzE1XTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0Lm11bHRpcGx5QnlVbmlmb3JtU2NhbGUgPSBmdW5jdGlvbihtYXRyaXgsIHNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJzY2FsZSIsIHNjYWxlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4WzBdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzFdID0gbWF0cml4WzFdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzJdID0gbWF0cml4WzJdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzNdOwogICAgICAgIHJlc3VsdFs0XSA9IG1hdHJpeFs0XSAqIHNjYWxlOwogICAgICAgIHJlc3VsdFs1XSA9IG1hdHJpeFs1XSAqIHNjYWxlOwogICAgICAgIHJlc3VsdFs2XSA9IG1hdHJpeFs2XSAqIHNjYWxlOwogICAgICAgIHJlc3VsdFs3XSA9IG1hdHJpeFs3XTsKICAgICAgICByZXN1bHRbOF0gPSBtYXRyaXhbOF0gKiBzY2FsZTsKICAgICAgICByZXN1bHRbOV0gPSBtYXRyaXhbOV0gKiBzY2FsZTsKICAgICAgICByZXN1bHRbMTBdID0gbWF0cml4WzEwXSAqIHNjYWxlOwogICAgICAgIHJlc3VsdFsxMV0gPSBtYXRyaXhbMTFdOwogICAgICAgIHJlc3VsdFsxMl0gPSBtYXRyaXhbMTJdOwogICAgICAgIHJlc3VsdFsxM10gPSBtYXRyaXhbMTNdOwogICAgICAgIHJlc3VsdFsxNF0gPSBtYXRyaXhbMTRdOwogICAgICAgIHJlc3VsdFsxNV0gPSBtYXRyaXhbMTVdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQubXVsdGlwbHlCeVZlY3RvciA9IGZ1bmN0aW9uKG1hdHJpeCwgY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgdlggPSBjYXJ0ZXNpYW4xMS54OwogICAgICAgIGNvbnN0IHZZID0gY2FydGVzaWFuMTEueTsKICAgICAgICBjb25zdCB2WiA9IGNhcnRlc2lhbjExLno7CiAgICAgICAgY29uc3QgdlcgPSBjYXJ0ZXNpYW4xMS53OwogICAgICAgIGNvbnN0IHggPSBtYXRyaXhbMF0gKiB2WCArIG1hdHJpeFs0XSAqIHZZICsgbWF0cml4WzhdICogdlogKyBtYXRyaXhbMTJdICogdlc7CiAgICAgICAgY29uc3QgeSA9IG1hdHJpeFsxXSAqIHZYICsgbWF0cml4WzVdICogdlkgKyBtYXRyaXhbOV0gKiB2WiArIG1hdHJpeFsxM10gKiB2VzsKICAgICAgICBjb25zdCB6ID0gbWF0cml4WzJdICogdlggKyBtYXRyaXhbNl0gKiB2WSArIG1hdHJpeFsxMF0gKiB2WiArIG1hdHJpeFsxNF0gKiB2VzsKICAgICAgICBjb25zdCB3ID0gbWF0cml4WzNdICogdlggKyBtYXRyaXhbN10gKiB2WSArIG1hdHJpeFsxMV0gKiB2WiArIG1hdHJpeFsxNV0gKiB2VzsKICAgICAgICByZXN1bHQueCA9IHg7CiAgICAgICAgcmVzdWx0LnkgPSB5OwogICAgICAgIHJlc3VsdC56ID0gejsKICAgICAgICByZXN1bHQudyA9IHc7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC5tdWx0aXBseUJ5UG9pbnRBc1ZlY3RvciA9IGZ1bmN0aW9uKG1hdHJpeCwgY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgdlggPSBjYXJ0ZXNpYW4xMS54OwogICAgICAgIGNvbnN0IHZZID0gY2FydGVzaWFuMTEueTsKICAgICAgICBjb25zdCB2WiA9IGNhcnRlc2lhbjExLno7CiAgICAgICAgY29uc3QgeCA9IG1hdHJpeFswXSAqIHZYICsgbWF0cml4WzRdICogdlkgKyBtYXRyaXhbOF0gKiB2WjsKICAgICAgICBjb25zdCB5ID0gbWF0cml4WzFdICogdlggKyBtYXRyaXhbNV0gKiB2WSArIG1hdHJpeFs5XSAqIHZaOwogICAgICAgIGNvbnN0IHogPSBtYXRyaXhbMl0gKiB2WCArIG1hdHJpeFs2XSAqIHZZICsgbWF0cml4WzEwXSAqIHZaOwogICAgICAgIHJlc3VsdC54ID0geDsKICAgICAgICByZXN1bHQueSA9IHk7CiAgICAgICAgcmVzdWx0LnogPSB6OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQubXVsdGlwbHlCeVBvaW50ID0gZnVuY3Rpb24obWF0cml4LCBjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCB2WCA9IGNhcnRlc2lhbjExLng7CiAgICAgICAgY29uc3QgdlkgPSBjYXJ0ZXNpYW4xMS55OwogICAgICAgIGNvbnN0IHZaID0gY2FydGVzaWFuMTEuejsKICAgICAgICBjb25zdCB4ID0gbWF0cml4WzBdICogdlggKyBtYXRyaXhbNF0gKiB2WSArIG1hdHJpeFs4XSAqIHZaICsgbWF0cml4WzEyXTsKICAgICAgICBjb25zdCB5ID0gbWF0cml4WzFdICogdlggKyBtYXRyaXhbNV0gKiB2WSArIG1hdHJpeFs5XSAqIHZaICsgbWF0cml4WzEzXTsKICAgICAgICBjb25zdCB6ID0gbWF0cml4WzJdICogdlggKyBtYXRyaXhbNl0gKiB2WSArIG1hdHJpeFsxMF0gKiB2WiArIG1hdHJpeFsxNF07CiAgICAgICAgcmVzdWx0LnggPSB4OwogICAgICAgIHJlc3VsdC55ID0geTsKICAgICAgICByZXN1bHQueiA9IHo7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC5tdWx0aXBseUJ5U2NhbGFyID0gZnVuY3Rpb24obWF0cml4LCBzY2FsYXIsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInNjYWxhciIsIHNjYWxhcik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdFswXSA9IG1hdHJpeFswXSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbMV0gPSBtYXRyaXhbMV0gKiBzY2FsYXI7CiAgICAgICAgcmVzdWx0WzJdID0gbWF0cml4WzJdICogc2NhbGFyOwogICAgICAgIHJlc3VsdFszXSA9IG1hdHJpeFszXSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbNF0gPSBtYXRyaXhbNF0gKiBzY2FsYXI7CiAgICAgICAgcmVzdWx0WzVdID0gbWF0cml4WzVdICogc2NhbGFyOwogICAgICAgIHJlc3VsdFs2XSA9IG1hdHJpeFs2XSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbN10gPSBtYXRyaXhbN10gKiBzY2FsYXI7CiAgICAgICAgcmVzdWx0WzhdID0gbWF0cml4WzhdICogc2NhbGFyOwogICAgICAgIHJlc3VsdFs5XSA9IG1hdHJpeFs5XSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbMTBdID0gbWF0cml4WzEwXSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbMTFdID0gbWF0cml4WzExXSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbMTJdID0gbWF0cml4WzEyXSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbMTNdID0gbWF0cml4WzEzXSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbMTRdID0gbWF0cml4WzE0XSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbMTVdID0gbWF0cml4WzE1XSAqIHNjYWxhcjsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0Lm5lZ2F0ZSA9IGZ1bmN0aW9uKG1hdHJpeCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHRbMF0gPSAtbWF0cml4WzBdOwogICAgICAgIHJlc3VsdFsxXSA9IC1tYXRyaXhbMV07CiAgICAgICAgcmVzdWx0WzJdID0gLW1hdHJpeFsyXTsKICAgICAgICByZXN1bHRbM10gPSAtbWF0cml4WzNdOwogICAgICAgIHJlc3VsdFs0XSA9IC1tYXRyaXhbNF07CiAgICAgICAgcmVzdWx0WzVdID0gLW1hdHJpeFs1XTsKICAgICAgICByZXN1bHRbNl0gPSAtbWF0cml4WzZdOwogICAgICAgIHJlc3VsdFs3XSA9IC1tYXRyaXhbN107CiAgICAgICAgcmVzdWx0WzhdID0gLW1hdHJpeFs4XTsKICAgICAgICByZXN1bHRbOV0gPSAtbWF0cml4WzldOwogICAgICAgIHJlc3VsdFsxMF0gPSAtbWF0cml4WzEwXTsKICAgICAgICByZXN1bHRbMTFdID0gLW1hdHJpeFsxMV07CiAgICAgICAgcmVzdWx0WzEyXSA9IC1tYXRyaXhbMTJdOwogICAgICAgIHJlc3VsdFsxM10gPSAtbWF0cml4WzEzXTsKICAgICAgICByZXN1bHRbMTRdID0gLW1hdHJpeFsxNF07CiAgICAgICAgcmVzdWx0WzE1XSA9IC1tYXRyaXhbMTVdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQudHJhbnNwb3NlID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IG1hdHJpeDEgPSBtYXRyaXhbMV07CiAgICAgICAgY29uc3QgbWF0cml4MiA9IG1hdHJpeFsyXTsKICAgICAgICBjb25zdCBtYXRyaXgzID0gbWF0cml4WzNdOwogICAgICAgIGNvbnN0IG1hdHJpeDYgPSBtYXRyaXhbNl07CiAgICAgICAgY29uc3QgbWF0cml4NyA9IG1hdHJpeFs3XTsKICAgICAgICBjb25zdCBtYXRyaXgxMSA9IG1hdHJpeFsxMV07CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4WzBdOwogICAgICAgIHJlc3VsdFsxXSA9IG1hdHJpeFs0XTsKICAgICAgICByZXN1bHRbMl0gPSBtYXRyaXhbOF07CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzEyXTsKICAgICAgICByZXN1bHRbNF0gPSBtYXRyaXgxOwogICAgICAgIHJlc3VsdFs1XSA9IG1hdHJpeFs1XTsKICAgICAgICByZXN1bHRbNl0gPSBtYXRyaXhbOV07CiAgICAgICAgcmVzdWx0WzddID0gbWF0cml4WzEzXTsKICAgICAgICByZXN1bHRbOF0gPSBtYXRyaXgyOwogICAgICAgIHJlc3VsdFs5XSA9IG1hdHJpeDY7CiAgICAgICAgcmVzdWx0WzEwXSA9IG1hdHJpeFsxMF07CiAgICAgICAgcmVzdWx0WzExXSA9IG1hdHJpeFsxNF07CiAgICAgICAgcmVzdWx0WzEyXSA9IG1hdHJpeDM7CiAgICAgICAgcmVzdWx0WzEzXSA9IG1hdHJpeDc7CiAgICAgICAgcmVzdWx0WzE0XSA9IG1hdHJpeDExOwogICAgICAgIHJlc3VsdFsxNV0gPSBtYXRyaXhbMTVdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDQuYWJzID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdFswXSA9IE1hdGguYWJzKG1hdHJpeFswXSk7CiAgICAgICAgcmVzdWx0WzFdID0gTWF0aC5hYnMobWF0cml4WzFdKTsKICAgICAgICByZXN1bHRbMl0gPSBNYXRoLmFicyhtYXRyaXhbMl0pOwogICAgICAgIHJlc3VsdFszXSA9IE1hdGguYWJzKG1hdHJpeFszXSk7CiAgICAgICAgcmVzdWx0WzRdID0gTWF0aC5hYnMobWF0cml4WzRdKTsKICAgICAgICByZXN1bHRbNV0gPSBNYXRoLmFicyhtYXRyaXhbNV0pOwogICAgICAgIHJlc3VsdFs2XSA9IE1hdGguYWJzKG1hdHJpeFs2XSk7CiAgICAgICAgcmVzdWx0WzddID0gTWF0aC5hYnMobWF0cml4WzddKTsKICAgICAgICByZXN1bHRbOF0gPSBNYXRoLmFicyhtYXRyaXhbOF0pOwogICAgICAgIHJlc3VsdFs5XSA9IE1hdGguYWJzKG1hdHJpeFs5XSk7CiAgICAgICAgcmVzdWx0WzEwXSA9IE1hdGguYWJzKG1hdHJpeFsxMF0pOwogICAgICAgIHJlc3VsdFsxMV0gPSBNYXRoLmFicyhtYXRyaXhbMTFdKTsKICAgICAgICByZXN1bHRbMTJdID0gTWF0aC5hYnMobWF0cml4WzEyXSk7CiAgICAgICAgcmVzdWx0WzEzXSA9IE1hdGguYWJzKG1hdHJpeFsxM10pOwogICAgICAgIHJlc3VsdFsxNF0gPSBNYXRoLmFicyhtYXRyaXhbMTRdKTsKICAgICAgICByZXN1bHRbMTVdID0gTWF0aC5hYnMobWF0cml4WzE1XSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC5lcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiAvLyBUcmFuc2xhdGlvbgogICAgICAgIGxlZnRbMTJdID09PSByaWdodFsxMl0gJiYgbGVmdFsxM10gPT09IHJpZ2h0WzEzXSAmJiBsZWZ0WzE0XSA9PT0gcmlnaHRbMTRdICYmIC8vIFJvdGF0aW9uL3NjYWxlCiAgICAgICAgbGVmdFswXSA9PT0gcmlnaHRbMF0gJiYgbGVmdFsxXSA9PT0gcmlnaHRbMV0gJiYgbGVmdFsyXSA9PT0gcmlnaHRbMl0gJiYgbGVmdFs0XSA9PT0gcmlnaHRbNF0gJiYgbGVmdFs1XSA9PT0gcmlnaHRbNV0gJiYgbGVmdFs2XSA9PT0gcmlnaHRbNl0gJiYgbGVmdFs4XSA9PT0gcmlnaHRbOF0gJiYgbGVmdFs5XSA9PT0gcmlnaHRbOV0gJiYgbGVmdFsxMF0gPT09IHJpZ2h0WzEwXSAmJiAvLyBCb3R0b20gcm93CiAgICAgICAgbGVmdFszXSA9PT0gcmlnaHRbM10gJiYgbGVmdFs3XSA9PT0gcmlnaHRbN10gJiYgbGVmdFsxMV0gPT09IHJpZ2h0WzExXSAmJiBsZWZ0WzE1XSA9PT0gcmlnaHRbMTVdOwogICAgICB9OwogICAgICBNYXRyaXg0LmVxdWFsc0Vwc2lsb24gPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgZXBzaWxvbikgewogICAgICAgIGVwc2lsb24gPSBlcHNpbG9uID8/IDA7CiAgICAgICAgcmV0dXJuIGxlZnQgPT09IHJpZ2h0IHx8IGRlZmluZWRfZGVmYXVsdChsZWZ0KSAmJiBkZWZpbmVkX2RlZmF1bHQocmlnaHQpICYmIE1hdGguYWJzKGxlZnRbMF0gLSByaWdodFswXSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzFdIC0gcmlnaHRbMV0pIDw9IGVwc2lsb24gJiYgTWF0aC5hYnMobGVmdFsyXSAtIHJpZ2h0WzJdKSA8PSBlcHNpbG9uICYmIE1hdGguYWJzKGxlZnRbM10gLSByaWdodFszXSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzRdIC0gcmlnaHRbNF0pIDw9IGVwc2lsb24gJiYgTWF0aC5hYnMobGVmdFs1XSAtIHJpZ2h0WzVdKSA8PSBlcHNpbG9uICYmIE1hdGguYWJzKGxlZnRbNl0gLSByaWdodFs2XSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzddIC0gcmlnaHRbN10pIDw9IGVwc2lsb24gJiYgTWF0aC5hYnMobGVmdFs4XSAtIHJpZ2h0WzhdKSA8PSBlcHNpbG9uICYmIE1hdGguYWJzKGxlZnRbOV0gLSByaWdodFs5XSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzEwXSAtIHJpZ2h0WzEwXSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzExXSAtIHJpZ2h0WzExXSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzEyXSAtIHJpZ2h0WzEyXSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzEzXSAtIHJpZ2h0WzEzXSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzE0XSAtIHJpZ2h0WzE0XSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzE1XSAtIHJpZ2h0WzE1XSkgPD0gZXBzaWxvbjsKICAgICAgfTsKICAgICAgTWF0cml4NC5nZXRUcmFuc2xhdGlvbiA9IGZ1bmN0aW9uKG1hdHJpeCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQueCA9IG1hdHJpeFsxMl07CiAgICAgICAgcmVzdWx0LnkgPSBtYXRyaXhbMTNdOwogICAgICAgIHJlc3VsdC56ID0gbWF0cml4WzE0XTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXg0LmdldE1hdHJpeDMgPSBmdW5jdGlvbihtYXRyaXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4WzBdOwogICAgICAgIHJlc3VsdFsxXSA9IG1hdHJpeFsxXTsKICAgICAgICByZXN1bHRbMl0gPSBtYXRyaXhbMl07CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzRdOwogICAgICAgIHJlc3VsdFs0XSA9IG1hdHJpeFs1XTsKICAgICAgICByZXN1bHRbNV0gPSBtYXRyaXhbNl07CiAgICAgICAgcmVzdWx0WzZdID0gbWF0cml4WzhdOwogICAgICAgIHJlc3VsdFs3XSA9IG1hdHJpeFs5XTsKICAgICAgICByZXN1bHRbOF0gPSBtYXRyaXhbMTBdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hJbnZlcnNlUm90YXRpb24gPSBuZXcgTWF0cml4M19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hNYXRyaXgzWmVybyA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEJvdHRvbVJvdyA9IG5ldyBDYXJ0ZXNpYW40X2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEV4cGVjdGVkQm90dG9tUm93ID0gbmV3IENhcnRlc2lhbjRfZGVmYXVsdCgwLCAwLCAwLCAxKTsKICAgICAgTWF0cml4NC5pbnZlcnNlID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHNyYzAgPSBtYXRyaXhbMF07CiAgICAgICAgY29uc3Qgc3JjMSA9IG1hdHJpeFs0XTsKICAgICAgICBjb25zdCBzcmMyID0gbWF0cml4WzhdOwogICAgICAgIGNvbnN0IHNyYzMgPSBtYXRyaXhbMTJdOwogICAgICAgIGNvbnN0IHNyYzQgPSBtYXRyaXhbMV07CiAgICAgICAgY29uc3Qgc3JjNSA9IG1hdHJpeFs1XTsKICAgICAgICBjb25zdCBzcmM2ID0gbWF0cml4WzldOwogICAgICAgIGNvbnN0IHNyYzcgPSBtYXRyaXhbMTNdOwogICAgICAgIGNvbnN0IHNyYzggPSBtYXRyaXhbMl07CiAgICAgICAgY29uc3Qgc3JjOSA9IG1hdHJpeFs2XTsKICAgICAgICBjb25zdCBzcmMxMCA9IG1hdHJpeFsxMF07CiAgICAgICAgY29uc3Qgc3JjMTEgPSBtYXRyaXhbMTRdOwogICAgICAgIGNvbnN0IHNyYzEyID0gbWF0cml4WzNdOwogICAgICAgIGNvbnN0IHNyYzEzID0gbWF0cml4WzddOwogICAgICAgIGNvbnN0IHNyYzE0ID0gbWF0cml4WzExXTsKICAgICAgICBjb25zdCBzcmMxNSA9IG1hdHJpeFsxNV07CiAgICAgICAgbGV0IHRtcDAgPSBzcmMxMCAqIHNyYzE1OwogICAgICAgIGxldCB0bXAxID0gc3JjMTEgKiBzcmMxNDsKICAgICAgICBsZXQgdG1wMiA9IHNyYzkgKiBzcmMxNTsKICAgICAgICBsZXQgdG1wMyA9IHNyYzExICogc3JjMTM7CiAgICAgICAgbGV0IHRtcDQgPSBzcmM5ICogc3JjMTQ7CiAgICAgICAgbGV0IHRtcDUgPSBzcmMxMCAqIHNyYzEzOwogICAgICAgIGxldCB0bXA2ID0gc3JjOCAqIHNyYzE1OwogICAgICAgIGxldCB0bXA3ID0gc3JjMTEgKiBzcmMxMjsKICAgICAgICBsZXQgdG1wOCA9IHNyYzggKiBzcmMxNDsKICAgICAgICBsZXQgdG1wOSA9IHNyYzEwICogc3JjMTI7CiAgICAgICAgbGV0IHRtcDEwID0gc3JjOCAqIHNyYzEzOwogICAgICAgIGxldCB0bXAxMSA9IHNyYzkgKiBzcmMxMjsKICAgICAgICBjb25zdCBkc3QwID0gdG1wMCAqIHNyYzUgKyB0bXAzICogc3JjNiArIHRtcDQgKiBzcmM3IC0gKHRtcDEgKiBzcmM1ICsgdG1wMiAqIHNyYzYgKyB0bXA1ICogc3JjNyk7CiAgICAgICAgY29uc3QgZHN0MSA9IHRtcDEgKiBzcmM0ICsgdG1wNiAqIHNyYzYgKyB0bXA5ICogc3JjNyAtICh0bXAwICogc3JjNCArIHRtcDcgKiBzcmM2ICsgdG1wOCAqIHNyYzcpOwogICAgICAgIGNvbnN0IGRzdDIgPSB0bXAyICogc3JjNCArIHRtcDcgKiBzcmM1ICsgdG1wMTAgKiBzcmM3IC0gKHRtcDMgKiBzcmM0ICsgdG1wNiAqIHNyYzUgKyB0bXAxMSAqIHNyYzcpOwogICAgICAgIGNvbnN0IGRzdDMgPSB0bXA1ICogc3JjNCArIHRtcDggKiBzcmM1ICsgdG1wMTEgKiBzcmM2IC0gKHRtcDQgKiBzcmM0ICsgdG1wOSAqIHNyYzUgKyB0bXAxMCAqIHNyYzYpOwogICAgICAgIGNvbnN0IGRzdDQgPSB0bXAxICogc3JjMSArIHRtcDIgKiBzcmMyICsgdG1wNSAqIHNyYzMgLSAodG1wMCAqIHNyYzEgKyB0bXAzICogc3JjMiArIHRtcDQgKiBzcmMzKTsKICAgICAgICBjb25zdCBkc3Q1ID0gdG1wMCAqIHNyYzAgKyB0bXA3ICogc3JjMiArIHRtcDggKiBzcmMzIC0gKHRtcDEgKiBzcmMwICsgdG1wNiAqIHNyYzIgKyB0bXA5ICogc3JjMyk7CiAgICAgICAgY29uc3QgZHN0NiA9IHRtcDMgKiBzcmMwICsgdG1wNiAqIHNyYzEgKyB0bXAxMSAqIHNyYzMgLSAodG1wMiAqIHNyYzAgKyB0bXA3ICogc3JjMSArIHRtcDEwICogc3JjMyk7CiAgICAgICAgY29uc3QgZHN0NyA9IHRtcDQgKiBzcmMwICsgdG1wOSAqIHNyYzEgKyB0bXAxMCAqIHNyYzIgLSAodG1wNSAqIHNyYzAgKyB0bXA4ICogc3JjMSArIHRtcDExICogc3JjMik7CiAgICAgICAgdG1wMCA9IHNyYzIgKiBzcmM3OwogICAgICAgIHRtcDEgPSBzcmMzICogc3JjNjsKICAgICAgICB0bXAyID0gc3JjMSAqIHNyYzc7CiAgICAgICAgdG1wMyA9IHNyYzMgKiBzcmM1OwogICAgICAgIHRtcDQgPSBzcmMxICogc3JjNjsKICAgICAgICB0bXA1ID0gc3JjMiAqIHNyYzU7CiAgICAgICAgdG1wNiA9IHNyYzAgKiBzcmM3OwogICAgICAgIHRtcDcgPSBzcmMzICogc3JjNDsKICAgICAgICB0bXA4ID0gc3JjMCAqIHNyYzY7CiAgICAgICAgdG1wOSA9IHNyYzIgKiBzcmM0OwogICAgICAgIHRtcDEwID0gc3JjMCAqIHNyYzU7CiAgICAgICAgdG1wMTEgPSBzcmMxICogc3JjNDsKICAgICAgICBjb25zdCBkc3Q4ID0gdG1wMCAqIHNyYzEzICsgdG1wMyAqIHNyYzE0ICsgdG1wNCAqIHNyYzE1IC0gKHRtcDEgKiBzcmMxMyArIHRtcDIgKiBzcmMxNCArIHRtcDUgKiBzcmMxNSk7CiAgICAgICAgY29uc3QgZHN0OSA9IHRtcDEgKiBzcmMxMiArIHRtcDYgKiBzcmMxNCArIHRtcDkgKiBzcmMxNSAtICh0bXAwICogc3JjMTIgKyB0bXA3ICogc3JjMTQgKyB0bXA4ICogc3JjMTUpOwogICAgICAgIGNvbnN0IGRzdDEwID0gdG1wMiAqIHNyYzEyICsgdG1wNyAqIHNyYzEzICsgdG1wMTAgKiBzcmMxNSAtICh0bXAzICogc3JjMTIgKyB0bXA2ICogc3JjMTMgKyB0bXAxMSAqIHNyYzE1KTsKICAgICAgICBjb25zdCBkc3QxMSA9IHRtcDUgKiBzcmMxMiArIHRtcDggKiBzcmMxMyArIHRtcDExICogc3JjMTQgLSAodG1wNCAqIHNyYzEyICsgdG1wOSAqIHNyYzEzICsgdG1wMTAgKiBzcmMxNCk7CiAgICAgICAgY29uc3QgZHN0MTIgPSB0bXAyICogc3JjMTAgKyB0bXA1ICogc3JjMTEgKyB0bXAxICogc3JjOSAtICh0bXA0ICogc3JjMTEgKyB0bXAwICogc3JjOSArIHRtcDMgKiBzcmMxMCk7CiAgICAgICAgY29uc3QgZHN0MTMgPSB0bXA4ICogc3JjMTEgKyB0bXAwICogc3JjOCArIHRtcDcgKiBzcmMxMCAtICh0bXA2ICogc3JjMTAgKyB0bXA5ICogc3JjMTEgKyB0bXAxICogc3JjOCk7CiAgICAgICAgY29uc3QgZHN0MTQgPSB0bXA2ICogc3JjOSArIHRtcDExICogc3JjMTEgKyB0bXAzICogc3JjOCAtICh0bXAxMCAqIHNyYzExICsgdG1wMiAqIHNyYzggKyB0bXA3ICogc3JjOSk7CiAgICAgICAgY29uc3QgZHN0MTUgPSB0bXAxMCAqIHNyYzEwICsgdG1wNCAqIHNyYzggKyB0bXA5ICogc3JjOSAtICh0bXA4ICogc3JjOSArIHRtcDExICogc3JjMTAgKyB0bXA1ICogc3JjOCk7CiAgICAgICAgbGV0IGRldCA9IHNyYzAgKiBkc3QwICsgc3JjMSAqIGRzdDEgKyBzcmMyICogZHN0MiArIHNyYzMgKiBkc3QzOwogICAgICAgIGlmIChNYXRoLmFicyhkZXQpIDwgTWF0aF9kZWZhdWx0LkVQU0lMT04yMSkgewogICAgICAgICAgaWYgKE1hdHJpeDNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgICBNYXRyaXg0LmdldE1hdHJpeDMobWF0cml4LCBzY3JhdGNoSW52ZXJzZVJvdGF0aW9uKSwKICAgICAgICAgICAgc2NyYXRjaE1hdHJpeDNaZXJvLAogICAgICAgICAgICBNYXRoX2RlZmF1bHQuRVBTSUxPTjcKICAgICAgICAgICkgJiYgQ2FydGVzaWFuNF9kZWZhdWx0LmVxdWFscygKICAgICAgICAgICAgTWF0cml4NC5nZXRSb3cobWF0cml4LCAzLCBzY3JhdGNoQm90dG9tUm93KSwKICAgICAgICAgICAgc2NyYXRjaEV4cGVjdGVkQm90dG9tUm93CiAgICAgICAgICApKSB7CiAgICAgICAgICAgIHJlc3VsdFswXSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFsxXSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFsyXSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFs0XSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFs1XSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFs2XSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFs4XSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFs5XSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFsxMF0gPSAwOwogICAgICAgICAgICByZXN1bHRbMTFdID0gMDsKICAgICAgICAgICAgcmVzdWx0WzEyXSA9IC1tYXRyaXhbMTJdOwogICAgICAgICAgICByZXN1bHRbMTNdID0gLW1hdHJpeFsxM107CiAgICAgICAgICAgIHJlc3VsdFsxNF0gPSAtbWF0cml4WzE0XTsKICAgICAgICAgICAgcmVzdWx0WzE1XSA9IDE7CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICB9CiAgICAgICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJtYXRyaXggaXMgbm90IGludmVydGlibGUgYmVjYXVzZSBpdHMgZGV0ZXJtaW5hdGUgaXMgemVyby4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBkZXQgPSAxIC8gZGV0OwogICAgICAgIHJlc3VsdFswXSA9IGRzdDAgKiBkZXQ7CiAgICAgICAgcmVzdWx0WzFdID0gZHN0MSAqIGRldDsKICAgICAgICByZXN1bHRbMl0gPSBkc3QyICogZGV0OwogICAgICAgIHJlc3VsdFszXSA9IGRzdDMgKiBkZXQ7CiAgICAgICAgcmVzdWx0WzRdID0gZHN0NCAqIGRldDsKICAgICAgICByZXN1bHRbNV0gPSBkc3Q1ICogZGV0OwogICAgICAgIHJlc3VsdFs2XSA9IGRzdDYgKiBkZXQ7CiAgICAgICAgcmVzdWx0WzddID0gZHN0NyAqIGRldDsKICAgICAgICByZXN1bHRbOF0gPSBkc3Q4ICogZGV0OwogICAgICAgIHJlc3VsdFs5XSA9IGRzdDkgKiBkZXQ7CiAgICAgICAgcmVzdWx0WzEwXSA9IGRzdDEwICogZGV0OwogICAgICAgIHJlc3VsdFsxMV0gPSBkc3QxMSAqIGRldDsKICAgICAgICByZXN1bHRbMTJdID0gZHN0MTIgKiBkZXQ7CiAgICAgICAgcmVzdWx0WzEzXSA9IGRzdDEzICogZGV0OwogICAgICAgIHJlc3VsdFsxNF0gPSBkc3QxNCAqIGRldDsKICAgICAgICByZXN1bHRbMTVdID0gZHN0MTUgKiBkZXQ7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4NC5pbnZlcnNlVHJhbnNmb3JtYXRpb24gPSBmdW5jdGlvbihtYXRyaXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgbWF0cml4MCA9IG1hdHJpeFswXTsKICAgICAgICBjb25zdCBtYXRyaXgxID0gbWF0cml4WzFdOwogICAgICAgIGNvbnN0IG1hdHJpeDIgPSBtYXRyaXhbMl07CiAgICAgICAgY29uc3QgbWF0cml4NCA9IG1hdHJpeFs0XTsKICAgICAgICBjb25zdCBtYXRyaXg1ID0gbWF0cml4WzVdOwogICAgICAgIGNvbnN0IG1hdHJpeDYgPSBtYXRyaXhbNl07CiAgICAgICAgY29uc3QgbWF0cml4OCA9IG1hdHJpeFs4XTsKICAgICAgICBjb25zdCBtYXRyaXg5ID0gbWF0cml4WzldOwogICAgICAgIGNvbnN0IG1hdHJpeDEwID0gbWF0cml4WzEwXTsKICAgICAgICBjb25zdCB2WCA9IG1hdHJpeFsxMl07CiAgICAgICAgY29uc3QgdlkgPSBtYXRyaXhbMTNdOwogICAgICAgIGNvbnN0IHZaID0gbWF0cml4WzE0XTsKICAgICAgICBjb25zdCB4ID0gLW1hdHJpeDAgKiB2WCAtIG1hdHJpeDEgKiB2WSAtIG1hdHJpeDIgKiB2WjsKICAgICAgICBjb25zdCB5ID0gLW1hdHJpeDQgKiB2WCAtIG1hdHJpeDUgKiB2WSAtIG1hdHJpeDYgKiB2WjsKICAgICAgICBjb25zdCB6ID0gLW1hdHJpeDggKiB2WCAtIG1hdHJpeDkgKiB2WSAtIG1hdHJpeDEwICogdlo7CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4MDsKICAgICAgICByZXN1bHRbMV0gPSBtYXRyaXg0OwogICAgICAgIHJlc3VsdFsyXSA9IG1hdHJpeDg7CiAgICAgICAgcmVzdWx0WzNdID0gMDsKICAgICAgICByZXN1bHRbNF0gPSBtYXRyaXgxOwogICAgICAgIHJlc3VsdFs1XSA9IG1hdHJpeDU7CiAgICAgICAgcmVzdWx0WzZdID0gbWF0cml4OTsKICAgICAgICByZXN1bHRbN10gPSAwOwogICAgICAgIHJlc3VsdFs4XSA9IG1hdHJpeDI7CiAgICAgICAgcmVzdWx0WzldID0gbWF0cml4NjsKICAgICAgICByZXN1bHRbMTBdID0gbWF0cml4MTA7CiAgICAgICAgcmVzdWx0WzExXSA9IDA7CiAgICAgICAgcmVzdWx0WzEyXSA9IHg7CiAgICAgICAgcmVzdWx0WzEzXSA9IHk7CiAgICAgICAgcmVzdWx0WzE0XSA9IHo7CiAgICAgICAgcmVzdWx0WzE1XSA9IDE7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NyYXRjaFRyYW5zcG9zZU1hdHJpeDIgPSBuZXcgTWF0cml4NCgpOwogICAgICBNYXRyaXg0LmludmVyc2VUcmFuc3Bvc2UgPSBmdW5jdGlvbihtYXRyaXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmV0dXJuIE1hdHJpeDQuaW52ZXJzZSgKICAgICAgICAgIE1hdHJpeDQudHJhbnNwb3NlKG1hdHJpeCwgc2NyYXRjaFRyYW5zcG9zZU1hdHJpeDIpLAogICAgICAgICAgcmVzdWx0CiAgICAgICAgKTsKICAgICAgfTsKICAgICAgTWF0cml4NC5JREVOVElUWSA9IE9iamVjdC5mcmVlemUoCiAgICAgICAgbmV3IE1hdHJpeDQoCiAgICAgICAgICAxLAogICAgICAgICAgMCwKICAgICAgICAgIDAsCiAgICAgICAgICAwLAogICAgICAgICAgMCwKICAgICAgICAgIDEsCiAgICAgICAgICAwLAogICAgICAgICAgMCwKICAgICAgICAgIDAsCiAgICAgICAgICAwLAogICAgICAgICAgMSwKICAgICAgICAgIDAsCiAgICAgICAgICAwLAogICAgICAgICAgMCwKICAgICAgICAgIDAsCiAgICAgICAgICAxCiAgICAgICAgKQogICAgICApOwogICAgICBNYXRyaXg0LlpFUk8gPSBPYmplY3QuZnJlZXplKAogICAgICAgIG5ldyBNYXRyaXg0KAogICAgICAgICAgMCwKICAgICAgICAgIDAsCiAgICAgICAgICAwLAogICAgICAgICAgMCwKICAgICAgICAgIDAsCiAgICAgICAgICAwLAogICAgICAgICAgMCwKICAgICAgICAgIDAsCiAgICAgICAgICAwLAogICAgICAgICAgMCwKICAgICAgICAgIDAsCiAgICAgICAgICAwLAogICAgICAgICAgMCwKICAgICAgICAgIDAsCiAgICAgICAgICAwLAogICAgICAgICAgMAogICAgICAgICkKICAgICAgKTsKICAgICAgTWF0cml4NC5DT0xVTU4wUk9XMCA9IDA7CiAgICAgIE1hdHJpeDQuQ09MVU1OMFJPVzEgPSAxOwogICAgICBNYXRyaXg0LkNPTFVNTjBST1cyID0gMjsKICAgICAgTWF0cml4NC5DT0xVTU4wUk9XMyA9IDM7CiAgICAgIE1hdHJpeDQuQ09MVU1OMVJPVzAgPSA0OwogICAgICBNYXRyaXg0LkNPTFVNTjFST1cxID0gNTsKICAgICAgTWF0cml4NC5DT0xVTU4xUk9XMiA9IDY7CiAgICAgIE1hdHJpeDQuQ09MVU1OMVJPVzMgPSA3OwogICAgICBNYXRyaXg0LkNPTFVNTjJST1cwID0gODsKICAgICAgTWF0cml4NC5DT0xVTU4yUk9XMSA9IDk7CiAgICAgIE1hdHJpeDQuQ09MVU1OMlJPVzIgPSAxMDsKICAgICAgTWF0cml4NC5DT0xVTU4yUk9XMyA9IDExOwogICAgICBNYXRyaXg0LkNPTFVNTjNST1cwID0gMTI7CiAgICAgIE1hdHJpeDQuQ09MVU1OM1JPVzEgPSAxMzsKICAgICAgTWF0cml4NC5DT0xVTU4zUk9XMiA9IDE0OwogICAgICBNYXRyaXg0LkNPTFVNTjNST1czID0gMTU7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKE1hdHJpeDQucHJvdG90eXBlLCB7CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgbnVtYmVyIG9mIGl0ZW1zIGluIHRoZSBjb2xsZWN0aW9uLgogICAgICAgICAqIEBtZW1iZXJvZiBNYXRyaXg0LnByb3RvdHlwZQogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKi8KICAgICAgICBsZW5ndGg6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBNYXRyaXg0LnBhY2tlZExlbmd0aDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBNYXRyaXg0LnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAgIHJldHVybiBNYXRyaXg0LmNsb25lKHRoaXMsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIE1hdHJpeDQucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uKHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIE1hdHJpeDQuZXF1YWxzKHRoaXMsIHJpZ2h0KTsKICAgICAgfTsKICAgICAgTWF0cml4NC5lcXVhbHNBcnJheSA9IGZ1bmN0aW9uKG1hdHJpeCwgYXJyYXksIG9mZnNldCkgewogICAgICAgIHJldHVybiBtYXRyaXhbMF0gPT09IGFycmF5W29mZnNldF0gJiYgbWF0cml4WzFdID09PSBhcnJheVtvZmZzZXQgKyAxXSAmJiBtYXRyaXhbMl0gPT09IGFycmF5W29mZnNldCArIDJdICYmIG1hdHJpeFszXSA9PT0gYXJyYXlbb2Zmc2V0ICsgM10gJiYgbWF0cml4WzRdID09PSBhcnJheVtvZmZzZXQgKyA0XSAmJiBtYXRyaXhbNV0gPT09IGFycmF5W29mZnNldCArIDVdICYmIG1hdHJpeFs2XSA9PT0gYXJyYXlbb2Zmc2V0ICsgNl0gJiYgbWF0cml4WzddID09PSBhcnJheVtvZmZzZXQgKyA3XSAmJiBtYXRyaXhbOF0gPT09IGFycmF5W29mZnNldCArIDhdICYmIG1hdHJpeFs5XSA9PT0gYXJyYXlbb2Zmc2V0ICsgOV0gJiYgbWF0cml4WzEwXSA9PT0gYXJyYXlbb2Zmc2V0ICsgMTBdICYmIG1hdHJpeFsxMV0gPT09IGFycmF5W29mZnNldCArIDExXSAmJiBtYXRyaXhbMTJdID09PSBhcnJheVtvZmZzZXQgKyAxMl0gJiYgbWF0cml4WzEzXSA9PT0gYXJyYXlbb2Zmc2V0ICsgMTNdICYmIG1hdHJpeFsxNF0gPT09IGFycmF5W29mZnNldCArIDE0XSAmJiBtYXRyaXhbMTVdID09PSBhcnJheVtvZmZzZXQgKyAxNV07CiAgICAgIH07CiAgICAgIE1hdHJpeDQucHJvdG90eXBlLmVxdWFsc0Vwc2lsb24gPSBmdW5jdGlvbihyaWdodCwgZXBzaWxvbikgewogICAgICAgIHJldHVybiBNYXRyaXg0LmVxdWFsc0Vwc2lsb24odGhpcywgcmlnaHQsIGVwc2lsb24pOwogICAgICB9OwogICAgICBNYXRyaXg0LnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBgKCR7dGhpc1swXX0sICR7dGhpc1s0XX0sICR7dGhpc1s4XX0sICR7dGhpc1sxMl19KQooJHt0aGlzWzFdfSwgJHt0aGlzWzVdfSwgJHt0aGlzWzldfSwgJHt0aGlzWzEzXX0pCigke3RoaXNbMl19LCAke3RoaXNbNl19LCAke3RoaXNbMTBdfSwgJHt0aGlzWzE0XX0pCigke3RoaXNbM119LCAke3RoaXNbN119LCAke3RoaXNbMTFdfSwgJHt0aGlzWzE1XX0pYDsKICAgICAgfTsKICAgICAgTWF0cml4NF9kZWZhdWx0ID0gTWF0cml4NDsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2JpbmFyeVNlYXJjaC5qcwogIGZ1bmN0aW9uIGJpbmFyeVNlYXJjaChhcnJheSwgaXRlbVRvRmluZCwgY29tcGFyYXRvcikgewogICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiaXRlbVRvRmluZCIsIGl0ZW1Ub0ZpbmQpOwogICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJjb21wYXJhdG9yIiwgY29tcGFyYXRvcik7CiAgICBsZXQgbG93ID0gMDsKICAgIGxldCBoaWdoID0gYXJyYXkubGVuZ3RoIC0gMTsKICAgIGxldCBpOwogICAgbGV0IGNvbXBhcmlzb247CiAgICB3aGlsZSAobG93IDw9IGhpZ2gpIHsKICAgICAgaSA9IH5+KChsb3cgKyBoaWdoKSAvIDIpOwogICAgICBjb21wYXJpc29uID0gY29tcGFyYXRvcihhcnJheVtpXSwgaXRlbVRvRmluZCk7CiAgICAgIGlmIChjb21wYXJpc29uIDwgMCkgewogICAgICAgIGxvdyA9IGkgKyAxOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChjb21wYXJpc29uID4gMCkgewogICAgICAgIGhpZ2ggPSBpIC0gMTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICByZXR1cm4gaTsKICAgIH0KICAgIHJldHVybiB+KGhpZ2ggKyAxKTsKICB9CiAgdmFyIGJpbmFyeVNlYXJjaF9kZWZhdWx0OwogIHZhciBpbml0X2JpbmFyeVNlYXJjaCA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvYmluYXJ5U2VhcmNoLmpzIigpIHsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBiaW5hcnlTZWFyY2hfZGVmYXVsdCA9IGJpbmFyeVNlYXJjaDsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0VhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzU2FtcGxlLmpzCiAgZnVuY3Rpb24gRWFydGhPcmllbnRhdGlvblBhcmFtZXRlcnNTYW1wbGUoeFBvbGVXYW5kZXIsIHlQb2xlV2FuZGVyLCB4UG9sZU9mZnNldCwgeVBvbGVPZmZzZXQsIHV0MU1pbnVzVXRjKSB7CiAgICB0aGlzLnhQb2xlV2FuZGVyID0geFBvbGVXYW5kZXI7CiAgICB0aGlzLnlQb2xlV2FuZGVyID0geVBvbGVXYW5kZXI7CiAgICB0aGlzLnhQb2xlT2Zmc2V0ID0geFBvbGVPZmZzZXQ7CiAgICB0aGlzLnlQb2xlT2Zmc2V0ID0geVBvbGVPZmZzZXQ7CiAgICB0aGlzLnV0MU1pbnVzVXRjID0gdXQxTWludXNVdGM7CiAgfQogIHZhciBFYXJ0aE9yaWVudGF0aW9uUGFyYW1ldGVyc1NhbXBsZV9kZWZhdWx0OwogIHZhciBpbml0X0VhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzU2FtcGxlID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9FYXJ0aE9yaWVudGF0aW9uUGFyYW1ldGVyc1NhbXBsZS5qcyIoKSB7CiAgICAgIEVhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzU2FtcGxlX2RlZmF1bHQgPSBFYXJ0aE9yaWVudGF0aW9uUGFyYW1ldGVyc1NhbXBsZTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2lzTGVhcFllYXIuanMKICBmdW5jdGlvbiBpc0xlYXBZZWFyKHllYXIpIHsKICAgIGlmICh5ZWFyID09PSBudWxsIHx8IGlzTmFOKHllYXIpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ5ZWFyIGlzIHJlcXVpcmVkIGFuZCBtdXN0IGJlIGEgbnVtYmVyLiIpOwogICAgfQogICAgcmV0dXJuIHllYXIgJSA0ID09PSAwICYmIHllYXIgJSAxMDAgIT09IDAgfHwgeWVhciAlIDQwMCA9PT0gMDsKICB9CiAgdmFyIGlzTGVhcFllYXJfZGVmYXVsdDsKICB2YXIgaW5pdF9pc0xlYXBZZWFyID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9pc0xlYXBZZWFyLmpzIigpIHsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpc0xlYXBZZWFyX2RlZmF1bHQgPSBpc0xlYXBZZWFyOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvR3JlZ29yaWFuRGF0ZS5qcwogIGZ1bmN0aW9uIEdyZWdvcmlhbkRhdGUoeWVhciwgbW9udGgsIGRheSwgaG91ciwgbWludXRlLCBzZWNvbmQsIG1pbGxpc2Vjb25kLCBpc0xlYXBTZWNvbmQpIHsKICAgIGNvbnN0IG1pbmltdW1ZZWFyID0gMTsKICAgIGNvbnN0IG1pbmltdW1Nb250aCA9IDE7CiAgICBjb25zdCBtaW5pbXVtRGF5ID0gMTsKICAgIGNvbnN0IG1pbmltdW1Ib3VyID0gMDsKICAgIGNvbnN0IG1pbmltdW1NaW51dGUgPSAwOwogICAgY29uc3QgbWluaW11bVNlY29uZCA9IDA7CiAgICBjb25zdCBtaW5pbXVtTWlsbGlzZWNvbmQgPSAwOwogICAgeWVhciA9IHllYXIgPz8gbWluaW11bVllYXI7CiAgICBtb250aCA9IG1vbnRoID8/IG1pbmltdW1Nb250aDsKICAgIGRheSA9IGRheSA/PyBtaW5pbXVtRGF5OwogICAgaG91ciA9IGhvdXIgPz8gbWluaW11bUhvdXI7CiAgICBtaW51dGUgPSBtaW51dGUgPz8gbWluaW11bU1pbnV0ZTsKICAgIHNlY29uZCA9IHNlY29uZCA/PyBtaW5pbXVtU2Vjb25kOwogICAgbWlsbGlzZWNvbmQgPSBtaWxsaXNlY29uZCA/PyBtaW5pbXVtTWlsbGlzZWNvbmQ7CiAgICBpc0xlYXBTZWNvbmQgPSBpc0xlYXBTZWNvbmQgPz8gZmFsc2U7CiAgICB2YWxpZGF0ZVJhbmdlKCk7CiAgICB2YWxpZGF0ZURhdGUoKTsKICAgIHRoaXMueWVhciA9IHllYXI7CiAgICB0aGlzLm1vbnRoID0gbW9udGg7CiAgICB0aGlzLmRheSA9IGRheTsKICAgIHRoaXMuaG91ciA9IGhvdXI7CiAgICB0aGlzLm1pbnV0ZSA9IG1pbnV0ZTsKICAgIHRoaXMuc2Vjb25kID0gc2Vjb25kOwogICAgdGhpcy5taWxsaXNlY29uZCA9IG1pbGxpc2Vjb25kOwogICAgdGhpcy5pc0xlYXBTZWNvbmQgPSBpc0xlYXBTZWNvbmQ7CiAgICBmdW5jdGlvbiB2YWxpZGF0ZVJhbmdlKCkgewogICAgICBjb25zdCBtYXhpbXVtWWVhciA9IDk5OTk7CiAgICAgIGNvbnN0IG1heGltdW1Nb250aCA9IDEyOwogICAgICBjb25zdCBtYXhpbXVtRGF5ID0gMzE7CiAgICAgIGNvbnN0IG1heGltdW1Ib3VyID0gMjM7CiAgICAgIGNvbnN0IG1heGltdW1NaW51dGUgPSA1OTsKICAgICAgY29uc3QgbWF4aW11bVNlY29uZCA9IDU5OwogICAgICBjb25zdCBleGNsdWRlZE1heGltdW1NaWxpc2Vjb25kID0gMWUzOwogICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygiWWVhciIsIHllYXIsIG1pbmltdW1ZZWFyKTsKICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoIlllYXIiLCB5ZWFyLCBtYXhpbXVtWWVhcik7CiAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJNb250aCIsIG1vbnRoLCBtaW5pbXVtTW9udGgpOwogICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygiTW9udGgiLCBtb250aCwgbWF4aW11bU1vbnRoKTsKICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoIkRheSIsIGRheSwgbWluaW11bURheSk7CiAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5sZXNzVGhhbk9yRXF1YWxzKCJEYXkiLCBkYXksIG1heGltdW1EYXkpOwogICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygiSG91ciIsIGhvdXIsIG1pbmltdW1Ib3VyKTsKICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoIkhvdXIiLCBob3VyLCBtYXhpbXVtSG91cik7CiAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJNaW51dGUiLCBtaW51dGUsIG1pbmltdW1NaW51dGUpOwogICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygiTWludXRlIiwgbWludXRlLCBtYXhpbXVtTWludXRlKTsKICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YuYm9vbCgiSXNMZWFwU2Vjb25kIiwgaXNMZWFwU2Vjb25kKTsKICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoIlNlY29uZCIsIHNlY29uZCwgbWluaW11bVNlY29uZCk7CiAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5sZXNzVGhhbk9yRXF1YWxzKAogICAgICAgICJTZWNvbmQiLAogICAgICAgIHNlY29uZCwKICAgICAgICBpc0xlYXBTZWNvbmQgPyBtYXhpbXVtU2Vjb25kICsgMSA6IG1heGltdW1TZWNvbmQKICAgICAgKTsKICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoCiAgICAgICAgIk1pbGxpc2Vjb25kIiwKICAgICAgICBtaWxsaXNlY29uZCwKICAgICAgICBtaW5pbXVtTWlsbGlzZWNvbmQKICAgICAgKTsKICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuKAogICAgICAgICJNaWxsaXNlY29uZCIsCiAgICAgICAgbWlsbGlzZWNvbmQsCiAgICAgICAgZXhjbHVkZWRNYXhpbXVtTWlsaXNlY29uZAogICAgICApOwogICAgfQogICAgZnVuY3Rpb24gdmFsaWRhdGVEYXRlKCkgewogICAgICBjb25zdCBkYXlzSW5Nb250aDIgPSBtb250aCA9PT0gMiAmJiBpc0xlYXBZZWFyX2RlZmF1bHQoeWVhcikgPyBkYXlzSW5ZZWFyW21vbnRoIC0gMV0gKyAxIDogZGF5c0luWWVhclttb250aCAtIDFdOwogICAgICBpZiAoZGF5ID4gZGF5c0luTW9udGgyKSB7CiAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIk1vbnRoIGFuZCBEYXkgcmVwcmVzZW50cyBpbnZhbGlkIGRhdGUiKTsKICAgICAgfQogICAgfQogIH0KICB2YXIgZGF5c0luWWVhciwgR3JlZ29yaWFuRGF0ZV9kZWZhdWx0OwogIHZhciBpbml0X0dyZWdvcmlhbkRhdGUgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dyZWdvcmlhbkRhdGUuanMiKCkgewogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9pc0xlYXBZZWFyKCk7CiAgICAgIGRheXNJblllYXIgPSBbMzEsIDI4LCAzMSwgMzAsIDMxLCAzMCwgMzEsIDMxLCAzMCwgMzEsIDMwLCAzMV07CiAgICAgIEdyZWdvcmlhbkRhdGVfZGVmYXVsdCA9IEdyZWdvcmlhbkRhdGU7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9MZWFwU2Vjb25kLmpzCiAgZnVuY3Rpb24gTGVhcFNlY29uZChkYXRlLCBvZmZzZXQpIHsKICAgIHRoaXMuanVsaWFuRGF0ZSA9IGRhdGU7CiAgICB0aGlzLm9mZnNldCA9IG9mZnNldDsKICB9CiAgdmFyIExlYXBTZWNvbmRfZGVmYXVsdDsKICB2YXIgaW5pdF9MZWFwU2Vjb25kID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9MZWFwU2Vjb25kLmpzIigpIHsKICAgICAgTGVhcFNlY29uZF9kZWZhdWx0ID0gTGVhcFNlY29uZDsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1RpbWVDb25zdGFudHMuanMKICB2YXIgVGltZUNvbnN0YW50cywgVGltZUNvbnN0YW50c19kZWZhdWx0OwogIHZhciBpbml0X1RpbWVDb25zdGFudHMgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1RpbWVDb25zdGFudHMuanMiKCkgewogICAgICBUaW1lQ29uc3RhbnRzID0gewogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBudW1iZXIgb2Ygc2Vjb25kcyBpbiBvbmUgbWlsbGlzZWNvbmQ6IDxjb2RlPjAuMDAxPC9jb2RlPgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgU0VDT05EU19QRVJfTUlMTElTRUNPTkQ6IDFlLTMsCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIG51bWJlciBvZiBzZWNvbmRzIGluIG9uZSBtaW51dGU6IDxjb2RlPjYwPC9jb2RlPi4KICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFNFQ09ORFNfUEVSX01JTlVURTogNjAsCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIG51bWJlciBvZiBtaW51dGVzIGluIG9uZSBob3VyOiA8Y29kZT42MDwvY29kZT4uCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBNSU5VVEVTX1BFUl9IT1VSOiA2MCwKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgbnVtYmVyIG9mIGhvdXJzIGluIG9uZSBkYXk6IDxjb2RlPjI0PC9jb2RlPi4KICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIEhPVVJTX1BFUl9EQVk6IDI0LAogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBudW1iZXIgb2Ygc2Vjb25kcyBpbiBvbmUgaG91cjogPGNvZGU+MzYwMDwvY29kZT4uCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBTRUNPTkRTX1BFUl9IT1VSOiAzNjAwLAogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBudW1iZXIgb2YgbWludXRlcyBpbiBvbmUgZGF5OiA8Y29kZT4xNDQwPC9jb2RlPi4KICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIE1JTlVURVNfUEVSX0RBWTogMTQ0MCwKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgbnVtYmVyIG9mIHNlY29uZHMgaW4gb25lIGRheSwgaWdub3JpbmcgbGVhcCBzZWNvbmRzOiA8Y29kZT44NjQwMDwvY29kZT4uCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBTRUNPTkRTX1BFUl9EQVk6IDg2NDAwLAogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBudW1iZXIgb2YgZGF5cyBpbiBvbmUgSnVsaWFuIGNlbnR1cnk6IDxjb2RlPjM2NTI1PC9jb2RlPi4KICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIERBWVNfUEVSX0pVTElBTl9DRU5UVVJZOiAzNjUyNSwKICAgICAgICAvKioKICAgICAgICAgKiBPbmUgdHJpbGxpb250aCBvZiBhIHNlY29uZC4KICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFBJQ09TRUNPTkQ6IDFlLTksCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIG51bWJlciBvZiBkYXlzIHRvIHN1YnRyYWN0IGZyb20gYSBKdWxpYW4gZGF0ZSB0byBkZXRlcm1pbmUgdGhlCiAgICAgICAgICogbW9kaWZpZWQgSnVsaWFuIGRhdGUsIHdoaWNoIGdpdmVzIHRoZSBudW1iZXIgb2YgZGF5cyBzaW5jZSBtaWRuaWdodAogICAgICAgICAqIG9uIE5vdmVtYmVyIDE3LCAxODU4LgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgTU9ESUZJRURfSlVMSUFOX0RBVEVfRElGRkVSRU5DRTogMjQwMDAwMDVlLTEKICAgICAgfTsKICAgICAgVGltZUNvbnN0YW50c19kZWZhdWx0ID0gT2JqZWN0LmZyZWV6ZShUaW1lQ29uc3RhbnRzKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1RpbWVTdGFuZGFyZC5qcwogIHZhciBUaW1lU3RhbmRhcmQsIFRpbWVTdGFuZGFyZF9kZWZhdWx0OwogIHZhciBpbml0X1RpbWVTdGFuZGFyZCA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvVGltZVN0YW5kYXJkLmpzIigpIHsKICAgICAgVGltZVN0YW5kYXJkID0gewogICAgICAgIC8qKgogICAgICAgICAqIFJlcHJlc2VudHMgdGhlIGNvb3JkaW5hdGVkIFVuaXZlcnNhbCBUaW1lIChVVEMpIHRpbWUgc3RhbmRhcmQuCiAgICAgICAgICoKICAgICAgICAgKiBVVEMgaXMgcmVsYXRlZCB0byBUQUkgYWNjb3JkaW5nIHRvIHRoZSByZWxhdGlvbnNoaXAKICAgICAgICAgKiA8Y29kZT5VVEMgPSBUQUkgLSBkZWx0YVQ8L2NvZGU+IHdoZXJlIDxjb2RlPmRlbHRhVDwvY29kZT4gaXMgdGhlIG51bWJlciBvZiBsZWFwCiAgICAgICAgICogc2Vjb25kcyB3aGljaCBoYXZlIGJlZW4gaW50cm9kdWNlZCBhcyBvZiB0aGUgdGltZSBpbiBUQUkuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFVUQzogMCwKICAgICAgICAvKioKICAgICAgICAgKiBSZXByZXNlbnRzIHRoZSBJbnRlcm5hdGlvbmFsIEF0b21pYyBUaW1lIChUQUkpIHRpbWUgc3RhbmRhcmQuCiAgICAgICAgICogVEFJIGlzIHRoZSBwcmluY2lwYWwgdGltZSBzdGFuZGFyZCB0byB3aGljaCB0aGUgb3RoZXIgdGltZSBzdGFuZGFyZHMgYXJlIHJlbGF0ZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFRBSTogMQogICAgICB9OwogICAgICBUaW1lU3RhbmRhcmRfZGVmYXVsdCA9IE9iamVjdC5mcmVlemUoVGltZVN0YW5kYXJkKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0p1bGlhbkRhdGUuanMKICBmdW5jdGlvbiBjb21wYXJlTGVhcFNlY29uZERhdGVzKGxlYXBTZWNvbmQsIGRhdGVUb0ZpbmQpIHsKICAgIHJldHVybiBKdWxpYW5EYXRlLmNvbXBhcmUobGVhcFNlY29uZC5qdWxpYW5EYXRlLCBkYXRlVG9GaW5kLmp1bGlhbkRhdGUpOwogIH0KICBmdW5jdGlvbiBjb252ZXJ0VXRjVG9UYWkoanVsaWFuRGF0ZSkgewogICAgYmluYXJ5U2VhcmNoU2NyYXRjaExlYXBTZWNvbmQuanVsaWFuRGF0ZSA9IGp1bGlhbkRhdGU7CiAgICBjb25zdCBsZWFwU2Vjb25kcyA9IEp1bGlhbkRhdGUubGVhcFNlY29uZHM7CiAgICBsZXQgaW5kZXggPSBiaW5hcnlTZWFyY2hfZGVmYXVsdCgKICAgICAgbGVhcFNlY29uZHMsCiAgICAgIGJpbmFyeVNlYXJjaFNjcmF0Y2hMZWFwU2Vjb25kLAogICAgICBjb21wYXJlTGVhcFNlY29uZERhdGVzCiAgICApOwogICAgaWYgKGluZGV4IDwgMCkgewogICAgICBpbmRleCA9IH5pbmRleDsKICAgIH0KICAgIGlmIChpbmRleCA+PSBsZWFwU2Vjb25kcy5sZW5ndGgpIHsKICAgICAgaW5kZXggPSBsZWFwU2Vjb25kcy5sZW5ndGggLSAxOwogICAgfQogICAgbGV0IG9mZnNldCA9IGxlYXBTZWNvbmRzW2luZGV4XS5vZmZzZXQ7CiAgICBpZiAoaW5kZXggPiAwKSB7CiAgICAgIGNvbnN0IGRpZmZlcmVuY2UgPSBKdWxpYW5EYXRlLnNlY29uZHNEaWZmZXJlbmNlKAogICAgICAgIGxlYXBTZWNvbmRzW2luZGV4XS5qdWxpYW5EYXRlLAogICAgICAgIGp1bGlhbkRhdGUKICAgICAgKTsKICAgICAgaWYgKGRpZmZlcmVuY2UgPiBvZmZzZXQpIHsKICAgICAgICBpbmRleC0tOwogICAgICAgIG9mZnNldCA9IGxlYXBTZWNvbmRzW2luZGV4XS5vZmZzZXQ7CiAgICAgIH0KICAgIH0KICAgIEp1bGlhbkRhdGUuYWRkU2Vjb25kcyhqdWxpYW5EYXRlLCBvZmZzZXQsIGp1bGlhbkRhdGUpOwogIH0KICBmdW5jdGlvbiBjb252ZXJ0VGFpVG9VdGMoanVsaWFuRGF0ZSwgcmVzdWx0KSB7CiAgICBiaW5hcnlTZWFyY2hTY3JhdGNoTGVhcFNlY29uZC5qdWxpYW5EYXRlID0ganVsaWFuRGF0ZTsKICAgIGNvbnN0IGxlYXBTZWNvbmRzID0gSnVsaWFuRGF0ZS5sZWFwU2Vjb25kczsKICAgIGxldCBpbmRleCA9IGJpbmFyeVNlYXJjaF9kZWZhdWx0KAogICAgICBsZWFwU2Vjb25kcywKICAgICAgYmluYXJ5U2VhcmNoU2NyYXRjaExlYXBTZWNvbmQsCiAgICAgIGNvbXBhcmVMZWFwU2Vjb25kRGF0ZXMKICAgICk7CiAgICBpZiAoaW5kZXggPCAwKSB7CiAgICAgIGluZGV4ID0gfmluZGV4OwogICAgfQogICAgaWYgKGluZGV4ID09PSAwKSB7CiAgICAgIHJldHVybiBKdWxpYW5EYXRlLmFkZFNlY29uZHMoanVsaWFuRGF0ZSwgLWxlYXBTZWNvbmRzWzBdLm9mZnNldCwgcmVzdWx0KTsKICAgIH0KICAgIGlmIChpbmRleCA+PSBsZWFwU2Vjb25kcy5sZW5ndGgpIHsKICAgICAgcmV0dXJuIEp1bGlhbkRhdGUuYWRkU2Vjb25kcygKICAgICAgICBqdWxpYW5EYXRlLAogICAgICAgIC1sZWFwU2Vjb25kc1tpbmRleCAtIDFdLm9mZnNldCwKICAgICAgICByZXN1bHQKICAgICAgKTsKICAgIH0KICAgIGNvbnN0IGRpZmZlcmVuY2UgPSBKdWxpYW5EYXRlLnNlY29uZHNEaWZmZXJlbmNlKAogICAgICBsZWFwU2Vjb25kc1tpbmRleF0uanVsaWFuRGF0ZSwKICAgICAganVsaWFuRGF0ZQogICAgKTsKICAgIGlmIChkaWZmZXJlbmNlID09PSAwKSB7CiAgICAgIHJldHVybiBKdWxpYW5EYXRlLmFkZFNlY29uZHMoCiAgICAgICAganVsaWFuRGF0ZSwKICAgICAgICAtbGVhcFNlY29uZHNbaW5kZXhdLm9mZnNldCwKICAgICAgICByZXN1bHQKICAgICAgKTsKICAgIH0KICAgIGlmIChkaWZmZXJlbmNlIDw9IDEpIHsKICAgICAgcmV0dXJuIHZvaWQgMDsKICAgIH0KICAgIHJldHVybiBKdWxpYW5EYXRlLmFkZFNlY29uZHMoCiAgICAgIGp1bGlhbkRhdGUsCiAgICAgIC1sZWFwU2Vjb25kc1stLWluZGV4XS5vZmZzZXQsCiAgICAgIHJlc3VsdAogICAgKTsKICB9CiAgZnVuY3Rpb24gc2V0Q29tcG9uZW50cyh3aG9sZURheXMsIHNlY29uZHNPZkRheSwganVsaWFuRGF0ZSkgewogICAgY29uc3QgZXh0cmFEYXlzID0gc2Vjb25kc09mRGF5IC8gVGltZUNvbnN0YW50c19kZWZhdWx0LlNFQ09ORFNfUEVSX0RBWSB8IDA7CiAgICB3aG9sZURheXMgKz0gZXh0cmFEYXlzOwogICAgc2Vjb25kc09mRGF5IC09IFRpbWVDb25zdGFudHNfZGVmYXVsdC5TRUNPTkRTX1BFUl9EQVkgKiBleHRyYURheXM7CiAgICBpZiAoc2Vjb25kc09mRGF5IDwgMCkgewogICAgICB3aG9sZURheXMtLTsKICAgICAgc2Vjb25kc09mRGF5ICs9IFRpbWVDb25zdGFudHNfZGVmYXVsdC5TRUNPTkRTX1BFUl9EQVk7CiAgICB9CiAgICBqdWxpYW5EYXRlLmRheU51bWJlciA9IHdob2xlRGF5czsKICAgIGp1bGlhbkRhdGUuc2Vjb25kc09mRGF5ID0gc2Vjb25kc09mRGF5OwogICAgcmV0dXJuIGp1bGlhbkRhdGU7CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVKdWxpYW5EYXRlQ29tcG9uZW50cyh5ZWFyLCBtb250aCwgZGF5LCBob3VyLCBtaW51dGUsIHNlY29uZCwgbWlsbGlzZWNvbmQpIHsKICAgIGNvbnN0IGEzID0gKG1vbnRoIC0gMTQpIC8gMTIgfCAwOwogICAgY29uc3QgYiA9IHllYXIgKyA0ODAwICsgYTM7CiAgICBsZXQgZGF5TnVtYmVyID0gKDE0NjEgKiBiIC8gNCB8IDApICsgKDM2NyAqIChtb250aCAtIDIgLSAxMiAqIGEzKSAvIDEyIHwgMCkgLSAoMyAqICgoYiArIDEwMCkgLyAxMDAgfCAwKSAvIDQgfCAwKSArIGRheSAtIDMyMDc1OwogICAgaG91ciA9IGhvdXIgLSAxMjsKICAgIGlmIChob3VyIDwgMCkgewogICAgICBob3VyICs9IDI0OwogICAgfQogICAgY29uc3Qgc2Vjb25kc09mRGF5ID0gc2Vjb25kICsgKGhvdXIgKiBUaW1lQ29uc3RhbnRzX2RlZmF1bHQuU0VDT05EU19QRVJfSE9VUiArIG1pbnV0ZSAqIFRpbWVDb25zdGFudHNfZGVmYXVsdC5TRUNPTkRTX1BFUl9NSU5VVEUgKyBtaWxsaXNlY29uZCAqIFRpbWVDb25zdGFudHNfZGVmYXVsdC5TRUNPTkRTX1BFUl9NSUxMSVNFQ09ORCk7CiAgICBpZiAoc2Vjb25kc09mRGF5ID49IDQzMjAwKSB7CiAgICAgIGRheU51bWJlciAtPSAxOwogICAgfQogICAgcmV0dXJuIFtkYXlOdW1iZXIsIHNlY29uZHNPZkRheV07CiAgfQogIGZ1bmN0aW9uIEp1bGlhbkRhdGUoanVsaWFuRGF5TnVtYmVyLCBzZWNvbmRzT2ZEYXksIHRpbWVTdGFuZGFyZCkgewogICAgdGhpcy5kYXlOdW1iZXIgPSB2b2lkIDA7CiAgICB0aGlzLnNlY29uZHNPZkRheSA9IHZvaWQgMDsKICAgIGp1bGlhbkRheU51bWJlciA9IGp1bGlhbkRheU51bWJlciA/PyAwOwogICAgc2Vjb25kc09mRGF5ID0gc2Vjb25kc09mRGF5ID8/IDA7CiAgICB0aW1lU3RhbmRhcmQgPSB0aW1lU3RhbmRhcmQgPz8gVGltZVN0YW5kYXJkX2RlZmF1bHQuVVRDOwogICAgY29uc3Qgd2hvbGVEYXlzID0ganVsaWFuRGF5TnVtYmVyIHwgMDsKICAgIHNlY29uZHNPZkRheSA9IHNlY29uZHNPZkRheSArIChqdWxpYW5EYXlOdW1iZXIgLSB3aG9sZURheXMpICogVGltZUNvbnN0YW50c19kZWZhdWx0LlNFQ09ORFNfUEVSX0RBWTsKICAgIHNldENvbXBvbmVudHMod2hvbGVEYXlzLCBzZWNvbmRzT2ZEYXksIHRoaXMpOwogICAgaWYgKHRpbWVTdGFuZGFyZCA9PT0gVGltZVN0YW5kYXJkX2RlZmF1bHQuVVRDKSB7CiAgICAgIGNvbnZlcnRVdGNUb1RhaSh0aGlzKTsKICAgIH0KICB9CiAgdmFyIGdyZWdvcmlhbkRhdGVTY3JhdGNoLCBkYXlzSW5Nb250aCwgZGF5c0luTGVhcEZlYnJ1YXJ5LCBiaW5hcnlTZWFyY2hTY3JhdGNoTGVhcFNlY29uZCwgbWF0Y2hDYWxlbmRhclllYXIsIG1hdGNoQ2FsZW5kYXJNb250aCwgbWF0Y2hPcmRpbmFsRGF0ZSwgbWF0Y2hXZWVrRGF0ZSwgbWF0Y2hDYWxlbmRhckRhdGUsIHV0Y09mZnNldCwgbWF0Y2hIb3VycywgbWF0Y2hIb3Vyc01pbnV0ZXMsIG1hdGNoSG91cnNNaW51dGVzU2Vjb25kcywgaXNvODYwMUVycm9yTWVzc2FnZSwgdG9HcmVnb3JpYW5EYXRlU2NyYXRjaCwgSnVsaWFuRGF0ZV9kZWZhdWx0OwogIHZhciBpbml0X0p1bGlhbkRhdGUgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0p1bGlhbkRhdGUuanMiKCkgewogICAgICBpbml0X2JpbmFyeVNlYXJjaCgpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0dyZWdvcmlhbkRhdGUoKTsKICAgICAgaW5pdF9pc0xlYXBZZWFyKCk7CiAgICAgIGluaXRfTGVhcFNlY29uZCgpOwogICAgICBpbml0X1RpbWVDb25zdGFudHMoKTsKICAgICAgaW5pdF9UaW1lU3RhbmRhcmQoKTsKICAgICAgZ3JlZ29yaWFuRGF0ZVNjcmF0Y2ggPSBuZXcgR3JlZ29yaWFuRGF0ZV9kZWZhdWx0KCk7CiAgICAgIGRheXNJbk1vbnRoID0gWzMxLCAyOCwgMzEsIDMwLCAzMSwgMzAsIDMxLCAzMSwgMzAsIDMxLCAzMCwgMzFdOwogICAgICBkYXlzSW5MZWFwRmVicnVhcnkgPSAyOTsKICAgICAgYmluYXJ5U2VhcmNoU2NyYXRjaExlYXBTZWNvbmQgPSBuZXcgTGVhcFNlY29uZF9kZWZhdWx0KCk7CiAgICAgIG1hdGNoQ2FsZW5kYXJZZWFyID0gL14oXGR7NH0pJC87CiAgICAgIG1hdGNoQ2FsZW5kYXJNb250aCA9IC9eKFxkezR9KS0oXGR7Mn0pJC87CiAgICAgIG1hdGNoT3JkaW5hbERhdGUgPSAvXihcZHs0fSktPyhcZHszfSkkLzsKICAgICAgbWF0Y2hXZWVrRGF0ZSA9IC9eKFxkezR9KS0/VyhcZHsyfSktPyhcZHsxfSk/JC87CiAgICAgIG1hdGNoQ2FsZW5kYXJEYXRlID0gL14oXGR7NH0pLT8oXGR7Mn0pLT8oXGR7Mn0pJC87CiAgICAgIHV0Y09mZnNldCA9IC8oW1orXC1dKT8oXGR7Mn0pPzo/KFxkezJ9KT8kLzsKICAgICAgbWF0Y2hIb3VycyA9IC9eKFxkezJ9KShcLlxkKyk/Ly5zb3VyY2UgKyB1dGNPZmZzZXQuc291cmNlOwogICAgICBtYXRjaEhvdXJzTWludXRlcyA9IC9eKFxkezJ9KTo/KFxkezJ9KShcLlxkKyk/Ly5zb3VyY2UgKyB1dGNPZmZzZXQuc291cmNlOwogICAgICBtYXRjaEhvdXJzTWludXRlc1NlY29uZHMgPSAvXihcZHsyfSk6PyhcZHsyfSk6PyhcZHsyfSkoXC5cZCspPy8uc291cmNlICsgdXRjT2Zmc2V0LnNvdXJjZTsKICAgICAgaXNvODYwMUVycm9yTWVzc2FnZSA9ICJJbnZhbGlkIElTTyA4NjAxIGRhdGUuIjsKICAgICAgSnVsaWFuRGF0ZS5mcm9tR3JlZ29yaWFuRGF0ZSA9IGZ1bmN0aW9uKGRhdGUsIHJlc3VsdCkgewogICAgICAgIGlmICghKGRhdGUgaW5zdGFuY2VvZiBHcmVnb3JpYW5EYXRlX2RlZmF1bHQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZGF0ZSBtdXN0IGJlIGEgdmFsaWQgR3JlZ29yaWFuRGF0ZS4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgY29tcG9uZW50cyA9IGNvbXB1dGVKdWxpYW5EYXRlQ29tcG9uZW50cygKICAgICAgICAgIGRhdGUueWVhciwKICAgICAgICAgIGRhdGUubW9udGgsCiAgICAgICAgICBkYXRlLmRheSwKICAgICAgICAgIGRhdGUuaG91ciwKICAgICAgICAgIGRhdGUubWludXRlLAogICAgICAgICAgZGF0ZS5zZWNvbmQsCiAgICAgICAgICBkYXRlLm1pbGxpc2Vjb25kCiAgICAgICAgKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IEp1bGlhbkRhdGUoY29tcG9uZW50c1swXSwgY29tcG9uZW50c1sxXSwgVGltZVN0YW5kYXJkX2RlZmF1bHQuVVRDKTsKICAgICAgICB9CiAgICAgICAgc2V0Q29tcG9uZW50cyhjb21wb25lbnRzWzBdLCBjb21wb25lbnRzWzFdLCByZXN1bHQpOwogICAgICAgIGNvbnZlcnRVdGNUb1RhaShyZXN1bHQpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEp1bGlhbkRhdGUuZnJvbURhdGUgPSBmdW5jdGlvbihkYXRlLCByZXN1bHQpIHsKICAgICAgICBpZiAoIShkYXRlIGluc3RhbmNlb2YgRGF0ZSkgfHwgaXNOYU4oZGF0ZS5nZXRUaW1lKCkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZGF0ZSBtdXN0IGJlIGEgdmFsaWQgSmF2YVNjcmlwdCBEYXRlLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBjb21wb25lbnRzID0gY29tcHV0ZUp1bGlhbkRhdGVDb21wb25lbnRzKAogICAgICAgICAgZGF0ZS5nZXRVVENGdWxsWWVhcigpLAogICAgICAgICAgZGF0ZS5nZXRVVENNb250aCgpICsgMSwKICAgICAgICAgIGRhdGUuZ2V0VVRDRGF0ZSgpLAogICAgICAgICAgZGF0ZS5nZXRVVENIb3VycygpLAogICAgICAgICAgZGF0ZS5nZXRVVENNaW51dGVzKCksCiAgICAgICAgICBkYXRlLmdldFVUQ1NlY29uZHMoKSwKICAgICAgICAgIGRhdGUuZ2V0VVRDTWlsbGlzZWNvbmRzKCkKICAgICAgICApOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgSnVsaWFuRGF0ZShjb21wb25lbnRzWzBdLCBjb21wb25lbnRzWzFdLCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5VVEMpOwogICAgICAgIH0KICAgICAgICBzZXRDb21wb25lbnRzKGNvbXBvbmVudHNbMF0sIGNvbXBvbmVudHNbMV0sIHJlc3VsdCk7CiAgICAgICAgY29udmVydFV0Y1RvVGFpKHJlc3VsdCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgSnVsaWFuRGF0ZS5mcm9tSXNvODYwMSA9IGZ1bmN0aW9uKGlzbzg2MDFTdHJpbmcsIHJlc3VsdCkgewogICAgICAgIGlmICh0eXBlb2YgaXNvODYwMVN0cmluZyAhPT0gInN0cmluZyIpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KGlzbzg2MDFFcnJvck1lc3NhZ2UpOwogICAgICAgIH0KICAgICAgICBpc284NjAxU3RyaW5nID0gaXNvODYwMVN0cmluZy5yZXBsYWNlKCIsIiwgIi4iKTsKICAgICAgICBsZXQgdG9rZW5zID0gaXNvODYwMVN0cmluZy5zcGxpdCgiVCIpOwogICAgICAgIGxldCB5ZWFyOwogICAgICAgIGxldCBtb250aCA9IDE7CiAgICAgICAgbGV0IGRheSA9IDE7CiAgICAgICAgbGV0IGhvdXIgPSAwOwogICAgICAgIGxldCBtaW51dGUgPSAwOwogICAgICAgIGxldCBzZWNvbmQgPSAwOwogICAgICAgIGxldCBtaWxsaXNlY29uZCA9IDA7CiAgICAgICAgY29uc3QgZGF0ZSA9IHRva2Vuc1swXTsKICAgICAgICBjb25zdCB0aW1lID0gdG9rZW5zWzFdOwogICAgICAgIGxldCB0bXAyOwogICAgICAgIGxldCBpbkxlYXBZZWFyOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGRhdGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdChpc284NjAxRXJyb3JNZXNzYWdlKTsKICAgICAgICB9CiAgICAgICAgbGV0IGRhc2hDb3VudDsKICAgICAgICB0b2tlbnMgPSBkYXRlLm1hdGNoKG1hdGNoQ2FsZW5kYXJEYXRlKTsKICAgICAgICBpZiAodG9rZW5zICE9PSBudWxsKSB7CiAgICAgICAgICBkYXNoQ291bnQgPSBkYXRlLnNwbGl0KCItIikubGVuZ3RoIC0gMTsKICAgICAgICAgIGlmIChkYXNoQ291bnQgPiAwICYmIGRhc2hDb3VudCAhPT0gMikgewogICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdChpc284NjAxRXJyb3JNZXNzYWdlKTsKICAgICAgICAgIH0KICAgICAgICAgIHllYXIgPSArdG9rZW5zWzFdOwogICAgICAgICAgbW9udGggPSArdG9rZW5zWzJdOwogICAgICAgICAgZGF5ID0gK3Rva2Vuc1szXTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdG9rZW5zID0gZGF0ZS5tYXRjaChtYXRjaENhbGVuZGFyTW9udGgpOwogICAgICAgICAgaWYgKHRva2VucyAhPT0gbnVsbCkgewogICAgICAgICAgICB5ZWFyID0gK3Rva2Vuc1sxXTsKICAgICAgICAgICAgbW9udGggPSArdG9rZW5zWzJdOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdG9rZW5zID0gZGF0ZS5tYXRjaChtYXRjaENhbGVuZGFyWWVhcik7CiAgICAgICAgICAgIGlmICh0b2tlbnMgIT09IG51bGwpIHsKICAgICAgICAgICAgICB5ZWFyID0gK3Rva2Vuc1sxXTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBsZXQgZGF5T2ZZZWFyOwogICAgICAgICAgICAgIHRva2VucyA9IGRhdGUubWF0Y2gobWF0Y2hPcmRpbmFsRGF0ZSk7CiAgICAgICAgICAgICAgaWYgKHRva2VucyAhPT0gbnVsbCkgewogICAgICAgICAgICAgICAgeWVhciA9ICt0b2tlbnNbMV07CiAgICAgICAgICAgICAgICBkYXlPZlllYXIgPSArdG9rZW5zWzJdOwogICAgICAgICAgICAgICAgaW5MZWFwWWVhciA9IGlzTGVhcFllYXJfZGVmYXVsdCh5ZWFyKTsKICAgICAgICAgICAgICAgIGlmIChkYXlPZlllYXIgPCAxIHx8IGluTGVhcFllYXIgJiYgZGF5T2ZZZWFyID4gMzY2IHx8ICFpbkxlYXBZZWFyICYmIGRheU9mWWVhciA+IDM2NSkgewogICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdChpc284NjAxRXJyb3JNZXNzYWdlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgdG9rZW5zID0gZGF0ZS5tYXRjaChtYXRjaFdlZWtEYXRlKTsKICAgICAgICAgICAgICAgIGlmICh0b2tlbnMgIT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgeWVhciA9ICt0b2tlbnNbMV07CiAgICAgICAgICAgICAgICAgIGNvbnN0IHdlZWtOdW1iZXIgPSArdG9rZW5zWzJdOwogICAgICAgICAgICAgICAgICBjb25zdCBkYXlPZldlZWsgPSArdG9rZW5zWzNdIHx8IDA7CiAgICAgICAgICAgICAgICAgIGRhc2hDb3VudCA9IGRhdGUuc3BsaXQoIi0iKS5sZW5ndGggLSAxOwogICAgICAgICAgICAgICAgICBpZiAoZGFzaENvdW50ID4gMCAmJiAoIWRlZmluZWRfZGVmYXVsdCh0b2tlbnNbM10pICYmIGRhc2hDb3VudCAhPT0gMSB8fCBkZWZpbmVkX2RlZmF1bHQodG9rZW5zWzNdKSAmJiBkYXNoQ291bnQgIT09IDIpKSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoaXNvODYwMUVycm9yTWVzc2FnZSk7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgY29uc3QgamFudWFyeTQgPSBuZXcgRGF0ZShEYXRlLlVUQyh5ZWFyLCAwLCA0KSk7CiAgICAgICAgICAgICAgICAgIGRheU9mWWVhciA9IHdlZWtOdW1iZXIgKiA3ICsgZGF5T2ZXZWVrIC0gamFudWFyeTQuZ2V0VVRDRGF5KCkgLSAzOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoaXNvODYwMUVycm9yTWVzc2FnZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRtcDIgPSBuZXcgRGF0ZShEYXRlLlVUQyh5ZWFyLCAwLCAxKSk7CiAgICAgICAgICAgICAgdG1wMi5zZXRVVENEYXRlKGRheU9mWWVhcik7CiAgICAgICAgICAgICAgbW9udGggPSB0bXAyLmdldFVUQ01vbnRoKCkgKyAxOwogICAgICAgICAgICAgIGRheSA9IHRtcDIuZ2V0VVRDRGF0ZSgpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGluTGVhcFllYXIgPSBpc0xlYXBZZWFyX2RlZmF1bHQoeWVhcik7CiAgICAgICAgaWYgKG1vbnRoIDwgMSB8fCBtb250aCA+IDEyIHx8IGRheSA8IDEgfHwgKG1vbnRoICE9PSAyIHx8ICFpbkxlYXBZZWFyKSAmJiBkYXkgPiBkYXlzSW5Nb250aFttb250aCAtIDFdIHx8IGluTGVhcFllYXIgJiYgbW9udGggPT09IDIgJiYgZGF5ID4gZGF5c0luTGVhcEZlYnJ1YXJ5KSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdChpc284NjAxRXJyb3JNZXNzYWdlKTsKICAgICAgICB9CiAgICAgICAgbGV0IG9mZnNldEluZGV4OwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQodGltZSkpIHsKICAgICAgICAgIHRva2VucyA9IHRpbWUubWF0Y2gobWF0Y2hIb3Vyc01pbnV0ZXNTZWNvbmRzKTsKICAgICAgICAgIGlmICh0b2tlbnMgIT09IG51bGwpIHsKICAgICAgICAgICAgZGFzaENvdW50ID0gdGltZS5zcGxpdCgiOiIpLmxlbmd0aCAtIDE7CiAgICAgICAgICAgIGlmIChkYXNoQ291bnQgPiAwICYmIGRhc2hDb3VudCAhPT0gMiAmJiBkYXNoQ291bnQgIT09IDMpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdChpc284NjAxRXJyb3JNZXNzYWdlKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBob3VyID0gK3Rva2Vuc1sxXTsKICAgICAgICAgICAgbWludXRlID0gK3Rva2Vuc1syXTsKICAgICAgICAgICAgc2Vjb25kID0gK3Rva2Vuc1szXTsKICAgICAgICAgICAgbWlsbGlzZWNvbmQgPSArKHRva2Vuc1s0XSB8fCAwKSAqIDFlMzsKICAgICAgICAgICAgb2Zmc2V0SW5kZXggPSA1OwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdG9rZW5zID0gdGltZS5tYXRjaChtYXRjaEhvdXJzTWludXRlcyk7CiAgICAgICAgICAgIGlmICh0b2tlbnMgIT09IG51bGwpIHsKICAgICAgICAgICAgICBkYXNoQ291bnQgPSB0aW1lLnNwbGl0KCI6IikubGVuZ3RoIC0gMTsKICAgICAgICAgICAgICBpZiAoZGFzaENvdW50ID4gMikgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoaXNvODYwMUVycm9yTWVzc2FnZSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGhvdXIgPSArdG9rZW5zWzFdOwogICAgICAgICAgICAgIG1pbnV0ZSA9ICt0b2tlbnNbMl07CiAgICAgICAgICAgICAgc2Vjb25kID0gKyh0b2tlbnNbM10gfHwgMCkgKiA2MDsKICAgICAgICAgICAgICBvZmZzZXRJbmRleCA9IDQ7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdG9rZW5zID0gdGltZS5tYXRjaChtYXRjaEhvdXJzKTsKICAgICAgICAgICAgICBpZiAodG9rZW5zICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICBob3VyID0gK3Rva2Vuc1sxXTsKICAgICAgICAgICAgICAgIG1pbnV0ZSA9ICsodG9rZW5zWzJdIHx8IDApICogNjA7CiAgICAgICAgICAgICAgICBvZmZzZXRJbmRleCA9IDM7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KGlzbzg2MDFFcnJvck1lc3NhZ2UpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKG1pbnV0ZSA+PSA2MCB8fCBzZWNvbmQgPj0gNjEgfHwgaG91ciA+IDI0IHx8IGhvdXIgPT09IDI0ICYmIChtaW51dGUgPiAwIHx8IHNlY29uZCA+IDAgfHwgbWlsbGlzZWNvbmQgPiAwKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdChpc284NjAxRXJyb3JNZXNzYWdlKTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHRva2Vuc1tvZmZzZXRJbmRleF07CiAgICAgICAgICBjb25zdCBvZmZzZXRIb3VycyA9ICt0b2tlbnNbb2Zmc2V0SW5kZXggKyAxXTsKICAgICAgICAgIGNvbnN0IG9mZnNldE1pbnV0ZXMgPSArKHRva2Vuc1tvZmZzZXRJbmRleCArIDJdIHx8IDApOwogICAgICAgICAgc3dpdGNoIChvZmZzZXQpIHsKICAgICAgICAgICAgY2FzZSAiKyI6CiAgICAgICAgICAgICAgaG91ciA9IGhvdXIgLSBvZmZzZXRIb3VyczsKICAgICAgICAgICAgICBtaW51dGUgPSBtaW51dGUgLSBvZmZzZXRNaW51dGVzOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICItIjoKICAgICAgICAgICAgICBob3VyID0gaG91ciArIG9mZnNldEhvdXJzOwogICAgICAgICAgICAgIG1pbnV0ZSA9IG1pbnV0ZSArIG9mZnNldE1pbnV0ZXM7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgIloiOgogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgIG1pbnV0ZSA9IG1pbnV0ZSArIG5ldyBEYXRlKAogICAgICAgICAgICAgICAgRGF0ZS5VVEMoeWVhciwgbW9udGggLSAxLCBkYXksIGhvdXIsIG1pbnV0ZSkKICAgICAgICAgICAgICApLmdldFRpbWV6b25lT2Zmc2V0KCk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IGlzTGVhcFNlY29uZCA9IHNlY29uZCA9PT0gNjA7CiAgICAgICAgaWYgKGlzTGVhcFNlY29uZCkgewogICAgICAgICAgc2Vjb25kLS07CiAgICAgICAgfQogICAgICAgIHdoaWxlIChtaW51dGUgPj0gNjApIHsKICAgICAgICAgIG1pbnV0ZSAtPSA2MDsKICAgICAgICAgIGhvdXIrKzsKICAgICAgICB9CiAgICAgICAgd2hpbGUgKGhvdXIgPj0gMjQpIHsKICAgICAgICAgIGhvdXIgLT0gMjQ7CiAgICAgICAgICBkYXkrKzsKICAgICAgICB9CiAgICAgICAgdG1wMiA9IGluTGVhcFllYXIgJiYgbW9udGggPT09IDIgPyBkYXlzSW5MZWFwRmVicnVhcnkgOiBkYXlzSW5Nb250aFttb250aCAtIDFdOwogICAgICAgIHdoaWxlIChkYXkgPiB0bXAyKSB7CiAgICAgICAgICBkYXkgLT0gdG1wMjsKICAgICAgICAgIG1vbnRoKys7CiAgICAgICAgICBpZiAobW9udGggPiAxMikgewogICAgICAgICAgICBtb250aCAtPSAxMjsKICAgICAgICAgICAgeWVhcisrOwogICAgICAgICAgfQogICAgICAgICAgdG1wMiA9IGluTGVhcFllYXIgJiYgbW9udGggPT09IDIgPyBkYXlzSW5MZWFwRmVicnVhcnkgOiBkYXlzSW5Nb250aFttb250aCAtIDFdOwogICAgICAgIH0KICAgICAgICB3aGlsZSAobWludXRlIDwgMCkgewogICAgICAgICAgbWludXRlICs9IDYwOwogICAgICAgICAgaG91ci0tOwogICAgICAgIH0KICAgICAgICB3aGlsZSAoaG91ciA8IDApIHsKICAgICAgICAgIGhvdXIgKz0gMjQ7CiAgICAgICAgICBkYXktLTsKICAgICAgICB9CiAgICAgICAgd2hpbGUgKGRheSA8IDEpIHsKICAgICAgICAgIG1vbnRoLS07CiAgICAgICAgICBpZiAobW9udGggPCAxKSB7CiAgICAgICAgICAgIG1vbnRoICs9IDEyOwogICAgICAgICAgICB5ZWFyLS07CiAgICAgICAgICB9CiAgICAgICAgICB0bXAyID0gaW5MZWFwWWVhciAmJiBtb250aCA9PT0gMiA/IGRheXNJbkxlYXBGZWJydWFyeSA6IGRheXNJbk1vbnRoW21vbnRoIC0gMV07CiAgICAgICAgICBkYXkgKz0gdG1wMjsKICAgICAgICB9CiAgICAgICAgY29uc3QgY29tcG9uZW50cyA9IGNvbXB1dGVKdWxpYW5EYXRlQ29tcG9uZW50cygKICAgICAgICAgIHllYXIsCiAgICAgICAgICBtb250aCwKICAgICAgICAgIGRheSwKICAgICAgICAgIGhvdXIsCiAgICAgICAgICBtaW51dGUsCiAgICAgICAgICBzZWNvbmQsCiAgICAgICAgICBtaWxsaXNlY29uZAogICAgICAgICk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEp1bGlhbkRhdGUoY29tcG9uZW50c1swXSwgY29tcG9uZW50c1sxXSwgVGltZVN0YW5kYXJkX2RlZmF1bHQuVVRDKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc2V0Q29tcG9uZW50cyhjb21wb25lbnRzWzBdLCBjb21wb25lbnRzWzFdLCByZXN1bHQpOwogICAgICAgICAgY29udmVydFV0Y1RvVGFpKHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIGlmIChpc0xlYXBTZWNvbmQpIHsKICAgICAgICAgIEp1bGlhbkRhdGUuYWRkU2Vjb25kcyhyZXN1bHQsIDEsIHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEp1bGlhbkRhdGUubm93ID0gZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgcmV0dXJuIEp1bGlhbkRhdGUuZnJvbURhdGUoLyogQF9fUFVSRV9fICovIG5ldyBEYXRlKCksIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIHRvR3JlZ29yaWFuRGF0ZVNjcmF0Y2ggPSBuZXcgSnVsaWFuRGF0ZSgwLCAwLCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5UQUkpOwogICAgICBKdWxpYW5EYXRlLnRvR3JlZ29yaWFuRGF0ZSA9IGZ1bmN0aW9uKGp1bGlhbkRhdGUsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGp1bGlhbkRhdGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgianVsaWFuRGF0ZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgbGV0IGlzTGVhcFNlY29uZCA9IGZhbHNlOwogICAgICAgIGxldCB0aGlzVXRjID0gY29udmVydFRhaVRvVXRjKGp1bGlhbkRhdGUsIHRvR3JlZ29yaWFuRGF0ZVNjcmF0Y2gpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHRoaXNVdGMpKSB7CiAgICAgICAgICBKdWxpYW5EYXRlLmFkZFNlY29uZHMoanVsaWFuRGF0ZSwgLTEsIHRvR3JlZ29yaWFuRGF0ZVNjcmF0Y2gpOwogICAgICAgICAgdGhpc1V0YyA9IGNvbnZlcnRUYWlUb1V0Yyh0b0dyZWdvcmlhbkRhdGVTY3JhdGNoLCB0b0dyZWdvcmlhbkRhdGVTY3JhdGNoKTsKICAgICAgICAgIGlzTGVhcFNlY29uZCA9IHRydWU7CiAgICAgICAgfQogICAgICAgIGxldCBqdWxpYW5EYXlOdW1iZXIgPSB0aGlzVXRjLmRheU51bWJlcjsKICAgICAgICBjb25zdCBzZWNvbmRzT2ZEYXkgPSB0aGlzVXRjLnNlY29uZHNPZkRheTsKICAgICAgICBpZiAoc2Vjb25kc09mRGF5ID49IDQzMjAwKSB7CiAgICAgICAgICBqdWxpYW5EYXlOdW1iZXIgKz0gMTsKICAgICAgICB9CiAgICAgICAgbGV0IEwgPSBqdWxpYW5EYXlOdW1iZXIgKyA2ODU2OSB8IDA7CiAgICAgICAgY29uc3QgTiA9IDQgKiBMIC8gMTQ2MDk3IHwgMDsKICAgICAgICBMID0gTCAtICgoMTQ2MDk3ICogTiArIDMpIC8gNCB8IDApIHwgMDsKICAgICAgICBjb25zdCBJID0gNGUzICogKEwgKyAxKSAvIDE0NjEwMDEgfCAwOwogICAgICAgIEwgPSBMIC0gKDE0NjEgKiBJIC8gNCB8IDApICsgMzEgfCAwOwogICAgICAgIGNvbnN0IEogPSA4MCAqIEwgLyAyNDQ3IHwgMDsKICAgICAgICBjb25zdCBkYXkgPSBMIC0gKDI0NDcgKiBKIC8gODAgfCAwKSB8IDA7CiAgICAgICAgTCA9IEogLyAxMSB8IDA7CiAgICAgICAgY29uc3QgbW9udGggPSBKICsgMiAtIDEyICogTCB8IDA7CiAgICAgICAgY29uc3QgeWVhciA9IDEwMCAqIChOIC0gNDkpICsgSSArIEwgfCAwOwogICAgICAgIGxldCBob3VyID0gc2Vjb25kc09mRGF5IC8gVGltZUNvbnN0YW50c19kZWZhdWx0LlNFQ09ORFNfUEVSX0hPVVIgfCAwOwogICAgICAgIGxldCByZW1haW5pbmdTZWNvbmRzID0gc2Vjb25kc09mRGF5IC0gaG91ciAqIFRpbWVDb25zdGFudHNfZGVmYXVsdC5TRUNPTkRTX1BFUl9IT1VSOwogICAgICAgIGNvbnN0IG1pbnV0ZSA9IHJlbWFpbmluZ1NlY29uZHMgLyBUaW1lQ29uc3RhbnRzX2RlZmF1bHQuU0VDT05EU19QRVJfTUlOVVRFIHwgMDsKICAgICAgICByZW1haW5pbmdTZWNvbmRzID0gcmVtYWluaW5nU2Vjb25kcyAtIG1pbnV0ZSAqIFRpbWVDb25zdGFudHNfZGVmYXVsdC5TRUNPTkRTX1BFUl9NSU5VVEU7CiAgICAgICAgbGV0IHNlY29uZCA9IHJlbWFpbmluZ1NlY29uZHMgfCAwOwogICAgICAgIGNvbnN0IG1pbGxpc2Vjb25kID0gKHJlbWFpbmluZ1NlY29uZHMgLSBzZWNvbmQpIC8gVGltZUNvbnN0YW50c19kZWZhdWx0LlNFQ09ORFNfUEVSX01JTExJU0VDT05EOwogICAgICAgIGhvdXIgKz0gMTI7CiAgICAgICAgaWYgKGhvdXIgPiAyMykgewogICAgICAgICAgaG91ciAtPSAyNDsKICAgICAgICB9CiAgICAgICAgaWYgKGlzTGVhcFNlY29uZCkgewogICAgICAgICAgc2Vjb25kICs9IDE7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgR3JlZ29yaWFuRGF0ZV9kZWZhdWx0KAogICAgICAgICAgICB5ZWFyLAogICAgICAgICAgICBtb250aCwKICAgICAgICAgICAgZGF5LAogICAgICAgICAgICBob3VyLAogICAgICAgICAgICBtaW51dGUsCiAgICAgICAgICAgIHNlY29uZCwKICAgICAgICAgICAgbWlsbGlzZWNvbmQsCiAgICAgICAgICAgIGlzTGVhcFNlY29uZAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnllYXIgPSB5ZWFyOwogICAgICAgIHJlc3VsdC5tb250aCA9IG1vbnRoOwogICAgICAgIHJlc3VsdC5kYXkgPSBkYXk7CiAgICAgICAgcmVzdWx0LmhvdXIgPSBob3VyOwogICAgICAgIHJlc3VsdC5taW51dGUgPSBtaW51dGU7CiAgICAgICAgcmVzdWx0LnNlY29uZCA9IHNlY29uZDsKICAgICAgICByZXN1bHQubWlsbGlzZWNvbmQgPSBtaWxsaXNlY29uZDsKICAgICAgICByZXN1bHQuaXNMZWFwU2Vjb25kID0gaXNMZWFwU2Vjb25kOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEp1bGlhbkRhdGUudG9EYXRlID0gZnVuY3Rpb24oanVsaWFuRGF0ZSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGp1bGlhbkRhdGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgianVsaWFuRGF0ZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZ0RhdGUgPSBKdWxpYW5EYXRlLnRvR3JlZ29yaWFuRGF0ZShqdWxpYW5EYXRlLCBncmVnb3JpYW5EYXRlU2NyYXRjaCk7CiAgICAgICAgbGV0IHNlY29uZCA9IGdEYXRlLnNlY29uZDsKICAgICAgICBpZiAoZ0RhdGUuaXNMZWFwU2Vjb25kKSB7CiAgICAgICAgICBzZWNvbmQgLT0gMTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBEYXRlKAogICAgICAgICAgRGF0ZS5VVEMoCiAgICAgICAgICAgIGdEYXRlLnllYXIsCiAgICAgICAgICAgIGdEYXRlLm1vbnRoIC0gMSwKICAgICAgICAgICAgZ0RhdGUuZGF5LAogICAgICAgICAgICBnRGF0ZS5ob3VyLAogICAgICAgICAgICBnRGF0ZS5taW51dGUsCiAgICAgICAgICAgIHNlY29uZCwKICAgICAgICAgICAgZ0RhdGUubWlsbGlzZWNvbmQKICAgICAgICAgICkKICAgICAgICApOwogICAgICB9OwogICAgICBKdWxpYW5EYXRlLnRvSXNvODYwMSA9IGZ1bmN0aW9uKGp1bGlhbkRhdGUsIHByZWNpc2lvbikgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGp1bGlhbkRhdGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgianVsaWFuRGF0ZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZ0RhdGUgPSBKdWxpYW5EYXRlLnRvR3JlZ29yaWFuRGF0ZShqdWxpYW5EYXRlLCBncmVnb3JpYW5EYXRlU2NyYXRjaCk7CiAgICAgICAgbGV0IHllYXIgPSBnRGF0ZS55ZWFyOwogICAgICAgIGxldCBtb250aCA9IGdEYXRlLm1vbnRoOwogICAgICAgIGxldCBkYXkgPSBnRGF0ZS5kYXk7CiAgICAgICAgbGV0IGhvdXIgPSBnRGF0ZS5ob3VyOwogICAgICAgIGNvbnN0IG1pbnV0ZSA9IGdEYXRlLm1pbnV0ZTsKICAgICAgICBjb25zdCBzZWNvbmQgPSBnRGF0ZS5zZWNvbmQ7CiAgICAgICAgY29uc3QgbWlsbGlzZWNvbmQgPSBnRGF0ZS5taWxsaXNlY29uZDsKICAgICAgICBpZiAoeWVhciA9PT0gMWU0ICYmIG1vbnRoID09PSAxICYmIGRheSA9PT0gMSAmJiBob3VyID09PSAwICYmIG1pbnV0ZSA9PT0gMCAmJiBzZWNvbmQgPT09IDAgJiYgbWlsbGlzZWNvbmQgPT09IDApIHsKICAgICAgICAgIHllYXIgPSA5OTk5OwogICAgICAgICAgbW9udGggPSAxMjsKICAgICAgICAgIGRheSA9IDMxOwogICAgICAgICAgaG91ciA9IDI0OwogICAgICAgIH0KICAgICAgICBsZXQgbWlsbGlzZWNvbmRTdHI7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocHJlY2lzaW9uKSAmJiBtaWxsaXNlY29uZCAhPT0gMCkgewogICAgICAgICAgY29uc3QgbWlsbGlzZWNvbmRIdW5kcmVkcyA9IG1pbGxpc2Vjb25kICogMC4wMTsKICAgICAgICAgIG1pbGxpc2Vjb25kU3RyID0gbWlsbGlzZWNvbmRIdW5kcmVkcyA8IDFlLTYgPyBtaWxsaXNlY29uZEh1bmRyZWRzLnRvRml4ZWQoMjApLnJlcGxhY2UoIi4iLCAiIikucmVwbGFjZSgvMCskLywgIiIpIDogbWlsbGlzZWNvbmRIdW5kcmVkcy50b1N0cmluZygpLnJlcGxhY2UoIi4iLCAiIik7CiAgICAgICAgICByZXR1cm4gYCR7eWVhci50b1N0cmluZygpLnBhZFN0YXJ0KDQsICIwIil9LSR7bW9udGgudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAiMCIpfS0ke2RheS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIil9VCR7aG91ci50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIil9OiR7bWludXRlLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKX06JHtzZWNvbmQudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAiMCIpfS4ke21pbGxpc2Vjb25kU3RyfVpgOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwcmVjaXNpb24pIHx8IHByZWNpc2lvbiA9PT0gMCkgewogICAgICAgICAgcmV0dXJuIGAke3llYXIudG9TdHJpbmcoKS5wYWRTdGFydCg0LCAiMCIpfS0ke21vbnRoLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKX0tJHtkYXkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAiMCIpfVQke2hvdXIudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAiMCIpfToke21pbnV0ZS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIil9OiR7c2Vjb25kLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKX1aYDsKICAgICAgICB9CiAgICAgICAgbWlsbGlzZWNvbmRTdHIgPSAobWlsbGlzZWNvbmQgKiAwLjAxKS50b0ZpeGVkKHByZWNpc2lvbikucmVwbGFjZSgiLiIsICIiKS5zbGljZSgwLCBwcmVjaXNpb24pOwogICAgICAgIHJldHVybiBgJHt5ZWFyLnRvU3RyaW5nKCkucGFkU3RhcnQoNCwgIjAiKX0tJHttb250aC50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIil9LSR7ZGF5LnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKX1UJHtob3VyLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKX06JHttaW51dGUudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAiMCIpfToke3NlY29uZC50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIil9LiR7bWlsbGlzZWNvbmRTdHJ9WmA7CiAgICAgIH07CiAgICAgIEp1bGlhbkRhdGUuY2xvbmUgPSBmdW5jdGlvbihqdWxpYW5EYXRlLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChqdWxpYW5EYXRlKSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBKdWxpYW5EYXRlKAogICAgICAgICAgICBqdWxpYW5EYXRlLmRheU51bWJlciwKICAgICAgICAgICAganVsaWFuRGF0ZS5zZWNvbmRzT2ZEYXksCiAgICAgICAgICAgIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmRheU51bWJlciA9IGp1bGlhbkRhdGUuZGF5TnVtYmVyOwogICAgICAgIHJlc3VsdC5zZWNvbmRzT2ZEYXkgPSBqdWxpYW5EYXRlLnNlY29uZHNPZkRheTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBKdWxpYW5EYXRlLmNvbXBhcmUgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGxlZnQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgibGVmdCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmlnaHQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicmlnaHQgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGp1bGlhbkRheU51bWJlckRpZmZlcmVuY2UgPSBsZWZ0LmRheU51bWJlciAtIHJpZ2h0LmRheU51bWJlcjsKICAgICAgICBpZiAoanVsaWFuRGF5TnVtYmVyRGlmZmVyZW5jZSAhPT0gMCkgewogICAgICAgICAgcmV0dXJuIGp1bGlhbkRheU51bWJlckRpZmZlcmVuY2U7CiAgICAgICAgfQogICAgICAgIHJldHVybiBsZWZ0LnNlY29uZHNPZkRheSAtIHJpZ2h0LnNlY29uZHNPZkRheTsKICAgICAgfTsKICAgICAgSnVsaWFuRGF0ZS5lcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiBsZWZ0LmRheU51bWJlciA9PT0gcmlnaHQuZGF5TnVtYmVyICYmIGxlZnQuc2Vjb25kc09mRGF5ID09PSByaWdodC5zZWNvbmRzT2ZEYXk7CiAgICAgIH07CiAgICAgIEp1bGlhbkRhdGUuZXF1YWxzRXBzaWxvbiA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCBlcHNpbG9uKSB7CiAgICAgICAgZXBzaWxvbiA9IGVwc2lsb24gPz8gMDsKICAgICAgICByZXR1cm4gbGVmdCA9PT0gcmlnaHQgfHwgZGVmaW5lZF9kZWZhdWx0KGxlZnQpICYmIGRlZmluZWRfZGVmYXVsdChyaWdodCkgJiYgTWF0aC5hYnMoSnVsaWFuRGF0ZS5zZWNvbmRzRGlmZmVyZW5jZShsZWZ0LCByaWdodCkpIDw9IGVwc2lsb247CiAgICAgIH07CiAgICAgIEp1bGlhbkRhdGUudG90YWxEYXlzID0gZnVuY3Rpb24oanVsaWFuRGF0ZSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGp1bGlhbkRhdGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgianVsaWFuRGF0ZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGp1bGlhbkRhdGUuZGF5TnVtYmVyICsganVsaWFuRGF0ZS5zZWNvbmRzT2ZEYXkgLyBUaW1lQ29uc3RhbnRzX2RlZmF1bHQuU0VDT05EU19QRVJfREFZOwogICAgICB9OwogICAgICBKdWxpYW5EYXRlLnNlY29uZHNEaWZmZXJlbmNlID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChsZWZ0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImxlZnQgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInJpZ2h0IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBkYXlEaWZmZXJlbmNlID0gKGxlZnQuZGF5TnVtYmVyIC0gcmlnaHQuZGF5TnVtYmVyKSAqIFRpbWVDb25zdGFudHNfZGVmYXVsdC5TRUNPTkRTX1BFUl9EQVk7CiAgICAgICAgcmV0dXJuIGRheURpZmZlcmVuY2UgKyAobGVmdC5zZWNvbmRzT2ZEYXkgLSByaWdodC5zZWNvbmRzT2ZEYXkpOwogICAgICB9OwogICAgICBKdWxpYW5EYXRlLmRheXNEaWZmZXJlbmNlID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChsZWZ0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImxlZnQgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInJpZ2h0IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBkYXlEaWZmZXJlbmNlID0gbGVmdC5kYXlOdW1iZXIgLSByaWdodC5kYXlOdW1iZXI7CiAgICAgICAgY29uc3Qgc2Vjb25kRGlmZmVyZW5jZSA9IChsZWZ0LnNlY29uZHNPZkRheSAtIHJpZ2h0LnNlY29uZHNPZkRheSkgLyBUaW1lQ29uc3RhbnRzX2RlZmF1bHQuU0VDT05EU19QRVJfREFZOwogICAgICAgIHJldHVybiBkYXlEaWZmZXJlbmNlICsgc2Vjb25kRGlmZmVyZW5jZTsKICAgICAgfTsKICAgICAgSnVsaWFuRGF0ZS5jb21wdXRlVGFpTWludXNVdGMgPSBmdW5jdGlvbihqdWxpYW5EYXRlKSB7CiAgICAgICAgYmluYXJ5U2VhcmNoU2NyYXRjaExlYXBTZWNvbmQuanVsaWFuRGF0ZSA9IGp1bGlhbkRhdGU7CiAgICAgICAgY29uc3QgbGVhcFNlY29uZHMgPSBKdWxpYW5EYXRlLmxlYXBTZWNvbmRzOwogICAgICAgIGxldCBpbmRleCA9IGJpbmFyeVNlYXJjaF9kZWZhdWx0KAogICAgICAgICAgbGVhcFNlY29uZHMsCiAgICAgICAgICBiaW5hcnlTZWFyY2hTY3JhdGNoTGVhcFNlY29uZCwKICAgICAgICAgIGNvbXBhcmVMZWFwU2Vjb25kRGF0ZXMKICAgICAgICApOwogICAgICAgIGlmIChpbmRleCA8IDApIHsKICAgICAgICAgIGluZGV4ID0gfmluZGV4OwogICAgICAgICAgLS1pbmRleDsKICAgICAgICAgIGlmIChpbmRleCA8IDApIHsKICAgICAgICAgICAgaW5kZXggPSAwOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gbGVhcFNlY29uZHNbaW5kZXhdLm9mZnNldDsKICAgICAgfTsKICAgICAgSnVsaWFuRGF0ZS5hZGRTZWNvbmRzID0gZnVuY3Rpb24oanVsaWFuRGF0ZSwgc2Vjb25kcywgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoanVsaWFuRGF0ZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJqdWxpYW5EYXRlIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChzZWNvbmRzKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInNlY29uZHMgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJyZXN1bHQgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZXRDb21wb25lbnRzKAogICAgICAgICAganVsaWFuRGF0ZS5kYXlOdW1iZXIsCiAgICAgICAgICBqdWxpYW5EYXRlLnNlY29uZHNPZkRheSArIHNlY29uZHMsCiAgICAgICAgICByZXN1bHQKICAgICAgICApOwogICAgICB9OwogICAgICBKdWxpYW5EYXRlLmFkZE1pbnV0ZXMgPSBmdW5jdGlvbihqdWxpYW5EYXRlLCBtaW51dGVzLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChqdWxpYW5EYXRlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImp1bGlhbkRhdGUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG1pbnV0ZXMpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgibWludXRlcyBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInJlc3VsdCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbmV3U2Vjb25kc09mRGF5ID0ganVsaWFuRGF0ZS5zZWNvbmRzT2ZEYXkgKyBtaW51dGVzICogVGltZUNvbnN0YW50c19kZWZhdWx0LlNFQ09ORFNfUEVSX01JTlVURTsKICAgICAgICByZXR1cm4gc2V0Q29tcG9uZW50cyhqdWxpYW5EYXRlLmRheU51bWJlciwgbmV3U2Vjb25kc09mRGF5LCByZXN1bHQpOwogICAgICB9OwogICAgICBKdWxpYW5EYXRlLmFkZEhvdXJzID0gZnVuY3Rpb24oanVsaWFuRGF0ZSwgaG91cnMsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGp1bGlhbkRhdGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgianVsaWFuRGF0ZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaG91cnMpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiaG91cnMgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJyZXN1bHQgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG5ld1NlY29uZHNPZkRheSA9IGp1bGlhbkRhdGUuc2Vjb25kc09mRGF5ICsgaG91cnMgKiBUaW1lQ29uc3RhbnRzX2RlZmF1bHQuU0VDT05EU19QRVJfSE9VUjsKICAgICAgICByZXR1cm4gc2V0Q29tcG9uZW50cyhqdWxpYW5EYXRlLmRheU51bWJlciwgbmV3U2Vjb25kc09mRGF5LCByZXN1bHQpOwogICAgICB9OwogICAgICBKdWxpYW5EYXRlLmFkZERheXMgPSBmdW5jdGlvbihqdWxpYW5EYXRlLCBkYXlzLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChqdWxpYW5EYXRlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImp1bGlhbkRhdGUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGRheXMpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZGF5cyBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInJlc3VsdCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbmV3SnVsaWFuRGF5TnVtYmVyID0ganVsaWFuRGF0ZS5kYXlOdW1iZXIgKyBkYXlzOwogICAgICAgIHJldHVybiBzZXRDb21wb25lbnRzKG5ld0p1bGlhbkRheU51bWJlciwganVsaWFuRGF0ZS5zZWNvbmRzT2ZEYXksIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIEp1bGlhbkRhdGUubGVzc1RoYW4gPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIHJldHVybiBKdWxpYW5EYXRlLmNvbXBhcmUobGVmdCwgcmlnaHQpIDwgMDsKICAgICAgfTsKICAgICAgSnVsaWFuRGF0ZS5sZXNzVGhhbk9yRXF1YWxzID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHsKICAgICAgICByZXR1cm4gSnVsaWFuRGF0ZS5jb21wYXJlKGxlZnQsIHJpZ2h0KSA8PSAwOwogICAgICB9OwogICAgICBKdWxpYW5EYXRlLmdyZWF0ZXJUaGFuID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHsKICAgICAgICByZXR1cm4gSnVsaWFuRGF0ZS5jb21wYXJlKGxlZnQsIHJpZ2h0KSA+IDA7CiAgICAgIH07CiAgICAgIEp1bGlhbkRhdGUuZ3JlYXRlclRoYW5PckVxdWFscyA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIEp1bGlhbkRhdGUuY29tcGFyZShsZWZ0LCByaWdodCkgPj0gMDsKICAgICAgfTsKICAgICAgSnVsaWFuRGF0ZS5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICByZXR1cm4gSnVsaWFuRGF0ZS5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBKdWxpYW5EYXRlLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbihyaWdodCkgewogICAgICAgIHJldHVybiBKdWxpYW5EYXRlLmVxdWFscyh0aGlzLCByaWdodCk7CiAgICAgIH07CiAgICAgIEp1bGlhbkRhdGUucHJvdG90eXBlLmVxdWFsc0Vwc2lsb24gPSBmdW5jdGlvbihyaWdodCwgZXBzaWxvbikgewogICAgICAgIHJldHVybiBKdWxpYW5EYXRlLmVxdWFsc0Vwc2lsb24odGhpcywgcmlnaHQsIGVwc2lsb24pOwogICAgICB9OwogICAgICBKdWxpYW5EYXRlLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBKdWxpYW5EYXRlLnRvSXNvODYwMSh0aGlzKTsKICAgICAgfTsKICAgICAgSnVsaWFuRGF0ZS5sZWFwU2Vjb25kcyA9IFsKICAgICAgICBuZXcgTGVhcFNlY29uZF9kZWZhdWx0KG5ldyBKdWxpYW5EYXRlKDI0NDEzMTcsIDQzMjEwLCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5UQUkpLCAxMCksCiAgICAgICAgLy8gSmFudWFyeSAxLCAxOTcyIDAwOjAwOjAwIFVUQwogICAgICAgIG5ldyBMZWFwU2Vjb25kX2RlZmF1bHQobmV3IEp1bGlhbkRhdGUoMjQ0MTQ5OSwgNDMyMTEsIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSSksIDExKSwKICAgICAgICAvLyBKdWx5IDEsIDE5NzIgMDA6MDA6MDAgVVRDCiAgICAgICAgbmV3IExlYXBTZWNvbmRfZGVmYXVsdChuZXcgSnVsaWFuRGF0ZSgyNDQxNjgzLCA0MzIxMiwgVGltZVN0YW5kYXJkX2RlZmF1bHQuVEFJKSwgMTIpLAogICAgICAgIC8vIEphbnVhcnkgMSwgMTk3MyAwMDowMDowMCBVVEMKICAgICAgICBuZXcgTGVhcFNlY29uZF9kZWZhdWx0KG5ldyBKdWxpYW5EYXRlKDI0NDIwNDgsIDQzMjEzLCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5UQUkpLCAxMyksCiAgICAgICAgLy8gSmFudWFyeSAxLCAxOTc0IDAwOjAwOjAwIFVUQwogICAgICAgIG5ldyBMZWFwU2Vjb25kX2RlZmF1bHQobmV3IEp1bGlhbkRhdGUoMjQ0MjQxMywgNDMyMTQsIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSSksIDE0KSwKICAgICAgICAvLyBKYW51YXJ5IDEsIDE5NzUgMDA6MDA6MDAgVVRDCiAgICAgICAgbmV3IExlYXBTZWNvbmRfZGVmYXVsdChuZXcgSnVsaWFuRGF0ZSgyNDQyNzc4LCA0MzIxNSwgVGltZVN0YW5kYXJkX2RlZmF1bHQuVEFJKSwgMTUpLAogICAgICAgIC8vIEphbnVhcnkgMSwgMTk3NiAwMDowMDowMCBVVEMKICAgICAgICBuZXcgTGVhcFNlY29uZF9kZWZhdWx0KG5ldyBKdWxpYW5EYXRlKDI0NDMxNDQsIDQzMjE2LCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5UQUkpLCAxNiksCiAgICAgICAgLy8gSmFudWFyeSAxLCAxOTc3IDAwOjAwOjAwIFVUQwogICAgICAgIG5ldyBMZWFwU2Vjb25kX2RlZmF1bHQobmV3IEp1bGlhbkRhdGUoMjQ0MzUwOSwgNDMyMTcsIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSSksIDE3KSwKICAgICAgICAvLyBKYW51YXJ5IDEsIDE5NzggMDA6MDA6MDAgVVRDCiAgICAgICAgbmV3IExlYXBTZWNvbmRfZGVmYXVsdChuZXcgSnVsaWFuRGF0ZSgyNDQzODc0LCA0MzIxOCwgVGltZVN0YW5kYXJkX2RlZmF1bHQuVEFJKSwgMTgpLAogICAgICAgIC8vIEphbnVhcnkgMSwgMTk3OSAwMDowMDowMCBVVEMKICAgICAgICBuZXcgTGVhcFNlY29uZF9kZWZhdWx0KG5ldyBKdWxpYW5EYXRlKDI0NDQyMzksIDQzMjE5LCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5UQUkpLCAxOSksCiAgICAgICAgLy8gSmFudWFyeSAxLCAxOTgwIDAwOjAwOjAwIFVUQwogICAgICAgIG5ldyBMZWFwU2Vjb25kX2RlZmF1bHQobmV3IEp1bGlhbkRhdGUoMjQ0NDc4NiwgNDMyMjAsIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSSksIDIwKSwKICAgICAgICAvLyBKdWx5IDEsIDE5ODEgMDA6MDA6MDAgVVRDCiAgICAgICAgbmV3IExlYXBTZWNvbmRfZGVmYXVsdChuZXcgSnVsaWFuRGF0ZSgyNDQ1MTUxLCA0MzIyMSwgVGltZVN0YW5kYXJkX2RlZmF1bHQuVEFJKSwgMjEpLAogICAgICAgIC8vIEp1bHkgMSwgMTk4MiAwMDowMDowMCBVVEMKICAgICAgICBuZXcgTGVhcFNlY29uZF9kZWZhdWx0KG5ldyBKdWxpYW5EYXRlKDI0NDU1MTYsIDQzMjIyLCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5UQUkpLCAyMiksCiAgICAgICAgLy8gSnVseSAxLCAxOTgzIDAwOjAwOjAwIFVUQwogICAgICAgIG5ldyBMZWFwU2Vjb25kX2RlZmF1bHQobmV3IEp1bGlhbkRhdGUoMjQ0NjI0NywgNDMyMjMsIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSSksIDIzKSwKICAgICAgICAvLyBKdWx5IDEsIDE5ODUgMDA6MDA6MDAgVVRDCiAgICAgICAgbmV3IExlYXBTZWNvbmRfZGVmYXVsdChuZXcgSnVsaWFuRGF0ZSgyNDQ3MTYxLCA0MzIyNCwgVGltZVN0YW5kYXJkX2RlZmF1bHQuVEFJKSwgMjQpLAogICAgICAgIC8vIEphbnVhcnkgMSwgMTk4OCAwMDowMDowMCBVVEMKICAgICAgICBuZXcgTGVhcFNlY29uZF9kZWZhdWx0KG5ldyBKdWxpYW5EYXRlKDI0NDc4OTIsIDQzMjI1LCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5UQUkpLCAyNSksCiAgICAgICAgLy8gSmFudWFyeSAxLCAxOTkwIDAwOjAwOjAwIFVUQwogICAgICAgIG5ldyBMZWFwU2Vjb25kX2RlZmF1bHQobmV3IEp1bGlhbkRhdGUoMjQ0ODI1NywgNDMyMjYsIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSSksIDI2KSwKICAgICAgICAvLyBKYW51YXJ5IDEsIDE5OTEgMDA6MDA6MDAgVVRDCiAgICAgICAgbmV3IExlYXBTZWNvbmRfZGVmYXVsdChuZXcgSnVsaWFuRGF0ZSgyNDQ4ODA0LCA0MzIyNywgVGltZVN0YW5kYXJkX2RlZmF1bHQuVEFJKSwgMjcpLAogICAgICAgIC8vIEp1bHkgMSwgMTk5MiAwMDowMDowMCBVVEMKICAgICAgICBuZXcgTGVhcFNlY29uZF9kZWZhdWx0KG5ldyBKdWxpYW5EYXRlKDI0NDkxNjksIDQzMjI4LCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5UQUkpLCAyOCksCiAgICAgICAgLy8gSnVseSAxLCAxOTkzIDAwOjAwOjAwIFVUQwogICAgICAgIG5ldyBMZWFwU2Vjb25kX2RlZmF1bHQobmV3IEp1bGlhbkRhdGUoMjQ0OTUzNCwgNDMyMjksIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSSksIDI5KSwKICAgICAgICAvLyBKdWx5IDEsIDE5OTQgMDA6MDA6MDAgVVRDCiAgICAgICAgbmV3IExlYXBTZWNvbmRfZGVmYXVsdChuZXcgSnVsaWFuRGF0ZSgyNDUwMDgzLCA0MzIzMCwgVGltZVN0YW5kYXJkX2RlZmF1bHQuVEFJKSwgMzApLAogICAgICAgIC8vIEphbnVhcnkgMSwgMTk5NiAwMDowMDowMCBVVEMKICAgICAgICBuZXcgTGVhcFNlY29uZF9kZWZhdWx0KG5ldyBKdWxpYW5EYXRlKDI0NTA2MzAsIDQzMjMxLCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5UQUkpLCAzMSksCiAgICAgICAgLy8gSnVseSAxLCAxOTk3IDAwOjAwOjAwIFVUQwogICAgICAgIG5ldyBMZWFwU2Vjb25kX2RlZmF1bHQobmV3IEp1bGlhbkRhdGUoMjQ1MTE3OSwgNDMyMzIsIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSSksIDMyKSwKICAgICAgICAvLyBKYW51YXJ5IDEsIDE5OTkgMDA6MDA6MDAgVVRDCiAgICAgICAgbmV3IExlYXBTZWNvbmRfZGVmYXVsdChuZXcgSnVsaWFuRGF0ZSgyNDUzNzM2LCA0MzIzMywgVGltZVN0YW5kYXJkX2RlZmF1bHQuVEFJKSwgMzMpLAogICAgICAgIC8vIEphbnVhcnkgMSwgMjAwNiAwMDowMDowMCBVVEMKICAgICAgICBuZXcgTGVhcFNlY29uZF9kZWZhdWx0KG5ldyBKdWxpYW5EYXRlKDI0NTQ4MzIsIDQzMjM0LCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5UQUkpLCAzNCksCiAgICAgICAgLy8gSmFudWFyeSAxLCAyMDA5IDAwOjAwOjAwIFVUQwogICAgICAgIG5ldyBMZWFwU2Vjb25kX2RlZmF1bHQobmV3IEp1bGlhbkRhdGUoMjQ1NjEwOSwgNDMyMzUsIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSSksIDM1KSwKICAgICAgICAvLyBKdWx5IDEsIDIwMTIgMDA6MDA6MDAgVVRDCiAgICAgICAgbmV3IExlYXBTZWNvbmRfZGVmYXVsdChuZXcgSnVsaWFuRGF0ZSgyNDU3MjA0LCA0MzIzNiwgVGltZVN0YW5kYXJkX2RlZmF1bHQuVEFJKSwgMzYpLAogICAgICAgIC8vIEp1bHkgMSwgMjAxNSAwMDowMDowMCBVVEMKICAgICAgICBuZXcgTGVhcFNlY29uZF9kZWZhdWx0KG5ldyBKdWxpYW5EYXRlKDI0NTc3NTQsIDQzMjM3LCBUaW1lU3RhbmRhcmRfZGVmYXVsdC5UQUkpLCAzNykKICAgICAgICAvLyBKYW51YXJ5IDEsIDIwMTcgMDA6MDA6MDAgVVRDCiAgICAgIF07CiAgICAgIEp1bGlhbkRhdGVfZGVmYXVsdCA9IEp1bGlhbkRhdGU7CiAgICB9CiAgfSk7CgogIC8vIG5vZGVfbW9kdWxlcy91cmlqcy9zcmMvcHVueWNvZGUuanMKICB2YXIgcmVxdWlyZV9wdW55Y29kZSA9IF9fY29tbW9uSlMoewogICAgIm5vZGVfbW9kdWxlcy91cmlqcy9zcmMvcHVueWNvZGUuanMiKGV4cG9ydHMyLCBtb2R1bGUpIHsKICAgICAgLyohIGh0dHBzOi8vbXRocy5iZS9wdW55Y29kZSB2MS40LjAgYnkgQG1hdGhpYXMgKi8KICAgICAgKGZ1bmN0aW9uKHJvb3QpIHsKICAgICAgICB2YXIgZnJlZUV4cG9ydHMgPSB0eXBlb2YgZXhwb3J0czIgPT0gIm9iamVjdCIgJiYgZXhwb3J0czIgJiYgIWV4cG9ydHMyLm5vZGVUeXBlICYmIGV4cG9ydHMyOwogICAgICAgIHZhciBmcmVlTW9kdWxlID0gdHlwZW9mIG1vZHVsZSA9PSAib2JqZWN0IiAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7CiAgICAgICAgdmFyIGZyZWVHbG9iYWwgPSB0eXBlb2YgZ2xvYmFsID09ICJvYmplY3QiICYmIGdsb2JhbDsKICAgICAgICBpZiAoZnJlZUdsb2JhbC5nbG9iYWwgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC5zZWxmID09PSBmcmVlR2xvYmFsKSB7CiAgICAgICAgICByb290ID0gZnJlZUdsb2JhbDsKICAgICAgICB9CiAgICAgICAgdmFyIHB1bnljb2RlLCBtYXhJbnQgPSAyMTQ3NDgzNjQ3LCBiYXNlID0gMzYsIHRNaW4gPSAxLCB0TWF4ID0gMjYsIHNrZXcgPSAzOCwgZGFtcCA9IDcwMCwgaW5pdGlhbEJpYXMgPSA3MiwgaW5pdGlhbE4gPSAxMjgsIGRlbGltaXRlciA9ICItIiwgcmVnZXhQdW55Y29kZSA9IC9eeG4tLS8sIHJlZ2V4Tm9uQVNDSUkgPSAvW15ceDIwLVx4N0VdLywgcmVnZXhTZXBhcmF0b3JzID0gL1tceDJFXHUzMDAyXHVGRjBFXHVGRjYxXS9nLCBlcnJvcnMgPSB7CiAgICAgICAgICAib3ZlcmZsb3ciOiAiT3ZlcmZsb3c6IGlucHV0IG5lZWRzIHdpZGVyIGludGVnZXJzIHRvIHByb2Nlc3MiLAogICAgICAgICAgIm5vdC1iYXNpYyI6ICJJbGxlZ2FsIGlucHV0ID49IDB4ODAgKG5vdCBhIGJhc2ljIGNvZGUgcG9pbnQpIiwKICAgICAgICAgICJpbnZhbGlkLWlucHV0IjogIkludmFsaWQgaW5wdXQiCiAgICAgICAgfSwgYmFzZU1pbnVzVE1pbiA9IGJhc2UgLSB0TWluLCBmbG9vciA9IE1hdGguZmxvb3IsIHN0cmluZ0Zyb21DaGFyQ29kZSA9IFN0cmluZy5mcm9tQ2hhckNvZGUsIGtleTsKICAgICAgICBmdW5jdGlvbiBlcnJvcih0eXBlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihlcnJvcnNbdHlwZV0pOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBtYXAoYXJyYXksIGZuKSB7CiAgICAgICAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoOwogICAgICAgICAgdmFyIHJlc3VsdCA9IFtdOwogICAgICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7CiAgICAgICAgICAgIHJlc3VsdFtsZW5ndGhdID0gZm4oYXJyYXlbbGVuZ3RoXSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBtYXBEb21haW4oc3RyaW5nLCBmbikgewogICAgICAgICAgdmFyIHBhcnRzID0gc3RyaW5nLnNwbGl0KCJAIik7CiAgICAgICAgICB2YXIgcmVzdWx0ID0gIiI7CiAgICAgICAgICBpZiAocGFydHMubGVuZ3RoID4gMSkgewogICAgICAgICAgICByZXN1bHQgPSBwYXJ0c1swXSArICJAIjsKICAgICAgICAgICAgc3RyaW5nID0gcGFydHNbMV07CiAgICAgICAgICB9CiAgICAgICAgICBzdHJpbmcgPSBzdHJpbmcucmVwbGFjZShyZWdleFNlcGFyYXRvcnMsICIuIik7CiAgICAgICAgICB2YXIgbGFiZWxzID0gc3RyaW5nLnNwbGl0KCIuIik7CiAgICAgICAgICB2YXIgZW5jb2RlZCA9IG1hcChsYWJlbHMsIGZuKS5qb2luKCIuIik7CiAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgZW5jb2RlZDsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gdWNzMmRlY29kZShzdHJpbmcpIHsKICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSwgY291bnRlciA9IDAsIGxlbmd0aCA9IHN0cmluZy5sZW5ndGgsIHZhbHVlLCBleHRyYTsKICAgICAgICAgIHdoaWxlIChjb3VudGVyIDwgbGVuZ3RoKSB7CiAgICAgICAgICAgIHZhbHVlID0gc3RyaW5nLmNoYXJDb2RlQXQoY291bnRlcisrKTsKICAgICAgICAgICAgaWYgKHZhbHVlID49IDU1Mjk2ICYmIHZhbHVlIDw9IDU2MzE5ICYmIGNvdW50ZXIgPCBsZW5ndGgpIHsKICAgICAgICAgICAgICBleHRyYSA9IHN0cmluZy5jaGFyQ29kZUF0KGNvdW50ZXIrKyk7CiAgICAgICAgICAgICAgaWYgKChleHRyYSAmIDY0NTEyKSA9PSA1NjMyMCkgewogICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goKCh2YWx1ZSAmIDEwMjMpIDw8IDEwKSArIChleHRyYSAmIDEwMjMpICsgNjU1MzYpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBvdXRwdXQucHVzaCh2YWx1ZSk7CiAgICAgICAgICAgICAgICBjb3VudGVyLS07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIG91dHB1dC5wdXNoKHZhbHVlKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG91dHB1dDsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gdWNzMmVuY29kZShhcnJheSkgewogICAgICAgICAgcmV0dXJuIG1hcChhcnJheSwgZnVuY3Rpb24odmFsdWUpIHsKICAgICAgICAgICAgdmFyIG91dHB1dCA9ICIiOwogICAgICAgICAgICBpZiAodmFsdWUgPiA2NTUzNSkgewogICAgICAgICAgICAgIHZhbHVlIC09IDY1NTM2OwogICAgICAgICAgICAgIG91dHB1dCArPSBzdHJpbmdGcm9tQ2hhckNvZGUodmFsdWUgPj4+IDEwICYgMTAyMyB8IDU1Mjk2KTsKICAgICAgICAgICAgICB2YWx1ZSA9IDU2MzIwIHwgdmFsdWUgJiAxMDIzOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG91dHB1dCArPSBzdHJpbmdGcm9tQ2hhckNvZGUodmFsdWUpOwogICAgICAgICAgICByZXR1cm4gb3V0cHV0OwogICAgICAgICAgfSkuam9pbigiIik7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGJhc2ljVG9EaWdpdChjb2RlUG9pbnQpIHsKICAgICAgICAgIGlmIChjb2RlUG9pbnQgLSA0OCA8IDEwKSB7CiAgICAgICAgICAgIHJldHVybiBjb2RlUG9pbnQgLSAyMjsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChjb2RlUG9pbnQgLSA2NSA8IDI2KSB7CiAgICAgICAgICAgIHJldHVybiBjb2RlUG9pbnQgLSA2NTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChjb2RlUG9pbnQgLSA5NyA8IDI2KSB7CiAgICAgICAgICAgIHJldHVybiBjb2RlUG9pbnQgLSA5NzsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBiYXNlOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBkaWdpdFRvQmFzaWMoZGlnaXQsIGZsYWcpIHsKICAgICAgICAgIHJldHVybiBkaWdpdCArIDIyICsgNzUgKiAoZGlnaXQgPCAyNikgLSAoKGZsYWcgIT0gMCkgPDwgNSk7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGFkYXB0KGRlbHRhLCBudW1Qb2ludHMsIGZpcnN0VGltZSkgewogICAgICAgICAgdmFyIGsgPSAwOwogICAgICAgICAgZGVsdGEgPSBmaXJzdFRpbWUgPyBmbG9vcihkZWx0YSAvIGRhbXApIDogZGVsdGEgPj4gMTsKICAgICAgICAgIGRlbHRhICs9IGZsb29yKGRlbHRhIC8gbnVtUG9pbnRzKTsKICAgICAgICAgIGZvciAoOyBkZWx0YSA+IGJhc2VNaW51c1RNaW4gKiB0TWF4ID4+IDE7IGsgKz0gYmFzZSkgewogICAgICAgICAgICBkZWx0YSA9IGZsb29yKGRlbHRhIC8gYmFzZU1pbnVzVE1pbik7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZmxvb3IoayArIChiYXNlTWludXNUTWluICsgMSkgKiBkZWx0YSAvIChkZWx0YSArIHNrZXcpKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gZGVjb2RlMyhpbnB1dCkgewogICAgICAgICAgdmFyIG91dHB1dCA9IFtdLCBpbnB1dExlbmd0aCA9IGlucHV0Lmxlbmd0aCwgb3V0LCBpID0gMCwgbiA9IGluaXRpYWxOLCBiaWFzID0gaW5pdGlhbEJpYXMsIGJhc2ljLCBqLCBpbmRleCwgb2xkaSwgdywgaywgZGlnaXQsIHQsIGJhc2VNaW51c1Q7CiAgICAgICAgICBiYXNpYyA9IGlucHV0Lmxhc3RJbmRleE9mKGRlbGltaXRlcik7CiAgICAgICAgICBpZiAoYmFzaWMgPCAwKSB7CiAgICAgICAgICAgIGJhc2ljID0gMDsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBiYXNpYzsgKytqKSB7CiAgICAgICAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KGopID49IDEyOCkgewogICAgICAgICAgICAgIGVycm9yKCJub3QtYmFzaWMiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvdXRwdXQucHVzaChpbnB1dC5jaGFyQ29kZUF0KGopKTsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAoaW5kZXggPSBiYXNpYyA+IDAgPyBiYXNpYyArIDEgOiAwOyBpbmRleCA8IGlucHV0TGVuZ3RoOyApIHsKICAgICAgICAgICAgZm9yIChvbGRpID0gaSwgdyA9IDEsIGsgPSBiYXNlOyA7IGsgKz0gYmFzZSkgewogICAgICAgICAgICAgIGlmIChpbmRleCA+PSBpbnB1dExlbmd0aCkgewogICAgICAgICAgICAgICAgZXJyb3IoImludmFsaWQtaW5wdXQiKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgZGlnaXQgPSBiYXNpY1RvRGlnaXQoaW5wdXQuY2hhckNvZGVBdChpbmRleCsrKSk7CiAgICAgICAgICAgICAgaWYgKGRpZ2l0ID49IGJhc2UgfHwgZGlnaXQgPiBmbG9vcigobWF4SW50IC0gaSkgLyB3KSkgewogICAgICAgICAgICAgICAgZXJyb3IoIm92ZXJmbG93Iik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGkgKz0gZGlnaXQgKiB3OwogICAgICAgICAgICAgIHQgPSBrIDw9IGJpYXMgPyB0TWluIDogayA+PSBiaWFzICsgdE1heCA/IHRNYXggOiBrIC0gYmlhczsKICAgICAgICAgICAgICBpZiAoZGlnaXQgPCB0KSB7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYmFzZU1pbnVzVCA9IGJhc2UgLSB0OwogICAgICAgICAgICAgIGlmICh3ID4gZmxvb3IobWF4SW50IC8gYmFzZU1pbnVzVCkpIHsKICAgICAgICAgICAgICAgIGVycm9yKCJvdmVyZmxvdyIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB3ICo9IGJhc2VNaW51c1Q7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb3V0ID0gb3V0cHV0Lmxlbmd0aCArIDE7CiAgICAgICAgICAgIGJpYXMgPSBhZGFwdChpIC0gb2xkaSwgb3V0LCBvbGRpID09IDApOwogICAgICAgICAgICBpZiAoZmxvb3IoaSAvIG91dCkgPiBtYXhJbnQgLSBuKSB7CiAgICAgICAgICAgICAgZXJyb3IoIm92ZXJmbG93Iik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbiArPSBmbG9vcihpIC8gb3V0KTsKICAgICAgICAgICAgaSAlPSBvdXQ7CiAgICAgICAgICAgIG91dHB1dC5zcGxpY2UoaSsrLCAwLCBuKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB1Y3MyZW5jb2RlKG91dHB1dCk7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGVuY29kZShpbnB1dCkgewogICAgICAgICAgdmFyIG4sIGRlbHRhLCBoYW5kbGVkQ1BDb3VudCwgYmFzaWNMZW5ndGgsIGJpYXMsIGosIG0sIHEsIGssIHQsIGN1cnJlbnRWYWx1ZSwgb3V0cHV0ID0gW10sIGlucHV0TGVuZ3RoLCBoYW5kbGVkQ1BDb3VudFBsdXNPbmUsIGJhc2VNaW51c1QsIHFNaW51c1Q7CiAgICAgICAgICBpbnB1dCA9IHVjczJkZWNvZGUoaW5wdXQpOwogICAgICAgICAgaW5wdXRMZW5ndGggPSBpbnB1dC5sZW5ndGg7CiAgICAgICAgICBuID0gaW5pdGlhbE47CiAgICAgICAgICBkZWx0YSA9IDA7CiAgICAgICAgICBiaWFzID0gaW5pdGlhbEJpYXM7CiAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgaW5wdXRMZW5ndGg7ICsraikgewogICAgICAgICAgICBjdXJyZW50VmFsdWUgPSBpbnB1dFtqXTsKICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA8IDEyOCkgewogICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0cmluZ0Zyb21DaGFyQ29kZShjdXJyZW50VmFsdWUpKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaGFuZGxlZENQQ291bnQgPSBiYXNpY0xlbmd0aCA9IG91dHB1dC5sZW5ndGg7CiAgICAgICAgICBpZiAoYmFzaWNMZW5ndGgpIHsKICAgICAgICAgICAgb3V0cHV0LnB1c2goZGVsaW1pdGVyKTsKICAgICAgICAgIH0KICAgICAgICAgIHdoaWxlIChoYW5kbGVkQ1BDb3VudCA8IGlucHV0TGVuZ3RoKSB7CiAgICAgICAgICAgIGZvciAobSA9IG1heEludCwgaiA9IDA7IGogPCBpbnB1dExlbmd0aDsgKytqKSB7CiAgICAgICAgICAgICAgY3VycmVudFZhbHVlID0gaW5wdXRbal07CiAgICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA+PSBuICYmIGN1cnJlbnRWYWx1ZSA8IG0pIHsKICAgICAgICAgICAgICAgIG0gPSBjdXJyZW50VmFsdWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGhhbmRsZWRDUENvdW50UGx1c09uZSA9IGhhbmRsZWRDUENvdW50ICsgMTsKICAgICAgICAgICAgaWYgKG0gLSBuID4gZmxvb3IoKG1heEludCAtIGRlbHRhKSAvIGhhbmRsZWRDUENvdW50UGx1c09uZSkpIHsKICAgICAgICAgICAgICBlcnJvcigib3ZlcmZsb3ciKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBkZWx0YSArPSAobSAtIG4pICogaGFuZGxlZENQQ291bnRQbHVzT25lOwogICAgICAgICAgICBuID0gbTsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGlucHV0TGVuZ3RoOyArK2opIHsKICAgICAgICAgICAgICBjdXJyZW50VmFsdWUgPSBpbnB1dFtqXTsKICAgICAgICAgICAgICBpZiAoY3VycmVudFZhbHVlIDwgbiAmJiArK2RlbHRhID4gbWF4SW50KSB7CiAgICAgICAgICAgICAgICBlcnJvcigib3ZlcmZsb3ciKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA9PSBuKSB7CiAgICAgICAgICAgICAgICBmb3IgKHEgPSBkZWx0YSwgayA9IGJhc2U7IDsgayArPSBiYXNlKSB7CiAgICAgICAgICAgICAgICAgIHQgPSBrIDw9IGJpYXMgPyB0TWluIDogayA+PSBiaWFzICsgdE1heCA/IHRNYXggOiBrIC0gYmlhczsKICAgICAgICAgICAgICAgICAgaWYgKHEgPCB0KSB7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgcU1pbnVzVCA9IHEgLSB0OwogICAgICAgICAgICAgICAgICBiYXNlTWludXNUID0gYmFzZSAtIHQ7CiAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKAogICAgICAgICAgICAgICAgICAgIHN0cmluZ0Zyb21DaGFyQ29kZShkaWdpdFRvQmFzaWModCArIHFNaW51c1QgJSBiYXNlTWludXNULCAwKSkKICAgICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgICAgcSA9IGZsb29yKHFNaW51c1QgLyBiYXNlTWludXNUKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0cmluZ0Zyb21DaGFyQ29kZShkaWdpdFRvQmFzaWMocSwgMCkpKTsKICAgICAgICAgICAgICAgIGJpYXMgPSBhZGFwdChkZWx0YSwgaGFuZGxlZENQQ291bnRQbHVzT25lLCBoYW5kbGVkQ1BDb3VudCA9PSBiYXNpY0xlbmd0aCk7CiAgICAgICAgICAgICAgICBkZWx0YSA9IDA7CiAgICAgICAgICAgICAgICArK2hhbmRsZWRDUENvdW50OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICArK2RlbHRhOwogICAgICAgICAgICArK247CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gb3V0cHV0LmpvaW4oIiIpOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiB0b1VuaWNvZGUoaW5wdXQpIHsKICAgICAgICAgIHJldHVybiBtYXBEb21haW4oaW5wdXQsIGZ1bmN0aW9uKHN0cmluZykgewogICAgICAgICAgICByZXR1cm4gcmVnZXhQdW55Y29kZS50ZXN0KHN0cmluZykgPyBkZWNvZGUzKHN0cmluZy5zbGljZSg0KS50b0xvd2VyQ2FzZSgpKSA6IHN0cmluZzsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiB0b0FTQ0lJKGlucHV0KSB7CiAgICAgICAgICByZXR1cm4gbWFwRG9tYWluKGlucHV0LCBmdW5jdGlvbihzdHJpbmcpIHsKICAgICAgICAgICAgcmV0dXJuIHJlZ2V4Tm9uQVNDSUkudGVzdChzdHJpbmcpID8gInhuLS0iICsgZW5jb2RlKHN0cmluZykgOiBzdHJpbmc7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgcHVueWNvZGUgPSB7CiAgICAgICAgICAvKioKICAgICAgICAgICAqIEEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgY3VycmVudCBQdW55Y29kZS5qcyB2ZXJzaW9uIG51bWJlci4KICAgICAgICAgICAqIEBtZW1iZXJPZiBwdW55Y29kZQogICAgICAgICAgICogQHR5cGUgU3RyaW5nCiAgICAgICAgICAgKi8KICAgICAgICAgICJ2ZXJzaW9uIjogIjEuMy4yIiwKICAgICAgICAgIC8qKgogICAgICAgICAgICogQW4gb2JqZWN0IG9mIG1ldGhvZHMgdG8gY29udmVydCBmcm9tIEphdmFTY3JpcHQncyBpbnRlcm5hbCBjaGFyYWN0ZXIKICAgICAgICAgICAqIHJlcHJlc2VudGF0aW9uIChVQ1MtMikgdG8gVW5pY29kZSBjb2RlIHBvaW50cywgYW5kIGJhY2suCiAgICAgICAgICAgKiBAc2VlIDxodHRwczovL21hdGhpYXNieW5lbnMuYmUvbm90ZXMvamF2YXNjcmlwdC1lbmNvZGluZz4KICAgICAgICAgICAqIEBtZW1iZXJPZiBwdW55Y29kZQogICAgICAgICAgICogQHR5cGUgT2JqZWN0CiAgICAgICAgICAgKi8KICAgICAgICAgICJ1Y3MyIjogewogICAgICAgICAgICAiZGVjb2RlIjogdWNzMmRlY29kZSwKICAgICAgICAgICAgImVuY29kZSI6IHVjczJlbmNvZGUKICAgICAgICAgIH0sCiAgICAgICAgICAiZGVjb2RlIjogZGVjb2RlMywKICAgICAgICAgICJlbmNvZGUiOiBlbmNvZGUsCiAgICAgICAgICAidG9BU0NJSSI6IHRvQVNDSUksCiAgICAgICAgICAidG9Vbmljb2RlIjogdG9Vbmljb2RlCiAgICAgICAgfTsKICAgICAgICBpZiAodHlwZW9mIGRlZmluZSA9PSAiZnVuY3Rpb24iICYmIHR5cGVvZiBkZWZpbmUuYW1kID09ICJvYmplY3QiICYmIGRlZmluZS5hbWQpIHsKICAgICAgICAgIGRlZmluZSgicHVueWNvZGUiLCBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHB1bnljb2RlOwogICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIGlmIChmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlKSB7CiAgICAgICAgICBpZiAobW9kdWxlLmV4cG9ydHMgPT0gZnJlZUV4cG9ydHMpIHsKICAgICAgICAgICAgZnJlZU1vZHVsZS5leHBvcnRzID0gcHVueWNvZGU7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmb3IgKGtleSBpbiBwdW55Y29kZSkgewogICAgICAgICAgICAgIHB1bnljb2RlLmhhc093blByb3BlcnR5KGtleSkgJiYgKGZyZWVFeHBvcnRzW2tleV0gPSBwdW55Y29kZVtrZXldKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByb290LnB1bnljb2RlID0gcHVueWNvZGU7CiAgICAgICAgfQogICAgICB9KShleHBvcnRzMik7CiAgICB9CiAgfSk7CgogIC8vIG5vZGVfbW9kdWxlcy91cmlqcy9zcmMvSVB2Ni5qcwogIHZhciByZXF1aXJlX0lQdjYgPSBfX2NvbW1vbkpTKHsKICAgICJub2RlX21vZHVsZXMvdXJpanMvc3JjL0lQdjYuanMiKGV4cG9ydHMyLCBtb2R1bGUpIHsKICAgICAgLyohCiAgICAgICAqIFVSSS5qcyAtIE11dGF0aW5nIFVSTHMKICAgICAgICogSVB2NiBTdXBwb3J0CiAgICAgICAqCiAgICAgICAqIFZlcnNpb246IDEuMTkuMTEKICAgICAgICoKICAgICAgICogQXV0aG9yOiBSb2RuZXkgUmVobQogICAgICAgKiBXZWI6IGh0dHA6Ly9tZWRpYWxpemUuZ2l0aHViLmlvL1VSSS5qcy8KICAgICAgICoKICAgICAgICogTGljZW5zZWQgdW5kZXIKICAgICAgICogICBNSVQgTGljZW5zZSBodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlCiAgICAgICAqCiAgICAgICAqLwogICAgICAoZnVuY3Rpb24ocm9vdCwgZmFjdG9yeSkgewogICAgICAgICJ1c2Ugc3RyaWN0IjsKICAgICAgICBpZiAodHlwZW9mIG1vZHVsZSA9PT0gIm9iamVjdCIgJiYgbW9kdWxlLmV4cG9ydHMpIHsKICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpOwogICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gImZ1bmN0aW9uIiAmJiBkZWZpbmUuYW1kKSB7CiAgICAgICAgICBkZWZpbmUoZmFjdG9yeSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJvb3QuSVB2NiA9IGZhY3Rvcnkocm9vdCk7CiAgICAgICAgfQogICAgICB9KShleHBvcnRzMiwgZnVuY3Rpb24ocm9vdCkgewogICAgICAgICJ1c2Ugc3RyaWN0IjsKICAgICAgICB2YXIgX0lQdjYgPSByb290ICYmIHJvb3QuSVB2NjsKICAgICAgICBmdW5jdGlvbiBiZXN0UHJlc2VudGF0aW9uKGFkZHJlc3MpIHsKICAgICAgICAgIHZhciBfYWRkcmVzcyA9IGFkZHJlc3MudG9Mb3dlckNhc2UoKTsKICAgICAgICAgIHZhciBzZWdtZW50cyA9IF9hZGRyZXNzLnNwbGl0KCI6Iik7CiAgICAgICAgICB2YXIgbGVuZ3RoID0gc2VnbWVudHMubGVuZ3RoOwogICAgICAgICAgdmFyIHRvdGFsID0gODsKICAgICAgICAgIGlmIChzZWdtZW50c1swXSA9PT0gIiIgJiYgc2VnbWVudHNbMV0gPT09ICIiICYmIHNlZ21lbnRzWzJdID09PSAiIikgewogICAgICAgICAgICBzZWdtZW50cy5zaGlmdCgpOwogICAgICAgICAgICBzZWdtZW50cy5zaGlmdCgpOwogICAgICAgICAgfSBlbHNlIGlmIChzZWdtZW50c1swXSA9PT0gIiIgJiYgc2VnbWVudHNbMV0gPT09ICIiKSB7CiAgICAgICAgICAgIHNlZ21lbnRzLnNoaWZ0KCk7CiAgICAgICAgICB9IGVsc2UgaWYgKHNlZ21lbnRzW2xlbmd0aCAtIDFdID09PSAiIiAmJiBzZWdtZW50c1tsZW5ndGggLSAyXSA9PT0gIiIpIHsKICAgICAgICAgICAgc2VnbWVudHMucG9wKCk7CiAgICAgICAgICB9CiAgICAgICAgICBsZW5ndGggPSBzZWdtZW50cy5sZW5ndGg7CiAgICAgICAgICBpZiAoc2VnbWVudHNbbGVuZ3RoIC0gMV0uaW5kZXhPZigiLiIpICE9PSAtMSkgewogICAgICAgICAgICB0b3RhbCA9IDc7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgcG9zOwogICAgICAgICAgZm9yIChwb3MgPSAwOyBwb3MgPCBsZW5ndGg7IHBvcysrKSB7CiAgICAgICAgICAgIGlmIChzZWdtZW50c1twb3NdID09PSAiIikgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAocG9zIDwgdG90YWwpIHsKICAgICAgICAgICAgc2VnbWVudHMuc3BsaWNlKHBvcywgMSwgIjAwMDAiKTsKICAgICAgICAgICAgd2hpbGUgKHNlZ21lbnRzLmxlbmd0aCA8IHRvdGFsKSB7CiAgICAgICAgICAgICAgc2VnbWVudHMuc3BsaWNlKHBvcywgMCwgIjAwMDAiKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgdmFyIF9zZWdtZW50czsKICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdG90YWw7IGkrKykgewogICAgICAgICAgICBfc2VnbWVudHMgPSBzZWdtZW50c1tpXS5zcGxpdCgiIik7CiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgMzsgaisrKSB7CiAgICAgICAgICAgICAgaWYgKF9zZWdtZW50c1swXSA9PT0gIjAiICYmIF9zZWdtZW50cy5sZW5ndGggPiAxKSB7CiAgICAgICAgICAgICAgICBfc2VnbWVudHMuc3BsaWNlKDAsIDEpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc2VnbWVudHNbaV0gPSBfc2VnbWVudHMuam9pbigiIik7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgYmVzdCA9IC0xOwogICAgICAgICAgdmFyIF9iZXN0ID0gMDsKICAgICAgICAgIHZhciBfY3VycmVudCA9IDA7CiAgICAgICAgICB2YXIgY3VycmVudCA9IC0xOwogICAgICAgICAgdmFyIGluemVyb2VzID0gZmFsc2U7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdG90YWw7IGkrKykgewogICAgICAgICAgICBpZiAoaW56ZXJvZXMpIHsKICAgICAgICAgICAgICBpZiAoc2VnbWVudHNbaV0gPT09ICIwIikgewogICAgICAgICAgICAgICAgX2N1cnJlbnQgKz0gMTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgaW56ZXJvZXMgPSBmYWxzZTsKICAgICAgICAgICAgICAgIGlmIChfY3VycmVudCA+IF9iZXN0KSB7CiAgICAgICAgICAgICAgICAgIGJlc3QgPSBjdXJyZW50OwogICAgICAgICAgICAgICAgICBfYmVzdCA9IF9jdXJyZW50OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBpZiAoc2VnbWVudHNbaV0gPT09ICIwIikgewogICAgICAgICAgICAgICAgaW56ZXJvZXMgPSB0cnVlOwogICAgICAgICAgICAgICAgY3VycmVudCA9IGk7CiAgICAgICAgICAgICAgICBfY3VycmVudCA9IDE7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoX2N1cnJlbnQgPiBfYmVzdCkgewogICAgICAgICAgICBiZXN0ID0gY3VycmVudDsKICAgICAgICAgICAgX2Jlc3QgPSBfY3VycmVudDsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChfYmVzdCA+IDEpIHsKICAgICAgICAgICAgc2VnbWVudHMuc3BsaWNlKGJlc3QsIF9iZXN0LCAiIik7CiAgICAgICAgICB9CiAgICAgICAgICBsZW5ndGggPSBzZWdtZW50cy5sZW5ndGg7CiAgICAgICAgICB2YXIgcmVzdWx0ID0gIiI7CiAgICAgICAgICBpZiAoc2VnbWVudHNbMF0gPT09ICIiKSB7CiAgICAgICAgICAgIHJlc3VsdCA9ICI6IjsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICByZXN1bHQgKz0gc2VnbWVudHNbaV07CiAgICAgICAgICAgIGlmIChpID09PSBsZW5ndGggLSAxKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVzdWx0ICs9ICI6IjsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChzZWdtZW50c1tsZW5ndGggLSAxXSA9PT0gIiIpIHsKICAgICAgICAgICAgcmVzdWx0ICs9ICI6IjsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7CiAgICAgICAgICBpZiAocm9vdC5JUHY2ID09PSB0aGlzKSB7CiAgICAgICAgICAgIHJvb3QuSVB2NiA9IF9JUHY2OwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIHJldHVybiB7CiAgICAgICAgICBiZXN0OiBiZXN0UHJlc2VudGF0aW9uLAogICAgICAgICAgbm9Db25mbGljdAogICAgICAgIH07CiAgICAgIH0pOwogICAgfQogIH0pOwoKICAvLyBub2RlX21vZHVsZXMvdXJpanMvc3JjL1NlY29uZExldmVsRG9tYWlucy5qcwogIHZhciByZXF1aXJlX1NlY29uZExldmVsRG9tYWlucyA9IF9fY29tbW9uSlMoewogICAgIm5vZGVfbW9kdWxlcy91cmlqcy9zcmMvU2Vjb25kTGV2ZWxEb21haW5zLmpzIihleHBvcnRzMiwgbW9kdWxlKSB7CiAgICAgIC8qIQogICAgICAgKiBVUkkuanMgLSBNdXRhdGluZyBVUkxzCiAgICAgICAqIFNlY29uZCBMZXZlbCBEb21haW4gKFNMRCkgU3VwcG9ydAogICAgICAgKgogICAgICAgKiBWZXJzaW9uOiAxLjE5LjExCiAgICAgICAqCiAgICAgICAqIEF1dGhvcjogUm9kbmV5IFJlaG0KICAgICAgICogV2ViOiBodHRwOi8vbWVkaWFsaXplLmdpdGh1Yi5pby9VUkkuanMvCiAgICAgICAqCiAgICAgICAqIExpY2Vuc2VkIHVuZGVyCiAgICAgICAqICAgTUlUIExpY2Vuc2UgaHR0cDovL3d3dy5vcGVuc291cmNlLm9yZy9saWNlbnNlcy9taXQtbGljZW5zZQogICAgICAgKgogICAgICAgKi8KICAgICAgKGZ1bmN0aW9uKHJvb3QsIGZhY3RvcnkpIHsKICAgICAgICAidXNlIHN0cmljdCI7CiAgICAgICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICJvYmplY3QiICYmIG1vZHVsZS5leHBvcnRzKSB7CiAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKTsKICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICJmdW5jdGlvbiIgJiYgZGVmaW5lLmFtZCkgewogICAgICAgICAgZGVmaW5lKGZhY3RvcnkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByb290LlNlY29uZExldmVsRG9tYWlucyA9IGZhY3Rvcnkocm9vdCk7CiAgICAgICAgfQogICAgICB9KShleHBvcnRzMiwgZnVuY3Rpb24ocm9vdCkgewogICAgICAgICJ1c2Ugc3RyaWN0IjsKICAgICAgICB2YXIgX1NlY29uZExldmVsRG9tYWlucyA9IHJvb3QgJiYgcm9vdC5TZWNvbmRMZXZlbERvbWFpbnM7CiAgICAgICAgdmFyIFNMRCA9IHsKICAgICAgICAgIC8vIGxpc3Qgb2Yga25vd24gU2Vjb25kIExldmVsIERvbWFpbnMKICAgICAgICAgIC8vIGNvbnZlcnRlZCBsaXN0IG9mIFNMRHMgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vZ2F2aW5nbWlsbGVyL3NlY29uZC1sZXZlbC1kb21haW5zCiAgICAgICAgICAvLyAtLS0tCiAgICAgICAgICAvLyBwdWJsaWNzdWZmaXgub3JnIGlzIG1vcmUgY3VycmVudCBhbmQgYWN0dWFsbHkgdXNlZCBieSBhIGNvdXBsZSBvZiBicm93c2VycyBpbnRlcm5hbGx5LgogICAgICAgICAgLy8gZG93bnNpZGUgaXMgaXQgYWxzbyBjb250YWlucyBkb21haW5zIGxpa2UgImR5bmRucy5vcmciIC0gd2hpY2ggaXMgZmluZSBmb3IgdGhlIHNlY3VyaXR5CiAgICAgICAgICAvLyBpc3N1ZXMgYnJvd3NlciBoYXZlIHRvIGRlYWwgd2l0aCAoU09QIGZvciBjb29raWVzLCBldGMpIC0gYnV0IGlzIHdheSBvdmVyYm9hcmQgZm9yIFVSSS5qcwogICAgICAgICAgLy8gLS0tLQogICAgICAgICAgbGlzdDogewogICAgICAgICAgICAiYWMiOiAiIGNvbSBnb3YgbWlsIG5ldCBvcmcgIiwKICAgICAgICAgICAgImFlIjogIiBhYyBjbyBnb3YgbWlsIG5hbWUgbmV0IG9yZyBwcm8gc2NoICIsCiAgICAgICAgICAgICJhZiI6ICIgY29tIGVkdSBnb3YgbmV0IG9yZyAiLAogICAgICAgICAgICAiYWwiOiAiIGNvbSBlZHUgZ292IG1pbCBuZXQgb3JnICIsCiAgICAgICAgICAgICJhbyI6ICIgY28gZWQgZ3YgaXQgb2cgcGIgIiwKICAgICAgICAgICAgImFyIjogIiBjb20gZWR1IGdvYiBnb3YgaW50IG1pbCBuZXQgb3JnIHR1ciAiLAogICAgICAgICAgICAiYXQiOiAiIGFjIGNvIGd2IG9yICIsCiAgICAgICAgICAgICJhdSI6ICIgYXNuIGNvbSBjc2lybyBlZHUgZ292IGlkIG5ldCBvcmcgIiwKICAgICAgICAgICAgImJhIjogIiBjbyBjb20gZWR1IGdvdiBtaWwgbmV0IG9yZyBycyB1bmJpIHVubW8gdW5zYSB1bnR6IHVuemUgIiwKICAgICAgICAgICAgImJiIjogIiBiaXogY28gY29tIGVkdSBnb3YgaW5mbyBuZXQgb3JnIHN0b3JlIHR2ICIsCiAgICAgICAgICAgICJiaCI6ICIgYml6IGNjIGNvbSBlZHUgZ292IGluZm8gbmV0IG9yZyAiLAogICAgICAgICAgICAiYm4iOiAiIGNvbSBlZHUgZ292IG5ldCBvcmcgIiwKICAgICAgICAgICAgImJvIjogIiBjb20gZWR1IGdvYiBnb3YgaW50IG1pbCBuZXQgb3JnIHR2ICIsCiAgICAgICAgICAgICJiciI6ICIgYWRtIGFkdiBhZ3IgYW0gYXJxIGFydCBhdG8gYiBiaW8gYmxvZyBibWQgY2ltIGNuZyBjbnQgY29tIGNvb3AgZWNuIGVkdSBlbmcgZXNwIGV0YyBldGkgZmFyIGZsb2cgZm0gZm5kIGZvdCBmc3QgZzEyIGdnZiBnb3YgaW1iIGluZCBpbmYgam9yIGp1cyBsZWwgbWF0IG1lZCBtaWwgbXVzIG5ldCBub20gbm90IG50ciBvZG8gb3JnIHBwZyBwcm8gcHNjIHBzaSBxc2wgcmVjIHNsZyBzcnYgdG1wIHRyZCB0dXIgdHYgdmV0IHZsb2cgd2lraSB6bGcgIiwKICAgICAgICAgICAgImJzIjogIiBjb20gZWR1IGdvdiBuZXQgb3JnICIsCiAgICAgICAgICAgICJieiI6ICIgZHUgZXQgb20gb3YgcmcgIiwKICAgICAgICAgICAgImNhIjogIiBhYiBiYyBtYiBuYiBuZiBubCBucyBudCBudSBvbiBwZSBxYyBzayB5ayAiLAogICAgICAgICAgICAiY2siOiAiIGJpeiBjbyBlZHUgZ2VuIGdvdiBpbmZvIG5ldCBvcmcgIiwKICAgICAgICAgICAgImNuIjogIiBhYyBhaCBiaiBjb20gY3EgZWR1IGZqIGdkIGdvdiBncyBneCBneiBoYSBoYiBoZSBoaSBobCBobiBqbCBqcyBqeCBsbiBtaWwgbmV0IG5tIG54IG9yZyBxaCBzYyBzZCBzaCBzbiBzeCB0aiB0dyB4aiB4eiB5biB6aiAiLAogICAgICAgICAgICAiY28iOiAiIGNvbSBlZHUgZ292IG1pbCBuZXQgbm9tIG9yZyAiLAogICAgICAgICAgICAiY3IiOiAiIGFjIGMgY28gZWQgZmkgZ28gb3Igc2EgIiwKICAgICAgICAgICAgImN5IjogIiBhYyBiaXogY29tIGVrbG9nZXMgZ292IGx0ZCBuYW1lIG5ldCBvcmcgcGFybGlhbWVudCBwcmVzcyBwcm8gdG0gIiwKICAgICAgICAgICAgImRvIjogIiBhcnQgY29tIGVkdSBnb2IgZ292IG1pbCBuZXQgb3JnIHNsZCB3ZWIgIiwKICAgICAgICAgICAgImR6IjogIiBhcnQgYXNzbyBjb20gZWR1IGdvdiBuZXQgb3JnIHBvbCAiLAogICAgICAgICAgICAiZWMiOiAiIGNvbSBlZHUgZmluIGdvdiBpbmZvIG1lZCBtaWwgbmV0IG9yZyBwcm8gIiwKICAgICAgICAgICAgImVnIjogIiBjb20gZWR1IGV1biBnb3YgbWlsIG5hbWUgbmV0IG9yZyBzY2kgIiwKICAgICAgICAgICAgImVyIjogIiBjb20gZWR1IGdvdiBpbmQgbWlsIG5ldCBvcmcgcm9jaGVzdCB3ICIsCiAgICAgICAgICAgICJlcyI6ICIgY29tIGVkdSBnb2Igbm9tIG9yZyAiLAogICAgICAgICAgICAiZXQiOiAiIGJpeiBjb20gZWR1IGdvdiBpbmZvIG5hbWUgbmV0IG9yZyAiLAogICAgICAgICAgICAiZmoiOiAiIGFjIGJpeiBjb20gaW5mbyBtaWwgbmFtZSBuZXQgb3JnIHBybyAiLAogICAgICAgICAgICAiZmsiOiAiIGFjIGNvIGdvdiBuZXQgbm9tIG9yZyAiLAogICAgICAgICAgICAiZnIiOiAiIGFzc28gY29tIGYgZ291diBub20gcHJkIHByZXNzZSB0bSAiLAogICAgICAgICAgICAiZ2ciOiAiIGNvIG5ldCBvcmcgIiwKICAgICAgICAgICAgImdoIjogIiBjb20gZWR1IGdvdiBtaWwgb3JnICIsCiAgICAgICAgICAgICJnbiI6ICIgYWMgY29tIGdvdiBuZXQgb3JnICIsCiAgICAgICAgICAgICJnciI6ICIgY29tIGVkdSBnb3YgbWlsIG5ldCBvcmcgIiwKICAgICAgICAgICAgImd0IjogIiBjb20gZWR1IGdvYiBpbmQgbWlsIG5ldCBvcmcgIiwKICAgICAgICAgICAgImd1IjogIiBjb20gZWR1IGdvdiBuZXQgb3JnICIsCiAgICAgICAgICAgICJoayI6ICIgY29tIGVkdSBnb3YgaWR2IG5ldCBvcmcgIiwKICAgICAgICAgICAgImh1IjogIiAyMDAwIGFncmFyIGJvbHQgY2FzaW5vIGNpdHkgY28gZXJvdGljYSBlcm90aWthIGZpbG0gZm9ydW0gZ2FtZXMgaG90ZWwgaW5mbyBpbmdhdGxhbiBqb2dhc3oga29ueXZlbG8gbGFrYXMgbWVkaWEgbmV3cyBvcmcgcHJpdiByZWtsYW0gc2V4IHNob3Agc3BvcnQgc3VsaSBzemV4IHRtIHRvenNkZSB1dGF6YXMgdmlkZW8gIiwKICAgICAgICAgICAgImlkIjogIiBhYyBjbyBnbyBtaWwgbmV0IG9yIHNjaCB3ZWIgIiwKICAgICAgICAgICAgImlsIjogIiBhYyBjbyBnb3YgaWRmIGsxMiBtdW5pIG5ldCBvcmcgIiwKICAgICAgICAgICAgImluIjogIiBhYyBjbyBlZHUgZXJuZXQgZmlybSBnZW4gZ292IGkgaW5kIG1pbCBuZXQgbmljIG9yZyByZXMgIiwKICAgICAgICAgICAgImlxIjogIiBjb20gZWR1IGdvdiBpIG1pbCBuZXQgb3JnICIsCiAgICAgICAgICAgICJpciI6ICIgYWMgY28gZG5zc2VjIGdvdiBpIGlkIG5ldCBvcmcgc2NoICIsCiAgICAgICAgICAgICJpdCI6ICIgZWR1IGdvdiAiLAogICAgICAgICAgICAiamUiOiAiIGNvIG5ldCBvcmcgIiwKICAgICAgICAgICAgImpvIjogIiBjb20gZWR1IGdvdiBtaWwgbmFtZSBuZXQgb3JnIHNjaCAiLAogICAgICAgICAgICAianAiOiAiIGFjIGFkIGNvIGVkIGdvIGdyIGxnIG5lIG9yICIsCiAgICAgICAgICAgICJrZSI6ICIgYWMgY28gZ28gaW5mbyBtZSBtb2JpIG5lIG9yIHNjICIsCiAgICAgICAgICAgICJraCI6ICIgY29tIGVkdSBnb3YgbWlsIG5ldCBvcmcgcGVyICIsCiAgICAgICAgICAgICJraSI6ICIgYml6IGNvbSBkZSBlZHUgZ292IGluZm8gbW9iIG5ldCBvcmcgdGVsICIsCiAgICAgICAgICAgICJrbSI6ICIgYXNzbyBjb20gY29vcCBlZHUgZ291diBrIG1lZGVjaW4gbWlsIG5vbSBub3RhaXJlcyBwaGFybWFjaWVucyBwcmVzc2UgdG0gdmV0ZXJpbmFpcmUgIiwKICAgICAgICAgICAgImtuIjogIiBlZHUgZ292IG5ldCBvcmcgIiwKICAgICAgICAgICAgImtyIjogIiBhYyBidXNhbiBjaHVuZ2J1ayBjaHVuZ25hbSBjbyBkYWVndSBkYWVqZW9uIGVzIGdhbmd3b24gZ28gZ3dhbmdqdSBneWVvbmdidWsgZ3llb25nZ2kgZ3llb25nbmFtIGhzIGluY2hlb24gamVqdSBqZW9uYnVrIGplb25uYW0gayBrZyBtaWwgbXMgbmUgb3IgcGUgcmUgc2Mgc2VvdWwgdWxzYW4gIiwKICAgICAgICAgICAgImt3IjogIiBjb20gZWR1IGdvdiBuZXQgb3JnICIsCiAgICAgICAgICAgICJreSI6ICIgY29tIGVkdSBnb3YgbmV0IG9yZyAiLAogICAgICAgICAgICAia3oiOiAiIGNvbSBlZHUgZ292IG1pbCBuZXQgb3JnICIsCiAgICAgICAgICAgICJsYiI6ICIgY29tIGVkdSBnb3YgbmV0IG9yZyAiLAogICAgICAgICAgICAibGsiOiAiIGFzc24gY29tIGVkdSBnb3YgZ3JwIGhvdGVsIGludCBsdGQgbmV0IG5nbyBvcmcgc2NoIHNvYyB3ZWIgIiwKICAgICAgICAgICAgImxyIjogIiBjb20gZWR1IGdvdiBuZXQgb3JnICIsCiAgICAgICAgICAgICJsdiI6ICIgYXNuIGNvbSBjb25mIGVkdSBnb3YgaWQgbWlsIG5ldCBvcmcgIiwKICAgICAgICAgICAgImx5IjogIiBjb20gZWR1IGdvdiBpZCBtZWQgbmV0IG9yZyBwbGMgc2NoICIsCiAgICAgICAgICAgICJtYSI6ICIgYWMgY28gZ292IG0gbmV0IG9yZyBwcmVzcyAiLAogICAgICAgICAgICAibWMiOiAiIGFzc28gdG0gIiwKICAgICAgICAgICAgIm1lIjogIiBhYyBjbyBlZHUgZ292IGl0cyBuZXQgb3JnIHByaXYgIiwKICAgICAgICAgICAgIm1nIjogIiBjb20gZWR1IGdvdiBtaWwgbm9tIG9yZyBwcmQgdG0gIiwKICAgICAgICAgICAgIm1rIjogIiBjb20gZWR1IGdvdiBpbmYgbmFtZSBuZXQgb3JnIHBybyAiLAogICAgICAgICAgICAibWwiOiAiIGNvbSBlZHUgZ292IG5ldCBvcmcgcHJlc3NlICIsCiAgICAgICAgICAgICJtbiI6ICIgZWR1IGdvdiBvcmcgIiwKICAgICAgICAgICAgIm1vIjogIiBjb20gZWR1IGdvdiBuZXQgb3JnICIsCiAgICAgICAgICAgICJtdCI6ICIgY29tIGVkdSBnb3YgbmV0IG9yZyAiLAogICAgICAgICAgICAibXYiOiAiIGFlcm8gYml6IGNvbSBjb29wIGVkdSBnb3YgaW5mbyBpbnQgbWlsIG11c2V1bSBuYW1lIG5ldCBvcmcgcHJvICIsCiAgICAgICAgICAgICJtdyI6ICIgYWMgY28gY29tIGNvb3AgZWR1IGdvdiBpbnQgbXVzZXVtIG5ldCBvcmcgIiwKICAgICAgICAgICAgIm14IjogIiBjb20gZWR1IGdvYiBuZXQgb3JnICIsCiAgICAgICAgICAgICJteSI6ICIgY29tIGVkdSBnb3YgbWlsIG5hbWUgbmV0IG9yZyBzY2ggIiwKICAgICAgICAgICAgIm5mIjogIiBhcnRzIGNvbSBmaXJtIGluZm8gbmV0IG90aGVyIHBlciByZWMgc3RvcmUgd2ViICIsCiAgICAgICAgICAgICJuZyI6ICIgYml6IGNvbSBlZHUgZ292IG1pbCBtb2JpIG5hbWUgbmV0IG9yZyBzY2ggIiwKICAgICAgICAgICAgIm5pIjogIiBhYyBjbyBjb20gZWR1IGdvYiBtaWwgbmV0IG5vbSBvcmcgIiwKICAgICAgICAgICAgIm5wIjogIiBjb20gZWR1IGdvdiBtaWwgbmV0IG9yZyAiLAogICAgICAgICAgICAibnIiOiAiIGJpeiBjb20gZWR1IGdvdiBpbmZvIG5ldCBvcmcgIiwKICAgICAgICAgICAgIm9tIjogIiBhYyBiaXogY28gY29tIGVkdSBnb3YgbWVkIG1pbCBtdXNldW0gbmV0IG9yZyBwcm8gc2NoICIsCiAgICAgICAgICAgICJwZSI6ICIgY29tIGVkdSBnb2IgbWlsIG5ldCBub20gb3JnIHNsZCAiLAogICAgICAgICAgICAicGgiOiAiIGNvbSBlZHUgZ292IGkgbWlsIG5ldCBuZ28gb3JnICIsCiAgICAgICAgICAgICJwayI6ICIgYml6IGNvbSBlZHUgZmFtIGdvYiBnb2sgZ29uIGdvcCBnb3MgZ292IG5ldCBvcmcgd2ViICIsCiAgICAgICAgICAgICJwbCI6ICIgYXJ0IGJpYWx5c3RvayBiaXogY29tIGVkdSBnZGEgZ2RhbnNrIGdvcnpvdyBnb3YgaW5mbyBrYXRvd2ljZSBrcmFrb3cgbG9keiBsdWJsaW4gbWlsIG5ldCBuZ28gb2xzenR5biBvcmcgcG96bmFuIHB3ciByYWRvbSBzbHVwc2sgc3pjemVjaW4gdG9ydW4gd2Fyc3phd2Egd2F3IHdyb2Mgd3JvY2xhdyB6Z29yYSAiLAogICAgICAgICAgICAicHIiOiAiIGFjIGJpeiBjb20gZWR1IGVzdCBnb3YgaW5mbyBpc2xhIG5hbWUgbmV0IG9yZyBwcm8gcHJvZiAiLAogICAgICAgICAgICAicHMiOiAiIGNvbSBlZHUgZ292IG5ldCBvcmcgcGxvIHNlYyAiLAogICAgICAgICAgICAicHciOiAiIGJlbGF1IGNvIGVkIGdvIG5lIG9yICIsCiAgICAgICAgICAgICJybyI6ICIgYXJ0cyBjb20gZmlybSBpbmZvIG5vbSBudCBvcmcgcmVjIHN0b3JlIHRtIHd3dyAiLAogICAgICAgICAgICAicnMiOiAiIGFjIGNvIGVkdSBnb3YgaW4gb3JnICIsCiAgICAgICAgICAgICJzYiI6ICIgY29tIGVkdSBnb3YgbmV0IG9yZyAiLAogICAgICAgICAgICAic2MiOiAiIGNvbSBlZHUgZ292IG5ldCBvcmcgIiwKICAgICAgICAgICAgInNoIjogIiBjbyBjb20gZWR1IGdvdiBuZXQgbm9tIG9yZyAiLAogICAgICAgICAgICAic2wiOiAiIGNvbSBlZHUgZ292IG5ldCBvcmcgIiwKICAgICAgICAgICAgInN0IjogIiBjbyBjb20gY29uc3VsYWRvIGVkdSBlbWJhaXhhZGEgZ292IG1pbCBuZXQgb3JnIHByaW5jaXBlIHNhb3RvbWUgc3RvcmUgIiwKICAgICAgICAgICAgInN2IjogIiBjb20gZWR1IGdvYiBvcmcgcmVkICIsCiAgICAgICAgICAgICJzeiI6ICIgYWMgY28gb3JnICIsCiAgICAgICAgICAgICJ0ciI6ICIgYXYgYmJzIGJlbCBiaXogY29tIGRyIGVkdSBnZW4gZ292IGluZm8gazEyIG5hbWUgbmV0IG9yZyBwb2wgdGVsIHRzayB0diB3ZWIgIiwKICAgICAgICAgICAgInR0IjogIiBhZXJvIGJpeiBjYXQgY28gY29tIGNvb3AgZWR1IGdvdiBpbmZvIGludCBqb2JzIG1pbCBtb2JpIG11c2V1bSBuYW1lIG5ldCBvcmcgcHJvIHRlbCB0cmF2ZWwgIiwKICAgICAgICAgICAgInR3IjogIiBjbHViIGNvbSBlYml6IGVkdSBnYW1lIGdvdiBpZHYgbWlsIG5ldCBvcmcgIiwKICAgICAgICAgICAgIm11IjogIiBhYyBjbyBjb20gZ292IG5ldCBvciBvcmcgIiwKICAgICAgICAgICAgIm16IjogIiBhYyBjbyBlZHUgZ292IG9yZyAiLAogICAgICAgICAgICAibmEiOiAiIGNvIGNvbSAiLAogICAgICAgICAgICAibnoiOiAiIGFjIGNvIGNyaSBnZWVrIGdlbiBnb3Z0IGhlYWx0aCBpd2kgbWFvcmkgbWlsIG5ldCBvcmcgcGFybGlhbWVudCBzY2hvb2wgIiwKICAgICAgICAgICAgInBhIjogIiBhYm8gYWMgY29tIGVkdSBnb2IgaW5nIG1lZCBuZXQgbm9tIG9yZyBzbGQgIiwKICAgICAgICAgICAgInB0IjogIiBjb20gZWR1IGdvdiBpbnQgbmV0IG5vbWUgb3JnIHB1YmwgIiwKICAgICAgICAgICAgInB5IjogIiBjb20gZWR1IGdvdiBtaWwgbmV0IG9yZyAiLAogICAgICAgICAgICAicWEiOiAiIGNvbSBlZHUgZ292IG1pbCBuZXQgb3JnICIsCiAgICAgICAgICAgICJyZSI6ICIgYXNzbyBjb20gbm9tICIsCiAgICAgICAgICAgICJydSI6ICIgYWMgYWR5Z2V5YSBhbHRhaSBhbXVyIGFya2hhbmdlbHNrIGFzdHJha2hhbiBiYXNoa2lyaWEgYmVsZ29yb2QgYmlyIGJyeWFuc2sgYnVyeWF0aWEgY2JnIGNoZWwgY2hlbHlhYmluc2sgY2hpdGEgY2h1a290a2EgY2h1dmFzaGlhIGNvbSBkYWdlc3RhbiBlLWJ1cmcgZWR1IGdvdiBncm96bnkgaW50IGlya3V0c2sgaXZhbm92byBpemhldnNrIGphciBqb3Noa2FyLW9sYSBrYWxteWtpYSBrYWx1Z2Ega2FtY2hhdGthIGthcmVsaWEga2F6YW4ga2NociBrZW1lcm92byBraGFiYXJvdnNrIGtoYWthc3NpYSBraHYga2lyb3Yga29lbmlnIGtvbWkga29zdHJvbWEga3Jhbm95YXJzayBrdWJhbiBrdXJnYW4ga3Vyc2sgbGlwZXRzayBtYWdhZGFuIG1hcmkgbWFyaS1lbCBtYXJpbmUgbWlsIG1vcmRvdmlhIG1vc3JlZyBtc2sgbXVybWFuc2sgbmFsY2hpayBuZXQgbm5vdiBub3Ygbm92b3NpYmlyc2sgbnNrIG9tc2sgb3JlbmJ1cmcgb3JnIG9yeW9sIHBlbnphIHBlcm0gcHAgcHNrb3YgcHR6IHJuZCByeWF6YW4gc2FraGFsaW4gc2FtYXJhIHNhcmF0b3Ygc2ltYmlyc2sgc21vbGVuc2sgc3BiIHN0YXZyb3BvbCBzdHYgc3VyZ3V0IHRhbWJvdiB0YXRhcnN0YW4gdG9tIHRvbXNrIHRzYXJpdHN5biB0c2sgdHVsYSB0dXZhIHR2ZXIgdHl1bWVuIHVkbSB1ZG11cnRpYSB1bGFuLXVkZSB2bGFkaWthdmtheiB2bGFkaW1pciB2bGFkaXZvc3RvayB2b2xnb2dyYWQgdm9sb2dkYSB2b3JvbmV6aCB2cm4gdnlhdGthIHlha3V0aWEgeWFtYWwgeWVrYXRlcmluYnVyZyB5dXpobm8tc2FraGFsaW5zayAiLAogICAgICAgICAgICAicnciOiAiIGFjIGNvIGNvbSBlZHUgZ291diBnb3YgaW50IG1pbCBuZXQgIiwKICAgICAgICAgICAgInNhIjogIiBjb20gZWR1IGdvdiBtZWQgbmV0IG9yZyBwdWIgc2NoICIsCiAgICAgICAgICAgICJzZCI6ICIgY29tIGVkdSBnb3YgaW5mbyBtZWQgbmV0IG9yZyB0diAiLAogICAgICAgICAgICAic2UiOiAiIGEgYWMgYiBiZCBjIGQgZSBmIGcgaCBpIGsgbCBtIG4gbyBvcmcgcCBwYXJ0aSBwcCBwcmVzcyByIHMgdCB0bSB1IHcgeCB5IHogIiwKICAgICAgICAgICAgInNnIjogIiBjb20gZWR1IGdvdiBpZG4gbmV0IG9yZyBwZXIgIiwKICAgICAgICAgICAgInNuIjogIiBhcnQgY29tIGVkdSBnb3V2IG9yZyBwZXJzbyB1bml2ICIsCiAgICAgICAgICAgICJzeSI6ICIgY29tIGVkdSBnb3YgbWlsIG5ldCBuZXdzIG9yZyAiLAogICAgICAgICAgICAidGgiOiAiIGFjIGNvIGdvIGluIG1pIG5ldCBvciAiLAogICAgICAgICAgICAidGoiOiAiIGFjIGJpeiBjbyBjb20gZWR1IGdvIGdvdiBpbmZvIGludCBtaWwgbmFtZSBuZXQgbmljIG9yZyB0ZXN0IHdlYiAiLAogICAgICAgICAgICAidG4iOiAiIGFncmluZXQgY29tIGRlZmVuc2UgZWR1bmV0IGVucyBmaW4gZ292IGluZCBpbmZvIGludGwgbWluY29tIG5hdCBuZXQgb3JnIHBlcnNvIHJucnQgcm5zIHJudSB0b3VyaXNtICIsCiAgICAgICAgICAgICJ0eiI6ICIgYWMgY28gZ28gbmUgb3IgIiwKICAgICAgICAgICAgInVhIjogIiBiaXogY2hlcmthc3N5IGNoZXJuaWdvdiBjaGVybm92dHN5IGNrIGNuIGNvIGNvbSBjcmltZWEgY3YgZG4gZG5lcHJvcGV0cm92c2sgZG9uZXRzayBkcCBlZHUgZ292IGlmIGluIGl2YW5vLWZyYW5raXZzayBraCBraGFya292IGtoZXJzb24ga2htZWxuaXRza2l5IGtpZXYga2lyb3ZvZ3JhZCBrbSBrciBrcyBrdiBsZyBsdWdhbnNrIGx1dHNrIGx2aXYgbWUgbWsgbmV0IG5pa29sYWV2IG9kIG9kZXNzYSBvcmcgcGwgcG9sdGF2YSBwcCByb3ZubyBydiBzZWJhc3RvcG9sIHN1bXkgdGUgdGVybm9waWwgdXpoZ29yb2QgdmlubmljYSB2biB6YXBvcml6aHpoZSB6aGl0b21pciB6cCB6dCAiLAogICAgICAgICAgICAidWciOiAiIGFjIGNvIGdvIG5lIG9yIG9yZyBzYyAiLAogICAgICAgICAgICAidWsiOiAiIGFjIGJsIGJyaXRpc2gtbGlicmFyeSBjbyBjeW0gZ292IGdvdnQgaWNuZXQgamV0IGxlYSBsdGQgbWUgbWlsIG1vZCBuYXRpb25hbC1saWJyYXJ5LXNjb3RsYW5kIG5lbCBuZXQgbmhzIG5pYyBubHMgb3JnIG9yZ24gcGFybGlhbWVudCBwbGMgcG9saWNlIHNjaCBzY290IHNvYyAiLAogICAgICAgICAgICAidXMiOiAiIGRuaSBmZWQgaXNhIGtpZHMgbnNuICIsCiAgICAgICAgICAgICJ1eSI6ICIgY29tIGVkdSBndWIgbWlsIG5ldCBvcmcgIiwKICAgICAgICAgICAgInZlIjogIiBjbyBjb20gZWR1IGdvYiBpbmZvIG1pbCBuZXQgb3JnIHdlYiAiLAogICAgICAgICAgICAidmkiOiAiIGNvIGNvbSBrMTIgbmV0IG9yZyAiLAogICAgICAgICAgICAidm4iOiAiIGFjIGJpeiBjb20gZWR1IGdvdiBoZWFsdGggaW5mbyBpbnQgbmFtZSBuZXQgb3JnIHBybyAiLAogICAgICAgICAgICAieWUiOiAiIGNvIGNvbSBnb3YgbHRkIG1lIG5ldCBvcmcgcGxjICIsCiAgICAgICAgICAgICJ5dSI6ICIgYWMgY28gZWR1IGdvdiBvcmcgIiwKICAgICAgICAgICAgInphIjogIiBhYyBhZ3JpYyBhbHQgYm91cnNlIGNpdHkgY28gY3liZXJuZXQgZGIgZWR1IGdvdiBncm9uZGFyIGlhY2Nlc3MgaW10IGluY2EgbGFuZGVzaWduIGxhdyBtaWwgbmV0IG5nbyBuaXMgbm9tIG9saXZldHRpIG9yZyBwaXggc2Nob29sIHRtIHdlYiAiLAogICAgICAgICAgICAiem0iOiAiIGFjIGNvIGNvbSBlZHUgZ292IG5ldCBvcmcgc2NoICIsCiAgICAgICAgICAgIC8vIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NlbnRyYWxOaWMjU2Vjb25kLWxldmVsX2RvbWFpbnMKICAgICAgICAgICAgImNvbSI6ICJhciBiciBjbiBkZSBldSBnYiBnciBodSBqcG4ga3Igbm8gcWMgcnUgc2Egc2UgdWsgdXMgdXkgemEgIiwKICAgICAgICAgICAgIm5ldCI6ICJnYiBqcCBzZSB1ayAiLAogICAgICAgICAgICAib3JnIjogImFlIiwKICAgICAgICAgICAgImRlIjogImNvbSAiCiAgICAgICAgICB9LAogICAgICAgICAgLy8gZ29yaGlsbCAyMDEzLTEwLTI1OiBVc2luZyBpbmRleE9mKCkgaW5zdGVhZCBSZWdleHAoKS4gU2lnbmlmaWNhbnQgYm9vc3QKICAgICAgICAgIC8vIGluIGJvdGggcGVyZm9ybWFuY2UgYW5kIG1lbW9yeSBmb290cHJpbnQuIE5vIGluaXRpYWxpemF0aW9uIHJlcXVpcmVkLgogICAgICAgICAgLy8gaHR0cDovL2pzcGVyZi5jb20vdXJpLWpzLXNsZC1yZWdleC12cy1iaW5hcnktc2VhcmNoLzQKICAgICAgICAgIC8vIEZvbGxvd2luZyBtZXRob2RzIHVzZSBsYXN0SW5kZXhPZigpIHJhdGhlciB0aGFuIGFycmF5LnNwbGl0KCkgaW4gb3JkZXIKICAgICAgICAgIC8vIHRvIGF2b2lkIGFueSBtZW1vcnkgYWxsb2NhdGlvbnMuCiAgICAgICAgICBoYXM6IGZ1bmN0aW9uKGRvbWFpbikgewogICAgICAgICAgICB2YXIgdGxkT2Zmc2V0ID0gZG9tYWluLmxhc3RJbmRleE9mKCIuIik7CiAgICAgICAgICAgIGlmICh0bGRPZmZzZXQgPD0gMCB8fCB0bGRPZmZzZXQgPj0gZG9tYWluLmxlbmd0aCAtIDEpIHsKICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIHNsZE9mZnNldCA9IGRvbWFpbi5sYXN0SW5kZXhPZigiLiIsIHRsZE9mZnNldCAtIDEpOwogICAgICAgICAgICBpZiAoc2xkT2Zmc2V0IDw9IDAgfHwgc2xkT2Zmc2V0ID49IHRsZE9mZnNldCAtIDEpIHsKICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIHNsZExpc3QgPSBTTEQubGlzdFtkb21haW4uc2xpY2UodGxkT2Zmc2V0ICsgMSldOwogICAgICAgICAgICBpZiAoIXNsZExpc3QpIHsKICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHNsZExpc3QuaW5kZXhPZigiICIgKyBkb21haW4uc2xpY2Uoc2xkT2Zmc2V0ICsgMSwgdGxkT2Zmc2V0KSArICIgIikgPj0gMDsKICAgICAgICAgIH0sCiAgICAgICAgICBpczogZnVuY3Rpb24oZG9tYWluKSB7CiAgICAgICAgICAgIHZhciB0bGRPZmZzZXQgPSBkb21haW4ubGFzdEluZGV4T2YoIi4iKTsKICAgICAgICAgICAgaWYgKHRsZE9mZnNldCA8PSAwIHx8IHRsZE9mZnNldCA+PSBkb21haW4ubGVuZ3RoIC0gMSkgewogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgc2xkT2Zmc2V0ID0gZG9tYWluLmxhc3RJbmRleE9mKCIuIiwgdGxkT2Zmc2V0IC0gMSk7CiAgICAgICAgICAgIGlmIChzbGRPZmZzZXQgPj0gMCkgewogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgc2xkTGlzdCA9IFNMRC5saXN0W2RvbWFpbi5zbGljZSh0bGRPZmZzZXQgKyAxKV07CiAgICAgICAgICAgIGlmICghc2xkTGlzdCkgewogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gc2xkTGlzdC5pbmRleE9mKCIgIiArIGRvbWFpbi5zbGljZSgwLCB0bGRPZmZzZXQpICsgIiAiKSA+PSAwOwogICAgICAgICAgfSwKICAgICAgICAgIGdldDogZnVuY3Rpb24oZG9tYWluKSB7CiAgICAgICAgICAgIHZhciB0bGRPZmZzZXQgPSBkb21haW4ubGFzdEluZGV4T2YoIi4iKTsKICAgICAgICAgICAgaWYgKHRsZE9mZnNldCA8PSAwIHx8IHRsZE9mZnNldCA+PSBkb21haW4ubGVuZ3RoIC0gMSkgewogICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBzbGRPZmZzZXQgPSBkb21haW4ubGFzdEluZGV4T2YoIi4iLCB0bGRPZmZzZXQgLSAxKTsKICAgICAgICAgICAgaWYgKHNsZE9mZnNldCA8PSAwIHx8IHNsZE9mZnNldCA+PSB0bGRPZmZzZXQgLSAxKSB7CiAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIHNsZExpc3QgPSBTTEQubGlzdFtkb21haW4uc2xpY2UodGxkT2Zmc2V0ICsgMSldOwogICAgICAgICAgICBpZiAoIXNsZExpc3QpIHsKICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoc2xkTGlzdC5pbmRleE9mKCIgIiArIGRvbWFpbi5zbGljZShzbGRPZmZzZXQgKyAxLCB0bGRPZmZzZXQpICsgIiAiKSA8IDApIHsKICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZG9tYWluLnNsaWNlKHNsZE9mZnNldCArIDEpOwogICAgICAgICAgfSwKICAgICAgICAgIG5vQ29uZmxpY3Q6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBpZiAocm9vdC5TZWNvbmRMZXZlbERvbWFpbnMgPT09IHRoaXMpIHsKICAgICAgICAgICAgICByb290LlNlY29uZExldmVsRG9tYWlucyA9IF9TZWNvbmRMZXZlbERvbWFpbnM7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICByZXR1cm4gU0xEOwogICAgICB9KTsKICAgIH0KICB9KTsKCiAgLy8gbm9kZV9tb2R1bGVzL3VyaWpzL3NyYy9VUkkuanMKICB2YXIgcmVxdWlyZV9VUkkgPSBfX2NvbW1vbkpTKHsKICAgICJub2RlX21vZHVsZXMvdXJpanMvc3JjL1VSSS5qcyIoZXhwb3J0czIsIG1vZHVsZSkgewogICAgICAvKiEKICAgICAgICogVVJJLmpzIC0gTXV0YXRpbmcgVVJMcwogICAgICAgKgogICAgICAgKiBWZXJzaW9uOiAxLjE5LjExCiAgICAgICAqCiAgICAgICAqIEF1dGhvcjogUm9kbmV5IFJlaG0KICAgICAgICogV2ViOiBodHRwOi8vbWVkaWFsaXplLmdpdGh1Yi5pby9VUkkuanMvCiAgICAgICAqCiAgICAgICAqIExpY2Vuc2VkIHVuZGVyCiAgICAgICAqICAgTUlUIExpY2Vuc2UgaHR0cDovL3d3dy5vcGVuc291cmNlLm9yZy9saWNlbnNlcy9taXQtbGljZW5zZQogICAgICAgKgogICAgICAgKi8KICAgICAgKGZ1bmN0aW9uKHJvb3QsIGZhY3RvcnkpIHsKICAgICAgICAidXNlIHN0cmljdCI7CiAgICAgICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICJvYmplY3QiICYmIG1vZHVsZS5leHBvcnRzKSB7CiAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkocmVxdWlyZV9wdW55Y29kZSgpLCByZXF1aXJlX0lQdjYoKSwgcmVxdWlyZV9TZWNvbmRMZXZlbERvbWFpbnMoKSk7CiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSAiZnVuY3Rpb24iICYmIGRlZmluZS5hbWQpIHsKICAgICAgICAgIGRlZmluZShbIi4vcHVueWNvZGUiLCAiLi9JUHY2IiwgIi4vU2Vjb25kTGV2ZWxEb21haW5zIl0sIGZhY3RvcnkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByb290LlVSSSA9IGZhY3Rvcnkocm9vdC5wdW55Y29kZSwgcm9vdC5JUHY2LCByb290LlNlY29uZExldmVsRG9tYWlucywgcm9vdCk7CiAgICAgICAgfQogICAgICB9KShleHBvcnRzMiwgZnVuY3Rpb24ocHVueWNvZGUsIElQdjYsIFNMRCwgcm9vdCkgewogICAgICAgICJ1c2Ugc3RyaWN0IjsKICAgICAgICB2YXIgX1VSSSA9IHJvb3QgJiYgcm9vdC5VUkk7CiAgICAgICAgZnVuY3Rpb24gVVJJKHVybCwgYmFzZSkgewogICAgICAgICAgdmFyIF91cmxTdXBwbGllZCA9IGFyZ3VtZW50cy5sZW5ndGggPj0gMTsKICAgICAgICAgIHZhciBfYmFzZVN1cHBsaWVkID0gYXJndW1lbnRzLmxlbmd0aCA+PSAyOwogICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFVSSSkpIHsKICAgICAgICAgICAgaWYgKF91cmxTdXBwbGllZCkgewogICAgICAgICAgICAgIGlmIChfYmFzZVN1cHBsaWVkKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFVSSSh1cmwsIGJhc2UpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gbmV3IFVSSSh1cmwpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBuZXcgVVJJKCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodXJsID09PSB2b2lkIDApIHsKICAgICAgICAgICAgaWYgKF91cmxTdXBwbGllZCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoInVuZGVmaW5lZCBpcyBub3QgYSB2YWxpZCBhcmd1bWVudCBmb3IgVVJJIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHR5cGVvZiBsb2NhdGlvbiAhPT0gInVuZGVmaW5lZCIpIHsKICAgICAgICAgICAgICB1cmwgPSBsb2NhdGlvbi5ocmVmICsgIiI7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdXJsID0gIiI7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmICh1cmwgPT09IG51bGwpIHsKICAgICAgICAgICAgaWYgKF91cmxTdXBwbGllZCkgewogICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIm51bGwgaXMgbm90IGEgdmFsaWQgYXJndW1lbnQgZm9yIFVSSSIpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLmhyZWYodXJsKTsKICAgICAgICAgIGlmIChiYXNlICE9PSB2b2lkIDApIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWJzb2x1dGVUbyhiYXNlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBpc0ludGVnZXIodmFsdWUpIHsKICAgICAgICAgIHJldHVybiAvXlswLTldKyQvLnRlc3QodmFsdWUpOwogICAgICAgIH0KICAgICAgICBVUkkudmVyc2lvbiA9ICIxLjE5LjExIjsKICAgICAgICB2YXIgcCA9IFVSSS5wcm90b3R5cGU7CiAgICAgICAgdmFyIGhhc093biA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7CiAgICAgICAgZnVuY3Rpb24gZXNjYXBlUmVnRXgoc3RyaW5nKSB7CiAgICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoLyhbLiorP149IToke30oKXxbXF1cL1xcXSkvZywgIlxcJDEiKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gZ2V0VHlwZSh2YWx1ZSkgewogICAgICAgICAgaWYgKHZhbHVlID09PSB2b2lkIDApIHsKICAgICAgICAgICAgcmV0dXJuICJVbmRlZmluZWQiOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIFN0cmluZyhPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpKS5zbGljZSg4LCAtMSk7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7CiAgICAgICAgICByZXR1cm4gZ2V0VHlwZShvYmopID09PSAiQXJyYXkiOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBmaWx0ZXJBcnJheVZhbHVlcyhkYXRhLCB2YWx1ZSkgewogICAgICAgICAgdmFyIGxvb2t1cCA9IHt9OwogICAgICAgICAgdmFyIGksIGxlbmd0aDsKICAgICAgICAgIGlmIChnZXRUeXBlKHZhbHVlKSA9PT0gIlJlZ0V4cCIpIHsKICAgICAgICAgICAgbG9va3VwID0gbnVsbDsKICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuZ3RoID0gdmFsdWUubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICBsb29rdXBbdmFsdWVbaV1dID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgbG9va3VwW3ZhbHVlXSA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBkYXRhLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHZhciBfbWF0Y2ggPSBsb29rdXAgJiYgbG9va3VwW2RhdGFbaV1dICE9PSB2b2lkIDAgfHwgIWxvb2t1cCAmJiB2YWx1ZS50ZXN0KGRhdGFbaV0pOwogICAgICAgICAgICBpZiAoX21hdGNoKSB7CiAgICAgICAgICAgICAgZGF0YS5zcGxpY2UoaSwgMSk7CiAgICAgICAgICAgICAgbGVuZ3RoLS07CiAgICAgICAgICAgICAgaS0tOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZGF0YTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gYXJyYXlDb250YWlucyhsaXN0LCB2YWx1ZSkgewogICAgICAgICAgdmFyIGksIGxlbmd0aDsKICAgICAgICAgIGlmIChpc0FycmF5KHZhbHVlKSkgewogICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSB2YWx1ZS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICAgIGlmICghYXJyYXlDb250YWlucyhsaXN0LCB2YWx1ZVtpXSkpIHsKICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgX3R5cGUgPSBnZXRUeXBlKHZhbHVlKTsKICAgICAgICAgIGZvciAoaSA9IDAsIGxlbmd0aCA9IGxpc3QubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgaWYgKF90eXBlID09PSAiUmVnRXhwIikgewogICAgICAgICAgICAgIGlmICh0eXBlb2YgbGlzdFtpXSA9PT0gInN0cmluZyIgJiYgbGlzdFtpXS5tYXRjaCh2YWx1ZSkpIHsKICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIGlmIChsaXN0W2ldID09PSB2YWx1ZSkgewogICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGFycmF5c0VxdWFsKG9uZSwgdHdvKSB7CiAgICAgICAgICBpZiAoIWlzQXJyYXkob25lKSB8fCAhaXNBcnJheSh0d28pKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChvbmUubGVuZ3RoICE9PSB0d28ubGVuZ3RoKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICAgIG9uZS5zb3J0KCk7CiAgICAgICAgICB0d28uc29ydCgpOwogICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBvbmUubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICAgIGlmIChvbmVbaV0gIT09IHR3b1tpXSkgewogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIHRyaW1TbGFzaGVzKHRleHQpIHsKICAgICAgICAgIHZhciB0cmltX2V4cHJlc3Npb24gPSAvXlwvK3xcLyskL2c7CiAgICAgICAgICByZXR1cm4gdGV4dC5yZXBsYWNlKHRyaW1fZXhwcmVzc2lvbiwgIiIpOwogICAgICAgIH0KICAgICAgICBVUkkuX3BhcnRzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICBwcm90b2NvbDogbnVsbCwKICAgICAgICAgICAgdXNlcm5hbWU6IG51bGwsCiAgICAgICAgICAgIHBhc3N3b3JkOiBudWxsLAogICAgICAgICAgICBob3N0bmFtZTogbnVsbCwKICAgICAgICAgICAgdXJuOiBudWxsLAogICAgICAgICAgICBwb3J0OiBudWxsLAogICAgICAgICAgICBwYXRoOiBudWxsLAogICAgICAgICAgICBxdWVyeTogbnVsbCwKICAgICAgICAgICAgZnJhZ21lbnQ6IG51bGwsCiAgICAgICAgICAgIC8vIHN0YXRlCiAgICAgICAgICAgIHByZXZlbnRJbnZhbGlkSG9zdG5hbWU6IFVSSS5wcmV2ZW50SW52YWxpZEhvc3RuYW1lLAogICAgICAgICAgICBkdXBsaWNhdGVRdWVyeVBhcmFtZXRlcnM6IFVSSS5kdXBsaWNhdGVRdWVyeVBhcmFtZXRlcnMsCiAgICAgICAgICAgIGVzY2FwZVF1ZXJ5U3BhY2U6IFVSSS5lc2NhcGVRdWVyeVNwYWNlCiAgICAgICAgICB9OwogICAgICAgIH07CiAgICAgICAgVVJJLnByZXZlbnRJbnZhbGlkSG9zdG5hbWUgPSBmYWxzZTsKICAgICAgICBVUkkuZHVwbGljYXRlUXVlcnlQYXJhbWV0ZXJzID0gZmFsc2U7CiAgICAgICAgVVJJLmVzY2FwZVF1ZXJ5U3BhY2UgPSB0cnVlOwogICAgICAgIFVSSS5wcm90b2NvbF9leHByZXNzaW9uID0gL15bYS16XVthLXowLTkuKy1dKiQvaTsKICAgICAgICBVUkkuaWRuX2V4cHJlc3Npb24gPSAvW15hLXowLTlcLl8tXS9pOwogICAgICAgIFVSSS5wdW55Y29kZV9leHByZXNzaW9uID0gLyh4bi0tKS9pOwogICAgICAgIFVSSS5pcDRfZXhwcmVzc2lvbiA9IC9eXGR7MSwzfVwuXGR7MSwzfVwuXGR7MSwzfVwuXGR7MSwzfSQvOwogICAgICAgIFVSSS5pcDZfZXhwcmVzc2lvbiA9IC9eXHMqKCgoWzAtOUEtRmEtZl17MSw0fTopezd9KFswLTlBLUZhLWZdezEsNH18OikpfCgoWzAtOUEtRmEtZl17MSw0fTopezZ9KDpbMC05QS1GYS1mXXsxLDR9fCgoMjVbMC01XXwyWzAtNF1cZHwxXGRcZHxbMS05XT9cZCkoXC4oMjVbMC01XXwyWzAtNF1cZHwxXGRcZHxbMS05XT9cZCkpezN9KXw6KSl8KChbMC05QS1GYS1mXXsxLDR9Oil7NX0oKCg6WzAtOUEtRmEtZl17MSw0fSl7MSwyfSl8OigoMjVbMC01XXwyWzAtNF1cZHwxXGRcZHxbMS05XT9cZCkoXC4oMjVbMC01XXwyWzAtNF1cZHwxXGRcZHxbMS05XT9cZCkpezN9KXw6KSl8KChbMC05QS1GYS1mXXsxLDR9Oil7NH0oKCg6WzAtOUEtRmEtZl17MSw0fSl7MSwzfSl8KCg6WzAtOUEtRmEtZl17MSw0fSk/OigoMjVbMC01XXwyWzAtNF1cZHwxXGRcZHxbMS05XT9cZCkoXC4oMjVbMC01XXwyWzAtNF1cZHwxXGRcZHxbMS05XT9cZCkpezN9KSl8OikpfCgoWzAtOUEtRmEtZl17MSw0fTopezN9KCgoOlswLTlBLUZhLWZdezEsNH0pezEsNH0pfCgoOlswLTlBLUZhLWZdezEsNH0pezAsMn06KCgyNVswLTVdfDJbMC00XVxkfDFcZFxkfFsxLTldP1xkKShcLigyNVswLTVdfDJbMC00XVxkfDFcZFxkfFsxLTldP1xkKSl7M30pKXw6KSl8KChbMC05QS1GYS1mXXsxLDR9Oil7Mn0oKCg6WzAtOUEtRmEtZl17MSw0fSl7MSw1fSl8KCg6WzAtOUEtRmEtZl17MSw0fSl7MCwzfTooKDI1WzAtNV18MlswLTRdXGR8MVxkXGR8WzEtOV0/XGQpKFwuKDI1WzAtNV18MlswLTRdXGR8MVxkXGR8WzEtOV0/XGQpKXszfSkpfDopKXwoKFswLTlBLUZhLWZdezEsNH06KXsxfSgoKDpbMC05QS1GYS1mXXsxLDR9KXsxLDZ9KXwoKDpbMC05QS1GYS1mXXsxLDR9KXswLDR9OigoMjVbMC01XXwyWzAtNF1cZHwxXGRcZHxbMS05XT9cZCkoXC4oMjVbMC01XXwyWzAtNF1cZHwxXGRcZHxbMS05XT9cZCkpezN9KSl8OikpfCg6KCgoOlswLTlBLUZhLWZdezEsNH0pezEsN30pfCgoOlswLTlBLUZhLWZdezEsNH0pezAsNX06KCgyNVswLTVdfDJbMC00XVxkfDFcZFxkfFsxLTldP1xkKShcLigyNVswLTVdfDJbMC00XVxkfDFcZFxkfFsxLTldP1xkKSl7M30pKXw6KSkpKCUuKyk/XHMqJC87CiAgICAgICAgVVJJLmZpbmRfdXJpX2V4cHJlc3Npb24gPSAvXGIoKD86W2Etel1bXHctXSs6KD86XC97MSwzfXxbYS16MC05JV0pfHd3d1xkezAsM31bLl18W2EtejAtOS5cLV0rWy5dW2Etel17Miw0fVwvKSg/OlteXHMoKTw+XSt8XCgoW15ccygpPD5dK3woXChbXlxzKCk8Pl0rXCkpKSpcKSkrKD86XCgoW15ccygpPD5dK3woXChbXlxzKCk8Pl0rXCkpKSpcKXxbXlxzYCEoKVxbXF17fTs6JyIuLDw+P8KrwrvigJzigJ3igJjigJldKSkvaWc7CiAgICAgICAgVVJJLmZpbmRVcmkgPSB7CiAgICAgICAgICAvLyB2YWxpZCAic2NoZW1lOi8vIiBvciAid3d3LiIKICAgICAgICAgIHN0YXJ0OiAvXGIoPzooW2Etel1bYS16MC05ListXSo6XC9cLyl8d3d3XC4pL2dpLAogICAgICAgICAgLy8gZXZlcnl0aGluZyB1cCB0byB0aGUgbmV4dCB3aGl0ZXNwYWNlCiAgICAgICAgICBlbmQ6IC9bXHNcclxuXXwkLywKICAgICAgICAgIC8vIHRyaW0gdHJhaWxpbmcgcHVuY3R1YXRpb24gY2FwdHVyZWQgYnkgZW5kIFJlZ0V4cAogICAgICAgICAgdHJpbTogL1tgISgpXFtcXXt9OzonIi4sPD4/wqvCu+KAnOKAneKAnuKAmOKAmV0rJC8sCiAgICAgICAgICAvLyBiYWxhbmNlZCBwYXJlbnMgaW5jbHVzaW9uICgpLCBbXSwge30sIDw+CiAgICAgICAgICBwYXJlbnM6IC8oXChbXlwpXSpcKXxcW1teXF1dKlxdfFx7W159XSpcfXw8W14+XSo+KS9nCiAgICAgICAgfTsKICAgICAgICBVUkkubGVhZGluZ193aGl0ZXNwYWNlX2V4cHJlc3Npb24gPSAvXltceDAwLVx4MjBcdTAwYTBcdTE2ODBcdTIwMDAtXHUyMDBhXHUyMDI4XHUyMDI5XHUyMDJmXHUyMDVmXHUzMDAwXHVmZWZmXSsvOwogICAgICAgIFVSSS5hc2NpaV90YWJfd2hpdGVzcGFjZSA9IC9bXHUwMDA5XHUwMDBBXHUwMDBEXSsvZzsKICAgICAgICBVUkkuZGVmYXVsdFBvcnRzID0gewogICAgICAgICAgaHR0cDogIjgwIiwKICAgICAgICAgIGh0dHBzOiAiNDQzIiwKICAgICAgICAgIGZ0cDogIjIxIiwKICAgICAgICAgIGdvcGhlcjogIjcwIiwKICAgICAgICAgIHdzOiAiODAiLAogICAgICAgICAgd3NzOiAiNDQzIgogICAgICAgIH07CiAgICAgICAgVVJJLmhvc3RQcm90b2NvbHMgPSBbCiAgICAgICAgICAiaHR0cCIsCiAgICAgICAgICAiaHR0cHMiCiAgICAgICAgXTsKICAgICAgICBVUkkuaW52YWxpZF9ob3N0bmFtZV9jaGFyYWN0ZXJzID0gL1teYS16QS1aMC05XC5cLTpfXS87CiAgICAgICAgVVJJLmRvbUF0dHJpYnV0ZXMgPSB7CiAgICAgICAgICAiYSI6ICJocmVmIiwKICAgICAgICAgICJibG9ja3F1b3RlIjogImNpdGUiLAogICAgICAgICAgImxpbmsiOiAiaHJlZiIsCiAgICAgICAgICAiYmFzZSI6ICJocmVmIiwKICAgICAgICAgICJzY3JpcHQiOiAic3JjIiwKICAgICAgICAgICJmb3JtIjogImFjdGlvbiIsCiAgICAgICAgICAiaW1nIjogInNyYyIsCiAgICAgICAgICAiYXJlYSI6ICJocmVmIiwKICAgICAgICAgICJpZnJhbWUiOiAic3JjIiwKICAgICAgICAgICJlbWJlZCI6ICJzcmMiLAogICAgICAgICAgInNvdXJjZSI6ICJzcmMiLAogICAgICAgICAgInRyYWNrIjogInNyYyIsCiAgICAgICAgICAiaW5wdXQiOiAic3JjIiwKICAgICAgICAgIC8vIGJ1dCBvbmx5IGlmIHR5cGU9ImltYWdlIgogICAgICAgICAgImF1ZGlvIjogInNyYyIsCiAgICAgICAgICAidmlkZW8iOiAic3JjIgogICAgICAgIH07CiAgICAgICAgVVJJLmdldERvbUF0dHJpYnV0ZSA9IGZ1bmN0aW9uKG5vZGUpIHsKICAgICAgICAgIGlmICghbm9kZSB8fCAhbm9kZS5ub2RlTmFtZSkgewogICAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgICAgfQogICAgICAgICAgdmFyIG5vZGVOYW1lID0gbm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpOwogICAgICAgICAgaWYgKG5vZGVOYW1lID09PSAiaW5wdXQiICYmIG5vZGUudHlwZSAhPT0gImltYWdlIikgewogICAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIFVSSS5kb21BdHRyaWJ1dGVzW25vZGVOYW1lXTsKICAgICAgICB9OwogICAgICAgIGZ1bmN0aW9uIGVzY2FwZUZvckR1bWJGaXJlZm94MzYodmFsdWUpIHsKICAgICAgICAgIHJldHVybiBlc2NhcGUodmFsdWUpOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBzdHJpY3RFbmNvZGVVUklDb21wb25lbnQoc3RyaW5nKSB7CiAgICAgICAgICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KHN0cmluZykucmVwbGFjZSgvWyEnKCkqXS9nLCBlc2NhcGVGb3JEdW1iRmlyZWZveDM2KS5yZXBsYWNlKC9cKi9nLCAiJTJBIik7CiAgICAgICAgfQogICAgICAgIFVSSS5lbmNvZGUgPSBzdHJpY3RFbmNvZGVVUklDb21wb25lbnQ7CiAgICAgICAgVVJJLmRlY29kZSA9IGRlY29kZVVSSUNvbXBvbmVudDsKICAgICAgICBVUkkuaXNvODg1OSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgVVJJLmVuY29kZSA9IGVzY2FwZTsKICAgICAgICAgIFVSSS5kZWNvZGUgPSB1bmVzY2FwZTsKICAgICAgICB9OwogICAgICAgIFVSSS51bmljb2RlID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICBVUkkuZW5jb2RlID0gc3RyaWN0RW5jb2RlVVJJQ29tcG9uZW50OwogICAgICAgICAgVVJJLmRlY29kZSA9IGRlY29kZVVSSUNvbXBvbmVudDsKICAgICAgICB9OwogICAgICAgIFVSSS5jaGFyYWN0ZXJzID0gewogICAgICAgICAgcGF0aG5hbWU6IHsKICAgICAgICAgICAgZW5jb2RlOiB7CiAgICAgICAgICAgICAgLy8gUkZDMzk4NiAyLjE6IEZvciBjb25zaXN0ZW5jeSwgVVJJIHByb2R1Y2VycyBhbmQgbm9ybWFsaXplcnMgc2hvdWxkCiAgICAgICAgICAgICAgLy8gdXNlIHVwcGVyY2FzZSBoZXhhZGVjaW1hbCBkaWdpdHMgZm9yIGFsbCBwZXJjZW50LWVuY29kaW5ncy4KICAgICAgICAgICAgICBleHByZXNzaW9uOiAvJSgyNHwyNnwyQnwyQ3wzQnwzRHwzQXw0MCkvaWcsCiAgICAgICAgICAgICAgbWFwOiB7CiAgICAgICAgICAgICAgICAvLyAtLl9+IScoKSoKICAgICAgICAgICAgICAgICIlMjQiOiAiJCIsCiAgICAgICAgICAgICAgICAiJTI2IjogIiYiLAogICAgICAgICAgICAgICAgIiUyQiI6ICIrIiwKICAgICAgICAgICAgICAgICIlMkMiOiAiLCIsCiAgICAgICAgICAgICAgICAiJTNCIjogIjsiLAogICAgICAgICAgICAgICAgIiUzRCI6ICI9IiwKICAgICAgICAgICAgICAgICIlM0EiOiAiOiIsCiAgICAgICAgICAgICAgICAiJTQwIjogIkAiCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICBkZWNvZGU6IHsKICAgICAgICAgICAgICBleHByZXNzaW9uOiAvW1wvXD8jXS9nLAogICAgICAgICAgICAgIG1hcDogewogICAgICAgICAgICAgICAgIi8iOiAiJTJGIiwKICAgICAgICAgICAgICAgICI/IjogIiUzRiIsCiAgICAgICAgICAgICAgICAiIyI6ICIlMjMiCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9LAogICAgICAgICAgcmVzZXJ2ZWQ6IHsKICAgICAgICAgICAgZW5jb2RlOiB7CiAgICAgICAgICAgICAgLy8gUkZDMzk4NiAyLjE6IEZvciBjb25zaXN0ZW5jeSwgVVJJIHByb2R1Y2VycyBhbmQgbm9ybWFsaXplcnMgc2hvdWxkCiAgICAgICAgICAgICAgLy8gdXNlIHVwcGVyY2FzZSBoZXhhZGVjaW1hbCBkaWdpdHMgZm9yIGFsbCBwZXJjZW50LWVuY29kaW5ncy4KICAgICAgICAgICAgICBleHByZXNzaW9uOiAvJSgyMXwyM3wyNHwyNnwyN3wyOHwyOXwyQXwyQnwyQ3wyRnwzQXwzQnwzRHwzRnw0MHw1Qnw1RCkvaWcsCiAgICAgICAgICAgICAgbWFwOiB7CiAgICAgICAgICAgICAgICAvLyBnZW4tZGVsaW1zCiAgICAgICAgICAgICAgICAiJTNBIjogIjoiLAogICAgICAgICAgICAgICAgIiUyRiI6ICIvIiwKICAgICAgICAgICAgICAgICIlM0YiOiAiPyIsCiAgICAgICAgICAgICAgICAiJTIzIjogIiMiLAogICAgICAgICAgICAgICAgIiU1QiI6ICJbIiwKICAgICAgICAgICAgICAgICIlNUQiOiAiXSIsCiAgICAgICAgICAgICAgICAiJTQwIjogIkAiLAogICAgICAgICAgICAgICAgLy8gc3ViLWRlbGltcwogICAgICAgICAgICAgICAgIiUyMSI6ICIhIiwKICAgICAgICAgICAgICAgICIlMjQiOiAiJCIsCiAgICAgICAgICAgICAgICAiJTI2IjogIiYiLAogICAgICAgICAgICAgICAgIiUyNyI6ICInIiwKICAgICAgICAgICAgICAgICIlMjgiOiAiKCIsCiAgICAgICAgICAgICAgICAiJTI5IjogIikiLAogICAgICAgICAgICAgICAgIiUyQSI6ICIqIiwKICAgICAgICAgICAgICAgICIlMkIiOiAiKyIsCiAgICAgICAgICAgICAgICAiJTJDIjogIiwiLAogICAgICAgICAgICAgICAgIiUzQiI6ICI7IiwKICAgICAgICAgICAgICAgICIlM0QiOiAiPSIKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0sCiAgICAgICAgICB1cm5wYXRoOiB7CiAgICAgICAgICAgIC8vIFRoZSBjaGFyYWN0ZXJzIHVuZGVyIGBlbmNvZGVgIGFyZSB0aGUgY2hhcmFjdGVycyBjYWxsZWQgb3V0IGJ5IFJGQyAyMTQxIGFzIGJlaW5nIGFjY2VwdGFibGUKICAgICAgICAgICAgLy8gZm9yIHVzYWdlIGluIGEgVVJOLiBSRkMyMTQxIGFsc28gY2FsbHMgb3V0ICItIiwgIi4iLCBhbmQgIl8iIGFzIGFjY2VwdGFibGUgY2hhcmFjdGVycywgYnV0CiAgICAgICAgICAgIC8vIHRoZXNlIGFyZW4ndCBlbmNvZGVkIGJ5IGVuY29kZVVSSUNvbXBvbmVudCwgc28gd2UgZG9uJ3QgaGF2ZSB0byBjYWxsIHRoZW0gb3V0IGhlcmUuIEFsc28KICAgICAgICAgICAgLy8gbm90ZSB0aGF0IHRoZSBjb2xvbiBjaGFyYWN0ZXIgaXMgbm90IGZlYXR1cmVkIGluIHRoZSBlbmNvZGluZyBtYXA7IHRoaXMgaXMgYmVjYXVzZSBVUkkuanMKICAgICAgICAgICAgLy8gZ2l2ZXMgdGhlIGNvbG9ucyBpbiBVUk5zIHNlbWFudGljIG1lYW5pbmcgYXMgdGhlIGRlbGltaXRlcnMgb2YgcGF0aCBzZWdlbWVudHMsIGFuZCBzbyBpdAogICAgICAgICAgICAvLyBzaG91bGQgbm90IGFwcGVhciB1bmVuY29kZWQgaW4gYSBzZWdtZW50IGl0c2VsZi4KICAgICAgICAgICAgLy8gU2VlIGFsc28gdGhlIG5vdGUgYWJvdmUgYWJvdXQgUkZDMzk4NiBhbmQgY2FwaXRhbGFsaXplZCBoZXggZGlnaXRzLgogICAgICAgICAgICBlbmNvZGU6IHsKICAgICAgICAgICAgICBleHByZXNzaW9uOiAvJSgyMXwyNHwyN3wyOHwyOXwyQXwyQnwyQ3wzQnwzRHw0MCkvaWcsCiAgICAgICAgICAgICAgbWFwOiB7CiAgICAgICAgICAgICAgICAiJTIxIjogIiEiLAogICAgICAgICAgICAgICAgIiUyNCI6ICIkIiwKICAgICAgICAgICAgICAgICIlMjciOiAiJyIsCiAgICAgICAgICAgICAgICAiJTI4IjogIigiLAogICAgICAgICAgICAgICAgIiUyOSI6ICIpIiwKICAgICAgICAgICAgICAgICIlMkEiOiAiKiIsCiAgICAgICAgICAgICAgICAiJTJCIjogIisiLAogICAgICAgICAgICAgICAgIiUyQyI6ICIsIiwKICAgICAgICAgICAgICAgICIlM0IiOiAiOyIsCiAgICAgICAgICAgICAgICAiJTNEIjogIj0iLAogICAgICAgICAgICAgICAgIiU0MCI6ICJAIgogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgLy8gVGhlc2UgY2hhcmFjdGVycyBhcmUgdGhlIGNoYXJhY3RlcnMgY2FsbGVkIG91dCBieSBSRkMyMTQxIGFzICJyZXNlcnZlZCIgY2hhcmFjdGVycyB0aGF0CiAgICAgICAgICAgIC8vIHNob3VsZCBuZXZlciBhcHBlYXIgaW4gYSBVUk4sIHBsdXMgdGhlIGNvbG9uIGNoYXJhY3RlciAoc2VlIG5vdGUgYWJvdmUpLgogICAgICAgICAgICBkZWNvZGU6IHsKICAgICAgICAgICAgICBleHByZXNzaW9uOiAvW1wvXD8jOl0vZywKICAgICAgICAgICAgICBtYXA6IHsKICAgICAgICAgICAgICAgICIvIjogIiUyRiIsCiAgICAgICAgICAgICAgICAiPyI6ICIlM0YiLAogICAgICAgICAgICAgICAgIiMiOiAiJTIzIiwKICAgICAgICAgICAgICAgICI6IjogIiUzQSIKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIFVSSS5lbmNvZGVRdWVyeSA9IGZ1bmN0aW9uKHN0cmluZywgZXNjYXBlUXVlcnlTcGFjZSkgewogICAgICAgICAgdmFyIGVzY2FwZWQgPSBVUkkuZW5jb2RlKHN0cmluZyArICIiKTsKICAgICAgICAgIGlmIChlc2NhcGVRdWVyeVNwYWNlID09PSB2b2lkIDApIHsKICAgICAgICAgICAgZXNjYXBlUXVlcnlTcGFjZSA9IFVSSS5lc2NhcGVRdWVyeVNwYWNlOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGVzY2FwZVF1ZXJ5U3BhY2UgPyBlc2NhcGVkLnJlcGxhY2UoLyUyMC9nLCAiKyIpIDogZXNjYXBlZDsKICAgICAgICB9OwogICAgICAgIFVSSS5kZWNvZGVRdWVyeSA9IGZ1bmN0aW9uKHN0cmluZywgZXNjYXBlUXVlcnlTcGFjZSkgewogICAgICAgICAgc3RyaW5nICs9ICIiOwogICAgICAgICAgaWYgKGVzY2FwZVF1ZXJ5U3BhY2UgPT09IHZvaWQgMCkgewogICAgICAgICAgICBlc2NhcGVRdWVyeVNwYWNlID0gVVJJLmVzY2FwZVF1ZXJ5U3BhY2U7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICByZXR1cm4gVVJJLmRlY29kZShlc2NhcGVRdWVyeVNwYWNlID8gc3RyaW5nLnJlcGxhY2UoL1wrL2csICIlMjAiKSA6IHN0cmluZyk7CiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIHJldHVybiBzdHJpbmc7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICB2YXIgX3BhcnRzID0geyAiZW5jb2RlIjogImVuY29kZSIsICJkZWNvZGUiOiAiZGVjb2RlIiB9OwogICAgICAgIHZhciBfcGFydDsKICAgICAgICB2YXIgZ2VuZXJhdGVBY2Nlc3NvciA9IGZ1bmN0aW9uKF9ncm91cCwgX3BhcnQyKSB7CiAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oc3RyaW5nKSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgcmV0dXJuIFVSSVtfcGFydDJdKHN0cmluZyArICIiKS5yZXBsYWNlKFVSSS5jaGFyYWN0ZXJzW19ncm91cF1bX3BhcnQyXS5leHByZXNzaW9uLCBmdW5jdGlvbihjKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gVVJJLmNoYXJhY3RlcnNbX2dyb3VwXVtfcGFydDJdLm1hcFtjXTsKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAgIHJldHVybiBzdHJpbmc7CiAgICAgICAgICAgIH0KICAgICAgICAgIH07CiAgICAgICAgfTsKICAgICAgICBmb3IgKF9wYXJ0IGluIF9wYXJ0cykgewogICAgICAgICAgVVJJW19wYXJ0ICsgIlBhdGhTZWdtZW50Il0gPSBnZW5lcmF0ZUFjY2Vzc29yKCJwYXRobmFtZSIsIF9wYXJ0c1tfcGFydF0pOwogICAgICAgICAgVVJJW19wYXJ0ICsgIlVyblBhdGhTZWdtZW50Il0gPSBnZW5lcmF0ZUFjY2Vzc29yKCJ1cm5wYXRoIiwgX3BhcnRzW19wYXJ0XSk7CiAgICAgICAgfQogICAgICAgIHZhciBnZW5lcmF0ZVNlZ21lbnRlZFBhdGhGdW5jdGlvbiA9IGZ1bmN0aW9uKF9zZXAsIF9jb2RpbmdGdW5jTmFtZSwgX2lubmVyQ29kaW5nRnVuY05hbWUpIHsKICAgICAgICAgIHJldHVybiBmdW5jdGlvbihzdHJpbmcpIHsKICAgICAgICAgICAgdmFyIGFjdHVhbENvZGluZ0Z1bmM7CiAgICAgICAgICAgIGlmICghX2lubmVyQ29kaW5nRnVuY05hbWUpIHsKICAgICAgICAgICAgICBhY3R1YWxDb2RpbmdGdW5jID0gVVJJW19jb2RpbmdGdW5jTmFtZV07CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgYWN0dWFsQ29kaW5nRnVuYyA9IGZ1bmN0aW9uKHN0cmluZzIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBVUklbX2NvZGluZ0Z1bmNOYW1lXShVUklbX2lubmVyQ29kaW5nRnVuY05hbWVdKHN0cmluZzIpKTsKICAgICAgICAgICAgICB9OwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBzZWdtZW50cyA9IChzdHJpbmcgKyAiIikuc3BsaXQoX3NlcCk7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBzZWdtZW50cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICAgIHNlZ21lbnRzW2ldID0gYWN0dWFsQ29kaW5nRnVuYyhzZWdtZW50c1tpXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHNlZ21lbnRzLmpvaW4oX3NlcCk7CiAgICAgICAgICB9OwogICAgICAgIH07CiAgICAgICAgVVJJLmRlY29kZVBhdGggPSBnZW5lcmF0ZVNlZ21lbnRlZFBhdGhGdW5jdGlvbigiLyIsICJkZWNvZGVQYXRoU2VnbWVudCIpOwogICAgICAgIFVSSS5kZWNvZGVVcm5QYXRoID0gZ2VuZXJhdGVTZWdtZW50ZWRQYXRoRnVuY3Rpb24oIjoiLCAiZGVjb2RlVXJuUGF0aFNlZ21lbnQiKTsKICAgICAgICBVUkkucmVjb2RlUGF0aCA9IGdlbmVyYXRlU2VnbWVudGVkUGF0aEZ1bmN0aW9uKCIvIiwgImVuY29kZVBhdGhTZWdtZW50IiwgImRlY29kZSIpOwogICAgICAgIFVSSS5yZWNvZGVVcm5QYXRoID0gZ2VuZXJhdGVTZWdtZW50ZWRQYXRoRnVuY3Rpb24oIjoiLCAiZW5jb2RlVXJuUGF0aFNlZ21lbnQiLCAiZGVjb2RlIik7CiAgICAgICAgVVJJLmVuY29kZVJlc2VydmVkID0gZ2VuZXJhdGVBY2Nlc3NvcigicmVzZXJ2ZWQiLCAiZW5jb2RlIik7CiAgICAgICAgVVJJLnBhcnNlID0gZnVuY3Rpb24oc3RyaW5nLCBwYXJ0cykgewogICAgICAgICAgdmFyIHBvczsKICAgICAgICAgIGlmICghcGFydHMpIHsKICAgICAgICAgICAgcGFydHMgPSB7CiAgICAgICAgICAgICAgcHJldmVudEludmFsaWRIb3N0bmFtZTogVVJJLnByZXZlbnRJbnZhbGlkSG9zdG5hbWUKICAgICAgICAgICAgfTsKICAgICAgICAgIH0KICAgICAgICAgIHN0cmluZyA9IHN0cmluZy5yZXBsYWNlKFVSSS5sZWFkaW5nX3doaXRlc3BhY2VfZXhwcmVzc2lvbiwgIiIpOwogICAgICAgICAgc3RyaW5nID0gc3RyaW5nLnJlcGxhY2UoVVJJLmFzY2lpX3RhYl93aGl0ZXNwYWNlLCAiIik7CiAgICAgICAgICBwb3MgPSBzdHJpbmcuaW5kZXhPZigiIyIpOwogICAgICAgICAgaWYgKHBvcyA+IC0xKSB7CiAgICAgICAgICAgIHBhcnRzLmZyYWdtZW50ID0gc3RyaW5nLnN1YnN0cmluZyhwb3MgKyAxKSB8fCBudWxsOwogICAgICAgICAgICBzdHJpbmcgPSBzdHJpbmcuc3Vic3RyaW5nKDAsIHBvcyk7CiAgICAgICAgICB9CiAgICAgICAgICBwb3MgPSBzdHJpbmcuaW5kZXhPZigiPyIpOwogICAgICAgICAgaWYgKHBvcyA+IC0xKSB7CiAgICAgICAgICAgIHBhcnRzLnF1ZXJ5ID0gc3RyaW5nLnN1YnN0cmluZyhwb3MgKyAxKSB8fCBudWxsOwogICAgICAgICAgICBzdHJpbmcgPSBzdHJpbmcuc3Vic3RyaW5nKDAsIHBvcyk7CiAgICAgICAgICB9CiAgICAgICAgICBzdHJpbmcgPSBzdHJpbmcucmVwbGFjZSgvXihodHRwcz98ZnRwfHdzcz8pPzorWy9cXF0qL2ksICIkMTovLyIpOwogICAgICAgICAgc3RyaW5nID0gc3RyaW5nLnJlcGxhY2UoL15bL1xcXXsyLH0vaSwgIi8vIik7CiAgICAgICAgICBpZiAoc3RyaW5nLnN1YnN0cmluZygwLCAyKSA9PT0gIi8vIikgewogICAgICAgICAgICBwYXJ0cy5wcm90b2NvbCA9IG51bGw7CiAgICAgICAgICAgIHN0cmluZyA9IHN0cmluZy5zdWJzdHJpbmcoMik7CiAgICAgICAgICAgIHN0cmluZyA9IFVSSS5wYXJzZUF1dGhvcml0eShzdHJpbmcsIHBhcnRzKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHBvcyA9IHN0cmluZy5pbmRleE9mKCI6Iik7CiAgICAgICAgICAgIGlmIChwb3MgPiAtMSkgewogICAgICAgICAgICAgIHBhcnRzLnByb3RvY29sID0gc3RyaW5nLnN1YnN0cmluZygwLCBwb3MpIHx8IG51bGw7CiAgICAgICAgICAgICAgaWYgKHBhcnRzLnByb3RvY29sICYmICFwYXJ0cy5wcm90b2NvbC5tYXRjaChVUkkucHJvdG9jb2xfZXhwcmVzc2lvbikpIHsKICAgICAgICAgICAgICAgIHBhcnRzLnByb3RvY29sID0gdm9pZCAwOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RyaW5nLnN1YnN0cmluZyhwb3MgKyAxLCBwb3MgKyAzKS5yZXBsYWNlKC9cXC9nLCAiLyIpID09PSAiLy8iKSB7CiAgICAgICAgICAgICAgICBzdHJpbmcgPSBzdHJpbmcuc3Vic3RyaW5nKHBvcyArIDMpOwogICAgICAgICAgICAgICAgc3RyaW5nID0gVVJJLnBhcnNlQXV0aG9yaXR5KHN0cmluZywgcGFydHMpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBzdHJpbmcgPSBzdHJpbmcuc3Vic3RyaW5nKHBvcyArIDEpOwogICAgICAgICAgICAgICAgcGFydHMudXJuID0gdHJ1ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHBhcnRzLnBhdGggPSBzdHJpbmc7CiAgICAgICAgICByZXR1cm4gcGFydHM7CiAgICAgICAgfTsKICAgICAgICBVUkkucGFyc2VIb3N0ID0gZnVuY3Rpb24oc3RyaW5nLCBwYXJ0cykgewogICAgICAgICAgaWYgKCFzdHJpbmcpIHsKICAgICAgICAgICAgc3RyaW5nID0gIiI7CiAgICAgICAgICB9CiAgICAgICAgICBzdHJpbmcgPSBzdHJpbmcucmVwbGFjZSgvXFwvZywgIi8iKTsKICAgICAgICAgIHZhciBwb3MgPSBzdHJpbmcuaW5kZXhPZigiLyIpOwogICAgICAgICAgdmFyIGJyYWNrZXRQb3M7CiAgICAgICAgICB2YXIgdDsKICAgICAgICAgIGlmIChwb3MgPT09IC0xKSB7CiAgICAgICAgICAgIHBvcyA9IHN0cmluZy5sZW5ndGg7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoc3RyaW5nLmNoYXJBdCgwKSA9PT0gIlsiKSB7CiAgICAgICAgICAgIGJyYWNrZXRQb3MgPSBzdHJpbmcuaW5kZXhPZigiXSIpOwogICAgICAgICAgICBwYXJ0cy5ob3N0bmFtZSA9IHN0cmluZy5zdWJzdHJpbmcoMSwgYnJhY2tldFBvcykgfHwgbnVsbDsKICAgICAgICAgICAgcGFydHMucG9ydCA9IHN0cmluZy5zdWJzdHJpbmcoYnJhY2tldFBvcyArIDIsIHBvcykgfHwgbnVsbDsKICAgICAgICAgICAgaWYgKHBhcnRzLnBvcnQgPT09ICIvIikgewogICAgICAgICAgICAgIHBhcnRzLnBvcnQgPSBudWxsOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB2YXIgZmlyc3RDb2xvbiA9IHN0cmluZy5pbmRleE9mKCI6Iik7CiAgICAgICAgICAgIHZhciBmaXJzdFNsYXNoID0gc3RyaW5nLmluZGV4T2YoIi8iKTsKICAgICAgICAgICAgdmFyIG5leHRDb2xvbiA9IHN0cmluZy5pbmRleE9mKCI6IiwgZmlyc3RDb2xvbiArIDEpOwogICAgICAgICAgICBpZiAobmV4dENvbG9uICE9PSAtMSAmJiAoZmlyc3RTbGFzaCA9PT0gLTEgfHwgbmV4dENvbG9uIDwgZmlyc3RTbGFzaCkpIHsKICAgICAgICAgICAgICBwYXJ0cy5ob3N0bmFtZSA9IHN0cmluZy5zdWJzdHJpbmcoMCwgcG9zKSB8fCBudWxsOwogICAgICAgICAgICAgIHBhcnRzLnBvcnQgPSBudWxsOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHQgPSBzdHJpbmcuc3Vic3RyaW5nKDAsIHBvcykuc3BsaXQoIjoiKTsKICAgICAgICAgICAgICBwYXJ0cy5ob3N0bmFtZSA9IHRbMF0gfHwgbnVsbDsKICAgICAgICAgICAgICBwYXJ0cy5wb3J0ID0gdFsxXSB8fCBudWxsOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAocGFydHMuaG9zdG5hbWUgJiYgc3RyaW5nLnN1YnN0cmluZyhwb3MpLmNoYXJBdCgwKSAhPT0gIi8iKSB7CiAgICAgICAgICAgIHBvcysrOwogICAgICAgICAgICBzdHJpbmcgPSAiLyIgKyBzdHJpbmc7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAocGFydHMucHJldmVudEludmFsaWRIb3N0bmFtZSkgewogICAgICAgICAgICBVUkkuZW5zdXJlVmFsaWRIb3N0bmFtZShwYXJ0cy5ob3N0bmFtZSwgcGFydHMucHJvdG9jb2wpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHBhcnRzLnBvcnQpIHsKICAgICAgICAgICAgVVJJLmVuc3VyZVZhbGlkUG9ydChwYXJ0cy5wb3J0KTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzdHJpbmcuc3Vic3RyaW5nKHBvcykgfHwgIi8iOwogICAgICAgIH07CiAgICAgICAgVVJJLnBhcnNlQXV0aG9yaXR5ID0gZnVuY3Rpb24oc3RyaW5nLCBwYXJ0cykgewogICAgICAgICAgc3RyaW5nID0gVVJJLnBhcnNlVXNlcmluZm8oc3RyaW5nLCBwYXJ0cyk7CiAgICAgICAgICByZXR1cm4gVVJJLnBhcnNlSG9zdChzdHJpbmcsIHBhcnRzKTsKICAgICAgICB9OwogICAgICAgIFVSSS5wYXJzZVVzZXJpbmZvID0gZnVuY3Rpb24oc3RyaW5nLCBwYXJ0cykgewogICAgICAgICAgdmFyIF9zdHJpbmcgPSBzdHJpbmc7CiAgICAgICAgICB2YXIgZmlyc3RCYWNrU2xhc2ggPSBzdHJpbmcuaW5kZXhPZigiXFwiKTsKICAgICAgICAgIGlmIChmaXJzdEJhY2tTbGFzaCAhPT0gLTEpIHsKICAgICAgICAgICAgc3RyaW5nID0gc3RyaW5nLnJlcGxhY2UoL1xcL2csICIvIik7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgZmlyc3RTbGFzaCA9IHN0cmluZy5pbmRleE9mKCIvIik7CiAgICAgICAgICB2YXIgcG9zID0gc3RyaW5nLmxhc3RJbmRleE9mKCJAIiwgZmlyc3RTbGFzaCA+IC0xID8gZmlyc3RTbGFzaCA6IHN0cmluZy5sZW5ndGggLSAxKTsKICAgICAgICAgIHZhciB0OwogICAgICAgICAgaWYgKHBvcyA+IC0xICYmIChmaXJzdFNsYXNoID09PSAtMSB8fCBwb3MgPCBmaXJzdFNsYXNoKSkgewogICAgICAgICAgICB0ID0gc3RyaW5nLnN1YnN0cmluZygwLCBwb3MpLnNwbGl0KCI6Iik7CiAgICAgICAgICAgIHBhcnRzLnVzZXJuYW1lID0gdFswXSA/IFVSSS5kZWNvZGUodFswXSkgOiBudWxsOwogICAgICAgICAgICB0LnNoaWZ0KCk7CiAgICAgICAgICAgIHBhcnRzLnBhc3N3b3JkID0gdFswXSA/IFVSSS5kZWNvZGUodC5qb2luKCI6IikpIDogbnVsbDsKICAgICAgICAgICAgc3RyaW5nID0gX3N0cmluZy5zdWJzdHJpbmcocG9zICsgMSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBwYXJ0cy51c2VybmFtZSA9IG51bGw7CiAgICAgICAgICAgIHBhcnRzLnBhc3N3b3JkID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzdHJpbmc7CiAgICAgICAgfTsKICAgICAgICBVUkkucGFyc2VRdWVyeSA9IGZ1bmN0aW9uKHN0cmluZywgZXNjYXBlUXVlcnlTcGFjZSkgewogICAgICAgICAgaWYgKCFzdHJpbmcpIHsKICAgICAgICAgICAgcmV0dXJuIHt9OwogICAgICAgICAgfQogICAgICAgICAgc3RyaW5nID0gc3RyaW5nLnJlcGxhY2UoLyYrL2csICImIikucmVwbGFjZSgvXlw/KiYqfCYrJC9nLCAiIik7CiAgICAgICAgICBpZiAoIXN0cmluZykgewogICAgICAgICAgICByZXR1cm4ge307CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgaXRlbXMgPSB7fTsKICAgICAgICAgIHZhciBzcGxpdHMgPSBzdHJpbmcuc3BsaXQoIiYiKTsKICAgICAgICAgIHZhciBsZW5ndGggPSBzcGxpdHMubGVuZ3RoOwogICAgICAgICAgdmFyIHYzLCBuYW1lLCB2YWx1ZTsKICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgdjMgPSBzcGxpdHNbaV0uc3BsaXQoIj0iKTsKICAgICAgICAgICAgbmFtZSA9IFVSSS5kZWNvZGVRdWVyeSh2My5zaGlmdCgpLCBlc2NhcGVRdWVyeVNwYWNlKTsKICAgICAgICAgICAgdmFsdWUgPSB2My5sZW5ndGggPyBVUkkuZGVjb2RlUXVlcnkodjMuam9pbigiPSIpLCBlc2NhcGVRdWVyeVNwYWNlKSA6IG51bGw7CiAgICAgICAgICAgIGlmIChuYW1lID09PSAiX19wcm90b19fIikgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9IGVsc2UgaWYgKGhhc093bi5jYWxsKGl0ZW1zLCBuYW1lKSkgewogICAgICAgICAgICAgIGlmICh0eXBlb2YgaXRlbXNbbmFtZV0gPT09ICJzdHJpbmciIHx8IGl0ZW1zW25hbWVdID09PSBudWxsKSB7CiAgICAgICAgICAgICAgICBpdGVtc1tuYW1lXSA9IFtpdGVtc1tuYW1lXV07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGl0ZW1zW25hbWVdLnB1c2godmFsdWUpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGl0ZW1zW25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBpdGVtczsKICAgICAgICB9OwogICAgICAgIFVSSS5idWlsZCA9IGZ1bmN0aW9uKHBhcnRzKSB7CiAgICAgICAgICB2YXIgdCA9ICIiOwogICAgICAgICAgdmFyIHJlcXVpcmVBYnNvbHV0ZVBhdGggPSBmYWxzZTsKICAgICAgICAgIGlmIChwYXJ0cy5wcm90b2NvbCkgewogICAgICAgICAgICB0ICs9IHBhcnRzLnByb3RvY29sICsgIjoiOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCFwYXJ0cy51cm4gJiYgKHQgfHwgcGFydHMuaG9zdG5hbWUpKSB7CiAgICAgICAgICAgIHQgKz0gIi8vIjsKICAgICAgICAgICAgcmVxdWlyZUFic29sdXRlUGF0aCA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICB0ICs9IFVSSS5idWlsZEF1dGhvcml0eShwYXJ0cykgfHwgIiI7CiAgICAgICAgICBpZiAodHlwZW9mIHBhcnRzLnBhdGggPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgIGlmIChwYXJ0cy5wYXRoLmNoYXJBdCgwKSAhPT0gIi8iICYmIHJlcXVpcmVBYnNvbHV0ZVBhdGgpIHsKICAgICAgICAgICAgICB0ICs9ICIvIjsKICAgICAgICAgICAgfQogICAgICAgICAgICB0ICs9IHBhcnRzLnBhdGg7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodHlwZW9mIHBhcnRzLnF1ZXJ5ID09PSAic3RyaW5nIiAmJiBwYXJ0cy5xdWVyeSkgewogICAgICAgICAgICB0ICs9ICI/IiArIHBhcnRzLnF1ZXJ5OwogICAgICAgICAgfQogICAgICAgICAgaWYgKHR5cGVvZiBwYXJ0cy5mcmFnbWVudCA9PT0gInN0cmluZyIgJiYgcGFydHMuZnJhZ21lbnQpIHsKICAgICAgICAgICAgdCArPSAiIyIgKyBwYXJ0cy5mcmFnbWVudDsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0OwogICAgICAgIH07CiAgICAgICAgVVJJLmJ1aWxkSG9zdCA9IGZ1bmN0aW9uKHBhcnRzKSB7CiAgICAgICAgICB2YXIgdCA9ICIiOwogICAgICAgICAgaWYgKCFwYXJ0cy5ob3N0bmFtZSkgewogICAgICAgICAgICByZXR1cm4gIiI7CiAgICAgICAgICB9IGVsc2UgaWYgKFVSSS5pcDZfZXhwcmVzc2lvbi50ZXN0KHBhcnRzLmhvc3RuYW1lKSkgewogICAgICAgICAgICB0ICs9ICJbIiArIHBhcnRzLmhvc3RuYW1lICsgIl0iOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdCArPSBwYXJ0cy5ob3N0bmFtZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChwYXJ0cy5wb3J0KSB7CiAgICAgICAgICAgIHQgKz0gIjoiICsgcGFydHMucG9ydDsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0OwogICAgICAgIH07CiAgICAgICAgVVJJLmJ1aWxkQXV0aG9yaXR5ID0gZnVuY3Rpb24ocGFydHMpIHsKICAgICAgICAgIHJldHVybiBVUkkuYnVpbGRVc2VyaW5mbyhwYXJ0cykgKyBVUkkuYnVpbGRIb3N0KHBhcnRzKTsKICAgICAgICB9OwogICAgICAgIFVSSS5idWlsZFVzZXJpbmZvID0gZnVuY3Rpb24ocGFydHMpIHsKICAgICAgICAgIHZhciB0ID0gIiI7CiAgICAgICAgICBpZiAocGFydHMudXNlcm5hbWUpIHsKICAgICAgICAgICAgdCArPSBVUkkuZW5jb2RlKHBhcnRzLnVzZXJuYW1lKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChwYXJ0cy5wYXNzd29yZCkgewogICAgICAgICAgICB0ICs9ICI6IiArIFVSSS5lbmNvZGUocGFydHMucGFzc3dvcmQpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHQpIHsKICAgICAgICAgICAgdCArPSAiQCI7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdDsKICAgICAgICB9OwogICAgICAgIFVSSS5idWlsZFF1ZXJ5ID0gZnVuY3Rpb24oZGF0YSwgZHVwbGljYXRlUXVlcnlQYXJhbWV0ZXJzLCBlc2NhcGVRdWVyeVNwYWNlKSB7CiAgICAgICAgICB2YXIgdCA9ICIiOwogICAgICAgICAgdmFyIHVuaXF1ZSwga2V5LCBpLCBsZW5ndGg7CiAgICAgICAgICBmb3IgKGtleSBpbiBkYXRhKSB7CiAgICAgICAgICAgIGlmIChrZXkgPT09ICJfX3Byb3RvX18iKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoaGFzT3duLmNhbGwoZGF0YSwga2V5KSkgewogICAgICAgICAgICAgIGlmIChpc0FycmF5KGRhdGFba2V5XSkpIHsKICAgICAgICAgICAgICAgIHVuaXF1ZSA9IHt9OwogICAgICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuZ3RoID0gZGF0YVtrZXldLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICAgIGlmIChkYXRhW2tleV1baV0gIT09IHZvaWQgMCAmJiB1bmlxdWVbZGF0YVtrZXldW2ldICsgIiJdID09PSB2b2lkIDApIHsKICAgICAgICAgICAgICAgICAgICB0ICs9ICImIiArIFVSSS5idWlsZFF1ZXJ5UGFyYW1ldGVyKGtleSwgZGF0YVtrZXldW2ldLCBlc2NhcGVRdWVyeVNwYWNlKTsKICAgICAgICAgICAgICAgICAgICBpZiAoZHVwbGljYXRlUXVlcnlQYXJhbWV0ZXJzICE9PSB0cnVlKSB7CiAgICAgICAgICAgICAgICAgICAgICB1bmlxdWVbZGF0YVtrZXldW2ldICsgIiJdID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGFba2V5XSAhPT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgICB0ICs9ICImIiArIFVSSS5idWlsZFF1ZXJ5UGFyYW1ldGVyKGtleSwgZGF0YVtrZXldLCBlc2NhcGVRdWVyeVNwYWNlKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0LnN1YnN0cmluZygxKTsKICAgICAgICB9OwogICAgICAgIFVSSS5idWlsZFF1ZXJ5UGFyYW1ldGVyID0gZnVuY3Rpb24obmFtZSwgdmFsdWUsIGVzY2FwZVF1ZXJ5U3BhY2UpIHsKICAgICAgICAgIHJldHVybiBVUkkuZW5jb2RlUXVlcnkobmFtZSwgZXNjYXBlUXVlcnlTcGFjZSkgKyAodmFsdWUgIT09IG51bGwgPyAiPSIgKyBVUkkuZW5jb2RlUXVlcnkodmFsdWUsIGVzY2FwZVF1ZXJ5U3BhY2UpIDogIiIpOwogICAgICAgIH07CiAgICAgICAgVVJJLmFkZFF1ZXJ5ID0gZnVuY3Rpb24oZGF0YSwgbmFtZSwgdmFsdWUpIHsKICAgICAgICAgIGlmICh0eXBlb2YgbmFtZSA9PT0gIm9iamVjdCIpIHsKICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG5hbWUpIHsKICAgICAgICAgICAgICBpZiAoaGFzT3duLmNhbGwobmFtZSwga2V5KSkgewogICAgICAgICAgICAgICAgVVJJLmFkZFF1ZXJ5KGRhdGEsIGtleSwgbmFtZVtrZXldKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG5hbWUgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgIGlmIChkYXRhW25hbWVdID09PSB2b2lkIDApIHsKICAgICAgICAgICAgICBkYXRhW25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhW25hbWVdID09PSAic3RyaW5nIikgewogICAgICAgICAgICAgIGRhdGFbbmFtZV0gPSBbZGF0YVtuYW1lXV07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCFpc0FycmF5KHZhbHVlKSkgewogICAgICAgICAgICAgIHZhbHVlID0gW3ZhbHVlXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBkYXRhW25hbWVdID0gKGRhdGFbbmFtZV0gfHwgW10pLmNvbmNhdCh2YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJVUkkuYWRkUXVlcnkoKSBhY2NlcHRzIGFuIG9iamVjdCwgc3RyaW5nIGFzIHRoZSBuYW1lIHBhcmFtZXRlciIpOwogICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgVVJJLnNldFF1ZXJ5ID0gZnVuY3Rpb24oZGF0YSwgbmFtZSwgdmFsdWUpIHsKICAgICAgICAgIGlmICh0eXBlb2YgbmFtZSA9PT0gIm9iamVjdCIpIHsKICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG5hbWUpIHsKICAgICAgICAgICAgICBpZiAoaGFzT3duLmNhbGwobmFtZSwga2V5KSkgewogICAgICAgICAgICAgICAgVVJJLnNldFF1ZXJ5KGRhdGEsIGtleSwgbmFtZVtrZXldKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG5hbWUgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgIGRhdGFbbmFtZV0gPSB2YWx1ZSA9PT0gdm9pZCAwID8gbnVsbCA6IHZhbHVlOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiVVJJLnNldFF1ZXJ5KCkgYWNjZXB0cyBhbiBvYmplY3QsIHN0cmluZyBhcyB0aGUgbmFtZSBwYXJhbWV0ZXIiKTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIFVSSS5yZW1vdmVRdWVyeSA9IGZ1bmN0aW9uKGRhdGEsIG5hbWUsIHZhbHVlKSB7CiAgICAgICAgICB2YXIgaSwgbGVuZ3RoLCBrZXk7CiAgICAgICAgICBpZiAoaXNBcnJheShuYW1lKSkgewogICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBuYW1lLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgZGF0YVtuYW1lW2ldXSA9IHZvaWQgMDsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIGlmIChnZXRUeXBlKG5hbWUpID09PSAiUmVnRXhwIikgewogICAgICAgICAgICBmb3IgKGtleSBpbiBkYXRhKSB7CiAgICAgICAgICAgICAgaWYgKG5hbWUudGVzdChrZXkpKSB7CiAgICAgICAgICAgICAgICBkYXRhW2tleV0gPSB2b2lkIDA7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBuYW1lID09PSAib2JqZWN0IikgewogICAgICAgICAgICBmb3IgKGtleSBpbiBuYW1lKSB7CiAgICAgICAgICAgICAgaWYgKGhhc093bi5jYWxsKG5hbWUsIGtleSkpIHsKICAgICAgICAgICAgICAgIFVSSS5yZW1vdmVRdWVyeShkYXRhLCBrZXksIG5hbWVba2V5XSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBuYW1lID09PSAic3RyaW5nIikgewogICAgICAgICAgICBpZiAodmFsdWUgIT09IHZvaWQgMCkgewogICAgICAgICAgICAgIGlmIChnZXRUeXBlKHZhbHVlKSA9PT0gIlJlZ0V4cCIpIHsKICAgICAgICAgICAgICAgIGlmICghaXNBcnJheShkYXRhW25hbWVdKSAmJiB2YWx1ZS50ZXN0KGRhdGFbbmFtZV0pKSB7CiAgICAgICAgICAgICAgICAgIGRhdGFbbmFtZV0gPSB2b2lkIDA7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBkYXRhW25hbWVdID0gZmlsdGVyQXJyYXlWYWx1ZXMoZGF0YVtuYW1lXSwgdmFsdWUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0gZWxzZSBpZiAoZGF0YVtuYW1lXSA9PT0gU3RyaW5nKHZhbHVlKSAmJiAoIWlzQXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA9PT0gMSkpIHsKICAgICAgICAgICAgICAgIGRhdGFbbmFtZV0gPSB2b2lkIDA7CiAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGRhdGFbbmFtZV0pKSB7CiAgICAgICAgICAgICAgICBkYXRhW25hbWVdID0gZmlsdGVyQXJyYXlWYWx1ZXMoZGF0YVtuYW1lXSwgdmFsdWUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBkYXRhW25hbWVdID0gdm9pZCAwOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJVUkkucmVtb3ZlUXVlcnkoKSBhY2NlcHRzIGFuIG9iamVjdCwgc3RyaW5nLCBSZWdFeHAgYXMgdGhlIGZpcnN0IHBhcmFtZXRlciIpOwogICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgVVJJLmhhc1F1ZXJ5ID0gZnVuY3Rpb24oZGF0YSwgbmFtZSwgdmFsdWUsIHdpdGhpbkFycmF5KSB7CiAgICAgICAgICBzd2l0Y2ggKGdldFR5cGUobmFtZSkpIHsKICAgICAgICAgICAgY2FzZSAiU3RyaW5nIjoKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiUmVnRXhwIjoKICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gZGF0YSkgewogICAgICAgICAgICAgICAgaWYgKGhhc093bi5jYWxsKGRhdGEsIGtleSkpIHsKICAgICAgICAgICAgICAgICAgaWYgKG5hbWUudGVzdChrZXkpICYmICh2YWx1ZSA9PT0gdm9pZCAwIHx8IFVSSS5oYXNRdWVyeShkYXRhLCBrZXksIHZhbHVlKSkpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIGNhc2UgIk9iamVjdCI6CiAgICAgICAgICAgICAgZm9yICh2YXIgX2tleSBpbiBuYW1lKSB7CiAgICAgICAgICAgICAgICBpZiAoaGFzT3duLmNhbGwobmFtZSwgX2tleSkpIHsKICAgICAgICAgICAgICAgICAgaWYgKCFVUkkuaGFzUXVlcnkoZGF0YSwgX2tleSwgbmFtZVtfa2V5XSkpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiVVJJLmhhc1F1ZXJ5KCkgYWNjZXB0cyBhIHN0cmluZywgcmVndWxhciBleHByZXNzaW9uIG9yIG9iamVjdCBhcyB0aGUgbmFtZSBwYXJhbWV0ZXIiKTsKICAgICAgICAgIH0KICAgICAgICAgIHN3aXRjaCAoZ2V0VHlwZSh2YWx1ZSkpIHsKICAgICAgICAgICAgY2FzZSAiVW5kZWZpbmVkIjoKICAgICAgICAgICAgICByZXR1cm4gbmFtZSBpbiBkYXRhOwogICAgICAgICAgICAvLyBkYXRhW25hbWVdICE9PSB1bmRlZmluZWQ7CiAgICAgICAgICAgIGNhc2UgIkJvb2xlYW4iOgogICAgICAgICAgICAgIHZhciBfYm9vbHkgPSBCb29sZWFuKGlzQXJyYXkoZGF0YVtuYW1lXSkgPyBkYXRhW25hbWVdLmxlbmd0aCA6IGRhdGFbbmFtZV0pOwogICAgICAgICAgICAgIHJldHVybiB2YWx1ZSA9PT0gX2Jvb2x5OwogICAgICAgICAgICBjYXNlICJGdW5jdGlvbiI6CiAgICAgICAgICAgICAgcmV0dXJuICEhdmFsdWUoZGF0YVtuYW1lXSwgbmFtZSwgZGF0YSk7CiAgICAgICAgICAgIGNhc2UgIkFycmF5IjoKICAgICAgICAgICAgICBpZiAoIWlzQXJyYXkoZGF0YVtuYW1lXSkpIHsKICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmFyIG9wID0gd2l0aGluQXJyYXkgPyBhcnJheUNvbnRhaW5zIDogYXJyYXlzRXF1YWw7CiAgICAgICAgICAgICAgcmV0dXJuIG9wKGRhdGFbbmFtZV0sIHZhbHVlKTsKICAgICAgICAgICAgY2FzZSAiUmVnRXhwIjoKICAgICAgICAgICAgICBpZiAoIWlzQXJyYXkoZGF0YVtuYW1lXSkpIHsKICAgICAgICAgICAgICAgIHJldHVybiBCb29sZWFuKGRhdGFbbmFtZV0gJiYgZGF0YVtuYW1lXS5tYXRjaCh2YWx1ZSkpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoIXdpdGhpbkFycmF5KSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiBhcnJheUNvbnRhaW5zKGRhdGFbbmFtZV0sIHZhbHVlKTsKICAgICAgICAgICAgY2FzZSAiTnVtYmVyIjoKICAgICAgICAgICAgICB2YWx1ZSA9IFN0cmluZyh2YWx1ZSk7CiAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi8KICAgICAgICAgICAgY2FzZSAiU3RyaW5nIjoKICAgICAgICAgICAgICBpZiAoIWlzQXJyYXkoZGF0YVtuYW1lXSkpIHsKICAgICAgICAgICAgICAgIHJldHVybiBkYXRhW25hbWVdID09PSB2YWx1ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKCF3aXRoaW5BcnJheSkgewogICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gYXJyYXlDb250YWlucyhkYXRhW25hbWVdLCB2YWx1ZSk7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiVVJJLmhhc1F1ZXJ5KCkgYWNjZXB0cyB1bmRlZmluZWQsIGJvb2xlYW4sIHN0cmluZywgbnVtYmVyLCBSZWdFeHAsIEZ1bmN0aW9uIGFzIHRoZSB2YWx1ZSBwYXJhbWV0ZXIiKTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIFVSSS5qb2luUGF0aHMgPSBmdW5jdGlvbigpIHsKICAgICAgICAgIHZhciBpbnB1dCA9IFtdOwogICAgICAgICAgdmFyIHNlZ21lbnRzID0gW107CiAgICAgICAgICB2YXIgbm9uRW1wdHlTZWdtZW50cyA9IDA7CiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICB2YXIgdXJsID0gbmV3IFVSSShhcmd1bWVudHNbaV0pOwogICAgICAgICAgICBpbnB1dC5wdXNoKHVybCk7CiAgICAgICAgICAgIHZhciBfc2VnbWVudHMgPSB1cmwuc2VnbWVudCgpOwogICAgICAgICAgICBmb3IgKHZhciBzID0gMDsgcyA8IF9zZWdtZW50cy5sZW5ndGg7IHMrKykgewogICAgICAgICAgICAgIGlmICh0eXBlb2YgX3NlZ21lbnRzW3NdID09PSAic3RyaW5nIikgewogICAgICAgICAgICAgICAgc2VnbWVudHMucHVzaChfc2VnbWVudHNbc10pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoX3NlZ21lbnRzW3NdKSB7CiAgICAgICAgICAgICAgICBub25FbXB0eVNlZ21lbnRzKys7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIXNlZ21lbnRzLmxlbmd0aCB8fCAhbm9uRW1wdHlTZWdtZW50cykgewogICAgICAgICAgICByZXR1cm4gbmV3IFVSSSgiIik7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgdXJpID0gbmV3IFVSSSgiIikuc2VnbWVudChzZWdtZW50cyk7CiAgICAgICAgICBpZiAoaW5wdXRbMF0ucGF0aCgpID09PSAiIiB8fCBpbnB1dFswXS5wYXRoKCkuc2xpY2UoMCwgMSkgPT09ICIvIikgewogICAgICAgICAgICB1cmkucGF0aCgiLyIgKyB1cmkucGF0aCgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB1cmkubm9ybWFsaXplKCk7CiAgICAgICAgfTsKICAgICAgICBVUkkuY29tbW9uUGF0aCA9IGZ1bmN0aW9uKG9uZSwgdHdvKSB7CiAgICAgICAgICB2YXIgbGVuZ3RoID0gTWF0aC5taW4ob25lLmxlbmd0aCwgdHdvLmxlbmd0aCk7CiAgICAgICAgICB2YXIgcG9zOwogICAgICAgICAgZm9yIChwb3MgPSAwOyBwb3MgPCBsZW5ndGg7IHBvcysrKSB7CiAgICAgICAgICAgIGlmIChvbmUuY2hhckF0KHBvcykgIT09IHR3by5jaGFyQXQocG9zKSkgewogICAgICAgICAgICAgIHBvcy0tOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAocG9zIDwgMSkgewogICAgICAgICAgICByZXR1cm4gb25lLmNoYXJBdCgwKSA9PT0gdHdvLmNoYXJBdCgwKSAmJiBvbmUuY2hhckF0KDApID09PSAiLyIgPyAiLyIgOiAiIjsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChvbmUuY2hhckF0KHBvcykgIT09ICIvIiB8fCB0d28uY2hhckF0KHBvcykgIT09ICIvIikgewogICAgICAgICAgICBwb3MgPSBvbmUuc3Vic3RyaW5nKDAsIHBvcykubGFzdEluZGV4T2YoIi8iKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBvbmUuc3Vic3RyaW5nKDAsIHBvcyArIDEpOwogICAgICAgIH07CiAgICAgICAgVVJJLndpdGhpblN0cmluZyA9IGZ1bmN0aW9uKHN0cmluZywgY2FsbGJhY2ssIG9wdGlvbnMpIHsKICAgICAgICAgIG9wdGlvbnMgfHwgKG9wdGlvbnMgPSB7fSk7CiAgICAgICAgICB2YXIgX3N0YXJ0ID0gb3B0aW9ucy5zdGFydCB8fCBVUkkuZmluZFVyaS5zdGFydDsKICAgICAgICAgIHZhciBfZW5kID0gb3B0aW9ucy5lbmQgfHwgVVJJLmZpbmRVcmkuZW5kOwogICAgICAgICAgdmFyIF90cmltID0gb3B0aW9ucy50cmltIHx8IFVSSS5maW5kVXJpLnRyaW07CiAgICAgICAgICB2YXIgX3BhcmVucyA9IG9wdGlvbnMucGFyZW5zIHx8IFVSSS5maW5kVXJpLnBhcmVuczsKICAgICAgICAgIHZhciBfYXR0cmlidXRlT3BlbiA9IC9bYS16MC05LV09WyInXT8kL2k7CiAgICAgICAgICBfc3RhcnQubGFzdEluZGV4ID0gMDsKICAgICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgIHZhciBtYXRjaCA9IF9zdGFydC5leGVjKHN0cmluZyk7CiAgICAgICAgICAgIGlmICghbWF0Y2gpIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgc3RhcnQgPSBtYXRjaC5pbmRleDsKICAgICAgICAgICAgaWYgKG9wdGlvbnMuaWdub3JlSHRtbCkgewogICAgICAgICAgICAgIHZhciBhdHRyaWJ1dGVPcGVuID0gc3RyaW5nLnNsaWNlKE1hdGgubWF4KHN0YXJ0IC0gMywgMCksIHN0YXJ0KTsKICAgICAgICAgICAgICBpZiAoYXR0cmlidXRlT3BlbiAmJiBfYXR0cmlidXRlT3Blbi50ZXN0KGF0dHJpYnV0ZU9wZW4pKSB7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGVuZCA9IHN0YXJ0ICsgc3RyaW5nLnNsaWNlKHN0YXJ0KS5zZWFyY2goX2VuZCk7CiAgICAgICAgICAgIHZhciBzbGljZSA9IHN0cmluZy5zbGljZShzdGFydCwgZW5kKTsKICAgICAgICAgICAgdmFyIHBhcmVuc0VuZCA9IC0xOwogICAgICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgICAgIHZhciBwYXJlbnNNYXRjaCA9IF9wYXJlbnMuZXhlYyhzbGljZSk7CiAgICAgICAgICAgICAgaWYgKCFwYXJlbnNNYXRjaCkgewogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHZhciBwYXJlbnNNYXRjaEVuZCA9IHBhcmVuc01hdGNoLmluZGV4ICsgcGFyZW5zTWF0Y2hbMF0ubGVuZ3RoOwogICAgICAgICAgICAgIHBhcmVuc0VuZCA9IE1hdGgubWF4KHBhcmVuc0VuZCwgcGFyZW5zTWF0Y2hFbmQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChwYXJlbnNFbmQgPiAtMSkgewogICAgICAgICAgICAgIHNsaWNlID0gc2xpY2Uuc2xpY2UoMCwgcGFyZW5zRW5kKSArIHNsaWNlLnNsaWNlKHBhcmVuc0VuZCkucmVwbGFjZShfdHJpbSwgIiIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHNsaWNlID0gc2xpY2UucmVwbGFjZShfdHJpbSwgIiIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChzbGljZS5sZW5ndGggPD0gbWF0Y2hbMF0ubGVuZ3RoKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKG9wdGlvbnMuaWdub3JlICYmIG9wdGlvbnMuaWdub3JlLnRlc3Qoc2xpY2UpKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5kID0gc3RhcnQgKyBzbGljZS5sZW5ndGg7CiAgICAgICAgICAgIHZhciByZXN1bHQgPSBjYWxsYmFjayhzbGljZSwgc3RhcnQsIGVuZCwgc3RyaW5nKTsKICAgICAgICAgICAgaWYgKHJlc3VsdCA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgX3N0YXJ0Lmxhc3RJbmRleCA9IGVuZDsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXN1bHQgPSBTdHJpbmcocmVzdWx0KTsKICAgICAgICAgICAgc3RyaW5nID0gc3RyaW5nLnNsaWNlKDAsIHN0YXJ0KSArIHJlc3VsdCArIHN0cmluZy5zbGljZShlbmQpOwogICAgICAgICAgICBfc3RhcnQubGFzdEluZGV4ID0gc3RhcnQgKyByZXN1bHQubGVuZ3RoOwogICAgICAgICAgfQogICAgICAgICAgX3N0YXJ0Lmxhc3RJbmRleCA9IDA7CiAgICAgICAgICByZXR1cm4gc3RyaW5nOwogICAgICAgIH07CiAgICAgICAgVVJJLmVuc3VyZVZhbGlkSG9zdG5hbWUgPSBmdW5jdGlvbih2MywgcHJvdG9jb2wpIHsKICAgICAgICAgIHZhciBoYXNIb3N0bmFtZSA9ICEhdjM7CiAgICAgICAgICB2YXIgaGFzUHJvdG9jb2wgPSAhIXByb3RvY29sOwogICAgICAgICAgdmFyIHJlamVjdEVtcHR5SG9zdG5hbWUgPSBmYWxzZTsKICAgICAgICAgIGlmIChoYXNQcm90b2NvbCkgewogICAgICAgICAgICByZWplY3RFbXB0eUhvc3RuYW1lID0gYXJyYXlDb250YWlucyhVUkkuaG9zdFByb3RvY29scywgcHJvdG9jb2wpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHJlamVjdEVtcHR5SG9zdG5hbWUgJiYgIWhhc0hvc3RuYW1lKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIkhvc3RuYW1lIGNhbm5vdCBiZSBlbXB0eSwgaWYgcHJvdG9jb2wgaXMgIiArIHByb3RvY29sKTsKICAgICAgICAgIH0gZWxzZSBpZiAodjMgJiYgdjMubWF0Y2goVVJJLmludmFsaWRfaG9zdG5hbWVfY2hhcmFjdGVycykpIHsKICAgICAgICAgICAgaWYgKCFwdW55Y29kZSkgewogICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0hvc3RuYW1lICInICsgdjMgKyAnIiBjb250YWlucyBjaGFyYWN0ZXJzIG90aGVyIHRoYW4gW0EtWjAtOS4tOl9dIGFuZCBQdW55Y29kZS5qcyBpcyBub3QgYXZhaWxhYmxlJyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHB1bnljb2RlLnRvQVNDSUkodjMpLm1hdGNoKFVSSS5pbnZhbGlkX2hvc3RuYW1lX2NoYXJhY3RlcnMpKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignSG9zdG5hbWUgIicgKyB2MyArICciIGNvbnRhaW5zIGNoYXJhY3RlcnMgb3RoZXIgdGhhbiBbQS1aMC05Li06X10nKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgVVJJLmVuc3VyZVZhbGlkUG9ydCA9IGZ1bmN0aW9uKHYzKSB7CiAgICAgICAgICBpZiAoIXYzKSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBwb3J0ID0gTnVtYmVyKHYzKTsKICAgICAgICAgIGlmIChpc0ludGVnZXIocG9ydCkgJiYgcG9ydCA+IDAgJiYgcG9ydCA8IDY1NTM2KSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1BvcnQgIicgKyB2MyArICciIGlzIG5vdCBhIHZhbGlkIHBvcnQnKTsKICAgICAgICB9OwogICAgICAgIFVSSS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24ocmVtb3ZlQWxsKSB7CiAgICAgICAgICBpZiAocmVtb3ZlQWxsKSB7CiAgICAgICAgICAgIHZhciB1bmNvbmZsaWN0ZWQgPSB7CiAgICAgICAgICAgICAgVVJJOiB0aGlzLm5vQ29uZmxpY3QoKQogICAgICAgICAgICB9OwogICAgICAgICAgICBpZiAocm9vdC5VUklUZW1wbGF0ZSAmJiB0eXBlb2Ygcm9vdC5VUklUZW1wbGF0ZS5ub0NvbmZsaWN0ID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICAgICAgdW5jb25mbGljdGVkLlVSSVRlbXBsYXRlID0gcm9vdC5VUklUZW1wbGF0ZS5ub0NvbmZsaWN0KCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJvb3QuSVB2NiAmJiB0eXBlb2Ygcm9vdC5JUHY2Lm5vQ29uZmxpY3QgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgICAgICB1bmNvbmZsaWN0ZWQuSVB2NiA9IHJvb3QuSVB2Ni5ub0NvbmZsaWN0KCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJvb3QuU2Vjb25kTGV2ZWxEb21haW5zICYmIHR5cGVvZiByb290LlNlY29uZExldmVsRG9tYWlucy5ub0NvbmZsaWN0ID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICAgICAgdW5jb25mbGljdGVkLlNlY29uZExldmVsRG9tYWlucyA9IHJvb3QuU2Vjb25kTGV2ZWxEb21haW5zLm5vQ29uZmxpY3QoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdW5jb25mbGljdGVkOwogICAgICAgICAgfSBlbHNlIGlmIChyb290LlVSSSA9PT0gdGhpcykgewogICAgICAgICAgICByb290LlVSSSA9IF9VUkk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9OwogICAgICAgIHAuYnVpbGQgPSBmdW5jdGlvbihkZWZlckJ1aWxkKSB7CiAgICAgICAgICBpZiAoZGVmZXJCdWlsZCA9PT0gdHJ1ZSkgewogICAgICAgICAgICB0aGlzLl9kZWZlcnJlZF9idWlsZCA9IHRydWU7CiAgICAgICAgICB9IGVsc2UgaWYgKGRlZmVyQnVpbGQgPT09IHZvaWQgMCB8fCB0aGlzLl9kZWZlcnJlZF9idWlsZCkgewogICAgICAgICAgICB0aGlzLl9zdHJpbmcgPSBVUkkuYnVpbGQodGhpcy5fcGFydHMpOwogICAgICAgICAgICB0aGlzLl9kZWZlcnJlZF9idWlsZCA9IGZhbHNlOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfTsKICAgICAgICBwLmNsb25lID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFVSSSh0aGlzKTsKICAgICAgICB9OwogICAgICAgIHAudmFsdWVPZiA9IHAudG9TdHJpbmcgPSBmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiB0aGlzLmJ1aWxkKGZhbHNlKS5fc3RyaW5nOwogICAgICAgIH07CiAgICAgICAgZnVuY3Rpb24gZ2VuZXJhdGVTaW1wbGVBY2Nlc3NvcihfcGFydDIpIHsKICAgICAgICAgIHJldHVybiBmdW5jdGlvbih2MywgYnVpbGQpIHsKICAgICAgICAgICAgaWYgKHYzID09PSB2b2lkIDApIHsKICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcGFydHNbX3BhcnQyXSB8fCAiIjsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB0aGlzLl9wYXJ0c1tfcGFydDJdID0gdjMgfHwgbnVsbDsKICAgICAgICAgICAgICB0aGlzLmJ1aWxkKCFidWlsZCk7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgIH0KICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGdlbmVyYXRlUHJlZml4QWNjZXNzb3IoX3BhcnQyLCBfa2V5KSB7CiAgICAgICAgICByZXR1cm4gZnVuY3Rpb24odjMsIGJ1aWxkKSB7CiAgICAgICAgICAgIGlmICh2MyA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3BhcnRzW19wYXJ0Ml0gfHwgIiI7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgaWYgKHYzICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICB2MyA9IHYzICsgIiI7CiAgICAgICAgICAgICAgICBpZiAodjMuY2hhckF0KDApID09PSBfa2V5KSB7CiAgICAgICAgICAgICAgICAgIHYzID0gdjMuc3Vic3RyaW5nKDEpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0aGlzLl9wYXJ0c1tfcGFydDJdID0gdjM7CiAgICAgICAgICAgICAgdGhpcy5idWlsZCghYnVpbGQpOwogICAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgICB9CiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICBwLnByb3RvY29sID0gZ2VuZXJhdGVTaW1wbGVBY2Nlc3NvcigicHJvdG9jb2wiKTsKICAgICAgICBwLnVzZXJuYW1lID0gZ2VuZXJhdGVTaW1wbGVBY2Nlc3NvcigidXNlcm5hbWUiKTsKICAgICAgICBwLnBhc3N3b3JkID0gZ2VuZXJhdGVTaW1wbGVBY2Nlc3NvcigicGFzc3dvcmQiKTsKICAgICAgICBwLmhvc3RuYW1lID0gZ2VuZXJhdGVTaW1wbGVBY2Nlc3NvcigiaG9zdG5hbWUiKTsKICAgICAgICBwLnBvcnQgPSBnZW5lcmF0ZVNpbXBsZUFjY2Vzc29yKCJwb3J0Iik7CiAgICAgICAgcC5xdWVyeSA9IGdlbmVyYXRlUHJlZml4QWNjZXNzb3IoInF1ZXJ5IiwgIj8iKTsKICAgICAgICBwLmZyYWdtZW50ID0gZ2VuZXJhdGVQcmVmaXhBY2Nlc3NvcigiZnJhZ21lbnQiLCAiIyIpOwogICAgICAgIHAuc2VhcmNoID0gZnVuY3Rpb24odjMsIGJ1aWxkKSB7CiAgICAgICAgICB2YXIgdCA9IHRoaXMucXVlcnkodjMsIGJ1aWxkKTsKICAgICAgICAgIHJldHVybiB0eXBlb2YgdCA9PT0gInN0cmluZyIgJiYgdC5sZW5ndGggPyAiPyIgKyB0IDogdDsKICAgICAgICB9OwogICAgICAgIHAuaGFzaCA9IGZ1bmN0aW9uKHYzLCBidWlsZCkgewogICAgICAgICAgdmFyIHQgPSB0aGlzLmZyYWdtZW50KHYzLCBidWlsZCk7CiAgICAgICAgICByZXR1cm4gdHlwZW9mIHQgPT09ICJzdHJpbmciICYmIHQubGVuZ3RoID8gIiMiICsgdCA6IHQ7CiAgICAgICAgfTsKICAgICAgICBwLnBhdGhuYW1lID0gZnVuY3Rpb24odjMsIGJ1aWxkKSB7CiAgICAgICAgICBpZiAodjMgPT09IHZvaWQgMCB8fCB2MyA9PT0gdHJ1ZSkgewogICAgICAgICAgICB2YXIgcmVzID0gdGhpcy5fcGFydHMucGF0aCB8fCAodGhpcy5fcGFydHMuaG9zdG5hbWUgPyAiLyIgOiAiIik7CiAgICAgICAgICAgIHJldHVybiB2MyA/ICh0aGlzLl9wYXJ0cy51cm4gPyBVUkkuZGVjb2RlVXJuUGF0aCA6IFVSSS5kZWNvZGVQYXRoKShyZXMpIDogcmVzOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKHRoaXMuX3BhcnRzLnVybikgewogICAgICAgICAgICAgIHRoaXMuX3BhcnRzLnBhdGggPSB2MyA/IFVSSS5yZWNvZGVVcm5QYXRoKHYzKSA6ICIiOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRoaXMuX3BhcnRzLnBhdGggPSB2MyA/IFVSSS5yZWNvZGVQYXRoKHYzKSA6ICIvIjsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLmJ1aWxkKCFidWlsZCk7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgcC5wYXRoID0gcC5wYXRobmFtZTsKICAgICAgICBwLmhyZWYgPSBmdW5jdGlvbihocmVmLCBidWlsZCkgewogICAgICAgICAgdmFyIGtleTsKICAgICAgICAgIGlmIChocmVmID09PSB2b2lkIDApIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9TdHJpbmcoKTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuX3N0cmluZyA9ICIiOwogICAgICAgICAgdGhpcy5fcGFydHMgPSBVUkkuX3BhcnRzKCk7CiAgICAgICAgICB2YXIgX1VSSTIgPSBocmVmIGluc3RhbmNlb2YgVVJJOwogICAgICAgICAgdmFyIF9vYmplY3QgPSB0eXBlb2YgaHJlZiA9PT0gIm9iamVjdCIgJiYgKGhyZWYuaG9zdG5hbWUgfHwgaHJlZi5wYXRoIHx8IGhyZWYucGF0aG5hbWUpOwogICAgICAgICAgaWYgKGhyZWYubm9kZU5hbWUpIHsKICAgICAgICAgICAgdmFyIGF0dHJpYnV0ZSA9IFVSSS5nZXREb21BdHRyaWJ1dGUoaHJlZik7CiAgICAgICAgICAgIGhyZWYgPSBocmVmW2F0dHJpYnV0ZV0gfHwgIiI7CiAgICAgICAgICAgIF9vYmplY3QgPSBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghX1VSSTIgJiYgX29iamVjdCAmJiBocmVmLnBhdGhuYW1lICE9PSB2b2lkIDApIHsKICAgICAgICAgICAgaHJlZiA9IGhyZWYudG9TdHJpbmcoKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh0eXBlb2YgaHJlZiA9PT0gInN0cmluZyIgfHwgaHJlZiBpbnN0YW5jZW9mIFN0cmluZykgewogICAgICAgICAgICB0aGlzLl9wYXJ0cyA9IFVSSS5wYXJzZShTdHJpbmcoaHJlZiksIHRoaXMuX3BhcnRzKTsKICAgICAgICAgIH0gZWxzZSBpZiAoX1VSSTIgfHwgX29iamVjdCkgewogICAgICAgICAgICB2YXIgc3JjID0gX1VSSTIgPyBocmVmLl9wYXJ0cyA6IGhyZWY7CiAgICAgICAgICAgIGZvciAoa2V5IGluIHNyYykgewogICAgICAgICAgICAgIGlmIChrZXkgPT09ICJxdWVyeSIpIHsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoaGFzT3duLmNhbGwodGhpcy5fcGFydHMsIGtleSkpIHsKICAgICAgICAgICAgICAgIHRoaXMuX3BhcnRzW2tleV0gPSBzcmNba2V5XTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHNyYy5xdWVyeSkgewogICAgICAgICAgICAgIHRoaXMucXVlcnkoc3JjLnF1ZXJ5LCBmYWxzZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoImludmFsaWQgaW5wdXQiKTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH07CiAgICAgICAgcC5pcyA9IGZ1bmN0aW9uKHdoYXQpIHsKICAgICAgICAgIHZhciBpcCA9IGZhbHNlOwogICAgICAgICAgdmFyIGlwNCA9IGZhbHNlOwogICAgICAgICAgdmFyIGlwNiA9IGZhbHNlOwogICAgICAgICAgdmFyIG5hbWUgPSBmYWxzZTsKICAgICAgICAgIHZhciBzbGQgPSBmYWxzZTsKICAgICAgICAgIHZhciBpZG4gPSBmYWxzZTsKICAgICAgICAgIHZhciBwdW55Y29kZTIgPSBmYWxzZTsKICAgICAgICAgIHZhciByZWxhdGl2ZSA9ICF0aGlzLl9wYXJ0cy51cm47CiAgICAgICAgICBpZiAodGhpcy5fcGFydHMuaG9zdG5hbWUpIHsKICAgICAgICAgICAgcmVsYXRpdmUgPSBmYWxzZTsKICAgICAgICAgICAgaXA0ID0gVVJJLmlwNF9leHByZXNzaW9uLnRlc3QodGhpcy5fcGFydHMuaG9zdG5hbWUpOwogICAgICAgICAgICBpcDYgPSBVUkkuaXA2X2V4cHJlc3Npb24udGVzdCh0aGlzLl9wYXJ0cy5ob3N0bmFtZSk7CiAgICAgICAgICAgIGlwID0gaXA0IHx8IGlwNjsKICAgICAgICAgICAgbmFtZSA9ICFpcDsKICAgICAgICAgICAgc2xkID0gbmFtZSAmJiBTTEQgJiYgU0xELmhhcyh0aGlzLl9wYXJ0cy5ob3N0bmFtZSk7CiAgICAgICAgICAgIGlkbiA9IG5hbWUgJiYgVVJJLmlkbl9leHByZXNzaW9uLnRlc3QodGhpcy5fcGFydHMuaG9zdG5hbWUpOwogICAgICAgICAgICBwdW55Y29kZTIgPSBuYW1lICYmIFVSSS5wdW55Y29kZV9leHByZXNzaW9uLnRlc3QodGhpcy5fcGFydHMuaG9zdG5hbWUpOwogICAgICAgICAgfQogICAgICAgICAgc3dpdGNoICh3aGF0LnRvTG93ZXJDYXNlKCkpIHsKICAgICAgICAgICAgY2FzZSAicmVsYXRpdmUiOgogICAgICAgICAgICAgIHJldHVybiByZWxhdGl2ZTsKICAgICAgICAgICAgY2FzZSAiYWJzb2x1dGUiOgogICAgICAgICAgICAgIHJldHVybiAhcmVsYXRpdmU7CiAgICAgICAgICAgIC8vIGhvc3RuYW1lIGlkZW50aWZpY2F0aW9uCiAgICAgICAgICAgIGNhc2UgImRvbWFpbiI6CiAgICAgICAgICAgIGNhc2UgIm5hbWUiOgogICAgICAgICAgICAgIHJldHVybiBuYW1lOwogICAgICAgICAgICBjYXNlICJzbGQiOgogICAgICAgICAgICAgIHJldHVybiBzbGQ7CiAgICAgICAgICAgIGNhc2UgImlwIjoKICAgICAgICAgICAgICByZXR1cm4gaXA7CiAgICAgICAgICAgIGNhc2UgImlwNCI6CiAgICAgICAgICAgIGNhc2UgImlwdjQiOgogICAgICAgICAgICBjYXNlICJpbmV0NCI6CiAgICAgICAgICAgICAgcmV0dXJuIGlwNDsKICAgICAgICAgICAgY2FzZSAiaXA2IjoKICAgICAgICAgICAgY2FzZSAiaXB2NiI6CiAgICAgICAgICAgIGNhc2UgImluZXQ2IjoKICAgICAgICAgICAgICByZXR1cm4gaXA2OwogICAgICAgICAgICBjYXNlICJpZG4iOgogICAgICAgICAgICAgIHJldHVybiBpZG47CiAgICAgICAgICAgIGNhc2UgInVybCI6CiAgICAgICAgICAgICAgcmV0dXJuICF0aGlzLl9wYXJ0cy51cm47CiAgICAgICAgICAgIGNhc2UgInVybiI6CiAgICAgICAgICAgICAgcmV0dXJuICEhdGhpcy5fcGFydHMudXJuOwogICAgICAgICAgICBjYXNlICJwdW55Y29kZSI6CiAgICAgICAgICAgICAgcmV0dXJuIHB1bnljb2RlMjsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH07CiAgICAgICAgdmFyIF9wcm90b2NvbCA9IHAucHJvdG9jb2w7CiAgICAgICAgdmFyIF9wb3J0ID0gcC5wb3J0OwogICAgICAgIHZhciBfaG9zdG5hbWUgPSBwLmhvc3RuYW1lOwogICAgICAgIHAucHJvdG9jb2wgPSBmdW5jdGlvbih2MywgYnVpbGQpIHsKICAgICAgICAgIGlmICh2MykgewogICAgICAgICAgICB2MyA9IHYzLnJlcGxhY2UoLzooXC9cLyk/JC8sICIiKTsKICAgICAgICAgICAgaWYgKCF2My5tYXRjaChVUkkucHJvdG9jb2xfZXhwcmVzc2lvbikpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdQcm90b2NvbCAiJyArIHYzICsgYCIgY29udGFpbnMgY2hhcmFjdGVycyBvdGhlciB0aGFuIFtBLVowLTkuKy1dIG9yIGRvZXNuJ3Qgc3RhcnQgd2l0aCBbQS1aXWApOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gX3Byb3RvY29sLmNhbGwodGhpcywgdjMsIGJ1aWxkKTsKICAgICAgICB9OwogICAgICAgIHAuc2NoZW1lID0gcC5wcm90b2NvbDsKICAgICAgICBwLnBvcnQgPSBmdW5jdGlvbih2MywgYnVpbGQpIHsKICAgICAgICAgIGlmICh0aGlzLl9wYXJ0cy51cm4pIHsKICAgICAgICAgICAgcmV0dXJuIHYzID09PSB2b2lkIDAgPyAiIiA6IHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodjMgIT09IHZvaWQgMCkgewogICAgICAgICAgICBpZiAodjMgPT09IDApIHsKICAgICAgICAgICAgICB2MyA9IG51bGw7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHYzKSB7CiAgICAgICAgICAgICAgdjMgKz0gIiI7CiAgICAgICAgICAgICAgaWYgKHYzLmNoYXJBdCgwKSA9PT0gIjoiKSB7CiAgICAgICAgICAgICAgICB2MyA9IHYzLnN1YnN0cmluZygxKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgVVJJLmVuc3VyZVZhbGlkUG9ydCh2Myk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBfcG9ydC5jYWxsKHRoaXMsIHYzLCBidWlsZCk7CiAgICAgICAgfTsKICAgICAgICBwLmhvc3RuYW1lID0gZnVuY3Rpb24odjMsIGJ1aWxkKSB7CiAgICAgICAgICBpZiAodGhpcy5fcGFydHMudXJuKSB7CiAgICAgICAgICAgIHJldHVybiB2MyA9PT0gdm9pZCAwID8gIiIgOiB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHYzICE9PSB2b2lkIDApIHsKICAgICAgICAgICAgdmFyIHggPSB7IHByZXZlbnRJbnZhbGlkSG9zdG5hbWU6IHRoaXMuX3BhcnRzLnByZXZlbnRJbnZhbGlkSG9zdG5hbWUgfTsKICAgICAgICAgICAgdmFyIHJlcyA9IFVSSS5wYXJzZUhvc3QodjMsIHgpOwogICAgICAgICAgICBpZiAocmVzICE9PSAiLyIpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdIb3N0bmFtZSAiJyArIHYzICsgJyIgY29udGFpbnMgY2hhcmFjdGVycyBvdGhlciB0aGFuIFtBLVowLTkuLV0nKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2MyA9IHguaG9zdG5hbWU7CiAgICAgICAgICAgIGlmICh0aGlzLl9wYXJ0cy5wcmV2ZW50SW52YWxpZEhvc3RuYW1lKSB7CiAgICAgICAgICAgICAgVVJJLmVuc3VyZVZhbGlkSG9zdG5hbWUodjMsIHRoaXMuX3BhcnRzLnByb3RvY29sKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIF9ob3N0bmFtZS5jYWxsKHRoaXMsIHYzLCBidWlsZCk7CiAgICAgICAgfTsKICAgICAgICBwLm9yaWdpbiA9IGZ1bmN0aW9uKHYzLCBidWlsZCkgewogICAgICAgICAgaWYgKHRoaXMuX3BhcnRzLnVybikgewogICAgICAgICAgICByZXR1cm4gdjMgPT09IHZvaWQgMCA/ICIiIDogdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2MyA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgIHZhciBwcm90b2NvbCA9IHRoaXMucHJvdG9jb2woKTsKICAgICAgICAgICAgdmFyIGF1dGhvcml0eSA9IHRoaXMuYXV0aG9yaXR5KCk7CiAgICAgICAgICAgIGlmICghYXV0aG9yaXR5KSB7CiAgICAgICAgICAgICAgcmV0dXJuICIiOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiAocHJvdG9jb2wgPyBwcm90b2NvbCArICI6Ly8iIDogIiIpICsgdGhpcy5hdXRob3JpdHkoKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHZhciBvcmlnaW4gPSBVUkkodjMpOwogICAgICAgICAgICB0aGlzLnByb3RvY29sKG9yaWdpbi5wcm90b2NvbCgpKS5hdXRob3JpdHkob3JpZ2luLmF1dGhvcml0eSgpKS5idWlsZCghYnVpbGQpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHAuaG9zdCA9IGZ1bmN0aW9uKHYzLCBidWlsZCkgewogICAgICAgICAgaWYgKHRoaXMuX3BhcnRzLnVybikgewogICAgICAgICAgICByZXR1cm4gdjMgPT09IHZvaWQgMCA/ICIiIDogdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2MyA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9wYXJ0cy5ob3N0bmFtZSA/IFVSSS5idWlsZEhvc3QodGhpcy5fcGFydHMpIDogIiI7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB2YXIgcmVzID0gVVJJLnBhcnNlSG9zdCh2MywgdGhpcy5fcGFydHMpOwogICAgICAgICAgICBpZiAocmVzICE9PSAiLyIpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdIb3N0bmFtZSAiJyArIHYzICsgJyIgY29udGFpbnMgY2hhcmFjdGVycyBvdGhlciB0aGFuIFtBLVowLTkuLV0nKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLmJ1aWxkKCFidWlsZCk7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgcC5hdXRob3JpdHkgPSBmdW5jdGlvbih2MywgYnVpbGQpIHsKICAgICAgICAgIGlmICh0aGlzLl9wYXJ0cy51cm4pIHsKICAgICAgICAgICAgcmV0dXJuIHYzID09PSB2b2lkIDAgPyAiIiA6IHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodjMgPT09IHZvaWQgMCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fcGFydHMuaG9zdG5hbWUgPyBVUkkuYnVpbGRBdXRob3JpdHkodGhpcy5fcGFydHMpIDogIiI7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB2YXIgcmVzID0gVVJJLnBhcnNlQXV0aG9yaXR5KHYzLCB0aGlzLl9wYXJ0cyk7CiAgICAgICAgICAgIGlmIChyZXMgIT09ICIvIikgewogICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0hvc3RuYW1lICInICsgdjMgKyAnIiBjb250YWlucyBjaGFyYWN0ZXJzIG90aGVyIHRoYW4gW0EtWjAtOS4tXScpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICBwLnVzZXJpbmZvID0gZnVuY3Rpb24odjMsIGJ1aWxkKSB7CiAgICAgICAgICBpZiAodGhpcy5fcGFydHMudXJuKSB7CiAgICAgICAgICAgIHJldHVybiB2MyA9PT0gdm9pZCAwID8gIiIgOiB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHYzID09PSB2b2lkIDApIHsKICAgICAgICAgICAgdmFyIHQgPSBVUkkuYnVpbGRVc2VyaW5mbyh0aGlzLl9wYXJ0cyk7CiAgICAgICAgICAgIHJldHVybiB0ID8gdC5zdWJzdHJpbmcoMCwgdC5sZW5ndGggLSAxKSA6IHQ7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpZiAodjNbdjMubGVuZ3RoIC0gMV0gIT09ICJAIikgewogICAgICAgICAgICAgIHYzICs9ICJAIjsKICAgICAgICAgICAgfQogICAgICAgICAgICBVUkkucGFyc2VVc2VyaW5mbyh2MywgdGhpcy5fcGFydHMpOwogICAgICAgICAgICB0aGlzLmJ1aWxkKCFidWlsZCk7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgcC5yZXNvdXJjZSA9IGZ1bmN0aW9uKHYzLCBidWlsZCkgewogICAgICAgICAgdmFyIHBhcnRzOwogICAgICAgICAgaWYgKHYzID09PSB2b2lkIDApIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMucGF0aCgpICsgdGhpcy5zZWFyY2goKSArIHRoaXMuaGFzaCgpOwogICAgICAgICAgfQogICAgICAgICAgcGFydHMgPSBVUkkucGFyc2UodjMpOwogICAgICAgICAgdGhpcy5fcGFydHMucGF0aCA9IHBhcnRzLnBhdGg7CiAgICAgICAgICB0aGlzLl9wYXJ0cy5xdWVyeSA9IHBhcnRzLnF1ZXJ5OwogICAgICAgICAgdGhpcy5fcGFydHMuZnJhZ21lbnQgPSBwYXJ0cy5mcmFnbWVudDsKICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH07CiAgICAgICAgcC5zdWJkb21haW4gPSBmdW5jdGlvbih2MywgYnVpbGQpIHsKICAgICAgICAgIGlmICh0aGlzLl9wYXJ0cy51cm4pIHsKICAgICAgICAgICAgcmV0dXJuIHYzID09PSB2b2lkIDAgPyAiIiA6IHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodjMgPT09IHZvaWQgMCkgewogICAgICAgICAgICBpZiAoIXRoaXMuX3BhcnRzLmhvc3RuYW1lIHx8IHRoaXMuaXMoIklQIikpIHsKICAgICAgICAgICAgICByZXR1cm4gIiI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGVuZCA9IHRoaXMuX3BhcnRzLmhvc3RuYW1lLmxlbmd0aCAtIHRoaXMuZG9tYWluKCkubGVuZ3RoIC0gMTsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3BhcnRzLmhvc3RuYW1lLnN1YnN0cmluZygwLCBlbmQpIHx8ICIiOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdmFyIGUgPSB0aGlzLl9wYXJ0cy5ob3N0bmFtZS5sZW5ndGggLSB0aGlzLmRvbWFpbigpLmxlbmd0aDsKICAgICAgICAgICAgdmFyIHN1YiA9IHRoaXMuX3BhcnRzLmhvc3RuYW1lLnN1YnN0cmluZygwLCBlKTsKICAgICAgICAgICAgdmFyIHJlcGxhY2UgPSBuZXcgUmVnRXhwKCJeIiArIGVzY2FwZVJlZ0V4KHN1YikpOwogICAgICAgICAgICBpZiAodjMgJiYgdjMuY2hhckF0KHYzLmxlbmd0aCAtIDEpICE9PSAiLiIpIHsKICAgICAgICAgICAgICB2MyArPSAiLiI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHYzLmluZGV4T2YoIjoiKSAhPT0gLTEpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJEb21haW5zIGNhbm5vdCBjb250YWluIGNvbG9ucyIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh2MykgewogICAgICAgICAgICAgIFVSSS5lbnN1cmVWYWxpZEhvc3RuYW1lKHYzLCB0aGlzLl9wYXJ0cy5wcm90b2NvbCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5fcGFydHMuaG9zdG5hbWUgPSB0aGlzLl9wYXJ0cy5ob3N0bmFtZS5yZXBsYWNlKHJlcGxhY2UsIHYzKTsKICAgICAgICAgICAgdGhpcy5idWlsZCghYnVpbGQpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHAuZG9tYWluID0gZnVuY3Rpb24odjMsIGJ1aWxkKSB7CiAgICAgICAgICBpZiAodGhpcy5fcGFydHMudXJuKSB7CiAgICAgICAgICAgIHJldHVybiB2MyA9PT0gdm9pZCAwID8gIiIgOiB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHR5cGVvZiB2MyA9PT0gImJvb2xlYW4iKSB7CiAgICAgICAgICAgIGJ1aWxkID0gdjM7CiAgICAgICAgICAgIHYzID0gdm9pZCAwOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHYzID09PSB2b2lkIDApIHsKICAgICAgICAgICAgaWYgKCF0aGlzLl9wYXJ0cy5ob3N0bmFtZSB8fCB0aGlzLmlzKCJJUCIpKSB7CiAgICAgICAgICAgICAgcmV0dXJuICIiOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciB0ID0gdGhpcy5fcGFydHMuaG9zdG5hbWUubWF0Y2goL1wuL2cpOwogICAgICAgICAgICBpZiAodCAmJiB0Lmxlbmd0aCA8IDIpIHsKICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcGFydHMuaG9zdG5hbWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGVuZCA9IHRoaXMuX3BhcnRzLmhvc3RuYW1lLmxlbmd0aCAtIHRoaXMudGxkKGJ1aWxkKS5sZW5ndGggLSAxOwogICAgICAgICAgICBlbmQgPSB0aGlzLl9wYXJ0cy5ob3N0bmFtZS5sYXN0SW5kZXhPZigiLiIsIGVuZCAtIDEpICsgMTsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3BhcnRzLmhvc3RuYW1lLnN1YnN0cmluZyhlbmQpIHx8ICIiOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKCF2MykgewogICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoImNhbm5vdCBzZXQgZG9tYWluIGVtcHR5Iik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHYzLmluZGV4T2YoIjoiKSAhPT0gLTEpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJEb21haW5zIGNhbm5vdCBjb250YWluIGNvbG9ucyIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIFVSSS5lbnN1cmVWYWxpZEhvc3RuYW1lKHYzLCB0aGlzLl9wYXJ0cy5wcm90b2NvbCk7CiAgICAgICAgICAgIGlmICghdGhpcy5fcGFydHMuaG9zdG5hbWUgfHwgdGhpcy5pcygiSVAiKSkgewogICAgICAgICAgICAgIHRoaXMuX3BhcnRzLmhvc3RuYW1lID0gdjM7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdmFyIHJlcGxhY2UgPSBuZXcgUmVnRXhwKGVzY2FwZVJlZ0V4KHRoaXMuZG9tYWluKCkpICsgIiQiKTsKICAgICAgICAgICAgICB0aGlzLl9wYXJ0cy5ob3N0bmFtZSA9IHRoaXMuX3BhcnRzLmhvc3RuYW1lLnJlcGxhY2UocmVwbGFjZSwgdjMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICBwLnRsZCA9IGZ1bmN0aW9uKHYzLCBidWlsZCkgewogICAgICAgICAgaWYgKHRoaXMuX3BhcnRzLnVybikgewogICAgICAgICAgICByZXR1cm4gdjMgPT09IHZvaWQgMCA/ICIiIDogdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh0eXBlb2YgdjMgPT09ICJib29sZWFuIikgewogICAgICAgICAgICBidWlsZCA9IHYzOwogICAgICAgICAgICB2MyA9IHZvaWQgMDsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2MyA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgIGlmICghdGhpcy5fcGFydHMuaG9zdG5hbWUgfHwgdGhpcy5pcygiSVAiKSkgewogICAgICAgICAgICAgIHJldHVybiAiIjsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgcG9zID0gdGhpcy5fcGFydHMuaG9zdG5hbWUubGFzdEluZGV4T2YoIi4iKTsKICAgICAgICAgICAgdmFyIHRsZCA9IHRoaXMuX3BhcnRzLmhvc3RuYW1lLnN1YnN0cmluZyhwb3MgKyAxKTsKICAgICAgICAgICAgaWYgKGJ1aWxkICE9PSB0cnVlICYmIFNMRCAmJiBTTEQubGlzdFt0bGQudG9Mb3dlckNhc2UoKV0pIHsKICAgICAgICAgICAgICByZXR1cm4gU0xELmdldCh0aGlzLl9wYXJ0cy5ob3N0bmFtZSkgfHwgdGxkOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0bGQ7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB2YXIgcmVwbGFjZTsKICAgICAgICAgICAgaWYgKCF2MykgewogICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoImNhbm5vdCBzZXQgVExEIGVtcHR5Iik7CiAgICAgICAgICAgIH0gZWxzZSBpZiAodjMubWF0Y2goL1teYS16QS1aMC05LV0vKSkgewogICAgICAgICAgICAgIGlmIChTTEQgJiYgU0xELmlzKHYzKSkgewogICAgICAgICAgICAgICAgcmVwbGFjZSA9IG5ldyBSZWdFeHAoZXNjYXBlUmVnRXgodGhpcy50bGQoKSkgKyAiJCIpOwogICAgICAgICAgICAgICAgdGhpcy5fcGFydHMuaG9zdG5hbWUgPSB0aGlzLl9wYXJ0cy5ob3N0bmFtZS5yZXBsYWNlKHJlcGxhY2UsIHYzKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVExEICInICsgdjMgKyAnIiBjb250YWlucyBjaGFyYWN0ZXJzIG90aGVyIHRoYW4gW0EtWjAtOV0nKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuX3BhcnRzLmhvc3RuYW1lIHx8IHRoaXMuaXMoIklQIikpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoImNhbm5vdCBzZXQgVExEIG9uIG5vbi1kb21haW4gaG9zdCIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJlcGxhY2UgPSBuZXcgUmVnRXhwKGVzY2FwZVJlZ0V4KHRoaXMudGxkKCkpICsgIiQiKTsKICAgICAgICAgICAgICB0aGlzLl9wYXJ0cy5ob3N0bmFtZSA9IHRoaXMuX3BhcnRzLmhvc3RuYW1lLnJlcGxhY2UocmVwbGFjZSwgdjMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICBwLmRpcmVjdG9yeSA9IGZ1bmN0aW9uKHYzLCBidWlsZCkgewogICAgICAgICAgaWYgKHRoaXMuX3BhcnRzLnVybikgewogICAgICAgICAgICByZXR1cm4gdjMgPT09IHZvaWQgMCA/ICIiIDogdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2MyA9PT0gdm9pZCAwIHx8IHYzID09PSB0cnVlKSB7CiAgICAgICAgICAgIGlmICghdGhpcy5fcGFydHMucGF0aCAmJiAhdGhpcy5fcGFydHMuaG9zdG5hbWUpIHsKICAgICAgICAgICAgICByZXR1cm4gIiI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHRoaXMuX3BhcnRzLnBhdGggPT09ICIvIikgewogICAgICAgICAgICAgIHJldHVybiAiLyI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGVuZCA9IHRoaXMuX3BhcnRzLnBhdGgubGVuZ3RoIC0gdGhpcy5maWxlbmFtZSgpLmxlbmd0aCAtIDE7CiAgICAgICAgICAgIHZhciByZXMgPSB0aGlzLl9wYXJ0cy5wYXRoLnN1YnN0cmluZygwLCBlbmQpIHx8ICh0aGlzLl9wYXJ0cy5ob3N0bmFtZSA/ICIvIiA6ICIiKTsKICAgICAgICAgICAgcmV0dXJuIHYzID8gVVJJLmRlY29kZVBhdGgocmVzKSA6IHJlczsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHZhciBlID0gdGhpcy5fcGFydHMucGF0aC5sZW5ndGggLSB0aGlzLmZpbGVuYW1lKCkubGVuZ3RoOwogICAgICAgICAgICB2YXIgZGlyZWN0b3J5ID0gdGhpcy5fcGFydHMucGF0aC5zdWJzdHJpbmcoMCwgZSk7CiAgICAgICAgICAgIHZhciByZXBsYWNlID0gbmV3IFJlZ0V4cCgiXiIgKyBlc2NhcGVSZWdFeChkaXJlY3RvcnkpKTsKICAgICAgICAgICAgaWYgKCF0aGlzLmlzKCJyZWxhdGl2ZSIpKSB7CiAgICAgICAgICAgICAgaWYgKCF2MykgewogICAgICAgICAgICAgICAgdjMgPSAiLyI7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICh2My5jaGFyQXQoMCkgIT09ICIvIikgewogICAgICAgICAgICAgICAgdjMgPSAiLyIgKyB2MzsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHYzICYmIHYzLmNoYXJBdCh2My5sZW5ndGggLSAxKSAhPT0gIi8iKSB7CiAgICAgICAgICAgICAgdjMgKz0gIi8iOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHYzID0gVVJJLnJlY29kZVBhdGgodjMpOwogICAgICAgICAgICB0aGlzLl9wYXJ0cy5wYXRoID0gdGhpcy5fcGFydHMucGF0aC5yZXBsYWNlKHJlcGxhY2UsIHYzKTsKICAgICAgICAgICAgdGhpcy5idWlsZCghYnVpbGQpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHAuZmlsZW5hbWUgPSBmdW5jdGlvbih2MywgYnVpbGQpIHsKICAgICAgICAgIGlmICh0aGlzLl9wYXJ0cy51cm4pIHsKICAgICAgICAgICAgcmV0dXJuIHYzID09PSB2b2lkIDAgPyAiIiA6IHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodHlwZW9mIHYzICE9PSAic3RyaW5nIikgewogICAgICAgICAgICBpZiAoIXRoaXMuX3BhcnRzLnBhdGggfHwgdGhpcy5fcGFydHMucGF0aCA9PT0gIi8iKSB7CiAgICAgICAgICAgICAgcmV0dXJuICIiOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBwb3MgPSB0aGlzLl9wYXJ0cy5wYXRoLmxhc3RJbmRleE9mKCIvIik7CiAgICAgICAgICAgIHZhciByZXMgPSB0aGlzLl9wYXJ0cy5wYXRoLnN1YnN0cmluZyhwb3MgKyAxKTsKICAgICAgICAgICAgcmV0dXJuIHYzID8gVVJJLmRlY29kZVBhdGhTZWdtZW50KHJlcykgOiByZXM7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB2YXIgbXV0YXRlZERpcmVjdG9yeSA9IGZhbHNlOwogICAgICAgICAgICBpZiAodjMuY2hhckF0KDApID09PSAiLyIpIHsKICAgICAgICAgICAgICB2MyA9IHYzLnN1YnN0cmluZygxKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodjMubWF0Y2goL1wuP1wvLykpIHsKICAgICAgICAgICAgICBtdXRhdGVkRGlyZWN0b3J5ID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgcmVwbGFjZSA9IG5ldyBSZWdFeHAoZXNjYXBlUmVnRXgodGhpcy5maWxlbmFtZSgpKSArICIkIik7CiAgICAgICAgICAgIHYzID0gVVJJLnJlY29kZVBhdGgodjMpOwogICAgICAgICAgICB0aGlzLl9wYXJ0cy5wYXRoID0gdGhpcy5fcGFydHMucGF0aC5yZXBsYWNlKHJlcGxhY2UsIHYzKTsKICAgICAgICAgICAgaWYgKG11dGF0ZWREaXJlY3RvcnkpIHsKICAgICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZVBhdGgoYnVpbGQpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHAuc3VmZml4ID0gZnVuY3Rpb24odjMsIGJ1aWxkKSB7CiAgICAgICAgICBpZiAodGhpcy5fcGFydHMudXJuKSB7CiAgICAgICAgICAgIHJldHVybiB2MyA9PT0gdm9pZCAwID8gIiIgOiB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHYzID09PSB2b2lkIDAgfHwgdjMgPT09IHRydWUpIHsKICAgICAgICAgICAgaWYgKCF0aGlzLl9wYXJ0cy5wYXRoIHx8IHRoaXMuX3BhcnRzLnBhdGggPT09ICIvIikgewogICAgICAgICAgICAgIHJldHVybiAiIjsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgZmlsZW5hbWUgPSB0aGlzLmZpbGVuYW1lKCk7CiAgICAgICAgICAgIHZhciBwb3MgPSBmaWxlbmFtZS5sYXN0SW5kZXhPZigiLiIpOwogICAgICAgICAgICB2YXIgcywgcmVzOwogICAgICAgICAgICBpZiAocG9zID09PSAtMSkgewogICAgICAgICAgICAgIHJldHVybiAiIjsKICAgICAgICAgICAgfQogICAgICAgICAgICBzID0gZmlsZW5hbWUuc3Vic3RyaW5nKHBvcyArIDEpOwogICAgICAgICAgICByZXMgPSAvXlthLXowLTklXSskL2kudGVzdChzKSA/IHMgOiAiIjsKICAgICAgICAgICAgcmV0dXJuIHYzID8gVVJJLmRlY29kZVBhdGhTZWdtZW50KHJlcykgOiByZXM7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpZiAodjMuY2hhckF0KDApID09PSAiLiIpIHsKICAgICAgICAgICAgICB2MyA9IHYzLnN1YnN0cmluZygxKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgc3VmZml4ID0gdGhpcy5zdWZmaXgoKTsKICAgICAgICAgICAgdmFyIHJlcGxhY2U7CiAgICAgICAgICAgIGlmICghc3VmZml4KSB7CiAgICAgICAgICAgICAgaWYgKCF2MykgewogICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRoaXMuX3BhcnRzLnBhdGggKz0gIi4iICsgVVJJLnJlY29kZVBhdGgodjMpOwogICAgICAgICAgICB9IGVsc2UgaWYgKCF2MykgewogICAgICAgICAgICAgIHJlcGxhY2UgPSBuZXcgUmVnRXhwKGVzY2FwZVJlZ0V4KCIuIiArIHN1ZmZpeCkgKyAiJCIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJlcGxhY2UgPSBuZXcgUmVnRXhwKGVzY2FwZVJlZ0V4KHN1ZmZpeCkgKyAiJCIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChyZXBsYWNlKSB7CiAgICAgICAgICAgICAgdjMgPSBVUkkucmVjb2RlUGF0aCh2Myk7CiAgICAgICAgICAgICAgdGhpcy5fcGFydHMucGF0aCA9IHRoaXMuX3BhcnRzLnBhdGgucmVwbGFjZShyZXBsYWNlLCB2Myk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5idWlsZCghYnVpbGQpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHAuc2VnbWVudCA9IGZ1bmN0aW9uKHNlZ21lbnQsIHYzLCBidWlsZCkgewogICAgICAgICAgdmFyIHNlcGFyYXRvciA9IHRoaXMuX3BhcnRzLnVybiA/ICI6IiA6ICIvIjsKICAgICAgICAgIHZhciBwYXRoID0gdGhpcy5wYXRoKCk7CiAgICAgICAgICB2YXIgYWJzb2x1dGUgPSBwYXRoLnN1YnN0cmluZygwLCAxKSA9PT0gIi8iOwogICAgICAgICAgdmFyIHNlZ21lbnRzID0gcGF0aC5zcGxpdChzZXBhcmF0b3IpOwogICAgICAgICAgaWYgKHNlZ21lbnQgIT09IHZvaWQgMCAmJiB0eXBlb2Ygc2VnbWVudCAhPT0gIm51bWJlciIpIHsKICAgICAgICAgICAgYnVpbGQgPSB2MzsKICAgICAgICAgICAgdjMgPSBzZWdtZW50OwogICAgICAgICAgICBzZWdtZW50ID0gdm9pZCAwOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHNlZ21lbnQgIT09IHZvaWQgMCAmJiB0eXBlb2Ygc2VnbWVudCAhPT0gIm51bWJlciIpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdCYWQgc2VnbWVudCAiJyArIHNlZ21lbnQgKyAnIiwgbXVzdCBiZSAwLWJhc2VkIGludGVnZXInKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChhYnNvbHV0ZSkgewogICAgICAgICAgICBzZWdtZW50cy5zaGlmdCgpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHNlZ21lbnQgPCAwKSB7CiAgICAgICAgICAgIHNlZ21lbnQgPSBNYXRoLm1heChzZWdtZW50cy5sZW5ndGggKyBzZWdtZW50LCAwKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2MyA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgIHJldHVybiBzZWdtZW50ID09PSB2b2lkIDAgPyBzZWdtZW50cyA6IHNlZ21lbnRzW3NlZ21lbnRdOwogICAgICAgICAgfSBlbHNlIGlmIChzZWdtZW50ID09PSBudWxsIHx8IHNlZ21lbnRzW3NlZ21lbnRdID09PSB2b2lkIDApIHsKICAgICAgICAgICAgaWYgKGlzQXJyYXkodjMpKSB7CiAgICAgICAgICAgICAgc2VnbWVudHMgPSBbXTsKICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHYzLmxlbmd0aDsgaSA8IGw7IGkrKykgewogICAgICAgICAgICAgICAgaWYgKCF2M1tpXS5sZW5ndGggJiYgKCFzZWdtZW50cy5sZW5ndGggfHwgIXNlZ21lbnRzW3NlZ21lbnRzLmxlbmd0aCAtIDFdLmxlbmd0aCkpIHsKICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoc2VnbWVudHMubGVuZ3RoICYmICFzZWdtZW50c1tzZWdtZW50cy5sZW5ndGggLSAxXS5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgc2VnbWVudHMucG9wKCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzZWdtZW50cy5wdXNoKHRyaW1TbGFzaGVzKHYzW2ldKSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgaWYgKHYzIHx8IHR5cGVvZiB2MyA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICB2MyA9IHRyaW1TbGFzaGVzKHYzKTsKICAgICAgICAgICAgICBpZiAoc2VnbWVudHNbc2VnbWVudHMubGVuZ3RoIC0gMV0gPT09ICIiKSB7CiAgICAgICAgICAgICAgICBzZWdtZW50c1tzZWdtZW50cy5sZW5ndGggLSAxXSA9IHYzOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBzZWdtZW50cy5wdXNoKHYzKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmICh2MykgewogICAgICAgICAgICAgIHNlZ21lbnRzW3NlZ21lbnRdID0gdHJpbVNsYXNoZXModjMpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHNlZ21lbnRzLnNwbGljZShzZWdtZW50LCAxKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGFic29sdXRlKSB7CiAgICAgICAgICAgIHNlZ21lbnRzLnVuc2hpZnQoIiIpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXMucGF0aChzZWdtZW50cy5qb2luKHNlcGFyYXRvciksIGJ1aWxkKTsKICAgICAgICB9OwogICAgICAgIHAuc2VnbWVudENvZGVkID0gZnVuY3Rpb24oc2VnbWVudCwgdjMsIGJ1aWxkKSB7CiAgICAgICAgICB2YXIgc2VnbWVudHMsIGksIGw7CiAgICAgICAgICBpZiAodHlwZW9mIHNlZ21lbnQgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgIGJ1aWxkID0gdjM7CiAgICAgICAgICAgIHYzID0gc2VnbWVudDsKICAgICAgICAgICAgc2VnbWVudCA9IHZvaWQgMDsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2MyA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgIHNlZ21lbnRzID0gdGhpcy5zZWdtZW50KHNlZ21lbnQsIHYzLCBidWlsZCk7CiAgICAgICAgICAgIGlmICghaXNBcnJheShzZWdtZW50cykpIHsKICAgICAgICAgICAgICBzZWdtZW50cyA9IHNlZ21lbnRzICE9PSB2b2lkIDAgPyBVUkkuZGVjb2RlKHNlZ21lbnRzKSA6IHZvaWQgMDsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBmb3IgKGkgPSAwLCBsID0gc2VnbWVudHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICAgICAgICBzZWdtZW50c1tpXSA9IFVSSS5kZWNvZGUoc2VnbWVudHNbaV0pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gc2VnbWVudHM7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIWlzQXJyYXkodjMpKSB7CiAgICAgICAgICAgIHYzID0gdHlwZW9mIHYzID09PSAic3RyaW5nIiB8fCB2MyBpbnN0YW5jZW9mIFN0cmluZyA/IFVSSS5lbmNvZGUodjMpIDogdjM7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBmb3IgKGkgPSAwLCBsID0gdjMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICAgICAgdjNbaV0gPSBVUkkuZW5jb2RlKHYzW2ldKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXMuc2VnbWVudChzZWdtZW50LCB2MywgYnVpbGQpOwogICAgICAgIH07CiAgICAgICAgdmFyIHEgPSBwLnF1ZXJ5OwogICAgICAgIHAucXVlcnkgPSBmdW5jdGlvbih2MywgYnVpbGQpIHsKICAgICAgICAgIGlmICh2MyA9PT0gdHJ1ZSkgewogICAgICAgICAgICByZXR1cm4gVVJJLnBhcnNlUXVlcnkodGhpcy5fcGFydHMucXVlcnksIHRoaXMuX3BhcnRzLmVzY2FwZVF1ZXJ5U3BhY2UpOwogICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdjMgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgICAgdmFyIGRhdGEgPSBVUkkucGFyc2VRdWVyeSh0aGlzLl9wYXJ0cy5xdWVyeSwgdGhpcy5fcGFydHMuZXNjYXBlUXVlcnlTcGFjZSk7CiAgICAgICAgICAgIHZhciByZXN1bHQgPSB2My5jYWxsKHRoaXMsIGRhdGEpOwogICAgICAgICAgICB0aGlzLl9wYXJ0cy5xdWVyeSA9IFVSSS5idWlsZFF1ZXJ5KHJlc3VsdCB8fCBkYXRhLCB0aGlzLl9wYXJ0cy5kdXBsaWNhdGVRdWVyeVBhcmFtZXRlcnMsIHRoaXMuX3BhcnRzLmVzY2FwZVF1ZXJ5U3BhY2UpOwogICAgICAgICAgICB0aGlzLmJ1aWxkKCFidWlsZCk7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfSBlbHNlIGlmICh2MyAhPT0gdm9pZCAwICYmIHR5cGVvZiB2MyAhPT0gInN0cmluZyIpIHsKICAgICAgICAgICAgdGhpcy5fcGFydHMucXVlcnkgPSBVUkkuYnVpbGRRdWVyeSh2MywgdGhpcy5fcGFydHMuZHVwbGljYXRlUXVlcnlQYXJhbWV0ZXJzLCB0aGlzLl9wYXJ0cy5lc2NhcGVRdWVyeVNwYWNlKTsKICAgICAgICAgICAgdGhpcy5idWlsZCghYnVpbGQpOwogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBxLmNhbGwodGhpcywgdjMsIGJ1aWxkKTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHAuc2V0UXVlcnkgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSwgYnVpbGQpIHsKICAgICAgICAgIHZhciBkYXRhID0gVVJJLnBhcnNlUXVlcnkodGhpcy5fcGFydHMucXVlcnksIHRoaXMuX3BhcnRzLmVzY2FwZVF1ZXJ5U3BhY2UpOwogICAgICAgICAgaWYgKHR5cGVvZiBuYW1lID09PSAic3RyaW5nIiB8fCBuYW1lIGluc3RhbmNlb2YgU3RyaW5nKSB7CiAgICAgICAgICAgIGRhdGFbbmFtZV0gPSB2YWx1ZSAhPT0gdm9pZCAwID8gdmFsdWUgOiBudWxsOwogICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbmFtZSA9PT0gIm9iamVjdCIpIHsKICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG5hbWUpIHsKICAgICAgICAgICAgICBpZiAoaGFzT3duLmNhbGwobmFtZSwga2V5KSkgewogICAgICAgICAgICAgICAgZGF0YVtrZXldID0gbmFtZVtrZXldOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigiVVJJLmFkZFF1ZXJ5KCkgYWNjZXB0cyBhbiBvYmplY3QsIHN0cmluZyBhcyB0aGUgbmFtZSBwYXJhbWV0ZXIiKTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuX3BhcnRzLnF1ZXJ5ID0gVVJJLmJ1aWxkUXVlcnkoZGF0YSwgdGhpcy5fcGFydHMuZHVwbGljYXRlUXVlcnlQYXJhbWV0ZXJzLCB0aGlzLl9wYXJ0cy5lc2NhcGVRdWVyeVNwYWNlKTsKICAgICAgICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gInN0cmluZyIpIHsKICAgICAgICAgICAgYnVpbGQgPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH07CiAgICAgICAgcC5hZGRRdWVyeSA9IGZ1bmN0aW9uKG5hbWUsIHZhbHVlLCBidWlsZCkgewogICAgICAgICAgdmFyIGRhdGEgPSBVUkkucGFyc2VRdWVyeSh0aGlzLl9wYXJ0cy5xdWVyeSwgdGhpcy5fcGFydHMuZXNjYXBlUXVlcnlTcGFjZSk7CiAgICAgICAgICBVUkkuYWRkUXVlcnkoZGF0YSwgbmFtZSwgdmFsdWUgPT09IHZvaWQgMCA/IG51bGwgOiB2YWx1ZSk7CiAgICAgICAgICB0aGlzLl9wYXJ0cy5xdWVyeSA9IFVSSS5idWlsZFF1ZXJ5KGRhdGEsIHRoaXMuX3BhcnRzLmR1cGxpY2F0ZVF1ZXJ5UGFyYW1ldGVycywgdGhpcy5fcGFydHMuZXNjYXBlUXVlcnlTcGFjZSk7CiAgICAgICAgICBpZiAodHlwZW9mIG5hbWUgIT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgIGJ1aWxkID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLmJ1aWxkKCFidWlsZCk7CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9OwogICAgICAgIHAucmVtb3ZlUXVlcnkgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSwgYnVpbGQpIHsKICAgICAgICAgIHZhciBkYXRhID0gVVJJLnBhcnNlUXVlcnkodGhpcy5fcGFydHMucXVlcnksIHRoaXMuX3BhcnRzLmVzY2FwZVF1ZXJ5U3BhY2UpOwogICAgICAgICAgVVJJLnJlbW92ZVF1ZXJ5KGRhdGEsIG5hbWUsIHZhbHVlKTsKICAgICAgICAgIHRoaXMuX3BhcnRzLnF1ZXJ5ID0gVVJJLmJ1aWxkUXVlcnkoZGF0YSwgdGhpcy5fcGFydHMuZHVwbGljYXRlUXVlcnlQYXJhbWV0ZXJzLCB0aGlzLl9wYXJ0cy5lc2NhcGVRdWVyeVNwYWNlKTsKICAgICAgICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gInN0cmluZyIpIHsKICAgICAgICAgICAgYnVpbGQgPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH07CiAgICAgICAgcC5oYXNRdWVyeSA9IGZ1bmN0aW9uKG5hbWUsIHZhbHVlLCB3aXRoaW5BcnJheSkgewogICAgICAgICAgdmFyIGRhdGEgPSBVUkkucGFyc2VRdWVyeSh0aGlzLl9wYXJ0cy5xdWVyeSwgdGhpcy5fcGFydHMuZXNjYXBlUXVlcnlTcGFjZSk7CiAgICAgICAgICByZXR1cm4gVVJJLmhhc1F1ZXJ5KGRhdGEsIG5hbWUsIHZhbHVlLCB3aXRoaW5BcnJheSk7CiAgICAgICAgfTsKICAgICAgICBwLnNldFNlYXJjaCA9IHAuc2V0UXVlcnk7CiAgICAgICAgcC5hZGRTZWFyY2ggPSBwLmFkZFF1ZXJ5OwogICAgICAgIHAucmVtb3ZlU2VhcmNoID0gcC5yZW1vdmVRdWVyeTsKICAgICAgICBwLmhhc1NlYXJjaCA9IHAuaGFzUXVlcnk7CiAgICAgICAgcC5ub3JtYWxpemUgPSBmdW5jdGlvbigpIHsKICAgICAgICAgIGlmICh0aGlzLl9wYXJ0cy51cm4pIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplUHJvdG9jb2woZmFsc2UpLm5vcm1hbGl6ZVBhdGgoZmFsc2UpLm5vcm1hbGl6ZVF1ZXJ5KGZhbHNlKS5ub3JtYWxpemVGcmFnbWVudChmYWxzZSkuYnVpbGQoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZVByb3RvY29sKGZhbHNlKS5ub3JtYWxpemVIb3N0bmFtZShmYWxzZSkubm9ybWFsaXplUG9ydChmYWxzZSkubm9ybWFsaXplUGF0aChmYWxzZSkubm9ybWFsaXplUXVlcnkoZmFsc2UpLm5vcm1hbGl6ZUZyYWdtZW50KGZhbHNlKS5idWlsZCgpOwogICAgICAgIH07CiAgICAgICAgcC5ub3JtYWxpemVQcm90b2NvbCA9IGZ1bmN0aW9uKGJ1aWxkKSB7CiAgICAgICAgICBpZiAodHlwZW9mIHRoaXMuX3BhcnRzLnByb3RvY29sID09PSAic3RyaW5nIikgewogICAgICAgICAgICB0aGlzLl9wYXJ0cy5wcm90b2NvbCA9IHRoaXMuX3BhcnRzLnByb3RvY29sLnRvTG93ZXJDYXNlKCk7CiAgICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH07CiAgICAgICAgcC5ub3JtYWxpemVIb3N0bmFtZSA9IGZ1bmN0aW9uKGJ1aWxkKSB7CiAgICAgICAgICBpZiAodGhpcy5fcGFydHMuaG9zdG5hbWUpIHsKICAgICAgICAgICAgaWYgKHRoaXMuaXMoIklETiIpICYmIHB1bnljb2RlKSB7CiAgICAgICAgICAgICAgdGhpcy5fcGFydHMuaG9zdG5hbWUgPSBwdW55Y29kZS50b0FTQ0lJKHRoaXMuX3BhcnRzLmhvc3RuYW1lKTsKICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLmlzKCJJUHY2IikgJiYgSVB2NikgewogICAgICAgICAgICAgIHRoaXMuX3BhcnRzLmhvc3RuYW1lID0gSVB2Ni5iZXN0KHRoaXMuX3BhcnRzLmhvc3RuYW1lKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLl9wYXJ0cy5ob3N0bmFtZSA9IHRoaXMuX3BhcnRzLmhvc3RuYW1lLnRvTG93ZXJDYXNlKCk7CiAgICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH07CiAgICAgICAgcC5ub3JtYWxpemVQb3J0ID0gZnVuY3Rpb24oYnVpbGQpIHsKICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fcGFydHMucHJvdG9jb2wgPT09ICJzdHJpbmciICYmIHRoaXMuX3BhcnRzLnBvcnQgPT09IFVSSS5kZWZhdWx0UG9ydHNbdGhpcy5fcGFydHMucHJvdG9jb2xdKSB7CiAgICAgICAgICAgIHRoaXMuX3BhcnRzLnBvcnQgPSBudWxsOwogICAgICAgICAgICB0aGlzLmJ1aWxkKCFidWlsZCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9OwogICAgICAgIHAubm9ybWFsaXplUGF0aCA9IGZ1bmN0aW9uKGJ1aWxkKSB7CiAgICAgICAgICB2YXIgX3BhdGggPSB0aGlzLl9wYXJ0cy5wYXRoOwogICAgICAgICAgaWYgKCFfcGF0aCkgewogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh0aGlzLl9wYXJ0cy51cm4pIHsKICAgICAgICAgICAgdGhpcy5fcGFydHMucGF0aCA9IFVSSS5yZWNvZGVVcm5QYXRoKHRoaXMuX3BhcnRzLnBhdGgpOwogICAgICAgICAgICB0aGlzLmJ1aWxkKCFidWlsZCk7CiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHRoaXMuX3BhcnRzLnBhdGggPT09ICIvIikgewogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIF9wYXRoID0gVVJJLnJlY29kZVBhdGgoX3BhdGgpOwogICAgICAgICAgdmFyIF93YXNfcmVsYXRpdmU7CiAgICAgICAgICB2YXIgX2xlYWRpbmdQYXJlbnRzID0gIiI7CiAgICAgICAgICB2YXIgX3BhcmVudCwgX3BvczsKICAgICAgICAgIGlmIChfcGF0aC5jaGFyQXQoMCkgIT09ICIvIikgewogICAgICAgICAgICBfd2FzX3JlbGF0aXZlID0gdHJ1ZTsKICAgICAgICAgICAgX3BhdGggPSAiLyIgKyBfcGF0aDsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChfcGF0aC5zbGljZSgtMykgPT09ICIvLi4iIHx8IF9wYXRoLnNsaWNlKC0yKSA9PT0gIi8uIikgewogICAgICAgICAgICBfcGF0aCArPSAiLyI7CiAgICAgICAgICB9CiAgICAgICAgICBfcGF0aCA9IF9wYXRoLnJlcGxhY2UoLyhcLyhcLlwvKSspfChcL1wuJCkvZywgIi8iKS5yZXBsYWNlKC9cL3syLH0vZywgIi8iKTsKICAgICAgICAgIGlmIChfd2FzX3JlbGF0aXZlKSB7CiAgICAgICAgICAgIF9sZWFkaW5nUGFyZW50cyA9IF9wYXRoLnN1YnN0cmluZygxKS5tYXRjaCgvXihcLlwuXC8pKy8pIHx8ICIiOwogICAgICAgICAgICBpZiAoX2xlYWRpbmdQYXJlbnRzKSB7CiAgICAgICAgICAgICAgX2xlYWRpbmdQYXJlbnRzID0gX2xlYWRpbmdQYXJlbnRzWzBdOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgICBfcGFyZW50ID0gX3BhdGguc2VhcmNoKC9cL1wuXC4oXC98JCkvKTsKICAgICAgICAgICAgaWYgKF9wYXJlbnQgPT09IC0xKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoX3BhcmVudCA9PT0gMCkgewogICAgICAgICAgICAgIF9wYXRoID0gX3BhdGguc3Vic3RyaW5nKDMpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIF9wb3MgPSBfcGF0aC5zdWJzdHJpbmcoMCwgX3BhcmVudCkubGFzdEluZGV4T2YoIi8iKTsKICAgICAgICAgICAgaWYgKF9wb3MgPT09IC0xKSB7CiAgICAgICAgICAgICAgX3BvcyA9IF9wYXJlbnQ7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgX3BhdGggPSBfcGF0aC5zdWJzdHJpbmcoMCwgX3BvcykgKyBfcGF0aC5zdWJzdHJpbmcoX3BhcmVudCArIDMpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKF93YXNfcmVsYXRpdmUgJiYgdGhpcy5pcygicmVsYXRpdmUiKSkgewogICAgICAgICAgICBfcGF0aCA9IF9sZWFkaW5nUGFyZW50cyArIF9wYXRoLnN1YnN0cmluZygxKTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuX3BhcnRzLnBhdGggPSBfcGF0aDsKICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH07CiAgICAgICAgcC5ub3JtYWxpemVQYXRobmFtZSA9IHAubm9ybWFsaXplUGF0aDsKICAgICAgICBwLm5vcm1hbGl6ZVF1ZXJ5ID0gZnVuY3Rpb24oYnVpbGQpIHsKICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5fcGFydHMucXVlcnkgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgIGlmICghdGhpcy5fcGFydHMucXVlcnkubGVuZ3RoKSB7CiAgICAgICAgICAgICAgdGhpcy5fcGFydHMucXVlcnkgPSBudWxsOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRoaXMucXVlcnkoVVJJLnBhcnNlUXVlcnkodGhpcy5fcGFydHMucXVlcnksIHRoaXMuX3BhcnRzLmVzY2FwZVF1ZXJ5U3BhY2UpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLmJ1aWxkKCFidWlsZCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9OwogICAgICAgIHAubm9ybWFsaXplRnJhZ21lbnQgPSBmdW5jdGlvbihidWlsZCkgewogICAgICAgICAgaWYgKCF0aGlzLl9wYXJ0cy5mcmFnbWVudCkgewogICAgICAgICAgICB0aGlzLl9wYXJ0cy5mcmFnbWVudCA9IG51bGw7CiAgICAgICAgICAgIHRoaXMuYnVpbGQoIWJ1aWxkKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH07CiAgICAgICAgcC5ub3JtYWxpemVTZWFyY2ggPSBwLm5vcm1hbGl6ZVF1ZXJ5OwogICAgICAgIHAubm9ybWFsaXplSGFzaCA9IHAubm9ybWFsaXplRnJhZ21lbnQ7CiAgICAgICAgcC5pc284ODU5ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICB2YXIgZSA9IFVSSS5lbmNvZGU7CiAgICAgICAgICB2YXIgZCA9IFVSSS5kZWNvZGU7CiAgICAgICAgICBVUkkuZW5jb2RlID0gZXNjYXBlOwogICAgICAgICAgVVJJLmRlY29kZSA9IGRlY29kZVVSSUNvbXBvbmVudDsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplKCk7CiAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBVUkkuZW5jb2RlID0gZTsKICAgICAgICAgICAgVVJJLmRlY29kZSA9IGQ7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9OwogICAgICAgIHAudW5pY29kZSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgdmFyIGUgPSBVUkkuZW5jb2RlOwogICAgICAgICAgdmFyIGQgPSBVUkkuZGVjb2RlOwogICAgICAgICAgVVJJLmVuY29kZSA9IHN0cmljdEVuY29kZVVSSUNvbXBvbmVudDsKICAgICAgICAgIFVSSS5kZWNvZGUgPSB1bmVzY2FwZTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHRoaXMubm9ybWFsaXplKCk7CiAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICBVUkkuZW5jb2RlID0gZTsKICAgICAgICAgICAgVVJJLmRlY29kZSA9IGQ7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICB9OwogICAgICAgIHAucmVhZGFibGUgPSBmdW5jdGlvbigpIHsKICAgICAgICAgIHZhciB1cmkgPSB0aGlzLmNsb25lKCk7CiAgICAgICAgICB1cmkudXNlcm5hbWUoIiIpLnBhc3N3b3JkKCIiKS5ub3JtYWxpemUoKTsKICAgICAgICAgIHZhciB0ID0gIiI7CiAgICAgICAgICBpZiAodXJpLl9wYXJ0cy5wcm90b2NvbCkgewogICAgICAgICAgICB0ICs9IHVyaS5fcGFydHMucHJvdG9jb2wgKyAiOi8vIjsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh1cmkuX3BhcnRzLmhvc3RuYW1lKSB7CiAgICAgICAgICAgIGlmICh1cmkuaXMoInB1bnljb2RlIikgJiYgcHVueWNvZGUpIHsKICAgICAgICAgICAgICB0ICs9IHB1bnljb2RlLnRvVW5pY29kZSh1cmkuX3BhcnRzLmhvc3RuYW1lKTsKICAgICAgICAgICAgICBpZiAodXJpLl9wYXJ0cy5wb3J0KSB7CiAgICAgICAgICAgICAgICB0ICs9ICI6IiArIHVyaS5fcGFydHMucG9ydDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdCArPSB1cmkuaG9zdCgpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodXJpLl9wYXJ0cy5ob3N0bmFtZSAmJiB1cmkuX3BhcnRzLnBhdGggJiYgdXJpLl9wYXJ0cy5wYXRoLmNoYXJBdCgwKSAhPT0gIi8iKSB7CiAgICAgICAgICAgIHQgKz0gIi8iOwogICAgICAgICAgfQogICAgICAgICAgdCArPSB1cmkucGF0aCh0cnVlKTsKICAgICAgICAgIGlmICh1cmkuX3BhcnRzLnF1ZXJ5KSB7CiAgICAgICAgICAgIHZhciBxMyA9ICIiOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgcXAgPSB1cmkuX3BhcnRzLnF1ZXJ5LnNwbGl0KCImIiksIGwgPSBxcC5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgICAgICB2YXIga3YgPSAocXBbaV0gfHwgIiIpLnNwbGl0KCI9Iik7CiAgICAgICAgICAgICAgcTMgKz0gIiYiICsgVVJJLmRlY29kZVF1ZXJ5KGt2WzBdLCB0aGlzLl9wYXJ0cy5lc2NhcGVRdWVyeVNwYWNlKS5yZXBsYWNlKC8mL2csICIlMjYiKTsKICAgICAgICAgICAgICBpZiAoa3ZbMV0gIT09IHZvaWQgMCkgewogICAgICAgICAgICAgICAgcTMgKz0gIj0iICsgVVJJLmRlY29kZVF1ZXJ5KGt2WzFdLCB0aGlzLl9wYXJ0cy5lc2NhcGVRdWVyeVNwYWNlKS5yZXBsYWNlKC8mL2csICIlMjYiKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdCArPSAiPyIgKyBxMy5zdWJzdHJpbmcoMSk7CiAgICAgICAgICB9CiAgICAgICAgICB0ICs9IFVSSS5kZWNvZGVRdWVyeSh1cmkuaGFzaCgpLCB0cnVlKTsKICAgICAgICAgIHJldHVybiB0OwogICAgICAgIH07CiAgICAgICAgcC5hYnNvbHV0ZVRvID0gZnVuY3Rpb24oYmFzZSkgewogICAgICAgICAgdmFyIHJlc29sdmVkID0gdGhpcy5jbG9uZSgpOwogICAgICAgICAgdmFyIHByb3BlcnRpZXMgPSBbInByb3RvY29sIiwgInVzZXJuYW1lIiwgInBhc3N3b3JkIiwgImhvc3RuYW1lIiwgInBvcnQiXTsKICAgICAgICAgIHZhciBiYXNlZGlyLCBpLCBwMjsKICAgICAgICAgIGlmICh0aGlzLl9wYXJ0cy51cm4pIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJVUk5zIGRvIG5vdCBoYXZlIGFueSBnZW5lcmFsbHkgZGVmaW5lZCBoaWVyYXJjaGljYWwgY29tcG9uZW50cyIpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCEoYmFzZSBpbnN0YW5jZW9mIFVSSSkpIHsKICAgICAgICAgICAgYmFzZSA9IG5ldyBVUkkoYmFzZSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAocmVzb2x2ZWQuX3BhcnRzLnByb3RvY29sKSB7CiAgICAgICAgICAgIHJldHVybiByZXNvbHZlZDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJlc29sdmVkLl9wYXJ0cy5wcm90b2NvbCA9IGJhc2UuX3BhcnRzLnByb3RvY29sOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHRoaXMuX3BhcnRzLmhvc3RuYW1lKSB7CiAgICAgICAgICAgIHJldHVybiByZXNvbHZlZDsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAoaSA9IDA7IHAyID0gcHJvcGVydGllc1tpXTsgaSsrKSB7CiAgICAgICAgICAgIHJlc29sdmVkLl9wYXJ0c1twMl0gPSBiYXNlLl9wYXJ0c1twMl07CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIXJlc29sdmVkLl9wYXJ0cy5wYXRoKSB7CiAgICAgICAgICAgIHJlc29sdmVkLl9wYXJ0cy5wYXRoID0gYmFzZS5fcGFydHMucGF0aDsKICAgICAgICAgICAgaWYgKCFyZXNvbHZlZC5fcGFydHMucXVlcnkpIHsKICAgICAgICAgICAgICByZXNvbHZlZC5fcGFydHMucXVlcnkgPSBiYXNlLl9wYXJ0cy5xdWVyeTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKHJlc29sdmVkLl9wYXJ0cy5wYXRoLnN1YnN0cmluZygtMikgPT09ICIuLiIpIHsKICAgICAgICAgICAgICByZXNvbHZlZC5fcGFydHMucGF0aCArPSAiLyI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJlc29sdmVkLnBhdGgoKS5jaGFyQXQoMCkgIT09ICIvIikgewogICAgICAgICAgICAgIGJhc2VkaXIgPSBiYXNlLmRpcmVjdG9yeSgpOwogICAgICAgICAgICAgIGJhc2VkaXIgPSBiYXNlZGlyID8gYmFzZWRpciA6IGJhc2UucGF0aCgpLmluZGV4T2YoIi8iKSA9PT0gMCA/ICIvIiA6ICIiOwogICAgICAgICAgICAgIHJlc29sdmVkLl9wYXJ0cy5wYXRoID0gKGJhc2VkaXIgPyBiYXNlZGlyICsgIi8iIDogIiIpICsgcmVzb2x2ZWQuX3BhcnRzLnBhdGg7CiAgICAgICAgICAgICAgcmVzb2x2ZWQubm9ybWFsaXplUGF0aCgpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXNvbHZlZC5idWlsZCgpOwogICAgICAgICAgcmV0dXJuIHJlc29sdmVkOwogICAgICAgIH07CiAgICAgICAgcC5yZWxhdGl2ZVRvID0gZnVuY3Rpb24oYmFzZSkgewogICAgICAgICAgdmFyIHJlbGF0aXZlID0gdGhpcy5jbG9uZSgpLm5vcm1hbGl6ZSgpOwogICAgICAgICAgdmFyIHJlbGF0aXZlUGFydHMsIGJhc2VQYXJ0cywgY29tbW9uLCByZWxhdGl2ZVBhdGgsIGJhc2VQYXRoOwogICAgICAgICAgaWYgKHJlbGF0aXZlLl9wYXJ0cy51cm4pIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJVUk5zIGRvIG5vdCBoYXZlIGFueSBnZW5lcmFsbHkgZGVmaW5lZCBoaWVyYXJjaGljYWwgY29tcG9uZW50cyIpOwogICAgICAgICAgfQogICAgICAgICAgYmFzZSA9IG5ldyBVUkkoYmFzZSkubm9ybWFsaXplKCk7CiAgICAgICAgICByZWxhdGl2ZVBhcnRzID0gcmVsYXRpdmUuX3BhcnRzOwogICAgICAgICAgYmFzZVBhcnRzID0gYmFzZS5fcGFydHM7CiAgICAgICAgICByZWxhdGl2ZVBhdGggPSByZWxhdGl2ZS5wYXRoKCk7CiAgICAgICAgICBiYXNlUGF0aCA9IGJhc2UucGF0aCgpOwogICAgICAgICAgaWYgKHJlbGF0aXZlUGF0aC5jaGFyQXQoMCkgIT09ICIvIikgewogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlVSSSBpcyBhbHJlYWR5IHJlbGF0aXZlIik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoYmFzZVBhdGguY2hhckF0KDApICE9PSAiLyIpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDYW5ub3QgY2FsY3VsYXRlIGEgVVJJIHJlbGF0aXZlIHRvIGFub3RoZXIgcmVsYXRpdmUgVVJJIik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAocmVsYXRpdmVQYXJ0cy5wcm90b2NvbCA9PT0gYmFzZVBhcnRzLnByb3RvY29sKSB7CiAgICAgICAgICAgIHJlbGF0aXZlUGFydHMucHJvdG9jb2wgPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHJlbGF0aXZlUGFydHMudXNlcm5hbWUgIT09IGJhc2VQYXJ0cy51c2VybmFtZSB8fCByZWxhdGl2ZVBhcnRzLnBhc3N3b3JkICE9PSBiYXNlUGFydHMucGFzc3dvcmQpIHsKICAgICAgICAgICAgcmV0dXJuIHJlbGF0aXZlLmJ1aWxkKCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAocmVsYXRpdmVQYXJ0cy5wcm90b2NvbCAhPT0gbnVsbCB8fCByZWxhdGl2ZVBhcnRzLnVzZXJuYW1lICE9PSBudWxsIHx8IHJlbGF0aXZlUGFydHMucGFzc3dvcmQgIT09IG51bGwpIHsKICAgICAgICAgICAgcmV0dXJuIHJlbGF0aXZlLmJ1aWxkKCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAocmVsYXRpdmVQYXJ0cy5ob3N0bmFtZSA9PT0gYmFzZVBhcnRzLmhvc3RuYW1lICYmIHJlbGF0aXZlUGFydHMucG9ydCA9PT0gYmFzZVBhcnRzLnBvcnQpIHsKICAgICAgICAgICAgcmVsYXRpdmVQYXJ0cy5ob3N0bmFtZSA9IG51bGw7CiAgICAgICAgICAgIHJlbGF0aXZlUGFydHMucG9ydCA9IG51bGw7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICByZXR1cm4gcmVsYXRpdmUuYnVpbGQoKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChyZWxhdGl2ZVBhdGggPT09IGJhc2VQYXRoKSB7CiAgICAgICAgICAgIHJlbGF0aXZlUGFydHMucGF0aCA9ICIiOwogICAgICAgICAgICByZXR1cm4gcmVsYXRpdmUuYnVpbGQoKTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbW1vbiA9IFVSSS5jb21tb25QYXRoKHJlbGF0aXZlUGF0aCwgYmFzZVBhdGgpOwogICAgICAgICAgaWYgKCFjb21tb24pIHsKICAgICAgICAgICAgcmV0dXJuIHJlbGF0aXZlLmJ1aWxkKCk7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgcGFyZW50cyA9IGJhc2VQYXJ0cy5wYXRoLnN1YnN0cmluZyhjb21tb24ubGVuZ3RoKS5yZXBsYWNlKC9bXlwvXSokLywgIiIpLnJlcGxhY2UoLy4qP1wvL2csICIuLi8iKTsKICAgICAgICAgIHJlbGF0aXZlUGFydHMucGF0aCA9IHBhcmVudHMgKyByZWxhdGl2ZVBhcnRzLnBhdGguc3Vic3RyaW5nKGNvbW1vbi5sZW5ndGgpIHx8ICIuLyI7CiAgICAgICAgICByZXR1cm4gcmVsYXRpdmUuYnVpbGQoKTsKICAgICAgICB9OwogICAgICAgIHAuZXF1YWxzID0gZnVuY3Rpb24odXJpKSB7CiAgICAgICAgICB2YXIgb25lID0gdGhpcy5jbG9uZSgpOwogICAgICAgICAgdmFyIHR3byA9IG5ldyBVUkkodXJpKTsKICAgICAgICAgIHZhciBvbmVfbWFwID0ge307CiAgICAgICAgICB2YXIgdHdvX21hcCA9IHt9OwogICAgICAgICAgdmFyIGNoZWNrZWQgPSB7fTsKICAgICAgICAgIHZhciBvbmVfcXVlcnksIHR3b19xdWVyeSwga2V5OwogICAgICAgICAgb25lLm5vcm1hbGl6ZSgpOwogICAgICAgICAgdHdvLm5vcm1hbGl6ZSgpOwogICAgICAgICAgaWYgKG9uZS50b1N0cmluZygpID09PSB0d28udG9TdHJpbmcoKSkgewogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICAgIG9uZV9xdWVyeSA9IG9uZS5xdWVyeSgpOwogICAgICAgICAgdHdvX3F1ZXJ5ID0gdHdvLnF1ZXJ5KCk7CiAgICAgICAgICBvbmUucXVlcnkoIiIpOwogICAgICAgICAgdHdvLnF1ZXJ5KCIiKTsKICAgICAgICAgIGlmIChvbmUudG9TdHJpbmcoKSAhPT0gdHdvLnRvU3RyaW5nKCkpIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG9uZV9xdWVyeS5sZW5ndGggIT09IHR3b19xdWVyeS5sZW5ndGgpIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgICAgb25lX21hcCA9IFVSSS5wYXJzZVF1ZXJ5KG9uZV9xdWVyeSwgdGhpcy5fcGFydHMuZXNjYXBlUXVlcnlTcGFjZSk7CiAgICAgICAgICB0d29fbWFwID0gVVJJLnBhcnNlUXVlcnkodHdvX3F1ZXJ5LCB0aGlzLl9wYXJ0cy5lc2NhcGVRdWVyeVNwYWNlKTsKICAgICAgICAgIGZvciAoa2V5IGluIG9uZV9tYXApIHsKICAgICAgICAgICAgaWYgKGhhc093bi5jYWxsKG9uZV9tYXAsIGtleSkpIHsKICAgICAgICAgICAgICBpZiAoIWlzQXJyYXkob25lX21hcFtrZXldKSkgewogICAgICAgICAgICAgICAgaWYgKG9uZV9tYXBba2V5XSAhPT0gdHdvX21hcFtrZXldKSB7CiAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFhcnJheXNFcXVhbChvbmVfbWFwW2tleV0sIHR3b19tYXBba2V5XSkpIHsKICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY2hlY2tlZFtrZXldID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZm9yIChrZXkgaW4gdHdvX21hcCkgewogICAgICAgICAgICBpZiAoaGFzT3duLmNhbGwodHdvX21hcCwga2V5KSkgewogICAgICAgICAgICAgIGlmICghY2hlY2tlZFtrZXldKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9OwogICAgICAgIHAucHJldmVudEludmFsaWRIb3N0bmFtZSA9IGZ1bmN0aW9uKHYzKSB7CiAgICAgICAgICB0aGlzLl9wYXJ0cy5wcmV2ZW50SW52YWxpZEhvc3RuYW1lID0gISF2MzsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH07CiAgICAgICAgcC5kdXBsaWNhdGVRdWVyeVBhcmFtZXRlcnMgPSBmdW5jdGlvbih2MykgewogICAgICAgICAgdGhpcy5fcGFydHMuZHVwbGljYXRlUXVlcnlQYXJhbWV0ZXJzID0gISF2MzsKICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgIH07CiAgICAgICAgcC5lc2NhcGVRdWVyeVNwYWNlID0gZnVuY3Rpb24odjMpIHsKICAgICAgICAgIHRoaXMuX3BhcnRzLmVzY2FwZVF1ZXJ5U3BhY2UgPSAhIXYzOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfTsKICAgICAgICByZXR1cm4gVVJJOwogICAgICB9KTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2FwcGVuZEZvcndhcmRTbGFzaC5qcwogIGZ1bmN0aW9uIGFwcGVuZEZvcndhcmRTbGFzaCh1cmwpIHsKICAgIGlmICh1cmwubGVuZ3RoID09PSAwIHx8IHVybFt1cmwubGVuZ3RoIC0gMV0gIT09ICIvIikgewogICAgICB1cmwgPSBgJHt1cmx9L2A7CiAgICB9CiAgICByZXR1cm4gdXJsOwogIH0KICB2YXIgYXBwZW5kRm9yd2FyZFNsYXNoX2RlZmF1bHQ7CiAgdmFyIGluaXRfYXBwZW5kRm9yd2FyZFNsYXNoID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9hcHBlbmRGb3J3YXJkU2xhc2guanMiKCkgewogICAgICBhcHBlbmRGb3J3YXJkU2xhc2hfZGVmYXVsdCA9IGFwcGVuZEZvcndhcmRTbGFzaDsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2Nsb25lLmpzCiAgZnVuY3Rpb24gY2xvbmUob2JqZWN0LCBkZWVwKSB7CiAgICBpZiAob2JqZWN0ID09PSBudWxsIHx8IHR5cGVvZiBvYmplY3QgIT09ICJvYmplY3QiKSB7CiAgICAgIHJldHVybiBvYmplY3Q7CiAgICB9CiAgICBkZWVwID0gZGVlcCA/PyBmYWxzZTsKICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBvYmplY3QuY29uc3RydWN0b3IoKTsKICAgIGZvciAoY29uc3QgcHJvcGVydHlOYW1lIGluIG9iamVjdCkgewogICAgICBpZiAob2JqZWN0Lmhhc093blByb3BlcnR5KHByb3BlcnR5TmFtZSkpIHsKICAgICAgICBsZXQgdmFsdWUgPSBvYmplY3RbcHJvcGVydHlOYW1lXTsKICAgICAgICBpZiAoZGVlcCkgewogICAgICAgICAgdmFsdWUgPSBjbG9uZSh2YWx1ZSwgZGVlcCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFtwcm9wZXJ0eU5hbWVdID0gdmFsdWU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIHZhciBjbG9uZV9kZWZhdWx0OwogIHZhciBpbml0X2Nsb25lID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9jbG9uZS5qcyIoKSB7CiAgICAgIGNsb25lX2RlZmF1bHQgPSBjbG9uZTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2NvbWJpbmUuanMKICBmdW5jdGlvbiBjb21iaW5lKG9iamVjdDEsIG9iamVjdDIsIGRlZXApIHsKICAgIGRlZXAgPSBkZWVwID8/IGZhbHNlOwogICAgY29uc3QgcmVzdWx0ID0ge307CiAgICBjb25zdCBvYmplY3QxRGVmaW5lZCA9IGRlZmluZWRfZGVmYXVsdChvYmplY3QxKTsKICAgIGNvbnN0IG9iamVjdDJEZWZpbmVkID0gZGVmaW5lZF9kZWZhdWx0KG9iamVjdDIpOwogICAgbGV0IHByb3BlcnR5OwogICAgbGV0IG9iamVjdDFWYWx1ZTsKICAgIGxldCBvYmplY3QyVmFsdWU7CiAgICBpZiAob2JqZWN0MURlZmluZWQpIHsKICAgICAgZm9yIChwcm9wZXJ0eSBpbiBvYmplY3QxKSB7CiAgICAgICAgaWYgKG9iamVjdDEuaGFzT3duUHJvcGVydHkocHJvcGVydHkpKSB7CiAgICAgICAgICBvYmplY3QxVmFsdWUgPSBvYmplY3QxW3Byb3BlcnR5XTsKICAgICAgICAgIGlmIChvYmplY3QyRGVmaW5lZCAmJiBkZWVwICYmIHR5cGVvZiBvYmplY3QxVmFsdWUgPT09ICJvYmplY3QiICYmIG9iamVjdDIuaGFzT3duUHJvcGVydHkocHJvcGVydHkpKSB7CiAgICAgICAgICAgIG9iamVjdDJWYWx1ZSA9IG9iamVjdDJbcHJvcGVydHldOwogICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdDJWYWx1ZSA9PT0gIm9iamVjdCIpIHsKICAgICAgICAgICAgICByZXN1bHRbcHJvcGVydHldID0gY29tYmluZShvYmplY3QxVmFsdWUsIG9iamVjdDJWYWx1ZSwgZGVlcCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmVzdWx0W3Byb3BlcnR5XSA9IG9iamVjdDFWYWx1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmVzdWx0W3Byb3BlcnR5XSA9IG9iamVjdDFWYWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChvYmplY3QyRGVmaW5lZCkgewogICAgICBmb3IgKHByb3BlcnR5IGluIG9iamVjdDIpIHsKICAgICAgICBpZiAob2JqZWN0Mi5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkgJiYgIXJlc3VsdC5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkpIHsKICAgICAgICAgIG9iamVjdDJWYWx1ZSA9IG9iamVjdDJbcHJvcGVydHldOwogICAgICAgICAgcmVzdWx0W3Byb3BlcnR5XSA9IG9iamVjdDJWYWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIHZhciBjb21iaW5lX2RlZmF1bHQ7CiAgdmFyIGluaXRfY29tYmluZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvY29tYmluZS5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBjb21iaW5lX2RlZmF1bHQgPSBjb21iaW5lOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvZGVmZXIuanMKICBmdW5jdGlvbiBkZWZlcigpIHsKICAgIGxldCByZXNvbHZlOwogICAgbGV0IHJlamVjdDsKICAgIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXMsIHJlaikgewogICAgICByZXNvbHZlID0gcmVzOwogICAgICByZWplY3QgPSByZWo7CiAgICB9KTsKICAgIHJldHVybiB7CiAgICAgIHJlc29sdmUsCiAgICAgIHJlamVjdCwKICAgICAgcHJvbWlzZQogICAgfTsKICB9CiAgdmFyIGRlZmVyX2RlZmF1bHQ7CiAgdmFyIGluaXRfZGVmZXIgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2RlZmVyLmpzIigpIHsKICAgICAgZGVmZXJfZGVmYXVsdCA9IGRlZmVyOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvZ2V0QWJzb2x1dGVVcmkuanMKICBmdW5jdGlvbiBnZXRBYnNvbHV0ZVVyaShyZWxhdGl2ZSwgYmFzZSkgewogICAgbGV0IGRvY3VtZW50T2JqZWN0OwogICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gInVuZGVmaW5lZCIpIHsKICAgICAgZG9jdW1lbnRPYmplY3QgPSBkb2N1bWVudDsKICAgIH0KICAgIHJldHVybiBnZXRBYnNvbHV0ZVVyaS5faW1wbGVtZW50YXRpb24ocmVsYXRpdmUsIGJhc2UsIGRvY3VtZW50T2JqZWN0KTsKICB9CiAgdmFyIGltcG9ydF91cmlqcywgZ2V0QWJzb2x1dGVVcmlfZGVmYXVsdDsKICB2YXIgaW5pdF9nZXRBYnNvbHV0ZVVyaSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvZ2V0QWJzb2x1dGVVcmkuanMiKCkgewogICAgICBpbXBvcnRfdXJpanMgPSBfX3RvRVNNKHJlcXVpcmVfVVJJKCksIDEpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBnZXRBYnNvbHV0ZVVyaS5faW1wbGVtZW50YXRpb24gPSBmdW5jdGlvbihyZWxhdGl2ZSwgYmFzZSwgZG9jdW1lbnRPYmplY3QpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZWxhdGl2ZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJyZWxhdGl2ZSB1cmkgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGJhc2UpKSB7CiAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50T2JqZWN0ID09PSAidW5kZWZpbmVkIikgewogICAgICAgICAgICByZXR1cm4gcmVsYXRpdmU7CiAgICAgICAgICB9CiAgICAgICAgICBiYXNlID0gZG9jdW1lbnRPYmplY3QuYmFzZVVSSSA/PyBkb2N1bWVudE9iamVjdC5sb2NhdGlvbi5ocmVmOwogICAgICAgIH0KICAgICAgICBjb25zdCByZWxhdGl2ZVVyaSA9IG5ldyBpbXBvcnRfdXJpanMuZGVmYXVsdChyZWxhdGl2ZSk7CiAgICAgICAgaWYgKHJlbGF0aXZlVXJpLnNjaGVtZSgpICE9PSAiIikgewogICAgICAgICAgcmV0dXJuIHJlbGF0aXZlVXJpLnRvU3RyaW5nKCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZWxhdGl2ZVVyaS5hYnNvbHV0ZVRvKGJhc2UpLnRvU3RyaW5nKCk7CiAgICAgIH07CiAgICAgIGdldEFic29sdXRlVXJpX2RlZmF1bHQgPSBnZXRBYnNvbHV0ZVVyaTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2dldEJhc2VVcmkuanMKICBmdW5jdGlvbiBnZXRCYXNlVXJpKHVyaSwgaW5jbHVkZVF1ZXJ5KSB7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh1cmkpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ1cmkgaXMgcmVxdWlyZWQuIik7CiAgICB9CiAgICBsZXQgYmFzZVBhdGggPSAiIjsKICAgIGNvbnN0IGkgPSB1cmkubGFzdEluZGV4T2YoIi8iKTsKICAgIGlmIChpICE9PSAtMSkgewogICAgICBiYXNlUGF0aCA9IHVyaS5zdWJzdHJpbmcoMCwgaSArIDEpOwogICAgfQogICAgaWYgKCFpbmNsdWRlUXVlcnkpIHsKICAgICAgcmV0dXJuIGJhc2VQYXRoOwogICAgfQogICAgdXJpID0gbmV3IGltcG9ydF91cmlqczIuZGVmYXVsdCh1cmkpOwogICAgaWYgKHVyaS5xdWVyeSgpLmxlbmd0aCAhPT0gMCkgewogICAgICBiYXNlUGF0aCArPSBgPyR7dXJpLnF1ZXJ5KCl9YDsKICAgIH0KICAgIGlmICh1cmkuZnJhZ21lbnQoKS5sZW5ndGggIT09IDApIHsKICAgICAgYmFzZVBhdGggKz0gYCMke3VyaS5mcmFnbWVudCgpfWA7CiAgICB9CiAgICByZXR1cm4gYmFzZVBhdGg7CiAgfQogIHZhciBpbXBvcnRfdXJpanMyLCBnZXRCYXNlVXJpX2RlZmF1bHQ7CiAgdmFyIGluaXRfZ2V0QmFzZVVyaSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvZ2V0QmFzZVVyaS5qcyIoKSB7CiAgICAgIGltcG9ydF91cmlqczIgPSBfX3RvRVNNKHJlcXVpcmVfVVJJKCksIDEpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBnZXRCYXNlVXJpX2RlZmF1bHQgPSBnZXRCYXNlVXJpOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvZ2V0RXh0ZW5zaW9uRnJvbVVyaS5qcwogIGZ1bmN0aW9uIGdldEV4dGVuc2lvbkZyb21VcmkodXJpKSB7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh1cmkpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ1cmkgaXMgcmVxdWlyZWQuIik7CiAgICB9CiAgICBjb25zdCB1cmlPYmplY3QgPSBuZXcgaW1wb3J0X3VyaWpzMy5kZWZhdWx0KHVyaSk7CiAgICB1cmlPYmplY3Qubm9ybWFsaXplKCk7CiAgICBsZXQgcGF0aCA9IHVyaU9iamVjdC5wYXRoKCk7CiAgICBsZXQgaW5kZXggPSBwYXRoLmxhc3RJbmRleE9mKCIvIik7CiAgICBpZiAoaW5kZXggIT09IC0xKSB7CiAgICAgIHBhdGggPSBwYXRoLnN1YnN0cihpbmRleCArIDEpOwogICAgfQogICAgaW5kZXggPSBwYXRoLmxhc3RJbmRleE9mKCIuIik7CiAgICBpZiAoaW5kZXggPT09IC0xKSB7CiAgICAgIHBhdGggPSAiIjsKICAgIH0gZWxzZSB7CiAgICAgIHBhdGggPSBwYXRoLnN1YnN0cihpbmRleCArIDEpOwogICAgfQogICAgcmV0dXJuIHBhdGg7CiAgfQogIHZhciBpbXBvcnRfdXJpanMzLCBnZXRFeHRlbnNpb25Gcm9tVXJpX2RlZmF1bHQ7CiAgdmFyIGluaXRfZ2V0RXh0ZW5zaW9uRnJvbVVyaSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvZ2V0RXh0ZW5zaW9uRnJvbVVyaS5qcyIoKSB7CiAgICAgIGltcG9ydF91cmlqczMgPSBfX3RvRVNNKHJlcXVpcmVfVVJJKCksIDEpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBnZXRFeHRlbnNpb25Gcm9tVXJpX2RlZmF1bHQgPSBnZXRFeHRlbnNpb25Gcm9tVXJpOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvZ2V0SW1hZ2VQaXhlbHMuanMKICBmdW5jdGlvbiBnZXRJbWFnZVBpeGVscyhpbWFnZSwgd2lkdGgsIGhlaWdodCkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQod2lkdGgpKSB7CiAgICAgIHdpZHRoID0gaW1hZ2Uud2lkdGg7CiAgICB9CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChoZWlnaHQpKSB7CiAgICAgIGhlaWdodCA9IGltYWdlLmhlaWdodDsKICAgIH0KICAgIGxldCBjb250ZXh0MkRzQnlIZWlnaHQgPSBjb250ZXh0MkRzQnlXaWR0aEFuZEhlaWdodFt3aWR0aF07CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChjb250ZXh0MkRzQnlIZWlnaHQpKSB7CiAgICAgIGNvbnRleHQyRHNCeUhlaWdodCA9IHt9OwogICAgICBjb250ZXh0MkRzQnlXaWR0aEFuZEhlaWdodFt3aWR0aF0gPSBjb250ZXh0MkRzQnlIZWlnaHQ7CiAgICB9CiAgICBsZXQgY29udGV4dDJkID0gY29udGV4dDJEc0J5SGVpZ2h0W2hlaWdodF07CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChjb250ZXh0MmQpKSB7CiAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImNhbnZhcyIpOwogICAgICBjYW52YXMud2lkdGggPSB3aWR0aDsKICAgICAgY2FudmFzLmhlaWdodCA9IGhlaWdodDsKICAgICAgY29udGV4dDJkID0gY2FudmFzLmdldENvbnRleHQoIjJkIiwgeyB3aWxsUmVhZEZyZXF1ZW50bHk6IHRydWUgfSk7CiAgICAgIGNvbnRleHQyZC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb24gPSAiY29weSI7CiAgICAgIGNvbnRleHQyRHNCeUhlaWdodFtoZWlnaHRdID0gY29udGV4dDJkOwogICAgfQogICAgY29udGV4dDJkLmRyYXdJbWFnZShpbWFnZSwgMCwgMCwgd2lkdGgsIGhlaWdodCk7CiAgICByZXR1cm4gY29udGV4dDJkLmdldEltYWdlRGF0YSgwLCAwLCB3aWR0aCwgaGVpZ2h0KS5kYXRhOwogIH0KICB2YXIgY29udGV4dDJEc0J5V2lkdGhBbmRIZWlnaHQsIGdldEltYWdlUGl4ZWxzX2RlZmF1bHQ7CiAgdmFyIGluaXRfZ2V0SW1hZ2VQaXhlbHMgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2dldEltYWdlUGl4ZWxzLmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGNvbnRleHQyRHNCeVdpZHRoQW5kSGVpZ2h0ID0ge307CiAgICAgIGdldEltYWdlUGl4ZWxzX2RlZmF1bHQgPSBnZXRJbWFnZVBpeGVsczsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2lzQmxvYlVyaS5qcwogIGZ1bmN0aW9uIGlzQmxvYlVyaSh1cmkpIHsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLnN0cmluZygidXJpIiwgdXJpKTsKICAgIHJldHVybiBibG9iVXJpUmVnZXgudGVzdCh1cmkpOwogIH0KICB2YXIgYmxvYlVyaVJlZ2V4LCBpc0Jsb2JVcmlfZGVmYXVsdDsKICB2YXIgaW5pdF9pc0Jsb2JVcmkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2lzQmxvYlVyaS5qcyIoKSB7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgYmxvYlVyaVJlZ2V4ID0gL15ibG9iOi9pOwogICAgICBpc0Jsb2JVcmlfZGVmYXVsdCA9IGlzQmxvYlVyaTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2lzQ3Jvc3NPcmlnaW5VcmwuanMKICBmdW5jdGlvbiBpc0Nyb3NzT3JpZ2luVXJsKHVybCkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYSkpIHsKICAgICAgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImEiKTsKICAgIH0KICAgIGEuaHJlZiA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmOwogICAgY29uc3QgaG9zdCA9IGEuaG9zdDsKICAgIGNvbnN0IHByb3RvY29sID0gYS5wcm90b2NvbDsKICAgIGEuaHJlZiA9IHVybDsKICAgIGEuaHJlZiA9IGEuaHJlZjsKICAgIHJldHVybiBwcm90b2NvbCAhPT0gYS5wcm90b2NvbCB8fCBob3N0ICE9PSBhLmhvc3Q7CiAgfQogIHZhciBhLCBpc0Nyb3NzT3JpZ2luVXJsX2RlZmF1bHQ7CiAgdmFyIGluaXRfaXNDcm9zc09yaWdpblVybCA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvaXNDcm9zc09yaWdpblVybC5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpc0Nyb3NzT3JpZ2luVXJsX2RlZmF1bHQgPSBpc0Nyb3NzT3JpZ2luVXJsOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvaXNEYXRhVXJpLmpzCiAgZnVuY3Rpb24gaXNEYXRhVXJpKHVyaSkgewogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yuc3RyaW5nKCJ1cmkiLCB1cmkpOwogICAgcmV0dXJuIGRhdGFVcmlSZWdleC50ZXN0KHVyaSk7CiAgfQogIHZhciBkYXRhVXJpUmVnZXgsIGlzRGF0YVVyaV9kZWZhdWx0OwogIHZhciBpbml0X2lzRGF0YVVyaSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvaXNEYXRhVXJpLmpzIigpIHsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBkYXRhVXJpUmVnZXggPSAvXmRhdGE6L2k7CiAgICAgIGlzRGF0YVVyaV9kZWZhdWx0ID0gaXNEYXRhVXJpOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvbG9hZEFuZEV4ZWN1dGVTY3JpcHQuanMKICBmdW5jdGlvbiBsb2FkQW5kRXhlY3V0ZVNjcmlwdCh1cmwpIHsKICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpOwogICAgc2NyaXB0LmFzeW5jID0gdHJ1ZTsKICAgIHNjcmlwdC5zcmMgPSB1cmw7CiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gewogICAgICBpZiAod2luZG93LmNyb3NzT3JpZ2luSXNvbGF0ZWQpIHsKICAgICAgICBzY3JpcHQuc2V0QXR0cmlidXRlKCJjcm9zc29yaWdpbiIsICJhbm9ueW1vdXMiKTsKICAgICAgfQogICAgICBjb25zdCBoZWFkID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImhlYWQiKVswXTsKICAgICAgc2NyaXB0Lm9ubG9hZCA9IGZ1bmN0aW9uKCkgewogICAgICAgIHNjcmlwdC5vbmxvYWQgPSB2b2lkIDA7CiAgICAgICAgaGVhZC5yZW1vdmVDaGlsZChzY3JpcHQpOwogICAgICAgIHJlc29sdmUoKTsKICAgICAgfTsKICAgICAgc2NyaXB0Lm9uZXJyb3IgPSBmdW5jdGlvbihlKSB7CiAgICAgICAgcmVqZWN0KGUpOwogICAgICB9OwogICAgICBoZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7CiAgICB9KTsKICB9CiAgdmFyIGxvYWRBbmRFeGVjdXRlU2NyaXB0X2RlZmF1bHQ7CiAgdmFyIGluaXRfbG9hZEFuZEV4ZWN1dGVTY3JpcHQgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2xvYWRBbmRFeGVjdXRlU2NyaXB0LmpzIigpIHsKICAgICAgbG9hZEFuZEV4ZWN1dGVTY3JpcHRfZGVmYXVsdCA9IGxvYWRBbmRFeGVjdXRlU2NyaXB0OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvb2JqZWN0VG9RdWVyeS5qcwogIGZ1bmN0aW9uIG9iamVjdFRvUXVlcnkob2JqKSB7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChvYmopKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJvYmogaXMgcmVxdWlyZWQuIik7CiAgICB9CiAgICBsZXQgcmVzdWx0ID0gIiI7CiAgICBmb3IgKGNvbnN0IHByb3BOYW1lIGluIG9iaikgewogICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkgewogICAgICAgIGNvbnN0IHZhbHVlID0gb2JqW3Byb3BOYW1lXTsKICAgICAgICBjb25zdCBwYXJ0ID0gYCR7ZW5jb2RlVVJJQ29tcG9uZW50KHByb3BOYW1lKX09YDsKICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSB2YWx1ZS5sZW5ndGg7IGkgPCBsZW47ICsraSkgewogICAgICAgICAgICByZXN1bHQgKz0gYCR7cGFydCArIGVuY29kZVVSSUNvbXBvbmVudCh2YWx1ZVtpXSl9JmA7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdCArPSBgJHtwYXJ0ICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKX0mYDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJlc3VsdCA9IHJlc3VsdC5zbGljZSgwLCAtMSk7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICB2YXIgb2JqZWN0VG9RdWVyeV9kZWZhdWx0OwogIHZhciBpbml0X29iamVjdFRvUXVlcnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL29iamVjdFRvUXVlcnkuanMiKCkgewogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBvYmplY3RUb1F1ZXJ5X2RlZmF1bHQgPSBvYmplY3RUb1F1ZXJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvcXVlcnlUb09iamVjdC5qcwogIGZ1bmN0aW9uIHF1ZXJ5VG9PYmplY3QocXVlcnlTdHJpbmcpIHsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHF1ZXJ5U3RyaW5nKSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicXVlcnlTdHJpbmcgaXMgcmVxdWlyZWQuIik7CiAgICB9CiAgICBjb25zdCByZXN1bHQgPSB7fTsKICAgIGlmIChxdWVyeVN0cmluZyA9PT0gIiIpIHsKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIGNvbnN0IHBhcnRzID0gcXVlcnlTdHJpbmcucmVwbGFjZSgvXCsvZywgIiUyMCIpLnNwbGl0KC9bJjtdLyk7CiAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gcGFydHMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHsKICAgICAgY29uc3Qgc3VicGFydHMgPSBwYXJ0c1tpXS5zcGxpdCgiPSIpOwogICAgICBjb25zdCBuYW1lID0gZGVjb2RlVVJJQ29tcG9uZW50KHN1YnBhcnRzWzBdKTsKICAgICAgbGV0IHZhbHVlID0gc3VicGFydHNbMV07CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQodmFsdWUpKSB7CiAgICAgICAgdmFsdWUgPSBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpOwogICAgICB9IGVsc2UgewogICAgICAgIHZhbHVlID0gIiI7CiAgICAgIH0KICAgICAgY29uc3QgcmVzdWx0VmFsdWUgPSByZXN1bHRbbmFtZV07CiAgICAgIGlmICh0eXBlb2YgcmVzdWx0VmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgICAgcmVzdWx0W25hbWVdID0gW3Jlc3VsdFZhbHVlLCB2YWx1ZV07CiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShyZXN1bHRWYWx1ZSkpIHsKICAgICAgICByZXN1bHRWYWx1ZS5wdXNoKHZhbHVlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXN1bHRbbmFtZV0gPSB2YWx1ZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgdmFyIHF1ZXJ5VG9PYmplY3RfZGVmYXVsdDsKICB2YXIgaW5pdF9xdWVyeVRvT2JqZWN0ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9xdWVyeVRvT2JqZWN0LmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgcXVlcnlUb09iamVjdF9kZWZhdWx0ID0gcXVlcnlUb09iamVjdDsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1JlcXVlc3RTdGF0ZS5qcwogIHZhciBSZXF1ZXN0U3RhdGUsIFJlcXVlc3RTdGF0ZV9kZWZhdWx0OwogIHZhciBpbml0X1JlcXVlc3RTdGF0ZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUmVxdWVzdFN0YXRlLmpzIigpIHsKICAgICAgUmVxdWVzdFN0YXRlID0gewogICAgICAgIC8qKgogICAgICAgICAqIEluaXRpYWwgdW5pc3N1ZWQgc3RhdGUuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFVOSVNTVUVEOiAwLAogICAgICAgIC8qKgogICAgICAgICAqIElzc3VlZCBidXQgbm90IHlldCBhY3RpdmUuIFdpbGwgYmVjb21lIGFjdGl2ZSB3aGVuIG9wZW4gc2xvdHMgYXJlIGF2YWlsYWJsZS4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgSVNTVUVEOiAxLAogICAgICAgIC8qKgogICAgICAgICAqIEFjdHVhbCBodHRwIHJlcXVlc3QgaGFzIGJlZW4gc2VudC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgQUNUSVZFOiAyLAogICAgICAgIC8qKgogICAgICAgICAqIFJlcXVlc3QgY29tcGxldGVkIHN1Y2Nlc3NmdWxseS4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgUkVDRUlWRUQ6IDMsCiAgICAgICAgLyoqCiAgICAgICAgICogUmVxdWVzdCB3YXMgY2FuY2VsbGVkLCBlaXRoZXIgZXhwbGljaXRseSBvciBhdXRvbWF0aWNhbGx5IGJlY2F1c2Ugb2YgbG93IHByaW9yaXR5LgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBDQU5DRUxMRUQ6IDQsCiAgICAgICAgLyoqCiAgICAgICAgICogUmVxdWVzdCBmYWlsZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIEZBSUxFRDogNQogICAgICB9OwogICAgICBSZXF1ZXN0U3RhdGVfZGVmYXVsdCA9IE9iamVjdC5mcmVlemUoUmVxdWVzdFN0YXRlKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1JlcXVlc3RUeXBlLmpzCiAgdmFyIFJlcXVlc3RUeXBlLCBSZXF1ZXN0VHlwZV9kZWZhdWx0OwogIHZhciBpbml0X1JlcXVlc3RUeXBlID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9SZXF1ZXN0VHlwZS5qcyIoKSB7CiAgICAgIFJlcXVlc3RUeXBlID0gewogICAgICAgIC8qKgogICAgICAgICAqIFRlcnJhaW4gcmVxdWVzdC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgVEVSUkFJTjogMCwKICAgICAgICAvKioKICAgICAgICAgKiBJbWFnZXJ5IHJlcXVlc3QuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIElNQUdFUlk6IDEsCiAgICAgICAgLyoqCiAgICAgICAgICogM0QgVGlsZXMgcmVxdWVzdC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgVElMRVMzRDogMiwKICAgICAgICAvKioKICAgICAgICAgKiBPdGhlciByZXF1ZXN0LgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBPVEhFUjogMwogICAgICB9OwogICAgICBSZXF1ZXN0VHlwZV9kZWZhdWx0ID0gT2JqZWN0LmZyZWV6ZShSZXF1ZXN0VHlwZSk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9SZXF1ZXN0LmpzCiAgZnVuY3Rpb24gUmVxdWVzdDIob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgY29uc3QgdGhyb3R0bGVCeVNlcnZlciA9IG9wdGlvbnMudGhyb3R0bGVCeVNlcnZlciA/PyBmYWxzZTsKICAgIGNvbnN0IHRocm90dGxlID0gb3B0aW9ucy50aHJvdHRsZSA/PyBmYWxzZTsKICAgIHRoaXMudXJsID0gb3B0aW9ucy51cmw7CiAgICB0aGlzLnJlcXVlc3RGdW5jdGlvbiA9IG9wdGlvbnMucmVxdWVzdEZ1bmN0aW9uOwogICAgdGhpcy5jYW5jZWxGdW5jdGlvbiA9IG9wdGlvbnMuY2FuY2VsRnVuY3Rpb247CiAgICB0aGlzLnByaW9yaXR5RnVuY3Rpb24gPSBvcHRpb25zLnByaW9yaXR5RnVuY3Rpb247CiAgICB0aGlzLnByaW9yaXR5ID0gb3B0aW9ucy5wcmlvcml0eSA/PyAwOwogICAgdGhpcy50aHJvdHRsZSA9IHRocm90dGxlOwogICAgdGhpcy50aHJvdHRsZUJ5U2VydmVyID0gdGhyb3R0bGVCeVNlcnZlcjsKICAgIHRoaXMudHlwZSA9IG9wdGlvbnMudHlwZSA/PyBSZXF1ZXN0VHlwZV9kZWZhdWx0Lk9USEVSOwogICAgdGhpcy5zZXJ2ZXJLZXkgPSBvcHRpb25zLnNlcnZlcktleTsKICAgIHRoaXMuc3RhdGUgPSBSZXF1ZXN0U3RhdGVfZGVmYXVsdC5VTklTU1VFRDsKICAgIHRoaXMuZGVmZXJyZWQgPSB2b2lkIDA7CiAgICB0aGlzLmNhbmNlbGxlZCA9IGZhbHNlOwogIH0KICB2YXIgUmVxdWVzdF9kZWZhdWx0OwogIHZhciBpbml0X1JlcXVlc3QgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1JlcXVlc3QuanMiKCkgewogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9SZXF1ZXN0U3RhdGUoKTsKICAgICAgaW5pdF9SZXF1ZXN0VHlwZSgpOwogICAgICBSZXF1ZXN0Mi5wcm90b3R5cGUuY2FuY2VsID0gZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5jYW5jZWxsZWQgPSB0cnVlOwogICAgICB9OwogICAgICBSZXF1ZXN0Mi5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFJlcXVlc3QyKHRoaXMpOwogICAgICAgIH0KICAgICAgICByZXN1bHQudXJsID0gdGhpcy51cmw7CiAgICAgICAgcmVzdWx0LnJlcXVlc3RGdW5jdGlvbiA9IHRoaXMucmVxdWVzdEZ1bmN0aW9uOwogICAgICAgIHJlc3VsdC5jYW5jZWxGdW5jdGlvbiA9IHRoaXMuY2FuY2VsRnVuY3Rpb247CiAgICAgICAgcmVzdWx0LnByaW9yaXR5RnVuY3Rpb24gPSB0aGlzLnByaW9yaXR5RnVuY3Rpb247CiAgICAgICAgcmVzdWx0LnByaW9yaXR5ID0gdGhpcy5wcmlvcml0eTsKICAgICAgICByZXN1bHQudGhyb3R0bGUgPSB0aGlzLnRocm90dGxlOwogICAgICAgIHJlc3VsdC50aHJvdHRsZUJ5U2VydmVyID0gdGhpcy50aHJvdHRsZUJ5U2VydmVyOwogICAgICAgIHJlc3VsdC50eXBlID0gdGhpcy50eXBlOwogICAgICAgIHJlc3VsdC5zZXJ2ZXJLZXkgPSB0aGlzLnNlcnZlcktleTsKICAgICAgICByZXN1bHQuc3RhdGUgPSBSZXF1ZXN0U3RhdGVfZGVmYXVsdC5VTklTU1VFRDsKICAgICAgICByZXN1bHQuZGVmZXJyZWQgPSB2b2lkIDA7CiAgICAgICAgcmVzdWx0LmNhbmNlbGxlZCA9IGZhbHNlOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFJlcXVlc3RfZGVmYXVsdCA9IFJlcXVlc3QyOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvcGFyc2VSZXNwb25zZUhlYWRlcnMuanMKICBmdW5jdGlvbiBwYXJzZVJlc3BvbnNlSGVhZGVycyhoZWFkZXJTdHJpbmcpIHsKICAgIGNvbnN0IGhlYWRlcnMgPSB7fTsKICAgIGlmICghaGVhZGVyU3RyaW5nKSB7CiAgICAgIHJldHVybiBoZWFkZXJzOwogICAgfQogICAgY29uc3QgaGVhZGVyUGFpcnMgPSBoZWFkZXJTdHJpbmcuc3BsaXQoIlxyXG4iKTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaGVhZGVyUGFpcnMubGVuZ3RoOyArK2kpIHsKICAgICAgY29uc3QgaGVhZGVyUGFpciA9IGhlYWRlclBhaXJzW2ldOwogICAgICBjb25zdCBpbmRleCA9IGhlYWRlclBhaXIuaW5kZXhPZigiOiAiKTsKICAgICAgaWYgKGluZGV4ID4gMCkgewogICAgICAgIGNvbnN0IGtleSA9IGhlYWRlclBhaXIuc3Vic3RyaW5nKDAsIGluZGV4KTsKICAgICAgICBjb25zdCB2YWwgPSBoZWFkZXJQYWlyLnN1YnN0cmluZyhpbmRleCArIDIpOwogICAgICAgIGhlYWRlcnNba2V5XSA9IHZhbDsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGhlYWRlcnM7CiAgfQogIHZhciBwYXJzZVJlc3BvbnNlSGVhZGVyc19kZWZhdWx0OwogIHZhciBpbml0X3BhcnNlUmVzcG9uc2VIZWFkZXJzID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9wYXJzZVJlc3BvbnNlSGVhZGVycy5qcyIoKSB7CiAgICAgIHBhcnNlUmVzcG9uc2VIZWFkZXJzX2RlZmF1bHQgPSBwYXJzZVJlc3BvbnNlSGVhZGVyczsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1JlcXVlc3RFcnJvckV2ZW50LmpzCiAgZnVuY3Rpb24gUmVxdWVzdEVycm9yRXZlbnQoc3RhdHVzQ29kZSwgcmVzcG9uc2UsIHJlc3BvbnNlSGVhZGVycykgewogICAgdGhpcy5zdGF0dXNDb2RlID0gc3RhdHVzQ29kZTsKICAgIHRoaXMucmVzcG9uc2UgPSByZXNwb25zZTsKICAgIHRoaXMucmVzcG9uc2VIZWFkZXJzID0gcmVzcG9uc2VIZWFkZXJzOwogICAgaWYgKHR5cGVvZiB0aGlzLnJlc3BvbnNlSGVhZGVycyA9PT0gInN0cmluZyIpIHsKICAgICAgdGhpcy5yZXNwb25zZUhlYWRlcnMgPSBwYXJzZVJlc3BvbnNlSGVhZGVyc19kZWZhdWx0KHRoaXMucmVzcG9uc2VIZWFkZXJzKTsKICAgIH0KICB9CiAgdmFyIFJlcXVlc3RFcnJvckV2ZW50X2RlZmF1bHQ7CiAgdmFyIGluaXRfUmVxdWVzdEVycm9yRXZlbnQgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1JlcXVlc3RFcnJvckV2ZW50LmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfcGFyc2VSZXNwb25zZUhlYWRlcnMoKTsKICAgICAgUmVxdWVzdEVycm9yRXZlbnQucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IHN0ciA9ICJSZXF1ZXN0IGhhcyBmYWlsZWQuIjsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHRoaXMuc3RhdHVzQ29kZSkpIHsKICAgICAgICAgIHN0ciArPSBgIFN0YXR1cyBDb2RlOiAke3RoaXMuc3RhdHVzQ29kZX1gOwogICAgICAgIH0KICAgICAgICByZXR1cm4gc3RyOwogICAgICB9OwogICAgICBSZXF1ZXN0RXJyb3JFdmVudF9kZWZhdWx0ID0gUmVxdWVzdEVycm9yRXZlbnQ7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9FdmVudC5qcwogIGZ1bmN0aW9uIEV2ZW50KCkgewogICAgdGhpcy5fbGlzdGVuZXJzID0gW107CiAgICB0aGlzLl9zY29wZXMgPSBbXTsKICAgIHRoaXMuX3RvUmVtb3ZlID0gW107CiAgICB0aGlzLl9pbnNpZGVSYWlzZUV2ZW50ID0gZmFsc2U7CiAgfQogIGZ1bmN0aW9uIGNvbXBhcmVOdW1iZXIoYTMsIGIpIHsKICAgIHJldHVybiBiIC0gYTM7CiAgfQogIHZhciBFdmVudF9kZWZhdWx0OwogIHZhciBpbml0X0V2ZW50ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9FdmVudC5qcyIoKSB7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKEV2ZW50LnByb3RvdHlwZSwgewogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBudW1iZXIgb2YgbGlzdGVuZXJzIGN1cnJlbnRseSBzdWJzY3JpYmVkIHRvIHRoZSBldmVudC4KICAgICAgICAgKiBAbWVtYmVyb2YgRXZlbnQucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBudW1iZXJPZkxpc3RlbmVyczogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2xpc3RlbmVycy5sZW5ndGggLSB0aGlzLl90b1JlbW92ZS5sZW5ndGg7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgRXZlbnQucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbihsaXN0ZW5lciwgc2NvcGUpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5mdW5jKCJsaXN0ZW5lciIsIGxpc3RlbmVyKTsKICAgICAgICB0aGlzLl9saXN0ZW5lcnMucHVzaChsaXN0ZW5lcik7CiAgICAgICAgdGhpcy5fc2NvcGVzLnB1c2goc2NvcGUpOwogICAgICAgIGNvbnN0IGV2ZW50ID0gdGhpczsKICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7CiAgICAgICAgICBldmVudC5yZW1vdmVFdmVudExpc3RlbmVyKGxpc3RlbmVyLCBzY29wZSk7CiAgICAgICAgfTsKICAgICAgfTsKICAgICAgRXZlbnQucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbihsaXN0ZW5lciwgc2NvcGUpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5mdW5jKCJsaXN0ZW5lciIsIGxpc3RlbmVyKTsKICAgICAgICBjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnM7CiAgICAgICAgY29uc3Qgc2NvcGVzID0gdGhpcy5fc2NvcGVzOwogICAgICAgIGxldCBpbmRleCA9IC0xOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBpZiAobGlzdGVuZXJzW2ldID09PSBsaXN0ZW5lciAmJiBzY29wZXNbaV0gPT09IHNjb3BlKSB7CiAgICAgICAgICAgIGluZGV4ID0gaTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgICAgIGlmICh0aGlzLl9pbnNpZGVSYWlzZUV2ZW50KSB7CiAgICAgICAgICAgIHRoaXMuX3RvUmVtb3ZlLnB1c2goaW5kZXgpOwogICAgICAgICAgICBsaXN0ZW5lcnNbaW5kZXhdID0gdm9pZCAwOwogICAgICAgICAgICBzY29wZXNbaW5kZXhdID0gdm9pZCAwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgbGlzdGVuZXJzLnNwbGljZShpbmRleCwgMSk7CiAgICAgICAgICAgIHNjb3Blcy5zcGxpY2UoaW5kZXgsIDEpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfTsKICAgICAgRXZlbnQucHJvdG90eXBlLnJhaXNlRXZlbnQgPSBmdW5jdGlvbigpIHsKICAgICAgICB0aGlzLl9pbnNpZGVSYWlzZUV2ZW50ID0gdHJ1ZTsKICAgICAgICBsZXQgaTsKICAgICAgICBjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnM7CiAgICAgICAgY29uc3Qgc2NvcGVzID0gdGhpcy5fc2NvcGVzOwogICAgICAgIGxldCBsZW5ndGggPSBsaXN0ZW5lcnMubGVuZ3RoOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgY29uc3QgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGxpc3RlbmVyKSkgewogICAgICAgICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkoc2NvcGVzW2ldLCBhcmd1bWVudHMpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCB0b1JlbW92ZSA9IHRoaXMuX3RvUmVtb3ZlOwogICAgICAgIGxlbmd0aCA9IHRvUmVtb3ZlLmxlbmd0aDsKICAgICAgICBpZiAobGVuZ3RoID4gMCkgewogICAgICAgICAgdG9SZW1vdmUuc29ydChjb21wYXJlTnVtYmVyKTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICBjb25zdCBpbmRleCA9IHRvUmVtb3ZlW2ldOwogICAgICAgICAgICBsaXN0ZW5lcnMuc3BsaWNlKGluZGV4LCAxKTsKICAgICAgICAgICAgc2NvcGVzLnNwbGljZShpbmRleCwgMSk7CiAgICAgICAgICB9CiAgICAgICAgICB0b1JlbW92ZS5sZW5ndGggPSAwOwogICAgICAgIH0KICAgICAgICB0aGlzLl9pbnNpZGVSYWlzZUV2ZW50ID0gZmFsc2U7CiAgICAgIH07CiAgICAgIEV2ZW50X2RlZmF1bHQgPSBFdmVudDsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0hlYXAuanMKICBmdW5jdGlvbiBIZWFwKG9wdGlvbnMpIHsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgib3B0aW9ucyIsIG9wdGlvbnMpOwogICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJvcHRpb25zLmNvbXBhcmF0b3IiLCBvcHRpb25zLmNvbXBhcmF0b3IpOwogICAgdGhpcy5fY29tcGFyYXRvciA9IG9wdGlvbnMuY29tcGFyYXRvcjsKICAgIHRoaXMuX2FycmF5ID0gW107CiAgICB0aGlzLl9sZW5ndGggPSAwOwogICAgdGhpcy5fbWF4aW11bUxlbmd0aCA9IHZvaWQgMDsKICB9CiAgZnVuY3Rpb24gc3dhcChhcnJheSwgYTMsIGIpIHsKICAgIGNvbnN0IHRlbXAgPSBhcnJheVthM107CiAgICBhcnJheVthM10gPSBhcnJheVtiXTsKICAgIGFycmF5W2JdID0gdGVtcDsKICB9CiAgdmFyIEhlYXBfZGVmYXVsdDsKICB2YXIgaW5pdF9IZWFwID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9IZWFwLmpzIigpIHsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoSGVhcC5wcm90b3R5cGUsIHsKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBsZW5ndGggb2YgdGhlIGhlYXAuCiAgICAgICAgICoKICAgICAgICAgKiBAbWVtYmVyb2YgSGVhcC5wcm90b3R5cGUKICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgbGVuZ3RoOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fbGVuZ3RoOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgaW50ZXJuYWwgYXJyYXkuCiAgICAgICAgICoKICAgICAgICAgKiBAbWVtYmVyb2YgSGVhcC5wcm90b3R5cGUKICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtBcnJheX0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBpbnRlcm5hbEFycmF5OiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fYXJyYXk7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIGFuZCBzZXRzIHRoZSBtYXhpbXVtIGxlbmd0aCBvZiB0aGUgaGVhcC4KICAgICAgICAgKgogICAgICAgICAqIEBtZW1iZXJvZiBIZWFwLnByb3RvdHlwZQogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKi8KICAgICAgICBtYXhpbXVtTGVuZ3RoOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fbWF4aW11bUxlbmd0aDsKICAgICAgICAgIH0sCiAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKHZhbHVlKSB7CiAgICAgICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJtYXhpbXVtTGVuZ3RoIiwgdmFsdWUsIDApOwogICAgICAgICAgICBjb25zdCBvcmlnaW5hbExlbmd0aCA9IHRoaXMuX2xlbmd0aDsKICAgICAgICAgICAgaWYgKHZhbHVlIDwgb3JpZ2luYWxMZW5ndGgpIHsKICAgICAgICAgICAgICBjb25zdCBhcnJheSA9IHRoaXMuX2FycmF5OwogICAgICAgICAgICAgIGZvciAobGV0IGkgPSB2YWx1ZTsgaSA8IG9yaWdpbmFsTGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgICAgIGFycmF5W2ldID0gdm9pZCAwOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0aGlzLl9sZW5ndGggPSB2YWx1ZTsKICAgICAgICAgICAgICBhcnJheS5sZW5ndGggPSB2YWx1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLl9tYXhpbXVtTGVuZ3RoID0gdmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgY29tcGFyYXRvciB0byB1c2UgZm9yIHRoZSBoZWFwLiBJZiBjb21wYXJhdG9yKGEsIGIpIGlzIGxlc3MgdGhhbiAwLCBzb3J0IGEgdG8gYSBsb3dlciBpbmRleCB0aGFuIGIsIG90aGVyd2lzZSBzb3J0IHRvIGEgaGlnaGVyIGluZGV4LgogICAgICAgICAqCiAgICAgICAgICogQG1lbWJlcm9mIEhlYXAucHJvdG90eXBlCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7SGVhcC5Db21wYXJhdG9yQ2FsbGJhY2t9CiAgICAgICAgICovCiAgICAgICAgY29tcGFyYXRvcjogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NvbXBhcmF0b3I7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgSGVhcC5wcm90b3R5cGUucmVzZXJ2ZSA9IGZ1bmN0aW9uKGxlbmd0aCkgewogICAgICAgIGxlbmd0aCA9IGxlbmd0aCA/PyB0aGlzLl9sZW5ndGg7CiAgICAgICAgdGhpcy5fYXJyYXkubGVuZ3RoID0gbGVuZ3RoOwogICAgICB9OwogICAgICBIZWFwLnByb3RvdHlwZS5oZWFwaWZ5ID0gZnVuY3Rpb24oaW5kZXgpIHsKICAgICAgICBpbmRleCA9IGluZGV4ID8/IDA7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gdGhpcy5fbGVuZ3RoOwogICAgICAgIGNvbnN0IGNvbXBhcmF0b3IgPSB0aGlzLl9jb21wYXJhdG9yOwogICAgICAgIGNvbnN0IGFycmF5ID0gdGhpcy5fYXJyYXk7CiAgICAgICAgbGV0IGNhbmRpZGF0ZSA9IC0xOwogICAgICAgIGxldCBpbnNlcnRpbmcgPSB0cnVlOwogICAgICAgIHdoaWxlIChpbnNlcnRpbmcpIHsKICAgICAgICAgIGNvbnN0IHJpZ2h0ID0gMiAqIChpbmRleCArIDEpOwogICAgICAgICAgY29uc3QgbGVmdCA9IHJpZ2h0IC0gMTsKICAgICAgICAgIGlmIChsZWZ0IDwgbGVuZ3RoICYmIGNvbXBhcmF0b3IoYXJyYXlbbGVmdF0sIGFycmF5W2luZGV4XSkgPCAwKSB7CiAgICAgICAgICAgIGNhbmRpZGF0ZSA9IGxlZnQ7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBjYW5kaWRhdGUgPSBpbmRleDsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChyaWdodCA8IGxlbmd0aCAmJiBjb21wYXJhdG9yKGFycmF5W3JpZ2h0XSwgYXJyYXlbY2FuZGlkYXRlXSkgPCAwKSB7CiAgICAgICAgICAgIGNhbmRpZGF0ZSA9IHJpZ2h0OwogICAgICAgICAgfQogICAgICAgICAgaWYgKGNhbmRpZGF0ZSAhPT0gaW5kZXgpIHsKICAgICAgICAgICAgc3dhcChhcnJheSwgY2FuZGlkYXRlLCBpbmRleCk7CiAgICAgICAgICAgIGluZGV4ID0gY2FuZGlkYXRlOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaW5zZXJ0aW5nID0gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9OwogICAgICBIZWFwLnByb3RvdHlwZS5yZXNvcnQgPSBmdW5jdGlvbigpIHsKICAgICAgICBjb25zdCBsZW5ndGggPSB0aGlzLl9sZW5ndGg7CiAgICAgICAgZm9yIChsZXQgaSA9IE1hdGguY2VpbChsZW5ndGggLyAyKTsgaSA+PSAwOyAtLWkpIHsKICAgICAgICAgIHRoaXMuaGVhcGlmeShpKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIEhlYXAucHJvdG90eXBlLmluc2VydCA9IGZ1bmN0aW9uKGVsZW1lbnQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImVsZW1lbnQiLCBlbGVtZW50KTsKICAgICAgICBjb25zdCBhcnJheSA9IHRoaXMuX2FycmF5OwogICAgICAgIGNvbnN0IGNvbXBhcmF0b3IgPSB0aGlzLl9jb21wYXJhdG9yOwogICAgICAgIGNvbnN0IG1heGltdW1MZW5ndGggPSB0aGlzLl9tYXhpbXVtTGVuZ3RoOwogICAgICAgIGxldCBpbmRleCA9IHRoaXMuX2xlbmd0aCsrOwogICAgICAgIGlmIChpbmRleCA8IGFycmF5Lmxlbmd0aCkgewogICAgICAgICAgYXJyYXlbaW5kZXhdID0gZWxlbWVudDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYXJyYXkucHVzaChlbGVtZW50KTsKICAgICAgICB9CiAgICAgICAgd2hpbGUgKGluZGV4ICE9PSAwKSB7CiAgICAgICAgICBjb25zdCBwYXJlbnQgPSBNYXRoLmZsb29yKChpbmRleCAtIDEpIC8gMik7CiAgICAgICAgICBpZiAoY29tcGFyYXRvcihhcnJheVtpbmRleF0sIGFycmF5W3BhcmVudF0pIDwgMCkgewogICAgICAgICAgICBzd2FwKGFycmF5LCBpbmRleCwgcGFyZW50KTsKICAgICAgICAgICAgaW5kZXggPSBwYXJlbnQ7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbGV0IHJlbW92ZWRFbGVtZW50OwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobWF4aW11bUxlbmd0aCkgJiYgdGhpcy5fbGVuZ3RoID4gbWF4aW11bUxlbmd0aCkgewogICAgICAgICAgcmVtb3ZlZEVsZW1lbnQgPSBhcnJheVttYXhpbXVtTGVuZ3RoXTsKICAgICAgICAgIHRoaXMuX2xlbmd0aCA9IG1heGltdW1MZW5ndGg7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZW1vdmVkRWxlbWVudDsKICAgICAgfTsKICAgICAgSGVhcC5wcm90b3R5cGUucG9wID0gZnVuY3Rpb24oaW5kZXgpIHsKICAgICAgICBpbmRleCA9IGluZGV4ID8/IDA7CiAgICAgICAgaWYgKHRoaXMuX2xlbmd0aCA9PT0gMCkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuKCJpbmRleCIsIGluZGV4LCB0aGlzLl9sZW5ndGgpOwogICAgICAgIGNvbnN0IGFycmF5ID0gdGhpcy5fYXJyYXk7CiAgICAgICAgY29uc3Qgcm9vdCA9IGFycmF5W2luZGV4XTsKICAgICAgICBzd2FwKGFycmF5LCBpbmRleCwgLS10aGlzLl9sZW5ndGgpOwogICAgICAgIHRoaXMuaGVhcGlmeShpbmRleCk7CiAgICAgICAgYXJyYXlbdGhpcy5fbGVuZ3RoXSA9IHZvaWQgMDsKICAgICAgICByZXR1cm4gcm9vdDsKICAgICAgfTsKICAgICAgSGVhcF9kZWZhdWx0ID0gSGVhcDsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1JlcXVlc3RTY2hlZHVsZXIuanMKICBmdW5jdGlvbiBzb3J0UmVxdWVzdHMoYTMsIGIpIHsKICAgIHJldHVybiBhMy5wcmlvcml0eSAtIGIucHJpb3JpdHk7CiAgfQogIGZ1bmN0aW9uIFJlcXVlc3RTY2hlZHVsZXIoKSB7CiAgfQogIGZ1bmN0aW9uIHVwZGF0ZVByaW9yaXR5KHJlcXVlc3QpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocmVxdWVzdC5wcmlvcml0eUZ1bmN0aW9uKSkgewogICAgICByZXF1ZXN0LnByaW9yaXR5ID0gcmVxdWVzdC5wcmlvcml0eUZ1bmN0aW9uKCk7CiAgICB9CiAgfQogIGZ1bmN0aW9uIGlzc3VlUmVxdWVzdChyZXF1ZXN0KSB7CiAgICBpZiAocmVxdWVzdC5zdGF0ZSA9PT0gUmVxdWVzdFN0YXRlX2RlZmF1bHQuVU5JU1NVRUQpIHsKICAgICAgcmVxdWVzdC5zdGF0ZSA9IFJlcXVlc3RTdGF0ZV9kZWZhdWx0LklTU1VFRDsKICAgICAgcmVxdWVzdC5kZWZlcnJlZCA9IGRlZmVyX2RlZmF1bHQoKTsKICAgIH0KICAgIHJldHVybiByZXF1ZXN0LmRlZmVycmVkLnByb21pc2U7CiAgfQogIGZ1bmN0aW9uIGdldFJlcXVlc3RSZWNlaXZlZEZ1bmN0aW9uKHJlcXVlc3QpIHsKICAgIHJldHVybiBmdW5jdGlvbihyZXN1bHRzKSB7CiAgICAgIGlmIChyZXF1ZXN0LnN0YXRlID09PSBSZXF1ZXN0U3RhdGVfZGVmYXVsdC5DQU5DRUxMRUQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29uc3QgZGVmZXJyZWQgPSByZXF1ZXN0LmRlZmVycmVkOwogICAgICAtLXN0YXRpc3RpY3MubnVtYmVyT2ZBY3RpdmVSZXF1ZXN0czsKICAgICAgLS1udW1iZXJPZkFjdGl2ZVJlcXVlc3RzQnlTZXJ2ZXJbcmVxdWVzdC5zZXJ2ZXJLZXldOwogICAgICByZXF1ZXN0Q29tcGxldGVkRXZlbnQucmFpc2VFdmVudCgpOwogICAgICByZXF1ZXN0LnN0YXRlID0gUmVxdWVzdFN0YXRlX2RlZmF1bHQuUkVDRUlWRUQ7CiAgICAgIHJlcXVlc3QuZGVmZXJyZWQgPSB2b2lkIDA7CiAgICAgIGRlZmVycmVkLnJlc29sdmUocmVzdWx0cyk7CiAgICB9OwogIH0KICBmdW5jdGlvbiBnZXRSZXF1ZXN0RmFpbGVkRnVuY3Rpb24ocmVxdWVzdCkgewogICAgcmV0dXJuIGZ1bmN0aW9uKGVycm9yKSB7CiAgICAgIGlmIChyZXF1ZXN0LnN0YXRlID09PSBSZXF1ZXN0U3RhdGVfZGVmYXVsdC5DQU5DRUxMRUQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgKytzdGF0aXN0aWNzLm51bWJlck9mRmFpbGVkUmVxdWVzdHM7CiAgICAgIC0tc3RhdGlzdGljcy5udW1iZXJPZkFjdGl2ZVJlcXVlc3RzOwogICAgICAtLW51bWJlck9mQWN0aXZlUmVxdWVzdHNCeVNlcnZlcltyZXF1ZXN0LnNlcnZlcktleV07CiAgICAgIHJlcXVlc3RDb21wbGV0ZWRFdmVudC5yYWlzZUV2ZW50KGVycm9yKTsKICAgICAgcmVxdWVzdC5zdGF0ZSA9IFJlcXVlc3RTdGF0ZV9kZWZhdWx0LkZBSUxFRDsKICAgICAgcmVxdWVzdC5kZWZlcnJlZC5yZWplY3QoZXJyb3IpOwogICAgfTsKICB9CiAgZnVuY3Rpb24gc3RhcnRSZXF1ZXN0KHJlcXVlc3QpIHsKICAgIGNvbnN0IHByb21pc2UgPSBpc3N1ZVJlcXVlc3QocmVxdWVzdCk7CiAgICByZXF1ZXN0LnN0YXRlID0gUmVxdWVzdFN0YXRlX2RlZmF1bHQuQUNUSVZFOwogICAgYWN0aXZlUmVxdWVzdHMucHVzaChyZXF1ZXN0KTsKICAgICsrc3RhdGlzdGljcy5udW1iZXJPZkFjdGl2ZVJlcXVlc3RzOwogICAgKytzdGF0aXN0aWNzLm51bWJlck9mQWN0aXZlUmVxdWVzdHNFdmVyOwogICAgKytudW1iZXJPZkFjdGl2ZVJlcXVlc3RzQnlTZXJ2ZXJbcmVxdWVzdC5zZXJ2ZXJLZXldOwogICAgcmVxdWVzdC5yZXF1ZXN0RnVuY3Rpb24oKS50aGVuKGdldFJlcXVlc3RSZWNlaXZlZEZ1bmN0aW9uKHJlcXVlc3QpKS5jYXRjaChnZXRSZXF1ZXN0RmFpbGVkRnVuY3Rpb24ocmVxdWVzdCkpOwogICAgcmV0dXJuIHByb21pc2U7CiAgfQogIGZ1bmN0aW9uIGNhbmNlbFJlcXVlc3QocmVxdWVzdCkgewogICAgY29uc3QgYWN0aXZlID0gcmVxdWVzdC5zdGF0ZSA9PT0gUmVxdWVzdFN0YXRlX2RlZmF1bHQuQUNUSVZFOwogICAgcmVxdWVzdC5zdGF0ZSA9IFJlcXVlc3RTdGF0ZV9kZWZhdWx0LkNBTkNFTExFRDsKICAgICsrc3RhdGlzdGljcy5udW1iZXJPZkNhbmNlbGxlZFJlcXVlc3RzOwogICAgaWYgKGRlZmluZWRfZGVmYXVsdChyZXF1ZXN0LmRlZmVycmVkKSkgewogICAgICBjb25zdCBkZWZlcnJlZCA9IHJlcXVlc3QuZGVmZXJyZWQ7CiAgICAgIHJlcXVlc3QuZGVmZXJyZWQgPSB2b2lkIDA7CiAgICAgIGRlZmVycmVkLnJlamVjdCgpOwogICAgfQogICAgaWYgKGFjdGl2ZSkgewogICAgICAtLXN0YXRpc3RpY3MubnVtYmVyT2ZBY3RpdmVSZXF1ZXN0czsKICAgICAgLS1udW1iZXJPZkFjdGl2ZVJlcXVlc3RzQnlTZXJ2ZXJbcmVxdWVzdC5zZXJ2ZXJLZXldOwogICAgICArK3N0YXRpc3RpY3MubnVtYmVyT2ZDYW5jZWxsZWRBY3RpdmVSZXF1ZXN0czsKICAgIH0KICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocmVxdWVzdC5jYW5jZWxGdW5jdGlvbikpIHsKICAgICAgcmVxdWVzdC5jYW5jZWxGdW5jdGlvbigpOwogICAgfQogIH0KICBmdW5jdGlvbiB1cGRhdGVTdGF0aXN0aWNzKCkgewogICAgaWYgKCFSZXF1ZXN0U2NoZWR1bGVyLmRlYnVnU2hvd1N0YXRpc3RpY3MpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKHN0YXRpc3RpY3MubnVtYmVyT2ZBY3RpdmVSZXF1ZXN0cyA9PT0gMCAmJiBzdGF0aXN0aWNzLmxhc3ROdW1iZXJPZkFjdGl2ZVJlcXVlc3RzID4gMCkgewogICAgICBpZiAoc3RhdGlzdGljcy5udW1iZXJPZkF0dGVtcHRlZFJlcXVlc3RzID4gMCkgewogICAgICAgIGNvbnNvbGUubG9nKAogICAgICAgICAgYE51bWJlciBvZiBhdHRlbXB0ZWQgcmVxdWVzdHM6ICR7c3RhdGlzdGljcy5udW1iZXJPZkF0dGVtcHRlZFJlcXVlc3RzfWAKICAgICAgICApOwogICAgICAgIHN0YXRpc3RpY3MubnVtYmVyT2ZBdHRlbXB0ZWRSZXF1ZXN0cyA9IDA7CiAgICAgIH0KICAgICAgaWYgKHN0YXRpc3RpY3MubnVtYmVyT2ZDYW5jZWxsZWRSZXF1ZXN0cyA+IDApIHsKICAgICAgICBjb25zb2xlLmxvZygKICAgICAgICAgIGBOdW1iZXIgb2YgY2FuY2VsbGVkIHJlcXVlc3RzOiAke3N0YXRpc3RpY3MubnVtYmVyT2ZDYW5jZWxsZWRSZXF1ZXN0c31gCiAgICAgICAgKTsKICAgICAgICBzdGF0aXN0aWNzLm51bWJlck9mQ2FuY2VsbGVkUmVxdWVzdHMgPSAwOwogICAgICB9CiAgICAgIGlmIChzdGF0aXN0aWNzLm51bWJlck9mQ2FuY2VsbGVkQWN0aXZlUmVxdWVzdHMgPiAwKSB7CiAgICAgICAgY29uc29sZS5sb2coCiAgICAgICAgICBgTnVtYmVyIG9mIGNhbmNlbGxlZCBhY3RpdmUgcmVxdWVzdHM6ICR7c3RhdGlzdGljcy5udW1iZXJPZkNhbmNlbGxlZEFjdGl2ZVJlcXVlc3RzfWAKICAgICAgICApOwogICAgICAgIHN0YXRpc3RpY3MubnVtYmVyT2ZDYW5jZWxsZWRBY3RpdmVSZXF1ZXN0cyA9IDA7CiAgICAgIH0KICAgICAgaWYgKHN0YXRpc3RpY3MubnVtYmVyT2ZGYWlsZWRSZXF1ZXN0cyA+IDApIHsKICAgICAgICBjb25zb2xlLmxvZygKICAgICAgICAgIGBOdW1iZXIgb2YgZmFpbGVkIHJlcXVlc3RzOiAke3N0YXRpc3RpY3MubnVtYmVyT2ZGYWlsZWRSZXF1ZXN0c31gCiAgICAgICAgKTsKICAgICAgICBzdGF0aXN0aWNzLm51bWJlck9mRmFpbGVkUmVxdWVzdHMgPSAwOwogICAgICB9CiAgICB9CiAgICBzdGF0aXN0aWNzLmxhc3ROdW1iZXJPZkFjdGl2ZVJlcXVlc3RzID0gc3RhdGlzdGljcy5udW1iZXJPZkFjdGl2ZVJlcXVlc3RzOwogIH0KICB2YXIgaW1wb3J0X3VyaWpzNCwgc3RhdGlzdGljcywgcHJpb3JpdHlIZWFwTGVuZ3RoLCByZXF1ZXN0SGVhcCwgYWN0aXZlUmVxdWVzdHMsIG51bWJlck9mQWN0aXZlUmVxdWVzdHNCeVNlcnZlciwgcGFnZVVyaSwgcmVxdWVzdENvbXBsZXRlZEV2ZW50LCBSZXF1ZXN0U2NoZWR1bGVyX2RlZmF1bHQ7CiAgdmFyIGluaXRfUmVxdWVzdFNjaGVkdWxlciA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUmVxdWVzdFNjaGVkdWxlci5qcyIoKSB7CiAgICAgIGltcG9ydF91cmlqczQgPSBfX3RvRVNNKHJlcXVpcmVfVVJJKCksIDEpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmZXIoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRXZlbnQoKTsKICAgICAgaW5pdF9IZWFwKCk7CiAgICAgIGluaXRfaXNCbG9iVXJpKCk7CiAgICAgIGluaXRfaXNEYXRhVXJpKCk7CiAgICAgIGluaXRfUmVxdWVzdFN0YXRlKCk7CiAgICAgIHN0YXRpc3RpY3MgPSB7CiAgICAgICAgbnVtYmVyT2ZBdHRlbXB0ZWRSZXF1ZXN0czogMCwKICAgICAgICBudW1iZXJPZkFjdGl2ZVJlcXVlc3RzOiAwLAogICAgICAgIG51bWJlck9mQ2FuY2VsbGVkUmVxdWVzdHM6IDAsCiAgICAgICAgbnVtYmVyT2ZDYW5jZWxsZWRBY3RpdmVSZXF1ZXN0czogMCwKICAgICAgICBudW1iZXJPZkZhaWxlZFJlcXVlc3RzOiAwLAogICAgICAgIG51bWJlck9mQWN0aXZlUmVxdWVzdHNFdmVyOiAwLAogICAgICAgIGxhc3ROdW1iZXJPZkFjdGl2ZVJlcXVlc3RzOiAwCiAgICAgIH07CiAgICAgIHByaW9yaXR5SGVhcExlbmd0aCA9IDIwOwogICAgICByZXF1ZXN0SGVhcCA9IG5ldyBIZWFwX2RlZmF1bHQoewogICAgICAgIGNvbXBhcmF0b3I6IHNvcnRSZXF1ZXN0cwogICAgICB9KTsKICAgICAgcmVxdWVzdEhlYXAubWF4aW11bUxlbmd0aCA9IHByaW9yaXR5SGVhcExlbmd0aDsKICAgICAgcmVxdWVzdEhlYXAucmVzZXJ2ZShwcmlvcml0eUhlYXBMZW5ndGgpOwogICAgICBhY3RpdmVSZXF1ZXN0cyA9IFtdOwogICAgICBudW1iZXJPZkFjdGl2ZVJlcXVlc3RzQnlTZXJ2ZXIgPSB7fTsKICAgICAgcGFnZVVyaSA9IHR5cGVvZiBkb2N1bWVudCAhPT0gInVuZGVmaW5lZCIgPyBuZXcgaW1wb3J0X3VyaWpzNC5kZWZhdWx0KGRvY3VtZW50LmxvY2F0aW9uLmhyZWYpIDogbmV3IGltcG9ydF91cmlqczQuZGVmYXVsdCgpOwogICAgICByZXF1ZXN0Q29tcGxldGVkRXZlbnQgPSBuZXcgRXZlbnRfZGVmYXVsdCgpOwogICAgICBSZXF1ZXN0U2NoZWR1bGVyLm1heGltdW1SZXF1ZXN0cyA9IDUwOwogICAgICBSZXF1ZXN0U2NoZWR1bGVyLm1heGltdW1SZXF1ZXN0c1BlclNlcnZlciA9IDE4OwogICAgICBSZXF1ZXN0U2NoZWR1bGVyLnJlcXVlc3RzQnlTZXJ2ZXIgPSB7fTsKICAgICAgUmVxdWVzdFNjaGVkdWxlci50aHJvdHRsZVJlcXVlc3RzID0gdHJ1ZTsKICAgICAgUmVxdWVzdFNjaGVkdWxlci5kZWJ1Z1Nob3dTdGF0aXN0aWNzID0gZmFsc2U7CiAgICAgIFJlcXVlc3RTY2hlZHVsZXIucmVxdWVzdENvbXBsZXRlZEV2ZW50ID0gcmVxdWVzdENvbXBsZXRlZEV2ZW50OwogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhSZXF1ZXN0U2NoZWR1bGVyLCB7CiAgICAgICAgLyoqCiAgICAgICAgICogUmV0dXJucyB0aGUgc3RhdGlzdGljcyB1c2VkIGJ5IHRoZSByZXF1ZXN0IHNjaGVkdWxlci4KICAgICAgICAgKgogICAgICAgICAqIEBtZW1iZXJvZiBSZXF1ZXN0U2NoZWR1bGVyCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7b2JqZWN0fQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgc3RhdGlzdGljczogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHN0YXRpc3RpY3M7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgbWF4aW11bSBzaXplIG9mIHRoZSBwcmlvcml0eSBoZWFwLiBUaGlzIGxpbWl0cyB0aGUgbnVtYmVyIG9mIHJlcXVlc3RzIHRoYXQgYXJlIHNvcnRlZCBieSBwcmlvcml0eS4gT25seSBhcHBsaWVzIHRvIHJlcXVlc3RzIHRoYXQgYXJlIG5vdCB5ZXQgYWN0aXZlLgogICAgICAgICAqCiAgICAgICAgICogQG1lbWJlcm9mIFJlcXVlc3RTY2hlZHVsZXIKICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGRlZmF1bHQgMjAKICAgICAgICAgKiBAcHJpdmF0ZQogICAgICAgICAqLwogICAgICAgIHByaW9yaXR5SGVhcExlbmd0aDogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHByaW9yaXR5SGVhcExlbmd0aDsKICAgICAgICAgIH0sCiAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKHZhbHVlKSB7CiAgICAgICAgICAgIGlmICh2YWx1ZSA8IHByaW9yaXR5SGVhcExlbmd0aCkgewogICAgICAgICAgICAgIHdoaWxlIChyZXF1ZXN0SGVhcC5sZW5ndGggPiB2YWx1ZSkgewogICAgICAgICAgICAgICAgY29uc3QgcmVxdWVzdCA9IHJlcXVlc3RIZWFwLnBvcCgpOwogICAgICAgICAgICAgICAgY2FuY2VsUmVxdWVzdChyZXF1ZXN0KTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcHJpb3JpdHlIZWFwTGVuZ3RoID0gdmFsdWU7CiAgICAgICAgICAgIHJlcXVlc3RIZWFwLm1heGltdW1MZW5ndGggPSB2YWx1ZTsKICAgICAgICAgICAgcmVxdWVzdEhlYXAucmVzZXJ2ZSh2YWx1ZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgUmVxdWVzdFNjaGVkdWxlci5zZXJ2ZXJIYXNPcGVuU2xvdHMgPSBmdW5jdGlvbihzZXJ2ZXJLZXksIGRlc2lyZWRSZXF1ZXN0cykgewogICAgICAgIGRlc2lyZWRSZXF1ZXN0cyA9IGRlc2lyZWRSZXF1ZXN0cyA/PyAxOwogICAgICAgIGNvbnN0IG1heFJlcXVlc3RzID0gUmVxdWVzdFNjaGVkdWxlci5yZXF1ZXN0c0J5U2VydmVyW3NlcnZlcktleV0gPz8gUmVxdWVzdFNjaGVkdWxlci5tYXhpbXVtUmVxdWVzdHNQZXJTZXJ2ZXI7CiAgICAgICAgY29uc3QgaGFzT3BlblNsb3RzU2VydmVyID0gbnVtYmVyT2ZBY3RpdmVSZXF1ZXN0c0J5U2VydmVyW3NlcnZlcktleV0gKyBkZXNpcmVkUmVxdWVzdHMgPD0gbWF4UmVxdWVzdHM7CiAgICAgICAgcmV0dXJuIGhhc09wZW5TbG90c1NlcnZlcjsKICAgICAgfTsKICAgICAgUmVxdWVzdFNjaGVkdWxlci5oZWFwSGFzT3BlblNsb3RzID0gZnVuY3Rpb24oZGVzaXJlZFJlcXVlc3RzKSB7CiAgICAgICAgY29uc3QgaGFzT3BlblNsb3RzSGVhcCA9IHJlcXVlc3RIZWFwLmxlbmd0aCArIGRlc2lyZWRSZXF1ZXN0cyA8PSBwcmlvcml0eUhlYXBMZW5ndGg7CiAgICAgICAgcmV0dXJuIGhhc09wZW5TbG90c0hlYXA7CiAgICAgIH07CiAgICAgIFJlcXVlc3RTY2hlZHVsZXIudXBkYXRlID0gZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IGk7CiAgICAgICAgbGV0IHJlcXVlc3Q7CiAgICAgICAgbGV0IHJlbW92ZUNvdW50ID0gMDsKICAgICAgICBjb25zdCBhY3RpdmVMZW5ndGggPSBhY3RpdmVSZXF1ZXN0cy5sZW5ndGg7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGFjdGl2ZUxlbmd0aDsgKytpKSB7CiAgICAgICAgICByZXF1ZXN0ID0gYWN0aXZlUmVxdWVzdHNbaV07CiAgICAgICAgICBpZiAocmVxdWVzdC5jYW5jZWxsZWQpIHsKICAgICAgICAgICAgY2FuY2VsUmVxdWVzdChyZXF1ZXN0KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChyZXF1ZXN0LnN0YXRlICE9PSBSZXF1ZXN0U3RhdGVfZGVmYXVsdC5BQ1RJVkUpIHsKICAgICAgICAgICAgKytyZW1vdmVDb3VudDsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAocmVtb3ZlQ291bnQgPiAwKSB7CiAgICAgICAgICAgIGFjdGl2ZVJlcXVlc3RzW2kgLSByZW1vdmVDb3VudF0gPSByZXF1ZXN0OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBhY3RpdmVSZXF1ZXN0cy5sZW5ndGggLT0gcmVtb3ZlQ291bnQ7CiAgICAgICAgY29uc3QgaXNzdWVkUmVxdWVzdHMgPSByZXF1ZXN0SGVhcC5pbnRlcm5hbEFycmF5OwogICAgICAgIGNvbnN0IGlzc3VlZExlbmd0aCA9IHJlcXVlc3RIZWFwLmxlbmd0aDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgaXNzdWVkTGVuZ3RoOyArK2kpIHsKICAgICAgICAgIHVwZGF0ZVByaW9yaXR5KGlzc3VlZFJlcXVlc3RzW2ldKTsKICAgICAgICB9CiAgICAgICAgcmVxdWVzdEhlYXAucmVzb3J0KCk7CiAgICAgICAgY29uc3Qgb3BlblNsb3RzID0gTWF0aC5tYXgoCiAgICAgICAgICBSZXF1ZXN0U2NoZWR1bGVyLm1heGltdW1SZXF1ZXN0cyAtIGFjdGl2ZVJlcXVlc3RzLmxlbmd0aCwKICAgICAgICAgIDAKICAgICAgICApOwogICAgICAgIGxldCBmaWxsZWRTbG90cyA9IDA7CiAgICAgICAgd2hpbGUgKGZpbGxlZFNsb3RzIDwgb3BlblNsb3RzICYmIHJlcXVlc3RIZWFwLmxlbmd0aCA+IDApIHsKICAgICAgICAgIHJlcXVlc3QgPSByZXF1ZXN0SGVhcC5wb3AoKTsKICAgICAgICAgIGlmIChyZXF1ZXN0LmNhbmNlbGxlZCkgewogICAgICAgICAgICBjYW5jZWxSZXF1ZXN0KHJlcXVlc3QpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChyZXF1ZXN0LnRocm90dGxlQnlTZXJ2ZXIgJiYgIVJlcXVlc3RTY2hlZHVsZXIuc2VydmVySGFzT3BlblNsb3RzKHJlcXVlc3Quc2VydmVyS2V5KSkgewogICAgICAgICAgICBjYW5jZWxSZXF1ZXN0KHJlcXVlc3QpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIHN0YXJ0UmVxdWVzdChyZXF1ZXN0KTsKICAgICAgICAgICsrZmlsbGVkU2xvdHM7CiAgICAgICAgfQogICAgICAgIHVwZGF0ZVN0YXRpc3RpY3MoKTsKICAgICAgfTsKICAgICAgUmVxdWVzdFNjaGVkdWxlci5nZXRTZXJ2ZXJLZXkgPSBmdW5jdGlvbih1cmwpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5zdHJpbmcoInVybCIsIHVybCk7CiAgICAgICAgbGV0IHVyaSA9IG5ldyBpbXBvcnRfdXJpanM0LmRlZmF1bHQodXJsKTsKICAgICAgICBpZiAodXJpLnNjaGVtZSgpID09PSAiIikgewogICAgICAgICAgdXJpID0gdXJpLmFic29sdXRlVG8ocGFnZVVyaSk7CiAgICAgICAgICB1cmkubm9ybWFsaXplKCk7CiAgICAgICAgfQogICAgICAgIGxldCBzZXJ2ZXJLZXkgPSB1cmkuYXV0aG9yaXR5KCk7CiAgICAgICAgaWYgKCEvOi8udGVzdChzZXJ2ZXJLZXkpKSB7CiAgICAgICAgICBzZXJ2ZXJLZXkgPSBgJHtzZXJ2ZXJLZXl9OiR7dXJpLnNjaGVtZSgpID09PSAiaHR0cHMiID8gIjQ0MyIgOiAiODAifWA7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGxlbmd0aCA9IG51bWJlck9mQWN0aXZlUmVxdWVzdHNCeVNlcnZlcltzZXJ2ZXJLZXldOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGxlbmd0aCkpIHsKICAgICAgICAgIG51bWJlck9mQWN0aXZlUmVxdWVzdHNCeVNlcnZlcltzZXJ2ZXJLZXldID0gMDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHNlcnZlcktleTsKICAgICAgfTsKICAgICAgUmVxdWVzdFNjaGVkdWxlci5yZXF1ZXN0ID0gZnVuY3Rpb24ocmVxdWVzdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVxdWVzdCIsIHJlcXVlc3QpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLnN0cmluZygicmVxdWVzdC51cmwiLCByZXF1ZXN0LnVybCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YuZnVuYygicmVxdWVzdC5yZXF1ZXN0RnVuY3Rpb24iLCByZXF1ZXN0LnJlcXVlc3RGdW5jdGlvbik7CiAgICAgICAgaWYgKGlzRGF0YVVyaV9kZWZhdWx0KHJlcXVlc3QudXJsKSB8fCBpc0Jsb2JVcmlfZGVmYXVsdChyZXF1ZXN0LnVybCkpIHsKICAgICAgICAgIHJlcXVlc3RDb21wbGV0ZWRFdmVudC5yYWlzZUV2ZW50KCk7CiAgICAgICAgICByZXF1ZXN0LnN0YXRlID0gUmVxdWVzdFN0YXRlX2RlZmF1bHQuUkVDRUlWRUQ7CiAgICAgICAgICByZXR1cm4gcmVxdWVzdC5yZXF1ZXN0RnVuY3Rpb24oKTsKICAgICAgICB9CiAgICAgICAgKytzdGF0aXN0aWNzLm51bWJlck9mQXR0ZW1wdGVkUmVxdWVzdHM7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVxdWVzdC5zZXJ2ZXJLZXkpKSB7CiAgICAgICAgICByZXF1ZXN0LnNlcnZlcktleSA9IFJlcXVlc3RTY2hlZHVsZXIuZ2V0U2VydmVyS2V5KHJlcXVlc3QudXJsKTsKICAgICAgICB9CiAgICAgICAgaWYgKFJlcXVlc3RTY2hlZHVsZXIudGhyb3R0bGVSZXF1ZXN0cyAmJiByZXF1ZXN0LnRocm90dGxlQnlTZXJ2ZXIgJiYgIVJlcXVlc3RTY2hlZHVsZXIuc2VydmVySGFzT3BlblNsb3RzKHJlcXVlc3Quc2VydmVyS2V5KSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgaWYgKCFSZXF1ZXN0U2NoZWR1bGVyLnRocm90dGxlUmVxdWVzdHMgfHwgIXJlcXVlc3QudGhyb3R0bGUpIHsKICAgICAgICAgIHJldHVybiBzdGFydFJlcXVlc3QocmVxdWVzdCk7CiAgICAgICAgfQogICAgICAgIGlmIChhY3RpdmVSZXF1ZXN0cy5sZW5ndGggPj0gUmVxdWVzdFNjaGVkdWxlci5tYXhpbXVtUmVxdWVzdHMpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIHVwZGF0ZVByaW9yaXR5KHJlcXVlc3QpOwogICAgICAgIGNvbnN0IHJlbW92ZWRSZXF1ZXN0ID0gcmVxdWVzdEhlYXAuaW5zZXJ0KHJlcXVlc3QpOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocmVtb3ZlZFJlcXVlc3QpKSB7CiAgICAgICAgICBpZiAocmVtb3ZlZFJlcXVlc3QgPT09IHJlcXVlc3QpIHsKICAgICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICAgIH0KICAgICAgICAgIGNhbmNlbFJlcXVlc3QocmVtb3ZlZFJlcXVlc3QpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gaXNzdWVSZXF1ZXN0KHJlcXVlc3QpOwogICAgICB9OwogICAgICBSZXF1ZXN0U2NoZWR1bGVyLmNsZWFyRm9yU3BlY3MgPSBmdW5jdGlvbigpIHsKICAgICAgICB3aGlsZSAocmVxdWVzdEhlYXAubGVuZ3RoID4gMCkgewogICAgICAgICAgY29uc3QgcmVxdWVzdCA9IHJlcXVlc3RIZWFwLnBvcCgpOwogICAgICAgICAgY2FuY2VsUmVxdWVzdChyZXF1ZXN0KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbGVuZ3RoID0gYWN0aXZlUmVxdWVzdHMubGVuZ3RoOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgIGNhbmNlbFJlcXVlc3QoYWN0aXZlUmVxdWVzdHNbaV0pOwogICAgICAgIH0KICAgICAgICBhY3RpdmVSZXF1ZXN0cy5sZW5ndGggPSAwOwogICAgICAgIG51bWJlck9mQWN0aXZlUmVxdWVzdHNCeVNlcnZlciA9IHt9OwogICAgICAgIHN0YXRpc3RpY3MubnVtYmVyT2ZBdHRlbXB0ZWRSZXF1ZXN0cyA9IDA7CiAgICAgICAgc3RhdGlzdGljcy5udW1iZXJPZkFjdGl2ZVJlcXVlc3RzID0gMDsKICAgICAgICBzdGF0aXN0aWNzLm51bWJlck9mQ2FuY2VsbGVkUmVxdWVzdHMgPSAwOwogICAgICAgIHN0YXRpc3RpY3MubnVtYmVyT2ZDYW5jZWxsZWRBY3RpdmVSZXF1ZXN0cyA9IDA7CiAgICAgICAgc3RhdGlzdGljcy5udW1iZXJPZkZhaWxlZFJlcXVlc3RzID0gMDsKICAgICAgICBzdGF0aXN0aWNzLm51bWJlck9mQWN0aXZlUmVxdWVzdHNFdmVyID0gMDsKICAgICAgICBzdGF0aXN0aWNzLmxhc3ROdW1iZXJPZkFjdGl2ZVJlcXVlc3RzID0gMDsKICAgICAgfTsKICAgICAgUmVxdWVzdFNjaGVkdWxlci5udW1iZXJPZkFjdGl2ZVJlcXVlc3RzQnlTZXJ2ZXIgPSBmdW5jdGlvbihzZXJ2ZXJLZXkpIHsKICAgICAgICByZXR1cm4gbnVtYmVyT2ZBY3RpdmVSZXF1ZXN0c0J5U2VydmVyW3NlcnZlcktleV07CiAgICAgIH07CiAgICAgIFJlcXVlc3RTY2hlZHVsZXIucmVxdWVzdEhlYXAgPSByZXF1ZXN0SGVhcDsKICAgICAgUmVxdWVzdFNjaGVkdWxlcl9kZWZhdWx0ID0gUmVxdWVzdFNjaGVkdWxlcjsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1RydXN0ZWRTZXJ2ZXJzLmpzCiAgZnVuY3Rpb24gZ2V0QXV0aG9yaXR5KHVybCkgewogICAgY29uc3QgdXJpID0gbmV3IGltcG9ydF91cmlqczUuZGVmYXVsdCh1cmwpOwogICAgdXJpLm5vcm1hbGl6ZSgpOwogICAgbGV0IGF1dGhvcml0eSA9IHVyaS5hdXRob3JpdHkoKTsKICAgIGlmIChhdXRob3JpdHkubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiB2b2lkIDA7CiAgICB9CiAgICB1cmkuYXV0aG9yaXR5KGF1dGhvcml0eSk7CiAgICBpZiAoYXV0aG9yaXR5LmluZGV4T2YoIkAiKSAhPT0gLTEpIHsKICAgICAgY29uc3QgcGFydHMgPSBhdXRob3JpdHkuc3BsaXQoIkAiKTsKICAgICAgYXV0aG9yaXR5ID0gcGFydHNbMV07CiAgICB9CiAgICBpZiAoYXV0aG9yaXR5LmluZGV4T2YoIjoiKSA9PT0gLTEpIHsKICAgICAgbGV0IHNjaGVtZSA9IHVyaS5zY2hlbWUoKTsKICAgICAgaWYgKHNjaGVtZS5sZW5ndGggPT09IDApIHsKICAgICAgICBzY2hlbWUgPSB3aW5kb3cubG9jYXRpb24ucHJvdG9jb2w7CiAgICAgICAgc2NoZW1lID0gc2NoZW1lLnN1YnN0cmluZygwLCBzY2hlbWUubGVuZ3RoIC0gMSk7CiAgICAgIH0KICAgICAgaWYgKHNjaGVtZSA9PT0gImh0dHAiKSB7CiAgICAgICAgYXV0aG9yaXR5ICs9ICI6ODAiOwogICAgICB9IGVsc2UgaWYgKHNjaGVtZSA9PT0gImh0dHBzIikgewogICAgICAgIGF1dGhvcml0eSArPSAiOjQ0MyI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGF1dGhvcml0eTsKICB9CiAgdmFyIGltcG9ydF91cmlqczUsIFRydXN0ZWRTZXJ2ZXJzLCBfc2VydmVycywgVHJ1c3RlZFNlcnZlcnNfZGVmYXVsdDsKICB2YXIgaW5pdF9UcnVzdGVkU2VydmVycyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvVHJ1c3RlZFNlcnZlcnMuanMiKCkgewogICAgICBpbXBvcnRfdXJpanM1ID0gX190b0VTTShyZXF1aXJlX1VSSSgpLCAxKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgVHJ1c3RlZFNlcnZlcnMgPSB7fTsKICAgICAgX3NlcnZlcnMgPSB7fTsKICAgICAgVHJ1c3RlZFNlcnZlcnMuYWRkID0gZnVuY3Rpb24oaG9zdCwgcG9ydCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGhvc3QpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiaG9zdCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocG9ydCkgfHwgcG9ydCA8PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicG9ydCBpcyByZXF1aXJlZCB0byBiZSBncmVhdGVyIHRoYW4gMC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgYXV0aG9yaXR5ID0gYCR7aG9zdC50b0xvd2VyQ2FzZSgpfToke3BvcnR9YDsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChfc2VydmVyc1thdXRob3JpdHldKSkgewogICAgICAgICAgX3NlcnZlcnNbYXV0aG9yaXR5XSA9IHRydWU7CiAgICAgICAgfQogICAgICB9OwogICAgICBUcnVzdGVkU2VydmVycy5yZW1vdmUgPSBmdW5jdGlvbihob3N0LCBwb3J0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaG9zdCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJob3N0IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwb3J0KSB8fCBwb3J0IDw9IDApIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJwb3J0IGlzIHJlcXVpcmVkIHRvIGJlIGdyZWF0ZXIgdGhhbiAwLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBhdXRob3JpdHkgPSBgJHtob3N0LnRvTG93ZXJDYXNlKCl9OiR7cG9ydH1gOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoX3NlcnZlcnNbYXV0aG9yaXR5XSkpIHsKICAgICAgICAgIGRlbGV0ZSBfc2VydmVyc1thdXRob3JpdHldOwogICAgICAgIH0KICAgICAgfTsKICAgICAgVHJ1c3RlZFNlcnZlcnMuY29udGFpbnMgPSBmdW5jdGlvbih1cmwpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh1cmwpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgidXJsIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBhdXRob3JpdHkgPSBnZXRBdXRob3JpdHkodXJsKTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGF1dGhvcml0eSkgJiYgZGVmaW5lZF9kZWZhdWx0KF9zZXJ2ZXJzW2F1dGhvcml0eV0pKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9OwogICAgICBUcnVzdGVkU2VydmVycy5jbGVhciA9IGZ1bmN0aW9uKCkgewogICAgICAgIF9zZXJ2ZXJzID0ge307CiAgICAgIH07CiAgICAgIFRydXN0ZWRTZXJ2ZXJzX2RlZmF1bHQgPSBUcnVzdGVkU2VydmVyczsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1Jlc291cmNlLmpzCiAgZnVuY3Rpb24gUmVzb3VyY2Uob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAic3RyaW5nIikgewogICAgICBvcHRpb25zID0gewogICAgICAgIHVybDogb3B0aW9ucwogICAgICB9OwogICAgfQogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yuc3RyaW5nKCJvcHRpb25zLnVybCIsIG9wdGlvbnMudXJsKTsKICAgIHRoaXMuX3VybCA9IHZvaWQgMDsKICAgIHRoaXMuX3RlbXBsYXRlVmFsdWVzID0gZGVmYXVsdENsb25lKG9wdGlvbnMudGVtcGxhdGVWYWx1ZXMsIHt9KTsKICAgIHRoaXMuX3F1ZXJ5UGFyYW1ldGVycyA9IGRlZmF1bHRDbG9uZShvcHRpb25zLnF1ZXJ5UGFyYW1ldGVycywge30pOwogICAgdGhpcy5oZWFkZXJzID0gZGVmYXVsdENsb25lKG9wdGlvbnMuaGVhZGVycywge30pOwogICAgdGhpcy5yZXF1ZXN0ID0gb3B0aW9ucy5yZXF1ZXN0ID8/IG5ldyBSZXF1ZXN0X2RlZmF1bHQoKTsKICAgIHRoaXMucHJveHkgPSBvcHRpb25zLnByb3h5OwogICAgdGhpcy5yZXRyeUNhbGxiYWNrID0gb3B0aW9ucy5yZXRyeUNhbGxiYWNrOwogICAgdGhpcy5yZXRyeUF0dGVtcHRzID0gb3B0aW9ucy5yZXRyeUF0dGVtcHRzID8/IDA7CiAgICB0aGlzLl9yZXRyeUNvdW50ID0gMDsKICAgIGNvbnN0IHBhcnNlVXJsID0gb3B0aW9ucy5wYXJzZVVybCA/PyB0cnVlOwogICAgaWYgKHBhcnNlVXJsKSB7CiAgICAgIHRoaXMucGFyc2VVcmwob3B0aW9ucy51cmwsIHRydWUsIHRydWUpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5fdXJsID0gb3B0aW9ucy51cmw7CiAgICB9CiAgICB0aGlzLl9jcmVkaXRzID0gb3B0aW9ucy5jcmVkaXRzOwogIH0KICBmdW5jdGlvbiBkZWZhdWx0Q2xvbmUodmFsdWUsIGRlZmF1bHRWYWx1ZSkgewogICAgcmV0dXJuIGRlZmluZWRfZGVmYXVsdCh2YWx1ZSkgPyBjbG9uZV9kZWZhdWx0KHZhbHVlKSA6IGRlZmF1bHRWYWx1ZTsKICB9CiAgZnVuY3Rpb24gcGFyc2VRdWVyeVN0cmluZyhxdWVyeVN0cmluZykgewogICAgaWYgKHF1ZXJ5U3RyaW5nLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4ge307CiAgICB9CiAgICBpZiAocXVlcnlTdHJpbmcuaW5kZXhPZigiPSIpID09PSAtMSkgewogICAgICByZXR1cm4geyBbcXVlcnlTdHJpbmddOiB2b2lkIDAgfTsKICAgIH0KICAgIHJldHVybiBxdWVyeVRvT2JqZWN0X2RlZmF1bHQocXVlcnlTdHJpbmcpOwogIH0KICBmdW5jdGlvbiBjb21iaW5lUXVlcnlQYXJhbWV0ZXJzKHExMiwgcTIyLCBwcmVzZXJ2ZVF1ZXJ5UGFyYW1ldGVycykgewogICAgaWYgKCFwcmVzZXJ2ZVF1ZXJ5UGFyYW1ldGVycykgewogICAgICByZXR1cm4gY29tYmluZV9kZWZhdWx0KHExMiwgcTIyKTsKICAgIH0KICAgIGNvbnN0IHJlc3VsdCA9IGNsb25lX2RlZmF1bHQocTEyLCB0cnVlKTsKICAgIGZvciAoY29uc3QgcGFyYW0gaW4gcTIyKSB7CiAgICAgIGlmIChxMjIuaGFzT3duUHJvcGVydHkocGFyYW0pKSB7CiAgICAgICAgbGV0IHZhbHVlID0gcmVzdWx0W3BhcmFtXTsKICAgICAgICBjb25zdCBxMlZhbHVlID0gcTIyW3BhcmFtXTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHZhbHVlKSkgewogICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSkgewogICAgICAgICAgICB2YWx1ZSA9IHJlc3VsdFtwYXJhbV0gPSBbdmFsdWVdOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0W3BhcmFtXSA9IHZhbHVlLmNvbmNhdChxMlZhbHVlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzdWx0W3BhcmFtXSA9IEFycmF5LmlzQXJyYXkocTJWYWx1ZSkgPyBxMlZhbHVlLnNsaWNlKCkgOiBxMlZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgZnVuY3Rpb24gc3RyaW5naWZ5UXVlcnkocXVlcnlPYmplY3QpIHsKICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhxdWVyeU9iamVjdCk7CiAgICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuICIiOwogICAgfQogICAgaWYgKGtleXMubGVuZ3RoID09PSAxICYmICFkZWZpbmVkX2RlZmF1bHQocXVlcnlPYmplY3Rba2V5c1swXV0pKSB7CiAgICAgIHJldHVybiBgPyR7a2V5c1swXX1gOwogICAgfQogICAgcmV0dXJuIGA/JHtvYmplY3RUb1F1ZXJ5X2RlZmF1bHQocXVlcnlPYmplY3QpfWA7CiAgfQogIGZ1bmN0aW9uIGZldGNoSW1hZ2Uob3B0aW9ucykgewogICAgY29uc3QgcmVzb3VyY2UgPSBvcHRpb25zLnJlc291cmNlOwogICAgY29uc3QgZmxpcFkgPSBvcHRpb25zLmZsaXBZOwogICAgY29uc3Qgc2tpcENvbG9yU3BhY2VDb252ZXJzaW9uID0gb3B0aW9ucy5za2lwQ29sb3JTcGFjZUNvbnZlcnNpb247CiAgICBjb25zdCBwcmVmZXJJbWFnZUJpdG1hcCA9IG9wdGlvbnMucHJlZmVySW1hZ2VCaXRtYXA7CiAgICBjb25zdCByZXF1ZXN0ID0gcmVzb3VyY2UucmVxdWVzdDsKICAgIHJlcXVlc3QudXJsID0gcmVzb3VyY2UudXJsOwogICAgcmVxdWVzdC5yZXF1ZXN0RnVuY3Rpb24gPSBmdW5jdGlvbigpIHsKICAgICAgbGV0IGNyb3NzT3JpZ2luID0gZmFsc2U7CiAgICAgIGlmICghcmVzb3VyY2UuaXNEYXRhVXJpICYmICFyZXNvdXJjZS5pc0Jsb2JVcmkpIHsKICAgICAgICBjcm9zc09yaWdpbiA9IHJlc291cmNlLmlzQ3Jvc3NPcmlnaW5Vcmw7CiAgICAgIH0KICAgICAgY29uc3QgZGVmZXJyZWQgPSBkZWZlcl9kZWZhdWx0KCk7CiAgICAgIFJlc291cmNlLl9JbXBsZW1lbnRhdGlvbnMuY3JlYXRlSW1hZ2UoCiAgICAgICAgcmVxdWVzdCwKICAgICAgICBjcm9zc09yaWdpbiwKICAgICAgICBkZWZlcnJlZCwKICAgICAgICBmbGlwWSwKICAgICAgICBza2lwQ29sb3JTcGFjZUNvbnZlcnNpb24sCiAgICAgICAgcHJlZmVySW1hZ2VCaXRtYXAKICAgICAgKTsKICAgICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7CiAgICB9OwogICAgY29uc3QgcHJvbWlzZSA9IFJlcXVlc3RTY2hlZHVsZXJfZGVmYXVsdC5yZXF1ZXN0KHJlcXVlc3QpOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocHJvbWlzZSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgcmV0dXJuIHByb21pc2UuY2F0Y2goZnVuY3Rpb24oZSkgewogICAgICBpZiAocmVxdWVzdC5zdGF0ZSAhPT0gUmVxdWVzdFN0YXRlX2RlZmF1bHQuRkFJTEVEKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGUpOwogICAgICB9CiAgICAgIHJldHVybiByZXNvdXJjZS5yZXRyeU9uRXJyb3IoZSkudGhlbihmdW5jdGlvbihyZXRyeSkgewogICAgICAgIGlmIChyZXRyeSkgewogICAgICAgICAgcmVxdWVzdC5zdGF0ZSA9IFJlcXVlc3RTdGF0ZV9kZWZhdWx0LlVOSVNTVUVEOwogICAgICAgICAgcmVxdWVzdC5kZWZlcnJlZCA9IHZvaWQgMDsKICAgICAgICAgIHJldHVybiBmZXRjaEltYWdlKHsKICAgICAgICAgICAgcmVzb3VyY2UsCiAgICAgICAgICAgIGZsaXBZLAogICAgICAgICAgICBza2lwQ29sb3JTcGFjZUNvbnZlcnNpb24sCiAgICAgICAgICAgIHByZWZlckltYWdlQml0bWFwCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGUpOwogICAgICB9KTsKICAgIH0pOwogIH0KICBmdW5jdGlvbiBmZXRjaEpzb25wKHJlc291cmNlLCBjYWxsYmFja1BhcmFtZXRlck5hbWUsIGZ1bmN0aW9uTmFtZSkgewogICAgY29uc3QgY2FsbGJhY2tRdWVyeSA9IHt9OwogICAgY2FsbGJhY2tRdWVyeVtjYWxsYmFja1BhcmFtZXRlck5hbWVdID0gZnVuY3Rpb25OYW1lOwogICAgcmVzb3VyY2Uuc2V0UXVlcnlQYXJhbWV0ZXJzKGNhbGxiYWNrUXVlcnkpOwogICAgY29uc3QgcmVxdWVzdCA9IHJlc291cmNlLnJlcXVlc3Q7CiAgICBjb25zdCB1cmwgPSByZXNvdXJjZS51cmw7CiAgICByZXF1ZXN0LnVybCA9IHVybDsKICAgIHJlcXVlc3QucmVxdWVzdEZ1bmN0aW9uID0gZnVuY3Rpb24oKSB7CiAgICAgIGNvbnN0IGRlZmVycmVkID0gZGVmZXJfZGVmYXVsdCgpOwogICAgICB3aW5kb3dbZnVuY3Rpb25OYW1lXSA9IGZ1bmN0aW9uKGRhdGEpIHsKICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKGRhdGEpOwogICAgICAgIHRyeSB7CiAgICAgICAgICBkZWxldGUgd2luZG93W2Z1bmN0aW9uTmFtZV07CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgd2luZG93W2Z1bmN0aW9uTmFtZV0gPSB2b2lkIDA7CiAgICAgICAgfQogICAgICB9OwogICAgICBSZXNvdXJjZS5fSW1wbGVtZW50YXRpb25zLmxvYWRBbmRFeGVjdXRlU2NyaXB0KHVybCwgZnVuY3Rpb25OYW1lLCBkZWZlcnJlZCk7CiAgICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlOwogICAgfTsKICAgIGNvbnN0IHByb21pc2UgPSBSZXF1ZXN0U2NoZWR1bGVyX2RlZmF1bHQucmVxdWVzdChyZXF1ZXN0KTsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHByb21pc2UpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHJldHVybiBwcm9taXNlLmNhdGNoKGZ1bmN0aW9uKGUpIHsKICAgICAgaWYgKHJlcXVlc3Quc3RhdGUgIT09IFJlcXVlc3RTdGF0ZV9kZWZhdWx0LkZBSUxFRCkgewogICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlKTsKICAgICAgfQogICAgICByZXR1cm4gcmVzb3VyY2UucmV0cnlPbkVycm9yKGUpLnRoZW4oZnVuY3Rpb24ocmV0cnkpIHsKICAgICAgICBpZiAocmV0cnkpIHsKICAgICAgICAgIHJlcXVlc3Quc3RhdGUgPSBSZXF1ZXN0U3RhdGVfZGVmYXVsdC5VTklTU1VFRDsKICAgICAgICAgIHJlcXVlc3QuZGVmZXJyZWQgPSB2b2lkIDA7CiAgICAgICAgICByZXR1cm4gZmV0Y2hKc29ucChyZXNvdXJjZSwgY2FsbGJhY2tQYXJhbWV0ZXJOYW1lLCBmdW5jdGlvbk5hbWUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7CiAgICAgIH0pOwogICAgfSk7CiAgfQogIGZ1bmN0aW9uIGNoZWNrQW5kUmVzZXRSZXF1ZXN0KHJlcXVlc3QpIHsKICAgIGlmIChyZXF1ZXN0LnN0YXRlID09PSBSZXF1ZXN0U3RhdGVfZGVmYXVsdC5JU1NVRUQgfHwgcmVxdWVzdC5zdGF0ZSA9PT0gUmVxdWVzdFN0YXRlX2RlZmF1bHQuQUNUSVZFKSB7CiAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3JfZGVmYXVsdCgiVGhlIFJlc291cmNlIGlzIGFscmVhZHkgYmVpbmcgZmV0Y2hlZC4iKTsKICAgIH0KICAgIHJlcXVlc3Quc3RhdGUgPSBSZXF1ZXN0U3RhdGVfZGVmYXVsdC5VTklTU1VFRDsKICAgIHJlcXVlc3QuZGVmZXJyZWQgPSB2b2lkIDA7CiAgfQogIGZ1bmN0aW9uIGRlY29kZURhdGFVcmlUZXh0KGlzQmFzZTY0LCBkYXRhKSB7CiAgICBjb25zdCByZXN1bHQgPSBkZWNvZGVVUklDb21wb25lbnQoZGF0YSk7CiAgICBpZiAoaXNCYXNlNjQpIHsKICAgICAgcmV0dXJuIGF0b2IocmVzdWx0KTsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGZ1bmN0aW9uIGRlY29kZURhdGFVcmlBcnJheUJ1ZmZlcihpc0Jhc2U2NCwgZGF0YSkgewogICAgY29uc3QgYnl0ZVN0cmluZyA9IGRlY29kZURhdGFVcmlUZXh0KGlzQmFzZTY0LCBkYXRhKTsKICAgIGNvbnN0IGJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcihieXRlU3RyaW5nLmxlbmd0aCk7CiAgICBjb25zdCB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyKTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZVN0cmluZy5sZW5ndGg7IGkrKykgewogICAgICB2aWV3W2ldID0gYnl0ZVN0cmluZy5jaGFyQ29kZUF0KGkpOwogICAgfQogICAgcmV0dXJuIGJ1ZmZlcjsKICB9CiAgZnVuY3Rpb24gZGVjb2RlRGF0YVVyaShkYXRhVXJpUmVnZXhSZXN1bHQsIHJlc3BvbnNlVHlwZSkgewogICAgcmVzcG9uc2VUeXBlID0gcmVzcG9uc2VUeXBlID8/ICIiOwogICAgY29uc3QgbWltZVR5cGUgPSBkYXRhVXJpUmVnZXhSZXN1bHRbMV07CiAgICBjb25zdCBpc0Jhc2U2NCA9ICEhZGF0YVVyaVJlZ2V4UmVzdWx0WzJdOwogICAgY29uc3QgZGF0YSA9IGRhdGFVcmlSZWdleFJlc3VsdFszXTsKICAgIGxldCBidWZmZXI7CiAgICBsZXQgcGFyc2VyOwogICAgc3dpdGNoIChyZXNwb25zZVR5cGUpIHsKICAgICAgY2FzZSAiIjoKICAgICAgY2FzZSAidGV4dCI6CiAgICAgICAgcmV0dXJuIGRlY29kZURhdGFVcmlUZXh0KGlzQmFzZTY0LCBkYXRhKTsKICAgICAgY2FzZSAiYXJyYXlidWZmZXIiOgogICAgICAgIHJldHVybiBkZWNvZGVEYXRhVXJpQXJyYXlCdWZmZXIoaXNCYXNlNjQsIGRhdGEpOwogICAgICBjYXNlICJibG9iIjoKICAgICAgICBidWZmZXIgPSBkZWNvZGVEYXRhVXJpQXJyYXlCdWZmZXIoaXNCYXNlNjQsIGRhdGEpOwogICAgICAgIHJldHVybiBuZXcgQmxvYihbYnVmZmVyXSwgewogICAgICAgICAgdHlwZTogbWltZVR5cGUKICAgICAgICB9KTsKICAgICAgY2FzZSAiZG9jdW1lbnQiOgogICAgICAgIHBhcnNlciA9IG5ldyBET01QYXJzZXIoKTsKICAgICAgICByZXR1cm4gcGFyc2VyLnBhcnNlRnJvbVN0cmluZygKICAgICAgICAgIGRlY29kZURhdGFVcmlUZXh0KGlzQmFzZTY0LCBkYXRhKSwKICAgICAgICAgIG1pbWVUeXBlCiAgICAgICAgKTsKICAgICAgY2FzZSAianNvbiI6CiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoZGVjb2RlRGF0YVVyaVRleHQoaXNCYXNlNjQsIGRhdGEpKTsKICAgICAgZGVmYXVsdDoKICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdChgVW5oYW5kbGVkIHJlc3BvbnNlVHlwZTogJHtyZXNwb25zZVR5cGV9YCk7CiAgICB9CiAgfQogIGZ1bmN0aW9uIGxvYWRXaXRoSHR0cFJlcXVlc3QodXJsLCByZXNwb25zZVR5cGUsIG1ldGhvZCwgZGF0YSwgaGVhZGVycywgZGVmZXJyZWQsIG92ZXJyaWRlTWltZVR5cGUpIHsKICAgIGZldGNoKHVybCwgewogICAgICBtZXRob2QsCiAgICAgIGhlYWRlcnMKICAgIH0pLnRoZW4oYXN5bmMgKHJlc3BvbnNlKSA9PiB7CiAgICAgIGlmICghcmVzcG9uc2Uub2spIHsKICAgICAgICBjb25zdCByZXNwb25zZUhlYWRlcnMgPSB7fTsKICAgICAgICByZXNwb25zZS5oZWFkZXJzLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHsKICAgICAgICAgIHJlc3BvbnNlSGVhZGVyc1trZXldID0gdmFsdWU7CiAgICAgICAgfSk7CiAgICAgICAgZGVmZXJyZWQucmVqZWN0KAogICAgICAgICAgbmV3IFJlcXVlc3RFcnJvckV2ZW50X2RlZmF1bHQocmVzcG9uc2Uuc3RhdHVzLCByZXNwb25zZSwgcmVzcG9uc2VIZWFkZXJzKQogICAgICAgICk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHN3aXRjaCAocmVzcG9uc2VUeXBlKSB7CiAgICAgICAgY2FzZSAidGV4dCI6CiAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKHJlc3BvbnNlLnRleHQoKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJqc29uIjoKICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUocmVzcG9uc2UuanNvbigpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKG5ldyBVaW50OEFycmF5KGF3YWl0IHJlc3BvbnNlLmFycmF5QnVmZmVyKCkpLmJ1ZmZlcik7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgfSkuY2F0Y2goKCkgPT4gewogICAgICBkZWZlcnJlZC5yZWplY3QobmV3IFJlcXVlc3RFcnJvckV2ZW50X2RlZmF1bHQoKSk7CiAgICB9KTsKICB9CiAgdmFyIGltcG9ydF91cmlqczYsIHhockJsb2JTdXBwb3J0ZWQsIHN1cHBvcnRzSW1hZ2VCaXRtYXBPcHRpb25zUHJvbWlzZSwgZGF0YVVyaVJlZ2V4Miwgbm9YTUxIdHRwUmVxdWVzdCwgUmVzb3VyY2VfZGVmYXVsdDsKICB2YXIgaW5pdF9SZXNvdXJjZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUmVzb3VyY2UuanMiKCkgewogICAgICBpbXBvcnRfdXJpanM2ID0gX190b0VTTShyZXF1aXJlX1VSSSgpLCAxKTsKICAgICAgaW5pdF9hcHBlbmRGb3J3YXJkU2xhc2goKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2Nsb25lKCk7CiAgICAgIGluaXRfY29tYmluZSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmVyKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfZ2V0QWJzb2x1dGVVcmkoKTsKICAgICAgaW5pdF9nZXRCYXNlVXJpKCk7CiAgICAgIGluaXRfZ2V0RXh0ZW5zaW9uRnJvbVVyaSgpOwogICAgICBpbml0X2dldEltYWdlUGl4ZWxzKCk7CiAgICAgIGluaXRfaXNCbG9iVXJpKCk7CiAgICAgIGluaXRfaXNDcm9zc09yaWdpblVybCgpOwogICAgICBpbml0X2lzRGF0YVVyaSgpOwogICAgICBpbml0X2xvYWRBbmRFeGVjdXRlU2NyaXB0KCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X29iamVjdFRvUXVlcnkoKTsKICAgICAgaW5pdF9xdWVyeVRvT2JqZWN0KCk7CiAgICAgIGluaXRfUmVxdWVzdCgpOwogICAgICBpbml0X1JlcXVlc3RFcnJvckV2ZW50KCk7CiAgICAgIGluaXRfUmVxdWVzdFNjaGVkdWxlcigpOwogICAgICBpbml0X1JlcXVlc3RTdGF0ZSgpOwogICAgICBpbml0X1J1bnRpbWVFcnJvcigpOwogICAgICBpbml0X1RydXN0ZWRTZXJ2ZXJzKCk7CiAgICAgIHhockJsb2JTdXBwb3J0ZWQgPSAoZnVuY3Rpb24oKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGNvbnN0IHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpOwogICAgICAgICAgeGhyLm9wZW4oIkdFVCIsICIjIiwgdHJ1ZSk7CiAgICAgICAgICB4aHIucmVzcG9uc2VUeXBlID0gImJsb2IiOwogICAgICAgICAgcmV0dXJuIHhoci5yZXNwb25zZVR5cGUgPT09ICJibG9iIjsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICB9KSgpOwogICAgICBSZXNvdXJjZS5jcmVhdGVJZk5lZWRlZCA9IGZ1bmN0aW9uKHJlc291cmNlKSB7CiAgICAgICAgaWYgKHJlc291cmNlIGluc3RhbmNlb2YgUmVzb3VyY2UpIHsKICAgICAgICAgIHJldHVybiByZXNvdXJjZS5nZXREZXJpdmVkUmVzb3VyY2UoewogICAgICAgICAgICByZXF1ZXN0OiByZXNvdXJjZS5yZXF1ZXN0CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaWYgKHR5cGVvZiByZXNvdXJjZSAhPT0gInN0cmluZyIpIHsKICAgICAgICAgIHJldHVybiByZXNvdXJjZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBSZXNvdXJjZSh7CiAgICAgICAgICB1cmw6IHJlc291cmNlCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLnN1cHBvcnRzSW1hZ2VCaXRtYXBPcHRpb25zID0gZnVuY3Rpb24oKSB7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChzdXBwb3J0c0ltYWdlQml0bWFwT3B0aW9uc1Byb21pc2UpKSB7CiAgICAgICAgICByZXR1cm4gc3VwcG9ydHNJbWFnZUJpdG1hcE9wdGlvbnNQcm9taXNlOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIGNyZWF0ZUltYWdlQml0bWFwICE9PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICBzdXBwb3J0c0ltYWdlQml0bWFwT3B0aW9uc1Byb21pc2UgPSBQcm9taXNlLnJlc29sdmUoZmFsc2UpOwogICAgICAgICAgcmV0dXJuIHN1cHBvcnRzSW1hZ2VCaXRtYXBPcHRpb25zUHJvbWlzZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgaW1hZ2VEYXRhVXJpID0gImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQUVBQUFBQkNBSUFBQUNRZDFQZUFBQUFCR2RCVFVFQUFFNGczckVpRGdBQUFDQmpTRkpOQUFCNkpnQUFnSVFBQVBvQUFBQ0E2QUFBZFRBQUFPcGdBQUE2bUFBQUYzQ2N1bEU4QUFBQURFbEVRVlFJMTJOZzZHQUFBQUVVQUluZ0UzWmlBQUFBQUVsRlRrU3VRbUNDIjsKICAgICAgICBzdXBwb3J0c0ltYWdlQml0bWFwT3B0aW9uc1Byb21pc2UgPSBSZXNvdXJjZS5mZXRjaEJsb2IoewogICAgICAgICAgdXJsOiBpbWFnZURhdGFVcmkKICAgICAgICB9KS50aGVuKGZ1bmN0aW9uKGJsb2IpIHsKICAgICAgICAgIGNvbnN0IGltYWdlQml0bWFwT3B0aW9ucyA9IHsKICAgICAgICAgICAgaW1hZ2VPcmllbnRhdGlvbjogImZsaXBZIiwKICAgICAgICAgICAgLy8gZGVmYXVsdCBpcyAiZnJvbS1pbWFnZSIKICAgICAgICAgICAgcHJlbXVsdGlwbHlBbHBoYTogIm5vbmUiLAogICAgICAgICAgICAvLyBkZWZhdWx0IGlzICJkZWZhdWx0IgogICAgICAgICAgICBjb2xvclNwYWNlQ29udmVyc2lvbjogIm5vbmUiCiAgICAgICAgICAgIC8vIGRlZmF1bHQgaXMgImRlZmF1bHQiCiAgICAgICAgICB9OwogICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFsKICAgICAgICAgICAgY3JlYXRlSW1hZ2VCaXRtYXAoYmxvYiwgaW1hZ2VCaXRtYXBPcHRpb25zKSwKICAgICAgICAgICAgY3JlYXRlSW1hZ2VCaXRtYXAoYmxvYikKICAgICAgICAgIF0pOwogICAgICAgIH0pLnRoZW4oZnVuY3Rpb24oaW1hZ2VCaXRtYXBzKSB7CiAgICAgICAgICBjb25zdCBjb2xvcldpdGhPcHRpb25zID0gZ2V0SW1hZ2VQaXhlbHNfZGVmYXVsdChpbWFnZUJpdG1hcHNbMF0pOwogICAgICAgICAgY29uc3QgY29sb3JXaXRoRGVmYXVsdHMgPSBnZXRJbWFnZVBpeGVsc19kZWZhdWx0KGltYWdlQml0bWFwc1sxXSk7CiAgICAgICAgICByZXR1cm4gY29sb3JXaXRoT3B0aW9uc1sxXSAhPT0gY29sb3JXaXRoRGVmYXVsdHNbMV07CiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIHN1cHBvcnRzSW1hZ2VCaXRtYXBPcHRpb25zUHJvbWlzZTsKICAgICAgfTsKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoUmVzb3VyY2UsIHsKICAgICAgICAvKioKICAgICAgICAgKiBSZXR1cm5zIHRydWUgaWYgYmxvYnMgYXJlIHN1cHBvcnRlZC4KICAgICAgICAgKgogICAgICAgICAqIEBtZW1iZXJvZiBSZXNvdXJjZQogICAgICAgICAqIEB0eXBlIHtib29sZWFufQogICAgICAgICAqCiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgaXNCbG9iU3VwcG9ydGVkOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4geGhyQmxvYlN1cHBvcnRlZDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhSZXNvdXJjZS5wcm90b3R5cGUsIHsKICAgICAgICAvKioKICAgICAgICAgKiBRdWVyeSBwYXJhbWV0ZXJzIGFwcGVuZGVkIHRvIHRoZSB1cmwuCiAgICAgICAgICoKICAgICAgICAgKiBAbWVtYmVyb2YgUmVzb3VyY2UucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge29iamVjdH0KICAgICAgICAgKgogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIHF1ZXJ5UGFyYW1ldGVyczogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3F1ZXJ5UGFyYW1ldGVyczsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBrZXkvdmFsdWUgcGFpcnMgdXNlZCB0byByZXBsYWNlIHRlbXBsYXRlIHBhcmFtZXRlcnMgaW4gdGhlIHVybC4KICAgICAgICAgKgogICAgICAgICAqIEBtZW1iZXJvZiBSZXNvdXJjZS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7b2JqZWN0fQogICAgICAgICAqCiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgdGVtcGxhdGVWYWx1ZXM6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl90ZW1wbGF0ZVZhbHVlczsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIFRoZSB1cmwgdG8gdGhlIHJlc291cmNlIHdpdGggdGVtcGxhdGUgdmFsdWVzIHJlcGxhY2VkLCBxdWVyeSBzdHJpbmcgYXBwZW5kZWQgYW5kIGVuY29kZWQgYnkgcHJveHkgaWYgb25lIHdhcyBzZXQuCiAgICAgICAgICoKICAgICAgICAgKiBAbWVtYmVyb2YgUmVzb3VyY2UucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge3N0cmluZ30KICAgICAgICAgKi8KICAgICAgICB1cmw6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldFVybENvbXBvbmVudCh0cnVlLCB0cnVlKTsKICAgICAgICAgIH0sCiAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKHZhbHVlKSB7CiAgICAgICAgICAgIHRoaXMucGFyc2VVcmwodmFsdWUsIGZhbHNlLCBmYWxzZSk7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZmlsZSBleHRlbnNpb24gb2YgdGhlIHJlc291cmNlLgogICAgICAgICAqCiAgICAgICAgICogQG1lbWJlcm9mIFJlc291cmNlLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtzdHJpbmd9CiAgICAgICAgICoKICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBleHRlbnNpb246IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBnZXRFeHRlbnNpb25Gcm9tVXJpX2RlZmF1bHQodGhpcy5fdXJsKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIFRydWUgaWYgdGhlIFJlc291cmNlIHJlZmVycyB0byBhIGRhdGEgVVJJLgogICAgICAgICAqCiAgICAgICAgICogQG1lbWJlcm9mIFJlc291cmNlLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtib29sZWFufQogICAgICAgICAqLwogICAgICAgIGlzRGF0YVVyaTogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIGlzRGF0YVVyaV9kZWZhdWx0KHRoaXMuX3VybCk7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBUcnVlIGlmIHRoZSBSZXNvdXJjZSByZWZlcnMgdG8gYSBibG9iIFVSSS4KICAgICAgICAgKgogICAgICAgICAqIEBtZW1iZXJvZiBSZXNvdXJjZS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7Ym9vbGVhbn0KICAgICAgICAgKi8KICAgICAgICBpc0Jsb2JVcmk6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBpc0Jsb2JVcmlfZGVmYXVsdCh0aGlzLl91cmwpOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogVHJ1ZSBpZiB0aGUgUmVzb3VyY2UgcmVmZXJzIHRvIGEgY3Jvc3Mgb3JpZ2luIFVSTC4KICAgICAgICAgKgogICAgICAgICAqIEBtZW1iZXJvZiBSZXNvdXJjZS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7Ym9vbGVhbn0KICAgICAgICAgKi8KICAgICAgICBpc0Nyb3NzT3JpZ2luVXJsOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gaXNDcm9zc09yaWdpblVybF9kZWZhdWx0KHRoaXMuX3VybCk7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBUcnVlIGlmIHRoZSBSZXNvdXJjZSBoYXMgcmVxdWVzdCBoZWFkZXJzLiBUaGlzIGlzIGVxdWl2YWxlbnQgdG8gY2hlY2tpbmcgaWYgdGhlIGhlYWRlcnMgcHJvcGVydHkgaGFzIGFueSBrZXlzLgogICAgICAgICAqCiAgICAgICAgICogQG1lbWJlcm9mIFJlc291cmNlLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtib29sZWFufQogICAgICAgICAqLwogICAgICAgIGhhc0hlYWRlcnM6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLmhlYWRlcnMpLmxlbmd0aCA+IDA7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBjcmVkaXRzIHJlcXVpcmVkIGZvciBhdHRyaWJ1dGlvbiBvZiBhbiBhc3NldC4KICAgICAgICAgKiBAcHJpdmF0ZQogICAgICAgICAqLwogICAgICAgIGNyZWRpdHM6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9jcmVkaXRzOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIFJlc291cmNlLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiB0aGlzLmdldFVybENvbXBvbmVudCh0cnVlLCB0cnVlKTsKICAgICAgfTsKICAgICAgUmVzb3VyY2UucHJvdG90eXBlLnBhcnNlVXJsID0gZnVuY3Rpb24odXJsLCBtZXJnZSwgcHJlc2VydmVRdWVyeSwgYmFzZVVybCkgewogICAgICAgIGxldCB1cmkgPSBuZXcgaW1wb3J0X3VyaWpzNi5kZWZhdWx0KHVybCk7CiAgICAgICAgY29uc3QgcXVlcnkgPSBwYXJzZVF1ZXJ5U3RyaW5nKHVyaS5xdWVyeSgpKTsKICAgICAgICB0aGlzLl9xdWVyeVBhcmFtZXRlcnMgPSBtZXJnZSA/IGNvbWJpbmVRdWVyeVBhcmFtZXRlcnMocXVlcnksIHRoaXMucXVlcnlQYXJhbWV0ZXJzLCBwcmVzZXJ2ZVF1ZXJ5KSA6IHF1ZXJ5OwogICAgICAgIHVyaS5zZWFyY2goIiIpOwogICAgICAgIHVyaS5mcmFnbWVudCgiIik7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChiYXNlVXJsKSAmJiB1cmkuc2NoZW1lKCkgPT09ICIiKSB7CiAgICAgICAgICB1cmkgPSB1cmkuYWJzb2x1dGVUbyhnZXRBYnNvbHV0ZVVyaV9kZWZhdWx0KGJhc2VVcmwpKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5fdXJsID0gdXJpLnRvU3RyaW5nKCk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLnByb3RvdHlwZS5nZXRVcmxDb21wb25lbnQgPSBmdW5jdGlvbihxdWVyeSwgcHJveHkpIHsKICAgICAgICBpZiAodGhpcy5pc0RhdGFVcmkpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl91cmw7CiAgICAgICAgfQogICAgICAgIGxldCB1cmwgPSB0aGlzLl91cmw7CiAgICAgICAgaWYgKHF1ZXJ5KSB7CiAgICAgICAgICB1cmwgPSBgJHt1cmx9JHtzdHJpbmdpZnlRdWVyeSh0aGlzLnF1ZXJ5UGFyYW1ldGVycyl9YDsKICAgICAgICB9CiAgICAgICAgdXJsID0gdXJsLnJlcGxhY2UoLyU3Qi9nLCAieyIpLnJlcGxhY2UoLyU3RC9nLCAifSIpOwogICAgICAgIGNvbnN0IHRlbXBsYXRlVmFsdWVzID0gdGhpcy5fdGVtcGxhdGVWYWx1ZXM7CiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHRlbXBsYXRlVmFsdWVzKS5sZW5ndGggPiAwKSB7CiAgICAgICAgICB1cmwgPSB1cmwucmVwbGFjZSgveyguKj8pfS9nLCBmdW5jdGlvbihtYXRjaCwga2V5KSB7CiAgICAgICAgICAgIGNvbnN0IHJlcGxhY2VtZW50ID0gdGVtcGxhdGVWYWx1ZXNba2V5XTsKICAgICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChyZXBsYWNlbWVudCkpIHsKICAgICAgICAgICAgICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KHJlcGxhY2VtZW50KTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbWF0Y2g7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaWYgKHByb3h5ICYmIGRlZmluZWRfZGVmYXVsdCh0aGlzLnByb3h5KSkgewogICAgICAgICAgdXJsID0gdGhpcy5wcm94eS5nZXRVUkwodXJsKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHVybDsKICAgICAgfTsKICAgICAgUmVzb3VyY2UucHJvdG90eXBlLnNldFF1ZXJ5UGFyYW1ldGVycyA9IGZ1bmN0aW9uKHBhcmFtcywgdXNlQXNEZWZhdWx0KSB7CiAgICAgICAgaWYgKHVzZUFzRGVmYXVsdCkgewogICAgICAgICAgdGhpcy5fcXVlcnlQYXJhbWV0ZXJzID0gY29tYmluZVF1ZXJ5UGFyYW1ldGVycygKICAgICAgICAgICAgdGhpcy5fcXVlcnlQYXJhbWV0ZXJzLAogICAgICAgICAgICBwYXJhbXMsCiAgICAgICAgICAgIGZhbHNlCiAgICAgICAgICApOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLl9xdWVyeVBhcmFtZXRlcnMgPSBjb21iaW5lUXVlcnlQYXJhbWV0ZXJzKAogICAgICAgICAgICBwYXJhbXMsCiAgICAgICAgICAgIHRoaXMuX3F1ZXJ5UGFyYW1ldGVycywKICAgICAgICAgICAgZmFsc2UKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICB9OwogICAgICBSZXNvdXJjZS5wcm90b3R5cGUuYXBwZW5kUXVlcnlQYXJhbWV0ZXJzID0gZnVuY3Rpb24ocGFyYW1zKSB7CiAgICAgICAgdGhpcy5fcXVlcnlQYXJhbWV0ZXJzID0gY29tYmluZVF1ZXJ5UGFyYW1ldGVycygKICAgICAgICAgIHBhcmFtcywKICAgICAgICAgIHRoaXMuX3F1ZXJ5UGFyYW1ldGVycywKICAgICAgICAgIHRydWUKICAgICAgICApOwogICAgICB9OwogICAgICBSZXNvdXJjZS5wcm90b3R5cGUuc2V0VGVtcGxhdGVWYWx1ZXMgPSBmdW5jdGlvbih0ZW1wbGF0ZSwgdXNlQXNEZWZhdWx0KSB7CiAgICAgICAgaWYgKHVzZUFzRGVmYXVsdCkgewogICAgICAgICAgdGhpcy5fdGVtcGxhdGVWYWx1ZXMgPSBjb21iaW5lX2RlZmF1bHQodGhpcy5fdGVtcGxhdGVWYWx1ZXMsIHRlbXBsYXRlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhpcy5fdGVtcGxhdGVWYWx1ZXMgPSBjb21iaW5lX2RlZmF1bHQodGVtcGxhdGUsIHRoaXMuX3RlbXBsYXRlVmFsdWVzKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIFJlc291cmNlLnByb3RvdHlwZS5nZXREZXJpdmVkUmVzb3VyY2UgPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgY29uc3QgcmVzb3VyY2UgPSB0aGlzLmNsb25lKCk7CiAgICAgICAgcmVzb3VyY2UuX3JldHJ5Q291bnQgPSAwOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob3B0aW9ucy51cmwpKSB7CiAgICAgICAgICBjb25zdCBwcmVzZXJ2ZVF1ZXJ5ID0gb3B0aW9ucy5wcmVzZXJ2ZVF1ZXJ5UGFyYW1ldGVycyA/PyBmYWxzZTsKICAgICAgICAgIHJlc291cmNlLnBhcnNlVXJsKG9wdGlvbnMudXJsLCB0cnVlLCBwcmVzZXJ2ZVF1ZXJ5LCB0aGlzLl91cmwpOwogICAgICAgIH0KICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMucXVlcnlQYXJhbWV0ZXJzKSkgewogICAgICAgICAgcmVzb3VyY2UuX3F1ZXJ5UGFyYW1ldGVycyA9IGNvbWJpbmVfZGVmYXVsdCgKICAgICAgICAgICAgb3B0aW9ucy5xdWVyeVBhcmFtZXRlcnMsCiAgICAgICAgICAgIHJlc291cmNlLnF1ZXJ5UGFyYW1ldGVycwogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChvcHRpb25zLnRlbXBsYXRlVmFsdWVzKSkgewogICAgICAgICAgcmVzb3VyY2UuX3RlbXBsYXRlVmFsdWVzID0gY29tYmluZV9kZWZhdWx0KAogICAgICAgICAgICBvcHRpb25zLnRlbXBsYXRlVmFsdWVzLAogICAgICAgICAgICByZXNvdXJjZS50ZW1wbGF0ZVZhbHVlcwogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChvcHRpb25zLmhlYWRlcnMpKSB7CiAgICAgICAgICByZXNvdXJjZS5oZWFkZXJzID0gY29tYmluZV9kZWZhdWx0KG9wdGlvbnMuaGVhZGVycywgcmVzb3VyY2UuaGVhZGVycyk7CiAgICAgICAgfQogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob3B0aW9ucy5wcm94eSkpIHsKICAgICAgICAgIHJlc291cmNlLnByb3h5ID0gb3B0aW9ucy5wcm94eTsKICAgICAgICB9CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChvcHRpb25zLnJlcXVlc3QpKSB7CiAgICAgICAgICByZXNvdXJjZS5yZXF1ZXN0ID0gb3B0aW9ucy5yZXF1ZXN0OwogICAgICAgIH0KICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMucmV0cnlDYWxsYmFjaykpIHsKICAgICAgICAgIHJlc291cmNlLnJldHJ5Q2FsbGJhY2sgPSBvcHRpb25zLnJldHJ5Q2FsbGJhY2s7CiAgICAgICAgfQogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob3B0aW9ucy5yZXRyeUF0dGVtcHRzKSkgewogICAgICAgICAgcmVzb3VyY2UucmV0cnlBdHRlbXB0cyA9IG9wdGlvbnMucmV0cnlBdHRlbXB0czsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc291cmNlOwogICAgICB9OwogICAgICBSZXNvdXJjZS5wcm90b3R5cGUucmV0cnlPbkVycm9yID0gZnVuY3Rpb24oZXJyb3IpIHsKICAgICAgICBjb25zdCByZXRyeUNhbGxiYWNrID0gdGhpcy5yZXRyeUNhbGxiYWNrOwogICAgICAgIGlmICh0eXBlb2YgcmV0cnlDYWxsYmFjayAhPT0gImZ1bmN0aW9uIiB8fCB0aGlzLl9yZXRyeUNvdW50ID49IHRoaXMucmV0cnlBdHRlbXB0cykgewogICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHRoYXQgPSB0aGlzOwogICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmV0cnlDYWxsYmFjayh0aGlzLCBlcnJvcikpLnRoZW4oZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgICArK3RoYXQuX3JldHJ5Q291bnQ7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0pOwogICAgICB9OwogICAgICBSZXNvdXJjZS5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFJlc291cmNlKHsKICAgICAgICAgICAgdXJsOiB0aGlzLl91cmwsCiAgICAgICAgICAgIHF1ZXJ5UGFyYW1ldGVyczogdGhpcy5xdWVyeVBhcmFtZXRlcnMsCiAgICAgICAgICAgIHRlbXBsYXRlVmFsdWVzOiB0aGlzLnRlbXBsYXRlVmFsdWVzLAogICAgICAgICAgICBoZWFkZXJzOiB0aGlzLmhlYWRlcnMsCiAgICAgICAgICAgIHByb3h5OiB0aGlzLnByb3h5LAogICAgICAgICAgICByZXRyeUNhbGxiYWNrOiB0aGlzLnJldHJ5Q2FsbGJhY2ssCiAgICAgICAgICAgIHJldHJ5QXR0ZW1wdHM6IHRoaXMucmV0cnlBdHRlbXB0cywKICAgICAgICAgICAgcmVxdWVzdDogdGhpcy5yZXF1ZXN0LmNsb25lKCksCiAgICAgICAgICAgIHBhcnNlVXJsOiBmYWxzZSwKICAgICAgICAgICAgY3JlZGl0czogZGVmaW5lZF9kZWZhdWx0KHRoaXMuY3JlZGl0cykgPyB0aGlzLmNyZWRpdHMuc2xpY2UoKSA6IHZvaWQgMAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5fdXJsID0gdGhpcy5fdXJsOwogICAgICAgIHJlc3VsdC5fcXVlcnlQYXJhbWV0ZXJzID0gY2xvbmVfZGVmYXVsdCh0aGlzLl9xdWVyeVBhcmFtZXRlcnMpOwogICAgICAgIHJlc3VsdC5fdGVtcGxhdGVWYWx1ZXMgPSBjbG9uZV9kZWZhdWx0KHRoaXMuX3RlbXBsYXRlVmFsdWVzKTsKICAgICAgICByZXN1bHQuaGVhZGVycyA9IGNsb25lX2RlZmF1bHQodGhpcy5oZWFkZXJzKTsKICAgICAgICByZXN1bHQucHJveHkgPSB0aGlzLnByb3h5OwogICAgICAgIHJlc3VsdC5yZXRyeUNhbGxiYWNrID0gdGhpcy5yZXRyeUNhbGxiYWNrOwogICAgICAgIHJlc3VsdC5yZXRyeUF0dGVtcHRzID0gdGhpcy5yZXRyeUF0dGVtcHRzOwogICAgICAgIHJlc3VsdC5fcmV0cnlDb3VudCA9IDA7CiAgICAgICAgcmVzdWx0LnJlcXVlc3QgPSB0aGlzLnJlcXVlc3QuY2xvbmUoKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBSZXNvdXJjZS5wcm90b3R5cGUuZ2V0QmFzZVVyaSA9IGZ1bmN0aW9uKGluY2x1ZGVRdWVyeSkgewogICAgICAgIHJldHVybiBnZXRCYXNlVXJpX2RlZmF1bHQodGhpcy5nZXRVcmxDb21wb25lbnQoaW5jbHVkZVF1ZXJ5KSwgaW5jbHVkZVF1ZXJ5KTsKICAgICAgfTsKICAgICAgUmVzb3VyY2UucHJvdG90eXBlLmFwcGVuZEZvcndhcmRTbGFzaCA9IGZ1bmN0aW9uKCkgewogICAgICAgIHRoaXMuX3VybCA9IGFwcGVuZEZvcndhcmRTbGFzaF9kZWZhdWx0KHRoaXMuX3VybCk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLnByb3RvdHlwZS5mZXRjaEFycmF5QnVmZmVyID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZmV0Y2goewogICAgICAgICAgcmVzcG9uc2VUeXBlOiAiYXJyYXlidWZmZXIiCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLmZldGNoQXJyYXlCdWZmZXIgPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgY29uc3QgcmVzb3VyY2UgPSBuZXcgUmVzb3VyY2Uob3B0aW9ucyk7CiAgICAgICAgcmV0dXJuIHJlc291cmNlLmZldGNoQXJyYXlCdWZmZXIoKTsKICAgICAgfTsKICAgICAgUmVzb3VyY2UucHJvdG90eXBlLmZldGNoQmxvYiA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiB0aGlzLmZldGNoKHsKICAgICAgICAgIHJlc3BvbnNlVHlwZTogImJsb2IiCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLmZldGNoQmxvYiA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBjb25zdCByZXNvdXJjZSA9IG5ldyBSZXNvdXJjZShvcHRpb25zKTsKICAgICAgICByZXR1cm4gcmVzb3VyY2UuZmV0Y2hCbG9iKCk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLnByb3RvdHlwZS5mZXRjaEltYWdlID0gZnVuY3Rpb24ob3B0aW9ucykgewogICAgICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgICAgICBjb25zdCBwcmVmZXJJbWFnZUJpdG1hcCA9IG9wdGlvbnMucHJlZmVySW1hZ2VCaXRtYXAgPz8gZmFsc2U7CiAgICAgICAgY29uc3QgcHJlZmVyQmxvYiA9IG9wdGlvbnMucHJlZmVyQmxvYiA/PyBmYWxzZTsKICAgICAgICBjb25zdCBmbGlwWSA9IG9wdGlvbnMuZmxpcFkgPz8gZmFsc2U7CiAgICAgICAgY29uc3Qgc2tpcENvbG9yU3BhY2VDb252ZXJzaW9uID0gb3B0aW9ucy5za2lwQ29sb3JTcGFjZUNvbnZlcnNpb24gPz8gZmFsc2U7CiAgICAgICAgY2hlY2tBbmRSZXNldFJlcXVlc3QodGhpcy5yZXF1ZXN0KTsKICAgICAgICBpZiAoIXhockJsb2JTdXBwb3J0ZWQgfHwgdGhpcy5pc0RhdGFVcmkgfHwgdGhpcy5pc0Jsb2JVcmkgfHwgIXRoaXMuaGFzSGVhZGVycyAmJiAhcHJlZmVyQmxvYikgewogICAgICAgICAgcmV0dXJuIGZldGNoSW1hZ2UoewogICAgICAgICAgICByZXNvdXJjZTogdGhpcywKICAgICAgICAgICAgZmxpcFksCiAgICAgICAgICAgIHNraXBDb2xvclNwYWNlQ29udmVyc2lvbiwKICAgICAgICAgICAgcHJlZmVySW1hZ2VCaXRtYXAKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBjb25zdCBibG9iUHJvbWlzZSA9IHRoaXMuZmV0Y2hCbG9iKCk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYmxvYlByb21pc2UpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGxldCBzdXBwb3J0c0ltYWdlQml0bWFwOwogICAgICAgIGxldCB1c2VJbWFnZUJpdG1hcDsKICAgICAgICBsZXQgZ2VuZXJhdGVkQmxvYlJlc291cmNlOwogICAgICAgIGxldCBnZW5lcmF0ZWRCbG9iOwogICAgICAgIHJldHVybiBSZXNvdXJjZS5zdXBwb3J0c0ltYWdlQml0bWFwT3B0aW9ucygpLnRoZW4oZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgICBzdXBwb3J0c0ltYWdlQml0bWFwID0gcmVzdWx0OwogICAgICAgICAgdXNlSW1hZ2VCaXRtYXAgPSBzdXBwb3J0c0ltYWdlQml0bWFwICYmIHByZWZlckltYWdlQml0bWFwOwogICAgICAgICAgcmV0dXJuIGJsb2JQcm9taXNlOwogICAgICAgIH0pLnRoZW4oZnVuY3Rpb24oYmxvYikgewogICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYmxvYikpIHsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgfQogICAgICAgICAgZ2VuZXJhdGVkQmxvYiA9IGJsb2I7CiAgICAgICAgICBpZiAodXNlSW1hZ2VCaXRtYXApIHsKICAgICAgICAgICAgcmV0dXJuIFJlc291cmNlLmNyZWF0ZUltYWdlQml0bWFwRnJvbUJsb2IoYmxvYiwgewogICAgICAgICAgICAgIGZsaXBZLAogICAgICAgICAgICAgIHByZW11bHRpcGx5QWxwaGE6IGZhbHNlLAogICAgICAgICAgICAgIHNraXBDb2xvclNwYWNlQ29udmVyc2lvbgogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGJsb2JVcmwgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTsKICAgICAgICAgIGdlbmVyYXRlZEJsb2JSZXNvdXJjZSA9IG5ldyBSZXNvdXJjZSh7CiAgICAgICAgICAgIHVybDogYmxvYlVybAogICAgICAgICAgfSk7CiAgICAgICAgICByZXR1cm4gZmV0Y2hJbWFnZSh7CiAgICAgICAgICAgIHJlc291cmNlOiBnZW5lcmF0ZWRCbG9iUmVzb3VyY2UsCiAgICAgICAgICAgIGZsaXBZLAogICAgICAgICAgICBza2lwQ29sb3JTcGFjZUNvbnZlcnNpb24sCiAgICAgICAgICAgIHByZWZlckltYWdlQml0bWFwOiBmYWxzZQogICAgICAgICAgfSk7CiAgICAgICAgfSkudGhlbihmdW5jdGlvbihpbWFnZSkgewogICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaW1hZ2UpKSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIGltYWdlLmJsb2IgPSBnZW5lcmF0ZWRCbG9iOwogICAgICAgICAgaWYgKHVzZUltYWdlQml0bWFwKSB7CiAgICAgICAgICAgIHJldHVybiBpbWFnZTsKICAgICAgICAgIH0KICAgICAgICAgIHdpbmRvdy5VUkwucmV2b2tlT2JqZWN0VVJMKGdlbmVyYXRlZEJsb2JSZXNvdXJjZS51cmwpOwogICAgICAgICAgcmV0dXJuIGltYWdlOwogICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uKGVycm9yKSB7CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGdlbmVyYXRlZEJsb2JSZXNvdXJjZSkpIHsKICAgICAgICAgICAgd2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwoZ2VuZXJhdGVkQmxvYlJlc291cmNlLnVybCk7CiAgICAgICAgICB9CiAgICAgICAgICBlcnJvci5ibG9iID0gZ2VuZXJhdGVkQmxvYjsKICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcik7CiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLmZldGNoSW1hZ2UgPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgY29uc3QgcmVzb3VyY2UgPSBuZXcgUmVzb3VyY2Uob3B0aW9ucyk7CiAgICAgICAgcmV0dXJuIHJlc291cmNlLmZldGNoSW1hZ2UoewogICAgICAgICAgZmxpcFk6IG9wdGlvbnMuZmxpcFksCiAgICAgICAgICBza2lwQ29sb3JTcGFjZUNvbnZlcnNpb246IG9wdGlvbnMuc2tpcENvbG9yU3BhY2VDb252ZXJzaW9uLAogICAgICAgICAgcHJlZmVyQmxvYjogb3B0aW9ucy5wcmVmZXJCbG9iLAogICAgICAgICAgcHJlZmVySW1hZ2VCaXRtYXA6IG9wdGlvbnMucHJlZmVySW1hZ2VCaXRtYXAKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgUmVzb3VyY2UucHJvdG90eXBlLmZldGNoVGV4dCA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiB0aGlzLmZldGNoKHsKICAgICAgICAgIHJlc3BvbnNlVHlwZTogInRleHQiCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLmZldGNoVGV4dCA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBjb25zdCByZXNvdXJjZSA9IG5ldyBSZXNvdXJjZShvcHRpb25zKTsKICAgICAgICByZXR1cm4gcmVzb3VyY2UuZmV0Y2hUZXh0KCk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLnByb3RvdHlwZS5mZXRjaEpzb24gPSBmdW5jdGlvbigpIHsKICAgICAgICBjb25zdCBwcm9taXNlID0gdGhpcy5mZXRjaCh7CiAgICAgICAgICByZXNwb25zZVR5cGU6ICJ0ZXh0IiwKICAgICAgICAgIGhlYWRlcnM6IHsKICAgICAgICAgICAgQWNjZXB0OiAiYXBwbGljYXRpb24vanNvbiwqLyo7cT0wLjAxIgogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHByb21pc2UpKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKSB7CiAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh2YWx1ZSkpIHsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UodmFsdWUpOwogICAgICAgIH0pOwogICAgICB9OwogICAgICBSZXNvdXJjZS5mZXRjaEpzb24gPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgY29uc3QgcmVzb3VyY2UgPSBuZXcgUmVzb3VyY2Uob3B0aW9ucyk7CiAgICAgICAgcmV0dXJuIHJlc291cmNlLmZldGNoSnNvbigpOwogICAgICB9OwogICAgICBSZXNvdXJjZS5wcm90b3R5cGUuZmV0Y2hYTUwgPSBmdW5jdGlvbigpIHsKICAgICAgICByZXR1cm4gdGhpcy5mZXRjaCh7CiAgICAgICAgICByZXNwb25zZVR5cGU6ICJkb2N1bWVudCIsCiAgICAgICAgICBvdmVycmlkZU1pbWVUeXBlOiAidGV4dC94bWwiCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLmZldGNoWE1MID0gZnVuY3Rpb24ob3B0aW9ucykgewogICAgICAgIGNvbnN0IHJlc291cmNlID0gbmV3IFJlc291cmNlKG9wdGlvbnMpOwogICAgICAgIHJldHVybiByZXNvdXJjZS5mZXRjaFhNTCgpOwogICAgICB9OwogICAgICBSZXNvdXJjZS5wcm90b3R5cGUuZmV0Y2hKc29ucCA9IGZ1bmN0aW9uKGNhbGxiYWNrUGFyYW1ldGVyTmFtZSkgewogICAgICAgIGNhbGxiYWNrUGFyYW1ldGVyTmFtZSA9IGNhbGxiYWNrUGFyYW1ldGVyTmFtZSA/PyAiY2FsbGJhY2siOwogICAgICAgIGNoZWNrQW5kUmVzZXRSZXF1ZXN0KHRoaXMucmVxdWVzdCk7CiAgICAgICAgbGV0IGZ1bmN0aW9uTmFtZTsKICAgICAgICBkbyB7CiAgICAgICAgICBmdW5jdGlvbk5hbWUgPSBgbG9hZEpzb25wJHtNYXRoX2RlZmF1bHQubmV4dFJhbmRvbU51bWJlcigpLnRvU3RyaW5nKCkuc3Vic3RyaW5nKDIsIDgpfWA7CiAgICAgICAgfSB3aGlsZSAoZGVmaW5lZF9kZWZhdWx0KHdpbmRvd1tmdW5jdGlvbk5hbWVdKSk7CiAgICAgICAgcmV0dXJuIGZldGNoSnNvbnAodGhpcywgY2FsbGJhY2tQYXJhbWV0ZXJOYW1lLCBmdW5jdGlvbk5hbWUpOwogICAgICB9OwogICAgICBSZXNvdXJjZS5mZXRjaEpzb25wID0gZnVuY3Rpb24ob3B0aW9ucykgewogICAgICAgIGNvbnN0IHJlc291cmNlID0gbmV3IFJlc291cmNlKG9wdGlvbnMpOwogICAgICAgIHJldHVybiByZXNvdXJjZS5mZXRjaEpzb25wKG9wdGlvbnMuY2FsbGJhY2tQYXJhbWV0ZXJOYW1lKTsKICAgICAgfTsKICAgICAgUmVzb3VyY2UucHJvdG90eXBlLl9tYWtlUmVxdWVzdCA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBjb25zdCByZXNvdXJjZSA9IHRoaXM7CiAgICAgICAgY2hlY2tBbmRSZXNldFJlcXVlc3QocmVzb3VyY2UucmVxdWVzdCk7CiAgICAgICAgY29uc3QgcmVxdWVzdCA9IHJlc291cmNlLnJlcXVlc3Q7CiAgICAgICAgY29uc3QgdXJsID0gcmVzb3VyY2UudXJsOwogICAgICAgIHJlcXVlc3QudXJsID0gdXJsOwogICAgICAgIHJlcXVlc3QucmVxdWVzdEZ1bmN0aW9uID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICBjb25zdCByZXNwb25zZVR5cGUgPSBvcHRpb25zLnJlc3BvbnNlVHlwZTsKICAgICAgICAgIGNvbnN0IGhlYWRlcnMgPSBjb21iaW5lX2RlZmF1bHQob3B0aW9ucy5oZWFkZXJzLCByZXNvdXJjZS5oZWFkZXJzKTsKICAgICAgICAgIGNvbnN0IG92ZXJyaWRlTWltZVR5cGUgPSBvcHRpb25zLm92ZXJyaWRlTWltZVR5cGU7CiAgICAgICAgICBjb25zdCBtZXRob2QgPSBvcHRpb25zLm1ldGhvZDsKICAgICAgICAgIGNvbnN0IGRhdGEgPSBvcHRpb25zLmRhdGE7CiAgICAgICAgICBjb25zdCBkZWZlcnJlZCA9IGRlZmVyX2RlZmF1bHQoKTsKICAgICAgICAgIGNvbnN0IHhociA9IFJlc291cmNlLl9JbXBsZW1lbnRhdGlvbnMubG9hZFdpdGhYaHIoCiAgICAgICAgICAgIHVybCwKICAgICAgICAgICAgcmVzcG9uc2VUeXBlLAogICAgICAgICAgICBtZXRob2QsCiAgICAgICAgICAgIGRhdGEsCiAgICAgICAgICAgIGhlYWRlcnMsCiAgICAgICAgICAgIGRlZmVycmVkLAogICAgICAgICAgICBvdmVycmlkZU1pbWVUeXBlCiAgICAgICAgICApOwogICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdCh4aHIpICYmIGRlZmluZWRfZGVmYXVsdCh4aHIuYWJvcnQpKSB7CiAgICAgICAgICAgIHJlcXVlc3QuY2FuY2VsRnVuY3Rpb24gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICB4aHIuYWJvcnQoKTsKICAgICAgICAgICAgfTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlOwogICAgICAgIH07CiAgICAgICAgY29uc3QgcHJvbWlzZSA9IFJlcXVlc3RTY2hlZHVsZXJfZGVmYXVsdC5yZXF1ZXN0KHJlcXVlc3QpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHByb21pc2UpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIHJldHVybiBwcm9taXNlLnRoZW4oZnVuY3Rpb24oZGF0YSkgewogICAgICAgICAgcmVxdWVzdC5jYW5jZWxGdW5jdGlvbiA9IHZvaWQgMDsKICAgICAgICAgIHJldHVybiBkYXRhOwogICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uKGUpIHsKICAgICAgICAgIHJlcXVlc3QuY2FuY2VsRnVuY3Rpb24gPSB2b2lkIDA7CiAgICAgICAgICBpZiAocmVxdWVzdC5zdGF0ZSAhPT0gUmVxdWVzdFN0YXRlX2RlZmF1bHQuRkFJTEVEKSB7CiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiByZXNvdXJjZS5yZXRyeU9uRXJyb3IoZSkudGhlbihmdW5jdGlvbihyZXRyeSkgewogICAgICAgICAgICBpZiAocmV0cnkpIHsKICAgICAgICAgICAgICByZXF1ZXN0LnN0YXRlID0gUmVxdWVzdFN0YXRlX2RlZmF1bHQuVU5JU1NVRUQ7CiAgICAgICAgICAgICAgcmVxdWVzdC5kZWZlcnJlZCA9IHZvaWQgMDsKICAgICAgICAgICAgICByZXR1cm4gcmVzb3VyY2UuZmV0Y2gob3B0aW9ucyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGUpOwogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIGRhdGFVcmlSZWdleDIgPSAvXmRhdGE6KC4qPykoO2Jhc2U2NCk/LCguKikkLzsKICAgICAgUmVzb3VyY2UucHJvdG90eXBlLmZldGNoID0gZnVuY3Rpb24ob3B0aW9ucykgewogICAgICAgIG9wdGlvbnMgPSBkZWZhdWx0Q2xvbmUob3B0aW9ucywge30pOwogICAgICAgIG9wdGlvbnMubWV0aG9kID0gIkdFVCI7CiAgICAgICAgcmV0dXJuIHRoaXMuX21ha2VSZXF1ZXN0KG9wdGlvbnMpOwogICAgICB9OwogICAgICBSZXNvdXJjZS5mZXRjaCA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBjb25zdCByZXNvdXJjZSA9IG5ldyBSZXNvdXJjZShvcHRpb25zKTsKICAgICAgICByZXR1cm4gcmVzb3VyY2UuZmV0Y2goewogICAgICAgICAgLy8gTWFrZSBjb3B5IG9mIGp1c3QgdGhlIG5lZWRlZCBmaWVsZHMgYmVjYXVzZSBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgdG8gYm90aCB0aGUgY29uc3RydWN0b3IgYW5kIHRvIGZldGNoCiAgICAgICAgICByZXNwb25zZVR5cGU6IG9wdGlvbnMucmVzcG9uc2VUeXBlLAogICAgICAgICAgb3ZlcnJpZGVNaW1lVHlwZTogb3B0aW9ucy5vdmVycmlkZU1pbWVUeXBlCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLnByb3RvdHlwZS5kZWxldGUgPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgb3B0aW9ucyA9IGRlZmF1bHRDbG9uZShvcHRpb25zLCB7fSk7CiAgICAgICAgb3B0aW9ucy5tZXRob2QgPSAiREVMRVRFIjsKICAgICAgICByZXR1cm4gdGhpcy5fbWFrZVJlcXVlc3Qob3B0aW9ucyk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLmRlbGV0ZSA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBjb25zdCByZXNvdXJjZSA9IG5ldyBSZXNvdXJjZShvcHRpb25zKTsKICAgICAgICByZXR1cm4gcmVzb3VyY2UuZGVsZXRlKHsKICAgICAgICAgIC8vIE1ha2UgY29weSBvZiBqdXN0IHRoZSBuZWVkZWQgZmllbGRzIGJlY2F1c2UgaGVhZGVycyBjYW4gYmUgcGFzc2VkIHRvIGJvdGggdGhlIGNvbnN0cnVjdG9yIGFuZCB0byBmZXRjaAogICAgICAgICAgcmVzcG9uc2VUeXBlOiBvcHRpb25zLnJlc3BvbnNlVHlwZSwKICAgICAgICAgIG92ZXJyaWRlTWltZVR5cGU6IG9wdGlvbnMub3ZlcnJpZGVNaW1lVHlwZSwKICAgICAgICAgIGRhdGE6IG9wdGlvbnMuZGF0YQogICAgICAgIH0pOwogICAgICB9OwogICAgICBSZXNvdXJjZS5wcm90b3R5cGUuaGVhZCA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBvcHRpb25zID0gZGVmYXVsdENsb25lKG9wdGlvbnMsIHt9KTsKICAgICAgICBvcHRpb25zLm1ldGhvZCA9ICJIRUFEIjsKICAgICAgICByZXR1cm4gdGhpcy5fbWFrZVJlcXVlc3Qob3B0aW9ucyk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLmhlYWQgPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgY29uc3QgcmVzb3VyY2UgPSBuZXcgUmVzb3VyY2Uob3B0aW9ucyk7CiAgICAgICAgcmV0dXJuIHJlc291cmNlLmhlYWQoewogICAgICAgICAgLy8gTWFrZSBjb3B5IG9mIGp1c3QgdGhlIG5lZWRlZCBmaWVsZHMgYmVjYXVzZSBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgdG8gYm90aCB0aGUgY29uc3RydWN0b3IgYW5kIHRvIGZldGNoCiAgICAgICAgICByZXNwb25zZVR5cGU6IG9wdGlvbnMucmVzcG9uc2VUeXBlLAogICAgICAgICAgb3ZlcnJpZGVNaW1lVHlwZTogb3B0aW9ucy5vdmVycmlkZU1pbWVUeXBlCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLnByb3RvdHlwZS5vcHRpb25zID0gZnVuY3Rpb24ob3B0aW9ucykgewogICAgICAgIG9wdGlvbnMgPSBkZWZhdWx0Q2xvbmUob3B0aW9ucywge30pOwogICAgICAgIG9wdGlvbnMubWV0aG9kID0gIk9QVElPTlMiOwogICAgICAgIHJldHVybiB0aGlzLl9tYWtlUmVxdWVzdChvcHRpb25zKTsKICAgICAgfTsKICAgICAgUmVzb3VyY2Uub3B0aW9ucyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBjb25zdCByZXNvdXJjZSA9IG5ldyBSZXNvdXJjZShvcHRpb25zKTsKICAgICAgICByZXR1cm4gcmVzb3VyY2Uub3B0aW9ucyh7CiAgICAgICAgICAvLyBNYWtlIGNvcHkgb2YganVzdCB0aGUgbmVlZGVkIGZpZWxkcyBiZWNhdXNlIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCB0byBib3RoIHRoZSBjb25zdHJ1Y3RvciBhbmQgdG8gZmV0Y2gKICAgICAgICAgIHJlc3BvbnNlVHlwZTogb3B0aW9ucy5yZXNwb25zZVR5cGUsCiAgICAgICAgICBvdmVycmlkZU1pbWVUeXBlOiBvcHRpb25zLm92ZXJyaWRlTWltZVR5cGUKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgUmVzb3VyY2UucHJvdG90eXBlLnBvc3QgPSBmdW5jdGlvbihkYXRhLCBvcHRpb25zKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJkYXRhIiwgZGF0YSk7CiAgICAgICAgb3B0aW9ucyA9IGRlZmF1bHRDbG9uZShvcHRpb25zLCB7fSk7CiAgICAgICAgb3B0aW9ucy5tZXRob2QgPSAiUE9TVCI7CiAgICAgICAgb3B0aW9ucy5kYXRhID0gZGF0YTsKICAgICAgICByZXR1cm4gdGhpcy5fbWFrZVJlcXVlc3Qob3B0aW9ucyk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLnBvc3QgPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgY29uc3QgcmVzb3VyY2UgPSBuZXcgUmVzb3VyY2Uob3B0aW9ucyk7CiAgICAgICAgcmV0dXJuIHJlc291cmNlLnBvc3Qob3B0aW9ucy5kYXRhLCB7CiAgICAgICAgICAvLyBNYWtlIGNvcHkgb2YganVzdCB0aGUgbmVlZGVkIGZpZWxkcyBiZWNhdXNlIGhlYWRlcnMgY2FuIGJlIHBhc3NlZCB0byBib3RoIHRoZSBjb25zdHJ1Y3RvciBhbmQgdG8gcG9zdAogICAgICAgICAgcmVzcG9uc2VUeXBlOiBvcHRpb25zLnJlc3BvbnNlVHlwZSwKICAgICAgICAgIG92ZXJyaWRlTWltZVR5cGU6IG9wdGlvbnMub3ZlcnJpZGVNaW1lVHlwZQogICAgICAgIH0pOwogICAgICB9OwogICAgICBSZXNvdXJjZS5wcm90b3R5cGUucHV0ID0gZnVuY3Rpb24oZGF0YSwgb3B0aW9ucykgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiZGF0YSIsIGRhdGEpOwogICAgICAgIG9wdGlvbnMgPSBkZWZhdWx0Q2xvbmUob3B0aW9ucywge30pOwogICAgICAgIG9wdGlvbnMubWV0aG9kID0gIlBVVCI7CiAgICAgICAgb3B0aW9ucy5kYXRhID0gZGF0YTsKICAgICAgICByZXR1cm4gdGhpcy5fbWFrZVJlcXVlc3Qob3B0aW9ucyk7CiAgICAgIH07CiAgICAgIFJlc291cmNlLnB1dCA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBjb25zdCByZXNvdXJjZSA9IG5ldyBSZXNvdXJjZShvcHRpb25zKTsKICAgICAgICByZXR1cm4gcmVzb3VyY2UucHV0KG9wdGlvbnMuZGF0YSwgewogICAgICAgICAgLy8gTWFrZSBjb3B5IG9mIGp1c3QgdGhlIG5lZWRlZCBmaWVsZHMgYmVjYXVzZSBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgdG8gYm90aCB0aGUgY29uc3RydWN0b3IgYW5kIHRvIHBvc3QKICAgICAgICAgIHJlc3BvbnNlVHlwZTogb3B0aW9ucy5yZXNwb25zZVR5cGUsCiAgICAgICAgICBvdmVycmlkZU1pbWVUeXBlOiBvcHRpb25zLm92ZXJyaWRlTWltZVR5cGUKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgUmVzb3VyY2UucHJvdG90eXBlLnBhdGNoID0gZnVuY3Rpb24oZGF0YSwgb3B0aW9ucykgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiZGF0YSIsIGRhdGEpOwogICAgICAgIG9wdGlvbnMgPSBkZWZhdWx0Q2xvbmUob3B0aW9ucywge30pOwogICAgICAgIG9wdGlvbnMubWV0aG9kID0gIlBBVENIIjsKICAgICAgICBvcHRpb25zLmRhdGEgPSBkYXRhOwogICAgICAgIHJldHVybiB0aGlzLl9tYWtlUmVxdWVzdChvcHRpb25zKTsKICAgICAgfTsKICAgICAgUmVzb3VyY2UucGF0Y2ggPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgY29uc3QgcmVzb3VyY2UgPSBuZXcgUmVzb3VyY2Uob3B0aW9ucyk7CiAgICAgICAgcmV0dXJuIHJlc291cmNlLnBhdGNoKG9wdGlvbnMuZGF0YSwgewogICAgICAgICAgLy8gTWFrZSBjb3B5IG9mIGp1c3QgdGhlIG5lZWRlZCBmaWVsZHMgYmVjYXVzZSBoZWFkZXJzIGNhbiBiZSBwYXNzZWQgdG8gYm90aCB0aGUgY29uc3RydWN0b3IgYW5kIHRvIHBvc3QKICAgICAgICAgIHJlc3BvbnNlVHlwZTogb3B0aW9ucy5yZXNwb25zZVR5cGUsCiAgICAgICAgICBvdmVycmlkZU1pbWVUeXBlOiBvcHRpb25zLm92ZXJyaWRlTWltZVR5cGUKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgUmVzb3VyY2UuX0ltcGxlbWVudGF0aW9ucyA9IHt9OwogICAgICBSZXNvdXJjZS5fSW1wbGVtZW50YXRpb25zLmxvYWRJbWFnZUVsZW1lbnQgPSBmdW5jdGlvbih1cmwsIGNyb3NzT3JpZ2luLCBkZWZlcnJlZCkgewogICAgICAgIGNvbnN0IGltYWdlID0gbmV3IEltYWdlKCk7CiAgICAgICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICBpZiAoaW1hZ2UubmF0dXJhbFdpZHRoID09PSAwICYmIGltYWdlLm5hdHVyYWxIZWlnaHQgPT09IDAgJiYgaW1hZ2Uud2lkdGggPT09IDAgJiYgaW1hZ2UuaGVpZ2h0ID09PSAwKSB7CiAgICAgICAgICAgIGltYWdlLndpZHRoID0gMzAwOwogICAgICAgICAgICBpbWFnZS5oZWlnaHQgPSAxNTA7CiAgICAgICAgICB9CiAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKGltYWdlKTsKICAgICAgICB9OwogICAgICAgIGltYWdlLm9uZXJyb3IgPSBmdW5jdGlvbihlKSB7CiAgICAgICAgICBkZWZlcnJlZC5yZWplY3QoZSk7CiAgICAgICAgfTsKICAgICAgICBpZiAoY3Jvc3NPcmlnaW4pIHsKICAgICAgICAgIGlmIChUcnVzdGVkU2VydmVyc19kZWZhdWx0LmNvbnRhaW5zKHVybCkpIHsKICAgICAgICAgICAgaW1hZ2UuY3Jvc3NPcmlnaW4gPSAidXNlLWNyZWRlbnRpYWxzIjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGltYWdlLmNyb3NzT3JpZ2luID0gIiI7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGltYWdlLnNyYyA9IHVybDsKICAgICAgfTsKICAgICAgUmVzb3VyY2UuX0ltcGxlbWVudGF0aW9ucy5jcmVhdGVJbWFnZSA9IGZ1bmN0aW9uKHJlcXVlc3QsIGNyb3NzT3JpZ2luLCBkZWZlcnJlZCwgZmxpcFksIHNraXBDb2xvclNwYWNlQ29udmVyc2lvbiwgcHJlZmVySW1hZ2VCaXRtYXApIHsKICAgICAgICBjb25zdCB1cmwgPSByZXF1ZXN0LnVybDsKICAgICAgICBSZXNvdXJjZS5zdXBwb3J0c0ltYWdlQml0bWFwT3B0aW9ucygpLnRoZW4oZnVuY3Rpb24oc3VwcG9ydHNJbWFnZUJpdG1hcCkgewogICAgICAgICAgaWYgKCEoc3VwcG9ydHNJbWFnZUJpdG1hcCAmJiBwcmVmZXJJbWFnZUJpdG1hcCkpIHsKICAgICAgICAgICAgUmVzb3VyY2UuX0ltcGxlbWVudGF0aW9ucy5sb2FkSW1hZ2VFbGVtZW50KHVybCwgY3Jvc3NPcmlnaW4sIGRlZmVycmVkKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgcmVzcG9uc2VUeXBlID0gImJsb2IiOwogICAgICAgICAgY29uc3QgbWV0aG9kID0gIkdFVCI7CiAgICAgICAgICBjb25zdCB4aHJEZWZlcnJlZCA9IGRlZmVyX2RlZmF1bHQoKTsKICAgICAgICAgIGNvbnN0IHhociA9IFJlc291cmNlLl9JbXBsZW1lbnRhdGlvbnMubG9hZFdpdGhYaHIoCiAgICAgICAgICAgIHVybCwKICAgICAgICAgICAgcmVzcG9uc2VUeXBlLAogICAgICAgICAgICBtZXRob2QsCiAgICAgICAgICAgIHZvaWQgMCwKICAgICAgICAgICAgdm9pZCAwLAogICAgICAgICAgICB4aHJEZWZlcnJlZCwKICAgICAgICAgICAgdm9pZCAwLAogICAgICAgICAgICB2b2lkIDAsCiAgICAgICAgICAgIHZvaWQgMAogICAgICAgICAgKTsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoeGhyKSAmJiBkZWZpbmVkX2RlZmF1bHQoeGhyLmFib3J0KSkgewogICAgICAgICAgICByZXF1ZXN0LmNhbmNlbEZ1bmN0aW9uID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgeGhyLmFib3J0KCk7CiAgICAgICAgICAgIH07CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4geGhyRGVmZXJyZWQucHJvbWlzZS50aGVuKGZ1bmN0aW9uKGJsb2IpIHsKICAgICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYmxvYikpIHsKICAgICAgICAgICAgICBkZWZlcnJlZC5yZWplY3QoCiAgICAgICAgICAgICAgICBuZXcgUnVudGltZUVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICAgICAgIGBTdWNjZXNzZnVsbHkgcmV0cmlldmVkICR7dXJsfSBidXQgaXQgY29udGFpbmVkIG5vIGNvbnRlbnQuYAogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBSZXNvdXJjZS5jcmVhdGVJbWFnZUJpdG1hcEZyb21CbG9iKGJsb2IsIHsKICAgICAgICAgICAgICBmbGlwWSwKICAgICAgICAgICAgICBwcmVtdWx0aXBseUFscGhhOiBmYWxzZSwKICAgICAgICAgICAgICBza2lwQ29sb3JTcGFjZUNvbnZlcnNpb24KICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uKGltYWdlKSB7CiAgICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUoaW1hZ2UpOwogICAgICAgICAgfSk7CiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24oZSkgewogICAgICAgICAgZGVmZXJyZWQucmVqZWN0KGUpOwogICAgICAgIH0pOwogICAgICB9OwogICAgICBSZXNvdXJjZS5jcmVhdGVJbWFnZUJpdG1hcEZyb21CbG9iID0gZnVuY3Rpb24oYmxvYiwgb3B0aW9ucykgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgib3B0aW9ucyIsIG9wdGlvbnMpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLmJvb2woIm9wdGlvbnMuZmxpcFkiLCBvcHRpb25zLmZsaXBZKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5ib29sKCJvcHRpb25zLnByZW11bHRpcGx5QWxwaGEiLCBvcHRpb25zLnByZW11bHRpcGx5QWxwaGEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLmJvb2woCiAgICAgICAgICAib3B0aW9ucy5za2lwQ29sb3JTcGFjZUNvbnZlcnNpb24iLAogICAgICAgICAgb3B0aW9ucy5za2lwQ29sb3JTcGFjZUNvbnZlcnNpb24KICAgICAgICApOwogICAgICAgIHJldHVybiBjcmVhdGVJbWFnZUJpdG1hcChibG9iLCB7CiAgICAgICAgICBpbWFnZU9yaWVudGF0aW9uOiBvcHRpb25zLmZsaXBZID8gImZsaXBZIiA6ICJmcm9tLWltYWdlIiwKICAgICAgICAgIHByZW11bHRpcGx5QWxwaGE6IG9wdGlvbnMucHJlbXVsdGlwbHlBbHBoYSA/ICJwcmVtdWx0aXBseSIgOiAibm9uZSIsCiAgICAgICAgICBjb2xvclNwYWNlQ29udmVyc2lvbjogb3B0aW9ucy5za2lwQ29sb3JTcGFjZUNvbnZlcnNpb24gPyAibm9uZSIgOiAiZGVmYXVsdCIKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgbm9YTUxIdHRwUmVxdWVzdCA9IHR5cGVvZiBYTUxIdHRwUmVxdWVzdCA9PT0gInVuZGVmaW5lZCI7CiAgICAgIFJlc291cmNlLl9JbXBsZW1lbnRhdGlvbnMubG9hZFdpdGhYaHIgPSBmdW5jdGlvbih1cmwsIHJlc3BvbnNlVHlwZSwgbWV0aG9kLCBkYXRhLCBoZWFkZXJzLCBkZWZlcnJlZCwgb3ZlcnJpZGVNaW1lVHlwZSkgewogICAgICAgIGNvbnN0IGRhdGFVcmlSZWdleFJlc3VsdCA9IGRhdGFVcmlSZWdleDIuZXhlYyh1cmwpOwogICAgICAgIGlmIChkYXRhVXJpUmVnZXhSZXN1bHQgIT09IG51bGwpIHsKICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUoZGVjb2RlRGF0YVVyaShkYXRhVXJpUmVnZXhSZXN1bHQsIHJlc3BvbnNlVHlwZSkpOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBpZiAobm9YTUxIdHRwUmVxdWVzdCkgewogICAgICAgICAgbG9hZFdpdGhIdHRwUmVxdWVzdCgKICAgICAgICAgICAgdXJsLAogICAgICAgICAgICByZXNwb25zZVR5cGUsCiAgICAgICAgICAgIG1ldGhvZCwKICAgICAgICAgICAgZGF0YSwKICAgICAgICAgICAgaGVhZGVycywKICAgICAgICAgICAgZGVmZXJyZWQsCiAgICAgICAgICAgIG92ZXJyaWRlTWltZVR5cGUKICAgICAgICAgICk7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpOwogICAgICAgIGlmIChUcnVzdGVkU2VydmVyc19kZWZhdWx0LmNvbnRhaW5zKHVybCkpIHsKICAgICAgICAgIHhoci53aXRoQ3JlZGVudGlhbHMgPSB0cnVlOwogICAgICAgIH0KICAgICAgICB4aHIub3BlbihtZXRob2QsIHVybCwgdHJ1ZSk7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChvdmVycmlkZU1pbWVUeXBlKSAmJiBkZWZpbmVkX2RlZmF1bHQoeGhyLm92ZXJyaWRlTWltZVR5cGUpKSB7CiAgICAgICAgICB4aHIub3ZlcnJpZGVNaW1lVHlwZShvdmVycmlkZU1pbWVUeXBlKTsKICAgICAgICB9CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChoZWFkZXJzKSkgewogICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gaGVhZGVycykgewogICAgICAgICAgICBpZiAoaGVhZGVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7CiAgICAgICAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoa2V5LCBoZWFkZXJzW2tleV0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocmVzcG9uc2VUeXBlKSkgewogICAgICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9IHJlc3BvbnNlVHlwZTsKICAgICAgICB9CiAgICAgICAgbGV0IGxvY2FsRmlsZSA9IGZhbHNlOwogICAgICAgIGlmICh0eXBlb2YgdXJsID09PSAic3RyaW5nIikgewogICAgICAgICAgbG9jYWxGaWxlID0gdXJsLmluZGV4T2YoImZpbGU6Ly8iKSA9PT0gMCB8fCB0eXBlb2Ygd2luZG93ICE9PSAidW5kZWZpbmVkIiAmJiB3aW5kb3cubG9jYXRpb24ub3JpZ2luID09PSAiZmlsZTovLyI7CiAgICAgICAgfQogICAgICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbigpIHsKICAgICAgICAgIGlmICgoeGhyLnN0YXR1cyA8IDIwMCB8fCB4aHIuc3RhdHVzID49IDMwMCkgJiYgIShsb2NhbEZpbGUgJiYgeGhyLnN0YXR1cyA9PT0gMCkpIHsKICAgICAgICAgICAgZGVmZXJyZWQucmVqZWN0KAogICAgICAgICAgICAgIG5ldyBSZXF1ZXN0RXJyb3JFdmVudF9kZWZhdWx0KAogICAgICAgICAgICAgICAgeGhyLnN0YXR1cywKICAgICAgICAgICAgICAgIHhoci5yZXNwb25zZSwKICAgICAgICAgICAgICAgIHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKQogICAgICAgICAgICAgICkKICAgICAgICAgICAgKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSB4aHIucmVzcG9uc2U7CiAgICAgICAgICBjb25zdCBicm93c2VyUmVzcG9uc2VUeXBlID0geGhyLnJlc3BvbnNlVHlwZTsKICAgICAgICAgIGlmIChtZXRob2QgPT09ICJIRUFEIiB8fCBtZXRob2QgPT09ICJPUFRJT05TIikgewogICAgICAgICAgICBjb25zdCByZXNwb25zZUhlYWRlclN0cmluZyA9IHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKTsKICAgICAgICAgICAgY29uc3Qgc3BsaXRIZWFkZXJzID0gcmVzcG9uc2VIZWFkZXJTdHJpbmcudHJpbSgpLnNwbGl0KC9bXHJcbl0rLyk7CiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlSGVhZGVycyA9IHt9OwogICAgICAgICAgICBzcGxpdEhlYWRlcnMuZm9yRWFjaChmdW5jdGlvbihsaW5lKSB7CiAgICAgICAgICAgICAgY29uc3QgcGFydHMgPSBsaW5lLnNwbGl0KCI6ICIpOwogICAgICAgICAgICAgIGNvbnN0IGhlYWRlciA9IHBhcnRzLnNoaWZ0KCk7CiAgICAgICAgICAgICAgcmVzcG9uc2VIZWFkZXJzW2hlYWRlcl0gPSBwYXJ0cy5qb2luKCI6ICIpOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZShyZXNwb25zZUhlYWRlcnMpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoeGhyLnN0YXR1cyA9PT0gMjA0KSB7CiAgICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUodm9pZCAwKTsKICAgICAgICAgIH0gZWxzZSBpZiAoZGVmaW5lZF9kZWZhdWx0KHJlc3BvbnNlKSAmJiAoIWRlZmluZWRfZGVmYXVsdChyZXNwb25zZVR5cGUpIHx8IGJyb3dzZXJSZXNwb25zZVR5cGUgPT09IHJlc3BvbnNlVHlwZSkpIHsKICAgICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZShyZXNwb25zZSk7CiAgICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlVHlwZSA9PT0gImpzb24iICYmIHR5cGVvZiByZXNwb25zZSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKEpTT04ucGFyc2UocmVzcG9uc2UpKTsKICAgICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAgIGRlZmVycmVkLnJlamVjdChlKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIGlmICgoYnJvd3NlclJlc3BvbnNlVHlwZSA9PT0gIiIgfHwgYnJvd3NlclJlc3BvbnNlVHlwZSA9PT0gImRvY3VtZW50IikgJiYgZGVmaW5lZF9kZWZhdWx0KHhoci5yZXNwb25zZVhNTCkgJiYgeGhyLnJlc3BvbnNlWE1MLmhhc0NoaWxkTm9kZXMoKSkgewogICAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKHhoci5yZXNwb25zZVhNTCk7CiAgICAgICAgICB9IGVsc2UgaWYgKChicm93c2VyUmVzcG9uc2VUeXBlID09PSAiIiB8fCBicm93c2VyUmVzcG9uc2VUeXBlID09PSAidGV4dCIpICYmIGRlZmluZWRfZGVmYXVsdCh4aHIucmVzcG9uc2VUZXh0KSkgewogICAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKHhoci5yZXNwb25zZVRleHQpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZGVmZXJyZWQucmVqZWN0KAogICAgICAgICAgICAgIG5ldyBSdW50aW1lRXJyb3JfZGVmYXVsdCgiSW52YWxpZCBYTUxIdHRwUmVxdWVzdCByZXNwb25zZSB0eXBlLiIpCiAgICAgICAgICAgICk7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICB4aHIub25lcnJvciA9IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgIGRlZmVycmVkLnJlamVjdChuZXcgUmVxdWVzdEVycm9yRXZlbnRfZGVmYXVsdCgpKTsKICAgICAgICB9OwogICAgICAgIHhoci5zZW5kKGRhdGEpOwogICAgICAgIHJldHVybiB4aHI7CiAgICAgIH07CiAgICAgIFJlc291cmNlLl9JbXBsZW1lbnRhdGlvbnMubG9hZEFuZEV4ZWN1dGVTY3JpcHQgPSBmdW5jdGlvbih1cmwsIGZ1bmN0aW9uTmFtZSwgZGVmZXJyZWQpIHsKICAgICAgICByZXR1cm4gbG9hZEFuZEV4ZWN1dGVTY3JpcHRfZGVmYXVsdCh1cmwsIGZ1bmN0aW9uTmFtZSkuY2F0Y2goZnVuY3Rpb24oZSkgewogICAgICAgICAgZGVmZXJyZWQucmVqZWN0KGUpOwogICAgICAgIH0pOwogICAgICB9OwogICAgICBSZXNvdXJjZS5fRGVmYXVsdEltcGxlbWVudGF0aW9ucyA9IHt9OwogICAgICBSZXNvdXJjZS5fRGVmYXVsdEltcGxlbWVudGF0aW9ucy5jcmVhdGVJbWFnZSA9IFJlc291cmNlLl9JbXBsZW1lbnRhdGlvbnMuY3JlYXRlSW1hZ2U7CiAgICAgIFJlc291cmNlLl9EZWZhdWx0SW1wbGVtZW50YXRpb25zLmxvYWRXaXRoWGhyID0gUmVzb3VyY2UuX0ltcGxlbWVudGF0aW9ucy5sb2FkV2l0aFhocjsKICAgICAgUmVzb3VyY2UuX0RlZmF1bHRJbXBsZW1lbnRhdGlvbnMubG9hZEFuZEV4ZWN1dGVTY3JpcHQgPSBSZXNvdXJjZS5fSW1wbGVtZW50YXRpb25zLmxvYWRBbmRFeGVjdXRlU2NyaXB0OwogICAgICBSZXNvdXJjZS5ERUZBVUxUID0gT2JqZWN0LmZyZWV6ZSgKICAgICAgICBuZXcgUmVzb3VyY2UoewogICAgICAgICAgdXJsOiB0eXBlb2YgZG9jdW1lbnQgPT09ICJ1bmRlZmluZWQiID8gIiIgOiBkb2N1bWVudC5sb2NhdGlvbi5ocmVmLnNwbGl0KCI/IilbMF0KICAgICAgICB9KQogICAgICApOwogICAgICBSZXNvdXJjZV9kZWZhdWx0ID0gUmVzb3VyY2U7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9FYXJ0aE9yaWVudGF0aW9uUGFyYW1ldGVycy5qcwogIGZ1bmN0aW9uIEVhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzKG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIHRoaXMuX2RhdGVzID0gdm9pZCAwOwogICAgdGhpcy5fc2FtcGxlcyA9IHZvaWQgMDsKICAgIHRoaXMuX2RhdGVDb2x1bW4gPSAtMTsKICAgIHRoaXMuX3hQb2xlV2FuZGVyUmFkaWFuc0NvbHVtbiA9IC0xOwogICAgdGhpcy5feVBvbGVXYW5kZXJSYWRpYW5zQ29sdW1uID0gLTE7CiAgICB0aGlzLl91dDFNaW51c1V0Y1NlY29uZHNDb2x1bW4gPSAtMTsKICAgIHRoaXMuX3hDZWxlc3RpYWxQb2xlT2Zmc2V0UmFkaWFuc0NvbHVtbiA9IC0xOwogICAgdGhpcy5feUNlbGVzdGlhbFBvbGVPZmZzZXRSYWRpYW5zQ29sdW1uID0gLTE7CiAgICB0aGlzLl90YWlNaW51c1V0Y1NlY29uZHNDb2x1bW4gPSAtMTsKICAgIHRoaXMuX2NvbHVtbkNvdW50ID0gMDsKICAgIHRoaXMuX2xhc3RJbmRleCA9IC0xOwogICAgdGhpcy5fYWRkTmV3TGVhcFNlY29uZHMgPSBvcHRpb25zLmFkZE5ld0xlYXBTZWNvbmRzID8/IHRydWU7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMuZGF0YSkpIHsKICAgICAgb25EYXRhUmVhZHkodGhpcywgb3B0aW9ucy5kYXRhKTsKICAgIH0gZWxzZSB7CiAgICAgIG9uRGF0YVJlYWR5KHRoaXMsIHsKICAgICAgICBjb2x1bW5OYW1lczogWwogICAgICAgICAgImRhdGVJc284NjAxIiwKICAgICAgICAgICJtb2RpZmllZEp1bGlhbkRhdGVVdGMiLAogICAgICAgICAgInhQb2xlV2FuZGVyUmFkaWFucyIsCiAgICAgICAgICAieVBvbGVXYW5kZXJSYWRpYW5zIiwKICAgICAgICAgICJ1dDFNaW51c1V0Y1NlY29uZHMiLAogICAgICAgICAgImxlbmd0aE9mRGF5Q29ycmVjdGlvblNlY29uZHMiLAogICAgICAgICAgInhDZWxlc3RpYWxQb2xlT2Zmc2V0UmFkaWFucyIsCiAgICAgICAgICAieUNlbGVzdGlhbFBvbGVPZmZzZXRSYWRpYW5zIiwKICAgICAgICAgICJ0YWlNaW51c1V0Y1NlY29uZHMiCiAgICAgICAgXSwKICAgICAgICBzYW1wbGVzOiBbXQogICAgICB9KTsKICAgIH0KICB9CiAgZnVuY3Rpb24gY29tcGFyZUxlYXBTZWNvbmREYXRlczIobGVhcFNlY29uZCwgZGF0ZVRvRmluZCkgewogICAgcmV0dXJuIEp1bGlhbkRhdGVfZGVmYXVsdC5jb21wYXJlKGxlYXBTZWNvbmQuanVsaWFuRGF0ZSwgZGF0ZVRvRmluZCk7CiAgfQogIGZ1bmN0aW9uIG9uRGF0YVJlYWR5KGVvcCwgZW9wRGF0YSkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZW9wRGF0YS5jb2x1bW5OYW1lcykpIHsKICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KAogICAgICAgICJFcnJvciBpbiBsb2FkZWQgRU9QIGRhdGE6IFRoZSBjb2x1bW5OYW1lcyBwcm9wZXJ0eSBpcyByZXF1aXJlZC4iCiAgICAgICk7CiAgICB9CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChlb3BEYXRhLnNhbXBsZXMpKSB7CiAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3JfZGVmYXVsdCgKICAgICAgICAiRXJyb3IgaW4gbG9hZGVkIEVPUCBkYXRhOiBUaGUgc2FtcGxlcyBwcm9wZXJ0eSBpcyByZXF1aXJlZC4iCiAgICAgICk7CiAgICB9CiAgICBjb25zdCBkYXRlQ29sdW1uID0gZW9wRGF0YS5jb2x1bW5OYW1lcy5pbmRleE9mKCJtb2RpZmllZEp1bGlhbkRhdGVVdGMiKTsKICAgIGNvbnN0IHhQb2xlV2FuZGVyUmFkaWFuc0NvbHVtbiA9IGVvcERhdGEuY29sdW1uTmFtZXMuaW5kZXhPZigieFBvbGVXYW5kZXJSYWRpYW5zIik7CiAgICBjb25zdCB5UG9sZVdhbmRlclJhZGlhbnNDb2x1bW4gPSBlb3BEYXRhLmNvbHVtbk5hbWVzLmluZGV4T2YoInlQb2xlV2FuZGVyUmFkaWFucyIpOwogICAgY29uc3QgdXQxTWludXNVdGNTZWNvbmRzQ29sdW1uID0gZW9wRGF0YS5jb2x1bW5OYW1lcy5pbmRleE9mKCJ1dDFNaW51c1V0Y1NlY29uZHMiKTsKICAgIGNvbnN0IHhDZWxlc3RpYWxQb2xlT2Zmc2V0UmFkaWFuc0NvbHVtbiA9IGVvcERhdGEuY29sdW1uTmFtZXMuaW5kZXhPZigKICAgICAgInhDZWxlc3RpYWxQb2xlT2Zmc2V0UmFkaWFucyIKICAgICk7CiAgICBjb25zdCB5Q2VsZXN0aWFsUG9sZU9mZnNldFJhZGlhbnNDb2x1bW4gPSBlb3BEYXRhLmNvbHVtbk5hbWVzLmluZGV4T2YoCiAgICAgICJ5Q2VsZXN0aWFsUG9sZU9mZnNldFJhZGlhbnMiCiAgICApOwogICAgY29uc3QgdGFpTWludXNVdGNTZWNvbmRzQ29sdW1uID0gZW9wRGF0YS5jb2x1bW5OYW1lcy5pbmRleE9mKCJ0YWlNaW51c1V0Y1NlY29uZHMiKTsKICAgIGlmIChkYXRlQ29sdW1uIDwgMCB8fCB4UG9sZVdhbmRlclJhZGlhbnNDb2x1bW4gPCAwIHx8IHlQb2xlV2FuZGVyUmFkaWFuc0NvbHVtbiA8IDAgfHwgdXQxTWludXNVdGNTZWNvbmRzQ29sdW1uIDwgMCB8fCB4Q2VsZXN0aWFsUG9sZU9mZnNldFJhZGlhbnNDb2x1bW4gPCAwIHx8IHlDZWxlc3RpYWxQb2xlT2Zmc2V0UmFkaWFuc0NvbHVtbiA8IDAgfHwgdGFpTWludXNVdGNTZWNvbmRzQ29sdW1uIDwgMCkgewogICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yX2RlZmF1bHQoCiAgICAgICAgIkVycm9yIGluIGxvYWRlZCBFT1AgZGF0YTogVGhlIGNvbHVtbk5hbWVzIHByb3BlcnR5IG11c3QgaW5jbHVkZSBtb2RpZmllZEp1bGlhbkRhdGVVdGMsIHhQb2xlV2FuZGVyUmFkaWFucywgeVBvbGVXYW5kZXJSYWRpYW5zLCB1dDFNaW51c1V0Y1NlY29uZHMsIHhDZWxlc3RpYWxQb2xlT2Zmc2V0UmFkaWFucywgeUNlbGVzdGlhbFBvbGVPZmZzZXRSYWRpYW5zLCBhbmQgdGFpTWludXNVdGNTZWNvbmRzIGNvbHVtbnMiCiAgICAgICk7CiAgICB9CiAgICBjb25zdCBzYW1wbGVzID0gZW9wLl9zYW1wbGVzID0gZW9wRGF0YS5zYW1wbGVzOwogICAgY29uc3QgZGF0ZXMgPSBlb3AuX2RhdGVzID0gW107CiAgICBlb3AuX2RhdGVDb2x1bW4gPSBkYXRlQ29sdW1uOwogICAgZW9wLl94UG9sZVdhbmRlclJhZGlhbnNDb2x1bW4gPSB4UG9sZVdhbmRlclJhZGlhbnNDb2x1bW47CiAgICBlb3AuX3lQb2xlV2FuZGVyUmFkaWFuc0NvbHVtbiA9IHlQb2xlV2FuZGVyUmFkaWFuc0NvbHVtbjsKICAgIGVvcC5fdXQxTWludXNVdGNTZWNvbmRzQ29sdW1uID0gdXQxTWludXNVdGNTZWNvbmRzQ29sdW1uOwogICAgZW9wLl94Q2VsZXN0aWFsUG9sZU9mZnNldFJhZGlhbnNDb2x1bW4gPSB4Q2VsZXN0aWFsUG9sZU9mZnNldFJhZGlhbnNDb2x1bW47CiAgICBlb3AuX3lDZWxlc3RpYWxQb2xlT2Zmc2V0UmFkaWFuc0NvbHVtbiA9IHlDZWxlc3RpYWxQb2xlT2Zmc2V0UmFkaWFuc0NvbHVtbjsKICAgIGVvcC5fdGFpTWludXNVdGNTZWNvbmRzQ29sdW1uID0gdGFpTWludXNVdGNTZWNvbmRzQ29sdW1uOwogICAgZW9wLl9jb2x1bW5Db3VudCA9IGVvcERhdGEuY29sdW1uTmFtZXMubGVuZ3RoOwogICAgZW9wLl9sYXN0SW5kZXggPSB2b2lkIDA7CiAgICBsZXQgbGFzdFRhaU1pbnVzVXRjOwogICAgY29uc3QgYWRkTmV3TGVhcFNlY29uZHMgPSBlb3AuX2FkZE5ld0xlYXBTZWNvbmRzOwogICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHNhbXBsZXMubGVuZ3RoOyBpIDwgbGVuOyBpICs9IGVvcC5fY29sdW1uQ291bnQpIHsKICAgICAgY29uc3QgbWpkID0gc2FtcGxlc1tpICsgZGF0ZUNvbHVtbl07CiAgICAgIGNvbnN0IHRhaU1pbnVzVXRjID0gc2FtcGxlc1tpICsgdGFpTWludXNVdGNTZWNvbmRzQ29sdW1uXTsKICAgICAgY29uc3QgZGF5ID0gbWpkICsgVGltZUNvbnN0YW50c19kZWZhdWx0Lk1PRElGSUVEX0pVTElBTl9EQVRFX0RJRkZFUkVOQ0U7CiAgICAgIGNvbnN0IGRhdGUgPSBuZXcgSnVsaWFuRGF0ZV9kZWZhdWx0KGRheSwgdGFpTWludXNVdGMsIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSSk7CiAgICAgIGRhdGVzLnB1c2goZGF0ZSk7CiAgICAgIGlmIChhZGROZXdMZWFwU2Vjb25kcykgewogICAgICAgIGlmICh0YWlNaW51c1V0YyAhPT0gbGFzdFRhaU1pbnVzVXRjICYmIGRlZmluZWRfZGVmYXVsdChsYXN0VGFpTWludXNVdGMpKSB7CiAgICAgICAgICBjb25zdCBsZWFwU2Vjb25kcyA9IEp1bGlhbkRhdGVfZGVmYXVsdC5sZWFwU2Vjb25kczsKICAgICAgICAgIGNvbnN0IGxlYXBTZWNvbmRJbmRleCA9IGJpbmFyeVNlYXJjaF9kZWZhdWx0KAogICAgICAgICAgICBsZWFwU2Vjb25kcywKICAgICAgICAgICAgZGF0ZSwKICAgICAgICAgICAgY29tcGFyZUxlYXBTZWNvbmREYXRlczIKICAgICAgICAgICk7CiAgICAgICAgICBpZiAobGVhcFNlY29uZEluZGV4IDwgMCkgewogICAgICAgICAgICBjb25zdCBsZWFwU2Vjb25kID0gbmV3IExlYXBTZWNvbmRfZGVmYXVsdChkYXRlLCB0YWlNaW51c1V0Yyk7CiAgICAgICAgICAgIGxlYXBTZWNvbmRzLnNwbGljZSh+bGVhcFNlY29uZEluZGV4LCAwLCBsZWFwU2Vjb25kKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbGFzdFRhaU1pbnVzVXRjID0gdGFpTWludXNVdGM7CiAgICAgIH0KICAgIH0KICB9CiAgZnVuY3Rpb24gZmlsbFJlc3VsdEZyb21JbmRleChlb3AsIHNhbXBsZXMsIGluZGV4LCBjb2x1bW5Db3VudCwgcmVzdWx0KSB7CiAgICBjb25zdCBzdGFydCA9IGluZGV4ICogY29sdW1uQ291bnQ7CiAgICByZXN1bHQueFBvbGVXYW5kZXIgPSBzYW1wbGVzW3N0YXJ0ICsgZW9wLl94UG9sZVdhbmRlclJhZGlhbnNDb2x1bW5dOwogICAgcmVzdWx0LnlQb2xlV2FuZGVyID0gc2FtcGxlc1tzdGFydCArIGVvcC5feVBvbGVXYW5kZXJSYWRpYW5zQ29sdW1uXTsKICAgIHJlc3VsdC54UG9sZU9mZnNldCA9IHNhbXBsZXNbc3RhcnQgKyBlb3AuX3hDZWxlc3RpYWxQb2xlT2Zmc2V0UmFkaWFuc0NvbHVtbl07CiAgICByZXN1bHQueVBvbGVPZmZzZXQgPSBzYW1wbGVzW3N0YXJ0ICsgZW9wLl95Q2VsZXN0aWFsUG9sZU9mZnNldFJhZGlhbnNDb2x1bW5dOwogICAgcmVzdWx0LnV0MU1pbnVzVXRjID0gc2FtcGxlc1tzdGFydCArIGVvcC5fdXQxTWludXNVdGNTZWNvbmRzQ29sdW1uXTsKICB9CiAgZnVuY3Rpb24gbGluZWFySW50ZXJwKGR4LCB5MSwgeTIpIHsKICAgIHJldHVybiB5MSArIGR4ICogKHkyIC0geTEpOwogIH0KICBmdW5jdGlvbiBpbnRlcnBvbGF0ZShlb3AsIGRhdGVzLCBzYW1wbGVzLCBkYXRlLCBiZWZvcmUsIGFmdGVyLCByZXN1bHQpIHsKICAgIGNvbnN0IGNvbHVtbkNvdW50ID0gZW9wLl9jb2x1bW5Db3VudDsKICAgIGlmIChhZnRlciA+IGRhdGVzLmxlbmd0aCAtIDEpIHsKICAgICAgcmVzdWx0LnhQb2xlV2FuZGVyID0gMDsKICAgICAgcmVzdWx0LnlQb2xlV2FuZGVyID0gMDsKICAgICAgcmVzdWx0LnhQb2xlT2Zmc2V0ID0gMDsKICAgICAgcmVzdWx0LnlQb2xlT2Zmc2V0ID0gMDsKICAgICAgcmVzdWx0LnV0MU1pbnVzVXRjID0gMDsKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIGNvbnN0IGJlZm9yZURhdGUgPSBkYXRlc1tiZWZvcmVdOwogICAgY29uc3QgYWZ0ZXJEYXRlID0gZGF0ZXNbYWZ0ZXJdOwogICAgaWYgKGJlZm9yZURhdGUuZXF1YWxzKGFmdGVyRGF0ZSkgfHwgZGF0ZS5lcXVhbHMoYmVmb3JlRGF0ZSkpIHsKICAgICAgZmlsbFJlc3VsdEZyb21JbmRleChlb3AsIHNhbXBsZXMsIGJlZm9yZSwgY29sdW1uQ291bnQsIHJlc3VsdCk7CiAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9IGVsc2UgaWYgKGRhdGUuZXF1YWxzKGFmdGVyRGF0ZSkpIHsKICAgICAgZmlsbFJlc3VsdEZyb21JbmRleChlb3AsIHNhbXBsZXMsIGFmdGVyLCBjb2x1bW5Db3VudCwgcmVzdWx0KTsKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIGNvbnN0IGZhY3RvciA9IEp1bGlhbkRhdGVfZGVmYXVsdC5zZWNvbmRzRGlmZmVyZW5jZShkYXRlLCBiZWZvcmVEYXRlKSAvIEp1bGlhbkRhdGVfZGVmYXVsdC5zZWNvbmRzRGlmZmVyZW5jZShhZnRlckRhdGUsIGJlZm9yZURhdGUpOwogICAgY29uc3Qgc3RhcnRCZWZvcmUgPSBiZWZvcmUgKiBjb2x1bW5Db3VudDsKICAgIGNvbnN0IHN0YXJ0QWZ0ZXIgPSBhZnRlciAqIGNvbHVtbkNvdW50OwogICAgbGV0IGJlZm9yZVV0MU1pbnVzVXRjID0gc2FtcGxlc1tzdGFydEJlZm9yZSArIGVvcC5fdXQxTWludXNVdGNTZWNvbmRzQ29sdW1uXTsKICAgIGxldCBhZnRlclV0MU1pbnVzVXRjID0gc2FtcGxlc1tzdGFydEFmdGVyICsgZW9wLl91dDFNaW51c1V0Y1NlY29uZHNDb2x1bW5dOwogICAgY29uc3Qgb2Zmc2V0RGlmZmVyZW5jZSA9IGFmdGVyVXQxTWludXNVdGMgLSBiZWZvcmVVdDFNaW51c1V0YzsKICAgIGlmIChvZmZzZXREaWZmZXJlbmNlID4gMC41IHx8IG9mZnNldERpZmZlcmVuY2UgPCAtMC41KSB7CiAgICAgIGNvbnN0IGJlZm9yZVRhaU1pbnVzVXRjID0gc2FtcGxlc1tzdGFydEJlZm9yZSArIGVvcC5fdGFpTWludXNVdGNTZWNvbmRzQ29sdW1uXTsKICAgICAgY29uc3QgYWZ0ZXJUYWlNaW51c1V0YyA9IHNhbXBsZXNbc3RhcnRBZnRlciArIGVvcC5fdGFpTWludXNVdGNTZWNvbmRzQ29sdW1uXTsKICAgICAgaWYgKGJlZm9yZVRhaU1pbnVzVXRjICE9PSBhZnRlclRhaU1pbnVzVXRjKSB7CiAgICAgICAgaWYgKGFmdGVyRGF0ZS5lcXVhbHMoZGF0ZSkpIHsKICAgICAgICAgIGJlZm9yZVV0MU1pbnVzVXRjID0gYWZ0ZXJVdDFNaW51c1V0YzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYWZ0ZXJVdDFNaW51c1V0YyAtPSBhZnRlclRhaU1pbnVzVXRjIC0gYmVmb3JlVGFpTWludXNVdGM7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXN1bHQueFBvbGVXYW5kZXIgPSBsaW5lYXJJbnRlcnAoCiAgICAgIGZhY3RvciwKICAgICAgc2FtcGxlc1tzdGFydEJlZm9yZSArIGVvcC5feFBvbGVXYW5kZXJSYWRpYW5zQ29sdW1uXSwKICAgICAgc2FtcGxlc1tzdGFydEFmdGVyICsgZW9wLl94UG9sZVdhbmRlclJhZGlhbnNDb2x1bW5dCiAgICApOwogICAgcmVzdWx0LnlQb2xlV2FuZGVyID0gbGluZWFySW50ZXJwKAogICAgICBmYWN0b3IsCiAgICAgIHNhbXBsZXNbc3RhcnRCZWZvcmUgKyBlb3AuX3lQb2xlV2FuZGVyUmFkaWFuc0NvbHVtbl0sCiAgICAgIHNhbXBsZXNbc3RhcnRBZnRlciArIGVvcC5feVBvbGVXYW5kZXJSYWRpYW5zQ29sdW1uXQogICAgKTsKICAgIHJlc3VsdC54UG9sZU9mZnNldCA9IGxpbmVhckludGVycCgKICAgICAgZmFjdG9yLAogICAgICBzYW1wbGVzW3N0YXJ0QmVmb3JlICsgZW9wLl94Q2VsZXN0aWFsUG9sZU9mZnNldFJhZGlhbnNDb2x1bW5dLAogICAgICBzYW1wbGVzW3N0YXJ0QWZ0ZXIgKyBlb3AuX3hDZWxlc3RpYWxQb2xlT2Zmc2V0UmFkaWFuc0NvbHVtbl0KICAgICk7CiAgICByZXN1bHQueVBvbGVPZmZzZXQgPSBsaW5lYXJJbnRlcnAoCiAgICAgIGZhY3RvciwKICAgICAgc2FtcGxlc1tzdGFydEJlZm9yZSArIGVvcC5feUNlbGVzdGlhbFBvbGVPZmZzZXRSYWRpYW5zQ29sdW1uXSwKICAgICAgc2FtcGxlc1tzdGFydEFmdGVyICsgZW9wLl95Q2VsZXN0aWFsUG9sZU9mZnNldFJhZGlhbnNDb2x1bW5dCiAgICApOwogICAgcmVzdWx0LnV0MU1pbnVzVXRjID0gbGluZWFySW50ZXJwKAogICAgICBmYWN0b3IsCiAgICAgIGJlZm9yZVV0MU1pbnVzVXRjLAogICAgICBhZnRlclV0MU1pbnVzVXRjCiAgICApOwogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgdmFyIEVhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzX2RlZmF1bHQ7CiAgdmFyIGluaXRfRWFydGhPcmllbnRhdGlvblBhcmFtZXRlcnMgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0VhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzLmpzIigpIHsKICAgICAgaW5pdF9iaW5hcnlTZWFyY2goKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FYXJ0aE9yaWVudGF0aW9uUGFyYW1ldGVyc1NhbXBsZSgpOwogICAgICBpbml0X0p1bGlhbkRhdGUoKTsKICAgICAgaW5pdF9MZWFwU2Vjb25kKCk7CiAgICAgIGluaXRfUmVzb3VyY2UoKTsKICAgICAgaW5pdF9SdW50aW1lRXJyb3IoKTsKICAgICAgaW5pdF9UaW1lQ29uc3RhbnRzKCk7CiAgICAgIGluaXRfVGltZVN0YW5kYXJkKCk7CiAgICAgIEVhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzLmZyb21VcmwgPSBhc3luYyBmdW5jdGlvbih1cmwsIG9wdGlvbnMpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInVybCIsIHVybCk7CiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgICAgIGNvbnN0IHJlc291cmNlID0gUmVzb3VyY2VfZGVmYXVsdC5jcmVhdGVJZk5lZWRlZCh1cmwpOwogICAgICAgIGxldCBlb3BEYXRhOwogICAgICAgIHRyeSB7CiAgICAgICAgICBlb3BEYXRhID0gYXdhaXQgcmVzb3VyY2UuZmV0Y2hKc29uKCk7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICBgQW4gZXJyb3Igb2NjdXJyZWQgd2hpbGUgcmV0cmlldmluZyB0aGUgRU9QIGRhdGEgZnJvbSB0aGUgVVJMICR7cmVzb3VyY2UudXJsfS5gCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IEVhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzKHsKICAgICAgICAgIGFkZE5ld0xlYXBTZWNvbmRzOiBvcHRpb25zLmFkZE5ld0xlYXBTZWNvbmRzLAogICAgICAgICAgZGF0YTogZW9wRGF0YQogICAgICAgIH0pOwogICAgICB9OwogICAgICBFYXJ0aE9yaWVudGF0aW9uUGFyYW1ldGVycy5OT05FID0gT2JqZWN0LmZyZWV6ZSh7CiAgICAgICAgY29tcHV0ZTogZnVuY3Rpb24oZGF0ZSwgcmVzdWx0KSB7CiAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICAgIHJlc3VsdCA9IG5ldyBFYXJ0aE9yaWVudGF0aW9uUGFyYW1ldGVyc1NhbXBsZV9kZWZhdWx0KDAsIDAsIDAsIDAsIDApOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcmVzdWx0LnhQb2xlV2FuZGVyID0gMDsKICAgICAgICAgICAgcmVzdWx0LnlQb2xlV2FuZGVyID0gMDsKICAgICAgICAgICAgcmVzdWx0LnhQb2xlT2Zmc2V0ID0gMDsKICAgICAgICAgICAgcmVzdWx0LnlQb2xlT2Zmc2V0ID0gMDsKICAgICAgICAgICAgcmVzdWx0LnV0MU1pbnVzVXRjID0gMDsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICB9KTsKICAgICAgRWFydGhPcmllbnRhdGlvblBhcmFtZXRlcnMucHJvdG90eXBlLmNvbXB1dGUgPSBmdW5jdGlvbihkYXRlLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh0aGlzLl9zYW1wbGVzKSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEVhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzU2FtcGxlX2RlZmF1bHQoMCwgMCwgMCwgMCwgMCk7CiAgICAgICAgfQogICAgICAgIGlmICh0aGlzLl9zYW1wbGVzLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgcmVzdWx0LnhQb2xlV2FuZGVyID0gMDsKICAgICAgICAgIHJlc3VsdC55UG9sZVdhbmRlciA9IDA7CiAgICAgICAgICByZXN1bHQueFBvbGVPZmZzZXQgPSAwOwogICAgICAgICAgcmVzdWx0LnlQb2xlT2Zmc2V0ID0gMDsKICAgICAgICAgIHJlc3VsdC51dDFNaW51c1V0YyA9IDA7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICBjb25zdCBkYXRlcyA9IHRoaXMuX2RhdGVzOwogICAgICAgIGNvbnN0IGxhc3RJbmRleCA9IHRoaXMuX2xhc3RJbmRleDsKICAgICAgICBsZXQgYmVmb3JlID0gMDsKICAgICAgICBsZXQgYWZ0ZXIgPSAwOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobGFzdEluZGV4KSkgewogICAgICAgICAgY29uc3QgcHJldmlvdXNJbmRleERhdGUgPSBkYXRlc1tsYXN0SW5kZXhdOwogICAgICAgICAgY29uc3QgbmV4dEluZGV4RGF0ZSA9IGRhdGVzW2xhc3RJbmRleCArIDFdOwogICAgICAgICAgY29uc3QgaXNBZnRlclByZXZpb3VzID0gSnVsaWFuRGF0ZV9kZWZhdWx0Lmxlc3NUaGFuT3JFcXVhbHMoCiAgICAgICAgICAgIHByZXZpb3VzSW5kZXhEYXRlLAogICAgICAgICAgICBkYXRlCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgaXNBZnRlckxhc3RTYW1wbGUgPSAhZGVmaW5lZF9kZWZhdWx0KG5leHRJbmRleERhdGUpOwogICAgICAgICAgY29uc3QgaXNCZWZvcmVOZXh0ID0gaXNBZnRlckxhc3RTYW1wbGUgfHwgSnVsaWFuRGF0ZV9kZWZhdWx0LmdyZWF0ZXJUaGFuT3JFcXVhbHMobmV4dEluZGV4RGF0ZSwgZGF0ZSk7CiAgICAgICAgICBpZiAoaXNBZnRlclByZXZpb3VzICYmIGlzQmVmb3JlTmV4dCkgewogICAgICAgICAgICBiZWZvcmUgPSBsYXN0SW5kZXg7CiAgICAgICAgICAgIGlmICghaXNBZnRlckxhc3RTYW1wbGUgJiYgbmV4dEluZGV4RGF0ZS5lcXVhbHMoZGF0ZSkpIHsKICAgICAgICAgICAgICArK2JlZm9yZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBhZnRlciA9IGJlZm9yZSArIDE7CiAgICAgICAgICAgIGludGVycG9sYXRlKHRoaXMsIGRhdGVzLCB0aGlzLl9zYW1wbGVzLCBkYXRlLCBiZWZvcmUsIGFmdGVyLCByZXN1bHQpOwogICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBsZXQgaW5kZXggPSBiaW5hcnlTZWFyY2hfZGVmYXVsdChkYXRlcywgZGF0ZSwgSnVsaWFuRGF0ZV9kZWZhdWx0LmNvbXBhcmUsIHRoaXMuX2RhdGVDb2x1bW4pOwogICAgICAgIGlmIChpbmRleCA+PSAwKSB7CiAgICAgICAgICBpZiAoaW5kZXggPCBkYXRlcy5sZW5ndGggLSAxICYmIGRhdGVzW2luZGV4ICsgMV0uZXF1YWxzKGRhdGUpKSB7CiAgICAgICAgICAgICsraW5kZXg7CiAgICAgICAgICB9CiAgICAgICAgICBiZWZvcmUgPSBpbmRleDsKICAgICAgICAgIGFmdGVyID0gaW5kZXg7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGFmdGVyID0gfmluZGV4OwogICAgICAgICAgYmVmb3JlID0gYWZ0ZXIgLSAxOwogICAgICAgICAgaWYgKGJlZm9yZSA8IDApIHsKICAgICAgICAgICAgYmVmb3JlID0gMDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgdGhpcy5fbGFzdEluZGV4ID0gYmVmb3JlOwogICAgICAgIGludGVycG9sYXRlKHRoaXMsIGRhdGVzLCB0aGlzLl9zYW1wbGVzLCBkYXRlLCBiZWZvcmUsIGFmdGVyLCByZXN1bHQpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEVhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzX2RlZmF1bHQgPSBFYXJ0aE9yaWVudGF0aW9uUGFyYW1ldGVyczsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0hlYWRpbmdQaXRjaFJvbGwuanMKICBmdW5jdGlvbiBIZWFkaW5nUGl0Y2hSb2xsKGhlYWRpbmcsIHBpdGNoLCByb2xsKSB7CiAgICB0aGlzLmhlYWRpbmcgPSBoZWFkaW5nID8/IDA7CiAgICB0aGlzLnBpdGNoID0gcGl0Y2ggPz8gMDsKICAgIHRoaXMucm9sbCA9IHJvbGwgPz8gMDsKICB9CiAgdmFyIEhlYWRpbmdQaXRjaFJvbGxfZGVmYXVsdDsKICB2YXIgaW5pdF9IZWFkaW5nUGl0Y2hSb2xsID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9IZWFkaW5nUGl0Y2hSb2xsLmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIEhlYWRpbmdQaXRjaFJvbGwuZnJvbVF1YXRlcm5pb24gPSBmdW5jdGlvbihxdWF0ZXJuaW9uLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChxdWF0ZXJuaW9uKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInF1YXRlcm5pb24gaXMgcmVxdWlyZWQiKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEhlYWRpbmdQaXRjaFJvbGwoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgdGVzdCA9IDIgKiAocXVhdGVybmlvbi53ICogcXVhdGVybmlvbi55IC0gcXVhdGVybmlvbi56ICogcXVhdGVybmlvbi54KTsKICAgICAgICBjb25zdCBkZW5vbWluYXRvclJvbGwgPSAxIC0gMiAqIChxdWF0ZXJuaW9uLnggKiBxdWF0ZXJuaW9uLnggKyBxdWF0ZXJuaW9uLnkgKiBxdWF0ZXJuaW9uLnkpOwogICAgICAgIGNvbnN0IG51bWVyYXRvclJvbGwgPSAyICogKHF1YXRlcm5pb24udyAqIHF1YXRlcm5pb24ueCArIHF1YXRlcm5pb24ueSAqIHF1YXRlcm5pb24ueik7CiAgICAgICAgY29uc3QgZGVub21pbmF0b3JIZWFkaW5nID0gMSAtIDIgKiAocXVhdGVybmlvbi55ICogcXVhdGVybmlvbi55ICsgcXVhdGVybmlvbi56ICogcXVhdGVybmlvbi56KTsKICAgICAgICBjb25zdCBudW1lcmF0b3JIZWFkaW5nID0gMiAqIChxdWF0ZXJuaW9uLncgKiBxdWF0ZXJuaW9uLnogKyBxdWF0ZXJuaW9uLnggKiBxdWF0ZXJuaW9uLnkpOwogICAgICAgIHJlc3VsdC5oZWFkaW5nID0gLU1hdGguYXRhbjIobnVtZXJhdG9ySGVhZGluZywgZGVub21pbmF0b3JIZWFkaW5nKTsKICAgICAgICByZXN1bHQucm9sbCA9IE1hdGguYXRhbjIobnVtZXJhdG9yUm9sbCwgZGVub21pbmF0b3JSb2xsKTsKICAgICAgICByZXN1bHQucGl0Y2ggPSAtTWF0aF9kZWZhdWx0LmFzaW5DbGFtcGVkKHRlc3QpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEhlYWRpbmdQaXRjaFJvbGwuZnJvbURlZ3JlZXMgPSBmdW5jdGlvbihoZWFkaW5nLCBwaXRjaCwgcm9sbCwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaGVhZGluZykpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJoZWFkaW5nIGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBpdGNoKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInBpdGNoIGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJvbGwpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicm9sbCBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgSGVhZGluZ1BpdGNoUm9sbCgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuaGVhZGluZyA9IGhlYWRpbmcgKiBNYXRoX2RlZmF1bHQuUkFESUFOU19QRVJfREVHUkVFOwogICAgICAgIHJlc3VsdC5waXRjaCA9IHBpdGNoICogTWF0aF9kZWZhdWx0LlJBRElBTlNfUEVSX0RFR1JFRTsKICAgICAgICByZXN1bHQucm9sbCA9IHJvbGwgKiBNYXRoX2RlZmF1bHQuUkFESUFOU19QRVJfREVHUkVFOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEhlYWRpbmdQaXRjaFJvbGwuY2xvbmUgPSBmdW5jdGlvbihoZWFkaW5nUGl0Y2hSb2xsLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChoZWFkaW5nUGl0Y2hSb2xsKSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBIZWFkaW5nUGl0Y2hSb2xsKAogICAgICAgICAgICBoZWFkaW5nUGl0Y2hSb2xsLmhlYWRpbmcsCiAgICAgICAgICAgIGhlYWRpbmdQaXRjaFJvbGwucGl0Y2gsCiAgICAgICAgICAgIGhlYWRpbmdQaXRjaFJvbGwucm9sbAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmhlYWRpbmcgPSBoZWFkaW5nUGl0Y2hSb2xsLmhlYWRpbmc7CiAgICAgICAgcmVzdWx0LnBpdGNoID0gaGVhZGluZ1BpdGNoUm9sbC5waXRjaDsKICAgICAgICByZXN1bHQucm9sbCA9IGhlYWRpbmdQaXRjaFJvbGwucm9sbDsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBIZWFkaW5nUGl0Y2hSb2xsLmVxdWFscyA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIGxlZnQgPT09IHJpZ2h0IHx8IGRlZmluZWRfZGVmYXVsdChsZWZ0KSAmJiBkZWZpbmVkX2RlZmF1bHQocmlnaHQpICYmIGxlZnQuaGVhZGluZyA9PT0gcmlnaHQuaGVhZGluZyAmJiBsZWZ0LnBpdGNoID09PSByaWdodC5waXRjaCAmJiBsZWZ0LnJvbGwgPT09IHJpZ2h0LnJvbGw7CiAgICAgIH07CiAgICAgIEhlYWRpbmdQaXRjaFJvbGwuZXF1YWxzRXBzaWxvbiA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCByZWxhdGl2ZUVwc2lsb24sIGFic29sdXRlRXBzaWxvbikgewogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIGxlZnQuaGVhZGluZywKICAgICAgICAgIHJpZ2h0LmhlYWRpbmcsCiAgICAgICAgICByZWxhdGl2ZUVwc2lsb24sCiAgICAgICAgICBhYnNvbHV0ZUVwc2lsb24KICAgICAgICApICYmIE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgbGVmdC5waXRjaCwKICAgICAgICAgIHJpZ2h0LnBpdGNoLAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKSAmJiBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIGxlZnQucm9sbCwKICAgICAgICAgIHJpZ2h0LnJvbGwsCiAgICAgICAgICByZWxhdGl2ZUVwc2lsb24sCiAgICAgICAgICBhYnNvbHV0ZUVwc2lsb24KICAgICAgICApOwogICAgICB9OwogICAgICBIZWFkaW5nUGl0Y2hSb2xsLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAgIHJldHVybiBIZWFkaW5nUGl0Y2hSb2xsLmNsb25lKHRoaXMsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIEhlYWRpbmdQaXRjaFJvbGwucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uKHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIEhlYWRpbmdQaXRjaFJvbGwuZXF1YWxzKHRoaXMsIHJpZ2h0KTsKICAgICAgfTsKICAgICAgSGVhZGluZ1BpdGNoUm9sbC5wcm90b3R5cGUuZXF1YWxzRXBzaWxvbiA9IGZ1bmN0aW9uKHJpZ2h0LCByZWxhdGl2ZUVwc2lsb24sIGFic29sdXRlRXBzaWxvbikgewogICAgICAgIHJldHVybiBIZWFkaW5nUGl0Y2hSb2xsLmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICB0aGlzLAogICAgICAgICAgcmlnaHQsCiAgICAgICAgICByZWxhdGl2ZUVwc2lsb24sCiAgICAgICAgICBhYnNvbHV0ZUVwc2lsb24KICAgICAgICApOwogICAgICB9OwogICAgICBIZWFkaW5nUGl0Y2hSb2xsLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBgKCR7dGhpcy5oZWFkaW5nfSwgJHt0aGlzLnBpdGNofSwgJHt0aGlzLnJvbGx9KWA7CiAgICAgIH07CiAgICAgIEhlYWRpbmdQaXRjaFJvbGxfZGVmYXVsdCA9IEhlYWRpbmdQaXRjaFJvbGw7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9idWlsZE1vZHVsZVVybC5qcwogIGZ1bmN0aW9uIGdldEJhc2VVcmxGcm9tQ2VzaXVtU2NyaXB0KCkgewogICAgY29uc3Qgc2NyaXB0cyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJzY3JpcHQiKTsKICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBzY3JpcHRzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgIGNvbnN0IHNyYyA9IHNjcmlwdHNbaV0uZ2V0QXR0cmlidXRlKCJzcmMiKTsKICAgICAgY29uc3QgcmVzdWx0ID0gY2VzaXVtU2NyaXB0UmVnZXguZXhlYyhzcmMpOwogICAgICBpZiAocmVzdWx0ICE9PSBudWxsKSB7CiAgICAgICAgcmV0dXJuIHJlc3VsdFsxXTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHZvaWQgMDsKICB9CiAgZnVuY3Rpb24gdHJ5TWFrZUFic29sdXRlKHVybCkgewogICAgaWYgKHR5cGVvZiBkb2N1bWVudCA9PT0gInVuZGVmaW5lZCIpIHsKICAgICAgcmV0dXJuIHVybDsKICAgIH0KICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGEyKSkgewogICAgICBhMiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImEiKTsKICAgIH0KICAgIGEyLmhyZWYgPSB1cmw7CiAgICByZXR1cm4gYTIuaHJlZjsKICB9CiAgZnVuY3Rpb24gZ2V0Q2VzaXVtQmFzZVVybCgpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoYmFzZVJlc291cmNlKSkgewogICAgICByZXR1cm4gYmFzZVJlc291cmNlOwogICAgfQogICAgbGV0IGJhc2VVcmxTdHJpbmc7CiAgICBpZiAodHlwZW9mIENFU0lVTV9CQVNFX1VSTCAhPT0gInVuZGVmaW5lZCIpIHsKICAgICAgYmFzZVVybFN0cmluZyA9IENFU0lVTV9CQVNFX1VSTDsKICAgIH0gZWxzZSBpZiAoZGVmaW5lZF9kZWZhdWx0KGltcG9ydF9tZXRhPy51cmwpKSB7CiAgICAgIGJhc2VVcmxTdHJpbmcgPSBnZXRBYnNvbHV0ZVVyaV9kZWZhdWx0KCIuIiwgaW1wb3J0X21ldGEudXJsKTsKICAgIH0gZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gIm9iamVjdCIgJiYgZGVmaW5lZF9kZWZhdWx0KGRlZmluZS5hbWQpICYmICFkZWZpbmUuYW1kLnRvVXJsVW5kZWZpbmVkICYmIGRlZmluZWRfZGVmYXVsdChfX3JlcXVpcmUudG9VcmwpKSB7CiAgICAgIGJhc2VVcmxTdHJpbmcgPSBnZXRBYnNvbHV0ZVVyaV9kZWZhdWx0KAogICAgICAgICIuLiIsCiAgICAgICAgYnVpbGRNb2R1bGVVcmwoIkNvcmUvYnVpbGRNb2R1bGVVcmwuanMiKQogICAgICApOwogICAgfSBlbHNlIHsKICAgICAgYmFzZVVybFN0cmluZyA9IGdldEJhc2VVcmxGcm9tQ2VzaXVtU2NyaXB0KCk7CiAgICB9CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChiYXNlVXJsU3RyaW5nKSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAiVW5hYmxlIHRvIGRldGVybWluZSBDZXNpdW0gYmFzZSBVUkwgYXV0b21hdGljYWxseSwgdHJ5IGRlZmluaW5nIGEgZ2xvYmFsIHZhcmlhYmxlIGNhbGxlZCBDRVNJVU1fQkFTRV9VUkwuIgogICAgICApOwogICAgfQogICAgYmFzZVJlc291cmNlID0gbmV3IFJlc291cmNlX2RlZmF1bHQoewogICAgICB1cmw6IHRyeU1ha2VBYnNvbHV0ZShiYXNlVXJsU3RyaW5nKQogICAgfSk7CiAgICBiYXNlUmVzb3VyY2UuYXBwZW5kRm9yd2FyZFNsYXNoKCk7CiAgICByZXR1cm4gYmFzZVJlc291cmNlOwogIH0KICBmdW5jdGlvbiBidWlsZE1vZHVsZVVybEZyb21SZXF1aXJlVG9VcmwobW9kdWxlSUQpIHsKICAgIHJldHVybiB0cnlNYWtlQWJzb2x1dGUoX19yZXF1aXJlLnRvVXJsKGAuLi8ke21vZHVsZUlEfWApKTsKICB9CiAgZnVuY3Rpb24gYnVpbGRNb2R1bGVVcmxGcm9tQmFzZVVybChtb2R1bGVJRCkgewogICAgY29uc3QgcmVzb3VyY2UgPSBnZXRDZXNpdW1CYXNlVXJsKCkuZ2V0RGVyaXZlZFJlc291cmNlKHsKICAgICAgdXJsOiBtb2R1bGVJRAogICAgfSk7CiAgICByZXR1cm4gcmVzb3VyY2UudXJsOwogIH0KICBmdW5jdGlvbiBidWlsZE1vZHVsZVVybChyZWxhdGl2ZVVybCkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaW1wbGVtZW50YXRpb24pKSB7CiAgICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSAib2JqZWN0IiAmJiBkZWZpbmVkX2RlZmF1bHQoZGVmaW5lLmFtZCkgJiYgIWRlZmluZS5hbWQudG9VcmxVbmRlZmluZWQgJiYgZGVmaW5lZF9kZWZhdWx0KF9fcmVxdWlyZS50b1VybCkpIHsKICAgICAgICBpbXBsZW1lbnRhdGlvbiA9IGJ1aWxkTW9kdWxlVXJsRnJvbVJlcXVpcmVUb1VybDsKICAgICAgfSBlbHNlIHsKICAgICAgICBpbXBsZW1lbnRhdGlvbiA9IGJ1aWxkTW9kdWxlVXJsRnJvbUJhc2VVcmw7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHVybCA9IGltcGxlbWVudGF0aW9uKHJlbGF0aXZlVXJsKTsKICAgIHJldHVybiB1cmw7CiAgfQogIHZhciBpbXBvcnRfbWV0YSwgY2VzaXVtU2NyaXB0UmVnZXgsIGEyLCBiYXNlUmVzb3VyY2UsIGltcGxlbWVudGF0aW9uLCBidWlsZE1vZHVsZVVybF9kZWZhdWx0OwogIHZhciBpbml0X2J1aWxkTW9kdWxlVXJsID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9idWlsZE1vZHVsZVVybC5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfZ2V0QWJzb2x1dGVVcmkoKTsKICAgICAgaW5pdF9SZXNvdXJjZSgpOwogICAgICBpbXBvcnRfbWV0YSA9IHt9OwogICAgICBjZXNpdW1TY3JpcHRSZWdleCA9IC8oKD86LipcLyl8XilDZXNpdW1cLmpzKD86XD98XCN8JCkvOwogICAgICBidWlsZE1vZHVsZVVybC5fY2VzaXVtU2NyaXB0UmVnZXggPSBjZXNpdW1TY3JpcHRSZWdleDsKICAgICAgYnVpbGRNb2R1bGVVcmwuX2J1aWxkTW9kdWxlVXJsRnJvbUJhc2VVcmwgPSBidWlsZE1vZHVsZVVybEZyb21CYXNlVXJsOwogICAgICBidWlsZE1vZHVsZVVybC5fY2xlYXJCYXNlUmVzb3VyY2UgPSBmdW5jdGlvbigpIHsKICAgICAgICBiYXNlUmVzb3VyY2UgPSB2b2lkIDA7CiAgICAgIH07CiAgICAgIGJ1aWxkTW9kdWxlVXJsLnNldEJhc2VVcmwgPSBmdW5jdGlvbih2YWx1ZSkgewogICAgICAgIGJhc2VSZXNvdXJjZSA9IFJlc291cmNlX2RlZmF1bHQuREVGQVVMVC5nZXREZXJpdmVkUmVzb3VyY2UoewogICAgICAgICAgdXJsOiB2YWx1ZQogICAgICAgIH0pOwogICAgICB9OwogICAgICBidWlsZE1vZHVsZVVybC5nZXRDZXNpdW1CYXNlVXJsID0gZ2V0Q2VzaXVtQmFzZVVybDsKICAgICAgYnVpbGRNb2R1bGVVcmxfZGVmYXVsdCA9IGJ1aWxkTW9kdWxlVXJsOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvSWF1MjAwNlh5c1NhbXBsZS5qcwogIGZ1bmN0aW9uIElhdTIwMDZYeXNTYW1wbGUoeCwgeSwgcykgewogICAgdGhpcy54ID0geDsKICAgIHRoaXMueSA9IHk7CiAgICB0aGlzLnMgPSBzOwogIH0KICB2YXIgSWF1MjAwNlh5c1NhbXBsZV9kZWZhdWx0OwogIHZhciBpbml0X0lhdTIwMDZYeXNTYW1wbGUgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0lhdTIwMDZYeXNTYW1wbGUuanMiKCkgewogICAgICBJYXUyMDA2WHlzU2FtcGxlX2RlZmF1bHQgPSBJYXUyMDA2WHlzU2FtcGxlOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvSWF1MjAwNlh5c0RhdGEuanMKICBmdW5jdGlvbiBJYXUyMDA2WHlzRGF0YShvcHRpb25zKSB7CiAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICB0aGlzLl94eXNGaWxlVXJsVGVtcGxhdGUgPSBSZXNvdXJjZV9kZWZhdWx0LmNyZWF0ZUlmTmVlZGVkKAogICAgICBvcHRpb25zLnh5c0ZpbGVVcmxUZW1wbGF0ZQogICAgKTsKICAgIHRoaXMuX2ludGVycG9sYXRpb25PcmRlciA9IG9wdGlvbnMuaW50ZXJwb2xhdGlvbk9yZGVyID8/IDk7CiAgICB0aGlzLl9zYW1wbGVaZXJvSnVsaWFuRXBoZW1lcmlzRGF0ZSA9IG9wdGlvbnMuc2FtcGxlWmVyb0p1bGlhbkVwaGVtZXJpc0RhdGUgPz8gMjQ0MjM5NjVlLTE7CiAgICB0aGlzLl9zYW1wbGVaZXJvRGF0ZVRUID0gbmV3IEp1bGlhbkRhdGVfZGVmYXVsdCgKICAgICAgdGhpcy5fc2FtcGxlWmVyb0p1bGlhbkVwaGVtZXJpc0RhdGUsCiAgICAgIDAsCiAgICAgIFRpbWVTdGFuZGFyZF9kZWZhdWx0LlRBSQogICAgKTsKICAgIHRoaXMuX3N0ZXBTaXplRGF5cyA9IG9wdGlvbnMuc3RlcFNpemVEYXlzID8/IDE7CiAgICB0aGlzLl9zYW1wbGVzUGVyWHlzRmlsZSA9IG9wdGlvbnMuc2FtcGxlc1Blclh5c0ZpbGUgPz8gMWUzOwogICAgdGhpcy5fdG90YWxTYW1wbGVzID0gb3B0aW9ucy50b3RhbFNhbXBsZXMgPz8gMjc0MjY7CiAgICB0aGlzLl9zYW1wbGVzID0gbmV3IEFycmF5KHRoaXMuX3RvdGFsU2FtcGxlcyAqIDMpOwogICAgdGhpcy5fY2h1bmtEb3dubG9hZHNJblByb2dyZXNzID0gW107CiAgICBjb25zdCBvcmRlciA9IHRoaXMuX2ludGVycG9sYXRpb25PcmRlcjsKICAgIGNvbnN0IGRlbm9tID0gdGhpcy5fZGVub21pbmF0b3JzID0gbmV3IEFycmF5KG9yZGVyICsgMSk7CiAgICBjb25zdCB4VGFibGUgPSB0aGlzLl94VGFibGUgPSBuZXcgQXJyYXkob3JkZXIgKyAxKTsKICAgIGNvbnN0IHN0ZXBOID0gTWF0aC5wb3codGhpcy5fc3RlcFNpemVEYXlzLCBvcmRlcik7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8PSBvcmRlcjsgKytpKSB7CiAgICAgIGRlbm9tW2ldID0gc3RlcE47CiAgICAgIHhUYWJsZVtpXSA9IGkgKiB0aGlzLl9zdGVwU2l6ZURheXM7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDw9IG9yZGVyOyArK2opIHsKICAgICAgICBpZiAoaiAhPT0gaSkgewogICAgICAgICAgZGVub21baV0gKj0gaSAtIGo7CiAgICAgICAgfQogICAgICB9CiAgICAgIGRlbm9tW2ldID0gMSAvIGRlbm9tW2ldOwogICAgfQogICAgdGhpcy5fd29yayA9IG5ldyBBcnJheShvcmRlciArIDEpOwogICAgdGhpcy5fY29lZiA9IG5ldyBBcnJheShvcmRlciArIDEpOwogIH0KICBmdW5jdGlvbiBnZXREYXlzU2luY2VFcG9jaCh4eXMsIGRheVRULCBzZWNvbmRUVCkgewogICAgY29uc3QgZGF0ZVRUID0ganVsaWFuRGF0ZVNjcmF0Y2g7CiAgICBkYXRlVFQuZGF5TnVtYmVyID0gZGF5VFQ7CiAgICBkYXRlVFQuc2Vjb25kc09mRGF5ID0gc2Vjb25kVFQ7CiAgICByZXR1cm4gSnVsaWFuRGF0ZV9kZWZhdWx0LmRheXNEaWZmZXJlbmNlKGRhdGVUVCwgeHlzLl9zYW1wbGVaZXJvRGF0ZVRUKTsKICB9CiAgZnVuY3Rpb24gcmVxdWVzdFh5c0NodW5rKHh5c0RhdGEsIGNodW5rSW5kZXgpIHsKICAgIGlmICh4eXNEYXRhLl9jaHVua0Rvd25sb2Fkc0luUHJvZ3Jlc3NbY2h1bmtJbmRleF0pIHsKICAgICAgcmV0dXJuIHh5c0RhdGEuX2NodW5rRG93bmxvYWRzSW5Qcm9ncmVzc1tjaHVua0luZGV4XTsKICAgIH0KICAgIGxldCBjaHVua1VybDsKICAgIGNvbnN0IHh5c0ZpbGVVcmxUZW1wbGF0ZSA9IHh5c0RhdGEuX3h5c0ZpbGVVcmxUZW1wbGF0ZTsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoeHlzRmlsZVVybFRlbXBsYXRlKSkgewogICAgICBjaHVua1VybCA9IHh5c0ZpbGVVcmxUZW1wbGF0ZS5nZXREZXJpdmVkUmVzb3VyY2UoewogICAgICAgIHRlbXBsYXRlVmFsdWVzOiB7CiAgICAgICAgICAwOiBjaHVua0luZGV4CiAgICAgICAgfQogICAgICB9KTsKICAgIH0gZWxzZSB7CiAgICAgIGNodW5rVXJsID0gbmV3IFJlc291cmNlX2RlZmF1bHQoewogICAgICAgIHVybDogYnVpbGRNb2R1bGVVcmxfZGVmYXVsdChgQXNzZXRzL0lBVTIwMDZfWFlTL0lBVTIwMDZfWFlTXyR7Y2h1bmtJbmRleH0uanNvbmApCiAgICAgIH0pOwogICAgfQogICAgY29uc3QgcHJvbWlzZSA9IGNodW5rVXJsLmZldGNoSnNvbigpLnRoZW4oZnVuY3Rpb24oY2h1bmspIHsKICAgICAgeHlzRGF0YS5fY2h1bmtEb3dubG9hZHNJblByb2dyZXNzW2NodW5rSW5kZXhdID0gZmFsc2U7CiAgICAgIGNvbnN0IHNhbXBsZXMgPSB4eXNEYXRhLl9zYW1wbGVzOwogICAgICBjb25zdCBuZXdTYW1wbGVzID0gY2h1bmsuc2FtcGxlczsKICAgICAgY29uc3Qgc3RhcnRJbmRleCA9IGNodW5rSW5kZXggKiB4eXNEYXRhLl9zYW1wbGVzUGVyWHlzRmlsZSAqIDM7CiAgICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBuZXdTYW1wbGVzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgICAgc2FtcGxlc1tzdGFydEluZGV4ICsgaV0gPSBuZXdTYW1wbGVzW2ldOwogICAgICB9CiAgICB9KTsKICAgIHh5c0RhdGEuX2NodW5rRG93bmxvYWRzSW5Qcm9ncmVzc1tjaHVua0luZGV4XSA9IHByb21pc2U7CiAgICByZXR1cm4gcHJvbWlzZTsKICB9CiAgdmFyIGp1bGlhbkRhdGVTY3JhdGNoLCBJYXUyMDA2WHlzRGF0YV9kZWZhdWx0OwogIHZhciBpbml0X0lhdTIwMDZYeXNEYXRhID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9JYXUyMDA2WHlzRGF0YS5qcyIoKSB7CiAgICAgIGluaXRfYnVpbGRNb2R1bGVVcmwoKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfSWF1MjAwNlh5c1NhbXBsZSgpOwogICAgICBpbml0X0p1bGlhbkRhdGUoKTsKICAgICAgaW5pdF9SZXNvdXJjZSgpOwogICAgICBpbml0X1RpbWVTdGFuZGFyZCgpOwogICAgICBqdWxpYW5EYXRlU2NyYXRjaCA9IG5ldyBKdWxpYW5EYXRlX2RlZmF1bHQoMCwgMCwgVGltZVN0YW5kYXJkX2RlZmF1bHQuVEFJKTsKICAgICAgSWF1MjAwNlh5c0RhdGEucHJvdG90eXBlLnByZWxvYWQgPSBmdW5jdGlvbihzdGFydERheVRULCBzdGFydFNlY29uZFRULCBzdG9wRGF5VFQsIHN0b3BTZWNvbmRUVCkgewogICAgICAgIGNvbnN0IHN0YXJ0RGF5c1NpbmNlRXBvY2ggPSBnZXREYXlzU2luY2VFcG9jaCgKICAgICAgICAgIHRoaXMsCiAgICAgICAgICBzdGFydERheVRULAogICAgICAgICAgc3RhcnRTZWNvbmRUVAogICAgICAgICk7CiAgICAgICAgY29uc3Qgc3RvcERheXNTaW5jZUVwb2NoID0gZ2V0RGF5c1NpbmNlRXBvY2godGhpcywgc3RvcERheVRULCBzdG9wU2Vjb25kVFQpOwogICAgICAgIGxldCBzdGFydEluZGV4ID0gc3RhcnREYXlzU2luY2VFcG9jaCAvIHRoaXMuX3N0ZXBTaXplRGF5cyAtIHRoaXMuX2ludGVycG9sYXRpb25PcmRlciAvIDIgfCAwOwogICAgICAgIGlmIChzdGFydEluZGV4IDwgMCkgewogICAgICAgICAgc3RhcnRJbmRleCA9IDA7CiAgICAgICAgfQogICAgICAgIGxldCBzdG9wSW5kZXggPSBzdG9wRGF5c1NpbmNlRXBvY2ggLyB0aGlzLl9zdGVwU2l6ZURheXMgLSB0aGlzLl9pbnRlcnBvbGF0aW9uT3JkZXIgLyAyIHwgMCArIHRoaXMuX2ludGVycG9sYXRpb25PcmRlcjsKICAgICAgICBpZiAoc3RvcEluZGV4ID49IHRoaXMuX3RvdGFsU2FtcGxlcykgewogICAgICAgICAgc3RvcEluZGV4ID0gdGhpcy5fdG90YWxTYW1wbGVzIC0gMTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc3RhcnRDaHVuayA9IHN0YXJ0SW5kZXggLyB0aGlzLl9zYW1wbGVzUGVyWHlzRmlsZSB8IDA7CiAgICAgICAgY29uc3Qgc3RvcENodW5rID0gc3RvcEluZGV4IC8gdGhpcy5fc2FtcGxlc1Blclh5c0ZpbGUgfCAwOwogICAgICAgIGNvbnN0IHByb21pc2VzID0gW107CiAgICAgICAgZm9yIChsZXQgaSA9IHN0YXJ0Q2h1bms7IGkgPD0gc3RvcENodW5rOyArK2kpIHsKICAgICAgICAgIHByb21pc2VzLnB1c2gocmVxdWVzdFh5c0NodW5rKHRoaXMsIGkpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTsKICAgICAgfTsKICAgICAgSWF1MjAwNlh5c0RhdGEucHJvdG90eXBlLmNvbXB1dGVYeXNSYWRpYW5zID0gZnVuY3Rpb24oZGF5VFQsIHNlY29uZFRULCByZXN1bHQpIHsKICAgICAgICBjb25zdCBkYXlzU2luY2VFcG9jaCA9IGdldERheXNTaW5jZUVwb2NoKHRoaXMsIGRheVRULCBzZWNvbmRUVCk7CiAgICAgICAgaWYgKGRheXNTaW5jZUVwb2NoIDwgMCkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgY29uc3QgY2VudGVySW5kZXggPSBkYXlzU2luY2VFcG9jaCAvIHRoaXMuX3N0ZXBTaXplRGF5cyB8IDA7CiAgICAgICAgaWYgKGNlbnRlckluZGV4ID49IHRoaXMuX3RvdGFsU2FtcGxlcykgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgY29uc3QgZGVncmVlID0gdGhpcy5faW50ZXJwb2xhdGlvbk9yZGVyOwogICAgICAgIGxldCBmaXJzdEluZGV4ID0gY2VudGVySW5kZXggLSAoZGVncmVlIC8gMiB8IDApOwogICAgICAgIGlmIChmaXJzdEluZGV4IDwgMCkgewogICAgICAgICAgZmlyc3RJbmRleCA9IDA7CiAgICAgICAgfQogICAgICAgIGxldCBsYXN0SW5kZXggPSBmaXJzdEluZGV4ICsgZGVncmVlOwogICAgICAgIGlmIChsYXN0SW5kZXggPj0gdGhpcy5fdG90YWxTYW1wbGVzKSB7CiAgICAgICAgICBsYXN0SW5kZXggPSB0aGlzLl90b3RhbFNhbXBsZXMgLSAxOwogICAgICAgICAgZmlyc3RJbmRleCA9IGxhc3RJbmRleCAtIGRlZ3JlZTsKICAgICAgICAgIGlmIChmaXJzdEluZGV4IDwgMCkgewogICAgICAgICAgICBmaXJzdEluZGV4ID0gMDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbGV0IGlzRGF0YU1pc3NpbmcgPSBmYWxzZTsKICAgICAgICBjb25zdCBzYW1wbGVzID0gdGhpcy5fc2FtcGxlczsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChzYW1wbGVzW2ZpcnN0SW5kZXggKiAzXSkpIHsKICAgICAgICAgIHJlcXVlc3RYeXNDaHVuayh0aGlzLCBmaXJzdEluZGV4IC8gdGhpcy5fc2FtcGxlc1Blclh5c0ZpbGUgfCAwKTsKICAgICAgICAgIGlzRGF0YU1pc3NpbmcgPSB0cnVlOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChzYW1wbGVzW2xhc3RJbmRleCAqIDNdKSkgewogICAgICAgICAgcmVxdWVzdFh5c0NodW5rKHRoaXMsIGxhc3RJbmRleCAvIHRoaXMuX3NhbXBsZXNQZXJYeXNGaWxlIHwgMCk7CiAgICAgICAgICBpc0RhdGFNaXNzaW5nID0gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKGlzRGF0YU1pc3NpbmcpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBJYXUyMDA2WHlzU2FtcGxlX2RlZmF1bHQoMCwgMCwgMCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC54ID0gMDsKICAgICAgICAgIHJlc3VsdC55ID0gMDsKICAgICAgICAgIHJlc3VsdC5zID0gMDsKICAgICAgICB9CiAgICAgICAgY29uc3QgeCA9IGRheXNTaW5jZUVwb2NoIC0gZmlyc3RJbmRleCAqIHRoaXMuX3N0ZXBTaXplRGF5czsKICAgICAgICBjb25zdCB3b3JrID0gdGhpcy5fd29yazsKICAgICAgICBjb25zdCBkZW5vbSA9IHRoaXMuX2Rlbm9taW5hdG9yczsKICAgICAgICBjb25zdCBjb2VmID0gdGhpcy5fY29lZjsKICAgICAgICBjb25zdCB4VGFibGUgPSB0aGlzLl94VGFibGU7CiAgICAgICAgbGV0IGksIGo7CiAgICAgICAgZm9yIChpID0gMDsgaSA8PSBkZWdyZWU7ICsraSkgewogICAgICAgICAgd29ya1tpXSA9IHggLSB4VGFibGVbaV07CiAgICAgICAgfQogICAgICAgIGZvciAoaSA9IDA7IGkgPD0gZGVncmVlOyArK2kpIHsKICAgICAgICAgIGNvZWZbaV0gPSAxOwogICAgICAgICAgZm9yIChqID0gMDsgaiA8PSBkZWdyZWU7ICsraikgewogICAgICAgICAgICBpZiAoaiAhPT0gaSkgewogICAgICAgICAgICAgIGNvZWZbaV0gKj0gd29ya1tqXTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgY29lZltpXSAqPSBkZW5vbVtpXTsKICAgICAgICAgIGxldCBzYW1wbGVJbmRleCA9IChmaXJzdEluZGV4ICsgaSkgKiAzOwogICAgICAgICAgcmVzdWx0LnggKz0gY29lZltpXSAqIHNhbXBsZXNbc2FtcGxlSW5kZXgrK107CiAgICAgICAgICByZXN1bHQueSArPSBjb2VmW2ldICogc2FtcGxlc1tzYW1wbGVJbmRleCsrXTsKICAgICAgICAgIHJlc3VsdC5zICs9IGNvZWZbaV0gKiBzYW1wbGVzW3NhbXBsZUluZGV4XTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgSWF1MjAwNlh5c0RhdGFfZGVmYXVsdCA9IElhdTIwMDZYeXNEYXRhOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvRnVsbHNjcmVlbi5qcwogIHZhciBfc3VwcG9ydHNGdWxsc2NyZWVuLCBfbmFtZXMsIEZ1bGxzY3JlZW4sIEZ1bGxzY3JlZW5fZGVmYXVsdDsKICB2YXIgaW5pdF9GdWxsc2NyZWVuID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9GdWxsc2NyZWVuLmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIF9uYW1lcyA9IHsKICAgICAgICByZXF1ZXN0RnVsbHNjcmVlbjogdm9pZCAwLAogICAgICAgIGV4aXRGdWxsc2NyZWVuOiB2b2lkIDAsCiAgICAgICAgZnVsbHNjcmVlbkVuYWJsZWQ6IHZvaWQgMCwKICAgICAgICBmdWxsc2NyZWVuRWxlbWVudDogdm9pZCAwLAogICAgICAgIGZ1bGxzY3JlZW5jaGFuZ2U6IHZvaWQgMCwKICAgICAgICBmdWxsc2NyZWVuZXJyb3I6IHZvaWQgMAogICAgICB9OwogICAgICBGdWxsc2NyZWVuID0ge307CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKEZ1bGxzY3JlZW4sIHsKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgZWxlbWVudCB0aGF0IGlzIGN1cnJlbnRseSBmdWxsc2NyZWVuLCBpZiBhbnkuICBUbyBzaW1wbHkgY2hlY2sgaWYgdGhlCiAgICAgICAgICogYnJvd3NlciBpcyBpbiBmdWxsc2NyZWVuIG1vZGUgb3Igbm90LCB1c2Uge0BsaW5rIEZ1bGxzY3JlZW4jZnVsbHNjcmVlbn0uCiAgICAgICAgICogQG1lbWJlcm9mIEZ1bGxzY3JlZW4KICAgICAgICAgKiBAdHlwZSB7b2JqZWN0fQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIGVsZW1lbnQ6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIGlmICghRnVsbHNjcmVlbi5zdXBwb3J0c0Z1bGxzY3JlZW4oKSkgewogICAgICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGRvY3VtZW50W19uYW1lcy5mdWxsc2NyZWVuRWxlbWVudF07CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgb24gdGhlIGRvY3VtZW50IHRoYXQgaXMgZmlyZWQgd2hlbiBmdWxsc2NyZWVuIGlzCiAgICAgICAgICogZW50ZXJlZCBvciBleGl0ZWQuICBUaGlzIGV2ZW50IG5hbWUgaXMgaW50ZW5kZWQgZm9yIHVzZSB3aXRoIGFkZEV2ZW50TGlzdGVuZXIuCiAgICAgICAgICogSW4geW91ciBldmVudCBoYW5kbGVyLCB0byBkZXRlcm1pbmUgaWYgdGhlIGJyb3dzZXIgaXMgaW4gZnVsbHNjcmVlbiBtb2RlIG9yIG5vdCwKICAgICAgICAgKiB1c2Uge0BsaW5rIEZ1bGxzY3JlZW4jZnVsbHNjcmVlbn0uCiAgICAgICAgICogQG1lbWJlcm9mIEZ1bGxzY3JlZW4KICAgICAgICAgKiBAdHlwZSB7c3RyaW5nfQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIGNoYW5nZUV2ZW50TmFtZTogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgaWYgKCFGdWxsc2NyZWVuLnN1cHBvcnRzRnVsbHNjcmVlbigpKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gX25hbWVzLmZ1bGxzY3JlZW5jaGFuZ2U7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdGhhdCBpcyBmaXJlZCB3aGVuIGEgZnVsbHNjcmVlbiBlcnJvcgogICAgICAgICAqIG9jY3Vycy4gIFRoaXMgZXZlbnQgbmFtZSBpcyBpbnRlbmRlZCBmb3IgdXNlIHdpdGggYWRkRXZlbnRMaXN0ZW5lci4KICAgICAgICAgKiBAbWVtYmVyb2YgRnVsbHNjcmVlbgogICAgICAgICAqIEB0eXBlIHtzdHJpbmd9CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgZXJyb3JFdmVudE5hbWU6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIGlmICghRnVsbHNjcmVlbi5zdXBwb3J0c0Z1bGxzY3JlZW4oKSkgewogICAgICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIF9uYW1lcy5mdWxsc2NyZWVuZXJyb3I7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgYnJvd3NlciB3aWxsIGFsbG93IGFuIGVsZW1lbnQgdG8gYmUgbWFkZSBmdWxsc2NyZWVuLCBvciBub3QuCiAgICAgICAgICogRm9yIGV4YW1wbGUsIGJ5IGRlZmF1bHQsIGlmcmFtZXMgY2Fubm90IGdvIGZ1bGxzY3JlZW4gdW5sZXNzIHRoZSBjb250YWluaW5nIHBhZ2UKICAgICAgICAgKiBhZGRzIGFuICJhbGxvd2Z1bGxzY3JlZW4iIGF0dHJpYnV0ZSAob3IgcHJlZml4ZWQgZXF1aXZhbGVudCkuCiAgICAgICAgICogQG1lbWJlcm9mIEZ1bGxzY3JlZW4KICAgICAgICAgKiBAdHlwZSB7Ym9vbGVhbn0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBlbmFibGVkOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBpZiAoIUZ1bGxzY3JlZW4uc3VwcG9ydHNGdWxsc2NyZWVuKCkpIHsKICAgICAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBkb2N1bWVudFtfbmFtZXMuZnVsbHNjcmVlbkVuYWJsZWRdOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogRGV0ZXJtaW5lcyBpZiB0aGUgYnJvd3NlciBpcyBjdXJyZW50bHkgaW4gZnVsbHNjcmVlbiBtb2RlLgogICAgICAgICAqIEBtZW1iZXJvZiBGdWxsc2NyZWVuCiAgICAgICAgICogQHR5cGUge2Jvb2xlYW59CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgZnVsbHNjcmVlbjogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgaWYgKCFGdWxsc2NyZWVuLnN1cHBvcnRzRnVsbHNjcmVlbigpKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gRnVsbHNjcmVlbi5lbGVtZW50ICE9PSBudWxsOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIEZ1bGxzY3JlZW4uc3VwcG9ydHNGdWxsc2NyZWVuID0gZnVuY3Rpb24oKSB7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChfc3VwcG9ydHNGdWxsc2NyZWVuKSkgewogICAgICAgICAgcmV0dXJuIF9zdXBwb3J0c0Z1bGxzY3JlZW47CiAgICAgICAgfQogICAgICAgIF9zdXBwb3J0c0Z1bGxzY3JlZW4gPSBmYWxzZTsKICAgICAgICBjb25zdCBib2R5ID0gZG9jdW1lbnQuYm9keTsKICAgICAgICBpZiAodHlwZW9mIGJvZHkucmVxdWVzdEZ1bGxzY3JlZW4gPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgIF9uYW1lcy5yZXF1ZXN0RnVsbHNjcmVlbiA9ICJyZXF1ZXN0RnVsbHNjcmVlbiI7CiAgICAgICAgICBfbmFtZXMuZXhpdEZ1bGxzY3JlZW4gPSAiZXhpdEZ1bGxzY3JlZW4iOwogICAgICAgICAgX25hbWVzLmZ1bGxzY3JlZW5FbmFibGVkID0gImZ1bGxzY3JlZW5FbmFibGVkIjsKICAgICAgICAgIF9uYW1lcy5mdWxsc2NyZWVuRWxlbWVudCA9ICJmdWxsc2NyZWVuRWxlbWVudCI7CiAgICAgICAgICBfbmFtZXMuZnVsbHNjcmVlbmNoYW5nZSA9ICJmdWxsc2NyZWVuY2hhbmdlIjsKICAgICAgICAgIF9uYW1lcy5mdWxsc2NyZWVuZXJyb3IgPSAiZnVsbHNjcmVlbmVycm9yIjsKICAgICAgICAgIF9zdXBwb3J0c0Z1bGxzY3JlZW4gPSB0cnVlOwogICAgICAgICAgcmV0dXJuIF9zdXBwb3J0c0Z1bGxzY3JlZW47CiAgICAgICAgfQogICAgICAgIGNvbnN0IHByZWZpeGVzID0gWyJ3ZWJraXQiLCAibW96IiwgIm8iLCAibXMiLCAia2h0bWwiXTsKICAgICAgICBsZXQgbmFtZTsKICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gcHJlZml4ZXMubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHsKICAgICAgICAgIGNvbnN0IHByZWZpeCA9IHByZWZpeGVzW2ldOwogICAgICAgICAgbmFtZSA9IGAke3ByZWZpeH1SZXF1ZXN0RnVsbHNjcmVlbmA7CiAgICAgICAgICBpZiAodHlwZW9mIGJvZHlbbmFtZV0gPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgICAgX25hbWVzLnJlcXVlc3RGdWxsc2NyZWVuID0gbmFtZTsKICAgICAgICAgICAgX3N1cHBvcnRzRnVsbHNjcmVlbiA9IHRydWU7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBuYW1lID0gYCR7cHJlZml4fVJlcXVlc3RGdWxsU2NyZWVuYDsKICAgICAgICAgICAgaWYgKHR5cGVvZiBib2R5W25hbWVdID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICAgICAgX25hbWVzLnJlcXVlc3RGdWxsc2NyZWVuID0gbmFtZTsKICAgICAgICAgICAgICBfc3VwcG9ydHNGdWxsc2NyZWVuID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgbmFtZSA9IGAke3ByZWZpeH1FeGl0RnVsbHNjcmVlbmA7CiAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50W25hbWVdID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICAgIF9uYW1lcy5leGl0RnVsbHNjcmVlbiA9IG5hbWU7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBuYW1lID0gYCR7cHJlZml4fUNhbmNlbEZ1bGxTY3JlZW5gOwogICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50W25hbWVdID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICAgICAgX25hbWVzLmV4aXRGdWxsc2NyZWVuID0gbmFtZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgbmFtZSA9IGAke3ByZWZpeH1GdWxsc2NyZWVuRW5hYmxlZGA7CiAgICAgICAgICBpZiAoZG9jdW1lbnRbbmFtZV0gIT09IHZvaWQgMCkgewogICAgICAgICAgICBfbmFtZXMuZnVsbHNjcmVlbkVuYWJsZWQgPSBuYW1lOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgbmFtZSA9IGAke3ByZWZpeH1GdWxsU2NyZWVuRW5hYmxlZGA7CiAgICAgICAgICAgIGlmIChkb2N1bWVudFtuYW1lXSAhPT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgX25hbWVzLmZ1bGxzY3JlZW5FbmFibGVkID0gbmFtZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgbmFtZSA9IGAke3ByZWZpeH1GdWxsc2NyZWVuRWxlbWVudGA7CiAgICAgICAgICBpZiAoZG9jdW1lbnRbbmFtZV0gIT09IHZvaWQgMCkgewogICAgICAgICAgICBfbmFtZXMuZnVsbHNjcmVlbkVsZW1lbnQgPSBuYW1lOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgbmFtZSA9IGAke3ByZWZpeH1GdWxsU2NyZWVuRWxlbWVudGA7CiAgICAgICAgICAgIGlmIChkb2N1bWVudFtuYW1lXSAhPT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgX25hbWVzLmZ1bGxzY3JlZW5FbGVtZW50ID0gbmFtZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgbmFtZSA9IGAke3ByZWZpeH1mdWxsc2NyZWVuY2hhbmdlYDsKICAgICAgICAgIGlmIChkb2N1bWVudFtgb24ke25hbWV9YF0gIT09IHZvaWQgMCkgewogICAgICAgICAgICBpZiAocHJlZml4ID09PSAibXMiKSB7CiAgICAgICAgICAgICAgbmFtZSA9ICJNU0Z1bGxzY3JlZW5DaGFuZ2UiOwogICAgICAgICAgICB9CiAgICAgICAgICAgIF9uYW1lcy5mdWxsc2NyZWVuY2hhbmdlID0gbmFtZTsKICAgICAgICAgIH0KICAgICAgICAgIG5hbWUgPSBgJHtwcmVmaXh9ZnVsbHNjcmVlbmVycm9yYDsKICAgICAgICAgIGlmIChkb2N1bWVudFtgb24ke25hbWV9YF0gIT09IHZvaWQgMCkgewogICAgICAgICAgICBpZiAocHJlZml4ID09PSAibXMiKSB7CiAgICAgICAgICAgICAgbmFtZSA9ICJNU0Z1bGxzY3JlZW5FcnJvciI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgX25hbWVzLmZ1bGxzY3JlZW5lcnJvciA9IG5hbWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBfc3VwcG9ydHNGdWxsc2NyZWVuOwogICAgICB9OwogICAgICBGdWxsc2NyZWVuLnJlcXVlc3RGdWxsc2NyZWVuID0gZnVuY3Rpb24oZWxlbWVudCwgdnJEZXZpY2UpIHsKICAgICAgICBpZiAoIUZ1bGxzY3JlZW4uc3VwcG9ydHNGdWxsc2NyZWVuKCkpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgZWxlbWVudFtfbmFtZXMucmVxdWVzdEZ1bGxzY3JlZW5dKHsgdnJEaXNwbGF5OiB2ckRldmljZSB9KTsKICAgICAgfTsKICAgICAgRnVsbHNjcmVlbi5leGl0RnVsbHNjcmVlbiA9IGZ1bmN0aW9uKCkgewogICAgICAgIGlmICghRnVsbHNjcmVlbi5zdXBwb3J0c0Z1bGxzY3JlZW4oKSkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBkb2N1bWVudFtfbmFtZXMuZXhpdEZ1bGxzY3JlZW5dKCk7CiAgICAgIH07CiAgICAgIEZ1bGxzY3JlZW4uX25hbWVzID0gX25hbWVzOwogICAgICBGdWxsc2NyZWVuX2RlZmF1bHQgPSBGdWxsc2NyZWVuOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvRmVhdHVyZURldGVjdGlvbi5qcwogIGZ1bmN0aW9uIGV4dHJhY3RWZXJzaW9uKHZlcnNpb25TdHJpbmcpIHsKICAgIGNvbnN0IHBhcnRzID0gdmVyc2lvblN0cmluZy5zcGxpdCgiLiIpOwogICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHBhcnRzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgIHBhcnRzW2ldID0gcGFyc2VJbnQocGFydHNbaV0sIDEwKTsKICAgIH0KICAgIHJldHVybiBwYXJ0czsKICB9CiAgZnVuY3Rpb24gaXNDaHJvbWUoKSB7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpc0Nocm9tZVJlc3VsdCkpIHsKICAgICAgaXNDaHJvbWVSZXN1bHQgPSBmYWxzZTsKICAgICAgaWYgKCFpc0VkZ2UoKSkgewogICAgICAgIGNvbnN0IGZpZWxkcyA9IC8gQ2hyb21lXC8oW1wuMC05XSspLy5leGVjKHRoZU5hdmlnYXRvci51c2VyQWdlbnQpOwogICAgICAgIGlmIChmaWVsZHMgIT09IG51bGwpIHsKICAgICAgICAgIGlzQ2hyb21lUmVzdWx0ID0gdHJ1ZTsKICAgICAgICAgIGNocm9tZVZlcnNpb25SZXN1bHQgPSBleHRyYWN0VmVyc2lvbihmaWVsZHNbMV0pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIGlzQ2hyb21lUmVzdWx0OwogIH0KICBmdW5jdGlvbiBjaHJvbWVWZXJzaW9uKCkgewogICAgcmV0dXJuIGlzQ2hyb21lKCkgJiYgY2hyb21lVmVyc2lvblJlc3VsdDsKICB9CiAgZnVuY3Rpb24gaXNTYWZhcmkoKSB7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpc1NhZmFyaVJlc3VsdCkpIHsKICAgICAgaXNTYWZhcmlSZXN1bHQgPSBmYWxzZTsKICAgICAgaWYgKCFpc0Nocm9tZSgpICYmICFpc0VkZ2UoKSAmJiAvIFNhZmFyaVwvW1wuMC05XSsvLnRlc3QodGhlTmF2aWdhdG9yLnVzZXJBZ2VudCkpIHsKICAgICAgICBjb25zdCBmaWVsZHMgPSAvIFZlcnNpb25cLyhbXC4wLTldKykvLmV4ZWModGhlTmF2aWdhdG9yLnVzZXJBZ2VudCk7CiAgICAgICAgaWYgKGZpZWxkcyAhPT0gbnVsbCkgewogICAgICAgICAgaXNTYWZhcmlSZXN1bHQgPSB0cnVlOwogICAgICAgICAgc2FmYXJpVmVyc2lvblJlc3VsdCA9IGV4dHJhY3RWZXJzaW9uKGZpZWxkc1sxXSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gaXNTYWZhcmlSZXN1bHQ7CiAgfQogIGZ1bmN0aW9uIHNhZmFyaVZlcnNpb24oKSB7CiAgICByZXR1cm4gaXNTYWZhcmkoKSAmJiBzYWZhcmlWZXJzaW9uUmVzdWx0OwogIH0KICBmdW5jdGlvbiBpc1dlYmtpdCgpIHsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGlzV2Via2l0UmVzdWx0KSkgewogICAgICBpc1dlYmtpdFJlc3VsdCA9IGZhbHNlOwogICAgICBjb25zdCBmaWVsZHMgPSAvIEFwcGxlV2ViS2l0XC8oW1wuMC05XSspKFwrPykvLmV4ZWModGhlTmF2aWdhdG9yLnVzZXJBZ2VudCk7CiAgICAgIGlmIChmaWVsZHMgIT09IG51bGwpIHsKICAgICAgICBpc1dlYmtpdFJlc3VsdCA9IHRydWU7CiAgICAgICAgd2Via2l0VmVyc2lvblJlc3VsdCA9IGV4dHJhY3RWZXJzaW9uKGZpZWxkc1sxXSk7CiAgICAgICAgd2Via2l0VmVyc2lvblJlc3VsdC5pc05pZ2h0bHkgPSAhIWZpZWxkc1syXTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGlzV2Via2l0UmVzdWx0OwogIH0KICBmdW5jdGlvbiB3ZWJraXRWZXJzaW9uKCkgewogICAgcmV0dXJuIGlzV2Via2l0KCkgJiYgd2Via2l0VmVyc2lvblJlc3VsdDsKICB9CiAgZnVuY3Rpb24gaXNJbnRlcm5ldEV4cGxvcmVyKCkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaXNJbnRlcm5ldEV4cGxvcmVyUmVzdWx0KSkgewogICAgICBpc0ludGVybmV0RXhwbG9yZXJSZXN1bHQgPSBmYWxzZTsKICAgICAgbGV0IGZpZWxkczsKICAgICAgaWYgKHRoZU5hdmlnYXRvci5hcHBOYW1lID09PSAiTWljcm9zb2Z0IEludGVybmV0IEV4cGxvcmVyIikgewogICAgICAgIGZpZWxkcyA9IC9NU0lFIChbMC05XXsxLH1bXC4wLTldezAsfSkvLmV4ZWModGhlTmF2aWdhdG9yLnVzZXJBZ2VudCk7CiAgICAgICAgaWYgKGZpZWxkcyAhPT0gbnVsbCkgewogICAgICAgICAgaXNJbnRlcm5ldEV4cGxvcmVyUmVzdWx0ID0gdHJ1ZTsKICAgICAgICAgIGludGVybmV0RXhwbG9yZXJWZXJzaW9uUmVzdWx0ID0gZXh0cmFjdFZlcnNpb24oZmllbGRzWzFdKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAodGhlTmF2aWdhdG9yLmFwcE5hbWUgPT09ICJOZXRzY2FwZSIpIHsKICAgICAgICBmaWVsZHMgPSAvVHJpZGVudFwvLipydjooWzAtOV17MSx9W1wuMC05XXswLH0pLy5leGVjKAogICAgICAgICAgdGhlTmF2aWdhdG9yLnVzZXJBZ2VudAogICAgICAgICk7CiAgICAgICAgaWYgKGZpZWxkcyAhPT0gbnVsbCkgewogICAgICAgICAgaXNJbnRlcm5ldEV4cGxvcmVyUmVzdWx0ID0gdHJ1ZTsKICAgICAgICAgIGludGVybmV0RXhwbG9yZXJWZXJzaW9uUmVzdWx0ID0gZXh0cmFjdFZlcnNpb24oZmllbGRzWzFdKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBpc0ludGVybmV0RXhwbG9yZXJSZXN1bHQ7CiAgfQogIGZ1bmN0aW9uIGludGVybmV0RXhwbG9yZXJWZXJzaW9uKCkgewogICAgcmV0dXJuIGlzSW50ZXJuZXRFeHBsb3JlcigpICYmIGludGVybmV0RXhwbG9yZXJWZXJzaW9uUmVzdWx0OwogIH0KICBmdW5jdGlvbiBpc0VkZ2UoKSB7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpc0VkZ2VSZXN1bHQpKSB7CiAgICAgIGlzRWRnZVJlc3VsdCA9IGZhbHNlOwogICAgICBjb25zdCBmaWVsZHMgPSAvIEVkZ1wvKFtcLjAtOV0rKS8uZXhlYyh0aGVOYXZpZ2F0b3IudXNlckFnZW50KTsKICAgICAgaWYgKGZpZWxkcyAhPT0gbnVsbCkgewogICAgICAgIGlzRWRnZVJlc3VsdCA9IHRydWU7CiAgICAgICAgZWRnZVZlcnNpb25SZXN1bHQgPSBleHRyYWN0VmVyc2lvbihmaWVsZHNbMV0pOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gaXNFZGdlUmVzdWx0OwogIH0KICBmdW5jdGlvbiBlZGdlVmVyc2lvbigpIHsKICAgIHJldHVybiBpc0VkZ2UoKSAmJiBlZGdlVmVyc2lvblJlc3VsdDsKICB9CiAgZnVuY3Rpb24gaXNGaXJlZm94KCkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaXNGaXJlZm94UmVzdWx0KSkgewogICAgICBpc0ZpcmVmb3hSZXN1bHQgPSBmYWxzZTsKICAgICAgY29uc3QgZmllbGRzID0gL0ZpcmVmb3hcLyhbXC4wLTldKykvLmV4ZWModGhlTmF2aWdhdG9yLnVzZXJBZ2VudCk7CiAgICAgIGlmIChmaWVsZHMgIT09IG51bGwpIHsKICAgICAgICBpc0ZpcmVmb3hSZXN1bHQgPSB0cnVlOwogICAgICAgIGZpcmVmb3hWZXJzaW9uUmVzdWx0ID0gZXh0cmFjdFZlcnNpb24oZmllbGRzWzFdKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGlzRmlyZWZveFJlc3VsdDsKICB9CiAgZnVuY3Rpb24gaXNXaW5kb3dzKCkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaXNXaW5kb3dzUmVzdWx0KSkgewogICAgICBpc1dpbmRvd3NSZXN1bHQgPSAvV2luZG93cy9pLnRlc3QodGhlTmF2aWdhdG9yLmFwcFZlcnNpb24pOwogICAgfQogICAgcmV0dXJuIGlzV2luZG93c1Jlc3VsdDsKICB9CiAgZnVuY3Rpb24gaXNJUGFkT3JJT1MoKSB7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpc0lQYWRPcklPU1Jlc3VsdCkpIHsKICAgICAgaXNJUGFkT3JJT1NSZXN1bHQgPSBuYXZpZ2F0b3IucGxhdGZvcm0gPT09ICJpUGhvbmUiIHx8IG5hdmlnYXRvci5wbGF0Zm9ybSA9PT0gImlQb2QiIHx8IG5hdmlnYXRvci5wbGF0Zm9ybSA9PT0gImlQYWQiOwogICAgfQogICAgcmV0dXJuIGlzSVBhZE9ySU9TUmVzdWx0OwogIH0KICBmdW5jdGlvbiBmaXJlZm94VmVyc2lvbigpIHsKICAgIHJldHVybiBpc0ZpcmVmb3goKSAmJiBmaXJlZm94VmVyc2lvblJlc3VsdDsKICB9CiAgZnVuY3Rpb24gc3VwcG9ydHNQb2ludGVyRXZlbnRzKCkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaGFzUG9pbnRlckV2ZW50cykpIHsKICAgICAgaGFzUG9pbnRlckV2ZW50cyA9ICFpc0ZpcmVmb3goKSAmJiB0eXBlb2YgUG9pbnRlckV2ZW50ICE9PSAidW5kZWZpbmVkIiAmJiAoIWRlZmluZWRfZGVmYXVsdCh0aGVOYXZpZ2F0b3IucG9pbnRlckVuYWJsZWQpIHx8IHRoZU5hdmlnYXRvci5wb2ludGVyRW5hYmxlZCk7CiAgICB9CiAgICByZXR1cm4gaGFzUG9pbnRlckV2ZW50czsKICB9CiAgZnVuY3Rpb24gc3VwcG9ydHNJbWFnZVJlbmRlcmluZ1BpeGVsYXRlZCgpIHsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHN1cHBvcnRzSW1hZ2VSZW5kZXJpbmdQaXhlbGF0ZWRSZXN1bHQpKSB7CiAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImNhbnZhcyIpOwogICAgICBjYW52YXMuc2V0QXR0cmlidXRlKAogICAgICAgICJzdHlsZSIsCiAgICAgICAgImltYWdlLXJlbmRlcmluZzogLW1vei1jcmlzcC1lZGdlcztpbWFnZS1yZW5kZXJpbmc6IHBpeGVsYXRlZDsiCiAgICAgICk7CiAgICAgIGNvbnN0IHRtcDIgPSBjYW52YXMuc3R5bGUuaW1hZ2VSZW5kZXJpbmc7CiAgICAgIHN1cHBvcnRzSW1hZ2VSZW5kZXJpbmdQaXhlbGF0ZWRSZXN1bHQgPSBkZWZpbmVkX2RlZmF1bHQodG1wMikgJiYgdG1wMiAhPT0gIiI7CiAgICAgIGlmIChzdXBwb3J0c0ltYWdlUmVuZGVyaW5nUGl4ZWxhdGVkUmVzdWx0KSB7CiAgICAgICAgaW1hZ2VSZW5kZXJpbmdWYWx1ZVJlc3VsdCA9IHRtcDI7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzdXBwb3J0c0ltYWdlUmVuZGVyaW5nUGl4ZWxhdGVkUmVzdWx0OwogIH0KICBmdW5jdGlvbiBpbWFnZVJlbmRlcmluZ1ZhbHVlKCkgewogICAgcmV0dXJuIHN1cHBvcnRzSW1hZ2VSZW5kZXJpbmdQaXhlbGF0ZWQoKSA/IGltYWdlUmVuZGVyaW5nVmFsdWVSZXN1bHQgOiB2b2lkIDA7CiAgfQogIGZ1bmN0aW9uIHN1cHBvcnRzV2ViUCgpIHsKICAgIGlmICghc3VwcG9ydHNXZWJQLmluaXRpYWxpemVkKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICJZb3UgbXVzdCBjYWxsIEZlYXR1cmVEZXRlY3Rpb24uc3VwcG9ydHNXZWJQLmluaXRpYWxpemUgYW5kIHdhaXQgZm9yIHRoZSBwcm9taXNlIHRvIHJlc29sdmUgYmVmb3JlIGNhbGxpbmcgRmVhdHVyZURldGVjdGlvbi5zdXBwb3J0c1dlYlAiCiAgICAgICk7CiAgICB9CiAgICByZXR1cm4gc3VwcG9ydHNXZWJQLl9yZXN1bHQ7CiAgfQogIHZhciB0aGVOYXZpZ2F0b3IsIGlzQ2hyb21lUmVzdWx0LCBjaHJvbWVWZXJzaW9uUmVzdWx0LCBpc1NhZmFyaVJlc3VsdCwgc2FmYXJpVmVyc2lvblJlc3VsdCwgaXNXZWJraXRSZXN1bHQsIHdlYmtpdFZlcnNpb25SZXN1bHQsIGlzSW50ZXJuZXRFeHBsb3JlclJlc3VsdCwgaW50ZXJuZXRFeHBsb3JlclZlcnNpb25SZXN1bHQsIGlzRWRnZVJlc3VsdCwgZWRnZVZlcnNpb25SZXN1bHQsIGlzRmlyZWZveFJlc3VsdCwgZmlyZWZveFZlcnNpb25SZXN1bHQsIGlzV2luZG93c1Jlc3VsdCwgaXNJUGFkT3JJT1NSZXN1bHQsIGhhc1BvaW50ZXJFdmVudHMsIGltYWdlUmVuZGVyaW5nVmFsdWVSZXN1bHQsIHN1cHBvcnRzSW1hZ2VSZW5kZXJpbmdQaXhlbGF0ZWRSZXN1bHQsIHR5cGVkQXJyYXlUeXBlcywgRmVhdHVyZURldGVjdGlvbiwgRmVhdHVyZURldGVjdGlvbl9kZWZhdWx0OwogIHZhciBpbml0X0ZlYXR1cmVEZXRlY3Rpb24gPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0ZlYXR1cmVEZXRlY3Rpb24uanMiKCkgewogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfRnVsbHNjcmVlbigpOwogICAgICBpZiAodHlwZW9mIG5hdmlnYXRvciAhPT0gInVuZGVmaW5lZCIpIHsKICAgICAgICB0aGVOYXZpZ2F0b3IgPSBuYXZpZ2F0b3I7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhlTmF2aWdhdG9yID0ge307CiAgICAgIH0KICAgICAgc3VwcG9ydHNXZWJQLl9wcm9taXNlID0gdm9pZCAwOwogICAgICBzdXBwb3J0c1dlYlAuX3Jlc3VsdCA9IHZvaWQgMDsKICAgICAgc3VwcG9ydHNXZWJQLmluaXRpYWxpemUgPSBmdW5jdGlvbigpIHsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHN1cHBvcnRzV2ViUC5fcHJvbWlzZSkpIHsKICAgICAgICAgIHJldHVybiBzdXBwb3J0c1dlYlAuX3Byb21pc2U7CiAgICAgICAgfQogICAgICAgIHN1cHBvcnRzV2ViUC5fcHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7CiAgICAgICAgICBjb25zdCBpbWFnZSA9IG5ldyBJbWFnZSgpOwogICAgICAgICAgaW1hZ2Uub25sb2FkID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHN1cHBvcnRzV2ViUC5fcmVzdWx0ID0gaW1hZ2Uud2lkdGggPiAwICYmIGltYWdlLmhlaWdodCA+IDA7CiAgICAgICAgICAgIHJlc29sdmUoc3VwcG9ydHNXZWJQLl9yZXN1bHQpOwogICAgICAgICAgfTsKICAgICAgICAgIGltYWdlLm9uZXJyb3IgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgc3VwcG9ydHNXZWJQLl9yZXN1bHQgPSBmYWxzZTsKICAgICAgICAgICAgcmVzb2x2ZShzdXBwb3J0c1dlYlAuX3Jlc3VsdCk7CiAgICAgICAgICB9OwogICAgICAgICAgaW1hZ2Uuc3JjID0gImRhdGE6aW1hZ2Uvd2VicDtiYXNlNjQsVWtsR1JpSUFBQUJYUlVKUVZsQTRJQllBQUFBd0FRQ2RBU29CQUFFQURzRCtKYVFBQTNBQUFBQUEiOwogICAgICAgIH0pOwogICAgICAgIHJldHVybiBzdXBwb3J0c1dlYlAuX3Byb21pc2U7CiAgICAgIH07CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKHN1cHBvcnRzV2ViUCwgewogICAgICAgIGluaXRpYWxpemVkOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gZGVmaW5lZF9kZWZhdWx0KHN1cHBvcnRzV2ViUC5fcmVzdWx0KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICB0eXBlZEFycmF5VHlwZXMgPSBbXTsKICAgICAgaWYgKHR5cGVvZiBBcnJheUJ1ZmZlciAhPT0gInVuZGVmaW5lZCIpIHsKICAgICAgICB0eXBlZEFycmF5VHlwZXMucHVzaCgKICAgICAgICAgIEludDhBcnJheSwKICAgICAgICAgIFVpbnQ4QXJyYXksCiAgICAgICAgICBJbnQxNkFycmF5LAogICAgICAgICAgVWludDE2QXJyYXksCiAgICAgICAgICBJbnQzMkFycmF5LAogICAgICAgICAgVWludDMyQXJyYXksCiAgICAgICAgICBGbG9hdDMyQXJyYXksCiAgICAgICAgICBGbG9hdDY0QXJyYXkKICAgICAgICApOwogICAgICAgIGlmICh0eXBlb2YgVWludDhDbGFtcGVkQXJyYXkgIT09ICJ1bmRlZmluZWQiKSB7CiAgICAgICAgICB0eXBlZEFycmF5VHlwZXMucHVzaChVaW50OENsYW1wZWRBcnJheSk7CiAgICAgICAgfQogICAgICAgIGlmICh0eXBlb2YgVWludDhDbGFtcGVkQXJyYXkgIT09ICJ1bmRlZmluZWQiKSB7CiAgICAgICAgICB0eXBlZEFycmF5VHlwZXMucHVzaChVaW50OENsYW1wZWRBcnJheSk7CiAgICAgICAgfQogICAgICAgIGlmICh0eXBlb2YgQmlnSW50NjRBcnJheSAhPT0gInVuZGVmaW5lZCIpIHsKICAgICAgICAgIHR5cGVkQXJyYXlUeXBlcy5wdXNoKEJpZ0ludDY0QXJyYXkpOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIEJpZ1VpbnQ2NEFycmF5ICE9PSAidW5kZWZpbmVkIikgewogICAgICAgICAgdHlwZWRBcnJheVR5cGVzLnB1c2goQmlnVWludDY0QXJyYXkpOwogICAgICAgIH0KICAgICAgfQogICAgICBGZWF0dXJlRGV0ZWN0aW9uID0gewogICAgICAgIGlzQ2hyb21lLAogICAgICAgIGNocm9tZVZlcnNpb24sCiAgICAgICAgaXNTYWZhcmksCiAgICAgICAgc2FmYXJpVmVyc2lvbiwKICAgICAgICBpc1dlYmtpdCwKICAgICAgICB3ZWJraXRWZXJzaW9uLAogICAgICAgIGlzSW50ZXJuZXRFeHBsb3JlciwKICAgICAgICBpbnRlcm5ldEV4cGxvcmVyVmVyc2lvbiwKICAgICAgICBpc0VkZ2UsCiAgICAgICAgZWRnZVZlcnNpb24sCiAgICAgICAgaXNGaXJlZm94LAogICAgICAgIGZpcmVmb3hWZXJzaW9uLAogICAgICAgIGlzV2luZG93cywKICAgICAgICBpc0lQYWRPcklPUywKICAgICAgICBoYXJkd2FyZUNvbmN1cnJlbmN5OiB0aGVOYXZpZ2F0b3IuaGFyZHdhcmVDb25jdXJyZW5jeSA/PyAzLAogICAgICAgIHN1cHBvcnRzUG9pbnRlckV2ZW50cywKICAgICAgICBzdXBwb3J0c0ltYWdlUmVuZGVyaW5nUGl4ZWxhdGVkLAogICAgICAgIHN1cHBvcnRzV2ViUCwKICAgICAgICBpbWFnZVJlbmRlcmluZ1ZhbHVlLAogICAgICAgIHR5cGVkQXJyYXlUeXBlcwogICAgICB9OwogICAgICBGZWF0dXJlRGV0ZWN0aW9uLnN1cHBvcnRzQmFzaXMgPSBmdW5jdGlvbihzY2VuZSkgewogICAgICAgIHJldHVybiBGZWF0dXJlRGV0ZWN0aW9uLnN1cHBvcnRzV2ViQXNzZW1ibHkoKSAmJiBzY2VuZS5jb250ZXh0LnN1cHBvcnRzQmFzaXM7CiAgICAgIH07CiAgICAgIEZlYXR1cmVEZXRlY3Rpb24uc3VwcG9ydHNGdWxsc2NyZWVuID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIEZ1bGxzY3JlZW5fZGVmYXVsdC5zdXBwb3J0c0Z1bGxzY3JlZW4oKTsKICAgICAgfTsKICAgICAgRmVhdHVyZURldGVjdGlvbi5zdXBwb3J0c1R5cGVkQXJyYXlzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIHR5cGVvZiBBcnJheUJ1ZmZlciAhPT0gInVuZGVmaW5lZCI7CiAgICAgIH07CiAgICAgIEZlYXR1cmVEZXRlY3Rpb24uc3VwcG9ydHNCaWdJbnQ2NEFycmF5ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIHR5cGVvZiBCaWdJbnQ2NEFycmF5ICE9PSAidW5kZWZpbmVkIjsKICAgICAgfTsKICAgICAgRmVhdHVyZURldGVjdGlvbi5zdXBwb3J0c0JpZ1VpbnQ2NEFycmF5ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIHR5cGVvZiBCaWdVaW50NjRBcnJheSAhPT0gInVuZGVmaW5lZCI7CiAgICAgIH07CiAgICAgIEZlYXR1cmVEZXRlY3Rpb24uc3VwcG9ydHNCaWdJbnQgPSBmdW5jdGlvbigpIHsKICAgICAgICByZXR1cm4gdHlwZW9mIEJpZ0ludCAhPT0gInVuZGVmaW5lZCI7CiAgICAgIH07CiAgICAgIEZlYXR1cmVEZXRlY3Rpb24uc3VwcG9ydHNXZWJXb3JrZXJzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIHR5cGVvZiBXb3JrZXIgIT09ICJ1bmRlZmluZWQiOwogICAgICB9OwogICAgICBGZWF0dXJlRGV0ZWN0aW9uLnN1cHBvcnRzV2ViQXNzZW1ibHkgPSBmdW5jdGlvbigpIHsKICAgICAgICByZXR1cm4gdHlwZW9mIFdlYkFzc2VtYmx5ICE9PSAidW5kZWZpbmVkIjsKICAgICAgfTsKICAgICAgRmVhdHVyZURldGVjdGlvbi5zdXBwb3J0c1dlYmdsMiA9IGZ1bmN0aW9uKHNjZW5lKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJzY2VuZSIsIHNjZW5lKTsKICAgICAgICByZXR1cm4gc2NlbmUuY29udGV4dC53ZWJnbDI7CiAgICAgIH07CiAgICAgIEZlYXR1cmVEZXRlY3Rpb24uc3VwcG9ydHNFc21XZWJXb3JrZXJzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuICFpc0ZpcmVmb3goKSB8fCBwYXJzZUludChmaXJlZm94VmVyc2lvblJlc3VsdCkgPj0gMTE0OwogICAgICB9OwogICAgICBGZWF0dXJlRGV0ZWN0aW9uX2RlZmF1bHQgPSBGZWF0dXJlRGV0ZWN0aW9uOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUXVhdGVybmlvbi5qcwogIGZ1bmN0aW9uIFF1YXRlcm5pb24oeCwgeSwgeiwgdykgewogICAgdGhpcy54ID0geCA/PyAwOwogICAgdGhpcy55ID0geSA/PyAwOwogICAgdGhpcy56ID0geiA/PyAwOwogICAgdGhpcy53ID0gdyA/PyAwOwogIH0KICB2YXIgZnJvbUF4aXNBbmdsZVNjcmF0Y2gsIGZyb21Sb3RhdGlvbk1hdHJpeE5leHQsIGZyb21Sb3RhdGlvbk1hdHJpeFF1YXQsIHNjcmF0Y2hIUFJRdWF0ZXJuaW9uLCBzY3JhdGNoSGVhZGluZ1F1YXRlcm5pb24sIHNjcmF0Y2hQaXRjaFF1YXRlcm5pb24sIHNjcmF0Y2hSb2xsUXVhdGVybmlvbiwgc2FtcGxlZFF1YXRlcm5pb25BeGlzLCBzYW1wbGVkUXVhdGVybmlvblJvdGF0aW9uLCBzYW1wbGVkUXVhdGVybmlvblRlbXBRdWF0ZXJuaW9uLCBzYW1wbGVkUXVhdGVybmlvblF1YXRlcm5pb24wLCBzYW1wbGVkUXVhdGVybmlvblF1YXRlcm5pb24wQ29uanVnYXRlLCBsZXJwU2NyYXRjaDQsIHNsZXJwRW5kTmVnYXRlZCwgc2xlcnBTY2FsZWRQLCBzbGVycFNjYWxlZFIsIHNxdWFkU2NyYXRjaENhcnRlc2lhbjAsIHNxdWFkU2NyYXRjaENhcnRlc2lhbjEsIHNxdWFkU2NyYXRjaFF1YXRlcm5pb24wLCBzcXVhZFNjcmF0Y2hRdWF0ZXJuaW9uMSwgZmFzdFNsZXJwU2NyYXRjaFF1YXRlcm5pb24sIG9wbXUsIHUsIHYsIGJULCBiRCwgUXVhdGVybmlvbl9kZWZhdWx0OwogIHZhciBpbml0X1F1YXRlcm5pb24gPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1F1YXRlcm5pb24uanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9GZWF0dXJlRGV0ZWN0aW9uKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X01hdHJpeDMoKTsKICAgICAgZnJvbUF4aXNBbmdsZVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIFF1YXRlcm5pb24uZnJvbUF4aXNBbmdsZSA9IGZ1bmN0aW9uKGF4aXMsIGFuZ2xlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImF4aXMiLCBheGlzKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoImFuZ2xlIiwgYW5nbGUpOwogICAgICAgIGNvbnN0IGhhbGZBbmdsZSA9IGFuZ2xlIC8gMjsKICAgICAgICBjb25zdCBzID0gTWF0aC5zaW4oaGFsZkFuZ2xlKTsKICAgICAgICBmcm9tQXhpc0FuZ2xlU2NyYXRjaCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoYXhpcywgZnJvbUF4aXNBbmdsZVNjcmF0Y2gpOwogICAgICAgIGNvbnN0IHggPSBmcm9tQXhpc0FuZ2xlU2NyYXRjaC54ICogczsKICAgICAgICBjb25zdCB5ID0gZnJvbUF4aXNBbmdsZVNjcmF0Y2gueSAqIHM7CiAgICAgICAgY29uc3QgeiA9IGZyb21BeGlzQW5nbGVTY3JhdGNoLnogKiBzOwogICAgICAgIGNvbnN0IHcgPSBNYXRoLmNvcyhoYWxmQW5nbGUpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgUXVhdGVybmlvbih4LCB5LCB6LCB3KTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnggPSB4OwogICAgICAgIHJlc3VsdC55ID0geTsKICAgICAgICByZXN1bHQueiA9IHo7CiAgICAgICAgcmVzdWx0LncgPSB3OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIGZyb21Sb3RhdGlvbk1hdHJpeE5leHQgPSBbMSwgMiwgMF07CiAgICAgIGZyb21Sb3RhdGlvbk1hdHJpeFF1YXQgPSBuZXcgQXJyYXkoMyk7CiAgICAgIFF1YXRlcm5pb24uZnJvbVJvdGF0aW9uTWF0cml4ID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgbGV0IHJvb3Q7CiAgICAgICAgbGV0IHg7CiAgICAgICAgbGV0IHk7CiAgICAgICAgbGV0IHo7CiAgICAgICAgbGV0IHc7CiAgICAgICAgY29uc3QgbTAwID0gbWF0cml4W01hdHJpeDNfZGVmYXVsdC5DT0xVTU4wUk9XMF07CiAgICAgICAgY29uc3QgbTExID0gbWF0cml4W01hdHJpeDNfZGVmYXVsdC5DT0xVTU4xUk9XMV07CiAgICAgICAgY29uc3QgbTIyID0gbWF0cml4W01hdHJpeDNfZGVmYXVsdC5DT0xVTU4yUk9XMl07CiAgICAgICAgY29uc3QgdHJhY2UgPSBtMDAgKyBtMTEgKyBtMjI7CiAgICAgICAgaWYgKHRyYWNlID4gMCkgewogICAgICAgICAgcm9vdCA9IE1hdGguc3FydCh0cmFjZSArIDEpOwogICAgICAgICAgdyA9IDAuNSAqIHJvb3Q7CiAgICAgICAgICByb290ID0gMC41IC8gcm9vdDsKICAgICAgICAgIHggPSAobWF0cml4W01hdHJpeDNfZGVmYXVsdC5DT0xVTU4xUk9XMl0gLSBtYXRyaXhbTWF0cml4M19kZWZhdWx0LkNPTFVNTjJST1cxXSkgKiByb290OwogICAgICAgICAgeSA9IChtYXRyaXhbTWF0cml4M19kZWZhdWx0LkNPTFVNTjJST1cwXSAtIG1hdHJpeFtNYXRyaXgzX2RlZmF1bHQuQ09MVU1OMFJPVzJdKSAqIHJvb3Q7CiAgICAgICAgICB6ID0gKG1hdHJpeFtNYXRyaXgzX2RlZmF1bHQuQ09MVU1OMFJPVzFdIC0gbWF0cml4W01hdHJpeDNfZGVmYXVsdC5DT0xVTU4xUk9XMF0pICogcm9vdDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgbmV4dCA9IGZyb21Sb3RhdGlvbk1hdHJpeE5leHQ7CiAgICAgICAgICBsZXQgaSA9IDA7CiAgICAgICAgICBpZiAobTExID4gbTAwKSB7CiAgICAgICAgICAgIGkgPSAxOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG0yMiA+IG0wMCAmJiBtMjIgPiBtMTEpIHsKICAgICAgICAgICAgaSA9IDI7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBqID0gbmV4dFtpXTsKICAgICAgICAgIGNvbnN0IGsgPSBuZXh0W2pdOwogICAgICAgICAgcm9vdCA9IE1hdGguc3FydCgKICAgICAgICAgICAgbWF0cml4W01hdHJpeDNfZGVmYXVsdC5nZXRFbGVtZW50SW5kZXgoaSwgaSldIC0gbWF0cml4W01hdHJpeDNfZGVmYXVsdC5nZXRFbGVtZW50SW5kZXgoaiwgaildIC0gbWF0cml4W01hdHJpeDNfZGVmYXVsdC5nZXRFbGVtZW50SW5kZXgoaywgayldICsgMQogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IHF1YXQgPSBmcm9tUm90YXRpb25NYXRyaXhRdWF0OwogICAgICAgICAgcXVhdFtpXSA9IDAuNSAqIHJvb3Q7CiAgICAgICAgICByb290ID0gMC41IC8gcm9vdDsKICAgICAgICAgIHcgPSAobWF0cml4W01hdHJpeDNfZGVmYXVsdC5nZXRFbGVtZW50SW5kZXgoaywgaildIC0gbWF0cml4W01hdHJpeDNfZGVmYXVsdC5nZXRFbGVtZW50SW5kZXgoaiwgayldKSAqIHJvb3Q7CiAgICAgICAgICBxdWF0W2pdID0gKG1hdHJpeFtNYXRyaXgzX2RlZmF1bHQuZ2V0RWxlbWVudEluZGV4KGosIGkpXSArIG1hdHJpeFtNYXRyaXgzX2RlZmF1bHQuZ2V0RWxlbWVudEluZGV4KGksIGopXSkgKiByb290OwogICAgICAgICAgcXVhdFtrXSA9IChtYXRyaXhbTWF0cml4M19kZWZhdWx0LmdldEVsZW1lbnRJbmRleChrLCBpKV0gKyBtYXRyaXhbTWF0cml4M19kZWZhdWx0LmdldEVsZW1lbnRJbmRleChpLCBrKV0pICogcm9vdDsKICAgICAgICAgIHggPSAtcXVhdFswXTsKICAgICAgICAgIHkgPSAtcXVhdFsxXTsKICAgICAgICAgIHogPSAtcXVhdFsyXTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBRdWF0ZXJuaW9uKHgsIHksIHosIHcpOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IHg7CiAgICAgICAgcmVzdWx0LnkgPSB5OwogICAgICAgIHJlc3VsdC56ID0gejsKICAgICAgICByZXN1bHQudyA9IHc7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NyYXRjaEhQUlF1YXRlcm5pb24gPSBuZXcgUXVhdGVybmlvbigpOwogICAgICBzY3JhdGNoSGVhZGluZ1F1YXRlcm5pb24gPSBuZXcgUXVhdGVybmlvbigpOwogICAgICBzY3JhdGNoUGl0Y2hRdWF0ZXJuaW9uID0gbmV3IFF1YXRlcm5pb24oKTsKICAgICAgc2NyYXRjaFJvbGxRdWF0ZXJuaW9uID0gbmV3IFF1YXRlcm5pb24oKTsKICAgICAgUXVhdGVybmlvbi5mcm9tSGVhZGluZ1BpdGNoUm9sbCA9IGZ1bmN0aW9uKGhlYWRpbmdQaXRjaFJvbGwsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiaGVhZGluZ1BpdGNoUm9sbCIsIGhlYWRpbmdQaXRjaFJvbGwpOwogICAgICAgIHNjcmF0Y2hSb2xsUXVhdGVybmlvbiA9IFF1YXRlcm5pb24uZnJvbUF4aXNBbmdsZSgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1gsCiAgICAgICAgICBoZWFkaW5nUGl0Y2hSb2xsLnJvbGwsCiAgICAgICAgICBzY3JhdGNoSFBSUXVhdGVybmlvbgogICAgICAgICk7CiAgICAgICAgc2NyYXRjaFBpdGNoUXVhdGVybmlvbiA9IFF1YXRlcm5pb24uZnJvbUF4aXNBbmdsZSgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1ksCiAgICAgICAgICAtaGVhZGluZ1BpdGNoUm9sbC5waXRjaCwKICAgICAgICAgIHJlc3VsdAogICAgICAgICk7CiAgICAgICAgcmVzdWx0ID0gUXVhdGVybmlvbi5tdWx0aXBseSgKICAgICAgICAgIHNjcmF0Y2hQaXRjaFF1YXRlcm5pb24sCiAgICAgICAgICBzY3JhdGNoUm9sbFF1YXRlcm5pb24sCiAgICAgICAgICBzY3JhdGNoUGl0Y2hRdWF0ZXJuaW9uCiAgICAgICAgKTsKICAgICAgICBzY3JhdGNoSGVhZGluZ1F1YXRlcm5pb24gPSBRdWF0ZXJuaW9uLmZyb21BeGlzQW5nbGUoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9aLAogICAgICAgICAgLWhlYWRpbmdQaXRjaFJvbGwuaGVhZGluZywKICAgICAgICAgIHNjcmF0Y2hIUFJRdWF0ZXJuaW9uCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gUXVhdGVybmlvbi5tdWx0aXBseShzY3JhdGNoSGVhZGluZ1F1YXRlcm5pb24sIHJlc3VsdCwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgc2FtcGxlZFF1YXRlcm5pb25BeGlzID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzYW1wbGVkUXVhdGVybmlvblJvdGF0aW9uID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzYW1wbGVkUXVhdGVybmlvblRlbXBRdWF0ZXJuaW9uID0gbmV3IFF1YXRlcm5pb24oKTsKICAgICAgc2FtcGxlZFF1YXRlcm5pb25RdWF0ZXJuaW9uMCA9IG5ldyBRdWF0ZXJuaW9uKCk7CiAgICAgIHNhbXBsZWRRdWF0ZXJuaW9uUXVhdGVybmlvbjBDb25qdWdhdGUgPSBuZXcgUXVhdGVybmlvbigpOwogICAgICBRdWF0ZXJuaW9uLnBhY2tlZExlbmd0aCA9IDQ7CiAgICAgIFF1YXRlcm5pb24ucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS54OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS55OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS56OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXhdID0gdmFsdWUudzsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIFF1YXRlcm5pb24udW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgUXVhdGVybmlvbigpOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIHJlc3VsdC55ID0gYXJyYXlbc3RhcnRpbmdJbmRleCArIDFdOwogICAgICAgIHJlc3VsdC56ID0gYXJyYXlbc3RhcnRpbmdJbmRleCArIDJdOwogICAgICAgIHJlc3VsdC53ID0gYXJyYXlbc3RhcnRpbmdJbmRleCArIDNdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFF1YXRlcm5pb24ucGFja2VkSW50ZXJwb2xhdGlvbkxlbmd0aCA9IDM7CiAgICAgIFF1YXRlcm5pb24uY29udmVydFBhY2tlZEFycmF5Rm9ySW50ZXJwb2xhdGlvbiA9IGZ1bmN0aW9uKHBhY2tlZEFycmF5LCBzdGFydGluZ0luZGV4LCBsYXN0SW5kZXgsIHJlc3VsdCkgewogICAgICAgIFF1YXRlcm5pb24udW5wYWNrKAogICAgICAgICAgcGFja2VkQXJyYXksCiAgICAgICAgICBsYXN0SW5kZXggKiA0LAogICAgICAgICAgc2FtcGxlZFF1YXRlcm5pb25RdWF0ZXJuaW9uMENvbmp1Z2F0ZQogICAgICAgICk7CiAgICAgICAgUXVhdGVybmlvbi5jb25qdWdhdGUoCiAgICAgICAgICBzYW1wbGVkUXVhdGVybmlvblF1YXRlcm5pb24wQ29uanVnYXRlLAogICAgICAgICAgc2FtcGxlZFF1YXRlcm5pb25RdWF0ZXJuaW9uMENvbmp1Z2F0ZQogICAgICAgICk7CiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IGxhc3RJbmRleCAtIHN0YXJ0aW5nSW5kZXggKyAxOyBpIDwgbGVuOyBpKyspIHsKICAgICAgICAgIGNvbnN0IG9mZnNldCA9IGkgKiAzOwogICAgICAgICAgUXVhdGVybmlvbi51bnBhY2soCiAgICAgICAgICAgIHBhY2tlZEFycmF5LAogICAgICAgICAgICAoc3RhcnRpbmdJbmRleCArIGkpICogNCwKICAgICAgICAgICAgc2FtcGxlZFF1YXRlcm5pb25UZW1wUXVhdGVybmlvbgogICAgICAgICAgKTsKICAgICAgICAgIFF1YXRlcm5pb24ubXVsdGlwbHkoCiAgICAgICAgICAgIHNhbXBsZWRRdWF0ZXJuaW9uVGVtcFF1YXRlcm5pb24sCiAgICAgICAgICAgIHNhbXBsZWRRdWF0ZXJuaW9uUXVhdGVybmlvbjBDb25qdWdhdGUsCiAgICAgICAgICAgIHNhbXBsZWRRdWF0ZXJuaW9uVGVtcFF1YXRlcm5pb24KICAgICAgICAgICk7CiAgICAgICAgICBpZiAoc2FtcGxlZFF1YXRlcm5pb25UZW1wUXVhdGVybmlvbi53IDwgMCkgewogICAgICAgICAgICBRdWF0ZXJuaW9uLm5lZ2F0ZSgKICAgICAgICAgICAgICBzYW1wbGVkUXVhdGVybmlvblRlbXBRdWF0ZXJuaW9uLAogICAgICAgICAgICAgIHNhbXBsZWRRdWF0ZXJuaW9uVGVtcFF1YXRlcm5pb24KICAgICAgICAgICAgKTsKICAgICAgICAgIH0KICAgICAgICAgIFF1YXRlcm5pb24uY29tcHV0ZUF4aXMoCiAgICAgICAgICAgIHNhbXBsZWRRdWF0ZXJuaW9uVGVtcFF1YXRlcm5pb24sCiAgICAgICAgICAgIHNhbXBsZWRRdWF0ZXJuaW9uQXhpcwogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IGFuZ2xlID0gUXVhdGVybmlvbi5jb21wdXRlQW5nbGUoc2FtcGxlZFF1YXRlcm5pb25UZW1wUXVhdGVybmlvbik7CiAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICAgIHJlc3VsdCA9IFtdOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0W29mZnNldF0gPSBzYW1wbGVkUXVhdGVybmlvbkF4aXMueCAqIGFuZ2xlOwogICAgICAgICAgcmVzdWx0W29mZnNldCArIDFdID0gc2FtcGxlZFF1YXRlcm5pb25BeGlzLnkgKiBhbmdsZTsKICAgICAgICAgIHJlc3VsdFtvZmZzZXQgKyAyXSA9IHNhbXBsZWRRdWF0ZXJuaW9uQXhpcy56ICogYW5nbGU7CiAgICAgICAgfQogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLnVucGFja0ludGVycG9sYXRpb25SZXN1bHQgPSBmdW5jdGlvbihhcnJheSwgc291cmNlQXJyYXksIGZpcnN0SW5kZXgsIGxhc3RJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IFF1YXRlcm5pb24oKTsKICAgICAgICB9CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShhcnJheSwgMCwgc2FtcGxlZFF1YXRlcm5pb25Sb3RhdGlvbik7CiAgICAgICAgY29uc3QgbWFnbml0dWRlID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZShzYW1wbGVkUXVhdGVybmlvblJvdGF0aW9uKTsKICAgICAgICBRdWF0ZXJuaW9uLnVucGFjayhzb3VyY2VBcnJheSwgbGFzdEluZGV4ICogNCwgc2FtcGxlZFF1YXRlcm5pb25RdWF0ZXJuaW9uMCk7CiAgICAgICAgaWYgKG1hZ25pdHVkZSA9PT0gMCkgewogICAgICAgICAgUXVhdGVybmlvbi5jbG9uZShRdWF0ZXJuaW9uLklERU5USVRZLCBzYW1wbGVkUXVhdGVybmlvblRlbXBRdWF0ZXJuaW9uKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgUXVhdGVybmlvbi5mcm9tQXhpc0FuZ2xlKAogICAgICAgICAgICBzYW1wbGVkUXVhdGVybmlvblJvdGF0aW9uLAogICAgICAgICAgICBtYWduaXR1ZGUsCiAgICAgICAgICAgIHNhbXBsZWRRdWF0ZXJuaW9uVGVtcFF1YXRlcm5pb24KICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBRdWF0ZXJuaW9uLm11bHRpcGx5KAogICAgICAgICAgc2FtcGxlZFF1YXRlcm5pb25UZW1wUXVhdGVybmlvbiwKICAgICAgICAgIHNhbXBsZWRRdWF0ZXJuaW9uUXVhdGVybmlvbjAsCiAgICAgICAgICByZXN1bHQKICAgICAgICApOwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLmNsb25lID0gZnVuY3Rpb24ocXVhdGVybmlvbiwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocXVhdGVybmlvbikpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgUXVhdGVybmlvbigKICAgICAgICAgICAgcXVhdGVybmlvbi54LAogICAgICAgICAgICBxdWF0ZXJuaW9uLnksCiAgICAgICAgICAgIHF1YXRlcm5pb24ueiwKICAgICAgICAgICAgcXVhdGVybmlvbi53CiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IHF1YXRlcm5pb24ueDsKICAgICAgICByZXN1bHQueSA9IHF1YXRlcm5pb24ueTsKICAgICAgICByZXN1bHQueiA9IHF1YXRlcm5pb24uejsKICAgICAgICByZXN1bHQudyA9IHF1YXRlcm5pb24udzsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLmNvbmp1Z2F0ZSA9IGZ1bmN0aW9uKHF1YXRlcm5pb24sIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicXVhdGVybmlvbiIsIHF1YXRlcm5pb24pOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQueCA9IC1xdWF0ZXJuaW9uLng7CiAgICAgICAgcmVzdWx0LnkgPSAtcXVhdGVybmlvbi55OwogICAgICAgIHJlc3VsdC56ID0gLXF1YXRlcm5pb24uejsKICAgICAgICByZXN1bHQudyA9IHF1YXRlcm5pb24udzsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLm1hZ25pdHVkZVNxdWFyZWQgPSBmdW5jdGlvbihxdWF0ZXJuaW9uKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJxdWF0ZXJuaW9uIiwgcXVhdGVybmlvbik7CiAgICAgICAgcmV0dXJuIHF1YXRlcm5pb24ueCAqIHF1YXRlcm5pb24ueCArIHF1YXRlcm5pb24ueSAqIHF1YXRlcm5pb24ueSArIHF1YXRlcm5pb24ueiAqIHF1YXRlcm5pb24ueiArIHF1YXRlcm5pb24udyAqIHF1YXRlcm5pb24udzsKICAgICAgfTsKICAgICAgUXVhdGVybmlvbi5tYWduaXR1ZGUgPSBmdW5jdGlvbihxdWF0ZXJuaW9uKSB7CiAgICAgICAgcmV0dXJuIE1hdGguc3FydChRdWF0ZXJuaW9uLm1hZ25pdHVkZVNxdWFyZWQocXVhdGVybmlvbikpOwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLm5vcm1hbGl6ZSA9IGZ1bmN0aW9uKHF1YXRlcm5pb24sIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBpbnZlcnNlTWFnbml0dWRlID0gMSAvIFF1YXRlcm5pb24ubWFnbml0dWRlKHF1YXRlcm5pb24pOwogICAgICAgIGNvbnN0IHggPSBxdWF0ZXJuaW9uLnggKiBpbnZlcnNlTWFnbml0dWRlOwogICAgICAgIGNvbnN0IHkgPSBxdWF0ZXJuaW9uLnkgKiBpbnZlcnNlTWFnbml0dWRlOwogICAgICAgIGNvbnN0IHogPSBxdWF0ZXJuaW9uLnogKiBpbnZlcnNlTWFnbml0dWRlOwogICAgICAgIGNvbnN0IHcgPSBxdWF0ZXJuaW9uLncgKiBpbnZlcnNlTWFnbml0dWRlOwogICAgICAgIHJlc3VsdC54ID0geDsKICAgICAgICByZXN1bHQueSA9IHk7CiAgICAgICAgcmVzdWx0LnogPSB6OwogICAgICAgIHJlc3VsdC53ID0gdzsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLmludmVyc2UgPSBmdW5jdGlvbihxdWF0ZXJuaW9uLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgbWFnbml0dWRlU3F1YXJlZCA9IFF1YXRlcm5pb24ubWFnbml0dWRlU3F1YXJlZChxdWF0ZXJuaW9uKTsKICAgICAgICByZXN1bHQgPSBRdWF0ZXJuaW9uLmNvbmp1Z2F0ZShxdWF0ZXJuaW9uLCByZXN1bHQpOwogICAgICAgIHJldHVybiBRdWF0ZXJuaW9uLm11bHRpcGx5QnlTY2FsYXIocmVzdWx0LCAxIC8gbWFnbml0dWRlU3F1YXJlZCwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgUXVhdGVybmlvbi5hZGQgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBsZWZ0LnggKyByaWdodC54OwogICAgICAgIHJlc3VsdC55ID0gbGVmdC55ICsgcmlnaHQueTsKICAgICAgICByZXN1bHQueiA9IGxlZnQueiArIHJpZ2h0Lno7CiAgICAgICAgcmVzdWx0LncgPSBsZWZ0LncgKyByaWdodC53OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFF1YXRlcm5pb24uc3VidHJhY3QgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBsZWZ0LnggLSByaWdodC54OwogICAgICAgIHJlc3VsdC55ID0gbGVmdC55IC0gcmlnaHQueTsKICAgICAgICByZXN1bHQueiA9IGxlZnQueiAtIHJpZ2h0Lno7CiAgICAgICAgcmVzdWx0LncgPSBsZWZ0LncgLSByaWdodC53OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFF1YXRlcm5pb24ubmVnYXRlID0gZnVuY3Rpb24ocXVhdGVybmlvbiwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJxdWF0ZXJuaW9uIiwgcXVhdGVybmlvbik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gLXF1YXRlcm5pb24ueDsKICAgICAgICByZXN1bHQueSA9IC1xdWF0ZXJuaW9uLnk7CiAgICAgICAgcmVzdWx0LnogPSAtcXVhdGVybmlvbi56OwogICAgICAgIHJlc3VsdC53ID0gLXF1YXRlcm5pb24udzsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLmRvdCA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICByZXR1cm4gbGVmdC54ICogcmlnaHQueCArIGxlZnQueSAqIHJpZ2h0LnkgKyBsZWZ0LnogKiByaWdodC56ICsgbGVmdC53ICogcmlnaHQudzsKICAgICAgfTsKICAgICAgUXVhdGVybmlvbi5tdWx0aXBseSA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImxlZnQiLCBsZWZ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJpZ2h0IiwgcmlnaHQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBsZWZ0WCA9IGxlZnQueDsKICAgICAgICBjb25zdCBsZWZ0WSA9IGxlZnQueTsKICAgICAgICBjb25zdCBsZWZ0WiA9IGxlZnQuejsKICAgICAgICBjb25zdCBsZWZ0VyA9IGxlZnQudzsKICAgICAgICBjb25zdCByaWdodFggPSByaWdodC54OwogICAgICAgIGNvbnN0IHJpZ2h0WSA9IHJpZ2h0Lnk7CiAgICAgICAgY29uc3QgcmlnaHRaID0gcmlnaHQuejsKICAgICAgICBjb25zdCByaWdodFcgPSByaWdodC53OwogICAgICAgIGNvbnN0IHggPSBsZWZ0VyAqIHJpZ2h0WCArIGxlZnRYICogcmlnaHRXICsgbGVmdFkgKiByaWdodFogLSBsZWZ0WiAqIHJpZ2h0WTsKICAgICAgICBjb25zdCB5ID0gbGVmdFcgKiByaWdodFkgLSBsZWZ0WCAqIHJpZ2h0WiArIGxlZnRZICogcmlnaHRXICsgbGVmdFogKiByaWdodFg7CiAgICAgICAgY29uc3QgeiA9IGxlZnRXICogcmlnaHRaICsgbGVmdFggKiByaWdodFkgLSBsZWZ0WSAqIHJpZ2h0WCArIGxlZnRaICogcmlnaHRXOwogICAgICAgIGNvbnN0IHcgPSBsZWZ0VyAqIHJpZ2h0VyAtIGxlZnRYICogcmlnaHRYIC0gbGVmdFkgKiByaWdodFkgLSBsZWZ0WiAqIHJpZ2h0WjsKICAgICAgICByZXN1bHQueCA9IHg7CiAgICAgICAgcmVzdWx0LnkgPSB5OwogICAgICAgIHJlc3VsdC56ID0gejsKICAgICAgICByZXN1bHQudyA9IHc7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUXVhdGVybmlvbi5tdWx0aXBseUJ5U2NhbGFyID0gZnVuY3Rpb24ocXVhdGVybmlvbiwgc2NhbGFyLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInF1YXRlcm5pb24iLCBxdWF0ZXJuaW9uKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInNjYWxhciIsIHNjYWxhcik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gcXVhdGVybmlvbi54ICogc2NhbGFyOwogICAgICAgIHJlc3VsdC55ID0gcXVhdGVybmlvbi55ICogc2NhbGFyOwogICAgICAgIHJlc3VsdC56ID0gcXVhdGVybmlvbi56ICogc2NhbGFyOwogICAgICAgIHJlc3VsdC53ID0gcXVhdGVybmlvbi53ICogc2NhbGFyOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFF1YXRlcm5pb24uZGl2aWRlQnlTY2FsYXIgPSBmdW5jdGlvbihxdWF0ZXJuaW9uLCBzY2FsYXIsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicXVhdGVybmlvbiIsIHF1YXRlcm5pb24pOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigic2NhbGFyIiwgc2NhbGFyKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnggPSBxdWF0ZXJuaW9uLnggLyBzY2FsYXI7CiAgICAgICAgcmVzdWx0LnkgPSBxdWF0ZXJuaW9uLnkgLyBzY2FsYXI7CiAgICAgICAgcmVzdWx0LnogPSBxdWF0ZXJuaW9uLnogLyBzY2FsYXI7CiAgICAgICAgcmVzdWx0LncgPSBxdWF0ZXJuaW9uLncgLyBzY2FsYXI7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUXVhdGVybmlvbi5jb21wdXRlQXhpcyA9IGZ1bmN0aW9uKHF1YXRlcm5pb24sIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicXVhdGVybmlvbiIsIHF1YXRlcm5pb24pOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCB3ID0gcXVhdGVybmlvbi53OwogICAgICAgIGlmIChNYXRoLmFicyh3IC0gMSkgPCBNYXRoX2RlZmF1bHQuRVBTSUxPTjYgfHwgTWF0aC5hYnModyArIDEpIDwgTWF0aF9kZWZhdWx0LkVQU0lMT042KSB7CiAgICAgICAgICByZXN1bHQueCA9IDE7CiAgICAgICAgICByZXN1bHQueSA9IHJlc3VsdC56ID0gMDsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHNjYWxhciA9IDEgLyBNYXRoLnNxcnQoMSAtIHcgKiB3KTsKICAgICAgICByZXN1bHQueCA9IHF1YXRlcm5pb24ueCAqIHNjYWxhcjsKICAgICAgICByZXN1bHQueSA9IHF1YXRlcm5pb24ueSAqIHNjYWxhcjsKICAgICAgICByZXN1bHQueiA9IHF1YXRlcm5pb24ueiAqIHNjYWxhcjsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLmNvbXB1dGVBbmdsZSA9IGZ1bmN0aW9uKHF1YXRlcm5pb24pIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInF1YXRlcm5pb24iLCBxdWF0ZXJuaW9uKTsKICAgICAgICBpZiAoTWF0aC5hYnMocXVhdGVybmlvbi53IC0gMSkgPCBNYXRoX2RlZmF1bHQuRVBTSUxPTjYpIHsKICAgICAgICAgIHJldHVybiAwOwogICAgICAgIH0KICAgICAgICByZXR1cm4gMiAqIE1hdGguYWNvcyhxdWF0ZXJuaW9uLncpOwogICAgICB9OwogICAgICBsZXJwU2NyYXRjaDQgPSBuZXcgUXVhdGVybmlvbigpOwogICAgICBRdWF0ZXJuaW9uLmxlcnAgPSBmdW5jdGlvbihzdGFydCwgZW5kLCB0LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInN0YXJ0Iiwgc3RhcnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiZW5kIiwgZW5kKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInQiLCB0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgbGVycFNjcmF0Y2g0ID0gUXVhdGVybmlvbi5tdWx0aXBseUJ5U2NhbGFyKGVuZCwgdCwgbGVycFNjcmF0Y2g0KTsKICAgICAgICByZXN1bHQgPSBRdWF0ZXJuaW9uLm11bHRpcGx5QnlTY2FsYXIoc3RhcnQsIDEgLSB0LCByZXN1bHQpOwogICAgICAgIHJldHVybiBRdWF0ZXJuaW9uLmFkZChsZXJwU2NyYXRjaDQsIHJlc3VsdCwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgc2xlcnBFbmROZWdhdGVkID0gbmV3IFF1YXRlcm5pb24oKTsKICAgICAgc2xlcnBTY2FsZWRQID0gbmV3IFF1YXRlcm5pb24oKTsKICAgICAgc2xlcnBTY2FsZWRSID0gbmV3IFF1YXRlcm5pb24oKTsKICAgICAgUXVhdGVybmlvbi5zbGVycCA9IGZ1bmN0aW9uKHN0YXJ0LCBlbmQsIHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic3RhcnQiLCBzdGFydCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJlbmQiLCBlbmQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigidCIsIHQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBsZXQgZG90ID0gUXVhdGVybmlvbi5kb3Qoc3RhcnQsIGVuZCk7CiAgICAgICAgbGV0IHIgPSBlbmQ7CiAgICAgICAgaWYgKGRvdCA8IDApIHsKICAgICAgICAgIGRvdCA9IC1kb3Q7CiAgICAgICAgICByID0gc2xlcnBFbmROZWdhdGVkID0gUXVhdGVybmlvbi5uZWdhdGUoZW5kLCBzbGVycEVuZE5lZ2F0ZWQpOwogICAgICAgIH0KICAgICAgICBpZiAoMSAtIGRvdCA8IE1hdGhfZGVmYXVsdC5FUFNJTE9ONikgewogICAgICAgICAgcmV0dXJuIFF1YXRlcm5pb24ubGVycChzdGFydCwgciwgdCwgcmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgdGhldGEgPSBNYXRoLmFjb3MoZG90KTsKICAgICAgICBzbGVycFNjYWxlZFAgPSBRdWF0ZXJuaW9uLm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgICBzdGFydCwKICAgICAgICAgIE1hdGguc2luKCgxIC0gdCkgKiB0aGV0YSksCiAgICAgICAgICBzbGVycFNjYWxlZFAKICAgICAgICApOwogICAgICAgIHNsZXJwU2NhbGVkUiA9IFF1YXRlcm5pb24ubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICAgIHIsCiAgICAgICAgICBNYXRoLnNpbih0ICogdGhldGEpLAogICAgICAgICAgc2xlcnBTY2FsZWRSCiAgICAgICAgKTsKICAgICAgICByZXN1bHQgPSBRdWF0ZXJuaW9uLmFkZChzbGVycFNjYWxlZFAsIHNsZXJwU2NhbGVkUiwgcmVzdWx0KTsKICAgICAgICByZXR1cm4gUXVhdGVybmlvbi5tdWx0aXBseUJ5U2NhbGFyKHJlc3VsdCwgMSAvIE1hdGguc2luKHRoZXRhKSwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgUXVhdGVybmlvbi5sb2cgPSBmdW5jdGlvbihxdWF0ZXJuaW9uLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInF1YXRlcm5pb24iLCBxdWF0ZXJuaW9uKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgdGhldGEgPSBNYXRoX2RlZmF1bHQuYWNvc0NsYW1wZWQocXVhdGVybmlvbi53KTsKICAgICAgICBsZXQgdGhldGFPdmVyU2luVGhldGEgPSAwOwogICAgICAgIGlmICh0aGV0YSAhPT0gMCkgewogICAgICAgICAgdGhldGFPdmVyU2luVGhldGEgPSB0aGV0YSAvIE1hdGguc2luKHRoZXRhKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKHF1YXRlcm5pb24sIHRoZXRhT3ZlclNpblRoZXRhLCByZXN1bHQpOwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLmV4cCA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgdGhldGEgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKGNhcnRlc2lhbjExKTsKICAgICAgICBsZXQgc2luVGhldGFPdmVyVGhldGEgPSAwOwogICAgICAgIGlmICh0aGV0YSAhPT0gMCkgewogICAgICAgICAgc2luVGhldGFPdmVyVGhldGEgPSBNYXRoLnNpbih0aGV0YSkgLyB0aGV0YTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnggPSBjYXJ0ZXNpYW4xMS54ICogc2luVGhldGFPdmVyVGhldGE7CiAgICAgICAgcmVzdWx0LnkgPSBjYXJ0ZXNpYW4xMS55ICogc2luVGhldGFPdmVyVGhldGE7CiAgICAgICAgcmVzdWx0LnogPSBjYXJ0ZXNpYW4xMS56ICogc2luVGhldGFPdmVyVGhldGE7CiAgICAgICAgcmVzdWx0LncgPSBNYXRoLmNvcyh0aGV0YSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc3F1YWRTY3JhdGNoQ2FydGVzaWFuMCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc3F1YWRTY3JhdGNoQ2FydGVzaWFuMSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc3F1YWRTY3JhdGNoUXVhdGVybmlvbjAgPSBuZXcgUXVhdGVybmlvbigpOwogICAgICBzcXVhZFNjcmF0Y2hRdWF0ZXJuaW9uMSA9IG5ldyBRdWF0ZXJuaW9uKCk7CiAgICAgIFF1YXRlcm5pb24uY29tcHV0ZUlubmVyUXVhZHJhbmdsZSA9IGZ1bmN0aW9uKHEwLCBxMTIsIHEyMiwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJxMCIsIHEwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInExIiwgcTEyKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInEyIiwgcTIyKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgcUludiA9IFF1YXRlcm5pb24uY29uanVnYXRlKHExMiwgc3F1YWRTY3JhdGNoUXVhdGVybmlvbjApOwogICAgICAgIFF1YXRlcm5pb24ubXVsdGlwbHkocUludiwgcTIyLCBzcXVhZFNjcmF0Y2hRdWF0ZXJuaW9uMSk7CiAgICAgICAgY29uc3QgY2FydDAgPSBRdWF0ZXJuaW9uLmxvZyhzcXVhZFNjcmF0Y2hRdWF0ZXJuaW9uMSwgc3F1YWRTY3JhdGNoQ2FydGVzaWFuMCk7CiAgICAgICAgUXVhdGVybmlvbi5tdWx0aXBseShxSW52LCBxMCwgc3F1YWRTY3JhdGNoUXVhdGVybmlvbjEpOwogICAgICAgIGNvbnN0IGNhcnQxID0gUXVhdGVybmlvbi5sb2coc3F1YWRTY3JhdGNoUXVhdGVybmlvbjEsIHNxdWFkU2NyYXRjaENhcnRlc2lhbjEpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoY2FydDAsIGNhcnQxLCBjYXJ0MCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoY2FydDAsIDAuMjUsIGNhcnQwKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKGNhcnQwLCBjYXJ0MCk7CiAgICAgICAgUXVhdGVybmlvbi5leHAoY2FydDAsIHNxdWFkU2NyYXRjaFF1YXRlcm5pb24wKTsKICAgICAgICByZXR1cm4gUXVhdGVybmlvbi5tdWx0aXBseShxMTIsIHNxdWFkU2NyYXRjaFF1YXRlcm5pb24wLCByZXN1bHQpOwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLnNxdWFkID0gZnVuY3Rpb24ocTAsIHExMiwgczAsIHMxLCB0LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInEwIiwgcTApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicTEiLCBxMTIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiczAiLCBzMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzMSIsIHMxKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInQiLCB0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3Qgc2xlcnAwID0gUXVhdGVybmlvbi5zbGVycChxMCwgcTEyLCB0LCBzcXVhZFNjcmF0Y2hRdWF0ZXJuaW9uMCk7CiAgICAgICAgY29uc3Qgc2xlcnAxID0gUXVhdGVybmlvbi5zbGVycChzMCwgczEsIHQsIHNxdWFkU2NyYXRjaFF1YXRlcm5pb24xKTsKICAgICAgICByZXR1cm4gUXVhdGVybmlvbi5zbGVycChzbGVycDAsIHNsZXJwMSwgMiAqIHQgKiAoMSAtIHQpLCByZXN1bHQpOwogICAgICB9OwogICAgICBmYXN0U2xlcnBTY3JhdGNoUXVhdGVybmlvbiA9IG5ldyBRdWF0ZXJuaW9uKCk7CiAgICAgIG9wbXUgPSAxLjkwMTEwNzQ1MzUxNzMwMDM7CiAgICAgIHUgPSBGZWF0dXJlRGV0ZWN0aW9uX2RlZmF1bHQuc3VwcG9ydHNUeXBlZEFycmF5cygpID8gbmV3IEZsb2F0MzJBcnJheSg4KSA6IFtdOwogICAgICB2ID0gRmVhdHVyZURldGVjdGlvbl9kZWZhdWx0LnN1cHBvcnRzVHlwZWRBcnJheXMoKSA/IG5ldyBGbG9hdDMyQXJyYXkoOCkgOiBbXTsKICAgICAgYlQgPSBGZWF0dXJlRGV0ZWN0aW9uX2RlZmF1bHQuc3VwcG9ydHNUeXBlZEFycmF5cygpID8gbmV3IEZsb2F0MzJBcnJheSg4KSA6IFtdOwogICAgICBiRCA9IEZlYXR1cmVEZXRlY3Rpb25fZGVmYXVsdC5zdXBwb3J0c1R5cGVkQXJyYXlzKCkgPyBuZXcgRmxvYXQzMkFycmF5KDgpIDogW107CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNzsgKytpKSB7CiAgICAgICAgY29uc3QgcyA9IGkgKyAxOwogICAgICAgIGNvbnN0IHQgPSAyICogcyArIDE7CiAgICAgICAgdVtpXSA9IDEgLyAocyAqIHQpOwogICAgICAgIHZbaV0gPSBzIC8gdDsKICAgICAgfQogICAgICB1WzddID0gb3BtdSAvICg4ICogMTcpOwogICAgICB2WzddID0gb3BtdSAqIDggLyAxNzsKICAgICAgUXVhdGVybmlvbi5mYXN0U2xlcnAgPSBmdW5jdGlvbihzdGFydCwgZW5kLCB0LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInN0YXJ0Iiwgc3RhcnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiZW5kIiwgZW5kKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInQiLCB0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgbGV0IHggPSBRdWF0ZXJuaW9uLmRvdChzdGFydCwgZW5kKTsKICAgICAgICBsZXQgc2lnbjM7CiAgICAgICAgaWYgKHggPj0gMCkgewogICAgICAgICAgc2lnbjMgPSAxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzaWduMyA9IC0xOwogICAgICAgICAgeCA9IC14OwogICAgICAgIH0KICAgICAgICBjb25zdCB4bTEgPSB4IC0gMTsKICAgICAgICBjb25zdCBkID0gMSAtIHQ7CiAgICAgICAgY29uc3Qgc3FyVCA9IHQgKiB0OwogICAgICAgIGNvbnN0IHNxckQgPSBkICogZDsKICAgICAgICBmb3IgKGxldCBpID0gNzsgaSA+PSAwOyAtLWkpIHsKICAgICAgICAgIGJUW2ldID0gKHVbaV0gKiBzcXJUIC0gdltpXSkgKiB4bTE7CiAgICAgICAgICBiRFtpXSA9ICh1W2ldICogc3FyRCAtIHZbaV0pICogeG0xOwogICAgICAgIH0KICAgICAgICBjb25zdCBjVCA9IHNpZ24zICogdCAqICgxICsgYlRbMF0gKiAoMSArIGJUWzFdICogKDEgKyBiVFsyXSAqICgxICsgYlRbM10gKiAoMSArIGJUWzRdICogKDEgKyBiVFs1XSAqICgxICsgYlRbNl0gKiAoMSArIGJUWzddKSkpKSkpKSk7CiAgICAgICAgY29uc3QgY0QgPSBkICogKDEgKyBiRFswXSAqICgxICsgYkRbMV0gKiAoMSArIGJEWzJdICogKDEgKyBiRFszXSAqICgxICsgYkRbNF0gKiAoMSArIGJEWzVdICogKDEgKyBiRFs2XSAqICgxICsgYkRbN10pKSkpKSkpKTsKICAgICAgICBjb25zdCB0ZW1wID0gUXVhdGVybmlvbi5tdWx0aXBseUJ5U2NhbGFyKAogICAgICAgICAgc3RhcnQsCiAgICAgICAgICBjRCwKICAgICAgICAgIGZhc3RTbGVycFNjcmF0Y2hRdWF0ZXJuaW9uCiAgICAgICAgKTsKICAgICAgICBRdWF0ZXJuaW9uLm11bHRpcGx5QnlTY2FsYXIoZW5kLCBjVCwgcmVzdWx0KTsKICAgICAgICByZXR1cm4gUXVhdGVybmlvbi5hZGQodGVtcCwgcmVzdWx0LCByZXN1bHQpOwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLmZhc3RTcXVhZCA9IGZ1bmN0aW9uKHEwLCBxMTIsIHMwLCBzMSwgdCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJxMCIsIHEwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInExIiwgcTEyKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInMwIiwgczApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiczEiLCBzMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJ0IiwgdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHNsZXJwMCA9IFF1YXRlcm5pb24uZmFzdFNsZXJwKHEwLCBxMTIsIHQsIHNxdWFkU2NyYXRjaFF1YXRlcm5pb24wKTsKICAgICAgICBjb25zdCBzbGVycDEgPSBRdWF0ZXJuaW9uLmZhc3RTbGVycChzMCwgczEsIHQsIHNxdWFkU2NyYXRjaFF1YXRlcm5pb24xKTsKICAgICAgICByZXR1cm4gUXVhdGVybmlvbi5mYXN0U2xlcnAoc2xlcnAwLCBzbGVycDEsIDIgKiB0ICogKDEgLSB0KSwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgUXVhdGVybmlvbi5lcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiBsZWZ0LnggPT09IHJpZ2h0LnggJiYgbGVmdC55ID09PSByaWdodC55ICYmIGxlZnQueiA9PT0gcmlnaHQueiAmJiBsZWZ0LncgPT09IHJpZ2h0Lnc7CiAgICAgIH07CiAgICAgIFF1YXRlcm5pb24uZXF1YWxzRXBzaWxvbiA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCBlcHNpbG9uKSB7CiAgICAgICAgZXBzaWxvbiA9IGVwc2lsb24gPz8gMDsKICAgICAgICByZXR1cm4gbGVmdCA9PT0gcmlnaHQgfHwgZGVmaW5lZF9kZWZhdWx0KGxlZnQpICYmIGRlZmluZWRfZGVmYXVsdChyaWdodCkgJiYgTWF0aC5hYnMobGVmdC54IC0gcmlnaHQueCkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0LnkgLSByaWdodC55KSA8PSBlcHNpbG9uICYmIE1hdGguYWJzKGxlZnQueiAtIHJpZ2h0LnopIDw9IGVwc2lsb24gJiYgTWF0aC5hYnMobGVmdC53IC0gcmlnaHQudykgPD0gZXBzaWxvbjsKICAgICAgfTsKICAgICAgUXVhdGVybmlvbi5aRVJPID0gT2JqZWN0LmZyZWV6ZShuZXcgUXVhdGVybmlvbigwLCAwLCAwLCAwKSk7CiAgICAgIFF1YXRlcm5pb24uSURFTlRJVFkgPSBPYmplY3QuZnJlZXplKG5ldyBRdWF0ZXJuaW9uKDAsIDAsIDAsIDEpKTsKICAgICAgUXVhdGVybmlvbi5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICByZXR1cm4gUXVhdGVybmlvbi5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbihyaWdodCkgewogICAgICAgIHJldHVybiBRdWF0ZXJuaW9uLmVxdWFscyh0aGlzLCByaWdodCk7CiAgICAgIH07CiAgICAgIFF1YXRlcm5pb24ucHJvdG90eXBlLmVxdWFsc0Vwc2lsb24gPSBmdW5jdGlvbihyaWdodCwgZXBzaWxvbikgewogICAgICAgIHJldHVybiBRdWF0ZXJuaW9uLmVxdWFsc0Vwc2lsb24odGhpcywgcmlnaHQsIGVwc2lsb24pOwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBgKCR7dGhpcy54fSwgJHt0aGlzLnl9LCAke3RoaXMuen0sICR7dGhpcy53fSlgOwogICAgICB9OwogICAgICBRdWF0ZXJuaW9uX2RlZmF1bHQgPSBRdWF0ZXJuaW9uOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvVHJhbnNmb3Jtcy5qcwogIHZhciBUcmFuc2Zvcm1zLCB2ZWN0b3JQcm9kdWN0TG9jYWxGcmFtZSwgZGVnZW5lcmF0ZVBvc2l0aW9uTG9jYWxGcmFtZSwgbG9jYWxGcmFtZVRvRml4ZWRGcmFtZUNhY2hlLCBzY3JhdGNoQ2FsY3VsYXRlQ2FydGVzaWFuLCBzY3JhdGNoRmlyc3RDYXJ0ZXNpYW4sIHNjcmF0Y2hTZWNvbmRDYXJ0ZXNpYW4sIHNjcmF0Y2hUaGlyZENhcnRlc2lhbiwgc2NyYXRjaEhQUlF1YXRlcm5pb24yLCBzY3JhdGNoU2NhbGUsIHNjcmF0Y2hIUFJNYXRyaXg0LCBzY3JhdGNoRU5VTWF0cml4NCwgc2NyYXRjaEhQUk1hdHJpeDMsIG5vU2NhbGUsIGhwckNlbnRlclNjcmF0Y2gsIGZmU2NyYXRjaCwgaHByVHJhbnNmb3JtU2NyYXRjaCwgaHByUm90YXRpb25TY3JhdGNoLCBocHJRdWF0ZXJuaW9uU2NyYXRjaCwgZ21zdENvbnN0YW50MCwgZ21zdENvbnN0YW50MSwgZ21zdENvbnN0YW50MiwgZ21zdENvbnN0YW50MywgcmF0ZUNvZWYsIHdnczg0V1JQcmVjZXNzaW5nLCB0d29QaU92ZXJTZWNvbmRzSW5EYXksIGRhdGVJblV0YywgdHRNaW51c1RhaSwgajIwMDB0dERheXMsIFRkdE1pbnVzVGFpLCBKMjAwMGQsIHNjcmF0Y2hIcHIsIHNjcmF0Y2hSb3RhdGlvbk1hdHJpeCwgZGF0ZVNjcmF0Y2gsIHh5c1NjcmF0Y2gsIGVvcFNjcmF0Y2gsIHJvdGF0aW9uMVNjcmF0Y2gsIHJvdGF0aW9uMlNjcmF0Y2gsIHBvaW50VG9XaW5kb3dDb29yZGluYXRlc1RlbXAsIG5vcm1hbFNjcmF0Y2gsIHJpZ2h0U2NyYXRjaCwgdXBTY3JhdGNoLCBzd2l6emxlTWF0cml4LCBzY3JhdGNoQ2FydG9ncmFwaGljLCBzY3JhdGNoQ2FydGVzaWFuM1Byb2plY3Rpb24sIHNjcmF0Y2hDZW50ZXIsIHNjcmF0Y2hSb3RhdGlvbiwgc2NyYXRjaEZyb21FTlUsIHNjcmF0Y2hUb0VOVSwgVHJhbnNmb3Jtc19kZWZhdWx0OwogIHZhciBpbml0X1RyYW5zZm9ybXMgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1RyYW5zZm9ybXMuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuNCgpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfRWFydGhPcmllbnRhdGlvblBhcmFtZXRlcnMoKTsKICAgICAgaW5pdF9FYXJ0aE9yaWVudGF0aW9uUGFyYW1ldGVyc1NhbXBsZSgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0hlYWRpbmdQaXRjaFJvbGwoKTsKICAgICAgaW5pdF9JYXUyMDA2WHlzRGF0YSgpOwogICAgICBpbml0X0lhdTIwMDZYeXNTYW1wbGUoKTsKICAgICAgaW5pdF9KdWxpYW5EYXRlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X01hdHJpeDMoKTsKICAgICAgaW5pdF9NYXRyaXg0KCk7CiAgICAgIGluaXRfUXVhdGVybmlvbigpOwogICAgICBpbml0X1RpbWVDb25zdGFudHMoKTsKICAgICAgVHJhbnNmb3JtcyA9IHt9OwogICAgICB2ZWN0b3JQcm9kdWN0TG9jYWxGcmFtZSA9IHsKICAgICAgICB1cDogewogICAgICAgICAgc291dGg6ICJlYXN0IiwKICAgICAgICAgIG5vcnRoOiAid2VzdCIsCiAgICAgICAgICB3ZXN0OiAic291dGgiLAogICAgICAgICAgZWFzdDogIm5vcnRoIgogICAgICAgIH0sCiAgICAgICAgZG93bjogewogICAgICAgICAgc291dGg6ICJ3ZXN0IiwKICAgICAgICAgIG5vcnRoOiAiZWFzdCIsCiAgICAgICAgICB3ZXN0OiAibm9ydGgiLAogICAgICAgICAgZWFzdDogInNvdXRoIgogICAgICAgIH0sCiAgICAgICAgc291dGg6IHsKICAgICAgICAgIHVwOiAid2VzdCIsCiAgICAgICAgICBkb3duOiAiZWFzdCIsCiAgICAgICAgICB3ZXN0OiAiZG93biIsCiAgICAgICAgICBlYXN0OiAidXAiCiAgICAgICAgfSwKICAgICAgICBub3J0aDogewogICAgICAgICAgdXA6ICJlYXN0IiwKICAgICAgICAgIGRvd246ICJ3ZXN0IiwKICAgICAgICAgIHdlc3Q6ICJ1cCIsCiAgICAgICAgICBlYXN0OiAiZG93biIKICAgICAgICB9LAogICAgICAgIHdlc3Q6IHsKICAgICAgICAgIHVwOiAibm9ydGgiLAogICAgICAgICAgZG93bjogInNvdXRoIiwKICAgICAgICAgIG5vcnRoOiAiZG93biIsCiAgICAgICAgICBzb3V0aDogInVwIgogICAgICAgIH0sCiAgICAgICAgZWFzdDogewogICAgICAgICAgdXA6ICJzb3V0aCIsCiAgICAgICAgICBkb3duOiAibm9ydGgiLAogICAgICAgICAgbm9ydGg6ICJ1cCIsCiAgICAgICAgICBzb3V0aDogImRvd24iCiAgICAgICAgfQogICAgICB9OwogICAgICBkZWdlbmVyYXRlUG9zaXRpb25Mb2NhbEZyYW1lID0gewogICAgICAgIG5vcnRoOiBbLTEsIDAsIDBdLAogICAgICAgIGVhc3Q6IFswLCAxLCAwXSwKICAgICAgICB1cDogWzAsIDAsIDFdLAogICAgICAgIHNvdXRoOiBbMSwgMCwgMF0sCiAgICAgICAgd2VzdDogWzAsIC0xLCAwXSwKICAgICAgICBkb3duOiBbMCwgMCwgLTFdCiAgICAgIH07CiAgICAgIGxvY2FsRnJhbWVUb0ZpeGVkRnJhbWVDYWNoZSA9IHt9OwogICAgICBzY3JhdGNoQ2FsY3VsYXRlQ2FydGVzaWFuID0gewogICAgICAgIGVhc3Q6IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKSwKICAgICAgICBub3J0aDogbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpLAogICAgICAgIHVwOiBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCksCiAgICAgICAgd2VzdDogbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpLAogICAgICAgIHNvdXRoOiBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCksCiAgICAgICAgZG93bjogbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpCiAgICAgIH07CiAgICAgIHNjcmF0Y2hGaXJzdENhcnRlc2lhbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFNlY29uZENhcnRlc2lhbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFRoaXJkQ2FydGVzaWFuID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBUcmFuc2Zvcm1zLmxvY2FsRnJhbWVUb0ZpeGVkRnJhbWVHZW5lcmF0b3IgPSBmdW5jdGlvbihmaXJzdEF4aXMsIHNlY29uZEF4aXMpIHsKICAgICAgICBpZiAoIXZlY3RvclByb2R1Y3RMb2NhbEZyYW1lLmhhc093blByb3BlcnR5KGZpcnN0QXhpcykgfHwgIXZlY3RvclByb2R1Y3RMb2NhbEZyYW1lW2ZpcnN0QXhpc10uaGFzT3duUHJvcGVydHkoc2Vjb25kQXhpcykpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICAiZmlyc3RBeGlzIGFuZCBzZWNvbmRBeGlzIG11c3QgYmUgZWFzdCwgbm9ydGgsIHVwLCB3ZXN0LCBzb3V0aCBvciBkb3duLiIKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHRoaXJkQXhpcyA9IHZlY3RvclByb2R1Y3RMb2NhbEZyYW1lW2ZpcnN0QXhpc11bc2Vjb25kQXhpc107CiAgICAgICAgbGV0IHJlc3VsdGF0OwogICAgICAgIGNvbnN0IGhhc2hBeGlzID0gZmlyc3RBeGlzICsgc2Vjb25kQXhpczsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGxvY2FsRnJhbWVUb0ZpeGVkRnJhbWVDYWNoZVtoYXNoQXhpc10pKSB7CiAgICAgICAgICByZXN1bHRhdCA9IGxvY2FsRnJhbWVUb0ZpeGVkRnJhbWVDYWNoZVtoYXNoQXhpc107CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdGF0ID0gZnVuY3Rpb24ob3JpZ2luLCBlbGxpcHNvaWQsIHJlc3VsdCkgewogICAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChvcmlnaW4pKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9yaWdpbiBpcyByZXF1aXJlZC4iKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoaXNOYU4ob3JpZ2luLngpIHx8IGlzTmFOKG9yaWdpbi55KSB8fCBpc05hTihvcmlnaW4ueikpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgib3JpZ2luIGhhcyBhIE5hTiBjb21wb25lbnQiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICAgICAgcmVzdWx0ID0gbmV3IE1hdHJpeDRfZGVmYXVsdCgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihvcmlnaW4sIENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjE0KSkgewogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICAgICAgICBkZWdlbmVyYXRlUG9zaXRpb25Mb2NhbEZyYW1lW2ZpcnN0QXhpc10sCiAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgc2NyYXRjaEZpcnN0Q2FydGVzaWFuCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgICAgICAgZGVnZW5lcmF0ZVBvc2l0aW9uTG9jYWxGcmFtZVtzZWNvbmRBeGlzXSwKICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICBzY3JhdGNoU2Vjb25kQ2FydGVzaWFuCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgICAgICAgZGVnZW5lcmF0ZVBvc2l0aW9uTG9jYWxGcmFtZVt0aGlyZEF4aXNdLAogICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgIHNjcmF0Y2hUaGlyZENhcnRlc2lhbgogICAgICAgICAgICAgICk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24ob3JpZ2luLngsIDAsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTQpICYmIE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKG9yaWdpbi55LCAwLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjE0KSkgewogICAgICAgICAgICAgIGNvbnN0IHNpZ24zID0gTWF0aF9kZWZhdWx0LnNpZ24ob3JpZ2luLnopOwogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICAgICAgICBkZWdlbmVyYXRlUG9zaXRpb25Mb2NhbEZyYW1lW2ZpcnN0QXhpc10sCiAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgc2NyYXRjaEZpcnN0Q2FydGVzaWFuCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBpZiAoZmlyc3RBeGlzICE9PSAiZWFzdCIgJiYgZmlyc3RBeGlzICE9PSAid2VzdCIpIHsKICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICAgICAgICAgICAgICBzY3JhdGNoRmlyc3RDYXJ0ZXNpYW4sCiAgICAgICAgICAgICAgICAgIHNpZ24zLAogICAgICAgICAgICAgICAgICBzY3JhdGNoRmlyc3RDYXJ0ZXNpYW4KICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICAgICAgICBkZWdlbmVyYXRlUG9zaXRpb25Mb2NhbEZyYW1lW3NlY29uZEF4aXNdLAogICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgIHNjcmF0Y2hTZWNvbmRDYXJ0ZXNpYW4KICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIGlmIChzZWNvbmRBeGlzICE9PSAiZWFzdCIgJiYgc2Vjb25kQXhpcyAhPT0gIndlc3QiKSB7CiAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICAgICAgICAgICAgc2NyYXRjaFNlY29uZENhcnRlc2lhbiwKICAgICAgICAgICAgICAgICAgc2lnbjMsCiAgICAgICAgICAgICAgICAgIHNjcmF0Y2hTZWNvbmRDYXJ0ZXNpYW4KICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICAgICAgICBkZWdlbmVyYXRlUG9zaXRpb25Mb2NhbEZyYW1lW3RoaXJkQXhpc10sCiAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgc2NyYXRjaFRoaXJkQ2FydGVzaWFuCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBpZiAodGhpcmRBeGlzICE9PSAiZWFzdCIgJiYgdGhpcmRBeGlzICE9PSAid2VzdCIpIHsKICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICAgICAgICAgICAgICBzY3JhdGNoVGhpcmRDYXJ0ZXNpYW4sCiAgICAgICAgICAgICAgICAgIHNpZ24zLAogICAgICAgICAgICAgICAgICBzY3JhdGNoVGhpcmRDYXJ0ZXNpYW4KICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGVsbGlwc29pZCA9IGVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgICAgICAgICAgIGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwob3JpZ2luLCBzY3JhdGNoQ2FsY3VsYXRlQ2FydGVzaWFuLnVwKTsKICAgICAgICAgICAgICBjb25zdCB1cCA9IHNjcmF0Y2hDYWxjdWxhdGVDYXJ0ZXNpYW4udXA7CiAgICAgICAgICAgICAgY29uc3QgZWFzdCA9IHNjcmF0Y2hDYWxjdWxhdGVDYXJ0ZXNpYW4uZWFzdDsKICAgICAgICAgICAgICBlYXN0LnggPSAtb3JpZ2luLnk7CiAgICAgICAgICAgICAgZWFzdC55ID0gb3JpZ2luLng7CiAgICAgICAgICAgICAgZWFzdC56ID0gMDsKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGVhc3QsIHNjcmF0Y2hDYWxjdWxhdGVDYXJ0ZXNpYW4uZWFzdCk7CiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKHVwLCBlYXN0LCBzY3JhdGNoQ2FsY3VsYXRlQ2FydGVzaWFuLm5vcnRoKTsKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICAgICAgICAgIHNjcmF0Y2hDYWxjdWxhdGVDYXJ0ZXNpYW4udXAsCiAgICAgICAgICAgICAgICAtMSwKICAgICAgICAgICAgICAgIHNjcmF0Y2hDYWxjdWxhdGVDYXJ0ZXNpYW4uZG93bgogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgICAgICAgICBzY3JhdGNoQ2FsY3VsYXRlQ2FydGVzaWFuLmVhc3QsCiAgICAgICAgICAgICAgICAtMSwKICAgICAgICAgICAgICAgIHNjcmF0Y2hDYWxjdWxhdGVDYXJ0ZXNpYW4ud2VzdAogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgICAgICAgICBzY3JhdGNoQ2FsY3VsYXRlQ2FydGVzaWFuLm5vcnRoLAogICAgICAgICAgICAgICAgLTEsCiAgICAgICAgICAgICAgICBzY3JhdGNoQ2FsY3VsYXRlQ2FydGVzaWFuLnNvdXRoCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBzY3JhdGNoRmlyc3RDYXJ0ZXNpYW4gPSBzY3JhdGNoQ2FsY3VsYXRlQ2FydGVzaWFuW2ZpcnN0QXhpc107CiAgICAgICAgICAgICAgc2NyYXRjaFNlY29uZENhcnRlc2lhbiA9IHNjcmF0Y2hDYWxjdWxhdGVDYXJ0ZXNpYW5bc2Vjb25kQXhpc107CiAgICAgICAgICAgICAgc2NyYXRjaFRoaXJkQ2FydGVzaWFuID0gc2NyYXRjaENhbGN1bGF0ZUNhcnRlc2lhblt0aGlyZEF4aXNdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJlc3VsdFswXSA9IHNjcmF0Y2hGaXJzdENhcnRlc2lhbi54OwogICAgICAgICAgICByZXN1bHRbMV0gPSBzY3JhdGNoRmlyc3RDYXJ0ZXNpYW4ueTsKICAgICAgICAgICAgcmVzdWx0WzJdID0gc2NyYXRjaEZpcnN0Q2FydGVzaWFuLno7CiAgICAgICAgICAgIHJlc3VsdFszXSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFs0XSA9IHNjcmF0Y2hTZWNvbmRDYXJ0ZXNpYW4ueDsKICAgICAgICAgICAgcmVzdWx0WzVdID0gc2NyYXRjaFNlY29uZENhcnRlc2lhbi55OwogICAgICAgICAgICByZXN1bHRbNl0gPSBzY3JhdGNoU2Vjb25kQ2FydGVzaWFuLno7CiAgICAgICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgICAgIHJlc3VsdFs4XSA9IHNjcmF0Y2hUaGlyZENhcnRlc2lhbi54OwogICAgICAgICAgICByZXN1bHRbOV0gPSBzY3JhdGNoVGhpcmRDYXJ0ZXNpYW4ueTsKICAgICAgICAgICAgcmVzdWx0WzEwXSA9IHNjcmF0Y2hUaGlyZENhcnRlc2lhbi56OwogICAgICAgICAgICByZXN1bHRbMTFdID0gMDsKICAgICAgICAgICAgcmVzdWx0WzEyXSA9IG9yaWdpbi54OwogICAgICAgICAgICByZXN1bHRbMTNdID0gb3JpZ2luLnk7CiAgICAgICAgICAgIHJlc3VsdFsxNF0gPSBvcmlnaW4uejsKICAgICAgICAgICAgcmVzdWx0WzE1XSA9IDE7CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICB9OwogICAgICAgICAgbG9jYWxGcmFtZVRvRml4ZWRGcmFtZUNhY2hlW2hhc2hBeGlzXSA9IHJlc3VsdGF0OwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0YXQ7CiAgICAgIH07CiAgICAgIFRyYW5zZm9ybXMuZWFzdE5vcnRoVXBUb0ZpeGVkRnJhbWUgPSBUcmFuc2Zvcm1zLmxvY2FsRnJhbWVUb0ZpeGVkRnJhbWVHZW5lcmF0b3IoCiAgICAgICAgImVhc3QiLAogICAgICAgICJub3J0aCIKICAgICAgKTsKICAgICAgVHJhbnNmb3Jtcy5ub3J0aEVhc3REb3duVG9GaXhlZEZyYW1lID0gVHJhbnNmb3Jtcy5sb2NhbEZyYW1lVG9GaXhlZEZyYW1lR2VuZXJhdG9yKCJub3J0aCIsICJlYXN0Iik7CiAgICAgIFRyYW5zZm9ybXMubm9ydGhVcEVhc3RUb0ZpeGVkRnJhbWUgPSBUcmFuc2Zvcm1zLmxvY2FsRnJhbWVUb0ZpeGVkRnJhbWVHZW5lcmF0b3IoCiAgICAgICAgIm5vcnRoIiwKICAgICAgICAidXAiCiAgICAgICk7CiAgICAgIFRyYW5zZm9ybXMubm9ydGhXZXN0VXBUb0ZpeGVkRnJhbWUgPSBUcmFuc2Zvcm1zLmxvY2FsRnJhbWVUb0ZpeGVkRnJhbWVHZW5lcmF0b3IoCiAgICAgICAgIm5vcnRoIiwKICAgICAgICAid2VzdCIKICAgICAgKTsKICAgICAgc2NyYXRjaEhQUlF1YXRlcm5pb24yID0gbmV3IFF1YXRlcm5pb25fZGVmYXVsdCgpOwogICAgICBzY3JhdGNoU2NhbGUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KDEsIDEsIDEpOwogICAgICBzY3JhdGNoSFBSTWF0cml4NCA9IG5ldyBNYXRyaXg0X2RlZmF1bHQoKTsKICAgICAgVHJhbnNmb3Jtcy5oZWFkaW5nUGl0Y2hSb2xsVG9GaXhlZEZyYW1lID0gZnVuY3Rpb24ob3JpZ2luLCBoZWFkaW5nUGl0Y2hSb2xsLCBlbGxpcHNvaWQsIGZpeGVkRnJhbWVUcmFuc2Zvcm0sIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiSGVhZGluZ1BpdGNoUm9sbCIsIGhlYWRpbmdQaXRjaFJvbGwpOwogICAgICAgIGZpeGVkRnJhbWVUcmFuc2Zvcm0gPSBmaXhlZEZyYW1lVHJhbnNmb3JtID8/IFRyYW5zZm9ybXMuZWFzdE5vcnRoVXBUb0ZpeGVkRnJhbWU7CiAgICAgICAgY29uc3QgaHByUXVhdGVybmlvbiA9IFF1YXRlcm5pb25fZGVmYXVsdC5mcm9tSGVhZGluZ1BpdGNoUm9sbCgKICAgICAgICAgIGhlYWRpbmdQaXRjaFJvbGwsCiAgICAgICAgICBzY3JhdGNoSFBSUXVhdGVybmlvbjIKICAgICAgICApOwogICAgICAgIGNvbnN0IGhwck1hdHJpeCA9IE1hdHJpeDRfZGVmYXVsdC5mcm9tVHJhbnNsYXRpb25RdWF0ZXJuaW9uUm90YXRpb25TY2FsZSgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLAogICAgICAgICAgaHByUXVhdGVybmlvbiwKICAgICAgICAgIHNjcmF0Y2hTY2FsZSwKICAgICAgICAgIHNjcmF0Y2hIUFJNYXRyaXg0CiAgICAgICAgKTsKICAgICAgICByZXN1bHQgPSBmaXhlZEZyYW1lVHJhbnNmb3JtKG9yaWdpbiwgZWxsaXBzb2lkLCByZXN1bHQpOwogICAgICAgIHJldHVybiBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHkocmVzdWx0LCBocHJNYXRyaXgsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hFTlVNYXRyaXg0ID0gbmV3IE1hdHJpeDRfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoSFBSTWF0cml4MyA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgVHJhbnNmb3Jtcy5oZWFkaW5nUGl0Y2hSb2xsUXVhdGVybmlvbiA9IGZ1bmN0aW9uKG9yaWdpbiwgaGVhZGluZ1BpdGNoUm9sbCwgZWxsaXBzb2lkLCBmaXhlZEZyYW1lVHJhbnNmb3JtLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIkhlYWRpbmdQaXRjaFJvbGwiLCBoZWFkaW5nUGl0Y2hSb2xsKTsKICAgICAgICBjb25zdCB0cmFuc2Zvcm0yID0gVHJhbnNmb3Jtcy5oZWFkaW5nUGl0Y2hSb2xsVG9GaXhlZEZyYW1lKAogICAgICAgICAgb3JpZ2luLAogICAgICAgICAgaGVhZGluZ1BpdGNoUm9sbCwKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIGZpeGVkRnJhbWVUcmFuc2Zvcm0sCiAgICAgICAgICBzY3JhdGNoRU5VTWF0cml4NAogICAgICAgICk7CiAgICAgICAgY29uc3Qgcm90YXRpb24gPSBNYXRyaXg0X2RlZmF1bHQuZ2V0TWF0cml4Myh0cmFuc2Zvcm0yLCBzY3JhdGNoSFBSTWF0cml4Myk7CiAgICAgICAgcmV0dXJuIFF1YXRlcm5pb25fZGVmYXVsdC5mcm9tUm90YXRpb25NYXRyaXgocm90YXRpb24sIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIG5vU2NhbGUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KDEsIDEsIDEpOwogICAgICBocHJDZW50ZXJTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBmZlNjcmF0Y2ggPSBuZXcgTWF0cml4NF9kZWZhdWx0KCk7CiAgICAgIGhwclRyYW5zZm9ybVNjcmF0Y2ggPSBuZXcgTWF0cml4NF9kZWZhdWx0KCk7CiAgICAgIGhwclJvdGF0aW9uU2NyYXRjaCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgaHByUXVhdGVybmlvblNjcmF0Y2ggPSBuZXcgUXVhdGVybmlvbl9kZWZhdWx0KCk7CiAgICAgIFRyYW5zZm9ybXMuZml4ZWRGcmFtZVRvSGVhZGluZ1BpdGNoUm9sbCA9IGZ1bmN0aW9uKHRyYW5zZm9ybTIsIGVsbGlwc29pZCwgZml4ZWRGcmFtZVRyYW5zZm9ybSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ0cmFuc2Zvcm0iLCB0cmFuc2Zvcm0yKTsKICAgICAgICBlbGxpcHNvaWQgPSBlbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgICAgICBmaXhlZEZyYW1lVHJhbnNmb3JtID0gZml4ZWRGcmFtZVRyYW5zZm9ybSA/PyBUcmFuc2Zvcm1zLmVhc3ROb3J0aFVwVG9GaXhlZEZyYW1lOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBIZWFkaW5nUGl0Y2hSb2xsX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgY2VudGVyID0gTWF0cml4NF9kZWZhdWx0LmdldFRyYW5zbGF0aW9uKHRyYW5zZm9ybTIsIGhwckNlbnRlclNjcmF0Y2gpOwogICAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzKGNlbnRlciwgQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8pKSB7CiAgICAgICAgICByZXN1bHQuaGVhZGluZyA9IDA7CiAgICAgICAgICByZXN1bHQucGl0Y2ggPSAwOwogICAgICAgICAgcmVzdWx0LnJvbGwgPSAwOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgbGV0IHRvRml4ZWRGcmFtZSA9IE1hdHJpeDRfZGVmYXVsdC5pbnZlcnNlVHJhbnNmb3JtYXRpb24oCiAgICAgICAgICBmaXhlZEZyYW1lVHJhbnNmb3JtKGNlbnRlciwgZWxsaXBzb2lkLCBmZlNjcmF0Y2gpLAogICAgICAgICAgZmZTY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBsZXQgdHJhbnNmb3JtQ29weSA9IE1hdHJpeDRfZGVmYXVsdC5zZXRTY2FsZSh0cmFuc2Zvcm0yLCBub1NjYWxlLCBocHJUcmFuc2Zvcm1TY3JhdGNoKTsKICAgICAgICB0cmFuc2Zvcm1Db3B5ID0gTWF0cml4NF9kZWZhdWx0LnNldFRyYW5zbGF0aW9uKAogICAgICAgICAgdHJhbnNmb3JtQ29weSwKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLAogICAgICAgICAgdHJhbnNmb3JtQ29weQogICAgICAgICk7CiAgICAgICAgdG9GaXhlZEZyYW1lID0gTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5KHRvRml4ZWRGcmFtZSwgdHJhbnNmb3JtQ29weSwgdG9GaXhlZEZyYW1lKTsKICAgICAgICBsZXQgcXVhdGVybmlvblJvdGF0aW9uID0gUXVhdGVybmlvbl9kZWZhdWx0LmZyb21Sb3RhdGlvbk1hdHJpeCgKICAgICAgICAgIE1hdHJpeDRfZGVmYXVsdC5nZXRNYXRyaXgzKHRvRml4ZWRGcmFtZSwgaHByUm90YXRpb25TY3JhdGNoKSwKICAgICAgICAgIGhwclF1YXRlcm5pb25TY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBxdWF0ZXJuaW9uUm90YXRpb24gPSBRdWF0ZXJuaW9uX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgcXVhdGVybmlvblJvdGF0aW9uLAogICAgICAgICAgcXVhdGVybmlvblJvdGF0aW9uCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gSGVhZGluZ1BpdGNoUm9sbF9kZWZhdWx0LmZyb21RdWF0ZXJuaW9uKHF1YXRlcm5pb25Sb3RhdGlvbiwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgZ21zdENvbnN0YW50MCA9IDYgKiAzNjAwICsgNDEgKiA2MCArIDUwLjU0ODQxOwogICAgICBnbXN0Q29uc3RhbnQxID0gODY0MDE4NDgxMjg2NmUtNjsKICAgICAgZ21zdENvbnN0YW50MiA9IDAuMDkzMTA0OwogICAgICBnbXN0Q29uc3RhbnQzID0gLTYyZS03OwogICAgICByYXRlQ29lZiA9IDExNzcyNzU4Mzg0NjY4ZS0zMjsKICAgICAgd2dzODRXUlByZWNlc3NpbmcgPSA3MjkyMTE1ODU1M2UtMTU7CiAgICAgIHR3b1BpT3ZlclNlY29uZHNJbkRheSA9IE1hdGhfZGVmYXVsdC5UV09fUEkgLyA4NjQwMDsKICAgICAgZGF0ZUluVXRjID0gbmV3IEp1bGlhbkRhdGVfZGVmYXVsdCgpOwogICAgICBUcmFuc2Zvcm1zLmNvbXB1dGVJY3JmVG9DZW50cmFsQm9keUZpeGVkTWF0cml4ID0gZnVuY3Rpb24oZGF0ZSwgcmVzdWx0KSB7CiAgICAgICAgbGV0IHRyYW5zZm9ybU1hdHJpeCA9IFRyYW5zZm9ybXMuY29tcHV0ZUljcmZUb0ZpeGVkTWF0cml4KGRhdGUsIHJlc3VsdCk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQodHJhbnNmb3JtTWF0cml4KSkgewogICAgICAgICAgdHJhbnNmb3JtTWF0cml4ID0gVHJhbnNmb3Jtcy5jb21wdXRlVGVtZVRvUHNldWRvRml4ZWRNYXRyaXgoZGF0ZSwgcmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRyYW5zZm9ybU1hdHJpeDsKICAgICAgfTsKICAgICAgVHJhbnNmb3Jtcy5jb21wdXRlVGVtZVRvUHNldWRvRml4ZWRNYXRyaXggPSBmdW5jdGlvbihkYXRlLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChkYXRlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImRhdGUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGRhdGVJblV0YyA9IEp1bGlhbkRhdGVfZGVmYXVsdC5hZGRTZWNvbmRzKAogICAgICAgICAgZGF0ZSwKICAgICAgICAgIC1KdWxpYW5EYXRlX2RlZmF1bHQuY29tcHV0ZVRhaU1pbnVzVXRjKGRhdGUpLAogICAgICAgICAgZGF0ZUluVXRjCiAgICAgICAgKTsKICAgICAgICBjb25zdCB1dGNEYXlOdW1iZXIgPSBkYXRlSW5VdGMuZGF5TnVtYmVyOwogICAgICAgIGNvbnN0IHV0Y1NlY29uZHNJbnRvRGF5ID0gZGF0ZUluVXRjLnNlY29uZHNPZkRheTsKICAgICAgICBsZXQgdDsKICAgICAgICBjb25zdCBkaWZmRGF5cyA9IHV0Y0RheU51bWJlciAtIDI0NTE1NDU7CiAgICAgICAgaWYgKHV0Y1NlY29uZHNJbnRvRGF5ID49IDQzMjAwKSB7CiAgICAgICAgICB0ID0gKGRpZmZEYXlzICsgMC41KSAvIFRpbWVDb25zdGFudHNfZGVmYXVsdC5EQVlTX1BFUl9KVUxJQU5fQ0VOVFVSWTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdCA9IChkaWZmRGF5cyAtIDAuNSkgLyBUaW1lQ29uc3RhbnRzX2RlZmF1bHQuREFZU19QRVJfSlVMSUFOX0NFTlRVUlk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGdtc3QwID0gZ21zdENvbnN0YW50MCArIHQgKiAoZ21zdENvbnN0YW50MSArIHQgKiAoZ21zdENvbnN0YW50MiArIHQgKiBnbXN0Q29uc3RhbnQzKSk7CiAgICAgICAgY29uc3QgYW5nbGUgPSBnbXN0MCAqIHR3b1BpT3ZlclNlY29uZHNJbkRheSAlIE1hdGhfZGVmYXVsdC5UV09fUEk7CiAgICAgICAgY29uc3QgcmF0aW8gPSB3Z3M4NFdSUHJlY2Vzc2luZyArIHJhdGVDb2VmICogKHV0Y0RheU51bWJlciAtIDI0NTE1NDU1ZS0xKTsKICAgICAgICBjb25zdCBzZWNvbmRzU2luY2VNaWRuaWdodCA9ICh1dGNTZWNvbmRzSW50b0RheSArIFRpbWVDb25zdGFudHNfZGVmYXVsdC5TRUNPTkRTX1BFUl9EQVkgKiAwLjUpICUgVGltZUNvbnN0YW50c19kZWZhdWx0LlNFQ09ORFNfUEVSX0RBWTsKICAgICAgICBjb25zdCBnaGEgPSBhbmdsZSArIHJhdGlvICogc2Vjb25kc1NpbmNlTWlkbmlnaHQ7CiAgICAgICAgY29uc3QgY29zR2hhID0gTWF0aC5jb3MoZ2hhKTsKICAgICAgICBjb25zdCBzaW5HaGEgPSBNYXRoLnNpbihnaGEpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgTWF0cml4M19kZWZhdWx0KAogICAgICAgICAgICBjb3NHaGEsCiAgICAgICAgICAgIHNpbkdoYSwKICAgICAgICAgICAgMCwKICAgICAgICAgICAgLXNpbkdoYSwKICAgICAgICAgICAgY29zR2hhLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAwLAogICAgICAgICAgICAxCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXN1bHRbMF0gPSBjb3NHaGE7CiAgICAgICAgcmVzdWx0WzFdID0gLXNpbkdoYTsKICAgICAgICByZXN1bHRbMl0gPSAwOwogICAgICAgIHJlc3VsdFszXSA9IHNpbkdoYTsKICAgICAgICByZXN1bHRbNF0gPSBjb3NHaGE7CiAgICAgICAgcmVzdWx0WzVdID0gMDsKICAgICAgICByZXN1bHRbNl0gPSAwOwogICAgICAgIHJlc3VsdFs3XSA9IDA7CiAgICAgICAgcmVzdWx0WzhdID0gMTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBUcmFuc2Zvcm1zLmlhdTIwMDZYeXNEYXRhID0gbmV3IElhdTIwMDZYeXNEYXRhX2RlZmF1bHQoKTsKICAgICAgVHJhbnNmb3Jtcy5lYXJ0aE9yaWVudGF0aW9uUGFyYW1ldGVycyA9IEVhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzX2RlZmF1bHQuTk9ORTsKICAgICAgdHRNaW51c1RhaSA9IDMyLjE4NDsKICAgICAgajIwMDB0dERheXMgPSAyNDUxNTQ1OwogICAgICBUcmFuc2Zvcm1zLnByZWxvYWRJY3JmRml4ZWQgPSBmdW5jdGlvbih0aW1lSW50ZXJ2YWwpIHsKICAgICAgICBjb25zdCBzdGFydERheVRUID0gdGltZUludGVydmFsLnN0YXJ0LmRheU51bWJlcjsKICAgICAgICBjb25zdCBzdGFydFNlY29uZFRUID0gdGltZUludGVydmFsLnN0YXJ0LnNlY29uZHNPZkRheSArIHR0TWludXNUYWk7CiAgICAgICAgY29uc3Qgc3RvcERheVRUID0gdGltZUludGVydmFsLnN0b3AuZGF5TnVtYmVyOwogICAgICAgIGNvbnN0IHN0b3BTZWNvbmRUVCA9IHRpbWVJbnRlcnZhbC5zdG9wLnNlY29uZHNPZkRheSArIHR0TWludXNUYWk7CiAgICAgICAgcmV0dXJuIFRyYW5zZm9ybXMuaWF1MjAwNlh5c0RhdGEucHJlbG9hZCgKICAgICAgICAgIHN0YXJ0RGF5VFQsCiAgICAgICAgICBzdGFydFNlY29uZFRULAogICAgICAgICAgc3RvcERheVRULAogICAgICAgICAgc3RvcFNlY29uZFRUCiAgICAgICAgKTsKICAgICAgfTsKICAgICAgVHJhbnNmb3Jtcy5jb21wdXRlSWNyZlRvRml4ZWRNYXRyaXggPSBmdW5jdGlvbihkYXRlLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChkYXRlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImRhdGUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZml4ZWRUb0ljcmZNdHggPSBUcmFuc2Zvcm1zLmNvbXB1dGVGaXhlZFRvSWNyZk1hdHJpeChkYXRlLCByZXN1bHQpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGZpeGVkVG9JY3JmTXR4KSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIE1hdHJpeDNfZGVmYXVsdC50cmFuc3Bvc2UoZml4ZWRUb0ljcmZNdHgsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIFRkdE1pbnVzVGFpID0gMzIuMTg0OwogICAgICBKMjAwMGQgPSAyNDUxNTQ1OwogICAgICBzY3JhdGNoSHByID0gbmV3IEhlYWRpbmdQaXRjaFJvbGxfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUm90YXRpb25NYXRyaXggPSBuZXcgTWF0cml4M19kZWZhdWx0KCk7CiAgICAgIGRhdGVTY3JhdGNoID0gbmV3IEp1bGlhbkRhdGVfZGVmYXVsdCgpOwogICAgICBUcmFuc2Zvcm1zLmNvbXB1dGVNb29uRml4ZWRUb0ljcmZNYXRyaXggPSBmdW5jdGlvbihkYXRlLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChkYXRlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImRhdGUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc2Vjb25kc1RUID0gSnVsaWFuRGF0ZV9kZWZhdWx0LmFkZFNlY29uZHMoZGF0ZSwgVGR0TWludXNUYWksIGRhdGVTY3JhdGNoKTsKICAgICAgICBjb25zdCBkID0gSnVsaWFuRGF0ZV9kZWZhdWx0LnRvdGFsRGF5cyhzZWNvbmRzVFQpIC0gSjIwMDBkOwogICAgICAgIGNvbnN0IGUxID0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucygxMi4xMTIpIC0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucygwLjA1Mjk5MikgKiBkOwogICAgICAgIGNvbnN0IGUyID0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucygyNC4yMjQpIC0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucygwLjEwNTk4NCkgKiBkOwogICAgICAgIGNvbnN0IGUzID0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucygyMjcuNjQ1KSArIE1hdGhfZGVmYXVsdC50b1JhZGlhbnMoMTMuMDEyKSAqIGQ7CiAgICAgICAgY29uc3QgZTQgPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKDI2MS4xMDUpICsgTWF0aF9kZWZhdWx0LnRvUmFkaWFucygxMy4zNDA3MTYpICogZDsKICAgICAgICBjb25zdCBlNSA9IE1hdGhfZGVmYXVsdC50b1JhZGlhbnMoMzU4KSArIE1hdGhfZGVmYXVsdC50b1JhZGlhbnMoMC45ODU2KSAqIGQ7CiAgICAgICAgc2NyYXRjaEhwci5waXRjaCA9IE1hdGhfZGVmYXVsdC50b1JhZGlhbnMoMjcwIC0gOTApIC0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucygzLjg3OCkgKiBNYXRoLnNpbihlMSkgLSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKDAuMTIpICogTWF0aC5zaW4oZTIpICsgTWF0aF9kZWZhdWx0LnRvUmFkaWFucygwLjA3KSAqIE1hdGguc2luKGUzKSAtIE1hdGhfZGVmYXVsdC50b1JhZGlhbnMoMC4wMTcpICogTWF0aC5zaW4oZTQpOwogICAgICAgIHNjcmF0Y2hIcHIucm9sbCA9IE1hdGhfZGVmYXVsdC50b1JhZGlhbnMoNjYuNTMgLSA5MCkgKyBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKDEuNTQzKSAqIE1hdGguY29zKGUxKSArIE1hdGhfZGVmYXVsdC50b1JhZGlhbnMoMC4yNCkgKiBNYXRoLmNvcyhlMikgLSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKDAuMDI4KSAqIE1hdGguY29zKGUzKSArIE1hdGhfZGVmYXVsdC50b1JhZGlhbnMoN2UtMykgKiBNYXRoLmNvcyhlNCk7CiAgICAgICAgc2NyYXRjaEhwci5oZWFkaW5nID0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucygyNDQuMzc1IC0gOTApICsgTWF0aF9kZWZhdWx0LnRvUmFkaWFucygxMy4xNzYzNTgzMSkgKiBkICsgTWF0aF9kZWZhdWx0LnRvUmFkaWFucygzLjU1OCkgKiBNYXRoLnNpbihlMSkgKyBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKDAuMTIxKSAqIE1hdGguc2luKGUyKSAtIE1hdGhfZGVmYXVsdC50b1JhZGlhbnMoMC4wNjQpICogTWF0aC5zaW4oZTMpICsgTWF0aF9kZWZhdWx0LnRvUmFkaWFucygwLjAxNikgKiBNYXRoLnNpbihlNCkgKyBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKDAuMDI1KSAqIE1hdGguc2luKGU1KTsKICAgICAgICByZXR1cm4gTWF0cml4M19kZWZhdWx0LmZyb21IZWFkaW5nUGl0Y2hSb2xsKHNjcmF0Y2hIcHIsIHNjcmF0Y2hSb3RhdGlvbk1hdHJpeCk7CiAgICAgIH07CiAgICAgIFRyYW5zZm9ybXMuY29tcHV0ZUljcmZUb01vb25GaXhlZE1hdHJpeCA9IGZ1bmN0aW9uKGRhdGUsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGRhdGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZGF0ZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IE1hdHJpeDNfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICBjb25zdCBmaXhlZFRvSWNyZk10eCA9IFRyYW5zZm9ybXMuY29tcHV0ZU1vb25GaXhlZFRvSWNyZk1hdHJpeChkYXRlLCByZXN1bHQpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGZpeGVkVG9JY3JmTXR4KSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIE1hdHJpeDNfZGVmYXVsdC50cmFuc3Bvc2UoZml4ZWRUb0ljcmZNdHgsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIHh5c1NjcmF0Y2ggPSBuZXcgSWF1MjAwNlh5c1NhbXBsZV9kZWZhdWx0KDAsIDAsIDApOwogICAgICBlb3BTY3JhdGNoID0gbmV3IEVhcnRoT3JpZW50YXRpb25QYXJhbWV0ZXJzU2FtcGxlX2RlZmF1bHQoCiAgICAgICAgMCwKICAgICAgICAwLAogICAgICAgIDAsCiAgICAgICAgMCwKICAgICAgICAwLAogICAgICAgIDAKICAgICAgKTsKICAgICAgcm90YXRpb24xU2NyYXRjaCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgcm90YXRpb24yU2NyYXRjaCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgVHJhbnNmb3Jtcy5jb21wdXRlRml4ZWRUb0ljcmZNYXRyaXggPSBmdW5jdGlvbihkYXRlLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChkYXRlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImRhdGUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZW9wID0gVHJhbnNmb3Jtcy5lYXJ0aE9yaWVudGF0aW9uUGFyYW1ldGVycy5jb21wdXRlKGRhdGUsIGVvcFNjcmF0Y2gpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGVvcCkpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGRheVRUID0gZGF0ZS5kYXlOdW1iZXI7CiAgICAgICAgY29uc3Qgc2Vjb25kVFQgPSBkYXRlLnNlY29uZHNPZkRheSArIHR0TWludXNUYWk7CiAgICAgICAgY29uc3QgeHlzID0gVHJhbnNmb3Jtcy5pYXUyMDA2WHlzRGF0YS5jb21wdXRlWHlzUmFkaWFucygKICAgICAgICAgIGRheVRULAogICAgICAgICAgc2Vjb25kVFQsCiAgICAgICAgICB4eXNTY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh4eXMpKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBjb25zdCB4ID0geHlzLnggKyBlb3AueFBvbGVPZmZzZXQ7CiAgICAgICAgY29uc3QgeSA9IHh5cy55ICsgZW9wLnlQb2xlT2Zmc2V0OwogICAgICAgIGNvbnN0IGEzID0gMSAvICgxICsgTWF0aC5zcXJ0KDEgLSB4ICogeCAtIHkgKiB5KSk7CiAgICAgICAgY29uc3Qgcm90YXRpb24xID0gcm90YXRpb24xU2NyYXRjaDsKICAgICAgICByb3RhdGlvbjFbMF0gPSAxIC0gYTMgKiB4ICogeDsKICAgICAgICByb3RhdGlvbjFbM10gPSAtYTMgKiB4ICogeTsKICAgICAgICByb3RhdGlvbjFbNl0gPSB4OwogICAgICAgIHJvdGF0aW9uMVsxXSA9IC1hMyAqIHggKiB5OwogICAgICAgIHJvdGF0aW9uMVs0XSA9IDEgLSBhMyAqIHkgKiB5OwogICAgICAgIHJvdGF0aW9uMVs3XSA9IHk7CiAgICAgICAgcm90YXRpb24xWzJdID0gLXg7CiAgICAgICAgcm90YXRpb24xWzVdID0gLXk7CiAgICAgICAgcm90YXRpb24xWzhdID0gMSAtIGEzICogKHggKiB4ICsgeSAqIHkpOwogICAgICAgIGNvbnN0IHJvdGF0aW9uMiA9IE1hdHJpeDNfZGVmYXVsdC5mcm9tUm90YXRpb25aKC14eXMucywgcm90YXRpb24yU2NyYXRjaCk7CiAgICAgICAgY29uc3QgbWF0cml4USA9IE1hdHJpeDNfZGVmYXVsdC5tdWx0aXBseShyb3RhdGlvbjEsIHJvdGF0aW9uMiwgcm90YXRpb24xU2NyYXRjaCk7CiAgICAgICAgY29uc3QgZGF0ZVV0MWRheSA9IGRhdGUuZGF5TnVtYmVyOwogICAgICAgIGNvbnN0IGRhdGVVdDFzZWMgPSBkYXRlLnNlY29uZHNPZkRheSAtIEp1bGlhbkRhdGVfZGVmYXVsdC5jb21wdXRlVGFpTWludXNVdGMoZGF0ZSkgKyBlb3AudXQxTWludXNVdGM7CiAgICAgICAgY29uc3QgZGF5c1NpbmNlSjIwMDAgPSBkYXRlVXQxZGF5IC0gMjQ1MTU0NTsKICAgICAgICBjb25zdCBmcmFjdGlvbk9mRGF5ID0gZGF0ZVV0MXNlYyAvIFRpbWVDb25zdGFudHNfZGVmYXVsdC5TRUNPTkRTX1BFUl9EQVk7CiAgICAgICAgbGV0IGVyYSA9IDAuNzc5MDU3MjczMjY0ICsgZnJhY3Rpb25PZkRheSArIDAuMDAyNzM3ODExOTExMzU0NDggKiAoZGF5c1NpbmNlSjIwMDAgKyBmcmFjdGlvbk9mRGF5KTsKICAgICAgICBlcmEgPSBlcmEgJSAxICogTWF0aF9kZWZhdWx0LlRXT19QSTsKICAgICAgICBjb25zdCBlYXJ0aFJvdGF0aW9uID0gTWF0cml4M19kZWZhdWx0LmZyb21Sb3RhdGlvblooZXJhLCByb3RhdGlvbjJTY3JhdGNoKTsKICAgICAgICBjb25zdCBwZlRvSWNyZiA9IE1hdHJpeDNfZGVmYXVsdC5tdWx0aXBseShtYXRyaXhRLCBlYXJ0aFJvdGF0aW9uLCByb3RhdGlvbjFTY3JhdGNoKTsKICAgICAgICBjb25zdCBjb3N4cCA9IE1hdGguY29zKGVvcC54UG9sZVdhbmRlcik7CiAgICAgICAgY29uc3QgY29zeXAgPSBNYXRoLmNvcyhlb3AueVBvbGVXYW5kZXIpOwogICAgICAgIGNvbnN0IHNpbnhwID0gTWF0aC5zaW4oZW9wLnhQb2xlV2FuZGVyKTsKICAgICAgICBjb25zdCBzaW55cCA9IE1hdGguc2luKGVvcC55UG9sZVdhbmRlcik7CiAgICAgICAgbGV0IHR0dCA9IGRheVRUIC0gajIwMDB0dERheXMgKyBzZWNvbmRUVCAvIFRpbWVDb25zdGFudHNfZGVmYXVsdC5TRUNPTkRTX1BFUl9EQVk7CiAgICAgICAgdHR0IC89IDM2NTI1OwogICAgICAgIGNvbnN0IHNwID0gLTQ3ZS02ICogdHR0ICogTWF0aF9kZWZhdWx0LlJBRElBTlNfUEVSX0RFR1JFRSAvIDM2MDA7CiAgICAgICAgY29uc3QgY29zc3AgPSBNYXRoLmNvcyhzcCk7CiAgICAgICAgY29uc3Qgc2luc3AgPSBNYXRoLnNpbihzcCk7CiAgICAgICAgY29uc3QgZlRvUGZNdHggPSByb3RhdGlvbjJTY3JhdGNoOwogICAgICAgIGZUb1BmTXR4WzBdID0gY29zeHAgKiBjb3NzcDsKICAgICAgICBmVG9QZk10eFsxXSA9IGNvc3hwICogc2luc3A7CiAgICAgICAgZlRvUGZNdHhbMl0gPSBzaW54cDsKICAgICAgICBmVG9QZk10eFszXSA9IC1jb3N5cCAqIHNpbnNwICsgc2lueXAgKiBzaW54cCAqIGNvc3NwOwogICAgICAgIGZUb1BmTXR4WzRdID0gY29zeXAgKiBjb3NzcCArIHNpbnlwICogc2lueHAgKiBzaW5zcDsKICAgICAgICBmVG9QZk10eFs1XSA9IC1zaW55cCAqIGNvc3hwOwogICAgICAgIGZUb1BmTXR4WzZdID0gLXNpbnlwICogc2luc3AgLSBjb3N5cCAqIHNpbnhwICogY29zc3A7CiAgICAgICAgZlRvUGZNdHhbN10gPSBzaW55cCAqIGNvc3NwIC0gY29zeXAgKiBzaW54cCAqIHNpbnNwOwogICAgICAgIGZUb1BmTXR4WzhdID0gY29zeXAgKiBjb3N4cDsKICAgICAgICByZXR1cm4gTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5KHBmVG9JY3JmLCBmVG9QZk10eCwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgcG9pbnRUb1dpbmRvd0Nvb3JkaW5hdGVzVGVtcCA9IG5ldyBDYXJ0ZXNpYW40X2RlZmF1bHQoKTsKICAgICAgVHJhbnNmb3Jtcy5wb2ludFRvV2luZG93Q29vcmRpbmF0ZXMgPSBmdW5jdGlvbihtb2RlbFZpZXdQcm9qZWN0aW9uTWF0cml4LCB2aWV3cG9ydFRyYW5zZm9ybWF0aW9uLCBwb2ludCwgcmVzdWx0KSB7CiAgICAgICAgcmVzdWx0ID0gVHJhbnNmb3Jtcy5wb2ludFRvR0xXaW5kb3dDb29yZGluYXRlcygKICAgICAgICAgIG1vZGVsVmlld1Byb2plY3Rpb25NYXRyaXgsCiAgICAgICAgICB2aWV3cG9ydFRyYW5zZm9ybWF0aW9uLAogICAgICAgICAgcG9pbnQsCiAgICAgICAgICByZXN1bHQKICAgICAgICApOwogICAgICAgIHJlc3VsdC55ID0gMiAqIHZpZXdwb3J0VHJhbnNmb3JtYXRpb25bNV0gLSByZXN1bHQueTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBUcmFuc2Zvcm1zLnBvaW50VG9HTFdpbmRvd0Nvb3JkaW5hdGVzID0gZnVuY3Rpb24obW9kZWxWaWV3UHJvamVjdGlvbk1hdHJpeCwgdmlld3BvcnRUcmFuc2Zvcm1hdGlvbiwgcG9pbnQsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG1vZGVsVmlld1Byb2plY3Rpb25NYXRyaXgpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgibW9kZWxWaWV3UHJvamVjdGlvbk1hdHJpeCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQodmlld3BvcnRUcmFuc2Zvcm1hdGlvbikpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ2aWV3cG9ydFRyYW5zZm9ybWF0aW9uIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwb2ludCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJwb2ludCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICBjb25zdCB0bXAyID0gcG9pbnRUb1dpbmRvd0Nvb3JkaW5hdGVzVGVtcDsKICAgICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlCeVZlY3RvcigKICAgICAgICAgIG1vZGVsVmlld1Byb2plY3Rpb25NYXRyaXgsCiAgICAgICAgICBDYXJ0ZXNpYW40X2RlZmF1bHQuZnJvbUVsZW1lbnRzKHBvaW50LngsIHBvaW50LnksIHBvaW50LnosIDEsIHRtcDIpLAogICAgICAgICAgdG1wMgogICAgICAgICk7CiAgICAgICAgQ2FydGVzaWFuNF9kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIodG1wMiwgMSAvIHRtcDIudywgdG1wMik7CiAgICAgICAgTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3Iodmlld3BvcnRUcmFuc2Zvcm1hdGlvbiwgdG1wMiwgdG1wMik7CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tQ2FydGVzaWFuNCh0bXAyLCByZXN1bHQpOwogICAgICB9OwogICAgICBub3JtYWxTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICByaWdodFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHVwU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgVHJhbnNmb3Jtcy5yb3RhdGlvbk1hdHJpeEZyb21Qb3NpdGlvblZlbG9jaXR5ID0gZnVuY3Rpb24ocG9zaXRpb24sIHZlbG9jaXR5LCBlbGxpcHNvaWQsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBvc2l0aW9uKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInBvc2l0aW9uIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh2ZWxvY2l0eSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ2ZWxvY2l0eSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgbm9ybWFsMiA9IChlbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdCkuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKAogICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICBub3JtYWxTY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBsZXQgcmlnaHQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3ModmVsb2NpdHksIG5vcm1hbDIsIHJpZ2h0U2NyYXRjaCk7CiAgICAgICAgaWYgKENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKHJpZ2h0LCBDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywgTWF0aF9kZWZhdWx0LkVQU0lMT042KSkgewogICAgICAgICAgcmlnaHQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWCwgcmlnaHQpOwogICAgICAgIH0KICAgICAgICBjb25zdCB1cCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhyaWdodCwgdmVsb2NpdHksIHVwU2NyYXRjaCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSh1cCwgdXApOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyh2ZWxvY2l0eSwgdXAsIHJpZ2h0KTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKHJpZ2h0LCByaWdodCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShyaWdodCwgcmlnaHQpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gdmVsb2NpdHkueDsKICAgICAgICByZXN1bHRbMV0gPSB2ZWxvY2l0eS55OwogICAgICAgIHJlc3VsdFsyXSA9IHZlbG9jaXR5Lno7CiAgICAgICAgcmVzdWx0WzNdID0gcmlnaHQueDsKICAgICAgICByZXN1bHRbNF0gPSByaWdodC55OwogICAgICAgIHJlc3VsdFs1XSA9IHJpZ2h0Lno7CiAgICAgICAgcmVzdWx0WzZdID0gdXAueDsKICAgICAgICByZXN1bHRbN10gPSB1cC55OwogICAgICAgIHJlc3VsdFs4XSA9IHVwLno7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc3dpenpsZU1hdHJpeCA9IG5ldyBNYXRyaXg0X2RlZmF1bHQoCiAgICAgICAgMCwKICAgICAgICAwLAogICAgICAgIDEsCiAgICAgICAgMCwKICAgICAgICAxLAogICAgICAgIDAsCiAgICAgICAgMCwKICAgICAgICAwLAogICAgICAgIDAsCiAgICAgICAgMSwKICAgICAgICAwLAogICAgICAgIDAsCiAgICAgICAgMCwKICAgICAgICAwLAogICAgICAgIDAsCiAgICAgICAgMQogICAgICApOwogICAgICBzY3JhdGNoQ2FydG9ncmFwaGljID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4zUHJvamVjdGlvbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENlbnRlciA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFJvdGF0aW9uID0gbmV3IE1hdHJpeDNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoRnJvbUVOVSA9IG5ldyBNYXRyaXg0X2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFRvRU5VID0gbmV3IE1hdHJpeDRfZGVmYXVsdCgpOwogICAgICBUcmFuc2Zvcm1zLmJhc2lzVG8yRCA9IGZ1bmN0aW9uKHByb2plY3Rpb24sIG1hdHJpeCwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocHJvamVjdGlvbikpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJwcm9qZWN0aW9uIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChtYXRyaXgpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgibWF0cml4IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicmVzdWx0IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBydGNDZW50ZXIgPSBNYXRyaXg0X2RlZmF1bHQuZ2V0VHJhbnNsYXRpb24obWF0cml4LCBzY3JhdGNoQ2VudGVyKTsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBwcm9qZWN0aW9uLmVsbGlwc29pZDsKICAgICAgICBsZXQgcHJvamVjdGVkUG9zaXRpb247CiAgICAgICAgaWYgKENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHMocnRjQ2VudGVyLCBDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTykpIHsKICAgICAgICAgIHByb2plY3RlZFBvc2l0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKAogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywKICAgICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjNQcm9qZWN0aW9uCiAgICAgICAgICApOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb25zdCBjYXJ0b2dyYXBoaWMyID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKAogICAgICAgICAgICBydGNDZW50ZXIsCiAgICAgICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWMKICAgICAgICAgICk7CiAgICAgICAgICBwcm9qZWN0ZWRQb3NpdGlvbiA9IHByb2plY3Rpb24ucHJvamVjdCgKICAgICAgICAgICAgY2FydG9ncmFwaGljMiwKICAgICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjNQcm9qZWN0aW9uCiAgICAgICAgICApOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21FbGVtZW50cygKICAgICAgICAgICAgcHJvamVjdGVkUG9zaXRpb24ueiwKICAgICAgICAgICAgcHJvamVjdGVkUG9zaXRpb24ueCwKICAgICAgICAgICAgcHJvamVjdGVkUG9zaXRpb24ueSwKICAgICAgICAgICAgcHJvamVjdGVkUG9zaXRpb24KICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGZyb21FTlUgPSBUcmFuc2Zvcm1zLmVhc3ROb3J0aFVwVG9GaXhlZEZyYW1lKAogICAgICAgICAgcnRjQ2VudGVyLAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgc2NyYXRjaEZyb21FTlUKICAgICAgICApOwogICAgICAgIGNvbnN0IHRvRU5VID0gTWF0cml4NF9kZWZhdWx0LmludmVyc2VUcmFuc2Zvcm1hdGlvbihmcm9tRU5VLCBzY3JhdGNoVG9FTlUpOwogICAgICAgIGNvbnN0IHJvdGF0aW9uID0gTWF0cml4NF9kZWZhdWx0LmdldE1hdHJpeDMobWF0cml4LCBzY3JhdGNoUm90YXRpb24pOwogICAgICAgIGNvbnN0IGxvY2FsID0gTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5QnlNYXRyaXgzKHRvRU5VLCByb3RhdGlvbiwgcmVzdWx0KTsKICAgICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHkoc3dpenpsZU1hdHJpeCwgbG9jYWwsIHJlc3VsdCk7CiAgICAgICAgTWF0cml4NF9kZWZhdWx0LnNldFRyYW5zbGF0aW9uKHJlc3VsdCwgcHJvamVjdGVkUG9zaXRpb24sIHJlc3VsdCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgVHJhbnNmb3Jtcy5lbGxpcHNvaWRUbzJETW9kZWxNYXRyaXggPSBmdW5jdGlvbihwcm9qZWN0aW9uLCBjZW50ZXIsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHByb2plY3Rpb24pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicHJvamVjdGlvbiBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoY2VudGVyKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImNlbnRlciBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInJlc3VsdCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gcHJvamVjdGlvbi5lbGxpcHNvaWQ7CiAgICAgICAgY29uc3QgZnJvbUVOVSA9IFRyYW5zZm9ybXMuZWFzdE5vcnRoVXBUb0ZpeGVkRnJhbWUoCiAgICAgICAgICBjZW50ZXIsCiAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICBzY3JhdGNoRnJvbUVOVQogICAgICAgICk7CiAgICAgICAgY29uc3QgdG9FTlUgPSBNYXRyaXg0X2RlZmF1bHQuaW52ZXJzZVRyYW5zZm9ybWF0aW9uKGZyb21FTlUsIHNjcmF0Y2hUb0VOVSk7CiAgICAgICAgY29uc3QgY2FydG9ncmFwaGljMiA9IGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYygKICAgICAgICAgIGNlbnRlciwKICAgICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWMKICAgICAgICApOwogICAgICAgIGNvbnN0IHByb2plY3RlZFBvc2l0aW9uID0gcHJvamVjdGlvbi5wcm9qZWN0KAogICAgICAgICAgY2FydG9ncmFwaGljMiwKICAgICAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4zUHJvamVjdGlvbgogICAgICAgICk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21FbGVtZW50cygKICAgICAgICAgIHByb2plY3RlZFBvc2l0aW9uLnosCiAgICAgICAgICBwcm9qZWN0ZWRQb3NpdGlvbi54LAogICAgICAgICAgcHJvamVjdGVkUG9zaXRpb24ueSwKICAgICAgICAgIHByb2plY3RlZFBvc2l0aW9uCiAgICAgICAgKTsKICAgICAgICBjb25zdCB0cmFuc2xhdGlvbjIgPSBNYXRyaXg0X2RlZmF1bHQuZnJvbVRyYW5zbGF0aW9uKAogICAgICAgICAgcHJvamVjdGVkUG9zaXRpb24sCiAgICAgICAgICBzY3JhdGNoRnJvbUVOVQogICAgICAgICk7CiAgICAgICAgTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5KHN3aXp6bGVNYXRyaXgsIHRvRU5VLCByZXN1bHQpOwogICAgICAgIE1hdHJpeDRfZGVmYXVsdC5tdWx0aXBseSh0cmFuc2xhdGlvbjIsIHJlc3VsdCwgcmVzdWx0KTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBUcmFuc2Zvcm1zX2RlZmF1bHQgPSBUcmFuc2Zvcm1zOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUmVjdGFuZ2xlLmpzCiAgZnVuY3Rpb24gUmVjdGFuZ2xlKHdlc3QsIHNvdXRoLCBlYXN0LCBub3J0aCkgewogICAgdGhpcy53ZXN0ID0gd2VzdCA/PyAwOwogICAgdGhpcy5zb3V0aCA9IHNvdXRoID8/IDA7CiAgICB0aGlzLmVhc3QgPSBlYXN0ID8/IDA7CiAgICB0aGlzLm5vcnRoID0gbm9ydGggPz8gMDsKICB9CiAgdmFyIGZyb21Cb3VuZGluZ1NwaGVyZU1hdHJpeFNjcmF0Y2gsIGZyb21Cb3VuZGluZ1NwaGVyZUVhc3RTY3JhdGNoLCBmcm9tQm91bmRpbmdTcGhlcmVOb3J0aFNjcmF0Y2gsIGZyb21Cb3VuZGluZ1NwaGVyZVdlc3RTY3JhdGNoLCBmcm9tQm91bmRpbmdTcGhlcmVTb3V0aFNjcmF0Y2gsIGZyb21Cb3VuZGluZ1NwaGVyZVBvc2l0aW9uc1NjcmF0Y2gsIHN1YnNhbXBsZUxsYVNjcmF0Y2gsIFJlY3RhbmdsZV9kZWZhdWx0OwogIHZhciBpbml0X1JlY3RhbmdsZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUmVjdGFuZ2xlLmpzIigpIHsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1RyYW5zZm9ybXMoKTsKICAgICAgaW5pdF9NYXRyaXg0KCk7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKFJlY3RhbmdsZS5wcm90b3R5cGUsIHsKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSB3aWR0aCBvZiB0aGUgcmVjdGFuZ2xlIGluIHJhZGlhbnMuCiAgICAgICAgICogQG1lbWJlcm9mIFJlY3RhbmdsZS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIHdpZHRoOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gUmVjdGFuZ2xlLmNvbXB1dGVXaWR0aCh0aGlzKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIGhlaWdodCBvZiB0aGUgcmVjdGFuZ2xlIGluIHJhZGlhbnMuCiAgICAgICAgICogQG1lbWJlcm9mIFJlY3RhbmdsZS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIGhlaWdodDogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIFJlY3RhbmdsZS5jb21wdXRlSGVpZ2h0KHRoaXMpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIFJlY3RhbmdsZS5wYWNrZWRMZW5ndGggPSA0OwogICAgICBSZWN0YW5nbGUucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS53ZXN0OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5zb3V0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuZWFzdDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLm5vcnRoOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLnVucGFjayA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydGluZ0luZGV4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IFJlY3RhbmdsZSgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQud2VzdCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LnNvdXRoID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHQuZWFzdCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0Lm5vcnRoID0gYXJyYXlbc3RhcnRpbmdJbmRleF07CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLmNvbXB1dGVXaWR0aCA9IGZ1bmN0aW9uKHJlY3RhbmdsZSkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVjdGFuZ2xlIiwgcmVjdGFuZ2xlKTsKICAgICAgICBsZXQgZWFzdCA9IHJlY3RhbmdsZS5lYXN0OwogICAgICAgIGNvbnN0IHdlc3QgPSByZWN0YW5nbGUud2VzdDsKICAgICAgICBpZiAoZWFzdCA8IHdlc3QpIHsKICAgICAgICAgIGVhc3QgKz0gTWF0aF9kZWZhdWx0LlRXT19QSTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGVhc3QgLSB3ZXN0OwogICAgICB9OwogICAgICBSZWN0YW5nbGUuY29tcHV0ZUhlaWdodCA9IGZ1bmN0aW9uKHJlY3RhbmdsZSkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVjdGFuZ2xlIiwgcmVjdGFuZ2xlKTsKICAgICAgICByZXR1cm4gcmVjdGFuZ2xlLm5vcnRoIC0gcmVjdGFuZ2xlLnNvdXRoOwogICAgICB9OwogICAgICBSZWN0YW5nbGUuZnJvbURlZ3JlZXMgPSBmdW5jdGlvbih3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGgsIHJlc3VsdCkgewogICAgICAgIHdlc3QgPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKHdlc3QgPz8gMCk7CiAgICAgICAgc291dGggPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKHNvdXRoID8/IDApOwogICAgICAgIGVhc3QgPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKGVhc3QgPz8gMCk7CiAgICAgICAgbm9ydGggPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKG5vcnRoID8/IDApOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgUmVjdGFuZ2xlKHdlc3QsIHNvdXRoLCBlYXN0LCBub3J0aCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC53ZXN0ID0gd2VzdDsKICAgICAgICByZXN1bHQuc291dGggPSBzb3V0aDsKICAgICAgICByZXN1bHQuZWFzdCA9IGVhc3Q7CiAgICAgICAgcmVzdWx0Lm5vcnRoID0gbm9ydGg7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLmZyb21SYWRpYW5zID0gZnVuY3Rpb24od2VzdCwgc291dGgsIGVhc3QsIG5vcnRoLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFJlY3RhbmdsZSh3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQud2VzdCA9IHdlc3QgPz8gMDsKICAgICAgICByZXN1bHQuc291dGggPSBzb3V0aCA/PyAwOwogICAgICAgIHJlc3VsdC5lYXN0ID0gZWFzdCA/PyAwOwogICAgICAgIHJlc3VsdC5ub3J0aCA9IG5vcnRoID8/IDA7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLmZyb21DYXJ0b2dyYXBoaWNBcnJheSA9IGZ1bmN0aW9uKGNhcnRvZ3JhcGhpY3MsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiY2FydG9ncmFwaGljcyIsIGNhcnRvZ3JhcGhpY3MpOwogICAgICAgIGxldCB3ZXN0ID0gTnVtYmVyLk1BWF9WQUxVRTsKICAgICAgICBsZXQgZWFzdCA9IC1OdW1iZXIuTUFYX1ZBTFVFOwogICAgICAgIGxldCB3ZXN0T3ZlcklETCA9IE51bWJlci5NQVhfVkFMVUU7CiAgICAgICAgbGV0IGVhc3RPdmVySURMID0gLU51bWJlci5NQVhfVkFMVUU7CiAgICAgICAgbGV0IHNvdXRoID0gTnVtYmVyLk1BWF9WQUxVRTsKICAgICAgICBsZXQgbm9ydGggPSAtTnVtYmVyLk1BWF9WQUxVRTsKICAgICAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gY2FydG9ncmFwaGljcy5sZW5ndGg7IGkgPCBsZW47IGkrKykgewogICAgICAgICAgY29uc3QgcG9zaXRpb24gPSBjYXJ0b2dyYXBoaWNzW2ldOwogICAgICAgICAgd2VzdCA9IE1hdGgubWluKHdlc3QsIHBvc2l0aW9uLmxvbmdpdHVkZSk7CiAgICAgICAgICBlYXN0ID0gTWF0aC5tYXgoZWFzdCwgcG9zaXRpb24ubG9uZ2l0dWRlKTsKICAgICAgICAgIHNvdXRoID0gTWF0aC5taW4oc291dGgsIHBvc2l0aW9uLmxhdGl0dWRlKTsKICAgICAgICAgIG5vcnRoID0gTWF0aC5tYXgobm9ydGgsIHBvc2l0aW9uLmxhdGl0dWRlKTsKICAgICAgICAgIGNvbnN0IGxvbkFkanVzdGVkID0gcG9zaXRpb24ubG9uZ2l0dWRlID49IDAgPyBwb3NpdGlvbi5sb25naXR1ZGUgOiBwb3NpdGlvbi5sb25naXR1ZGUgKyBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgICAgICAgd2VzdE92ZXJJREwgPSBNYXRoLm1pbih3ZXN0T3ZlcklETCwgbG9uQWRqdXN0ZWQpOwogICAgICAgICAgZWFzdE92ZXJJREwgPSBNYXRoLm1heChlYXN0T3ZlcklETCwgbG9uQWRqdXN0ZWQpOwogICAgICAgIH0KICAgICAgICBpZiAoZWFzdCAtIHdlc3QgPiBlYXN0T3ZlcklETCAtIHdlc3RPdmVySURMKSB7CiAgICAgICAgICB3ZXN0ID0gd2VzdE92ZXJJREw7CiAgICAgICAgICBlYXN0ID0gZWFzdE92ZXJJREw7CiAgICAgICAgICBpZiAoZWFzdCA+IE1hdGhfZGVmYXVsdC5QSSkgewogICAgICAgICAgICBlYXN0ID0gZWFzdCAtIE1hdGhfZGVmYXVsdC5UV09fUEk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAod2VzdCA+IE1hdGhfZGVmYXVsdC5QSSkgewogICAgICAgICAgICB3ZXN0ID0gd2VzdCAtIE1hdGhfZGVmYXVsdC5UV09fUEk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgUmVjdGFuZ2xlKHdlc3QsIHNvdXRoLCBlYXN0LCBub3J0aCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC53ZXN0ID0gd2VzdDsKICAgICAgICByZXN1bHQuc291dGggPSBzb3V0aDsKICAgICAgICByZXN1bHQuZWFzdCA9IGVhc3Q7CiAgICAgICAgcmVzdWx0Lm5vcnRoID0gbm9ydGg7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLmZyb21DYXJ0ZXNpYW5BcnJheSA9IGZ1bmN0aW9uKGNhcnRlc2lhbnMsIGVsbGlwc29pZCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJjYXJ0ZXNpYW5zIiwgY2FydGVzaWFucyk7CiAgICAgICAgZWxsaXBzb2lkID0gZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICAgICAgbGV0IHdlc3QgPSBOdW1iZXIuTUFYX1ZBTFVFOwogICAgICAgIGxldCBlYXN0ID0gLU51bWJlci5NQVhfVkFMVUU7CiAgICAgICAgbGV0IHdlc3RPdmVySURMID0gTnVtYmVyLk1BWF9WQUxVRTsKICAgICAgICBsZXQgZWFzdE92ZXJJREwgPSAtTnVtYmVyLk1BWF9WQUxVRTsKICAgICAgICBsZXQgc291dGggPSBOdW1iZXIuTUFYX1ZBTFVFOwogICAgICAgIGxldCBub3J0aCA9IC1OdW1iZXIuTUFYX1ZBTFVFOwogICAgICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBjYXJ0ZXNpYW5zLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyhjYXJ0ZXNpYW5zW2ldKTsKICAgICAgICAgIHdlc3QgPSBNYXRoLm1pbih3ZXN0LCBwb3NpdGlvbi5sb25naXR1ZGUpOwogICAgICAgICAgZWFzdCA9IE1hdGgubWF4KGVhc3QsIHBvc2l0aW9uLmxvbmdpdHVkZSk7CiAgICAgICAgICBzb3V0aCA9IE1hdGgubWluKHNvdXRoLCBwb3NpdGlvbi5sYXRpdHVkZSk7CiAgICAgICAgICBub3J0aCA9IE1hdGgubWF4KG5vcnRoLCBwb3NpdGlvbi5sYXRpdHVkZSk7CiAgICAgICAgICBjb25zdCBsb25BZGp1c3RlZCA9IHBvc2l0aW9uLmxvbmdpdHVkZSA+PSAwID8gcG9zaXRpb24ubG9uZ2l0dWRlIDogcG9zaXRpb24ubG9uZ2l0dWRlICsgTWF0aF9kZWZhdWx0LlRXT19QSTsKICAgICAgICAgIHdlc3RPdmVySURMID0gTWF0aC5taW4od2VzdE92ZXJJREwsIGxvbkFkanVzdGVkKTsKICAgICAgICAgIGVhc3RPdmVySURMID0gTWF0aC5tYXgoZWFzdE92ZXJJREwsIGxvbkFkanVzdGVkKTsKICAgICAgICB9CiAgICAgICAgaWYgKGVhc3QgLSB3ZXN0ID4gZWFzdE92ZXJJREwgLSB3ZXN0T3ZlcklETCkgewogICAgICAgICAgd2VzdCA9IHdlc3RPdmVySURMOwogICAgICAgICAgZWFzdCA9IGVhc3RPdmVySURMOwogICAgICAgICAgaWYgKGVhc3QgPiBNYXRoX2RlZmF1bHQuUEkpIHsKICAgICAgICAgICAgZWFzdCA9IGVhc3QgLSBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHdlc3QgPiBNYXRoX2RlZmF1bHQuUEkpIHsKICAgICAgICAgICAgd2VzdCA9IHdlc3QgLSBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFJlY3RhbmdsZSh3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQud2VzdCA9IHdlc3Q7CiAgICAgICAgcmVzdWx0LnNvdXRoID0gc291dGg7CiAgICAgICAgcmVzdWx0LmVhc3QgPSBlYXN0OwogICAgICAgIHJlc3VsdC5ub3J0aCA9IG5vcnRoOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIGZyb21Cb3VuZGluZ1NwaGVyZU1hdHJpeFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZyb21Cb3VuZGluZ1NwaGVyZUVhc3RTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBmcm9tQm91bmRpbmdTcGhlcmVOb3J0aFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZyb21Cb3VuZGluZ1NwaGVyZVdlc3RTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBmcm9tQm91bmRpbmdTcGhlcmVTb3V0aFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZyb21Cb3VuZGluZ1NwaGVyZVBvc2l0aW9uc1NjcmF0Y2ggPSBuZXcgQXJyYXkoNSk7CiAgICAgIGZvciAobGV0IG4gPSAwOyBuIDwgZnJvbUJvdW5kaW5nU3BoZXJlUG9zaXRpb25zU2NyYXRjaC5sZW5ndGg7ICsrbikgewogICAgICAgIGZyb21Cb3VuZGluZ1NwaGVyZVBvc2l0aW9uc1NjcmF0Y2hbbl0gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIH0KICAgICAgUmVjdGFuZ2xlLmZyb21Cb3VuZGluZ1NwaGVyZSA9IGZ1bmN0aW9uKGJvdW5kaW5nU3BoZXJlLCBlbGxpcHNvaWQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiYm91bmRpbmdTcGhlcmUiLCBib3VuZGluZ1NwaGVyZSk7CiAgICAgICAgY29uc3QgY2VudGVyID0gYm91bmRpbmdTcGhlcmUuY2VudGVyOwogICAgICAgIGNvbnN0IHJhZGl1cyA9IGJvdW5kaW5nU3BoZXJlLnJhZGl1czsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChlbGxpcHNvaWQpKSB7CiAgICAgICAgICBlbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgUmVjdGFuZ2xlKCk7CiAgICAgICAgfQogICAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzKGNlbnRlciwgQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8pKSB7CiAgICAgICAgICBSZWN0YW5nbGUuY2xvbmUoUmVjdGFuZ2xlLk1BWF9WQUxVRSwgcmVzdWx0KTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGZyb21FTlUgPSBUcmFuc2Zvcm1zX2RlZmF1bHQuZWFzdE5vcnRoVXBUb0ZpeGVkRnJhbWUoCiAgICAgICAgICBjZW50ZXIsCiAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICBmcm9tQm91bmRpbmdTcGhlcmVNYXRyaXhTY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBjb25zdCBlYXN0ID0gTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5QnlQb2ludEFzVmVjdG9yKAogICAgICAgICAgZnJvbUVOVSwKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1gsCiAgICAgICAgICBmcm9tQm91bmRpbmdTcGhlcmVFYXN0U2NyYXRjaAogICAgICAgICk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShlYXN0LCBlYXN0KTsKICAgICAgICBjb25zdCBub3J0aCA9IE1hdHJpeDRfZGVmYXVsdC5tdWx0aXBseUJ5UG9pbnRBc1ZlY3RvcigKICAgICAgICAgIGZyb21FTlUsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9ZLAogICAgICAgICAgZnJvbUJvdW5kaW5nU3BoZXJlTm9ydGhTY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKG5vcnRoLCBub3J0aCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobm9ydGgsIHJhZGl1cywgbm9ydGgpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGVhc3QsIHJhZGl1cywgZWFzdCk7CiAgICAgICAgY29uc3Qgc291dGggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKG5vcnRoLCBmcm9tQm91bmRpbmdTcGhlcmVTb3V0aFNjcmF0Y2gpOwogICAgICAgIGNvbnN0IHdlc3QgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKGVhc3QsIGZyb21Cb3VuZGluZ1NwaGVyZVdlc3RTY3JhdGNoKTsKICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBmcm9tQm91bmRpbmdTcGhlcmVQb3NpdGlvbnNTY3JhdGNoOwogICAgICAgIGxldCBjb3JuZXIgPSBwb3NpdGlvbnNbMF07CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChjZW50ZXIsIG5vcnRoLCBjb3JuZXIpOwogICAgICAgIGNvcm5lciA9IHBvc2l0aW9uc1sxXTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNlbnRlciwgd2VzdCwgY29ybmVyKTsKICAgICAgICBjb3JuZXIgPSBwb3NpdGlvbnNbMl07CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChjZW50ZXIsIHNvdXRoLCBjb3JuZXIpOwogICAgICAgIGNvcm5lciA9IHBvc2l0aW9uc1szXTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNlbnRlciwgZWFzdCwgY29ybmVyKTsKICAgICAgICBwb3NpdGlvbnNbNF0gPSBjZW50ZXI7CiAgICAgICAgcmV0dXJuIFJlY3RhbmdsZS5mcm9tQ2FydGVzaWFuQXJyYXkocG9zaXRpb25zLCBlbGxpcHNvaWQsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIFJlY3RhbmdsZS5jbG9uZSA9IGZ1bmN0aW9uKHJlY3RhbmdsZSwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVjdGFuZ2xlKSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBSZWN0YW5nbGUoCiAgICAgICAgICAgIHJlY3RhbmdsZS53ZXN0LAogICAgICAgICAgICByZWN0YW5nbGUuc291dGgsCiAgICAgICAgICAgIHJlY3RhbmdsZS5lYXN0LAogICAgICAgICAgICByZWN0YW5nbGUubm9ydGgKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC53ZXN0ID0gcmVjdGFuZ2xlLndlc3Q7CiAgICAgICAgcmVzdWx0LnNvdXRoID0gcmVjdGFuZ2xlLnNvdXRoOwogICAgICAgIHJlc3VsdC5lYXN0ID0gcmVjdGFuZ2xlLmVhc3Q7CiAgICAgICAgcmVzdWx0Lm5vcnRoID0gcmVjdGFuZ2xlLm5vcnRoOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFJlY3RhbmdsZS5lcXVhbHNFcHNpbG9uID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIGFic29sdXRlRXBzaWxvbikgewogICAgICAgIGFic29sdXRlRXBzaWxvbiA9IGFic29sdXRlRXBzaWxvbiA/PyAwOwogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiBNYXRoLmFicyhsZWZ0Lndlc3QgLSByaWdodC53ZXN0KSA8PSBhYnNvbHV0ZUVwc2lsb24gJiYgTWF0aC5hYnMobGVmdC5zb3V0aCAtIHJpZ2h0LnNvdXRoKSA8PSBhYnNvbHV0ZUVwc2lsb24gJiYgTWF0aC5hYnMobGVmdC5lYXN0IC0gcmlnaHQuZWFzdCkgPD0gYWJzb2x1dGVFcHNpbG9uICYmIE1hdGguYWJzKGxlZnQubm9ydGggLSByaWdodC5ub3J0aCkgPD0gYWJzb2x1dGVFcHNpbG9uOwogICAgICB9OwogICAgICBSZWN0YW5nbGUucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgcmV0dXJuIFJlY3RhbmdsZS5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBSZWN0YW5nbGUucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uKG90aGVyKSB7CiAgICAgICAgcmV0dXJuIFJlY3RhbmdsZS5lcXVhbHModGhpcywgb3RoZXIpOwogICAgICB9OwogICAgICBSZWN0YW5nbGUuZXF1YWxzID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHsKICAgICAgICByZXR1cm4gbGVmdCA9PT0gcmlnaHQgfHwgZGVmaW5lZF9kZWZhdWx0KGxlZnQpICYmIGRlZmluZWRfZGVmYXVsdChyaWdodCkgJiYgbGVmdC53ZXN0ID09PSByaWdodC53ZXN0ICYmIGxlZnQuc291dGggPT09IHJpZ2h0LnNvdXRoICYmIGxlZnQuZWFzdCA9PT0gcmlnaHQuZWFzdCAmJiBsZWZ0Lm5vcnRoID09PSByaWdodC5ub3J0aDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLnByb3RvdHlwZS5lcXVhbHNFcHNpbG9uID0gZnVuY3Rpb24ob3RoZXIsIGVwc2lsb24pIHsKICAgICAgICByZXR1cm4gUmVjdGFuZ2xlLmVxdWFsc0Vwc2lsb24odGhpcywgb3RoZXIsIGVwc2lsb24pOwogICAgICB9OwogICAgICBSZWN0YW5nbGUuX3ZhbGlkYXRlID0gZnVuY3Rpb24ocmVjdGFuZ2xlKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZWN0YW5nbGUiLCByZWN0YW5nbGUpOwogICAgICAgIGNvbnN0IG5vcnRoID0gcmVjdGFuZ2xlLm5vcnRoOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKAogICAgICAgICAgIm5vcnRoIiwKICAgICAgICAgIG5vcnRoLAogICAgICAgICAgLU1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTwogICAgICAgICk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoIm5vcnRoIiwgbm9ydGgsIE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyk7CiAgICAgICAgY29uc3Qgc291dGggPSByZWN0YW5nbGUuc291dGg7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoCiAgICAgICAgICAic291dGgiLAogICAgICAgICAgc291dGgsCiAgICAgICAgICAtTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPCiAgICAgICAgKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygic291dGgiLCBzb3V0aCwgTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPKTsKICAgICAgICBjb25zdCB3ZXN0ID0gcmVjdGFuZ2xlLndlc3Q7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoIndlc3QiLCB3ZXN0LCAtTWF0aC5QSSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoIndlc3QiLCB3ZXN0LCBNYXRoLlBJKTsKICAgICAgICBjb25zdCBlYXN0ID0gcmVjdGFuZ2xlLmVhc3Q7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoImVhc3QiLCBlYXN0LCAtTWF0aC5QSSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoImVhc3QiLCBlYXN0LCBNYXRoLlBJKTsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLnNvdXRod2VzdCA9IGZ1bmN0aW9uKHJlY3RhbmdsZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZWN0YW5nbGUiLCByZWN0YW5nbGUpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQocmVjdGFuZ2xlLndlc3QsIHJlY3RhbmdsZS5zb3V0aCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5sb25naXR1ZGUgPSByZWN0YW5nbGUud2VzdDsKICAgICAgICByZXN1bHQubGF0aXR1ZGUgPSByZWN0YW5nbGUuc291dGg7CiAgICAgICAgcmVzdWx0LmhlaWdodCA9IDA7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLm5vcnRod2VzdCA9IGZ1bmN0aW9uKHJlY3RhbmdsZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZWN0YW5nbGUiLCByZWN0YW5nbGUpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQocmVjdGFuZ2xlLndlc3QsIHJlY3RhbmdsZS5ub3J0aCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5sb25naXR1ZGUgPSByZWN0YW5nbGUud2VzdDsKICAgICAgICByZXN1bHQubGF0aXR1ZGUgPSByZWN0YW5nbGUubm9ydGg7CiAgICAgICAgcmVzdWx0LmhlaWdodCA9IDA7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLm5vcnRoZWFzdCA9IGZ1bmN0aW9uKHJlY3RhbmdsZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZWN0YW5nbGUiLCByZWN0YW5nbGUpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQocmVjdGFuZ2xlLmVhc3QsIHJlY3RhbmdsZS5ub3J0aCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5sb25naXR1ZGUgPSByZWN0YW5nbGUuZWFzdDsKICAgICAgICByZXN1bHQubGF0aXR1ZGUgPSByZWN0YW5nbGUubm9ydGg7CiAgICAgICAgcmVzdWx0LmhlaWdodCA9IDA7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLnNvdXRoZWFzdCA9IGZ1bmN0aW9uKHJlY3RhbmdsZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZWN0YW5nbGUiLCByZWN0YW5nbGUpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQocmVjdGFuZ2xlLmVhc3QsIHJlY3RhbmdsZS5zb3V0aCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5sb25naXR1ZGUgPSByZWN0YW5nbGUuZWFzdDsKICAgICAgICByZXN1bHQubGF0aXR1ZGUgPSByZWN0YW5nbGUuc291dGg7CiAgICAgICAgcmVzdWx0LmhlaWdodCA9IDA7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLmNlbnRlciA9IGZ1bmN0aW9uKHJlY3RhbmdsZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZWN0YW5nbGUiLCByZWN0YW5nbGUpOwogICAgICAgIGxldCBlYXN0ID0gcmVjdGFuZ2xlLmVhc3Q7CiAgICAgICAgY29uc3Qgd2VzdCA9IHJlY3RhbmdsZS53ZXN0OwogICAgICAgIGlmIChlYXN0IDwgd2VzdCkgewogICAgICAgICAgZWFzdCArPSBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgICAgIH0KICAgICAgICBjb25zdCBsb25naXR1ZGUgPSBNYXRoX2RlZmF1bHQubmVnYXRpdmVQaVRvUGkoKHdlc3QgKyBlYXN0KSAqIDAuNSk7CiAgICAgICAgY29uc3QgbGF0aXR1ZGUgPSAocmVjdGFuZ2xlLnNvdXRoICsgcmVjdGFuZ2xlLm5vcnRoKSAqIDAuNTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KGxvbmdpdHVkZSwgbGF0aXR1ZGUpOwogICAgICAgIH0KICAgICAgICByZXN1bHQubG9uZ2l0dWRlID0gbG9uZ2l0dWRlOwogICAgICAgIHJlc3VsdC5sYXRpdHVkZSA9IGxhdGl0dWRlOwogICAgICAgIHJlc3VsdC5oZWlnaHQgPSAwOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFJlY3RhbmdsZS5pbnRlcnNlY3Rpb24gPSBmdW5jdGlvbihyZWN0YW5nbGUsIG90aGVyUmVjdGFuZ2xlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlY3RhbmdsZSIsIHJlY3RhbmdsZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJvdGhlclJlY3RhbmdsZSIsIG90aGVyUmVjdGFuZ2xlKTsKICAgICAgICBsZXQgcmVjdGFuZ2xlRWFzdCA9IHJlY3RhbmdsZS5lYXN0OwogICAgICAgIGxldCByZWN0YW5nbGVXZXN0ID0gcmVjdGFuZ2xlLndlc3Q7CiAgICAgICAgbGV0IG90aGVyUmVjdGFuZ2xlRWFzdCA9IG90aGVyUmVjdGFuZ2xlLmVhc3Q7CiAgICAgICAgbGV0IG90aGVyUmVjdGFuZ2xlV2VzdCA9IG90aGVyUmVjdGFuZ2xlLndlc3Q7CiAgICAgICAgaWYgKHJlY3RhbmdsZUVhc3QgPCByZWN0YW5nbGVXZXN0ICYmIG90aGVyUmVjdGFuZ2xlRWFzdCA+IDApIHsKICAgICAgICAgIHJlY3RhbmdsZUVhc3QgKz0gTWF0aF9kZWZhdWx0LlRXT19QSTsKICAgICAgICB9IGVsc2UgaWYgKG90aGVyUmVjdGFuZ2xlRWFzdCA8IG90aGVyUmVjdGFuZ2xlV2VzdCAmJiByZWN0YW5nbGVFYXN0ID4gMCkgewogICAgICAgICAgb3RoZXJSZWN0YW5nbGVFYXN0ICs9IE1hdGhfZGVmYXVsdC5UV09fUEk7CiAgICAgICAgfQogICAgICAgIGlmIChyZWN0YW5nbGVFYXN0IDwgcmVjdGFuZ2xlV2VzdCAmJiBvdGhlclJlY3RhbmdsZVdlc3QgPCAwKSB7CiAgICAgICAgICBvdGhlclJlY3RhbmdsZVdlc3QgKz0gTWF0aF9kZWZhdWx0LlRXT19QSTsKICAgICAgICB9IGVsc2UgaWYgKG90aGVyUmVjdGFuZ2xlRWFzdCA8IG90aGVyUmVjdGFuZ2xlV2VzdCAmJiByZWN0YW5nbGVXZXN0IDwgMCkgewogICAgICAgICAgcmVjdGFuZ2xlV2VzdCArPSBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgICAgIH0KICAgICAgICBjb25zdCB3ZXN0ID0gTWF0aF9kZWZhdWx0Lm5lZ2F0aXZlUGlUb1BpKAogICAgICAgICAgTWF0aC5tYXgocmVjdGFuZ2xlV2VzdCwgb3RoZXJSZWN0YW5nbGVXZXN0KQogICAgICAgICk7CiAgICAgICAgY29uc3QgZWFzdCA9IE1hdGhfZGVmYXVsdC5uZWdhdGl2ZVBpVG9QaSgKICAgICAgICAgIE1hdGgubWluKHJlY3RhbmdsZUVhc3QsIG90aGVyUmVjdGFuZ2xlRWFzdCkKICAgICAgICApOwogICAgICAgIGlmICgocmVjdGFuZ2xlLndlc3QgPCByZWN0YW5nbGUuZWFzdCB8fCBvdGhlclJlY3RhbmdsZS53ZXN0IDwgb3RoZXJSZWN0YW5nbGUuZWFzdCkgJiYgZWFzdCA8PSB3ZXN0KSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBjb25zdCBzb3V0aCA9IE1hdGgubWF4KHJlY3RhbmdsZS5zb3V0aCwgb3RoZXJSZWN0YW5nbGUuc291dGgpOwogICAgICAgIGNvbnN0IG5vcnRoID0gTWF0aC5taW4ocmVjdGFuZ2xlLm5vcnRoLCBvdGhlclJlY3RhbmdsZS5ub3J0aCk7CiAgICAgICAgaWYgKHNvdXRoID49IG5vcnRoKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFJlY3RhbmdsZSh3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQud2VzdCA9IHdlc3Q7CiAgICAgICAgcmVzdWx0LnNvdXRoID0gc291dGg7CiAgICAgICAgcmVzdWx0LmVhc3QgPSBlYXN0OwogICAgICAgIHJlc3VsdC5ub3J0aCA9IG5vcnRoOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFJlY3RhbmdsZS5zaW1wbGVJbnRlcnNlY3Rpb24gPSBmdW5jdGlvbihyZWN0YW5nbGUsIG90aGVyUmVjdGFuZ2xlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlY3RhbmdsZSIsIHJlY3RhbmdsZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJvdGhlclJlY3RhbmdsZSIsIG90aGVyUmVjdGFuZ2xlKTsKICAgICAgICBjb25zdCB3ZXN0ID0gTWF0aC5tYXgocmVjdGFuZ2xlLndlc3QsIG90aGVyUmVjdGFuZ2xlLndlc3QpOwogICAgICAgIGNvbnN0IHNvdXRoID0gTWF0aC5tYXgocmVjdGFuZ2xlLnNvdXRoLCBvdGhlclJlY3RhbmdsZS5zb3V0aCk7CiAgICAgICAgY29uc3QgZWFzdCA9IE1hdGgubWluKHJlY3RhbmdsZS5lYXN0LCBvdGhlclJlY3RhbmdsZS5lYXN0KTsKICAgICAgICBjb25zdCBub3J0aCA9IE1hdGgubWluKHJlY3RhbmdsZS5ub3J0aCwgb3RoZXJSZWN0YW5nbGUubm9ydGgpOwogICAgICAgIGlmIChzb3V0aCA+PSBub3J0aCB8fCB3ZXN0ID49IGVhc3QpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgUmVjdGFuZ2xlKHdlc3QsIHNvdXRoLCBlYXN0LCBub3J0aCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC53ZXN0ID0gd2VzdDsKICAgICAgICByZXN1bHQuc291dGggPSBzb3V0aDsKICAgICAgICByZXN1bHQuZWFzdCA9IGVhc3Q7CiAgICAgICAgcmVzdWx0Lm5vcnRoID0gbm9ydGg7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLnVuaW9uID0gZnVuY3Rpb24ocmVjdGFuZ2xlLCBvdGhlclJlY3RhbmdsZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZWN0YW5nbGUiLCByZWN0YW5nbGUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgib3RoZXJSZWN0YW5nbGUiLCBvdGhlclJlY3RhbmdsZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IFJlY3RhbmdsZSgpOwogICAgICAgIH0KICAgICAgICBsZXQgcmVjdGFuZ2xlRWFzdCA9IHJlY3RhbmdsZS5lYXN0OwogICAgICAgIGxldCByZWN0YW5nbGVXZXN0ID0gcmVjdGFuZ2xlLndlc3Q7CiAgICAgICAgbGV0IG90aGVyUmVjdGFuZ2xlRWFzdCA9IG90aGVyUmVjdGFuZ2xlLmVhc3Q7CiAgICAgICAgbGV0IG90aGVyUmVjdGFuZ2xlV2VzdCA9IG90aGVyUmVjdGFuZ2xlLndlc3Q7CiAgICAgICAgaWYgKHJlY3RhbmdsZUVhc3QgPCByZWN0YW5nbGVXZXN0ICYmIG90aGVyUmVjdGFuZ2xlRWFzdCA+IDApIHsKICAgICAgICAgIHJlY3RhbmdsZUVhc3QgKz0gTWF0aF9kZWZhdWx0LlRXT19QSTsKICAgICAgICB9IGVsc2UgaWYgKG90aGVyUmVjdGFuZ2xlRWFzdCA8IG90aGVyUmVjdGFuZ2xlV2VzdCAmJiByZWN0YW5nbGVFYXN0ID4gMCkgewogICAgICAgICAgb3RoZXJSZWN0YW5nbGVFYXN0ICs9IE1hdGhfZGVmYXVsdC5UV09fUEk7CiAgICAgICAgfQogICAgICAgIGlmIChyZWN0YW5nbGVFYXN0IDwgcmVjdGFuZ2xlV2VzdCAmJiBvdGhlclJlY3RhbmdsZVdlc3QgPCAwKSB7CiAgICAgICAgICBvdGhlclJlY3RhbmdsZVdlc3QgKz0gTWF0aF9kZWZhdWx0LlRXT19QSTsKICAgICAgICB9IGVsc2UgaWYgKG90aGVyUmVjdGFuZ2xlRWFzdCA8IG90aGVyUmVjdGFuZ2xlV2VzdCAmJiByZWN0YW5nbGVXZXN0IDwgMCkgewogICAgICAgICAgcmVjdGFuZ2xlV2VzdCArPSBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgICAgIH0KICAgICAgICBjb25zdCB3ZXN0ID0gTWF0aF9kZWZhdWx0Lm5lZ2F0aXZlUGlUb1BpKAogICAgICAgICAgTWF0aC5taW4ocmVjdGFuZ2xlV2VzdCwgb3RoZXJSZWN0YW5nbGVXZXN0KQogICAgICAgICk7CiAgICAgICAgY29uc3QgZWFzdCA9IE1hdGhfZGVmYXVsdC5uZWdhdGl2ZVBpVG9QaSgKICAgICAgICAgIE1hdGgubWF4KHJlY3RhbmdsZUVhc3QsIG90aGVyUmVjdGFuZ2xlRWFzdCkKICAgICAgICApOwogICAgICAgIHJlc3VsdC53ZXN0ID0gd2VzdDsKICAgICAgICByZXN1bHQuc291dGggPSBNYXRoLm1pbihyZWN0YW5nbGUuc291dGgsIG90aGVyUmVjdGFuZ2xlLnNvdXRoKTsKICAgICAgICByZXN1bHQuZWFzdCA9IGVhc3Q7CiAgICAgICAgcmVzdWx0Lm5vcnRoID0gTWF0aC5tYXgocmVjdGFuZ2xlLm5vcnRoLCBvdGhlclJlY3RhbmdsZS5ub3J0aCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLmV4cGFuZCA9IGZ1bmN0aW9uKHJlY3RhbmdsZSwgY2FydG9ncmFwaGljMiwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZWN0YW5nbGUiLCByZWN0YW5nbGUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydG9ncmFwaGljIiwgY2FydG9ncmFwaGljMik7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IFJlY3RhbmdsZSgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQud2VzdCA9IE1hdGgubWluKHJlY3RhbmdsZS53ZXN0LCBjYXJ0b2dyYXBoaWMyLmxvbmdpdHVkZSk7CiAgICAgICAgcmVzdWx0LnNvdXRoID0gTWF0aC5taW4ocmVjdGFuZ2xlLnNvdXRoLCBjYXJ0b2dyYXBoaWMyLmxhdGl0dWRlKTsKICAgICAgICByZXN1bHQuZWFzdCA9IE1hdGgubWF4KHJlY3RhbmdsZS5lYXN0LCBjYXJ0b2dyYXBoaWMyLmxvbmdpdHVkZSk7CiAgICAgICAgcmVzdWx0Lm5vcnRoID0gTWF0aC5tYXgocmVjdGFuZ2xlLm5vcnRoLCBjYXJ0b2dyYXBoaWMyLmxhdGl0dWRlKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBSZWN0YW5nbGUuY29udGFpbnMgPSBmdW5jdGlvbihyZWN0YW5nbGUsIGNhcnRvZ3JhcGhpYzIpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlY3RhbmdsZSIsIHJlY3RhbmdsZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0b2dyYXBoaWMiLCBjYXJ0b2dyYXBoaWMyKTsKICAgICAgICBsZXQgbG9uZ2l0dWRlID0gY2FydG9ncmFwaGljMi5sb25naXR1ZGU7CiAgICAgICAgY29uc3QgbGF0aXR1ZGUgPSBjYXJ0b2dyYXBoaWMyLmxhdGl0dWRlOwogICAgICAgIGNvbnN0IHdlc3QgPSByZWN0YW5nbGUud2VzdDsKICAgICAgICBsZXQgZWFzdCA9IHJlY3RhbmdsZS5lYXN0OwogICAgICAgIGlmIChlYXN0IDwgd2VzdCkgewogICAgICAgICAgZWFzdCArPSBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgICAgICAgaWYgKGxvbmdpdHVkZSA8IDApIHsKICAgICAgICAgICAgbG9uZ2l0dWRlICs9IE1hdGhfZGVmYXVsdC5UV09fUEk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiAobG9uZ2l0dWRlID4gd2VzdCB8fCBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihsb25naXR1ZGUsIHdlc3QsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTQpKSAmJiAobG9uZ2l0dWRlIDwgZWFzdCB8fCBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihsb25naXR1ZGUsIGVhc3QsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTQpKSAmJiBsYXRpdHVkZSA+PSByZWN0YW5nbGUuc291dGggJiYgbGF0aXR1ZGUgPD0gcmVjdGFuZ2xlLm5vcnRoOwogICAgICB9OwogICAgICBzdWJzYW1wbGVMbGFTY3JhdGNoID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIFJlY3RhbmdsZS5zdWJzYW1wbGUgPSBmdW5jdGlvbihyZWN0YW5nbGUsIGVsbGlwc29pZCwgc3VyZmFjZUhlaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZWN0YW5nbGUiLCByZWN0YW5nbGUpOwogICAgICAgIGVsbGlwc29pZCA9IGVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgICAgIHN1cmZhY2VIZWlnaHQgPSBzdXJmYWNlSGVpZ2h0ID8/IDA7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gW107CiAgICAgICAgfQogICAgICAgIGxldCBsZW5ndGggPSAwOwogICAgICAgIGNvbnN0IG5vcnRoID0gcmVjdGFuZ2xlLm5vcnRoOwogICAgICAgIGNvbnN0IHNvdXRoID0gcmVjdGFuZ2xlLnNvdXRoOwogICAgICAgIGNvbnN0IGVhc3QgPSByZWN0YW5nbGUuZWFzdDsKICAgICAgICBjb25zdCB3ZXN0ID0gcmVjdGFuZ2xlLndlc3Q7CiAgICAgICAgY29uc3QgbGxhID0gc3Vic2FtcGxlTGxhU2NyYXRjaDsKICAgICAgICBsbGEuaGVpZ2h0ID0gc3VyZmFjZUhlaWdodDsKICAgICAgICBsbGEubG9uZ2l0dWRlID0gd2VzdDsKICAgICAgICBsbGEubGF0aXR1ZGUgPSBub3J0aDsKICAgICAgICByZXN1bHRbbGVuZ3RoXSA9IGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbihsbGEsIHJlc3VsdFtsZW5ndGhdKTsKICAgICAgICBsZW5ndGgrKzsKICAgICAgICBsbGEubG9uZ2l0dWRlID0gZWFzdDsKICAgICAgICByZXN1bHRbbGVuZ3RoXSA9IGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbihsbGEsIHJlc3VsdFtsZW5ndGhdKTsKICAgICAgICBsZW5ndGgrKzsKICAgICAgICBsbGEubGF0aXR1ZGUgPSBzb3V0aDsKICAgICAgICByZXN1bHRbbGVuZ3RoXSA9IGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbihsbGEsIHJlc3VsdFtsZW5ndGhdKTsKICAgICAgICBsZW5ndGgrKzsKICAgICAgICBsbGEubG9uZ2l0dWRlID0gd2VzdDsKICAgICAgICByZXN1bHRbbGVuZ3RoXSA9IGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbihsbGEsIHJlc3VsdFtsZW5ndGhdKTsKICAgICAgICBsZW5ndGgrKzsKICAgICAgICBpZiAobm9ydGggPCAwKSB7CiAgICAgICAgICBsbGEubGF0aXR1ZGUgPSBub3J0aDsKICAgICAgICB9IGVsc2UgaWYgKHNvdXRoID4gMCkgewogICAgICAgICAgbGxhLmxhdGl0dWRlID0gc291dGg7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGxsYS5sYXRpdHVkZSA9IDA7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgODsgKytpKSB7CiAgICAgICAgICBsbGEubG9uZ2l0dWRlID0gLU1hdGguUEkgKyBpICogTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPOwogICAgICAgICAgaWYgKFJlY3RhbmdsZS5jb250YWlucyhyZWN0YW5nbGUsIGxsYSkpIHsKICAgICAgICAgICAgcmVzdWx0W2xlbmd0aF0gPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4obGxhLCByZXN1bHRbbGVuZ3RoXSk7CiAgICAgICAgICAgIGxlbmd0aCsrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAobGxhLmxhdGl0dWRlID09PSAwKSB7CiAgICAgICAgICBsbGEubG9uZ2l0dWRlID0gd2VzdDsKICAgICAgICAgIHJlc3VsdFtsZW5ndGhdID0gZWxsaXBzb2lkLmNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuKGxsYSwgcmVzdWx0W2xlbmd0aF0pOwogICAgICAgICAgbGVuZ3RoKys7CiAgICAgICAgICBsbGEubG9uZ2l0dWRlID0gZWFzdDsKICAgICAgICAgIHJlc3VsdFtsZW5ndGhdID0gZWxsaXBzb2lkLmNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuKGxsYSwgcmVzdWx0W2xlbmd0aF0pOwogICAgICAgICAgbGVuZ3RoKys7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5sZW5ndGggPSBsZW5ndGg7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLnN1YnNlY3Rpb24gPSBmdW5jdGlvbihyZWN0YW5nbGUsIHdlc3RMZXJwLCBzb3V0aExlcnAsIGVhc3RMZXJwLCBub3J0aExlcnAsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVjdGFuZ2xlIiwgcmVjdGFuZ2xlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygid2VzdExlcnAiLCB3ZXN0TGVycCwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoIndlc3RMZXJwIiwgd2VzdExlcnAsIDEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJzb3V0aExlcnAiLCBzb3V0aExlcnAsIDApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5sZXNzVGhhbk9yRXF1YWxzKCJzb3V0aExlcnAiLCBzb3V0aExlcnAsIDEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJlYXN0TGVycCIsIGVhc3RMZXJwLCAwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygiZWFzdExlcnAiLCBlYXN0TGVycCwgMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoIm5vcnRoTGVycCIsIG5vcnRoTGVycCwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoIm5vcnRoTGVycCIsIG5vcnRoTGVycCwgMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoIndlc3RMZXJwIiwgd2VzdExlcnAsIGVhc3RMZXJwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygic291dGhMZXJwIiwgc291dGhMZXJwLCBub3J0aExlcnApOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBSZWN0YW5nbGUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKHJlY3RhbmdsZS53ZXN0IDw9IHJlY3RhbmdsZS5lYXN0KSB7CiAgICAgICAgICBjb25zdCB3aWR0aCA9IHJlY3RhbmdsZS5lYXN0IC0gcmVjdGFuZ2xlLndlc3Q7CiAgICAgICAgICByZXN1bHQud2VzdCA9IHJlY3RhbmdsZS53ZXN0ICsgd2VzdExlcnAgKiB3aWR0aDsKICAgICAgICAgIHJlc3VsdC5lYXN0ID0gcmVjdGFuZ2xlLndlc3QgKyBlYXN0TGVycCAqIHdpZHRoOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb25zdCB3aWR0aCA9IE1hdGhfZGVmYXVsdC5UV09fUEkgKyByZWN0YW5nbGUuZWFzdCAtIHJlY3RhbmdsZS53ZXN0OwogICAgICAgICAgcmVzdWx0Lndlc3QgPSBNYXRoX2RlZmF1bHQubmVnYXRpdmVQaVRvUGkocmVjdGFuZ2xlLndlc3QgKyB3ZXN0TGVycCAqIHdpZHRoKTsKICAgICAgICAgIHJlc3VsdC5lYXN0ID0gTWF0aF9kZWZhdWx0Lm5lZ2F0aXZlUGlUb1BpKHJlY3RhbmdsZS53ZXN0ICsgZWFzdExlcnAgKiB3aWR0aCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGhlaWdodCA9IHJlY3RhbmdsZS5ub3J0aCAtIHJlY3RhbmdsZS5zb3V0aDsKICAgICAgICByZXN1bHQuc291dGggPSByZWN0YW5nbGUuc291dGggKyBzb3V0aExlcnAgKiBoZWlnaHQ7CiAgICAgICAgcmVzdWx0Lm5vcnRoID0gcmVjdGFuZ2xlLnNvdXRoICsgbm9ydGhMZXJwICogaGVpZ2h0OwogICAgICAgIGlmICh3ZXN0TGVycCA9PT0gMSkgewogICAgICAgICAgcmVzdWx0Lndlc3QgPSByZWN0YW5nbGUuZWFzdDsKICAgICAgICB9CiAgICAgICAgaWYgKGVhc3RMZXJwID09PSAxKSB7CiAgICAgICAgICByZXN1bHQuZWFzdCA9IHJlY3RhbmdsZS5lYXN0OwogICAgICAgIH0KICAgICAgICBpZiAoc291dGhMZXJwID09PSAxKSB7CiAgICAgICAgICByZXN1bHQuc291dGggPSByZWN0YW5nbGUubm9ydGg7CiAgICAgICAgfQogICAgICAgIGlmIChub3J0aExlcnAgPT09IDEpIHsKICAgICAgICAgIHJlc3VsdC5ub3J0aCA9IHJlY3RhbmdsZS5ub3J0aDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlLk1BWF9WQUxVRSA9IE9iamVjdC5mcmVlemUoCiAgICAgICAgbmV3IFJlY3RhbmdsZSgKICAgICAgICAgIC1NYXRoLlBJLAogICAgICAgICAgLU1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTywKICAgICAgICAgIE1hdGguUEksCiAgICAgICAgICBNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08KICAgICAgICApCiAgICAgICk7CiAgICAgIFJlY3RhbmdsZV9kZWZhdWx0ID0gUmVjdGFuZ2xlOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQm91bmRpbmdTcGhlcmUuanMKICBmdW5jdGlvbiBCb3VuZGluZ1NwaGVyZShjZW50ZXIsIHJhZGl1cykgewogICAgdGhpcy5jZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY2VudGVyID8/IENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPKTsKICAgIHRoaXMucmFkaXVzID0gcmFkaXVzID8/IDA7CiAgfQogIHZhciBmcm9tUG9pbnRzWE1pbiwgZnJvbVBvaW50c1lNaW4sIGZyb21Qb2ludHNaTWluLCBmcm9tUG9pbnRzWE1heCwgZnJvbVBvaW50c1lNYXgsIGZyb21Qb2ludHNaTWF4LCBmcm9tUG9pbnRzQ3VycmVudFBvcywgZnJvbVBvaW50c1NjcmF0Y2gsIGZyb21Qb2ludHNSaXR0ZXJDZW50ZXIsIGZyb21Qb2ludHNNaW5Cb3hQdCwgZnJvbVBvaW50c01heEJveFB0LCBmcm9tUG9pbnRzTmFpdmVDZW50ZXJTY3JhdGNoLCB2b2x1bWVDb25zdGFudCwgZGVmYXVsdFByb2plY3Rpb24sIGZyb21SZWN0YW5nbGUyRExvd2VyTGVmdCwgZnJvbVJlY3RhbmdsZTJEVXBwZXJSaWdodCwgZnJvbVJlY3RhbmdsZTJEU291dGh3ZXN0LCBmcm9tUmVjdGFuZ2xlMkROb3J0aGVhc3QsIGZyb21SZWN0YW5nbGUzRFNjcmF0Y2gsIGZyb21Cb3VuZGluZ1NwaGVyZXNTY3JhdGNoLCBmcm9tT3JpZW50ZWRCb3VuZGluZ0JveFNjcmF0Y2hVLCBmcm9tT3JpZW50ZWRCb3VuZGluZ0JveFNjcmF0Y2hWLCBmcm9tT3JpZW50ZWRCb3VuZGluZ0JveFNjcmF0Y2hXLCBzY3JhdGNoRnJvbVRyYW5zZm9ybWF0aW9uQ2VudGVyLCBzY3JhdGNoRnJvbVRyYW5zZm9ybWF0aW9uU2NhbGUsIHVuaW9uU2NyYXRjaCwgdW5pb25TY3JhdGNoQ2VudGVyLCBleHBhbmRTY3JhdGNoLCBkaXN0YW5jZVNxdWFyZWRUb1NjcmF0Y2gsIHNjcmF0Y2hDYXJ0ZXNpYW4zLCBwcm9qZWN0VG8yRE5vcm1hbFNjcmF0Y2gsIHByb2plY3RUbzJERWFzdFNjcmF0Y2gsIHByb2plY3RUbzJETm9ydGhTY3JhdGNoLCBwcm9qZWN0VG8yRFdlc3RTY3JhdGNoLCBwcm9qZWN0VG8yRFNvdXRoU2NyYXRjaCwgcHJvamVjdFRvMkRDYXJ0b2dyYXBoaWNTY3JhdGNoLCBwcm9qZWN0VG8yRFBvc2l0aW9uc1NjcmF0Y2gsIHByb2plY3RUbzJEUHJvamVjdGlvbiwgQm91bmRpbmdTcGhlcmVfZGVmYXVsdDsKICB2YXIgaW5pdF9Cb3VuZGluZ1NwaGVyZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQm91bmRpbmdTcGhlcmUuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DYXJ0b2dyYXBoaWMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9HZW9ncmFwaGljUHJvamVjdGlvbigpOwogICAgICBpbml0X0ludGVyc2VjdCgpOwogICAgICBpbml0X0ludGVydmFsKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X01hdHJpeDMoKTsKICAgICAgaW5pdF9NYXRyaXg0KCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIGZyb21Qb2ludHNYTWluID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBmcm9tUG9pbnRzWU1pbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZnJvbVBvaW50c1pNaW4gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZyb21Qb2ludHNYTWF4ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBmcm9tUG9pbnRzWU1heCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZnJvbVBvaW50c1pNYXggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZyb21Qb2ludHNDdXJyZW50UG9zID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBmcm9tUG9pbnRzU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZnJvbVBvaW50c1JpdHRlckNlbnRlciA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZnJvbVBvaW50c01pbkJveFB0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBmcm9tUG9pbnRzTWF4Qm94UHQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZyb21Qb2ludHNOYWl2ZUNlbnRlclNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHZvbHVtZUNvbnN0YW50ID0gNCAvIDMgKiBNYXRoX2RlZmF1bHQuUEk7CiAgICAgIEJvdW5kaW5nU3BoZXJlLmZyb21Qb2ludHMgPSBmdW5jdGlvbihwb3NpdGlvbnMsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBCb3VuZGluZ1NwaGVyZSgpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwb3NpdGlvbnMpIHx8IHBvc2l0aW9ucy5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHJlc3VsdC5jZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sIHJlc3VsdC5jZW50ZXIpOwogICAgICAgICAgcmVzdWx0LnJhZGl1cyA9IDA7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICBjb25zdCBjdXJyZW50UG9zID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHBvc2l0aW9uc1swXSwgZnJvbVBvaW50c0N1cnJlbnRQb3MpOwogICAgICAgIGNvbnN0IHhNaW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgZnJvbVBvaW50c1hNaW4pOwogICAgICAgIGNvbnN0IHlNaW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgZnJvbVBvaW50c1lNaW4pOwogICAgICAgIGNvbnN0IHpNaW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgZnJvbVBvaW50c1pNaW4pOwogICAgICAgIGNvbnN0IHhNYXggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgZnJvbVBvaW50c1hNYXgpOwogICAgICAgIGNvbnN0IHlNYXggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgZnJvbVBvaW50c1lNYXgpOwogICAgICAgIGNvbnN0IHpNYXggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgZnJvbVBvaW50c1pNYXgpOwogICAgICAgIGNvbnN0IG51bVBvc2l0aW9ucyA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgbGV0IGk7CiAgICAgICAgZm9yIChpID0gMTsgaSA8IG51bVBvc2l0aW9uczsgaSsrKSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocG9zaXRpb25zW2ldLCBjdXJyZW50UG9zKTsKICAgICAgICAgIGNvbnN0IHggPSBjdXJyZW50UG9zLng7CiAgICAgICAgICBjb25zdCB5ID0gY3VycmVudFBvcy55OwogICAgICAgICAgY29uc3QgeiA9IGN1cnJlbnRQb3MuejsKICAgICAgICAgIGlmICh4IDwgeE1pbi54KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB4TWluKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh4ID4geE1heC54KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB4TWF4KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh5IDwgeU1pbi55KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB5TWluKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh5ID4geU1heC55KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB5TWF4KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh6IDwgek1pbi56KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB6TWluKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh6ID4gek1heC56KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB6TWF4KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgeFNwYW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlU3F1YXJlZCgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCh4TWF4LCB4TWluLCBmcm9tUG9pbnRzU2NyYXRjaCkKICAgICAgICApOwogICAgICAgIGNvbnN0IHlTcGFuID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZVNxdWFyZWQoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoeU1heCwgeU1pbiwgZnJvbVBvaW50c1NjcmF0Y2gpCiAgICAgICAgKTsKICAgICAgICBjb25zdCB6U3BhbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGVTcXVhcmVkKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHpNYXgsIHpNaW4sIGZyb21Qb2ludHNTY3JhdGNoKQogICAgICAgICk7CiAgICAgICAgbGV0IGRpYW1ldGVyMSA9IHhNaW47CiAgICAgICAgbGV0IGRpYW1ldGVyMiA9IHhNYXg7CiAgICAgICAgbGV0IG1heFNwYW4gPSB4U3BhbjsKICAgICAgICBpZiAoeVNwYW4gPiBtYXhTcGFuKSB7CiAgICAgICAgICBtYXhTcGFuID0geVNwYW47CiAgICAgICAgICBkaWFtZXRlcjEgPSB5TWluOwogICAgICAgICAgZGlhbWV0ZXIyID0geU1heDsKICAgICAgICB9CiAgICAgICAgaWYgKHpTcGFuID4gbWF4U3BhbikgewogICAgICAgICAgbWF4U3BhbiA9IHpTcGFuOwogICAgICAgICAgZGlhbWV0ZXIxID0gek1pbjsKICAgICAgICAgIGRpYW1ldGVyMiA9IHpNYXg7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHJpdHRlckNlbnRlciA9IGZyb21Qb2ludHNSaXR0ZXJDZW50ZXI7CiAgICAgICAgcml0dGVyQ2VudGVyLnggPSAoZGlhbWV0ZXIxLnggKyBkaWFtZXRlcjIueCkgKiAwLjU7CiAgICAgICAgcml0dGVyQ2VudGVyLnkgPSAoZGlhbWV0ZXIxLnkgKyBkaWFtZXRlcjIueSkgKiAwLjU7CiAgICAgICAgcml0dGVyQ2VudGVyLnogPSAoZGlhbWV0ZXIxLnogKyBkaWFtZXRlcjIueikgKiAwLjU7CiAgICAgICAgbGV0IHJhZGl1c1NxdWFyZWQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlU3F1YXJlZCgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChkaWFtZXRlcjIsIHJpdHRlckNlbnRlciwgZnJvbVBvaW50c1NjcmF0Y2gpCiAgICAgICAgKTsKICAgICAgICBsZXQgcml0dGVyUmFkaXVzID0gTWF0aC5zcXJ0KHJhZGl1c1NxdWFyZWQpOwogICAgICAgIGNvbnN0IG1pbkJveFB0ID0gZnJvbVBvaW50c01pbkJveFB0OwogICAgICAgIG1pbkJveFB0LnggPSB4TWluLng7CiAgICAgICAgbWluQm94UHQueSA9IHlNaW4ueTsKICAgICAgICBtaW5Cb3hQdC56ID0gek1pbi56OwogICAgICAgIGNvbnN0IG1heEJveFB0ID0gZnJvbVBvaW50c01heEJveFB0OwogICAgICAgIG1heEJveFB0LnggPSB4TWF4Lng7CiAgICAgICAgbWF4Qm94UHQueSA9IHlNYXgueTsKICAgICAgICBtYXhCb3hQdC56ID0gek1heC56OwogICAgICAgIGNvbnN0IG5haXZlQ2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1pZHBvaW50KAogICAgICAgICAgbWluQm94UHQsCiAgICAgICAgICBtYXhCb3hQdCwKICAgICAgICAgIGZyb21Qb2ludHNOYWl2ZUNlbnRlclNjcmF0Y2gKICAgICAgICApOwogICAgICAgIGxldCBuYWl2ZVJhZGl1cyA9IDA7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IG51bVBvc2l0aW9uczsgaSsrKSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocG9zaXRpb25zW2ldLCBjdXJyZW50UG9zKTsKICAgICAgICAgIGNvbnN0IHIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKAogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoY3VycmVudFBvcywgbmFpdmVDZW50ZXIsIGZyb21Qb2ludHNTY3JhdGNoKQogICAgICAgICAgKTsKICAgICAgICAgIGlmIChyID4gbmFpdmVSYWRpdXMpIHsKICAgICAgICAgICAgbmFpdmVSYWRpdXMgPSByOwogICAgICAgICAgfQogICAgICAgICAgY29uc3Qgb2xkQ2VudGVyVG9Qb2ludFNxdWFyZWQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlU3F1YXJlZCgKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGN1cnJlbnRQb3MsIHJpdHRlckNlbnRlciwgZnJvbVBvaW50c1NjcmF0Y2gpCiAgICAgICAgICApOwogICAgICAgICAgaWYgKG9sZENlbnRlclRvUG9pbnRTcXVhcmVkID4gcmFkaXVzU3F1YXJlZCkgewogICAgICAgICAgICBjb25zdCBvbGRDZW50ZXJUb1BvaW50ID0gTWF0aC5zcXJ0KG9sZENlbnRlclRvUG9pbnRTcXVhcmVkKTsKICAgICAgICAgICAgcml0dGVyUmFkaXVzID0gKHJpdHRlclJhZGl1cyArIG9sZENlbnRlclRvUG9pbnQpICogMC41OwogICAgICAgICAgICByYWRpdXNTcXVhcmVkID0gcml0dGVyUmFkaXVzICogcml0dGVyUmFkaXVzOwogICAgICAgICAgICBjb25zdCBvbGRUb05ldyA9IG9sZENlbnRlclRvUG9pbnQgLSByaXR0ZXJSYWRpdXM7CiAgICAgICAgICAgIHJpdHRlckNlbnRlci54ID0gKHJpdHRlclJhZGl1cyAqIHJpdHRlckNlbnRlci54ICsgb2xkVG9OZXcgKiBjdXJyZW50UG9zLngpIC8gb2xkQ2VudGVyVG9Qb2ludDsKICAgICAgICAgICAgcml0dGVyQ2VudGVyLnkgPSAocml0dGVyUmFkaXVzICogcml0dGVyQ2VudGVyLnkgKyBvbGRUb05ldyAqIGN1cnJlbnRQb3MueSkgLyBvbGRDZW50ZXJUb1BvaW50OwogICAgICAgICAgICByaXR0ZXJDZW50ZXIueiA9IChyaXR0ZXJSYWRpdXMgKiByaXR0ZXJDZW50ZXIueiArIG9sZFRvTmV3ICogY3VycmVudFBvcy56KSAvIG9sZENlbnRlclRvUG9pbnQ7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChyaXR0ZXJSYWRpdXMgPCBuYWl2ZVJhZGl1cykgewogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHJpdHRlckNlbnRlciwgcmVzdWx0LmNlbnRlcik7CiAgICAgICAgICByZXN1bHQucmFkaXVzID0gcml0dGVyUmFkaXVzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUobmFpdmVDZW50ZXIsIHJlc3VsdC5jZW50ZXIpOwogICAgICAgICAgcmVzdWx0LnJhZGl1cyA9IG5haXZlUmFkaXVzOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBkZWZhdWx0UHJvamVjdGlvbiA9IG5ldyBHZW9ncmFwaGljUHJvamVjdGlvbl9kZWZhdWx0KCk7CiAgICAgIGZyb21SZWN0YW5nbGUyRExvd2VyTGVmdCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZnJvbVJlY3RhbmdsZTJEVXBwZXJSaWdodCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZnJvbVJlY3RhbmdsZTJEU291dGh3ZXN0ID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIGZyb21SZWN0YW5nbGUyRE5vcnRoZWFzdCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBCb3VuZGluZ1NwaGVyZS5mcm9tUmVjdGFuZ2xlMkQgPSBmdW5jdGlvbihyZWN0YW5nbGUsIHByb2plY3Rpb24sIHJlc3VsdCkgewogICAgICAgIHJldHVybiBCb3VuZGluZ1NwaGVyZS5mcm9tUmVjdGFuZ2xlV2l0aEhlaWdodHMyRCgKICAgICAgICAgIHJlY3RhbmdsZSwKICAgICAgICAgIHByb2plY3Rpb24sCiAgICAgICAgICAwLAogICAgICAgICAgMCwKICAgICAgICAgIHJlc3VsdAogICAgICAgICk7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nU3BoZXJlLmZyb21SZWN0YW5nbGVXaXRoSGVpZ2h0czJEID0gZnVuY3Rpb24ocmVjdGFuZ2xlLCBwcm9qZWN0aW9uLCBtaW5pbXVtSGVpZ2h0LCBtYXhpbXVtSGVpZ2h0LCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQm91bmRpbmdTcGhlcmUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVjdGFuZ2xlKSkgewogICAgICAgICAgcmVzdWx0LmNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywgcmVzdWx0LmNlbnRlcik7CiAgICAgICAgICByZXN1bHQucmFkaXVzID0gMDsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGRlZmF1bHRQcm9qZWN0aW9uLl9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgICAgIHByb2plY3Rpb24gPSBwcm9qZWN0aW9uID8/IGRlZmF1bHRQcm9qZWN0aW9uOwogICAgICAgIFJlY3RhbmdsZV9kZWZhdWx0LnNvdXRod2VzdChyZWN0YW5nbGUsIGZyb21SZWN0YW5nbGUyRFNvdXRod2VzdCk7CiAgICAgICAgZnJvbVJlY3RhbmdsZTJEU291dGh3ZXN0LmhlaWdodCA9IG1pbmltdW1IZWlnaHQ7CiAgICAgICAgUmVjdGFuZ2xlX2RlZmF1bHQubm9ydGhlYXN0KHJlY3RhbmdsZSwgZnJvbVJlY3RhbmdsZTJETm9ydGhlYXN0KTsKICAgICAgICBmcm9tUmVjdGFuZ2xlMkROb3J0aGVhc3QuaGVpZ2h0ID0gbWF4aW11bUhlaWdodDsKICAgICAgICBjb25zdCBsb3dlckxlZnQgPSBwcm9qZWN0aW9uLnByb2plY3QoCiAgICAgICAgICBmcm9tUmVjdGFuZ2xlMkRTb3V0aHdlc3QsCiAgICAgICAgICBmcm9tUmVjdGFuZ2xlMkRMb3dlckxlZnQKICAgICAgICApOwogICAgICAgIGNvbnN0IHVwcGVyUmlnaHQgPSBwcm9qZWN0aW9uLnByb2plY3QoCiAgICAgICAgICBmcm9tUmVjdGFuZ2xlMkROb3J0aGVhc3QsCiAgICAgICAgICBmcm9tUmVjdGFuZ2xlMkRVcHBlclJpZ2h0CiAgICAgICAgKTsKICAgICAgICBjb25zdCB3aWR0aCA9IHVwcGVyUmlnaHQueCAtIGxvd2VyTGVmdC54OwogICAgICAgIGNvbnN0IGhlaWdodCA9IHVwcGVyUmlnaHQueSAtIGxvd2VyTGVmdC55OwogICAgICAgIGNvbnN0IGVsZXZhdGlvbiA9IHVwcGVyUmlnaHQueiAtIGxvd2VyTGVmdC56OwogICAgICAgIHJlc3VsdC5yYWRpdXMgPSBNYXRoLnNxcnQod2lkdGggKiB3aWR0aCArIGhlaWdodCAqIGhlaWdodCArIGVsZXZhdGlvbiAqIGVsZXZhdGlvbikgKiAwLjU7CiAgICAgICAgY29uc3QgY2VudGVyID0gcmVzdWx0LmNlbnRlcjsKICAgICAgICBjZW50ZXIueCA9IGxvd2VyTGVmdC54ICsgd2lkdGggKiAwLjU7CiAgICAgICAgY2VudGVyLnkgPSBsb3dlckxlZnQueSArIGhlaWdodCAqIDAuNTsKICAgICAgICBjZW50ZXIueiA9IGxvd2VyTGVmdC56ICsgZWxldmF0aW9uICogMC41OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIGZyb21SZWN0YW5nbGUzRFNjcmF0Y2ggPSBbXTsKICAgICAgQm91bmRpbmdTcGhlcmUuZnJvbVJlY3RhbmdsZTNEID0gZnVuY3Rpb24ocmVjdGFuZ2xlLCBlbGxpcHNvaWQsIHN1cmZhY2VIZWlnaHQsIHJlc3VsdCkgewogICAgICAgIGVsbGlwc29pZCA9IGVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgICAgIHN1cmZhY2VIZWlnaHQgPSBzdXJmYWNlSGVpZ2h0ID8/IDA7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEJvdW5kaW5nU3BoZXJlKCk7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlY3RhbmdsZSkpIHsKICAgICAgICAgIHJlc3VsdC5jZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sIHJlc3VsdC5jZW50ZXIpOwogICAgICAgICAgcmVzdWx0LnJhZGl1cyA9IDA7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBSZWN0YW5nbGVfZGVmYXVsdC5zdWJzYW1wbGUoCiAgICAgICAgICByZWN0YW5nbGUsCiAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICBzdXJmYWNlSGVpZ2h0LAogICAgICAgICAgZnJvbVJlY3RhbmdsZTNEU2NyYXRjaAogICAgICAgICk7CiAgICAgICAgcmV0dXJuIEJvdW5kaW5nU3BoZXJlLmZyb21Qb2ludHMocG9zaXRpb25zLCByZXN1bHQpOwogICAgICB9OwogICAgICBCb3VuZGluZ1NwaGVyZS5mcm9tVmVydGljZXMgPSBmdW5jdGlvbihwb3NpdGlvbnMsIGNlbnRlciwgc3RyaWRlLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQm91bmRpbmdTcGhlcmUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocG9zaXRpb25zKSB8fCBwb3NpdGlvbnMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXN1bHQuY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLCByZXN1bHQuY2VudGVyKTsKICAgICAgICAgIHJlc3VsdC5yYWRpdXMgPSAwOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgY2VudGVyID0gY2VudGVyID8/IENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPOwogICAgICAgIHN0cmlkZSA9IHN0cmlkZSA/PyAzOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJzdHJpZGUiLCBzdHJpZGUsIDMpOwogICAgICAgIGNvbnN0IGN1cnJlbnRQb3MgPSBmcm9tUG9pbnRzQ3VycmVudFBvczsKICAgICAgICBjdXJyZW50UG9zLnggPSBwb3NpdGlvbnNbMF0gKyBjZW50ZXIueDsKICAgICAgICBjdXJyZW50UG9zLnkgPSBwb3NpdGlvbnNbMV0gKyBjZW50ZXIueTsKICAgICAgICBjdXJyZW50UG9zLnogPSBwb3NpdGlvbnNbMl0gKyBjZW50ZXIuejsKICAgICAgICBjb25zdCB4TWluID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGN1cnJlbnRQb3MsIGZyb21Qb2ludHNYTWluKTsKICAgICAgICBjb25zdCB5TWluID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGN1cnJlbnRQb3MsIGZyb21Qb2ludHNZTWluKTsKICAgICAgICBjb25zdCB6TWluID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGN1cnJlbnRQb3MsIGZyb21Qb2ludHNaTWluKTsKICAgICAgICBjb25zdCB4TWF4ID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGN1cnJlbnRQb3MsIGZyb21Qb2ludHNYTWF4KTsKICAgICAgICBjb25zdCB5TWF4ID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGN1cnJlbnRQb3MsIGZyb21Qb2ludHNZTWF4KTsKICAgICAgICBjb25zdCB6TWF4ID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGN1cnJlbnRQb3MsIGZyb21Qb2ludHNaTWF4KTsKICAgICAgICBjb25zdCBudW1FbGVtZW50cyA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgbGV0IGk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IG51bUVsZW1lbnRzOyBpICs9IHN0cmlkZSkgewogICAgICAgICAgY29uc3QgeCA9IHBvc2l0aW9uc1tpXSArIGNlbnRlci54OwogICAgICAgICAgY29uc3QgeSA9IHBvc2l0aW9uc1tpICsgMV0gKyBjZW50ZXIueTsKICAgICAgICAgIGNvbnN0IHogPSBwb3NpdGlvbnNbaSArIDJdICsgY2VudGVyLno7CiAgICAgICAgICBjdXJyZW50UG9zLnggPSB4OwogICAgICAgICAgY3VycmVudFBvcy55ID0geTsKICAgICAgICAgIGN1cnJlbnRQb3MueiA9IHo7CiAgICAgICAgICBpZiAoeCA8IHhNaW4ueCkgewogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgeE1pbik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoeCA+IHhNYXgueCkgewogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgeE1heCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoeSA8IHlNaW4ueSkgewogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgeU1pbik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoeSA+IHlNYXgueSkgewogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgeU1heCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoeiA8IHpNaW4ueikgewogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgek1pbik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoeiA+IHpNYXgueikgewogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY3VycmVudFBvcywgek1heCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IHhTcGFuID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZVNxdWFyZWQoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoeE1heCwgeE1pbiwgZnJvbVBvaW50c1NjcmF0Y2gpCiAgICAgICAgKTsKICAgICAgICBjb25zdCB5U3BhbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGVTcXVhcmVkKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHlNYXgsIHlNaW4sIGZyb21Qb2ludHNTY3JhdGNoKQogICAgICAgICk7CiAgICAgICAgY29uc3QgelNwYW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlU3F1YXJlZCgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCh6TWF4LCB6TWluLCBmcm9tUG9pbnRzU2NyYXRjaCkKICAgICAgICApOwogICAgICAgIGxldCBkaWFtZXRlcjEgPSB4TWluOwogICAgICAgIGxldCBkaWFtZXRlcjIgPSB4TWF4OwogICAgICAgIGxldCBtYXhTcGFuID0geFNwYW47CiAgICAgICAgaWYgKHlTcGFuID4gbWF4U3BhbikgewogICAgICAgICAgbWF4U3BhbiA9IHlTcGFuOwogICAgICAgICAgZGlhbWV0ZXIxID0geU1pbjsKICAgICAgICAgIGRpYW1ldGVyMiA9IHlNYXg7CiAgICAgICAgfQogICAgICAgIGlmICh6U3BhbiA+IG1heFNwYW4pIHsKICAgICAgICAgIG1heFNwYW4gPSB6U3BhbjsKICAgICAgICAgIGRpYW1ldGVyMSA9IHpNaW47CiAgICAgICAgICBkaWFtZXRlcjIgPSB6TWF4OwogICAgICAgIH0KICAgICAgICBjb25zdCByaXR0ZXJDZW50ZXIgPSBmcm9tUG9pbnRzUml0dGVyQ2VudGVyOwogICAgICAgIHJpdHRlckNlbnRlci54ID0gKGRpYW1ldGVyMS54ICsgZGlhbWV0ZXIyLngpICogMC41OwogICAgICAgIHJpdHRlckNlbnRlci55ID0gKGRpYW1ldGVyMS55ICsgZGlhbWV0ZXIyLnkpICogMC41OwogICAgICAgIHJpdHRlckNlbnRlci56ID0gKGRpYW1ldGVyMS56ICsgZGlhbWV0ZXIyLnopICogMC41OwogICAgICAgIGxldCByYWRpdXNTcXVhcmVkID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZVNxdWFyZWQoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoZGlhbWV0ZXIyLCByaXR0ZXJDZW50ZXIsIGZyb21Qb2ludHNTY3JhdGNoKQogICAgICAgICk7CiAgICAgICAgbGV0IHJpdHRlclJhZGl1cyA9IE1hdGguc3FydChyYWRpdXNTcXVhcmVkKTsKICAgICAgICBjb25zdCBtaW5Cb3hQdCA9IGZyb21Qb2ludHNNaW5Cb3hQdDsKICAgICAgICBtaW5Cb3hQdC54ID0geE1pbi54OwogICAgICAgIG1pbkJveFB0LnkgPSB5TWluLnk7CiAgICAgICAgbWluQm94UHQueiA9IHpNaW4uejsKICAgICAgICBjb25zdCBtYXhCb3hQdCA9IGZyb21Qb2ludHNNYXhCb3hQdDsKICAgICAgICBtYXhCb3hQdC54ID0geE1heC54OwogICAgICAgIG1heEJveFB0LnkgPSB5TWF4Lnk7CiAgICAgICAgbWF4Qm94UHQueiA9IHpNYXguejsKICAgICAgICBjb25zdCBuYWl2ZUNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5taWRwb2ludCgKICAgICAgICAgIG1pbkJveFB0LAogICAgICAgICAgbWF4Qm94UHQsCiAgICAgICAgICBmcm9tUG9pbnRzTmFpdmVDZW50ZXJTY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBsZXQgbmFpdmVSYWRpdXMgPSAwOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1FbGVtZW50czsgaSArPSBzdHJpZGUpIHsKICAgICAgICAgIGN1cnJlbnRQb3MueCA9IHBvc2l0aW9uc1tpXSArIGNlbnRlci54OwogICAgICAgICAgY3VycmVudFBvcy55ID0gcG9zaXRpb25zW2kgKyAxXSArIGNlbnRlci55OwogICAgICAgICAgY3VycmVudFBvcy56ID0gcG9zaXRpb25zW2kgKyAyXSArIGNlbnRlci56OwogICAgICAgICAgY29uc3QgciA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUoCiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjdXJyZW50UG9zLCBuYWl2ZUNlbnRlciwgZnJvbVBvaW50c1NjcmF0Y2gpCiAgICAgICAgICApOwogICAgICAgICAgaWYgKHIgPiBuYWl2ZVJhZGl1cykgewogICAgICAgICAgICBuYWl2ZVJhZGl1cyA9IHI7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBvbGRDZW50ZXJUb1BvaW50U3F1YXJlZCA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGVTcXVhcmVkKAogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoY3VycmVudFBvcywgcml0dGVyQ2VudGVyLCBmcm9tUG9pbnRzU2NyYXRjaCkKICAgICAgICAgICk7CiAgICAgICAgICBpZiAob2xkQ2VudGVyVG9Qb2ludFNxdWFyZWQgPiByYWRpdXNTcXVhcmVkKSB7CiAgICAgICAgICAgIGNvbnN0IG9sZENlbnRlclRvUG9pbnQgPSBNYXRoLnNxcnQob2xkQ2VudGVyVG9Qb2ludFNxdWFyZWQpOwogICAgICAgICAgICByaXR0ZXJSYWRpdXMgPSAocml0dGVyUmFkaXVzICsgb2xkQ2VudGVyVG9Qb2ludCkgKiAwLjU7CiAgICAgICAgICAgIHJhZGl1c1NxdWFyZWQgPSByaXR0ZXJSYWRpdXMgKiByaXR0ZXJSYWRpdXM7CiAgICAgICAgICAgIGNvbnN0IG9sZFRvTmV3ID0gb2xkQ2VudGVyVG9Qb2ludCAtIHJpdHRlclJhZGl1czsKICAgICAgICAgICAgcml0dGVyQ2VudGVyLnggPSAocml0dGVyUmFkaXVzICogcml0dGVyQ2VudGVyLnggKyBvbGRUb05ldyAqIGN1cnJlbnRQb3MueCkgLyBvbGRDZW50ZXJUb1BvaW50OwogICAgICAgICAgICByaXR0ZXJDZW50ZXIueSA9IChyaXR0ZXJSYWRpdXMgKiByaXR0ZXJDZW50ZXIueSArIG9sZFRvTmV3ICogY3VycmVudFBvcy55KSAvIG9sZENlbnRlclRvUG9pbnQ7CiAgICAgICAgICAgIHJpdHRlckNlbnRlci56ID0gKHJpdHRlclJhZGl1cyAqIHJpdHRlckNlbnRlci56ICsgb2xkVG9OZXcgKiBjdXJyZW50UG9zLnopIC8gb2xkQ2VudGVyVG9Qb2ludDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHJpdHRlclJhZGl1cyA8IG5haXZlUmFkaXVzKSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocml0dGVyQ2VudGVyLCByZXN1bHQuY2VudGVyKTsKICAgICAgICAgIHJlc3VsdC5yYWRpdXMgPSByaXR0ZXJSYWRpdXM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShuYWl2ZUNlbnRlciwgcmVzdWx0LmNlbnRlcik7CiAgICAgICAgICByZXN1bHQucmFkaXVzID0gbmFpdmVSYWRpdXM7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nU3BoZXJlLmZyb21FbmNvZGVkQ2FydGVzaWFuVmVydGljZXMgPSBmdW5jdGlvbihwb3NpdGlvbnNIaWdoLCBwb3NpdGlvbnNMb3csIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBCb3VuZGluZ1NwaGVyZSgpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwb3NpdGlvbnNIaWdoKSB8fCAhZGVmaW5lZF9kZWZhdWx0KHBvc2l0aW9uc0xvdykgfHwgcG9zaXRpb25zSGlnaC5sZW5ndGggIT09IHBvc2l0aW9uc0xvdy5sZW5ndGggfHwgcG9zaXRpb25zSGlnaC5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHJlc3VsdC5jZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sIHJlc3VsdC5jZW50ZXIpOwogICAgICAgICAgcmVzdWx0LnJhZGl1cyA9IDA7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICBjb25zdCBjdXJyZW50UG9zID0gZnJvbVBvaW50c0N1cnJlbnRQb3M7CiAgICAgICAgY3VycmVudFBvcy54ID0gcG9zaXRpb25zSGlnaFswXSArIHBvc2l0aW9uc0xvd1swXTsKICAgICAgICBjdXJyZW50UG9zLnkgPSBwb3NpdGlvbnNIaWdoWzFdICsgcG9zaXRpb25zTG93WzFdOwogICAgICAgIGN1cnJlbnRQb3MueiA9IHBvc2l0aW9uc0hpZ2hbMl0gKyBwb3NpdGlvbnNMb3dbMl07CiAgICAgICAgY29uc3QgeE1pbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCBmcm9tUG9pbnRzWE1pbik7CiAgICAgICAgY29uc3QgeU1pbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCBmcm9tUG9pbnRzWU1pbik7CiAgICAgICAgY29uc3Qgek1pbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCBmcm9tUG9pbnRzWk1pbik7CiAgICAgICAgY29uc3QgeE1heCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCBmcm9tUG9pbnRzWE1heCk7CiAgICAgICAgY29uc3QgeU1heCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCBmcm9tUG9pbnRzWU1heCk7CiAgICAgICAgY29uc3Qgek1heCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCBmcm9tUG9pbnRzWk1heCk7CiAgICAgICAgY29uc3QgbnVtRWxlbWVudHMgPSBwb3NpdGlvbnNIaWdoLmxlbmd0aDsKICAgICAgICBsZXQgaTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtRWxlbWVudHM7IGkgKz0gMykgewogICAgICAgICAgY29uc3QgeCA9IHBvc2l0aW9uc0hpZ2hbaV0gKyBwb3NpdGlvbnNMb3dbaV07CiAgICAgICAgICBjb25zdCB5ID0gcG9zaXRpb25zSGlnaFtpICsgMV0gKyBwb3NpdGlvbnNMb3dbaSArIDFdOwogICAgICAgICAgY29uc3QgeiA9IHBvc2l0aW9uc0hpZ2hbaSArIDJdICsgcG9zaXRpb25zTG93W2kgKyAyXTsKICAgICAgICAgIGN1cnJlbnRQb3MueCA9IHg7CiAgICAgICAgICBjdXJyZW50UG9zLnkgPSB5OwogICAgICAgICAgY3VycmVudFBvcy56ID0gejsKICAgICAgICAgIGlmICh4IDwgeE1pbi54KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB4TWluKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh4ID4geE1heC54KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB4TWF4KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh5IDwgeU1pbi55KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB5TWluKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh5ID4geU1heC55KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB5TWF4KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh6IDwgek1pbi56KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB6TWluKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh6ID4gek1heC56KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjdXJyZW50UG9zLCB6TWF4KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgeFNwYW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlU3F1YXJlZCgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCh4TWF4LCB4TWluLCBmcm9tUG9pbnRzU2NyYXRjaCkKICAgICAgICApOwogICAgICAgIGNvbnN0IHlTcGFuID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZVNxdWFyZWQoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoeU1heCwgeU1pbiwgZnJvbVBvaW50c1NjcmF0Y2gpCiAgICAgICAgKTsKICAgICAgICBjb25zdCB6U3BhbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGVTcXVhcmVkKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHpNYXgsIHpNaW4sIGZyb21Qb2ludHNTY3JhdGNoKQogICAgICAgICk7CiAgICAgICAgbGV0IGRpYW1ldGVyMSA9IHhNaW47CiAgICAgICAgbGV0IGRpYW1ldGVyMiA9IHhNYXg7CiAgICAgICAgbGV0IG1heFNwYW4gPSB4U3BhbjsKICAgICAgICBpZiAoeVNwYW4gPiBtYXhTcGFuKSB7CiAgICAgICAgICBtYXhTcGFuID0geVNwYW47CiAgICAgICAgICBkaWFtZXRlcjEgPSB5TWluOwogICAgICAgICAgZGlhbWV0ZXIyID0geU1heDsKICAgICAgICB9CiAgICAgICAgaWYgKHpTcGFuID4gbWF4U3BhbikgewogICAgICAgICAgbWF4U3BhbiA9IHpTcGFuOwogICAgICAgICAgZGlhbWV0ZXIxID0gek1pbjsKICAgICAgICAgIGRpYW1ldGVyMiA9IHpNYXg7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHJpdHRlckNlbnRlciA9IGZyb21Qb2ludHNSaXR0ZXJDZW50ZXI7CiAgICAgICAgcml0dGVyQ2VudGVyLnggPSAoZGlhbWV0ZXIxLnggKyBkaWFtZXRlcjIueCkgKiAwLjU7CiAgICAgICAgcml0dGVyQ2VudGVyLnkgPSAoZGlhbWV0ZXIxLnkgKyBkaWFtZXRlcjIueSkgKiAwLjU7CiAgICAgICAgcml0dGVyQ2VudGVyLnogPSAoZGlhbWV0ZXIxLnogKyBkaWFtZXRlcjIueikgKiAwLjU7CiAgICAgICAgbGV0IHJhZGl1c1NxdWFyZWQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlU3F1YXJlZCgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChkaWFtZXRlcjIsIHJpdHRlckNlbnRlciwgZnJvbVBvaW50c1NjcmF0Y2gpCiAgICAgICAgKTsKICAgICAgICBsZXQgcml0dGVyUmFkaXVzID0gTWF0aC5zcXJ0KHJhZGl1c1NxdWFyZWQpOwogICAgICAgIGNvbnN0IG1pbkJveFB0ID0gZnJvbVBvaW50c01pbkJveFB0OwogICAgICAgIG1pbkJveFB0LnggPSB4TWluLng7CiAgICAgICAgbWluQm94UHQueSA9IHlNaW4ueTsKICAgICAgICBtaW5Cb3hQdC56ID0gek1pbi56OwogICAgICAgIGNvbnN0IG1heEJveFB0ID0gZnJvbVBvaW50c01heEJveFB0OwogICAgICAgIG1heEJveFB0LnggPSB4TWF4Lng7CiAgICAgICAgbWF4Qm94UHQueSA9IHlNYXgueTsKICAgICAgICBtYXhCb3hQdC56ID0gek1heC56OwogICAgICAgIGNvbnN0IG5haXZlQ2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1pZHBvaW50KAogICAgICAgICAgbWluQm94UHQsCiAgICAgICAgICBtYXhCb3hQdCwKICAgICAgICAgIGZyb21Qb2ludHNOYWl2ZUNlbnRlclNjcmF0Y2gKICAgICAgICApOwogICAgICAgIGxldCBuYWl2ZVJhZGl1cyA9IDA7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IG51bUVsZW1lbnRzOyBpICs9IDMpIHsKICAgICAgICAgIGN1cnJlbnRQb3MueCA9IHBvc2l0aW9uc0hpZ2hbaV0gKyBwb3NpdGlvbnNMb3dbaV07CiAgICAgICAgICBjdXJyZW50UG9zLnkgPSBwb3NpdGlvbnNIaWdoW2kgKyAxXSArIHBvc2l0aW9uc0xvd1tpICsgMV07CiAgICAgICAgICBjdXJyZW50UG9zLnogPSBwb3NpdGlvbnNIaWdoW2kgKyAyXSArIHBvc2l0aW9uc0xvd1tpICsgMl07CiAgICAgICAgICBjb25zdCByID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZSgKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGN1cnJlbnRQb3MsIG5haXZlQ2VudGVyLCBmcm9tUG9pbnRzU2NyYXRjaCkKICAgICAgICAgICk7CiAgICAgICAgICBpZiAociA+IG5haXZlUmFkaXVzKSB7CiAgICAgICAgICAgIG5haXZlUmFkaXVzID0gcjsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IG9sZENlbnRlclRvUG9pbnRTcXVhcmVkID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZVNxdWFyZWQoCiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjdXJyZW50UG9zLCByaXR0ZXJDZW50ZXIsIGZyb21Qb2ludHNTY3JhdGNoKQogICAgICAgICAgKTsKICAgICAgICAgIGlmIChvbGRDZW50ZXJUb1BvaW50U3F1YXJlZCA+IHJhZGl1c1NxdWFyZWQpIHsKICAgICAgICAgICAgY29uc3Qgb2xkQ2VudGVyVG9Qb2ludCA9IE1hdGguc3FydChvbGRDZW50ZXJUb1BvaW50U3F1YXJlZCk7CiAgICAgICAgICAgIHJpdHRlclJhZGl1cyA9IChyaXR0ZXJSYWRpdXMgKyBvbGRDZW50ZXJUb1BvaW50KSAqIDAuNTsKICAgICAgICAgICAgcmFkaXVzU3F1YXJlZCA9IHJpdHRlclJhZGl1cyAqIHJpdHRlclJhZGl1czsKICAgICAgICAgICAgY29uc3Qgb2xkVG9OZXcgPSBvbGRDZW50ZXJUb1BvaW50IC0gcml0dGVyUmFkaXVzOwogICAgICAgICAgICByaXR0ZXJDZW50ZXIueCA9IChyaXR0ZXJSYWRpdXMgKiByaXR0ZXJDZW50ZXIueCArIG9sZFRvTmV3ICogY3VycmVudFBvcy54KSAvIG9sZENlbnRlclRvUG9pbnQ7CiAgICAgICAgICAgIHJpdHRlckNlbnRlci55ID0gKHJpdHRlclJhZGl1cyAqIHJpdHRlckNlbnRlci55ICsgb2xkVG9OZXcgKiBjdXJyZW50UG9zLnkpIC8gb2xkQ2VudGVyVG9Qb2ludDsKICAgICAgICAgICAgcml0dGVyQ2VudGVyLnogPSAocml0dGVyUmFkaXVzICogcml0dGVyQ2VudGVyLnogKyBvbGRUb05ldyAqIGN1cnJlbnRQb3MueikgLyBvbGRDZW50ZXJUb1BvaW50OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAocml0dGVyUmFkaXVzIDwgbmFpdmVSYWRpdXMpIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShyaXR0ZXJDZW50ZXIsIHJlc3VsdC5jZW50ZXIpOwogICAgICAgICAgcmVzdWx0LnJhZGl1cyA9IHJpdHRlclJhZGl1czsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKG5haXZlQ2VudGVyLCByZXN1bHQuY2VudGVyKTsKICAgICAgICAgIHJlc3VsdC5yYWRpdXMgPSBuYWl2ZVJhZGl1czsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQm91bmRpbmdTcGhlcmUuZnJvbUNvcm5lclBvaW50cyA9IGZ1bmN0aW9uKGNvcm5lciwgb3Bwb3NpdGVDb3JuZXIsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY29ybmVyIiwgY29ybmVyKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm9wcG9zaXRlQ29ybmVyIiwgb3Bwb3NpdGVDb3JuZXIpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBCb3VuZGluZ1NwaGVyZSgpOwogICAgICAgIH0KICAgICAgICBjb25zdCBjZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWlkcG9pbnQoY29ybmVyLCBvcHBvc2l0ZUNvcm5lciwgcmVzdWx0LmNlbnRlcik7CiAgICAgICAgcmVzdWx0LnJhZGl1cyA9IENhcnRlc2lhbjNfZGVmYXVsdC5kaXN0YW5jZShjZW50ZXIsIG9wcG9zaXRlQ29ybmVyKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBCb3VuZGluZ1NwaGVyZS5mcm9tRWxsaXBzb2lkID0gZnVuY3Rpb24oZWxsaXBzb2lkLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImVsbGlwc29pZCIsIGVsbGlwc29pZCk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEJvdW5kaW5nU3BoZXJlKCk7CiAgICAgICAgfQogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywgcmVzdWx0LmNlbnRlcik7CiAgICAgICAgcmVzdWx0LnJhZGl1cyA9IGVsbGlwc29pZC5tYXhpbXVtUmFkaXVzOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIGZyb21Cb3VuZGluZ1NwaGVyZXNTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBCb3VuZGluZ1NwaGVyZS5mcm9tQm91bmRpbmdTcGhlcmVzID0gZnVuY3Rpb24oYm91bmRpbmdTcGhlcmVzLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQm91bmRpbmdTcGhlcmUoKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYm91bmRpbmdTcGhlcmVzKSB8fCBib3VuZGluZ1NwaGVyZXMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXN1bHQuY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLCByZXN1bHQuY2VudGVyKTsKICAgICAgICAgIHJlc3VsdC5yYWRpdXMgPSAwOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgY29uc3QgbGVuZ3RoID0gYm91bmRpbmdTcGhlcmVzLmxlbmd0aDsKICAgICAgICBpZiAobGVuZ3RoID09PSAxKSB7CiAgICAgICAgICByZXR1cm4gQm91bmRpbmdTcGhlcmUuY2xvbmUoYm91bmRpbmdTcGhlcmVzWzBdLCByZXN1bHQpOwogICAgICAgIH0KICAgICAgICBpZiAobGVuZ3RoID09PSAyKSB7CiAgICAgICAgICByZXR1cm4gQm91bmRpbmdTcGhlcmUudW5pb24oYm91bmRpbmdTcGhlcmVzWzBdLCBib3VuZGluZ1NwaGVyZXNbMV0sIHJlc3VsdCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IFtdOwogICAgICAgIGxldCBpOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgcG9zaXRpb25zLnB1c2goYm91bmRpbmdTcGhlcmVzW2ldLmNlbnRlcik7CiAgICAgICAgfQogICAgICAgIHJlc3VsdCA9IEJvdW5kaW5nU3BoZXJlLmZyb21Qb2ludHMocG9zaXRpb25zLCByZXN1bHQpOwogICAgICAgIGNvbnN0IGNlbnRlciA9IHJlc3VsdC5jZW50ZXI7CiAgICAgICAgbGV0IHJhZGl1cyA9IHJlc3VsdC5yYWRpdXM7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBjb25zdCB0bXAyID0gYm91bmRpbmdTcGhlcmVzW2ldOwogICAgICAgICAgcmFkaXVzID0gTWF0aC5tYXgoCiAgICAgICAgICAgIHJhZGl1cywKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmRpc3RhbmNlKGNlbnRlciwgdG1wMi5jZW50ZXIsIGZyb21Cb3VuZGluZ1NwaGVyZXNTY3JhdGNoKSArIHRtcDIucmFkaXVzCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXN1bHQucmFkaXVzID0gcmFkaXVzOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIGZyb21PcmllbnRlZEJvdW5kaW5nQm94U2NyYXRjaFUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZyb21PcmllbnRlZEJvdW5kaW5nQm94U2NyYXRjaFYgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZyb21PcmllbnRlZEJvdW5kaW5nQm94U2NyYXRjaFcgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIEJvdW5kaW5nU3BoZXJlLmZyb21PcmllbnRlZEJvdW5kaW5nQm94ID0gZnVuY3Rpb24ob3JpZW50ZWRCb3VuZGluZ0JveCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJvcmllbnRlZEJvdW5kaW5nQm94Iiwgb3JpZW50ZWRCb3VuZGluZ0JveCk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEJvdW5kaW5nU3BoZXJlKCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGhhbGZBeGVzID0gb3JpZW50ZWRCb3VuZGluZ0JveC5oYWxmQXhlczsKICAgICAgICBjb25zdCB1MyA9IE1hdHJpeDNfZGVmYXVsdC5nZXRDb2x1bW4oaGFsZkF4ZXMsIDAsIGZyb21PcmllbnRlZEJvdW5kaW5nQm94U2NyYXRjaFUpOwogICAgICAgIGNvbnN0IHYzID0gTWF0cml4M19kZWZhdWx0LmdldENvbHVtbihoYWxmQXhlcywgMSwgZnJvbU9yaWVudGVkQm91bmRpbmdCb3hTY3JhdGNoVik7CiAgICAgICAgY29uc3QgdyA9IE1hdHJpeDNfZGVmYXVsdC5nZXRDb2x1bW4oaGFsZkF4ZXMsIDIsIGZyb21PcmllbnRlZEJvdW5kaW5nQm94U2NyYXRjaFcpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQodTMsIHYzLCB1Myk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZCh1MywgdywgdTMpOwogICAgICAgIHJlc3VsdC5jZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUob3JpZW50ZWRCb3VuZGluZ0JveC5jZW50ZXIsIHJlc3VsdC5jZW50ZXIpOwogICAgICAgIHJlc3VsdC5yYWRpdXMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKHUzKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBzY3JhdGNoRnJvbVRyYW5zZm9ybWF0aW9uQ2VudGVyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoRnJvbVRyYW5zZm9ybWF0aW9uU2NhbGUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIEJvdW5kaW5nU3BoZXJlLmZyb21UcmFuc2Zvcm1hdGlvbiA9IGZ1bmN0aW9uKHRyYW5zZm9ybWF0aW9uLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInRyYW5zZm9ybWF0aW9uIiwgdHJhbnNmb3JtYXRpb24pOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBCb3VuZGluZ1NwaGVyZSgpOwogICAgICAgIH0KICAgICAgICBjb25zdCBjZW50ZXIgPSBNYXRyaXg0X2RlZmF1bHQuZ2V0VHJhbnNsYXRpb24oCiAgICAgICAgICB0cmFuc2Zvcm1hdGlvbiwKICAgICAgICAgIHNjcmF0Y2hGcm9tVHJhbnNmb3JtYXRpb25DZW50ZXIKICAgICAgICApOwogICAgICAgIGNvbnN0IHNjYWxlID0gTWF0cml4NF9kZWZhdWx0LmdldFNjYWxlKAogICAgICAgICAgdHJhbnNmb3JtYXRpb24sCiAgICAgICAgICBzY3JhdGNoRnJvbVRyYW5zZm9ybWF0aW9uU2NhbGUKICAgICAgICApOwogICAgICAgIGNvbnN0IHJhZGl1cyA9IDAuNSAqIENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUoc2NhbGUpOwogICAgICAgIHJlc3VsdC5jZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY2VudGVyLCByZXN1bHQuY2VudGVyKTsKICAgICAgICByZXN1bHQucmFkaXVzID0gcmFkaXVzOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nU3BoZXJlLmNsb25lID0gZnVuY3Rpb24oc3BoZXJlLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChzcGhlcmUpKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IEJvdW5kaW5nU3BoZXJlKHNwaGVyZS5jZW50ZXIsIHNwaGVyZS5yYWRpdXMpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHNwaGVyZS5jZW50ZXIsIHJlc3VsdC5jZW50ZXIpOwogICAgICAgIHJlc3VsdC5yYWRpdXMgPSBzcGhlcmUucmFkaXVzOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nU3BoZXJlLnBhY2tlZExlbmd0aCA9IDQ7CiAgICAgIEJvdW5kaW5nU3BoZXJlLnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBjb25zdCBjZW50ZXIgPSB2YWx1ZS5jZW50ZXI7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IGNlbnRlci54OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSBjZW50ZXIueTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gY2VudGVyLno7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleF0gPSB2YWx1ZS5yYWRpdXM7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBCb3VuZGluZ1NwaGVyZS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBCb3VuZGluZ1NwaGVyZSgpOwogICAgICAgIH0KICAgICAgICBjb25zdCBjZW50ZXIgPSByZXN1bHQuY2VudGVyOwogICAgICAgIGNlbnRlci54ID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjZW50ZXIueSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY2VudGVyLnogPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdC5yYWRpdXMgPSBhcnJheVtzdGFydGluZ0luZGV4XTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICB1bmlvblNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHVuaW9uU2NyYXRjaENlbnRlciA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgQm91bmRpbmdTcGhlcmUudW5pb24gPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQm91bmRpbmdTcGhlcmUoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbGVmdENlbnRlciA9IGxlZnQuY2VudGVyOwogICAgICAgIGNvbnN0IGxlZnRSYWRpdXMgPSBsZWZ0LnJhZGl1czsKICAgICAgICBjb25zdCByaWdodENlbnRlciA9IHJpZ2h0LmNlbnRlcjsKICAgICAgICBjb25zdCByaWdodFJhZGl1cyA9IHJpZ2h0LnJhZGl1czsKICAgICAgICBjb25zdCB0b1JpZ2h0Q2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KAogICAgICAgICAgcmlnaHRDZW50ZXIsCiAgICAgICAgICBsZWZ0Q2VudGVyLAogICAgICAgICAgdW5pb25TY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBjb25zdCBjZW50ZXJTZXBhcmF0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZSh0b1JpZ2h0Q2VudGVyKTsKICAgICAgICBpZiAobGVmdFJhZGl1cyA+PSBjZW50ZXJTZXBhcmF0aW9uICsgcmlnaHRSYWRpdXMpIHsKICAgICAgICAgIGxlZnQuY2xvbmUocmVzdWx0KTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGlmIChyaWdodFJhZGl1cyA+PSBjZW50ZXJTZXBhcmF0aW9uICsgbGVmdFJhZGl1cykgewogICAgICAgICAgcmlnaHQuY2xvbmUocmVzdWx0KTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGhhbGZEaXN0YW5jZUJldHdlZW5UYW5nZW50UG9pbnRzID0gKGxlZnRSYWRpdXMgKyBjZW50ZXJTZXBhcmF0aW9uICsgcmlnaHRSYWRpdXMpICogMC41OwogICAgICAgIGNvbnN0IGNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICAgICAgdG9SaWdodENlbnRlciwKICAgICAgICAgICgtbGVmdFJhZGl1cyArIGhhbGZEaXN0YW5jZUJldHdlZW5UYW5nZW50UG9pbnRzKSAvIGNlbnRlclNlcGFyYXRpb24sCiAgICAgICAgICB1bmlvblNjcmF0Y2hDZW50ZXIKICAgICAgICApOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoY2VudGVyLCBsZWZ0Q2VudGVyLCBjZW50ZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjZW50ZXIsIHJlc3VsdC5jZW50ZXIpOwogICAgICAgIHJlc3VsdC5yYWRpdXMgPSBoYWxmRGlzdGFuY2VCZXR3ZWVuVGFuZ2VudFBvaW50czsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBleHBhbmRTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBCb3VuZGluZ1NwaGVyZS5leHBhbmQgPSBmdW5jdGlvbihzcGhlcmUsIHBvaW50LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInNwaGVyZSIsIHNwaGVyZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJwb2ludCIsIHBvaW50KTsKICAgICAgICByZXN1bHQgPSBCb3VuZGluZ1NwaGVyZS5jbG9uZShzcGhlcmUsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgcmFkaXVzID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZSgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChwb2ludCwgcmVzdWx0LmNlbnRlciwgZXhwYW5kU2NyYXRjaCkKICAgICAgICApOwogICAgICAgIGlmIChyYWRpdXMgPiByZXN1bHQucmFkaXVzKSB7CiAgICAgICAgICByZXN1bHQucmFkaXVzID0gcmFkaXVzOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBCb3VuZGluZ1NwaGVyZS5pbnRlcnNlY3RQbGFuZSA9IGZ1bmN0aW9uKHNwaGVyZSwgcGxhbmUpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInNwaGVyZSIsIHNwaGVyZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJwbGFuZSIsIHBsYW5lKTsKICAgICAgICBjb25zdCBjZW50ZXIgPSBzcGhlcmUuY2VudGVyOwogICAgICAgIGNvbnN0IHJhZGl1cyA9IHNwaGVyZS5yYWRpdXM7CiAgICAgICAgY29uc3Qgbm9ybWFsMiA9IHBsYW5lLm5vcm1hbDsKICAgICAgICBjb25zdCBkaXN0YW5jZVRvUGxhbmUgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KG5vcm1hbDIsIGNlbnRlcikgKyBwbGFuZS5kaXN0YW5jZTsKICAgICAgICBpZiAoZGlzdGFuY2VUb1BsYW5lIDwgLXJhZGl1cykgewogICAgICAgICAgcmV0dXJuIEludGVyc2VjdF9kZWZhdWx0Lk9VVFNJREU7CiAgICAgICAgfSBlbHNlIGlmIChkaXN0YW5jZVRvUGxhbmUgPCByYWRpdXMpIHsKICAgICAgICAgIHJldHVybiBJbnRlcnNlY3RfZGVmYXVsdC5JTlRFUlNFQ1RJTkc7CiAgICAgICAgfQogICAgICAgIHJldHVybiBJbnRlcnNlY3RfZGVmYXVsdC5JTlNJREU7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nU3BoZXJlLnRyYW5zZm9ybSA9IGZ1bmN0aW9uKHNwaGVyZSwgdHJhbnNmb3JtMiwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzcGhlcmUiLCBzcGhlcmUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidHJhbnNmb3JtIiwgdHJhbnNmb3JtMik7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEJvdW5kaW5nU3BoZXJlKCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5jZW50ZXIgPSBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlCeVBvaW50KAogICAgICAgICAgdHJhbnNmb3JtMiwKICAgICAgICAgIHNwaGVyZS5jZW50ZXIsCiAgICAgICAgICByZXN1bHQuY2VudGVyCiAgICAgICAgKTsKICAgICAgICByZXN1bHQucmFkaXVzID0gTWF0cml4NF9kZWZhdWx0LmdldE1heGltdW1TY2FsZSh0cmFuc2Zvcm0yKSAqIHNwaGVyZS5yYWRpdXM7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgZGlzdGFuY2VTcXVhcmVkVG9TY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBCb3VuZGluZ1NwaGVyZS5kaXN0YW5jZVNxdWFyZWRUbyA9IGZ1bmN0aW9uKHNwaGVyZSwgY2FydGVzaWFuMTEpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInNwaGVyZSIsIHNwaGVyZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgY29uc3QgZGlmZiA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgICAgIHNwaGVyZS5jZW50ZXIsCiAgICAgICAgICBjYXJ0ZXNpYW4xMSwKICAgICAgICAgIGRpc3RhbmNlU3F1YXJlZFRvU2NyYXRjaAogICAgICAgICk7CiAgICAgICAgY29uc3QgZGlzdGFuY2UgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKGRpZmYpIC0gc3BoZXJlLnJhZGl1czsKICAgICAgICBpZiAoZGlzdGFuY2UgPD0gMCkgewogICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQogICAgICAgIHJldHVybiBkaXN0YW5jZSAqIGRpc3RhbmNlOwogICAgICB9OwogICAgICBCb3VuZGluZ1NwaGVyZS50cmFuc2Zvcm1XaXRob3V0U2NhbGUgPSBmdW5jdGlvbihzcGhlcmUsIHRyYW5zZm9ybTIsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic3BoZXJlIiwgc3BoZXJlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInRyYW5zZm9ybSIsIHRyYW5zZm9ybTIpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBCb3VuZGluZ1NwaGVyZSgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuY2VudGVyID0gTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5QnlQb2ludCgKICAgICAgICAgIHRyYW5zZm9ybTIsCiAgICAgICAgICBzcGhlcmUuY2VudGVyLAogICAgICAgICAgcmVzdWx0LmNlbnRlcgogICAgICAgICk7CiAgICAgICAgcmVzdWx0LnJhZGl1cyA9IHNwaGVyZS5yYWRpdXM7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIEJvdW5kaW5nU3BoZXJlLmNvbXB1dGVQbGFuZURpc3RhbmNlcyA9IGZ1bmN0aW9uKHNwaGVyZSwgcG9zaXRpb24sIGRpcmVjdGlvbjIsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic3BoZXJlIiwgc3BoZXJlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInBvc2l0aW9uIiwgcG9zaXRpb24pOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiZGlyZWN0aW9uIiwgZGlyZWN0aW9uMik7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEludGVydmFsX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgdG9DZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgICAgICBzcGhlcmUuY2VudGVyLAogICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuMwogICAgICAgICk7CiAgICAgICAgY29uc3QgbWFnID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCB0b0NlbnRlcik7CiAgICAgICAgcmVzdWx0LnN0YXJ0ID0gbWFnIC0gc3BoZXJlLnJhZGl1czsKICAgICAgICByZXN1bHQuc3RvcCA9IG1hZyArIHNwaGVyZS5yYWRpdXM7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgcHJvamVjdFRvMkROb3JtYWxTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBwcm9qZWN0VG8yREVhc3RTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBwcm9qZWN0VG8yRE5vcnRoU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgcHJvamVjdFRvMkRXZXN0U2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgcHJvamVjdFRvMkRTb3V0aFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHByb2plY3RUbzJEQ2FydG9ncmFwaGljU2NyYXRjaCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBwcm9qZWN0VG8yRFBvc2l0aW9uc1NjcmF0Y2ggPSBuZXcgQXJyYXkoOCk7CiAgICAgIGZvciAobGV0IG4gPSAwOyBuIDwgODsgKytuKSB7CiAgICAgICAgcHJvamVjdFRvMkRQb3NpdGlvbnNTY3JhdGNoW25dID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICB9CiAgICAgIHByb2plY3RUbzJEUHJvamVjdGlvbiA9IG5ldyBHZW9ncmFwaGljUHJvamVjdGlvbl9kZWZhdWx0KCk7CiAgICAgIEJvdW5kaW5nU3BoZXJlLnByb2plY3RUbzJEID0gZnVuY3Rpb24oc3BoZXJlLCBwcm9qZWN0aW9uLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInNwaGVyZSIsIHNwaGVyZSk7CiAgICAgICAgcHJvamVjdFRvMkRQcm9qZWN0aW9uLl9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgICAgIHByb2plY3Rpb24gPSBwcm9qZWN0aW9uID8/IHByb2plY3RUbzJEUHJvamVjdGlvbjsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBwcm9qZWN0aW9uLmVsbGlwc29pZDsKICAgICAgICBsZXQgY2VudGVyID0gc3BoZXJlLmNlbnRlcjsKICAgICAgICBjb25zdCByYWRpdXMgPSBzcGhlcmUucmFkaXVzOwogICAgICAgIGxldCBub3JtYWwyOwogICAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzKGNlbnRlciwgQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8pKSB7CiAgICAgICAgICBub3JtYWwyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1gsIHByb2plY3RUbzJETm9ybWFsU2NyYXRjaCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG5vcm1hbDIgPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKGNlbnRlciwgcHJvamVjdFRvMkROb3JtYWxTY3JhdGNoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZWFzdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcygKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1osCiAgICAgICAgICBub3JtYWwyLAogICAgICAgICAgcHJvamVjdFRvMkRFYXN0U2NyYXRjaAogICAgICAgICk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShlYXN0LCBlYXN0KTsKICAgICAgICBjb25zdCBub3J0aCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhub3JtYWwyLCBlYXN0LCBwcm9qZWN0VG8yRE5vcnRoU2NyYXRjaCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShub3J0aCwgbm9ydGgpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKG5vcm1hbDIsIHJhZGl1cywgbm9ybWFsMik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobm9ydGgsIHJhZGl1cywgbm9ydGgpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGVhc3QsIHJhZGl1cywgZWFzdCk7CiAgICAgICAgY29uc3Qgc291dGggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKG5vcnRoLCBwcm9qZWN0VG8yRFNvdXRoU2NyYXRjaCk7CiAgICAgICAgY29uc3Qgd2VzdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoZWFzdCwgcHJvamVjdFRvMkRXZXN0U2NyYXRjaCk7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gcHJvamVjdFRvMkRQb3NpdGlvbnNTY3JhdGNoOwogICAgICAgIGxldCBjb3JuZXIgPSBwb3NpdGlvbnNbMF07CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChub3JtYWwyLCBub3J0aCwgY29ybmVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNvcm5lciwgZWFzdCwgY29ybmVyKTsKICAgICAgICBjb3JuZXIgPSBwb3NpdGlvbnNbMV07CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChub3JtYWwyLCBub3J0aCwgY29ybmVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNvcm5lciwgd2VzdCwgY29ybmVyKTsKICAgICAgICBjb3JuZXIgPSBwb3NpdGlvbnNbMl07CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChub3JtYWwyLCBzb3V0aCwgY29ybmVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNvcm5lciwgd2VzdCwgY29ybmVyKTsKICAgICAgICBjb3JuZXIgPSBwb3NpdGlvbnNbM107CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChub3JtYWwyLCBzb3V0aCwgY29ybmVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNvcm5lciwgZWFzdCwgY29ybmVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKG5vcm1hbDIsIG5vcm1hbDIpOwogICAgICAgIGNvcm5lciA9IHBvc2l0aW9uc1s0XTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKG5vcm1hbDIsIG5vcnRoLCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoY29ybmVyLCBlYXN0LCBjb3JuZXIpOwogICAgICAgIGNvcm5lciA9IHBvc2l0aW9uc1s1XTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKG5vcm1hbDIsIG5vcnRoLCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoY29ybmVyLCB3ZXN0LCBjb3JuZXIpOwogICAgICAgIGNvcm5lciA9IHBvc2l0aW9uc1s2XTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKG5vcm1hbDIsIHNvdXRoLCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoY29ybmVyLCB3ZXN0LCBjb3JuZXIpOwogICAgICAgIGNvcm5lciA9IHBvc2l0aW9uc1s3XTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKG5vcm1hbDIsIHNvdXRoLCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoY29ybmVyLCBlYXN0LCBjb3JuZXIpOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgY29uc3QgcG9zaXRpb24gPSBwb3NpdGlvbnNbaV07CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNlbnRlciwgcG9zaXRpb24sIHBvc2l0aW9uKTsKICAgICAgICAgIGNvbnN0IGNhcnRvZ3JhcGhpYzIgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMoCiAgICAgICAgICAgIHBvc2l0aW9uLAogICAgICAgICAgICBwcm9qZWN0VG8yRENhcnRvZ3JhcGhpY1NjcmF0Y2gKICAgICAgICAgICk7CiAgICAgICAgICBwcm9qZWN0aW9uLnByb2plY3QoY2FydG9ncmFwaGljMiwgcG9zaXRpb24pOwogICAgICAgIH0KICAgICAgICByZXN1bHQgPSBCb3VuZGluZ1NwaGVyZS5mcm9tUG9pbnRzKHBvc2l0aW9ucywgcmVzdWx0KTsKICAgICAgICBjZW50ZXIgPSByZXN1bHQuY2VudGVyOwogICAgICAgIGNvbnN0IHggPSBjZW50ZXIueDsKICAgICAgICBjb25zdCB5ID0gY2VudGVyLnk7CiAgICAgICAgY29uc3QgeiA9IGNlbnRlci56OwogICAgICAgIGNlbnRlci54ID0gejsKICAgICAgICBjZW50ZXIueSA9IHg7CiAgICAgICAgY2VudGVyLnogPSB5OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nU3BoZXJlLmlzT2NjbHVkZWQgPSBmdW5jdGlvbihzcGhlcmUsIG9jY2x1ZGVyKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzcGhlcmUiLCBzcGhlcmUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgib2NjbHVkZXIiLCBvY2NsdWRlcik7CiAgICAgICAgcmV0dXJuICFvY2NsdWRlci5pc0JvdW5kaW5nU3BoZXJlVmlzaWJsZShzcGhlcmUpOwogICAgICB9OwogICAgICBCb3VuZGluZ1NwaGVyZS5lcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiBDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzKGxlZnQuY2VudGVyLCByaWdodC5jZW50ZXIpICYmIGxlZnQucmFkaXVzID09PSByaWdodC5yYWRpdXM7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nU3BoZXJlLnByb3RvdHlwZS5pbnRlcnNlY3RQbGFuZSA9IGZ1bmN0aW9uKHBsYW5lKSB7CiAgICAgICAgcmV0dXJuIEJvdW5kaW5nU3BoZXJlLmludGVyc2VjdFBsYW5lKHRoaXMsIHBsYW5lKTsKICAgICAgfTsKICAgICAgQm91bmRpbmdTcGhlcmUucHJvdG90eXBlLmRpc3RhbmNlU3F1YXJlZFRvID0gZnVuY3Rpb24oY2FydGVzaWFuMTEpIHsKICAgICAgICByZXR1cm4gQm91bmRpbmdTcGhlcmUuZGlzdGFuY2VTcXVhcmVkVG8odGhpcywgY2FydGVzaWFuMTEpOwogICAgICB9OwogICAgICBCb3VuZGluZ1NwaGVyZS5wcm90b3R5cGUuY29tcHV0ZVBsYW5lRGlzdGFuY2VzID0gZnVuY3Rpb24ocG9zaXRpb24sIGRpcmVjdGlvbjIsIHJlc3VsdCkgewogICAgICAgIHJldHVybiBCb3VuZGluZ1NwaGVyZS5jb21wdXRlUGxhbmVEaXN0YW5jZXMoCiAgICAgICAgICB0aGlzLAogICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICBkaXJlY3Rpb24yLAogICAgICAgICAgcmVzdWx0CiAgICAgICAgKTsKICAgICAgfTsKICAgICAgQm91bmRpbmdTcGhlcmUucHJvdG90eXBlLmlzT2NjbHVkZWQgPSBmdW5jdGlvbihvY2NsdWRlcikgewogICAgICAgIHJldHVybiBCb3VuZGluZ1NwaGVyZS5pc09jY2x1ZGVkKHRoaXMsIG9jY2x1ZGVyKTsKICAgICAgfTsKICAgICAgQm91bmRpbmdTcGhlcmUucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uKHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIEJvdW5kaW5nU3BoZXJlLmVxdWFscyh0aGlzLCByaWdodCk7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nU3BoZXJlLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAgIHJldHVybiBCb3VuZGluZ1NwaGVyZS5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBCb3VuZGluZ1NwaGVyZS5wcm90b3R5cGUudm9sdW1lID0gZnVuY3Rpb24oKSB7CiAgICAgICAgY29uc3QgcmFkaXVzID0gdGhpcy5yYWRpdXM7CiAgICAgICAgcmV0dXJuIHZvbHVtZUNvbnN0YW50ICogcmFkaXVzICogcmFkaXVzICogcmFkaXVzOwogICAgICB9OwogICAgICBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0ID0gQm91bmRpbmdTcGhlcmU7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9XZWJHTENvbnN0YW50cy5qcwogIHZhciBXZWJHTENvbnN0YW50cywgV2ViR0xDb25zdGFudHNfZGVmYXVsdDsKICB2YXIgaW5pdF9XZWJHTENvbnN0YW50cyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvV2ViR0xDb25zdGFudHMuanMiKCkgewogICAgICBXZWJHTENvbnN0YW50cyA9IHsKICAgICAgICBERVBUSF9CVUZGRVJfQklUOiAyNTYsCiAgICAgICAgU1RFTkNJTF9CVUZGRVJfQklUOiAxMDI0LAogICAgICAgIENPTE9SX0JVRkZFUl9CSVQ6IDE2Mzg0LAogICAgICAgIFBPSU5UUzogMCwKICAgICAgICBMSU5FUzogMSwKICAgICAgICBMSU5FX0xPT1A6IDIsCiAgICAgICAgTElORV9TVFJJUDogMywKICAgICAgICBUUklBTkdMRVM6IDQsCiAgICAgICAgVFJJQU5HTEVfU1RSSVA6IDUsCiAgICAgICAgVFJJQU5HTEVfRkFOOiA2LAogICAgICAgIFpFUk86IDAsCiAgICAgICAgT05FOiAxLAogICAgICAgIFNSQ19DT0xPUjogNzY4LAogICAgICAgIE9ORV9NSU5VU19TUkNfQ09MT1I6IDc2OSwKICAgICAgICBTUkNfQUxQSEE6IDc3MCwKICAgICAgICBPTkVfTUlOVVNfU1JDX0FMUEhBOiA3NzEsCiAgICAgICAgRFNUX0FMUEhBOiA3NzIsCiAgICAgICAgT05FX01JTlVTX0RTVF9BTFBIQTogNzczLAogICAgICAgIERTVF9DT0xPUjogNzc0LAogICAgICAgIE9ORV9NSU5VU19EU1RfQ09MT1I6IDc3NSwKICAgICAgICBTUkNfQUxQSEFfU0FUVVJBVEU6IDc3NiwKICAgICAgICBGVU5DX0FERDogMzI3NzQsCiAgICAgICAgQkxFTkRfRVFVQVRJT046IDMyNzc3LAogICAgICAgIEJMRU5EX0VRVUFUSU9OX1JHQjogMzI3NzcsCiAgICAgICAgLy8gc2FtZSBhcyBCTEVORF9FUVVBVElPTgogICAgICAgIEJMRU5EX0VRVUFUSU9OX0FMUEhBOiAzNDg3NywKICAgICAgICBGVU5DX1NVQlRSQUNUOiAzMjc3OCwKICAgICAgICBGVU5DX1JFVkVSU0VfU1VCVFJBQ1Q6IDMyNzc5LAogICAgICAgIEJMRU5EX0RTVF9SR0I6IDMyOTY4LAogICAgICAgIEJMRU5EX1NSQ19SR0I6IDMyOTY5LAogICAgICAgIEJMRU5EX0RTVF9BTFBIQTogMzI5NzAsCiAgICAgICAgQkxFTkRfU1JDX0FMUEhBOiAzMjk3MSwKICAgICAgICBDT05TVEFOVF9DT0xPUjogMzI3NjksCiAgICAgICAgT05FX01JTlVTX0NPTlNUQU5UX0NPTE9SOiAzMjc3MCwKICAgICAgICBDT05TVEFOVF9BTFBIQTogMzI3NzEsCiAgICAgICAgT05FX01JTlVTX0NPTlNUQU5UX0FMUEhBOiAzMjc3MiwKICAgICAgICBCTEVORF9DT0xPUjogMzI3NzMsCiAgICAgICAgQVJSQVlfQlVGRkVSOiAzNDk2MiwKICAgICAgICBFTEVNRU5UX0FSUkFZX0JVRkZFUjogMzQ5NjMsCiAgICAgICAgQVJSQVlfQlVGRkVSX0JJTkRJTkc6IDM0OTY0LAogICAgICAgIEVMRU1FTlRfQVJSQVlfQlVGRkVSX0JJTkRJTkc6IDM0OTY1LAogICAgICAgIFNUUkVBTV9EUkFXOiAzNTA0MCwKICAgICAgICBTVEFUSUNfRFJBVzogMzUwNDQsCiAgICAgICAgRFlOQU1JQ19EUkFXOiAzNTA0OCwKICAgICAgICBCVUZGRVJfU0laRTogMzQ2NjAsCiAgICAgICAgQlVGRkVSX1VTQUdFOiAzNDY2MSwKICAgICAgICBDVVJSRU5UX1ZFUlRFWF9BVFRSSUI6IDM0MzQyLAogICAgICAgIEZST05UOiAxMDI4LAogICAgICAgIEJBQ0s6IDEwMjksCiAgICAgICAgRlJPTlRfQU5EX0JBQ0s6IDEwMzIsCiAgICAgICAgQ1VMTF9GQUNFOiAyODg0LAogICAgICAgIEJMRU5EOiAzMDQyLAogICAgICAgIERJVEhFUjogMzAyNCwKICAgICAgICBTVEVOQ0lMX1RFU1Q6IDI5NjAsCiAgICAgICAgREVQVEhfVEVTVDogMjkyOSwKICAgICAgICBTQ0lTU09SX1RFU1Q6IDMwODksCiAgICAgICAgUE9MWUdPTl9PRkZTRVRfRklMTDogMzI4MjMsCiAgICAgICAgU0FNUExFX0FMUEhBX1RPX0NPVkVSQUdFOiAzMjkyNiwKICAgICAgICBTQU1QTEVfQ09WRVJBR0U6IDMyOTI4LAogICAgICAgIE5PX0VSUk9SOiAwLAogICAgICAgIElOVkFMSURfRU5VTTogMTI4MCwKICAgICAgICBJTlZBTElEX1ZBTFVFOiAxMjgxLAogICAgICAgIElOVkFMSURfT1BFUkFUSU9OOiAxMjgyLAogICAgICAgIE9VVF9PRl9NRU1PUlk6IDEyODUsCiAgICAgICAgQ1c6IDIzMDQsCiAgICAgICAgQ0NXOiAyMzA1LAogICAgICAgIExJTkVfV0lEVEg6IDI4NDksCiAgICAgICAgQUxJQVNFRF9QT0lOVF9TSVpFX1JBTkdFOiAzMzkwMSwKICAgICAgICBBTElBU0VEX0xJTkVfV0lEVEhfUkFOR0U6IDMzOTAyLAogICAgICAgIENVTExfRkFDRV9NT0RFOiAyODg1LAogICAgICAgIEZST05UX0ZBQ0U6IDI4ODYsCiAgICAgICAgREVQVEhfUkFOR0U6IDI5MjgsCiAgICAgICAgREVQVEhfV1JJVEVNQVNLOiAyOTMwLAogICAgICAgIERFUFRIX0NMRUFSX1ZBTFVFOiAyOTMxLAogICAgICAgIERFUFRIX0ZVTkM6IDI5MzIsCiAgICAgICAgU1RFTkNJTF9DTEVBUl9WQUxVRTogMjk2MSwKICAgICAgICBTVEVOQ0lMX0ZVTkM6IDI5NjIsCiAgICAgICAgU1RFTkNJTF9GQUlMOiAyOTY0LAogICAgICAgIFNURU5DSUxfUEFTU19ERVBUSF9GQUlMOiAyOTY1LAogICAgICAgIFNURU5DSUxfUEFTU19ERVBUSF9QQVNTOiAyOTY2LAogICAgICAgIFNURU5DSUxfUkVGOiAyOTY3LAogICAgICAgIFNURU5DSUxfVkFMVUVfTUFTSzogMjk2MywKICAgICAgICBTVEVOQ0lMX1dSSVRFTUFTSzogMjk2OCwKICAgICAgICBTVEVOQ0lMX0JBQ0tfRlVOQzogMzQ4MTYsCiAgICAgICAgU1RFTkNJTF9CQUNLX0ZBSUw6IDM0ODE3LAogICAgICAgIFNURU5DSUxfQkFDS19QQVNTX0RFUFRIX0ZBSUw6IDM0ODE4LAogICAgICAgIFNURU5DSUxfQkFDS19QQVNTX0RFUFRIX1BBU1M6IDM0ODE5LAogICAgICAgIFNURU5DSUxfQkFDS19SRUY6IDM2MDAzLAogICAgICAgIFNURU5DSUxfQkFDS19WQUxVRV9NQVNLOiAzNjAwNCwKICAgICAgICBTVEVOQ0lMX0JBQ0tfV1JJVEVNQVNLOiAzNjAwNSwKICAgICAgICBWSUVXUE9SVDogMjk3OCwKICAgICAgICBTQ0lTU09SX0JPWDogMzA4OCwKICAgICAgICBDT0xPUl9DTEVBUl9WQUxVRTogMzEwNiwKICAgICAgICBDT0xPUl9XUklURU1BU0s6IDMxMDcsCiAgICAgICAgVU5QQUNLX0FMSUdOTUVOVDogMzMxNywKICAgICAgICBQQUNLX0FMSUdOTUVOVDogMzMzMywKICAgICAgICBNQVhfVEVYVFVSRV9TSVpFOiAzMzc5LAogICAgICAgIE1BWF9WSUVXUE9SVF9ESU1TOiAzMzg2LAogICAgICAgIFNVQlBJWEVMX0JJVFM6IDM0MDgsCiAgICAgICAgUkVEX0JJVFM6IDM0MTAsCiAgICAgICAgR1JFRU5fQklUUzogMzQxMSwKICAgICAgICBCTFVFX0JJVFM6IDM0MTIsCiAgICAgICAgQUxQSEFfQklUUzogMzQxMywKICAgICAgICBERVBUSF9CSVRTOiAzNDE0LAogICAgICAgIFNURU5DSUxfQklUUzogMzQxNSwKICAgICAgICBQT0xZR09OX09GRlNFVF9VTklUUzogMTA3NTIsCiAgICAgICAgUE9MWUdPTl9PRkZTRVRfRkFDVE9SOiAzMjgyNCwKICAgICAgICBURVhUVVJFX0JJTkRJTkdfMkQ6IDMyODczLAogICAgICAgIFNBTVBMRV9CVUZGRVJTOiAzMjkzNiwKICAgICAgICBTQU1QTEVTOiAzMjkzNywKICAgICAgICBTQU1QTEVfQ09WRVJBR0VfVkFMVUU6IDMyOTM4LAogICAgICAgIFNBTVBMRV9DT1ZFUkFHRV9JTlZFUlQ6IDMyOTM5LAogICAgICAgIENPTVBSRVNTRURfVEVYVFVSRV9GT1JNQVRTOiAzNDQ2NywKICAgICAgICBET05UX0NBUkU6IDQzNTIsCiAgICAgICAgRkFTVEVTVDogNDM1MywKICAgICAgICBOSUNFU1Q6IDQzNTQsCiAgICAgICAgR0VORVJBVEVfTUlQTUFQX0hJTlQ6IDMzMTcwLAogICAgICAgIEJZVEU6IDUxMjAsCiAgICAgICAgVU5TSUdORURfQllURTogNTEyMSwKICAgICAgICBTSE9SVDogNTEyMiwKICAgICAgICBVTlNJR05FRF9TSE9SVDogNTEyMywKICAgICAgICBJTlQ6IDUxMjQsCiAgICAgICAgVU5TSUdORURfSU5UOiA1MTI1LAogICAgICAgIEZMT0FUOiA1MTI2LAogICAgICAgIERFUFRIX0NPTVBPTkVOVDogNjQwMiwKICAgICAgICBBTFBIQTogNjQwNiwKICAgICAgICBSR0I6IDY0MDcsCiAgICAgICAgUkdCQTogNjQwOCwKICAgICAgICBMVU1JTkFOQ0U6IDY0MDksCiAgICAgICAgTFVNSU5BTkNFX0FMUEhBOiA2NDEwLAogICAgICAgIFVOU0lHTkVEX1NIT1JUXzRfNF80XzQ6IDMyODE5LAogICAgICAgIFVOU0lHTkVEX1NIT1JUXzVfNV81XzE6IDMyODIwLAogICAgICAgIFVOU0lHTkVEX1NIT1JUXzVfNl81OiAzMzYzNSwKICAgICAgICBGUkFHTUVOVF9TSEFERVI6IDM1NjMyLAogICAgICAgIFZFUlRFWF9TSEFERVI6IDM1NjMzLAogICAgICAgIE1BWF9WRVJURVhfQVRUUklCUzogMzQ5MjEsCiAgICAgICAgTUFYX1ZFUlRFWF9VTklGT1JNX1ZFQ1RPUlM6IDM2MzQ3LAogICAgICAgIE1BWF9WQVJZSU5HX1ZFQ1RPUlM6IDM2MzQ4LAogICAgICAgIE1BWF9DT01CSU5FRF9URVhUVVJFX0lNQUdFX1VOSVRTOiAzNTY2MSwKICAgICAgICBNQVhfVkVSVEVYX1RFWFRVUkVfSU1BR0VfVU5JVFM6IDM1NjYwLAogICAgICAgIE1BWF9URVhUVVJFX0lNQUdFX1VOSVRTOiAzNDkzMCwKICAgICAgICBNQVhfRlJBR01FTlRfVU5JRk9STV9WRUNUT1JTOiAzNjM0OSwKICAgICAgICBTSEFERVJfVFlQRTogMzU2NjMsCiAgICAgICAgREVMRVRFX1NUQVRVUzogMzU3MTIsCiAgICAgICAgTElOS19TVEFUVVM6IDM1NzE0LAogICAgICAgIFZBTElEQVRFX1NUQVRVUzogMzU3MTUsCiAgICAgICAgQVRUQUNIRURfU0hBREVSUzogMzU3MTcsCiAgICAgICAgQUNUSVZFX1VOSUZPUk1TOiAzNTcxOCwKICAgICAgICBBQ1RJVkVfQVRUUklCVVRFUzogMzU3MjEsCiAgICAgICAgU0hBRElOR19MQU5HVUFHRV9WRVJTSU9OOiAzNTcyNCwKICAgICAgICBDVVJSRU5UX1BST0dSQU06IDM1NzI1LAogICAgICAgIE5FVkVSOiA1MTIsCiAgICAgICAgTEVTUzogNTEzLAogICAgICAgIEVRVUFMOiA1MTQsCiAgICAgICAgTEVRVUFMOiA1MTUsCiAgICAgICAgR1JFQVRFUjogNTE2LAogICAgICAgIE5PVEVRVUFMOiA1MTcsCiAgICAgICAgR0VRVUFMOiA1MTgsCiAgICAgICAgQUxXQVlTOiA1MTksCiAgICAgICAgS0VFUDogNzY4MCwKICAgICAgICBSRVBMQUNFOiA3NjgxLAogICAgICAgIElOQ1I6IDc2ODIsCiAgICAgICAgREVDUjogNzY4MywKICAgICAgICBJTlZFUlQ6IDUzODYsCiAgICAgICAgSU5DUl9XUkFQOiAzNDA1NSwKICAgICAgICBERUNSX1dSQVA6IDM0MDU2LAogICAgICAgIFZFTkRPUjogNzkzNiwKICAgICAgICBSRU5ERVJFUjogNzkzNywKICAgICAgICBWRVJTSU9OOiA3OTM4LAogICAgICAgIE5FQVJFU1Q6IDk3MjgsCiAgICAgICAgTElORUFSOiA5NzI5LAogICAgICAgIE5FQVJFU1RfTUlQTUFQX05FQVJFU1Q6IDk5ODQsCiAgICAgICAgTElORUFSX01JUE1BUF9ORUFSRVNUOiA5OTg1LAogICAgICAgIE5FQVJFU1RfTUlQTUFQX0xJTkVBUjogOTk4NiwKICAgICAgICBMSU5FQVJfTUlQTUFQX0xJTkVBUjogOTk4NywKICAgICAgICBURVhUVVJFX01BR19GSUxURVI6IDEwMjQwLAogICAgICAgIFRFWFRVUkVfTUlOX0ZJTFRFUjogMTAyNDEsCiAgICAgICAgVEVYVFVSRV9XUkFQX1M6IDEwMjQyLAogICAgICAgIFRFWFRVUkVfV1JBUF9UOiAxMDI0MywKICAgICAgICBURVhUVVJFXzJEOiAzNTUzLAogICAgICAgIFRFWFRVUkU6IDU4OTAsCiAgICAgICAgVEVYVFVSRV9DVUJFX01BUDogMzQwNjcsCiAgICAgICAgVEVYVFVSRV9CSU5ESU5HX0NVQkVfTUFQOiAzNDA2OCwKICAgICAgICBURVhUVVJFX0NVQkVfTUFQX1BPU0lUSVZFX1g6IDM0MDY5LAogICAgICAgIFRFWFRVUkVfQ1VCRV9NQVBfTkVHQVRJVkVfWDogMzQwNzAsCiAgICAgICAgVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9ZOiAzNDA3MSwKICAgICAgICBURVhUVVJFX0NVQkVfTUFQX05FR0FUSVZFX1k6IDM0MDcyLAogICAgICAgIFRFWFRVUkVfQ1VCRV9NQVBfUE9TSVRJVkVfWjogMzQwNzMsCiAgICAgICAgVEVYVFVSRV9DVUJFX01BUF9ORUdBVElWRV9aOiAzNDA3NCwKICAgICAgICBNQVhfQ1VCRV9NQVBfVEVYVFVSRV9TSVpFOiAzNDA3NiwKICAgICAgICBURVhUVVJFMDogMzM5ODQsCiAgICAgICAgVEVYVFVSRTE6IDMzOTg1LAogICAgICAgIFRFWFRVUkUyOiAzMzk4NiwKICAgICAgICBURVhUVVJFMzogMzM5ODcsCiAgICAgICAgVEVYVFVSRTQ6IDMzOTg4LAogICAgICAgIFRFWFRVUkU1OiAzMzk4OSwKICAgICAgICBURVhUVVJFNjogMzM5OTAsCiAgICAgICAgVEVYVFVSRTc6IDMzOTkxLAogICAgICAgIFRFWFRVUkU4OiAzMzk5MiwKICAgICAgICBURVhUVVJFOTogMzM5OTMsCiAgICAgICAgVEVYVFVSRTEwOiAzMzk5NCwKICAgICAgICBURVhUVVJFMTE6IDMzOTk1LAogICAgICAgIFRFWFRVUkUxMjogMzM5OTYsCiAgICAgICAgVEVYVFVSRTEzOiAzMzk5NywKICAgICAgICBURVhUVVJFMTQ6IDMzOTk4LAogICAgICAgIFRFWFRVUkUxNTogMzM5OTksCiAgICAgICAgVEVYVFVSRTE2OiAzNGUzLAogICAgICAgIFRFWFRVUkUxNzogMzQwMDEsCiAgICAgICAgVEVYVFVSRTE4OiAzNDAwMiwKICAgICAgICBURVhUVVJFMTk6IDM0MDAzLAogICAgICAgIFRFWFRVUkUyMDogMzQwMDQsCiAgICAgICAgVEVYVFVSRTIxOiAzNDAwNSwKICAgICAgICBURVhUVVJFMjI6IDM0MDA2LAogICAgICAgIFRFWFRVUkUyMzogMzQwMDcsCiAgICAgICAgVEVYVFVSRTI0OiAzNDAwOCwKICAgICAgICBURVhUVVJFMjU6IDM0MDA5LAogICAgICAgIFRFWFRVUkUyNjogMzQwMTAsCiAgICAgICAgVEVYVFVSRTI3OiAzNDAxMSwKICAgICAgICBURVhUVVJFMjg6IDM0MDEyLAogICAgICAgIFRFWFRVUkUyOTogMzQwMTMsCiAgICAgICAgVEVYVFVSRTMwOiAzNDAxNCwKICAgICAgICBURVhUVVJFMzE6IDM0MDE1LAogICAgICAgIEFDVElWRV9URVhUVVJFOiAzNDAxNiwKICAgICAgICBSRVBFQVQ6IDEwNDk3LAogICAgICAgIENMQU1QX1RPX0VER0U6IDMzMDcxLAogICAgICAgIE1JUlJPUkVEX1JFUEVBVDogMzM2NDgsCiAgICAgICAgRkxPQVRfVkVDMjogMzU2NjQsCiAgICAgICAgRkxPQVRfVkVDMzogMzU2NjUsCiAgICAgICAgRkxPQVRfVkVDNDogMzU2NjYsCiAgICAgICAgSU5UX1ZFQzI6IDM1NjY3LAogICAgICAgIElOVF9WRUMzOiAzNTY2OCwKICAgICAgICBJTlRfVkVDNDogMzU2NjksCiAgICAgICAgQk9PTDogMzU2NzAsCiAgICAgICAgQk9PTF9WRUMyOiAzNTY3MSwKICAgICAgICBCT09MX1ZFQzM6IDM1NjcyLAogICAgICAgIEJPT0xfVkVDNDogMzU2NzMsCiAgICAgICAgRkxPQVRfTUFUMjogMzU2NzQsCiAgICAgICAgRkxPQVRfTUFUMzogMzU2NzUsCiAgICAgICAgRkxPQVRfTUFUNDogMzU2NzYsCiAgICAgICAgU0FNUExFUl8yRDogMzU2NzgsCiAgICAgICAgU0FNUExFUl9DVUJFOiAzNTY4MCwKICAgICAgICBWRVJURVhfQVRUUklCX0FSUkFZX0VOQUJMRUQ6IDM0MzM4LAogICAgICAgIFZFUlRFWF9BVFRSSUJfQVJSQVlfU0laRTogMzQzMzksCiAgICAgICAgVkVSVEVYX0FUVFJJQl9BUlJBWV9TVFJJREU6IDM0MzQwLAogICAgICAgIFZFUlRFWF9BVFRSSUJfQVJSQVlfVFlQRTogMzQzNDEsCiAgICAgICAgVkVSVEVYX0FUVFJJQl9BUlJBWV9OT1JNQUxJWkVEOiAzNDkyMiwKICAgICAgICBWRVJURVhfQVRUUklCX0FSUkFZX1BPSU5URVI6IDM0MzczLAogICAgICAgIFZFUlRFWF9BVFRSSUJfQVJSQVlfQlVGRkVSX0JJTkRJTkc6IDM0OTc1LAogICAgICAgIElNUExFTUVOVEFUSU9OX0NPTE9SX1JFQURfVFlQRTogMzU3MzgsCiAgICAgICAgSU1QTEVNRU5UQVRJT05fQ09MT1JfUkVBRF9GT1JNQVQ6IDM1NzM5LAogICAgICAgIENPTVBJTEVfU1RBVFVTOiAzNTcxMywKICAgICAgICBMT1dfRkxPQVQ6IDM2MzM2LAogICAgICAgIE1FRElVTV9GTE9BVDogMzYzMzcsCiAgICAgICAgSElHSF9GTE9BVDogMzYzMzgsCiAgICAgICAgTE9XX0lOVDogMzYzMzksCiAgICAgICAgTUVESVVNX0lOVDogMzYzNDAsCiAgICAgICAgSElHSF9JTlQ6IDM2MzQxLAogICAgICAgIEZSQU1FQlVGRkVSOiAzNjE2MCwKICAgICAgICBSRU5ERVJCVUZGRVI6IDM2MTYxLAogICAgICAgIFJHQkE0OiAzMjg1NCwKICAgICAgICBSR0I1X0ExOiAzMjg1NSwKICAgICAgICBSR0I1NjU6IDM2MTk0LAogICAgICAgIERFUFRIX0NPTVBPTkVOVDE2OiAzMzE4OSwKICAgICAgICBTVEVOQ0lMX0lOREVYOiA2NDAxLAogICAgICAgIFNURU5DSUxfSU5ERVg4OiAzNjE2OCwKICAgICAgICBERVBUSF9TVEVOQ0lMOiAzNDA0MSwKICAgICAgICBSRU5ERVJCVUZGRVJfV0lEVEg6IDM2MTYyLAogICAgICAgIFJFTkRFUkJVRkZFUl9IRUlHSFQ6IDM2MTYzLAogICAgICAgIFJFTkRFUkJVRkZFUl9JTlRFUk5BTF9GT1JNQVQ6IDM2MTY0LAogICAgICAgIFJFTkRFUkJVRkZFUl9SRURfU0laRTogMzYxNzYsCiAgICAgICAgUkVOREVSQlVGRkVSX0dSRUVOX1NJWkU6IDM2MTc3LAogICAgICAgIFJFTkRFUkJVRkZFUl9CTFVFX1NJWkU6IDM2MTc4LAogICAgICAgIFJFTkRFUkJVRkZFUl9BTFBIQV9TSVpFOiAzNjE3OSwKICAgICAgICBSRU5ERVJCVUZGRVJfREVQVEhfU0laRTogMzYxODAsCiAgICAgICAgUkVOREVSQlVGRkVSX1NURU5DSUxfU0laRTogMzYxODEsCiAgICAgICAgRlJBTUVCVUZGRVJfQVRUQUNITUVOVF9PQkpFQ1RfVFlQRTogMzYwNDgsCiAgICAgICAgRlJBTUVCVUZGRVJfQVRUQUNITUVOVF9PQkpFQ1RfTkFNRTogMzYwNDksCiAgICAgICAgRlJBTUVCVUZGRVJfQVRUQUNITUVOVF9URVhUVVJFX0xFVkVMOiAzNjA1MCwKICAgICAgICBGUkFNRUJVRkZFUl9BVFRBQ0hNRU5UX1RFWFRVUkVfQ1VCRV9NQVBfRkFDRTogMzYwNTEsCiAgICAgICAgQ09MT1JfQVRUQUNITUVOVDA6IDM2MDY0LAogICAgICAgIERFUFRIX0FUVEFDSE1FTlQ6IDM2MDk2LAogICAgICAgIFNURU5DSUxfQVRUQUNITUVOVDogMzYxMjgsCiAgICAgICAgREVQVEhfU1RFTkNJTF9BVFRBQ0hNRU5UOiAzMzMwNiwKICAgICAgICBOT05FOiAwLAogICAgICAgIEZSQU1FQlVGRkVSX0NPTVBMRVRFOiAzNjA1MywKICAgICAgICBGUkFNRUJVRkZFUl9JTkNPTVBMRVRFX0FUVEFDSE1FTlQ6IDM2MDU0LAogICAgICAgIEZSQU1FQlVGRkVSX0lOQ09NUExFVEVfTUlTU0lOR19BVFRBQ0hNRU5UOiAzNjA1NSwKICAgICAgICBGUkFNRUJVRkZFUl9JTkNPTVBMRVRFX0RJTUVOU0lPTlM6IDM2MDU3LAogICAgICAgIEZSQU1FQlVGRkVSX1VOU1VQUE9SVEVEOiAzNjA2MSwKICAgICAgICBGUkFNRUJVRkZFUl9CSU5ESU5HOiAzNjAwNiwKICAgICAgICBSRU5ERVJCVUZGRVJfQklORElORzogMzYwMDcsCiAgICAgICAgTUFYX1JFTkRFUkJVRkZFUl9TSVpFOiAzNDAyNCwKICAgICAgICBJTlZBTElEX0ZSQU1FQlVGRkVSX09QRVJBVElPTjogMTI4NiwKICAgICAgICBVTlBBQ0tfRkxJUF9ZX1dFQkdMOiAzNzQ0MCwKICAgICAgICBVTlBBQ0tfUFJFTVVMVElQTFlfQUxQSEFfV0VCR0w6IDM3NDQxLAogICAgICAgIENPTlRFWFRfTE9TVF9XRUJHTDogMzc0NDIsCiAgICAgICAgVU5QQUNLX0NPTE9SU1BBQ0VfQ09OVkVSU0lPTl9XRUJHTDogMzc0NDMsCiAgICAgICAgQlJPV1NFUl9ERUZBVUxUX1dFQkdMOiAzNzQ0NCwKICAgICAgICAvLyBXRUJHTF9jb21wcmVzc2VkX3RleHR1cmVfczN0YwogICAgICAgIENPTVBSRVNTRURfUkdCX1MzVENfRFhUMV9FWFQ6IDMzNzc2LAogICAgICAgIENPTVBSRVNTRURfUkdCQV9TM1RDX0RYVDFfRVhUOiAzMzc3NywKICAgICAgICBDT01QUkVTU0VEX1JHQkFfUzNUQ19EWFQzX0VYVDogMzM3NzgsCiAgICAgICAgQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUNV9FWFQ6IDMzNzc5LAogICAgICAgIC8vIFdFQkdMX2NvbXByZXNzZWRfdGV4dHVyZV9wdnJ0YwogICAgICAgIENPTVBSRVNTRURfUkdCX1BWUlRDXzRCUFBWMV9JTUc6IDM1ODQwLAogICAgICAgIENPTVBSRVNTRURfUkdCX1BWUlRDXzJCUFBWMV9JTUc6IDM1ODQxLAogICAgICAgIENPTVBSRVNTRURfUkdCQV9QVlJUQ180QlBQVjFfSU1HOiAzNTg0MiwKICAgICAgICBDT01QUkVTU0VEX1JHQkFfUFZSVENfMkJQUFYxX0lNRzogMzU4NDMsCiAgICAgICAgLy8gV0VCR0xfY29tcHJlc3NlZF90ZXh0dXJlX2FzdGMKICAgICAgICBDT01QUkVTU0VEX1JHQkFfQVNUQ180eDRfV0VCR0w6IDM3ODA4LAogICAgICAgIC8vIFdFQkdMX2NvbXByZXNzZWRfdGV4dHVyZV9ldGMxCiAgICAgICAgQ09NUFJFU1NFRF9SR0JfRVRDMV9XRUJHTDogMzYxOTYsCiAgICAgICAgLy8gRVhUX3RleHR1cmVfY29tcHJlc3Npb25fYnB0YwogICAgICAgIENPTVBSRVNTRURfUkdCQV9CUFRDX1VOT1JNOiAzNjQ5MiwKICAgICAgICAvLyBFWFRfY29sb3JfYnVmZmVyX2hhbGZfZmxvYXQKICAgICAgICBIQUxGX0ZMT0FUX09FUzogMzYxOTMsCiAgICAgICAgLy8gRGVza3RvcCBPcGVuR0wKICAgICAgICBET1VCTEU6IDUxMzAsCiAgICAgICAgLy8gV2ViR0wgMgogICAgICAgIFJFQURfQlVGRkVSOiAzMDc0LAogICAgICAgIFVOUEFDS19ST1dfTEVOR1RIOiAzMzE0LAogICAgICAgIFVOUEFDS19TS0lQX1JPV1M6IDMzMTUsCiAgICAgICAgVU5QQUNLX1NLSVBfUElYRUxTOiAzMzE2LAogICAgICAgIFBBQ0tfUk9XX0xFTkdUSDogMzMzMCwKICAgICAgICBQQUNLX1NLSVBfUk9XUzogMzMzMSwKICAgICAgICBQQUNLX1NLSVBfUElYRUxTOiAzMzMyLAogICAgICAgIENPTE9SOiA2MTQ0LAogICAgICAgIERFUFRIOiA2MTQ1LAogICAgICAgIFNURU5DSUw6IDYxNDYsCiAgICAgICAgUkVEOiA2NDAzLAogICAgICAgIFJHQjg6IDMyODQ5LAogICAgICAgIFJHQkE4OiAzMjg1NiwKICAgICAgICBSR0IxMF9BMjogMzI4NTcsCiAgICAgICAgVEVYVFVSRV9CSU5ESU5HXzNEOiAzMjg3NCwKICAgICAgICBVTlBBQ0tfU0tJUF9JTUFHRVM6IDMyODc3LAogICAgICAgIFVOUEFDS19JTUFHRV9IRUlHSFQ6IDMyODc4LAogICAgICAgIFRFWFRVUkVfM0Q6IDMyODc5LAogICAgICAgIFRFWFRVUkVfV1JBUF9SOiAzMjg4MiwKICAgICAgICBNQVhfM0RfVEVYVFVSRV9TSVpFOiAzMjg4MywKICAgICAgICBVTlNJR05FRF9JTlRfMl8xMF8xMF8xMF9SRVY6IDMzNjQwLAogICAgICAgIE1BWF9FTEVNRU5UU19WRVJUSUNFUzogMzNlMywKICAgICAgICBNQVhfRUxFTUVOVFNfSU5ESUNFUzogMzMwMDEsCiAgICAgICAgVEVYVFVSRV9NSU5fTE9EOiAzMzA4MiwKICAgICAgICBURVhUVVJFX01BWF9MT0Q6IDMzMDgzLAogICAgICAgIFRFWFRVUkVfQkFTRV9MRVZFTDogMzMwODQsCiAgICAgICAgVEVYVFVSRV9NQVhfTEVWRUw6IDMzMDg1LAogICAgICAgIE1JTjogMzI3NzUsCiAgICAgICAgTUFYOiAzMjc3NiwKICAgICAgICBERVBUSF9DT01QT05FTlQyNDogMzMxOTAsCiAgICAgICAgTUFYX1RFWFRVUkVfTE9EX0JJQVM6IDM0MDQ1LAogICAgICAgIFRFWFRVUkVfQ09NUEFSRV9NT0RFOiAzNDg5MiwKICAgICAgICBURVhUVVJFX0NPTVBBUkVfRlVOQzogMzQ4OTMsCiAgICAgICAgQ1VSUkVOVF9RVUVSWTogMzQ5MTcsCiAgICAgICAgUVVFUllfUkVTVUxUOiAzNDkxOCwKICAgICAgICBRVUVSWV9SRVNVTFRfQVZBSUxBQkxFOiAzNDkxOSwKICAgICAgICBTVFJFQU1fUkVBRDogMzUwNDEsCiAgICAgICAgU1RSRUFNX0NPUFk6IDM1MDQyLAogICAgICAgIFNUQVRJQ19SRUFEOiAzNTA0NSwKICAgICAgICBTVEFUSUNfQ09QWTogMzUwNDYsCiAgICAgICAgRFlOQU1JQ19SRUFEOiAzNTA0OSwKICAgICAgICBEWU5BTUlDX0NPUFk6IDM1MDUwLAogICAgICAgIE1BWF9EUkFXX0JVRkZFUlM6IDM0ODUyLAogICAgICAgIERSQVdfQlVGRkVSMDogMzQ4NTMsCiAgICAgICAgRFJBV19CVUZGRVIxOiAzNDg1NCwKICAgICAgICBEUkFXX0JVRkZFUjI6IDM0ODU1LAogICAgICAgIERSQVdfQlVGRkVSMzogMzQ4NTYsCiAgICAgICAgRFJBV19CVUZGRVI0OiAzNDg1NywKICAgICAgICBEUkFXX0JVRkZFUjU6IDM0ODU4LAogICAgICAgIERSQVdfQlVGRkVSNjogMzQ4NTksCiAgICAgICAgRFJBV19CVUZGRVI3OiAzNDg2MCwKICAgICAgICBEUkFXX0JVRkZFUjg6IDM0ODYxLAogICAgICAgIERSQVdfQlVGRkVSOTogMzQ4NjIsCiAgICAgICAgRFJBV19CVUZGRVIxMDogMzQ4NjMsCiAgICAgICAgRFJBV19CVUZGRVIxMTogMzQ4NjQsCiAgICAgICAgRFJBV19CVUZGRVIxMjogMzQ4NjUsCiAgICAgICAgRFJBV19CVUZGRVIxMzogMzQ4NjYsCiAgICAgICAgRFJBV19CVUZGRVIxNDogMzQ4NjcsCiAgICAgICAgRFJBV19CVUZGRVIxNTogMzQ4NjgsCiAgICAgICAgTUFYX0ZSQUdNRU5UX1VOSUZPUk1fQ09NUE9ORU5UUzogMzU2NTcsCiAgICAgICAgTUFYX1ZFUlRFWF9VTklGT1JNX0NPTVBPTkVOVFM6IDM1NjU4LAogICAgICAgIFNBTVBMRVJfM0Q6IDM1Njc5LAogICAgICAgIFNBTVBMRVJfMkRfU0hBRE9XOiAzNTY4MiwKICAgICAgICBGUkFHTUVOVF9TSEFERVJfREVSSVZBVElWRV9ISU5UOiAzNTcyMywKICAgICAgICBQSVhFTF9QQUNLX0JVRkZFUjogMzUwNTEsCiAgICAgICAgUElYRUxfVU5QQUNLX0JVRkZFUjogMzUwNTIsCiAgICAgICAgUElYRUxfUEFDS19CVUZGRVJfQklORElORzogMzUwNTMsCiAgICAgICAgUElYRUxfVU5QQUNLX0JVRkZFUl9CSU5ESU5HOiAzNTA1NSwKICAgICAgICBGTE9BVF9NQVQyeDM6IDM1Njg1LAogICAgICAgIEZMT0FUX01BVDJ4NDogMzU2ODYsCiAgICAgICAgRkxPQVRfTUFUM3gyOiAzNTY4NywKICAgICAgICBGTE9BVF9NQVQzeDQ6IDM1Njg4LAogICAgICAgIEZMT0FUX01BVDR4MjogMzU2ODksCiAgICAgICAgRkxPQVRfTUFUNHgzOiAzNTY5MCwKICAgICAgICBTUkdCOiAzNTkwNCwKICAgICAgICBTUkdCODogMzU5MDUsCiAgICAgICAgU1JHQjhfQUxQSEE4OiAzNTkwNywKICAgICAgICBDT01QQVJFX1JFRl9UT19URVhUVVJFOiAzNDg5NCwKICAgICAgICBSR0JBMzJGOiAzNDgzNiwKICAgICAgICBSR0IzMkY6IDM0ODM3LAogICAgICAgIFJHQkExNkY6IDM0ODQyLAogICAgICAgIFJHQjE2RjogMzQ4NDMsCiAgICAgICAgVkVSVEVYX0FUVFJJQl9BUlJBWV9JTlRFR0VSOiAzNTA2OSwKICAgICAgICBNQVhfQVJSQVlfVEVYVFVSRV9MQVlFUlM6IDM1MDcxLAogICAgICAgIE1JTl9QUk9HUkFNX1RFWEVMX09GRlNFVDogMzUwNzYsCiAgICAgICAgTUFYX1BST0dSQU1fVEVYRUxfT0ZGU0VUOiAzNTA3NywKICAgICAgICBNQVhfVkFSWUlOR19DT01QT05FTlRTOiAzNTY1OSwKICAgICAgICBURVhUVVJFXzJEX0FSUkFZOiAzNTg2NiwKICAgICAgICBURVhUVVJFX0JJTkRJTkdfMkRfQVJSQVk6IDM1ODY5LAogICAgICAgIFIxMUZfRzExRl9CMTBGOiAzNTg5OCwKICAgICAgICBVTlNJR05FRF9JTlRfMTBGXzExRl8xMUZfUkVWOiAzNTg5OSwKICAgICAgICBSR0I5X0U1OiAzNTkwMSwKICAgICAgICBVTlNJR05FRF9JTlRfNV85XzlfOV9SRVY6IDM1OTAyLAogICAgICAgIFRSQU5TRk9STV9GRUVEQkFDS19CVUZGRVJfTU9ERTogMzU5NjcsCiAgICAgICAgTUFYX1RSQU5TRk9STV9GRUVEQkFDS19TRVBBUkFURV9DT01QT05FTlRTOiAzNTk2OCwKICAgICAgICBUUkFOU0ZPUk1fRkVFREJBQ0tfVkFSWUlOR1M6IDM1OTcxLAogICAgICAgIFRSQU5TRk9STV9GRUVEQkFDS19CVUZGRVJfU1RBUlQ6IDM1OTcyLAogICAgICAgIFRSQU5TRk9STV9GRUVEQkFDS19CVUZGRVJfU0laRTogMzU5NzMsCiAgICAgICAgVFJBTlNGT1JNX0ZFRURCQUNLX1BSSU1JVElWRVNfV1JJVFRFTjogMzU5NzYsCiAgICAgICAgUkFTVEVSSVpFUl9ESVNDQVJEOiAzNTk3NywKICAgICAgICBNQVhfVFJBTlNGT1JNX0ZFRURCQUNLX0lOVEVSTEVBVkVEX0NPTVBPTkVOVFM6IDM1OTc4LAogICAgICAgIE1BWF9UUkFOU0ZPUk1fRkVFREJBQ0tfU0VQQVJBVEVfQVRUUklCUzogMzU5NzksCiAgICAgICAgSU5URVJMRUFWRURfQVRUUklCUzogMzU5ODAsCiAgICAgICAgU0VQQVJBVEVfQVRUUklCUzogMzU5ODEsCiAgICAgICAgVFJBTlNGT1JNX0ZFRURCQUNLX0JVRkZFUjogMzU5ODIsCiAgICAgICAgVFJBTlNGT1JNX0ZFRURCQUNLX0JVRkZFUl9CSU5ESU5HOiAzNTk4MywKICAgICAgICBSR0JBMzJVSTogMzYyMDgsCiAgICAgICAgUkdCMzJVSTogMzYyMDksCiAgICAgICAgUkdCQTE2VUk6IDM2MjE0LAogICAgICAgIFJHQjE2VUk6IDM2MjE1LAogICAgICAgIFJHQkE4VUk6IDM2MjIwLAogICAgICAgIFJHQjhVSTogMzYyMjEsCiAgICAgICAgUkdCQTMySTogMzYyMjYsCiAgICAgICAgUkdCMzJJOiAzNjIyNywKICAgICAgICBSR0JBMTZJOiAzNjIzMiwKICAgICAgICBSR0IxNkk6IDM2MjMzLAogICAgICAgIFJHQkE4STogMzYyMzgsCiAgICAgICAgUkdCOEk6IDM2MjM5LAogICAgICAgIFJFRF9JTlRFR0VSOiAzNjI0NCwKICAgICAgICBSR0JfSU5URUdFUjogMzYyNDgsCiAgICAgICAgUkdCQV9JTlRFR0VSOiAzNjI0OSwKICAgICAgICBTQU1QTEVSXzJEX0FSUkFZOiAzNjI4OSwKICAgICAgICBTQU1QTEVSXzJEX0FSUkFZX1NIQURPVzogMzYyOTIsCiAgICAgICAgU0FNUExFUl9DVUJFX1NIQURPVzogMzYyOTMsCiAgICAgICAgVU5TSUdORURfSU5UX1ZFQzI6IDM2Mjk0LAogICAgICAgIFVOU0lHTkVEX0lOVF9WRUMzOiAzNjI5NSwKICAgICAgICBVTlNJR05FRF9JTlRfVkVDNDogMzYyOTYsCiAgICAgICAgSU5UX1NBTVBMRVJfMkQ6IDM2Mjk4LAogICAgICAgIElOVF9TQU1QTEVSXzNEOiAzNjI5OSwKICAgICAgICBJTlRfU0FNUExFUl9DVUJFOiAzNjMwMCwKICAgICAgICBJTlRfU0FNUExFUl8yRF9BUlJBWTogMzYzMDMsCiAgICAgICAgVU5TSUdORURfSU5UX1NBTVBMRVJfMkQ6IDM2MzA2LAogICAgICAgIFVOU0lHTkVEX0lOVF9TQU1QTEVSXzNEOiAzNjMwNywKICAgICAgICBVTlNJR05FRF9JTlRfU0FNUExFUl9DVUJFOiAzNjMwOCwKICAgICAgICBVTlNJR05FRF9JTlRfU0FNUExFUl8yRF9BUlJBWTogMzYzMTEsCiAgICAgICAgREVQVEhfQ09NUE9ORU5UMzJGOiAzNjAxMiwKICAgICAgICBERVBUSDMyRl9TVEVOQ0lMODogMzYwMTMsCiAgICAgICAgRkxPQVRfMzJfVU5TSUdORURfSU5UXzI0XzhfUkVWOiAzNjI2OSwKICAgICAgICBGUkFNRUJVRkZFUl9BVFRBQ0hNRU5UX0NPTE9SX0VOQ09ESU5HOiAzMzI5NiwKICAgICAgICBGUkFNRUJVRkZFUl9BVFRBQ0hNRU5UX0NPTVBPTkVOVF9UWVBFOiAzMzI5NywKICAgICAgICBGUkFNRUJVRkZFUl9BVFRBQ0hNRU5UX1JFRF9TSVpFOiAzMzI5OCwKICAgICAgICBGUkFNRUJVRkZFUl9BVFRBQ0hNRU5UX0dSRUVOX1NJWkU6IDMzMjk5LAogICAgICAgIEZSQU1FQlVGRkVSX0FUVEFDSE1FTlRfQkxVRV9TSVpFOiAzMzMwMCwKICAgICAgICBGUkFNRUJVRkZFUl9BVFRBQ0hNRU5UX0FMUEhBX1NJWkU6IDMzMzAxLAogICAgICAgIEZSQU1FQlVGRkVSX0FUVEFDSE1FTlRfREVQVEhfU0laRTogMzMzMDIsCiAgICAgICAgRlJBTUVCVUZGRVJfQVRUQUNITUVOVF9TVEVOQ0lMX1NJWkU6IDMzMzAzLAogICAgICAgIEZSQU1FQlVGRkVSX0RFRkFVTFQ6IDMzMzA0LAogICAgICAgIFVOU0lHTkVEX0lOVF8yNF84OiAzNDA0MiwKICAgICAgICBERVBUSDI0X1NURU5DSUw4OiAzNTA1NiwKICAgICAgICBVTlNJR05FRF9OT1JNQUxJWkVEOiAzNTg2MywKICAgICAgICBEUkFXX0ZSQU1FQlVGRkVSX0JJTkRJTkc6IDM2MDA2LAogICAgICAgIC8vIFNhbWUgYXMgRlJBTUVCVUZGRVJfQklORElORwogICAgICAgIFJFQURfRlJBTUVCVUZGRVI6IDM2MDA4LAogICAgICAgIERSQVdfRlJBTUVCVUZGRVI6IDM2MDA5LAogICAgICAgIFJFQURfRlJBTUVCVUZGRVJfQklORElORzogMzYwMTAsCiAgICAgICAgUkVOREVSQlVGRkVSX1NBTVBMRVM6IDM2MDExLAogICAgICAgIEZSQU1FQlVGRkVSX0FUVEFDSE1FTlRfVEVYVFVSRV9MQVlFUjogMzYwNTIsCiAgICAgICAgTUFYX0NPTE9SX0FUVEFDSE1FTlRTOiAzNjA2MywKICAgICAgICBDT0xPUl9BVFRBQ0hNRU5UMTogMzYwNjUsCiAgICAgICAgQ09MT1JfQVRUQUNITUVOVDI6IDM2MDY2LAogICAgICAgIENPTE9SX0FUVEFDSE1FTlQzOiAzNjA2NywKICAgICAgICBDT0xPUl9BVFRBQ0hNRU5UNDogMzYwNjgsCiAgICAgICAgQ09MT1JfQVRUQUNITUVOVDU6IDM2MDY5LAogICAgICAgIENPTE9SX0FUVEFDSE1FTlQ2OiAzNjA3MCwKICAgICAgICBDT0xPUl9BVFRBQ0hNRU5UNzogMzYwNzEsCiAgICAgICAgQ09MT1JfQVRUQUNITUVOVDg6IDM2MDcyLAogICAgICAgIENPTE9SX0FUVEFDSE1FTlQ5OiAzNjA3MywKICAgICAgICBDT0xPUl9BVFRBQ0hNRU5UMTA6IDM2MDc0LAogICAgICAgIENPTE9SX0FUVEFDSE1FTlQxMTogMzYwNzUsCiAgICAgICAgQ09MT1JfQVRUQUNITUVOVDEyOiAzNjA3NiwKICAgICAgICBDT0xPUl9BVFRBQ0hNRU5UMTM6IDM2MDc3LAogICAgICAgIENPTE9SX0FUVEFDSE1FTlQxNDogMzYwNzgsCiAgICAgICAgQ09MT1JfQVRUQUNITUVOVDE1OiAzNjA3OSwKICAgICAgICBGUkFNRUJVRkZFUl9JTkNPTVBMRVRFX01VTFRJU0FNUExFOiAzNjE4MiwKICAgICAgICBNQVhfU0FNUExFUzogMzYxODMsCiAgICAgICAgSEFMRl9GTE9BVDogNTEzMSwKICAgICAgICBSRzogMzMzMTksCiAgICAgICAgUkdfSU5URUdFUjogMzMzMjAsCiAgICAgICAgUjg6IDMzMzIxLAogICAgICAgIFJHODogMzMzMjMsCiAgICAgICAgUjE2RjogMzMzMjUsCiAgICAgICAgUjMyRjogMzMzMjYsCiAgICAgICAgUkcxNkY6IDMzMzI3LAogICAgICAgIFJHMzJGOiAzMzMyOCwKICAgICAgICBSOEk6IDMzMzI5LAogICAgICAgIFI4VUk6IDMzMzMwLAogICAgICAgIFIxNkk6IDMzMzMxLAogICAgICAgIFIxNlVJOiAzMzMzMiwKICAgICAgICBSMzJJOiAzMzMzMywKICAgICAgICBSMzJVSTogMzMzMzQsCiAgICAgICAgUkc4STogMzMzMzUsCiAgICAgICAgUkc4VUk6IDMzMzM2LAogICAgICAgIFJHMTZJOiAzMzMzNywKICAgICAgICBSRzE2VUk6IDMzMzM4LAogICAgICAgIFJHMzJJOiAzMzMzOSwKICAgICAgICBSRzMyVUk6IDMzMzQwLAogICAgICAgIFZFUlRFWF9BUlJBWV9CSU5ESU5HOiAzNDIyOSwKICAgICAgICBSOF9TTk9STTogMzY3NTYsCiAgICAgICAgUkc4X1NOT1JNOiAzNjc1NywKICAgICAgICBSR0I4X1NOT1JNOiAzNjc1OCwKICAgICAgICBSR0JBOF9TTk9STTogMzY3NTksCiAgICAgICAgU0lHTkVEX05PUk1BTElaRUQ6IDM2NzY0LAogICAgICAgIENPUFlfUkVBRF9CVUZGRVI6IDM2NjYyLAogICAgICAgIENPUFlfV1JJVEVfQlVGRkVSOiAzNjY2MywKICAgICAgICBDT1BZX1JFQURfQlVGRkVSX0JJTkRJTkc6IDM2NjYyLAogICAgICAgIC8vIFNhbWUgYXMgQ09QWV9SRUFEX0JVRkZFUgogICAgICAgIENPUFlfV1JJVEVfQlVGRkVSX0JJTkRJTkc6IDM2NjYzLAogICAgICAgIC8vIFNhbWUgYXMgQ09QWV9XUklURV9CVUZGRVIKICAgICAgICBVTklGT1JNX0JVRkZFUjogMzUzNDUsCiAgICAgICAgVU5JRk9STV9CVUZGRVJfQklORElORzogMzUzNjgsCiAgICAgICAgVU5JRk9STV9CVUZGRVJfU1RBUlQ6IDM1MzY5LAogICAgICAgIFVOSUZPUk1fQlVGRkVSX1NJWkU6IDM1MzcwLAogICAgICAgIE1BWF9WRVJURVhfVU5JRk9STV9CTE9DS1M6IDM1MzcxLAogICAgICAgIE1BWF9GUkFHTUVOVF9VTklGT1JNX0JMT0NLUzogMzUzNzMsCiAgICAgICAgTUFYX0NPTUJJTkVEX1VOSUZPUk1fQkxPQ0tTOiAzNTM3NCwKICAgICAgICBNQVhfVU5JRk9STV9CVUZGRVJfQklORElOR1M6IDM1Mzc1LAogICAgICAgIE1BWF9VTklGT1JNX0JMT0NLX1NJWkU6IDM1Mzc2LAogICAgICAgIE1BWF9DT01CSU5FRF9WRVJURVhfVU5JRk9STV9DT01QT05FTlRTOiAzNTM3NywKICAgICAgICBNQVhfQ09NQklORURfRlJBR01FTlRfVU5JRk9STV9DT01QT05FTlRTOiAzNTM3OSwKICAgICAgICBVTklGT1JNX0JVRkZFUl9PRkZTRVRfQUxJR05NRU5UOiAzNTM4MCwKICAgICAgICBBQ1RJVkVfVU5JRk9STV9CTE9DS1M6IDM1MzgyLAogICAgICAgIFVOSUZPUk1fVFlQRTogMzUzODMsCiAgICAgICAgVU5JRk9STV9TSVpFOiAzNTM4NCwKICAgICAgICBVTklGT1JNX0JMT0NLX0lOREVYOiAzNTM4NiwKICAgICAgICBVTklGT1JNX09GRlNFVDogMzUzODcsCiAgICAgICAgVU5JRk9STV9BUlJBWV9TVFJJREU6IDM1Mzg4LAogICAgICAgIFVOSUZPUk1fTUFUUklYX1NUUklERTogMzUzODksCiAgICAgICAgVU5JRk9STV9JU19ST1dfTUFKT1I6IDM1MzkwLAogICAgICAgIFVOSUZPUk1fQkxPQ0tfQklORElORzogMzUzOTEsCiAgICAgICAgVU5JRk9STV9CTE9DS19EQVRBX1NJWkU6IDM1MzkyLAogICAgICAgIFVOSUZPUk1fQkxPQ0tfQUNUSVZFX1VOSUZPUk1TOiAzNTM5NCwKICAgICAgICBVTklGT1JNX0JMT0NLX0FDVElWRV9VTklGT1JNX0lORElDRVM6IDM1Mzk1LAogICAgICAgIFVOSUZPUk1fQkxPQ0tfUkVGRVJFTkNFRF9CWV9WRVJURVhfU0hBREVSOiAzNTM5NiwKICAgICAgICBVTklGT1JNX0JMT0NLX1JFRkVSRU5DRURfQllfRlJBR01FTlRfU0hBREVSOiAzNTM5OCwKICAgICAgICBJTlZBTElEX0lOREVYOiA0Mjk0OTY3Mjk1LAogICAgICAgIE1BWF9WRVJURVhfT1VUUFVUX0NPTVBPTkVOVFM6IDM3MTU0LAogICAgICAgIE1BWF9GUkFHTUVOVF9JTlBVVF9DT01QT05FTlRTOiAzNzE1NywKICAgICAgICBNQVhfU0VSVkVSX1dBSVRfVElNRU9VVDogMzcxMzcsCiAgICAgICAgT0JKRUNUX1RZUEU6IDM3MTM4LAogICAgICAgIFNZTkNfQ09ORElUSU9OOiAzNzEzOSwKICAgICAgICBTWU5DX1NUQVRVUzogMzcxNDAsCiAgICAgICAgU1lOQ19GTEFHUzogMzcxNDEsCiAgICAgICAgU1lOQ19GRU5DRTogMzcxNDIsCiAgICAgICAgU1lOQ19HUFVfQ09NTUFORFNfQ09NUExFVEU6IDM3MTQzLAogICAgICAgIFVOU0lHTkFMRUQ6IDM3MTQ0LAogICAgICAgIFNJR05BTEVEOiAzNzE0NSwKICAgICAgICBBTFJFQURZX1NJR05BTEVEOiAzNzE0NiwKICAgICAgICBUSU1FT1VUX0VYUElSRUQ6IDM3MTQ3LAogICAgICAgIENPTkRJVElPTl9TQVRJU0ZJRUQ6IDM3MTQ4LAogICAgICAgIFdBSVRfRkFJTEVEOiAzNzE0OSwKICAgICAgICBTWU5DX0ZMVVNIX0NPTU1BTkRTX0JJVDogMSwKICAgICAgICBWRVJURVhfQVRUUklCX0FSUkFZX0RJVklTT1I6IDM1MDcwLAogICAgICAgIEFOWV9TQU1QTEVTX1BBU1NFRDogMzU4ODcsCiAgICAgICAgQU5ZX1NBTVBMRVNfUEFTU0VEX0NPTlNFUlZBVElWRTogMzYyMDIsCiAgICAgICAgU0FNUExFUl9CSU5ESU5HOiAzNTA5NywKICAgICAgICBSR0IxMF9BMlVJOiAzNjk3NSwKICAgICAgICBJTlRfMl8xMF8xMF8xMF9SRVY6IDM2MjU1LAogICAgICAgIFRSQU5TRk9STV9GRUVEQkFDSzogMzYzODYsCiAgICAgICAgVFJBTlNGT1JNX0ZFRURCQUNLX1BBVVNFRDogMzYzODcsCiAgICAgICAgVFJBTlNGT1JNX0ZFRURCQUNLX0FDVElWRTogMzYzODgsCiAgICAgICAgVFJBTlNGT1JNX0ZFRURCQUNLX0JJTkRJTkc6IDM2Mzg5LAogICAgICAgIENPTVBSRVNTRURfUjExX0VBQzogMzc0ODgsCiAgICAgICAgQ09NUFJFU1NFRF9TSUdORURfUjExX0VBQzogMzc0ODksCiAgICAgICAgQ09NUFJFU1NFRF9SRzExX0VBQzogMzc0OTAsCiAgICAgICAgQ09NUFJFU1NFRF9TSUdORURfUkcxMV9FQUM6IDM3NDkxLAogICAgICAgIENPTVBSRVNTRURfUkdCOF9FVEMyOiAzNzQ5MiwKICAgICAgICBDT01QUkVTU0VEX1NSR0I4X0VUQzI6IDM3NDkzLAogICAgICAgIENPTVBSRVNTRURfUkdCOF9QVU5DSFRIUk9VR0hfQUxQSEExX0VUQzI6IDM3NDk0LAogICAgICAgIENPTVBSRVNTRURfU1JHQjhfUFVOQ0hUSFJPVUdIX0FMUEhBMV9FVEMyOiAzNzQ5NSwKICAgICAgICBDT01QUkVTU0VEX1JHQkE4X0VUQzJfRUFDOiAzNzQ5NiwKICAgICAgICBDT01QUkVTU0VEX1NSR0I4X0FMUEhBOF9FVEMyX0VBQzogMzc0OTcsCiAgICAgICAgVEVYVFVSRV9JTU1VVEFCTEVfRk9STUFUOiAzNzE2NywKICAgICAgICBNQVhfRUxFTUVOVF9JTkRFWDogMzYyMDMsCiAgICAgICAgVEVYVFVSRV9JTU1VVEFCTEVfTEVWRUxTOiAzMzUwMywKICAgICAgICAvLyBFeHRlbnNpb25zCiAgICAgICAgTUFYX1RFWFRVUkVfTUFYX0FOSVNPVFJPUFlfRVhUOiAzNDA0NwogICAgICB9OwogICAgICBXZWJHTENvbnN0YW50c19kZWZhdWx0ID0gT2JqZWN0LmZyZWV6ZShXZWJHTENvbnN0YW50cyk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Db21wb25lbnREYXRhdHlwZS5qcwogIHZhciBDb21wb25lbnREYXRhdHlwZSwgQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdDsKICB2YXIgaW5pdF9Db21wb25lbnREYXRhdHlwZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ29tcG9uZW50RGF0YXR5cGUuanMiKCkgewogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X1dlYkdMQ29uc3RhbnRzKCk7CiAgICAgIENvbXBvbmVudERhdGF0eXBlID0gewogICAgICAgIC8qKgogICAgICAgICAqIDgtYml0IHNpZ25lZCBieXRlIGNvcnJlc3BvbmRpbmcgdG8gPGNvZGU+Z2wuQllURTwvY29kZT4gYW5kIHRoZSB0eXBlCiAgICAgICAgICogb2YgYW4gZWxlbWVudCBpbiA8Y29kZT5JbnQ4QXJyYXk8L2NvZGU+LgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBCWVRFOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkJZVEUsCiAgICAgICAgLyoqCiAgICAgICAgICogOC1iaXQgdW5zaWduZWQgYnl0ZSBjb3JyZXNwb25kaW5nIHRvIDxjb2RlPlVOU0lHTkVEX0JZVEU8L2NvZGU+IGFuZCB0aGUgdHlwZQogICAgICAgICAqIG9mIGFuIGVsZW1lbnQgaW4gPGNvZGU+VWludDhBcnJheTwvY29kZT4uCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFVOU0lHTkVEX0JZVEU6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuVU5TSUdORURfQllURSwKICAgICAgICAvKioKICAgICAgICAgKiAxNi1iaXQgc2lnbmVkIHNob3J0IGNvcnJlc3BvbmRpbmcgdG8gPGNvZGU+U0hPUlQ8L2NvZGU+IGFuZCB0aGUgdHlwZQogICAgICAgICAqIG9mIGFuIGVsZW1lbnQgaW4gPGNvZGU+SW50MTZBcnJheTwvY29kZT4uCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFNIT1JUOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlNIT1JULAogICAgICAgIC8qKgogICAgICAgICAqIDE2LWJpdCB1bnNpZ25lZCBzaG9ydCBjb3JyZXNwb25kaW5nIHRvIDxjb2RlPlVOU0lHTkVEX1NIT1JUPC9jb2RlPiBhbmQgdGhlIHR5cGUKICAgICAgICAgKiBvZiBhbiBlbGVtZW50IGluIDxjb2RlPlVpbnQxNkFycmF5PC9jb2RlPi4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgVU5TSUdORURfU0hPUlQ6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuVU5TSUdORURfU0hPUlQsCiAgICAgICAgLyoqCiAgICAgICAgICogMzItYml0IHNpZ25lZCBpbnQgY29ycmVzcG9uZGluZyB0byA8Y29kZT5JTlQ8L2NvZGU+IGFuZCB0aGUgdHlwZQogICAgICAgICAqIG9mIGFuIGVsZW1lbnQgaW4gPGNvZGU+SW50MzJBcnJheTwvY29kZT4uCiAgICAgICAgICoKICAgICAgICAgKiBAbWVtYmVyT2YgQ29tcG9uZW50RGF0YXR5cGUKICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgSU5UOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LklOVCwKICAgICAgICAvKioKICAgICAgICAgKiAzMi1iaXQgdW5zaWduZWQgaW50IGNvcnJlc3BvbmRpbmcgdG8gPGNvZGU+VU5TSUdORURfSU5UPC9jb2RlPiBhbmQgdGhlIHR5cGUKICAgICAgICAgKiBvZiBhbiBlbGVtZW50IGluIDxjb2RlPlVpbnQzMkFycmF5PC9jb2RlPi4KICAgICAgICAgKgogICAgICAgICAqIEBtZW1iZXJPZiBDb21wb25lbnREYXRhdHlwZQogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBVTlNJR05FRF9JTlQ6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuVU5TSUdORURfSU5ULAogICAgICAgIC8qKgogICAgICAgICAqIDMyLWJpdCBmbG9hdGluZy1wb2ludCBjb3JyZXNwb25kaW5nIHRvIDxjb2RlPkZMT0FUPC9jb2RlPiBhbmQgdGhlIHR5cGUKICAgICAgICAgKiBvZiBhbiBlbGVtZW50IGluIDxjb2RlPkZsb2F0MzJBcnJheTwvY29kZT4uCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIEZMT0FUOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkZMT0FULAogICAgICAgIC8qKgogICAgICAgICAqIDY0LWJpdCBmbG9hdGluZy1wb2ludCBjb3JyZXNwb25kaW5nIHRvIDxjb2RlPmdsLkRPVUJMRTwvY29kZT4gKGluIERlc2t0b3AgT3BlbkdMOwogICAgICAgICAqIHRoaXMgaXMgbm90IHN1cHBvcnRlZCBpbiBXZWJHTCwgYW5kIGlzIGVtdWxhdGVkIGluIENlc2l1bSB2aWEge0BsaW5rIEdlb21ldHJ5UGlwZWxpbmUuZW5jb2RlQXR0cmlidXRlfSkKICAgICAgICAgKiBhbmQgdGhlIHR5cGUgb2YgYW4gZWxlbWVudCBpbiA8Y29kZT5GbG9hdDY0QXJyYXk8L2NvZGU+LgogICAgICAgICAqCiAgICAgICAgICogQG1lbWJlck9mIENvbXBvbmVudERhdGF0eXBlCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqIEBkZWZhdWx0IDB4MTQwQQogICAgICAgICAqLwogICAgICAgIERPVUJMRTogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5ET1VCTEUKICAgICAgfTsKICAgICAgQ29tcG9uZW50RGF0YXR5cGUuZ2V0U2l6ZUluQnl0ZXMgPSBmdW5jdGlvbihjb21wb25lbnREYXRhdHlwZSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGNvbXBvbmVudERhdGF0eXBlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInZhbHVlIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBzd2l0Y2ggKGNvbXBvbmVudERhdGF0eXBlKSB7CiAgICAgICAgICBjYXNlIENvbXBvbmVudERhdGF0eXBlLkJZVEU6CiAgICAgICAgICAgIHJldHVybiBJbnQ4QXJyYXkuQllURVNfUEVSX0VMRU1FTlQ7CiAgICAgICAgICBjYXNlIENvbXBvbmVudERhdGF0eXBlLlVOU0lHTkVEX0JZVEU6CiAgICAgICAgICAgIHJldHVybiBVaW50OEFycmF5LkJZVEVTX1BFUl9FTEVNRU5UOwogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZS5TSE9SVDoKICAgICAgICAgICAgcmV0dXJuIEludDE2QXJyYXkuQllURVNfUEVSX0VMRU1FTlQ7CiAgICAgICAgICBjYXNlIENvbXBvbmVudERhdGF0eXBlLlVOU0lHTkVEX1NIT1JUOgogICAgICAgICAgICByZXR1cm4gVWludDE2QXJyYXkuQllURVNfUEVSX0VMRU1FTlQ7CiAgICAgICAgICBjYXNlIENvbXBvbmVudERhdGF0eXBlLklOVDoKICAgICAgICAgICAgcmV0dXJuIEludDMyQXJyYXkuQllURVNfUEVSX0VMRU1FTlQ7CiAgICAgICAgICBjYXNlIENvbXBvbmVudERhdGF0eXBlLlVOU0lHTkVEX0lOVDoKICAgICAgICAgICAgcmV0dXJuIFVpbnQzMkFycmF5LkJZVEVTX1BFUl9FTEVNRU5UOwogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZS5GTE9BVDoKICAgICAgICAgICAgcmV0dXJuIEZsb2F0MzJBcnJheS5CWVRFU19QRVJfRUxFTUVOVDsKICAgICAgICAgIGNhc2UgQ29tcG9uZW50RGF0YXR5cGUuRE9VQkxFOgogICAgICAgICAgICByZXR1cm4gRmxvYXQ2NEFycmF5LkJZVEVTX1BFUl9FTEVNRU5UOwogICAgICAgICAgLy8+PmluY2x1ZGVTdGFydCgnZGVidWcnLCBwcmFnbWFzLmRlYnVnKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJjb21wb25lbnREYXRhdHlwZSBpcyBub3QgYSB2YWxpZCB2YWx1ZS4iKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIENvbXBvbmVudERhdGF0eXBlLmZyb21UeXBlZEFycmF5ID0gZnVuY3Rpb24oYXJyYXkpIHsKICAgICAgICBpZiAoYXJyYXkgaW5zdGFuY2VvZiBJbnQ4QXJyYXkpIHsKICAgICAgICAgIHJldHVybiBDb21wb25lbnREYXRhdHlwZS5CWVRFOwogICAgICAgIH0KICAgICAgICBpZiAoYXJyYXkgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7CiAgICAgICAgICByZXR1cm4gQ29tcG9uZW50RGF0YXR5cGUuVU5TSUdORURfQllURTsKICAgICAgICB9CiAgICAgICAgaWYgKGFycmF5IGluc3RhbmNlb2YgSW50MTZBcnJheSkgewogICAgICAgICAgcmV0dXJuIENvbXBvbmVudERhdGF0eXBlLlNIT1JUOwogICAgICAgIH0KICAgICAgICBpZiAoYXJyYXkgaW5zdGFuY2VvZiBVaW50MTZBcnJheSkgewogICAgICAgICAgcmV0dXJuIENvbXBvbmVudERhdGF0eXBlLlVOU0lHTkVEX1NIT1JUOwogICAgICAgIH0KICAgICAgICBpZiAoYXJyYXkgaW5zdGFuY2VvZiBJbnQzMkFycmF5KSB7CiAgICAgICAgICByZXR1cm4gQ29tcG9uZW50RGF0YXR5cGUuSU5UOwogICAgICAgIH0KICAgICAgICBpZiAoYXJyYXkgaW5zdGFuY2VvZiBVaW50MzJBcnJheSkgewogICAgICAgICAgcmV0dXJuIENvbXBvbmVudERhdGF0eXBlLlVOU0lHTkVEX0lOVDsKICAgICAgICB9CiAgICAgICAgaWYgKGFycmF5IGluc3RhbmNlb2YgRmxvYXQzMkFycmF5KSB7CiAgICAgICAgICByZXR1cm4gQ29tcG9uZW50RGF0YXR5cGUuRkxPQVQ7CiAgICAgICAgfQogICAgICAgIGlmIChhcnJheSBpbnN0YW5jZW9mIEZsb2F0NjRBcnJheSkgewogICAgICAgICAgcmV0dXJuIENvbXBvbmVudERhdGF0eXBlLkRPVUJMRTsKICAgICAgICB9CiAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAiYXJyYXkgbXVzdCBiZSBhbiBJbnQ4QXJyYXksIFVpbnQ4QXJyYXksIEludDE2QXJyYXksIFVpbnQxNkFycmF5LCBJbnQzMkFycmF5LCBVaW50MzJBcnJheSwgRmxvYXQzMkFycmF5LCBvciBGbG9hdDY0QXJyYXkuIgogICAgICAgICk7CiAgICAgIH07CiAgICAgIENvbXBvbmVudERhdGF0eXBlLnZhbGlkYXRlID0gZnVuY3Rpb24oY29tcG9uZW50RGF0YXR5cGUpIHsKICAgICAgICByZXR1cm4gZGVmaW5lZF9kZWZhdWx0KGNvbXBvbmVudERhdGF0eXBlKSAmJiAoY29tcG9uZW50RGF0YXR5cGUgPT09IENvbXBvbmVudERhdGF0eXBlLkJZVEUgfHwgY29tcG9uZW50RGF0YXR5cGUgPT09IENvbXBvbmVudERhdGF0eXBlLlVOU0lHTkVEX0JZVEUgfHwgY29tcG9uZW50RGF0YXR5cGUgPT09IENvbXBvbmVudERhdGF0eXBlLlNIT1JUIHx8IGNvbXBvbmVudERhdGF0eXBlID09PSBDb21wb25lbnREYXRhdHlwZS5VTlNJR05FRF9TSE9SVCB8fCBjb21wb25lbnREYXRhdHlwZSA9PT0gQ29tcG9uZW50RGF0YXR5cGUuSU5UIHx8IGNvbXBvbmVudERhdGF0eXBlID09PSBDb21wb25lbnREYXRhdHlwZS5VTlNJR05FRF9JTlQgfHwgY29tcG9uZW50RGF0YXR5cGUgPT09IENvbXBvbmVudERhdGF0eXBlLkZMT0FUIHx8IGNvbXBvbmVudERhdGF0eXBlID09PSBDb21wb25lbnREYXRhdHlwZS5ET1VCTEUpOwogICAgICB9OwogICAgICBDb21wb25lbnREYXRhdHlwZS5jcmVhdGVUeXBlZEFycmF5ID0gZnVuY3Rpb24oY29tcG9uZW50RGF0YXR5cGUsIHZhbHVlc09yTGVuZ3RoKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoY29tcG9uZW50RGF0YXR5cGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiY29tcG9uZW50RGF0YXR5cGUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHZhbHVlc09yTGVuZ3RoKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInZhbHVlc09yTGVuZ3RoIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBzd2l0Y2ggKGNvbXBvbmVudERhdGF0eXBlKSB7CiAgICAgICAgICBjYXNlIENvbXBvbmVudERhdGF0eXBlLkJZVEU6CiAgICAgICAgICAgIHJldHVybiBuZXcgSW50OEFycmF5KHZhbHVlc09yTGVuZ3RoKTsKICAgICAgICAgIGNhc2UgQ29tcG9uZW50RGF0YXR5cGUuVU5TSUdORURfQllURToKICAgICAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KHZhbHVlc09yTGVuZ3RoKTsKICAgICAgICAgIGNhc2UgQ29tcG9uZW50RGF0YXR5cGUuU0hPUlQ6CiAgICAgICAgICAgIHJldHVybiBuZXcgSW50MTZBcnJheSh2YWx1ZXNPckxlbmd0aCk7CiAgICAgICAgICBjYXNlIENvbXBvbmVudERhdGF0eXBlLlVOU0lHTkVEX1NIT1JUOgogICAgICAgICAgICByZXR1cm4gbmV3IFVpbnQxNkFycmF5KHZhbHVlc09yTGVuZ3RoKTsKICAgICAgICAgIGNhc2UgQ29tcG9uZW50RGF0YXR5cGUuSU5UOgogICAgICAgICAgICByZXR1cm4gbmV3IEludDMyQXJyYXkodmFsdWVzT3JMZW5ndGgpOwogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZS5VTlNJR05FRF9JTlQ6CiAgICAgICAgICAgIHJldHVybiBuZXcgVWludDMyQXJyYXkodmFsdWVzT3JMZW5ndGgpOwogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZS5GTE9BVDoKICAgICAgICAgICAgcmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkodmFsdWVzT3JMZW5ndGgpOwogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZS5ET1VCTEU6CiAgICAgICAgICAgIHJldHVybiBuZXcgRmxvYXQ2NEFycmF5KHZhbHVlc09yTGVuZ3RoKTsKICAgICAgICAgIC8vPj5pbmNsdWRlU3RhcnQoJ2RlYnVnJywgcHJhZ21hcy5kZWJ1Zyk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiY29tcG9uZW50RGF0YXR5cGUgaXMgbm90IGEgdmFsaWQgdmFsdWUuIik7CiAgICAgICAgfQogICAgICB9OwogICAgICBDb21wb25lbnREYXRhdHlwZS5jcmVhdGVBcnJheUJ1ZmZlclZpZXcgPSBmdW5jdGlvbihjb21wb25lbnREYXRhdHlwZSwgYnVmZmVyLCBieXRlT2Zmc2V0LCBsZW5ndGgpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChjb21wb25lbnREYXRhdHlwZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJjb21wb25lbnREYXRhdHlwZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYnVmZmVyKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImJ1ZmZlciBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgYnl0ZU9mZnNldCA9IGJ5dGVPZmZzZXQgPz8gMDsKICAgICAgICBsZW5ndGggPSBsZW5ndGggPz8gKGJ1ZmZlci5ieXRlTGVuZ3RoIC0gYnl0ZU9mZnNldCkgLyBDb21wb25lbnREYXRhdHlwZS5nZXRTaXplSW5CeXRlcyhjb21wb25lbnREYXRhdHlwZSk7CiAgICAgICAgc3dpdGNoIChjb21wb25lbnREYXRhdHlwZSkgewogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZS5CWVRFOgogICAgICAgICAgICByZXR1cm4gbmV3IEludDhBcnJheShidWZmZXIsIGJ5dGVPZmZzZXQsIGxlbmd0aCk7CiAgICAgICAgICBjYXNlIENvbXBvbmVudERhdGF0eXBlLlVOU0lHTkVEX0JZVEU6CiAgICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShidWZmZXIsIGJ5dGVPZmZzZXQsIGxlbmd0aCk7CiAgICAgICAgICBjYXNlIENvbXBvbmVudERhdGF0eXBlLlNIT1JUOgogICAgICAgICAgICByZXR1cm4gbmV3IEludDE2QXJyYXkoYnVmZmVyLCBieXRlT2Zmc2V0LCBsZW5ndGgpOwogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZS5VTlNJR05FRF9TSE9SVDoKICAgICAgICAgICAgcmV0dXJuIG5ldyBVaW50MTZBcnJheShidWZmZXIsIGJ5dGVPZmZzZXQsIGxlbmd0aCk7CiAgICAgICAgICBjYXNlIENvbXBvbmVudERhdGF0eXBlLklOVDoKICAgICAgICAgICAgcmV0dXJuIG5ldyBJbnQzMkFycmF5KGJ1ZmZlciwgYnl0ZU9mZnNldCwgbGVuZ3RoKTsKICAgICAgICAgIGNhc2UgQ29tcG9uZW50RGF0YXR5cGUuVU5TSUdORURfSU5UOgogICAgICAgICAgICByZXR1cm4gbmV3IFVpbnQzMkFycmF5KGJ1ZmZlciwgYnl0ZU9mZnNldCwgbGVuZ3RoKTsKICAgICAgICAgIGNhc2UgQ29tcG9uZW50RGF0YXR5cGUuRkxPQVQ6CiAgICAgICAgICAgIHJldHVybiBuZXcgRmxvYXQzMkFycmF5KGJ1ZmZlciwgYnl0ZU9mZnNldCwgbGVuZ3RoKTsKICAgICAgICAgIGNhc2UgQ29tcG9uZW50RGF0YXR5cGUuRE9VQkxFOgogICAgICAgICAgICByZXR1cm4gbmV3IEZsb2F0NjRBcnJheShidWZmZXIsIGJ5dGVPZmZzZXQsIGxlbmd0aCk7CiAgICAgICAgICAvLz4+aW5jbHVkZVN0YXJ0KCdkZWJ1ZycsIHByYWdtYXMuZGVidWcpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImNvbXBvbmVudERhdGF0eXBlIGlzIG5vdCBhIHZhbGlkIHZhbHVlLiIpOwogICAgICAgIH0KICAgICAgfTsKICAgICAgQ29tcG9uZW50RGF0YXR5cGUuZnJvbU5hbWUgPSBmdW5jdGlvbihuYW1lKSB7CiAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICBjYXNlICJCWVRFIjoKICAgICAgICAgICAgcmV0dXJuIENvbXBvbmVudERhdGF0eXBlLkJZVEU7CiAgICAgICAgICBjYXNlICJVTlNJR05FRF9CWVRFIjoKICAgICAgICAgICAgcmV0dXJuIENvbXBvbmVudERhdGF0eXBlLlVOU0lHTkVEX0JZVEU7CiAgICAgICAgICBjYXNlICJTSE9SVCI6CiAgICAgICAgICAgIHJldHVybiBDb21wb25lbnREYXRhdHlwZS5TSE9SVDsKICAgICAgICAgIGNhc2UgIlVOU0lHTkVEX1NIT1JUIjoKICAgICAgICAgICAgcmV0dXJuIENvbXBvbmVudERhdGF0eXBlLlVOU0lHTkVEX1NIT1JUOwogICAgICAgICAgY2FzZSAiSU5UIjoKICAgICAgICAgICAgcmV0dXJuIENvbXBvbmVudERhdGF0eXBlLklOVDsKICAgICAgICAgIGNhc2UgIlVOU0lHTkVEX0lOVCI6CiAgICAgICAgICAgIHJldHVybiBDb21wb25lbnREYXRhdHlwZS5VTlNJR05FRF9JTlQ7CiAgICAgICAgICBjYXNlICJGTE9BVCI6CiAgICAgICAgICAgIHJldHVybiBDb21wb25lbnREYXRhdHlwZS5GTE9BVDsKICAgICAgICAgIGNhc2UgIkRPVUJMRSI6CiAgICAgICAgICAgIHJldHVybiBDb21wb25lbnREYXRhdHlwZS5ET1VCTEU7CiAgICAgICAgICAvLz4+aW5jbHVkZVN0YXJ0KCdkZWJ1ZycsIHByYWdtYXMuZGVidWcpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm5hbWUgaXMgbm90IGEgdmFsaWQgdmFsdWUuIik7CiAgICAgICAgfQogICAgICB9OwogICAgICBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0ID0gT2JqZWN0LmZyZWV6ZShDb21wb25lbnREYXRhdHlwZSk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9HZW9tZXRyeVR5cGUuanMKICB2YXIgR2VvbWV0cnlUeXBlLCBHZW9tZXRyeVR5cGVfZGVmYXVsdDsKICB2YXIgaW5pdF9HZW9tZXRyeVR5cGUgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dlb21ldHJ5VHlwZS5qcyIoKSB7CiAgICAgIEdlb21ldHJ5VHlwZSA9IHsKICAgICAgICBOT05FOiAwLAogICAgICAgIFRSSUFOR0xFUzogMSwKICAgICAgICBMSU5FUzogMiwKICAgICAgICBQT0xZTElORVM6IDMKICAgICAgfTsKICAgICAgR2VvbWV0cnlUeXBlX2RlZmF1bHQgPSBPYmplY3QuZnJlZXplKEdlb21ldHJ5VHlwZSk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9NYXRyaXgyLmpzCiAgZnVuY3Rpb24gTWF0cml4Mihjb2x1bW4wUm93MCwgY29sdW1uMVJvdzAsIGNvbHVtbjBSb3cxLCBjb2x1bW4xUm93MSkgewogICAgdGhpc1swXSA9IGNvbHVtbjBSb3cwID8/IDA7CiAgICB0aGlzWzFdID0gY29sdW1uMFJvdzEgPz8gMDsKICAgIHRoaXNbMl0gPSBjb2x1bW4xUm93MCA/PyAwOwogICAgdGhpc1szXSA9IGNvbHVtbjFSb3cxID8/IDA7CiAgfQogIHZhciBzY2FsZVNjcmF0Y2gxMywgc2NhbGVTY3JhdGNoMjMsIHNjcmF0Y2hDb2x1bW4zLCBzY2FsZVNjcmF0Y2gzMywgc2NhbGVTY3JhdGNoNDMsIHNjYWxlU2NyYXRjaDUzLCBNYXRyaXgyX2RlZmF1bHQ7CiAgdmFyIGluaXRfTWF0cml4MiA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvTWF0cml4Mi5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMigpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIE1hdHJpeDIucGFja2VkTGVuZ3RoID0gNDsKICAgICAgTWF0cml4Mi5wYWNrID0gZnVuY3Rpb24odmFsdWUsIGFycmF5LCBzdGFydGluZ0luZGV4KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJ2YWx1ZSIsIHZhbHVlKTsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlWzBdOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZVsxXTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWVbMl07CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlWzNdOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgTWF0cml4Mi51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBNYXRyaXgyKCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0WzFdID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHRbMl0gPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdFszXSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4Mi5wYWNrQXJyYXkgPSBmdW5jdGlvbihhcnJheSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBjb25zdCBsZW5ndGggPSBhcnJheS5sZW5ndGg7CiAgICAgICAgY29uc3QgcmVzdWx0TGVuZ3RoID0gbGVuZ3RoICogNDsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQXJyYXkocmVzdWx0TGVuZ3RoKTsKICAgICAgICB9IGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KHJlc3VsdCkgJiYgcmVzdWx0Lmxlbmd0aCAhPT0gcmVzdWx0TGVuZ3RoKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgIklmIHJlc3VsdCBpcyBhIHR5cGVkIGFycmF5LCBpdCBtdXN0IGhhdmUgZXhhY3RseSBhcnJheS5sZW5ndGggKiA0IGVsZW1lbnRzIgogICAgICAgICAgKTsKICAgICAgICB9IGVsc2UgaWYgKHJlc3VsdC5sZW5ndGggIT09IHJlc3VsdExlbmd0aCkgewogICAgICAgICAgcmVzdWx0Lmxlbmd0aCA9IHJlc3VsdExlbmd0aDsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgTWF0cml4Mi5wYWNrKGFycmF5W2ldLCByZXN1bHQsIGkgKiA0KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4Mi51bnBhY2tBcnJheSA9IGZ1bmN0aW9uKGFycmF5LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJhcnJheS5sZW5ndGgiLCBhcnJheS5sZW5ndGgsIDQpOwogICAgICAgIGlmIChhcnJheS5sZW5ndGggJSA0ICE9PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYXJyYXkgbGVuZ3RoIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA0LiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBsZW5ndGggPSBhcnJheS5sZW5ndGg7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEFycmF5KGxlbmd0aCAvIDQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQubGVuZ3RoID0gbGVuZ3RoIC8gNDsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gNCkgewogICAgICAgICAgY29uc3QgaW5kZXggPSBpIC8gNDsKICAgICAgICAgIHJlc3VsdFtpbmRleF0gPSBNYXRyaXgyLnVucGFjayhhcnJheSwgaSwgcmVzdWx0W2luZGV4XSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDIuY2xvbmUgPSBmdW5jdGlvbihtYXRyaXgsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG1hdHJpeCkpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgTWF0cml4MihtYXRyaXhbMF0sIG1hdHJpeFsyXSwgbWF0cml4WzFdLCBtYXRyaXhbM10pOwogICAgICAgIH0KICAgICAgICByZXN1bHRbMF0gPSBtYXRyaXhbMF07CiAgICAgICAgcmVzdWx0WzFdID0gbWF0cml4WzFdOwogICAgICAgIHJlc3VsdFsyXSA9IG1hdHJpeFsyXTsKICAgICAgICByZXN1bHRbM10gPSBtYXRyaXhbM107CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4Mi5mcm9tQXJyYXkgPSBNYXRyaXgyLnVucGFjazsKICAgICAgTWF0cml4Mi5mcm9tQ29sdW1uTWFqb3JBcnJheSA9IGZ1bmN0aW9uKHZhbHVlcywgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ2YWx1ZXMiLCB2YWx1ZXMpOwogICAgICAgIHJldHVybiBNYXRyaXgyLmNsb25lKHZhbHVlcywgcmVzdWx0KTsKICAgICAgfTsKICAgICAgTWF0cml4Mi5mcm9tUm93TWFqb3JBcnJheSA9IGZ1bmN0aW9uKHZhbHVlcywgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ2YWx1ZXMiLCB2YWx1ZXMpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgTWF0cml4Mih2YWx1ZXNbMF0sIHZhbHVlc1sxXSwgdmFsdWVzWzJdLCB2YWx1ZXNbM10pOwogICAgICAgIH0KICAgICAgICByZXN1bHRbMF0gPSB2YWx1ZXNbMF07CiAgICAgICAgcmVzdWx0WzFdID0gdmFsdWVzWzJdOwogICAgICAgIHJlc3VsdFsyXSA9IHZhbHVlc1sxXTsKICAgICAgICByZXN1bHRbM10gPSB2YWx1ZXNbM107CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4Mi5mcm9tU2NhbGUgPSBmdW5jdGlvbihzY2FsZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzY2FsZSIsIHNjYWxlKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IE1hdHJpeDIoc2NhbGUueCwgMCwgMCwgc2NhbGUueSk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IHNjYWxlLng7CiAgICAgICAgcmVzdWx0WzFdID0gMDsKICAgICAgICByZXN1bHRbMl0gPSAwOwogICAgICAgIHJlc3VsdFszXSA9IHNjYWxlLnk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4Mi5mcm9tVW5pZm9ybVNjYWxlID0gZnVuY3Rpb24oc2NhbGUsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigic2NhbGUiLCBzY2FsZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBNYXRyaXgyKHNjYWxlLCAwLCAwLCBzY2FsZSk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFswXSA9IHNjYWxlOwogICAgICAgIHJlc3VsdFsxXSA9IDA7CiAgICAgICAgcmVzdWx0WzJdID0gMDsKICAgICAgICByZXN1bHRbM10gPSBzY2FsZTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgyLmZyb21Sb3RhdGlvbiA9IGZ1bmN0aW9uKGFuZ2xlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoImFuZ2xlIiwgYW5nbGUpOwogICAgICAgIGNvbnN0IGNvc0FuZ2xlID0gTWF0aC5jb3MoYW5nbGUpOwogICAgICAgIGNvbnN0IHNpbkFuZ2xlID0gTWF0aC5zaW4oYW5nbGUpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgTWF0cml4Mihjb3NBbmdsZSwgLXNpbkFuZ2xlLCBzaW5BbmdsZSwgY29zQW5nbGUpOwogICAgICAgIH0KICAgICAgICByZXN1bHRbMF0gPSBjb3NBbmdsZTsKICAgICAgICByZXN1bHRbMV0gPSBzaW5BbmdsZTsKICAgICAgICByZXN1bHRbMl0gPSAtc2luQW5nbGU7CiAgICAgICAgcmVzdWx0WzNdID0gY29zQW5nbGU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4Mi50b0FycmF5ID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIFttYXRyaXhbMF0sIG1hdHJpeFsxXSwgbWF0cml4WzJdLCBtYXRyaXhbM11dOwogICAgICAgIH0KICAgICAgICByZXN1bHRbMF0gPSBtYXRyaXhbMF07CiAgICAgICAgcmVzdWx0WzFdID0gbWF0cml4WzFdOwogICAgICAgIHJlc3VsdFsyXSA9IG1hdHJpeFsyXTsKICAgICAgICByZXN1bHRbM10gPSBtYXRyaXhbM107CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4Mi5nZXRFbGVtZW50SW5kZXggPSBmdW5jdGlvbihjb2x1bW4sIHJvdykgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJyb3ciLCByb3csIDApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5sZXNzVGhhbk9yRXF1YWxzKCJyb3ciLCByb3csIDEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJjb2x1bW4iLCBjb2x1bW4sIDApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5sZXNzVGhhbk9yRXF1YWxzKCJjb2x1bW4iLCBjb2x1bW4sIDEpOwogICAgICAgIHJldHVybiBjb2x1bW4gKiAyICsgcm93OwogICAgICB9OwogICAgICBNYXRyaXgyLmdldENvbHVtbiA9IGZ1bmN0aW9uKG1hdHJpeCwgaW5kZXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygiaW5kZXgiLCBpbmRleCwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoImluZGV4IiwgaW5kZXgsIDEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBzdGFydEluZGV4ID0gaW5kZXggKiAyOwogICAgICAgIGNvbnN0IHggPSBtYXRyaXhbc3RhcnRJbmRleF07CiAgICAgICAgY29uc3QgeSA9IG1hdHJpeFtzdGFydEluZGV4ICsgMV07CiAgICAgICAgcmVzdWx0LnggPSB4OwogICAgICAgIHJlc3VsdC55ID0geTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgyLnNldENvbHVtbiA9IGZ1bmN0aW9uKG1hdHJpeCwgaW5kZXgsIGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoImluZGV4IiwgaW5kZXgsIDApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5sZXNzVGhhbk9yRXF1YWxzKCJpbmRleCIsIGluZGV4LCAxKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0ID0gTWF0cml4Mi5jbG9uZShtYXRyaXgsIHJlc3VsdCk7CiAgICAgICAgY29uc3Qgc3RhcnRJbmRleCA9IGluZGV4ICogMjsKICAgICAgICByZXN1bHRbc3RhcnRJbmRleF0gPSBjYXJ0ZXNpYW4xMS54OwogICAgICAgIHJlc3VsdFtzdGFydEluZGV4ICsgMV0gPSBjYXJ0ZXNpYW4xMS55OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDIuZ2V0Um93ID0gZnVuY3Rpb24obWF0cml4LCBpbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJpbmRleCIsIGluZGV4LCAwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygiaW5kZXgiLCBpbmRleCwgMSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHggPSBtYXRyaXhbaW5kZXhdOwogICAgICAgIGNvbnN0IHkgPSBtYXRyaXhbaW5kZXggKyAyXTsKICAgICAgICByZXN1bHQueCA9IHg7CiAgICAgICAgcmVzdWx0LnkgPSB5OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDIuc2V0Um93ID0gZnVuY3Rpb24obWF0cml4LCBpbmRleCwgY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygiaW5kZXgiLCBpbmRleCwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoImluZGV4IiwgaW5kZXgsIDEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQgPSBNYXRyaXgyLmNsb25lKG1hdHJpeCwgcmVzdWx0KTsKICAgICAgICByZXN1bHRbaW5kZXhdID0gY2FydGVzaWFuMTEueDsKICAgICAgICByZXN1bHRbaW5kZXggKyAyXSA9IGNhcnRlc2lhbjExLnk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NhbGVTY3JhdGNoMTMgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIE1hdHJpeDIuc2V0U2NhbGUgPSBmdW5jdGlvbihtYXRyaXgsIHNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzY2FsZSIsIHNjYWxlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgZXhpc3RpbmdTY2FsZSA9IE1hdHJpeDIuZ2V0U2NhbGUobWF0cml4LCBzY2FsZVNjcmF0Y2gxMyk7CiAgICAgICAgY29uc3Qgc2NhbGVSYXRpb1ggPSBzY2FsZS54IC8gZXhpc3RpbmdTY2FsZS54OwogICAgICAgIGNvbnN0IHNjYWxlUmF0aW9ZID0gc2NhbGUueSAvIGV4aXN0aW5nU2NhbGUueTsKICAgICAgICByZXN1bHRbMF0gPSBtYXRyaXhbMF0gKiBzY2FsZVJhdGlvWDsKICAgICAgICByZXN1bHRbMV0gPSBtYXRyaXhbMV0gKiBzY2FsZVJhdGlvWDsKICAgICAgICByZXN1bHRbMl0gPSBtYXRyaXhbMl0gKiBzY2FsZVJhdGlvWTsKICAgICAgICByZXN1bHRbM10gPSBtYXRyaXhbM10gKiBzY2FsZVJhdGlvWTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBzY2FsZVNjcmF0Y2gyMyA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKTsKICAgICAgTWF0cml4Mi5zZXRVbmlmb3JtU2NhbGUgPSBmdW5jdGlvbihtYXRyaXgsIHNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJzY2FsZSIsIHNjYWxlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgZXhpc3RpbmdTY2FsZSA9IE1hdHJpeDIuZ2V0U2NhbGUobWF0cml4LCBzY2FsZVNjcmF0Y2gyMyk7CiAgICAgICAgY29uc3Qgc2NhbGVSYXRpb1ggPSBzY2FsZSAvIGV4aXN0aW5nU2NhbGUueDsKICAgICAgICBjb25zdCBzY2FsZVJhdGlvWSA9IHNjYWxlIC8gZXhpc3RpbmdTY2FsZS55OwogICAgICAgIHJlc3VsdFswXSA9IG1hdHJpeFswXSAqIHNjYWxlUmF0aW9YOwogICAgICAgIHJlc3VsdFsxXSA9IG1hdHJpeFsxXSAqIHNjYWxlUmF0aW9YOwogICAgICAgIHJlc3VsdFsyXSA9IG1hdHJpeFsyXSAqIHNjYWxlUmF0aW9ZOwogICAgICAgIHJlc3VsdFszXSA9IG1hdHJpeFszXSAqIHNjYWxlUmF0aW9ZOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hDb2x1bW4zID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBNYXRyaXgyLmdldFNjYWxlID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC54ID0gQ2FydGVzaWFuMl9kZWZhdWx0Lm1hZ25pdHVkZSgKICAgICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHMobWF0cml4WzBdLCBtYXRyaXhbMV0sIHNjcmF0Y2hDb2x1bW4zKQogICAgICAgICk7CiAgICAgICAgcmVzdWx0LnkgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQubWFnbml0dWRlKAogICAgICAgICAgQ2FydGVzaWFuMl9kZWZhdWx0LmZyb21FbGVtZW50cyhtYXRyaXhbMl0sIG1hdHJpeFszXSwgc2NyYXRjaENvbHVtbjMpCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBzY2FsZVNjcmF0Y2gzMyA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKTsKICAgICAgTWF0cml4Mi5nZXRNYXhpbXVtU2NhbGUgPSBmdW5jdGlvbihtYXRyaXgpIHsKICAgICAgICBNYXRyaXgyLmdldFNjYWxlKG1hdHJpeCwgc2NhbGVTY3JhdGNoMzMpOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4yX2RlZmF1bHQubWF4aW11bUNvbXBvbmVudChzY2FsZVNjcmF0Y2gzMyk7CiAgICAgIH07CiAgICAgIHNjYWxlU2NyYXRjaDQzID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBNYXRyaXgyLnNldFJvdGF0aW9uID0gZnVuY3Rpb24obWF0cml4LCByb3RhdGlvbiwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBzY2FsZSA9IE1hdHJpeDIuZ2V0U2NhbGUobWF0cml4LCBzY2FsZVNjcmF0Y2g0Myk7CiAgICAgICAgcmVzdWx0WzBdID0gcm90YXRpb25bMF0gKiBzY2FsZS54OwogICAgICAgIHJlc3VsdFsxXSA9IHJvdGF0aW9uWzFdICogc2NhbGUueDsKICAgICAgICByZXN1bHRbMl0gPSByb3RhdGlvblsyXSAqIHNjYWxlLnk7CiAgICAgICAgcmVzdWx0WzNdID0gcm90YXRpb25bM10gKiBzY2FsZS55OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHNjYWxlU2NyYXRjaDUzID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBNYXRyaXgyLmdldFJvdGF0aW9uID0gZnVuY3Rpb24obWF0cml4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHNjYWxlID0gTWF0cml4Mi5nZXRTY2FsZShtYXRyaXgsIHNjYWxlU2NyYXRjaDUzKTsKICAgICAgICByZXN1bHRbMF0gPSBtYXRyaXhbMF0gLyBzY2FsZS54OwogICAgICAgIHJlc3VsdFsxXSA9IG1hdHJpeFsxXSAvIHNjYWxlLng7CiAgICAgICAgcmVzdWx0WzJdID0gbWF0cml4WzJdIC8gc2NhbGUueTsKICAgICAgICByZXN1bHRbM10gPSBtYXRyaXhbM10gLyBzY2FsZS55OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDIubXVsdGlwbHkgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzAgPSBsZWZ0WzBdICogcmlnaHRbMF0gKyBsZWZ0WzJdICogcmlnaHRbMV07CiAgICAgICAgY29uc3QgY29sdW1uMVJvdzAgPSBsZWZ0WzBdICogcmlnaHRbMl0gKyBsZWZ0WzJdICogcmlnaHRbM107CiAgICAgICAgY29uc3QgY29sdW1uMFJvdzEgPSBsZWZ0WzFdICogcmlnaHRbMF0gKyBsZWZ0WzNdICogcmlnaHRbMV07CiAgICAgICAgY29uc3QgY29sdW1uMVJvdzEgPSBsZWZ0WzFdICogcmlnaHRbMl0gKyBsZWZ0WzNdICogcmlnaHRbM107CiAgICAgICAgcmVzdWx0WzBdID0gY29sdW1uMFJvdzA7CiAgICAgICAgcmVzdWx0WzFdID0gY29sdW1uMFJvdzE7CiAgICAgICAgcmVzdWx0WzJdID0gY29sdW1uMVJvdzA7CiAgICAgICAgcmVzdWx0WzNdID0gY29sdW1uMVJvdzE7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4Mi5hZGQgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0WzBdID0gbGVmdFswXSArIHJpZ2h0WzBdOwogICAgICAgIHJlc3VsdFsxXSA9IGxlZnRbMV0gKyByaWdodFsxXTsKICAgICAgICByZXN1bHRbMl0gPSBsZWZ0WzJdICsgcmlnaHRbMl07CiAgICAgICAgcmVzdWx0WzNdID0gbGVmdFszXSArIHJpZ2h0WzNdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDIuc3VidHJhY3QgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0WzBdID0gbGVmdFswXSAtIHJpZ2h0WzBdOwogICAgICAgIHJlc3VsdFsxXSA9IGxlZnRbMV0gLSByaWdodFsxXTsKICAgICAgICByZXN1bHRbMl0gPSBsZWZ0WzJdIC0gcmlnaHRbMl07CiAgICAgICAgcmVzdWx0WzNdID0gbGVmdFszXSAtIHJpZ2h0WzNdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDIubXVsdGlwbHlCeVZlY3RvciA9IGZ1bmN0aW9uKG1hdHJpeCwgY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgeCA9IG1hdHJpeFswXSAqIGNhcnRlc2lhbjExLnggKyBtYXRyaXhbMl0gKiBjYXJ0ZXNpYW4xMS55OwogICAgICAgIGNvbnN0IHkgPSBtYXRyaXhbMV0gKiBjYXJ0ZXNpYW4xMS54ICsgbWF0cml4WzNdICogY2FydGVzaWFuMTEueTsKICAgICAgICByZXN1bHQueCA9IHg7CiAgICAgICAgcmVzdWx0LnkgPSB5OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDIubXVsdGlwbHlCeVNjYWxhciA9IGZ1bmN0aW9uKG1hdHJpeCwgc2NhbGFyLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJzY2FsYXIiLCBzY2FsYXIpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHRbMF0gPSBtYXRyaXhbMF0gKiBzY2FsYXI7CiAgICAgICAgcmVzdWx0WzFdID0gbWF0cml4WzFdICogc2NhbGFyOwogICAgICAgIHJlc3VsdFsyXSA9IG1hdHJpeFsyXSAqIHNjYWxhcjsKICAgICAgICByZXN1bHRbM10gPSBtYXRyaXhbM10gKiBzY2FsYXI7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4Mi5tdWx0aXBseUJ5U2NhbGUgPSBmdW5jdGlvbihtYXRyaXgsIHNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJzY2FsZSIsIHNjYWxlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4WzBdICogc2NhbGUueDsKICAgICAgICByZXN1bHRbMV0gPSBtYXRyaXhbMV0gKiBzY2FsZS54OwogICAgICAgIHJlc3VsdFsyXSA9IG1hdHJpeFsyXSAqIHNjYWxlLnk7CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzNdICogc2NhbGUueTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgyLm11bHRpcGx5QnlVbmlmb3JtU2NhbGUgPSBmdW5jdGlvbihtYXRyaXgsIHNjYWxlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm1hdHJpeCIsIG1hdHJpeCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJzY2FsZSIsIHNjYWxlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0WzBdID0gbWF0cml4WzBdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzFdID0gbWF0cml4WzFdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzJdID0gbWF0cml4WzJdICogc2NhbGU7CiAgICAgICAgcmVzdWx0WzNdID0gbWF0cml4WzNdICogc2NhbGU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgTWF0cml4Mi5uZWdhdGUgPSBmdW5jdGlvbihtYXRyaXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF0cml4IiwgbWF0cml4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0WzBdID0gLW1hdHJpeFswXTsKICAgICAgICByZXN1bHRbMV0gPSAtbWF0cml4WzFdOwogICAgICAgIHJlc3VsdFsyXSA9IC1tYXRyaXhbMl07CiAgICAgICAgcmVzdWx0WzNdID0gLW1hdHJpeFszXTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgyLnRyYW5zcG9zZSA9IGZ1bmN0aW9uKG1hdHJpeCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICBjb25zdCBjb2x1bW4wUm93MCA9IG1hdHJpeFswXTsKICAgICAgICBjb25zdCBjb2x1bW4wUm93MSA9IG1hdHJpeFsyXTsKICAgICAgICBjb25zdCBjb2x1bW4xUm93MCA9IG1hdHJpeFsxXTsKICAgICAgICBjb25zdCBjb2x1bW4xUm93MSA9IG1hdHJpeFszXTsKICAgICAgICByZXN1bHRbMF0gPSBjb2x1bW4wUm93MDsKICAgICAgICByZXN1bHRbMV0gPSBjb2x1bW4wUm93MTsKICAgICAgICByZXN1bHRbMl0gPSBjb2x1bW4xUm93MDsKICAgICAgICByZXN1bHRbM10gPSBjb2x1bW4xUm93MTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBNYXRyaXgyLmFicyA9IGZ1bmN0aW9uKG1hdHJpeCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHRbMF0gPSBNYXRoLmFicyhtYXRyaXhbMF0pOwogICAgICAgIHJlc3VsdFsxXSA9IE1hdGguYWJzKG1hdHJpeFsxXSk7CiAgICAgICAgcmVzdWx0WzJdID0gTWF0aC5hYnMobWF0cml4WzJdKTsKICAgICAgICByZXN1bHRbM10gPSBNYXRoLmFicyhtYXRyaXhbM10pOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE1hdHJpeDIuZXF1YWxzID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHsKICAgICAgICByZXR1cm4gbGVmdCA9PT0gcmlnaHQgfHwgZGVmaW5lZF9kZWZhdWx0KGxlZnQpICYmIGRlZmluZWRfZGVmYXVsdChyaWdodCkgJiYgbGVmdFswXSA9PT0gcmlnaHRbMF0gJiYgbGVmdFsxXSA9PT0gcmlnaHRbMV0gJiYgbGVmdFsyXSA9PT0gcmlnaHRbMl0gJiYgbGVmdFszXSA9PT0gcmlnaHRbM107CiAgICAgIH07CiAgICAgIE1hdHJpeDIuZXF1YWxzQXJyYXkgPSBmdW5jdGlvbihtYXRyaXgsIGFycmF5LCBvZmZzZXQpIHsKICAgICAgICByZXR1cm4gbWF0cml4WzBdID09PSBhcnJheVtvZmZzZXRdICYmIG1hdHJpeFsxXSA9PT0gYXJyYXlbb2Zmc2V0ICsgMV0gJiYgbWF0cml4WzJdID09PSBhcnJheVtvZmZzZXQgKyAyXSAmJiBtYXRyaXhbM10gPT09IGFycmF5W29mZnNldCArIDNdOwogICAgICB9OwogICAgICBNYXRyaXgyLmVxdWFsc0Vwc2lsb24gPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgZXBzaWxvbikgewogICAgICAgIGVwc2lsb24gPSBlcHNpbG9uID8/IDA7CiAgICAgICAgcmV0dXJuIGxlZnQgPT09IHJpZ2h0IHx8IGRlZmluZWRfZGVmYXVsdChsZWZ0KSAmJiBkZWZpbmVkX2RlZmF1bHQocmlnaHQpICYmIE1hdGguYWJzKGxlZnRbMF0gLSByaWdodFswXSkgPD0gZXBzaWxvbiAmJiBNYXRoLmFicyhsZWZ0WzFdIC0gcmlnaHRbMV0pIDw9IGVwc2lsb24gJiYgTWF0aC5hYnMobGVmdFsyXSAtIHJpZ2h0WzJdKSA8PSBlcHNpbG9uICYmIE1hdGguYWJzKGxlZnRbM10gLSByaWdodFszXSkgPD0gZXBzaWxvbjsKICAgICAgfTsKICAgICAgTWF0cml4Mi5JREVOVElUWSA9IE9iamVjdC5mcmVlemUobmV3IE1hdHJpeDIoMSwgMCwgMCwgMSkpOwogICAgICBNYXRyaXgyLlpFUk8gPSBPYmplY3QuZnJlZXplKG5ldyBNYXRyaXgyKDAsIDAsIDAsIDApKTsKICAgICAgTWF0cml4Mi5DT0xVTU4wUk9XMCA9IDA7CiAgICAgIE1hdHJpeDIuQ09MVU1OMFJPVzEgPSAxOwogICAgICBNYXRyaXgyLkNPTFVNTjFST1cwID0gMjsKICAgICAgTWF0cml4Mi5DT0xVTU4xUk9XMSA9IDM7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKE1hdHJpeDIucHJvdG90eXBlLCB7CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgbnVtYmVyIG9mIGl0ZW1zIGluIHRoZSBjb2xsZWN0aW9uLgogICAgICAgICAqIEBtZW1iZXJvZiBNYXRyaXgyLnByb3RvdHlwZQogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKi8KICAgICAgICBsZW5ndGg6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBNYXRyaXgyLnBhY2tlZExlbmd0aDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBNYXRyaXgyLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAgIHJldHVybiBNYXRyaXgyLmNsb25lKHRoaXMsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIE1hdHJpeDIucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uKHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIE1hdHJpeDIuZXF1YWxzKHRoaXMsIHJpZ2h0KTsKICAgICAgfTsKICAgICAgTWF0cml4Mi5wcm90b3R5cGUuZXF1YWxzRXBzaWxvbiA9IGZ1bmN0aW9uKHJpZ2h0LCBlcHNpbG9uKSB7CiAgICAgICAgcmV0dXJuIE1hdHJpeDIuZXF1YWxzRXBzaWxvbih0aGlzLCByaWdodCwgZXBzaWxvbik7CiAgICAgIH07CiAgICAgIE1hdHJpeDIucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIGAoJHt0aGlzWzBdfSwgJHt0aGlzWzJdfSkKKCR7dGhpc1sxXX0sICR7dGhpc1szXX0pYDsKICAgICAgfTsKICAgICAgTWF0cml4Ml9kZWZhdWx0ID0gTWF0cml4MjsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1ByaW1pdGl2ZVR5cGUuanMKICB2YXIgUHJpbWl0aXZlVHlwZSwgUHJpbWl0aXZlVHlwZV9kZWZhdWx0OwogIHZhciBpbml0X1ByaW1pdGl2ZVR5cGUgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1ByaW1pdGl2ZVR5cGUuanMiKCkgewogICAgICBpbml0X1dlYkdMQ29uc3RhbnRzKCk7CiAgICAgIFByaW1pdGl2ZVR5cGUgPSB7CiAgICAgICAgLyoqCiAgICAgICAgICogUG9pbnRzIHByaW1pdGl2ZSB3aGVyZSBlYWNoIHZlcnRleCAob3IgaW5kZXgpIGlzIGEgc2VwYXJhdGUgcG9pbnQuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFBPSU5UUzogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5QT0lOVFMsCiAgICAgICAgLyoqCiAgICAgICAgICogTGluZXMgcHJpbWl0aXZlIHdoZXJlIGVhY2ggdHdvIHZlcnRpY2VzIChvciBpbmRpY2VzKSBpcyBhIGxpbmUgc2VnbWVudC4gIExpbmUgc2VnbWVudHMgYXJlIG5vdCBuZWNlc3NhcmlseSBjb25uZWN0ZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIExJTkVTOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkxJTkVTLAogICAgICAgIC8qKgogICAgICAgICAqIExpbmUgbG9vcCBwcmltaXRpdmUgd2hlcmUgZWFjaCB2ZXJ0ZXggKG9yIGluZGV4KSBhZnRlciB0aGUgZmlyc3QgY29ubmVjdHMgYSBsaW5lIHRvCiAgICAgICAgICogdGhlIHByZXZpb3VzIHZlcnRleCwgYW5kIHRoZSBsYXN0IHZlcnRleCBpbXBsaWNpdGx5IGNvbm5lY3RzIHRvIHRoZSBmaXJzdC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgTElORV9MT09QOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkxJTkVfTE9PUCwKICAgICAgICAvKioKICAgICAgICAgKiBMaW5lIHN0cmlwIHByaW1pdGl2ZSB3aGVyZSBlYWNoIHZlcnRleCAob3IgaW5kZXgpIGFmdGVyIHRoZSBmaXJzdCBjb25uZWN0cyBhIGxpbmUgdG8gdGhlIHByZXZpb3VzIHZlcnRleC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgTElORV9TVFJJUDogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5MSU5FX1NUUklQLAogICAgICAgIC8qKgogICAgICAgICAqIFRyaWFuZ2xlcyBwcmltaXRpdmUgd2hlcmUgZWFjaCB0aHJlZSB2ZXJ0aWNlcyAob3IgaW5kaWNlcykgaXMgYSB0cmlhbmdsZS4gIFRyaWFuZ2xlcyBkbyBub3QgbmVjZXNzYXJpbHkgc2hhcmUgZWRnZXMuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFRSSUFOR0xFUzogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5UUklBTkdMRVMsCiAgICAgICAgLyoqCiAgICAgICAgICogVHJpYW5nbGUgc3RyaXAgcHJpbWl0aXZlIHdoZXJlIGVhY2ggdmVydGV4IChvciBpbmRleCkgYWZ0ZXIgdGhlIGZpcnN0IHR3byBjb25uZWN0IHRvCiAgICAgICAgICogdGhlIHByZXZpb3VzIHR3byB2ZXJ0aWNlcyBmb3JtaW5nIGEgdHJpYW5nbGUuICBGb3IgZXhhbXBsZSwgdGhpcyBjYW4gYmUgdXNlZCB0byBtb2RlbCBhIHdhbGwuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFRSSUFOR0xFX1NUUklQOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlRSSUFOR0xFX1NUUklQLAogICAgICAgIC8qKgogICAgICAgICAqIFRyaWFuZ2xlIGZhbiBwcmltaXRpdmUgd2hlcmUgZWFjaCB2ZXJ0ZXggKG9yIGluZGV4KSBhZnRlciB0aGUgZmlyc3QgdHdvIGNvbm5lY3QgdG8KICAgICAgICAgKiB0aGUgcHJldmlvdXMgdmVydGV4IGFuZCB0aGUgZmlyc3QgdmVydGV4IGZvcm1pbmcgYSB0cmlhbmdsZS4gIEZvciBleGFtcGxlLCB0aGlzIGNhbiBiZSB1c2VkCiAgICAgICAgICogdG8gbW9kZWwgYSBjb25lIG9yIGNpcmNsZS4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgVFJJQU5HTEVfRkFOOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlRSSUFOR0xFX0ZBTgogICAgICB9OwogICAgICBQcmltaXRpdmVUeXBlLmlzTGluZXMgPSBmdW5jdGlvbihwcmltaXRpdmVUeXBlKSB7CiAgICAgICAgcmV0dXJuIHByaW1pdGl2ZVR5cGUgPT09IFByaW1pdGl2ZVR5cGUuTElORVMgfHwgcHJpbWl0aXZlVHlwZSA9PT0gUHJpbWl0aXZlVHlwZS5MSU5FX0xPT1AgfHwgcHJpbWl0aXZlVHlwZSA9PT0gUHJpbWl0aXZlVHlwZS5MSU5FX1NUUklQOwogICAgICB9OwogICAgICBQcmltaXRpdmVUeXBlLmlzVHJpYW5nbGVzID0gZnVuY3Rpb24ocHJpbWl0aXZlVHlwZSkgewogICAgICAgIHJldHVybiBwcmltaXRpdmVUeXBlID09PSBQcmltaXRpdmVUeXBlLlRSSUFOR0xFUyB8fCBwcmltaXRpdmVUeXBlID09PSBQcmltaXRpdmVUeXBlLlRSSUFOR0xFX1NUUklQIHx8IHByaW1pdGl2ZVR5cGUgPT09IFByaW1pdGl2ZVR5cGUuVFJJQU5HTEVfRkFOOwogICAgICB9OwogICAgICBQcmltaXRpdmVUeXBlLnZhbGlkYXRlID0gZnVuY3Rpb24ocHJpbWl0aXZlVHlwZSkgewogICAgICAgIHJldHVybiBwcmltaXRpdmVUeXBlID09PSBQcmltaXRpdmVUeXBlLlBPSU5UUyB8fCBwcmltaXRpdmVUeXBlID09PSBQcmltaXRpdmVUeXBlLkxJTkVTIHx8IHByaW1pdGl2ZVR5cGUgPT09IFByaW1pdGl2ZVR5cGUuTElORV9MT09QIHx8IHByaW1pdGl2ZVR5cGUgPT09IFByaW1pdGl2ZVR5cGUuTElORV9TVFJJUCB8fCBwcmltaXRpdmVUeXBlID09PSBQcmltaXRpdmVUeXBlLlRSSUFOR0xFUyB8fCBwcmltaXRpdmVUeXBlID09PSBQcmltaXRpdmVUeXBlLlRSSUFOR0xFX1NUUklQIHx8IHByaW1pdGl2ZVR5cGUgPT09IFByaW1pdGl2ZVR5cGUuVFJJQU5HTEVfRkFOOwogICAgICB9OwogICAgICBQcmltaXRpdmVUeXBlX2RlZmF1bHQgPSBPYmplY3QuZnJlZXplKFByaW1pdGl2ZVR5cGUpOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvR2VvbWV0cnkuanMKICBmdW5jdGlvbiBHZW9tZXRyeShvcHRpb25zKSB7CiAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm9wdGlvbnMuYXR0cmlidXRlcyIsIG9wdGlvbnMuYXR0cmlidXRlcyk7CiAgICB0aGlzLmF0dHJpYnV0ZXMgPSBvcHRpb25zLmF0dHJpYnV0ZXM7CiAgICB0aGlzLmluZGljZXMgPSBvcHRpb25zLmluZGljZXM7CiAgICB0aGlzLnByaW1pdGl2ZVR5cGUgPSBvcHRpb25zLnByaW1pdGl2ZVR5cGUgPz8gUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUzsKICAgIHRoaXMuYm91bmRpbmdTcGhlcmUgPSBvcHRpb25zLmJvdW5kaW5nU3BoZXJlOwogICAgdGhpcy5nZW9tZXRyeVR5cGUgPSBvcHRpb25zLmdlb21ldHJ5VHlwZSA/PyBHZW9tZXRyeVR5cGVfZGVmYXVsdC5OT05FOwogICAgdGhpcy5ib3VuZGluZ1NwaGVyZUNWID0gb3B0aW9ucy5ib3VuZGluZ1NwaGVyZUNWOwogICAgdGhpcy5vZmZzZXRBdHRyaWJ1dGUgPSBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZTsKICB9CiAgdmFyIHJlY3RhbmdsZUNlbnRlclNjcmF0Y2gsIGVudUNlbnRlclNjcmF0Y2gsIGZpeGVkRnJhbWVUb0VudVNjcmF0Y2gsIGJvdW5kaW5nUmVjdGFuZ2xlUG9pbnRzQ2FydG9ncmFwaGljU2NyYXRjaCwgYm91bmRpbmdSZWN0YW5nbGVQb2ludHNFbnVTY3JhdGNoLCBwb2ludHMyRFNjcmF0Y2gsIHBvaW50RW51U2NyYXRjaCwgZW51Um90YXRpb25TY3JhdGNoLCBlbnVSb3RhdGlvbk1hdHJpeFNjcmF0Y2gsIHJvdGF0aW9uMkRTY3JhdGNoLCBHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X0dlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9HZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMigpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DYXJ0b2dyYXBoaWMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0dlb21ldHJ5VHlwZSgpOwogICAgICBpbml0X01hdHJpeDIoKTsKICAgICAgaW5pdF9NYXRyaXgzKCk7CiAgICAgIGluaXRfTWF0cml4NCgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgaW5pdF9RdWF0ZXJuaW9uKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfVHJhbnNmb3JtcygpOwogICAgICBHZW9tZXRyeS5jb21wdXRlTnVtYmVyT2ZWZXJ0aWNlcyA9IGZ1bmN0aW9uKGdlb21ldHJ5KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJnZW9tZXRyeSIsIGdlb21ldHJ5KTsKICAgICAgICBsZXQgbnVtYmVyT2ZWZXJ0aWNlcyA9IC0xOwogICAgICAgIGZvciAoY29uc3QgcHJvcGVydHkgaW4gZ2VvbWV0cnkuYXR0cmlidXRlcykgewogICAgICAgICAgaWYgKGdlb21ldHJ5LmF0dHJpYnV0ZXMuaGFzT3duUHJvcGVydHkocHJvcGVydHkpICYmIGRlZmluZWRfZGVmYXVsdChnZW9tZXRyeS5hdHRyaWJ1dGVzW3Byb3BlcnR5XSkgJiYgZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5LmF0dHJpYnV0ZXNbcHJvcGVydHldLnZhbHVlcykpIHsKICAgICAgICAgICAgY29uc3QgYXR0cmlidXRlID0gZ2VvbWV0cnkuYXR0cmlidXRlc1twcm9wZXJ0eV07CiAgICAgICAgICAgIGNvbnN0IG51bSA9IGF0dHJpYnV0ZS52YWx1ZXMubGVuZ3RoIC8gYXR0cmlidXRlLmNvbXBvbmVudHNQZXJBdHRyaWJ1dGU7CiAgICAgICAgICAgIGlmIChudW1iZXJPZlZlcnRpY2VzICE9PSBudW0gJiYgbnVtYmVyT2ZWZXJ0aWNlcyAhPT0gLTEpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgICAgICJBbGwgYXR0cmlidXRlIGxpc3RzIG11c3QgaGF2ZSB0aGUgc2FtZSBudW1iZXIgb2YgYXR0cmlidXRlcy4iCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBudW1iZXJPZlZlcnRpY2VzID0gbnVtOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gbnVtYmVyT2ZWZXJ0aWNlczsKICAgICAgfTsKICAgICAgcmVjdGFuZ2xlQ2VudGVyU2NyYXRjaCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBlbnVDZW50ZXJTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBmaXhlZEZyYW1lVG9FbnVTY3JhdGNoID0gbmV3IE1hdHJpeDRfZGVmYXVsdCgpOwogICAgICBib3VuZGluZ1JlY3RhbmdsZVBvaW50c0NhcnRvZ3JhcGhpY1NjcmF0Y2ggPSBbCiAgICAgICAgbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCksCiAgICAgICAgbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCksCiAgICAgICAgbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCkKICAgICAgXTsKICAgICAgYm91bmRpbmdSZWN0YW5nbGVQb2ludHNFbnVTY3JhdGNoID0gWwogICAgICAgIG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKSwKICAgICAgICBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCksCiAgICAgICAgbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpCiAgICAgIF07CiAgICAgIHBvaW50czJEU2NyYXRjaCA9IFtuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCksIG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKSwgbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpXTsKICAgICAgcG9pbnRFbnVTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBlbnVSb3RhdGlvblNjcmF0Y2ggPSBuZXcgUXVhdGVybmlvbl9kZWZhdWx0KCk7CiAgICAgIGVudVJvdGF0aW9uTWF0cml4U2NyYXRjaCA9IG5ldyBNYXRyaXg0X2RlZmF1bHQoKTsKICAgICAgcm90YXRpb24yRFNjcmF0Y2ggPSBuZXcgTWF0cml4Ml9kZWZhdWx0KCk7CiAgICAgIEdlb21ldHJ5Ll90ZXh0dXJlQ29vcmRpbmF0ZVJvdGF0aW9uUG9pbnRzID0gZnVuY3Rpb24ocG9zaXRpb25zLCBzdFJvdGF0aW9uLCBlbGxpcHNvaWQsIGJvdW5kaW5nUmVjdGFuZ2xlKSB7CiAgICAgICAgbGV0IGk7CiAgICAgICAgY29uc3QgcmVjdGFuZ2xlQ2VudGVyID0gUmVjdGFuZ2xlX2RlZmF1bHQuY2VudGVyKAogICAgICAgICAgYm91bmRpbmdSZWN0YW5nbGUsCiAgICAgICAgICByZWN0YW5nbGVDZW50ZXJTY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBjb25zdCBlbnVDZW50ZXIgPSBDYXJ0b2dyYXBoaWNfZGVmYXVsdC50b0NhcnRlc2lhbigKICAgICAgICAgIHJlY3RhbmdsZUNlbnRlciwKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIGVudUNlbnRlclNjcmF0Y2gKICAgICAgICApOwogICAgICAgIGNvbnN0IGVudVRvRml4ZWRGcmFtZSA9IFRyYW5zZm9ybXNfZGVmYXVsdC5lYXN0Tm9ydGhVcFRvRml4ZWRGcmFtZSgKICAgICAgICAgIGVudUNlbnRlciwKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIGZpeGVkRnJhbWVUb0VudVNjcmF0Y2gKICAgICAgICApOwogICAgICAgIGNvbnN0IGZpeGVkRnJhbWVUb0VudSA9IE1hdHJpeDRfZGVmYXVsdC5pbnZlcnNlKAogICAgICAgICAgZW51VG9GaXhlZEZyYW1lLAogICAgICAgICAgZml4ZWRGcmFtZVRvRW51U2NyYXRjaAogICAgICAgICk7CiAgICAgICAgY29uc3QgYm91bmRpbmdQb2ludHNFbnUgPSBib3VuZGluZ1JlY3RhbmdsZVBvaW50c0VudVNjcmF0Y2g7CiAgICAgICAgY29uc3QgYm91bmRpbmdQb2ludHNDYXJ0byA9IGJvdW5kaW5nUmVjdGFuZ2xlUG9pbnRzQ2FydG9ncmFwaGljU2NyYXRjaDsKICAgICAgICBib3VuZGluZ1BvaW50c0NhcnRvWzBdLmxvbmdpdHVkZSA9IGJvdW5kaW5nUmVjdGFuZ2xlLndlc3Q7CiAgICAgICAgYm91bmRpbmdQb2ludHNDYXJ0b1swXS5sYXRpdHVkZSA9IGJvdW5kaW5nUmVjdGFuZ2xlLnNvdXRoOwogICAgICAgIGJvdW5kaW5nUG9pbnRzQ2FydG9bMV0ubG9uZ2l0dWRlID0gYm91bmRpbmdSZWN0YW5nbGUud2VzdDsKICAgICAgICBib3VuZGluZ1BvaW50c0NhcnRvWzFdLmxhdGl0dWRlID0gYm91bmRpbmdSZWN0YW5nbGUubm9ydGg7CiAgICAgICAgYm91bmRpbmdQb2ludHNDYXJ0b1syXS5sb25naXR1ZGUgPSBib3VuZGluZ1JlY3RhbmdsZS5lYXN0OwogICAgICAgIGJvdW5kaW5nUG9pbnRzQ2FydG9bMl0ubGF0aXR1ZGUgPSBib3VuZGluZ1JlY3RhbmdsZS5zb3V0aDsKICAgICAgICBsZXQgcG9zRW51ID0gcG9pbnRFbnVTY3JhdGNoOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCAzOyBpKyspIHsKICAgICAgICAgIENhcnRvZ3JhcGhpY19kZWZhdWx0LnRvQ2FydGVzaWFuKGJvdW5kaW5nUG9pbnRzQ2FydG9baV0sIGVsbGlwc29pZCwgcG9zRW51KTsKICAgICAgICAgIHBvc0VudSA9IE1hdHJpeDRfZGVmYXVsdC5tdWx0aXBseUJ5UG9pbnRBc1ZlY3RvcihmaXhlZEZyYW1lVG9FbnUsIHBvc0VudSwgcG9zRW51KTsKICAgICAgICAgIGJvdW5kaW5nUG9pbnRzRW51W2ldLnggPSBwb3NFbnUueDsKICAgICAgICAgIGJvdW5kaW5nUG9pbnRzRW51W2ldLnkgPSBwb3NFbnUueTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgcm90YXRpb24gPSBRdWF0ZXJuaW9uX2RlZmF1bHQuZnJvbUF4aXNBbmdsZSgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1osCiAgICAgICAgICAtc3RSb3RhdGlvbiwKICAgICAgICAgIGVudVJvdGF0aW9uU2NyYXRjaAogICAgICAgICk7CiAgICAgICAgY29uc3QgdGV4dHVyZU1hdHJpeCA9IE1hdHJpeDNfZGVmYXVsdC5mcm9tUXVhdGVybmlvbigKICAgICAgICAgIHJvdGF0aW9uLAogICAgICAgICAgZW51Um90YXRpb25NYXRyaXhTY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBjb25zdCBwb3NpdGlvbnNMZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgICAgIGxldCBlbnVNaW5YID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgICAgIGxldCBlbnVNaW5ZID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgICAgIGxldCBlbnVNYXhYID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZOwogICAgICAgIGxldCBlbnVNYXhZID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBwb3NpdGlvbnNMZW5ndGg7IGkrKykgewogICAgICAgICAgcG9zRW51ID0gTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5QnlQb2ludEFzVmVjdG9yKAogICAgICAgICAgICBmaXhlZEZyYW1lVG9FbnUsCiAgICAgICAgICAgIHBvc2l0aW9uc1tpXSwKICAgICAgICAgICAgcG9zRW51CiAgICAgICAgICApOwogICAgICAgICAgcG9zRW51ID0gTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3IodGV4dHVyZU1hdHJpeCwgcG9zRW51LCBwb3NFbnUpOwogICAgICAgICAgZW51TWluWCA9IE1hdGgubWluKGVudU1pblgsIHBvc0VudS54KTsKICAgICAgICAgIGVudU1pblkgPSBNYXRoLm1pbihlbnVNaW5ZLCBwb3NFbnUueSk7CiAgICAgICAgICBlbnVNYXhYID0gTWF0aC5tYXgoZW51TWF4WCwgcG9zRW51LngpOwogICAgICAgICAgZW51TWF4WSA9IE1hdGgubWF4KGVudU1heFksIHBvc0VudS55KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgdG9EZXNpcmVkSW5Db21wdXRlZCA9IE1hdHJpeDJfZGVmYXVsdC5mcm9tUm90YXRpb24oCiAgICAgICAgICBzdFJvdGF0aW9uLAogICAgICAgICAgcm90YXRpb24yRFNjcmF0Y2gKICAgICAgICApOwogICAgICAgIGNvbnN0IHBvaW50czJEID0gcG9pbnRzMkRTY3JhdGNoOwogICAgICAgIHBvaW50czJEWzBdLnggPSBlbnVNaW5YOwogICAgICAgIHBvaW50czJEWzBdLnkgPSBlbnVNaW5ZOwogICAgICAgIHBvaW50czJEWzFdLnggPSBlbnVNaW5YOwogICAgICAgIHBvaW50czJEWzFdLnkgPSBlbnVNYXhZOwogICAgICAgIHBvaW50czJEWzJdLnggPSBlbnVNYXhYOwogICAgICAgIHBvaW50czJEWzJdLnkgPSBlbnVNaW5ZOwogICAgICAgIGNvbnN0IGJvdW5kaW5nRW51TWluID0gYm91bmRpbmdQb2ludHNFbnVbMF07CiAgICAgICAgY29uc3QgYm91bmRpbmdQb2ludHNXaWR0aCA9IGJvdW5kaW5nUG9pbnRzRW51WzJdLnggLSBib3VuZGluZ0VudU1pbi54OwogICAgICAgIGNvbnN0IGJvdW5kaW5nUG9pbnRzSGVpZ2h0ID0gYm91bmRpbmdQb2ludHNFbnVbMV0ueSAtIGJvdW5kaW5nRW51TWluLnk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IDM7IGkrKykgewogICAgICAgICAgY29uc3QgcG9pbnQyRCA9IHBvaW50czJEW2ldOwogICAgICAgICAgTWF0cml4Ml9kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3IodG9EZXNpcmVkSW5Db21wdXRlZCwgcG9pbnQyRCwgcG9pbnQyRCk7CiAgICAgICAgICBwb2ludDJELnggPSAocG9pbnQyRC54IC0gYm91bmRpbmdFbnVNaW4ueCkgLyBib3VuZGluZ1BvaW50c1dpZHRoOwogICAgICAgICAgcG9pbnQyRC55ID0gKHBvaW50MkQueSAtIGJvdW5kaW5nRW51TWluLnkpIC8gYm91bmRpbmdQb2ludHNIZWlnaHQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG1pblhZQ29ybmVyID0gcG9pbnRzMkRbMF07CiAgICAgICAgY29uc3QgbWF4WUNvcm5lciA9IHBvaW50czJEWzFdOwogICAgICAgIGNvbnN0IG1heFhDb3JuZXIgPSBwb2ludHMyRFsyXTsKICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXkoNik7CiAgICAgICAgQ2FydGVzaWFuMl9kZWZhdWx0LnBhY2sobWluWFlDb3JuZXIsIHJlc3VsdCk7CiAgICAgICAgQ2FydGVzaWFuMl9kZWZhdWx0LnBhY2sobWF4WUNvcm5lciwgcmVzdWx0LCAyKTsKICAgICAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQucGFjayhtYXhYQ29ybmVyLCByZXN1bHQsIDQpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEdlb21ldHJ5X2RlZmF1bHQgPSBHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dlb21ldHJ5QXR0cmlidXRlLmpzCiAgZnVuY3Rpb24gR2VvbWV0cnlBdHRyaWJ1dGUob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQob3B0aW9ucy5jb21wb25lbnREYXRhdHlwZSkpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9wdGlvbnMuY29tcG9uZW50RGF0YXR5cGUgaXMgcmVxdWlyZWQuIik7CiAgICB9CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChvcHRpb25zLmNvbXBvbmVudHNQZXJBdHRyaWJ1dGUpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJvcHRpb25zLmNvbXBvbmVudHNQZXJBdHRyaWJ1dGUgaXMgcmVxdWlyZWQuIik7CiAgICB9CiAgICBpZiAob3B0aW9ucy5jb21wb25lbnRzUGVyQXR0cmlidXRlIDwgMSB8fCBvcHRpb25zLmNvbXBvbmVudHNQZXJBdHRyaWJ1dGUgPiA0KSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICJvcHRpb25zLmNvbXBvbmVudHNQZXJBdHRyaWJ1dGUgbXVzdCBiZSBiZXR3ZWVuIDEgYW5kIDQuIgogICAgICApOwogICAgfQogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQob3B0aW9ucy52YWx1ZXMpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJvcHRpb25zLnZhbHVlcyBpcyByZXF1aXJlZC4iKTsKICAgIH0KICAgIHRoaXMuY29tcG9uZW50RGF0YXR5cGUgPSBvcHRpb25zLmNvbXBvbmVudERhdGF0eXBlOwogICAgdGhpcy5jb21wb25lbnRzUGVyQXR0cmlidXRlID0gb3B0aW9ucy5jb21wb25lbnRzUGVyQXR0cmlidXRlOwogICAgdGhpcy5ub3JtYWxpemUgPSBvcHRpb25zLm5vcm1hbGl6ZSA/PyBmYWxzZTsKICAgIHRoaXMudmFsdWVzID0gb3B0aW9ucy52YWx1ZXM7CiAgfQogIHZhciBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0OwogIHZhciBpbml0X0dlb21ldHJ5QXR0cmlidXRlID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9HZW9tZXRyeUF0dHJpYnV0ZS5qcyIoKSB7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQgPSBHZW9tZXRyeUF0dHJpYnV0ZTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dlb21ldHJ5QXR0cmlidXRlcy5qcwogIGZ1bmN0aW9uIEdlb21ldHJ5QXR0cmlidXRlcyhvcHRpb25zKSB7CiAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICB0aGlzLnBvc2l0aW9uID0gb3B0aW9ucy5wb3NpdGlvbjsKICAgIHRoaXMubm9ybWFsID0gb3B0aW9ucy5ub3JtYWw7CiAgICB0aGlzLnN0ID0gb3B0aW9ucy5zdDsKICAgIHRoaXMuYml0YW5nZW50ID0gb3B0aW9ucy5iaXRhbmdlbnQ7CiAgICB0aGlzLnRhbmdlbnQgPSBvcHRpb25zLnRhbmdlbnQ7CiAgICB0aGlzLmNvbG9yID0gb3B0aW9ucy5jb2xvcjsKICB9CiAgdmFyIEdlb21ldHJ5QXR0cmlidXRlc19kZWZhdWx0OwogIHZhciBpbml0X0dlb21ldHJ5QXR0cmlidXRlcyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvR2VvbWV0cnlBdHRyaWJ1dGVzLmpzIigpIHsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQgPSBHZW9tZXRyeUF0dHJpYnV0ZXM7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvU2NlbmUvQXR0cmlidXRlVHlwZS5qcwogIHZhciBBdHRyaWJ1dGVUeXBlLCBBdHRyaWJ1dGVUeXBlX2RlZmF1bHQ7CiAgdmFyIGluaXRfQXR0cmlidXRlVHlwZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1NjZW5lL0F0dHJpYnV0ZVR5cGUuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuNCgpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9NYXRyaXgyKCk7CiAgICAgIGluaXRfTWF0cml4MygpOwogICAgICBpbml0X01hdHJpeDQoKTsKICAgICAgQXR0cmlidXRlVHlwZSA9IHsKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgYXR0cmlidXRlIGlzIGEgc2luZ2xlIGNvbXBvbmVudC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtzdHJpbmd9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgU0NBTEFSOiAiU0NBTEFSIiwKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgYXR0cmlidXRlIGlzIGEgdHdvLWNvbXBvbmVudCB2ZWN0b3IuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7c3RyaW5nfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFZFQzI6ICJWRUMyIiwKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgYXR0cmlidXRlIGlzIGEgdGhyZWUtY29tcG9uZW50IHZlY3Rvci4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtzdHJpbmd9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgVkVDMzogIlZFQzMiLAogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBhdHRyaWJ1dGUgaXMgYSBmb3VyLWNvbXBvbmVudCB2ZWN0b3IuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7c3RyaW5nfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFZFQzQ6ICJWRUM0IiwKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgYXR0cmlidXRlIGlzIGEgMngyIG1hdHJpeC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtzdHJpbmd9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgTUFUMjogIk1BVDIiLAogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBhdHRyaWJ1dGUgaXMgYSAzeDMgbWF0cml4LgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge3N0cmluZ30KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBNQVQzOiAiTUFUMyIsCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIGF0dHJpYnV0ZSBpcyBhIDR4NCBtYXRyaXguCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7c3RyaW5nfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIE1BVDQ6ICJNQVQ0IgogICAgICB9OwogICAgICBBdHRyaWJ1dGVUeXBlLmdldE1hdGhUeXBlID0gZnVuY3Rpb24oYXR0cmlidXRlVHlwZSkgewogICAgICAgIHN3aXRjaCAoYXR0cmlidXRlVHlwZSkgewogICAgICAgICAgY2FzZSBBdHRyaWJ1dGVUeXBlLlNDQUxBUjoKICAgICAgICAgICAgcmV0dXJuIE51bWJlcjsKICAgICAgICAgIGNhc2UgQXR0cmlidXRlVHlwZS5WRUMyOgogICAgICAgICAgICByZXR1cm4gQ2FydGVzaWFuMl9kZWZhdWx0OwogICAgICAgICAgY2FzZSBBdHRyaWJ1dGVUeXBlLlZFQzM6CiAgICAgICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQ7CiAgICAgICAgICBjYXNlIEF0dHJpYnV0ZVR5cGUuVkVDNDoKICAgICAgICAgICAgcmV0dXJuIENhcnRlc2lhbjRfZGVmYXVsdDsKICAgICAgICAgIGNhc2UgQXR0cmlidXRlVHlwZS5NQVQyOgogICAgICAgICAgICByZXR1cm4gTWF0cml4Ml9kZWZhdWx0OwogICAgICAgICAgY2FzZSBBdHRyaWJ1dGVUeXBlLk1BVDM6CiAgICAgICAgICAgIHJldHVybiBNYXRyaXgzX2RlZmF1bHQ7CiAgICAgICAgICBjYXNlIEF0dHJpYnV0ZVR5cGUuTUFUNDoKICAgICAgICAgICAgcmV0dXJuIE1hdHJpeDRfZGVmYXVsdDsKICAgICAgICAgIC8vPj5pbmNsdWRlU3RhcnQoJ2RlYnVnJywgcHJhZ21hcy5kZWJ1Zyk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYXR0cmlidXRlVHlwZSBpcyBub3QgYSB2YWxpZCB2YWx1ZS4iKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIEF0dHJpYnV0ZVR5cGUuZ2V0TnVtYmVyT2ZDb21wb25lbnRzID0gZnVuY3Rpb24oYXR0cmlidXRlVHlwZSkgewogICAgICAgIHN3aXRjaCAoYXR0cmlidXRlVHlwZSkgewogICAgICAgICAgY2FzZSBBdHRyaWJ1dGVUeXBlLlNDQUxBUjoKICAgICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgICBjYXNlIEF0dHJpYnV0ZVR5cGUuVkVDMjoKICAgICAgICAgICAgcmV0dXJuIDI7CiAgICAgICAgICBjYXNlIEF0dHJpYnV0ZVR5cGUuVkVDMzoKICAgICAgICAgICAgcmV0dXJuIDM7CiAgICAgICAgICBjYXNlIEF0dHJpYnV0ZVR5cGUuVkVDNDoKICAgICAgICAgIGNhc2UgQXR0cmlidXRlVHlwZS5NQVQyOgogICAgICAgICAgICByZXR1cm4gNDsKICAgICAgICAgIGNhc2UgQXR0cmlidXRlVHlwZS5NQVQzOgogICAgICAgICAgICByZXR1cm4gOTsKICAgICAgICAgIGNhc2UgQXR0cmlidXRlVHlwZS5NQVQ0OgogICAgICAgICAgICByZXR1cm4gMTY7CiAgICAgICAgICAvLz4+aW5jbHVkZVN0YXJ0KCdkZWJ1ZycsIHByYWdtYXMuZGVidWcpOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImF0dHJpYnV0ZVR5cGUgaXMgbm90IGEgdmFsaWQgdmFsdWUuIik7CiAgICAgICAgfQogICAgICB9OwogICAgICBBdHRyaWJ1dGVUeXBlLmdldEF0dHJpYnV0ZUxvY2F0aW9uQ291bnQgPSBmdW5jdGlvbihhdHRyaWJ1dGVUeXBlKSB7CiAgICAgICAgc3dpdGNoIChhdHRyaWJ1dGVUeXBlKSB7CiAgICAgICAgICBjYXNlIEF0dHJpYnV0ZVR5cGUuU0NBTEFSOgogICAgICAgICAgY2FzZSBBdHRyaWJ1dGVUeXBlLlZFQzI6CiAgICAgICAgICBjYXNlIEF0dHJpYnV0ZVR5cGUuVkVDMzoKICAgICAgICAgIGNhc2UgQXR0cmlidXRlVHlwZS5WRUM0OgogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICAgIGNhc2UgQXR0cmlidXRlVHlwZS5NQVQyOgogICAgICAgICAgICByZXR1cm4gMjsKICAgICAgICAgIGNhc2UgQXR0cmlidXRlVHlwZS5NQVQzOgogICAgICAgICAgICByZXR1cm4gMzsKICAgICAgICAgIGNhc2UgQXR0cmlidXRlVHlwZS5NQVQ0OgogICAgICAgICAgICByZXR1cm4gNDsKICAgICAgICAgIC8vPj5pbmNsdWRlU3RhcnQoJ2RlYnVnJywgcHJhZ21hcy5kZWJ1Zyk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYXR0cmlidXRlVHlwZSBpcyBub3QgYSB2YWxpZCB2YWx1ZS4iKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIEF0dHJpYnV0ZVR5cGUuZ2V0R2xzbFR5cGUgPSBmdW5jdGlvbihhdHRyaWJ1dGVUeXBlKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yuc3RyaW5nKCJhdHRyaWJ1dGVUeXBlIiwgYXR0cmlidXRlVHlwZSk7CiAgICAgICAgc3dpdGNoIChhdHRyaWJ1dGVUeXBlKSB7CiAgICAgICAgICBjYXNlIEF0dHJpYnV0ZVR5cGUuU0NBTEFSOgogICAgICAgICAgICByZXR1cm4gImZsb2F0IjsKICAgICAgICAgIGNhc2UgQXR0cmlidXRlVHlwZS5WRUMyOgogICAgICAgICAgICByZXR1cm4gInZlYzIiOwogICAgICAgICAgY2FzZSBBdHRyaWJ1dGVUeXBlLlZFQzM6CiAgICAgICAgICAgIHJldHVybiAidmVjMyI7CiAgICAgICAgICBjYXNlIEF0dHJpYnV0ZVR5cGUuVkVDNDoKICAgICAgICAgICAgcmV0dXJuICJ2ZWM0IjsKICAgICAgICAgIGNhc2UgQXR0cmlidXRlVHlwZS5NQVQyOgogICAgICAgICAgICByZXR1cm4gIm1hdDIiOwogICAgICAgICAgY2FzZSBBdHRyaWJ1dGVUeXBlLk1BVDM6CiAgICAgICAgICAgIHJldHVybiAibWF0MyI7CiAgICAgICAgICBjYXNlIEF0dHJpYnV0ZVR5cGUuTUFUNDoKICAgICAgICAgICAgcmV0dXJuICJtYXQ0IjsKICAgICAgICAgIC8vPj5pbmNsdWRlU3RhcnQoJ2RlYnVnJywgcHJhZ21hcy5kZWJ1Zyk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYXR0cmlidXRlVHlwZSBpcyBub3QgYSB2YWxpZCB2YWx1ZS4iKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIEF0dHJpYnV0ZVR5cGVfZGVmYXVsdCA9IE9iamVjdC5mcmVlemUoQXR0cmlidXRlVHlwZSk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9BdHRyaWJ1dGVDb21wcmVzc2lvbi5qcwogIGZ1bmN0aW9uIGZvcmNlVWludDgodmFsdWUpIHsKICAgIHVpbnQ4Rm9yY2VBcnJheVswXSA9IHZhbHVlOwogICAgcmV0dXJuIHVpbnQ4Rm9yY2VBcnJheVswXTsKICB9CiAgZnVuY3Rpb24gemlnWmFnRGVjb2RlKHZhbHVlKSB7CiAgICByZXR1cm4gdmFsdWUgPj4gMSBeIC0odmFsdWUgJiAxKTsKICB9CiAgdmFyIFJJR0hUX1NISUZULCBMRUZUX1NISUZULCBBdHRyaWJ1dGVDb21wcmVzc2lvbiwgb2N0RW5jb2RlU2NyYXRjaCwgdWludDhGb3JjZUFycmF5LCBzY3JhdGNoRW5jb2RlQ2FydDIsIEF0dHJpYnV0ZUNvbXByZXNzaW9uX2RlZmF1bHQ7CiAgdmFyIGluaXRfQXR0cmlidXRlQ29tcHJlc3Npb24gPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0F0dHJpYnV0ZUNvbXByZXNzaW9uLmpzIigpIHsKICAgICAgaW5pdF9DYXJ0ZXNpYW4yKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NvbXBvbmVudERhdGF0eXBlKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfQXR0cmlidXRlVHlwZSgpOwogICAgICBSSUdIVF9TSElGVCA9IDEgLyAyNTY7CiAgICAgIExFRlRfU0hJRlQgPSAyNTY7CiAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uID0ge307CiAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLm9jdEVuY29kZUluUmFuZ2UgPSBmdW5jdGlvbih2ZWN0b3IsIHJhbmdlTWF4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInZlY3RvciIsIHZlY3Rvcik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IG1hZ1NxdWFyZWQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlU3F1YXJlZCh2ZWN0b3IpOwogICAgICAgIGlmIChNYXRoLmFicyhtYWdTcXVhcmVkIC0gMSkgPiBNYXRoX2RlZmF1bHQuRVBTSUxPTjYpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ2ZWN0b3IgbXVzdCBiZSBub3JtYWxpemVkLiIpOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IHZlY3Rvci54IC8gKE1hdGguYWJzKHZlY3Rvci54KSArIE1hdGguYWJzKHZlY3Rvci55KSArIE1hdGguYWJzKHZlY3Rvci56KSk7CiAgICAgICAgcmVzdWx0LnkgPSB2ZWN0b3IueSAvIChNYXRoLmFicyh2ZWN0b3IueCkgKyBNYXRoLmFicyh2ZWN0b3IueSkgKyBNYXRoLmFicyh2ZWN0b3IueikpOwogICAgICAgIGlmICh2ZWN0b3IueiA8IDApIHsKICAgICAgICAgIGNvbnN0IHggPSByZXN1bHQueDsKICAgICAgICAgIGNvbnN0IHkgPSByZXN1bHQueTsKICAgICAgICAgIHJlc3VsdC54ID0gKDEgLSBNYXRoLmFicyh5KSkgKiBNYXRoX2RlZmF1bHQuc2lnbk5vdFplcm8oeCk7CiAgICAgICAgICByZXN1bHQueSA9ICgxIC0gTWF0aC5hYnMoeCkpICogTWF0aF9kZWZhdWx0LnNpZ25Ob3RaZXJvKHkpOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IE1hdGhfZGVmYXVsdC50b1NOb3JtKHJlc3VsdC54LCByYW5nZU1heCk7CiAgICAgICAgcmVzdWx0LnkgPSBNYXRoX2RlZmF1bHQudG9TTm9ybShyZXN1bHQueSwgcmFuZ2VNYXgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLm9jdEVuY29kZSA9IGZ1bmN0aW9uKHZlY3RvciwgcmVzdWx0KSB7CiAgICAgICAgcmV0dXJuIEF0dHJpYnV0ZUNvbXByZXNzaW9uLm9jdEVuY29kZUluUmFuZ2UodmVjdG9yLCAyNTUsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIG9jdEVuY29kZVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIHVpbnQ4Rm9yY2VBcnJheSA9IG5ldyBVaW50OEFycmF5KDEpOwogICAgICBBdHRyaWJ1dGVDb21wcmVzc2lvbi5vY3RFbmNvZGVUb0NhcnRlc2lhbjQgPSBmdW5jdGlvbih2ZWN0b3IsIHJlc3VsdCkgewogICAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLm9jdEVuY29kZUluUmFuZ2UodmVjdG9yLCA2NTUzNSwgb2N0RW5jb2RlU2NyYXRjaCk7CiAgICAgICAgcmVzdWx0LnggPSBmb3JjZVVpbnQ4KG9jdEVuY29kZVNjcmF0Y2gueCAqIFJJR0hUX1NISUZUKTsKICAgICAgICByZXN1bHQueSA9IGZvcmNlVWludDgob2N0RW5jb2RlU2NyYXRjaC54KTsKICAgICAgICByZXN1bHQueiA9IGZvcmNlVWludDgob2N0RW5jb2RlU2NyYXRjaC55ICogUklHSFRfU0hJRlQpOwogICAgICAgIHJlc3VsdC53ID0gZm9yY2VVaW50OChvY3RFbmNvZGVTY3JhdGNoLnkpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLm9jdERlY29kZUluUmFuZ2UgPSBmdW5jdGlvbih4LCB5LCByYW5nZU1heCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGlmICh4IDwgMCB8fCB4ID4gcmFuZ2VNYXggfHwgeSA8IDAgfHwgeSA+IHJhbmdlTWF4KSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgYHggYW5kIHkgbXVzdCBiZSB1bnNpZ25lZCBub3JtYWxpemVkIGludGVnZXJzIGJldHdlZW4gMCBhbmQgJHtyYW5nZU1heH1gCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IE1hdGhfZGVmYXVsdC5mcm9tU05vcm0oeCwgcmFuZ2VNYXgpOwogICAgICAgIHJlc3VsdC55ID0gTWF0aF9kZWZhdWx0LmZyb21TTm9ybSh5LCByYW5nZU1heCk7CiAgICAgICAgcmVzdWx0LnogPSAxIC0gKE1hdGguYWJzKHJlc3VsdC54KSArIE1hdGguYWJzKHJlc3VsdC55KSk7CiAgICAgICAgaWYgKHJlc3VsdC56IDwgMCkgewogICAgICAgICAgY29uc3Qgb2xkVlggPSByZXN1bHQueDsKICAgICAgICAgIHJlc3VsdC54ID0gKDEgLSBNYXRoLmFicyhyZXN1bHQueSkpICogTWF0aF9kZWZhdWx0LnNpZ25Ob3RaZXJvKG9sZFZYKTsKICAgICAgICAgIHJlc3VsdC55ID0gKDEgLSBNYXRoLmFicyhvbGRWWCkpICogTWF0aF9kZWZhdWx0LnNpZ25Ob3RaZXJvKHJlc3VsdC55KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUocmVzdWx0LCByZXN1bHQpOwogICAgICB9OwogICAgICBBdHRyaWJ1dGVDb21wcmVzc2lvbi5vY3REZWNvZGUgPSBmdW5jdGlvbih4LCB5LCByZXN1bHQpIHsKICAgICAgICByZXR1cm4gQXR0cmlidXRlQ29tcHJlc3Npb24ub2N0RGVjb2RlSW5SYW5nZSh4LCB5LCAyNTUsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLm9jdERlY29kZUZyb21DYXJ0ZXNpYW40ID0gZnVuY3Rpb24oZW5jb2RlZCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJlbmNvZGVkIiwgZW5jb2RlZCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHggPSBlbmNvZGVkLng7CiAgICAgICAgY29uc3QgeSA9IGVuY29kZWQueTsKICAgICAgICBjb25zdCB6ID0gZW5jb2RlZC56OwogICAgICAgIGNvbnN0IHcgPSBlbmNvZGVkLnc7CiAgICAgICAgaWYgKHggPCAwIHx8IHggPiAyNTUgfHwgeSA8IDAgfHwgeSA+IDI1NSB8fCB6IDwgMCB8fCB6ID4gMjU1IHx8IHcgPCAwIHx8IHcgPiAyNTUpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICAieCwgeSwgeiwgYW5kIHcgbXVzdCBiZSB1bnNpZ25lZCBub3JtYWxpemVkIGludGVnZXJzIGJldHdlZW4gMCBhbmQgMjU1IgogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgeE9jdDE2ID0geCAqIExFRlRfU0hJRlQgKyB5OwogICAgICAgIGNvbnN0IHlPY3QxNiA9IHogKiBMRUZUX1NISUZUICsgdzsKICAgICAgICByZXR1cm4gQXR0cmlidXRlQ29tcHJlc3Npb24ub2N0RGVjb2RlSW5SYW5nZSh4T2N0MTYsIHlPY3QxNiwgNjU1MzUsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLm9jdFBhY2tGbG9hdCA9IGZ1bmN0aW9uKGVuY29kZWQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImVuY29kZWQiLCBlbmNvZGVkKTsKICAgICAgICByZXR1cm4gMjU2ICogZW5jb2RlZC54ICsgZW5jb2RlZC55OwogICAgICB9OwogICAgICBzY3JhdGNoRW5jb2RlQ2FydDIgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLm9jdEVuY29kZUZsb2F0ID0gZnVuY3Rpb24odmVjdG9yKSB7CiAgICAgICAgQXR0cmlidXRlQ29tcHJlc3Npb24ub2N0RW5jb2RlKHZlY3Rvciwgc2NyYXRjaEVuY29kZUNhcnQyKTsKICAgICAgICByZXR1cm4gQXR0cmlidXRlQ29tcHJlc3Npb24ub2N0UGFja0Zsb2F0KHNjcmF0Y2hFbmNvZGVDYXJ0Mik7CiAgICAgIH07CiAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLm9jdERlY29kZUZsb2F0ID0gZnVuY3Rpb24odmFsdWUsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgY29uc3QgdGVtcCA9IHZhbHVlIC8gMjU2OwogICAgICAgIGNvbnN0IHggPSBNYXRoLmZsb29yKHRlbXApOwogICAgICAgIGNvbnN0IHkgPSAodGVtcCAtIHgpICogMjU2OwogICAgICAgIHJldHVybiBBdHRyaWJ1dGVDb21wcmVzc2lvbi5vY3REZWNvZGUoeCwgeSwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgQXR0cmlidXRlQ29tcHJlc3Npb24ub2N0UGFjayA9IGZ1bmN0aW9uKHYxMiwgdjIyLCB2MywgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ2MSIsIHYxMik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ2MiIsIHYyMik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ2MyIsIHYzKTsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgZW5jb2RlZDEgPSBBdHRyaWJ1dGVDb21wcmVzc2lvbi5vY3RFbmNvZGVGbG9hdCh2MTIpOwogICAgICAgIGNvbnN0IGVuY29kZWQyID0gQXR0cmlidXRlQ29tcHJlc3Npb24ub2N0RW5jb2RlRmxvYXQodjIyKTsKICAgICAgICBjb25zdCBlbmNvZGVkMyA9IEF0dHJpYnV0ZUNvbXByZXNzaW9uLm9jdEVuY29kZSh2Mywgc2NyYXRjaEVuY29kZUNhcnQyKTsKICAgICAgICByZXN1bHQueCA9IDY1NTM2ICogZW5jb2RlZDMueCArIGVuY29kZWQxOwogICAgICAgIHJlc3VsdC55ID0gNjU1MzYgKiBlbmNvZGVkMy55ICsgZW5jb2RlZDI7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQXR0cmlidXRlQ29tcHJlc3Npb24ub2N0VW5wYWNrID0gZnVuY3Rpb24ocGFja2VkLCB2MTIsIHYyMiwgdjMpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInBhY2tlZCIsIHBhY2tlZCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ2MSIsIHYxMik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ2MiIsIHYyMik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ2MyIsIHYzKTsKICAgICAgICBsZXQgdGVtcCA9IHBhY2tlZC54IC8gNjU1MzY7CiAgICAgICAgY29uc3QgeCA9IE1hdGguZmxvb3IodGVtcCk7CiAgICAgICAgY29uc3QgZW5jb2RlZEZsb2F0MSA9ICh0ZW1wIC0geCkgKiA2NTUzNjsKICAgICAgICB0ZW1wID0gcGFja2VkLnkgLyA2NTUzNjsKICAgICAgICBjb25zdCB5ID0gTWF0aC5mbG9vcih0ZW1wKTsKICAgICAgICBjb25zdCBlbmNvZGVkRmxvYXQyID0gKHRlbXAgLSB5KSAqIDY1NTM2OwogICAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLm9jdERlY29kZUZsb2F0KGVuY29kZWRGbG9hdDEsIHYxMik7CiAgICAgICAgQXR0cmlidXRlQ29tcHJlc3Npb24ub2N0RGVjb2RlRmxvYXQoZW5jb2RlZEZsb2F0MiwgdjIyKTsKICAgICAgICBBdHRyaWJ1dGVDb21wcmVzc2lvbi5vY3REZWNvZGUoeCwgeSwgdjMpOwogICAgICB9OwogICAgICBBdHRyaWJ1dGVDb21wcmVzc2lvbi5jb21wcmVzc1RleHR1cmVDb29yZGluYXRlcyA9IGZ1bmN0aW9uKHRleHR1cmVDb29yZGluYXRlcykgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgidGV4dHVyZUNvb3JkaW5hdGVzIiwgdGV4dHVyZUNvb3JkaW5hdGVzKTsKICAgICAgICBjb25zdCB4ID0gdGV4dHVyZUNvb3JkaW5hdGVzLnggKiA0MDk1IHwgMDsKICAgICAgICBjb25zdCB5ID0gdGV4dHVyZUNvb3JkaW5hdGVzLnkgKiA0MDk1IHwgMDsKICAgICAgICByZXR1cm4gNDA5NiAqIHggKyB5OwogICAgICB9OwogICAgICBBdHRyaWJ1dGVDb21wcmVzc2lvbi5kZWNvbXByZXNzVGV4dHVyZUNvb3JkaW5hdGVzID0gZnVuY3Rpb24oY29tcHJlc3NlZCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJjb21wcmVzc2VkIiwgY29tcHJlc3NlZCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHRlbXAgPSBjb21wcmVzc2VkIC8gNDA5NjsKICAgICAgICBjb25zdCB4WmVyb1RvNDA5NSA9IE1hdGguZmxvb3IodGVtcCk7CiAgICAgICAgcmVzdWx0LnggPSB4WmVyb1RvNDA5NSAvIDQwOTU7CiAgICAgICAgcmVzdWx0LnkgPSAoY29tcHJlc3NlZCAtIHhaZXJvVG80MDk1ICogNDA5NikgLyA0MDk1OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLnppZ1phZ0RlbHRhRGVjb2RlID0gZnVuY3Rpb24odUJ1ZmZlciwgdkJ1ZmZlciwgaGVpZ2h0QnVmZmVyKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ1QnVmZmVyIiwgdUJ1ZmZlcik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ2QnVmZmVyIiwgdkJ1ZmZlcik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmVxdWFscygKICAgICAgICAgICJ1QnVmZmVyLmxlbmd0aCIsCiAgICAgICAgICAidkJ1ZmZlci5sZW5ndGgiLAogICAgICAgICAgdUJ1ZmZlci5sZW5ndGgsCiAgICAgICAgICB2QnVmZmVyLmxlbmd0aAogICAgICAgICk7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChoZWlnaHRCdWZmZXIpKSB7CiAgICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZXF1YWxzKAogICAgICAgICAgICAidUJ1ZmZlci5sZW5ndGgiLAogICAgICAgICAgICAiaGVpZ2h0QnVmZmVyLmxlbmd0aCIsCiAgICAgICAgICAgIHVCdWZmZXIubGVuZ3RoLAogICAgICAgICAgICBoZWlnaHRCdWZmZXIubGVuZ3RoCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBjb3VudCA9IHVCdWZmZXIubGVuZ3RoOwogICAgICAgIGxldCB1MyA9IDA7CiAgICAgICAgbGV0IHYzID0gMDsKICAgICAgICBsZXQgaGVpZ2h0ID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyArK2kpIHsKICAgICAgICAgIHUzICs9IHppZ1phZ0RlY29kZSh1QnVmZmVyW2ldKTsKICAgICAgICAgIHYzICs9IHppZ1phZ0RlY29kZSh2QnVmZmVyW2ldKTsKICAgICAgICAgIHVCdWZmZXJbaV0gPSB1MzsKICAgICAgICAgIHZCdWZmZXJbaV0gPSB2MzsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaGVpZ2h0QnVmZmVyKSkgewogICAgICAgICAgICBoZWlnaHQgKz0gemlnWmFnRGVjb2RlKGhlaWdodEJ1ZmZlcltpXSk7CiAgICAgICAgICAgIGhlaWdodEJ1ZmZlcltpXSA9IGhlaWdodDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH07CiAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLmRlcXVhbnRpemUgPSBmdW5jdGlvbih0eXBlZEFycmF5LCBjb21wb25lbnREYXRhdHlwZSwgdHlwZSwgY291bnQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInR5cGVkQXJyYXkiLCB0eXBlZEFycmF5KTsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImNvbXBvbmVudERhdGF0eXBlIiwgY29tcG9uZW50RGF0YXR5cGUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgidHlwZSIsIHR5cGUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiY291bnQiLCBjb3VudCk7CiAgICAgICAgY29uc3QgY29tcG9uZW50c1BlckF0dHJpYnV0ZSA9IEF0dHJpYnV0ZVR5cGVfZGVmYXVsdC5nZXROdW1iZXJPZkNvbXBvbmVudHModHlwZSk7CiAgICAgICAgbGV0IGRpdmlzb3I7CiAgICAgICAgc3dpdGNoIChjb21wb25lbnREYXRhdHlwZSkgewogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkJZVEU6CiAgICAgICAgICAgIGRpdmlzb3IgPSAxMjc7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEU6CiAgICAgICAgICAgIGRpdmlzb3IgPSAyNTU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlNIT1JUOgogICAgICAgICAgICBkaXZpc29yID0gMzI3Njc7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX1NIT1JUOgogICAgICAgICAgICBkaXZpc29yID0gNjU1MzU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LklOVDoKICAgICAgICAgICAgZGl2aXNvciA9IDIxNDc0ODM2NDc7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0lOVDoKICAgICAgICAgICAgZGl2aXNvciA9IDQyOTQ5NjcyOTU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgLy8+PmluY2x1ZGVTdGFydCgnZGVidWcnLCBwcmFnbWFzLmRlYnVnKTsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICAgIGBDYW5ub3QgZGVxdWFudGl6ZSBjb21wb25lbnQgZGF0YXR5cGU6ICR7Y29tcG9uZW50RGF0YXR5cGV9YAogICAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBkZXF1YW50aXplZFR5cGVkQXJyYXkgPSBuZXcgRmxvYXQzMkFycmF5KAogICAgICAgICAgY291bnQgKiBjb21wb25lbnRzUGVyQXR0cmlidXRlCiAgICAgICAgKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgY29tcG9uZW50c1BlckF0dHJpYnV0ZTsgaisrKSB7CiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gaSAqIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGUgKyBqOwogICAgICAgICAgICBkZXF1YW50aXplZFR5cGVkQXJyYXlbaW5kZXhdID0gTWF0aC5tYXgoCiAgICAgICAgICAgICAgdHlwZWRBcnJheVtpbmRleF0gLyBkaXZpc29yLAogICAgICAgICAgICAgIC0xCiAgICAgICAgICAgICk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBkZXF1YW50aXplZFR5cGVkQXJyYXk7CiAgICAgIH07CiAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uLmRlY29kZVJHQjU2NSA9IGZ1bmN0aW9uKHR5cGVkQXJyYXksIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgidHlwZWRBcnJheSIsIHR5cGVkQXJyYXkpOwogICAgICAgIGNvbnN0IGV4cGVjdGVkTGVuZ3RoID0gdHlwZWRBcnJheS5sZW5ndGggKiAzOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmVxdWFscygKICAgICAgICAgICAgInJlc3VsdC5sZW5ndGgiLAogICAgICAgICAgICAidHlwZWRBcnJheS5sZW5ndGggKiAzIiwKICAgICAgICAgICAgcmVzdWx0Lmxlbmd0aCwKICAgICAgICAgICAgZXhwZWN0ZWRMZW5ndGgKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGNvdW50ID0gdHlwZWRBcnJheS5sZW5ndGg7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEZsb2F0MzJBcnJheShjb3VudCAqIDMpOwogICAgICAgIH0KICAgICAgICBjb25zdCBtYXNrNSA9ICgxIDw8IDUpIC0gMTsKICAgICAgICBjb25zdCBtYXNrNiA9ICgxIDw8IDYpIC0gMTsKICAgICAgICBjb25zdCBub3JtYWxpemU1ID0gMSAvIDMxOwogICAgICAgIGNvbnN0IG5vcm1hbGl6ZTYgPSAxIC8gNjM7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHR5cGVkQXJyYXlbaV07CiAgICAgICAgICBjb25zdCByZWQgPSB2YWx1ZSA+PiAxMTsKICAgICAgICAgIGNvbnN0IGdyZWVuID0gdmFsdWUgPj4gNSAmIG1hc2s2OwogICAgICAgICAgY29uc3QgYmx1ZSA9IHZhbHVlICYgbWFzazU7CiAgICAgICAgICBjb25zdCBvZmZzZXQgPSAzICogaTsKICAgICAgICAgIHJlc3VsdFtvZmZzZXRdID0gcmVkICogbm9ybWFsaXplNTsKICAgICAgICAgIHJlc3VsdFtvZmZzZXQgKyAxXSA9IGdyZWVuICogbm9ybWFsaXplNjsKICAgICAgICAgIHJlc3VsdFtvZmZzZXQgKyAyXSA9IGJsdWUgKiBub3JtYWxpemU1OwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBBdHRyaWJ1dGVDb21wcmVzc2lvbl9kZWZhdWx0ID0gQXR0cmlidXRlQ29tcHJlc3Npb247CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9iYXJ5Y2VudHJpY0Nvb3JkaW5hdGVzLmpzCiAgZnVuY3Rpb24gYmFyeWNlbnRyaWNDb29yZGluYXRlcyhwb2ludCwgcDAsIHAxLCBwMiwgcmVzdWx0KSB7CiAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInBvaW50IiwgcG9pbnQpOwogICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJwMCIsIHAwKTsKICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgicDEiLCBwMSk7CiAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInAyIiwgcDIpOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICByZXN1bHQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICB9CiAgICBsZXQgdjAyOwogICAgbGV0IHYxMjsKICAgIGxldCB2MjI7CiAgICBsZXQgZG90MDA7CiAgICBsZXQgZG90MDE7CiAgICBsZXQgZG90MDI7CiAgICBsZXQgZG90MTE7CiAgICBsZXQgZG90MTI7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwMC56KSkgewogICAgICBpZiAoQ2FydGVzaWFuMl9kZWZhdWx0LmVxdWFsc0Vwc2lsb24ocG9pbnQsIHAwLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjE0KSkgewogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWCwgcmVzdWx0KTsKICAgICAgfQogICAgICBpZiAoQ2FydGVzaWFuMl9kZWZhdWx0LmVxdWFsc0Vwc2lsb24ocG9pbnQsIHAxLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjE0KSkgewogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWSwgcmVzdWx0KTsKICAgICAgfQogICAgICBpZiAoQ2FydGVzaWFuMl9kZWZhdWx0LmVxdWFsc0Vwc2lsb24ocG9pbnQsIHAyLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjE0KSkgewogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWiwgcmVzdWx0KTsKICAgICAgfQogICAgICB2MDIgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuc3VidHJhY3QocDEsIHAwLCBzY3JhdGNoQ2FydGVzaWFuMSk7CiAgICAgIHYxMiA9IENhcnRlc2lhbjJfZGVmYXVsdC5zdWJ0cmFjdChwMiwgcDAsIHNjcmF0Y2hDYXJ0ZXNpYW4yKTsKICAgICAgdjIyID0gQ2FydGVzaWFuMl9kZWZhdWx0LnN1YnRyYWN0KHBvaW50LCBwMCwgc2NyYXRjaENhcnRlc2lhbjMyKTsKICAgICAgZG90MDAgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuZG90KHYwMiwgdjAyKTsKICAgICAgZG90MDEgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuZG90KHYwMiwgdjEyKTsKICAgICAgZG90MDIgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuZG90KHYwMiwgdjIyKTsKICAgICAgZG90MTEgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuZG90KHYxMiwgdjEyKTsKICAgICAgZG90MTIgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuZG90KHYxMiwgdjIyKTsKICAgIH0gZWxzZSB7CiAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihwb2ludCwgcDAsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTQpKSB7CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9YLCByZXN1bHQpOwogICAgICB9CiAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihwb2ludCwgcDEsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTQpKSB7CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9ZLCByZXN1bHQpOwogICAgICB9CiAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihwb2ludCwgcDIsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTQpKSB7CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9aLCByZXN1bHQpOwogICAgICB9CiAgICAgIHYwMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChwMSwgcDAsIHNjcmF0Y2hDYXJ0ZXNpYW4xKTsKICAgICAgdjEyID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHAyLCBwMCwgc2NyYXRjaENhcnRlc2lhbjIpOwogICAgICB2MjIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QocG9pbnQsIHAwLCBzY3JhdGNoQ2FydGVzaWFuMzIpOwogICAgICBkb3QwMCA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QodjAyLCB2MDIpOwogICAgICBkb3QwMSA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QodjAyLCB2MTIpOwogICAgICBkb3QwMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QodjAyLCB2MjIpOwogICAgICBkb3QxMSA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QodjEyLCB2MTIpOwogICAgICBkb3QxMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QodjEyLCB2MjIpOwogICAgfQogICAgcmVzdWx0LnkgPSBkb3QxMSAqIGRvdDAyIC0gZG90MDEgKiBkb3QxMjsKICAgIHJlc3VsdC56ID0gZG90MDAgKiBkb3QxMiAtIGRvdDAxICogZG90MDI7CiAgICBjb25zdCBxID0gZG90MDAgKiBkb3QxMSAtIGRvdDAxICogZG90MDE7CiAgICBpZiAocSA9PT0gMCkgewogICAgICByZXR1cm4gdm9pZCAwOwogICAgfQogICAgcmVzdWx0LnkgLz0gcTsKICAgIHJlc3VsdC56IC89IHE7CiAgICByZXN1bHQueCA9IDEgLSByZXN1bHQueSAtIHJlc3VsdC56OwogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgdmFyIHNjcmF0Y2hDYXJ0ZXNpYW4xLCBzY3JhdGNoQ2FydGVzaWFuMiwgc2NyYXRjaENhcnRlc2lhbjMyLCBiYXJ5Y2VudHJpY0Nvb3JkaW5hdGVzX2RlZmF1bHQ7CiAgdmFyIGluaXRfYmFyeWNlbnRyaWNDb29yZGluYXRlcyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvYmFyeWNlbnRyaWNDb29yZGluYXRlcy5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMigpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4xID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydGVzaWFuMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjMyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBiYXJ5Y2VudHJpY0Nvb3JkaW5hdGVzX2RlZmF1bHQgPSBiYXJ5Y2VudHJpY0Nvb3JkaW5hdGVzOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvRW5jb2RlZENhcnRlc2lhbjMuanMKICBmdW5jdGlvbiBFbmNvZGVkQ2FydGVzaWFuMygpIHsKICAgIHRoaXMuaGlnaCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTyk7CiAgICB0aGlzLmxvdyA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTyk7CiAgfQogIHZhciBzY3JhdGNoRW5jb2RlLCBlbmNvZGVkUCwgRW5jb2RlZENhcnRlc2lhbjNfZGVmYXVsdDsKICB2YXIgaW5pdF9FbmNvZGVkQ2FydGVzaWFuMyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvRW5jb2RlZENhcnRlc2lhbjMuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgRW5jb2RlZENhcnRlc2lhbjMuZW5jb2RlID0gZnVuY3Rpb24odmFsdWUsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gewogICAgICAgICAgICBoaWdoOiAwLAogICAgICAgICAgICBsb3c6IDAKICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIGxldCBkb3VibGVIaWdoOwogICAgICAgIGlmICh2YWx1ZSA+PSAwKSB7CiAgICAgICAgICBkb3VibGVIaWdoID0gTWF0aC5mbG9vcih2YWx1ZSAvIDY1NTM2KSAqIDY1NTM2OwogICAgICAgICAgcmVzdWx0LmhpZ2ggPSBkb3VibGVIaWdoOwogICAgICAgICAgcmVzdWx0LmxvdyA9IHZhbHVlIC0gZG91YmxlSGlnaDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZG91YmxlSGlnaCA9IE1hdGguZmxvb3IoLXZhbHVlIC8gNjU1MzYpICogNjU1MzY7CiAgICAgICAgICByZXN1bHQuaGlnaCA9IC1kb3VibGVIaWdoOwogICAgICAgICAgcmVzdWx0LmxvdyA9IHZhbHVlICsgZG91YmxlSGlnaDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NyYXRjaEVuY29kZSA9IHsKICAgICAgICBoaWdoOiAwLAogICAgICAgIGxvdzogMAogICAgICB9OwogICAgICBFbmNvZGVkQ2FydGVzaWFuMy5mcm9tQ2FydGVzaWFuID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBFbmNvZGVkQ2FydGVzaWFuMygpOwogICAgICAgIH0KICAgICAgICBjb25zdCBoaWdoID0gcmVzdWx0LmhpZ2g7CiAgICAgICAgY29uc3QgbG93ID0gcmVzdWx0LmxvdzsKICAgICAgICBFbmNvZGVkQ2FydGVzaWFuMy5lbmNvZGUoY2FydGVzaWFuMTEueCwgc2NyYXRjaEVuY29kZSk7CiAgICAgICAgaGlnaC54ID0gc2NyYXRjaEVuY29kZS5oaWdoOwogICAgICAgIGxvdy54ID0gc2NyYXRjaEVuY29kZS5sb3c7CiAgICAgICAgRW5jb2RlZENhcnRlc2lhbjMuZW5jb2RlKGNhcnRlc2lhbjExLnksIHNjcmF0Y2hFbmNvZGUpOwogICAgICAgIGhpZ2gueSA9IHNjcmF0Y2hFbmNvZGUuaGlnaDsKICAgICAgICBsb3cueSA9IHNjcmF0Y2hFbmNvZGUubG93OwogICAgICAgIEVuY29kZWRDYXJ0ZXNpYW4zLmVuY29kZShjYXJ0ZXNpYW4xMS56LCBzY3JhdGNoRW5jb2RlKTsKICAgICAgICBoaWdoLnogPSBzY3JhdGNoRW5jb2RlLmhpZ2g7CiAgICAgICAgbG93LnogPSBzY3JhdGNoRW5jb2RlLmxvdzsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBlbmNvZGVkUCA9IG5ldyBFbmNvZGVkQ2FydGVzaWFuMygpOwogICAgICBFbmNvZGVkQ2FydGVzaWFuMy53cml0ZUVsZW1lbnRzID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIGNhcnRlc2lhbkFycmF5LCBpbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiY2FydGVzaWFuQXJyYXkiLCBjYXJ0ZXNpYW5BcnJheSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJpbmRleCIsIGluZGV4KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygiaW5kZXgiLCBpbmRleCwgMCk7CiAgICAgICAgRW5jb2RlZENhcnRlc2lhbjMuZnJvbUNhcnRlc2lhbihjYXJ0ZXNpYW4xMSwgZW5jb2RlZFApOwogICAgICAgIGNvbnN0IGhpZ2ggPSBlbmNvZGVkUC5oaWdoOwogICAgICAgIGNvbnN0IGxvdyA9IGVuY29kZWRQLmxvdzsKICAgICAgICBjYXJ0ZXNpYW5BcnJheVtpbmRleF0gPSBoaWdoLng7CiAgICAgICAgY2FydGVzaWFuQXJyYXlbaW5kZXggKyAxXSA9IGhpZ2gueTsKICAgICAgICBjYXJ0ZXNpYW5BcnJheVtpbmRleCArIDJdID0gaGlnaC56OwogICAgICAgIGNhcnRlc2lhbkFycmF5W2luZGV4ICsgM10gPSBsb3cueDsKICAgICAgICBjYXJ0ZXNpYW5BcnJheVtpbmRleCArIDRdID0gbG93Lnk7CiAgICAgICAgY2FydGVzaWFuQXJyYXlbaW5kZXggKyA1XSA9IGxvdy56OwogICAgICB9OwogICAgICBFbmNvZGVkQ2FydGVzaWFuM19kZWZhdWx0ID0gRW5jb2RlZENhcnRlc2lhbjM7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9JbmRleERhdGF0eXBlLmpzCiAgdmFyIEluZGV4RGF0YXR5cGUsIEluZGV4RGF0YXR5cGVfZGVmYXVsdDsKICB2YXIgaW5pdF9JbmRleERhdGF0eXBlID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9JbmRleERhdGF0eXBlLmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfV2ViR0xDb25zdGFudHMoKTsKICAgICAgSW5kZXhEYXRhdHlwZSA9IHsKICAgICAgICAvKioKICAgICAgICAgKiA4LWJpdCB1bnNpZ25lZCBieXRlIGNvcnJlc3BvbmRpbmcgdG8gPGNvZGU+VU5TSUdORURfQllURTwvY29kZT4gYW5kIHRoZSB0eXBlCiAgICAgICAgICogb2YgYW4gZWxlbWVudCBpbiA8Y29kZT5VaW50OEFycmF5PC9jb2RlPi4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgVU5TSUdORURfQllURTogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5VTlNJR05FRF9CWVRFLAogICAgICAgIC8qKgogICAgICAgICAqIDE2LWJpdCB1bnNpZ25lZCBzaG9ydCBjb3JyZXNwb25kaW5nIHRvIDxjb2RlPlVOU0lHTkVEX1NIT1JUPC9jb2RlPiBhbmQgdGhlIHR5cGUKICAgICAgICAgKiBvZiBhbiBlbGVtZW50IGluIDxjb2RlPlVpbnQxNkFycmF5PC9jb2RlPi4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgVU5TSUdORURfU0hPUlQ6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuVU5TSUdORURfU0hPUlQsCiAgICAgICAgLyoqCiAgICAgICAgICogMzItYml0IHVuc2lnbmVkIGludCBjb3JyZXNwb25kaW5nIHRvIDxjb2RlPlVOU0lHTkVEX0lOVDwvY29kZT4gYW5kIHRoZSB0eXBlCiAgICAgICAgICogb2YgYW4gZWxlbWVudCBpbiA8Y29kZT5VaW50MzJBcnJheTwvY29kZT4uCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFVOU0lHTkVEX0lOVDogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5VTlNJR05FRF9JTlQKICAgICAgfTsKICAgICAgSW5kZXhEYXRhdHlwZS5nZXRTaXplSW5CeXRlcyA9IGZ1bmN0aW9uKGluZGV4RGF0YXR5cGUpIHsKICAgICAgICBzd2l0Y2ggKGluZGV4RGF0YXR5cGUpIHsKICAgICAgICAgIGNhc2UgSW5kZXhEYXRhdHlwZS5VTlNJR05FRF9CWVRFOgogICAgICAgICAgICByZXR1cm4gVWludDhBcnJheS5CWVRFU19QRVJfRUxFTUVOVDsKICAgICAgICAgIGNhc2UgSW5kZXhEYXRhdHlwZS5VTlNJR05FRF9TSE9SVDoKICAgICAgICAgICAgcmV0dXJuIFVpbnQxNkFycmF5LkJZVEVTX1BFUl9FTEVNRU5UOwogICAgICAgICAgY2FzZSBJbmRleERhdGF0eXBlLlVOU0lHTkVEX0lOVDoKICAgICAgICAgICAgcmV0dXJuIFVpbnQzMkFycmF5LkJZVEVTX1BFUl9FTEVNRU5UOwogICAgICAgIH0KICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICJpbmRleERhdGF0eXBlIGlzIHJlcXVpcmVkIGFuZCBtdXN0IGJlIGEgdmFsaWQgSW5kZXhEYXRhdHlwZSBjb25zdGFudC4iCiAgICAgICAgKTsKICAgICAgfTsKICAgICAgSW5kZXhEYXRhdHlwZS5mcm9tU2l6ZUluQnl0ZXMgPSBmdW5jdGlvbihzaXplSW5CeXRlcykgewogICAgICAgIHN3aXRjaCAoc2l6ZUluQnl0ZXMpIHsKICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgcmV0dXJuIEluZGV4RGF0YXR5cGUuVU5TSUdORURfU0hPUlQ7CiAgICAgICAgICBjYXNlIDQ6CiAgICAgICAgICAgIHJldHVybiBJbmRleERhdGF0eXBlLlVOU0lHTkVEX0lOVDsKICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgcmV0dXJuIEluZGV4RGF0YXR5cGUuVU5TSUdORURfQllURTsKICAgICAgICAgIC8vPj5pbmNsdWRlU3RhcnQoJ2RlYnVnJywgcHJhZ21hcy5kZWJ1Zyk7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgICAiU2l6ZSBpbiBieXRlcyBjYW5ub3QgYmUgbWFwcGVkIHRvIGFuIEluZGV4RGF0YXR5cGUiCiAgICAgICAgICAgICk7CiAgICAgICAgfQogICAgICB9OwogICAgICBJbmRleERhdGF0eXBlLnZhbGlkYXRlID0gZnVuY3Rpb24oaW5kZXhEYXRhdHlwZSkgewogICAgICAgIHJldHVybiBkZWZpbmVkX2RlZmF1bHQoaW5kZXhEYXRhdHlwZSkgJiYgKGluZGV4RGF0YXR5cGUgPT09IEluZGV4RGF0YXR5cGUuVU5TSUdORURfQllURSB8fCBpbmRleERhdGF0eXBlID09PSBJbmRleERhdGF0eXBlLlVOU0lHTkVEX1NIT1JUIHx8IGluZGV4RGF0YXR5cGUgPT09IEluZGV4RGF0YXR5cGUuVU5TSUdORURfSU5UKTsKICAgICAgfTsKICAgICAgSW5kZXhEYXRhdHlwZS5jcmVhdGVUeXBlZEFycmF5ID0gZnVuY3Rpb24obnVtYmVyT2ZWZXJ0aWNlcywgaW5kaWNlc0xlbmd0aE9yQXJyYXkpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChudW1iZXJPZlZlcnRpY2VzKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm51bWJlck9mVmVydGljZXMgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmIChudW1iZXJPZlZlcnRpY2VzID49IE1hdGhfZGVmYXVsdC5TSVhUWV9GT1VSX0tJTE9CWVRFUykgewogICAgICAgICAgcmV0dXJuIG5ldyBVaW50MzJBcnJheShpbmRpY2VzTGVuZ3RoT3JBcnJheSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgVWludDE2QXJyYXkoaW5kaWNlc0xlbmd0aE9yQXJyYXkpOwogICAgICB9OwogICAgICBJbmRleERhdGF0eXBlLmNyZWF0ZVR5cGVkQXJyYXlGcm9tQXJyYXlCdWZmZXIgPSBmdW5jdGlvbihudW1iZXJPZlZlcnRpY2VzLCBzb3VyY2VBcnJheSwgYnl0ZU9mZnNldCwgbGVuZ3RoKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQobnVtYmVyT2ZWZXJ0aWNlcykpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJudW1iZXJPZlZlcnRpY2VzIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChzb3VyY2VBcnJheSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJzb3VyY2VBcnJheSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYnl0ZU9mZnNldCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJieXRlT2Zmc2V0IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAobnVtYmVyT2ZWZXJ0aWNlcyA+PSBNYXRoX2RlZmF1bHQuU0lYVFlfRk9VUl9LSUxPQllURVMpIHsKICAgICAgICAgIHJldHVybiBuZXcgVWludDMyQXJyYXkoc291cmNlQXJyYXksIGJ5dGVPZmZzZXQsIGxlbmd0aCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgVWludDE2QXJyYXkoc291cmNlQXJyYXksIGJ5dGVPZmZzZXQsIGxlbmd0aCk7CiAgICAgIH07CiAgICAgIEluZGV4RGF0YXR5cGUuZnJvbVR5cGVkQXJyYXkgPSBmdW5jdGlvbihhcnJheSkgewogICAgICAgIGlmIChhcnJheSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHsKICAgICAgICAgIHJldHVybiBJbmRleERhdGF0eXBlLlVOU0lHTkVEX0JZVEU7CiAgICAgICAgfQogICAgICAgIGlmIChhcnJheSBpbnN0YW5jZW9mIFVpbnQxNkFycmF5KSB7CiAgICAgICAgICByZXR1cm4gSW5kZXhEYXRhdHlwZS5VTlNJR05FRF9TSE9SVDsKICAgICAgICB9CiAgICAgICAgaWYgKGFycmF5IGluc3RhbmNlb2YgVWludDMyQXJyYXkpIHsKICAgICAgICAgIHJldHVybiBJbmRleERhdGF0eXBlLlVOU0lHTkVEX0lOVDsKICAgICAgICB9CiAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAiYXJyYXkgbXVzdCBiZSBhIFVpbnQ4QXJyYXksIFVpbnQxNkFycmF5LCBvciBVaW50MzJBcnJheS4iCiAgICAgICAgKTsKICAgICAgfTsKICAgICAgSW5kZXhEYXRhdHlwZV9kZWZhdWx0ID0gT2JqZWN0LmZyZWV6ZShJbmRleERhdGF0eXBlKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1F1YWRyYXRpY1JlYWxQb2x5bm9taWFsLmpzCiAgZnVuY3Rpb24gYWRkV2l0aENhbmNlbGxhdGlvbkNoZWNrKGxlZnQsIHJpZ2h0LCB0b2xlcmFuY2UpIHsKICAgIGNvbnN0IGRpZmZlcmVuY2UgPSBsZWZ0ICsgcmlnaHQ7CiAgICBpZiAoTWF0aF9kZWZhdWx0LnNpZ24obGVmdCkgIT09IE1hdGhfZGVmYXVsdC5zaWduKHJpZ2h0KSAmJiBNYXRoLmFicyhkaWZmZXJlbmNlIC8gTWF0aC5tYXgoTWF0aC5hYnMobGVmdCksIE1hdGguYWJzKHJpZ2h0KSkpIDwgdG9sZXJhbmNlKSB7CiAgICAgIHJldHVybiAwOwogICAgfQogICAgcmV0dXJuIGRpZmZlcmVuY2U7CiAgfQogIHZhciBRdWFkcmF0aWNSZWFsUG9seW5vbWlhbCwgUXVhZHJhdGljUmVhbFBvbHlub21pYWxfZGVmYXVsdDsKICB2YXIgaW5pdF9RdWFkcmF0aWNSZWFsUG9seW5vbWlhbCA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUXVhZHJhdGljUmVhbFBvbHlub21pYWwuanMiKCkgewogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBRdWFkcmF0aWNSZWFsUG9seW5vbWlhbCA9IHt9OwogICAgICBRdWFkcmF0aWNSZWFsUG9seW5vbWlhbC5jb21wdXRlRGlzY3JpbWluYW50ID0gZnVuY3Rpb24oYTMsIGIsIGMpIHsKICAgICAgICBpZiAodHlwZW9mIGEzICE9PSAibnVtYmVyIikgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImEgaXMgYSByZXF1aXJlZCBudW1iZXIuIik7CiAgICAgICAgfQogICAgICAgIGlmICh0eXBlb2YgYiAhPT0gIm51bWJlciIpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJiIGlzIGEgcmVxdWlyZWQgbnVtYmVyLiIpOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIGMgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYyBpcyBhIHJlcXVpcmVkIG51bWJlci4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZGlzY3JpbWluYW50ID0gYiAqIGIgLSA0ICogYTMgKiBjOwogICAgICAgIHJldHVybiBkaXNjcmltaW5hbnQ7CiAgICAgIH07CiAgICAgIFF1YWRyYXRpY1JlYWxQb2x5bm9taWFsLmNvbXB1dGVSZWFsUm9vdHMgPSBmdW5jdGlvbihhMywgYiwgYykgewogICAgICAgIGlmICh0eXBlb2YgYTMgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYSBpcyBhIHJlcXVpcmVkIG51bWJlci4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSAibnVtYmVyIikgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImIgaXMgYSByZXF1aXJlZCBudW1iZXIuIik7CiAgICAgICAgfQogICAgICAgIGlmICh0eXBlb2YgYyAhPT0gIm51bWJlciIpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJjIGlzIGEgcmVxdWlyZWQgbnVtYmVyLiIpOwogICAgICAgIH0KICAgICAgICBsZXQgcmF0aW87CiAgICAgICAgaWYgKGEzID09PSAwKSB7CiAgICAgICAgICBpZiAoYiA9PT0gMCkgewogICAgICAgICAgICByZXR1cm4gW107CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gWy1jIC8gYl07CiAgICAgICAgfSBlbHNlIGlmIChiID09PSAwKSB7CiAgICAgICAgICBpZiAoYyA9PT0gMCkgewogICAgICAgICAgICByZXR1cm4gWzAsIDBdOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgY01hZ25pdHVkZSA9IE1hdGguYWJzKGMpOwogICAgICAgICAgY29uc3QgYU1hZ25pdHVkZSA9IE1hdGguYWJzKGEzKTsKICAgICAgICAgIGlmIChjTWFnbml0dWRlIDwgYU1hZ25pdHVkZSAmJiBjTWFnbml0dWRlIC8gYU1hZ25pdHVkZSA8IE1hdGhfZGVmYXVsdC5FUFNJTE9OMTQpIHsKICAgICAgICAgICAgcmV0dXJuIFswLCAwXTsKICAgICAgICAgIH0gZWxzZSBpZiAoY01hZ25pdHVkZSA+IGFNYWduaXR1ZGUgJiYgYU1hZ25pdHVkZSAvIGNNYWduaXR1ZGUgPCBNYXRoX2RlZmF1bHQuRVBTSUxPTjE0KSB7CiAgICAgICAgICAgIHJldHVybiBbXTsKICAgICAgICAgIH0KICAgICAgICAgIHJhdGlvID0gLWMgLyBhMzsKICAgICAgICAgIGlmIChyYXRpbyA8IDApIHsKICAgICAgICAgICAgcmV0dXJuIFtdOwogICAgICAgICAgfQogICAgICAgICAgY29uc3Qgcm9vdCA9IE1hdGguc3FydChyYXRpbyk7CiAgICAgICAgICByZXR1cm4gWy1yb290LCByb290XTsKICAgICAgICB9IGVsc2UgaWYgKGMgPT09IDApIHsKICAgICAgICAgIHJhdGlvID0gLWIgLyBhMzsKICAgICAgICAgIGlmIChyYXRpbyA8IDApIHsKICAgICAgICAgICAgcmV0dXJuIFtyYXRpbywgMF07CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gWzAsIHJhdGlvXTsKICAgICAgICB9CiAgICAgICAgY29uc3QgYjIgPSBiICogYjsKICAgICAgICBjb25zdCBmb3VyX2FjID0gNCAqIGEzICogYzsKICAgICAgICBjb25zdCByYWRpY2FuZCA9IGFkZFdpdGhDYW5jZWxsYXRpb25DaGVjayhiMiwgLWZvdXJfYWMsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTQpOwogICAgICAgIGlmIChyYWRpY2FuZCA8IDApIHsKICAgICAgICAgIHJldHVybiBbXTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcSA9IC0wLjUgKiBhZGRXaXRoQ2FuY2VsbGF0aW9uQ2hlY2soCiAgICAgICAgICBiLAogICAgICAgICAgTWF0aF9kZWZhdWx0LnNpZ24oYikgKiBNYXRoLnNxcnQocmFkaWNhbmQpLAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xNAogICAgICAgICk7CiAgICAgICAgaWYgKGIgPiAwKSB7CiAgICAgICAgICByZXR1cm4gW3EgLyBhMywgYyAvIHFdOwogICAgICAgIH0KICAgICAgICByZXR1cm4gW2MgLyBxLCBxIC8gYTNdOwogICAgICB9OwogICAgICBRdWFkcmF0aWNSZWFsUG9seW5vbWlhbF9kZWZhdWx0ID0gUXVhZHJhdGljUmVhbFBvbHlub21pYWw7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9DdWJpY1JlYWxQb2x5bm9taWFsLmpzCiAgZnVuY3Rpb24gY29tcHV0ZVJlYWxSb290cyhhMywgYiwgYywgZCkgewogICAgY29uc3QgQSA9IGEzOwogICAgY29uc3QgQiA9IGIgLyAzOwogICAgY29uc3QgQyA9IGMgLyAzOwogICAgY29uc3QgRCA9IGQ7CiAgICBjb25zdCBBQyA9IEEgKiBDOwogICAgY29uc3QgQkQgPSBCICogRDsKICAgIGNvbnN0IEIyID0gQiAqIEI7CiAgICBjb25zdCBDMiA9IEMgKiBDOwogICAgY29uc3QgZGVsdGExID0gQSAqIEMgLSBCMjsKICAgIGNvbnN0IGRlbHRhMiA9IEEgKiBEIC0gQiAqIEM7CiAgICBjb25zdCBkZWx0YTMgPSBCICogRCAtIEMyOwogICAgY29uc3QgZGlzY3JpbWluYW50ID0gNCAqIGRlbHRhMSAqIGRlbHRhMyAtIGRlbHRhMiAqIGRlbHRhMjsKICAgIGxldCB0ZW1wOwogICAgbGV0IHRlbXAxOwogICAgaWYgKGRpc2NyaW1pbmFudCA8IDApIHsKICAgICAgbGV0IEFCYXI7CiAgICAgIGxldCBDQmFyOwogICAgICBsZXQgREJhcjsKICAgICAgaWYgKEIyICogQkQgPj0gQUMgKiBDMikgewogICAgICAgIEFCYXIgPSBBOwogICAgICAgIENCYXIgPSBkZWx0YTE7CiAgICAgICAgREJhciA9IC0yICogQiAqIGRlbHRhMSArIEEgKiBkZWx0YTI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgQUJhciA9IEQ7CiAgICAgICAgQ0JhciA9IGRlbHRhMzsKICAgICAgICBEQmFyID0gLUQgKiBkZWx0YTIgKyAyICogQyAqIGRlbHRhMzsKICAgICAgfQogICAgICBjb25zdCBzID0gREJhciA8IDAgPyAtMSA6IDE7CiAgICAgIGNvbnN0IHRlbXAwID0gLXMgKiBNYXRoLmFicyhBQmFyKSAqIE1hdGguc3FydCgtZGlzY3JpbWluYW50KTsKICAgICAgdGVtcDEgPSAtREJhciArIHRlbXAwOwogICAgICBjb25zdCB4ID0gdGVtcDEgLyAyOwogICAgICBjb25zdCBwID0geCA8IDAgPyAtTWF0aC5wb3coLXgsIDEgLyAzKSA6IE1hdGgucG93KHgsIDEgLyAzKTsKICAgICAgY29uc3QgcSA9IHRlbXAxID09PSB0ZW1wMCA/IC1wIDogLUNCYXIgLyBwOwogICAgICB0ZW1wID0gQ0JhciA8PSAwID8gcCArIHEgOiAtREJhciAvIChwICogcCArIHEgKiBxICsgQ0Jhcik7CiAgICAgIGlmIChCMiAqIEJEID49IEFDICogQzIpIHsKICAgICAgICByZXR1cm4gWyh0ZW1wIC0gQikgLyBBXTsKICAgICAgfQogICAgICByZXR1cm4gWy1EIC8gKHRlbXAgKyBDKV07CiAgICB9CiAgICBjb25zdCBDQmFyQSA9IGRlbHRhMTsKICAgIGNvbnN0IERCYXJBID0gLTIgKiBCICogZGVsdGExICsgQSAqIGRlbHRhMjsKICAgIGNvbnN0IENCYXJEID0gZGVsdGEzOwogICAgY29uc3QgREJhckQgPSAtRCAqIGRlbHRhMiArIDIgKiBDICogZGVsdGEzOwogICAgY29uc3Qgc3F1YXJlUm9vdE9mRGlzY3JpbWluYW50ID0gTWF0aC5zcXJ0KGRpc2NyaW1pbmFudCk7CiAgICBjb25zdCBoYWxmU3F1YXJlUm9vdE9mMyA9IE1hdGguc3FydCgzKSAvIDI7CiAgICBsZXQgdGhldGEgPSBNYXRoLmFicyhNYXRoLmF0YW4yKEEgKiBzcXVhcmVSb290T2ZEaXNjcmltaW5hbnQsIC1EQmFyQSkgLyAzKTsKICAgIHRlbXAgPSAyICogTWF0aC5zcXJ0KC1DQmFyQSk7CiAgICBsZXQgY29zaW5lID0gTWF0aC5jb3ModGhldGEpOwogICAgdGVtcDEgPSB0ZW1wICogY29zaW5lOwogICAgbGV0IHRlbXAzID0gdGVtcCAqICgtY29zaW5lIC8gMiAtIGhhbGZTcXVhcmVSb290T2YzICogTWF0aC5zaW4odGhldGEpKTsKICAgIGNvbnN0IG51bWVyYXRvckxhcmdlID0gdGVtcDEgKyB0ZW1wMyA+IDIgKiBCID8gdGVtcDEgLSBCIDogdGVtcDMgLSBCOwogICAgY29uc3QgZGVub21pbmF0b3JMYXJnZSA9IEE7CiAgICBjb25zdCByb290MSA9IG51bWVyYXRvckxhcmdlIC8gZGVub21pbmF0b3JMYXJnZTsKICAgIHRoZXRhID0gTWF0aC5hYnMoTWF0aC5hdGFuMihEICogc3F1YXJlUm9vdE9mRGlzY3JpbWluYW50LCAtREJhckQpIC8gMyk7CiAgICB0ZW1wID0gMiAqIE1hdGguc3FydCgtQ0JhckQpOwogICAgY29zaW5lID0gTWF0aC5jb3ModGhldGEpOwogICAgdGVtcDEgPSB0ZW1wICogY29zaW5lOwogICAgdGVtcDMgPSB0ZW1wICogKC1jb3NpbmUgLyAyIC0gaGFsZlNxdWFyZVJvb3RPZjMgKiBNYXRoLnNpbih0aGV0YSkpOwogICAgY29uc3QgbnVtZXJhdG9yU21hbGwgPSAtRDsKICAgIGNvbnN0IGRlbm9taW5hdG9yU21hbGwgPSB0ZW1wMSArIHRlbXAzIDwgMiAqIEMgPyB0ZW1wMSArIEMgOiB0ZW1wMyArIEM7CiAgICBjb25zdCByb290MyA9IG51bWVyYXRvclNtYWxsIC8gZGVub21pbmF0b3JTbWFsbDsKICAgIGNvbnN0IEUgPSBkZW5vbWluYXRvckxhcmdlICogZGVub21pbmF0b3JTbWFsbDsKICAgIGNvbnN0IEYgPSAtbnVtZXJhdG9yTGFyZ2UgKiBkZW5vbWluYXRvclNtYWxsIC0gZGVub21pbmF0b3JMYXJnZSAqIG51bWVyYXRvclNtYWxsOwogICAgY29uc3QgRyA9IG51bWVyYXRvckxhcmdlICogbnVtZXJhdG9yU21hbGw7CiAgICBjb25zdCByb290MiA9IChDICogRiAtIEIgKiBHKSAvICgtQiAqIEYgKyBDICogRSk7CiAgICBpZiAocm9vdDEgPD0gcm9vdDIpIHsKICAgICAgaWYgKHJvb3QxIDw9IHJvb3QzKSB7CiAgICAgICAgaWYgKHJvb3QyIDw9IHJvb3QzKSB7CiAgICAgICAgICByZXR1cm4gW3Jvb3QxLCByb290Miwgcm9vdDNdOwogICAgICAgIH0KICAgICAgICByZXR1cm4gW3Jvb3QxLCByb290Mywgcm9vdDJdOwogICAgICB9CiAgICAgIHJldHVybiBbcm9vdDMsIHJvb3QxLCByb290Ml07CiAgICB9CiAgICBpZiAocm9vdDEgPD0gcm9vdDMpIHsKICAgICAgcmV0dXJuIFtyb290Miwgcm9vdDEsIHJvb3QzXTsKICAgIH0KICAgIGlmIChyb290MiA8PSByb290MykgewogICAgICByZXR1cm4gW3Jvb3QyLCByb290Mywgcm9vdDFdOwogICAgfQogICAgcmV0dXJuIFtyb290Mywgcm9vdDIsIHJvb3QxXTsKICB9CiAgdmFyIEN1YmljUmVhbFBvbHlub21pYWwsIEN1YmljUmVhbFBvbHlub21pYWxfZGVmYXVsdDsKICB2YXIgaW5pdF9DdWJpY1JlYWxQb2x5bm9taWFsID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9DdWJpY1JlYWxQb2x5bm9taWFsLmpzIigpIHsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X1F1YWRyYXRpY1JlYWxQb2x5bm9taWFsKCk7CiAgICAgIEN1YmljUmVhbFBvbHlub21pYWwgPSB7fTsKICAgICAgQ3ViaWNSZWFsUG9seW5vbWlhbC5jb21wdXRlRGlzY3JpbWluYW50ID0gZnVuY3Rpb24oYTMsIGIsIGMsIGQpIHsKICAgICAgICBpZiAodHlwZW9mIGEzICE9PSAibnVtYmVyIikgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImEgaXMgYSByZXF1aXJlZCBudW1iZXIuIik7CiAgICAgICAgfQogICAgICAgIGlmICh0eXBlb2YgYiAhPT0gIm51bWJlciIpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJiIGlzIGEgcmVxdWlyZWQgbnVtYmVyLiIpOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIGMgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYyBpcyBhIHJlcXVpcmVkIG51bWJlci4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKHR5cGVvZiBkICE9PSAibnVtYmVyIikgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImQgaXMgYSByZXF1aXJlZCBudW1iZXIuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGEyMiA9IGEzICogYTM7CiAgICAgICAgY29uc3QgYjIgPSBiICogYjsKICAgICAgICBjb25zdCBjMiA9IGMgKiBjOwogICAgICAgIGNvbnN0IGQyID0gZCAqIGQ7CiAgICAgICAgY29uc3QgZGlzY3JpbWluYW50ID0gMTggKiBhMyAqIGIgKiBjICogZCArIGIyICogYzIgLSAyNyAqIGEyMiAqIGQyIC0gNCAqIChhMyAqIGMyICogYyArIGIyICogYiAqIGQpOwogICAgICAgIHJldHVybiBkaXNjcmltaW5hbnQ7CiAgICAgIH07CiAgICAgIEN1YmljUmVhbFBvbHlub21pYWwuY29tcHV0ZVJlYWxSb290cyA9IGZ1bmN0aW9uKGEzLCBiLCBjLCBkKSB7CiAgICAgICAgaWYgKHR5cGVvZiBhMyAhPT0gIm51bWJlciIpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhIGlzIGEgcmVxdWlyZWQgbnVtYmVyLiIpOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIGIgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYiBpcyBhIHJlcXVpcmVkIG51bWJlci4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKHR5cGVvZiBjICE9PSAibnVtYmVyIikgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImMgaXMgYSByZXF1aXJlZCBudW1iZXIuIik7CiAgICAgICAgfQogICAgICAgIGlmICh0eXBlb2YgZCAhPT0gIm51bWJlciIpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJkIGlzIGEgcmVxdWlyZWQgbnVtYmVyLiIpOwogICAgICAgIH0KICAgICAgICBsZXQgcm9vdHM7CiAgICAgICAgbGV0IHJhdGlvOwogICAgICAgIGlmIChhMyA9PT0gMCkgewogICAgICAgICAgcmV0dXJuIFF1YWRyYXRpY1JlYWxQb2x5bm9taWFsX2RlZmF1bHQuY29tcHV0ZVJlYWxSb290cyhiLCBjLCBkKTsKICAgICAgICB9IGVsc2UgaWYgKGIgPT09IDApIHsKICAgICAgICAgIGlmIChjID09PSAwKSB7CiAgICAgICAgICAgIGlmIChkID09PSAwKSB7CiAgICAgICAgICAgICAgcmV0dXJuIFswLCAwLCAwXTsKICAgICAgICAgICAgfQogICAgICAgICAgICByYXRpbyA9IC1kIC8gYTM7CiAgICAgICAgICAgIGNvbnN0IHJvb3QgPSByYXRpbyA8IDAgPyAtTWF0aC5wb3coLXJhdGlvLCAxIC8gMykgOiBNYXRoLnBvdyhyYXRpbywgMSAvIDMpOwogICAgICAgICAgICByZXR1cm4gW3Jvb3QsIHJvb3QsIHJvb3RdOwogICAgICAgICAgfSBlbHNlIGlmIChkID09PSAwKSB7CiAgICAgICAgICAgIHJvb3RzID0gUXVhZHJhdGljUmVhbFBvbHlub21pYWxfZGVmYXVsdC5jb21wdXRlUmVhbFJvb3RzKGEzLCAwLCBjKTsKICAgICAgICAgICAgaWYgKHJvb3RzLkxlbmd0aCA9PT0gMCkgewogICAgICAgICAgICAgIHJldHVybiBbMF07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIFtyb290c1swXSwgMCwgcm9vdHNbMV1dOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGNvbXB1dGVSZWFsUm9vdHMoYTMsIDAsIGMsIGQpOwogICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gMCkgewogICAgICAgICAgaWYgKGQgPT09IDApIHsKICAgICAgICAgICAgcmF0aW8gPSAtYiAvIGEzOwogICAgICAgICAgICBpZiAocmF0aW8gPCAwKSB7CiAgICAgICAgICAgICAgcmV0dXJuIFtyYXRpbywgMCwgMF07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIFswLCAwLCByYXRpb107CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gY29tcHV0ZVJlYWxSb290cyhhMywgYiwgMCwgZCk7CiAgICAgICAgfSBlbHNlIGlmIChkID09PSAwKSB7CiAgICAgICAgICByb290cyA9IFF1YWRyYXRpY1JlYWxQb2x5bm9taWFsX2RlZmF1bHQuY29tcHV0ZVJlYWxSb290cyhhMywgYiwgYyk7CiAgICAgICAgICBpZiAocm9vdHMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgIHJldHVybiBbMF07CiAgICAgICAgICB9IGVsc2UgaWYgKHJvb3RzWzFdIDw9IDApIHsKICAgICAgICAgICAgcmV0dXJuIFtyb290c1swXSwgcm9vdHNbMV0sIDBdOwogICAgICAgICAgfSBlbHNlIGlmIChyb290c1swXSA+PSAwKSB7CiAgICAgICAgICAgIHJldHVybiBbMCwgcm9vdHNbMF0sIHJvb3RzWzFdXTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBbcm9vdHNbMF0sIDAsIHJvb3RzWzFdXTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNvbXB1dGVSZWFsUm9vdHMoYTMsIGIsIGMsIGQpOwogICAgICB9OwogICAgICBDdWJpY1JlYWxQb2x5bm9taWFsX2RlZmF1bHQgPSBDdWJpY1JlYWxQb2x5bm9taWFsOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUXVhcnRpY1JlYWxQb2x5bm9taWFsLmpzCiAgZnVuY3Rpb24gb3JpZ2luYWwoYTMsIGEyMiwgYTEsIGEwKSB7CiAgICBjb25zdCBhM1NxdWFyZWQgPSBhMyAqIGEzOwogICAgY29uc3QgcCA9IGEyMiAtIDMgKiBhM1NxdWFyZWQgLyA4OwogICAgY29uc3QgcSA9IGExIC0gYTIyICogYTMgLyAyICsgYTNTcXVhcmVkICogYTMgLyA4OwogICAgY29uc3QgciA9IGEwIC0gYTEgKiBhMyAvIDQgKyBhMjIgKiBhM1NxdWFyZWQgLyAxNiAtIDMgKiBhM1NxdWFyZWQgKiBhM1NxdWFyZWQgLyAyNTY7CiAgICBjb25zdCBjdWJpY1Jvb3RzID0gQ3ViaWNSZWFsUG9seW5vbWlhbF9kZWZhdWx0LmNvbXB1dGVSZWFsUm9vdHMoCiAgICAgIDEsCiAgICAgIDIgKiBwLAogICAgICBwICogcCAtIDQgKiByLAogICAgICAtcSAqIHEKICAgICk7CiAgICBpZiAoY3ViaWNSb290cy5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IHRlbXAgPSAtYTMgLyA0OwogICAgICBjb25zdCBoU3F1YXJlZCA9IGN1YmljUm9vdHNbY3ViaWNSb290cy5sZW5ndGggLSAxXTsKICAgICAgaWYgKE1hdGguYWJzKGhTcXVhcmVkKSA8IE1hdGhfZGVmYXVsdC5FUFNJTE9OMTQpIHsKICAgICAgICBjb25zdCByb290cyA9IFF1YWRyYXRpY1JlYWxQb2x5bm9taWFsX2RlZmF1bHQuY29tcHV0ZVJlYWxSb290cygxLCBwLCByKTsKICAgICAgICBpZiAocm9vdHMubGVuZ3RoID09PSAyKSB7CiAgICAgICAgICBjb25zdCByb290MCA9IHJvb3RzWzBdOwogICAgICAgICAgY29uc3Qgcm9vdDEgPSByb290c1sxXTsKICAgICAgICAgIGxldCB5OwogICAgICAgICAgaWYgKHJvb3QwID49IDAgJiYgcm9vdDEgPj0gMCkgewogICAgICAgICAgICBjb25zdCB5MCA9IE1hdGguc3FydChyb290MCk7CiAgICAgICAgICAgIGNvbnN0IHkxID0gTWF0aC5zcXJ0KHJvb3QxKTsKICAgICAgICAgICAgcmV0dXJuIFt0ZW1wIC0geTEsIHRlbXAgLSB5MCwgdGVtcCArIHkwLCB0ZW1wICsgeTFdOwogICAgICAgICAgfSBlbHNlIGlmIChyb290MCA+PSAwICYmIHJvb3QxIDwgMCkgewogICAgICAgICAgICB5ID0gTWF0aC5zcXJ0KHJvb3QwKTsKICAgICAgICAgICAgcmV0dXJuIFt0ZW1wIC0geSwgdGVtcCArIHldOwogICAgICAgICAgfSBlbHNlIGlmIChyb290MCA8IDAgJiYgcm9vdDEgPj0gMCkgewogICAgICAgICAgICB5ID0gTWF0aC5zcXJ0KHJvb3QxKTsKICAgICAgICAgICAgcmV0dXJuIFt0ZW1wIC0geSwgdGVtcCArIHldOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gW107CiAgICAgIH0gZWxzZSBpZiAoaFNxdWFyZWQgPiAwKSB7CiAgICAgICAgY29uc3QgaCA9IE1hdGguc3FydChoU3F1YXJlZCk7CiAgICAgICAgY29uc3QgbSA9IChwICsgaFNxdWFyZWQgLSBxIC8gaCkgLyAyOwogICAgICAgIGNvbnN0IG4gPSAocCArIGhTcXVhcmVkICsgcSAvIGgpIC8gMjsKICAgICAgICBjb25zdCByb290czEgPSBRdWFkcmF0aWNSZWFsUG9seW5vbWlhbF9kZWZhdWx0LmNvbXB1dGVSZWFsUm9vdHMoMSwgaCwgbSk7CiAgICAgICAgY29uc3Qgcm9vdHMyID0gUXVhZHJhdGljUmVhbFBvbHlub21pYWxfZGVmYXVsdC5jb21wdXRlUmVhbFJvb3RzKDEsIC1oLCBuKTsKICAgICAgICBpZiAocm9vdHMxLmxlbmd0aCAhPT0gMCkgewogICAgICAgICAgcm9vdHMxWzBdICs9IHRlbXA7CiAgICAgICAgICByb290czFbMV0gKz0gdGVtcDsKICAgICAgICAgIGlmIChyb290czIubGVuZ3RoICE9PSAwKSB7CiAgICAgICAgICAgIHJvb3RzMlswXSArPSB0ZW1wOwogICAgICAgICAgICByb290czJbMV0gKz0gdGVtcDsKICAgICAgICAgICAgaWYgKHJvb3RzMVsxXSA8PSByb290czJbMF0pIHsKICAgICAgICAgICAgICByZXR1cm4gW3Jvb3RzMVswXSwgcm9vdHMxWzFdLCByb290czJbMF0sIHJvb3RzMlsxXV07CiAgICAgICAgICAgIH0gZWxzZSBpZiAocm9vdHMyWzFdIDw9IHJvb3RzMVswXSkgewogICAgICAgICAgICAgIHJldHVybiBbcm9vdHMyWzBdLCByb290czJbMV0sIHJvb3RzMVswXSwgcm9vdHMxWzFdXTsKICAgICAgICAgICAgfSBlbHNlIGlmIChyb290czFbMF0gPj0gcm9vdHMyWzBdICYmIHJvb3RzMVsxXSA8PSByb290czJbMV0pIHsKICAgICAgICAgICAgICByZXR1cm4gW3Jvb3RzMlswXSwgcm9vdHMxWzBdLCByb290czFbMV0sIHJvb3RzMlsxXV07CiAgICAgICAgICAgIH0gZWxzZSBpZiAocm9vdHMyWzBdID49IHJvb3RzMVswXSAmJiByb290czJbMV0gPD0gcm9vdHMxWzFdKSB7CiAgICAgICAgICAgICAgcmV0dXJuIFtyb290czFbMF0sIHJvb3RzMlswXSwgcm9vdHMyWzFdLCByb290czFbMV1dOwogICAgICAgICAgICB9IGVsc2UgaWYgKHJvb3RzMVswXSA+IHJvb3RzMlswXSAmJiByb290czFbMF0gPCByb290czJbMV0pIHsKICAgICAgICAgICAgICByZXR1cm4gW3Jvb3RzMlswXSwgcm9vdHMxWzBdLCByb290czJbMV0sIHJvb3RzMVsxXV07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIFtyb290czFbMF0sIHJvb3RzMlswXSwgcm9vdHMxWzFdLCByb290czJbMV1dOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHJvb3RzMTsKICAgICAgICB9CiAgICAgICAgaWYgKHJvb3RzMi5sZW5ndGggIT09IDApIHsKICAgICAgICAgIHJvb3RzMlswXSArPSB0ZW1wOwogICAgICAgICAgcm9vdHMyWzFdICs9IHRlbXA7CiAgICAgICAgICByZXR1cm4gcm9vdHMyOwogICAgICAgIH0KICAgICAgICByZXR1cm4gW107CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBbXTsKICB9CiAgZnVuY3Rpb24gbmV1bWFyayhhMywgYTIyLCBhMSwgYTApIHsKICAgIGNvbnN0IGExU3F1YXJlZCA9IGExICogYTE7CiAgICBjb25zdCBhMlNxdWFyZWQgPSBhMjIgKiBhMjI7CiAgICBjb25zdCBhM1NxdWFyZWQgPSBhMyAqIGEzOwogICAgY29uc3QgcCA9IC0yICogYTIyOwogICAgY29uc3QgcSA9IGExICogYTMgKyBhMlNxdWFyZWQgLSA0ICogYTA7CiAgICBjb25zdCByID0gYTNTcXVhcmVkICogYTAgLSBhMSAqIGEyMiAqIGEzICsgYTFTcXVhcmVkOwogICAgY29uc3QgY3ViaWNSb290cyA9IEN1YmljUmVhbFBvbHlub21pYWxfZGVmYXVsdC5jb21wdXRlUmVhbFJvb3RzKDEsIHAsIHEsIHIpOwogICAgaWYgKGN1YmljUm9vdHMubGVuZ3RoID4gMCkgewogICAgICBjb25zdCB5ID0gY3ViaWNSb290c1swXTsKICAgICAgY29uc3QgdGVtcCA9IGEyMiAtIHk7CiAgICAgIGNvbnN0IHRlbXBTcXVhcmVkID0gdGVtcCAqIHRlbXA7CiAgICAgIGNvbnN0IGcxID0gYTMgLyAyOwogICAgICBjb25zdCBoMSA9IHRlbXAgLyAyOwogICAgICBjb25zdCBtID0gdGVtcFNxdWFyZWQgLSA0ICogYTA7CiAgICAgIGNvbnN0IG1FcnJvciA9IHRlbXBTcXVhcmVkICsgNCAqIE1hdGguYWJzKGEwKTsKICAgICAgY29uc3QgbiA9IGEzU3F1YXJlZCAtIDQgKiB5OwogICAgICBjb25zdCBuRXJyb3IgPSBhM1NxdWFyZWQgKyA0ICogTWF0aC5hYnMoeSk7CiAgICAgIGxldCBnMjsKICAgICAgbGV0IGgyOwogICAgICBpZiAoeSA8IDAgfHwgbSAqIG5FcnJvciA8IG4gKiBtRXJyb3IpIHsKICAgICAgICBjb25zdCBzcXVhcmVSb290T2ZOID0gTWF0aC5zcXJ0KG4pOwogICAgICAgIGcyID0gc3F1YXJlUm9vdE9mTiAvIDI7CiAgICAgICAgaDIgPSBzcXVhcmVSb290T2ZOID09PSAwID8gMCA6IChhMyAqIGgxIC0gYTEpIC8gc3F1YXJlUm9vdE9mTjsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBzcXVhcmVSb290T2ZNID0gTWF0aC5zcXJ0KG0pOwogICAgICAgIGcyID0gc3F1YXJlUm9vdE9mTSA9PT0gMCA/IDAgOiAoYTMgKiBoMSAtIGExKSAvIHNxdWFyZVJvb3RPZk07CiAgICAgICAgaDIgPSBzcXVhcmVSb290T2ZNIC8gMjsKICAgICAgfQogICAgICBsZXQgRzsKICAgICAgbGV0IGc7CiAgICAgIGlmIChnMSA9PT0gMCAmJiBnMiA9PT0gMCkgewogICAgICAgIEcgPSAwOwogICAgICAgIGcgPSAwOwogICAgICB9IGVsc2UgaWYgKE1hdGhfZGVmYXVsdC5zaWduKGcxKSA9PT0gTWF0aF9kZWZhdWx0LnNpZ24oZzIpKSB7CiAgICAgICAgRyA9IGcxICsgZzI7CiAgICAgICAgZyA9IHkgLyBHOwogICAgICB9IGVsc2UgewogICAgICAgIGcgPSBnMSAtIGcyOwogICAgICAgIEcgPSB5IC8gZzsKICAgICAgfQogICAgICBsZXQgSDsKICAgICAgbGV0IGg7CiAgICAgIGlmIChoMSA9PT0gMCAmJiBoMiA9PT0gMCkgewogICAgICAgIEggPSAwOwogICAgICAgIGggPSAwOwogICAgICB9IGVsc2UgaWYgKE1hdGhfZGVmYXVsdC5zaWduKGgxKSA9PT0gTWF0aF9kZWZhdWx0LnNpZ24oaDIpKSB7CiAgICAgICAgSCA9IGgxICsgaDI7CiAgICAgICAgaCA9IGEwIC8gSDsKICAgICAgfSBlbHNlIHsKICAgICAgICBoID0gaDEgLSBoMjsKICAgICAgICBIID0gYTAgLyBoOwogICAgICB9CiAgICAgIGNvbnN0IHJvb3RzMSA9IFF1YWRyYXRpY1JlYWxQb2x5bm9taWFsX2RlZmF1bHQuY29tcHV0ZVJlYWxSb290cygxLCBHLCBIKTsKICAgICAgY29uc3Qgcm9vdHMyID0gUXVhZHJhdGljUmVhbFBvbHlub21pYWxfZGVmYXVsdC5jb21wdXRlUmVhbFJvb3RzKDEsIGcsIGgpOwogICAgICBpZiAocm9vdHMxLmxlbmd0aCAhPT0gMCkgewogICAgICAgIGlmIChyb290czIubGVuZ3RoICE9PSAwKSB7CiAgICAgICAgICBpZiAocm9vdHMxWzFdIDw9IHJvb3RzMlswXSkgewogICAgICAgICAgICByZXR1cm4gW3Jvb3RzMVswXSwgcm9vdHMxWzFdLCByb290czJbMF0sIHJvb3RzMlsxXV07CiAgICAgICAgICB9IGVsc2UgaWYgKHJvb3RzMlsxXSA8PSByb290czFbMF0pIHsKICAgICAgICAgICAgcmV0dXJuIFtyb290czJbMF0sIHJvb3RzMlsxXSwgcm9vdHMxWzBdLCByb290czFbMV1dOwogICAgICAgICAgfSBlbHNlIGlmIChyb290czFbMF0gPj0gcm9vdHMyWzBdICYmIHJvb3RzMVsxXSA8PSByb290czJbMV0pIHsKICAgICAgICAgICAgcmV0dXJuIFtyb290czJbMF0sIHJvb3RzMVswXSwgcm9vdHMxWzFdLCByb290czJbMV1dOwogICAgICAgICAgfSBlbHNlIGlmIChyb290czJbMF0gPj0gcm9vdHMxWzBdICYmIHJvb3RzMlsxXSA8PSByb290czFbMV0pIHsKICAgICAgICAgICAgcmV0dXJuIFtyb290czFbMF0sIHJvb3RzMlswXSwgcm9vdHMyWzFdLCByb290czFbMV1dOwogICAgICAgICAgfSBlbHNlIGlmIChyb290czFbMF0gPiByb290czJbMF0gJiYgcm9vdHMxWzBdIDwgcm9vdHMyWzFdKSB7CiAgICAgICAgICAgIHJldHVybiBbcm9vdHMyWzBdLCByb290czFbMF0sIHJvb3RzMlsxXSwgcm9vdHMxWzFdXTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBbcm9vdHMxWzBdLCByb290czJbMF0sIHJvb3RzMVsxXSwgcm9vdHMyWzFdXTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJvb3RzMTsKICAgICAgfQogICAgICBpZiAocm9vdHMyLmxlbmd0aCAhPT0gMCkgewogICAgICAgIHJldHVybiByb290czI7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBbXTsKICB9CiAgdmFyIFF1YXJ0aWNSZWFsUG9seW5vbWlhbCwgUXVhcnRpY1JlYWxQb2x5bm9taWFsX2RlZmF1bHQ7CiAgdmFyIGluaXRfUXVhcnRpY1JlYWxQb2x5bm9taWFsID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9RdWFydGljUmVhbFBvbHlub21pYWwuanMiKCkgewogICAgICBpbml0X0N1YmljUmVhbFBvbHlub21pYWwoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9RdWFkcmF0aWNSZWFsUG9seW5vbWlhbCgpOwogICAgICBRdWFydGljUmVhbFBvbHlub21pYWwgPSB7fTsKICAgICAgUXVhcnRpY1JlYWxQb2x5bm9taWFsLmNvbXB1dGVEaXNjcmltaW5hbnQgPSBmdW5jdGlvbihhMywgYiwgYywgZCwgZSkgewogICAgICAgIGlmICh0eXBlb2YgYTMgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYSBpcyBhIHJlcXVpcmVkIG51bWJlci4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSAibnVtYmVyIikgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImIgaXMgYSByZXF1aXJlZCBudW1iZXIuIik7CiAgICAgICAgfQogICAgICAgIGlmICh0eXBlb2YgYyAhPT0gIm51bWJlciIpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJjIGlzIGEgcmVxdWlyZWQgbnVtYmVyLiIpOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIGQgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZCBpcyBhIHJlcXVpcmVkIG51bWJlci4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKHR5cGVvZiBlICE9PSAibnVtYmVyIikgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImUgaXMgYSByZXF1aXJlZCBudW1iZXIuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGEyMiA9IGEzICogYTM7CiAgICAgICAgY29uc3QgYTMyID0gYTIyICogYTM7CiAgICAgICAgY29uc3QgYjIgPSBiICogYjsKICAgICAgICBjb25zdCBiMyA9IGIyICogYjsKICAgICAgICBjb25zdCBjMiA9IGMgKiBjOwogICAgICAgIGNvbnN0IGMzMiA9IGMyICogYzsKICAgICAgICBjb25zdCBkMiA9IGQgKiBkOwogICAgICAgIGNvbnN0IGQzID0gZDIgKiBkOwogICAgICAgIGNvbnN0IGUyID0gZSAqIGU7CiAgICAgICAgY29uc3QgZTMgPSBlMiAqIGU7CiAgICAgICAgY29uc3QgZGlzY3JpbWluYW50ID0gYjIgKiBjMiAqIGQyIC0gNCAqIGIzICogZDMgLSA0ICogYTMgKiBjMzIgKiBkMiArIDE4ICogYTMgKiBiICogYyAqIGQzIC0gMjcgKiBhMjIgKiBkMiAqIGQyICsgMjU2ICogYTMyICogZTMgKyBlICogKDE4ICogYjMgKiBjICogZCAtIDQgKiBiMiAqIGMzMiArIDE2ICogYTMgKiBjMiAqIGMyIC0gODAgKiBhMyAqIGIgKiBjMiAqIGQgLSA2ICogYTMgKiBiMiAqIGQyICsgMTQ0ICogYTIyICogYyAqIGQyKSArIGUyICogKDE0NCAqIGEzICogYjIgKiBjIC0gMjcgKiBiMiAqIGIyIC0gMTI4ICogYTIyICogYzIgLSAxOTIgKiBhMjIgKiBiICogZCk7CiAgICAgICAgcmV0dXJuIGRpc2NyaW1pbmFudDsKICAgICAgfTsKICAgICAgUXVhcnRpY1JlYWxQb2x5bm9taWFsLmNvbXB1dGVSZWFsUm9vdHMgPSBmdW5jdGlvbihhMywgYiwgYywgZCwgZSkgewogICAgICAgIGlmICh0eXBlb2YgYTMgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYSBpcyBhIHJlcXVpcmVkIG51bWJlci4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKHR5cGVvZiBiICE9PSAibnVtYmVyIikgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImIgaXMgYSByZXF1aXJlZCBudW1iZXIuIik7CiAgICAgICAgfQogICAgICAgIGlmICh0eXBlb2YgYyAhPT0gIm51bWJlciIpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJjIGlzIGEgcmVxdWlyZWQgbnVtYmVyLiIpOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZW9mIGQgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZCBpcyBhIHJlcXVpcmVkIG51bWJlci4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKHR5cGVvZiBlICE9PSAibnVtYmVyIikgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImUgaXMgYSByZXF1aXJlZCBudW1iZXIuIik7CiAgICAgICAgfQogICAgICAgIGlmIChNYXRoLmFicyhhMykgPCBNYXRoX2RlZmF1bHQuRVBTSUxPTjE1KSB7CiAgICAgICAgICByZXR1cm4gQ3ViaWNSZWFsUG9seW5vbWlhbF9kZWZhdWx0LmNvbXB1dGVSZWFsUm9vdHMoYiwgYywgZCwgZSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGEzMiA9IGIgLyBhMzsKICAgICAgICBjb25zdCBhMjIgPSBjIC8gYTM7CiAgICAgICAgY29uc3QgYTEgPSBkIC8gYTM7CiAgICAgICAgY29uc3QgYTAgPSBlIC8gYTM7CiAgICAgICAgbGV0IGsgPSBhMzIgPCAwID8gMSA6IDA7CiAgICAgICAgayArPSBhMjIgPCAwID8gayArIDEgOiBrOwogICAgICAgIGsgKz0gYTEgPCAwID8gayArIDEgOiBrOwogICAgICAgIGsgKz0gYTAgPCAwID8gayArIDEgOiBrOwogICAgICAgIHN3aXRjaCAoaykgewogICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICByZXR1cm4gb3JpZ2luYWwoYTMyLCBhMjIsIGExLCBhMCk7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHJldHVybiBuZXVtYXJrKGEzMiwgYTIyLCBhMSwgYTApOwogICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICByZXR1cm4gbmV1bWFyayhhMzIsIGEyMiwgYTEsIGEwKTsKICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsKGEzMiwgYTIyLCBhMSwgYTApOwogICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICByZXR1cm4gb3JpZ2luYWwoYTMyLCBhMjIsIGExLCBhMCk7CiAgICAgICAgICBjYXNlIDU6CiAgICAgICAgICAgIHJldHVybiBuZXVtYXJrKGEzMiwgYTIyLCBhMSwgYTApOwogICAgICAgICAgY2FzZSA2OgogICAgICAgICAgICByZXR1cm4gb3JpZ2luYWwoYTMyLCBhMjIsIGExLCBhMCk7CiAgICAgICAgICBjYXNlIDc6CiAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbChhMzIsIGEyMiwgYTEsIGEwKTsKICAgICAgICAgIGNhc2UgODoKICAgICAgICAgICAgcmV0dXJuIG5ldW1hcmsoYTMyLCBhMjIsIGExLCBhMCk7CiAgICAgICAgICBjYXNlIDk6CiAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbChhMzIsIGEyMiwgYTEsIGEwKTsKICAgICAgICAgIGNhc2UgMTA6CiAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbChhMzIsIGEyMiwgYTEsIGEwKTsKICAgICAgICAgIGNhc2UgMTE6CiAgICAgICAgICAgIHJldHVybiBuZXVtYXJrKGEzMiwgYTIyLCBhMSwgYTApOwogICAgICAgICAgY2FzZSAxMjoKICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsKGEzMiwgYTIyLCBhMSwgYTApOwogICAgICAgICAgY2FzZSAxMzoKICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsKGEzMiwgYTIyLCBhMSwgYTApOwogICAgICAgICAgY2FzZSAxNDoKICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsKGEzMiwgYTIyLCBhMSwgYTApOwogICAgICAgICAgY2FzZSAxNToKICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsKGEzMiwgYTIyLCBhMSwgYTApOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgIH07CiAgICAgIFF1YXJ0aWNSZWFsUG9seW5vbWlhbF9kZWZhdWx0ID0gUXVhcnRpY1JlYWxQb2x5bm9taWFsOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUmF5LmpzCiAgZnVuY3Rpb24gUmF5KG9yaWdpbiwgZGlyZWN0aW9uMikgewogICAgZGlyZWN0aW9uMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShkaXJlY3Rpb24yID8/IENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPKTsKICAgIGlmICghQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFscyhkaXJlY3Rpb24yLCBDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTykpIHsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShkaXJlY3Rpb24yLCBkaXJlY3Rpb24yKTsKICAgIH0KICAgIHRoaXMub3JpZ2luID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKG9yaWdpbiA/PyBDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTyk7CiAgICB0aGlzLmRpcmVjdGlvbiA9IGRpcmVjdGlvbjI7CiAgfQogIHZhciBSYXlfZGVmYXVsdDsKICB2YXIgaW5pdF9SYXkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1JheS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBSYXkuY2xvbmUgPSBmdW5jdGlvbihyYXksIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJheSkpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgUmF5KHJheS5vcmlnaW4sIHJheS5kaXJlY3Rpb24pOwogICAgICAgIH0KICAgICAgICByZXN1bHQub3JpZ2luID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHJheS5vcmlnaW4pOwogICAgICAgIHJlc3VsdC5kaXJlY3Rpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocmF5LmRpcmVjdGlvbik7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUmF5LmdldFBvaW50ID0gZnVuY3Rpb24ocmF5LCB0LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJheSIsIHJheSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJ0IiwgdCk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihyYXkuZGlyZWN0aW9uLCB0LCByZXN1bHQpOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHJheS5vcmlnaW4sIHJlc3VsdCwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgUmF5X2RlZmF1bHQgPSBSYXk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9JbnRlcnNlY3Rpb25UZXN0cy5qcwogIGZ1bmN0aW9uIHNvbHZlUXVhZHJhdGljKGEzLCBiLCBjLCByZXN1bHQpIHsKICAgIGNvbnN0IGRldCA9IGIgKiBiIC0gNCAqIGEzICogYzsKICAgIGlmIChkZXQgPCAwKSB7CiAgICAgIHJldHVybiB2b2lkIDA7CiAgICB9IGVsc2UgaWYgKGRldCA+IDApIHsKICAgICAgY29uc3QgZGVub20gPSAxIC8gKDIgKiBhMyk7CiAgICAgIGNvbnN0IGRpc2MgPSBNYXRoLnNxcnQoZGV0KTsKICAgICAgY29uc3Qgcm9vdDAgPSAoLWIgKyBkaXNjKSAqIGRlbm9tOwogICAgICBjb25zdCByb290MSA9ICgtYiAtIGRpc2MpICogZGVub207CiAgICAgIGlmIChyb290MCA8IHJvb3QxKSB7CiAgICAgICAgcmVzdWx0LnJvb3QwID0gcm9vdDA7CiAgICAgICAgcmVzdWx0LnJvb3QxID0gcm9vdDE7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmVzdWx0LnJvb3QwID0gcm9vdDE7CiAgICAgICAgcmVzdWx0LnJvb3QxID0gcm9vdDA7CiAgICAgIH0KICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIGNvbnN0IHJvb3QgPSAtYiAvICgyICogYTMpOwogICAgaWYgKHJvb3QgPT09IDApIHsKICAgICAgcmV0dXJuIHZvaWQgMDsKICAgIH0KICAgIHJlc3VsdC5yb290MCA9IHJlc3VsdC5yb290MSA9IHJvb3Q7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICBmdW5jdGlvbiByYXlTcGhlcmUocmF5LCBzcGhlcmUsIHJlc3VsdCkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICByZXN1bHQgPSBuZXcgSW50ZXJ2YWxfZGVmYXVsdCgpOwogICAgfQogICAgY29uc3Qgb3JpZ2luID0gcmF5Lm9yaWdpbjsKICAgIGNvbnN0IGRpcmVjdGlvbjIgPSByYXkuZGlyZWN0aW9uOwogICAgY29uc3QgY2VudGVyID0gc3BoZXJlLmNlbnRlcjsKICAgIGNvbnN0IHJhZGl1c1NxdWFyZWQgPSBzcGhlcmUucmFkaXVzICogc3BoZXJlLnJhZGl1czsKICAgIGNvbnN0IGRpZmYgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3Qob3JpZ2luLCBjZW50ZXIsIHNjcmF0Y2hQVmVjKTsKICAgIGNvbnN0IGEzID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCBkaXJlY3Rpb24yKTsKICAgIGNvbnN0IGIgPSAyICogQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCBkaWZmKTsKICAgIGNvbnN0IGMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlU3F1YXJlZChkaWZmKSAtIHJhZGl1c1NxdWFyZWQ7CiAgICBjb25zdCByb290cyA9IHNvbHZlUXVhZHJhdGljKGEzLCBiLCBjLCByYXlTcGhlcmVSb290cyk7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyb290cykpIHsKICAgICAgcmV0dXJuIHZvaWQgMDsKICAgIH0KICAgIHJlc3VsdC5zdGFydCA9IHJvb3RzLnJvb3QwOwogICAgcmVzdWx0LnN0b3AgPSByb290cy5yb290MTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGZ1bmN0aW9uIGFkZFdpdGhDYW5jZWxsYXRpb25DaGVjazIobGVmdCwgcmlnaHQsIHRvbGVyYW5jZSkgewogICAgY29uc3QgZGlmZmVyZW5jZSA9IGxlZnQgKyByaWdodDsKICAgIGlmIChNYXRoX2RlZmF1bHQuc2lnbihsZWZ0KSAhPT0gTWF0aF9kZWZhdWx0LnNpZ24ocmlnaHQpICYmIE1hdGguYWJzKGRpZmZlcmVuY2UgLyBNYXRoLm1heChNYXRoLmFicyhsZWZ0KSwgTWF0aC5hYnMocmlnaHQpKSkgPCB0b2xlcmFuY2UpIHsKICAgICAgcmV0dXJuIDA7CiAgICB9CiAgICByZXR1cm4gZGlmZmVyZW5jZTsKICB9CiAgdmFyIEludGVyc2VjdGlvblRlc3RzLCBzY3JhdGNoRWRnZTAsIHNjcmF0Y2hFZGdlMSwgc2NyYXRjaFBWZWMsIHNjcmF0Y2hUVmVjLCBzY3JhdGNoUVZlYywgc2NyYXRjaExpbmVTZWdtZW50VHJpYW5nbGVSYXksIHJheVNwaGVyZVJvb3RzLCBzY3JhdGNoTGluZVNlZ21lbnRSYXksIHNjcmF0Y2hRLCBzY3JhdGNoVywgZmlyc3RBeGlzU2NyYXRjaCwgc2Vjb25kQXhpc1NjcmF0Y2gsIHRoaXJkQXhpc1NjcmF0Y2gsIHJlZmVyZW5jZVNjcmF0Y2gsIGJDYXJ0LCBiU2NyYXRjaCwgYnRTY3JhdGNoLCBkaVNjcmF0Y2gsIGRTY3JhdGNoLCBjU2NyYXRjaCwgdGVtcE1hdHJpeCwgYVNjcmF0Y2gsIHNTY3JhdGNoLCBjbG9zZXN0U2NyYXRjaCwgc3VyZlBvaW50U2NyYXRjaCwgbGluZVNlZ21lbnRQbGFuZURpZmZlcmVuY2UsIEludGVyc2VjdGlvblRlc3RzX2RlZmF1bHQ7CiAgdmFyIGluaXRfSW50ZXJzZWN0aW9uVGVzdHMgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0ludGVyc2VjdGlvblRlc3RzLmpzIigpIHsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfSW50ZXJ2YWwoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfTWF0cml4MygpOwogICAgICBpbml0X1F1YWRyYXRpY1JlYWxQb2x5bm9taWFsKCk7CiAgICAgIGluaXRfUXVhcnRpY1JlYWxQb2x5bm9taWFsKCk7CiAgICAgIGluaXRfUmF5KCk7CiAgICAgIEludGVyc2VjdGlvblRlc3RzID0ge307CiAgICAgIEludGVyc2VjdGlvblRlc3RzLnJheVBsYW5lID0gZnVuY3Rpb24ocmF5LCBwbGFuZSwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInJheSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocGxhbmUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicGxhbmUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgb3JpZ2luID0gcmF5Lm9yaWdpbjsKICAgICAgICBjb25zdCBkaXJlY3Rpb24yID0gcmF5LmRpcmVjdGlvbjsKICAgICAgICBjb25zdCBub3JtYWwyID0gcGxhbmUubm9ybWFsOwogICAgICAgIGNvbnN0IGRlbm9taW5hdG9yID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChub3JtYWwyLCBkaXJlY3Rpb24yKTsKICAgICAgICBpZiAoTWF0aC5hYnMoZGVub21pbmF0b3IpIDwgTWF0aF9kZWZhdWx0LkVQU0lMT04xNSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgY29uc3QgdCA9ICgtcGxhbmUuZGlzdGFuY2UgLSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KG5vcm1hbDIsIG9yaWdpbikpIC8gZGVub21pbmF0b3I7CiAgICAgICAgaWYgKHQgPCAwKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICByZXN1bHQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihkaXJlY3Rpb24yLCB0LCByZXN1bHQpOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKG9yaWdpbiwgcmVzdWx0LCByZXN1bHQpOwogICAgICB9OwogICAgICBzY3JhdGNoRWRnZTAgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hFZGdlMSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBWZWMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hUVmVjID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUVZlYyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgSW50ZXJzZWN0aW9uVGVzdHMucmF5VHJpYW5nbGVQYXJhbWV0cmljID0gZnVuY3Rpb24ocmF5LCBwMCwgcDEsIHAyLCBjdWxsQmFja0ZhY2VzKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInJheSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocDApKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicDAgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHAxKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInAxIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwMikpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJwMiBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY3VsbEJhY2tGYWNlcyA9IGN1bGxCYWNrRmFjZXMgPz8gZmFsc2U7CiAgICAgICAgY29uc3Qgb3JpZ2luID0gcmF5Lm9yaWdpbjsKICAgICAgICBjb25zdCBkaXJlY3Rpb24yID0gcmF5LmRpcmVjdGlvbjsKICAgICAgICBjb25zdCBlZGdlMCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChwMSwgcDAsIHNjcmF0Y2hFZGdlMCk7CiAgICAgICAgY29uc3QgZWRnZTEgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QocDIsIHAwLCBzY3JhdGNoRWRnZTEpOwogICAgICAgIGNvbnN0IHAgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoZGlyZWN0aW9uMiwgZWRnZTEsIHNjcmF0Y2hQVmVjKTsKICAgICAgICBjb25zdCBkZXQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KGVkZ2UwLCBwKTsKICAgICAgICBsZXQgdHZlYzsKICAgICAgICBsZXQgcTsKICAgICAgICBsZXQgdTM7CiAgICAgICAgbGV0IHYzOwogICAgICAgIGxldCB0OwogICAgICAgIGlmIChjdWxsQmFja0ZhY2VzKSB7CiAgICAgICAgICBpZiAoZGV0IDwgTWF0aF9kZWZhdWx0LkVQU0lMT042KSB7CiAgICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgICB9CiAgICAgICAgICB0dmVjID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KG9yaWdpbiwgcDAsIHNjcmF0Y2hUVmVjKTsKICAgICAgICAgIHUzID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdCh0dmVjLCBwKTsKICAgICAgICAgIGlmICh1MyA8IDAgfHwgdTMgPiBkZXQpIHsKICAgICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICAgIH0KICAgICAgICAgIHEgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3ModHZlYywgZWRnZTAsIHNjcmF0Y2hRVmVjKTsKICAgICAgICAgIHYzID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCBxKTsKICAgICAgICAgIGlmICh2MyA8IDAgfHwgdTMgKyB2MyA+IGRldCkgewogICAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgICAgfQogICAgICAgICAgdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QoZWRnZTEsIHEpIC8gZGV0OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoTWF0aC5hYnMoZGV0KSA8IE1hdGhfZGVmYXVsdC5FUFNJTE9ONikgewogICAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgaW52RGV0ID0gMSAvIGRldDsKICAgICAgICAgIHR2ZWMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3Qob3JpZ2luLCBwMCwgc2NyYXRjaFRWZWMpOwogICAgICAgICAgdTMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHR2ZWMsIHApICogaW52RGV0OwogICAgICAgICAgaWYgKHUzIDwgMCB8fCB1MyA+IDEpIHsKICAgICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICAgIH0KICAgICAgICAgIHEgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3ModHZlYywgZWRnZTAsIHNjcmF0Y2hRVmVjKTsKICAgICAgICAgIHYzID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCBxKSAqIGludkRldDsKICAgICAgICAgIGlmICh2MyA8IDAgfHwgdTMgKyB2MyA+IDEpIHsKICAgICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICAgIH0KICAgICAgICAgIHQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KGVkZ2UxLCBxKSAqIGludkRldDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHQ7CiAgICAgIH07CiAgICAgIEludGVyc2VjdGlvblRlc3RzLnJheVRyaWFuZ2xlID0gZnVuY3Rpb24ocmF5LCBwMCwgcDEsIHAyLCBjdWxsQmFja0ZhY2VzLCByZXN1bHQpIHsKICAgICAgICBjb25zdCB0ID0gSW50ZXJzZWN0aW9uVGVzdHMucmF5VHJpYW5nbGVQYXJhbWV0cmljKAogICAgICAgICAgcmF5LAogICAgICAgICAgcDAsCiAgICAgICAgICBwMSwKICAgICAgICAgIHAyLAogICAgICAgICAgY3VsbEJhY2tGYWNlcwogICAgICAgICk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQodCkgfHwgdCA8IDApIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIocmF5LmRpcmVjdGlvbiwgdCwgcmVzdWx0KTsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuM19kZWZhdWx0LmFkZChyYXkub3JpZ2luLCByZXN1bHQsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hMaW5lU2VnbWVudFRyaWFuZ2xlUmF5ID0gbmV3IFJheV9kZWZhdWx0KCk7CiAgICAgIEludGVyc2VjdGlvblRlc3RzLmxpbmVTZWdtZW50VHJpYW5nbGUgPSBmdW5jdGlvbih2MDIsIHYxMiwgcDAsIHAxLCBwMiwgY3VsbEJhY2tGYWNlcywgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQodjAyKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInYwIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh2MTIpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgidjEgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHAwKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInAwIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwMSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJwMSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocDIpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicDIgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHJheSA9IHNjcmF0Y2hMaW5lU2VnbWVudFRyaWFuZ2xlUmF5OwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZSh2MDIsIHJheS5vcmlnaW4pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCh2MTIsIHYwMiwgcmF5LmRpcmVjdGlvbik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShyYXkuZGlyZWN0aW9uLCByYXkuZGlyZWN0aW9uKTsKICAgICAgICBjb25zdCB0ID0gSW50ZXJzZWN0aW9uVGVzdHMucmF5VHJpYW5nbGVQYXJhbWV0cmljKAogICAgICAgICAgcmF5LAogICAgICAgICAgcDAsCiAgICAgICAgICBwMSwKICAgICAgICAgIHAyLAogICAgICAgICAgY3VsbEJhY2tGYWNlcwogICAgICAgICk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQodCkgfHwgdCA8IDAgfHwgdCA+IENhcnRlc2lhbjNfZGVmYXVsdC5kaXN0YW5jZSh2MDIsIHYxMikpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIocmF5LmRpcmVjdGlvbiwgdCwgcmVzdWx0KTsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuM19kZWZhdWx0LmFkZChyYXkub3JpZ2luLCByZXN1bHQsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIHJheVNwaGVyZVJvb3RzID0gewogICAgICAgIHJvb3QwOiAwLAogICAgICAgIHJvb3QxOiAwCiAgICAgIH07CiAgICAgIEludGVyc2VjdGlvblRlc3RzLnJheVNwaGVyZSA9IGZ1bmN0aW9uKHJheSwgc3BoZXJlLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyYXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicmF5IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChzcGhlcmUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgic3BoZXJlIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICByZXN1bHQgPSByYXlTcGhlcmUocmF5LCBzcGhlcmUsIHJlc3VsdCk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSB8fCByZXN1bHQuc3RvcCA8IDApIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5zdGFydCA9IE1hdGgubWF4KHJlc3VsdC5zdGFydCwgMCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NyYXRjaExpbmVTZWdtZW50UmF5ID0gbmV3IFJheV9kZWZhdWx0KCk7CiAgICAgIEludGVyc2VjdGlvblRlc3RzLmxpbmVTZWdtZW50U3BoZXJlID0gZnVuY3Rpb24ocDAsIHAxLCBzcGhlcmUsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHAwKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInAwIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwMSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJwMSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoc3BoZXJlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInNwaGVyZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcmF5ID0gc2NyYXRjaExpbmVTZWdtZW50UmF5OwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShwMCwgcmF5Lm9yaWdpbik7CiAgICAgICAgY29uc3QgZGlyZWN0aW9uMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChwMSwgcDAsIHJheS5kaXJlY3Rpb24pOwogICAgICAgIGNvbnN0IG1heFQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKGRpcmVjdGlvbjIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoZGlyZWN0aW9uMiwgZGlyZWN0aW9uMik7CiAgICAgICAgcmVzdWx0ID0gcmF5U3BoZXJlKHJheSwgc3BoZXJlLCByZXN1bHQpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkgfHwgcmVzdWx0LnN0b3AgPCAwIHx8IHJlc3VsdC5zdGFydCA+IG1heFQpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5zdGFydCA9IE1hdGgubWF4KHJlc3VsdC5zdGFydCwgMCk7CiAgICAgICAgcmVzdWx0LnN0b3AgPSBNYXRoLm1pbihyZXN1bHQuc3RvcCwgbWF4VCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NyYXRjaFEgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hXID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBJbnRlcnNlY3Rpb25UZXN0cy5yYXlFbGxpcHNvaWQgPSBmdW5jdGlvbihyYXksIGVsbGlwc29pZCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJheSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJyYXkgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGVsbGlwc29pZCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJlbGxpcHNvaWQgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGludmVyc2VSYWRpaSA9IGVsbGlwc29pZC5vbmVPdmVyUmFkaWk7CiAgICAgICAgY29uc3QgcSA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUNvbXBvbmVudHMoaW52ZXJzZVJhZGlpLCByYXkub3JpZ2luLCBzY3JhdGNoUSk7CiAgICAgICAgY29uc3QgdyA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUNvbXBvbmVudHMoCiAgICAgICAgICBpbnZlcnNlUmFkaWksCiAgICAgICAgICByYXkuZGlyZWN0aW9uLAogICAgICAgICAgc2NyYXRjaFcKICAgICAgICApOwogICAgICAgIGNvbnN0IHEyMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGVTcXVhcmVkKHEpOwogICAgICAgIGNvbnN0IHF3ID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChxLCB3KTsKICAgICAgICBsZXQgZGlmZmVyZW5jZSwgdzIsIHByb2R1Y3QsIGRpc2NyaW1pbmFudCwgdGVtcDsKICAgICAgICBpZiAocTIyID4gMSkgewogICAgICAgICAgaWYgKHF3ID49IDApIHsKICAgICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHF3MiA9IHF3ICogcXc7CiAgICAgICAgICBkaWZmZXJlbmNlID0gcTIyIC0gMTsKICAgICAgICAgIHcyID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZVNxdWFyZWQodyk7CiAgICAgICAgICBwcm9kdWN0ID0gdzIgKiBkaWZmZXJlbmNlOwogICAgICAgICAgaWYgKHF3MiA8IHByb2R1Y3QpIHsKICAgICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICAgIH0gZWxzZSBpZiAocXcyID4gcHJvZHVjdCkgewogICAgICAgICAgICBkaXNjcmltaW5hbnQgPSBxdyAqIHF3IC0gcHJvZHVjdDsKICAgICAgICAgICAgdGVtcCA9IC1xdyArIE1hdGguc3FydChkaXNjcmltaW5hbnQpOwogICAgICAgICAgICBjb25zdCByb290MCA9IHRlbXAgLyB3MjsKICAgICAgICAgICAgY29uc3Qgcm9vdDEgPSBkaWZmZXJlbmNlIC8gdGVtcDsKICAgICAgICAgICAgaWYgKHJvb3QwIDwgcm9vdDEpIHsKICAgICAgICAgICAgICByZXR1cm4gbmV3IEludGVydmFsX2RlZmF1bHQocm9vdDAsIHJvb3QxKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgIHN0YXJ0OiByb290MSwKICAgICAgICAgICAgICBzdG9wOiByb290MAogICAgICAgICAgICB9OwogICAgICAgICAgfQogICAgICAgICAgY29uc3Qgcm9vdCA9IE1hdGguc3FydChkaWZmZXJlbmNlIC8gdzIpOwogICAgICAgICAgcmV0dXJuIG5ldyBJbnRlcnZhbF9kZWZhdWx0KHJvb3QsIHJvb3QpOwogICAgICAgIH0gZWxzZSBpZiAocTIyIDwgMSkgewogICAgICAgICAgZGlmZmVyZW5jZSA9IHEyMiAtIDE7CiAgICAgICAgICB3MiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGVTcXVhcmVkKHcpOwogICAgICAgICAgcHJvZHVjdCA9IHcyICogZGlmZmVyZW5jZTsKICAgICAgICAgIGRpc2NyaW1pbmFudCA9IHF3ICogcXcgLSBwcm9kdWN0OwogICAgICAgICAgdGVtcCA9IC1xdyArIE1hdGguc3FydChkaXNjcmltaW5hbnQpOwogICAgICAgICAgcmV0dXJuIG5ldyBJbnRlcnZhbF9kZWZhdWx0KDAsIHRlbXAgLyB3Mik7CiAgICAgICAgfQogICAgICAgIGlmIChxdyA8IDApIHsKICAgICAgICAgIHcyID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZVNxdWFyZWQodyk7CiAgICAgICAgICByZXR1cm4gbmV3IEludGVydmFsX2RlZmF1bHQoMCwgLXF3IC8gdzIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICB9OwogICAgICBJbnRlcnNlY3Rpb25UZXN0cy5xdWFkcmF0aWNWZWN0b3JFeHByZXNzaW9uID0gZnVuY3Rpb24oQSwgYiwgYywgeCwgdykgewogICAgICAgIGNvbnN0IHhTcXVhcmVkID0geCAqIHg7CiAgICAgICAgY29uc3Qgd1NxdWFyZWQgPSB3ICogdzsKICAgICAgICBjb25zdCBsMiA9IChBW01hdHJpeDNfZGVmYXVsdC5DT0xVTU4xUk9XMV0gLSBBW01hdHJpeDNfZGVmYXVsdC5DT0xVTU4yUk9XMl0pICogd1NxdWFyZWQ7CiAgICAgICAgY29uc3QgbDEgPSB3ICogKHggKiBhZGRXaXRoQ2FuY2VsbGF0aW9uQ2hlY2syKAogICAgICAgICAgQVtNYXRyaXgzX2RlZmF1bHQuQ09MVU1OMVJPVzBdLAogICAgICAgICAgQVtNYXRyaXgzX2RlZmF1bHQuQ09MVU1OMFJPVzFdLAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xNQogICAgICAgICkgKyBiLnkpOwogICAgICAgIGNvbnN0IGwwID0gQVtNYXRyaXgzX2RlZmF1bHQuQ09MVU1OMFJPVzBdICogeFNxdWFyZWQgKyBBW01hdHJpeDNfZGVmYXVsdC5DT0xVTU4yUk9XMl0gKiB3U3F1YXJlZCArIHggKiBiLnggKyBjOwogICAgICAgIGNvbnN0IHIxID0gd1NxdWFyZWQgKiBhZGRXaXRoQ2FuY2VsbGF0aW9uQ2hlY2syKAogICAgICAgICAgQVtNYXRyaXgzX2RlZmF1bHQuQ09MVU1OMlJPVzFdLAogICAgICAgICAgQVtNYXRyaXgzX2RlZmF1bHQuQ09MVU1OMVJPVzJdLAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xNQogICAgICAgICk7CiAgICAgICAgY29uc3QgcjAgPSB3ICogKHggKiBhZGRXaXRoQ2FuY2VsbGF0aW9uQ2hlY2syKEFbTWF0cml4M19kZWZhdWx0LkNPTFVNTjJST1cwXSwgQVtNYXRyaXgzX2RlZmF1bHQuQ09MVU1OMFJPVzJdKSArIGIueik7CiAgICAgICAgbGV0IGNvc2luZXM7CiAgICAgICAgY29uc3Qgc29sdXRpb25zID0gW107CiAgICAgICAgaWYgKHIwID09PSAwICYmIHIxID09PSAwKSB7CiAgICAgICAgICBjb3NpbmVzID0gUXVhZHJhdGljUmVhbFBvbHlub21pYWxfZGVmYXVsdC5jb21wdXRlUmVhbFJvb3RzKGwyLCBsMSwgbDApOwogICAgICAgICAgaWYgKGNvc2luZXMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgIHJldHVybiBzb2x1dGlvbnM7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBjb3NpbmUwID0gY29zaW5lc1swXTsKICAgICAgICAgIGNvbnN0IHNpbmUwID0gTWF0aC5zcXJ0KE1hdGgubWF4KDEgLSBjb3NpbmUwICogY29zaW5lMCwgMCkpOwogICAgICAgICAgc29sdXRpb25zLnB1c2gobmV3IENhcnRlc2lhbjNfZGVmYXVsdCh4LCB3ICogY29zaW5lMCwgdyAqIC1zaW5lMCkpOwogICAgICAgICAgc29sdXRpb25zLnB1c2gobmV3IENhcnRlc2lhbjNfZGVmYXVsdCh4LCB3ICogY29zaW5lMCwgdyAqIHNpbmUwKSk7CiAgICAgICAgICBpZiAoY29zaW5lcy5sZW5ndGggPT09IDIpIHsKICAgICAgICAgICAgY29uc3QgY29zaW5lMSA9IGNvc2luZXNbMV07CiAgICAgICAgICAgIGNvbnN0IHNpbmUxID0gTWF0aC5zcXJ0KE1hdGgubWF4KDEgLSBjb3NpbmUxICogY29zaW5lMSwgMCkpOwogICAgICAgICAgICBzb2x1dGlvbnMucHVzaChuZXcgQ2FydGVzaWFuM19kZWZhdWx0KHgsIHcgKiBjb3NpbmUxLCB3ICogLXNpbmUxKSk7CiAgICAgICAgICAgIHNvbHV0aW9ucy5wdXNoKG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoeCwgdyAqIGNvc2luZTEsIHcgKiBzaW5lMSkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHNvbHV0aW9uczsKICAgICAgICB9CiAgICAgICAgY29uc3QgcjBTcXVhcmVkID0gcjAgKiByMDsKICAgICAgICBjb25zdCByMVNxdWFyZWQgPSByMSAqIHIxOwogICAgICAgIGNvbnN0IGwyU3F1YXJlZCA9IGwyICogbDI7CiAgICAgICAgY29uc3QgcjByMSA9IHIwICogcjE7CiAgICAgICAgY29uc3QgYzQgPSBsMlNxdWFyZWQgKyByMVNxdWFyZWQ7CiAgICAgICAgY29uc3QgYzMyID0gMiAqIChsMSAqIGwyICsgcjByMSk7CiAgICAgICAgY29uc3QgYzIgPSAyICogbDAgKiBsMiArIGwxICogbDEgLSByMVNxdWFyZWQgKyByMFNxdWFyZWQ7CiAgICAgICAgY29uc3QgYzEgPSAyICogKGwwICogbDEgLSByMHIxKTsKICAgICAgICBjb25zdCBjMCA9IGwwICogbDAgLSByMFNxdWFyZWQ7CiAgICAgICAgaWYgKGM0ID09PSAwICYmIGMzMiA9PT0gMCAmJiBjMiA9PT0gMCAmJiBjMSA9PT0gMCkgewogICAgICAgICAgcmV0dXJuIHNvbHV0aW9uczsKICAgICAgICB9CiAgICAgICAgY29zaW5lcyA9IFF1YXJ0aWNSZWFsUG9seW5vbWlhbF9kZWZhdWx0LmNvbXB1dGVSZWFsUm9vdHMoYzQsIGMzMiwgYzIsIGMxLCBjMCk7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gY29zaW5lcy5sZW5ndGg7CiAgICAgICAgaWYgKGxlbmd0aCA9PT0gMCkgewogICAgICAgICAgcmV0dXJuIHNvbHV0aW9uczsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgY29uc3QgY29zaW5lID0gY29zaW5lc1tpXTsKICAgICAgICAgIGNvbnN0IGNvc2luZVNxdWFyZWQgPSBjb3NpbmUgKiBjb3NpbmU7CiAgICAgICAgICBjb25zdCBzaW5lU3F1YXJlZCA9IE1hdGgubWF4KDEgLSBjb3NpbmVTcXVhcmVkLCAwKTsKICAgICAgICAgIGNvbnN0IHNpbmUgPSBNYXRoLnNxcnQoc2luZVNxdWFyZWQpOwogICAgICAgICAgbGV0IGxlZnQ7CiAgICAgICAgICBpZiAoTWF0aF9kZWZhdWx0LnNpZ24obDIpID09PSBNYXRoX2RlZmF1bHQuc2lnbihsMCkpIHsKICAgICAgICAgICAgbGVmdCA9IGFkZFdpdGhDYW5jZWxsYXRpb25DaGVjazIoCiAgICAgICAgICAgICAgbDIgKiBjb3NpbmVTcXVhcmVkICsgbDAsCiAgICAgICAgICAgICAgbDEgKiBjb3NpbmUsCiAgICAgICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xMgogICAgICAgICAgICApOwogICAgICAgICAgfSBlbHNlIGlmIChNYXRoX2RlZmF1bHQuc2lnbihsMCkgPT09IE1hdGhfZGVmYXVsdC5zaWduKGwxICogY29zaW5lKSkgewogICAgICAgICAgICBsZWZ0ID0gYWRkV2l0aENhbmNlbGxhdGlvbkNoZWNrMigKICAgICAgICAgICAgICBsMiAqIGNvc2luZVNxdWFyZWQsCiAgICAgICAgICAgICAgbDEgKiBjb3NpbmUgKyBsMCwKICAgICAgICAgICAgICBNYXRoX2RlZmF1bHQuRVBTSUxPTjEyCiAgICAgICAgICAgICk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBsZWZ0ID0gYWRkV2l0aENhbmNlbGxhdGlvbkNoZWNrMigKICAgICAgICAgICAgICBsMiAqIGNvc2luZVNxdWFyZWQgKyBsMSAqIGNvc2luZSwKICAgICAgICAgICAgICBsMCwKICAgICAgICAgICAgICBNYXRoX2RlZmF1bHQuRVBTSUxPTjEyCiAgICAgICAgICAgICk7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCByaWdodCA9IGFkZFdpdGhDYW5jZWxsYXRpb25DaGVjazIoCiAgICAgICAgICAgIHIxICogY29zaW5lLAogICAgICAgICAgICByMCwKICAgICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xNQogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IHByb2R1Y3QgPSBsZWZ0ICogcmlnaHQ7CiAgICAgICAgICBpZiAocHJvZHVjdCA8IDApIHsKICAgICAgICAgICAgc29sdXRpb25zLnB1c2gobmV3IENhcnRlc2lhbjNfZGVmYXVsdCh4LCB3ICogY29zaW5lLCB3ICogc2luZSkpOwogICAgICAgICAgfSBlbHNlIGlmIChwcm9kdWN0ID4gMCkgewogICAgICAgICAgICBzb2x1dGlvbnMucHVzaChuZXcgQ2FydGVzaWFuM19kZWZhdWx0KHgsIHcgKiBjb3NpbmUsIHcgKiAtc2luZSkpOwogICAgICAgICAgfSBlbHNlIGlmIChzaW5lICE9PSAwKSB7CiAgICAgICAgICAgIHNvbHV0aW9ucy5wdXNoKG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoeCwgdyAqIGNvc2luZSwgdyAqIC1zaW5lKSk7CiAgICAgICAgICAgIHNvbHV0aW9ucy5wdXNoKG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoeCwgdyAqIGNvc2luZSwgdyAqIHNpbmUpKTsKICAgICAgICAgICAgKytpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc29sdXRpb25zLnB1c2gobmV3IENhcnRlc2lhbjNfZGVmYXVsdCh4LCB3ICogY29zaW5lLCB3ICogc2luZSkpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gc29sdXRpb25zOwogICAgICB9OwogICAgICBmaXJzdEF4aXNTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzZWNvbmRBeGlzU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgdGhpcmRBeGlzU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgcmVmZXJlbmNlU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgYkNhcnQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGJTY3JhdGNoID0gbmV3IE1hdHJpeDNfZGVmYXVsdCgpOwogICAgICBidFNjcmF0Y2ggPSBuZXcgTWF0cml4M19kZWZhdWx0KCk7CiAgICAgIGRpU2NyYXRjaCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgZFNjcmF0Y2ggPSBuZXcgTWF0cml4M19kZWZhdWx0KCk7CiAgICAgIGNTY3JhdGNoID0gbmV3IE1hdHJpeDNfZGVmYXVsdCgpOwogICAgICB0ZW1wTWF0cml4ID0gbmV3IE1hdHJpeDNfZGVmYXVsdCgpOwogICAgICBhU2NyYXRjaCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgc1NjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNsb3Nlc3RTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzdXJmUG9pbnRTY3JhdGNoID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIEludGVyc2VjdGlvblRlc3RzLmdyYXppbmdBbHRpdHVkZUxvY2F0aW9uID0gZnVuY3Rpb24ocmF5LCBlbGxpcHNvaWQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyYXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicmF5IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChlbGxpcHNvaWQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZWxsaXBzb2lkIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBwb3NpdGlvbiA9IHJheS5vcmlnaW47CiAgICAgICAgY29uc3QgZGlyZWN0aW9uMiA9IHJheS5kaXJlY3Rpb247CiAgICAgICAgaWYgKCFDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzKHBvc2l0aW9uLCBDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTykpIHsKICAgICAgICAgIGNvbnN0IG5vcm1hbDIgPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKHBvc2l0aW9uLCBmaXJzdEF4aXNTY3JhdGNoKTsKICAgICAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KGRpcmVjdGlvbjIsIG5vcm1hbDIpID49IDApIHsKICAgICAgICAgICAgcmV0dXJuIHBvc2l0aW9uOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBpbnRlcnNlY3RzMiA9IGRlZmluZWRfZGVmYXVsdCh0aGlzLnJheUVsbGlwc29pZChyYXksIGVsbGlwc29pZCkpOwogICAgICAgIGNvbnN0IGYgPSBlbGxpcHNvaWQudHJhbnNmb3JtUG9zaXRpb25Ub1NjYWxlZFNwYWNlKAogICAgICAgICAgZGlyZWN0aW9uMiwKICAgICAgICAgIGZpcnN0QXhpc1NjcmF0Y2gKICAgICAgICApOwogICAgICAgIGNvbnN0IGZpcnN0QXhpcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoZiwgZik7CiAgICAgICAgY29uc3QgcmVmZXJlbmNlID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1vc3RPcnRob2dvbmFsQXhpcyhmLCByZWZlcmVuY2VTY3JhdGNoKTsKICAgICAgICBjb25zdCBzZWNvbmRBeGlzID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhyZWZlcmVuY2UsIGZpcnN0QXhpcywgc2Vjb25kQXhpc1NjcmF0Y2gpLAogICAgICAgICAgc2Vjb25kQXhpc1NjcmF0Y2gKICAgICAgICApOwogICAgICAgIGNvbnN0IHRoaXJkQXhpcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoZmlyc3RBeGlzLCBzZWNvbmRBeGlzLCB0aGlyZEF4aXNTY3JhdGNoKSwKICAgICAgICAgIHRoaXJkQXhpc1NjcmF0Y2gKICAgICAgICApOwogICAgICAgIGNvbnN0IEIgPSBiU2NyYXRjaDsKICAgICAgICBCWzBdID0gZmlyc3RBeGlzLng7CiAgICAgICAgQlsxXSA9IGZpcnN0QXhpcy55OwogICAgICAgIEJbMl0gPSBmaXJzdEF4aXMuejsKICAgICAgICBCWzNdID0gc2Vjb25kQXhpcy54OwogICAgICAgIEJbNF0gPSBzZWNvbmRBeGlzLnk7CiAgICAgICAgQls1XSA9IHNlY29uZEF4aXMuejsKICAgICAgICBCWzZdID0gdGhpcmRBeGlzLng7CiAgICAgICAgQls3XSA9IHRoaXJkQXhpcy55OwogICAgICAgIEJbOF0gPSB0aGlyZEF4aXMuejsKICAgICAgICBjb25zdCBCX1QgPSBNYXRyaXgzX2RlZmF1bHQudHJhbnNwb3NlKEIsIGJ0U2NyYXRjaCk7CiAgICAgICAgY29uc3QgRF9JID0gTWF0cml4M19kZWZhdWx0LmZyb21TY2FsZShlbGxpcHNvaWQucmFkaWksIGRpU2NyYXRjaCk7CiAgICAgICAgY29uc3QgRCA9IE1hdHJpeDNfZGVmYXVsdC5mcm9tU2NhbGUoZWxsaXBzb2lkLm9uZU92ZXJSYWRpaSwgZFNjcmF0Y2gpOwogICAgICAgIGNvbnN0IEMgPSBjU2NyYXRjaDsKICAgICAgICBDWzBdID0gMDsKICAgICAgICBDWzFdID0gLWRpcmVjdGlvbjIuejsKICAgICAgICBDWzJdID0gZGlyZWN0aW9uMi55OwogICAgICAgIENbM10gPSBkaXJlY3Rpb24yLno7CiAgICAgICAgQ1s0XSA9IDA7CiAgICAgICAgQ1s1XSA9IC1kaXJlY3Rpb24yLng7CiAgICAgICAgQ1s2XSA9IC1kaXJlY3Rpb24yLnk7CiAgICAgICAgQ1s3XSA9IGRpcmVjdGlvbjIueDsKICAgICAgICBDWzhdID0gMDsKICAgICAgICBjb25zdCB0ZW1wID0gTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5KAogICAgICAgICAgTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5KEJfVCwgRCwgdGVtcE1hdHJpeCksCiAgICAgICAgICBDLAogICAgICAgICAgdGVtcE1hdHJpeAogICAgICAgICk7CiAgICAgICAgY29uc3QgQSA9IE1hdHJpeDNfZGVmYXVsdC5tdWx0aXBseSgKICAgICAgICAgIE1hdHJpeDNfZGVmYXVsdC5tdWx0aXBseSh0ZW1wLCBEX0ksIGFTY3JhdGNoKSwKICAgICAgICAgIEIsCiAgICAgICAgICBhU2NyYXRjaAogICAgICAgICk7CiAgICAgICAgY29uc3QgYiA9IE1hdHJpeDNfZGVmYXVsdC5tdWx0aXBseUJ5VmVjdG9yKHRlbXAsIHBvc2l0aW9uLCBiQ2FydCk7CiAgICAgICAgY29uc3Qgc29sdXRpb25zID0gSW50ZXJzZWN0aW9uVGVzdHMucXVhZHJhdGljVmVjdG9yRXhwcmVzc2lvbigKICAgICAgICAgIEEsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKGIsIGZpcnN0QXhpc1NjcmF0Y2gpLAogICAgICAgICAgMCwKICAgICAgICAgIDAsCiAgICAgICAgICAxCiAgICAgICAgKTsKICAgICAgICBsZXQgczsKICAgICAgICBsZXQgYWx0aXR1ZGU7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gc29sdXRpb25zLmxlbmd0aDsKICAgICAgICBpZiAobGVuZ3RoID4gMCkgewogICAgICAgICAgbGV0IGNsb3Nlc3QgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sIGNsb3Nlc3RTY3JhdGNoKTsKICAgICAgICAgIGxldCBtYXhpbXVtVmFsdWUgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgIHMgPSBNYXRyaXgzX2RlZmF1bHQubXVsdGlwbHlCeVZlY3RvcigKICAgICAgICAgICAgICBEX0ksCiAgICAgICAgICAgICAgTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3IoQiwgc29sdXRpb25zW2ldLCBzU2NyYXRjaCksCiAgICAgICAgICAgICAgc1NjcmF0Y2gKICAgICAgICAgICAgKTsKICAgICAgICAgICAgY29uc3QgdjMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChzLCBwb3NpdGlvbiwgcmVmZXJlbmNlU2NyYXRjaCksCiAgICAgICAgICAgICAgcmVmZXJlbmNlU2NyYXRjaAogICAgICAgICAgICApOwogICAgICAgICAgICBjb25zdCBkb3RQcm9kdWN0ID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdCh2MywgZGlyZWN0aW9uMik7CiAgICAgICAgICAgIGlmIChkb3RQcm9kdWN0ID4gbWF4aW11bVZhbHVlKSB7CiAgICAgICAgICAgICAgbWF4aW11bVZhbHVlID0gZG90UHJvZHVjdDsKICAgICAgICAgICAgICBjbG9zZXN0ID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHMsIGNsb3Nlc3QpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBzdXJmYWNlUG9pbnQgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMoCiAgICAgICAgICAgIGNsb3Nlc3QsCiAgICAgICAgICAgIHN1cmZQb2ludFNjcmF0Y2gKICAgICAgICAgICk7CiAgICAgICAgICBtYXhpbXVtVmFsdWUgPSBNYXRoX2RlZmF1bHQuY2xhbXAobWF4aW11bVZhbHVlLCAwLCAxKTsKICAgICAgICAgIGFsdGl0dWRlID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZSgKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGNsb3Nlc3QsIHBvc2l0aW9uLCByZWZlcmVuY2VTY3JhdGNoKQogICAgICAgICAgKSAqIE1hdGguc3FydCgxIC0gbWF4aW11bVZhbHVlICogbWF4aW11bVZhbHVlKTsKICAgICAgICAgIGFsdGl0dWRlID0gaW50ZXJzZWN0czIgPyAtYWx0aXR1ZGUgOiBhbHRpdHVkZTsKICAgICAgICAgIHN1cmZhY2VQb2ludC5oZWlnaHQgPSBhbHRpdHVkZTsKICAgICAgICAgIHJldHVybiBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oc3VyZmFjZVBvaW50LCBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICB9OwogICAgICBsaW5lU2VnbWVudFBsYW5lRGlmZmVyZW5jZSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgSW50ZXJzZWN0aW9uVGVzdHMubGluZVNlZ21lbnRQbGFuZSA9IGZ1bmN0aW9uKGVuZFBvaW50MCwgZW5kUG9pbnQxLCBwbGFuZSwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZW5kUG9pbnQwKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImVuZFBvaW50MCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZW5kUG9pbnQxKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImVuZFBvaW50MSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocGxhbmUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicGxhbmUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZGlmZmVyZW5jZSA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgICAgIGVuZFBvaW50MSwKICAgICAgICAgIGVuZFBvaW50MCwKICAgICAgICAgIGxpbmVTZWdtZW50UGxhbmVEaWZmZXJlbmNlCiAgICAgICAgKTsKICAgICAgICBjb25zdCBub3JtYWwyID0gcGxhbmUubm9ybWFsOwogICAgICAgIGNvbnN0IG5Eb3REaWZmID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChub3JtYWwyLCBkaWZmZXJlbmNlKTsKICAgICAgICBpZiAoTWF0aC5hYnMobkRvdERpZmYpIDwgTWF0aF9kZWZhdWx0LkVQU0lMT042KSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBjb25zdCBuRG90UDAgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KG5vcm1hbDIsIGVuZFBvaW50MCk7CiAgICAgICAgY29uc3QgdCA9IC0ocGxhbmUuZGlzdGFuY2UgKyBuRG90UDApIC8gbkRvdERpZmY7CiAgICAgICAgaWYgKHQgPCAwIHx8IHQgPiAxKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihkaWZmZXJlbmNlLCB0LCByZXN1bHQpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoZW5kUG9pbnQwLCByZXN1bHQsIHJlc3VsdCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgSW50ZXJzZWN0aW9uVGVzdHMudHJpYW5nbGVQbGFuZUludGVyc2VjdGlvbiA9IGZ1bmN0aW9uKHAwLCBwMSwgcDIsIHBsYW5lKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocDApIHx8ICFkZWZpbmVkX2RlZmF1bHQocDEpIHx8ICFkZWZpbmVkX2RlZmF1bHQocDIpIHx8ICFkZWZpbmVkX2RlZmF1bHQocGxhbmUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicDAsIHAxLCBwMiwgYW5kIHBsYW5lIGFyZSByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcGxhbmVOb3JtYWwgPSBwbGFuZS5ub3JtYWw7CiAgICAgICAgY29uc3QgcGxhbmVEID0gcGxhbmUuZGlzdGFuY2U7CiAgICAgICAgY29uc3QgcDBCZWhpbmQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHBsYW5lTm9ybWFsLCBwMCkgKyBwbGFuZUQgPCAwOwogICAgICAgIGNvbnN0IHAxQmVoaW5kID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChwbGFuZU5vcm1hbCwgcDEpICsgcGxhbmVEIDwgMDsKICAgICAgICBjb25zdCBwMkJlaGluZCA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QocGxhbmVOb3JtYWwsIHAyKSArIHBsYW5lRCA8IDA7CiAgICAgICAgbGV0IG51bUJlaGluZCA9IDA7CiAgICAgICAgbnVtQmVoaW5kICs9IHAwQmVoaW5kID8gMSA6IDA7CiAgICAgICAgbnVtQmVoaW5kICs9IHAxQmVoaW5kID8gMSA6IDA7CiAgICAgICAgbnVtQmVoaW5kICs9IHAyQmVoaW5kID8gMSA6IDA7CiAgICAgICAgbGV0IHUxMiwgdTIyOwogICAgICAgIGlmIChudW1CZWhpbmQgPT09IDEgfHwgbnVtQmVoaW5kID09PSAyKSB7CiAgICAgICAgICB1MTIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgICAgICB1MjIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIGlmIChudW1CZWhpbmQgPT09IDEpIHsKICAgICAgICAgIGlmIChwMEJlaGluZCkgewogICAgICAgICAgICBJbnRlcnNlY3Rpb25UZXN0cy5saW5lU2VnbWVudFBsYW5lKHAwLCBwMSwgcGxhbmUsIHUxMik7CiAgICAgICAgICAgIEludGVyc2VjdGlvblRlc3RzLmxpbmVTZWdtZW50UGxhbmUocDAsIHAyLCBwbGFuZSwgdTIyKTsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICBwb3NpdGlvbnM6IFtwMCwgcDEsIHAyLCB1MTIsIHUyMl0sCiAgICAgICAgICAgICAgaW5kaWNlczogWwogICAgICAgICAgICAgICAgLy8gQmVoaW5kCiAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgMywKICAgICAgICAgICAgICAgIDQsCiAgICAgICAgICAgICAgICAvLyBJbiBmcm9udAogICAgICAgICAgICAgICAgMSwKICAgICAgICAgICAgICAgIDIsCiAgICAgICAgICAgICAgICA0LAogICAgICAgICAgICAgICAgMSwKICAgICAgICAgICAgICAgIDQsCiAgICAgICAgICAgICAgICAzCiAgICAgICAgICAgICAgXQogICAgICAgICAgICB9OwogICAgICAgICAgfSBlbHNlIGlmIChwMUJlaGluZCkgewogICAgICAgICAgICBJbnRlcnNlY3Rpb25UZXN0cy5saW5lU2VnbWVudFBsYW5lKHAxLCBwMiwgcGxhbmUsIHUxMik7CiAgICAgICAgICAgIEludGVyc2VjdGlvblRlc3RzLmxpbmVTZWdtZW50UGxhbmUocDEsIHAwLCBwbGFuZSwgdTIyKTsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICBwb3NpdGlvbnM6IFtwMCwgcDEsIHAyLCB1MTIsIHUyMl0sCiAgICAgICAgICAgICAgaW5kaWNlczogWwogICAgICAgICAgICAgICAgLy8gQmVoaW5kCiAgICAgICAgICAgICAgICAxLAogICAgICAgICAgICAgICAgMywKICAgICAgICAgICAgICAgIDQsCiAgICAgICAgICAgICAgICAvLyBJbiBmcm9udAogICAgICAgICAgICAgICAgMiwKICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICA0LAogICAgICAgICAgICAgICAgMiwKICAgICAgICAgICAgICAgIDQsCiAgICAgICAgICAgICAgICAzCiAgICAgICAgICAgICAgXQogICAgICAgICAgICB9OwogICAgICAgICAgfSBlbHNlIGlmIChwMkJlaGluZCkgewogICAgICAgICAgICBJbnRlcnNlY3Rpb25UZXN0cy5saW5lU2VnbWVudFBsYW5lKHAyLCBwMCwgcGxhbmUsIHUxMik7CiAgICAgICAgICAgIEludGVyc2VjdGlvblRlc3RzLmxpbmVTZWdtZW50UGxhbmUocDIsIHAxLCBwbGFuZSwgdTIyKTsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICBwb3NpdGlvbnM6IFtwMCwgcDEsIHAyLCB1MTIsIHUyMl0sCiAgICAgICAgICAgICAgaW5kaWNlczogWwogICAgICAgICAgICAgICAgLy8gQmVoaW5kCiAgICAgICAgICAgICAgICAyLAogICAgICAgICAgICAgICAgMywKICAgICAgICAgICAgICAgIDQsCiAgICAgICAgICAgICAgICAvLyBJbiBmcm9udAogICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICA0LAogICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgIDQsCiAgICAgICAgICAgICAgICAzCiAgICAgICAgICAgICAgXQogICAgICAgICAgICB9OwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAobnVtQmVoaW5kID09PSAyKSB7CiAgICAgICAgICBpZiAoIXAwQmVoaW5kKSB7CiAgICAgICAgICAgIEludGVyc2VjdGlvblRlc3RzLmxpbmVTZWdtZW50UGxhbmUocDEsIHAwLCBwbGFuZSwgdTEyKTsKICAgICAgICAgICAgSW50ZXJzZWN0aW9uVGVzdHMubGluZVNlZ21lbnRQbGFuZShwMiwgcDAsIHBsYW5lLCB1MjIpOwogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgIHBvc2l0aW9uczogW3AwLCBwMSwgcDIsIHUxMiwgdTIyXSwKICAgICAgICAgICAgICBpbmRpY2VzOiBbCiAgICAgICAgICAgICAgICAvLyBCZWhpbmQKICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAyLAogICAgICAgICAgICAgICAgNCwKICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICA0LAogICAgICAgICAgICAgICAgMywKICAgICAgICAgICAgICAgIC8vIEluIGZyb250CiAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgMywKICAgICAgICAgICAgICAgIDQKICAgICAgICAgICAgICBdCiAgICAgICAgICAgIH07CiAgICAgICAgICB9IGVsc2UgaWYgKCFwMUJlaGluZCkgewogICAgICAgICAgICBJbnRlcnNlY3Rpb25UZXN0cy5saW5lU2VnbWVudFBsYW5lKHAyLCBwMSwgcGxhbmUsIHUxMik7CiAgICAgICAgICAgIEludGVyc2VjdGlvblRlc3RzLmxpbmVTZWdtZW50UGxhbmUocDAsIHAxLCBwbGFuZSwgdTIyKTsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICBwb3NpdGlvbnM6IFtwMCwgcDEsIHAyLCB1MTIsIHUyMl0sCiAgICAgICAgICAgICAgaW5kaWNlczogWwogICAgICAgICAgICAgICAgLy8gQmVoaW5kCiAgICAgICAgICAgICAgICAyLAogICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgIDQsCiAgICAgICAgICAgICAgICAyLAogICAgICAgICAgICAgICAgNCwKICAgICAgICAgICAgICAgIDMsCiAgICAgICAgICAgICAgICAvLyBJbiBmcm9udAogICAgICAgICAgICAgICAgMSwKICAgICAgICAgICAgICAgIDMsCiAgICAgICAgICAgICAgICA0CiAgICAgICAgICAgICAgXQogICAgICAgICAgICB9OwogICAgICAgICAgfSBlbHNlIGlmICghcDJCZWhpbmQpIHsKICAgICAgICAgICAgSW50ZXJzZWN0aW9uVGVzdHMubGluZVNlZ21lbnRQbGFuZShwMCwgcDIsIHBsYW5lLCB1MTIpOwogICAgICAgICAgICBJbnRlcnNlY3Rpb25UZXN0cy5saW5lU2VnbWVudFBsYW5lKHAxLCBwMiwgcGxhbmUsIHUyMik7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgcG9zaXRpb25zOiBbcDAsIHAxLCBwMiwgdTEyLCB1MjJdLAogICAgICAgICAgICAgIGluZGljZXM6IFsKICAgICAgICAgICAgICAgIC8vIEJlaGluZAogICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICA0LAogICAgICAgICAgICAgICAgMCwKICAgICAgICAgICAgICAgIDQsCiAgICAgICAgICAgICAgICAzLAogICAgICAgICAgICAgICAgLy8gSW4gZnJvbnQKICAgICAgICAgICAgICAgIDIsCiAgICAgICAgICAgICAgICAzLAogICAgICAgICAgICAgICAgNAogICAgICAgICAgICAgIF0KICAgICAgICAgICAgfTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgfTsKICAgICAgSW50ZXJzZWN0aW9uVGVzdHNfZGVmYXVsdCA9IEludGVyc2VjdGlvblRlc3RzOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUGxhbmUuanMKICBmdW5jdGlvbiBQbGFuZShub3JtYWwyLCBkaXN0YW5jZSkgewogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJub3JtYWwiLCBub3JtYWwyKTsKICAgIGlmICghTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUobm9ybWFsMiksCiAgICAgIDEsCiAgICAgIE1hdGhfZGVmYXVsdC5FUFNJTE9ONgogICAgKSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgibm9ybWFsIG11c3QgYmUgbm9ybWFsaXplZC4iKTsKICAgIH0KICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigiZGlzdGFuY2UiLCBkaXN0YW5jZSk7CiAgICB0aGlzLm5vcm1hbCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShub3JtYWwyKTsKICAgIHRoaXMuZGlzdGFuY2UgPSBkaXN0YW5jZTsKICB9CiAgdmFyIHNjcmF0Y2hOb3JtYWwsIHNjcmF0Y2hDYXJ0ZXNpYW4sIHNjcmF0Y2hJbnZlcnNlVHJhbnNwb3NlLCBzY3JhdGNoUGxhbmVDYXJ0ZXNpYW40LCBzY3JhdGNoVHJhbnNmb3JtTm9ybWFsLCBQbGFuZV9kZWZhdWx0OwogIHZhciBpbml0X1BsYW5lID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9QbGFuZS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRlc2lhbjQoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9NYXRyaXg0KCk7CiAgICAgIFBsYW5lLmZyb21Qb2ludE5vcm1hbCA9IGZ1bmN0aW9uKHBvaW50LCBub3JtYWwyLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInBvaW50IiwgcG9pbnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibm9ybWFsIiwgbm9ybWFsMik7CiAgICAgICAgaWYgKCFNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUobm9ybWFsMiksCiAgICAgICAgICAxLAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT042CiAgICAgICAgKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm5vcm1hbCBtdXN0IGJlIG5vcm1hbGl6ZWQuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGRpc3RhbmNlID0gLUNhcnRlc2lhbjNfZGVmYXVsdC5kb3Qobm9ybWFsMiwgcG9pbnQpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgUGxhbmUobm9ybWFsMiwgZGlzdGFuY2UpOwogICAgICAgIH0KICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUobm9ybWFsMiwgcmVzdWx0Lm5vcm1hbCk7CiAgICAgICAgcmVzdWx0LmRpc3RhbmNlID0gZGlzdGFuY2U7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NyYXRjaE5vcm1hbCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgUGxhbmUuZnJvbUNhcnRlc2lhbjQgPSBmdW5jdGlvbihjb2VmZmljaWVudHMsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiY29lZmZpY2llbnRzIiwgY29lZmZpY2llbnRzKTsKICAgICAgICBjb25zdCBub3JtYWwyID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21DYXJ0ZXNpYW40KGNvZWZmaWNpZW50cywgc2NyYXRjaE5vcm1hbCk7CiAgICAgICAgY29uc3QgZGlzdGFuY2UgPSBjb2VmZmljaWVudHMudzsKICAgICAgICBpZiAoIU1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZShub3JtYWwyKSwKICAgICAgICAgIDEsCiAgICAgICAgICBNYXRoX2RlZmF1bHQuRVBTSUxPTjYKICAgICAgICApKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgibm9ybWFsIG11c3QgYmUgbm9ybWFsaXplZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBQbGFuZShub3JtYWwyLCBkaXN0YW5jZSk7CiAgICAgICAgfQogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShub3JtYWwyLCByZXN1bHQubm9ybWFsKTsKICAgICAgICByZXN1bHQuZGlzdGFuY2UgPSBkaXN0YW5jZTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBQbGFuZS5nZXRQb2ludERpc3RhbmNlID0gZnVuY3Rpb24ocGxhbmUsIHBvaW50KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJwbGFuZSIsIHBsYW5lKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInBvaW50IiwgcG9pbnQpOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHBsYW5lLm5vcm1hbCwgcG9pbnQpICsgcGxhbmUuZGlzdGFuY2U7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIFBsYW5lLnByb2plY3RQb2ludE9udG9QbGFuZSA9IGZ1bmN0aW9uKHBsYW5lLCBwb2ludCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJwbGFuZSIsIHBsYW5lKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInBvaW50IiwgcG9pbnQpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcG9pbnREaXN0YW5jZSA9IFBsYW5lLmdldFBvaW50RGlzdGFuY2UocGxhbmUsIHBvaW50KTsKICAgICAgICBjb25zdCBzY2FsZWROb3JtYWwgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICAgIHBsYW5lLm5vcm1hbCwKICAgICAgICAgIHBvaW50RGlzdGFuY2UsCiAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHBvaW50LCBzY2FsZWROb3JtYWwsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hJbnZlcnNlVHJhbnNwb3NlID0gbmV3IE1hdHJpeDRfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGxhbmVDYXJ0ZXNpYW40ID0gbmV3IENhcnRlc2lhbjRfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoVHJhbnNmb3JtTm9ybWFsID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBQbGFuZS50cmFuc2Zvcm0gPSBmdW5jdGlvbihwbGFuZSwgdHJhbnNmb3JtMiwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJwbGFuZSIsIHBsYW5lKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInRyYW5zZm9ybSIsIHRyYW5zZm9ybTIpOwogICAgICAgIGNvbnN0IG5vcm1hbDIgPSBwbGFuZS5ub3JtYWw7CiAgICAgICAgY29uc3QgZGlzdGFuY2UgPSBwbGFuZS5kaXN0YW5jZTsKICAgICAgICBjb25zdCBpbnZlcnNlVHJhbnNwb3NlMiA9IE1hdHJpeDRfZGVmYXVsdC5pbnZlcnNlVHJhbnNwb3NlKAogICAgICAgICAgdHJhbnNmb3JtMiwKICAgICAgICAgIHNjcmF0Y2hJbnZlcnNlVHJhbnNwb3NlCiAgICAgICAgKTsKICAgICAgICBsZXQgcGxhbmVBc0NhcnRlc2lhbjQgPSBDYXJ0ZXNpYW40X2RlZmF1bHQuZnJvbUVsZW1lbnRzKAogICAgICAgICAgbm9ybWFsMi54LAogICAgICAgICAgbm9ybWFsMi55LAogICAgICAgICAgbm9ybWFsMi56LAogICAgICAgICAgZGlzdGFuY2UsCiAgICAgICAgICBzY3JhdGNoUGxhbmVDYXJ0ZXNpYW40CiAgICAgICAgKTsKICAgICAgICBwbGFuZUFzQ2FydGVzaWFuNCA9IE1hdHJpeDRfZGVmYXVsdC5tdWx0aXBseUJ5VmVjdG9yKAogICAgICAgICAgaW52ZXJzZVRyYW5zcG9zZTIsCiAgICAgICAgICBwbGFuZUFzQ2FydGVzaWFuNCwKICAgICAgICAgIHBsYW5lQXNDYXJ0ZXNpYW40CiAgICAgICAgKTsKICAgICAgICBjb25zdCB0cmFuc2Zvcm1lZE5vcm1hbCA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQ2FydGVzaWFuNCgKICAgICAgICAgIHBsYW5lQXNDYXJ0ZXNpYW40LAogICAgICAgICAgc2NyYXRjaFRyYW5zZm9ybU5vcm1hbAogICAgICAgICk7CiAgICAgICAgcGxhbmVBc0NhcnRlc2lhbjQgPSBDYXJ0ZXNpYW40X2RlZmF1bHQuZGl2aWRlQnlTY2FsYXIoCiAgICAgICAgICBwbGFuZUFzQ2FydGVzaWFuNCwKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUodHJhbnNmb3JtZWROb3JtYWwpLAogICAgICAgICAgcGxhbmVBc0NhcnRlc2lhbjQKICAgICAgICApOwogICAgICAgIHJldHVybiBQbGFuZS5mcm9tQ2FydGVzaWFuNChwbGFuZUFzQ2FydGVzaWFuNCwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgUGxhbmUuY2xvbmUgPSBmdW5jdGlvbihwbGFuZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJwbGFuZSIsIHBsYW5lKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFBsYW5lKHBsYW5lLm5vcm1hbCwgcGxhbmUuZGlzdGFuY2UpOwogICAgICAgIH0KICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocGxhbmUubm9ybWFsLCByZXN1bHQubm9ybWFsKTsKICAgICAgICByZXN1bHQuZGlzdGFuY2UgPSBwbGFuZS5kaXN0YW5jZTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBQbGFuZS5lcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgcmV0dXJuIGxlZnQuZGlzdGFuY2UgPT09IHJpZ2h0LmRpc3RhbmNlICYmIENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHMobGVmdC5ub3JtYWwsIHJpZ2h0Lm5vcm1hbCk7CiAgICAgIH07CiAgICAgIFBsYW5lLk9SSUdJTl9YWV9QTEFORSA9IE9iamVjdC5mcmVlemUobmV3IFBsYW5lKENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1osIDApKTsKICAgICAgUGxhbmUuT1JJR0lOX1laX1BMQU5FID0gT2JqZWN0LmZyZWV6ZShuZXcgUGxhbmUoQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWCwgMCkpOwogICAgICBQbGFuZS5PUklHSU5fWlhfUExBTkUgPSBPYmplY3QuZnJlZXplKG5ldyBQbGFuZShDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9ZLCAwKSk7CiAgICAgIFBsYW5lX2RlZmF1bHQgPSBQbGFuZTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1RpcHNpZnkuanMKICB2YXIgVGlwc2lmeSwgVGlwc2lmeV9kZWZhdWx0OwogIHZhciBpbml0X1RpcHNpZnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1RpcHNpZnkuanMiKCkgewogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBUaXBzaWZ5ID0ge307CiAgICAgIFRpcHNpZnkuY2FsY3VsYXRlQUNNUiA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICAgICAgY29uc3QgaW5kaWNlcyA9IG9wdGlvbnMuaW5kaWNlczsKICAgICAgICBsZXQgbWF4aW11bUluZGV4ID0gb3B0aW9ucy5tYXhpbXVtSW5kZXg7CiAgICAgICAgY29uc3QgY2FjaGVTaXplID0gb3B0aW9ucy5jYWNoZVNpemUgPz8gMjQ7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaW5kaWNlcykpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJpbmRpY2VzIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBudW1JbmRpY2VzID0gaW5kaWNlcy5sZW5ndGg7CiAgICAgICAgaWYgKG51bUluZGljZXMgPCAzIHx8IG51bUluZGljZXMgJSAzICE9PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiaW5kaWNlcyBsZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIHRocmVlLiIpOwogICAgICAgIH0KICAgICAgICBpZiAobWF4aW11bUluZGV4IDw9IDApIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJtYXhpbXVtSW5kZXggbXVzdCBiZSBncmVhdGVyIHRoYW4gemVyby4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKGNhY2hlU2l6ZSA8IDMpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJjYWNoZVNpemUgbXVzdCBiZSBncmVhdGVyIHRoYW4gdHdvLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChtYXhpbXVtSW5kZXgpKSB7CiAgICAgICAgICBtYXhpbXVtSW5kZXggPSAwOwogICAgICAgICAgbGV0IGN1cnJlbnRJbmRleCA9IDA7CiAgICAgICAgICBsZXQgaW50b0luZGljZXMgPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07CiAgICAgICAgICB3aGlsZSAoY3VycmVudEluZGV4IDwgbnVtSW5kaWNlcykgewogICAgICAgICAgICBpZiAoaW50b0luZGljZXMgPiBtYXhpbXVtSW5kZXgpIHsKICAgICAgICAgICAgICBtYXhpbXVtSW5kZXggPSBpbnRvSW5kaWNlczsKICAgICAgICAgICAgfQogICAgICAgICAgICArK2N1cnJlbnRJbmRleDsKICAgICAgICAgICAgaW50b0luZGljZXMgPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IHZlcnRleFRpbWVTdGFtcHMgPSBbXTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1heGltdW1JbmRleCArIDE7IGkrKykgewogICAgICAgICAgdmVydGV4VGltZVN0YW1wc1tpXSA9IDA7CiAgICAgICAgfQogICAgICAgIGxldCBzID0gY2FjaGVTaXplICsgMTsKICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG51bUluZGljZXM7ICsraikgewogICAgICAgICAgaWYgKHMgLSB2ZXJ0ZXhUaW1lU3RhbXBzW2luZGljZXNbal1dID4gY2FjaGVTaXplKSB7CiAgICAgICAgICAgIHZlcnRleFRpbWVTdGFtcHNbaW5kaWNlc1tqXV0gPSBzOwogICAgICAgICAgICArK3M7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiAocyAtIGNhY2hlU2l6ZSArIDEpIC8gKG51bUluZGljZXMgLyAzKTsKICAgICAgfTsKICAgICAgVGlwc2lmeS50aXBzaWZ5ID0gZnVuY3Rpb24ob3B0aW9ucykgewogICAgICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgICAgICBjb25zdCBpbmRpY2VzID0gb3B0aW9ucy5pbmRpY2VzOwogICAgICAgIGNvbnN0IG1heGltdW1JbmRleCA9IG9wdGlvbnMubWF4aW11bUluZGV4OwogICAgICAgIGNvbnN0IGNhY2hlU2l6ZSA9IG9wdGlvbnMuY2FjaGVTaXplID8/IDI0OwogICAgICAgIGxldCBjdXJzb3I7CiAgICAgICAgZnVuY3Rpb24gc2tpcERlYWRFbmQodmVydGljZXMyLCBkZWFkRW5kMiwgaW5kaWNlczIsIG1heGltdW1JbmRleFBsdXNPbmUyKSB7CiAgICAgICAgICB3aGlsZSAoZGVhZEVuZDIubGVuZ3RoID49IDEpIHsKICAgICAgICAgICAgY29uc3QgZCA9IGRlYWRFbmQyW2RlYWRFbmQyLmxlbmd0aCAtIDFdOwogICAgICAgICAgICBkZWFkRW5kMi5zcGxpY2UoZGVhZEVuZDIubGVuZ3RoIC0gMSwgMSk7CiAgICAgICAgICAgIGlmICh2ZXJ0aWNlczJbZF0ubnVtTGl2ZVRyaWFuZ2xlcyA+IDApIHsKICAgICAgICAgICAgICByZXR1cm4gZDsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgd2hpbGUgKGN1cnNvciA8IG1heGltdW1JbmRleFBsdXNPbmUyKSB7CiAgICAgICAgICAgIGlmICh2ZXJ0aWNlczJbY3Vyc29yXS5udW1MaXZlVHJpYW5nbGVzID4gMCkgewogICAgICAgICAgICAgICsrY3Vyc29yOwogICAgICAgICAgICAgIHJldHVybiBjdXJzb3IgLSAxOwogICAgICAgICAgICB9CiAgICAgICAgICAgICsrY3Vyc29yOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIC0xOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBnZXROZXh0VmVydGV4KGluZGljZXMyLCBjYWNoZVNpemUyLCBvbmVSaW5nMiwgdmVydGljZXMyLCBzMiwgZGVhZEVuZDIsIG1heGltdW1JbmRleFBsdXNPbmUyKSB7CiAgICAgICAgICBsZXQgbiA9IC0xOwogICAgICAgICAgbGV0IHA7CiAgICAgICAgICBsZXQgbSA9IC0xOwogICAgICAgICAgbGV0IGl0T25lUmluZyA9IDA7CiAgICAgICAgICB3aGlsZSAoaXRPbmVSaW5nIDwgb25lUmluZzIubGVuZ3RoKSB7CiAgICAgICAgICAgIGNvbnN0IGluZGV4MiA9IG9uZVJpbmcyW2l0T25lUmluZ107CiAgICAgICAgICAgIGlmICh2ZXJ0aWNlczJbaW5kZXgyXS5udW1MaXZlVHJpYW5nbGVzKSB7CiAgICAgICAgICAgICAgcCA9IDA7CiAgICAgICAgICAgICAgaWYgKHMyIC0gdmVydGljZXMyW2luZGV4Ml0udGltZVN0YW1wICsgMiAqIHZlcnRpY2VzMltpbmRleDJdLm51bUxpdmVUcmlhbmdsZXMgPD0gY2FjaGVTaXplMikgewogICAgICAgICAgICAgICAgcCA9IHMyIC0gdmVydGljZXMyW2luZGV4Ml0udGltZVN0YW1wOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAocCA+IG0gfHwgbSA9PT0gLTEpIHsKICAgICAgICAgICAgICAgIG0gPSBwOwogICAgICAgICAgICAgICAgbiA9IGluZGV4MjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgKytpdE9uZVJpbmc7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobiA9PT0gLTEpIHsKICAgICAgICAgICAgcmV0dXJuIHNraXBEZWFkRW5kKHZlcnRpY2VzMiwgZGVhZEVuZDIsIGluZGljZXMyLCBtYXhpbXVtSW5kZXhQbHVzT25lMik7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gbjsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaW5kaWNlcykpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJpbmRpY2VzIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBudW1JbmRpY2VzID0gaW5kaWNlcy5sZW5ndGg7CiAgICAgICAgaWYgKG51bUluZGljZXMgPCAzIHx8IG51bUluZGljZXMgJSAzICE9PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiaW5kaWNlcyBsZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIHRocmVlLiIpOwogICAgICAgIH0KICAgICAgICBpZiAobWF4aW11bUluZGV4IDw9IDApIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJtYXhpbXVtSW5kZXggbXVzdCBiZSBncmVhdGVyIHRoYW4gemVyby4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKGNhY2hlU2l6ZSA8IDMpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJjYWNoZVNpemUgbXVzdCBiZSBncmVhdGVyIHRoYW4gdHdvLiIpOwogICAgICAgIH0KICAgICAgICBsZXQgbWF4aW11bUluZGV4UGx1c09uZSA9IDA7CiAgICAgICAgbGV0IGN1cnJlbnRJbmRleCA9IDA7CiAgICAgICAgbGV0IGludG9JbmRpY2VzID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdOwogICAgICAgIGNvbnN0IGVuZEluZGV4ID0gbnVtSW5kaWNlczsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG1heGltdW1JbmRleCkpIHsKICAgICAgICAgIG1heGltdW1JbmRleFBsdXNPbmUgPSBtYXhpbXVtSW5kZXggKyAxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB3aGlsZSAoY3VycmVudEluZGV4IDwgZW5kSW5kZXgpIHsKICAgICAgICAgICAgaWYgKGludG9JbmRpY2VzID4gbWF4aW11bUluZGV4UGx1c09uZSkgewogICAgICAgICAgICAgIG1heGltdW1JbmRleFBsdXNPbmUgPSBpbnRvSW5kaWNlczsKICAgICAgICAgICAgfQogICAgICAgICAgICArK2N1cnJlbnRJbmRleDsKICAgICAgICAgICAgaW50b0luZGljZXMgPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobWF4aW11bUluZGV4UGx1c09uZSA9PT0gLTEpIHsKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgICB9CiAgICAgICAgICArK21heGltdW1JbmRleFBsdXNPbmU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHZlcnRpY2VzID0gW107CiAgICAgICAgbGV0IGk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IG1heGltdW1JbmRleFBsdXNPbmU7IGkrKykgewogICAgICAgICAgdmVydGljZXNbaV0gPSB7CiAgICAgICAgICAgIG51bUxpdmVUcmlhbmdsZXM6IDAsCiAgICAgICAgICAgIHRpbWVTdGFtcDogMCwKICAgICAgICAgICAgdmVydGV4VHJpYW5nbGVzOiBbXQogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgY3VycmVudEluZGV4ID0gMDsKICAgICAgICBsZXQgdHJpYW5nbGUgPSAwOwogICAgICAgIHdoaWxlIChjdXJyZW50SW5kZXggPCBlbmRJbmRleCkgewogICAgICAgICAgdmVydGljZXNbaW5kaWNlc1tjdXJyZW50SW5kZXhdXS52ZXJ0ZXhUcmlhbmdsZXMucHVzaCh0cmlhbmdsZSk7CiAgICAgICAgICArK3ZlcnRpY2VzW2luZGljZXNbY3VycmVudEluZGV4XV0ubnVtTGl2ZVRyaWFuZ2xlczsKICAgICAgICAgIHZlcnRpY2VzW2luZGljZXNbY3VycmVudEluZGV4ICsgMV1dLnZlcnRleFRyaWFuZ2xlcy5wdXNoKHRyaWFuZ2xlKTsKICAgICAgICAgICsrdmVydGljZXNbaW5kaWNlc1tjdXJyZW50SW5kZXggKyAxXV0ubnVtTGl2ZVRyaWFuZ2xlczsKICAgICAgICAgIHZlcnRpY2VzW2luZGljZXNbY3VycmVudEluZGV4ICsgMl1dLnZlcnRleFRyaWFuZ2xlcy5wdXNoKHRyaWFuZ2xlKTsKICAgICAgICAgICsrdmVydGljZXNbaW5kaWNlc1tjdXJyZW50SW5kZXggKyAyXV0ubnVtTGl2ZVRyaWFuZ2xlczsKICAgICAgICAgICsrdHJpYW5nbGU7CiAgICAgICAgICBjdXJyZW50SW5kZXggKz0gMzsKICAgICAgICB9CiAgICAgICAgbGV0IGYgPSAwOwogICAgICAgIGxldCBzID0gY2FjaGVTaXplICsgMTsKICAgICAgICBjdXJzb3IgPSAxOwogICAgICAgIGxldCBvbmVSaW5nID0gW107CiAgICAgICAgY29uc3QgZGVhZEVuZCA9IFtdOwogICAgICAgIGxldCB2ZXJ0ZXg7CiAgICAgICAgbGV0IGludG9WZXJ0aWNlczsKICAgICAgICBsZXQgY3VycmVudE91dHB1dEluZGV4ID0gMDsKICAgICAgICBjb25zdCBvdXRwdXRJbmRpY2VzID0gW107CiAgICAgICAgY29uc3QgbnVtVHJpYW5nbGVzID0gbnVtSW5kaWNlcyAvIDM7CiAgICAgICAgY29uc3QgdHJpYW5nbGVFbWl0dGVkID0gW107CiAgICAgICAgZm9yIChpID0gMDsgaSA8IG51bVRyaWFuZ2xlczsgaSsrKSB7CiAgICAgICAgICB0cmlhbmdsZUVtaXR0ZWRbaV0gPSBmYWxzZTsKICAgICAgICB9CiAgICAgICAgbGV0IGluZGV4OwogICAgICAgIGxldCBsaW1pdDsKICAgICAgICB3aGlsZSAoZiAhPT0gLTEpIHsKICAgICAgICAgIG9uZVJpbmcgPSBbXTsKICAgICAgICAgIGludG9WZXJ0aWNlcyA9IHZlcnRpY2VzW2ZdOwogICAgICAgICAgbGltaXQgPSBpbnRvVmVydGljZXMudmVydGV4VHJpYW5nbGVzLmxlbmd0aDsKICAgICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgbGltaXQ7ICsraykgewogICAgICAgICAgICB0cmlhbmdsZSA9IGludG9WZXJ0aWNlcy52ZXJ0ZXhUcmlhbmdsZXNba107CiAgICAgICAgICAgIGlmICghdHJpYW5nbGVFbWl0dGVkW3RyaWFuZ2xlXSkgewogICAgICAgICAgICAgIHRyaWFuZ2xlRW1pdHRlZFt0cmlhbmdsZV0gPSB0cnVlOwogICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IHRyaWFuZ2xlICsgdHJpYW5nbGUgKyB0cmlhbmdsZTsKICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IDM7ICsraikgewogICAgICAgICAgICAgICAgaW5kZXggPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07CiAgICAgICAgICAgICAgICBvbmVSaW5nLnB1c2goaW5kZXgpOwogICAgICAgICAgICAgICAgZGVhZEVuZC5wdXNoKGluZGV4KTsKICAgICAgICAgICAgICAgIG91dHB1dEluZGljZXNbY3VycmVudE91dHB1dEluZGV4XSA9IGluZGV4OwogICAgICAgICAgICAgICAgKytjdXJyZW50T3V0cHV0SW5kZXg7CiAgICAgICAgICAgICAgICB2ZXJ0ZXggPSB2ZXJ0aWNlc1tpbmRleF07CiAgICAgICAgICAgICAgICAtLXZlcnRleC5udW1MaXZlVHJpYW5nbGVzOwogICAgICAgICAgICAgICAgaWYgKHMgLSB2ZXJ0ZXgudGltZVN0YW1wID4gY2FjaGVTaXplKSB7CiAgICAgICAgICAgICAgICAgIHZlcnRleC50aW1lU3RhbXAgPSBzOwogICAgICAgICAgICAgICAgICArK3M7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICArK2N1cnJlbnRJbmRleDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGYgPSBnZXROZXh0VmVydGV4KAogICAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgICBjYWNoZVNpemUsCiAgICAgICAgICAgIG9uZVJpbmcsCiAgICAgICAgICAgIHZlcnRpY2VzLAogICAgICAgICAgICBzLAogICAgICAgICAgICBkZWFkRW5kLAogICAgICAgICAgICBtYXhpbXVtSW5kZXhQbHVzT25lCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXR1cm4gb3V0cHV0SW5kaWNlczsKICAgICAgfTsKICAgICAgVGlwc2lmeV9kZWZhdWx0ID0gVGlwc2lmeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dlb21ldHJ5UGlwZWxpbmUuanMKICBmdW5jdGlvbiBhZGRUcmlhbmdsZShsaW5lcywgaW5kZXgsIGkwLCBpMSwgaTIpIHsKICAgIGxpbmVzW2luZGV4KytdID0gaTA7CiAgICBsaW5lc1tpbmRleCsrXSA9IGkxOwogICAgbGluZXNbaW5kZXgrK10gPSBpMTsKICAgIGxpbmVzW2luZGV4KytdID0gaTI7CiAgICBsaW5lc1tpbmRleCsrXSA9IGkyOwogICAgbGluZXNbaW5kZXhdID0gaTA7CiAgfQogIGZ1bmN0aW9uIHRyaWFuZ2xlc1RvTGluZXModHJpYW5nbGVzKSB7CiAgICBjb25zdCBjb3VudCA9IHRyaWFuZ2xlcy5sZW5ndGg7CiAgICBjb25zdCBzaXplID0gY291bnQgLyAzICogNjsKICAgIGNvbnN0IGxpbmVzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoY291bnQsIHNpemUpOwogICAgbGV0IGluZGV4ID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7IGkgKz0gMywgaW5kZXggKz0gNikgewogICAgICBhZGRUcmlhbmdsZShsaW5lcywgaW5kZXgsIHRyaWFuZ2xlc1tpXSwgdHJpYW5nbGVzW2kgKyAxXSwgdHJpYW5nbGVzW2kgKyAyXSk7CiAgICB9CiAgICByZXR1cm4gbGluZXM7CiAgfQogIGZ1bmN0aW9uIHRyaWFuZ2xlU3RyaXBUb0xpbmVzKHRyaWFuZ2xlcykgewogICAgY29uc3QgY291bnQgPSB0cmlhbmdsZXMubGVuZ3RoOwogICAgaWYgKGNvdW50ID49IDMpIHsKICAgICAgY29uc3Qgc2l6ZSA9IChjb3VudCAtIDIpICogNjsKICAgICAgY29uc3QgbGluZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheShjb3VudCwgc2l6ZSk7CiAgICAgIGFkZFRyaWFuZ2xlKGxpbmVzLCAwLCB0cmlhbmdsZXNbMF0sIHRyaWFuZ2xlc1sxXSwgdHJpYW5nbGVzWzJdKTsKICAgICAgbGV0IGluZGV4ID0gNjsKICAgICAgZm9yIChsZXQgaSA9IDM7IGkgPCBjb3VudDsgKytpLCBpbmRleCArPSA2KSB7CiAgICAgICAgYWRkVHJpYW5nbGUoCiAgICAgICAgICBsaW5lcywKICAgICAgICAgIGluZGV4LAogICAgICAgICAgdHJpYW5nbGVzW2kgLSAxXSwKICAgICAgICAgIHRyaWFuZ2xlc1tpXSwKICAgICAgICAgIHRyaWFuZ2xlc1tpIC0gMl0KICAgICAgICApOwogICAgICB9CiAgICAgIHJldHVybiBsaW5lczsKICAgIH0KICAgIHJldHVybiBuZXcgVWludDE2QXJyYXkoKTsKICB9CiAgZnVuY3Rpb24gdHJpYW5nbGVGYW5Ub0xpbmVzKHRyaWFuZ2xlcykgewogICAgaWYgKHRyaWFuZ2xlcy5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IGNvdW50ID0gdHJpYW5nbGVzLmxlbmd0aCAtIDE7CiAgICAgIGNvbnN0IHNpemUgPSAoY291bnQgLSAxKSAqIDY7CiAgICAgIGNvbnN0IGxpbmVzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoY291bnQsIHNpemUpOwogICAgICBjb25zdCBiYXNlID0gdHJpYW5nbGVzWzBdOwogICAgICBsZXQgaW5kZXggPSAwOwogICAgICBmb3IgKGxldCBpID0gMTsgaSA8IGNvdW50OyArK2ksIGluZGV4ICs9IDYpIHsKICAgICAgICBhZGRUcmlhbmdsZShsaW5lcywgaW5kZXgsIGJhc2UsIHRyaWFuZ2xlc1tpXSwgdHJpYW5nbGVzW2kgKyAxXSk7CiAgICAgIH0KICAgICAgcmV0dXJuIGxpbmVzOwogICAgfQogICAgcmV0dXJuIG5ldyBVaW50MTZBcnJheSgpOwogIH0KICBmdW5jdGlvbiBjb3B5QXR0cmlidXRlc0Rlc2NyaXB0aW9ucyhhdHRyaWJ1dGVzKSB7CiAgICBjb25zdCBuZXdBdHRyaWJ1dGVzID0ge307CiAgICBmb3IgKGNvbnN0IGF0dHJpYnV0ZSBpbiBhdHRyaWJ1dGVzKSB7CiAgICAgIGlmIChhdHRyaWJ1dGVzLmhhc093blByb3BlcnR5KGF0dHJpYnV0ZSkgJiYgZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXNbYXR0cmlidXRlXSkgJiYgZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXNbYXR0cmlidXRlXS52YWx1ZXMpKSB7CiAgICAgICAgY29uc3QgYXR0ciA9IGF0dHJpYnV0ZXNbYXR0cmlidXRlXTsKICAgICAgICBuZXdBdHRyaWJ1dGVzW2F0dHJpYnV0ZV0gPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogYXR0ci5jb21wb25lbnREYXRhdHlwZSwKICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IGF0dHIuY29tcG9uZW50c1BlckF0dHJpYnV0ZSwKICAgICAgICAgIG5vcm1hbGl6ZTogYXR0ci5ub3JtYWxpemUsCiAgICAgICAgICB2YWx1ZXM6IFtdCiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBuZXdBdHRyaWJ1dGVzOwogIH0KICBmdW5jdGlvbiBjb3B5VmVydGV4KGRlc3RpbmF0aW9uQXR0cmlidXRlcywgc291cmNlQXR0cmlidXRlcywgaW5kZXgpIHsKICAgIGZvciAoY29uc3QgYXR0cmlidXRlIGluIHNvdXJjZUF0dHJpYnV0ZXMpIHsKICAgICAgaWYgKHNvdXJjZUF0dHJpYnV0ZXMuaGFzT3duUHJvcGVydHkoYXR0cmlidXRlKSAmJiBkZWZpbmVkX2RlZmF1bHQoc291cmNlQXR0cmlidXRlc1thdHRyaWJ1dGVdKSAmJiBkZWZpbmVkX2RlZmF1bHQoc291cmNlQXR0cmlidXRlc1thdHRyaWJ1dGVdLnZhbHVlcykpIHsKICAgICAgICBjb25zdCBhdHRyID0gc291cmNlQXR0cmlidXRlc1thdHRyaWJ1dGVdOwogICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgYXR0ci5jb21wb25lbnRzUGVyQXR0cmlidXRlOyArK2spIHsKICAgICAgICAgIGRlc3RpbmF0aW9uQXR0cmlidXRlc1thdHRyaWJ1dGVdLnZhbHVlcy5wdXNoKAogICAgICAgICAgICBhdHRyLnZhbHVlc1tpbmRleCAqIGF0dHIuY29tcG9uZW50c1BlckF0dHJpYnV0ZSArIGtdCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICBmdW5jdGlvbiB0cmFuc2Zvcm1Qb2ludChtYXRyaXgsIGF0dHJpYnV0ZSkgewogICAgaWYgKGRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGUpKSB7CiAgICAgIGNvbnN0IHZhbHVlcyA9IGF0dHJpYnV0ZS52YWx1ZXM7CiAgICAgIGNvbnN0IGxlbmd0aCA9IHZhbHVlcy5sZW5ndGg7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKHZhbHVlcywgaSwgc2NyYXRjaENhcnRlc2lhbjMzKTsKICAgICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlCeVBvaW50KG1hdHJpeCwgc2NyYXRjaENhcnRlc2lhbjMzLCBzY3JhdGNoQ2FydGVzaWFuMzMpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHNjcmF0Y2hDYXJ0ZXNpYW4zMywgdmFsdWVzLCBpKTsKICAgICAgfQogICAgfQogIH0KICBmdW5jdGlvbiB0cmFuc2Zvcm1WZWN0b3IobWF0cml4LCBhdHRyaWJ1dGUpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlKSkgewogICAgICBjb25zdCB2YWx1ZXMgPSBhdHRyaWJ1dGUudmFsdWVzOwogICAgICBjb25zdCBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAzKSB7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjayh2YWx1ZXMsIGksIHNjcmF0Y2hDYXJ0ZXNpYW4zMyk7CiAgICAgICAgTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3IobWF0cml4LCBzY3JhdGNoQ2FydGVzaWFuMzMsIHNjcmF0Y2hDYXJ0ZXNpYW4zMyk7CiAgICAgICAgc2NyYXRjaENhcnRlc2lhbjMzID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4zMywKICAgICAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4zMwogICAgICAgICk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soc2NyYXRjaENhcnRlc2lhbjMzLCB2YWx1ZXMsIGkpOwogICAgICB9CiAgICB9CiAgfQogIGZ1bmN0aW9uIGZpbmRBdHRyaWJ1dGVzSW5BbGxHZW9tZXRyaWVzKGluc3RhbmNlcywgcHJvcGVydHlOYW1lKSB7CiAgICBjb25zdCBsZW5ndGggPSBpbnN0YW5jZXMubGVuZ3RoOwogICAgY29uc3QgYXR0cmlidXRlc0luQWxsR2VvbWV0cmllcyA9IHt9OwogICAgY29uc3QgYXR0cmlidXRlczAgPSBpbnN0YW5jZXNbMF1bcHJvcGVydHlOYW1lXS5hdHRyaWJ1dGVzOwogICAgbGV0IG5hbWU7CiAgICBmb3IgKG5hbWUgaW4gYXR0cmlidXRlczApIHsKICAgICAgaWYgKGF0dHJpYnV0ZXMwLmhhc093blByb3BlcnR5KG5hbWUpICYmIGRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVzMFtuYW1lXSkgJiYgZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXMwW25hbWVdLnZhbHVlcykpIHsKICAgICAgICBjb25zdCBhdHRyaWJ1dGUgPSBhdHRyaWJ1dGVzMFtuYW1lXTsKICAgICAgICBsZXQgbnVtYmVyT2ZDb21wb25lbnRzID0gYXR0cmlidXRlLnZhbHVlcy5sZW5ndGg7CiAgICAgICAgbGV0IGluQWxsR2VvbWV0cmllcyA9IHRydWU7CiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgY29uc3Qgb3RoZXJBdHRyaWJ1dGUgPSBpbnN0YW5jZXNbaV1bcHJvcGVydHlOYW1lXS5hdHRyaWJ1dGVzW25hbWVdOwogICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQob3RoZXJBdHRyaWJ1dGUpIHx8IGF0dHJpYnV0ZS5jb21wb25lbnREYXRhdHlwZSAhPT0gb3RoZXJBdHRyaWJ1dGUuY29tcG9uZW50RGF0YXR5cGUgfHwgYXR0cmlidXRlLmNvbXBvbmVudHNQZXJBdHRyaWJ1dGUgIT09IG90aGVyQXR0cmlidXRlLmNvbXBvbmVudHNQZXJBdHRyaWJ1dGUgfHwgYXR0cmlidXRlLm5vcm1hbGl6ZSAhPT0gb3RoZXJBdHRyaWJ1dGUubm9ybWFsaXplKSB7CiAgICAgICAgICAgIGluQWxsR2VvbWV0cmllcyA9IGZhbHNlOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIG51bWJlck9mQ29tcG9uZW50cyArPSBvdGhlckF0dHJpYnV0ZS52YWx1ZXMubGVuZ3RoOwogICAgICAgIH0KICAgICAgICBpZiAoaW5BbGxHZW9tZXRyaWVzKSB7CiAgICAgICAgICBhdHRyaWJ1dGVzSW5BbGxHZW9tZXRyaWVzW25hbWVdID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogYXR0cmlidXRlLmNvbXBvbmVudERhdGF0eXBlLAogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiBhdHRyaWJ1dGUuY29tcG9uZW50c1BlckF0dHJpYnV0ZSwKICAgICAgICAgICAgbm9ybWFsaXplOiBhdHRyaWJ1dGUubm9ybWFsaXplLAogICAgICAgICAgICB2YWx1ZXM6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgICAgICAgICBhdHRyaWJ1dGUuY29tcG9uZW50RGF0YXR5cGUsCiAgICAgICAgICAgICAgbnVtYmVyT2ZDb21wb25lbnRzCiAgICAgICAgICAgICkKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIGF0dHJpYnV0ZXNJbkFsbEdlb21ldHJpZXM7CiAgfQogIGZ1bmN0aW9uIGNvbWJpbmVHZW9tZXRyaWVzKGluc3RhbmNlcywgcHJvcGVydHlOYW1lKSB7CiAgICBjb25zdCBsZW5ndGggPSBpbnN0YW5jZXMubGVuZ3RoOwogICAgbGV0IG5hbWU7CiAgICBsZXQgaTsKICAgIGxldCBqOwogICAgbGV0IGs7CiAgICBjb25zdCBtID0gaW5zdGFuY2VzWzBdLm1vZGVsTWF0cml4OwogICAgY29uc3QgaGF2ZUluZGljZXMgPSBkZWZpbmVkX2RlZmF1bHQoaW5zdGFuY2VzWzBdW3Byb3BlcnR5TmFtZV0uaW5kaWNlcyk7CiAgICBjb25zdCBwcmltaXRpdmVUeXBlID0gaW5zdGFuY2VzWzBdW3Byb3BlcnR5TmFtZV0ucHJpbWl0aXZlVHlwZTsKICAgIGZvciAoaSA9IDE7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBpZiAoIU1hdHJpeDRfZGVmYXVsdC5lcXVhbHMoaW5zdGFuY2VzW2ldLm1vZGVsTWF0cml4LCBtKSkgewogICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJBbGwgaW5zdGFuY2VzIG11c3QgaGF2ZSB0aGUgc2FtZSBtb2RlbE1hdHJpeC4iKTsKICAgICAgfQogICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGluc3RhbmNlc1tpXVtwcm9wZXJ0eU5hbWVdLmluZGljZXMpICE9PSBoYXZlSW5kaWNlcykgewogICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgIkFsbCBpbnN0YW5jZSBnZW9tZXRyaWVzIG11c3QgaGF2ZSBhbiBpbmRpY2VzIG9yIG5vdCBoYXZlIG9uZS4iCiAgICAgICAgKTsKICAgICAgfQogICAgICBpZiAoaW5zdGFuY2VzW2ldW3Byb3BlcnR5TmFtZV0ucHJpbWl0aXZlVHlwZSAhPT0gcHJpbWl0aXZlVHlwZSkgewogICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgIkFsbCBpbnN0YW5jZSBnZW9tZXRyaWVzIG11c3QgaGF2ZSB0aGUgc2FtZSBwcmltaXRpdmVUeXBlLiIKICAgICAgICApOwogICAgICB9CiAgICB9CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gZmluZEF0dHJpYnV0ZXNJbkFsbEdlb21ldHJpZXMoaW5zdGFuY2VzLCBwcm9wZXJ0eU5hbWUpOwogICAgbGV0IHZhbHVlczsKICAgIGxldCBzb3VyY2VWYWx1ZXM7CiAgICBsZXQgc291cmNlVmFsdWVzTGVuZ3RoOwogICAgZm9yIChuYW1lIGluIGF0dHJpYnV0ZXMpIHsKICAgICAgaWYgKGF0dHJpYnV0ZXMuaGFzT3duUHJvcGVydHkobmFtZSkpIHsKICAgICAgICB2YWx1ZXMgPSBhdHRyaWJ1dGVzW25hbWVdLnZhbHVlczsKICAgICAgICBrID0gMDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgIHNvdXJjZVZhbHVlcyA9IGluc3RhbmNlc1tpXVtwcm9wZXJ0eU5hbWVdLmF0dHJpYnV0ZXNbbmFtZV0udmFsdWVzOwogICAgICAgICAgc291cmNlVmFsdWVzTGVuZ3RoID0gc291cmNlVmFsdWVzLmxlbmd0aDsKICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBzb3VyY2VWYWx1ZXNMZW5ndGg7ICsraikgewogICAgICAgICAgICB2YWx1ZXNbaysrXSA9IHNvdXJjZVZhbHVlc1tqXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGxldCBpbmRpY2VzOwogICAgaWYgKGhhdmVJbmRpY2VzKSB7CiAgICAgIGxldCBudW1iZXJPZkluZGljZXMgPSAwOwogICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICBudW1iZXJPZkluZGljZXMgKz0gaW5zdGFuY2VzW2ldW3Byb3BlcnR5TmFtZV0uaW5kaWNlcy5sZW5ndGg7CiAgICAgIH0KICAgICAgY29uc3QgbnVtYmVyT2ZWZXJ0aWNlcyA9IEdlb21ldHJ5X2RlZmF1bHQuY29tcHV0ZU51bWJlck9mVmVydGljZXMoCiAgICAgICAgbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgICAgYXR0cmlidXRlcywKICAgICAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5QT0lOVFMKICAgICAgICB9KQogICAgICApOwogICAgICBjb25zdCBkZXN0SW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KAogICAgICAgIG51bWJlck9mVmVydGljZXMsCiAgICAgICAgbnVtYmVyT2ZJbmRpY2VzCiAgICAgICk7CiAgICAgIGxldCBkZXN0T2Zmc2V0ID0gMDsKICAgICAgbGV0IG9mZnNldCA9IDA7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgIGNvbnN0IHNvdXJjZUluZGljZXMgPSBpbnN0YW5jZXNbaV1bcHJvcGVydHlOYW1lXS5pbmRpY2VzOwogICAgICAgIGNvbnN0IHNvdXJjZUluZGljZXNMZW4gPSBzb3VyY2VJbmRpY2VzLmxlbmd0aDsKICAgICAgICBmb3IgKGsgPSAwOyBrIDwgc291cmNlSW5kaWNlc0xlbjsgKytrKSB7CiAgICAgICAgICBkZXN0SW5kaWNlc1tkZXN0T2Zmc2V0KytdID0gb2Zmc2V0ICsgc291cmNlSW5kaWNlc1trXTsKICAgICAgICB9CiAgICAgICAgb2Zmc2V0ICs9IEdlb21ldHJ5X2RlZmF1bHQuY29tcHV0ZU51bWJlck9mVmVydGljZXMoaW5zdGFuY2VzW2ldW3Byb3BlcnR5TmFtZV0pOwogICAgICB9CiAgICAgIGluZGljZXMgPSBkZXN0SW5kaWNlczsKICAgIH0KICAgIGxldCBjZW50ZXIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICBsZXQgcmFkaXVzID0gMDsKICAgIGxldCBiczsKICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBicyA9IGluc3RhbmNlc1tpXVtwcm9wZXJ0eU5hbWVdLmJvdW5kaW5nU3BoZXJlOwogICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChicykpIHsKICAgICAgICBjZW50ZXIgPSB2b2lkIDA7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChicy5jZW50ZXIsIGNlbnRlciwgY2VudGVyKTsKICAgIH0KICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoY2VudGVyKSkgewogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZGl2aWRlQnlTY2FsYXIoY2VudGVyLCBsZW5ndGgsIGNlbnRlcik7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgIGJzID0gaW5zdGFuY2VzW2ldW3Byb3BlcnR5TmFtZV0uYm91bmRpbmdTcGhlcmU7CiAgICAgICAgY29uc3QgdGVtcFJhZGl1cyA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoYnMuY2VudGVyLCBjZW50ZXIsIHRlbXBTY3JhdGNoKQogICAgICAgICkgKyBicy5yYWRpdXM7CiAgICAgICAgaWYgKHRlbXBSYWRpdXMgPiByYWRpdXMpIHsKICAgICAgICAgIHJhZGl1cyA9IHRlbXBSYWRpdXM7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICBhdHRyaWJ1dGVzLAogICAgICBpbmRpY2VzLAogICAgICBwcmltaXRpdmVUeXBlLAogICAgICBib3VuZGluZ1NwaGVyZTogZGVmaW5lZF9kZWZhdWx0KGNlbnRlcikgPyBuZXcgQm91bmRpbmdTcGhlcmVfZGVmYXVsdChjZW50ZXIsIHJhZGl1cykgOiB2b2lkIDAKICAgIH0pOwogIH0KICBmdW5jdGlvbiBpbmRleFRyaWFuZ2xlcyhnZW9tZXRyeSkgewogICAgaWYgKGRlZmluZWRfZGVmYXVsdChnZW9tZXRyeS5pbmRpY2VzKSkgewogICAgICByZXR1cm4gZ2VvbWV0cnk7CiAgICB9CiAgICBjb25zdCBudW1iZXJPZlZlcnRpY2VzID0gR2VvbWV0cnlfZGVmYXVsdC5jb21wdXRlTnVtYmVyT2ZWZXJ0aWNlcyhnZW9tZXRyeSk7CiAgICBpZiAobnVtYmVyT2ZWZXJ0aWNlcyA8IDMpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIlRoZSBudW1iZXIgb2YgdmVydGljZXMgbXVzdCBiZSBhdCBsZWFzdCB0aHJlZS4iKTsKICAgIH0KICAgIGlmIChudW1iZXJPZlZlcnRpY2VzICUgMyAhPT0gMCkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAiVGhlIG51bWJlciBvZiB2ZXJ0aWNlcyBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgdGhyZWUuIgogICAgICApOwogICAgfQogICAgY29uc3QgaW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KAogICAgICBudW1iZXJPZlZlcnRpY2VzLAogICAgICBudW1iZXJPZlZlcnRpY2VzCiAgICApOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZlZlcnRpY2VzOyArK2kpIHsKICAgICAgaW5kaWNlc1tpXSA9IGk7CiAgICB9CiAgICBnZW9tZXRyeS5pbmRpY2VzID0gaW5kaWNlczsKICAgIHJldHVybiBnZW9tZXRyeTsKICB9CiAgZnVuY3Rpb24gaW5kZXhUcmlhbmdsZUZhbihnZW9tZXRyeSkgewogICAgY29uc3QgbnVtYmVyT2ZWZXJ0aWNlcyA9IEdlb21ldHJ5X2RlZmF1bHQuY29tcHV0ZU51bWJlck9mVmVydGljZXMoZ2VvbWV0cnkpOwogICAgaWYgKG51bWJlck9mVmVydGljZXMgPCAzKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJUaGUgbnVtYmVyIG9mIHZlcnRpY2VzIG11c3QgYmUgYXQgbGVhc3QgdGhyZWUuIik7CiAgICB9CiAgICBjb25zdCBpbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgIG51bWJlck9mVmVydGljZXMsCiAgICAgIChudW1iZXJPZlZlcnRpY2VzIC0gMikgKiAzCiAgICApOwogICAgaW5kaWNlc1swXSA9IDE7CiAgICBpbmRpY2VzWzFdID0gMDsKICAgIGluZGljZXNbMl0gPSAyOwogICAgbGV0IGluZGljZXNJbmRleCA9IDM7CiAgICBmb3IgKGxldCBpID0gMzsgaSA8IG51bWJlck9mVmVydGljZXM7ICsraSkgewogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGkgLSAxOwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IDA7CiAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaTsKICAgIH0KICAgIGdlb21ldHJ5LmluZGljZXMgPSBpbmRpY2VzOwogICAgZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSA9IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5UUklBTkdMRVM7CiAgICByZXR1cm4gZ2VvbWV0cnk7CiAgfQogIGZ1bmN0aW9uIGluZGV4VHJpYW5nbGVTdHJpcChnZW9tZXRyeSkgewogICAgY29uc3QgbnVtYmVyT2ZWZXJ0aWNlcyA9IEdlb21ldHJ5X2RlZmF1bHQuY29tcHV0ZU51bWJlck9mVmVydGljZXMoZ2VvbWV0cnkpOwogICAgaWYgKG51bWJlck9mVmVydGljZXMgPCAzKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJUaGUgbnVtYmVyIG9mIHZlcnRpY2VzIG11c3QgYmUgYXQgbGVhc3QgMy4iKTsKICAgIH0KICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgbnVtYmVyT2ZWZXJ0aWNlcywKICAgICAgKG51bWJlck9mVmVydGljZXMgLSAyKSAqIDMKICAgICk7CiAgICBpbmRpY2VzWzBdID0gMDsKICAgIGluZGljZXNbMV0gPSAxOwogICAgaW5kaWNlc1syXSA9IDI7CiAgICBpZiAobnVtYmVyT2ZWZXJ0aWNlcyA+IDMpIHsKICAgICAgaW5kaWNlc1szXSA9IDA7CiAgICAgIGluZGljZXNbNF0gPSAyOwogICAgICBpbmRpY2VzWzVdID0gMzsKICAgIH0KICAgIGxldCBpbmRpY2VzSW5kZXggPSA2OwogICAgZm9yIChsZXQgaSA9IDM7IGkgPCBudW1iZXJPZlZlcnRpY2VzIC0gMTsgaSArPSAyKSB7CiAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaTsKICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBpIC0gMTsKICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBpICsgMTsKICAgICAgaWYgKGkgKyAyIDwgbnVtYmVyT2ZWZXJ0aWNlcykgewogICAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaTsKICAgICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGkgKyAxOwogICAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaSArIDI7CiAgICAgIH0KICAgIH0KICAgIGdlb21ldHJ5LmluZGljZXMgPSBpbmRpY2VzOwogICAgZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSA9IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5UUklBTkdMRVM7CiAgICByZXR1cm4gZ2VvbWV0cnk7CiAgfQogIGZ1bmN0aW9uIGluZGV4TGluZXMoZ2VvbWV0cnkpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZ2VvbWV0cnkuaW5kaWNlcykpIHsKICAgICAgcmV0dXJuIGdlb21ldHJ5OwogICAgfQogICAgY29uc3QgbnVtYmVyT2ZWZXJ0aWNlcyA9IEdlb21ldHJ5X2RlZmF1bHQuY29tcHV0ZU51bWJlck9mVmVydGljZXMoZ2VvbWV0cnkpOwogICAgaWYgKG51bWJlck9mVmVydGljZXMgPCAyKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJUaGUgbnVtYmVyIG9mIHZlcnRpY2VzIG11c3QgYmUgYXQgbGVhc3QgdHdvLiIpOwogICAgfQogICAgaWYgKG51bWJlck9mVmVydGljZXMgJSAyICE9PSAwKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJUaGUgbnVtYmVyIG9mIHZlcnRpY2VzIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAyLiIpOwogICAgfQogICAgY29uc3QgaW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KAogICAgICBudW1iZXJPZlZlcnRpY2VzLAogICAgICBudW1iZXJPZlZlcnRpY2VzCiAgICApOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZlZlcnRpY2VzOyArK2kpIHsKICAgICAgaW5kaWNlc1tpXSA9IGk7CiAgICB9CiAgICBnZW9tZXRyeS5pbmRpY2VzID0gaW5kaWNlczsKICAgIHJldHVybiBnZW9tZXRyeTsKICB9CiAgZnVuY3Rpb24gaW5kZXhMaW5lU3RyaXAoZ2VvbWV0cnkpIHsKICAgIGNvbnN0IG51bWJlck9mVmVydGljZXMgPSBHZW9tZXRyeV9kZWZhdWx0LmNvbXB1dGVOdW1iZXJPZlZlcnRpY2VzKGdlb21ldHJ5KTsKICAgIGlmIChudW1iZXJPZlZlcnRpY2VzIDwgMikgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiVGhlIG51bWJlciBvZiB2ZXJ0aWNlcyBtdXN0IGJlIGF0IGxlYXN0IHR3by4iKTsKICAgIH0KICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgbnVtYmVyT2ZWZXJ0aWNlcywKICAgICAgKG51bWJlck9mVmVydGljZXMgLSAxKSAqIDIKICAgICk7CiAgICBpbmRpY2VzWzBdID0gMDsKICAgIGluZGljZXNbMV0gPSAxOwogICAgbGV0IGluZGljZXNJbmRleCA9IDI7CiAgICBmb3IgKGxldCBpID0gMjsgaSA8IG51bWJlck9mVmVydGljZXM7ICsraSkgewogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGkgLSAxOwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGk7CiAgICB9CiAgICBnZW9tZXRyeS5pbmRpY2VzID0gaW5kaWNlczsKICAgIGdlb21ldHJ5LnByaW1pdGl2ZVR5cGUgPSBQcmltaXRpdmVUeXBlX2RlZmF1bHQuTElORVM7CiAgICByZXR1cm4gZ2VvbWV0cnk7CiAgfQogIGZ1bmN0aW9uIGluZGV4TGluZUxvb3AoZ2VvbWV0cnkpIHsKICAgIGNvbnN0IG51bWJlck9mVmVydGljZXMgPSBHZW9tZXRyeV9kZWZhdWx0LmNvbXB1dGVOdW1iZXJPZlZlcnRpY2VzKGdlb21ldHJ5KTsKICAgIGlmIChudW1iZXJPZlZlcnRpY2VzIDwgMikgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiVGhlIG51bWJlciBvZiB2ZXJ0aWNlcyBtdXN0IGJlIGF0IGxlYXN0IHR3by4iKTsKICAgIH0KICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgbnVtYmVyT2ZWZXJ0aWNlcywKICAgICAgbnVtYmVyT2ZWZXJ0aWNlcyAqIDIKICAgICk7CiAgICBpbmRpY2VzWzBdID0gMDsKICAgIGluZGljZXNbMV0gPSAxOwogICAgbGV0IGluZGljZXNJbmRleCA9IDI7CiAgICBmb3IgKGxldCBpID0gMjsgaSA8IG51bWJlck9mVmVydGljZXM7ICsraSkgewogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGkgLSAxOwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGk7CiAgICB9CiAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IG51bWJlck9mVmVydGljZXMgLSAxOwogICAgaW5kaWNlc1tpbmRpY2VzSW5kZXhdID0gMDsKICAgIGdlb21ldHJ5LmluZGljZXMgPSBpbmRpY2VzOwogICAgZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSA9IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5MSU5FUzsKICAgIHJldHVybiBnZW9tZXRyeTsKICB9CiAgZnVuY3Rpb24gaW5kZXhQcmltaXRpdmUoZ2VvbWV0cnkpIHsKICAgIHN3aXRjaCAoZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSkgewogICAgICBjYXNlIFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5UUklBTkdMRV9GQU46CiAgICAgICAgcmV0dXJuIGluZGV4VHJpYW5nbGVGYW4oZ2VvbWV0cnkpOwogICAgICBjYXNlIFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5UUklBTkdMRV9TVFJJUDoKICAgICAgICByZXR1cm4gaW5kZXhUcmlhbmdsZVN0cmlwKGdlb21ldHJ5KTsKICAgICAgY2FzZSBQcmltaXRpdmVUeXBlX2RlZmF1bHQuVFJJQU5HTEVTOgogICAgICAgIHJldHVybiBpbmRleFRyaWFuZ2xlcyhnZW9tZXRyeSk7CiAgICAgIGNhc2UgUHJpbWl0aXZlVHlwZV9kZWZhdWx0LkxJTkVfU1RSSVA6CiAgICAgICAgcmV0dXJuIGluZGV4TGluZVN0cmlwKGdlb21ldHJ5KTsKICAgICAgY2FzZSBQcmltaXRpdmVUeXBlX2RlZmF1bHQuTElORV9MT09QOgogICAgICAgIHJldHVybiBpbmRleExpbmVMb29wKGdlb21ldHJ5KTsKICAgICAgY2FzZSBQcmltaXRpdmVUeXBlX2RlZmF1bHQuTElORVM6CiAgICAgICAgcmV0dXJuIGluZGV4TGluZXMoZ2VvbWV0cnkpOwogICAgfQogICAgcmV0dXJuIGdlb21ldHJ5OwogIH0KICBmdW5jdGlvbiBvZmZzZXRQb2ludEZyb21YWlBsYW5lKHAsIGlzQmVoaW5kKSB7CiAgICBpZiAoTWF0aC5hYnMocC55KSA8IE1hdGhfZGVmYXVsdC5FUFNJTE9ONikgewogICAgICBpZiAoaXNCZWhpbmQpIHsKICAgICAgICBwLnkgPSAtTWF0aF9kZWZhdWx0LkVQU0lMT042OwogICAgICB9IGVsc2UgewogICAgICAgIHAueSA9IE1hdGhfZGVmYXVsdC5FUFNJTE9ONjsKICAgICAgfQogICAgfQogIH0KICBmdW5jdGlvbiBvZmZzZXRUcmlhbmdsZUZyb21YWlBsYW5lKHAwLCBwMSwgcDIpIHsKICAgIGlmIChwMC55ICE9PSAwICYmIHAxLnkgIT09IDAgJiYgcDIueSAhPT0gMCkgewogICAgICBvZmZzZXRQb2ludEZyb21YWlBsYW5lKHAwLCBwMC55IDwgMCk7CiAgICAgIG9mZnNldFBvaW50RnJvbVhaUGxhbmUocDEsIHAxLnkgPCAwKTsKICAgICAgb2Zmc2V0UG9pbnRGcm9tWFpQbGFuZShwMiwgcDIueSA8IDApOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBwMHkgPSBNYXRoLmFicyhwMC55KTsKICAgIGNvbnN0IHAxeSA9IE1hdGguYWJzKHAxLnkpOwogICAgY29uc3QgcDJ5ID0gTWF0aC5hYnMocDIueSk7CiAgICBsZXQgc2lnbjM7CiAgICBpZiAocDB5ID4gcDF5KSB7CiAgICAgIGlmIChwMHkgPiBwMnkpIHsKICAgICAgICBzaWduMyA9IE1hdGhfZGVmYXVsdC5zaWduKHAwLnkpOwogICAgICB9IGVsc2UgewogICAgICAgIHNpZ24zID0gTWF0aF9kZWZhdWx0LnNpZ24ocDIueSk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAocDF5ID4gcDJ5KSB7CiAgICAgIHNpZ24zID0gTWF0aF9kZWZhdWx0LnNpZ24ocDEueSk7CiAgICB9IGVsc2UgewogICAgICBzaWduMyA9IE1hdGhfZGVmYXVsdC5zaWduKHAyLnkpOwogICAgfQogICAgY29uc3QgaXNCZWhpbmQgPSBzaWduMyA8IDA7CiAgICBvZmZzZXRQb2ludEZyb21YWlBsYW5lKHAwLCBpc0JlaGluZCk7CiAgICBvZmZzZXRQb2ludEZyb21YWlBsYW5lKHAxLCBpc0JlaGluZCk7CiAgICBvZmZzZXRQb2ludEZyb21YWlBsYW5lKHAyLCBpc0JlaGluZCk7CiAgfQogIGZ1bmN0aW9uIGdldFhaSW50ZXJzZWN0aW9uT2Zmc2V0UG9pbnRzKHAsIHAxLCB1MTIsIHYxMikgewogICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZCgKICAgICAgcCwKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHAxLCBwLCBjMyksCiAgICAgICAgcC55IC8gKHAueSAtIHAxLnkpLAogICAgICAgIGMzCiAgICAgICksCiAgICAgIHUxMgogICAgKTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZSh1MTIsIHYxMik7CiAgICBvZmZzZXRQb2ludEZyb21YWlBsYW5lKHUxMiwgdHJ1ZSk7CiAgICBvZmZzZXRQb2ludEZyb21YWlBsYW5lKHYxMiwgZmFsc2UpOwogIH0KICBmdW5jdGlvbiBzcGxpdFRyaWFuZ2xlKHAwLCBwMSwgcDIpIHsKICAgIGlmIChwMC54ID49IDAgfHwgcDEueCA+PSAwIHx8IHAyLnggPj0gMCkgewogICAgICByZXR1cm4gdm9pZCAwOwogICAgfQogICAgb2Zmc2V0VHJpYW5nbGVGcm9tWFpQbGFuZShwMCwgcDEsIHAyKTsKICAgIGNvbnN0IHAwQmVoaW5kID0gcDAueSA8IDA7CiAgICBjb25zdCBwMUJlaGluZCA9IHAxLnkgPCAwOwogICAgY29uc3QgcDJCZWhpbmQgPSBwMi55IDwgMDsKICAgIGxldCBudW1CZWhpbmQgPSAwOwogICAgbnVtQmVoaW5kICs9IHAwQmVoaW5kID8gMSA6IDA7CiAgICBudW1CZWhpbmQgKz0gcDFCZWhpbmQgPyAxIDogMDsKICAgIG51bUJlaGluZCArPSBwMkJlaGluZCA/IDEgOiAwOwogICAgY29uc3QgaW5kaWNlcyA9IHNwbGl0VHJpYW5nbGVSZXN1bHQuaW5kaWNlczsKICAgIGlmIChudW1CZWhpbmQgPT09IDEpIHsKICAgICAgaW5kaWNlc1sxXSA9IDM7CiAgICAgIGluZGljZXNbMl0gPSA0OwogICAgICBpbmRpY2VzWzVdID0gNjsKICAgICAgaW5kaWNlc1s3XSA9IDY7CiAgICAgIGluZGljZXNbOF0gPSA1OwogICAgICBpZiAocDBCZWhpbmQpIHsKICAgICAgICBnZXRYWkludGVyc2VjdGlvbk9mZnNldFBvaW50cyhwMCwgcDEsIHUxLCBxMSk7CiAgICAgICAgZ2V0WFpJbnRlcnNlY3Rpb25PZmZzZXRQb2ludHMocDAsIHAyLCB1MiwgcTIpOwogICAgICAgIGluZGljZXNbMF0gPSAwOwogICAgICAgIGluZGljZXNbM10gPSAxOwogICAgICAgIGluZGljZXNbNF0gPSAyOwogICAgICAgIGluZGljZXNbNl0gPSAxOwogICAgICB9IGVsc2UgaWYgKHAxQmVoaW5kKSB7CiAgICAgICAgZ2V0WFpJbnRlcnNlY3Rpb25PZmZzZXRQb2ludHMocDEsIHAyLCB1MSwgcTEpOwogICAgICAgIGdldFhaSW50ZXJzZWN0aW9uT2Zmc2V0UG9pbnRzKHAxLCBwMCwgdTIsIHEyKTsKICAgICAgICBpbmRpY2VzWzBdID0gMTsKICAgICAgICBpbmRpY2VzWzNdID0gMjsKICAgICAgICBpbmRpY2VzWzRdID0gMDsKICAgICAgICBpbmRpY2VzWzZdID0gMjsKICAgICAgfSBlbHNlIGlmIChwMkJlaGluZCkgewogICAgICAgIGdldFhaSW50ZXJzZWN0aW9uT2Zmc2V0UG9pbnRzKHAyLCBwMCwgdTEsIHExKTsKICAgICAgICBnZXRYWkludGVyc2VjdGlvbk9mZnNldFBvaW50cyhwMiwgcDEsIHUyLCBxMik7CiAgICAgICAgaW5kaWNlc1swXSA9IDI7CiAgICAgICAgaW5kaWNlc1szXSA9IDA7CiAgICAgICAgaW5kaWNlc1s0XSA9IDE7CiAgICAgICAgaW5kaWNlc1s2XSA9IDA7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAobnVtQmVoaW5kID09PSAyKSB7CiAgICAgIGluZGljZXNbMl0gPSA0OwogICAgICBpbmRpY2VzWzRdID0gNDsKICAgICAgaW5kaWNlc1s1XSA9IDM7CiAgICAgIGluZGljZXNbN10gPSA1OwogICAgICBpbmRpY2VzWzhdID0gNjsKICAgICAgaWYgKCFwMEJlaGluZCkgewogICAgICAgIGdldFhaSW50ZXJzZWN0aW9uT2Zmc2V0UG9pbnRzKHAwLCBwMSwgdTEsIHExKTsKICAgICAgICBnZXRYWkludGVyc2VjdGlvbk9mZnNldFBvaW50cyhwMCwgcDIsIHUyLCBxMik7CiAgICAgICAgaW5kaWNlc1swXSA9IDE7CiAgICAgICAgaW5kaWNlc1sxXSA9IDI7CiAgICAgICAgaW5kaWNlc1szXSA9IDE7CiAgICAgICAgaW5kaWNlc1s2XSA9IDA7CiAgICAgIH0gZWxzZSBpZiAoIXAxQmVoaW5kKSB7CiAgICAgICAgZ2V0WFpJbnRlcnNlY3Rpb25PZmZzZXRQb2ludHMocDEsIHAyLCB1MSwgcTEpOwogICAgICAgIGdldFhaSW50ZXJzZWN0aW9uT2Zmc2V0UG9pbnRzKHAxLCBwMCwgdTIsIHEyKTsKICAgICAgICBpbmRpY2VzWzBdID0gMjsKICAgICAgICBpbmRpY2VzWzFdID0gMDsKICAgICAgICBpbmRpY2VzWzNdID0gMjsKICAgICAgICBpbmRpY2VzWzZdID0gMTsKICAgICAgfSBlbHNlIGlmICghcDJCZWhpbmQpIHsKICAgICAgICBnZXRYWkludGVyc2VjdGlvbk9mZnNldFBvaW50cyhwMiwgcDAsIHUxLCBxMSk7CiAgICAgICAgZ2V0WFpJbnRlcnNlY3Rpb25PZmZzZXRQb2ludHMocDIsIHAxLCB1MiwgcTIpOwogICAgICAgIGluZGljZXNbMF0gPSAwOwogICAgICAgIGluZGljZXNbMV0gPSAxOwogICAgICAgIGluZGljZXNbM10gPSAwOwogICAgICAgIGluZGljZXNbNl0gPSAyOwogICAgICB9CiAgICB9CiAgICBjb25zdCBwb3NpdGlvbnMgPSBzcGxpdFRyaWFuZ2xlUmVzdWx0LnBvc2l0aW9uczsKICAgIHBvc2l0aW9uc1swXSA9IHAwOwogICAgcG9zaXRpb25zWzFdID0gcDE7CiAgICBwb3NpdGlvbnNbMl0gPSBwMjsKICAgIHBvc2l0aW9ucy5sZW5ndGggPSAzOwogICAgaWYgKG51bUJlaGluZCA9PT0gMSB8fCBudW1CZWhpbmQgPT09IDIpIHsKICAgICAgcG9zaXRpb25zWzNdID0gdTE7CiAgICAgIHBvc2l0aW9uc1s0XSA9IHUyOwogICAgICBwb3NpdGlvbnNbNV0gPSBxMTsKICAgICAgcG9zaXRpb25zWzZdID0gcTI7CiAgICAgIHBvc2l0aW9ucy5sZW5ndGggPSA3OwogICAgfQogICAgcmV0dXJuIHNwbGl0VHJpYW5nbGVSZXN1bHQ7CiAgfQogIGZ1bmN0aW9uIHVwZGF0ZUdlb21ldHJ5QWZ0ZXJTcGxpdChnZW9tZXRyeSwgY29tcHV0ZUJvdW5kaW5nU3BoZXJlKSB7CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gZ2VvbWV0cnkuYXR0cmlidXRlczsKICAgIGlmIChhdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIHZvaWQgMDsKICAgIH0KICAgIGZvciAoY29uc3QgcHJvcGVydHkgaW4gYXR0cmlidXRlcykgewogICAgICBpZiAoYXR0cmlidXRlcy5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkgJiYgZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXNbcHJvcGVydHldKSAmJiBkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlc1twcm9wZXJ0eV0udmFsdWVzKSkgewogICAgICAgIGNvbnN0IGF0dHJpYnV0ZSA9IGF0dHJpYnV0ZXNbcHJvcGVydHldOwogICAgICAgIGF0dHJpYnV0ZS52YWx1ZXMgPSBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgICAgICBhdHRyaWJ1dGUuY29tcG9uZW50RGF0YXR5cGUsCiAgICAgICAgICBhdHRyaWJ1dGUudmFsdWVzCiAgICAgICAgKTsKICAgICAgfQogICAgfQogICAgY29uc3QgbnVtYmVyT2ZWZXJ0aWNlcyA9IEdlb21ldHJ5X2RlZmF1bHQuY29tcHV0ZU51bWJlck9mVmVydGljZXMoZ2VvbWV0cnkpOwogICAgZ2VvbWV0cnkuaW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KAogICAgICBudW1iZXJPZlZlcnRpY2VzLAogICAgICBnZW9tZXRyeS5pbmRpY2VzCiAgICApOwogICAgaWYgKGNvbXB1dGVCb3VuZGluZ1NwaGVyZSkgewogICAgICBnZW9tZXRyeS5ib3VuZGluZ1NwaGVyZSA9IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbVZlcnRpY2VzKAogICAgICAgIGF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzCiAgICAgICk7CiAgICB9CiAgICByZXR1cm4gZ2VvbWV0cnk7CiAgfQogIGZ1bmN0aW9uIGNvcHlHZW9tZXRyeUZvclNwbGl0KGdlb21ldHJ5KSB7CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gZ2VvbWV0cnkuYXR0cmlidXRlczsKICAgIGNvbnN0IGNvcGllZEF0dHJpYnV0ZXMgPSB7fTsKICAgIGZvciAoY29uc3QgcHJvcGVydHkgaW4gYXR0cmlidXRlcykgewogICAgICBpZiAoYXR0cmlidXRlcy5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkgJiYgZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXNbcHJvcGVydHldKSAmJiBkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlc1twcm9wZXJ0eV0udmFsdWVzKSkgewogICAgICAgIGNvbnN0IGF0dHJpYnV0ZSA9IGF0dHJpYnV0ZXNbcHJvcGVydHldOwogICAgICAgIGNvcGllZEF0dHJpYnV0ZXNbcHJvcGVydHldID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IGF0dHJpYnV0ZS5jb21wb25lbnREYXRhdHlwZSwKICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IGF0dHJpYnV0ZS5jb21wb25lbnRzUGVyQXR0cmlidXRlLAogICAgICAgICAgbm9ybWFsaXplOiBhdHRyaWJ1dGUubm9ybWFsaXplLAogICAgICAgICAgdmFsdWVzOiBbXQogICAgICAgIH0pOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICBhdHRyaWJ1dGVzOiBjb3BpZWRBdHRyaWJ1dGVzLAogICAgICBpbmRpY2VzOiBbXSwKICAgICAgcHJpbWl0aXZlVHlwZTogZ2VvbWV0cnkucHJpbWl0aXZlVHlwZQogICAgfSk7CiAgfQogIGZ1bmN0aW9uIHVwZGF0ZUluc3RhbmNlQWZ0ZXJTcGxpdChpbnN0YW5jZSwgd2VzdEdlb21ldHJ5LCBlYXN0R2VvbWV0cnkpIHsKICAgIGNvbnN0IGNvbXB1dGVCb3VuZGluZ1NwaGVyZSA9IGRlZmluZWRfZGVmYXVsdChpbnN0YW5jZS5nZW9tZXRyeS5ib3VuZGluZ1NwaGVyZSk7CiAgICB3ZXN0R2VvbWV0cnkgPSB1cGRhdGVHZW9tZXRyeUFmdGVyU3BsaXQod2VzdEdlb21ldHJ5LCBjb21wdXRlQm91bmRpbmdTcGhlcmUpOwogICAgZWFzdEdlb21ldHJ5ID0gdXBkYXRlR2VvbWV0cnlBZnRlclNwbGl0KGVhc3RHZW9tZXRyeSwgY29tcHV0ZUJvdW5kaW5nU3BoZXJlKTsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZWFzdEdlb21ldHJ5KSAmJiAhZGVmaW5lZF9kZWZhdWx0KHdlc3RHZW9tZXRyeSkpIHsKICAgICAgaW5zdGFuY2UuZ2VvbWV0cnkgPSBlYXN0R2VvbWV0cnk7CiAgICB9IGVsc2UgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZWFzdEdlb21ldHJ5KSAmJiBkZWZpbmVkX2RlZmF1bHQod2VzdEdlb21ldHJ5KSkgewogICAgICBpbnN0YW5jZS5nZW9tZXRyeSA9IHdlc3RHZW9tZXRyeTsKICAgIH0gZWxzZSB7CiAgICAgIGluc3RhbmNlLndlc3RIZW1pc3BoZXJlR2VvbWV0cnkgPSB3ZXN0R2VvbWV0cnk7CiAgICAgIGluc3RhbmNlLmVhc3RIZW1pc3BoZXJlR2VvbWV0cnkgPSBlYXN0R2VvbWV0cnk7CiAgICAgIGluc3RhbmNlLmdlb21ldHJ5ID0gdm9pZCAwOwogICAgfQogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZUJhcnljZW50cmljSW50ZXJwb2xhdGVGdW5jdGlvbihDYXJ0ZXNpYW5UeXBlLCBudW1iZXJPZkNvbXBvbmVudHMpIHsKICAgIGNvbnN0IHYwU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW5UeXBlKCk7CiAgICBjb25zdCB2MVNjcmF0Y2gyID0gbmV3IENhcnRlc2lhblR5cGUoKTsKICAgIGNvbnN0IHYyU2NyYXRjaDIgPSBuZXcgQ2FydGVzaWFuVHlwZSgpOwogICAgcmV0dXJuIGZ1bmN0aW9uKGkwLCBpMSwgaTIsIGNvb3Jkcywgc291cmNlVmFsdWVzLCBjdXJyZW50VmFsdWVzLCBpbnNlcnRlZEluZGV4LCBub3JtYWxpemUpIHsKICAgICAgY29uc3QgdjAyID0gQ2FydGVzaWFuVHlwZS5mcm9tQXJyYXkoCiAgICAgICAgc291cmNlVmFsdWVzLAogICAgICAgIGkwICogbnVtYmVyT2ZDb21wb25lbnRzLAogICAgICAgIHYwU2NyYXRjaAogICAgICApOwogICAgICBjb25zdCB2MTIgPSBDYXJ0ZXNpYW5UeXBlLmZyb21BcnJheSgKICAgICAgICBzb3VyY2VWYWx1ZXMsCiAgICAgICAgaTEgKiBudW1iZXJPZkNvbXBvbmVudHMsCiAgICAgICAgdjFTY3JhdGNoMgogICAgICApOwogICAgICBjb25zdCB2MjIgPSBDYXJ0ZXNpYW5UeXBlLmZyb21BcnJheSgKICAgICAgICBzb3VyY2VWYWx1ZXMsCiAgICAgICAgaTIgKiBudW1iZXJPZkNvbXBvbmVudHMsCiAgICAgICAgdjJTY3JhdGNoMgogICAgICApOwogICAgICBDYXJ0ZXNpYW5UeXBlLm11bHRpcGx5QnlTY2FsYXIodjAyLCBjb29yZHMueCwgdjAyKTsKICAgICAgQ2FydGVzaWFuVHlwZS5tdWx0aXBseUJ5U2NhbGFyKHYxMiwgY29vcmRzLnksIHYxMik7CiAgICAgIENhcnRlc2lhblR5cGUubXVsdGlwbHlCeVNjYWxhcih2MjIsIGNvb3Jkcy56LCB2MjIpOwogICAgICBjb25zdCB2YWx1ZSA9IENhcnRlc2lhblR5cGUuYWRkKHYwMiwgdjEyLCB2MDIpOwogICAgICBDYXJ0ZXNpYW5UeXBlLmFkZCh2YWx1ZSwgdjIyLCB2YWx1ZSk7CiAgICAgIGlmIChub3JtYWxpemUpIHsKICAgICAgICBDYXJ0ZXNpYW5UeXBlLm5vcm1hbGl6ZSh2YWx1ZSwgdmFsdWUpOwogICAgICB9CiAgICAgIENhcnRlc2lhblR5cGUucGFjaygKICAgICAgICB2YWx1ZSwKICAgICAgICBjdXJyZW50VmFsdWVzLAogICAgICAgIGluc2VydGVkSW5kZXggKiBudW1iZXJPZkNvbXBvbmVudHMKICAgICAgKTsKICAgIH07CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVUcmlhbmdsZUF0dHJpYnV0ZXMoaTAsIGkxLCBpMiwgcG9pbnQsIHBvc2l0aW9ucywgbm9ybWFscywgdGFuZ2VudHMsIGJpdGFuZ2VudHMsIHRleENvb3JkcywgZXh0cnVkZURpcmVjdGlvbnMsIGFwcGx5T2Zmc2V0LCBjdXJyZW50QXR0cmlidXRlcywgY3VzdG9tQXR0cmlidXRlTmFtZXMsIGN1c3RvbUF0dHJpYnV0ZXNMZW5ndGgsIGFsbEF0dHJpYnV0ZXMsIGluc2VydGVkSW5kZXgpIHsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG5vcm1hbHMpICYmICFkZWZpbmVkX2RlZmF1bHQodGFuZ2VudHMpICYmICFkZWZpbmVkX2RlZmF1bHQoYml0YW5nZW50cykgJiYgIWRlZmluZWRfZGVmYXVsdCh0ZXhDb29yZHMpICYmICFkZWZpbmVkX2RlZmF1bHQoZXh0cnVkZURpcmVjdGlvbnMpICYmIGN1c3RvbUF0dHJpYnV0ZXNMZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgcDAgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHBvc2l0aW9ucywgaTAgKiAzLCBwMFNjcmF0Y2gpOwogICAgY29uc3QgcDEgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHBvc2l0aW9ucywgaTEgKiAzLCBwMVNjcmF0Y2gpOwogICAgY29uc3QgcDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHBvc2l0aW9ucywgaTIgKiAzLCBwMlNjcmF0Y2gpOwogICAgY29uc3QgY29vcmRzID0gYmFyeWNlbnRyaWNDb29yZGluYXRlc19kZWZhdWx0KHBvaW50LCBwMCwgcDEsIHAyLCBiYXJ5Y2VudHJpY1NjcmF0Y2gpOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoY29vcmRzKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG5vcm1hbHMpKSB7CiAgICAgIGludGVycG9sYXRlQW5kUGFja0NhcnRlc2lhbjMoCiAgICAgICAgaTAsCiAgICAgICAgaTEsCiAgICAgICAgaTIsCiAgICAgICAgY29vcmRzLAogICAgICAgIG5vcm1hbHMsCiAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMubm9ybWFsLnZhbHVlcywKICAgICAgICBpbnNlcnRlZEluZGV4LAogICAgICAgIHRydWUKICAgICAgKTsKICAgIH0KICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZXh0cnVkZURpcmVjdGlvbnMpKSB7CiAgICAgIGNvbnN0IGQwID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShleHRydWRlRGlyZWN0aW9ucywgaTAgKiAzLCBwMFNjcmF0Y2gpOwogICAgICBjb25zdCBkMSA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoZXh0cnVkZURpcmVjdGlvbnMsIGkxICogMywgcDFTY3JhdGNoKTsKICAgICAgY29uc3QgZDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KGV4dHJ1ZGVEaXJlY3Rpb25zLCBpMiAqIDMsIHAyU2NyYXRjaCk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGQwLCBjb29yZHMueCwgZDApOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihkMSwgY29vcmRzLnksIGQxKTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoZDIsIGNvb3Jkcy56LCBkMik7CiAgICAgIGxldCBkaXJlY3Rpb24yOwogICAgICBpZiAoIUNhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHMoZDAsIENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPKSB8fCAhQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFscyhkMSwgQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8pIHx8ICFDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzKGQyLCBDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTykpIHsKICAgICAgICBkaXJlY3Rpb24yID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZChkMCwgZDEsIGQwKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGRpcmVjdGlvbjIsIGQyLCBkaXJlY3Rpb24yKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGRpcmVjdGlvbjIsIGRpcmVjdGlvbjIpOwogICAgICB9IGVsc2UgewogICAgICAgIGRpcmVjdGlvbjIgPSBwMFNjcmF0Y2g7CiAgICAgICAgZGlyZWN0aW9uMi54ID0gMDsKICAgICAgICBkaXJlY3Rpb24yLnkgPSAwOwogICAgICAgIGRpcmVjdGlvbjIueiA9IDA7CiAgICAgIH0KICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soCiAgICAgICAgZGlyZWN0aW9uMiwKICAgICAgICBjdXJyZW50QXR0cmlidXRlcy5leHRydWRlRGlyZWN0aW9uLnZhbHVlcywKICAgICAgICBpbnNlcnRlZEluZGV4ICogMwogICAgICApOwogICAgfQogICAgaWYgKGRlZmluZWRfZGVmYXVsdChhcHBseU9mZnNldCkpIHsKICAgICAgaW50ZXJwb2xhdGVBbmRQYWNrQm9vbGVhbigKICAgICAgICBpMCwKICAgICAgICBpMSwKICAgICAgICBpMiwKICAgICAgICBjb29yZHMsCiAgICAgICAgYXBwbHlPZmZzZXQsCiAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMuYXBwbHlPZmZzZXQudmFsdWVzLAogICAgICAgIGluc2VydGVkSW5kZXgKICAgICAgKTsKICAgIH0KICAgIGlmIChkZWZpbmVkX2RlZmF1bHQodGFuZ2VudHMpKSB7CiAgICAgIGludGVycG9sYXRlQW5kUGFja0NhcnRlc2lhbjMoCiAgICAgICAgaTAsCiAgICAgICAgaTEsCiAgICAgICAgaTIsCiAgICAgICAgY29vcmRzLAogICAgICAgIHRhbmdlbnRzLAogICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzLnRhbmdlbnQudmFsdWVzLAogICAgICAgIGluc2VydGVkSW5kZXgsCiAgICAgICAgdHJ1ZQogICAgICApOwogICAgfQogICAgaWYgKGRlZmluZWRfZGVmYXVsdChiaXRhbmdlbnRzKSkgewogICAgICBpbnRlcnBvbGF0ZUFuZFBhY2tDYXJ0ZXNpYW4zKAogICAgICAgIGkwLAogICAgICAgIGkxLAogICAgICAgIGkyLAogICAgICAgIGNvb3JkcywKICAgICAgICBiaXRhbmdlbnRzLAogICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzLmJpdGFuZ2VudC52YWx1ZXMsCiAgICAgICAgaW5zZXJ0ZWRJbmRleCwKICAgICAgICB0cnVlCiAgICAgICk7CiAgICB9CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHRleENvb3JkcykpIHsKICAgICAgaW50ZXJwb2xhdGVBbmRQYWNrQ2FydGVzaWFuMigKICAgICAgICBpMCwKICAgICAgICBpMSwKICAgICAgICBpMiwKICAgICAgICBjb29yZHMsCiAgICAgICAgdGV4Q29vcmRzLAogICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzLnN0LnZhbHVlcywKICAgICAgICBpbnNlcnRlZEluZGV4CiAgICAgICk7CiAgICB9CiAgICBpZiAoY3VzdG9tQXR0cmlidXRlc0xlbmd0aCA+IDApIHsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjdXN0b21BdHRyaWJ1dGVzTGVuZ3RoOyBpKyspIHsKICAgICAgICBjb25zdCBhdHRyaWJ1dGVOYW1lID0gY3VzdG9tQXR0cmlidXRlTmFtZXNbaV07CiAgICAgICAgZ2VuZXJpY0ludGVycG9sYXRlKAogICAgICAgICAgaTAsCiAgICAgICAgICBpMSwKICAgICAgICAgIGkyLAogICAgICAgICAgY29vcmRzLAogICAgICAgICAgaW5zZXJ0ZWRJbmRleCwKICAgICAgICAgIGFsbEF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0sCiAgICAgICAgICBjdXJyZW50QXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXQogICAgICAgICk7CiAgICAgIH0KICAgIH0KICB9CiAgZnVuY3Rpb24gZ2VuZXJpY0ludGVycG9sYXRlKGkwLCBpMSwgaTIsIGNvb3JkcywgaW5zZXJ0ZWRJbmRleCwgc291cmNlQXR0cmlidXRlLCBjdXJyZW50QXR0cmlidXRlKSB7CiAgICBjb25zdCBjb21wb25lbnRzUGVyQXR0cmlidXRlID0gc291cmNlQXR0cmlidXRlLmNvbXBvbmVudHNQZXJBdHRyaWJ1dGU7CiAgICBjb25zdCBzb3VyY2VWYWx1ZXMgPSBzb3VyY2VBdHRyaWJ1dGUudmFsdWVzOwogICAgY29uc3QgY3VycmVudFZhbHVlcyA9IGN1cnJlbnRBdHRyaWJ1dGUudmFsdWVzOwogICAgc3dpdGNoIChjb21wb25lbnRzUGVyQXR0cmlidXRlKSB7CiAgICAgIGNhc2UgNDoKICAgICAgICBpbnRlcnBvbGF0ZUFuZFBhY2tDYXJ0ZXNpYW40KAogICAgICAgICAgaTAsCiAgICAgICAgICBpMSwKICAgICAgICAgIGkyLAogICAgICAgICAgY29vcmRzLAogICAgICAgICAgc291cmNlVmFsdWVzLAogICAgICAgICAgY3VycmVudFZhbHVlcywKICAgICAgICAgIGluc2VydGVkSW5kZXgsCiAgICAgICAgICBmYWxzZQogICAgICAgICk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMzoKICAgICAgICBpbnRlcnBvbGF0ZUFuZFBhY2tDYXJ0ZXNpYW4zKAogICAgICAgICAgaTAsCiAgICAgICAgICBpMSwKICAgICAgICAgIGkyLAogICAgICAgICAgY29vcmRzLAogICAgICAgICAgc291cmNlVmFsdWVzLAogICAgICAgICAgY3VycmVudFZhbHVlcywKICAgICAgICAgIGluc2VydGVkSW5kZXgsCiAgICAgICAgICBmYWxzZQogICAgICAgICk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMjoKICAgICAgICBpbnRlcnBvbGF0ZUFuZFBhY2tDYXJ0ZXNpYW4yKAogICAgICAgICAgaTAsCiAgICAgICAgICBpMSwKICAgICAgICAgIGkyLAogICAgICAgICAgY29vcmRzLAogICAgICAgICAgc291cmNlVmFsdWVzLAogICAgICAgICAgY3VycmVudFZhbHVlcywKICAgICAgICAgIGluc2VydGVkSW5kZXgsCiAgICAgICAgICBmYWxzZQogICAgICAgICk7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgY3VycmVudFZhbHVlc1tpbnNlcnRlZEluZGV4XSA9IHNvdXJjZVZhbHVlc1tpMF0gKiBjb29yZHMueCArIHNvdXJjZVZhbHVlc1tpMV0gKiBjb29yZHMueSArIHNvdXJjZVZhbHVlc1tpMl0gKiBjb29yZHMuejsKICAgIH0KICB9CiAgZnVuY3Rpb24gaW5zZXJ0U3BsaXRQb2ludChjdXJyZW50QXR0cmlidXRlcywgY3VycmVudEluZGljZXMsIGN1cnJlbnRJbmRleE1hcCwgaW5kaWNlcywgY3VycmVudEluZGV4LCBwb2ludCkgewogICAgY29uc3QgaW5zZXJ0SW5kZXggPSBjdXJyZW50QXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMubGVuZ3RoIC8gMzsKICAgIGlmIChjdXJyZW50SW5kZXggIT09IC0xKSB7CiAgICAgIGNvbnN0IHByZXZJbmRleCA9IGluZGljZXNbY3VycmVudEluZGV4XTsKICAgICAgY29uc3QgbmV3SW5kZXggPSBjdXJyZW50SW5kZXhNYXBbcHJldkluZGV4XTsKICAgICAgaWYgKG5ld0luZGV4ID09PSAtMSkgewogICAgICAgIGN1cnJlbnRJbmRleE1hcFtwcmV2SW5kZXhdID0gaW5zZXJ0SW5kZXg7CiAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLnB1c2gocG9pbnQueCwgcG9pbnQueSwgcG9pbnQueik7CiAgICAgICAgY3VycmVudEluZGljZXMucHVzaChpbnNlcnRJbmRleCk7CiAgICAgICAgcmV0dXJuIGluc2VydEluZGV4OwogICAgICB9CiAgICAgIGN1cnJlbnRJbmRpY2VzLnB1c2gobmV3SW5kZXgpOwogICAgICByZXR1cm4gbmV3SW5kZXg7CiAgICB9CiAgICBjdXJyZW50QXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMucHVzaChwb2ludC54LCBwb2ludC55LCBwb2ludC56KTsKICAgIGN1cnJlbnRJbmRpY2VzLnB1c2goaW5zZXJ0SW5kZXgpOwogICAgcmV0dXJuIGluc2VydEluZGV4OwogIH0KICBmdW5jdGlvbiBzcGxpdExvbmdpdHVkZVRyaWFuZ2xlcyhpbnN0YW5jZSkgewogICAgY29uc3QgZ2VvbWV0cnkgPSBpbnN0YW5jZS5nZW9tZXRyeTsKICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBnZW9tZXRyeS5hdHRyaWJ1dGVzOwogICAgY29uc3QgcG9zaXRpb25zID0gYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXM7CiAgICBjb25zdCBub3JtYWxzID0gZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXMubm9ybWFsKSA/IGF0dHJpYnV0ZXMubm9ybWFsLnZhbHVlcyA6IHZvaWQgMDsKICAgIGNvbnN0IGJpdGFuZ2VudHMgPSBkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlcy5iaXRhbmdlbnQpID8gYXR0cmlidXRlcy5iaXRhbmdlbnQudmFsdWVzIDogdm9pZCAwOwogICAgY29uc3QgdGFuZ2VudHMgPSBkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlcy50YW5nZW50KSA/IGF0dHJpYnV0ZXMudGFuZ2VudC52YWx1ZXMgOiB2b2lkIDA7CiAgICBjb25zdCB0ZXhDb29yZHMgPSBkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlcy5zdCkgPyBhdHRyaWJ1dGVzLnN0LnZhbHVlcyA6IHZvaWQgMDsKICAgIGNvbnN0IGV4dHJ1ZGVEaXJlY3Rpb25zID0gZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXMuZXh0cnVkZURpcmVjdGlvbikgPyBhdHRyaWJ1dGVzLmV4dHJ1ZGVEaXJlY3Rpb24udmFsdWVzIDogdm9pZCAwOwogICAgY29uc3QgYXBwbHlPZmZzZXQgPSBkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlcy5hcHBseU9mZnNldCkgPyBhdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0LnZhbHVlcyA6IHZvaWQgMDsKICAgIGNvbnN0IGluZGljZXMgPSBnZW9tZXRyeS5pbmRpY2VzOwogICAgY29uc3QgY3VzdG9tQXR0cmlidXRlTmFtZXMgPSBbXTsKICAgIGZvciAoY29uc3QgYXR0cmlidXRlTmFtZSBpbiBhdHRyaWJ1dGVzKSB7CiAgICAgIGlmIChhdHRyaWJ1dGVzLmhhc093blByb3BlcnR5KGF0dHJpYnV0ZU5hbWUpICYmICFOQU1FRF9BVFRSSUJVVEVTW2F0dHJpYnV0ZU5hbWVdICYmIGRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdKSkgewogICAgICAgIGN1c3RvbUF0dHJpYnV0ZU5hbWVzLnB1c2goYXR0cmlidXRlTmFtZSk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGN1c3RvbUF0dHJpYnV0ZXNMZW5ndGggPSBjdXN0b21BdHRyaWJ1dGVOYW1lcy5sZW5ndGg7CiAgICBjb25zdCBlYXN0R2VvbWV0cnkgPSBjb3B5R2VvbWV0cnlGb3JTcGxpdChnZW9tZXRyeSk7CiAgICBjb25zdCB3ZXN0R2VvbWV0cnkgPSBjb3B5R2VvbWV0cnlGb3JTcGxpdChnZW9tZXRyeSk7CiAgICBsZXQgY3VycmVudEF0dHJpYnV0ZXM7CiAgICBsZXQgY3VycmVudEluZGljZXM7CiAgICBsZXQgY3VycmVudEluZGV4TWFwOwogICAgbGV0IGluc2VydGVkSW5kZXg7CiAgICBsZXQgaTsKICAgIGNvbnN0IHdlc3RHZW9tZXRyeUluZGV4TWFwID0gW107CiAgICB3ZXN0R2VvbWV0cnlJbmRleE1hcC5sZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoIC8gMzsKICAgIGNvbnN0IGVhc3RHZW9tZXRyeUluZGV4TWFwID0gW107CiAgICBlYXN0R2VvbWV0cnlJbmRleE1hcC5sZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoIC8gMzsKICAgIGZvciAoaSA9IDA7IGkgPCB3ZXN0R2VvbWV0cnlJbmRleE1hcC5sZW5ndGg7ICsraSkgewogICAgICB3ZXN0R2VvbWV0cnlJbmRleE1hcFtpXSA9IC0xOwogICAgICBlYXN0R2VvbWV0cnlJbmRleE1hcFtpXSA9IC0xOwogICAgfQogICAgY29uc3QgbGVuID0gaW5kaWNlcy5sZW5ndGg7CiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpICs9IDMpIHsKICAgICAgY29uc3QgaTAgPSBpbmRpY2VzW2ldOwogICAgICBjb25zdCBpMSA9IGluZGljZXNbaSArIDFdOwogICAgICBjb25zdCBpMiA9IGluZGljZXNbaSArIDJdOwogICAgICBsZXQgcDAgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHBvc2l0aW9ucywgaTAgKiAzKTsKICAgICAgbGV0IHAxID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIGkxICogMyk7CiAgICAgIGxldCBwMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkocG9zaXRpb25zLCBpMiAqIDMpOwogICAgICBjb25zdCByZXN1bHQgPSBzcGxpdFRyaWFuZ2xlKHAwLCBwMSwgcDIpOwogICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkgJiYgcmVzdWx0LnBvc2l0aW9ucy5sZW5ndGggPiAzKSB7CiAgICAgICAgY29uc3QgcmVzdWx0UG9zaXRpb25zID0gcmVzdWx0LnBvc2l0aW9uczsKICAgICAgICBjb25zdCByZXN1bHRJbmRpY2VzID0gcmVzdWx0LmluZGljZXM7CiAgICAgICAgY29uc3QgcmVzdWx0TGVuZ3RoID0gcmVzdWx0SW5kaWNlcy5sZW5ndGg7CiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCByZXN1bHRMZW5ndGg7ICsraikgewogICAgICAgICAgY29uc3QgcmVzdWx0SW5kZXggPSByZXN1bHRJbmRpY2VzW2pdOwogICAgICAgICAgY29uc3QgcG9pbnQgPSByZXN1bHRQb3NpdGlvbnNbcmVzdWx0SW5kZXhdOwogICAgICAgICAgaWYgKHBvaW50LnkgPCAwKSB7CiAgICAgICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzID0gd2VzdEdlb21ldHJ5LmF0dHJpYnV0ZXM7CiAgICAgICAgICAgIGN1cnJlbnRJbmRpY2VzID0gd2VzdEdlb21ldHJ5LmluZGljZXM7CiAgICAgICAgICAgIGN1cnJlbnRJbmRleE1hcCA9IHdlc3RHZW9tZXRyeUluZGV4TWFwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMgPSBlYXN0R2VvbWV0cnkuYXR0cmlidXRlczsKICAgICAgICAgICAgY3VycmVudEluZGljZXMgPSBlYXN0R2VvbWV0cnkuaW5kaWNlczsKICAgICAgICAgICAgY3VycmVudEluZGV4TWFwID0gZWFzdEdlb21ldHJ5SW5kZXhNYXA7CiAgICAgICAgICB9CiAgICAgICAgICBpbnNlcnRlZEluZGV4ID0gaW5zZXJ0U3BsaXRQb2ludCgKICAgICAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMsCiAgICAgICAgICAgIGN1cnJlbnRJbmRpY2VzLAogICAgICAgICAgICBjdXJyZW50SW5kZXhNYXAsCiAgICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICAgIHJlc3VsdEluZGV4IDwgMyA/IGkgKyByZXN1bHRJbmRleCA6IC0xLAogICAgICAgICAgICBwb2ludAogICAgICAgICAgKTsKICAgICAgICAgIGNvbXB1dGVUcmlhbmdsZUF0dHJpYnV0ZXMoCiAgICAgICAgICAgIGkwLAogICAgICAgICAgICBpMSwKICAgICAgICAgICAgaTIsCiAgICAgICAgICAgIHBvaW50LAogICAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICAgIG5vcm1hbHMsCiAgICAgICAgICAgIHRhbmdlbnRzLAogICAgICAgICAgICBiaXRhbmdlbnRzLAogICAgICAgICAgICB0ZXhDb29yZHMsCiAgICAgICAgICAgIGV4dHJ1ZGVEaXJlY3Rpb25zLAogICAgICAgICAgICBhcHBseU9mZnNldCwKICAgICAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMsCiAgICAgICAgICAgIGN1c3RvbUF0dHJpYnV0ZU5hbWVzLAogICAgICAgICAgICBjdXN0b21BdHRyaWJ1dGVzTGVuZ3RoLAogICAgICAgICAgICBhdHRyaWJ1dGVzLAogICAgICAgICAgICBpbnNlcnRlZEluZGV4CiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHAwID0gcmVzdWx0LnBvc2l0aW9uc1swXTsKICAgICAgICAgIHAxID0gcmVzdWx0LnBvc2l0aW9uc1sxXTsKICAgICAgICAgIHAyID0gcmVzdWx0LnBvc2l0aW9uc1syXTsKICAgICAgICB9CiAgICAgICAgaWYgKHAwLnkgPCAwKSB7CiAgICAgICAgICBjdXJyZW50QXR0cmlidXRlcyA9IHdlc3RHZW9tZXRyeS5hdHRyaWJ1dGVzOwogICAgICAgICAgY3VycmVudEluZGljZXMgPSB3ZXN0R2VvbWV0cnkuaW5kaWNlczsKICAgICAgICAgIGN1cnJlbnRJbmRleE1hcCA9IHdlc3RHZW9tZXRyeUluZGV4TWFwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjdXJyZW50QXR0cmlidXRlcyA9IGVhc3RHZW9tZXRyeS5hdHRyaWJ1dGVzOwogICAgICAgICAgY3VycmVudEluZGljZXMgPSBlYXN0R2VvbWV0cnkuaW5kaWNlczsKICAgICAgICAgIGN1cnJlbnRJbmRleE1hcCA9IGVhc3RHZW9tZXRyeUluZGV4TWFwOwogICAgICAgIH0KICAgICAgICBpbnNlcnRlZEluZGV4ID0gaW5zZXJ0U3BsaXRQb2ludCgKICAgICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzLAogICAgICAgICAgY3VycmVudEluZGljZXMsCiAgICAgICAgICBjdXJyZW50SW5kZXhNYXAsCiAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgaSwKICAgICAgICAgIHAwCiAgICAgICAgKTsKICAgICAgICBjb21wdXRlVHJpYW5nbGVBdHRyaWJ1dGVzKAogICAgICAgICAgaTAsCiAgICAgICAgICBpMSwKICAgICAgICAgIGkyLAogICAgICAgICAgcDAsCiAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICBub3JtYWxzLAogICAgICAgICAgdGFuZ2VudHMsCiAgICAgICAgICBiaXRhbmdlbnRzLAogICAgICAgICAgdGV4Q29vcmRzLAogICAgICAgICAgZXh0cnVkZURpcmVjdGlvbnMsCiAgICAgICAgICBhcHBseU9mZnNldCwKICAgICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzLAogICAgICAgICAgY3VzdG9tQXR0cmlidXRlTmFtZXMsCiAgICAgICAgICBjdXN0b21BdHRyaWJ1dGVzTGVuZ3RoLAogICAgICAgICAgYXR0cmlidXRlcywKICAgICAgICAgIGluc2VydGVkSW5kZXgKICAgICAgICApOwogICAgICAgIGluc2VydGVkSW5kZXggPSBpbnNlcnRTcGxpdFBvaW50KAogICAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMsCiAgICAgICAgICBjdXJyZW50SW5kaWNlcywKICAgICAgICAgIGN1cnJlbnRJbmRleE1hcCwKICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICBpICsgMSwKICAgICAgICAgIHAxCiAgICAgICAgKTsKICAgICAgICBjb21wdXRlVHJpYW5nbGVBdHRyaWJ1dGVzKAogICAgICAgICAgaTAsCiAgICAgICAgICBpMSwKICAgICAgICAgIGkyLAogICAgICAgICAgcDEsCiAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICBub3JtYWxzLAogICAgICAgICAgdGFuZ2VudHMsCiAgICAgICAgICBiaXRhbmdlbnRzLAogICAgICAgICAgdGV4Q29vcmRzLAogICAgICAgICAgZXh0cnVkZURpcmVjdGlvbnMsCiAgICAgICAgICBhcHBseU9mZnNldCwKICAgICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzLAogICAgICAgICAgY3VzdG9tQXR0cmlidXRlTmFtZXMsCiAgICAgICAgICBjdXN0b21BdHRyaWJ1dGVzTGVuZ3RoLAogICAgICAgICAgYXR0cmlidXRlcywKICAgICAgICAgIGluc2VydGVkSW5kZXgKICAgICAgICApOwogICAgICAgIGluc2VydGVkSW5kZXggPSBpbnNlcnRTcGxpdFBvaW50KAogICAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMsCiAgICAgICAgICBjdXJyZW50SW5kaWNlcywKICAgICAgICAgIGN1cnJlbnRJbmRleE1hcCwKICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICBpICsgMiwKICAgICAgICAgIHAyCiAgICAgICAgKTsKICAgICAgICBjb21wdXRlVHJpYW5nbGVBdHRyaWJ1dGVzKAogICAgICAgICAgaTAsCiAgICAgICAgICBpMSwKICAgICAgICAgIGkyLAogICAgICAgICAgcDIsCiAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICBub3JtYWxzLAogICAgICAgICAgdGFuZ2VudHMsCiAgICAgICAgICBiaXRhbmdlbnRzLAogICAgICAgICAgdGV4Q29vcmRzLAogICAgICAgICAgZXh0cnVkZURpcmVjdGlvbnMsCiAgICAgICAgICBhcHBseU9mZnNldCwKICAgICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzLAogICAgICAgICAgY3VzdG9tQXR0cmlidXRlTmFtZXMsCiAgICAgICAgICBjdXN0b21BdHRyaWJ1dGVzTGVuZ3RoLAogICAgICAgICAgYXR0cmlidXRlcywKICAgICAgICAgIGluc2VydGVkSW5kZXgKICAgICAgICApOwogICAgICB9CiAgICB9CiAgICB1cGRhdGVJbnN0YW5jZUFmdGVyU3BsaXQoaW5zdGFuY2UsIHdlc3RHZW9tZXRyeSwgZWFzdEdlb21ldHJ5KTsKICB9CiAgZnVuY3Rpb24gY29tcHV0ZUxpbmVBdHRyaWJ1dGVzKGkwLCBpMSwgcG9pbnQsIHBvc2l0aW9ucywgaW5zZXJ0SW5kZXgsIGN1cnJlbnRBdHRyaWJ1dGVzLCBhcHBseU9mZnNldCkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYXBwbHlPZmZzZXQpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHAwID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIGkwICogMywgcDBTY3JhdGNoKTsKICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihwMCwgcG9pbnQsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTApKSB7CiAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0LnZhbHVlc1tpbnNlcnRJbmRleF0gPSBhcHBseU9mZnNldFtpMF07CiAgICB9IGVsc2UgewogICAgICBjdXJyZW50QXR0cmlidXRlcy5hcHBseU9mZnNldC52YWx1ZXNbaW5zZXJ0SW5kZXhdID0gYXBwbHlPZmZzZXRbaTFdOwogICAgfQogIH0KICBmdW5jdGlvbiBzcGxpdExvbmdpdHVkZUxpbmVzKGluc3RhbmNlKSB7CiAgICBjb25zdCBnZW9tZXRyeSA9IGluc3RhbmNlLmdlb21ldHJ5OwogICAgY29uc3QgYXR0cmlidXRlcyA9IGdlb21ldHJ5LmF0dHJpYnV0ZXM7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBhdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlczsKICAgIGNvbnN0IGFwcGx5T2Zmc2V0ID0gZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXMuYXBwbHlPZmZzZXQpID8gYXR0cmlidXRlcy5hcHBseU9mZnNldC52YWx1ZXMgOiB2b2lkIDA7CiAgICBjb25zdCBpbmRpY2VzID0gZ2VvbWV0cnkuaW5kaWNlczsKICAgIGNvbnN0IGVhc3RHZW9tZXRyeSA9IGNvcHlHZW9tZXRyeUZvclNwbGl0KGdlb21ldHJ5KTsKICAgIGNvbnN0IHdlc3RHZW9tZXRyeSA9IGNvcHlHZW9tZXRyeUZvclNwbGl0KGdlb21ldHJ5KTsKICAgIGxldCBpOwogICAgY29uc3QgbGVuZ3RoID0gaW5kaWNlcy5sZW5ndGg7CiAgICBjb25zdCB3ZXN0R2VvbWV0cnlJbmRleE1hcCA9IFtdOwogICAgd2VzdEdlb21ldHJ5SW5kZXhNYXAubGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aCAvIDM7CiAgICBjb25zdCBlYXN0R2VvbWV0cnlJbmRleE1hcCA9IFtdOwogICAgZWFzdEdlb21ldHJ5SW5kZXhNYXAubGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aCAvIDM7CiAgICBmb3IgKGkgPSAwOyBpIDwgd2VzdEdlb21ldHJ5SW5kZXhNYXAubGVuZ3RoOyArK2kpIHsKICAgICAgd2VzdEdlb21ldHJ5SW5kZXhNYXBbaV0gPSAtMTsKICAgICAgZWFzdEdlb21ldHJ5SW5kZXhNYXBbaV0gPSAtMTsKICAgIH0KICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMikgewogICAgICBjb25zdCBpMCA9IGluZGljZXNbaV07CiAgICAgIGNvbnN0IGkxID0gaW5kaWNlc1tpICsgMV07CiAgICAgIGNvbnN0IHAwID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIGkwICogMywgcDBTY3JhdGNoKTsKICAgICAgY29uc3QgcDEgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHBvc2l0aW9ucywgaTEgKiAzLCBwMVNjcmF0Y2gpOwogICAgICBsZXQgaW5zZXJ0SW5kZXg7CiAgICAgIGlmIChNYXRoLmFicyhwMC55KSA8IE1hdGhfZGVmYXVsdC5FUFNJTE9ONikgewogICAgICAgIGlmIChwMC55IDwgMCkgewogICAgICAgICAgcDAueSA9IC1NYXRoX2RlZmF1bHQuRVBTSUxPTjY7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHAwLnkgPSBNYXRoX2RlZmF1bHQuRVBTSUxPTjY7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChNYXRoLmFicyhwMS55KSA8IE1hdGhfZGVmYXVsdC5FUFNJTE9ONikgewogICAgICAgIGlmIChwMS55IDwgMCkgewogICAgICAgICAgcDEueSA9IC1NYXRoX2RlZmF1bHQuRVBTSUxPTjY7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHAxLnkgPSBNYXRoX2RlZmF1bHQuRVBTSUxPTjY7CiAgICAgICAgfQogICAgICB9CiAgICAgIGxldCBwMEF0dHJpYnV0ZXMgPSBlYXN0R2VvbWV0cnkuYXR0cmlidXRlczsKICAgICAgbGV0IHAwSW5kaWNlcyA9IGVhc3RHZW9tZXRyeS5pbmRpY2VzOwogICAgICBsZXQgcDBJbmRleE1hcCA9IGVhc3RHZW9tZXRyeUluZGV4TWFwOwogICAgICBsZXQgcDFBdHRyaWJ1dGVzID0gd2VzdEdlb21ldHJ5LmF0dHJpYnV0ZXM7CiAgICAgIGxldCBwMUluZGljZXMgPSB3ZXN0R2VvbWV0cnkuaW5kaWNlczsKICAgICAgbGV0IHAxSW5kZXhNYXAgPSB3ZXN0R2VvbWV0cnlJbmRleE1hcDsKICAgICAgY29uc3QgaW50ZXJzZWN0aW9uID0gSW50ZXJzZWN0aW9uVGVzdHNfZGVmYXVsdC5saW5lU2VnbWVudFBsYW5lKAogICAgICAgIHAwLAogICAgICAgIHAxLAogICAgICAgIHh6UGxhbmUsCiAgICAgICAgcDJTY3JhdGNoCiAgICAgICk7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaW50ZXJzZWN0aW9uKSkgewogICAgICAgIGNvbnN0IG9mZnNldCA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWSwKICAgICAgICAgIDUgKiBNYXRoX2RlZmF1bHQuRVBTSUxPTjksCiAgICAgICAgICBvZmZzZXRTY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBpZiAocDAueSA8IDApIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUob2Zmc2V0LCBvZmZzZXQpOwogICAgICAgICAgcDBBdHRyaWJ1dGVzID0gd2VzdEdlb21ldHJ5LmF0dHJpYnV0ZXM7CiAgICAgICAgICBwMEluZGljZXMgPSB3ZXN0R2VvbWV0cnkuaW5kaWNlczsKICAgICAgICAgIHAwSW5kZXhNYXAgPSB3ZXN0R2VvbWV0cnlJbmRleE1hcDsKICAgICAgICAgIHAxQXR0cmlidXRlcyA9IGVhc3RHZW9tZXRyeS5hdHRyaWJ1dGVzOwogICAgICAgICAgcDFJbmRpY2VzID0gZWFzdEdlb21ldHJ5LmluZGljZXM7CiAgICAgICAgICBwMUluZGV4TWFwID0gZWFzdEdlb21ldHJ5SW5kZXhNYXA7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG9mZnNldFBvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZCgKICAgICAgICAgIGludGVyc2VjdGlvbiwKICAgICAgICAgIG9mZnNldCwKICAgICAgICAgIG9mZnNldFBvaW50U2NyYXRjaAogICAgICAgICk7CiAgICAgICAgaW5zZXJ0SW5kZXggPSBpbnNlcnRTcGxpdFBvaW50KAogICAgICAgICAgcDBBdHRyaWJ1dGVzLAogICAgICAgICAgcDBJbmRpY2VzLAogICAgICAgICAgcDBJbmRleE1hcCwKICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICBpLAogICAgICAgICAgcDAKICAgICAgICApOwogICAgICAgIGNvbXB1dGVMaW5lQXR0cmlidXRlcygKICAgICAgICAgIGkwLAogICAgICAgICAgaTEsCiAgICAgICAgICBwMCwKICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgIGluc2VydEluZGV4LAogICAgICAgICAgcDBBdHRyaWJ1dGVzLAogICAgICAgICAgYXBwbHlPZmZzZXQKICAgICAgICApOwogICAgICAgIGluc2VydEluZGV4ID0gaW5zZXJ0U3BsaXRQb2ludCgKICAgICAgICAgIHAwQXR0cmlidXRlcywKICAgICAgICAgIHAwSW5kaWNlcywKICAgICAgICAgIHAwSW5kZXhNYXAsCiAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgLTEsCiAgICAgICAgICBvZmZzZXRQb2ludAogICAgICAgICk7CiAgICAgICAgY29tcHV0ZUxpbmVBdHRyaWJ1dGVzKAogICAgICAgICAgaTAsCiAgICAgICAgICBpMSwKICAgICAgICAgIG9mZnNldFBvaW50LAogICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgaW5zZXJ0SW5kZXgsCiAgICAgICAgICBwMEF0dHJpYnV0ZXMsCiAgICAgICAgICBhcHBseU9mZnNldAogICAgICAgICk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShvZmZzZXQsIG9mZnNldCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChpbnRlcnNlY3Rpb24sIG9mZnNldCwgb2Zmc2V0UG9pbnQpOwogICAgICAgIGluc2VydEluZGV4ID0gaW5zZXJ0U3BsaXRQb2ludCgKICAgICAgICAgIHAxQXR0cmlidXRlcywKICAgICAgICAgIHAxSW5kaWNlcywKICAgICAgICAgIHAxSW5kZXhNYXAsCiAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgLTEsCiAgICAgICAgICBvZmZzZXRQb2ludAogICAgICAgICk7CiAgICAgICAgY29tcHV0ZUxpbmVBdHRyaWJ1dGVzKAogICAgICAgICAgaTAsCiAgICAgICAgICBpMSwKICAgICAgICAgIG9mZnNldFBvaW50LAogICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgaW5zZXJ0SW5kZXgsCiAgICAgICAgICBwMUF0dHJpYnV0ZXMsCiAgICAgICAgICBhcHBseU9mZnNldAogICAgICAgICk7CiAgICAgICAgaW5zZXJ0SW5kZXggPSBpbnNlcnRTcGxpdFBvaW50KAogICAgICAgICAgcDFBdHRyaWJ1dGVzLAogICAgICAgICAgcDFJbmRpY2VzLAogICAgICAgICAgcDFJbmRleE1hcCwKICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICBpICsgMSwKICAgICAgICAgIHAxCiAgICAgICAgKTsKICAgICAgICBjb21wdXRlTGluZUF0dHJpYnV0ZXMoCiAgICAgICAgICBpMCwKICAgICAgICAgIGkxLAogICAgICAgICAgcDEsCiAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICBpbnNlcnRJbmRleCwKICAgICAgICAgIHAxQXR0cmlidXRlcywKICAgICAgICAgIGFwcGx5T2Zmc2V0CiAgICAgICAgKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBsZXQgY3VycmVudEF0dHJpYnV0ZXM7CiAgICAgICAgbGV0IGN1cnJlbnRJbmRpY2VzOwogICAgICAgIGxldCBjdXJyZW50SW5kZXhNYXA7CiAgICAgICAgaWYgKHAwLnkgPCAwKSB7CiAgICAgICAgICBjdXJyZW50QXR0cmlidXRlcyA9IHdlc3RHZW9tZXRyeS5hdHRyaWJ1dGVzOwogICAgICAgICAgY3VycmVudEluZGljZXMgPSB3ZXN0R2VvbWV0cnkuaW5kaWNlczsKICAgICAgICAgIGN1cnJlbnRJbmRleE1hcCA9IHdlc3RHZW9tZXRyeUluZGV4TWFwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjdXJyZW50QXR0cmlidXRlcyA9IGVhc3RHZW9tZXRyeS5hdHRyaWJ1dGVzOwogICAgICAgICAgY3VycmVudEluZGljZXMgPSBlYXN0R2VvbWV0cnkuaW5kaWNlczsKICAgICAgICAgIGN1cnJlbnRJbmRleE1hcCA9IGVhc3RHZW9tZXRyeUluZGV4TWFwOwogICAgICAgIH0KICAgICAgICBpbnNlcnRJbmRleCA9IGluc2VydFNwbGl0UG9pbnQoCiAgICAgICAgICBjdXJyZW50QXR0cmlidXRlcywKICAgICAgICAgIGN1cnJlbnRJbmRpY2VzLAogICAgICAgICAgY3VycmVudEluZGV4TWFwLAogICAgICAgICAgaW5kaWNlcywKICAgICAgICAgIGksCiAgICAgICAgICBwMAogICAgICAgICk7CiAgICAgICAgY29tcHV0ZUxpbmVBdHRyaWJ1dGVzKAogICAgICAgICAgaTAsCiAgICAgICAgICBpMSwKICAgICAgICAgIHAwLAogICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgaW5zZXJ0SW5kZXgsCiAgICAgICAgICBjdXJyZW50QXR0cmlidXRlcywKICAgICAgICAgIGFwcGx5T2Zmc2V0CiAgICAgICAgKTsKICAgICAgICBpbnNlcnRJbmRleCA9IGluc2VydFNwbGl0UG9pbnQoCiAgICAgICAgICBjdXJyZW50QXR0cmlidXRlcywKICAgICAgICAgIGN1cnJlbnRJbmRpY2VzLAogICAgICAgICAgY3VycmVudEluZGV4TWFwLAogICAgICAgICAgaW5kaWNlcywKICAgICAgICAgIGkgKyAxLAogICAgICAgICAgcDEKICAgICAgICApOwogICAgICAgIGNvbXB1dGVMaW5lQXR0cmlidXRlcygKICAgICAgICAgIGkwLAogICAgICAgICAgaTEsCiAgICAgICAgICBwMSwKICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgIGluc2VydEluZGV4LAogICAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMsCiAgICAgICAgICBhcHBseU9mZnNldAogICAgICAgICk7CiAgICAgIH0KICAgIH0KICAgIHVwZGF0ZUluc3RhbmNlQWZ0ZXJTcGxpdChpbnN0YW5jZSwgd2VzdEdlb21ldHJ5LCBlYXN0R2VvbWV0cnkpOwogIH0KICBmdW5jdGlvbiB1cGRhdGVBZGphY2VuY3lBZnRlclNwbGl0KGdlb21ldHJ5KSB7CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gZ2VvbWV0cnkuYXR0cmlidXRlczsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IGF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzOwogICAgY29uc3QgcHJldlBvc2l0aW9ucyA9IGF0dHJpYnV0ZXMucHJldlBvc2l0aW9uLnZhbHVlczsKICAgIGNvbnN0IG5leHRQb3NpdGlvbnMgPSBhdHRyaWJ1dGVzLm5leHRQb3NpdGlvbi52YWx1ZXM7CiAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgZm9yIChsZXQgaiA9IDA7IGogPCBsZW5ndGg7IGogKz0gMykgewogICAgICBjb25zdCBwb3NpdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2socG9zaXRpb25zLCBqLCBjYXJ0ZXNpYW4zU2NyYXRjaDApOwogICAgICBpZiAocG9zaXRpb24ueCA+IDApIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBwcmV2UG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICAgIHByZXZQb3NpdGlvbnMsCiAgICAgICAgaiwKICAgICAgICBjYXJ0ZXNpYW4zU2NyYXRjaDIKICAgICAgKTsKICAgICAgaWYgKHBvc2l0aW9uLnkgPCAwICYmIHByZXZQb3NpdGlvbi55ID4gMCB8fCBwb3NpdGlvbi55ID4gMCAmJiBwcmV2UG9zaXRpb24ueSA8IDApIHsKICAgICAgICBpZiAoaiAtIDMgPiAwKSB7CiAgICAgICAgICBwcmV2UG9zaXRpb25zW2pdID0gcG9zaXRpb25zW2ogLSAzXTsKICAgICAgICAgIHByZXZQb3NpdGlvbnNbaiArIDFdID0gcG9zaXRpb25zW2ogLSAyXTsKICAgICAgICAgIHByZXZQb3NpdGlvbnNbaiArIDJdID0gcG9zaXRpb25zW2ogLSAxXTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2socG9zaXRpb24sIHByZXZQb3NpdGlvbnMsIGopOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBuZXh0UG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICAgIG5leHRQb3NpdGlvbnMsCiAgICAgICAgaiwKICAgICAgICBjYXJ0ZXNpYW4zU2NyYXRjaDMKICAgICAgKTsKICAgICAgaWYgKHBvc2l0aW9uLnkgPCAwICYmIG5leHRQb3NpdGlvbi55ID4gMCB8fCBwb3NpdGlvbi55ID4gMCAmJiBuZXh0UG9zaXRpb24ueSA8IDApIHsKICAgICAgICBpZiAoaiArIDMgPCBsZW5ndGgpIHsKICAgICAgICAgIG5leHRQb3NpdGlvbnNbal0gPSBwb3NpdGlvbnNbaiArIDNdOwogICAgICAgICAgbmV4dFBvc2l0aW9uc1tqICsgMV0gPSBwb3NpdGlvbnNbaiArIDRdOwogICAgICAgICAgbmV4dFBvc2l0aW9uc1tqICsgMl0gPSBwb3NpdGlvbnNbaiArIDVdOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhwb3NpdGlvbiwgbmV4dFBvc2l0aW9ucywgaik7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQogIGZ1bmN0aW9uIHNwbGl0TG9uZ2l0dWRlUG9seWxpbmUoaW5zdGFuY2UpIHsKICAgIGNvbnN0IGdlb21ldHJ5ID0gaW5zdGFuY2UuZ2VvbWV0cnk7CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gZ2VvbWV0cnkuYXR0cmlidXRlczsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IGF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzOwogICAgY29uc3QgcHJldlBvc2l0aW9ucyA9IGF0dHJpYnV0ZXMucHJldlBvc2l0aW9uLnZhbHVlczsKICAgIGNvbnN0IG5leHRQb3NpdGlvbnMgPSBhdHRyaWJ1dGVzLm5leHRQb3NpdGlvbi52YWx1ZXM7CiAgICBjb25zdCBleHBhbmRBbmRXaWR0aHMgPSBhdHRyaWJ1dGVzLmV4cGFuZEFuZFdpZHRoLnZhbHVlczsKICAgIGNvbnN0IHRleENvb3JkcyA9IGRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVzLnN0KSA/IGF0dHJpYnV0ZXMuc3QudmFsdWVzIDogdm9pZCAwOwogICAgY29uc3QgY29sb3JzID0gZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXMuY29sb3IpID8gYXR0cmlidXRlcy5jb2xvci52YWx1ZXMgOiB2b2lkIDA7CiAgICBjb25zdCBlYXN0R2VvbWV0cnkgPSBjb3B5R2VvbWV0cnlGb3JTcGxpdChnZW9tZXRyeSk7CiAgICBjb25zdCB3ZXN0R2VvbWV0cnkgPSBjb3B5R2VvbWV0cnlGb3JTcGxpdChnZW9tZXRyeSk7CiAgICBsZXQgaTsKICAgIGxldCBqOwogICAgbGV0IGluZGV4OwogICAgbGV0IGludGVyc2VjdGlvbkZvdW5kID0gZmFsc2U7CiAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoIC8gMzsKICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gNCkgewogICAgICBjb25zdCBpMCA9IGk7CiAgICAgIGNvbnN0IGkyID0gaSArIDI7CiAgICAgIGNvbnN0IHAwID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIGkwICogMywgY2FydGVzaWFuM1NjcmF0Y2gwKTsKICAgICAgY29uc3QgcDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHBvc2l0aW9ucywgaTIgKiAzLCBjYXJ0ZXNpYW4zU2NyYXRjaDIpOwogICAgICBpZiAoTWF0aC5hYnMocDAueSkgPCBjb3BsYW5hck9mZnNldCkgewogICAgICAgIHAwLnkgPSBjb3BsYW5hck9mZnNldCAqIChwMi55IDwgMCA/IC0xIDogMSk7CiAgICAgICAgcG9zaXRpb25zW2kgKiAzICsgMV0gPSBwMC55OwogICAgICAgIHBvc2l0aW9uc1soaSArIDEpICogMyArIDFdID0gcDAueTsKICAgICAgICBmb3IgKGogPSBpMCAqIDM7IGogPCBpMCAqIDMgKyA0ICogMzsgaiArPSAzKSB7CiAgICAgICAgICBwcmV2UG9zaXRpb25zW2pdID0gcG9zaXRpb25zW2kgKiAzXTsKICAgICAgICAgIHByZXZQb3NpdGlvbnNbaiArIDFdID0gcG9zaXRpb25zW2kgKiAzICsgMV07CiAgICAgICAgICBwcmV2UG9zaXRpb25zW2ogKyAyXSA9IHBvc2l0aW9uc1tpICogMyArIDJdOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoTWF0aC5hYnMocDIueSkgPCBjb3BsYW5hck9mZnNldCkgewogICAgICAgIHAyLnkgPSBjb3BsYW5hck9mZnNldCAqIChwMC55IDwgMCA/IC0xIDogMSk7CiAgICAgICAgcG9zaXRpb25zWyhpICsgMikgKiAzICsgMV0gPSBwMi55OwogICAgICAgIHBvc2l0aW9uc1soaSArIDMpICogMyArIDFdID0gcDIueTsKICAgICAgICBmb3IgKGogPSBpMCAqIDM7IGogPCBpMCAqIDMgKyA0ICogMzsgaiArPSAzKSB7CiAgICAgICAgICBuZXh0UG9zaXRpb25zW2pdID0gcG9zaXRpb25zWyhpICsgMikgKiAzXTsKICAgICAgICAgIG5leHRQb3NpdGlvbnNbaiArIDFdID0gcG9zaXRpb25zWyhpICsgMikgKiAzICsgMV07CiAgICAgICAgICBuZXh0UG9zaXRpb25zW2ogKyAyXSA9IHBvc2l0aW9uc1soaSArIDIpICogMyArIDJdOwogICAgICAgIH0KICAgICAgfQogICAgICBsZXQgcDBBdHRyaWJ1dGVzID0gZWFzdEdlb21ldHJ5LmF0dHJpYnV0ZXM7CiAgICAgIGxldCBwMEluZGljZXMgPSBlYXN0R2VvbWV0cnkuaW5kaWNlczsKICAgICAgbGV0IHAyQXR0cmlidXRlcyA9IHdlc3RHZW9tZXRyeS5hdHRyaWJ1dGVzOwogICAgICBsZXQgcDJJbmRpY2VzID0gd2VzdEdlb21ldHJ5LmluZGljZXM7CiAgICAgIGNvbnN0IGludGVyc2VjdGlvbiA9IEludGVyc2VjdGlvblRlc3RzX2RlZmF1bHQubGluZVNlZ21lbnRQbGFuZSgKICAgICAgICBwMCwKICAgICAgICBwMiwKICAgICAgICB4elBsYW5lLAogICAgICAgIGNhcnRlc2lhbjNTY3JhdGNoNAogICAgICApOwogICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGludGVyc2VjdGlvbikpIHsKICAgICAgICBpbnRlcnNlY3Rpb25Gb3VuZCA9IHRydWU7CiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9ZLAogICAgICAgICAgb2Zmc2V0U2NhbGFyLAogICAgICAgICAgY2FydGVzaWFuM1NjcmF0Y2g1CiAgICAgICAgKTsKICAgICAgICBpZiAocDAueSA8IDApIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUob2Zmc2V0LCBvZmZzZXQpOwogICAgICAgICAgcDBBdHRyaWJ1dGVzID0gd2VzdEdlb21ldHJ5LmF0dHJpYnV0ZXM7CiAgICAgICAgICBwMEluZGljZXMgPSB3ZXN0R2VvbWV0cnkuaW5kaWNlczsKICAgICAgICAgIHAyQXR0cmlidXRlcyA9IGVhc3RHZW9tZXRyeS5hdHRyaWJ1dGVzOwogICAgICAgICAgcDJJbmRpY2VzID0gZWFzdEdlb21ldHJ5LmluZGljZXM7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG9mZnNldFBvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZCgKICAgICAgICAgIGludGVyc2VjdGlvbiwKICAgICAgICAgIG9mZnNldCwKICAgICAgICAgIGNhcnRlc2lhbjNTY3JhdGNoNgogICAgICAgICk7CiAgICAgICAgcDBBdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5wdXNoKHAwLngsIHAwLnksIHAwLnosIHAwLngsIHAwLnksIHAwLnopOwogICAgICAgIHAwQXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMucHVzaCgKICAgICAgICAgIG9mZnNldFBvaW50LngsCiAgICAgICAgICBvZmZzZXRQb2ludC55LAogICAgICAgICAgb2Zmc2V0UG9pbnQuegogICAgICAgICk7CiAgICAgICAgcDBBdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5wdXNoKAogICAgICAgICAgb2Zmc2V0UG9pbnQueCwKICAgICAgICAgIG9mZnNldFBvaW50LnksCiAgICAgICAgICBvZmZzZXRQb2ludC56CiAgICAgICAgKTsKICAgICAgICBwMEF0dHJpYnV0ZXMucHJldlBvc2l0aW9uLnZhbHVlcy5wdXNoKAogICAgICAgICAgcHJldlBvc2l0aW9uc1tpMCAqIDNdLAogICAgICAgICAgcHJldlBvc2l0aW9uc1tpMCAqIDMgKyAxXSwKICAgICAgICAgIHByZXZQb3NpdGlvbnNbaTAgKiAzICsgMl0KICAgICAgICApOwogICAgICAgIHAwQXR0cmlidXRlcy5wcmV2UG9zaXRpb24udmFsdWVzLnB1c2goCiAgICAgICAgICBwcmV2UG9zaXRpb25zW2kwICogMyArIDNdLAogICAgICAgICAgcHJldlBvc2l0aW9uc1tpMCAqIDMgKyA0XSwKICAgICAgICAgIHByZXZQb3NpdGlvbnNbaTAgKiAzICsgNV0KICAgICAgICApOwogICAgICAgIHAwQXR0cmlidXRlcy5wcmV2UG9zaXRpb24udmFsdWVzLnB1c2gocDAueCwgcDAueSwgcDAueiwgcDAueCwgcDAueSwgcDAueik7CiAgICAgICAgcDBBdHRyaWJ1dGVzLm5leHRQb3NpdGlvbi52YWx1ZXMucHVzaCgKICAgICAgICAgIG9mZnNldFBvaW50LngsCiAgICAgICAgICBvZmZzZXRQb2ludC55LAogICAgICAgICAgb2Zmc2V0UG9pbnQuegogICAgICAgICk7CiAgICAgICAgcDBBdHRyaWJ1dGVzLm5leHRQb3NpdGlvbi52YWx1ZXMucHVzaCgKICAgICAgICAgIG9mZnNldFBvaW50LngsCiAgICAgICAgICBvZmZzZXRQb2ludC55LAogICAgICAgICAgb2Zmc2V0UG9pbnQuegogICAgICAgICk7CiAgICAgICAgcDBBdHRyaWJ1dGVzLm5leHRQb3NpdGlvbi52YWx1ZXMucHVzaCgKICAgICAgICAgIG9mZnNldFBvaW50LngsCiAgICAgICAgICBvZmZzZXRQb2ludC55LAogICAgICAgICAgb2Zmc2V0UG9pbnQuegogICAgICAgICk7CiAgICAgICAgcDBBdHRyaWJ1dGVzLm5leHRQb3NpdGlvbi52YWx1ZXMucHVzaCgKICAgICAgICAgIG9mZnNldFBvaW50LngsCiAgICAgICAgICBvZmZzZXRQb2ludC55LAogICAgICAgICAgb2Zmc2V0UG9pbnQuegogICAgICAgICk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShvZmZzZXQsIG9mZnNldCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChpbnRlcnNlY3Rpb24sIG9mZnNldCwgb2Zmc2V0UG9pbnQpOwogICAgICAgIHAyQXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMucHVzaCgKICAgICAgICAgIG9mZnNldFBvaW50LngsCiAgICAgICAgICBvZmZzZXRQb2ludC55LAogICAgICAgICAgb2Zmc2V0UG9pbnQuegogICAgICAgICk7CiAgICAgICAgcDJBdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5wdXNoKAogICAgICAgICAgb2Zmc2V0UG9pbnQueCwKICAgICAgICAgIG9mZnNldFBvaW50LnksCiAgICAgICAgICBvZmZzZXRQb2ludC56CiAgICAgICAgKTsKICAgICAgICBwMkF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLnB1c2gocDIueCwgcDIueSwgcDIueiwgcDIueCwgcDIueSwgcDIueik7CiAgICAgICAgcDJBdHRyaWJ1dGVzLnByZXZQb3NpdGlvbi52YWx1ZXMucHVzaCgKICAgICAgICAgIG9mZnNldFBvaW50LngsCiAgICAgICAgICBvZmZzZXRQb2ludC55LAogICAgICAgICAgb2Zmc2V0UG9pbnQuegogICAgICAgICk7CiAgICAgICAgcDJBdHRyaWJ1dGVzLnByZXZQb3NpdGlvbi52YWx1ZXMucHVzaCgKICAgICAgICAgIG9mZnNldFBvaW50LngsCiAgICAgICAgICBvZmZzZXRQb2ludC55LAogICAgICAgICAgb2Zmc2V0UG9pbnQuegogICAgICAgICk7CiAgICAgICAgcDJBdHRyaWJ1dGVzLnByZXZQb3NpdGlvbi52YWx1ZXMucHVzaCgKICAgICAgICAgIG9mZnNldFBvaW50LngsCiAgICAgICAgICBvZmZzZXRQb2ludC55LAogICAgICAgICAgb2Zmc2V0UG9pbnQuegogICAgICAgICk7CiAgICAgICAgcDJBdHRyaWJ1dGVzLnByZXZQb3NpdGlvbi52YWx1ZXMucHVzaCgKICAgICAgICAgIG9mZnNldFBvaW50LngsCiAgICAgICAgICBvZmZzZXRQb2ludC55LAogICAgICAgICAgb2Zmc2V0UG9pbnQuegogICAgICAgICk7CiAgICAgICAgcDJBdHRyaWJ1dGVzLm5leHRQb3NpdGlvbi52YWx1ZXMucHVzaChwMi54LCBwMi55LCBwMi56LCBwMi54LCBwMi55LCBwMi56KTsKICAgICAgICBwMkF0dHJpYnV0ZXMubmV4dFBvc2l0aW9uLnZhbHVlcy5wdXNoKAogICAgICAgICAgbmV4dFBvc2l0aW9uc1tpMiAqIDNdLAogICAgICAgICAgbmV4dFBvc2l0aW9uc1tpMiAqIDMgKyAxXSwKICAgICAgICAgIG5leHRQb3NpdGlvbnNbaTIgKiAzICsgMl0KICAgICAgICApOwogICAgICAgIHAyQXR0cmlidXRlcy5uZXh0UG9zaXRpb24udmFsdWVzLnB1c2goCiAgICAgICAgICBuZXh0UG9zaXRpb25zW2kyICogMyArIDNdLAogICAgICAgICAgbmV4dFBvc2l0aW9uc1tpMiAqIDMgKyA0XSwKICAgICAgICAgIG5leHRQb3NpdGlvbnNbaTIgKiAzICsgNV0KICAgICAgICApOwogICAgICAgIGNvbnN0IGV3MCA9IENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICBleHBhbmRBbmRXaWR0aHMsCiAgICAgICAgICBpMCAqIDIsCiAgICAgICAgICBjYXJ0ZXNpYW4yU2NyYXRjaDAKICAgICAgICApOwogICAgICAgIGNvbnN0IHdpZHRoID0gTWF0aC5hYnMoZXcwLnkpOwogICAgICAgIHAwQXR0cmlidXRlcy5leHBhbmRBbmRXaWR0aC52YWx1ZXMucHVzaCgtMSwgd2lkdGgsIDEsIHdpZHRoKTsKICAgICAgICBwMEF0dHJpYnV0ZXMuZXhwYW5kQW5kV2lkdGgudmFsdWVzLnB1c2goLTEsIC13aWR0aCwgMSwgLXdpZHRoKTsKICAgICAgICBwMkF0dHJpYnV0ZXMuZXhwYW5kQW5kV2lkdGgudmFsdWVzLnB1c2goLTEsIHdpZHRoLCAxLCB3aWR0aCk7CiAgICAgICAgcDJBdHRyaWJ1dGVzLmV4cGFuZEFuZFdpZHRoLnZhbHVlcy5wdXNoKC0xLCAtd2lkdGgsIDEsIC13aWR0aCk7CiAgICAgICAgbGV0IHQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlU3F1YXJlZCgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChpbnRlcnNlY3Rpb24sIHAwLCBjYXJ0ZXNpYW4zU2NyYXRjaDMpCiAgICAgICAgKTsKICAgICAgICB0IC89IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGVTcXVhcmVkKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHAyLCBwMCwgY2FydGVzaWFuM1NjcmF0Y2gzKQogICAgICAgICk7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChjb2xvcnMpKSB7CiAgICAgICAgICBjb25zdCBjMCA9IENhcnRlc2lhbjRfZGVmYXVsdC5mcm9tQXJyYXkoY29sb3JzLCBpMCAqIDQsIGNhcnRlc2lhbjRTY3JhdGNoMCk7CiAgICAgICAgICBjb25zdCBjMiA9IENhcnRlc2lhbjRfZGVmYXVsdC5mcm9tQXJyYXkoY29sb3JzLCBpMiAqIDQsIGNhcnRlc2lhbjRTY3JhdGNoMCk7CiAgICAgICAgICBjb25zdCByID0gTWF0aF9kZWZhdWx0LmxlcnAoYzAueCwgYzIueCwgdCk7CiAgICAgICAgICBjb25zdCBnID0gTWF0aF9kZWZhdWx0LmxlcnAoYzAueSwgYzIueSwgdCk7CiAgICAgICAgICBjb25zdCBiID0gTWF0aF9kZWZhdWx0LmxlcnAoYzAueiwgYzIueiwgdCk7CiAgICAgICAgICBjb25zdCBhMyA9IE1hdGhfZGVmYXVsdC5sZXJwKGMwLncsIGMyLncsIHQpOwogICAgICAgICAgZm9yIChqID0gaTAgKiA0OyBqIDwgaTAgKiA0ICsgMiAqIDQ7ICsraikgewogICAgICAgICAgICBwMEF0dHJpYnV0ZXMuY29sb3IudmFsdWVzLnB1c2goY29sb3JzW2pdKTsKICAgICAgICAgIH0KICAgICAgICAgIHAwQXR0cmlidXRlcy5jb2xvci52YWx1ZXMucHVzaChyLCBnLCBiLCBhMyk7CiAgICAgICAgICBwMEF0dHJpYnV0ZXMuY29sb3IudmFsdWVzLnB1c2gociwgZywgYiwgYTMpOwogICAgICAgICAgcDJBdHRyaWJ1dGVzLmNvbG9yLnZhbHVlcy5wdXNoKHIsIGcsIGIsIGEzKTsKICAgICAgICAgIHAyQXR0cmlidXRlcy5jb2xvci52YWx1ZXMucHVzaChyLCBnLCBiLCBhMyk7CiAgICAgICAgICBmb3IgKGogPSBpMiAqIDQ7IGogPCBpMiAqIDQgKyAyICogNDsgKytqKSB7CiAgICAgICAgICAgIHAyQXR0cmlidXRlcy5jb2xvci52YWx1ZXMucHVzaChjb2xvcnNbal0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHRleENvb3JkcykpIHsKICAgICAgICAgIGNvbnN0IHMwID0gQ2FydGVzaWFuMl9kZWZhdWx0LmZyb21BcnJheSh0ZXhDb29yZHMsIGkwICogMiwgY2FydGVzaWFuMlNjcmF0Y2gwKTsKICAgICAgICAgIGNvbnN0IHMzID0gQ2FydGVzaWFuMl9kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgICAgdGV4Q29vcmRzLAogICAgICAgICAgICAoaSArIDMpICogMiwKICAgICAgICAgICAgY2FydGVzaWFuMlNjcmF0Y2gxCiAgICAgICAgICApOwogICAgICAgICAgY29uc3Qgc3ggPSBNYXRoX2RlZmF1bHQubGVycChzMC54LCBzMy54LCB0KTsKICAgICAgICAgIGZvciAoaiA9IGkwICogMjsgaiA8IGkwICogMiArIDIgKiAyOyArK2opIHsKICAgICAgICAgICAgcDBBdHRyaWJ1dGVzLnN0LnZhbHVlcy5wdXNoKHRleENvb3Jkc1tqXSk7CiAgICAgICAgICB9CiAgICAgICAgICBwMEF0dHJpYnV0ZXMuc3QudmFsdWVzLnB1c2goc3gsIHMwLnkpOwogICAgICAgICAgcDBBdHRyaWJ1dGVzLnN0LnZhbHVlcy5wdXNoKHN4LCBzMy55KTsKICAgICAgICAgIHAyQXR0cmlidXRlcy5zdC52YWx1ZXMucHVzaChzeCwgczAueSk7CiAgICAgICAgICBwMkF0dHJpYnV0ZXMuc3QudmFsdWVzLnB1c2goc3gsIHMzLnkpOwogICAgICAgICAgZm9yIChqID0gaTIgKiAyOyBqIDwgaTIgKiAyICsgMiAqIDI7ICsraikgewogICAgICAgICAgICBwMkF0dHJpYnV0ZXMuc3QudmFsdWVzLnB1c2godGV4Q29vcmRzW2pdKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaW5kZXggPSBwMEF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLmxlbmd0aCAvIDMgLSA0OwogICAgICAgIHAwSW5kaWNlcy5wdXNoKGluZGV4LCBpbmRleCArIDIsIGluZGV4ICsgMSk7CiAgICAgICAgcDBJbmRpY2VzLnB1c2goaW5kZXggKyAxLCBpbmRleCArIDIsIGluZGV4ICsgMyk7CiAgICAgICAgaW5kZXggPSBwMkF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLmxlbmd0aCAvIDMgLSA0OwogICAgICAgIHAySW5kaWNlcy5wdXNoKGluZGV4LCBpbmRleCArIDIsIGluZGV4ICsgMSk7CiAgICAgICAgcDJJbmRpY2VzLnB1c2goaW5kZXggKyAxLCBpbmRleCArIDIsIGluZGV4ICsgMyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbGV0IGN1cnJlbnRBdHRyaWJ1dGVzOwogICAgICAgIGxldCBjdXJyZW50SW5kaWNlczsKICAgICAgICBpZiAocDAueSA8IDApIHsKICAgICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzID0gd2VzdEdlb21ldHJ5LmF0dHJpYnV0ZXM7CiAgICAgICAgICBjdXJyZW50SW5kaWNlcyA9IHdlc3RHZW9tZXRyeS5pbmRpY2VzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjdXJyZW50QXR0cmlidXRlcyA9IGVhc3RHZW9tZXRyeS5hdHRyaWJ1dGVzOwogICAgICAgICAgY3VycmVudEluZGljZXMgPSBlYXN0R2VvbWV0cnkuaW5kaWNlczsKICAgICAgICB9CiAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLnB1c2gocDAueCwgcDAueSwgcDAueik7CiAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLnB1c2gocDAueCwgcDAueSwgcDAueik7CiAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLnB1c2gocDIueCwgcDIueSwgcDIueik7CiAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLnB1c2gocDIueCwgcDIueSwgcDIueik7CiAgICAgICAgZm9yIChqID0gaSAqIDM7IGogPCBpICogMyArIDQgKiAzOyArK2opIHsKICAgICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzLnByZXZQb3NpdGlvbi52YWx1ZXMucHVzaChwcmV2UG9zaXRpb25zW2pdKTsKICAgICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzLm5leHRQb3NpdGlvbi52YWx1ZXMucHVzaChuZXh0UG9zaXRpb25zW2pdKTsKICAgICAgICB9CiAgICAgICAgZm9yIChqID0gaSAqIDI7IGogPCBpICogMiArIDQgKiAyOyArK2opIHsKICAgICAgICAgIGN1cnJlbnRBdHRyaWJ1dGVzLmV4cGFuZEFuZFdpZHRoLnZhbHVlcy5wdXNoKGV4cGFuZEFuZFdpZHRoc1tqXSk7CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHRleENvb3JkcykpIHsKICAgICAgICAgICAgY3VycmVudEF0dHJpYnV0ZXMuc3QudmFsdWVzLnB1c2godGV4Q29vcmRzW2pdKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChjb2xvcnMpKSB7CiAgICAgICAgICBmb3IgKGogPSBpICogNDsgaiA8IGkgKiA0ICsgNCAqIDQ7ICsraikgewogICAgICAgICAgICBjdXJyZW50QXR0cmlidXRlcy5jb2xvci52YWx1ZXMucHVzaChjb2xvcnNbal0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpbmRleCA9IGN1cnJlbnRBdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5sZW5ndGggLyAzIC0gNDsKICAgICAgICBjdXJyZW50SW5kaWNlcy5wdXNoKGluZGV4LCBpbmRleCArIDIsIGluZGV4ICsgMSk7CiAgICAgICAgY3VycmVudEluZGljZXMucHVzaChpbmRleCArIDEsIGluZGV4ICsgMiwgaW5kZXggKyAzKTsKICAgICAgfQogICAgfQogICAgaWYgKGludGVyc2VjdGlvbkZvdW5kKSB7CiAgICAgIHVwZGF0ZUFkamFjZW5jeUFmdGVyU3BsaXQod2VzdEdlb21ldHJ5KTsKICAgICAgdXBkYXRlQWRqYWNlbmN5QWZ0ZXJTcGxpdChlYXN0R2VvbWV0cnkpOwogICAgfQogICAgdXBkYXRlSW5zdGFuY2VBZnRlclNwbGl0KGluc3RhbmNlLCB3ZXN0R2VvbWV0cnksIGVhc3RHZW9tZXRyeSk7CiAgfQogIHZhciBHZW9tZXRyeVBpcGVsaW5lLCBzY3JhdGNoUHJvamVjdFRvMkRDYXJ0ZXNpYW4zLCBzY3JhdGNoUHJvamVjdFRvMkRDYXJ0b2dyYXBoaWMsIGVuY29kZWRSZXN1bHQsIHNjcmF0Y2hDYXJ0ZXNpYW4zMywgaW52ZXJzZVRyYW5zcG9zZSwgbm9ybWFsTWF0cml4LCB0ZW1wU2NyYXRjaCwgbm9ybWFsLCB2MCwgdjEsIHYyLCBub3JtYWxTY3JhdGNoMiwgbm9ybWFsU2NhbGUsIHRTY3JhdGNoLCBzY3JhdGNoQ2FydGVzaWFuMjIsIHRvRW5jb2RlMSwgdG9FbmNvZGUyLCB0b0VuY29kZTMsIGVuY29kZVJlc3VsdDIsIGMzLCB1MSwgdTIsIHExLCBxMiwgc3BsaXRUcmlhbmdsZVJlc3VsdCwgaW50ZXJwb2xhdGVBbmRQYWNrQ2FydGVzaWFuNCwgaW50ZXJwb2xhdGVBbmRQYWNrQ2FydGVzaWFuMywgaW50ZXJwb2xhdGVBbmRQYWNrQ2FydGVzaWFuMiwgaW50ZXJwb2xhdGVBbmRQYWNrQm9vbGVhbiwgcDBTY3JhdGNoLCBwMVNjcmF0Y2gsIHAyU2NyYXRjaCwgYmFyeWNlbnRyaWNTY3JhdGNoLCBOQU1FRF9BVFRSSUJVVEVTLCB4elBsYW5lLCBvZmZzZXRTY3JhdGNoLCBvZmZzZXRQb2ludFNjcmF0Y2gsIGNhcnRlc2lhbjJTY3JhdGNoMCwgY2FydGVzaWFuMlNjcmF0Y2gxLCBjYXJ0ZXNpYW4zU2NyYXRjaDAsIGNhcnRlc2lhbjNTY3JhdGNoMiwgY2FydGVzaWFuM1NjcmF0Y2gzLCBjYXJ0ZXNpYW4zU2NyYXRjaDQsIGNhcnRlc2lhbjNTY3JhdGNoNSwgY2FydGVzaWFuM1NjcmF0Y2g2LCBjYXJ0ZXNpYW40U2NyYXRjaDAsIG9mZnNldFNjYWxhciwgY29wbGFuYXJPZmZzZXQsIEdlb21ldHJ5UGlwZWxpbmVfZGVmYXVsdDsKICB2YXIgaW5pdF9HZW9tZXRyeVBpcGVsaW5lID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9HZW9tZXRyeVBpcGVsaW5lLmpzIigpIHsKICAgICAgaW5pdF9BdHRyaWJ1dGVDb21wcmVzc2lvbigpOwogICAgICBpbml0X2JhcnljZW50cmljQ29vcmRpbmF0ZXMoKTsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuNCgpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X0NvbXBvbmVudERhdGF0eXBlKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfRW5jb2RlZENhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9HZW9ncmFwaGljUHJvamVjdGlvbigpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeVR5cGUoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfSW50ZXJzZWN0KCk7CiAgICAgIGluaXRfSW50ZXJzZWN0aW9uVGVzdHMoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfTWF0cml4MygpOwogICAgICBpbml0X01hdHJpeDQoKTsKICAgICAgaW5pdF9QbGFuZSgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgaW5pdF9UaXBzaWZ5KCk7CiAgICAgIEdlb21ldHJ5UGlwZWxpbmUgPSB7fTsKICAgICAgR2VvbWV0cnlQaXBlbGluZS50b1dpcmVmcmFtZSA9IGZ1bmN0aW9uKGdlb21ldHJ5KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZ2VvbWV0cnkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZ2VvbWV0cnkgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGluZGljZXMgPSBnZW9tZXRyeS5pbmRpY2VzOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaW5kaWNlcykpIHsKICAgICAgICAgIHN3aXRjaCAoZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSkgewogICAgICAgICAgICBjYXNlIFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5UUklBTkdMRVM6CiAgICAgICAgICAgICAgZ2VvbWV0cnkuaW5kaWNlcyA9IHRyaWFuZ2xlc1RvTGluZXMoaW5kaWNlcyk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFX1NUUklQOgogICAgICAgICAgICAgIGdlb21ldHJ5LmluZGljZXMgPSB0cmlhbmdsZVN0cmlwVG9MaW5lcyhpbmRpY2VzKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBQcmltaXRpdmVUeXBlX2RlZmF1bHQuVFJJQU5HTEVfRkFOOgogICAgICAgICAgICAgIGdlb21ldHJ5LmluZGljZXMgPSB0cmlhbmdsZUZhblRvTGluZXMoaW5kaWNlcyk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIC8vPj5pbmNsdWRlU3RhcnQoJ2RlYnVnJywgcHJhZ21hcy5kZWJ1Zyk7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICAgICAiZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSBtdXN0IGJlIFRSSUFOR0xFUywgVFJJQU5HTEVfU1RSSVAsIG9yIFRSSUFOR0xFX0ZBTi4iCiAgICAgICAgICAgICAgKTsKICAgICAgICAgIH0KICAgICAgICAgIGdlb21ldHJ5LnByaW1pdGl2ZVR5cGUgPSBQcmltaXRpdmVUeXBlX2RlZmF1bHQuTElORVM7CiAgICAgICAgfQogICAgICAgIHJldHVybiBnZW9tZXRyeTsKICAgICAgfTsKICAgICAgR2VvbWV0cnlQaXBlbGluZS5jcmVhdGVMaW5lU2VnbWVudHNGb3JWZWN0b3JzID0gZnVuY3Rpb24oZ2VvbWV0cnksIGF0dHJpYnV0ZU5hbWUsIGxlbmd0aCkgewogICAgICAgIGF0dHJpYnV0ZU5hbWUgPSBhdHRyaWJ1dGVOYW1lID8/ICJub3JtYWwiOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImdlb21ldHJ5IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24gaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgYGdlb21ldHJ5LmF0dHJpYnV0ZXMgbXVzdCBoYXZlIGFuIGF0dHJpYnV0ZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgdGhlIGF0dHJpYnV0ZU5hbWUgcGFyYW1ldGVyLCAke2F0dHJpYnV0ZU5hbWV9LmAKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGxlbmd0aCA9IGxlbmd0aCA/PyAxZTQ7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gZ2VvbWV0cnkuYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXM7CiAgICAgICAgY29uc3QgdmVjdG9ycyA9IGdlb21ldHJ5LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0udmFsdWVzOwogICAgICAgIGNvbnN0IHBvc2l0aW9uc0xlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgY29uc3QgbmV3UG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheSgyICogcG9zaXRpb25zTGVuZ3RoKTsKICAgICAgICBsZXQgaiA9IDA7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb3NpdGlvbnNMZW5ndGg7IGkgKz0gMykgewogICAgICAgICAgbmV3UG9zaXRpb25zW2orK10gPSBwb3NpdGlvbnNbaV07CiAgICAgICAgICBuZXdQb3NpdGlvbnNbaisrXSA9IHBvc2l0aW9uc1tpICsgMV07CiAgICAgICAgICBuZXdQb3NpdGlvbnNbaisrXSA9IHBvc2l0aW9uc1tpICsgMl07CiAgICAgICAgICBuZXdQb3NpdGlvbnNbaisrXSA9IHBvc2l0aW9uc1tpXSArIHZlY3RvcnNbaV0gKiBsZW5ndGg7CiAgICAgICAgICBuZXdQb3NpdGlvbnNbaisrXSA9IHBvc2l0aW9uc1tpICsgMV0gKyB2ZWN0b3JzW2kgKyAxXSAqIGxlbmd0aDsKICAgICAgICAgIG5ld1Bvc2l0aW9uc1tqKytdID0gcG9zaXRpb25zW2kgKyAyXSArIHZlY3RvcnNbaSArIDJdICogbGVuZ3RoOwogICAgICAgIH0KICAgICAgICBsZXQgbmV3Qm91bmRpbmdTcGhlcmU7CiAgICAgICAgY29uc3QgYnMgPSBnZW9tZXRyeS5ib3VuZGluZ1NwaGVyZTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGJzKSkgewogICAgICAgICAgbmV3Qm91bmRpbmdTcGhlcmUgPSBuZXcgQm91bmRpbmdTcGhlcmVfZGVmYXVsdChicy5jZW50ZXIsIGJzLnJhZGl1cyArIGxlbmd0aCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgIHBvc2l0aW9uOiBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFLAogICAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICAgICAgdmFsdWVzOiBuZXdQb3NpdGlvbnMKICAgICAgICAgICAgfSkKICAgICAgICAgIH0sCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBQcmltaXRpdmVUeXBlX2RlZmF1bHQuTElORVMsCiAgICAgICAgICBib3VuZGluZ1NwaGVyZTogbmV3Qm91bmRpbmdTcGhlcmUKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgR2VvbWV0cnlQaXBlbGluZS5jcmVhdGVBdHRyaWJ1dGVMb2NhdGlvbnMgPSBmdW5jdGlvbihnZW9tZXRyeSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImdlb21ldHJ5IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBzZW1hbnRpY3MgPSBbCiAgICAgICAgICAicG9zaXRpb24iLAogICAgICAgICAgInBvc2l0aW9uSGlnaCIsCiAgICAgICAgICAicG9zaXRpb25Mb3ciLAogICAgICAgICAgLy8gRnJvbSBWZXJ0ZXhGb3JtYXQucG9zaXRpb24gLSBhZnRlciAyRCBwcm9qZWN0aW9uIGFuZCBoaWdoLXByZWNpc2lvbiBlbmNvZGluZwogICAgICAgICAgInBvc2l0aW9uM0RIaWdoIiwKICAgICAgICAgICJwb3NpdGlvbjNETG93IiwKICAgICAgICAgICJwb3NpdGlvbjJESGlnaCIsCiAgICAgICAgICAicG9zaXRpb24yRExvdyIsCiAgICAgICAgICAvLyBGcm9tIFByaW1pdGl2ZQogICAgICAgICAgInBpY2tDb2xvciIsCiAgICAgICAgICAvLyBGcm9tIFZlcnRleEZvcm1hdAogICAgICAgICAgIm5vcm1hbCIsCiAgICAgICAgICAic3QiLAogICAgICAgICAgInRhbmdlbnQiLAogICAgICAgICAgImJpdGFuZ2VudCIsCiAgICAgICAgICAvLyBGb3Igc2hhZG93IHZvbHVtZXMKICAgICAgICAgICJleHRydWRlRGlyZWN0aW9uIiwKICAgICAgICAgIC8vIEZyb20gY29tcHJlc3NpbmcgdGV4dHVyZSBjb29yZGluYXRlcyBhbmQgbm9ybWFscwogICAgICAgICAgImNvbXByZXNzZWRBdHRyaWJ1dGVzIgogICAgICAgIF07CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IGdlb21ldHJ5LmF0dHJpYnV0ZXM7CiAgICAgICAgY29uc3QgaW5kaWNlcyA9IHt9OwogICAgICAgIGxldCBqID0gMDsKICAgICAgICBsZXQgaTsKICAgICAgICBjb25zdCBsZW4gPSBzZW1hbnRpY3MubGVuZ3RoOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47ICsraSkgewogICAgICAgICAgY29uc3Qgc2VtYW50aWMgPSBzZW1hbnRpY3NbaV07CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXNbc2VtYW50aWNdKSkgewogICAgICAgICAgICBpbmRpY2VzW3NlbWFudGljXSA9IGorKzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZm9yIChjb25zdCBuYW1lIGluIGF0dHJpYnV0ZXMpIHsKICAgICAgICAgIGlmIChhdHRyaWJ1dGVzLmhhc093blByb3BlcnR5KG5hbWUpICYmICFkZWZpbmVkX2RlZmF1bHQoaW5kaWNlc1tuYW1lXSkpIHsKICAgICAgICAgICAgaW5kaWNlc1tuYW1lXSA9IGorKzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGluZGljZXM7CiAgICAgIH07CiAgICAgIEdlb21ldHJ5UGlwZWxpbmUucmVvcmRlckZvclByZVZlcnRleENhY2hlID0gZnVuY3Rpb24oZ2VvbWV0cnkpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChnZW9tZXRyeSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJnZW9tZXRyeSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbnVtVmVydGljZXMgPSBHZW9tZXRyeV9kZWZhdWx0LmNvbXB1dGVOdW1iZXJPZlZlcnRpY2VzKGdlb21ldHJ5KTsKICAgICAgICBjb25zdCBpbmRpY2VzID0gZ2VvbWV0cnkuaW5kaWNlczsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGluZGljZXMpKSB7CiAgICAgICAgICBjb25zdCBpbmRleENyb3NzUmVmZXJlbmNlT2xkVG9OZXcgPSBuZXcgSW50MzJBcnJheShudW1WZXJ0aWNlcyk7CiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bVZlcnRpY2VzOyBpKyspIHsKICAgICAgICAgICAgaW5kZXhDcm9zc1JlZmVyZW5jZU9sZFRvTmV3W2ldID0gLTE7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBpbmRpY2VzSW4gPSBpbmRpY2VzOwogICAgICAgICAgY29uc3QgbnVtSW5kaWNlcyA9IGluZGljZXNJbi5sZW5ndGg7CiAgICAgICAgICBjb25zdCBpbmRpY2VzT3V0ID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkobnVtVmVydGljZXMsIG51bUluZGljZXMpOwogICAgICAgICAgbGV0IGludG9JbmRpY2VzSW4gPSAwOwogICAgICAgICAgbGV0IGludG9JbmRpY2VzT3V0ID0gMDsKICAgICAgICAgIGxldCBuZXh0SW5kZXggPSAwOwogICAgICAgICAgbGV0IHRlbXBJbmRleDsKICAgICAgICAgIHdoaWxlIChpbnRvSW5kaWNlc0luIDwgbnVtSW5kaWNlcykgewogICAgICAgICAgICB0ZW1wSW5kZXggPSBpbmRleENyb3NzUmVmZXJlbmNlT2xkVG9OZXdbaW5kaWNlc0luW2ludG9JbmRpY2VzSW5dXTsKICAgICAgICAgICAgaWYgKHRlbXBJbmRleCAhPT0gLTEpIHsKICAgICAgICAgICAgICBpbmRpY2VzT3V0W2ludG9JbmRpY2VzT3V0XSA9IHRlbXBJbmRleDsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB0ZW1wSW5kZXggPSBpbmRpY2VzSW5baW50b0luZGljZXNJbl07CiAgICAgICAgICAgICAgaW5kZXhDcm9zc1JlZmVyZW5jZU9sZFRvTmV3W3RlbXBJbmRleF0gPSBuZXh0SW5kZXg7CiAgICAgICAgICAgICAgaW5kaWNlc091dFtpbnRvSW5kaWNlc091dF0gPSBuZXh0SW5kZXg7CiAgICAgICAgICAgICAgKytuZXh0SW5kZXg7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgKytpbnRvSW5kaWNlc0luOwogICAgICAgICAgICArK2ludG9JbmRpY2VzT3V0OwogICAgICAgICAgfQogICAgICAgICAgZ2VvbWV0cnkuaW5kaWNlcyA9IGluZGljZXNPdXQ7CiAgICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gZ2VvbWV0cnkuYXR0cmlidXRlczsKICAgICAgICAgIGZvciAoY29uc3QgcHJvcGVydHkgaW4gYXR0cmlidXRlcykgewogICAgICAgICAgICBpZiAoYXR0cmlidXRlcy5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSkgJiYgZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXNbcHJvcGVydHldKSAmJiBkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlc1twcm9wZXJ0eV0udmFsdWVzKSkgewogICAgICAgICAgICAgIGNvbnN0IGF0dHJpYnV0ZSA9IGF0dHJpYnV0ZXNbcHJvcGVydHldOwogICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnRzSW4gPSBhdHRyaWJ1dGUudmFsdWVzOwogICAgICAgICAgICAgIGxldCBpbnRvRWxlbWVudHNJbiA9IDA7CiAgICAgICAgICAgICAgY29uc3QgbnVtQ29tcG9uZW50cyA9IGF0dHJpYnV0ZS5jb21wb25lbnRzUGVyQXR0cmlidXRlOwogICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnRzT3V0ID0gQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KAogICAgICAgICAgICAgICAgYXR0cmlidXRlLmNvbXBvbmVudERhdGF0eXBlLAogICAgICAgICAgICAgICAgbmV4dEluZGV4ICogbnVtQ29tcG9uZW50cwogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgd2hpbGUgKGludG9FbGVtZW50c0luIDwgbnVtVmVydGljZXMpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHRlbXAgPSBpbmRleENyb3NzUmVmZXJlbmNlT2xkVG9OZXdbaW50b0VsZW1lbnRzSW5dOwogICAgICAgICAgICAgICAgaWYgKHRlbXAgIT09IC0xKSB7CiAgICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbnVtQ29tcG9uZW50czsgaisrKSB7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudHNPdXRbbnVtQ29tcG9uZW50cyAqIHRlbXAgKyBqXSA9IGVsZW1lbnRzSW5bbnVtQ29tcG9uZW50cyAqIGludG9FbGVtZW50c0luICsgal07CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICsraW50b0VsZW1lbnRzSW47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGF0dHJpYnV0ZS52YWx1ZXMgPSBlbGVtZW50c091dDsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gZ2VvbWV0cnk7CiAgICAgIH07CiAgICAgIEdlb21ldHJ5UGlwZWxpbmUucmVvcmRlckZvclBvc3RWZXJ0ZXhDYWNoZSA9IGZ1bmN0aW9uKGdlb21ldHJ5LCBjYWNoZUNhcGFjaXR5KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZ2VvbWV0cnkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZ2VvbWV0cnkgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGluZGljZXMgPSBnZW9tZXRyeS5pbmRpY2VzOwogICAgICAgIGlmIChnZW9tZXRyeS5wcmltaXRpdmVUeXBlID09PSBQcmltaXRpdmVUeXBlX2RlZmF1bHQuVFJJQU5HTEVTICYmIGRlZmluZWRfZGVmYXVsdChpbmRpY2VzKSkgewogICAgICAgICAgY29uc3QgbnVtSW5kaWNlcyA9IGluZGljZXMubGVuZ3RoOwogICAgICAgICAgbGV0IG1heGltdW1JbmRleCA9IDA7CiAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG51bUluZGljZXM7IGorKykgewogICAgICAgICAgICBpZiAoaW5kaWNlc1tqXSA+IG1heGltdW1JbmRleCkgewogICAgICAgICAgICAgIG1heGltdW1JbmRleCA9IGluZGljZXNbal07CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGdlb21ldHJ5LmluZGljZXMgPSBUaXBzaWZ5X2RlZmF1bHQudGlwc2lmeSh7CiAgICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICAgIG1heGltdW1JbmRleCwKICAgICAgICAgICAgY2FjaGVTaXplOiBjYWNoZUNhcGFjaXR5CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGdlb21ldHJ5OwogICAgICB9OwogICAgICBHZW9tZXRyeVBpcGVsaW5lLmZpdFRvVW5zaWduZWRTaG9ydEluZGljZXMgPSBmdW5jdGlvbihnZW9tZXRyeSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImdlb21ldHJ5IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5LmluZGljZXMpICYmIGdlb21ldHJ5LnByaW1pdGl2ZVR5cGUgIT09IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5UUklBTkdMRVMgJiYgZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSAhPT0gUHJpbWl0aXZlVHlwZV9kZWZhdWx0LkxJTkVTICYmIGdlb21ldHJ5LnByaW1pdGl2ZVR5cGUgIT09IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5QT0lOVFMpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICAiZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSBtdXN0IGVxdWFsIHRvIFByaW1pdGl2ZVR5cGUuVFJJQU5HTEVTLCBQcmltaXRpdmVUeXBlLkxJTkVTLCBvciBQcmltaXRpdmVUeXBlLlBPSU5UUy4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBnZW9tZXRyaWVzID0gW107CiAgICAgICAgY29uc3QgbnVtYmVyT2ZWZXJ0aWNlcyA9IEdlb21ldHJ5X2RlZmF1bHQuY29tcHV0ZU51bWJlck9mVmVydGljZXMoZ2VvbWV0cnkpOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZ2VvbWV0cnkuaW5kaWNlcykgJiYgbnVtYmVyT2ZWZXJ0aWNlcyA+PSBNYXRoX2RlZmF1bHQuU0lYVFlfRk9VUl9LSUxPQllURVMpIHsKICAgICAgICAgIGxldCBvbGRUb05ld0luZGV4ID0gW107CiAgICAgICAgICBsZXQgbmV3SW5kaWNlcyA9IFtdOwogICAgICAgICAgbGV0IGN1cnJlbnRJbmRleCA9IDA7CiAgICAgICAgICBsZXQgbmV3QXR0cmlidXRlcyA9IGNvcHlBdHRyaWJ1dGVzRGVzY3JpcHRpb25zKGdlb21ldHJ5LmF0dHJpYnV0ZXMpOwogICAgICAgICAgY29uc3Qgb3JpZ2luYWxJbmRpY2VzID0gZ2VvbWV0cnkuaW5kaWNlczsKICAgICAgICAgIGNvbnN0IG51bWJlck9mSW5kaWNlcyA9IG9yaWdpbmFsSW5kaWNlcy5sZW5ndGg7CiAgICAgICAgICBsZXQgaW5kaWNlc1BlclByaW1pdGl2ZTsKICAgICAgICAgIGlmIChnZW9tZXRyeS5wcmltaXRpdmVUeXBlID09PSBQcmltaXRpdmVUeXBlX2RlZmF1bHQuVFJJQU5HTEVTKSB7CiAgICAgICAgICAgIGluZGljZXNQZXJQcmltaXRpdmUgPSAzOwogICAgICAgICAgfSBlbHNlIGlmIChnZW9tZXRyeS5wcmltaXRpdmVUeXBlID09PSBQcmltaXRpdmVUeXBlX2RlZmF1bHQuTElORVMpIHsKICAgICAgICAgICAgaW5kaWNlc1BlclByaW1pdGl2ZSA9IDI7CiAgICAgICAgICB9IGVsc2UgaWYgKGdlb21ldHJ5LnByaW1pdGl2ZVR5cGUgPT09IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5QT0lOVFMpIHsKICAgICAgICAgICAgaW5kaWNlc1BlclByaW1pdGl2ZSA9IDE7CiAgICAgICAgICB9CiAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG51bWJlck9mSW5kaWNlczsgaiArPSBpbmRpY2VzUGVyUHJpbWl0aXZlKSB7CiAgICAgICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgaW5kaWNlc1BlclByaW1pdGl2ZTsgKytrKSB7CiAgICAgICAgICAgICAgY29uc3QgeCA9IG9yaWdpbmFsSW5kaWNlc1tqICsga107CiAgICAgICAgICAgICAgbGV0IGkgPSBvbGRUb05ld0luZGV4W3hdOwogICAgICAgICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGkpKSB7CiAgICAgICAgICAgICAgICBpID0gY3VycmVudEluZGV4Kys7CiAgICAgICAgICAgICAgICBvbGRUb05ld0luZGV4W3hdID0gaTsKICAgICAgICAgICAgICAgIGNvcHlWZXJ0ZXgobmV3QXR0cmlidXRlcywgZ2VvbWV0cnkuYXR0cmlidXRlcywgeCk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIG5ld0luZGljZXMucHVzaChpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoY3VycmVudEluZGV4ICsgaW5kaWNlc1BlclByaW1pdGl2ZSA+PSBNYXRoX2RlZmF1bHQuU0lYVFlfRk9VUl9LSUxPQllURVMpIHsKICAgICAgICAgICAgICBnZW9tZXRyaWVzLnB1c2goCiAgICAgICAgICAgICAgICBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6IG5ld0F0dHJpYnV0ZXMsCiAgICAgICAgICAgICAgICAgIGluZGljZXM6IG5ld0luZGljZXMsCiAgICAgICAgICAgICAgICAgIHByaW1pdGl2ZVR5cGU6IGdlb21ldHJ5LnByaW1pdGl2ZVR5cGUsCiAgICAgICAgICAgICAgICAgIGJvdW5kaW5nU3BoZXJlOiBnZW9tZXRyeS5ib3VuZGluZ1NwaGVyZSwKICAgICAgICAgICAgICAgICAgYm91bmRpbmdTcGhlcmVDVjogZ2VvbWV0cnkuYm91bmRpbmdTcGhlcmVDVgogICAgICAgICAgICAgICAgfSkKICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIG9sZFRvTmV3SW5kZXggPSBbXTsKICAgICAgICAgICAgICBuZXdJbmRpY2VzID0gW107CiAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gMDsKICAgICAgICAgICAgICBuZXdBdHRyaWJ1dGVzID0gY29weUF0dHJpYnV0ZXNEZXNjcmlwdGlvbnMoZ2VvbWV0cnkuYXR0cmlidXRlcyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChuZXdJbmRpY2VzLmxlbmd0aCAhPT0gMCkgewogICAgICAgICAgICBnZW9tZXRyaWVzLnB1c2goCiAgICAgICAgICAgICAgbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgICAgICAgICAgYXR0cmlidXRlczogbmV3QXR0cmlidXRlcywKICAgICAgICAgICAgICAgIGluZGljZXM6IG5ld0luZGljZXMsCiAgICAgICAgICAgICAgICBwcmltaXRpdmVUeXBlOiBnZW9tZXRyeS5wcmltaXRpdmVUeXBlLAogICAgICAgICAgICAgICAgYm91bmRpbmdTcGhlcmU6IGdlb21ldHJ5LmJvdW5kaW5nU3BoZXJlLAogICAgICAgICAgICAgICAgYm91bmRpbmdTcGhlcmVDVjogZ2VvbWV0cnkuYm91bmRpbmdTcGhlcmVDVgogICAgICAgICAgICAgIH0pCiAgICAgICAgICAgICk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGdlb21ldHJpZXMucHVzaChnZW9tZXRyeSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBnZW9tZXRyaWVzOwogICAgICB9OwogICAgICBzY3JhdGNoUHJvamVjdFRvMkRDYXJ0ZXNpYW4zID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUHJvamVjdFRvMkRDYXJ0b2dyYXBoaWMgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgR2VvbWV0cnlQaXBlbGluZS5wcm9qZWN0VG8yRCA9IGZ1bmN0aW9uKGdlb21ldHJ5LCBhdHRyaWJ1dGVOYW1lLCBhdHRyaWJ1dGVOYW1lM0QsIGF0dHJpYnV0ZU5hbWUyRCwgcHJvamVjdGlvbikgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImdlb21ldHJ5IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVOYW1lKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImF0dHJpYnV0ZU5hbWUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZU5hbWUzRCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhdHRyaWJ1dGVOYW1lM0QgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZU5hbWUyRCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhdHRyaWJ1dGVOYW1lMkQgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgYGdlb21ldHJ5IG11c3QgaGF2ZSBhdHRyaWJ1dGUgbWF0Y2hpbmcgdGhlIGF0dHJpYnV0ZU5hbWUgYXJndW1lbnQ6ICR7YXR0cmlidXRlTmFtZX0uYAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgaWYgKGdlb21ldHJ5LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV0uY29tcG9uZW50RGF0YXR5cGUgIT09IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgIlRoZSBhdHRyaWJ1dGUgY29tcG9uZW50RGF0YXR5cGUgbXVzdCBiZSBDb21wb25lbnREYXRhdHlwZS5ET1VCTEUuIgogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgYXR0cmlidXRlID0gZ2VvbWV0cnkuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXTsKICAgICAgICBwcm9qZWN0aW9uID0gZGVmaW5lZF9kZWZhdWx0KHByb2plY3Rpb24pID8gcHJvamVjdGlvbiA6IG5ldyBHZW9ncmFwaGljUHJvamVjdGlvbl9kZWZhdWx0KCk7CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gcHJvamVjdGlvbi5lbGxpcHNvaWQ7CiAgICAgICAgY29uc3QgdmFsdWVzM0QgPSBhdHRyaWJ1dGUudmFsdWVzOwogICAgICAgIGNvbnN0IHByb2plY3RlZFZhbHVlcyA9IG5ldyBGbG9hdDY0QXJyYXkodmFsdWVzM0QubGVuZ3RoKTsKICAgICAgICBsZXQgaW5kZXggPSAwOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdmFsdWVzM0QubGVuZ3RoOyBpICs9IDMpIHsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgICAgdmFsdWVzM0QsCiAgICAgICAgICAgIGksCiAgICAgICAgICAgIHNjcmF0Y2hQcm9qZWN0VG8yRENhcnRlc2lhbjMKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBsb25MYXQgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMoCiAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICBzY3JhdGNoUHJvamVjdFRvMkRDYXJ0b2dyYXBoaWMKICAgICAgICAgICk7CiAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChsb25MYXQpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICAgIGBDb3VsZCBub3QgcHJvamVjdCBwb2ludCAoJHt2YWx1ZS54fSwgJHt2YWx1ZS55fSwgJHt2YWx1ZS56fSkgdG8gMkQuYAogICAgICAgICAgICApOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgcHJvamVjdGVkTG9uTGF0ID0gcHJvamVjdGlvbi5wcm9qZWN0KAogICAgICAgICAgICBsb25MYXQsCiAgICAgICAgICAgIHNjcmF0Y2hQcm9qZWN0VG8yRENhcnRlc2lhbjMKICAgICAgICAgICk7CiAgICAgICAgICBwcm9qZWN0ZWRWYWx1ZXNbaW5kZXgrK10gPSBwcm9qZWN0ZWRMb25MYXQueDsKICAgICAgICAgIHByb2plY3RlZFZhbHVlc1tpbmRleCsrXSA9IHByb2plY3RlZExvbkxhdC55OwogICAgICAgICAgcHJvamVjdGVkVmFsdWVzW2luZGV4KytdID0gcHJvamVjdGVkTG9uTGF0Lno7CiAgICAgICAgfQogICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZTNEXSA9IGF0dHJpYnV0ZTsKICAgICAgICBnZW9tZXRyeS5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWUyRF0gPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgdmFsdWVzOiBwcm9qZWN0ZWRWYWx1ZXMKICAgICAgICB9KTsKICAgICAgICBkZWxldGUgZ2VvbWV0cnkuYXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXTsKICAgICAgICByZXR1cm4gZ2VvbWV0cnk7CiAgICAgIH07CiAgICAgIGVuY29kZWRSZXN1bHQgPSB7CiAgICAgICAgaGlnaDogMCwKICAgICAgICBsb3c6IDAKICAgICAgfTsKICAgICAgR2VvbWV0cnlQaXBlbGluZS5lbmNvZGVBdHRyaWJ1dGUgPSBmdW5jdGlvbihnZW9tZXRyeSwgYXR0cmlidXRlTmFtZSwgYXR0cmlidXRlSGlnaE5hbWUsIGF0dHJpYnV0ZUxvd05hbWUpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChnZW9tZXRyeSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJnZW9tZXRyeSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlTmFtZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhdHRyaWJ1dGVOYW1lIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVIaWdoTmFtZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhdHRyaWJ1dGVIaWdoTmFtZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlTG93TmFtZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhdHRyaWJ1dGVMb3dOYW1lIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChnZW9tZXRyeS5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgIGBnZW9tZXRyeSBtdXN0IGhhdmUgYXR0cmlidXRlIG1hdGNoaW5nIHRoZSBhdHRyaWJ1dGVOYW1lIGFyZ3VtZW50OiAke2F0dHJpYnV0ZU5hbWV9LmAKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGlmIChnZW9tZXRyeS5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdLmNvbXBvbmVudERhdGF0eXBlICE9PSBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJUaGUgYXR0cmlidXRlIGNvbXBvbmVudERhdGF0eXBlIG11c3QgYmUgQ29tcG9uZW50RGF0YXR5cGUuRE9VQkxFLiIKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGF0dHJpYnV0ZSA9IGdlb21ldHJ5LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV07CiAgICAgICAgY29uc3QgdmFsdWVzID0gYXR0cmlidXRlLnZhbHVlczsKICAgICAgICBjb25zdCBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoOwogICAgICAgIGNvbnN0IGhpZ2hWYWx1ZXMgPSBuZXcgRmxvYXQzMkFycmF5KGxlbmd0aCk7CiAgICAgICAgY29uc3QgbG93VmFsdWVzID0gbmV3IEZsb2F0MzJBcnJheShsZW5ndGgpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgIEVuY29kZWRDYXJ0ZXNpYW4zX2RlZmF1bHQuZW5jb2RlKHZhbHVlc1tpXSwgZW5jb2RlZFJlc3VsdCk7CiAgICAgICAgICBoaWdoVmFsdWVzW2ldID0gZW5jb2RlZFJlc3VsdC5oaWdoOwogICAgICAgICAgbG93VmFsdWVzW2ldID0gZW5jb2RlZFJlc3VsdC5sb3c7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGNvbXBvbmVudHNQZXJBdHRyaWJ1dGUgPSBhdHRyaWJ1dGUuY29tcG9uZW50c1BlckF0dHJpYnV0ZTsKICAgICAgICBnZW9tZXRyeS5hdHRyaWJ1dGVzW2F0dHJpYnV0ZUhpZ2hOYW1lXSA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZSwKICAgICAgICAgIHZhbHVlczogaGlnaFZhbHVlcwogICAgICAgIH0pOwogICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXNbYXR0cmlidXRlTG93TmFtZV0gPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGUsCiAgICAgICAgICB2YWx1ZXM6IGxvd1ZhbHVlcwogICAgICAgIH0pOwogICAgICAgIGRlbGV0ZSBnZW9tZXRyeS5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdOwogICAgICAgIHJldHVybiBnZW9tZXRyeTsKICAgICAgfTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjMzID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBpbnZlcnNlVHJhbnNwb3NlID0gbmV3IE1hdHJpeDRfZGVmYXVsdCgpOwogICAgICBub3JtYWxNYXRyaXggPSBuZXcgTWF0cml4M19kZWZhdWx0KCk7CiAgICAgIEdlb21ldHJ5UGlwZWxpbmUudHJhbnNmb3JtVG9Xb3JsZENvb3JkaW5hdGVzID0gZnVuY3Rpb24oaW5zdGFuY2UpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpbnN0YW5jZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJpbnN0YW5jZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbW9kZWxNYXRyaXggPSBpbnN0YW5jZS5tb2RlbE1hdHJpeDsKICAgICAgICBpZiAoTWF0cml4NF9kZWZhdWx0LmVxdWFscyhtb2RlbE1hdHJpeCwgTWF0cml4NF9kZWZhdWx0LklERU5USVRZKSkgewogICAgICAgICAgcmV0dXJuIGluc3RhbmNlOwogICAgICAgIH0KICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gaW5zdGFuY2UuZ2VvbWV0cnkuYXR0cmlidXRlczsKICAgICAgICB0cmFuc2Zvcm1Qb2ludChtb2RlbE1hdHJpeCwgYXR0cmlidXRlcy5wb3NpdGlvbik7CiAgICAgICAgdHJhbnNmb3JtUG9pbnQobW9kZWxNYXRyaXgsIGF0dHJpYnV0ZXMucHJldlBvc2l0aW9uKTsKICAgICAgICB0cmFuc2Zvcm1Qb2ludChtb2RlbE1hdHJpeCwgYXR0cmlidXRlcy5uZXh0UG9zaXRpb24pOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlcy5ub3JtYWwpIHx8IGRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVzLnRhbmdlbnQpIHx8IGRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVzLmJpdGFuZ2VudCkpIHsKICAgICAgICAgIE1hdHJpeDRfZGVmYXVsdC5pbnZlcnNlKG1vZGVsTWF0cml4LCBpbnZlcnNlVHJhbnNwb3NlKTsKICAgICAgICAgIE1hdHJpeDRfZGVmYXVsdC50cmFuc3Bvc2UoaW52ZXJzZVRyYW5zcG9zZSwgaW52ZXJzZVRyYW5zcG9zZSk7CiAgICAgICAgICBNYXRyaXg0X2RlZmF1bHQuZ2V0TWF0cml4MyhpbnZlcnNlVHJhbnNwb3NlLCBub3JtYWxNYXRyaXgpOwogICAgICAgICAgdHJhbnNmb3JtVmVjdG9yKG5vcm1hbE1hdHJpeCwgYXR0cmlidXRlcy5ub3JtYWwpOwogICAgICAgICAgdHJhbnNmb3JtVmVjdG9yKG5vcm1hbE1hdHJpeCwgYXR0cmlidXRlcy50YW5nZW50KTsKICAgICAgICAgIHRyYW5zZm9ybVZlY3Rvcihub3JtYWxNYXRyaXgsIGF0dHJpYnV0ZXMuYml0YW5nZW50KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgYm91bmRpbmdTcGhlcmUgPSBpbnN0YW5jZS5nZW9tZXRyeS5ib3VuZGluZ1NwaGVyZTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGJvdW5kaW5nU3BoZXJlKSkgewogICAgICAgICAgaW5zdGFuY2UuZ2VvbWV0cnkuYm91bmRpbmdTcGhlcmUgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LnRyYW5zZm9ybSgKICAgICAgICAgICAgYm91bmRpbmdTcGhlcmUsCiAgICAgICAgICAgIG1vZGVsTWF0cml4LAogICAgICAgICAgICBib3VuZGluZ1NwaGVyZQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgaW5zdGFuY2UubW9kZWxNYXRyaXggPSBNYXRyaXg0X2RlZmF1bHQuY2xvbmUoTWF0cml4NF9kZWZhdWx0LklERU5USVRZKTsKICAgICAgICByZXR1cm4gaW5zdGFuY2U7CiAgICAgIH07CiAgICAgIHRlbXBTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBHZW9tZXRyeVBpcGVsaW5lLmNvbWJpbmVJbnN0YW5jZXMgPSBmdW5jdGlvbihpbnN0YW5jZXMpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpbnN0YW5jZXMpIHx8IGluc3RhbmNlcy5sZW5ndGggPCAxKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgImluc3RhbmNlcyBpcyByZXF1aXJlZCBhbmQgbXVzdCBoYXZlIGxlbmd0aCBncmVhdGVyIHRoYW4gemVyby4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBpbnN0YW5jZUdlb21ldHJ5ID0gW107CiAgICAgICAgY29uc3QgaW5zdGFuY2VTcGxpdEdlb21ldHJ5ID0gW107CiAgICAgICAgY29uc3QgbGVuZ3RoID0gaW5zdGFuY2VzLmxlbmd0aDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICBjb25zdCBpbnN0YW5jZSA9IGluc3RhbmNlc1tpXTsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaW5zdGFuY2UuZ2VvbWV0cnkpKSB7CiAgICAgICAgICAgIGluc3RhbmNlR2VvbWV0cnkucHVzaChpbnN0YW5jZSk7CiAgICAgICAgICB9IGVsc2UgaWYgKGRlZmluZWRfZGVmYXVsdChpbnN0YW5jZS53ZXN0SGVtaXNwaGVyZUdlb21ldHJ5KSAmJiBkZWZpbmVkX2RlZmF1bHQoaW5zdGFuY2UuZWFzdEhlbWlzcGhlcmVHZW9tZXRyeSkpIHsKICAgICAgICAgICAgaW5zdGFuY2VTcGxpdEdlb21ldHJ5LnB1c2goaW5zdGFuY2UpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBnZW9tZXRyaWVzID0gW107CiAgICAgICAgaWYgKGluc3RhbmNlR2VvbWV0cnkubGVuZ3RoID4gMCkgewogICAgICAgICAgZ2VvbWV0cmllcy5wdXNoKGNvbWJpbmVHZW9tZXRyaWVzKGluc3RhbmNlR2VvbWV0cnksICJnZW9tZXRyeSIpKTsKICAgICAgICB9CiAgICAgICAgaWYgKGluc3RhbmNlU3BsaXRHZW9tZXRyeS5sZW5ndGggPiAwKSB7CiAgICAgICAgICBnZW9tZXRyaWVzLnB1c2goCiAgICAgICAgICAgIGNvbWJpbmVHZW9tZXRyaWVzKGluc3RhbmNlU3BsaXRHZW9tZXRyeSwgIndlc3RIZW1pc3BoZXJlR2VvbWV0cnkiKQogICAgICAgICAgKTsKICAgICAgICAgIGdlb21ldHJpZXMucHVzaCgKICAgICAgICAgICAgY29tYmluZUdlb21ldHJpZXMoaW5zdGFuY2VTcGxpdEdlb21ldHJ5LCAiZWFzdEhlbWlzcGhlcmVHZW9tZXRyeSIpCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZ2VvbWV0cmllczsKICAgICAgfTsKICAgICAgbm9ybWFsID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICB2MCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgdjEgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHYyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBHZW9tZXRyeVBpcGVsaW5lLmNvbXB1dGVOb3JtYWwgPSBmdW5jdGlvbihnZW9tZXRyeSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImdlb21ldHJ5IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uKSB8fCAhZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcyBpcyByZXF1aXJlZC4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChnZW9tZXRyeS5pbmRpY2VzKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImdlb21ldHJ5LmluZGljZXMgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmIChnZW9tZXRyeS5pbmRpY2VzLmxlbmd0aCA8IDIgfHwgZ2VvbWV0cnkuaW5kaWNlcy5sZW5ndGggJSAzICE9PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgImdlb21ldHJ5LmluZGljZXMgbGVuZ3RoIG11c3QgYmUgZ3JlYXRlciB0aGFuIDAgYW5kIGJlIGEgbXVsdGlwbGUgb2YgMy4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBpZiAoZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSAhPT0gUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUykgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJnZW9tZXRyeS5wcmltaXRpdmVUeXBlIG11c3QgYmUgUHJpbWl0aXZlVHlwZS5UUklBTkdMRVMuIgogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgaW5kaWNlcyA9IGdlb21ldHJ5LmluZGljZXM7CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IGdlb21ldHJ5LmF0dHJpYnV0ZXM7CiAgICAgICAgY29uc3QgdmVydGljZXMgPSBhdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlczsKICAgICAgICBjb25zdCBudW1WZXJ0aWNlcyA9IGF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLmxlbmd0aCAvIDM7CiAgICAgICAgY29uc3QgbnVtSW5kaWNlcyA9IGluZGljZXMubGVuZ3RoOwogICAgICAgIGNvbnN0IG5vcm1hbHNQZXJWZXJ0ZXggPSBuZXcgQXJyYXkobnVtVmVydGljZXMpOwogICAgICAgIGNvbnN0IG5vcm1hbHNQZXJUcmlhbmdsZSA9IG5ldyBBcnJheShudW1JbmRpY2VzIC8gMyk7CiAgICAgICAgY29uc3Qgbm9ybWFsSW5kaWNlcyA9IG5ldyBBcnJheShudW1JbmRpY2VzKTsKICAgICAgICBsZXQgaTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtVmVydGljZXM7IGkrKykgewogICAgICAgICAgbm9ybWFsc1BlclZlcnRleFtpXSA9IHsKICAgICAgICAgICAgaW5kZXhPZmZzZXQ6IDAsCiAgICAgICAgICAgIGNvdW50OiAwLAogICAgICAgICAgICBjdXJyZW50Q291bnQ6IDAKICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIGxldCBqID0gMDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtSW5kaWNlczsgaSArPSAzKSB7CiAgICAgICAgICBjb25zdCBpMCA9IGluZGljZXNbaV07CiAgICAgICAgICBjb25zdCBpMSA9IGluZGljZXNbaSArIDFdOwogICAgICAgICAgY29uc3QgaTIgPSBpbmRpY2VzW2kgKyAyXTsKICAgICAgICAgIGNvbnN0IGkwMyA9IGkwICogMzsKICAgICAgICAgIGNvbnN0IGkxMyA9IGkxICogMzsKICAgICAgICAgIGNvbnN0IGkyMyA9IGkyICogMzsKICAgICAgICAgIHYwLnggPSB2ZXJ0aWNlc1tpMDNdOwogICAgICAgICAgdjAueSA9IHZlcnRpY2VzW2kwMyArIDFdOwogICAgICAgICAgdjAueiA9IHZlcnRpY2VzW2kwMyArIDJdOwogICAgICAgICAgdjEueCA9IHZlcnRpY2VzW2kxM107CiAgICAgICAgICB2MS55ID0gdmVydGljZXNbaTEzICsgMV07CiAgICAgICAgICB2MS56ID0gdmVydGljZXNbaTEzICsgMl07CiAgICAgICAgICB2Mi54ID0gdmVydGljZXNbaTIzXTsKICAgICAgICAgIHYyLnkgPSB2ZXJ0aWNlc1tpMjMgKyAxXTsKICAgICAgICAgIHYyLnogPSB2ZXJ0aWNlc1tpMjMgKyAyXTsKICAgICAgICAgIG5vcm1hbHNQZXJWZXJ0ZXhbaTBdLmNvdW50Kys7CiAgICAgICAgICBub3JtYWxzUGVyVmVydGV4W2kxXS5jb3VudCsrOwogICAgICAgICAgbm9ybWFsc1BlclZlcnRleFtpMl0uY291bnQrKzsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCh2MSwgdjAsIHYxKTsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCh2MiwgdjAsIHYyKTsKICAgICAgICAgIG5vcm1hbHNQZXJUcmlhbmdsZVtqXSA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyh2MSwgdjIsIG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKSk7CiAgICAgICAgICBqKys7CiAgICAgICAgfQogICAgICAgIGxldCBpbmRleE9mZnNldCA9IDA7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IG51bVZlcnRpY2VzOyBpKyspIHsKICAgICAgICAgIG5vcm1hbHNQZXJWZXJ0ZXhbaV0uaW5kZXhPZmZzZXQgKz0gaW5kZXhPZmZzZXQ7CiAgICAgICAgICBpbmRleE9mZnNldCArPSBub3JtYWxzUGVyVmVydGV4W2ldLmNvdW50OwogICAgICAgIH0KICAgICAgICBqID0gMDsKICAgICAgICBsZXQgdmVydGV4Tm9ybWFsRGF0YTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtSW5kaWNlczsgaSArPSAzKSB7CiAgICAgICAgICB2ZXJ0ZXhOb3JtYWxEYXRhID0gbm9ybWFsc1BlclZlcnRleFtpbmRpY2VzW2ldXTsKICAgICAgICAgIGxldCBpbmRleCA9IHZlcnRleE5vcm1hbERhdGEuaW5kZXhPZmZzZXQgKyB2ZXJ0ZXhOb3JtYWxEYXRhLmN1cnJlbnRDb3VudDsKICAgICAgICAgIG5vcm1hbEluZGljZXNbaW5kZXhdID0gajsKICAgICAgICAgIHZlcnRleE5vcm1hbERhdGEuY3VycmVudENvdW50Kys7CiAgICAgICAgICB2ZXJ0ZXhOb3JtYWxEYXRhID0gbm9ybWFsc1BlclZlcnRleFtpbmRpY2VzW2kgKyAxXV07CiAgICAgICAgICBpbmRleCA9IHZlcnRleE5vcm1hbERhdGEuaW5kZXhPZmZzZXQgKyB2ZXJ0ZXhOb3JtYWxEYXRhLmN1cnJlbnRDb3VudDsKICAgICAgICAgIG5vcm1hbEluZGljZXNbaW5kZXhdID0gajsKICAgICAgICAgIHZlcnRleE5vcm1hbERhdGEuY3VycmVudENvdW50Kys7CiAgICAgICAgICB2ZXJ0ZXhOb3JtYWxEYXRhID0gbm9ybWFsc1BlclZlcnRleFtpbmRpY2VzW2kgKyAyXV07CiAgICAgICAgICBpbmRleCA9IHZlcnRleE5vcm1hbERhdGEuaW5kZXhPZmZzZXQgKyB2ZXJ0ZXhOb3JtYWxEYXRhLmN1cnJlbnRDb3VudDsKICAgICAgICAgIG5vcm1hbEluZGljZXNbaW5kZXhdID0gajsKICAgICAgICAgIHZlcnRleE5vcm1hbERhdGEuY3VycmVudENvdW50Kys7CiAgICAgICAgICBqKys7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG5vcm1hbFZhbHVlcyA9IG5ldyBGbG9hdDMyQXJyYXkobnVtVmVydGljZXMgKiAzKTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtVmVydGljZXM7IGkrKykgewogICAgICAgICAgY29uc3QgaTMgPSBpICogMzsKICAgICAgICAgIHZlcnRleE5vcm1hbERhdGEgPSBub3JtYWxzUGVyVmVydGV4W2ldOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLCBub3JtYWwpOwogICAgICAgICAgaWYgKHZlcnRleE5vcm1hbERhdGEuY291bnQgPiAwKSB7CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCB2ZXJ0ZXhOb3JtYWxEYXRhLmNvdW50OyBqKyspIHsKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKAogICAgICAgICAgICAgICAgbm9ybWFsLAogICAgICAgICAgICAgICAgbm9ybWFsc1BlclRyaWFuZ2xlW25vcm1hbEluZGljZXNbdmVydGV4Tm9ybWFsRGF0YS5pbmRleE9mZnNldCArIGpdXSwKICAgICAgICAgICAgICAgIG5vcm1hbAogICAgICAgICAgICAgICk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLCBub3JtYWwsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTApKSB7CiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKAogICAgICAgICAgICAgICAgbm9ybWFsc1BlclRyaWFuZ2xlW25vcm1hbEluZGljZXNbdmVydGV4Tm9ybWFsRGF0YS5pbmRleE9mZnNldF1dLAogICAgICAgICAgICAgICAgbm9ybWFsCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLCBub3JtYWwsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTApKSB7CiAgICAgICAgICAgIG5vcm1hbC56ID0gMTsKICAgICAgICAgIH0KICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUobm9ybWFsLCBub3JtYWwpOwogICAgICAgICAgbm9ybWFsVmFsdWVzW2kzXSA9IG5vcm1hbC54OwogICAgICAgICAgbm9ybWFsVmFsdWVzW2kzICsgMV0gPSBub3JtYWwueTsKICAgICAgICAgIG5vcm1hbFZhbHVlc1tpMyArIDJdID0gbm9ybWFsLno7CiAgICAgICAgfQogICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMubm9ybWFsID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgdmFsdWVzOiBub3JtYWxWYWx1ZXMKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gZ2VvbWV0cnk7CiAgICAgIH07CiAgICAgIG5vcm1hbFNjcmF0Y2gyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBub3JtYWxTY2FsZSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgdFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIEdlb21ldHJ5UGlwZWxpbmUuY29tcHV0ZVRhbmdlbnRBbmRCaXRhbmdlbnQgPSBmdW5jdGlvbihnZW9tZXRyeSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImdlb21ldHJ5IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gZ2VvbWV0cnkuYXR0cmlidXRlczsKICAgICAgICBjb25zdCBpbmRpY2VzID0gZ2VvbWV0cnkuaW5kaWNlczsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVzLnBvc2l0aW9uKSB8fCAhZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcyBpcyByZXF1aXJlZC4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVzLm5vcm1hbCkgfHwgIWRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVzLm5vcm1hbC52YWx1ZXMpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZ2VvbWV0cnkuYXR0cmlidXRlcy5ub3JtYWwudmFsdWVzIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVzLnN0KSB8fCAhZGVmaW5lZF9kZWZhdWx0KGF0dHJpYnV0ZXMuc3QudmFsdWVzKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImdlb21ldHJ5LmF0dHJpYnV0ZXMuc3QudmFsdWVzIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpbmRpY2VzKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImdlb21ldHJ5LmluZGljZXMgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA8IDIgfHwgaW5kaWNlcy5sZW5ndGggJSAzICE9PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgImdlb21ldHJ5LmluZGljZXMgbGVuZ3RoIG11c3QgYmUgZ3JlYXRlciB0aGFuIDAgYW5kIGJlIGEgbXVsdGlwbGUgb2YgMy4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBpZiAoZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSAhPT0gUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUykgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJnZW9tZXRyeS5wcmltaXRpdmVUeXBlIG11c3QgYmUgUHJpbWl0aXZlVHlwZS5UUklBTkdMRVMuIgogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgdmVydGljZXMgPSBnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlczsKICAgICAgICBjb25zdCBub3JtYWxzID0gZ2VvbWV0cnkuYXR0cmlidXRlcy5ub3JtYWwudmFsdWVzOwogICAgICAgIGNvbnN0IHN0ID0gZ2VvbWV0cnkuYXR0cmlidXRlcy5zdC52YWx1ZXM7CiAgICAgICAgY29uc3QgbnVtVmVydGljZXMgPSBnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5sZW5ndGggLyAzOwogICAgICAgIGNvbnN0IG51bUluZGljZXMgPSBpbmRpY2VzLmxlbmd0aDsKICAgICAgICBjb25zdCB0YW4xID0gbmV3IEFycmF5KG51bVZlcnRpY2VzICogMyk7CiAgICAgICAgbGV0IGk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhbjEubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHRhbjFbaV0gPSAwOwogICAgICAgIH0KICAgICAgICBsZXQgaTAzOwogICAgICAgIGxldCBpMTM7CiAgICAgICAgbGV0IGkyMzsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtSW5kaWNlczsgaSArPSAzKSB7CiAgICAgICAgICBjb25zdCBpMCA9IGluZGljZXNbaV07CiAgICAgICAgICBjb25zdCBpMSA9IGluZGljZXNbaSArIDFdOwogICAgICAgICAgY29uc3QgaTIgPSBpbmRpY2VzW2kgKyAyXTsKICAgICAgICAgIGkwMyA9IGkwICogMzsKICAgICAgICAgIGkxMyA9IGkxICogMzsKICAgICAgICAgIGkyMyA9IGkyICogMzsKICAgICAgICAgIGNvbnN0IGkwMiA9IGkwICogMjsKICAgICAgICAgIGNvbnN0IGkxMiA9IGkxICogMjsKICAgICAgICAgIGNvbnN0IGkyMiA9IGkyICogMjsKICAgICAgICAgIGNvbnN0IHV4ID0gdmVydGljZXNbaTAzXTsKICAgICAgICAgIGNvbnN0IHV5ID0gdmVydGljZXNbaTAzICsgMV07CiAgICAgICAgICBjb25zdCB1eiA9IHZlcnRpY2VzW2kwMyArIDJdOwogICAgICAgICAgY29uc3Qgd3ggPSBzdFtpMDJdOwogICAgICAgICAgY29uc3Qgd3kgPSBzdFtpMDIgKyAxXTsKICAgICAgICAgIGNvbnN0IHQxID0gc3RbaTEyICsgMV0gLSB3eTsKICAgICAgICAgIGNvbnN0IHQyID0gc3RbaTIyICsgMV0gLSB3eTsKICAgICAgICAgIGNvbnN0IHIgPSAxIC8gKChzdFtpMTJdIC0gd3gpICogdDIgLSAoc3RbaTIyXSAtIHd4KSAqIHQxKTsKICAgICAgICAgIGNvbnN0IHNkaXJ4ID0gKHQyICogKHZlcnRpY2VzW2kxM10gLSB1eCkgLSB0MSAqICh2ZXJ0aWNlc1tpMjNdIC0gdXgpKSAqIHI7CiAgICAgICAgICBjb25zdCBzZGlyeSA9ICh0MiAqICh2ZXJ0aWNlc1tpMTMgKyAxXSAtIHV5KSAtIHQxICogKHZlcnRpY2VzW2kyMyArIDFdIC0gdXkpKSAqIHI7CiAgICAgICAgICBjb25zdCBzZGlyeiA9ICh0MiAqICh2ZXJ0aWNlc1tpMTMgKyAyXSAtIHV6KSAtIHQxICogKHZlcnRpY2VzW2kyMyArIDJdIC0gdXopKSAqIHI7CiAgICAgICAgICB0YW4xW2kwM10gKz0gc2Rpcng7CiAgICAgICAgICB0YW4xW2kwMyArIDFdICs9IHNkaXJ5OwogICAgICAgICAgdGFuMVtpMDMgKyAyXSArPSBzZGlyejsKICAgICAgICAgIHRhbjFbaTEzXSArPSBzZGlyeDsKICAgICAgICAgIHRhbjFbaTEzICsgMV0gKz0gc2Rpcnk7CiAgICAgICAgICB0YW4xW2kxMyArIDJdICs9IHNkaXJ6OwogICAgICAgICAgdGFuMVtpMjNdICs9IHNkaXJ4OwogICAgICAgICAgdGFuMVtpMjMgKyAxXSArPSBzZGlyeTsKICAgICAgICAgIHRhbjFbaTIzICsgMl0gKz0gc2Rpcno7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHRhbmdlbnRWYWx1ZXMgPSBuZXcgRmxvYXQzMkFycmF5KG51bVZlcnRpY2VzICogMyk7CiAgICAgICAgY29uc3QgYml0YW5nZW50VmFsdWVzID0gbmV3IEZsb2F0MzJBcnJheShudW1WZXJ0aWNlcyAqIDMpOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1WZXJ0aWNlczsgaSsrKSB7CiAgICAgICAgICBpMDMgPSBpICogMzsKICAgICAgICAgIGkxMyA9IGkwMyArIDE7CiAgICAgICAgICBpMjMgPSBpMDMgKyAyOwogICAgICAgICAgY29uc3QgbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkobm9ybWFscywgaTAzLCBub3JtYWxTY3JhdGNoMik7CiAgICAgICAgICBjb25zdCB0ID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSh0YW4xLCBpMDMsIHRTY3JhdGNoKTsKICAgICAgICAgIGNvbnN0IHNjYWxhciA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QobiwgdCk7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihuLCBzY2FsYXIsIG5vcm1hbFNjYWxlKTsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHQsIG5vcm1hbFNjYWxlLCB0KSwgdCk7CiAgICAgICAgICB0YW5nZW50VmFsdWVzW2kwM10gPSB0Lng7CiAgICAgICAgICB0YW5nZW50VmFsdWVzW2kxM10gPSB0Lnk7CiAgICAgICAgICB0YW5nZW50VmFsdWVzW2kyM10gPSB0Lno7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhuLCB0LCB0KSwgdCk7CiAgICAgICAgICBiaXRhbmdlbnRWYWx1ZXNbaTAzXSA9IHQueDsKICAgICAgICAgIGJpdGFuZ2VudFZhbHVlc1tpMTNdID0gdC55OwogICAgICAgICAgYml0YW5nZW50VmFsdWVzW2kyM10gPSB0Lno7CiAgICAgICAgfQogICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMudGFuZ2VudCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgIHZhbHVlczogdGFuZ2VudFZhbHVlcwogICAgICAgIH0pOwogICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMuYml0YW5nZW50ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgdmFsdWVzOiBiaXRhbmdlbnRWYWx1ZXMKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gZ2VvbWV0cnk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4yMiA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKTsKICAgICAgdG9FbmNvZGUxID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICB0b0VuY29kZTIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHRvRW5jb2RlMyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZW5jb2RlUmVzdWx0MiA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKTsKICAgICAgR2VvbWV0cnlQaXBlbGluZS5jb21wcmVzc1ZlcnRpY2VzID0gZnVuY3Rpb24oZ2VvbWV0cnkpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChnZW9tZXRyeSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJnZW9tZXRyeSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZXh0cnVkZUF0dHJpYnV0ZSA9IGdlb21ldHJ5LmF0dHJpYnV0ZXMuZXh0cnVkZURpcmVjdGlvbjsKICAgICAgICBsZXQgaTsKICAgICAgICBsZXQgbnVtVmVydGljZXM7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChleHRydWRlQXR0cmlidXRlKSkgewogICAgICAgICAgY29uc3QgZXh0cnVkZURpcmVjdGlvbnMgPSBleHRydWRlQXR0cmlidXRlLnZhbHVlczsKICAgICAgICAgIG51bVZlcnRpY2VzID0gZXh0cnVkZURpcmVjdGlvbnMubGVuZ3RoIC8gMzsKICAgICAgICAgIGNvbnN0IGNvbXByZXNzZWREaXJlY3Rpb25zID0gbmV3IEZsb2F0MzJBcnJheShudW1WZXJ0aWNlcyAqIDIpOwogICAgICAgICAgbGV0IGkyID0gMDsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1WZXJ0aWNlczsgKytpKSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoZXh0cnVkZURpcmVjdGlvbnMsIGkgKiAzLCB0b0VuY29kZTEpOwogICAgICAgICAgICBpZiAoQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFscyh0b0VuY29kZTEsIENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPKSkgewogICAgICAgICAgICAgIGkyICs9IDI7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW5jb2RlUmVzdWx0MiA9IEF0dHJpYnV0ZUNvbXByZXNzaW9uX2RlZmF1bHQub2N0RW5jb2RlSW5SYW5nZSgKICAgICAgICAgICAgICB0b0VuY29kZTEsCiAgICAgICAgICAgICAgNjU1MzUsCiAgICAgICAgICAgICAgZW5jb2RlUmVzdWx0MgogICAgICAgICAgICApOwogICAgICAgICAgICBjb21wcmVzc2VkRGlyZWN0aW9uc1tpMisrXSA9IGVuY29kZVJlc3VsdDIueDsKICAgICAgICAgICAgY29tcHJlc3NlZERpcmVjdGlvbnNbaTIrK10gPSBlbmNvZGVSZXN1bHQyLnk7CiAgICAgICAgICB9CiAgICAgICAgICBnZW9tZXRyeS5hdHRyaWJ1dGVzLmNvbXByZXNzZWRBdHRyaWJ1dGVzID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMiwKICAgICAgICAgICAgdmFsdWVzOiBjb21wcmVzc2VkRGlyZWN0aW9ucwogICAgICAgICAgfSk7CiAgICAgICAgICBkZWxldGUgZ2VvbWV0cnkuYXR0cmlidXRlcy5leHRydWRlRGlyZWN0aW9uOwogICAgICAgICAgcmV0dXJuIGdlb21ldHJ5OwogICAgICAgIH0KICAgICAgICBjb25zdCBub3JtYWxBdHRyaWJ1dGUgPSBnZW9tZXRyeS5hdHRyaWJ1dGVzLm5vcm1hbDsKICAgICAgICBjb25zdCBzdEF0dHJpYnV0ZSA9IGdlb21ldHJ5LmF0dHJpYnV0ZXMuc3Q7CiAgICAgICAgY29uc3QgaGFzTm9ybWFsID0gZGVmaW5lZF9kZWZhdWx0KG5vcm1hbEF0dHJpYnV0ZSk7CiAgICAgICAgY29uc3QgaGFzU3QgPSBkZWZpbmVkX2RlZmF1bHQoc3RBdHRyaWJ1dGUpOwogICAgICAgIGlmICghaGFzTm9ybWFsICYmICFoYXNTdCkgewogICAgICAgICAgcmV0dXJuIGdlb21ldHJ5OwogICAgICAgIH0KICAgICAgICBjb25zdCB0YW5nZW50QXR0cmlidXRlID0gZ2VvbWV0cnkuYXR0cmlidXRlcy50YW5nZW50OwogICAgICAgIGNvbnN0IGJpdGFuZ2VudEF0dHJpYnV0ZSA9IGdlb21ldHJ5LmF0dHJpYnV0ZXMuYml0YW5nZW50OwogICAgICAgIGNvbnN0IGhhc1RhbmdlbnQgPSBkZWZpbmVkX2RlZmF1bHQodGFuZ2VudEF0dHJpYnV0ZSk7CiAgICAgICAgY29uc3QgaGFzQml0YW5nZW50ID0gZGVmaW5lZF9kZWZhdWx0KGJpdGFuZ2VudEF0dHJpYnV0ZSk7CiAgICAgICAgbGV0IG5vcm1hbHM7CiAgICAgICAgbGV0IHN0OwogICAgICAgIGxldCB0YW5nZW50czsKICAgICAgICBsZXQgYml0YW5nZW50czsKICAgICAgICBpZiAoaGFzTm9ybWFsKSB7CiAgICAgICAgICBub3JtYWxzID0gbm9ybWFsQXR0cmlidXRlLnZhbHVlczsKICAgICAgICB9CiAgICAgICAgaWYgKGhhc1N0KSB7CiAgICAgICAgICBzdCA9IHN0QXR0cmlidXRlLnZhbHVlczsKICAgICAgICB9CiAgICAgICAgaWYgKGhhc1RhbmdlbnQpIHsKICAgICAgICAgIHRhbmdlbnRzID0gdGFuZ2VudEF0dHJpYnV0ZS52YWx1ZXM7CiAgICAgICAgfQogICAgICAgIGlmIChoYXNCaXRhbmdlbnQpIHsKICAgICAgICAgIGJpdGFuZ2VudHMgPSBiaXRhbmdlbnRBdHRyaWJ1dGUudmFsdWVzOwogICAgICAgIH0KICAgICAgICBjb25zdCBsZW5ndGggPSBoYXNOb3JtYWwgPyBub3JtYWxzLmxlbmd0aCA6IHN0Lmxlbmd0aDsKICAgICAgICBjb25zdCBudW1Db21wb25lbnRzID0gaGFzTm9ybWFsID8gMyA6IDI7CiAgICAgICAgbnVtVmVydGljZXMgPSBsZW5ndGggLyBudW1Db21wb25lbnRzOwogICAgICAgIGxldCBjb21wcmVzc2VkTGVuZ3RoID0gbnVtVmVydGljZXM7CiAgICAgICAgbGV0IG51bUNvbXByZXNzZWRDb21wb25lbnRzID0gaGFzU3QgJiYgaGFzTm9ybWFsID8gMiA6IDE7CiAgICAgICAgbnVtQ29tcHJlc3NlZENvbXBvbmVudHMgKz0gaGFzVGFuZ2VudCB8fCBoYXNCaXRhbmdlbnQgPyAxIDogMDsKICAgICAgICBjb21wcmVzc2VkTGVuZ3RoICo9IG51bUNvbXByZXNzZWRDb21wb25lbnRzOwogICAgICAgIGNvbnN0IGNvbXByZXNzZWRBdHRyaWJ1dGVzID0gbmV3IEZsb2F0MzJBcnJheShjb21wcmVzc2VkTGVuZ3RoKTsKICAgICAgICBsZXQgbm9ybWFsSW5kZXggPSAwOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1WZXJ0aWNlczsgKytpKSB7CiAgICAgICAgICBpZiAoaGFzU3QpIHsKICAgICAgICAgICAgQ2FydGVzaWFuMl9kZWZhdWx0LmZyb21BcnJheShzdCwgaSAqIDIsIHNjcmF0Y2hDYXJ0ZXNpYW4yMik7CiAgICAgICAgICAgIGNvbXByZXNzZWRBdHRyaWJ1dGVzW25vcm1hbEluZGV4KytdID0gQXR0cmlidXRlQ29tcHJlc3Npb25fZGVmYXVsdC5jb21wcmVzc1RleHR1cmVDb29yZGluYXRlcyhzY3JhdGNoQ2FydGVzaWFuMjIpOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgaW5kZXggPSBpICogMzsKICAgICAgICAgIGlmIChoYXNOb3JtYWwgJiYgZGVmaW5lZF9kZWZhdWx0KHRhbmdlbnRzKSAmJiBkZWZpbmVkX2RlZmF1bHQoYml0YW5nZW50cykpIHsKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShub3JtYWxzLCBpbmRleCwgdG9FbmNvZGUxKTsKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSh0YW5nZW50cywgaW5kZXgsIHRvRW5jb2RlMik7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoYml0YW5nZW50cywgaW5kZXgsIHRvRW5jb2RlMyk7CiAgICAgICAgICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uX2RlZmF1bHQub2N0UGFjaygKICAgICAgICAgICAgICB0b0VuY29kZTEsCiAgICAgICAgICAgICAgdG9FbmNvZGUyLAogICAgICAgICAgICAgIHRvRW5jb2RlMywKICAgICAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuMjIKICAgICAgICAgICAgKTsKICAgICAgICAgICAgY29tcHJlc3NlZEF0dHJpYnV0ZXNbbm9ybWFsSW5kZXgrK10gPSBzY3JhdGNoQ2FydGVzaWFuMjIueDsKICAgICAgICAgICAgY29tcHJlc3NlZEF0dHJpYnV0ZXNbbm9ybWFsSW5kZXgrK10gPSBzY3JhdGNoQ2FydGVzaWFuMjIueTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmIChoYXNOb3JtYWwpIHsKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KG5vcm1hbHMsIGluZGV4LCB0b0VuY29kZTEpOwogICAgICAgICAgICAgIGNvbXByZXNzZWRBdHRyaWJ1dGVzW25vcm1hbEluZGV4KytdID0gQXR0cmlidXRlQ29tcHJlc3Npb25fZGVmYXVsdC5vY3RFbmNvZGVGbG9hdCh0b0VuY29kZTEpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChoYXNUYW5nZW50KSB7CiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSh0YW5nZW50cywgaW5kZXgsIHRvRW5jb2RlMSk7CiAgICAgICAgICAgICAgY29tcHJlc3NlZEF0dHJpYnV0ZXNbbm9ybWFsSW5kZXgrK10gPSBBdHRyaWJ1dGVDb21wcmVzc2lvbl9kZWZhdWx0Lm9jdEVuY29kZUZsb2F0KHRvRW5jb2RlMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGhhc0JpdGFuZ2VudCkgewogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoYml0YW5nZW50cywgaW5kZXgsIHRvRW5jb2RlMSk7CiAgICAgICAgICAgICAgY29tcHJlc3NlZEF0dHJpYnV0ZXNbbm9ybWFsSW5kZXgrK10gPSBBdHRyaWJ1dGVDb21wcmVzc2lvbl9kZWZhdWx0Lm9jdEVuY29kZUZsb2F0KHRvRW5jb2RlMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZ2VvbWV0cnkuYXR0cmlidXRlcy5jb21wcmVzc2VkQXR0cmlidXRlcyA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogbnVtQ29tcHJlc3NlZENvbXBvbmVudHMsCiAgICAgICAgICB2YWx1ZXM6IGNvbXByZXNzZWRBdHRyaWJ1dGVzCiAgICAgICAgfSk7CiAgICAgICAgaWYgKGhhc05vcm1hbCkgewogICAgICAgICAgZGVsZXRlIGdlb21ldHJ5LmF0dHJpYnV0ZXMubm9ybWFsOwogICAgICAgIH0KICAgICAgICBpZiAoaGFzU3QpIHsKICAgICAgICAgIGRlbGV0ZSBnZW9tZXRyeS5hdHRyaWJ1dGVzLnN0OwogICAgICAgIH0KICAgICAgICBpZiAoaGFzQml0YW5nZW50KSB7CiAgICAgICAgICBkZWxldGUgZ2VvbWV0cnkuYXR0cmlidXRlcy5iaXRhbmdlbnQ7CiAgICAgICAgfQogICAgICAgIGlmIChoYXNUYW5nZW50KSB7CiAgICAgICAgICBkZWxldGUgZ2VvbWV0cnkuYXR0cmlidXRlcy50YW5nZW50OwogICAgICAgIH0KICAgICAgICByZXR1cm4gZ2VvbWV0cnk7CiAgICAgIH07CiAgICAgIGMzID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICB1MSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgdTIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHExID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBxMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc3BsaXRUcmlhbmdsZVJlc3VsdCA9IHsKICAgICAgICBwb3NpdGlvbnM6IG5ldyBBcnJheSg3KSwKICAgICAgICBpbmRpY2VzOiBuZXcgQXJyYXkoMyAqIDMpCiAgICAgIH07CiAgICAgIGludGVycG9sYXRlQW5kUGFja0NhcnRlc2lhbjQgPSBnZW5lcmF0ZUJhcnljZW50cmljSW50ZXJwb2xhdGVGdW5jdGlvbigKICAgICAgICBDYXJ0ZXNpYW40X2RlZmF1bHQsCiAgICAgICAgNAogICAgICApOwogICAgICBpbnRlcnBvbGF0ZUFuZFBhY2tDYXJ0ZXNpYW4zID0gZ2VuZXJhdGVCYXJ5Y2VudHJpY0ludGVycG9sYXRlRnVuY3Rpb24oCiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LAogICAgICAgIDMKICAgICAgKTsKICAgICAgaW50ZXJwb2xhdGVBbmRQYWNrQ2FydGVzaWFuMiA9IGdlbmVyYXRlQmFyeWNlbnRyaWNJbnRlcnBvbGF0ZUZ1bmN0aW9uKAogICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdCwKICAgICAgICAyCiAgICAgICk7CiAgICAgIGludGVycG9sYXRlQW5kUGFja0Jvb2xlYW4gPSBmdW5jdGlvbihpMCwgaTEsIGkyLCBjb29yZHMsIHNvdXJjZVZhbHVlcywgY3VycmVudFZhbHVlcywgaW5zZXJ0ZWRJbmRleCkgewogICAgICAgIGNvbnN0IHYxMiA9IHNvdXJjZVZhbHVlc1tpMF0gKiBjb29yZHMueDsKICAgICAgICBjb25zdCB2MjIgPSBzb3VyY2VWYWx1ZXNbaTFdICogY29vcmRzLnk7CiAgICAgICAgY29uc3QgdjMgPSBzb3VyY2VWYWx1ZXNbaTJdICogY29vcmRzLno7CiAgICAgICAgY3VycmVudFZhbHVlc1tpbnNlcnRlZEluZGV4XSA9IHYxMiArIHYyMiArIHYzID4gTWF0aF9kZWZhdWx0LkVQU0lMT042ID8gMSA6IDA7CiAgICAgIH07CiAgICAgIHAwU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgcDFTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBwMlNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGJhcnljZW50cmljU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgTkFNRURfQVRUUklCVVRFUyA9IHsKICAgICAgICBwb3NpdGlvbjogdHJ1ZSwKICAgICAgICBub3JtYWw6IHRydWUsCiAgICAgICAgYml0YW5nZW50OiB0cnVlLAogICAgICAgIHRhbmdlbnQ6IHRydWUsCiAgICAgICAgc3Q6IHRydWUsCiAgICAgICAgZXh0cnVkZURpcmVjdGlvbjogdHJ1ZSwKICAgICAgICBhcHBseU9mZnNldDogdHJ1ZQogICAgICB9OwogICAgICB4elBsYW5lID0gUGxhbmVfZGVmYXVsdC5mcm9tUG9pbnROb3JtYWwoQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sIENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1kpOwogICAgICBvZmZzZXRTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBvZmZzZXRQb2ludFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjJTY3JhdGNoMCA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKTsKICAgICAgY2FydGVzaWFuMlNjcmF0Y2gxID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBjYXJ0ZXNpYW4zU2NyYXRjaDAgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjNTY3JhdGNoMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgY2FydGVzaWFuM1NjcmF0Y2gzID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBjYXJ0ZXNpYW4zU2NyYXRjaDQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjNTY3JhdGNoNSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgY2FydGVzaWFuM1NjcmF0Y2g2ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBjYXJ0ZXNpYW40U2NyYXRjaDAgPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KCk7CiAgICAgIG9mZnNldFNjYWxhciA9IDUgKiBNYXRoX2RlZmF1bHQuRVBTSUxPTjk7CiAgICAgIGNvcGxhbmFyT2Zmc2V0ID0gTWF0aF9kZWZhdWx0LkVQU0lMT042OwogICAgICBHZW9tZXRyeVBpcGVsaW5lLnNwbGl0TG9uZ2l0dWRlID0gZnVuY3Rpb24oaW5zdGFuY2UpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpbnN0YW5jZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJpbnN0YW5jZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZ2VvbWV0cnkgPSBpbnN0YW5jZS5nZW9tZXRyeTsKICAgICAgICBjb25zdCBib3VuZGluZ1NwaGVyZSA9IGdlb21ldHJ5LmJvdW5kaW5nU3BoZXJlOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoYm91bmRpbmdTcGhlcmUpKSB7CiAgICAgICAgICBjb25zdCBtaW5YID0gYm91bmRpbmdTcGhlcmUuY2VudGVyLnggLSBib3VuZGluZ1NwaGVyZS5yYWRpdXM7CiAgICAgICAgICBpZiAobWluWCA+IDAgfHwgQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5pbnRlcnNlY3RQbGFuZShib3VuZGluZ1NwaGVyZSwgUGxhbmVfZGVmYXVsdC5PUklHSU5fWlhfUExBTkUpICE9PSBJbnRlcnNlY3RfZGVmYXVsdC5JTlRFUlNFQ1RJTkcpIHsKICAgICAgICAgICAgcmV0dXJuIGluc3RhbmNlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoZ2VvbWV0cnkuZ2VvbWV0cnlUeXBlICE9PSBHZW9tZXRyeVR5cGVfZGVmYXVsdC5OT05FKSB7CiAgICAgICAgICBzd2l0Y2ggKGdlb21ldHJ5Lmdlb21ldHJ5VHlwZSkgewogICAgICAgICAgICBjYXNlIEdlb21ldHJ5VHlwZV9kZWZhdWx0LlBPTFlMSU5FUzoKICAgICAgICAgICAgICBzcGxpdExvbmdpdHVkZVBvbHlsaW5lKGluc3RhbmNlKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBHZW9tZXRyeVR5cGVfZGVmYXVsdC5UUklBTkdMRVM6CiAgICAgICAgICAgICAgc3BsaXRMb25naXR1ZGVUcmlhbmdsZXMoaW5zdGFuY2UpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIEdlb21ldHJ5VHlwZV9kZWZhdWx0LkxJTkVTOgogICAgICAgICAgICAgIHNwbGl0TG9uZ2l0dWRlTGluZXMoaW5zdGFuY2UpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpbmRleFByaW1pdGl2ZShnZW9tZXRyeSk7CiAgICAgICAgICBpZiAoZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSA9PT0gUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUykgewogICAgICAgICAgICBzcGxpdExvbmdpdHVkZVRyaWFuZ2xlcyhpbnN0YW5jZSk7CiAgICAgICAgICB9IGVsc2UgaWYgKGdlb21ldHJ5LnByaW1pdGl2ZVR5cGUgPT09IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5MSU5FUykgewogICAgICAgICAgICBzcGxpdExvbmdpdHVkZUxpbmVzKGluc3RhbmNlKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGluc3RhbmNlOwogICAgICB9OwogICAgICBHZW9tZXRyeVBpcGVsaW5lX2RlZmF1bHQgPSBHZW9tZXRyeVBpcGVsaW5lOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvT2Zmc2V0R2VvbWV0cnlJbnN0YW5jZUF0dHJpYnV0ZS5qcwogIGZ1bmN0aW9uIE9mZnNldEdlb21ldHJ5SW5zdGFuY2VBdHRyaWJ1dGUoeCwgeSwgeikgewogICAgeCA9IHggPz8gMDsKICAgIHkgPSB5ID8/IDA7CiAgICB6ID0geiA/PyAwOwogICAgdGhpcy52YWx1ZSA9IG5ldyBGbG9hdDMyQXJyYXkoW3gsIHksIHpdKTsKICB9CiAgdmFyIE9mZnNldEdlb21ldHJ5SW5zdGFuY2VBdHRyaWJ1dGVfZGVmYXVsdDsKICB2YXIgaW5pdF9PZmZzZXRHZW9tZXRyeUluc3RhbmNlQXR0cmlidXRlID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9PZmZzZXRHZW9tZXRyeUluc3RhbmNlQXR0cmlidXRlLmpzIigpIHsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X0NvbXBvbmVudERhdGF0eXBlKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhPZmZzZXRHZW9tZXRyeUluc3RhbmNlQXR0cmlidXRlLnByb3RvdHlwZSwgewogICAgICAgIC8qKgogICAgICAgICAqIFRoZSBkYXRhdHlwZSBvZiBlYWNoIGNvbXBvbmVudCBpbiB0aGUgYXR0cmlidXRlLCBlLmcuLCBpbmRpdmlkdWFsIGVsZW1lbnRzIGluCiAgICAgICAgICoge0BsaW5rIE9mZnNldEdlb21ldHJ5SW5zdGFuY2VBdHRyaWJ1dGUjdmFsdWV9LgogICAgICAgICAqCiAgICAgICAgICogQG1lbWJlcm9mIE9mZnNldEdlb21ldHJ5SW5zdGFuY2VBdHRyaWJ1dGUucHJvdG90eXBlCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7Q29tcG9uZW50RGF0YXR5cGV9CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICoKICAgICAgICAgKiBAZGVmYXVsdCB7QGxpbmsgQ29tcG9uZW50RGF0YXR5cGUuRkxPQVR9CiAgICAgICAgICovCiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FUOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIG51bWJlciBvZiBjb21wb25lbnRzIGluIHRoZSBhdHRyaWJ1dGVzLCBpLmUuLCB7QGxpbmsgT2Zmc2V0R2VvbWV0cnlJbnN0YW5jZUF0dHJpYnV0ZSN2YWx1ZX0uCiAgICAgICAgICoKICAgICAgICAgKiBAbWVtYmVyb2YgT2Zmc2V0R2VvbWV0cnlJbnN0YW5jZUF0dHJpYnV0ZS5wcm90b3R5cGUKICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICoKICAgICAgICAgKiBAZGVmYXVsdCAzCiAgICAgICAgICovCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIDM7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBXaGVuIDxjb2RlPnRydWU8L2NvZGU+IGFuZCA8Y29kZT5jb21wb25lbnREYXRhdHlwZTwvY29kZT4gaXMgYW4gaW50ZWdlciBmb3JtYXQsCiAgICAgICAgICogaW5kaWNhdGUgdGhhdCB0aGUgY29tcG9uZW50cyBzaG91bGQgYmUgbWFwcGVkIHRvIHRoZSByYW5nZSBbMCwgMV0gKHVuc2lnbmVkKQogICAgICAgICAqIG9yIFstMSwgMV0gKHNpZ25lZCkgd2hlbiB0aGV5IGFyZSBhY2Nlc3NlZCBhcyBmbG9hdGluZy1wb2ludCBmb3IgcmVuZGVyaW5nLgogICAgICAgICAqCiAgICAgICAgICogQG1lbWJlcm9mIE9mZnNldEdlb21ldHJ5SW5zdGFuY2VBdHRyaWJ1dGUucHJvdG90eXBlCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7Ym9vbGVhbn0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKgogICAgICAgICAqIEBkZWZhdWx0IGZhbHNlCiAgICAgICAgICovCiAgICAgICAgbm9ybWFsaXplOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgT2Zmc2V0R2VvbWV0cnlJbnN0YW5jZUF0dHJpYnV0ZS5mcm9tQ2FydGVzaWFuMyA9IGZ1bmN0aW9uKG9mZnNldCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgib2Zmc2V0Iiwgb2Zmc2V0KTsKICAgICAgICByZXR1cm4gbmV3IE9mZnNldEdlb21ldHJ5SW5zdGFuY2VBdHRyaWJ1dGUob2Zmc2V0LngsIG9mZnNldC55LCBvZmZzZXQueik7CiAgICAgIH07CiAgICAgIE9mZnNldEdlb21ldHJ5SW5zdGFuY2VBdHRyaWJ1dGUudG9WYWx1ZSA9IGZ1bmN0aW9uKG9mZnNldCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJvZmZzZXQiLCBvZmZzZXQpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBGbG9hdDMyQXJyYXkoW29mZnNldC54LCBvZmZzZXQueSwgb2Zmc2V0LnpdKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gb2Zmc2V0Lng7CiAgICAgICAgcmVzdWx0WzFdID0gb2Zmc2V0Lnk7CiAgICAgICAgcmVzdWx0WzJdID0gb2Zmc2V0Lno7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgT2Zmc2V0R2VvbWV0cnlJbnN0YW5jZUF0dHJpYnV0ZV9kZWZhdWx0ID0gT2Zmc2V0R2VvbWV0cnlJbnN0YW5jZUF0dHJpYnV0ZTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1dlYk1lcmNhdG9yUHJvamVjdGlvbi5qcwogIGZ1bmN0aW9uIFdlYk1lcmNhdG9yUHJvamVjdGlvbihlbGxpcHNvaWQpIHsKICAgIHRoaXMuX2VsbGlwc29pZCA9IGVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5XR1M4NDsKICAgIHRoaXMuX3NlbWltYWpvckF4aXMgPSB0aGlzLl9lbGxpcHNvaWQubWF4aW11bVJhZGl1czsKICAgIHRoaXMuX29uZU92ZXJTZW1pbWFqb3JBeGlzID0gMSAvIHRoaXMuX3NlbWltYWpvckF4aXM7CiAgfQogIHZhciBXZWJNZXJjYXRvclByb2plY3Rpb25fZGVmYXVsdDsKICB2YXIgaW5pdF9XZWJNZXJjYXRvclByb2plY3Rpb24gPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1dlYk1lcmNhdG9yUHJvamVjdGlvbi5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoV2ViTWVyY2F0b3JQcm9qZWN0aW9uLnByb3RvdHlwZSwgewogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIHtAbGluayBFbGxpcHNvaWR9LgogICAgICAgICAqCiAgICAgICAgICogQG1lbWJlcm9mIFdlYk1lcmNhdG9yUHJvamVjdGlvbi5wcm90b3R5cGUKICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtFbGxpcHNvaWR9CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgZWxsaXBzb2lkOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fZWxsaXBzb2lkOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIFdlYk1lcmNhdG9yUHJvamVjdGlvbi5tZXJjYXRvckFuZ2xlVG9HZW9kZXRpY0xhdGl0dWRlID0gZnVuY3Rpb24obWVyY2F0b3JBbmdsZSkgewogICAgICAgIHJldHVybiBNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08gLSAyICogTWF0aC5hdGFuKE1hdGguZXhwKC1tZXJjYXRvckFuZ2xlKSk7CiAgICAgIH07CiAgICAgIFdlYk1lcmNhdG9yUHJvamVjdGlvbi5nZW9kZXRpY0xhdGl0dWRlVG9NZXJjYXRvckFuZ2xlID0gZnVuY3Rpb24obGF0aXR1ZGUpIHsKICAgICAgICBpZiAobGF0aXR1ZGUgPiBXZWJNZXJjYXRvclByb2plY3Rpb24uTWF4aW11bUxhdGl0dWRlKSB7CiAgICAgICAgICBsYXRpdHVkZSA9IFdlYk1lcmNhdG9yUHJvamVjdGlvbi5NYXhpbXVtTGF0aXR1ZGU7CiAgICAgICAgfSBlbHNlIGlmIChsYXRpdHVkZSA8IC1XZWJNZXJjYXRvclByb2plY3Rpb24uTWF4aW11bUxhdGl0dWRlKSB7CiAgICAgICAgICBsYXRpdHVkZSA9IC1XZWJNZXJjYXRvclByb2plY3Rpb24uTWF4aW11bUxhdGl0dWRlOwogICAgICAgIH0KICAgICAgICBjb25zdCBzaW5MYXRpdHVkZSA9IE1hdGguc2luKGxhdGl0dWRlKTsKICAgICAgICByZXR1cm4gMC41ICogTWF0aC5sb2coKDEgKyBzaW5MYXRpdHVkZSkgLyAoMSAtIHNpbkxhdGl0dWRlKSk7CiAgICAgIH07CiAgICAgIFdlYk1lcmNhdG9yUHJvamVjdGlvbi5NYXhpbXVtTGF0aXR1ZGUgPSBXZWJNZXJjYXRvclByb2plY3Rpb24ubWVyY2F0b3JBbmdsZVRvR2VvZGV0aWNMYXRpdHVkZShNYXRoLlBJKTsKICAgICAgV2ViTWVyY2F0b3JQcm9qZWN0aW9uLnByb3RvdHlwZS5wcm9qZWN0ID0gZnVuY3Rpb24oY2FydG9ncmFwaGljMiwgcmVzdWx0KSB7CiAgICAgICAgY29uc3Qgc2VtaW1ham9yQXhpcyA9IHRoaXMuX3NlbWltYWpvckF4aXM7CiAgICAgICAgY29uc3QgeCA9IGNhcnRvZ3JhcGhpYzIubG9uZ2l0dWRlICogc2VtaW1ham9yQXhpczsKICAgICAgICBjb25zdCB5ID0gV2ViTWVyY2F0b3JQcm9qZWN0aW9uLmdlb2RldGljTGF0aXR1ZGVUb01lcmNhdG9yQW5nbGUoCiAgICAgICAgICBjYXJ0b2dyYXBoaWMyLmxhdGl0dWRlCiAgICAgICAgKSAqIHNlbWltYWpvckF4aXM7CiAgICAgICAgY29uc3QgeiA9IGNhcnRvZ3JhcGhpYzIuaGVpZ2h0OwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KHgsIHksIHopOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IHg7CiAgICAgICAgcmVzdWx0LnkgPSB5OwogICAgICAgIHJlc3VsdC56ID0gejsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBXZWJNZXJjYXRvclByb2plY3Rpb24ucHJvdG90eXBlLnVucHJvamVjdCA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChjYXJ0ZXNpYW4xMSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJjYXJ0ZXNpYW4gaXMgcmVxdWlyZWQiKTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgb25lT3ZlckVhcnRoU2VtaW1ham9yQXhpcyA9IHRoaXMuX29uZU92ZXJTZW1pbWFqb3JBeGlzOwogICAgICAgIGNvbnN0IGxvbmdpdHVkZSA9IGNhcnRlc2lhbjExLnggKiBvbmVPdmVyRWFydGhTZW1pbWFqb3JBeGlzOwogICAgICAgIGNvbnN0IGxhdGl0dWRlID0gV2ViTWVyY2F0b3JQcm9qZWN0aW9uLm1lcmNhdG9yQW5nbGVUb0dlb2RldGljTGF0aXR1ZGUoCiAgICAgICAgICBjYXJ0ZXNpYW4xMS55ICogb25lT3ZlckVhcnRoU2VtaW1ham9yQXhpcwogICAgICAgICk7CiAgICAgICAgY29uc3QgaGVpZ2h0ID0gY2FydGVzaWFuMTEuejsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KGxvbmdpdHVkZSwgbGF0aXR1ZGUsIGhlaWdodCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5sb25naXR1ZGUgPSBsb25naXR1ZGU7CiAgICAgICAgcmVzdWx0LmxhdGl0dWRlID0gbGF0aXR1ZGU7CiAgICAgICAgcmVzdWx0LmhlaWdodCA9IGhlaWdodDsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBXZWJNZXJjYXRvclByb2plY3Rpb25fZGVmYXVsdCA9IFdlYk1lcmNhdG9yUHJvamVjdGlvbjsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9TY2VuZS9QcmltaXRpdmVQaXBlbGluZS5qcwogIGZ1bmN0aW9uIHRyYW5zZm9ybVRvV29ybGRDb29yZGluYXRlcyhpbnN0YW5jZXMsIHByaW1pdGl2ZU1vZGVsTWF0cml4LCBzY2VuZTNET25seSkgewogICAgbGV0IHRvV29ybGQgPSAhc2NlbmUzRE9ubHk7CiAgICBjb25zdCBsZW5ndGggPSBpbnN0YW5jZXMubGVuZ3RoOwogICAgbGV0IGk7CiAgICBpZiAoIXRvV29ybGQgJiYgbGVuZ3RoID4gMSkgewogICAgICBjb25zdCBtb2RlbE1hdHJpeCA9IGluc3RhbmNlc1swXS5tb2RlbE1hdHJpeDsKICAgICAgZm9yIChpID0gMTsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgaWYgKCFNYXRyaXg0X2RlZmF1bHQuZXF1YWxzKG1vZGVsTWF0cml4LCBpbnN0YW5jZXNbaV0ubW9kZWxNYXRyaXgpKSB7CiAgICAgICAgICB0b1dvcmxkID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKHRvV29ybGQpIHsKICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChpbnN0YW5jZXNbaV0uZ2VvbWV0cnkpKSB7CiAgICAgICAgICBHZW9tZXRyeVBpcGVsaW5lX2RlZmF1bHQudHJhbnNmb3JtVG9Xb3JsZENvb3JkaW5hdGVzKGluc3RhbmNlc1tpXSk7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlUcmFuc2Zvcm1hdGlvbigKICAgICAgICBwcmltaXRpdmVNb2RlbE1hdHJpeCwKICAgICAgICBpbnN0YW5jZXNbMF0ubW9kZWxNYXRyaXgsCiAgICAgICAgcHJpbWl0aXZlTW9kZWxNYXRyaXgKICAgICAgKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gYWRkR2VvbWV0cnlCYXRjaElkKGdlb21ldHJ5LCBiYXRjaElkKSB7CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gZ2VvbWV0cnkuYXR0cmlidXRlczsKICAgIGNvbnN0IHBvc2l0aW9uQXR0ciA9IGF0dHJpYnV0ZXMucG9zaXRpb247CiAgICBjb25zdCBudW1iZXJPZkNvbXBvbmVudHMgPSBwb3NpdGlvbkF0dHIudmFsdWVzLmxlbmd0aCAvIHBvc2l0aW9uQXR0ci5jb21wb25lbnRzUGVyQXR0cmlidXRlOwogICAgYXR0cmlidXRlcy5iYXRjaElkID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMSwKICAgICAgdmFsdWVzOiBuZXcgRmxvYXQzMkFycmF5KG51bWJlck9mQ29tcG9uZW50cykKICAgIH0pOwogICAgY29uc3QgdmFsdWVzID0gYXR0cmlidXRlcy5iYXRjaElkLnZhbHVlczsKICAgIGZvciAobGV0IGogPSAwOyBqIDwgbnVtYmVyT2ZDb21wb25lbnRzOyArK2opIHsKICAgICAgdmFsdWVzW2pdID0gYmF0Y2hJZDsKICAgIH0KICB9CiAgZnVuY3Rpb24gYWRkQmF0Y2hJZHMoaW5zdGFuY2VzKSB7CiAgICBjb25zdCBsZW5ndGggPSBpbnN0YW5jZXMubGVuZ3RoOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBjb25zdCBpbnN0YW5jZSA9IGluc3RhbmNlc1tpXTsKICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChpbnN0YW5jZS5nZW9tZXRyeSkpIHsKICAgICAgICBhZGRHZW9tZXRyeUJhdGNoSWQoaW5zdGFuY2UuZ2VvbWV0cnksIGkpOwogICAgICB9IGVsc2UgaWYgKGRlZmluZWRfZGVmYXVsdChpbnN0YW5jZS53ZXN0SGVtaXNwaGVyZUdlb21ldHJ5KSAmJiBkZWZpbmVkX2RlZmF1bHQoaW5zdGFuY2UuZWFzdEhlbWlzcGhlcmVHZW9tZXRyeSkpIHsKICAgICAgICBhZGRHZW9tZXRyeUJhdGNoSWQoaW5zdGFuY2Uud2VzdEhlbWlzcGhlcmVHZW9tZXRyeSwgaSk7CiAgICAgICAgYWRkR2VvbWV0cnlCYXRjaElkKGluc3RhbmNlLmVhc3RIZW1pc3BoZXJlR2VvbWV0cnksIGkpOwogICAgICB9CiAgICB9CiAgfQogIGZ1bmN0aW9uIGdlb21ldHJ5UGlwZWxpbmUocGFyYW1ldGVycykgewogICAgY29uc3QgaW5zdGFuY2VzID0gcGFyYW1ldGVycy5pbnN0YW5jZXM7CiAgICBjb25zdCBwcm9qZWN0aW9uID0gcGFyYW1ldGVycy5wcm9qZWN0aW9uOwogICAgY29uc3QgdWludEluZGV4U3VwcG9ydCA9IHBhcmFtZXRlcnMuZWxlbWVudEluZGV4VWludFN1cHBvcnRlZDsKICAgIGNvbnN0IHNjZW5lM0RPbmx5ID0gcGFyYW1ldGVycy5zY2VuZTNET25seTsKICAgIGNvbnN0IHZlcnRleENhY2hlT3B0aW1pemUgPSBwYXJhbWV0ZXJzLnZlcnRleENhY2hlT3B0aW1pemU7CiAgICBjb25zdCBjb21wcmVzc1ZlcnRpY2VzID0gcGFyYW1ldGVycy5jb21wcmVzc1ZlcnRpY2VzOwogICAgY29uc3QgbW9kZWxNYXRyaXggPSBwYXJhbWV0ZXJzLm1vZGVsTWF0cml4OwogICAgbGV0IGk7CiAgICBsZXQgZ2VvbWV0cnk7CiAgICBsZXQgcHJpbWl0aXZlVHlwZTsKICAgIGxldCBsZW5ndGggPSBpbnN0YW5jZXMubGVuZ3RoOwogICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaW5zdGFuY2VzW2ldLmdlb21ldHJ5KSkgewogICAgICAgIHByaW1pdGl2ZVR5cGUgPSBpbnN0YW5jZXNbaV0uZ2VvbWV0cnkucHJpbWl0aXZlVHlwZTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgZm9yIChpID0gMTsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaW5zdGFuY2VzW2ldLmdlb21ldHJ5KSAmJiBpbnN0YW5jZXNbaV0uZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSAhPT0gcHJpbWl0aXZlVHlwZSkgewogICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgIkFsbCBpbnN0YW5jZSBnZW9tZXRyaWVzIG11c3QgaGF2ZSB0aGUgc2FtZSBwcmltaXRpdmVUeXBlLiIKICAgICAgICApOwogICAgICB9CiAgICB9CiAgICB0cmFuc2Zvcm1Ub1dvcmxkQ29vcmRpbmF0ZXMoaW5zdGFuY2VzLCBtb2RlbE1hdHJpeCwgc2NlbmUzRE9ubHkpOwogICAgaWYgKCFzY2VuZTNET25seSkgewogICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGluc3RhbmNlc1tpXS5nZW9tZXRyeSkpIHsKICAgICAgICAgIEdlb21ldHJ5UGlwZWxpbmVfZGVmYXVsdC5zcGxpdExvbmdpdHVkZShpbnN0YW5jZXNbaV0pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgYWRkQmF0Y2hJZHMoaW5zdGFuY2VzKTsKICAgIGlmICh2ZXJ0ZXhDYWNoZU9wdGltaXplKSB7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgIGNvbnN0IGluc3RhbmNlID0gaW5zdGFuY2VzW2ldOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaW5zdGFuY2UuZ2VvbWV0cnkpKSB7CiAgICAgICAgICBHZW9tZXRyeVBpcGVsaW5lX2RlZmF1bHQucmVvcmRlckZvclBvc3RWZXJ0ZXhDYWNoZShpbnN0YW5jZS5nZW9tZXRyeSk7CiAgICAgICAgICBHZW9tZXRyeVBpcGVsaW5lX2RlZmF1bHQucmVvcmRlckZvclByZVZlcnRleENhY2hlKGluc3RhbmNlLmdlb21ldHJ5KTsKICAgICAgICB9IGVsc2UgaWYgKGRlZmluZWRfZGVmYXVsdChpbnN0YW5jZS53ZXN0SGVtaXNwaGVyZUdlb21ldHJ5KSAmJiBkZWZpbmVkX2RlZmF1bHQoaW5zdGFuY2UuZWFzdEhlbWlzcGhlcmVHZW9tZXRyeSkpIHsKICAgICAgICAgIEdlb21ldHJ5UGlwZWxpbmVfZGVmYXVsdC5yZW9yZGVyRm9yUG9zdFZlcnRleENhY2hlKAogICAgICAgICAgICBpbnN0YW5jZS53ZXN0SGVtaXNwaGVyZUdlb21ldHJ5CiAgICAgICAgICApOwogICAgICAgICAgR2VvbWV0cnlQaXBlbGluZV9kZWZhdWx0LnJlb3JkZXJGb3JQcmVWZXJ0ZXhDYWNoZSgKICAgICAgICAgICAgaW5zdGFuY2Uud2VzdEhlbWlzcGhlcmVHZW9tZXRyeQogICAgICAgICAgKTsKICAgICAgICAgIEdlb21ldHJ5UGlwZWxpbmVfZGVmYXVsdC5yZW9yZGVyRm9yUG9zdFZlcnRleENhY2hlKAogICAgICAgICAgICBpbnN0YW5jZS5lYXN0SGVtaXNwaGVyZUdlb21ldHJ5CiAgICAgICAgICApOwogICAgICAgICAgR2VvbWV0cnlQaXBlbGluZV9kZWZhdWx0LnJlb3JkZXJGb3JQcmVWZXJ0ZXhDYWNoZSgKICAgICAgICAgICAgaW5zdGFuY2UuZWFzdEhlbWlzcGhlcmVHZW9tZXRyeQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGxldCBnZW9tZXRyaWVzID0gR2VvbWV0cnlQaXBlbGluZV9kZWZhdWx0LmNvbWJpbmVJbnN0YW5jZXMoaW5zdGFuY2VzKTsKICAgIGxlbmd0aCA9IGdlb21ldHJpZXMubGVuZ3RoOwogICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgIGdlb21ldHJ5ID0gZ2VvbWV0cmllc1tpXTsKICAgICAgY29uc3QgYXR0cmlidXRlcyA9IGdlb21ldHJ5LmF0dHJpYnV0ZXM7CiAgICAgIGlmICghc2NlbmUzRE9ubHkpIHsKICAgICAgICBmb3IgKGNvbnN0IG5hbWUgaW4gYXR0cmlidXRlcykgewogICAgICAgICAgaWYgKGF0dHJpYnV0ZXMuaGFzT3duUHJvcGVydHkobmFtZSkgJiYgYXR0cmlidXRlc1tuYW1lXS5jb21wb25lbnREYXRhdHlwZSA9PT0gQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUpIHsKICAgICAgICAgICAgY29uc3QgbmFtZTNEID0gYCR7bmFtZX0zRGA7CiAgICAgICAgICAgIGNvbnN0IG5hbWUyRCA9IGAke25hbWV9MkRgOwogICAgICAgICAgICBHZW9tZXRyeVBpcGVsaW5lX2RlZmF1bHQucHJvamVjdFRvMkQoCiAgICAgICAgICAgICAgZ2VvbWV0cnksCiAgICAgICAgICAgICAgbmFtZSwKICAgICAgICAgICAgICBuYW1lM0QsCiAgICAgICAgICAgICAgbmFtZTJELAogICAgICAgICAgICAgIHByb2plY3Rpb24KICAgICAgICAgICAgKTsKICAgICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChnZW9tZXRyeS5ib3VuZGluZ1NwaGVyZSkgJiYgbmFtZSA9PT0gInBvc2l0aW9uIikgewogICAgICAgICAgICAgIGdlb21ldHJ5LmJvdW5kaW5nU3BoZXJlQ1YgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21WZXJ0aWNlcygKICAgICAgICAgICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24yRC52YWx1ZXMKICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIEdlb21ldHJ5UGlwZWxpbmVfZGVmYXVsdC5lbmNvZGVBdHRyaWJ1dGUoCiAgICAgICAgICAgICAgZ2VvbWV0cnksCiAgICAgICAgICAgICAgbmFtZTNELAogICAgICAgICAgICAgIGAke25hbWUzRH1IaWdoYCwKICAgICAgICAgICAgICBgJHtuYW1lM0R9TG93YAogICAgICAgICAgICApOwogICAgICAgICAgICBHZW9tZXRyeVBpcGVsaW5lX2RlZmF1bHQuZW5jb2RlQXR0cmlidXRlKAogICAgICAgICAgICAgIGdlb21ldHJ5LAogICAgICAgICAgICAgIG5hbWUyRCwKICAgICAgICAgICAgICBgJHtuYW1lMkR9SGlnaGAsCiAgICAgICAgICAgICAgYCR7bmFtZTJEfUxvd2AKICAgICAgICAgICAgKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yIChjb25zdCBuYW1lIGluIGF0dHJpYnV0ZXMpIHsKICAgICAgICAgIGlmIChhdHRyaWJ1dGVzLmhhc093blByb3BlcnR5KG5hbWUpICYmIGF0dHJpYnV0ZXNbbmFtZV0uY29tcG9uZW50RGF0YXR5cGUgPT09IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFKSB7CiAgICAgICAgICAgIEdlb21ldHJ5UGlwZWxpbmVfZGVmYXVsdC5lbmNvZGVBdHRyaWJ1dGUoCiAgICAgICAgICAgICAgZ2VvbWV0cnksCiAgICAgICAgICAgICAgbmFtZSwKICAgICAgICAgICAgICBgJHtuYW1lfTNESGlnaGAsCiAgICAgICAgICAgICAgYCR7bmFtZX0zRExvd2AKICAgICAgICAgICAgKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGNvbXByZXNzVmVydGljZXMpIHsKICAgICAgICBHZW9tZXRyeVBpcGVsaW5lX2RlZmF1bHQuY29tcHJlc3NWZXJ0aWNlcyhnZW9tZXRyeSk7CiAgICAgIH0KICAgIH0KICAgIGlmICghdWludEluZGV4U3VwcG9ydCkgewogICAgICBsZXQgc3BsaXRHZW9tZXRyaWVzID0gW107CiAgICAgIGxlbmd0aCA9IGdlb21ldHJpZXMubGVuZ3RoOwogICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICBnZW9tZXRyeSA9IGdlb21ldHJpZXNbaV07CiAgICAgICAgc3BsaXRHZW9tZXRyaWVzID0gc3BsaXRHZW9tZXRyaWVzLmNvbmNhdCgKICAgICAgICAgIEdlb21ldHJ5UGlwZWxpbmVfZGVmYXVsdC5maXRUb1Vuc2lnbmVkU2hvcnRJbmRpY2VzKGdlb21ldHJ5KQogICAgICAgICk7CiAgICAgIH0KICAgICAgZ2VvbWV0cmllcyA9IHNwbGl0R2VvbWV0cmllczsKICAgIH0KICAgIHJldHVybiBnZW9tZXRyaWVzOwogIH0KICBmdW5jdGlvbiBjcmVhdGVQaWNrT2Zmc2V0cyhpbnN0YW5jZXMsIGdlb21ldHJ5TmFtZSwgZ2VvbWV0cmllcywgcGlja09mZnNldHMpIHsKICAgIGxldCBvZmZzZXQ7CiAgICBsZXQgaW5kZXhDb3VudDsKICAgIGxldCBnZW9tZXRyeUluZGV4OwogICAgY29uc3Qgb2Zmc2V0SW5kZXggPSBwaWNrT2Zmc2V0cy5sZW5ndGggLSAxOwogICAgaWYgKG9mZnNldEluZGV4ID49IDApIHsKICAgICAgY29uc3QgcGlja09mZnNldCA9IHBpY2tPZmZzZXRzW29mZnNldEluZGV4XTsKICAgICAgb2Zmc2V0ID0gcGlja09mZnNldC5vZmZzZXQgKyBwaWNrT2Zmc2V0LmNvdW50OwogICAgICBnZW9tZXRyeUluZGV4ID0gcGlja09mZnNldC5pbmRleDsKICAgICAgaW5kZXhDb3VudCA9IGdlb21ldHJpZXNbZ2VvbWV0cnlJbmRleF0uaW5kaWNlcy5sZW5ndGg7CiAgICB9IGVsc2UgewogICAgICBvZmZzZXQgPSAwOwogICAgICBnZW9tZXRyeUluZGV4ID0gMDsKICAgICAgaW5kZXhDb3VudCA9IGdlb21ldHJpZXNbZ2VvbWV0cnlJbmRleF0uaW5kaWNlcy5sZW5ndGg7CiAgICB9CiAgICBjb25zdCBsZW5ndGggPSBpbnN0YW5jZXMubGVuZ3RoOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBjb25zdCBpbnN0YW5jZSA9IGluc3RhbmNlc1tpXTsKICAgICAgY29uc3QgZ2VvbWV0cnkgPSBpbnN0YW5jZVtnZW9tZXRyeU5hbWVdOwogICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChnZW9tZXRyeSkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBjb3VudCA9IGdlb21ldHJ5LmluZGljZXMubGVuZ3RoOwogICAgICBpZiAob2Zmc2V0ICsgY291bnQgPiBpbmRleENvdW50KSB7CiAgICAgICAgb2Zmc2V0ID0gMDsKICAgICAgICBpbmRleENvdW50ID0gZ2VvbWV0cmllc1srK2dlb21ldHJ5SW5kZXhdLmluZGljZXMubGVuZ3RoOwogICAgICB9CiAgICAgIHBpY2tPZmZzZXRzLnB1c2goewogICAgICAgIGluZGV4OiBnZW9tZXRyeUluZGV4LAogICAgICAgIG9mZnNldCwKICAgICAgICBjb3VudAogICAgICB9KTsKICAgICAgb2Zmc2V0ICs9IGNvdW50OwogICAgfQogIH0KICBmdW5jdGlvbiBjcmVhdGVJbnN0YW5jZVBpY2tPZmZzZXRzKGluc3RhbmNlcywgZ2VvbWV0cmllcykgewogICAgY29uc3QgcGlja09mZnNldHMgPSBbXTsKICAgIGNyZWF0ZVBpY2tPZmZzZXRzKGluc3RhbmNlcywgImdlb21ldHJ5IiwgZ2VvbWV0cmllcywgcGlja09mZnNldHMpOwogICAgY3JlYXRlUGlja09mZnNldHMoCiAgICAgIGluc3RhbmNlcywKICAgICAgIndlc3RIZW1pc3BoZXJlR2VvbWV0cnkiLAogICAgICBnZW9tZXRyaWVzLAogICAgICBwaWNrT2Zmc2V0cwogICAgKTsKICAgIGNyZWF0ZVBpY2tPZmZzZXRzKAogICAgICBpbnN0YW5jZXMsCiAgICAgICJlYXN0SGVtaXNwaGVyZUdlb21ldHJ5IiwKICAgICAgZ2VvbWV0cmllcywKICAgICAgcGlja09mZnNldHMKICAgICk7CiAgICByZXR1cm4gcGlja09mZnNldHM7CiAgfQogIGZ1bmN0aW9uIHRyYW5zZmVyR2VvbWV0cnkoZ2VvbWV0cnksIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBnZW9tZXRyeS5hdHRyaWJ1dGVzOwogICAgZm9yIChjb25zdCBuYW1lIGluIGF0dHJpYnV0ZXMpIHsKICAgICAgaWYgKGF0dHJpYnV0ZXMuaGFzT3duUHJvcGVydHkobmFtZSkpIHsKICAgICAgICBjb25zdCBhdHRyaWJ1dGUgPSBhdHRyaWJ1dGVzW25hbWVdOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlKSAmJiBkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlLnZhbHVlcykpIHsKICAgICAgICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaChhdHRyaWJ1dGUudmFsdWVzLmJ1ZmZlcik7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5LmluZGljZXMpKSB7CiAgICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaChnZW9tZXRyeS5pbmRpY2VzLmJ1ZmZlcik7CiAgICB9CiAgfQogIGZ1bmN0aW9uIHRyYW5zZmVyR2VvbWV0cmllcyhnZW9tZXRyaWVzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICBjb25zdCBsZW5ndGggPSBnZW9tZXRyaWVzLmxlbmd0aDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgdHJhbnNmZXJHZW9tZXRyeShnZW9tZXRyaWVzW2ldLCB0cmFuc2ZlcmFibGVPYmplY3RzKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gY291bnRDcmVhdGVHZW9tZXRyeVJlc3VsdHMoaXRlbXMpIHsKICAgIGxldCBjb3VudCA9IDE7CiAgICBjb25zdCBsZW5ndGggPSBpdGVtcy5sZW5ndGg7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIGNvbnN0IGdlb21ldHJ5ID0gaXRlbXNbaV07CiAgICAgICsrY291bnQ7CiAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5KSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBnZW9tZXRyeS5hdHRyaWJ1dGVzOwogICAgICBjb3VudCArPSA3ICsgMiAqIEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQucGFja2VkTGVuZ3RoICsgKGRlZmluZWRfZGVmYXVsdChnZW9tZXRyeS5pbmRpY2VzKSA/IGdlb21ldHJ5LmluZGljZXMubGVuZ3RoIDogMCk7CiAgICAgIGZvciAoY29uc3QgcHJvcGVydHkgaW4gYXR0cmlidXRlcykgewogICAgICAgIGlmIChhdHRyaWJ1dGVzLmhhc093blByb3BlcnR5KHByb3BlcnR5KSAmJiBkZWZpbmVkX2RlZmF1bHQoYXR0cmlidXRlc1twcm9wZXJ0eV0pKSB7CiAgICAgICAgICBjb25zdCBhdHRyaWJ1dGUgPSBhdHRyaWJ1dGVzW3Byb3BlcnR5XTsKICAgICAgICAgIGNvdW50ICs9IDUgKyBhdHRyaWJ1dGUudmFsdWVzLmxlbmd0aDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBjb3VudDsKICB9CiAgZnVuY3Rpb24gcGFja0luc3RhbmNlc0ZvckNvbWJpbmUoaW5zdGFuY2VzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICBjb25zdCBsZW5ndGggPSBpbnN0YW5jZXMubGVuZ3RoOwogICAgY29uc3QgcGFja2VkRGF0YSA9IG5ldyBGbG9hdDY0QXJyYXkoMSArIGxlbmd0aCAqIDE5KTsKICAgIGxldCBjb3VudCA9IDA7CiAgICBwYWNrZWREYXRhW2NvdW50KytdID0gbGVuZ3RoOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBjb25zdCBpbnN0YW5jZSA9IGluc3RhbmNlc1tpXTsKICAgICAgTWF0cml4NF9kZWZhdWx0LnBhY2soaW5zdGFuY2UubW9kZWxNYXRyaXgsIHBhY2tlZERhdGEsIGNvdW50KTsKICAgICAgY291bnQgKz0gTWF0cml4NF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChpbnN0YW5jZS5hdHRyaWJ1dGVzKSAmJiBkZWZpbmVkX2RlZmF1bHQoaW5zdGFuY2UuYXR0cmlidXRlcy5vZmZzZXQpKSB7CiAgICAgICAgY29uc3QgdmFsdWVzID0gaW5zdGFuY2UuYXR0cmlidXRlcy5vZmZzZXQudmFsdWU7CiAgICAgICAgcGFja2VkRGF0YVtjb3VudF0gPSB2YWx1ZXNbMF07CiAgICAgICAgcGFja2VkRGF0YVtjb3VudCArIDFdID0gdmFsdWVzWzFdOwogICAgICAgIHBhY2tlZERhdGFbY291bnQgKyAyXSA9IHZhbHVlc1syXTsKICAgICAgfQogICAgICBjb3VudCArPSAzOwogICAgfQogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKHBhY2tlZERhdGEuYnVmZmVyKTsKICAgIHJldHVybiBwYWNrZWREYXRhOwogIH0KICBmdW5jdGlvbiB1bnBhY2tJbnN0YW5jZXNGb3JDb21iaW5lKGRhdGEpIHsKICAgIGNvbnN0IHBhY2tlZEluc3RhbmNlcyA9IGRhdGE7CiAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXkocGFja2VkSW5zdGFuY2VzWzBdKTsKICAgIGxldCBjb3VudCA9IDA7CiAgICBsZXQgaSA9IDE7CiAgICB3aGlsZSAoaSA8IHBhY2tlZEluc3RhbmNlcy5sZW5ndGgpIHsKICAgICAgY29uc3QgbW9kZWxNYXRyaXggPSBNYXRyaXg0X2RlZmF1bHQudW5wYWNrKHBhY2tlZEluc3RhbmNlcywgaSk7CiAgICAgIGxldCBhdHRyaWJ1dGVzOwogICAgICBpICs9IE1hdHJpeDRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocGFja2VkSW5zdGFuY2VzW2ldKSkgewogICAgICAgIGF0dHJpYnV0ZXMgPSB7CiAgICAgICAgICBvZmZzZXQ6IG5ldyBPZmZzZXRHZW9tZXRyeUluc3RhbmNlQXR0cmlidXRlX2RlZmF1bHQoCiAgICAgICAgICAgIHBhY2tlZEluc3RhbmNlc1tpXSwKICAgICAgICAgICAgcGFja2VkSW5zdGFuY2VzW2kgKyAxXSwKICAgICAgICAgICAgcGFja2VkSW5zdGFuY2VzW2kgKyAyXQogICAgICAgICAgKQogICAgICAgIH07CiAgICAgIH0KICAgICAgaSArPSAzOwogICAgICByZXN1bHRbY291bnQrK10gPSB7CiAgICAgICAgbW9kZWxNYXRyaXgsCiAgICAgICAgYXR0cmlidXRlcwogICAgICB9OwogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgZnVuY3Rpb24gcGFja0JvdW5kaW5nU3BoZXJlcyhib3VuZGluZ1NwaGVyZXMpIHsKICAgIGNvbnN0IGxlbmd0aCA9IGJvdW5kaW5nU3BoZXJlcy5sZW5ndGg7CiAgICBjb25zdCBidWZmZXJMZW5ndGggPSAxICsgKEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQucGFja2VkTGVuZ3RoICsgMSkgKiBsZW5ndGg7CiAgICBjb25zdCBidWZmZXIgPSBuZXcgRmxvYXQzMkFycmF5KGJ1ZmZlckxlbmd0aCk7CiAgICBsZXQgYnVmZmVySW5kZXggPSAwOwogICAgYnVmZmVyW2J1ZmZlckluZGV4KytdID0gbGVuZ3RoOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBjb25zdCBicyA9IGJvdW5kaW5nU3BoZXJlc1tpXTsKICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYnMpKSB7CiAgICAgICAgYnVmZmVyW2J1ZmZlckluZGV4KytdID0gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICBidWZmZXJbYnVmZmVySW5kZXgrK10gPSAxOwogICAgICAgIEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQucGFjayhib3VuZGluZ1NwaGVyZXNbaV0sIGJ1ZmZlciwgYnVmZmVySW5kZXgpOwogICAgICB9CiAgICAgIGJ1ZmZlckluZGV4ICs9IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgfQogICAgcmV0dXJuIGJ1ZmZlcjsKICB9CiAgZnVuY3Rpb24gdW5wYWNrQm91bmRpbmdTcGhlcmVzKGJ1ZmZlcikgewogICAgY29uc3QgcmVzdWx0ID0gbmV3IEFycmF5KGJ1ZmZlclswXSk7CiAgICBsZXQgY291bnQgPSAwOwogICAgbGV0IGkgPSAxOwogICAgd2hpbGUgKGkgPCBidWZmZXIubGVuZ3RoKSB7CiAgICAgIGlmIChidWZmZXJbaSsrXSA9PT0gMSkgewogICAgICAgIHJlc3VsdFtjb3VudF0gPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LnVucGFjayhidWZmZXIsIGkpOwogICAgICB9CiAgICAgICsrY291bnQ7CiAgICAgIGkgKz0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICB2YXIgUHJpbWl0aXZlUGlwZWxpbmUsIFByaW1pdGl2ZVBpcGVsaW5lX2RlZmF1bHQ7CiAgdmFyIGluaXRfUHJpbWl0aXZlUGlwZWxpbmUgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9TY2VuZS9QcmltaXRpdmVQaXBlbGluZS5qcyIoKSB7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0dlb2dyYXBoaWNQcm9qZWN0aW9uKCk7CiAgICAgIGluaXRfR2VvbWV0cnkoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlcygpOwogICAgICBpbml0X0dlb21ldHJ5UGlwZWxpbmUoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfTWF0cml4NCgpOwogICAgICBpbml0X09mZnNldEdlb21ldHJ5SW5zdGFuY2VBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9XZWJNZXJjYXRvclByb2plY3Rpb24oKTsKICAgICAgUHJpbWl0aXZlUGlwZWxpbmUgPSB7fTsKICAgICAgUHJpbWl0aXZlUGlwZWxpbmUuY29tYmluZUdlb21ldHJ5ID0gZnVuY3Rpb24ocGFyYW1ldGVycykgewogICAgICAgIGxldCBnZW9tZXRyaWVzOwogICAgICAgIGxldCBhdHRyaWJ1dGVMb2NhdGlvbnM7CiAgICAgICAgY29uc3QgaW5zdGFuY2VzID0gcGFyYW1ldGVycy5pbnN0YW5jZXM7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gaW5zdGFuY2VzLmxlbmd0aDsKICAgICAgICBsZXQgcGlja09mZnNldHM7CiAgICAgICAgbGV0IG9mZnNldEluc3RhbmNlRXh0ZW5kOwogICAgICAgIGxldCBoYXNPZmZzZXQgPSBmYWxzZTsKICAgICAgICBpZiAobGVuZ3RoID4gMCkgewogICAgICAgICAgZ2VvbWV0cmllcyA9IGdlb21ldHJ5UGlwZWxpbmUocGFyYW1ldGVycyk7CiAgICAgICAgICBpZiAoZ2VvbWV0cmllcy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIGF0dHJpYnV0ZUxvY2F0aW9ucyA9IEdlb21ldHJ5UGlwZWxpbmVfZGVmYXVsdC5jcmVhdGVBdHRyaWJ1dGVMb2NhdGlvbnMoCiAgICAgICAgICAgICAgZ2VvbWV0cmllc1swXQogICAgICAgICAgICApOwogICAgICAgICAgICBpZiAocGFyYW1ldGVycy5jcmVhdGVQaWNrT2Zmc2V0cykgewogICAgICAgICAgICAgIHBpY2tPZmZzZXRzID0gY3JlYXRlSW5zdGFuY2VQaWNrT2Zmc2V0cyhpbnN0YW5jZXMsIGdlb21ldHJpZXMpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGluc3RhbmNlc1swXS5hdHRyaWJ1dGVzKSAmJiBkZWZpbmVkX2RlZmF1bHQoaW5zdGFuY2VzWzBdLmF0dHJpYnV0ZXMub2Zmc2V0KSkgewogICAgICAgICAgICBvZmZzZXRJbnN0YW5jZUV4dGVuZCA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgICAgICAgICBoYXNPZmZzZXQgPSB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBib3VuZGluZ1NwaGVyZXMgPSBuZXcgQXJyYXkobGVuZ3RoKTsKICAgICAgICBjb25zdCBib3VuZGluZ1NwaGVyZXNDViA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgIGNvbnN0IGluc3RhbmNlID0gaW5zdGFuY2VzW2ldOwogICAgICAgICAgY29uc3QgZ2VvbWV0cnkgPSBpbnN0YW5jZS5nZW9tZXRyeTsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZ2VvbWV0cnkpKSB7CiAgICAgICAgICAgIGJvdW5kaW5nU3BoZXJlc1tpXSA9IGdlb21ldHJ5LmJvdW5kaW5nU3BoZXJlOwogICAgICAgICAgICBib3VuZGluZ1NwaGVyZXNDVltpXSA9IGdlb21ldHJ5LmJvdW5kaW5nU3BoZXJlQ1Y7CiAgICAgICAgICAgIGlmIChoYXNPZmZzZXQpIHsKICAgICAgICAgICAgICBvZmZzZXRJbnN0YW5jZUV4dGVuZFtpXSA9IGluc3RhbmNlLmdlb21ldHJ5Lm9mZnNldEF0dHJpYnV0ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgY29uc3QgZWFzdEhlbWlzcGhlcmVHZW9tZXRyeSA9IGluc3RhbmNlLmVhc3RIZW1pc3BoZXJlR2VvbWV0cnk7CiAgICAgICAgICBjb25zdCB3ZXN0SGVtaXNwaGVyZUdlb21ldHJ5ID0gaW5zdGFuY2Uud2VzdEhlbWlzcGhlcmVHZW9tZXRyeTsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZWFzdEhlbWlzcGhlcmVHZW9tZXRyeSkgJiYgZGVmaW5lZF9kZWZhdWx0KHdlc3RIZW1pc3BoZXJlR2VvbWV0cnkpKSB7CiAgICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZWFzdEhlbWlzcGhlcmVHZW9tZXRyeS5ib3VuZGluZ1NwaGVyZSkgJiYgZGVmaW5lZF9kZWZhdWx0KHdlc3RIZW1pc3BoZXJlR2VvbWV0cnkuYm91bmRpbmdTcGhlcmUpKSB7CiAgICAgICAgICAgICAgYm91bmRpbmdTcGhlcmVzW2ldID0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC51bmlvbigKICAgICAgICAgICAgICAgIGVhc3RIZW1pc3BoZXJlR2VvbWV0cnkuYm91bmRpbmdTcGhlcmUsCiAgICAgICAgICAgICAgICB3ZXN0SGVtaXNwaGVyZUdlb21ldHJ5LmJvdW5kaW5nU3BoZXJlCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGVhc3RIZW1pc3BoZXJlR2VvbWV0cnkuYm91bmRpbmdTcGhlcmVDVikgJiYgZGVmaW5lZF9kZWZhdWx0KHdlc3RIZW1pc3BoZXJlR2VvbWV0cnkuYm91bmRpbmdTcGhlcmVDVikpIHsKICAgICAgICAgICAgICBib3VuZGluZ1NwaGVyZXNDVltpXSA9IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQudW5pb24oCiAgICAgICAgICAgICAgICBlYXN0SGVtaXNwaGVyZUdlb21ldHJ5LmJvdW5kaW5nU3BoZXJlQ1YsCiAgICAgICAgICAgICAgICB3ZXN0SGVtaXNwaGVyZUdlb21ldHJ5LmJvdW5kaW5nU3BoZXJlQ1YKICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB7CiAgICAgICAgICBnZW9tZXRyaWVzLAogICAgICAgICAgbW9kZWxNYXRyaXg6IHBhcmFtZXRlcnMubW9kZWxNYXRyaXgsCiAgICAgICAgICBhdHRyaWJ1dGVMb2NhdGlvbnMsCiAgICAgICAgICBwaWNrT2Zmc2V0cywKICAgICAgICAgIG9mZnNldEluc3RhbmNlRXh0ZW5kLAogICAgICAgICAgYm91bmRpbmdTcGhlcmVzLAogICAgICAgICAgYm91bmRpbmdTcGhlcmVzQ1YKICAgICAgICB9OwogICAgICB9OwogICAgICBQcmltaXRpdmVQaXBlbGluZS5wYWNrQ3JlYXRlR2VvbWV0cnlSZXN1bHRzID0gZnVuY3Rpb24oaXRlbXMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgICAgICBjb25zdCBwYWNrZWREYXRhID0gbmV3IEZsb2F0NjRBcnJheShjb3VudENyZWF0ZUdlb21ldHJ5UmVzdWx0cyhpdGVtcykpOwogICAgICAgIGNvbnN0IHN0cmluZ1RhYmxlID0gW107CiAgICAgICAgY29uc3Qgc3RyaW5nSGFzaCA9IHt9OwogICAgICAgIGNvbnN0IGxlbmd0aCA9IGl0ZW1zLmxlbmd0aDsKICAgICAgICBsZXQgY291bnQgPSAwOwogICAgICAgIHBhY2tlZERhdGFbY291bnQrK10gPSBsZW5ndGg7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgY29uc3QgZ2VvbWV0cnkgPSBpdGVtc1tpXTsKICAgICAgICAgIGNvbnN0IHZhbGlkR2VvbWV0cnkgPSBkZWZpbmVkX2RlZmF1bHQoZ2VvbWV0cnkpOwogICAgICAgICAgcGFja2VkRGF0YVtjb3VudCsrXSA9IHZhbGlkR2VvbWV0cnkgPyAxIDogMDsKICAgICAgICAgIGlmICghdmFsaWRHZW9tZXRyeSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIHBhY2tlZERhdGFbY291bnQrK10gPSBnZW9tZXRyeS5wcmltaXRpdmVUeXBlOwogICAgICAgICAgcGFja2VkRGF0YVtjb3VudCsrXSA9IGdlb21ldHJ5Lmdlb21ldHJ5VHlwZTsKICAgICAgICAgIHBhY2tlZERhdGFbY291bnQrK10gPSBnZW9tZXRyeS5vZmZzZXRBdHRyaWJ1dGUgPz8gLTE7CiAgICAgICAgICBjb25zdCB2YWxpZEJvdW5kaW5nU3BoZXJlID0gZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5LmJvdW5kaW5nU3BoZXJlKSA/IDEgOiAwOwogICAgICAgICAgcGFja2VkRGF0YVtjb3VudCsrXSA9IHZhbGlkQm91bmRpbmdTcGhlcmU7CiAgICAgICAgICBpZiAodmFsaWRCb3VuZGluZ1NwaGVyZSkgewogICAgICAgICAgICBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LnBhY2soZ2VvbWV0cnkuYm91bmRpbmdTcGhlcmUsIHBhY2tlZERhdGEsIGNvdW50KTsKICAgICAgICAgIH0KICAgICAgICAgIGNvdW50ICs9IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgICAgY29uc3QgdmFsaWRCb3VuZGluZ1NwaGVyZUNWID0gZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5LmJvdW5kaW5nU3BoZXJlQ1YpID8gMSA6IDA7CiAgICAgICAgICBwYWNrZWREYXRhW2NvdW50KytdID0gdmFsaWRCb3VuZGluZ1NwaGVyZUNWOwogICAgICAgICAgaWYgKHZhbGlkQm91bmRpbmdTcGhlcmVDVikgewogICAgICAgICAgICBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LnBhY2soZ2VvbWV0cnkuYm91bmRpbmdTcGhlcmVDViwgcGFja2VkRGF0YSwgY291bnQpOwogICAgICAgICAgfQogICAgICAgICAgY291bnQgKz0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gZ2VvbWV0cnkuYXR0cmlidXRlczsKICAgICAgICAgIGNvbnN0IGF0dHJpYnV0ZXNUb1dyaXRlID0gW107CiAgICAgICAgICBmb3IgKGNvbnN0IHByb3BlcnR5IGluIGF0dHJpYnV0ZXMpIHsKICAgICAgICAgICAgaWYgKGF0dHJpYnV0ZXMuaGFzT3duUHJvcGVydHkocHJvcGVydHkpICYmIGRlZmluZWRfZGVmYXVsdChhdHRyaWJ1dGVzW3Byb3BlcnR5XSkpIHsKICAgICAgICAgICAgICBhdHRyaWJ1dGVzVG9Xcml0ZS5wdXNoKHByb3BlcnR5KTsKICAgICAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChzdHJpbmdIYXNoW3Byb3BlcnR5XSkpIHsKICAgICAgICAgICAgICAgIHN0cmluZ0hhc2hbcHJvcGVydHldID0gc3RyaW5nVGFibGUubGVuZ3RoOwogICAgICAgICAgICAgICAgc3RyaW5nVGFibGUucHVzaChwcm9wZXJ0eSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBwYWNrZWREYXRhW2NvdW50KytdID0gYXR0cmlidXRlc1RvV3JpdGUubGVuZ3RoOwogICAgICAgICAgZm9yIChsZXQgcSA9IDA7IHEgPCBhdHRyaWJ1dGVzVG9Xcml0ZS5sZW5ndGg7IHErKykgewogICAgICAgICAgICBjb25zdCBuYW1lID0gYXR0cmlidXRlc1RvV3JpdGVbcV07CiAgICAgICAgICAgIGNvbnN0IGF0dHJpYnV0ZSA9IGF0dHJpYnV0ZXNbbmFtZV07CiAgICAgICAgICAgIHBhY2tlZERhdGFbY291bnQrK10gPSBzdHJpbmdIYXNoW25hbWVdOwogICAgICAgICAgICBwYWNrZWREYXRhW2NvdW50KytdID0gYXR0cmlidXRlLmNvbXBvbmVudERhdGF0eXBlOwogICAgICAgICAgICBwYWNrZWREYXRhW2NvdW50KytdID0gYXR0cmlidXRlLmNvbXBvbmVudHNQZXJBdHRyaWJ1dGU7CiAgICAgICAgICAgIHBhY2tlZERhdGFbY291bnQrK10gPSBhdHRyaWJ1dGUubm9ybWFsaXplID8gMSA6IDA7CiAgICAgICAgICAgIHBhY2tlZERhdGFbY291bnQrK10gPSBhdHRyaWJ1dGUudmFsdWVzLmxlbmd0aDsKICAgICAgICAgICAgcGFja2VkRGF0YS5zZXQoYXR0cmlidXRlLnZhbHVlcywgY291bnQpOwogICAgICAgICAgICBjb3VudCArPSBhdHRyaWJ1dGUudmFsdWVzLmxlbmd0aDsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGluZGljZXNMZW5ndGggPSBkZWZpbmVkX2RlZmF1bHQoZ2VvbWV0cnkuaW5kaWNlcykgPyBnZW9tZXRyeS5pbmRpY2VzLmxlbmd0aCA6IDA7CiAgICAgICAgICBwYWNrZWREYXRhW2NvdW50KytdID0gaW5kaWNlc0xlbmd0aDsKICAgICAgICAgIGlmIChpbmRpY2VzTGVuZ3RoID4gMCkgewogICAgICAgICAgICBwYWNrZWREYXRhLnNldChnZW9tZXRyeS5pbmRpY2VzLCBjb3VudCk7CiAgICAgICAgICAgIGNvdW50ICs9IGluZGljZXNMZW5ndGg7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaChwYWNrZWREYXRhLmJ1ZmZlcik7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHN0cmluZ1RhYmxlLAogICAgICAgICAgcGFja2VkRGF0YQogICAgICAgIH07CiAgICAgIH07CiAgICAgIFByaW1pdGl2ZVBpcGVsaW5lLnVucGFja0NyZWF0ZUdlb21ldHJ5UmVzdWx0cyA9IGZ1bmN0aW9uKGNyZWF0ZUdlb21ldHJ5UmVzdWx0KSB7CiAgICAgICAgY29uc3Qgc3RyaW5nVGFibGUgPSBjcmVhdGVHZW9tZXRyeVJlc3VsdC5zdHJpbmdUYWJsZTsKICAgICAgICBjb25zdCBwYWNrZWRHZW9tZXRyeSA9IGNyZWF0ZUdlb21ldHJ5UmVzdWx0LnBhY2tlZERhdGE7CiAgICAgICAgbGV0IGk7CiAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IEFycmF5KHBhY2tlZEdlb21ldHJ5WzBdKTsKICAgICAgICBsZXQgcmVzdWx0SW5kZXggPSAwOwogICAgICAgIGxldCBwYWNrZWRHZW9tZXRyeUluZGV4ID0gMTsKICAgICAgICB3aGlsZSAocGFja2VkR2VvbWV0cnlJbmRleCA8IHBhY2tlZEdlb21ldHJ5Lmxlbmd0aCkgewogICAgICAgICAgY29uc3QgdmFsaWQgPSBwYWNrZWRHZW9tZXRyeVtwYWNrZWRHZW9tZXRyeUluZGV4KytdID09PSAxOwogICAgICAgICAgaWYgKCF2YWxpZCkgewogICAgICAgICAgICByZXN1bHRbcmVzdWx0SW5kZXgrK10gPSB2b2lkIDA7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgcHJpbWl0aXZlVHlwZSA9IHBhY2tlZEdlb21ldHJ5W3BhY2tlZEdlb21ldHJ5SW5kZXgrK107CiAgICAgICAgICBjb25zdCBnZW9tZXRyeVR5cGUgPSBwYWNrZWRHZW9tZXRyeVtwYWNrZWRHZW9tZXRyeUluZGV4KytdOwogICAgICAgICAgbGV0IG9mZnNldEF0dHJpYnV0ZSA9IHBhY2tlZEdlb21ldHJ5W3BhY2tlZEdlb21ldHJ5SW5kZXgrK107CiAgICAgICAgICBpZiAob2Zmc2V0QXR0cmlidXRlID09PSAtMSkgewogICAgICAgICAgICBvZmZzZXRBdHRyaWJ1dGUgPSB2b2lkIDA7CiAgICAgICAgICB9CiAgICAgICAgICBsZXQgYm91bmRpbmdTcGhlcmU7CiAgICAgICAgICBsZXQgYm91bmRpbmdTcGhlcmVDVjsKICAgICAgICAgIGNvbnN0IHZhbGlkQm91bmRpbmdTcGhlcmUgPSBwYWNrZWRHZW9tZXRyeVtwYWNrZWRHZW9tZXRyeUluZGV4KytdID09PSAxOwogICAgICAgICAgaWYgKHZhbGlkQm91bmRpbmdTcGhlcmUpIHsKICAgICAgICAgICAgYm91bmRpbmdTcGhlcmUgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LnVucGFjaygKICAgICAgICAgICAgICBwYWNrZWRHZW9tZXRyeSwKICAgICAgICAgICAgICBwYWNrZWRHZW9tZXRyeUluZGV4CiAgICAgICAgICAgICk7CiAgICAgICAgICB9CiAgICAgICAgICBwYWNrZWRHZW9tZXRyeUluZGV4ICs9IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgICAgY29uc3QgdmFsaWRCb3VuZGluZ1NwaGVyZUNWID0gcGFja2VkR2VvbWV0cnlbcGFja2VkR2VvbWV0cnlJbmRleCsrXSA9PT0gMTsKICAgICAgICAgIGlmICh2YWxpZEJvdW5kaW5nU3BoZXJlQ1YpIHsKICAgICAgICAgICAgYm91bmRpbmdTcGhlcmVDViA9IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgICAgIHBhY2tlZEdlb21ldHJ5LAogICAgICAgICAgICAgIHBhY2tlZEdlb21ldHJ5SW5kZXgKICAgICAgICAgICAgKTsKICAgICAgICAgIH0KICAgICAgICAgIHBhY2tlZEdlb21ldHJ5SW5kZXggKz0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgICBsZXQgbGVuZ3RoOwogICAgICAgICAgbGV0IHZhbHVlczsKICAgICAgICAgIGxldCBjb21wb25lbnRzUGVyQXR0cmlidXRlOwogICAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZXNfZGVmYXVsdCgpOwogICAgICAgICAgY29uc3QgbnVtQXR0cmlidXRlcyA9IHBhY2tlZEdlb21ldHJ5W3BhY2tlZEdlb21ldHJ5SW5kZXgrK107CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtQXR0cmlidXRlczsgaSsrKSB7CiAgICAgICAgICAgIGNvbnN0IG5hbWUgPSBzdHJpbmdUYWJsZVtwYWNrZWRHZW9tZXRyeVtwYWNrZWRHZW9tZXRyeUluZGV4KytdXTsKICAgICAgICAgICAgY29uc3QgY29tcG9uZW50RGF0YXR5cGUgPSBwYWNrZWRHZW9tZXRyeVtwYWNrZWRHZW9tZXRyeUluZGV4KytdOwogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlID0gcGFja2VkR2VvbWV0cnlbcGFja2VkR2VvbWV0cnlJbmRleCsrXTsKICAgICAgICAgICAgY29uc3Qgbm9ybWFsaXplID0gcGFja2VkR2VvbWV0cnlbcGFja2VkR2VvbWV0cnlJbmRleCsrXSAhPT0gMDsKICAgICAgICAgICAgbGVuZ3RoID0gcGFja2VkR2VvbWV0cnlbcGFja2VkR2VvbWV0cnlJbmRleCsrXTsKICAgICAgICAgICAgdmFsdWVzID0gQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KGNvbXBvbmVudERhdGF0eXBlLCBsZW5ndGgpOwogICAgICAgICAgICBmb3IgKGxldCB2YWx1ZXNJbmRleCA9IDA7IHZhbHVlc0luZGV4IDwgbGVuZ3RoOyB2YWx1ZXNJbmRleCsrKSB7CiAgICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0luZGV4XSA9IHBhY2tlZEdlb21ldHJ5W3BhY2tlZEdlb21ldHJ5SW5kZXgrK107CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYXR0cmlidXRlc1tuYW1lXSA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZSwKICAgICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlLAogICAgICAgICAgICAgIG5vcm1hbGl6ZSwKICAgICAgICAgICAgICB2YWx1ZXMKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBsZXQgaW5kaWNlczsKICAgICAgICAgIGxlbmd0aCA9IHBhY2tlZEdlb21ldHJ5W3BhY2tlZEdlb21ldHJ5SW5kZXgrK107CiAgICAgICAgICBpZiAobGVuZ3RoID4gMCkgewogICAgICAgICAgICBjb25zdCBudW1iZXJPZlZlcnRpY2VzID0gdmFsdWVzLmxlbmd0aCAvIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU7CiAgICAgICAgICAgIGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheShudW1iZXJPZlZlcnRpY2VzLCBsZW5ndGgpOwogICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICBpbmRpY2VzW2ldID0gcGFja2VkR2VvbWV0cnlbcGFja2VkR2VvbWV0cnlJbmRleCsrXTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0W3Jlc3VsdEluZGV4KytdID0gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgICAgICBwcmltaXRpdmVUeXBlLAogICAgICAgICAgICBnZW9tZXRyeVR5cGUsCiAgICAgICAgICAgIGJvdW5kaW5nU3BoZXJlLAogICAgICAgICAgICBib3VuZGluZ1NwaGVyZUNWLAogICAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgICBhdHRyaWJ1dGVzLAogICAgICAgICAgICBvZmZzZXRBdHRyaWJ1dGUKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBQcmltaXRpdmVQaXBlbGluZS5wYWNrQ29tYmluZUdlb21ldHJ5UGFyYW1ldGVycyA9IGZ1bmN0aW9uKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgICAgICBjb25zdCBjcmVhdGVHZW9tZXRyeVJlc3VsdHMgPSBwYXJhbWV0ZXJzLmNyZWF0ZUdlb21ldHJ5UmVzdWx0czsKICAgICAgICBjb25zdCBsZW5ndGggPSBjcmVhdGVHZW9tZXRyeVJlc3VsdHMubGVuZ3RoOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaChjcmVhdGVHZW9tZXRyeVJlc3VsdHNbaV0ucGFja2VkRGF0YS5idWZmZXIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gewogICAgICAgICAgY3JlYXRlR2VvbWV0cnlSZXN1bHRzOiBwYXJhbWV0ZXJzLmNyZWF0ZUdlb21ldHJ5UmVzdWx0cywKICAgICAgICAgIHBhY2tlZEluc3RhbmNlczogcGFja0luc3RhbmNlc0ZvckNvbWJpbmUoCiAgICAgICAgICAgIHBhcmFtZXRlcnMuaW5zdGFuY2VzLAogICAgICAgICAgICB0cmFuc2ZlcmFibGVPYmplY3RzCiAgICAgICAgICApLAogICAgICAgICAgZWxsaXBzb2lkOiBwYXJhbWV0ZXJzLmVsbGlwc29pZCwKICAgICAgICAgIGlzR2VvZ3JhcGhpYzogcGFyYW1ldGVycy5wcm9qZWN0aW9uIGluc3RhbmNlb2YgR2VvZ3JhcGhpY1Byb2plY3Rpb25fZGVmYXVsdCwKICAgICAgICAgIGVsZW1lbnRJbmRleFVpbnRTdXBwb3J0ZWQ6IHBhcmFtZXRlcnMuZWxlbWVudEluZGV4VWludFN1cHBvcnRlZCwKICAgICAgICAgIHNjZW5lM0RPbmx5OiBwYXJhbWV0ZXJzLnNjZW5lM0RPbmx5LAogICAgICAgICAgdmVydGV4Q2FjaGVPcHRpbWl6ZTogcGFyYW1ldGVycy52ZXJ0ZXhDYWNoZU9wdGltaXplLAogICAgICAgICAgY29tcHJlc3NWZXJ0aWNlczogcGFyYW1ldGVycy5jb21wcmVzc1ZlcnRpY2VzLAogICAgICAgICAgbW9kZWxNYXRyaXg6IHBhcmFtZXRlcnMubW9kZWxNYXRyaXgsCiAgICAgICAgICBjcmVhdGVQaWNrT2Zmc2V0czogcGFyYW1ldGVycy5jcmVhdGVQaWNrT2Zmc2V0cwogICAgICAgIH07CiAgICAgIH07CiAgICAgIFByaW1pdGl2ZVBpcGVsaW5lLnVucGFja0NvbWJpbmVHZW9tZXRyeVBhcmFtZXRlcnMgPSBmdW5jdGlvbihwYWNrZWRQYXJhbWV0ZXJzKSB7CiAgICAgICAgY29uc3QgaW5zdGFuY2VzID0gdW5wYWNrSW5zdGFuY2VzRm9yQ29tYmluZShwYWNrZWRQYXJhbWV0ZXJzLnBhY2tlZEluc3RhbmNlcyk7CiAgICAgICAgY29uc3QgY3JlYXRlR2VvbWV0cnlSZXN1bHRzID0gcGFja2VkUGFyYW1ldGVycy5jcmVhdGVHZW9tZXRyeVJlc3VsdHM7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gY3JlYXRlR2VvbWV0cnlSZXN1bHRzLmxlbmd0aDsKICAgICAgICBsZXQgaW5zdGFuY2VJbmRleCA9IDA7CiAgICAgICAgZm9yIChsZXQgcmVzdWx0SW5kZXggPSAwOyByZXN1bHRJbmRleCA8IGxlbmd0aDsgcmVzdWx0SW5kZXgrKykgewogICAgICAgICAgY29uc3QgZ2VvbWV0cmllcyA9IFByaW1pdGl2ZVBpcGVsaW5lLnVucGFja0NyZWF0ZUdlb21ldHJ5UmVzdWx0cygKICAgICAgICAgICAgY3JlYXRlR2VvbWV0cnlSZXN1bHRzW3Jlc3VsdEluZGV4XQogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IGdlb21ldHJpZXNMZW5ndGggPSBnZW9tZXRyaWVzLmxlbmd0aDsKICAgICAgICAgIGZvciAobGV0IGdlb21ldHJ5SW5kZXggPSAwOyBnZW9tZXRyeUluZGV4IDwgZ2VvbWV0cmllc0xlbmd0aDsgZ2VvbWV0cnlJbmRleCsrKSB7CiAgICAgICAgICAgIGNvbnN0IGdlb21ldHJ5ID0gZ2VvbWV0cmllc1tnZW9tZXRyeUluZGV4XTsKICAgICAgICAgICAgY29uc3QgaW5zdGFuY2UgPSBpbnN0YW5jZXNbaW5zdGFuY2VJbmRleF07CiAgICAgICAgICAgIGluc3RhbmNlLmdlb21ldHJ5ID0gZ2VvbWV0cnk7CiAgICAgICAgICAgICsraW5zdGFuY2VJbmRleDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUocGFja2VkUGFyYW1ldGVycy5lbGxpcHNvaWQpOwogICAgICAgIGNvbnN0IHByb2plY3Rpb24gPSBwYWNrZWRQYXJhbWV0ZXJzLmlzR2VvZ3JhcGhpYyA/IG5ldyBHZW9ncmFwaGljUHJvamVjdGlvbl9kZWZhdWx0KGVsbGlwc29pZCkgOiBuZXcgV2ViTWVyY2F0b3JQcm9qZWN0aW9uX2RlZmF1bHQoZWxsaXBzb2lkKTsKICAgICAgICByZXR1cm4gewogICAgICAgICAgaW5zdGFuY2VzLAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgcHJvamVjdGlvbiwKICAgICAgICAgIGVsZW1lbnRJbmRleFVpbnRTdXBwb3J0ZWQ6IHBhY2tlZFBhcmFtZXRlcnMuZWxlbWVudEluZGV4VWludFN1cHBvcnRlZCwKICAgICAgICAgIHNjZW5lM0RPbmx5OiBwYWNrZWRQYXJhbWV0ZXJzLnNjZW5lM0RPbmx5LAogICAgICAgICAgdmVydGV4Q2FjaGVPcHRpbWl6ZTogcGFja2VkUGFyYW1ldGVycy52ZXJ0ZXhDYWNoZU9wdGltaXplLAogICAgICAgICAgY29tcHJlc3NWZXJ0aWNlczogcGFja2VkUGFyYW1ldGVycy5jb21wcmVzc1ZlcnRpY2VzLAogICAgICAgICAgbW9kZWxNYXRyaXg6IE1hdHJpeDRfZGVmYXVsdC5jbG9uZShwYWNrZWRQYXJhbWV0ZXJzLm1vZGVsTWF0cml4KSwKICAgICAgICAgIGNyZWF0ZVBpY2tPZmZzZXRzOiBwYWNrZWRQYXJhbWV0ZXJzLmNyZWF0ZVBpY2tPZmZzZXRzCiAgICAgICAgfTsKICAgICAgfTsKICAgICAgUHJpbWl0aXZlUGlwZWxpbmUucGFja0NvbWJpbmVHZW9tZXRyeVJlc3VsdHMgPSBmdW5jdGlvbihyZXN1bHRzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChyZXN1bHRzLmdlb21ldHJpZXMpKSB7CiAgICAgICAgICB0cmFuc2Zlckdlb21ldHJpZXMocmVzdWx0cy5nZW9tZXRyaWVzLCB0cmFuc2ZlcmFibGVPYmplY3RzKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcGFja2VkQm91bmRpbmdTcGhlcmVzID0gcGFja0JvdW5kaW5nU3BoZXJlcyhyZXN1bHRzLmJvdW5kaW5nU3BoZXJlcyk7CiAgICAgICAgY29uc3QgcGFja2VkQm91bmRpbmdTcGhlcmVzQ1YgPSBwYWNrQm91bmRpbmdTcGhlcmVzKAogICAgICAgICAgcmVzdWx0cy5ib3VuZGluZ1NwaGVyZXNDVgogICAgICAgICk7CiAgICAgICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKAogICAgICAgICAgcGFja2VkQm91bmRpbmdTcGhlcmVzLmJ1ZmZlciwKICAgICAgICAgIHBhY2tlZEJvdW5kaW5nU3BoZXJlc0NWLmJ1ZmZlcgogICAgICAgICk7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGdlb21ldHJpZXM6IHJlc3VsdHMuZ2VvbWV0cmllcywKICAgICAgICAgIGF0dHJpYnV0ZUxvY2F0aW9uczogcmVzdWx0cy5hdHRyaWJ1dGVMb2NhdGlvbnMsCiAgICAgICAgICBtb2RlbE1hdHJpeDogcmVzdWx0cy5tb2RlbE1hdHJpeCwKICAgICAgICAgIHBpY2tPZmZzZXRzOiByZXN1bHRzLnBpY2tPZmZzZXRzLAogICAgICAgICAgb2Zmc2V0SW5zdGFuY2VFeHRlbmQ6IHJlc3VsdHMub2Zmc2V0SW5zdGFuY2VFeHRlbmQsCiAgICAgICAgICBib3VuZGluZ1NwaGVyZXM6IHBhY2tlZEJvdW5kaW5nU3BoZXJlcywKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlc0NWOiBwYWNrZWRCb3VuZGluZ1NwaGVyZXNDVgogICAgICAgIH07CiAgICAgIH07CiAgICAgIFByaW1pdGl2ZVBpcGVsaW5lLnVucGFja0NvbWJpbmVHZW9tZXRyeVJlc3VsdHMgPSBmdW5jdGlvbihwYWNrZWRSZXN1bHQpIHsKICAgICAgICByZXR1cm4gewogICAgICAgICAgZ2VvbWV0cmllczogcGFja2VkUmVzdWx0Lmdlb21ldHJpZXMsCiAgICAgICAgICBhdHRyaWJ1dGVMb2NhdGlvbnM6IHBhY2tlZFJlc3VsdC5hdHRyaWJ1dGVMb2NhdGlvbnMsCiAgICAgICAgICBtb2RlbE1hdHJpeDogcGFja2VkUmVzdWx0Lm1vZGVsTWF0cml4LAogICAgICAgICAgcGlja09mZnNldHM6IHBhY2tlZFJlc3VsdC5waWNrT2Zmc2V0cywKICAgICAgICAgIG9mZnNldEluc3RhbmNlRXh0ZW5kOiBwYWNrZWRSZXN1bHQub2Zmc2V0SW5zdGFuY2VFeHRlbmQsCiAgICAgICAgICBib3VuZGluZ1NwaGVyZXM6IHVucGFja0JvdW5kaW5nU3BoZXJlcyhwYWNrZWRSZXN1bHQuYm91bmRpbmdTcGhlcmVzKSwKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlc0NWOiB1bnBhY2tCb3VuZGluZ1NwaGVyZXMocGFja2VkUmVzdWx0LmJvdW5kaW5nU3BoZXJlc0NWKQogICAgICAgIH07CiAgICAgIH07CiAgICAgIFByaW1pdGl2ZVBpcGVsaW5lX2RlZmF1bHQgPSBQcmltaXRpdmVQaXBlbGluZTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2Zvcm1hdEVycm9yLmpzCiAgZnVuY3Rpb24gZm9ybWF0RXJyb3Iob2JqZWN0KSB7CiAgICBsZXQgcmVzdWx0OwogICAgY29uc3QgbmFtZSA9IG9iamVjdC5uYW1lOwogICAgY29uc3QgbWVzc2FnZSA9IG9iamVjdC5tZXNzYWdlOwogICAgaWYgKGRlZmluZWRfZGVmYXVsdChuYW1lKSAmJiBkZWZpbmVkX2RlZmF1bHQobWVzc2FnZSkpIHsKICAgICAgcmVzdWx0ID0gYCR7bmFtZX06ICR7bWVzc2FnZX1gOwogICAgfSBlbHNlIHsKICAgICAgcmVzdWx0ID0gb2JqZWN0LnRvU3RyaW5nKCk7CiAgICB9CiAgICBjb25zdCBzdGFjayA9IG9iamVjdC5zdGFjazsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoc3RhY2spKSB7CiAgICAgIHJlc3VsdCArPSBgCiR7c3RhY2t9YDsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIHZhciBmb3JtYXRFcnJvcl9kZWZhdWx0OwogIHZhciBpbml0X2Zvcm1hdEVycm9yID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9mb3JtYXRFcnJvci5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBmb3JtYXRFcnJvcl9kZWZhdWx0ID0gZm9ybWF0RXJyb3I7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyLmpzCiAgdmFyIGNyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXJfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXJfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlVGFza1Byb2Nlc3Nvcldvcmtlcl9kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gY3JlYXRlVGFza1Byb2Nlc3Nvcldvcmtlcih3b3JrZXJGdW5jdGlvbikgewogICAgYXN5bmMgZnVuY3Rpb24gb25NZXNzYWdlSGFuZGxlcih7IGRhdGEgfSkgewogICAgICBjb25zdCB0cmFuc2ZlcmFibGVPYmplY3RzID0gW107CiAgICAgIGNvbnN0IHJlc3BvbnNlTWVzc2FnZSA9IHsKICAgICAgICBpZDogZGF0YS5pZCwKICAgICAgICByZXN1bHQ6IHZvaWQgMCwKICAgICAgICBlcnJvcjogdm9pZCAwCiAgICAgIH07CiAgICAgIHNlbGYuQ0VTSVVNX0JBU0VfVVJMID0gZGF0YS5iYXNlVXJsOwogICAgICB0cnkgewogICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdvcmtlckZ1bmN0aW9uKGRhdGEucGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cyk7CiAgICAgICAgcmVzcG9uc2VNZXNzYWdlLnJlc3VsdCA9IHJlc3VsdDsKICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikgewogICAgICAgICAgcmVzcG9uc2VNZXNzYWdlLmVycm9yID0gewogICAgICAgICAgICBuYW1lOiBlcnJvci5uYW1lLAogICAgICAgICAgICBtZXNzYWdlOiBlcnJvci5tZXNzYWdlLAogICAgICAgICAgICBzdGFjazogZXJyb3Iuc3RhY2sKICAgICAgICAgIH07CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3BvbnNlTWVzc2FnZS5lcnJvciA9IGVycm9yOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoIWRhdGEuY2FuVHJhbnNmZXJBcnJheUJ1ZmZlcikgewogICAgICAgIHRyYW5zZmVyYWJsZU9iamVjdHMubGVuZ3RoID0gMDsKICAgICAgfQogICAgICB0cnkgewogICAgICAgIHBvc3RNZXNzYWdlKHJlc3BvbnNlTWVzc2FnZSwgdHJhbnNmZXJhYmxlT2JqZWN0cyk7CiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgcmVzcG9uc2VNZXNzYWdlLnJlc3VsdCA9IHZvaWQgMDsKICAgICAgICByZXNwb25zZU1lc3NhZ2UuZXJyb3IgPSBgcG9zdE1lc3NhZ2UgZmFpbGVkIHdpdGggZXJyb3I6ICR7Zm9ybWF0RXJyb3JfZGVmYXVsdCgKICAgICAgICAgIGVycm9yCiAgICAgICAgKX0KICB3aXRoIHJlc3BvbnNlTWVzc2FnZTogJHtKU09OLnN0cmluZ2lmeShyZXNwb25zZU1lc3NhZ2UpfWA7CiAgICAgICAgcG9zdE1lc3NhZ2UocmVzcG9uc2VNZXNzYWdlKTsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gb25NZXNzYWdlRXJyb3JIYW5kbGVyKGV2ZW50KSB7CiAgICAgIHBvc3RNZXNzYWdlKHsKICAgICAgICBpZDogZXZlbnQuZGF0YT8uaWQsCiAgICAgICAgZXJyb3I6IGBwb3N0TWVzc2FnZSBmYWlsZWQgd2l0aCBlcnJvcjogJHtKU09OLnN0cmluZ2lmeShldmVudCl9YAogICAgICB9KTsKICAgIH0KICAgIHNlbGYub25tZXNzYWdlID0gb25NZXNzYWdlSGFuZGxlcjsKICAgIHNlbGYub25tZXNzYWdlZXJyb3IgPSBvbk1lc3NhZ2VFcnJvckhhbmRsZXI7CiAgICByZXR1cm4gc2VsZjsKICB9CiAgdmFyIGNyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXJfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyLmpzIigpIHsKICAgICAgaW5pdF9mb3JtYXRFcnJvcigpOwogICAgICBjcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyX2RlZmF1bHQgPSBjcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY29tYmluZUdlb21ldHJ5LmpzCiAgdmFyIGNvbWJpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY29tYmluZUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNvbWJpbmVHZW9tZXRyeV9kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gY29tYmluZUdlb21ldHJ5KHBhY2tlZFBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIGNvbnN0IHBhcmFtZXRlcnMgPSBQcmltaXRpdmVQaXBlbGluZV9kZWZhdWx0LnVucGFja0NvbWJpbmVHZW9tZXRyeVBhcmFtZXRlcnMocGFja2VkUGFyYW1ldGVycyk7CiAgICBjb25zdCByZXN1bHRzID0gUHJpbWl0aXZlUGlwZWxpbmVfZGVmYXVsdC5jb21iaW5lR2VvbWV0cnkocGFyYW1ldGVycyk7CiAgICByZXR1cm4gUHJpbWl0aXZlUGlwZWxpbmVfZGVmYXVsdC5wYWNrQ29tYmluZUdlb21ldHJ5UmVzdWx0cygKICAgICAgcmVzdWx0cywKICAgICAgdHJhbnNmZXJhYmxlT2JqZWN0cwogICAgKTsKICB9CiAgdmFyIGNvbWJpbmVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X2NvbWJpbmVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY29tYmluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9QcmltaXRpdmVQaXBlbGluZSgpOwogICAgICBpbml0X2NyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXIoKTsKICAgICAgY29tYmluZUdlb21ldHJ5X2RlZmF1bHQgPSBjcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyX2RlZmF1bHQoY29tYmluZUdlb21ldHJ5KTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dlb21ldHJ5T2Zmc2V0QXR0cmlidXRlLmpzCiAgdmFyIEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlLCBHZW9tZXRyeU9mZnNldEF0dHJpYnV0ZV9kZWZhdWx0OwogIHZhciBpbml0X0dlb21ldHJ5T2Zmc2V0QXR0cmlidXRlID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9HZW9tZXRyeU9mZnNldEF0dHJpYnV0ZS5qcyIoKSB7CiAgICAgIEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlID0gewogICAgICAgIE5PTkU6IDAsCiAgICAgICAgVE9QOiAxLAogICAgICAgIEFMTDogMgogICAgICB9OwogICAgICBHZW9tZXRyeU9mZnNldEF0dHJpYnV0ZV9kZWZhdWx0ID0gT2JqZWN0LmZyZWV6ZShHZW9tZXRyeU9mZnNldEF0dHJpYnV0ZSk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9WZXJ0ZXhGb3JtYXQuanMKICBmdW5jdGlvbiBWZXJ0ZXhGb3JtYXQob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgdGhpcy5wb3NpdGlvbiA9IG9wdGlvbnMucG9zaXRpb24gPz8gZmFsc2U7CiAgICB0aGlzLm5vcm1hbCA9IG9wdGlvbnMubm9ybWFsID8/IGZhbHNlOwogICAgdGhpcy5zdCA9IG9wdGlvbnMuc3QgPz8gZmFsc2U7CiAgICB0aGlzLmJpdGFuZ2VudCA9IG9wdGlvbnMuYml0YW5nZW50ID8/IGZhbHNlOwogICAgdGhpcy50YW5nZW50ID0gb3B0aW9ucy50YW5nZW50ID8/IGZhbHNlOwogICAgdGhpcy5jb2xvciA9IG9wdGlvbnMuY29sb3IgPz8gZmFsc2U7CiAgfQogIHZhciBWZXJ0ZXhGb3JtYXRfZGVmYXVsdDsKICB2YXIgaW5pdF9WZXJ0ZXhGb3JtYXQgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1ZlcnRleEZvcm1hdC5qcyIoKSB7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIFZlcnRleEZvcm1hdC5QT1NJVElPTl9PTkxZID0gT2JqZWN0LmZyZWV6ZSgKICAgICAgICBuZXcgVmVydGV4Rm9ybWF0KHsKICAgICAgICAgIHBvc2l0aW9uOiB0cnVlCiAgICAgICAgfSkKICAgICAgKTsKICAgICAgVmVydGV4Rm9ybWF0LlBPU0lUSU9OX0FORF9OT1JNQUwgPSBPYmplY3QuZnJlZXplKAogICAgICAgIG5ldyBWZXJ0ZXhGb3JtYXQoewogICAgICAgICAgcG9zaXRpb246IHRydWUsCiAgICAgICAgICBub3JtYWw6IHRydWUKICAgICAgICB9KQogICAgICApOwogICAgICBWZXJ0ZXhGb3JtYXQuUE9TSVRJT05fTk9STUFMX0FORF9TVCA9IE9iamVjdC5mcmVlemUoCiAgICAgICAgbmV3IFZlcnRleEZvcm1hdCh7CiAgICAgICAgICBwb3NpdGlvbjogdHJ1ZSwKICAgICAgICAgIG5vcm1hbDogdHJ1ZSwKICAgICAgICAgIHN0OiB0cnVlCiAgICAgICAgfSkKICAgICAgKTsKICAgICAgVmVydGV4Rm9ybWF0LlBPU0lUSU9OX0FORF9TVCA9IE9iamVjdC5mcmVlemUoCiAgICAgICAgbmV3IFZlcnRleEZvcm1hdCh7CiAgICAgICAgICBwb3NpdGlvbjogdHJ1ZSwKICAgICAgICAgIHN0OiB0cnVlCiAgICAgICAgfSkKICAgICAgKTsKICAgICAgVmVydGV4Rm9ybWF0LlBPU0lUSU9OX0FORF9DT0xPUiA9IE9iamVjdC5mcmVlemUoCiAgICAgICAgbmV3IFZlcnRleEZvcm1hdCh7CiAgICAgICAgICBwb3NpdGlvbjogdHJ1ZSwKICAgICAgICAgIGNvbG9yOiB0cnVlCiAgICAgICAgfSkKICAgICAgKTsKICAgICAgVmVydGV4Rm9ybWF0LkFMTCA9IE9iamVjdC5mcmVlemUoCiAgICAgICAgbmV3IFZlcnRleEZvcm1hdCh7CiAgICAgICAgICBwb3NpdGlvbjogdHJ1ZSwKICAgICAgICAgIG5vcm1hbDogdHJ1ZSwKICAgICAgICAgIHN0OiB0cnVlLAogICAgICAgICAgdGFuZ2VudDogdHJ1ZSwKICAgICAgICAgIGJpdGFuZ2VudDogdHJ1ZQogICAgICAgIH0pCiAgICAgICk7CiAgICAgIFZlcnRleEZvcm1hdC5ERUZBVUxUID0gVmVydGV4Rm9ybWF0LlBPU0lUSU9OX05PUk1BTF9BTkRfU1Q7CiAgICAgIFZlcnRleEZvcm1hdC5wYWNrZWRMZW5ndGggPSA2OwogICAgICBWZXJ0ZXhGb3JtYXQucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHZhbHVlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInZhbHVlIGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFycmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLnBvc2l0aW9uID8gMSA6IDA7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLm5vcm1hbCA/IDEgOiAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5zdCA/IDEgOiAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS50YW5nZW50ID8gMSA6IDA7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLmJpdGFuZ2VudCA/IDEgOiAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXhdID0gdmFsdWUuY29sb3IgPyAxIDogMDsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIFZlcnRleEZvcm1hdC51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYXJyYXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYXJyYXkgaXMgcmVxdWlyZWQiKTsKICAgICAgICB9CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgVmVydGV4Rm9ybWF0KCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5wb3NpdGlvbiA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPT09IDE7CiAgICAgICAgcmVzdWx0Lm5vcm1hbCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPT09IDE7CiAgICAgICAgcmVzdWx0LnN0ID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9PT0gMTsKICAgICAgICByZXN1bHQudGFuZ2VudCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPT09IDE7CiAgICAgICAgcmVzdWx0LmJpdGFuZ2VudCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPT09IDE7CiAgICAgICAgcmVzdWx0LmNvbG9yID0gYXJyYXlbc3RhcnRpbmdJbmRleF0gPT09IDE7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgVmVydGV4Rm9ybWF0LmNsb25lID0gZnVuY3Rpb24odmVydGV4Rm9ybWF0LCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh2ZXJ0ZXhGb3JtYXQpKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgVmVydGV4Rm9ybWF0KCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5wb3NpdGlvbiA9IHZlcnRleEZvcm1hdC5wb3NpdGlvbjsKICAgICAgICByZXN1bHQubm9ybWFsID0gdmVydGV4Rm9ybWF0Lm5vcm1hbDsKICAgICAgICByZXN1bHQuc3QgPSB2ZXJ0ZXhGb3JtYXQuc3Q7CiAgICAgICAgcmVzdWx0LnRhbmdlbnQgPSB2ZXJ0ZXhGb3JtYXQudGFuZ2VudDsKICAgICAgICByZXN1bHQuYml0YW5nZW50ID0gdmVydGV4Rm9ybWF0LmJpdGFuZ2VudDsKICAgICAgICByZXN1bHQuY29sb3IgPSB2ZXJ0ZXhGb3JtYXQuY29sb3I7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgVmVydGV4Rm9ybWF0X2RlZmF1bHQgPSBWZXJ0ZXhGb3JtYXQ7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Cb3hHZW9tZXRyeS5qcwogIGZ1bmN0aW9uIEJveEdlb21ldHJ5KG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIGNvbnN0IG1pbjMgPSBvcHRpb25zLm1pbmltdW07CiAgICBjb25zdCBtYXgzID0gb3B0aW9ucy5tYXhpbXVtOwogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtaW4iLCBtaW4zKTsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF4IiwgbWF4Myk7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlKSAmJiBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5UT1ApIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgIkdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlLlRPUCBpcyBub3QgYSBzdXBwb3J0ZWQgb3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGUgZm9yIHRoaXMgZ2VvbWV0cnkuIgogICAgICApOwogICAgfQogICAgY29uc3QgdmVydGV4Rm9ybWF0ID0gb3B0aW9ucy52ZXJ0ZXhGb3JtYXQgPz8gVmVydGV4Rm9ybWF0X2RlZmF1bHQuREVGQVVMVDsKICAgIHRoaXMuX21pbmltdW0gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUobWluMyk7CiAgICB0aGlzLl9tYXhpbXVtID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKG1heDMpOwogICAgdGhpcy5fdmVydGV4Rm9ybWF0ID0gdmVydGV4Rm9ybWF0OwogICAgdGhpcy5fb2Zmc2V0QXR0cmlidXRlID0gb3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGU7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZUJveEdlb21ldHJ5IjsKICB9CiAgdmFyIGRpZmZTY3JhdGNoLCBzY3JhdGNoTWluLCBzY3JhdGNoTWF4LCBzY3JhdGNoVmVydGV4Rm9ybWF0LCBzY3JhdGNoT3B0aW9ucywgdW5pdEJveEdlb21ldHJ5LCBCb3hHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X0JveEdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Cb3hHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZXMoKTsKICAgICAgaW5pdF9HZW9tZXRyeU9mZnNldEF0dHJpYnV0ZSgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgaW5pdF9WZXJ0ZXhGb3JtYXQoKTsKICAgICAgZGlmZlNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIEJveEdlb21ldHJ5LmZyb21EaW1lbnNpb25zID0gZnVuY3Rpb24ob3B0aW9ucykgewogICAgICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgICAgICBjb25zdCBkaW1lbnNpb25zID0gb3B0aW9ucy5kaW1lbnNpb25zOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiZGltZW5zaW9ucyIsIGRpbWVuc2lvbnMpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJkaW1lbnNpb25zLngiLCBkaW1lbnNpb25zLngsIDApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJkaW1lbnNpb25zLnkiLCBkaW1lbnNpb25zLnksIDApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJkaW1lbnNpb25zLnoiLCBkaW1lbnNpb25zLnosIDApOwogICAgICAgIGNvbnN0IGNvcm5lciA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGRpbWVuc2lvbnMsIDAuNSwgbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpKTsKICAgICAgICByZXR1cm4gbmV3IEJveEdlb21ldHJ5KHsKICAgICAgICAgIG1pbmltdW06IENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoY29ybmVyLCBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCkpLAogICAgICAgICAgbWF4aW11bTogY29ybmVyLAogICAgICAgICAgdmVydGV4Rm9ybWF0OiBvcHRpb25zLnZlcnRleEZvcm1hdCwKICAgICAgICAgIG9mZnNldEF0dHJpYnV0ZTogb3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGUKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgQm94R2VvbWV0cnkuZnJvbUF4aXNBbGlnbmVkQm91bmRpbmdCb3ggPSBmdW5jdGlvbihib3VuZGluZ0JveCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiYm91bmRpbmdCb3giLCBib3VuZGluZ0JveCk7CiAgICAgICAgcmV0dXJuIG5ldyBCb3hHZW9tZXRyeSh7CiAgICAgICAgICBtaW5pbXVtOiBib3VuZGluZ0JveC5taW5pbXVtLAogICAgICAgICAgbWF4aW11bTogYm91bmRpbmdCb3gubWF4aW11bQogICAgICAgIH0pOwogICAgICB9OwogICAgICBCb3hHZW9tZXRyeS5wYWNrZWRMZW5ndGggPSAyICogQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCArIFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIDE7CiAgICAgIEJveEdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayh2YWx1ZS5fbWluaW11bSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKAogICAgICAgICAgdmFsdWUuX21heGltdW0sCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXggKyBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoCiAgICAgICAgKTsKICAgICAgICBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrKAogICAgICAgICAgdmFsdWUuX3ZlcnRleEZvcm1hdCwKICAgICAgICAgIGFycmF5LAogICAgICAgICAgc3RhcnRpbmdJbmRleCArIDIgKiBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoCiAgICAgICAgKTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4ICsgMiAqIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrZWRMZW5ndGhdID0gdmFsdWUuX29mZnNldEF0dHJpYnV0ZSA/PyAtMTsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hNaW4gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hNYXggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQgPSBuZXcgVmVydGV4Rm9ybWF0X2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE9wdGlvbnMgPSB7CiAgICAgICAgbWluaW11bTogc2NyYXRjaE1pbiwKICAgICAgICBtYXhpbXVtOiBzY3JhdGNoTWF4LAogICAgICAgIHZlcnRleEZvcm1hdDogc2NyYXRjaFZlcnRleEZvcm1hdCwKICAgICAgICBvZmZzZXRBdHRyaWJ1dGU6IHZvaWQgMAogICAgICB9OwogICAgICBCb3hHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGNvbnN0IG1pbjMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoTWluKTsKICAgICAgICBjb25zdCBtYXgzID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjaygKICAgICAgICAgIGFycmF5LAogICAgICAgICAgc3RhcnRpbmdJbmRleCArIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGgsCiAgICAgICAgICBzY3JhdGNoTWF4CiAgICAgICAgKTsKICAgICAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXggKyAyICogQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCwKICAgICAgICAgIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQKICAgICAgICApOwogICAgICAgIGNvbnN0IG9mZnNldEF0dHJpYnV0ZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXggKyAyICogQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCArIFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aF07CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgc2NyYXRjaE9wdGlvbnMub2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlID09PSAtMSA/IHZvaWQgMCA6IG9mZnNldEF0dHJpYnV0ZTsKICAgICAgICAgIHJldHVybiBuZXcgQm94R2VvbWV0cnkoc2NyYXRjaE9wdGlvbnMpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuX21pbmltdW0gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUobWluMywgcmVzdWx0Ll9taW5pbXVtKTsKICAgICAgICByZXN1bHQuX21heGltdW0gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUobWF4MywgcmVzdWx0Ll9tYXhpbXVtKTsKICAgICAgICByZXN1bHQuX3ZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LmNsb25lKHZlcnRleEZvcm1hdCwgcmVzdWx0Ll92ZXJ0ZXhGb3JtYXQpOwogICAgICAgIHJlc3VsdC5fb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlID09PSAtMSA/IHZvaWQgMCA6IG9mZnNldEF0dHJpYnV0ZTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBCb3hHZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKGJveEdlb21ldHJ5KSB7CiAgICAgICAgY29uc3QgbWluMyA9IGJveEdlb21ldHJ5Ll9taW5pbXVtOwogICAgICAgIGNvbnN0IG1heDMgPSBib3hHZW9tZXRyeS5fbWF4aW11bTsKICAgICAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBib3hHZW9tZXRyeS5fdmVydGV4Rm9ybWF0OwogICAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzKG1pbjMsIG1heDMpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoKTsKICAgICAgICBsZXQgaW5kaWNlczsKICAgICAgICBsZXQgcG9zaXRpb25zOwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQucG9zaXRpb24gJiYgKHZlcnRleEZvcm1hdC5zdCB8fCB2ZXJ0ZXhGb3JtYXQubm9ybWFsIHx8IHZlcnRleEZvcm1hdC50YW5nZW50IHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpKSB7CiAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnBvc2l0aW9uKSB7CiAgICAgICAgICAgIHBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkoNiAqIDQgKiAzKTsKICAgICAgICAgICAgcG9zaXRpb25zWzBdID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbMV0gPSBtaW4zLnk7CiAgICAgICAgICAgIHBvc2l0aW9uc1syXSA9IG1heDMuejsKICAgICAgICAgICAgcG9zaXRpb25zWzNdID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbNF0gPSBtaW4zLnk7CiAgICAgICAgICAgIHBvc2l0aW9uc1s1XSA9IG1heDMuejsKICAgICAgICAgICAgcG9zaXRpb25zWzZdID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbN10gPSBtYXgzLnk7CiAgICAgICAgICAgIHBvc2l0aW9uc1s4XSA9IG1heDMuejsKICAgICAgICAgICAgcG9zaXRpb25zWzldID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbMTBdID0gbWF4My55OwogICAgICAgICAgICBwb3NpdGlvbnNbMTFdID0gbWF4My56OwogICAgICAgICAgICBwb3NpdGlvbnNbMTJdID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbMTNdID0gbWluMy55OwogICAgICAgICAgICBwb3NpdGlvbnNbMTRdID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbMTVdID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbMTZdID0gbWluMy55OwogICAgICAgICAgICBwb3NpdGlvbnNbMTddID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbMThdID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbMTldID0gbWF4My55OwogICAgICAgICAgICBwb3NpdGlvbnNbMjBdID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbMjFdID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbMjJdID0gbWF4My55OwogICAgICAgICAgICBwb3NpdGlvbnNbMjNdID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbMjRdID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbMjVdID0gbWluMy55OwogICAgICAgICAgICBwb3NpdGlvbnNbMjZdID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbMjddID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbMjhdID0gbWF4My55OwogICAgICAgICAgICBwb3NpdGlvbnNbMjldID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbMzBdID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbMzFdID0gbWF4My55OwogICAgICAgICAgICBwb3NpdGlvbnNbMzJdID0gbWF4My56OwogICAgICAgICAgICBwb3NpdGlvbnNbMzNdID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbMzRdID0gbWluMy55OwogICAgICAgICAgICBwb3NpdGlvbnNbMzVdID0gbWF4My56OwogICAgICAgICAgICBwb3NpdGlvbnNbMzZdID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbMzddID0gbWluMy55OwogICAgICAgICAgICBwb3NpdGlvbnNbMzhdID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbMzldID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbNDBdID0gbWF4My55OwogICAgICAgICAgICBwb3NpdGlvbnNbNDFdID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbNDJdID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbNDNdID0gbWF4My55OwogICAgICAgICAgICBwb3NpdGlvbnNbNDRdID0gbWF4My56OwogICAgICAgICAgICBwb3NpdGlvbnNbNDVdID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbNDZdID0gbWluMy55OwogICAgICAgICAgICBwb3NpdGlvbnNbNDddID0gbWF4My56OwogICAgICAgICAgICBwb3NpdGlvbnNbNDhdID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbNDldID0gbWF4My55OwogICAgICAgICAgICBwb3NpdGlvbnNbNTBdID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbNTFdID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbNTJdID0gbWF4My55OwogICAgICAgICAgICBwb3NpdGlvbnNbNTNdID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbNTRdID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbNTVdID0gbWF4My55OwogICAgICAgICAgICBwb3NpdGlvbnNbNTZdID0gbWF4My56OwogICAgICAgICAgICBwb3NpdGlvbnNbNTddID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbNThdID0gbWF4My55OwogICAgICAgICAgICBwb3NpdGlvbnNbNTldID0gbWF4My56OwogICAgICAgICAgICBwb3NpdGlvbnNbNjBdID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbNjFdID0gbWluMy55OwogICAgICAgICAgICBwb3NpdGlvbnNbNjJdID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbNjNdID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbNjRdID0gbWluMy55OwogICAgICAgICAgICBwb3NpdGlvbnNbNjVdID0gbWluMy56OwogICAgICAgICAgICBwb3NpdGlvbnNbNjZdID0gbWF4My54OwogICAgICAgICAgICBwb3NpdGlvbnNbNjddID0gbWluMy55OwogICAgICAgICAgICBwb3NpdGlvbnNbNjhdID0gbWF4My56OwogICAgICAgICAgICBwb3NpdGlvbnNbNjldID0gbWluMy54OwogICAgICAgICAgICBwb3NpdGlvbnNbNzBdID0gbWluMy55OwogICAgICAgICAgICBwb3NpdGlvbnNbNzFdID0gbWF4My56OwogICAgICAgICAgICBhdHRyaWJ1dGVzLnBvc2l0aW9uID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgICAgIHZhbHVlczogcG9zaXRpb25zCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5ub3JtYWwpIHsKICAgICAgICAgICAgY29uc3Qgbm9ybWFscyA9IG5ldyBGbG9hdDMyQXJyYXkoNiAqIDQgKiAzKTsKICAgICAgICAgICAgbm9ybWFsc1swXSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMV0gPSAwOwogICAgICAgICAgICBub3JtYWxzWzJdID0gMTsKICAgICAgICAgICAgbm9ybWFsc1szXSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbNF0gPSAwOwogICAgICAgICAgICBub3JtYWxzWzVdID0gMTsKICAgICAgICAgICAgbm9ybWFsc1s2XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbN10gPSAwOwogICAgICAgICAgICBub3JtYWxzWzhdID0gMTsKICAgICAgICAgICAgbm9ybWFsc1s5XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMTBdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1sxMV0gPSAxOwogICAgICAgICAgICBub3JtYWxzWzEyXSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMTNdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1sxNF0gPSAtMTsKICAgICAgICAgICAgbm9ybWFsc1sxNV0gPSAwOwogICAgICAgICAgICBub3JtYWxzWzE2XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMTddID0gLTE7CiAgICAgICAgICAgIG5vcm1hbHNbMThdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1sxOV0gPSAwOwogICAgICAgICAgICBub3JtYWxzWzIwXSA9IC0xOwogICAgICAgICAgICBub3JtYWxzWzIxXSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMjJdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1syM10gPSAtMTsKICAgICAgICAgICAgbm9ybWFsc1syNF0gPSAxOwogICAgICAgICAgICBub3JtYWxzWzI1XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMjZdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1syN10gPSAxOwogICAgICAgICAgICBub3JtYWxzWzI4XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMjldID0gMDsKICAgICAgICAgICAgbm9ybWFsc1szMF0gPSAxOwogICAgICAgICAgICBub3JtYWxzWzMxXSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMzJdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1szM10gPSAxOwogICAgICAgICAgICBub3JtYWxzWzM0XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMzVdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1szNl0gPSAtMTsKICAgICAgICAgICAgbm9ybWFsc1szN10gPSAwOwogICAgICAgICAgICBub3JtYWxzWzM4XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMzldID0gLTE7CiAgICAgICAgICAgIG5vcm1hbHNbNDBdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1s0MV0gPSAwOwogICAgICAgICAgICBub3JtYWxzWzQyXSA9IC0xOwogICAgICAgICAgICBub3JtYWxzWzQzXSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbNDRdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1s0NV0gPSAtMTsKICAgICAgICAgICAgbm9ybWFsc1s0Nl0gPSAwOwogICAgICAgICAgICBub3JtYWxzWzQ3XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbNDhdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1s0OV0gPSAxOwogICAgICAgICAgICBub3JtYWxzWzUwXSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbNTFdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1s1Ml0gPSAxOwogICAgICAgICAgICBub3JtYWxzWzUzXSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbNTRdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1s1NV0gPSAxOwogICAgICAgICAgICBub3JtYWxzWzU2XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbNTddID0gMDsKICAgICAgICAgICAgbm9ybWFsc1s1OF0gPSAxOwogICAgICAgICAgICBub3JtYWxzWzU5XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbNjBdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1s2MV0gPSAtMTsKICAgICAgICAgICAgbm9ybWFsc1s2Ml0gPSAwOwogICAgICAgICAgICBub3JtYWxzWzYzXSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbNjRdID0gLTE7CiAgICAgICAgICAgIG5vcm1hbHNbNjVdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1s2Nl0gPSAwOwogICAgICAgICAgICBub3JtYWxzWzY3XSA9IC0xOwogICAgICAgICAgICBub3JtYWxzWzY4XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbNjldID0gMDsKICAgICAgICAgICAgbm9ybWFsc1s3MF0gPSAtMTsKICAgICAgICAgICAgbm9ybWFsc1s3MV0gPSAwOwogICAgICAgICAgICBhdHRyaWJ1dGVzLm5vcm1hbCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgICAgIHZhbHVlczogbm9ybWFscwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICAgICAgY29uc3QgdGV4Q29vcmRzID0gbmV3IEZsb2F0MzJBcnJheSg2ICogNCAqIDIpOwogICAgICAgICAgICB0ZXhDb29yZHNbMF0gPSAwOwogICAgICAgICAgICB0ZXhDb29yZHNbMV0gPSAwOwogICAgICAgICAgICB0ZXhDb29yZHNbMl0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbM10gPSAwOwogICAgICAgICAgICB0ZXhDb29yZHNbNF0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbNV0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbNl0gPSAwOwogICAgICAgICAgICB0ZXhDb29yZHNbN10gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbOF0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbOV0gPSAwOwogICAgICAgICAgICB0ZXhDb29yZHNbMTBdID0gMDsKICAgICAgICAgICAgdGV4Q29vcmRzWzExXSA9IDA7CiAgICAgICAgICAgIHRleENvb3Jkc1sxMl0gPSAwOwogICAgICAgICAgICB0ZXhDb29yZHNbMTNdID0gMTsKICAgICAgICAgICAgdGV4Q29vcmRzWzE0XSA9IDE7CiAgICAgICAgICAgIHRleENvb3Jkc1sxNV0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbMTZdID0gMDsKICAgICAgICAgICAgdGV4Q29vcmRzWzE3XSA9IDA7CiAgICAgICAgICAgIHRleENvb3Jkc1sxOF0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbMTldID0gMDsKICAgICAgICAgICAgdGV4Q29vcmRzWzIwXSA9IDE7CiAgICAgICAgICAgIHRleENvb3Jkc1syMV0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbMjJdID0gMDsKICAgICAgICAgICAgdGV4Q29vcmRzWzIzXSA9IDE7CiAgICAgICAgICAgIHRleENvb3Jkc1syNF0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbMjVdID0gMDsKICAgICAgICAgICAgdGV4Q29vcmRzWzI2XSA9IDA7CiAgICAgICAgICAgIHRleENvb3Jkc1syN10gPSAwOwogICAgICAgICAgICB0ZXhDb29yZHNbMjhdID0gMDsKICAgICAgICAgICAgdGV4Q29vcmRzWzI5XSA9IDE7CiAgICAgICAgICAgIHRleENvb3Jkc1szMF0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbMzFdID0gMTsKICAgICAgICAgICAgdGV4Q29vcmRzWzMyXSA9IDE7CiAgICAgICAgICAgIHRleENvb3Jkc1szM10gPSAwOwogICAgICAgICAgICB0ZXhDb29yZHNbMzRdID0gMDsKICAgICAgICAgICAgdGV4Q29vcmRzWzM1XSA9IDA7CiAgICAgICAgICAgIHRleENvb3Jkc1szNl0gPSAwOwogICAgICAgICAgICB0ZXhDb29yZHNbMzddID0gMTsKICAgICAgICAgICAgdGV4Q29vcmRzWzM4XSA9IDE7CiAgICAgICAgICAgIHRleENvb3Jkc1szOV0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbNDBdID0gMDsKICAgICAgICAgICAgdGV4Q29vcmRzWzQxXSA9IDA7CiAgICAgICAgICAgIHRleENvb3Jkc1s0Ml0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbNDNdID0gMDsKICAgICAgICAgICAgdGV4Q29vcmRzWzQ0XSA9IDE7CiAgICAgICAgICAgIHRleENvb3Jkc1s0NV0gPSAxOwogICAgICAgICAgICB0ZXhDb29yZHNbNDZdID0gMDsKICAgICAgICAgICAgdGV4Q29vcmRzWzQ3XSA9IDE7CiAgICAgICAgICAgIGF0dHJpYnV0ZXMuc3QgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMiwKICAgICAgICAgICAgICB2YWx1ZXM6IHRleENvb3JkcwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICAgICAgICBjb25zdCB0YW5nZW50cyA9IG5ldyBGbG9hdDMyQXJyYXkoNiAqIDQgKiAzKTsKICAgICAgICAgICAgdGFuZ2VudHNbMF0gPSAxOwogICAgICAgICAgICB0YW5nZW50c1sxXSA9IDA7CiAgICAgICAgICAgIHRhbmdlbnRzWzJdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbM10gPSAxOwogICAgICAgICAgICB0YW5nZW50c1s0XSA9IDA7CiAgICAgICAgICAgIHRhbmdlbnRzWzVdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbNl0gPSAxOwogICAgICAgICAgICB0YW5nZW50c1s3XSA9IDA7CiAgICAgICAgICAgIHRhbmdlbnRzWzhdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbOV0gPSAxOwogICAgICAgICAgICB0YW5nZW50c1sxMF0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1sxMV0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1sxMl0gPSAtMTsKICAgICAgICAgICAgdGFuZ2VudHNbMTNdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMTRdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMTVdID0gLTE7CiAgICAgICAgICAgIHRhbmdlbnRzWzE2XSA9IDA7CiAgICAgICAgICAgIHRhbmdlbnRzWzE3XSA9IDA7CiAgICAgICAgICAgIHRhbmdlbnRzWzE4XSA9IC0xOwogICAgICAgICAgICB0YW5nZW50c1sxOV0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1syMF0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1syMV0gPSAtMTsKICAgICAgICAgICAgdGFuZ2VudHNbMjJdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMjNdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMjRdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMjVdID0gMTsKICAgICAgICAgICAgdGFuZ2VudHNbMjZdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMjddID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMjhdID0gMTsKICAgICAgICAgICAgdGFuZ2VudHNbMjldID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMzBdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMzFdID0gMTsKICAgICAgICAgICAgdGFuZ2VudHNbMzJdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMzNdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMzRdID0gMTsKICAgICAgICAgICAgdGFuZ2VudHNbMzVdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMzZdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMzddID0gLTE7CiAgICAgICAgICAgIHRhbmdlbnRzWzM4XSA9IDA7CiAgICAgICAgICAgIHRhbmdlbnRzWzM5XSA9IDA7CiAgICAgICAgICAgIHRhbmdlbnRzWzQwXSA9IC0xOwogICAgICAgICAgICB0YW5nZW50c1s0MV0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s0Ml0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s0M10gPSAtMTsKICAgICAgICAgICAgdGFuZ2VudHNbNDRdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbNDVdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbNDZdID0gLTE7CiAgICAgICAgICAgIHRhbmdlbnRzWzQ3XSA9IDA7CiAgICAgICAgICAgIHRhbmdlbnRzWzQ4XSA9IC0xOwogICAgICAgICAgICB0YW5nZW50c1s0OV0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s1MF0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s1MV0gPSAtMTsKICAgICAgICAgICAgdGFuZ2VudHNbNTJdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbNTNdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbNTRdID0gLTE7CiAgICAgICAgICAgIHRhbmdlbnRzWzU1XSA9IDA7CiAgICAgICAgICAgIHRhbmdlbnRzWzU2XSA9IDA7CiAgICAgICAgICAgIHRhbmdlbnRzWzU3XSA9IC0xOwogICAgICAgICAgICB0YW5nZW50c1s1OF0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s1OV0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s2MF0gPSAxOwogICAgICAgICAgICB0YW5nZW50c1s2MV0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s2Ml0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s2M10gPSAxOwogICAgICAgICAgICB0YW5nZW50c1s2NF0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s2NV0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s2Nl0gPSAxOwogICAgICAgICAgICB0YW5nZW50c1s2N10gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s2OF0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s2OV0gPSAxOwogICAgICAgICAgICB0YW5nZW50c1s3MF0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s3MV0gPSAwOwogICAgICAgICAgICBhdHRyaWJ1dGVzLnRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgICB2YWx1ZXM6IHRhbmdlbnRzCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgICAgY29uc3QgYml0YW5nZW50cyA9IG5ldyBGbG9hdDMyQXJyYXkoNiAqIDQgKiAzKTsKICAgICAgICAgICAgYml0YW5nZW50c1swXSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMV0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzJdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1szXSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNF0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzVdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s2XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbN10gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzhdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s5XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMTBdID0gMTsKICAgICAgICAgICAgYml0YW5nZW50c1sxMV0gPSAwOwogICAgICAgICAgICBiaXRhbmdlbnRzWzEyXSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMTNdID0gMTsKICAgICAgICAgICAgYml0YW5nZW50c1sxNF0gPSAwOwogICAgICAgICAgICBiaXRhbmdlbnRzWzE1XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMTZdID0gMTsKICAgICAgICAgICAgYml0YW5nZW50c1sxN10gPSAwOwogICAgICAgICAgICBiaXRhbmdlbnRzWzE4XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMTldID0gMTsKICAgICAgICAgICAgYml0YW5nZW50c1syMF0gPSAwOwogICAgICAgICAgICBiaXRhbmdlbnRzWzIxXSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMjJdID0gMTsKICAgICAgICAgICAgYml0YW5nZW50c1syM10gPSAwOwogICAgICAgICAgICBiaXRhbmdlbnRzWzI0XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMjVdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1syNl0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzI3XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMjhdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1syOV0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzMwXSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMzFdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1szMl0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzMzXSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMzRdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1szNV0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzM2XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMzddID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1szOF0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzM5XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNDBdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s0MV0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzQyXSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNDNdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s0NF0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzQ1XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNDZdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s0N10gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzQ4XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNDldID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s1MF0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzUxXSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNTJdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s1M10gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzU0XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNTVdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s1Nl0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzU3XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNThdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s1OV0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzYwXSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNjFdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s2Ml0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzYzXSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNjRdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s2NV0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzY2XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNjddID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s2OF0gPSAxOwogICAgICAgICAgICBiaXRhbmdlbnRzWzY5XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNzBdID0gMDsKICAgICAgICAgICAgYml0YW5nZW50c1s3MV0gPSAxOwogICAgICAgICAgICBhdHRyaWJ1dGVzLmJpdGFuZ2VudCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgICAgIHZhbHVlczogYml0YW5nZW50cwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGluZGljZXMgPSBuZXcgVWludDE2QXJyYXkoNiAqIDIgKiAzKTsKICAgICAgICAgIGluZGljZXNbMF0gPSAwOwogICAgICAgICAgaW5kaWNlc1sxXSA9IDE7CiAgICAgICAgICBpbmRpY2VzWzJdID0gMjsKICAgICAgICAgIGluZGljZXNbM10gPSAwOwogICAgICAgICAgaW5kaWNlc1s0XSA9IDI7CiAgICAgICAgICBpbmRpY2VzWzVdID0gMzsKICAgICAgICAgIGluZGljZXNbNl0gPSA0ICsgMjsKICAgICAgICAgIGluZGljZXNbN10gPSA0ICsgMTsKICAgICAgICAgIGluZGljZXNbOF0gPSA0ICsgMDsKICAgICAgICAgIGluZGljZXNbOV0gPSA0ICsgMzsKICAgICAgICAgIGluZGljZXNbMTBdID0gNCArIDI7CiAgICAgICAgICBpbmRpY2VzWzExXSA9IDQgKyAwOwogICAgICAgICAgaW5kaWNlc1sxMl0gPSA4ICsgMDsKICAgICAgICAgIGluZGljZXNbMTNdID0gOCArIDE7CiAgICAgICAgICBpbmRpY2VzWzE0XSA9IDggKyAyOwogICAgICAgICAgaW5kaWNlc1sxNV0gPSA4ICsgMDsKICAgICAgICAgIGluZGljZXNbMTZdID0gOCArIDI7CiAgICAgICAgICBpbmRpY2VzWzE3XSA9IDggKyAzOwogICAgICAgICAgaW5kaWNlc1sxOF0gPSAxMiArIDI7CiAgICAgICAgICBpbmRpY2VzWzE5XSA9IDEyICsgMTsKICAgICAgICAgIGluZGljZXNbMjBdID0gMTIgKyAwOwogICAgICAgICAgaW5kaWNlc1syMV0gPSAxMiArIDM7CiAgICAgICAgICBpbmRpY2VzWzIyXSA9IDEyICsgMjsKICAgICAgICAgIGluZGljZXNbMjNdID0gMTIgKyAwOwogICAgICAgICAgaW5kaWNlc1syNF0gPSAxNiArIDI7CiAgICAgICAgICBpbmRpY2VzWzI1XSA9IDE2ICsgMTsKICAgICAgICAgIGluZGljZXNbMjZdID0gMTYgKyAwOwogICAgICAgICAgaW5kaWNlc1syN10gPSAxNiArIDM7CiAgICAgICAgICBpbmRpY2VzWzI4XSA9IDE2ICsgMjsKICAgICAgICAgIGluZGljZXNbMjldID0gMTYgKyAwOwogICAgICAgICAgaW5kaWNlc1szMF0gPSAyMCArIDA7CiAgICAgICAgICBpbmRpY2VzWzMxXSA9IDIwICsgMTsKICAgICAgICAgIGluZGljZXNbMzJdID0gMjAgKyAyOwogICAgICAgICAgaW5kaWNlc1szM10gPSAyMCArIDA7CiAgICAgICAgICBpbmRpY2VzWzM0XSA9IDIwICsgMjsKICAgICAgICAgIGluZGljZXNbMzVdID0gMjAgKyAzOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBwb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KDggKiAzKTsKICAgICAgICAgIHBvc2l0aW9uc1swXSA9IG1pbjMueDsKICAgICAgICAgIHBvc2l0aW9uc1sxXSA9IG1pbjMueTsKICAgICAgICAgIHBvc2l0aW9uc1syXSA9IG1pbjMuejsKICAgICAgICAgIHBvc2l0aW9uc1szXSA9IG1heDMueDsKICAgICAgICAgIHBvc2l0aW9uc1s0XSA9IG1pbjMueTsKICAgICAgICAgIHBvc2l0aW9uc1s1XSA9IG1pbjMuejsKICAgICAgICAgIHBvc2l0aW9uc1s2XSA9IG1heDMueDsKICAgICAgICAgIHBvc2l0aW9uc1s3XSA9IG1heDMueTsKICAgICAgICAgIHBvc2l0aW9uc1s4XSA9IG1pbjMuejsKICAgICAgICAgIHBvc2l0aW9uc1s5XSA9IG1pbjMueDsKICAgICAgICAgIHBvc2l0aW9uc1sxMF0gPSBtYXgzLnk7CiAgICAgICAgICBwb3NpdGlvbnNbMTFdID0gbWluMy56OwogICAgICAgICAgcG9zaXRpb25zWzEyXSA9IG1pbjMueDsKICAgICAgICAgIHBvc2l0aW9uc1sxM10gPSBtaW4zLnk7CiAgICAgICAgICBwb3NpdGlvbnNbMTRdID0gbWF4My56OwogICAgICAgICAgcG9zaXRpb25zWzE1XSA9IG1heDMueDsKICAgICAgICAgIHBvc2l0aW9uc1sxNl0gPSBtaW4zLnk7CiAgICAgICAgICBwb3NpdGlvbnNbMTddID0gbWF4My56OwogICAgICAgICAgcG9zaXRpb25zWzE4XSA9IG1heDMueDsKICAgICAgICAgIHBvc2l0aW9uc1sxOV0gPSBtYXgzLnk7CiAgICAgICAgICBwb3NpdGlvbnNbMjBdID0gbWF4My56OwogICAgICAgICAgcG9zaXRpb25zWzIxXSA9IG1pbjMueDsKICAgICAgICAgIHBvc2l0aW9uc1syMl0gPSBtYXgzLnk7CiAgICAgICAgICBwb3NpdGlvbnNbMjNdID0gbWF4My56OwogICAgICAgICAgYXR0cmlidXRlcy5wb3NpdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFLAogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgICB2YWx1ZXM6IHBvc2l0aW9ucwogICAgICAgICAgfSk7CiAgICAgICAgICBpbmRpY2VzID0gbmV3IFVpbnQxNkFycmF5KDYgKiAyICogMyk7CiAgICAgICAgICBpbmRpY2VzWzBdID0gNDsKICAgICAgICAgIGluZGljZXNbMV0gPSA1OwogICAgICAgICAgaW5kaWNlc1syXSA9IDY7CiAgICAgICAgICBpbmRpY2VzWzNdID0gNDsKICAgICAgICAgIGluZGljZXNbNF0gPSA2OwogICAgICAgICAgaW5kaWNlc1s1XSA9IDc7CiAgICAgICAgICBpbmRpY2VzWzZdID0gMTsKICAgICAgICAgIGluZGljZXNbN10gPSAwOwogICAgICAgICAgaW5kaWNlc1s4XSA9IDM7CiAgICAgICAgICBpbmRpY2VzWzldID0gMTsKICAgICAgICAgIGluZGljZXNbMTBdID0gMzsKICAgICAgICAgIGluZGljZXNbMTFdID0gMjsKICAgICAgICAgIGluZGljZXNbMTJdID0gMTsKICAgICAgICAgIGluZGljZXNbMTNdID0gNjsKICAgICAgICAgIGluZGljZXNbMTRdID0gNTsKICAgICAgICAgIGluZGljZXNbMTVdID0gMTsKICAgICAgICAgIGluZGljZXNbMTZdID0gMjsKICAgICAgICAgIGluZGljZXNbMTddID0gNjsKICAgICAgICAgIGluZGljZXNbMThdID0gMjsKICAgICAgICAgIGluZGljZXNbMTldID0gMzsKICAgICAgICAgIGluZGljZXNbMjBdID0gNzsKICAgICAgICAgIGluZGljZXNbMjFdID0gMjsKICAgICAgICAgIGluZGljZXNbMjJdID0gNzsKICAgICAgICAgIGluZGljZXNbMjNdID0gNjsKICAgICAgICAgIGluZGljZXNbMjRdID0gMzsKICAgICAgICAgIGluZGljZXNbMjVdID0gMDsKICAgICAgICAgIGluZGljZXNbMjZdID0gNDsKICAgICAgICAgIGluZGljZXNbMjddID0gMzsKICAgICAgICAgIGluZGljZXNbMjhdID0gNDsKICAgICAgICAgIGluZGljZXNbMjldID0gNzsKICAgICAgICAgIGluZGljZXNbMzBdID0gMDsKICAgICAgICAgIGluZGljZXNbMzFdID0gMTsKICAgICAgICAgIGluZGljZXNbMzJdID0gNTsKICAgICAgICAgIGluZGljZXNbMzNdID0gMDsKICAgICAgICAgIGluZGljZXNbMzRdID0gNTsKICAgICAgICAgIGluZGljZXNbMzVdID0gNDsKICAgICAgICB9CiAgICAgICAgY29uc3QgZGlmZiA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChtYXgzLCBtaW4zLCBkaWZmU2NyYXRjaCk7CiAgICAgICAgY29uc3QgcmFkaXVzID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZShkaWZmKSAqIDAuNTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGJveEdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUpKSB7CiAgICAgICAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgICAgICAgY29uc3Qgb2Zmc2V0VmFsdWUgPSBib3hHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlID09PSBHZW9tZXRyeU9mZnNldEF0dHJpYnV0ZV9kZWZhdWx0Lk5PTkUgPyAwIDogMTsKICAgICAgICAgIGNvbnN0IGFwcGx5T2Zmc2V0ID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoIC8gMykuZmlsbChvZmZzZXRWYWx1ZSk7CiAgICAgICAgICBhdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9CWVRFLAogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAxLAogICAgICAgICAgICB2YWx1ZXM6IGFwcGx5T2Zmc2V0CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgICAgIGF0dHJpYnV0ZXMsCiAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUywKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlOiBuZXcgQm91bmRpbmdTcGhlcmVfZGVmYXVsdChDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywgcmFkaXVzKSwKICAgICAgICAgIG9mZnNldEF0dHJpYnV0ZTogYm94R2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZQogICAgICAgIH0pOwogICAgICB9OwogICAgICBCb3hHZW9tZXRyeS5nZXRVbml0Qm94ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQodW5pdEJveEdlb21ldHJ5KSkgewogICAgICAgICAgdW5pdEJveEdlb21ldHJ5ID0gQm94R2VvbWV0cnkuY3JlYXRlR2VvbWV0cnkoCiAgICAgICAgICAgIEJveEdlb21ldHJ5LmZyb21EaW1lbnNpb25zKHsKICAgICAgICAgICAgICBkaW1lbnNpb25zOiBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KDEsIDEsIDEpLAogICAgICAgICAgICAgIHZlcnRleEZvcm1hdDogVmVydGV4Rm9ybWF0X2RlZmF1bHQuUE9TSVRJT05fT05MWQogICAgICAgICAgICB9KQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHVuaXRCb3hHZW9tZXRyeTsKICAgICAgfTsKICAgICAgQm94R2VvbWV0cnlfZGVmYXVsdCA9IEJveEdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlQm94R2VvbWV0cnkuanMKICB2YXIgY3JlYXRlQm94R2VvbWV0cnlfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZUJveEdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZUJveEdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVCb3hHZW9tZXRyeShib3hHZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgYm94R2VvbWV0cnkgPSBCb3hHZW9tZXRyeV9kZWZhdWx0LnVucGFjayhib3hHZW9tZXRyeSwgb2Zmc2V0KTsKICAgIH0KICAgIHJldHVybiBCb3hHZW9tZXRyeV9kZWZhdWx0LmNyZWF0ZUdlb21ldHJ5KGJveEdlb21ldHJ5KTsKICB9CiAgdmFyIGNyZWF0ZUJveEdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlQm94R2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUJveEdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9Cb3hHZW9tZXRyeSgpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgY3JlYXRlQm94R2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZUJveEdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQm94T3V0bGluZUdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gQm94T3V0bGluZUdlb21ldHJ5KG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIGNvbnN0IG1pbjMgPSBvcHRpb25zLm1pbmltdW07CiAgICBjb25zdCBtYXgzID0gb3B0aW9ucy5tYXhpbXVtOwogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJtaW4iLCBtaW4zKTsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibWF4IiwgbWF4Myk7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlKSAmJiBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5UT1ApIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgIkdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlLlRPUCBpcyBub3QgYSBzdXBwb3J0ZWQgb3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGUgZm9yIHRoaXMgZ2VvbWV0cnkuIgogICAgICApOwogICAgfQogICAgdGhpcy5fbWluID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKG1pbjMpOwogICAgdGhpcy5fbWF4ID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKG1heDMpOwogICAgdGhpcy5fb2Zmc2V0QXR0cmlidXRlID0gb3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGU7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZUJveE91dGxpbmVHZW9tZXRyeSI7CiAgfQogIHZhciBkaWZmU2NyYXRjaDIsIHNjcmF0Y2hNaW4yLCBzY3JhdGNoTWF4Miwgc2NyYXRjaE9wdGlvbnMyLCBCb3hPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9Cb3hPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0JveE91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZXMoKTsKICAgICAgaW5pdF9HZW9tZXRyeU9mZnNldEF0dHJpYnV0ZSgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgZGlmZlNjcmF0Y2gyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBCb3hPdXRsaW5lR2VvbWV0cnkuZnJvbURpbWVuc2lvbnMgPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgICAgIGNvbnN0IGRpbWVuc2lvbnMgPSBvcHRpb25zLmRpbWVuc2lvbnM7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJkaW1lbnNpb25zIiwgZGltZW5zaW9ucyk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoImRpbWVuc2lvbnMueCIsIGRpbWVuc2lvbnMueCwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoImRpbWVuc2lvbnMueSIsIGRpbWVuc2lvbnMueSwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoImRpbWVuc2lvbnMueiIsIGRpbWVuc2lvbnMueiwgMCk7CiAgICAgICAgY29uc3QgY29ybmVyID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoZGltZW5zaW9ucywgMC41LCBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCkpOwogICAgICAgIHJldHVybiBuZXcgQm94T3V0bGluZUdlb21ldHJ5KHsKICAgICAgICAgIG1pbmltdW06IENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoY29ybmVyLCBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCkpLAogICAgICAgICAgbWF4aW11bTogY29ybmVyLAogICAgICAgICAgb2Zmc2V0QXR0cmlidXRlOiBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZQogICAgICAgIH0pOwogICAgICB9OwogICAgICBCb3hPdXRsaW5lR2VvbWV0cnkuZnJvbUF4aXNBbGlnbmVkQm91bmRpbmdCb3ggPSBmdW5jdGlvbihib3VuZGluZ0JveCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiYm91bmRpbmRCb3giLCBib3VuZGluZ0JveCk7CiAgICAgICAgcmV0dXJuIG5ldyBCb3hPdXRsaW5lR2VvbWV0cnkoewogICAgICAgICAgbWluaW11bTogYm91bmRpbmdCb3gubWluaW11bSwKICAgICAgICAgIG1heGltdW06IGJvdW5kaW5nQm94Lm1heGltdW0KICAgICAgICB9KTsKICAgICAgfTsKICAgICAgQm94T3V0bGluZUdlb21ldHJ5LnBhY2tlZExlbmd0aCA9IDIgKiBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoICsgMTsKICAgICAgQm94T3V0bGluZUdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayh2YWx1ZS5fbWluLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2sodmFsdWUuX21heCwgYXJyYXksIHN0YXJ0aW5nSW5kZXggKyBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoKTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4ICsgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCAqIDJdID0gdmFsdWUuX29mZnNldEF0dHJpYnV0ZSA/PyAtMTsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hNaW4yID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoTWF4MiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE9wdGlvbnMyID0gewogICAgICAgIG1pbmltdW06IHNjcmF0Y2hNaW4yLAogICAgICAgIG1heGltdW06IHNjcmF0Y2hNYXgyLAogICAgICAgIG9mZnNldEF0dHJpYnV0ZTogdm9pZCAwCiAgICAgIH07CiAgICAgIEJveE91dGxpbmVHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGNvbnN0IG1pbjMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoTWluMik7CiAgICAgICAgY29uc3QgbWF4MyA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXggKyBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoLAogICAgICAgICAgc2NyYXRjaE1heDIKICAgICAgICApOwogICAgICAgIGNvbnN0IG9mZnNldEF0dHJpYnV0ZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXggKyBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoICogMl07CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgc2NyYXRjaE9wdGlvbnMyLm9mZnNldEF0dHJpYnV0ZSA9IG9mZnNldEF0dHJpYnV0ZSA9PT0gLTEgPyB2b2lkIDAgOiBvZmZzZXRBdHRyaWJ1dGU7CiAgICAgICAgICByZXR1cm4gbmV3IEJveE91dGxpbmVHZW9tZXRyeShzY3JhdGNoT3B0aW9uczIpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuX21pbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShtaW4zLCByZXN1bHQuX21pbik7CiAgICAgICAgcmVzdWx0Ll9tYXggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUobWF4MywgcmVzdWx0Ll9tYXgpOwogICAgICAgIHJlc3VsdC5fb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlID09PSAtMSA/IHZvaWQgMCA6IG9mZnNldEF0dHJpYnV0ZTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBCb3hPdXRsaW5lR2VvbWV0cnkuY3JlYXRlR2VvbWV0cnkgPSBmdW5jdGlvbihib3hHZW9tZXRyeSkgewogICAgICAgIGNvbnN0IG1pbjMgPSBib3hHZW9tZXRyeS5fbWluOwogICAgICAgIGNvbnN0IG1heDMgPSBib3hHZW9tZXRyeS5fbWF4OwogICAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzKG1pbjMsIG1heDMpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoKTsKICAgICAgICBjb25zdCBpbmRpY2VzID0gbmV3IFVpbnQxNkFycmF5KDEyICogMik7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheSg4ICogMyk7CiAgICAgICAgcG9zaXRpb25zWzBdID0gbWluMy54OwogICAgICAgIHBvc2l0aW9uc1sxXSA9IG1pbjMueTsKICAgICAgICBwb3NpdGlvbnNbMl0gPSBtaW4zLno7CiAgICAgICAgcG9zaXRpb25zWzNdID0gbWF4My54OwogICAgICAgIHBvc2l0aW9uc1s0XSA9IG1pbjMueTsKICAgICAgICBwb3NpdGlvbnNbNV0gPSBtaW4zLno7CiAgICAgICAgcG9zaXRpb25zWzZdID0gbWF4My54OwogICAgICAgIHBvc2l0aW9uc1s3XSA9IG1heDMueTsKICAgICAgICBwb3NpdGlvbnNbOF0gPSBtaW4zLno7CiAgICAgICAgcG9zaXRpb25zWzldID0gbWluMy54OwogICAgICAgIHBvc2l0aW9uc1sxMF0gPSBtYXgzLnk7CiAgICAgICAgcG9zaXRpb25zWzExXSA9IG1pbjMuejsKICAgICAgICBwb3NpdGlvbnNbMTJdID0gbWluMy54OwogICAgICAgIHBvc2l0aW9uc1sxM10gPSBtaW4zLnk7CiAgICAgICAgcG9zaXRpb25zWzE0XSA9IG1heDMuejsKICAgICAgICBwb3NpdGlvbnNbMTVdID0gbWF4My54OwogICAgICAgIHBvc2l0aW9uc1sxNl0gPSBtaW4zLnk7CiAgICAgICAgcG9zaXRpb25zWzE3XSA9IG1heDMuejsKICAgICAgICBwb3NpdGlvbnNbMThdID0gbWF4My54OwogICAgICAgIHBvc2l0aW9uc1sxOV0gPSBtYXgzLnk7CiAgICAgICAgcG9zaXRpb25zWzIwXSA9IG1heDMuejsKICAgICAgICBwb3NpdGlvbnNbMjFdID0gbWluMy54OwogICAgICAgIHBvc2l0aW9uc1syMl0gPSBtYXgzLnk7CiAgICAgICAgcG9zaXRpb25zWzIzXSA9IG1heDMuejsKICAgICAgICBhdHRyaWJ1dGVzLnBvc2l0aW9uID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFLAogICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgIHZhbHVlczogcG9zaXRpb25zCiAgICAgICAgfSk7CiAgICAgICAgaW5kaWNlc1swXSA9IDQ7CiAgICAgICAgaW5kaWNlc1sxXSA9IDU7CiAgICAgICAgaW5kaWNlc1syXSA9IDU7CiAgICAgICAgaW5kaWNlc1szXSA9IDY7CiAgICAgICAgaW5kaWNlc1s0XSA9IDY7CiAgICAgICAgaW5kaWNlc1s1XSA9IDc7CiAgICAgICAgaW5kaWNlc1s2XSA9IDc7CiAgICAgICAgaW5kaWNlc1s3XSA9IDQ7CiAgICAgICAgaW5kaWNlc1s4XSA9IDA7CiAgICAgICAgaW5kaWNlc1s5XSA9IDE7CiAgICAgICAgaW5kaWNlc1sxMF0gPSAxOwogICAgICAgIGluZGljZXNbMTFdID0gMjsKICAgICAgICBpbmRpY2VzWzEyXSA9IDI7CiAgICAgICAgaW5kaWNlc1sxM10gPSAzOwogICAgICAgIGluZGljZXNbMTRdID0gMzsKICAgICAgICBpbmRpY2VzWzE1XSA9IDA7CiAgICAgICAgaW5kaWNlc1sxNl0gPSAwOwogICAgICAgIGluZGljZXNbMTddID0gNDsKICAgICAgICBpbmRpY2VzWzE4XSA9IDE7CiAgICAgICAgaW5kaWNlc1sxOV0gPSA1OwogICAgICAgIGluZGljZXNbMjBdID0gMjsKICAgICAgICBpbmRpY2VzWzIxXSA9IDY7CiAgICAgICAgaW5kaWNlc1syMl0gPSAzOwogICAgICAgIGluZGljZXNbMjNdID0gNzsKICAgICAgICBjb25zdCBkaWZmID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KG1heDMsIG1pbjMsIGRpZmZTY3JhdGNoMik7CiAgICAgICAgY29uc3QgcmFkaXVzID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZShkaWZmKSAqIDAuNTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGJveEdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUpKSB7CiAgICAgICAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgICAgICAgY29uc3Qgb2Zmc2V0VmFsdWUgPSBib3hHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlID09PSBHZW9tZXRyeU9mZnNldEF0dHJpYnV0ZV9kZWZhdWx0Lk5PTkUgPyAwIDogMTsKICAgICAgICAgIGNvbnN0IGFwcGx5T2Zmc2V0ID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoIC8gMykuZmlsbChvZmZzZXRWYWx1ZSk7CiAgICAgICAgICBhdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9CWVRFLAogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAxLAogICAgICAgICAgICB2YWx1ZXM6IGFwcGx5T2Zmc2V0CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgICAgIGF0dHJpYnV0ZXMsCiAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LkxJTkVTLAogICAgICAgICAgYm91bmRpbmdTcGhlcmU6IG5ldyBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0KENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLCByYWRpdXMpLAogICAgICAgICAgb2Zmc2V0QXR0cmlidXRlOiBib3hHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIEJveE91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gQm94T3V0bGluZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlQm94T3V0bGluZUdlb21ldHJ5LmpzCiAgdmFyIGNyZWF0ZUJveE91dGxpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlQm94T3V0bGluZUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZUJveE91dGxpbmVHZW9tZXRyeV9kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gY3JlYXRlQm94T3V0bGluZUdlb21ldHJ5KGJveEdlb21ldHJ5LCBvZmZzZXQpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob2Zmc2V0KSkgewogICAgICBib3hHZW9tZXRyeSA9IEJveE91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjayhib3hHZW9tZXRyeSwgb2Zmc2V0KTsKICAgIH0KICAgIHJldHVybiBCb3hPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeShib3hHZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVCb3hPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVCb3hPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUJveE91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQm94T3V0bGluZUdlb21ldHJ5KCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBjcmVhdGVCb3hPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZUJveE91dGxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0VsbGlwc2VHZW9tZXRyeUxpYnJhcnkuanMKICBmdW5jdGlvbiBwb2ludE9uRWxsaXBzb2lkKHRoZXRhLCByb3RhdGlvbiwgbm9ydGhWZWMsIGVhc3RWZWMsIGFTcXIsIGFiLCBiU3FyLCBtYWcsIHVuaXRQb3MsIHJlc3VsdCkgewogICAgY29uc3QgYXppbXV0aCA9IHRoZXRhICsgcm90YXRpb247CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihlYXN0VmVjLCBNYXRoLmNvcyhhemltdXRoKSwgcm90QXhpcyk7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihub3J0aFZlYywgTWF0aC5zaW4oYXppbXV0aCksIHRlbXBWZWMpOwogICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChyb3RBeGlzLCB0ZW1wVmVjLCByb3RBeGlzKTsKICAgIGxldCBjb3NUaGV0YVNxdWFyZWQgPSBNYXRoLmNvcyh0aGV0YSk7CiAgICBjb3NUaGV0YVNxdWFyZWQgPSBjb3NUaGV0YVNxdWFyZWQgKiBjb3NUaGV0YVNxdWFyZWQ7CiAgICBsZXQgc2luVGhldGFTcXVhcmVkID0gTWF0aC5zaW4odGhldGEpOwogICAgc2luVGhldGFTcXVhcmVkID0gc2luVGhldGFTcXVhcmVkICogc2luVGhldGFTcXVhcmVkOwogICAgY29uc3QgcmFkaXVzID0gYWIgLyBNYXRoLnNxcnQoYlNxciAqIGNvc1RoZXRhU3F1YXJlZCArIGFTcXIgKiBzaW5UaGV0YVNxdWFyZWQpOwogICAgY29uc3QgYW5nbGUgPSByYWRpdXMgLyBtYWc7CiAgICBRdWF0ZXJuaW9uX2RlZmF1bHQuZnJvbUF4aXNBbmdsZShyb3RBeGlzLCBhbmdsZSwgdW5pdFF1YXQpOwogICAgTWF0cml4M19kZWZhdWx0LmZyb21RdWF0ZXJuaW9uKHVuaXRRdWF0LCByb3RNdHgpOwogICAgTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3Iocm90TXR4LCB1bml0UG9zLCByZXN1bHQpOwogICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShyZXN1bHQsIHJlc3VsdCk7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihyZXN1bHQsIG1hZywgcmVzdWx0KTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQogIHZhciBFbGxpcHNlR2VvbWV0cnlMaWJyYXJ5LCByb3RBeGlzLCB0ZW1wVmVjLCB1bml0UXVhdCwgcm90TXR4LCBzY3JhdGNoQ2FydGVzaWFuMTIsIHNjcmF0Y2hDYXJ0ZXNpYW4yMywgc2NyYXRjaENhcnRlc2lhbjM0LCBzY3JhdGNoTm9ybWFsMiwgdW5pdFBvc1NjcmF0Y2gsIGVhc3RWZWNTY3JhdGNoLCBub3J0aFZlY1NjcmF0Y2gsIEVsbGlwc2VHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdDsKICB2YXIgaW5pdF9FbGxpcHNlR2VvbWV0cnlMaWJyYXJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9FbGxpcHNlR2VvbWV0cnlMaWJyYXJ5LmpzIigpIHsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X01hdHJpeDMoKTsKICAgICAgaW5pdF9RdWF0ZXJuaW9uKCk7CiAgICAgIEVsbGlwc2VHZW9tZXRyeUxpYnJhcnkgPSB7fTsKICAgICAgcm90QXhpcyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgdGVtcFZlYyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgdW5pdFF1YXQgPSBuZXcgUXVhdGVybmlvbl9kZWZhdWx0KCk7CiAgICAgIHJvdE10eCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjEyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydGVzaWFuMjMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4zNCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE5vcm1hbDIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIEVsbGlwc2VHZW9tZXRyeUxpYnJhcnkucmFpc2VQb3NpdGlvbnNUb0hlaWdodCA9IGZ1bmN0aW9uKHBvc2l0aW9ucywgb3B0aW9ucywgZXh0cnVkZSkgewogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IG9wdGlvbnMuZWxsaXBzb2lkOwogICAgICAgIGNvbnN0IGhlaWdodCA9IG9wdGlvbnMuaGVpZ2h0OwogICAgICAgIGNvbnN0IGV4dHJ1ZGVkSGVpZ2h0ID0gb3B0aW9ucy5leHRydWRlZEhlaWdodDsKICAgICAgICBjb25zdCBzaXplID0gZXh0cnVkZSA/IHBvc2l0aW9ucy5sZW5ndGggLyAzICogMiA6IHBvc2l0aW9ucy5sZW5ndGggLyAzOwogICAgICAgIGNvbnN0IGZpbmFsUG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShzaXplICogMyk7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBjb25zdCBib3R0b21PZmZzZXQgPSBleHRydWRlID8gbGVuZ3RoIDogMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAzKSB7CiAgICAgICAgICBjb25zdCBpMSA9IGkgKyAxOwogICAgICAgICAgY29uc3QgaTIgPSBpICsgMjsKICAgICAgICAgIGNvbnN0IHBvc2l0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIGksIHNjcmF0Y2hDYXJ0ZXNpYW4xMik7CiAgICAgICAgICBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZShwb3NpdGlvbiwgcG9zaXRpb24pOwogICAgICAgICAgY29uc3QgZXh0cnVkZWRQb3NpdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShwb3NpdGlvbiwgc2NyYXRjaENhcnRlc2lhbjIzKTsKICAgICAgICAgIGNvbnN0IG5vcm1hbDIgPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKHBvc2l0aW9uLCBzY3JhdGNoTm9ybWFsMik7CiAgICAgICAgICBjb25zdCBzY2FsZWROb3JtYWwgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICAgICAgbm9ybWFsMiwKICAgICAgICAgICAgaGVpZ2h0LAogICAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuMzQKICAgICAgICAgICk7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHBvc2l0aW9uLCBzY2FsZWROb3JtYWwsIHBvc2l0aW9uKTsKICAgICAgICAgIGlmIChleHRydWRlKSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKG5vcm1hbDIsIGV4dHJ1ZGVkSGVpZ2h0LCBzY2FsZWROb3JtYWwpOwogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGV4dHJ1ZGVkUG9zaXRpb24sIHNjYWxlZE5vcm1hbCwgZXh0cnVkZWRQb3NpdGlvbik7CiAgICAgICAgICAgIGZpbmFsUG9zaXRpb25zW2kgKyBib3R0b21PZmZzZXRdID0gZXh0cnVkZWRQb3NpdGlvbi54OwogICAgICAgICAgICBmaW5hbFBvc2l0aW9uc1tpMSArIGJvdHRvbU9mZnNldF0gPSBleHRydWRlZFBvc2l0aW9uLnk7CiAgICAgICAgICAgIGZpbmFsUG9zaXRpb25zW2kyICsgYm90dG9tT2Zmc2V0XSA9IGV4dHJ1ZGVkUG9zaXRpb24uejsKICAgICAgICAgIH0KICAgICAgICAgIGZpbmFsUG9zaXRpb25zW2ldID0gcG9zaXRpb24ueDsKICAgICAgICAgIGZpbmFsUG9zaXRpb25zW2kxXSA9IHBvc2l0aW9uLnk7CiAgICAgICAgICBmaW5hbFBvc2l0aW9uc1tpMl0gPSBwb3NpdGlvbi56OwogICAgICAgIH0KICAgICAgICByZXR1cm4gZmluYWxQb3NpdGlvbnM7CiAgICAgIH07CiAgICAgIHVuaXRQb3NTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBlYXN0VmVjU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgbm9ydGhWZWNTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBFbGxpcHNlR2VvbWV0cnlMaWJyYXJ5LmNvbXB1dGVFbGxpcHNlUG9zaXRpb25zID0gZnVuY3Rpb24ob3B0aW9ucywgYWRkRmlsbFBvc2l0aW9ucywgYWRkRWRnZVBvc2l0aW9ucykgewogICAgICAgIGNvbnN0IHNlbWlNaW5vckF4aXMgPSBvcHRpb25zLnNlbWlNaW5vckF4aXM7CiAgICAgICAgY29uc3Qgc2VtaU1ham9yQXhpcyA9IG9wdGlvbnMuc2VtaU1ham9yQXhpczsKICAgICAgICBjb25zdCByb3RhdGlvbiA9IG9wdGlvbnMucm90YXRpb247CiAgICAgICAgY29uc3QgY2VudGVyID0gb3B0aW9ucy5jZW50ZXI7CiAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBvcHRpb25zLmdyYW51bGFyaXR5ICogODsKICAgICAgICBjb25zdCBhU3FyID0gc2VtaU1pbm9yQXhpcyAqIHNlbWlNaW5vckF4aXM7CiAgICAgICAgY29uc3QgYlNxciA9IHNlbWlNYWpvckF4aXMgKiBzZW1pTWFqb3JBeGlzOwogICAgICAgIGNvbnN0IGFiID0gc2VtaU1ham9yQXhpcyAqIHNlbWlNaW5vckF4aXM7CiAgICAgICAgY29uc3QgbWFnID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZShjZW50ZXIpOwogICAgICAgIGNvbnN0IHVuaXRQb3MgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGNlbnRlciwgdW5pdFBvc1NjcmF0Y2gpOwogICAgICAgIGxldCBlYXN0VmVjID0gQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1osIGNlbnRlciwgZWFzdFZlY1NjcmF0Y2gpOwogICAgICAgIGVhc3RWZWMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGVhc3RWZWMsIGVhc3RWZWMpOwogICAgICAgIGNvbnN0IG5vcnRoVmVjID0gQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKHVuaXRQb3MsIGVhc3RWZWMsIG5vcnRoVmVjU2NyYXRjaCk7CiAgICAgICAgbGV0IG51bVB0cyA9IDEgKyBNYXRoLmNlaWwoTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPIC8gZ3JhbnVsYXJpdHkpOwogICAgICAgIGNvbnN0IGRlbHRhVGhldGEgPSBNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08gLyAobnVtUHRzIC0gMSk7CiAgICAgICAgbGV0IHRoZXRhID0gTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPIC0gbnVtUHRzICogZGVsdGFUaGV0YTsKICAgICAgICBpZiAodGhldGEgPCAwKSB7CiAgICAgICAgICBudW1QdHMgLT0gTWF0aC5jZWlsKE1hdGguYWJzKHRoZXRhKSAvIGRlbHRhVGhldGEpOwogICAgICAgIH0KICAgICAgICBjb25zdCBzaXplID0gMiAqIChudW1QdHMgKiAobnVtUHRzICsgMikpOwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IGFkZEZpbGxQb3NpdGlvbnMgPyBuZXcgQXJyYXkoc2l6ZSAqIDMpIDogdm9pZCAwOwogICAgICAgIGxldCBwb3NpdGlvbkluZGV4ID0gMDsKICAgICAgICBsZXQgcG9zaXRpb24gPSBzY3JhdGNoQ2FydGVzaWFuMTI7CiAgICAgICAgbGV0IHJlZmxlY3RlZFBvc2l0aW9uID0gc2NyYXRjaENhcnRlc2lhbjIzOwogICAgICAgIGNvbnN0IG91dGVyUG9zaXRpb25zTGVuZ3RoID0gbnVtUHRzICogNCAqIDM7CiAgICAgICAgbGV0IG91dGVyUmlnaHRJbmRleCA9IG91dGVyUG9zaXRpb25zTGVuZ3RoIC0gMTsKICAgICAgICBsZXQgb3V0ZXJMZWZ0SW5kZXggPSAwOwogICAgICAgIGNvbnN0IG91dGVyUG9zaXRpb25zID0gYWRkRWRnZVBvc2l0aW9ucyA/IG5ldyBBcnJheShvdXRlclBvc2l0aW9uc0xlbmd0aCkgOiB2b2lkIDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgbGV0IGo7CiAgICAgICAgbGV0IG51bUludGVyaW9yOwogICAgICAgIGxldCB0OwogICAgICAgIGxldCBpbnRlcmlvclBvc2l0aW9uOwogICAgICAgIHRoZXRhID0gTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPOwogICAgICAgIHBvc2l0aW9uID0gcG9pbnRPbkVsbGlwc29pZCgKICAgICAgICAgIHRoZXRhLAogICAgICAgICAgcm90YXRpb24sCiAgICAgICAgICBub3J0aFZlYywKICAgICAgICAgIGVhc3RWZWMsCiAgICAgICAgICBhU3FyLAogICAgICAgICAgYWIsCiAgICAgICAgICBiU3FyLAogICAgICAgICAgbWFnLAogICAgICAgICAgdW5pdFBvcywKICAgICAgICAgIHBvc2l0aW9uCiAgICAgICAgKTsKICAgICAgICBpZiAoYWRkRmlsbFBvc2l0aW9ucykgewogICAgICAgICAgcG9zaXRpb25zW3Bvc2l0aW9uSW5kZXgrK10gPSBwb3NpdGlvbi54OwogICAgICAgICAgcG9zaXRpb25zW3Bvc2l0aW9uSW5kZXgrK10gPSBwb3NpdGlvbi55OwogICAgICAgICAgcG9zaXRpb25zW3Bvc2l0aW9uSW5kZXgrK10gPSBwb3NpdGlvbi56OwogICAgICAgIH0KICAgICAgICBpZiAoYWRkRWRnZVBvc2l0aW9ucykgewogICAgICAgICAgb3V0ZXJQb3NpdGlvbnNbb3V0ZXJSaWdodEluZGV4LS1dID0gcG9zaXRpb24uejsKICAgICAgICAgIG91dGVyUG9zaXRpb25zW291dGVyUmlnaHRJbmRleC0tXSA9IHBvc2l0aW9uLnk7CiAgICAgICAgICBvdXRlclBvc2l0aW9uc1tvdXRlclJpZ2h0SW5kZXgtLV0gPSBwb3NpdGlvbi54OwogICAgICAgIH0KICAgICAgICB0aGV0YSA9IE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyAtIGRlbHRhVGhldGE7CiAgICAgICAgZm9yIChpID0gMTsgaSA8IG51bVB0cyArIDE7ICsraSkgewogICAgICAgICAgcG9zaXRpb24gPSBwb2ludE9uRWxsaXBzb2lkKAogICAgICAgICAgICB0aGV0YSwKICAgICAgICAgICAgcm90YXRpb24sCiAgICAgICAgICAgIG5vcnRoVmVjLAogICAgICAgICAgICBlYXN0VmVjLAogICAgICAgICAgICBhU3FyLAogICAgICAgICAgICBhYiwKICAgICAgICAgICAgYlNxciwKICAgICAgICAgICAgbWFnLAogICAgICAgICAgICB1bml0UG9zLAogICAgICAgICAgICBwb3NpdGlvbgogICAgICAgICAgKTsKICAgICAgICAgIHJlZmxlY3RlZFBvc2l0aW9uID0gcG9pbnRPbkVsbGlwc29pZCgKICAgICAgICAgICAgTWF0aC5QSSAtIHRoZXRhLAogICAgICAgICAgICByb3RhdGlvbiwKICAgICAgICAgICAgbm9ydGhWZWMsCiAgICAgICAgICAgIGVhc3RWZWMsCiAgICAgICAgICAgIGFTcXIsCiAgICAgICAgICAgIGFiLAogICAgICAgICAgICBiU3FyLAogICAgICAgICAgICBtYWcsCiAgICAgICAgICAgIHVuaXRQb3MsCiAgICAgICAgICAgIHJlZmxlY3RlZFBvc2l0aW9uCiAgICAgICAgICApOwogICAgICAgICAgaWYgKGFkZEZpbGxQb3NpdGlvbnMpIHsKICAgICAgICAgICAgcG9zaXRpb25zW3Bvc2l0aW9uSW5kZXgrK10gPSBwb3NpdGlvbi54OwogICAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IHBvc2l0aW9uLnk7CiAgICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gcG9zaXRpb24uejsKICAgICAgICAgICAgbnVtSW50ZXJpb3IgPSAyICogaSArIDI7CiAgICAgICAgICAgIGZvciAoaiA9IDE7IGogPCBudW1JbnRlcmlvciAtIDE7ICsraikgewogICAgICAgICAgICAgIHQgPSBqIC8gKG51bUludGVyaW9yIC0gMSk7CiAgICAgICAgICAgICAgaW50ZXJpb3JQb3NpdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5sZXJwKAogICAgICAgICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICAgICAgICByZWZsZWN0ZWRQb3NpdGlvbiwKICAgICAgICAgICAgICAgIHQsCiAgICAgICAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuMzQKICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gaW50ZXJpb3JQb3NpdGlvbi54OwogICAgICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gaW50ZXJpb3JQb3NpdGlvbi55OwogICAgICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gaW50ZXJpb3JQb3NpdGlvbi56OwogICAgICAgICAgICB9CiAgICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gcmVmbGVjdGVkUG9zaXRpb24ueDsKICAgICAgICAgICAgcG9zaXRpb25zW3Bvc2l0aW9uSW5kZXgrK10gPSByZWZsZWN0ZWRQb3NpdGlvbi55OwogICAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IHJlZmxlY3RlZFBvc2l0aW9uLno7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoYWRkRWRnZVBvc2l0aW9ucykgewogICAgICAgICAgICBvdXRlclBvc2l0aW9uc1tvdXRlclJpZ2h0SW5kZXgtLV0gPSBwb3NpdGlvbi56OwogICAgICAgICAgICBvdXRlclBvc2l0aW9uc1tvdXRlclJpZ2h0SW5kZXgtLV0gPSBwb3NpdGlvbi55OwogICAgICAgICAgICBvdXRlclBvc2l0aW9uc1tvdXRlclJpZ2h0SW5kZXgtLV0gPSBwb3NpdGlvbi54OwogICAgICAgICAgICBvdXRlclBvc2l0aW9uc1tvdXRlckxlZnRJbmRleCsrXSA9IHJlZmxlY3RlZFBvc2l0aW9uLng7CiAgICAgICAgICAgIG91dGVyUG9zaXRpb25zW291dGVyTGVmdEluZGV4KytdID0gcmVmbGVjdGVkUG9zaXRpb24ueTsKICAgICAgICAgICAgb3V0ZXJQb3NpdGlvbnNbb3V0ZXJMZWZ0SW5kZXgrK10gPSByZWZsZWN0ZWRQb3NpdGlvbi56OwogICAgICAgICAgfQogICAgICAgICAgdGhldGEgPSBNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08gLSAoaSArIDEpICogZGVsdGFUaGV0YTsKICAgICAgICB9CiAgICAgICAgZm9yIChpID0gbnVtUHRzOyBpID4gMTsgLS1pKSB7CiAgICAgICAgICB0aGV0YSA9IE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyAtIChpIC0gMSkgKiBkZWx0YVRoZXRhOwogICAgICAgICAgcG9zaXRpb24gPSBwb2ludE9uRWxsaXBzb2lkKAogICAgICAgICAgICAtdGhldGEsCiAgICAgICAgICAgIHJvdGF0aW9uLAogICAgICAgICAgICBub3J0aFZlYywKICAgICAgICAgICAgZWFzdFZlYywKICAgICAgICAgICAgYVNxciwKICAgICAgICAgICAgYWIsCiAgICAgICAgICAgIGJTcXIsCiAgICAgICAgICAgIG1hZywKICAgICAgICAgICAgdW5pdFBvcywKICAgICAgICAgICAgcG9zaXRpb24KICAgICAgICAgICk7CiAgICAgICAgICByZWZsZWN0ZWRQb3NpdGlvbiA9IHBvaW50T25FbGxpcHNvaWQoCiAgICAgICAgICAgIHRoZXRhICsgTWF0aC5QSSwKICAgICAgICAgICAgcm90YXRpb24sCiAgICAgICAgICAgIG5vcnRoVmVjLAogICAgICAgICAgICBlYXN0VmVjLAogICAgICAgICAgICBhU3FyLAogICAgICAgICAgICBhYiwKICAgICAgICAgICAgYlNxciwKICAgICAgICAgICAgbWFnLAogICAgICAgICAgICB1bml0UG9zLAogICAgICAgICAgICByZWZsZWN0ZWRQb3NpdGlvbgogICAgICAgICAgKTsKICAgICAgICAgIGlmIChhZGRGaWxsUG9zaXRpb25zKSB7CiAgICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gcG9zaXRpb24ueDsKICAgICAgICAgICAgcG9zaXRpb25zW3Bvc2l0aW9uSW5kZXgrK10gPSBwb3NpdGlvbi55OwogICAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IHBvc2l0aW9uLno7CiAgICAgICAgICAgIG51bUludGVyaW9yID0gMiAqIChpIC0gMSkgKyAyOwogICAgICAgICAgICBmb3IgKGogPSAxOyBqIDwgbnVtSW50ZXJpb3IgLSAxOyArK2opIHsKICAgICAgICAgICAgICB0ID0gaiAvIChudW1JbnRlcmlvciAtIDEpOwogICAgICAgICAgICAgIGludGVyaW9yUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubGVycCgKICAgICAgICAgICAgICAgIHBvc2l0aW9uLAogICAgICAgICAgICAgICAgcmVmbGVjdGVkUG9zaXRpb24sCiAgICAgICAgICAgICAgICB0LAogICAgICAgICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjM0CiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IGludGVyaW9yUG9zaXRpb24ueDsKICAgICAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IGludGVyaW9yUG9zaXRpb24ueTsKICAgICAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IGludGVyaW9yUG9zaXRpb24uejsKICAgICAgICAgICAgfQogICAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IHJlZmxlY3RlZFBvc2l0aW9uLng7CiAgICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gcmVmbGVjdGVkUG9zaXRpb24ueTsKICAgICAgICAgICAgcG9zaXRpb25zW3Bvc2l0aW9uSW5kZXgrK10gPSByZWZsZWN0ZWRQb3NpdGlvbi56OwogICAgICAgICAgfQogICAgICAgICAgaWYgKGFkZEVkZ2VQb3NpdGlvbnMpIHsKICAgICAgICAgICAgb3V0ZXJQb3NpdGlvbnNbb3V0ZXJSaWdodEluZGV4LS1dID0gcG9zaXRpb24uejsKICAgICAgICAgICAgb3V0ZXJQb3NpdGlvbnNbb3V0ZXJSaWdodEluZGV4LS1dID0gcG9zaXRpb24ueTsKICAgICAgICAgICAgb3V0ZXJQb3NpdGlvbnNbb3V0ZXJSaWdodEluZGV4LS1dID0gcG9zaXRpb24ueDsKICAgICAgICAgICAgb3V0ZXJQb3NpdGlvbnNbb3V0ZXJMZWZ0SW5kZXgrK10gPSByZWZsZWN0ZWRQb3NpdGlvbi54OwogICAgICAgICAgICBvdXRlclBvc2l0aW9uc1tvdXRlckxlZnRJbmRleCsrXSA9IHJlZmxlY3RlZFBvc2l0aW9uLnk7CiAgICAgICAgICAgIG91dGVyUG9zaXRpb25zW291dGVyTGVmdEluZGV4KytdID0gcmVmbGVjdGVkUG9zaXRpb24uejsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgdGhldGEgPSBNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV087CiAgICAgICAgcG9zaXRpb24gPSBwb2ludE9uRWxsaXBzb2lkKAogICAgICAgICAgLXRoZXRhLAogICAgICAgICAgcm90YXRpb24sCiAgICAgICAgICBub3J0aFZlYywKICAgICAgICAgIGVhc3RWZWMsCiAgICAgICAgICBhU3FyLAogICAgICAgICAgYWIsCiAgICAgICAgICBiU3FyLAogICAgICAgICAgbWFnLAogICAgICAgICAgdW5pdFBvcywKICAgICAgICAgIHBvc2l0aW9uCiAgICAgICAgKTsKICAgICAgICBjb25zdCByID0ge307CiAgICAgICAgaWYgKGFkZEZpbGxQb3NpdGlvbnMpIHsKICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gcG9zaXRpb24ueDsKICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gcG9zaXRpb24ueTsKICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gcG9zaXRpb24uejsKICAgICAgICAgIHIucG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgICAgICAgci5udW1QdHMgPSBudW1QdHM7CiAgICAgICAgfQogICAgICAgIGlmIChhZGRFZGdlUG9zaXRpb25zKSB7CiAgICAgICAgICBvdXRlclBvc2l0aW9uc1tvdXRlclJpZ2h0SW5kZXgtLV0gPSBwb3NpdGlvbi56OwogICAgICAgICAgb3V0ZXJQb3NpdGlvbnNbb3V0ZXJSaWdodEluZGV4LS1dID0gcG9zaXRpb24ueTsKICAgICAgICAgIG91dGVyUG9zaXRpb25zW291dGVyUmlnaHRJbmRleC0tXSA9IHBvc2l0aW9uLng7CiAgICAgICAgICByLm91dGVyUG9zaXRpb25zID0gb3V0ZXJQb3NpdGlvbnM7CiAgICAgICAgfQogICAgICAgIHJldHVybiByOwogICAgICB9OwogICAgICBFbGxpcHNlR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQgPSBFbGxpcHNlR2VvbWV0cnlMaWJyYXJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvR2VvbWV0cnlJbnN0YW5jZS5qcwogIGZ1bmN0aW9uIEdlb21ldHJ5SW5zdGFuY2Uob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQob3B0aW9ucy5nZW9tZXRyeSkpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9wdGlvbnMuZ2VvbWV0cnkgaXMgcmVxdWlyZWQuIik7CiAgICB9CiAgICB0aGlzLmdlb21ldHJ5ID0gb3B0aW9ucy5nZW9tZXRyeTsKICAgIHRoaXMubW9kZWxNYXRyaXggPSBNYXRyaXg0X2RlZmF1bHQuY2xvbmUob3B0aW9ucy5tb2RlbE1hdHJpeCA/PyBNYXRyaXg0X2RlZmF1bHQuSURFTlRJVFkpOwogICAgdGhpcy5pZCA9IG9wdGlvbnMuaWQ7CiAgICB0aGlzLnBpY2tQcmltaXRpdmUgPSBvcHRpb25zLnBpY2tQcmltaXRpdmU7CiAgICB0aGlzLmF0dHJpYnV0ZXMgPSBvcHRpb25zLmF0dHJpYnV0ZXMgPz8ge307CiAgICB0aGlzLndlc3RIZW1pc3BoZXJlR2VvbWV0cnkgPSB2b2lkIDA7CiAgICB0aGlzLmVhc3RIZW1pc3BoZXJlR2VvbWV0cnkgPSB2b2lkIDA7CiAgfQogIHZhciBHZW9tZXRyeUluc3RhbmNlX2RlZmF1bHQ7CiAgdmFyIGluaXRfR2VvbWV0cnlJbnN0YW5jZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvR2VvbWV0cnlJbnN0YW5jZS5qcyIoKSB7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfTWF0cml4NCgpOwogICAgICBHZW9tZXRyeUluc3RhbmNlX2RlZmF1bHQgPSBHZW9tZXRyeUluc3RhbmNlOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvRWxsaXBzZUdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gY29tcHV0ZVRvcEJvdHRvbUF0dHJpYnV0ZXMocG9zaXRpb25zLCBvcHRpb25zLCBleHRydWRlKSB7CiAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBvcHRpb25zLnZlcnRleEZvcm1hdDsKICAgIGNvbnN0IGNlbnRlciA9IG9wdGlvbnMuY2VudGVyOwogICAgY29uc3Qgc2VtaU1ham9yQXhpcyA9IG9wdGlvbnMuc2VtaU1ham9yQXhpczsKICAgIGNvbnN0IHNlbWlNaW5vckF4aXMgPSBvcHRpb25zLnNlbWlNaW5vckF4aXM7CiAgICBjb25zdCBlbGxpcHNvaWQgPSBvcHRpb25zLmVsbGlwc29pZDsKICAgIGNvbnN0IHN0Um90YXRpb24gPSBvcHRpb25zLnN0Um90YXRpb247CiAgICBjb25zdCBzaXplID0gZXh0cnVkZSA/IHBvc2l0aW9ucy5sZW5ndGggLyAzICogMiA6IHBvc2l0aW9ucy5sZW5ndGggLyAzOwogICAgY29uc3Qgc2hhZG93Vm9sdW1lID0gb3B0aW9ucy5zaGFkb3dWb2x1bWU7CiAgICBjb25zdCB0ZXh0dXJlQ29vcmRpbmF0ZXMgPSB2ZXJ0ZXhGb3JtYXQuc3QgPyBuZXcgRmxvYXQzMkFycmF5KHNpemUgKiAyKSA6IHZvaWQgMDsKICAgIGNvbnN0IG5vcm1hbHMgPSB2ZXJ0ZXhGb3JtYXQubm9ybWFsID8gbmV3IEZsb2F0MzJBcnJheShzaXplICogMykgOiB2b2lkIDA7CiAgICBjb25zdCB0YW5nZW50cyA9IHZlcnRleEZvcm1hdC50YW5nZW50ID8gbmV3IEZsb2F0MzJBcnJheShzaXplICogMykgOiB2b2lkIDA7CiAgICBjb25zdCBiaXRhbmdlbnRzID0gdmVydGV4Rm9ybWF0LmJpdGFuZ2VudCA/IG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSAqIDMpIDogdm9pZCAwOwogICAgY29uc3QgZXh0cnVkZU5vcm1hbHMgPSBzaGFkb3dWb2x1bWUgPyBuZXcgRmxvYXQzMkFycmF5KHNpemUgKiAzKSA6IHZvaWQgMDsKICAgIGxldCB0ZXh0dXJlQ29vcmRJbmRleCA9IDA7CiAgICBsZXQgbm9ybWFsMiA9IHNjcmF0Y2hOb3JtYWwzOwogICAgbGV0IHRhbmdlbnQgPSBzY3JhdGNoVGFuZ2VudDsKICAgIGxldCBiaXRhbmdlbnQgPSBzY3JhdGNoQml0YW5nZW50OwogICAgY29uc3QgcHJvamVjdGlvbiA9IG5ldyBHZW9ncmFwaGljUHJvamVjdGlvbl9kZWZhdWx0KGVsbGlwc29pZCk7CiAgICBjb25zdCBwcm9qZWN0ZWRDZW50ZXIgPSBwcm9qZWN0aW9uLnByb2plY3QoCiAgICAgIGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyhjZW50ZXIsIHNjcmF0Y2hDYXJ0b2dyYXBoaWMyKSwKICAgICAgcHJvamVjdGVkQ2VudGVyU2NyYXRjaAogICAgKTsKICAgIGNvbnN0IGdlb2RldGljTm9ybWFsID0gZWxsaXBzb2lkLnNjYWxlVG9HZW9kZXRpY1N1cmZhY2UoCiAgICAgIGNlbnRlciwKICAgICAgc2NyYXRjaENhcnRlc2lhbjEzCiAgICApOwogICAgZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbChnZW9kZXRpY05vcm1hbCwgZ2VvZGV0aWNOb3JtYWwpOwogICAgbGV0IHRleHR1cmVNYXRyaXggPSB0ZXh0dXJlTWF0cml4U2NyYXRjaDsKICAgIGxldCB0YW5nZW50TWF0cml4ID0gdGFuZ2VudE1hdHJpeFNjcmF0Y2g7CiAgICBpZiAoc3RSb3RhdGlvbiAhPT0gMCkgewogICAgICBsZXQgcm90YXRpb24gPSBRdWF0ZXJuaW9uX2RlZmF1bHQuZnJvbUF4aXNBbmdsZSgKICAgICAgICBnZW9kZXRpY05vcm1hbCwKICAgICAgICBzdFJvdGF0aW9uLAogICAgICAgIHF1YXRlcm5pb25TY3JhdGNoCiAgICAgICk7CiAgICAgIHRleHR1cmVNYXRyaXggPSBNYXRyaXgzX2RlZmF1bHQuZnJvbVF1YXRlcm5pb24ocm90YXRpb24sIHRleHR1cmVNYXRyaXgpOwogICAgICByb3RhdGlvbiA9IFF1YXRlcm5pb25fZGVmYXVsdC5mcm9tQXhpc0FuZ2xlKAogICAgICAgIGdlb2RldGljTm9ybWFsLAogICAgICAgIC1zdFJvdGF0aW9uLAogICAgICAgIHF1YXRlcm5pb25TY3JhdGNoCiAgICAgICk7CiAgICAgIHRhbmdlbnRNYXRyaXggPSBNYXRyaXgzX2RlZmF1bHQuZnJvbVF1YXRlcm5pb24ocm90YXRpb24sIHRhbmdlbnRNYXRyaXgpOwogICAgfSBlbHNlIHsKICAgICAgdGV4dHVyZU1hdHJpeCA9IE1hdHJpeDNfZGVmYXVsdC5jbG9uZShNYXRyaXgzX2RlZmF1bHQuSURFTlRJVFksIHRleHR1cmVNYXRyaXgpOwogICAgICB0YW5nZW50TWF0cml4ID0gTWF0cml4M19kZWZhdWx0LmNsb25lKE1hdHJpeDNfZGVmYXVsdC5JREVOVElUWSwgdGFuZ2VudE1hdHJpeCk7CiAgICB9CiAgICBjb25zdCBtaW5UZXhDb29yZCA9IENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHMoCiAgICAgIE51bWJlci5QT1NJVElWRV9JTkZJTklUWSwKICAgICAgTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLAogICAgICBzY3JhdGNoTWluVGV4Q29vcmQKICAgICk7CiAgICBjb25zdCBtYXhUZXhDb29yZCA9IENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHMoCiAgICAgIE51bWJlci5ORUdBVElWRV9JTkZJTklUWSwKICAgICAgTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZLAogICAgICBzY3JhdGNoTWF4VGV4Q29vcmQKICAgICk7CiAgICBsZXQgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgIGNvbnN0IGJvdHRvbU9mZnNldCA9IGV4dHJ1ZGUgPyBsZW5ndGggOiAwOwogICAgY29uc3Qgc3RPZmZzZXQgPSBib3R0b21PZmZzZXQgLyAzICogMjsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHsKICAgICAgY29uc3QgaTEgPSBpICsgMTsKICAgICAgY29uc3QgaTIgPSBpICsgMjsKICAgICAgY29uc3QgcG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHBvc2l0aW9ucywgaSwgc2NyYXRjaENhcnRlc2lhbjEzKTsKICAgICAgaWYgKHZlcnRleEZvcm1hdC5zdCkgewogICAgICAgIGNvbnN0IHJvdGF0ZWRQb2ludCA9IE1hdHJpeDNfZGVmYXVsdC5tdWx0aXBseUJ5VmVjdG9yKAogICAgICAgICAgdGV4dHVyZU1hdHJpeCwKICAgICAgICAgIHBvc2l0aW9uLAogICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjI0CiAgICAgICAgKTsKICAgICAgICBjb25zdCBwcm9qZWN0ZWRQb2ludCA9IHByb2plY3Rpb24ucHJvamVjdCgKICAgICAgICAgIGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyhyb3RhdGVkUG9pbnQsIHNjcmF0Y2hDYXJ0b2dyYXBoaWMyKSwKICAgICAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4zNQogICAgICAgICk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHByb2plY3RlZFBvaW50LCBwcm9qZWN0ZWRDZW50ZXIsIHByb2plY3RlZFBvaW50KTsKICAgICAgICB0ZXhDb29yZFNjcmF0Y2gueCA9IChwcm9qZWN0ZWRQb2ludC54ICsgc2VtaU1ham9yQXhpcykgLyAoMiAqIHNlbWlNYWpvckF4aXMpOwogICAgICAgIHRleENvb3JkU2NyYXRjaC55ID0gKHByb2plY3RlZFBvaW50LnkgKyBzZW1pTWlub3JBeGlzKSAvICgyICogc2VtaU1pbm9yQXhpcyk7CiAgICAgICAgbWluVGV4Q29vcmQueCA9IE1hdGgubWluKHRleENvb3JkU2NyYXRjaC54LCBtaW5UZXhDb29yZC54KTsKICAgICAgICBtaW5UZXhDb29yZC55ID0gTWF0aC5taW4odGV4Q29vcmRTY3JhdGNoLnksIG1pblRleENvb3JkLnkpOwogICAgICAgIG1heFRleENvb3JkLnggPSBNYXRoLm1heCh0ZXhDb29yZFNjcmF0Y2gueCwgbWF4VGV4Q29vcmQueCk7CiAgICAgICAgbWF4VGV4Q29vcmQueSA9IE1hdGgubWF4KHRleENvb3JkU2NyYXRjaC55LCBtYXhUZXhDb29yZC55KTsKICAgICAgICBpZiAoZXh0cnVkZSkgewogICAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW3RleHR1cmVDb29yZEluZGV4ICsgc3RPZmZzZXRdID0gdGV4Q29vcmRTY3JhdGNoLng7CiAgICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXNbdGV4dHVyZUNvb3JkSW5kZXggKyAxICsgc3RPZmZzZXRdID0gdGV4Q29vcmRTY3JhdGNoLnk7CiAgICAgICAgfQogICAgICAgIHRleHR1cmVDb29yZGluYXRlc1t0ZXh0dXJlQ29vcmRJbmRleCsrXSA9IHRleENvb3JkU2NyYXRjaC54OwogICAgICAgIHRleHR1cmVDb29yZGluYXRlc1t0ZXh0dXJlQ29vcmRJbmRleCsrXSA9IHRleENvb3JkU2NyYXRjaC55OwogICAgICB9CiAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsIHx8IHZlcnRleEZvcm1hdC50YW5nZW50IHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQgfHwgc2hhZG93Vm9sdW1lKSB7CiAgICAgICAgbm9ybWFsMiA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwocG9zaXRpb24sIG5vcm1hbDIpOwogICAgICAgIGlmIChzaGFkb3dWb2x1bWUpIHsKICAgICAgICAgIGV4dHJ1ZGVOb3JtYWxzW2kgKyBib3R0b21PZmZzZXRdID0gLW5vcm1hbDIueDsKICAgICAgICAgIGV4dHJ1ZGVOb3JtYWxzW2kxICsgYm90dG9tT2Zmc2V0XSA9IC1ub3JtYWwyLnk7CiAgICAgICAgICBleHRydWRlTm9ybWFsc1tpMiArIGJvdHRvbU9mZnNldF0gPSAtbm9ybWFsMi56OwogICAgICAgIH0KICAgICAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCB8fCB2ZXJ0ZXhGb3JtYXQudGFuZ2VudCB8fCB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQgfHwgdmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgICAgICB0YW5nZW50ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWiwgbm9ybWFsMiwgdGFuZ2VudCksCiAgICAgICAgICAgICAgdGFuZ2VudAogICAgICAgICAgICApOwogICAgICAgICAgICBNYXRyaXgzX2RlZmF1bHQubXVsdGlwbHlCeVZlY3Rvcih0YW5nZW50TWF0cml4LCB0YW5nZW50LCB0YW5nZW50KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgICAgICAgIG5vcm1hbHNbaV0gPSBub3JtYWwyLng7CiAgICAgICAgICAgIG5vcm1hbHNbaTFdID0gbm9ybWFsMi55OwogICAgICAgICAgICBub3JtYWxzW2kyXSA9IG5vcm1hbDIuejsKICAgICAgICAgICAgaWYgKGV4dHJ1ZGUpIHsKICAgICAgICAgICAgICBub3JtYWxzW2kgKyBib3R0b21PZmZzZXRdID0gLW5vcm1hbDIueDsKICAgICAgICAgICAgICBub3JtYWxzW2kxICsgYm90dG9tT2Zmc2V0XSA9IC1ub3JtYWwyLnk7CiAgICAgICAgICAgICAgbm9ybWFsc1tpMiArIGJvdHRvbU9mZnNldF0gPSAtbm9ybWFsMi56OwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQpIHsKICAgICAgICAgICAgdGFuZ2VudHNbaV0gPSB0YW5nZW50Lng7CiAgICAgICAgICAgIHRhbmdlbnRzW2kxXSA9IHRhbmdlbnQueTsKICAgICAgICAgICAgdGFuZ2VudHNbaTJdID0gdGFuZ2VudC56OwogICAgICAgICAgICBpZiAoZXh0cnVkZSkgewogICAgICAgICAgICAgIHRhbmdlbnRzW2kgKyBib3R0b21PZmZzZXRdID0gLXRhbmdlbnQueDsKICAgICAgICAgICAgICB0YW5nZW50c1tpMSArIGJvdHRvbU9mZnNldF0gPSAtdGFuZ2VudC55OwogICAgICAgICAgICAgIHRhbmdlbnRzW2kyICsgYm90dG9tT2Zmc2V0XSA9IC10YW5nZW50Lno7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgICAgIGJpdGFuZ2VudCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKG5vcm1hbDIsIHRhbmdlbnQsIGJpdGFuZ2VudCksCiAgICAgICAgICAgICAgYml0YW5nZW50CiAgICAgICAgICAgICk7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbaV0gPSBiaXRhbmdlbnQueDsKICAgICAgICAgICAgYml0YW5nZW50c1tpMV0gPSBiaXRhbmdlbnQueTsKICAgICAgICAgICAgYml0YW5nZW50c1tpMl0gPSBiaXRhbmdlbnQuejsKICAgICAgICAgICAgaWYgKGV4dHJ1ZGUpIHsKICAgICAgICAgICAgICBiaXRhbmdlbnRzW2kgKyBib3R0b21PZmZzZXRdID0gYml0YW5nZW50Lng7CiAgICAgICAgICAgICAgYml0YW5nZW50c1tpMSArIGJvdHRvbU9mZnNldF0gPSBiaXRhbmdlbnQueTsKICAgICAgICAgICAgICBiaXRhbmdlbnRzW2kyICsgYm90dG9tT2Zmc2V0XSA9IGJpdGFuZ2VudC56OwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAodmVydGV4Rm9ybWF0LnN0KSB7CiAgICAgIGxlbmd0aCA9IHRleHR1cmVDb29yZGluYXRlcy5sZW5ndGg7CiAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgbGVuZ3RoOyBrICs9IDIpIHsKICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXNba10gPSAodGV4dHVyZUNvb3JkaW5hdGVzW2tdIC0gbWluVGV4Q29vcmQueCkgLyAobWF4VGV4Q29vcmQueCAtIG1pblRleENvb3JkLngpOwogICAgICAgIHRleHR1cmVDb29yZGluYXRlc1trICsgMV0gPSAodGV4dHVyZUNvb3JkaW5hdGVzW2sgKyAxXSAtIG1pblRleENvb3JkLnkpIC8gKG1heFRleENvb3JkLnkgLSBtaW5UZXhDb29yZC55KTsKICAgICAgfQogICAgfQogICAgY29uc3QgYXR0cmlidXRlcyA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZXNfZGVmYXVsdCgpOwogICAgaWYgKHZlcnRleEZvcm1hdC5wb3NpdGlvbikgewogICAgICBjb25zdCBmaW5hbFBvc2l0aW9ucyA9IEVsbGlwc2VHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5yYWlzZVBvc2l0aW9uc1RvSGVpZ2h0KAogICAgICAgIHBvc2l0aW9ucywKICAgICAgICBvcHRpb25zLAogICAgICAgIGV4dHJ1ZGUKICAgICAgKTsKICAgICAgYXR0cmlidXRlcy5wb3NpdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IGZpbmFsUG9zaXRpb25zCiAgICAgIH0pOwogICAgfQogICAgaWYgKHZlcnRleEZvcm1hdC5zdCkgewogICAgICBhdHRyaWJ1dGVzLnN0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDIsCiAgICAgICAgdmFsdWVzOiB0ZXh0dXJlQ29vcmRpbmF0ZXMKICAgICAgfSk7CiAgICB9CiAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICBhdHRyaWJ1dGVzLm5vcm1hbCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgIHZhbHVlczogbm9ybWFscwogICAgICB9KTsKICAgIH0KICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICBhdHRyaWJ1dGVzLnRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IHRhbmdlbnRzCiAgICAgIH0pOwogICAgfQogICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgYXR0cmlidXRlcy5iaXRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IGJpdGFuZ2VudHMKICAgICAgfSk7CiAgICB9CiAgICBpZiAoc2hhZG93Vm9sdW1lKSB7CiAgICAgIGF0dHJpYnV0ZXMuZXh0cnVkZURpcmVjdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgIHZhbHVlczogZXh0cnVkZU5vcm1hbHMKICAgICAgfSk7CiAgICB9CiAgICBpZiAoZXh0cnVkZSAmJiBkZWZpbmVkX2RlZmF1bHQob3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGUpKSB7CiAgICAgIGxldCBvZmZzZXRBdHRyaWJ1dGUgPSBuZXcgVWludDhBcnJheShzaXplKTsKICAgICAgaWYgKG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlID09PSBHZW9tZXRyeU9mZnNldEF0dHJpYnV0ZV9kZWZhdWx0LlRPUCkgewogICAgICAgIG9mZnNldEF0dHJpYnV0ZSA9IG9mZnNldEF0dHJpYnV0ZS5maWxsKDEsIDAsIHNpemUgLyAyKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBvZmZzZXRWYWx1ZSA9IG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlID09PSBHZW9tZXRyeU9mZnNldEF0dHJpYnV0ZV9kZWZhdWx0Lk5PTkUgPyAwIDogMTsKICAgICAgICBvZmZzZXRBdHRyaWJ1dGUgPSBvZmZzZXRBdHRyaWJ1dGUuZmlsbChvZmZzZXRWYWx1ZSk7CiAgICAgIH0KICAgICAgYXR0cmlidXRlcy5hcHBseU9mZnNldCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9CWVRFLAogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDEsCiAgICAgICAgdmFsdWVzOiBvZmZzZXRBdHRyaWJ1dGUKICAgICAgfSk7CiAgICB9CiAgICByZXR1cm4gYXR0cmlidXRlczsKICB9CiAgZnVuY3Rpb24gdG9wSW5kaWNlcyhudW1QdHMpIHsKICAgIGNvbnN0IGluZGljZXMgPSBuZXcgQXJyYXkoMTIgKiAobnVtUHRzICogKG51bVB0cyArIDEpKSAtIDYpOwogICAgbGV0IGluZGljZXNJbmRleCA9IDA7CiAgICBsZXQgcHJldkluZGV4OwogICAgbGV0IG51bUludGVyaW9yOwogICAgbGV0IHBvc2l0aW9uSW5kZXg7CiAgICBsZXQgaTsKICAgIGxldCBqOwogICAgcHJldkluZGV4ID0gMDsKICAgIHBvc2l0aW9uSW5kZXggPSAxOwogICAgZm9yIChpID0gMDsgaSA8IDM7IGkrKykgewogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHBvc2l0aW9uSW5kZXgrKzsKICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwcmV2SW5kZXg7CiAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gcG9zaXRpb25JbmRleDsKICAgIH0KICAgIGZvciAoaSA9IDI7IGkgPCBudW1QdHMgKyAxOyArK2kpIHsKICAgICAgcG9zaXRpb25JbmRleCA9IGkgKiAoaSArIDEpIC0gMTsKICAgICAgcHJldkluZGV4ID0gKGkgLSAxKSAqIGkgLSAxOwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHBvc2l0aW9uSW5kZXgrKzsKICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwcmV2SW5kZXg7CiAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gcG9zaXRpb25JbmRleDsKICAgICAgbnVtSW50ZXJpb3IgPSAyICogaTsKICAgICAgZm9yIChqID0gMDsgaiA8IG51bUludGVyaW9yIC0gMTsgKytqKSB7CiAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwb3NpdGlvbkluZGV4OwogICAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gcHJldkluZGV4Kys7CiAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwcmV2SW5kZXg7CiAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwb3NpdGlvbkluZGV4Kys7CiAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwcmV2SW5kZXg7CiAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwb3NpdGlvbkluZGV4OwogICAgICB9CiAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gcG9zaXRpb25JbmRleCsrOwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHByZXZJbmRleDsKICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwb3NpdGlvbkluZGV4OwogICAgfQogICAgbnVtSW50ZXJpb3IgPSBudW1QdHMgKiAyOwogICAgKytwb3NpdGlvbkluZGV4OwogICAgKytwcmV2SW5kZXg7CiAgICBmb3IgKGkgPSAwOyBpIDwgbnVtSW50ZXJpb3IgLSAxOyArK2kpIHsKICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwb3NpdGlvbkluZGV4OwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHByZXZJbmRleCsrOwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHByZXZJbmRleDsKICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwb3NpdGlvbkluZGV4Kys7CiAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gcHJldkluZGV4OwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHBvc2l0aW9uSW5kZXg7CiAgICB9CiAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHBvc2l0aW9uSW5kZXg7CiAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHByZXZJbmRleCsrOwogICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwcmV2SW5kZXg7CiAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHBvc2l0aW9uSW5kZXgrKzsKICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gcHJldkluZGV4Kys7CiAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHByZXZJbmRleDsKICAgICsrcHJldkluZGV4OwogICAgZm9yIChpID0gbnVtUHRzIC0gMTsgaSA+IDE7IC0taSkgewogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHByZXZJbmRleCsrOwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHByZXZJbmRleDsKICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwb3NpdGlvbkluZGV4OwogICAgICBudW1JbnRlcmlvciA9IDIgKiBpOwogICAgICBmb3IgKGogPSAwOyBqIDwgbnVtSW50ZXJpb3IgLSAxOyArK2opIHsKICAgICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHBvc2l0aW9uSW5kZXg7CiAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwcmV2SW5kZXgrKzsKICAgICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHByZXZJbmRleDsKICAgICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHBvc2l0aW9uSW5kZXgrKzsKICAgICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHByZXZJbmRleDsKICAgICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHBvc2l0aW9uSW5kZXg7CiAgICAgIH0KICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwcmV2SW5kZXgrKzsKICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwcmV2SW5kZXgrKzsKICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwb3NpdGlvbkluZGV4Kys7CiAgICB9CiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgaSsrKSB7CiAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gcHJldkluZGV4Kys7CiAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gcHJldkluZGV4OwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHBvc2l0aW9uSW5kZXg7CiAgICB9CiAgICByZXR1cm4gaW5kaWNlczsKICB9CiAgZnVuY3Rpb24gY29tcHV0ZUVsbGlwc2Uob3B0aW9ucykgewogICAgY29uc3QgY2VudGVyID0gb3B0aW9ucy5jZW50ZXI7CiAgICBib3VuZGluZ1NwaGVyZUNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICBvcHRpb25zLmVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwoY2VudGVyLCBib3VuZGluZ1NwaGVyZUNlbnRlciksCiAgICAgIG9wdGlvbnMuaGVpZ2h0LAogICAgICBib3VuZGluZ1NwaGVyZUNlbnRlcgogICAgKTsKICAgIGJvdW5kaW5nU3BoZXJlQ2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZCgKICAgICAgY2VudGVyLAogICAgICBib3VuZGluZ1NwaGVyZUNlbnRlciwKICAgICAgYm91bmRpbmdTcGhlcmVDZW50ZXIKICAgICk7CiAgICBjb25zdCBib3VuZGluZ1NwaGVyZSA9IG5ldyBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0KAogICAgICBib3VuZGluZ1NwaGVyZUNlbnRlciwKICAgICAgb3B0aW9ucy5zZW1pTWFqb3JBeGlzCiAgICApOwogICAgY29uc3QgY2VwID0gRWxsaXBzZUdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVFbGxpcHNlUG9zaXRpb25zKAogICAgICBvcHRpb25zLAogICAgICB0cnVlLAogICAgICBmYWxzZQogICAgKTsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IGNlcC5wb3NpdGlvbnM7CiAgICBjb25zdCBudW1QdHMgPSBjZXAubnVtUHRzOwogICAgY29uc3QgYXR0cmlidXRlcyA9IGNvbXB1dGVUb3BCb3R0b21BdHRyaWJ1dGVzKHBvc2l0aW9ucywgb3B0aW9ucywgZmFsc2UpOwogICAgbGV0IGluZGljZXMgPSB0b3BJbmRpY2VzKG51bVB0cyk7CiAgICBpbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkocG9zaXRpb25zLmxlbmd0aCAvIDMsIGluZGljZXMpOwogICAgcmV0dXJuIHsKICAgICAgYm91bmRpbmdTcGhlcmUsCiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGluZGljZXMKICAgIH07CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVXYWxsQXR0cmlidXRlcyhwb3NpdGlvbnMsIG9wdGlvbnMpIHsKICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IG9wdGlvbnMudmVydGV4Rm9ybWF0OwogICAgY29uc3QgY2VudGVyID0gb3B0aW9ucy5jZW50ZXI7CiAgICBjb25zdCBzZW1pTWFqb3JBeGlzID0gb3B0aW9ucy5zZW1pTWFqb3JBeGlzOwogICAgY29uc3Qgc2VtaU1pbm9yQXhpcyA9IG9wdGlvbnMuc2VtaU1pbm9yQXhpczsKICAgIGNvbnN0IGVsbGlwc29pZCA9IG9wdGlvbnMuZWxsaXBzb2lkOwogICAgY29uc3QgaGVpZ2h0ID0gb3B0aW9ucy5oZWlnaHQ7CiAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IG9wdGlvbnMuZXh0cnVkZWRIZWlnaHQ7CiAgICBjb25zdCBzdFJvdGF0aW9uID0gb3B0aW9ucy5zdFJvdGF0aW9uOwogICAgY29uc3Qgc2l6ZSA9IHBvc2l0aW9ucy5sZW5ndGggLyAzICogMjsKICAgIGNvbnN0IGZpbmFsUG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShzaXplICogMyk7CiAgICBjb25zdCB0ZXh0dXJlQ29vcmRpbmF0ZXMgPSB2ZXJ0ZXhGb3JtYXQuc3QgPyBuZXcgRmxvYXQzMkFycmF5KHNpemUgKiAyKSA6IHZvaWQgMDsKICAgIGNvbnN0IG5vcm1hbHMgPSB2ZXJ0ZXhGb3JtYXQubm9ybWFsID8gbmV3IEZsb2F0MzJBcnJheShzaXplICogMykgOiB2b2lkIDA7CiAgICBjb25zdCB0YW5nZW50cyA9IHZlcnRleEZvcm1hdC50YW5nZW50ID8gbmV3IEZsb2F0MzJBcnJheShzaXplICogMykgOiB2b2lkIDA7CiAgICBjb25zdCBiaXRhbmdlbnRzID0gdmVydGV4Rm9ybWF0LmJpdGFuZ2VudCA/IG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSAqIDMpIDogdm9pZCAwOwogICAgY29uc3Qgc2hhZG93Vm9sdW1lID0gb3B0aW9ucy5zaGFkb3dWb2x1bWU7CiAgICBjb25zdCBleHRydWRlTm9ybWFscyA9IHNoYWRvd1ZvbHVtZSA/IG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSAqIDMpIDogdm9pZCAwOwogICAgbGV0IHRleHR1cmVDb29yZEluZGV4ID0gMDsKICAgIGxldCBub3JtYWwyID0gc2NyYXRjaE5vcm1hbDM7CiAgICBsZXQgdGFuZ2VudCA9IHNjcmF0Y2hUYW5nZW50OwogICAgbGV0IGJpdGFuZ2VudCA9IHNjcmF0Y2hCaXRhbmdlbnQ7CiAgICBjb25zdCBwcm9qZWN0aW9uID0gbmV3IEdlb2dyYXBoaWNQcm9qZWN0aW9uX2RlZmF1bHQoZWxsaXBzb2lkKTsKICAgIGNvbnN0IHByb2plY3RlZENlbnRlciA9IHByb2plY3Rpb24ucHJvamVjdCgKICAgICAgZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKGNlbnRlciwgc2NyYXRjaENhcnRvZ3JhcGhpYzIpLAogICAgICBwcm9qZWN0ZWRDZW50ZXJTY3JhdGNoCiAgICApOwogICAgY29uc3QgZ2VvZGV0aWNOb3JtYWwgPSBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZSgKICAgICAgY2VudGVyLAogICAgICBzY3JhdGNoQ2FydGVzaWFuMTMKICAgICk7CiAgICBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKGdlb2RldGljTm9ybWFsLCBnZW9kZXRpY05vcm1hbCk7CiAgICBjb25zdCByb3RhdGlvbiA9IFF1YXRlcm5pb25fZGVmYXVsdC5mcm9tQXhpc0FuZ2xlKAogICAgICBnZW9kZXRpY05vcm1hbCwKICAgICAgc3RSb3RhdGlvbiwKICAgICAgcXVhdGVybmlvblNjcmF0Y2gKICAgICk7CiAgICBjb25zdCB0ZXh0dXJlTWF0cml4ID0gTWF0cml4M19kZWZhdWx0LmZyb21RdWF0ZXJuaW9uKHJvdGF0aW9uLCB0ZXh0dXJlTWF0cml4U2NyYXRjaCk7CiAgICBjb25zdCBtaW5UZXhDb29yZCA9IENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHMoCiAgICAgIE51bWJlci5QT1NJVElWRV9JTkZJTklUWSwKICAgICAgTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLAogICAgICBzY3JhdGNoTWluVGV4Q29vcmQKICAgICk7CiAgICBjb25zdCBtYXhUZXhDb29yZCA9IENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHMoCiAgICAgIE51bWJlci5ORUdBVElWRV9JTkZJTklUWSwKICAgICAgTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZLAogICAgICBzY3JhdGNoTWF4VGV4Q29vcmQKICAgICk7CiAgICBsZXQgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgIGNvbnN0IHN0T2Zmc2V0ID0gbGVuZ3RoIC8gMyAqIDI7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAzKSB7CiAgICAgIGNvbnN0IGkxID0gaSArIDE7CiAgICAgIGNvbnN0IGkyID0gaSArIDI7CiAgICAgIGxldCBwb3NpdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkocG9zaXRpb25zLCBpLCBzY3JhdGNoQ2FydGVzaWFuMTMpOwogICAgICBsZXQgZXh0cnVkZWRQb3NpdGlvbjsKICAgICAgaWYgKHZlcnRleEZvcm1hdC5zdCkgewogICAgICAgIGNvbnN0IHJvdGF0ZWRQb2ludCA9IE1hdHJpeDNfZGVmYXVsdC5tdWx0aXBseUJ5VmVjdG9yKAogICAgICAgICAgdGV4dHVyZU1hdHJpeCwKICAgICAgICAgIHBvc2l0aW9uLAogICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjI0CiAgICAgICAgKTsKICAgICAgICBjb25zdCBwcm9qZWN0ZWRQb2ludCA9IHByb2plY3Rpb24ucHJvamVjdCgKICAgICAgICAgIGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyhyb3RhdGVkUG9pbnQsIHNjcmF0Y2hDYXJ0b2dyYXBoaWMyKSwKICAgICAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4zNQogICAgICAgICk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHByb2plY3RlZFBvaW50LCBwcm9qZWN0ZWRDZW50ZXIsIHByb2plY3RlZFBvaW50KTsKICAgICAgICB0ZXhDb29yZFNjcmF0Y2gueCA9IChwcm9qZWN0ZWRQb2ludC54ICsgc2VtaU1ham9yQXhpcykgLyAoMiAqIHNlbWlNYWpvckF4aXMpOwogICAgICAgIHRleENvb3JkU2NyYXRjaC55ID0gKHByb2plY3RlZFBvaW50LnkgKyBzZW1pTWlub3JBeGlzKSAvICgyICogc2VtaU1pbm9yQXhpcyk7CiAgICAgICAgbWluVGV4Q29vcmQueCA9IE1hdGgubWluKHRleENvb3JkU2NyYXRjaC54LCBtaW5UZXhDb29yZC54KTsKICAgICAgICBtaW5UZXhDb29yZC55ID0gTWF0aC5taW4odGV4Q29vcmRTY3JhdGNoLnksIG1pblRleENvb3JkLnkpOwogICAgICAgIG1heFRleENvb3JkLnggPSBNYXRoLm1heCh0ZXhDb29yZFNjcmF0Y2gueCwgbWF4VGV4Q29vcmQueCk7CiAgICAgICAgbWF4VGV4Q29vcmQueSA9IE1hdGgubWF4KHRleENvb3JkU2NyYXRjaC55LCBtYXhUZXhDb29yZC55KTsKICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXNbdGV4dHVyZUNvb3JkSW5kZXggKyBzdE9mZnNldF0gPSB0ZXhDb29yZFNjcmF0Y2gueDsKICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXNbdGV4dHVyZUNvb3JkSW5kZXggKyAxICsgc3RPZmZzZXRdID0gdGV4Q29vcmRTY3JhdGNoLnk7CiAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW3RleHR1cmVDb29yZEluZGV4KytdID0gdGV4Q29vcmRTY3JhdGNoLng7CiAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW3RleHR1cmVDb29yZEluZGV4KytdID0gdGV4Q29vcmRTY3JhdGNoLnk7CiAgICAgIH0KICAgICAgcG9zaXRpb24gPSBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZShwb3NpdGlvbiwgcG9zaXRpb24pOwogICAgICBleHRydWRlZFBvc2l0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHBvc2l0aW9uLCBzY3JhdGNoQ2FydGVzaWFuMjQpOwogICAgICBub3JtYWwyID0gZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbChwb3NpdGlvbiwgbm9ybWFsMik7CiAgICAgIGlmIChzaGFkb3dWb2x1bWUpIHsKICAgICAgICBleHRydWRlTm9ybWFsc1tpICsgbGVuZ3RoXSA9IC1ub3JtYWwyLng7CiAgICAgICAgZXh0cnVkZU5vcm1hbHNbaTEgKyBsZW5ndGhdID0gLW5vcm1hbDIueTsKICAgICAgICBleHRydWRlTm9ybWFsc1tpMiArIGxlbmd0aF0gPSAtbm9ybWFsMi56OwogICAgICB9CiAgICAgIGxldCBzY2FsZWROb3JtYWwgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICBub3JtYWwyLAogICAgICAgIGhlaWdodCwKICAgICAgICBzY3JhdGNoQ2FydGVzaWFuNAogICAgICApOwogICAgICBwb3NpdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocG9zaXRpb24sIHNjYWxlZE5vcm1hbCwgcG9zaXRpb24pOwogICAgICBzY2FsZWROb3JtYWwgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICBub3JtYWwyLAogICAgICAgIGV4dHJ1ZGVkSGVpZ2h0LAogICAgICAgIHNjYWxlZE5vcm1hbAogICAgICApOwogICAgICBleHRydWRlZFBvc2l0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZCgKICAgICAgICBleHRydWRlZFBvc2l0aW9uLAogICAgICAgIHNjYWxlZE5vcm1hbCwKICAgICAgICBleHRydWRlZFBvc2l0aW9uCiAgICAgICk7CiAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQucG9zaXRpb24pIHsKICAgICAgICBmaW5hbFBvc2l0aW9uc1tpICsgbGVuZ3RoXSA9IGV4dHJ1ZGVkUG9zaXRpb24ueDsKICAgICAgICBmaW5hbFBvc2l0aW9uc1tpMSArIGxlbmd0aF0gPSBleHRydWRlZFBvc2l0aW9uLnk7CiAgICAgICAgZmluYWxQb3NpdGlvbnNbaTIgKyBsZW5ndGhdID0gZXh0cnVkZWRQb3NpdGlvbi56OwogICAgICAgIGZpbmFsUG9zaXRpb25zW2ldID0gcG9zaXRpb24ueDsKICAgICAgICBmaW5hbFBvc2l0aW9uc1tpMV0gPSBwb3NpdGlvbi55OwogICAgICAgIGZpbmFsUG9zaXRpb25zW2kyXSA9IHBvc2l0aW9uLno7CiAgICAgIH0KICAgICAgaWYgKHZlcnRleEZvcm1hdC5ub3JtYWwgfHwgdmVydGV4Rm9ybWF0LnRhbmdlbnQgfHwgdmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgIGJpdGFuZ2VudCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShub3JtYWwyLCBiaXRhbmdlbnQpOwogICAgICAgIGNvbnN0IG5leHQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgKGkgKyAzKSAlIGxlbmd0aCwKICAgICAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW40CiAgICAgICAgKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QobmV4dCwgcG9zaXRpb24sIG5leHQpOwogICAgICAgIGNvbnN0IGJvdHRvbSA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgICAgIGV4dHJ1ZGVkUG9zaXRpb24sCiAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4zNQogICAgICAgICk7CiAgICAgICAgbm9ybWFsMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoYm90dG9tLCBuZXh0LCBub3JtYWwyKSwKICAgICAgICAgIG5vcm1hbDIKICAgICAgICApOwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgICAgICBub3JtYWxzW2ldID0gbm9ybWFsMi54OwogICAgICAgICAgbm9ybWFsc1tpMV0gPSBub3JtYWwyLnk7CiAgICAgICAgICBub3JtYWxzW2kyXSA9IG5vcm1hbDIuejsKICAgICAgICAgIG5vcm1hbHNbaSArIGxlbmd0aF0gPSBub3JtYWwyLng7CiAgICAgICAgICBub3JtYWxzW2kxICsgbGVuZ3RoXSA9IG5vcm1hbDIueTsKICAgICAgICAgIG5vcm1hbHNbaTIgKyBsZW5ndGhdID0gbm9ybWFsMi56OwogICAgICAgIH0KICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQpIHsKICAgICAgICAgIHRhbmdlbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoYml0YW5nZW50LCBub3JtYWwyLCB0YW5nZW50KSwKICAgICAgICAgICAgdGFuZ2VudAogICAgICAgICAgKTsKICAgICAgICAgIHRhbmdlbnRzW2ldID0gdGFuZ2VudC54OwogICAgICAgICAgdGFuZ2VudHNbaTFdID0gdGFuZ2VudC55OwogICAgICAgICAgdGFuZ2VudHNbaTJdID0gdGFuZ2VudC56OwogICAgICAgICAgdGFuZ2VudHNbaSArIGxlbmd0aF0gPSB0YW5nZW50Lng7CiAgICAgICAgICB0YW5nZW50c1tpICsgMSArIGxlbmd0aF0gPSB0YW5nZW50Lnk7CiAgICAgICAgICB0YW5nZW50c1tpICsgMiArIGxlbmd0aF0gPSB0YW5nZW50Lno7CiAgICAgICAgfQogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgICBiaXRhbmdlbnRzW2ldID0gYml0YW5nZW50Lng7CiAgICAgICAgICBiaXRhbmdlbnRzW2kxXSA9IGJpdGFuZ2VudC55OwogICAgICAgICAgYml0YW5nZW50c1tpMl0gPSBiaXRhbmdlbnQuejsKICAgICAgICAgIGJpdGFuZ2VudHNbaSArIGxlbmd0aF0gPSBiaXRhbmdlbnQueDsKICAgICAgICAgIGJpdGFuZ2VudHNbaTEgKyBsZW5ndGhdID0gYml0YW5nZW50Lnk7CiAgICAgICAgICBiaXRhbmdlbnRzW2kyICsgbGVuZ3RoXSA9IGJpdGFuZ2VudC56OwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKHZlcnRleEZvcm1hdC5zdCkgewogICAgICBsZW5ndGggPSB0ZXh0dXJlQ29vcmRpbmF0ZXMubGVuZ3RoOwogICAgICBmb3IgKGxldCBrID0gMDsgayA8IGxlbmd0aDsgayArPSAyKSB7CiAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW2tdID0gKHRleHR1cmVDb29yZGluYXRlc1trXSAtIG1pblRleENvb3JkLngpIC8gKG1heFRleENvb3JkLnggLSBtaW5UZXhDb29yZC54KTsKICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXNbayArIDFdID0gKHRleHR1cmVDb29yZGluYXRlc1trICsgMV0gLSBtaW5UZXhDb29yZC55KSAvIChtYXhUZXhDb29yZC55IC0gbWluVGV4Q29vcmQueSk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoKTsKICAgIGlmICh2ZXJ0ZXhGb3JtYXQucG9zaXRpb24pIHsKICAgICAgYXR0cmlidXRlcy5wb3NpdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IGZpbmFsUG9zaXRpb25zCiAgICAgIH0pOwogICAgfQogICAgaWYgKHZlcnRleEZvcm1hdC5zdCkgewogICAgICBhdHRyaWJ1dGVzLnN0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDIsCiAgICAgICAgdmFsdWVzOiB0ZXh0dXJlQ29vcmRpbmF0ZXMKICAgICAgfSk7CiAgICB9CiAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICBhdHRyaWJ1dGVzLm5vcm1hbCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgIHZhbHVlczogbm9ybWFscwogICAgICB9KTsKICAgIH0KICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICBhdHRyaWJ1dGVzLnRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IHRhbmdlbnRzCiAgICAgIH0pOwogICAgfQogICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgYXR0cmlidXRlcy5iaXRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IGJpdGFuZ2VudHMKICAgICAgfSk7CiAgICB9CiAgICBpZiAoc2hhZG93Vm9sdW1lKSB7CiAgICAgIGF0dHJpYnV0ZXMuZXh0cnVkZURpcmVjdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgIHZhbHVlczogZXh0cnVkZU5vcm1hbHMKICAgICAgfSk7CiAgICB9CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlKSkgewogICAgICBsZXQgb2Zmc2V0QXR0cmlidXRlID0gbmV3IFVpbnQ4QXJyYXkoc2l6ZSk7CiAgICAgIGlmIChvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5UT1ApIHsKICAgICAgICBvZmZzZXRBdHRyaWJ1dGUgPSBvZmZzZXRBdHRyaWJ1dGUuZmlsbCgxLCAwLCBzaXplIC8gMik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3Qgb2Zmc2V0VmFsdWUgPSBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5OT05FID8gMCA6IDE7CiAgICAgICAgb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlLmZpbGwob2Zmc2V0VmFsdWUpOwogICAgICB9CiAgICAgIGF0dHJpYnV0ZXMuYXBwbHlPZmZzZXQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuVU5TSUdORURfQllURSwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAxLAogICAgICAgIHZhbHVlczogb2Zmc2V0QXR0cmlidXRlCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIGF0dHJpYnV0ZXM7CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVXYWxsSW5kaWNlcyhwb3NpdGlvbnMpIHsKICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGggLyAzOwogICAgY29uc3QgaW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KGxlbmd0aCwgbGVuZ3RoICogNik7CiAgICBsZXQgaW5kZXggPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBjb25zdCBVTCA9IGk7CiAgICAgIGNvbnN0IExMID0gaSArIGxlbmd0aDsKICAgICAgY29uc3QgVVIgPSAoVUwgKyAxKSAlIGxlbmd0aDsKICAgICAgY29uc3QgTFIgPSBVUiArIGxlbmd0aDsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IFVMOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gTEw7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBVUjsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IFVSOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gTEw7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBMUjsKICAgIH0KICAgIHJldHVybiBpbmRpY2VzOwogIH0KICBmdW5jdGlvbiBjb21wdXRlRXh0cnVkZWRFbGxpcHNlKG9wdGlvbnMpIHsKICAgIGNvbnN0IGNlbnRlciA9IG9wdGlvbnMuY2VudGVyOwogICAgY29uc3QgZWxsaXBzb2lkID0gb3B0aW9ucy5lbGxpcHNvaWQ7CiAgICBjb25zdCBzZW1pTWFqb3JBeGlzID0gb3B0aW9ucy5zZW1pTWFqb3JBeGlzOwogICAgbGV0IHNjYWxlZE5vcm1hbCA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKGNlbnRlciwgc2NyYXRjaENhcnRlc2lhbjEzKSwKICAgICAgb3B0aW9ucy5oZWlnaHQsCiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4xMwogICAgKTsKICAgIHRvcEJvdW5kaW5nU3BoZXJlLmNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoCiAgICAgIGNlbnRlciwKICAgICAgc2NhbGVkTm9ybWFsLAogICAgICB0b3BCb3VuZGluZ1NwaGVyZS5jZW50ZXIKICAgICk7CiAgICB0b3BCb3VuZGluZ1NwaGVyZS5yYWRpdXMgPSBzZW1pTWFqb3JBeGlzOwogICAgc2NhbGVkTm9ybWFsID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgIGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwoY2VudGVyLCBzY2FsZWROb3JtYWwpLAogICAgICBvcHRpb25zLmV4dHJ1ZGVkSGVpZ2h0LAogICAgICBzY2FsZWROb3JtYWwKICAgICk7CiAgICBib3R0b21Cb3VuZGluZ1NwaGVyZS5jZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKAogICAgICBjZW50ZXIsCiAgICAgIHNjYWxlZE5vcm1hbCwKICAgICAgYm90dG9tQm91bmRpbmdTcGhlcmUuY2VudGVyCiAgICApOwogICAgYm90dG9tQm91bmRpbmdTcGhlcmUucmFkaXVzID0gc2VtaU1ham9yQXhpczsKICAgIGNvbnN0IGNlcCA9IEVsbGlwc2VHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlRWxsaXBzZVBvc2l0aW9ucygKICAgICAgb3B0aW9ucywKICAgICAgdHJ1ZSwKICAgICAgdHJ1ZQogICAgKTsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IGNlcC5wb3NpdGlvbnM7CiAgICBjb25zdCBudW1QdHMgPSBjZXAubnVtUHRzOwogICAgY29uc3Qgb3V0ZXJQb3NpdGlvbnMgPSBjZXAub3V0ZXJQb3NpdGlvbnM7CiAgICBjb25zdCBib3VuZGluZ1NwaGVyZSA9IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQudW5pb24oCiAgICAgIHRvcEJvdW5kaW5nU3BoZXJlLAogICAgICBib3R0b21Cb3VuZGluZ1NwaGVyZQogICAgKTsKICAgIGNvbnN0IHRvcEJvdHRvbUF0dHJpYnV0ZXMgPSBjb21wdXRlVG9wQm90dG9tQXR0cmlidXRlcygKICAgICAgcG9zaXRpb25zLAogICAgICBvcHRpb25zLAogICAgICB0cnVlCiAgICApOwogICAgbGV0IGluZGljZXMgPSB0b3BJbmRpY2VzKG51bVB0cyk7CiAgICBjb25zdCBsZW5ndGggPSBpbmRpY2VzLmxlbmd0aDsKICAgIGluZGljZXMubGVuZ3RoID0gbGVuZ3RoICogMjsKICAgIGNvbnN0IHBvc0xlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGggLyAzOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMykgewogICAgICBpbmRpY2VzW2kgKyBsZW5ndGhdID0gaW5kaWNlc1tpICsgMl0gKyBwb3NMZW5ndGg7CiAgICAgIGluZGljZXNbaSArIDEgKyBsZW5ndGhdID0gaW5kaWNlc1tpICsgMV0gKyBwb3NMZW5ndGg7CiAgICAgIGluZGljZXNbaSArIDIgKyBsZW5ndGhdID0gaW5kaWNlc1tpXSArIHBvc0xlbmd0aDsKICAgIH0KICAgIGNvbnN0IHRvcEJvdHRvbUluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgcG9zTGVuZ3RoICogMiAvIDMsCiAgICAgIGluZGljZXMKICAgICk7CiAgICBjb25zdCB0b3BCb3R0b21HZW8gPSBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgIGF0dHJpYnV0ZXM6IHRvcEJvdHRvbUF0dHJpYnV0ZXMsCiAgICAgIGluZGljZXM6IHRvcEJvdHRvbUluZGljZXMsCiAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5UUklBTkdMRVMKICAgIH0pOwogICAgY29uc3Qgd2FsbEF0dHJpYnV0ZXMgPSBjb21wdXRlV2FsbEF0dHJpYnV0ZXMob3V0ZXJQb3NpdGlvbnMsIG9wdGlvbnMpOwogICAgaW5kaWNlcyA9IGNvbXB1dGVXYWxsSW5kaWNlcyhvdXRlclBvc2l0aW9ucyk7CiAgICBjb25zdCB3YWxsSW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KAogICAgICBvdXRlclBvc2l0aW9ucy5sZW5ndGggKiAyIC8gMywKICAgICAgaW5kaWNlcwogICAgKTsKICAgIGNvbnN0IHdhbGxHZW8gPSBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgIGF0dHJpYnV0ZXM6IHdhbGxBdHRyaWJ1dGVzLAogICAgICBpbmRpY2VzOiB3YWxsSW5kaWNlcywKICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUwogICAgfSk7CiAgICBjb25zdCBnZW8gPSBHZW9tZXRyeVBpcGVsaW5lX2RlZmF1bHQuY29tYmluZUluc3RhbmNlcyhbCiAgICAgIG5ldyBHZW9tZXRyeUluc3RhbmNlX2RlZmF1bHQoewogICAgICAgIGdlb21ldHJ5OiB0b3BCb3R0b21HZW8KICAgICAgfSksCiAgICAgIG5ldyBHZW9tZXRyeUluc3RhbmNlX2RlZmF1bHQoewogICAgICAgIGdlb21ldHJ5OiB3YWxsR2VvCiAgICAgIH0pCiAgICBdKTsKICAgIHJldHVybiB7CiAgICAgIGJvdW5kaW5nU3BoZXJlLAogICAgICBhdHRyaWJ1dGVzOiBnZW9bMF0uYXR0cmlidXRlcywKICAgICAgaW5kaWNlczogZ2VvWzBdLmluZGljZXMKICAgIH07CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVSZWN0YW5nbGUoY2VudGVyLCBzZW1pTWFqb3JBeGlzLCBzZW1pTWlub3JBeGlzLCByb3RhdGlvbiwgZ3JhbnVsYXJpdHksIGVsbGlwc29pZCwgcmVzdWx0KSB7CiAgICBjb25zdCBjZXAgPSBFbGxpcHNlR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZUVsbGlwc2VQb3NpdGlvbnMoCiAgICAgIHsKICAgICAgICBjZW50ZXIsCiAgICAgICAgc2VtaU1ham9yQXhpcywKICAgICAgICBzZW1pTWlub3JBeGlzLAogICAgICAgIHJvdGF0aW9uLAogICAgICAgIGdyYW51bGFyaXR5CiAgICAgIH0sCiAgICAgIGZhbHNlLAogICAgICB0cnVlCiAgICApOwogICAgY29uc3QgcG9zaXRpb25zRmxhdCA9IGNlcC5vdXRlclBvc2l0aW9uczsKICAgIGNvbnN0IHBvc2l0aW9uc0NvdW50ID0gcG9zaXRpb25zRmxhdC5sZW5ndGggLyAzOwogICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEFycmF5KHBvc2l0aW9uc0NvdW50KTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9zaXRpb25zQ291bnQ7ICsraSkgewogICAgICBwb3NpdGlvbnNbaV0gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHBvc2l0aW9uc0ZsYXQsIGkgKiAzKTsKICAgIH0KICAgIGNvbnN0IHJlY3RhbmdsZSA9IFJlY3RhbmdsZV9kZWZhdWx0LmZyb21DYXJ0ZXNpYW5BcnJheShwb3NpdGlvbnMsIGVsbGlwc29pZCwgcmVzdWx0KTsKICAgIGlmIChyZWN0YW5nbGUud2lkdGggPiBNYXRoX2RlZmF1bHQuUEkpIHsKICAgICAgcmVjdGFuZ2xlLm5vcnRoID0gcmVjdGFuZ2xlLm5vcnRoID4gMCA/IE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyAtIE1hdGhfZGVmYXVsdC5FUFNJTE9ONyA6IHJlY3RhbmdsZS5ub3J0aDsKICAgICAgcmVjdGFuZ2xlLnNvdXRoID0gcmVjdGFuZ2xlLnNvdXRoIDwgMCA/IE1hdGhfZGVmYXVsdC5FUFNJTE9ONyAtIE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyA6IHJlY3RhbmdsZS5zb3V0aDsKICAgICAgcmVjdGFuZ2xlLmVhc3QgPSBNYXRoX2RlZmF1bHQuUEk7CiAgICAgIHJlY3RhbmdsZS53ZXN0ID0gLU1hdGhfZGVmYXVsdC5QSTsKICAgIH0KICAgIHJldHVybiByZWN0YW5nbGU7CiAgfQogIGZ1bmN0aW9uIEVsbGlwc2VHZW9tZXRyeShvcHRpb25zKSB7CiAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICBjb25zdCBjZW50ZXIgPSBvcHRpb25zLmNlbnRlcjsKICAgIGNvbnN0IGVsbGlwc29pZCA9IG9wdGlvbnMuZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICBjb25zdCBzZW1pTWFqb3JBeGlzID0gb3B0aW9ucy5zZW1pTWFqb3JBeGlzOwogICAgY29uc3Qgc2VtaU1pbm9yQXhpcyA9IG9wdGlvbnMuc2VtaU1pbm9yQXhpczsKICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gb3B0aW9ucy5ncmFudWxhcml0eSA/PyBNYXRoX2RlZmF1bHQuUkFESUFOU19QRVJfREVHUkVFOwogICAgY29uc3QgdmVydGV4Rm9ybWF0ID0gb3B0aW9ucy52ZXJ0ZXhGb3JtYXQgPz8gVmVydGV4Rm9ybWF0X2RlZmF1bHQuREVGQVVMVDsKICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgib3B0aW9ucy5jZW50ZXIiLCBjZW50ZXIpOwogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJvcHRpb25zLnNlbWlNYWpvckF4aXMiLCBzZW1pTWFqb3JBeGlzKTsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigib3B0aW9ucy5zZW1pTWlub3JBeGlzIiwgc2VtaU1pbm9yQXhpcyk7CiAgICBpZiAoc2VtaU1ham9yQXhpcyA8IHNlbWlNaW5vckF4aXMpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgInNlbWlNYWpvckF4aXMgbXVzdCBiZSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gdGhlIHNlbWlNaW5vckF4aXMuIgogICAgICApOwogICAgfQogICAgaWYgKGdyYW51bGFyaXR5IDw9IDApIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImdyYW51bGFyaXR5IG11c3QgYmUgZ3JlYXRlciB0aGFuIHplcm8uIik7CiAgICB9CiAgICBjb25zdCBoZWlnaHQgPSBvcHRpb25zLmhlaWdodCA/PyAwOwogICAgY29uc3QgZXh0cnVkZWRIZWlnaHQgPSBvcHRpb25zLmV4dHJ1ZGVkSGVpZ2h0ID8/IGhlaWdodDsKICAgIHRoaXMuX2NlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjZW50ZXIpOwogICAgdGhpcy5fc2VtaU1ham9yQXhpcyA9IHNlbWlNYWpvckF4aXM7CiAgICB0aGlzLl9zZW1pTWlub3JBeGlzID0gc2VtaU1pbm9yQXhpczsKICAgIHRoaXMuX2VsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKGVsbGlwc29pZCk7CiAgICB0aGlzLl9yb3RhdGlvbiA9IG9wdGlvbnMucm90YXRpb24gPz8gMDsKICAgIHRoaXMuX3N0Um90YXRpb24gPSBvcHRpb25zLnN0Um90YXRpb24gPz8gMDsKICAgIHRoaXMuX2hlaWdodCA9IE1hdGgubWF4KGV4dHJ1ZGVkSGVpZ2h0LCBoZWlnaHQpOwogICAgdGhpcy5fZ3JhbnVsYXJpdHkgPSBncmFudWxhcml0eTsKICAgIHRoaXMuX3ZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LmNsb25lKHZlcnRleEZvcm1hdCk7CiAgICB0aGlzLl9leHRydWRlZEhlaWdodCA9IE1hdGgubWluKGV4dHJ1ZGVkSGVpZ2h0LCBoZWlnaHQpOwogICAgdGhpcy5fc2hhZG93Vm9sdW1lID0gb3B0aW9ucy5zaGFkb3dWb2x1bWUgPz8gZmFsc2U7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZUVsbGlwc2VHZW9tZXRyeSI7CiAgICB0aGlzLl9vZmZzZXRBdHRyaWJ1dGUgPSBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZTsKICAgIHRoaXMuX3JlY3RhbmdsZSA9IHZvaWQgMDsKICAgIHRoaXMuX3RleHR1cmVDb29yZGluYXRlUm90YXRpb25Qb2ludHMgPSB2b2lkIDA7CiAgfQogIGZ1bmN0aW9uIHRleHR1cmVDb29yZGluYXRlUm90YXRpb25Qb2ludHMoZWxsaXBzZUdlb21ldHJ5KSB7CiAgICBjb25zdCBzdFJvdGF0aW9uID0gLWVsbGlwc2VHZW9tZXRyeS5fc3RSb3RhdGlvbjsKICAgIGlmIChzdFJvdGF0aW9uID09PSAwKSB7CiAgICAgIHJldHVybiBbMCwgMCwgMCwgMSwgMSwgMF07CiAgICB9CiAgICBjb25zdCBjZXAgPSBFbGxpcHNlR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZUVsbGlwc2VQb3NpdGlvbnMoCiAgICAgIHsKICAgICAgICBjZW50ZXI6IGVsbGlwc2VHZW9tZXRyeS5fY2VudGVyLAogICAgICAgIHNlbWlNYWpvckF4aXM6IGVsbGlwc2VHZW9tZXRyeS5fc2VtaU1ham9yQXhpcywKICAgICAgICBzZW1pTWlub3JBeGlzOiBlbGxpcHNlR2VvbWV0cnkuX3NlbWlNaW5vckF4aXMsCiAgICAgICAgcm90YXRpb246IGVsbGlwc2VHZW9tZXRyeS5fcm90YXRpb24sCiAgICAgICAgZ3JhbnVsYXJpdHk6IGVsbGlwc2VHZW9tZXRyeS5fZ3JhbnVsYXJpdHkKICAgICAgfSwKICAgICAgZmFsc2UsCiAgICAgIHRydWUKICAgICk7CiAgICBjb25zdCBwb3NpdGlvbnNGbGF0ID0gY2VwLm91dGVyUG9zaXRpb25zOwogICAgY29uc3QgcG9zaXRpb25zQ291bnQgPSBwb3NpdGlvbnNGbGF0Lmxlbmd0aCAvIDM7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgQXJyYXkocG9zaXRpb25zQ291bnQpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb3NpdGlvbnNDb3VudDsgKytpKSB7CiAgICAgIHBvc2l0aW9uc1tpXSA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkocG9zaXRpb25zRmxhdCwgaSAqIDMpOwogICAgfQogICAgY29uc3QgZWxsaXBzb2lkID0gZWxsaXBzZUdlb21ldHJ5Ll9lbGxpcHNvaWQ7CiAgICBjb25zdCBib3VuZGluZ1JlY3RhbmdsZSA9IGVsbGlwc2VHZW9tZXRyeS5yZWN0YW5nbGU7CiAgICByZXR1cm4gR2VvbWV0cnlfZGVmYXVsdC5fdGV4dHVyZUNvb3JkaW5hdGVSb3RhdGlvblBvaW50cygKICAgICAgcG9zaXRpb25zLAogICAgICBzdFJvdGF0aW9uLAogICAgICBlbGxpcHNvaWQsCiAgICAgIGJvdW5kaW5nUmVjdGFuZ2xlCiAgICApOwogIH0KICB2YXIgc2NyYXRjaENhcnRlc2lhbjEzLCBzY3JhdGNoQ2FydGVzaWFuMjQsIHNjcmF0Y2hDYXJ0ZXNpYW4zNSwgc2NyYXRjaENhcnRlc2lhbjQsIHRleENvb3JkU2NyYXRjaCwgdGV4dHVyZU1hdHJpeFNjcmF0Y2gsIHRhbmdlbnRNYXRyaXhTY3JhdGNoLCBxdWF0ZXJuaW9uU2NyYXRjaCwgc2NyYXRjaE5vcm1hbDMsIHNjcmF0Y2hUYW5nZW50LCBzY3JhdGNoQml0YW5nZW50LCBzY3JhdGNoQ2FydG9ncmFwaGljMiwgcHJvamVjdGVkQ2VudGVyU2NyYXRjaCwgc2NyYXRjaE1pblRleENvb3JkLCBzY3JhdGNoTWF4VGV4Q29vcmQsIGJvdW5kaW5nU3BoZXJlQ2VudGVyLCB0b3BCb3VuZGluZ1NwaGVyZSwgYm90dG9tQm91bmRpbmdTcGhlcmUsIHNjcmF0Y2hDZW50ZXIyLCBzY3JhdGNoRWxsaXBzb2lkLCBzY3JhdGNoVmVydGV4Rm9ybWF0Miwgc2NyYXRjaE9wdGlvbnMzLCBFbGxpcHNlR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9FbGxpcHNlR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0VsbGlwc2VHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4yKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfQ29tcG9uZW50RGF0YXR5cGUoKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9FbGxpcHNlR2VvbWV0cnlMaWJyYXJ5KCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfR2VvZ3JhcGhpY1Byb2plY3Rpb24oKTsKICAgICAgaW5pdF9HZW9tZXRyeSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGVzKCk7CiAgICAgIGluaXRfR2VvbWV0cnlJbnN0YW5jZSgpOwogICAgICBpbml0X0dlb21ldHJ5T2Zmc2V0QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlQaXBlbGluZSgpOwogICAgICBpbml0X0luZGV4RGF0YXR5cGUoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfTWF0cml4MygpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgaW5pdF9RdWF0ZXJuaW9uKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfVmVydGV4Rm9ybWF0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4xMyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjI0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydGVzaWFuMzUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW40ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICB0ZXhDb29yZFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIHRleHR1cmVNYXRyaXhTY3JhdGNoID0gbmV3IE1hdHJpeDNfZGVmYXVsdCgpOwogICAgICB0YW5nZW50TWF0cml4U2NyYXRjaCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgcXVhdGVybmlvblNjcmF0Y2ggPSBuZXcgUXVhdGVybmlvbl9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hOb3JtYWwzID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoVGFuZ2VudCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEJpdGFuZ2VudCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzIgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgcHJvamVjdGVkQ2VudGVyU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE1pblRleENvb3JkID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoTWF4VGV4Q29vcmQgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIGJvdW5kaW5nU3BoZXJlQ2VudGVyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICB0b3BCb3VuZGluZ1NwaGVyZSA9IG5ldyBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0KCk7CiAgICAgIGJvdHRvbUJvdW5kaW5nU3BoZXJlID0gbmV3IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQoKTsKICAgICAgRWxsaXBzZUdlb21ldHJ5LnBhY2tlZExlbmd0aCA9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyA5OwogICAgICBFbGxpcHNlR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHZhbHVlLl9jZW50ZXIsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgRWxsaXBzb2lkX2RlZmF1bHQucGFjayh2YWx1ZS5fZWxsaXBzb2lkLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFjayh2YWx1ZS5fdmVydGV4Rm9ybWF0LCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9zZW1pTWFqb3JBeGlzOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fc2VtaU1pbm9yQXhpczsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX3JvdGF0aW9uOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fc3RSb3RhdGlvbjsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2hlaWdodDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2dyYW51bGFyaXR5OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9zaGFkb3dWb2x1bWUgPyAxIDogMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLl9vZmZzZXRBdHRyaWJ1dGUgPz8gLTE7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBzY3JhdGNoQ2VudGVyMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEVsbGlwc29pZCA9IG5ldyBFbGxpcHNvaWRfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoVmVydGV4Rm9ybWF0MiA9IG5ldyBWZXJ0ZXhGb3JtYXRfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoT3B0aW9uczMgPSB7CiAgICAgICAgY2VudGVyOiBzY3JhdGNoQ2VudGVyMiwKICAgICAgICBlbGxpcHNvaWQ6IHNjcmF0Y2hFbGxpcHNvaWQsCiAgICAgICAgdmVydGV4Rm9ybWF0OiBzY3JhdGNoVmVydGV4Rm9ybWF0MiwKICAgICAgICBzZW1pTWFqb3JBeGlzOiB2b2lkIDAsCiAgICAgICAgc2VtaU1pbm9yQXhpczogdm9pZCAwLAogICAgICAgIHJvdGF0aW9uOiB2b2lkIDAsCiAgICAgICAgc3RSb3RhdGlvbjogdm9pZCAwLAogICAgICAgIGhlaWdodDogdm9pZCAwLAogICAgICAgIGdyYW51bGFyaXR5OiB2b2lkIDAsCiAgICAgICAgZXh0cnVkZWRIZWlnaHQ6IHZvaWQgMCwKICAgICAgICBzaGFkb3dWb2x1bWU6IHZvaWQgMCwKICAgICAgICBvZmZzZXRBdHRyaWJ1dGU6IHZvaWQgMAogICAgICB9OwogICAgICBFbGxpcHNlR2VvbWV0cnkudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBjb25zdCBjZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoQ2VudGVyMik7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCwgc2NyYXRjaEVsbGlwc29pZCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgYXJyYXksCiAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDIKICAgICAgICApOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IHNlbWlNYWpvckF4aXMgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHNlbWlNaW5vckF4aXMgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHJvdGF0aW9uID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBzdFJvdGF0aW9uID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBoZWlnaHQgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3Qgc2hhZG93Vm9sdW1lID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9PT0gMTsKICAgICAgICBjb25zdCBvZmZzZXRBdHRyaWJ1dGUgPSBhcnJheVtzdGFydGluZ0luZGV4XTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczMuaGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMzLmV4dHJ1ZGVkSGVpZ2h0ID0gZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczMuZ3JhbnVsYXJpdHkgPSBncmFudWxhcml0eTsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMy5zdFJvdGF0aW9uID0gc3RSb3RhdGlvbjsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMy5yb3RhdGlvbiA9IHJvdGF0aW9uOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMzLnNlbWlNYWpvckF4aXMgPSBzZW1pTWFqb3JBeGlzOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMzLnNlbWlNaW5vckF4aXMgPSBzZW1pTWlub3JBeGlzOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMzLnNoYWRvd1ZvbHVtZSA9IHNoYWRvd1ZvbHVtZTsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMy5vZmZzZXRBdHRyaWJ1dGUgPSBvZmZzZXRBdHRyaWJ1dGUgPT09IC0xID8gdm9pZCAwIDogb2Zmc2V0QXR0cmlidXRlOwogICAgICAgICAgcmV0dXJuIG5ldyBFbGxpcHNlR2VvbWV0cnkoc2NyYXRjaE9wdGlvbnMzKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0Ll9jZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY2VudGVyLCByZXN1bHQuX2NlbnRlcik7CiAgICAgICAgcmVzdWx0Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShlbGxpcHNvaWQsIHJlc3VsdC5fZWxsaXBzb2lkKTsKICAgICAgICByZXN1bHQuX3ZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LmNsb25lKHZlcnRleEZvcm1hdCwgcmVzdWx0Ll92ZXJ0ZXhGb3JtYXQpOwogICAgICAgIHJlc3VsdC5fc2VtaU1ham9yQXhpcyA9IHNlbWlNYWpvckF4aXM7CiAgICAgICAgcmVzdWx0Ll9zZW1pTWlub3JBeGlzID0gc2VtaU1pbm9yQXhpczsKICAgICAgICByZXN1bHQuX3JvdGF0aW9uID0gcm90YXRpb247CiAgICAgICAgcmVzdWx0Ll9zdFJvdGF0aW9uID0gc3RSb3RhdGlvbjsKICAgICAgICByZXN1bHQuX2hlaWdodCA9IGhlaWdodDsKICAgICAgICByZXN1bHQuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICAgICAgcmVzdWx0Ll9leHRydWRlZEhlaWdodCA9IGV4dHJ1ZGVkSGVpZ2h0OwogICAgICAgIHJlc3VsdC5fc2hhZG93Vm9sdW1lID0gc2hhZG93Vm9sdW1lOwogICAgICAgIHJlc3VsdC5fb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlID09PSAtMSA/IHZvaWQgMCA6IG9mZnNldEF0dHJpYnV0ZTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBFbGxpcHNlR2VvbWV0cnkuY29tcHV0ZVJlY3RhbmdsZSA9IGZ1bmN0aW9uKG9wdGlvbnMsIHJlc3VsdCkgewogICAgICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgICAgICBjb25zdCBjZW50ZXIgPSBvcHRpb25zLmNlbnRlcjsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBvcHRpb25zLmVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgICAgIGNvbnN0IHNlbWlNYWpvckF4aXMgPSBvcHRpb25zLnNlbWlNYWpvckF4aXM7CiAgICAgICAgY29uc3Qgc2VtaU1pbm9yQXhpcyA9IG9wdGlvbnMuc2VtaU1pbm9yQXhpczsKICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IG9wdGlvbnMuZ3JhbnVsYXJpdHkgPz8gTWF0aF9kZWZhdWx0LlJBRElBTlNfUEVSX0RFR1JFRTsKICAgICAgICBjb25zdCByb3RhdGlvbiA9IG9wdGlvbnMucm90YXRpb24gPz8gMDsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoIm9wdGlvbnMuY2VudGVyIiwgY2VudGVyKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoIm9wdGlvbnMuc2VtaU1ham9yQXhpcyIsIHNlbWlNYWpvckF4aXMpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigib3B0aW9ucy5zZW1pTWlub3JBeGlzIiwgc2VtaU1pbm9yQXhpcyk7CiAgICAgICAgaWYgKHNlbWlNYWpvckF4aXMgPCBzZW1pTWlub3JBeGlzKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgInNlbWlNYWpvckF4aXMgbXVzdCBiZSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gdGhlIHNlbWlNaW5vckF4aXMuIgogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgaWYgKGdyYW51bGFyaXR5IDw9IDApIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJncmFudWxhcml0eSBtdXN0IGJlIGdyZWF0ZXIgdGhhbiB6ZXJvLiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gY29tcHV0ZVJlY3RhbmdsZSgKICAgICAgICAgIGNlbnRlciwKICAgICAgICAgIHNlbWlNYWpvckF4aXMsCiAgICAgICAgICBzZW1pTWlub3JBeGlzLAogICAgICAgICAgcm90YXRpb24sCiAgICAgICAgICBncmFudWxhcml0eSwKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIHJlc3VsdAogICAgICAgICk7CiAgICAgIH07CiAgICAgIEVsbGlwc2VHZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKGVsbGlwc2VHZW9tZXRyeSkgewogICAgICAgIGlmIChlbGxpcHNlR2VvbWV0cnkuX3NlbWlNYWpvckF4aXMgPD0gMCB8fCBlbGxpcHNlR2VvbWV0cnkuX3NlbWlNaW5vckF4aXMgPD0gMCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBjb25zdCBoZWlnaHQgPSBlbGxpcHNlR2VvbWV0cnkuX2hlaWdodDsKICAgICAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IGVsbGlwc2VHZW9tZXRyeS5fZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgY29uc3QgZXh0cnVkZSA9ICFNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIGhlaWdodCwKICAgICAgICAgIGV4dHJ1ZGVkSGVpZ2h0LAogICAgICAgICAgMCwKICAgICAgICAgIE1hdGhfZGVmYXVsdC5FUFNJTE9OMgogICAgICAgICk7CiAgICAgICAgZWxsaXBzZUdlb21ldHJ5Ll9jZW50ZXIgPSBlbGxpcHNlR2VvbWV0cnkuX2VsbGlwc29pZC5zY2FsZVRvR2VvZGV0aWNTdXJmYWNlKAogICAgICAgICAgZWxsaXBzZUdlb21ldHJ5Ll9jZW50ZXIsCiAgICAgICAgICBlbGxpcHNlR2VvbWV0cnkuX2NlbnRlcgogICAgICAgICk7CiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHsKICAgICAgICAgIGNlbnRlcjogZWxsaXBzZUdlb21ldHJ5Ll9jZW50ZXIsCiAgICAgICAgICBzZW1pTWFqb3JBeGlzOiBlbGxpcHNlR2VvbWV0cnkuX3NlbWlNYWpvckF4aXMsCiAgICAgICAgICBzZW1pTWlub3JBeGlzOiBlbGxpcHNlR2VvbWV0cnkuX3NlbWlNaW5vckF4aXMsCiAgICAgICAgICBlbGxpcHNvaWQ6IGVsbGlwc2VHZW9tZXRyeS5fZWxsaXBzb2lkLAogICAgICAgICAgcm90YXRpb246IGVsbGlwc2VHZW9tZXRyeS5fcm90YXRpb24sCiAgICAgICAgICBoZWlnaHQsCiAgICAgICAgICBncmFudWxhcml0eTogZWxsaXBzZUdlb21ldHJ5Ll9ncmFudWxhcml0eSwKICAgICAgICAgIHZlcnRleEZvcm1hdDogZWxsaXBzZUdlb21ldHJ5Ll92ZXJ0ZXhGb3JtYXQsCiAgICAgICAgICBzdFJvdGF0aW9uOiBlbGxpcHNlR2VvbWV0cnkuX3N0Um90YXRpb24KICAgICAgICB9OwogICAgICAgIGxldCBnZW9tZXRyeTsKICAgICAgICBpZiAoZXh0cnVkZSkgewogICAgICAgICAgb3B0aW9ucy5leHRydWRlZEhlaWdodCA9IGV4dHJ1ZGVkSGVpZ2h0OwogICAgICAgICAgb3B0aW9ucy5zaGFkb3dWb2x1bWUgPSBlbGxpcHNlR2VvbWV0cnkuX3NoYWRvd1ZvbHVtZTsKICAgICAgICAgIG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlID0gZWxsaXBzZUdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGU7CiAgICAgICAgICBnZW9tZXRyeSA9IGNvbXB1dGVFeHRydWRlZEVsbGlwc2Uob3B0aW9ucyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGdlb21ldHJ5ID0gY29tcHV0ZUVsbGlwc2Uob3B0aW9ucyk7CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGVsbGlwc2VHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlKSkgewogICAgICAgICAgICBjb25zdCBsZW5ndGggPSBnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5sZW5ndGg7CiAgICAgICAgICAgIGNvbnN0IG9mZnNldFZhbHVlID0gZWxsaXBzZUdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuTk9ORSA/IDAgOiAxOwogICAgICAgICAgICBjb25zdCBhcHBseU9mZnNldCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCAvIDMpLmZpbGwob2Zmc2V0VmFsdWUpOwogICAgICAgICAgICBnZW9tZXRyeS5hdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEUsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMSwKICAgICAgICAgICAgICB2YWx1ZXM6IGFwcGx5T2Zmc2V0CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgICAgYXR0cmlidXRlczogZ2VvbWV0cnkuYXR0cmlidXRlcywKICAgICAgICAgIGluZGljZXM6IGdlb21ldHJ5LmluZGljZXMsCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBQcmltaXRpdmVUeXBlX2RlZmF1bHQuVFJJQU5HTEVTLAogICAgICAgICAgYm91bmRpbmdTcGhlcmU6IGdlb21ldHJ5LmJvdW5kaW5nU3BoZXJlLAogICAgICAgICAgb2Zmc2V0QXR0cmlidXRlOiBlbGxpcHNlR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZQogICAgICAgIH0pOwogICAgICB9OwogICAgICBFbGxpcHNlR2VvbWV0cnkuY3JlYXRlU2hhZG93Vm9sdW1lID0gZnVuY3Rpb24oZWxsaXBzZUdlb21ldHJ5LCBtaW5IZWlnaHRGdW5jLCBtYXhIZWlnaHRGdW5jKSB7CiAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBlbGxpcHNlR2VvbWV0cnkuX2dyYW51bGFyaXR5OwogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IGVsbGlwc2VHZW9tZXRyeS5fZWxsaXBzb2lkOwogICAgICAgIGNvbnN0IG1pbkhlaWdodCA9IG1pbkhlaWdodEZ1bmMoZ3JhbnVsYXJpdHksIGVsbGlwc29pZCk7CiAgICAgICAgY29uc3QgbWF4SGVpZ2h0ID0gbWF4SGVpZ2h0RnVuYyhncmFudWxhcml0eSwgZWxsaXBzb2lkKTsKICAgICAgICByZXR1cm4gbmV3IEVsbGlwc2VHZW9tZXRyeSh7CiAgICAgICAgICBjZW50ZXI6IGVsbGlwc2VHZW9tZXRyeS5fY2VudGVyLAogICAgICAgICAgc2VtaU1ham9yQXhpczogZWxsaXBzZUdlb21ldHJ5Ll9zZW1pTWFqb3JBeGlzLAogICAgICAgICAgc2VtaU1pbm9yQXhpczogZWxsaXBzZUdlb21ldHJ5Ll9zZW1pTWlub3JBeGlzLAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgcm90YXRpb246IGVsbGlwc2VHZW9tZXRyeS5fcm90YXRpb24sCiAgICAgICAgICBzdFJvdGF0aW9uOiBlbGxpcHNlR2VvbWV0cnkuX3N0Um90YXRpb24sCiAgICAgICAgICBncmFudWxhcml0eSwKICAgICAgICAgIGV4dHJ1ZGVkSGVpZ2h0OiBtaW5IZWlnaHQsCiAgICAgICAgICBoZWlnaHQ6IG1heEhlaWdodCwKICAgICAgICAgIHZlcnRleEZvcm1hdDogVmVydGV4Rm9ybWF0X2RlZmF1bHQuUE9TSVRJT05fT05MWSwKICAgICAgICAgIHNoYWRvd1ZvbHVtZTogdHJ1ZQogICAgICAgIH0pOwogICAgICB9OwogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhFbGxpcHNlR2VvbWV0cnkucHJvdG90eXBlLCB7CiAgICAgICAgLyoqCiAgICAgICAgICogQHByaXZhdGUKICAgICAgICAgKi8KICAgICAgICByZWN0YW5nbGU6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHRoaXMuX3JlY3RhbmdsZSkpIHsKICAgICAgICAgICAgICB0aGlzLl9yZWN0YW5nbGUgPSBjb21wdXRlUmVjdGFuZ2xlKAogICAgICAgICAgICAgICAgdGhpcy5fY2VudGVyLAogICAgICAgICAgICAgICAgdGhpcy5fc2VtaU1ham9yQXhpcywKICAgICAgICAgICAgICAgIHRoaXMuX3NlbWlNaW5vckF4aXMsCiAgICAgICAgICAgICAgICB0aGlzLl9yb3RhdGlvbiwKICAgICAgICAgICAgICAgIHRoaXMuX2dyYW51bGFyaXR5LAogICAgICAgICAgICAgICAgdGhpcy5fZWxsaXBzb2lkCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdGhpcy5fcmVjdGFuZ2xlOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogRm9yIHJlbWFwcGluZyB0ZXh0dXJlIGNvb3JkaW5hdGVzIHdoZW4gcmVuZGVyaW5nIEVsbGlwc2VHZW9tZXRyaWVzIGFzIEdyb3VuZFByaW1pdGl2ZXMuCiAgICAgICAgICogQHByaXZhdGUKICAgICAgICAgKi8KICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZVJvdGF0aW9uUG9pbnRzOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh0aGlzLl90ZXh0dXJlQ29vcmRpbmF0ZVJvdGF0aW9uUG9pbnRzKSkgewogICAgICAgICAgICAgIHRoaXMuX3RleHR1cmVDb29yZGluYXRlUm90YXRpb25Qb2ludHMgPSB0ZXh0dXJlQ29vcmRpbmF0ZVJvdGF0aW9uUG9pbnRzKHRoaXMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0aGlzLl90ZXh0dXJlQ29vcmRpbmF0ZVJvdGF0aW9uUG9pbnRzOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIEVsbGlwc2VHZW9tZXRyeV9kZWZhdWx0ID0gRWxsaXBzZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ2lyY2xlR2VvbWV0cnkuanMKICBmdW5jdGlvbiBDaXJjbGVHZW9tZXRyeShvcHRpb25zKSB7CiAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICBjb25zdCByYWRpdXMgPSBvcHRpb25zLnJhZGl1czsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigicmFkaXVzIiwgcmFkaXVzKTsKICAgIGNvbnN0IGVsbGlwc2VHZW9tZXRyeU9wdGlvbnMgPSB7CiAgICAgIGNlbnRlcjogb3B0aW9ucy5jZW50ZXIsCiAgICAgIHNlbWlNYWpvckF4aXM6IHJhZGl1cywKICAgICAgc2VtaU1pbm9yQXhpczogcmFkaXVzLAogICAgICBlbGxpcHNvaWQ6IG9wdGlvbnMuZWxsaXBzb2lkLAogICAgICBoZWlnaHQ6IG9wdGlvbnMuaGVpZ2h0LAogICAgICBleHRydWRlZEhlaWdodDogb3B0aW9ucy5leHRydWRlZEhlaWdodCwKICAgICAgZ3JhbnVsYXJpdHk6IG9wdGlvbnMuZ3JhbnVsYXJpdHksCiAgICAgIHZlcnRleEZvcm1hdDogb3B0aW9ucy52ZXJ0ZXhGb3JtYXQsCiAgICAgIHN0Um90YXRpb246IG9wdGlvbnMuc3RSb3RhdGlvbiwKICAgICAgc2hhZG93Vm9sdW1lOiBvcHRpb25zLnNoYWRvd1ZvbHVtZQogICAgfTsKICAgIHRoaXMuX2VsbGlwc2VHZW9tZXRyeSA9IG5ldyBFbGxpcHNlR2VvbWV0cnlfZGVmYXVsdChlbGxpcHNlR2VvbWV0cnlPcHRpb25zKTsKICAgIHRoaXMuX3dvcmtlck5hbWUgPSAiY3JlYXRlQ2lyY2xlR2VvbWV0cnkiOwogIH0KICB2YXIgc2NyYXRjaEVsbGlwc2VHZW9tZXRyeSwgc2NyYXRjaE9wdGlvbnM0LCBDaXJjbGVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X0NpcmNsZUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9DaXJjbGVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc2VHZW9tZXRyeSgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X1ZlcnRleEZvcm1hdCgpOwogICAgICBDaXJjbGVHZW9tZXRyeS5wYWNrZWRMZW5ndGggPSBFbGxpcHNlR2VvbWV0cnlfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgIENpcmNsZUdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIHJldHVybiBFbGxpcHNlR2VvbWV0cnlfZGVmYXVsdC5wYWNrKHZhbHVlLl9lbGxpcHNlR2VvbWV0cnksIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgfTsKICAgICAgc2NyYXRjaEVsbGlwc2VHZW9tZXRyeSA9IG5ldyBFbGxpcHNlR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgICAgY2VudGVyOiBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCksCiAgICAgICAgc2VtaU1ham9yQXhpczogMSwKICAgICAgICBzZW1pTWlub3JBeGlzOiAxCiAgICAgIH0pOwogICAgICBzY3JhdGNoT3B0aW9uczQgPSB7CiAgICAgICAgY2VudGVyOiBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCksCiAgICAgICAgcmFkaXVzOiB2b2lkIDAsCiAgICAgICAgZWxsaXBzb2lkOiBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0KSwKICAgICAgICBoZWlnaHQ6IHZvaWQgMCwKICAgICAgICBleHRydWRlZEhlaWdodDogdm9pZCAwLAogICAgICAgIGdyYW51bGFyaXR5OiB2b2lkIDAsCiAgICAgICAgdmVydGV4Rm9ybWF0OiBuZXcgVmVydGV4Rm9ybWF0X2RlZmF1bHQoKSwKICAgICAgICBzdFJvdGF0aW9uOiB2b2lkIDAsCiAgICAgICAgc2VtaU1ham9yQXhpczogdm9pZCAwLAogICAgICAgIHNlbWlNaW5vckF4aXM6IHZvaWQgMCwKICAgICAgICBzaGFkb3dWb2x1bWU6IHZvaWQgMAogICAgICB9OwogICAgICBDaXJjbGVHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgY29uc3QgZWxsaXBzZUdlb21ldHJ5ID0gRWxsaXBzZUdlb21ldHJ5X2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgYXJyYXksCiAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgc2NyYXRjaEVsbGlwc2VHZW9tZXRyeQogICAgICAgICk7CiAgICAgICAgc2NyYXRjaE9wdGlvbnM0LmNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZSgKICAgICAgICAgIGVsbGlwc2VHZW9tZXRyeS5fY2VudGVyLAogICAgICAgICAgc2NyYXRjaE9wdGlvbnM0LmNlbnRlcgogICAgICAgICk7CiAgICAgICAgc2NyYXRjaE9wdGlvbnM0LmVsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKAogICAgICAgICAgZWxsaXBzZUdlb21ldHJ5Ll9lbGxpcHNvaWQsCiAgICAgICAgICBzY3JhdGNoT3B0aW9uczQuZWxsaXBzb2lkCiAgICAgICAgKTsKICAgICAgICBzY3JhdGNoT3B0aW9uczQuZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoCiAgICAgICAgICBlbGxpcHNlR2VvbWV0cnkuX2VsbGlwc29pZCwKICAgICAgICAgIHNjcmF0Y2hFbGxpcHNlR2VvbWV0cnkuX2VsbGlwc29pZAogICAgICAgICk7CiAgICAgICAgc2NyYXRjaE9wdGlvbnM0LmhlaWdodCA9IGVsbGlwc2VHZW9tZXRyeS5faGVpZ2h0OwogICAgICAgIHNjcmF0Y2hPcHRpb25zNC5leHRydWRlZEhlaWdodCA9IGVsbGlwc2VHZW9tZXRyeS5fZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgc2NyYXRjaE9wdGlvbnM0LmdyYW51bGFyaXR5ID0gZWxsaXBzZUdlb21ldHJ5Ll9ncmFudWxhcml0eTsKICAgICAgICBzY3JhdGNoT3B0aW9uczQudmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQuY2xvbmUoCiAgICAgICAgICBlbGxpcHNlR2VvbWV0cnkuX3ZlcnRleEZvcm1hdCwKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zNC52ZXJ0ZXhGb3JtYXQKICAgICAgICApOwogICAgICAgIHNjcmF0Y2hPcHRpb25zNC5zdFJvdGF0aW9uID0gZWxsaXBzZUdlb21ldHJ5Ll9zdFJvdGF0aW9uOwogICAgICAgIHNjcmF0Y2hPcHRpb25zNC5zaGFkb3dWb2x1bWUgPSBlbGxpcHNlR2VvbWV0cnkuX3NoYWRvd1ZvbHVtZTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczQucmFkaXVzID0gZWxsaXBzZUdlb21ldHJ5Ll9zZW1pTWFqb3JBeGlzOwogICAgICAgICAgcmV0dXJuIG5ldyBDaXJjbGVHZW9tZXRyeShzY3JhdGNoT3B0aW9uczQpOwogICAgICAgIH0KICAgICAgICBzY3JhdGNoT3B0aW9uczQuc2VtaU1ham9yQXhpcyA9IGVsbGlwc2VHZW9tZXRyeS5fc2VtaU1ham9yQXhpczsKICAgICAgICBzY3JhdGNoT3B0aW9uczQuc2VtaU1pbm9yQXhpcyA9IGVsbGlwc2VHZW9tZXRyeS5fc2VtaU1pbm9yQXhpczsKICAgICAgICByZXN1bHQuX2VsbGlwc2VHZW9tZXRyeSA9IG5ldyBFbGxpcHNlR2VvbWV0cnlfZGVmYXVsdChzY3JhdGNoT3B0aW9uczQpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENpcmNsZUdlb21ldHJ5LmNyZWF0ZUdlb21ldHJ5ID0gZnVuY3Rpb24oY2lyY2xlR2VvbWV0cnkpIHsKICAgICAgICByZXR1cm4gRWxsaXBzZUdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkoY2lyY2xlR2VvbWV0cnkuX2VsbGlwc2VHZW9tZXRyeSk7CiAgICAgIH07CiAgICAgIENpcmNsZUdlb21ldHJ5LmNyZWF0ZVNoYWRvd1ZvbHVtZSA9IGZ1bmN0aW9uKGNpcmNsZUdlb21ldHJ5LCBtaW5IZWlnaHRGdW5jLCBtYXhIZWlnaHRGdW5jKSB7CiAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBjaXJjbGVHZW9tZXRyeS5fZWxsaXBzZUdlb21ldHJ5Ll9ncmFudWxhcml0eTsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBjaXJjbGVHZW9tZXRyeS5fZWxsaXBzZUdlb21ldHJ5Ll9lbGxpcHNvaWQ7CiAgICAgICAgY29uc3QgbWluSGVpZ2h0ID0gbWluSGVpZ2h0RnVuYyhncmFudWxhcml0eSwgZWxsaXBzb2lkKTsKICAgICAgICBjb25zdCBtYXhIZWlnaHQgPSBtYXhIZWlnaHRGdW5jKGdyYW51bGFyaXR5LCBlbGxpcHNvaWQpOwogICAgICAgIHJldHVybiBuZXcgQ2lyY2xlR2VvbWV0cnkoewogICAgICAgICAgY2VudGVyOiBjaXJjbGVHZW9tZXRyeS5fZWxsaXBzZUdlb21ldHJ5Ll9jZW50ZXIsCiAgICAgICAgICByYWRpdXM6IGNpcmNsZUdlb21ldHJ5Ll9lbGxpcHNlR2VvbWV0cnkuX3NlbWlNYWpvckF4aXMsCiAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICBzdFJvdGF0aW9uOiBjaXJjbGVHZW9tZXRyeS5fZWxsaXBzZUdlb21ldHJ5Ll9zdFJvdGF0aW9uLAogICAgICAgICAgZ3JhbnVsYXJpdHksCiAgICAgICAgICBleHRydWRlZEhlaWdodDogbWluSGVpZ2h0LAogICAgICAgICAgaGVpZ2h0OiBtYXhIZWlnaHQsCiAgICAgICAgICB2ZXJ0ZXhGb3JtYXQ6IFZlcnRleEZvcm1hdF9kZWZhdWx0LlBPU0lUSU9OX09OTFksCiAgICAgICAgICBzaGFkb3dWb2x1bWU6IHRydWUKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoQ2lyY2xlR2VvbWV0cnkucHJvdG90eXBlLCB7CiAgICAgICAgLyoqCiAgICAgICAgICogQHByaXZhdGUKICAgICAgICAgKi8KICAgICAgICByZWN0YW5nbGU6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9lbGxpcHNlR2VvbWV0cnkucmVjdGFuZ2xlOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogRm9yIHJlbWFwcGluZyB0ZXh0dXJlIGNvb3JkaW5hdGVzIHdoZW4gcmVuZGVyaW5nIENpcmNsZUdlb21ldHJpZXMgYXMgR3JvdW5kUHJpbWl0aXZlcy4KICAgICAgICAgKiBAcHJpdmF0ZQogICAgICAgICAqLwogICAgICAgIHRleHR1cmVDb29yZGluYXRlUm90YXRpb25Qb2ludHM6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9lbGxpcHNlR2VvbWV0cnkudGV4dHVyZUNvb3JkaW5hdGVSb3RhdGlvblBvaW50czsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBDaXJjbGVHZW9tZXRyeV9kZWZhdWx0ID0gQ2lyY2xlR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVDaXJjbGVHZW9tZXRyeS5qcwogIHZhciBjcmVhdGVDaXJjbGVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlQ2lyY2xlR2VvbWV0cnlfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlQ2lyY2xlR2VvbWV0cnlfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZUNpcmNsZUdlb21ldHJ5KGNpcmNsZUdlb21ldHJ5LCBvZmZzZXQpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob2Zmc2V0KSkgewogICAgICBjaXJjbGVHZW9tZXRyeSA9IENpcmNsZUdlb21ldHJ5X2RlZmF1bHQudW5wYWNrKGNpcmNsZUdlb21ldHJ5LCBvZmZzZXQpOwogICAgfQogICAgY2lyY2xlR2VvbWV0cnkuX2VsbGlwc2VHZW9tZXRyeS5fY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKAogICAgICBjaXJjbGVHZW9tZXRyeS5fZWxsaXBzZUdlb21ldHJ5Ll9jZW50ZXIKICAgICk7CiAgICBjaXJjbGVHZW9tZXRyeS5fZWxsaXBzZUdlb21ldHJ5Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZSgKICAgICAgY2lyY2xlR2VvbWV0cnkuX2VsbGlwc2VHZW9tZXRyeS5fZWxsaXBzb2lkCiAgICApOwogICAgcmV0dXJuIENpcmNsZUdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkoY2lyY2xlR2VvbWV0cnkpOwogIH0KICB2YXIgY3JlYXRlQ2lyY2xlR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVDaXJjbGVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlQ2lyY2xlR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaXJjbGVHZW9tZXRyeSgpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgY3JlYXRlQ2lyY2xlR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZUNpcmNsZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvRWxsaXBzZU91dGxpbmVHZW9tZXRyeS5qcwogIGZ1bmN0aW9uIGNvbXB1dGVFbGxpcHNlMihvcHRpb25zKSB7CiAgICBjb25zdCBjZW50ZXIgPSBvcHRpb25zLmNlbnRlcjsKICAgIGJvdW5kaW5nU3BoZXJlQ2VudGVyMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICBvcHRpb25zLmVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwoY2VudGVyLCBib3VuZGluZ1NwaGVyZUNlbnRlcjIpLAogICAgICBvcHRpb25zLmhlaWdodCwKICAgICAgYm91bmRpbmdTcGhlcmVDZW50ZXIyCiAgICApOwogICAgYm91bmRpbmdTcGhlcmVDZW50ZXIyID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZCgKICAgICAgY2VudGVyLAogICAgICBib3VuZGluZ1NwaGVyZUNlbnRlcjIsCiAgICAgIGJvdW5kaW5nU3BoZXJlQ2VudGVyMgogICAgKTsKICAgIGNvbnN0IGJvdW5kaW5nU3BoZXJlID0gbmV3IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQoCiAgICAgIGJvdW5kaW5nU3BoZXJlQ2VudGVyMiwKICAgICAgb3B0aW9ucy5zZW1pTWFqb3JBeGlzCiAgICApOwogICAgY29uc3QgcG9zaXRpb25zID0gRWxsaXBzZUdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVFbGxpcHNlUG9zaXRpb25zKAogICAgICBvcHRpb25zLAogICAgICBmYWxzZSwKICAgICAgdHJ1ZQogICAgKS5vdXRlclBvc2l0aW9uczsKICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoewogICAgICBwb3NpdGlvbjogbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgIHZhbHVlczogRWxsaXBzZUdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LnJhaXNlUG9zaXRpb25zVG9IZWlnaHQoCiAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICBvcHRpb25zLAogICAgICAgICAgZmFsc2UKICAgICAgICApCiAgICAgIH0pCiAgICB9KTsKICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGggLyAzOwogICAgY29uc3QgaW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KGxlbmd0aCwgbGVuZ3RoICogMik7CiAgICBsZXQgaW5kZXggPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBpbmRpY2VzW2luZGV4KytdID0gaTsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IChpICsgMSkgJSBsZW5ndGg7CiAgICB9CiAgICByZXR1cm4gewogICAgICBib3VuZGluZ1NwaGVyZSwKICAgICAgYXR0cmlidXRlcywKICAgICAgaW5kaWNlcwogICAgfTsKICB9CiAgZnVuY3Rpb24gY29tcHV0ZUV4dHJ1ZGVkRWxsaXBzZTIob3B0aW9ucykgewogICAgY29uc3QgY2VudGVyID0gb3B0aW9ucy5jZW50ZXI7CiAgICBjb25zdCBlbGxpcHNvaWQgPSBvcHRpb25zLmVsbGlwc29pZDsKICAgIGNvbnN0IHNlbWlNYWpvckF4aXMgPSBvcHRpb25zLnNlbWlNYWpvckF4aXM7CiAgICBsZXQgc2NhbGVkTm9ybWFsID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgIGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwoY2VudGVyLCBzY3JhdGNoQ2FydGVzaWFuMTQpLAogICAgICBvcHRpb25zLmhlaWdodCwKICAgICAgc2NyYXRjaENhcnRlc2lhbjE0CiAgICApOwogICAgdG9wQm91bmRpbmdTcGhlcmUyLmNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoCiAgICAgIGNlbnRlciwKICAgICAgc2NhbGVkTm9ybWFsLAogICAgICB0b3BCb3VuZGluZ1NwaGVyZTIuY2VudGVyCiAgICApOwogICAgdG9wQm91bmRpbmdTcGhlcmUyLnJhZGl1cyA9IHNlbWlNYWpvckF4aXM7CiAgICBzY2FsZWROb3JtYWwgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbChjZW50ZXIsIHNjYWxlZE5vcm1hbCksCiAgICAgIG9wdGlvbnMuZXh0cnVkZWRIZWlnaHQsCiAgICAgIHNjYWxlZE5vcm1hbAogICAgKTsKICAgIGJvdHRvbUJvdW5kaW5nU3BoZXJlMi5jZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKAogICAgICBjZW50ZXIsCiAgICAgIHNjYWxlZE5vcm1hbCwKICAgICAgYm90dG9tQm91bmRpbmdTcGhlcmUyLmNlbnRlcgogICAgKTsKICAgIGJvdHRvbUJvdW5kaW5nU3BoZXJlMi5yYWRpdXMgPSBzZW1pTWFqb3JBeGlzOwogICAgbGV0IHBvc2l0aW9ucyA9IEVsbGlwc2VHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlRWxsaXBzZVBvc2l0aW9ucygKICAgICAgb3B0aW9ucywKICAgICAgZmFsc2UsCiAgICAgIHRydWUKICAgICkub3V0ZXJQb3NpdGlvbnM7CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlc19kZWZhdWx0KHsKICAgICAgcG9zaXRpb246IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IEVsbGlwc2VHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5yYWlzZVBvc2l0aW9uc1RvSGVpZ2h0KAogICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgb3B0aW9ucywKICAgICAgICAgIHRydWUKICAgICAgICApCiAgICAgIH0pCiAgICB9KTsKICAgIHBvc2l0aW9ucyA9IGF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzOwogICAgY29uc3QgYm91bmRpbmdTcGhlcmUgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LnVuaW9uKAogICAgICB0b3BCb3VuZGluZ1NwaGVyZTIsCiAgICAgIGJvdHRvbUJvdW5kaW5nU3BoZXJlMgogICAgKTsKICAgIGxldCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoIC8gMzsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGUpKSB7CiAgICAgIGxldCBhcHBseU9mZnNldCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCk7CiAgICAgIGlmIChvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5UT1ApIHsKICAgICAgICBhcHBseU9mZnNldCA9IGFwcGx5T2Zmc2V0LmZpbGwoMSwgMCwgbGVuZ3RoIC8gMik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3Qgb2Zmc2V0VmFsdWUgPSBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5OT05FID8gMCA6IDE7CiAgICAgICAgYXBwbHlPZmZzZXQgPSBhcHBseU9mZnNldC5maWxsKG9mZnNldFZhbHVlKTsKICAgICAgfQogICAgICBhdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEUsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMSwKICAgICAgICB2YWx1ZXM6IGFwcGx5T2Zmc2V0CiAgICAgIH0pOwogICAgfQogICAgbGV0IG51bWJlck9mVmVydGljYWxMaW5lcyA9IG9wdGlvbnMubnVtYmVyT2ZWZXJ0aWNhbExpbmVzID8/IDE2OwogICAgbnVtYmVyT2ZWZXJ0aWNhbExpbmVzID0gTWF0aF9kZWZhdWx0LmNsYW1wKAogICAgICBudW1iZXJPZlZlcnRpY2FsTGluZXMsCiAgICAgIDAsCiAgICAgIGxlbmd0aCAvIDIKICAgICk7CiAgICBjb25zdCBpbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgIGxlbmd0aCwKICAgICAgbGVuZ3RoICogMiArIG51bWJlck9mVmVydGljYWxMaW5lcyAqIDIKICAgICk7CiAgICBsZW5ndGggLz0gMjsKICAgIGxldCBpbmRleCA9IDA7CiAgICBsZXQgaTsKICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBpbmRpY2VzW2luZGV4KytdID0gaTsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IChpICsgMSkgJSBsZW5ndGg7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpICsgbGVuZ3RoOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gKGkgKyAxKSAlIGxlbmd0aCArIGxlbmd0aDsKICAgIH0KICAgIGxldCBudW1TaWRlOwogICAgaWYgKG51bWJlck9mVmVydGljYWxMaW5lcyA+IDApIHsKICAgICAgY29uc3QgbnVtU2lkZUxpbmVzID0gTWF0aC5taW4obnVtYmVyT2ZWZXJ0aWNhbExpbmVzLCBsZW5ndGgpOwogICAgICBudW1TaWRlID0gTWF0aC5yb3VuZChsZW5ndGggLyBudW1TaWRlTGluZXMpOwogICAgICBjb25zdCBtYXhJID0gTWF0aC5taW4obnVtU2lkZSAqIG51bWJlck9mVmVydGljYWxMaW5lcywgbGVuZ3RoKTsKICAgICAgZm9yIChpID0gMDsgaSA8IG1heEk7IGkgKz0gbnVtU2lkZSkgewogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpICsgbGVuZ3RoOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gewogICAgICBib3VuZGluZ1NwaGVyZSwKICAgICAgYXR0cmlidXRlcywKICAgICAgaW5kaWNlcwogICAgfTsKICB9CiAgZnVuY3Rpb24gRWxsaXBzZU91dGxpbmVHZW9tZXRyeShvcHRpb25zKSB7CiAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICBjb25zdCBjZW50ZXIgPSBvcHRpb25zLmNlbnRlcjsKICAgIGNvbnN0IGVsbGlwc29pZCA9IG9wdGlvbnMuZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICBjb25zdCBzZW1pTWFqb3JBeGlzID0gb3B0aW9ucy5zZW1pTWFqb3JBeGlzOwogICAgY29uc3Qgc2VtaU1pbm9yQXhpcyA9IG9wdGlvbnMuc2VtaU1pbm9yQXhpczsKICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gb3B0aW9ucy5ncmFudWxhcml0eSA/PyBNYXRoX2RlZmF1bHQuUkFESUFOU19QRVJfREVHUkVFOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoY2VudGVyKSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiY2VudGVyIGlzIHJlcXVpcmVkLiIpOwogICAgfQogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoc2VtaU1ham9yQXhpcykpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInNlbWlNYWpvckF4aXMgaXMgcmVxdWlyZWQuIik7CiAgICB9CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChzZW1pTWlub3JBeGlzKSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgic2VtaU1pbm9yQXhpcyBpcyByZXF1aXJlZC4iKTsKICAgIH0KICAgIGlmIChzZW1pTWFqb3JBeGlzIDwgc2VtaU1pbm9yQXhpcykgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAic2VtaU1ham9yQXhpcyBtdXN0IGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byB0aGUgc2VtaU1pbm9yQXhpcy4iCiAgICAgICk7CiAgICB9CiAgICBpZiAoZ3JhbnVsYXJpdHkgPD0gMCkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZ3JhbnVsYXJpdHkgbXVzdCBiZSBncmVhdGVyIHRoYW4gemVyby4iKTsKICAgIH0KICAgIGNvbnN0IGhlaWdodCA9IG9wdGlvbnMuaGVpZ2h0ID8/IDA7CiAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IG9wdGlvbnMuZXh0cnVkZWRIZWlnaHQgPz8gaGVpZ2h0OwogICAgdGhpcy5fY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGNlbnRlcik7CiAgICB0aGlzLl9zZW1pTWFqb3JBeGlzID0gc2VtaU1ham9yQXhpczsKICAgIHRoaXMuX3NlbWlNaW5vckF4aXMgPSBzZW1pTWlub3JBeGlzOwogICAgdGhpcy5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoZWxsaXBzb2lkKTsKICAgIHRoaXMuX3JvdGF0aW9uID0gb3B0aW9ucy5yb3RhdGlvbiA/PyAwOwogICAgdGhpcy5faGVpZ2h0ID0gTWF0aC5tYXgoZXh0cnVkZWRIZWlnaHQsIGhlaWdodCk7CiAgICB0aGlzLl9ncmFudWxhcml0eSA9IGdyYW51bGFyaXR5OwogICAgdGhpcy5fZXh0cnVkZWRIZWlnaHQgPSBNYXRoLm1pbihleHRydWRlZEhlaWdodCwgaGVpZ2h0KTsKICAgIHRoaXMuX251bWJlck9mVmVydGljYWxMaW5lcyA9IE1hdGgubWF4KAogICAgICBvcHRpb25zLm51bWJlck9mVmVydGljYWxMaW5lcyA/PyAxNiwKICAgICAgMAogICAgKTsKICAgIHRoaXMuX29mZnNldEF0dHJpYnV0ZSA9IG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlOwogICAgdGhpcy5fd29ya2VyTmFtZSA9ICJjcmVhdGVFbGxpcHNlT3V0bGluZUdlb21ldHJ5IjsKICB9CiAgdmFyIHNjcmF0Y2hDYXJ0ZXNpYW4xNCwgYm91bmRpbmdTcGhlcmVDZW50ZXIyLCB0b3BCb3VuZGluZ1NwaGVyZTIsIGJvdHRvbUJvdW5kaW5nU3BoZXJlMiwgc2NyYXRjaENlbnRlcjMsIHNjcmF0Y2hFbGxpcHNvaWQyLCBzY3JhdGNoT3B0aW9uczUsIEVsbGlwc2VPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9FbGxpcHNlT3V0bGluZUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9FbGxpcHNlT3V0bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0VsbGlwc2VHZW9tZXRyeUxpYnJhcnkoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9HZW9tZXRyeSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGVzKCk7CiAgICAgIGluaXRfR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjE0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBib3VuZGluZ1NwaGVyZUNlbnRlcjIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHRvcEJvdW5kaW5nU3BoZXJlMiA9IG5ldyBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0KCk7CiAgICAgIGJvdHRvbUJvdW5kaW5nU3BoZXJlMiA9IG5ldyBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0KCk7CiAgICAgIEVsbGlwc2VPdXRsaW5lR2VvbWV0cnkucGFja2VkTGVuZ3RoID0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCArIEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIDg7CiAgICAgIEVsbGlwc2VPdXRsaW5lR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHZhbHVlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInZhbHVlIGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFycmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2sodmFsdWUuX2NlbnRlciwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrKHZhbHVlLl9lbGxpcHNvaWQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX3NlbWlNYWpvckF4aXM7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9zZW1pTWlub3JBeGlzOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fcm90YXRpb247CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9oZWlnaHQ7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9ncmFudWxhcml0eTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2V4dHJ1ZGVkSGVpZ2h0OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fbnVtYmVyT2ZWZXJ0aWNhbExpbmVzOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXhdID0gdmFsdWUuX29mZnNldEF0dHJpYnV0ZSA/PyAtMTsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hDZW50ZXIzID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoRWxsaXBzb2lkMiA9IG5ldyBFbGxpcHNvaWRfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoT3B0aW9uczUgPSB7CiAgICAgICAgY2VudGVyOiBzY3JhdGNoQ2VudGVyMywKICAgICAgICBlbGxpcHNvaWQ6IHNjcmF0Y2hFbGxpcHNvaWQyLAogICAgICAgIHNlbWlNYWpvckF4aXM6IHZvaWQgMCwKICAgICAgICBzZW1pTWlub3JBeGlzOiB2b2lkIDAsCiAgICAgICAgcm90YXRpb246IHZvaWQgMCwKICAgICAgICBoZWlnaHQ6IHZvaWQgMCwKICAgICAgICBncmFudWxhcml0eTogdm9pZCAwLAogICAgICAgIGV4dHJ1ZGVkSGVpZ2h0OiB2b2lkIDAsCiAgICAgICAgbnVtYmVyT2ZWZXJ0aWNhbExpbmVzOiB2b2lkIDAsCiAgICAgICAgb2Zmc2V0QXR0cmlidXRlOiB2b2lkIDAKICAgICAgfTsKICAgICAgRWxsaXBzZU91dGxpbmVHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYXJyYXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYXJyYXkgaXMgcmVxdWlyZWQiKTsKICAgICAgICB9CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBjb25zdCBjZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoQ2VudGVyMyk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCwgc2NyYXRjaEVsbGlwc29pZDIpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IHNlbWlNYWpvckF4aXMgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHNlbWlNaW5vckF4aXMgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHJvdGF0aW9uID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBoZWlnaHQgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgbnVtYmVyT2ZWZXJ0aWNhbExpbmVzID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBvZmZzZXRBdHRyaWJ1dGUgPSBhcnJheVtzdGFydGluZ0luZGV4XTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczUuaGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgICAgc2NyYXRjaE9wdGlvbnM1LmV4dHJ1ZGVkSGVpZ2h0ID0gZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczUuZ3JhbnVsYXJpdHkgPSBncmFudWxhcml0eTsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zNS5yb3RhdGlvbiA9IHJvdGF0aW9uOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnM1LnNlbWlNYWpvckF4aXMgPSBzZW1pTWFqb3JBeGlzOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnM1LnNlbWlNaW5vckF4aXMgPSBzZW1pTWlub3JBeGlzOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnM1Lm51bWJlck9mVmVydGljYWxMaW5lcyA9IG51bWJlck9mVmVydGljYWxMaW5lczsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zNS5vZmZzZXRBdHRyaWJ1dGUgPSBvZmZzZXRBdHRyaWJ1dGUgPT09IC0xID8gdm9pZCAwIDogb2Zmc2V0QXR0cmlidXRlOwogICAgICAgICAgcmV0dXJuIG5ldyBFbGxpcHNlT3V0bGluZUdlb21ldHJ5KHNjcmF0Y2hPcHRpb25zNSk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5fY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGNlbnRlciwgcmVzdWx0Ll9jZW50ZXIpOwogICAgICAgIHJlc3VsdC5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoZWxsaXBzb2lkLCByZXN1bHQuX2VsbGlwc29pZCk7CiAgICAgICAgcmVzdWx0Ll9zZW1pTWFqb3JBeGlzID0gc2VtaU1ham9yQXhpczsKICAgICAgICByZXN1bHQuX3NlbWlNaW5vckF4aXMgPSBzZW1pTWlub3JBeGlzOwogICAgICAgIHJlc3VsdC5fcm90YXRpb24gPSByb3RhdGlvbjsKICAgICAgICByZXN1bHQuX2hlaWdodCA9IGhlaWdodDsKICAgICAgICByZXN1bHQuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICAgICAgcmVzdWx0Ll9leHRydWRlZEhlaWdodCA9IGV4dHJ1ZGVkSGVpZ2h0OwogICAgICAgIHJlc3VsdC5fbnVtYmVyT2ZWZXJ0aWNhbExpbmVzID0gbnVtYmVyT2ZWZXJ0aWNhbExpbmVzOwogICAgICAgIHJlc3VsdC5fb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlID09PSAtMSA/IHZvaWQgMCA6IG9mZnNldEF0dHJpYnV0ZTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBFbGxpcHNlT3V0bGluZUdlb21ldHJ5LmNyZWF0ZUdlb21ldHJ5ID0gZnVuY3Rpb24oZWxsaXBzZUdlb21ldHJ5KSB7CiAgICAgICAgaWYgKGVsbGlwc2VHZW9tZXRyeS5fc2VtaU1ham9yQXhpcyA8PSAwIHx8IGVsbGlwc2VHZW9tZXRyeS5fc2VtaU1pbm9yQXhpcyA8PSAwKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IGhlaWdodCA9IGVsbGlwc2VHZW9tZXRyeS5faGVpZ2h0OwogICAgICAgIGNvbnN0IGV4dHJ1ZGVkSGVpZ2h0ID0gZWxsaXBzZUdlb21ldHJ5Ll9leHRydWRlZEhlaWdodDsKICAgICAgICBjb25zdCBleHRydWRlID0gIU1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgaGVpZ2h0LAogICAgICAgICAgZXh0cnVkZWRIZWlnaHQsCiAgICAgICAgICAwLAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04yCiAgICAgICAgKTsKICAgICAgICBlbGxpcHNlR2VvbWV0cnkuX2NlbnRlciA9IGVsbGlwc2VHZW9tZXRyeS5fZWxsaXBzb2lkLnNjYWxlVG9HZW9kZXRpY1N1cmZhY2UoCiAgICAgICAgICBlbGxpcHNlR2VvbWV0cnkuX2NlbnRlciwKICAgICAgICAgIGVsbGlwc2VHZW9tZXRyeS5fY2VudGVyCiAgICAgICAgKTsKICAgICAgICBjb25zdCBvcHRpb25zID0gewogICAgICAgICAgY2VudGVyOiBlbGxpcHNlR2VvbWV0cnkuX2NlbnRlciwKICAgICAgICAgIHNlbWlNYWpvckF4aXM6IGVsbGlwc2VHZW9tZXRyeS5fc2VtaU1ham9yQXhpcywKICAgICAgICAgIHNlbWlNaW5vckF4aXM6IGVsbGlwc2VHZW9tZXRyeS5fc2VtaU1pbm9yQXhpcywKICAgICAgICAgIGVsbGlwc29pZDogZWxsaXBzZUdlb21ldHJ5Ll9lbGxpcHNvaWQsCiAgICAgICAgICByb3RhdGlvbjogZWxsaXBzZUdlb21ldHJ5Ll9yb3RhdGlvbiwKICAgICAgICAgIGhlaWdodCwKICAgICAgICAgIGdyYW51bGFyaXR5OiBlbGxpcHNlR2VvbWV0cnkuX2dyYW51bGFyaXR5LAogICAgICAgICAgbnVtYmVyT2ZWZXJ0aWNhbExpbmVzOiBlbGxpcHNlR2VvbWV0cnkuX251bWJlck9mVmVydGljYWxMaW5lcwogICAgICAgIH07CiAgICAgICAgbGV0IGdlb21ldHJ5OwogICAgICAgIGlmIChleHRydWRlKSB7CiAgICAgICAgICBvcHRpb25zLmV4dHJ1ZGVkSGVpZ2h0ID0gZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgICBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSA9IGVsbGlwc2VHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlOwogICAgICAgICAgZ2VvbWV0cnkgPSBjb21wdXRlRXh0cnVkZWRFbGxpcHNlMihvcHRpb25zKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZ2VvbWV0cnkgPSBjb21wdXRlRWxsaXBzZTIob3B0aW9ucyk7CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGVsbGlwc2VHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlKSkgewogICAgICAgICAgICBjb25zdCBsZW5ndGggPSBnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5sZW5ndGg7CiAgICAgICAgICAgIGNvbnN0IG9mZnNldFZhbHVlID0gZWxsaXBzZUdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuTk9ORSA/IDAgOiAxOwogICAgICAgICAgICBjb25zdCBhcHBseU9mZnNldCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCAvIDMpLmZpbGwob2Zmc2V0VmFsdWUpOwogICAgICAgICAgICBnZW9tZXRyeS5hdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEUsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMSwKICAgICAgICAgICAgICB2YWx1ZXM6IGFwcGx5T2Zmc2V0CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgICAgYXR0cmlidXRlczogZ2VvbWV0cnkuYXR0cmlidXRlcywKICAgICAgICAgIGluZGljZXM6IGdlb21ldHJ5LmluZGljZXMsCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBQcmltaXRpdmVUeXBlX2RlZmF1bHQuTElORVMsCiAgICAgICAgICBib3VuZGluZ1NwaGVyZTogZ2VvbWV0cnkuYm91bmRpbmdTcGhlcmUsCiAgICAgICAgICBvZmZzZXRBdHRyaWJ1dGU6IGVsbGlwc2VHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIEVsbGlwc2VPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdCA9IEVsbGlwc2VPdXRsaW5lR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9DaXJjbGVPdXRsaW5lR2VvbWV0cnkuanMKICBmdW5jdGlvbiBDaXJjbGVPdXRsaW5lR2VvbWV0cnkob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgY29uc3QgcmFkaXVzID0gb3B0aW9ucy5yYWRpdXM7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInJhZGl1cyIsIHJhZGl1cyk7CiAgICBjb25zdCBlbGxpcHNlR2VvbWV0cnlPcHRpb25zID0gewogICAgICBjZW50ZXI6IG9wdGlvbnMuY2VudGVyLAogICAgICBzZW1pTWFqb3JBeGlzOiByYWRpdXMsCiAgICAgIHNlbWlNaW5vckF4aXM6IHJhZGl1cywKICAgICAgZWxsaXBzb2lkOiBvcHRpb25zLmVsbGlwc29pZCwKICAgICAgaGVpZ2h0OiBvcHRpb25zLmhlaWdodCwKICAgICAgZXh0cnVkZWRIZWlnaHQ6IG9wdGlvbnMuZXh0cnVkZWRIZWlnaHQsCiAgICAgIGdyYW51bGFyaXR5OiBvcHRpb25zLmdyYW51bGFyaXR5LAogICAgICBudW1iZXJPZlZlcnRpY2FsTGluZXM6IG9wdGlvbnMubnVtYmVyT2ZWZXJ0aWNhbExpbmVzCiAgICB9OwogICAgdGhpcy5fZWxsaXBzZUdlb21ldHJ5ID0gbmV3IEVsbGlwc2VPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdChlbGxpcHNlR2VvbWV0cnlPcHRpb25zKTsKICAgIHRoaXMuX3dvcmtlck5hbWUgPSAiY3JlYXRlQ2lyY2xlT3V0bGluZUdlb21ldHJ5IjsKICB9CiAgdmFyIHNjcmF0Y2hFbGxpcHNlR2VvbWV0cnkyLCBzY3JhdGNoT3B0aW9uczYsIENpcmNsZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X0NpcmNsZU91dGxpbmVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ2lyY2xlT3V0bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzZU91dGxpbmVHZW9tZXRyeSgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBDaXJjbGVPdXRsaW5lR2VvbWV0cnkucGFja2VkTGVuZ3RoID0gRWxsaXBzZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgQ2lyY2xlT3V0bGluZUdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIHJldHVybiBFbGxpcHNlT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQucGFjaygKICAgICAgICAgIHZhbHVlLl9lbGxpcHNlR2VvbWV0cnksCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXgKICAgICAgICApOwogICAgICB9OwogICAgICBzY3JhdGNoRWxsaXBzZUdlb21ldHJ5MiA9IG5ldyBFbGxpcHNlT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgIGNlbnRlcjogbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpLAogICAgICAgIHNlbWlNYWpvckF4aXM6IDEsCiAgICAgICAgc2VtaU1pbm9yQXhpczogMQogICAgICB9KTsKICAgICAgc2NyYXRjaE9wdGlvbnM2ID0gewogICAgICAgIGNlbnRlcjogbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpLAogICAgICAgIHJhZGl1czogdm9pZCAwLAogICAgICAgIGVsbGlwc29pZDogRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoRWxsaXBzb2lkX2RlZmF1bHQuVU5JVF9TUEhFUkUpLAogICAgICAgIGhlaWdodDogdm9pZCAwLAogICAgICAgIGV4dHJ1ZGVkSGVpZ2h0OiB2b2lkIDAsCiAgICAgICAgZ3JhbnVsYXJpdHk6IHZvaWQgMCwKICAgICAgICBudW1iZXJPZlZlcnRpY2FsTGluZXM6IHZvaWQgMCwKICAgICAgICBzZW1pTWFqb3JBeGlzOiB2b2lkIDAsCiAgICAgICAgc2VtaU1pbm9yQXhpczogdm9pZCAwCiAgICAgIH07CiAgICAgIENpcmNsZU91dGxpbmVHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgY29uc3QgZWxsaXBzZUdlb21ldHJ5ID0gRWxsaXBzZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjaygKICAgICAgICAgIGFycmF5LAogICAgICAgICAgc3RhcnRpbmdJbmRleCwKICAgICAgICAgIHNjcmF0Y2hFbGxpcHNlR2VvbWV0cnkyCiAgICAgICAgKTsKICAgICAgICBzY3JhdGNoT3B0aW9uczYuY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKAogICAgICAgICAgZWxsaXBzZUdlb21ldHJ5Ll9jZW50ZXIsCiAgICAgICAgICBzY3JhdGNoT3B0aW9uczYuY2VudGVyCiAgICAgICAgKTsKICAgICAgICBzY3JhdGNoT3B0aW9uczYuZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoCiAgICAgICAgICBlbGxpcHNlR2VvbWV0cnkuX2VsbGlwc29pZCwKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zNi5lbGxpcHNvaWQKICAgICAgICApOwogICAgICAgIHNjcmF0Y2hPcHRpb25zNi5oZWlnaHQgPSBlbGxpcHNlR2VvbWV0cnkuX2hlaWdodDsKICAgICAgICBzY3JhdGNoT3B0aW9uczYuZXh0cnVkZWRIZWlnaHQgPSBlbGxpcHNlR2VvbWV0cnkuX2V4dHJ1ZGVkSGVpZ2h0OwogICAgICAgIHNjcmF0Y2hPcHRpb25zNi5ncmFudWxhcml0eSA9IGVsbGlwc2VHZW9tZXRyeS5fZ3JhbnVsYXJpdHk7CiAgICAgICAgc2NyYXRjaE9wdGlvbnM2Lm51bWJlck9mVmVydGljYWxMaW5lcyA9IGVsbGlwc2VHZW9tZXRyeS5fbnVtYmVyT2ZWZXJ0aWNhbExpbmVzOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zNi5yYWRpdXMgPSBlbGxpcHNlR2VvbWV0cnkuX3NlbWlNYWpvckF4aXM7CiAgICAgICAgICByZXR1cm4gbmV3IENpcmNsZU91dGxpbmVHZW9tZXRyeShzY3JhdGNoT3B0aW9uczYpOwogICAgICAgIH0KICAgICAgICBzY3JhdGNoT3B0aW9uczYuc2VtaU1ham9yQXhpcyA9IGVsbGlwc2VHZW9tZXRyeS5fc2VtaU1ham9yQXhpczsKICAgICAgICBzY3JhdGNoT3B0aW9uczYuc2VtaU1pbm9yQXhpcyA9IGVsbGlwc2VHZW9tZXRyeS5fc2VtaU1pbm9yQXhpczsKICAgICAgICByZXN1bHQuX2VsbGlwc2VHZW9tZXRyeSA9IG5ldyBFbGxpcHNlT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQoc2NyYXRjaE9wdGlvbnM2KTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDaXJjbGVPdXRsaW5lR2VvbWV0cnkuY3JlYXRlR2VvbWV0cnkgPSBmdW5jdGlvbihjaXJjbGVHZW9tZXRyeSkgewogICAgICAgIHJldHVybiBFbGxpcHNlT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkoY2lyY2xlR2VvbWV0cnkuX2VsbGlwc2VHZW9tZXRyeSk7CiAgICAgIH07CiAgICAgIENpcmNsZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gQ2lyY2xlT3V0bGluZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlQ2lyY2xlT3V0bGluZUdlb21ldHJ5LmpzCiAgdmFyIGNyZWF0ZUNpcmNsZU91dGxpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlQ2lyY2xlT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZUNpcmNsZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gY3JlYXRlQ2lyY2xlT3V0bGluZUdlb21ldHJ5KGNpcmNsZUdlb21ldHJ5LCBvZmZzZXQpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob2Zmc2V0KSkgewogICAgICBjaXJjbGVHZW9tZXRyeSA9IENpcmNsZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjayhjaXJjbGVHZW9tZXRyeSwgb2Zmc2V0KTsKICAgIH0KICAgIGNpcmNsZUdlb21ldHJ5Ll9lbGxpcHNlR2VvbWV0cnkuX2NlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZSgKICAgICAgY2lyY2xlR2VvbWV0cnkuX2VsbGlwc2VHZW9tZXRyeS5fY2VudGVyCiAgICApOwogICAgY2lyY2xlR2VvbWV0cnkuX2VsbGlwc2VHZW9tZXRyeS5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoCiAgICAgIGNpcmNsZUdlb21ldHJ5Ll9lbGxpcHNlR2VvbWV0cnkuX2VsbGlwc29pZAogICAgKTsKICAgIHJldHVybiBDaXJjbGVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeShjaXJjbGVHZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVDaXJjbGVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVDaXJjbGVPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUNpcmNsZU91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NpcmNsZU91dGxpbmVHZW9tZXRyeSgpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgY3JlYXRlQ2lyY2xlT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQgPSBjcmVhdGVDaXJjbGVPdXRsaW5lR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9hcnJheVJlbW92ZUR1cGxpY2F0ZXMuanMKICBmdW5jdGlvbiBhcnJheVJlbW92ZUR1cGxpY2F0ZXModmFsdWVzLCBlcXVhbHNFcHNpbG9uLCB3cmFwQXJvdW5kLCByZW1vdmVkSW5kaWNlcykgewogICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJlcXVhbHNFcHNpbG9uIiwgZXF1YWxzRXBzaWxvbik7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh2YWx1ZXMpKSB7CiAgICAgIHJldHVybiB2b2lkIDA7CiAgICB9CiAgICB3cmFwQXJvdW5kID0gd3JhcEFyb3VuZCA/PyBmYWxzZTsKICAgIGNvbnN0IHN0b3JlUmVtb3ZlZEluZGljZXMgPSBkZWZpbmVkX2RlZmF1bHQocmVtb3ZlZEluZGljZXMpOwogICAgY29uc3QgbGVuZ3RoID0gdmFsdWVzLmxlbmd0aDsKICAgIGlmIChsZW5ndGggPCAyKSB7CiAgICAgIHJldHVybiB2YWx1ZXM7CiAgICB9CiAgICBsZXQgaTsKICAgIGxldCB2MDIgPSB2YWx1ZXNbMF07CiAgICBsZXQgdjEyOwogICAgbGV0IGNsZWFuZWRWYWx1ZXM7CiAgICBsZXQgbGFzdENsZWFuSW5kZXggPSAwOwogICAgbGV0IHJlbW92ZWRJbmRleExDSSA9IC0xOwogICAgZm9yIChpID0gMTsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgIHYxMiA9IHZhbHVlc1tpXTsKICAgICAgaWYgKGVxdWFsc0Vwc2lsb24odjAyLCB2MTIsIHJlbW92ZUR1cGxpY2F0ZXNFcHNpbG9uKSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGNsZWFuZWRWYWx1ZXMpKSB7CiAgICAgICAgICBjbGVhbmVkVmFsdWVzID0gdmFsdWVzLnNsaWNlKDAsIGkpOwogICAgICAgICAgbGFzdENsZWFuSW5kZXggPSBpIC0gMTsKICAgICAgICAgIHJlbW92ZWRJbmRleExDSSA9IDA7CiAgICAgICAgfQogICAgICAgIGlmIChzdG9yZVJlbW92ZWRJbmRpY2VzKSB7CiAgICAgICAgICByZW1vdmVkSW5kaWNlcy5wdXNoKGkpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGNsZWFuZWRWYWx1ZXMpKSB7CiAgICAgICAgICBjbGVhbmVkVmFsdWVzLnB1c2godjEyKTsKICAgICAgICAgIGxhc3RDbGVhbkluZGV4ID0gaTsKICAgICAgICAgIGlmIChzdG9yZVJlbW92ZWRJbmRpY2VzKSB7CiAgICAgICAgICAgIHJlbW92ZWRJbmRleExDSSA9IHJlbW92ZWRJbmRpY2VzLmxlbmd0aDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgdjAyID0gdjEyOwogICAgICB9CiAgICB9CiAgICBpZiAod3JhcEFyb3VuZCAmJiBlcXVhbHNFcHNpbG9uKHZhbHVlc1swXSwgdmFsdWVzW2xlbmd0aCAtIDFdLCByZW1vdmVEdXBsaWNhdGVzRXBzaWxvbikpIHsKICAgICAgaWYgKHN0b3JlUmVtb3ZlZEluZGljZXMpIHsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGNsZWFuZWRWYWx1ZXMpKSB7CiAgICAgICAgICByZW1vdmVkSW5kaWNlcy5zcGxpY2UocmVtb3ZlZEluZGV4TENJLCAwLCBsYXN0Q2xlYW5JbmRleCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlbW92ZWRJbmRpY2VzLnB1c2gobGVuZ3RoIC0gMSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoY2xlYW5lZFZhbHVlcykpIHsKICAgICAgICBjbGVhbmVkVmFsdWVzLmxlbmd0aCAtPSAxOwogICAgICB9IGVsc2UgewogICAgICAgIGNsZWFuZWRWYWx1ZXMgPSB2YWx1ZXMuc2xpY2UoMCwgLTEpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZGVmaW5lZF9kZWZhdWx0KGNsZWFuZWRWYWx1ZXMpID8gY2xlYW5lZFZhbHVlcyA6IHZhbHVlczsKICB9CiAgdmFyIHJlbW92ZUR1cGxpY2F0ZXNFcHNpbG9uLCBhcnJheVJlbW92ZUR1cGxpY2F0ZXNfZGVmYXVsdDsKICB2YXIgaW5pdF9hcnJheVJlbW92ZUR1cGxpY2F0ZXMgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2FycmF5UmVtb3ZlRHVwbGljYXRlcy5qcyIoKSB7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICByZW1vdmVEdXBsaWNhdGVzRXBzaWxvbiA9IE1hdGhfZGVmYXVsdC5FUFNJTE9OMTA7CiAgICAgIGFycmF5UmVtb3ZlRHVwbGljYXRlc19kZWZhdWx0ID0gYXJyYXlSZW1vdmVEdXBsaWNhdGVzOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQm91bmRpbmdSZWN0YW5nbGUuanMKICBmdW5jdGlvbiBCb3VuZGluZ1JlY3RhbmdsZSh4LCB5LCB3aWR0aCwgaGVpZ2h0KSB7CiAgICB0aGlzLnggPSB4ID8/IDA7CiAgICB0aGlzLnkgPSB5ID8/IDA7CiAgICB0aGlzLndpZHRoID0gd2lkdGggPz8gMDsKICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0ID8/IDA7CiAgfQogIHZhciBkZWZhdWx0UHJvamVjdGlvbjIsIGZyb21SZWN0YW5nbGVMb3dlckxlZnQsIGZyb21SZWN0YW5nbGVVcHBlclJpZ2h0LCBCb3VuZGluZ1JlY3RhbmdsZV9kZWZhdWx0OwogIHZhciBpbml0X0JvdW5kaW5nUmVjdGFuZ2xlID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Cb3VuZGluZ1JlY3RhbmdsZS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMigpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0dlb2dyYXBoaWNQcm9qZWN0aW9uKCk7CiAgICAgIGluaXRfSW50ZXJzZWN0KCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIEJvdW5kaW5nUmVjdGFuZ2xlLnBhY2tlZExlbmd0aCA9IDQ7CiAgICAgIEJvdW5kaW5nUmVjdGFuZ2xlLnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUueDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUueTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUud2lkdGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleF0gPSB2YWx1ZS5oZWlnaHQ7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBCb3VuZGluZ1JlY3RhbmdsZS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBCb3VuZGluZ1JlY3RhbmdsZSgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQueCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LnkgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdC53aWR0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LmhlaWdodCA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nUmVjdGFuZ2xlLmZyb21Qb2ludHMgPSBmdW5jdGlvbihwb3NpdGlvbnMsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBCb3VuZGluZ1JlY3RhbmdsZSgpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwb3NpdGlvbnMpIHx8IHBvc2l0aW9ucy5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHJlc3VsdC54ID0gMDsKICAgICAgICAgIHJlc3VsdC55ID0gMDsKICAgICAgICAgIHJlc3VsdC53aWR0aCA9IDA7CiAgICAgICAgICByZXN1bHQuaGVpZ2h0ID0gMDsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgbGV0IG1pbmltdW1YID0gcG9zaXRpb25zWzBdLng7CiAgICAgICAgbGV0IG1pbmltdW1ZID0gcG9zaXRpb25zWzBdLnk7CiAgICAgICAgbGV0IG1heGltdW1YID0gcG9zaXRpb25zWzBdLng7CiAgICAgICAgbGV0IG1heGltdW1ZID0gcG9zaXRpb25zWzBdLnk7CiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgY29uc3QgcCA9IHBvc2l0aW9uc1tpXTsKICAgICAgICAgIGNvbnN0IHggPSBwLng7CiAgICAgICAgICBjb25zdCB5ID0gcC55OwogICAgICAgICAgbWluaW11bVggPSBNYXRoLm1pbih4LCBtaW5pbXVtWCk7CiAgICAgICAgICBtYXhpbXVtWCA9IE1hdGgubWF4KHgsIG1heGltdW1YKTsKICAgICAgICAgIG1pbmltdW1ZID0gTWF0aC5taW4oeSwgbWluaW11bVkpOwogICAgICAgICAgbWF4aW11bVkgPSBNYXRoLm1heCh5LCBtYXhpbXVtWSk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC54ID0gbWluaW11bVg7CiAgICAgICAgcmVzdWx0LnkgPSBtaW5pbXVtWTsKICAgICAgICByZXN1bHQud2lkdGggPSBtYXhpbXVtWCAtIG1pbmltdW1YOwogICAgICAgIHJlc3VsdC5oZWlnaHQgPSBtYXhpbXVtWSAtIG1pbmltdW1ZOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIGRlZmF1bHRQcm9qZWN0aW9uMiA9IG5ldyBHZW9ncmFwaGljUHJvamVjdGlvbl9kZWZhdWx0KCk7CiAgICAgIGZyb21SZWN0YW5nbGVMb3dlckxlZnQgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgZnJvbVJlY3RhbmdsZVVwcGVyUmlnaHQgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgQm91bmRpbmdSZWN0YW5nbGUuZnJvbVJlY3RhbmdsZSA9IGZ1bmN0aW9uKHJlY3RhbmdsZSwgcHJvamVjdGlvbiwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEJvdW5kaW5nUmVjdGFuZ2xlKCk7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlY3RhbmdsZSkpIHsKICAgICAgICAgIHJlc3VsdC54ID0gMDsKICAgICAgICAgIHJlc3VsdC55ID0gMDsKICAgICAgICAgIHJlc3VsdC53aWR0aCA9IDA7CiAgICAgICAgICByZXN1bHQuaGVpZ2h0ID0gMDsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGRlZmF1bHRQcm9qZWN0aW9uMi5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgICAgICBwcm9qZWN0aW9uID0gcHJvamVjdGlvbiA/PyBkZWZhdWx0UHJvamVjdGlvbjI7CiAgICAgICAgY29uc3QgbG93ZXJMZWZ0ID0gcHJvamVjdGlvbi5wcm9qZWN0KAogICAgICAgICAgUmVjdGFuZ2xlX2RlZmF1bHQuc291dGh3ZXN0KHJlY3RhbmdsZSwgZnJvbVJlY3RhbmdsZUxvd2VyTGVmdCkKICAgICAgICApOwogICAgICAgIGNvbnN0IHVwcGVyUmlnaHQgPSBwcm9qZWN0aW9uLnByb2plY3QoCiAgICAgICAgICBSZWN0YW5nbGVfZGVmYXVsdC5ub3J0aGVhc3QocmVjdGFuZ2xlLCBmcm9tUmVjdGFuZ2xlVXBwZXJSaWdodCkKICAgICAgICApOwogICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdC5zdWJ0cmFjdCh1cHBlclJpZ2h0LCBsb3dlckxlZnQsIHVwcGVyUmlnaHQpOwogICAgICAgIHJlc3VsdC54ID0gbG93ZXJMZWZ0Lng7CiAgICAgICAgcmVzdWx0LnkgPSBsb3dlckxlZnQueTsKICAgICAgICByZXN1bHQud2lkdGggPSB1cHBlclJpZ2h0Lng7CiAgICAgICAgcmVzdWx0LmhlaWdodCA9IHVwcGVyUmlnaHQueTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBCb3VuZGluZ1JlY3RhbmdsZS5jbG9uZSA9IGZ1bmN0aW9uKHJlY3RhbmdsZSwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVjdGFuZ2xlKSkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBCb3VuZGluZ1JlY3RhbmdsZSgKICAgICAgICAgICAgcmVjdGFuZ2xlLngsCiAgICAgICAgICAgIHJlY3RhbmdsZS55LAogICAgICAgICAgICByZWN0YW5nbGUud2lkdGgsCiAgICAgICAgICAgIHJlY3RhbmdsZS5oZWlnaHQKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC54ID0gcmVjdGFuZ2xlLng7CiAgICAgICAgcmVzdWx0LnkgPSByZWN0YW5nbGUueTsKICAgICAgICByZXN1bHQud2lkdGggPSByZWN0YW5nbGUud2lkdGg7CiAgICAgICAgcmVzdWx0LmhlaWdodCA9IHJlY3RhbmdsZS5oZWlnaHQ7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQm91bmRpbmdSZWN0YW5nbGUudW5pb24gPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQm91bmRpbmdSZWN0YW5nbGUoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbG93ZXJMZWZ0WCA9IE1hdGgubWluKGxlZnQueCwgcmlnaHQueCk7CiAgICAgICAgY29uc3QgbG93ZXJMZWZ0WSA9IE1hdGgubWluKGxlZnQueSwgcmlnaHQueSk7CiAgICAgICAgY29uc3QgdXBwZXJSaWdodFggPSBNYXRoLm1heChsZWZ0LnggKyBsZWZ0LndpZHRoLCByaWdodC54ICsgcmlnaHQud2lkdGgpOwogICAgICAgIGNvbnN0IHVwcGVyUmlnaHRZID0gTWF0aC5tYXgobGVmdC55ICsgbGVmdC5oZWlnaHQsIHJpZ2h0LnkgKyByaWdodC5oZWlnaHQpOwogICAgICAgIHJlc3VsdC54ID0gbG93ZXJMZWZ0WDsKICAgICAgICByZXN1bHQueSA9IGxvd2VyTGVmdFk7CiAgICAgICAgcmVzdWx0LndpZHRoID0gdXBwZXJSaWdodFggLSBsb3dlckxlZnRYOwogICAgICAgIHJlc3VsdC5oZWlnaHQgPSB1cHBlclJpZ2h0WSAtIGxvd2VyTGVmdFk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQm91bmRpbmdSZWN0YW5nbGUuZXhwYW5kID0gZnVuY3Rpb24ocmVjdGFuZ2xlLCBwb2ludCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZWN0YW5nbGUiLCByZWN0YW5nbGUpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicG9pbnQiLCBwb2ludCk7CiAgICAgICAgcmVzdWx0ID0gQm91bmRpbmdSZWN0YW5nbGUuY2xvbmUocmVjdGFuZ2xlLCByZXN1bHQpOwogICAgICAgIGNvbnN0IHdpZHRoID0gcG9pbnQueCAtIHJlc3VsdC54OwogICAgICAgIGNvbnN0IGhlaWdodCA9IHBvaW50LnkgLSByZXN1bHQueTsKICAgICAgICBpZiAod2lkdGggPiByZXN1bHQud2lkdGgpIHsKICAgICAgICAgIHJlc3VsdC53aWR0aCA9IHdpZHRoOwogICAgICAgIH0gZWxzZSBpZiAod2lkdGggPCAwKSB7CiAgICAgICAgICByZXN1bHQud2lkdGggLT0gd2lkdGg7CiAgICAgICAgICByZXN1bHQueCA9IHBvaW50Lng7CiAgICAgICAgfQogICAgICAgIGlmIChoZWlnaHQgPiByZXN1bHQuaGVpZ2h0KSB7CiAgICAgICAgICByZXN1bHQuaGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgIH0gZWxzZSBpZiAoaGVpZ2h0IDwgMCkgewogICAgICAgICAgcmVzdWx0LmhlaWdodCAtPSBoZWlnaHQ7CiAgICAgICAgICByZXN1bHQueSA9IHBvaW50Lnk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nUmVjdGFuZ2xlLmludGVyc2VjdCA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBjb25zdCBsZWZ0WCA9IGxlZnQueDsKICAgICAgICBjb25zdCBsZWZ0WSA9IGxlZnQueTsKICAgICAgICBjb25zdCByaWdodFggPSByaWdodC54OwogICAgICAgIGNvbnN0IHJpZ2h0WSA9IHJpZ2h0Lnk7CiAgICAgICAgaWYgKCEobGVmdFggPiByaWdodFggKyByaWdodC53aWR0aCB8fCBsZWZ0WCArIGxlZnQud2lkdGggPCByaWdodFggfHwgbGVmdFkgKyBsZWZ0LmhlaWdodCA8IHJpZ2h0WSB8fCBsZWZ0WSA+IHJpZ2h0WSArIHJpZ2h0LmhlaWdodCkpIHsKICAgICAgICAgIHJldHVybiBJbnRlcnNlY3RfZGVmYXVsdC5JTlRFUlNFQ1RJTkc7CiAgICAgICAgfQogICAgICAgIHJldHVybiBJbnRlcnNlY3RfZGVmYXVsdC5PVVRTSURFOwogICAgICB9OwogICAgICBCb3VuZGluZ1JlY3RhbmdsZS5lcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCBkZWZpbmVkX2RlZmF1bHQobGVmdCkgJiYgZGVmaW5lZF9kZWZhdWx0KHJpZ2h0KSAmJiBsZWZ0LnggPT09IHJpZ2h0LnggJiYgbGVmdC55ID09PSByaWdodC55ICYmIGxlZnQud2lkdGggPT09IHJpZ2h0LndpZHRoICYmIGxlZnQuaGVpZ2h0ID09PSByaWdodC5oZWlnaHQ7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nUmVjdGFuZ2xlLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAgIHJldHVybiBCb3VuZGluZ1JlY3RhbmdsZS5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBCb3VuZGluZ1JlY3RhbmdsZS5wcm90b3R5cGUuaW50ZXJzZWN0ID0gZnVuY3Rpb24ocmlnaHQpIHsKICAgICAgICByZXR1cm4gQm91bmRpbmdSZWN0YW5nbGUuaW50ZXJzZWN0KHRoaXMsIHJpZ2h0KTsKICAgICAgfTsKICAgICAgQm91bmRpbmdSZWN0YW5nbGUucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uKHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIEJvdW5kaW5nUmVjdGFuZ2xlLmVxdWFscyh0aGlzLCByaWdodCk7CiAgICAgIH07CiAgICAgIEJvdW5kaW5nUmVjdGFuZ2xlX2RlZmF1bHQgPSBCb3VuZGluZ1JlY3RhbmdsZTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0F4aXNBbGlnbmVkQm91bmRpbmdCb3guanMKICBmdW5jdGlvbiBBeGlzQWxpZ25lZEJvdW5kaW5nQm94KG1pbmltdW0sIG1heGltdW0sIGNlbnRlcikgewogICAgdGhpcy5taW5pbXVtID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKG1pbmltdW0gPz8gQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8pOwogICAgdGhpcy5tYXhpbXVtID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKG1heGltdW0gPz8gQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8pOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoY2VudGVyKSkgewogICAgICBjZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWlkcG9pbnQodGhpcy5taW5pbXVtLCB0aGlzLm1heGltdW0sIG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKSk7CiAgICB9IGVsc2UgewogICAgICBjZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY2VudGVyKTsKICAgIH0KICAgIHRoaXMuY2VudGVyID0gY2VudGVyOwogIH0KICB2YXIgaW50ZXJzZWN0U2NyYXRjaCwgQXhpc0FsaWduZWRCb3VuZGluZ0JveF9kZWZhdWx0OwogIHZhciBpbml0X0F4aXNBbGlnbmVkQm91bmRpbmdCb3ggPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0F4aXNBbGlnbmVkQm91bmRpbmdCb3guanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9JbnRlcnNlY3QoKTsKICAgICAgQXhpc0FsaWduZWRCb3VuZGluZ0JveC5mcm9tQ29ybmVycyA9IGZ1bmN0aW9uKG1pbmltdW0sIG1heGltdW0sIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgibWluaW11bSIsIG1pbmltdW0pOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgibWF4aW11bSIsIG1heGltdW0pOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBBeGlzQWxpZ25lZEJvdW5kaW5nQm94KCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5taW5pbXVtID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKG1pbmltdW0sIHJlc3VsdC5taW5pbXVtKTsKICAgICAgICByZXN1bHQubWF4aW11bSA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShtYXhpbXVtLCByZXN1bHQubWF4aW11bSk7CiAgICAgICAgcmVzdWx0LmNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5taWRwb2ludChtaW5pbXVtLCBtYXhpbXVtLCByZXN1bHQuY2VudGVyKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBBeGlzQWxpZ25lZEJvdW5kaW5nQm94LmZyb21Qb2ludHMgPSBmdW5jdGlvbihwb3NpdGlvbnMsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBBeGlzQWxpZ25lZEJvdW5kaW5nQm94KCk7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBvc2l0aW9ucykgfHwgcG9zaXRpb25zLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgcmVzdWx0Lm1pbmltdW0gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sIHJlc3VsdC5taW5pbXVtKTsKICAgICAgICAgIHJlc3VsdC5tYXhpbXVtID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLCByZXN1bHQubWF4aW11bSk7CiAgICAgICAgICByZXN1bHQuY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLCByZXN1bHQuY2VudGVyKTsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGxldCBtaW5pbXVtWCA9IHBvc2l0aW9uc1swXS54OwogICAgICAgIGxldCBtaW5pbXVtWSA9IHBvc2l0aW9uc1swXS55OwogICAgICAgIGxldCBtaW5pbXVtWiA9IHBvc2l0aW9uc1swXS56OwogICAgICAgIGxldCBtYXhpbXVtWCA9IHBvc2l0aW9uc1swXS54OwogICAgICAgIGxldCBtYXhpbXVtWSA9IHBvc2l0aW9uc1swXS55OwogICAgICAgIGxldCBtYXhpbXVtWiA9IHBvc2l0aW9uc1swXS56OwogICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgY29uc3QgcCA9IHBvc2l0aW9uc1tpXTsKICAgICAgICAgIGNvbnN0IHggPSBwLng7CiAgICAgICAgICBjb25zdCB5ID0gcC55OwogICAgICAgICAgY29uc3QgeiA9IHAuejsKICAgICAgICAgIG1pbmltdW1YID0gTWF0aC5taW4oeCwgbWluaW11bVgpOwogICAgICAgICAgbWF4aW11bVggPSBNYXRoLm1heCh4LCBtYXhpbXVtWCk7CiAgICAgICAgICBtaW5pbXVtWSA9IE1hdGgubWluKHksIG1pbmltdW1ZKTsKICAgICAgICAgIG1heGltdW1ZID0gTWF0aC5tYXgoeSwgbWF4aW11bVkpOwogICAgICAgICAgbWluaW11bVogPSBNYXRoLm1pbih6LCBtaW5pbXVtWik7CiAgICAgICAgICBtYXhpbXVtWiA9IE1hdGgubWF4KHosIG1heGltdW1aKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbWluaW11bSA9IHJlc3VsdC5taW5pbXVtOwogICAgICAgIG1pbmltdW0ueCA9IG1pbmltdW1YOwogICAgICAgIG1pbmltdW0ueSA9IG1pbmltdW1ZOwogICAgICAgIG1pbmltdW0ueiA9IG1pbmltdW1aOwogICAgICAgIGNvbnN0IG1heGltdW0gPSByZXN1bHQubWF4aW11bTsKICAgICAgICBtYXhpbXVtLnggPSBtYXhpbXVtWDsKICAgICAgICBtYXhpbXVtLnkgPSBtYXhpbXVtWTsKICAgICAgICBtYXhpbXVtLnogPSBtYXhpbXVtWjsKICAgICAgICByZXN1bHQuY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1pZHBvaW50KG1pbmltdW0sIG1heGltdW0sIHJlc3VsdC5jZW50ZXIpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEF4aXNBbGlnbmVkQm91bmRpbmdCb3guY2xvbmUgPSBmdW5jdGlvbihib3gsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGJveCkpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgQXhpc0FsaWduZWRCb3VuZGluZ0JveChib3gubWluaW11bSwgYm94Lm1heGltdW0sIGJveC5jZW50ZXIpOwogICAgICAgIH0KICAgICAgICByZXN1bHQubWluaW11bSA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShib3gubWluaW11bSwgcmVzdWx0Lm1pbmltdW0pOwogICAgICAgIHJlc3VsdC5tYXhpbXVtID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGJveC5tYXhpbXVtLCByZXN1bHQubWF4aW11bSk7CiAgICAgICAgcmVzdWx0LmNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShib3guY2VudGVyLCByZXN1bHQuY2VudGVyKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBBeGlzQWxpZ25lZEJvdW5kaW5nQm94LmVxdWFscyA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgcmV0dXJuIGxlZnQgPT09IHJpZ2h0IHx8IGRlZmluZWRfZGVmYXVsdChsZWZ0KSAmJiBkZWZpbmVkX2RlZmF1bHQocmlnaHQpICYmIENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHMobGVmdC5jZW50ZXIsIHJpZ2h0LmNlbnRlcikgJiYgQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFscyhsZWZ0Lm1pbmltdW0sIHJpZ2h0Lm1pbmltdW0pICYmIENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHMobGVmdC5tYXhpbXVtLCByaWdodC5tYXhpbXVtKTsKICAgICAgfTsKICAgICAgaW50ZXJzZWN0U2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgQXhpc0FsaWduZWRCb3VuZGluZ0JveC5pbnRlcnNlY3RQbGFuZSA9IGZ1bmN0aW9uKGJveCwgcGxhbmUpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImJveCIsIGJveCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJwbGFuZSIsIHBsYW5lKTsKICAgICAgICBpbnRlcnNlY3RTY3JhdGNoID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KAogICAgICAgICAgYm94Lm1heGltdW0sCiAgICAgICAgICBib3gubWluaW11bSwKICAgICAgICAgIGludGVyc2VjdFNjcmF0Y2gKICAgICAgICApOwogICAgICAgIGNvbnN0IGggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICAgIGludGVyc2VjdFNjcmF0Y2gsCiAgICAgICAgICAwLjUsCiAgICAgICAgICBpbnRlcnNlY3RTY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBjb25zdCBub3JtYWwyID0gcGxhbmUubm9ybWFsOwogICAgICAgIGNvbnN0IGUgPSBoLnggKiBNYXRoLmFicyhub3JtYWwyLngpICsgaC55ICogTWF0aC5hYnMobm9ybWFsMi55KSArIGgueiAqIE1hdGguYWJzKG5vcm1hbDIueik7CiAgICAgICAgY29uc3QgcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QoYm94LmNlbnRlciwgbm9ybWFsMikgKyBwbGFuZS5kaXN0YW5jZTsKICAgICAgICBpZiAocyAtIGUgPiAwKSB7CiAgICAgICAgICByZXR1cm4gSW50ZXJzZWN0X2RlZmF1bHQuSU5TSURFOwogICAgICAgIH0KICAgICAgICBpZiAocyArIGUgPCAwKSB7CiAgICAgICAgICByZXR1cm4gSW50ZXJzZWN0X2RlZmF1bHQuT1VUU0lERTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIEludGVyc2VjdF9kZWZhdWx0LklOVEVSU0VDVElORzsKICAgICAgfTsKICAgICAgQXhpc0FsaWduZWRCb3VuZGluZ0JveC5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICByZXR1cm4gQXhpc0FsaWduZWRCb3VuZGluZ0JveC5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBBeGlzQWxpZ25lZEJvdW5kaW5nQm94LnByb3RvdHlwZS5pbnRlcnNlY3RQbGFuZSA9IGZ1bmN0aW9uKHBsYW5lKSB7CiAgICAgICAgcmV0dXJuIEF4aXNBbGlnbmVkQm91bmRpbmdCb3guaW50ZXJzZWN0UGxhbmUodGhpcywgcGxhbmUpOwogICAgICB9OwogICAgICBBeGlzQWxpZ25lZEJvdW5kaW5nQm94LnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbihyaWdodCkgewogICAgICAgIHJldHVybiBBeGlzQWxpZ25lZEJvdW5kaW5nQm94LmVxdWFscyh0aGlzLCByaWdodCk7CiAgICAgIH07CiAgICAgIEF4aXNBbGlnbmVkQm91bmRpbmdCb3hfZGVmYXVsdCA9IEF4aXNBbGlnbmVkQm91bmRpbmdCb3g7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9FbGxpcHNvaWRUYW5nZW50UGxhbmUuanMKICBmdW5jdGlvbiBFbGxpcHNvaWRUYW5nZW50UGxhbmUob3JpZ2luLCBlbGxpcHNvaWQpIHsKICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgib3JpZ2luIiwgb3JpZ2luKTsKICAgIGVsbGlwc29pZCA9IGVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgb3JpZ2luID0gZWxsaXBzb2lkLnNjYWxlVG9HZW9kZXRpY1N1cmZhY2Uob3JpZ2luKTsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG9yaWdpbikpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgIm9yaWdpbiBtdXN0IG5vdCBiZSBhdCB0aGUgY2VudGVyIG9mIHRoZSBlbGxpcHNvaWQuIgogICAgICApOwogICAgfQogICAgY29uc3QgZWFzdE5vcnRoVXAgPSBUcmFuc2Zvcm1zX2RlZmF1bHQuZWFzdE5vcnRoVXBUb0ZpeGVkRnJhbWUob3JpZ2luLCBlbGxpcHNvaWQpOwogICAgdGhpcy5fZWxsaXBzb2lkID0gZWxsaXBzb2lkOwogICAgdGhpcy5fb3JpZ2luID0gb3JpZ2luOwogICAgdGhpcy5feEF4aXMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUNhcnRlc2lhbjQoCiAgICAgIE1hdHJpeDRfZGVmYXVsdC5nZXRDb2x1bW4oZWFzdE5vcnRoVXAsIDAsIHNjcmF0Y2hDYXJ0NCkKICAgICk7CiAgICB0aGlzLl95QXhpcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQ2FydGVzaWFuNCgKICAgICAgTWF0cml4NF9kZWZhdWx0LmdldENvbHVtbihlYXN0Tm9ydGhVcCwgMSwgc2NyYXRjaENhcnQ0KQogICAgKTsKICAgIGNvbnN0IG5vcm1hbDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUNhcnRlc2lhbjQoCiAgICAgIE1hdHJpeDRfZGVmYXVsdC5nZXRDb2x1bW4oZWFzdE5vcnRoVXAsIDIsIHNjcmF0Y2hDYXJ0NCkKICAgICk7CiAgICB0aGlzLl9wbGFuZSA9IFBsYW5lX2RlZmF1bHQuZnJvbVBvaW50Tm9ybWFsKG9yaWdpbiwgbm9ybWFsMik7CiAgfQogIHZhciBzY3JhdGNoQ2FydDQsIHRtcCwgc2NyYXRjaFByb2plY3RQb2ludE9udG9QbGFuZVJheSwgc2NyYXRjaFByb2plY3RQb2ludE9udG9QbGFuZUNhcnRlc2lhbjMsIHByb2plY3RQb2ludHNPbnRvRWxsaXBzb2lkU2NyYXRjaCwgRWxsaXBzb2lkVGFuZ2VudFBsYW5lX2RlZmF1bHQ7CiAgdmFyIGluaXRfRWxsaXBzb2lkVGFuZ2VudFBsYW5lID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9FbGxpcHNvaWRUYW5nZW50UGxhbmUuanMiKCkgewogICAgICBpbml0X0F4aXNBbGlnbmVkQm91bmRpbmdCb3goKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4yKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRlc2lhbjQoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0ludGVyc2VjdGlvblRlc3RzKCk7CiAgICAgIGluaXRfTWF0cml4NCgpOwogICAgICBpbml0X1BsYW5lKCk7CiAgICAgIGluaXRfUmF5KCk7CiAgICAgIGluaXRfVHJhbnNmb3JtcygpOwogICAgICBzY3JhdGNoQ2FydDQgPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KCk7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKEVsbGlwc29pZFRhbmdlbnRQbGFuZS5wcm90b3R5cGUsIHsKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBlbGxpcHNvaWQuCiAgICAgICAgICogQG1lbWJlcm9mIEVsbGlwc29pZFRhbmdlbnRQbGFuZS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7RWxsaXBzb2lkfQogICAgICAgICAqLwogICAgICAgIGVsbGlwc29pZDogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2VsbGlwc29pZDsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIG9yaWdpbi4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkVGFuZ2VudFBsYW5lLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtDYXJ0ZXNpYW4zfQogICAgICAgICAqLwogICAgICAgIG9yaWdpbjogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29yaWdpbjsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIHBsYW5lIHdoaWNoIGlzIHRhbmdlbnQgdG8gdGhlIGVsbGlwc29pZC4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkVGFuZ2VudFBsYW5lLnByb3RvdHlwZQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqIEB0eXBlIHtQbGFuZX0KICAgICAgICAgKi8KICAgICAgICBwbGFuZTogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3BsYW5lOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgbG9jYWwgWC1heGlzIChlYXN0KSBvZiB0aGUgdGFuZ2VudCBwbGFuZS4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkVGFuZ2VudFBsYW5lLnByb3RvdHlwZQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqIEB0eXBlIHtDYXJ0ZXNpYW4zfQogICAgICAgICAqLwogICAgICAgIHhBeGlzOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5feEF4aXM7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBsb2NhbCBZLWF4aXMgKG5vcnRoKSBvZiB0aGUgdGFuZ2VudCBwbGFuZS4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkVGFuZ2VudFBsYW5lLnByb3RvdHlwZQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqIEB0eXBlIHtDYXJ0ZXNpYW4zfQogICAgICAgICAqLwogICAgICAgIHlBeGlzOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5feUF4aXM7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBsb2NhbCBaLWF4aXMgKHVwKSBvZiB0aGUgdGFuZ2VudCBwbGFuZS4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkVGFuZ2VudFBsYW5lLnByb3RvdHlwZQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqIEB0eXBlIHtDYXJ0ZXNpYW4zfQogICAgICAgICAqLwogICAgICAgIHpBeGlzOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fcGxhbmUubm9ybWFsOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHRtcCA9IG5ldyBBeGlzQWxpZ25lZEJvdW5kaW5nQm94X2RlZmF1bHQoKTsKICAgICAgRWxsaXBzb2lkVGFuZ2VudFBsYW5lLmZyb21Qb2ludHMgPSBmdW5jdGlvbihjYXJ0ZXNpYW5zLCBlbGxpcHNvaWQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImNhcnRlc2lhbnMiLCBjYXJ0ZXNpYW5zKTsKICAgICAgICBjb25zdCBib3ggPSBBeGlzQWxpZ25lZEJvdW5kaW5nQm94X2RlZmF1bHQuZnJvbVBvaW50cyhjYXJ0ZXNpYW5zLCB0bXApOwogICAgICAgIHJldHVybiBuZXcgRWxsaXBzb2lkVGFuZ2VudFBsYW5lKGJveC5jZW50ZXIsIGVsbGlwc29pZCk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hQcm9qZWN0UG9pbnRPbnRvUGxhbmVSYXkgPSBuZXcgUmF5X2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFByb2plY3RQb2ludE9udG9QbGFuZUNhcnRlc2lhbjMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIEVsbGlwc29pZFRhbmdlbnRQbGFuZS5wcm90b3R5cGUucHJvamVjdFBvaW50T250b1BsYW5lID0gZnVuY3Rpb24oY2FydGVzaWFuMTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiY2FydGVzaWFuIiwgY2FydGVzaWFuMTEpOwogICAgICAgIGNvbnN0IHJheSA9IHNjcmF0Y2hQcm9qZWN0UG9pbnRPbnRvUGxhbmVSYXk7CiAgICAgICAgcmF5Lm9yaWdpbiA9IGNhcnRlc2lhbjExOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoY2FydGVzaWFuMTEsIHJheS5kaXJlY3Rpb24pOwogICAgICAgIGxldCBpbnRlcnNlY3Rpb25Qb2ludCA9IEludGVyc2VjdGlvblRlc3RzX2RlZmF1bHQucmF5UGxhbmUoCiAgICAgICAgICByYXksCiAgICAgICAgICB0aGlzLl9wbGFuZSwKICAgICAgICAgIHNjcmF0Y2hQcm9qZWN0UG9pbnRPbnRvUGxhbmVDYXJ0ZXNpYW4zCiAgICAgICAgKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpbnRlcnNlY3Rpb25Qb2ludCkpIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUocmF5LmRpcmVjdGlvbiwgcmF5LmRpcmVjdGlvbik7CiAgICAgICAgICBpbnRlcnNlY3Rpb25Qb2ludCA9IEludGVyc2VjdGlvblRlc3RzX2RlZmF1bHQucmF5UGxhbmUoCiAgICAgICAgICAgIHJheSwKICAgICAgICAgICAgdGhpcy5fcGxhbmUsCiAgICAgICAgICAgIHNjcmF0Y2hQcm9qZWN0UG9pbnRPbnRvUGxhbmVDYXJ0ZXNpYW4zCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGludGVyc2VjdGlvblBvaW50KSkgewogICAgICAgICAgY29uc3QgdjMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgICAgICAgIGludGVyc2VjdGlvblBvaW50LAogICAgICAgICAgICB0aGlzLl9vcmlnaW4sCiAgICAgICAgICAgIGludGVyc2VjdGlvblBvaW50CiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgeCA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QodGhpcy5feEF4aXMsIHYzKTsKICAgICAgICAgIGNvbnN0IHkgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHRoaXMuX3lBeGlzLCB2Myk7CiAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KHgsIHkpOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LnggPSB4OwogICAgICAgICAgcmVzdWx0LnkgPSB5OwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkVGFuZ2VudFBsYW5lLnByb3RvdHlwZS5wcm9qZWN0UG9pbnRzT250b1BsYW5lID0gZnVuY3Rpb24oY2FydGVzaWFucywgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJjYXJ0ZXNpYW5zIiwgY2FydGVzaWFucyk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gW107CiAgICAgICAgfQogICAgICAgIGxldCBjb3VudCA9IDA7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gY2FydGVzaWFucy5sZW5ndGg7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgY29uc3QgcCA9IHRoaXMucHJvamVjdFBvaW50T250b1BsYW5lKGNhcnRlc2lhbnNbaV0sIHJlc3VsdFtjb3VudF0pOwogICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChwKSkgewogICAgICAgICAgICByZXN1bHRbY291bnRdID0gcDsKICAgICAgICAgICAgY291bnQrKzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmVzdWx0Lmxlbmd0aCA9IGNvdW50OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZFRhbmdlbnRQbGFuZS5wcm90b3R5cGUucHJvamVjdFBvaW50VG9OZWFyZXN0T25QbGFuZSA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHJheSA9IHNjcmF0Y2hQcm9qZWN0UG9pbnRPbnRvUGxhbmVSYXk7CiAgICAgICAgcmF5Lm9yaWdpbiA9IGNhcnRlc2lhbjExOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZSh0aGlzLl9wbGFuZS5ub3JtYWwsIHJheS5kaXJlY3Rpb24pOwogICAgICAgIGxldCBpbnRlcnNlY3Rpb25Qb2ludCA9IEludGVyc2VjdGlvblRlc3RzX2RlZmF1bHQucmF5UGxhbmUoCiAgICAgICAgICByYXksCiAgICAgICAgICB0aGlzLl9wbGFuZSwKICAgICAgICAgIHNjcmF0Y2hQcm9qZWN0UG9pbnRPbnRvUGxhbmVDYXJ0ZXNpYW4zCiAgICAgICAgKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpbnRlcnNlY3Rpb25Qb2ludCkpIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUocmF5LmRpcmVjdGlvbiwgcmF5LmRpcmVjdGlvbik7CiAgICAgICAgICBpbnRlcnNlY3Rpb25Qb2ludCA9IEludGVyc2VjdGlvblRlc3RzX2RlZmF1bHQucmF5UGxhbmUoCiAgICAgICAgICAgIHJheSwKICAgICAgICAgICAgdGhpcy5fcGxhbmUsCiAgICAgICAgICAgIHNjcmF0Y2hQcm9qZWN0UG9pbnRPbnRvUGxhbmVDYXJ0ZXNpYW4zCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCB2MyA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgICAgIGludGVyc2VjdGlvblBvaW50LAogICAgICAgICAgdGhpcy5fb3JpZ2luLAogICAgICAgICAgaW50ZXJzZWN0aW9uUG9pbnQKICAgICAgICApOwogICAgICAgIGNvbnN0IHggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHRoaXMuX3hBeGlzLCB2Myk7CiAgICAgICAgY29uc3QgeSA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QodGhpcy5feUF4aXMsIHYzKTsKICAgICAgICByZXN1bHQueCA9IHg7CiAgICAgICAgcmVzdWx0LnkgPSB5OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZFRhbmdlbnRQbGFuZS5wcm90b3R5cGUucHJvamVjdFBvaW50c1RvTmVhcmVzdE9uUGxhbmUgPSBmdW5jdGlvbihjYXJ0ZXNpYW5zLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImNhcnRlc2lhbnMiLCBjYXJ0ZXNpYW5zKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBbXTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbGVuZ3RoID0gY2FydGVzaWFucy5sZW5ndGg7CiAgICAgICAgcmVzdWx0Lmxlbmd0aCA9IGxlbmd0aDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICByZXN1bHRbaV0gPSB0aGlzLnByb2plY3RQb2ludFRvTmVhcmVzdE9uUGxhbmUoY2FydGVzaWFuc1tpXSwgcmVzdWx0W2ldKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgcHJvamVjdFBvaW50c09udG9FbGxpcHNvaWRTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBFbGxpcHNvaWRUYW5nZW50UGxhbmUucHJvdG90eXBlLnByb2plY3RQb2ludE9udG9FbGxpcHNvaWQgPSBmdW5jdGlvbihjYXJ0ZXNpYW4xMSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJjYXJ0ZXNpYW4iLCBjYXJ0ZXNpYW4xMSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSB0aGlzLl9lbGxpcHNvaWQ7CiAgICAgICAgY29uc3Qgb3JpZ2luID0gdGhpcy5fb3JpZ2luOwogICAgICAgIGNvbnN0IHhBeGlzID0gdGhpcy5feEF4aXM7CiAgICAgICAgY29uc3QgeUF4aXMgPSB0aGlzLl95QXhpczsKICAgICAgICBjb25zdCB0bXAyID0gcHJvamVjdFBvaW50c09udG9FbGxpcHNvaWRTY3JhdGNoOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKHhBeGlzLCBjYXJ0ZXNpYW4xMS54LCB0bXAyKTsKICAgICAgICByZXN1bHQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKG9yaWdpbiwgdG1wMiwgcmVzdWx0KTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcih5QXhpcywgY2FydGVzaWFuMTEueSwgdG1wMik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChyZXN1bHQsIHRtcDIsIHJlc3VsdCk7CiAgICAgICAgZWxsaXBzb2lkLnNjYWxlVG9HZW9jZW50cmljU3VyZmFjZShyZXN1bHQsIHJlc3VsdCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkVGFuZ2VudFBsYW5lLnByb3RvdHlwZS5wcm9qZWN0UG9pbnRzT250b0VsbGlwc29pZCA9IGZ1bmN0aW9uKGNhcnRlc2lhbnMsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiY2FydGVzaWFucyIsIGNhcnRlc2lhbnMpOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IGNhcnRlc2lhbnMubGVuZ3RoOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXN1bHQubGVuZ3RoID0gbGVuZ3RoOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICByZXN1bHRbaV0gPSB0aGlzLnByb2plY3RQb2ludE9udG9FbGxpcHNvaWQoY2FydGVzaWFuc1tpXSwgcmVzdWx0W2ldKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkVGFuZ2VudFBsYW5lX2RlZmF1bHQgPSBFbGxpcHNvaWRUYW5nZW50UGxhbmU7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9PcmllbnRlZEJvdW5kaW5nQm94LmpzCiAgZnVuY3Rpb24gT3JpZW50ZWRCb3VuZGluZ0JveChjZW50ZXIsIGhhbGZBeGVzKSB7CiAgICB0aGlzLmNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjZW50ZXIgPz8gQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8pOwogICAgdGhpcy5oYWxmQXhlcyA9IE1hdHJpeDNfZGVmYXVsdC5jbG9uZShoYWxmQXhlcyA/PyBNYXRyaXgzX2RlZmF1bHQuWkVSTyk7CiAgfQogIGZ1bmN0aW9uIGZyb21QbGFuZUV4dGVudHMocGxhbmVPcmlnaW4sIHBsYW5lWEF4aXMsIHBsYW5lWUF4aXMsIHBsYW5lWkF4aXMsIG1pbmltdW1YLCBtYXhpbXVtWCwgbWluaW11bVksIG1heGltdW1ZLCBtaW5pbXVtWiwgbWF4aW11bVosIHJlc3VsdCkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQobWluaW11bVgpIHx8ICFkZWZpbmVkX2RlZmF1bHQobWF4aW11bVgpIHx8ICFkZWZpbmVkX2RlZmF1bHQobWluaW11bVkpIHx8ICFkZWZpbmVkX2RlZmF1bHQobWF4aW11bVkpIHx8ICFkZWZpbmVkX2RlZmF1bHQobWluaW11bVopIHx8ICFkZWZpbmVkX2RlZmF1bHQobWF4aW11bVopKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICJhbGwgZXh0ZW50cyAobWluaW11bS9tYXhpbXVtIFgvWS9aKSBhcmUgcmVxdWlyZWQuIgogICAgICApOwogICAgfQogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICByZXN1bHQgPSBuZXcgT3JpZW50ZWRCb3VuZGluZ0JveCgpOwogICAgfQogICAgY29uc3QgaGFsZkF4ZXMgPSByZXN1bHQuaGFsZkF4ZXM7CiAgICBNYXRyaXgzX2RlZmF1bHQuc2V0Q29sdW1uKGhhbGZBeGVzLCAwLCBwbGFuZVhBeGlzLCBoYWxmQXhlcyk7CiAgICBNYXRyaXgzX2RlZmF1bHQuc2V0Q29sdW1uKGhhbGZBeGVzLCAxLCBwbGFuZVlBeGlzLCBoYWxmQXhlcyk7CiAgICBNYXRyaXgzX2RlZmF1bHQuc2V0Q29sdW1uKGhhbGZBeGVzLCAyLCBwbGFuZVpBeGlzLCBoYWxmQXhlcyk7CiAgICBsZXQgY2VudGVyT2Zmc2V0ID0gc2NyYXRjaE9mZnNldDsKICAgIGNlbnRlck9mZnNldC54ID0gKG1pbmltdW1YICsgbWF4aW11bVgpIC8gMjsKICAgIGNlbnRlck9mZnNldC55ID0gKG1pbmltdW1ZICsgbWF4aW11bVkpIC8gMjsKICAgIGNlbnRlck9mZnNldC56ID0gKG1pbmltdW1aICsgbWF4aW11bVopIC8gMjsKICAgIGNvbnN0IHNjYWxlID0gc2NyYXRjaFNjYWxlMjsKICAgIHNjYWxlLnggPSAobWF4aW11bVggLSBtaW5pbXVtWCkgLyAyOwogICAgc2NhbGUueSA9IChtYXhpbXVtWSAtIG1pbmltdW1ZKSAvIDI7CiAgICBzY2FsZS56ID0gKG1heGltdW1aIC0gbWluaW11bVopIC8gMjsKICAgIGNvbnN0IGNlbnRlciA9IHJlc3VsdC5jZW50ZXI7CiAgICBjZW50ZXJPZmZzZXQgPSBNYXRyaXgzX2RlZmF1bHQubXVsdGlwbHlCeVZlY3RvcihoYWxmQXhlcywgY2VudGVyT2Zmc2V0LCBjZW50ZXJPZmZzZXQpOwogICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChwbGFuZU9yaWdpbiwgY2VudGVyT2Zmc2V0LCBjZW50ZXIpOwogICAgTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsZShoYWxmQXhlcywgc2NhbGUsIGhhbGZBeGVzKTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQogIHZhciBzY3JhdGNoQ2FydGVzaWFuMTUsIHNjcmF0Y2hDYXJ0ZXNpYW4yNSwgc2NyYXRjaENhcnRlc2lhbjM2LCBzY3JhdGNoQ2FydGVzaWFuNDIsIHNjcmF0Y2hDYXJ0ZXNpYW41LCBzY3JhdGNoQ2FydGVzaWFuNiwgc2NyYXRjaENvdmFyaWFuY2VSZXN1bHQsIHNjcmF0Y2hFaWdlblJlc3VsdCwgc2NyYXRjaE9mZnNldCwgc2NyYXRjaFNjYWxlMiwgc2NyYXRjaFJlY3RhbmdsZUNlbnRlckNhcnRvZ3JhcGhpYywgc2NyYXRjaFJlY3RhbmdsZUNlbnRlciwgc2NyYXRjaFBlcmltZXRlckNhcnRvZ3JhcGhpY05DLCBzY3JhdGNoUGVyaW1ldGVyQ2FydG9ncmFwaGljTlcsIHNjcmF0Y2hQZXJpbWV0ZXJDYXJ0b2dyYXBoaWNDVywgc2NyYXRjaFBlcmltZXRlckNhcnRvZ3JhcGhpY1NXLCBzY3JhdGNoUGVyaW1ldGVyQ2FydG9ncmFwaGljU0MsIHNjcmF0Y2hQZXJpbWV0ZXJDYXJ0ZXNpYW5OQywgc2NyYXRjaFBlcmltZXRlckNhcnRlc2lhbk5XLCBzY3JhdGNoUGVyaW1ldGVyQ2FydGVzaWFuQ1csIHNjcmF0Y2hQZXJpbWV0ZXJDYXJ0ZXNpYW5TVywgc2NyYXRjaFBlcmltZXRlckNhcnRlc2lhblNDLCBzY3JhdGNoUGVyaW1ldGVyUHJvamVjdGVkTkMsIHNjcmF0Y2hQZXJpbWV0ZXJQcm9qZWN0ZWROVywgc2NyYXRjaFBlcmltZXRlclByb2plY3RlZENXLCBzY3JhdGNoUGVyaW1ldGVyUHJvamVjdGVkU1csIHNjcmF0Y2hQZXJpbWV0ZXJQcm9qZWN0ZWRTQywgc2NyYXRjaFBsYW5lT3JpZ2luLCBzY3JhdGNoUGxhbmVOb3JtYWwsIHNjcmF0Y2hQbGFuZVhBeGlzLCBzY3JhdGNoSG9yaXpvbkNhcnRlc2lhbiwgc2NyYXRjaEhvcml6b25Qcm9qZWN0ZWQsIHNjcmF0Y2hNYXhZLCBzY3JhdGNoTWluWSwgc2NyYXRjaFosIHNjcmF0Y2hQbGFuZSwgc2NyYXRjaENhcnRlc2lhblUsIHNjcmF0Y2hDYXJ0ZXNpYW5WLCBzY3JhdGNoQ2FydGVzaWFuVywgc2NyYXRjaFZhbGlkQXhpczIsIHNjcmF0Y2hWYWxpZEF4aXMzLCBzY3JhdGNoUFByaW1lLCBzY3JhdGNoQ29ybmVyLCBzY3JhdGNoVG9DZW50ZXIsIHNjcmF0Y2hYQXhpcywgc2NyYXRjaFlBeGlzLCBzY3JhdGNoWkF4aXMsIHNjcmF0Y2hSb3RhdGlvblNjYWxlLCBzY3JhdGNoQm91bmRpbmdTcGhlcmUsIE9yaWVudGVkQm91bmRpbmdCb3hfZGVmYXVsdDsKICB2YXIgaW5pdF9PcmllbnRlZEJvdW5kaW5nQm94ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9PcmllbnRlZEJvdW5kaW5nQm94LmpzIigpIHsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWRUYW5nZW50UGxhbmUoKTsKICAgICAgaW5pdF9JbnRlcnNlY3QoKTsKICAgICAgaW5pdF9JbnRlcnZhbCgpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9NYXRyaXgzKCk7CiAgICAgIGluaXRfTWF0cml4NCgpOwogICAgICBpbml0X1BsYW5lKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIE9yaWVudGVkQm91bmRpbmdCb3gucGFja2VkTGVuZ3RoID0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCArIE1hdHJpeDNfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgIE9yaWVudGVkQm91bmRpbmdCb3gucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHZhbHVlLmNlbnRlciwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIE1hdHJpeDNfZGVmYXVsdC5wYWNrKHZhbHVlLmhhbGZBeGVzLCBhcnJheSwgc3RhcnRpbmdJbmRleCArIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGgpOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgT3JpZW50ZWRCb3VuZGluZ0JveC51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBPcmllbnRlZEJvdW5kaW5nQm94KCk7CiAgICAgICAgfQogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdC5jZW50ZXIpOwogICAgICAgIE1hdHJpeDNfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXggKyBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoLAogICAgICAgICAgcmVzdWx0LmhhbGZBeGVzCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBzY3JhdGNoQ2FydGVzaWFuMTUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4yNSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjM2ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydGVzaWFuNDIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW41ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydGVzaWFuNiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENvdmFyaWFuY2VSZXN1bHQgPSBuZXcgTWF0cml4M19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hFaWdlblJlc3VsdCA9IHsKICAgICAgICB1bml0YXJ5OiBuZXcgTWF0cml4M19kZWZhdWx0KCksCiAgICAgICAgZGlhZ29uYWw6IG5ldyBNYXRyaXgzX2RlZmF1bHQoKQogICAgICB9OwogICAgICBPcmllbnRlZEJvdW5kaW5nQm94LmZyb21Qb2ludHMgPSBmdW5jdGlvbihwb3NpdGlvbnMsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBPcmllbnRlZEJvdW5kaW5nQm94KCk7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBvc2l0aW9ucykgfHwgcG9zaXRpb25zLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgcmVzdWx0LmhhbGZBeGVzID0gTWF0cml4M19kZWZhdWx0LlpFUk87CiAgICAgICAgICByZXN1bHQuY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LlpFUk87CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICBsZXQgaTsKICAgICAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgICAgIGNvbnN0IG1lYW5Qb2ludCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShwb3NpdGlvbnNbMF0sIHNjcmF0Y2hDYXJ0ZXNpYW4xNSk7CiAgICAgICAgZm9yIChpID0gMTsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKG1lYW5Qb2ludCwgcG9zaXRpb25zW2ldLCBtZWFuUG9pbnQpOwogICAgICAgIH0KICAgICAgICBjb25zdCBpbnZMZW5ndGggPSAxIC8gbGVuZ3RoOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKG1lYW5Qb2ludCwgaW52TGVuZ3RoLCBtZWFuUG9pbnQpOwogICAgICAgIGxldCBleHggPSAwOwogICAgICAgIGxldCBleHkgPSAwOwogICAgICAgIGxldCBleHogPSAwOwogICAgICAgIGxldCBleXkgPSAwOwogICAgICAgIGxldCBleXogPSAwOwogICAgICAgIGxldCBlenogPSAwOwogICAgICAgIGxldCBwOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgcCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChwb3NpdGlvbnNbaV0sIG1lYW5Qb2ludCwgc2NyYXRjaENhcnRlc2lhbjI1KTsKICAgICAgICAgIGV4eCArPSBwLnggKiBwLng7CiAgICAgICAgICBleHkgKz0gcC54ICogcC55OwogICAgICAgICAgZXh6ICs9IHAueCAqIHAuejsKICAgICAgICAgIGV5eSArPSBwLnkgKiBwLnk7CiAgICAgICAgICBleXogKz0gcC55ICogcC56OwogICAgICAgICAgZXp6ICs9IHAueiAqIHAuejsKICAgICAgICB9CiAgICAgICAgZXh4ICo9IGludkxlbmd0aDsKICAgICAgICBleHkgKj0gaW52TGVuZ3RoOwogICAgICAgIGV4eiAqPSBpbnZMZW5ndGg7CiAgICAgICAgZXl5ICo9IGludkxlbmd0aDsKICAgICAgICBleXogKj0gaW52TGVuZ3RoOwogICAgICAgIGV6eiAqPSBpbnZMZW5ndGg7CiAgICAgICAgY29uc3QgY292YXJpYW5jZU1hdHJpeCA9IHNjcmF0Y2hDb3ZhcmlhbmNlUmVzdWx0OwogICAgICAgIGNvdmFyaWFuY2VNYXRyaXhbMF0gPSBleHg7CiAgICAgICAgY292YXJpYW5jZU1hdHJpeFsxXSA9IGV4eTsKICAgICAgICBjb3ZhcmlhbmNlTWF0cml4WzJdID0gZXh6OwogICAgICAgIGNvdmFyaWFuY2VNYXRyaXhbM10gPSBleHk7CiAgICAgICAgY292YXJpYW5jZU1hdHJpeFs0XSA9IGV5eTsKICAgICAgICBjb3ZhcmlhbmNlTWF0cml4WzVdID0gZXl6OwogICAgICAgIGNvdmFyaWFuY2VNYXRyaXhbNl0gPSBleHo7CiAgICAgICAgY292YXJpYW5jZU1hdHJpeFs3XSA9IGV5ejsKICAgICAgICBjb3ZhcmlhbmNlTWF0cml4WzhdID0gZXp6OwogICAgICAgIGNvbnN0IGVpZ2VuRGVjb21wb3NpdGlvbiA9IE1hdHJpeDNfZGVmYXVsdC5jb21wdXRlRWlnZW5EZWNvbXBvc2l0aW9uKAogICAgICAgICAgY292YXJpYW5jZU1hdHJpeCwKICAgICAgICAgIHNjcmF0Y2hFaWdlblJlc3VsdAogICAgICAgICk7CiAgICAgICAgY29uc3Qgcm90YXRpb24gPSBNYXRyaXgzX2RlZmF1bHQuY2xvbmUoZWlnZW5EZWNvbXBvc2l0aW9uLnVuaXRhcnksIHJlc3VsdC5oYWxmQXhlcyk7CiAgICAgICAgbGV0IHYxMiA9IE1hdHJpeDNfZGVmYXVsdC5nZXRDb2x1bW4ocm90YXRpb24sIDAsIHNjcmF0Y2hDYXJ0ZXNpYW40Mik7CiAgICAgICAgbGV0IHYyMiA9IE1hdHJpeDNfZGVmYXVsdC5nZXRDb2x1bW4ocm90YXRpb24sIDEsIHNjcmF0Y2hDYXJ0ZXNpYW41KTsKICAgICAgICBsZXQgdjMgPSBNYXRyaXgzX2RlZmF1bHQuZ2V0Q29sdW1uKHJvdGF0aW9uLCAyLCBzY3JhdGNoQ2FydGVzaWFuNik7CiAgICAgICAgbGV0IHUxMiA9IC1OdW1iZXIuTUFYX1ZBTFVFOwogICAgICAgIGxldCB1MjIgPSAtTnVtYmVyLk1BWF9WQUxVRTsKICAgICAgICBsZXQgdTMgPSAtTnVtYmVyLk1BWF9WQUxVRTsKICAgICAgICBsZXQgbDEgPSBOdW1iZXIuTUFYX1ZBTFVFOwogICAgICAgIGxldCBsMiA9IE51bWJlci5NQVhfVkFMVUU7CiAgICAgICAgbGV0IGwzID0gTnVtYmVyLk1BWF9WQUxVRTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHAgPSBwb3NpdGlvbnNbaV07CiAgICAgICAgICB1MTIgPSBNYXRoLm1heChDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHYxMiwgcCksIHUxMik7CiAgICAgICAgICB1MjIgPSBNYXRoLm1heChDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHYyMiwgcCksIHUyMik7CiAgICAgICAgICB1MyA9IE1hdGgubWF4KENhcnRlc2lhbjNfZGVmYXVsdC5kb3QodjMsIHApLCB1Myk7CiAgICAgICAgICBsMSA9IE1hdGgubWluKENhcnRlc2lhbjNfZGVmYXVsdC5kb3QodjEyLCBwKSwgbDEpOwogICAgICAgICAgbDIgPSBNYXRoLm1pbihDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHYyMiwgcCksIGwyKTsKICAgICAgICAgIGwzID0gTWF0aC5taW4oQ2FydGVzaWFuM19kZWZhdWx0LmRvdCh2MywgcCksIGwzKTsKICAgICAgICB9CiAgICAgICAgdjEyID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIodjEyLCAwLjUgKiAobDEgKyB1MTIpLCB2MTIpOwogICAgICAgIHYyMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKHYyMiwgMC41ICogKGwyICsgdTIyKSwgdjIyKTsKICAgICAgICB2MyA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKHYzLCAwLjUgKiAobDMgKyB1MyksIHYzKTsKICAgICAgICBjb25zdCBjZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHYxMiwgdjIyLCByZXN1bHQuY2VudGVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNlbnRlciwgdjMsIGNlbnRlcik7CiAgICAgICAgY29uc3Qgc2NhbGUgPSBzY3JhdGNoQ2FydGVzaWFuMzY7CiAgICAgICAgc2NhbGUueCA9IHUxMiAtIGwxOwogICAgICAgIHNjYWxlLnkgPSB1MjIgLSBsMjsKICAgICAgICBzY2FsZS56ID0gdTMgLSBsMzsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihzY2FsZSwgMC41LCBzY2FsZSk7CiAgICAgICAgTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsZShyZXN1bHQuaGFsZkF4ZXMsIHNjYWxlLCByZXN1bHQuaGFsZkF4ZXMpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hPZmZzZXQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hTY2FsZTIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hSZWN0YW5nbGVDZW50ZXJDYXJ0b2dyYXBoaWMgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFJlY3RhbmdsZUNlbnRlciA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBlcmltZXRlckNhcnRvZ3JhcGhpY05DID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQZXJpbWV0ZXJDYXJ0b2dyYXBoaWNOVyA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGVyaW1ldGVyQ2FydG9ncmFwaGljQ1cgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBlcmltZXRlckNhcnRvZ3JhcGhpY1NXID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQZXJpbWV0ZXJDYXJ0b2dyYXBoaWNTQyA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGVyaW1ldGVyQ2FydGVzaWFuTkMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQZXJpbWV0ZXJDYXJ0ZXNpYW5OVyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBlcmltZXRlckNhcnRlc2lhbkNXID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGVyaW1ldGVyQ2FydGVzaWFuU1cgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQZXJpbWV0ZXJDYXJ0ZXNpYW5TQyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBlcmltZXRlclByb2plY3RlZE5DID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGVyaW1ldGVyUHJvamVjdGVkTlcgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQZXJpbWV0ZXJQcm9qZWN0ZWRDVyA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBlcmltZXRlclByb2plY3RlZFNXID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGVyaW1ldGVyUHJvamVjdGVkU0MgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQbGFuZU9yaWdpbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBsYW5lTm9ybWFsID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGxhbmVYQXhpcyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEhvcml6b25DYXJ0ZXNpYW4gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hIb3Jpem9uUHJvamVjdGVkID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoTWF4WSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE1pblkgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2haID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGxhbmUgPSBuZXcgUGxhbmVfZGVmYXVsdChDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9YLCAwKTsKICAgICAgT3JpZW50ZWRCb3VuZGluZ0JveC5mcm9tUmVjdGFuZ2xlID0gZnVuY3Rpb24ocmVjdGFuZ2xlLCBtaW5pbXVtSGVpZ2h0LCBtYXhpbXVtSGVpZ2h0LCBlbGxpcHNvaWQsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlY3RhbmdsZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJyZWN0YW5nbGUgaXMgcmVxdWlyZWQiKTsKICAgICAgICB9CiAgICAgICAgaWYgKHJlY3RhbmdsZS53aWR0aCA8IDAgfHwgcmVjdGFuZ2xlLndpZHRoID4gTWF0aF9kZWZhdWx0LlRXT19QSSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIlJlY3RhbmdsZSB3aWR0aCBtdXN0IGJlIGJldHdlZW4gMCBhbmQgMiAqIHBpIik7CiAgICAgICAgfQogICAgICAgIGlmIChyZWN0YW5nbGUuaGVpZ2h0IDwgMCB8fCByZWN0YW5nbGUuaGVpZ2h0ID4gTWF0aF9kZWZhdWx0LlBJKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiUmVjdGFuZ2xlIGhlaWdodCBtdXN0IGJlIGJldHdlZW4gMCBhbmQgcGkiKTsKICAgICAgICB9CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChlbGxpcHNvaWQpICYmICFNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIGVsbGlwc29pZC5yYWRpaS54LAogICAgICAgICAgZWxsaXBzb2lkLnJhZGlpLnksCiAgICAgICAgICBNYXRoX2RlZmF1bHQuRVBTSUxPTjE1CiAgICAgICAgKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJFbGxpcHNvaWQgbXVzdCBiZSBhbiBlbGxpcHNvaWQgb2YgcmV2b2x1dGlvbiAocmFkaWkueCA9PSByYWRpaS55KSIKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIG1pbmltdW1IZWlnaHQgPSBtaW5pbXVtSGVpZ2h0ID8/IDA7CiAgICAgICAgbWF4aW11bUhlaWdodCA9IG1heGltdW1IZWlnaHQgPz8gMDsKICAgICAgICBlbGxpcHNvaWQgPSBlbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgICAgICBsZXQgbWluWCwgbWF4WCwgbWluWSwgbWF4WSwgbWluWiwgbWF4WiwgcGxhbmU7CiAgICAgICAgaWYgKHJlY3RhbmdsZS53aWR0aCA8PSBNYXRoX2RlZmF1bHQuUEkpIHsKICAgICAgICAgIGNvbnN0IHRhbmdlbnRQb2ludENhcnRvZ3JhcGhpYyA9IFJlY3RhbmdsZV9kZWZhdWx0LmNlbnRlcigKICAgICAgICAgICAgcmVjdGFuZ2xlLAogICAgICAgICAgICBzY3JhdGNoUmVjdGFuZ2xlQ2VudGVyQ2FydG9ncmFwaGljCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgdGFuZ2VudFBvaW50ID0gZWxsaXBzb2lkLmNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuKAogICAgICAgICAgICB0YW5nZW50UG9pbnRDYXJ0b2dyYXBoaWMsCiAgICAgICAgICAgIHNjcmF0Y2hSZWN0YW5nbGVDZW50ZXIKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCB0YW5nZW50UGxhbmUgPSBuZXcgRWxsaXBzb2lkVGFuZ2VudFBsYW5lX2RlZmF1bHQodGFuZ2VudFBvaW50LCBlbGxpcHNvaWQpOwogICAgICAgICAgcGxhbmUgPSB0YW5nZW50UGxhbmUucGxhbmU7CiAgICAgICAgICBjb25zdCBsb25DZW50ZXIgPSB0YW5nZW50UG9pbnRDYXJ0b2dyYXBoaWMubG9uZ2l0dWRlOwogICAgICAgICAgY29uc3QgbGF0Q2VudGVyID0gcmVjdGFuZ2xlLnNvdXRoIDwgMCAmJiByZWN0YW5nbGUubm9ydGggPiAwID8gMCA6IHRhbmdlbnRQb2ludENhcnRvZ3JhcGhpYy5sYXRpdHVkZTsKICAgICAgICAgIGNvbnN0IHBlcmltZXRlckNhcnRvZ3JhcGhpY05DID0gQ2FydG9ncmFwaGljX2RlZmF1bHQuZnJvbVJhZGlhbnMoCiAgICAgICAgICAgIGxvbkNlbnRlciwKICAgICAgICAgICAgcmVjdGFuZ2xlLm5vcnRoLAogICAgICAgICAgICBtYXhpbXVtSGVpZ2h0LAogICAgICAgICAgICBzY3JhdGNoUGVyaW1ldGVyQ2FydG9ncmFwaGljTkMKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBwZXJpbWV0ZXJDYXJ0b2dyYXBoaWNOVyA9IENhcnRvZ3JhcGhpY19kZWZhdWx0LmZyb21SYWRpYW5zKAogICAgICAgICAgICByZWN0YW5nbGUud2VzdCwKICAgICAgICAgICAgcmVjdGFuZ2xlLm5vcnRoLAogICAgICAgICAgICBtYXhpbXVtSGVpZ2h0LAogICAgICAgICAgICBzY3JhdGNoUGVyaW1ldGVyQ2FydG9ncmFwaGljTlcKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBwZXJpbWV0ZXJDYXJ0b2dyYXBoaWNDVyA9IENhcnRvZ3JhcGhpY19kZWZhdWx0LmZyb21SYWRpYW5zKAogICAgICAgICAgICByZWN0YW5nbGUud2VzdCwKICAgICAgICAgICAgbGF0Q2VudGVyLAogICAgICAgICAgICBtYXhpbXVtSGVpZ2h0LAogICAgICAgICAgICBzY3JhdGNoUGVyaW1ldGVyQ2FydG9ncmFwaGljQ1cKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBwZXJpbWV0ZXJDYXJ0b2dyYXBoaWNTVyA9IENhcnRvZ3JhcGhpY19kZWZhdWx0LmZyb21SYWRpYW5zKAogICAgICAgICAgICByZWN0YW5nbGUud2VzdCwKICAgICAgICAgICAgcmVjdGFuZ2xlLnNvdXRoLAogICAgICAgICAgICBtYXhpbXVtSGVpZ2h0LAogICAgICAgICAgICBzY3JhdGNoUGVyaW1ldGVyQ2FydG9ncmFwaGljU1cKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBwZXJpbWV0ZXJDYXJ0b2dyYXBoaWNTQyA9IENhcnRvZ3JhcGhpY19kZWZhdWx0LmZyb21SYWRpYW5zKAogICAgICAgICAgICBsb25DZW50ZXIsCiAgICAgICAgICAgIHJlY3RhbmdsZS5zb3V0aCwKICAgICAgICAgICAgbWF4aW11bUhlaWdodCwKICAgICAgICAgICAgc2NyYXRjaFBlcmltZXRlckNhcnRvZ3JhcGhpY1NDCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgcGVyaW1ldGVyQ2FydGVzaWFuTkMgPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oCiAgICAgICAgICAgIHBlcmltZXRlckNhcnRvZ3JhcGhpY05DLAogICAgICAgICAgICBzY3JhdGNoUGVyaW1ldGVyQ2FydGVzaWFuTkMKICAgICAgICAgICk7CiAgICAgICAgICBsZXQgcGVyaW1ldGVyQ2FydGVzaWFuTlcgPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oCiAgICAgICAgICAgIHBlcmltZXRlckNhcnRvZ3JhcGhpY05XLAogICAgICAgICAgICBzY3JhdGNoUGVyaW1ldGVyQ2FydGVzaWFuTlcKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBwZXJpbWV0ZXJDYXJ0ZXNpYW5DVyA9IGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbigKICAgICAgICAgICAgcGVyaW1ldGVyQ2FydG9ncmFwaGljQ1csCiAgICAgICAgICAgIHNjcmF0Y2hQZXJpbWV0ZXJDYXJ0ZXNpYW5DVwogICAgICAgICAgKTsKICAgICAgICAgIGxldCBwZXJpbWV0ZXJDYXJ0ZXNpYW5TVyA9IGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbigKICAgICAgICAgICAgcGVyaW1ldGVyQ2FydG9ncmFwaGljU1csCiAgICAgICAgICAgIHNjcmF0Y2hQZXJpbWV0ZXJDYXJ0ZXNpYW5TVwogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IHBlcmltZXRlckNhcnRlc2lhblNDID0gZWxsaXBzb2lkLmNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuKAogICAgICAgICAgICBwZXJpbWV0ZXJDYXJ0b2dyYXBoaWNTQywKICAgICAgICAgICAgc2NyYXRjaFBlcmltZXRlckNhcnRlc2lhblNDCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgcGVyaW1ldGVyUHJvamVjdGVkTkMgPSB0YW5nZW50UGxhbmUucHJvamVjdFBvaW50VG9OZWFyZXN0T25QbGFuZSgKICAgICAgICAgICAgcGVyaW1ldGVyQ2FydGVzaWFuTkMsCiAgICAgICAgICAgIHNjcmF0Y2hQZXJpbWV0ZXJQcm9qZWN0ZWROQwogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IHBlcmltZXRlclByb2plY3RlZE5XID0gdGFuZ2VudFBsYW5lLnByb2plY3RQb2ludFRvTmVhcmVzdE9uUGxhbmUoCiAgICAgICAgICAgIHBlcmltZXRlckNhcnRlc2lhbk5XLAogICAgICAgICAgICBzY3JhdGNoUGVyaW1ldGVyUHJvamVjdGVkTlcKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBwZXJpbWV0ZXJQcm9qZWN0ZWRDVyA9IHRhbmdlbnRQbGFuZS5wcm9qZWN0UG9pbnRUb05lYXJlc3RPblBsYW5lKAogICAgICAgICAgICBwZXJpbWV0ZXJDYXJ0ZXNpYW5DVywKICAgICAgICAgICAgc2NyYXRjaFBlcmltZXRlclByb2plY3RlZENXCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgcGVyaW1ldGVyUHJvamVjdGVkU1cgPSB0YW5nZW50UGxhbmUucHJvamVjdFBvaW50VG9OZWFyZXN0T25QbGFuZSgKICAgICAgICAgICAgcGVyaW1ldGVyQ2FydGVzaWFuU1csCiAgICAgICAgICAgIHNjcmF0Y2hQZXJpbWV0ZXJQcm9qZWN0ZWRTVwogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IHBlcmltZXRlclByb2plY3RlZFNDID0gdGFuZ2VudFBsYW5lLnByb2plY3RQb2ludFRvTmVhcmVzdE9uUGxhbmUoCiAgICAgICAgICAgIHBlcmltZXRlckNhcnRlc2lhblNDLAogICAgICAgICAgICBzY3JhdGNoUGVyaW1ldGVyUHJvamVjdGVkU0MKICAgICAgICAgICk7CiAgICAgICAgICBtaW5YID0gTWF0aC5taW4oCiAgICAgICAgICAgIHBlcmltZXRlclByb2plY3RlZE5XLngsCiAgICAgICAgICAgIHBlcmltZXRlclByb2plY3RlZENXLngsCiAgICAgICAgICAgIHBlcmltZXRlclByb2plY3RlZFNXLngKICAgICAgICAgICk7CiAgICAgICAgICBtYXhYID0gLW1pblg7CiAgICAgICAgICBtYXhZID0gTWF0aC5tYXgocGVyaW1ldGVyUHJvamVjdGVkTlcueSwgcGVyaW1ldGVyUHJvamVjdGVkTkMueSk7CiAgICAgICAgICBtaW5ZID0gTWF0aC5taW4ocGVyaW1ldGVyUHJvamVjdGVkU1cueSwgcGVyaW1ldGVyUHJvamVjdGVkU0MueSk7CiAgICAgICAgICBwZXJpbWV0ZXJDYXJ0b2dyYXBoaWNOVy5oZWlnaHQgPSBwZXJpbWV0ZXJDYXJ0b2dyYXBoaWNTVy5oZWlnaHQgPSBtaW5pbXVtSGVpZ2h0OwogICAgICAgICAgcGVyaW1ldGVyQ2FydGVzaWFuTlcgPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oCiAgICAgICAgICAgIHBlcmltZXRlckNhcnRvZ3JhcGhpY05XLAogICAgICAgICAgICBzY3JhdGNoUGVyaW1ldGVyQ2FydGVzaWFuTlcKICAgICAgICAgICk7CiAgICAgICAgICBwZXJpbWV0ZXJDYXJ0ZXNpYW5TVyA9IGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbigKICAgICAgICAgICAgcGVyaW1ldGVyQ2FydG9ncmFwaGljU1csCiAgICAgICAgICAgIHNjcmF0Y2hQZXJpbWV0ZXJDYXJ0ZXNpYW5TVwogICAgICAgICAgKTsKICAgICAgICAgIG1pblogPSBNYXRoLm1pbigKICAgICAgICAgICAgUGxhbmVfZGVmYXVsdC5nZXRQb2ludERpc3RhbmNlKHBsYW5lLCBwZXJpbWV0ZXJDYXJ0ZXNpYW5OVyksCiAgICAgICAgICAgIFBsYW5lX2RlZmF1bHQuZ2V0UG9pbnREaXN0YW5jZShwbGFuZSwgcGVyaW1ldGVyQ2FydGVzaWFuU1cpCiAgICAgICAgICApOwogICAgICAgICAgbWF4WiA9IG1heGltdW1IZWlnaHQ7CiAgICAgICAgICByZXR1cm4gZnJvbVBsYW5lRXh0ZW50cygKICAgICAgICAgICAgdGFuZ2VudFBsYW5lLm9yaWdpbiwKICAgICAgICAgICAgdGFuZ2VudFBsYW5lLnhBeGlzLAogICAgICAgICAgICB0YW5nZW50UGxhbmUueUF4aXMsCiAgICAgICAgICAgIHRhbmdlbnRQbGFuZS56QXhpcywKICAgICAgICAgICAgbWluWCwKICAgICAgICAgICAgbWF4WCwKICAgICAgICAgICAgbWluWSwKICAgICAgICAgICAgbWF4WSwKICAgICAgICAgICAgbWluWiwKICAgICAgICAgICAgbWF4WiwKICAgICAgICAgICAgcmVzdWx0CiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBmdWxseUFib3ZlRXF1YXRvciA9IHJlY3RhbmdsZS5zb3V0aCA+IDA7CiAgICAgICAgY29uc3QgZnVsbHlCZWxvd0VxdWF0b3IgPSByZWN0YW5nbGUubm9ydGggPCAwOwogICAgICAgIGNvbnN0IGxhdGl0dWRlTmVhcmVzdFRvRXF1YXRvciA9IGZ1bGx5QWJvdmVFcXVhdG9yID8gcmVjdGFuZ2xlLnNvdXRoIDogZnVsbHlCZWxvd0VxdWF0b3IgPyByZWN0YW5nbGUubm9ydGggOiAwOwogICAgICAgIGNvbnN0IGNlbnRlckxvbmdpdHVkZSA9IFJlY3RhbmdsZV9kZWZhdWx0LmNlbnRlcigKICAgICAgICAgIHJlY3RhbmdsZSwKICAgICAgICAgIHNjcmF0Y2hSZWN0YW5nbGVDZW50ZXJDYXJ0b2dyYXBoaWMKICAgICAgICApLmxvbmdpdHVkZTsKICAgICAgICBjb25zdCBwbGFuZU9yaWdpbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tUmFkaWFucygKICAgICAgICAgIGNlbnRlckxvbmdpdHVkZSwKICAgICAgICAgIGxhdGl0dWRlTmVhcmVzdFRvRXF1YXRvciwKICAgICAgICAgIG1heGltdW1IZWlnaHQsCiAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICBzY3JhdGNoUGxhbmVPcmlnaW4KICAgICAgICApOwogICAgICAgIHBsYW5lT3JpZ2luLnogPSAwOwogICAgICAgIGNvbnN0IGlzUG9sZSA9IE1hdGguYWJzKHBsYW5lT3JpZ2luLngpIDwgTWF0aF9kZWZhdWx0LkVQU0lMT04xMCAmJiBNYXRoLmFicyhwbGFuZU9yaWdpbi55KSA8IE1hdGhfZGVmYXVsdC5FUFNJTE9OMTA7CiAgICAgICAgY29uc3QgcGxhbmVOb3JtYWwgPSAhaXNQb2xlID8gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShwbGFuZU9yaWdpbiwgc2NyYXRjaFBsYW5lTm9ybWFsKSA6IENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1g7CiAgICAgICAgY29uc3QgcGxhbmVZQXhpcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1o7CiAgICAgICAgY29uc3QgcGxhbmVYQXhpcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcygKICAgICAgICAgIHBsYW5lTm9ybWFsLAogICAgICAgICAgcGxhbmVZQXhpcywKICAgICAgICAgIHNjcmF0Y2hQbGFuZVhBeGlzCiAgICAgICAgKTsKICAgICAgICBwbGFuZSA9IFBsYW5lX2RlZmF1bHQuZnJvbVBvaW50Tm9ybWFsKHBsYW5lT3JpZ2luLCBwbGFuZU5vcm1hbCwgc2NyYXRjaFBsYW5lKTsKICAgICAgICBjb25zdCBob3Jpem9uQ2FydGVzaWFuID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21SYWRpYW5zKAogICAgICAgICAgY2VudGVyTG9uZ2l0dWRlICsgTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPLAogICAgICAgICAgbGF0aXR1ZGVOZWFyZXN0VG9FcXVhdG9yLAogICAgICAgICAgbWF4aW11bUhlaWdodCwKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIHNjcmF0Y2hIb3Jpem9uQ2FydGVzaWFuCiAgICAgICAgKTsKICAgICAgICBtYXhYID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdCgKICAgICAgICAgIFBsYW5lX2RlZmF1bHQucHJvamVjdFBvaW50T250b1BsYW5lKAogICAgICAgICAgICBwbGFuZSwKICAgICAgICAgICAgaG9yaXpvbkNhcnRlc2lhbiwKICAgICAgICAgICAgc2NyYXRjaEhvcml6b25Qcm9qZWN0ZWQKICAgICAgICAgICksCiAgICAgICAgICBwbGFuZVhBeGlzCiAgICAgICAgKTsKICAgICAgICBtaW5YID0gLW1heFg7CiAgICAgICAgbWF4WSA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tUmFkaWFucygKICAgICAgICAgIDAsCiAgICAgICAgICByZWN0YW5nbGUubm9ydGgsCiAgICAgICAgICBmdWxseUJlbG93RXF1YXRvciA/IG1pbmltdW1IZWlnaHQgOiBtYXhpbXVtSGVpZ2h0LAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgc2NyYXRjaE1heFkKICAgICAgICApLno7CiAgICAgICAgbWluWSA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tUmFkaWFucygKICAgICAgICAgIDAsCiAgICAgICAgICByZWN0YW5nbGUuc291dGgsCiAgICAgICAgICBmdWxseUFib3ZlRXF1YXRvciA/IG1pbmltdW1IZWlnaHQgOiBtYXhpbXVtSGVpZ2h0LAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgc2NyYXRjaE1pblkKICAgICAgICApLno7CiAgICAgICAgY29uc3QgZmFyWiA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tUmFkaWFucygKICAgICAgICAgIHJlY3RhbmdsZS5lYXN0LAogICAgICAgICAgbGF0aXR1ZGVOZWFyZXN0VG9FcXVhdG9yLAogICAgICAgICAgbWF4aW11bUhlaWdodCwKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIHNjcmF0Y2haCiAgICAgICAgKTsKICAgICAgICBtaW5aID0gUGxhbmVfZGVmYXVsdC5nZXRQb2ludERpc3RhbmNlKHBsYW5lLCBmYXJaKTsKICAgICAgICBtYXhaID0gMDsKICAgICAgICByZXR1cm4gZnJvbVBsYW5lRXh0ZW50cygKICAgICAgICAgIHBsYW5lT3JpZ2luLAogICAgICAgICAgcGxhbmVYQXhpcywKICAgICAgICAgIHBsYW5lWUF4aXMsCiAgICAgICAgICBwbGFuZU5vcm1hbCwKICAgICAgICAgIG1pblgsCiAgICAgICAgICBtYXhYLAogICAgICAgICAgbWluWSwKICAgICAgICAgIG1heFksCiAgICAgICAgICBtaW5aLAogICAgICAgICAgbWF4WiwKICAgICAgICAgIHJlc3VsdAogICAgICAgICk7CiAgICAgIH07CiAgICAgIE9yaWVudGVkQm91bmRpbmdCb3guZnJvbVRyYW5zZm9ybWF0aW9uID0gZnVuY3Rpb24odHJhbnNmb3JtYXRpb24sIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidHJhbnNmb3JtYXRpb24iLCB0cmFuc2Zvcm1hdGlvbik7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IE9yaWVudGVkQm91bmRpbmdCb3goKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmNlbnRlciA9IE1hdHJpeDRfZGVmYXVsdC5nZXRUcmFuc2xhdGlvbih0cmFuc2Zvcm1hdGlvbiwgcmVzdWx0LmNlbnRlcik7CiAgICAgICAgcmVzdWx0LmhhbGZBeGVzID0gTWF0cml4NF9kZWZhdWx0LmdldE1hdHJpeDModHJhbnNmb3JtYXRpb24sIHJlc3VsdC5oYWxmQXhlcyk7CiAgICAgICAgcmVzdWx0LmhhbGZBeGVzID0gTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgICByZXN1bHQuaGFsZkF4ZXMsCiAgICAgICAgICAwLjUsCiAgICAgICAgICByZXN1bHQuaGFsZkF4ZXMKICAgICAgICApOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE9yaWVudGVkQm91bmRpbmdCb3guY2xvbmUgPSBmdW5jdGlvbihib3gsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGJveCkpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgT3JpZW50ZWRCb3VuZGluZ0JveChib3guY2VudGVyLCBib3guaGFsZkF4ZXMpOwogICAgICAgIH0KICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoYm94LmNlbnRlciwgcmVzdWx0LmNlbnRlcik7CiAgICAgICAgTWF0cml4M19kZWZhdWx0LmNsb25lKGJveC5oYWxmQXhlcywgcmVzdWx0LmhhbGZBeGVzKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBPcmllbnRlZEJvdW5kaW5nQm94LmludGVyc2VjdFBsYW5lID0gZnVuY3Rpb24oYm94LCBwbGFuZSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGJveCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJib3ggaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBsYW5lKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInBsYW5lIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBjZW50ZXIgPSBib3guY2VudGVyOwogICAgICAgIGNvbnN0IG5vcm1hbDIgPSBwbGFuZS5ub3JtYWw7CiAgICAgICAgY29uc3QgaGFsZkF4ZXMgPSBib3guaGFsZkF4ZXM7CiAgICAgICAgY29uc3Qgbm9ybWFsWCA9IG5vcm1hbDIueCwgbm9ybWFsWSA9IG5vcm1hbDIueSwgbm9ybWFsWiA9IG5vcm1hbDIuejsKICAgICAgICBjb25zdCByYWRFZmZlY3RpdmUgPSBNYXRoLmFicygKICAgICAgICAgIG5vcm1hbFggKiBoYWxmQXhlc1tNYXRyaXgzX2RlZmF1bHQuQ09MVU1OMFJPVzBdICsgbm9ybWFsWSAqIGhhbGZBeGVzW01hdHJpeDNfZGVmYXVsdC5DT0xVTU4wUk9XMV0gKyBub3JtYWxaICogaGFsZkF4ZXNbTWF0cml4M19kZWZhdWx0LkNPTFVNTjBST1cyXQogICAgICAgICkgKyBNYXRoLmFicygKICAgICAgICAgIG5vcm1hbFggKiBoYWxmQXhlc1tNYXRyaXgzX2RlZmF1bHQuQ09MVU1OMVJPVzBdICsgbm9ybWFsWSAqIGhhbGZBeGVzW01hdHJpeDNfZGVmYXVsdC5DT0xVTU4xUk9XMV0gKyBub3JtYWxaICogaGFsZkF4ZXNbTWF0cml4M19kZWZhdWx0LkNPTFVNTjFST1cyXQogICAgICAgICkgKyBNYXRoLmFicygKICAgICAgICAgIG5vcm1hbFggKiBoYWxmQXhlc1tNYXRyaXgzX2RlZmF1bHQuQ09MVU1OMlJPVzBdICsgbm9ybWFsWSAqIGhhbGZBeGVzW01hdHJpeDNfZGVmYXVsdC5DT0xVTU4yUk9XMV0gKyBub3JtYWxaICogaGFsZkF4ZXNbTWF0cml4M19kZWZhdWx0LkNPTFVNTjJST1cyXQogICAgICAgICk7CiAgICAgICAgY29uc3QgZGlzdGFuY2VUb1BsYW5lID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChub3JtYWwyLCBjZW50ZXIpICsgcGxhbmUuZGlzdGFuY2U7CiAgICAgICAgaWYgKGRpc3RhbmNlVG9QbGFuZSA8PSAtcmFkRWZmZWN0aXZlKSB7CiAgICAgICAgICByZXR1cm4gSW50ZXJzZWN0X2RlZmF1bHQuT1VUU0lERTsKICAgICAgICB9IGVsc2UgaWYgKGRpc3RhbmNlVG9QbGFuZSA+PSByYWRFZmZlY3RpdmUpIHsKICAgICAgICAgIHJldHVybiBJbnRlcnNlY3RfZGVmYXVsdC5JTlNJREU7CiAgICAgICAgfQogICAgICAgIHJldHVybiBJbnRlcnNlY3RfZGVmYXVsdC5JTlRFUlNFQ1RJTkc7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW5VID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydGVzaWFuViA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhblcgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hWYWxpZEF4aXMyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoVmFsaWRBeGlzMyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBQcmltZSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgT3JpZW50ZWRCb3VuZGluZ0JveC5kaXN0YW5jZVNxdWFyZWRUbyA9IGZ1bmN0aW9uKGJveCwgY2FydGVzaWFuMTEpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChib3gpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYm94IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChjYXJ0ZXNpYW4xMSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJjYXJ0ZXNpYW4gaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG9mZnNldCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjYXJ0ZXNpYW4xMSwgYm94LmNlbnRlciwgc2NyYXRjaE9mZnNldCk7CiAgICAgICAgY29uc3QgaGFsZkF4ZXMgPSBib3guaGFsZkF4ZXM7CiAgICAgICAgbGV0IHUzID0gTWF0cml4M19kZWZhdWx0LmdldENvbHVtbihoYWxmQXhlcywgMCwgc2NyYXRjaENhcnRlc2lhblUpOwogICAgICAgIGxldCB2MyA9IE1hdHJpeDNfZGVmYXVsdC5nZXRDb2x1bW4oaGFsZkF4ZXMsIDEsIHNjcmF0Y2hDYXJ0ZXNpYW5WKTsKICAgICAgICBsZXQgdyA9IE1hdHJpeDNfZGVmYXVsdC5nZXRDb2x1bW4oaGFsZkF4ZXMsIDIsIHNjcmF0Y2hDYXJ0ZXNpYW5XKTsKICAgICAgICBjb25zdCB1SGFsZiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUodTMpOwogICAgICAgIGNvbnN0IHZIYWxmID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZSh2Myk7CiAgICAgICAgY29uc3Qgd0hhbGYgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKHcpOwogICAgICAgIGxldCB1VmFsaWQgPSB0cnVlOwogICAgICAgIGxldCB2VmFsaWQgPSB0cnVlOwogICAgICAgIGxldCB3VmFsaWQgPSB0cnVlOwogICAgICAgIGlmICh1SGFsZiA+IDApIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5kaXZpZGVCeVNjYWxhcih1MywgdUhhbGYsIHUzKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdVZhbGlkID0gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGlmICh2SGFsZiA+IDApIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5kaXZpZGVCeVNjYWxhcih2MywgdkhhbGYsIHYzKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdlZhbGlkID0gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGlmICh3SGFsZiA+IDApIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5kaXZpZGVCeVNjYWxhcih3LCB3SGFsZiwgdyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHdWYWxpZCA9IGZhbHNlOwogICAgICAgIH0KICAgICAgICBjb25zdCBudW1iZXJPZkRlZ2VuZXJhdGVBeGVzID0gIXVWYWxpZCArICF2VmFsaWQgKyAhd1ZhbGlkOwogICAgICAgIGxldCB2YWxpZEF4aXMxOwogICAgICAgIGxldCB2YWxpZEF4aXMyOwogICAgICAgIGxldCB2YWxpZEF4aXMzOwogICAgICAgIGlmIChudW1iZXJPZkRlZ2VuZXJhdGVBeGVzID09PSAxKSB7CiAgICAgICAgICBsZXQgZGVnZW5lcmF0ZUF4aXMgPSB1MzsKICAgICAgICAgIHZhbGlkQXhpczEgPSB2MzsKICAgICAgICAgIHZhbGlkQXhpczIgPSB3OwogICAgICAgICAgaWYgKCF2VmFsaWQpIHsKICAgICAgICAgICAgZGVnZW5lcmF0ZUF4aXMgPSB2MzsKICAgICAgICAgICAgdmFsaWRBeGlzMSA9IHUzOwogICAgICAgICAgfSBlbHNlIGlmICghd1ZhbGlkKSB7CiAgICAgICAgICAgIGRlZ2VuZXJhdGVBeGlzID0gdzsKICAgICAgICAgICAgdmFsaWRBeGlzMiA9IHUzOwogICAgICAgICAgfQogICAgICAgICAgdmFsaWRBeGlzMyA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyh2YWxpZEF4aXMxLCB2YWxpZEF4aXMyLCBzY3JhdGNoVmFsaWRBeGlzMyk7CiAgICAgICAgICBpZiAoZGVnZW5lcmF0ZUF4aXMgPT09IHUzKSB7CiAgICAgICAgICAgIHUzID0gdmFsaWRBeGlzMzsKICAgICAgICAgIH0gZWxzZSBpZiAoZGVnZW5lcmF0ZUF4aXMgPT09IHYzKSB7CiAgICAgICAgICAgIHYzID0gdmFsaWRBeGlzMzsKICAgICAgICAgIH0gZWxzZSBpZiAoZGVnZW5lcmF0ZUF4aXMgPT09IHcpIHsKICAgICAgICAgICAgdyA9IHZhbGlkQXhpczM7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChudW1iZXJPZkRlZ2VuZXJhdGVBeGVzID09PSAyKSB7CiAgICAgICAgICB2YWxpZEF4aXMxID0gdTM7CiAgICAgICAgICBpZiAodlZhbGlkKSB7CiAgICAgICAgICAgIHZhbGlkQXhpczEgPSB2MzsKICAgICAgICAgIH0gZWxzZSBpZiAod1ZhbGlkKSB7CiAgICAgICAgICAgIHZhbGlkQXhpczEgPSB3OwogICAgICAgICAgfQogICAgICAgICAgbGV0IGNyb3NzVmVjdG9yID0gQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWTsKICAgICAgICAgIGlmIChjcm9zc1ZlY3Rvci5lcXVhbHNFcHNpbG9uKHZhbGlkQXhpczEsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMykpIHsKICAgICAgICAgICAgY3Jvc3NWZWN0b3IgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9YOwogICAgICAgICAgfQogICAgICAgICAgdmFsaWRBeGlzMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyh2YWxpZEF4aXMxLCBjcm9zc1ZlY3Rvciwgc2NyYXRjaFZhbGlkQXhpczIpOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSh2YWxpZEF4aXMyLCB2YWxpZEF4aXMyKTsKICAgICAgICAgIHZhbGlkQXhpczMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3ModmFsaWRBeGlzMSwgdmFsaWRBeGlzMiwgc2NyYXRjaFZhbGlkQXhpczMpOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSh2YWxpZEF4aXMzLCB2YWxpZEF4aXMzKTsKICAgICAgICAgIGlmICh2YWxpZEF4aXMxID09PSB1MykgewogICAgICAgICAgICB2MyA9IHZhbGlkQXhpczI7CiAgICAgICAgICAgIHcgPSB2YWxpZEF4aXMzOwogICAgICAgICAgfSBlbHNlIGlmICh2YWxpZEF4aXMxID09PSB2MykgewogICAgICAgICAgICB3ID0gdmFsaWRBeGlzMjsKICAgICAgICAgICAgdTMgPSB2YWxpZEF4aXMzOwogICAgICAgICAgfSBlbHNlIGlmICh2YWxpZEF4aXMxID09PSB3KSB7CiAgICAgICAgICAgIHUzID0gdmFsaWRBeGlzMjsKICAgICAgICAgICAgdjMgPSB2YWxpZEF4aXMzOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAobnVtYmVyT2ZEZWdlbmVyYXRlQXhlcyA9PT0gMykgewogICAgICAgICAgdTMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9YOwogICAgICAgICAgdjMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9ZOwogICAgICAgICAgdyA9IENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1o7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHBQcmltZSA9IHNjcmF0Y2hQUHJpbWU7CiAgICAgICAgcFByaW1lLnggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KG9mZnNldCwgdTMpOwogICAgICAgIHBQcmltZS55ID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChvZmZzZXQsIHYzKTsKICAgICAgICBwUHJpbWUueiA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3Qob2Zmc2V0LCB3KTsKICAgICAgICBsZXQgZGlzdGFuY2VTcXVhcmVkID0gMDsKICAgICAgICBsZXQgZDsKICAgICAgICBpZiAocFByaW1lLnggPCAtdUhhbGYpIHsKICAgICAgICAgIGQgPSBwUHJpbWUueCArIHVIYWxmOwogICAgICAgICAgZGlzdGFuY2VTcXVhcmVkICs9IGQgKiBkOwogICAgICAgIH0gZWxzZSBpZiAocFByaW1lLnggPiB1SGFsZikgewogICAgICAgICAgZCA9IHBQcmltZS54IC0gdUhhbGY7CiAgICAgICAgICBkaXN0YW5jZVNxdWFyZWQgKz0gZCAqIGQ7CiAgICAgICAgfQogICAgICAgIGlmIChwUHJpbWUueSA8IC12SGFsZikgewogICAgICAgICAgZCA9IHBQcmltZS55ICsgdkhhbGY7CiAgICAgICAgICBkaXN0YW5jZVNxdWFyZWQgKz0gZCAqIGQ7CiAgICAgICAgfSBlbHNlIGlmIChwUHJpbWUueSA+IHZIYWxmKSB7CiAgICAgICAgICBkID0gcFByaW1lLnkgLSB2SGFsZjsKICAgICAgICAgIGRpc3RhbmNlU3F1YXJlZCArPSBkICogZDsKICAgICAgICB9CiAgICAgICAgaWYgKHBQcmltZS56IDwgLXdIYWxmKSB7CiAgICAgICAgICBkID0gcFByaW1lLnogKyB3SGFsZjsKICAgICAgICAgIGRpc3RhbmNlU3F1YXJlZCArPSBkICogZDsKICAgICAgICB9IGVsc2UgaWYgKHBQcmltZS56ID4gd0hhbGYpIHsKICAgICAgICAgIGQgPSBwUHJpbWUueiAtIHdIYWxmOwogICAgICAgICAgZGlzdGFuY2VTcXVhcmVkICs9IGQgKiBkOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZGlzdGFuY2VTcXVhcmVkOwogICAgICB9OwogICAgICBzY3JhdGNoQ29ybmVyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoVG9DZW50ZXIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIE9yaWVudGVkQm91bmRpbmdCb3guY29tcHV0ZVBsYW5lRGlzdGFuY2VzID0gZnVuY3Rpb24oYm94LCBwb3NpdGlvbiwgZGlyZWN0aW9uMiwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYm94KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImJveCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocG9zaXRpb24pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicG9zaXRpb24gaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGRpcmVjdGlvbjIpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZGlyZWN0aW9uIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgSW50ZXJ2YWxfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICBsZXQgbWluRGlzdCA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTsKICAgICAgICBsZXQgbWF4RGlzdCA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgICAgICBjb25zdCBjZW50ZXIgPSBib3guY2VudGVyOwogICAgICAgIGNvbnN0IGhhbGZBeGVzID0gYm94LmhhbGZBeGVzOwogICAgICAgIGNvbnN0IHUzID0gTWF0cml4M19kZWZhdWx0LmdldENvbHVtbihoYWxmQXhlcywgMCwgc2NyYXRjaENhcnRlc2lhblUpOwogICAgICAgIGNvbnN0IHYzID0gTWF0cml4M19kZWZhdWx0LmdldENvbHVtbihoYWxmQXhlcywgMSwgc2NyYXRjaENhcnRlc2lhblYpOwogICAgICAgIGNvbnN0IHcgPSBNYXRyaXgzX2RlZmF1bHQuZ2V0Q29sdW1uKGhhbGZBeGVzLCAyLCBzY3JhdGNoQ2FydGVzaWFuVyk7CiAgICAgICAgY29uc3QgY29ybmVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZCh1MywgdjMsIHNjcmF0Y2hDb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoY29ybmVyLCB3LCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoY29ybmVyLCBjZW50ZXIsIGNvcm5lcik7CiAgICAgICAgY29uc3QgdG9DZW50ZXIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoY29ybmVyLCBwb3NpdGlvbiwgc2NyYXRjaFRvQ2VudGVyKTsKICAgICAgICBsZXQgbWFnID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCB0b0NlbnRlcik7CiAgICAgICAgbWluRGlzdCA9IE1hdGgubWluKG1hZywgbWluRGlzdCk7CiAgICAgICAgbWF4RGlzdCA9IE1hdGgubWF4KG1hZywgbWF4RGlzdCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChjZW50ZXIsIHUzLCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoY29ybmVyLCB2MywgY29ybmVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoY29ybmVyLCB3LCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjb3JuZXIsIHBvc2l0aW9uLCB0b0NlbnRlcik7CiAgICAgICAgbWFnID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCB0b0NlbnRlcik7CiAgICAgICAgbWluRGlzdCA9IE1hdGgubWluKG1hZywgbWluRGlzdCk7CiAgICAgICAgbWF4RGlzdCA9IE1hdGgubWF4KG1hZywgbWF4RGlzdCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChjZW50ZXIsIHUzLCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjb3JuZXIsIHYzLCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoY29ybmVyLCB3LCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjb3JuZXIsIHBvc2l0aW9uLCB0b0NlbnRlcik7CiAgICAgICAgbWFnID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCB0b0NlbnRlcik7CiAgICAgICAgbWluRGlzdCA9IE1hdGgubWluKG1hZywgbWluRGlzdCk7CiAgICAgICAgbWF4RGlzdCA9IE1hdGgubWF4KG1hZywgbWF4RGlzdCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChjZW50ZXIsIHUzLCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjb3JuZXIsIHYzLCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjb3JuZXIsIHcsIGNvcm5lcik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGNvcm5lciwgcG9zaXRpb24sIHRvQ2VudGVyKTsKICAgICAgICBtYWcgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KGRpcmVjdGlvbjIsIHRvQ2VudGVyKTsKICAgICAgICBtaW5EaXN0ID0gTWF0aC5taW4obWFnLCBtaW5EaXN0KTsKICAgICAgICBtYXhEaXN0ID0gTWF0aC5tYXgobWFnLCBtYXhEaXN0KTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoY2VudGVyLCB1MywgY29ybmVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNvcm5lciwgdjMsIGNvcm5lcik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChjb3JuZXIsIHcsIGNvcm5lcik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGNvcm5lciwgcG9zaXRpb24sIHRvQ2VudGVyKTsKICAgICAgICBtYWcgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KGRpcmVjdGlvbjIsIHRvQ2VudGVyKTsKICAgICAgICBtaW5EaXN0ID0gTWF0aC5taW4obWFnLCBtaW5EaXN0KTsKICAgICAgICBtYXhEaXN0ID0gTWF0aC5tYXgobWFnLCBtYXhEaXN0KTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoY2VudGVyLCB1MywgY29ybmVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNvcm5lciwgdjMsIGNvcm5lcik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGNvcm5lciwgdywgY29ybmVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoY29ybmVyLCBwb3NpdGlvbiwgdG9DZW50ZXIpOwogICAgICAgIG1hZyA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QoZGlyZWN0aW9uMiwgdG9DZW50ZXIpOwogICAgICAgIG1pbkRpc3QgPSBNYXRoLm1pbihtYWcsIG1pbkRpc3QpOwogICAgICAgIG1heERpc3QgPSBNYXRoLm1heChtYWcsIG1heERpc3QpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjZW50ZXIsIHUzLCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjb3JuZXIsIHYzLCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoY29ybmVyLCB3LCBjb3JuZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChjb3JuZXIsIHBvc2l0aW9uLCB0b0NlbnRlcik7CiAgICAgICAgbWFnID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCB0b0NlbnRlcik7CiAgICAgICAgbWluRGlzdCA9IE1hdGgubWluKG1hZywgbWluRGlzdCk7CiAgICAgICAgbWF4RGlzdCA9IE1hdGgubWF4KG1hZywgbWF4RGlzdCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGNlbnRlciwgdTMsIGNvcm5lcik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGNvcm5lciwgdjMsIGNvcm5lcik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGNvcm5lciwgdywgY29ybmVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoY29ybmVyLCBwb3NpdGlvbiwgdG9DZW50ZXIpOwogICAgICAgIG1hZyA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QoZGlyZWN0aW9uMiwgdG9DZW50ZXIpOwogICAgICAgIG1pbkRpc3QgPSBNYXRoLm1pbihtYWcsIG1pbkRpc3QpOwogICAgICAgIG1heERpc3QgPSBNYXRoLm1heChtYWcsIG1heERpc3QpOwogICAgICAgIHJlc3VsdC5zdGFydCA9IG1pbkRpc3Q7CiAgICAgICAgcmVzdWx0LnN0b3AgPSBtYXhEaXN0OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hYQXhpcyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFlBeGlzID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoWkF4aXMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIE9yaWVudGVkQm91bmRpbmdCb3guY29tcHV0ZUNvcm5lcnMgPSBmdW5jdGlvbihib3gsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiYm94IiwgYm94KTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBbCiAgICAgICAgICAgIG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKSwKICAgICAgICAgICAgbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpLAogICAgICAgICAgICBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCksCiAgICAgICAgICAgIG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKSwKICAgICAgICAgICAgbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpLAogICAgICAgICAgICBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCksCiAgICAgICAgICAgIG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKSwKICAgICAgICAgICAgbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpCiAgICAgICAgICBdOwogICAgICAgIH0KICAgICAgICBjb25zdCBjZW50ZXIgPSBib3guY2VudGVyOwogICAgICAgIGNvbnN0IGhhbGZBeGVzID0gYm94LmhhbGZBeGVzOwogICAgICAgIGNvbnN0IHhBeGlzID0gTWF0cml4M19kZWZhdWx0LmdldENvbHVtbihoYWxmQXhlcywgMCwgc2NyYXRjaFhBeGlzKTsKICAgICAgICBjb25zdCB5QXhpcyA9IE1hdHJpeDNfZGVmYXVsdC5nZXRDb2x1bW4oaGFsZkF4ZXMsIDEsIHNjcmF0Y2hZQXhpcyk7CiAgICAgICAgY29uc3QgekF4aXMgPSBNYXRyaXgzX2RlZmF1bHQuZ2V0Q29sdW1uKGhhbGZBeGVzLCAyLCBzY3JhdGNoWkF4aXMpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjZW50ZXIsIHJlc3VsdFswXSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHJlc3VsdFswXSwgeEF4aXMsIHJlc3VsdFswXSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHJlc3VsdFswXSwgeUF4aXMsIHJlc3VsdFswXSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHJlc3VsdFswXSwgekF4aXMsIHJlc3VsdFswXSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGNlbnRlciwgcmVzdWx0WzFdKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QocmVzdWx0WzFdLCB4QXhpcywgcmVzdWx0WzFdKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QocmVzdWx0WzFdLCB5QXhpcywgcmVzdWx0WzFdKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHJlc3VsdFsxXSwgekF4aXMsIHJlc3VsdFsxXSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGNlbnRlciwgcmVzdWx0WzJdKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QocmVzdWx0WzJdLCB4QXhpcywgcmVzdWx0WzJdKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHJlc3VsdFsyXSwgeUF4aXMsIHJlc3VsdFsyXSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHJlc3VsdFsyXSwgekF4aXMsIHJlc3VsdFsyXSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGNlbnRlciwgcmVzdWx0WzNdKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QocmVzdWx0WzNdLCB4QXhpcywgcmVzdWx0WzNdKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHJlc3VsdFszXSwgeUF4aXMsIHJlc3VsdFszXSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChyZXN1bHRbM10sIHpBeGlzLCByZXN1bHRbM10pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjZW50ZXIsIHJlc3VsdFs0XSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChyZXN1bHRbNF0sIHhBeGlzLCByZXN1bHRbNF0pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChyZXN1bHRbNF0sIHlBeGlzLCByZXN1bHRbNF0pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChyZXN1bHRbNF0sIHpBeGlzLCByZXN1bHRbNF0pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjZW50ZXIsIHJlc3VsdFs1XSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChyZXN1bHRbNV0sIHhBeGlzLCByZXN1bHRbNV0pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChyZXN1bHRbNV0sIHlBeGlzLCByZXN1bHRbNV0pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocmVzdWx0WzVdLCB6QXhpcywgcmVzdWx0WzVdKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY2VudGVyLCByZXN1bHRbNl0pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocmVzdWx0WzZdLCB4QXhpcywgcmVzdWx0WzZdKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHJlc3VsdFs2XSwgeUF4aXMsIHJlc3VsdFs2XSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHJlc3VsdFs2XSwgekF4aXMsIHJlc3VsdFs2XSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGNlbnRlciwgcmVzdWx0WzddKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHJlc3VsdFs3XSwgeEF4aXMsIHJlc3VsdFs3XSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChyZXN1bHRbN10sIHlBeGlzLCByZXN1bHRbN10pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocmVzdWx0WzddLCB6QXhpcywgcmVzdWx0WzddKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBzY3JhdGNoUm90YXRpb25TY2FsZSA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgT3JpZW50ZWRCb3VuZGluZ0JveC5jb21wdXRlVHJhbnNmb3JtYXRpb24gPSBmdW5jdGlvbihib3gsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiYm94IiwgYm94KTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgTWF0cml4NF9kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHRyYW5zbGF0aW9uMiA9IGJveC5jZW50ZXI7CiAgICAgICAgY29uc3Qgcm90YXRpb25TY2FsZSA9IE1hdHJpeDNfZGVmYXVsdC5tdWx0aXBseUJ5VW5pZm9ybVNjYWxlKAogICAgICAgICAgYm94LmhhbGZBeGVzLAogICAgICAgICAgMiwKICAgICAgICAgIHNjcmF0Y2hSb3RhdGlvblNjYWxlCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gTWF0cml4NF9kZWZhdWx0LmZyb21Sb3RhdGlvblRyYW5zbGF0aW9uKHJvdGF0aW9uU2NhbGUsIHRyYW5zbGF0aW9uMiwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgc2NyYXRjaEJvdW5kaW5nU3BoZXJlID0gbmV3IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQoKTsKICAgICAgT3JpZW50ZWRCb3VuZGluZ0JveC5pc09jY2x1ZGVkID0gZnVuY3Rpb24oYm94LCBvY2NsdWRlcikgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGJveCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJib3ggaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG9jY2x1ZGVyKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9jY2x1ZGVyIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBzcGhlcmUgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21PcmllbnRlZEJvdW5kaW5nQm94KAogICAgICAgICAgYm94LAogICAgICAgICAgc2NyYXRjaEJvdW5kaW5nU3BoZXJlCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gIW9jY2x1ZGVyLmlzQm91bmRpbmdTcGhlcmVWaXNpYmxlKHNwaGVyZSk7CiAgICAgIH07CiAgICAgIE9yaWVudGVkQm91bmRpbmdCb3gucHJvdG90eXBlLmludGVyc2VjdFBsYW5lID0gZnVuY3Rpb24ocGxhbmUpIHsKICAgICAgICByZXR1cm4gT3JpZW50ZWRCb3VuZGluZ0JveC5pbnRlcnNlY3RQbGFuZSh0aGlzLCBwbGFuZSk7CiAgICAgIH07CiAgICAgIE9yaWVudGVkQm91bmRpbmdCb3gucHJvdG90eXBlLmRpc3RhbmNlU3F1YXJlZFRvID0gZnVuY3Rpb24oY2FydGVzaWFuMTEpIHsKICAgICAgICByZXR1cm4gT3JpZW50ZWRCb3VuZGluZ0JveC5kaXN0YW5jZVNxdWFyZWRUbyh0aGlzLCBjYXJ0ZXNpYW4xMSk7CiAgICAgIH07CiAgICAgIE9yaWVudGVkQm91bmRpbmdCb3gucHJvdG90eXBlLmNvbXB1dGVQbGFuZURpc3RhbmNlcyA9IGZ1bmN0aW9uKHBvc2l0aW9uLCBkaXJlY3Rpb24yLCByZXN1bHQpIHsKICAgICAgICByZXR1cm4gT3JpZW50ZWRCb3VuZGluZ0JveC5jb21wdXRlUGxhbmVEaXN0YW5jZXMoCiAgICAgICAgICB0aGlzLAogICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICBkaXJlY3Rpb24yLAogICAgICAgICAgcmVzdWx0CiAgICAgICAgKTsKICAgICAgfTsKICAgICAgT3JpZW50ZWRCb3VuZGluZ0JveC5wcm90b3R5cGUuY29tcHV0ZUNvcm5lcnMgPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICByZXR1cm4gT3JpZW50ZWRCb3VuZGluZ0JveC5jb21wdXRlQ29ybmVycyh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBPcmllbnRlZEJvdW5kaW5nQm94LnByb3RvdHlwZS5jb21wdXRlVHJhbnNmb3JtYXRpb24gPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICByZXR1cm4gT3JpZW50ZWRCb3VuZGluZ0JveC5jb21wdXRlVHJhbnNmb3JtYXRpb24odGhpcywgcmVzdWx0KTsKICAgICAgfTsKICAgICAgT3JpZW50ZWRCb3VuZGluZ0JveC5wcm90b3R5cGUuaXNPY2NsdWRlZCA9IGZ1bmN0aW9uKG9jY2x1ZGVyKSB7CiAgICAgICAgcmV0dXJuIE9yaWVudGVkQm91bmRpbmdCb3guaXNPY2NsdWRlZCh0aGlzLCBvY2NsdWRlcik7CiAgICAgIH07CiAgICAgIE9yaWVudGVkQm91bmRpbmdCb3guZXF1YWxzID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHsKICAgICAgICByZXR1cm4gbGVmdCA9PT0gcmlnaHQgfHwgZGVmaW5lZF9kZWZhdWx0KGxlZnQpICYmIGRlZmluZWRfZGVmYXVsdChyaWdodCkgJiYgQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFscyhsZWZ0LmNlbnRlciwgcmlnaHQuY2VudGVyKSAmJiBNYXRyaXgzX2RlZmF1bHQuZXF1YWxzKGxlZnQuaGFsZkF4ZXMsIHJpZ2h0LmhhbGZBeGVzKTsKICAgICAgfTsKICAgICAgT3JpZW50ZWRCb3VuZGluZ0JveC5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICByZXR1cm4gT3JpZW50ZWRCb3VuZGluZ0JveC5jbG9uZSh0aGlzLCByZXN1bHQpOwogICAgICB9OwogICAgICBPcmllbnRlZEJvdW5kaW5nQm94LnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbihyaWdodCkgewogICAgICAgIHJldHVybiBPcmllbnRlZEJvdW5kaW5nQm94LmVxdWFscyh0aGlzLCByaWdodCk7CiAgICAgIH07CiAgICAgIE9yaWVudGVkQm91bmRpbmdCb3hfZGVmYXVsdCA9IE9yaWVudGVkQm91bmRpbmdCb3g7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Db3BsYW5hclBvbHlnb25HZW9tZXRyeUxpYnJhcnkuanMKICBmdW5jdGlvbiBwcm9qZWN0VG8yRChwb3NpdGlvbiwgY2VudGVyLCBheGlzMSwgYXhpczIsIHJlc3VsdCkgewogICAgY29uc3QgdjMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QocG9zaXRpb24sIGNlbnRlciwgc2NyYXRjaEludGVyc2VjdGlvblBvaW50KTsKICAgIGNvbnN0IHggPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KGF4aXMxLCB2Myk7CiAgICBjb25zdCB5ID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChheGlzMiwgdjMpOwogICAgcmV0dXJuIENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHMoeCwgeSwgcmVzdWx0KTsKICB9CiAgdmFyIENvcGxhbmFyUG9seWdvbkdlb21ldHJ5TGlicmFyeSwgc2NyYXRjaEludGVyc2VjdGlvblBvaW50LCBzY3JhdGNoWEF4aXMyLCBzY3JhdGNoWUF4aXMyLCBzY3JhdGNoWkF4aXMyLCBvYmJTY3JhdGNoLCBDb3BsYW5hclBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdDsKICB2YXIgaW5pdF9Db3BsYW5hclBvbHlnb25HZW9tZXRyeUxpYnJhcnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NvcGxhbmFyUG9seWdvbkdlb21ldHJ5TGlicmFyeS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMigpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X01hdHJpeDMoKTsKICAgICAgaW5pdF9PcmllbnRlZEJvdW5kaW5nQm94KCk7CiAgICAgIENvcGxhbmFyUG9seWdvbkdlb21ldHJ5TGlicmFyeSA9IHt9OwogICAgICBzY3JhdGNoSW50ZXJzZWN0aW9uUG9pbnQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hYQXhpczIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hZQXhpczIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2haQXhpczIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIG9iYlNjcmF0Y2ggPSBuZXcgT3JpZW50ZWRCb3VuZGluZ0JveF9kZWZhdWx0KCk7CiAgICAgIENvcGxhbmFyUG9seWdvbkdlb21ldHJ5TGlicmFyeS52YWxpZE91dGxpbmUgPSBmdW5jdGlvbihwb3NpdGlvbnMpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInBvc2l0aW9ucyIsIHBvc2l0aW9ucyk7CiAgICAgICAgY29uc3Qgb3JpZW50ZWRCb3VuZGluZ0JveCA9IE9yaWVudGVkQm91bmRpbmdCb3hfZGVmYXVsdC5mcm9tUG9pbnRzKAogICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgb2JiU2NyYXRjaAogICAgICAgICk7CiAgICAgICAgY29uc3QgaGFsZkF4ZXMgPSBvcmllbnRlZEJvdW5kaW5nQm94LmhhbGZBeGVzOwogICAgICAgIGNvbnN0IHhBeGlzID0gTWF0cml4M19kZWZhdWx0LmdldENvbHVtbihoYWxmQXhlcywgMCwgc2NyYXRjaFhBeGlzMik7CiAgICAgICAgY29uc3QgeUF4aXMgPSBNYXRyaXgzX2RlZmF1bHQuZ2V0Q29sdW1uKGhhbGZBeGVzLCAxLCBzY3JhdGNoWUF4aXMyKTsKICAgICAgICBjb25zdCB6QXhpcyA9IE1hdHJpeDNfZGVmYXVsdC5nZXRDb2x1bW4oaGFsZkF4ZXMsIDIsIHNjcmF0Y2haQXhpczIpOwogICAgICAgIGNvbnN0IHhNYWcgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKHhBeGlzKTsKICAgICAgICBjb25zdCB5TWFnID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZSh5QXhpcyk7CiAgICAgICAgY29uc3Qgek1hZyA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUoekF4aXMpOwogICAgICAgIHJldHVybiAhKHhNYWcgPT09IDAgJiYgKHlNYWcgPT09IDAgfHwgek1hZyA9PT0gMCkgfHwgeU1hZyA9PT0gMCAmJiB6TWFnID09PSAwKTsKICAgICAgfTsKICAgICAgQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LmNvbXB1dGVQcm9qZWN0VG8yREFyZ3VtZW50cyA9IGZ1bmN0aW9uKHBvc2l0aW9ucywgY2VudGVyUmVzdWx0LCBwbGFuZUF4aXMxUmVzdWx0LCBwbGFuZUF4aXMyUmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJwb3NpdGlvbnMiLCBwb3NpdGlvbnMpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiY2VudGVyUmVzdWx0IiwgY2VudGVyUmVzdWx0KTsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInBsYW5lQXhpczFSZXN1bHQiLCBwbGFuZUF4aXMxUmVzdWx0KTsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInBsYW5lQXhpczJSZXN1bHQiLCBwbGFuZUF4aXMyUmVzdWx0KTsKICAgICAgICBjb25zdCBvcmllbnRlZEJvdW5kaW5nQm94ID0gT3JpZW50ZWRCb3VuZGluZ0JveF9kZWZhdWx0LmZyb21Qb2ludHMoCiAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICBvYmJTY3JhdGNoCiAgICAgICAgKTsKICAgICAgICBjb25zdCBoYWxmQXhlcyA9IG9yaWVudGVkQm91bmRpbmdCb3guaGFsZkF4ZXM7CiAgICAgICAgY29uc3QgeEF4aXMgPSBNYXRyaXgzX2RlZmF1bHQuZ2V0Q29sdW1uKGhhbGZBeGVzLCAwLCBzY3JhdGNoWEF4aXMyKTsKICAgICAgICBjb25zdCB5QXhpcyA9IE1hdHJpeDNfZGVmYXVsdC5nZXRDb2x1bW4oaGFsZkF4ZXMsIDEsIHNjcmF0Y2hZQXhpczIpOwogICAgICAgIGNvbnN0IHpBeGlzID0gTWF0cml4M19kZWZhdWx0LmdldENvbHVtbihoYWxmQXhlcywgMiwgc2NyYXRjaFpBeGlzMik7CiAgICAgICAgY29uc3QgeE1hZyA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUoeEF4aXMpOwogICAgICAgIGNvbnN0IHlNYWcgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKHlBeGlzKTsKICAgICAgICBjb25zdCB6TWFnID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZSh6QXhpcyk7CiAgICAgICAgY29uc3QgbWluMyA9IE1hdGgubWluKHhNYWcsIHlNYWcsIHpNYWcpOwogICAgICAgIGlmICh4TWFnID09PSAwICYmICh5TWFnID09PSAwIHx8IHpNYWcgPT09IDApIHx8IHlNYWcgPT09IDAgJiYgek1hZyA9PT0gMCkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICBsZXQgcGxhbmVBeGlzMTsKICAgICAgICBsZXQgcGxhbmVBeGlzMjsKICAgICAgICBpZiAobWluMyA9PT0geU1hZyB8fCBtaW4zID09PSB6TWFnKSB7CiAgICAgICAgICBwbGFuZUF4aXMxID0geEF4aXM7CiAgICAgICAgfQogICAgICAgIGlmIChtaW4zID09PSB4TWFnKSB7CiAgICAgICAgICBwbGFuZUF4aXMxID0geUF4aXM7CiAgICAgICAgfSBlbHNlIGlmIChtaW4zID09PSB6TWFnKSB7CiAgICAgICAgICBwbGFuZUF4aXMyID0geUF4aXM7CiAgICAgICAgfQogICAgICAgIGlmIChtaW4zID09PSB4TWFnIHx8IG1pbjMgPT09IHlNYWcpIHsKICAgICAgICAgIHBsYW5lQXhpczIgPSB6QXhpczsKICAgICAgICB9CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShwbGFuZUF4aXMxLCBwbGFuZUF4aXMxUmVzdWx0KTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKHBsYW5lQXhpczIsIHBsYW5lQXhpczJSZXN1bHQpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShvcmllbnRlZEJvdW5kaW5nQm94LmNlbnRlciwgY2VudGVyUmVzdWx0KTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfTsKICAgICAgQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LmNyZWF0ZVByb2plY3RQb2ludHNUbzJERnVuY3Rpb24gPSBmdW5jdGlvbihjZW50ZXIsIGF4aXMxLCBheGlzMikgewogICAgICAgIHJldHVybiBmdW5jdGlvbihwb3NpdGlvbnMpIHsKICAgICAgICAgIGNvbnN0IHBvc2l0aW9uUmVzdWx0cyA9IG5ldyBBcnJheShwb3NpdGlvbnMubGVuZ3RoKTsKICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9zaXRpb25zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHBvc2l0aW9uUmVzdWx0c1tpXSA9IHByb2plY3RUbzJEKHBvc2l0aW9uc1tpXSwgY2VudGVyLCBheGlzMSwgYXhpczIpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHBvc2l0aW9uUmVzdWx0czsKICAgICAgICB9OwogICAgICB9OwogICAgICBDb3BsYW5hclBvbHlnb25HZW9tZXRyeUxpYnJhcnkuY3JlYXRlUHJvamVjdFBvaW50VG8yREZ1bmN0aW9uID0gZnVuY3Rpb24oY2VudGVyLCBheGlzMSwgYXhpczIpIHsKICAgICAgICByZXR1cm4gZnVuY3Rpb24ocG9zaXRpb24sIHJlc3VsdCkgewogICAgICAgICAgcmV0dXJuIHByb2plY3RUbzJEKHBvc2l0aW9uLCBjZW50ZXIsIGF4aXMxLCBheGlzMiwgcmVzdWx0KTsKICAgICAgICB9OwogICAgICB9OwogICAgICBDb3BsYW5hclBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdCA9IENvcGxhbmFyUG9seWdvbkdlb21ldHJ5TGlicmFyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0FyY1R5cGUuanMKICB2YXIgQXJjVHlwZSwgQXJjVHlwZV9kZWZhdWx0OwogIHZhciBpbml0X0FyY1R5cGUgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0FyY1R5cGUuanMiKCkgewogICAgICBBcmNUeXBlID0gewogICAgICAgIC8qKgogICAgICAgICAqIFN0cmFpZ2h0IGxpbmUgdGhhdCBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBzdXJmYWNlIG9mIHRoZSBlbGxpcHNvaWQuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIE5PTkU6IDAsCiAgICAgICAgLyoqCiAgICAgICAgICogRm9sbG93IGdlb2Rlc2ljIHBhdGguCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIEdFT0RFU0lDOiAxLAogICAgICAgIC8qKgogICAgICAgICAqIEZvbGxvdyByaHVtYiBvciBsb3hvZHJvbWUgcGF0aC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgUkhVTUI6IDIKICAgICAgfTsKICAgICAgQXJjVHlwZV9kZWZhdWx0ID0gT2JqZWN0LmZyZWV6ZShBcmNUeXBlKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0VsbGlwc29pZFJodW1iTGluZS5qcwogIGZ1bmN0aW9uIGNhbGN1bGF0ZU0oZWxsaXB0aWNpdHksIG1ham9yLCBsYXRpdHVkZSkgewogICAgaWYgKGVsbGlwdGljaXR5ID09PSAwKSB7CiAgICAgIHJldHVybiBtYWpvciAqIGxhdGl0dWRlOwogICAgfQogICAgY29uc3QgZTIgPSBlbGxpcHRpY2l0eSAqIGVsbGlwdGljaXR5OwogICAgY29uc3QgZTQgPSBlMiAqIGUyOwogICAgY29uc3QgZTYgPSBlNCAqIGUyOwogICAgY29uc3QgZTggPSBlNiAqIGUyOwogICAgY29uc3QgZTEwID0gZTggKiBlMjsKICAgIGNvbnN0IGUxMiA9IGUxMCAqIGUyOwogICAgY29uc3QgcGhpID0gbGF0aXR1ZGU7CiAgICBjb25zdCBzaW4yUGhpID0gTWF0aC5zaW4oMiAqIHBoaSk7CiAgICBjb25zdCBzaW40UGhpID0gTWF0aC5zaW4oNCAqIHBoaSk7CiAgICBjb25zdCBzaW42UGhpID0gTWF0aC5zaW4oNiAqIHBoaSk7CiAgICBjb25zdCBzaW44UGhpID0gTWF0aC5zaW4oOCAqIHBoaSk7CiAgICBjb25zdCBzaW4xMFBoaSA9IE1hdGguc2luKDEwICogcGhpKTsKICAgIGNvbnN0IHNpbjEyUGhpID0gTWF0aC5zaW4oMTIgKiBwaGkpOwogICAgcmV0dXJuIG1ham9yICogKCgxIC0gZTIgLyA0IC0gMyAqIGU0IC8gNjQgLSA1ICogZTYgLyAyNTYgLSAxNzUgKiBlOCAvIDE2Mzg0IC0gNDQxICogZTEwIC8gNjU1MzYgLSA0ODUxICogZTEyIC8gMTA0ODU3NikgKiBwaGkgLSAoMyAqIGUyIC8gOCArIDMgKiBlNCAvIDMyICsgNDUgKiBlNiAvIDEwMjQgKyAxMDUgKiBlOCAvIDQwOTYgKyAyMjA1ICogZTEwIC8gMTMxMDcyICsgNjIzNyAqIGUxMiAvIDUyNDI4OCkgKiBzaW4yUGhpICsgKDE1ICogZTQgLyAyNTYgKyA0NSAqIGU2IC8gMTAyNCArIDUyNSAqIGU4IC8gMTYzODQgKyAxNTc1ICogZTEwIC8gNjU1MzYgKyAxNTU5MjUgKiBlMTIgLyA4Mzg4NjA4KSAqIHNpbjRQaGkgLSAoMzUgKiBlNiAvIDMwNzIgKyAxNzUgKiBlOCAvIDEyMjg4ICsgMzY3NSAqIGUxMCAvIDI2MjE0NCArIDEzNDc1ICogZTEyIC8gMTA0ODU3NikgKiBzaW42UGhpICsgKDMxNSAqIGU4IC8gMTMxMDcyICsgMjIwNSAqIGUxMCAvIDUyNDI4OCArIDQzNjU5ICogZTEyIC8gODM4ODYwOCkgKiBzaW44UGhpIC0gKDY5MyAqIGUxMCAvIDEzMTA3MjAgKyA2MjM3ICogZTEyIC8gNTI0Mjg4MCkgKiBzaW4xMFBoaSArIDEwMDEgKiBlMTIgLyA4Mzg4NjA4ICogc2luMTJQaGkpOwogIH0KICBmdW5jdGlvbiBjYWxjdWxhdGVJbnZlcnNlTShNLCBlbGxpcHRpY2l0eSwgbWFqb3IpIHsKICAgIGNvbnN0IGQgPSBNIC8gbWFqb3I7CiAgICBpZiAoZWxsaXB0aWNpdHkgPT09IDApIHsKICAgICAgcmV0dXJuIGQ7CiAgICB9CiAgICBjb25zdCBkMiA9IGQgKiBkOwogICAgY29uc3QgZDMgPSBkMiAqIGQ7CiAgICBjb25zdCBkNCA9IGQzICogZDsKICAgIGNvbnN0IGUgPSBlbGxpcHRpY2l0eTsKICAgIGNvbnN0IGUyID0gZSAqIGU7CiAgICBjb25zdCBlNCA9IGUyICogZTI7CiAgICBjb25zdCBlNiA9IGU0ICogZTI7CiAgICBjb25zdCBlOCA9IGU2ICogZTI7CiAgICBjb25zdCBlMTAgPSBlOCAqIGUyOwogICAgY29uc3QgZTEyID0gZTEwICogZTI7CiAgICBjb25zdCBzaW4yRCA9IE1hdGguc2luKDIgKiBkKTsKICAgIGNvbnN0IGNvczJEID0gTWF0aC5jb3MoMiAqIGQpOwogICAgY29uc3Qgc2luNEQgPSBNYXRoLnNpbig0ICogZCk7CiAgICBjb25zdCBjb3M0RCA9IE1hdGguY29zKDQgKiBkKTsKICAgIGNvbnN0IHNpbjZEID0gTWF0aC5zaW4oNiAqIGQpOwogICAgY29uc3QgY29zNkQgPSBNYXRoLmNvcyg2ICogZCk7CiAgICBjb25zdCBzaW44RCA9IE1hdGguc2luKDggKiBkKTsKICAgIGNvbnN0IGNvczhEID0gTWF0aC5jb3MoOCAqIGQpOwogICAgY29uc3Qgc2luMTBEID0gTWF0aC5zaW4oMTAgKiBkKTsKICAgIGNvbnN0IGNvczEwRCA9IE1hdGguY29zKDEwICogZCk7CiAgICBjb25zdCBzaW4xMkQgPSBNYXRoLnNpbigxMiAqIGQpOwogICAgcmV0dXJuIGQgKyBkICogZTIgLyA0ICsgNyAqIGQgKiBlNCAvIDY0ICsgMTUgKiBkICogZTYgLyAyNTYgKyA1NzkgKiBkICogZTggLyAxNjM4NCArIDE1MTUgKiBkICogZTEwIC8gNjU1MzYgKyAxNjgzNyAqIGQgKiBlMTIgLyAxMDQ4NTc2ICsgKDMgKiBkICogZTQgLyAxNiArIDQ1ICogZCAqIGU2IC8gMjU2IC0gZCAqICgzMiAqIGQyIC0gNTYxKSAqIGU4IC8gNDA5NiAtIGQgKiAoMjMyICogZDIgLSAxNjc3KSAqIGUxMCAvIDE2Mzg0ICsgZCAqICgzOTk5ODUgLSA5MDU2MCAqIGQyICsgNTEyICogZDQpICogZTEyIC8gNTI0Mjg4MCkgKiBjb3MyRCArICgyMSAqIGQgKiBlNiAvIDI1NiArIDQ4MyAqIGQgKiBlOCAvIDQwOTYgLSBkICogKDIyNCAqIGQyIC0gMTk2OSkgKiBlMTAgLyAxNjM4NCAtIGQgKiAoMzMxNTIgKiBkMiAtIDExMjU5OSkgKiBlMTIgLyAxMDQ4NTc2KSAqIGNvczREICsgKDE1MSAqIGQgKiBlOCAvIDQwOTYgKyA0NjgxICogZCAqIGUxMCAvIDY1NTM2ICsgMTQ3OSAqIGQgKiBlMTIgLyAxNjM4NCAtIDQ1MyAqIGQzICogZTEyIC8gMzI3NjgpICogY29zNkQgKyAoMTA5NyAqIGQgKiBlMTAgLyA2NTUzNiArIDQyNzgzICogZCAqIGUxMiAvIDEwNDg1NzYpICogY29zOEQgKyA4MDExICogZCAqIGUxMiAvIDEwNDg1NzYgKiBjb3MxMEQgKyAoMyAqIGUyIC8gOCArIDMgKiBlNCAvIDE2ICsgMjEzICogZTYgLyAyMDQ4IC0gMyAqIGQyICogZTYgLyA2NCArIDI1NSAqIGU4IC8gNDA5NiAtIDMzICogZDIgKiBlOCAvIDUxMiArIDIwODYxICogZTEwIC8gNTI0Mjg4IC0gMzMgKiBkMiAqIGUxMCAvIDUxMiArIGQ0ICogZTEwIC8gMTAyNCArIDI4MjczICogZTEyIC8gMTA0ODU3NiAtIDQ3MSAqIGQyICogZTEyIC8gODE5MiArIDkgKiBkNCAqIGUxMiAvIDQwOTYpICogc2luMkQgKyAoMjEgKiBlNCAvIDI1NiArIDIxICogZTYgLyAyNTYgKyA1MzMgKiBlOCAvIDgxOTIgLSAyMSAqIGQyICogZTggLyA1MTIgKyAxOTcgKiBlMTAgLyA0MDk2IC0gMzE1ICogZDIgKiBlMTAgLyA0MDk2ICsgNTg0MDM5ICogZTEyIC8gMTY3NzcyMTYgLSAxMjUxNyAqIGQyICogZTEyIC8gMTMxMDcyICsgNyAqIGQ0ICogZTEyIC8gMjA0OCkgKiBzaW40RCArICgxNTEgKiBlNiAvIDYxNDQgKyAxNTEgKiBlOCAvIDQwOTYgKyA1MDE5ICogZTEwIC8gMTMxMDcyIC0gNDUzICogZDIgKiBlMTAgLyAxNjM4NCArIDI2OTY1ICogZTEyIC8gNzg2NDMyIC0gODYwNyAqIGQyICogZTEyIC8gMTMxMDcyKSAqIHNpbjZEICsgKDEwOTcgKiBlOCAvIDEzMTA3MiArIDEwOTcgKiBlMTAgLyA2NTUzNiArIDIyNTc5NyAqIGUxMiAvIDEwNDg1NzYwIC0gMTA5NyAqIGQyICogZTEyIC8gNjU1MzYpICogc2luOEQgKyAoODAxMSAqIGUxMCAvIDI2MjE0NDAgKyA4MDExICogZTEyIC8gMTA0ODU3NikgKiBzaW4xMEQgKyAyOTMzOTMgKiBlMTIgLyAyNTE2NTgyNDAgKiBzaW4xMkQ7CiAgfQogIGZ1bmN0aW9uIGNhbGN1bGF0ZVNpZ21hKGVsbGlwdGljaXR5LCBsYXRpdHVkZSkgewogICAgaWYgKGVsbGlwdGljaXR5ID09PSAwKSB7CiAgICAgIHJldHVybiBNYXRoLmxvZyhNYXRoLnRhbigwLjUgKiAoTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPICsgbGF0aXR1ZGUpKSk7CiAgICB9CiAgICBjb25zdCBlU2luTCA9IGVsbGlwdGljaXR5ICogTWF0aC5zaW4obGF0aXR1ZGUpOwogICAgcmV0dXJuIE1hdGgubG9nKE1hdGgudGFuKDAuNSAqIChNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08gKyBsYXRpdHVkZSkpKSAtIGVsbGlwdGljaXR5IC8gMiAqIE1hdGgubG9nKCgxICsgZVNpbkwpIC8gKDEgLSBlU2luTCkpOwogIH0KICBmdW5jdGlvbiBjYWxjdWxhdGVIZWFkaW5nKGVsbGlwc29pZFJodW1iTGluZSwgZmlyc3RMb25naXR1ZGUsIGZpcnN0TGF0aXR1ZGUsIHNlY29uZExvbmdpdHVkZSwgc2Vjb25kTGF0aXR1ZGUpIHsKICAgIGNvbnN0IHNpZ21hMSA9IGNhbGN1bGF0ZVNpZ21hKGVsbGlwc29pZFJodW1iTGluZS5fZWxsaXB0aWNpdHksIGZpcnN0TGF0aXR1ZGUpOwogICAgY29uc3Qgc2lnbWEyID0gY2FsY3VsYXRlU2lnbWEoCiAgICAgIGVsbGlwc29pZFJodW1iTGluZS5fZWxsaXB0aWNpdHksCiAgICAgIHNlY29uZExhdGl0dWRlCiAgICApOwogICAgcmV0dXJuIE1hdGguYXRhbjIoCiAgICAgIE1hdGhfZGVmYXVsdC5uZWdhdGl2ZVBpVG9QaShzZWNvbmRMb25naXR1ZGUgLSBmaXJzdExvbmdpdHVkZSksCiAgICAgIHNpZ21hMiAtIHNpZ21hMQogICAgKTsKICB9CiAgZnVuY3Rpb24gY2FsY3VsYXRlQXJjTGVuZ3RoKGVsbGlwc29pZFJodW1iTGluZSwgbWFqb3IsIG1pbm9yLCBmaXJzdExvbmdpdHVkZSwgZmlyc3RMYXRpdHVkZSwgc2Vjb25kTG9uZ2l0dWRlLCBzZWNvbmRMYXRpdHVkZSkgewogICAgY29uc3QgaGVhZGluZyA9IGVsbGlwc29pZFJodW1iTGluZS5faGVhZGluZzsKICAgIGNvbnN0IGRlbHRhTG9uZ2l0dWRlID0gc2Vjb25kTG9uZ2l0dWRlIC0gZmlyc3RMb25naXR1ZGU7CiAgICBsZXQgZGlzdGFuY2UgPSAwOwogICAgaWYgKE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICBNYXRoLmFicyhoZWFkaW5nKSwKICAgICAgTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPLAogICAgICBNYXRoX2RlZmF1bHQuRVBTSUxPTjgKICAgICkpIHsKICAgICAgaWYgKG1ham9yID09PSBtaW5vcikgewogICAgICAgIGRpc3RhbmNlID0gbWFqb3IgKiBNYXRoLmNvcyhmaXJzdExhdGl0dWRlKSAqIE1hdGhfZGVmYXVsdC5uZWdhdGl2ZVBpVG9QaShkZWx0YUxvbmdpdHVkZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3Qgc2luUGhpID0gTWF0aC5zaW4oZmlyc3RMYXRpdHVkZSk7CiAgICAgICAgZGlzdGFuY2UgPSBtYWpvciAqIE1hdGguY29zKGZpcnN0TGF0aXR1ZGUpICogTWF0aF9kZWZhdWx0Lm5lZ2F0aXZlUGlUb1BpKGRlbHRhTG9uZ2l0dWRlKSAvIE1hdGguc3FydCgxIC0gZWxsaXBzb2lkUmh1bWJMaW5lLl9lbGxpcHRpY2l0eVNxdWFyZWQgKiBzaW5QaGkgKiBzaW5QaGkpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBNMSA9IGNhbGN1bGF0ZU0oCiAgICAgICAgZWxsaXBzb2lkUmh1bWJMaW5lLl9lbGxpcHRpY2l0eSwKICAgICAgICBtYWpvciwKICAgICAgICBmaXJzdExhdGl0dWRlCiAgICAgICk7CiAgICAgIGNvbnN0IE0yID0gY2FsY3VsYXRlTSgKICAgICAgICBlbGxpcHNvaWRSaHVtYkxpbmUuX2VsbGlwdGljaXR5LAogICAgICAgIG1ham9yLAogICAgICAgIHNlY29uZExhdGl0dWRlCiAgICAgICk7CiAgICAgIGRpc3RhbmNlID0gKE0yIC0gTTEpIC8gTWF0aC5jb3MoaGVhZGluZyk7CiAgICB9CiAgICByZXR1cm4gTWF0aC5hYnMoZGlzdGFuY2UpOwogIH0KICBmdW5jdGlvbiBjb21wdXRlUHJvcGVydGllcyhlbGxpcHNvaWRSaHVtYkxpbmUsIHN0YXJ0LCBlbmQsIGVsbGlwc29pZCkgewogICAgY29uc3QgZmlyc3RDYXJ0ZXNpYW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oc3RhcnQsIHNjcmF0Y2hDYXJ0MiksCiAgICAgIHNjcmF0Y2hDYXJ0MQogICAgKTsKICAgIGNvbnN0IGxhc3RDYXJ0ZXNpYW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oZW5kLCBzY3JhdGNoQ2FydDIpLAogICAgICBzY3JhdGNoQ2FydDIKICAgICk7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygKICAgICAgInZhbHVlIiwKICAgICAgTWF0aC5hYnMoCiAgICAgICAgTWF0aC5hYnMoQ2FydGVzaWFuM19kZWZhdWx0LmFuZ2xlQmV0d2VlbihmaXJzdENhcnRlc2lhbiwgbGFzdENhcnRlc2lhbikpIC0gTWF0aC5QSQogICAgICApLAogICAgICAwLjAxMjUKICAgICk7CiAgICBjb25zdCBtYWpvciA9IGVsbGlwc29pZC5tYXhpbXVtUmFkaXVzOwogICAgY29uc3QgbWlub3IgPSBlbGxpcHNvaWQubWluaW11bVJhZGl1czsKICAgIGNvbnN0IG1ham9yU3F1YXJlZCA9IG1ham9yICogbWFqb3I7CiAgICBjb25zdCBtaW5vclNxdWFyZWQgPSBtaW5vciAqIG1pbm9yOwogICAgZWxsaXBzb2lkUmh1bWJMaW5lLl9lbGxpcHRpY2l0eVNxdWFyZWQgPSAobWFqb3JTcXVhcmVkIC0gbWlub3JTcXVhcmVkKSAvIG1ham9yU3F1YXJlZDsKICAgIGVsbGlwc29pZFJodW1iTGluZS5fZWxsaXB0aWNpdHkgPSBNYXRoLnNxcnQoCiAgICAgIGVsbGlwc29pZFJodW1iTGluZS5fZWxsaXB0aWNpdHlTcXVhcmVkCiAgICApOwogICAgZWxsaXBzb2lkUmh1bWJMaW5lLl9zdGFydCA9IENhcnRvZ3JhcGhpY19kZWZhdWx0LmNsb25lKAogICAgICBzdGFydCwKICAgICAgZWxsaXBzb2lkUmh1bWJMaW5lLl9zdGFydAogICAgKTsKICAgIGVsbGlwc29pZFJodW1iTGluZS5fc3RhcnQuaGVpZ2h0ID0gMDsKICAgIGVsbGlwc29pZFJodW1iTGluZS5fZW5kID0gQ2FydG9ncmFwaGljX2RlZmF1bHQuY2xvbmUoZW5kLCBlbGxpcHNvaWRSaHVtYkxpbmUuX2VuZCk7CiAgICBlbGxpcHNvaWRSaHVtYkxpbmUuX2VuZC5oZWlnaHQgPSAwOwogICAgZWxsaXBzb2lkUmh1bWJMaW5lLl9oZWFkaW5nID0gY2FsY3VsYXRlSGVhZGluZygKICAgICAgZWxsaXBzb2lkUmh1bWJMaW5lLAogICAgICBzdGFydC5sb25naXR1ZGUsCiAgICAgIHN0YXJ0LmxhdGl0dWRlLAogICAgICBlbmQubG9uZ2l0dWRlLAogICAgICBlbmQubGF0aXR1ZGUKICAgICk7CiAgICBlbGxpcHNvaWRSaHVtYkxpbmUuX2Rpc3RhbmNlID0gY2FsY3VsYXRlQXJjTGVuZ3RoKAogICAgICBlbGxpcHNvaWRSaHVtYkxpbmUsCiAgICAgIGVsbGlwc29pZC5tYXhpbXVtUmFkaXVzLAogICAgICBlbGxpcHNvaWQubWluaW11bVJhZGl1cywKICAgICAgc3RhcnQubG9uZ2l0dWRlLAogICAgICBzdGFydC5sYXRpdHVkZSwKICAgICAgZW5kLmxvbmdpdHVkZSwKICAgICAgZW5kLmxhdGl0dWRlCiAgICApOwogIH0KICBmdW5jdGlvbiBpbnRlcnBvbGF0ZVVzaW5nU3VyZmFjZURpc3RhbmNlKHN0YXJ0LCBoZWFkaW5nLCBkaXN0YW5jZSwgbWFqb3IsIGVsbGlwdGljaXR5LCByZXN1bHQpIHsKICAgIGlmIChkaXN0YW5jZSA9PT0gMCkgewogICAgICByZXR1cm4gQ2FydG9ncmFwaGljX2RlZmF1bHQuY2xvbmUoc3RhcnQsIHJlc3VsdCk7CiAgICB9CiAgICBjb25zdCBlbGxpcHRpY2l0eVNxdWFyZWQgPSBlbGxpcHRpY2l0eSAqIGVsbGlwdGljaXR5OwogICAgbGV0IGxvbmdpdHVkZTsKICAgIGxldCBsYXRpdHVkZTsKICAgIGxldCBkZWx0YUxvbmdpdHVkZTsKICAgIGlmIChNYXRoLmFicyhNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08gLSBNYXRoLmFicyhoZWFkaW5nKSkgPiBNYXRoX2RlZmF1bHQuRVBTSUxPTjgpIHsKICAgICAgY29uc3QgTTEgPSBjYWxjdWxhdGVNKGVsbGlwdGljaXR5LCBtYWpvciwgc3RhcnQubGF0aXR1ZGUpOwogICAgICBjb25zdCBkZWx0YU0gPSBkaXN0YW5jZSAqIE1hdGguY29zKGhlYWRpbmcpOwogICAgICBjb25zdCBNMiA9IE0xICsgZGVsdGFNOwogICAgICBsYXRpdHVkZSA9IGNhbGN1bGF0ZUludmVyc2VNKE0yLCBlbGxpcHRpY2l0eSwgbWFqb3IpOwogICAgICBpZiAoTWF0aC5hYnMoaGVhZGluZykgPCBNYXRoX2RlZmF1bHQuRVBTSUxPTjEwKSB7CiAgICAgICAgbG9uZ2l0dWRlID0gTWF0aF9kZWZhdWx0Lm5lZ2F0aXZlUGlUb1BpKHN0YXJ0LmxvbmdpdHVkZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3Qgc2lnbWExID0gY2FsY3VsYXRlU2lnbWEoZWxsaXB0aWNpdHksIHN0YXJ0LmxhdGl0dWRlKTsKICAgICAgICBjb25zdCBzaWdtYTIgPSBjYWxjdWxhdGVTaWdtYShlbGxpcHRpY2l0eSwgbGF0aXR1ZGUpOwogICAgICAgIGRlbHRhTG9uZ2l0dWRlID0gTWF0aC50YW4oaGVhZGluZykgKiAoc2lnbWEyIC0gc2lnbWExKTsKICAgICAgICBsb25naXR1ZGUgPSBNYXRoX2RlZmF1bHQubmVnYXRpdmVQaVRvUGkoc3RhcnQubG9uZ2l0dWRlICsgZGVsdGFMb25naXR1ZGUpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBsYXRpdHVkZSA9IHN0YXJ0LmxhdGl0dWRlOwogICAgICBsZXQgbG9jYWxSYWQ7CiAgICAgIGlmIChlbGxpcHRpY2l0eSA9PT0gMCkgewogICAgICAgIGxvY2FsUmFkID0gbWFqb3IgKiBNYXRoLmNvcyhzdGFydC5sYXRpdHVkZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3Qgc2luUGhpID0gTWF0aC5zaW4oc3RhcnQubGF0aXR1ZGUpOwogICAgICAgIGxvY2FsUmFkID0gbWFqb3IgKiBNYXRoLmNvcyhzdGFydC5sYXRpdHVkZSkgLyBNYXRoLnNxcnQoMSAtIGVsbGlwdGljaXR5U3F1YXJlZCAqIHNpblBoaSAqIHNpblBoaSk7CiAgICAgIH0KICAgICAgZGVsdGFMb25naXR1ZGUgPSBkaXN0YW5jZSAvIGxvY2FsUmFkOwogICAgICBpZiAoaGVhZGluZyA+IDApIHsKICAgICAgICBsb25naXR1ZGUgPSBNYXRoX2RlZmF1bHQubmVnYXRpdmVQaVRvUGkoc3RhcnQubG9uZ2l0dWRlICsgZGVsdGFMb25naXR1ZGUpOwogICAgICB9IGVsc2UgewogICAgICAgIGxvbmdpdHVkZSA9IE1hdGhfZGVmYXVsdC5uZWdhdGl2ZVBpVG9QaShzdGFydC5sb25naXR1ZGUgLSBkZWx0YUxvbmdpdHVkZSk7CiAgICAgIH0KICAgIH0KICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICByZXN1bHQubG9uZ2l0dWRlID0gbG9uZ2l0dWRlOwogICAgICByZXN1bHQubGF0aXR1ZGUgPSBsYXRpdHVkZTsKICAgICAgcmVzdWx0LmhlaWdodCA9IDA7CiAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9CiAgICByZXR1cm4gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KGxvbmdpdHVkZSwgbGF0aXR1ZGUsIDApOwogIH0KICBmdW5jdGlvbiBFbGxpcHNvaWRSaHVtYkxpbmUoc3RhcnQsIGVuZCwgZWxsaXBzb2lkKSB7CiAgICBjb25zdCBlID0gZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICB0aGlzLl9lbGxpcHNvaWQgPSBlOwogICAgdGhpcy5fc3RhcnQgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgIHRoaXMuX2VuZCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgdGhpcy5faGVhZGluZyA9IHZvaWQgMDsKICAgIHRoaXMuX2Rpc3RhbmNlID0gdm9pZCAwOwogICAgdGhpcy5fZWxsaXB0aWNpdHkgPSB2b2lkIDA7CiAgICB0aGlzLl9lbGxpcHRpY2l0eVNxdWFyZWQgPSB2b2lkIDA7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHN0YXJ0KSAmJiBkZWZpbmVkX2RlZmF1bHQoZW5kKSkgewogICAgICBjb21wdXRlUHJvcGVydGllcyh0aGlzLCBzdGFydCwgZW5kLCBlKTsKICAgIH0KICB9CiAgdmFyIHNjcmF0Y2hDYXJ0MSwgc2NyYXRjaENhcnQyLCBFbGxpcHNvaWRSaHVtYkxpbmVfZGVmYXVsdDsKICB2YXIgaW5pdF9FbGxpcHNvaWRSaHVtYkxpbmUgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0VsbGlwc29pZFJodW1iTGluZS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBzY3JhdGNoQ2FydDEgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0MiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoRWxsaXBzb2lkUmh1bWJMaW5lLnByb3RvdHlwZSwgewogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIGVsbGlwc29pZC4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkUmh1bWJMaW5lLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtFbGxpcHNvaWR9CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgZWxsaXBzb2lkOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fZWxsaXBzb2lkOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgc3VyZmFjZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBzdGFydCBhbmQgZW5kIHBvaW50CiAgICAgICAgICogQG1lbWJlcm9mIEVsbGlwc29pZFJodW1iTGluZS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIHN1cmZhY2VEaXN0YW5jZTogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJkaXN0YW5jZSIsIHRoaXMuX2Rpc3RhbmNlKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2Rpc3RhbmNlOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgaW5pdGlhbCBwbGFuZXRvZGV0aWMgcG9pbnQgb24gdGhlIHBhdGguCiAgICAgICAgICogQG1lbWJlcm9mIEVsbGlwc29pZFJodW1iTGluZS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7Q2FydG9ncmFwaGljfQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIHN0YXJ0OiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fc3RhcnQ7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBmaW5hbCBwbGFuZXRvZGV0aWMgcG9pbnQgb24gdGhlIHBhdGguCiAgICAgICAgICogQG1lbWJlcm9mIEVsbGlwc29pZFJodW1iTGluZS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7Q2FydG9ncmFwaGljfQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIGVuZDogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2VuZDsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIGhlYWRpbmcgZnJvbSB0aGUgc3RhcnQgcG9pbnQgdG8gdGhlIGVuZCBwb2ludC4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkUmh1bWJMaW5lLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgaGVhZGluZzogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJkaXN0YW5jZSIsIHRoaXMuX2Rpc3RhbmNlKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2hlYWRpbmc7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgRWxsaXBzb2lkUmh1bWJMaW5lLmZyb21TdGFydEhlYWRpbmdEaXN0YW5jZSA9IGZ1bmN0aW9uKHN0YXJ0LCBoZWFkaW5nLCBkaXN0YW5jZSwgZWxsaXBzb2lkLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInN0YXJ0Iiwgc3RhcnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiaGVhZGluZyIsIGhlYWRpbmcpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiZGlzdGFuY2UiLCBkaXN0YW5jZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuKCJkaXN0YW5jZSIsIGRpc3RhbmNlLCAwKTsKICAgICAgICBjb25zdCBlID0gZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICAgICAgY29uc3QgbWFqb3IgPSBlLm1heGltdW1SYWRpdXM7CiAgICAgICAgY29uc3QgbWlub3IgPSBlLm1pbmltdW1SYWRpdXM7CiAgICAgICAgY29uc3QgbWFqb3JTcXVhcmVkID0gbWFqb3IgKiBtYWpvcjsKICAgICAgICBjb25zdCBtaW5vclNxdWFyZWQgPSBtaW5vciAqIG1pbm9yOwogICAgICAgIGNvbnN0IGVsbGlwdGljaXR5ID0gTWF0aC5zcXJ0KChtYWpvclNxdWFyZWQgLSBtaW5vclNxdWFyZWQpIC8gbWFqb3JTcXVhcmVkKTsKICAgICAgICBoZWFkaW5nID0gTWF0aF9kZWZhdWx0Lm5lZ2F0aXZlUGlUb1BpKGhlYWRpbmcpOwogICAgICAgIGNvbnN0IGVuZCA9IGludGVycG9sYXRlVXNpbmdTdXJmYWNlRGlzdGFuY2UoCiAgICAgICAgICBzdGFydCwKICAgICAgICAgIGhlYWRpbmcsCiAgICAgICAgICBkaXN0YW5jZSwKICAgICAgICAgIGUubWF4aW11bVJhZGl1cywKICAgICAgICAgIGVsbGlwdGljaXR5CiAgICAgICAgKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpIHx8IGRlZmluZWRfZGVmYXVsdChlbGxpcHNvaWQpICYmICFlbGxpcHNvaWQuZXF1YWxzKHJlc3VsdC5lbGxpcHNvaWQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IEVsbGlwc29pZFJodW1iTGluZShzdGFydCwgZW5kLCBlKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnNldEVuZFBvaW50cyhzdGFydCwgZW5kKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBFbGxpcHNvaWRSaHVtYkxpbmUucHJvdG90eXBlLnNldEVuZFBvaW50cyA9IGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInN0YXJ0Iiwgc3RhcnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiZW5kIiwgZW5kKTsKICAgICAgICBjb21wdXRlUHJvcGVydGllcyh0aGlzLCBzdGFydCwgZW5kLCB0aGlzLl9lbGxpcHNvaWQpOwogICAgICB9OwogICAgICBFbGxpcHNvaWRSaHVtYkxpbmUucHJvdG90eXBlLmludGVycG9sYXRlVXNpbmdGcmFjdGlvbiA9IGZ1bmN0aW9uKGZyYWN0aW9uLCByZXN1bHQpIHsKICAgICAgICByZXR1cm4gdGhpcy5pbnRlcnBvbGF0ZVVzaW5nU3VyZmFjZURpc3RhbmNlKAogICAgICAgICAgZnJhY3Rpb24gKiB0aGlzLl9kaXN0YW5jZSwKICAgICAgICAgIHJlc3VsdAogICAgICAgICk7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZFJodW1iTGluZS5wcm90b3R5cGUuaW50ZXJwb2xhdGVVc2luZ1N1cmZhY2VEaXN0YW5jZSA9IGZ1bmN0aW9uKGRpc3RhbmNlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoImRpc3RhbmNlIiwgZGlzdGFuY2UpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHRoaXMuX2Rpc3RhbmNlKSB8fCB0aGlzLl9kaXN0YW5jZSA9PT0gMCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJFbGxpcHNvaWRSaHVtYkxpbmUgbXVzdCBoYXZlIGRpc3RpbmN0IHN0YXJ0IGFuZCBlbmQgc2V0LiIKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBpbnRlcnBvbGF0ZVVzaW5nU3VyZmFjZURpc3RhbmNlKAogICAgICAgICAgdGhpcy5fc3RhcnQsCiAgICAgICAgICB0aGlzLl9oZWFkaW5nLAogICAgICAgICAgZGlzdGFuY2UsCiAgICAgICAgICB0aGlzLl9lbGxpcHNvaWQubWF4aW11bVJhZGl1cywKICAgICAgICAgIHRoaXMuX2VsbGlwdGljaXR5LAogICAgICAgICAgcmVzdWx0CiAgICAgICAgKTsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkUmh1bWJMaW5lLnByb3RvdHlwZS5maW5kSW50ZXJzZWN0aW9uV2l0aExvbmdpdHVkZSA9IGZ1bmN0aW9uKGludGVyc2VjdGlvbkxvbmdpdHVkZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJpbnRlcnNlY3Rpb25Mb25naXR1ZGUiLCBpbnRlcnNlY3Rpb25Mb25naXR1ZGUpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHRoaXMuX2Rpc3RhbmNlKSB8fCB0aGlzLl9kaXN0YW5jZSA9PT0gMCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJFbGxpcHNvaWRSaHVtYkxpbmUgbXVzdCBoYXZlIGRpc3RpbmN0IHN0YXJ0IGFuZCBlbmQgc2V0LiIKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGVsbGlwdGljaXR5ID0gdGhpcy5fZWxsaXB0aWNpdHk7CiAgICAgICAgY29uc3QgaGVhZGluZyA9IHRoaXMuX2hlYWRpbmc7CiAgICAgICAgY29uc3QgYWJzSGVhZGluZyA9IE1hdGguYWJzKGhlYWRpbmcpOwogICAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5fc3RhcnQ7CiAgICAgICAgaW50ZXJzZWN0aW9uTG9uZ2l0dWRlID0gTWF0aF9kZWZhdWx0Lm5lZ2F0aXZlUGlUb1BpKGludGVyc2VjdGlvbkxvbmdpdHVkZSk7CiAgICAgICAgaWYgKE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgTWF0aC5hYnMoaW50ZXJzZWN0aW9uTG9uZ2l0dWRlKSwKICAgICAgICAgIE1hdGguUEksCiAgICAgICAgICBNYXRoX2RlZmF1bHQuRVBTSUxPTjE0CiAgICAgICAgKSkgewogICAgICAgICAgaW50ZXJzZWN0aW9uTG9uZ2l0dWRlID0gTWF0aF9kZWZhdWx0LnNpZ24oc3RhcnQubG9uZ2l0dWRlKSAqIE1hdGguUEk7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICBpZiAoTWF0aC5hYnMoTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPIC0gYWJzSGVhZGluZykgPD0gTWF0aF9kZWZhdWx0LkVQU0lMT044KSB7CiAgICAgICAgICByZXN1bHQubG9uZ2l0dWRlID0gaW50ZXJzZWN0aW9uTG9uZ2l0dWRlOwogICAgICAgICAgcmVzdWx0LmxhdGl0dWRlID0gc3RhcnQubGF0aXR1ZGU7CiAgICAgICAgICByZXN1bHQuaGVpZ2h0ID0gMDsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfSBlbHNlIGlmIChNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIE1hdGguYWJzKE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyAtIGFic0hlYWRpbmcpLAogICAgICAgICAgTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPLAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT044CiAgICAgICAgKSkgewogICAgICAgICAgaWYgKE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgICBpbnRlcnNlY3Rpb25Mb25naXR1ZGUsCiAgICAgICAgICAgIHN0YXJ0LmxvbmdpdHVkZSwKICAgICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xMgogICAgICAgICAgKSkgewogICAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0LmxvbmdpdHVkZSA9IGludGVyc2VjdGlvbkxvbmdpdHVkZTsKICAgICAgICAgIHJlc3VsdC5sYXRpdHVkZSA9IE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyAqIE1hdGhfZGVmYXVsdC5zaWduKE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyAtIGhlYWRpbmcpOwogICAgICAgICAgcmVzdWx0LmhlaWdodCA9IDA7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICBjb25zdCBwaGkxID0gc3RhcnQubGF0aXR1ZGU7CiAgICAgICAgY29uc3QgZVNpblBoaTEgPSBlbGxpcHRpY2l0eSAqIE1hdGguc2luKHBoaTEpOwogICAgICAgIGNvbnN0IGxlZnRDb21wb25lbnQgPSBNYXRoLnRhbigwLjUgKiAoTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPICsgcGhpMSkpICogTWF0aC5leHAoKGludGVyc2VjdGlvbkxvbmdpdHVkZSAtIHN0YXJ0LmxvbmdpdHVkZSkgLyBNYXRoLnRhbihoZWFkaW5nKSk7CiAgICAgICAgY29uc3QgZGVub21pbmF0b3IgPSAoMSArIGVTaW5QaGkxKSAvICgxIC0gZVNpblBoaTEpOwogICAgICAgIGxldCBuZXdQaGkgPSBzdGFydC5sYXRpdHVkZTsKICAgICAgICBsZXQgcGhpOwogICAgICAgIGRvIHsKICAgICAgICAgIHBoaSA9IG5ld1BoaTsKICAgICAgICAgIGNvbnN0IGVTaW5QaGkgPSBlbGxpcHRpY2l0eSAqIE1hdGguc2luKHBoaSk7CiAgICAgICAgICBjb25zdCBudW1lcmF0b3IgPSAoMSArIGVTaW5QaGkpIC8gKDEgLSBlU2luUGhpKTsKICAgICAgICAgIG5ld1BoaSA9IDIgKiBNYXRoLmF0YW4oCiAgICAgICAgICAgIGxlZnRDb21wb25lbnQgKiBNYXRoLnBvdyhudW1lcmF0b3IgLyBkZW5vbWluYXRvciwgZWxsaXB0aWNpdHkgLyAyKQogICAgICAgICAgKSAtIE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTzsKICAgICAgICB9IHdoaWxlICghTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24obmV3UGhpLCBwaGksIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTIpKTsKICAgICAgICByZXN1bHQubG9uZ2l0dWRlID0gaW50ZXJzZWN0aW9uTG9uZ2l0dWRlOwogICAgICAgIHJlc3VsdC5sYXRpdHVkZSA9IG5ld1BoaTsKICAgICAgICByZXN1bHQuaGVpZ2h0ID0gMDsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBFbGxpcHNvaWRSaHVtYkxpbmUucHJvdG90eXBlLmZpbmRJbnRlcnNlY3Rpb25XaXRoTGF0aXR1ZGUgPSBmdW5jdGlvbihpbnRlcnNlY3Rpb25MYXRpdHVkZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJpbnRlcnNlY3Rpb25MYXRpdHVkZSIsIGludGVyc2VjdGlvbkxhdGl0dWRlKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh0aGlzLl9kaXN0YW5jZSkgfHwgdGhpcy5fZGlzdGFuY2UgPT09IDApIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICAiRWxsaXBzb2lkUmh1bWJMaW5lIG11c3QgaGF2ZSBkaXN0aW5jdCBzdGFydCBhbmQgZW5kIHNldC4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBlbGxpcHRpY2l0eSA9IHRoaXMuX2VsbGlwdGljaXR5OwogICAgICAgIGNvbnN0IGhlYWRpbmcgPSB0aGlzLl9oZWFkaW5nOwogICAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5fc3RhcnQ7CiAgICAgICAgaWYgKE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgTWF0aC5hYnMoaGVhZGluZyksCiAgICAgICAgICBNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08sCiAgICAgICAgICBNYXRoX2RlZmF1bHQuRVBTSUxPTjgKICAgICAgICApKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IHNpZ21hMSA9IGNhbGN1bGF0ZVNpZ21hKGVsbGlwdGljaXR5LCBzdGFydC5sYXRpdHVkZSk7CiAgICAgICAgY29uc3Qgc2lnbWEyID0gY2FsY3VsYXRlU2lnbWEoZWxsaXB0aWNpdHksIGludGVyc2VjdGlvbkxhdGl0dWRlKTsKICAgICAgICBjb25zdCBkZWx0YUxvbmdpdHVkZSA9IE1hdGgudGFuKGhlYWRpbmcpICogKHNpZ21hMiAtIHNpZ21hMSk7CiAgICAgICAgY29uc3QgbG9uZ2l0dWRlID0gTWF0aF9kZWZhdWx0Lm5lZ2F0aXZlUGlUb1BpKHN0YXJ0LmxvbmdpdHVkZSArIGRlbHRhTG9uZ2l0dWRlKTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdC5sb25naXR1ZGUgPSBsb25naXR1ZGU7CiAgICAgICAgICByZXN1bHQubGF0aXR1ZGUgPSBpbnRlcnNlY3Rpb25MYXRpdHVkZTsKICAgICAgICAgIHJlc3VsdC5oZWlnaHQgPSAwOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdChsb25naXR1ZGUsIGludGVyc2VjdGlvbkxhdGl0dWRlLCAwKTsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkUmh1bWJMaW5lX2RlZmF1bHQgPSBFbGxpcHNvaWRSaHVtYkxpbmU7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Qb2x5Z29uSGllcmFyY2h5LmpzCiAgZnVuY3Rpb24gUG9seWdvbkhpZXJhcmNoeShwb3NpdGlvbnMsIGhvbGVzKSB7CiAgICB0aGlzLnBvc2l0aW9ucyA9IGRlZmluZWRfZGVmYXVsdChwb3NpdGlvbnMpID8gcG9zaXRpb25zIDogW107CiAgICB0aGlzLmhvbGVzID0gZGVmaW5lZF9kZWZhdWx0KGhvbGVzKSA/IGhvbGVzIDogW107CiAgfQogIHZhciBQb2x5Z29uSGllcmFyY2h5X2RlZmF1bHQ7CiAgdmFyIGluaXRfUG9seWdvbkhpZXJhcmNoeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUG9seWdvbkhpZXJhcmNoeS5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBQb2x5Z29uSGllcmFyY2h5X2RlZmF1bHQgPSBQb2x5Z29uSGllcmFyY2h5OwogICAgfQogIH0pOwoKICAvLyBub2RlX21vZHVsZXMvZWFyY3V0L3NyYy9lYXJjdXQuanMKICBmdW5jdGlvbiBlYXJjdXQoZGF0YSwgaG9sZUluZGljZXMsIGRpbSA9IDIpIHsKICAgIGNvbnN0IGhhc0hvbGVzID0gaG9sZUluZGljZXMgJiYgaG9sZUluZGljZXMubGVuZ3RoOwogICAgY29uc3Qgb3V0ZXJMZW4gPSBoYXNIb2xlcyA/IGhvbGVJbmRpY2VzWzBdICogZGltIDogZGF0YS5sZW5ndGg7CiAgICBsZXQgb3V0ZXJOb2RlID0gbGlua2VkTGlzdChkYXRhLCAwLCBvdXRlckxlbiwgZGltLCB0cnVlKTsKICAgIGNvbnN0IHRyaWFuZ2xlcyA9IFtdOwogICAgaWYgKCFvdXRlck5vZGUgfHwgb3V0ZXJOb2RlLm5leHQgPT09IG91dGVyTm9kZS5wcmV2KSByZXR1cm4gdHJpYW5nbGVzOwogICAgbGV0IG1pblgsIG1pblksIGludlNpemU7CiAgICBpZiAoaGFzSG9sZXMpIG91dGVyTm9kZSA9IGVsaW1pbmF0ZUhvbGVzKGRhdGEsIGhvbGVJbmRpY2VzLCBvdXRlck5vZGUsIGRpbSk7CiAgICBpZiAoZGF0YS5sZW5ndGggPiA4MCAqIGRpbSkgewogICAgICBtaW5YID0gZGF0YVswXTsKICAgICAgbWluWSA9IGRhdGFbMV07CiAgICAgIGxldCBtYXhYID0gbWluWDsKICAgICAgbGV0IG1heFkgPSBtaW5ZOwogICAgICBmb3IgKGxldCBpID0gZGltOyBpIDwgb3V0ZXJMZW47IGkgKz0gZGltKSB7CiAgICAgICAgY29uc3QgeCA9IGRhdGFbaV07CiAgICAgICAgY29uc3QgeSA9IGRhdGFbaSArIDFdOwogICAgICAgIGlmICh4IDwgbWluWCkgbWluWCA9IHg7CiAgICAgICAgaWYgKHkgPCBtaW5ZKSBtaW5ZID0geTsKICAgICAgICBpZiAoeCA+IG1heFgpIG1heFggPSB4OwogICAgICAgIGlmICh5ID4gbWF4WSkgbWF4WSA9IHk7CiAgICAgIH0KICAgICAgaW52U2l6ZSA9IE1hdGgubWF4KG1heFggLSBtaW5YLCBtYXhZIC0gbWluWSk7CiAgICAgIGludlNpemUgPSBpbnZTaXplICE9PSAwID8gMzI3NjcgLyBpbnZTaXplIDogMDsKICAgIH0KICAgIGVhcmN1dExpbmtlZChvdXRlck5vZGUsIHRyaWFuZ2xlcywgZGltLCBtaW5YLCBtaW5ZLCBpbnZTaXplLCAwKTsKICAgIHJldHVybiB0cmlhbmdsZXM7CiAgfQogIGZ1bmN0aW9uIGxpbmtlZExpc3QoZGF0YSwgc3RhcnQsIGVuZCwgZGltLCBjbG9ja3dpc2UpIHsKICAgIGxldCBsYXN0OwogICAgaWYgKGNsb2Nrd2lzZSA9PT0gc2lnbmVkQXJlYShkYXRhLCBzdGFydCwgZW5kLCBkaW0pID4gMCkgewogICAgICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkgKz0gZGltKSBsYXN0ID0gaW5zZXJ0Tm9kZShpIC8gZGltIHwgMCwgZGF0YVtpXSwgZGF0YVtpICsgMV0sIGxhc3QpOwogICAgfSBlbHNlIHsKICAgICAgZm9yIChsZXQgaSA9IGVuZCAtIGRpbTsgaSA+PSBzdGFydDsgaSAtPSBkaW0pIGxhc3QgPSBpbnNlcnROb2RlKGkgLyBkaW0gfCAwLCBkYXRhW2ldLCBkYXRhW2kgKyAxXSwgbGFzdCk7CiAgICB9CiAgICBpZiAobGFzdCAmJiBlcXVhbHMobGFzdCwgbGFzdC5uZXh0KSkgewogICAgICByZW1vdmVOb2RlKGxhc3QpOwogICAgICBsYXN0ID0gbGFzdC5uZXh0OwogICAgfQogICAgcmV0dXJuIGxhc3Q7CiAgfQogIGZ1bmN0aW9uIGZpbHRlclBvaW50cyhzdGFydCwgZW5kKSB7CiAgICBpZiAoIXN0YXJ0KSByZXR1cm4gc3RhcnQ7CiAgICBpZiAoIWVuZCkgZW5kID0gc3RhcnQ7CiAgICBsZXQgcCA9IHN0YXJ0LCBhZ2FpbjsKICAgIGRvIHsKICAgICAgYWdhaW4gPSBmYWxzZTsKICAgICAgaWYgKCFwLnN0ZWluZXIgJiYgKGVxdWFscyhwLCBwLm5leHQpIHx8IGFyZWEocC5wcmV2LCBwLCBwLm5leHQpID09PSAwKSkgewogICAgICAgIHJlbW92ZU5vZGUocCk7CiAgICAgICAgcCA9IGVuZCA9IHAucHJldjsKICAgICAgICBpZiAocCA9PT0gcC5uZXh0KSBicmVhazsKICAgICAgICBhZ2FpbiA9IHRydWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcCA9IHAubmV4dDsKICAgICAgfQogICAgfSB3aGlsZSAoYWdhaW4gfHwgcCAhPT0gZW5kKTsKICAgIHJldHVybiBlbmQ7CiAgfQogIGZ1bmN0aW9uIGVhcmN1dExpbmtlZChlYXIsIHRyaWFuZ2xlcywgZGltLCBtaW5YLCBtaW5ZLCBpbnZTaXplLCBwYXNzKSB7CiAgICBpZiAoIWVhcikgcmV0dXJuOwogICAgaWYgKCFwYXNzICYmIGludlNpemUpIGluZGV4Q3VydmUoZWFyLCBtaW5YLCBtaW5ZLCBpbnZTaXplKTsKICAgIGxldCBzdG9wID0gZWFyOwogICAgd2hpbGUgKGVhci5wcmV2ICE9PSBlYXIubmV4dCkgewogICAgICBjb25zdCBwcmV2ID0gZWFyLnByZXY7CiAgICAgIGNvbnN0IG5leHQgPSBlYXIubmV4dDsKICAgICAgaWYgKGludlNpemUgPyBpc0Vhckhhc2hlZChlYXIsIG1pblgsIG1pblksIGludlNpemUpIDogaXNFYXIoZWFyKSkgewogICAgICAgIHRyaWFuZ2xlcy5wdXNoKHByZXYuaSwgZWFyLmksIG5leHQuaSk7CiAgICAgICAgcmVtb3ZlTm9kZShlYXIpOwogICAgICAgIGVhciA9IG5leHQubmV4dDsKICAgICAgICBzdG9wID0gbmV4dC5uZXh0OwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGVhciA9IG5leHQ7CiAgICAgIGlmIChlYXIgPT09IHN0b3ApIHsKICAgICAgICBpZiAoIXBhc3MpIHsKICAgICAgICAgIGVhcmN1dExpbmtlZChmaWx0ZXJQb2ludHMoZWFyKSwgdHJpYW5nbGVzLCBkaW0sIG1pblgsIG1pblksIGludlNpemUsIDEpOwogICAgICAgIH0gZWxzZSBpZiAocGFzcyA9PT0gMSkgewogICAgICAgICAgZWFyID0gY3VyZUxvY2FsSW50ZXJzZWN0aW9ucyhmaWx0ZXJQb2ludHMoZWFyKSwgdHJpYW5nbGVzKTsKICAgICAgICAgIGVhcmN1dExpbmtlZChlYXIsIHRyaWFuZ2xlcywgZGltLCBtaW5YLCBtaW5ZLCBpbnZTaXplLCAyKTsKICAgICAgICB9IGVsc2UgaWYgKHBhc3MgPT09IDIpIHsKICAgICAgICAgIHNwbGl0RWFyY3V0KGVhciwgdHJpYW5nbGVzLCBkaW0sIG1pblgsIG1pblksIGludlNpemUpOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogIH0KICBmdW5jdGlvbiBpc0VhcihlYXIpIHsKICAgIGNvbnN0IGEzID0gZWFyLnByZXYsIGIgPSBlYXIsIGMgPSBlYXIubmV4dDsKICAgIGlmIChhcmVhKGEzLCBiLCBjKSA+PSAwKSByZXR1cm4gZmFsc2U7CiAgICBjb25zdCBheCA9IGEzLngsIGJ4ID0gYi54LCBjeCA9IGMueCwgYXkgPSBhMy55LCBieSA9IGIueSwgY3kgPSBjLnk7CiAgICBjb25zdCB4MCA9IE1hdGgubWluKGF4LCBieCwgY3gpLCB5MCA9IE1hdGgubWluKGF5LCBieSwgY3kpLCB4MSA9IE1hdGgubWF4KGF4LCBieCwgY3gpLCB5MSA9IE1hdGgubWF4KGF5LCBieSwgY3kpOwogICAgbGV0IHAgPSBjLm5leHQ7CiAgICB3aGlsZSAocCAhPT0gYTMpIHsKICAgICAgaWYgKHAueCA+PSB4MCAmJiBwLnggPD0geDEgJiYgcC55ID49IHkwICYmIHAueSA8PSB5MSAmJiBwb2ludEluVHJpYW5nbGVFeGNlcHRGaXJzdChheCwgYXksIGJ4LCBieSwgY3gsIGN5LCBwLngsIHAueSkgJiYgYXJlYShwLnByZXYsIHAsIHAubmV4dCkgPj0gMCkgcmV0dXJuIGZhbHNlOwogICAgICBwID0gcC5uZXh0OwogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfQogIGZ1bmN0aW9uIGlzRWFySGFzaGVkKGVhciwgbWluWCwgbWluWSwgaW52U2l6ZSkgewogICAgY29uc3QgYTMgPSBlYXIucHJldiwgYiA9IGVhciwgYyA9IGVhci5uZXh0OwogICAgaWYgKGFyZWEoYTMsIGIsIGMpID49IDApIHJldHVybiBmYWxzZTsKICAgIGNvbnN0IGF4ID0gYTMueCwgYnggPSBiLngsIGN4ID0gYy54LCBheSA9IGEzLnksIGJ5ID0gYi55LCBjeSA9IGMueTsKICAgIGNvbnN0IHgwID0gTWF0aC5taW4oYXgsIGJ4LCBjeCksIHkwID0gTWF0aC5taW4oYXksIGJ5LCBjeSksIHgxID0gTWF0aC5tYXgoYXgsIGJ4LCBjeCksIHkxID0gTWF0aC5tYXgoYXksIGJ5LCBjeSk7CiAgICBjb25zdCBtaW5aID0gek9yZGVyKHgwLCB5MCwgbWluWCwgbWluWSwgaW52U2l6ZSksIG1heFogPSB6T3JkZXIoeDEsIHkxLCBtaW5YLCBtaW5ZLCBpbnZTaXplKTsKICAgIGxldCBwID0gZWFyLnByZXZaLCBuID0gZWFyLm5leHRaOwogICAgd2hpbGUgKHAgJiYgcC56ID49IG1pblogJiYgbiAmJiBuLnogPD0gbWF4WikgewogICAgICBpZiAocC54ID49IHgwICYmIHAueCA8PSB4MSAmJiBwLnkgPj0geTAgJiYgcC55IDw9IHkxICYmIHAgIT09IGEzICYmIHAgIT09IGMgJiYgcG9pbnRJblRyaWFuZ2xlRXhjZXB0Rmlyc3QoYXgsIGF5LCBieCwgYnksIGN4LCBjeSwgcC54LCBwLnkpICYmIGFyZWEocC5wcmV2LCBwLCBwLm5leHQpID49IDApIHJldHVybiBmYWxzZTsKICAgICAgcCA9IHAucHJldlo7CiAgICAgIGlmIChuLnggPj0geDAgJiYgbi54IDw9IHgxICYmIG4ueSA+PSB5MCAmJiBuLnkgPD0geTEgJiYgbiAhPT0gYTMgJiYgbiAhPT0gYyAmJiBwb2ludEluVHJpYW5nbGVFeGNlcHRGaXJzdChheCwgYXksIGJ4LCBieSwgY3gsIGN5LCBuLngsIG4ueSkgJiYgYXJlYShuLnByZXYsIG4sIG4ubmV4dCkgPj0gMCkgcmV0dXJuIGZhbHNlOwogICAgICBuID0gbi5uZXh0WjsKICAgIH0KICAgIHdoaWxlIChwICYmIHAueiA+PSBtaW5aKSB7CiAgICAgIGlmIChwLnggPj0geDAgJiYgcC54IDw9IHgxICYmIHAueSA+PSB5MCAmJiBwLnkgPD0geTEgJiYgcCAhPT0gYTMgJiYgcCAhPT0gYyAmJiBwb2ludEluVHJpYW5nbGVFeGNlcHRGaXJzdChheCwgYXksIGJ4LCBieSwgY3gsIGN5LCBwLngsIHAueSkgJiYgYXJlYShwLnByZXYsIHAsIHAubmV4dCkgPj0gMCkgcmV0dXJuIGZhbHNlOwogICAgICBwID0gcC5wcmV2WjsKICAgIH0KICAgIHdoaWxlIChuICYmIG4ueiA8PSBtYXhaKSB7CiAgICAgIGlmIChuLnggPj0geDAgJiYgbi54IDw9IHgxICYmIG4ueSA+PSB5MCAmJiBuLnkgPD0geTEgJiYgbiAhPT0gYTMgJiYgbiAhPT0gYyAmJiBwb2ludEluVHJpYW5nbGVFeGNlcHRGaXJzdChheCwgYXksIGJ4LCBieSwgY3gsIGN5LCBuLngsIG4ueSkgJiYgYXJlYShuLnByZXYsIG4sIG4ubmV4dCkgPj0gMCkgcmV0dXJuIGZhbHNlOwogICAgICBuID0gbi5uZXh0WjsKICAgIH0KICAgIHJldHVybiB0cnVlOwogIH0KICBmdW5jdGlvbiBjdXJlTG9jYWxJbnRlcnNlY3Rpb25zKHN0YXJ0LCB0cmlhbmdsZXMpIHsKICAgIGxldCBwID0gc3RhcnQ7CiAgICBkbyB7CiAgICAgIGNvbnN0IGEzID0gcC5wcmV2LCBiID0gcC5uZXh0Lm5leHQ7CiAgICAgIGlmICghZXF1YWxzKGEzLCBiKSAmJiBpbnRlcnNlY3RzKGEzLCBwLCBwLm5leHQsIGIpICYmIGxvY2FsbHlJbnNpZGUoYTMsIGIpICYmIGxvY2FsbHlJbnNpZGUoYiwgYTMpKSB7CiAgICAgICAgdHJpYW5nbGVzLnB1c2goYTMuaSwgcC5pLCBiLmkpOwogICAgICAgIHJlbW92ZU5vZGUocCk7CiAgICAgICAgcmVtb3ZlTm9kZShwLm5leHQpOwogICAgICAgIHAgPSBzdGFydCA9IGI7CiAgICAgIH0KICAgICAgcCA9IHAubmV4dDsKICAgIH0gd2hpbGUgKHAgIT09IHN0YXJ0KTsKICAgIHJldHVybiBmaWx0ZXJQb2ludHMocCk7CiAgfQogIGZ1bmN0aW9uIHNwbGl0RWFyY3V0KHN0YXJ0LCB0cmlhbmdsZXMsIGRpbSwgbWluWCwgbWluWSwgaW52U2l6ZSkgewogICAgbGV0IGEzID0gc3RhcnQ7CiAgICBkbyB7CiAgICAgIGxldCBiID0gYTMubmV4dC5uZXh0OwogICAgICB3aGlsZSAoYiAhPT0gYTMucHJldikgewogICAgICAgIGlmIChhMy5pICE9PSBiLmkgJiYgaXNWYWxpZERpYWdvbmFsKGEzLCBiKSkgewogICAgICAgICAgbGV0IGMgPSBzcGxpdFBvbHlnb24oYTMsIGIpOwogICAgICAgICAgYTMgPSBmaWx0ZXJQb2ludHMoYTMsIGEzLm5leHQpOwogICAgICAgICAgYyA9IGZpbHRlclBvaW50cyhjLCBjLm5leHQpOwogICAgICAgICAgZWFyY3V0TGlua2VkKGEzLCB0cmlhbmdsZXMsIGRpbSwgbWluWCwgbWluWSwgaW52U2l6ZSwgMCk7CiAgICAgICAgICBlYXJjdXRMaW5rZWQoYywgdHJpYW5nbGVzLCBkaW0sIG1pblgsIG1pblksIGludlNpemUsIDApOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBiID0gYi5uZXh0OwogICAgICB9CiAgICAgIGEzID0gYTMubmV4dDsKICAgIH0gd2hpbGUgKGEzICE9PSBzdGFydCk7CiAgfQogIGZ1bmN0aW9uIGVsaW1pbmF0ZUhvbGVzKGRhdGEsIGhvbGVJbmRpY2VzLCBvdXRlck5vZGUsIGRpbSkgewogICAgY29uc3QgcXVldWUgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwLCBsZW4gPSBob2xlSW5kaWNlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykgewogICAgICBjb25zdCBzdGFydCA9IGhvbGVJbmRpY2VzW2ldICogZGltOwogICAgICBjb25zdCBlbmQgPSBpIDwgbGVuIC0gMSA/IGhvbGVJbmRpY2VzW2kgKyAxXSAqIGRpbSA6IGRhdGEubGVuZ3RoOwogICAgICBjb25zdCBsaXN0ID0gbGlua2VkTGlzdChkYXRhLCBzdGFydCwgZW5kLCBkaW0sIGZhbHNlKTsKICAgICAgaWYgKGxpc3QgPT09IGxpc3QubmV4dCkgbGlzdC5zdGVpbmVyID0gdHJ1ZTsKICAgICAgcXVldWUucHVzaChnZXRMZWZ0bW9zdChsaXN0KSk7CiAgICB9CiAgICBxdWV1ZS5zb3J0KGNvbXBhcmVYWVNsb3BlKTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcXVldWUubGVuZ3RoOyBpKyspIHsKICAgICAgb3V0ZXJOb2RlID0gZWxpbWluYXRlSG9sZShxdWV1ZVtpXSwgb3V0ZXJOb2RlKTsKICAgIH0KICAgIHJldHVybiBvdXRlck5vZGU7CiAgfQogIGZ1bmN0aW9uIGNvbXBhcmVYWVNsb3BlKGEzLCBiKSB7CiAgICBsZXQgcmVzdWx0ID0gYTMueCAtIGIueDsKICAgIGlmIChyZXN1bHQgPT09IDApIHsKICAgICAgcmVzdWx0ID0gYTMueSAtIGIueTsKICAgICAgaWYgKHJlc3VsdCA9PT0gMCkgewogICAgICAgIGNvbnN0IGFTbG9wZSA9IChhMy5uZXh0LnkgLSBhMy55KSAvIChhMy5uZXh0LnggLSBhMy54KTsKICAgICAgICBjb25zdCBiU2xvcGUgPSAoYi5uZXh0LnkgLSBiLnkpIC8gKGIubmV4dC54IC0gYi54KTsKICAgICAgICByZXN1bHQgPSBhU2xvcGUgLSBiU2xvcGU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGZ1bmN0aW9uIGVsaW1pbmF0ZUhvbGUoaG9sZSwgb3V0ZXJOb2RlKSB7CiAgICBjb25zdCBicmlkZ2UgPSBmaW5kSG9sZUJyaWRnZShob2xlLCBvdXRlck5vZGUpOwogICAgaWYgKCFicmlkZ2UpIHsKICAgICAgcmV0dXJuIG91dGVyTm9kZTsKICAgIH0KICAgIGNvbnN0IGJyaWRnZVJldmVyc2UgPSBzcGxpdFBvbHlnb24oYnJpZGdlLCBob2xlKTsKICAgIGZpbHRlclBvaW50cyhicmlkZ2VSZXZlcnNlLCBicmlkZ2VSZXZlcnNlLm5leHQpOwogICAgcmV0dXJuIGZpbHRlclBvaW50cyhicmlkZ2UsIGJyaWRnZS5uZXh0KTsKICB9CiAgZnVuY3Rpb24gZmluZEhvbGVCcmlkZ2UoaG9sZSwgb3V0ZXJOb2RlKSB7CiAgICBsZXQgcCA9IG91dGVyTm9kZTsKICAgIGNvbnN0IGh4ID0gaG9sZS54OwogICAgY29uc3QgaHkgPSBob2xlLnk7CiAgICBsZXQgcXggPSAtSW5maW5pdHk7CiAgICBsZXQgbTsKICAgIGlmIChlcXVhbHMoaG9sZSwgcCkpIHJldHVybiBwOwogICAgZG8gewogICAgICBpZiAoZXF1YWxzKGhvbGUsIHAubmV4dCkpIHJldHVybiBwLm5leHQ7CiAgICAgIGVsc2UgaWYgKGh5IDw9IHAueSAmJiBoeSA+PSBwLm5leHQueSAmJiBwLm5leHQueSAhPT0gcC55KSB7CiAgICAgICAgY29uc3QgeCA9IHAueCArIChoeSAtIHAueSkgKiAocC5uZXh0LnggLSBwLngpIC8gKHAubmV4dC55IC0gcC55KTsKICAgICAgICBpZiAoeCA8PSBoeCAmJiB4ID4gcXgpIHsKICAgICAgICAgIHF4ID0geDsKICAgICAgICAgIG0gPSBwLnggPCBwLm5leHQueCA/IHAgOiBwLm5leHQ7CiAgICAgICAgICBpZiAoeCA9PT0gaHgpIHJldHVybiBtOwogICAgICAgIH0KICAgICAgfQogICAgICBwID0gcC5uZXh0OwogICAgfSB3aGlsZSAocCAhPT0gb3V0ZXJOb2RlKTsKICAgIGlmICghbSkgcmV0dXJuIG51bGw7CiAgICBjb25zdCBzdG9wID0gbTsKICAgIGNvbnN0IG14ID0gbS54OwogICAgY29uc3QgbXkgPSBtLnk7CiAgICBsZXQgdGFuTWluID0gSW5maW5pdHk7CiAgICBwID0gbTsKICAgIGRvIHsKICAgICAgaWYgKGh4ID49IHAueCAmJiBwLnggPj0gbXggJiYgaHggIT09IHAueCAmJiBwb2ludEluVHJpYW5nbGUoaHkgPCBteSA/IGh4IDogcXgsIGh5LCBteCwgbXksIGh5IDwgbXkgPyBxeCA6IGh4LCBoeSwgcC54LCBwLnkpKSB7CiAgICAgICAgY29uc3QgdGFuID0gTWF0aC5hYnMoaHkgLSBwLnkpIC8gKGh4IC0gcC54KTsKICAgICAgICBpZiAobG9jYWxseUluc2lkZShwLCBob2xlKSAmJiAodGFuIDwgdGFuTWluIHx8IHRhbiA9PT0gdGFuTWluICYmIChwLnggPiBtLnggfHwgcC54ID09PSBtLnggJiYgc2VjdG9yQ29udGFpbnNTZWN0b3IobSwgcCkpKSkgewogICAgICAgICAgbSA9IHA7CiAgICAgICAgICB0YW5NaW4gPSB0YW47CiAgICAgICAgfQogICAgICB9CiAgICAgIHAgPSBwLm5leHQ7CiAgICB9IHdoaWxlIChwICE9PSBzdG9wKTsKICAgIHJldHVybiBtOwogIH0KICBmdW5jdGlvbiBzZWN0b3JDb250YWluc1NlY3RvcihtLCBwKSB7CiAgICByZXR1cm4gYXJlYShtLnByZXYsIG0sIHAucHJldikgPCAwICYmIGFyZWEocC5uZXh0LCBtLCBtLm5leHQpIDwgMDsKICB9CiAgZnVuY3Rpb24gaW5kZXhDdXJ2ZShzdGFydCwgbWluWCwgbWluWSwgaW52U2l6ZSkgewogICAgbGV0IHAgPSBzdGFydDsKICAgIGRvIHsKICAgICAgaWYgKHAueiA9PT0gMCkgcC56ID0gek9yZGVyKHAueCwgcC55LCBtaW5YLCBtaW5ZLCBpbnZTaXplKTsKICAgICAgcC5wcmV2WiA9IHAucHJldjsKICAgICAgcC5uZXh0WiA9IHAubmV4dDsKICAgICAgcCA9IHAubmV4dDsKICAgIH0gd2hpbGUgKHAgIT09IHN0YXJ0KTsKICAgIHAucHJldloubmV4dFogPSBudWxsOwogICAgcC5wcmV2WiA9IG51bGw7CiAgICBzb3J0TGlua2VkKHApOwogIH0KICBmdW5jdGlvbiBzb3J0TGlua2VkKGxpc3QpIHsKICAgIGxldCBudW1NZXJnZXM7CiAgICBsZXQgaW5TaXplID0gMTsKICAgIGRvIHsKICAgICAgbGV0IHAgPSBsaXN0OwogICAgICBsZXQgZTsKICAgICAgbGlzdCA9IG51bGw7CiAgICAgIGxldCB0YWlsID0gbnVsbDsKICAgICAgbnVtTWVyZ2VzID0gMDsKICAgICAgd2hpbGUgKHApIHsKICAgICAgICBudW1NZXJnZXMrKzsKICAgICAgICBsZXQgcSA9IHA7CiAgICAgICAgbGV0IHBTaXplID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluU2l6ZTsgaSsrKSB7CiAgICAgICAgICBwU2l6ZSsrOwogICAgICAgICAgcSA9IHEubmV4dFo7CiAgICAgICAgICBpZiAoIXEpIGJyZWFrOwogICAgICAgIH0KICAgICAgICBsZXQgcVNpemUgPSBpblNpemU7CiAgICAgICAgd2hpbGUgKHBTaXplID4gMCB8fCBxU2l6ZSA+IDAgJiYgcSkgewogICAgICAgICAgaWYgKHBTaXplICE9PSAwICYmIChxU2l6ZSA9PT0gMCB8fCAhcSB8fCBwLnogPD0gcS56KSkgewogICAgICAgICAgICBlID0gcDsKICAgICAgICAgICAgcCA9IHAubmV4dFo7CiAgICAgICAgICAgIHBTaXplLS07CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlID0gcTsKICAgICAgICAgICAgcSA9IHEubmV4dFo7CiAgICAgICAgICAgIHFTaXplLS07CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodGFpbCkgdGFpbC5uZXh0WiA9IGU7CiAgICAgICAgICBlbHNlIGxpc3QgPSBlOwogICAgICAgICAgZS5wcmV2WiA9IHRhaWw7CiAgICAgICAgICB0YWlsID0gZTsKICAgICAgICB9CiAgICAgICAgcCA9IHE7CiAgICAgIH0KICAgICAgdGFpbC5uZXh0WiA9IG51bGw7CiAgICAgIGluU2l6ZSAqPSAyOwogICAgfSB3aGlsZSAobnVtTWVyZ2VzID4gMSk7CiAgICByZXR1cm4gbGlzdDsKICB9CiAgZnVuY3Rpb24gek9yZGVyKHgsIHksIG1pblgsIG1pblksIGludlNpemUpIHsKICAgIHggPSAoeCAtIG1pblgpICogaW52U2l6ZSB8IDA7CiAgICB5ID0gKHkgLSBtaW5ZKSAqIGludlNpemUgfCAwOwogICAgeCA9ICh4IHwgeCA8PCA4KSAmIDE2NzExOTM1OwogICAgeCA9ICh4IHwgeCA8PCA0KSAmIDI1MjY0NTEzNTsKICAgIHggPSAoeCB8IHggPDwgMikgJiA4NTg5OTM0NTk7CiAgICB4ID0gKHggfCB4IDw8IDEpICYgMTQzMTY1NTc2NTsKICAgIHkgPSAoeSB8IHkgPDwgOCkgJiAxNjcxMTkzNTsKICAgIHkgPSAoeSB8IHkgPDwgNCkgJiAyNTI2NDUxMzU7CiAgICB5ID0gKHkgfCB5IDw8IDIpICYgODU4OTkzNDU5OwogICAgeSA9ICh5IHwgeSA8PCAxKSAmIDE0MzE2NTU3NjU7CiAgICByZXR1cm4geCB8IHkgPDwgMTsKICB9CiAgZnVuY3Rpb24gZ2V0TGVmdG1vc3Qoc3RhcnQpIHsKICAgIGxldCBwID0gc3RhcnQsIGxlZnRtb3N0ID0gc3RhcnQ7CiAgICBkbyB7CiAgICAgIGlmIChwLnggPCBsZWZ0bW9zdC54IHx8IHAueCA9PT0gbGVmdG1vc3QueCAmJiBwLnkgPCBsZWZ0bW9zdC55KSBsZWZ0bW9zdCA9IHA7CiAgICAgIHAgPSBwLm5leHQ7CiAgICB9IHdoaWxlIChwICE9PSBzdGFydCk7CiAgICByZXR1cm4gbGVmdG1vc3Q7CiAgfQogIGZ1bmN0aW9uIHBvaW50SW5UcmlhbmdsZShheCwgYXksIGJ4LCBieSwgY3gsIGN5LCBweCwgcHkpIHsKICAgIHJldHVybiAoY3ggLSBweCkgKiAoYXkgLSBweSkgPj0gKGF4IC0gcHgpICogKGN5IC0gcHkpICYmIChheCAtIHB4KSAqIChieSAtIHB5KSA+PSAoYnggLSBweCkgKiAoYXkgLSBweSkgJiYgKGJ4IC0gcHgpICogKGN5IC0gcHkpID49IChjeCAtIHB4KSAqIChieSAtIHB5KTsKICB9CiAgZnVuY3Rpb24gcG9pbnRJblRyaWFuZ2xlRXhjZXB0Rmlyc3QoYXgsIGF5LCBieCwgYnksIGN4LCBjeSwgcHgsIHB5KSB7CiAgICByZXR1cm4gIShheCA9PT0gcHggJiYgYXkgPT09IHB5KSAmJiBwb2ludEluVHJpYW5nbGUoYXgsIGF5LCBieCwgYnksIGN4LCBjeSwgcHgsIHB5KTsKICB9CiAgZnVuY3Rpb24gaXNWYWxpZERpYWdvbmFsKGEzLCBiKSB7CiAgICByZXR1cm4gYTMubmV4dC5pICE9PSBiLmkgJiYgYTMucHJldi5pICE9PSBiLmkgJiYgIWludGVyc2VjdHNQb2x5Z29uKGEzLCBiKSAmJiAvLyBkb2Vzbid0IGludGVyc2VjdCBvdGhlciBlZGdlcwogICAgKGxvY2FsbHlJbnNpZGUoYTMsIGIpICYmIGxvY2FsbHlJbnNpZGUoYiwgYTMpICYmIG1pZGRsZUluc2lkZShhMywgYikgJiYgLy8gbG9jYWxseSB2aXNpYmxlCiAgICAoYXJlYShhMy5wcmV2LCBhMywgYi5wcmV2KSB8fCBhcmVhKGEzLCBiLnByZXYsIGIpKSB8fCAvLyBkb2VzIG5vdCBjcmVhdGUgb3Bwb3NpdGUtZmFjaW5nIHNlY3RvcnMKICAgIGVxdWFscyhhMywgYikgJiYgYXJlYShhMy5wcmV2LCBhMywgYTMubmV4dCkgPiAwICYmIGFyZWEoYi5wcmV2LCBiLCBiLm5leHQpID4gMCk7CiAgfQogIGZ1bmN0aW9uIGFyZWEocCwgcSwgcikgewogICAgcmV0dXJuIChxLnkgLSBwLnkpICogKHIueCAtIHEueCkgLSAocS54IC0gcC54KSAqIChyLnkgLSBxLnkpOwogIH0KICBmdW5jdGlvbiBlcXVhbHMocDEsIHAyKSB7CiAgICByZXR1cm4gcDEueCA9PT0gcDIueCAmJiBwMS55ID09PSBwMi55OwogIH0KICBmdW5jdGlvbiBpbnRlcnNlY3RzKHAxLCBxMTIsIHAyLCBxMjIpIHsKICAgIGNvbnN0IG8xID0gc2lnbjIoYXJlYShwMSwgcTEyLCBwMikpOwogICAgY29uc3QgbzIgPSBzaWduMihhcmVhKHAxLCBxMTIsIHEyMikpOwogICAgY29uc3QgbzMgPSBzaWduMihhcmVhKHAyLCBxMjIsIHAxKSk7CiAgICBjb25zdCBvNCA9IHNpZ24yKGFyZWEocDIsIHEyMiwgcTEyKSk7CiAgICBpZiAobzEgIT09IG8yICYmIG8zICE9PSBvNCkgcmV0dXJuIHRydWU7CiAgICBpZiAobzEgPT09IDAgJiYgb25TZWdtZW50KHAxLCBwMiwgcTEyKSkgcmV0dXJuIHRydWU7CiAgICBpZiAobzIgPT09IDAgJiYgb25TZWdtZW50KHAxLCBxMjIsIHExMikpIHJldHVybiB0cnVlOwogICAgaWYgKG8zID09PSAwICYmIG9uU2VnbWVudChwMiwgcDEsIHEyMikpIHJldHVybiB0cnVlOwogICAgaWYgKG80ID09PSAwICYmIG9uU2VnbWVudChwMiwgcTEyLCBxMjIpKSByZXR1cm4gdHJ1ZTsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgZnVuY3Rpb24gb25TZWdtZW50KHAsIHEsIHIpIHsKICAgIHJldHVybiBxLnggPD0gTWF0aC5tYXgocC54LCByLngpICYmIHEueCA+PSBNYXRoLm1pbihwLngsIHIueCkgJiYgcS55IDw9IE1hdGgubWF4KHAueSwgci55KSAmJiBxLnkgPj0gTWF0aC5taW4ocC55LCByLnkpOwogIH0KICBmdW5jdGlvbiBzaWduMihudW0pIHsKICAgIHJldHVybiBudW0gPiAwID8gMSA6IG51bSA8IDAgPyAtMSA6IDA7CiAgfQogIGZ1bmN0aW9uIGludGVyc2VjdHNQb2x5Z29uKGEzLCBiKSB7CiAgICBsZXQgcCA9IGEzOwogICAgZG8gewogICAgICBpZiAocC5pICE9PSBhMy5pICYmIHAubmV4dC5pICE9PSBhMy5pICYmIHAuaSAhPT0gYi5pICYmIHAubmV4dC5pICE9PSBiLmkgJiYgaW50ZXJzZWN0cyhwLCBwLm5leHQsIGEzLCBiKSkgcmV0dXJuIHRydWU7CiAgICAgIHAgPSBwLm5leHQ7CiAgICB9IHdoaWxlIChwICE9PSBhMyk7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGZ1bmN0aW9uIGxvY2FsbHlJbnNpZGUoYTMsIGIpIHsKICAgIHJldHVybiBhcmVhKGEzLnByZXYsIGEzLCBhMy5uZXh0KSA8IDAgPyBhcmVhKGEzLCBiLCBhMy5uZXh0KSA+PSAwICYmIGFyZWEoYTMsIGEzLnByZXYsIGIpID49IDAgOiBhcmVhKGEzLCBiLCBhMy5wcmV2KSA8IDAgfHwgYXJlYShhMywgYTMubmV4dCwgYikgPCAwOwogIH0KICBmdW5jdGlvbiBtaWRkbGVJbnNpZGUoYTMsIGIpIHsKICAgIGxldCBwID0gYTM7CiAgICBsZXQgaW5zaWRlID0gZmFsc2U7CiAgICBjb25zdCBweCA9IChhMy54ICsgYi54KSAvIDI7CiAgICBjb25zdCBweSA9IChhMy55ICsgYi55KSAvIDI7CiAgICBkbyB7CiAgICAgIGlmIChwLnkgPiBweSAhPT0gcC5uZXh0LnkgPiBweSAmJiBwLm5leHQueSAhPT0gcC55ICYmIHB4IDwgKHAubmV4dC54IC0gcC54KSAqIChweSAtIHAueSkgLyAocC5uZXh0LnkgLSBwLnkpICsgcC54KQogICAgICAgIGluc2lkZSA9ICFpbnNpZGU7CiAgICAgIHAgPSBwLm5leHQ7CiAgICB9IHdoaWxlIChwICE9PSBhMyk7CiAgICByZXR1cm4gaW5zaWRlOwogIH0KICBmdW5jdGlvbiBzcGxpdFBvbHlnb24oYTMsIGIpIHsKICAgIGNvbnN0IGEyMiA9IGNyZWF0ZU5vZGUoYTMuaSwgYTMueCwgYTMueSksIGIyID0gY3JlYXRlTm9kZShiLmksIGIueCwgYi55KSwgYW4gPSBhMy5uZXh0LCBicCA9IGIucHJldjsKICAgIGEzLm5leHQgPSBiOwogICAgYi5wcmV2ID0gYTM7CiAgICBhMjIubmV4dCA9IGFuOwogICAgYW4ucHJldiA9IGEyMjsKICAgIGIyLm5leHQgPSBhMjI7CiAgICBhMjIucHJldiA9IGIyOwogICAgYnAubmV4dCA9IGIyOwogICAgYjIucHJldiA9IGJwOwogICAgcmV0dXJuIGIyOwogIH0KICBmdW5jdGlvbiBpbnNlcnROb2RlKGksIHgsIHksIGxhc3QpIHsKICAgIGNvbnN0IHAgPSBjcmVhdGVOb2RlKGksIHgsIHkpOwogICAgaWYgKCFsYXN0KSB7CiAgICAgIHAucHJldiA9IHA7CiAgICAgIHAubmV4dCA9IHA7CiAgICB9IGVsc2UgewogICAgICBwLm5leHQgPSBsYXN0Lm5leHQ7CiAgICAgIHAucHJldiA9IGxhc3Q7CiAgICAgIGxhc3QubmV4dC5wcmV2ID0gcDsKICAgICAgbGFzdC5uZXh0ID0gcDsKICAgIH0KICAgIHJldHVybiBwOwogIH0KICBmdW5jdGlvbiByZW1vdmVOb2RlKHApIHsKICAgIHAubmV4dC5wcmV2ID0gcC5wcmV2OwogICAgcC5wcmV2Lm5leHQgPSBwLm5leHQ7CiAgICBpZiAocC5wcmV2WikgcC5wcmV2Wi5uZXh0WiA9IHAubmV4dFo7CiAgICBpZiAocC5uZXh0WikgcC5uZXh0Wi5wcmV2WiA9IHAucHJldlo7CiAgfQogIGZ1bmN0aW9uIGNyZWF0ZU5vZGUoaSwgeCwgeSkgewogICAgcmV0dXJuIHsKICAgICAgaSwKICAgICAgLy8gdmVydGV4IGluZGV4IGluIGNvb3JkaW5hdGVzIGFycmF5CiAgICAgIHgsCiAgICAgIHksCiAgICAgIC8vIHZlcnRleCBjb29yZGluYXRlcwogICAgICBwcmV2OiBudWxsLAogICAgICAvLyBwcmV2aW91cyBhbmQgbmV4dCB2ZXJ0ZXggbm9kZXMgaW4gYSBwb2x5Z29uIHJpbmcKICAgICAgbmV4dDogbnVsbCwKICAgICAgejogMCwKICAgICAgLy8gei1vcmRlciBjdXJ2ZSB2YWx1ZQogICAgICBwcmV2WjogbnVsbCwKICAgICAgLy8gcHJldmlvdXMgYW5kIG5leHQgbm9kZXMgaW4gei1vcmRlcgogICAgICBuZXh0WjogbnVsbCwKICAgICAgc3RlaW5lcjogZmFsc2UKICAgICAgLy8gaW5kaWNhdGVzIHdoZXRoZXIgdGhpcyBpcyBhIHN0ZWluZXIgcG9pbnQKICAgIH07CiAgfQogIGZ1bmN0aW9uIHNpZ25lZEFyZWEoZGF0YSwgc3RhcnQsIGVuZCwgZGltKSB7CiAgICBsZXQgc3VtID0gMDsKICAgIGZvciAobGV0IGkgPSBzdGFydCwgaiA9IGVuZCAtIGRpbTsgaSA8IGVuZDsgaSArPSBkaW0pIHsKICAgICAgc3VtICs9IChkYXRhW2pdIC0gZGF0YVtpXSkgKiAoZGF0YVtpICsgMV0gKyBkYXRhW2ogKyAxXSk7CiAgICAgIGogPSBpOwogICAgfQogICAgcmV0dXJuIHN1bTsKICB9CiAgdmFyIGluaXRfZWFyY3V0ID0gX19lc20oewogICAgIm5vZGVfbW9kdWxlcy9lYXJjdXQvc3JjL2VhcmN1dC5qcyIoKSB7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9XaW5kaW5nT3JkZXIuanMKICB2YXIgV2luZGluZ09yZGVyLCBXaW5kaW5nT3JkZXJfZGVmYXVsdDsKICB2YXIgaW5pdF9XaW5kaW5nT3JkZXIgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1dpbmRpbmdPcmRlci5qcyIoKSB7CiAgICAgIGluaXRfV2ViR0xDb25zdGFudHMoKTsKICAgICAgV2luZGluZ09yZGVyID0gewogICAgICAgIC8qKgogICAgICAgICAqIFZlcnRpY2VzIGFyZSBpbiBjbG9ja3dpc2Ugb3JkZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIENMT0NLV0lTRTogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5DVywKICAgICAgICAvKioKICAgICAgICAgKiBWZXJ0aWNlcyBhcmUgaW4gY291bnRlci1jbG9ja3dpc2Ugb3JkZXIuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIENPVU5URVJfQ0xPQ0tXSVNFOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkNDVwogICAgICB9OwogICAgICBXaW5kaW5nT3JkZXIudmFsaWRhdGUgPSBmdW5jdGlvbih3aW5kaW5nT3JkZXIpIHsKICAgICAgICByZXR1cm4gd2luZGluZ09yZGVyID09PSBXaW5kaW5nT3JkZXIuQ0xPQ0tXSVNFIHx8IHdpbmRpbmdPcmRlciA9PT0gV2luZGluZ09yZGVyLkNPVU5URVJfQ0xPQ0tXSVNFOwogICAgICB9OwogICAgICBXaW5kaW5nT3JkZXJfZGVmYXVsdCA9IE9iamVjdC5mcmVlemUoV2luZGluZ09yZGVyKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1BvbHlnb25QaXBlbGluZS5qcwogIHZhciBzY2FsZVRvR2VvZGV0aWNIZWlnaHROLCBzY2FsZVRvR2VvZGV0aWNIZWlnaHRQLCBQb2x5Z29uUGlwZWxpbmUsIHN1YmRpdmlzaW9uVjBTY3JhdGNoLCBzdWJkaXZpc2lvblYxU2NyYXRjaCwgc3ViZGl2aXNpb25WMlNjcmF0Y2gsIHN1YmRpdmlzaW9uUzBTY3JhdGNoLCBzdWJkaXZpc2lvblMxU2NyYXRjaCwgc3ViZGl2aXNpb25TMlNjcmF0Y2gsIHN1YmRpdmlzaW9uTWlkU2NyYXRjaCwgc3ViZGl2aXNpb25UMFNjcmF0Y2gsIHN1YmRpdmlzaW9uVDFTY3JhdGNoLCBzdWJkaXZpc2lvblQyU2NyYXRjaCwgc3ViZGl2aXNpb25UZXhjb29yZE1pZFNjcmF0Y2gsIHN1YmRpdmlzaW9uQzBTY3JhdGNoLCBzdWJkaXZpc2lvbkMxU2NyYXRjaCwgc3ViZGl2aXNpb25DMlNjcmF0Y2gsIHN1YmRpdmlzaW9uQ2FydG9ncmFwaGljU2NyYXRjaCwgUG9seWdvblBpcGVsaW5lX2RlZmF1bHQ7CiAgdmFyIGluaXRfUG9seWdvblBpcGVsaW5lID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Qb2x5Z29uUGlwZWxpbmUuanMiKCkgewogICAgICBpbml0X2VhcmN1dCgpOwogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWRSaHVtYkxpbmUoKTsKICAgICAgaW5pdF9HZW9tZXRyeSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgaW5pdF9XaW5kaW5nT3JkZXIoKTsKICAgICAgc2NhbGVUb0dlb2RldGljSGVpZ2h0TiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NhbGVUb0dlb2RldGljSGVpZ2h0UCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgUG9seWdvblBpcGVsaW5lID0ge307CiAgICAgIFBvbHlnb25QaXBlbGluZS5jb21wdXRlQXJlYTJEID0gZnVuY3Rpb24ocG9zaXRpb25zKSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJwb3NpdGlvbnMiLCBwb3NpdGlvbnMpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKAogICAgICAgICAgInBvc2l0aW9ucy5sZW5ndGgiLAogICAgICAgICAgcG9zaXRpb25zLmxlbmd0aCwKICAgICAgICAgIDMKICAgICAgICApOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgbGV0IGFyZWEyID0gMDsKICAgICAgICBmb3IgKGxldCBpMCA9IGxlbmd0aCAtIDEsIGkxID0gMDsgaTEgPCBsZW5ndGg7IGkwID0gaTErKykgewogICAgICAgICAgY29uc3QgdjAyID0gcG9zaXRpb25zW2kwXTsKICAgICAgICAgIGNvbnN0IHYxMiA9IHBvc2l0aW9uc1tpMV07CiAgICAgICAgICBhcmVhMiArPSB2MDIueCAqIHYxMi55IC0gdjEyLnggKiB2MDIueTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGFyZWEyICogMC41OwogICAgICB9OwogICAgICBQb2x5Z29uUGlwZWxpbmUuY29tcHV0ZVdpbmRpbmdPcmRlcjJEID0gZnVuY3Rpb24ocG9zaXRpb25zKSB7CiAgICAgICAgY29uc3QgYXJlYTIgPSBQb2x5Z29uUGlwZWxpbmUuY29tcHV0ZUFyZWEyRChwb3NpdGlvbnMpOwogICAgICAgIHJldHVybiBhcmVhMiA+IDAgPyBXaW5kaW5nT3JkZXJfZGVmYXVsdC5DT1VOVEVSX0NMT0NLV0lTRSA6IFdpbmRpbmdPcmRlcl9kZWZhdWx0LkNMT0NLV0lTRTsKICAgICAgfTsKICAgICAgUG9seWdvblBpcGVsaW5lLnRyaWFuZ3VsYXRlID0gZnVuY3Rpb24ocG9zaXRpb25zLCBob2xlcykgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgicG9zaXRpb25zIiwgcG9zaXRpb25zKTsKICAgICAgICBjb25zdCBmbGF0dGVuZWRQb3NpdGlvbnMgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQucGFja0FycmF5KHBvc2l0aW9ucyk7CiAgICAgICAgcmV0dXJuIGVhcmN1dChmbGF0dGVuZWRQb3NpdGlvbnMsIGhvbGVzLCAyKTsKICAgICAgfTsKICAgICAgc3ViZGl2aXNpb25WMFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHN1YmRpdmlzaW9uVjFTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzdWJkaXZpc2lvblYyU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc3ViZGl2aXNpb25TMFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHN1YmRpdmlzaW9uUzFTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzdWJkaXZpc2lvblMyU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc3ViZGl2aXNpb25NaWRTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzdWJkaXZpc2lvblQwU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKTsKICAgICAgc3ViZGl2aXNpb25UMVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIHN1YmRpdmlzaW9uVDJTY3JhdGNoID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBzdWJkaXZpc2lvblRleGNvb3JkTWlkU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKTsKICAgICAgUG9seWdvblBpcGVsaW5lLmNvbXB1dGVTdWJkaXZpc2lvbiA9IGZ1bmN0aW9uKGVsbGlwc29pZCwgcG9zaXRpb25zLCBpbmRpY2VzLCB0ZXhjb29yZHMsIGdyYW51bGFyaXR5KSB7CiAgICAgICAgZ3JhbnVsYXJpdHkgPSBncmFudWxhcml0eSA/PyBNYXRoX2RlZmF1bHQuUkFESUFOU19QRVJfREVHUkVFOwogICAgICAgIGNvbnN0IGhhc1RleGNvb3JkcyA9IGRlZmluZWRfZGVmYXVsdCh0ZXhjb29yZHMpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiZWxsaXBzb2lkIiwgZWxsaXBzb2lkKTsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInBvc2l0aW9ucyIsIHBvc2l0aW9ucyk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJpbmRpY2VzIiwgaW5kaWNlcyk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoImluZGljZXMubGVuZ3RoIiwgaW5kaWNlcy5sZW5ndGgsIDMpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5lcXVhbHMoImluZGljZXMubGVuZ3RoICUgMyIsICIwIiwgaW5kaWNlcy5sZW5ndGggJSAzLCAwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW4oImdyYW51bGFyaXR5IiwgZ3JhbnVsYXJpdHksIDApOwogICAgICAgIGNvbnN0IHRyaWFuZ2xlcyA9IGluZGljZXMuc2xpY2UoMCk7CiAgICAgICAgbGV0IGk7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBjb25zdCBzdWJkaXZpZGVkUG9zaXRpb25zID0gbmV3IEFycmF5KGxlbmd0aCAqIDMpOwogICAgICAgIGNvbnN0IHN1YmRpdmlkZWRUZXhjb29yZHMgPSBuZXcgQXJyYXkobGVuZ3RoICogMik7CiAgICAgICAgbGV0IHEgPSAwOwogICAgICAgIGxldCBwID0gMDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGNvbnN0IGl0ZW0gPSBwb3NpdGlvbnNbaV07CiAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zW3ErK10gPSBpdGVtLng7CiAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zW3ErK10gPSBpdGVtLnk7CiAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zW3ErK10gPSBpdGVtLno7CiAgICAgICAgICBpZiAoaGFzVGV4Y29vcmRzKSB7CiAgICAgICAgICAgIGNvbnN0IHRleGNvb3JkSXRlbSA9IHRleGNvb3Jkc1tpXTsKICAgICAgICAgICAgc3ViZGl2aWRlZFRleGNvb3Jkc1twKytdID0gdGV4Y29vcmRJdGVtLng7CiAgICAgICAgICAgIHN1YmRpdmlkZWRUZXhjb29yZHNbcCsrXSA9IHRleGNvb3JkSXRlbS55OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBzdWJkaXZpZGVkSW5kaWNlcyA9IFtdOwogICAgICAgIGNvbnN0IGVkZ2VzID0ge307CiAgICAgICAgY29uc3QgcmFkaXVzID0gZWxsaXBzb2lkLm1heGltdW1SYWRpdXM7CiAgICAgICAgY29uc3QgbWluRGlzdGFuY2UgPSBNYXRoX2RlZmF1bHQuY2hvcmRMZW5ndGgoZ3JhbnVsYXJpdHksIHJhZGl1cyk7CiAgICAgICAgY29uc3QgbWluRGlzdGFuY2VTcXJkID0gbWluRGlzdGFuY2UgKiBtaW5EaXN0YW5jZTsKICAgICAgICB3aGlsZSAodHJpYW5nbGVzLmxlbmd0aCA+IDApIHsKICAgICAgICAgIGNvbnN0IGkyID0gdHJpYW5nbGVzLnBvcCgpOwogICAgICAgICAgY29uc3QgaTEgPSB0cmlhbmdsZXMucG9wKCk7CiAgICAgICAgICBjb25zdCBpMCA9IHRyaWFuZ2xlcy5wb3AoKTsKICAgICAgICAgIGNvbnN0IHYwMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnMsCiAgICAgICAgICAgIGkwICogMywKICAgICAgICAgICAgc3ViZGl2aXNpb25WMFNjcmF0Y2gKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCB2MTIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zLAogICAgICAgICAgICBpMSAqIDMsCiAgICAgICAgICAgIHN1YmRpdmlzaW9uVjFTY3JhdGNoCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgdjIyID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9ucywKICAgICAgICAgICAgaTIgKiAzLAogICAgICAgICAgICBzdWJkaXZpc2lvblYyU2NyYXRjaAogICAgICAgICAgKTsKICAgICAgICAgIGxldCB0MCwgdDEsIHQyOwogICAgICAgICAgaWYgKGhhc1RleGNvb3JkcykgewogICAgICAgICAgICB0MCA9IENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICAgICAgc3ViZGl2aWRlZFRleGNvb3JkcywKICAgICAgICAgICAgICBpMCAqIDIsCiAgICAgICAgICAgICAgc3ViZGl2aXNpb25UMFNjcmF0Y2gKICAgICAgICAgICAgKTsKICAgICAgICAgICAgdDEgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgICAgIHN1YmRpdmlkZWRUZXhjb29yZHMsCiAgICAgICAgICAgICAgaTEgKiAyLAogICAgICAgICAgICAgIHN1YmRpdmlzaW9uVDFTY3JhdGNoCiAgICAgICAgICAgICk7CiAgICAgICAgICAgIHQyID0gQ2FydGVzaWFuMl9kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgICAgICBzdWJkaXZpZGVkVGV4Y29vcmRzLAogICAgICAgICAgICAgIGkyICogMiwKICAgICAgICAgICAgICBzdWJkaXZpc2lvblQyU2NyYXRjaAogICAgICAgICAgICApOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgczAgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSh2MDIsIHN1YmRpdmlzaW9uUzBTY3JhdGNoKSwKICAgICAgICAgICAgcmFkaXVzLAogICAgICAgICAgICBzdWJkaXZpc2lvblMwU2NyYXRjaAogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IHMxID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUodjEyLCBzdWJkaXZpc2lvblMxU2NyYXRjaCksCiAgICAgICAgICAgIHJhZGl1cywKICAgICAgICAgICAgc3ViZGl2aXNpb25TMVNjcmF0Y2gKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBzMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKHYyMiwgc3ViZGl2aXNpb25TMlNjcmF0Y2gpLAogICAgICAgICAgICByYWRpdXMsCiAgICAgICAgICAgIHN1YmRpdmlzaW9uUzJTY3JhdGNoCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgZzAgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlU3F1YXJlZCgKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHMwLCBzMSwgc3ViZGl2aXNpb25NaWRTY3JhdGNoKQogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IGcxID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZVNxdWFyZWQoCiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChzMSwgczIsIHN1YmRpdmlzaW9uTWlkU2NyYXRjaCkKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBnMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGVTcXVhcmVkKAogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoczIsIHMwLCBzdWJkaXZpc2lvbk1pZFNjcmF0Y2gpCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgbWF4MyA9IE1hdGgubWF4KGcwLCBnMSwgZzIpOwogICAgICAgICAgbGV0IGVkZ2U7CiAgICAgICAgICBsZXQgbWlkOwogICAgICAgICAgbGV0IG1pZFRleGNvb3JkOwogICAgICAgICAgaWYgKG1heDMgPiBtaW5EaXN0YW5jZVNxcmQpIHsKICAgICAgICAgICAgaWYgKGcwID09PSBtYXgzKSB7CiAgICAgICAgICAgICAgZWRnZSA9IGAke01hdGgubWluKGkwLCBpMSl9ICR7TWF0aC5tYXgoaTAsIGkxKX1gOwogICAgICAgICAgICAgIGkgPSBlZGdlc1tlZGdlXTsKICAgICAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpKSkgewogICAgICAgICAgICAgICAgbWlkID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZCh2MDIsIHYxMiwgc3ViZGl2aXNpb25NaWRTY3JhdGNoKTsKICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKG1pZCwgMC41LCBtaWQpOwogICAgICAgICAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9ucy5wdXNoKG1pZC54LCBtaWQueSwgbWlkLnopOwogICAgICAgICAgICAgICAgaSA9IHN1YmRpdmlkZWRQb3NpdGlvbnMubGVuZ3RoIC8gMyAtIDE7CiAgICAgICAgICAgICAgICBlZGdlc1tlZGdlXSA9IGk7CiAgICAgICAgICAgICAgICBpZiAoaGFzVGV4Y29vcmRzKSB7CiAgICAgICAgICAgICAgICAgIG1pZFRleGNvb3JkID0gQ2FydGVzaWFuMl9kZWZhdWx0LmFkZCh0MCwgdDEsIHN1YmRpdmlzaW9uVGV4Y29vcmRNaWRTY3JhdGNoKTsKICAgICAgICAgICAgICAgICAgQ2FydGVzaWFuMl9kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobWlkVGV4Y29vcmQsIDAuNSwgbWlkVGV4Y29vcmQpOwogICAgICAgICAgICAgICAgICBzdWJkaXZpZGVkVGV4Y29vcmRzLnB1c2gobWlkVGV4Y29vcmQueCwgbWlkVGV4Y29vcmQueSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRyaWFuZ2xlcy5wdXNoKGkwLCBpLCBpMik7CiAgICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2goaSwgaTEsIGkyKTsKICAgICAgICAgICAgfSBlbHNlIGlmIChnMSA9PT0gbWF4MykgewogICAgICAgICAgICAgIGVkZ2UgPSBgJHtNYXRoLm1pbihpMSwgaTIpfSAke01hdGgubWF4KGkxLCBpMil9YDsKICAgICAgICAgICAgICBpID0gZWRnZXNbZWRnZV07CiAgICAgICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaSkpIHsKICAgICAgICAgICAgICAgIG1pZCA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQodjEyLCB2MjIsIHN1YmRpdmlzaW9uTWlkU2NyYXRjaCk7CiAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihtaWQsIDAuNSwgbWlkKTsKICAgICAgICAgICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnMucHVzaChtaWQueCwgbWlkLnksIG1pZC56KTsKICAgICAgICAgICAgICAgIGkgPSBzdWJkaXZpZGVkUG9zaXRpb25zLmxlbmd0aCAvIDMgLSAxOwogICAgICAgICAgICAgICAgZWRnZXNbZWRnZV0gPSBpOwogICAgICAgICAgICAgICAgaWYgKGhhc1RleGNvb3JkcykgewogICAgICAgICAgICAgICAgICBtaWRUZXhjb29yZCA9IENhcnRlc2lhbjJfZGVmYXVsdC5hZGQodDEsIHQyLCBzdWJkaXZpc2lvblRleGNvb3JkTWlkU2NyYXRjaCk7CiAgICAgICAgICAgICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKG1pZFRleGNvb3JkLCAwLjUsIG1pZFRleGNvb3JkKTsKICAgICAgICAgICAgICAgICAgc3ViZGl2aWRlZFRleGNvb3Jkcy5wdXNoKG1pZFRleGNvb3JkLngsIG1pZFRleGNvb3JkLnkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0cmlhbmdsZXMucHVzaChpMSwgaSwgaTApOwogICAgICAgICAgICAgIHRyaWFuZ2xlcy5wdXNoKGksIGkyLCBpMCk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoZzIgPT09IG1heDMpIHsKICAgICAgICAgICAgICBlZGdlID0gYCR7TWF0aC5taW4oaTIsIGkwKX0gJHtNYXRoLm1heChpMiwgaTApfWA7CiAgICAgICAgICAgICAgaSA9IGVkZ2VzW2VkZ2VdOwogICAgICAgICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGkpKSB7CiAgICAgICAgICAgICAgICBtaWQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHYyMiwgdjAyLCBzdWJkaXZpc2lvbk1pZFNjcmF0Y2gpOwogICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobWlkLCAwLjUsIG1pZCk7CiAgICAgICAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zLnB1c2gobWlkLngsIG1pZC55LCBtaWQueik7CiAgICAgICAgICAgICAgICBpID0gc3ViZGl2aWRlZFBvc2l0aW9ucy5sZW5ndGggLyAzIC0gMTsKICAgICAgICAgICAgICAgIGVkZ2VzW2VkZ2VdID0gaTsKICAgICAgICAgICAgICAgIGlmIChoYXNUZXhjb29yZHMpIHsKICAgICAgICAgICAgICAgICAgbWlkVGV4Y29vcmQgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuYWRkKHQyLCB0MCwgc3ViZGl2aXNpb25UZXhjb29yZE1pZFNjcmF0Y2gpOwogICAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihtaWRUZXhjb29yZCwgMC41LCBtaWRUZXhjb29yZCk7CiAgICAgICAgICAgICAgICAgIHN1YmRpdmlkZWRUZXhjb29yZHMucHVzaChtaWRUZXhjb29yZC54LCBtaWRUZXhjb29yZC55KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2goaTIsIGksIGkxKTsKICAgICAgICAgICAgICB0cmlhbmdsZXMucHVzaChpLCBpMCwgaTEpOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdWJkaXZpZGVkSW5kaWNlcy5wdXNoKGkwKTsKICAgICAgICAgICAgc3ViZGl2aWRlZEluZGljZXMucHVzaChpMSk7CiAgICAgICAgICAgIHN1YmRpdmlkZWRJbmRpY2VzLnB1c2goaTIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBnZW9tZXRyeU9wdGlvbnMgPSB7CiAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgIHBvc2l0aW9uOiBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFLAogICAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICAgICAgdmFsdWVzOiBzdWJkaXZpZGVkUG9zaXRpb25zCiAgICAgICAgICAgIH0pCiAgICAgICAgICB9LAogICAgICAgICAgaW5kaWNlczogc3ViZGl2aWRlZEluZGljZXMsCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBQcmltaXRpdmVUeXBlX2RlZmF1bHQuVFJJQU5HTEVTCiAgICAgICAgfTsKICAgICAgICBpZiAoaGFzVGV4Y29vcmRzKSB7CiAgICAgICAgICBnZW9tZXRyeU9wdGlvbnMuYXR0cmlidXRlcy5zdCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDIsCiAgICAgICAgICAgIHZhbHVlczogc3ViZGl2aWRlZFRleGNvb3JkcwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgR2VvbWV0cnlfZGVmYXVsdChnZW9tZXRyeU9wdGlvbnMpOwogICAgICB9OwogICAgICBzdWJkaXZpc2lvbkMwU2NyYXRjaCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBzdWJkaXZpc2lvbkMxU2NyYXRjaCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBzdWJkaXZpc2lvbkMyU2NyYXRjaCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBzdWJkaXZpc2lvbkNhcnRvZ3JhcGhpY1NjcmF0Y2ggPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgUG9seWdvblBpcGVsaW5lLmNvbXB1dGVSaHVtYkxpbmVTdWJkaXZpc2lvbiA9IGZ1bmN0aW9uKGVsbGlwc29pZCwgcG9zaXRpb25zLCBpbmRpY2VzLCB0ZXhjb29yZHMsIGdyYW51bGFyaXR5KSB7CiAgICAgICAgZ3JhbnVsYXJpdHkgPSBncmFudWxhcml0eSA/PyBNYXRoX2RlZmF1bHQuUkFESUFOU19QRVJfREVHUkVFOwogICAgICAgIGNvbnN0IGhhc1RleGNvb3JkcyA9IGRlZmluZWRfZGVmYXVsdCh0ZXhjb29yZHMpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiZWxsaXBzb2lkIiwgZWxsaXBzb2lkKTsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInBvc2l0aW9ucyIsIHBvc2l0aW9ucyk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJpbmRpY2VzIiwgaW5kaWNlcyk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoImluZGljZXMubGVuZ3RoIiwgaW5kaWNlcy5sZW5ndGgsIDMpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5lcXVhbHMoImluZGljZXMubGVuZ3RoICUgMyIsICIwIiwgaW5kaWNlcy5sZW5ndGggJSAzLCAwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW4oImdyYW51bGFyaXR5IiwgZ3JhbnVsYXJpdHksIDApOwogICAgICAgIGNvbnN0IHRyaWFuZ2xlcyA9IGluZGljZXMuc2xpY2UoMCk7CiAgICAgICAgbGV0IGk7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBjb25zdCBzdWJkaXZpZGVkUG9zaXRpb25zID0gbmV3IEFycmF5KGxlbmd0aCAqIDMpOwogICAgICAgIGNvbnN0IHN1YmRpdmlkZWRUZXhjb29yZHMgPSBuZXcgQXJyYXkobGVuZ3RoICogMik7CiAgICAgICAgbGV0IHEgPSAwOwogICAgICAgIGxldCBwID0gMDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGNvbnN0IGl0ZW0gPSBwb3NpdGlvbnNbaV07CiAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zW3ErK10gPSBpdGVtLng7CiAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zW3ErK10gPSBpdGVtLnk7CiAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zW3ErK10gPSBpdGVtLno7CiAgICAgICAgICBpZiAoaGFzVGV4Y29vcmRzKSB7CiAgICAgICAgICAgIGNvbnN0IHRleGNvb3JkSXRlbSA9IHRleGNvb3Jkc1tpXTsKICAgICAgICAgICAgc3ViZGl2aWRlZFRleGNvb3Jkc1twKytdID0gdGV4Y29vcmRJdGVtLng7CiAgICAgICAgICAgIHN1YmRpdmlkZWRUZXhjb29yZHNbcCsrXSA9IHRleGNvb3JkSXRlbS55OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBzdWJkaXZpZGVkSW5kaWNlcyA9IFtdOwogICAgICAgIGNvbnN0IGVkZ2VzID0ge307CiAgICAgICAgY29uc3QgcmFkaXVzID0gZWxsaXBzb2lkLm1heGltdW1SYWRpdXM7CiAgICAgICAgY29uc3QgbWluRGlzdGFuY2UgPSBNYXRoX2RlZmF1bHQuY2hvcmRMZW5ndGgoZ3JhbnVsYXJpdHksIHJhZGl1cyk7CiAgICAgICAgY29uc3Qgcmh1bWIwID0gbmV3IEVsbGlwc29pZFJodW1iTGluZV9kZWZhdWx0KHZvaWQgMCwgdm9pZCAwLCBlbGxpcHNvaWQpOwogICAgICAgIGNvbnN0IHJodW1iMSA9IG5ldyBFbGxpcHNvaWRSaHVtYkxpbmVfZGVmYXVsdCh2b2lkIDAsIHZvaWQgMCwgZWxsaXBzb2lkKTsKICAgICAgICBjb25zdCByaHVtYjIgPSBuZXcgRWxsaXBzb2lkUmh1bWJMaW5lX2RlZmF1bHQodm9pZCAwLCB2b2lkIDAsIGVsbGlwc29pZCk7CiAgICAgICAgd2hpbGUgKHRyaWFuZ2xlcy5sZW5ndGggPiAwKSB7CiAgICAgICAgICBjb25zdCBpMiA9IHRyaWFuZ2xlcy5wb3AoKTsKICAgICAgICAgIGNvbnN0IGkxID0gdHJpYW5nbGVzLnBvcCgpOwogICAgICAgICAgY29uc3QgaTAgPSB0cmlhbmdsZXMucG9wKCk7CiAgICAgICAgICBjb25zdCB2MDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zLAogICAgICAgICAgICBpMCAqIDMsCiAgICAgICAgICAgIHN1YmRpdmlzaW9uVjBTY3JhdGNoCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgdjEyID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9ucywKICAgICAgICAgICAgaTEgKiAzLAogICAgICAgICAgICBzdWJkaXZpc2lvblYxU2NyYXRjaAogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IHYyMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnMsCiAgICAgICAgICAgIGkyICogMywKICAgICAgICAgICAgc3ViZGl2aXNpb25WMlNjcmF0Y2gKICAgICAgICAgICk7CiAgICAgICAgICBsZXQgdDAsIHQxLCB0MjsKICAgICAgICAgIGlmIChoYXNUZXhjb29yZHMpIHsKICAgICAgICAgICAgdDAgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgICAgIHN1YmRpdmlkZWRUZXhjb29yZHMsCiAgICAgICAgICAgICAgaTAgKiAyLAogICAgICAgICAgICAgIHN1YmRpdmlzaW9uVDBTY3JhdGNoCiAgICAgICAgICAgICk7CiAgICAgICAgICAgIHQxID0gQ2FydGVzaWFuMl9kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgICAgICBzdWJkaXZpZGVkVGV4Y29vcmRzLAogICAgICAgICAgICAgIGkxICogMiwKICAgICAgICAgICAgICBzdWJkaXZpc2lvblQxU2NyYXRjaAogICAgICAgICAgICApOwogICAgICAgICAgICB0MiA9IENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICAgICAgc3ViZGl2aWRlZFRleGNvb3JkcywKICAgICAgICAgICAgICBpMiAqIDIsCiAgICAgICAgICAgICAgc3ViZGl2aXNpb25UMlNjcmF0Y2gKICAgICAgICAgICAgKTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGMwID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKHYwMiwgc3ViZGl2aXNpb25DMFNjcmF0Y2gpOwogICAgICAgICAgY29uc3QgYzEgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWModjEyLCBzdWJkaXZpc2lvbkMxU2NyYXRjaCk7CiAgICAgICAgICBjb25zdCBjMiA9IGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyh2MjIsIHN1YmRpdmlzaW9uQzJTY3JhdGNoKTsKICAgICAgICAgIHJodW1iMC5zZXRFbmRQb2ludHMoYzAsIGMxKTsKICAgICAgICAgIGNvbnN0IGcwID0gcmh1bWIwLnN1cmZhY2VEaXN0YW5jZTsKICAgICAgICAgIHJodW1iMS5zZXRFbmRQb2ludHMoYzEsIGMyKTsKICAgICAgICAgIGNvbnN0IGcxID0gcmh1bWIxLnN1cmZhY2VEaXN0YW5jZTsKICAgICAgICAgIHJodW1iMi5zZXRFbmRQb2ludHMoYzIsIGMwKTsKICAgICAgICAgIGNvbnN0IGcyID0gcmh1bWIyLnN1cmZhY2VEaXN0YW5jZTsKICAgICAgICAgIGNvbnN0IG1heDMgPSBNYXRoLm1heChnMCwgZzEsIGcyKTsKICAgICAgICAgIGxldCBlZGdlOwogICAgICAgICAgbGV0IG1pZDsKICAgICAgICAgIGxldCBtaWRIZWlnaHQ7CiAgICAgICAgICBsZXQgbWlkQ2FydGVzaWFuMzsKICAgICAgICAgIGxldCBtaWRUZXhjb29yZDsKICAgICAgICAgIGlmIChtYXgzID4gbWluRGlzdGFuY2UpIHsKICAgICAgICAgICAgaWYgKGcwID09PSBtYXgzKSB7CiAgICAgICAgICAgICAgZWRnZSA9IGAke01hdGgubWluKGkwLCBpMSl9ICR7TWF0aC5tYXgoaTAsIGkxKX1gOwogICAgICAgICAgICAgIGkgPSBlZGdlc1tlZGdlXTsKICAgICAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpKSkgewogICAgICAgICAgICAgICAgbWlkID0gcmh1bWIwLmludGVycG9sYXRlVXNpbmdGcmFjdGlvbigKICAgICAgICAgICAgICAgICAgMC41LAogICAgICAgICAgICAgICAgICBzdWJkaXZpc2lvbkNhcnRvZ3JhcGhpY1NjcmF0Y2gKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICBtaWRIZWlnaHQgPSAoYzAuaGVpZ2h0ICsgYzEuaGVpZ2h0KSAqIDAuNTsKICAgICAgICAgICAgICAgIG1pZENhcnRlc2lhbjMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbVJhZGlhbnMoCiAgICAgICAgICAgICAgICAgIG1pZC5sb25naXR1ZGUsCiAgICAgICAgICAgICAgICAgIG1pZC5sYXRpdHVkZSwKICAgICAgICAgICAgICAgICAgbWlkSGVpZ2h0LAogICAgICAgICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgICAgICAgIHN1YmRpdmlzaW9uTWlkU2NyYXRjaAogICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnMucHVzaCgKICAgICAgICAgICAgICAgICAgbWlkQ2FydGVzaWFuMy54LAogICAgICAgICAgICAgICAgICBtaWRDYXJ0ZXNpYW4zLnksCiAgICAgICAgICAgICAgICAgIG1pZENhcnRlc2lhbjMuegogICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgIGkgPSBzdWJkaXZpZGVkUG9zaXRpb25zLmxlbmd0aCAvIDMgLSAxOwogICAgICAgICAgICAgICAgZWRnZXNbZWRnZV0gPSBpOwogICAgICAgICAgICAgICAgaWYgKGhhc1RleGNvb3JkcykgewogICAgICAgICAgICAgICAgICBtaWRUZXhjb29yZCA9IENhcnRlc2lhbjJfZGVmYXVsdC5hZGQodDAsIHQxLCBzdWJkaXZpc2lvblRleGNvb3JkTWlkU2NyYXRjaCk7CiAgICAgICAgICAgICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKG1pZFRleGNvb3JkLCAwLjUsIG1pZFRleGNvb3JkKTsKICAgICAgICAgICAgICAgICAgc3ViZGl2aWRlZFRleGNvb3Jkcy5wdXNoKG1pZFRleGNvb3JkLngsIG1pZFRleGNvb3JkLnkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0cmlhbmdsZXMucHVzaChpMCwgaSwgaTIpOwogICAgICAgICAgICAgIHRyaWFuZ2xlcy5wdXNoKGksIGkxLCBpMik7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoZzEgPT09IG1heDMpIHsKICAgICAgICAgICAgICBlZGdlID0gYCR7TWF0aC5taW4oaTEsIGkyKX0gJHtNYXRoLm1heChpMSwgaTIpfWA7CiAgICAgICAgICAgICAgaSA9IGVkZ2VzW2VkZ2VdOwogICAgICAgICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGkpKSB7CiAgICAgICAgICAgICAgICBtaWQgPSByaHVtYjEuaW50ZXJwb2xhdGVVc2luZ0ZyYWN0aW9uKAogICAgICAgICAgICAgICAgICAwLjUsCiAgICAgICAgICAgICAgICAgIHN1YmRpdmlzaW9uQ2FydG9ncmFwaGljU2NyYXRjaAogICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgIG1pZEhlaWdodCA9IChjMS5oZWlnaHQgKyBjMi5oZWlnaHQpICogMC41OwogICAgICAgICAgICAgICAgbWlkQ2FydGVzaWFuMyA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tUmFkaWFucygKICAgICAgICAgICAgICAgICAgbWlkLmxvbmdpdHVkZSwKICAgICAgICAgICAgICAgICAgbWlkLmxhdGl0dWRlLAogICAgICAgICAgICAgICAgICBtaWRIZWlnaHQsCiAgICAgICAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgICAgICAgc3ViZGl2aXNpb25NaWRTY3JhdGNoCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9ucy5wdXNoKAogICAgICAgICAgICAgICAgICBtaWRDYXJ0ZXNpYW4zLngsCiAgICAgICAgICAgICAgICAgIG1pZENhcnRlc2lhbjMueSwKICAgICAgICAgICAgICAgICAgbWlkQ2FydGVzaWFuMy56CiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgaSA9IHN1YmRpdmlkZWRQb3NpdGlvbnMubGVuZ3RoIC8gMyAtIDE7CiAgICAgICAgICAgICAgICBlZGdlc1tlZGdlXSA9IGk7CiAgICAgICAgICAgICAgICBpZiAoaGFzVGV4Y29vcmRzKSB7CiAgICAgICAgICAgICAgICAgIG1pZFRleGNvb3JkID0gQ2FydGVzaWFuMl9kZWZhdWx0LmFkZCh0MSwgdDIsIHN1YmRpdmlzaW9uVGV4Y29vcmRNaWRTY3JhdGNoKTsKICAgICAgICAgICAgICAgICAgQ2FydGVzaWFuMl9kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobWlkVGV4Y29vcmQsIDAuNSwgbWlkVGV4Y29vcmQpOwogICAgICAgICAgICAgICAgICBzdWJkaXZpZGVkVGV4Y29vcmRzLnB1c2gobWlkVGV4Y29vcmQueCwgbWlkVGV4Y29vcmQueSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRyaWFuZ2xlcy5wdXNoKGkxLCBpLCBpMCk7CiAgICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2goaSwgaTIsIGkwKTsKICAgICAgICAgICAgfSBlbHNlIGlmIChnMiA9PT0gbWF4MykgewogICAgICAgICAgICAgIGVkZ2UgPSBgJHtNYXRoLm1pbihpMiwgaTApfSAke01hdGgubWF4KGkyLCBpMCl9YDsKICAgICAgICAgICAgICBpID0gZWRnZXNbZWRnZV07CiAgICAgICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaSkpIHsKICAgICAgICAgICAgICAgIG1pZCA9IHJodW1iMi5pbnRlcnBvbGF0ZVVzaW5nRnJhY3Rpb24oCiAgICAgICAgICAgICAgICAgIDAuNSwKICAgICAgICAgICAgICAgICAgc3ViZGl2aXNpb25DYXJ0b2dyYXBoaWNTY3JhdGNoCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgbWlkSGVpZ2h0ID0gKGMyLmhlaWdodCArIGMwLmhlaWdodCkgKiAwLjU7CiAgICAgICAgICAgICAgICBtaWRDYXJ0ZXNpYW4zID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21SYWRpYW5zKAogICAgICAgICAgICAgICAgICBtaWQubG9uZ2l0dWRlLAogICAgICAgICAgICAgICAgICBtaWQubGF0aXR1ZGUsCiAgICAgICAgICAgICAgICAgIG1pZEhlaWdodCwKICAgICAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgICAgICBzdWJkaXZpc2lvbk1pZFNjcmF0Y2gKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zLnB1c2goCiAgICAgICAgICAgICAgICAgIG1pZENhcnRlc2lhbjMueCwKICAgICAgICAgICAgICAgICAgbWlkQ2FydGVzaWFuMy55LAogICAgICAgICAgICAgICAgICBtaWRDYXJ0ZXNpYW4zLnoKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICBpID0gc3ViZGl2aWRlZFBvc2l0aW9ucy5sZW5ndGggLyAzIC0gMTsKICAgICAgICAgICAgICAgIGVkZ2VzW2VkZ2VdID0gaTsKICAgICAgICAgICAgICAgIGlmIChoYXNUZXhjb29yZHMpIHsKICAgICAgICAgICAgICAgICAgbWlkVGV4Y29vcmQgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuYWRkKHQyLCB0MCwgc3ViZGl2aXNpb25UZXhjb29yZE1pZFNjcmF0Y2gpOwogICAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihtaWRUZXhjb29yZCwgMC41LCBtaWRUZXhjb29yZCk7CiAgICAgICAgICAgICAgICAgIHN1YmRpdmlkZWRUZXhjb29yZHMucHVzaChtaWRUZXhjb29yZC54LCBtaWRUZXhjb29yZC55KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2goaTIsIGksIGkxKTsKICAgICAgICAgICAgICB0cmlhbmdsZXMucHVzaChpLCBpMCwgaTEpOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdWJkaXZpZGVkSW5kaWNlcy5wdXNoKGkwKTsKICAgICAgICAgICAgc3ViZGl2aWRlZEluZGljZXMucHVzaChpMSk7CiAgICAgICAgICAgIHN1YmRpdmlkZWRJbmRpY2VzLnB1c2goaTIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBnZW9tZXRyeU9wdGlvbnMgPSB7CiAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgIHBvc2l0aW9uOiBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFLAogICAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICAgICAgdmFsdWVzOiBzdWJkaXZpZGVkUG9zaXRpb25zCiAgICAgICAgICAgIH0pCiAgICAgICAgICB9LAogICAgICAgICAgaW5kaWNlczogc3ViZGl2aWRlZEluZGljZXMsCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBQcmltaXRpdmVUeXBlX2RlZmF1bHQuVFJJQU5HTEVTCiAgICAgICAgfTsKICAgICAgICBpZiAoaGFzVGV4Y29vcmRzKSB7CiAgICAgICAgICBnZW9tZXRyeU9wdGlvbnMuYXR0cmlidXRlcy5zdCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDIsCiAgICAgICAgICAgIHZhbHVlczogc3ViZGl2aWRlZFRleGNvb3JkcwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgR2VvbWV0cnlfZGVmYXVsdChnZW9tZXRyeU9wdGlvbnMpOwogICAgICB9OwogICAgICBQb2x5Z29uUGlwZWxpbmUuc2NhbGVUb0dlb2RldGljSGVpZ2h0ID0gZnVuY3Rpb24ocG9zaXRpb25zLCBoZWlnaHQsIGVsbGlwc29pZCwgc2NhbGVUb1N1cmZhY2U0KSB7CiAgICAgICAgZWxsaXBzb2lkID0gZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICAgICAgbGV0IG4gPSBzY2FsZVRvR2VvZGV0aWNIZWlnaHROOwogICAgICAgIGxldCBwID0gc2NhbGVUb0dlb2RldGljSGVpZ2h0UDsKICAgICAgICBoZWlnaHQgPSBoZWlnaHQgPz8gMDsKICAgICAgICBzY2FsZVRvU3VyZmFjZTQgPSBzY2FsZVRvU3VyZmFjZTQgPz8gdHJ1ZTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHBvc2l0aW9ucykpIHsKICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAzKSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkocG9zaXRpb25zLCBpLCBwKTsKICAgICAgICAgICAgaWYgKHNjYWxlVG9TdXJmYWNlNCkgewogICAgICAgICAgICAgIHAgPSBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZShwLCBwKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoaGVpZ2h0ICE9PSAwKSB7CiAgICAgICAgICAgICAgbiA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwocCwgbik7CiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobiwgaGVpZ2h0LCBuKTsKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHAsIG4sIHApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHBvc2l0aW9uc1tpXSA9IHAueDsKICAgICAgICAgICAgcG9zaXRpb25zW2kgKyAxXSA9IHAueTsKICAgICAgICAgICAgcG9zaXRpb25zW2kgKyAyXSA9IHAuejsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHBvc2l0aW9uczsKICAgICAgfTsKICAgICAgUG9seWdvblBpcGVsaW5lX2RlZmF1bHQgPSBQb2x5Z29uUGlwZWxpbmU7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9RdWV1ZS5qcwogIGZ1bmN0aW9uIFF1ZXVlKCkgewogICAgdGhpcy5fYXJyYXkgPSBbXTsKICAgIHRoaXMuX29mZnNldCA9IDA7CiAgICB0aGlzLl9sZW5ndGggPSAwOwogIH0KICB2YXIgUXVldWVfZGVmYXVsdDsKICB2YXIgaW5pdF9RdWV1ZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUXVldWUuanMiKCkgewogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhRdWV1ZS5wcm90b3R5cGUsIHsKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgbGVuZ3RoIG9mIHRoZSBxdWV1ZS4KICAgICAgICAgKgogICAgICAgICAqIEBtZW1iZXJvZiBRdWV1ZS5wcm90b3R5cGUKICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgbGVuZ3RoOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fbGVuZ3RoOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIFF1ZXVlLnByb3RvdHlwZS5lbnF1ZXVlID0gZnVuY3Rpb24oaXRlbSkgewogICAgICAgIHRoaXMuX2FycmF5LnB1c2goaXRlbSk7CiAgICAgICAgdGhpcy5fbGVuZ3RoKys7CiAgICAgIH07CiAgICAgIFF1ZXVlLnByb3RvdHlwZS5kZXF1ZXVlID0gZnVuY3Rpb24oKSB7CiAgICAgICAgaWYgKHRoaXMuX2xlbmd0aCA9PT0gMCkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgY29uc3QgYXJyYXkgPSB0aGlzLl9hcnJheTsKICAgICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5fb2Zmc2V0OwogICAgICAgIGNvbnN0IGl0ZW0gPSBhcnJheVtvZmZzZXRdOwogICAgICAgIGFycmF5W29mZnNldF0gPSB2b2lkIDA7CiAgICAgICAgb2Zmc2V0Kys7CiAgICAgICAgaWYgKG9mZnNldCA+IDEwICYmIG9mZnNldCAqIDIgPiBhcnJheS5sZW5ndGgpIHsKICAgICAgICAgIHRoaXMuX2FycmF5ID0gYXJyYXkuc2xpY2Uob2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCA9IDA7CiAgICAgICAgfQogICAgICAgIHRoaXMuX29mZnNldCA9IG9mZnNldDsKICAgICAgICB0aGlzLl9sZW5ndGgtLTsKICAgICAgICByZXR1cm4gaXRlbTsKICAgICAgfTsKICAgICAgUXVldWUucHJvdG90eXBlLnBlZWsgPSBmdW5jdGlvbigpIHsKICAgICAgICBpZiAodGhpcy5fbGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpcy5fYXJyYXlbdGhpcy5fb2Zmc2V0XTsKICAgICAgfTsKICAgICAgUXVldWUucHJvdG90eXBlLmNvbnRhaW5zID0gZnVuY3Rpb24oaXRlbSkgewogICAgICAgIHJldHVybiB0aGlzLl9hcnJheS5pbmRleE9mKGl0ZW0pICE9PSAtMTsKICAgICAgfTsKICAgICAgUXVldWUucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24oKSB7CiAgICAgICAgdGhpcy5fYXJyYXkubGVuZ3RoID0gdGhpcy5fb2Zmc2V0ID0gdGhpcy5fbGVuZ3RoID0gMDsKICAgICAgfTsKICAgICAgUXVldWUucHJvdG90eXBlLnNvcnQgPSBmdW5jdGlvbihjb21wYXJlRnVuY3Rpb24pIHsKICAgICAgICBpZiAodGhpcy5fb2Zmc2V0ID4gMCkgewogICAgICAgICAgdGhpcy5fYXJyYXkgPSB0aGlzLl9hcnJheS5zbGljZSh0aGlzLl9vZmZzZXQpOwogICAgICAgICAgdGhpcy5fb2Zmc2V0ID0gMDsKICAgICAgICB9CiAgICAgICAgdGhpcy5fYXJyYXkuc29ydChjb21wYXJlRnVuY3Rpb24pOwogICAgICB9OwogICAgICBRdWV1ZV9kZWZhdWx0ID0gUXVldWU7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Qb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LmpzCiAgZnVuY3Rpb24gZ2V0UG9pbnRBdERpc3RhbmNlMkQocDAsIHAxLCBkaXN0YW5jZSwgbGVuZ3RoKSB7CiAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQuc3VidHJhY3QocDEsIHAwLCBkaXN0YW5jZTJEU2NyYXRjaCk7CiAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgZGlzdGFuY2UyRFNjcmF0Y2gsCiAgICAgIGRpc3RhbmNlIC8gbGVuZ3RoLAogICAgICBkaXN0YW5jZTJEU2NyYXRjaAogICAgKTsKICAgIENhcnRlc2lhbjJfZGVmYXVsdC5hZGQocDAsIGRpc3RhbmNlMkRTY3JhdGNoLCBkaXN0YW5jZTJEU2NyYXRjaCk7CiAgICByZXR1cm4gW2Rpc3RhbmNlMkRTY3JhdGNoLngsIGRpc3RhbmNlMkRTY3JhdGNoLnldOwogIH0KICBmdW5jdGlvbiBnZXRQb2ludEF0RGlzdGFuY2UocDAsIHAxLCBkaXN0YW5jZSwgbGVuZ3RoKSB7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QocDEsIHAwLCBkaXN0YW5jZVNjcmF0Y2g0KTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICBkaXN0YW5jZVNjcmF0Y2g0LAogICAgICBkaXN0YW5jZSAvIGxlbmd0aCwKICAgICAgZGlzdGFuY2VTY3JhdGNoNAogICAgKTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocDAsIGRpc3RhbmNlU2NyYXRjaDQsIGRpc3RhbmNlU2NyYXRjaDQpOwogICAgcmV0dXJuIFtkaXN0YW5jZVNjcmF0Y2g0LngsIGRpc3RhbmNlU2NyYXRjaDQueSwgZGlzdGFuY2VTY3JhdGNoNC56XTsKICB9CiAgZnVuY3Rpb24gY29tcHV0ZUVxdWF0b3JJbnRlcnNlY3Rpb25SaHVtYihzdGFydCwgZW5kLCBlbGxpcHNvaWQpIHsKICAgIGNvbnN0IGMwID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKHN0YXJ0LCBzY3JhdGNoQ2FydG9ncmFwaGljMCk7CiAgICBjb25zdCBjMSA9IGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyhlbmQsIHNjcmF0Y2hDYXJ0b2dyYXBoaWMxKTsKICAgIGlmIChNYXRoLnNpZ24oYzAubGF0aXR1ZGUpID09PSBNYXRoLnNpZ24oYzEubGF0aXR1ZGUpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHNjcmF0Y2hSaHVtYkxpbmUuc2V0RW5kUG9pbnRzKGMwLCBjMSk7CiAgICBjb25zdCBpbnRlcnNlY3Rpb24gPSBzY3JhdGNoUmh1bWJMaW5lLmZpbmRJbnRlcnNlY3Rpb25XaXRoTGF0aXR1ZGUoCiAgICAgIDAsCiAgICAgIHNjcmF0Y2hSaHVtYkludGVyc2VjdGlvbgogICAgKTsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGludGVyc2VjdGlvbikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IG1pbkxvbmdpdHVkZSA9IE1hdGgubWluKGMwLmxvbmdpdHVkZSwgYzEubG9uZ2l0dWRlKTsKICAgIGxldCBtYXhMb25naXR1ZGUgPSBNYXRoLm1heChjMC5sb25naXR1ZGUsIGMxLmxvbmdpdHVkZSk7CiAgICBpZiAoTWF0aC5hYnMobWF4TG9uZ2l0dWRlIC0gbWluTG9uZ2l0dWRlKSA+IE1hdGhfZGVmYXVsdC5QSSkgewogICAgICBjb25zdCBzd2FwMiA9IG1pbkxvbmdpdHVkZTsKICAgICAgbWluTG9uZ2l0dWRlID0gbWF4TG9uZ2l0dWRlOwogICAgICBtYXhMb25naXR1ZGUgPSBzd2FwMjsKICAgIH0KICAgIGlmIChpbnRlcnNlY3Rpb24ubG9uZ2l0dWRlIDwgbWluTG9uZ2l0dWRlIHx8IGludGVyc2VjdGlvbi5sb25naXR1ZGUgPiBtYXhMb25naXR1ZGUpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgcmV0dXJuIGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbihpbnRlcnNlY3Rpb24pOwogIH0KICBmdW5jdGlvbiBjb21wdXRlRXF1YXRvckludGVyc2VjdGlvbihzdGFydCwgZW5kLCBlbGxpcHNvaWQsIGFyY1R5cGUpIHsKICAgIGlmIChhcmNUeXBlID09PSBBcmNUeXBlX2RlZmF1bHQuUkhVTUIpIHsKICAgICAgcmV0dXJuIGNvbXB1dGVFcXVhdG9ySW50ZXJzZWN0aW9uUmh1bWIoc3RhcnQsIGVuZCwgZWxsaXBzb2lkKTsKICAgIH0KICAgIGNvbnN0IGludGVyc2VjdGlvbiA9IEludGVyc2VjdGlvblRlc3RzX2RlZmF1bHQubGluZVNlZ21lbnRQbGFuZSgKICAgICAgc3RhcnQsCiAgICAgIGVuZCwKICAgICAgUGxhbmVfZGVmYXVsdC5PUklHSU5fWFlfUExBTkUKICAgICk7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpbnRlcnNlY3Rpb24pKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHJldHVybiBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZShpbnRlcnNlY3Rpb24sIGludGVyc2VjdGlvbik7CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVFZGdlc09uUGxhbmUocG9zaXRpb25zLCBlbGxpcHNvaWQsIGFyY1R5cGUpIHsKICAgIGNvbnN0IGVkZ2VzT25QbGFuZSA9IFtdOwogICAgbGV0IHN0YXJ0UG9pbnQsIGVuZFBvaW50LCB0eXBlLCBuZXh0LCBpbnRlcnNlY3Rpb24sIGkgPSAwOwogICAgd2hpbGUgKGkgPCBwb3NpdGlvbnMubGVuZ3RoKSB7CiAgICAgIHN0YXJ0UG9pbnQgPSBwb3NpdGlvbnNbaV07CiAgICAgIGVuZFBvaW50ID0gcG9zaXRpb25zWyhpICsgMSkgJSBwb3NpdGlvbnMubGVuZ3RoXTsKICAgICAgdHlwZSA9IE1hdGhfZGVmYXVsdC5zaWduKHN0YXJ0UG9pbnQueik7CiAgICAgIG5leHQgPSBNYXRoX2RlZmF1bHQuc2lnbihlbmRQb2ludC56KTsKICAgICAgY29uc3QgZ2V0TG9uZ2l0dWRlID0gKHBvc2l0aW9uKSA9PiB7CiAgICAgICAgY29uc3QgY2FydG9ncmFwaGljMiA9IGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYygKICAgICAgICAgIHBvc2l0aW9uLAogICAgICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzMKICAgICAgICApOwogICAgICAgIHJldHVybiBjYXJ0b2dyYXBoaWMyLmxvbmdpdHVkZTsKICAgICAgfTsKICAgICAgaWYgKHR5cGUgPT09IDApIHsKICAgICAgICBlZGdlc09uUGxhbmUucHVzaCh7CiAgICAgICAgICBwb3NpdGlvbjogaSwKICAgICAgICAgIHR5cGUsCiAgICAgICAgICB2aXNpdGVkOiBmYWxzZSwKICAgICAgICAgIG5leHQsCiAgICAgICAgICB0aGV0YTogZ2V0TG9uZ2l0dWRlKHN0YXJ0UG9pbnQpCiAgICAgICAgfSk7CiAgICAgIH0gZWxzZSBpZiAobmV4dCAhPT0gMCkgewogICAgICAgIGludGVyc2VjdGlvbiA9IGNvbXB1dGVFcXVhdG9ySW50ZXJzZWN0aW9uKAogICAgICAgICAgc3RhcnRQb2ludCwKICAgICAgICAgIGVuZFBvaW50LAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgYXJjVHlwZQogICAgICAgICk7CiAgICAgICAgKytpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGludGVyc2VjdGlvbikpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBwb3NpdGlvbnMuc3BsaWNlKGksIDAsIGludGVyc2VjdGlvbik7CiAgICAgICAgZWRnZXNPblBsYW5lLnB1c2goewogICAgICAgICAgcG9zaXRpb246IGksCiAgICAgICAgICB0eXBlLAogICAgICAgICAgdmlzaXRlZDogZmFsc2UsCiAgICAgICAgICBuZXh0LAogICAgICAgICAgdGhldGE6IGdldExvbmdpdHVkZShpbnRlcnNlY3Rpb24pCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgKytpOwogICAgfQogICAgcmV0dXJuIGVkZ2VzT25QbGFuZTsKICB9CiAgZnVuY3Rpb24gd2lyZVBvbHlnb24ocG9seWdvbnMsIHBvbHlnb25JbmRleCwgcG9zaXRpb25zLCBlZGdlc09uUGxhbmUsIHRvRGVsZXRlLCBzdGFydEluZGV4LCBhYm92ZVBsYW5lKSB7CiAgICBjb25zdCBwb2x5Z29uMiA9IFtdOwogICAgbGV0IGkgPSBzdGFydEluZGV4OwogICAgY29uc3QgZ2V0TWF0Y2hpbmdFZGdlID0gKGkyKSA9PiAoZWRnZSkgPT4gZWRnZS5wb3NpdGlvbiA9PT0gaTI7CiAgICBjb25zdCBwb2x5Z29uc1RvV2lyZSA9IFtdOwogICAgZG8gewogICAgICBjb25zdCBwb3NpdGlvbiA9IHBvc2l0aW9uc1tpXTsKICAgICAgcG9seWdvbjIucHVzaChwb3NpdGlvbik7CiAgICAgIGNvbnN0IGVkZ2VJbmRleCA9IGVkZ2VzT25QbGFuZS5maW5kSW5kZXgoZ2V0TWF0Y2hpbmdFZGdlKGkpKTsKICAgICAgY29uc3QgZWRnZSA9IGVkZ2VzT25QbGFuZVtlZGdlSW5kZXhdOwogICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChlZGdlKSkgewogICAgICAgICsraTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB7IHZpc2l0ZWQ6IGhhc0JlZW5WaXNpdGVkLCB0eXBlLCBuZXh0IH0gPSBlZGdlOwogICAgICBlZGdlLnZpc2l0ZWQgPSB0cnVlOwogICAgICBpZiAodHlwZSA9PT0gMCkgewogICAgICAgIGlmIChuZXh0ID09PSAwKSB7CiAgICAgICAgICBjb25zdCBwcmV2aW91c0VkZ2UgPSBlZGdlc09uUGxhbmVbZWRnZUluZGV4IC0gKGFib3ZlUGxhbmUgPyAxIDogLTEpXTsKICAgICAgICAgIGlmIChwcmV2aW91c0VkZ2U/LnBvc2l0aW9uID09PSBpICsgMSkgewogICAgICAgICAgICBwcmV2aW91c0VkZ2UudmlzaXRlZCA9IHRydWU7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICArK2k7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoIWhhc0JlZW5WaXNpdGVkICYmIGFib3ZlUGxhbmUgJiYgbmV4dCA+IDAgfHwgc3RhcnRJbmRleCA9PT0gaSAmJiAhYWJvdmVQbGFuZSAmJiBuZXh0IDwgMCkgewogICAgICAgICAgKytpOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIGNvbnN0IGZvbGxvd0VkZ2UgPSBhYm92ZVBsYW5lID8gdHlwZSA+PSAwIDogdHlwZSA8PSAwOwogICAgICBpZiAoIWZvbGxvd0VkZ2UpIHsKICAgICAgICArK2k7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKCFoYXNCZWVuVmlzaXRlZCkgewogICAgICAgIHBvbHlnb25zVG9XaXJlLnB1c2goaSk7CiAgICAgIH0KICAgICAgY29uc3QgbmV4dEVkZ2VJbmRleCA9IGVkZ2VJbmRleCArIChhYm92ZVBsYW5lID8gMSA6IC0xKTsKICAgICAgY29uc3QgbmV4dEVkZ2UgPSBlZGdlc09uUGxhbmVbbmV4dEVkZ2VJbmRleF07CiAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG5leHRFZGdlKSkgewogICAgICAgICsraTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpID0gbmV4dEVkZ2UucG9zaXRpb247CiAgICB9IHdoaWxlIChpIDwgcG9zaXRpb25zLmxlbmd0aCAmJiBpID49IDAgJiYgaSAhPT0gc3RhcnRJbmRleCAmJiBwb2x5Z29uMi5sZW5ndGggPCBwb3NpdGlvbnMubGVuZ3RoKTsKICAgIHBvbHlnb25zLnNwbGljZShwb2x5Z29uSW5kZXgsIHRvRGVsZXRlLCBwb2x5Z29uMik7CiAgICBmb3IgKGNvbnN0IGluZGV4IG9mIHBvbHlnb25zVG9XaXJlKSB7CiAgICAgIHBvbHlnb25JbmRleCA9IHdpcmVQb2x5Z29uKAogICAgICAgIHBvbHlnb25zLAogICAgICAgICsrcG9seWdvbkluZGV4LAogICAgICAgIHBvc2l0aW9ucywKICAgICAgICBlZGdlc09uUGxhbmUsCiAgICAgICAgMCwKICAgICAgICBpbmRleCwKICAgICAgICAhYWJvdmVQbGFuZQogICAgICApOwogICAgfQogICAgcmV0dXJuIHBvbHlnb25JbmRleDsKICB9CiAgdmFyIFBvbHlnb25HZW9tZXRyeUxpYnJhcnksIGRpc3RhbmNlMkRTY3JhdGNoLCBkaXN0YW5jZVNjcmF0Y2g0LCBzY3JhdGNoQ2FydG9ncmFwaGljMCwgc2NyYXRjaENhcnRvZ3JhcGhpYzEsIHNjcmF0Y2hDYXJ0b2dyYXBoaWMyMiwgc2NyYXRjaENhcnRlc2lhbjAsIHNjcmF0Y2hSaHVtYkxpbmUsIHNjYWxlVG9HZW9kZXRpY0hlaWdodE4xLCBzY2FsZVRvR2VvZGV0aWNIZWlnaHROMiwgc2NhbGVUb0dlb2RldGljSGVpZ2h0UDEsIHNjYWxlVG9HZW9kZXRpY0hlaWdodFAyLCBzY3JhdGNoUmh1bWJJbnRlcnNlY3Rpb24sIHNjcmF0Y2hDYXJ0b2dyYXBoaWMzLCBjb21wdXRlQm91bmRpbmdSZWN0YW5nbGVDYXJ0ZXNpYW4yLCBjb21wdXRlQm91bmRpbmdSZWN0YW5nbGVDYXJ0ZXNpYW4zLCBjb21wdXRlQm91bmRpbmdSZWN0YW5nbGVRdWF0ZXJuaW9uLCBjb21wdXRlQm91bmRpbmdSZWN0YW5nbGVNYXRyaXgzLCBjb21wdXRlV2FsbFRleGNvb3Jkc1N1YmRpdmlkZWQsIGNvbXB1dGVXYWxsSW5kaWNlc1N1YmRpdmlkZWQsIHAxU2NyYXRjaDIsIHAyU2NyYXRjaDIsIFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdDsKICB2YXIgaW5pdF9Qb2x5Z29uR2VvbWV0cnlMaWJyYXJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Qb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LmpzIigpIHsKICAgICAgaW5pdF9BcmNUeXBlKCk7CiAgICAgIGluaXRfYXJyYXlSZW1vdmVEdXBsaWNhdGVzKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMigpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DYXJ0b2dyYXBoaWMoKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWRSaHVtYkxpbmUoKTsKICAgICAgaW5pdF9HZW9tZXRyeSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGVzKCk7CiAgICAgIGluaXRfR2VvbWV0cnlQaXBlbGluZSgpOwogICAgICBpbml0X0luZGV4RGF0YXR5cGUoKTsKICAgICAgaW5pdF9JbnRlcnNlY3Rpb25UZXN0cygpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9NYXRyaXgzKCk7CiAgICAgIGluaXRfUGxhbmUoKTsKICAgICAgaW5pdF9Qb2x5Z29uSGllcmFyY2h5KCk7CiAgICAgIGluaXRfUG9seWdvblBpcGVsaW5lKCk7CiAgICAgIGluaXRfUHJpbWl0aXZlVHlwZSgpOwogICAgICBpbml0X1F1YXRlcm5pb24oKTsKICAgICAgaW5pdF9RdWV1ZSgpOwogICAgICBpbml0X1dpbmRpbmdPcmRlcigpOwogICAgICBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5ID0ge307CiAgICAgIFBvbHlnb25HZW9tZXRyeUxpYnJhcnkuY29tcHV0ZUhpZXJhcmNoeVBhY2tlZExlbmd0aCA9IGZ1bmN0aW9uKHBvbHlnb25IaWVyYXJjaHksIENhcnRlc2lhblgpIHsKICAgICAgICBsZXQgbnVtQ29tcG9uZW50cyA9IDA7CiAgICAgICAgY29uc3Qgc3RhY2sgPSBbcG9seWdvbkhpZXJhcmNoeV07CiAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgIGNvbnN0IGhpZXJhcmNoeSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaGllcmFyY2h5KSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIG51bUNvbXBvbmVudHMgKz0gMjsKICAgICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IGhpZXJhcmNoeS5wb3NpdGlvbnM7CiAgICAgICAgICBjb25zdCBob2xlcyA9IGhpZXJhcmNoeS5ob2xlczsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocG9zaXRpb25zKSAmJiBwb3NpdGlvbnMubGVuZ3RoID4gMCkgewogICAgICAgICAgICBudW1Db21wb25lbnRzICs9IHBvc2l0aW9ucy5sZW5ndGggKiBDYXJ0ZXNpYW5YLnBhY2tlZExlbmd0aDsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaG9sZXMpKSB7CiAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IGhvbGVzLmxlbmd0aDsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgICAgIHN0YWNrLnB1c2goaG9sZXNbaV0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBudW1Db21wb25lbnRzOwogICAgICB9OwogICAgICBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnBhY2tQb2x5Z29uSGllcmFyY2h5ID0gZnVuY3Rpb24ocG9seWdvbkhpZXJhcmNoeSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgsIENhcnRlc2lhblgpIHsKICAgICAgICBjb25zdCBzdGFjayA9IFtwb2x5Z29uSGllcmFyY2h5XTsKICAgICAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgY29uc3QgaGllcmFyY2h5ID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChoaWVyYXJjaHkpKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgcG9zaXRpb25zID0gaGllcmFyY2h5LnBvc2l0aW9uczsKICAgICAgICAgIGNvbnN0IGhvbGVzID0gaGllcmFyY2h5LmhvbGVzOwogICAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IGRlZmluZWRfZGVmYXVsdChwb3NpdGlvbnMpID8gcG9zaXRpb25zLmxlbmd0aCA6IDA7CiAgICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gZGVmaW5lZF9kZWZhdWx0KGhvbGVzKSA/IGhvbGVzLmxlbmd0aCA6IDA7CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHBvc2l0aW9ucykpIHsKICAgICAgICAgICAgY29uc3QgcG9zaXRpb25zTGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb3NpdGlvbnNMZW5ndGg7ICsraSwgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW5YLnBhY2tlZExlbmd0aCkgewogICAgICAgICAgICAgIENhcnRlc2lhblgucGFjayhwb3NpdGlvbnNbaV0sIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChob2xlcykpIHsKICAgICAgICAgICAgY29uc3QgaG9sZXNMZW5ndGggPSBob2xlcy5sZW5ndGg7CiAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgaG9sZXNMZW5ndGg7ICsraikgewogICAgICAgICAgICAgIHN0YWNrLnB1c2goaG9sZXNbal0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBzdGFydGluZ0luZGV4OwogICAgICB9OwogICAgICBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnVucGFja1BvbHlnb25IaWVyYXJjaHkgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgQ2FydGVzaWFuWCkgewogICAgICAgIGNvbnN0IHBvc2l0aW9uc0xlbmd0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgaG9sZXNMZW5ndGggPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IG5ldyBBcnJheShwb3NpdGlvbnNMZW5ndGgpOwogICAgICAgIGNvbnN0IGhvbGVzID0gaG9sZXNMZW5ndGggPiAwID8gbmV3IEFycmF5KGhvbGVzTGVuZ3RoKSA6IHZvaWQgMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBvc2l0aW9uc0xlbmd0aDsgKytpLCBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhblgucGFja2VkTGVuZ3RoKSB7CiAgICAgICAgICBwb3NpdGlvbnNbaV0gPSBDYXJ0ZXNpYW5YLnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgaG9sZXNMZW5ndGg7ICsraikgewogICAgICAgICAgaG9sZXNbal0gPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnVucGFja1BvbHlnb25IaWVyYXJjaHkoCiAgICAgICAgICAgIGFycmF5LAogICAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgICBDYXJ0ZXNpYW5YCiAgICAgICAgICApOwogICAgICAgICAgc3RhcnRpbmdJbmRleCA9IGhvbGVzW2pdLnN0YXJ0aW5nSW5kZXg7CiAgICAgICAgICBkZWxldGUgaG9sZXNbal0uc3RhcnRpbmdJbmRleDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgIGhvbGVzLAogICAgICAgICAgc3RhcnRpbmdJbmRleAogICAgICAgIH07CiAgICAgIH07CiAgICAgIGRpc3RhbmNlMkRTY3JhdGNoID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBkaXN0YW5jZVNjcmF0Y2g0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnN1YmRpdmlkZUxpbmVDb3VudCA9IGZ1bmN0aW9uKHAwLCBwMSwgbWluRGlzdGFuY2UpIHsKICAgICAgICBjb25zdCBkaXN0YW5jZSA9IENhcnRlc2lhbjNfZGVmYXVsdC5kaXN0YW5jZShwMCwgcDEpOwogICAgICAgIGNvbnN0IG4gPSBkaXN0YW5jZSAvIG1pbkRpc3RhbmNlOwogICAgICAgIGNvbnN0IGNvdW50RGl2aWRlID0gTWF0aC5tYXgoMCwgTWF0aC5jZWlsKE1hdGhfZGVmYXVsdC5sb2cyKG4pKSk7CiAgICAgICAgcmV0dXJuIE1hdGgucG93KDIsIGNvdW50RGl2aWRlKTsKICAgICAgfTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzAgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzEgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzIyID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4wID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUmh1bWJMaW5lID0gbmV3IEVsbGlwc29pZFJodW1iTGluZV9kZWZhdWx0KCk7CiAgICAgIFBvbHlnb25HZW9tZXRyeUxpYnJhcnkuc3ViZGl2aWRlUmh1bWJMaW5lQ291bnQgPSBmdW5jdGlvbihlbGxpcHNvaWQsIHAwLCBwMSwgbWluRGlzdGFuY2UpIHsKICAgICAgICBjb25zdCBjMCA9IGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyhwMCwgc2NyYXRjaENhcnRvZ3JhcGhpYzApOwogICAgICAgIGNvbnN0IGMxID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKHAxLCBzY3JhdGNoQ2FydG9ncmFwaGljMSk7CiAgICAgICAgY29uc3Qgcmh1bWIgPSBuZXcgRWxsaXBzb2lkUmh1bWJMaW5lX2RlZmF1bHQoYzAsIGMxLCBlbGxpcHNvaWQpOwogICAgICAgIGNvbnN0IG4gPSByaHVtYi5zdXJmYWNlRGlzdGFuY2UgLyBtaW5EaXN0YW5jZTsKICAgICAgICBjb25zdCBjb3VudERpdmlkZSA9IE1hdGgubWF4KDAsIE1hdGguY2VpbChNYXRoX2RlZmF1bHQubG9nMihuKSkpOwogICAgICAgIHJldHVybiBNYXRoLnBvdygyLCBjb3VudERpdmlkZSk7CiAgICAgIH07CiAgICAgIFBvbHlnb25HZW9tZXRyeUxpYnJhcnkuc3ViZGl2aWRlVGV4Y29vcmRMaW5lID0gZnVuY3Rpb24odDAsIHQxLCBwMCwgcDEsIG1pbkRpc3RhbmNlLCByZXN1bHQpIHsKICAgICAgICBjb25zdCBzdWJkaXZpc2lvbnMgPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnN1YmRpdmlkZUxpbmVDb3VudCgKICAgICAgICAgIHAwLAogICAgICAgICAgcDEsCiAgICAgICAgICBtaW5EaXN0YW5jZQogICAgICAgICk7CiAgICAgICAgY29uc3QgbGVuZ3RoMkQgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuZGlzdGFuY2UodDAsIHQxKTsKICAgICAgICBjb25zdCBkaXN0YW5jZUJldHdlZW5Db29yZHMgPSBsZW5ndGgyRCAvIHN1YmRpdmlzaW9uczsKICAgICAgICBjb25zdCB0ZXhjb29yZHMgPSByZXN1bHQ7CiAgICAgICAgdGV4Y29vcmRzLmxlbmd0aCA9IHN1YmRpdmlzaW9ucyAqIDI7CiAgICAgICAgbGV0IGluZGV4ID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHN1YmRpdmlzaW9uczsgaSsrKSB7CiAgICAgICAgICBjb25zdCB0ID0gZ2V0UG9pbnRBdERpc3RhbmNlMkQodDAsIHQxLCBpICogZGlzdGFuY2VCZXR3ZWVuQ29vcmRzLCBsZW5ndGgyRCk7CiAgICAgICAgICB0ZXhjb29yZHNbaW5kZXgrK10gPSB0WzBdOwogICAgICAgICAgdGV4Y29vcmRzW2luZGV4KytdID0gdFsxXTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRleGNvb3JkczsKICAgICAgfTsKICAgICAgUG9seWdvbkdlb21ldHJ5TGlicmFyeS5zdWJkaXZpZGVMaW5lID0gZnVuY3Rpb24ocDAsIHAxLCBtaW5EaXN0YW5jZSwgcmVzdWx0KSB7CiAgICAgICAgY29uc3QgbnVtVmVydGljZXMgPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnN1YmRpdmlkZUxpbmVDb3VudCgKICAgICAgICAgIHAwLAogICAgICAgICAgcDEsCiAgICAgICAgICBtaW5EaXN0YW5jZQogICAgICAgICk7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gQ2FydGVzaWFuM19kZWZhdWx0LmRpc3RhbmNlKHAwLCBwMSk7CiAgICAgICAgY29uc3QgZGlzdGFuY2VCZXR3ZWVuVmVydGljZXMgPSBsZW5ndGggLyBudW1WZXJ0aWNlczsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBbXTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gcmVzdWx0OwogICAgICAgIHBvc2l0aW9ucy5sZW5ndGggPSBudW1WZXJ0aWNlcyAqIDM7CiAgICAgICAgbGV0IGluZGV4ID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bVZlcnRpY2VzOyBpKyspIHsKICAgICAgICAgIGNvbnN0IHAgPSBnZXRQb2ludEF0RGlzdGFuY2UocDAsIHAxLCBpICogZGlzdGFuY2VCZXR3ZWVuVmVydGljZXMsIGxlbmd0aCk7CiAgICAgICAgICBwb3NpdGlvbnNbaW5kZXgrK10gPSBwWzBdOwogICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gcFsxXTsKICAgICAgICAgIHBvc2l0aW9uc1tpbmRleCsrXSA9IHBbMl07CiAgICAgICAgfQogICAgICAgIHJldHVybiBwb3NpdGlvbnM7CiAgICAgIH07CiAgICAgIFBvbHlnb25HZW9tZXRyeUxpYnJhcnkuc3ViZGl2aWRlVGV4Y29vcmRSaHVtYkxpbmUgPSBmdW5jdGlvbih0MCwgdDEsIGVsbGlwc29pZCwgcDAsIHAxLCBtaW5EaXN0YW5jZSwgcmVzdWx0KSB7CiAgICAgICAgY29uc3QgYzAgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMocDAsIHNjcmF0Y2hDYXJ0b2dyYXBoaWMwKTsKICAgICAgICBjb25zdCBjMSA9IGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyhwMSwgc2NyYXRjaENhcnRvZ3JhcGhpYzEpOwogICAgICAgIHNjcmF0Y2hSaHVtYkxpbmUuc2V0RW5kUG9pbnRzKGMwLCBjMSk7CiAgICAgICAgY29uc3QgbiA9IHNjcmF0Y2hSaHVtYkxpbmUuc3VyZmFjZURpc3RhbmNlIC8gbWluRGlzdGFuY2U7CiAgICAgICAgY29uc3QgY291bnREaXZpZGUgPSBNYXRoLm1heCgwLCBNYXRoLmNlaWwoTWF0aF9kZWZhdWx0LmxvZzIobikpKTsKICAgICAgICBjb25zdCBzdWJkaXZpc2lvbnMgPSBNYXRoLnBvdygyLCBjb3VudERpdmlkZSk7CiAgICAgICAgY29uc3QgbGVuZ3RoMkQgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuZGlzdGFuY2UodDAsIHQxKTsKICAgICAgICBjb25zdCBkaXN0YW5jZUJldHdlZW5Db29yZHMgPSBsZW5ndGgyRCAvIHN1YmRpdmlzaW9uczsKICAgICAgICBjb25zdCB0ZXhjb29yZHMgPSByZXN1bHQ7CiAgICAgICAgdGV4Y29vcmRzLmxlbmd0aCA9IHN1YmRpdmlzaW9ucyAqIDI7CiAgICAgICAgbGV0IGluZGV4ID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHN1YmRpdmlzaW9uczsgaSsrKSB7CiAgICAgICAgICBjb25zdCB0ID0gZ2V0UG9pbnRBdERpc3RhbmNlMkQodDAsIHQxLCBpICogZGlzdGFuY2VCZXR3ZWVuQ29vcmRzLCBsZW5ndGgyRCk7CiAgICAgICAgICB0ZXhjb29yZHNbaW5kZXgrK10gPSB0WzBdOwogICAgICAgICAgdGV4Y29vcmRzW2luZGV4KytdID0gdFsxXTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRleGNvb3JkczsKICAgICAgfTsKICAgICAgUG9seWdvbkdlb21ldHJ5TGlicmFyeS5zdWJkaXZpZGVSaHVtYkxpbmUgPSBmdW5jdGlvbihlbGxpcHNvaWQsIHAwLCBwMSwgbWluRGlzdGFuY2UsIHJlc3VsdCkgewogICAgICAgIGNvbnN0IGMwID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKHAwLCBzY3JhdGNoQ2FydG9ncmFwaGljMCk7CiAgICAgICAgY29uc3QgYzEgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMocDEsIHNjcmF0Y2hDYXJ0b2dyYXBoaWMxKTsKICAgICAgICBjb25zdCByaHVtYiA9IG5ldyBFbGxpcHNvaWRSaHVtYkxpbmVfZGVmYXVsdChjMCwgYzEsIGVsbGlwc29pZCk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gW107CiAgICAgICAgfQogICAgICAgIGlmIChyaHVtYi5zdXJmYWNlRGlzdGFuY2UgPD0gbWluRGlzdGFuY2UpIHsKICAgICAgICAgIHJlc3VsdC5sZW5ndGggPSAzOwogICAgICAgICAgcmVzdWx0WzBdID0gcDAueDsKICAgICAgICAgIHJlc3VsdFsxXSA9IHAwLnk7CiAgICAgICAgICByZXN1bHRbMl0gPSBwMC56OwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgY29uc3QgbiA9IHJodW1iLnN1cmZhY2VEaXN0YW5jZSAvIG1pbkRpc3RhbmNlOwogICAgICAgIGNvbnN0IGNvdW50RGl2aWRlID0gTWF0aC5tYXgoMCwgTWF0aC5jZWlsKE1hdGhfZGVmYXVsdC5sb2cyKG4pKSk7CiAgICAgICAgY29uc3QgbnVtVmVydGljZXMgPSBNYXRoLnBvdygyLCBjb3VudERpdmlkZSk7CiAgICAgICAgY29uc3QgZGlzdGFuY2VCZXR3ZWVuVmVydGljZXMgPSByaHVtYi5zdXJmYWNlRGlzdGFuY2UgLyBudW1WZXJ0aWNlczsKICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSByZXN1bHQ7CiAgICAgICAgcG9zaXRpb25zLmxlbmd0aCA9IG51bVZlcnRpY2VzICogMzsKICAgICAgICBsZXQgaW5kZXggPSAwOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtVmVydGljZXM7IGkrKykgewogICAgICAgICAgY29uc3QgYyA9IHJodW1iLmludGVycG9sYXRlVXNpbmdTdXJmYWNlRGlzdGFuY2UoCiAgICAgICAgICAgIGkgKiBkaXN0YW5jZUJldHdlZW5WZXJ0aWNlcywKICAgICAgICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzIyCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgcCA9IGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbihjLCBzY3JhdGNoQ2FydGVzaWFuMCk7CiAgICAgICAgICBwb3NpdGlvbnNbaW5kZXgrK10gPSBwLng7CiAgICAgICAgICBwb3NpdGlvbnNbaW5kZXgrK10gPSBwLnk7CiAgICAgICAgICBwb3NpdGlvbnNbaW5kZXgrK10gPSBwLno7CiAgICAgICAgfQogICAgICAgIHJldHVybiBwb3NpdGlvbnM7CiAgICAgIH07CiAgICAgIHNjYWxlVG9HZW9kZXRpY0hlaWdodE4xID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY2FsZVRvR2VvZGV0aWNIZWlnaHROMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NhbGVUb0dlb2RldGljSGVpZ2h0UDEgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjYWxlVG9HZW9kZXRpY0hlaWdodFAyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnNjYWxlVG9HZW9kZXRpY0hlaWdodEV4dHJ1ZGVkID0gZnVuY3Rpb24oZ2VvbWV0cnksIG1heEhlaWdodCwgbWluSGVpZ2h0LCBlbGxpcHNvaWQsIHBlclBvc2l0aW9uSGVpZ2h0KSB7CiAgICAgICAgZWxsaXBzb2lkID0gZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICAgICAgY29uc3QgbjEgPSBzY2FsZVRvR2VvZGV0aWNIZWlnaHROMTsKICAgICAgICBsZXQgbjIgPSBzY2FsZVRvR2VvZGV0aWNIZWlnaHROMjsKICAgICAgICBjb25zdCBwID0gc2NhbGVUb0dlb2RldGljSGVpZ2h0UDE7CiAgICAgICAgbGV0IHAyID0gc2NhbGVUb0dlb2RldGljSGVpZ2h0UDI7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChnZW9tZXRyeSkgJiYgZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5LmF0dHJpYnV0ZXMpICYmIGRlZmluZWRfZGVmYXVsdChnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uKSkgewogICAgICAgICAgY29uc3QgcG9zaXRpb25zID0gZ2VvbWV0cnkuYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXM7CiAgICAgICAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoIC8gMjsKICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHsKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIGksIHApOwogICAgICAgICAgICBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKHAsIG4xKTsKICAgICAgICAgICAgcDIgPSBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZShwLCBwMik7CiAgICAgICAgICAgIG4yID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobjEsIG1pbkhlaWdodCwgbjIpOwogICAgICAgICAgICBuMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocDIsIG4yLCBuMik7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpICsgbGVuZ3RoXSA9IG4yLng7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpICsgMSArIGxlbmd0aF0gPSBuMi55OwogICAgICAgICAgICBwb3NpdGlvbnNbaSArIDIgKyBsZW5ndGhdID0gbjIuejsKICAgICAgICAgICAgaWYgKHBlclBvc2l0aW9uSGVpZ2h0KSB7CiAgICAgICAgICAgICAgcDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocCwgcDIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG4yID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobjEsIG1heEhlaWdodCwgbjIpOwogICAgICAgICAgICBuMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocDIsIG4yLCBuMik7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpXSA9IG4yLng7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpICsgMV0gPSBuMi55OwogICAgICAgICAgICBwb3NpdGlvbnNbaSArIDJdID0gbjIuejsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGdlb21ldHJ5OwogICAgICB9OwogICAgICBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnBvbHlnb25PdXRsaW5lc0Zyb21IaWVyYXJjaHkgPSBmdW5jdGlvbihwb2x5Z29uSGllcmFyY2h5LCBzY2FsZVRvRWxsaXBzb2lkU3VyZmFjZSwgZWxsaXBzb2lkKSB7CiAgICAgICAgY29uc3QgcG9seWdvbnMgPSBbXTsKICAgICAgICBjb25zdCBxdWV1ZSA9IG5ldyBRdWV1ZV9kZWZhdWx0KCk7CiAgICAgICAgcXVldWUuZW5xdWV1ZShwb2x5Z29uSGllcmFyY2h5KTsKICAgICAgICBsZXQgaTsKICAgICAgICBsZXQgajsKICAgICAgICBsZXQgbGVuZ3RoOwogICAgICAgIHdoaWxlIChxdWV1ZS5sZW5ndGggIT09IDApIHsKICAgICAgICAgIGNvbnN0IG91dGVyTm9kZSA9IHF1ZXVlLmRlcXVldWUoKTsKICAgICAgICAgIGxldCBvdXRlclJpbmcgPSBvdXRlck5vZGUucG9zaXRpb25zOwogICAgICAgICAgaWYgKHNjYWxlVG9FbGxpcHNvaWRTdXJmYWNlKSB7CiAgICAgICAgICAgIGxlbmd0aCA9IG91dGVyUmluZy5sZW5ndGg7CiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICAgIGVsbGlwc29pZC5zY2FsZVRvR2VvZGV0aWNTdXJmYWNlKG91dGVyUmluZ1tpXSwgb3V0ZXJSaW5nW2ldKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgb3V0ZXJSaW5nID0gYXJyYXlSZW1vdmVEdXBsaWNhdGVzX2RlZmF1bHQoCiAgICAgICAgICAgIG91dGVyUmluZywKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFsc0Vwc2lsb24sCiAgICAgICAgICAgIHRydWUKICAgICAgICAgICk7CiAgICAgICAgICBpZiAob3V0ZXJSaW5nLmxlbmd0aCA8IDMpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBudW1DaGlsZHJlbiA9IG91dGVyTm9kZS5ob2xlcyA/IG91dGVyTm9kZS5ob2xlcy5sZW5ndGggOiAwOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8IG51bUNoaWxkcmVuOyBpKyspIHsKICAgICAgICAgICAgY29uc3QgaG9sZSA9IG91dGVyTm9kZS5ob2xlc1tpXTsKICAgICAgICAgICAgbGV0IGhvbGVQb3NpdGlvbnMgPSBob2xlLnBvc2l0aW9uczsKICAgICAgICAgICAgaWYgKHNjYWxlVG9FbGxpcHNvaWRTdXJmYWNlKSB7CiAgICAgICAgICAgICAgbGVuZ3RoID0gaG9sZVBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGxlbmd0aDsgKytqKSB7CiAgICAgICAgICAgICAgICBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZShob2xlUG9zaXRpb25zW2pdLCBob2xlUG9zaXRpb25zW2pdKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaG9sZVBvc2l0aW9ucyA9IGFycmF5UmVtb3ZlRHVwbGljYXRlc19kZWZhdWx0KAogICAgICAgICAgICAgIGhvbGVQb3NpdGlvbnMsCiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFsc0Vwc2lsb24sCiAgICAgICAgICAgICAgdHJ1ZQogICAgICAgICAgICApOwogICAgICAgICAgICBpZiAoaG9sZVBvc2l0aW9ucy5sZW5ndGggPCAzKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcG9seWdvbnMucHVzaChob2xlUG9zaXRpb25zKTsKICAgICAgICAgICAgbGV0IG51bUdyYW5kY2hpbGRyZW4gPSAwOwogICAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGhvbGUuaG9sZXMpKSB7CiAgICAgICAgICAgICAgbnVtR3JhbmRjaGlsZHJlbiA9IGhvbGUuaG9sZXMubGVuZ3RoOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBudW1HcmFuZGNoaWxkcmVuOyBqKyspIHsKICAgICAgICAgICAgICBxdWV1ZS5lbnF1ZXVlKGhvbGUuaG9sZXNbal0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBwb2x5Z29ucy5wdXNoKG91dGVyUmluZyk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBwb2x5Z29uczsKICAgICAgfTsKICAgICAgc2NyYXRjaFJodW1iSW50ZXJzZWN0aW9uID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWMzID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIFBvbHlnb25HZW9tZXRyeUxpYnJhcnkuc3BsaXRQb2x5Z29uc09uRXF1YXRvciA9IGZ1bmN0aW9uKG91dGVyUmluZ3MsIGVsbGlwc29pZCwgYXJjVHlwZSwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gW107CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5zcGxpY2UoMCwgMCwgLi4ub3V0ZXJSaW5ncyk7CiAgICAgICAgcmVzdWx0Lmxlbmd0aCA9IG91dGVyUmluZ3MubGVuZ3RoOwogICAgICAgIGxldCBjdXJyZW50UG9seWdvbiA9IDA7CiAgICAgICAgd2hpbGUgKGN1cnJlbnRQb2x5Z29uIDwgcmVzdWx0Lmxlbmd0aCkgewogICAgICAgICAgY29uc3Qgb3V0ZXJSaW5nID0gcmVzdWx0W2N1cnJlbnRQb2x5Z29uXTsKICAgICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IG91dGVyUmluZy5zbGljZSgpOwogICAgICAgICAgaWYgKG91dGVyUmluZy5sZW5ndGggPCAzKSB7CiAgICAgICAgICAgIHJlc3VsdFtjdXJyZW50UG9seWdvbl0gPSBwb3NpdGlvbnM7CiAgICAgICAgICAgICsrY3VycmVudFBvbHlnb247CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgZWRnZXNPblBsYW5lID0gY29tcHV0ZUVkZ2VzT25QbGFuZShwb3NpdGlvbnMsIGVsbGlwc29pZCwgYXJjVHlwZSk7CiAgICAgICAgICBpZiAocG9zaXRpb25zLmxlbmd0aCA9PT0gb3V0ZXJSaW5nLmxlbmd0aCB8fCBlZGdlc09uUGxhbmUubGVuZ3RoIDw9IDEpIHsKICAgICAgICAgICAgcmVzdWx0W2N1cnJlbnRQb2x5Z29uXSA9IHBvc2l0aW9uczsKICAgICAgICAgICAgKytjdXJyZW50UG9seWdvbjsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBlZGdlc09uUGxhbmUuc29ydCgoYTMsIGIpID0+IHsKICAgICAgICAgICAgcmV0dXJuIGEzLnRoZXRhIC0gYi50aGV0YTsKICAgICAgICAgIH0pOwogICAgICAgICAgY29uc3Qgbm9ydGggPSBwb3NpdGlvbnNbMF0ueiA+PSAwOwogICAgICAgICAgY3VycmVudFBvbHlnb24gPSB3aXJlUG9seWdvbigKICAgICAgICAgICAgcmVzdWx0LAogICAgICAgICAgICBjdXJyZW50UG9seWdvbiwKICAgICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgICBlZGdlc09uUGxhbmUsCiAgICAgICAgICAgIDEsCiAgICAgICAgICAgIDAsCiAgICAgICAgICAgIG5vcnRoCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnBvbHlnb25zRnJvbUhpZXJhcmNoeSA9IGZ1bmN0aW9uKHBvbHlnb25IaWVyYXJjaHksIGtlZXBEdXBsaWNhdGVzLCBwcm9qZWN0UG9pbnRzVG8yRCwgc2NhbGVUb0VsbGlwc29pZFN1cmZhY2UsIGVsbGlwc29pZCwgc3BsaXRQb2x5Z29ucykgewogICAgICAgIGNvbnN0IGhpZXJhcmNoeSA9IFtdOwogICAgICAgIGNvbnN0IHBvbHlnb25zID0gW107CiAgICAgICAgY29uc3QgcXVldWUgPSBuZXcgUXVldWVfZGVmYXVsdCgpOwogICAgICAgIHF1ZXVlLmVucXVldWUocG9seWdvbkhpZXJhcmNoeSk7CiAgICAgICAgbGV0IHNwbGl0ID0gZGVmaW5lZF9kZWZhdWx0KHNwbGl0UG9seWdvbnMpOwogICAgICAgIHdoaWxlIChxdWV1ZS5sZW5ndGggIT09IDApIHsKICAgICAgICAgIGNvbnN0IG91dGVyTm9kZSA9IHF1ZXVlLmRlcXVldWUoKTsKICAgICAgICAgIGxldCBvdXRlclJpbmcgPSBvdXRlck5vZGUucG9zaXRpb25zOwogICAgICAgICAgY29uc3QgaG9sZXMgPSBvdXRlck5vZGUuaG9sZXM7CiAgICAgICAgICBsZXQgaTsKICAgICAgICAgIGxldCBsZW5ndGg7CiAgICAgICAgICBpZiAoc2NhbGVUb0VsbGlwc29pZFN1cmZhY2UpIHsKICAgICAgICAgICAgbGVuZ3RoID0gb3V0ZXJSaW5nLmxlbmd0aDsKICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgZWxsaXBzb2lkLnNjYWxlVG9HZW9kZXRpY1N1cmZhY2Uob3V0ZXJSaW5nW2ldLCBvdXRlclJpbmdbaV0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIWtlZXBEdXBsaWNhdGVzKSB7CiAgICAgICAgICAgIG91dGVyUmluZyA9IGFycmF5UmVtb3ZlRHVwbGljYXRlc19kZWZhdWx0KAogICAgICAgICAgICAgIG91dGVyUmluZywKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbiwKICAgICAgICAgICAgICB0cnVlCiAgICAgICAgICAgICk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAob3V0ZXJSaW5nLmxlbmd0aCA8IDMpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBsZXQgcG9zaXRpb25zMkQgPSBwcm9qZWN0UG9pbnRzVG8yRChvdXRlclJpbmcpOwogICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocG9zaXRpb25zMkQpKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgaG9sZUluZGljZXMgPSBbXTsKICAgICAgICAgIGxldCBvcmlnaW5hbFdpbmRpbmdPcmRlciA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LmNvbXB1dGVXaW5kaW5nT3JkZXIyRChwb3NpdGlvbnMyRCk7CiAgICAgICAgICBpZiAob3JpZ2luYWxXaW5kaW5nT3JkZXIgPT09IFdpbmRpbmdPcmRlcl9kZWZhdWx0LkNMT0NLV0lTRSkgewogICAgICAgICAgICBwb3NpdGlvbnMyRC5yZXZlcnNlKCk7CiAgICAgICAgICAgIG91dGVyUmluZyA9IG91dGVyUmluZy5zbGljZSgpLnJldmVyc2UoKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChzcGxpdCkgewogICAgICAgICAgICBzcGxpdCA9IGZhbHNlOwogICAgICAgICAgICBsZXQgcG9seWdvbnMyID0gW291dGVyUmluZ107CiAgICAgICAgICAgIHBvbHlnb25zMiA9IHNwbGl0UG9seWdvbnMocG9seWdvbnMyLCBwb2x5Z29uczIpOwogICAgICAgICAgICBpZiAocG9seWdvbnMyLmxlbmd0aCA+IDEpIHsKICAgICAgICAgICAgICBmb3IgKGNvbnN0IHBvc2l0aW9uczIgb2YgcG9seWdvbnMyKSB7CiAgICAgICAgICAgICAgICBxdWV1ZS5lbnF1ZXVlKG5ldyBQb2x5Z29uSGllcmFyY2h5X2RlZmF1bHQocG9zaXRpb25zMiwgaG9sZXMpKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGxldCBwb3NpdGlvbnMgPSBvdXRlclJpbmcuc2xpY2UoKTsKICAgICAgICAgIGNvbnN0IG51bUNoaWxkcmVuID0gZGVmaW5lZF9kZWZhdWx0KGhvbGVzKSA/IGhvbGVzLmxlbmd0aCA6IDA7CiAgICAgICAgICBjb25zdCBwb2x5Z29uSG9sZXMgPSBbXTsKICAgICAgICAgIGxldCBqOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8IG51bUNoaWxkcmVuOyBpKyspIHsKICAgICAgICAgICAgY29uc3QgaG9sZSA9IGhvbGVzW2ldOwogICAgICAgICAgICBsZXQgaG9sZVBvc2l0aW9ucyA9IGhvbGUucG9zaXRpb25zOwogICAgICAgICAgICBpZiAoc2NhbGVUb0VsbGlwc29pZFN1cmZhY2UpIHsKICAgICAgICAgICAgICBsZW5ndGggPSBob2xlUG9zaXRpb25zLmxlbmd0aDsKICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbGVuZ3RoOyArK2opIHsKICAgICAgICAgICAgICAgIGVsbGlwc29pZC5zY2FsZVRvR2VvZGV0aWNTdXJmYWNlKGhvbGVQb3NpdGlvbnNbal0sIGhvbGVQb3NpdGlvbnNbal0pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoIWtlZXBEdXBsaWNhdGVzKSB7CiAgICAgICAgICAgICAgaG9sZVBvc2l0aW9ucyA9IGFycmF5UmVtb3ZlRHVwbGljYXRlc19kZWZhdWx0KAogICAgICAgICAgICAgICAgaG9sZVBvc2l0aW9ucywKICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uLAogICAgICAgICAgICAgICAgdHJ1ZQogICAgICAgICAgICAgICk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGhvbGVQb3NpdGlvbnMubGVuZ3RoIDwgMykgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGhvbGVQb3NpdGlvbnMyRCA9IHByb2plY3RQb2ludHNUbzJEKGhvbGVQb3NpdGlvbnMpOwogICAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChob2xlUG9zaXRpb25zMkQpKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb3JpZ2luYWxXaW5kaW5nT3JkZXIgPSBQb2x5Z29uUGlwZWxpbmVfZGVmYXVsdC5jb21wdXRlV2luZGluZ09yZGVyMkQoaG9sZVBvc2l0aW9uczJEKTsKICAgICAgICAgICAgaWYgKG9yaWdpbmFsV2luZGluZ09yZGVyID09PSBXaW5kaW5nT3JkZXJfZGVmYXVsdC5DTE9DS1dJU0UpIHsKICAgICAgICAgICAgICBob2xlUG9zaXRpb25zMkQucmV2ZXJzZSgpOwogICAgICAgICAgICAgIGhvbGVQb3NpdGlvbnMgPSBob2xlUG9zaXRpb25zLnNsaWNlKCkucmV2ZXJzZSgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHBvbHlnb25Ib2xlcy5wdXNoKGhvbGVQb3NpdGlvbnMpOwogICAgICAgICAgICBob2xlSW5kaWNlcy5wdXNoKHBvc2l0aW9ucy5sZW5ndGgpOwogICAgICAgICAgICBwb3NpdGlvbnMgPSBwb3NpdGlvbnMuY29uY2F0KGhvbGVQb3NpdGlvbnMpOwogICAgICAgICAgICBwb3NpdGlvbnMyRCA9IHBvc2l0aW9uczJELmNvbmNhdChob2xlUG9zaXRpb25zMkQpOwogICAgICAgICAgICBsZXQgbnVtR3JhbmRjaGlsZHJlbiA9IDA7CiAgICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaG9sZS5ob2xlcykpIHsKICAgICAgICAgICAgICBudW1HcmFuZGNoaWxkcmVuID0gaG9sZS5ob2xlcy5sZW5ndGg7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IG51bUdyYW5kY2hpbGRyZW47IGorKykgewogICAgICAgICAgICAgIHF1ZXVlLmVucXVldWUoaG9sZS5ob2xlc1tqXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGhpZXJhcmNoeS5wdXNoKHsKICAgICAgICAgICAgb3V0ZXJSaW5nLAogICAgICAgICAgICBob2xlczogcG9seWdvbkhvbGVzCiAgICAgICAgICB9KTsKICAgICAgICAgIHBvbHlnb25zLnB1c2goewogICAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICAgIHBvc2l0aW9uczJELAogICAgICAgICAgICBob2xlczogaG9sZUluZGljZXMKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICByZXR1cm4gewogICAgICAgICAgaGllcmFyY2h5LAogICAgICAgICAgcG9seWdvbnMKICAgICAgICB9OwogICAgICB9OwogICAgICBjb21wdXRlQm91bmRpbmdSZWN0YW5nbGVDYXJ0ZXNpYW4yID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBjb21wdXRlQm91bmRpbmdSZWN0YW5nbGVDYXJ0ZXNpYW4zID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBjb21wdXRlQm91bmRpbmdSZWN0YW5nbGVRdWF0ZXJuaW9uID0gbmV3IFF1YXRlcm5pb25fZGVmYXVsdCgpOwogICAgICBjb21wdXRlQm91bmRpbmdSZWN0YW5nbGVNYXRyaXgzID0gbmV3IE1hdHJpeDNfZGVmYXVsdCgpOwogICAgICBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LmNvbXB1dGVCb3VuZGluZ1JlY3RhbmdsZSA9IGZ1bmN0aW9uKHBsYW5lTm9ybWFsLCBwcm9qZWN0UG9pbnRUbzJELCBwb3NpdGlvbnMsIGFuZ2xlLCByZXN1bHQpIHsKICAgICAgICBjb25zdCByb3RhdGlvbiA9IFF1YXRlcm5pb25fZGVmYXVsdC5mcm9tQXhpc0FuZ2xlKAogICAgICAgICAgcGxhbmVOb3JtYWwsCiAgICAgICAgICBhbmdsZSwKICAgICAgICAgIGNvbXB1dGVCb3VuZGluZ1JlY3RhbmdsZVF1YXRlcm5pb24KICAgICAgICApOwogICAgICAgIGNvbnN0IHRleHR1cmVNYXRyaXggPSBNYXRyaXgzX2RlZmF1bHQuZnJvbVF1YXRlcm5pb24oCiAgICAgICAgICByb3RhdGlvbiwKICAgICAgICAgIGNvbXB1dGVCb3VuZGluZ1JlY3RhbmdsZU1hdHJpeDMKICAgICAgICApOwogICAgICAgIGxldCBtaW5YID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgICAgIGxldCBtYXhYID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZOwogICAgICAgIGxldCBtaW5ZID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgICAgIGxldCBtYXhZID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgY29uc3QgcCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZSgKICAgICAgICAgICAgcG9zaXRpb25zW2ldLAogICAgICAgICAgICBjb21wdXRlQm91bmRpbmdSZWN0YW5nbGVDYXJ0ZXNpYW4zCiAgICAgICAgICApOwogICAgICAgICAgTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3IodGV4dHVyZU1hdHJpeCwgcCwgcCk7CiAgICAgICAgICBjb25zdCBzdCA9IHByb2plY3RQb2ludFRvMkQocCwgY29tcHV0ZUJvdW5kaW5nUmVjdGFuZ2xlQ2FydGVzaWFuMik7CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHN0KSkgewogICAgICAgICAgICBtaW5YID0gTWF0aC5taW4obWluWCwgc3QueCk7CiAgICAgICAgICAgIG1heFggPSBNYXRoLm1heChtYXhYLCBzdC54KTsKICAgICAgICAgICAgbWluWSA9IE1hdGgubWluKG1pblksIHN0LnkpOwogICAgICAgICAgICBtYXhZID0gTWF0aC5tYXgobWF4WSwgc3QueSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJlc3VsdC54ID0gbWluWDsKICAgICAgICByZXN1bHQueSA9IG1pblk7CiAgICAgICAgcmVzdWx0LndpZHRoID0gbWF4WCAtIG1pblg7CiAgICAgICAgcmVzdWx0LmhlaWdodCA9IG1heFkgLSBtaW5ZOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFBvbHlnb25HZW9tZXRyeUxpYnJhcnkuY3JlYXRlR2VvbWV0cnlGcm9tUG9zaXRpb25zID0gZnVuY3Rpb24oZWxsaXBzb2lkLCBwb2x5Z29uMiwgdGV4dHVyZUNvb3JkaW5hdGVzLCBncmFudWxhcml0eSwgcGVyUG9zaXRpb25IZWlnaHQsIHZlcnRleEZvcm1hdCwgYXJjVHlwZSkgewogICAgICAgIGxldCBpbmRpY2VzID0gUG9seWdvblBpcGVsaW5lX2RlZmF1bHQudHJpYW5ndWxhdGUocG9seWdvbjIucG9zaXRpb25zMkQsIHBvbHlnb24yLmhvbGVzKTsKICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPCAzKSB7CiAgICAgICAgICBpbmRpY2VzID0gWzAsIDEsIDJdOwogICAgICAgIH0KICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBwb2x5Z29uMi5wb3NpdGlvbnM7CiAgICAgICAgY29uc3QgaGFzVGV4Y29vcmRzID0gZGVmaW5lZF9kZWZhdWx0KHRleHR1cmVDb29yZGluYXRlcyk7CiAgICAgICAgY29uc3QgdGV4Y29vcmRzID0gaGFzVGV4Y29vcmRzID8gdGV4dHVyZUNvb3JkaW5hdGVzLnBvc2l0aW9ucyA6IHZvaWQgMDsKICAgICAgICBpZiAocGVyUG9zaXRpb25IZWlnaHQpIHsKICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgICBjb25zdCBmbGF0dGVuZWRQb3NpdGlvbnMgPSBuZXcgQXJyYXkobGVuZ3RoICogMyk7CiAgICAgICAgICBsZXQgaW5kZXggPSAwOwogICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICBjb25zdCBwID0gcG9zaXRpb25zW2ldOwogICAgICAgICAgICBmbGF0dGVuZWRQb3NpdGlvbnNbaW5kZXgrK10gPSBwLng7CiAgICAgICAgICAgIGZsYXR0ZW5lZFBvc2l0aW9uc1tpbmRleCsrXSA9IHAueTsKICAgICAgICAgICAgZmxhdHRlbmVkUG9zaXRpb25zW2luZGV4KytdID0gcC56OwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgZ2VvbWV0cnlPcHRpb25zID0gewogICAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgICAgcG9zaXRpb246IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICAgICAgICB2YWx1ZXM6IGZsYXR0ZW5lZFBvc2l0aW9ucwogICAgICAgICAgICAgIH0pCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5UUklBTkdMRVMKICAgICAgICAgIH07CiAgICAgICAgICBpZiAoaGFzVGV4Y29vcmRzKSB7CiAgICAgICAgICAgIGdlb21ldHJ5T3B0aW9ucy5hdHRyaWJ1dGVzLnN0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDIsCiAgICAgICAgICAgICAgdmFsdWVzOiBDYXJ0ZXNpYW4yX2RlZmF1bHQucGFja0FycmF5KHRleGNvb3JkcykKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBnZW9tZXRyeSA9IG5ldyBHZW9tZXRyeV9kZWZhdWx0KGdlb21ldHJ5T3B0aW9ucyk7CiAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICAgICAgICByZXR1cm4gR2VvbWV0cnlQaXBlbGluZV9kZWZhdWx0LmNvbXB1dGVOb3JtYWwoZ2VvbWV0cnkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGdlb21ldHJ5OwogICAgICAgIH0KICAgICAgICBpZiAoYXJjVHlwZSA9PT0gQXJjVHlwZV9kZWZhdWx0LkdFT0RFU0lDKSB7CiAgICAgICAgICByZXR1cm4gUG9seWdvblBpcGVsaW5lX2RlZmF1bHQuY29tcHV0ZVN1YmRpdmlzaW9uKAogICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgICAgaW5kaWNlcywKICAgICAgICAgICAgdGV4Y29vcmRzLAogICAgICAgICAgICBncmFudWxhcml0eQogICAgICAgICAgKTsKICAgICAgICB9IGVsc2UgaWYgKGFyY1R5cGUgPT09IEFyY1R5cGVfZGVmYXVsdC5SSFVNQikgewogICAgICAgICAgcmV0dXJuIFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LmNvbXB1dGVSaHVtYkxpbmVTdWJkaXZpc2lvbigKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICAgIHRleGNvb3JkcywKICAgICAgICAgICAgZ3JhbnVsYXJpdHkKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICB9OwogICAgICBjb21wdXRlV2FsbFRleGNvb3Jkc1N1YmRpdmlkZWQgPSBbXTsKICAgICAgY29tcHV0ZVdhbGxJbmRpY2VzU3ViZGl2aWRlZCA9IFtdOwogICAgICBwMVNjcmF0Y2gyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBwMlNjcmF0Y2gyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LmNvbXB1dGVXYWxsR2VvbWV0cnkgPSBmdW5jdGlvbihwb3NpdGlvbnMsIHRleHR1cmVDb29yZGluYXRlcywgZWxsaXBzb2lkLCBncmFudWxhcml0eSwgcGVyUG9zaXRpb25IZWlnaHQsIGFyY1R5cGUpIHsKICAgICAgICBsZXQgZWRnZVBvc2l0aW9uczsKICAgICAgICBsZXQgdG9wRWRnZUxlbmd0aDsKICAgICAgICBsZXQgaTsKICAgICAgICBsZXQgcDE7CiAgICAgICAgbGV0IHAyOwogICAgICAgIGxldCB0MTsKICAgICAgICBsZXQgdDI7CiAgICAgICAgbGV0IGVkZ2VUZXhjb29yZHM7CiAgICAgICAgbGV0IHRvcEVkZ2VUZXhjb29yZExlbmd0aDsKICAgICAgICBsZXQgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBsZXQgaW5kZXggPSAwOwogICAgICAgIGxldCB0ZXh0dXJlSW5kZXggPSAwOwogICAgICAgIGNvbnN0IGhhc1RleGNvb3JkcyA9IGRlZmluZWRfZGVmYXVsdCh0ZXh0dXJlQ29vcmRpbmF0ZXMpOwogICAgICAgIGNvbnN0IHRleGNvb3JkcyA9IGhhc1RleGNvb3JkcyA/IHRleHR1cmVDb29yZGluYXRlcy5wb3NpdGlvbnMgOiB2b2lkIDA7CiAgICAgICAgaWYgKCFwZXJQb3NpdGlvbkhlaWdodCkgewogICAgICAgICAgY29uc3QgbWluRGlzdGFuY2UgPSBNYXRoX2RlZmF1bHQuY2hvcmRMZW5ndGgoCiAgICAgICAgICAgIGdyYW51bGFyaXR5LAogICAgICAgICAgICBlbGxpcHNvaWQubWF4aW11bVJhZGl1cwogICAgICAgICAgKTsKICAgICAgICAgIGxldCBudW1WZXJ0aWNlcyA9IDA7CiAgICAgICAgICBpZiAoYXJjVHlwZSA9PT0gQXJjVHlwZV9kZWZhdWx0LkdFT0RFU0lDKSB7CiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICAgIG51bVZlcnRpY2VzICs9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnkuc3ViZGl2aWRlTGluZUNvdW50KAogICAgICAgICAgICAgICAgcG9zaXRpb25zW2ldLAogICAgICAgICAgICAgICAgcG9zaXRpb25zWyhpICsgMSkgJSBsZW5ndGhdLAogICAgICAgICAgICAgICAgbWluRGlzdGFuY2UKICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgaWYgKGFyY1R5cGUgPT09IEFyY1R5cGVfZGVmYXVsdC5SSFVNQikgewogICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICBudW1WZXJ0aWNlcyArPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnN1YmRpdmlkZVJodW1iTGluZUNvdW50KAogICAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgICAgcG9zaXRpb25zW2ldLAogICAgICAgICAgICAgICAgcG9zaXRpb25zWyhpICsgMSkgJSBsZW5ndGhdLAogICAgICAgICAgICAgICAgbWluRGlzdGFuY2UKICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB0b3BFZGdlTGVuZ3RoID0gKG51bVZlcnRpY2VzICsgbGVuZ3RoKSAqIDM7CiAgICAgICAgICBlZGdlUG9zaXRpb25zID0gbmV3IEFycmF5KHRvcEVkZ2VMZW5ndGggKiAyKTsKICAgICAgICAgIGlmIChoYXNUZXhjb29yZHMpIHsKICAgICAgICAgICAgdG9wRWRnZVRleGNvb3JkTGVuZ3RoID0gKG51bVZlcnRpY2VzICsgbGVuZ3RoKSAqIDI7CiAgICAgICAgICAgIGVkZ2VUZXhjb29yZHMgPSBuZXcgQXJyYXkodG9wRWRnZVRleGNvb3JkTGVuZ3RoICogMik7CiAgICAgICAgICB9CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgcDEgPSBwb3NpdGlvbnNbaV07CiAgICAgICAgICAgIHAyID0gcG9zaXRpb25zWyhpICsgMSkgJSBsZW5ndGhdOwogICAgICAgICAgICBsZXQgdGVtcFBvc2l0aW9uczsKICAgICAgICAgICAgbGV0IHRlbXBUZXhjb29yZHM7CiAgICAgICAgICAgIGlmIChoYXNUZXhjb29yZHMpIHsKICAgICAgICAgICAgICB0MSA9IHRleGNvb3Jkc1tpXTsKICAgICAgICAgICAgICB0MiA9IHRleGNvb3Jkc1soaSArIDEpICUgbGVuZ3RoXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoYXJjVHlwZSA9PT0gQXJjVHlwZV9kZWZhdWx0LkdFT0RFU0lDKSB7CiAgICAgICAgICAgICAgdGVtcFBvc2l0aW9ucyA9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnkuc3ViZGl2aWRlTGluZSgKICAgICAgICAgICAgICAgIHAxLAogICAgICAgICAgICAgICAgcDIsCiAgICAgICAgICAgICAgICBtaW5EaXN0YW5jZSwKICAgICAgICAgICAgICAgIGNvbXB1dGVXYWxsSW5kaWNlc1N1YmRpdmlkZWQKICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIGlmIChoYXNUZXhjb29yZHMpIHsKICAgICAgICAgICAgICAgIHRlbXBUZXhjb29yZHMgPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnN1YmRpdmlkZVRleGNvb3JkTGluZSgKICAgICAgICAgICAgICAgICAgdDEsCiAgICAgICAgICAgICAgICAgIHQyLAogICAgICAgICAgICAgICAgICBwMSwKICAgICAgICAgICAgICAgICAgcDIsCiAgICAgICAgICAgICAgICAgIG1pbkRpc3RhbmNlLAogICAgICAgICAgICAgICAgICBjb21wdXRlV2FsbFRleGNvb3Jkc1N1YmRpdmlkZWQKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgaWYgKGFyY1R5cGUgPT09IEFyY1R5cGVfZGVmYXVsdC5SSFVNQikgewogICAgICAgICAgICAgIHRlbXBQb3NpdGlvbnMgPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnN1YmRpdmlkZVJodW1iTGluZSgKICAgICAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgICAgIHAxLAogICAgICAgICAgICAgICAgcDIsCiAgICAgICAgICAgICAgICBtaW5EaXN0YW5jZSwKICAgICAgICAgICAgICAgIGNvbXB1dGVXYWxsSW5kaWNlc1N1YmRpdmlkZWQKICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIGlmIChoYXNUZXhjb29yZHMpIHsKICAgICAgICAgICAgICAgIHRlbXBUZXhjb29yZHMgPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5LnN1YmRpdmlkZVRleGNvb3JkUmh1bWJMaW5lKAogICAgICAgICAgICAgICAgICB0MSwKICAgICAgICAgICAgICAgICAgdDIsCiAgICAgICAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgICAgICAgcDEsCiAgICAgICAgICAgICAgICAgIHAyLAogICAgICAgICAgICAgICAgICBtaW5EaXN0YW5jZSwKICAgICAgICAgICAgICAgICAgY29tcHV0ZVdhbGxUZXhjb29yZHNTdWJkaXZpZGVkCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCB0ZW1wUG9zaXRpb25zTGVuZ3RoID0gdGVtcFBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGVtcFBvc2l0aW9uc0xlbmd0aDsgKytqLCArK2luZGV4KSB7CiAgICAgICAgICAgICAgZWRnZVBvc2l0aW9uc1tpbmRleF0gPSB0ZW1wUG9zaXRpb25zW2pdOwogICAgICAgICAgICAgIGVkZ2VQb3NpdGlvbnNbaW5kZXggKyB0b3BFZGdlTGVuZ3RoXSA9IHRlbXBQb3NpdGlvbnNbal07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWRnZVBvc2l0aW9uc1tpbmRleF0gPSBwMi54OwogICAgICAgICAgICBlZGdlUG9zaXRpb25zW2luZGV4ICsgdG9wRWRnZUxlbmd0aF0gPSBwMi54OwogICAgICAgICAgICArK2luZGV4OwogICAgICAgICAgICBlZGdlUG9zaXRpb25zW2luZGV4XSA9IHAyLnk7CiAgICAgICAgICAgIGVkZ2VQb3NpdGlvbnNbaW5kZXggKyB0b3BFZGdlTGVuZ3RoXSA9IHAyLnk7CiAgICAgICAgICAgICsraW5kZXg7CiAgICAgICAgICAgIGVkZ2VQb3NpdGlvbnNbaW5kZXhdID0gcDIuejsKICAgICAgICAgICAgZWRnZVBvc2l0aW9uc1tpbmRleCArIHRvcEVkZ2VMZW5ndGhdID0gcDIuejsKICAgICAgICAgICAgKytpbmRleDsKICAgICAgICAgICAgaWYgKGhhc1RleGNvb3JkcykgewogICAgICAgICAgICAgIGNvbnN0IHRlbXBUZXhjb29yZHNMZW5ndGggPSB0ZW1wVGV4Y29vcmRzLmxlbmd0aDsKICAgICAgICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IHRlbXBUZXhjb29yZHNMZW5ndGg7ICsraywgKyt0ZXh0dXJlSW5kZXgpIHsKICAgICAgICAgICAgICAgIGVkZ2VUZXhjb29yZHNbdGV4dHVyZUluZGV4XSA9IHRlbXBUZXhjb29yZHNba107CiAgICAgICAgICAgICAgICBlZGdlVGV4Y29vcmRzW3RleHR1cmVJbmRleCArIHRvcEVkZ2VUZXhjb29yZExlbmd0aF0gPSB0ZW1wVGV4Y29vcmRzW2tdOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBlZGdlVGV4Y29vcmRzW3RleHR1cmVJbmRleF0gPSB0Mi54OwogICAgICAgICAgICAgIGVkZ2VUZXhjb29yZHNbdGV4dHVyZUluZGV4ICsgdG9wRWRnZVRleGNvb3JkTGVuZ3RoXSA9IHQyLng7CiAgICAgICAgICAgICAgKyt0ZXh0dXJlSW5kZXg7CiAgICAgICAgICAgICAgZWRnZVRleGNvb3Jkc1t0ZXh0dXJlSW5kZXhdID0gdDIueTsKICAgICAgICAgICAgICBlZGdlVGV4Y29vcmRzW3RleHR1cmVJbmRleCArIHRvcEVkZ2VUZXhjb29yZExlbmd0aF0gPSB0Mi55OwogICAgICAgICAgICAgICsrdGV4dHVyZUluZGV4OwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRvcEVkZ2VMZW5ndGggPSBsZW5ndGggKiAzICogMjsKICAgICAgICAgIGVkZ2VQb3NpdGlvbnMgPSBuZXcgQXJyYXkodG9wRWRnZUxlbmd0aCAqIDIpOwogICAgICAgICAgaWYgKGhhc1RleGNvb3JkcykgewogICAgICAgICAgICB0b3BFZGdlVGV4Y29vcmRMZW5ndGggPSBsZW5ndGggKiAyICogMjsKICAgICAgICAgICAgZWRnZVRleGNvb3JkcyA9IG5ldyBBcnJheSh0b3BFZGdlVGV4Y29vcmRMZW5ndGggKiAyKTsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICBwMSA9IHBvc2l0aW9uc1tpXTsKICAgICAgICAgICAgcDIgPSBwb3NpdGlvbnNbKGkgKyAxKSAlIGxlbmd0aF07CiAgICAgICAgICAgIGVkZ2VQb3NpdGlvbnNbaW5kZXhdID0gZWRnZVBvc2l0aW9uc1tpbmRleCArIHRvcEVkZ2VMZW5ndGhdID0gcDEueDsKICAgICAgICAgICAgKytpbmRleDsKICAgICAgICAgICAgZWRnZVBvc2l0aW9uc1tpbmRleF0gPSBlZGdlUG9zaXRpb25zW2luZGV4ICsgdG9wRWRnZUxlbmd0aF0gPSBwMS55OwogICAgICAgICAgICArK2luZGV4OwogICAgICAgICAgICBlZGdlUG9zaXRpb25zW2luZGV4XSA9IGVkZ2VQb3NpdGlvbnNbaW5kZXggKyB0b3BFZGdlTGVuZ3RoXSA9IHAxLno7CiAgICAgICAgICAgICsraW5kZXg7CiAgICAgICAgICAgIGVkZ2VQb3NpdGlvbnNbaW5kZXhdID0gZWRnZVBvc2l0aW9uc1tpbmRleCArIHRvcEVkZ2VMZW5ndGhdID0gcDIueDsKICAgICAgICAgICAgKytpbmRleDsKICAgICAgICAgICAgZWRnZVBvc2l0aW9uc1tpbmRleF0gPSBlZGdlUG9zaXRpb25zW2luZGV4ICsgdG9wRWRnZUxlbmd0aF0gPSBwMi55OwogICAgICAgICAgICArK2luZGV4OwogICAgICAgICAgICBlZGdlUG9zaXRpb25zW2luZGV4XSA9IGVkZ2VQb3NpdGlvbnNbaW5kZXggKyB0b3BFZGdlTGVuZ3RoXSA9IHAyLno7CiAgICAgICAgICAgICsraW5kZXg7CiAgICAgICAgICAgIGlmIChoYXNUZXhjb29yZHMpIHsKICAgICAgICAgICAgICB0MSA9IHRleGNvb3Jkc1tpXTsKICAgICAgICAgICAgICB0MiA9IHRleGNvb3Jkc1soaSArIDEpICUgbGVuZ3RoXTsKICAgICAgICAgICAgICBlZGdlVGV4Y29vcmRzW3RleHR1cmVJbmRleF0gPSBlZGdlVGV4Y29vcmRzW3RleHR1cmVJbmRleCArIHRvcEVkZ2VUZXhjb29yZExlbmd0aF0gPSB0MS54OwogICAgICAgICAgICAgICsrdGV4dHVyZUluZGV4OwogICAgICAgICAgICAgIGVkZ2VUZXhjb29yZHNbdGV4dHVyZUluZGV4XSA9IGVkZ2VUZXhjb29yZHNbdGV4dHVyZUluZGV4ICsgdG9wRWRnZVRleGNvb3JkTGVuZ3RoXSA9IHQxLnk7CiAgICAgICAgICAgICAgKyt0ZXh0dXJlSW5kZXg7CiAgICAgICAgICAgICAgZWRnZVRleGNvb3Jkc1t0ZXh0dXJlSW5kZXhdID0gZWRnZVRleGNvb3Jkc1t0ZXh0dXJlSW5kZXggKyB0b3BFZGdlVGV4Y29vcmRMZW5ndGhdID0gdDIueDsKICAgICAgICAgICAgICArK3RleHR1cmVJbmRleDsKICAgICAgICAgICAgICBlZGdlVGV4Y29vcmRzW3RleHR1cmVJbmRleF0gPSBlZGdlVGV4Y29vcmRzW3RleHR1cmVJbmRleCArIHRvcEVkZ2VUZXhjb29yZExlbmd0aF0gPSB0Mi55OwogICAgICAgICAgICAgICsrdGV4dHVyZUluZGV4OwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGxlbmd0aCA9IGVkZ2VQb3NpdGlvbnMubGVuZ3RoOwogICAgICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgICAgIGxlbmd0aCAvIDMsCiAgICAgICAgICBsZW5ndGggLSBwb3NpdGlvbnMubGVuZ3RoICogNgogICAgICAgICk7CiAgICAgICAgbGV0IGVkZ2VJbmRleCA9IDA7CiAgICAgICAgbGVuZ3RoIC89IDY7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBjb25zdCBVTCA9IGk7CiAgICAgICAgICBjb25zdCBVUiA9IFVMICsgMTsKICAgICAgICAgIGNvbnN0IExMID0gVUwgKyBsZW5ndGg7CiAgICAgICAgICBjb25zdCBMUiA9IExMICsgMTsKICAgICAgICAgIHAxID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShlZGdlUG9zaXRpb25zLCBVTCAqIDMsIHAxU2NyYXRjaDIpOwogICAgICAgICAgcDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KGVkZ2VQb3NpdGlvbnMsIFVSICogMywgcDJTY3JhdGNoMik7CiAgICAgICAgICBpZiAoQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICAgIHAxLAogICAgICAgICAgICBwMiwKICAgICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xMCwKICAgICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xMAogICAgICAgICAgKSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGluZGljZXNbZWRnZUluZGV4KytdID0gVUw7CiAgICAgICAgICBpbmRpY2VzW2VkZ2VJbmRleCsrXSA9IExMOwogICAgICAgICAgaW5kaWNlc1tlZGdlSW5kZXgrK10gPSBVUjsKICAgICAgICAgIGluZGljZXNbZWRnZUluZGV4KytdID0gVVI7CiAgICAgICAgICBpbmRpY2VzW2VkZ2VJbmRleCsrXSA9IExMOwogICAgICAgICAgaW5kaWNlc1tlZGdlSW5kZXgrK10gPSBMUjsKICAgICAgICB9CiAgICAgICAgY29uc3QgZ2VvbWV0cnlPcHRpb25zID0gewogICAgICAgICAgYXR0cmlidXRlczogbmV3IEdlb21ldHJ5QXR0cmlidXRlc19kZWZhdWx0KHsKICAgICAgICAgICAgcG9zaXRpb246IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgICB2YWx1ZXM6IGVkZ2VQb3NpdGlvbnMKICAgICAgICAgICAgfSkKICAgICAgICAgIH0pLAogICAgICAgICAgaW5kaWNlcywKICAgICAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5UUklBTkdMRVMKICAgICAgICB9OwogICAgICAgIGlmIChoYXNUZXhjb29yZHMpIHsKICAgICAgICAgIGdlb21ldHJ5T3B0aW9ucy5hdHRyaWJ1dGVzLnN0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMiwKICAgICAgICAgICAgdmFsdWVzOiBlZGdlVGV4Y29vcmRzCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZ2VvbWV0cnkgPSBuZXcgR2VvbWV0cnlfZGVmYXVsdChnZW9tZXRyeU9wdGlvbnMpOwogICAgICAgIHJldHVybiBnZW9tZXRyeTsKICAgICAgfTsKICAgICAgUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0ID0gUG9seWdvbkdlb21ldHJ5TGlicmFyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NvcGxhbmFyUG9seWdvbkdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gY3JlYXRlR2VvbWV0cnlGcm9tUG9seWdvbihwb2x5Z29uMiwgdmVydGV4Rm9ybWF0LCBib3VuZGluZ1JlY3RhbmdsZSwgc3RSb3RhdGlvbiwgaGFyZGNvZGVkVGV4dHVyZUNvb3JkaW5hdGVzLCBwcm9qZWN0UG9pbnRUbzJELCBub3JtYWwyLCB0YW5nZW50LCBiaXRhbmdlbnQpIHsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IHBvbHlnb24yLnBvc2l0aW9uczsKICAgIGxldCBpbmRpY2VzID0gUG9seWdvblBpcGVsaW5lX2RlZmF1bHQudHJpYW5ndWxhdGUocG9seWdvbjIucG9zaXRpb25zMkQsIHBvbHlnb24yLmhvbGVzKTsKICAgIGlmIChpbmRpY2VzLmxlbmd0aCA8IDMpIHsKICAgICAgaW5kaWNlcyA9IFswLCAxLCAyXTsKICAgIH0KICAgIGNvbnN0IG5ld0luZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgcG9zaXRpb25zLmxlbmd0aCwKICAgICAgaW5kaWNlcy5sZW5ndGgKICAgICk7CiAgICBuZXdJbmRpY2VzLnNldChpbmRpY2VzKTsKICAgIGxldCB0ZXh0dXJlTWF0cml4ID0gdGV4dHVyZU1hdHJpeFNjcmF0Y2gyOwogICAgaWYgKHN0Um90YXRpb24gIT09IDApIHsKICAgICAgbGV0IHJvdGF0aW9uID0gUXVhdGVybmlvbl9kZWZhdWx0LmZyb21BeGlzQW5nbGUoCiAgICAgICAgbm9ybWFsMiwKICAgICAgICBzdFJvdGF0aW9uLAogICAgICAgIHF1YXRlcm5pb25TY3JhdGNoMgogICAgICApOwogICAgICB0ZXh0dXJlTWF0cml4ID0gTWF0cml4M19kZWZhdWx0LmZyb21RdWF0ZXJuaW9uKHJvdGF0aW9uLCB0ZXh0dXJlTWF0cml4KTsKICAgICAgaWYgKHZlcnRleEZvcm1hdC50YW5nZW50IHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICByb3RhdGlvbiA9IFF1YXRlcm5pb25fZGVmYXVsdC5mcm9tQXhpc0FuZ2xlKAogICAgICAgICAgbm9ybWFsMiwKICAgICAgICAgIC1zdFJvdGF0aW9uLAogICAgICAgICAgcXVhdGVybmlvblNjcmF0Y2gyCiAgICAgICAgKTsKICAgICAgICBjb25zdCB0YW5nZW50Um90YXRpb24gPSBNYXRyaXgzX2RlZmF1bHQuZnJvbVF1YXRlcm5pb24oCiAgICAgICAgICByb3RhdGlvbiwKICAgICAgICAgIHRhbmdlbnRSb3RhdGlvblNjcmF0Y2gKICAgICAgICApOwogICAgICAgIHRhbmdlbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3IodGFuZ2VudFJvdGF0aW9uLCB0YW5nZW50LCB0YW5nZW50KSwKICAgICAgICAgIHRhbmdlbnQKICAgICAgICApOwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgICBiaXRhbmdlbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3Mobm9ybWFsMiwgdGFuZ2VudCwgYml0YW5nZW50KSwKICAgICAgICAgICAgYml0YW5nZW50CiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdGV4dHVyZU1hdHJpeCA9IE1hdHJpeDNfZGVmYXVsdC5jbG9uZShNYXRyaXgzX2RlZmF1bHQuSURFTlRJVFksIHRleHR1cmVNYXRyaXgpOwogICAgfQogICAgY29uc3Qgc3RPcmlnaW4gPSB0ZXh0dXJlQ29vcmRpbmF0ZXNPcmlnaW47CiAgICBpZiAodmVydGV4Rm9ybWF0LnN0KSB7CiAgICAgIHN0T3JpZ2luLnggPSBib3VuZGluZ1JlY3RhbmdsZS54OwogICAgICBzdE9yaWdpbi55ID0gYm91bmRpbmdSZWN0YW5nbGUueTsKICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICBjb25zdCBzaXplID0gbGVuZ3RoICogMzsKICAgIGNvbnN0IGZsYXRQb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KHNpemUpOwogICAgY29uc3Qgbm9ybWFscyA9IHZlcnRleEZvcm1hdC5ub3JtYWwgPyBuZXcgRmxvYXQzMkFycmF5KHNpemUpIDogdm9pZCAwOwogICAgY29uc3QgdGFuZ2VudHMgPSB2ZXJ0ZXhGb3JtYXQudGFuZ2VudCA/IG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSkgOiB2b2lkIDA7CiAgICBjb25zdCBiaXRhbmdlbnRzID0gdmVydGV4Rm9ybWF0LmJpdGFuZ2VudCA/IG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSkgOiB2b2lkIDA7CiAgICBjb25zdCB0ZXh0dXJlQ29vcmRpbmF0ZXMgPSB2ZXJ0ZXhGb3JtYXQuc3QgPyBuZXcgRmxvYXQzMkFycmF5KGxlbmd0aCAqIDIpIDogdm9pZCAwOwogICAgbGV0IHBvc2l0aW9uSW5kZXggPSAwOwogICAgbGV0IG5vcm1hbEluZGV4ID0gMDsKICAgIGxldCBiaXRhbmdlbnRJbmRleCA9IDA7CiAgICBsZXQgdGFuZ2VudEluZGV4ID0gMDsKICAgIGxldCBzdEluZGV4ID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgY29uc3QgcG9zaXRpb24gPSBwb3NpdGlvbnNbaV07CiAgICAgIGZsYXRQb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IHBvc2l0aW9uLng7CiAgICAgIGZsYXRQb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IHBvc2l0aW9uLnk7CiAgICAgIGZsYXRQb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IHBvc2l0aW9uLno7CiAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGhhcmRjb2RlZFRleHR1cmVDb29yZGluYXRlcykgJiYgaGFyZGNvZGVkVGV4dHVyZUNvb3JkaW5hdGVzLnBvc2l0aW9ucy5sZW5ndGggPT09IGxlbmd0aCkgewogICAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW3N0SW5kZXgrK10gPSBoYXJkY29kZWRUZXh0dXJlQ29vcmRpbmF0ZXMucG9zaXRpb25zW2ldLng7CiAgICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXNbc3RJbmRleCsrXSA9IGhhcmRjb2RlZFRleHR1cmVDb29yZGluYXRlcy5wb3NpdGlvbnNbaV0ueTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgcCA9IE1hdHJpeDNfZGVmYXVsdC5tdWx0aXBseUJ5VmVjdG9yKAogICAgICAgICAgICB0ZXh0dXJlTWF0cml4LAogICAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgICAgc2NyYXRjaFBvc2l0aW9uCiAgICAgICAgICApOwogICAgICAgICAgY29uc3Qgc3QgPSBwcm9qZWN0UG9pbnRUbzJEKHAsIHN0U2NyYXRjaCk7CiAgICAgICAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQuc3VidHJhY3Qoc3QsIHN0T3JpZ2luLCBzdCk7CiAgICAgICAgICBjb25zdCBzdHggPSBNYXRoX2RlZmF1bHQuY2xhbXAoc3QueCAvIGJvdW5kaW5nUmVjdGFuZ2xlLndpZHRoLCAwLCAxKTsKICAgICAgICAgIGNvbnN0IHN0eSA9IE1hdGhfZGVmYXVsdC5jbGFtcChzdC55IC8gYm91bmRpbmdSZWN0YW5nbGUuaGVpZ2h0LCAwLCAxKTsKICAgICAgICAgIHRleHR1cmVDb29yZGluYXRlc1tzdEluZGV4KytdID0gc3R4OwogICAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW3N0SW5kZXgrK10gPSBzdHk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgICAgbm9ybWFsc1tub3JtYWxJbmRleCsrXSA9IG5vcm1hbDIueDsKICAgICAgICBub3JtYWxzW25vcm1hbEluZGV4KytdID0gbm9ybWFsMi55OwogICAgICAgIG5vcm1hbHNbbm9ybWFsSW5kZXgrK10gPSBub3JtYWwyLno7CiAgICAgIH0KICAgICAgaWYgKHZlcnRleEZvcm1hdC50YW5nZW50KSB7CiAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC54OwogICAgICAgIHRhbmdlbnRzW3RhbmdlbnRJbmRleCsrXSA9IHRhbmdlbnQueTsKICAgICAgICB0YW5nZW50c1t0YW5nZW50SW5kZXgrK10gPSB0YW5nZW50Lno7CiAgICAgIH0KICAgICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICBiaXRhbmdlbnRzW2JpdGFuZ2VudEluZGV4KytdID0gYml0YW5nZW50Lng7CiAgICAgICAgYml0YW5nZW50c1tiaXRhbmdlbnRJbmRleCsrXSA9IGJpdGFuZ2VudC55OwogICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQuejsKICAgICAgfQogICAgfQogICAgY29uc3QgYXR0cmlidXRlcyA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZXNfZGVmYXVsdCgpOwogICAgaWYgKHZlcnRleEZvcm1hdC5wb3NpdGlvbikgewogICAgICBhdHRyaWJ1dGVzLnBvc2l0aW9uID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgIHZhbHVlczogZmxhdFBvc2l0aW9ucwogICAgICB9KTsKICAgIH0KICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgIGF0dHJpYnV0ZXMubm9ybWFsID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgdmFsdWVzOiBub3JtYWxzCiAgICAgIH0pOwogICAgfQogICAgaWYgKHZlcnRleEZvcm1hdC50YW5nZW50KSB7CiAgICAgIGF0dHJpYnV0ZXMudGFuZ2VudCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgIHZhbHVlczogdGFuZ2VudHMKICAgICAgfSk7CiAgICB9CiAgICBpZiAodmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICBhdHRyaWJ1dGVzLmJpdGFuZ2VudCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgIHZhbHVlczogYml0YW5nZW50cwogICAgICB9KTsKICAgIH0KICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgYXR0cmlidXRlcy5zdCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAyLAogICAgICAgIHZhbHVlczogdGV4dHVyZUNvb3JkaW5hdGVzCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgYXR0cmlidXRlcywKICAgICAgaW5kaWNlczogbmV3SW5kaWNlcywKICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUwogICAgfSk7CiAgfQogIGZ1bmN0aW9uIENvcGxhbmFyUG9seWdvbkdlb21ldHJ5KG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIGNvbnN0IHBvbHlnb25IaWVyYXJjaHkgPSBvcHRpb25zLnBvbHlnb25IaWVyYXJjaHk7CiAgICBjb25zdCB0ZXh0dXJlQ29vcmRpbmF0ZXMgPSBvcHRpb25zLnRleHR1cmVDb29yZGluYXRlczsKICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgib3B0aW9ucy5wb2x5Z29uSGllcmFyY2h5IiwgcG9seWdvbkhpZXJhcmNoeSk7CiAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBvcHRpb25zLnZlcnRleEZvcm1hdCA/PyBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5ERUZBVUxUOwogICAgdGhpcy5fdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQuY2xvbmUodmVydGV4Rm9ybWF0KTsKICAgIHRoaXMuX3BvbHlnb25IaWVyYXJjaHkgPSBwb2x5Z29uSGllcmFyY2h5OwogICAgdGhpcy5fc3RSb3RhdGlvbiA9IG9wdGlvbnMuc3RSb3RhdGlvbiA/PyAwOwogICAgdGhpcy5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUob3B0aW9ucy5lbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdCk7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZUNvcGxhbmFyUG9seWdvbkdlb21ldHJ5IjsKICAgIHRoaXMuX3RleHR1cmVDb29yZGluYXRlcyA9IHRleHR1cmVDb29yZGluYXRlczsKICAgIHRoaXMucGFja2VkTGVuZ3RoID0gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVIaWVyYXJjaHlQYWNrZWRMZW5ndGgoCiAgICAgIHBvbHlnb25IaWVyYXJjaHksCiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdAogICAgKSArIFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIChkZWZpbmVkX2RlZmF1bHQodGV4dHVyZUNvb3JkaW5hdGVzKSA/IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlSGllcmFyY2h5UGFja2VkTGVuZ3RoKAogICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXMsCiAgICAgIENhcnRlc2lhbjJfZGVmYXVsdAogICAgKSA6IDEpICsgMjsKICB9CiAgdmFyIHNjcmF0Y2hQb3NpdGlvbiwgc2NyYXRjaEJSLCBzdFNjcmF0Y2gsIHRleHR1cmVDb29yZGluYXRlc09yaWdpbiwgc2NyYXRjaE5vcm1hbDQsIHNjcmF0Y2hUYW5nZW50Miwgc2NyYXRjaEJpdGFuZ2VudDIsIGNlbnRlclNjcmF0Y2gsIGF4aXMxU2NyYXRjaCwgYXhpczJTY3JhdGNoLCBxdWF0ZXJuaW9uU2NyYXRjaDIsIHRleHR1cmVNYXRyaXhTY3JhdGNoMiwgdGFuZ2VudFJvdGF0aW9uU2NyYXRjaCwgc3VyZmFjZU5vcm1hbFNjcmF0Y2gsIHNjcmF0Y2hFbGxpcHNvaWQzLCBzY3JhdGNoVmVydGV4Rm9ybWF0Mywgc2NyYXRjaE9wdGlvbnM3LCBDb3BsYW5hclBvbHlnb25HZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X0NvcGxhbmFyUG9seWdvbkdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Db3BsYW5hclBvbHlnb25HZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfYXJyYXlSZW1vdmVEdXBsaWNhdGVzKCk7CiAgICAgIGluaXRfQm91bmRpbmdSZWN0YW5nbGUoKTsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X0NvcGxhbmFyUG9seWdvbkdlb21ldHJ5TGlicmFyeSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9HZW9tZXRyeSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGVzKCk7CiAgICAgIGluaXRfR2VvbWV0cnlJbnN0YW5jZSgpOwogICAgICBpbml0X0dlb21ldHJ5UGlwZWxpbmUoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X01hdHJpeDMoKTsKICAgICAgaW5pdF9Qb2x5Z29uR2VvbWV0cnlMaWJyYXJ5KCk7CiAgICAgIGluaXRfUG9seWdvblBpcGVsaW5lKCk7CiAgICAgIGluaXRfUHJpbWl0aXZlVHlwZSgpOwogICAgICBpbml0X1F1YXRlcm5pb24oKTsKICAgICAgaW5pdF9WZXJ0ZXhGb3JtYXQoKTsKICAgICAgc2NyYXRjaFBvc2l0aW9uID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQlIgPSBuZXcgQm91bmRpbmdSZWN0YW5nbGVfZGVmYXVsdCgpOwogICAgICBzdFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIHRleHR1cmVDb29yZGluYXRlc09yaWdpbiA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE5vcm1hbDQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hUYW5nZW50MiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEJpdGFuZ2VudDIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNlbnRlclNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGF4aXMxU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgYXhpczJTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBxdWF0ZXJuaW9uU2NyYXRjaDIgPSBuZXcgUXVhdGVybmlvbl9kZWZhdWx0KCk7CiAgICAgIHRleHR1cmVNYXRyaXhTY3JhdGNoMiA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgdGFuZ2VudFJvdGF0aW9uU2NyYXRjaCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgc3VyZmFjZU5vcm1hbFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIENvcGxhbmFyUG9seWdvbkdlb21ldHJ5LmZyb21Qb3NpdGlvbnMgPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgib3B0aW9ucy5wb3NpdGlvbnMiLCBvcHRpb25zLnBvc2l0aW9ucyk7CiAgICAgICAgY29uc3QgbmV3T3B0aW9ucyA9IHsKICAgICAgICAgIHBvbHlnb25IaWVyYXJjaHk6IHsKICAgICAgICAgICAgcG9zaXRpb25zOiBvcHRpb25zLnBvc2l0aW9ucwogICAgICAgICAgfSwKICAgICAgICAgIHZlcnRleEZvcm1hdDogb3B0aW9ucy52ZXJ0ZXhGb3JtYXQsCiAgICAgICAgICBzdFJvdGF0aW9uOiBvcHRpb25zLnN0Um90YXRpb24sCiAgICAgICAgICBlbGxpcHNvaWQ6IG9wdGlvbnMuZWxsaXBzb2lkLAogICAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzOiBvcHRpb25zLnRleHR1cmVDb29yZGluYXRlcwogICAgICAgIH07CiAgICAgICAgcmV0dXJuIG5ldyBDb3BsYW5hclBvbHlnb25HZW9tZXRyeShuZXdPcHRpb25zKTsKICAgICAgfTsKICAgICAgQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQucGFja1BvbHlnb25IaWVyYXJjaHkoCiAgICAgICAgICB2YWx1ZS5fcG9seWdvbkhpZXJhcmNoeSwKICAgICAgICAgIGFycmF5LAogICAgICAgICAgc3RhcnRpbmdJbmRleCwKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdAogICAgICAgICk7CiAgICAgICAgRWxsaXBzb2lkX2RlZmF1bHQucGFjayh2YWx1ZS5fZWxsaXBzb2lkLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFjayh2YWx1ZS5fdmVydGV4Rm9ybWF0LCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9zdFJvdGF0aW9uOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQodmFsdWUuX3RleHR1cmVDb29yZGluYXRlcykpIHsKICAgICAgICAgIHN0YXJ0aW5nSW5kZXggPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQucGFja1BvbHlnb25IaWVyYXJjaHkoCiAgICAgICAgICAgIHZhbHVlLl90ZXh0dXJlQ29vcmRpbmF0ZXMsCiAgICAgICAgICAgIGFycmF5LAogICAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQKICAgICAgICAgICk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSAtMTsKICAgICAgICB9CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLnBhY2tlZExlbmd0aDsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hFbGxpcHNvaWQzID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoRWxsaXBzb2lkX2RlZmF1bHQuVU5JVF9TUEhFUkUpOwogICAgICBzY3JhdGNoVmVydGV4Rm9ybWF0MyA9IG5ldyBWZXJ0ZXhGb3JtYXRfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoT3B0aW9uczcgPSB7CiAgICAgICAgcG9seWdvbkhpZXJhcmNoeToge30KICAgICAgfTsKICAgICAgQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnkudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBjb25zdCBwb2x5Z29uSGllcmFyY2h5ID0gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LnVucGFja1BvbHlnb25IaWVyYXJjaHkoCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQKICAgICAgICApOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBwb2x5Z29uSGllcmFyY2h5LnN0YXJ0aW5nSW5kZXg7CiAgICAgICAgZGVsZXRlIHBvbHlnb25IaWVyYXJjaHkuc3RhcnRpbmdJbmRleDsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHNjcmF0Y2hFbGxpcHNvaWQzKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICBzY3JhdGNoVmVydGV4Rm9ybWF0MwogICAgICAgICk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3Qgc3RSb3RhdGlvbiA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgdGV4dHVyZUNvb3JkaW5hdGVzID0gYXJyYXlbc3RhcnRpbmdJbmRleF0gPT09IC0xID8gdm9pZCAwIDogUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LnVucGFja1BvbHlnb25IaWVyYXJjaHkoCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQKICAgICAgICApOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQodGV4dHVyZUNvb3JkaW5hdGVzKSkgewogICAgICAgICAgc3RhcnRpbmdJbmRleCA9IHRleHR1cmVDb29yZGluYXRlcy5zdGFydGluZ0luZGV4OwogICAgICAgICAgZGVsZXRlIHRleHR1cmVDb29yZGluYXRlcy5zdGFydGluZ0luZGV4OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdGFydGluZ0luZGV4Kys7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHBhY2tlZExlbmd0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENvcGxhbmFyUG9seWdvbkdlb21ldHJ5KHNjcmF0Y2hPcHRpb25zNyk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5fcG9seWdvbkhpZXJhcmNoeSA9IHBvbHlnb25IaWVyYXJjaHk7CiAgICAgICAgcmVzdWx0Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShlbGxpcHNvaWQsIHJlc3VsdC5fZWxsaXBzb2lkKTsKICAgICAgICByZXN1bHQuX3ZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LmNsb25lKHZlcnRleEZvcm1hdCwgcmVzdWx0Ll92ZXJ0ZXhGb3JtYXQpOwogICAgICAgIHJlc3VsdC5fc3RSb3RhdGlvbiA9IHN0Um90YXRpb247CiAgICAgICAgcmVzdWx0Ll90ZXh0dXJlQ29vcmRpbmF0ZXMgPSB0ZXh0dXJlQ29vcmRpbmF0ZXM7CiAgICAgICAgcmVzdWx0LnBhY2tlZExlbmd0aCA9IHBhY2tlZExlbmd0aDsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDb3BsYW5hclBvbHlnb25HZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKHBvbHlnb25HZW9tZXRyeSkgewogICAgICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IHBvbHlnb25HZW9tZXRyeS5fdmVydGV4Rm9ybWF0OwogICAgICAgIGNvbnN0IHBvbHlnb25IaWVyYXJjaHkgPSBwb2x5Z29uR2VvbWV0cnkuX3BvbHlnb25IaWVyYXJjaHk7CiAgICAgICAgY29uc3Qgc3RSb3RhdGlvbiA9IHBvbHlnb25HZW9tZXRyeS5fc3RSb3RhdGlvbjsKICAgICAgICBjb25zdCB0ZXh0dXJlQ29vcmRpbmF0ZXMgPSBwb2x5Z29uR2VvbWV0cnkuX3RleHR1cmVDb29yZGluYXRlczsKICAgICAgICBjb25zdCBoYXNUZXh0dXJlQ29vcmRpbmF0ZXMgPSBkZWZpbmVkX2RlZmF1bHQodGV4dHVyZUNvb3JkaW5hdGVzKTsKICAgICAgICBsZXQgb3V0ZXJQb3NpdGlvbnMgPSBwb2x5Z29uSGllcmFyY2h5LnBvc2l0aW9uczsKICAgICAgICBvdXRlclBvc2l0aW9ucyA9IGFycmF5UmVtb3ZlRHVwbGljYXRlc19kZWZhdWx0KAogICAgICAgICAgb3V0ZXJQb3NpdGlvbnMsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbiwKICAgICAgICAgIHRydWUKICAgICAgICApOwogICAgICAgIGlmIChvdXRlclBvc2l0aW9ucy5sZW5ndGggPCAzKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGxldCBub3JtYWwyID0gc2NyYXRjaE5vcm1hbDQ7CiAgICAgICAgbGV0IHRhbmdlbnQgPSBzY3JhdGNoVGFuZ2VudDI7CiAgICAgICAgbGV0IGJpdGFuZ2VudCA9IHNjcmF0Y2hCaXRhbmdlbnQyOwogICAgICAgIGxldCBheGlzMSA9IGF4aXMxU2NyYXRjaDsKICAgICAgICBjb25zdCBheGlzMiA9IGF4aXMyU2NyYXRjaDsKICAgICAgICBjb25zdCB2YWxpZEdlb21ldHJ5ID0gQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZVByb2plY3RUbzJEQXJndW1lbnRzKAogICAgICAgICAgb3V0ZXJQb3NpdGlvbnMsCiAgICAgICAgICBjZW50ZXJTY3JhdGNoLAogICAgICAgICAgYXhpczEsCiAgICAgICAgICBheGlzMgogICAgICAgICk7CiAgICAgICAgaWYgKCF2YWxpZEdlb21ldHJ5KSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBub3JtYWwyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKGF4aXMxLCBheGlzMiwgbm9ybWFsMik7CiAgICAgICAgbm9ybWFsMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUobm9ybWFsMiwgbm9ybWFsMik7CiAgICAgICAgaWYgKCFDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIGNlbnRlclNjcmF0Y2gsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywKICAgICAgICAgIE1hdGhfZGVmYXVsdC5FUFNJTE9ONgogICAgICAgICkpIHsKICAgICAgICAgIGNvbnN0IHN1cmZhY2VOb3JtYWwgPSBwb2x5Z29uR2VvbWV0cnkuX2VsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwoCiAgICAgICAgICAgIGNlbnRlclNjcmF0Y2gsCiAgICAgICAgICAgIHN1cmZhY2VOb3JtYWxTY3JhdGNoCiAgICAgICAgICApOwogICAgICAgICAgaWYgKENhcnRlc2lhbjNfZGVmYXVsdC5kb3Qobm9ybWFsMiwgc3VyZmFjZU5vcm1hbCkgPCAwKSB7CiAgICAgICAgICAgIG5vcm1hbDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKG5vcm1hbDIsIG5vcm1hbDIpOwogICAgICAgICAgICBheGlzMSA9IENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoYXhpczEsIGF4aXMxKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgcHJvamVjdFBvaW50cyA9IENvcGxhbmFyUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNyZWF0ZVByb2plY3RQb2ludHNUbzJERnVuY3Rpb24oCiAgICAgICAgICBjZW50ZXJTY3JhdGNoLAogICAgICAgICAgYXhpczEsCiAgICAgICAgICBheGlzMgogICAgICAgICk7CiAgICAgICAgY29uc3QgcHJvamVjdFBvaW50ID0gQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY3JlYXRlUHJvamVjdFBvaW50VG8yREZ1bmN0aW9uKAogICAgICAgICAgY2VudGVyU2NyYXRjaCwKICAgICAgICAgIGF4aXMxLAogICAgICAgICAgYXhpczIKICAgICAgICApOwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICAgICAgdGFuZ2VudCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShheGlzMSwgdGFuZ2VudCk7CiAgICAgICAgfQogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgICBiaXRhbmdlbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoYXhpczIsIGJpdGFuZ2VudCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHJlc3VsdHMgPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQucG9seWdvbnNGcm9tSGllcmFyY2h5KAogICAgICAgICAgcG9seWdvbkhpZXJhcmNoeSwKICAgICAgICAgIGhhc1RleHR1cmVDb29yZGluYXRlcywKICAgICAgICAgIHByb2plY3RQb2ludHMsCiAgICAgICAgICBmYWxzZQogICAgICAgICk7CiAgICAgICAgY29uc3QgaGllcmFyY2h5ID0gcmVzdWx0cy5oaWVyYXJjaHk7CiAgICAgICAgY29uc3QgcG9seWdvbnMgPSByZXN1bHRzLnBvbHlnb25zOwogICAgICAgIGNvbnN0IGR1bW15RnVuY3Rpb24gPSBmdW5jdGlvbihpZGVudGl0eSkgewogICAgICAgICAgcmV0dXJuIGlkZW50aXR5OwogICAgICAgIH07CiAgICAgICAgY29uc3QgdGV4dHVyZUNvb3JkaW5hdGVQb2x5Z29ucyA9IGhhc1RleHR1cmVDb29yZGluYXRlcyA/IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5wb2x5Z29uc0Zyb21IaWVyYXJjaHkoCiAgICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXMsCiAgICAgICAgICB0cnVlLAogICAgICAgICAgZHVtbXlGdW5jdGlvbiwKICAgICAgICAgIGZhbHNlCiAgICAgICAgKS5wb2x5Z29ucyA6IHZvaWQgMDsKICAgICAgICBpZiAoaGllcmFyY2h5Lmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBvdXRlclBvc2l0aW9ucyA9IGhpZXJhcmNoeVswXS5vdXRlclJpbmc7CiAgICAgICAgY29uc3QgYm91bmRpbmdTcGhlcmUgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21Qb2ludHMob3V0ZXJQb3NpdGlvbnMpOwogICAgICAgIGNvbnN0IGJvdW5kaW5nUmVjdGFuZ2xlID0gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVCb3VuZGluZ1JlY3RhbmdsZSgKICAgICAgICAgIG5vcm1hbDIsCiAgICAgICAgICBwcm9qZWN0UG9pbnQsCiAgICAgICAgICBvdXRlclBvc2l0aW9ucywKICAgICAgICAgIHN0Um90YXRpb24sCiAgICAgICAgICBzY3JhdGNoQlIKICAgICAgICApOwogICAgICAgIGNvbnN0IGdlb21ldHJpZXMgPSBbXTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBvbHlnb25zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBjb25zdCBnZW9tZXRyeUluc3RhbmNlID0gbmV3IEdlb21ldHJ5SW5zdGFuY2VfZGVmYXVsdCh7CiAgICAgICAgICAgIGdlb21ldHJ5OiBjcmVhdGVHZW9tZXRyeUZyb21Qb2x5Z29uKAogICAgICAgICAgICAgIHBvbHlnb25zW2ldLAogICAgICAgICAgICAgIHZlcnRleEZvcm1hdCwKICAgICAgICAgICAgICBib3VuZGluZ1JlY3RhbmdsZSwKICAgICAgICAgICAgICBzdFJvdGF0aW9uLAogICAgICAgICAgICAgIGhhc1RleHR1cmVDb29yZGluYXRlcyA/IHRleHR1cmVDb29yZGluYXRlUG9seWdvbnNbaV0gOiB2b2lkIDAsCiAgICAgICAgICAgICAgcHJvamVjdFBvaW50LAogICAgICAgICAgICAgIG5vcm1hbDIsCiAgICAgICAgICAgICAgdGFuZ2VudCwKICAgICAgICAgICAgICBiaXRhbmdlbnQKICAgICAgICAgICAgKQogICAgICAgICAgfSk7CiAgICAgICAgICBnZW9tZXRyaWVzLnB1c2goZ2VvbWV0cnlJbnN0YW5jZSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGdlb21ldHJ5ID0gR2VvbWV0cnlQaXBlbGluZV9kZWZhdWx0LmNvbWJpbmVJbnN0YW5jZXMoZ2VvbWV0cmllcylbMF07CiAgICAgICAgZ2VvbWV0cnkuYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMgPSBuZXcgRmxvYXQ2NEFycmF5KAogICAgICAgICAgZ2VvbWV0cnkuYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMKICAgICAgICApOwogICAgICAgIGdlb21ldHJ5LmluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLmxlbmd0aCAvIDMsCiAgICAgICAgICBnZW9tZXRyeS5pbmRpY2VzCiAgICAgICAgKTsKICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gZ2VvbWV0cnkuYXR0cmlidXRlczsKICAgICAgICBpZiAoIXZlcnRleEZvcm1hdC5wb3NpdGlvbikgewogICAgICAgICAgZGVsZXRlIGF0dHJpYnV0ZXMucG9zaXRpb247CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgICAgICBhdHRyaWJ1dGVzLAogICAgICAgICAgaW5kaWNlczogZ2VvbWV0cnkuaW5kaWNlcywKICAgICAgICAgIHByaW1pdGl2ZVR5cGU6IGdlb21ldHJ5LnByaW1pdGl2ZVR5cGUsCiAgICAgICAgICBib3VuZGluZ1NwaGVyZQogICAgICAgIH0pOwogICAgICB9OwogICAgICBDb3BsYW5hclBvbHlnb25HZW9tZXRyeV9kZWZhdWx0ID0gQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVDb3BsYW5hclBvbHlnb25HZW9tZXRyeS5qcwogIHZhciBjcmVhdGVDb3BsYW5hclBvbHlnb25HZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnlfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnlfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZUNvcGxhbmFyUG9seWdvbkdlb21ldHJ5KHBvbHlnb25HZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgcG9seWdvbkdlb21ldHJ5ID0gQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnlfZGVmYXVsdC51bnBhY2socG9seWdvbkdlb21ldHJ5LCBvZmZzZXQpOwogICAgfQogICAgcmV0dXJuIENvcGxhbmFyUG9seWdvbkdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkocG9seWdvbkdlb21ldHJ5KTsKICB9CiAgdmFyIGNyZWF0ZUNvcGxhbmFyUG9seWdvbkdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUNvcGxhbmFyUG9seWdvbkdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9Db3BsYW5hclBvbHlnb25HZW9tZXRyeSgpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgY3JlYXRlQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZUNvcGxhbmFyUG9seWdvbkdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gY3JlYXRlR2VvbWV0cnlGcm9tUG9zaXRpb25zKHBvc2l0aW9ucykgewogICAgY29uc3QgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgIGNvbnN0IGZsYXRQb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KGxlbmd0aCAqIDMpOwogICAgY29uc3QgaW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KGxlbmd0aCwgbGVuZ3RoICogMik7CiAgICBsZXQgcG9zaXRpb25JbmRleCA9IDA7CiAgICBsZXQgaW5kZXggPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBjb25zdCBwb3NpdGlvbiA9IHBvc2l0aW9uc1tpXTsKICAgICAgZmxhdFBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gcG9zaXRpb24ueDsKICAgICAgZmxhdFBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gcG9zaXRpb24ueTsKICAgICAgZmxhdFBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gcG9zaXRpb24uejsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGk7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSAoaSArIDEpICUgbGVuZ3RoOwogICAgfQogICAgY29uc3QgYXR0cmlidXRlcyA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZXNfZGVmYXVsdCh7CiAgICAgIHBvc2l0aW9uOiBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFLAogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgdmFsdWVzOiBmbGF0UG9zaXRpb25zCiAgICAgIH0pCiAgICB9KTsKICAgIHJldHVybiBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGluZGljZXMsCiAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5MSU5FUwogICAgfSk7CiAgfQogIGZ1bmN0aW9uIENvcGxhbmFyUG9seWdvbk91dGxpbmVHZW9tZXRyeShvcHRpb25zKSB7CiAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICBjb25zdCBwb2x5Z29uSGllcmFyY2h5ID0gb3B0aW9ucy5wb2x5Z29uSGllcmFyY2h5OwogICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJvcHRpb25zLnBvbHlnb25IaWVyYXJjaHkiLCBwb2x5Z29uSGllcmFyY2h5KTsKICAgIHRoaXMuX3BvbHlnb25IaWVyYXJjaHkgPSBwb2x5Z29uSGllcmFyY2h5OwogICAgdGhpcy5fd29ya2VyTmFtZSA9ICJjcmVhdGVDb3BsYW5hclBvbHlnb25PdXRsaW5lR2VvbWV0cnkiOwogICAgdGhpcy5wYWNrZWRMZW5ndGggPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZUhpZXJhcmNoeVBhY2tlZExlbmd0aCgKICAgICAgcG9seWdvbkhpZXJhcmNoeSwKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0CiAgICApICsgMTsKICB9CiAgdmFyIHNjcmF0Y2hPcHRpb25zOCwgQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Db3BsYW5hclBvbHlnb25PdXRsaW5lR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X2FycmF5UmVtb3ZlRHVwbGljYXRlcygpOwogICAgICBpbml0X0JvdW5kaW5nU3BoZXJlKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfQ29tcG9uZW50RGF0YXR5cGUoKTsKICAgICAgaW5pdF9Db3BsYW5hclBvbHlnb25HZW9tZXRyeUxpYnJhcnkoKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfR2VvbWV0cnkoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlcygpOwogICAgICBpbml0X0dlb21ldHJ5SW5zdGFuY2UoKTsKICAgICAgaW5pdF9HZW9tZXRyeVBpcGVsaW5lKCk7CiAgICAgIGluaXRfSW5kZXhEYXRhdHlwZSgpOwogICAgICBpbml0X1BvbHlnb25HZW9tZXRyeUxpYnJhcnkoKTsKICAgICAgaW5pdF9QcmltaXRpdmVUeXBlKCk7CiAgICAgIENvcGxhbmFyUG9seWdvbk91dGxpbmVHZW9tZXRyeS5mcm9tUG9zaXRpb25zID0gZnVuY3Rpb24ob3B0aW9ucykgewogICAgICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoIm9wdGlvbnMucG9zaXRpb25zIiwgb3B0aW9ucy5wb3NpdGlvbnMpOwogICAgICAgIGNvbnN0IG5ld09wdGlvbnMgPSB7CiAgICAgICAgICBwb2x5Z29uSGllcmFyY2h5OiB7CiAgICAgICAgICAgIHBvc2l0aW9uczogb3B0aW9ucy5wb3NpdGlvbnMKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHJldHVybiBuZXcgQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5KG5ld09wdGlvbnMpOwogICAgICB9OwogICAgICBDb3BsYW5hclBvbHlnb25PdXRsaW5lR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQucGFja1BvbHlnb25IaWVyYXJjaHkoCiAgICAgICAgICB2YWx1ZS5fcG9seWdvbkhpZXJhcmNoeSwKICAgICAgICAgIGFycmF5LAogICAgICAgICAgc3RhcnRpbmdJbmRleCwKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdAogICAgICAgICk7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleF0gPSB2YWx1ZS5wYWNrZWRMZW5ndGg7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBzY3JhdGNoT3B0aW9uczggPSB7CiAgICAgICAgcG9seWdvbkhpZXJhcmNoeToge30KICAgICAgfTsKICAgICAgQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5LnVucGFjayA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydGluZ0luZGV4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgY29uc3QgcG9seWdvbkhpZXJhcmNoeSA9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC51bnBhY2tQb2x5Z29uSGllcmFyY2h5KAogICAgICAgICAgYXJyYXksCiAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0CiAgICAgICAgKTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gcG9seWdvbkhpZXJhcmNoeS5zdGFydGluZ0luZGV4OwogICAgICAgIGRlbGV0ZSBwb2x5Z29uSGllcmFyY2h5LnN0YXJ0aW5nSW5kZXg7CiAgICAgICAgY29uc3QgcGFja2VkTGVuZ3RoID0gYXJyYXlbc3RhcnRpbmdJbmRleF07CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENvcGxhbmFyUG9seWdvbk91dGxpbmVHZW9tZXRyeShzY3JhdGNoT3B0aW9uczgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuX3BvbHlnb25IaWVyYXJjaHkgPSBwb2x5Z29uSGllcmFyY2h5OwogICAgICAgIHJlc3VsdC5wYWNrZWRMZW5ndGggPSBwYWNrZWRMZW5ndGg7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5LmNyZWF0ZUdlb21ldHJ5ID0gZnVuY3Rpb24ocG9seWdvbkdlb21ldHJ5KSB7CiAgICAgICAgY29uc3QgcG9seWdvbkhpZXJhcmNoeSA9IHBvbHlnb25HZW9tZXRyeS5fcG9seWdvbkhpZXJhcmNoeTsKICAgICAgICBsZXQgb3V0ZXJQb3NpdGlvbnMgPSBwb2x5Z29uSGllcmFyY2h5LnBvc2l0aW9uczsKICAgICAgICBvdXRlclBvc2l0aW9ucyA9IGFycmF5UmVtb3ZlRHVwbGljYXRlc19kZWZhdWx0KAogICAgICAgICAgb3V0ZXJQb3NpdGlvbnMsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbiwKICAgICAgICAgIHRydWUKICAgICAgICApOwogICAgICAgIGlmIChvdXRlclBvc2l0aW9ucy5sZW5ndGggPCAzKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IGlzVmFsaWQgPSBDb3BsYW5hclBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC52YWxpZE91dGxpbmUob3V0ZXJQb3NpdGlvbnMpOwogICAgICAgIGlmICghaXNWYWxpZCkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgY29uc3QgcG9seWdvbnMgPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQucG9seWdvbk91dGxpbmVzRnJvbUhpZXJhcmNoeSgKICAgICAgICAgIHBvbHlnb25IaWVyYXJjaHksCiAgICAgICAgICBmYWxzZQogICAgICAgICk7CiAgICAgICAgaWYgKHBvbHlnb25zLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgY29uc3QgZ2VvbWV0cmllcyA9IFtdOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9seWdvbnMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGNvbnN0IGdlb21ldHJ5SW5zdGFuY2UgPSBuZXcgR2VvbWV0cnlJbnN0YW5jZV9kZWZhdWx0KHsKICAgICAgICAgICAgZ2VvbWV0cnk6IGNyZWF0ZUdlb21ldHJ5RnJvbVBvc2l0aW9ucyhwb2x5Z29uc1tpXSkKICAgICAgICAgIH0pOwogICAgICAgICAgZ2VvbWV0cmllcy5wdXNoKGdlb21ldHJ5SW5zdGFuY2UpOwogICAgICAgIH0KICAgICAgICBjb25zdCBnZW9tZXRyeSA9IEdlb21ldHJ5UGlwZWxpbmVfZGVmYXVsdC5jb21iaW5lSW5zdGFuY2VzKGdlb21ldHJpZXMpWzBdOwogICAgICAgIGNvbnN0IGJvdW5kaW5nU3BoZXJlID0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5mcm9tUG9pbnRzKHBvbHlnb25IaWVyYXJjaHkucG9zaXRpb25zKTsKICAgICAgICByZXR1cm4gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgICAgYXR0cmlidXRlczogZ2VvbWV0cnkuYXR0cmlidXRlcywKICAgICAgICAgIGluZGljZXM6IGdlb21ldHJ5LmluZGljZXMsCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBnZW9tZXRyeS5wcmltaXRpdmVUeXBlLAogICAgICAgICAgYm91bmRpbmdTcGhlcmUKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQgPSBDb3BsYW5hclBvbHlnb25PdXRsaW5lR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVDb3BsYW5hclBvbHlnb25PdXRsaW5lR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChjcmVhdGVDb3BsYW5hclBvbHlnb25PdXRsaW5lR2VvbWV0cnlfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVDb3BsYW5hclBvbHlnb25PdXRsaW5lR2VvbWV0cnkocG9seWdvbkdlb21ldHJ5LCBvZmZzZXQpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob2Zmc2V0KSkgewogICAgICBwb2x5Z29uR2VvbWV0cnkgPSBDb3BsYW5hclBvbHlnb25PdXRsaW5lR2VvbWV0cnlfZGVmYXVsdC51bnBhY2soCiAgICAgICAgcG9seWdvbkdlb21ldHJ5LAogICAgICAgIG9mZnNldAogICAgICApOwogICAgfQogICAgcG9seWdvbkdlb21ldHJ5Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShwb2x5Z29uR2VvbWV0cnkuX2VsbGlwc29pZCk7CiAgICByZXR1cm4gQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkocG9seWdvbkdlb21ldHJ5KTsKICB9CiAgdmFyIGNyZWF0ZUNvcGxhbmFyUG9seWdvbk91dGxpbmVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X2NyZWF0ZUNvcGxhbmFyUG9seWdvbk91dGxpbmVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9Db3BsYW5hclBvbHlnb25PdXRsaW5lR2VvbWV0cnkoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGNyZWF0ZUNvcGxhbmFyUG9seWdvbk91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gY3JlYXRlQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ29ybmVyVHlwZS5qcwogIHZhciBDb3JuZXJUeXBlLCBDb3JuZXJUeXBlX2RlZmF1bHQ7CiAgdmFyIGluaXRfQ29ybmVyVHlwZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ29ybmVyVHlwZS5qcyIoKSB7CiAgICAgIENvcm5lclR5cGUgPSB7CiAgICAgICAgLyoqCiAgICAgICAgICogPGltZyBzcmM9IkltYWdlcy9Db3JuZXJUeXBlUm91bmRlZC5wbmciIHN0eWxlPSJ2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlOyIgd2lkdGg9IjE4NiIgaGVpZ2h0PSIxODkiIC8+CiAgICAgICAgICoKICAgICAgICAgKiBDb3JuZXIgaGFzIGEgc21vb3RoIGVkZ2UuCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBST1VOREVEOiAwLAogICAgICAgIC8qKgogICAgICAgICAqIDxpbWcgc3JjPSJJbWFnZXMvQ29ybmVyVHlwZU1pdGVyZWQucG5nIiBzdHlsZT0idmVydGljYWwtYWxpZ246IG1pZGRsZTsiIHdpZHRoPSIxODYiIGhlaWdodD0iMTg5IiAvPgogICAgICAgICAqCiAgICAgICAgICogQ29ybmVyIHBvaW50IGlzIHRoZSBpbnRlcnNlY3Rpb24gb2YgYWRqYWNlbnQgZWRnZXMuCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBNSVRFUkVEOiAxLAogICAgICAgIC8qKgogICAgICAgICAqIDxpbWcgc3JjPSJJbWFnZXMvQ29ybmVyVHlwZUJldmVsZWQucG5nIiBzdHlsZT0idmVydGljYWwtYWxpZ246IG1pZGRsZTsiIHdpZHRoPSIxODYiIGhlaWdodD0iMTg5IiAvPgogICAgICAgICAqCiAgICAgICAgICogQ29ybmVyIGlzIGNsaXBwZWQuCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBCRVZFTEVEOiAyCiAgICAgIH07CiAgICAgIENvcm5lclR5cGVfZGVmYXVsdCA9IE9iamVjdC5mcmVlemUoQ29ybmVyVHlwZSk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9FbGxpcHNvaWRHZW9kZXNpYy5qcwogIGZ1bmN0aW9uIHNldENvbnN0YW50cyhlbGxpcHNvaWRHZW9kZXNpYzIpIHsKICAgIGNvbnN0IHVTcXVhcmVkID0gZWxsaXBzb2lkR2VvZGVzaWMyLl91U3F1YXJlZDsKICAgIGNvbnN0IGEzID0gZWxsaXBzb2lkR2VvZGVzaWMyLl9lbGxpcHNvaWQubWF4aW11bVJhZGl1czsKICAgIGNvbnN0IGIgPSBlbGxpcHNvaWRHZW9kZXNpYzIuX2VsbGlwc29pZC5taW5pbXVtUmFkaXVzOwogICAgY29uc3QgZiA9IChhMyAtIGIpIC8gYTM7CiAgICBjb25zdCBjb3NpbmVIZWFkaW5nID0gTWF0aC5jb3MoZWxsaXBzb2lkR2VvZGVzaWMyLl9zdGFydEhlYWRpbmcpOwogICAgY29uc3Qgc2luZUhlYWRpbmcgPSBNYXRoLnNpbihlbGxpcHNvaWRHZW9kZXNpYzIuX3N0YXJ0SGVhZGluZyk7CiAgICBjb25zdCB0YW5VID0gKDEgLSBmKSAqIE1hdGgudGFuKGVsbGlwc29pZEdlb2Rlc2ljMi5fc3RhcnQubGF0aXR1ZGUpOwogICAgY29uc3QgY29zaW5lVSA9IDEgLyBNYXRoLnNxcnQoMSArIHRhblUgKiB0YW5VKTsKICAgIGNvbnN0IHNpbmVVID0gY29zaW5lVSAqIHRhblU7CiAgICBjb25zdCBzaWdtYSA9IE1hdGguYXRhbjIodGFuVSwgY29zaW5lSGVhZGluZyk7CiAgICBjb25zdCBzaW5lQWxwaGEgPSBjb3NpbmVVICogc2luZUhlYWRpbmc7CiAgICBjb25zdCBzaW5lU3F1YXJlZEFscGhhID0gc2luZUFscGhhICogc2luZUFscGhhOwogICAgY29uc3QgY29zaW5lU3F1YXJlZEFscGhhID0gMSAtIHNpbmVTcXVhcmVkQWxwaGE7CiAgICBjb25zdCBjb3NpbmVBbHBoYSA9IE1hdGguc3FydChjb3NpbmVTcXVhcmVkQWxwaGEpOwogICAgY29uc3QgdTJPdmVyNCA9IHVTcXVhcmVkIC8gNDsKICAgIGNvbnN0IHU0T3ZlcjE2ID0gdTJPdmVyNCAqIHUyT3ZlcjQ7CiAgICBjb25zdCB1Nk92ZXI2NCA9IHU0T3ZlcjE2ICogdTJPdmVyNDsKICAgIGNvbnN0IHU4T3ZlcjI1NiA9IHU0T3ZlcjE2ICogdTRPdmVyMTY7CiAgICBjb25zdCBhMCA9IDEgKyB1Mk92ZXI0IC0gMyAqIHU0T3ZlcjE2IC8gNCArIDUgKiB1Nk92ZXI2NCAvIDQgLSAxNzUgKiB1OE92ZXIyNTYgLyA2NDsKICAgIGNvbnN0IGExID0gMSAtIHUyT3ZlcjQgKyAxNSAqIHU0T3ZlcjE2IC8gOCAtIDM1ICogdTZPdmVyNjQgLyA4OwogICAgY29uc3QgYTIyID0gMSAtIDMgKiB1Mk92ZXI0ICsgMzUgKiB1NE92ZXIxNiAvIDQ7CiAgICBjb25zdCBhMzIgPSAxIC0gNSAqIHUyT3ZlcjQ7CiAgICBjb25zdCBkaXN0YW5jZVJhdGlvID0gYTAgKiBzaWdtYSAtIGExICogTWF0aC5zaW4oMiAqIHNpZ21hKSAqIHUyT3ZlcjQgLyAyIC0gYTIyICogTWF0aC5zaW4oNCAqIHNpZ21hKSAqIHU0T3ZlcjE2IC8gMTYgLSBhMzIgKiBNYXRoLnNpbig2ICogc2lnbWEpICogdTZPdmVyNjQgLyA0OCAtIE1hdGguc2luKDggKiBzaWdtYSkgKiA1ICogdThPdmVyMjU2IC8gNTEyOwogICAgY29uc3QgY29uc3RhbnRzID0gZWxsaXBzb2lkR2VvZGVzaWMyLl9jb25zdGFudHM7CiAgICBjb25zdGFudHMuYSA9IGEzOwogICAgY29uc3RhbnRzLmIgPSBiOwogICAgY29uc3RhbnRzLmYgPSBmOwogICAgY29uc3RhbnRzLmNvc2luZUhlYWRpbmcgPSBjb3NpbmVIZWFkaW5nOwogICAgY29uc3RhbnRzLnNpbmVIZWFkaW5nID0gc2luZUhlYWRpbmc7CiAgICBjb25zdGFudHMudGFuVSA9IHRhblU7CiAgICBjb25zdGFudHMuY29zaW5lVSA9IGNvc2luZVU7CiAgICBjb25zdGFudHMuc2luZVUgPSBzaW5lVTsKICAgIGNvbnN0YW50cy5zaWdtYSA9IHNpZ21hOwogICAgY29uc3RhbnRzLnNpbmVBbHBoYSA9IHNpbmVBbHBoYTsKICAgIGNvbnN0YW50cy5zaW5lU3F1YXJlZEFscGhhID0gc2luZVNxdWFyZWRBbHBoYTsKICAgIGNvbnN0YW50cy5jb3NpbmVTcXVhcmVkQWxwaGEgPSBjb3NpbmVTcXVhcmVkQWxwaGE7CiAgICBjb25zdGFudHMuY29zaW5lQWxwaGEgPSBjb3NpbmVBbHBoYTsKICAgIGNvbnN0YW50cy51Mk92ZXI0ID0gdTJPdmVyNDsKICAgIGNvbnN0YW50cy51NE92ZXIxNiA9IHU0T3ZlcjE2OwogICAgY29uc3RhbnRzLnU2T3ZlcjY0ID0gdTZPdmVyNjQ7CiAgICBjb25zdGFudHMudThPdmVyMjU2ID0gdThPdmVyMjU2OwogICAgY29uc3RhbnRzLmEwID0gYTA7CiAgICBjb25zdGFudHMuYTEgPSBhMTsKICAgIGNvbnN0YW50cy5hMiA9IGEyMjsKICAgIGNvbnN0YW50cy5hMyA9IGEzMjsKICAgIGNvbnN0YW50cy5kaXN0YW5jZVJhdGlvID0gZGlzdGFuY2VSYXRpbzsKICB9CiAgZnVuY3Rpb24gY29tcHV0ZUMoZiwgY29zaW5lU3F1YXJlZEFscGhhKSB7CiAgICByZXR1cm4gZiAqIGNvc2luZVNxdWFyZWRBbHBoYSAqICg0ICsgZiAqICg0IC0gMyAqIGNvc2luZVNxdWFyZWRBbHBoYSkpIC8gMTY7CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVEZWx0YUxhbWJkYShmLCBzaW5lQWxwaGEsIGNvc2luZVNxdWFyZWRBbHBoYSwgc2lnbWEsIHNpbmVTaWdtYSwgY29zaW5lU2lnbWEsIGNvc2luZVR3aWNlU2lnbWFNaWRwb2ludCkgewogICAgY29uc3QgQyA9IGNvbXB1dGVDKGYsIGNvc2luZVNxdWFyZWRBbHBoYSk7CiAgICByZXR1cm4gKDEgLSBDKSAqIGYgKiBzaW5lQWxwaGEgKiAoc2lnbWEgKyBDICogc2luZVNpZ21hICogKGNvc2luZVR3aWNlU2lnbWFNaWRwb2ludCArIEMgKiBjb3NpbmVTaWdtYSAqICgyICogY29zaW5lVHdpY2VTaWdtYU1pZHBvaW50ICogY29zaW5lVHdpY2VTaWdtYU1pZHBvaW50IC0gMSkpKTsKICB9CiAgZnVuY3Rpb24gdmluY2VudHlJbnZlcnNlRm9ybXVsYShlbGxpcHNvaWRHZW9kZXNpYzIsIG1ham9yLCBtaW5vciwgZmlyc3RMb25naXR1ZGUsIGZpcnN0TGF0aXR1ZGUsIHNlY29uZExvbmdpdHVkZSwgc2Vjb25kTGF0aXR1ZGUpIHsKICAgIGNvbnN0IGVmZiA9IChtYWpvciAtIG1pbm9yKSAvIG1ham9yOwogICAgY29uc3QgbCA9IHNlY29uZExvbmdpdHVkZSAtIGZpcnN0TG9uZ2l0dWRlOwogICAgY29uc3QgdTEyID0gTWF0aC5hdGFuKCgxIC0gZWZmKSAqIE1hdGgudGFuKGZpcnN0TGF0aXR1ZGUpKTsKICAgIGNvbnN0IHUyMiA9IE1hdGguYXRhbigoMSAtIGVmZikgKiBNYXRoLnRhbihzZWNvbmRMYXRpdHVkZSkpOwogICAgY29uc3QgY29zaW5lVTEgPSBNYXRoLmNvcyh1MTIpOwogICAgY29uc3Qgc2luZVUxID0gTWF0aC5zaW4odTEyKTsKICAgIGNvbnN0IGNvc2luZVUyID0gTWF0aC5jb3ModTIyKTsKICAgIGNvbnN0IHNpbmVVMiA9IE1hdGguc2luKHUyMik7CiAgICBjb25zdCBjYyA9IGNvc2luZVUxICogY29zaW5lVTI7CiAgICBjb25zdCBjcyA9IGNvc2luZVUxICogc2luZVUyOwogICAgY29uc3Qgc3MgPSBzaW5lVTEgKiBzaW5lVTI7CiAgICBjb25zdCBzYyA9IHNpbmVVMSAqIGNvc2luZVUyOwogICAgbGV0IGxhbWJkYSA9IGw7CiAgICBsZXQgbGFtYmRhRG90ID0gTWF0aF9kZWZhdWx0LlRXT19QSTsKICAgIGxldCBjb3NpbmVMYW1iZGEgPSBNYXRoLmNvcyhsYW1iZGEpOwogICAgbGV0IHNpbmVMYW1iZGEgPSBNYXRoLnNpbihsYW1iZGEpOwogICAgbGV0IHNpZ21hOwogICAgbGV0IGNvc2luZVNpZ21hOwogICAgbGV0IHNpbmVTaWdtYTsKICAgIGxldCBjb3NpbmVTcXVhcmVkQWxwaGE7CiAgICBsZXQgY29zaW5lVHdpY2VTaWdtYU1pZHBvaW50OwogICAgZG8gewogICAgICBjb3NpbmVMYW1iZGEgPSBNYXRoLmNvcyhsYW1iZGEpOwogICAgICBzaW5lTGFtYmRhID0gTWF0aC5zaW4obGFtYmRhKTsKICAgICAgY29uc3QgdGVtcCA9IGNzIC0gc2MgKiBjb3NpbmVMYW1iZGE7CiAgICAgIHNpbmVTaWdtYSA9IE1hdGguc3FydCgKICAgICAgICBjb3NpbmVVMiAqIGNvc2luZVUyICogc2luZUxhbWJkYSAqIHNpbmVMYW1iZGEgKyB0ZW1wICogdGVtcAogICAgICApOwogICAgICBjb3NpbmVTaWdtYSA9IHNzICsgY2MgKiBjb3NpbmVMYW1iZGE7CiAgICAgIHNpZ21hID0gTWF0aC5hdGFuMihzaW5lU2lnbWEsIGNvc2luZVNpZ21hKTsKICAgICAgbGV0IHNpbmVBbHBoYTsKICAgICAgaWYgKHNpbmVTaWdtYSA9PT0gMCkgewogICAgICAgIHNpbmVBbHBoYSA9IDA7CiAgICAgICAgY29zaW5lU3F1YXJlZEFscGhhID0gMTsKICAgICAgfSBlbHNlIHsKICAgICAgICBzaW5lQWxwaGEgPSBjYyAqIHNpbmVMYW1iZGEgLyBzaW5lU2lnbWE7CiAgICAgICAgY29zaW5lU3F1YXJlZEFscGhhID0gMSAtIHNpbmVBbHBoYSAqIHNpbmVBbHBoYTsKICAgICAgfQogICAgICBsYW1iZGFEb3QgPSBsYW1iZGE7CiAgICAgIGNvc2luZVR3aWNlU2lnbWFNaWRwb2ludCA9IGNvc2luZVNpZ21hIC0gMiAqIHNzIC8gY29zaW5lU3F1YXJlZEFscGhhOwogICAgICBpZiAoIWlzRmluaXRlKGNvc2luZVR3aWNlU2lnbWFNaWRwb2ludCkpIHsKICAgICAgICBjb3NpbmVUd2ljZVNpZ21hTWlkcG9pbnQgPSAwOwogICAgICB9CiAgICAgIGxhbWJkYSA9IGwgKyBjb21wdXRlRGVsdGFMYW1iZGEoCiAgICAgICAgZWZmLAogICAgICAgIHNpbmVBbHBoYSwKICAgICAgICBjb3NpbmVTcXVhcmVkQWxwaGEsCiAgICAgICAgc2lnbWEsCiAgICAgICAgc2luZVNpZ21hLAogICAgICAgIGNvc2luZVNpZ21hLAogICAgICAgIGNvc2luZVR3aWNlU2lnbWFNaWRwb2ludAogICAgICApOwogICAgfSB3aGlsZSAoTWF0aC5hYnMobGFtYmRhIC0gbGFtYmRhRG90KSA+IE1hdGhfZGVmYXVsdC5FUFNJTE9OMTIpOwogICAgY29uc3QgdVNxdWFyZWQgPSBjb3NpbmVTcXVhcmVkQWxwaGEgKiAobWFqb3IgKiBtYWpvciAtIG1pbm9yICogbWlub3IpIC8gKG1pbm9yICogbWlub3IpOwogICAgY29uc3QgQSA9IDEgKyB1U3F1YXJlZCAqICg0MDk2ICsgdVNxdWFyZWQgKiAodVNxdWFyZWQgKiAoMzIwIC0gMTc1ICogdVNxdWFyZWQpIC0gNzY4KSkgLyAxNjM4NDsKICAgIGNvbnN0IEIgPSB1U3F1YXJlZCAqICgyNTYgKyB1U3F1YXJlZCAqICh1U3F1YXJlZCAqICg3NCAtIDQ3ICogdVNxdWFyZWQpIC0gMTI4KSkgLyAxMDI0OwogICAgY29uc3QgY29zaW5lU3F1YXJlZFR3aWNlU2lnbWFNaWRwb2ludCA9IGNvc2luZVR3aWNlU2lnbWFNaWRwb2ludCAqIGNvc2luZVR3aWNlU2lnbWFNaWRwb2ludDsKICAgIGNvbnN0IGRlbHRhU2lnbWEgPSBCICogc2luZVNpZ21hICogKGNvc2luZVR3aWNlU2lnbWFNaWRwb2ludCArIEIgKiAoY29zaW5lU2lnbWEgKiAoMiAqIGNvc2luZVNxdWFyZWRUd2ljZVNpZ21hTWlkcG9pbnQgLSAxKSAtIEIgKiBjb3NpbmVUd2ljZVNpZ21hTWlkcG9pbnQgKiAoNCAqIHNpbmVTaWdtYSAqIHNpbmVTaWdtYSAtIDMpICogKDQgKiBjb3NpbmVTcXVhcmVkVHdpY2VTaWdtYU1pZHBvaW50IC0gMykgLyA2KSAvIDQpOwogICAgY29uc3QgZGlzdGFuY2UgPSBtaW5vciAqIEEgKiAoc2lnbWEgLSBkZWx0YVNpZ21hKTsKICAgIGNvbnN0IHN0YXJ0SGVhZGluZyA9IE1hdGguYXRhbjIoCiAgICAgIGNvc2luZVUyICogc2luZUxhbWJkYSwKICAgICAgY3MgLSBzYyAqIGNvc2luZUxhbWJkYQogICAgKTsKICAgIGNvbnN0IGVuZEhlYWRpbmcgPSBNYXRoLmF0YW4yKGNvc2luZVUxICogc2luZUxhbWJkYSwgY3MgKiBjb3NpbmVMYW1iZGEgLSBzYyk7CiAgICBlbGxpcHNvaWRHZW9kZXNpYzIuX2Rpc3RhbmNlID0gZGlzdGFuY2U7CiAgICBlbGxpcHNvaWRHZW9kZXNpYzIuX3N0YXJ0SGVhZGluZyA9IHN0YXJ0SGVhZGluZzsKICAgIGVsbGlwc29pZEdlb2Rlc2ljMi5fZW5kSGVhZGluZyA9IGVuZEhlYWRpbmc7CiAgICBlbGxpcHNvaWRHZW9kZXNpYzIuX3VTcXVhcmVkID0gdVNxdWFyZWQ7CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVQcm9wZXJ0aWVzMihlbGxpcHNvaWRHZW9kZXNpYzIsIHN0YXJ0LCBlbmQsIGVsbGlwc29pZCkgewogICAgY29uc3QgZmlyc3RDYXJ0ZXNpYW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oc3RhcnQsIHNjcmF0Y2hDYXJ0MjIpLAogICAgICBzY3JhdGNoQ2FydDEyCiAgICApOwogICAgY29uc3QgbGFzdENhcnRlc2lhbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgIGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbihlbmQsIHNjcmF0Y2hDYXJ0MjIpLAogICAgICBzY3JhdGNoQ2FydDIyCiAgICApOwogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoCiAgICAgICJ2YWx1ZSIsCiAgICAgIE1hdGguYWJzKAogICAgICAgIE1hdGguYWJzKENhcnRlc2lhbjNfZGVmYXVsdC5hbmdsZUJldHdlZW4oZmlyc3RDYXJ0ZXNpYW4sIGxhc3RDYXJ0ZXNpYW4pKSAtIE1hdGguUEkKICAgICAgKSwKICAgICAgMC4wMTI1CiAgICApOwogICAgdmluY2VudHlJbnZlcnNlRm9ybXVsYSgKICAgICAgZWxsaXBzb2lkR2VvZGVzaWMyLAogICAgICBlbGxpcHNvaWQubWF4aW11bVJhZGl1cywKICAgICAgZWxsaXBzb2lkLm1pbmltdW1SYWRpdXMsCiAgICAgIHN0YXJ0LmxvbmdpdHVkZSwKICAgICAgc3RhcnQubGF0aXR1ZGUsCiAgICAgIGVuZC5sb25naXR1ZGUsCiAgICAgIGVuZC5sYXRpdHVkZQogICAgKTsKICAgIGVsbGlwc29pZEdlb2Rlc2ljMi5fc3RhcnQgPSBDYXJ0b2dyYXBoaWNfZGVmYXVsdC5jbG9uZSgKICAgICAgc3RhcnQsCiAgICAgIGVsbGlwc29pZEdlb2Rlc2ljMi5fc3RhcnQKICAgICk7CiAgICBlbGxpcHNvaWRHZW9kZXNpYzIuX2VuZCA9IENhcnRvZ3JhcGhpY19kZWZhdWx0LmNsb25lKGVuZCwgZWxsaXBzb2lkR2VvZGVzaWMyLl9lbmQpOwogICAgZWxsaXBzb2lkR2VvZGVzaWMyLl9zdGFydC5oZWlnaHQgPSAwOwogICAgZWxsaXBzb2lkR2VvZGVzaWMyLl9lbmQuaGVpZ2h0ID0gMDsKICAgIHNldENvbnN0YW50cyhlbGxpcHNvaWRHZW9kZXNpYzIpOwogIH0KICBmdW5jdGlvbiBFbGxpcHNvaWRHZW9kZXNpYyhzdGFydCwgZW5kLCBlbGxpcHNvaWQpIHsKICAgIGNvbnN0IGUgPSBlbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgIHRoaXMuX2VsbGlwc29pZCA9IGU7CiAgICB0aGlzLl9zdGFydCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgdGhpcy5fZW5kID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICB0aGlzLl9jb25zdGFudHMgPSB7fTsKICAgIHRoaXMuX3N0YXJ0SGVhZGluZyA9IHZvaWQgMDsKICAgIHRoaXMuX2VuZEhlYWRpbmcgPSB2b2lkIDA7CiAgICB0aGlzLl9kaXN0YW5jZSA9IHZvaWQgMDsKICAgIHRoaXMuX3VTcXVhcmVkID0gdm9pZCAwOwogICAgaWYgKGRlZmluZWRfZGVmYXVsdChzdGFydCkgJiYgZGVmaW5lZF9kZWZhdWx0KGVuZCkpIHsKICAgICAgY29tcHV0ZVByb3BlcnRpZXMyKHRoaXMsIHN0YXJ0LCBlbmQsIGUpOwogICAgfQogIH0KICB2YXIgc2NyYXRjaENhcnQxMiwgc2NyYXRjaENhcnQyMiwgRWxsaXBzb2lkR2VvZGVzaWNfZGVmYXVsdDsKICB2YXIgaW5pdF9FbGxpcHNvaWRHZW9kZXNpYyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvRWxsaXBzb2lkR2VvZGVzaWMuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DYXJ0b2dyYXBoaWMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIHNjcmF0Y2hDYXJ0MTIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0MjIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKEVsbGlwc29pZEdlb2Rlc2ljLnByb3RvdHlwZSwgewogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIGVsbGlwc29pZC4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkR2VvZGVzaWMucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge0VsbGlwc29pZH0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBlbGxpcHNvaWQ6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9lbGxpcHNvaWQ7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBzdXJmYWNlIGRpc3RhbmNlIGJldHdlZW4gdGhlIHN0YXJ0IGFuZCBlbmQgcG9pbnQKICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkR2VvZGVzaWMucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBzdXJmYWNlRGlzdGFuY2U6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiZGlzdGFuY2UiLCB0aGlzLl9kaXN0YW5jZSk7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kaXN0YW5jZTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIGluaXRpYWwgcGxhbmV0b2RldGljIHBvaW50IG9uIHRoZSBwYXRoLgogICAgICAgICAqIEBtZW1iZXJvZiBFbGxpcHNvaWRHZW9kZXNpYy5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7Q2FydG9ncmFwaGljfQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIHN0YXJ0OiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fc3RhcnQ7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBmaW5hbCBwbGFuZXRvZGV0aWMgcG9pbnQgb24gdGhlIHBhdGguCiAgICAgICAgICogQG1lbWJlcm9mIEVsbGlwc29pZEdlb2Rlc2ljLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtDYXJ0b2dyYXBoaWN9CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgZW5kOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fZW5kOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgaGVhZGluZyBhdCB0aGUgaW5pdGlhbCBwb2ludC4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkR2VvZGVzaWMucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBzdGFydEhlYWRpbmc6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiZGlzdGFuY2UiLCB0aGlzLl9kaXN0YW5jZSk7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9zdGFydEhlYWRpbmc7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBoZWFkaW5nIGF0IHRoZSBmaW5hbCBwb2ludC4KICAgICAgICAgKiBAbWVtYmVyb2YgRWxsaXBzb2lkR2VvZGVzaWMucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBlbmRIZWFkaW5nOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImRpc3RhbmNlIiwgdGhpcy5fZGlzdGFuY2UpOwogICAgICAgICAgICByZXR1cm4gdGhpcy5fZW5kSGVhZGluZzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBFbGxpcHNvaWRHZW9kZXNpYy5wcm90b3R5cGUuc2V0RW5kUG9pbnRzID0gZnVuY3Rpb24oc3RhcnQsIGVuZCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgic3RhcnQiLCBzdGFydCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJlbmQiLCBlbmQpOwogICAgICAgIGNvbXB1dGVQcm9wZXJ0aWVzMih0aGlzLCBzdGFydCwgZW5kLCB0aGlzLl9lbGxpcHNvaWQpOwogICAgICB9OwogICAgICBFbGxpcHNvaWRHZW9kZXNpYy5wcm90b3R5cGUuaW50ZXJwb2xhdGVVc2luZ0ZyYWN0aW9uID0gZnVuY3Rpb24oZnJhY3Rpb24sIHJlc3VsdCkgewogICAgICAgIHJldHVybiB0aGlzLmludGVycG9sYXRlVXNpbmdTdXJmYWNlRGlzdGFuY2UoCiAgICAgICAgICB0aGlzLl9kaXN0YW5jZSAqIGZyYWN0aW9uLAogICAgICAgICAgcmVzdWx0CiAgICAgICAgKTsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkR2VvZGVzaWMucHJvdG90eXBlLmludGVycG9sYXRlVXNpbmdTdXJmYWNlRGlzdGFuY2UgPSBmdW5jdGlvbihkaXN0YW5jZSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJkaXN0YW5jZSIsIHRoaXMuX2Rpc3RhbmNlKTsKICAgICAgICBjb25zdCBjb25zdGFudHMgPSB0aGlzLl9jb25zdGFudHM7CiAgICAgICAgY29uc3QgcyA9IGNvbnN0YW50cy5kaXN0YW5jZVJhdGlvICsgZGlzdGFuY2UgLyBjb25zdGFudHMuYjsKICAgICAgICBjb25zdCBjb3NpbmUyUyA9IE1hdGguY29zKDIgKiBzKTsKICAgICAgICBjb25zdCBjb3NpbmU0UyA9IE1hdGguY29zKDQgKiBzKTsKICAgICAgICBjb25zdCBjb3NpbmU2UyA9IE1hdGguY29zKDYgKiBzKTsKICAgICAgICBjb25zdCBzaW5lMlMgPSBNYXRoLnNpbigyICogcyk7CiAgICAgICAgY29uc3Qgc2luZTRTID0gTWF0aC5zaW4oNCAqIHMpOwogICAgICAgIGNvbnN0IHNpbmU2UyA9IE1hdGguc2luKDYgKiBzKTsKICAgICAgICBjb25zdCBzaW5lOFMgPSBNYXRoLnNpbig4ICogcyk7CiAgICAgICAgY29uc3QgczIgPSBzICogczsKICAgICAgICBjb25zdCBzMyA9IHMgKiBzMjsKICAgICAgICBjb25zdCB1OE92ZXIyNTYgPSBjb25zdGFudHMudThPdmVyMjU2OwogICAgICAgIGNvbnN0IHUyT3ZlcjQgPSBjb25zdGFudHMudTJPdmVyNDsKICAgICAgICBjb25zdCB1Nk92ZXI2NCA9IGNvbnN0YW50cy51Nk92ZXI2NDsKICAgICAgICBjb25zdCB1NE92ZXIxNiA9IGNvbnN0YW50cy51NE92ZXIxNjsKICAgICAgICBsZXQgc2lnbWEgPSAyICogczMgKiB1OE92ZXIyNTYgKiBjb3NpbmUyUyAvIDMgKyBzICogKDEgLSB1Mk92ZXI0ICsgNyAqIHU0T3ZlcjE2IC8gNCAtIDE1ICogdTZPdmVyNjQgLyA0ICsgNTc5ICogdThPdmVyMjU2IC8gNjQgLSAodTRPdmVyMTYgLSAxNSAqIHU2T3ZlcjY0IC8gNCArIDE4NyAqIHU4T3ZlcjI1NiAvIDE2KSAqIGNvc2luZTJTIC0gKDUgKiB1Nk92ZXI2NCAvIDQgLSAxMTUgKiB1OE92ZXIyNTYgLyAxNikgKiBjb3NpbmU0UyAtIDI5ICogdThPdmVyMjU2ICogY29zaW5lNlMgLyAxNikgKyAodTJPdmVyNCAvIDIgLSB1NE92ZXIxNiArIDcxICogdTZPdmVyNjQgLyAzMiAtIDg1ICogdThPdmVyMjU2IC8gMTYpICogc2luZTJTICsgKDUgKiB1NE92ZXIxNiAvIDE2IC0gNSAqIHU2T3ZlcjY0IC8gNCArIDM4MyAqIHU4T3ZlcjI1NiAvIDk2KSAqIHNpbmU0UyAtIHMyICogKCh1Nk92ZXI2NCAtIDExICogdThPdmVyMjU2IC8gMikgKiBzaW5lMlMgKyA1ICogdThPdmVyMjU2ICogc2luZTRTIC8gMikgKyAoMjkgKiB1Nk92ZXI2NCAvIDk2IC0gMjkgKiB1OE92ZXIyNTYgLyAxNikgKiBzaW5lNlMgKyA1MzkgKiB1OE92ZXIyNTYgKiBzaW5lOFMgLyAxNTM2OwogICAgICAgIGNvbnN0IHRoZXRhID0gTWF0aC5hc2luKE1hdGguc2luKHNpZ21hKSAqIGNvbnN0YW50cy5jb3NpbmVBbHBoYSk7CiAgICAgICAgY29uc3QgbGF0aXR1ZGUgPSBNYXRoLmF0YW4oY29uc3RhbnRzLmEgLyBjb25zdGFudHMuYiAqIE1hdGgudGFuKHRoZXRhKSk7CiAgICAgICAgc2lnbWEgPSBzaWdtYSAtIGNvbnN0YW50cy5zaWdtYTsKICAgICAgICBjb25zdCBjb3NpbmVUd2ljZVNpZ21hTWlkcG9pbnQgPSBNYXRoLmNvcygyICogY29uc3RhbnRzLnNpZ21hICsgc2lnbWEpOwogICAgICAgIGNvbnN0IHNpbmVTaWdtYSA9IE1hdGguc2luKHNpZ21hKTsKICAgICAgICBjb25zdCBjb3NpbmVTaWdtYSA9IE1hdGguY29zKHNpZ21hKTsKICAgICAgICBjb25zdCBjYyA9IGNvbnN0YW50cy5jb3NpbmVVICogY29zaW5lU2lnbWE7CiAgICAgICAgY29uc3Qgc3MgPSBjb25zdGFudHMuc2luZVUgKiBzaW5lU2lnbWE7CiAgICAgICAgY29uc3QgbGFtYmRhID0gTWF0aC5hdGFuMigKICAgICAgICAgIHNpbmVTaWdtYSAqIGNvbnN0YW50cy5zaW5lSGVhZGluZywKICAgICAgICAgIGNjIC0gc3MgKiBjb25zdGFudHMuY29zaW5lSGVhZGluZwogICAgICAgICk7CiAgICAgICAgY29uc3QgbCA9IGxhbWJkYSAtIGNvbXB1dGVEZWx0YUxhbWJkYSgKICAgICAgICAgIGNvbnN0YW50cy5mLAogICAgICAgICAgY29uc3RhbnRzLnNpbmVBbHBoYSwKICAgICAgICAgIGNvbnN0YW50cy5jb3NpbmVTcXVhcmVkQWxwaGEsCiAgICAgICAgICBzaWdtYSwKICAgICAgICAgIHNpbmVTaWdtYSwKICAgICAgICAgIGNvc2luZVNpZ21hLAogICAgICAgICAgY29zaW5lVHdpY2VTaWdtYU1pZHBvaW50CiAgICAgICAgKTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdC5sb25naXR1ZGUgPSB0aGlzLl9zdGFydC5sb25naXR1ZGUgKyBsOwogICAgICAgICAgcmVzdWx0LmxhdGl0dWRlID0gbGF0aXR1ZGU7CiAgICAgICAgICByZXN1bHQuaGVpZ2h0ID0gMDsKICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQodGhpcy5fc3RhcnQubG9uZ2l0dWRlICsgbCwgbGF0aXR1ZGUsIDApOwogICAgICB9OwogICAgICBFbGxpcHNvaWRHZW9kZXNpY19kZWZhdWx0ID0gRWxsaXBzb2lkR2VvZGVzaWM7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Qb2x5bGluZVBpcGVsaW5lLmpzCiAgZnVuY3Rpb24gc3ViZGl2aWRlSGVpZ2h0cyhudW1Qb2ludHMsIGgwLCBoMSkgewogICAgY29uc3QgaGVpZ2h0cyA9IHN1YmRpdmlkZUhlaWdodHNTY3JhdGNoQXJyYXk7CiAgICBoZWlnaHRzLmxlbmd0aCA9IG51bVBvaW50czsKICAgIGxldCBpOwogICAgaWYgKGgwID09PSBoMSkgewogICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtUG9pbnRzOyBpKyspIHsKICAgICAgICBoZWlnaHRzW2ldID0gaDA7CiAgICAgIH0KICAgICAgcmV0dXJuIGhlaWdodHM7CiAgICB9CiAgICBjb25zdCBkSGVpZ2h0ID0gaDEgLSBoMDsKICAgIGNvbnN0IGhlaWdodFBlclZlcnRleCA9IGRIZWlnaHQgLyBudW1Qb2ludHM7CiAgICBmb3IgKGkgPSAwOyBpIDwgbnVtUG9pbnRzOyBpKyspIHsKICAgICAgY29uc3QgaCA9IGgwICsgaSAqIGhlaWdodFBlclZlcnRleDsKICAgICAgaGVpZ2h0c1tpXSA9IGg7CiAgICB9CiAgICByZXR1cm4gaGVpZ2h0czsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVDYXJ0ZXNpYW5BcmMocDAsIHAxLCBtaW5EaXN0YW5jZSwgZWxsaXBzb2lkLCBoMCwgaDEsIGFycmF5LCBvZmZzZXQpIHsKICAgIGNvbnN0IGZpcnN0ID0gZWxsaXBzb2lkLnNjYWxlVG9HZW9kZXRpY1N1cmZhY2UocDAsIHNjYWxlRmlyc3QpOwogICAgY29uc3QgbGFzdCA9IGVsbGlwc29pZC5zY2FsZVRvR2VvZGV0aWNTdXJmYWNlKHAxLCBzY2FsZUxhc3QpOwogICAgY29uc3QgbnVtUG9pbnRzID0gUG9seWxpbmVQaXBlbGluZS5udW1iZXJPZlBvaW50cyhwMCwgcDEsIG1pbkRpc3RhbmNlKTsKICAgIGNvbnN0IHN0YXJ0ID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKGZpcnN0LCBjYXJ0bzEpOwogICAgY29uc3QgZW5kID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKGxhc3QsIGNhcnRvMik7CiAgICBjb25zdCBoZWlnaHRzID0gc3ViZGl2aWRlSGVpZ2h0cyhudW1Qb2ludHMsIGgwLCBoMSk7CiAgICBlbGxpcHNvaWRHZW9kZXNpYy5zZXRFbmRQb2ludHMoc3RhcnQsIGVuZCk7CiAgICBjb25zdCBzdXJmYWNlRGlzdGFuY2VCZXR3ZWVuUG9pbnRzID0gZWxsaXBzb2lkR2VvZGVzaWMuc3VyZmFjZURpc3RhbmNlIC8gbnVtUG9pbnRzOwogICAgbGV0IGluZGV4ID0gb2Zmc2V0OwogICAgc3RhcnQuaGVpZ2h0ID0gaDA7CiAgICBsZXQgY2FydCA9IGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbihzdGFydCwgY2FydGVzaWFuKTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKGNhcnQsIGFycmF5LCBpbmRleCk7CiAgICBpbmRleCArPSAzOwogICAgZm9yIChsZXQgaSA9IDE7IGkgPCBudW1Qb2ludHM7IGkrKykgewogICAgICBjb25zdCBjYXJ0byA9IGVsbGlwc29pZEdlb2Rlc2ljLmludGVycG9sYXRlVXNpbmdTdXJmYWNlRGlzdGFuY2UoCiAgICAgICAgaSAqIHN1cmZhY2VEaXN0YW5jZUJldHdlZW5Qb2ludHMsCiAgICAgICAgY2FydG8yCiAgICAgICk7CiAgICAgIGNhcnRvLmhlaWdodCA9IGhlaWdodHNbaV07CiAgICAgIGNhcnQgPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oY2FydG8sIGNhcnRlc2lhbik7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKGNhcnQsIGFycmF5LCBpbmRleCk7CiAgICAgIGluZGV4ICs9IDM7CiAgICB9CiAgICByZXR1cm4gaW5kZXg7CiAgfQogIGZ1bmN0aW9uIGdlbmVyYXRlQ2FydGVzaWFuUmh1bWJBcmMocDAsIHAxLCBncmFudWxhcml0eSwgZWxsaXBzb2lkLCBoMCwgaDEsIGFycmF5LCBvZmZzZXQpIHsKICAgIGNvbnN0IHN0YXJ0ID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKHAwLCBjYXJ0bzEpOwogICAgY29uc3QgZW5kID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKHAxLCBjYXJ0bzIpOwogICAgY29uc3QgbnVtUG9pbnRzID0gUG9seWxpbmVQaXBlbGluZS5udW1iZXJPZlBvaW50c1JodW1iTGluZSgKICAgICAgc3RhcnQsCiAgICAgIGVuZCwKICAgICAgZ3JhbnVsYXJpdHkKICAgICk7CiAgICBzdGFydC5oZWlnaHQgPSAwOwogICAgZW5kLmhlaWdodCA9IDA7CiAgICBjb25zdCBoZWlnaHRzID0gc3ViZGl2aWRlSGVpZ2h0cyhudW1Qb2ludHMsIGgwLCBoMSk7CiAgICBpZiAoIWVsbGlwc29pZFJodW1iLmVsbGlwc29pZC5lcXVhbHMoZWxsaXBzb2lkKSkgewogICAgICBlbGxpcHNvaWRSaHVtYiA9IG5ldyBFbGxpcHNvaWRSaHVtYkxpbmVfZGVmYXVsdCh2b2lkIDAsIHZvaWQgMCwgZWxsaXBzb2lkKTsKICAgIH0KICAgIGVsbGlwc29pZFJodW1iLnNldEVuZFBvaW50cyhzdGFydCwgZW5kKTsKICAgIGNvbnN0IHN1cmZhY2VEaXN0YW5jZUJldHdlZW5Qb2ludHMgPSBlbGxpcHNvaWRSaHVtYi5zdXJmYWNlRGlzdGFuY2UgLyBudW1Qb2ludHM7CiAgICBsZXQgaW5kZXggPSBvZmZzZXQ7CiAgICBzdGFydC5oZWlnaHQgPSBoMDsKICAgIGxldCBjYXJ0ID0gZWxsaXBzb2lkLmNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuKHN0YXJ0LCBjYXJ0ZXNpYW4pOwogICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soY2FydCwgYXJyYXksIGluZGV4KTsKICAgIGluZGV4ICs9IDM7CiAgICBmb3IgKGxldCBpID0gMTsgaSA8IG51bVBvaW50czsgaSsrKSB7CiAgICAgIGNvbnN0IGNhcnRvID0gZWxsaXBzb2lkUmh1bWIuaW50ZXJwb2xhdGVVc2luZ1N1cmZhY2VEaXN0YW5jZSgKICAgICAgICBpICogc3VyZmFjZURpc3RhbmNlQmV0d2VlblBvaW50cywKICAgICAgICBjYXJ0bzIKICAgICAgKTsKICAgICAgY2FydG8uaGVpZ2h0ID0gaGVpZ2h0c1tpXTsKICAgICAgY2FydCA9IGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbihjYXJ0bywgY2FydGVzaWFuKTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soY2FydCwgYXJyYXksIGluZGV4KTsKICAgICAgaW5kZXggKz0gMzsKICAgIH0KICAgIHJldHVybiBpbmRleDsKICB9CiAgdmFyIFBvbHlsaW5lUGlwZWxpbmUsIGNhcnRvU2NyYXRjaCwgd3JhcExvbmdpdHVkZUludmVyc01hdHJpeCwgd3JhcExvbmdpdHVkZU9yaWdpbiwgd3JhcExvbmdpdHVkZVhaTm9ybWFsLCB3cmFwTG9uZ2l0dWRlWFpQbGFuZSwgd3JhcExvbmdpdHVkZVlaTm9ybWFsLCB3cmFwTG9uZ2l0dWRlWVpQbGFuZSwgd3JhcExvbmdpdHVkZUludGVyc2VjdGlvbiwgd3JhcExvbmdpdHVkZU9mZnNldCwgc3ViZGl2aWRlSGVpZ2h0c1NjcmF0Y2hBcnJheSwgY2FydG8xLCBjYXJ0bzIsIGNhcnRlc2lhbiwgc2NhbGVGaXJzdCwgc2NhbGVMYXN0LCBlbGxpcHNvaWRHZW9kZXNpYywgZWxsaXBzb2lkUmh1bWIsIHNjcmF0Y2hDYXJ0b2dyYXBoaWMwMiwgc2NyYXRjaENhcnRvZ3JhcGhpYzEyLCBQb2x5bGluZVBpcGVsaW5lX2RlZmF1bHQ7CiAgdmFyIGluaXRfUG9seWxpbmVQaXBlbGluZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUG9seWxpbmVQaXBlbGluZS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0VsbGlwc29pZEdlb2Rlc2ljKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkUmh1bWJMaW5lKCk7CiAgICAgIGluaXRfSW50ZXJzZWN0aW9uVGVzdHMoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfTWF0cml4NCgpOwogICAgICBpbml0X1BsYW5lKCk7CiAgICAgIFBvbHlsaW5lUGlwZWxpbmUgPSB7fTsKICAgICAgUG9seWxpbmVQaXBlbGluZS5udW1iZXJPZlBvaW50cyA9IGZ1bmN0aW9uKHAwLCBwMSwgbWluRGlzdGFuY2UpIHsKICAgICAgICBjb25zdCBkaXN0YW5jZSA9IENhcnRlc2lhbjNfZGVmYXVsdC5kaXN0YW5jZShwMCwgcDEpOwogICAgICAgIHJldHVybiBNYXRoLmNlaWwoZGlzdGFuY2UgLyBtaW5EaXN0YW5jZSk7CiAgICAgIH07CiAgICAgIFBvbHlsaW5lUGlwZWxpbmUubnVtYmVyT2ZQb2ludHNSaHVtYkxpbmUgPSBmdW5jdGlvbihwMCwgcDEsIGdyYW51bGFyaXR5KSB7CiAgICAgICAgY29uc3QgcmFkaWFuc0Rpc3RhbmNlU3F1YXJlZCA9IE1hdGgucG93KHAwLmxvbmdpdHVkZSAtIHAxLmxvbmdpdHVkZSwgMikgKyBNYXRoLnBvdyhwMC5sYXRpdHVkZSAtIHAxLmxhdGl0dWRlLCAyKTsKICAgICAgICByZXR1cm4gTWF0aC5tYXgoCiAgICAgICAgICAxLAogICAgICAgICAgTWF0aC5jZWlsKE1hdGguc3FydChyYWRpYW5zRGlzdGFuY2VTcXVhcmVkIC8gKGdyYW51bGFyaXR5ICogZ3JhbnVsYXJpdHkpKSkKICAgICAgICApOwogICAgICB9OwogICAgICBjYXJ0b1NjcmF0Y2ggPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgUG9seWxpbmVQaXBlbGluZS5leHRyYWN0SGVpZ2h0cyA9IGZ1bmN0aW9uKHBvc2l0aW9ucywgZWxsaXBzb2lkKSB7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBjb25zdCBoZWlnaHRzID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgY29uc3QgcCA9IHBvc2l0aW9uc1tpXTsKICAgICAgICAgIGhlaWdodHNbaV0gPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMocCwgY2FydG9TY3JhdGNoKS5oZWlnaHQ7CiAgICAgICAgfQogICAgICAgIHJldHVybiBoZWlnaHRzOwogICAgICB9OwogICAgICB3cmFwTG9uZ2l0dWRlSW52ZXJzTWF0cml4ID0gbmV3IE1hdHJpeDRfZGVmYXVsdCgpOwogICAgICB3cmFwTG9uZ2l0dWRlT3JpZ2luID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICB3cmFwTG9uZ2l0dWRlWFpOb3JtYWwgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHdyYXBMb25naXR1ZGVYWlBsYW5lID0gbmV3IFBsYW5lX2RlZmF1bHQoQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWCwgMCk7CiAgICAgIHdyYXBMb25naXR1ZGVZWk5vcm1hbCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgd3JhcExvbmdpdHVkZVlaUGxhbmUgPSBuZXcgUGxhbmVfZGVmYXVsdChDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9YLCAwKTsKICAgICAgd3JhcExvbmdpdHVkZUludGVyc2VjdGlvbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgd3JhcExvbmdpdHVkZU9mZnNldCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc3ViZGl2aWRlSGVpZ2h0c1NjcmF0Y2hBcnJheSA9IFtdOwogICAgICBjYXJ0bzEgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgY2FydG8yID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NhbGVGaXJzdCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NhbGVMYXN0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBlbGxpcHNvaWRHZW9kZXNpYyA9IG5ldyBFbGxpcHNvaWRHZW9kZXNpY19kZWZhdWx0KCk7CiAgICAgIGVsbGlwc29pZFJodW1iID0gbmV3IEVsbGlwc29pZFJodW1iTGluZV9kZWZhdWx0KCk7CiAgICAgIFBvbHlsaW5lUGlwZWxpbmUud3JhcExvbmdpdHVkZSA9IGZ1bmN0aW9uKHBvc2l0aW9ucywgbW9kZWxNYXRyaXgpIHsKICAgICAgICBjb25zdCBjYXJ0ZXNpYW5zID0gW107CiAgICAgICAgY29uc3Qgc2VnbWVudHMgPSBbXTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHBvc2l0aW9ucykgJiYgcG9zaXRpb25zLmxlbmd0aCA+IDApIHsKICAgICAgICAgIG1vZGVsTWF0cml4ID0gbW9kZWxNYXRyaXggPz8gTWF0cml4NF9kZWZhdWx0LklERU5USVRZOwogICAgICAgICAgY29uc3QgaW52ZXJzZU1vZGVsTWF0cml4ID0gTWF0cml4NF9kZWZhdWx0LmludmVyc2VUcmFuc2Zvcm1hdGlvbigKICAgICAgICAgICAgbW9kZWxNYXRyaXgsCiAgICAgICAgICAgIHdyYXBMb25naXR1ZGVJbnZlcnNNYXRyaXgKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBvcmlnaW4gPSBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlCeVBvaW50KAogICAgICAgICAgICBpbnZlcnNlTW9kZWxNYXRyaXgsCiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLAogICAgICAgICAgICB3cmFwTG9uZ2l0dWRlT3JpZ2luCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgeHpOb3JtYWwgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlCeVBvaW50QXNWZWN0b3IoCiAgICAgICAgICAgICAgaW52ZXJzZU1vZGVsTWF0cml4LAogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1ksCiAgICAgICAgICAgICAgd3JhcExvbmdpdHVkZVhaTm9ybWFsCiAgICAgICAgICAgICksCiAgICAgICAgICAgIHdyYXBMb25naXR1ZGVYWk5vcm1hbAogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IHh6UGxhbmUyID0gUGxhbmVfZGVmYXVsdC5mcm9tUG9pbnROb3JtYWwoCiAgICAgICAgICAgIG9yaWdpbiwKICAgICAgICAgICAgeHpOb3JtYWwsCiAgICAgICAgICAgIHdyYXBMb25naXR1ZGVYWlBsYW5lCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgeXpOb3JtYWwgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlCeVBvaW50QXNWZWN0b3IoCiAgICAgICAgICAgICAgaW52ZXJzZU1vZGVsTWF0cml4LAogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1gsCiAgICAgICAgICAgICAgd3JhcExvbmdpdHVkZVlaTm9ybWFsCiAgICAgICAgICAgICksCiAgICAgICAgICAgIHdyYXBMb25naXR1ZGVZWk5vcm1hbAogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IHl6UGxhbmUgPSBQbGFuZV9kZWZhdWx0LmZyb21Qb2ludE5vcm1hbCgKICAgICAgICAgICAgb3JpZ2luLAogICAgICAgICAgICB5ek5vcm1hbCwKICAgICAgICAgICAgd3JhcExvbmdpdHVkZVlaUGxhbmUKICAgICAgICAgICk7CiAgICAgICAgICBsZXQgY291bnQgPSAxOwogICAgICAgICAgY2FydGVzaWFucy5wdXNoKENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShwb3NpdGlvbnNbMF0pKTsKICAgICAgICAgIGxldCBwcmV2ID0gY2FydGVzaWFuc1swXTsKICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgIGNvbnN0IGN1ciA9IHBvc2l0aW9uc1tpXTsKICAgICAgICAgICAgaWYgKFBsYW5lX2RlZmF1bHQuZ2V0UG9pbnREaXN0YW5jZSh5elBsYW5lLCBwcmV2KSA8IDAgfHwgUGxhbmVfZGVmYXVsdC5nZXRQb2ludERpc3RhbmNlKHl6UGxhbmUsIGN1cikgPCAwKSB7CiAgICAgICAgICAgICAgY29uc3QgaW50ZXJzZWN0aW9uID0gSW50ZXJzZWN0aW9uVGVzdHNfZGVmYXVsdC5saW5lU2VnbWVudFBsYW5lKAogICAgICAgICAgICAgICAgcHJldiwKICAgICAgICAgICAgICAgIGN1ciwKICAgICAgICAgICAgICAgIHh6UGxhbmUyLAogICAgICAgICAgICAgICAgd3JhcExvbmdpdHVkZUludGVyc2VjdGlvbgogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChpbnRlcnNlY3Rpb24pKSB7CiAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICAgICAgICAgICAgeHpOb3JtYWwsCiAgICAgICAgICAgICAgICAgIDVlLTksCiAgICAgICAgICAgICAgICAgIHdyYXBMb25naXR1ZGVPZmZzZXQKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICBpZiAoUGxhbmVfZGVmYXVsdC5nZXRQb2ludERpc3RhbmNlKHh6UGxhbmUyLCBwcmV2KSA8IDApIHsKICAgICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShvZmZzZXQsIG9mZnNldCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjYXJ0ZXNpYW5zLnB1c2goCiAgICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoaW50ZXJzZWN0aW9uLCBvZmZzZXQsIG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKSkKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICBzZWdtZW50cy5wdXNoKGNvdW50ICsgMSk7CiAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKG9mZnNldCwgb2Zmc2V0KTsKICAgICAgICAgICAgICAgIGNhcnRlc2lhbnMucHVzaCgKICAgICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChpbnRlcnNlY3Rpb24sIG9mZnNldCwgbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpKQogICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgIGNvdW50ID0gMTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2FydGVzaWFucy5wdXNoKENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShwb3NpdGlvbnNbaV0pKTsKICAgICAgICAgICAgY291bnQrKzsKICAgICAgICAgICAgcHJldiA9IGN1cjsKICAgICAgICAgIH0KICAgICAgICAgIHNlZ21lbnRzLnB1c2goY291bnQpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gewogICAgICAgICAgcG9zaXRpb25zOiBjYXJ0ZXNpYW5zLAogICAgICAgICAgbGVuZ3Roczogc2VnbWVudHMKICAgICAgICB9OwogICAgICB9OwogICAgICBQb2x5bGluZVBpcGVsaW5lLmdlbmVyYXRlQXJjID0gZnVuY3Rpb24ob3B0aW9ucykgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMpKSB7CiAgICAgICAgICBvcHRpb25zID0ge307CiAgICAgICAgfQogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IG9wdGlvbnMucG9zaXRpb25zOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBvc2l0aW9ucykpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJvcHRpb25zLnBvc2l0aW9ucyBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBvcHRpb25zLmVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgICAgIGxldCBoZWlnaHQgPSBvcHRpb25zLmhlaWdodCA/PyAwOwogICAgICAgIGNvbnN0IGhhc0hlaWdodEFycmF5ID0gQXJyYXkuaXNBcnJheShoZWlnaHQpOwogICAgICAgIGlmIChsZW5ndGggPCAxKSB7CiAgICAgICAgICByZXR1cm4gW107CiAgICAgICAgfSBlbHNlIGlmIChsZW5ndGggPT09IDEpIHsKICAgICAgICAgIGNvbnN0IHAgPSBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZShwb3NpdGlvbnNbMF0sIHNjYWxlRmlyc3QpOwogICAgICAgICAgaGVpZ2h0ID0gaGFzSGVpZ2h0QXJyYXkgPyBoZWlnaHRbMF0gOiBoZWlnaHQ7CiAgICAgICAgICBpZiAoaGVpZ2h0ICE9PSAwKSB7CiAgICAgICAgICAgIGNvbnN0IG4gPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKHAsIGNhcnRlc2lhbik7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKG4sIGhlaWdodCwgbik7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocCwgbiwgcCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gW3AueCwgcC55LCBwLnpdOwogICAgICAgIH0KICAgICAgICBsZXQgbWluRGlzdGFuY2UgPSBvcHRpb25zLm1pbkRpc3RhbmNlOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG1pbkRpc3RhbmNlKSkgewogICAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBvcHRpb25zLmdyYW51bGFyaXR5ID8/IE1hdGhfZGVmYXVsdC5SQURJQU5TX1BFUl9ERUdSRUU7CiAgICAgICAgICBtaW5EaXN0YW5jZSA9IE1hdGhfZGVmYXVsdC5jaG9yZExlbmd0aChncmFudWxhcml0eSwgZWxsaXBzb2lkLm1heGltdW1SYWRpdXMpOwogICAgICAgIH0KICAgICAgICBsZXQgbnVtUG9pbnRzID0gMDsKICAgICAgICBsZXQgaTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoIC0gMTsgaSsrKSB7CiAgICAgICAgICBudW1Qb2ludHMgKz0gUG9seWxpbmVQaXBlbGluZS5udW1iZXJPZlBvaW50cygKICAgICAgICAgICAgcG9zaXRpb25zW2ldLAogICAgICAgICAgICBwb3NpdGlvbnNbaSArIDFdLAogICAgICAgICAgICBtaW5EaXN0YW5jZQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgYXJyYXlMZW5ndGggPSAobnVtUG9pbnRzICsgMSkgKiAzOwogICAgICAgIGNvbnN0IG5ld1Bvc2l0aW9ucyA9IG5ldyBBcnJheShhcnJheUxlbmd0aCk7CiAgICAgICAgbGV0IG9mZnNldCA9IDA7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aCAtIDE7IGkrKykgewogICAgICAgICAgY29uc3QgcDAgPSBwb3NpdGlvbnNbaV07CiAgICAgICAgICBjb25zdCBwMSA9IHBvc2l0aW9uc1tpICsgMV07CiAgICAgICAgICBjb25zdCBoMCA9IGhhc0hlaWdodEFycmF5ID8gaGVpZ2h0W2ldIDogaGVpZ2h0OwogICAgICAgICAgY29uc3QgaDEgPSBoYXNIZWlnaHRBcnJheSA/IGhlaWdodFtpICsgMV0gOiBoZWlnaHQ7CiAgICAgICAgICBvZmZzZXQgPSBnZW5lcmF0ZUNhcnRlc2lhbkFyYygKICAgICAgICAgICAgcDAsCiAgICAgICAgICAgIHAxLAogICAgICAgICAgICBtaW5EaXN0YW5jZSwKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICBoMCwKICAgICAgICAgICAgaDEsCiAgICAgICAgICAgIG5ld1Bvc2l0aW9ucywKICAgICAgICAgICAgb2Zmc2V0CiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBzdWJkaXZpZGVIZWlnaHRzU2NyYXRjaEFycmF5Lmxlbmd0aCA9IDA7CiAgICAgICAgY29uc3QgbGFzdFBvaW50ID0gcG9zaXRpb25zW2xlbmd0aCAtIDFdOwogICAgICAgIGNvbnN0IGNhcnRvID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKGxhc3RQb2ludCwgY2FydG8xKTsKICAgICAgICBjYXJ0by5oZWlnaHQgPSBoYXNIZWlnaHRBcnJheSA/IGhlaWdodFtsZW5ndGggLSAxXSA6IGhlaWdodDsKICAgICAgICBjb25zdCBjYXJ0ID0gZWxsaXBzb2lkLmNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuKGNhcnRvLCBjYXJ0ZXNpYW4pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKGNhcnQsIG5ld1Bvc2l0aW9ucywgYXJyYXlMZW5ndGggLSAzKTsKICAgICAgICByZXR1cm4gbmV3UG9zaXRpb25zOwogICAgICB9OwogICAgICBzY3JhdGNoQ2FydG9ncmFwaGljMDIgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzEyID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIFBvbHlsaW5lUGlwZWxpbmUuZ2VuZXJhdGVSaHVtYkFyYyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChvcHRpb25zKSkgewogICAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICAgIH0KICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBvcHRpb25zLnBvc2l0aW9uczsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwb3NpdGlvbnMpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgib3B0aW9ucy5wb3NpdGlvbnMgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gb3B0aW9ucy5lbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgICAgICBsZXQgaGVpZ2h0ID0gb3B0aW9ucy5oZWlnaHQgPz8gMDsKICAgICAgICBjb25zdCBoYXNIZWlnaHRBcnJheSA9IEFycmF5LmlzQXJyYXkoaGVpZ2h0KTsKICAgICAgICBpZiAobGVuZ3RoIDwgMSkgewogICAgICAgICAgcmV0dXJuIFtdOwogICAgICAgIH0gZWxzZSBpZiAobGVuZ3RoID09PSAxKSB7CiAgICAgICAgICBjb25zdCBwID0gZWxsaXBzb2lkLnNjYWxlVG9HZW9kZXRpY1N1cmZhY2UocG9zaXRpb25zWzBdLCBzY2FsZUZpcnN0KTsKICAgICAgICAgIGhlaWdodCA9IGhhc0hlaWdodEFycmF5ID8gaGVpZ2h0WzBdIDogaGVpZ2h0OwogICAgICAgICAgaWYgKGhlaWdodCAhPT0gMCkgewogICAgICAgICAgICBjb25zdCBuID0gZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbChwLCBjYXJ0ZXNpYW4pOwogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihuLCBoZWlnaHQsIG4pOwogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHAsIG4sIHApOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIFtwLngsIHAueSwgcC56XTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBvcHRpb25zLmdyYW51bGFyaXR5ID8/IE1hdGhfZGVmYXVsdC5SQURJQU5TX1BFUl9ERUdSRUU7CiAgICAgICAgbGV0IG51bVBvaW50cyA9IDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgbGV0IGMwID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKAogICAgICAgICAgcG9zaXRpb25zWzBdLAogICAgICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzAyCiAgICAgICAgKTsKICAgICAgICBsZXQgYzE7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aCAtIDE7IGkrKykgewogICAgICAgICAgYzEgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMoCiAgICAgICAgICAgIHBvc2l0aW9uc1tpICsgMV0sCiAgICAgICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWMxMgogICAgICAgICAgKTsKICAgICAgICAgIG51bVBvaW50cyArPSBQb2x5bGluZVBpcGVsaW5lLm51bWJlck9mUG9pbnRzUmh1bWJMaW5lKGMwLCBjMSwgZ3JhbnVsYXJpdHkpOwogICAgICAgICAgYzAgPSBDYXJ0b2dyYXBoaWNfZGVmYXVsdC5jbG9uZShjMSwgc2NyYXRjaENhcnRvZ3JhcGhpYzAyKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgYXJyYXlMZW5ndGggPSAobnVtUG9pbnRzICsgMSkgKiAzOwogICAgICAgIGNvbnN0IG5ld1Bvc2l0aW9ucyA9IG5ldyBBcnJheShhcnJheUxlbmd0aCk7CiAgICAgICAgbGV0IG9mZnNldCA9IDA7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aCAtIDE7IGkrKykgewogICAgICAgICAgY29uc3QgcDAgPSBwb3NpdGlvbnNbaV07CiAgICAgICAgICBjb25zdCBwMSA9IHBvc2l0aW9uc1tpICsgMV07CiAgICAgICAgICBjb25zdCBoMCA9IGhhc0hlaWdodEFycmF5ID8gaGVpZ2h0W2ldIDogaGVpZ2h0OwogICAgICAgICAgY29uc3QgaDEgPSBoYXNIZWlnaHRBcnJheSA/IGhlaWdodFtpICsgMV0gOiBoZWlnaHQ7CiAgICAgICAgICBvZmZzZXQgPSBnZW5lcmF0ZUNhcnRlc2lhblJodW1iQXJjKAogICAgICAgICAgICBwMCwKICAgICAgICAgICAgcDEsCiAgICAgICAgICAgIGdyYW51bGFyaXR5LAogICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgIGgwLAogICAgICAgICAgICBoMSwKICAgICAgICAgICAgbmV3UG9zaXRpb25zLAogICAgICAgICAgICBvZmZzZXQKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHN1YmRpdmlkZUhlaWdodHNTY3JhdGNoQXJyYXkubGVuZ3RoID0gMDsKICAgICAgICBjb25zdCBsYXN0UG9pbnQgPSBwb3NpdGlvbnNbbGVuZ3RoIC0gMV07CiAgICAgICAgY29uc3QgY2FydG8gPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMobGFzdFBvaW50LCBjYXJ0bzEpOwogICAgICAgIGNhcnRvLmhlaWdodCA9IGhhc0hlaWdodEFycmF5ID8gaGVpZ2h0W2xlbmd0aCAtIDFdIDogaGVpZ2h0OwogICAgICAgIGNvbnN0IGNhcnQgPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oY2FydG8sIGNhcnRlc2lhbik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soY2FydCwgbmV3UG9zaXRpb25zLCBhcnJheUxlbmd0aCAtIDMpOwogICAgICAgIHJldHVybiBuZXdQb3NpdGlvbnM7CiAgICAgIH07CiAgICAgIFBvbHlsaW5lUGlwZWxpbmUuZ2VuZXJhdGVDYXJ0ZXNpYW5BcmMgPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgY29uc3QgbnVtYmVyQXJyYXkgPSBQb2x5bGluZVBpcGVsaW5lLmdlbmVyYXRlQXJjKG9wdGlvbnMpOwogICAgICAgIGNvbnN0IHNpemUgPSBudW1iZXJBcnJheS5sZW5ndGggLyAzOwogICAgICAgIGNvbnN0IG5ld1Bvc2l0aW9ucyA9IG5ldyBBcnJheShzaXplKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykgewogICAgICAgICAgbmV3UG9zaXRpb25zW2ldID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjayhudW1iZXJBcnJheSwgaSAqIDMpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3UG9zaXRpb25zOwogICAgICB9OwogICAgICBQb2x5bGluZVBpcGVsaW5lLmdlbmVyYXRlQ2FydGVzaWFuUmh1bWJBcmMgPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgY29uc3QgbnVtYmVyQXJyYXkgPSBQb2x5bGluZVBpcGVsaW5lLmdlbmVyYXRlUmh1bWJBcmMob3B0aW9ucyk7CiAgICAgICAgY29uc3Qgc2l6ZSA9IG51bWJlckFycmF5Lmxlbmd0aCAvIDM7CiAgICAgICAgY29uc3QgbmV3UG9zaXRpb25zID0gbmV3IEFycmF5KHNpemUpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7CiAgICAgICAgICBuZXdQb3NpdGlvbnNbaV0gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKG51bWJlckFycmF5LCBpICogMyk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXdQb3NpdGlvbnM7CiAgICAgIH07CiAgICAgIFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdCA9IFBvbHlsaW5lUGlwZWxpbmU7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9vbmVUaW1lV2FybmluZy5qcwogIGZ1bmN0aW9uIG9uZVRpbWVXYXJuaW5nKGlkZW50aWZpZXIsIG1lc3NhZ2UpIHsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGlkZW50aWZpZXIpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJpZGVudGlmaWVyIGlzIHJlcXVpcmVkLiIpOwogICAgfQogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQod2FybmluZ3NbaWRlbnRpZmllcl0pKSB7CiAgICAgIHdhcm5pbmdzW2lkZW50aWZpZXJdID0gdHJ1ZTsKICAgICAgY29uc29sZS53YXJuKG1lc3NhZ2UgPz8gaWRlbnRpZmllcik7CiAgICB9CiAgfQogIHZhciB3YXJuaW5ncywgb25lVGltZVdhcm5pbmdfZGVmYXVsdDsKICB2YXIgaW5pdF9vbmVUaW1lV2FybmluZyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvb25lVGltZVdhcm5pbmcuanMiKCkgewogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICB3YXJuaW5ncyA9IHt9OwogICAgICBvbmVUaW1lV2FybmluZy5nZW9tZXRyeU91dGxpbmVzID0gIkVudGl0eSBnZW9tZXRyeSBvdXRsaW5lcyBhcmUgdW5zdXBwb3J0ZWQgb24gdGVycmFpbi4gT3V0bGluZXMgd2lsbCBiZSBkaXNhYmxlZC4gVG8gZW5hYmxlIG91dGxpbmVzLCBkaXNhYmxlIGdlb21ldHJ5IHRlcnJhaW4gY2xhbXBpbmcgYnkgZXhwbGljaXRseSBzZXR0aW5nIGhlaWdodCB0byAwLiI7CiAgICAgIG9uZVRpbWVXYXJuaW5nLmdlb21ldHJ5WkluZGV4ID0gIkVudGl0eSBnZW9tZXRyeSB3aXRoIHpJbmRleCBhcmUgdW5zdXBwb3J0ZWQgd2hlbiBoZWlnaHQgb3IgZXh0cnVkZWRIZWlnaHQgYXJlIGRlZmluZWQuICB6SW5kZXggd2lsbCBiZSBpZ25vcmVkIjsKICAgICAgb25lVGltZVdhcm5pbmcuZ2VvbWV0cnlIZWlnaHRSZWZlcmVuY2UgPSAiRW50aXR5IGNvcnJpZG9yLCBlbGxpcHNlLCBwb2x5Z29uIG9yIHJlY3RhbmdsZSB3aXRoIGhlaWdodFJlZmVyZW5jZSBtdXN0IGFsc28gaGF2ZSBhIGRlZmluZWQgaGVpZ2h0LiAgaGVpZ2h0UmVmZXJlbmNlIHdpbGwgYmUgaWdub3JlZCI7CiAgICAgIG9uZVRpbWVXYXJuaW5nLmdlb21ldHJ5RXh0cnVkZWRIZWlnaHRSZWZlcmVuY2UgPSAiRW50aXR5IGNvcnJpZG9yLCBlbGxpcHNlLCBwb2x5Z29uIG9yIHJlY3RhbmdsZSB3aXRoIGV4dHJ1ZGVkSGVpZ2h0UmVmZXJlbmNlIG11c3QgYWxzbyBoYXZlIGEgZGVmaW5lZCBleHRydWRlZEhlaWdodC4gIGV4dHJ1ZGVkSGVpZ2h0UmVmZXJlbmNlIHdpbGwgYmUgaWdub3JlZCI7CiAgICAgIG9uZVRpbWVXYXJuaW5nX2RlZmF1bHQgPSBvbmVUaW1lV2FybmluZzsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1BvbHlsaW5lVm9sdW1lR2VvbWV0cnlMaWJyYXJ5LmpzCiAgZnVuY3Rpb24gc2NhbGVUb1N1cmZhY2UocG9zaXRpb25zLCBlbGxpcHNvaWQpIHsKICAgIGNvbnN0IGhlaWdodHMgPSBuZXcgQXJyYXkocG9zaXRpb25zLmxlbmd0aCk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBvc2l0aW9ucy5sZW5ndGg7IGkrKykgewogICAgICBjb25zdCBwb3MgPSBwb3NpdGlvbnNbaV07CiAgICAgIGNhcnRvZ3JhcGhpYyA9IGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyhwb3MsIGNhcnRvZ3JhcGhpYyk7CiAgICAgIGhlaWdodHNbaV0gPSBjYXJ0b2dyYXBoaWMuaGVpZ2h0OwogICAgICBwb3NpdGlvbnNbaV0gPSBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZShwb3MsIHBvcyk7CiAgICB9CiAgICByZXR1cm4gaGVpZ2h0czsKICB9CiAgZnVuY3Rpb24gc3ViZGl2aWRlSGVpZ2h0czIocG9pbnRzLCBoMCwgaDEsIGdyYW51bGFyaXR5KSB7CiAgICBjb25zdCBwMCA9IHBvaW50c1swXTsKICAgIGNvbnN0IHAxID0gcG9pbnRzWzFdOwogICAgY29uc3QgYW5nbGVCZXR3ZWVuID0gQ2FydGVzaWFuM19kZWZhdWx0LmFuZ2xlQmV0d2VlbihwMCwgcDEpOwogICAgY29uc3QgbnVtUG9pbnRzID0gTWF0aC5jZWlsKGFuZ2xlQmV0d2VlbiAvIGdyYW51bGFyaXR5KTsKICAgIGNvbnN0IGhlaWdodHMgPSBuZXcgQXJyYXkobnVtUG9pbnRzKTsKICAgIGxldCBpOwogICAgaWYgKGgwID09PSBoMSkgewogICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtUG9pbnRzOyBpKyspIHsKICAgICAgICBoZWlnaHRzW2ldID0gaDA7CiAgICAgIH0KICAgICAgaGVpZ2h0cy5wdXNoKGgxKTsKICAgICAgcmV0dXJuIGhlaWdodHM7CiAgICB9CiAgICBjb25zdCBkSGVpZ2h0ID0gaDEgLSBoMDsKICAgIGNvbnN0IGhlaWdodFBlclZlcnRleCA9IGRIZWlnaHQgLyBudW1Qb2ludHM7CiAgICBmb3IgKGkgPSAxOyBpIDwgbnVtUG9pbnRzOyBpKyspIHsKICAgICAgY29uc3QgaCA9IGgwICsgaSAqIGhlaWdodFBlclZlcnRleDsKICAgICAgaGVpZ2h0c1tpXSA9IGg7CiAgICB9CiAgICBoZWlnaHRzWzBdID0gaDA7CiAgICBoZWlnaHRzLnB1c2goaDEpOwogICAgcmV0dXJuIGhlaWdodHM7CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVSb3RhdGlvbkFuZ2xlKHN0YXJ0LCBlbmQsIHBvc2l0aW9uLCBlbGxpcHNvaWQpIHsKICAgIGNvbnN0IHRhbmdlbnRQbGFuZSA9IG5ldyBFbGxpcHNvaWRUYW5nZW50UGxhbmVfZGVmYXVsdChwb3NpdGlvbiwgZWxsaXBzb2lkKTsKICAgIGNvbnN0IG5leHQgPSB0YW5nZW50UGxhbmUucHJvamVjdFBvaW50T250b1BsYW5lKAogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHBvc2l0aW9uLCBzdGFydCwgbmV4dFNjcmF0Y2gpLAogICAgICBuZXh0U2NyYXRjaAogICAgKTsKICAgIGNvbnN0IHByZXYgPSB0YW5nZW50UGxhbmUucHJvamVjdFBvaW50T250b1BsYW5lKAogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHBvc2l0aW9uLCBlbmQsIHByZXZTY3JhdGNoKSwKICAgICAgcHJldlNjcmF0Y2gKICAgICk7CiAgICBjb25zdCBhbmdsZSA9IENhcnRlc2lhbjJfZGVmYXVsdC5hbmdsZUJldHdlZW4obmV4dCwgcHJldik7CiAgICByZXR1cm4gcHJldi54ICogbmV4dC55IC0gcHJldi55ICogbmV4dC54ID49IDAgPyAtYW5nbGUgOiBhbmdsZTsKICB9CiAgZnVuY3Rpb24gYWRkUG9zaXRpb24oY2VudGVyLCBsZWZ0LCBzaGFwZSwgZmluYWxQb3NpdGlvbnMsIGVsbGlwc29pZCwgaGVpZ2h0LCB4U2NhbGFyLCByZXBlYXQpIHsKICAgIGxldCB3ZXN0ID0gd2VzdFNjcmF0Y2g7CiAgICBsZXQgZmluYWxQb3NpdGlvbiA9IGZpbmFsUG9zU2NyYXRjaDsKICAgIHRyYW5zZm9ybSA9IFRyYW5zZm9ybXNfZGVmYXVsdC5lYXN0Tm9ydGhVcFRvRml4ZWRGcmFtZShjZW50ZXIsIGVsbGlwc29pZCwgdHJhbnNmb3JtKTsKICAgIHdlc3QgPSBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlCeVBvaW50QXNWZWN0b3IodHJhbnNmb3JtLCBuZWdhdGl2ZVgsIHdlc3QpOwogICAgd2VzdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUod2VzdCwgd2VzdCk7CiAgICBjb25zdCBhbmdsZSA9IGNvbXB1dGVSb3RhdGlvbkFuZ2xlKHdlc3QsIGxlZnQsIGNlbnRlciwgZWxsaXBzb2lkKTsKICAgIHJvdGF0aW9uWiA9IE1hdHJpeDNfZGVmYXVsdC5mcm9tUm90YXRpb25aKGFuZ2xlLCByb3RhdGlvblopOwogICAgaGVpZ2h0Q2FydGVzaWFuLnogPSBoZWlnaHQ7CiAgICB0cmFuc2Zvcm0gPSBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlUcmFuc2Zvcm1hdGlvbigKICAgICAgdHJhbnNmb3JtLAogICAgICBNYXRyaXg0X2RlZmF1bHQuZnJvbVJvdGF0aW9uVHJhbnNsYXRpb24ocm90YXRpb25aLCBoZWlnaHRDYXJ0ZXNpYW4sIHRyYW5zbGF0aW9uKSwKICAgICAgdHJhbnNmb3JtCiAgICApOwogICAgY29uc3Qgc2NhbGUgPSBzY2FsZU1hdHJpeDsKICAgIHNjYWxlWzBdID0geFNjYWxhcjsKICAgIGZvciAobGV0IGogPSAwOyBqIDwgcmVwZWF0OyBqKyspIHsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaGFwZS5sZW5ndGg7IGkgKz0gMykgewogICAgICAgIGZpbmFsUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHNoYXBlLCBpLCBmaW5hbFBvc2l0aW9uKTsKICAgICAgICBmaW5hbFBvc2l0aW9uID0gTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3IoCiAgICAgICAgICBzY2FsZSwKICAgICAgICAgIGZpbmFsUG9zaXRpb24sCiAgICAgICAgICBmaW5hbFBvc2l0aW9uCiAgICAgICAgKTsKICAgICAgICBmaW5hbFBvc2l0aW9uID0gTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5QnlQb2ludCgKICAgICAgICAgIHRyYW5zZm9ybSwKICAgICAgICAgIGZpbmFsUG9zaXRpb24sCiAgICAgICAgICBmaW5hbFBvc2l0aW9uCiAgICAgICAgKTsKICAgICAgICBmaW5hbFBvc2l0aW9ucy5wdXNoKGZpbmFsUG9zaXRpb24ueCwgZmluYWxQb3NpdGlvbi55LCBmaW5hbFBvc2l0aW9uLnopOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZmluYWxQb3NpdGlvbnM7CiAgfQogIGZ1bmN0aW9uIGFkZFBvc2l0aW9ucyhjZW50ZXJzLCBsZWZ0LCBzaGFwZSwgZmluYWxQb3NpdGlvbnMsIGVsbGlwc29pZCwgaGVpZ2h0cywgeFNjYWxhcikgewogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjZW50ZXJzLmxlbmd0aDsgaSArPSAzKSB7CiAgICAgIGNvbnN0IGNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoY2VudGVycywgaSwgY2VudGVyU2NyYXRjaDIpOwogICAgICBmaW5hbFBvc2l0aW9ucyA9IGFkZFBvc2l0aW9uKAogICAgICAgIGNlbnRlciwKICAgICAgICBsZWZ0LAogICAgICAgIHNoYXBlLAogICAgICAgIGZpbmFsUG9zaXRpb25zLAogICAgICAgIGVsbGlwc29pZCwKICAgICAgICBoZWlnaHRzW2kgLyAzXSwKICAgICAgICB4U2NhbGFyLAogICAgICAgIDEKICAgICAgKTsKICAgIH0KICAgIHJldHVybiBmaW5hbFBvc2l0aW9uczsKICB9CiAgZnVuY3Rpb24gY29udmVydFNoYXBlVG8zRER1cGxpY2F0ZShzaGFwZTJELCBib3VuZGluZ1JlY3RhbmdsZSkgewogICAgY29uc3QgbGVuZ3RoID0gc2hhcGUyRC5sZW5ndGg7CiAgICBjb25zdCBzaGFwZSA9IG5ldyBBcnJheShsZW5ndGggKiA2KTsKICAgIGxldCBpbmRleCA9IDA7CiAgICBjb25zdCB4T2Zmc2V0ID0gYm91bmRpbmdSZWN0YW5nbGUueCArIGJvdW5kaW5nUmVjdGFuZ2xlLndpZHRoIC8gMjsKICAgIGNvbnN0IHlPZmZzZXQgPSBib3VuZGluZ1JlY3RhbmdsZS55ICsgYm91bmRpbmdSZWN0YW5nbGUuaGVpZ2h0IC8gMjsKICAgIGxldCBwb2ludCA9IHNoYXBlMkRbMF07CiAgICBzaGFwZVtpbmRleCsrXSA9IHBvaW50LnggLSB4T2Zmc2V0OwogICAgc2hhcGVbaW5kZXgrK10gPSAwOwogICAgc2hhcGVbaW5kZXgrK10gPSBwb2ludC55IC0geU9mZnNldDsKICAgIGZvciAobGV0IGkgPSAxOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgcG9pbnQgPSBzaGFwZTJEW2ldOwogICAgICBjb25zdCB4ID0gcG9pbnQueCAtIHhPZmZzZXQ7CiAgICAgIGNvbnN0IHogPSBwb2ludC55IC0geU9mZnNldDsKICAgICAgc2hhcGVbaW5kZXgrK10gPSB4OwogICAgICBzaGFwZVtpbmRleCsrXSA9IDA7CiAgICAgIHNoYXBlW2luZGV4KytdID0gejsKICAgICAgc2hhcGVbaW5kZXgrK10gPSB4OwogICAgICBzaGFwZVtpbmRleCsrXSA9IDA7CiAgICAgIHNoYXBlW2luZGV4KytdID0gejsKICAgIH0KICAgIHBvaW50ID0gc2hhcGUyRFswXTsKICAgIHNoYXBlW2luZGV4KytdID0gcG9pbnQueCAtIHhPZmZzZXQ7CiAgICBzaGFwZVtpbmRleCsrXSA9IDA7CiAgICBzaGFwZVtpbmRleCsrXSA9IHBvaW50LnkgLSB5T2Zmc2V0OwogICAgcmV0dXJuIHNoYXBlOwogIH0KICBmdW5jdGlvbiBjb252ZXJ0U2hhcGVUbzNEKHNoYXBlMkQsIGJvdW5kaW5nUmVjdGFuZ2xlKSB7CiAgICBjb25zdCBsZW5ndGggPSBzaGFwZTJELmxlbmd0aDsKICAgIGNvbnN0IHNoYXBlID0gbmV3IEFycmF5KGxlbmd0aCAqIDMpOwogICAgbGV0IGluZGV4ID0gMDsKICAgIGNvbnN0IHhPZmZzZXQgPSBib3VuZGluZ1JlY3RhbmdsZS54ICsgYm91bmRpbmdSZWN0YW5nbGUud2lkdGggLyAyOwogICAgY29uc3QgeU9mZnNldCA9IGJvdW5kaW5nUmVjdGFuZ2xlLnkgKyBib3VuZGluZ1JlY3RhbmdsZS5oZWlnaHQgLyAyOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBzaGFwZVtpbmRleCsrXSA9IHNoYXBlMkRbaV0ueCAtIHhPZmZzZXQ7CiAgICAgIHNoYXBlW2luZGV4KytdID0gMDsKICAgICAgc2hhcGVbaW5kZXgrK10gPSBzaGFwZTJEW2ldLnkgLSB5T2Zmc2V0OwogICAgfQogICAgcmV0dXJuIHNoYXBlOwogIH0KICBmdW5jdGlvbiBjb21wdXRlUm91bmRDb3JuZXIocGl2b3QsIHN0YXJ0UG9pbnQsIGVuZFBvaW50LCBjb3JuZXJUeXBlLCBsZWZ0SXNPdXRzaWRlLCBlbGxpcHNvaWQsIGZpbmFsUG9zaXRpb25zLCBzaGFwZSwgaGVpZ2h0LCBkdXBsaWNhdGVQb2ludHMpIHsKICAgIGNvbnN0IGFuZ2xlID0gQ2FydGVzaWFuM19kZWZhdWx0LmFuZ2xlQmV0d2VlbigKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHN0YXJ0UG9pbnQsIHBpdm90LCBzY3JhdGNoMSksCiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChlbmRQb2ludCwgcGl2b3QsIHNjcmF0Y2gyKQogICAgKTsKICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gY29ybmVyVHlwZSA9PT0gQ29ybmVyVHlwZV9kZWZhdWx0LkJFVkVMRUQgPyAwIDogTWF0aC5jZWlsKGFuZ2xlIC8gTWF0aF9kZWZhdWx0LnRvUmFkaWFucyg1KSk7CiAgICBsZXQgbTsKICAgIGlmIChsZWZ0SXNPdXRzaWRlKSB7CiAgICAgIG0gPSBNYXRyaXgzX2RlZmF1bHQuZnJvbVF1YXRlcm5pb24oCiAgICAgICAgUXVhdGVybmlvbl9kZWZhdWx0LmZyb21BeGlzQW5nbGUoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKHBpdm90LCBzY3JhdGNoMSksCiAgICAgICAgICBhbmdsZSAvIChncmFudWxhcml0eSArIDEpLAogICAgICAgICAgcXVhdGVyaW9uCiAgICAgICAgKSwKICAgICAgICByb3RNYXRyaXgKICAgICAgKTsKICAgIH0gZWxzZSB7CiAgICAgIG0gPSBNYXRyaXgzX2RlZmF1bHQuZnJvbVF1YXRlcm5pb24oCiAgICAgICAgUXVhdGVybmlvbl9kZWZhdWx0LmZyb21BeGlzQW5nbGUocGl2b3QsIGFuZ2xlIC8gKGdyYW51bGFyaXR5ICsgMSksIHF1YXRlcmlvbiksCiAgICAgICAgcm90TWF0cml4CiAgICAgICk7CiAgICB9CiAgICBsZXQgbGVmdDsKICAgIGxldCBzdXJmYWNlUG9pbnQ7CiAgICBzdGFydFBvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHN0YXJ0UG9pbnQsIHN0YXJ0UG9pbnRTY3JhdGNoKTsKICAgIGlmIChncmFudWxhcml0eSA+IDApIHsKICAgICAgY29uc3QgcmVwZWF0ID0gZHVwbGljYXRlUG9pbnRzID8gMiA6IDE7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZ3JhbnVsYXJpdHk7IGkrKykgewogICAgICAgIHN0YXJ0UG9pbnQgPSBNYXRyaXgzX2RlZmF1bHQubXVsdGlwbHlCeVZlY3RvcihtLCBzdGFydFBvaW50LCBzdGFydFBvaW50KTsKICAgICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHN0YXJ0UG9pbnQsIHBpdm90LCBzY3JhdGNoMSk7CiAgICAgICAgbGVmdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUobGVmdCwgbGVmdCk7CiAgICAgICAgaWYgKCFsZWZ0SXNPdXRzaWRlKSB7CiAgICAgICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShsZWZ0LCBsZWZ0KTsKICAgICAgICB9CiAgICAgICAgc3VyZmFjZVBvaW50ID0gZWxsaXBzb2lkLnNjYWxlVG9HZW9kZXRpY1N1cmZhY2Uoc3RhcnRQb2ludCwgc2NyYXRjaDIpOwogICAgICAgIGZpbmFsUG9zaXRpb25zID0gYWRkUG9zaXRpb24oCiAgICAgICAgICBzdXJmYWNlUG9pbnQsCiAgICAgICAgICBsZWZ0LAogICAgICAgICAgc2hhcGUsCiAgICAgICAgICBmaW5hbFBvc2l0aW9ucywKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIGhlaWdodCwKICAgICAgICAgIDEsCiAgICAgICAgICByZXBlYXQKICAgICAgICApOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHN0YXJ0UG9pbnQsIHBpdm90LCBzY3JhdGNoMSk7CiAgICAgIGxlZnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGxlZnQsIGxlZnQpOwogICAgICBpZiAoIWxlZnRJc091dHNpZGUpIHsKICAgICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShsZWZ0LCBsZWZ0KTsKICAgICAgfQogICAgICBzdXJmYWNlUG9pbnQgPSBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZShzdGFydFBvaW50LCBzY3JhdGNoMik7CiAgICAgIGZpbmFsUG9zaXRpb25zID0gYWRkUG9zaXRpb24oCiAgICAgICAgc3VyZmFjZVBvaW50LAogICAgICAgIGxlZnQsCiAgICAgICAgc2hhcGUsCiAgICAgICAgZmluYWxQb3NpdGlvbnMsCiAgICAgICAgZWxsaXBzb2lkLAogICAgICAgIGhlaWdodCwKICAgICAgICAxLAogICAgICAgIDEKICAgICAgKTsKICAgICAgZW5kUG9pbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoZW5kUG9pbnQsIHN0YXJ0UG9pbnRTY3JhdGNoKTsKICAgICAgbGVmdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChlbmRQb2ludCwgcGl2b3QsIHNjcmF0Y2gxKTsKICAgICAgbGVmdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUobGVmdCwgbGVmdCk7CiAgICAgIGlmICghbGVmdElzT3V0c2lkZSkgewogICAgICAgIGxlZnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKGxlZnQsIGxlZnQpOwogICAgICB9CiAgICAgIHN1cmZhY2VQb2ludCA9IGVsbGlwc29pZC5zY2FsZVRvR2VvZGV0aWNTdXJmYWNlKGVuZFBvaW50LCBzY3JhdGNoMik7CiAgICAgIGZpbmFsUG9zaXRpb25zID0gYWRkUG9zaXRpb24oCiAgICAgICAgc3VyZmFjZVBvaW50LAogICAgICAgIGxlZnQsCiAgICAgICAgc2hhcGUsCiAgICAgICAgZmluYWxQb3NpdGlvbnMsCiAgICAgICAgZWxsaXBzb2lkLAogICAgICAgIGhlaWdodCwKICAgICAgICAxLAogICAgICAgIDEKICAgICAgKTsKICAgIH0KICAgIHJldHVybiBmaW5hbFBvc2l0aW9uczsKICB9CiAgdmFyIHNjcmF0Y2gyQXJyYXksIHNjcmF0Y2hDYXJ0ZXNpYW4xNiwgc2NyYXRjaENhcnRlc2lhbjI2LCBzY3JhdGNoQ2FydGVzaWFuMzcsIHNjcmF0Y2hDYXJ0ZXNpYW40Mywgc2NyYXRjaENhcnRlc2lhbjUyLCBzY3JhdGNoQ2FydGVzaWFuNjIsIHNjcmF0Y2hDYXJ0ZXNpYW43LCBzY3JhdGNoQ2FydGVzaWFuOCwgc2NyYXRjaENhcnRlc2lhbjksIHNjcmF0Y2gxLCBzY3JhdGNoMiwgUG9seWxpbmVWb2x1bWVHZW9tZXRyeUxpYnJhcnksIGNhcnRvZ3JhcGhpYywgbmV4dFNjcmF0Y2gsIHByZXZTY3JhdGNoLCBuZWdhdGl2ZVgsIHRyYW5zZm9ybSwgdHJhbnNsYXRpb24sIHJvdGF0aW9uWiwgc2NhbGVNYXRyaXgsIHdlc3RTY3JhdGNoLCBmaW5hbFBvc1NjcmF0Y2gsIGhlaWdodENhcnRlc2lhbiwgY2VudGVyU2NyYXRjaDIsIHF1YXRlcmlvbiwgc3RhcnRQb2ludFNjcmF0Y2gsIHJvdE1hdHJpeCwgc2NyYXRjaEZvcndhcmRQcm9qZWN0aW9uLCBzY3JhdGNoQmFja3dhcmRQcm9qZWN0aW9uLCBQb2x5bGluZVZvbHVtZUdlb21ldHJ5TGlicmFyeV9kZWZhdWx0OwogIHZhciBpbml0X1BvbHlsaW5lVm9sdW1lR2VvbWV0cnlMaWJyYXJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Qb2x5bGluZVZvbHVtZUdlb21ldHJ5TGlicmFyeS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMigpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW40KCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfQ29ybmVyVHlwZSgpOwogICAgICBpbml0X0VsbGlwc29pZFRhbmdlbnRQbGFuZSgpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9NYXRyaXgzKCk7CiAgICAgIGluaXRfTWF0cml4NCgpOwogICAgICBpbml0X1BvbHlsaW5lUGlwZWxpbmUoKTsKICAgICAgaW5pdF9RdWF0ZXJuaW9uKCk7CiAgICAgIGluaXRfVHJhbnNmb3JtcygpOwogICAgICBpbml0X29uZVRpbWVXYXJuaW5nKCk7CiAgICAgIHNjcmF0Y2gyQXJyYXkgPSBbbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpLCBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCldOwogICAgICBzY3JhdGNoQ2FydGVzaWFuMTYgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4yNiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjM3ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydGVzaWFuNDMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW41MiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjYyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydGVzaWFuNyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW45ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoMSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaDIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIFBvbHlsaW5lVm9sdW1lR2VvbWV0cnlMaWJyYXJ5ID0ge307CiAgICAgIGNhcnRvZ3JhcGhpYyA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBuZXh0U2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgcHJldlNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIG5lZ2F0aXZlWCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoLTEsIDAsIDApOwogICAgICB0cmFuc2Zvcm0gPSBuZXcgTWF0cml4NF9kZWZhdWx0KCk7CiAgICAgIHRyYW5zbGF0aW9uID0gbmV3IE1hdHJpeDRfZGVmYXVsdCgpOwogICAgICByb3RhdGlvblogPSBuZXcgTWF0cml4M19kZWZhdWx0KCk7CiAgICAgIHNjYWxlTWF0cml4ID0gTWF0cml4M19kZWZhdWx0LklERU5USVRZLmNsb25lKCk7CiAgICAgIHdlc3RTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBmaW5hbFBvc1NjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KCk7CiAgICAgIGhlaWdodENhcnRlc2lhbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgY2VudGVyU2NyYXRjaDIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHF1YXRlcmlvbiA9IG5ldyBRdWF0ZXJuaW9uX2RlZmF1bHQoKTsKICAgICAgc3RhcnRQb2ludFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHJvdE1hdHJpeCA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgUG9seWxpbmVWb2x1bWVHZW9tZXRyeUxpYnJhcnkucmVtb3ZlRHVwbGljYXRlc0Zyb21TaGFwZSA9IGZ1bmN0aW9uKHNoYXBlUG9zaXRpb25zKSB7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gc2hhcGVQb3NpdGlvbnMubGVuZ3RoOwogICAgICAgIGNvbnN0IGNsZWFuZWRQb3NpdGlvbnMgPSBbXTsKICAgICAgICBmb3IgKGxldCBpMCA9IGxlbmd0aCAtIDEsIGkxID0gMDsgaTEgPCBsZW5ndGg7IGkwID0gaTErKykgewogICAgICAgICAgY29uc3QgdjAyID0gc2hhcGVQb3NpdGlvbnNbaTBdOwogICAgICAgICAgY29uc3QgdjEyID0gc2hhcGVQb3NpdGlvbnNbaTFdOwogICAgICAgICAgaWYgKCFDYXJ0ZXNpYW4yX2RlZmF1bHQuZXF1YWxzKHYwMiwgdjEyKSkgewogICAgICAgICAgICBjbGVhbmVkUG9zaXRpb25zLnB1c2godjEyKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNsZWFuZWRQb3NpdGlvbnM7CiAgICAgIH07CiAgICAgIFBvbHlsaW5lVm9sdW1lR2VvbWV0cnlMaWJyYXJ5LmFuZ2xlSXNHcmVhdGVyVGhhblBpID0gZnVuY3Rpb24oZm9yd2FyZCwgYmFja3dhcmQsIHBvc2l0aW9uLCBlbGxpcHNvaWQpIHsKICAgICAgICBjb25zdCB0YW5nZW50UGxhbmUgPSBuZXcgRWxsaXBzb2lkVGFuZ2VudFBsYW5lX2RlZmF1bHQocG9zaXRpb24sIGVsbGlwc29pZCk7CiAgICAgICAgY29uc3QgbmV4dCA9IHRhbmdlbnRQbGFuZS5wcm9qZWN0UG9pbnRPbnRvUGxhbmUoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHBvc2l0aW9uLCBmb3J3YXJkLCBuZXh0U2NyYXRjaCksCiAgICAgICAgICBuZXh0U2NyYXRjaAogICAgICAgICk7CiAgICAgICAgY29uc3QgcHJldiA9IHRhbmdlbnRQbGFuZS5wcm9qZWN0UG9pbnRPbnRvUGxhbmUoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHBvc2l0aW9uLCBiYWNrd2FyZCwgcHJldlNjcmF0Y2gpLAogICAgICAgICAgcHJldlNjcmF0Y2gKICAgICAgICApOwogICAgICAgIHJldHVybiBwcmV2LnggKiBuZXh0LnkgLSBwcmV2LnkgKiBuZXh0LnggPj0gMDsKICAgICAgfTsKICAgICAgc2NyYXRjaEZvcndhcmRQcm9qZWN0aW9uID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQmFja3dhcmRQcm9qZWN0aW9uID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBQb2x5bGluZVZvbHVtZUdlb21ldHJ5TGlicmFyeS5jb21wdXRlUG9zaXRpb25zID0gZnVuY3Rpb24ocG9zaXRpb25zLCBzaGFwZTJELCBib3VuZGluZ1JlY3RhbmdsZSwgZ2VvbWV0cnksIGR1cGxpY2F0ZVBvaW50cykgewogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IGdlb21ldHJ5Ll9lbGxpcHNvaWQ7CiAgICAgICAgY29uc3QgaGVpZ2h0cyA9IHNjYWxlVG9TdXJmYWNlKHBvc2l0aW9ucywgZWxsaXBzb2lkKTsKICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IGdlb21ldHJ5Ll9ncmFudWxhcml0eTsKICAgICAgICBjb25zdCBjb3JuZXJUeXBlID0gZ2VvbWV0cnkuX2Nvcm5lclR5cGU7CiAgICAgICAgY29uc3Qgc2hhcGVGb3JTaWRlcyA9IGR1cGxpY2F0ZVBvaW50cyA/IGNvbnZlcnRTaGFwZVRvM0REdXBsaWNhdGUoc2hhcGUyRCwgYm91bmRpbmdSZWN0YW5nbGUpIDogY29udmVydFNoYXBlVG8zRChzaGFwZTJELCBib3VuZGluZ1JlY3RhbmdsZSk7CiAgICAgICAgY29uc3Qgc2hhcGVGb3JFbmRzID0gZHVwbGljYXRlUG9pbnRzID8gY29udmVydFNoYXBlVG8zRChzaGFwZTJELCBib3VuZGluZ1JlY3RhbmdsZSkgOiB2b2lkIDA7CiAgICAgICAgY29uc3QgaGVpZ2h0T2Zmc2V0ID0gYm91bmRpbmdSZWN0YW5nbGUuaGVpZ2h0IC8gMjsKICAgICAgICBjb25zdCB3aWR0aCA9IGJvdW5kaW5nUmVjdGFuZ2xlLndpZHRoIC8gMjsKICAgICAgICBsZXQgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBsZXQgZmluYWxQb3NpdGlvbnMgPSBbXTsKICAgICAgICBsZXQgZW5kcyA9IGR1cGxpY2F0ZVBvaW50cyA/IFtdIDogdm9pZCAwOwogICAgICAgIGxldCBmb3J3YXJkID0gc2NyYXRjaENhcnRlc2lhbjE2OwogICAgICAgIGxldCBiYWNrd2FyZCA9IHNjcmF0Y2hDYXJ0ZXNpYW4yNjsKICAgICAgICBsZXQgY29ybmVyRGlyZWN0aW9uID0gc2NyYXRjaENhcnRlc2lhbjM3OwogICAgICAgIGxldCBzdXJmYWNlTm9ybWFsID0gc2NyYXRjaENhcnRlc2lhbjQzOwogICAgICAgIGxldCBwaXZvdCA9IHNjcmF0Y2hDYXJ0ZXNpYW41MjsKICAgICAgICBsZXQgc3RhcnQgPSBzY3JhdGNoQ2FydGVzaWFuNjI7CiAgICAgICAgbGV0IGVuZCA9IHNjcmF0Y2hDYXJ0ZXNpYW43OwogICAgICAgIGxldCBsZWZ0ID0gc2NyYXRjaENhcnRlc2lhbjg7CiAgICAgICAgbGV0IHByZXZpb3VzUG9zaXRpb24gPSBzY3JhdGNoQ2FydGVzaWFuOTsKICAgICAgICBsZXQgcG9zaXRpb24gPSBwb3NpdGlvbnNbMF07CiAgICAgICAgbGV0IG5leHRQb3NpdGlvbiA9IHBvc2l0aW9uc1sxXTsKICAgICAgICBzdXJmYWNlTm9ybWFsID0gZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbChwb3NpdGlvbiwgc3VyZmFjZU5vcm1hbCk7CiAgICAgICAgZm9yd2FyZCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChuZXh0UG9zaXRpb24sIHBvc2l0aW9uLCBmb3J3YXJkKTsKICAgICAgICBmb3J3YXJkID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShmb3J3YXJkLCBmb3J3YXJkKTsKICAgICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKHN1cmZhY2VOb3JtYWwsIGZvcndhcmQsIGxlZnQpOwogICAgICAgIGxlZnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGxlZnQsIGxlZnQpOwogICAgICAgIGxldCBoMCA9IGhlaWdodHNbMF07CiAgICAgICAgbGV0IGgxID0gaGVpZ2h0c1sxXTsKICAgICAgICBpZiAoZHVwbGljYXRlUG9pbnRzKSB7CiAgICAgICAgICBlbmRzID0gYWRkUG9zaXRpb24oCiAgICAgICAgICAgIHBvc2l0aW9uLAogICAgICAgICAgICBsZWZ0LAogICAgICAgICAgICBzaGFwZUZvckVuZHMsCiAgICAgICAgICAgIGVuZHMsCiAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgaDAgKyBoZWlnaHRPZmZzZXQsCiAgICAgICAgICAgIDEsCiAgICAgICAgICAgIDEKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHByZXZpb3VzUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocG9zaXRpb24sIHByZXZpb3VzUG9zaXRpb24pOwogICAgICAgIHBvc2l0aW9uID0gbmV4dFBvc2l0aW9uOwogICAgICAgIGJhY2t3YXJkID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShmb3J3YXJkLCBiYWNrd2FyZCk7CiAgICAgICAgbGV0IHN1YmRpdmlkZWRIZWlnaHRzOwogICAgICAgIGxldCBzdWJkaXZpZGVkUG9zaXRpb25zOwogICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgbGVuZ3RoIC0gMTsgaSsrKSB7CiAgICAgICAgICBjb25zdCByZXBlYXQgPSBkdXBsaWNhdGVQb2ludHMgPyAyIDogMTsKICAgICAgICAgIG5leHRQb3NpdGlvbiA9IHBvc2l0aW9uc1tpICsgMV07CiAgICAgICAgICBpZiAocG9zaXRpb24uZXF1YWxzKG5leHRQb3NpdGlvbikpIHsKICAgICAgICAgICAgb25lVGltZVdhcm5pbmdfZGVmYXVsdCgKICAgICAgICAgICAgICAiUG9zaXRpb25zIGFyZSB0b28gY2xvc2UgYW5kIGFyZSBjb25zaWRlcmVkIGVxdWl2YWxlbnQgd2l0aCByb3VuZGluZyBlcnJvci4iCiAgICAgICAgICAgICk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgZm9yd2FyZCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChuZXh0UG9zaXRpb24sIHBvc2l0aW9uLCBmb3J3YXJkKTsKICAgICAgICAgIGZvcndhcmQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGZvcndhcmQsIGZvcndhcmQpOwogICAgICAgICAgc3VyZmFjZU5vcm1hbCA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwocG9zaXRpb24sIHN1cmZhY2VOb3JtYWwpOwogICAgICAgICAgY29uc3QgZm9yd2FyZFByb2plY3Rpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICAgICAgc3VyZmFjZU5vcm1hbCwKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmRvdChmb3J3YXJkLCBzdXJmYWNlTm9ybWFsKSwKICAgICAgICAgICAgc2NyYXRjaEZvcndhcmRQcm9qZWN0aW9uCiAgICAgICAgICApOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGZvcndhcmQsIGZvcndhcmRQcm9qZWN0aW9uLCBmb3J3YXJkUHJvamVjdGlvbik7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGZvcndhcmRQcm9qZWN0aW9uLCBmb3J3YXJkUHJvamVjdGlvbik7CiAgICAgICAgICBjb25zdCBiYWNrd2FyZFByb2plY3Rpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICAgICAgc3VyZmFjZU5vcm1hbCwKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmRvdChiYWNrd2FyZCwgc3VyZmFjZU5vcm1hbCksCiAgICAgICAgICAgIHNjcmF0Y2hCYWNrd2FyZFByb2plY3Rpb24KICAgICAgICAgICk7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoYmFja3dhcmQsIGJhY2t3YXJkUHJvamVjdGlvbiwgYmFja3dhcmRQcm9qZWN0aW9uKTsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoYmFja3dhcmRQcm9qZWN0aW9uLCBiYWNrd2FyZFByb2plY3Rpb24pOwogICAgICAgICAgY29uc3QgZG9Db3JuZXIgPSAhTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICAgIE1hdGguYWJzKENhcnRlc2lhbjNfZGVmYXVsdC5kb3QoZm9yd2FyZFByb2plY3Rpb24sIGJhY2t3YXJkUHJvamVjdGlvbikpLAogICAgICAgICAgICAxLAogICAgICAgICAgICBNYXRoX2RlZmF1bHQuRVBTSUxPTjcKICAgICAgICAgICk7CiAgICAgICAgICBpZiAoZG9Db3JuZXIpIHsKICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZChmb3J3YXJkLCBiYWNrd2FyZCwgY29ybmVyRGlyZWN0aW9uKTsKICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShjb3JuZXJEaXJlY3Rpb24sIGNvcm5lckRpcmVjdGlvbik7CiAgICAgICAgICAgIGNvcm5lckRpcmVjdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcygKICAgICAgICAgICAgICBjb3JuZXJEaXJlY3Rpb24sCiAgICAgICAgICAgICAgc3VyZmFjZU5vcm1hbCwKICAgICAgICAgICAgICBjb3JuZXJEaXJlY3Rpb24KICAgICAgICAgICAgKTsKICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKAogICAgICAgICAgICAgIHN1cmZhY2VOb3JtYWwsCiAgICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uLAogICAgICAgICAgICAgIGNvcm5lckRpcmVjdGlvbgogICAgICAgICAgICApOwogICAgICAgICAgICBjb3JuZXJEaXJlY3Rpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGNvcm5lckRpcmVjdGlvbiwgY29ybmVyRGlyZWN0aW9uKTsKICAgICAgICAgICAgY29uc3Qgc2NhbGFyID0gMSAvIE1hdGgubWF4KAogICAgICAgICAgICAgIDAuMjUsCiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZSgKICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhjb3JuZXJEaXJlY3Rpb24sIGJhY2t3YXJkLCBzY3JhdGNoMSkKICAgICAgICAgICAgICApCiAgICAgICAgICAgICk7CiAgICAgICAgICAgIGNvbnN0IGxlZnRJc091dHNpZGUgPSBQb2x5bGluZVZvbHVtZUdlb21ldHJ5TGlicmFyeS5hbmdsZUlzR3JlYXRlclRoYW5QaSgKICAgICAgICAgICAgICBmb3J3YXJkLAogICAgICAgICAgICAgIGJhY2t3YXJkLAogICAgICAgICAgICAgIHBvc2l0aW9uLAogICAgICAgICAgICAgIGVsbGlwc29pZAogICAgICAgICAgICApOwogICAgICAgICAgICBpZiAobGVmdElzT3V0c2lkZSkgewogICAgICAgICAgICAgIHBpdm90ID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZCgKICAgICAgICAgICAgICAgIHBvc2l0aW9uLAogICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgICAgICAgICAgIGNvcm5lckRpcmVjdGlvbiwKICAgICAgICAgICAgICAgICAgc2NhbGFyICogd2lkdGgsCiAgICAgICAgICAgICAgICAgIGNvcm5lckRpcmVjdGlvbgogICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgIHBpdm90CiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBzdGFydCA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoCiAgICAgICAgICAgICAgICBwaXZvdCwKICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGxlZnQsIHdpZHRoLCBzdGFydCksCiAgICAgICAgICAgICAgICBzdGFydAogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgc2NyYXRjaDJBcnJheVswXSA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShwcmV2aW91c1Bvc2l0aW9uLCBzY3JhdGNoMkFycmF5WzBdKTsKICAgICAgICAgICAgICBzY3JhdGNoMkFycmF5WzFdID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHN0YXJ0LCBzY3JhdGNoMkFycmF5WzFdKTsKICAgICAgICAgICAgICBzdWJkaXZpZGVkSGVpZ2h0cyA9IHN1YmRpdmlkZUhlaWdodHMyKAogICAgICAgICAgICAgICAgc2NyYXRjaDJBcnJheSwKICAgICAgICAgICAgICAgIGgwICsgaGVpZ2h0T2Zmc2V0LAogICAgICAgICAgICAgICAgaDEgKyBoZWlnaHRPZmZzZXQsCiAgICAgICAgICAgICAgICBncmFudWxhcml0eQogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9ucyA9IFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdC5nZW5lcmF0ZUFyYyh7CiAgICAgICAgICAgICAgICBwb3NpdGlvbnM6IHNjcmF0Y2gyQXJyYXksCiAgICAgICAgICAgICAgICBncmFudWxhcml0eSwKICAgICAgICAgICAgICAgIGVsbGlwc29pZAogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIGZpbmFsUG9zaXRpb25zID0gYWRkUG9zaXRpb25zKAogICAgICAgICAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9ucywKICAgICAgICAgICAgICAgIGxlZnQsCiAgICAgICAgICAgICAgICBzaGFwZUZvclNpZGVzLAogICAgICAgICAgICAgICAgZmluYWxQb3NpdGlvbnMsCiAgICAgICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgICAgICBzdWJkaXZpZGVkSGVpZ2h0cywKICAgICAgICAgICAgICAgIDEKICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIGxlZnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3Moc3VyZmFjZU5vcm1hbCwgZm9yd2FyZCwgbGVmdCk7CiAgICAgICAgICAgICAgbGVmdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUobGVmdCwgbGVmdCk7CiAgICAgICAgICAgICAgZW5kID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZCgKICAgICAgICAgICAgICAgIHBpdm90LAogICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobGVmdCwgd2lkdGgsIGVuZCksCiAgICAgICAgICAgICAgICBlbmQKICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIGlmIChjb3JuZXJUeXBlID09PSBDb3JuZXJUeXBlX2RlZmF1bHQuUk9VTkRFRCB8fCBjb3JuZXJUeXBlID09PSBDb3JuZXJUeXBlX2RlZmF1bHQuQkVWRUxFRCkgewogICAgICAgICAgICAgICAgY29tcHV0ZVJvdW5kQ29ybmVyKAogICAgICAgICAgICAgICAgICBwaXZvdCwKICAgICAgICAgICAgICAgICAgc3RhcnQsCiAgICAgICAgICAgICAgICAgIGVuZCwKICAgICAgICAgICAgICAgICAgY29ybmVyVHlwZSwKICAgICAgICAgICAgICAgICAgbGVmdElzT3V0c2lkZSwKICAgICAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgICAgICBmaW5hbFBvc2l0aW9ucywKICAgICAgICAgICAgICAgICAgc2hhcGVGb3JTaWRlcywKICAgICAgICAgICAgICAgICAgaDEgKyBoZWlnaHRPZmZzZXQsCiAgICAgICAgICAgICAgICAgIGR1cGxpY2F0ZVBvaW50cwogICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShjb3JuZXJEaXJlY3Rpb24sIGNvcm5lckRpcmVjdGlvbik7CiAgICAgICAgICAgICAgICBmaW5hbFBvc2l0aW9ucyA9IGFkZFBvc2l0aW9uKAogICAgICAgICAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uLAogICAgICAgICAgICAgICAgICBzaGFwZUZvclNpZGVzLAogICAgICAgICAgICAgICAgICBmaW5hbFBvc2l0aW9ucywKICAgICAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgICAgICBoMSArIGhlaWdodE9mZnNldCwKICAgICAgICAgICAgICAgICAgc2NhbGFyLAogICAgICAgICAgICAgICAgICByZXBlYXQKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHByZXZpb3VzUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoZW5kLCBwcmV2aW91c1Bvc2l0aW9uKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBwaXZvdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoCiAgICAgICAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICAgICAgICAgICAgICBjb3JuZXJEaXJlY3Rpb24sCiAgICAgICAgICAgICAgICAgIHNjYWxhciAqIHdpZHRoLAogICAgICAgICAgICAgICAgICBjb3JuZXJEaXJlY3Rpb24KICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICBwaXZvdAogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgc3RhcnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKAogICAgICAgICAgICAgICAgcGl2b3QsCiAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihsZWZ0LCAtd2lkdGgsIHN0YXJ0KSwKICAgICAgICAgICAgICAgIHN0YXJ0CiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBzY3JhdGNoMkFycmF5WzBdID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHByZXZpb3VzUG9zaXRpb24sIHNjcmF0Y2gyQXJyYXlbMF0pOwogICAgICAgICAgICAgIHNjcmF0Y2gyQXJyYXlbMV0gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoc3RhcnQsIHNjcmF0Y2gyQXJyYXlbMV0pOwogICAgICAgICAgICAgIHN1YmRpdmlkZWRIZWlnaHRzID0gc3ViZGl2aWRlSGVpZ2h0czIoCiAgICAgICAgICAgICAgICBzY3JhdGNoMkFycmF5LAogICAgICAgICAgICAgICAgaDAgKyBoZWlnaHRPZmZzZXQsCiAgICAgICAgICAgICAgICBoMSArIGhlaWdodE9mZnNldCwKICAgICAgICAgICAgICAgIGdyYW51bGFyaXR5CiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zID0gUG9seWxpbmVQaXBlbGluZV9kZWZhdWx0LmdlbmVyYXRlQXJjKHsKICAgICAgICAgICAgICAgIHBvc2l0aW9uczogc2NyYXRjaDJBcnJheSwKICAgICAgICAgICAgICAgIGdyYW51bGFyaXR5LAogICAgICAgICAgICAgICAgZWxsaXBzb2lkCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgZmluYWxQb3NpdGlvbnMgPSBhZGRQb3NpdGlvbnMoCiAgICAgICAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zLAogICAgICAgICAgICAgICAgbGVmdCwKICAgICAgICAgICAgICAgIHNoYXBlRm9yU2lkZXMsCiAgICAgICAgICAgICAgICBmaW5hbFBvc2l0aW9ucywKICAgICAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgICAgIHN1YmRpdmlkZWRIZWlnaHRzLAogICAgICAgICAgICAgICAgMQogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgbGVmdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhzdXJmYWNlTm9ybWFsLCBmb3J3YXJkLCBsZWZ0KTsKICAgICAgICAgICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShsZWZ0LCBsZWZ0KTsKICAgICAgICAgICAgICBlbmQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKAogICAgICAgICAgICAgICAgcGl2b3QsCiAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihsZWZ0LCAtd2lkdGgsIGVuZCksCiAgICAgICAgICAgICAgICBlbmQKICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIGlmIChjb3JuZXJUeXBlID09PSBDb3JuZXJUeXBlX2RlZmF1bHQuUk9VTkRFRCB8fCBjb3JuZXJUeXBlID09PSBDb3JuZXJUeXBlX2RlZmF1bHQuQkVWRUxFRCkgewogICAgICAgICAgICAgICAgY29tcHV0ZVJvdW5kQ29ybmVyKAogICAgICAgICAgICAgICAgICBwaXZvdCwKICAgICAgICAgICAgICAgICAgc3RhcnQsCiAgICAgICAgICAgICAgICAgIGVuZCwKICAgICAgICAgICAgICAgICAgY29ybmVyVHlwZSwKICAgICAgICAgICAgICAgICAgbGVmdElzT3V0c2lkZSwKICAgICAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgICAgICBmaW5hbFBvc2l0aW9ucywKICAgICAgICAgICAgICAgICAgc2hhcGVGb3JTaWRlcywKICAgICAgICAgICAgICAgICAgaDEgKyBoZWlnaHRPZmZzZXQsCiAgICAgICAgICAgICAgICAgIGR1cGxpY2F0ZVBvaW50cwogICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZmluYWxQb3NpdGlvbnMgPSBhZGRQb3NpdGlvbigKICAgICAgICAgICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICAgICAgICAgIGNvcm5lckRpcmVjdGlvbiwKICAgICAgICAgICAgICAgICAgc2hhcGVGb3JTaWRlcywKICAgICAgICAgICAgICAgICAgZmluYWxQb3NpdGlvbnMsCiAgICAgICAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgICAgICAgaDEgKyBoZWlnaHRPZmZzZXQsCiAgICAgICAgICAgICAgICAgIHNjYWxhciwKICAgICAgICAgICAgICAgICAgcmVwZWF0CiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBwcmV2aW91c1Bvc2l0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGVuZCwgcHJldmlvdXNQb3NpdGlvbik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYmFja3dhcmQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKGZvcndhcmQsIGJhY2t3YXJkKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZpbmFsUG9zaXRpb25zID0gYWRkUG9zaXRpb24oCiAgICAgICAgICAgICAgcHJldmlvdXNQb3NpdGlvbiwKICAgICAgICAgICAgICBsZWZ0LAogICAgICAgICAgICAgIHNoYXBlRm9yU2lkZXMsCiAgICAgICAgICAgICAgZmluYWxQb3NpdGlvbnMsCiAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgIGgwICsgaGVpZ2h0T2Zmc2V0LAogICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgMQogICAgICAgICAgICApOwogICAgICAgICAgICBwcmV2aW91c1Bvc2l0aW9uID0gcG9zaXRpb247CiAgICAgICAgICB9CiAgICAgICAgICBoMCA9IGgxOwogICAgICAgICAgaDEgPSBoZWlnaHRzW2kgKyAxXTsKICAgICAgICAgIHBvc2l0aW9uID0gbmV4dFBvc2l0aW9uOwogICAgICAgIH0KICAgICAgICBzY3JhdGNoMkFycmF5WzBdID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHByZXZpb3VzUG9zaXRpb24sIHNjcmF0Y2gyQXJyYXlbMF0pOwogICAgICAgIHNjcmF0Y2gyQXJyYXlbMV0gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocG9zaXRpb24sIHNjcmF0Y2gyQXJyYXlbMV0pOwogICAgICAgIHN1YmRpdmlkZWRIZWlnaHRzID0gc3ViZGl2aWRlSGVpZ2h0czIoCiAgICAgICAgICBzY3JhdGNoMkFycmF5LAogICAgICAgICAgaDAgKyBoZWlnaHRPZmZzZXQsCiAgICAgICAgICBoMSArIGhlaWdodE9mZnNldCwKICAgICAgICAgIGdyYW51bGFyaXR5CiAgICAgICAgKTsKICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zID0gUG9seWxpbmVQaXBlbGluZV9kZWZhdWx0LmdlbmVyYXRlQXJjKHsKICAgICAgICAgIHBvc2l0aW9uczogc2NyYXRjaDJBcnJheSwKICAgICAgICAgIGdyYW51bGFyaXR5LAogICAgICAgICAgZWxsaXBzb2lkCiAgICAgICAgfSk7CiAgICAgICAgZmluYWxQb3NpdGlvbnMgPSBhZGRQb3NpdGlvbnMoCiAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zLAogICAgICAgICAgbGVmdCwKICAgICAgICAgIHNoYXBlRm9yU2lkZXMsCiAgICAgICAgICBmaW5hbFBvc2l0aW9ucywKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIHN1YmRpdmlkZWRIZWlnaHRzLAogICAgICAgICAgMQogICAgICAgICk7CiAgICAgICAgaWYgKGR1cGxpY2F0ZVBvaW50cykgewogICAgICAgICAgZW5kcyA9IGFkZFBvc2l0aW9uKAogICAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgICAgbGVmdCwKICAgICAgICAgICAgc2hhcGVGb3JFbmRzLAogICAgICAgICAgICBlbmRzLAogICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgIGgxICsgaGVpZ2h0T2Zmc2V0LAogICAgICAgICAgICAxLAogICAgICAgICAgICAxCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBsZW5ndGggPSBmaW5hbFBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgY29uc3QgcG9zTGVuZ3RoID0gZHVwbGljYXRlUG9pbnRzID8gbGVuZ3RoICsgZW5kcy5sZW5ndGggOiBsZW5ndGg7CiAgICAgICAgY29uc3QgY29tYmluZWRQb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KHBvc0xlbmd0aCk7CiAgICAgICAgY29tYmluZWRQb3NpdGlvbnMuc2V0KGZpbmFsUG9zaXRpb25zKTsKICAgICAgICBpZiAoZHVwbGljYXRlUG9pbnRzKSB7CiAgICAgICAgICBjb21iaW5lZFBvc2l0aW9ucy5zZXQoZW5kcywgbGVuZ3RoKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGNvbWJpbmVkUG9zaXRpb25zOwogICAgICB9OwogICAgICBQb2x5bGluZVZvbHVtZUdlb21ldHJ5TGlicmFyeV9kZWZhdWx0ID0gUG9seWxpbmVWb2x1bWVHZW9tZXRyeUxpYnJhcnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Db3JyaWRvckdlb21ldHJ5TGlicmFyeS5qcwogIGZ1bmN0aW9uIGNvbXB1dGVSb3VuZENvcm5lcjIoY29ybmVyUG9pbnQsIHN0YXJ0UG9pbnQsIGVuZFBvaW50LCBjb3JuZXJUeXBlLCBsZWZ0SXNPdXRzaWRlKSB7CiAgICBjb25zdCBhbmdsZSA9IENhcnRlc2lhbjNfZGVmYXVsdC5hbmdsZUJldHdlZW4oCiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChzdGFydFBvaW50LCBjb3JuZXJQb2ludCwgc2NyYXRjaDEyKSwKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGVuZFBvaW50LCBjb3JuZXJQb2ludCwgc2NyYXRjaDIyKQogICAgKTsKICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gY29ybmVyVHlwZSA9PT0gQ29ybmVyVHlwZV9kZWZhdWx0LkJFVkVMRUQgPyAxIDogTWF0aC5jZWlsKGFuZ2xlIC8gTWF0aF9kZWZhdWx0LnRvUmFkaWFucyg1KSkgKyAxOwogICAgY29uc3Qgc2l6ZSA9IGdyYW51bGFyaXR5ICogMzsKICAgIGNvbnN0IGFycmF5ID0gbmV3IEFycmF5KHNpemUpOwogICAgYXJyYXlbc2l6ZSAtIDNdID0gZW5kUG9pbnQueDsKICAgIGFycmF5W3NpemUgLSAyXSA9IGVuZFBvaW50Lnk7CiAgICBhcnJheVtzaXplIC0gMV0gPSBlbmRQb2ludC56OwogICAgbGV0IG07CiAgICBpZiAobGVmdElzT3V0c2lkZSkgewogICAgICBtID0gTWF0cml4M19kZWZhdWx0LmZyb21RdWF0ZXJuaW9uKAogICAgICAgIFF1YXRlcm5pb25fZGVmYXVsdC5mcm9tQXhpc0FuZ2xlKAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShjb3JuZXJQb2ludCwgc2NyYXRjaDEyKSwKICAgICAgICAgIGFuZ2xlIC8gZ3JhbnVsYXJpdHksCiAgICAgICAgICBxdWF0ZXJpb24yCiAgICAgICAgKSwKICAgICAgICByb3RNYXRyaXgyCiAgICAgICk7CiAgICB9IGVsc2UgewogICAgICBtID0gTWF0cml4M19kZWZhdWx0LmZyb21RdWF0ZXJuaW9uKAogICAgICAgIFF1YXRlcm5pb25fZGVmYXVsdC5mcm9tQXhpc0FuZ2xlKGNvcm5lclBvaW50LCBhbmdsZSAvIGdyYW51bGFyaXR5LCBxdWF0ZXJpb24yKSwKICAgICAgICByb3RNYXRyaXgyCiAgICAgICk7CiAgICB9CiAgICBsZXQgaW5kZXggPSAwOwogICAgc3RhcnRQb2ludCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShzdGFydFBvaW50LCBzY3JhdGNoMTIpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBncmFudWxhcml0eTsgaSsrKSB7CiAgICAgIHN0YXJ0UG9pbnQgPSBNYXRyaXgzX2RlZmF1bHQubXVsdGlwbHlCeVZlY3RvcihtLCBzdGFydFBvaW50LCBzdGFydFBvaW50KTsKICAgICAgYXJyYXlbaW5kZXgrK10gPSBzdGFydFBvaW50Lng7CiAgICAgIGFycmF5W2luZGV4KytdID0gc3RhcnRQb2ludC55OwogICAgICBhcnJheVtpbmRleCsrXSA9IHN0YXJ0UG9pbnQuejsKICAgIH0KICAgIHJldHVybiBhcnJheTsKICB9CiAgZnVuY3Rpb24gYWRkRW5kQ2FwcyhjYWxjdWxhdGVkUG9zaXRpb25zKSB7CiAgICBsZXQgY29ybmVyUG9pbnQgPSBjYXJ0ZXNpYW4xOwogICAgbGV0IHN0YXJ0UG9pbnQgPSBjYXJ0ZXNpYW4yOwogICAgbGV0IGVuZFBvaW50ID0gY2FydGVzaWFuMzsKICAgIGxldCBsZWZ0RWRnZSA9IGNhbGN1bGF0ZWRQb3NpdGlvbnNbMV07CiAgICBzdGFydFBvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgY2FsY3VsYXRlZFBvc2l0aW9uc1sxXSwKICAgICAgbGVmdEVkZ2UubGVuZ3RoIC0gMywKICAgICAgc3RhcnRQb2ludAogICAgKTsKICAgIGVuZFBvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShjYWxjdWxhdGVkUG9zaXRpb25zWzBdLCAwLCBlbmRQb2ludCk7CiAgICBjb3JuZXJQb2ludCA9IENhcnRlc2lhbjNfZGVmYXVsdC5taWRwb2ludChzdGFydFBvaW50LCBlbmRQb2ludCwgY29ybmVyUG9pbnQpOwogICAgY29uc3QgZmlyc3RFbmRDYXAgPSBjb21wdXRlUm91bmRDb3JuZXIyKAogICAgICBjb3JuZXJQb2ludCwKICAgICAgc3RhcnRQb2ludCwKICAgICAgZW5kUG9pbnQsCiAgICAgIENvcm5lclR5cGVfZGVmYXVsdC5ST1VOREVELAogICAgICBmYWxzZQogICAgKTsKICAgIGNvbnN0IGxlbmd0aCA9IGNhbGN1bGF0ZWRQb3NpdGlvbnMubGVuZ3RoIC0gMTsKICAgIGNvbnN0IHJpZ2h0RWRnZSA9IGNhbGN1bGF0ZWRQb3NpdGlvbnNbbGVuZ3RoIC0gMV07CiAgICBsZWZ0RWRnZSA9IGNhbGN1bGF0ZWRQb3NpdGlvbnNbbGVuZ3RoXTsKICAgIHN0YXJ0UG9pbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICByaWdodEVkZ2UsCiAgICAgIHJpZ2h0RWRnZS5sZW5ndGggLSAzLAogICAgICBzdGFydFBvaW50CiAgICApOwogICAgZW5kUG9pbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KGxlZnRFZGdlLCAwLCBlbmRQb2ludCk7CiAgICBjb3JuZXJQb2ludCA9IENhcnRlc2lhbjNfZGVmYXVsdC5taWRwb2ludChzdGFydFBvaW50LCBlbmRQb2ludCwgY29ybmVyUG9pbnQpOwogICAgY29uc3QgbGFzdEVuZENhcCA9IGNvbXB1dGVSb3VuZENvcm5lcjIoCiAgICAgIGNvcm5lclBvaW50LAogICAgICBzdGFydFBvaW50LAogICAgICBlbmRQb2ludCwKICAgICAgQ29ybmVyVHlwZV9kZWZhdWx0LlJPVU5ERUQsCiAgICAgIGZhbHNlCiAgICApOwogICAgcmV0dXJuIFtmaXJzdEVuZENhcCwgbGFzdEVuZENhcF07CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVNaXRlcmVkQ29ybmVyKHBvc2l0aW9uLCBsZWZ0Q29ybmVyRGlyZWN0aW9uLCBsYXN0UG9pbnQsIGxlZnRJc091dHNpZGUpIHsKICAgIGxldCBjb3JuZXJQb2ludCA9IHNjcmF0Y2gxMjsKICAgIGlmIChsZWZ0SXNPdXRzaWRlKSB7CiAgICAgIGNvcm5lclBvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZChwb3NpdGlvbiwgbGVmdENvcm5lckRpcmVjdGlvbiwgY29ybmVyUG9pbnQpOwogICAgfSBlbHNlIHsKICAgICAgbGVmdENvcm5lckRpcmVjdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoCiAgICAgICAgbGVmdENvcm5lckRpcmVjdGlvbiwKICAgICAgICBsZWZ0Q29ybmVyRGlyZWN0aW9uCiAgICAgICk7CiAgICAgIGNvcm5lclBvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZChwb3NpdGlvbiwgbGVmdENvcm5lckRpcmVjdGlvbiwgY29ybmVyUG9pbnQpOwogICAgfQogICAgcmV0dXJuIFsKICAgICAgY29ybmVyUG9pbnQueCwKICAgICAgY29ybmVyUG9pbnQueSwKICAgICAgY29ybmVyUG9pbnQueiwKICAgICAgbGFzdFBvaW50LngsCiAgICAgIGxhc3RQb2ludC55LAogICAgICBsYXN0UG9pbnQuegogICAgXTsKICB9CiAgZnVuY3Rpb24gYWRkU2hpZnRlZFBvc2l0aW9ucyhwb3NpdGlvbnMsIGxlZnQsIHNjYWxhciwgY2FsY3VsYXRlZFBvc2l0aW9ucykgewogICAgY29uc3QgcmlnaHRQb3NpdGlvbnMgPSBuZXcgQXJyYXkocG9zaXRpb25zLmxlbmd0aCk7CiAgICBjb25zdCBsZWZ0UG9zaXRpb25zID0gbmV3IEFycmF5KHBvc2l0aW9ucy5sZW5ndGgpOwogICAgY29uc3Qgc2NhbGVkTGVmdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGxlZnQsIHNjYWxhciwgc2NyYXRjaDEyKTsKICAgIGNvbnN0IHNjYWxlZFJpZ2h0ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShzY2FsZWRMZWZ0LCBzY3JhdGNoMjIpOwogICAgbGV0IHJpZ2h0SW5kZXggPSAwOwogICAgbGV0IGxlZnRJbmRleCA9IHBvc2l0aW9ucy5sZW5ndGggLSAxOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyBpICs9IDMpIHsKICAgICAgY29uc3QgcG9zID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIGksIHNjcmF0Y2gzKTsKICAgICAgY29uc3QgcmlnaHRQb3MgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHBvcywgc2NhbGVkUmlnaHQsIHNjcmF0Y2g0KTsKICAgICAgcmlnaHRQb3NpdGlvbnNbcmlnaHRJbmRleCsrXSA9IHJpZ2h0UG9zLng7CiAgICAgIHJpZ2h0UG9zaXRpb25zW3JpZ2h0SW5kZXgrK10gPSByaWdodFBvcy55OwogICAgICByaWdodFBvc2l0aW9uc1tyaWdodEluZGV4KytdID0gcmlnaHRQb3MuejsKICAgICAgY29uc3QgbGVmdFBvcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocG9zLCBzY2FsZWRMZWZ0LCBzY3JhdGNoNCk7CiAgICAgIGxlZnRQb3NpdGlvbnNbbGVmdEluZGV4LS1dID0gbGVmdFBvcy56OwogICAgICBsZWZ0UG9zaXRpb25zW2xlZnRJbmRleC0tXSA9IGxlZnRQb3MueTsKICAgICAgbGVmdFBvc2l0aW9uc1tsZWZ0SW5kZXgtLV0gPSBsZWZ0UG9zLng7CiAgICB9CiAgICBjYWxjdWxhdGVkUG9zaXRpb25zLnB1c2gocmlnaHRQb3NpdGlvbnMsIGxlZnRQb3NpdGlvbnMpOwogICAgcmV0dXJuIGNhbGN1bGF0ZWRQb3NpdGlvbnM7CiAgfQogIHZhciBDb3JyaWRvckdlb21ldHJ5TGlicmFyeSwgc2NyYXRjaDEyLCBzY3JhdGNoMjIsIHNjcmF0Y2gzLCBzY3JhdGNoNCwgc2NhbGVBcnJheTIsIGNhcnRlc2lhbjEsIGNhcnRlc2lhbjIsIGNhcnRlc2lhbjMsIGNhcnRlc2lhbjQsIGNhcnRlc2lhbjUsIGNhcnRlc2lhbjYsIGNhcnRlc2lhbjcsIGNhcnRlc2lhbjgsIGNhcnRlc2lhbjksIGNhcnRlc2lhbjEwLCBxdWF0ZXJpb24yLCByb3RNYXRyaXgyLCBzY3JhdGNoRm9yd2FyZFByb2plY3Rpb24yLCBzY3JhdGNoQmFja3dhcmRQcm9qZWN0aW9uMiwgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdDsKICB2YXIgaW5pdF9Db3JyaWRvckdlb21ldHJ5TGlicmFyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnkuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9Db3JuZXJUeXBlKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9NYXRyaXgzKCk7CiAgICAgIGluaXRfUG9seWxpbmVQaXBlbGluZSgpOwogICAgICBpbml0X1BvbHlsaW5lVm9sdW1lR2VvbWV0cnlMaWJyYXJ5KCk7CiAgICAgIGluaXRfUXVhdGVybmlvbigpOwogICAgICBDb3JyaWRvckdlb21ldHJ5TGlicmFyeSA9IHt9OwogICAgICBzY3JhdGNoMTIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2gyMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaDMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2g0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY2FsZUFycmF5MiA9IFtuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCksIG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKV07CiAgICAgIGNhcnRlc2lhbjEgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjYgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjcgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjkgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjEwID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBxdWF0ZXJpb24yID0gbmV3IFF1YXRlcm5pb25fZGVmYXVsdCgpOwogICAgICByb3RNYXRyaXgyID0gbmV3IE1hdHJpeDNfZGVmYXVsdCgpOwogICAgICBDb3JyaWRvckdlb21ldHJ5TGlicmFyeS5hZGRBdHRyaWJ1dGUgPSBmdW5jdGlvbihhdHRyaWJ1dGUsIHZhbHVlLCBmcm9udCwgYmFjaykgewogICAgICAgIGNvbnN0IHggPSB2YWx1ZS54OwogICAgICAgIGNvbnN0IHkgPSB2YWx1ZS55OwogICAgICAgIGNvbnN0IHogPSB2YWx1ZS56OwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZnJvbnQpKSB7CiAgICAgICAgICBhdHRyaWJ1dGVbZnJvbnRdID0geDsKICAgICAgICAgIGF0dHJpYnV0ZVtmcm9udCArIDFdID0geTsKICAgICAgICAgIGF0dHJpYnV0ZVtmcm9udCArIDJdID0gejsKICAgICAgICB9CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChiYWNrKSkgewogICAgICAgICAgYXR0cmlidXRlW2JhY2tdID0gejsKICAgICAgICAgIGF0dHJpYnV0ZVtiYWNrIC0gMV0gPSB5OwogICAgICAgICAgYXR0cmlidXRlW2JhY2sgLSAyXSA9IHg7CiAgICAgICAgfQogICAgICB9OwogICAgICBzY3JhdGNoRm9yd2FyZFByb2plY3Rpb24yID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQmFja3dhcmRQcm9qZWN0aW9uMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnkuY29tcHV0ZVBvc2l0aW9ucyA9IGZ1bmN0aW9uKHBhcmFtcykgewogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gcGFyYW1zLmdyYW51bGFyaXR5OwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IHBhcmFtcy5wb3NpdGlvbnM7CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gcGFyYW1zLmVsbGlwc29pZDsKICAgICAgICBjb25zdCB3aWR0aCA9IHBhcmFtcy53aWR0aCAvIDI7CiAgICAgICAgY29uc3QgY29ybmVyVHlwZSA9IHBhcmFtcy5jb3JuZXJUeXBlOwogICAgICAgIGNvbnN0IHNhdmVBdHRyaWJ1dGVzID0gcGFyYW1zLnNhdmVBdHRyaWJ1dGVzOwogICAgICAgIGxldCBub3JtYWwyID0gY2FydGVzaWFuMTsKICAgICAgICBsZXQgZm9yd2FyZCA9IGNhcnRlc2lhbjI7CiAgICAgICAgbGV0IGJhY2t3YXJkID0gY2FydGVzaWFuMzsKICAgICAgICBsZXQgbGVmdCA9IGNhcnRlc2lhbjQ7CiAgICAgICAgbGV0IGNvcm5lckRpcmVjdGlvbiA9IGNhcnRlc2lhbjU7CiAgICAgICAgbGV0IHN0YXJ0UG9pbnQgPSBjYXJ0ZXNpYW42OwogICAgICAgIGxldCBwcmV2aW91c1BvcyA9IGNhcnRlc2lhbjc7CiAgICAgICAgbGV0IHJpZ2h0UG9zID0gY2FydGVzaWFuODsKICAgICAgICBsZXQgbGVmdFBvcyA9IGNhcnRlc2lhbjk7CiAgICAgICAgbGV0IGNlbnRlciA9IGNhcnRlc2lhbjEwOwogICAgICAgIGxldCBjYWxjdWxhdGVkUG9zaXRpb25zID0gW107CiAgICAgICAgY29uc3QgY2FsY3VsYXRlZExlZnRzID0gc2F2ZUF0dHJpYnV0ZXMgPyBbXSA6IHZvaWQgMDsKICAgICAgICBjb25zdCBjYWxjdWxhdGVkTm9ybWFscyA9IHNhdmVBdHRyaWJ1dGVzID8gW10gOiB2b2lkIDA7CiAgICAgICAgbGV0IHBvc2l0aW9uID0gcG9zaXRpb25zWzBdOwogICAgICAgIGxldCBuZXh0UG9zaXRpb24gPSBwb3NpdGlvbnNbMV07CiAgICAgICAgZm9yd2FyZCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QobmV4dFBvc2l0aW9uLCBwb3NpdGlvbiwgZm9yd2FyZCksCiAgICAgICAgICBmb3J3YXJkCiAgICAgICAgKTsKICAgICAgICBub3JtYWwyID0gZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbChwb3NpdGlvbiwgbm9ybWFsMik7CiAgICAgICAgbGVmdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKG5vcm1hbDIsIGZvcndhcmQsIGxlZnQpLCBsZWZ0KTsKICAgICAgICBpZiAoc2F2ZUF0dHJpYnV0ZXMpIHsKICAgICAgICAgIGNhbGN1bGF0ZWRMZWZ0cy5wdXNoKGxlZnQueCwgbGVmdC55LCBsZWZ0LnopOwogICAgICAgICAgY2FsY3VsYXRlZE5vcm1hbHMucHVzaChub3JtYWwyLngsIG5vcm1hbDIueSwgbm9ybWFsMi56KTsKICAgICAgICB9CiAgICAgICAgcHJldmlvdXNQb3MgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocG9zaXRpb24sIHByZXZpb3VzUG9zKTsKICAgICAgICBwb3NpdGlvbiA9IG5leHRQb3NpdGlvbjsKICAgICAgICBiYWNrd2FyZCA9IENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoZm9yd2FyZCwgYmFja3dhcmQpOwogICAgICAgIGxldCBzdWJkaXZpZGVkUG9zaXRpb25zOwogICAgICAgIGNvbnN0IGNvcm5lcnMgPSBbXTsKICAgICAgICBsZXQgaTsKICAgICAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgICAgIGZvciAoaSA9IDE7IGkgPCBsZW5ndGggLSAxOyBpKyspIHsKICAgICAgICAgIG5vcm1hbDIgPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKHBvc2l0aW9uLCBub3JtYWwyKTsKICAgICAgICAgIG5leHRQb3NpdGlvbiA9IHBvc2l0aW9uc1tpICsgMV07CiAgICAgICAgICBmb3J3YXJkID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KG5leHRQb3NpdGlvbiwgcG9zaXRpb24sIGZvcndhcmQpLAogICAgICAgICAgICBmb3J3YXJkCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgZm9yd2FyZFByb2plY3Rpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICAgICAgbm9ybWFsMiwKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmRvdChmb3J3YXJkLCBub3JtYWwyKSwKICAgICAgICAgICAgc2NyYXRjaEZvcndhcmRQcm9qZWN0aW9uMgogICAgICAgICAgKTsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChmb3J3YXJkLCBmb3J3YXJkUHJvamVjdGlvbiwgZm9yd2FyZFByb2plY3Rpb24pOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShmb3J3YXJkUHJvamVjdGlvbiwgZm9yd2FyZFByb2plY3Rpb24pOwogICAgICAgICAgY29uc3QgYmFja3dhcmRQcm9qZWN0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgICAgIG5vcm1hbDIsCiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5kb3QoYmFja3dhcmQsIG5vcm1hbDIpLAogICAgICAgICAgICBzY3JhdGNoQmFja3dhcmRQcm9qZWN0aW9uMgogICAgICAgICAgKTsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChiYWNrd2FyZCwgYmFja3dhcmRQcm9qZWN0aW9uLCBiYWNrd2FyZFByb2plY3Rpb24pOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShiYWNrd2FyZFByb2plY3Rpb24sIGJhY2t3YXJkUHJvamVjdGlvbik7CiAgICAgICAgICBjb25zdCBkb0Nvcm5lciA9ICFNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgICAgTWF0aC5hYnMoQ2FydGVzaWFuM19kZWZhdWx0LmRvdChmb3J3YXJkUHJvamVjdGlvbiwgYmFja3dhcmRQcm9qZWN0aW9uKSksCiAgICAgICAgICAgIDEsCiAgICAgICAgICAgIE1hdGhfZGVmYXVsdC5FUFNJTE9ONwogICAgICAgICAgKTsKICAgICAgICAgIGlmIChkb0Nvcm5lcikgewogICAgICAgICAgICBjb3JuZXJEaXJlY3Rpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoZm9yd2FyZCwgYmFja3dhcmQsIGNvcm5lckRpcmVjdGlvbiksCiAgICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uCiAgICAgICAgICAgICk7CiAgICAgICAgICAgIGNvcm5lckRpcmVjdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcygKICAgICAgICAgICAgICBjb3JuZXJEaXJlY3Rpb24sCiAgICAgICAgICAgICAgbm9ybWFsMiwKICAgICAgICAgICAgICBjb3JuZXJEaXJlY3Rpb24KICAgICAgICAgICAgKTsKICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKAogICAgICAgICAgICAgIG5vcm1hbDIsCiAgICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uLAogICAgICAgICAgICAgIGNvcm5lckRpcmVjdGlvbgogICAgICAgICAgICApOwogICAgICAgICAgICBjb3JuZXJEaXJlY3Rpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGNvcm5lckRpcmVjdGlvbiwgY29ybmVyRGlyZWN0aW9uKTsKICAgICAgICAgICAgY29uc3Qgc2NhbGFyID0gd2lkdGggLyBNYXRoLm1heCgKICAgICAgICAgICAgICAwLjI1LAogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tYWduaXR1ZGUoCiAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoY29ybmVyRGlyZWN0aW9uLCBiYWNrd2FyZCwgc2NyYXRjaDEyKQogICAgICAgICAgICAgICkKICAgICAgICAgICAgKTsKICAgICAgICAgICAgY29uc3QgbGVmdElzT3V0c2lkZSA9IFBvbHlsaW5lVm9sdW1lR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYW5nbGVJc0dyZWF0ZXJUaGFuUGkoCiAgICAgICAgICAgICAgZm9yd2FyZCwKICAgICAgICAgICAgICBiYWNrd2FyZCwKICAgICAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgICAgICBlbGxpcHNvaWQKICAgICAgICAgICAgKTsKICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uLAogICAgICAgICAgICAgIHNjYWxhciwKICAgICAgICAgICAgICBjb3JuZXJEaXJlY3Rpb24KICAgICAgICAgICAgKTsKICAgICAgICAgICAgaWYgKGxlZnRJc091dHNpZGUpIHsKICAgICAgICAgICAgICByaWdodFBvcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocG9zaXRpb24sIGNvcm5lckRpcmVjdGlvbiwgcmlnaHRQb3MpOwogICAgICAgICAgICAgIGNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoCiAgICAgICAgICAgICAgICByaWdodFBvcywKICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGxlZnQsIHdpZHRoLCBjZW50ZXIpLAogICAgICAgICAgICAgICAgY2VudGVyCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBsZWZ0UG9zID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZCgKICAgICAgICAgICAgICAgIHJpZ2h0UG9zLAogICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobGVmdCwgd2lkdGggKiAyLCBsZWZ0UG9zKSwKICAgICAgICAgICAgICAgIGxlZnRQb3MKICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIHNjYWxlQXJyYXkyWzBdID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHByZXZpb3VzUG9zLCBzY2FsZUFycmF5MlswXSk7CiAgICAgICAgICAgICAgc2NhbGVBcnJheTJbMV0gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoY2VudGVyLCBzY2FsZUFycmF5MlsxXSk7CiAgICAgICAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9ucyA9IFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdC5nZW5lcmF0ZUFyYyh7CiAgICAgICAgICAgICAgICBwb3NpdGlvbnM6IHNjYWxlQXJyYXkyLAogICAgICAgICAgICAgICAgZ3JhbnVsYXJpdHksCiAgICAgICAgICAgICAgICBlbGxpcHNvaWQKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICBjYWxjdWxhdGVkUG9zaXRpb25zID0gYWRkU2hpZnRlZFBvc2l0aW9ucygKICAgICAgICAgICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnMsCiAgICAgICAgICAgICAgICBsZWZ0LAogICAgICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgICAgICBjYWxjdWxhdGVkUG9zaXRpb25zCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBpZiAoc2F2ZUF0dHJpYnV0ZXMpIHsKICAgICAgICAgICAgICAgIGNhbGN1bGF0ZWRMZWZ0cy5wdXNoKGxlZnQueCwgbGVmdC55LCBsZWZ0LnopOwogICAgICAgICAgICAgICAgY2FsY3VsYXRlZE5vcm1hbHMucHVzaChub3JtYWwyLngsIG5vcm1hbDIueSwgbm9ybWFsMi56KTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgc3RhcnRQb2ludCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShsZWZ0UG9zLCBzdGFydFBvaW50KTsKICAgICAgICAgICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhub3JtYWwyLCBmb3J3YXJkLCBsZWZ0KSwKICAgICAgICAgICAgICAgIGxlZnQKICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIGxlZnRQb3MgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKAogICAgICAgICAgICAgICAgcmlnaHRQb3MsCiAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihsZWZ0LCB3aWR0aCAqIDIsIGxlZnRQb3MpLAogICAgICAgICAgICAgICAgbGVmdFBvcwogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgcHJldmlvdXNQb3MgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKAogICAgICAgICAgICAgICAgcmlnaHRQb3MsCiAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihsZWZ0LCB3aWR0aCwgcHJldmlvdXNQb3MpLAogICAgICAgICAgICAgICAgcHJldmlvdXNQb3MKICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIGlmIChjb3JuZXJUeXBlID09PSBDb3JuZXJUeXBlX2RlZmF1bHQuUk9VTkRFRCB8fCBjb3JuZXJUeXBlID09PSBDb3JuZXJUeXBlX2RlZmF1bHQuQkVWRUxFRCkgewogICAgICAgICAgICAgICAgY29ybmVycy5wdXNoKHsKICAgICAgICAgICAgICAgICAgbGVmdFBvc2l0aW9uczogY29tcHV0ZVJvdW5kQ29ybmVyMigKICAgICAgICAgICAgICAgICAgICByaWdodFBvcywKICAgICAgICAgICAgICAgICAgICBzdGFydFBvaW50LAogICAgICAgICAgICAgICAgICAgIGxlZnRQb3MsCiAgICAgICAgICAgICAgICAgICAgY29ybmVyVHlwZSwKICAgICAgICAgICAgICAgICAgICBsZWZ0SXNPdXRzaWRlCiAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBjb3JuZXJzLnB1c2goewogICAgICAgICAgICAgICAgICBsZWZ0UG9zaXRpb25zOiBjb21wdXRlTWl0ZXJlZENvcm5lcigKICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKGNvcm5lckRpcmVjdGlvbiwgY29ybmVyRGlyZWN0aW9uKSwKICAgICAgICAgICAgICAgICAgICBsZWZ0UG9zLAogICAgICAgICAgICAgICAgICAgIGxlZnRJc091dHNpZGUKICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGxlZnRQb3MgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHBvc2l0aW9uLCBjb3JuZXJEaXJlY3Rpb24sIGxlZnRQb3MpOwogICAgICAgICAgICAgIGNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoCiAgICAgICAgICAgICAgICBsZWZ0UG9zLAogICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZSgKICAgICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobGVmdCwgd2lkdGgsIGNlbnRlciksCiAgICAgICAgICAgICAgICAgIGNlbnRlcgogICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgIGNlbnRlcgogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgcmlnaHRQb3MgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKAogICAgICAgICAgICAgICAgbGVmdFBvcywKICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoCiAgICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGxlZnQsIHdpZHRoICogMiwgcmlnaHRQb3MpLAogICAgICAgICAgICAgICAgICByaWdodFBvcwogICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgIHJpZ2h0UG9zCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBzY2FsZUFycmF5MlswXSA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShwcmV2aW91c1Bvcywgc2NhbGVBcnJheTJbMF0pOwogICAgICAgICAgICAgIHNjYWxlQXJyYXkyWzFdID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGNlbnRlciwgc2NhbGVBcnJheTJbMV0pOwogICAgICAgICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnMgPSBQb2x5bGluZVBpcGVsaW5lX2RlZmF1bHQuZ2VuZXJhdGVBcmMoewogICAgICAgICAgICAgICAgcG9zaXRpb25zOiBzY2FsZUFycmF5MiwKICAgICAgICAgICAgICAgIGdyYW51bGFyaXR5LAogICAgICAgICAgICAgICAgZWxsaXBzb2lkCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgY2FsY3VsYXRlZFBvc2l0aW9ucyA9IGFkZFNoaWZ0ZWRQb3NpdGlvbnMoCiAgICAgICAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zLAogICAgICAgICAgICAgICAgbGVmdCwKICAgICAgICAgICAgICAgIHdpZHRoLAogICAgICAgICAgICAgICAgY2FsY3VsYXRlZFBvc2l0aW9ucwogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgaWYgKHNhdmVBdHRyaWJ1dGVzKSB7CiAgICAgICAgICAgICAgICBjYWxjdWxhdGVkTGVmdHMucHVzaChsZWZ0LngsIGxlZnQueSwgbGVmdC56KTsKICAgICAgICAgICAgICAgIGNhbGN1bGF0ZWROb3JtYWxzLnB1c2gobm9ybWFsMi54LCBub3JtYWwyLnksIG5vcm1hbDIueik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHN0YXJ0UG9pbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocmlnaHRQb3MsIHN0YXJ0UG9pbnQpOwogICAgICAgICAgICAgIGxlZnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKG5vcm1hbDIsIGZvcndhcmQsIGxlZnQpLAogICAgICAgICAgICAgICAgbGVmdAogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgcmlnaHRQb3MgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKAogICAgICAgICAgICAgICAgbGVmdFBvcywKICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoCiAgICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGxlZnQsIHdpZHRoICogMiwgcmlnaHRQb3MpLAogICAgICAgICAgICAgICAgICByaWdodFBvcwogICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgIHJpZ2h0UG9zCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBwcmV2aW91c1BvcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoCiAgICAgICAgICAgICAgICBsZWZ0UG9zLAogICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZSgKICAgICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIobGVmdCwgd2lkdGgsIHByZXZpb3VzUG9zKSwKICAgICAgICAgICAgICAgICAgcHJldmlvdXNQb3MKICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICBwcmV2aW91c1BvcwogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgaWYgKGNvcm5lclR5cGUgPT09IENvcm5lclR5cGVfZGVmYXVsdC5ST1VOREVEIHx8IGNvcm5lclR5cGUgPT09IENvcm5lclR5cGVfZGVmYXVsdC5CRVZFTEVEKSB7CiAgICAgICAgICAgICAgICBjb3JuZXJzLnB1c2goewogICAgICAgICAgICAgICAgICByaWdodFBvc2l0aW9uczogY29tcHV0ZVJvdW5kQ29ybmVyMigKICAgICAgICAgICAgICAgICAgICBsZWZ0UG9zLAogICAgICAgICAgICAgICAgICAgIHN0YXJ0UG9pbnQsCiAgICAgICAgICAgICAgICAgICAgcmlnaHRQb3MsCiAgICAgICAgICAgICAgICAgICAgY29ybmVyVHlwZSwKICAgICAgICAgICAgICAgICAgICBsZWZ0SXNPdXRzaWRlCiAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBjb3JuZXJzLnB1c2goewogICAgICAgICAgICAgICAgICByaWdodFBvc2l0aW9uczogY29tcHV0ZU1pdGVyZWRDb3JuZXIoCiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICAgICAgICAgICAgY29ybmVyRGlyZWN0aW9uLAogICAgICAgICAgICAgICAgICAgIHJpZ2h0UG9zLAogICAgICAgICAgICAgICAgICAgIGxlZnRJc091dHNpZGUKICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGJhY2t3YXJkID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShmb3J3YXJkLCBiYWNrd2FyZCk7CiAgICAgICAgICB9CiAgICAgICAgICBwb3NpdGlvbiA9IG5leHRQb3NpdGlvbjsKICAgICAgICB9CiAgICAgICAgbm9ybWFsMiA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwocG9zaXRpb24sIG5vcm1hbDIpOwogICAgICAgIHNjYWxlQXJyYXkyWzBdID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHByZXZpb3VzUG9zLCBzY2FsZUFycmF5MlswXSk7CiAgICAgICAgc2NhbGVBcnJheTJbMV0gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocG9zaXRpb24sIHNjYWxlQXJyYXkyWzFdKTsKICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zID0gUG9seWxpbmVQaXBlbGluZV9kZWZhdWx0LmdlbmVyYXRlQXJjKHsKICAgICAgICAgIHBvc2l0aW9uczogc2NhbGVBcnJheTIsCiAgICAgICAgICBncmFudWxhcml0eSwKICAgICAgICAgIGVsbGlwc29pZAogICAgICAgIH0pOwogICAgICAgIGNhbGN1bGF0ZWRQb3NpdGlvbnMgPSBhZGRTaGlmdGVkUG9zaXRpb25zKAogICAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9ucywKICAgICAgICAgIGxlZnQsCiAgICAgICAgICB3aWR0aCwKICAgICAgICAgIGNhbGN1bGF0ZWRQb3NpdGlvbnMKICAgICAgICApOwogICAgICAgIGlmIChzYXZlQXR0cmlidXRlcykgewogICAgICAgICAgY2FsY3VsYXRlZExlZnRzLnB1c2gobGVmdC54LCBsZWZ0LnksIGxlZnQueik7CiAgICAgICAgICBjYWxjdWxhdGVkTm9ybWFscy5wdXNoKG5vcm1hbDIueCwgbm9ybWFsMi55LCBub3JtYWwyLnopOwogICAgICAgIH0KICAgICAgICBsZXQgZW5kUG9zaXRpb25zOwogICAgICAgIGlmIChjb3JuZXJUeXBlID09PSBDb3JuZXJUeXBlX2RlZmF1bHQuUk9VTkRFRCkgewogICAgICAgICAgZW5kUG9zaXRpb25zID0gYWRkRW5kQ2FwcyhjYWxjdWxhdGVkUG9zaXRpb25zKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHBvc2l0aW9uczogY2FsY3VsYXRlZFBvc2l0aW9ucywKICAgICAgICAgIGNvcm5lcnMsCiAgICAgICAgICBsZWZ0czogY2FsY3VsYXRlZExlZnRzLAogICAgICAgICAgbm9ybWFsczogY2FsY3VsYXRlZE5vcm1hbHMsCiAgICAgICAgICBlbmRQb3NpdGlvbnMKICAgICAgICB9OwogICAgICB9OwogICAgICBDb3JyaWRvckdlb21ldHJ5TGlicmFyeV9kZWZhdWx0ID0gQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Db3JyaWRvckdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gc2NhbGVUb1N1cmZhY2UyKHBvc2l0aW9ucywgZWxsaXBzb2lkKSB7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBvc2l0aW9ucy5sZW5ndGg7IGkrKykgewogICAgICBwb3NpdGlvbnNbaV0gPSBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZShwb3NpdGlvbnNbaV0sIHBvc2l0aW9uc1tpXSk7CiAgICB9CiAgICByZXR1cm4gcG9zaXRpb25zOwogIH0KICBmdW5jdGlvbiBhZGROb3JtYWxzKGF0dHIsIG5vcm1hbDIsIGxlZnQsIGZyb250LCBiYWNrLCB2ZXJ0ZXhGb3JtYXQpIHsKICAgIGNvbnN0IG5vcm1hbHMgPSBhdHRyLm5vcm1hbHM7CiAgICBjb25zdCB0YW5nZW50cyA9IGF0dHIudGFuZ2VudHM7CiAgICBjb25zdCBiaXRhbmdlbnRzID0gYXR0ci5iaXRhbmdlbnRzOwogICAgY29uc3QgZm9yd2FyZCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhsZWZ0LCBub3JtYWwyLCBzY3JhdGNoMTMpLAogICAgICBzY3JhdGNoMTMKICAgICk7CiAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICBDb3JyaWRvckdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmFkZEF0dHJpYnV0ZShub3JtYWxzLCBub3JtYWwyLCBmcm9udCwgYmFjayk7CiAgICB9CiAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQpIHsKICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUodGFuZ2VudHMsIGZvcndhcmQsIGZyb250LCBiYWNrKTsKICAgIH0KICAgIGlmICh2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgIENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYWRkQXR0cmlidXRlKGJpdGFuZ2VudHMsIGxlZnQsIGZyb250LCBiYWNrKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gY29tYmluZTIoY29tcHV0ZWRQb3NpdGlvbnMsIHZlcnRleEZvcm1hdCwgZWxsaXBzb2lkKSB7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBjb21wdXRlZFBvc2l0aW9ucy5wb3NpdGlvbnM7CiAgICBjb25zdCBjb3JuZXJzID0gY29tcHV0ZWRQb3NpdGlvbnMuY29ybmVyczsKICAgIGNvbnN0IGVuZFBvc2l0aW9ucyA9IGNvbXB1dGVkUG9zaXRpb25zLmVuZFBvc2l0aW9uczsKICAgIGNvbnN0IGNvbXB1dGVkTGVmdHMgPSBjb21wdXRlZFBvc2l0aW9ucy5sZWZ0czsKICAgIGNvbnN0IGNvbXB1dGVkTm9ybWFscyA9IGNvbXB1dGVkUG9zaXRpb25zLm5vcm1hbHM7CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlc19kZWZhdWx0KCk7CiAgICBsZXQgY29ybmVyOwogICAgbGV0IGxlZnRDb3VudCA9IDA7CiAgICBsZXQgcmlnaHRDb3VudCA9IDA7CiAgICBsZXQgaTsKICAgIGxldCBpbmRpY2VzTGVuZ3RoID0gMDsKICAgIGxldCBsZW5ndGg7CiAgICBmb3IgKGkgPSAwOyBpIDwgcG9zaXRpb25zLmxlbmd0aDsgaSArPSAyKSB7CiAgICAgIGxlbmd0aCA9IHBvc2l0aW9uc1tpXS5sZW5ndGggLSAzOwogICAgICBsZWZ0Q291bnQgKz0gbGVuZ3RoOwogICAgICBpbmRpY2VzTGVuZ3RoICs9IGxlbmd0aCAqIDI7CiAgICAgIHJpZ2h0Q291bnQgKz0gcG9zaXRpb25zW2kgKyAxXS5sZW5ndGggLSAzOwogICAgfQogICAgbGVmdENvdW50ICs9IDM7CiAgICByaWdodENvdW50ICs9IDM7CiAgICBmb3IgKGkgPSAwOyBpIDwgY29ybmVycy5sZW5ndGg7IGkrKykgewogICAgICBjb3JuZXIgPSBjb3JuZXJzW2ldOwogICAgICBjb25zdCBsZWZ0U2lkZSA9IGNvcm5lcnNbaV0ubGVmdFBvc2l0aW9uczsKICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChsZWZ0U2lkZSkpIHsKICAgICAgICBsZW5ndGggPSBsZWZ0U2lkZS5sZW5ndGg7CiAgICAgICAgbGVmdENvdW50ICs9IGxlbmd0aDsKICAgICAgICBpbmRpY2VzTGVuZ3RoICs9IGxlbmd0aDsKICAgICAgfSBlbHNlIHsKICAgICAgICBsZW5ndGggPSBjb3JuZXJzW2ldLnJpZ2h0UG9zaXRpb25zLmxlbmd0aDsKICAgICAgICByaWdodENvdW50ICs9IGxlbmd0aDsKICAgICAgICBpbmRpY2VzTGVuZ3RoICs9IGxlbmd0aDsKICAgICAgfQogICAgfQogICAgY29uc3QgYWRkRW5kUG9zaXRpb25zID0gZGVmaW5lZF9kZWZhdWx0KGVuZFBvc2l0aW9ucyk7CiAgICBsZXQgZW5kUG9zaXRpb25MZW5ndGg7CiAgICBpZiAoYWRkRW5kUG9zaXRpb25zKSB7CiAgICAgIGVuZFBvc2l0aW9uTGVuZ3RoID0gZW5kUG9zaXRpb25zWzBdLmxlbmd0aCAtIDM7CiAgICAgIGxlZnRDb3VudCArPSBlbmRQb3NpdGlvbkxlbmd0aDsKICAgICAgcmlnaHRDb3VudCArPSBlbmRQb3NpdGlvbkxlbmd0aDsKICAgICAgZW5kUG9zaXRpb25MZW5ndGggLz0gMzsKICAgICAgaW5kaWNlc0xlbmd0aCArPSBlbmRQb3NpdGlvbkxlbmd0aCAqIDY7CiAgICB9CiAgICBjb25zdCBzaXplID0gbGVmdENvdW50ICsgcmlnaHRDb3VudDsKICAgIGNvbnN0IGZpbmFsUG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShzaXplKTsKICAgIGNvbnN0IG5vcm1hbHMgPSB2ZXJ0ZXhGb3JtYXQubm9ybWFsID8gbmV3IEZsb2F0MzJBcnJheShzaXplKSA6IHZvaWQgMDsKICAgIGNvbnN0IHRhbmdlbnRzID0gdmVydGV4Rm9ybWF0LnRhbmdlbnQgPyBuZXcgRmxvYXQzMkFycmF5KHNpemUpIDogdm9pZCAwOwogICAgY29uc3QgYml0YW5nZW50cyA9IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQgPyBuZXcgRmxvYXQzMkFycmF5KHNpemUpIDogdm9pZCAwOwogICAgY29uc3QgYXR0ciA9IHsKICAgICAgbm9ybWFscywKICAgICAgdGFuZ2VudHMsCiAgICAgIGJpdGFuZ2VudHMKICAgIH07CiAgICBsZXQgZnJvbnQgPSAwOwogICAgbGV0IGJhY2sgPSBzaXplIC0gMTsKICAgIGxldCBVTCwgTEwsIFVSLCBMUjsKICAgIGxldCBub3JtYWwyID0gY2FydGVzaWFuMTI7CiAgICBsZXQgbGVmdCA9IGNhcnRlc2lhbjIyOwogICAgbGV0IHJpZ2h0UG9zLCBsZWZ0UG9zOwogICAgY29uc3QgaGFsZkxlbmd0aCA9IGVuZFBvc2l0aW9uTGVuZ3RoIC8gMjsKICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheShzaXplIC8gMywgaW5kaWNlc0xlbmd0aCk7CiAgICBsZXQgaW5kZXggPSAwOwogICAgaWYgKGFkZEVuZFBvc2l0aW9ucykgewogICAgICBsZWZ0UG9zID0gY2FydGVzaWFuMzI7CiAgICAgIHJpZ2h0UG9zID0gY2FydGVzaWFuNDI7CiAgICAgIGNvbnN0IGZpcnN0RW5kUG9zaXRpb25zID0gZW5kUG9zaXRpb25zWzBdOwogICAgICBub3JtYWwyID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShjb21wdXRlZE5vcm1hbHMsIDAsIG5vcm1hbDIpOwogICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShjb21wdXRlZExlZnRzLCAwLCBsZWZ0KTsKICAgICAgZm9yIChpID0gMDsgaSA8IGhhbGZMZW5ndGg7IGkrKykgewogICAgICAgIGxlZnRQb3MgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgZmlyc3RFbmRQb3NpdGlvbnMsCiAgICAgICAgICAoaGFsZkxlbmd0aCAtIDEgLSBpKSAqIDMsCiAgICAgICAgICBsZWZ0UG9zCiAgICAgICAgKTsKICAgICAgICByaWdodFBvcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICBmaXJzdEVuZFBvc2l0aW9ucywKICAgICAgICAgIChoYWxmTGVuZ3RoICsgaSkgKiAzLAogICAgICAgICAgcmlnaHRQb3MKICAgICAgICApOwogICAgICAgIENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYWRkQXR0cmlidXRlKGZpbmFsUG9zaXRpb25zLCByaWdodFBvcywgZnJvbnQpOwogICAgICAgIENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYWRkQXR0cmlidXRlKAogICAgICAgICAgZmluYWxQb3NpdGlvbnMsCiAgICAgICAgICBsZWZ0UG9zLAogICAgICAgICAgdm9pZCAwLAogICAgICAgICAgYmFjawogICAgICAgICk7CiAgICAgICAgYWRkTm9ybWFscyhhdHRyLCBub3JtYWwyLCBsZWZ0LCBmcm9udCwgYmFjaywgdmVydGV4Rm9ybWF0KTsKICAgICAgICBMTCA9IGZyb250IC8gMzsKICAgICAgICBMUiA9IExMICsgMTsKICAgICAgICBVTCA9IChiYWNrIC0gMikgLyAzOwogICAgICAgIFVSID0gVUwgLSAxOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBVTDsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gTEw7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IFVSOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBVUjsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gTEw7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IExSOwogICAgICAgIGZyb250ICs9IDM7CiAgICAgICAgYmFjayAtPSAzOwogICAgICB9CiAgICB9CiAgICBsZXQgcG9zSW5kZXggPSAwOwogICAgbGV0IGNvbXBJbmRleCA9IDA7CiAgICBsZXQgcmlnaHRFZGdlID0gcG9zaXRpb25zW3Bvc0luZGV4KytdOwogICAgbGV0IGxlZnRFZGdlID0gcG9zaXRpb25zW3Bvc0luZGV4KytdOwogICAgZmluYWxQb3NpdGlvbnMuc2V0KHJpZ2h0RWRnZSwgZnJvbnQpOwogICAgZmluYWxQb3NpdGlvbnMuc2V0KGxlZnRFZGdlLCBiYWNrIC0gbGVmdEVkZ2UubGVuZ3RoICsgMSk7CiAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShjb21wdXRlZExlZnRzLCBjb21wSW5kZXgsIGxlZnQpOwogICAgbGV0IHJpZ2h0Tm9ybWFsOwogICAgbGV0IGxlZnROb3JtYWw7CiAgICBsZW5ndGggPSBsZWZ0RWRnZS5sZW5ndGggLSAzOwogICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAzKSB7CiAgICAgIHJpZ2h0Tm9ybWFsID0gZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbCgKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHJpZ2h0RWRnZSwgaSwgc2NyYXRjaDEzKSwKICAgICAgICBzY3JhdGNoMTMKICAgICAgKTsKICAgICAgbGVmdE5vcm1hbCA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwoCiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShsZWZ0RWRnZSwgbGVuZ3RoIC0gaSwgc2NyYXRjaDIzKSwKICAgICAgICBzY3JhdGNoMjMKICAgICAgKTsKICAgICAgbm9ybWFsMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChyaWdodE5vcm1hbCwgbGVmdE5vcm1hbCwgbm9ybWFsMiksCiAgICAgICAgbm9ybWFsMgogICAgICApOwogICAgICBhZGROb3JtYWxzKGF0dHIsIG5vcm1hbDIsIGxlZnQsIGZyb250LCBiYWNrLCB2ZXJ0ZXhGb3JtYXQpOwogICAgICBMTCA9IGZyb250IC8gMzsKICAgICAgTFIgPSBMTCArIDE7CiAgICAgIFVMID0gKGJhY2sgLSAyKSAvIDM7CiAgICAgIFVSID0gVUwgLSAxOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gVUw7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBMTDsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IFVSOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gVVI7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBMTDsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IExSOwogICAgICBmcm9udCArPSAzOwogICAgICBiYWNrIC09IDM7CiAgICB9CiAgICByaWdodE5vcm1hbCA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwoCiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkocmlnaHRFZGdlLCBsZW5ndGgsIHNjcmF0Y2gxMyksCiAgICAgIHNjcmF0Y2gxMwogICAgKTsKICAgIGxlZnROb3JtYWwgPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKAogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KGxlZnRFZGdlLCBsZW5ndGgsIHNjcmF0Y2gyMyksCiAgICAgIHNjcmF0Y2gyMwogICAgKTsKICAgIG5vcm1hbDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHJpZ2h0Tm9ybWFsLCBsZWZ0Tm9ybWFsLCBub3JtYWwyKSwKICAgICAgbm9ybWFsMgogICAgKTsKICAgIGNvbXBJbmRleCArPSAzOwogICAgZm9yIChpID0gMDsgaSA8IGNvcm5lcnMubGVuZ3RoOyBpKyspIHsKICAgICAgbGV0IGo7CiAgICAgIGNvcm5lciA9IGNvcm5lcnNbaV07CiAgICAgIGNvbnN0IGwgPSBjb3JuZXIubGVmdFBvc2l0aW9uczsKICAgICAgY29uc3QgciA9IGNvcm5lci5yaWdodFBvc2l0aW9uczsKICAgICAgbGV0IHBpdm90OwogICAgICBsZXQgc3RhcnQ7CiAgICAgIGxldCBvdXRzaWRlUG9pbnQgPSBjYXJ0ZXNpYW42MjsKICAgICAgbGV0IHByZXZpb3VzUG9pbnQgPSBjYXJ0ZXNpYW4zMjsKICAgICAgbGV0IG5leHRQb2ludCA9IGNhcnRlc2lhbjQyOwogICAgICBub3JtYWwyID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShjb21wdXRlZE5vcm1hbHMsIGNvbXBJbmRleCwgbm9ybWFsMik7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobCkpIHsKICAgICAgICBhZGROb3JtYWxzKGF0dHIsIG5vcm1hbDIsIGxlZnQsIHZvaWQgMCwgYmFjaywgdmVydGV4Rm9ybWF0KTsKICAgICAgICBiYWNrIC09IDM7CiAgICAgICAgcGl2b3QgPSBMUjsKICAgICAgICBzdGFydCA9IFVSOwogICAgICAgIGZvciAoaiA9IDA7IGogPCBsLmxlbmd0aCAvIDM7IGorKykgewogICAgICAgICAgb3V0c2lkZVBvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShsLCBqICogMywgb3V0c2lkZVBvaW50KTsKICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBwaXZvdDsKICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBzdGFydCAtIGogLSAxOwogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHN0YXJ0IC0gajsKICAgICAgICAgIENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYWRkQXR0cmlidXRlKAogICAgICAgICAgICBmaW5hbFBvc2l0aW9ucywKICAgICAgICAgICAgb3V0c2lkZVBvaW50LAogICAgICAgICAgICB2b2lkIDAsCiAgICAgICAgICAgIGJhY2sKICAgICAgICAgICk7CiAgICAgICAgICBwcmV2aW91c1BvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgICAgZmluYWxQb3NpdGlvbnMsCiAgICAgICAgICAgIChzdGFydCAtIGogLSAxKSAqIDMsCiAgICAgICAgICAgIHByZXZpb3VzUG9pbnQKICAgICAgICAgICk7CiAgICAgICAgICBuZXh0UG9pbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KGZpbmFsUG9zaXRpb25zLCBwaXZvdCAqIDMsIG5leHRQb2ludCk7CiAgICAgICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHByZXZpb3VzUG9pbnQsIG5leHRQb2ludCwgbGVmdCksCiAgICAgICAgICAgIGxlZnQKICAgICAgICAgICk7CiAgICAgICAgICBhZGROb3JtYWxzKGF0dHIsIG5vcm1hbDIsIGxlZnQsIHZvaWQgMCwgYmFjaywgdmVydGV4Rm9ybWF0KTsKICAgICAgICAgIGJhY2sgLT0gMzsKICAgICAgICB9CiAgICAgICAgb3V0c2lkZVBvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgIGZpbmFsUG9zaXRpb25zLAogICAgICAgICAgcGl2b3QgKiAzLAogICAgICAgICAgb3V0c2lkZVBvaW50CiAgICAgICAgKTsKICAgICAgICBwcmV2aW91c1BvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShmaW5hbFBvc2l0aW9ucywgc3RhcnQgKiAzLCBwcmV2aW91c1BvaW50KSwKICAgICAgICAgIG91dHNpZGVQb2ludCwKICAgICAgICAgIHByZXZpb3VzUG9pbnQKICAgICAgICApOwogICAgICAgIG5leHRQb2ludCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoZmluYWxQb3NpdGlvbnMsIChzdGFydCAtIGopICogMywgbmV4dFBvaW50KSwKICAgICAgICAgIG91dHNpZGVQb2ludCwKICAgICAgICAgIG5leHRQb2ludAogICAgICAgICk7CiAgICAgICAgbGVmdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHByZXZpb3VzUG9pbnQsIG5leHRQb2ludCwgbGVmdCksCiAgICAgICAgICBsZWZ0CiAgICAgICAgKTsKICAgICAgICBhZGROb3JtYWxzKGF0dHIsIG5vcm1hbDIsIGxlZnQsIGZyb250LCB2b2lkIDAsIHZlcnRleEZvcm1hdCk7CiAgICAgICAgZnJvbnQgKz0gMzsKICAgICAgfSBlbHNlIHsKICAgICAgICBhZGROb3JtYWxzKGF0dHIsIG5vcm1hbDIsIGxlZnQsIGZyb250LCB2b2lkIDAsIHZlcnRleEZvcm1hdCk7CiAgICAgICAgZnJvbnQgKz0gMzsKICAgICAgICBwaXZvdCA9IFVSOwogICAgICAgIHN0YXJ0ID0gTFI7CiAgICAgICAgZm9yIChqID0gMDsgaiA8IHIubGVuZ3RoIC8gMzsgaisrKSB7CiAgICAgICAgICBvdXRzaWRlUG9pbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHIsIGogKiAzLCBvdXRzaWRlUG9pbnQpOwogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHBpdm90OwogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHN0YXJ0ICsgajsKICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBzdGFydCArIGogKyAxOwogICAgICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUoCiAgICAgICAgICAgIGZpbmFsUG9zaXRpb25zLAogICAgICAgICAgICBvdXRzaWRlUG9pbnQsCiAgICAgICAgICAgIGZyb250CiAgICAgICAgICApOwogICAgICAgICAgcHJldmlvdXNQb2ludCA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICAgIGZpbmFsUG9zaXRpb25zLAogICAgICAgICAgICBwaXZvdCAqIDMsCiAgICAgICAgICAgIHByZXZpb3VzUG9pbnQKICAgICAgICAgICk7CiAgICAgICAgICBuZXh0UG9pbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgICBmaW5hbFBvc2l0aW9ucywKICAgICAgICAgICAgKHN0YXJ0ICsgaikgKiAzLAogICAgICAgICAgICBuZXh0UG9pbnQKICAgICAgICAgICk7CiAgICAgICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHByZXZpb3VzUG9pbnQsIG5leHRQb2ludCwgbGVmdCksCiAgICAgICAgICAgIGxlZnQKICAgICAgICAgICk7CiAgICAgICAgICBhZGROb3JtYWxzKGF0dHIsIG5vcm1hbDIsIGxlZnQsIGZyb250LCB2b2lkIDAsIHZlcnRleEZvcm1hdCk7CiAgICAgICAgICBmcm9udCArPSAzOwogICAgICAgIH0KICAgICAgICBvdXRzaWRlUG9pbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgZmluYWxQb3NpdGlvbnMsCiAgICAgICAgICBwaXZvdCAqIDMsCiAgICAgICAgICBvdXRzaWRlUG9pbnQKICAgICAgICApOwogICAgICAgIHByZXZpb3VzUG9pbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KGZpbmFsUG9zaXRpb25zLCAoc3RhcnQgKyBqKSAqIDMsIHByZXZpb3VzUG9pbnQpLAogICAgICAgICAgb3V0c2lkZVBvaW50LAogICAgICAgICAgcHJldmlvdXNQb2ludAogICAgICAgICk7CiAgICAgICAgbmV4dFBvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShmaW5hbFBvc2l0aW9ucywgc3RhcnQgKiAzLCBuZXh0UG9pbnQpLAogICAgICAgICAgb3V0c2lkZVBvaW50LAogICAgICAgICAgbmV4dFBvaW50CiAgICAgICAgKTsKICAgICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoQ2FydGVzaWFuM19kZWZhdWx0LmFkZChuZXh0UG9pbnQsIHByZXZpb3VzUG9pbnQsIGxlZnQpLCBsZWZ0KSwKICAgICAgICAgIGxlZnQKICAgICAgICApOwogICAgICAgIGFkZE5vcm1hbHMoYXR0ciwgbm9ybWFsMiwgbGVmdCwgdm9pZCAwLCBiYWNrLCB2ZXJ0ZXhGb3JtYXQpOwogICAgICAgIGJhY2sgLT0gMzsKICAgICAgfQogICAgICByaWdodEVkZ2UgPSBwb3NpdGlvbnNbcG9zSW5kZXgrK107CiAgICAgIGxlZnRFZGdlID0gcG9zaXRpb25zW3Bvc0luZGV4KytdOwogICAgICByaWdodEVkZ2Uuc3BsaWNlKDAsIDMpOwogICAgICBsZWZ0RWRnZS5zcGxpY2UobGVmdEVkZ2UubGVuZ3RoIC0gMywgMyk7CiAgICAgIGZpbmFsUG9zaXRpb25zLnNldChyaWdodEVkZ2UsIGZyb250KTsKICAgICAgZmluYWxQb3NpdGlvbnMuc2V0KGxlZnRFZGdlLCBiYWNrIC0gbGVmdEVkZ2UubGVuZ3RoICsgMSk7CiAgICAgIGxlbmd0aCA9IGxlZnRFZGdlLmxlbmd0aCAtIDM7CiAgICAgIGNvbXBJbmRleCArPSAzOwogICAgICBsZWZ0ID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShjb21wdXRlZExlZnRzLCBjb21wSW5kZXgsIGxlZnQpOwogICAgICBmb3IgKGogPSAwOyBqIDwgbGVmdEVkZ2UubGVuZ3RoOyBqICs9IDMpIHsKICAgICAgICByaWdodE5vcm1hbCA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHJpZ2h0RWRnZSwgaiwgc2NyYXRjaDEzKSwKICAgICAgICAgIHNjcmF0Y2gxMwogICAgICAgICk7CiAgICAgICAgbGVmdE5vcm1hbCA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KGxlZnRFZGdlLCBsZW5ndGggLSBqLCBzY3JhdGNoMjMpLAogICAgICAgICAgc2NyYXRjaDIzCiAgICAgICAgKTsKICAgICAgICBub3JtYWwyID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocmlnaHROb3JtYWwsIGxlZnROb3JtYWwsIG5vcm1hbDIpLAogICAgICAgICAgbm9ybWFsMgogICAgICAgICk7CiAgICAgICAgYWRkTm9ybWFscyhhdHRyLCBub3JtYWwyLCBsZWZ0LCBmcm9udCwgYmFjaywgdmVydGV4Rm9ybWF0KTsKICAgICAgICBMUiA9IGZyb250IC8gMzsKICAgICAgICBMTCA9IExSIC0gMTsKICAgICAgICBVUiA9IChiYWNrIC0gMikgLyAzOwogICAgICAgIFVMID0gVVIgKyAxOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBVTDsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gTEw7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IFVSOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBVUjsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gTEw7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IExSOwogICAgICAgIGZyb250ICs9IDM7CiAgICAgICAgYmFjayAtPSAzOwogICAgICB9CiAgICAgIGZyb250IC09IDM7CiAgICAgIGJhY2sgKz0gMzsKICAgIH0KICAgIG5vcm1hbDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICBjb21wdXRlZE5vcm1hbHMsCiAgICAgIGNvbXB1dGVkTm9ybWFscy5sZW5ndGggLSAzLAogICAgICBub3JtYWwyCiAgICApOwogICAgYWRkTm9ybWFscyhhdHRyLCBub3JtYWwyLCBsZWZ0LCBmcm9udCwgYmFjaywgdmVydGV4Rm9ybWF0KTsKICAgIGlmIChhZGRFbmRQb3NpdGlvbnMpIHsKICAgICAgZnJvbnQgKz0gMzsKICAgICAgYmFjayAtPSAzOwogICAgICBsZWZ0UG9zID0gY2FydGVzaWFuMzI7CiAgICAgIHJpZ2h0UG9zID0gY2FydGVzaWFuNDI7CiAgICAgIGNvbnN0IGxhc3RFbmRQb3NpdGlvbnMgPSBlbmRQb3NpdGlvbnNbMV07CiAgICAgIGZvciAoaSA9IDA7IGkgPCBoYWxmTGVuZ3RoOyBpKyspIHsKICAgICAgICBsZWZ0UG9zID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgIGxhc3RFbmRQb3NpdGlvbnMsCiAgICAgICAgICAoZW5kUG9zaXRpb25MZW5ndGggLSBpIC0gMSkgKiAzLAogICAgICAgICAgbGVmdFBvcwogICAgICAgICk7CiAgICAgICAgcmlnaHRQb3MgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KGxhc3RFbmRQb3NpdGlvbnMsIGkgKiAzLCByaWdodFBvcyk7CiAgICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUoCiAgICAgICAgICBmaW5hbFBvc2l0aW9ucywKICAgICAgICAgIGxlZnRQb3MsCiAgICAgICAgICB2b2lkIDAsCiAgICAgICAgICBiYWNrCiAgICAgICAgKTsKICAgICAgICBDb3JyaWRvckdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmFkZEF0dHJpYnV0ZShmaW5hbFBvc2l0aW9ucywgcmlnaHRQb3MsIGZyb250KTsKICAgICAgICBhZGROb3JtYWxzKGF0dHIsIG5vcm1hbDIsIGxlZnQsIGZyb250LCBiYWNrLCB2ZXJ0ZXhGb3JtYXQpOwogICAgICAgIExSID0gZnJvbnQgLyAzOwogICAgICAgIExMID0gTFIgLSAxOwogICAgICAgIFVSID0gKGJhY2sgLSAyKSAvIDM7CiAgICAgICAgVUwgPSBVUiArIDE7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IFVMOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBMTDsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gVVI7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IFVSOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBMTDsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gTFI7CiAgICAgICAgZnJvbnQgKz0gMzsKICAgICAgICBiYWNrIC09IDM7CiAgICAgIH0KICAgIH0KICAgIGF0dHJpYnV0ZXMucG9zaXRpb24gPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgdmFsdWVzOiBmaW5hbFBvc2l0aW9ucwogICAgfSk7CiAgICBpZiAodmVydGV4Rm9ybWF0LnN0KSB7CiAgICAgIGNvbnN0IHN0ID0gbmV3IEZsb2F0MzJBcnJheShzaXplIC8gMyAqIDIpOwogICAgICBsZXQgcmlnaHRTdDsKICAgICAgbGV0IGxlZnRTdDsKICAgICAgbGV0IHN0SW5kZXggPSAwOwogICAgICBpZiAoYWRkRW5kUG9zaXRpb25zKSB7CiAgICAgICAgbGVmdENvdW50IC89IDM7CiAgICAgICAgcmlnaHRDb3VudCAvPSAzOwogICAgICAgIGNvbnN0IHRoZXRhID0gTWF0aC5QSSAvIChlbmRQb3NpdGlvbkxlbmd0aCArIDEpOwogICAgICAgIGxlZnRTdCA9IDEgLyAobGVmdENvdW50IC0gZW5kUG9zaXRpb25MZW5ndGggKyAxKTsKICAgICAgICByaWdodFN0ID0gMSAvIChyaWdodENvdW50IC0gZW5kUG9zaXRpb25MZW5ndGggKyAxKTsKICAgICAgICBsZXQgYTM7CiAgICAgICAgY29uc3QgaGFsZkVuZFBvcyA9IGVuZFBvc2l0aW9uTGVuZ3RoIC8gMjsKICAgICAgICBmb3IgKGkgPSBoYWxmRW5kUG9zICsgMTsgaSA8IGVuZFBvc2l0aW9uTGVuZ3RoICsgMTsgaSsrKSB7CiAgICAgICAgICBhMyA9IE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyArIHRoZXRhICogaTsKICAgICAgICAgIHN0W3N0SW5kZXgrK10gPSByaWdodFN0ICogKDEgKyBNYXRoLmNvcyhhMykpOwogICAgICAgICAgc3Rbc3RJbmRleCsrXSA9IDAuNSAqICgxICsgTWF0aC5zaW4oYTMpKTsKICAgICAgICB9CiAgICAgICAgZm9yIChpID0gMTsgaSA8IHJpZ2h0Q291bnQgLSBlbmRQb3NpdGlvbkxlbmd0aCArIDE7IGkrKykgewogICAgICAgICAgc3Rbc3RJbmRleCsrXSA9IGkgKiByaWdodFN0OwogICAgICAgICAgc3Rbc3RJbmRleCsrXSA9IDA7CiAgICAgICAgfQogICAgICAgIGZvciAoaSA9IGVuZFBvc2l0aW9uTGVuZ3RoOyBpID4gaGFsZkVuZFBvczsgaS0tKSB7CiAgICAgICAgICBhMyA9IE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyAtIGkgKiB0aGV0YTsKICAgICAgICAgIHN0W3N0SW5kZXgrK10gPSAxIC0gcmlnaHRTdCAqICgxICsgTWF0aC5jb3MoYTMpKTsKICAgICAgICAgIHN0W3N0SW5kZXgrK10gPSAwLjUgKiAoMSArIE1hdGguc2luKGEzKSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaSA9IGhhbGZFbmRQb3M7IGkgPiAwOyBpLS0pIHsKICAgICAgICAgIGEzID0gTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPIC0gdGhldGEgKiBpOwogICAgICAgICAgc3Rbc3RJbmRleCsrXSA9IDEgLSBsZWZ0U3QgKiAoMSArIE1hdGguY29zKGEzKSk7CiAgICAgICAgICBzdFtzdEluZGV4KytdID0gMC41ICogKDEgKyBNYXRoLnNpbihhMykpOwogICAgICAgIH0KICAgICAgICBmb3IgKGkgPSBsZWZ0Q291bnQgLSBlbmRQb3NpdGlvbkxlbmd0aDsgaSA+IDA7IGktLSkgewogICAgICAgICAgc3Rbc3RJbmRleCsrXSA9IGkgKiBsZWZ0U3Q7CiAgICAgICAgICBzdFtzdEluZGV4KytdID0gMTsKICAgICAgICB9CiAgICAgICAgZm9yIChpID0gMTsgaSA8IGhhbGZFbmRQb3MgKyAxOyBpKyspIHsKICAgICAgICAgIGEzID0gTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPICsgdGhldGEgKiBpOwogICAgICAgICAgc3Rbc3RJbmRleCsrXSA9IGxlZnRTdCAqICgxICsgTWF0aC5jb3MoYTMpKTsKICAgICAgICAgIHN0W3N0SW5kZXgrK10gPSAwLjUgKiAoMSArIE1hdGguc2luKGEzKSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGxlZnRDb3VudCAvPSAzOwogICAgICAgIHJpZ2h0Q291bnQgLz0gMzsKICAgICAgICBsZWZ0U3QgPSAxIC8gKGxlZnRDb3VudCAtIDEpOwogICAgICAgIHJpZ2h0U3QgPSAxIC8gKHJpZ2h0Q291bnQgLSAxKTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcmlnaHRDb3VudDsgaSsrKSB7CiAgICAgICAgICBzdFtzdEluZGV4KytdID0gaSAqIHJpZ2h0U3Q7CiAgICAgICAgICBzdFtzdEluZGV4KytdID0gMDsKICAgICAgICB9CiAgICAgICAgZm9yIChpID0gbGVmdENvdW50OyBpID4gMDsgaS0tKSB7CiAgICAgICAgICBzdFtzdEluZGV4KytdID0gKGkgLSAxKSAqIGxlZnRTdDsKICAgICAgICAgIHN0W3N0SW5kZXgrK10gPSAxOwogICAgICAgIH0KICAgICAgfQogICAgICBhdHRyaWJ1dGVzLnN0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDIsCiAgICAgICAgdmFsdWVzOiBzdAogICAgICB9KTsKICAgIH0KICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgIGF0dHJpYnV0ZXMubm9ybWFsID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgdmFsdWVzOiBhdHRyLm5vcm1hbHMKICAgICAgfSk7CiAgICB9CiAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQpIHsKICAgICAgYXR0cmlidXRlcy50YW5nZW50ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgdmFsdWVzOiBhdHRyLnRhbmdlbnRzCiAgICAgIH0pOwogICAgfQogICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgYXR0cmlidXRlcy5iaXRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IGF0dHIuYml0YW5nZW50cwogICAgICB9KTsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGluZGljZXMKICAgIH07CiAgfQogIGZ1bmN0aW9uIGV4dHJ1ZGVkQXR0cmlidXRlcyhhdHRyaWJ1dGVzLCB2ZXJ0ZXhGb3JtYXQpIHsKICAgIGlmICghdmVydGV4Rm9ybWF0Lm5vcm1hbCAmJiAhdmVydGV4Rm9ybWF0LnRhbmdlbnQgJiYgIXZlcnRleEZvcm1hdC5iaXRhbmdlbnQgJiYgIXZlcnRleEZvcm1hdC5zdCkgewogICAgICByZXR1cm4gYXR0cmlidXRlczsKICAgIH0KICAgIGNvbnN0IHBvc2l0aW9ucyA9IGF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzOwogICAgbGV0IHRvcE5vcm1hbHM7CiAgICBsZXQgdG9wQml0YW5nZW50czsKICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsIHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgdG9wTm9ybWFscyA9IGF0dHJpYnV0ZXMubm9ybWFsLnZhbHVlczsKICAgICAgdG9wQml0YW5nZW50cyA9IGF0dHJpYnV0ZXMuYml0YW5nZW50LnZhbHVlczsKICAgIH0KICAgIGNvbnN0IHNpemUgPSBhdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5sZW5ndGggLyAxODsKICAgIGNvbnN0IHRocmVlU2l6ZSA9IHNpemUgKiAzOwogICAgY29uc3QgdHdvU2l6ZSA9IHNpemUgKiAyOwogICAgY29uc3Qgc2l4U2l6ZSA9IHRocmVlU2l6ZSAqIDI7CiAgICBsZXQgaTsKICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsIHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQgfHwgdmVydGV4Rm9ybWF0LnRhbmdlbnQpIHsKICAgICAgY29uc3Qgbm9ybWFscyA9IHZlcnRleEZvcm1hdC5ub3JtYWwgPyBuZXcgRmxvYXQzMkFycmF5KHRocmVlU2l6ZSAqIDYpIDogdm9pZCAwOwogICAgICBjb25zdCB0YW5nZW50cyA9IHZlcnRleEZvcm1hdC50YW5nZW50ID8gbmV3IEZsb2F0MzJBcnJheSh0aHJlZVNpemUgKiA2KSA6IHZvaWQgMDsKICAgICAgY29uc3QgYml0YW5nZW50cyA9IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQgPyBuZXcgRmxvYXQzMkFycmF5KHRocmVlU2l6ZSAqIDYpIDogdm9pZCAwOwogICAgICBsZXQgdG9wUG9zaXRpb24gPSBjYXJ0ZXNpYW4xMjsKICAgICAgbGV0IGJvdHRvbVBvc2l0aW9uID0gY2FydGVzaWFuMjI7CiAgICAgIGxldCBwcmV2aW91c1Bvc2l0aW9uID0gY2FydGVzaWFuMzI7CiAgICAgIGxldCBub3JtYWwyID0gY2FydGVzaWFuNDI7CiAgICAgIGxldCB0YW5nZW50ID0gY2FydGVzaWFuNTI7CiAgICAgIGxldCBiaXRhbmdlbnQgPSBjYXJ0ZXNpYW42MjsKICAgICAgbGV0IGF0dHJJbmRleCA9IHNpeFNpemU7CiAgICAgIGZvciAoaSA9IDA7IGkgPCB0aHJlZVNpemU7IGkgKz0gMykgewogICAgICAgIGNvbnN0IGF0dHJJbmRleE9mZnNldCA9IGF0dHJJbmRleCArIHNpeFNpemU7CiAgICAgICAgdG9wUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHBvc2l0aW9ucywgaSwgdG9wUG9zaXRpb24pOwogICAgICAgIGJvdHRvbVBvc2l0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgIGkgKyB0aHJlZVNpemUsCiAgICAgICAgICBib3R0b21Qb3NpdGlvbgogICAgICAgICk7CiAgICAgICAgcHJldmlvdXNQb3NpdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICAoaSArIDMpICUgdGhyZWVTaXplLAogICAgICAgICAgcHJldmlvdXNQb3NpdGlvbgogICAgICAgICk7CiAgICAgICAgYm90dG9tUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgICAgICBib3R0b21Qb3NpdGlvbiwKICAgICAgICAgIHRvcFBvc2l0aW9uLAogICAgICAgICAgYm90dG9tUG9zaXRpb24KICAgICAgICApOwogICAgICAgIHByZXZpb3VzUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgICAgICBwcmV2aW91c1Bvc2l0aW9uLAogICAgICAgICAgdG9wUG9zaXRpb24sCiAgICAgICAgICBwcmV2aW91c1Bvc2l0aW9uCiAgICAgICAgKTsKICAgICAgICBub3JtYWwyID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhib3R0b21Qb3NpdGlvbiwgcHJldmlvdXNQb3NpdGlvbiwgbm9ybWFsMiksCiAgICAgICAgICBub3JtYWwyCiAgICAgICAgKTsKICAgICAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUobm9ybWFscywgbm9ybWFsMiwgYXR0ckluZGV4T2Zmc2V0KTsKICAgICAgICAgIENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYWRkQXR0cmlidXRlKAogICAgICAgICAgICBub3JtYWxzLAogICAgICAgICAgICBub3JtYWwyLAogICAgICAgICAgICBhdHRySW5kZXhPZmZzZXQgKyAzCiAgICAgICAgICApOwogICAgICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUobm9ybWFscywgbm9ybWFsMiwgYXR0ckluZGV4KTsKICAgICAgICAgIENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYWRkQXR0cmlidXRlKG5vcm1hbHMsIG5vcm1hbDIsIGF0dHJJbmRleCArIDMpOwogICAgICAgIH0KICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQgfHwgdmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgICAgYml0YW5nZW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSh0b3BOb3JtYWxzLCBpLCBiaXRhbmdlbnQpOwogICAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUoCiAgICAgICAgICAgICAgYml0YW5nZW50cywKICAgICAgICAgICAgICBiaXRhbmdlbnQsCiAgICAgICAgICAgICAgYXR0ckluZGV4T2Zmc2V0CiAgICAgICAgICAgICk7CiAgICAgICAgICAgIENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYWRkQXR0cmlidXRlKAogICAgICAgICAgICAgIGJpdGFuZ2VudHMsCiAgICAgICAgICAgICAgYml0YW5nZW50LAogICAgICAgICAgICAgIGF0dHJJbmRleE9mZnNldCArIDMKICAgICAgICAgICAgKTsKICAgICAgICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUoCiAgICAgICAgICAgICAgYml0YW5nZW50cywKICAgICAgICAgICAgICBiaXRhbmdlbnQsCiAgICAgICAgICAgICAgYXR0ckluZGV4CiAgICAgICAgICAgICk7CiAgICAgICAgICAgIENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYWRkQXR0cmlidXRlKAogICAgICAgICAgICAgIGJpdGFuZ2VudHMsCiAgICAgICAgICAgICAgYml0YW5nZW50LAogICAgICAgICAgICAgIGF0dHJJbmRleCArIDMKICAgICAgICAgICAgKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICAgICAgICB0YW5nZW50ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoYml0YW5nZW50LCBub3JtYWwyLCB0YW5nZW50KSwKICAgICAgICAgICAgICB0YW5nZW50CiAgICAgICAgICAgICk7CiAgICAgICAgICAgIENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYWRkQXR0cmlidXRlKAogICAgICAgICAgICAgIHRhbmdlbnRzLAogICAgICAgICAgICAgIHRhbmdlbnQsCiAgICAgICAgICAgICAgYXR0ckluZGV4T2Zmc2V0CiAgICAgICAgICAgICk7CiAgICAgICAgICAgIENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYWRkQXR0cmlidXRlKAogICAgICAgICAgICAgIHRhbmdlbnRzLAogICAgICAgICAgICAgIHRhbmdlbnQsCiAgICAgICAgICAgICAgYXR0ckluZGV4T2Zmc2V0ICsgMwogICAgICAgICAgICApOwogICAgICAgICAgICBDb3JyaWRvckdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmFkZEF0dHJpYnV0ZSh0YW5nZW50cywgdGFuZ2VudCwgYXR0ckluZGV4KTsKICAgICAgICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUoCiAgICAgICAgICAgICAgdGFuZ2VudHMsCiAgICAgICAgICAgICAgdGFuZ2VudCwKICAgICAgICAgICAgICBhdHRySW5kZXggKyAzCiAgICAgICAgICAgICk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGF0dHJJbmRleCArPSA2OwogICAgICB9CiAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgICAgbm9ybWFscy5zZXQodG9wTm9ybWFscyk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHRocmVlU2l6ZTsgaSArPSAzKSB7CiAgICAgICAgICBub3JtYWxzW2kgKyB0aHJlZVNpemVdID0gLXRvcE5vcm1hbHNbaV07CiAgICAgICAgICBub3JtYWxzW2kgKyB0aHJlZVNpemUgKyAxXSA9IC10b3BOb3JtYWxzW2kgKyAxXTsKICAgICAgICAgIG5vcm1hbHNbaSArIHRocmVlU2l6ZSArIDJdID0gLXRvcE5vcm1hbHNbaSArIDJdOwogICAgICAgIH0KICAgICAgICBhdHRyaWJ1dGVzLm5vcm1hbC52YWx1ZXMgPSBub3JtYWxzOwogICAgICB9IGVsc2UgewogICAgICAgIGF0dHJpYnV0ZXMubm9ybWFsID0gdm9pZCAwOwogICAgICB9CiAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgYml0YW5nZW50cy5zZXQodG9wQml0YW5nZW50cyk7CiAgICAgICAgYml0YW5nZW50cy5zZXQodG9wQml0YW5nZW50cywgdGhyZWVTaXplKTsKICAgICAgICBhdHRyaWJ1dGVzLmJpdGFuZ2VudC52YWx1ZXMgPSBiaXRhbmdlbnRzOwogICAgICB9IGVsc2UgewogICAgICAgIGF0dHJpYnV0ZXMuYml0YW5nZW50ID0gdm9pZCAwOwogICAgICB9CiAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICAgIGNvbnN0IHRvcFRhbmdlbnRzID0gYXR0cmlidXRlcy50YW5nZW50LnZhbHVlczsKICAgICAgICB0YW5nZW50cy5zZXQodG9wVGFuZ2VudHMpOwogICAgICAgIHRhbmdlbnRzLnNldCh0b3BUYW5nZW50cywgdGhyZWVTaXplKTsKICAgICAgICBhdHRyaWJ1dGVzLnRhbmdlbnQudmFsdWVzID0gdGFuZ2VudHM7CiAgICAgIH0KICAgIH0KICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgY29uc3QgdG9wU3QgPSBhdHRyaWJ1dGVzLnN0LnZhbHVlczsKICAgICAgY29uc3Qgc3QgPSBuZXcgRmxvYXQzMkFycmF5KHR3b1NpemUgKiA2KTsKICAgICAgc3Quc2V0KHRvcFN0KTsKICAgICAgc3Quc2V0KHRvcFN0LCB0d29TaXplKTsKICAgICAgbGV0IGluZGV4ID0gdHdvU2l6ZSAqIDI7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMjsgaisrKSB7CiAgICAgICAgc3RbaW5kZXgrK10gPSB0b3BTdFswXTsKICAgICAgICBzdFtpbmRleCsrXSA9IHRvcFN0WzFdOwogICAgICAgIGZvciAoaSA9IDI7IGkgPCB0d29TaXplOyBpICs9IDIpIHsKICAgICAgICAgIGNvbnN0IHMgPSB0b3BTdFtpXTsKICAgICAgICAgIGNvbnN0IHQgPSB0b3BTdFtpICsgMV07CiAgICAgICAgICBzdFtpbmRleCsrXSA9IHM7CiAgICAgICAgICBzdFtpbmRleCsrXSA9IHQ7CiAgICAgICAgICBzdFtpbmRleCsrXSA9IHM7CiAgICAgICAgICBzdFtpbmRleCsrXSA9IHQ7CiAgICAgICAgfQogICAgICAgIHN0W2luZGV4KytdID0gdG9wU3RbMF07CiAgICAgICAgc3RbaW5kZXgrK10gPSB0b3BTdFsxXTsKICAgICAgfQogICAgICBhdHRyaWJ1dGVzLnN0LnZhbHVlcyA9IHN0OwogICAgfQogICAgcmV0dXJuIGF0dHJpYnV0ZXM7CiAgfQogIGZ1bmN0aW9uIGFkZFdhbGxQb3NpdGlvbnMocG9zaXRpb25zLCBpbmRleCwgd2FsbFBvc2l0aW9ucykgewogICAgd2FsbFBvc2l0aW9uc1tpbmRleCsrXSA9IHBvc2l0aW9uc1swXTsKICAgIHdhbGxQb3NpdGlvbnNbaW5kZXgrK10gPSBwb3NpdGlvbnNbMV07CiAgICB3YWxsUG9zaXRpb25zW2luZGV4KytdID0gcG9zaXRpb25zWzJdOwogICAgZm9yIChsZXQgaSA9IDM7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyBpICs9IDMpIHsKICAgICAgY29uc3QgeCA9IHBvc2l0aW9uc1tpXTsKICAgICAgY29uc3QgeSA9IHBvc2l0aW9uc1tpICsgMV07CiAgICAgIGNvbnN0IHogPSBwb3NpdGlvbnNbaSArIDJdOwogICAgICB3YWxsUG9zaXRpb25zW2luZGV4KytdID0geDsKICAgICAgd2FsbFBvc2l0aW9uc1tpbmRleCsrXSA9IHk7CiAgICAgIHdhbGxQb3NpdGlvbnNbaW5kZXgrK10gPSB6OwogICAgICB3YWxsUG9zaXRpb25zW2luZGV4KytdID0geDsKICAgICAgd2FsbFBvc2l0aW9uc1tpbmRleCsrXSA9IHk7CiAgICAgIHdhbGxQb3NpdGlvbnNbaW5kZXgrK10gPSB6OwogICAgfQogICAgd2FsbFBvc2l0aW9uc1tpbmRleCsrXSA9IHBvc2l0aW9uc1swXTsKICAgIHdhbGxQb3NpdGlvbnNbaW5kZXgrK10gPSBwb3NpdGlvbnNbMV07CiAgICB3YWxsUG9zaXRpb25zW2luZGV4KytdID0gcG9zaXRpb25zWzJdOwogICAgcmV0dXJuIHdhbGxQb3NpdGlvbnM7CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVQb3NpdGlvbnNFeHRydWRlZChwYXJhbXMsIHZlcnRleEZvcm1hdCkgewogICAgY29uc3QgdG9wVmVydGV4Rm9ybWF0ID0gbmV3IFZlcnRleEZvcm1hdF9kZWZhdWx0KHsKICAgICAgcG9zaXRpb246IHZlcnRleEZvcm1hdC5wb3NpdGlvbiwKICAgICAgbm9ybWFsOiB2ZXJ0ZXhGb3JtYXQubm9ybWFsIHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQgfHwgcGFyYW1zLnNoYWRvd1ZvbHVtZSwKICAgICAgdGFuZ2VudDogdmVydGV4Rm9ybWF0LnRhbmdlbnQsCiAgICAgIGJpdGFuZ2VudDogdmVydGV4Rm9ybWF0Lm5vcm1hbCB8fCB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50LAogICAgICBzdDogdmVydGV4Rm9ybWF0LnN0CiAgICB9KTsKICAgIGNvbnN0IGVsbGlwc29pZCA9IHBhcmFtcy5lbGxpcHNvaWQ7CiAgICBjb25zdCBjb21wdXRlZFBvc2l0aW9ucyA9IENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZVBvc2l0aW9ucyhwYXJhbXMpOwogICAgY29uc3QgYXR0ciA9IGNvbWJpbmUyKGNvbXB1dGVkUG9zaXRpb25zLCB0b3BWZXJ0ZXhGb3JtYXQsIGVsbGlwc29pZCk7CiAgICBjb25zdCBoZWlnaHQgPSBwYXJhbXMuaGVpZ2h0OwogICAgY29uc3QgZXh0cnVkZWRIZWlnaHQgPSBwYXJhbXMuZXh0cnVkZWRIZWlnaHQ7CiAgICBsZXQgYXR0cmlidXRlcyA9IGF0dHIuYXR0cmlidXRlczsKICAgIGNvbnN0IGluZGljZXMgPSBhdHRyLmluZGljZXM7CiAgICBsZXQgcG9zaXRpb25zID0gYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXM7CiAgICBsZXQgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgIGNvbnN0IG5ld1Bvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkobGVuZ3RoICogNik7CiAgICBsZXQgZXh0cnVkZWRQb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KGxlbmd0aCk7CiAgICBleHRydWRlZFBvc2l0aW9ucy5zZXQocG9zaXRpb25zKTsKICAgIGxldCB3YWxsUG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShsZW5ndGggKiA0KTsKICAgIHBvc2l0aW9ucyA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LnNjYWxlVG9HZW9kZXRpY0hlaWdodCgKICAgICAgcG9zaXRpb25zLAogICAgICBoZWlnaHQsCiAgICAgIGVsbGlwc29pZAogICAgKTsKICAgIHdhbGxQb3NpdGlvbnMgPSBhZGRXYWxsUG9zaXRpb25zKHBvc2l0aW9ucywgMCwgd2FsbFBvc2l0aW9ucyk7CiAgICBleHRydWRlZFBvc2l0aW9ucyA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LnNjYWxlVG9HZW9kZXRpY0hlaWdodCgKICAgICAgZXh0cnVkZWRQb3NpdGlvbnMsCiAgICAgIGV4dHJ1ZGVkSGVpZ2h0LAogICAgICBlbGxpcHNvaWQKICAgICk7CiAgICB3YWxsUG9zaXRpb25zID0gYWRkV2FsbFBvc2l0aW9ucygKICAgICAgZXh0cnVkZWRQb3NpdGlvbnMsCiAgICAgIGxlbmd0aCAqIDIsCiAgICAgIHdhbGxQb3NpdGlvbnMKICAgICk7CiAgICBuZXdQb3NpdGlvbnMuc2V0KHBvc2l0aW9ucyk7CiAgICBuZXdQb3NpdGlvbnMuc2V0KGV4dHJ1ZGVkUG9zaXRpb25zLCBsZW5ndGgpOwogICAgbmV3UG9zaXRpb25zLnNldCh3YWxsUG9zaXRpb25zLCBsZW5ndGggKiAyKTsKICAgIGF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzID0gbmV3UG9zaXRpb25zOwogICAgYXR0cmlidXRlcyA9IGV4dHJ1ZGVkQXR0cmlidXRlcyhhdHRyaWJ1dGVzLCB2ZXJ0ZXhGb3JtYXQpOwogICAgbGV0IGk7CiAgICBjb25zdCBzaXplID0gbGVuZ3RoIC8gMzsKICAgIGlmIChwYXJhbXMuc2hhZG93Vm9sdW1lKSB7CiAgICAgIGNvbnN0IHRvcE5vcm1hbHMgPSBhdHRyaWJ1dGVzLm5vcm1hbC52YWx1ZXM7CiAgICAgIGxlbmd0aCA9IHRvcE5vcm1hbHMubGVuZ3RoOwogICAgICBsZXQgZXh0cnVkZU5vcm1hbHMgPSBuZXcgRmxvYXQzMkFycmF5KGxlbmd0aCAqIDYpOwogICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICB0b3BOb3JtYWxzW2ldID0gLXRvcE5vcm1hbHNbaV07CiAgICAgIH0KICAgICAgZXh0cnVkZU5vcm1hbHMuc2V0KHRvcE5vcm1hbHMsIGxlbmd0aCk7CiAgICAgIGV4dHJ1ZGVOb3JtYWxzID0gYWRkV2FsbFBvc2l0aW9ucyh0b3BOb3JtYWxzLCBsZW5ndGggKiA0LCBleHRydWRlTm9ybWFscyk7CiAgICAgIGF0dHJpYnV0ZXMuZXh0cnVkZURpcmVjdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgIHZhbHVlczogZXh0cnVkZU5vcm1hbHMKICAgICAgfSk7CiAgICAgIGlmICghdmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICAgIGF0dHJpYnV0ZXMubm9ybWFsID0gdm9pZCAwOwogICAgICB9CiAgICB9CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHBhcmFtcy5vZmZzZXRBdHRyaWJ1dGUpKSB7CiAgICAgIGxldCBhcHBseU9mZnNldCA9IG5ldyBVaW50OEFycmF5KHNpemUgKiA2KTsKICAgICAgaWYgKHBhcmFtcy5vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuVE9QKSB7CiAgICAgICAgYXBwbHlPZmZzZXQgPSBhcHBseU9mZnNldC5maWxsKDEsIDAsIHNpemUpLmZpbGwoMSwgc2l6ZSAqIDIsIHNpemUgKiA0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBhcHBseU9mZnNldFZhbHVlID0gcGFyYW1zLm9mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5OT05FID8gMCA6IDE7CiAgICAgICAgYXBwbHlPZmZzZXQgPSBhcHBseU9mZnNldC5maWxsKGFwcGx5T2Zmc2V0VmFsdWUpOwogICAgICB9CiAgICAgIGF0dHJpYnV0ZXMuYXBwbHlPZmZzZXQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuVU5TSUdORURfQllURSwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAxLAogICAgICAgIHZhbHVlczogYXBwbHlPZmZzZXQKICAgICAgfSk7CiAgICB9CiAgICBjb25zdCBpTGVuZ3RoID0gaW5kaWNlcy5sZW5ndGg7CiAgICBjb25zdCB0d29TaXplID0gc2l6ZSArIHNpemU7CiAgICBjb25zdCBuZXdJbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgIG5ld1Bvc2l0aW9ucy5sZW5ndGggLyAzLAogICAgICBpTGVuZ3RoICogMiArIHR3b1NpemUgKiAzCiAgICApOwogICAgbmV3SW5kaWNlcy5zZXQoaW5kaWNlcyk7CiAgICBsZXQgaW5kZXggPSBpTGVuZ3RoOwogICAgZm9yIChpID0gMDsgaSA8IGlMZW5ndGg7IGkgKz0gMykgewogICAgICBjb25zdCB2MDIgPSBpbmRpY2VzW2ldOwogICAgICBjb25zdCB2MTIgPSBpbmRpY2VzW2kgKyAxXTsKICAgICAgY29uc3QgdjIyID0gaW5kaWNlc1tpICsgMl07CiAgICAgIG5ld0luZGljZXNbaW5kZXgrK10gPSB2MjIgKyBzaXplOwogICAgICBuZXdJbmRpY2VzW2luZGV4KytdID0gdjEyICsgc2l6ZTsKICAgICAgbmV3SW5kaWNlc1tpbmRleCsrXSA9IHYwMiArIHNpemU7CiAgICB9CiAgICBsZXQgVUwsIExMLCBVUiwgTFI7CiAgICBmb3IgKGkgPSAwOyBpIDwgdHdvU2l6ZTsgaSArPSAyKSB7CiAgICAgIFVMID0gaSArIHR3b1NpemU7CiAgICAgIExMID0gVUwgKyB0d29TaXplOwogICAgICBVUiA9IFVMICsgMTsKICAgICAgTFIgPSBMTCArIDE7CiAgICAgIG5ld0luZGljZXNbaW5kZXgrK10gPSBVTDsKICAgICAgbmV3SW5kaWNlc1tpbmRleCsrXSA9IExMOwogICAgICBuZXdJbmRpY2VzW2luZGV4KytdID0gVVI7CiAgICAgIG5ld0luZGljZXNbaW5kZXgrK10gPSBVUjsKICAgICAgbmV3SW5kaWNlc1tpbmRleCsrXSA9IExMOwogICAgICBuZXdJbmRpY2VzW2luZGV4KytdID0gTFI7CiAgICB9CiAgICByZXR1cm4gewogICAgICBhdHRyaWJ1dGVzLAogICAgICBpbmRpY2VzOiBuZXdJbmRpY2VzCiAgICB9OwogIH0KICBmdW5jdGlvbiBjb21wdXRlT2Zmc2V0UG9pbnRzKHBvc2l0aW9uMSwgcG9zaXRpb24yLCBlbGxpcHNvaWQsIGhhbGZXaWR0aCwgbWluMywgbWF4MykgewogICAgY29uc3QgZGlyZWN0aW9uMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgcG9zaXRpb24yLAogICAgICBwb3NpdGlvbjEsCiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4xNwogICAgKTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoZGlyZWN0aW9uMiwgZGlyZWN0aW9uMik7CiAgICBjb25zdCBub3JtYWwyID0gZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbChwb3NpdGlvbjEsIHNjcmF0Y2hDYXJ0ZXNpYW4yNyk7CiAgICBjb25zdCBvZmZzZXREaXJlY3Rpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoCiAgICAgIGRpcmVjdGlvbjIsCiAgICAgIG5vcm1hbDIsCiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4xNwogICAgKTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKG9mZnNldERpcmVjdGlvbiwgaGFsZldpZHRoLCBvZmZzZXREaXJlY3Rpb24pOwogICAgbGV0IG1pbkxhdCA9IG1pbjMubGF0aXR1ZGU7CiAgICBsZXQgbWluTG9uID0gbWluMy5sb25naXR1ZGU7CiAgICBsZXQgbWF4TGF0ID0gbWF4My5sYXRpdHVkZTsKICAgIGxldCBtYXhMb24gPSBtYXgzLmxvbmdpdHVkZTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocG9zaXRpb24xLCBvZmZzZXREaXJlY3Rpb24sIHNjcmF0Y2hDYXJ0ZXNpYW4yNyk7CiAgICBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMoc2NyYXRjaENhcnRlc2lhbjI3LCBzY3JhdGNoQ2FydG9ncmFwaGljNCk7CiAgICBsZXQgbGF0ID0gc2NyYXRjaENhcnRvZ3JhcGhpYzQubGF0aXR1ZGU7CiAgICBsZXQgbG9uID0gc2NyYXRjaENhcnRvZ3JhcGhpYzQubG9uZ2l0dWRlOwogICAgbWluTGF0ID0gTWF0aC5taW4obWluTGF0LCBsYXQpOwogICAgbWluTG9uID0gTWF0aC5taW4obWluTG9uLCBsb24pOwogICAgbWF4TGF0ID0gTWF0aC5tYXgobWF4TGF0LCBsYXQpOwogICAgbWF4TG9uID0gTWF0aC5tYXgobWF4TG9uLCBsb24pOwogICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHBvc2l0aW9uMSwgb2Zmc2V0RGlyZWN0aW9uLCBzY3JhdGNoQ2FydGVzaWFuMjcpOwogICAgZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKHNjcmF0Y2hDYXJ0ZXNpYW4yNywgc2NyYXRjaENhcnRvZ3JhcGhpYzQpOwogICAgbGF0ID0gc2NyYXRjaENhcnRvZ3JhcGhpYzQubGF0aXR1ZGU7CiAgICBsb24gPSBzY3JhdGNoQ2FydG9ncmFwaGljNC5sb25naXR1ZGU7CiAgICBtaW5MYXQgPSBNYXRoLm1pbihtaW5MYXQsIGxhdCk7CiAgICBtaW5Mb24gPSBNYXRoLm1pbihtaW5Mb24sIGxvbik7CiAgICBtYXhMYXQgPSBNYXRoLm1heChtYXhMYXQsIGxhdCk7CiAgICBtYXhMb24gPSBNYXRoLm1heChtYXhMb24sIGxvbik7CiAgICBtaW4zLmxhdGl0dWRlID0gbWluTGF0OwogICAgbWluMy5sb25naXR1ZGUgPSBtaW5Mb247CiAgICBtYXgzLmxhdGl0dWRlID0gbWF4TGF0OwogICAgbWF4My5sb25naXR1ZGUgPSBtYXhMb247CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVSZWN0YW5nbGUyKHBvc2l0aW9ucywgZWxsaXBzb2lkLCB3aWR0aCwgY29ybmVyVHlwZSwgcmVzdWx0KSB7CiAgICBwb3NpdGlvbnMgPSBzY2FsZVRvU3VyZmFjZTIocG9zaXRpb25zLCBlbGxpcHNvaWQpOwogICAgY29uc3QgY2xlYW5Qb3NpdGlvbnMgPSBhcnJheVJlbW92ZUR1cGxpY2F0ZXNfZGVmYXVsdCgKICAgICAgcG9zaXRpb25zLAogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbgogICAgKTsKICAgIGNvbnN0IGxlbmd0aCA9IGNsZWFuUG9zaXRpb25zLmxlbmd0aDsKICAgIGlmIChsZW5ndGggPCAyIHx8IHdpZHRoIDw9IDApIHsKICAgICAgcmV0dXJuIG5ldyBSZWN0YW5nbGVfZGVmYXVsdCgpOwogICAgfQogICAgY29uc3QgaGFsZldpZHRoID0gd2lkdGggKiAwLjU7CiAgICBzY3JhdGNoQ2FydG9ncmFwaGljTWluLmxhdGl0dWRlID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgc2NyYXRjaENhcnRvZ3JhcGhpY01pbi5sb25naXR1ZGUgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICBzY3JhdGNoQ2FydG9ncmFwaGljTWF4LmxhdGl0dWRlID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZOwogICAgc2NyYXRjaENhcnRvZ3JhcGhpY01heC5sb25naXR1ZGUgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICBsZXQgbGF0LCBsb247CiAgICBpZiAoY29ybmVyVHlwZSA9PT0gQ29ybmVyVHlwZV9kZWZhdWx0LlJPVU5ERUQpIHsKICAgICAgY29uc3QgZmlyc3QgPSBjbGVhblBvc2l0aW9uc1swXTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KGZpcnN0LCBjbGVhblBvc2l0aW9uc1sxXSwgc2NyYXRjaENhcnRlc2lhbk9mZnNldCk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoc2NyYXRjaENhcnRlc2lhbk9mZnNldCwgc2NyYXRjaENhcnRlc2lhbk9mZnNldCk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW5PZmZzZXQsCiAgICAgICAgaGFsZldpZHRoLAogICAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW5PZmZzZXQKICAgICAgKTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChmaXJzdCwgc2NyYXRjaENhcnRlc2lhbk9mZnNldCwgc2NyYXRjaENhcnRlc2lhbkVuZHMpOwogICAgICBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMoCiAgICAgICAgc2NyYXRjaENhcnRlc2lhbkVuZHMsCiAgICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzQKICAgICAgKTsKICAgICAgbGF0ID0gc2NyYXRjaENhcnRvZ3JhcGhpYzQubGF0aXR1ZGU7CiAgICAgIGxvbiA9IHNjcmF0Y2hDYXJ0b2dyYXBoaWM0LmxvbmdpdHVkZTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpY01pbi5sYXRpdHVkZSA9IE1hdGgubWluKAogICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWNNaW4ubGF0aXR1ZGUsCiAgICAgICAgbGF0CiAgICAgICk7CiAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWNNaW4ubG9uZ2l0dWRlID0gTWF0aC5taW4oCiAgICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpY01pbi5sb25naXR1ZGUsCiAgICAgICAgbG9uCiAgICAgICk7CiAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWNNYXgubGF0aXR1ZGUgPSBNYXRoLm1heCgKICAgICAgICBzY3JhdGNoQ2FydG9ncmFwaGljTWF4LmxhdGl0dWRlLAogICAgICAgIGxhdAogICAgICApOwogICAgICBzY3JhdGNoQ2FydG9ncmFwaGljTWF4LmxvbmdpdHVkZSA9IE1hdGgubWF4KAogICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWNNYXgubG9uZ2l0dWRlLAogICAgICAgIGxvbgogICAgICApOwogICAgfQogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGggLSAxOyArK2kpIHsKICAgICAgY29tcHV0ZU9mZnNldFBvaW50cygKICAgICAgICBjbGVhblBvc2l0aW9uc1tpXSwKICAgICAgICBjbGVhblBvc2l0aW9uc1tpICsgMV0sCiAgICAgICAgZWxsaXBzb2lkLAogICAgICAgIGhhbGZXaWR0aCwKICAgICAgICBzY3JhdGNoQ2FydG9ncmFwaGljTWluLAogICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWNNYXgKICAgICAgKTsKICAgIH0KICAgIGNvbnN0IGxhc3QgPSBjbGVhblBvc2l0aW9uc1tsZW5ndGggLSAxXTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChsYXN0LCBjbGVhblBvc2l0aW9uc1tsZW5ndGggLSAyXSwgc2NyYXRjaENhcnRlc2lhbk9mZnNldCk7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKHNjcmF0Y2hDYXJ0ZXNpYW5PZmZzZXQsIHNjcmF0Y2hDYXJ0ZXNpYW5PZmZzZXQpOwogICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW5PZmZzZXQsCiAgICAgIGhhbGZXaWR0aCwKICAgICAgc2NyYXRjaENhcnRlc2lhbk9mZnNldAogICAgKTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQobGFzdCwgc2NyYXRjaENhcnRlc2lhbk9mZnNldCwgc2NyYXRjaENhcnRlc2lhbkVuZHMpOwogICAgY29tcHV0ZU9mZnNldFBvaW50cygKICAgICAgbGFzdCwKICAgICAgc2NyYXRjaENhcnRlc2lhbkVuZHMsCiAgICAgIGVsbGlwc29pZCwKICAgICAgaGFsZldpZHRoLAogICAgICBzY3JhdGNoQ2FydG9ncmFwaGljTWluLAogICAgICBzY3JhdGNoQ2FydG9ncmFwaGljTWF4CiAgICApOwogICAgaWYgKGNvcm5lclR5cGUgPT09IENvcm5lclR5cGVfZGVmYXVsdC5ST1VOREVEKSB7CiAgICAgIGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYygKICAgICAgICBzY3JhdGNoQ2FydGVzaWFuRW5kcywKICAgICAgICBzY3JhdGNoQ2FydG9ncmFwaGljNAogICAgICApOwogICAgICBsYXQgPSBzY3JhdGNoQ2FydG9ncmFwaGljNC5sYXRpdHVkZTsKICAgICAgbG9uID0gc2NyYXRjaENhcnRvZ3JhcGhpYzQubG9uZ2l0dWRlOwogICAgICBzY3JhdGNoQ2FydG9ncmFwaGljTWluLmxhdGl0dWRlID0gTWF0aC5taW4oCiAgICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpY01pbi5sYXRpdHVkZSwKICAgICAgICBsYXQKICAgICAgKTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpY01pbi5sb25naXR1ZGUgPSBNYXRoLm1pbigKICAgICAgICBzY3JhdGNoQ2FydG9ncmFwaGljTWluLmxvbmdpdHVkZSwKICAgICAgICBsb24KICAgICAgKTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpY01heC5sYXRpdHVkZSA9IE1hdGgubWF4KAogICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWNNYXgubGF0aXR1ZGUsCiAgICAgICAgbGF0CiAgICAgICk7CiAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWNNYXgubG9uZ2l0dWRlID0gTWF0aC5tYXgoCiAgICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpY01heC5sb25naXR1ZGUsCiAgICAgICAgbG9uCiAgICAgICk7CiAgICB9CiAgICBjb25zdCByZWN0YW5nbGUgPSBkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSA/IHJlc3VsdCA6IG5ldyBSZWN0YW5nbGVfZGVmYXVsdCgpOwogICAgcmVjdGFuZ2xlLm5vcnRoID0gc2NyYXRjaENhcnRvZ3JhcGhpY01heC5sYXRpdHVkZTsKICAgIHJlY3RhbmdsZS5zb3V0aCA9IHNjcmF0Y2hDYXJ0b2dyYXBoaWNNaW4ubGF0aXR1ZGU7CiAgICByZWN0YW5nbGUuZWFzdCA9IHNjcmF0Y2hDYXJ0b2dyYXBoaWNNYXgubG9uZ2l0dWRlOwogICAgcmVjdGFuZ2xlLndlc3QgPSBzY3JhdGNoQ2FydG9ncmFwaGljTWluLmxvbmdpdHVkZTsKICAgIHJldHVybiByZWN0YW5nbGU7CiAgfQogIGZ1bmN0aW9uIENvcnJpZG9yR2VvbWV0cnkob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgY29uc3QgcG9zaXRpb25zID0gb3B0aW9ucy5wb3NpdGlvbnM7CiAgICBjb25zdCB3aWR0aCA9IG9wdGlvbnMud2lkdGg7CiAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoIm9wdGlvbnMucG9zaXRpb25zIiwgcG9zaXRpb25zKTsKICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgib3B0aW9ucy53aWR0aCIsIHdpZHRoKTsKICAgIGNvbnN0IGhlaWdodCA9IG9wdGlvbnMuaGVpZ2h0ID8/IDA7CiAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IG9wdGlvbnMuZXh0cnVkZWRIZWlnaHQgPz8gaGVpZ2h0OwogICAgdGhpcy5fcG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgdGhpcy5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUob3B0aW9ucy5lbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdCk7CiAgICB0aGlzLl92ZXJ0ZXhGb3JtYXQgPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5jbG9uZSgKICAgICAgb3B0aW9ucy52ZXJ0ZXhGb3JtYXQgPz8gVmVydGV4Rm9ybWF0X2RlZmF1bHQuREVGQVVMVAogICAgKTsKICAgIHRoaXMuX3dpZHRoID0gd2lkdGg7CiAgICB0aGlzLl9oZWlnaHQgPSBNYXRoLm1heChoZWlnaHQsIGV4dHJ1ZGVkSGVpZ2h0KTsKICAgIHRoaXMuX2V4dHJ1ZGVkSGVpZ2h0ID0gTWF0aC5taW4oaGVpZ2h0LCBleHRydWRlZEhlaWdodCk7CiAgICB0aGlzLl9jb3JuZXJUeXBlID0gb3B0aW9ucy5jb3JuZXJUeXBlID8/IENvcm5lclR5cGVfZGVmYXVsdC5ST1VOREVEOwogICAgdGhpcy5fZ3JhbnVsYXJpdHkgPSBvcHRpb25zLmdyYW51bGFyaXR5ID8/IE1hdGhfZGVmYXVsdC5SQURJQU5TX1BFUl9ERUdSRUU7CiAgICB0aGlzLl9zaGFkb3dWb2x1bWUgPSBvcHRpb25zLnNoYWRvd1ZvbHVtZSA/PyBmYWxzZTsKICAgIHRoaXMuX3dvcmtlck5hbWUgPSAiY3JlYXRlQ29ycmlkb3JHZW9tZXRyeSI7CiAgICB0aGlzLl9vZmZzZXRBdHRyaWJ1dGUgPSBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZTsKICAgIHRoaXMuX3JlY3RhbmdsZSA9IHZvaWQgMDsKICAgIHRoaXMucGFja2VkTGVuZ3RoID0gMSArIHBvc2l0aW9ucy5sZW5ndGggKiBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoICsgRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoICsgVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFja2VkTGVuZ3RoICsgNzsKICB9CiAgdmFyIGNhcnRlc2lhbjEyLCBjYXJ0ZXNpYW4yMiwgY2FydGVzaWFuMzIsIGNhcnRlc2lhbjQyLCBjYXJ0ZXNpYW41MiwgY2FydGVzaWFuNjIsIHNjcmF0Y2gxMywgc2NyYXRjaDIzLCBzY3JhdGNoQ2FydGVzaWFuMTcsIHNjcmF0Y2hDYXJ0ZXNpYW4yNywgc2NyYXRjaENhcnRvZ3JhcGhpYzQsIHNjcmF0Y2hDYXJ0ZXNpYW5PZmZzZXQsIHNjcmF0Y2hDYXJ0ZXNpYW5FbmRzLCBzY3JhdGNoQ2FydG9ncmFwaGljTWluLCBzY3JhdGNoQ2FydG9ncmFwaGljTWF4LCBzY3JhdGNoRWxsaXBzb2lkNCwgc2NyYXRjaFZlcnRleEZvcm1hdDQsIHNjcmF0Y2hPcHRpb25zOSwgQ29ycmlkb3JHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X0NvcnJpZG9yR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NvcnJpZG9yR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X2FycmF5UmVtb3ZlRHVwbGljYXRlcygpOwogICAgICBpbml0X0JvdW5kaW5nU3BoZXJlKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfQ29tcG9uZW50RGF0YXR5cGUoKTsKICAgICAgaW5pdF9Db3JuZXJUeXBlKCk7CiAgICAgIGluaXRfQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnkoKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfR2VvbWV0cnkoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlcygpOwogICAgICBpbml0X0dlb21ldHJ5T2Zmc2V0QXR0cmlidXRlKCk7CiAgICAgIGluaXRfSW5kZXhEYXRhdHlwZSgpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9Qb2x5Z29uUGlwZWxpbmUoKTsKICAgICAgaW5pdF9QcmltaXRpdmVUeXBlKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfVmVydGV4Rm9ybWF0KCk7CiAgICAgIGNhcnRlc2lhbjEyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBjYXJ0ZXNpYW4yMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgY2FydGVzaWFuMzIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjQyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBjYXJ0ZXNpYW41MiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgY2FydGVzaWFuNjIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2gxMyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaDIzID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydGVzaWFuMTcgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4yNyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzQgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbk9mZnNldCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbkVuZHMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWNNaW4gPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpY01heCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBDb3JyaWRvckdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSB2YWx1ZS5fcG9zaXRpb25zOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IGxlbmd0aDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpLCBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGgpIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHBvc2l0aW9uc1tpXSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIH0KICAgICAgICBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrKHZhbHVlLl9lbGxpcHNvaWQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrKHZhbHVlLl92ZXJ0ZXhGb3JtYXQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX3dpZHRoOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5faGVpZ2h0OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9jb3JuZXJUeXBlOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fZ3JhbnVsYXJpdHk7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9zaGFkb3dWb2x1bWUgPyAxIDogMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLl9vZmZzZXRBdHRyaWJ1dGUgPz8gLTE7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBzY3JhdGNoRWxsaXBzb2lkNCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKEVsbGlwc29pZF9kZWZhdWx0LlVOSVRfU1BIRVJFKTsKICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDQgPSBuZXcgVmVydGV4Rm9ybWF0X2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE9wdGlvbnM5ID0gewogICAgICAgIHBvc2l0aW9uczogdm9pZCAwLAogICAgICAgIGVsbGlwc29pZDogc2NyYXRjaEVsbGlwc29pZDQsCiAgICAgICAgdmVydGV4Rm9ybWF0OiBzY3JhdGNoVmVydGV4Rm9ybWF0NCwKICAgICAgICB3aWR0aDogdm9pZCAwLAogICAgICAgIGhlaWdodDogdm9pZCAwLAogICAgICAgIGV4dHJ1ZGVkSGVpZ2h0OiB2b2lkIDAsCiAgICAgICAgY29ybmVyVHlwZTogdm9pZCAwLAogICAgICAgIGdyYW51bGFyaXR5OiB2b2lkIDAsCiAgICAgICAgc2hhZG93Vm9sdW1lOiB2b2lkIDAsCiAgICAgICAgb2Zmc2V0QXR0cmlidXRlOiB2b2lkIDAKICAgICAgfTsKICAgICAgQ29ycmlkb3JHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSwgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoKSB7CiAgICAgICAgICBwb3NpdGlvbnNbaV0gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoRWxsaXBzb2lkNCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgYXJyYXksCiAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDQKICAgICAgICApOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IHdpZHRoID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBoZWlnaHQgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IGV4dHJ1ZGVkSGVpZ2h0ID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBjb3JuZXJUeXBlID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3Qgc2hhZG93Vm9sdW1lID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9PT0gMTsKICAgICAgICBjb25zdCBvZmZzZXRBdHRyaWJ1dGUgPSBhcnJheVtzdGFydGluZ0luZGV4XTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczkucG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnM5LndpZHRoID0gd2lkdGg7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczkuaGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgICAgc2NyYXRjaE9wdGlvbnM5LmV4dHJ1ZGVkSGVpZ2h0ID0gZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczkuY29ybmVyVHlwZSA9IGNvcm5lclR5cGU7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczkuZ3JhbnVsYXJpdHkgPSBncmFudWxhcml0eTsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zOS5zaGFkb3dWb2x1bWUgPSBzaGFkb3dWb2x1bWU7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczkub2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlID09PSAtMSA/IHZvaWQgMCA6IG9mZnNldEF0dHJpYnV0ZTsKICAgICAgICAgIHJldHVybiBuZXcgQ29ycmlkb3JHZW9tZXRyeShzY3JhdGNoT3B0aW9uczkpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuX3Bvc2l0aW9ucyA9IHBvc2l0aW9uczsKICAgICAgICByZXN1bHQuX2VsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKGVsbGlwc29pZCwgcmVzdWx0Ll9lbGxpcHNvaWQpOwogICAgICAgIHJlc3VsdC5fdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQuY2xvbmUodmVydGV4Rm9ybWF0LCByZXN1bHQuX3ZlcnRleEZvcm1hdCk7CiAgICAgICAgcmVzdWx0Ll93aWR0aCA9IHdpZHRoOwogICAgICAgIHJlc3VsdC5faGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgIHJlc3VsdC5fZXh0cnVkZWRIZWlnaHQgPSBleHRydWRlZEhlaWdodDsKICAgICAgICByZXN1bHQuX2Nvcm5lclR5cGUgPSBjb3JuZXJUeXBlOwogICAgICAgIHJlc3VsdC5fZ3JhbnVsYXJpdHkgPSBncmFudWxhcml0eTsKICAgICAgICByZXN1bHQuX3NoYWRvd1ZvbHVtZSA9IHNoYWRvd1ZvbHVtZTsKICAgICAgICByZXN1bHQuX29mZnNldEF0dHJpYnV0ZSA9IG9mZnNldEF0dHJpYnV0ZSA9PT0gLTEgPyB2b2lkIDAgOiBvZmZzZXRBdHRyaWJ1dGU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ29ycmlkb3JHZW9tZXRyeS5jb21wdXRlUmVjdGFuZ2xlID0gZnVuY3Rpb24ob3B0aW9ucywgcmVzdWx0KSB7CiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IG9wdGlvbnMucG9zaXRpb25zOwogICAgICAgIGNvbnN0IHdpZHRoID0gb3B0aW9ucy53aWR0aDsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoIm9wdGlvbnMucG9zaXRpb25zIiwgcG9zaXRpb25zKTsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoIm9wdGlvbnMud2lkdGgiLCB3aWR0aCk7CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gb3B0aW9ucy5lbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgICAgICBjb25zdCBjb3JuZXJUeXBlID0gb3B0aW9ucy5jb3JuZXJUeXBlID8/IENvcm5lclR5cGVfZGVmYXVsdC5ST1VOREVEOwogICAgICAgIHJldHVybiBjb21wdXRlUmVjdGFuZ2xlMihwb3NpdGlvbnMsIGVsbGlwc29pZCwgd2lkdGgsIGNvcm5lclR5cGUsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIENvcnJpZG9yR2VvbWV0cnkuY3JlYXRlR2VvbWV0cnkgPSBmdW5jdGlvbihjb3JyaWRvckdlb21ldHJ5KSB7CiAgICAgICAgbGV0IHBvc2l0aW9ucyA9IGNvcnJpZG9yR2VvbWV0cnkuX3Bvc2l0aW9uczsKICAgICAgICBjb25zdCB3aWR0aCA9IGNvcnJpZG9yR2VvbWV0cnkuX3dpZHRoOwogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IGNvcnJpZG9yR2VvbWV0cnkuX2VsbGlwc29pZDsKICAgICAgICBwb3NpdGlvbnMgPSBzY2FsZVRvU3VyZmFjZTIocG9zaXRpb25zLCBlbGxpcHNvaWQpOwogICAgICAgIGNvbnN0IGNsZWFuUG9zaXRpb25zID0gYXJyYXlSZW1vdmVEdXBsaWNhdGVzX2RlZmF1bHQoCiAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbgogICAgICAgICk7CiAgICAgICAgaWYgKGNsZWFuUG9zaXRpb25zLmxlbmd0aCA8IDIgfHwgd2lkdGggPD0gMCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBjb25zdCBoZWlnaHQgPSBjb3JyaWRvckdlb21ldHJ5Ll9oZWlnaHQ7CiAgICAgICAgY29uc3QgZXh0cnVkZWRIZWlnaHQgPSBjb3JyaWRvckdlb21ldHJ5Ll9leHRydWRlZEhlaWdodDsKICAgICAgICBjb25zdCBleHRydWRlID0gIU1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgaGVpZ2h0LAogICAgICAgICAgZXh0cnVkZWRIZWlnaHQsCiAgICAgICAgICAwLAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04yCiAgICAgICAgKTsKICAgICAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBjb3JyaWRvckdlb21ldHJ5Ll92ZXJ0ZXhGb3JtYXQ7CiAgICAgICAgY29uc3QgcGFyYW1zID0gewogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgcG9zaXRpb25zOiBjbGVhblBvc2l0aW9ucywKICAgICAgICAgIHdpZHRoLAogICAgICAgICAgY29ybmVyVHlwZTogY29ycmlkb3JHZW9tZXRyeS5fY29ybmVyVHlwZSwKICAgICAgICAgIGdyYW51bGFyaXR5OiBjb3JyaWRvckdlb21ldHJ5Ll9ncmFudWxhcml0eSwKICAgICAgICAgIHNhdmVBdHRyaWJ1dGVzOiB0cnVlCiAgICAgICAgfTsKICAgICAgICBsZXQgYXR0cjsKICAgICAgICBpZiAoZXh0cnVkZSkgewogICAgICAgICAgcGFyYW1zLmhlaWdodCA9IGhlaWdodDsKICAgICAgICAgIHBhcmFtcy5leHRydWRlZEhlaWdodCA9IGV4dHJ1ZGVkSGVpZ2h0OwogICAgICAgICAgcGFyYW1zLnNoYWRvd1ZvbHVtZSA9IGNvcnJpZG9yR2VvbWV0cnkuX3NoYWRvd1ZvbHVtZTsKICAgICAgICAgIHBhcmFtcy5vZmZzZXRBdHRyaWJ1dGUgPSBjb3JyaWRvckdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGU7CiAgICAgICAgICBhdHRyID0gY29tcHV0ZVBvc2l0aW9uc0V4dHJ1ZGVkKHBhcmFtcywgdmVydGV4Rm9ybWF0KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgY29tcHV0ZWRQb3NpdGlvbnMgPSBDb3JyaWRvckdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVQb3NpdGlvbnMocGFyYW1zKTsKICAgICAgICAgIGF0dHIgPSBjb21iaW5lMihjb21wdXRlZFBvc2l0aW9ucywgdmVydGV4Rm9ybWF0LCBlbGxpcHNvaWQpOwogICAgICAgICAgYXR0ci5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcyA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LnNjYWxlVG9HZW9kZXRpY0hlaWdodCgKICAgICAgICAgICAgYXR0ci5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcywKICAgICAgICAgICAgaGVpZ2h0LAogICAgICAgICAgICBlbGxpcHNvaWQKICAgICAgICAgICk7CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGNvcnJpZG9yR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZSkpIHsKICAgICAgICAgICAgY29uc3QgYXBwbHlPZmZzZXRWYWx1ZSA9IGNvcnJpZG9yR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5OT05FID8gMCA6IDE7CiAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IGF0dHIuYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMubGVuZ3RoOwogICAgICAgICAgICBjb25zdCBhcHBseU9mZnNldCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCAvIDMpLmZpbGwoYXBwbHlPZmZzZXRWYWx1ZSk7CiAgICAgICAgICAgIGF0dHIuYXR0cmlidXRlcy5hcHBseU9mZnNldCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9CWVRFLAogICAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDEsCiAgICAgICAgICAgICAgdmFsdWVzOiBhcHBseU9mZnNldAogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IGF0dHIuYXR0cmlidXRlczsKICAgICAgICBjb25zdCBib3VuZGluZ1NwaGVyZSA9IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbVZlcnRpY2VzKAogICAgICAgICAgYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMsCiAgICAgICAgICB2b2lkIDAsCiAgICAgICAgICAzCiAgICAgICAgKTsKICAgICAgICBpZiAoIXZlcnRleEZvcm1hdC5wb3NpdGlvbikgewogICAgICAgICAgYXR0ci5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcyA9IHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgICAgIGF0dHJpYnV0ZXMsCiAgICAgICAgICBpbmRpY2VzOiBhdHRyLmluZGljZXMsCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBQcmltaXRpdmVUeXBlX2RlZmF1bHQuVFJJQU5HTEVTLAogICAgICAgICAgYm91bmRpbmdTcGhlcmUsCiAgICAgICAgICBvZmZzZXRBdHRyaWJ1dGU6IGNvcnJpZG9yR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZQogICAgICAgIH0pOwogICAgICB9OwogICAgICBDb3JyaWRvckdlb21ldHJ5LmNyZWF0ZVNoYWRvd1ZvbHVtZSA9IGZ1bmN0aW9uKGNvcnJpZG9yR2VvbWV0cnksIG1pbkhlaWdodEZ1bmMsIG1heEhlaWdodEZ1bmMpIHsKICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IGNvcnJpZG9yR2VvbWV0cnkuX2dyYW51bGFyaXR5OwogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IGNvcnJpZG9yR2VvbWV0cnkuX2VsbGlwc29pZDsKICAgICAgICBjb25zdCBtaW5IZWlnaHQgPSBtaW5IZWlnaHRGdW5jKGdyYW51bGFyaXR5LCBlbGxpcHNvaWQpOwogICAgICAgIGNvbnN0IG1heEhlaWdodCA9IG1heEhlaWdodEZ1bmMoZ3JhbnVsYXJpdHksIGVsbGlwc29pZCk7CiAgICAgICAgcmV0dXJuIG5ldyBDb3JyaWRvckdlb21ldHJ5KHsKICAgICAgICAgIHBvc2l0aW9uczogY29ycmlkb3JHZW9tZXRyeS5fcG9zaXRpb25zLAogICAgICAgICAgd2lkdGg6IGNvcnJpZG9yR2VvbWV0cnkuX3dpZHRoLAogICAgICAgICAgY29ybmVyVHlwZTogY29ycmlkb3JHZW9tZXRyeS5fY29ybmVyVHlwZSwKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIGdyYW51bGFyaXR5LAogICAgICAgICAgZXh0cnVkZWRIZWlnaHQ6IG1pbkhlaWdodCwKICAgICAgICAgIGhlaWdodDogbWF4SGVpZ2h0LAogICAgICAgICAgdmVydGV4Rm9ybWF0OiBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5QT1NJVElPTl9PTkxZLAogICAgICAgICAgc2hhZG93Vm9sdW1lOiB0cnVlCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKENvcnJpZG9yR2VvbWV0cnkucHJvdG90eXBlLCB7CiAgICAgICAgLyoqCiAgICAgICAgICogQHByaXZhdGUKICAgICAgICAgKi8KICAgICAgICByZWN0YW5nbGU6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHRoaXMuX3JlY3RhbmdsZSkpIHsKICAgICAgICAgICAgICB0aGlzLl9yZWN0YW5nbGUgPSBjb21wdXRlUmVjdGFuZ2xlMigKICAgICAgICAgICAgICAgIHRoaXMuX3Bvc2l0aW9ucywKICAgICAgICAgICAgICAgIHRoaXMuX2VsbGlwc29pZCwKICAgICAgICAgICAgICAgIHRoaXMuX3dpZHRoLAogICAgICAgICAgICAgICAgdGhpcy5fY29ybmVyVHlwZQogICAgICAgICAgICAgICk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3JlY3RhbmdsZTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEZvciByZW1hcHBpbmcgdGV4dHVyZSBjb29yZGluYXRlcyB3aGVuIHJlbmRlcmluZyBDb3JyaWRvckdlb21ldHJpZXMgYXMgR3JvdW5kUHJpbWl0aXZlcy4KICAgICAgICAgKgogICAgICAgICAqIENvcnJpZG9ycyBkb24ndCBzdXBwb3J0IHN0Um90YXRpb24sCiAgICAgICAgICogc28ganVzdCByZXR1cm4gdGhlIGNvcm5lcnMgb2YgdGhlIG9yaWdpbmFsIHN5c3RlbS4KICAgICAgICAgKiBAcHJpdmF0ZQogICAgICAgICAqLwogICAgICAgIHRleHR1cmVDb29yZGluYXRlUm90YXRpb25Qb2ludHM6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBbMCwgMCwgMCwgMSwgMSwgMF07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgQ29ycmlkb3JHZW9tZXRyeV9kZWZhdWx0ID0gQ29ycmlkb3JHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUNvcnJpZG9yR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlQ29ycmlkb3JHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlQ29ycmlkb3JHZW9tZXRyeV9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVDb3JyaWRvckdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVDb3JyaWRvckdlb21ldHJ5KGNvcnJpZG9yR2VvbWV0cnksIG9mZnNldCkgewogICAgaWYgKGRlZmluZWRfZGVmYXVsdChvZmZzZXQpKSB7CiAgICAgIGNvcnJpZG9yR2VvbWV0cnkgPSBDb3JyaWRvckdlb21ldHJ5X2RlZmF1bHQudW5wYWNrKGNvcnJpZG9yR2VvbWV0cnksIG9mZnNldCk7CiAgICB9CiAgICBjb3JyaWRvckdlb21ldHJ5Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShjb3JyaWRvckdlb21ldHJ5Ll9lbGxpcHNvaWQpOwogICAgcmV0dXJuIENvcnJpZG9yR2VvbWV0cnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeShjb3JyaWRvckdlb21ldHJ5KTsKICB9CiAgdmFyIGNyZWF0ZUNvcnJpZG9yR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVDb3JyaWRvckdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVDb3JyaWRvckdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9Db3JyaWRvckdlb21ldHJ5KCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBjcmVhdGVDb3JyaWRvckdlb21ldHJ5X2RlZmF1bHQgPSBjcmVhdGVDb3JyaWRvckdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnkuanMKICBmdW5jdGlvbiBzY2FsZVRvU3VyZmFjZTMocG9zaXRpb25zLCBlbGxpcHNvaWQpIHsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9zaXRpb25zLmxlbmd0aDsgaSsrKSB7CiAgICAgIHBvc2l0aW9uc1tpXSA9IGVsbGlwc29pZC5zY2FsZVRvR2VvZGV0aWNTdXJmYWNlKHBvc2l0aW9uc1tpXSwgcG9zaXRpb25zW2ldKTsKICAgIH0KICAgIHJldHVybiBwb3NpdGlvbnM7CiAgfQogIGZ1bmN0aW9uIGNvbWJpbmUzKGNvbXB1dGVkUG9zaXRpb25zLCBjb3JuZXJUeXBlKSB7CiAgICBjb25zdCB3YWxsSW5kaWNlcyA9IFtdOwogICAgY29uc3QgcG9zaXRpb25zID0gY29tcHV0ZWRQb3NpdGlvbnMucG9zaXRpb25zOwogICAgY29uc3QgY29ybmVycyA9IGNvbXB1dGVkUG9zaXRpb25zLmNvcm5lcnM7CiAgICBjb25zdCBlbmRQb3NpdGlvbnMgPSBjb21wdXRlZFBvc2l0aW9ucy5lbmRQb3NpdGlvbnM7CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlc19kZWZhdWx0KCk7CiAgICBsZXQgY29ybmVyOwogICAgbGV0IGxlZnRDb3VudCA9IDA7CiAgICBsZXQgcmlnaHRDb3VudCA9IDA7CiAgICBsZXQgaTsKICAgIGxldCBpbmRpY2VzTGVuZ3RoID0gMDsKICAgIGxldCBsZW5ndGg7CiAgICBmb3IgKGkgPSAwOyBpIDwgcG9zaXRpb25zLmxlbmd0aDsgaSArPSAyKSB7CiAgICAgIGxlbmd0aCA9IHBvc2l0aW9uc1tpXS5sZW5ndGggLSAzOwogICAgICBsZWZ0Q291bnQgKz0gbGVuZ3RoOwogICAgICBpbmRpY2VzTGVuZ3RoICs9IGxlbmd0aCAvIDMgKiA0OwogICAgICByaWdodENvdW50ICs9IHBvc2l0aW9uc1tpICsgMV0ubGVuZ3RoIC0gMzsKICAgIH0KICAgIGxlZnRDb3VudCArPSAzOwogICAgcmlnaHRDb3VudCArPSAzOwogICAgZm9yIChpID0gMDsgaSA8IGNvcm5lcnMubGVuZ3RoOyBpKyspIHsKICAgICAgY29ybmVyID0gY29ybmVyc1tpXTsKICAgICAgY29uc3QgbGVmdFNpZGUgPSBjb3JuZXJzW2ldLmxlZnRQb3NpdGlvbnM7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobGVmdFNpZGUpKSB7CiAgICAgICAgbGVuZ3RoID0gbGVmdFNpZGUubGVuZ3RoOwogICAgICAgIGxlZnRDb3VudCArPSBsZW5ndGg7CiAgICAgICAgaW5kaWNlc0xlbmd0aCArPSBsZW5ndGggLyAzICogMjsKICAgICAgfSBlbHNlIHsKICAgICAgICBsZW5ndGggPSBjb3JuZXJzW2ldLnJpZ2h0UG9zaXRpb25zLmxlbmd0aDsKICAgICAgICByaWdodENvdW50ICs9IGxlbmd0aDsKICAgICAgICBpbmRpY2VzTGVuZ3RoICs9IGxlbmd0aCAvIDMgKiAyOwogICAgICB9CiAgICB9CiAgICBjb25zdCBhZGRFbmRQb3NpdGlvbnMgPSBkZWZpbmVkX2RlZmF1bHQoZW5kUG9zaXRpb25zKTsKICAgIGxldCBlbmRQb3NpdGlvbkxlbmd0aDsKICAgIGlmIChhZGRFbmRQb3NpdGlvbnMpIHsKICAgICAgZW5kUG9zaXRpb25MZW5ndGggPSBlbmRQb3NpdGlvbnNbMF0ubGVuZ3RoIC0gMzsKICAgICAgbGVmdENvdW50ICs9IGVuZFBvc2l0aW9uTGVuZ3RoOwogICAgICByaWdodENvdW50ICs9IGVuZFBvc2l0aW9uTGVuZ3RoOwogICAgICBlbmRQb3NpdGlvbkxlbmd0aCAvPSAzOwogICAgICBpbmRpY2VzTGVuZ3RoICs9IGVuZFBvc2l0aW9uTGVuZ3RoICogNDsKICAgIH0KICAgIGNvbnN0IHNpemUgPSBsZWZ0Q291bnQgKyByaWdodENvdW50OwogICAgY29uc3QgZmluYWxQb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KHNpemUpOwogICAgbGV0IGZyb250ID0gMDsKICAgIGxldCBiYWNrID0gc2l6ZSAtIDE7CiAgICBsZXQgVUwsIExMLCBVUiwgTFI7CiAgICBsZXQgcmlnaHRQb3MsIGxlZnRQb3M7CiAgICBjb25zdCBoYWxmTGVuZ3RoID0gZW5kUG9zaXRpb25MZW5ndGggLyAyOwogICAgY29uc3QgaW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KHNpemUgLyAzLCBpbmRpY2VzTGVuZ3RoICsgNCk7CiAgICBsZXQgaW5kZXggPSAwOwogICAgaW5kaWNlc1tpbmRleCsrXSA9IGZyb250IC8gMzsKICAgIGluZGljZXNbaW5kZXgrK10gPSAoYmFjayAtIDIpIC8gMzsKICAgIGlmIChhZGRFbmRQb3NpdGlvbnMpIHsKICAgICAgd2FsbEluZGljZXMucHVzaChmcm9udCAvIDMpOwogICAgICBsZWZ0UG9zID0gY2FydGVzaWFuMTM7CiAgICAgIHJpZ2h0UG9zID0gY2FydGVzaWFuMjM7CiAgICAgIGNvbnN0IGZpcnN0RW5kUG9zaXRpb25zID0gZW5kUG9zaXRpb25zWzBdOwogICAgICBmb3IgKGkgPSAwOyBpIDwgaGFsZkxlbmd0aDsgaSsrKSB7CiAgICAgICAgbGVmdFBvcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICBmaXJzdEVuZFBvc2l0aW9ucywKICAgICAgICAgIChoYWxmTGVuZ3RoIC0gMSAtIGkpICogMywKICAgICAgICAgIGxlZnRQb3MKICAgICAgICApOwogICAgICAgIHJpZ2h0UG9zID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgIGZpcnN0RW5kUG9zaXRpb25zLAogICAgICAgICAgKGhhbGZMZW5ndGggKyBpKSAqIDMsCiAgICAgICAgICByaWdodFBvcwogICAgICAgICk7CiAgICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUoZmluYWxQb3NpdGlvbnMsIHJpZ2h0UG9zLCBmcm9udCk7CiAgICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUoCiAgICAgICAgICBmaW5hbFBvc2l0aW9ucywKICAgICAgICAgIGxlZnRQb3MsCiAgICAgICAgICB2b2lkIDAsCiAgICAgICAgICBiYWNrCiAgICAgICAgKTsKICAgICAgICBMTCA9IGZyb250IC8gMzsKICAgICAgICBMUiA9IExMICsgMTsKICAgICAgICBVTCA9IChiYWNrIC0gMikgLyAzOwogICAgICAgIFVSID0gVUwgLSAxOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBVTDsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gVVI7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IExMOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBMUjsKICAgICAgICBmcm9udCArPSAzOwogICAgICAgIGJhY2sgLT0gMzsKICAgICAgfQogICAgfQogICAgbGV0IHBvc0luZGV4ID0gMDsKICAgIGxldCByaWdodEVkZ2UgPSBwb3NpdGlvbnNbcG9zSW5kZXgrK107CiAgICBsZXQgbGVmdEVkZ2UgPSBwb3NpdGlvbnNbcG9zSW5kZXgrK107CiAgICBmaW5hbFBvc2l0aW9ucy5zZXQocmlnaHRFZGdlLCBmcm9udCk7CiAgICBmaW5hbFBvc2l0aW9ucy5zZXQobGVmdEVkZ2UsIGJhY2sgLSBsZWZ0RWRnZS5sZW5ndGggKyAxKTsKICAgIGxlbmd0aCA9IGxlZnRFZGdlLmxlbmd0aCAtIDM7CiAgICB3YWxsSW5kaWNlcy5wdXNoKGZyb250IC8gMywgKGJhY2sgLSAyKSAvIDMpOwogICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAzKSB7CiAgICAgIExMID0gZnJvbnQgLyAzOwogICAgICBMUiA9IExMICsgMTsKICAgICAgVUwgPSAoYmFjayAtIDIpIC8gMzsKICAgICAgVVIgPSBVTCAtIDE7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBVTDsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IFVSOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gTEw7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBMUjsKICAgICAgZnJvbnQgKz0gMzsKICAgICAgYmFjayAtPSAzOwogICAgfQogICAgZm9yIChpID0gMDsgaSA8IGNvcm5lcnMubGVuZ3RoOyBpKyspIHsKICAgICAgbGV0IGo7CiAgICAgIGNvcm5lciA9IGNvcm5lcnNbaV07CiAgICAgIGNvbnN0IGwgPSBjb3JuZXIubGVmdFBvc2l0aW9uczsKICAgICAgY29uc3QgciA9IGNvcm5lci5yaWdodFBvc2l0aW9uczsKICAgICAgbGV0IHN0YXJ0OwogICAgICBsZXQgb3V0c2lkZVBvaW50ID0gY2FydGVzaWFuMzM7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobCkpIHsKICAgICAgICBiYWNrIC09IDM7CiAgICAgICAgc3RhcnQgPSBVUjsKICAgICAgICB3YWxsSW5kaWNlcy5wdXNoKExSKTsKICAgICAgICBmb3IgKGogPSAwOyBqIDwgbC5sZW5ndGggLyAzOyBqKyspIHsKICAgICAgICAgIG91dHNpZGVQb2ludCA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkobCwgaiAqIDMsIG91dHNpZGVQb2ludCk7CiAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gc3RhcnQgLSBqIC0gMTsKICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBzdGFydCAtIGo7CiAgICAgICAgICBDb3JyaWRvckdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmFkZEF0dHJpYnV0ZSgKICAgICAgICAgICAgZmluYWxQb3NpdGlvbnMsCiAgICAgICAgICAgIG91dHNpZGVQb2ludCwKICAgICAgICAgICAgdm9pZCAwLAogICAgICAgICAgICBiYWNrCiAgICAgICAgICApOwogICAgICAgICAgYmFjayAtPSAzOwogICAgICAgIH0KICAgICAgICB3YWxsSW5kaWNlcy5wdXNoKHN0YXJ0IC0gTWF0aC5mbG9vcihsLmxlbmd0aCAvIDYpKTsKICAgICAgICBpZiAoY29ybmVyVHlwZSA9PT0gQ29ybmVyVHlwZV9kZWZhdWx0LkJFVkVMRUQpIHsKICAgICAgICAgIHdhbGxJbmRpY2VzLnB1c2goKGJhY2sgLSAyKSAvIDMgKyAxKTsKICAgICAgICB9CiAgICAgICAgZnJvbnQgKz0gMzsKICAgICAgfSBlbHNlIHsKICAgICAgICBmcm9udCArPSAzOwogICAgICAgIHN0YXJ0ID0gTFI7CiAgICAgICAgd2FsbEluZGljZXMucHVzaChVUik7CiAgICAgICAgZm9yIChqID0gMDsgaiA8IHIubGVuZ3RoIC8gMzsgaisrKSB7CiAgICAgICAgICBvdXRzaWRlUG9pbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHIsIGogKiAzLCBvdXRzaWRlUG9pbnQpOwogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHN0YXJ0ICsgajsKICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBzdGFydCArIGogKyAxOwogICAgICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUoCiAgICAgICAgICAgIGZpbmFsUG9zaXRpb25zLAogICAgICAgICAgICBvdXRzaWRlUG9pbnQsCiAgICAgICAgICAgIGZyb250CiAgICAgICAgICApOwogICAgICAgICAgZnJvbnQgKz0gMzsKICAgICAgICB9CiAgICAgICAgd2FsbEluZGljZXMucHVzaChzdGFydCArIE1hdGguZmxvb3Ioci5sZW5ndGggLyA2KSk7CiAgICAgICAgaWYgKGNvcm5lclR5cGUgPT09IENvcm5lclR5cGVfZGVmYXVsdC5CRVZFTEVEKSB7CiAgICAgICAgICB3YWxsSW5kaWNlcy5wdXNoKGZyb250IC8gMyAtIDEpOwogICAgICAgIH0KICAgICAgICBiYWNrIC09IDM7CiAgICAgIH0KICAgICAgcmlnaHRFZGdlID0gcG9zaXRpb25zW3Bvc0luZGV4KytdOwogICAgICBsZWZ0RWRnZSA9IHBvc2l0aW9uc1twb3NJbmRleCsrXTsKICAgICAgcmlnaHRFZGdlLnNwbGljZSgwLCAzKTsKICAgICAgbGVmdEVkZ2Uuc3BsaWNlKGxlZnRFZGdlLmxlbmd0aCAtIDMsIDMpOwogICAgICBmaW5hbFBvc2l0aW9ucy5zZXQocmlnaHRFZGdlLCBmcm9udCk7CiAgICAgIGZpbmFsUG9zaXRpb25zLnNldChsZWZ0RWRnZSwgYmFjayAtIGxlZnRFZGdlLmxlbmd0aCArIDEpOwogICAgICBsZW5ndGggPSBsZWZ0RWRnZS5sZW5ndGggLSAzOwogICAgICBmb3IgKGogPSAwOyBqIDwgbGVmdEVkZ2UubGVuZ3RoOyBqICs9IDMpIHsKICAgICAgICBMUiA9IGZyb250IC8gMzsKICAgICAgICBMTCA9IExSIC0gMTsKICAgICAgICBVUiA9IChiYWNrIC0gMikgLyAzOwogICAgICAgIFVMID0gVVIgKyAxOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBVTDsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gVVI7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IExMOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBMUjsKICAgICAgICBmcm9udCArPSAzOwogICAgICAgIGJhY2sgLT0gMzsKICAgICAgfQogICAgICBmcm9udCAtPSAzOwogICAgICBiYWNrICs9IDM7CiAgICAgIHdhbGxJbmRpY2VzLnB1c2goZnJvbnQgLyAzLCAoYmFjayAtIDIpIC8gMyk7CiAgICB9CiAgICBpZiAoYWRkRW5kUG9zaXRpb25zKSB7CiAgICAgIGZyb250ICs9IDM7CiAgICAgIGJhY2sgLT0gMzsKICAgICAgbGVmdFBvcyA9IGNhcnRlc2lhbjEzOwogICAgICByaWdodFBvcyA9IGNhcnRlc2lhbjIzOwogICAgICBjb25zdCBsYXN0RW5kUG9zaXRpb25zID0gZW5kUG9zaXRpb25zWzFdOwogICAgICBmb3IgKGkgPSAwOyBpIDwgaGFsZkxlbmd0aDsgaSsrKSB7CiAgICAgICAgbGVmdFBvcyA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICBsYXN0RW5kUG9zaXRpb25zLAogICAgICAgICAgKGVuZFBvc2l0aW9uTGVuZ3RoIC0gaSAtIDEpICogMywKICAgICAgICAgIGxlZnRQb3MKICAgICAgICApOwogICAgICAgIHJpZ2h0UG9zID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShsYXN0RW5kUG9zaXRpb25zLCBpICogMywgcmlnaHRQb3MpOwogICAgICAgIENvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuYWRkQXR0cmlidXRlKAogICAgICAgICAgZmluYWxQb3NpdGlvbnMsCiAgICAgICAgICBsZWZ0UG9zLAogICAgICAgICAgdm9pZCAwLAogICAgICAgICAgYmFjawogICAgICAgICk7CiAgICAgICAgQ29ycmlkb3JHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5hZGRBdHRyaWJ1dGUoZmluYWxQb3NpdGlvbnMsIHJpZ2h0UG9zLCBmcm9udCk7CiAgICAgICAgTFIgPSBmcm9udCAvIDM7CiAgICAgICAgTEwgPSBMUiAtIDE7CiAgICAgICAgVVIgPSAoYmFjayAtIDIpIC8gMzsKICAgICAgICBVTCA9IFVSICsgMTsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gVUw7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IFVSOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBMTDsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gTFI7CiAgICAgICAgZnJvbnQgKz0gMzsKICAgICAgICBiYWNrIC09IDM7CiAgICAgIH0KICAgICAgd2FsbEluZGljZXMucHVzaChmcm9udCAvIDMpOwogICAgfSBlbHNlIHsKICAgICAgd2FsbEluZGljZXMucHVzaChmcm9udCAvIDMsIChiYWNrIC0gMikgLyAzKTsKICAgIH0KICAgIGluZGljZXNbaW5kZXgrK10gPSBmcm9udCAvIDM7CiAgICBpbmRpY2VzW2luZGV4KytdID0gKGJhY2sgLSAyKSAvIDM7CiAgICBhdHRyaWJ1dGVzLnBvc2l0aW9uID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgIHZhbHVlczogZmluYWxQb3NpdGlvbnMKICAgIH0pOwogICAgcmV0dXJuIHsKICAgICAgYXR0cmlidXRlcywKICAgICAgaW5kaWNlcywKICAgICAgd2FsbEluZGljZXMKICAgIH07CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVQb3NpdGlvbnNFeHRydWRlZDIocGFyYW1zKSB7CiAgICBjb25zdCBlbGxpcHNvaWQgPSBwYXJhbXMuZWxsaXBzb2lkOwogICAgY29uc3QgY29tcHV0ZWRQb3NpdGlvbnMgPSBDb3JyaWRvckdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVQb3NpdGlvbnMocGFyYW1zKTsKICAgIGNvbnN0IGF0dHIgPSBjb21iaW5lMyhjb21wdXRlZFBvc2l0aW9ucywgcGFyYW1zLmNvcm5lclR5cGUpOwogICAgY29uc3Qgd2FsbEluZGljZXMgPSBhdHRyLndhbGxJbmRpY2VzOwogICAgY29uc3QgaGVpZ2h0ID0gcGFyYW1zLmhlaWdodDsKICAgIGNvbnN0IGV4dHJ1ZGVkSGVpZ2h0ID0gcGFyYW1zLmV4dHJ1ZGVkSGVpZ2h0OwogICAgY29uc3QgYXR0cmlidXRlcyA9IGF0dHIuYXR0cmlidXRlczsKICAgIGNvbnN0IGluZGljZXMgPSBhdHRyLmluZGljZXM7CiAgICBsZXQgcG9zaXRpb25zID0gYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXM7CiAgICBsZXQgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgIGxldCBleHRydWRlZFBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkobGVuZ3RoKTsKICAgIGV4dHJ1ZGVkUG9zaXRpb25zLnNldChwb3NpdGlvbnMpOwogICAgY29uc3QgbmV3UG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShsZW5ndGggKiAyKTsKICAgIHBvc2l0aW9ucyA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LnNjYWxlVG9HZW9kZXRpY0hlaWdodCgKICAgICAgcG9zaXRpb25zLAogICAgICBoZWlnaHQsCiAgICAgIGVsbGlwc29pZAogICAgKTsKICAgIGV4dHJ1ZGVkUG9zaXRpb25zID0gUG9seWdvblBpcGVsaW5lX2RlZmF1bHQuc2NhbGVUb0dlb2RldGljSGVpZ2h0KAogICAgICBleHRydWRlZFBvc2l0aW9ucywKICAgICAgZXh0cnVkZWRIZWlnaHQsCiAgICAgIGVsbGlwc29pZAogICAgKTsKICAgIG5ld1Bvc2l0aW9ucy5zZXQocG9zaXRpb25zKTsKICAgIG5ld1Bvc2l0aW9ucy5zZXQoZXh0cnVkZWRQb3NpdGlvbnMsIGxlbmd0aCk7CiAgICBhdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcyA9IG5ld1Bvc2l0aW9uczsKICAgIGxlbmd0aCAvPSAzOwogICAgaWYgKGRlZmluZWRfZGVmYXVsdChwYXJhbXMub2Zmc2V0QXR0cmlidXRlKSkgewogICAgICBsZXQgYXBwbHlPZmZzZXQgPSBuZXcgVWludDhBcnJheShsZW5ndGggKiAyKTsKICAgICAgaWYgKHBhcmFtcy5vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuVE9QKSB7CiAgICAgICAgYXBwbHlPZmZzZXQgPSBhcHBseU9mZnNldC5maWxsKDEsIDAsIGxlbmd0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgYXBwbHlPZmZzZXRWYWx1ZSA9IHBhcmFtcy5vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuTk9ORSA/IDAgOiAxOwogICAgICAgIGFwcGx5T2Zmc2V0ID0gYXBwbHlPZmZzZXQuZmlsbChhcHBseU9mZnNldFZhbHVlKTsKICAgICAgfQogICAgICBhdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEUsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMSwKICAgICAgICB2YWx1ZXM6IGFwcGx5T2Zmc2V0CiAgICAgIH0pOwogICAgfQogICAgbGV0IGk7CiAgICBjb25zdCBpTGVuZ3RoID0gaW5kaWNlcy5sZW5ndGg7CiAgICBjb25zdCBuZXdJbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgIG5ld1Bvc2l0aW9ucy5sZW5ndGggLyAzLAogICAgICAoaUxlbmd0aCArIHdhbGxJbmRpY2VzLmxlbmd0aCkgKiAyCiAgICApOwogICAgbmV3SW5kaWNlcy5zZXQoaW5kaWNlcyk7CiAgICBsZXQgaW5kZXggPSBpTGVuZ3RoOwogICAgZm9yIChpID0gMDsgaSA8IGlMZW5ndGg7IGkgKz0gMikgewogICAgICBjb25zdCB2MDIgPSBpbmRpY2VzW2ldOwogICAgICBjb25zdCB2MTIgPSBpbmRpY2VzW2kgKyAxXTsKICAgICAgbmV3SW5kaWNlc1tpbmRleCsrXSA9IHYwMiArIGxlbmd0aDsKICAgICAgbmV3SW5kaWNlc1tpbmRleCsrXSA9IHYxMiArIGxlbmd0aDsKICAgIH0KICAgIGxldCBVTCwgTEw7CiAgICBmb3IgKGkgPSAwOyBpIDwgd2FsbEluZGljZXMubGVuZ3RoOyBpKyspIHsKICAgICAgVUwgPSB3YWxsSW5kaWNlc1tpXTsKICAgICAgTEwgPSBVTCArIGxlbmd0aDsKICAgICAgbmV3SW5kaWNlc1tpbmRleCsrXSA9IFVMOwogICAgICBuZXdJbmRpY2VzW2luZGV4KytdID0gTEw7CiAgICB9CiAgICByZXR1cm4gewogICAgICBhdHRyaWJ1dGVzLAogICAgICBpbmRpY2VzOiBuZXdJbmRpY2VzCiAgICB9OwogIH0KICBmdW5jdGlvbiBDb3JyaWRvck91dGxpbmVHZW9tZXRyeShvcHRpb25zKSB7CiAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBvcHRpb25zLnBvc2l0aW9uczsKICAgIGNvbnN0IHdpZHRoID0gb3B0aW9ucy53aWR0aDsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgib3B0aW9ucy5wb3NpdGlvbnMiLCBwb3NpdGlvbnMpOwogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJvcHRpb25zLndpZHRoIiwgd2lkdGgpOwogICAgY29uc3QgaGVpZ2h0ID0gb3B0aW9ucy5oZWlnaHQgPz8gMDsKICAgIGNvbnN0IGV4dHJ1ZGVkSGVpZ2h0ID0gb3B0aW9ucy5leHRydWRlZEhlaWdodCA/PyBoZWlnaHQ7CiAgICB0aGlzLl9wb3NpdGlvbnMgPSBwb3NpdGlvbnM7CiAgICB0aGlzLl9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShvcHRpb25zLmVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0KTsKICAgIHRoaXMuX3dpZHRoID0gd2lkdGg7CiAgICB0aGlzLl9oZWlnaHQgPSBNYXRoLm1heChoZWlnaHQsIGV4dHJ1ZGVkSGVpZ2h0KTsKICAgIHRoaXMuX2V4dHJ1ZGVkSGVpZ2h0ID0gTWF0aC5taW4oaGVpZ2h0LCBleHRydWRlZEhlaWdodCk7CiAgICB0aGlzLl9jb3JuZXJUeXBlID0gb3B0aW9ucy5jb3JuZXJUeXBlID8/IENvcm5lclR5cGVfZGVmYXVsdC5ST1VOREVEOwogICAgdGhpcy5fZ3JhbnVsYXJpdHkgPSBvcHRpb25zLmdyYW51bGFyaXR5ID8/IE1hdGhfZGVmYXVsdC5SQURJQU5TX1BFUl9ERUdSRUU7CiAgICB0aGlzLl9vZmZzZXRBdHRyaWJ1dGUgPSBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZTsKICAgIHRoaXMuX3dvcmtlck5hbWUgPSAiY3JlYXRlQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnkiOwogICAgdGhpcy5wYWNrZWRMZW5ndGggPSAxICsgcG9zaXRpb25zLmxlbmd0aCAqIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyA2OwogIH0KICB2YXIgY2FydGVzaWFuMTMsIGNhcnRlc2lhbjIzLCBjYXJ0ZXNpYW4zMywgc2NyYXRjaEVsbGlwc29pZDUsIHNjcmF0Y2hPcHRpb25zMTAsIENvcnJpZG9yT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NvcnJpZG9yT3V0bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9hcnJheVJlbW92ZUR1cGxpY2F0ZXMoKTsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X0NvbXBvbmVudERhdGF0eXBlKCk7CiAgICAgIGluaXRfQ29ybmVyVHlwZSgpOwogICAgICBpbml0X0NvcnJpZG9yR2VvbWV0cnlMaWJyYXJ5KCk7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZXMoKTsKICAgICAgaW5pdF9HZW9tZXRyeU9mZnNldEF0dHJpYnV0ZSgpOwogICAgICBpbml0X0luZGV4RGF0YXR5cGUoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfUG9seWdvblBpcGVsaW5lKCk7CiAgICAgIGluaXRfUHJpbWl0aXZlVHlwZSgpOwogICAgICBjYXJ0ZXNpYW4xMyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgY2FydGVzaWFuMjMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjMzID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBDb3JyaWRvck91dGxpbmVHZW9tZXRyeS5wYWNrID0gZnVuY3Rpb24odmFsdWUsIGFycmF5LCBzdGFydGluZ0luZGV4KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJ2YWx1ZSIsIHZhbHVlKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gdmFsdWUuX3Bvc2l0aW9uczsKICAgICAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSBsZW5ndGg7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSwgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoKSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhwb3NpdGlvbnNbaV0sIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICB9CiAgICAgICAgRWxsaXBzb2lkX2RlZmF1bHQucGFjayh2YWx1ZS5fZWxsaXBzb2lkLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl93aWR0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2hlaWdodDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2V4dHJ1ZGVkSGVpZ2h0OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fY29ybmVyVHlwZTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2dyYW51bGFyaXR5OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXhdID0gdmFsdWUuX29mZnNldEF0dHJpYnV0ZSA/PyAtMTsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hFbGxpcHNvaWQ1ID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoRWxsaXBzb2lkX2RlZmF1bHQuVU5JVF9TUEhFUkUpOwogICAgICBzY3JhdGNoT3B0aW9uczEwID0gewogICAgICAgIHBvc2l0aW9uczogdm9pZCAwLAogICAgICAgIGVsbGlwc29pZDogc2NyYXRjaEVsbGlwc29pZDUsCiAgICAgICAgd2lkdGg6IHZvaWQgMCwKICAgICAgICBoZWlnaHQ6IHZvaWQgMCwKICAgICAgICBleHRydWRlZEhlaWdodDogdm9pZCAwLAogICAgICAgIGNvcm5lclR5cGU6IHZvaWQgMCwKICAgICAgICBncmFudWxhcml0eTogdm9pZCAwLAogICAgICAgIG9mZnNldEF0dHJpYnV0ZTogdm9pZCAwCiAgICAgIH07CiAgICAgIENvcnJpZG9yT3V0bGluZUdlb21ldHJ5LnVucGFjayA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydGluZ0luZGV4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgQXJyYXkobGVuZ3RoKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpLCBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGgpIHsKICAgICAgICAgIHBvc2l0aW9uc1tpXSA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIH0KICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHNjcmF0Y2hFbGxpcHNvaWQ1KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCB3aWR0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgaGVpZ2h0ID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgY29ybmVyVHlwZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IG9mZnNldEF0dHJpYnV0ZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTAucG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxMC53aWR0aCA9IHdpZHRoOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxMC5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczEwLmV4dHJ1ZGVkSGVpZ2h0ID0gZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczEwLmNvcm5lclR5cGUgPSBjb3JuZXJUeXBlOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxMC5ncmFudWxhcml0eSA9IGdyYW51bGFyaXR5OwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxMC5vZmZzZXRBdHRyaWJ1dGUgPSBvZmZzZXRBdHRyaWJ1dGUgPT09IC0xID8gdm9pZCAwIDogb2Zmc2V0QXR0cmlidXRlOwogICAgICAgICAgcmV0dXJuIG5ldyBDb3JyaWRvck91dGxpbmVHZW9tZXRyeShzY3JhdGNoT3B0aW9uczEwKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0Ll9wb3NpdGlvbnMgPSBwb3NpdGlvbnM7CiAgICAgICAgcmVzdWx0Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShlbGxpcHNvaWQsIHJlc3VsdC5fZWxsaXBzb2lkKTsKICAgICAgICByZXN1bHQuX3dpZHRoID0gd2lkdGg7CiAgICAgICAgcmVzdWx0Ll9oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgcmVzdWx0Ll9leHRydWRlZEhlaWdodCA9IGV4dHJ1ZGVkSGVpZ2h0OwogICAgICAgIHJlc3VsdC5fY29ybmVyVHlwZSA9IGNvcm5lclR5cGU7CiAgICAgICAgcmVzdWx0Ll9ncmFudWxhcml0eSA9IGdyYW51bGFyaXR5OwogICAgICAgIHJlc3VsdC5fb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlID09PSAtMSA/IHZvaWQgMCA6IG9mZnNldEF0dHJpYnV0ZTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDb3JyaWRvck91dGxpbmVHZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKGNvcnJpZG9yT3V0bGluZUdlb21ldHJ5KSB7CiAgICAgICAgbGV0IHBvc2l0aW9ucyA9IGNvcnJpZG9yT3V0bGluZUdlb21ldHJ5Ll9wb3NpdGlvbnM7CiAgICAgICAgY29uc3Qgd2lkdGggPSBjb3JyaWRvck91dGxpbmVHZW9tZXRyeS5fd2lkdGg7CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gY29ycmlkb3JPdXRsaW5lR2VvbWV0cnkuX2VsbGlwc29pZDsKICAgICAgICBwb3NpdGlvbnMgPSBzY2FsZVRvU3VyZmFjZTMocG9zaXRpb25zLCBlbGxpcHNvaWQpOwogICAgICAgIGNvbnN0IGNsZWFuUG9zaXRpb25zID0gYXJyYXlSZW1vdmVEdXBsaWNhdGVzX2RlZmF1bHQoCiAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbgogICAgICAgICk7CiAgICAgICAgaWYgKGNsZWFuUG9zaXRpb25zLmxlbmd0aCA8IDIgfHwgd2lkdGggPD0gMCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBjb25zdCBoZWlnaHQgPSBjb3JyaWRvck91dGxpbmVHZW9tZXRyeS5faGVpZ2h0OwogICAgICAgIGNvbnN0IGV4dHJ1ZGVkSGVpZ2h0ID0gY29ycmlkb3JPdXRsaW5lR2VvbWV0cnkuX2V4dHJ1ZGVkSGVpZ2h0OwogICAgICAgIGNvbnN0IGV4dHJ1ZGUgPSAhTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICBoZWlnaHQsCiAgICAgICAgICBleHRydWRlZEhlaWdodCwKICAgICAgICAgIDAsCiAgICAgICAgICBNYXRoX2RlZmF1bHQuRVBTSUxPTjIKICAgICAgICApOwogICAgICAgIGNvbnN0IHBhcmFtcyA9IHsKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIHBvc2l0aW9uczogY2xlYW5Qb3NpdGlvbnMsCiAgICAgICAgICB3aWR0aCwKICAgICAgICAgIGNvcm5lclR5cGU6IGNvcnJpZG9yT3V0bGluZUdlb21ldHJ5Ll9jb3JuZXJUeXBlLAogICAgICAgICAgZ3JhbnVsYXJpdHk6IGNvcnJpZG9yT3V0bGluZUdlb21ldHJ5Ll9ncmFudWxhcml0eSwKICAgICAgICAgIHNhdmVBdHRyaWJ1dGVzOiBmYWxzZQogICAgICAgIH07CiAgICAgICAgbGV0IGF0dHI7CiAgICAgICAgaWYgKGV4dHJ1ZGUpIHsKICAgICAgICAgIHBhcmFtcy5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgICBwYXJhbXMuZXh0cnVkZWRIZWlnaHQgPSBleHRydWRlZEhlaWdodDsKICAgICAgICAgIHBhcmFtcy5vZmZzZXRBdHRyaWJ1dGUgPSBjb3JyaWRvck91dGxpbmVHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlOwogICAgICAgICAgYXR0ciA9IGNvbXB1dGVQb3NpdGlvbnNFeHRydWRlZDIocGFyYW1zKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgY29tcHV0ZWRQb3NpdGlvbnMgPSBDb3JyaWRvckdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVQb3NpdGlvbnMocGFyYW1zKTsKICAgICAgICAgIGF0dHIgPSBjb21iaW5lMyhjb21wdXRlZFBvc2l0aW9ucywgcGFyYW1zLmNvcm5lclR5cGUpOwogICAgICAgICAgYXR0ci5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcyA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LnNjYWxlVG9HZW9kZXRpY0hlaWdodCgKICAgICAgICAgICAgYXR0ci5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcywKICAgICAgICAgICAgaGVpZ2h0LAogICAgICAgICAgICBlbGxpcHNvaWQKICAgICAgICAgICk7CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGNvcnJpZG9yT3V0bGluZUdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUpKSB7CiAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IGF0dHIuYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMubGVuZ3RoOwogICAgICAgICAgICBjb25zdCBvZmZzZXRWYWx1ZSA9IGNvcnJpZG9yT3V0bGluZUdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuTk9ORSA/IDAgOiAxOwogICAgICAgICAgICBjb25zdCBhcHBseU9mZnNldCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCAvIDMpLmZpbGwob2Zmc2V0VmFsdWUpOwogICAgICAgICAgICBhdHRyLmF0dHJpYnV0ZXMuYXBwbHlPZmZzZXQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuVU5TSUdORURfQllURSwKICAgICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAxLAogICAgICAgICAgICAgIHZhbHVlczogYXBwbHlPZmZzZXQKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBhdHRyLmF0dHJpYnV0ZXM7CiAgICAgICAgY29uc3QgYm91bmRpbmdTcGhlcmUgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21WZXJ0aWNlcygKICAgICAgICAgIGF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLAogICAgICAgICAgdm9pZCAwLAogICAgICAgICAgMwogICAgICAgICk7CiAgICAgICAgcmV0dXJuIG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgICAgIGF0dHJpYnV0ZXMsCiAgICAgICAgICBpbmRpY2VzOiBhdHRyLmluZGljZXMsCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBQcmltaXRpdmVUeXBlX2RlZmF1bHQuTElORVMsCiAgICAgICAgICBib3VuZGluZ1NwaGVyZSwKICAgICAgICAgIG9mZnNldEF0dHJpYnV0ZTogY29ycmlkb3JPdXRsaW5lR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZQogICAgICAgIH0pOwogICAgICB9OwogICAgICBDb3JyaWRvck91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVDb3JyaWRvck91dGxpbmVHZW9tZXRyeS5qcwogIHZhciBjcmVhdGVDb3JyaWRvck91dGxpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnlfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZUNvcnJpZG9yT3V0bGluZUdlb21ldHJ5KGNvcnJpZG9yT3V0bGluZUdlb21ldHJ5LCBvZmZzZXQpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob2Zmc2V0KSkgewogICAgICBjb3JyaWRvck91dGxpbmVHZW9tZXRyeSA9IENvcnJpZG9yT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQudW5wYWNrKAogICAgICAgIGNvcnJpZG9yT3V0bGluZUdlb21ldHJ5LAogICAgICAgIG9mZnNldAogICAgICApOwogICAgfQogICAgY29ycmlkb3JPdXRsaW5lR2VvbWV0cnkuX2VsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKAogICAgICBjb3JyaWRvck91dGxpbmVHZW9tZXRyeS5fZWxsaXBzb2lkCiAgICApOwogICAgcmV0dXJuIENvcnJpZG9yT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkoY29ycmlkb3JPdXRsaW5lR2VvbWV0cnkpOwogIH0KICB2YXIgY3JlYXRlQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVDb3JyaWRvck91dGxpbmVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0NvcnJpZG9yT3V0bGluZUdlb21ldHJ5KCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBjcmVhdGVDb3JyaWRvck91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gY3JlYXRlQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9DeWxpbmRlckdlb21ldHJ5TGlicmFyeS5qcwogIHZhciBDeWxpbmRlckdlb21ldHJ5TGlicmFyeSwgQ3lsaW5kZXJHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdDsKICB2YXIgaW5pdF9DeWxpbmRlckdlb21ldHJ5TGlicmFyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ3lsaW5kZXJHZW9tZXRyeUxpYnJhcnkuanMiKCkgewogICAgICBpbml0X01hdGgoKTsKICAgICAgQ3lsaW5kZXJHZW9tZXRyeUxpYnJhcnkgPSB7fTsKICAgICAgQ3lsaW5kZXJHZW9tZXRyeUxpYnJhcnkuY29tcHV0ZVBvc2l0aW9ucyA9IGZ1bmN0aW9uKGxlbmd0aCwgdG9wUmFkaXVzLCBib3R0b21SYWRpdXMsIHNsaWNlcywgZmlsbCkgewogICAgICAgIGNvbnN0IHRvcFogPSBsZW5ndGggKiAwLjU7CiAgICAgICAgY29uc3QgYm90dG9tWiA9IC10b3BaOwogICAgICAgIGNvbnN0IHR3b1NsaWNlID0gc2xpY2VzICsgc2xpY2VzOwogICAgICAgIGNvbnN0IHNpemUgPSBmaWxsID8gMiAqIHR3b1NsaWNlIDogdHdvU2xpY2U7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShzaXplICogMyk7CiAgICAgICAgbGV0IGk7CiAgICAgICAgbGV0IGluZGV4ID0gMDsKICAgICAgICBsZXQgdGJJbmRleCA9IDA7CiAgICAgICAgY29uc3QgYm90dG9tT2Zmc2V0ID0gZmlsbCA/IHR3b1NsaWNlICogMyA6IDA7CiAgICAgICAgY29uc3QgdG9wT2Zmc2V0ID0gZmlsbCA/ICh0d29TbGljZSArIHNsaWNlcykgKiAzIDogc2xpY2VzICogMzsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc2xpY2VzOyBpKyspIHsKICAgICAgICAgIGNvbnN0IGFuZ2xlID0gaSAvIHNsaWNlcyAqIE1hdGhfZGVmYXVsdC5UV09fUEk7CiAgICAgICAgICBjb25zdCB4ID0gTWF0aC5jb3MoYW5nbGUpOwogICAgICAgICAgY29uc3QgeSA9IE1hdGguc2luKGFuZ2xlKTsKICAgICAgICAgIGNvbnN0IGJvdHRvbVggPSB4ICogYm90dG9tUmFkaXVzOwogICAgICAgICAgY29uc3QgYm90dG9tWSA9IHkgKiBib3R0b21SYWRpdXM7CiAgICAgICAgICBjb25zdCB0b3BYID0geCAqIHRvcFJhZGl1czsKICAgICAgICAgIGNvbnN0IHRvcFkgPSB5ICogdG9wUmFkaXVzOwogICAgICAgICAgcG9zaXRpb25zW3RiSW5kZXggKyBib3R0b21PZmZzZXRdID0gYm90dG9tWDsKICAgICAgICAgIHBvc2l0aW9uc1t0YkluZGV4ICsgYm90dG9tT2Zmc2V0ICsgMV0gPSBib3R0b21ZOwogICAgICAgICAgcG9zaXRpb25zW3RiSW5kZXggKyBib3R0b21PZmZzZXQgKyAyXSA9IGJvdHRvbVo7CiAgICAgICAgICBwb3NpdGlvbnNbdGJJbmRleCArIHRvcE9mZnNldF0gPSB0b3BYOwogICAgICAgICAgcG9zaXRpb25zW3RiSW5kZXggKyB0b3BPZmZzZXQgKyAxXSA9IHRvcFk7CiAgICAgICAgICBwb3NpdGlvbnNbdGJJbmRleCArIHRvcE9mZnNldCArIDJdID0gdG9wWjsKICAgICAgICAgIHRiSW5kZXggKz0gMzsKICAgICAgICAgIGlmIChmaWxsKSB7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpbmRleCsrXSA9IGJvdHRvbVg7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpbmRleCsrXSA9IGJvdHRvbVk7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpbmRleCsrXSA9IGJvdHRvbVo7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpbmRleCsrXSA9IHRvcFg7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpbmRleCsrXSA9IHRvcFk7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpbmRleCsrXSA9IHRvcFo7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBwb3NpdGlvbnM7CiAgICAgIH07CiAgICAgIEN5bGluZGVyR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQgPSBDeWxpbmRlckdlb21ldHJ5TGlicmFyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0N5bGluZGVyR2VvbWV0cnkuanMKICBmdW5jdGlvbiBDeWxpbmRlckdlb21ldHJ5KG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIGNvbnN0IGxlbmd0aCA9IG9wdGlvbnMubGVuZ3RoOwogICAgY29uc3QgdG9wUmFkaXVzID0gb3B0aW9ucy50b3BSYWRpdXM7CiAgICBjb25zdCBib3R0b21SYWRpdXMgPSBvcHRpb25zLmJvdHRvbVJhZGl1czsKICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IG9wdGlvbnMudmVydGV4Rm9ybWF0ID8/IFZlcnRleEZvcm1hdF9kZWZhdWx0LkRFRkFVTFQ7CiAgICBjb25zdCBzbGljZXMgPSBvcHRpb25zLnNsaWNlcyA/PyAxMjg7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChsZW5ndGgpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJvcHRpb25zLmxlbmd0aCBtdXN0IGJlIGRlZmluZWQuIik7CiAgICB9CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh0b3BSYWRpdXMpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJvcHRpb25zLnRvcFJhZGl1cyBtdXN0IGJlIGRlZmluZWQuIik7CiAgICB9CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChib3R0b21SYWRpdXMpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJvcHRpb25zLmJvdHRvbVJhZGl1cyBtdXN0IGJlIGRlZmluZWQuIik7CiAgICB9CiAgICBpZiAoc2xpY2VzIDwgMykgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAib3B0aW9ucy5zbGljZXMgbXVzdCBiZSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gMy4iCiAgICAgICk7CiAgICB9CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlKSAmJiBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5UT1ApIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgIkdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlLlRPUCBpcyBub3QgYSBzdXBwb3J0ZWQgb3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGUgZm9yIHRoaXMgZ2VvbWV0cnkuIgogICAgICApOwogICAgfQogICAgdGhpcy5fbGVuZ3RoID0gbGVuZ3RoOwogICAgdGhpcy5fdG9wUmFkaXVzID0gdG9wUmFkaXVzOwogICAgdGhpcy5fYm90dG9tUmFkaXVzID0gYm90dG9tUmFkaXVzOwogICAgdGhpcy5fdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQuY2xvbmUodmVydGV4Rm9ybWF0KTsKICAgIHRoaXMuX3NsaWNlcyA9IHNsaWNlczsKICAgIHRoaXMuX29mZnNldEF0dHJpYnV0ZSA9IG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlOwogICAgdGhpcy5fd29ya2VyTmFtZSA9ICJjcmVhdGVDeWxpbmRlckdlb21ldHJ5IjsKICB9CiAgdmFyIHJhZGl1c1NjcmF0Y2gsIG5vcm1hbFNjcmF0Y2gzLCBiaXRhbmdlbnRTY3JhdGNoLCB0YW5nZW50U2NyYXRjaCwgcG9zaXRpb25TY3JhdGNoLCBzY3JhdGNoVmVydGV4Rm9ybWF0NSwgc2NyYXRjaE9wdGlvbnMxMSwgdW5pdEN5bGluZGVyR2VvbWV0cnksIEN5bGluZGVyR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9DeWxpbmRlckdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9DeWxpbmRlckdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ29tcG9uZW50RGF0YXR5cGUoKTsKICAgICAgaW5pdF9DeWxpbmRlckdlb21ldHJ5TGlicmFyeSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZXMoKTsKICAgICAgaW5pdF9HZW9tZXRyeU9mZnNldEF0dHJpYnV0ZSgpOwogICAgICBpbml0X0luZGV4RGF0YXR5cGUoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfUHJpbWl0aXZlVHlwZSgpOwogICAgICBpbml0X1ZlcnRleEZvcm1hdCgpOwogICAgICByYWRpdXNTY3JhdGNoID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBub3JtYWxTY3JhdGNoMyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgYml0YW5nZW50U2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgdGFuZ2VudFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHBvc2l0aW9uU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgQ3lsaW5kZXJHZW9tZXRyeS5wYWNrZWRMZW5ndGggPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyA1OwogICAgICBDeWxpbmRlckdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh2YWx1ZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ2YWx1ZSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhcnJheSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhcnJheSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2sodmFsdWUuX3ZlcnRleEZvcm1hdCwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fbGVuZ3RoOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fdG9wUmFkaXVzOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fYm90dG9tUmFkaXVzOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fc2xpY2VzOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXhdID0gdmFsdWUuX29mZnNldEF0dHJpYnV0ZSA/PyAtMTsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQ1ID0gbmV3IFZlcnRleEZvcm1hdF9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hPcHRpb25zMTEgPSB7CiAgICAgICAgdmVydGV4Rm9ybWF0OiBzY3JhdGNoVmVydGV4Rm9ybWF0NSwKICAgICAgICBsZW5ndGg6IHZvaWQgMCwKICAgICAgICB0b3BSYWRpdXM6IHZvaWQgMCwKICAgICAgICBib3R0b21SYWRpdXM6IHZvaWQgMCwKICAgICAgICBzbGljZXM6IHZvaWQgMCwKICAgICAgICBvZmZzZXRBdHRyaWJ1dGU6IHZvaWQgMAogICAgICB9OwogICAgICBDeWxpbmRlckdlb21ldHJ5LnVucGFjayA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydGluZ0luZGV4LCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhcnJheSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhcnJheSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnVucGFjaygKICAgICAgICAgIGFycmF5LAogICAgICAgICAgc3RhcnRpbmdJbmRleCwKICAgICAgICAgIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQ1CiAgICAgICAgKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCBsZW5ndGggPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHRvcFJhZGl1cyA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgYm90dG9tUmFkaXVzID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBzbGljZXMgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IG9mZnNldEF0dHJpYnV0ZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTEubGVuZ3RoID0gbGVuZ3RoOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxMS50b3BSYWRpdXMgPSB0b3BSYWRpdXM7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczExLmJvdHRvbVJhZGl1cyA9IGJvdHRvbVJhZGl1czsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTEuc2xpY2VzID0gc2xpY2VzOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxMS5vZmZzZXRBdHRyaWJ1dGUgPSBvZmZzZXRBdHRyaWJ1dGUgPT09IC0xID8gdm9pZCAwIDogb2Zmc2V0QXR0cmlidXRlOwogICAgICAgICAgcmV0dXJuIG5ldyBDeWxpbmRlckdlb21ldHJ5KHNjcmF0Y2hPcHRpb25zMTEpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuX3ZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LmNsb25lKHZlcnRleEZvcm1hdCwgcmVzdWx0Ll92ZXJ0ZXhGb3JtYXQpOwogICAgICAgIHJlc3VsdC5fbGVuZ3RoID0gbGVuZ3RoOwogICAgICAgIHJlc3VsdC5fdG9wUmFkaXVzID0gdG9wUmFkaXVzOwogICAgICAgIHJlc3VsdC5fYm90dG9tUmFkaXVzID0gYm90dG9tUmFkaXVzOwogICAgICAgIHJlc3VsdC5fc2xpY2VzID0gc2xpY2VzOwogICAgICAgIHJlc3VsdC5fb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlID09PSAtMSA/IHZvaWQgMCA6IG9mZnNldEF0dHJpYnV0ZTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDeWxpbmRlckdlb21ldHJ5LmNyZWF0ZUdlb21ldHJ5ID0gZnVuY3Rpb24oY3lsaW5kZXJHZW9tZXRyeSkgewogICAgICAgIGxldCBsZW5ndGggPSBjeWxpbmRlckdlb21ldHJ5Ll9sZW5ndGg7CiAgICAgICAgY29uc3QgdG9wUmFkaXVzID0gY3lsaW5kZXJHZW9tZXRyeS5fdG9wUmFkaXVzOwogICAgICAgIGNvbnN0IGJvdHRvbVJhZGl1cyA9IGN5bGluZGVyR2VvbWV0cnkuX2JvdHRvbVJhZGl1czsKICAgICAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBjeWxpbmRlckdlb21ldHJ5Ll92ZXJ0ZXhGb3JtYXQ7CiAgICAgICAgY29uc3Qgc2xpY2VzID0gY3lsaW5kZXJHZW9tZXRyeS5fc2xpY2VzOwogICAgICAgIGlmIChsZW5ndGggPD0gMCB8fCB0b3BSYWRpdXMgPCAwIHx8IGJvdHRvbVJhZGl1cyA8IDAgfHwgdG9wUmFkaXVzID09PSAwICYmIGJvdHRvbVJhZGl1cyA9PT0gMCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBjb25zdCB0d29TbGljZXMgPSBzbGljZXMgKyBzbGljZXM7CiAgICAgICAgY29uc3QgdGhyZWVTbGljZXMgPSBzbGljZXMgKyB0d29TbGljZXM7CiAgICAgICAgY29uc3QgbnVtVmVydGljZXMgPSB0d29TbGljZXMgKyB0d29TbGljZXM7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gQ3lsaW5kZXJHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlUG9zaXRpb25zKAogICAgICAgICAgbGVuZ3RoLAogICAgICAgICAgdG9wUmFkaXVzLAogICAgICAgICAgYm90dG9tUmFkaXVzLAogICAgICAgICAgc2xpY2VzLAogICAgICAgICAgdHJ1ZQogICAgICAgICk7CiAgICAgICAgY29uc3Qgc3QgPSB2ZXJ0ZXhGb3JtYXQuc3QgPyBuZXcgRmxvYXQzMkFycmF5KG51bVZlcnRpY2VzICogMikgOiB2b2lkIDA7CiAgICAgICAgY29uc3Qgbm9ybWFscyA9IHZlcnRleEZvcm1hdC5ub3JtYWwgPyBuZXcgRmxvYXQzMkFycmF5KG51bVZlcnRpY2VzICogMykgOiB2b2lkIDA7CiAgICAgICAgY29uc3QgdGFuZ2VudHMgPSB2ZXJ0ZXhGb3JtYXQudGFuZ2VudCA/IG5ldyBGbG9hdDMyQXJyYXkobnVtVmVydGljZXMgKiAzKSA6IHZvaWQgMDsKICAgICAgICBjb25zdCBiaXRhbmdlbnRzID0gdmVydGV4Rm9ybWF0LmJpdGFuZ2VudCA/IG5ldyBGbG9hdDMyQXJyYXkobnVtVmVydGljZXMgKiAzKSA6IHZvaWQgMDsKICAgICAgICBsZXQgaTsKICAgICAgICBjb25zdCBjb21wdXRlTm9ybWFsID0gdmVydGV4Rm9ybWF0Lm5vcm1hbCB8fCB2ZXJ0ZXhGb3JtYXQudGFuZ2VudCB8fCB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50OwogICAgICAgIGlmIChjb21wdXRlTm9ybWFsKSB7CiAgICAgICAgICBjb25zdCBjb21wdXRlVGFuZ2VudCA9IHZlcnRleEZvcm1hdC50YW5nZW50IHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQ7CiAgICAgICAgICBsZXQgbm9ybWFsSW5kZXggPSAwOwogICAgICAgICAgbGV0IHRhbmdlbnRJbmRleCA9IDA7CiAgICAgICAgICBsZXQgYml0YW5nZW50SW5kZXggPSAwOwogICAgICAgICAgY29uc3QgdGhldGEgPSBNYXRoLmF0YW4yKGJvdHRvbVJhZGl1cyAtIHRvcFJhZGl1cywgbGVuZ3RoKTsKICAgICAgICAgIGNvbnN0IG5vcm1hbDIgPSBub3JtYWxTY3JhdGNoMzsKICAgICAgICAgIG5vcm1hbDIueiA9IE1hdGguc2luKHRoZXRhKTsKICAgICAgICAgIGNvbnN0IG5vcm1hbFNjYWxlMiA9IE1hdGguY29zKHRoZXRhKTsKICAgICAgICAgIGxldCB0YW5nZW50ID0gdGFuZ2VudFNjcmF0Y2g7CiAgICAgICAgICBsZXQgYml0YW5nZW50ID0gYml0YW5nZW50U2NyYXRjaDsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzbGljZXM7IGkrKykgewogICAgICAgICAgICBjb25zdCBhbmdsZSA9IGkgLyBzbGljZXMgKiBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgICAgICAgICBjb25zdCB4ID0gbm9ybWFsU2NhbGUyICogTWF0aC5jb3MoYW5nbGUpOwogICAgICAgICAgICBjb25zdCB5ID0gbm9ybWFsU2NhbGUyICogTWF0aC5zaW4oYW5nbGUpOwogICAgICAgICAgICBpZiAoY29tcHV0ZU5vcm1hbCkgewogICAgICAgICAgICAgIG5vcm1hbDIueCA9IHg7CiAgICAgICAgICAgICAgbm9ybWFsMi55ID0geTsKICAgICAgICAgICAgICBpZiAoY29tcHV0ZVRhbmdlbnQpIHsKICAgICAgICAgICAgICAgIHRhbmdlbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWiwgbm9ybWFsMiwgdGFuZ2VudCksCiAgICAgICAgICAgICAgICAgIHRhbmdlbnQKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgICAgICAgICAgICBub3JtYWxzW25vcm1hbEluZGV4KytdID0gbm9ybWFsMi54OwogICAgICAgICAgICAgICAgbm9ybWFsc1tub3JtYWxJbmRleCsrXSA9IG5vcm1hbDIueTsKICAgICAgICAgICAgICAgIG5vcm1hbHNbbm9ybWFsSW5kZXgrK10gPSBub3JtYWwyLno7CiAgICAgICAgICAgICAgICBub3JtYWxzW25vcm1hbEluZGV4KytdID0gbm9ybWFsMi54OwogICAgICAgICAgICAgICAgbm9ybWFsc1tub3JtYWxJbmRleCsrXSA9IG5vcm1hbDIueTsKICAgICAgICAgICAgICAgIG5vcm1hbHNbbm9ybWFsSW5kZXgrK10gPSBub3JtYWwyLno7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICAgICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC54OwogICAgICAgICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC55OwogICAgICAgICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC56OwogICAgICAgICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC54OwogICAgICAgICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC55OwogICAgICAgICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC56OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgICAgICAgICAgYml0YW5nZW50ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKG5vcm1hbDIsIHRhbmdlbnQsIGJpdGFuZ2VudCksCiAgICAgICAgICAgICAgICAgIGJpdGFuZ2VudAogICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQueDsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQueTsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQuejsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQueDsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQueTsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQuejsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzbGljZXM7IGkrKykgewogICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICAgICAgICAgIG5vcm1hbHNbbm9ybWFsSW5kZXgrK10gPSAwOwogICAgICAgICAgICAgIG5vcm1hbHNbbm9ybWFsSW5kZXgrK10gPSAwOwogICAgICAgICAgICAgIG5vcm1hbHNbbm9ybWFsSW5kZXgrK10gPSAtMTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQpIHsKICAgICAgICAgICAgICB0YW5nZW50c1t0YW5nZW50SW5kZXgrK10gPSAxOwogICAgICAgICAgICAgIHRhbmdlbnRzW3RhbmdlbnRJbmRleCsrXSA9IDA7CiAgICAgICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSAwOwogICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSAtMTsKICAgICAgICAgICAgICBiaXRhbmdlbnRzW2JpdGFuZ2VudEluZGV4KytdID0gMDsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZm9yIChpID0gMDsgaSA8IHNsaWNlczsgaSsrKSB7CiAgICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgICAgICAgICAgbm9ybWFsc1tub3JtYWxJbmRleCsrXSA9IDA7CiAgICAgICAgICAgICAgbm9ybWFsc1tub3JtYWxJbmRleCsrXSA9IDA7CiAgICAgICAgICAgICAgbm9ybWFsc1tub3JtYWxJbmRleCsrXSA9IDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHZlcnRleEZvcm1hdC50YW5nZW50KSB7CiAgICAgICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gMTsKICAgICAgICAgICAgICB0YW5nZW50c1t0YW5nZW50SW5kZXgrK10gPSAwOwogICAgICAgICAgICAgIHRhbmdlbnRzW3RhbmdlbnRJbmRleCsrXSA9IDA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgICAgICBiaXRhbmdlbnRzW2JpdGFuZ2VudEluZGV4KytdID0gMDsKICAgICAgICAgICAgICBiaXRhbmdlbnRzW2JpdGFuZ2VudEluZGV4KytdID0gMTsKICAgICAgICAgICAgICBiaXRhbmdlbnRzW2JpdGFuZ2VudEluZGV4KytdID0gMDsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBudW1JbmRpY2VzID0gMTIgKiBzbGljZXMgLSAxMjsKICAgICAgICBjb25zdCBpbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkobnVtVmVydGljZXMsIG51bUluZGljZXMpOwogICAgICAgIGxldCBpbmRleCA9IDA7CiAgICAgICAgbGV0IGogPSAwOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBzbGljZXMgLSAxOyBpKyspIHsKICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBqOwogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGogKyAyOwogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGogKyAzOwogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGo7CiAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gaiArIDM7CiAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gaiArIDE7CiAgICAgICAgICBqICs9IDI7CiAgICAgICAgfQogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSB0d29TbGljZXMgLSAyOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSAwOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSAxOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSB0d29TbGljZXMgLSAyOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSAxOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSB0d29TbGljZXMgLSAxOwogICAgICAgIGZvciAoaSA9IDE7IGkgPCBzbGljZXMgLSAxOyBpKyspIHsKICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSB0d29TbGljZXMgKyBpICsgMTsKICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSB0d29TbGljZXMgKyBpOwogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHR3b1NsaWNlczsKICAgICAgICB9CiAgICAgICAgZm9yIChpID0gMTsgaSA8IHNsaWNlcyAtIDE7IGkrKykgewogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHRocmVlU2xpY2VzOwogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHRocmVlU2xpY2VzICsgaTsKICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSB0aHJlZVNsaWNlcyArIGkgKyAxOwogICAgICAgIH0KICAgICAgICBsZXQgdGV4dHVyZUNvb3JkSW5kZXggPSAwOwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICAgIGNvbnN0IHJhZCA9IE1hdGgubWF4KHRvcFJhZGl1cywgYm90dG9tUmFkaXVzKTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1WZXJ0aWNlczsgaSsrKSB7CiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIGkgKiAzLCBwb3NpdGlvblNjcmF0Y2gpOwogICAgICAgICAgICBzdFt0ZXh0dXJlQ29vcmRJbmRleCsrXSA9IChwb3NpdGlvbi54ICsgcmFkKSAvICgyICogcmFkKTsKICAgICAgICAgICAgc3RbdGV4dHVyZUNvb3JkSW5kZXgrK10gPSAocG9zaXRpb24ueSArIHJhZCkgLyAoMiAqIHJhZCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoKTsKICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnBvc2l0aW9uKSB7CiAgICAgICAgICBhdHRyaWJ1dGVzLnBvc2l0aW9uID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICAgIHZhbHVlczogcG9zaXRpb25zCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5ub3JtYWwpIHsKICAgICAgICAgIGF0dHJpYnV0ZXMubm9ybWFsID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgdmFsdWVzOiBub3JtYWxzCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC50YW5nZW50KSB7CiAgICAgICAgICBhdHRyaWJ1dGVzLnRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgICB2YWx1ZXM6IHRhbmdlbnRzCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgIGF0dHJpYnV0ZXMuYml0YW5nZW50ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgdmFsdWVzOiBiaXRhbmdlbnRzCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5zdCkgewogICAgICAgICAgYXR0cmlidXRlcy5zdCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDIsCiAgICAgICAgICAgIHZhbHVlczogc3QKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICByYWRpdXNTY3JhdGNoLnggPSBsZW5ndGggKiAwLjU7CiAgICAgICAgcmFkaXVzU2NyYXRjaC55ID0gTWF0aC5tYXgoYm90dG9tUmFkaXVzLCB0b3BSYWRpdXMpOwogICAgICAgIGNvbnN0IGJvdW5kaW5nU3BoZXJlID0gbmV3IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQoCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywKICAgICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdC5tYWduaXR1ZGUocmFkaXVzU2NyYXRjaCkKICAgICAgICApOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoY3lsaW5kZXJHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlKSkgewogICAgICAgICAgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICAgIGNvbnN0IG9mZnNldFZhbHVlID0gY3lsaW5kZXJHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlID09PSBHZW9tZXRyeU9mZnNldEF0dHJpYnV0ZV9kZWZhdWx0Lk5PTkUgPyAwIDogMTsKICAgICAgICAgIGNvbnN0IGFwcGx5T2Zmc2V0ID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoIC8gMykuZmlsbChvZmZzZXRWYWx1ZSk7CiAgICAgICAgICBhdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9CWVRFLAogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAxLAogICAgICAgICAgICB2YWx1ZXM6IGFwcGx5T2Zmc2V0CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgICAgIGF0dHJpYnV0ZXMsCiAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUywKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlLAogICAgICAgICAgb2Zmc2V0QXR0cmlidXRlOiBjeWxpbmRlckdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgQ3lsaW5kZXJHZW9tZXRyeS5nZXRVbml0Q3lsaW5kZXIgPSBmdW5jdGlvbigpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh1bml0Q3lsaW5kZXJHZW9tZXRyeSkpIHsKICAgICAgICAgIHVuaXRDeWxpbmRlckdlb21ldHJ5ID0gQ3lsaW5kZXJHZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSgKICAgICAgICAgICAgbmV3IEN5bGluZGVyR2VvbWV0cnkoewogICAgICAgICAgICAgIHRvcFJhZGl1czogMSwKICAgICAgICAgICAgICBib3R0b21SYWRpdXM6IDEsCiAgICAgICAgICAgICAgbGVuZ3RoOiAxLAogICAgICAgICAgICAgIHZlcnRleEZvcm1hdDogVmVydGV4Rm9ybWF0X2RlZmF1bHQuUE9TSVRJT05fT05MWQogICAgICAgICAgICB9KQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHVuaXRDeWxpbmRlckdlb21ldHJ5OwogICAgICB9OwogICAgICBDeWxpbmRlckdlb21ldHJ5X2RlZmF1bHQgPSBDeWxpbmRlckdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlQ3lsaW5kZXJHZW9tZXRyeS5qcwogIHZhciBjcmVhdGVDeWxpbmRlckdlb21ldHJ5X2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChjcmVhdGVDeWxpbmRlckdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZUN5bGluZGVyR2VvbWV0cnlfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZUN5bGluZGVyR2VvbWV0cnkoY3lsaW5kZXJHZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgY3lsaW5kZXJHZW9tZXRyeSA9IEN5bGluZGVyR2VvbWV0cnlfZGVmYXVsdC51bnBhY2soY3lsaW5kZXJHZW9tZXRyeSwgb2Zmc2V0KTsKICAgIH0KICAgIHJldHVybiBDeWxpbmRlckdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkoY3lsaW5kZXJHZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVDeWxpbmRlckdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlQ3lsaW5kZXJHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlQ3lsaW5kZXJHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQ3lsaW5kZXJHZW9tZXRyeSgpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgY3JlYXRlQ3lsaW5kZXJHZW9tZXRyeV9kZWZhdWx0ID0gY3JlYXRlQ3lsaW5kZXJHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0N5bGluZGVyT3V0bGluZUdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gQ3lsaW5kZXJPdXRsaW5lR2VvbWV0cnkob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgY29uc3QgbGVuZ3RoID0gb3B0aW9ucy5sZW5ndGg7CiAgICBjb25zdCB0b3BSYWRpdXMgPSBvcHRpb25zLnRvcFJhZGl1czsKICAgIGNvbnN0IGJvdHRvbVJhZGl1cyA9IG9wdGlvbnMuYm90dG9tUmFkaXVzOwogICAgY29uc3Qgc2xpY2VzID0gb3B0aW9ucy5zbGljZXMgPz8gMTI4OwogICAgY29uc3QgbnVtYmVyT2ZWZXJ0aWNhbExpbmVzID0gTWF0aC5tYXgoCiAgICAgIG9wdGlvbnMubnVtYmVyT2ZWZXJ0aWNhbExpbmVzID8/IDE2LAogICAgICAwCiAgICApOwogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJvcHRpb25zLnBvc2l0aW9ucyIsIGxlbmd0aCk7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoIm9wdGlvbnMudG9wUmFkaXVzIiwgdG9wUmFkaXVzKTsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigib3B0aW9ucy5ib3R0b21SYWRpdXMiLCBib3R0b21SYWRpdXMpOwogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoIm9wdGlvbnMuc2xpY2VzIiwgc2xpY2VzLCAzKTsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGUpICYmIG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlID09PSBHZW9tZXRyeU9mZnNldEF0dHJpYnV0ZV9kZWZhdWx0LlRPUCkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAiR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGUuVE9QIGlzIG5vdCBhIHN1cHBvcnRlZCBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSBmb3IgdGhpcyBnZW9tZXRyeS4iCiAgICAgICk7CiAgICB9CiAgICB0aGlzLl9sZW5ndGggPSBsZW5ndGg7CiAgICB0aGlzLl90b3BSYWRpdXMgPSB0b3BSYWRpdXM7CiAgICB0aGlzLl9ib3R0b21SYWRpdXMgPSBib3R0b21SYWRpdXM7CiAgICB0aGlzLl9zbGljZXMgPSBzbGljZXM7CiAgICB0aGlzLl9udW1iZXJPZlZlcnRpY2FsTGluZXMgPSBudW1iZXJPZlZlcnRpY2FsTGluZXM7CiAgICB0aGlzLl9vZmZzZXRBdHRyaWJ1dGUgPSBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZTsKICAgIHRoaXMuX3dvcmtlck5hbWUgPSAiY3JlYXRlQ3lsaW5kZXJPdXRsaW5lR2VvbWV0cnkiOwogIH0KICB2YXIgcmFkaXVzU2NyYXRjaDIsIHNjcmF0Y2hPcHRpb25zMTIsIEN5bGluZGVyT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfQ3lsaW5kZXJPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0N5bGluZGVyT3V0bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X0N5bGluZGVyR2VvbWV0cnlMaWJyYXJ5KCk7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfR2VvbWV0cnkoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlcygpOwogICAgICBpbml0X0dlb21ldHJ5T2Zmc2V0QXR0cmlidXRlKCk7CiAgICAgIGluaXRfSW5kZXhEYXRhdHlwZSgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgcmFkaXVzU2NyYXRjaDIgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIEN5bGluZGVyT3V0bGluZUdlb21ldHJ5LnBhY2tlZExlbmd0aCA9IDY7CiAgICAgIEN5bGluZGVyT3V0bGluZUdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2xlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX3RvcFJhZGl1czsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2JvdHRvbVJhZGl1czsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX3NsaWNlczsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX251bWJlck9mVmVydGljYWxMaW5lczsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLl9vZmZzZXRBdHRyaWJ1dGUgPz8gLTE7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBzY3JhdGNoT3B0aW9uczEyID0gewogICAgICAgIGxlbmd0aDogdm9pZCAwLAogICAgICAgIHRvcFJhZGl1czogdm9pZCAwLAogICAgICAgIGJvdHRvbVJhZGl1czogdm9pZCAwLAogICAgICAgIHNsaWNlczogdm9pZCAwLAogICAgICAgIG51bWJlck9mVmVydGljYWxMaW5lczogdm9pZCAwLAogICAgICAgIG9mZnNldEF0dHJpYnV0ZTogdm9pZCAwCiAgICAgIH07CiAgICAgIEN5bGluZGVyT3V0bGluZUdlb21ldHJ5LnVucGFjayA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydGluZ0luZGV4LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCB0b3BSYWRpdXMgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IGJvdHRvbVJhZGl1cyA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3Qgc2xpY2VzID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBudW1iZXJPZlZlcnRpY2FsTGluZXMgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IG9mZnNldEF0dHJpYnV0ZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTIubGVuZ3RoID0gbGVuZ3RoOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxMi50b3BSYWRpdXMgPSB0b3BSYWRpdXM7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczEyLmJvdHRvbVJhZGl1cyA9IGJvdHRvbVJhZGl1czsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTIuc2xpY2VzID0gc2xpY2VzOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxMi5udW1iZXJPZlZlcnRpY2FsTGluZXMgPSBudW1iZXJPZlZlcnRpY2FsTGluZXM7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczEyLm9mZnNldEF0dHJpYnV0ZSA9IG9mZnNldEF0dHJpYnV0ZSA9PT0gLTEgPyB2b2lkIDAgOiBvZmZzZXRBdHRyaWJ1dGU7CiAgICAgICAgICByZXR1cm4gbmV3IEN5bGluZGVyT3V0bGluZUdlb21ldHJ5KHNjcmF0Y2hPcHRpb25zMTIpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuX2xlbmd0aCA9IGxlbmd0aDsKICAgICAgICByZXN1bHQuX3RvcFJhZGl1cyA9IHRvcFJhZGl1czsKICAgICAgICByZXN1bHQuX2JvdHRvbVJhZGl1cyA9IGJvdHRvbVJhZGl1czsKICAgICAgICByZXN1bHQuX3NsaWNlcyA9IHNsaWNlczsKICAgICAgICByZXN1bHQuX251bWJlck9mVmVydGljYWxMaW5lcyA9IG51bWJlck9mVmVydGljYWxMaW5lczsKICAgICAgICByZXN1bHQuX29mZnNldEF0dHJpYnV0ZSA9IG9mZnNldEF0dHJpYnV0ZSA9PT0gLTEgPyB2b2lkIDAgOiBvZmZzZXRBdHRyaWJ1dGU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ3lsaW5kZXJPdXRsaW5lR2VvbWV0cnkuY3JlYXRlR2VvbWV0cnkgPSBmdW5jdGlvbihjeWxpbmRlckdlb21ldHJ5KSB7CiAgICAgICAgbGV0IGxlbmd0aCA9IGN5bGluZGVyR2VvbWV0cnkuX2xlbmd0aDsKICAgICAgICBjb25zdCB0b3BSYWRpdXMgPSBjeWxpbmRlckdlb21ldHJ5Ll90b3BSYWRpdXM7CiAgICAgICAgY29uc3QgYm90dG9tUmFkaXVzID0gY3lsaW5kZXJHZW9tZXRyeS5fYm90dG9tUmFkaXVzOwogICAgICAgIGNvbnN0IHNsaWNlcyA9IGN5bGluZGVyR2VvbWV0cnkuX3NsaWNlczsKICAgICAgICBjb25zdCBudW1iZXJPZlZlcnRpY2FsTGluZXMgPSBjeWxpbmRlckdlb21ldHJ5Ll9udW1iZXJPZlZlcnRpY2FsTGluZXM7CiAgICAgICAgaWYgKGxlbmd0aCA8PSAwIHx8IHRvcFJhZGl1cyA8IDAgfHwgYm90dG9tUmFkaXVzIDwgMCB8fCB0b3BSYWRpdXMgPT09IDAgJiYgYm90dG9tUmFkaXVzID09PSAwKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IG51bVZlcnRpY2VzID0gc2xpY2VzICogMjsKICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBDeWxpbmRlckdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVQb3NpdGlvbnMoCiAgICAgICAgICBsZW5ndGgsCiAgICAgICAgICB0b3BSYWRpdXMsCiAgICAgICAgICBib3R0b21SYWRpdXMsCiAgICAgICAgICBzbGljZXMsCiAgICAgICAgICBmYWxzZQogICAgICAgICk7CiAgICAgICAgbGV0IG51bUluZGljZXMgPSBzbGljZXMgKiAyOwogICAgICAgIGxldCBudW1TaWRlOwogICAgICAgIGlmIChudW1iZXJPZlZlcnRpY2FsTGluZXMgPiAwKSB7CiAgICAgICAgICBjb25zdCBudW1TaWRlTGluZXMgPSBNYXRoLm1pbihudW1iZXJPZlZlcnRpY2FsTGluZXMsIHNsaWNlcyk7CiAgICAgICAgICBudW1TaWRlID0gTWF0aC5yb3VuZChzbGljZXMgLyBudW1TaWRlTGluZXMpOwogICAgICAgICAgbnVtSW5kaWNlcyArPSBudW1TaWRlTGluZXM7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheShudW1WZXJ0aWNlcywgbnVtSW5kaWNlcyAqIDIpOwogICAgICAgIGxldCBpbmRleCA9IDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHNsaWNlcyAtIDE7IGkrKykgewogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGk7CiAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gaSArIDE7CiAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gaSArIHNsaWNlczsKICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpICsgMSArIHNsaWNlczsKICAgICAgICB9CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHNsaWNlcyAtIDE7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IDA7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHNsaWNlcyArIHNsaWNlcyAtIDE7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHNsaWNlczsKICAgICAgICBpZiAobnVtYmVyT2ZWZXJ0aWNhbExpbmVzID4gMCkgewogICAgICAgICAgZm9yIChpID0gMDsgaSA8IHNsaWNlczsgaSArPSBudW1TaWRlKSB7CiAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpOwogICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gaSArIHNsaWNlczsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZXNfZGVmYXVsdCgpOwogICAgICAgIGF0dHJpYnV0ZXMucG9zaXRpb24gPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgdmFsdWVzOiBwb3NpdGlvbnMKICAgICAgICB9KTsKICAgICAgICByYWRpdXNTY3JhdGNoMi54ID0gbGVuZ3RoICogMC41OwogICAgICAgIHJhZGl1c1NjcmF0Y2gyLnkgPSBNYXRoLm1heChib3R0b21SYWRpdXMsIHRvcFJhZGl1cyk7CiAgICAgICAgY29uc3QgYm91bmRpbmdTcGhlcmUgPSBuZXcgQm91bmRpbmdTcGhlcmVfZGVmYXVsdCgKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLAogICAgICAgICAgQ2FydGVzaWFuMl9kZWZhdWx0Lm1hZ25pdHVkZShyYWRpdXNTY3JhdGNoMikKICAgICAgICApOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoY3lsaW5kZXJHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlKSkgewogICAgICAgICAgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICAgIGNvbnN0IG9mZnNldFZhbHVlID0gY3lsaW5kZXJHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlID09PSBHZW9tZXRyeU9mZnNldEF0dHJpYnV0ZV9kZWZhdWx0Lk5PTkUgPyAwIDogMTsKICAgICAgICAgIGNvbnN0IGFwcGx5T2Zmc2V0ID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoIC8gMykuZmlsbChvZmZzZXRWYWx1ZSk7CiAgICAgICAgICBhdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9CWVRFLAogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAxLAogICAgICAgICAgICB2YWx1ZXM6IGFwcGx5T2Zmc2V0CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgICAgIGF0dHJpYnV0ZXMsCiAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LkxJTkVTLAogICAgICAgICAgYm91bmRpbmdTcGhlcmUsCiAgICAgICAgICBvZmZzZXRBdHRyaWJ1dGU6IGN5bGluZGVyR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZQogICAgICAgIH0pOwogICAgICB9OwogICAgICBDeWxpbmRlck91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gQ3lsaW5kZXJPdXRsaW5lR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVDeWxpbmRlck91dGxpbmVHZW9tZXRyeS5qcwogIHZhciBjcmVhdGVDeWxpbmRlck91dGxpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlQ3lsaW5kZXJPdXRsaW5lR2VvbWV0cnlfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlQ3lsaW5kZXJPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZUN5bGluZGVyT3V0bGluZUdlb21ldHJ5KGN5bGluZGVyR2VvbWV0cnksIG9mZnNldCkgewogICAgaWYgKGRlZmluZWRfZGVmYXVsdChvZmZzZXQpKSB7CiAgICAgIGN5bGluZGVyR2VvbWV0cnkgPSBDeWxpbmRlck91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjayhjeWxpbmRlckdlb21ldHJ5LCBvZmZzZXQpOwogICAgfQogICAgcmV0dXJuIEN5bGluZGVyT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkoY3lsaW5kZXJHZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVDeWxpbmRlck91dGxpbmVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X2NyZWF0ZUN5bGluZGVyT3V0bGluZUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVDeWxpbmRlck91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQ3lsaW5kZXJPdXRsaW5lR2VvbWV0cnkoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGNyZWF0ZUN5bGluZGVyT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQgPSBjcmVhdGVDeWxpbmRlck91dGxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUVsbGlwc2VHZW9tZXRyeS5qcwogIHZhciBjcmVhdGVFbGxpcHNlR2VvbWV0cnlfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZUVsbGlwc2VHZW9tZXRyeV9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVFbGxpcHNlR2VvbWV0cnlfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZUVsbGlwc2VHZW9tZXRyeShlbGxpcHNlR2VvbWV0cnksIG9mZnNldCkgewogICAgaWYgKGRlZmluZWRfZGVmYXVsdChvZmZzZXQpKSB7CiAgICAgIGVsbGlwc2VHZW9tZXRyeSA9IEVsbGlwc2VHZW9tZXRyeV9kZWZhdWx0LnVucGFjayhlbGxpcHNlR2VvbWV0cnksIG9mZnNldCk7CiAgICB9CiAgICBlbGxpcHNlR2VvbWV0cnkuX2NlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShlbGxpcHNlR2VvbWV0cnkuX2NlbnRlcik7CiAgICBlbGxpcHNlR2VvbWV0cnkuX2VsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKGVsbGlwc2VHZW9tZXRyeS5fZWxsaXBzb2lkKTsKICAgIHJldHVybiBFbGxpcHNlR2VvbWV0cnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeShlbGxpcHNlR2VvbWV0cnkpOwogIH0KICB2YXIgY3JlYXRlRWxsaXBzZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlRWxsaXBzZUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVFbGxpcHNlR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzZUdlb21ldHJ5KCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGNyZWF0ZUVsbGlwc2VHZW9tZXRyeV9kZWZhdWx0ID0gY3JlYXRlRWxsaXBzZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlRWxsaXBzZU91dGxpbmVHZW9tZXRyeS5qcwogIHZhciBjcmVhdGVFbGxpcHNlT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChjcmVhdGVFbGxpcHNlT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZUVsbGlwc2VPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZUVsbGlwc2VPdXRsaW5lR2VvbWV0cnkoZWxsaXBzZUdlb21ldHJ5LCBvZmZzZXQpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob2Zmc2V0KSkgewogICAgICBlbGxpcHNlR2VvbWV0cnkgPSBFbGxpcHNlT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQudW5wYWNrKGVsbGlwc2VHZW9tZXRyeSwgb2Zmc2V0KTsKICAgIH0KICAgIGVsbGlwc2VHZW9tZXRyeS5fY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGVsbGlwc2VHZW9tZXRyeS5fY2VudGVyKTsKICAgIGVsbGlwc2VHZW9tZXRyeS5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoZWxsaXBzZUdlb21ldHJ5Ll9lbGxpcHNvaWQpOwogICAgcmV0dXJuIEVsbGlwc2VPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeShlbGxpcHNlR2VvbWV0cnkpOwogIH0KICB2YXIgY3JlYXRlRWxsaXBzZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X2NyZWF0ZUVsbGlwc2VPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUVsbGlwc2VPdXRsaW5lR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzZU91dGxpbmVHZW9tZXRyeSgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBjcmVhdGVFbGxpcHNlT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQgPSBjcmVhdGVFbGxpcHNlT3V0bGluZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvRWxsaXBzb2lkR2VvbWV0cnkuanMKICBmdW5jdGlvbiBFbGxpcHNvaWRHZW9tZXRyeShvcHRpb25zKSB7CiAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICBjb25zdCByYWRpaSA9IG9wdGlvbnMucmFkaWkgPz8gZGVmYXVsdFJhZGlpOwogICAgY29uc3QgaW5uZXJSYWRpaSA9IG9wdGlvbnMuaW5uZXJSYWRpaSA/PyByYWRpaTsKICAgIGNvbnN0IG1pbmltdW1DbG9jayA9IG9wdGlvbnMubWluaW11bUNsb2NrID8/IDA7CiAgICBjb25zdCBtYXhpbXVtQ2xvY2sgPSBvcHRpb25zLm1heGltdW1DbG9jayA/PyBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgY29uc3QgbWluaW11bUNvbmUgPSBvcHRpb25zLm1pbmltdW1Db25lID8/IDA7CiAgICBjb25zdCBtYXhpbXVtQ29uZSA9IG9wdGlvbnMubWF4aW11bUNvbmUgPz8gTWF0aF9kZWZhdWx0LlBJOwogICAgY29uc3Qgc3RhY2tQYXJ0aXRpb25zID0gTWF0aC5yb3VuZChvcHRpb25zLnN0YWNrUGFydGl0aW9ucyA/PyA2NCk7CiAgICBjb25zdCBzbGljZVBhcnRpdGlvbnMgPSBNYXRoLnJvdW5kKG9wdGlvbnMuc2xpY2VQYXJ0aXRpb25zID8/IDY0KTsKICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IG9wdGlvbnMudmVydGV4Rm9ybWF0ID8/IFZlcnRleEZvcm1hdF9kZWZhdWx0LkRFRkFVTFQ7CiAgICBpZiAoc2xpY2VQYXJ0aXRpb25zIDwgMykgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAib3B0aW9ucy5zbGljZVBhcnRpdGlvbnMgY2Fubm90IGJlIGxlc3MgdGhhbiB0aHJlZS4iCiAgICAgICk7CiAgICB9CiAgICBpZiAoc3RhY2tQYXJ0aXRpb25zIDwgMykgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAib3B0aW9ucy5zdGFja1BhcnRpdGlvbnMgY2Fubm90IGJlIGxlc3MgdGhhbiB0aHJlZS4iCiAgICAgICk7CiAgICB9CiAgICB0aGlzLl9yYWRpaSA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShyYWRpaSk7CiAgICB0aGlzLl9pbm5lclJhZGlpID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGlubmVyUmFkaWkpOwogICAgdGhpcy5fbWluaW11bUNsb2NrID0gbWluaW11bUNsb2NrOwogICAgdGhpcy5fbWF4aW11bUNsb2NrID0gbWF4aW11bUNsb2NrOwogICAgdGhpcy5fbWluaW11bUNvbmUgPSBtaW5pbXVtQ29uZTsKICAgIHRoaXMuX21heGltdW1Db25lID0gbWF4aW11bUNvbmU7CiAgICB0aGlzLl9zdGFja1BhcnRpdGlvbnMgPSBzdGFja1BhcnRpdGlvbnM7CiAgICB0aGlzLl9zbGljZVBhcnRpdGlvbnMgPSBzbGljZVBhcnRpdGlvbnM7CiAgICB0aGlzLl92ZXJ0ZXhGb3JtYXQgPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5jbG9uZSh2ZXJ0ZXhGb3JtYXQpOwogICAgdGhpcy5fb2Zmc2V0QXR0cmlidXRlID0gb3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGU7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZUVsbGlwc29pZEdlb21ldHJ5IjsKICB9CiAgdmFyIHNjcmF0Y2hQb3NpdGlvbjIsIHNjcmF0Y2hOb3JtYWw1LCBzY3JhdGNoVGFuZ2VudDMsIHNjcmF0Y2hCaXRhbmdlbnQzLCBzY3JhdGNoTm9ybWFsU1QsIGRlZmF1bHRSYWRpaSwgY29zLCBzaW4sIHNjcmF0Y2hSYWRpaSwgc2NyYXRjaElubmVyUmFkaWksIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQ2LCBzY3JhdGNoT3B0aW9uczEzLCB1bml0RWxsaXBzb2lkR2VvbWV0cnksIEVsbGlwc29pZEdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfRWxsaXBzb2lkR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0VsbGlwc29pZEdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ29tcG9uZW50RGF0YXR5cGUoKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9HZW9tZXRyeSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGVzKCk7CiAgICAgIGluaXRfR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgaW5pdF9WZXJ0ZXhGb3JtYXQoKTsKICAgICAgc2NyYXRjaFBvc2l0aW9uMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE5vcm1hbDUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hUYW5nZW50MyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEJpdGFuZ2VudDMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hOb3JtYWxTVCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZGVmYXVsdFJhZGlpID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgxLCAxLCAxKTsKICAgICAgY29zID0gTWF0aC5jb3M7CiAgICAgIHNpbiA9IE1hdGguc2luOwogICAgICBFbGxpcHNvaWRHZW9tZXRyeS5wYWNrZWRMZW5ndGggPSAyICogQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCArIFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIDc7CiAgICAgIEVsbGlwc29pZEdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh2YWx1ZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ2YWx1ZSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhcnJheSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhcnJheSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHZhbHVlLl9yYWRpaSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayh2YWx1ZS5faW5uZXJSYWRpaSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrKHZhbHVlLl92ZXJ0ZXhGb3JtYXQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX21pbmltdW1DbG9jazsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX21heGltdW1DbG9jazsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX21pbmltdW1Db25lOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fbWF4aW11bUNvbmU7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9zdGFja1BhcnRpdGlvbnM7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9zbGljZVBhcnRpdGlvbnM7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleF0gPSB2YWx1ZS5fb2Zmc2V0QXR0cmlidXRlID8/IC0xOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgc2NyYXRjaFJhZGlpID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoSW5uZXJSYWRpaSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDYgPSBuZXcgVmVydGV4Rm9ybWF0X2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE9wdGlvbnMxMyA9IHsKICAgICAgICByYWRpaTogc2NyYXRjaFJhZGlpLAogICAgICAgIGlubmVyUmFkaWk6IHNjcmF0Y2hJbm5lclJhZGlpLAogICAgICAgIHZlcnRleEZvcm1hdDogc2NyYXRjaFZlcnRleEZvcm1hdDYsCiAgICAgICAgbWluaW11bUNsb2NrOiB2b2lkIDAsCiAgICAgICAgbWF4aW11bUNsb2NrOiB2b2lkIDAsCiAgICAgICAgbWluaW11bUNvbmU6IHZvaWQgMCwKICAgICAgICBtYXhpbXVtQ29uZTogdm9pZCAwLAogICAgICAgIHN0YWNrUGFydGl0aW9uczogdm9pZCAwLAogICAgICAgIHNsaWNlUGFydGl0aW9uczogdm9pZCAwLAogICAgICAgIG9mZnNldEF0dHJpYnV0ZTogdm9pZCAwCiAgICAgIH07CiAgICAgIEVsbGlwc29pZEdlb21ldHJ5LnVucGFjayA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydGluZ0luZGV4LCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhcnJheSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhcnJheSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGNvbnN0IHJhZGlpID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCwgc2NyYXRjaFJhZGlpKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgaW5uZXJSYWRpaSA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHNjcmF0Y2hJbm5lclJhZGlpKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgYXJyYXksCiAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDYKICAgICAgICApOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IG1pbmltdW1DbG9jayA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgbWF4aW11bUNsb2NrID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBtaW5pbXVtQ29uZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgbWF4aW11bUNvbmUgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHN0YWNrUGFydGl0aW9ucyA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3Qgc2xpY2VQYXJ0aXRpb25zID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBvZmZzZXRBdHRyaWJ1dGUgPSBhcnJheVtzdGFydGluZ0luZGV4XTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczEzLm1pbmltdW1DbG9jayA9IG1pbmltdW1DbG9jazsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTMubWF4aW11bUNsb2NrID0gbWF4aW11bUNsb2NrOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxMy5taW5pbXVtQ29uZSA9IG1pbmltdW1Db25lOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxMy5tYXhpbXVtQ29uZSA9IG1heGltdW1Db25lOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxMy5zdGFja1BhcnRpdGlvbnMgPSBzdGFja1BhcnRpdGlvbnM7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczEzLnNsaWNlUGFydGl0aW9ucyA9IHNsaWNlUGFydGl0aW9uczsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTMub2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlID09PSAtMSA/IHZvaWQgMCA6IG9mZnNldEF0dHJpYnV0ZTsKICAgICAgICAgIHJldHVybiBuZXcgRWxsaXBzb2lkR2VvbWV0cnkoc2NyYXRjaE9wdGlvbnMxMyk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5fcmFkaWkgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocmFkaWksIHJlc3VsdC5fcmFkaWkpOwogICAgICAgIHJlc3VsdC5faW5uZXJSYWRpaSA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShpbm5lclJhZGlpLCByZXN1bHQuX2lubmVyUmFkaWkpOwogICAgICAgIHJlc3VsdC5fdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQuY2xvbmUodmVydGV4Rm9ybWF0LCByZXN1bHQuX3ZlcnRleEZvcm1hdCk7CiAgICAgICAgcmVzdWx0Ll9taW5pbXVtQ2xvY2sgPSBtaW5pbXVtQ2xvY2s7CiAgICAgICAgcmVzdWx0Ll9tYXhpbXVtQ2xvY2sgPSBtYXhpbXVtQ2xvY2s7CiAgICAgICAgcmVzdWx0Ll9taW5pbXVtQ29uZSA9IG1pbmltdW1Db25lOwogICAgICAgIHJlc3VsdC5fbWF4aW11bUNvbmUgPSBtYXhpbXVtQ29uZTsKICAgICAgICByZXN1bHQuX3N0YWNrUGFydGl0aW9ucyA9IHN0YWNrUGFydGl0aW9uczsKICAgICAgICByZXN1bHQuX3NsaWNlUGFydGl0aW9ucyA9IHNsaWNlUGFydGl0aW9uczsKICAgICAgICByZXN1bHQuX29mZnNldEF0dHJpYnV0ZSA9IG9mZnNldEF0dHJpYnV0ZSA9PT0gLTEgPyB2b2lkIDAgOiBvZmZzZXRBdHRyaWJ1dGU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkR2VvbWV0cnkuY3JlYXRlR2VvbWV0cnkgPSBmdW5jdGlvbihlbGxpcHNvaWRHZW9tZXRyeSkgewogICAgICAgIGNvbnN0IHJhZGlpID0gZWxsaXBzb2lkR2VvbWV0cnkuX3JhZGlpOwogICAgICAgIGlmIChyYWRpaS54IDw9IDAgfHwgcmFkaWkueSA8PSAwIHx8IHJhZGlpLnogPD0gMCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBjb25zdCBpbm5lclJhZGlpID0gZWxsaXBzb2lkR2VvbWV0cnkuX2lubmVyUmFkaWk7CiAgICAgICAgaWYgKGlubmVyUmFkaWkueCA8PSAwIHx8IGlubmVyUmFkaWkueSA8PSAwIHx8IGlubmVyUmFkaWkueiA8PSAwKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IG1pbmltdW1DbG9jayA9IGVsbGlwc29pZEdlb21ldHJ5Ll9taW5pbXVtQ2xvY2s7CiAgICAgICAgY29uc3QgbWF4aW11bUNsb2NrID0gZWxsaXBzb2lkR2VvbWV0cnkuX21heGltdW1DbG9jazsKICAgICAgICBjb25zdCBtaW5pbXVtQ29uZSA9IGVsbGlwc29pZEdlb21ldHJ5Ll9taW5pbXVtQ29uZTsKICAgICAgICBjb25zdCBtYXhpbXVtQ29uZSA9IGVsbGlwc29pZEdlb21ldHJ5Ll9tYXhpbXVtQ29uZTsKICAgICAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBlbGxpcHNvaWRHZW9tZXRyeS5fdmVydGV4Rm9ybWF0OwogICAgICAgIGxldCBzbGljZVBhcnRpdGlvbnMgPSBlbGxpcHNvaWRHZW9tZXRyeS5fc2xpY2VQYXJ0aXRpb25zICsgMTsKICAgICAgICBsZXQgc3RhY2tQYXJ0aXRpb25zID0gZWxsaXBzb2lkR2VvbWV0cnkuX3N0YWNrUGFydGl0aW9ucyArIDE7CiAgICAgICAgc2xpY2VQYXJ0aXRpb25zID0gTWF0aC5yb3VuZCgKICAgICAgICAgIHNsaWNlUGFydGl0aW9ucyAqIE1hdGguYWJzKG1heGltdW1DbG9jayAtIG1pbmltdW1DbG9jaykgLyBNYXRoX2RlZmF1bHQuVFdPX1BJCiAgICAgICAgKTsKICAgICAgICBzdGFja1BhcnRpdGlvbnMgPSBNYXRoLnJvdW5kKAogICAgICAgICAgc3RhY2tQYXJ0aXRpb25zICogTWF0aC5hYnMobWF4aW11bUNvbmUgLSBtaW5pbXVtQ29uZSkgLyBNYXRoX2RlZmF1bHQuUEkKICAgICAgICApOwogICAgICAgIGlmIChzbGljZVBhcnRpdGlvbnMgPCAyKSB7CiAgICAgICAgICBzbGljZVBhcnRpdGlvbnMgPSAyOwogICAgICAgIH0KICAgICAgICBpZiAoc3RhY2tQYXJ0aXRpb25zIDwgMikgewogICAgICAgICAgc3RhY2tQYXJ0aXRpb25zID0gMjsKICAgICAgICB9CiAgICAgICAgbGV0IGk7CiAgICAgICAgbGV0IGo7CiAgICAgICAgbGV0IGluZGV4ID0gMDsKICAgICAgICBjb25zdCBwaGlzID0gW21pbmltdW1Db25lXTsKICAgICAgICBjb25zdCB0aGV0YXMgPSBbbWluaW11bUNsb2NrXTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc3RhY2tQYXJ0aXRpb25zOyBpKyspIHsKICAgICAgICAgIHBoaXMucHVzaCgKICAgICAgICAgICAgbWluaW11bUNvbmUgKyBpICogKG1heGltdW1Db25lIC0gbWluaW11bUNvbmUpIC8gKHN0YWNrUGFydGl0aW9ucyAtIDEpCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBwaGlzLnB1c2gobWF4aW11bUNvbmUpOwogICAgICAgIGZvciAoaiA9IDA7IGogPCBzbGljZVBhcnRpdGlvbnM7IGorKykgewogICAgICAgICAgdGhldGFzLnB1c2goCiAgICAgICAgICAgIG1pbmltdW1DbG9jayArIGogKiAobWF4aW11bUNsb2NrIC0gbWluaW11bUNsb2NrKSAvIChzbGljZVBhcnRpdGlvbnMgLSAxKQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgdGhldGFzLnB1c2gobWF4aW11bUNsb2NrKTsKICAgICAgICBjb25zdCBudW1QaGlzID0gcGhpcy5sZW5ndGg7CiAgICAgICAgY29uc3QgbnVtVGhldGFzID0gdGhldGFzLmxlbmd0aDsKICAgICAgICBsZXQgZXh0cmFJbmRpY2VzID0gMDsKICAgICAgICBsZXQgdmVydGV4TXVsdGlwbGllciA9IDE7CiAgICAgICAgY29uc3QgaGFzSW5uZXJTdXJmYWNlID0gaW5uZXJSYWRpaS54ICE9PSByYWRpaS54IHx8IGlubmVyUmFkaWkueSAhPT0gcmFkaWkueSB8fCBpbm5lclJhZGlpLnogIT09IHJhZGlpLno7CiAgICAgICAgbGV0IGlzVG9wT3BlbiA9IGZhbHNlOwogICAgICAgIGxldCBpc0JvdE9wZW4gPSBmYWxzZTsKICAgICAgICBsZXQgaXNDbG9ja09wZW4gPSBmYWxzZTsKICAgICAgICBpZiAoaGFzSW5uZXJTdXJmYWNlKSB7CiAgICAgICAgICB2ZXJ0ZXhNdWx0aXBsaWVyID0gMjsKICAgICAgICAgIGlmIChtaW5pbXVtQ29uZSA+IDApIHsKICAgICAgICAgICAgaXNUb3BPcGVuID0gdHJ1ZTsKICAgICAgICAgICAgZXh0cmFJbmRpY2VzICs9IHNsaWNlUGFydGl0aW9ucyAtIDE7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobWF4aW11bUNvbmUgPCBNYXRoLlBJKSB7CiAgICAgICAgICAgIGlzQm90T3BlbiA9IHRydWU7CiAgICAgICAgICAgIGV4dHJhSW5kaWNlcyArPSBzbGljZVBhcnRpdGlvbnMgLSAxOwogICAgICAgICAgfQogICAgICAgICAgaWYgKChtYXhpbXVtQ2xvY2sgLSBtaW5pbXVtQ2xvY2spICUgTWF0aF9kZWZhdWx0LlRXT19QSSkgewogICAgICAgICAgICBpc0Nsb2NrT3BlbiA9IHRydWU7CiAgICAgICAgICAgIGV4dHJhSW5kaWNlcyArPSAoc3RhY2tQYXJ0aXRpb25zIC0gMSkgKiAyICsgMTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGV4dHJhSW5kaWNlcyArPSAxOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCB2ZXJ0ZXhDb3VudCA9IG51bVRoZXRhcyAqIG51bVBoaXMgKiB2ZXJ0ZXhNdWx0aXBsaWVyOwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkodmVydGV4Q291bnQgKiAzKTsKICAgICAgICBjb25zdCBpc0lubmVyID0gbmV3IEFycmF5KHZlcnRleENvdW50KS5maWxsKGZhbHNlKTsKICAgICAgICBjb25zdCBuZWdhdGVOb3JtYWwgPSBuZXcgQXJyYXkodmVydGV4Q291bnQpLmZpbGwoZmFsc2UpOwogICAgICAgIGNvbnN0IGluZGV4Q291bnQgPSBzbGljZVBhcnRpdGlvbnMgKiBzdGFja1BhcnRpdGlvbnMgKiB2ZXJ0ZXhNdWx0aXBsaWVyOwogICAgICAgIGNvbnN0IG51bUluZGljZXMgPSA2ICogKGluZGV4Q291bnQgKyBleHRyYUluZGljZXMgKyAxIC0gKHNsaWNlUGFydGl0aW9ucyArIHN0YWNrUGFydGl0aW9ucykgKiB2ZXJ0ZXhNdWx0aXBsaWVyKTsKICAgICAgICBjb25zdCBpbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoaW5kZXhDb3VudCwgbnVtSW5kaWNlcyk7CiAgICAgICAgY29uc3Qgbm9ybWFscyA9IHZlcnRleEZvcm1hdC5ub3JtYWwgPyBuZXcgRmxvYXQzMkFycmF5KHZlcnRleENvdW50ICogMykgOiB2b2lkIDA7CiAgICAgICAgY29uc3QgdGFuZ2VudHMgPSB2ZXJ0ZXhGb3JtYXQudGFuZ2VudCA/IG5ldyBGbG9hdDMyQXJyYXkodmVydGV4Q291bnQgKiAzKSA6IHZvaWQgMDsKICAgICAgICBjb25zdCBiaXRhbmdlbnRzID0gdmVydGV4Rm9ybWF0LmJpdGFuZ2VudCA/IG5ldyBGbG9hdDMyQXJyYXkodmVydGV4Q291bnQgKiAzKSA6IHZvaWQgMDsKICAgICAgICBjb25zdCBzdCA9IHZlcnRleEZvcm1hdC5zdCA/IG5ldyBGbG9hdDMyQXJyYXkodmVydGV4Q291bnQgKiAyKSA6IHZvaWQgMDsKICAgICAgICBjb25zdCBzaW5QaGkgPSBuZXcgQXJyYXkobnVtUGhpcyk7CiAgICAgICAgY29uc3QgY29zUGhpID0gbmV3IEFycmF5KG51bVBoaXMpOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1QaGlzOyBpKyspIHsKICAgICAgICAgIHNpblBoaVtpXSA9IHNpbihwaGlzW2ldKTsKICAgICAgICAgIGNvc1BoaVtpXSA9IGNvcyhwaGlzW2ldKTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc2luVGhldGEgPSBuZXcgQXJyYXkobnVtVGhldGFzKTsKICAgICAgICBjb25zdCBjb3NUaGV0YSA9IG5ldyBBcnJheShudW1UaGV0YXMpOwogICAgICAgIGZvciAoaiA9IDA7IGogPCBudW1UaGV0YXM7IGorKykgewogICAgICAgICAgY29zVGhldGFbal0gPSBjb3ModGhldGFzW2pdKTsKICAgICAgICAgIHNpblRoZXRhW2pdID0gc2luKHRoZXRhc1tqXSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1QaGlzOyBpKyspIHsKICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBudW1UaGV0YXM7IGorKykgewogICAgICAgICAgICBwb3NpdGlvbnNbaW5kZXgrK10gPSByYWRpaS54ICogc2luUGhpW2ldICogY29zVGhldGFbal07CiAgICAgICAgICAgIHBvc2l0aW9uc1tpbmRleCsrXSA9IHJhZGlpLnkgKiBzaW5QaGlbaV0gKiBzaW5UaGV0YVtqXTsKICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gcmFkaWkueiAqIGNvc1BoaVtpXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbGV0IHZlcnRleEluZGV4ID0gdmVydGV4Q291bnQgLyAyOwogICAgICAgIGlmIChoYXNJbm5lclN1cmZhY2UpIHsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1QaGlzOyBpKyspIHsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IG51bVRoZXRhczsgaisrKSB7CiAgICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gaW5uZXJSYWRpaS54ICogc2luUGhpW2ldICogY29zVGhldGFbal07CiAgICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gaW5uZXJSYWRpaS55ICogc2luUGhpW2ldICogc2luVGhldGFbal07CiAgICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gaW5uZXJSYWRpaS56ICogY29zUGhpW2ldOwogICAgICAgICAgICAgIGlzSW5uZXJbdmVydGV4SW5kZXhdID0gdHJ1ZTsKICAgICAgICAgICAgICBpZiAoaSA+IDAgJiYgaSAhPT0gbnVtUGhpcyAtIDEgJiYgaiAhPT0gMCAmJiBqICE9PSBudW1UaGV0YXMgLSAxKSB7CiAgICAgICAgICAgICAgICBuZWdhdGVOb3JtYWxbdmVydGV4SW5kZXhdID0gdHJ1ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmVydGV4SW5kZXgrKzsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpbmRleCA9IDA7CiAgICAgICAgbGV0IHRvcE9mZnNldDsKICAgICAgICBsZXQgYm90dG9tT2Zmc2V0OwogICAgICAgIGZvciAoaSA9IDE7IGkgPCBudW1QaGlzIC0gMjsgaSsrKSB7CiAgICAgICAgICB0b3BPZmZzZXQgPSBpICogbnVtVGhldGFzOwogICAgICAgICAgYm90dG9tT2Zmc2V0ID0gKGkgKyAxKSAqIG51bVRoZXRhczsKICAgICAgICAgIGZvciAoaiA9IDE7IGogPCBudW1UaGV0YXMgLSAyOyBqKyspIHsKICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGJvdHRvbU9mZnNldCArIGo7CiAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBib3R0b21PZmZzZXQgKyBqICsgMTsKICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHRvcE9mZnNldCArIGogKyAxOwogICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gYm90dG9tT2Zmc2V0ICsgajsKICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHRvcE9mZnNldCArIGogKyAxOwogICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gdG9wT2Zmc2V0ICsgajsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGhhc0lubmVyU3VyZmFjZSkgewogICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gbnVtUGhpcyAqIG51bVRoZXRhczsKICAgICAgICAgIGZvciAoaSA9IDE7IGkgPCBudW1QaGlzIC0gMjsgaSsrKSB7CiAgICAgICAgICAgIHRvcE9mZnNldCA9IG9mZnNldCArIGkgKiBudW1UaGV0YXM7CiAgICAgICAgICAgIGJvdHRvbU9mZnNldCA9IG9mZnNldCArIChpICsgMSkgKiBudW1UaGV0YXM7CiAgICAgICAgICAgIGZvciAoaiA9IDE7IGogPCBudW1UaGV0YXMgLSAyOyBqKyspIHsKICAgICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gYm90dG9tT2Zmc2V0ICsgajsKICAgICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gdG9wT2Zmc2V0ICsgajsKICAgICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gdG9wT2Zmc2V0ICsgaiArIDE7CiAgICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGJvdHRvbU9mZnNldCArIGo7CiAgICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHRvcE9mZnNldCArIGogKyAxOwogICAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBib3R0b21PZmZzZXQgKyBqICsgMTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBsZXQgb3V0ZXJPZmZzZXQ7CiAgICAgICAgbGV0IGlubmVyT2Zmc2V0OwogICAgICAgIGlmIChoYXNJbm5lclN1cmZhY2UpIHsKICAgICAgICAgIGlmIChpc1RvcE9wZW4pIHsKICAgICAgICAgICAgaW5uZXJPZmZzZXQgPSBudW1QaGlzICogbnVtVGhldGFzOwogICAgICAgICAgICBmb3IgKGkgPSAxOyBpIDwgbnVtVGhldGFzIC0gMjsgaSsrKSB7CiAgICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGk7CiAgICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGkgKyAxOwogICAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpbm5lck9mZnNldCArIGkgKyAxOwogICAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpOwogICAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpbm5lck9mZnNldCArIGkgKyAxOwogICAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpbm5lck9mZnNldCArIGk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChpc0JvdE9wZW4pIHsKICAgICAgICAgICAgb3V0ZXJPZmZzZXQgPSBudW1QaGlzICogbnVtVGhldGFzIC0gbnVtVGhldGFzOwogICAgICAgICAgICBpbm5lck9mZnNldCA9IG51bVBoaXMgKiBudW1UaGV0YXMgKiB2ZXJ0ZXhNdWx0aXBsaWVyIC0gbnVtVGhldGFzOwogICAgICAgICAgICBmb3IgKGkgPSAxOyBpIDwgbnVtVGhldGFzIC0gMjsgaSsrKSB7CiAgICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IG91dGVyT2Zmc2V0ICsgaSArIDE7CiAgICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IG91dGVyT2Zmc2V0ICsgaTsKICAgICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gaW5uZXJPZmZzZXQgKyBpOwogICAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBvdXRlck9mZnNldCArIGkgKyAxOwogICAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpbm5lck9mZnNldCArIGk7CiAgICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGlubmVyT2Zmc2V0ICsgaSArIDE7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGlzQ2xvY2tPcGVuKSB7CiAgICAgICAgICBmb3IgKGkgPSAxOyBpIDwgbnVtUGhpcyAtIDI7IGkrKykgewogICAgICAgICAgICBpbm5lck9mZnNldCA9IG51bVRoZXRhcyAqIG51bVBoaXMgKyBudW1UaGV0YXMgKiBpOwogICAgICAgICAgICBvdXRlck9mZnNldCA9IG51bVRoZXRhcyAqIGk7CiAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpbm5lck9mZnNldDsKICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IG91dGVyT2Zmc2V0ICsgbnVtVGhldGFzOwogICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gb3V0ZXJPZmZzZXQ7CiAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpbm5lck9mZnNldDsKICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGlubmVyT2Zmc2V0ICsgbnVtVGhldGFzOwogICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gb3V0ZXJPZmZzZXQgKyBudW1UaGV0YXM7CiAgICAgICAgICB9CiAgICAgICAgICBmb3IgKGkgPSAxOyBpIDwgbnVtUGhpcyAtIDI7IGkrKykgewogICAgICAgICAgICBpbm5lck9mZnNldCA9IG51bVRoZXRhcyAqIG51bVBoaXMgKyBudW1UaGV0YXMgKiAoaSArIDEpIC0gMTsKICAgICAgICAgICAgb3V0ZXJPZmZzZXQgPSBudW1UaGV0YXMgKiAoaSArIDEpIC0gMTsKICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IG91dGVyT2Zmc2V0ICsgbnVtVGhldGFzOwogICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gaW5uZXJPZmZzZXQ7CiAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBvdXRlck9mZnNldDsKICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IG91dGVyT2Zmc2V0ICsgbnVtVGhldGFzOwogICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gaW5uZXJPZmZzZXQgKyBudW1UaGV0YXM7CiAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpbm5lck9mZnNldDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZXNfZGVmYXVsdCgpOwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQucG9zaXRpb24pIHsKICAgICAgICAgIGF0dHJpYnV0ZXMucG9zaXRpb24gPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgdmFsdWVzOiBwb3NpdGlvbnMKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBsZXQgc3RJbmRleCA9IDA7CiAgICAgICAgbGV0IG5vcm1hbEluZGV4ID0gMDsKICAgICAgICBsZXQgdGFuZ2VudEluZGV4ID0gMDsKICAgICAgICBsZXQgYml0YW5nZW50SW5kZXggPSAwOwogICAgICAgIGNvbnN0IHZlcnRleENvdW50SGFsZiA9IHZlcnRleENvdW50IC8gMjsKICAgICAgICBsZXQgZWxsaXBzb2lkOwogICAgICAgIGNvbnN0IGVsbGlwc29pZE91dGVyID0gRWxsaXBzb2lkX2RlZmF1bHQuZnJvbUNhcnRlc2lhbjMocmFkaWkpOwogICAgICAgIGNvbnN0IGVsbGlwc29pZElubmVyID0gRWxsaXBzb2lkX2RlZmF1bHQuZnJvbUNhcnRlc2lhbjMoaW5uZXJSYWRpaSk7CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5zdCB8fCB2ZXJ0ZXhGb3JtYXQubm9ybWFsIHx8IHZlcnRleEZvcm1hdC50YW5nZW50IHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB2ZXJ0ZXhDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGVsbGlwc29pZCA9IGlzSW5uZXJbaV0gPyBlbGxpcHNvaWRJbm5lciA6IGVsbGlwc29pZE91dGVyOwogICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkocG9zaXRpb25zLCBpICogMywgc2NyYXRjaFBvc2l0aW9uMik7CiAgICAgICAgICAgIGNvbnN0IG5vcm1hbDIgPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKHBvc2l0aW9uLCBzY3JhdGNoTm9ybWFsNSk7CiAgICAgICAgICAgIGlmIChuZWdhdGVOb3JtYWxbaV0pIHsKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKG5vcm1hbDIsIG5vcm1hbDIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICAgICAgICBjb25zdCBub3JtYWxTVCA9IENhcnRlc2lhbjJfZGVmYXVsdC5uZWdhdGUobm9ybWFsMiwgc2NyYXRjaE5vcm1hbFNUKTsKICAgICAgICAgICAgICBzdFtzdEluZGV4KytdID0gTWF0aC5hdGFuMihub3JtYWxTVC55LCBub3JtYWxTVC54KSAvIE1hdGhfZGVmYXVsdC5UV09fUEkgKyAwLjU7CiAgICAgICAgICAgICAgc3Rbc3RJbmRleCsrXSA9IE1hdGguYXNpbihub3JtYWwyLnopIC8gTWF0aC5QSSArIDAuNTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICAgICAgICAgIG5vcm1hbHNbbm9ybWFsSW5kZXgrK10gPSBub3JtYWwyLng7CiAgICAgICAgICAgICAgbm9ybWFsc1tub3JtYWxJbmRleCsrXSA9IG5vcm1hbDIueTsKICAgICAgICAgICAgICBub3JtYWxzW25vcm1hbEluZGV4KytdID0gbm9ybWFsMi56OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCB8fCB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgICAgICAgY29uc3QgdGFuZ2VudCA9IHNjcmF0Y2hUYW5nZW50MzsKICAgICAgICAgICAgICBsZXQgdGFuZ2V0T2Zmc2V0ID0gMDsKICAgICAgICAgICAgICBsZXQgdW5pdDsKICAgICAgICAgICAgICBpZiAoaXNJbm5lcltpXSkgewogICAgICAgICAgICAgICAgdGFuZ2V0T2Zmc2V0ID0gdmVydGV4Q291bnRIYWxmOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoIWlzVG9wT3BlbiAmJiBpID49IHRhbmdldE9mZnNldCAmJiBpIDwgdGFuZ2V0T2Zmc2V0ICsgbnVtVGhldGFzICogMikgewogICAgICAgICAgICAgICAgdW5pdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1g7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHVuaXQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9aOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3ModW5pdCwgbm9ybWFsMiwgdGFuZ2VudCk7CiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSh0YW5nZW50LCB0YW5nZW50KTsKICAgICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQpIHsKICAgICAgICAgICAgICAgIHRhbmdlbnRzW3RhbmdlbnRJbmRleCsrXSA9IHRhbmdlbnQueDsKICAgICAgICAgICAgICAgIHRhbmdlbnRzW3RhbmdlbnRJbmRleCsrXSA9IHRhbmdlbnQueTsKICAgICAgICAgICAgICAgIHRhbmdlbnRzW3RhbmdlbnRJbmRleCsrXSA9IHRhbmdlbnQuejsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgICAgICAgIGNvbnN0IGJpdGFuZ2VudCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhub3JtYWwyLCB0YW5nZW50LCBzY3JhdGNoQml0YW5nZW50Myk7CiAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGJpdGFuZ2VudCwgYml0YW5nZW50KTsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQueDsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQueTsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQuejsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICAgICAgYXR0cmlidXRlcy5zdCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAyLAogICAgICAgICAgICAgIHZhbHVlczogc3QKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICAgICAgICBhdHRyaWJ1dGVzLm5vcm1hbCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgICAgIHZhbHVlczogbm9ybWFscwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICAgICAgICBhdHRyaWJ1dGVzLnRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgICB2YWx1ZXM6IHRhbmdlbnRzCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgICAgYXR0cmlidXRlcy5iaXRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgICB2YWx1ZXM6IGJpdGFuZ2VudHMKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZWxsaXBzb2lkR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZSkpIHsKICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgICBjb25zdCBvZmZzZXRWYWx1ZSA9IGVsbGlwc29pZEdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuTk9ORSA/IDAgOiAxOwogICAgICAgICAgY29uc3QgYXBwbHlPZmZzZXQgPSBuZXcgVWludDhBcnJheShsZW5ndGggLyAzKS5maWxsKG9mZnNldFZhbHVlKTsKICAgICAgICAgIGF0dHJpYnV0ZXMuYXBwbHlPZmZzZXQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEUsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDEsCiAgICAgICAgICAgIHZhbHVlczogYXBwbHlPZmZzZXQKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgICAgYXR0cmlidXRlcywKICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBQcmltaXRpdmVUeXBlX2RlZmF1bHQuVFJJQU5HTEVTLAogICAgICAgICAgYm91bmRpbmdTcGhlcmU6IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbUVsbGlwc29pZChlbGxpcHNvaWRPdXRlciksCiAgICAgICAgICBvZmZzZXRBdHRyaWJ1dGU6IGVsbGlwc29pZEdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkR2VvbWV0cnkuZ2V0VW5pdEVsbGlwc29pZCA9IGZ1bmN0aW9uKCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHVuaXRFbGxpcHNvaWRHZW9tZXRyeSkpIHsKICAgICAgICAgIHVuaXRFbGxpcHNvaWRHZW9tZXRyeSA9IEVsbGlwc29pZEdlb21ldHJ5LmNyZWF0ZUdlb21ldHJ5KAogICAgICAgICAgICBuZXcgRWxsaXBzb2lkR2VvbWV0cnkoewogICAgICAgICAgICAgIHJhZGlpOiBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KDEsIDEsIDEpLAogICAgICAgICAgICAgIHZlcnRleEZvcm1hdDogVmVydGV4Rm9ybWF0X2RlZmF1bHQuUE9TSVRJT05fT05MWQogICAgICAgICAgICB9KQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHVuaXRFbGxpcHNvaWRHZW9tZXRyeTsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkR2VvbWV0cnlfZGVmYXVsdCA9IEVsbGlwc29pZEdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlRWxsaXBzb2lkR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlRWxsaXBzb2lkR2VvbWV0cnlfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZUVsbGlwc29pZEdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZUVsbGlwc29pZEdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVFbGxpcHNvaWRHZW9tZXRyeShlbGxpcHNvaWRHZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgZWxsaXBzb2lkR2VvbWV0cnkgPSBFbGxpcHNvaWRHZW9tZXRyeV9kZWZhdWx0LnVucGFjayhlbGxpcHNvaWRHZW9tZXRyeSwgb2Zmc2V0KTsKICAgIH0KICAgIHJldHVybiBFbGxpcHNvaWRHZW9tZXRyeV9kZWZhdWx0LmNyZWF0ZUdlb21ldHJ5KGVsbGlwc29pZEdlb21ldHJ5KTsKICB9CiAgdmFyIGNyZWF0ZUVsbGlwc29pZEdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlRWxsaXBzb2lkR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUVsbGlwc29pZEdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkR2VvbWV0cnkoKTsKICAgICAgY3JlYXRlRWxsaXBzb2lkR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZUVsbGlwc29pZEdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvRWxsaXBzb2lkT3V0bGluZUdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gRWxsaXBzb2lkT3V0bGluZUdlb21ldHJ5KG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIGNvbnN0IHJhZGlpID0gb3B0aW9ucy5yYWRpaSA/PyBkZWZhdWx0UmFkaWkyOwogICAgY29uc3QgaW5uZXJSYWRpaSA9IG9wdGlvbnMuaW5uZXJSYWRpaSA/PyByYWRpaTsKICAgIGNvbnN0IG1pbmltdW1DbG9jayA9IG9wdGlvbnMubWluaW11bUNsb2NrID8/IDA7CiAgICBjb25zdCBtYXhpbXVtQ2xvY2sgPSBvcHRpb25zLm1heGltdW1DbG9jayA/PyBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgY29uc3QgbWluaW11bUNvbmUgPSBvcHRpb25zLm1pbmltdW1Db25lID8/IDA7CiAgICBjb25zdCBtYXhpbXVtQ29uZSA9IG9wdGlvbnMubWF4aW11bUNvbmUgPz8gTWF0aF9kZWZhdWx0LlBJOwogICAgY29uc3Qgc3RhY2tQYXJ0aXRpb25zID0gTWF0aC5yb3VuZChvcHRpb25zLnN0YWNrUGFydGl0aW9ucyA/PyAxMCk7CiAgICBjb25zdCBzbGljZVBhcnRpdGlvbnMgPSBNYXRoLnJvdW5kKG9wdGlvbnMuc2xpY2VQYXJ0aXRpb25zID8/IDgpOwogICAgY29uc3Qgc3ViZGl2aXNpb25zID0gTWF0aC5yb3VuZChvcHRpb25zLnN1YmRpdmlzaW9ucyA/PyAxMjgpOwogICAgaWYgKHN0YWNrUGFydGl0aW9ucyA8IDEpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9wdGlvbnMuc3RhY2tQYXJ0aXRpb25zIGNhbm5vdCBiZSBsZXNzIHRoYW4gMSIpOwogICAgfQogICAgaWYgKHNsaWNlUGFydGl0aW9ucyA8IDApIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9wdGlvbnMuc2xpY2VQYXJ0aXRpb25zIGNhbm5vdCBiZSBsZXNzIHRoYW4gMCIpOwogICAgfQogICAgaWYgKHN1YmRpdmlzaW9ucyA8IDApIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgIm9wdGlvbnMuc3ViZGl2aXNpb25zIG11c3QgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHplcm8uIgogICAgICApOwogICAgfQogICAgaWYgKGRlZmluZWRfZGVmYXVsdChvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSkgJiYgb3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuVE9QKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICJHZW9tZXRyeU9mZnNldEF0dHJpYnV0ZS5UT1AgaXMgbm90IGEgc3VwcG9ydGVkIG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlIGZvciB0aGlzIGdlb21ldHJ5LiIKICAgICAgKTsKICAgIH0KICAgIHRoaXMuX3JhZGlpID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHJhZGlpKTsKICAgIHRoaXMuX2lubmVyUmFkaWkgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoaW5uZXJSYWRpaSk7CiAgICB0aGlzLl9taW5pbXVtQ2xvY2sgPSBtaW5pbXVtQ2xvY2s7CiAgICB0aGlzLl9tYXhpbXVtQ2xvY2sgPSBtYXhpbXVtQ2xvY2s7CiAgICB0aGlzLl9taW5pbXVtQ29uZSA9IG1pbmltdW1Db25lOwogICAgdGhpcy5fbWF4aW11bUNvbmUgPSBtYXhpbXVtQ29uZTsKICAgIHRoaXMuX3N0YWNrUGFydGl0aW9ucyA9IHN0YWNrUGFydGl0aW9uczsKICAgIHRoaXMuX3NsaWNlUGFydGl0aW9ucyA9IHNsaWNlUGFydGl0aW9uczsKICAgIHRoaXMuX3N1YmRpdmlzaW9ucyA9IHN1YmRpdmlzaW9uczsKICAgIHRoaXMuX29mZnNldEF0dHJpYnV0ZSA9IG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlOwogICAgdGhpcy5fd29ya2VyTmFtZSA9ICJjcmVhdGVFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnkiOwogIH0KICB2YXIgZGVmYXVsdFJhZGlpMiwgY29zMiwgc2luMiwgc2NyYXRjaFJhZGlpMiwgc2NyYXRjaElubmVyUmFkaWkyLCBzY3JhdGNoT3B0aW9uczE0LCBFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9FbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0VsbGlwc29pZE91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ29tcG9uZW50RGF0YXR5cGUoKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9HZW9tZXRyeSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGVzKCk7CiAgICAgIGluaXRfR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgZGVmYXVsdFJhZGlpMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoMSwgMSwgMSk7CiAgICAgIGNvczIgPSBNYXRoLmNvczsKICAgICAgc2luMiA9IE1hdGguc2luOwogICAgICBFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnkucGFja2VkTGVuZ3RoID0gMiAqIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyA4OwogICAgICBFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHZhbHVlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInZhbHVlIGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFycmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2sodmFsdWUuX3JhZGlpLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHZhbHVlLl9pbm5lclJhZGlpLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fbWluaW11bUNsb2NrOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fbWF4aW11bUNsb2NrOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fbWluaW11bUNvbmU7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9tYXhpbXVtQ29uZTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX3N0YWNrUGFydGl0aW9uczsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX3NsaWNlUGFydGl0aW9uczsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX3N1YmRpdmlzaW9uczsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLl9vZmZzZXRBdHRyaWJ1dGUgPz8gLTE7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBzY3JhdGNoUmFkaWkyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoSW5uZXJSYWRpaTIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hPcHRpb25zMTQgPSB7CiAgICAgICAgcmFkaWk6IHNjcmF0Y2hSYWRpaTIsCiAgICAgICAgaW5uZXJSYWRpaTogc2NyYXRjaElubmVyUmFkaWkyLAogICAgICAgIG1pbmltdW1DbG9jazogdm9pZCAwLAogICAgICAgIG1heGltdW1DbG9jazogdm9pZCAwLAogICAgICAgIG1pbmltdW1Db25lOiB2b2lkIDAsCiAgICAgICAgbWF4aW11bUNvbmU6IHZvaWQgMCwKICAgICAgICBzdGFja1BhcnRpdGlvbnM6IHZvaWQgMCwKICAgICAgICBzbGljZVBhcnRpdGlvbnM6IHZvaWQgMCwKICAgICAgICBzdWJkaXZpc2lvbnM6IHZvaWQgMCwKICAgICAgICBvZmZzZXRBdHRyaWJ1dGU6IHZvaWQgMAogICAgICB9OwogICAgICBFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnkudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFycmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgY29uc3QgcmFkaWkgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoUmFkaWkyKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgaW5uZXJSYWRpaSA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHNjcmF0Y2hJbm5lclJhZGlpMik7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IG1pbmltdW1DbG9jayA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgbWF4aW11bUNsb2NrID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBtaW5pbXVtQ29uZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgbWF4aW11bUNvbmUgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHN0YWNrUGFydGl0aW9ucyA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3Qgc2xpY2VQYXJ0aXRpb25zID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBzdWJkaXZpc2lvbnMgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IG9mZnNldEF0dHJpYnV0ZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTQubWluaW11bUNsb2NrID0gbWluaW11bUNsb2NrOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxNC5tYXhpbXVtQ2xvY2sgPSBtYXhpbXVtQ2xvY2s7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE0Lm1pbmltdW1Db25lID0gbWluaW11bUNvbmU7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE0Lm1heGltdW1Db25lID0gbWF4aW11bUNvbmU7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE0LnN0YWNrUGFydGl0aW9ucyA9IHN0YWNrUGFydGl0aW9uczsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTQuc2xpY2VQYXJ0aXRpb25zID0gc2xpY2VQYXJ0aXRpb25zOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxNC5zdWJkaXZpc2lvbnMgPSBzdWJkaXZpc2lvbnM7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE0Lm9mZnNldEF0dHJpYnV0ZSA9IG9mZnNldEF0dHJpYnV0ZSA9PT0gLTEgPyB2b2lkIDAgOiBvZmZzZXRBdHRyaWJ1dGU7CiAgICAgICAgICByZXR1cm4gbmV3IEVsbGlwc29pZE91dGxpbmVHZW9tZXRyeShzY3JhdGNoT3B0aW9uczE0KTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0Ll9yYWRpaSA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShyYWRpaSwgcmVzdWx0Ll9yYWRpaSk7CiAgICAgICAgcmVzdWx0Ll9pbm5lclJhZGlpID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGlubmVyUmFkaWksIHJlc3VsdC5faW5uZXJSYWRpaSk7CiAgICAgICAgcmVzdWx0Ll9taW5pbXVtQ2xvY2sgPSBtaW5pbXVtQ2xvY2s7CiAgICAgICAgcmVzdWx0Ll9tYXhpbXVtQ2xvY2sgPSBtYXhpbXVtQ2xvY2s7CiAgICAgICAgcmVzdWx0Ll9taW5pbXVtQ29uZSA9IG1pbmltdW1Db25lOwogICAgICAgIHJlc3VsdC5fbWF4aW11bUNvbmUgPSBtYXhpbXVtQ29uZTsKICAgICAgICByZXN1bHQuX3N0YWNrUGFydGl0aW9ucyA9IHN0YWNrUGFydGl0aW9uczsKICAgICAgICByZXN1bHQuX3NsaWNlUGFydGl0aW9ucyA9IHNsaWNlUGFydGl0aW9uczsKICAgICAgICByZXN1bHQuX3N1YmRpdmlzaW9ucyA9IHN1YmRpdmlzaW9uczsKICAgICAgICByZXN1bHQuX29mZnNldEF0dHJpYnV0ZSA9IG9mZnNldEF0dHJpYnV0ZSA9PT0gLTEgPyB2b2lkIDAgOiBvZmZzZXRBdHRyaWJ1dGU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkT3V0bGluZUdlb21ldHJ5LmNyZWF0ZUdlb21ldHJ5ID0gZnVuY3Rpb24oZWxsaXBzb2lkR2VvbWV0cnkpIHsKICAgICAgICBjb25zdCByYWRpaSA9IGVsbGlwc29pZEdlb21ldHJ5Ll9yYWRpaTsKICAgICAgICBpZiAocmFkaWkueCA8PSAwIHx8IHJhZGlpLnkgPD0gMCB8fCByYWRpaS56IDw9IDApIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgY29uc3QgaW5uZXJSYWRpaSA9IGVsbGlwc29pZEdlb21ldHJ5Ll9pbm5lclJhZGlpOwogICAgICAgIGlmIChpbm5lclJhZGlpLnggPD0gMCB8fCBpbm5lclJhZGlpLnkgPD0gMCB8fCBpbm5lclJhZGlpLnogPD0gMCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBjb25zdCBtaW5pbXVtQ2xvY2sgPSBlbGxpcHNvaWRHZW9tZXRyeS5fbWluaW11bUNsb2NrOwogICAgICAgIGNvbnN0IG1heGltdW1DbG9jayA9IGVsbGlwc29pZEdlb21ldHJ5Ll9tYXhpbXVtQ2xvY2s7CiAgICAgICAgY29uc3QgbWluaW11bUNvbmUgPSBlbGxpcHNvaWRHZW9tZXRyeS5fbWluaW11bUNvbmU7CiAgICAgICAgY29uc3QgbWF4aW11bUNvbmUgPSBlbGxpcHNvaWRHZW9tZXRyeS5fbWF4aW11bUNvbmU7CiAgICAgICAgY29uc3Qgc3ViZGl2aXNpb25zID0gZWxsaXBzb2lkR2VvbWV0cnkuX3N1YmRpdmlzaW9uczsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5mcm9tQ2FydGVzaWFuMyhyYWRpaSk7CiAgICAgICAgbGV0IHNsaWNlUGFydGl0aW9ucyA9IGVsbGlwc29pZEdlb21ldHJ5Ll9zbGljZVBhcnRpdGlvbnMgKyAxOwogICAgICAgIGxldCBzdGFja1BhcnRpdGlvbnMgPSBlbGxpcHNvaWRHZW9tZXRyeS5fc3RhY2tQYXJ0aXRpb25zICsgMTsKICAgICAgICBzbGljZVBhcnRpdGlvbnMgPSBNYXRoLnJvdW5kKAogICAgICAgICAgc2xpY2VQYXJ0aXRpb25zICogTWF0aC5hYnMobWF4aW11bUNsb2NrIC0gbWluaW11bUNsb2NrKSAvIE1hdGhfZGVmYXVsdC5UV09fUEkKICAgICAgICApOwogICAgICAgIHN0YWNrUGFydGl0aW9ucyA9IE1hdGgucm91bmQoCiAgICAgICAgICBzdGFja1BhcnRpdGlvbnMgKiBNYXRoLmFicyhtYXhpbXVtQ29uZSAtIG1pbmltdW1Db25lKSAvIE1hdGhfZGVmYXVsdC5QSQogICAgICAgICk7CiAgICAgICAgaWYgKHNsaWNlUGFydGl0aW9ucyA8IDIpIHsKICAgICAgICAgIHNsaWNlUGFydGl0aW9ucyA9IDI7CiAgICAgICAgfQogICAgICAgIGlmIChzdGFja1BhcnRpdGlvbnMgPCAyKSB7CiAgICAgICAgICBzdGFja1BhcnRpdGlvbnMgPSAyOwogICAgICAgIH0KICAgICAgICBsZXQgZXh0cmFJbmRpY2VzID0gMDsKICAgICAgICBsZXQgdmVydGV4TXVsdGlwbGllciA9IDE7CiAgICAgICAgY29uc3QgaGFzSW5uZXJTdXJmYWNlID0gaW5uZXJSYWRpaS54ICE9PSByYWRpaS54IHx8IGlubmVyUmFkaWkueSAhPT0gcmFkaWkueSB8fCBpbm5lclJhZGlpLnogIT09IHJhZGlpLno7CiAgICAgICAgbGV0IGlzVG9wT3BlbiA9IGZhbHNlOwogICAgICAgIGxldCBpc0JvdE9wZW4gPSBmYWxzZTsKICAgICAgICBpZiAoaGFzSW5uZXJTdXJmYWNlKSB7CiAgICAgICAgICB2ZXJ0ZXhNdWx0aXBsaWVyID0gMjsKICAgICAgICAgIGlmIChtaW5pbXVtQ29uZSA+IDApIHsKICAgICAgICAgICAgaXNUb3BPcGVuID0gdHJ1ZTsKICAgICAgICAgICAgZXh0cmFJbmRpY2VzICs9IHNsaWNlUGFydGl0aW9uczsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChtYXhpbXVtQ29uZSA8IE1hdGguUEkpIHsKICAgICAgICAgICAgaXNCb3RPcGVuID0gdHJ1ZTsKICAgICAgICAgICAgZXh0cmFJbmRpY2VzICs9IHNsaWNlUGFydGl0aW9uczsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgdmVydGV4Q291bnQgPSBzdWJkaXZpc2lvbnMgKiB2ZXJ0ZXhNdWx0aXBsaWVyICogKHN0YWNrUGFydGl0aW9ucyArIHNsaWNlUGFydGl0aW9ucyk7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheSh2ZXJ0ZXhDb3VudCAqIDMpOwogICAgICAgIGNvbnN0IG51bUluZGljZXMgPSAyICogKHZlcnRleENvdW50ICsgZXh0cmFJbmRpY2VzIC0gKHNsaWNlUGFydGl0aW9ucyArIHN0YWNrUGFydGl0aW9ucykgKiB2ZXJ0ZXhNdWx0aXBsaWVyKTsKICAgICAgICBjb25zdCBpbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkodmVydGV4Q291bnQsIG51bUluZGljZXMpOwogICAgICAgIGxldCBpOwogICAgICAgIGxldCBqOwogICAgICAgIGxldCB0aGV0YTsKICAgICAgICBsZXQgcGhpOwogICAgICAgIGxldCBpbmRleCA9IDA7CiAgICAgICAgY29uc3Qgc2luUGhpID0gbmV3IEFycmF5KHN0YWNrUGFydGl0aW9ucyk7CiAgICAgICAgY29uc3QgY29zUGhpID0gbmV3IEFycmF5KHN0YWNrUGFydGl0aW9ucyk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHN0YWNrUGFydGl0aW9uczsgaSsrKSB7CiAgICAgICAgICBwaGkgPSBtaW5pbXVtQ29uZSArIGkgKiAobWF4aW11bUNvbmUgLSBtaW5pbXVtQ29uZSkgLyAoc3RhY2tQYXJ0aXRpb25zIC0gMSk7CiAgICAgICAgICBzaW5QaGlbaV0gPSBzaW4yKHBoaSk7CiAgICAgICAgICBjb3NQaGlbaV0gPSBjb3MyKHBoaSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHNpblRoZXRhID0gbmV3IEFycmF5KHN1YmRpdmlzaW9ucyk7CiAgICAgICAgY29uc3QgY29zVGhldGEgPSBuZXcgQXJyYXkoc3ViZGl2aXNpb25zKTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc3ViZGl2aXNpb25zOyBpKyspIHsKICAgICAgICAgIHRoZXRhID0gbWluaW11bUNsb2NrICsgaSAqIChtYXhpbXVtQ2xvY2sgLSBtaW5pbXVtQ2xvY2spIC8gKHN1YmRpdmlzaW9ucyAtIDEpOwogICAgICAgICAgc2luVGhldGFbaV0gPSBzaW4yKHRoZXRhKTsKICAgICAgICAgIGNvc1RoZXRhW2ldID0gY29zMih0aGV0YSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaSA9IDA7IGkgPCBzdGFja1BhcnRpdGlvbnM7IGkrKykgewogICAgICAgICAgZm9yIChqID0gMDsgaiA8IHN1YmRpdmlzaW9uczsgaisrKSB7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpbmRleCsrXSA9IHJhZGlpLnggKiBzaW5QaGlbaV0gKiBjb3NUaGV0YVtqXTsKICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gcmFkaWkueSAqIHNpblBoaVtpXSAqIHNpblRoZXRhW2pdOwogICAgICAgICAgICBwb3NpdGlvbnNbaW5kZXgrK10gPSByYWRpaS56ICogY29zUGhpW2ldOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoaGFzSW5uZXJTdXJmYWNlKSB7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc3RhY2tQYXJ0aXRpb25zOyBpKyspIHsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHN1YmRpdmlzaW9uczsgaisrKSB7CiAgICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gaW5uZXJSYWRpaS54ICogc2luUGhpW2ldICogY29zVGhldGFbal07CiAgICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gaW5uZXJSYWRpaS55ICogc2luUGhpW2ldICogc2luVGhldGFbal07CiAgICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gaW5uZXJSYWRpaS56ICogY29zUGhpW2ldOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHNpblBoaS5sZW5ndGggPSBzdWJkaXZpc2lvbnM7CiAgICAgICAgY29zUGhpLmxlbmd0aCA9IHN1YmRpdmlzaW9uczsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc3ViZGl2aXNpb25zOyBpKyspIHsKICAgICAgICAgIHBoaSA9IG1pbmltdW1Db25lICsgaSAqIChtYXhpbXVtQ29uZSAtIG1pbmltdW1Db25lKSAvIChzdWJkaXZpc2lvbnMgLSAxKTsKICAgICAgICAgIHNpblBoaVtpXSA9IHNpbjIocGhpKTsKICAgICAgICAgIGNvc1BoaVtpXSA9IGNvczIocGhpKTsKICAgICAgICB9CiAgICAgICAgc2luVGhldGEubGVuZ3RoID0gc2xpY2VQYXJ0aXRpb25zOwogICAgICAgIGNvc1RoZXRhLmxlbmd0aCA9IHNsaWNlUGFydGl0aW9uczsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc2xpY2VQYXJ0aXRpb25zOyBpKyspIHsKICAgICAgICAgIHRoZXRhID0gbWluaW11bUNsb2NrICsgaSAqIChtYXhpbXVtQ2xvY2sgLSBtaW5pbXVtQ2xvY2spIC8gKHNsaWNlUGFydGl0aW9ucyAtIDEpOwogICAgICAgICAgc2luVGhldGFbaV0gPSBzaW4yKHRoZXRhKTsKICAgICAgICAgIGNvc1RoZXRhW2ldID0gY29zMih0aGV0YSk7CiAgICAgICAgfQogICAgICAgIGZvciAoaSA9IDA7IGkgPCBzdWJkaXZpc2lvbnM7IGkrKykgewogICAgICAgICAgZm9yIChqID0gMDsgaiA8IHNsaWNlUGFydGl0aW9uczsgaisrKSB7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpbmRleCsrXSA9IHJhZGlpLnggKiBzaW5QaGlbaV0gKiBjb3NUaGV0YVtqXTsKICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gcmFkaWkueSAqIHNpblBoaVtpXSAqIHNpblRoZXRhW2pdOwogICAgICAgICAgICBwb3NpdGlvbnNbaW5kZXgrK10gPSByYWRpaS56ICogY29zUGhpW2ldOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoaGFzSW5uZXJTdXJmYWNlKSB7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc3ViZGl2aXNpb25zOyBpKyspIHsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHNsaWNlUGFydGl0aW9uczsgaisrKSB7CiAgICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gaW5uZXJSYWRpaS54ICogc2luUGhpW2ldICogY29zVGhldGFbal07CiAgICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gaW5uZXJSYWRpaS55ICogc2luUGhpW2ldICogc2luVGhldGFbal07CiAgICAgICAgICAgICAgcG9zaXRpb25zW2luZGV4KytdID0gaW5uZXJSYWRpaS56ICogY29zUGhpW2ldOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGluZGV4ID0gMDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc3RhY2tQYXJ0aXRpb25zICogdmVydGV4TXVsdGlwbGllcjsgaSsrKSB7CiAgICAgICAgICBjb25zdCB0b3BPZmZzZXQgPSBpICogc3ViZGl2aXNpb25zOwogICAgICAgICAgZm9yIChqID0gMDsgaiA8IHN1YmRpdmlzaW9ucyAtIDE7IGorKykgewogICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gdG9wT2Zmc2V0ICsgajsKICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHRvcE9mZnNldCArIGogKyAxOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBsZXQgb2Zmc2V0ID0gc3RhY2tQYXJ0aXRpb25zICogc3ViZGl2aXNpb25zICogdmVydGV4TXVsdGlwbGllcjsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc2xpY2VQYXJ0aXRpb25zOyBpKyspIHsKICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBzdWJkaXZpc2lvbnMgLSAxOyBqKyspIHsKICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IG9mZnNldCArIGkgKyBqICogc2xpY2VQYXJ0aXRpb25zOwogICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gb2Zmc2V0ICsgaSArIChqICsgMSkgKiBzbGljZVBhcnRpdGlvbnM7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChoYXNJbm5lclN1cmZhY2UpIHsKICAgICAgICAgIG9mZnNldCA9IHN0YWNrUGFydGl0aW9ucyAqIHN1YmRpdmlzaW9ucyAqIHZlcnRleE11bHRpcGxpZXIgKyBzbGljZVBhcnRpdGlvbnMgKiBzdWJkaXZpc2lvbnM7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc2xpY2VQYXJ0aXRpb25zOyBpKyspIHsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHN1YmRpdmlzaW9ucyAtIDE7IGorKykgewogICAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBvZmZzZXQgKyBpICsgaiAqIHNsaWNlUGFydGl0aW9uczsKICAgICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gb2Zmc2V0ICsgaSArIChqICsgMSkgKiBzbGljZVBhcnRpdGlvbnM7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGhhc0lubmVyU3VyZmFjZSkgewogICAgICAgICAgbGV0IG91dGVyT2Zmc2V0ID0gc3RhY2tQYXJ0aXRpb25zICogc3ViZGl2aXNpb25zICogdmVydGV4TXVsdGlwbGllcjsKICAgICAgICAgIGxldCBpbm5lck9mZnNldCA9IG91dGVyT2Zmc2V0ICsgc3ViZGl2aXNpb25zICogc2xpY2VQYXJ0aXRpb25zOwogICAgICAgICAgaWYgKGlzVG9wT3BlbikgewogICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc2xpY2VQYXJ0aXRpb25zOyBpKyspIHsKICAgICAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gb3V0ZXJPZmZzZXQgKyBpOwogICAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpbm5lck9mZnNldCArIGk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChpc0JvdE9wZW4pIHsKICAgICAgICAgICAgb3V0ZXJPZmZzZXQgKz0gc3ViZGl2aXNpb25zICogc2xpY2VQYXJ0aXRpb25zIC0gc2xpY2VQYXJ0aXRpb25zOwogICAgICAgICAgICBpbm5lck9mZnNldCArPSBzdWJkaXZpc2lvbnMgKiBzbGljZVBhcnRpdGlvbnMgLSBzbGljZVBhcnRpdGlvbnM7CiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzbGljZVBhcnRpdGlvbnM7IGkrKykgewogICAgICAgICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBvdXRlck9mZnNldCArIGk7CiAgICAgICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGlubmVyT2Zmc2V0ICsgaTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlc19kZWZhdWx0KHsKICAgICAgICAgIHBvc2l0aW9uOiBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgdmFsdWVzOiBwb3NpdGlvbnMKICAgICAgICAgIH0pCiAgICAgICAgfSk7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChlbGxpcHNvaWRHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlKSkgewogICAgICAgICAgY29uc3QgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICAgIGNvbnN0IG9mZnNldFZhbHVlID0gZWxsaXBzb2lkR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5OT05FID8gMCA6IDE7CiAgICAgICAgICBjb25zdCBhcHBseU9mZnNldCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCAvIDMpLmZpbGwob2Zmc2V0VmFsdWUpOwogICAgICAgICAgYXR0cmlidXRlcy5hcHBseU9mZnNldCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuVU5TSUdORURfQllURSwKICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMSwKICAgICAgICAgICAgdmFsdWVzOiBhcHBseU9mZnNldAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgICAgICBhdHRyaWJ1dGVzLAogICAgICAgICAgaW5kaWNlcywKICAgICAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5MSU5FUywKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlOiBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21FbGxpcHNvaWQoZWxsaXBzb2lkKSwKICAgICAgICAgIG9mZnNldEF0dHJpYnV0ZTogZWxsaXBzb2lkR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZQogICAgICAgIH0pOwogICAgICB9OwogICAgICBFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdCA9IEVsbGlwc29pZE91dGxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUVsbGlwc29pZE91dGxpbmVHZW9tZXRyeS5qcwogIHZhciBjcmVhdGVFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZUVsbGlwc29pZE91dGxpbmVHZW9tZXRyeV9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZUVsbGlwc29pZE91dGxpbmVHZW9tZXRyeShlbGxpcHNvaWRHZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGVsbGlwc29pZEdlb21ldHJ5LmJ1ZmZlciwgb2Zmc2V0KSkgewogICAgICBlbGxpcHNvaWRHZW9tZXRyeSA9IEVsbGlwc29pZE91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjaygKICAgICAgICBlbGxpcHNvaWRHZW9tZXRyeSwKICAgICAgICBvZmZzZXQKICAgICAgKTsKICAgIH0KICAgIHJldHVybiBFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeShlbGxpcHNvaWRHZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUVsbGlwc29pZE91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZE91dGxpbmVHZW9tZXRyeSgpOwogICAgICBjcmVhdGVFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZUVsbGlwc29pZE91dGxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0N1bGxpbmdWb2x1bWUuanMKICBmdW5jdGlvbiBDdWxsaW5nVm9sdW1lKHBsYW5lcykgewogICAgdGhpcy5wbGFuZXMgPSBwbGFuZXMgPz8gW107CiAgfQogIHZhciBmYWNlcywgc2NyYXRjaFBsYW5lQ2VudGVyLCBzY3JhdGNoUGxhbmVOb3JtYWwyLCBzY3JhdGNoUGxhbmUyLCBDdWxsaW5nVm9sdW1lX2RlZmF1bHQ7CiAgdmFyIGluaXRfQ3VsbGluZ1ZvbHVtZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQ3VsbGluZ1ZvbHVtZS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRlc2lhbjQoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9JbnRlcnNlY3QoKTsKICAgICAgaW5pdF9QbGFuZSgpOwogICAgICBmYWNlcyA9IFtuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCksIG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKSwgbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpXTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1gsIGZhY2VzWzBdKTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1ksIGZhY2VzWzFdKTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1osIGZhY2VzWzJdKTsKICAgICAgc2NyYXRjaFBsYW5lQ2VudGVyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGxhbmVOb3JtYWwyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGxhbmUyID0gbmV3IFBsYW5lX2RlZmF1bHQobmV3IENhcnRlc2lhbjNfZGVmYXVsdCgxLCAwLCAwKSwgMCk7CiAgICAgIEN1bGxpbmdWb2x1bWUuZnJvbUJvdW5kaW5nU3BoZXJlID0gZnVuY3Rpb24oYm91bmRpbmdTcGhlcmUsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGJvdW5kaW5nU3BoZXJlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImJvdW5kaW5nU3BoZXJlIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQ3VsbGluZ1ZvbHVtZSgpOwogICAgICAgIH0KICAgICAgICBjb25zdCBsZW5ndGggPSBmYWNlcy5sZW5ndGg7CiAgICAgICAgY29uc3QgcGxhbmVzID0gcmVzdWx0LnBsYW5lczsKICAgICAgICBwbGFuZXMubGVuZ3RoID0gMiAqIGxlbmd0aDsKICAgICAgICBjb25zdCBjZW50ZXIgPSBib3VuZGluZ1NwaGVyZS5jZW50ZXI7CiAgICAgICAgY29uc3QgcmFkaXVzID0gYm91bmRpbmdTcGhlcmUucmFkaXVzOwogICAgICAgIGxldCBwbGFuZUluZGV4ID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICBjb25zdCBmYWNlTm9ybWFsID0gZmFjZXNbaV07CiAgICAgICAgICBsZXQgcGxhbmUwID0gcGxhbmVzW3BsYW5lSW5kZXhdOwogICAgICAgICAgbGV0IHBsYW5lMSA9IHBsYW5lc1twbGFuZUluZGV4ICsgMV07CiAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwbGFuZTApKSB7CiAgICAgICAgICAgIHBsYW5lMCA9IHBsYW5lc1twbGFuZUluZGV4XSA9IG5ldyBDYXJ0ZXNpYW40X2RlZmF1bHQoKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBsYW5lMSkpIHsKICAgICAgICAgICAgcGxhbmUxID0gcGxhbmVzW3BsYW5lSW5kZXggKyAxXSA9IG5ldyBDYXJ0ZXNpYW40X2RlZmF1bHQoKTsKICAgICAgICAgIH0KICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGZhY2VOb3JtYWwsIC1yYWRpdXMsIHNjcmF0Y2hQbGFuZUNlbnRlcik7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNlbnRlciwgc2NyYXRjaFBsYW5lQ2VudGVyLCBzY3JhdGNoUGxhbmVDZW50ZXIpOwogICAgICAgICAgcGxhbmUwLnggPSBmYWNlTm9ybWFsLng7CiAgICAgICAgICBwbGFuZTAueSA9IGZhY2VOb3JtYWwueTsKICAgICAgICAgIHBsYW5lMC56ID0gZmFjZU5vcm1hbC56OwogICAgICAgICAgcGxhbmUwLncgPSAtQ2FydGVzaWFuM19kZWZhdWx0LmRvdChmYWNlTm9ybWFsLCBzY3JhdGNoUGxhbmVDZW50ZXIpOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoZmFjZU5vcm1hbCwgcmFkaXVzLCBzY3JhdGNoUGxhbmVDZW50ZXIpOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChjZW50ZXIsIHNjcmF0Y2hQbGFuZUNlbnRlciwgc2NyYXRjaFBsYW5lQ2VudGVyKTsKICAgICAgICAgIHBsYW5lMS54ID0gLWZhY2VOb3JtYWwueDsKICAgICAgICAgIHBsYW5lMS55ID0gLWZhY2VOb3JtYWwueTsKICAgICAgICAgIHBsYW5lMS56ID0gLWZhY2VOb3JtYWwuejsKICAgICAgICAgIHBsYW5lMS53ID0gLUNhcnRlc2lhbjNfZGVmYXVsdC5kb3QoCiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoZmFjZU5vcm1hbCwgc2NyYXRjaFBsYW5lTm9ybWFsMiksCiAgICAgICAgICAgIHNjcmF0Y2hQbGFuZUNlbnRlcgogICAgICAgICAgKTsKICAgICAgICAgIHBsYW5lSW5kZXggKz0gMjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ3VsbGluZ1ZvbHVtZS5wcm90b3R5cGUuY29tcHV0ZVZpc2liaWxpdHkgPSBmdW5jdGlvbihib3VuZGluZ1ZvbHVtZSkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGJvdW5kaW5nVm9sdW1lKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImJvdW5kaW5nVm9sdW1lIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBwbGFuZXMgPSB0aGlzLnBsYW5lczsKICAgICAgICBsZXQgaW50ZXJzZWN0aW5nID0gZmFsc2U7CiAgICAgICAgZm9yIChsZXQgayA9IDAsIGxlbiA9IHBsYW5lcy5sZW5ndGg7IGsgPCBsZW47ICsraykgewogICAgICAgICAgY29uc3QgcmVzdWx0ID0gYm91bmRpbmdWb2x1bWUuaW50ZXJzZWN0UGxhbmUoCiAgICAgICAgICAgIFBsYW5lX2RlZmF1bHQuZnJvbUNhcnRlc2lhbjQocGxhbmVzW2tdLCBzY3JhdGNoUGxhbmUyKQogICAgICAgICAgKTsKICAgICAgICAgIGlmIChyZXN1bHQgPT09IEludGVyc2VjdF9kZWZhdWx0Lk9VVFNJREUpIHsKICAgICAgICAgICAgcmV0dXJuIEludGVyc2VjdF9kZWZhdWx0Lk9VVFNJREU7CiAgICAgICAgICB9IGVsc2UgaWYgKHJlc3VsdCA9PT0gSW50ZXJzZWN0X2RlZmF1bHQuSU5URVJTRUNUSU5HKSB7CiAgICAgICAgICAgIGludGVyc2VjdGluZyA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBpbnRlcnNlY3RpbmcgPyBJbnRlcnNlY3RfZGVmYXVsdC5JTlRFUlNFQ1RJTkcgOiBJbnRlcnNlY3RfZGVmYXVsdC5JTlNJREU7CiAgICAgIH07CiAgICAgIEN1bGxpbmdWb2x1bWUucHJvdG90eXBlLmNvbXB1dGVWaXNpYmlsaXR5V2l0aFBsYW5lTWFzayA9IGZ1bmN0aW9uKGJvdW5kaW5nVm9sdW1lLCBwYXJlbnRQbGFuZU1hc2spIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChib3VuZGluZ1ZvbHVtZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJib3VuZGluZ1ZvbHVtZSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocGFyZW50UGxhbmVNYXNrKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInBhcmVudFBsYW5lTWFzayBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKHBhcmVudFBsYW5lTWFzayA9PT0gQ3VsbGluZ1ZvbHVtZS5NQVNLX09VVFNJREUgfHwgcGFyZW50UGxhbmVNYXNrID09PSBDdWxsaW5nVm9sdW1lLk1BU0tfSU5TSURFKSB7CiAgICAgICAgICByZXR1cm4gcGFyZW50UGxhbmVNYXNrOwogICAgICAgIH0KICAgICAgICBsZXQgbWFzayA9IEN1bGxpbmdWb2x1bWUuTUFTS19JTlNJREU7CiAgICAgICAgY29uc3QgcGxhbmVzID0gdGhpcy5wbGFuZXM7CiAgICAgICAgZm9yIChsZXQgayA9IDAsIGxlbiA9IHBsYW5lcy5sZW5ndGg7IGsgPCBsZW47ICsraykgewogICAgICAgICAgY29uc3QgZmxhZyA9IGsgPCAzMSA/IDEgPDwgayA6IDA7CiAgICAgICAgICBpZiAoayA8IDMxICYmIChwYXJlbnRQbGFuZU1hc2sgJiBmbGFnKSA9PT0gMCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGJvdW5kaW5nVm9sdW1lLmludGVyc2VjdFBsYW5lKAogICAgICAgICAgICBQbGFuZV9kZWZhdWx0LmZyb21DYXJ0ZXNpYW40KHBsYW5lc1trXSwgc2NyYXRjaFBsYW5lMikKICAgICAgICAgICk7CiAgICAgICAgICBpZiAocmVzdWx0ID09PSBJbnRlcnNlY3RfZGVmYXVsdC5PVVRTSURFKSB7CiAgICAgICAgICAgIHJldHVybiBDdWxsaW5nVm9sdW1lLk1BU0tfT1VUU0lERTsKICAgICAgICAgIH0gZWxzZSBpZiAocmVzdWx0ID09PSBJbnRlcnNlY3RfZGVmYXVsdC5JTlRFUlNFQ1RJTkcpIHsKICAgICAgICAgICAgbWFzayB8PSBmbGFnOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gbWFzazsKICAgICAgfTsKICAgICAgQ3VsbGluZ1ZvbHVtZS5NQVNLX09VVFNJREUgPSA0Mjk0OTY3Mjk1OwogICAgICBDdWxsaW5nVm9sdW1lLk1BU0tfSU5TSURFID0gMDsKICAgICAgQ3VsbGluZ1ZvbHVtZS5NQVNLX0lOREVURVJNSU5BVEUgPSAyMTQ3NDgzNjQ3OwogICAgICBDdWxsaW5nVm9sdW1lX2RlZmF1bHQgPSBDdWxsaW5nVm9sdW1lOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvT3J0aG9ncmFwaGljT2ZmQ2VudGVyRnJ1c3R1bS5qcwogIGZ1bmN0aW9uIE9ydGhvZ3JhcGhpY09mZkNlbnRlckZydXN0dW0ob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgdGhpcy5sZWZ0ID0gb3B0aW9ucy5sZWZ0OwogICAgdGhpcy5fbGVmdCA9IHZvaWQgMDsKICAgIHRoaXMucmlnaHQgPSBvcHRpb25zLnJpZ2h0OwogICAgdGhpcy5fcmlnaHQgPSB2b2lkIDA7CiAgICB0aGlzLnRvcCA9IG9wdGlvbnMudG9wOwogICAgdGhpcy5fdG9wID0gdm9pZCAwOwogICAgdGhpcy5ib3R0b20gPSBvcHRpb25zLmJvdHRvbTsKICAgIHRoaXMuX2JvdHRvbSA9IHZvaWQgMDsKICAgIHRoaXMubmVhciA9IG9wdGlvbnMubmVhciA/PyAxOwogICAgdGhpcy5fbmVhciA9IHRoaXMubmVhcjsKICAgIHRoaXMuZmFyID0gb3B0aW9ucy5mYXIgPz8gNWU4OwogICAgdGhpcy5fZmFyID0gdGhpcy5mYXI7CiAgICB0aGlzLl9jdWxsaW5nVm9sdW1lID0gbmV3IEN1bGxpbmdWb2x1bWVfZGVmYXVsdCgpOwogICAgdGhpcy5fb3J0aG9ncmFwaGljTWF0cml4ID0gbmV3IE1hdHJpeDRfZGVmYXVsdCgpOwogIH0KICBmdW5jdGlvbiB1cGRhdGUoZnJ1c3R1bSkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZnJ1c3R1bS5yaWdodCkgfHwgIWRlZmluZWRfZGVmYXVsdChmcnVzdHVtLmxlZnQpIHx8ICFkZWZpbmVkX2RlZmF1bHQoZnJ1c3R1bS50b3ApIHx8ICFkZWZpbmVkX2RlZmF1bHQoZnJ1c3R1bS5ib3R0b20pIHx8ICFkZWZpbmVkX2RlZmF1bHQoZnJ1c3R1bS5uZWFyKSB8fCAhZGVmaW5lZF9kZWZhdWx0KGZydXN0dW0uZmFyKSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAicmlnaHQsIGxlZnQsIHRvcCwgYm90dG9tLCBuZWFyLCBvciBmYXIgcGFyYW1ldGVycyBhcmUgbm90IHNldC4iCiAgICAgICk7CiAgICB9CiAgICBpZiAoZnJ1c3R1bS50b3AgIT09IGZydXN0dW0uX3RvcCB8fCBmcnVzdHVtLmJvdHRvbSAhPT0gZnJ1c3R1bS5fYm90dG9tIHx8IGZydXN0dW0ubGVmdCAhPT0gZnJ1c3R1bS5fbGVmdCB8fCBmcnVzdHVtLnJpZ2h0ICE9PSBmcnVzdHVtLl9yaWdodCB8fCBmcnVzdHVtLm5lYXIgIT09IGZydXN0dW0uX25lYXIgfHwgZnJ1c3R1bS5mYXIgIT09IGZydXN0dW0uX2ZhcikgewogICAgICBpZiAoZnJ1c3R1bS5sZWZ0ID4gZnJ1c3R1bS5yaWdodCkgewogICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJyaWdodCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiBsZWZ0LiIpOwogICAgICB9CiAgICAgIGlmIChmcnVzdHVtLmJvdHRvbSA+IGZydXN0dW0udG9wKSB7CiAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInRvcCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiBib3R0b20uIik7CiAgICAgIH0KICAgICAgaWYgKGZydXN0dW0ubmVhciA8PSAwIHx8IGZydXN0dW0ubmVhciA+IGZydXN0dW0uZmFyKSB7CiAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAibmVhciBtdXN0IGJlIGdyZWF0ZXIgdGhhbiB6ZXJvIGFuZCBsZXNzIHRoYW4gZmFyLiIKICAgICAgICApOwogICAgICB9CiAgICAgIGZydXN0dW0uX2xlZnQgPSBmcnVzdHVtLmxlZnQ7CiAgICAgIGZydXN0dW0uX3JpZ2h0ID0gZnJ1c3R1bS5yaWdodDsKICAgICAgZnJ1c3R1bS5fdG9wID0gZnJ1c3R1bS50b3A7CiAgICAgIGZydXN0dW0uX2JvdHRvbSA9IGZydXN0dW0uYm90dG9tOwogICAgICBmcnVzdHVtLl9uZWFyID0gZnJ1c3R1bS5uZWFyOwogICAgICBmcnVzdHVtLl9mYXIgPSBmcnVzdHVtLmZhcjsKICAgICAgZnJ1c3R1bS5fb3J0aG9ncmFwaGljTWF0cml4ID0gTWF0cml4NF9kZWZhdWx0LmNvbXB1dGVPcnRob2dyYXBoaWNPZmZDZW50ZXIoCiAgICAgICAgZnJ1c3R1bS5sZWZ0LAogICAgICAgIGZydXN0dW0ucmlnaHQsCiAgICAgICAgZnJ1c3R1bS5ib3R0b20sCiAgICAgICAgZnJ1c3R1bS50b3AsCiAgICAgICAgZnJ1c3R1bS5uZWFyLAogICAgICAgIGZydXN0dW0uZmFyLAogICAgICAgIGZydXN0dW0uX29ydGhvZ3JhcGhpY01hdHJpeAogICAgICApOwogICAgfQogIH0KICB2YXIgZ2V0UGxhbmVzUmlnaHQsIGdldFBsYW5lc05lYXJDZW50ZXIsIGdldFBsYW5lc1BvaW50LCBuZWdhdGVTY3JhdGNoLCBPcnRob2dyYXBoaWNPZmZDZW50ZXJGcnVzdHVtX2RlZmF1bHQ7CiAgdmFyIGluaXRfT3J0aG9ncmFwaGljT2ZmQ2VudGVyRnJ1c3R1bSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvT3J0aG9ncmFwaGljT2ZmQ2VudGVyRnJ1c3R1bS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRlc2lhbjQoKTsKICAgICAgaW5pdF9DdWxsaW5nVm9sdW1lKCk7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X01hdHJpeDQoKTsKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoT3J0aG9ncmFwaGljT2ZmQ2VudGVyRnJ1c3R1bS5wcm90b3R5cGUsIHsKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBvcnRob2dyYXBoaWMgcHJvamVjdGlvbiBtYXRyaXggY29tcHV0ZWQgZnJvbSB0aGUgdmlldyBmcnVzdHVtLgogICAgICAgICAqIEBtZW1iZXJvZiBPcnRob2dyYXBoaWNPZmZDZW50ZXJGcnVzdHVtLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtNYXRyaXg0fQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIHByb2plY3Rpb25NYXRyaXg6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHVwZGF0ZSh0aGlzKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29ydGhvZ3JhcGhpY01hdHJpeDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBnZXRQbGFuZXNSaWdodCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZ2V0UGxhbmVzTmVhckNlbnRlciA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZ2V0UGxhbmVzUG9pbnQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIG5lZ2F0ZVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIE9ydGhvZ3JhcGhpY09mZkNlbnRlckZydXN0dW0ucHJvdG90eXBlLmNvbXB1dGVDdWxsaW5nVm9sdW1lID0gZnVuY3Rpb24ocG9zaXRpb24sIGRpcmVjdGlvbjIsIHVwKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocG9zaXRpb24pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicG9zaXRpb24gaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGRpcmVjdGlvbjIpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZGlyZWN0aW9uIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh1cCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ1cCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcGxhbmVzID0gdGhpcy5fY3VsbGluZ1ZvbHVtZS5wbGFuZXM7CiAgICAgICAgY29uc3QgdCA9IHRoaXMudG9wOwogICAgICAgIGNvbnN0IGIgPSB0aGlzLmJvdHRvbTsKICAgICAgICBjb25zdCByID0gdGhpcy5yaWdodDsKICAgICAgICBjb25zdCBsID0gdGhpcy5sZWZ0OwogICAgICAgIGNvbnN0IG4gPSB0aGlzLm5lYXI7CiAgICAgICAgY29uc3QgZiA9IHRoaXMuZmFyOwogICAgICAgIGNvbnN0IHJpZ2h0ID0gQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKGRpcmVjdGlvbjIsIHVwLCBnZXRQbGFuZXNSaWdodCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShyaWdodCwgcmlnaHQpOwogICAgICAgIGNvbnN0IG5lYXJDZW50ZXIgPSBnZXRQbGFuZXNOZWFyQ2VudGVyOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGRpcmVjdGlvbjIsIG4sIG5lYXJDZW50ZXIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocG9zaXRpb24sIG5lYXJDZW50ZXIsIG5lYXJDZW50ZXIpOwogICAgICAgIGNvbnN0IHBvaW50ID0gZ2V0UGxhbmVzUG9pbnQ7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIocmlnaHQsIGwsIHBvaW50KTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKG5lYXJDZW50ZXIsIHBvaW50LCBwb2ludCk7CiAgICAgICAgbGV0IHBsYW5lID0gcGxhbmVzWzBdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBsYW5lKSkgewogICAgICAgICAgcGxhbmUgPSBwbGFuZXNbMF0gPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIHBsYW5lLnggPSByaWdodC54OwogICAgICAgIHBsYW5lLnkgPSByaWdodC55OwogICAgICAgIHBsYW5lLnogPSByaWdodC56OwogICAgICAgIHBsYW5lLncgPSAtQ2FydGVzaWFuM19kZWZhdWx0LmRvdChyaWdodCwgcG9pbnQpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKHJpZ2h0LCByLCBwb2ludCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChuZWFyQ2VudGVyLCBwb2ludCwgcG9pbnQpOwogICAgICAgIHBsYW5lID0gcGxhbmVzWzFdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBsYW5lKSkgewogICAgICAgICAgcGxhbmUgPSBwbGFuZXNbMV0gPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIHBsYW5lLnggPSAtcmlnaHQueDsKICAgICAgICBwbGFuZS55ID0gLXJpZ2h0Lnk7CiAgICAgICAgcGxhbmUueiA9IC1yaWdodC56OwogICAgICAgIHBsYW5lLncgPSAtQ2FydGVzaWFuM19kZWZhdWx0LmRvdChDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKHJpZ2h0LCBuZWdhdGVTY3JhdGNoKSwgcG9pbnQpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKHVwLCBiLCBwb2ludCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChuZWFyQ2VudGVyLCBwb2ludCwgcG9pbnQpOwogICAgICAgIHBsYW5lID0gcGxhbmVzWzJdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBsYW5lKSkgewogICAgICAgICAgcGxhbmUgPSBwbGFuZXNbMl0gPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIHBsYW5lLnggPSB1cC54OwogICAgICAgIHBsYW5lLnkgPSB1cC55OwogICAgICAgIHBsYW5lLnogPSB1cC56OwogICAgICAgIHBsYW5lLncgPSAtQ2FydGVzaWFuM19kZWZhdWx0LmRvdCh1cCwgcG9pbnQpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKHVwLCB0LCBwb2ludCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChuZWFyQ2VudGVyLCBwb2ludCwgcG9pbnQpOwogICAgICAgIHBsYW5lID0gcGxhbmVzWzNdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBsYW5lKSkgewogICAgICAgICAgcGxhbmUgPSBwbGFuZXNbM10gPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIHBsYW5lLnggPSAtdXAueDsKICAgICAgICBwbGFuZS55ID0gLXVwLnk7CiAgICAgICAgcGxhbmUueiA9IC11cC56OwogICAgICAgIHBsYW5lLncgPSAtQ2FydGVzaWFuM19kZWZhdWx0LmRvdChDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKHVwLCBuZWdhdGVTY3JhdGNoKSwgcG9pbnQpOwogICAgICAgIHBsYW5lID0gcGxhbmVzWzRdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBsYW5lKSkgewogICAgICAgICAgcGxhbmUgPSBwbGFuZXNbNF0gPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIHBsYW5lLnggPSBkaXJlY3Rpb24yLng7CiAgICAgICAgcGxhbmUueSA9IGRpcmVjdGlvbjIueTsKICAgICAgICBwbGFuZS56ID0gZGlyZWN0aW9uMi56OwogICAgICAgIHBsYW5lLncgPSAtQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCBuZWFyQ2VudGVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihkaXJlY3Rpb24yLCBmLCBwb2ludCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChwb3NpdGlvbiwgcG9pbnQsIHBvaW50KTsKICAgICAgICBwbGFuZSA9IHBsYW5lc1s1XTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwbGFuZSkpIHsKICAgICAgICAgIHBsYW5lID0gcGxhbmVzWzVdID0gbmV3IENhcnRlc2lhbjRfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICBwbGFuZS54ID0gLWRpcmVjdGlvbjIueDsKICAgICAgICBwbGFuZS55ID0gLWRpcmVjdGlvbjIueTsKICAgICAgICBwbGFuZS56ID0gLWRpcmVjdGlvbjIuejsKICAgICAgICBwbGFuZS53ID0gLUNhcnRlc2lhbjNfZGVmYXVsdC5kb3QoQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShkaXJlY3Rpb24yLCBuZWdhdGVTY3JhdGNoKSwgcG9pbnQpOwogICAgICAgIHJldHVybiB0aGlzLl9jdWxsaW5nVm9sdW1lOwogICAgICB9OwogICAgICBPcnRob2dyYXBoaWNPZmZDZW50ZXJGcnVzdHVtLnByb3RvdHlwZS5nZXRQaXhlbERpbWVuc2lvbnMgPSBmdW5jdGlvbihkcmF3aW5nQnVmZmVyV2lkdGgsIGRyYXdpbmdCdWZmZXJIZWlnaHQsIGRpc3RhbmNlLCBwaXhlbFJhdGlvLCByZXN1bHQpIHsKICAgICAgICB1cGRhdGUodGhpcyk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZHJhd2luZ0J1ZmZlcldpZHRoKSB8fCAhZGVmaW5lZF9kZWZhdWx0KGRyYXdpbmdCdWZmZXJIZWlnaHQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgIkJvdGggZHJhd2luZ0J1ZmZlcldpZHRoIGFuZCBkcmF3aW5nQnVmZmVySGVpZ2h0IGFyZSByZXF1aXJlZC4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBpZiAoZHJhd2luZ0J1ZmZlcldpZHRoIDw9IDApIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJkcmF3aW5nQnVmZmVyV2lkdGggbXVzdCBiZSBncmVhdGVyIHRoYW4gemVyby4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKGRyYXdpbmdCdWZmZXJIZWlnaHQgPD0gMCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImRyYXdpbmdCdWZmZXJIZWlnaHQgbXVzdCBiZSBncmVhdGVyIHRoYW4gemVyby4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZGlzdGFuY2UpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZGlzdGFuY2UgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBpeGVsUmF0aW8pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicGl4ZWxSYXRpbyBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKHBpeGVsUmF0aW8gPD0gMCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInBpeGVsUmF0aW8gbXVzdCBiZSBncmVhdGVyIHRoYW4gemVyby4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIkEgcmVzdWx0IG9iamVjdCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZnJ1c3R1bVdpZHRoID0gdGhpcy5yaWdodCAtIHRoaXMubGVmdDsKICAgICAgICBjb25zdCBmcnVzdHVtSGVpZ2h0ID0gdGhpcy50b3AgLSB0aGlzLmJvdHRvbTsKICAgICAgICBjb25zdCBwaXhlbFdpZHRoID0gcGl4ZWxSYXRpbyAqIGZydXN0dW1XaWR0aCAvIGRyYXdpbmdCdWZmZXJXaWR0aDsKICAgICAgICBjb25zdCBwaXhlbEhlaWdodCA9IHBpeGVsUmF0aW8gKiBmcnVzdHVtSGVpZ2h0IC8gZHJhd2luZ0J1ZmZlckhlaWdodDsKICAgICAgICByZXN1bHQueCA9IHBpeGVsV2lkdGg7CiAgICAgICAgcmVzdWx0LnkgPSBwaXhlbEhlaWdodDsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBPcnRob2dyYXBoaWNPZmZDZW50ZXJGcnVzdHVtLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBPcnRob2dyYXBoaWNPZmZDZW50ZXJGcnVzdHVtKCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5sZWZ0ID0gdGhpcy5sZWZ0OwogICAgICAgIHJlc3VsdC5yaWdodCA9IHRoaXMucmlnaHQ7CiAgICAgICAgcmVzdWx0LnRvcCA9IHRoaXMudG9wOwogICAgICAgIHJlc3VsdC5ib3R0b20gPSB0aGlzLmJvdHRvbTsKICAgICAgICByZXN1bHQubmVhciA9IHRoaXMubmVhcjsKICAgICAgICByZXN1bHQuZmFyID0gdGhpcy5mYXI7CiAgICAgICAgcmVzdWx0Ll9sZWZ0ID0gdm9pZCAwOwogICAgICAgIHJlc3VsdC5fcmlnaHQgPSB2b2lkIDA7CiAgICAgICAgcmVzdWx0Ll90b3AgPSB2b2lkIDA7CiAgICAgICAgcmVzdWx0Ll9ib3R0b20gPSB2b2lkIDA7CiAgICAgICAgcmVzdWx0Ll9uZWFyID0gdm9pZCAwOwogICAgICAgIHJlc3VsdC5fZmFyID0gdm9pZCAwOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE9ydGhvZ3JhcGhpY09mZkNlbnRlckZydXN0dW0ucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uKG90aGVyKSB7CiAgICAgICAgcmV0dXJuIGRlZmluZWRfZGVmYXVsdChvdGhlcikgJiYgb3RoZXIgaW5zdGFuY2VvZiBPcnRob2dyYXBoaWNPZmZDZW50ZXJGcnVzdHVtICYmIHRoaXMucmlnaHQgPT09IG90aGVyLnJpZ2h0ICYmIHRoaXMubGVmdCA9PT0gb3RoZXIubGVmdCAmJiB0aGlzLnRvcCA9PT0gb3RoZXIudG9wICYmIHRoaXMuYm90dG9tID09PSBvdGhlci5ib3R0b20gJiYgdGhpcy5uZWFyID09PSBvdGhlci5uZWFyICYmIHRoaXMuZmFyID09PSBvdGhlci5mYXI7CiAgICAgIH07CiAgICAgIE9ydGhvZ3JhcGhpY09mZkNlbnRlckZydXN0dW0ucHJvdG90eXBlLmVxdWFsc0Vwc2lsb24gPSBmdW5jdGlvbihvdGhlciwgcmVsYXRpdmVFcHNpbG9uLCBhYnNvbHV0ZUVwc2lsb24pIHsKICAgICAgICByZXR1cm4gb3RoZXIgPT09IHRoaXMgfHwgZGVmaW5lZF9kZWZhdWx0KG90aGVyKSAmJiBvdGhlciBpbnN0YW5jZW9mIE9ydGhvZ3JhcGhpY09mZkNlbnRlckZydXN0dW0gJiYgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICB0aGlzLnJpZ2h0LAogICAgICAgICAgb3RoZXIucmlnaHQsCiAgICAgICAgICByZWxhdGl2ZUVwc2lsb24sCiAgICAgICAgICBhYnNvbHV0ZUVwc2lsb24KICAgICAgICApICYmIE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgdGhpcy5sZWZ0LAogICAgICAgICAgb3RoZXIubGVmdCwKICAgICAgICAgIHJlbGF0aXZlRXBzaWxvbiwKICAgICAgICAgIGFic29sdXRlRXBzaWxvbgogICAgICAgICkgJiYgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICB0aGlzLnRvcCwKICAgICAgICAgIG90aGVyLnRvcCwKICAgICAgICAgIHJlbGF0aXZlRXBzaWxvbiwKICAgICAgICAgIGFic29sdXRlRXBzaWxvbgogICAgICAgICkgJiYgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICB0aGlzLmJvdHRvbSwKICAgICAgICAgIG90aGVyLmJvdHRvbSwKICAgICAgICAgIHJlbGF0aXZlRXBzaWxvbiwKICAgICAgICAgIGFic29sdXRlRXBzaWxvbgogICAgICAgICkgJiYgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICB0aGlzLm5lYXIsCiAgICAgICAgICBvdGhlci5uZWFyLAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKSAmJiBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIHRoaXMuZmFyLAogICAgICAgICAgb3RoZXIuZmFyLAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKTsKICAgICAgfTsKICAgICAgT3J0aG9ncmFwaGljT2ZmQ2VudGVyRnJ1c3R1bV9kZWZhdWx0ID0gT3J0aG9ncmFwaGljT2ZmQ2VudGVyRnJ1c3R1bTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL09ydGhvZ3JhcGhpY0ZydXN0dW0uanMKICBmdW5jdGlvbiBPcnRob2dyYXBoaWNGcnVzdHVtKG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIHRoaXMuX29mZkNlbnRlckZydXN0dW0gPSBuZXcgT3J0aG9ncmFwaGljT2ZmQ2VudGVyRnJ1c3R1bV9kZWZhdWx0KCk7CiAgICB0aGlzLndpZHRoID0gb3B0aW9ucy53aWR0aDsKICAgIHRoaXMuX3dpZHRoID0gdm9pZCAwOwogICAgdGhpcy5hc3BlY3RSYXRpbyA9IG9wdGlvbnMuYXNwZWN0UmF0aW87CiAgICB0aGlzLl9hc3BlY3RSYXRpbyA9IHZvaWQgMDsKICAgIHRoaXMubmVhciA9IG9wdGlvbnMubmVhciA/PyAxOwogICAgdGhpcy5fbmVhciA9IHRoaXMubmVhcjsKICAgIHRoaXMuZmFyID0gb3B0aW9ucy5mYXIgPz8gNWU4OwogICAgdGhpcy5fZmFyID0gdGhpcy5mYXI7CiAgfQogIGZ1bmN0aW9uIHVwZGF0ZTIoZnJ1c3R1bSkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZnJ1c3R1bS53aWR0aCkgfHwgIWRlZmluZWRfZGVmYXVsdChmcnVzdHVtLmFzcGVjdFJhdGlvKSB8fCAhZGVmaW5lZF9kZWZhdWx0KGZydXN0dW0ubmVhcikgfHwgIWRlZmluZWRfZGVmYXVsdChmcnVzdHVtLmZhcikpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgIndpZHRoLCBhc3BlY3RSYXRpbywgbmVhciwgb3IgZmFyIHBhcmFtZXRlcnMgYXJlIG5vdCBzZXQuIgogICAgICApOwogICAgfQogICAgY29uc3QgZiA9IGZydXN0dW0uX29mZkNlbnRlckZydXN0dW07CiAgICBpZiAoZnJ1c3R1bS53aWR0aCAhPT0gZnJ1c3R1bS5fd2lkdGggfHwgZnJ1c3R1bS5hc3BlY3RSYXRpbyAhPT0gZnJ1c3R1bS5fYXNwZWN0UmF0aW8gfHwgZnJ1c3R1bS5uZWFyICE9PSBmcnVzdHVtLl9uZWFyIHx8IGZydXN0dW0uZmFyICE9PSBmcnVzdHVtLl9mYXIpIHsKICAgICAgaWYgKGZydXN0dW0uYXNwZWN0UmF0aW8gPCAwKSB7CiAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFzcGVjdFJhdGlvIG11c3QgYmUgcG9zaXRpdmUuIik7CiAgICAgIH0KICAgICAgaWYgKGZydXN0dW0ubmVhciA8IDAgfHwgZnJ1c3R1bS5uZWFyID4gZnJ1c3R1bS5mYXIpIHsKICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICJuZWFyIG11c3QgYmUgZ3JlYXRlciB0aGFuIHplcm8gYW5kIGxlc3MgdGhhbiBmYXIuIgogICAgICAgICk7CiAgICAgIH0KICAgICAgZnJ1c3R1bS5fYXNwZWN0UmF0aW8gPSBmcnVzdHVtLmFzcGVjdFJhdGlvOwogICAgICBmcnVzdHVtLl93aWR0aCA9IGZydXN0dW0ud2lkdGg7CiAgICAgIGZydXN0dW0uX25lYXIgPSBmcnVzdHVtLm5lYXI7CiAgICAgIGZydXN0dW0uX2ZhciA9IGZydXN0dW0uZmFyOwogICAgICBjb25zdCByYXRpbyA9IDEgLyBmcnVzdHVtLmFzcGVjdFJhdGlvOwogICAgICBmLnJpZ2h0ID0gZnJ1c3R1bS53aWR0aCAqIDAuNTsKICAgICAgZi5sZWZ0ID0gLWYucmlnaHQ7CiAgICAgIGYudG9wID0gcmF0aW8gKiBmLnJpZ2h0OwogICAgICBmLmJvdHRvbSA9IC1mLnRvcDsKICAgICAgZi5uZWFyID0gZnJ1c3R1bS5uZWFyOwogICAgICBmLmZhciA9IGZydXN0dW0uZmFyOwogICAgfQogIH0KICB2YXIgT3J0aG9ncmFwaGljRnJ1c3R1bV9kZWZhdWx0OwogIHZhciBpbml0X09ydGhvZ3JhcGhpY0ZydXN0dW0gPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL09ydGhvZ3JhcGhpY0ZydXN0dW0uanMiKCkgewogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X09ydGhvZ3JhcGhpY09mZkNlbnRlckZydXN0dW0oKTsKICAgICAgT3J0aG9ncmFwaGljRnJ1c3R1bS5wYWNrZWRMZW5ndGggPSA0OwogICAgICBPcnRob2dyYXBoaWNGcnVzdHVtLnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUud2lkdGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLmFzcGVjdFJhdGlvOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5uZWFyOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXhdID0gdmFsdWUuZmFyOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgT3J0aG9ncmFwaGljRnJ1c3R1bS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBPcnRob2dyYXBoaWNGcnVzdHVtKCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC53aWR0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LmFzcGVjdFJhdGlvID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHQubmVhciA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LmZhciA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKE9ydGhvZ3JhcGhpY0ZydXN0dW0ucHJvdG90eXBlLCB7CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgb3J0aG9ncmFwaGljIHByb2plY3Rpb24gbWF0cml4IGNvbXB1dGVkIGZyb20gdGhlIHZpZXcgZnJ1c3R1bS4KICAgICAgICAgKiBAbWVtYmVyb2YgT3J0aG9ncmFwaGljRnJ1c3R1bS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7TWF0cml4NH0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBwcm9qZWN0aW9uTWF0cml4OiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICB1cGRhdGUyKHRoaXMpOwogICAgICAgICAgICByZXR1cm4gdGhpcy5fb2ZmQ2VudGVyRnJ1c3R1bS5wcm9qZWN0aW9uTWF0cml4OwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgb3J0aG9ncmFwaGljIHByb2plY3Rpb24gbWF0cml4IGNvbXB1dGVkIGZyb20gdGhlIHZpZXcgZnJ1c3R1bS4KICAgICAgICAgKiBAbWVtYmVyb2YgT3J0aG9ncmFwaGljRnJ1c3R1bS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7T3J0aG9ncmFwaGljT2ZmQ2VudGVyRnJ1c3R1bX0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKiBAcHJpdmF0ZQogICAgICAgICAqLwogICAgICAgIG9mZkNlbnRlckZydXN0dW06IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHVwZGF0ZTIodGhpcyk7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vZmZDZW50ZXJGcnVzdHVtOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIE9ydGhvZ3JhcGhpY0ZydXN0dW0ucHJvdG90eXBlLmNvbXB1dGVDdWxsaW5nVm9sdW1lID0gZnVuY3Rpb24ocG9zaXRpb24sIGRpcmVjdGlvbjIsIHVwKSB7CiAgICAgICAgdXBkYXRlMih0aGlzKTsKICAgICAgICByZXR1cm4gdGhpcy5fb2ZmQ2VudGVyRnJ1c3R1bS5jb21wdXRlQ3VsbGluZ1ZvbHVtZShwb3NpdGlvbiwgZGlyZWN0aW9uMiwgdXApOwogICAgICB9OwogICAgICBPcnRob2dyYXBoaWNGcnVzdHVtLnByb3RvdHlwZS5nZXRQaXhlbERpbWVuc2lvbnMgPSBmdW5jdGlvbihkcmF3aW5nQnVmZmVyV2lkdGgsIGRyYXdpbmdCdWZmZXJIZWlnaHQsIGRpc3RhbmNlLCBwaXhlbFJhdGlvLCByZXN1bHQpIHsKICAgICAgICB1cGRhdGUyKHRoaXMpOwogICAgICAgIHJldHVybiB0aGlzLl9vZmZDZW50ZXJGcnVzdHVtLmdldFBpeGVsRGltZW5zaW9ucygKICAgICAgICAgIGRyYXdpbmdCdWZmZXJXaWR0aCwKICAgICAgICAgIGRyYXdpbmdCdWZmZXJIZWlnaHQsCiAgICAgICAgICBkaXN0YW5jZSwKICAgICAgICAgIHBpeGVsUmF0aW8sCiAgICAgICAgICByZXN1bHQKICAgICAgICApOwogICAgICB9OwogICAgICBPcnRob2dyYXBoaWNGcnVzdHVtLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBPcnRob2dyYXBoaWNGcnVzdHVtKCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5hc3BlY3RSYXRpbyA9IHRoaXMuYXNwZWN0UmF0aW87CiAgICAgICAgcmVzdWx0LndpZHRoID0gdGhpcy53aWR0aDsKICAgICAgICByZXN1bHQubmVhciA9IHRoaXMubmVhcjsKICAgICAgICByZXN1bHQuZmFyID0gdGhpcy5mYXI7CiAgICAgICAgcmVzdWx0Ll9hc3BlY3RSYXRpbyA9IHZvaWQgMDsKICAgICAgICByZXN1bHQuX3dpZHRoID0gdm9pZCAwOwogICAgICAgIHJlc3VsdC5fbmVhciA9IHZvaWQgMDsKICAgICAgICByZXN1bHQuX2ZhciA9IHZvaWQgMDsKICAgICAgICB0aGlzLl9vZmZDZW50ZXJGcnVzdHVtLmNsb25lKHJlc3VsdC5fb2ZmQ2VudGVyRnJ1c3R1bSk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgT3J0aG9ncmFwaGljRnJ1c3R1bS5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24ob3RoZXIpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChvdGhlcikgfHwgIShvdGhlciBpbnN0YW5jZW9mIE9ydGhvZ3JhcGhpY0ZydXN0dW0pKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHVwZGF0ZTIodGhpcyk7CiAgICAgICAgdXBkYXRlMihvdGhlcik7CiAgICAgICAgcmV0dXJuIHRoaXMud2lkdGggPT09IG90aGVyLndpZHRoICYmIHRoaXMuYXNwZWN0UmF0aW8gPT09IG90aGVyLmFzcGVjdFJhdGlvICYmIHRoaXMuX29mZkNlbnRlckZydXN0dW0uZXF1YWxzKG90aGVyLl9vZmZDZW50ZXJGcnVzdHVtKTsKICAgICAgfTsKICAgICAgT3J0aG9ncmFwaGljRnJ1c3R1bS5wcm90b3R5cGUuZXF1YWxzRXBzaWxvbiA9IGZ1bmN0aW9uKG90aGVyLCByZWxhdGl2ZUVwc2lsb24sIGFic29sdXRlRXBzaWxvbikgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG90aGVyKSB8fCAhKG90aGVyIGluc3RhbmNlb2YgT3J0aG9ncmFwaGljRnJ1c3R1bSkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgdXBkYXRlMih0aGlzKTsKICAgICAgICB1cGRhdGUyKG90aGVyKTsKICAgICAgICByZXR1cm4gTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICB0aGlzLndpZHRoLAogICAgICAgICAgb3RoZXIud2lkdGgsCiAgICAgICAgICByZWxhdGl2ZUVwc2lsb24sCiAgICAgICAgICBhYnNvbHV0ZUVwc2lsb24KICAgICAgICApICYmIE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgdGhpcy5hc3BlY3RSYXRpbywKICAgICAgICAgIG90aGVyLmFzcGVjdFJhdGlvLAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKSAmJiB0aGlzLl9vZmZDZW50ZXJGcnVzdHVtLmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICBvdGhlci5fb2ZmQ2VudGVyRnJ1c3R1bSwKICAgICAgICAgIHJlbGF0aXZlRXBzaWxvbiwKICAgICAgICAgIGFic29sdXRlRXBzaWxvbgogICAgICAgICk7CiAgICAgIH07CiAgICAgIE9ydGhvZ3JhcGhpY0ZydXN0dW1fZGVmYXVsdCA9IE9ydGhvZ3JhcGhpY0ZydXN0dW07CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9QZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW0uanMKICBmdW5jdGlvbiBQZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW0ob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgdGhpcy5sZWZ0ID0gb3B0aW9ucy5sZWZ0OwogICAgdGhpcy5fbGVmdCA9IHZvaWQgMDsKICAgIHRoaXMucmlnaHQgPSBvcHRpb25zLnJpZ2h0OwogICAgdGhpcy5fcmlnaHQgPSB2b2lkIDA7CiAgICB0aGlzLnRvcCA9IG9wdGlvbnMudG9wOwogICAgdGhpcy5fdG9wID0gdm9pZCAwOwogICAgdGhpcy5ib3R0b20gPSBvcHRpb25zLmJvdHRvbTsKICAgIHRoaXMuX2JvdHRvbSA9IHZvaWQgMDsKICAgIHRoaXMubmVhciA9IG9wdGlvbnMubmVhciA/PyAxOwogICAgdGhpcy5fbmVhciA9IHRoaXMubmVhcjsKICAgIHRoaXMuZmFyID0gb3B0aW9ucy5mYXIgPz8gNWU4OwogICAgdGhpcy5fZmFyID0gdGhpcy5mYXI7CiAgICB0aGlzLl9jdWxsaW5nVm9sdW1lID0gbmV3IEN1bGxpbmdWb2x1bWVfZGVmYXVsdCgpOwogICAgdGhpcy5fcGVyc3BlY3RpdmVNYXRyaXggPSBuZXcgTWF0cml4NF9kZWZhdWx0KCk7CiAgICB0aGlzLl9pbmZpbml0ZVBlcnNwZWN0aXZlID0gbmV3IE1hdHJpeDRfZGVmYXVsdCgpOwogIH0KICBmdW5jdGlvbiB1cGRhdGUzKGZydXN0dW0pIHsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGZydXN0dW0ucmlnaHQpIHx8ICFkZWZpbmVkX2RlZmF1bHQoZnJ1c3R1bS5sZWZ0KSB8fCAhZGVmaW5lZF9kZWZhdWx0KGZydXN0dW0udG9wKSB8fCAhZGVmaW5lZF9kZWZhdWx0KGZydXN0dW0uYm90dG9tKSB8fCAhZGVmaW5lZF9kZWZhdWx0KGZydXN0dW0ubmVhcikgfHwgIWRlZmluZWRfZGVmYXVsdChmcnVzdHVtLmZhcikpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgInJpZ2h0LCBsZWZ0LCB0b3AsIGJvdHRvbSwgbmVhciwgb3IgZmFyIHBhcmFtZXRlcnMgYXJlIG5vdCBzZXQuIgogICAgICApOwogICAgfQogICAgY29uc3QgeyB0b3AsIGJvdHRvbSwgcmlnaHQsIGxlZnQsIG5lYXIsIGZhciB9ID0gZnJ1c3R1bTsKICAgIGNvbnN0IGNoYW5nZWQgPSB0b3AgIT09IGZydXN0dW0uX3RvcCB8fCBib3R0b20gIT09IGZydXN0dW0uX2JvdHRvbSB8fCBsZWZ0ICE9PSBmcnVzdHVtLl9sZWZ0IHx8IHJpZ2h0ICE9PSBmcnVzdHVtLl9yaWdodCB8fCBuZWFyICE9PSBmcnVzdHVtLl9uZWFyIHx8IGZhciAhPT0gZnJ1c3R1bS5fZmFyOwogICAgaWYgKCFjaGFuZ2VkKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChmcnVzdHVtLm5lYXIgPD0gMCB8fCBmcnVzdHVtLm5lYXIgPiBmcnVzdHVtLmZhcikgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAibmVhciBtdXN0IGJlIGdyZWF0ZXIgdGhhbiB6ZXJvIGFuZCBsZXNzIHRoYW4gZmFyLiIKICAgICAgKTsKICAgIH0KICAgIGZydXN0dW0uX2xlZnQgPSBsZWZ0OwogICAgZnJ1c3R1bS5fcmlnaHQgPSByaWdodDsKICAgIGZydXN0dW0uX3RvcCA9IHRvcDsKICAgIGZydXN0dW0uX2JvdHRvbSA9IGJvdHRvbTsKICAgIGZydXN0dW0uX25lYXIgPSBuZWFyOwogICAgZnJ1c3R1bS5fZmFyID0gZmFyOwogICAgZnJ1c3R1bS5fcGVyc3BlY3RpdmVNYXRyaXggPSBNYXRyaXg0X2RlZmF1bHQuY29tcHV0ZVBlcnNwZWN0aXZlT2ZmQ2VudGVyKAogICAgICBsZWZ0LAogICAgICByaWdodCwKICAgICAgYm90dG9tLAogICAgICB0b3AsCiAgICAgIG5lYXIsCiAgICAgIGZhciwKICAgICAgZnJ1c3R1bS5fcGVyc3BlY3RpdmVNYXRyaXgKICAgICk7CiAgICBmcnVzdHVtLl9pbmZpbml0ZVBlcnNwZWN0aXZlID0gTWF0cml4NF9kZWZhdWx0LmNvbXB1dGVJbmZpbml0ZVBlcnNwZWN0aXZlT2ZmQ2VudGVyKAogICAgICBsZWZ0LAogICAgICByaWdodCwKICAgICAgYm90dG9tLAogICAgICB0b3AsCiAgICAgIG5lYXIsCiAgICAgIGZydXN0dW0uX2luZmluaXRlUGVyc3BlY3RpdmUKICAgICk7CiAgfQogIHZhciBnZXRQbGFuZXNSaWdodDIsIGdldFBsYW5lc05lYXJDZW50ZXIyLCBnZXRQbGFuZXNGYXJDZW50ZXIsIGdldFBsYW5lc05vcm1hbCwgUGVyc3BlY3RpdmVPZmZDZW50ZXJGcnVzdHVtX2RlZmF1bHQ7CiAgdmFyIGluaXRfUGVyc3BlY3RpdmVPZmZDZW50ZXJGcnVzdHVtID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9QZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW0uanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW40KCk7CiAgICAgIGluaXRfQ3VsbGluZ1ZvbHVtZSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9NYXRyaXg0KCk7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKFBlcnNwZWN0aXZlT2ZmQ2VudGVyRnJ1c3R1bS5wcm90b3R5cGUsIHsKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBwZXJzcGVjdGl2ZSBwcm9qZWN0aW9uIG1hdHJpeCBjb21wdXRlZCBmcm9tIHRoZSB2aWV3IGZydXN0dW0uCiAgICAgICAgICogVGhlIHByb2plY3Rpb24gbWF0cml4IHdpbGwgYmUgcmVjb21wdXRlZCBpZiBhbnkgZnJ1c3R1bSBwYXJhbWV0ZXJzIGhhdmUgY2hhbmdlZC4KICAgICAgICAgKgogICAgICAgICAqIEBtZW1iZXJvZiBQZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW0ucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge01hdHJpeDR9CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICoKICAgICAgICAgKiBAc2VlIFBlcnNwZWN0aXZlT2ZmQ2VudGVyRnJ1c3R1bSNpbmZpbml0ZVByb2plY3Rpb25NYXRyaXgKICAgICAgICAgKi8KICAgICAgICBwcm9qZWN0aW9uTWF0cml4OiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICB1cGRhdGUzKHRoaXMpOwogICAgICAgICAgICByZXR1cm4gdGhpcy5fcGVyc3BlY3RpdmVNYXRyaXg7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBwZXJzcGVjdGl2ZSBwcm9qZWN0aW9uIG1hdHJpeCBjb21wdXRlZCBmcm9tIHRoZSB2aWV3IGZydXN0dW0gd2l0aCBhbiBpbmZpbml0ZSBmYXIgcGxhbmUuCiAgICAgICAgICogQG1lbWJlcm9mIFBlcnNwZWN0aXZlT2ZmQ2VudGVyRnJ1c3R1bS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7TWF0cml4NH0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKgogICAgICAgICAqIEBzZWUgUGVyc3BlY3RpdmVPZmZDZW50ZXJGcnVzdHVtI3Byb2plY3Rpb25NYXRyaXgKICAgICAgICAgKi8KICAgICAgICBpbmZpbml0ZVByb2plY3Rpb25NYXRyaXg6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHVwZGF0ZTModGhpcyk7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9pbmZpbml0ZVBlcnNwZWN0aXZlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIGdldFBsYW5lc1JpZ2h0MiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZ2V0UGxhbmVzTmVhckNlbnRlcjIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGdldFBsYW5lc0ZhckNlbnRlciA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZ2V0UGxhbmVzTm9ybWFsID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBQZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW0ucHJvdG90eXBlLmNvbXB1dGVDdWxsaW5nVm9sdW1lID0gZnVuY3Rpb24ocG9zaXRpb24sIGRpcmVjdGlvbjIsIHVwKSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocG9zaXRpb24pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicG9zaXRpb24gaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGRpcmVjdGlvbjIpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZGlyZWN0aW9uIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh1cCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ1cCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcGxhbmVzID0gdGhpcy5fY3VsbGluZ1ZvbHVtZS5wbGFuZXM7CiAgICAgICAgY29uc3QgdCA9IHRoaXMudG9wOwogICAgICAgIGNvbnN0IGIgPSB0aGlzLmJvdHRvbTsKICAgICAgICBjb25zdCByID0gdGhpcy5yaWdodDsKICAgICAgICBjb25zdCBsID0gdGhpcy5sZWZ0OwogICAgICAgIGNvbnN0IG4gPSB0aGlzLm5lYXI7CiAgICAgICAgY29uc3QgZiA9IHRoaXMuZmFyOwogICAgICAgIGNvbnN0IHJpZ2h0ID0gQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKGRpcmVjdGlvbjIsIHVwLCBnZXRQbGFuZXNSaWdodDIpOwogICAgICAgIGNvbnN0IG5lYXJDZW50ZXIgPSBnZXRQbGFuZXNOZWFyQ2VudGVyMjsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihkaXJlY3Rpb24yLCBuLCBuZWFyQ2VudGVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHBvc2l0aW9uLCBuZWFyQ2VudGVyLCBuZWFyQ2VudGVyKTsKICAgICAgICBjb25zdCBmYXJDZW50ZXIgPSBnZXRQbGFuZXNGYXJDZW50ZXI7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoZGlyZWN0aW9uMiwgZiwgZmFyQ2VudGVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHBvc2l0aW9uLCBmYXJDZW50ZXIsIGZhckNlbnRlcik7CiAgICAgICAgY29uc3Qgbm9ybWFsMiA9IGdldFBsYW5lc05vcm1hbDsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihyaWdodCwgbCwgbm9ybWFsMik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChuZWFyQ2VudGVyLCBub3JtYWwyLCBub3JtYWwyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3Qobm9ybWFsMiwgcG9zaXRpb24sIG5vcm1hbDIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUobm9ybWFsMiwgbm9ybWFsMik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKG5vcm1hbDIsIHVwLCBub3JtYWwyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKG5vcm1hbDIsIG5vcm1hbDIpOwogICAgICAgIGxldCBwbGFuZSA9IHBsYW5lc1swXTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwbGFuZSkpIHsKICAgICAgICAgIHBsYW5lID0gcGxhbmVzWzBdID0gbmV3IENhcnRlc2lhbjRfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICBwbGFuZS54ID0gbm9ybWFsMi54OwogICAgICAgIHBsYW5lLnkgPSBub3JtYWwyLnk7CiAgICAgICAgcGxhbmUueiA9IG5vcm1hbDIuejsKICAgICAgICBwbGFuZS53ID0gLUNhcnRlc2lhbjNfZGVmYXVsdC5kb3Qobm9ybWFsMiwgcG9zaXRpb24pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKHJpZ2h0LCByLCBub3JtYWwyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKG5lYXJDZW50ZXIsIG5vcm1hbDIsIG5vcm1hbDIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChub3JtYWwyLCBwb3NpdGlvbiwgbm9ybWFsMik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKHVwLCBub3JtYWwyLCBub3JtYWwyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKG5vcm1hbDIsIG5vcm1hbDIpOwogICAgICAgIHBsYW5lID0gcGxhbmVzWzFdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBsYW5lKSkgewogICAgICAgICAgcGxhbmUgPSBwbGFuZXNbMV0gPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIHBsYW5lLnggPSBub3JtYWwyLng7CiAgICAgICAgcGxhbmUueSA9IG5vcm1hbDIueTsKICAgICAgICBwbGFuZS56ID0gbm9ybWFsMi56OwogICAgICAgIHBsYW5lLncgPSAtQ2FydGVzaWFuM19kZWZhdWx0LmRvdChub3JtYWwyLCBwb3NpdGlvbik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIodXAsIGIsIG5vcm1hbDIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQobmVhckNlbnRlciwgbm9ybWFsMiwgbm9ybWFsMik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KG5vcm1hbDIsIHBvc2l0aW9uLCBub3JtYWwyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MocmlnaHQsIG5vcm1hbDIsIG5vcm1hbDIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUobm9ybWFsMiwgbm9ybWFsMik7CiAgICAgICAgcGxhbmUgPSBwbGFuZXNbMl07CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocGxhbmUpKSB7CiAgICAgICAgICBwbGFuZSA9IHBsYW5lc1syXSA9IG5ldyBDYXJ0ZXNpYW40X2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgcGxhbmUueCA9IG5vcm1hbDIueDsKICAgICAgICBwbGFuZS55ID0gbm9ybWFsMi55OwogICAgICAgIHBsYW5lLnogPSBub3JtYWwyLno7CiAgICAgICAgcGxhbmUudyA9IC1DYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KG5vcm1hbDIsIHBvc2l0aW9uKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcih1cCwgdCwgbm9ybWFsMik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChuZWFyQ2VudGVyLCBub3JtYWwyLCBub3JtYWwyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3Qobm9ybWFsMiwgcG9zaXRpb24sIG5vcm1hbDIpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhub3JtYWwyLCByaWdodCwgbm9ybWFsMik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShub3JtYWwyLCBub3JtYWwyKTsKICAgICAgICBwbGFuZSA9IHBsYW5lc1szXTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwbGFuZSkpIHsKICAgICAgICAgIHBsYW5lID0gcGxhbmVzWzNdID0gbmV3IENhcnRlc2lhbjRfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICBwbGFuZS54ID0gbm9ybWFsMi54OwogICAgICAgIHBsYW5lLnkgPSBub3JtYWwyLnk7CiAgICAgICAgcGxhbmUueiA9IG5vcm1hbDIuejsKICAgICAgICBwbGFuZS53ID0gLUNhcnRlc2lhbjNfZGVmYXVsdC5kb3Qobm9ybWFsMiwgcG9zaXRpb24pOwogICAgICAgIHBsYW5lID0gcGxhbmVzWzRdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBsYW5lKSkgewogICAgICAgICAgcGxhbmUgPSBwbGFuZXNbNF0gPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIHBsYW5lLnggPSBkaXJlY3Rpb24yLng7CiAgICAgICAgcGxhbmUueSA9IGRpcmVjdGlvbjIueTsKICAgICAgICBwbGFuZS56ID0gZGlyZWN0aW9uMi56OwogICAgICAgIHBsYW5lLncgPSAtQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCBuZWFyQ2VudGVyKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKGRpcmVjdGlvbjIsIG5vcm1hbDIpOwogICAgICAgIHBsYW5lID0gcGxhbmVzWzVdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBsYW5lKSkgewogICAgICAgICAgcGxhbmUgPSBwbGFuZXNbNV0gPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIHBsYW5lLnggPSBub3JtYWwyLng7CiAgICAgICAgcGxhbmUueSA9IG5vcm1hbDIueTsKICAgICAgICBwbGFuZS56ID0gbm9ybWFsMi56OwogICAgICAgIHBsYW5lLncgPSAtQ2FydGVzaWFuM19kZWZhdWx0LmRvdChub3JtYWwyLCBmYXJDZW50ZXIpOwogICAgICAgIHJldHVybiB0aGlzLl9jdWxsaW5nVm9sdW1lOwogICAgICB9OwogICAgICBQZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW0ucHJvdG90eXBlLmdldFBpeGVsRGltZW5zaW9ucyA9IGZ1bmN0aW9uKGRyYXdpbmdCdWZmZXJXaWR0aCwgZHJhd2luZ0J1ZmZlckhlaWdodCwgZGlzdGFuY2UsIHBpeGVsUmF0aW8sIHJlc3VsdCkgewogICAgICAgIHVwZGF0ZTModGhpcyk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZHJhd2luZ0J1ZmZlcldpZHRoKSB8fCAhZGVmaW5lZF9kZWZhdWx0KGRyYXdpbmdCdWZmZXJIZWlnaHQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgIkJvdGggZHJhd2luZ0J1ZmZlcldpZHRoIGFuZCBkcmF3aW5nQnVmZmVySGVpZ2h0IGFyZSByZXF1aXJlZC4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBpZiAoZHJhd2luZ0J1ZmZlcldpZHRoIDw9IDApIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJkcmF3aW5nQnVmZmVyV2lkdGggbXVzdCBiZSBncmVhdGVyIHRoYW4gemVyby4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKGRyYXdpbmdCdWZmZXJIZWlnaHQgPD0gMCkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImRyYXdpbmdCdWZmZXJIZWlnaHQgbXVzdCBiZSBncmVhdGVyIHRoYW4gemVyby4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZGlzdGFuY2UpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiZGlzdGFuY2UgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBpeGVsUmF0aW8pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicGl4ZWxSYXRpbyBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBpZiAocGl4ZWxSYXRpbyA8PSAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicGl4ZWxSYXRpbyBtdXN0IGJlIGdyZWF0ZXIgdGhhbiB6ZXJvLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiQSByZXN1bHQgb2JqZWN0IGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBpbnZlcnNlTmVhciA9IDEgLyB0aGlzLm5lYXI7CiAgICAgICAgbGV0IHRhblRoZXRhID0gdGhpcy50b3AgKiBpbnZlcnNlTmVhcjsKICAgICAgICBjb25zdCBwaXhlbEhlaWdodCA9IDIgKiBwaXhlbFJhdGlvICogZGlzdGFuY2UgKiB0YW5UaGV0YSAvIGRyYXdpbmdCdWZmZXJIZWlnaHQ7CiAgICAgICAgdGFuVGhldGEgPSB0aGlzLnJpZ2h0ICogaW52ZXJzZU5lYXI7CiAgICAgICAgY29uc3QgcGl4ZWxXaWR0aCA9IDIgKiBwaXhlbFJhdGlvICogZGlzdGFuY2UgKiB0YW5UaGV0YSAvIGRyYXdpbmdCdWZmZXJXaWR0aDsKICAgICAgICByZXN1bHQueCA9IHBpeGVsV2lkdGg7CiAgICAgICAgcmVzdWx0LnkgPSBwaXhlbEhlaWdodDsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBQZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW0ucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IFBlcnNwZWN0aXZlT2ZmQ2VudGVyRnJ1c3R1bSgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQucmlnaHQgPSB0aGlzLnJpZ2h0OwogICAgICAgIHJlc3VsdC5sZWZ0ID0gdGhpcy5sZWZ0OwogICAgICAgIHJlc3VsdC50b3AgPSB0aGlzLnRvcDsKICAgICAgICByZXN1bHQuYm90dG9tID0gdGhpcy5ib3R0b207CiAgICAgICAgcmVzdWx0Lm5lYXIgPSB0aGlzLm5lYXI7CiAgICAgICAgcmVzdWx0LmZhciA9IHRoaXMuZmFyOwogICAgICAgIHJlc3VsdC5fbGVmdCA9IHZvaWQgMDsKICAgICAgICByZXN1bHQuX3JpZ2h0ID0gdm9pZCAwOwogICAgICAgIHJlc3VsdC5fdG9wID0gdm9pZCAwOwogICAgICAgIHJlc3VsdC5fYm90dG9tID0gdm9pZCAwOwogICAgICAgIHJlc3VsdC5fbmVhciA9IHZvaWQgMDsKICAgICAgICByZXN1bHQuX2ZhciA9IHZvaWQgMDsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBQZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW0ucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uKG90aGVyKSB7CiAgICAgICAgcmV0dXJuIGRlZmluZWRfZGVmYXVsdChvdGhlcikgJiYgb3RoZXIgaW5zdGFuY2VvZiBQZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW0gJiYgdGhpcy5yaWdodCA9PT0gb3RoZXIucmlnaHQgJiYgdGhpcy5sZWZ0ID09PSBvdGhlci5sZWZ0ICYmIHRoaXMudG9wID09PSBvdGhlci50b3AgJiYgdGhpcy5ib3R0b20gPT09IG90aGVyLmJvdHRvbSAmJiB0aGlzLm5lYXIgPT09IG90aGVyLm5lYXIgJiYgdGhpcy5mYXIgPT09IG90aGVyLmZhcjsKICAgICAgfTsKICAgICAgUGVyc3BlY3RpdmVPZmZDZW50ZXJGcnVzdHVtLnByb3RvdHlwZS5lcXVhbHNFcHNpbG9uID0gZnVuY3Rpb24ob3RoZXIsIHJlbGF0aXZlRXBzaWxvbiwgYWJzb2x1dGVFcHNpbG9uKSB7CiAgICAgICAgcmV0dXJuIG90aGVyID09PSB0aGlzIHx8IGRlZmluZWRfZGVmYXVsdChvdGhlcikgJiYgb3RoZXIgaW5zdGFuY2VvZiBQZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW0gJiYgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICB0aGlzLnJpZ2h0LAogICAgICAgICAgb3RoZXIucmlnaHQsCiAgICAgICAgICByZWxhdGl2ZUVwc2lsb24sCiAgICAgICAgICBhYnNvbHV0ZUVwc2lsb24KICAgICAgICApICYmIE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgdGhpcy5sZWZ0LAogICAgICAgICAgb3RoZXIubGVmdCwKICAgICAgICAgIHJlbGF0aXZlRXBzaWxvbiwKICAgICAgICAgIGFic29sdXRlRXBzaWxvbgogICAgICAgICkgJiYgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICB0aGlzLnRvcCwKICAgICAgICAgIG90aGVyLnRvcCwKICAgICAgICAgIHJlbGF0aXZlRXBzaWxvbiwKICAgICAgICAgIGFic29sdXRlRXBzaWxvbgogICAgICAgICkgJiYgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICB0aGlzLmJvdHRvbSwKICAgICAgICAgIG90aGVyLmJvdHRvbSwKICAgICAgICAgIHJlbGF0aXZlRXBzaWxvbiwKICAgICAgICAgIGFic29sdXRlRXBzaWxvbgogICAgICAgICkgJiYgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICB0aGlzLm5lYXIsCiAgICAgICAgICBvdGhlci5uZWFyLAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKSAmJiBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIHRoaXMuZmFyLAogICAgICAgICAgb3RoZXIuZmFyLAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKTsKICAgICAgfTsKICAgICAgUGVyc3BlY3RpdmVPZmZDZW50ZXJGcnVzdHVtX2RlZmF1bHQgPSBQZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW07CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9QZXJzcGVjdGl2ZUZydXN0dW0uanMKICBmdW5jdGlvbiBQZXJzcGVjdGl2ZUZydXN0dW0ob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgdGhpcy5fb2ZmQ2VudGVyRnJ1c3R1bSA9IG5ldyBQZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW1fZGVmYXVsdCgpOwogICAgdGhpcy5mb3YgPSBvcHRpb25zLmZvdjsKICAgIHRoaXMuX2ZvdiA9IHZvaWQgMDsKICAgIHRoaXMuX2ZvdnkgPSB2b2lkIDA7CiAgICB0aGlzLl9zc2VEZW5vbWluYXRvciA9IHZvaWQgMDsKICAgIHRoaXMuYXNwZWN0UmF0aW8gPSBvcHRpb25zLmFzcGVjdFJhdGlvOwogICAgdGhpcy5fYXNwZWN0UmF0aW8gPSB2b2lkIDA7CiAgICB0aGlzLm5lYXIgPSBvcHRpb25zLm5lYXIgPz8gMTsKICAgIHRoaXMuX25lYXIgPSB0aGlzLm5lYXI7CiAgICB0aGlzLmZhciA9IG9wdGlvbnMuZmFyID8/IDVlODsKICAgIHRoaXMuX2ZhciA9IHRoaXMuZmFyOwogICAgdGhpcy54T2Zmc2V0ID0gb3B0aW9ucy54T2Zmc2V0ID8/IDA7CiAgICB0aGlzLl94T2Zmc2V0ID0gdGhpcy54T2Zmc2V0OwogICAgdGhpcy55T2Zmc2V0ID0gb3B0aW9ucy55T2Zmc2V0ID8/IDA7CiAgICB0aGlzLl95T2Zmc2V0ID0gdGhpcy55T2Zmc2V0OwogIH0KICBmdW5jdGlvbiB1cGRhdGU0KGZydXN0dW0pIHsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGZydXN0dW0uZm92KSB8fCAhZGVmaW5lZF9kZWZhdWx0KGZydXN0dW0uYXNwZWN0UmF0aW8pIHx8ICFkZWZpbmVkX2RlZmF1bHQoZnJ1c3R1bS5uZWFyKSB8fCAhZGVmaW5lZF9kZWZhdWx0KGZydXN0dW0uZmFyKSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAiZm92LCBhc3BlY3RSYXRpbywgbmVhciwgb3IgZmFyIHBhcmFtZXRlcnMgYXJlIG5vdCBzZXQuIgogICAgICApOwogICAgfQogICAgY29uc3QgY2hhbmdlZCA9IGZydXN0dW0uZm92ICE9PSBmcnVzdHVtLl9mb3YgfHwgZnJ1c3R1bS5hc3BlY3RSYXRpbyAhPT0gZnJ1c3R1bS5fYXNwZWN0UmF0aW8gfHwgZnJ1c3R1bS5uZWFyICE9PSBmcnVzdHVtLl9uZWFyIHx8IGZydXN0dW0uZmFyICE9PSBmcnVzdHVtLl9mYXIgfHwgZnJ1c3R1bS54T2Zmc2V0ICE9PSBmcnVzdHVtLl94T2Zmc2V0IHx8IGZydXN0dW0ueU9mZnNldCAhPT0gZnJ1c3R1bS5feU9mZnNldDsKICAgIGlmICghY2hhbmdlZCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygiZm92IiwgZnJ1c3R1bS5mb3YsIDApOwogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuKCJmb3YiLCBmcnVzdHVtLmZvdiwgTWF0aC5QSSk7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIuZ3JlYXRlclRoYW5PckVxdWFscygKICAgICAgImFzcGVjdFJhdGlvIiwKICAgICAgZnJ1c3R1bS5hc3BlY3RSYXRpbywKICAgICAgMAogICAgKTsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5ncmVhdGVyVGhhbk9yRXF1YWxzKCJuZWFyIiwgZnJ1c3R1bS5uZWFyLCAwKTsKICAgIGlmIChmcnVzdHVtLm5lYXIgPiBmcnVzdHVtLmZhcikgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgibmVhciBtdXN0IGJlIGxlc3MgdGhhbiBmYXIuIik7CiAgICB9CiAgICBmcnVzdHVtLl9hc3BlY3RSYXRpbyA9IGZydXN0dW0uYXNwZWN0UmF0aW87CiAgICBmcnVzdHVtLl9mb3YgPSBmcnVzdHVtLmZvdjsKICAgIGZydXN0dW0uX2ZvdnkgPSBmcnVzdHVtLmFzcGVjdFJhdGlvIDw9IDEgPyBmcnVzdHVtLmZvdiA6IE1hdGguYXRhbihNYXRoLnRhbihmcnVzdHVtLmZvdiAqIDAuNSkgLyBmcnVzdHVtLmFzcGVjdFJhdGlvKSAqIDI7CiAgICBmcnVzdHVtLl9uZWFyID0gZnJ1c3R1bS5uZWFyOwogICAgZnJ1c3R1bS5fZmFyID0gZnJ1c3R1bS5mYXI7CiAgICBmcnVzdHVtLl9zc2VEZW5vbWluYXRvciA9IDIgKiBNYXRoLnRhbigwLjUgKiBmcnVzdHVtLl9mb3Z5KTsKICAgIGZydXN0dW0uX3hPZmZzZXQgPSBmcnVzdHVtLnhPZmZzZXQ7CiAgICBmcnVzdHVtLl95T2Zmc2V0ID0gZnJ1c3R1bS55T2Zmc2V0OwogICAgY29uc3QgZiA9IGZydXN0dW0uX29mZkNlbnRlckZydXN0dW07CiAgICBmLnRvcCA9IGZydXN0dW0ubmVhciAqIE1hdGgudGFuKDAuNSAqIGZydXN0dW0uX2ZvdnkpOwogICAgZi5ib3R0b20gPSAtZi50b3A7CiAgICBmLnJpZ2h0ID0gZnJ1c3R1bS5hc3BlY3RSYXRpbyAqIGYudG9wOwogICAgZi5sZWZ0ID0gLWYucmlnaHQ7CiAgICBmLm5lYXIgPSBmcnVzdHVtLm5lYXI7CiAgICBmLmZhciA9IGZydXN0dW0uZmFyOwogICAgZi5yaWdodCArPSBmcnVzdHVtLnhPZmZzZXQ7CiAgICBmLmxlZnQgKz0gZnJ1c3R1bS54T2Zmc2V0OwogICAgZi50b3AgKz0gZnJ1c3R1bS55T2Zmc2V0OwogICAgZi5ib3R0b20gKz0gZnJ1c3R1bS55T2Zmc2V0OwogIH0KICB2YXIgUGVyc3BlY3RpdmVGcnVzdHVtX2RlZmF1bHQ7CiAgdmFyIGluaXRfUGVyc3BlY3RpdmVGcnVzdHVtID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9QZXJzcGVjdGl2ZUZydXN0dW0uanMiKCkgewogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1BlcnNwZWN0aXZlT2ZmQ2VudGVyRnJ1c3R1bSgpOwogICAgICBQZXJzcGVjdGl2ZUZydXN0dW0ucGFja2VkTGVuZ3RoID0gNjsKICAgICAgUGVyc3BlY3RpdmVGcnVzdHVtLnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuZm92OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5hc3BlY3RSYXRpbzsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUubmVhcjsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuZmFyOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS54T2Zmc2V0OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXhdID0gdmFsdWUueU9mZnNldDsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIFBlcnNwZWN0aXZlRnJ1c3R1bS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBQZXJzcGVjdGl2ZUZydXN0dW0oKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LmZvdiA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LmFzcGVjdFJhdGlvID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHQubmVhciA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LmZhciA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LnhPZmZzZXQgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIHJlc3VsdC55T2Zmc2V0ID0gYXJyYXlbc3RhcnRpbmdJbmRleF07CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoUGVyc3BlY3RpdmVGcnVzdHVtLnByb3RvdHlwZSwgewogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIHBlcnNwZWN0aXZlIHByb2plY3Rpb24gbWF0cml4IGNvbXB1dGVkIGZyb20gdGhlIHZpZXcgZnJ1c3R1bS4KICAgICAgICAgKiBJZiBuZWNlc3NhcnksIHRoZSBwcm9qZWN0aW9uIG1hdHJpeCB3aWxsIGJlIHJlY29tcHV0ZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAbWVtYmVyb2YgUGVyc3BlY3RpdmVGcnVzdHVtLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtNYXRyaXg0fQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqCiAgICAgICAgICogQHNlZSBQZXJzcGVjdGl2ZU9mZkNlbnRlckZydXN0dW0jcHJvamVjdGlvbk1hdHJpeC4KICAgICAgICAgKiBAc2VlIFBlcnNwZWN0aXZlRnJ1c3R1bSNpbmZpbml0ZVByb2plY3Rpb25NYXRyaXgKICAgICAgICAgKi8KICAgICAgICBwcm9qZWN0aW9uTWF0cml4OiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICB1cGRhdGU0KHRoaXMpOwogICAgICAgICAgICByZXR1cm4gdGhpcy5fb2ZmQ2VudGVyRnJ1c3R1bS5wcm9qZWN0aW9uTWF0cml4OwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogVGhlIHBlcnNwZWN0aXZlIHByb2plY3Rpb24gbWF0cml4IGNvbXB1dGVkIGZyb20gdGhlIHZpZXcgZnJ1c3R1bSB3aXRoIGFuIGluZmluaXRlIGZhciBwbGFuZS4KICAgICAgICAgKiBAbWVtYmVyb2YgUGVyc3BlY3RpdmVGcnVzdHVtLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtNYXRyaXg0fQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqCiAgICAgICAgICogQHNlZSBQZXJzcGVjdGl2ZUZydXN0dW0jcHJvamVjdGlvbk1hdHJpeAogICAgICAgICAqLwogICAgICAgIGluZmluaXRlUHJvamVjdGlvbk1hdHJpeDogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgdXBkYXRlNCh0aGlzKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29mZkNlbnRlckZydXN0dW0uaW5maW5pdGVQcm9qZWN0aW9uTWF0cml4OwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgYW5nbGUgb2YgdGhlIHZlcnRpY2FsIGZpZWxkIG9mIHZpZXcsIGluIHJhZGlhbnMuCiAgICAgICAgICogQG1lbWJlcm9mIFBlcnNwZWN0aXZlRnJ1c3R1bS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfHVuZGVmaW5lZH0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKiBAZGVmYXVsdCB1bmRlZmluZWQKICAgICAgICAgKi8KICAgICAgICBmb3Z5OiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICB1cGRhdGU0KHRoaXMpOwogICAgICAgICAgICByZXR1cm4gdGhpcy5fZm92eTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgc3NlRGVub21pbmF0b3I6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHVwZGF0ZTQodGhpcyk7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9zc2VEZW5vbWluYXRvcjsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIG9ydGhvZ3JhcGhpYyBwcm9qZWN0aW9uIG1hdHJpeCBjb21wdXRlZCBmcm9tIHRoZSB2aWV3IGZydXN0dW0uCiAgICAgICAgICogQG1lbWJlcm9mIFBlcnNwZWN0aXZlRnJ1c3R1bS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7UGVyc3BlY3RpdmVPZmZDZW50ZXJGcnVzdHVtfQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgb2ZmQ2VudGVyRnJ1c3R1bTogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgdXBkYXRlNCh0aGlzKTsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29mZkNlbnRlckZydXN0dW07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgUGVyc3BlY3RpdmVGcnVzdHVtLnByb3RvdHlwZS5jb21wdXRlQ3VsbGluZ1ZvbHVtZSA9IGZ1bmN0aW9uKHBvc2l0aW9uLCBkaXJlY3Rpb24yLCB1cCkgewogICAgICAgIHVwZGF0ZTQodGhpcyk7CiAgICAgICAgcmV0dXJuIHRoaXMuX29mZkNlbnRlckZydXN0dW0uY29tcHV0ZUN1bGxpbmdWb2x1bWUocG9zaXRpb24sIGRpcmVjdGlvbjIsIHVwKTsKICAgICAgfTsKICAgICAgUGVyc3BlY3RpdmVGcnVzdHVtLnByb3RvdHlwZS5nZXRQaXhlbERpbWVuc2lvbnMgPSBmdW5jdGlvbihkcmF3aW5nQnVmZmVyV2lkdGgsIGRyYXdpbmdCdWZmZXJIZWlnaHQsIGRpc3RhbmNlLCBwaXhlbFJhdGlvLCByZXN1bHQpIHsKICAgICAgICB1cGRhdGU0KHRoaXMpOwogICAgICAgIHJldHVybiB0aGlzLl9vZmZDZW50ZXJGcnVzdHVtLmdldFBpeGVsRGltZW5zaW9ucygKICAgICAgICAgIGRyYXdpbmdCdWZmZXJXaWR0aCwKICAgICAgICAgIGRyYXdpbmdCdWZmZXJIZWlnaHQsCiAgICAgICAgICBkaXN0YW5jZSwKICAgICAgICAgIHBpeGVsUmF0aW8sCiAgICAgICAgICByZXN1bHQKICAgICAgICApOwogICAgICB9OwogICAgICBQZXJzcGVjdGl2ZUZydXN0dW0ucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IFBlcnNwZWN0aXZlRnJ1c3R1bSgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYXNwZWN0UmF0aW8gPSB0aGlzLmFzcGVjdFJhdGlvOwogICAgICAgIHJlc3VsdC5mb3YgPSB0aGlzLmZvdjsKICAgICAgICByZXN1bHQubmVhciA9IHRoaXMubmVhcjsKICAgICAgICByZXN1bHQuZmFyID0gdGhpcy5mYXI7CiAgICAgICAgcmVzdWx0Ll9hc3BlY3RSYXRpbyA9IHZvaWQgMDsKICAgICAgICByZXN1bHQuX2ZvdiA9IHZvaWQgMDsKICAgICAgICByZXN1bHQuX25lYXIgPSB2b2lkIDA7CiAgICAgICAgcmVzdWx0Ll9mYXIgPSB2b2lkIDA7CiAgICAgICAgdGhpcy5fb2ZmQ2VudGVyRnJ1c3R1bS5jbG9uZShyZXN1bHQuX29mZkNlbnRlckZydXN0dW0pOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFBlcnNwZWN0aXZlRnJ1c3R1bS5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24ob3RoZXIpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChvdGhlcikgfHwgIShvdGhlciBpbnN0YW5jZW9mIFBlcnNwZWN0aXZlRnJ1c3R1bSkpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgdXBkYXRlNCh0aGlzKTsKICAgICAgICB1cGRhdGU0KG90aGVyKTsKICAgICAgICByZXR1cm4gdGhpcy5mb3YgPT09IG90aGVyLmZvdiAmJiB0aGlzLmFzcGVjdFJhdGlvID09PSBvdGhlci5hc3BlY3RSYXRpbyAmJiB0aGlzLl9vZmZDZW50ZXJGcnVzdHVtLmVxdWFscyhvdGhlci5fb2ZmQ2VudGVyRnJ1c3R1bSk7CiAgICAgIH07CiAgICAgIFBlcnNwZWN0aXZlRnJ1c3R1bS5wcm90b3R5cGUuZXF1YWxzRXBzaWxvbiA9IGZ1bmN0aW9uKG90aGVyLCByZWxhdGl2ZUVwc2lsb24sIGFic29sdXRlRXBzaWxvbikgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG90aGVyKSB8fCAhKG90aGVyIGluc3RhbmNlb2YgUGVyc3BlY3RpdmVGcnVzdHVtKSkgewogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICB1cGRhdGU0KHRoaXMpOwogICAgICAgIHVwZGF0ZTQob3RoZXIpOwogICAgICAgIHJldHVybiBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIHRoaXMuZm92LAogICAgICAgICAgb3RoZXIuZm92LAogICAgICAgICAgcmVsYXRpdmVFcHNpbG9uLAogICAgICAgICAgYWJzb2x1dGVFcHNpbG9uCiAgICAgICAgKSAmJiBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIHRoaXMuYXNwZWN0UmF0aW8sCiAgICAgICAgICBvdGhlci5hc3BlY3RSYXRpbywKICAgICAgICAgIHJlbGF0aXZlRXBzaWxvbiwKICAgICAgICAgIGFic29sdXRlRXBzaWxvbgogICAgICAgICkgJiYgdGhpcy5fb2ZmQ2VudGVyRnJ1c3R1bS5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgb3RoZXIuX29mZkNlbnRlckZydXN0dW0sCiAgICAgICAgICByZWxhdGl2ZUVwc2lsb24sCiAgICAgICAgICBhYnNvbHV0ZUVwc2lsb24KICAgICAgICApOwogICAgICB9OwogICAgICBQZXJzcGVjdGl2ZUZydXN0dW1fZGVmYXVsdCA9IFBlcnNwZWN0aXZlRnJ1c3R1bTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0ZydXN0dW1HZW9tZXRyeS5qcwogIGZ1bmN0aW9uIEZydXN0dW1HZW9tZXRyeShvcHRpb25zKSB7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm9wdGlvbnMiLCBvcHRpb25zKTsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgib3B0aW9ucy5mcnVzdHVtIiwgb3B0aW9ucy5mcnVzdHVtKTsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgib3B0aW9ucy5vcmlnaW4iLCBvcHRpb25zLm9yaWdpbik7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm9wdGlvbnMub3JpZW50YXRpb24iLCBvcHRpb25zLm9yaWVudGF0aW9uKTsKICAgIGNvbnN0IGZydXN0dW0gPSBvcHRpb25zLmZydXN0dW07CiAgICBjb25zdCBvcmllbnRhdGlvbiA9IG9wdGlvbnMub3JpZW50YXRpb247CiAgICBjb25zdCBvcmlnaW4gPSBvcHRpb25zLm9yaWdpbjsKICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IG9wdGlvbnMudmVydGV4Rm9ybWF0ID8/IFZlcnRleEZvcm1hdF9kZWZhdWx0LkRFRkFVTFQ7CiAgICBjb25zdCBkcmF3TmVhclBsYW5lID0gb3B0aW9ucy5fZHJhd05lYXJQbGFuZSA/PyB0cnVlOwogICAgbGV0IGZydXN0dW1UeXBlOwogICAgbGV0IGZydXN0dW1QYWNrZWRMZW5ndGg7CiAgICBpZiAoZnJ1c3R1bSBpbnN0YW5jZW9mIFBlcnNwZWN0aXZlRnJ1c3R1bV9kZWZhdWx0KSB7CiAgICAgIGZydXN0dW1UeXBlID0gUEVSU1BFQ1RJVkU7CiAgICAgIGZydXN0dW1QYWNrZWRMZW5ndGggPSBQZXJzcGVjdGl2ZUZydXN0dW1fZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICB9IGVsc2UgaWYgKGZydXN0dW0gaW5zdGFuY2VvZiBPcnRob2dyYXBoaWNGcnVzdHVtX2RlZmF1bHQpIHsKICAgICAgZnJ1c3R1bVR5cGUgPSBPUlRIT0dSQVBISUM7CiAgICAgIGZydXN0dW1QYWNrZWRMZW5ndGggPSBPcnRob2dyYXBoaWNGcnVzdHVtX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgfQogICAgdGhpcy5fZnJ1c3R1bVR5cGUgPSBmcnVzdHVtVHlwZTsKICAgIHRoaXMuX2ZydXN0dW0gPSBmcnVzdHVtLmNsb25lKCk7CiAgICB0aGlzLl9vcmlnaW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUob3JpZ2luKTsKICAgIHRoaXMuX29yaWVudGF0aW9uID0gUXVhdGVybmlvbl9kZWZhdWx0LmNsb25lKG9yaWVudGF0aW9uKTsKICAgIHRoaXMuX2RyYXdOZWFyUGxhbmUgPSBkcmF3TmVhclBsYW5lOwogICAgdGhpcy5fdmVydGV4Rm9ybWF0ID0gdmVydGV4Rm9ybWF0OwogICAgdGhpcy5fd29ya2VyTmFtZSA9ICJjcmVhdGVGcnVzdHVtR2VvbWV0cnkiOwogICAgdGhpcy5wYWNrZWRMZW5ndGggPSAyICsgZnJ1c3R1bVBhY2tlZExlbmd0aCArIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyBRdWF0ZXJuaW9uX2RlZmF1bHQucGFja2VkTGVuZ3RoICsgVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFja2VkTGVuZ3RoOwogIH0KICBmdW5jdGlvbiBnZXRBdHRyaWJ1dGVzKG9mZnNldCwgbm9ybWFscywgdGFuZ2VudHMsIGJpdGFuZ2VudHMsIHN0LCBub3JtYWwyLCB0YW5nZW50LCBiaXRhbmdlbnQpIHsKICAgIGNvbnN0IHN0T2Zmc2V0ID0gb2Zmc2V0IC8gMyAqIDI7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDQ7ICsraSkgewogICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG5vcm1hbHMpKSB7CiAgICAgICAgbm9ybWFsc1tvZmZzZXRdID0gbm9ybWFsMi54OwogICAgICAgIG5vcm1hbHNbb2Zmc2V0ICsgMV0gPSBub3JtYWwyLnk7CiAgICAgICAgbm9ybWFsc1tvZmZzZXQgKyAyXSA9IG5vcm1hbDIuejsKICAgICAgfQogICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHRhbmdlbnRzKSkgewogICAgICAgIHRhbmdlbnRzW29mZnNldF0gPSB0YW5nZW50Lng7CiAgICAgICAgdGFuZ2VudHNbb2Zmc2V0ICsgMV0gPSB0YW5nZW50Lnk7CiAgICAgICAgdGFuZ2VudHNbb2Zmc2V0ICsgMl0gPSB0YW5nZW50Lno7CiAgICAgIH0KICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChiaXRhbmdlbnRzKSkgewogICAgICAgIGJpdGFuZ2VudHNbb2Zmc2V0XSA9IGJpdGFuZ2VudC54OwogICAgICAgIGJpdGFuZ2VudHNbb2Zmc2V0ICsgMV0gPSBiaXRhbmdlbnQueTsKICAgICAgICBiaXRhbmdlbnRzW29mZnNldCArIDJdID0gYml0YW5nZW50Lno7CiAgICAgIH0KICAgICAgb2Zmc2V0ICs9IDM7CiAgICB9CiAgICBzdFtzdE9mZnNldF0gPSAwOwogICAgc3Rbc3RPZmZzZXQgKyAxXSA9IDA7CiAgICBzdFtzdE9mZnNldCArIDJdID0gMTsKICAgIHN0W3N0T2Zmc2V0ICsgM10gPSAwOwogICAgc3Rbc3RPZmZzZXQgKyA0XSA9IDE7CiAgICBzdFtzdE9mZnNldCArIDVdID0gMTsKICAgIHN0W3N0T2Zmc2V0ICsgNl0gPSAwOwogICAgc3Rbc3RPZmZzZXQgKyA3XSA9IDE7CiAgfQogIHZhciBQRVJTUEVDVElWRSwgT1JUSE9HUkFQSElDLCBzY3JhdGNoUGFja1BlcnNwZWN0aXZlLCBzY3JhdGNoUGFja09ydGhvZ3JhcGhpYywgc2NyYXRjaFBhY2tRdWF0ZXJuaW9uLCBzY3JhdGNoUGFja29yaWdpbiwgc2NyYXRjaFZlcnRleEZvcm1hdDcsIHNjcmF0Y2hSb3RhdGlvbk1hdHJpeDIsIHNjcmF0Y2hWaWV3TWF0cml4LCBzY3JhdGNoSW52ZXJzZU1hdHJpeCwgc2NyYXRjaFhEaXJlY3Rpb24sIHNjcmF0Y2hZRGlyZWN0aW9uLCBzY3JhdGNoWkRpcmVjdGlvbiwgc2NyYXRjaE5lZ2F0aXZlWCwgc2NyYXRjaE5lZ2F0aXZlWSwgc2NyYXRjaE5lZ2F0aXZlWiwgZnJ1c3R1bVNwbGl0cywgZnJ1c3R1bUNvcm5lcnNOREMsIHNjcmF0Y2hGcnVzdHVtQ29ybmVycywgRnJ1c3R1bUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfRnJ1c3R1bUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9GcnVzdHVtR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0JvdW5kaW5nU3BoZXJlKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRlc2lhbjQoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X0NvbXBvbmVudERhdGF0eXBlKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZXMoKTsKICAgICAgaW5pdF9NYXRyaXgzKCk7CiAgICAgIGluaXRfTWF0cml4NCgpOwogICAgICBpbml0X09ydGhvZ3JhcGhpY0ZydXN0dW0oKTsKICAgICAgaW5pdF9QZXJzcGVjdGl2ZUZydXN0dW0oKTsKICAgICAgaW5pdF9QcmltaXRpdmVUeXBlKCk7CiAgICAgIGluaXRfUXVhdGVybmlvbigpOwogICAgICBpbml0X1ZlcnRleEZvcm1hdCgpOwogICAgICBQRVJTUEVDVElWRSA9IDA7CiAgICAgIE9SVEhPR1JBUEhJQyA9IDE7CiAgICAgIEZydXN0dW1HZW9tZXRyeS5wYWNrID0gZnVuY3Rpb24odmFsdWUsIGFycmF5LCBzdGFydGluZ0luZGV4KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJ2YWx1ZSIsIHZhbHVlKTsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgY29uc3QgZnJ1c3R1bVR5cGUgPSB2YWx1ZS5fZnJ1c3R1bVR5cGU7CiAgICAgICAgY29uc3QgZnJ1c3R1bSA9IHZhbHVlLl9mcnVzdHVtOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSBmcnVzdHVtVHlwZTsKICAgICAgICBpZiAoZnJ1c3R1bVR5cGUgPT09IFBFUlNQRUNUSVZFKSB7CiAgICAgICAgICBQZXJzcGVjdGl2ZUZydXN0dW1fZGVmYXVsdC5wYWNrKGZydXN0dW0sIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gUGVyc3BlY3RpdmVGcnVzdHVtX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBPcnRob2dyYXBoaWNGcnVzdHVtX2RlZmF1bHQucGFjayhmcnVzdHVtLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgICBzdGFydGluZ0luZGV4ICs9IE9ydGhvZ3JhcGhpY0ZydXN0dW1fZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgfQogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHZhbHVlLl9vcmlnaW4sIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgUXVhdGVybmlvbl9kZWZhdWx0LnBhY2sodmFsdWUuX29yaWVudGF0aW9uLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBRdWF0ZXJuaW9uX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2sodmFsdWUuX3ZlcnRleEZvcm1hdCwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXhdID0gdmFsdWUuX2RyYXdOZWFyUGxhbmUgPyAxIDogMDsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hQYWNrUGVyc3BlY3RpdmUgPSBuZXcgUGVyc3BlY3RpdmVGcnVzdHVtX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBhY2tPcnRob2dyYXBoaWMgPSBuZXcgT3J0aG9ncmFwaGljRnJ1c3R1bV9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQYWNrUXVhdGVybmlvbiA9IG5ldyBRdWF0ZXJuaW9uX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBhY2tvcmlnaW4gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQ3ID0gbmV3IFZlcnRleEZvcm1hdF9kZWZhdWx0KCk7CiAgICAgIEZydXN0dW1HZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGNvbnN0IGZydXN0dW1UeXBlID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBsZXQgZnJ1c3R1bTsKICAgICAgICBpZiAoZnJ1c3R1bVR5cGUgPT09IFBFUlNQRUNUSVZFKSB7CiAgICAgICAgICBmcnVzdHVtID0gUGVyc3BlY3RpdmVGcnVzdHVtX2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgICBhcnJheSwKICAgICAgICAgICAgc3RhcnRpbmdJbmRleCwKICAgICAgICAgICAgc2NyYXRjaFBhY2tQZXJzcGVjdGl2ZQogICAgICAgICAgKTsKICAgICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gUGVyc3BlY3RpdmVGcnVzdHVtX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBmcnVzdHVtID0gT3J0aG9ncmFwaGljRnJ1c3R1bV9kZWZhdWx0LnVucGFjaygKICAgICAgICAgICAgYXJyYXksCiAgICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICAgIHNjcmF0Y2hQYWNrT3J0aG9ncmFwaGljCiAgICAgICAgICApOwogICAgICAgICAgc3RhcnRpbmdJbmRleCArPSBPcnRob2dyYXBoaWNGcnVzdHVtX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIH0KICAgICAgICBjb25zdCBvcmlnaW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoUGFja29yaWdpbik7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IG9yaWVudGF0aW9uID0gUXVhdGVybmlvbl9kZWZhdWx0LnVucGFjaygKICAgICAgICAgIGFycmF5LAogICAgICAgICAgc3RhcnRpbmdJbmRleCwKICAgICAgICAgIHNjcmF0Y2hQYWNrUXVhdGVybmlvbgogICAgICAgICk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBRdWF0ZXJuaW9uX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnVucGFjaygKICAgICAgICAgIGFycmF5LAogICAgICAgICAgc3RhcnRpbmdJbmRleCwKICAgICAgICAgIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQ3CiAgICAgICAgKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCBkcmF3TmVhclBsYW5lID0gYXJyYXlbc3RhcnRpbmdJbmRleF0gPT09IDE7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBGcnVzdHVtR2VvbWV0cnkoewogICAgICAgICAgICBmcnVzdHVtLAogICAgICAgICAgICBvcmlnaW4sCiAgICAgICAgICAgIG9yaWVudGF0aW9uLAogICAgICAgICAgICB2ZXJ0ZXhGb3JtYXQsCiAgICAgICAgICAgIF9kcmF3TmVhclBsYW5lOiBkcmF3TmVhclBsYW5lCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZnJ1c3R1bVJlc3VsdCA9IGZydXN0dW1UeXBlID09PSByZXN1bHQuX2ZydXN0dW1UeXBlID8gcmVzdWx0Ll9mcnVzdHVtIDogdm9pZCAwOwogICAgICAgIHJlc3VsdC5fZnJ1c3R1bSA9IGZydXN0dW0uY2xvbmUoZnJ1c3R1bVJlc3VsdCk7CiAgICAgICAgcmVzdWx0Ll9mcnVzdHVtVHlwZSA9IGZydXN0dW1UeXBlOwogICAgICAgIHJlc3VsdC5fb3JpZ2luID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKG9yaWdpbiwgcmVzdWx0Ll9vcmlnaW4pOwogICAgICAgIHJlc3VsdC5fb3JpZW50YXRpb24gPSBRdWF0ZXJuaW9uX2RlZmF1bHQuY2xvbmUob3JpZW50YXRpb24sIHJlc3VsdC5fb3JpZW50YXRpb24pOwogICAgICAgIHJlc3VsdC5fdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQuY2xvbmUodmVydGV4Rm9ybWF0LCByZXN1bHQuX3ZlcnRleEZvcm1hdCk7CiAgICAgICAgcmVzdWx0Ll9kcmF3TmVhclBsYW5lID0gZHJhd05lYXJQbGFuZTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBzY3JhdGNoUm90YXRpb25NYXRyaXgyID0gbmV3IE1hdHJpeDNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoVmlld01hdHJpeCA9IG5ldyBNYXRyaXg0X2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEludmVyc2VNYXRyaXggPSBuZXcgTWF0cml4NF9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hYRGlyZWN0aW9uID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoWURpcmVjdGlvbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFpEaXJlY3Rpb24gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hOZWdhdGl2ZVggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hOZWdhdGl2ZVkgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hOZWdhdGl2ZVogPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZydXN0dW1TcGxpdHMgPSBuZXcgQXJyYXkoMyk7CiAgICAgIGZydXN0dW1Db3JuZXJzTkRDID0gbmV3IEFycmF5KDQpOwogICAgICBmcnVzdHVtQ29ybmVyc05EQ1swXSA9IG5ldyBDYXJ0ZXNpYW40X2RlZmF1bHQoLTEsIC0xLCAxLCAxKTsKICAgICAgZnJ1c3R1bUNvcm5lcnNORENbMV0gPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KDEsIC0xLCAxLCAxKTsKICAgICAgZnJ1c3R1bUNvcm5lcnNORENbMl0gPSBuZXcgQ2FydGVzaWFuNF9kZWZhdWx0KDEsIDEsIDEsIDEpOwogICAgICBmcnVzdHVtQ29ybmVyc05EQ1szXSA9IG5ldyBDYXJ0ZXNpYW40X2RlZmF1bHQoLTEsIDEsIDEsIDEpOwogICAgICBzY3JhdGNoRnJ1c3R1bUNvcm5lcnMgPSBuZXcgQXJyYXkoNCk7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNDsgKytpKSB7CiAgICAgICAgc2NyYXRjaEZydXN0dW1Db3JuZXJzW2ldID0gbmV3IENhcnRlc2lhbjRfZGVmYXVsdCgpOwogICAgICB9CiAgICAgIEZydXN0dW1HZW9tZXRyeS5fY29tcHV0ZU5lYXJGYXJQbGFuZXMgPSBmdW5jdGlvbihvcmlnaW4sIG9yaWVudGF0aW9uLCBmcnVzdHVtVHlwZSwgZnJ1c3R1bSwgcG9zaXRpb25zLCB4RGlyZWN0aW9uLCB5RGlyZWN0aW9uLCB6RGlyZWN0aW9uKSB7CiAgICAgICAgY29uc3Qgcm90YXRpb25NYXRyaXggPSBNYXRyaXgzX2RlZmF1bHQuZnJvbVF1YXRlcm5pb24oCiAgICAgICAgICBvcmllbnRhdGlvbiwKICAgICAgICAgIHNjcmF0Y2hSb3RhdGlvbk1hdHJpeDIKICAgICAgICApOwogICAgICAgIGxldCB4ID0geERpcmVjdGlvbiA/PyBzY3JhdGNoWERpcmVjdGlvbjsKICAgICAgICBsZXQgeSA9IHlEaXJlY3Rpb24gPz8gc2NyYXRjaFlEaXJlY3Rpb247CiAgICAgICAgbGV0IHogPSB6RGlyZWN0aW9uID8/IHNjcmF0Y2haRGlyZWN0aW9uOwogICAgICAgIHggPSBNYXRyaXgzX2RlZmF1bHQuZ2V0Q29sdW1uKHJvdGF0aW9uTWF0cml4LCAwLCB4KTsKICAgICAgICB5ID0gTWF0cml4M19kZWZhdWx0LmdldENvbHVtbihyb3RhdGlvbk1hdHJpeCwgMSwgeSk7CiAgICAgICAgeiA9IE1hdHJpeDNfZGVmYXVsdC5nZXRDb2x1bW4ocm90YXRpb25NYXRyaXgsIDIsIHopOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoeCwgeCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSh5LCB5KTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKHosIHopOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoeCwgeCk7CiAgICAgICAgY29uc3QgdmlldyA9IE1hdHJpeDRfZGVmYXVsdC5jb21wdXRlVmlldyhvcmlnaW4sIHosIHksIHgsIHNjcmF0Y2hWaWV3TWF0cml4KTsKICAgICAgICBsZXQgaW52ZXJzZVZpZXc7CiAgICAgICAgbGV0IGludmVyc2VWaWV3UHJvamVjdGlvbjsKICAgICAgICBjb25zdCBwcm9qZWN0aW9uID0gZnJ1c3R1bS5wcm9qZWN0aW9uTWF0cml4OwogICAgICAgIGlmIChmcnVzdHVtVHlwZSA9PT0gUEVSU1BFQ1RJVkUpIHsKICAgICAgICAgIGNvbnN0IHZpZXdQcm9qZWN0aW9uID0gTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5KAogICAgICAgICAgICBwcm9qZWN0aW9uLAogICAgICAgICAgICB2aWV3LAogICAgICAgICAgICBzY3JhdGNoSW52ZXJzZU1hdHJpeAogICAgICAgICAgKTsKICAgICAgICAgIGludmVyc2VWaWV3UHJvamVjdGlvbiA9IE1hdHJpeDRfZGVmYXVsdC5pbnZlcnNlKAogICAgICAgICAgICB2aWV3UHJvamVjdGlvbiwKICAgICAgICAgICAgc2NyYXRjaEludmVyc2VNYXRyaXgKICAgICAgICAgICk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGludmVyc2VWaWV3ID0gTWF0cml4NF9kZWZhdWx0LmludmVyc2VUcmFuc2Zvcm1hdGlvbih2aWV3LCBzY3JhdGNoSW52ZXJzZU1hdHJpeCk7CiAgICAgICAgfQogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaW52ZXJzZVZpZXdQcm9qZWN0aW9uKSkgewogICAgICAgICAgZnJ1c3R1bVNwbGl0c1swXSA9IGZydXN0dW0ubmVhcjsKICAgICAgICAgIGZydXN0dW1TcGxpdHNbMV0gPSBmcnVzdHVtLmZhcjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZnJ1c3R1bVNwbGl0c1swXSA9IDA7CiAgICAgICAgICBmcnVzdHVtU3BsaXRzWzFdID0gZnJ1c3R1bS5uZWFyOwogICAgICAgICAgZnJ1c3R1bVNwbGl0c1syXSA9IGZydXN0dW0uZmFyOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI7ICsraSkgewogICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCA0OyArK2opIHsKICAgICAgICAgICAgbGV0IGNvcm5lciA9IENhcnRlc2lhbjRfZGVmYXVsdC5jbG9uZSgKICAgICAgICAgICAgICBmcnVzdHVtQ29ybmVyc05EQ1tqXSwKICAgICAgICAgICAgICBzY3JhdGNoRnJ1c3R1bUNvcm5lcnNbal0KICAgICAgICAgICAgKTsKICAgICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoaW52ZXJzZVZpZXdQcm9qZWN0aW9uKSkgewogICAgICAgICAgICAgIGNvbnN0IG9mZkNlbnRlckZydXN0dW0gPSBmcnVzdHVtLm9mZkNlbnRlckZydXN0dW07CiAgICAgICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChvZmZDZW50ZXJGcnVzdHVtKSkgewogICAgICAgICAgICAgICAgZnJ1c3R1bSA9IG9mZkNlbnRlckZydXN0dW07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNvbnN0IG5lYXIgPSBmcnVzdHVtU3BsaXRzW2ldOwogICAgICAgICAgICAgIGNvbnN0IGZhciA9IGZydXN0dW1TcGxpdHNbaSArIDFdOwogICAgICAgICAgICAgIGNvcm5lci54ID0gKGNvcm5lci54ICogKGZydXN0dW0ucmlnaHQgLSBmcnVzdHVtLmxlZnQpICsgZnJ1c3R1bS5sZWZ0ICsgZnJ1c3R1bS5yaWdodCkgKiAwLjU7CiAgICAgICAgICAgICAgY29ybmVyLnkgPSAoY29ybmVyLnkgKiAoZnJ1c3R1bS50b3AgLSBmcnVzdHVtLmJvdHRvbSkgKyBmcnVzdHVtLmJvdHRvbSArIGZydXN0dW0udG9wKSAqIDAuNTsKICAgICAgICAgICAgICBjb3JuZXIueiA9IChjb3JuZXIueiAqIChuZWFyIC0gZmFyKSAtIG5lYXIgLSBmYXIpICogMC41OwogICAgICAgICAgICAgIGNvcm5lci53ID0gMTsKICAgICAgICAgICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlCeVZlY3RvcihpbnZlcnNlVmlldywgY29ybmVyLCBjb3JuZXIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGNvcm5lciA9IE1hdHJpeDRfZGVmYXVsdC5tdWx0aXBseUJ5VmVjdG9yKAogICAgICAgICAgICAgICAgaW52ZXJzZVZpZXdQcm9qZWN0aW9uLAogICAgICAgICAgICAgICAgY29ybmVyLAogICAgICAgICAgICAgICAgY29ybmVyCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBjb25zdCB3ID0gMSAvIGNvcm5lci53OwogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGNvcm5lciwgdywgY29ybmVyKTsKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoY29ybmVyLCBvcmlnaW4sIGNvcm5lcik7CiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShjb3JuZXIsIGNvcm5lcik7CiAgICAgICAgICAgICAgY29uc3QgZmFjID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdCh6LCBjb3JuZXIpOwogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKGNvcm5lciwgZnJ1c3R1bVNwbGl0c1tpXSAvIGZhYywgY29ybmVyKTsKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGNvcm5lciwgb3JpZ2luLCBjb3JuZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHBvc2l0aW9uc1sxMiAqIGkgKyBqICogM10gPSBjb3JuZXIueDsKICAgICAgICAgICAgcG9zaXRpb25zWzEyICogaSArIGogKiAzICsgMV0gPSBjb3JuZXIueTsKICAgICAgICAgICAgcG9zaXRpb25zWzEyICogaSArIGogKiAzICsgMl0gPSBjb3JuZXIuejsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH07CiAgICAgIEZydXN0dW1HZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKGZydXN0dW1HZW9tZXRyeSkgewogICAgICAgIGNvbnN0IGZydXN0dW1UeXBlID0gZnJ1c3R1bUdlb21ldHJ5Ll9mcnVzdHVtVHlwZTsKICAgICAgICBjb25zdCBmcnVzdHVtID0gZnJ1c3R1bUdlb21ldHJ5Ll9mcnVzdHVtOwogICAgICAgIGNvbnN0IG9yaWdpbiA9IGZydXN0dW1HZW9tZXRyeS5fb3JpZ2luOwogICAgICAgIGNvbnN0IG9yaWVudGF0aW9uID0gZnJ1c3R1bUdlb21ldHJ5Ll9vcmllbnRhdGlvbjsKICAgICAgICBjb25zdCBkcmF3TmVhclBsYW5lID0gZnJ1c3R1bUdlb21ldHJ5Ll9kcmF3TmVhclBsYW5lOwogICAgICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IGZydXN0dW1HZW9tZXRyeS5fdmVydGV4Rm9ybWF0OwogICAgICAgIGNvbnN0IG51bWJlck9mUGxhbmVzID0gZHJhd05lYXJQbGFuZSA/IDYgOiA1OwogICAgICAgIGxldCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KDMgKiA0ICogNik7CiAgICAgICAgRnJ1c3R1bUdlb21ldHJ5Ll9jb21wdXRlTmVhckZhclBsYW5lcygKICAgICAgICAgIG9yaWdpbiwKICAgICAgICAgIG9yaWVudGF0aW9uLAogICAgICAgICAgZnJ1c3R1bVR5cGUsCiAgICAgICAgICBmcnVzdHVtLAogICAgICAgICAgcG9zaXRpb25zCiAgICAgICAgKTsKICAgICAgICBsZXQgb2Zmc2V0ID0gMyAqIDQgKiAyOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXRdID0gcG9zaXRpb25zWzMgKiA0XTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgMV0gPSBwb3NpdGlvbnNbMyAqIDQgKyAxXTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgMl0gPSBwb3NpdGlvbnNbMyAqIDQgKyAyXTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgM10gPSBwb3NpdGlvbnNbMF07CiAgICAgICAgcG9zaXRpb25zW29mZnNldCArIDRdID0gcG9zaXRpb25zWzFdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyA1XSA9IHBvc2l0aW9uc1syXTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgNl0gPSBwb3NpdGlvbnNbMyAqIDNdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyA3XSA9IHBvc2l0aW9uc1szICogMyArIDFdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyA4XSA9IHBvc2l0aW9uc1szICogMyArIDJdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyA5XSA9IHBvc2l0aW9uc1szICogN107CiAgICAgICAgcG9zaXRpb25zW29mZnNldCArIDEwXSA9IHBvc2l0aW9uc1szICogNyArIDFdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAxMV0gPSBwb3NpdGlvbnNbMyAqIDcgKyAyXTsKICAgICAgICBvZmZzZXQgKz0gMyAqIDQ7CiAgICAgICAgcG9zaXRpb25zW29mZnNldF0gPSBwb3NpdGlvbnNbMyAqIDVdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAxXSA9IHBvc2l0aW9uc1szICogNSArIDFdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAyXSA9IHBvc2l0aW9uc1szICogNSArIDJdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAzXSA9IHBvc2l0aW9uc1szXTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgNF0gPSBwb3NpdGlvbnNbMyArIDFdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyA1XSA9IHBvc2l0aW9uc1szICsgMl07CiAgICAgICAgcG9zaXRpb25zW29mZnNldCArIDZdID0gcG9zaXRpb25zWzBdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyA3XSA9IHBvc2l0aW9uc1sxXTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgOF0gPSBwb3NpdGlvbnNbMl07CiAgICAgICAgcG9zaXRpb25zW29mZnNldCArIDldID0gcG9zaXRpb25zWzMgKiA0XTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgMTBdID0gcG9zaXRpb25zWzMgKiA0ICsgMV07CiAgICAgICAgcG9zaXRpb25zW29mZnNldCArIDExXSA9IHBvc2l0aW9uc1szICogNCArIDJdOwogICAgICAgIG9mZnNldCArPSAzICogNDsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0XSA9IHBvc2l0aW9uc1szXTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgMV0gPSBwb3NpdGlvbnNbMyArIDFdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAyXSA9IHBvc2l0aW9uc1szICsgMl07CiAgICAgICAgcG9zaXRpb25zW29mZnNldCArIDNdID0gcG9zaXRpb25zWzMgKiA1XTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgNF0gPSBwb3NpdGlvbnNbMyAqIDUgKyAxXTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgNV0gPSBwb3NpdGlvbnNbMyAqIDUgKyAyXTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgNl0gPSBwb3NpdGlvbnNbMyAqIDZdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyA3XSA9IHBvc2l0aW9uc1szICogNiArIDFdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyA4XSA9IHBvc2l0aW9uc1szICogNiArIDJdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyA5XSA9IHBvc2l0aW9uc1szICogMl07CiAgICAgICAgcG9zaXRpb25zW29mZnNldCArIDEwXSA9IHBvc2l0aW9uc1szICogMiArIDFdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAxMV0gPSBwb3NpdGlvbnNbMyAqIDIgKyAyXTsKICAgICAgICBvZmZzZXQgKz0gMyAqIDQ7CiAgICAgICAgcG9zaXRpb25zW29mZnNldF0gPSBwb3NpdGlvbnNbMyAqIDJdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAxXSA9IHBvc2l0aW9uc1szICogMiArIDFdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAyXSA9IHBvc2l0aW9uc1szICogMiArIDJdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAzXSA9IHBvc2l0aW9uc1szICogNl07CiAgICAgICAgcG9zaXRpb25zW29mZnNldCArIDRdID0gcG9zaXRpb25zWzMgKiA2ICsgMV07CiAgICAgICAgcG9zaXRpb25zW29mZnNldCArIDVdID0gcG9zaXRpb25zWzMgKiA2ICsgMl07CiAgICAgICAgcG9zaXRpb25zW29mZnNldCArIDZdID0gcG9zaXRpb25zWzMgKiA3XTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgN10gPSBwb3NpdGlvbnNbMyAqIDcgKyAxXTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgOF0gPSBwb3NpdGlvbnNbMyAqIDcgKyAyXTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgOV0gPSBwb3NpdGlvbnNbMyAqIDNdOwogICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAxMF0gPSBwb3NpdGlvbnNbMyAqIDMgKyAxXTsKICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgMTFdID0gcG9zaXRpb25zWzMgKiAzICsgMl07CiAgICAgICAgaWYgKCFkcmF3TmVhclBsYW5lKSB7CiAgICAgICAgICBwb3NpdGlvbnMgPSBwb3NpdGlvbnMuc3ViYXJyYXkoMyAqIDQpOwogICAgICAgIH0KICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlc19kZWZhdWx0KHsKICAgICAgICAgIHBvc2l0aW9uOiBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgdmFsdWVzOiBwb3NpdGlvbnMKICAgICAgICAgIH0pCiAgICAgICAgfSk7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdCh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB8fCBkZWZpbmVkX2RlZmF1bHQodmVydGV4Rm9ybWF0LnRhbmdlbnQpIHx8IGRlZmluZWRfZGVmYXVsdCh2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB8fCBkZWZpbmVkX2RlZmF1bHQodmVydGV4Rm9ybWF0LnN0KSkgewogICAgICAgICAgY29uc3Qgbm9ybWFscyA9IGRlZmluZWRfZGVmYXVsdCh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSA/IG5ldyBGbG9hdDMyQXJyYXkoMyAqIDQgKiBudW1iZXJPZlBsYW5lcykgOiB2b2lkIDA7CiAgICAgICAgICBjb25zdCB0YW5nZW50cyA9IGRlZmluZWRfZGVmYXVsdCh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgPyBuZXcgRmxvYXQzMkFycmF5KDMgKiA0ICogbnVtYmVyT2ZQbGFuZXMpIDogdm9pZCAwOwogICAgICAgICAgY29uc3QgYml0YW5nZW50cyA9IGRlZmluZWRfZGVmYXVsdCh2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSA/IG5ldyBGbG9hdDMyQXJyYXkoMyAqIDQgKiBudW1iZXJPZlBsYW5lcykgOiB2b2lkIDA7CiAgICAgICAgICBjb25zdCBzdCA9IGRlZmluZWRfZGVmYXVsdCh2ZXJ0ZXhGb3JtYXQuc3QpID8gbmV3IEZsb2F0MzJBcnJheSgyICogNCAqIG51bWJlck9mUGxhbmVzKSA6IHZvaWQgMDsKICAgICAgICAgIGNvbnN0IHggPSBzY3JhdGNoWERpcmVjdGlvbjsKICAgICAgICAgIGNvbnN0IHkgPSBzY3JhdGNoWURpcmVjdGlvbjsKICAgICAgICAgIGNvbnN0IHogPSBzY3JhdGNoWkRpcmVjdGlvbjsKICAgICAgICAgIGNvbnN0IG5lZ2F0aXZlWDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubmVnYXRlKHgsIHNjcmF0Y2hOZWdhdGl2ZVgpOwogICAgICAgICAgY29uc3QgbmVnYXRpdmVZID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZSh5LCBzY3JhdGNoTmVnYXRpdmVZKTsKICAgICAgICAgIGNvbnN0IG5lZ2F0aXZlWiA9IENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoeiwgc2NyYXRjaE5lZ2F0aXZlWik7CiAgICAgICAgICBvZmZzZXQgPSAwOwogICAgICAgICAgaWYgKGRyYXdOZWFyUGxhbmUpIHsKICAgICAgICAgICAgZ2V0QXR0cmlidXRlcyhvZmZzZXQsIG5vcm1hbHMsIHRhbmdlbnRzLCBiaXRhbmdlbnRzLCBzdCwgbmVnYXRpdmVaLCB4LCB5KTsKICAgICAgICAgICAgb2Zmc2V0ICs9IDMgKiA0OwogICAgICAgICAgfQogICAgICAgICAgZ2V0QXR0cmlidXRlcyhvZmZzZXQsIG5vcm1hbHMsIHRhbmdlbnRzLCBiaXRhbmdlbnRzLCBzdCwgeiwgbmVnYXRpdmVYMiwgeSk7CiAgICAgICAgICBvZmZzZXQgKz0gMyAqIDQ7CiAgICAgICAgICBnZXRBdHRyaWJ1dGVzKAogICAgICAgICAgICBvZmZzZXQsCiAgICAgICAgICAgIG5vcm1hbHMsCiAgICAgICAgICAgIHRhbmdlbnRzLAogICAgICAgICAgICBiaXRhbmdlbnRzLAogICAgICAgICAgICBzdCwKICAgICAgICAgICAgbmVnYXRpdmVYMiwKICAgICAgICAgICAgbmVnYXRpdmVaLAogICAgICAgICAgICB5CiAgICAgICAgICApOwogICAgICAgICAgb2Zmc2V0ICs9IDMgKiA0OwogICAgICAgICAgZ2V0QXR0cmlidXRlcygKICAgICAgICAgICAgb2Zmc2V0LAogICAgICAgICAgICBub3JtYWxzLAogICAgICAgICAgICB0YW5nZW50cywKICAgICAgICAgICAgYml0YW5nZW50cywKICAgICAgICAgICAgc3QsCiAgICAgICAgICAgIG5lZ2F0aXZlWSwKICAgICAgICAgICAgbmVnYXRpdmVaLAogICAgICAgICAgICBuZWdhdGl2ZVgyCiAgICAgICAgICApOwogICAgICAgICAgb2Zmc2V0ICs9IDMgKiA0OwogICAgICAgICAgZ2V0QXR0cmlidXRlcyhvZmZzZXQsIG5vcm1hbHMsIHRhbmdlbnRzLCBiaXRhbmdlbnRzLCBzdCwgeCwgeiwgeSk7CiAgICAgICAgICBvZmZzZXQgKz0gMyAqIDQ7CiAgICAgICAgICBnZXRBdHRyaWJ1dGVzKG9mZnNldCwgbm9ybWFscywgdGFuZ2VudHMsIGJpdGFuZ2VudHMsIHN0LCB5LCB6LCBuZWdhdGl2ZVgyKTsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobm9ybWFscykpIHsKICAgICAgICAgICAgYXR0cmlidXRlcy5ub3JtYWwgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgICB2YWx1ZXM6IG5vcm1hbHMKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHRhbmdlbnRzKSkgewogICAgICAgICAgICBhdHRyaWJ1dGVzLnRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgICB2YWx1ZXM6IHRhbmdlbnRzCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChiaXRhbmdlbnRzKSkgewogICAgICAgICAgICBhdHRyaWJ1dGVzLmJpdGFuZ2VudCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgICAgIHZhbHVlczogYml0YW5nZW50cwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoc3QpKSB7CiAgICAgICAgICAgIGF0dHJpYnV0ZXMuc3QgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMiwKICAgICAgICAgICAgICB2YWx1ZXM6IHN0CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBpbmRpY2VzID0gbmV3IFVpbnQxNkFycmF5KDYgKiBudW1iZXJPZlBsYW5lcyk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZlBsYW5lczsgKytpKSB7CiAgICAgICAgICBjb25zdCBpbmRleE9mZnNldCA9IGkgKiA2OwogICAgICAgICAgY29uc3QgaW5kZXggPSBpICogNDsKICAgICAgICAgIGluZGljZXNbaW5kZXhPZmZzZXRdID0gaW5kZXg7CiAgICAgICAgICBpbmRpY2VzW2luZGV4T2Zmc2V0ICsgMV0gPSBpbmRleCArIDE7CiAgICAgICAgICBpbmRpY2VzW2luZGV4T2Zmc2V0ICsgMl0gPSBpbmRleCArIDI7CiAgICAgICAgICBpbmRpY2VzW2luZGV4T2Zmc2V0ICsgM10gPSBpbmRleDsKICAgICAgICAgIGluZGljZXNbaW5kZXhPZmZzZXQgKyA0XSA9IGluZGV4ICsgMjsKICAgICAgICAgIGluZGljZXNbaW5kZXhPZmZzZXQgKyA1XSA9IGluZGV4ICsgMzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgICAgIGF0dHJpYnV0ZXMsCiAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUywKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlOiBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21WZXJ0aWNlcyhwb3NpdGlvbnMpCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIEZydXN0dW1HZW9tZXRyeV9kZWZhdWx0ID0gRnJ1c3R1bUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlRnJ1c3R1bUdlb21ldHJ5LmpzCiAgdmFyIGNyZWF0ZUZydXN0dW1HZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlRnJ1c3R1bUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZUZydXN0dW1HZW9tZXRyeV9kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gY3JlYXRlRnJ1c3R1bUdlb21ldHJ5KGZydXN0dW1HZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgZnJ1c3R1bUdlb21ldHJ5ID0gRnJ1c3R1bUdlb21ldHJ5X2RlZmF1bHQudW5wYWNrKGZydXN0dW1HZW9tZXRyeSwgb2Zmc2V0KTsKICAgIH0KICAgIHJldHVybiBGcnVzdHVtR2VvbWV0cnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeShmcnVzdHVtR2VvbWV0cnkpOwogIH0KICB2YXIgY3JlYXRlRnJ1c3R1bUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlRnJ1c3R1bUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVGcnVzdHVtR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9GcnVzdHVtR2VvbWV0cnkoKTsKICAgICAgY3JlYXRlRnJ1c3R1bUdlb21ldHJ5X2RlZmF1bHQgPSBjcmVhdGVGcnVzdHVtR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9GcnVzdHVtT3V0bGluZUdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gRnJ1c3R1bU91dGxpbmVHZW9tZXRyeShvcHRpb25zKSB7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm9wdGlvbnMiLCBvcHRpb25zKTsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgib3B0aW9ucy5mcnVzdHVtIiwgb3B0aW9ucy5mcnVzdHVtKTsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgib3B0aW9ucy5vcmlnaW4iLCBvcHRpb25zLm9yaWdpbik7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm9wdGlvbnMub3JpZW50YXRpb24iLCBvcHRpb25zLm9yaWVudGF0aW9uKTsKICAgIGNvbnN0IGZydXN0dW0gPSBvcHRpb25zLmZydXN0dW07CiAgICBjb25zdCBvcmllbnRhdGlvbiA9IG9wdGlvbnMub3JpZW50YXRpb247CiAgICBjb25zdCBvcmlnaW4gPSBvcHRpb25zLm9yaWdpbjsKICAgIGNvbnN0IGRyYXdOZWFyUGxhbmUgPSBvcHRpb25zLl9kcmF3TmVhclBsYW5lID8/IHRydWU7CiAgICBsZXQgZnJ1c3R1bVR5cGU7CiAgICBsZXQgZnJ1c3R1bVBhY2tlZExlbmd0aDsKICAgIGlmIChmcnVzdHVtIGluc3RhbmNlb2YgUGVyc3BlY3RpdmVGcnVzdHVtX2RlZmF1bHQpIHsKICAgICAgZnJ1c3R1bVR5cGUgPSBQRVJTUEVDVElWRTI7CiAgICAgIGZydXN0dW1QYWNrZWRMZW5ndGggPSBQZXJzcGVjdGl2ZUZydXN0dW1fZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICB9IGVsc2UgaWYgKGZydXN0dW0gaW5zdGFuY2VvZiBPcnRob2dyYXBoaWNGcnVzdHVtX2RlZmF1bHQpIHsKICAgICAgZnJ1c3R1bVR5cGUgPSBPUlRIT0dSQVBISUMyOwogICAgICBmcnVzdHVtUGFja2VkTGVuZ3RoID0gT3J0aG9ncmFwaGljRnJ1c3R1bV9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgIH0KICAgIHRoaXMuX2ZydXN0dW1UeXBlID0gZnJ1c3R1bVR5cGU7CiAgICB0aGlzLl9mcnVzdHVtID0gZnJ1c3R1bS5jbG9uZSgpOwogICAgdGhpcy5fb3JpZ2luID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKG9yaWdpbik7CiAgICB0aGlzLl9vcmllbnRhdGlvbiA9IFF1YXRlcm5pb25fZGVmYXVsdC5jbG9uZShvcmllbnRhdGlvbik7CiAgICB0aGlzLl9kcmF3TmVhclBsYW5lID0gZHJhd05lYXJQbGFuZTsKICAgIHRoaXMuX3dvcmtlck5hbWUgPSAiY3JlYXRlRnJ1c3R1bU91dGxpbmVHZW9tZXRyeSI7CiAgICB0aGlzLnBhY2tlZExlbmd0aCA9IDIgKyBmcnVzdHVtUGFja2VkTGVuZ3RoICsgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCArIFF1YXRlcm5pb25fZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgfQogIHZhciBQRVJTUEVDVElWRTIsIE9SVEhPR1JBUEhJQzIsIHNjcmF0Y2hQYWNrUGVyc3BlY3RpdmUyLCBzY3JhdGNoUGFja09ydGhvZ3JhcGhpYzIsIHNjcmF0Y2hQYWNrUXVhdGVybmlvbjIsIHNjcmF0Y2hQYWNrb3JpZ2luMiwgRnJ1c3R1bU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X0ZydXN0dW1PdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0ZydXN0dW1PdXRsaW5lR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0JvdW5kaW5nU3BoZXJlKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfQ29tcG9uZW50RGF0YXR5cGUoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRnJ1c3R1bUdlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnkoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlcygpOwogICAgICBpbml0X09ydGhvZ3JhcGhpY0ZydXN0dW0oKTsKICAgICAgaW5pdF9QZXJzcGVjdGl2ZUZydXN0dW0oKTsKICAgICAgaW5pdF9QcmltaXRpdmVUeXBlKCk7CiAgICAgIGluaXRfUXVhdGVybmlvbigpOwogICAgICBQRVJTUEVDVElWRTIgPSAwOwogICAgICBPUlRIT0dSQVBISUMyID0gMTsKICAgICAgRnJ1c3R1bU91dGxpbmVHZW9tZXRyeS5wYWNrID0gZnVuY3Rpb24odmFsdWUsIGFycmF5LCBzdGFydGluZ0luZGV4KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJ2YWx1ZSIsIHZhbHVlKTsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgY29uc3QgZnJ1c3R1bVR5cGUgPSB2YWx1ZS5fZnJ1c3R1bVR5cGU7CiAgICAgICAgY29uc3QgZnJ1c3R1bSA9IHZhbHVlLl9mcnVzdHVtOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSBmcnVzdHVtVHlwZTsKICAgICAgICBpZiAoZnJ1c3R1bVR5cGUgPT09IFBFUlNQRUNUSVZFMikgewogICAgICAgICAgUGVyc3BlY3RpdmVGcnVzdHVtX2RlZmF1bHQucGFjayhmcnVzdHVtLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgICBzdGFydGluZ0luZGV4ICs9IFBlcnNwZWN0aXZlRnJ1c3R1bV9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgT3J0aG9ncmFwaGljRnJ1c3R1bV9kZWZhdWx0LnBhY2soZnJ1c3R1bSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgICAgc3RhcnRpbmdJbmRleCArPSBPcnRob2dyYXBoaWNGcnVzdHVtX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIH0KICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayh2YWx1ZS5fb3JpZ2luLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIFF1YXRlcm5pb25fZGVmYXVsdC5wYWNrKHZhbHVlLl9vcmllbnRhdGlvbiwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gUXVhdGVybmlvbl9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLl9kcmF3TmVhclBsYW5lID8gMSA6IDA7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBzY3JhdGNoUGFja1BlcnNwZWN0aXZlMiA9IG5ldyBQZXJzcGVjdGl2ZUZydXN0dW1fZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGFja09ydGhvZ3JhcGhpYzIgPSBuZXcgT3J0aG9ncmFwaGljRnJ1c3R1bV9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQYWNrUXVhdGVybmlvbjIgPSBuZXcgUXVhdGVybmlvbl9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQYWNrb3JpZ2luMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgRnJ1c3R1bU91dGxpbmVHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGNvbnN0IGZydXN0dW1UeXBlID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBsZXQgZnJ1c3R1bTsKICAgICAgICBpZiAoZnJ1c3R1bVR5cGUgPT09IFBFUlNQRUNUSVZFMikgewogICAgICAgICAgZnJ1c3R1bSA9IFBlcnNwZWN0aXZlRnJ1c3R1bV9kZWZhdWx0LnVucGFjaygKICAgICAgICAgICAgYXJyYXksCiAgICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICAgIHNjcmF0Y2hQYWNrUGVyc3BlY3RpdmUyCiAgICAgICAgICApOwogICAgICAgICAgc3RhcnRpbmdJbmRleCArPSBQZXJzcGVjdGl2ZUZydXN0dW1fZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGZydXN0dW0gPSBPcnRob2dyYXBoaWNGcnVzdHVtX2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgICBhcnJheSwKICAgICAgICAgICAgc3RhcnRpbmdJbmRleCwKICAgICAgICAgICAgc2NyYXRjaFBhY2tPcnRob2dyYXBoaWMyCiAgICAgICAgICApOwogICAgICAgICAgc3RhcnRpbmdJbmRleCArPSBPcnRob2dyYXBoaWNGcnVzdHVtX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIH0KICAgICAgICBjb25zdCBvcmlnaW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoUGFja29yaWdpbjIpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCBvcmllbnRhdGlvbiA9IFF1YXRlcm5pb25fZGVmYXVsdC51bnBhY2soCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICBzY3JhdGNoUGFja1F1YXRlcm5pb24yCiAgICAgICAgKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFF1YXRlcm5pb25fZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgZHJhd05lYXJQbGFuZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdID09PSAxOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgRnJ1c3R1bU91dGxpbmVHZW9tZXRyeSh7CiAgICAgICAgICAgIGZydXN0dW0sCiAgICAgICAgICAgIG9yaWdpbiwKICAgICAgICAgICAgb3JpZW50YXRpb24sCiAgICAgICAgICAgIF9kcmF3TmVhclBsYW5lOiBkcmF3TmVhclBsYW5lCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZnJ1c3R1bVJlc3VsdCA9IGZydXN0dW1UeXBlID09PSByZXN1bHQuX2ZydXN0dW1UeXBlID8gcmVzdWx0Ll9mcnVzdHVtIDogdm9pZCAwOwogICAgICAgIHJlc3VsdC5fZnJ1c3R1bSA9IGZydXN0dW0uY2xvbmUoZnJ1c3R1bVJlc3VsdCk7CiAgICAgICAgcmVzdWx0Ll9mcnVzdHVtVHlwZSA9IGZydXN0dW1UeXBlOwogICAgICAgIHJlc3VsdC5fb3JpZ2luID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKG9yaWdpbiwgcmVzdWx0Ll9vcmlnaW4pOwogICAgICAgIHJlc3VsdC5fb3JpZW50YXRpb24gPSBRdWF0ZXJuaW9uX2RlZmF1bHQuY2xvbmUob3JpZW50YXRpb24sIHJlc3VsdC5fb3JpZW50YXRpb24pOwogICAgICAgIHJlc3VsdC5fZHJhd05lYXJQbGFuZSA9IGRyYXdOZWFyUGxhbmU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgRnJ1c3R1bU91dGxpbmVHZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKGZydXN0dW1HZW9tZXRyeSkgewogICAgICAgIGNvbnN0IGZydXN0dW1UeXBlID0gZnJ1c3R1bUdlb21ldHJ5Ll9mcnVzdHVtVHlwZTsKICAgICAgICBjb25zdCBmcnVzdHVtID0gZnJ1c3R1bUdlb21ldHJ5Ll9mcnVzdHVtOwogICAgICAgIGNvbnN0IG9yaWdpbiA9IGZydXN0dW1HZW9tZXRyeS5fb3JpZ2luOwogICAgICAgIGNvbnN0IG9yaWVudGF0aW9uID0gZnJ1c3R1bUdlb21ldHJ5Ll9vcmllbnRhdGlvbjsKICAgICAgICBjb25zdCBkcmF3TmVhclBsYW5lID0gZnJ1c3R1bUdlb21ldHJ5Ll9kcmF3TmVhclBsYW5lOwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkoMyAqIDQgKiAyKTsKICAgICAgICBGcnVzdHVtR2VvbWV0cnlfZGVmYXVsdC5fY29tcHV0ZU5lYXJGYXJQbGFuZXMoCiAgICAgICAgICBvcmlnaW4sCiAgICAgICAgICBvcmllbnRhdGlvbiwKICAgICAgICAgIGZydXN0dW1UeXBlLAogICAgICAgICAgZnJ1c3R1bSwKICAgICAgICAgIHBvc2l0aW9ucwogICAgICAgICk7CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZXNfZGVmYXVsdCh7CiAgICAgICAgICBwb3NpdGlvbjogbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICAgIHZhbHVlczogcG9zaXRpb25zCiAgICAgICAgICB9KQogICAgICAgIH0pOwogICAgICAgIGxldCBvZmZzZXQ7CiAgICAgICAgbGV0IGluZGV4OwogICAgICAgIGNvbnN0IG51bWJlck9mUGxhbmVzID0gZHJhd05lYXJQbGFuZSA/IDIgOiAxOwogICAgICAgIGNvbnN0IGluZGljZXMgPSBuZXcgVWludDE2QXJyYXkoOCAqIChudW1iZXJPZlBsYW5lcyArIDEpKTsKICAgICAgICBsZXQgaSA9IGRyYXdOZWFyUGxhbmUgPyAwIDogMTsKICAgICAgICBmb3IgKDsgaSA8IDI7ICsraSkgewogICAgICAgICAgb2Zmc2V0ID0gZHJhd05lYXJQbGFuZSA/IGkgKiA4IDogMDsKICAgICAgICAgIGluZGV4ID0gaSAqIDQ7CiAgICAgICAgICBpbmRpY2VzW29mZnNldF0gPSBpbmRleDsKICAgICAgICAgIGluZGljZXNbb2Zmc2V0ICsgMV0gPSBpbmRleCArIDE7CiAgICAgICAgICBpbmRpY2VzW29mZnNldCArIDJdID0gaW5kZXggKyAxOwogICAgICAgICAgaW5kaWNlc1tvZmZzZXQgKyAzXSA9IGluZGV4ICsgMjsKICAgICAgICAgIGluZGljZXNbb2Zmc2V0ICsgNF0gPSBpbmRleCArIDI7CiAgICAgICAgICBpbmRpY2VzW29mZnNldCArIDVdID0gaW5kZXggKyAzOwogICAgICAgICAgaW5kaWNlc1tvZmZzZXQgKyA2XSA9IGluZGV4ICsgMzsKICAgICAgICAgIGluZGljZXNbb2Zmc2V0ICsgN10gPSBpbmRleDsKICAgICAgICB9CiAgICAgICAgZm9yIChpID0gMDsgaSA8IDI7ICsraSkgewogICAgICAgICAgb2Zmc2V0ID0gKG51bWJlck9mUGxhbmVzICsgaSkgKiA4OwogICAgICAgICAgaW5kZXggPSBpICogNDsKICAgICAgICAgIGluZGljZXNbb2Zmc2V0XSA9IGluZGV4OwogICAgICAgICAgaW5kaWNlc1tvZmZzZXQgKyAxXSA9IGluZGV4ICsgNDsKICAgICAgICAgIGluZGljZXNbb2Zmc2V0ICsgMl0gPSBpbmRleCArIDE7CiAgICAgICAgICBpbmRpY2VzW29mZnNldCArIDNdID0gaW5kZXggKyA1OwogICAgICAgICAgaW5kaWNlc1tvZmZzZXQgKyA0XSA9IGluZGV4ICsgMjsKICAgICAgICAgIGluZGljZXNbb2Zmc2V0ICsgNV0gPSBpbmRleCArIDY7CiAgICAgICAgICBpbmRpY2VzW29mZnNldCArIDZdID0gaW5kZXggKyAzOwogICAgICAgICAgaW5kaWNlc1tvZmZzZXQgKyA3XSA9IGluZGV4ICsgNzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgICAgIGF0dHJpYnV0ZXMsCiAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LkxJTkVTLAogICAgICAgICAgYm91bmRpbmdTcGhlcmU6IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbVZlcnRpY2VzKHBvc2l0aW9ucykKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgRnJ1c3R1bU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gRnJ1c3R1bU91dGxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUZydXN0dW1PdXRsaW5lR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlRnJ1c3R1bU91dGxpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlRnJ1c3R1bU91dGxpbmVHZW9tZXRyeV9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVGcnVzdHVtT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVGcnVzdHVtT3V0bGluZUdlb21ldHJ5KGZydXN0dW1HZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgZnJ1c3R1bUdlb21ldHJ5ID0gRnJ1c3R1bU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjayhmcnVzdHVtR2VvbWV0cnksIG9mZnNldCk7CiAgICB9CiAgICByZXR1cm4gRnJ1c3R1bU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LmNyZWF0ZUdlb21ldHJ5KGZydXN0dW1HZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVGcnVzdHVtT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlRnJ1c3R1bU91dGxpbmVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlRnJ1c3R1bU91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0ZydXN0dW1PdXRsaW5lR2VvbWV0cnkoKTsKICAgICAgY3JlYXRlRnJ1c3R1bU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gY3JlYXRlRnJ1c3R1bU91dGxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dlb2dyYXBoaWNUaWxpbmdTY2hlbWUuanMKICBmdW5jdGlvbiBHZW9ncmFwaGljVGlsaW5nU2NoZW1lKG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIHRoaXMuX2VsbGlwc29pZCA9IG9wdGlvbnMuZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICB0aGlzLl9yZWN0YW5nbGUgPSBvcHRpb25zLnJlY3RhbmdsZSA/PyBSZWN0YW5nbGVfZGVmYXVsdC5NQVhfVkFMVUU7CiAgICB0aGlzLl9wcm9qZWN0aW9uID0gbmV3IEdlb2dyYXBoaWNQcm9qZWN0aW9uX2RlZmF1bHQodGhpcy5fZWxsaXBzb2lkKTsKICAgIHRoaXMuX251bWJlck9mTGV2ZWxaZXJvVGlsZXNYID0gb3B0aW9ucy5udW1iZXJPZkxldmVsWmVyb1RpbGVzWCA/PyAyOwogICAgdGhpcy5fbnVtYmVyT2ZMZXZlbFplcm9UaWxlc1kgPSBvcHRpb25zLm51bWJlck9mTGV2ZWxaZXJvVGlsZXNZID8/IDE7CiAgfQogIHZhciBHZW9ncmFwaGljVGlsaW5nU2NoZW1lX2RlZmF1bHQ7CiAgdmFyIGluaXRfR2VvZ3JhcGhpY1RpbGluZ1NjaGVtZSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvR2VvZ3JhcGhpY1RpbGluZ1NjaGVtZS5qcyIoKSB7CiAgICAgIGluaXRfQ2FydGVzaWFuMigpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0dlb2dyYXBoaWNQcm9qZWN0aW9uKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1JlY3RhbmdsZSgpOwogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhHZW9ncmFwaGljVGlsaW5nU2NoZW1lLnByb3RvdHlwZSwgewogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIGVsbGlwc29pZCB0aGF0IGlzIHRpbGVkIGJ5IHRoaXMgdGlsaW5nIHNjaGVtZS4KICAgICAgICAgKiBAbWVtYmVyb2YgR2VvZ3JhcGhpY1RpbGluZ1NjaGVtZS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7RWxsaXBzb2lkfQogICAgICAgICAqLwogICAgICAgIGVsbGlwc29pZDogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2VsbGlwc29pZDsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgdGhlIHJlY3RhbmdsZSwgaW4gcmFkaWFucywgY292ZXJlZCBieSB0aGlzIHRpbGluZyBzY2hlbWUuCiAgICAgICAgICogQG1lbWJlcm9mIEdlb2dyYXBoaWNUaWxpbmdTY2hlbWUucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge1JlY3RhbmdsZX0KICAgICAgICAgKi8KICAgICAgICByZWN0YW5nbGU6IHsKICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9yZWN0YW5nbGU7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBtYXAgcHJvamVjdGlvbiB1c2VkIGJ5IHRoaXMgdGlsaW5nIHNjaGVtZS4KICAgICAgICAgKiBAbWVtYmVyb2YgR2VvZ3JhcGhpY1RpbGluZ1NjaGVtZS5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7TWFwUHJvamVjdGlvbn0KICAgICAgICAgKi8KICAgICAgICBwcm9qZWN0aW9uOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fcHJvamVjdGlvbjsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pOwogICAgICBHZW9ncmFwaGljVGlsaW5nU2NoZW1lLnByb3RvdHlwZS5nZXROdW1iZXJPZlhUaWxlc0F0TGV2ZWwgPSBmdW5jdGlvbihsZXZlbCkgewogICAgICAgIHJldHVybiB0aGlzLl9udW1iZXJPZkxldmVsWmVyb1RpbGVzWCA8PCBsZXZlbDsKICAgICAgfTsKICAgICAgR2VvZ3JhcGhpY1RpbGluZ1NjaGVtZS5wcm90b3R5cGUuZ2V0TnVtYmVyT2ZZVGlsZXNBdExldmVsID0gZnVuY3Rpb24obGV2ZWwpIHsKICAgICAgICByZXR1cm4gdGhpcy5fbnVtYmVyT2ZMZXZlbFplcm9UaWxlc1kgPDwgbGV2ZWw7CiAgICAgIH07CiAgICAgIEdlb2dyYXBoaWNUaWxpbmdTY2hlbWUucHJvdG90eXBlLnJlY3RhbmdsZVRvTmF0aXZlUmVjdGFuZ2xlID0gZnVuY3Rpb24ocmVjdGFuZ2xlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInJlY3RhbmdsZSIsIHJlY3RhbmdsZSk7CiAgICAgICAgY29uc3Qgd2VzdCA9IE1hdGhfZGVmYXVsdC50b0RlZ3JlZXMocmVjdGFuZ2xlLndlc3QpOwogICAgICAgIGNvbnN0IHNvdXRoID0gTWF0aF9kZWZhdWx0LnRvRGVncmVlcyhyZWN0YW5nbGUuc291dGgpOwogICAgICAgIGNvbnN0IGVhc3QgPSBNYXRoX2RlZmF1bHQudG9EZWdyZWVzKHJlY3RhbmdsZS5lYXN0KTsKICAgICAgICBjb25zdCBub3J0aCA9IE1hdGhfZGVmYXVsdC50b0RlZ3JlZXMocmVjdGFuZ2xlLm5vcnRoKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFJlY3RhbmdsZV9kZWZhdWx0KHdlc3QsIHNvdXRoLCBlYXN0LCBub3J0aCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC53ZXN0ID0gd2VzdDsKICAgICAgICByZXN1bHQuc291dGggPSBzb3V0aDsKICAgICAgICByZXN1bHQuZWFzdCA9IGVhc3Q7CiAgICAgICAgcmVzdWx0Lm5vcnRoID0gbm9ydGg7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgR2VvZ3JhcGhpY1RpbGluZ1NjaGVtZS5wcm90b3R5cGUudGlsZVhZVG9OYXRpdmVSZWN0YW5nbGUgPSBmdW5jdGlvbih4LCB5LCBsZXZlbCwgcmVzdWx0KSB7CiAgICAgICAgY29uc3QgcmVjdGFuZ2xlUmFkaWFucyA9IHRoaXMudGlsZVhZVG9SZWN0YW5nbGUoeCwgeSwgbGV2ZWwsIHJlc3VsdCk7CiAgICAgICAgcmVjdGFuZ2xlUmFkaWFucy53ZXN0ID0gTWF0aF9kZWZhdWx0LnRvRGVncmVlcyhyZWN0YW5nbGVSYWRpYW5zLndlc3QpOwogICAgICAgIHJlY3RhbmdsZVJhZGlhbnMuc291dGggPSBNYXRoX2RlZmF1bHQudG9EZWdyZWVzKHJlY3RhbmdsZVJhZGlhbnMuc291dGgpOwogICAgICAgIHJlY3RhbmdsZVJhZGlhbnMuZWFzdCA9IE1hdGhfZGVmYXVsdC50b0RlZ3JlZXMocmVjdGFuZ2xlUmFkaWFucy5lYXN0KTsKICAgICAgICByZWN0YW5nbGVSYWRpYW5zLm5vcnRoID0gTWF0aF9kZWZhdWx0LnRvRGVncmVlcyhyZWN0YW5nbGVSYWRpYW5zLm5vcnRoKTsKICAgICAgICByZXR1cm4gcmVjdGFuZ2xlUmFkaWFuczsKICAgICAgfTsKICAgICAgR2VvZ3JhcGhpY1RpbGluZ1NjaGVtZS5wcm90b3R5cGUudGlsZVhZVG9SZWN0YW5nbGUgPSBmdW5jdGlvbih4LCB5LCBsZXZlbCwgcmVzdWx0KSB7CiAgICAgICAgY29uc3QgcmVjdGFuZ2xlID0gdGhpcy5fcmVjdGFuZ2xlOwogICAgICAgIGNvbnN0IHhUaWxlcyA9IHRoaXMuZ2V0TnVtYmVyT2ZYVGlsZXNBdExldmVsKGxldmVsKTsKICAgICAgICBjb25zdCB5VGlsZXMgPSB0aGlzLmdldE51bWJlck9mWVRpbGVzQXRMZXZlbChsZXZlbCk7CiAgICAgICAgY29uc3QgeFRpbGVXaWR0aCA9IHJlY3RhbmdsZS53aWR0aCAvIHhUaWxlczsKICAgICAgICBjb25zdCB3ZXN0ID0geCAqIHhUaWxlV2lkdGggKyByZWN0YW5nbGUud2VzdDsKICAgICAgICBjb25zdCBlYXN0ID0gKHggKyAxKSAqIHhUaWxlV2lkdGggKyByZWN0YW5nbGUud2VzdDsKICAgICAgICBjb25zdCB5VGlsZUhlaWdodCA9IHJlY3RhbmdsZS5oZWlnaHQgLyB5VGlsZXM7CiAgICAgICAgY29uc3Qgbm9ydGggPSByZWN0YW5nbGUubm9ydGggLSB5ICogeVRpbGVIZWlnaHQ7CiAgICAgICAgY29uc3Qgc291dGggPSByZWN0YW5nbGUubm9ydGggLSAoeSArIDEpICogeVRpbGVIZWlnaHQ7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IFJlY3RhbmdsZV9kZWZhdWx0KHdlc3QsIHNvdXRoLCBlYXN0LCBub3J0aCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC53ZXN0ID0gd2VzdDsKICAgICAgICByZXN1bHQuc291dGggPSBzb3V0aDsKICAgICAgICByZXN1bHQuZWFzdCA9IGVhc3Q7CiAgICAgICAgcmVzdWx0Lm5vcnRoID0gbm9ydGg7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgR2VvZ3JhcGhpY1RpbGluZ1NjaGVtZS5wcm90b3R5cGUucG9zaXRpb25Ub1RpbGVYWSA9IGZ1bmN0aW9uKHBvc2l0aW9uLCBsZXZlbCwgcmVzdWx0KSB7CiAgICAgICAgY29uc3QgcmVjdGFuZ2xlID0gdGhpcy5fcmVjdGFuZ2xlOwogICAgICAgIGlmICghUmVjdGFuZ2xlX2RlZmF1bHQuY29udGFpbnMocmVjdGFuZ2xlLCBwb3NpdGlvbikpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHhUaWxlcyA9IHRoaXMuZ2V0TnVtYmVyT2ZYVGlsZXNBdExldmVsKGxldmVsKTsKICAgICAgICBjb25zdCB5VGlsZXMgPSB0aGlzLmdldE51bWJlck9mWVRpbGVzQXRMZXZlbChsZXZlbCk7CiAgICAgICAgY29uc3QgeFRpbGVXaWR0aCA9IHJlY3RhbmdsZS53aWR0aCAvIHhUaWxlczsKICAgICAgICBjb25zdCB5VGlsZUhlaWdodCA9IHJlY3RhbmdsZS5oZWlnaHQgLyB5VGlsZXM7CiAgICAgICAgbGV0IGxvbmdpdHVkZSA9IHBvc2l0aW9uLmxvbmdpdHVkZTsKICAgICAgICBpZiAocmVjdGFuZ2xlLmVhc3QgPCByZWN0YW5nbGUud2VzdCkgewogICAgICAgICAgbG9uZ2l0dWRlICs9IE1hdGhfZGVmYXVsdC5UV09fUEk7CiAgICAgICAgfQogICAgICAgIGxldCB4VGlsZUNvb3JkaW5hdGUgPSAobG9uZ2l0dWRlIC0gcmVjdGFuZ2xlLndlc3QpIC8geFRpbGVXaWR0aCB8IDA7CiAgICAgICAgaWYgKHhUaWxlQ29vcmRpbmF0ZSA+PSB4VGlsZXMpIHsKICAgICAgICAgIHhUaWxlQ29vcmRpbmF0ZSA9IHhUaWxlcyAtIDE7CiAgICAgICAgfQogICAgICAgIGxldCB5VGlsZUNvb3JkaW5hdGUgPSAocmVjdGFuZ2xlLm5vcnRoIC0gcG9zaXRpb24ubGF0aXR1ZGUpIC8geVRpbGVIZWlnaHQgfCAwOwogICAgICAgIGlmICh5VGlsZUNvb3JkaW5hdGUgPj0geVRpbGVzKSB7CiAgICAgICAgICB5VGlsZUNvb3JkaW5hdGUgPSB5VGlsZXMgLSAxOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCh4VGlsZUNvb3JkaW5hdGUsIHlUaWxlQ29vcmRpbmF0ZSk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC54ID0geFRpbGVDb29yZGluYXRlOwogICAgICAgIHJlc3VsdC55ID0geVRpbGVDb29yZGluYXRlOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEdlb2dyYXBoaWNUaWxpbmdTY2hlbWVfZGVmYXVsdCA9IEdlb2dyYXBoaWNUaWxpbmdTY2hlbWU7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9BcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLmpzCiAgZnVuY3Rpb24gZ2V0VGlsZVhZTGV2ZWwocmVjdGFuZ2xlKSB7CiAgICBDYXJ0b2dyYXBoaWNfZGVmYXVsdC5mcm9tUmFkaWFucygKICAgICAgcmVjdGFuZ2xlLmVhc3QsCiAgICAgIHJlY3RhbmdsZS5ub3J0aCwKICAgICAgMCwKICAgICAgc2NyYXRjaENvcm5lcnNbMF0KICAgICk7CiAgICBDYXJ0b2dyYXBoaWNfZGVmYXVsdC5mcm9tUmFkaWFucygKICAgICAgcmVjdGFuZ2xlLndlc3QsCiAgICAgIHJlY3RhbmdsZS5ub3J0aCwKICAgICAgMCwKICAgICAgc2NyYXRjaENvcm5lcnNbMV0KICAgICk7CiAgICBDYXJ0b2dyYXBoaWNfZGVmYXVsdC5mcm9tUmFkaWFucygKICAgICAgcmVjdGFuZ2xlLmVhc3QsCiAgICAgIHJlY3RhbmdsZS5zb3V0aCwKICAgICAgMCwKICAgICAgc2NyYXRjaENvcm5lcnNbMl0KICAgICk7CiAgICBDYXJ0b2dyYXBoaWNfZGVmYXVsdC5mcm9tUmFkaWFucygKICAgICAgcmVjdGFuZ2xlLndlc3QsCiAgICAgIHJlY3RhbmdsZS5zb3V0aCwKICAgICAgMCwKICAgICAgc2NyYXRjaENvcm5lcnNbM10KICAgICk7CiAgICBsZXQgbGFzdExldmVsWCA9IDAsIGxhc3RMZXZlbFkgPSAwOwogICAgbGV0IGN1cnJlbnRYID0gMCwgY3VycmVudFkgPSAwOwogICAgY29uc3QgbWF4TGV2ZWwgPSBBcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLl90ZXJyYWluSGVpZ2h0c01heExldmVsOwogICAgbGV0IGk7CiAgICBmb3IgKGkgPSAwOyBpIDw9IG1heExldmVsOyArK2kpIHsKICAgICAgbGV0IGZhaWxlZCA9IGZhbHNlOwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IDQ7ICsraikgewogICAgICAgIGNvbnN0IGNvcm5lciA9IHNjcmF0Y2hDb3JuZXJzW2pdOwogICAgICAgIHRpbGluZ1NjaGVtZS5wb3NpdGlvblRvVGlsZVhZKGNvcm5lciwgaSwgc2NyYXRjaFRpbGVYWSk7CiAgICAgICAgaWYgKGogPT09IDApIHsKICAgICAgICAgIGN1cnJlbnRYID0gc2NyYXRjaFRpbGVYWS54OwogICAgICAgICAgY3VycmVudFkgPSBzY3JhdGNoVGlsZVhZLnk7CiAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50WCAhPT0gc2NyYXRjaFRpbGVYWS54IHx8IGN1cnJlbnRZICE9PSBzY3JhdGNoVGlsZVhZLnkpIHsKICAgICAgICAgIGZhaWxlZCA9IHRydWU7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGZhaWxlZCkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGxhc3RMZXZlbFggPSBjdXJyZW50WDsKICAgICAgbGFzdExldmVsWSA9IGN1cnJlbnRZOwogICAgfQogICAgaWYgKGkgPT09IDApIHsKICAgICAgcmV0dXJuIHZvaWQgMDsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIHg6IGxhc3RMZXZlbFgsCiAgICAgIHk6IGxhc3RMZXZlbFksCiAgICAgIGxldmVsOiBpID4gbWF4TGV2ZWwgPyBtYXhMZXZlbCA6IGkgLSAxCiAgICB9OwogIH0KICB2YXIgc2NyYXRjaERpYWdvbmFsQ2FydGVzaWFuTkUsIHNjcmF0Y2hEaWFnb25hbENhcnRlc2lhblNXLCBzY3JhdGNoRGlhZ29uYWxDYXJ0b2dyYXBoaWMsIHNjcmF0Y2hDZW50ZXJDYXJ0ZXNpYW4sIHNjcmF0Y2hTdXJmYWNlQ2FydGVzaWFuLCBzY3JhdGNoQm91bmRpbmdTcGhlcmUyLCB0aWxpbmdTY2hlbWUsIHNjcmF0Y2hDb3JuZXJzLCBzY3JhdGNoVGlsZVhZLCBBcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLCBBcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzX2RlZmF1bHQ7CiAgdmFyIGluaXRfQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cy5qcyIoKSB7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9idWlsZE1vZHVsZVVybCgpOwogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9HZW9ncmFwaGljVGlsaW5nU2NoZW1lKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfUmVzb3VyY2UoKTsKICAgICAgc2NyYXRjaERpYWdvbmFsQ2FydGVzaWFuTkUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hEaWFnb25hbENhcnRlc2lhblNXID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoRGlhZ29uYWxDYXJ0b2dyYXBoaWMgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENlbnRlckNhcnRlc2lhbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFN1cmZhY2VDYXJ0ZXNpYW4gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hCb3VuZGluZ1NwaGVyZTIgPSBuZXcgQm91bmRpbmdTcGhlcmVfZGVmYXVsdCgpOwogICAgICB0aWxpbmdTY2hlbWUgPSBuZXcgR2VvZ3JhcGhpY1RpbGluZ1NjaGVtZV9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDb3JuZXJzID0gWwogICAgICAgIG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpLAogICAgICAgIG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpLAogICAgICAgIG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpLAogICAgICAgIG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpCiAgICAgIF07CiAgICAgIHNjcmF0Y2hUaWxlWFkgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIEFwcHJveGltYXRlVGVycmFpbkhlaWdodHMgPSB7fTsKICAgICAgQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cy5pbml0aWFsaXplID0gZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IGluaXRQcm9taXNlID0gQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cy5faW5pdFByb21pc2U7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChpbml0UHJvbWlzZSkpIHsKICAgICAgICAgIHJldHVybiBpbml0UHJvbWlzZTsKICAgICAgICB9CiAgICAgICAgaW5pdFByb21pc2UgPSBSZXNvdXJjZV9kZWZhdWx0LmZldGNoSnNvbigKICAgICAgICAgIGJ1aWxkTW9kdWxlVXJsX2RlZmF1bHQoIkFzc2V0cy9hcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLmpzb24iKQogICAgICAgICkudGhlbihmdW5jdGlvbihqc29uKSB7CiAgICAgICAgICBBcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLl90ZXJyYWluSGVpZ2h0cyA9IGpzb247CiAgICAgICAgfSk7CiAgICAgICAgQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cy5faW5pdFByb21pc2UgPSBpbml0UHJvbWlzZTsKICAgICAgICByZXR1cm4gaW5pdFByb21pc2U7CiAgICAgIH07CiAgICAgIEFwcHJveGltYXRlVGVycmFpbkhlaWdodHMuZ2V0TWluaW11bU1heGltdW1IZWlnaHRzID0gZnVuY3Rpb24ocmVjdGFuZ2xlLCBlbGxpcHNvaWQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInJlY3RhbmdsZSIsIHJlY3RhbmdsZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cy5fdGVycmFpbkhlaWdodHMpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgIllvdSBtdXN0IGNhbGwgQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cy5pbml0aWFsaXplIGFuZCB3YWl0IGZvciB0aGUgcHJvbWlzZSB0byByZXNvbHZlIGJlZm9yZSB1c2luZyB0aGlzIGZ1bmN0aW9uIgogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgZWxsaXBzb2lkID0gZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICAgICAgY29uc3QgeHlMZXZlbCA9IGdldFRpbGVYWUxldmVsKHJlY3RhbmdsZSk7CiAgICAgICAgbGV0IG1pblRlcnJhaW5IZWlnaHQgPSBBcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLl9kZWZhdWx0TWluVGVycmFpbkhlaWdodDsKICAgICAgICBsZXQgbWF4VGVycmFpbkhlaWdodCA9IEFwcHJveGltYXRlVGVycmFpbkhlaWdodHMuX2RlZmF1bHRNYXhUZXJyYWluSGVpZ2h0OwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoeHlMZXZlbCkpIHsKICAgICAgICAgIGNvbnN0IGtleSA9IGAke3h5TGV2ZWwubGV2ZWx9LSR7eHlMZXZlbC54fS0ke3h5TGV2ZWwueX1gOwogICAgICAgICAgY29uc3QgaGVpZ2h0cyA9IEFwcHJveGltYXRlVGVycmFpbkhlaWdodHMuX3RlcnJhaW5IZWlnaHRzW2tleV07CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGhlaWdodHMpKSB7CiAgICAgICAgICAgIG1pblRlcnJhaW5IZWlnaHQgPSBoZWlnaHRzWzBdOwogICAgICAgICAgICBtYXhUZXJyYWluSGVpZ2h0ID0gaGVpZ2h0c1sxXTsKICAgICAgICAgIH0KICAgICAgICAgIGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbigKICAgICAgICAgICAgUmVjdGFuZ2xlX2RlZmF1bHQubm9ydGhlYXN0KHJlY3RhbmdsZSwgc2NyYXRjaERpYWdvbmFsQ2FydG9ncmFwaGljKSwKICAgICAgICAgICAgc2NyYXRjaERpYWdvbmFsQ2FydGVzaWFuTkUKICAgICAgICAgICk7CiAgICAgICAgICBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oCiAgICAgICAgICAgIFJlY3RhbmdsZV9kZWZhdWx0LnNvdXRod2VzdChyZWN0YW5nbGUsIHNjcmF0Y2hEaWFnb25hbENhcnRvZ3JhcGhpYyksCiAgICAgICAgICAgIHNjcmF0Y2hEaWFnb25hbENhcnRlc2lhblNXCiAgICAgICAgICApOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm1pZHBvaW50KAogICAgICAgICAgICBzY3JhdGNoRGlhZ29uYWxDYXJ0ZXNpYW5TVywKICAgICAgICAgICAgc2NyYXRjaERpYWdvbmFsQ2FydGVzaWFuTkUsCiAgICAgICAgICAgIHNjcmF0Y2hDZW50ZXJDYXJ0ZXNpYW4KICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBzdXJmYWNlUG9zaXRpb24gPSBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZSgKICAgICAgICAgICAgc2NyYXRjaENlbnRlckNhcnRlc2lhbiwKICAgICAgICAgICAgc2NyYXRjaFN1cmZhY2VDYXJ0ZXNpYW4KICAgICAgICAgICk7CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHN1cmZhY2VQb3NpdGlvbikpIHsKICAgICAgICAgICAgY29uc3QgZGlzdGFuY2UgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZGlzdGFuY2UoCiAgICAgICAgICAgICAgc2NyYXRjaENlbnRlckNhcnRlc2lhbiwKICAgICAgICAgICAgICBzdXJmYWNlUG9zaXRpb24KICAgICAgICAgICAgKTsKICAgICAgICAgICAgbWluVGVycmFpbkhlaWdodCA9IE1hdGgubWluKG1pblRlcnJhaW5IZWlnaHQsIC1kaXN0YW5jZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBtaW5UZXJyYWluSGVpZ2h0ID0gQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cy5fZGVmYXVsdE1pblRlcnJhaW5IZWlnaHQ7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG1pblRlcnJhaW5IZWlnaHQgPSBNYXRoLm1heCgKICAgICAgICAgIEFwcHJveGltYXRlVGVycmFpbkhlaWdodHMuX2RlZmF1bHRNaW5UZXJyYWluSGVpZ2h0LAogICAgICAgICAgbWluVGVycmFpbkhlaWdodAogICAgICAgICk7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIG1pbmltdW1UZXJyYWluSGVpZ2h0OiBtaW5UZXJyYWluSGVpZ2h0LAogICAgICAgICAgbWF4aW11bVRlcnJhaW5IZWlnaHQ6IG1heFRlcnJhaW5IZWlnaHQKICAgICAgICB9OwogICAgICB9OwogICAgICBBcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLmdldEJvdW5kaW5nU3BoZXJlID0gZnVuY3Rpb24ocmVjdGFuZ2xlLCBlbGxpcHNvaWQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInJlY3RhbmdsZSIsIHJlY3RhbmdsZSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cy5fdGVycmFpbkhlaWdodHMpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgIllvdSBtdXN0IGNhbGwgQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cy5pbml0aWFsaXplIGFuZCB3YWl0IGZvciB0aGUgcHJvbWlzZSB0byByZXNvbHZlIGJlZm9yZSB1c2luZyB0aGlzIGZ1bmN0aW9uIgogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgZWxsaXBzb2lkID0gZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICAgICAgY29uc3QgeHlMZXZlbCA9IGdldFRpbGVYWUxldmVsKHJlY3RhbmdsZSk7CiAgICAgICAgbGV0IG1heFRlcnJhaW5IZWlnaHQgPSBBcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLl9kZWZhdWx0TWF4VGVycmFpbkhlaWdodDsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHh5TGV2ZWwpKSB7CiAgICAgICAgICBjb25zdCBrZXkgPSBgJHt4eUxldmVsLmxldmVsfS0ke3h5TGV2ZWwueH0tJHt4eUxldmVsLnl9YDsKICAgICAgICAgIGNvbnN0IGhlaWdodHMgPSBBcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLl90ZXJyYWluSGVpZ2h0c1trZXldOwogICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChoZWlnaHRzKSkgewogICAgICAgICAgICBtYXhUZXJyYWluSGVpZ2h0ID0gaGVpZ2h0c1sxXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgcmVzdWx0ID0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5mcm9tUmVjdGFuZ2xlM0QocmVjdGFuZ2xlLCBlbGxpcHNvaWQsIDApOwogICAgICAgIEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbVJlY3RhbmdsZTNEKAogICAgICAgICAgcmVjdGFuZ2xlLAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgbWF4VGVycmFpbkhlaWdodCwKICAgICAgICAgIHNjcmF0Y2hCb3VuZGluZ1NwaGVyZTIKICAgICAgICApOwogICAgICAgIHJldHVybiBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LnVuaW9uKHJlc3VsdCwgc2NyYXRjaEJvdW5kaW5nU3BoZXJlMiwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cy5fdGVycmFpbkhlaWdodHNNYXhMZXZlbCA9IDY7CiAgICAgIEFwcHJveGltYXRlVGVycmFpbkhlaWdodHMuX2RlZmF1bHRNYXhUZXJyYWluSGVpZ2h0ID0gOWUzOwogICAgICBBcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLl9kZWZhdWx0TWluVGVycmFpbkhlaWdodCA9IC0xZTU7CiAgICAgIEFwcHJveGltYXRlVGVycmFpbkhlaWdodHMuX3RlcnJhaW5IZWlnaHRzID0gdm9pZCAwOwogICAgICBBcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLl9pbml0UHJvbWlzZSA9IHZvaWQgMDsKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cywgewogICAgICAgIC8qKgogICAgICAgICAqIERldGVybWluZXMgaWYgdGhlIHRlcnJhaW4gaGVpZ2h0cyBhcmUgaW5pdGlhbGl6ZWQgYW5kIHJlYWR5IHRvIHVzZS4gVG8gaW5pdGlhbGl6ZSB0aGUgdGVycmFpbiBoZWlnaHRzLAogICAgICAgICAqIGNhbGwge0BsaW5rIEFwcHJveGltYXRlVGVycmFpbkhlaWdodHMjaW5pdGlhbGl6ZX0gYW5kIHdhaXQgZm9yIHRoZSByZXR1cm5lZCBwcm9taXNlIHRvIHJlc29sdmUuCiAgICAgICAgICogQHR5cGUge2Jvb2xlYW59CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICogQG1lbWJlcm9mIEFwcHJveGltYXRlVGVycmFpbkhlaWdodHMKICAgICAgICAgKi8KICAgICAgICBpbml0aWFsaXplZDogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIGRlZmluZWRfZGVmYXVsdChBcHByb3hpbWF0ZVRlcnJhaW5IZWlnaHRzLl90ZXJyYWluSGVpZ2h0cyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0c19kZWZhdWx0ID0gQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0czsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dyb3VuZFBvbHlsaW5lR2VvbWV0cnkuanMKICBmdW5jdGlvbiBHcm91bmRQb2x5bGluZUdlb21ldHJ5KG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IG9wdGlvbnMucG9zaXRpb25zOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocG9zaXRpb25zKSB8fCBwb3NpdGlvbnMubGVuZ3RoIDwgMikgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiQXQgbGVhc3QgdHdvIHBvc2l0aW9ucyBhcmUgcmVxdWlyZWQuIik7CiAgICB9CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMuYXJjVHlwZSkgJiYgb3B0aW9ucy5hcmNUeXBlICE9PSBBcmNUeXBlX2RlZmF1bHQuR0VPREVTSUMgJiYgb3B0aW9ucy5hcmNUeXBlICE9PSBBcmNUeXBlX2RlZmF1bHQuUkhVTUIpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgIlZhbGlkIG9wdGlvbnMgZm9yIGFyY1R5cGUgYXJlIEFyY1R5cGUuR0VPREVTSUMgYW5kIEFyY1R5cGUuUkhVTUIuIgogICAgICApOwogICAgfQogICAgdGhpcy53aWR0aCA9IG9wdGlvbnMud2lkdGggPz8gMTsKICAgIHRoaXMuX3Bvc2l0aW9ucyA9IHBvc2l0aW9uczsKICAgIHRoaXMuZ3JhbnVsYXJpdHkgPSBvcHRpb25zLmdyYW51bGFyaXR5ID8/IDk5OTk7CiAgICB0aGlzLmxvb3AgPSBvcHRpb25zLmxvb3AgPz8gZmFsc2U7CiAgICB0aGlzLmFyY1R5cGUgPSBvcHRpb25zLmFyY1R5cGUgPz8gQXJjVHlwZV9kZWZhdWx0LkdFT0RFU0lDOwogICAgdGhpcy5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgIHRoaXMuX3Byb2plY3Rpb25JbmRleCA9IDA7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZUdyb3VuZFBvbHlsaW5lR2VvbWV0cnkiOwogICAgdGhpcy5fc2NlbmUzRE9ubHkgPSBmYWxzZTsKICB9CiAgZnVuY3Rpb24gY29tcHV0ZVJpZ2h0Tm9ybWFsKHN0YXJ0LCBlbmQsIG1heEhlaWdodCwgZWxsaXBzb2lkLCByZXN1bHQpIHsKICAgIGNvbnN0IHN0YXJ0Qm90dG9tID0gZ2V0UG9zaXRpb24oZWxsaXBzb2lkLCBzdGFydCwgMCwgY2FydDNTY3JhdGNoMSk7CiAgICBjb25zdCBzdGFydFRvcCA9IGdldFBvc2l0aW9uKGVsbGlwc29pZCwgc3RhcnQsIG1heEhlaWdodCwgY2FydDNTY3JhdGNoMik7CiAgICBjb25zdCBlbmRCb3R0b20gPSBnZXRQb3NpdGlvbihlbGxpcHNvaWQsIGVuZCwgMCwgY2FydDNTY3JhdGNoMyk7CiAgICBjb25zdCB1cCA9IGRpcmVjdGlvbihzdGFydFRvcCwgc3RhcnRCb3R0b20sIGNhcnQzU2NyYXRjaDIpOwogICAgY29uc3QgZm9yd2FyZCA9IGRpcmVjdGlvbihlbmRCb3R0b20sIHN0YXJ0Qm90dG9tLCBjYXJ0M1NjcmF0Y2gzKTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhmb3J3YXJkLCB1cCwgcmVzdWx0KTsKICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKHJlc3VsdCwgcmVzdWx0KTsKICB9CiAgZnVuY3Rpb24gaW50ZXJwb2xhdGVTZWdtZW50KHN0YXJ0LCBlbmQsIG1pbkhlaWdodCwgbWF4SGVpZ2h0LCBncmFudWxhcml0eSwgYXJjVHlwZSwgZWxsaXBzb2lkLCBub3JtYWxzQXJyYXksIGJvdHRvbVBvc2l0aW9uc0FycmF5LCB0b3BQb3NpdGlvbnNBcnJheSwgY2FydG9ncmFwaGljc0FycmF5KSB7CiAgICBpZiAoZ3JhbnVsYXJpdHkgPT09IDApIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IGVsbGlwc29pZExpbmU7CiAgICBpZiAoYXJjVHlwZSA9PT0gQXJjVHlwZV9kZWZhdWx0LkdFT0RFU0lDKSB7CiAgICAgIGVsbGlwc29pZExpbmUgPSBuZXcgRWxsaXBzb2lkR2VvZGVzaWNfZGVmYXVsdChzdGFydCwgZW5kLCBlbGxpcHNvaWQpOwogICAgfSBlbHNlIGlmIChhcmNUeXBlID09PSBBcmNUeXBlX2RlZmF1bHQuUkhVTUIpIHsKICAgICAgZWxsaXBzb2lkTGluZSA9IG5ldyBFbGxpcHNvaWRSaHVtYkxpbmVfZGVmYXVsdChzdGFydCwgZW5kLCBlbGxpcHNvaWQpOwogICAgfQogICAgY29uc3Qgc3VyZmFjZURpc3RhbmNlID0gZWxsaXBzb2lkTGluZS5zdXJmYWNlRGlzdGFuY2U7CiAgICBpZiAoc3VyZmFjZURpc3RhbmNlIDwgZ3JhbnVsYXJpdHkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgaW50ZXJwb2xhdGVkTm9ybWFsID0gY29tcHV0ZVJpZ2h0Tm9ybWFsKAogICAgICBzdGFydCwKICAgICAgZW5kLAogICAgICBtYXhIZWlnaHQsCiAgICAgIGVsbGlwc29pZCwKICAgICAgaW50ZXJwb2xhdGVkTm9ybWFsU2NyYXRjaAogICAgKTsKICAgIGNvbnN0IHNlZ21lbnRzID0gTWF0aC5jZWlsKHN1cmZhY2VEaXN0YW5jZSAvIGdyYW51bGFyaXR5KTsKICAgIGNvbnN0IGludGVycG9pbnREaXN0YW5jZSA9IHN1cmZhY2VEaXN0YW5jZSAvIHNlZ21lbnRzOwogICAgbGV0IGRpc3RhbmNlRnJvbVN0YXJ0ID0gaW50ZXJwb2ludERpc3RhbmNlOwogICAgY29uc3QgcG9pbnRzVG9BZGQgPSBzZWdtZW50cyAtIDE7CiAgICBsZXQgcGFja0luZGV4ID0gbm9ybWFsc0FycmF5Lmxlbmd0aDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9pbnRzVG9BZGQ7IGkrKykgewogICAgICBjb25zdCBpbnRlcnBvbGF0ZWRDYXJ0b2dyYXBoaWMgPSBlbGxpcHNvaWRMaW5lLmludGVycG9sYXRlVXNpbmdTdXJmYWNlRGlzdGFuY2UoCiAgICAgICAgZGlzdGFuY2VGcm9tU3RhcnQsCiAgICAgICAgaW50ZXJwb2xhdGVkQ2FydG9ncmFwaGljU2NyYXRjaAogICAgICApOwogICAgICBjb25zdCBpbnRlcnBvbGF0ZWRCb3R0b20gPSBnZXRQb3NpdGlvbigKICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgaW50ZXJwb2xhdGVkQ2FydG9ncmFwaGljLAogICAgICAgIG1pbkhlaWdodCwKICAgICAgICBpbnRlcnBvbGF0ZWRCb3R0b21TY3JhdGNoCiAgICAgICk7CiAgICAgIGNvbnN0IGludGVycG9sYXRlZFRvcCA9IGdldFBvc2l0aW9uKAogICAgICAgIGVsbGlwc29pZCwKICAgICAgICBpbnRlcnBvbGF0ZWRDYXJ0b2dyYXBoaWMsCiAgICAgICAgbWF4SGVpZ2h0LAogICAgICAgIGludGVycG9sYXRlZFRvcFNjcmF0Y2gKICAgICAgKTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soaW50ZXJwb2xhdGVkTm9ybWFsLCBub3JtYWxzQXJyYXksIHBhY2tJbmRleCk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKGludGVycG9sYXRlZEJvdHRvbSwgYm90dG9tUG9zaXRpb25zQXJyYXksIHBhY2tJbmRleCk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKGludGVycG9sYXRlZFRvcCwgdG9wUG9zaXRpb25zQXJyYXksIHBhY2tJbmRleCk7CiAgICAgIGNhcnRvZ3JhcGhpY3NBcnJheS5wdXNoKGludGVycG9sYXRlZENhcnRvZ3JhcGhpYy5sYXRpdHVkZSk7CiAgICAgIGNhcnRvZ3JhcGhpY3NBcnJheS5wdXNoKGludGVycG9sYXRlZENhcnRvZ3JhcGhpYy5sb25naXR1ZGUpOwogICAgICBwYWNrSW5kZXggKz0gMzsKICAgICAgZGlzdGFuY2VGcm9tU3RhcnQgKz0gaW50ZXJwb2ludERpc3RhbmNlOwogICAgfQogIH0KICBmdW5jdGlvbiBnZXRQb3NpdGlvbihlbGxpcHNvaWQsIGNhcnRvZ3JhcGhpYzIsIGhlaWdodCwgcmVzdWx0KSB7CiAgICBDYXJ0b2dyYXBoaWNfZGVmYXVsdC5jbG9uZShjYXJ0b2dyYXBoaWMyLCBoZWlnaHRsZXNzQ2FydG9ncmFwaGljU2NyYXRjaCk7CiAgICBoZWlnaHRsZXNzQ2FydG9ncmFwaGljU2NyYXRjaC5oZWlnaHQgPSBoZWlnaHQ7CiAgICByZXR1cm4gQ2FydG9ncmFwaGljX2RlZmF1bHQudG9DYXJ0ZXNpYW4oCiAgICAgIGhlaWdodGxlc3NDYXJ0b2dyYXBoaWNTY3JhdGNoLAogICAgICBlbGxpcHNvaWQsCiAgICAgIHJlc3VsdAogICAgKTsKICB9CiAgZnVuY3Rpb24gZGlyZWN0aW9uKHRhcmdldCwgb3JpZ2luLCByZXN1bHQpIHsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCh0YXJnZXQsIG9yaWdpbiwgcmVzdWx0KTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUocmVzdWx0LCByZXN1bHQpOwogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgZnVuY3Rpb24gdGFuZ2VudERpcmVjdGlvbih0YXJnZXQsIG9yaWdpbiwgdXAsIHJlc3VsdCkgewogICAgcmVzdWx0ID0gZGlyZWN0aW9uKHRhcmdldCwgb3JpZ2luLCByZXN1bHQpOwogICAgcmVzdWx0ID0gQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKHJlc3VsdCwgdXAsIHJlc3VsdCk7CiAgICByZXN1bHQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKHJlc3VsdCwgcmVzdWx0KTsKICAgIHJlc3VsdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyh1cCwgcmVzdWx0LCByZXN1bHQpOwogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgZnVuY3Rpb24gY29tcHV0ZVZlcnRleE1pdGVyTm9ybWFsKHByZXZpb3VzQm90dG9tLCB2ZXJ0ZXhCb3R0b20sIHZlcnRleFRvcCwgbmV4dEJvdHRvbSwgcmVzdWx0KSB7CiAgICBjb25zdCB1cCA9IGRpcmVjdGlvbih2ZXJ0ZXhUb3AsIHZlcnRleEJvdHRvbSwgdmVydGV4VXBTY3JhdGNoKTsKICAgIGNvbnN0IHRvUHJldmlvdXMgPSB0YW5nZW50RGlyZWN0aW9uKAogICAgICBwcmV2aW91c0JvdHRvbSwKICAgICAgdmVydGV4Qm90dG9tLAogICAgICB1cCwKICAgICAgdG9QcmV2aW91c1NjcmF0Y2gKICAgICk7CiAgICBjb25zdCB0b05leHQgPSB0YW5nZW50RGlyZWN0aW9uKG5leHRCb3R0b20sIHZlcnRleEJvdHRvbSwgdXAsIHRvTmV4dFNjcmF0Y2gpOwogICAgaWYgKE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHRvUHJldmlvdXMsIHRvTmV4dCksCiAgICAgIGNvc2luZTE4MCwKICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT041CiAgICApKSB7CiAgICAgIHJlc3VsdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyh1cCwgdG9QcmV2aW91cywgcmVzdWx0KTsKICAgICAgcmVzdWx0ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShyZXN1bHQsIHJlc3VsdCk7CiAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9CiAgICByZXN1bHQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHRvTmV4dCwgdG9QcmV2aW91cywgcmVzdWx0KTsKICAgIHJlc3VsdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUocmVzdWx0LCByZXN1bHQpOwogICAgY29uc3QgZm9yd2FyZCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyh1cCwgcmVzdWx0LCBmb3J3YXJkU2NyYXRjaCk7CiAgICBpZiAoQ2FydGVzaWFuM19kZWZhdWx0LmRvdCh0b05leHQsIGZvcndhcmQpIDwgY29zaW5lOTApIHsKICAgICAgcmVzdWx0ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5lZ2F0ZShyZXN1bHQsIHJlc3VsdCk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICBmdW5jdGlvbiBicmVha01pdGVyKGVuZEdlb21ldHJ5Tm9ybWFsLCBzdGFydEJvdHRvbSwgZW5kQm90dG9tLCBlbmRUb3ApIHsKICAgIGNvbnN0IGxpbmVEaXJlY3Rpb24gPSBkaXJlY3Rpb24oZW5kQm90dG9tLCBzdGFydEJvdHRvbSwgbGluZURpcmVjdGlvblNjcmF0Y2gpOwogICAgY29uc3QgZG90ID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChsaW5lRGlyZWN0aW9uLCBlbmRHZW9tZXRyeU5vcm1hbCk7CiAgICBpZiAoZG90ID4gTUlURVJfQlJFQUtfU01BTEwgfHwgZG90IDwgTUlURVJfQlJFQUtfTEFSR0UpIHsKICAgICAgY29uc3QgdmVydGV4VXAgPSBkaXJlY3Rpb24oZW5kVG9wLCBlbmRCb3R0b20sIHZlcnRleFVwU2NyYXRjaCk7CiAgICAgIGNvbnN0IGFuZ2xlID0gZG90IDwgTUlURVJfQlJFQUtfTEFSR0UgPyBNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08gOiAtTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPOwogICAgICBjb25zdCBxdWF0ZXJuaW9uID0gUXVhdGVybmlvbl9kZWZhdWx0LmZyb21BeGlzQW5nbGUoCiAgICAgICAgdmVydGV4VXAsCiAgICAgICAgYW5nbGUsCiAgICAgICAgcXVhdGVybmlvblNjcmF0Y2gzCiAgICAgICk7CiAgICAgIGNvbnN0IHJvdGF0aW9uTWF0cml4ID0gTWF0cml4M19kZWZhdWx0LmZyb21RdWF0ZXJuaW9uKHF1YXRlcm5pb24sIG1hdHJpeDNTY3JhdGNoKTsKICAgICAgTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3IoCiAgICAgICAgcm90YXRpb25NYXRyaXgsCiAgICAgICAgZW5kR2VvbWV0cnlOb3JtYWwsCiAgICAgICAgZW5kR2VvbWV0cnlOb3JtYWwKICAgICAgKTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGZ1bmN0aW9uIHByb2plY3ROb3JtYWwocHJvamVjdGlvbiwgY2FydG9ncmFwaGljMiwgbm9ybWFsMiwgcHJvamVjdGVkUG9zaXRpb24sIHJlc3VsdCkgewogICAgY29uc3QgcG9zaXRpb24gPSBDYXJ0b2dyYXBoaWNfZGVmYXVsdC50b0NhcnRlc2lhbigKICAgICAgY2FydG9ncmFwaGljMiwKICAgICAgcHJvamVjdGlvbi5fZWxsaXBzb2lkLAogICAgICBub3JtYWxTdGFydHBvaW50U2NyYXRjaAogICAgKTsKICAgIGxldCBub3JtYWxFbmRwb2ludCA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQocG9zaXRpb24sIG5vcm1hbDIsIG5vcm1hbEVuZHBvaW50U2NyYXRjaCk7CiAgICBsZXQgZmxpcE5vcm1hbCA9IGZhbHNlOwogICAgY29uc3QgZWxsaXBzb2lkID0gcHJvamVjdGlvbi5fZWxsaXBzb2lkOwogICAgbGV0IG5vcm1hbEVuZHBvaW50Q2FydG9ncmFwaGljID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKAogICAgICBub3JtYWxFbmRwb2ludCwKICAgICAgZW5kUG9zQ2FydG9ncmFwaGljU2NyYXRjaAogICAgKTsKICAgIGlmIChNYXRoLmFicyhjYXJ0b2dyYXBoaWMyLmxvbmdpdHVkZSAtIG5vcm1hbEVuZHBvaW50Q2FydG9ncmFwaGljLmxvbmdpdHVkZSkgPiBNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08pIHsKICAgICAgZmxpcE5vcm1hbCA9IHRydWU7CiAgICAgIG5vcm1hbEVuZHBvaW50ID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KAogICAgICAgIHBvc2l0aW9uLAogICAgICAgIG5vcm1hbDIsCiAgICAgICAgbm9ybWFsRW5kcG9pbnRTY3JhdGNoCiAgICAgICk7CiAgICAgIG5vcm1hbEVuZHBvaW50Q2FydG9ncmFwaGljID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKAogICAgICAgIG5vcm1hbEVuZHBvaW50LAogICAgICAgIGVuZFBvc0NhcnRvZ3JhcGhpY1NjcmF0Y2gKICAgICAgKTsKICAgIH0KICAgIG5vcm1hbEVuZHBvaW50Q2FydG9ncmFwaGljLmhlaWdodCA9IDA7CiAgICBjb25zdCBub3JtYWxFbmRwb2ludFByb2plY3RlZCA9IHByb2plY3Rpb24ucHJvamVjdCgKICAgICAgbm9ybWFsRW5kcG9pbnRDYXJ0b2dyYXBoaWMsCiAgICAgIHJlc3VsdAogICAgKTsKICAgIHJlc3VsdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgbm9ybWFsRW5kcG9pbnRQcm9qZWN0ZWQsCiAgICAgIHByb2plY3RlZFBvc2l0aW9uLAogICAgICByZXN1bHQKICAgICk7CiAgICByZXN1bHQueiA9IDA7CiAgICByZXN1bHQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKHJlc3VsdCwgcmVzdWx0KTsKICAgIGlmIChmbGlwTm9ybWFsKSB7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUocmVzdWx0LCByZXN1bHQpOwogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgZnVuY3Rpb24gYWRqdXN0SGVpZ2h0cyhib3R0b20sIHRvcCwgbWluSGVpZ2h0LCBtYXhIZWlnaHQsIGFkanVzdEhlaWdodEJvdHRvbSwgYWRqdXN0SGVpZ2h0VG9wKSB7CiAgICBjb25zdCBhZGp1c3RIZWlnaHROb3JtYWwgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgIHRvcCwKICAgICAgYm90dG9tLAogICAgICBhZGp1c3RIZWlnaHROb3JtYWxTY3JhdGNoCiAgICApOwogICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShhZGp1c3RIZWlnaHROb3JtYWwsIGFkanVzdEhlaWdodE5vcm1hbCk7CiAgICBjb25zdCBkaXN0YW5jZUZvckJvdHRvbSA9IG1pbkhlaWdodCAtIFdBTExfSU5JVElBTF9NSU5fSEVJR0hUOwogICAgbGV0IGFkanVzdEhlaWdodE9mZnNldCA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICBhZGp1c3RIZWlnaHROb3JtYWwsCiAgICAgIGRpc3RhbmNlRm9yQm90dG9tLAogICAgICBhZGp1c3RIZWlnaHRPZmZzZXRTY3JhdGNoCiAgICApOwogICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChib3R0b20sIGFkanVzdEhlaWdodE9mZnNldCwgYWRqdXN0SGVpZ2h0Qm90dG9tKTsKICAgIGNvbnN0IGRpc3RhbmNlRm9yVG9wID0gbWF4SGVpZ2h0IC0gV0FMTF9JTklUSUFMX01BWF9IRUlHSFQ7CiAgICBhZGp1c3RIZWlnaHRPZmZzZXQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgYWRqdXN0SGVpZ2h0Tm9ybWFsLAogICAgICBkaXN0YW5jZUZvclRvcCwKICAgICAgYWRqdXN0SGVpZ2h0T2Zmc2V0U2NyYXRjaAogICAgKTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQodG9wLCBhZGp1c3RIZWlnaHRPZmZzZXQsIGFkanVzdEhlaWdodFRvcCk7CiAgfQogIGZ1bmN0aW9uIG51ZGdlWFooc3RhcnQsIGVuZCkgewogICAgY29uc3Qgc3RhcnRUb1haZGlzdGFuY2UgPSBQbGFuZV9kZWZhdWx0LmdldFBvaW50RGlzdGFuY2UoWFpfUExBTkUsIHN0YXJ0KTsKICAgIGNvbnN0IGVuZFRvWFpkaXN0YW5jZSA9IFBsYW5lX2RlZmF1bHQuZ2V0UG9pbnREaXN0YW5jZShYWl9QTEFORSwgZW5kKTsKICAgIGxldCBvZmZzZXQgPSBudWRnZURpcmVjdGlvblNjcmF0Y2g7CiAgICBpZiAoTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oc3RhcnRUb1haZGlzdGFuY2UsIDAsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMikpIHsKICAgICAgb2Zmc2V0ID0gZGlyZWN0aW9uKGVuZCwgc3RhcnQsIG9mZnNldCk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKG9mZnNldCwgTWF0aF9kZWZhdWx0LkVQU0lMT04yLCBvZmZzZXQpOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHN0YXJ0LCBvZmZzZXQsIHN0YXJ0KTsKICAgIH0gZWxzZSBpZiAoTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oZW5kVG9YWmRpc3RhbmNlLCAwLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjIpKSB7CiAgICAgIG9mZnNldCA9IGRpcmVjdGlvbihzdGFydCwgZW5kLCBvZmZzZXQpOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcihvZmZzZXQsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMiwgb2Zmc2V0KTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChlbmQsIG9mZnNldCwgZW5kKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gbnVkZ2VDYXJ0b2dyYXBoaWMoc3RhcnQsIGVuZCkgewogICAgY29uc3QgYWJzU3RhcnRMb24gPSBNYXRoLmFicyhzdGFydC5sb25naXR1ZGUpOwogICAgY29uc3QgYWJzRW5kTG9uID0gTWF0aC5hYnMoZW5kLmxvbmdpdHVkZSk7CiAgICBpZiAoTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oYWJzU3RhcnRMb24sIE1hdGhfZGVmYXVsdC5QSSwgTWF0aF9kZWZhdWx0LkVQU0lMT04xMSkpIHsKICAgICAgY29uc3QgZW5kU2lnbiA9IE1hdGhfZGVmYXVsdC5zaWduKGVuZC5sb25naXR1ZGUpOwogICAgICBzdGFydC5sb25naXR1ZGUgPSBlbmRTaWduICogKGFic1N0YXJ0TG9uIC0gTWF0aF9kZWZhdWx0LkVQU0lMT04xMSk7CiAgICAgIHJldHVybiAxOwogICAgfSBlbHNlIGlmIChNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihhYnNFbmRMb24sIE1hdGhfZGVmYXVsdC5QSSwgTWF0aF9kZWZhdWx0LkVQU0lMT04xMSkpIHsKICAgICAgY29uc3Qgc3RhcnRTaWduID0gTWF0aF9kZWZhdWx0LnNpZ24oc3RhcnQubG9uZ2l0dWRlKTsKICAgICAgZW5kLmxvbmdpdHVkZSA9IHN0YXJ0U2lnbiAqIChhYnNFbmRMb24gLSBNYXRoX2RlZmF1bHQuRVBTSUxPTjExKTsKICAgICAgcmV0dXJuIDI7CiAgICB9CiAgICByZXR1cm4gMDsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVHZW9tZXRyeUF0dHJpYnV0ZXMobG9vcCwgcHJvamVjdGlvbiwgYm90dG9tUG9zaXRpb25zQXJyYXksIHRvcFBvc2l0aW9uc0FycmF5LCBub3JtYWxzQXJyYXksIGNhcnRvZ3JhcGhpY3NBcnJheSwgY29tcHV0ZTJkQXR0cmlidXRlcykgewogICAgbGV0IGk7CiAgICBsZXQgaW5kZXg7CiAgICBjb25zdCBlbGxpcHNvaWQgPSBwcm9qZWN0aW9uLl9lbGxpcHNvaWQ7CiAgICBjb25zdCBzZWdtZW50Q291bnQgPSBib3R0b21Qb3NpdGlvbnNBcnJheS5sZW5ndGggLyAzIC0gMTsKICAgIGNvbnN0IHZlcnRleENvdW50ID0gc2VnbWVudENvdW50ICogODsKICAgIGNvbnN0IGFycmF5U2l6ZVZlYzQgPSB2ZXJ0ZXhDb3VudCAqIDQ7CiAgICBjb25zdCBpbmRleENvdW50ID0gc2VnbWVudENvdW50ICogMzY7CiAgICBjb25zdCBpbmRpY2VzID0gdmVydGV4Q291bnQgPiA2NTUzNSA/IG5ldyBVaW50MzJBcnJheShpbmRleENvdW50KSA6IG5ldyBVaW50MTZBcnJheShpbmRleENvdW50KTsKICAgIGNvbnN0IHBvc2l0aW9uc0FycmF5ID0gbmV3IEZsb2F0NjRBcnJheSh2ZXJ0ZXhDb3VudCAqIDMpOwogICAgY29uc3Qgc3RhcnRIaUFuZEZvcndhcmRPZmZzZXRYID0gbmV3IEZsb2F0MzJBcnJheShhcnJheVNpemVWZWM0KTsKICAgIGNvbnN0IHN0YXJ0TG9BbmRGb3J3YXJkT2Zmc2V0WSA9IG5ldyBGbG9hdDMyQXJyYXkoYXJyYXlTaXplVmVjNCk7CiAgICBjb25zdCBzdGFydE5vcm1hbEFuZEZvcndhcmRPZmZzZXRaID0gbmV3IEZsb2F0MzJBcnJheShhcnJheVNpemVWZWM0KTsKICAgIGNvbnN0IGVuZE5vcm1hbEFuZFRleHR1cmVDb29yZGluYXRlTm9ybWFsaXphdGlvblggPSBuZXcgRmxvYXQzMkFycmF5KAogICAgICBhcnJheVNpemVWZWM0CiAgICApOwogICAgY29uc3QgcmlnaHROb3JtYWxBbmRUZXh0dXJlQ29vcmRpbmF0ZU5vcm1hbGl6YXRpb25ZID0gbmV3IEZsb2F0MzJBcnJheSgKICAgICAgYXJyYXlTaXplVmVjNAogICAgKTsKICAgIGxldCBzdGFydEhpTG8yRDsKICAgIGxldCBvZmZzZXRBbmRSaWdodDJEOwogICAgbGV0IHN0YXJ0RW5kTm9ybWFsczJEOwogICAgbGV0IHRleGNvb3JkTm9ybWFsaXphdGlvbjJEOwogICAgaWYgKGNvbXB1dGUyZEF0dHJpYnV0ZXMpIHsKICAgICAgc3RhcnRIaUxvMkQgPSBuZXcgRmxvYXQzMkFycmF5KGFycmF5U2l6ZVZlYzQpOwogICAgICBvZmZzZXRBbmRSaWdodDJEID0gbmV3IEZsb2F0MzJBcnJheShhcnJheVNpemVWZWM0KTsKICAgICAgc3RhcnRFbmROb3JtYWxzMkQgPSBuZXcgRmxvYXQzMkFycmF5KGFycmF5U2l6ZVZlYzQpOwogICAgICB0ZXhjb29yZE5vcm1hbGl6YXRpb24yRCA9IG5ldyBGbG9hdDMyQXJyYXkodmVydGV4Q291bnQgKiAyKTsKICAgIH0KICAgIGNvbnN0IGNhcnRvZ3JhcGhpY3NMZW5ndGggPSBjYXJ0b2dyYXBoaWNzQXJyYXkubGVuZ3RoIC8gMjsKICAgIGxldCBsZW5ndGgyRCA9IDA7CiAgICBjb25zdCBzdGFydENhcnRvZ3JhcGhpYyA9IHN0YXJ0Q2FydG9ncmFwaGljU2NyYXRjaDsKICAgIHN0YXJ0Q2FydG9ncmFwaGljLmhlaWdodCA9IDA7CiAgICBjb25zdCBlbmRDYXJ0b2dyYXBoaWMgPSBlbmRDYXJ0b2dyYXBoaWNTY3JhdGNoOwogICAgZW5kQ2FydG9ncmFwaGljLmhlaWdodCA9IDA7CiAgICBsZXQgc2VnbWVudFN0YXJ0Q2FydGVzaWFuID0gc2VnbWVudFN0YXJ0VG9wU2NyYXRjaDsKICAgIGxldCBzZWdtZW50RW5kQ2FydGVzaWFuID0gc2VnbWVudEVuZFRvcFNjcmF0Y2g7CiAgICBpZiAoY29tcHV0ZTJkQXR0cmlidXRlcykgewogICAgICBpbmRleCA9IDA7CiAgICAgIGZvciAoaSA9IDE7IGkgPCBjYXJ0b2dyYXBoaWNzTGVuZ3RoOyBpKyspIHsKICAgICAgICBzdGFydENhcnRvZ3JhcGhpYy5sYXRpdHVkZSA9IGNhcnRvZ3JhcGhpY3NBcnJheVtpbmRleF07CiAgICAgICAgc3RhcnRDYXJ0b2dyYXBoaWMubG9uZ2l0dWRlID0gY2FydG9ncmFwaGljc0FycmF5W2luZGV4ICsgMV07CiAgICAgICAgZW5kQ2FydG9ncmFwaGljLmxhdGl0dWRlID0gY2FydG9ncmFwaGljc0FycmF5W2luZGV4ICsgMl07CiAgICAgICAgZW5kQ2FydG9ncmFwaGljLmxvbmdpdHVkZSA9IGNhcnRvZ3JhcGhpY3NBcnJheVtpbmRleCArIDNdOwogICAgICAgIHNlZ21lbnRTdGFydENhcnRlc2lhbiA9IHByb2plY3Rpb24ucHJvamVjdCgKICAgICAgICAgIHN0YXJ0Q2FydG9ncmFwaGljLAogICAgICAgICAgc2VnbWVudFN0YXJ0Q2FydGVzaWFuCiAgICAgICAgKTsKICAgICAgICBzZWdtZW50RW5kQ2FydGVzaWFuID0gcHJvamVjdGlvbi5wcm9qZWN0KAogICAgICAgICAgZW5kQ2FydG9ncmFwaGljLAogICAgICAgICAgc2VnbWVudEVuZENhcnRlc2lhbgogICAgICAgICk7CiAgICAgICAgbGVuZ3RoMkQgKz0gQ2FydGVzaWFuM19kZWZhdWx0LmRpc3RhbmNlKAogICAgICAgICAgc2VnbWVudFN0YXJ0Q2FydGVzaWFuLAogICAgICAgICAgc2VnbWVudEVuZENhcnRlc2lhbgogICAgICAgICk7CiAgICAgICAgaW5kZXggKz0gMjsKICAgICAgfQogICAgfQogICAgY29uc3QgcG9zaXRpb25zTGVuZ3RoID0gdG9wUG9zaXRpb25zQXJyYXkubGVuZ3RoIC8gMzsKICAgIHNlZ21lbnRFbmRDYXJ0ZXNpYW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICB0b3BQb3NpdGlvbnNBcnJheSwKICAgICAgMCwKICAgICAgc2VnbWVudEVuZENhcnRlc2lhbgogICAgKTsKICAgIGxldCBsZW5ndGgzRCA9IDA7CiAgICBpbmRleCA9IDM7CiAgICBmb3IgKGkgPSAxOyBpIDwgcG9zaXRpb25zTGVuZ3RoOyBpKyspIHsKICAgICAgc2VnbWVudFN0YXJ0Q2FydGVzaWFuID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKAogICAgICAgIHNlZ21lbnRFbmRDYXJ0ZXNpYW4sCiAgICAgICAgc2VnbWVudFN0YXJ0Q2FydGVzaWFuCiAgICAgICk7CiAgICAgIHNlZ21lbnRFbmRDYXJ0ZXNpYW4gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICAgIHRvcFBvc2l0aW9uc0FycmF5LAogICAgICAgIGluZGV4LAogICAgICAgIHNlZ21lbnRFbmRDYXJ0ZXNpYW4KICAgICAgKTsKICAgICAgbGVuZ3RoM0QgKz0gQ2FydGVzaWFuM19kZWZhdWx0LmRpc3RhbmNlKHNlZ21lbnRTdGFydENhcnRlc2lhbiwgc2VnbWVudEVuZENhcnRlc2lhbik7CiAgICAgIGluZGV4ICs9IDM7CiAgICB9CiAgICBsZXQgajsKICAgIGluZGV4ID0gMzsKICAgIGxldCBjYXJ0b2dyYXBoaWNzSW5kZXggPSAwOwogICAgbGV0IHZlYzJzV3JpdGVJbmRleCA9IDA7CiAgICBsZXQgdmVjM3NXcml0ZUluZGV4ID0gMDsKICAgIGxldCB2ZWM0c1dyaXRlSW5kZXggPSAwOwogICAgbGV0IG1pdGVyQnJva2VuID0gZmFsc2U7CiAgICBsZXQgZW5kQm90dG9tID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjaygKICAgICAgYm90dG9tUG9zaXRpb25zQXJyYXksCiAgICAgIDAsCiAgICAgIHNlZ21lbnRFbmRCb3R0b21TY3JhdGNoCiAgICApOwogICAgbGV0IGVuZFRvcCA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2sodG9wUG9zaXRpb25zQXJyYXksIDAsIHNlZ21lbnRFbmRUb3BTY3JhdGNoKTsKICAgIGxldCBlbmRHZW9tZXRyeU5vcm1hbCA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soCiAgICAgIG5vcm1hbHNBcnJheSwKICAgICAgMCwKICAgICAgc2VnbWVudEVuZE5vcm1hbFNjcmF0Y2gKICAgICk7CiAgICBpZiAobG9vcCkgewogICAgICBjb25zdCBwcmVFbmRCb3R0b20gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICAgIGJvdHRvbVBvc2l0aW9uc0FycmF5LAogICAgICAgIGJvdHRvbVBvc2l0aW9uc0FycmF5Lmxlbmd0aCAtIDYsCiAgICAgICAgc2VnbWVudFN0YXJ0Qm90dG9tU2NyYXRjaAogICAgICApOwogICAgICBpZiAoYnJlYWtNaXRlcihlbmRHZW9tZXRyeU5vcm1hbCwgcHJlRW5kQm90dG9tLCBlbmRCb3R0b20sIGVuZFRvcCkpIHsKICAgICAgICBlbmRHZW9tZXRyeU5vcm1hbCA9IENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoCiAgICAgICAgICBlbmRHZW9tZXRyeU5vcm1hbCwKICAgICAgICAgIGVuZEdlb21ldHJ5Tm9ybWFsCiAgICAgICAgKTsKICAgICAgfQogICAgfQogICAgbGV0IGxlbmd0aFNvRmFyM0QgPSAwOwogICAgbGV0IGxlbmd0aFNvRmFyMkQgPSAwOwogICAgbGV0IHN1bUhlaWdodHMgPSAwOwogICAgZm9yIChpID0gMDsgaSA8IHNlZ21lbnRDb3VudDsgaSsrKSB7CiAgICAgIGNvbnN0IHN0YXJ0Qm90dG9tID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGVuZEJvdHRvbSwgc2VnbWVudFN0YXJ0Qm90dG9tU2NyYXRjaCk7CiAgICAgIGNvbnN0IHN0YXJ0VG9wID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGVuZFRvcCwgc2VnbWVudFN0YXJ0VG9wU2NyYXRjaCk7CiAgICAgIGxldCBzdGFydEdlb21ldHJ5Tm9ybWFsID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKAogICAgICAgIGVuZEdlb21ldHJ5Tm9ybWFsLAogICAgICAgIHNlZ21lbnRTdGFydE5vcm1hbFNjcmF0Y2gKICAgICAgKTsKICAgICAgaWYgKG1pdGVyQnJva2VuKSB7CiAgICAgICAgc3RhcnRHZW9tZXRyeU5vcm1hbCA9IENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUoCiAgICAgICAgICBzdGFydEdlb21ldHJ5Tm9ybWFsLAogICAgICAgICAgc3RhcnRHZW9tZXRyeU5vcm1hbAogICAgICAgICk7CiAgICAgIH0KICAgICAgZW5kQm90dG9tID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjaygKICAgICAgICBib3R0b21Qb3NpdGlvbnNBcnJheSwKICAgICAgICBpbmRleCwKICAgICAgICBzZWdtZW50RW5kQm90dG9tU2NyYXRjaAogICAgICApOwogICAgICBlbmRUb3AgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKHRvcFBvc2l0aW9uc0FycmF5LCBpbmRleCwgc2VnbWVudEVuZFRvcFNjcmF0Y2gpOwogICAgICBlbmRHZW9tZXRyeU5vcm1hbCA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soCiAgICAgICAgbm9ybWFsc0FycmF5LAogICAgICAgIGluZGV4LAogICAgICAgIHNlZ21lbnRFbmROb3JtYWxTY3JhdGNoCiAgICAgICk7CiAgICAgIG1pdGVyQnJva2VuID0gYnJlYWtNaXRlcihlbmRHZW9tZXRyeU5vcm1hbCwgc3RhcnRCb3R0b20sIGVuZEJvdHRvbSwgZW5kVG9wKTsKICAgICAgc3RhcnRDYXJ0b2dyYXBoaWMubGF0aXR1ZGUgPSBjYXJ0b2dyYXBoaWNzQXJyYXlbY2FydG9ncmFwaGljc0luZGV4XTsKICAgICAgc3RhcnRDYXJ0b2dyYXBoaWMubG9uZ2l0dWRlID0gY2FydG9ncmFwaGljc0FycmF5W2NhcnRvZ3JhcGhpY3NJbmRleCArIDFdOwogICAgICBlbmRDYXJ0b2dyYXBoaWMubGF0aXR1ZGUgPSBjYXJ0b2dyYXBoaWNzQXJyYXlbY2FydG9ncmFwaGljc0luZGV4ICsgMl07CiAgICAgIGVuZENhcnRvZ3JhcGhpYy5sb25naXR1ZGUgPSBjYXJ0b2dyYXBoaWNzQXJyYXlbY2FydG9ncmFwaGljc0luZGV4ICsgM107CiAgICAgIGxldCBzdGFydDJEOwogICAgICBsZXQgZW5kMkQ7CiAgICAgIGxldCBzdGFydEdlb21ldHJ5Tm9ybWFsMkQ7CiAgICAgIGxldCBlbmRHZW9tZXRyeU5vcm1hbDJEOwogICAgICBpZiAoY29tcHV0ZTJkQXR0cmlidXRlcykgewogICAgICAgIGNvbnN0IG51ZGdlUmVzdWx0ID0gbnVkZ2VDYXJ0b2dyYXBoaWMoc3RhcnRDYXJ0b2dyYXBoaWMsIGVuZENhcnRvZ3JhcGhpYyk7CiAgICAgICAgc3RhcnQyRCA9IHByb2plY3Rpb24ucHJvamVjdChzdGFydENhcnRvZ3JhcGhpYywgc2VnbWVudFN0YXJ0MkRTY3JhdGNoKTsKICAgICAgICBlbmQyRCA9IHByb2plY3Rpb24ucHJvamVjdChlbmRDYXJ0b2dyYXBoaWMsIHNlZ21lbnRFbmQyRFNjcmF0Y2gpOwogICAgICAgIGNvbnN0IGRpcmVjdGlvbjJEID0gZGlyZWN0aW9uKGVuZDJELCBzdGFydDJELCBmb3J3YXJkT2Zmc2V0MkRTY3JhdGNoKTsKICAgICAgICBkaXJlY3Rpb24yRC55ID0gTWF0aC5hYnMoZGlyZWN0aW9uMkQueSk7CiAgICAgICAgc3RhcnRHZW9tZXRyeU5vcm1hbDJEID0gc2VnbWVudFN0YXJ0Tm9ybWFsMkRTY3JhdGNoOwogICAgICAgIGVuZEdlb21ldHJ5Tm9ybWFsMkQgPSBzZWdtZW50RW5kTm9ybWFsMkRTY3JhdGNoOwogICAgICAgIGlmIChudWRnZVJlc3VsdCA9PT0gMCB8fCBDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KGRpcmVjdGlvbjJELCBDYXJ0ZXNpYW4zX2RlZmF1bHQuVU5JVF9ZKSA+IE1JVEVSX0JSRUFLX1NNQUxMKSB7CiAgICAgICAgICBzdGFydEdlb21ldHJ5Tm9ybWFsMkQgPSBwcm9qZWN0Tm9ybWFsKAogICAgICAgICAgICBwcm9qZWN0aW9uLAogICAgICAgICAgICBzdGFydENhcnRvZ3JhcGhpYywKICAgICAgICAgICAgc3RhcnRHZW9tZXRyeU5vcm1hbCwKICAgICAgICAgICAgc3RhcnQyRCwKICAgICAgICAgICAgc2VnbWVudFN0YXJ0Tm9ybWFsMkRTY3JhdGNoCiAgICAgICAgICApOwogICAgICAgICAgZW5kR2VvbWV0cnlOb3JtYWwyRCA9IHByb2plY3ROb3JtYWwoCiAgICAgICAgICAgIHByb2plY3Rpb24sCiAgICAgICAgICAgIGVuZENhcnRvZ3JhcGhpYywKICAgICAgICAgICAgZW5kR2VvbWV0cnlOb3JtYWwsCiAgICAgICAgICAgIGVuZDJELAogICAgICAgICAgICBzZWdtZW50RW5kTm9ybWFsMkRTY3JhdGNoCiAgICAgICAgICApOwogICAgICAgIH0gZWxzZSBpZiAobnVkZ2VSZXN1bHQgPT09IDEpIHsKICAgICAgICAgIGVuZEdlb21ldHJ5Tm9ybWFsMkQgPSBwcm9qZWN0Tm9ybWFsKAogICAgICAgICAgICBwcm9qZWN0aW9uLAogICAgICAgICAgICBlbmRDYXJ0b2dyYXBoaWMsCiAgICAgICAgICAgIGVuZEdlb21ldHJ5Tm9ybWFsLAogICAgICAgICAgICBlbmQyRCwKICAgICAgICAgICAgc2VnbWVudEVuZE5vcm1hbDJEU2NyYXRjaAogICAgICAgICAgKTsKICAgICAgICAgIHN0YXJ0R2VvbWV0cnlOb3JtYWwyRC54ID0gMDsKICAgICAgICAgIHN0YXJ0R2VvbWV0cnlOb3JtYWwyRC55ID0gTWF0aF9kZWZhdWx0LnNpZ24oCiAgICAgICAgICAgIHN0YXJ0Q2FydG9ncmFwaGljLmxvbmdpdHVkZSAtIE1hdGguYWJzKGVuZENhcnRvZ3JhcGhpYy5sb25naXR1ZGUpCiAgICAgICAgICApOwogICAgICAgICAgc3RhcnRHZW9tZXRyeU5vcm1hbDJELnogPSAwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdGFydEdlb21ldHJ5Tm9ybWFsMkQgPSBwcm9qZWN0Tm9ybWFsKAogICAgICAgICAgICBwcm9qZWN0aW9uLAogICAgICAgICAgICBzdGFydENhcnRvZ3JhcGhpYywKICAgICAgICAgICAgc3RhcnRHZW9tZXRyeU5vcm1hbCwKICAgICAgICAgICAgc3RhcnQyRCwKICAgICAgICAgICAgc2VnbWVudFN0YXJ0Tm9ybWFsMkRTY3JhdGNoCiAgICAgICAgICApOwogICAgICAgICAgZW5kR2VvbWV0cnlOb3JtYWwyRC54ID0gMDsKICAgICAgICAgIGVuZEdlb21ldHJ5Tm9ybWFsMkQueSA9IE1hdGhfZGVmYXVsdC5zaWduKAogICAgICAgICAgICBzdGFydENhcnRvZ3JhcGhpYy5sb25naXR1ZGUgLSBlbmRDYXJ0b2dyYXBoaWMubG9uZ2l0dWRlCiAgICAgICAgICApOwogICAgICAgICAgZW5kR2VvbWV0cnlOb3JtYWwyRC56ID0gMDsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3Qgc2VnbWVudExlbmd0aDNEID0gQ2FydGVzaWFuM19kZWZhdWx0LmRpc3RhbmNlKHN0YXJ0VG9wLCBlbmRUb3ApOwogICAgICBjb25zdCBlbmNvZGVkU3RhcnQgPSBFbmNvZGVkQ2FydGVzaWFuM19kZWZhdWx0LmZyb21DYXJ0ZXNpYW4oCiAgICAgICAgc3RhcnRCb3R0b20sCiAgICAgICAgZW5jb2RlU2NyYXRjaAogICAgICApOwogICAgICBjb25zdCBmb3J3YXJkT2Zmc2V0ID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KAogICAgICAgIGVuZEJvdHRvbSwKICAgICAgICBzdGFydEJvdHRvbSwKICAgICAgICBvZmZzZXRTY3JhdGNoMgogICAgICApOwogICAgICBjb25zdCBmb3J3YXJkID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShmb3J3YXJkT2Zmc2V0LCByaWdodFNjcmF0Y2gyKTsKICAgICAgbGV0IHN0YXJ0VXAgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3Qoc3RhcnRUb3AsIHN0YXJ0Qm90dG9tLCBzdGFydFVwU2NyYXRjaCk7CiAgICAgIHN0YXJ0VXAgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKHN0YXJ0VXAsIHN0YXJ0VXApOwogICAgICBsZXQgcmlnaHROb3JtYWwgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoZm9yd2FyZCwgc3RhcnRVcCwgcmlnaHRTY3JhdGNoMik7CiAgICAgIHJpZ2h0Tm9ybWFsID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShyaWdodE5vcm1hbCwgcmlnaHROb3JtYWwpOwogICAgICBsZXQgc3RhcnRQbGFuZU5vcm1hbCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcygKICAgICAgICBzdGFydFVwLAogICAgICAgIHN0YXJ0R2VvbWV0cnlOb3JtYWwsCiAgICAgICAgc3RhcnRQbGFuZU5vcm1hbFNjcmF0Y2gKICAgICAgKTsKICAgICAgc3RhcnRQbGFuZU5vcm1hbCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoc3RhcnRQbGFuZU5vcm1hbCwgc3RhcnRQbGFuZU5vcm1hbCk7CiAgICAgIGxldCBlbmRVcCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChlbmRUb3AsIGVuZEJvdHRvbSwgZW5kVXBTY3JhdGNoKTsKICAgICAgZW5kVXAgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGVuZFVwLCBlbmRVcCk7CiAgICAgIGxldCBlbmRQbGFuZU5vcm1hbCA9IENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcygKICAgICAgICBlbmRHZW9tZXRyeU5vcm1hbCwKICAgICAgICBlbmRVcCwKICAgICAgICBlbmRQbGFuZU5vcm1hbFNjcmF0Y2gKICAgICAgKTsKICAgICAgZW5kUGxhbmVOb3JtYWwgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGVuZFBsYW5lTm9ybWFsLCBlbmRQbGFuZU5vcm1hbCk7CiAgICAgIGNvbnN0IHRleGNvb3JkTm9ybWFsaXphdGlvbjNEWCA9IHNlZ21lbnRMZW5ndGgzRCAvIGxlbmd0aDNEOwogICAgICBjb25zdCB0ZXhjb29yZE5vcm1hbGl6YXRpb24zRFkgPSBsZW5ndGhTb0ZhcjNEIC8gbGVuZ3RoM0Q7CiAgICAgIGxldCBzZWdtZW50TGVuZ3RoMkQgPSAwOwogICAgICBsZXQgZW5jb2RlZFN0YXJ0MkQ7CiAgICAgIGxldCBmb3J3YXJkT2Zmc2V0MkQ7CiAgICAgIGxldCByaWdodDJEOwogICAgICBsZXQgdGV4Y29vcmROb3JtYWxpemF0aW9uMkRYID0gMDsKICAgICAgbGV0IHRleGNvb3JkTm9ybWFsaXphdGlvbjJEWSA9IDA7CiAgICAgIGlmIChjb21wdXRlMmRBdHRyaWJ1dGVzKSB7CiAgICAgICAgc2VnbWVudExlbmd0aDJEID0gQ2FydGVzaWFuM19kZWZhdWx0LmRpc3RhbmNlKHN0YXJ0MkQsIGVuZDJEKTsKICAgICAgICBlbmNvZGVkU3RhcnQyRCA9IEVuY29kZWRDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUNhcnRlc2lhbigKICAgICAgICAgIHN0YXJ0MkQsCiAgICAgICAgICBlbmNvZGVTY3JhdGNoMkQKICAgICAgICApOwogICAgICAgIGZvcndhcmRPZmZzZXQyRCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgICAgIGVuZDJELAogICAgICAgICAgc3RhcnQyRCwKICAgICAgICAgIGZvcndhcmRPZmZzZXQyRFNjcmF0Y2gKICAgICAgICApOwogICAgICAgIHJpZ2h0MkQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKGZvcndhcmRPZmZzZXQyRCwgcmlnaHQyRFNjcmF0Y2gpOwogICAgICAgIGNvbnN0IHN3YXAyID0gcmlnaHQyRC54OwogICAgICAgIHJpZ2h0MkQueCA9IHJpZ2h0MkQueTsKICAgICAgICByaWdodDJELnkgPSAtc3dhcDI7CiAgICAgICAgdGV4Y29vcmROb3JtYWxpemF0aW9uMkRYID0gc2VnbWVudExlbmd0aDJEIC8gbGVuZ3RoMkQ7CiAgICAgICAgdGV4Y29vcmROb3JtYWxpemF0aW9uMkRZID0gbGVuZ3RoU29GYXIyRCAvIGxlbmd0aDJEOwogICAgICB9CiAgICAgIGZvciAoaiA9IDA7IGogPCA4OyBqKyspIHsKICAgICAgICBjb25zdCB2ZWM0SW5kZXggPSB2ZWM0c1dyaXRlSW5kZXggKyBqICogNDsKICAgICAgICBjb25zdCB2ZWMySW5kZXggPSB2ZWMyc1dyaXRlSW5kZXggKyBqICogMjsKICAgICAgICBjb25zdCB3SW5kZXggPSB2ZWM0SW5kZXggKyAzOwogICAgICAgIGNvbnN0IHJpZ2h0UGxhbmVTaWRlID0gaiA8IDQgPyAxIDogLTE7CiAgICAgICAgY29uc3QgdG9wQm90dG9tU2lkZSA9IGogPT09IDIgfHwgaiA9PT0gMyB8fCBqID09PSA2IHx8IGogPT09IDcgPyAxIDogLTE7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soZW5jb2RlZFN0YXJ0LmhpZ2gsIHN0YXJ0SGlBbmRGb3J3YXJkT2Zmc2V0WCwgdmVjNEluZGV4KTsKICAgICAgICBzdGFydEhpQW5kRm9yd2FyZE9mZnNldFhbd0luZGV4XSA9IGZvcndhcmRPZmZzZXQueDsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhlbmNvZGVkU3RhcnQubG93LCBzdGFydExvQW5kRm9yd2FyZE9mZnNldFksIHZlYzRJbmRleCk7CiAgICAgICAgc3RhcnRMb0FuZEZvcndhcmRPZmZzZXRZW3dJbmRleF0gPSBmb3J3YXJkT2Zmc2V0Lnk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soCiAgICAgICAgICBzdGFydFBsYW5lTm9ybWFsLAogICAgICAgICAgc3RhcnROb3JtYWxBbmRGb3J3YXJkT2Zmc2V0WiwKICAgICAgICAgIHZlYzRJbmRleAogICAgICAgICk7CiAgICAgICAgc3RhcnROb3JtYWxBbmRGb3J3YXJkT2Zmc2V0Wlt3SW5kZXhdID0gZm9yd2FyZE9mZnNldC56OwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKAogICAgICAgICAgZW5kUGxhbmVOb3JtYWwsCiAgICAgICAgICBlbmROb3JtYWxBbmRUZXh0dXJlQ29vcmRpbmF0ZU5vcm1hbGl6YXRpb25YLAogICAgICAgICAgdmVjNEluZGV4CiAgICAgICAgKTsKICAgICAgICBlbmROb3JtYWxBbmRUZXh0dXJlQ29vcmRpbmF0ZU5vcm1hbGl6YXRpb25YW3dJbmRleF0gPSB0ZXhjb29yZE5vcm1hbGl6YXRpb24zRFggKiByaWdodFBsYW5lU2lkZTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjaygKICAgICAgICAgIHJpZ2h0Tm9ybWFsLAogICAgICAgICAgcmlnaHROb3JtYWxBbmRUZXh0dXJlQ29vcmRpbmF0ZU5vcm1hbGl6YXRpb25ZLAogICAgICAgICAgdmVjNEluZGV4CiAgICAgICAgKTsKICAgICAgICBsZXQgdGV4Y29vcmROb3JtYWxpemF0aW9uID0gdGV4Y29vcmROb3JtYWxpemF0aW9uM0RZICogdG9wQm90dG9tU2lkZTsKICAgICAgICBpZiAodGV4Y29vcmROb3JtYWxpemF0aW9uID09PSAwICYmIHRvcEJvdHRvbVNpZGUgPCAwKSB7CiAgICAgICAgICB0ZXhjb29yZE5vcm1hbGl6YXRpb24gPSA5OwogICAgICAgIH0KICAgICAgICByaWdodE5vcm1hbEFuZFRleHR1cmVDb29yZGluYXRlTm9ybWFsaXphdGlvbllbd0luZGV4XSA9IHRleGNvb3JkTm9ybWFsaXphdGlvbjsKICAgICAgICBpZiAoY29tcHV0ZTJkQXR0cmlidXRlcykgewogICAgICAgICAgc3RhcnRIaUxvMkRbdmVjNEluZGV4XSA9IGVuY29kZWRTdGFydDJELmhpZ2gueDsKICAgICAgICAgIHN0YXJ0SGlMbzJEW3ZlYzRJbmRleCArIDFdID0gZW5jb2RlZFN0YXJ0MkQuaGlnaC55OwogICAgICAgICAgc3RhcnRIaUxvMkRbdmVjNEluZGV4ICsgMl0gPSBlbmNvZGVkU3RhcnQyRC5sb3cueDsKICAgICAgICAgIHN0YXJ0SGlMbzJEW3ZlYzRJbmRleCArIDNdID0gZW5jb2RlZFN0YXJ0MkQubG93Lnk7CiAgICAgICAgICBzdGFydEVuZE5vcm1hbHMyRFt2ZWM0SW5kZXhdID0gLXN0YXJ0R2VvbWV0cnlOb3JtYWwyRC55OwogICAgICAgICAgc3RhcnRFbmROb3JtYWxzMkRbdmVjNEluZGV4ICsgMV0gPSBzdGFydEdlb21ldHJ5Tm9ybWFsMkQueDsKICAgICAgICAgIHN0YXJ0RW5kTm9ybWFsczJEW3ZlYzRJbmRleCArIDJdID0gZW5kR2VvbWV0cnlOb3JtYWwyRC55OwogICAgICAgICAgc3RhcnRFbmROb3JtYWxzMkRbdmVjNEluZGV4ICsgM10gPSAtZW5kR2VvbWV0cnlOb3JtYWwyRC54OwogICAgICAgICAgb2Zmc2V0QW5kUmlnaHQyRFt2ZWM0SW5kZXhdID0gZm9yd2FyZE9mZnNldDJELng7CiAgICAgICAgICBvZmZzZXRBbmRSaWdodDJEW3ZlYzRJbmRleCArIDFdID0gZm9yd2FyZE9mZnNldDJELnk7CiAgICAgICAgICBvZmZzZXRBbmRSaWdodDJEW3ZlYzRJbmRleCArIDJdID0gcmlnaHQyRC54OwogICAgICAgICAgb2Zmc2V0QW5kUmlnaHQyRFt2ZWM0SW5kZXggKyAzXSA9IHJpZ2h0MkQueTsKICAgICAgICAgIHRleGNvb3JkTm9ybWFsaXphdGlvbjJEW3ZlYzJJbmRleF0gPSB0ZXhjb29yZE5vcm1hbGl6YXRpb24yRFggKiByaWdodFBsYW5lU2lkZTsKICAgICAgICAgIHRleGNvb3JkTm9ybWFsaXphdGlvbiA9IHRleGNvb3JkTm9ybWFsaXphdGlvbjJEWSAqIHRvcEJvdHRvbVNpZGU7CiAgICAgICAgICBpZiAodGV4Y29vcmROb3JtYWxpemF0aW9uID09PSAwICYmIHRvcEJvdHRvbVNpZGUgPCAwKSB7CiAgICAgICAgICAgIHRleGNvb3JkTm9ybWFsaXphdGlvbiA9IDk7CiAgICAgICAgICB9CiAgICAgICAgICB0ZXhjb29yZE5vcm1hbGl6YXRpb24yRFt2ZWMySW5kZXggKyAxXSA9IHRleGNvb3JkTm9ybWFsaXphdGlvbjsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgYWRqdXN0SGVpZ2h0U3RhcnRCb3R0b20gPSBhZGp1c3RIZWlnaHRTdGFydEJvdHRvbVNjcmF0Y2g7CiAgICAgIGNvbnN0IGFkanVzdEhlaWdodEVuZEJvdHRvbSA9IGFkanVzdEhlaWdodEVuZEJvdHRvbVNjcmF0Y2g7CiAgICAgIGNvbnN0IGFkanVzdEhlaWdodFN0YXJ0VG9wID0gYWRqdXN0SGVpZ2h0U3RhcnRUb3BTY3JhdGNoOwogICAgICBjb25zdCBhZGp1c3RIZWlnaHRFbmRUb3AgPSBhZGp1c3RIZWlnaHRFbmRUb3BTY3JhdGNoOwogICAgICBjb25zdCBnZXRIZWlnaHRzUmVjdGFuZ2xlID0gUmVjdGFuZ2xlX2RlZmF1bHQuZnJvbUNhcnRvZ3JhcGhpY0FycmF5KAogICAgICAgIGdldEhlaWdodENhcnRvZ3JhcGhpY3MsCiAgICAgICAgZ2V0SGVpZ2h0UmVjdGFuZ2xlU2NyYXRjaAogICAgICApOwogICAgICBjb25zdCBtaW5NYXhIZWlnaHRzID0gQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0c19kZWZhdWx0LmdldE1pbmltdW1NYXhpbXVtSGVpZ2h0cygKICAgICAgICBnZXRIZWlnaHRzUmVjdGFuZ2xlLAogICAgICAgIGVsbGlwc29pZAogICAgICApOwogICAgICBjb25zdCBtaW5IZWlnaHQgPSBtaW5NYXhIZWlnaHRzLm1pbmltdW1UZXJyYWluSGVpZ2h0OwogICAgICBjb25zdCBtYXhIZWlnaHQgPSBtaW5NYXhIZWlnaHRzLm1heGltdW1UZXJyYWluSGVpZ2h0OwogICAgICBzdW1IZWlnaHRzICs9IE1hdGguYWJzKG1pbkhlaWdodCk7CiAgICAgIHN1bUhlaWdodHMgKz0gTWF0aC5hYnMobWF4SGVpZ2h0KTsKICAgICAgYWRqdXN0SGVpZ2h0cygKICAgICAgICBzdGFydEJvdHRvbSwKICAgICAgICBzdGFydFRvcCwKICAgICAgICBtaW5IZWlnaHQsCiAgICAgICAgbWF4SGVpZ2h0LAogICAgICAgIGFkanVzdEhlaWdodFN0YXJ0Qm90dG9tLAogICAgICAgIGFkanVzdEhlaWdodFN0YXJ0VG9wCiAgICAgICk7CiAgICAgIGFkanVzdEhlaWdodHMoCiAgICAgICAgZW5kQm90dG9tLAogICAgICAgIGVuZFRvcCwKICAgICAgICBtaW5IZWlnaHQsCiAgICAgICAgbWF4SGVpZ2h0LAogICAgICAgIGFkanVzdEhlaWdodEVuZEJvdHRvbSwKICAgICAgICBhZGp1c3RIZWlnaHRFbmRUb3AKICAgICAgKTsKICAgICAgbGV0IG5vcm1hbE51ZGdlID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgcmlnaHROb3JtYWwsCiAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT041LAogICAgICAgIG5vcm1hbE51ZGdlU2NyYXRjaAogICAgICApOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKAogICAgICAgIGFkanVzdEhlaWdodFN0YXJ0Qm90dG9tLAogICAgICAgIG5vcm1hbE51ZGdlLAogICAgICAgIGFkanVzdEhlaWdodFN0YXJ0Qm90dG9tCiAgICAgICk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoYWRqdXN0SGVpZ2h0RW5kQm90dG9tLCBub3JtYWxOdWRnZSwgYWRqdXN0SGVpZ2h0RW5kQm90dG9tKTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChhZGp1c3RIZWlnaHRTdGFydFRvcCwgbm9ybWFsTnVkZ2UsIGFkanVzdEhlaWdodFN0YXJ0VG9wKTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChhZGp1c3RIZWlnaHRFbmRUb3AsIG5vcm1hbE51ZGdlLCBhZGp1c3RIZWlnaHRFbmRUb3ApOwogICAgICBudWRnZVhaKGFkanVzdEhlaWdodFN0YXJ0Qm90dG9tLCBhZGp1c3RIZWlnaHRFbmRCb3R0b20pOwogICAgICBudWRnZVhaKGFkanVzdEhlaWdodFN0YXJ0VG9wLCBhZGp1c3RIZWlnaHRFbmRUb3ApOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhhZGp1c3RIZWlnaHRTdGFydEJvdHRvbSwgcG9zaXRpb25zQXJyYXksIHZlYzNzV3JpdGVJbmRleCk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKGFkanVzdEhlaWdodEVuZEJvdHRvbSwgcG9zaXRpb25zQXJyYXksIHZlYzNzV3JpdGVJbmRleCArIDMpOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhhZGp1c3RIZWlnaHRFbmRUb3AsIHBvc2l0aW9uc0FycmF5LCB2ZWMzc1dyaXRlSW5kZXggKyA2KTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soYWRqdXN0SGVpZ2h0U3RhcnRUb3AsIHBvc2l0aW9uc0FycmF5LCB2ZWMzc1dyaXRlSW5kZXggKyA5KTsKICAgICAgbm9ybWFsTnVkZ2UgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubXVsdGlwbHlCeVNjYWxhcigKICAgICAgICByaWdodE5vcm1hbCwKICAgICAgICAtMiAqIE1hdGhfZGVmYXVsdC5FUFNJTE9ONSwKICAgICAgICBub3JtYWxOdWRnZVNjcmF0Y2gKICAgICAgKTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZCgKICAgICAgICBhZGp1c3RIZWlnaHRTdGFydEJvdHRvbSwKICAgICAgICBub3JtYWxOdWRnZSwKICAgICAgICBhZGp1c3RIZWlnaHRTdGFydEJvdHRvbQogICAgICApOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKGFkanVzdEhlaWdodEVuZEJvdHRvbSwgbm9ybWFsTnVkZ2UsIGFkanVzdEhlaWdodEVuZEJvdHRvbSk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoYWRqdXN0SGVpZ2h0U3RhcnRUb3AsIG5vcm1hbE51ZGdlLCBhZGp1c3RIZWlnaHRTdGFydFRvcCk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoYWRqdXN0SGVpZ2h0RW5kVG9wLCBub3JtYWxOdWRnZSwgYWRqdXN0SGVpZ2h0RW5kVG9wKTsKICAgICAgbnVkZ2VYWihhZGp1c3RIZWlnaHRTdGFydEJvdHRvbSwgYWRqdXN0SGVpZ2h0RW5kQm90dG9tKTsKICAgICAgbnVkZ2VYWihhZGp1c3RIZWlnaHRTdGFydFRvcCwgYWRqdXN0SGVpZ2h0RW5kVG9wKTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soCiAgICAgICAgYWRqdXN0SGVpZ2h0U3RhcnRCb3R0b20sCiAgICAgICAgcG9zaXRpb25zQXJyYXksCiAgICAgICAgdmVjM3NXcml0ZUluZGV4ICsgMTIKICAgICAgKTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soCiAgICAgICAgYWRqdXN0SGVpZ2h0RW5kQm90dG9tLAogICAgICAgIHBvc2l0aW9uc0FycmF5LAogICAgICAgIHZlYzNzV3JpdGVJbmRleCArIDE1CiAgICAgICk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKGFkanVzdEhlaWdodEVuZFRvcCwgcG9zaXRpb25zQXJyYXksIHZlYzNzV3JpdGVJbmRleCArIDE4KTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soYWRqdXN0SGVpZ2h0U3RhcnRUb3AsIHBvc2l0aW9uc0FycmF5LCB2ZWMzc1dyaXRlSW5kZXggKyAyMSk7CiAgICAgIGNhcnRvZ3JhcGhpY3NJbmRleCArPSAyOwogICAgICBpbmRleCArPSAzOwogICAgICB2ZWMyc1dyaXRlSW5kZXggKz0gMTY7CiAgICAgIHZlYzNzV3JpdGVJbmRleCArPSAyNDsKICAgICAgdmVjNHNXcml0ZUluZGV4ICs9IDMyOwogICAgICBsZW5ndGhTb0ZhcjNEICs9IHNlZ21lbnRMZW5ndGgzRDsKICAgICAgbGVuZ3RoU29GYXIyRCArPSBzZWdtZW50TGVuZ3RoMkQ7CiAgICB9CiAgICBpbmRleCA9IDA7CiAgICBsZXQgaW5kZXhPZmZzZXQgPSAwOwogICAgZm9yIChpID0gMDsgaSA8IHNlZ21lbnRDb3VudDsgaSsrKSB7CiAgICAgIGZvciAoaiA9IDA7IGogPCBSRUZFUkVOQ0VfSU5ESUNFU19MRU5HVEg7IGorKykgewogICAgICAgIGluZGljZXNbaW5kZXggKyBqXSA9IFJFRkVSRU5DRV9JTkRJQ0VTW2pdICsgaW5kZXhPZmZzZXQ7CiAgICAgIH0KICAgICAgaW5kZXhPZmZzZXQgKz0gODsKICAgICAgaW5kZXggKz0gUkVGRVJFTkNFX0lORElDRVNfTEVOR1RIOwogICAgfQogICAgY29uc3QgYm91bmRpbmdTcGhlcmVzID0gc2NyYXRjaEJvdW5kaW5nU3BoZXJlczsKICAgIEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbVZlcnRpY2VzKAogICAgICBib3R0b21Qb3NpdGlvbnNBcnJheSwKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sCiAgICAgIDMsCiAgICAgIGJvdW5kaW5nU3BoZXJlc1swXQogICAgKTsKICAgIEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbVZlcnRpY2VzKAogICAgICB0b3BQb3NpdGlvbnNBcnJheSwKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sCiAgICAgIDMsCiAgICAgIGJvdW5kaW5nU3BoZXJlc1sxXQogICAgKTsKICAgIGNvbnN0IGJvdW5kaW5nU3BoZXJlID0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5mcm9tQm91bmRpbmdTcGhlcmVzKGJvdW5kaW5nU3BoZXJlcyk7CiAgICBib3VuZGluZ1NwaGVyZS5yYWRpdXMgKz0gc3VtSGVpZ2h0cyAvIChzZWdtZW50Q291bnQgKiAyKTsKICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSB7CiAgICAgIHBvc2l0aW9uOiBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFLAogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgbm9ybWFsaXplOiBmYWxzZSwKICAgICAgICB2YWx1ZXM6IHBvc2l0aW9uc0FycmF5CiAgICAgIH0pLAogICAgICBzdGFydEhpQW5kRm9yd2FyZE9mZnNldFg6IGdldFZlYzRHZW9tZXRyeUF0dHJpYnV0ZSgKICAgICAgICBzdGFydEhpQW5kRm9yd2FyZE9mZnNldFgKICAgICAgKSwKICAgICAgc3RhcnRMb0FuZEZvcndhcmRPZmZzZXRZOiBnZXRWZWM0R2VvbWV0cnlBdHRyaWJ1dGUoCiAgICAgICAgc3RhcnRMb0FuZEZvcndhcmRPZmZzZXRZCiAgICAgICksCiAgICAgIHN0YXJ0Tm9ybWFsQW5kRm9yd2FyZE9mZnNldFo6IGdldFZlYzRHZW9tZXRyeUF0dHJpYnV0ZSgKICAgICAgICBzdGFydE5vcm1hbEFuZEZvcndhcmRPZmZzZXRaCiAgICAgICksCiAgICAgIGVuZE5vcm1hbEFuZFRleHR1cmVDb29yZGluYXRlTm9ybWFsaXphdGlvblg6IGdldFZlYzRHZW9tZXRyeUF0dHJpYnV0ZSgKICAgICAgICBlbmROb3JtYWxBbmRUZXh0dXJlQ29vcmRpbmF0ZU5vcm1hbGl6YXRpb25YCiAgICAgICksCiAgICAgIHJpZ2h0Tm9ybWFsQW5kVGV4dHVyZUNvb3JkaW5hdGVOb3JtYWxpemF0aW9uWTogZ2V0VmVjNEdlb21ldHJ5QXR0cmlidXRlKAogICAgICAgIHJpZ2h0Tm9ybWFsQW5kVGV4dHVyZUNvb3JkaW5hdGVOb3JtYWxpemF0aW9uWQogICAgICApCiAgICB9OwogICAgaWYgKGNvbXB1dGUyZEF0dHJpYnV0ZXMpIHsKICAgICAgYXR0cmlidXRlcy5zdGFydEhpTG8yRCA9IGdldFZlYzRHZW9tZXRyeUF0dHJpYnV0ZShzdGFydEhpTG8yRCk7CiAgICAgIGF0dHJpYnV0ZXMub2Zmc2V0QW5kUmlnaHQyRCA9IGdldFZlYzRHZW9tZXRyeUF0dHJpYnV0ZShvZmZzZXRBbmRSaWdodDJEKTsKICAgICAgYXR0cmlidXRlcy5zdGFydEVuZE5vcm1hbHMyRCA9IGdldFZlYzRHZW9tZXRyeUF0dHJpYnV0ZShzdGFydEVuZE5vcm1hbHMyRCk7CiAgICAgIGF0dHJpYnV0ZXMudGV4Y29vcmROb3JtYWxpemF0aW9uMkQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMiwKICAgICAgICBub3JtYWxpemU6IGZhbHNlLAogICAgICAgIHZhbHVlczogdGV4Y29vcmROb3JtYWxpemF0aW9uMkQKICAgICAgfSk7CiAgICB9CiAgICByZXR1cm4gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICBhdHRyaWJ1dGVzLAogICAgICBpbmRpY2VzLAogICAgICBib3VuZGluZ1NwaGVyZQogICAgfSk7CiAgfQogIGZ1bmN0aW9uIGdldFZlYzRHZW9tZXRyeUF0dHJpYnV0ZSh0eXBlZEFycmF5KSB7CiAgICByZXR1cm4gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogNCwKICAgICAgbm9ybWFsaXplOiBmYWxzZSwKICAgICAgdmFsdWVzOiB0eXBlZEFycmF5CiAgICB9KTsKICB9CiAgdmFyIFBST0pFQ1RJT05TLCBQUk9KRUNUSU9OX0NPVU5ULCBNSVRFUl9CUkVBS19TTUFMTCwgTUlURVJfQlJFQUtfTEFSR0UsIFdBTExfSU5JVElBTF9NSU5fSEVJR0hULCBXQUxMX0lOSVRJQUxfTUFYX0hFSUdIVCwgY2FydDNTY3JhdGNoMSwgY2FydDNTY3JhdGNoMiwgY2FydDNTY3JhdGNoMywgaW50ZXJwb2xhdGVkQ2FydG9ncmFwaGljU2NyYXRjaCwgaW50ZXJwb2xhdGVkQm90dG9tU2NyYXRjaCwgaW50ZXJwb2xhdGVkVG9wU2NyYXRjaCwgaW50ZXJwb2xhdGVkTm9ybWFsU2NyYXRjaCwgaGVpZ2h0bGVzc0NhcnRvZ3JhcGhpY1NjcmF0Y2gsIHRvUHJldmlvdXNTY3JhdGNoLCB0b05leHRTY3JhdGNoLCBmb3J3YXJkU2NyYXRjaCwgdmVydGV4VXBTY3JhdGNoLCBjb3NpbmU5MCwgY29zaW5lMTgwLCBYWl9QTEFORSwgcHJldmlvdXNCb3R0b21TY3JhdGNoLCB2ZXJ0ZXhCb3R0b21TY3JhdGNoLCB2ZXJ0ZXhUb3BTY3JhdGNoLCBuZXh0Qm90dG9tU2NyYXRjaCwgdmVydGV4Tm9ybWFsU2NyYXRjaCwgaW50ZXJzZWN0aW9uU2NyYXRjaCwgY2FydG9ncmFwaGljU2NyYXRjaDAsIGNhcnRvZ3JhcGhpY1NjcmF0Y2gxLCBjYXJ0b2dyYXBoaWNJbnRlcnNlY3Rpb25TY3JhdGNoLCBsaW5lRGlyZWN0aW9uU2NyYXRjaCwgbWF0cml4M1NjcmF0Y2gsIHF1YXRlcm5pb25TY3JhdGNoMywgZW5kUG9zQ2FydG9ncmFwaGljU2NyYXRjaCwgbm9ybWFsU3RhcnRwb2ludFNjcmF0Y2gsIG5vcm1hbEVuZHBvaW50U2NyYXRjaCwgYWRqdXN0SGVpZ2h0Tm9ybWFsU2NyYXRjaCwgYWRqdXN0SGVpZ2h0T2Zmc2V0U2NyYXRjaCwgbnVkZ2VEaXJlY3Rpb25TY3JhdGNoLCBzdGFydENhcnRvZ3JhcGhpY1NjcmF0Y2gsIGVuZENhcnRvZ3JhcGhpY1NjcmF0Y2gsIHNlZ21lbnRTdGFydFRvcFNjcmF0Y2gsIHNlZ21lbnRFbmRUb3BTY3JhdGNoLCBzZWdtZW50U3RhcnRCb3R0b21TY3JhdGNoLCBzZWdtZW50RW5kQm90dG9tU2NyYXRjaCwgc2VnbWVudFN0YXJ0Tm9ybWFsU2NyYXRjaCwgc2VnbWVudEVuZE5vcm1hbFNjcmF0Y2gsIGdldEhlaWdodENhcnRvZ3JhcGhpY3MsIGdldEhlaWdodFJlY3RhbmdsZVNjcmF0Y2gsIGFkanVzdEhlaWdodFN0YXJ0VG9wU2NyYXRjaCwgYWRqdXN0SGVpZ2h0RW5kVG9wU2NyYXRjaCwgYWRqdXN0SGVpZ2h0U3RhcnRCb3R0b21TY3JhdGNoLCBhZGp1c3RIZWlnaHRFbmRCb3R0b21TY3JhdGNoLCBzZWdtZW50U3RhcnQyRFNjcmF0Y2gsIHNlZ21lbnRFbmQyRFNjcmF0Y2gsIHNlZ21lbnRTdGFydE5vcm1hbDJEU2NyYXRjaCwgc2VnbWVudEVuZE5vcm1hbDJEU2NyYXRjaCwgb2Zmc2V0U2NyYXRjaDIsIHN0YXJ0VXBTY3JhdGNoLCBlbmRVcFNjcmF0Y2gsIHJpZ2h0U2NyYXRjaDIsIHN0YXJ0UGxhbmVOb3JtYWxTY3JhdGNoLCBlbmRQbGFuZU5vcm1hbFNjcmF0Y2gsIGVuY29kZVNjcmF0Y2gsIGVuY29kZVNjcmF0Y2gyRCwgZm9yd2FyZE9mZnNldDJEU2NyYXRjaCwgcmlnaHQyRFNjcmF0Y2gsIG5vcm1hbE51ZGdlU2NyYXRjaCwgc2NyYXRjaEJvdW5kaW5nU3BoZXJlcywgUkVGRVJFTkNFX0lORElDRVMsIFJFRkVSRU5DRV9JTkRJQ0VTX0xFTkdUSCwgR3JvdW5kUG9seWxpbmVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X0dyb3VuZFBvbHlsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dyb3VuZFBvbHlsaW5lR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0FwcHJveGltYXRlVGVycmFpbkhlaWdodHMoKTsKICAgICAgaW5pdF9BcmNUeXBlKCk7CiAgICAgIGluaXRfYXJyYXlSZW1vdmVEdXBsaWNhdGVzKCk7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0VsbGlwc29pZEdlb2Rlc2ljKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkUmh1bWJMaW5lKCk7CiAgICAgIGluaXRfRW5jb2RlZENhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9HZW9ncmFwaGljUHJvamVjdGlvbigpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9JbnRlcnNlY3Rpb25UZXN0cygpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9NYXRyaXgzKCk7CiAgICAgIGluaXRfUGxhbmUoKTsKICAgICAgaW5pdF9RdWF0ZXJuaW9uKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfV2ViTWVyY2F0b3JQcm9qZWN0aW9uKCk7CiAgICAgIFBST0pFQ1RJT05TID0gW0dlb2dyYXBoaWNQcm9qZWN0aW9uX2RlZmF1bHQsIFdlYk1lcmNhdG9yUHJvamVjdGlvbl9kZWZhdWx0XTsKICAgICAgUFJPSkVDVElPTl9DT1VOVCA9IFBST0pFQ1RJT05TLmxlbmd0aDsKICAgICAgTUlURVJfQlJFQUtfU01BTEwgPSBNYXRoLmNvcyhNYXRoX2RlZmF1bHQudG9SYWRpYW5zKDMwKSk7CiAgICAgIE1JVEVSX0JSRUFLX0xBUkdFID0gTWF0aC5jb3MoTWF0aF9kZWZhdWx0LnRvUmFkaWFucygxNTApKTsKICAgICAgV0FMTF9JTklUSUFMX01JTl9IRUlHSFQgPSAwOwogICAgICBXQUxMX0lOSVRJQUxfTUFYX0hFSUdIVCA9IDFlMzsKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoR3JvdW5kUG9seWxpbmVHZW9tZXRyeS5wcm90b3R5cGUsIHsKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHVzZWQgdG8gcGFjayB0aGUgb2JqZWN0IGludG8gYW4gYXJyYXkuCiAgICAgICAgICogQG1lbWJlcm9mIEdyb3VuZFBvbHlsaW5lR2VvbWV0cnkucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKiBAcHJpdmF0ZQogICAgICAgICAqLwogICAgICAgIHBhY2tlZExlbmd0aDogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIDEgKyB0aGlzLl9wb3NpdGlvbnMubGVuZ3RoICogMyArIDEgKyAxICsgMSArIEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIDEgKyAxOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIEdyb3VuZFBvbHlsaW5lR2VvbWV0cnkuc2V0UHJvamVjdGlvbkFuZEVsbGlwc29pZCA9IGZ1bmN0aW9uKGdyb3VuZFBvbHlsaW5lR2VvbWV0cnksIG1hcFByb2plY3Rpb24pIHsKICAgICAgICBsZXQgcHJvamVjdGlvbkluZGV4ID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IFBST0pFQ1RJT05fQ09VTlQ7IGkrKykgewogICAgICAgICAgaWYgKG1hcFByb2plY3Rpb24gaW5zdGFuY2VvZiBQUk9KRUNUSU9OU1tpXSkgewogICAgICAgICAgICBwcm9qZWN0aW9uSW5kZXggPSBpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZ3JvdW5kUG9seWxpbmVHZW9tZXRyeS5fcHJvamVjdGlvbkluZGV4ID0gcHJvamVjdGlvbkluZGV4OwogICAgICAgIGdyb3VuZFBvbHlsaW5lR2VvbWV0cnkuX2VsbGlwc29pZCA9IG1hcFByb2plY3Rpb24uZWxsaXBzb2lkOwogICAgICB9OwogICAgICBjYXJ0M1NjcmF0Y2gxID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBjYXJ0M1NjcmF0Y2gyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBjYXJ0M1NjcmF0Y2gzID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBpbnRlcnBvbGF0ZWRDYXJ0b2dyYXBoaWNTY3JhdGNoID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIGludGVycG9sYXRlZEJvdHRvbVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGludGVycG9sYXRlZFRvcFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGludGVycG9sYXRlZE5vcm1hbFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGhlaWdodGxlc3NDYXJ0b2dyYXBoaWNTY3JhdGNoID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIEdyb3VuZFBvbHlsaW5lR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBsZXQgaW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gdmFsdWUuX3Bvc2l0aW9uczsKICAgICAgICBjb25zdCBwb3NpdGlvbnNMZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgICAgIGFycmF5W2luZGV4KytdID0gcG9zaXRpb25zTGVuZ3RoOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9zaXRpb25zTGVuZ3RoOyArK2kpIHsKICAgICAgICAgIGNvbnN0IGNhcnRlc2lhbjExID0gcG9zaXRpb25zW2ldOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soY2FydGVzaWFuMTEsIGFycmF5LCBpbmRleCk7CiAgICAgICAgICBpbmRleCArPSAzOwogICAgICAgIH0KICAgICAgICBhcnJheVtpbmRleCsrXSA9IHZhbHVlLmdyYW51bGFyaXR5OwogICAgICAgIGFycmF5W2luZGV4KytdID0gdmFsdWUubG9vcCA/IDEgOiAwOwogICAgICAgIGFycmF5W2luZGV4KytdID0gdmFsdWUuYXJjVHlwZTsKICAgICAgICBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrKHZhbHVlLl9lbGxpcHNvaWQsIGFycmF5LCBpbmRleCk7CiAgICAgICAgaW5kZXggKz0gRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGFycmF5W2luZGV4KytdID0gdmFsdWUuX3Byb2plY3Rpb25JbmRleDsKICAgICAgICBhcnJheVtpbmRleCsrXSA9IHZhbHVlLl9zY2VuZTNET25seSA/IDEgOiAwOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgR3JvdW5kUG9seWxpbmVHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBsZXQgaW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgY29uc3QgcG9zaXRpb25zTGVuZ3RoID0gYXJyYXlbaW5kZXgrK107CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEFycmF5KHBvc2l0aW9uc0xlbmd0aCk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb3NpdGlvbnNMZW5ndGg7IGkrKykgewogICAgICAgICAgcG9zaXRpb25zW2ldID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjayhhcnJheSwgaW5kZXgpOwogICAgICAgICAgaW5kZXggKz0gMzsKICAgICAgICB9CiAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBhcnJheVtpbmRleCsrXTsKICAgICAgICBjb25zdCBsb29wID0gYXJyYXlbaW5kZXgrK10gPT09IDE7CiAgICAgICAgY29uc3QgYXJjVHlwZSA9IGFycmF5W2luZGV4KytdOwogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LnVucGFjayhhcnJheSwgaW5kZXgpOwogICAgICAgIGluZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCBwcm9qZWN0aW9uSW5kZXggPSBhcnJheVtpbmRleCsrXTsKICAgICAgICBjb25zdCBzY2VuZTNET25seSA9IGFycmF5W2luZGV4KytdID09PSAxOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBHcm91bmRQb2x5bGluZUdlb21ldHJ5KHsKICAgICAgICAgICAgcG9zaXRpb25zCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0Ll9wb3NpdGlvbnMgPSBwb3NpdGlvbnM7CiAgICAgICAgcmVzdWx0LmdyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICAgICAgcmVzdWx0Lmxvb3AgPSBsb29wOwogICAgICAgIHJlc3VsdC5hcmNUeXBlID0gYXJjVHlwZTsKICAgICAgICByZXN1bHQuX2VsbGlwc29pZCA9IGVsbGlwc29pZDsKICAgICAgICByZXN1bHQuX3Byb2plY3Rpb25JbmRleCA9IHByb2plY3Rpb25JbmRleDsKICAgICAgICByZXN1bHQuX3NjZW5lM0RPbmx5ID0gc2NlbmUzRE9ubHk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgdG9QcmV2aW91c1NjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHRvTmV4dFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZvcndhcmRTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICB2ZXJ0ZXhVcFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNvc2luZTkwID0gMDsKICAgICAgY29zaW5lMTgwID0gLTE7CiAgICAgIFhaX1BMQU5FID0gUGxhbmVfZGVmYXVsdC5mcm9tUG9pbnROb3JtYWwoQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sIENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1kpOwogICAgICBwcmV2aW91c0JvdHRvbVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHZlcnRleEJvdHRvbVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHZlcnRleFRvcFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIG5leHRCb3R0b21TY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICB2ZXJ0ZXhOb3JtYWxTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBpbnRlcnNlY3Rpb25TY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBjYXJ0b2dyYXBoaWNTY3JhdGNoMCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBjYXJ0b2dyYXBoaWNTY3JhdGNoMSA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBjYXJ0b2dyYXBoaWNJbnRlcnNlY3Rpb25TY3JhdGNoID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIEdyb3VuZFBvbHlsaW5lR2VvbWV0cnkuY3JlYXRlR2VvbWV0cnkgPSBmdW5jdGlvbihncm91bmRQb2x5bGluZUdlb21ldHJ5KSB7CiAgICAgICAgY29uc3QgY29tcHV0ZTJkQXR0cmlidXRlcyA9ICFncm91bmRQb2x5bGluZUdlb21ldHJ5Ll9zY2VuZTNET25seTsKICAgICAgICBsZXQgbG9vcCA9IGdyb3VuZFBvbHlsaW5lR2VvbWV0cnkubG9vcDsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBncm91bmRQb2x5bGluZUdlb21ldHJ5Ll9lbGxpcHNvaWQ7CiAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBncm91bmRQb2x5bGluZUdlb21ldHJ5LmdyYW51bGFyaXR5OwogICAgICAgIGNvbnN0IGFyY1R5cGUgPSBncm91bmRQb2x5bGluZUdlb21ldHJ5LmFyY1R5cGU7CiAgICAgICAgY29uc3QgcHJvamVjdGlvbiA9IG5ldyBQUk9KRUNUSU9OU1tncm91bmRQb2x5bGluZUdlb21ldHJ5Ll9wcm9qZWN0aW9uSW5kZXhdKAogICAgICAgICAgZWxsaXBzb2lkCiAgICAgICAgKTsKICAgICAgICBjb25zdCBtaW5IZWlnaHQgPSBXQUxMX0lOSVRJQUxfTUlOX0hFSUdIVDsKICAgICAgICBjb25zdCBtYXhIZWlnaHQgPSBXQUxMX0lOSVRJQUxfTUFYX0hFSUdIVDsKICAgICAgICBsZXQgaW5kZXg7CiAgICAgICAgbGV0IGk7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gZ3JvdW5kUG9seWxpbmVHZW9tZXRyeS5fcG9zaXRpb25zOwogICAgICAgIGNvbnN0IHBvc2l0aW9uc0xlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgaWYgKHBvc2l0aW9uc0xlbmd0aCA9PT0gMikgewogICAgICAgICAgbG9vcCA9IGZhbHNlOwogICAgICAgIH0KICAgICAgICBsZXQgcDA7CiAgICAgICAgbGV0IHAxOwogICAgICAgIGxldCBjMDsKICAgICAgICBsZXQgYzE7CiAgICAgICAgY29uc3Qgcmh1bWJMaW5lID0gbmV3IEVsbGlwc29pZFJodW1iTGluZV9kZWZhdWx0KHZvaWQgMCwgdm9pZCAwLCBlbGxpcHNvaWQpOwogICAgICAgIGxldCBpbnRlcnNlY3Rpb247CiAgICAgICAgbGV0IGludGVyc2VjdGlvbkNhcnRvZ3JhcGhpYzsKICAgICAgICBsZXQgaW50ZXJzZWN0aW9uTG9uZ2l0dWRlOwogICAgICAgIGNvbnN0IHNwbGl0UG9zaXRpb25zID0gW3Bvc2l0aW9uc1swXV07CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHBvc2l0aW9uc0xlbmd0aCAtIDE7IGkrKykgewogICAgICAgICAgcDAgPSBwb3NpdGlvbnNbaV07CiAgICAgICAgICBwMSA9IHBvc2l0aW9uc1tpICsgMV07CiAgICAgICAgICBpbnRlcnNlY3Rpb24gPSBJbnRlcnNlY3Rpb25UZXN0c19kZWZhdWx0LmxpbmVTZWdtZW50UGxhbmUoCiAgICAgICAgICAgIHAwLAogICAgICAgICAgICBwMSwKICAgICAgICAgICAgWFpfUExBTkUsCiAgICAgICAgICAgIGludGVyc2VjdGlvblNjcmF0Y2gKICAgICAgICAgICk7CiAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGludGVyc2VjdGlvbikgJiYgIUNhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKGludGVyc2VjdGlvbiwgcDAsIE1hdGhfZGVmYXVsdC5FUFNJTE9ONykgJiYgIUNhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKGludGVyc2VjdGlvbiwgcDEsIE1hdGhfZGVmYXVsdC5FUFNJTE9ONykpIHsKICAgICAgICAgICAgaWYgKGdyb3VuZFBvbHlsaW5lR2VvbWV0cnkuYXJjVHlwZSA9PT0gQXJjVHlwZV9kZWZhdWx0LkdFT0RFU0lDKSB7CiAgICAgICAgICAgICAgc3BsaXRQb3NpdGlvbnMucHVzaChDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoaW50ZXJzZWN0aW9uKSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoZ3JvdW5kUG9seWxpbmVHZW9tZXRyeS5hcmNUeXBlID09PSBBcmNUeXBlX2RlZmF1bHQuUkhVTUIpIHsKICAgICAgICAgICAgICBpbnRlcnNlY3Rpb25Mb25naXR1ZGUgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMoCiAgICAgICAgICAgICAgICBpbnRlcnNlY3Rpb24sCiAgICAgICAgICAgICAgICBjYXJ0b2dyYXBoaWNTY3JhdGNoMAogICAgICAgICAgICAgICkubG9uZ2l0dWRlOwogICAgICAgICAgICAgIGMwID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKHAwLCBjYXJ0b2dyYXBoaWNTY3JhdGNoMCk7CiAgICAgICAgICAgICAgYzEgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMocDEsIGNhcnRvZ3JhcGhpY1NjcmF0Y2gxKTsKICAgICAgICAgICAgICByaHVtYkxpbmUuc2V0RW5kUG9pbnRzKGMwLCBjMSk7CiAgICAgICAgICAgICAgaW50ZXJzZWN0aW9uQ2FydG9ncmFwaGljID0gcmh1bWJMaW5lLmZpbmRJbnRlcnNlY3Rpb25XaXRoTG9uZ2l0dWRlKAogICAgICAgICAgICAgICAgaW50ZXJzZWN0aW9uTG9uZ2l0dWRlLAogICAgICAgICAgICAgICAgY2FydG9ncmFwaGljSW50ZXJzZWN0aW9uU2NyYXRjaAogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgaW50ZXJzZWN0aW9uID0gZWxsaXBzb2lkLmNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuKAogICAgICAgICAgICAgICAgaW50ZXJzZWN0aW9uQ2FydG9ncmFwaGljLAogICAgICAgICAgICAgICAgaW50ZXJzZWN0aW9uU2NyYXRjaAogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChpbnRlcnNlY3Rpb24pICYmICFDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihpbnRlcnNlY3Rpb24sIHAwLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjcpICYmICFDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihpbnRlcnNlY3Rpb24sIHAxLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjcpKSB7CiAgICAgICAgICAgICAgICBzcGxpdFBvc2l0aW9ucy5wdXNoKENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShpbnRlcnNlY3Rpb24pKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHNwbGl0UG9zaXRpb25zLnB1c2gocDEpOwogICAgICAgIH0KICAgICAgICBpZiAobG9vcCkgewogICAgICAgICAgcDAgPSBwb3NpdGlvbnNbcG9zaXRpb25zTGVuZ3RoIC0gMV07CiAgICAgICAgICBwMSA9IHBvc2l0aW9uc1swXTsKICAgICAgICAgIGludGVyc2VjdGlvbiA9IEludGVyc2VjdGlvblRlc3RzX2RlZmF1bHQubGluZVNlZ21lbnRQbGFuZSgKICAgICAgICAgICAgcDAsCiAgICAgICAgICAgIHAxLAogICAgICAgICAgICBYWl9QTEFORSwKICAgICAgICAgICAgaW50ZXJzZWN0aW9uU2NyYXRjaAogICAgICAgICAgKTsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaW50ZXJzZWN0aW9uKSAmJiAhQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFsc0Vwc2lsb24oaW50ZXJzZWN0aW9uLCBwMCwgTWF0aF9kZWZhdWx0LkVQU0lMT043KSAmJiAhQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFsc0Vwc2lsb24oaW50ZXJzZWN0aW9uLCBwMSwgTWF0aF9kZWZhdWx0LkVQU0lMT043KSkgewogICAgICAgICAgICBpZiAoZ3JvdW5kUG9seWxpbmVHZW9tZXRyeS5hcmNUeXBlID09PSBBcmNUeXBlX2RlZmF1bHQuR0VPREVTSUMpIHsKICAgICAgICAgICAgICBzcGxpdFBvc2l0aW9ucy5wdXNoKENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShpbnRlcnNlY3Rpb24pKTsKICAgICAgICAgICAgfSBlbHNlIGlmIChncm91bmRQb2x5bGluZUdlb21ldHJ5LmFyY1R5cGUgPT09IEFyY1R5cGVfZGVmYXVsdC5SSFVNQikgewogICAgICAgICAgICAgIGludGVyc2VjdGlvbkxvbmdpdHVkZSA9IGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYygKICAgICAgICAgICAgICAgIGludGVyc2VjdGlvbiwKICAgICAgICAgICAgICAgIGNhcnRvZ3JhcGhpY1NjcmF0Y2gwCiAgICAgICAgICAgICAgKS5sb25naXR1ZGU7CiAgICAgICAgICAgICAgYzAgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMocDAsIGNhcnRvZ3JhcGhpY1NjcmF0Y2gwKTsKICAgICAgICAgICAgICBjMSA9IGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyhwMSwgY2FydG9ncmFwaGljU2NyYXRjaDEpOwogICAgICAgICAgICAgIHJodW1iTGluZS5zZXRFbmRQb2ludHMoYzAsIGMxKTsKICAgICAgICAgICAgICBpbnRlcnNlY3Rpb25DYXJ0b2dyYXBoaWMgPSByaHVtYkxpbmUuZmluZEludGVyc2VjdGlvbldpdGhMb25naXR1ZGUoCiAgICAgICAgICAgICAgICBpbnRlcnNlY3Rpb25Mb25naXR1ZGUsCiAgICAgICAgICAgICAgICBjYXJ0b2dyYXBoaWNJbnRlcnNlY3Rpb25TY3JhdGNoCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBpbnRlcnNlY3Rpb24gPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oCiAgICAgICAgICAgICAgICBpbnRlcnNlY3Rpb25DYXJ0b2dyYXBoaWMsCiAgICAgICAgICAgICAgICBpbnRlcnNlY3Rpb25TY3JhdGNoCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGludGVyc2VjdGlvbikgJiYgIUNhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKGludGVyc2VjdGlvbiwgcDAsIE1hdGhfZGVmYXVsdC5FUFNJTE9ONykgJiYgIUNhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKGludGVyc2VjdGlvbiwgcDEsIE1hdGhfZGVmYXVsdC5FUFNJTE9ONykpIHsKICAgICAgICAgICAgICAgIHNwbGl0UG9zaXRpb25zLnB1c2goQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGludGVyc2VjdGlvbikpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBsZXQgY2FydG9ncmFwaGljc0xlbmd0aCA9IHNwbGl0UG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBsZXQgY2FydG9ncmFwaGljcyA9IG5ldyBBcnJheShjYXJ0b2dyYXBoaWNzTGVuZ3RoKTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY2FydG9ncmFwaGljc0xlbmd0aDsgaSsrKSB7CiAgICAgICAgICBjb25zdCBjYXJ0b2dyYXBoaWMyID0gQ2FydG9ncmFwaGljX2RlZmF1bHQuZnJvbUNhcnRlc2lhbigKICAgICAgICAgICAgc3BsaXRQb3NpdGlvbnNbaV0sCiAgICAgICAgICAgIGVsbGlwc29pZAogICAgICAgICAgKTsKICAgICAgICAgIGNhcnRvZ3JhcGhpYzIuaGVpZ2h0ID0gMDsKICAgICAgICAgIGNhcnRvZ3JhcGhpY3NbaV0gPSBjYXJ0b2dyYXBoaWMyOwogICAgICAgIH0KICAgICAgICBjYXJ0b2dyYXBoaWNzID0gYXJyYXlSZW1vdmVEdXBsaWNhdGVzX2RlZmF1bHQoCiAgICAgICAgICBjYXJ0b2dyYXBoaWNzLAogICAgICAgICAgQ2FydG9ncmFwaGljX2RlZmF1bHQuZXF1YWxzRXBzaWxvbgogICAgICAgICk7CiAgICAgICAgY2FydG9ncmFwaGljc0xlbmd0aCA9IGNhcnRvZ3JhcGhpY3MubGVuZ3RoOwogICAgICAgIGlmIChjYXJ0b2dyYXBoaWNzTGVuZ3RoIDwgMikgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgY29uc3QgY2FydG9ncmFwaGljc0FycmF5ID0gW107CiAgICAgICAgY29uc3Qgbm9ybWFsc0FycmF5ID0gW107CiAgICAgICAgY29uc3QgYm90dG9tUG9zaXRpb25zQXJyYXkgPSBbXTsKICAgICAgICBjb25zdCB0b3BQb3NpdGlvbnNBcnJheSA9IFtdOwogICAgICAgIGxldCBwcmV2aW91c0JvdHRvbSA9IHByZXZpb3VzQm90dG9tU2NyYXRjaDsKICAgICAgICBsZXQgdmVydGV4Qm90dG9tID0gdmVydGV4Qm90dG9tU2NyYXRjaDsKICAgICAgICBsZXQgdmVydGV4VG9wID0gdmVydGV4VG9wU2NyYXRjaDsKICAgICAgICBsZXQgbmV4dEJvdHRvbSA9IG5leHRCb3R0b21TY3JhdGNoOwogICAgICAgIGxldCB2ZXJ0ZXhOb3JtYWwgPSB2ZXJ0ZXhOb3JtYWxTY3JhdGNoOwogICAgICAgIGNvbnN0IHN0YXJ0Q2FydG9ncmFwaGljID0gY2FydG9ncmFwaGljc1swXTsKICAgICAgICBjb25zdCBuZXh0Q2FydG9ncmFwaGljID0gY2FydG9ncmFwaGljc1sxXTsKICAgICAgICBjb25zdCBwcmVzdGFydENhcnRvZ3JhcGhpYyA9IGNhcnRvZ3JhcGhpY3NbY2FydG9ncmFwaGljc0xlbmd0aCAtIDFdOwogICAgICAgIHByZXZpb3VzQm90dG9tID0gZ2V0UG9zaXRpb24oCiAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICBwcmVzdGFydENhcnRvZ3JhcGhpYywKICAgICAgICAgIG1pbkhlaWdodCwKICAgICAgICAgIHByZXZpb3VzQm90dG9tCiAgICAgICAgKTsKICAgICAgICBuZXh0Qm90dG9tID0gZ2V0UG9zaXRpb24oZWxsaXBzb2lkLCBuZXh0Q2FydG9ncmFwaGljLCBtaW5IZWlnaHQsIG5leHRCb3R0b20pOwogICAgICAgIHZlcnRleEJvdHRvbSA9IGdldFBvc2l0aW9uKAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgc3RhcnRDYXJ0b2dyYXBoaWMsCiAgICAgICAgICBtaW5IZWlnaHQsCiAgICAgICAgICB2ZXJ0ZXhCb3R0b20KICAgICAgICApOwogICAgICAgIHZlcnRleFRvcCA9IGdldFBvc2l0aW9uKGVsbGlwc29pZCwgc3RhcnRDYXJ0b2dyYXBoaWMsIG1heEhlaWdodCwgdmVydGV4VG9wKTsKICAgICAgICBpZiAobG9vcCkgewogICAgICAgICAgdmVydGV4Tm9ybWFsID0gY29tcHV0ZVZlcnRleE1pdGVyTm9ybWFsKAogICAgICAgICAgICBwcmV2aW91c0JvdHRvbSwKICAgICAgICAgICAgdmVydGV4Qm90dG9tLAogICAgICAgICAgICB2ZXJ0ZXhUb3AsCiAgICAgICAgICAgIG5leHRCb3R0b20sCiAgICAgICAgICAgIHZlcnRleE5vcm1hbAogICAgICAgICAgKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmVydGV4Tm9ybWFsID0gY29tcHV0ZVJpZ2h0Tm9ybWFsKAogICAgICAgICAgICBzdGFydENhcnRvZ3JhcGhpYywKICAgICAgICAgICAgbmV4dENhcnRvZ3JhcGhpYywKICAgICAgICAgICAgbWF4SGVpZ2h0LAogICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgIHZlcnRleE5vcm1hbAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2sodmVydGV4Tm9ybWFsLCBub3JtYWxzQXJyYXksIDApOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHZlcnRleEJvdHRvbSwgYm90dG9tUG9zaXRpb25zQXJyYXksIDApOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHZlcnRleFRvcCwgdG9wUG9zaXRpb25zQXJyYXksIDApOwogICAgICAgIGNhcnRvZ3JhcGhpY3NBcnJheS5wdXNoKHN0YXJ0Q2FydG9ncmFwaGljLmxhdGl0dWRlKTsKICAgICAgICBjYXJ0b2dyYXBoaWNzQXJyYXkucHVzaChzdGFydENhcnRvZ3JhcGhpYy5sb25naXR1ZGUpOwogICAgICAgIGludGVycG9sYXRlU2VnbWVudCgKICAgICAgICAgIHN0YXJ0Q2FydG9ncmFwaGljLAogICAgICAgICAgbmV4dENhcnRvZ3JhcGhpYywKICAgICAgICAgIG1pbkhlaWdodCwKICAgICAgICAgIG1heEhlaWdodCwKICAgICAgICAgIGdyYW51bGFyaXR5LAogICAgICAgICAgYXJjVHlwZSwKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIG5vcm1hbHNBcnJheSwKICAgICAgICAgIGJvdHRvbVBvc2l0aW9uc0FycmF5LAogICAgICAgICAgdG9wUG9zaXRpb25zQXJyYXksCiAgICAgICAgICBjYXJ0b2dyYXBoaWNzQXJyYXkKICAgICAgICApOwogICAgICAgIGZvciAoaSA9IDE7IGkgPCBjYXJ0b2dyYXBoaWNzTGVuZ3RoIC0gMTsgKytpKSB7CiAgICAgICAgICBwcmV2aW91c0JvdHRvbSA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZSh2ZXJ0ZXhCb3R0b20sIHByZXZpb3VzQm90dG9tKTsKICAgICAgICAgIHZlcnRleEJvdHRvbSA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShuZXh0Qm90dG9tLCB2ZXJ0ZXhCb3R0b20pOwogICAgICAgICAgY29uc3QgdmVydGV4Q2FydG9ncmFwaGljID0gY2FydG9ncmFwaGljc1tpXTsKICAgICAgICAgIGdldFBvc2l0aW9uKGVsbGlwc29pZCwgdmVydGV4Q2FydG9ncmFwaGljLCBtYXhIZWlnaHQsIHZlcnRleFRvcCk7CiAgICAgICAgICBnZXRQb3NpdGlvbihlbGxpcHNvaWQsIGNhcnRvZ3JhcGhpY3NbaSArIDFdLCBtaW5IZWlnaHQsIG5leHRCb3R0b20pOwogICAgICAgICAgY29tcHV0ZVZlcnRleE1pdGVyTm9ybWFsKAogICAgICAgICAgICBwcmV2aW91c0JvdHRvbSwKICAgICAgICAgICAgdmVydGV4Qm90dG9tLAogICAgICAgICAgICB2ZXJ0ZXhUb3AsCiAgICAgICAgICAgIG5leHRCb3R0b20sCiAgICAgICAgICAgIHZlcnRleE5vcm1hbAogICAgICAgICAgKTsKICAgICAgICAgIGluZGV4ID0gbm9ybWFsc0FycmF5Lmxlbmd0aDsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHZlcnRleE5vcm1hbCwgbm9ybWFsc0FycmF5LCBpbmRleCk7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayh2ZXJ0ZXhCb3R0b20sIGJvdHRvbVBvc2l0aW9uc0FycmF5LCBpbmRleCk7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayh2ZXJ0ZXhUb3AsIHRvcFBvc2l0aW9uc0FycmF5LCBpbmRleCk7CiAgICAgICAgICBjYXJ0b2dyYXBoaWNzQXJyYXkucHVzaCh2ZXJ0ZXhDYXJ0b2dyYXBoaWMubGF0aXR1ZGUpOwogICAgICAgICAgY2FydG9ncmFwaGljc0FycmF5LnB1c2godmVydGV4Q2FydG9ncmFwaGljLmxvbmdpdHVkZSk7CiAgICAgICAgICBpbnRlcnBvbGF0ZVNlZ21lbnQoCiAgICAgICAgICAgIGNhcnRvZ3JhcGhpY3NbaV0sCiAgICAgICAgICAgIGNhcnRvZ3JhcGhpY3NbaSArIDFdLAogICAgICAgICAgICBtaW5IZWlnaHQsCiAgICAgICAgICAgIG1heEhlaWdodCwKICAgICAgICAgICAgZ3JhbnVsYXJpdHksCiAgICAgICAgICAgIGFyY1R5cGUsCiAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgbm9ybWFsc0FycmF5LAogICAgICAgICAgICBib3R0b21Qb3NpdGlvbnNBcnJheSwKICAgICAgICAgICAgdG9wUG9zaXRpb25zQXJyYXksCiAgICAgICAgICAgIGNhcnRvZ3JhcGhpY3NBcnJheQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZW5kQ2FydG9ncmFwaGljID0gY2FydG9ncmFwaGljc1tjYXJ0b2dyYXBoaWNzTGVuZ3RoIC0gMV07CiAgICAgICAgY29uc3QgcHJlRW5kQ2FydG9ncmFwaGljID0gY2FydG9ncmFwaGljc1tjYXJ0b2dyYXBoaWNzTGVuZ3RoIC0gMl07CiAgICAgICAgdmVydGV4Qm90dG9tID0gZ2V0UG9zaXRpb24oCiAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICBlbmRDYXJ0b2dyYXBoaWMsCiAgICAgICAgICBtaW5IZWlnaHQsCiAgICAgICAgICB2ZXJ0ZXhCb3R0b20KICAgICAgICApOwogICAgICAgIHZlcnRleFRvcCA9IGdldFBvc2l0aW9uKGVsbGlwc29pZCwgZW5kQ2FydG9ncmFwaGljLCBtYXhIZWlnaHQsIHZlcnRleFRvcCk7CiAgICAgICAgaWYgKGxvb3ApIHsKICAgICAgICAgIGNvbnN0IHBvc3RFbmRDYXJ0b2dyYXBoaWMgPSBjYXJ0b2dyYXBoaWNzWzBdOwogICAgICAgICAgcHJldmlvdXNCb3R0b20gPSBnZXRQb3NpdGlvbigKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICBwcmVFbmRDYXJ0b2dyYXBoaWMsCiAgICAgICAgICAgIG1pbkhlaWdodCwKICAgICAgICAgICAgcHJldmlvdXNCb3R0b20KICAgICAgICAgICk7CiAgICAgICAgICBuZXh0Qm90dG9tID0gZ2V0UG9zaXRpb24oCiAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgcG9zdEVuZENhcnRvZ3JhcGhpYywKICAgICAgICAgICAgbWluSGVpZ2h0LAogICAgICAgICAgICBuZXh0Qm90dG9tCiAgICAgICAgICApOwogICAgICAgICAgdmVydGV4Tm9ybWFsID0gY29tcHV0ZVZlcnRleE1pdGVyTm9ybWFsKAogICAgICAgICAgICBwcmV2aW91c0JvdHRvbSwKICAgICAgICAgICAgdmVydGV4Qm90dG9tLAogICAgICAgICAgICB2ZXJ0ZXhUb3AsCiAgICAgICAgICAgIG5leHRCb3R0b20sCiAgICAgICAgICAgIHZlcnRleE5vcm1hbAogICAgICAgICAgKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmVydGV4Tm9ybWFsID0gY29tcHV0ZVJpZ2h0Tm9ybWFsKAogICAgICAgICAgICBwcmVFbmRDYXJ0b2dyYXBoaWMsCiAgICAgICAgICAgIGVuZENhcnRvZ3JhcGhpYywKICAgICAgICAgICAgbWF4SGVpZ2h0LAogICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgIHZlcnRleE5vcm1hbAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgaW5kZXggPSBub3JtYWxzQXJyYXkubGVuZ3RoOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHZlcnRleE5vcm1hbCwgbm9ybWFsc0FycmF5LCBpbmRleCk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2sodmVydGV4Qm90dG9tLCBib3R0b21Qb3NpdGlvbnNBcnJheSwgaW5kZXgpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHZlcnRleFRvcCwgdG9wUG9zaXRpb25zQXJyYXksIGluZGV4KTsKICAgICAgICBjYXJ0b2dyYXBoaWNzQXJyYXkucHVzaChlbmRDYXJ0b2dyYXBoaWMubGF0aXR1ZGUpOwogICAgICAgIGNhcnRvZ3JhcGhpY3NBcnJheS5wdXNoKGVuZENhcnRvZ3JhcGhpYy5sb25naXR1ZGUpOwogICAgICAgIGlmIChsb29wKSB7CiAgICAgICAgICBpbnRlcnBvbGF0ZVNlZ21lbnQoCiAgICAgICAgICAgIGVuZENhcnRvZ3JhcGhpYywKICAgICAgICAgICAgc3RhcnRDYXJ0b2dyYXBoaWMsCiAgICAgICAgICAgIG1pbkhlaWdodCwKICAgICAgICAgICAgbWF4SGVpZ2h0LAogICAgICAgICAgICBncmFudWxhcml0eSwKICAgICAgICAgICAgYXJjVHlwZSwKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICBub3JtYWxzQXJyYXksCiAgICAgICAgICAgIGJvdHRvbVBvc2l0aW9uc0FycmF5LAogICAgICAgICAgICB0b3BQb3NpdGlvbnNBcnJheSwKICAgICAgICAgICAgY2FydG9ncmFwaGljc0FycmF5CiAgICAgICAgICApOwogICAgICAgICAgaW5kZXggPSBub3JtYWxzQXJyYXkubGVuZ3RoOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8IDM7ICsraSkgewogICAgICAgICAgICBub3JtYWxzQXJyYXlbaW5kZXggKyBpXSA9IG5vcm1hbHNBcnJheVtpXTsKICAgICAgICAgICAgYm90dG9tUG9zaXRpb25zQXJyYXlbaW5kZXggKyBpXSA9IGJvdHRvbVBvc2l0aW9uc0FycmF5W2ldOwogICAgICAgICAgICB0b3BQb3NpdGlvbnNBcnJheVtpbmRleCArIGldID0gdG9wUG9zaXRpb25zQXJyYXlbaV07CiAgICAgICAgICB9CiAgICAgICAgICBjYXJ0b2dyYXBoaWNzQXJyYXkucHVzaChzdGFydENhcnRvZ3JhcGhpYy5sYXRpdHVkZSk7CiAgICAgICAgICBjYXJ0b2dyYXBoaWNzQXJyYXkucHVzaChzdGFydENhcnRvZ3JhcGhpYy5sb25naXR1ZGUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZ2VuZXJhdGVHZW9tZXRyeUF0dHJpYnV0ZXMoCiAgICAgICAgICBsb29wLAogICAgICAgICAgcHJvamVjdGlvbiwKICAgICAgICAgIGJvdHRvbVBvc2l0aW9uc0FycmF5LAogICAgICAgICAgdG9wUG9zaXRpb25zQXJyYXksCiAgICAgICAgICBub3JtYWxzQXJyYXksCiAgICAgICAgICBjYXJ0b2dyYXBoaWNzQXJyYXksCiAgICAgICAgICBjb21wdXRlMmRBdHRyaWJ1dGVzCiAgICAgICAgKTsKICAgICAgfTsKICAgICAgbGluZURpcmVjdGlvblNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIG1hdHJpeDNTY3JhdGNoID0gbmV3IE1hdHJpeDNfZGVmYXVsdCgpOwogICAgICBxdWF0ZXJuaW9uU2NyYXRjaDMgPSBuZXcgUXVhdGVybmlvbl9kZWZhdWx0KCk7CiAgICAgIGVuZFBvc0NhcnRvZ3JhcGhpY1NjcmF0Y2ggPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgbm9ybWFsU3RhcnRwb2ludFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIG5vcm1hbEVuZHBvaW50U2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgYWRqdXN0SGVpZ2h0Tm9ybWFsU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgYWRqdXN0SGVpZ2h0T2Zmc2V0U2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgbnVkZ2VEaXJlY3Rpb25TY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzdGFydENhcnRvZ3JhcGhpY1NjcmF0Y2ggPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgZW5kQ2FydG9ncmFwaGljU2NyYXRjaCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBzZWdtZW50U3RhcnRUb3BTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzZWdtZW50RW5kVG9wU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2VnbWVudFN0YXJ0Qm90dG9tU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2VnbWVudEVuZEJvdHRvbVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNlZ21lbnRTdGFydE5vcm1hbFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNlZ21lbnRFbmROb3JtYWxTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBnZXRIZWlnaHRDYXJ0b2dyYXBoaWNzID0gWwogICAgICAgIHN0YXJ0Q2FydG9ncmFwaGljU2NyYXRjaCwKICAgICAgICBlbmRDYXJ0b2dyYXBoaWNTY3JhdGNoCiAgICAgIF07CiAgICAgIGdldEhlaWdodFJlY3RhbmdsZVNjcmF0Y2ggPSBuZXcgUmVjdGFuZ2xlX2RlZmF1bHQoKTsKICAgICAgYWRqdXN0SGVpZ2h0U3RhcnRUb3BTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBhZGp1c3RIZWlnaHRFbmRUb3BTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBhZGp1c3RIZWlnaHRTdGFydEJvdHRvbVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGFkanVzdEhlaWdodEVuZEJvdHRvbVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNlZ21lbnRTdGFydDJEU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2VnbWVudEVuZDJEU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2VnbWVudFN0YXJ0Tm9ybWFsMkRTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzZWdtZW50RW5kTm9ybWFsMkRTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBvZmZzZXRTY3JhdGNoMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc3RhcnRVcFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGVuZFVwU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgcmlnaHRTY3JhdGNoMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc3RhcnRQbGFuZU5vcm1hbFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGVuZFBsYW5lTm9ybWFsU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZW5jb2RlU2NyYXRjaCA9IG5ldyBFbmNvZGVkQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGVuY29kZVNjcmF0Y2gyRCA9IG5ldyBFbmNvZGVkQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGZvcndhcmRPZmZzZXQyRFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHJpZ2h0MkRTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBub3JtYWxOdWRnZVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hCb3VuZGluZ1NwaGVyZXMgPSBbbmV3IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQoKSwgbmV3IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQoKV07CiAgICAgIFJFRkVSRU5DRV9JTkRJQ0VTID0gWwogICAgICAgIDAsCiAgICAgICAgMiwKICAgICAgICAxLAogICAgICAgIDAsCiAgICAgICAgMywKICAgICAgICAyLAogICAgICAgIC8vIHJpZ2h0CiAgICAgICAgMCwKICAgICAgICA3LAogICAgICAgIDMsCiAgICAgICAgMCwKICAgICAgICA0LAogICAgICAgIDcsCiAgICAgICAgLy8gc3RhcnQKICAgICAgICAwLAogICAgICAgIDUsCiAgICAgICAgNCwKICAgICAgICAwLAogICAgICAgIDEsCiAgICAgICAgNSwKICAgICAgICAvLyBib3R0b20KICAgICAgICA1LAogICAgICAgIDcsCiAgICAgICAgNCwKICAgICAgICA1LAogICAgICAgIDYsCiAgICAgICAgNywKICAgICAgICAvLyBsZWZ0CiAgICAgICAgNSwKICAgICAgICAyLAogICAgICAgIDYsCiAgICAgICAgNSwKICAgICAgICAxLAogICAgICAgIDIsCiAgICAgICAgLy8gZW5kCiAgICAgICAgMywKICAgICAgICA2LAogICAgICAgIDIsCiAgICAgICAgMywKICAgICAgICA3LAogICAgICAgIDYKICAgICAgICAvLyB0b3AKICAgICAgXTsKICAgICAgUkVGRVJFTkNFX0lORElDRVNfTEVOR1RIID0gUkVGRVJFTkNFX0lORElDRVMubGVuZ3RoOwogICAgICBHcm91bmRQb2x5bGluZUdlb21ldHJ5Ll9wcm9qZWN0Tm9ybWFsID0gcHJvamVjdE5vcm1hbDsKICAgICAgR3JvdW5kUG9seWxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gR3JvdW5kUG9seWxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUdyb3VuZFBvbHlsaW5lR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlR3JvdW5kUG9seWxpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlR3JvdW5kUG9seWxpbmVHZW9tZXRyeV9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVHcm91bmRQb2x5bGluZUdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVHcm91bmRQb2x5bGluZUdlb21ldHJ5KGdyb3VuZFBvbHlsaW5lR2VvbWV0cnksIG9mZnNldCkgewogICAgcmV0dXJuIEFwcHJveGltYXRlVGVycmFpbkhlaWdodHNfZGVmYXVsdC5pbml0aWFsaXplKCkudGhlbihmdW5jdGlvbigpIHsKICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChvZmZzZXQpKSB7CiAgICAgICAgZ3JvdW5kUG9seWxpbmVHZW9tZXRyeSA9IEdyb3VuZFBvbHlsaW5lR2VvbWV0cnlfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICBncm91bmRQb2x5bGluZUdlb21ldHJ5LAogICAgICAgICAgb2Zmc2V0CiAgICAgICAgKTsKICAgICAgfQogICAgICByZXR1cm4gR3JvdW5kUG9seWxpbmVHZW9tZXRyeV9kZWZhdWx0LmNyZWF0ZUdlb21ldHJ5KGdyb3VuZFBvbHlsaW5lR2VvbWV0cnkpOwogICAgfSk7CiAgfQogIHZhciBjcmVhdGVHcm91bmRQb2x5bGluZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlR3JvdW5kUG9seWxpbmVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlR3JvdW5kUG9seWxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQXBwcm94aW1hdGVUZXJyYWluSGVpZ2h0cygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9Hcm91bmRQb2x5bGluZUdlb21ldHJ5KCk7CiAgICAgIGNyZWF0ZUdyb3VuZFBvbHlsaW5lR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZUdyb3VuZFBvbHlsaW5lR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9QbGFuZUdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gUGxhbmVHZW9tZXRyeShvcHRpb25zKSB7CiAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBvcHRpb25zLnZlcnRleEZvcm1hdCA/PyBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5ERUZBVUxUOwogICAgdGhpcy5fdmVydGV4Rm9ybWF0ID0gdmVydGV4Rm9ybWF0OwogICAgdGhpcy5fd29ya2VyTmFtZSA9ICJjcmVhdGVQbGFuZUdlb21ldHJ5IjsKICB9CiAgdmFyIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQ4LCBzY3JhdGNoT3B0aW9uczE1LCBtaW4sIG1heCwgUGxhbmVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X1BsYW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1BsYW5lR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0JvdW5kaW5nU3BoZXJlKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfQ29tcG9uZW50RGF0YXR5cGUoKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfR2VvbWV0cnkoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlcygpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgaW5pdF9WZXJ0ZXhGb3JtYXQoKTsKICAgICAgUGxhbmVHZW9tZXRyeS5wYWNrZWRMZW5ndGggPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgIFBsYW5lR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2sodmFsdWUuX3ZlcnRleEZvcm1hdCwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDggPSBuZXcgVmVydGV4Rm9ybWF0X2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE9wdGlvbnMxNSA9IHsKICAgICAgICB2ZXJ0ZXhGb3JtYXQ6IHNjcmF0Y2hWZXJ0ZXhGb3JtYXQ4CiAgICAgIH07CiAgICAgIFBsYW5lR2VvbWV0cnkudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICBzY3JhdGNoVmVydGV4Rm9ybWF0OAogICAgICAgICk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBQbGFuZUdlb21ldHJ5KHNjcmF0Y2hPcHRpb25zMTUpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuX3ZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LmNsb25lKHZlcnRleEZvcm1hdCwgcmVzdWx0Ll92ZXJ0ZXhGb3JtYXQpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIG1pbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoLTAuNSwgLTAuNSwgMCk7CiAgICAgIG1heCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoMC41LCAwLjUsIDApOwogICAgICBQbGFuZUdlb21ldHJ5LmNyZWF0ZUdlb21ldHJ5ID0gZnVuY3Rpb24ocGxhbmVHZW9tZXRyeSkgewogICAgICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IHBsYW5lR2VvbWV0cnkuX3ZlcnRleEZvcm1hdDsKICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlc19kZWZhdWx0KCk7CiAgICAgICAgbGV0IGluZGljZXM7CiAgICAgICAgbGV0IHBvc2l0aW9uczsKICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnBvc2l0aW9uKSB7CiAgICAgICAgICBwb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KDQgKiAzKTsKICAgICAgICAgIHBvc2l0aW9uc1swXSA9IG1pbi54OwogICAgICAgICAgcG9zaXRpb25zWzFdID0gbWluLnk7CiAgICAgICAgICBwb3NpdGlvbnNbMl0gPSAwOwogICAgICAgICAgcG9zaXRpb25zWzNdID0gbWF4Lng7CiAgICAgICAgICBwb3NpdGlvbnNbNF0gPSBtaW4ueTsKICAgICAgICAgIHBvc2l0aW9uc1s1XSA9IDA7CiAgICAgICAgICBwb3NpdGlvbnNbNl0gPSBtYXgueDsKICAgICAgICAgIHBvc2l0aW9uc1s3XSA9IG1heC55OwogICAgICAgICAgcG9zaXRpb25zWzhdID0gMDsKICAgICAgICAgIHBvc2l0aW9uc1s5XSA9IG1pbi54OwogICAgICAgICAgcG9zaXRpb25zWzEwXSA9IG1heC55OwogICAgICAgICAgcG9zaXRpb25zWzExXSA9IDA7CiAgICAgICAgICBhdHRyaWJ1dGVzLnBvc2l0aW9uID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICAgIHZhbHVlczogcG9zaXRpb25zCiAgICAgICAgICB9KTsKICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgICAgICAgIGNvbnN0IG5vcm1hbHMgPSBuZXcgRmxvYXQzMkFycmF5KDQgKiAzKTsKICAgICAgICAgICAgbm9ybWFsc1swXSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMV0gPSAwOwogICAgICAgICAgICBub3JtYWxzWzJdID0gMTsKICAgICAgICAgICAgbm9ybWFsc1szXSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbNF0gPSAwOwogICAgICAgICAgICBub3JtYWxzWzVdID0gMTsKICAgICAgICAgICAgbm9ybWFsc1s2XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbN10gPSAwOwogICAgICAgICAgICBub3JtYWxzWzhdID0gMTsKICAgICAgICAgICAgbm9ybWFsc1s5XSA9IDA7CiAgICAgICAgICAgIG5vcm1hbHNbMTBdID0gMDsKICAgICAgICAgICAgbm9ybWFsc1sxMV0gPSAxOwogICAgICAgICAgICBhdHRyaWJ1dGVzLm5vcm1hbCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgICAgIHZhbHVlczogbm9ybWFscwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICAgICAgY29uc3QgdGV4Q29vcmRzID0gbmV3IEZsb2F0MzJBcnJheSg0ICogMik7CiAgICAgICAgICAgIHRleENvb3Jkc1swXSA9IDA7CiAgICAgICAgICAgIHRleENvb3Jkc1sxXSA9IDA7CiAgICAgICAgICAgIHRleENvb3Jkc1syXSA9IDE7CiAgICAgICAgICAgIHRleENvb3Jkc1szXSA9IDA7CiAgICAgICAgICAgIHRleENvb3Jkc1s0XSA9IDE7CiAgICAgICAgICAgIHRleENvb3Jkc1s1XSA9IDE7CiAgICAgICAgICAgIHRleENvb3Jkc1s2XSA9IDA7CiAgICAgICAgICAgIHRleENvb3Jkc1s3XSA9IDE7CiAgICAgICAgICAgIGF0dHJpYnV0ZXMuc3QgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMiwKICAgICAgICAgICAgICB2YWx1ZXM6IHRleENvb3JkcwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICAgICAgICBjb25zdCB0YW5nZW50cyA9IG5ldyBGbG9hdDMyQXJyYXkoNCAqIDMpOwogICAgICAgICAgICB0YW5nZW50c1swXSA9IDE7CiAgICAgICAgICAgIHRhbmdlbnRzWzFdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbMl0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1szXSA9IDE7CiAgICAgICAgICAgIHRhbmdlbnRzWzRdID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbNV0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s2XSA9IDE7CiAgICAgICAgICAgIHRhbmdlbnRzWzddID0gMDsKICAgICAgICAgICAgdGFuZ2VudHNbOF0gPSAwOwogICAgICAgICAgICB0YW5nZW50c1s5XSA9IDE7CiAgICAgICAgICAgIHRhbmdlbnRzWzEwXSA9IDA7CiAgICAgICAgICAgIHRhbmdlbnRzWzExXSA9IDA7CiAgICAgICAgICAgIGF0dHJpYnV0ZXMudGFuZ2VudCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgICAgIHZhbHVlczogdGFuZ2VudHMKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgICAgICBjb25zdCBiaXRhbmdlbnRzID0gbmV3IEZsb2F0MzJBcnJheSg0ICogMyk7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMF0gPSAwOwogICAgICAgICAgICBiaXRhbmdlbnRzWzFdID0gMTsKICAgICAgICAgICAgYml0YW5nZW50c1syXSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbM10gPSAwOwogICAgICAgICAgICBiaXRhbmdlbnRzWzRdID0gMTsKICAgICAgICAgICAgYml0YW5nZW50c1s1XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbNl0gPSAwOwogICAgICAgICAgICBiaXRhbmdlbnRzWzddID0gMTsKICAgICAgICAgICAgYml0YW5nZW50c1s4XSA9IDA7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbOV0gPSAwOwogICAgICAgICAgICBiaXRhbmdlbnRzWzEwXSA9IDE7CiAgICAgICAgICAgIGJpdGFuZ2VudHNbMTFdID0gMDsKICAgICAgICAgICAgYXR0cmlidXRlcy5iaXRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgICB2YWx1ZXM6IGJpdGFuZ2VudHMKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBpbmRpY2VzID0gbmV3IFVpbnQxNkFycmF5KDIgKiAzKTsKICAgICAgICAgIGluZGljZXNbMF0gPSAwOwogICAgICAgICAgaW5kaWNlc1sxXSA9IDE7CiAgICAgICAgICBpbmRpY2VzWzJdID0gMjsKICAgICAgICAgIGluZGljZXNbM10gPSAwOwogICAgICAgICAgaW5kaWNlc1s0XSA9IDI7CiAgICAgICAgICBpbmRpY2VzWzVdID0gMzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgICAgIGF0dHJpYnV0ZXMsCiAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUywKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlOiBuZXcgQm91bmRpbmdTcGhlcmVfZGVmYXVsdChDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywgTWF0aC5zcXJ0KDIpKQogICAgICAgIH0pOwogICAgICB9OwogICAgICBQbGFuZUdlb21ldHJ5X2RlZmF1bHQgPSBQbGFuZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlUGxhbmVHZW9tZXRyeS5qcwogIHZhciBjcmVhdGVQbGFuZUdlb21ldHJ5X2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChjcmVhdGVQbGFuZUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZVBsYW5lR2VvbWV0cnlfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZVBsYW5lR2VvbWV0cnkocGxhbmVHZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgcGxhbmVHZW9tZXRyeSA9IFBsYW5lR2VvbWV0cnlfZGVmYXVsdC51bnBhY2socGxhbmVHZW9tZXRyeSwgb2Zmc2V0KTsKICAgIH0KICAgIHJldHVybiBQbGFuZUdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkocGxhbmVHZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVQbGFuZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlUGxhbmVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlUGxhbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X1BsYW5lR2VvbWV0cnkoKTsKICAgICAgY3JlYXRlUGxhbmVHZW9tZXRyeV9kZWZhdWx0ID0gY3JlYXRlUGxhbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1BsYW5lT3V0bGluZUdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gUGxhbmVPdXRsaW5lR2VvbWV0cnkoKSB7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZVBsYW5lT3V0bGluZUdlb21ldHJ5IjsKICB9CiAgdmFyIG1pbjIsIG1heDIsIFBsYW5lT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfUGxhbmVPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1BsYW5lT3V0bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X0NvbXBvbmVudERhdGF0eXBlKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZXMoKTsKICAgICAgaW5pdF9QcmltaXRpdmVUeXBlKCk7CiAgICAgIFBsYW5lT3V0bGluZUdlb21ldHJ5LnBhY2tlZExlbmd0aCA9IDA7CiAgICAgIFBsYW5lT3V0bGluZUdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXkpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBQbGFuZU91dGxpbmVHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFBsYW5lT3V0bGluZUdlb21ldHJ5KCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIG1pbjIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KC0wLjUsIC0wLjUsIDApOwogICAgICBtYXgyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgwLjUsIDAuNSwgMCk7CiAgICAgIFBsYW5lT3V0bGluZUdlb21ldHJ5LmNyZWF0ZUdlb21ldHJ5ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZXNfZGVmYXVsdCgpOwogICAgICAgIGNvbnN0IGluZGljZXMgPSBuZXcgVWludDE2QXJyYXkoNCAqIDIpOwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkoNCAqIDMpOwogICAgICAgIHBvc2l0aW9uc1swXSA9IG1pbjIueDsKICAgICAgICBwb3NpdGlvbnNbMV0gPSBtaW4yLnk7CiAgICAgICAgcG9zaXRpb25zWzJdID0gbWluMi56OwogICAgICAgIHBvc2l0aW9uc1szXSA9IG1heDIueDsKICAgICAgICBwb3NpdGlvbnNbNF0gPSBtaW4yLnk7CiAgICAgICAgcG9zaXRpb25zWzVdID0gbWluMi56OwogICAgICAgIHBvc2l0aW9uc1s2XSA9IG1heDIueDsKICAgICAgICBwb3NpdGlvbnNbN10gPSBtYXgyLnk7CiAgICAgICAgcG9zaXRpb25zWzhdID0gbWluMi56OwogICAgICAgIHBvc2l0aW9uc1s5XSA9IG1pbjIueDsKICAgICAgICBwb3NpdGlvbnNbMTBdID0gbWF4Mi55OwogICAgICAgIHBvc2l0aW9uc1sxMV0gPSBtaW4yLno7CiAgICAgICAgYXR0cmlidXRlcy5wb3NpdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICB2YWx1ZXM6IHBvc2l0aW9ucwogICAgICAgIH0pOwogICAgICAgIGluZGljZXNbMF0gPSAwOwogICAgICAgIGluZGljZXNbMV0gPSAxOwogICAgICAgIGluZGljZXNbMl0gPSAxOwogICAgICAgIGluZGljZXNbM10gPSAyOwogICAgICAgIGluZGljZXNbNF0gPSAyOwogICAgICAgIGluZGljZXNbNV0gPSAzOwogICAgICAgIGluZGljZXNbNl0gPSAzOwogICAgICAgIGluZGljZXNbN10gPSAwOwogICAgICAgIHJldHVybiBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgICAgICBhdHRyaWJ1dGVzLAogICAgICAgICAgaW5kaWNlcywKICAgICAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5MSU5FUywKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlOiBuZXcgQm91bmRpbmdTcGhlcmVfZGVmYXVsdChDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywgTWF0aC5zcXJ0KDIpKQogICAgICAgIH0pOwogICAgICB9OwogICAgICBQbGFuZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gUGxhbmVPdXRsaW5lR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVQbGFuZU91dGxpbmVHZW9tZXRyeS5qcwogIHZhciBjcmVhdGVQbGFuZU91dGxpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlUGxhbmVPdXRsaW5lR2VvbWV0cnlfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlUGxhbmVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZVBsYW5lT3V0bGluZUdlb21ldHJ5KHBsYW5lR2VvbWV0cnksIG9mZnNldCkgewogICAgaWYgKGRlZmluZWRfZGVmYXVsdChvZmZzZXQpKSB7CiAgICAgIHBsYW5lR2VvbWV0cnkgPSBQbGFuZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjayhwbGFuZUdlb21ldHJ5LCBvZmZzZXQpOwogICAgfQogICAgcmV0dXJuIFBsYW5lT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkocGxhbmVHZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVQbGFuZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X2NyZWF0ZVBsYW5lT3V0bGluZUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVQbGFuZU91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X1BsYW5lT3V0bGluZUdlb21ldHJ5KCk7CiAgICAgIGNyZWF0ZVBsYW5lT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQgPSBjcmVhdGVQbGFuZU91dGxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1N0ZXJlb2dyYXBoaWMuanMKICBmdW5jdGlvbiBTdGVyZW9ncmFwaGljKHBvc2l0aW9uLCB0YW5nZW50UGxhbmUpIHsKICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHRoaXMucG9zaXRpb24pKSB7CiAgICAgIHRoaXMucG9zaXRpb24gPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICB9CiAgICB0aGlzLnRhbmdlbnRQbGFuZSA9IHRhbmdlbnRQbGFuZTsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHRoaXMudGFuZ2VudFBsYW5lKSkgewogICAgICB0aGlzLnRhbmdlbnRQbGFuZSA9IFN0ZXJlb2dyYXBoaWMuTk9SVEhfUE9MRV9UQU5HRU5UX1BMQU5FOwogICAgfQogIH0KICB2YXIgc2NyYXRjaENhcnRvZ3JhcGhpYzUsIHNjcmF0Y2hDYXJ0ZXNpYW4xMCwgc2NyYXRjaFByb2plY3RQb2ludE9udG9QbGFuZVJheTIsIHNjcmF0Y2hQcm9qZWN0UG9pbnRPbnRvUGxhbmVSYXlEaXJlY3Rpb24sIHNjcmF0Y2hQcm9qZWN0UG9pbnRPbnRvUGxhbmVDYXJ0ZXNpYW4zMiwgU3RlcmVvZ3JhcGhpY19kZWZhdWx0OwogIHZhciBpbml0X1N0ZXJlb2dyYXBoaWMgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1N0ZXJlb2dyYXBoaWMuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkVGFuZ2VudFBsYW5lKCk7CiAgICAgIGluaXRfSW50ZXJzZWN0aW9uVGVzdHMoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfUmF5KCk7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKFN0ZXJlb2dyYXBoaWMucHJvdG90eXBlLCB7CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgZWxsaXBzb2lkLgogICAgICAgICAqIEBtZW1iZXJvZiBTdGVyZW9ncmFwaGljLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtFbGxpcHNvaWR9CiAgICAgICAgICovCiAgICAgICAgZWxsaXBzb2lkOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy50YW5nZW50UGxhbmUuZWxsaXBzb2lkOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgeCBjb29yZGluYXRlCiAgICAgICAgICogQG1lbWJlcm9mIFN0ZXJlb2dyYXBoaWMucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKi8KICAgICAgICB4OiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5wb3NpdGlvbi54OwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyB0aGUgeSBjb29yZGluYXRlCiAgICAgICAgICogQG1lbWJlcm9mIFN0ZXJlb2dyYXBoaWMucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKi8KICAgICAgICB5OiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5wb3NpdGlvbi55OwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogQ29tcHV0ZXMgdGhlIGNvbmZvcm1hbCBsYXRpdHVkZSwgb3IgdGhlIGVsbGlwc29pZGFsIGxhdGl0dWRlIHByb2plY3RlZCBvbnRvIGFuIGFyYml0cmFyeSBzcGhlcmUuCiAgICAgICAgICogQG1lbWJlcm9mIFN0ZXJlb2dyYXBoaWMucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKi8KICAgICAgICBjb25mb3JtYWxMYXRpdHVkZTogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgY29uc3QgciA9IENhcnRlc2lhbjJfZGVmYXVsdC5tYWduaXR1ZGUodGhpcy5wb3NpdGlvbik7CiAgICAgICAgICAgIGNvbnN0IGQgPSAyICogdGhpcy5lbGxpcHNvaWQubWF4aW11bVJhZGl1czsKICAgICAgICAgICAgY29uc3Qgc2lnbjMgPSB0aGlzLnRhbmdlbnRQbGFuZS5wbGFuZS5ub3JtYWwuejsKICAgICAgICAgICAgcmV0dXJuIHNpZ24zICogKE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyAtIDIgKiBNYXRoLmF0YW4yKHIsIGQpKTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIENvbXB1dGVzIHRoZSBsb25naXR1ZGUKICAgICAgICAgKiBAbWVtYmVyb2YgU3RlcmVvZ3JhcGhpYy5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqLwogICAgICAgIGxvbmdpdHVkZTogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgbGV0IGxvbmdpdHVkZSA9IE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyArIE1hdGguYXRhbjIodGhpcy55LCB0aGlzLngpOwogICAgICAgICAgICBpZiAobG9uZ2l0dWRlID4gTWF0aC5QSSkgewogICAgICAgICAgICAgIGxvbmdpdHVkZSAtPSBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBsb25naXR1ZGU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzUgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjEwID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBTdGVyZW9ncmFwaGljLnByb3RvdHlwZS5nZXRMYXRpdHVkZSA9IGZ1bmN0aW9uKGVsbGlwc29pZCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGVsbGlwc29pZCkpIHsKICAgICAgICAgIGVsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICAgICAgfQogICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWM1LmxhdGl0dWRlID0gdGhpcy5jb25mb3JtYWxMYXRpdHVkZTsKICAgICAgICBzY3JhdGNoQ2FydG9ncmFwaGljNS5sb25naXR1ZGUgPSB0aGlzLmxvbmdpdHVkZTsKICAgICAgICBzY3JhdGNoQ2FydG9ncmFwaGljNS5oZWlnaHQgPSAwOwogICAgICAgIGNvbnN0IGNhcnRlc2lhbjExID0gdGhpcy5lbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oCiAgICAgICAgICBzY3JhdGNoQ2FydG9ncmFwaGljNSwKICAgICAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4xMAogICAgICAgICk7CiAgICAgICAgZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKGNhcnRlc2lhbjExLCBzY3JhdGNoQ2FydG9ncmFwaGljNSk7CiAgICAgICAgcmV0dXJuIHNjcmF0Y2hDYXJ0b2dyYXBoaWM1LmxhdGl0dWRlOwogICAgICB9OwogICAgICBzY3JhdGNoUHJvamVjdFBvaW50T250b1BsYW5lUmF5MiA9IG5ldyBSYXlfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUHJvamVjdFBvaW50T250b1BsYW5lUmF5RGlyZWN0aW9uID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUHJvamVjdFBvaW50T250b1BsYW5lQ2FydGVzaWFuMzIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIFN0ZXJlb2dyYXBoaWMuZnJvbUNhcnRlc2lhbiA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBjb25zdCBzaWduMyA9IE1hdGhfZGVmYXVsdC5zaWduTm90WmVybyhjYXJ0ZXNpYW4xMS56KTsKICAgICAgICBsZXQgdGFuZ2VudFBsYW5lID0gU3RlcmVvZ3JhcGhpYy5OT1JUSF9QT0xFX1RBTkdFTlRfUExBTkU7CiAgICAgICAgbGV0IG9yaWdpbiA9IFN0ZXJlb2dyYXBoaWMuU09VVEhfUE9MRTsKICAgICAgICBpZiAoc2lnbjMgPCAwKSB7CiAgICAgICAgICB0YW5nZW50UGxhbmUgPSBTdGVyZW9ncmFwaGljLlNPVVRIX1BPTEVfVEFOR0VOVF9QTEFORTsKICAgICAgICAgIG9yaWdpbiA9IFN0ZXJlb2dyYXBoaWMuTk9SVEhfUE9MRTsKICAgICAgICB9CiAgICAgICAgY29uc3QgcmF5ID0gc2NyYXRjaFByb2plY3RQb2ludE9udG9QbGFuZVJheTI7CiAgICAgICAgcmF5Lm9yaWdpbiA9IHRhbmdlbnRQbGFuZS5lbGxpcHNvaWQuc2NhbGVUb0dlb2NlbnRyaWNTdXJmYWNlKAogICAgICAgICAgY2FydGVzaWFuMTEsCiAgICAgICAgICByYXkub3JpZ2luCiAgICAgICAgKTsKICAgICAgICByYXkuZGlyZWN0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KAogICAgICAgICAgcmF5Lm9yaWdpbiwKICAgICAgICAgIG9yaWdpbiwKICAgICAgICAgIHNjcmF0Y2hQcm9qZWN0UG9pbnRPbnRvUGxhbmVSYXlEaXJlY3Rpb24KICAgICAgICApOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUocmF5LmRpcmVjdGlvbiwgcmF5LmRpcmVjdGlvbik7CiAgICAgICAgY29uc3QgaW50ZXJzZWN0aW9uUG9pbnQgPSBJbnRlcnNlY3Rpb25UZXN0c19kZWZhdWx0LnJheVBsYW5lKAogICAgICAgICAgcmF5LAogICAgICAgICAgdGFuZ2VudFBsYW5lLnBsYW5lLAogICAgICAgICAgc2NyYXRjaFByb2plY3RQb2ludE9udG9QbGFuZUNhcnRlc2lhbjMyCiAgICAgICAgKTsKICAgICAgICBjb25zdCB2MyA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChpbnRlcnNlY3Rpb25Qb2ludCwgb3JpZ2luLCBpbnRlcnNlY3Rpb25Qb2ludCk7CiAgICAgICAgY29uc3QgeCA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QodGFuZ2VudFBsYW5lLnhBeGlzLCB2Myk7CiAgICAgICAgY29uc3QgeSA9IHNpZ24zICogQ2FydGVzaWFuM19kZWZhdWx0LmRvdCh0YW5nZW50UGxhbmUueUF4aXMsIHYzKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFN0ZXJlb2dyYXBoaWMobmV3IENhcnRlc2lhbjJfZGVmYXVsdCh4LCB5KSwgdGFuZ2VudFBsYW5lKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnBvc2l0aW9uID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCh4LCB5KTsKICAgICAgICByZXN1bHQudGFuZ2VudFBsYW5lID0gdGFuZ2VudFBsYW5lOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFN0ZXJlb2dyYXBoaWMuZnJvbUNhcnRlc2lhbkFycmF5ID0gZnVuY3Rpb24oY2FydGVzaWFucywgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJjYXJ0ZXNpYW5zIiwgY2FydGVzaWFucyk7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gY2FydGVzaWFucy5sZW5ndGg7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5sZW5ndGggPSBsZW5ndGg7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgIHJlc3VsdFtpXSA9IFN0ZXJlb2dyYXBoaWMuZnJvbUNhcnRlc2lhbihjYXJ0ZXNpYW5zW2ldLCByZXN1bHRbaV0pOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBTdGVyZW9ncmFwaGljLmNsb25lID0gZnVuY3Rpb24oc3RlcmVvZ3JhcGhpYywgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoc3RlcmVvZ3JhcGhpYykpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgU3RlcmVvZ3JhcGhpYygKICAgICAgICAgICAgc3RlcmVvZ3JhcGhpYy5wb3NpdGlvbiwKICAgICAgICAgICAgc3RlcmVvZ3JhcGhpYy50YW5nZW50UGxhbmUKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5wb3NpdGlvbiA9IHN0ZXJlb2dyYXBoaWMucG9zaXRpb247CiAgICAgICAgcmVzdWx0LnRhbmdlbnRQbGFuZSA9IHN0ZXJlb2dyYXBoaWMudGFuZ2VudFBsYW5lOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFN0ZXJlb2dyYXBoaWMuSEFMRl9VTklUX1NQSEVSRSA9IE9iamVjdC5mcmVlemUobmV3IEVsbGlwc29pZF9kZWZhdWx0KDAuNSwgMC41LCAwLjUpKTsKICAgICAgU3RlcmVvZ3JhcGhpYy5OT1JUSF9QT0xFID0gT2JqZWN0LmZyZWV6ZShuZXcgQ2FydGVzaWFuM19kZWZhdWx0KDAsIDAsIDAuNSkpOwogICAgICBTdGVyZW9ncmFwaGljLlNPVVRIX1BPTEUgPSBPYmplY3QuZnJlZXplKG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoMCwgMCwgLTAuNSkpOwogICAgICBTdGVyZW9ncmFwaGljLk5PUlRIX1BPTEVfVEFOR0VOVF9QTEFORSA9IE9iamVjdC5mcmVlemUoCiAgICAgICAgbmV3IEVsbGlwc29pZFRhbmdlbnRQbGFuZV9kZWZhdWx0KAogICAgICAgICAgU3RlcmVvZ3JhcGhpYy5OT1JUSF9QT0xFLAogICAgICAgICAgU3RlcmVvZ3JhcGhpYy5IQUxGX1VOSVRfU1BIRVJFCiAgICAgICAgKQogICAgICApOwogICAgICBTdGVyZW9ncmFwaGljLlNPVVRIX1BPTEVfVEFOR0VOVF9QTEFORSA9IE9iamVjdC5mcmVlemUoCiAgICAgICAgbmV3IEVsbGlwc29pZFRhbmdlbnRQbGFuZV9kZWZhdWx0KAogICAgICAgICAgU3RlcmVvZ3JhcGhpYy5TT1VUSF9QT0xFLAogICAgICAgICAgU3RlcmVvZ3JhcGhpYy5IQUxGX1VOSVRfU1BIRVJFCiAgICAgICAgKQogICAgICApOwogICAgICBTdGVyZW9ncmFwaGljX2RlZmF1bHQgPSBTdGVyZW9ncmFwaGljOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUG9seWdvbkdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gYWRqdXN0UG9zSGVpZ2h0c0Zvck5vcm1hbChwb3NpdGlvbiwgcDEsIHAyLCBlbGxpcHNvaWQpIHsKICAgIGNvbnN0IGNhcnRvMTIgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMocG9zaXRpb24sIHNjcmF0Y2hDYXJ0bzEpOwogICAgY29uc3QgaGVpZ2h0ID0gY2FydG8xMi5oZWlnaHQ7CiAgICBjb25zdCBwMUNhcnRvID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKHAxLCBzY3JhdGNoQ2FydG8yKTsKICAgIHAxQ2FydG8uaGVpZ2h0ID0gaGVpZ2h0OwogICAgZWxsaXBzb2lkLmNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuKHAxQ2FydG8sIHAxKTsKICAgIGNvbnN0IHAyQ2FydG8gPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMocDIsIHNjcmF0Y2hDYXJ0bzIpOwogICAgcDJDYXJ0by5oZWlnaHQgPSBoZWlnaHQgLSAxMDA7CiAgICBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4ocDJDYXJ0bywgcDIpOwogIH0KICBmdW5jdGlvbiBjb21wdXRlQXR0cmlidXRlcyhvcHRpb25zKSB7CiAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBvcHRpb25zLnZlcnRleEZvcm1hdDsKICAgIGNvbnN0IGdlb21ldHJ5ID0gb3B0aW9ucy5nZW9tZXRyeTsKICAgIGNvbnN0IHNoYWRvd1ZvbHVtZSA9IG9wdGlvbnMuc2hhZG93Vm9sdW1lOwogICAgY29uc3QgZmxhdFBvc2l0aW9ucyA9IGdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzOwogICAgY29uc3QgZmxhdFRleGNvb3JkcyA9IGRlZmluZWRfZGVmYXVsdChnZW9tZXRyeS5hdHRyaWJ1dGVzLnN0KSA/IGdlb21ldHJ5LmF0dHJpYnV0ZXMuc3QudmFsdWVzIDogdm9pZCAwOwogICAgbGV0IGxlbmd0aCA9IGZsYXRQb3NpdGlvbnMubGVuZ3RoOwogICAgY29uc3Qgd2FsbCA9IG9wdGlvbnMud2FsbDsKICAgIGNvbnN0IHRvcCA9IG9wdGlvbnMudG9wIHx8IHdhbGw7CiAgICBjb25zdCBib3R0b20gPSBvcHRpb25zLmJvdHRvbSB8fCB3YWxsOwogICAgaWYgKHZlcnRleEZvcm1hdC5zdCB8fCB2ZXJ0ZXhGb3JtYXQubm9ybWFsIHx8IHZlcnRleEZvcm1hdC50YW5nZW50IHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQgfHwgc2hhZG93Vm9sdW1lKSB7CiAgICAgIGNvbnN0IGJvdW5kaW5nUmVjdGFuZ2xlID0gb3B0aW9ucy5ib3VuZGluZ1JlY3RhbmdsZTsKICAgICAgY29uc3Qgcm90YXRpb25BeGlzID0gb3B0aW9ucy5yb3RhdGlvbkF4aXM7CiAgICAgIGNvbnN0IHByb2plY3RUbzJkID0gb3B0aW9ucy5wcm9qZWN0VG8yZDsKICAgICAgY29uc3QgZWxsaXBzb2lkID0gb3B0aW9ucy5lbGxpcHNvaWQ7CiAgICAgIGNvbnN0IHN0Um90YXRpb24gPSBvcHRpb25zLnN0Um90YXRpb247CiAgICAgIGNvbnN0IHBlclBvc2l0aW9uSGVpZ2h0ID0gb3B0aW9ucy5wZXJQb3NpdGlvbkhlaWdodDsKICAgICAgY29uc3Qgb3JpZ2luID0gYXBwZW5kVGV4dHVyZUNvb3JkaW5hdGVzT3JpZ2luOwogICAgICBvcmlnaW4ueCA9IGJvdW5kaW5nUmVjdGFuZ2xlLng7CiAgICAgIG9yaWdpbi55ID0gYm91bmRpbmdSZWN0YW5nbGUueTsKICAgICAgY29uc3QgdGV4dHVyZUNvb3JkaW5hdGVzID0gdmVydGV4Rm9ybWF0LnN0ID8gbmV3IEZsb2F0MzJBcnJheSgyICogKGxlbmd0aCAvIDMpKSA6IHZvaWQgMDsKICAgICAgbGV0IG5vcm1hbHM7CiAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgICAgaWYgKHBlclBvc2l0aW9uSGVpZ2h0ICYmIHRvcCAmJiAhd2FsbCkgewogICAgICAgICAgbm9ybWFscyA9IGdlb21ldHJ5LmF0dHJpYnV0ZXMubm9ybWFsLnZhbHVlczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbm9ybWFscyA9IG5ldyBGbG9hdDMyQXJyYXkobGVuZ3RoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgdGFuZ2VudHMgPSB2ZXJ0ZXhGb3JtYXQudGFuZ2VudCA/IG5ldyBGbG9hdDMyQXJyYXkobGVuZ3RoKSA6IHZvaWQgMDsKICAgICAgY29uc3QgYml0YW5nZW50cyA9IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQgPyBuZXcgRmxvYXQzMkFycmF5KGxlbmd0aCkgOiB2b2lkIDA7CiAgICAgIGNvbnN0IGV4dHJ1ZGVOb3JtYWxzID0gc2hhZG93Vm9sdW1lID8gbmV3IEZsb2F0MzJBcnJheShsZW5ndGgpIDogdm9pZCAwOwogICAgICBsZXQgdGV4dHVyZUNvb3JkSW5kZXggPSAwOwogICAgICBsZXQgYXR0ckluZGV4ID0gMDsKICAgICAgbGV0IG5vcm1hbDIgPSBzY3JhdGNoTm9ybWFsNjsKICAgICAgbGV0IHRhbmdlbnQgPSBzY3JhdGNoVGFuZ2VudDQ7CiAgICAgIGxldCBiaXRhbmdlbnQgPSBzY3JhdGNoQml0YW5nZW50NDsKICAgICAgbGV0IHJlY29tcHV0ZU5vcm1hbCA9IHRydWU7CiAgICAgIGxldCB0ZXh0dXJlTWF0cml4ID0gYXBwZW5kVGV4dHVyZUNvb3JkaW5hdGVzTWF0cml4MzsKICAgICAgbGV0IHRhbmdlbnRSb3RhdGlvbk1hdHJpeCA9IHRhbmdlbnRNYXRyaXhTY3JhdGNoMjsKICAgICAgaWYgKHN0Um90YXRpb24gIT09IDApIHsKICAgICAgICBsZXQgcm90YXRpb24gPSBRdWF0ZXJuaW9uX2RlZmF1bHQuZnJvbUF4aXNBbmdsZSgKICAgICAgICAgIHJvdGF0aW9uQXhpcywKICAgICAgICAgIHN0Um90YXRpb24sCiAgICAgICAgICBhcHBlbmRUZXh0dXJlQ29vcmRpbmF0ZXNRdWF0ZXJuaW9uCiAgICAgICAgKTsKICAgICAgICB0ZXh0dXJlTWF0cml4ID0gTWF0cml4M19kZWZhdWx0LmZyb21RdWF0ZXJuaW9uKHJvdGF0aW9uLCB0ZXh0dXJlTWF0cml4KTsKICAgICAgICByb3RhdGlvbiA9IFF1YXRlcm5pb25fZGVmYXVsdC5mcm9tQXhpc0FuZ2xlKAogICAgICAgICAgcm90YXRpb25BeGlzLAogICAgICAgICAgLXN0Um90YXRpb24sCiAgICAgICAgICBhcHBlbmRUZXh0dXJlQ29vcmRpbmF0ZXNRdWF0ZXJuaW9uCiAgICAgICAgKTsKICAgICAgICB0YW5nZW50Um90YXRpb25NYXRyaXggPSBNYXRyaXgzX2RlZmF1bHQuZnJvbVF1YXRlcm5pb24oCiAgICAgICAgICByb3RhdGlvbiwKICAgICAgICAgIHRhbmdlbnRSb3RhdGlvbk1hdHJpeAogICAgICAgICk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGV4dHVyZU1hdHJpeCA9IE1hdHJpeDNfZGVmYXVsdC5jbG9uZShNYXRyaXgzX2RlZmF1bHQuSURFTlRJVFksIHRleHR1cmVNYXRyaXgpOwogICAgICAgIHRhbmdlbnRSb3RhdGlvbk1hdHJpeCA9IE1hdHJpeDNfZGVmYXVsdC5jbG9uZSgKICAgICAgICAgIE1hdHJpeDNfZGVmYXVsdC5JREVOVElUWSwKICAgICAgICAgIHRhbmdlbnRSb3RhdGlvbk1hdHJpeAogICAgICAgICk7CiAgICAgIH0KICAgICAgbGV0IGJvdHRvbU9mZnNldCA9IDA7CiAgICAgIGxldCBib3R0b21PZmZzZXQyID0gMDsKICAgICAgaWYgKHRvcCAmJiBib3R0b20pIHsKICAgICAgICBib3R0b21PZmZzZXQgPSBsZW5ndGggLyAyOwogICAgICAgIGJvdHRvbU9mZnNldDIgPSBsZW5ndGggLyAzOwogICAgICAgIGxlbmd0aCAvPSAyOwogICAgICB9CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHsKICAgICAgICBjb25zdCBwb3NpdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICBmbGF0UG9zaXRpb25zLAogICAgICAgICAgaSwKICAgICAgICAgIGFwcGVuZFRleHR1cmVDb29yZGluYXRlc0NhcnRlc2lhbjMKICAgICAgICApOwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGZsYXRUZXhjb29yZHMpKSB7CiAgICAgICAgICAgIGxldCBwID0gTWF0cml4M19kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3IoCiAgICAgICAgICAgICAgdGV4dHVyZU1hdHJpeCwKICAgICAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgICAgICBzY3JhdGNoUG9zaXRpb24zCiAgICAgICAgICAgICk7CiAgICAgICAgICAgIHAgPSBlbGxpcHNvaWQuc2NhbGVUb0dlb2RldGljU3VyZmFjZShwLCBwKTsKICAgICAgICAgICAgY29uc3Qgc3QgPSBwcm9qZWN0VG8yZChbcF0sIGFwcGVuZFRleHR1cmVDb29yZGluYXRlc0NhcnRlc2lhbjIpWzBdOwogICAgICAgICAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQuc3VidHJhY3Qoc3QsIG9yaWdpbiwgc3QpOwogICAgICAgICAgICBjb25zdCBzdHggPSBNYXRoX2RlZmF1bHQuY2xhbXAoc3QueCAvIGJvdW5kaW5nUmVjdGFuZ2xlLndpZHRoLCAwLCAxKTsKICAgICAgICAgICAgY29uc3Qgc3R5ID0gTWF0aF9kZWZhdWx0LmNsYW1wKHN0LnkgLyBib3VuZGluZ1JlY3RhbmdsZS5oZWlnaHQsIDAsIDEpOwogICAgICAgICAgICBpZiAoYm90dG9tKSB7CiAgICAgICAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW3RleHR1cmVDb29yZEluZGV4ICsgYm90dG9tT2Zmc2V0Ml0gPSBzdHg7CiAgICAgICAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW3RleHR1cmVDb29yZEluZGV4ICsgMSArIGJvdHRvbU9mZnNldDJdID0gc3R5OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh0b3ApIHsKICAgICAgICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXNbdGV4dHVyZUNvb3JkSW5kZXhdID0gc3R4OwogICAgICAgICAgICAgIHRleHR1cmVDb29yZGluYXRlc1t0ZXh0dXJlQ29vcmRJbmRleCArIDFdID0gc3R5OwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRleHR1cmVDb29yZEluZGV4ICs9IDI7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsIHx8IHZlcnRleEZvcm1hdC50YW5nZW50IHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQgfHwgc2hhZG93Vm9sdW1lKSB7CiAgICAgICAgICBjb25zdCBhdHRySW5kZXgxID0gYXR0ckluZGV4ICsgMTsKICAgICAgICAgIGNvbnN0IGF0dHJJbmRleDIgPSBhdHRySW5kZXggKyAyOwogICAgICAgICAgaWYgKHdhbGwpIHsKICAgICAgICAgICAgaWYgKGkgKyAzIDwgbGVuZ3RoKSB7CiAgICAgICAgICAgICAgY29uc3QgcDEgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KGZsYXRQb3NpdGlvbnMsIGkgKyAzLCBwMVNjcmF0Y2gzKTsKICAgICAgICAgICAgICBpZiAocmVjb21wdXRlTm9ybWFsKSB7CiAgICAgICAgICAgICAgICBjb25zdCBwMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICAgICAgICAgIGZsYXRQb3NpdGlvbnMsCiAgICAgICAgICAgICAgICAgIGkgKyBsZW5ndGgsCiAgICAgICAgICAgICAgICAgIHAyU2NyYXRjaDMKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICBpZiAocGVyUG9zaXRpb25IZWlnaHQpIHsKICAgICAgICAgICAgICAgICAgYWRqdXN0UG9zSGVpZ2h0c0Zvck5vcm1hbChwb3NpdGlvbiwgcDEsIHAyLCBlbGxpcHNvaWQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHAxLCBwb3NpdGlvbiwgcDEpOwogICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHAyLCBwb3NpdGlvbiwgcDIpOwogICAgICAgICAgICAgICAgbm9ybWFsMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhwMiwgcDEsIG5vcm1hbDIpLAogICAgICAgICAgICAgICAgICBub3JtYWwyCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgcmVjb21wdXRlTm9ybWFsID0gZmFsc2U7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihwMSwgcG9zaXRpb24sIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTApKSB7CiAgICAgICAgICAgICAgICByZWNvbXB1dGVOb3JtYWwgPSB0cnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQgfHwgdmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgICAgICAgIGJpdGFuZ2VudCA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwocG9zaXRpb24sIGJpdGFuZ2VudCk7CiAgICAgICAgICAgICAgaWYgKHZlcnRleEZvcm1hdC50YW5nZW50KSB7CiAgICAgICAgICAgICAgICB0YW5nZW50ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKGJpdGFuZ2VudCwgbm9ybWFsMiwgdGFuZ2VudCksCiAgICAgICAgICAgICAgICAgIHRhbmdlbnQKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBub3JtYWwyID0gZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbChwb3NpdGlvbiwgbm9ybWFsMik7CiAgICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCB8fCB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgICAgICAgaWYgKHBlclBvc2l0aW9uSGVpZ2h0KSB7CiAgICAgICAgICAgICAgICBzY3JhdGNoUGVyUG9zTm9ybWFsID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgICAgICAgICAgbm9ybWFscywKICAgICAgICAgICAgICAgICAgYXR0ckluZGV4LAogICAgICAgICAgICAgICAgICBzY3JhdGNoUGVyUG9zTm9ybWFsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgc2NyYXRjaFBlclBvc1RhbmdlbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoCiAgICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5VTklUX1osCiAgICAgICAgICAgICAgICAgIHNjcmF0Y2hQZXJQb3NOb3JtYWwsCiAgICAgICAgICAgICAgICAgIHNjcmF0Y2hQZXJQb3NUYW5nZW50CiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgc2NyYXRjaFBlclBvc1RhbmdlbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgICAgICAgICBNYXRyaXgzX2RlZmF1bHQubXVsdGlwbHlCeVZlY3RvcigKICAgICAgICAgICAgICAgICAgICB0YW5nZW50Um90YXRpb25NYXRyaXgsCiAgICAgICAgICAgICAgICAgICAgc2NyYXRjaFBlclBvc1RhbmdlbnQsCiAgICAgICAgICAgICAgICAgICAgc2NyYXRjaFBlclBvc1RhbmdlbnQKICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgc2NyYXRjaFBlclBvc1RhbmdlbnQKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgICAgICAgICAgICBzY3JhdGNoUGVyUG9zQml0YW5nZW50ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoCiAgICAgICAgICAgICAgICAgICAgICBzY3JhdGNoUGVyUG9zTm9ybWFsLAogICAgICAgICAgICAgICAgICAgICAgc2NyYXRjaFBlclBvc1RhbmdlbnQsCiAgICAgICAgICAgICAgICAgICAgICBzY3JhdGNoUGVyUG9zQml0YW5nZW50CiAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICBzY3JhdGNoUGVyUG9zQml0YW5nZW50CiAgICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRhbmdlbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWiwgbm9ybWFsMiwgdGFuZ2VudCk7CiAgICAgICAgICAgICAgdGFuZ2VudCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgICAgICAgICAgICBNYXRyaXgzX2RlZmF1bHQubXVsdGlwbHlCeVZlY3Rvcih0YW5nZW50Um90YXRpb25NYXRyaXgsIHRhbmdlbnQsIHRhbmdlbnQpLAogICAgICAgICAgICAgICAgdGFuZ2VudAogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudCA9IENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jcm9zcyhub3JtYWwyLCB0YW5nZW50LCBiaXRhbmdlbnQpLAogICAgICAgICAgICAgICAgICBiaXRhbmdlbnQKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICAgICAgICBpZiAob3B0aW9ucy53YWxsKSB7CiAgICAgICAgICAgICAgbm9ybWFsc1thdHRySW5kZXggKyBib3R0b21PZmZzZXRdID0gbm9ybWFsMi54OwogICAgICAgICAgICAgIG5vcm1hbHNbYXR0ckluZGV4MSArIGJvdHRvbU9mZnNldF0gPSBub3JtYWwyLnk7CiAgICAgICAgICAgICAgbm9ybWFsc1thdHRySW5kZXgyICsgYm90dG9tT2Zmc2V0XSA9IG5vcm1hbDIuejsKICAgICAgICAgICAgfSBlbHNlIGlmIChib3R0b20pIHsKICAgICAgICAgICAgICBub3JtYWxzW2F0dHJJbmRleCArIGJvdHRvbU9mZnNldF0gPSAtbm9ybWFsMi54OwogICAgICAgICAgICAgIG5vcm1hbHNbYXR0ckluZGV4MSArIGJvdHRvbU9mZnNldF0gPSAtbm9ybWFsMi55OwogICAgICAgICAgICAgIG5vcm1hbHNbYXR0ckluZGV4MiArIGJvdHRvbU9mZnNldF0gPSAtbm9ybWFsMi56OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh0b3AgJiYgIXBlclBvc2l0aW9uSGVpZ2h0IHx8IHdhbGwpIHsKICAgICAgICAgICAgICBub3JtYWxzW2F0dHJJbmRleF0gPSBub3JtYWwyLng7CiAgICAgICAgICAgICAgbm9ybWFsc1thdHRySW5kZXgxXSA9IG5vcm1hbDIueTsKICAgICAgICAgICAgICBub3JtYWxzW2F0dHJJbmRleDJdID0gbm9ybWFsMi56OwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoc2hhZG93Vm9sdW1lKSB7CiAgICAgICAgICAgIGlmICh3YWxsKSB7CiAgICAgICAgICAgICAgbm9ybWFsMiA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwocG9zaXRpb24sIG5vcm1hbDIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGV4dHJ1ZGVOb3JtYWxzW2F0dHJJbmRleCArIGJvdHRvbU9mZnNldF0gPSAtbm9ybWFsMi54OwogICAgICAgICAgICBleHRydWRlTm9ybWFsc1thdHRySW5kZXgxICsgYm90dG9tT2Zmc2V0XSA9IC1ub3JtYWwyLnk7CiAgICAgICAgICAgIGV4dHJ1ZGVOb3JtYWxzW2F0dHJJbmRleDIgKyBib3R0b21PZmZzZXRdID0gLW5vcm1hbDIuejsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICAgICAgICBpZiAob3B0aW9ucy53YWxsKSB7CiAgICAgICAgICAgICAgdGFuZ2VudHNbYXR0ckluZGV4ICsgYm90dG9tT2Zmc2V0XSA9IHRhbmdlbnQueDsKICAgICAgICAgICAgICB0YW5nZW50c1thdHRySW5kZXgxICsgYm90dG9tT2Zmc2V0XSA9IHRhbmdlbnQueTsKICAgICAgICAgICAgICB0YW5nZW50c1thdHRySW5kZXgyICsgYm90dG9tT2Zmc2V0XSA9IHRhbmdlbnQuejsKICAgICAgICAgICAgfSBlbHNlIGlmIChib3R0b20pIHsKICAgICAgICAgICAgICB0YW5nZW50c1thdHRySW5kZXggKyBib3R0b21PZmZzZXRdID0gLXRhbmdlbnQueDsKICAgICAgICAgICAgICB0YW5nZW50c1thdHRySW5kZXgxICsgYm90dG9tT2Zmc2V0XSA9IC10YW5nZW50Lnk7CiAgICAgICAgICAgICAgdGFuZ2VudHNbYXR0ckluZGV4MiArIGJvdHRvbU9mZnNldF0gPSAtdGFuZ2VudC56OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh0b3ApIHsKICAgICAgICAgICAgICBpZiAocGVyUG9zaXRpb25IZWlnaHQpIHsKICAgICAgICAgICAgICAgIHRhbmdlbnRzW2F0dHJJbmRleF0gPSBzY3JhdGNoUGVyUG9zVGFuZ2VudC54OwogICAgICAgICAgICAgICAgdGFuZ2VudHNbYXR0ckluZGV4MV0gPSBzY3JhdGNoUGVyUG9zVGFuZ2VudC55OwogICAgICAgICAgICAgICAgdGFuZ2VudHNbYXR0ckluZGV4Ml0gPSBzY3JhdGNoUGVyUG9zVGFuZ2VudC56OwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0YW5nZW50c1thdHRySW5kZXhdID0gdGFuZ2VudC54OwogICAgICAgICAgICAgICAgdGFuZ2VudHNbYXR0ckluZGV4MV0gPSB0YW5nZW50Lnk7CiAgICAgICAgICAgICAgICB0YW5nZW50c1thdHRySW5kZXgyXSA9IHRhbmdlbnQuejsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgICAgIGlmIChib3R0b20pIHsKICAgICAgICAgICAgICBiaXRhbmdlbnRzW2F0dHJJbmRleCArIGJvdHRvbU9mZnNldF0gPSBiaXRhbmdlbnQueDsKICAgICAgICAgICAgICBiaXRhbmdlbnRzW2F0dHJJbmRleDEgKyBib3R0b21PZmZzZXRdID0gYml0YW5nZW50Lnk7CiAgICAgICAgICAgICAgYml0YW5nZW50c1thdHRySW5kZXgyICsgYm90dG9tT2Zmc2V0XSA9IGJpdGFuZ2VudC56OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh0b3ApIHsKICAgICAgICAgICAgICBpZiAocGVyUG9zaXRpb25IZWlnaHQpIHsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYXR0ckluZGV4XSA9IHNjcmF0Y2hQZXJQb3NCaXRhbmdlbnQueDsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYXR0ckluZGV4MV0gPSBzY3JhdGNoUGVyUG9zQml0YW5nZW50Lnk7CiAgICAgICAgICAgICAgICBiaXRhbmdlbnRzW2F0dHJJbmRleDJdID0gc2NyYXRjaFBlclBvc0JpdGFuZ2VudC56OwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBiaXRhbmdlbnRzW2F0dHJJbmRleF0gPSBiaXRhbmdlbnQueDsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYXR0ckluZGV4MV0gPSBiaXRhbmdlbnQueTsKICAgICAgICAgICAgICAgIGJpdGFuZ2VudHNbYXR0ckluZGV4Ml0gPSBiaXRhbmdlbnQuejsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGF0dHJJbmRleCArPSAzOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAodmVydGV4Rm9ybWF0LnN0ICYmICFkZWZpbmVkX2RlZmF1bHQoZmxhdFRleGNvb3JkcykpIHsKICAgICAgICBnZW9tZXRyeS5hdHRyaWJ1dGVzLnN0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAyLAogICAgICAgICAgdmFsdWVzOiB0ZXh0dXJlQ29vcmRpbmF0ZXMKICAgICAgICB9KTsKICAgICAgfQogICAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMubm9ybWFsID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgdmFsdWVzOiBub3JtYWxzCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgaWYgKHZlcnRleEZvcm1hdC50YW5nZW50KSB7CiAgICAgICAgZ2VvbWV0cnkuYXR0cmlidXRlcy50YW5nZW50ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgdmFsdWVzOiB0YW5nZW50cwogICAgICAgIH0pOwogICAgICB9CiAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgZ2VvbWV0cnkuYXR0cmlidXRlcy5iaXRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICB2YWx1ZXM6IGJpdGFuZ2VudHMKICAgICAgICB9KTsKICAgICAgfQogICAgICBpZiAoc2hhZG93Vm9sdW1lKSB7CiAgICAgICAgZ2VvbWV0cnkuYXR0cmlidXRlcy5leHRydWRlRGlyZWN0aW9uID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgdmFsdWVzOiBleHRydWRlTm9ybWFscwogICAgICAgIH0pOwogICAgICB9CiAgICB9CiAgICBpZiAob3B0aW9ucy5leHRydWRlICYmIGRlZmluZWRfZGVmYXVsdChvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSkpIHsKICAgICAgY29uc3Qgc2l6ZSA9IGZsYXRQb3NpdGlvbnMubGVuZ3RoIC8gMzsKICAgICAgbGV0IG9mZnNldEF0dHJpYnV0ZSA9IG5ldyBVaW50OEFycmF5KHNpemUpOwogICAgICBpZiAob3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuVE9QKSB7CiAgICAgICAgaWYgKHRvcCAmJiBib3R0b20gfHwgd2FsbCkgewogICAgICAgICAgb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlLmZpbGwoMSwgMCwgc2l6ZSAvIDIpOwogICAgICAgIH0gZWxzZSBpZiAodG9wKSB7CiAgICAgICAgICBvZmZzZXRBdHRyaWJ1dGUgPSBvZmZzZXRBdHRyaWJ1dGUuZmlsbCgxKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3Qgb2Zmc2V0VmFsdWUgPSBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5OT05FID8gMCA6IDE7CiAgICAgICAgb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlLmZpbGwob2Zmc2V0VmFsdWUpOwogICAgICB9CiAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMuYXBwbHlPZmZzZXQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuVU5TSUdORURfQllURSwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAxLAogICAgICAgIHZhbHVlczogb2Zmc2V0QXR0cmlidXRlCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIGdlb21ldHJ5OwogIH0KICBmdW5jdGlvbiBjcmVhdGVHZW9tZXRyeUZyb21Qb3NpdGlvbnNFeHRydWRlZChlbGxpcHNvaWQsIHBvbHlnb24yLCB0ZXh0dXJlQ29vcmRpbmF0ZXMsIGdyYW51bGFyaXR5LCBoaWVyYXJjaHksIHBlclBvc2l0aW9uSGVpZ2h0LCBjbG9zZVRvcCwgY2xvc2VCb3R0b20sIHZlcnRleEZvcm1hdCwgYXJjVHlwZSkgewogICAgY29uc3QgZ2VvcyA9IHsKICAgICAgd2FsbHM6IFtdCiAgICB9OwogICAgbGV0IGk7CiAgICBpZiAoY2xvc2VUb3AgfHwgY2xvc2VCb3R0b20pIHsKICAgICAgY29uc3QgdG9wR2VvID0gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNyZWF0ZUdlb21ldHJ5RnJvbVBvc2l0aW9ucygKICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgcG9seWdvbjIsCiAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzLAogICAgICAgIGdyYW51bGFyaXR5LAogICAgICAgIHBlclBvc2l0aW9uSGVpZ2h0LAogICAgICAgIHZlcnRleEZvcm1hdCwKICAgICAgICBhcmNUeXBlCiAgICAgICk7CiAgICAgIGNvbnN0IGVkZ2VQb2ludHMgPSB0b3BHZW8uYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXM7CiAgICAgIGNvbnN0IGluZGljZXMgPSB0b3BHZW8uaW5kaWNlczsKICAgICAgbGV0IG51bVBvc2l0aW9uczsKICAgICAgbGV0IG5ld0luZGljZXM7CiAgICAgIGlmIChjbG9zZVRvcCAmJiBjbG9zZUJvdHRvbSkgewogICAgICAgIGNvbnN0IHRvcEJvdHRvbVBvc2l0aW9ucyA9IGVkZ2VQb2ludHMuY29uY2F0KGVkZ2VQb2ludHMpOwogICAgICAgIG51bVBvc2l0aW9ucyA9IHRvcEJvdHRvbVBvc2l0aW9ucy5sZW5ndGggLyAzOwogICAgICAgIG5ld0luZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgICAgIG51bVBvc2l0aW9ucywKICAgICAgICAgIGluZGljZXMubGVuZ3RoICogMgogICAgICAgICk7CiAgICAgICAgbmV3SW5kaWNlcy5zZXQoaW5kaWNlcyk7CiAgICAgICAgY29uc3QgaWxlbmd0aCA9IGluZGljZXMubGVuZ3RoOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IG51bVBvc2l0aW9ucyAvIDI7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGlsZW5ndGg7IGkgKz0gMykgewogICAgICAgICAgY29uc3QgaTAgPSBuZXdJbmRpY2VzW2ldICsgbGVuZ3RoOwogICAgICAgICAgY29uc3QgaTEgPSBuZXdJbmRpY2VzW2kgKyAxXSArIGxlbmd0aDsKICAgICAgICAgIGNvbnN0IGkyID0gbmV3SW5kaWNlc1tpICsgMl0gKyBsZW5ndGg7CiAgICAgICAgICBuZXdJbmRpY2VzW2kgKyBpbGVuZ3RoXSA9IGkyOwogICAgICAgICAgbmV3SW5kaWNlc1tpICsgMSArIGlsZW5ndGhdID0gaTE7CiAgICAgICAgICBuZXdJbmRpY2VzW2kgKyAyICsgaWxlbmd0aF0gPSBpMDsKICAgICAgICB9CiAgICAgICAgdG9wR2VvLmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzID0gdG9wQm90dG9tUG9zaXRpb25zOwogICAgICAgIGlmIChwZXJQb3NpdGlvbkhlaWdodCAmJiB2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgICAgICBjb25zdCBub3JtYWxzID0gdG9wR2VvLmF0dHJpYnV0ZXMubm9ybWFsLnZhbHVlczsKICAgICAgICAgIHRvcEdlby5hdHRyaWJ1dGVzLm5vcm1hbC52YWx1ZXMgPSBuZXcgRmxvYXQzMkFycmF5KAogICAgICAgICAgICB0b3BCb3R0b21Qb3NpdGlvbnMubGVuZ3RoCiAgICAgICAgICApOwogICAgICAgICAgdG9wR2VvLmF0dHJpYnV0ZXMubm9ybWFsLnZhbHVlcy5zZXQobm9ybWFscyk7CiAgICAgICAgfQogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QgJiYgZGVmaW5lZF9kZWZhdWx0KHRleHR1cmVDb29yZGluYXRlcykpIHsKICAgICAgICAgIGNvbnN0IHRleGNvb3JkcyA9IHRvcEdlby5hdHRyaWJ1dGVzLnN0LnZhbHVlczsKICAgICAgICAgIHRvcEdlby5hdHRyaWJ1dGVzLnN0LnZhbHVlcyA9IG5ldyBGbG9hdDMyQXJyYXkobnVtUG9zaXRpb25zICogMik7CiAgICAgICAgICB0b3BHZW8uYXR0cmlidXRlcy5zdC52YWx1ZXMgPSB0ZXhjb29yZHMuY29uY2F0KHRleGNvb3Jkcyk7CiAgICAgICAgfQogICAgICAgIHRvcEdlby5pbmRpY2VzID0gbmV3SW5kaWNlczsKICAgICAgfSBlbHNlIGlmIChjbG9zZUJvdHRvbSkgewogICAgICAgIG51bVBvc2l0aW9ucyA9IGVkZ2VQb2ludHMubGVuZ3RoIC8gMzsKICAgICAgICBuZXdJbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkobnVtUG9zaXRpb25zLCBpbmRpY2VzLmxlbmd0aCk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpICs9IDMpIHsKICAgICAgICAgIG5ld0luZGljZXNbaV0gPSBpbmRpY2VzW2kgKyAyXTsKICAgICAgICAgIG5ld0luZGljZXNbaSArIDFdID0gaW5kaWNlc1tpICsgMV07CiAgICAgICAgICBuZXdJbmRpY2VzW2kgKyAyXSA9IGluZGljZXNbaV07CiAgICAgICAgfQogICAgICAgIHRvcEdlby5pbmRpY2VzID0gbmV3SW5kaWNlczsKICAgICAgfQogICAgICBnZW9zLnRvcEFuZEJvdHRvbSA9IG5ldyBHZW9tZXRyeUluc3RhbmNlX2RlZmF1bHQoewogICAgICAgIGdlb21ldHJ5OiB0b3BHZW8KICAgICAgfSk7CiAgICB9CiAgICBsZXQgb3V0ZXJSaW5nID0gaGllcmFyY2h5Lm91dGVyUmluZzsKICAgIGNvbnN0IHRhbmdlbnRQbGFuZSA9IEVsbGlwc29pZFRhbmdlbnRQbGFuZV9kZWZhdWx0LmZyb21Qb2ludHMob3V0ZXJSaW5nLCBlbGxpcHNvaWQpOwogICAgbGV0IHBvc2l0aW9uczJEID0gdGFuZ2VudFBsYW5lLnByb2plY3RQb2ludHNPbnRvUGxhbmUoCiAgICAgIG91dGVyUmluZywKICAgICAgY3JlYXRlR2VvbWV0cnlGcm9tUG9zaXRpb25zRXh0cnVkZWRQb3NpdGlvbnMKICAgICk7CiAgICBsZXQgd2luZGluZ09yZGVyID0gUG9seWdvblBpcGVsaW5lX2RlZmF1bHQuY29tcHV0ZVdpbmRpbmdPcmRlcjJEKHBvc2l0aW9uczJEKTsKICAgIGlmICh3aW5kaW5nT3JkZXIgPT09IFdpbmRpbmdPcmRlcl9kZWZhdWx0LkNMT0NLV0lTRSkgewogICAgICBvdXRlclJpbmcgPSBvdXRlclJpbmcuc2xpY2UoKS5yZXZlcnNlKCk7CiAgICB9CiAgICBsZXQgd2FsbEdlbyA9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlV2FsbEdlb21ldHJ5KAogICAgICBvdXRlclJpbmcsCiAgICAgIHRleHR1cmVDb29yZGluYXRlcywKICAgICAgZWxsaXBzb2lkLAogICAgICBncmFudWxhcml0eSwKICAgICAgcGVyUG9zaXRpb25IZWlnaHQsCiAgICAgIGFyY1R5cGUKICAgICk7CiAgICBnZW9zLndhbGxzLnB1c2goCiAgICAgIG5ldyBHZW9tZXRyeUluc3RhbmNlX2RlZmF1bHQoewogICAgICAgIGdlb21ldHJ5OiB3YWxsR2VvCiAgICAgIH0pCiAgICApOwogICAgY29uc3QgaG9sZXMgPSBoaWVyYXJjaHkuaG9sZXM7CiAgICBmb3IgKGkgPSAwOyBpIDwgaG9sZXMubGVuZ3RoOyBpKyspIHsKICAgICAgbGV0IGhvbGUgPSBob2xlc1tpXTsKICAgICAgcG9zaXRpb25zMkQgPSB0YW5nZW50UGxhbmUucHJvamVjdFBvaW50c09udG9QbGFuZSgKICAgICAgICBob2xlLAogICAgICAgIGNyZWF0ZUdlb21ldHJ5RnJvbVBvc2l0aW9uc0V4dHJ1ZGVkUG9zaXRpb25zCiAgICAgICk7CiAgICAgIHdpbmRpbmdPcmRlciA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LmNvbXB1dGVXaW5kaW5nT3JkZXIyRChwb3NpdGlvbnMyRCk7CiAgICAgIGlmICh3aW5kaW5nT3JkZXIgPT09IFdpbmRpbmdPcmRlcl9kZWZhdWx0LkNPVU5URVJfQ0xPQ0tXSVNFKSB7CiAgICAgICAgaG9sZSA9IGhvbGUuc2xpY2UoKS5yZXZlcnNlKCk7CiAgICAgIH0KICAgICAgd2FsbEdlbyA9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlV2FsbEdlb21ldHJ5KAogICAgICAgIGhvbGUsCiAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzLAogICAgICAgIGVsbGlwc29pZCwKICAgICAgICBncmFudWxhcml0eSwKICAgICAgICBwZXJQb3NpdGlvbkhlaWdodCwKICAgICAgICBhcmNUeXBlCiAgICAgICk7CiAgICAgIGdlb3Mud2FsbHMucHVzaCgKICAgICAgICBuZXcgR2VvbWV0cnlJbnN0YW5jZV9kZWZhdWx0KHsKICAgICAgICAgIGdlb21ldHJ5OiB3YWxsR2VvCiAgICAgICAgfSkKICAgICAgKTsKICAgIH0KICAgIHJldHVybiBnZW9zOwogIH0KICBmdW5jdGlvbiBQb2x5Z29uR2VvbWV0cnkob3B0aW9ucykgewogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJvcHRpb25zIiwgb3B0aW9ucyk7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm9wdGlvbnMucG9seWdvbkhpZXJhcmNoeSIsIG9wdGlvbnMucG9seWdvbkhpZXJhcmNoeSk7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMucGVyUG9zaXRpb25IZWlnaHQpICYmIG9wdGlvbnMucGVyUG9zaXRpb25IZWlnaHQgJiYgZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMuaGVpZ2h0KSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAiQ2Fubm90IHVzZSBib3RoIG9wdGlvbnMucGVyUG9zaXRpb25IZWlnaHQgYW5kIG9wdGlvbnMuaGVpZ2h0IgogICAgICApOwogICAgfQogICAgaWYgKGRlZmluZWRfZGVmYXVsdChvcHRpb25zLmFyY1R5cGUpICYmIG9wdGlvbnMuYXJjVHlwZSAhPT0gQXJjVHlwZV9kZWZhdWx0LkdFT0RFU0lDICYmIG9wdGlvbnMuYXJjVHlwZSAhPT0gQXJjVHlwZV9kZWZhdWx0LlJIVU1CKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICJJbnZhbGlkIGFyY1R5cGUuIFZhbGlkIG9wdGlvbnMgYXJlIEFyY1R5cGUuR0VPREVTSUMgYW5kIEFyY1R5cGUuUkhVTUIuIgogICAgICApOwogICAgfQogICAgY29uc3QgcG9seWdvbkhpZXJhcmNoeSA9IG9wdGlvbnMucG9seWdvbkhpZXJhcmNoeTsKICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IG9wdGlvbnMudmVydGV4Rm9ybWF0ID8/IFZlcnRleEZvcm1hdF9kZWZhdWx0LkRFRkFVTFQ7CiAgICBjb25zdCBlbGxpcHNvaWQgPSBvcHRpb25zLmVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBvcHRpb25zLmdyYW51bGFyaXR5ID8/IE1hdGhfZGVmYXVsdC5SQURJQU5TX1BFUl9ERUdSRUU7CiAgICBjb25zdCBzdFJvdGF0aW9uID0gb3B0aW9ucy5zdFJvdGF0aW9uID8/IDA7CiAgICBjb25zdCB0ZXh0dXJlQ29vcmRpbmF0ZXMgPSBvcHRpb25zLnRleHR1cmVDb29yZGluYXRlczsKICAgIGNvbnN0IHBlclBvc2l0aW9uSGVpZ2h0ID0gb3B0aW9ucy5wZXJQb3NpdGlvbkhlaWdodCA/PyBmYWxzZTsKICAgIGNvbnN0IHBlclBvc2l0aW9uSGVpZ2h0RXh0cnVkZSA9IHBlclBvc2l0aW9uSGVpZ2h0ICYmIGRlZmluZWRfZGVmYXVsdChvcHRpb25zLmV4dHJ1ZGVkSGVpZ2h0KTsKICAgIGxldCBoZWlnaHQgPSBvcHRpb25zLmhlaWdodCA/PyAwOwogICAgbGV0IGV4dHJ1ZGVkSGVpZ2h0ID0gb3B0aW9ucy5leHRydWRlZEhlaWdodCA/PyBoZWlnaHQ7CiAgICBpZiAoIXBlclBvc2l0aW9uSGVpZ2h0RXh0cnVkZSkgewogICAgICBjb25zdCBoID0gTWF0aC5tYXgoaGVpZ2h0LCBleHRydWRlZEhlaWdodCk7CiAgICAgIGV4dHJ1ZGVkSGVpZ2h0ID0gTWF0aC5taW4oaGVpZ2h0LCBleHRydWRlZEhlaWdodCk7CiAgICAgIGhlaWdodCA9IGg7CiAgICB9CiAgICB0aGlzLl92ZXJ0ZXhGb3JtYXQgPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5jbG9uZSh2ZXJ0ZXhGb3JtYXQpOwogICAgdGhpcy5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoZWxsaXBzb2lkKTsKICAgIHRoaXMuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICB0aGlzLl9zdFJvdGF0aW9uID0gc3RSb3RhdGlvbjsKICAgIHRoaXMuX2hlaWdodCA9IGhlaWdodDsKICAgIHRoaXMuX2V4dHJ1ZGVkSGVpZ2h0ID0gZXh0cnVkZWRIZWlnaHQ7CiAgICB0aGlzLl9jbG9zZVRvcCA9IG9wdGlvbnMuY2xvc2VUb3AgPz8gdHJ1ZTsKICAgIHRoaXMuX2Nsb3NlQm90dG9tID0gb3B0aW9ucy5jbG9zZUJvdHRvbSA/PyB0cnVlOwogICAgdGhpcy5fcG9seWdvbkhpZXJhcmNoeSA9IHBvbHlnb25IaWVyYXJjaHk7CiAgICB0aGlzLl9wZXJQb3NpdGlvbkhlaWdodCA9IHBlclBvc2l0aW9uSGVpZ2h0OwogICAgdGhpcy5fcGVyUG9zaXRpb25IZWlnaHRFeHRydWRlID0gcGVyUG9zaXRpb25IZWlnaHRFeHRydWRlOwogICAgdGhpcy5fc2hhZG93Vm9sdW1lID0gb3B0aW9ucy5zaGFkb3dWb2x1bWUgPz8gZmFsc2U7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZVBvbHlnb25HZW9tZXRyeSI7CiAgICB0aGlzLl9vZmZzZXRBdHRyaWJ1dGUgPSBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZTsKICAgIHRoaXMuX2FyY1R5cGUgPSBvcHRpb25zLmFyY1R5cGUgPz8gQXJjVHlwZV9kZWZhdWx0LkdFT0RFU0lDOwogICAgdGhpcy5fcmVjdGFuZ2xlID0gdm9pZCAwOwogICAgdGhpcy5fdGV4dHVyZUNvb3JkaW5hdGVSb3RhdGlvblBvaW50cyA9IHZvaWQgMDsKICAgIHRoaXMuX3RleHR1cmVDb29yZGluYXRlcyA9IHRleHR1cmVDb29yZGluYXRlczsKICAgIHRoaXMucGFja2VkTGVuZ3RoID0gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVIaWVyYXJjaHlQYWNrZWRMZW5ndGgoCiAgICAgIHBvbHlnb25IaWVyYXJjaHksCiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdAogICAgKSArIEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aCArICh0ZXh0dXJlQ29vcmRpbmF0ZXMgPyBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZUhpZXJhcmNoeVBhY2tlZExlbmd0aCgKICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzLAogICAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQKICAgICkgOiAxKSArIDEyOwogIH0KICBmdW5jdGlvbiBleHBhbmRSZWN0YW5nbGUocG9sYXIsIGxhc3RQb2xhciwgZWxsaXBzb2lkLCBhcmNUeXBlLCBwb2x5Z29uMiwgcmVzdWx0KSB7CiAgICBjb25zdCBsb25naXR1ZGUgPSBwb2xhci5sb25naXR1ZGU7CiAgICBjb25zdCBsb25BZGp1c3RlZCA9IGxvbmdpdHVkZSA+PSAwID8gbG9uZ2l0dWRlIDogbG9uZ2l0dWRlICsgTWF0aF9kZWZhdWx0LlRXT19QSTsKICAgIHBvbHlnb24yLndlc3RPdmVySWRsID0gTWF0aC5taW4ocG9seWdvbjIud2VzdE92ZXJJZGwsIGxvbkFkanVzdGVkKTsKICAgIHBvbHlnb24yLmVhc3RPdmVySWRsID0gTWF0aC5tYXgocG9seWdvbjIuZWFzdE92ZXJJZGwsIGxvbkFkanVzdGVkKTsKICAgIHJlc3VsdC53ZXN0ID0gTWF0aC5taW4ocmVzdWx0Lndlc3QsIGxvbmdpdHVkZSk7CiAgICByZXN1bHQuZWFzdCA9IE1hdGgubWF4KHJlc3VsdC5lYXN0LCBsb25naXR1ZGUpOwogICAgY29uc3QgbGF0aXR1ZGUgPSBwb2xhci5nZXRMYXRpdHVkZShlbGxpcHNvaWQpOwogICAgbGV0IHNlZ21lbnRMYXRpdHVkZSA9IGxhdGl0dWRlOwogICAgcmVzdWx0LnNvdXRoID0gTWF0aC5taW4ocmVzdWx0LnNvdXRoLCBsYXRpdHVkZSk7CiAgICByZXN1bHQubm9ydGggPSBNYXRoLm1heChyZXN1bHQubm9ydGgsIGxhdGl0dWRlKTsKICAgIGlmIChhcmNUeXBlICE9PSBBcmNUeXBlX2RlZmF1bHQuUkhVTUIpIHsKICAgICAgY29uc3Qgc2VnbWVudCA9IENhcnRlc2lhbjJfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgICBsYXN0UG9sYXIucG9zaXRpb24sCiAgICAgICAgcG9sYXIucG9zaXRpb24sCiAgICAgICAgc2NyYXRjaENhcnRlc2lhbjAyCiAgICAgICk7CiAgICAgIGNvbnN0IHQgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuZG90KGxhc3RQb2xhci5wb3NpdGlvbiwgc2VnbWVudCkgLyBDYXJ0ZXNpYW4yX2RlZmF1bHQuZG90KHNlZ21lbnQsIHNlZ21lbnQpOwogICAgICBpZiAodCA+IDAgJiYgdCA8IDEpIHsKICAgICAgICBjb25zdCBwcm9qZWN0ZWQgPSBDYXJ0ZXNpYW4yX2RlZmF1bHQuYWRkKAogICAgICAgICAgbGFzdFBvbGFyLnBvc2l0aW9uLAogICAgICAgICAgQ2FydGVzaWFuMl9kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoc2VnbWVudCwgLXQsIHNlZ21lbnQpLAogICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjE4CiAgICAgICAgKTsKICAgICAgICBjb25zdCBjbG9zZXN0UG9sYXIgPSBTdGVyZW9ncmFwaGljX2RlZmF1bHQuY2xvbmUobGFzdFBvbGFyLCBzY3JhdGNoUG9sYXJDbG9zZXN0KTsKICAgICAgICBjbG9zZXN0UG9sYXIucG9zaXRpb24gPSBwcm9qZWN0ZWQ7CiAgICAgICAgY29uc3QgYWRqdXN0ZWRMYXRpdHVkZSA9IGNsb3Nlc3RQb2xhci5nZXRMYXRpdHVkZShlbGxpcHNvaWQpOwogICAgICAgIHJlc3VsdC5zb3V0aCA9IE1hdGgubWluKHJlc3VsdC5zb3V0aCwgYWRqdXN0ZWRMYXRpdHVkZSk7CiAgICAgICAgcmVzdWx0Lm5vcnRoID0gTWF0aC5tYXgocmVzdWx0Lm5vcnRoLCBhZGp1c3RlZExhdGl0dWRlKTsKICAgICAgICBpZiAoTWF0aC5hYnMobGF0aXR1ZGUpID4gTWF0aC5hYnMoYWRqdXN0ZWRMYXRpdHVkZSkpIHsKICAgICAgICAgIHNlZ21lbnRMYXRpdHVkZSA9IGFkanVzdGVkTGF0aXR1ZGU7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBjb25zdCBkaXJlY3Rpb24yID0gbGFzdFBvbGFyLnggKiBwb2xhci55IC0gcG9sYXIueCAqIGxhc3RQb2xhci55OwogICAgbGV0IGFuZ2xlID0gTWF0aC5zaWduKGRpcmVjdGlvbjIpOwogICAgaWYgKGFuZ2xlICE9PSAwKSB7CiAgICAgIGFuZ2xlICo9IENhcnRlc2lhbjJfZGVmYXVsdC5hbmdsZUJldHdlZW4obGFzdFBvbGFyLnBvc2l0aW9uLCBwb2xhci5wb3NpdGlvbik7CiAgICB9CiAgICBpZiAoc2VnbWVudExhdGl0dWRlID49IDApIHsKICAgICAgcG9seWdvbjIubm9ydGhBbmdsZSArPSBhbmdsZTsKICAgIH0KICAgIGlmIChzZWdtZW50TGF0aXR1ZGUgPD0gMCkgewogICAgICBwb2x5Z29uMi5zb3V0aEFuZ2xlICs9IGFuZ2xlOwogICAgfQogIH0KICBmdW5jdGlvbiBnZXRUYW5nZW50UGxhbmUocmVjdGFuZ2xlLCBwb3NpdGlvbnMsIGVsbGlwc29pZCkgewogICAgaWYgKHJlY3RhbmdsZS5oZWlnaHQgPj0gTWF0aF9kZWZhdWx0LlBJIHx8IHJlY3RhbmdsZS53aWR0aCA+PSBNYXRoX2RlZmF1bHQuUEkpIHsKICAgICAgY29uc3QgcG9sYXIgPSBTdGVyZW9ncmFwaGljX2RlZmF1bHQuZnJvbUNhcnRlc2lhbigKICAgICAgICBwb3NpdGlvbnNbMF0sCiAgICAgICAgc2NyYXRjaFBvbGFyRm9yUGxhbmUKICAgICAgKTsKICAgICAgcmV0dXJuIHBvbGFyLnRhbmdlbnRQbGFuZTsKICAgIH0KICAgIHJldHVybiBFbGxpcHNvaWRUYW5nZW50UGxhbmVfZGVmYXVsdC5mcm9tUG9pbnRzKHBvc2l0aW9ucywgZWxsaXBzb2lkKTsKICB9CiAgZnVuY3Rpb24gY3JlYXRlUHJvamVjdFRvMmQocmVjdGFuZ2xlLCBvdXRlclBvc2l0aW9ucywgZWxsaXBzb2lkKSB7CiAgICByZXR1cm4gKHBvc2l0aW9ucywgcmVzdWx0cykgPT4gewogICAgICBpZiAocmVjdGFuZ2xlLmhlaWdodCA+PSBNYXRoX2RlZmF1bHQuUEkgfHwgcmVjdGFuZ2xlLndpZHRoID49IE1hdGhfZGVmYXVsdC5QSSkgewogICAgICAgIGlmIChyZWN0YW5nbGUuc291dGggPCAwICYmIHJlY3RhbmdsZS5ub3J0aCA+IDApIHsKICAgICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdHMpKSB7CiAgICAgICAgICAgIHJlc3VsdHMgPSBbXTsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9zaXRpb25zLmxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgIGNvbnN0IGNhcnRvZ3JhcGhpYzIgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMoCiAgICAgICAgICAgICAgcG9zaXRpb25zW2ldLAogICAgICAgICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWNDeWxsaW5kcmljYWwKICAgICAgICAgICAgKTsKICAgICAgICAgICAgcmVzdWx0c1tpXSA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoCiAgICAgICAgICAgICAgY2FydG9ncmFwaGljMi5sb25naXR1ZGUgLyBNYXRoX2RlZmF1bHQuUEksCiAgICAgICAgICAgICAgY2FydG9ncmFwaGljMi5sYXRpdHVkZSAvIE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTwogICAgICAgICAgICApOwogICAgICAgICAgfQogICAgICAgICAgcmVzdWx0cy5sZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgICAgICAgcmV0dXJuIHJlc3VsdHM7CiAgICAgICAgfQogICAgICAgIHJldHVybiBTdGVyZW9ncmFwaGljX2RlZmF1bHQuZnJvbUNhcnRlc2lhbkFycmF5KHBvc2l0aW9ucywgcmVzdWx0cyk7CiAgICAgIH0KICAgICAgY29uc3QgdGFuZ2VudFBsYW5lID0gRWxsaXBzb2lkVGFuZ2VudFBsYW5lX2RlZmF1bHQuZnJvbVBvaW50cygKICAgICAgICBvdXRlclBvc2l0aW9ucywKICAgICAgICBlbGxpcHNvaWQKICAgICAgKTsKICAgICAgcmV0dXJuIHRhbmdlbnRQbGFuZS5wcm9qZWN0UG9pbnRzT250b1BsYW5lKHBvc2l0aW9ucywgcmVzdWx0cyk7CiAgICB9OwogIH0KICBmdW5jdGlvbiBjcmVhdGVQcm9qZWN0UG9zaXRpb25UbzJkKHJlY3RhbmdsZSwgb3V0ZXJSaW5nLCBlbGxpcHNvaWQpIHsKICAgIGlmIChyZWN0YW5nbGUuaGVpZ2h0ID49IE1hdGhfZGVmYXVsdC5QSSB8fCByZWN0YW5nbGUud2lkdGggPj0gTWF0aF9kZWZhdWx0LlBJKSB7CiAgICAgIHJldHVybiAocG9zaXRpb24sIHJlc3VsdCkgPT4gewogICAgICAgIGlmIChyZWN0YW5nbGUuc291dGggPCAwICYmIHJlY3RhbmdsZS5ub3J0aCA+IDApIHsKICAgICAgICAgIGNvbnN0IGNhcnRvZ3JhcGhpYzIgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMoCiAgICAgICAgICAgIHBvc2l0aW9uLAogICAgICAgICAgICBzY3JhdGNoQ2FydG9ncmFwaGljQ3lsbGluZHJpY2FsCiAgICAgICAgICApOwogICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgICByZXN1bHQgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHQueCA9IGNhcnRvZ3JhcGhpYzIubG9uZ2l0dWRlIC8gTWF0aF9kZWZhdWx0LlBJOwogICAgICAgICAgcmVzdWx0LnkgPSBjYXJ0b2dyYXBoaWMyLmxhdGl0dWRlIC8gTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIFN0ZXJlb2dyYXBoaWNfZGVmYXVsdC5mcm9tQ2FydGVzaWFuKHBvc2l0aW9uLCByZXN1bHQpOwogICAgICB9OwogICAgfQogICAgY29uc3QgdGFuZ2VudFBsYW5lID0gRWxsaXBzb2lkVGFuZ2VudFBsYW5lX2RlZmF1bHQuZnJvbVBvaW50cyhvdXRlclJpbmcsIGVsbGlwc29pZCk7CiAgICByZXR1cm4gKHBvc2l0aW9uLCByZXN1bHQpID0+IHsKICAgICAgcmV0dXJuIHRhbmdlbnRQbGFuZS5wcm9qZWN0UG9pbnRzT250b1BsYW5lKHBvc2l0aW9uLCByZXN1bHQpOwogICAgfTsKICB9CiAgZnVuY3Rpb24gY3JlYXRlU3BsaXRQb2x5Z29ucyhyZWN0YW5nbGUsIGVsbGlwc29pZCwgYXJjVHlwZSwgcGVyUG9zaXRpb25IZWlnaHQpIHsKICAgIHJldHVybiAocG9seWdvbnMsIHJlc3VsdHMpID0+IHsKICAgICAgaWYgKCFwZXJQb3NpdGlvbkhlaWdodCAmJiAocmVjdGFuZ2xlLmhlaWdodCA+PSBNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08gfHwgcmVjdGFuZ2xlLndpZHRoID49IDIgKiBNYXRoX2RlZmF1bHQuUElfT1ZFUl9USFJFRSkpIHsKICAgICAgICByZXR1cm4gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LnNwbGl0UG9seWdvbnNPbkVxdWF0b3IoCiAgICAgICAgICBwb2x5Z29ucywKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIGFyY1R5cGUsCiAgICAgICAgICByZXN1bHRzCiAgICAgICAgKTsKICAgICAgfQogICAgICByZXR1cm4gcG9seWdvbnM7CiAgICB9OwogIH0KICBmdW5jdGlvbiBjb21wdXRlQm91bmRpbmdSZWN0YW5nbGUob3V0ZXJSaW5nLCByZWN0YW5nbGUsIGVsbGlwc29pZCwgc3RSb3RhdGlvbikgewogICAgaWYgKHJlY3RhbmdsZS5oZWlnaHQgPj0gTWF0aF9kZWZhdWx0LlBJIHx8IHJlY3RhbmdsZS53aWR0aCA+PSBNYXRoX2RlZmF1bHQuUEkpIHsKICAgICAgcmV0dXJuIEJvdW5kaW5nUmVjdGFuZ2xlX2RlZmF1bHQuZnJvbVJlY3RhbmdsZSgKICAgICAgICByZWN0YW5nbGUsCiAgICAgICAgdm9pZCAwLAogICAgICAgIHNjcmF0Y2hCb3VuZGluZ1JlY3RhbmdsZQogICAgICApOwogICAgfQogICAgY29uc3Qgb3V0ZXJQb3NpdGlvbnMgPSBvdXRlclJpbmc7CiAgICBjb25zdCB0YW5nZW50UGxhbmUgPSBFbGxpcHNvaWRUYW5nZW50UGxhbmVfZGVmYXVsdC5mcm9tUG9pbnRzKAogICAgICBvdXRlclBvc2l0aW9ucywKICAgICAgZWxsaXBzb2lkCiAgICApOwogICAgcmV0dXJuIFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlQm91bmRpbmdSZWN0YW5nbGUoCiAgICAgIHRhbmdlbnRQbGFuZS5wbGFuZS5ub3JtYWwsCiAgICAgIHRhbmdlbnRQbGFuZS5wcm9qZWN0UG9pbnRPbnRvUGxhbmUuYmluZCh0YW5nZW50UGxhbmUpLAogICAgICBvdXRlclBvc2l0aW9ucywKICAgICAgc3RSb3RhdGlvbiwKICAgICAgc2NyYXRjaEJvdW5kaW5nUmVjdGFuZ2xlCiAgICApOwogIH0KICBmdW5jdGlvbiB0ZXh0dXJlQ29vcmRpbmF0ZVJvdGF0aW9uUG9pbnRzMihwb2x5Z29uR2VvbWV0cnkpIHsKICAgIGNvbnN0IHN0Um90YXRpb24gPSAtcG9seWdvbkdlb21ldHJ5Ll9zdFJvdGF0aW9uOwogICAgaWYgKHN0Um90YXRpb24gPT09IDApIHsKICAgICAgcmV0dXJuIFswLCAwLCAwLCAxLCAxLCAwXTsKICAgIH0KICAgIGNvbnN0IGVsbGlwc29pZCA9IHBvbHlnb25HZW9tZXRyeS5fZWxsaXBzb2lkOwogICAgY29uc3QgcG9zaXRpb25zID0gcG9seWdvbkdlb21ldHJ5Ll9wb2x5Z29uSGllcmFyY2h5LnBvc2l0aW9uczsKICAgIGNvbnN0IGJvdW5kaW5nUmVjdGFuZ2xlID0gcG9seWdvbkdlb21ldHJ5LnJlY3RhbmdsZTsKICAgIHJldHVybiBHZW9tZXRyeV9kZWZhdWx0Ll90ZXh0dXJlQ29vcmRpbmF0ZVJvdGF0aW9uUG9pbnRzKAogICAgICBwb3NpdGlvbnMsCiAgICAgIHN0Um90YXRpb24sCiAgICAgIGVsbGlwc29pZCwKICAgICAgYm91bmRpbmdSZWN0YW5nbGUKICAgICk7CiAgfQogIHZhciBzY3JhdGNoQ2FydG8xLCBzY3JhdGNoQ2FydG8yLCBzY3JhdGNoQm91bmRpbmdSZWN0YW5nbGUsIHNjcmF0Y2hQb3NpdGlvbjMsIHNjcmF0Y2hOb3JtYWw2LCBzY3JhdGNoVGFuZ2VudDQsIHNjcmF0Y2hCaXRhbmdlbnQ0LCBwMVNjcmF0Y2gzLCBwMlNjcmF0Y2gzLCBzY3JhdGNoUGVyUG9zTm9ybWFsLCBzY3JhdGNoUGVyUG9zVGFuZ2VudCwgc2NyYXRjaFBlclBvc0JpdGFuZ2VudCwgYXBwZW5kVGV4dHVyZUNvb3JkaW5hdGVzT3JpZ2luLCBhcHBlbmRUZXh0dXJlQ29vcmRpbmF0ZXNDYXJ0ZXNpYW4yLCBhcHBlbmRUZXh0dXJlQ29vcmRpbmF0ZXNDYXJ0ZXNpYW4zLCBhcHBlbmRUZXh0dXJlQ29vcmRpbmF0ZXNRdWF0ZXJuaW9uLCBhcHBlbmRUZXh0dXJlQ29vcmRpbmF0ZXNNYXRyaXgzLCB0YW5nZW50TWF0cml4U2NyYXRjaDIsIGNyZWF0ZUdlb21ldHJ5RnJvbVBvc2l0aW9uc0V4dHJ1ZGVkUG9zaXRpb25zLCBzY3JhdGNoRWxsaXBzb2lkNiwgc2NyYXRjaFZlcnRleEZvcm1hdDksIGR1bW15T3B0aW9ucywgc2NyYXRjaENhcnRlc2lhbjAyLCBzY3JhdGNoQ2FydGVzaWFuMTgsIHNjcmF0Y2hQb2xhckNsb3Nlc3QsIHNjcmF0Y2hQb2xhciwgc2NyYXRjaFBvbGFyUHJldmlvdXMsIHBvbHlnb24sIHNjcmF0Y2hQb2xhckZvclBsYW5lLCBzY3JhdGNoQ2FydG9ncmFwaGljQ3lsbGluZHJpY2FsLCBQb2x5Z29uR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9Qb2x5Z29uR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1BvbHlnb25HZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQXJjVHlwZSgpOwogICAgICBpbml0X0JvdW5kaW5nUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4yKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfQ29tcG9uZW50RGF0YXR5cGUoKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWRUYW5nZW50UGxhbmUoKTsKICAgICAgaW5pdF9HZW9tZXRyeSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlJbnN0YW5jZSgpOwogICAgICBpbml0X0dlb21ldHJ5T2Zmc2V0QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlQaXBlbGluZSgpOwogICAgICBpbml0X0luZGV4RGF0YXR5cGUoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfTWF0cml4MygpOwogICAgICBpbml0X1BvbHlnb25HZW9tZXRyeUxpYnJhcnkoKTsKICAgICAgaW5pdF9Qb2x5Z29uUGlwZWxpbmUoKTsKICAgICAgaW5pdF9RdWF0ZXJuaW9uKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfU3RlcmVvZ3JhcGhpYygpOwogICAgICBpbml0X1ZlcnRleEZvcm1hdCgpOwogICAgICBpbml0X1dpbmRpbmdPcmRlcigpOwogICAgICBzY3JhdGNoQ2FydG8xID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0bzIgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEJvdW5kaW5nUmVjdGFuZ2xlID0gbmV3IEJvdW5kaW5nUmVjdGFuZ2xlX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBvc2l0aW9uMyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE5vcm1hbDYgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hUYW5nZW50NCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEJpdGFuZ2VudDQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHAxU2NyYXRjaDMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHAyU2NyYXRjaDMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQZXJQb3NOb3JtYWwgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQZXJQb3NUYW5nZW50ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUGVyUG9zQml0YW5nZW50ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBhcHBlbmRUZXh0dXJlQ29vcmRpbmF0ZXNPcmlnaW4gPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIGFwcGVuZFRleHR1cmVDb29yZGluYXRlc0NhcnRlc2lhbjIgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIGFwcGVuZFRleHR1cmVDb29yZGluYXRlc0NhcnRlc2lhbjMgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGFwcGVuZFRleHR1cmVDb29yZGluYXRlc1F1YXRlcm5pb24gPSBuZXcgUXVhdGVybmlvbl9kZWZhdWx0KCk7CiAgICAgIGFwcGVuZFRleHR1cmVDb29yZGluYXRlc01hdHJpeDMgPSBuZXcgTWF0cml4M19kZWZhdWx0KCk7CiAgICAgIHRhbmdlbnRNYXRyaXhTY3JhdGNoMiA9IG5ldyBNYXRyaXgzX2RlZmF1bHQoKTsKICAgICAgY3JlYXRlR2VvbWV0cnlGcm9tUG9zaXRpb25zRXh0cnVkZWRQb3NpdGlvbnMgPSBbXTsKICAgICAgUG9seWdvbkdlb21ldHJ5LmZyb21Qb3NpdGlvbnMgPSBmdW5jdGlvbihvcHRpb25zKSB7CiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgib3B0aW9ucy5wb3NpdGlvbnMiLCBvcHRpb25zLnBvc2l0aW9ucyk7CiAgICAgICAgY29uc3QgbmV3T3B0aW9ucyA9IHsKICAgICAgICAgIHBvbHlnb25IaWVyYXJjaHk6IHsKICAgICAgICAgICAgcG9zaXRpb25zOiBvcHRpb25zLnBvc2l0aW9ucwogICAgICAgICAgfSwKICAgICAgICAgIGhlaWdodDogb3B0aW9ucy5oZWlnaHQsCiAgICAgICAgICBleHRydWRlZEhlaWdodDogb3B0aW9ucy5leHRydWRlZEhlaWdodCwKICAgICAgICAgIHZlcnRleEZvcm1hdDogb3B0aW9ucy52ZXJ0ZXhGb3JtYXQsCiAgICAgICAgICBzdFJvdGF0aW9uOiBvcHRpb25zLnN0Um90YXRpb24sCiAgICAgICAgICBlbGxpcHNvaWQ6IG9wdGlvbnMuZWxsaXBzb2lkLAogICAgICAgICAgZ3JhbnVsYXJpdHk6IG9wdGlvbnMuZ3JhbnVsYXJpdHksCiAgICAgICAgICBwZXJQb3NpdGlvbkhlaWdodDogb3B0aW9ucy5wZXJQb3NpdGlvbkhlaWdodCwKICAgICAgICAgIGNsb3NlVG9wOiBvcHRpb25zLmNsb3NlVG9wLAogICAgICAgICAgY2xvc2VCb3R0b206IG9wdGlvbnMuY2xvc2VCb3R0b20sCiAgICAgICAgICBvZmZzZXRBdHRyaWJ1dGU6IG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlLAogICAgICAgICAgYXJjVHlwZTogb3B0aW9ucy5hcmNUeXBlLAogICAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzOiBvcHRpb25zLnRleHR1cmVDb29yZGluYXRlcwogICAgICAgIH07CiAgICAgICAgcmV0dXJuIG5ldyBQb2x5Z29uR2VvbWV0cnkobmV3T3B0aW9ucyk7CiAgICAgIH07CiAgICAgIFBvbHlnb25HZW9tZXRyeS5wYWNrID0gZnVuY3Rpb24odmFsdWUsIGFycmF5LCBzdGFydGluZ0luZGV4KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJ2YWx1ZSIsIHZhbHVlKTsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoImFycmF5IiwgYXJyYXkpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5wYWNrUG9seWdvbkhpZXJhcmNoeSgKICAgICAgICAgIHZhbHVlLl9wb2x5Z29uSGllcmFyY2h5LAogICAgICAgICAgYXJyYXksCiAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0CiAgICAgICAgKTsKICAgICAgICBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrKHZhbHVlLl9lbGxpcHNvaWQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrKHZhbHVlLl92ZXJ0ZXhGb3JtYXQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2hlaWdodDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2V4dHJ1ZGVkSGVpZ2h0OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fZ3JhbnVsYXJpdHk7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9zdFJvdGF0aW9uOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fcGVyUG9zaXRpb25IZWlnaHRFeHRydWRlID8gMSA6IDA7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9wZXJQb3NpdGlvbkhlaWdodCA/IDEgOiAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fY2xvc2VUb3AgPyAxIDogMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2Nsb3NlQm90dG9tID8gMSA6IDA7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9zaGFkb3dWb2x1bWUgPyAxIDogMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX29mZnNldEF0dHJpYnV0ZSA/PyAtMTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2FyY1R5cGU7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdCh2YWx1ZS5fdGV4dHVyZUNvb3JkaW5hdGVzKSkgewogICAgICAgICAgc3RhcnRpbmdJbmRleCA9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5wYWNrUG9seWdvbkhpZXJhcmNoeSgKICAgICAgICAgICAgdmFsdWUuX3RleHR1cmVDb29yZGluYXRlcywKICAgICAgICAgICAgYXJyYXksCiAgICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdAogICAgICAgICAgKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IC0xOwogICAgICAgIH0KICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUucGFja2VkTGVuZ3RoOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgc2NyYXRjaEVsbGlwc29pZDYgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShFbGxpcHNvaWRfZGVmYXVsdC5VTklUX1NQSEVSRSk7CiAgICAgIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQ5ID0gbmV3IFZlcnRleEZvcm1hdF9kZWZhdWx0KCk7CiAgICAgIGR1bW15T3B0aW9ucyA9IHsKICAgICAgICBwb2x5Z29uSGllcmFyY2h5OiB7fQogICAgICB9OwogICAgICBQb2x5Z29uR2VvbWV0cnkudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBjb25zdCBwb2x5Z29uSGllcmFyY2h5ID0gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LnVucGFja1BvbHlnb25IaWVyYXJjaHkoCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQKICAgICAgICApOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBwb2x5Z29uSGllcmFyY2h5LnN0YXJ0aW5nSW5kZXg7CiAgICAgICAgZGVsZXRlIHBvbHlnb25IaWVyYXJjaHkuc3RhcnRpbmdJbmRleDsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHNjcmF0Y2hFbGxpcHNvaWQ2KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICBzY3JhdGNoVmVydGV4Rm9ybWF0OQogICAgICAgICk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgaGVpZ2h0ID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHN0Um90YXRpb24gPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHBlclBvc2l0aW9uSGVpZ2h0RXh0cnVkZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPT09IDE7CiAgICAgICAgY29uc3QgcGVyUG9zaXRpb25IZWlnaHQgPSBhcnJheVtzdGFydGluZ0luZGV4KytdID09PSAxOwogICAgICAgIGNvbnN0IGNsb3NlVG9wID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9PT0gMTsKICAgICAgICBjb25zdCBjbG9zZUJvdHRvbSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPT09IDE7CiAgICAgICAgY29uc3Qgc2hhZG93Vm9sdW1lID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9PT0gMTsKICAgICAgICBjb25zdCBvZmZzZXRBdHRyaWJ1dGUgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IGFyY1R5cGUgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHRleHR1cmVDb29yZGluYXRlcyA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdID09PSAtMSA/IHZvaWQgMCA6IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC51bnBhY2tQb2x5Z29uSGllcmFyY2h5KAogICAgICAgICAgYXJyYXksCiAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgQ2FydGVzaWFuMl9kZWZhdWx0CiAgICAgICAgKTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHRleHR1cmVDb29yZGluYXRlcykpIHsKICAgICAgICAgIHN0YXJ0aW5nSW5kZXggPSB0ZXh0dXJlQ29vcmRpbmF0ZXMuc3RhcnRpbmdJbmRleDsKICAgICAgICAgIGRlbGV0ZSB0ZXh0dXJlQ29vcmRpbmF0ZXMuc3RhcnRpbmdJbmRleDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3RhcnRpbmdJbmRleCsrOwogICAgICAgIH0KICAgICAgICBjb25zdCBwYWNrZWRMZW5ndGggPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBQb2x5Z29uR2VvbWV0cnkoZHVtbXlPcHRpb25zKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0Ll9wb2x5Z29uSGllcmFyY2h5ID0gcG9seWdvbkhpZXJhcmNoeTsKICAgICAgICByZXN1bHQuX2VsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKGVsbGlwc29pZCwgcmVzdWx0Ll9lbGxpcHNvaWQpOwogICAgICAgIHJlc3VsdC5fdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQuY2xvbmUodmVydGV4Rm9ybWF0LCByZXN1bHQuX3ZlcnRleEZvcm1hdCk7CiAgICAgICAgcmVzdWx0Ll9oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgcmVzdWx0Ll9leHRydWRlZEhlaWdodCA9IGV4dHJ1ZGVkSGVpZ2h0OwogICAgICAgIHJlc3VsdC5fZ3JhbnVsYXJpdHkgPSBncmFudWxhcml0eTsKICAgICAgICByZXN1bHQuX3N0Um90YXRpb24gPSBzdFJvdGF0aW9uOwogICAgICAgIHJlc3VsdC5fcGVyUG9zaXRpb25IZWlnaHRFeHRydWRlID0gcGVyUG9zaXRpb25IZWlnaHRFeHRydWRlOwogICAgICAgIHJlc3VsdC5fcGVyUG9zaXRpb25IZWlnaHQgPSBwZXJQb3NpdGlvbkhlaWdodDsKICAgICAgICByZXN1bHQuX2Nsb3NlVG9wID0gY2xvc2VUb3A7CiAgICAgICAgcmVzdWx0Ll9jbG9zZUJvdHRvbSA9IGNsb3NlQm90dG9tOwogICAgICAgIHJlc3VsdC5fc2hhZG93Vm9sdW1lID0gc2hhZG93Vm9sdW1lOwogICAgICAgIHJlc3VsdC5fb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlID09PSAtMSA/IHZvaWQgMCA6IG9mZnNldEF0dHJpYnV0ZTsKICAgICAgICByZXN1bHQuX2FyY1R5cGUgPSBhcmNUeXBlOwogICAgICAgIHJlc3VsdC5fdGV4dHVyZUNvb3JkaW5hdGVzID0gdGV4dHVyZUNvb3JkaW5hdGVzOwogICAgICAgIHJlc3VsdC5wYWNrZWRMZW5ndGggPSBwYWNrZWRMZW5ndGg7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjAyID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydGVzaWFuMTggPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQb2xhckNsb3Nlc3QgPSBuZXcgU3RlcmVvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQb2xhciA9IG5ldyBTdGVyZW9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFBvbGFyUHJldmlvdXMgPSBuZXcgU3RlcmVvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHBvbHlnb24gPSB7CiAgICAgICAgbm9ydGhBbmdsZTogMCwKICAgICAgICBzb3V0aEFuZ2xlOiAwLAogICAgICAgIHdlc3RPdmVySWRsOiAwLAogICAgICAgIGVhc3RPdmVySWRsOiAwCiAgICAgIH07CiAgICAgIFBvbHlnb25HZW9tZXRyeS5jb21wdXRlUmVjdGFuZ2xlRnJvbVBvc2l0aW9ucyA9IGZ1bmN0aW9uKHBvc2l0aW9ucywgZWxsaXBzb2lkLCBhcmNUeXBlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoInBvc2l0aW9ucyIsIHBvc2l0aW9ucyk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IFJlY3RhbmdsZV9kZWZhdWx0KCk7CiAgICAgICAgfQogICAgICAgIGlmIChwb3NpdGlvbnMubGVuZ3RoIDwgMykgewogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgcmVzdWx0Lndlc3QgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICAgICAgcmVzdWx0LmVhc3QgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICAgICAgcmVzdWx0LnNvdXRoID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgICAgIHJlc3VsdC5ub3J0aCA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgICAgICBwb2x5Z29uLm5vcnRoQW5nbGUgPSAwOwogICAgICAgIHBvbHlnb24uc291dGhBbmdsZSA9IDA7CiAgICAgICAgcG9seWdvbi53ZXN0T3ZlcklkbCA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTsKICAgICAgICBwb2x5Z29uLmVhc3RPdmVySWRsID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZOwogICAgICAgIGNvbnN0IHBvc2l0aW9uc0xlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgbGV0IGxhc3RQb2xhclBvc2l0aW9uID0gU3RlcmVvZ3JhcGhpY19kZWZhdWx0LmZyb21DYXJ0ZXNpYW4oCiAgICAgICAgICBwb3NpdGlvbnNbMF0sCiAgICAgICAgICBzY3JhdGNoUG9sYXJQcmV2aW91cwogICAgICAgICk7CiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBwb3NpdGlvbnNMZW5ndGg7IGkrKykgewogICAgICAgICAgY29uc3QgcG9sYXJQb3NpdGlvbiA9IFN0ZXJlb2dyYXBoaWNfZGVmYXVsdC5mcm9tQ2FydGVzaWFuKAogICAgICAgICAgICBwb3NpdGlvbnNbaV0sCiAgICAgICAgICAgIHNjcmF0Y2hQb2xhcgogICAgICAgICAgKTsKICAgICAgICAgIGV4cGFuZFJlY3RhbmdsZSgKICAgICAgICAgICAgcG9sYXJQb3NpdGlvbiwKICAgICAgICAgICAgbGFzdFBvbGFyUG9zaXRpb24sCiAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgYXJjVHlwZSwKICAgICAgICAgICAgcG9seWdvbiwKICAgICAgICAgICAgcmVzdWx0CiAgICAgICAgICApOwogICAgICAgICAgbGFzdFBvbGFyUG9zaXRpb24gPSBTdGVyZW9ncmFwaGljX2RlZmF1bHQuY2xvbmUocG9sYXJQb3NpdGlvbiwgbGFzdFBvbGFyUG9zaXRpb24pOwogICAgICAgIH0KICAgICAgICBleHBhbmRSZWN0YW5nbGUoCiAgICAgICAgICBTdGVyZW9ncmFwaGljX2RlZmF1bHQuZnJvbUNhcnRlc2lhbihwb3NpdGlvbnNbMF0sIHNjcmF0Y2hQb2xhciksCiAgICAgICAgICBsYXN0UG9sYXJQb3NpdGlvbiwKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIGFyY1R5cGUsCiAgICAgICAgICBwb2x5Z29uLAogICAgICAgICAgcmVzdWx0CiAgICAgICAgKTsKICAgICAgICBpZiAocmVzdWx0LmVhc3QgLSByZXN1bHQud2VzdCA+IHBvbHlnb24uZWFzdE92ZXJJZGwgLSBwb2x5Z29uLndlc3RPdmVySWRsKSB7CiAgICAgICAgICByZXN1bHQud2VzdCA9IHBvbHlnb24ud2VzdE92ZXJJZGw7CiAgICAgICAgICByZXN1bHQuZWFzdCA9IHBvbHlnb24uZWFzdE92ZXJJZGw7CiAgICAgICAgICBpZiAocmVzdWx0LmVhc3QgPiBNYXRoX2RlZmF1bHQuUEkpIHsKICAgICAgICAgICAgcmVzdWx0LmVhc3QgPSByZXN1bHQuZWFzdCAtIE1hdGhfZGVmYXVsdC5UV09fUEk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAocmVzdWx0Lndlc3QgPiBNYXRoX2RlZmF1bHQuUEkpIHsKICAgICAgICAgICAgcmVzdWx0Lndlc3QgPSByZXN1bHQud2VzdCAtIE1hdGhfZGVmYXVsdC5UV09fUEk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbigKICAgICAgICAgIE1hdGguYWJzKHBvbHlnb24ubm9ydGhBbmdsZSksCiAgICAgICAgICBNYXRoX2RlZmF1bHQuVFdPX1BJLAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xMAogICAgICAgICkpIHsKICAgICAgICAgIHJlc3VsdC5ub3J0aCA9IE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTzsKICAgICAgICAgIHJlc3VsdC5lYXN0ID0gTWF0aF9kZWZhdWx0LlBJOwogICAgICAgICAgcmVzdWx0Lndlc3QgPSAtTWF0aF9kZWZhdWx0LlBJOwogICAgICAgIH0KICAgICAgICBpZiAoTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICBNYXRoLmFicyhwb2x5Z29uLnNvdXRoQW5nbGUpLAogICAgICAgICAgTWF0aF9kZWZhdWx0LlRXT19QSSwKICAgICAgICAgIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTAKICAgICAgICApKSB7CiAgICAgICAgICByZXN1bHQuc291dGggPSAtTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPOwogICAgICAgICAgcmVzdWx0LmVhc3QgPSBNYXRoX2RlZmF1bHQuUEk7CiAgICAgICAgICByZXN1bHQud2VzdCA9IC1NYXRoX2RlZmF1bHQuUEk7CiAgICAgICAgfQogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hQb2xhckZvclBsYW5lID0gbmV3IFN0ZXJlb2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydG9ncmFwaGljQ3lsbGluZHJpY2FsID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIFBvbHlnb25HZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKHBvbHlnb25HZW9tZXRyeSkgewogICAgICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IHBvbHlnb25HZW9tZXRyeS5fdmVydGV4Rm9ybWF0OwogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IHBvbHlnb25HZW9tZXRyeS5fZWxsaXBzb2lkOwogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gcG9seWdvbkdlb21ldHJ5Ll9ncmFudWxhcml0eTsKICAgICAgICBjb25zdCBzdFJvdGF0aW9uID0gcG9seWdvbkdlb21ldHJ5Ll9zdFJvdGF0aW9uOwogICAgICAgIGNvbnN0IHBvbHlnb25IaWVyYXJjaHkgPSBwb2x5Z29uR2VvbWV0cnkuX3BvbHlnb25IaWVyYXJjaHk7CiAgICAgICAgY29uc3QgcGVyUG9zaXRpb25IZWlnaHQgPSBwb2x5Z29uR2VvbWV0cnkuX3BlclBvc2l0aW9uSGVpZ2h0OwogICAgICAgIGNvbnN0IGNsb3NlVG9wID0gcG9seWdvbkdlb21ldHJ5Ll9jbG9zZVRvcDsKICAgICAgICBjb25zdCBjbG9zZUJvdHRvbSA9IHBvbHlnb25HZW9tZXRyeS5fY2xvc2VCb3R0b207CiAgICAgICAgY29uc3QgYXJjVHlwZSA9IHBvbHlnb25HZW9tZXRyeS5fYXJjVHlwZTsKICAgICAgICBjb25zdCB0ZXh0dXJlQ29vcmRpbmF0ZXMgPSBwb2x5Z29uR2VvbWV0cnkuX3RleHR1cmVDb29yZGluYXRlczsKICAgICAgICBjb25zdCBoYXNUZXh0dXJlQ29vcmRpbmF0ZXMgPSBkZWZpbmVkX2RlZmF1bHQodGV4dHVyZUNvb3JkaW5hdGVzKTsKICAgICAgICBjb25zdCBvdXRlclBvc2l0aW9ucyA9IHBvbHlnb25IaWVyYXJjaHkucG9zaXRpb25zOwogICAgICAgIGlmIChvdXRlclBvc2l0aW9ucy5sZW5ndGggPCAzKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IHJlY3RhbmdsZSA9IHBvbHlnb25HZW9tZXRyeS5yZWN0YW5nbGU7CiAgICAgICAgY29uc3QgcmVzdWx0cyA9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5wb2x5Z29uc0Zyb21IaWVyYXJjaHkoCiAgICAgICAgICBwb2x5Z29uSGllcmFyY2h5LAogICAgICAgICAgaGFzVGV4dHVyZUNvb3JkaW5hdGVzLAogICAgICAgICAgY3JlYXRlUHJvamVjdFRvMmQocmVjdGFuZ2xlLCBvdXRlclBvc2l0aW9ucywgZWxsaXBzb2lkKSwKICAgICAgICAgICFwZXJQb3NpdGlvbkhlaWdodCwKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIGNyZWF0ZVNwbGl0UG9seWdvbnMocmVjdGFuZ2xlLCBlbGxpcHNvaWQsIGFyY1R5cGUsIHBlclBvc2l0aW9uSGVpZ2h0KQogICAgICAgICk7CiAgICAgICAgY29uc3QgaGllcmFyY2h5ID0gcmVzdWx0cy5oaWVyYXJjaHk7CiAgICAgICAgY29uc3QgcG9seWdvbnMgPSByZXN1bHRzLnBvbHlnb25zOwogICAgICAgIGNvbnN0IGR1bW15RnVuY3Rpb24gPSBmdW5jdGlvbihpZGVudGl0eSkgewogICAgICAgICAgcmV0dXJuIGlkZW50aXR5OwogICAgICAgIH07CiAgICAgICAgY29uc3QgdGV4dHVyZUNvb3JkaW5hdGVQb2x5Z29ucyA9IGhhc1RleHR1cmVDb29yZGluYXRlcyA/IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5wb2x5Z29uc0Zyb21IaWVyYXJjaHkoCiAgICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXMsCiAgICAgICAgICB0cnVlLAogICAgICAgICAgZHVtbXlGdW5jdGlvbiwKICAgICAgICAgIGZhbHNlLAogICAgICAgICAgZWxsaXBzb2lkCiAgICAgICAgKS5wb2x5Z29ucyA6IHZvaWQgMDsKICAgICAgICBpZiAoaGllcmFyY2h5Lmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBjb25zdCBvdXRlclJpbmcgPSBoaWVyYXJjaHlbMF0ub3V0ZXJSaW5nOwogICAgICAgIGNvbnN0IGJvdW5kaW5nUmVjdGFuZ2xlID0gY29tcHV0ZUJvdW5kaW5nUmVjdGFuZ2xlKAogICAgICAgICAgb3V0ZXJSaW5nLAogICAgICAgICAgcmVjdGFuZ2xlLAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgc3RSb3RhdGlvbgogICAgICAgICk7CiAgICAgICAgY29uc3QgZ2VvbWV0cmllcyA9IFtdOwogICAgICAgIGNvbnN0IGhlaWdodCA9IHBvbHlnb25HZW9tZXRyeS5faGVpZ2h0OwogICAgICAgIGNvbnN0IGV4dHJ1ZGVkSGVpZ2h0ID0gcG9seWdvbkdlb21ldHJ5Ll9leHRydWRlZEhlaWdodDsKICAgICAgICBjb25zdCBleHRydWRlID0gcG9seWdvbkdlb21ldHJ5Ll9wZXJQb3NpdGlvbkhlaWdodEV4dHJ1ZGUgfHwgIU1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKGhlaWdodCwgZXh0cnVkZWRIZWlnaHQsIDAsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMik7CiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHsKICAgICAgICAgIHBlclBvc2l0aW9uSGVpZ2h0LAogICAgICAgICAgdmVydGV4Rm9ybWF0LAogICAgICAgICAgZ2VvbWV0cnk6IHZvaWQgMCwKICAgICAgICAgIHJvdGF0aW9uQXhpczogZ2V0VGFuZ2VudFBsYW5lKHJlY3RhbmdsZSwgb3V0ZXJSaW5nLCBlbGxpcHNvaWQpLnBsYW5lLm5vcm1hbCwKICAgICAgICAgIHByb2plY3RUbzJkOiBjcmVhdGVQcm9qZWN0UG9zaXRpb25UbzJkKHJlY3RhbmdsZSwgb3V0ZXJSaW5nLCBlbGxpcHNvaWQpLAogICAgICAgICAgYm91bmRpbmdSZWN0YW5nbGUsCiAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICBzdFJvdGF0aW9uLAogICAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzOiB2b2lkIDAsCiAgICAgICAgICBib3R0b206IGZhbHNlLAogICAgICAgICAgdG9wOiB0cnVlLAogICAgICAgICAgd2FsbDogZmFsc2UsCiAgICAgICAgICBleHRydWRlOiBmYWxzZSwKICAgICAgICAgIGFyY1R5cGUKICAgICAgICB9OwogICAgICAgIGxldCBpOwogICAgICAgIGlmIChleHRydWRlKSB7CiAgICAgICAgICBvcHRpb25zLmV4dHJ1ZGUgPSB0cnVlOwogICAgICAgICAgb3B0aW9ucy50b3AgPSBjbG9zZVRvcDsKICAgICAgICAgIG9wdGlvbnMuYm90dG9tID0gY2xvc2VCb3R0b207CiAgICAgICAgICBvcHRpb25zLnNoYWRvd1ZvbHVtZSA9IHBvbHlnb25HZW9tZXRyeS5fc2hhZG93Vm9sdW1lOwogICAgICAgICAgb3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGUgPSBwb2x5Z29uR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBwb2x5Z29ucy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBjb25zdCBzcGxpdEdlb21ldHJ5ID0gY3JlYXRlR2VvbWV0cnlGcm9tUG9zaXRpb25zRXh0cnVkZWQoCiAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgIHBvbHlnb25zW2ldLAogICAgICAgICAgICAgIGhhc1RleHR1cmVDb29yZGluYXRlcyA/IHRleHR1cmVDb29yZGluYXRlUG9seWdvbnNbaV0gOiB2b2lkIDAsCiAgICAgICAgICAgICAgZ3JhbnVsYXJpdHksCiAgICAgICAgICAgICAgaGllcmFyY2h5W2ldLAogICAgICAgICAgICAgIHBlclBvc2l0aW9uSGVpZ2h0LAogICAgICAgICAgICAgIGNsb3NlVG9wLAogICAgICAgICAgICAgIGNsb3NlQm90dG9tLAogICAgICAgICAgICAgIHZlcnRleEZvcm1hdCwKICAgICAgICAgICAgICBhcmNUeXBlCiAgICAgICAgICAgICk7CiAgICAgICAgICAgIGxldCB0b3BBbmRCb3R0b207CiAgICAgICAgICAgIGlmIChjbG9zZVRvcCAmJiBjbG9zZUJvdHRvbSkgewogICAgICAgICAgICAgIHRvcEFuZEJvdHRvbSA9IHNwbGl0R2VvbWV0cnkudG9wQW5kQm90dG9tOwogICAgICAgICAgICAgIG9wdGlvbnMuZ2VvbWV0cnkgPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuc2NhbGVUb0dlb2RldGljSGVpZ2h0RXh0cnVkZWQoCiAgICAgICAgICAgICAgICB0b3BBbmRCb3R0b20uZ2VvbWV0cnksCiAgICAgICAgICAgICAgICBoZWlnaHQsCiAgICAgICAgICAgICAgICBleHRydWRlZEhlaWdodCwKICAgICAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgICAgIHBlclBvc2l0aW9uSGVpZ2h0CiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgfSBlbHNlIGlmIChjbG9zZVRvcCkgewogICAgICAgICAgICAgIHRvcEFuZEJvdHRvbSA9IHNwbGl0R2VvbWV0cnkudG9wQW5kQm90dG9tOwogICAgICAgICAgICAgIHRvcEFuZEJvdHRvbS5nZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcyA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LnNjYWxlVG9HZW9kZXRpY0hlaWdodCgKICAgICAgICAgICAgICAgIHRvcEFuZEJvdHRvbS5nZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcywKICAgICAgICAgICAgICAgIGhlaWdodCwKICAgICAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgICAgICFwZXJQb3NpdGlvbkhlaWdodAogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgb3B0aW9ucy5nZW9tZXRyeSA9IHRvcEFuZEJvdHRvbS5nZW9tZXRyeTsKICAgICAgICAgICAgfSBlbHNlIGlmIChjbG9zZUJvdHRvbSkgewogICAgICAgICAgICAgIHRvcEFuZEJvdHRvbSA9IHNwbGl0R2VvbWV0cnkudG9wQW5kQm90dG9tOwogICAgICAgICAgICAgIHRvcEFuZEJvdHRvbS5nZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcyA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LnNjYWxlVG9HZW9kZXRpY0hlaWdodCgKICAgICAgICAgICAgICAgIHRvcEFuZEJvdHRvbS5nZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcywKICAgICAgICAgICAgICAgIGV4dHJ1ZGVkSGVpZ2h0LAogICAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgICAgdHJ1ZQogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgb3B0aW9ucy5nZW9tZXRyeSA9IHRvcEFuZEJvdHRvbS5nZW9tZXRyeTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoY2xvc2VUb3AgfHwgY2xvc2VCb3R0b20pIHsKICAgICAgICAgICAgICBvcHRpb25zLndhbGwgPSBmYWxzZTsKICAgICAgICAgICAgICB0b3BBbmRCb3R0b20uZ2VvbWV0cnkgPSBjb21wdXRlQXR0cmlidXRlcyhvcHRpb25zKTsKICAgICAgICAgICAgICBnZW9tZXRyaWVzLnB1c2godG9wQW5kQm90dG9tKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCB3YWxscyA9IHNwbGl0R2VvbWV0cnkud2FsbHM7CiAgICAgICAgICAgIG9wdGlvbnMud2FsbCA9IHRydWU7CiAgICAgICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgd2FsbHMubGVuZ3RoOyBrKyspIHsKICAgICAgICAgICAgICBjb25zdCB3YWxsID0gd2FsbHNba107CiAgICAgICAgICAgICAgb3B0aW9ucy5nZW9tZXRyeSA9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5zY2FsZVRvR2VvZGV0aWNIZWlnaHRFeHRydWRlZCgKICAgICAgICAgICAgICAgIHdhbGwuZ2VvbWV0cnksCiAgICAgICAgICAgICAgICBoZWlnaHQsCiAgICAgICAgICAgICAgICBleHRydWRlZEhlaWdodCwKICAgICAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgICAgIHBlclBvc2l0aW9uSGVpZ2h0CiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICB3YWxsLmdlb21ldHJ5ID0gY29tcHV0ZUF0dHJpYnV0ZXMob3B0aW9ucyk7CiAgICAgICAgICAgICAgZ2VvbWV0cmllcy5wdXNoKHdhbGwpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBwb2x5Z29ucy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBjb25zdCBnZW9tZXRyeUluc3RhbmNlID0gbmV3IEdlb21ldHJ5SW5zdGFuY2VfZGVmYXVsdCh7CiAgICAgICAgICAgICAgZ2VvbWV0cnk6IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeUZyb21Qb3NpdGlvbnMoCiAgICAgICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgICAgICBwb2x5Z29uc1tpXSwKICAgICAgICAgICAgICAgIGhhc1RleHR1cmVDb29yZGluYXRlcyA/IHRleHR1cmVDb29yZGluYXRlUG9seWdvbnNbaV0gOiB2b2lkIDAsCiAgICAgICAgICAgICAgICBncmFudWxhcml0eSwKICAgICAgICAgICAgICAgIHBlclBvc2l0aW9uSGVpZ2h0LAogICAgICAgICAgICAgICAgdmVydGV4Rm9ybWF0LAogICAgICAgICAgICAgICAgYXJjVHlwZQogICAgICAgICAgICAgICkKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGdlb21ldHJ5SW5zdGFuY2UuZ2VvbWV0cnkuYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMgPSBQb2x5Z29uUGlwZWxpbmVfZGVmYXVsdC5zY2FsZVRvR2VvZGV0aWNIZWlnaHQoCiAgICAgICAgICAgICAgZ2VvbWV0cnlJbnN0YW5jZS5nZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcywKICAgICAgICAgICAgICBoZWlnaHQsCiAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgICFwZXJQb3NpdGlvbkhlaWdodAogICAgICAgICAgICApOwogICAgICAgICAgICBvcHRpb25zLmdlb21ldHJ5ID0gZ2VvbWV0cnlJbnN0YW5jZS5nZW9tZXRyeTsKICAgICAgICAgICAgZ2VvbWV0cnlJbnN0YW5jZS5nZW9tZXRyeSA9IGNvbXB1dGVBdHRyaWJ1dGVzKG9wdGlvbnMpOwogICAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHBvbHlnb25HZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlKSkgewogICAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IGdlb21ldHJ5SW5zdGFuY2UuZ2VvbWV0cnkuYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMubGVuZ3RoOwogICAgICAgICAgICAgIGNvbnN0IG9mZnNldFZhbHVlID0gcG9seWdvbkdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuTk9ORSA/IDAgOiAxOwogICAgICAgICAgICAgIGNvbnN0IGFwcGx5T2Zmc2V0ID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoIC8gMykuZmlsbChvZmZzZXRWYWx1ZSk7CiAgICAgICAgICAgICAgZ2VvbWV0cnlJbnN0YW5jZS5nZW9tZXRyeS5hdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuVU5TSUdORURfQllURSwKICAgICAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDEsCiAgICAgICAgICAgICAgICB2YWx1ZXM6IGFwcGx5T2Zmc2V0CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZ2VvbWV0cmllcy5wdXNoKGdlb21ldHJ5SW5zdGFuY2UpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBnZW9tZXRyeSA9IEdlb21ldHJ5UGlwZWxpbmVfZGVmYXVsdC5jb21iaW5lSW5zdGFuY2VzKGdlb21ldHJpZXMpWzBdOwogICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzID0gbmV3IEZsb2F0NjRBcnJheSgKICAgICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzCiAgICAgICAgKTsKICAgICAgICBnZW9tZXRyeS5pbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgICAgICBnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5sZW5ndGggLyAzLAogICAgICAgICAgZ2VvbWV0cnkuaW5kaWNlcwogICAgICAgICk7CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IGdlb21ldHJ5LmF0dHJpYnV0ZXM7CiAgICAgICAgY29uc3QgYm91bmRpbmdTcGhlcmUgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21WZXJ0aWNlcygKICAgICAgICAgIGF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzCiAgICAgICAgKTsKICAgICAgICBpZiAoIXZlcnRleEZvcm1hdC5wb3NpdGlvbikgewogICAgICAgICAgZGVsZXRlIGF0dHJpYnV0ZXMucG9zaXRpb247CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgICAgICBhdHRyaWJ1dGVzLAogICAgICAgICAgaW5kaWNlczogZ2VvbWV0cnkuaW5kaWNlcywKICAgICAgICAgIHByaW1pdGl2ZVR5cGU6IGdlb21ldHJ5LnByaW1pdGl2ZVR5cGUsCiAgICAgICAgICBib3VuZGluZ1NwaGVyZSwKICAgICAgICAgIG9mZnNldEF0dHJpYnV0ZTogcG9seWdvbkdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgUG9seWdvbkdlb21ldHJ5LmNyZWF0ZVNoYWRvd1ZvbHVtZSA9IGZ1bmN0aW9uKHBvbHlnb25HZW9tZXRyeSwgbWluSGVpZ2h0RnVuYywgbWF4SGVpZ2h0RnVuYykgewogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gcG9seWdvbkdlb21ldHJ5Ll9ncmFudWxhcml0eTsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBwb2x5Z29uR2VvbWV0cnkuX2VsbGlwc29pZDsKICAgICAgICBjb25zdCBtaW5IZWlnaHQgPSBtaW5IZWlnaHRGdW5jKGdyYW51bGFyaXR5LCBlbGxpcHNvaWQpOwogICAgICAgIGNvbnN0IG1heEhlaWdodCA9IG1heEhlaWdodEZ1bmMoZ3JhbnVsYXJpdHksIGVsbGlwc29pZCk7CiAgICAgICAgcmV0dXJuIG5ldyBQb2x5Z29uR2VvbWV0cnkoewogICAgICAgICAgcG9seWdvbkhpZXJhcmNoeTogcG9seWdvbkdlb21ldHJ5Ll9wb2x5Z29uSGllcmFyY2h5LAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgc3RSb3RhdGlvbjogcG9seWdvbkdlb21ldHJ5Ll9zdFJvdGF0aW9uLAogICAgICAgICAgZ3JhbnVsYXJpdHksCiAgICAgICAgICBwZXJQb3NpdGlvbkhlaWdodDogZmFsc2UsCiAgICAgICAgICBleHRydWRlZEhlaWdodDogbWluSGVpZ2h0LAogICAgICAgICAgaGVpZ2h0OiBtYXhIZWlnaHQsCiAgICAgICAgICB2ZXJ0ZXhGb3JtYXQ6IFZlcnRleEZvcm1hdF9kZWZhdWx0LlBPU0lUSU9OX09OTFksCiAgICAgICAgICBzaGFkb3dWb2x1bWU6IHRydWUsCiAgICAgICAgICBhcmNUeXBlOiBwb2x5Z29uR2VvbWV0cnkuX2FyY1R5cGUKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoUG9seWdvbkdlb21ldHJ5LnByb3RvdHlwZSwgewogICAgICAgIC8qKgogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgcmVjdGFuZ2xlOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh0aGlzLl9yZWN0YW5nbGUpKSB7CiAgICAgICAgICAgICAgY29uc3QgcG9zaXRpb25zID0gdGhpcy5fcG9seWdvbkhpZXJhcmNoeS5wb3NpdGlvbnM7CiAgICAgICAgICAgICAgdGhpcy5fcmVjdGFuZ2xlID0gUG9seWdvbkdlb21ldHJ5LmNvbXB1dGVSZWN0YW5nbGVGcm9tUG9zaXRpb25zKAogICAgICAgICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgICAgICAgdGhpcy5fZWxsaXBzb2lkLAogICAgICAgICAgICAgICAgdGhpcy5fYXJjVHlwZQogICAgICAgICAgICAgICk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3JlY3RhbmdsZTsKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEZvciByZW1hcHBpbmcgdGV4dHVyZSBjb29yZGluYXRlcyB3aGVuIHJlbmRlcmluZyBQb2x5Z29uR2VvbWV0cmllcyBhcyBHcm91bmRQcmltaXRpdmVzLgogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVSb3RhdGlvblBvaW50czogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQodGhpcy5fdGV4dHVyZUNvb3JkaW5hdGVSb3RhdGlvblBvaW50cykpIHsKICAgICAgICAgICAgICB0aGlzLl90ZXh0dXJlQ29vcmRpbmF0ZVJvdGF0aW9uUG9pbnRzID0gdGV4dHVyZUNvb3JkaW5hdGVSb3RhdGlvblBvaW50czIodGhpcyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3RleHR1cmVDb29yZGluYXRlUm90YXRpb25Qb2ludHM7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgUG9seWdvbkdlb21ldHJ5X2RlZmF1bHQgPSBQb2x5Z29uR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVQb2x5Z29uR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlUG9seWdvbkdlb21ldHJ5X2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChjcmVhdGVQb2x5Z29uR2VvbWV0cnlfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlUG9seWdvbkdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVQb2x5Z29uR2VvbWV0cnkocG9seWdvbkdlb21ldHJ5LCBvZmZzZXQpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob2Zmc2V0KSkgewogICAgICBwb2x5Z29uR2VvbWV0cnkgPSBQb2x5Z29uR2VvbWV0cnlfZGVmYXVsdC51bnBhY2socG9seWdvbkdlb21ldHJ5LCBvZmZzZXQpOwogICAgfQogICAgcG9seWdvbkdlb21ldHJ5Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShwb2x5Z29uR2VvbWV0cnkuX2VsbGlwc29pZCk7CiAgICByZXR1cm4gUG9seWdvbkdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkocG9seWdvbkdlb21ldHJ5KTsKICB9CiAgdmFyIGNyZWF0ZVBvbHlnb25HZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X2NyZWF0ZVBvbHlnb25HZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlUG9seWdvbkdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfUG9seWdvbkdlb21ldHJ5KCk7CiAgICAgIGNyZWF0ZVBvbHlnb25HZW9tZXRyeV9kZWZhdWx0ID0gY3JlYXRlUG9seWdvbkdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUG9seWdvbk91dGxpbmVHZW9tZXRyeS5qcwogIGZ1bmN0aW9uIGNyZWF0ZUdlb21ldHJ5RnJvbVBvc2l0aW9uczIoZWxsaXBzb2lkLCBwb3NpdGlvbnMsIG1pbkRpc3RhbmNlLCBwZXJQb3NpdGlvbkhlaWdodCwgYXJjVHlwZSkgewogICAgY29uc3QgdGFuZ2VudFBsYW5lID0gRWxsaXBzb2lkVGFuZ2VudFBsYW5lX2RlZmF1bHQuZnJvbVBvaW50cyhwb3NpdGlvbnMsIGVsbGlwc29pZCk7CiAgICBjb25zdCBwb3NpdGlvbnMyRCA9IHRhbmdlbnRQbGFuZS5wcm9qZWN0UG9pbnRzT250b1BsYW5lKAogICAgICBwb3NpdGlvbnMsCiAgICAgIGNyZWF0ZUdlb21ldHJ5RnJvbVBvc2l0aW9uc1Bvc2l0aW9ucwogICAgKTsKICAgIGNvbnN0IG9yaWdpbmFsV2luZGluZ09yZGVyID0gUG9seWdvblBpcGVsaW5lX2RlZmF1bHQuY29tcHV0ZVdpbmRpbmdPcmRlcjJEKHBvc2l0aW9uczJEKTsKICAgIGlmIChvcmlnaW5hbFdpbmRpbmdPcmRlciA9PT0gV2luZGluZ09yZGVyX2RlZmF1bHQuQ0xPQ0tXSVNFKSB7CiAgICAgIHBvc2l0aW9uczJELnJldmVyc2UoKTsKICAgICAgcG9zaXRpb25zID0gcG9zaXRpb25zLnNsaWNlKCkucmV2ZXJzZSgpOwogICAgfQogICAgbGV0IHN1YmRpdmlkZWRQb3NpdGlvbnM7CiAgICBsZXQgaTsKICAgIGxldCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgbGV0IGluZGV4ID0gMDsKICAgIGlmICghcGVyUG9zaXRpb25IZWlnaHQpIHsKICAgICAgbGV0IG51bVZlcnRpY2VzID0gMDsKICAgICAgaWYgKGFyY1R5cGUgPT09IEFyY1R5cGVfZGVmYXVsdC5HRU9ERVNJQykgewogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgbnVtVmVydGljZXMgKz0gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LnN1YmRpdmlkZUxpbmVDb3VudCgKICAgICAgICAgICAgcG9zaXRpb25zW2ldLAogICAgICAgICAgICBwb3NpdGlvbnNbKGkgKyAxKSAlIGxlbmd0aF0sCiAgICAgICAgICAgIG1pbkRpc3RhbmNlCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChhcmNUeXBlID09PSBBcmNUeXBlX2RlZmF1bHQuUkhVTUIpIHsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgIG51bVZlcnRpY2VzICs9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5zdWJkaXZpZGVSaHVtYkxpbmVDb3VudCgKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICBwb3NpdGlvbnNbaV0sCiAgICAgICAgICAgIHBvc2l0aW9uc1soaSArIDEpICUgbGVuZ3RoXSwKICAgICAgICAgICAgbWluRGlzdGFuY2UKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KG51bVZlcnRpY2VzICogMyk7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgIGxldCB0ZW1wUG9zaXRpb25zOwogICAgICAgIGlmIChhcmNUeXBlID09PSBBcmNUeXBlX2RlZmF1bHQuR0VPREVTSUMpIHsKICAgICAgICAgIHRlbXBQb3NpdGlvbnMgPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuc3ViZGl2aWRlTGluZSgKICAgICAgICAgICAgcG9zaXRpb25zW2ldLAogICAgICAgICAgICBwb3NpdGlvbnNbKGkgKyAxKSAlIGxlbmd0aF0sCiAgICAgICAgICAgIG1pbkRpc3RhbmNlLAogICAgICAgICAgICBjcmVhdGVHZW9tZXRyeUZyb21Qb3NpdGlvbnNTdWJkaXZpZGVkCiAgICAgICAgICApOwogICAgICAgIH0gZWxzZSBpZiAoYXJjVHlwZSA9PT0gQXJjVHlwZV9kZWZhdWx0LlJIVU1CKSB7CiAgICAgICAgICB0ZW1wUG9zaXRpb25zID0gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LnN1YmRpdmlkZVJodW1iTGluZSgKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICBwb3NpdGlvbnNbaV0sCiAgICAgICAgICAgIHBvc2l0aW9uc1soaSArIDEpICUgbGVuZ3RoXSwKICAgICAgICAgICAgbWluRGlzdGFuY2UsCiAgICAgICAgICAgIGNyZWF0ZUdlb21ldHJ5RnJvbVBvc2l0aW9uc1N1YmRpdmlkZWQKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHRlbXBQb3NpdGlvbnNMZW5ndGggPSB0ZW1wUG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRlbXBQb3NpdGlvbnNMZW5ndGg7ICsraikgewogICAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9uc1tpbmRleCsrXSA9IHRlbXBQb3NpdGlvbnNbal07CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBzdWJkaXZpZGVkUG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShsZW5ndGggKiAyICogMyk7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgIGNvbnN0IHAwID0gcG9zaXRpb25zW2ldOwogICAgICAgIGNvbnN0IHAxID0gcG9zaXRpb25zWyhpICsgMSkgJSBsZW5ndGhdOwogICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnNbaW5kZXgrK10gPSBwMC54OwogICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnNbaW5kZXgrK10gPSBwMC55OwogICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnNbaW5kZXgrK10gPSBwMC56OwogICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnNbaW5kZXgrK10gPSBwMS54OwogICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnNbaW5kZXgrK10gPSBwMS55OwogICAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnNbaW5kZXgrK10gPSBwMS56OwogICAgICB9CiAgICB9CiAgICBsZW5ndGggPSBzdWJkaXZpZGVkUG9zaXRpb25zLmxlbmd0aCAvIDM7CiAgICBjb25zdCBpbmRpY2VzU2l6ZSA9IGxlbmd0aCAqIDI7CiAgICBjb25zdCBpbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkobGVuZ3RoLCBpbmRpY2VzU2l6ZSk7CiAgICBpbmRleCA9IDA7CiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoIC0gMTsgaSsrKSB7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gaSArIDE7CiAgICB9CiAgICBpbmRpY2VzW2luZGV4KytdID0gbGVuZ3RoIC0gMTsKICAgIGluZGljZXNbaW5kZXgrK10gPSAwOwogICAgcmV0dXJuIG5ldyBHZW9tZXRyeUluc3RhbmNlX2RlZmF1bHQoewogICAgICBnZW9tZXRyeTogbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgIGF0dHJpYnV0ZXM6IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZXNfZGVmYXVsdCh7CiAgICAgICAgICBwb3NpdGlvbjogbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICAgIHZhbHVlczogc3ViZGl2aWRlZFBvc2l0aW9ucwogICAgICAgICAgfSkKICAgICAgICB9KSwKICAgICAgICBpbmRpY2VzLAogICAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5MSU5FUwogICAgICB9KQogICAgfSk7CiAgfQogIGZ1bmN0aW9uIGNyZWF0ZUdlb21ldHJ5RnJvbVBvc2l0aW9uc0V4dHJ1ZGVkMihlbGxpcHNvaWQsIHBvc2l0aW9ucywgbWluRGlzdGFuY2UsIHBlclBvc2l0aW9uSGVpZ2h0LCBhcmNUeXBlKSB7CiAgICBjb25zdCB0YW5nZW50UGxhbmUgPSBFbGxpcHNvaWRUYW5nZW50UGxhbmVfZGVmYXVsdC5mcm9tUG9pbnRzKHBvc2l0aW9ucywgZWxsaXBzb2lkKTsKICAgIGNvbnN0IHBvc2l0aW9uczJEID0gdGFuZ2VudFBsYW5lLnByb2plY3RQb2ludHNPbnRvUGxhbmUoCiAgICAgIHBvc2l0aW9ucywKICAgICAgY3JlYXRlR2VvbWV0cnlGcm9tUG9zaXRpb25zUG9zaXRpb25zCiAgICApOwogICAgY29uc3Qgb3JpZ2luYWxXaW5kaW5nT3JkZXIgPSBQb2x5Z29uUGlwZWxpbmVfZGVmYXVsdC5jb21wdXRlV2luZGluZ09yZGVyMkQocG9zaXRpb25zMkQpOwogICAgaWYgKG9yaWdpbmFsV2luZGluZ09yZGVyID09PSBXaW5kaW5nT3JkZXJfZGVmYXVsdC5DTE9DS1dJU0UpIHsKICAgICAgcG9zaXRpb25zMkQucmV2ZXJzZSgpOwogICAgICBwb3NpdGlvbnMgPSBwb3NpdGlvbnMuc2xpY2UoKS5yZXZlcnNlKCk7CiAgICB9CiAgICBsZXQgc3ViZGl2aWRlZFBvc2l0aW9uczsKICAgIGxldCBpOwogICAgbGV0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICBjb25zdCBjb3JuZXJzID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICBsZXQgaW5kZXggPSAwOwogICAgaWYgKCFwZXJQb3NpdGlvbkhlaWdodCkgewogICAgICBsZXQgbnVtVmVydGljZXMgPSAwOwogICAgICBpZiAoYXJjVHlwZSA9PT0gQXJjVHlwZV9kZWZhdWx0LkdFT0RFU0lDKSB7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBudW1WZXJ0aWNlcyArPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuc3ViZGl2aWRlTGluZUNvdW50KAogICAgICAgICAgICBwb3NpdGlvbnNbaV0sCiAgICAgICAgICAgIHBvc2l0aW9uc1soaSArIDEpICUgbGVuZ3RoXSwKICAgICAgICAgICAgbWluRGlzdGFuY2UKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGFyY1R5cGUgPT09IEFyY1R5cGVfZGVmYXVsdC5SSFVNQikgewogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgbnVtVmVydGljZXMgKz0gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LnN1YmRpdmlkZVJodW1iTGluZUNvdW50KAogICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgIHBvc2l0aW9uc1tpXSwKICAgICAgICAgICAgcG9zaXRpb25zWyhpICsgMSkgJSBsZW5ndGhdLAogICAgICAgICAgICBtaW5EaXN0YW5jZQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgc3ViZGl2aWRlZFBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkobnVtVmVydGljZXMgKiAzICogMik7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgIGNvcm5lcnNbaV0gPSBpbmRleCAvIDM7CiAgICAgICAgbGV0IHRlbXBQb3NpdGlvbnM7CiAgICAgICAgaWYgKGFyY1R5cGUgPT09IEFyY1R5cGVfZGVmYXVsdC5HRU9ERVNJQykgewogICAgICAgICAgdGVtcFBvc2l0aW9ucyA9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5zdWJkaXZpZGVMaW5lKAogICAgICAgICAgICBwb3NpdGlvbnNbaV0sCiAgICAgICAgICAgIHBvc2l0aW9uc1soaSArIDEpICUgbGVuZ3RoXSwKICAgICAgICAgICAgbWluRGlzdGFuY2UsCiAgICAgICAgICAgIGNyZWF0ZUdlb21ldHJ5RnJvbVBvc2l0aW9uc1N1YmRpdmlkZWQKICAgICAgICAgICk7CiAgICAgICAgfSBlbHNlIGlmIChhcmNUeXBlID09PSBBcmNUeXBlX2RlZmF1bHQuUkhVTUIpIHsKICAgICAgICAgIHRlbXBQb3NpdGlvbnMgPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuc3ViZGl2aWRlUmh1bWJMaW5lKAogICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgIHBvc2l0aW9uc1tpXSwKICAgICAgICAgICAgcG9zaXRpb25zWyhpICsgMSkgJSBsZW5ndGhdLAogICAgICAgICAgICBtaW5EaXN0YW5jZSwKICAgICAgICAgICAgY3JlYXRlR2VvbWV0cnlGcm9tUG9zaXRpb25zU3ViZGl2aWRlZAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgdGVtcFBvc2l0aW9uc0xlbmd0aCA9IHRlbXBQb3NpdGlvbnMubGVuZ3RoOwogICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGVtcFBvc2l0aW9uc0xlbmd0aDsgKytqKSB7CiAgICAgICAgICBzdWJkaXZpZGVkUG9zaXRpb25zW2luZGV4KytdID0gdGVtcFBvc2l0aW9uc1tqXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHN1YmRpdmlkZWRQb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KGxlbmd0aCAqIDIgKiAzICogMik7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgIGNvcm5lcnNbaV0gPSBpbmRleCAvIDM7CiAgICAgICAgY29uc3QgcDAgPSBwb3NpdGlvbnNbaV07CiAgICAgICAgY29uc3QgcDEgPSBwb3NpdGlvbnNbKGkgKyAxKSAlIGxlbmd0aF07CiAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9uc1tpbmRleCsrXSA9IHAwLng7CiAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9uc1tpbmRleCsrXSA9IHAwLnk7CiAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9uc1tpbmRleCsrXSA9IHAwLno7CiAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9uc1tpbmRleCsrXSA9IHAxLng7CiAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9uc1tpbmRleCsrXSA9IHAxLnk7CiAgICAgICAgc3ViZGl2aWRlZFBvc2l0aW9uc1tpbmRleCsrXSA9IHAxLno7CiAgICAgIH0KICAgIH0KICAgIGxlbmd0aCA9IHN1YmRpdmlkZWRQb3NpdGlvbnMubGVuZ3RoIC8gKDMgKiAyKTsKICAgIGNvbnN0IGNvcm5lcnNMZW5ndGggPSBjb3JuZXJzLmxlbmd0aDsKICAgIGNvbnN0IGluZGljZXNTaXplID0gKGxlbmd0aCAqIDIgKyBjb3JuZXJzTGVuZ3RoKSAqIDI7CiAgICBjb25zdCBpbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgIGxlbmd0aCArIGNvcm5lcnNMZW5ndGgsCiAgICAgIGluZGljZXNTaXplCiAgICApOwogICAgaW5kZXggPSAwOwogICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gKGkgKyAxKSAlIGxlbmd0aDsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGkgKyBsZW5ndGg7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSAoaSArIDEpICUgbGVuZ3RoICsgbGVuZ3RoOwogICAgfQogICAgZm9yIChpID0gMDsgaSA8IGNvcm5lcnNMZW5ndGg7IGkrKykgewogICAgICBjb25zdCBjb3JuZXIgPSBjb3JuZXJzW2ldOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gY29ybmVyOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gY29ybmVyICsgbGVuZ3RoOwogICAgfQogICAgcmV0dXJuIG5ldyBHZW9tZXRyeUluc3RhbmNlX2RlZmF1bHQoewogICAgICBnZW9tZXRyeTogbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgIGF0dHJpYnV0ZXM6IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZXNfZGVmYXVsdCh7CiAgICAgICAgICBwb3NpdGlvbjogbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICAgIHZhbHVlczogc3ViZGl2aWRlZFBvc2l0aW9ucwogICAgICAgICAgfSkKICAgICAgICB9KSwKICAgICAgICBpbmRpY2VzLAogICAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5MSU5FUwogICAgICB9KQogICAgfSk7CiAgfQogIGZ1bmN0aW9uIFBvbHlnb25PdXRsaW5lR2VvbWV0cnkob3B0aW9ucykgewogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJvcHRpb25zIiwgb3B0aW9ucyk7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoIm9wdGlvbnMucG9seWdvbkhpZXJhcmNoeSIsIG9wdGlvbnMucG9seWdvbkhpZXJhcmNoeSk7CiAgICBpZiAob3B0aW9ucy5wZXJQb3NpdGlvbkhlaWdodCAmJiBkZWZpbmVkX2RlZmF1bHQob3B0aW9ucy5oZWlnaHQpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICJDYW5ub3QgdXNlIGJvdGggb3B0aW9ucy5wZXJQb3NpdGlvbkhlaWdodCBhbmQgb3B0aW9ucy5oZWlnaHQiCiAgICAgICk7CiAgICB9CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMuYXJjVHlwZSkgJiYgb3B0aW9ucy5hcmNUeXBlICE9PSBBcmNUeXBlX2RlZmF1bHQuR0VPREVTSUMgJiYgb3B0aW9ucy5hcmNUeXBlICE9PSBBcmNUeXBlX2RlZmF1bHQuUkhVTUIpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgIkludmFsaWQgYXJjVHlwZS4gVmFsaWQgb3B0aW9ucyBhcmUgQXJjVHlwZS5HRU9ERVNJQyBhbmQgQXJjVHlwZS5SSFVNQi4iCiAgICAgICk7CiAgICB9CiAgICBjb25zdCBwb2x5Z29uSGllcmFyY2h5ID0gb3B0aW9ucy5wb2x5Z29uSGllcmFyY2h5OwogICAgY29uc3QgZWxsaXBzb2lkID0gb3B0aW9ucy5lbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gb3B0aW9ucy5ncmFudWxhcml0eSA/PyBNYXRoX2RlZmF1bHQuUkFESUFOU19QRVJfREVHUkVFOwogICAgY29uc3QgcGVyUG9zaXRpb25IZWlnaHQgPSBvcHRpb25zLnBlclBvc2l0aW9uSGVpZ2h0ID8/IGZhbHNlOwogICAgY29uc3QgcGVyUG9zaXRpb25IZWlnaHRFeHRydWRlID0gcGVyUG9zaXRpb25IZWlnaHQgJiYgZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMuZXh0cnVkZWRIZWlnaHQpOwogICAgY29uc3QgYXJjVHlwZSA9IG9wdGlvbnMuYXJjVHlwZSA/PyBBcmNUeXBlX2RlZmF1bHQuR0VPREVTSUM7CiAgICBsZXQgaGVpZ2h0ID0gb3B0aW9ucy5oZWlnaHQgPz8gMDsKICAgIGxldCBleHRydWRlZEhlaWdodCA9IG9wdGlvbnMuZXh0cnVkZWRIZWlnaHQgPz8gaGVpZ2h0OwogICAgaWYgKCFwZXJQb3NpdGlvbkhlaWdodEV4dHJ1ZGUpIHsKICAgICAgY29uc3QgaCA9IE1hdGgubWF4KGhlaWdodCwgZXh0cnVkZWRIZWlnaHQpOwogICAgICBleHRydWRlZEhlaWdodCA9IE1hdGgubWluKGhlaWdodCwgZXh0cnVkZWRIZWlnaHQpOwogICAgICBoZWlnaHQgPSBoOwogICAgfQogICAgdGhpcy5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoZWxsaXBzb2lkKTsKICAgIHRoaXMuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICB0aGlzLl9oZWlnaHQgPSBoZWlnaHQ7CiAgICB0aGlzLl9leHRydWRlZEhlaWdodCA9IGV4dHJ1ZGVkSGVpZ2h0OwogICAgdGhpcy5fYXJjVHlwZSA9IGFyY1R5cGU7CiAgICB0aGlzLl9wb2x5Z29uSGllcmFyY2h5ID0gcG9seWdvbkhpZXJhcmNoeTsKICAgIHRoaXMuX3BlclBvc2l0aW9uSGVpZ2h0ID0gcGVyUG9zaXRpb25IZWlnaHQ7CiAgICB0aGlzLl9wZXJQb3NpdGlvbkhlaWdodEV4dHJ1ZGUgPSBwZXJQb3NpdGlvbkhlaWdodEV4dHJ1ZGU7CiAgICB0aGlzLl9vZmZzZXRBdHRyaWJ1dGUgPSBvcHRpb25zLm9mZnNldEF0dHJpYnV0ZTsKICAgIHRoaXMuX3dvcmtlck5hbWUgPSAiY3JlYXRlUG9seWdvbk91dGxpbmVHZW9tZXRyeSI7CiAgICB0aGlzLnBhY2tlZExlbmd0aCA9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlSGllcmFyY2h5UGFja2VkTGVuZ3RoKAogICAgICBwb2x5Z29uSGllcmFyY2h5LAogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQKICAgICkgKyBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyA4OwogIH0KICB2YXIgY3JlYXRlR2VvbWV0cnlGcm9tUG9zaXRpb25zUG9zaXRpb25zLCBjcmVhdGVHZW9tZXRyeUZyb21Qb3NpdGlvbnNTdWJkaXZpZGVkLCBzY3JhdGNoRWxsaXBzb2lkNywgZHVtbXlPcHRpb25zMiwgUG9seWdvbk91dGxpbmVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X1BvbHlnb25PdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1BvbHlnb25PdXRsaW5lR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0FyY1R5cGUoKTsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X0NvbXBvbmVudERhdGF0eXBlKCk7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkVGFuZ2VudFBsYW5lKCk7CiAgICAgIGluaXRfR2VvbWV0cnkoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlcygpOwogICAgICBpbml0X0dlb21ldHJ5SW5zdGFuY2UoKTsKICAgICAgaW5pdF9HZW9tZXRyeU9mZnNldEF0dHJpYnV0ZSgpOwogICAgICBpbml0X0dlb21ldHJ5UGlwZWxpbmUoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1BvbHlnb25HZW9tZXRyeUxpYnJhcnkoKTsKICAgICAgaW5pdF9Qb2x5Z29uUGlwZWxpbmUoKTsKICAgICAgaW5pdF9QcmltaXRpdmVUeXBlKCk7CiAgICAgIGluaXRfV2luZGluZ09yZGVyKCk7CiAgICAgIGNyZWF0ZUdlb21ldHJ5RnJvbVBvc2l0aW9uc1Bvc2l0aW9ucyA9IFtdOwogICAgICBjcmVhdGVHZW9tZXRyeUZyb21Qb3NpdGlvbnNTdWJkaXZpZGVkID0gW107CiAgICAgIFBvbHlnb25PdXRsaW5lR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBQb2x5Z29uR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQucGFja1BvbHlnb25IaWVyYXJjaHkoCiAgICAgICAgICB2YWx1ZS5fcG9seWdvbkhpZXJhcmNoeSwKICAgICAgICAgIGFycmF5LAogICAgICAgICAgc3RhcnRpbmdJbmRleCwKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdAogICAgICAgICk7CiAgICAgICAgRWxsaXBzb2lkX2RlZmF1bHQucGFjayh2YWx1ZS5fZWxsaXBzb2lkLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9oZWlnaHQ7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9leHRydWRlZEhlaWdodDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2dyYW51bGFyaXR5OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fcGVyUG9zaXRpb25IZWlnaHRFeHRydWRlID8gMSA6IDA7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9wZXJQb3NpdGlvbkhlaWdodCA/IDEgOiAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fYXJjVHlwZTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX29mZnNldEF0dHJpYnV0ZSA/PyAtMTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLnBhY2tlZExlbmd0aDsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hFbGxpcHNvaWQ3ID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoRWxsaXBzb2lkX2RlZmF1bHQuVU5JVF9TUEhFUkUpOwogICAgICBkdW1teU9wdGlvbnMyID0gewogICAgICAgIHBvbHlnb25IaWVyYXJjaHk6IHt9CiAgICAgIH07CiAgICAgIFBvbHlnb25PdXRsaW5lR2VvbWV0cnkudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBjb25zdCBwb2x5Z29uSGllcmFyY2h5ID0gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LnVucGFja1BvbHlnb25IaWVyYXJjaHkoCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQKICAgICAgICApOwogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBwb2x5Z29uSGllcmFyY2h5LnN0YXJ0aW5nSW5kZXg7CiAgICAgICAgZGVsZXRlIHBvbHlnb25IaWVyYXJjaHkuc3RhcnRpbmdJbmRleDsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHNjcmF0Y2hFbGxpcHNvaWQ3KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCBoZWlnaHQgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IGV4dHJ1ZGVkSGVpZ2h0ID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgcGVyUG9zaXRpb25IZWlnaHRFeHRydWRlID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9PT0gMTsKICAgICAgICBjb25zdCBwZXJQb3NpdGlvbkhlaWdodCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPT09IDE7CiAgICAgICAgY29uc3QgYXJjVHlwZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3Qgb2Zmc2V0QXR0cmlidXRlID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBwYWNrZWRMZW5ndGggPSBhcnJheVtzdGFydGluZ0luZGV4XTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgUG9seWdvbk91dGxpbmVHZW9tZXRyeShkdW1teU9wdGlvbnMyKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0Ll9wb2x5Z29uSGllcmFyY2h5ID0gcG9seWdvbkhpZXJhcmNoeTsKICAgICAgICByZXN1bHQuX2VsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKGVsbGlwc29pZCwgcmVzdWx0Ll9lbGxpcHNvaWQpOwogICAgICAgIHJlc3VsdC5faGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgIHJlc3VsdC5fZXh0cnVkZWRIZWlnaHQgPSBleHRydWRlZEhlaWdodDsKICAgICAgICByZXN1bHQuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICAgICAgcmVzdWx0Ll9wZXJQb3NpdGlvbkhlaWdodCA9IHBlclBvc2l0aW9uSGVpZ2h0OwogICAgICAgIHJlc3VsdC5fcGVyUG9zaXRpb25IZWlnaHRFeHRydWRlID0gcGVyUG9zaXRpb25IZWlnaHRFeHRydWRlOwogICAgICAgIHJlc3VsdC5fYXJjVHlwZSA9IGFyY1R5cGU7CiAgICAgICAgcmVzdWx0Ll9vZmZzZXRBdHRyaWJ1dGUgPSBvZmZzZXRBdHRyaWJ1dGUgPT09IC0xID8gdm9pZCAwIDogb2Zmc2V0QXR0cmlidXRlOwogICAgICAgIHJlc3VsdC5wYWNrZWRMZW5ndGggPSBwYWNrZWRMZW5ndGg7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgUG9seWdvbk91dGxpbmVHZW9tZXRyeS5mcm9tUG9zaXRpb25zID0gZnVuY3Rpb24ob3B0aW9ucykgewogICAgICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgICAgICBDaGVja19kZWZhdWx0LmRlZmluZWQoIm9wdGlvbnMucG9zaXRpb25zIiwgb3B0aW9ucy5wb3NpdGlvbnMpOwogICAgICAgIGNvbnN0IG5ld09wdGlvbnMgPSB7CiAgICAgICAgICBwb2x5Z29uSGllcmFyY2h5OiB7CiAgICAgICAgICAgIHBvc2l0aW9uczogb3B0aW9ucy5wb3NpdGlvbnMKICAgICAgICAgIH0sCiAgICAgICAgICBoZWlnaHQ6IG9wdGlvbnMuaGVpZ2h0LAogICAgICAgICAgZXh0cnVkZWRIZWlnaHQ6IG9wdGlvbnMuZXh0cnVkZWRIZWlnaHQsCiAgICAgICAgICBlbGxpcHNvaWQ6IG9wdGlvbnMuZWxsaXBzb2lkLAogICAgICAgICAgZ3JhbnVsYXJpdHk6IG9wdGlvbnMuZ3JhbnVsYXJpdHksCiAgICAgICAgICBwZXJQb3NpdGlvbkhlaWdodDogb3B0aW9ucy5wZXJQb3NpdGlvbkhlaWdodCwKICAgICAgICAgIGFyY1R5cGU6IG9wdGlvbnMuYXJjVHlwZSwKICAgICAgICAgIG9mZnNldEF0dHJpYnV0ZTogb3B0aW9ucy5vZmZzZXRBdHRyaWJ1dGUKICAgICAgICB9OwogICAgICAgIHJldHVybiBuZXcgUG9seWdvbk91dGxpbmVHZW9tZXRyeShuZXdPcHRpb25zKTsKICAgICAgfTsKICAgICAgUG9seWdvbk91dGxpbmVHZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKHBvbHlnb25HZW9tZXRyeSkgewogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IHBvbHlnb25HZW9tZXRyeS5fZWxsaXBzb2lkOwogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gcG9seWdvbkdlb21ldHJ5Ll9ncmFudWxhcml0eTsKICAgICAgICBjb25zdCBwb2x5Z29uSGllcmFyY2h5ID0gcG9seWdvbkdlb21ldHJ5Ll9wb2x5Z29uSGllcmFyY2h5OwogICAgICAgIGNvbnN0IHBlclBvc2l0aW9uSGVpZ2h0ID0gcG9seWdvbkdlb21ldHJ5Ll9wZXJQb3NpdGlvbkhlaWdodDsKICAgICAgICBjb25zdCBhcmNUeXBlID0gcG9seWdvbkdlb21ldHJ5Ll9hcmNUeXBlOwogICAgICAgIGNvbnN0IHBvbHlnb25zID0gUG9seWdvbkdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LnBvbHlnb25PdXRsaW5lc0Zyb21IaWVyYXJjaHkoCiAgICAgICAgICBwb2x5Z29uSGllcmFyY2h5LAogICAgICAgICAgIXBlclBvc2l0aW9uSGVpZ2h0LAogICAgICAgICAgZWxsaXBzb2lkCiAgICAgICAgKTsKICAgICAgICBpZiAocG9seWdvbnMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBsZXQgZ2VvbWV0cnlJbnN0YW5jZTsKICAgICAgICBjb25zdCBnZW9tZXRyaWVzID0gW107CiAgICAgICAgY29uc3QgbWluRGlzdGFuY2UgPSBNYXRoX2RlZmF1bHQuY2hvcmRMZW5ndGgoCiAgICAgICAgICBncmFudWxhcml0eSwKICAgICAgICAgIGVsbGlwc29pZC5tYXhpbXVtUmFkaXVzCiAgICAgICAgKTsKICAgICAgICBjb25zdCBoZWlnaHQgPSBwb2x5Z29uR2VvbWV0cnkuX2hlaWdodDsKICAgICAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IHBvbHlnb25HZW9tZXRyeS5fZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgY29uc3QgZXh0cnVkZSA9IHBvbHlnb25HZW9tZXRyeS5fcGVyUG9zaXRpb25IZWlnaHRFeHRydWRlIHx8ICFNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihoZWlnaHQsIGV4dHJ1ZGVkSGVpZ2h0LCAwLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjIpOwogICAgICAgIGxldCBvZmZzZXRWYWx1ZTsKICAgICAgICBsZXQgaTsKICAgICAgICBpZiAoZXh0cnVkZSkgewogICAgICAgICAgZm9yIChpID0gMDsgaSA8IHBvbHlnb25zLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGdlb21ldHJ5SW5zdGFuY2UgPSBjcmVhdGVHZW9tZXRyeUZyb21Qb3NpdGlvbnNFeHRydWRlZDIoCiAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgIHBvbHlnb25zW2ldLAogICAgICAgICAgICAgIG1pbkRpc3RhbmNlLAogICAgICAgICAgICAgIHBlclBvc2l0aW9uSGVpZ2h0LAogICAgICAgICAgICAgIGFyY1R5cGUKICAgICAgICAgICAgKTsKICAgICAgICAgICAgZ2VvbWV0cnlJbnN0YW5jZS5nZW9tZXRyeSA9IFBvbHlnb25HZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5zY2FsZVRvR2VvZGV0aWNIZWlnaHRFeHRydWRlZCgKICAgICAgICAgICAgICBnZW9tZXRyeUluc3RhbmNlLmdlb21ldHJ5LAogICAgICAgICAgICAgIGhlaWdodCwKICAgICAgICAgICAgICBleHRydWRlZEhlaWdodCwKICAgICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgICAgcGVyUG9zaXRpb25IZWlnaHQKICAgICAgICAgICAgKTsKICAgICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChwb2x5Z29uR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZSkpIHsKICAgICAgICAgICAgICBjb25zdCBzaXplID0gZ2VvbWV0cnlJbnN0YW5jZS5nZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5sZW5ndGggLyAzOwogICAgICAgICAgICAgIGxldCBvZmZzZXRBdHRyaWJ1dGUgPSBuZXcgVWludDhBcnJheShzaXplKTsKICAgICAgICAgICAgICBpZiAocG9seWdvbkdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuVE9QKSB7CiAgICAgICAgICAgICAgICBvZmZzZXRBdHRyaWJ1dGUgPSBvZmZzZXRBdHRyaWJ1dGUuZmlsbCgxLCAwLCBzaXplIC8gMik7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIG9mZnNldFZhbHVlID0gcG9seWdvbkdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuTk9ORSA/IDAgOiAxOwogICAgICAgICAgICAgICAgb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlLmZpbGwob2Zmc2V0VmFsdWUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBnZW9tZXRyeUluc3RhbmNlLmdlb21ldHJ5LmF0dHJpYnV0ZXMuYXBwbHlPZmZzZXQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9CWVRFLAogICAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMSwKICAgICAgICAgICAgICAgIHZhbHVlczogb2Zmc2V0QXR0cmlidXRlCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZ2VvbWV0cmllcy5wdXNoKGdlb21ldHJ5SW5zdGFuY2UpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcG9seWdvbnMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgZ2VvbWV0cnlJbnN0YW5jZSA9IGNyZWF0ZUdlb21ldHJ5RnJvbVBvc2l0aW9uczIoCiAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgIHBvbHlnb25zW2ldLAogICAgICAgICAgICAgIG1pbkRpc3RhbmNlLAogICAgICAgICAgICAgIHBlclBvc2l0aW9uSGVpZ2h0LAogICAgICAgICAgICAgIGFyY1R5cGUKICAgICAgICAgICAgKTsKICAgICAgICAgICAgZ2VvbWV0cnlJbnN0YW5jZS5nZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcyA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LnNjYWxlVG9HZW9kZXRpY0hlaWdodCgKICAgICAgICAgICAgICBnZW9tZXRyeUluc3RhbmNlLmdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLAogICAgICAgICAgICAgIGhlaWdodCwKICAgICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgICAgIXBlclBvc2l0aW9uSGVpZ2h0CiAgICAgICAgICAgICk7CiAgICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocG9seWdvbkdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUpKSB7CiAgICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gZ2VvbWV0cnlJbnN0YW5jZS5nZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcy5sZW5ndGg7CiAgICAgICAgICAgICAgb2Zmc2V0VmFsdWUgPSBwb2x5Z29uR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5OT05FID8gMCA6IDE7CiAgICAgICAgICAgICAgY29uc3QgYXBwbHlPZmZzZXQgPSBuZXcgVWludDhBcnJheShsZW5ndGggLyAzKS5maWxsKG9mZnNldFZhbHVlKTsKICAgICAgICAgICAgICBnZW9tZXRyeUluc3RhbmNlLmdlb21ldHJ5LmF0dHJpYnV0ZXMuYXBwbHlPZmZzZXQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9CWVRFLAogICAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMSwKICAgICAgICAgICAgICAgIHZhbHVlczogYXBwbHlPZmZzZXQKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBnZW9tZXRyaWVzLnB1c2goZ2VvbWV0cnlJbnN0YW5jZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IGdlb21ldHJ5ID0gR2VvbWV0cnlQaXBlbGluZV9kZWZhdWx0LmNvbWJpbmVJbnN0YW5jZXMoZ2VvbWV0cmllcylbMF07CiAgICAgICAgY29uc3QgYm91bmRpbmdTcGhlcmUgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21WZXJ0aWNlcygKICAgICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgICAgYXR0cmlidXRlczogZ2VvbWV0cnkuYXR0cmlidXRlcywKICAgICAgICAgIGluZGljZXM6IGdlb21ldHJ5LmluZGljZXMsCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBnZW9tZXRyeS5wcmltaXRpdmVUeXBlLAogICAgICAgICAgYm91bmRpbmdTcGhlcmUsCiAgICAgICAgICBvZmZzZXRBdHRyaWJ1dGU6IHBvbHlnb25HZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIFBvbHlnb25PdXRsaW5lR2VvbWV0cnlfZGVmYXVsdCA9IFBvbHlnb25PdXRsaW5lR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVQb2x5Z29uT3V0bGluZUdlb21ldHJ5LmpzCiAgdmFyIGNyZWF0ZVBvbHlnb25PdXRsaW5lR2VvbWV0cnlfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZVBvbHlnb25PdXRsaW5lR2VvbWV0cnlfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlUG9seWdvbk91dGxpbmVHZW9tZXRyeV9kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gY3JlYXRlUG9seWdvbk91dGxpbmVHZW9tZXRyeShwb2x5Z29uR2VvbWV0cnksIG9mZnNldCkgewogICAgaWYgKGRlZmluZWRfZGVmYXVsdChvZmZzZXQpKSB7CiAgICAgIHBvbHlnb25HZW9tZXRyeSA9IFBvbHlnb25PdXRsaW5lR2VvbWV0cnlfZGVmYXVsdC51bnBhY2socG9seWdvbkdlb21ldHJ5LCBvZmZzZXQpOwogICAgfQogICAgcG9seWdvbkdlb21ldHJ5Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShwb2x5Z29uR2VvbWV0cnkuX2VsbGlwc29pZCk7CiAgICByZXR1cm4gUG9seWdvbk91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LmNyZWF0ZUdlb21ldHJ5KHBvbHlnb25HZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVQb2x5Z29uT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlUG9seWdvbk91dGxpbmVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlUG9seWdvbk91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X1BvbHlnb25PdXRsaW5lR2VvbWV0cnkoKTsKICAgICAgY3JlYXRlUG9seWdvbk91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gY3JlYXRlUG9seWdvbk91dGxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NvbG9yLmpzCiAgZnVuY3Rpb24gaHVlMnJnYihtMSwgbTIsIGgpIHsKICAgIGlmIChoIDwgMCkgewogICAgICBoICs9IDE7CiAgICB9CiAgICBpZiAoaCA+IDEpIHsKICAgICAgaCAtPSAxOwogICAgfQogICAgaWYgKGggKiA2IDwgMSkgewogICAgICByZXR1cm4gbTEgKyAobTIgLSBtMSkgKiA2ICogaDsKICAgIH0KICAgIGlmIChoICogMiA8IDEpIHsKICAgICAgcmV0dXJuIG0yOwogICAgfQogICAgaWYgKGggKiAzIDwgMikgewogICAgICByZXR1cm4gbTEgKyAobTIgLSBtMSkgKiAoMiAvIDMgLSBoKSAqIDY7CiAgICB9CiAgICByZXR1cm4gbTE7CiAgfQogIGZ1bmN0aW9uIENvbG9yKHJlZCwgZ3JlZW4sIGJsdWUsIGFscGhhKSB7CiAgICB0aGlzLnJlZCA9IHJlZCA/PyAxOwogICAgdGhpcy5ncmVlbiA9IGdyZWVuID8/IDE7CiAgICB0aGlzLmJsdWUgPSBibHVlID8/IDE7CiAgICB0aGlzLmFscGhhID0gYWxwaGEgPz8gMTsKICB9CiAgdmFyIHNjcmF0Y2hBcnJheUJ1ZmZlciwgc2NyYXRjaFVpbnQzMkFycmF5LCBzY3JhdGNoVWludDhBcnJheSwgcmdiYU1hdGNoZXIsIHJyZ2diYmFhTWF0Y2hlciwgcmdiUGFyZW50aGVzZXNNYXRjaGVyLCBoc2xQYXJlbnRoZXNlc01hdGNoZXIsIENvbG9yX2RlZmF1bHQ7CiAgdmFyIGluaXRfQ29sb3IgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0NvbG9yLmpzIigpIHsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9GZWF0dXJlRGV0ZWN0aW9uKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBDb2xvci5mcm9tQ2FydGVzaWFuNCA9IGZ1bmN0aW9uKGNhcnRlc2lhbjExLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImNhcnRlc2lhbiIsIGNhcnRlc2lhbjExKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gbmV3IENvbG9yKGNhcnRlc2lhbjExLngsIGNhcnRlc2lhbjExLnksIGNhcnRlc2lhbjExLnosIGNhcnRlc2lhbjExLncpOwogICAgICAgIH0KICAgICAgICByZXN1bHQucmVkID0gY2FydGVzaWFuMTEueDsKICAgICAgICByZXN1bHQuZ3JlZW4gPSBjYXJ0ZXNpYW4xMS55OwogICAgICAgIHJlc3VsdC5ibHVlID0gY2FydGVzaWFuMTEuejsKICAgICAgICByZXN1bHQuYWxwaGEgPSBjYXJ0ZXNpYW4xMS53OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENvbG9yLmZyb21CeXRlcyA9IGZ1bmN0aW9uKHJlZCwgZ3JlZW4sIGJsdWUsIGFscGhhLCByZXN1bHQpIHsKICAgICAgICByZWQgPSBDb2xvci5ieXRlVG9GbG9hdChyZWQgPz8gMjU1KTsKICAgICAgICBncmVlbiA9IENvbG9yLmJ5dGVUb0Zsb2F0KGdyZWVuID8/IDI1NSk7CiAgICAgICAgYmx1ZSA9IENvbG9yLmJ5dGVUb0Zsb2F0KGJsdWUgPz8gMjU1KTsKICAgICAgICBhbHBoYSA9IENvbG9yLmJ5dGVUb0Zsb2F0KGFscGhhID8/IDI1NSk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBDb2xvcihyZWQsIGdyZWVuLCBibHVlLCBhbHBoYSk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5yZWQgPSByZWQ7CiAgICAgICAgcmVzdWx0LmdyZWVuID0gZ3JlZW47CiAgICAgICAgcmVzdWx0LmJsdWUgPSBibHVlOwogICAgICAgIHJlc3VsdC5hbHBoYSA9IGFscGhhOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENvbG9yLmZyb21BbHBoYSA9IGZ1bmN0aW9uKGNvbG9yLCBhbHBoYSwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjb2xvciIsIGNvbG9yKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoImFscGhhIiwgYWxwaGEpOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgQ29sb3IoY29sb3IucmVkLCBjb2xvci5ncmVlbiwgY29sb3IuYmx1ZSwgYWxwaGEpOwogICAgICAgIH0KICAgICAgICByZXN1bHQucmVkID0gY29sb3IucmVkOwogICAgICAgIHJlc3VsdC5ncmVlbiA9IGNvbG9yLmdyZWVuOwogICAgICAgIHJlc3VsdC5ibHVlID0gY29sb3IuYmx1ZTsKICAgICAgICByZXN1bHQuYWxwaGEgPSBhbHBoYTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBpZiAoRmVhdHVyZURldGVjdGlvbl9kZWZhdWx0LnN1cHBvcnRzVHlwZWRBcnJheXMoKSkgewogICAgICAgIHNjcmF0Y2hBcnJheUJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcig0KTsKICAgICAgICBzY3JhdGNoVWludDMyQXJyYXkgPSBuZXcgVWludDMyQXJyYXkoc2NyYXRjaEFycmF5QnVmZmVyKTsKICAgICAgICBzY3JhdGNoVWludDhBcnJheSA9IG5ldyBVaW50OEFycmF5KHNjcmF0Y2hBcnJheUJ1ZmZlcik7CiAgICAgIH0KICAgICAgQ29sb3IuZnJvbVJnYmEgPSBmdW5jdGlvbihyZ2JhLCByZXN1bHQpIHsKICAgICAgICBzY3JhdGNoVWludDMyQXJyYXlbMF0gPSByZ2JhOwogICAgICAgIHJldHVybiBDb2xvci5mcm9tQnl0ZXMoCiAgICAgICAgICBzY3JhdGNoVWludDhBcnJheVswXSwKICAgICAgICAgIHNjcmF0Y2hVaW50OEFycmF5WzFdLAogICAgICAgICAgc2NyYXRjaFVpbnQ4QXJyYXlbMl0sCiAgICAgICAgICBzY3JhdGNoVWludDhBcnJheVszXSwKICAgICAgICAgIHJlc3VsdAogICAgICAgICk7CiAgICAgIH07CiAgICAgIENvbG9yLmZyb21Ic2wgPSBmdW5jdGlvbihodWUsIHNhdHVyYXRpb24sIGxpZ2h0bmVzcywgYWxwaGEsIHJlc3VsdCkgewogICAgICAgIGh1ZSA9IChodWUgPz8gMCkgJSAxOwogICAgICAgIHNhdHVyYXRpb24gPSBzYXR1cmF0aW9uID8/IDA7CiAgICAgICAgbGlnaHRuZXNzID0gbGlnaHRuZXNzID8/IDA7CiAgICAgICAgYWxwaGEgPSBhbHBoYSA/PyAxOwogICAgICAgIGxldCByZWQgPSBsaWdodG5lc3M7CiAgICAgICAgbGV0IGdyZWVuID0gbGlnaHRuZXNzOwogICAgICAgIGxldCBibHVlID0gbGlnaHRuZXNzOwogICAgICAgIGlmIChzYXR1cmF0aW9uICE9PSAwKSB7CiAgICAgICAgICBsZXQgbTI7CiAgICAgICAgICBpZiAobGlnaHRuZXNzIDwgMC41KSB7CiAgICAgICAgICAgIG0yID0gbGlnaHRuZXNzICogKDEgKyBzYXR1cmF0aW9uKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIG0yID0gbGlnaHRuZXNzICsgc2F0dXJhdGlvbiAtIGxpZ2h0bmVzcyAqIHNhdHVyYXRpb247CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBtMSA9IDIgKiBsaWdodG5lc3MgLSBtMjsKICAgICAgICAgIHJlZCA9IGh1ZTJyZ2IobTEsIG0yLCBodWUgKyAxIC8gMyk7CiAgICAgICAgICBncmVlbiA9IGh1ZTJyZ2IobTEsIG0yLCBodWUpOwogICAgICAgICAgYmx1ZSA9IGh1ZTJyZ2IobTEsIG0yLCBodWUgLSAxIC8gMyk7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgQ29sb3IocmVkLCBncmVlbiwgYmx1ZSwgYWxwaGEpOwogICAgICAgIH0KICAgICAgICByZXN1bHQucmVkID0gcmVkOwogICAgICAgIHJlc3VsdC5ncmVlbiA9IGdyZWVuOwogICAgICAgIHJlc3VsdC5ibHVlID0gYmx1ZTsKICAgICAgICByZXN1bHQuYWxwaGEgPSBhbHBoYTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDb2xvci5mcm9tUmFuZG9tID0gZnVuY3Rpb24ob3B0aW9ucywgcmVzdWx0KSB7CiAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgICAgIGxldCByZWQgPSBvcHRpb25zLnJlZDsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZWQpKSB7CiAgICAgICAgICBjb25zdCBtaW5pbXVtUmVkID0gb3B0aW9ucy5taW5pbXVtUmVkID8/IDA7CiAgICAgICAgICBjb25zdCBtYXhpbXVtUmVkID0gb3B0aW9ucy5tYXhpbXVtUmVkID8/IDE7CiAgICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygibWluaW11bVJlZCIsIG1pbmltdW1SZWQsIG1heGltdW1SZWQpOwogICAgICAgICAgcmVkID0gbWluaW11bVJlZCArIE1hdGhfZGVmYXVsdC5uZXh0UmFuZG9tTnVtYmVyKCkgKiAobWF4aW11bVJlZCAtIG1pbmltdW1SZWQpOwogICAgICAgIH0KICAgICAgICBsZXQgZ3JlZW4gPSBvcHRpb25zLmdyZWVuOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGdyZWVuKSkgewogICAgICAgICAgY29uc3QgbWluaW11bUdyZWVuID0gb3B0aW9ucy5taW5pbXVtR3JlZW4gPz8gMDsKICAgICAgICAgIGNvbnN0IG1heGltdW1HcmVlbiA9IG9wdGlvbnMubWF4aW11bUdyZWVuID8/IDE7CiAgICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIubGVzc1RoYW5PckVxdWFscygKICAgICAgICAgICAgIm1pbmltdW1HcmVlbiIsCiAgICAgICAgICAgIG1pbmltdW1HcmVlbiwKICAgICAgICAgICAgbWF4aW11bUdyZWVuCiAgICAgICAgICApOwogICAgICAgICAgZ3JlZW4gPSBtaW5pbXVtR3JlZW4gKyBNYXRoX2RlZmF1bHQubmV4dFJhbmRvbU51bWJlcigpICogKG1heGltdW1HcmVlbiAtIG1pbmltdW1HcmVlbik7CiAgICAgICAgfQogICAgICAgIGxldCBibHVlID0gb3B0aW9ucy5ibHVlOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGJsdWUpKSB7CiAgICAgICAgICBjb25zdCBtaW5pbXVtQmx1ZSA9IG9wdGlvbnMubWluaW11bUJsdWUgPz8gMDsKICAgICAgICAgIGNvbnN0IG1heGltdW1CbHVlID0gb3B0aW9ucy5tYXhpbXVtQmx1ZSA/PyAxOwogICAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmxlc3NUaGFuT3JFcXVhbHMoCiAgICAgICAgICAgICJtaW5pbXVtQmx1ZSIsCiAgICAgICAgICAgIG1pbmltdW1CbHVlLAogICAgICAgICAgICBtYXhpbXVtQmx1ZQogICAgICAgICAgKTsKICAgICAgICAgIGJsdWUgPSBtaW5pbXVtQmx1ZSArIE1hdGhfZGVmYXVsdC5uZXh0UmFuZG9tTnVtYmVyKCkgKiAobWF4aW11bUJsdWUgLSBtaW5pbXVtQmx1ZSk7CiAgICAgICAgfQogICAgICAgIGxldCBhbHBoYSA9IG9wdGlvbnMuYWxwaGE7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYWxwaGEpKSB7CiAgICAgICAgICBjb25zdCBtaW5pbXVtQWxwaGEgPSBvcHRpb25zLm1pbmltdW1BbHBoYSA/PyAwOwogICAgICAgICAgY29uc3QgbWF4aW11bUFscGhhID0gb3B0aW9ucy5tYXhpbXVtQWxwaGEgPz8gMTsKICAgICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlci5sZXNzVGhhbk9yRXF1YWxzKAogICAgICAgICAgICAibWluaW11bUFscGhhIiwKICAgICAgICAgICAgbWluaW11bUFscGhhLAogICAgICAgICAgICBtYXhpbXVtQWxwaGEKICAgICAgICAgICk7CiAgICAgICAgICBhbHBoYSA9IG1pbmltdW1BbHBoYSArIE1hdGhfZGVmYXVsdC5uZXh0UmFuZG9tTnVtYmVyKCkgKiAobWF4aW11bUFscGhhIC0gbWluaW11bUFscGhhKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBDb2xvcihyZWQsIGdyZWVuLCBibHVlLCBhbHBoYSk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5yZWQgPSByZWQ7CiAgICAgICAgcmVzdWx0LmdyZWVuID0gZ3JlZW47CiAgICAgICAgcmVzdWx0LmJsdWUgPSBibHVlOwogICAgICAgIHJlc3VsdC5hbHBoYSA9IGFscGhhOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHJnYmFNYXRjaGVyID0gL14jKFswLTlhLWZdKShbMC05YS1mXSkoWzAtOWEtZl0pKFswLTlhLWZdKT8kL2k7CiAgICAgIHJyZ2diYmFhTWF0Y2hlciA9IC9eIyhbMC05YS1mXXsyfSkoWzAtOWEtZl17Mn0pKFswLTlhLWZdezJ9KShbMC05YS1mXXsyfSk/JC9pOwogICAgICByZ2JQYXJlbnRoZXNlc01hdGNoZXIgPSAvXnJnYmE/XHMqXChccyooWzAtOS5dKyU/KVxzKlssXHNdK1xzKihbMC05Ll0rJT8pXHMqWyxcc10rXHMqKFswLTkuXSslPykoPzpccypbLFxzL10rXHMqKFswLTkuXSspKT9ccypcKSQvaTsKICAgICAgaHNsUGFyZW50aGVzZXNNYXRjaGVyID0gL15oc2xhP1xzKlwoXHMqKFswLTkuXSspXHMqWyxcc10rXHMqKFswLTkuXSslKVxzKlssXHNdK1xzKihbMC05Ll0rJSkoPzpccypbLFxzL10rXHMqKFswLTkuXSspKT9ccypcKSQvaTsKICAgICAgQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nID0gZnVuY3Rpb24oY29sb3IsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLnN0cmluZygiY29sb3IiLCBjb2xvcik7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENvbG9yKCk7CiAgICAgICAgfQogICAgICAgIGNvbG9yID0gY29sb3IudHJpbSgpOwogICAgICAgIGNvbnN0IG5hbWVkQ29sb3IgPSBDb2xvcltjb2xvci50b1VwcGVyQ2FzZSgpXTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG5hbWVkQ29sb3IpKSB7CiAgICAgICAgICBDb2xvci5jbG9uZShuYW1lZENvbG9yLCByZXN1bHQpOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgbGV0IG1hdGNoZXMgPSByZ2JhTWF0Y2hlci5leGVjKGNvbG9yKTsKICAgICAgICBpZiAobWF0Y2hlcyAhPT0gbnVsbCkgewogICAgICAgICAgcmVzdWx0LnJlZCA9IHBhcnNlSW50KG1hdGNoZXNbMV0sIDE2KSAvIDE1OwogICAgICAgICAgcmVzdWx0LmdyZWVuID0gcGFyc2VJbnQobWF0Y2hlc1syXSwgMTYpIC8gMTU7CiAgICAgICAgICByZXN1bHQuYmx1ZSA9IHBhcnNlSW50KG1hdGNoZXNbM10sIDE2KSAvIDE1OwogICAgICAgICAgcmVzdWx0LmFscGhhID0gcGFyc2VJbnQobWF0Y2hlc1s0XSA/PyAiZiIsIDE2KSAvIDE1OwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgbWF0Y2hlcyA9IHJyZ2diYmFhTWF0Y2hlci5leGVjKGNvbG9yKTsKICAgICAgICBpZiAobWF0Y2hlcyAhPT0gbnVsbCkgewogICAgICAgICAgcmVzdWx0LnJlZCA9IHBhcnNlSW50KG1hdGNoZXNbMV0sIDE2KSAvIDI1NTsKICAgICAgICAgIHJlc3VsdC5ncmVlbiA9IHBhcnNlSW50KG1hdGNoZXNbMl0sIDE2KSAvIDI1NTsKICAgICAgICAgIHJlc3VsdC5ibHVlID0gcGFyc2VJbnQobWF0Y2hlc1szXSwgMTYpIC8gMjU1OwogICAgICAgICAgcmVzdWx0LmFscGhhID0gcGFyc2VJbnQobWF0Y2hlc1s0XSA/PyAiZmYiLCAxNikgLyAyNTU7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICBtYXRjaGVzID0gcmdiUGFyZW50aGVzZXNNYXRjaGVyLmV4ZWMoY29sb3IpOwogICAgICAgIGlmIChtYXRjaGVzICE9PSBudWxsKSB7CiAgICAgICAgICByZXN1bHQucmVkID0gcGFyc2VGbG9hdChtYXRjaGVzWzFdKSAvICgiJSIgPT09IG1hdGNoZXNbMV0uc3Vic3RyKC0xKSA/IDEwMCA6IDI1NSk7CiAgICAgICAgICByZXN1bHQuZ3JlZW4gPSBwYXJzZUZsb2F0KG1hdGNoZXNbMl0pIC8gKCIlIiA9PT0gbWF0Y2hlc1syXS5zdWJzdHIoLTEpID8gMTAwIDogMjU1KTsKICAgICAgICAgIHJlc3VsdC5ibHVlID0gcGFyc2VGbG9hdChtYXRjaGVzWzNdKSAvICgiJSIgPT09IG1hdGNoZXNbM10uc3Vic3RyKC0xKSA/IDEwMCA6IDI1NSk7CiAgICAgICAgICByZXN1bHQuYWxwaGEgPSBwYXJzZUZsb2F0KG1hdGNoZXNbNF0gPz8gIjEuMCIpOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgICAgbWF0Y2hlcyA9IGhzbFBhcmVudGhlc2VzTWF0Y2hlci5leGVjKGNvbG9yKTsKICAgICAgICBpZiAobWF0Y2hlcyAhPT0gbnVsbCkgewogICAgICAgICAgcmV0dXJuIENvbG9yLmZyb21Ic2woCiAgICAgICAgICAgIHBhcnNlRmxvYXQobWF0Y2hlc1sxXSkgLyAzNjAsCiAgICAgICAgICAgIHBhcnNlRmxvYXQobWF0Y2hlc1syXSkgLyAxMDAsCiAgICAgICAgICAgIHBhcnNlRmxvYXQobWF0Y2hlc1szXSkgLyAxMDAsCiAgICAgICAgICAgIHBhcnNlRmxvYXQobWF0Y2hlc1s0XSA/PyAiMS4wIiksCiAgICAgICAgICAgIHJlc3VsdAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0ID0gdm9pZCAwOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENvbG9yLnBhY2tlZExlbmd0aCA9IDQ7CiAgICAgIENvbG9yLnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUucmVkOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5ncmVlbjsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuYmx1ZTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLmFscGhhOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgQ29sb3IudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgQ29sb3IoKTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnJlZCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LmdyZWVuID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICByZXN1bHQuYmx1ZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgcmVzdWx0LmFscGhhID0gYXJyYXlbc3RhcnRpbmdJbmRleF07CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ29sb3IuYnl0ZVRvRmxvYXQgPSBmdW5jdGlvbihudW1iZXIpIHsKICAgICAgICByZXR1cm4gbnVtYmVyIC8gMjU1OwogICAgICB9OwogICAgICBDb2xvci5mbG9hdFRvQnl0ZSA9IGZ1bmN0aW9uKG51bWJlcikgewogICAgICAgIHJldHVybiBudW1iZXIgPT09IDEgPyAyNTUgOiBudW1iZXIgKiAyNTYgfCAwOwogICAgICB9OwogICAgICBDb2xvci5jbG9uZSA9IGZ1bmN0aW9uKGNvbG9yLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChjb2xvcikpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJldHVybiBuZXcgQ29sb3IoY29sb3IucmVkLCBjb2xvci5ncmVlbiwgY29sb3IuYmx1ZSwgY29sb3IuYWxwaGEpOwogICAgICAgIH0KICAgICAgICByZXN1bHQucmVkID0gY29sb3IucmVkOwogICAgICAgIHJlc3VsdC5ncmVlbiA9IGNvbG9yLmdyZWVuOwogICAgICAgIHJlc3VsdC5ibHVlID0gY29sb3IuYmx1ZTsKICAgICAgICByZXN1bHQuYWxwaGEgPSBjb2xvci5hbHBoYTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDb2xvci5lcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCAvLwogICAgICAgIGRlZmluZWRfZGVmYXVsdChsZWZ0KSAmJiAvLwogICAgICAgIGRlZmluZWRfZGVmYXVsdChyaWdodCkgJiYgLy8KICAgICAgICBsZWZ0LnJlZCA9PT0gcmlnaHQucmVkICYmIC8vCiAgICAgICAgbGVmdC5ncmVlbiA9PT0gcmlnaHQuZ3JlZW4gJiYgLy8KICAgICAgICBsZWZ0LmJsdWUgPT09IHJpZ2h0LmJsdWUgJiYgLy8KICAgICAgICBsZWZ0LmFscGhhID09PSByaWdodC5hbHBoYTsKICAgICAgfTsKICAgICAgQ29sb3IuZXF1YWxzQXJyYXkgPSBmdW5jdGlvbihjb2xvciwgYXJyYXksIG9mZnNldCkgewogICAgICAgIHJldHVybiBjb2xvci5yZWQgPT09IGFycmF5W29mZnNldF0gJiYgY29sb3IuZ3JlZW4gPT09IGFycmF5W29mZnNldCArIDFdICYmIGNvbG9yLmJsdWUgPT09IGFycmF5W29mZnNldCArIDJdICYmIGNvbG9yLmFscGhhID09PSBhcnJheVtvZmZzZXQgKyAzXTsKICAgICAgfTsKICAgICAgQ29sb3IucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgcmV0dXJuIENvbG9yLmNsb25lKHRoaXMsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIENvbG9yLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbihvdGhlcikgewogICAgICAgIHJldHVybiBDb2xvci5lcXVhbHModGhpcywgb3RoZXIpOwogICAgICB9OwogICAgICBDb2xvci5wcm90b3R5cGUuZXF1YWxzRXBzaWxvbiA9IGZ1bmN0aW9uKG90aGVyLCBlcHNpbG9uKSB7CiAgICAgICAgcmV0dXJuIHRoaXMgPT09IG90aGVyIHx8IC8vCiAgICAgICAgZGVmaW5lZF9kZWZhdWx0KG90aGVyKSAmJiAvLwogICAgICAgIE1hdGguYWJzKHRoaXMucmVkIC0gb3RoZXIucmVkKSA8PSBlcHNpbG9uICYmIC8vCiAgICAgICAgTWF0aC5hYnModGhpcy5ncmVlbiAtIG90aGVyLmdyZWVuKSA8PSBlcHNpbG9uICYmIC8vCiAgICAgICAgTWF0aC5hYnModGhpcy5ibHVlIC0gb3RoZXIuYmx1ZSkgPD0gZXBzaWxvbiAmJiAvLwogICAgICAgIE1hdGguYWJzKHRoaXMuYWxwaGEgLSBvdGhlci5hbHBoYSkgPD0gZXBzaWxvbjsKICAgICAgfTsKICAgICAgQ29sb3IucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIGAoJHt0aGlzLnJlZH0sICR7dGhpcy5ncmVlbn0sICR7dGhpcy5ibHVlfSwgJHt0aGlzLmFscGhhfSlgOwogICAgICB9OwogICAgICBDb2xvci5wcm90b3R5cGUudG9Dc3NDb2xvclN0cmluZyA9IGZ1bmN0aW9uKCkgewogICAgICAgIGNvbnN0IHJlZCA9IENvbG9yLmZsb2F0VG9CeXRlKHRoaXMucmVkKTsKICAgICAgICBjb25zdCBncmVlbiA9IENvbG9yLmZsb2F0VG9CeXRlKHRoaXMuZ3JlZW4pOwogICAgICAgIGNvbnN0IGJsdWUgPSBDb2xvci5mbG9hdFRvQnl0ZSh0aGlzLmJsdWUpOwogICAgICAgIGlmICh0aGlzLmFscGhhID09PSAxKSB7CiAgICAgICAgICByZXR1cm4gYHJnYigke3JlZH0sJHtncmVlbn0sJHtibHVlfSlgOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYHJnYmEoJHtyZWR9LCR7Z3JlZW59LCR7Ymx1ZX0sJHt0aGlzLmFscGhhfSlgOwogICAgICB9OwogICAgICBDb2xvci5wcm90b3R5cGUudG9Dc3NIZXhTdHJpbmcgPSBmdW5jdGlvbigpIHsKICAgICAgICBsZXQgciA9IENvbG9yLmZsb2F0VG9CeXRlKHRoaXMucmVkKS50b1N0cmluZygxNik7CiAgICAgICAgaWYgKHIubGVuZ3RoIDwgMikgewogICAgICAgICAgciA9IGAwJHtyfWA7CiAgICAgICAgfQogICAgICAgIGxldCBnID0gQ29sb3IuZmxvYXRUb0J5dGUodGhpcy5ncmVlbikudG9TdHJpbmcoMTYpOwogICAgICAgIGlmIChnLmxlbmd0aCA8IDIpIHsKICAgICAgICAgIGcgPSBgMCR7Z31gOwogICAgICAgIH0KICAgICAgICBsZXQgYiA9IENvbG9yLmZsb2F0VG9CeXRlKHRoaXMuYmx1ZSkudG9TdHJpbmcoMTYpOwogICAgICAgIGlmIChiLmxlbmd0aCA8IDIpIHsKICAgICAgICAgIGIgPSBgMCR7Yn1gOwogICAgICAgIH0KICAgICAgICBpZiAodGhpcy5hbHBoYSA8IDEpIHsKICAgICAgICAgIGxldCBoZXhBbHBoYSA9IENvbG9yLmZsb2F0VG9CeXRlKHRoaXMuYWxwaGEpLnRvU3RyaW5nKDE2KTsKICAgICAgICAgIGlmIChoZXhBbHBoYS5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgIGhleEFscGhhID0gYDAke2hleEFscGhhfWA7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gYCMke3J9JHtnfSR7Yn0ke2hleEFscGhhfWA7CiAgICAgICAgfQogICAgICAgIHJldHVybiBgIyR7cn0ke2d9JHtifWA7CiAgICAgIH07CiAgICAgIENvbG9yLnByb3RvdHlwZS50b0J5dGVzID0gZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgY29uc3QgcmVkID0gQ29sb3IuZmxvYXRUb0J5dGUodGhpcy5yZWQpOwogICAgICAgIGNvbnN0IGdyZWVuID0gQ29sb3IuZmxvYXRUb0J5dGUodGhpcy5ncmVlbik7CiAgICAgICAgY29uc3QgYmx1ZSA9IENvbG9yLmZsb2F0VG9CeXRlKHRoaXMuYmx1ZSk7CiAgICAgICAgY29uc3QgYWxwaGEgPSBDb2xvci5mbG9hdFRvQnl0ZSh0aGlzLmFscGhhKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXR1cm4gW3JlZCwgZ3JlZW4sIGJsdWUsIGFscGhhXTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0WzBdID0gcmVkOwogICAgICAgIHJlc3VsdFsxXSA9IGdyZWVuOwogICAgICAgIHJlc3VsdFsyXSA9IGJsdWU7CiAgICAgICAgcmVzdWx0WzNdID0gYWxwaGE7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ29sb3IucHJvdG90eXBlLnRvUmdiYSA9IGZ1bmN0aW9uKCkgewogICAgICAgIHNjcmF0Y2hVaW50OEFycmF5WzBdID0gQ29sb3IuZmxvYXRUb0J5dGUodGhpcy5yZWQpOwogICAgICAgIHNjcmF0Y2hVaW50OEFycmF5WzFdID0gQ29sb3IuZmxvYXRUb0J5dGUodGhpcy5ncmVlbik7CiAgICAgICAgc2NyYXRjaFVpbnQ4QXJyYXlbMl0gPSBDb2xvci5mbG9hdFRvQnl0ZSh0aGlzLmJsdWUpOwogICAgICAgIHNjcmF0Y2hVaW50OEFycmF5WzNdID0gQ29sb3IuZmxvYXRUb0J5dGUodGhpcy5hbHBoYSk7CiAgICAgICAgcmV0dXJuIHNjcmF0Y2hVaW50MzJBcnJheVswXTsKICAgICAgfTsKICAgICAgQ29sb3IucHJvdG90eXBlLmJyaWdodGVuID0gZnVuY3Rpb24obWFnbml0dWRlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoIm1hZ25pdHVkZSIsIG1hZ25pdHVkZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoIm1hZ25pdHVkZSIsIG1hZ25pdHVkZSwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIG1hZ25pdHVkZSA9IDEgLSBtYWduaXR1ZGU7CiAgICAgICAgcmVzdWx0LnJlZCA9IDEgLSAoMSAtIHRoaXMucmVkKSAqIG1hZ25pdHVkZTsKICAgICAgICByZXN1bHQuZ3JlZW4gPSAxIC0gKDEgLSB0aGlzLmdyZWVuKSAqIG1hZ25pdHVkZTsKICAgICAgICByZXN1bHQuYmx1ZSA9IDEgLSAoMSAtIHRoaXMuYmx1ZSkgKiBtYWduaXR1ZGU7CiAgICAgICAgcmVzdWx0LmFscGhhID0gdGhpcy5hbHBoYTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDb2xvci5wcm90b3R5cGUuZGFya2VuID0gZnVuY3Rpb24obWFnbml0dWRlLCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoIm1hZ25pdHVkZSIsIG1hZ25pdHVkZSk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyLmdyZWF0ZXJUaGFuT3JFcXVhbHMoIm1hZ25pdHVkZSIsIG1hZ25pdHVkZSwgMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIG1hZ25pdHVkZSA9IDEgLSBtYWduaXR1ZGU7CiAgICAgICAgcmVzdWx0LnJlZCA9IHRoaXMucmVkICogbWFnbml0dWRlOwogICAgICAgIHJlc3VsdC5ncmVlbiA9IHRoaXMuZ3JlZW4gKiBtYWduaXR1ZGU7CiAgICAgICAgcmVzdWx0LmJsdWUgPSB0aGlzLmJsdWUgKiBtYWduaXR1ZGU7CiAgICAgICAgcmVzdWx0LmFscGhhID0gdGhpcy5hbHBoYTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDb2xvci5wcm90b3R5cGUud2l0aEFscGhhID0gZnVuY3Rpb24oYWxwaGEsIHJlc3VsdCkgewogICAgICAgIHJldHVybiBDb2xvci5mcm9tQWxwaGEodGhpcywgYWxwaGEsIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIENvbG9yLmFkZCA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImxlZnQiLCBsZWZ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJpZ2h0IiwgcmlnaHQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQucmVkID0gbGVmdC5yZWQgKyByaWdodC5yZWQ7CiAgICAgICAgcmVzdWx0LmdyZWVuID0gbGVmdC5ncmVlbiArIHJpZ2h0LmdyZWVuOwogICAgICAgIHJlc3VsdC5ibHVlID0gbGVmdC5ibHVlICsgcmlnaHQuYmx1ZTsKICAgICAgICByZXN1bHQuYWxwaGEgPSBsZWZ0LmFscGhhICsgcmlnaHQuYWxwaGE7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ29sb3Iuc3VidHJhY3QgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnJlZCA9IGxlZnQucmVkIC0gcmlnaHQucmVkOwogICAgICAgIHJlc3VsdC5ncmVlbiA9IGxlZnQuZ3JlZW4gLSByaWdodC5ncmVlbjsKICAgICAgICByZXN1bHQuYmx1ZSA9IGxlZnQuYmx1ZSAtIHJpZ2h0LmJsdWU7CiAgICAgICAgcmVzdWx0LmFscGhhID0gbGVmdC5hbHBoYSAtIHJpZ2h0LmFscGhhOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENvbG9yLm11bHRpcGx5ID0gZnVuY3Rpb24obGVmdCwgcmlnaHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgibGVmdCIsIGxlZnQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmlnaHQiLCByaWdodCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC5yZWQgPSBsZWZ0LnJlZCAqIHJpZ2h0LnJlZDsKICAgICAgICByZXN1bHQuZ3JlZW4gPSBsZWZ0LmdyZWVuICogcmlnaHQuZ3JlZW47CiAgICAgICAgcmVzdWx0LmJsdWUgPSBsZWZ0LmJsdWUgKiByaWdodC5ibHVlOwogICAgICAgIHJlc3VsdC5hbHBoYSA9IGxlZnQuYWxwaGEgKiByaWdodC5hbHBoYTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDb2xvci5kaXZpZGUgPSBmdW5jdGlvbihsZWZ0LCByaWdodCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJsZWZ0IiwgbGVmdCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyaWdodCIsIHJpZ2h0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlc3VsdCIsIHJlc3VsdCk7CiAgICAgICAgcmVzdWx0LnJlZCA9IGxlZnQucmVkIC8gcmlnaHQucmVkOwogICAgICAgIHJlc3VsdC5ncmVlbiA9IGxlZnQuZ3JlZW4gLyByaWdodC5ncmVlbjsKICAgICAgICByZXN1bHQuYmx1ZSA9IGxlZnQuYmx1ZSAvIHJpZ2h0LmJsdWU7CiAgICAgICAgcmVzdWx0LmFscGhhID0gbGVmdC5hbHBoYSAvIHJpZ2h0LmFscGhhOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENvbG9yLm1vZCA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0LCByZXN1bHQpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImxlZnQiLCBsZWZ0KTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJpZ2h0IiwgcmlnaHQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQucmVkID0gbGVmdC5yZWQgJSByaWdodC5yZWQ7CiAgICAgICAgcmVzdWx0LmdyZWVuID0gbGVmdC5ncmVlbiAlIHJpZ2h0LmdyZWVuOwogICAgICAgIHJlc3VsdC5ibHVlID0gbGVmdC5ibHVlICUgcmlnaHQuYmx1ZTsKICAgICAgICByZXN1bHQuYWxwaGEgPSBsZWZ0LmFscGhhICUgcmlnaHQuYWxwaGE7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgQ29sb3IubGVycCA9IGZ1bmN0aW9uKHN0YXJ0LCBlbmQsIHQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgic3RhcnQiLCBzdGFydCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJlbmQiLCBlbmQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigidCIsIHQpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVzdWx0IiwgcmVzdWx0KTsKICAgICAgICByZXN1bHQucmVkID0gTWF0aF9kZWZhdWx0LmxlcnAoc3RhcnQucmVkLCBlbmQucmVkLCB0KTsKICAgICAgICByZXN1bHQuZ3JlZW4gPSBNYXRoX2RlZmF1bHQubGVycChzdGFydC5ncmVlbiwgZW5kLmdyZWVuLCB0KTsKICAgICAgICByZXN1bHQuYmx1ZSA9IE1hdGhfZGVmYXVsdC5sZXJwKHN0YXJ0LmJsdWUsIGVuZC5ibHVlLCB0KTsKICAgICAgICByZXN1bHQuYWxwaGEgPSBNYXRoX2RlZmF1bHQubGVycChzdGFydC5hbHBoYSwgZW5kLmFscGhhLCB0KTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBDb2xvci5tdWx0aXBseUJ5U2NhbGFyID0gZnVuY3Rpb24oY29sb3IsIHNjYWxhciwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjb2xvciIsIGNvbG9yKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInNjYWxhciIsIHNjYWxhcik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC5yZWQgPSBjb2xvci5yZWQgKiBzY2FsYXI7CiAgICAgICAgcmVzdWx0LmdyZWVuID0gY29sb3IuZ3JlZW4gKiBzY2FsYXI7CiAgICAgICAgcmVzdWx0LmJsdWUgPSBjb2xvci5ibHVlICogc2NhbGFyOwogICAgICAgIHJlc3VsdC5hbHBoYSA9IGNvbG9yLmFscGhhICogc2NhbGFyOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENvbG9yLmRpdmlkZUJ5U2NhbGFyID0gZnVuY3Rpb24oY29sb3IsIHNjYWxhciwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJjb2xvciIsIGNvbG9yKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInNjYWxhciIsIHNjYWxhcik7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZXN1bHQiLCByZXN1bHQpOwogICAgICAgIHJlc3VsdC5yZWQgPSBjb2xvci5yZWQgLyBzY2FsYXI7CiAgICAgICAgcmVzdWx0LmdyZWVuID0gY29sb3IuZ3JlZW4gLyBzY2FsYXI7CiAgICAgICAgcmVzdWx0LmJsdWUgPSBjb2xvci5ibHVlIC8gc2NhbGFyOwogICAgICAgIHJlc3VsdC5hbHBoYSA9IGNvbG9yLmFscGhhIC8gc2NhbGFyOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIENvbG9yLkFMSUNFQkxVRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRjBGOEZGIikpOwogICAgICBDb2xvci5BTlRJUVVFV0hJVEUgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0ZBRUJENyIpKTsKICAgICAgQ29sb3IuQVFVQSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjMDBGRkZGIikpOwogICAgICBDb2xvci5BUVVBTUFSSU5FID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM3RkZGRDQiKSk7CiAgICAgIENvbG9yLkFaVVJFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGMEZGRkYiKSk7CiAgICAgIENvbG9yLkJFSUdFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGNUY1REMiKSk7CiAgICAgIENvbG9yLkJJU1FVRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkZFNEM0IikpOwogICAgICBDb2xvci5CTEFDSyA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjMDAwMDAwIikpOwogICAgICBDb2xvci5CTEFOQ0hFREFMTU9ORCA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkZFQkNEIikpOwogICAgICBDb2xvci5CTFVFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiMwMDAwRkYiKSk7CiAgICAgIENvbG9yLkJMVUVWSU9MRVQgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzhBMkJFMiIpKTsKICAgICAgQ29sb3IuQlJPV04gPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0E1MkEyQSIpKTsKICAgICAgQ29sb3IuQlVSTFlXT09EID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNERUI4ODciKSk7CiAgICAgIENvbG9yLkNBREVUQkxVRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjNUY5RUEwIikpOwogICAgICBDb2xvci5DSEFSVFJFVVNFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM3RkZGMDAiKSk7CiAgICAgIENvbG9yLkNIT0NPTEFURSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRDI2OTFFIikpOwogICAgICBDb2xvci5DT1JBTCA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkY3RjUwIikpOwogICAgICBDb2xvci5DT1JORkxPV0VSQkxVRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjNjQ5NUVEIikpOwogICAgICBDb2xvci5DT1JOU0lMSyA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkZGOERDIikpOwogICAgICBDb2xvci5DUklNU09OID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNEQzE0M0MiKSk7CiAgICAgIENvbG9yLkNZQU4gPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzAwRkZGRiIpKTsKICAgICAgQ29sb3IuREFSS0JMVUUgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzAwMDA4QiIpKTsKICAgICAgQ29sb3IuREFSS0NZQU4gPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzAwOEI4QiIpKTsKICAgICAgQ29sb3IuREFSS0dPTERFTlJPRCA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjQjg4NjBCIikpOwogICAgICBDb2xvci5EQVJLR1JBWSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjQTlBOUE5IikpOwogICAgICBDb2xvci5EQVJLR1JFRU4gPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzAwNjQwMCIpKTsKICAgICAgQ29sb3IuREFSS0dSRVkgPSBDb2xvci5EQVJLR1JBWTsKICAgICAgQ29sb3IuREFSS0tIQUtJID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNCREI3NkIiKSk7CiAgICAgIENvbG9yLkRBUktNQUdFTlRBID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM4QjAwOEIiKSk7CiAgICAgIENvbG9yLkRBUktPTElWRUdSRUVOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM1NTZCMkYiKSk7CiAgICAgIENvbG9yLkRBUktPUkFOR0UgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0ZGOEMwMCIpKTsKICAgICAgQ29sb3IuREFSS09SQ0hJRCA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjOTkzMkNDIikpOwogICAgICBDb2xvci5EQVJLUkVEID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM4QjAwMDAiKSk7CiAgICAgIENvbG9yLkRBUktTQUxNT04gPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0U5OTY3QSIpKTsKICAgICAgQ29sb3IuREFSS1NFQUdSRUVOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM4RkJDOEYiKSk7CiAgICAgIENvbG9yLkRBUktTTEFURUJMVUUgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzQ4M0Q4QiIpKTsKICAgICAgQ29sb3IuREFSS1NMQVRFR1JBWSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjMkY0RjRGIikpOwogICAgICBDb2xvci5EQVJLU0xBVEVHUkVZID0gQ29sb3IuREFSS1NMQVRFR1JBWTsKICAgICAgQ29sb3IuREFSS1RVUlFVT0lTRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjMDBDRUQxIikpOwogICAgICBDb2xvci5EQVJLVklPTEVUID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM5NDAwRDMiKSk7CiAgICAgIENvbG9yLkRFRVBQSU5LID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRjE0OTMiKSk7CiAgICAgIENvbG9yLkRFRVBTS1lCTFVFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiMwMEJGRkYiKSk7CiAgICAgIENvbG9yLkRJTUdSQVkgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzY5Njk2OSIpKTsKICAgICAgQ29sb3IuRElNR1JFWSA9IENvbG9yLkRJTUdSQVk7CiAgICAgIENvbG9yLkRPREdFUkJMVUUgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzFFOTBGRiIpKTsKICAgICAgQ29sb3IuRklSRUJSSUNLID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNCMjIyMjIiKSk7CiAgICAgIENvbG9yLkZMT1JBTFdISVRFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRkZBRjAiKSk7CiAgICAgIENvbG9yLkZPUkVTVEdSRUVOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiMyMjhCMjIiKSk7CiAgICAgIENvbG9yLkZVQ0hTSUEgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0ZGMDBGRiIpKTsKICAgICAgQ29sb3IuR0FJTlNCT1JPID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNEQ0RDREMiKSk7CiAgICAgIENvbG9yLkdIT1NUV0hJVEUgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0Y4RjhGRiIpKTsKICAgICAgQ29sb3IuR09MRCA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkZENzAwIikpOwogICAgICBDb2xvci5HT0xERU5ST0QgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0RBQTUyMCIpKTsKICAgICAgQ29sb3IuR1JBWSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjODA4MDgwIikpOwogICAgICBDb2xvci5HUkVFTiA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjMDA4MDAwIikpOwogICAgICBDb2xvci5HUkVFTllFTExPVyA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjQURGRjJGIikpOwogICAgICBDb2xvci5HUkVZID0gQ29sb3IuR1JBWTsKICAgICAgQ29sb3IuSE9ORVlERVcgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0YwRkZGMCIpKTsKICAgICAgQ29sb3IuSE9UUElOSyA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkY2OUI0IikpOwogICAgICBDb2xvci5JTkRJQU5SRUQgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0NENUM1QyIpKTsKICAgICAgQ29sb3IuSU5ESUdPID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM0QjAwODIiKSk7CiAgICAgIENvbG9yLklWT1JZID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRkZGRjAiKSk7CiAgICAgIENvbG9yLktIQUtJID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGMEU2OEMiKSk7CiAgICAgIENvbG9yLkxBVkVOREVSID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNFNkU2RkEiKSk7CiAgICAgIENvbG9yLkxBVkVOREFSX0JMVVNIID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRkYwRjUiKSk7CiAgICAgIENvbG9yLkxBV05HUkVFTiA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjN0NGQzAwIikpOwogICAgICBDb2xvci5MRU1PTkNISUZGT04gPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0ZGRkFDRCIpKTsKICAgICAgQ29sb3IuTElHSFRCTFVFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNBREQ4RTYiKSk7CiAgICAgIENvbG9yLkxJR0hUQ09SQUwgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0YwODA4MCIpKTsKICAgICAgQ29sb3IuTElHSFRDWUFOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNFMEZGRkYiKSk7CiAgICAgIENvbG9yLkxJR0hUR09MREVOUk9EWUVMTE9XID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGQUZBRDIiKSk7CiAgICAgIENvbG9yLkxJR0hUR1JBWSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRDNEM0QzIikpOwogICAgICBDb2xvci5MSUdIVEdSRUVOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM5MEVFOTAiKSk7CiAgICAgIENvbG9yLkxJR0hUR1JFWSA9IENvbG9yLkxJR0hUR1JBWTsKICAgICAgQ29sb3IuTElHSFRQSU5LID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRkI2QzEiKSk7CiAgICAgIENvbG9yLkxJR0hUU0VBR1JFRU4gPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzIwQjJBQSIpKTsKICAgICAgQ29sb3IuTElHSFRTS1lCTFVFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM4N0NFRkEiKSk7CiAgICAgIENvbG9yLkxJR0hUU0xBVEVHUkFZID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM3Nzg4OTkiKSk7CiAgICAgIENvbG9yLkxJR0hUU0xBVEVHUkVZID0gQ29sb3IuTElHSFRTTEFURUdSQVk7CiAgICAgIENvbG9yLkxJR0hUU1RFRUxCTFVFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNCMEM0REUiKSk7CiAgICAgIENvbG9yLkxJR0hUWUVMTE9XID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRkZGRTAiKSk7CiAgICAgIENvbG9yLkxJTUUgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzAwRkYwMCIpKTsKICAgICAgQ29sb3IuTElNRUdSRUVOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiMzMkNEMzIiKSk7CiAgICAgIENvbG9yLkxJTkVOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGQUYwRTYiKSk7CiAgICAgIENvbG9yLk1BR0VOVEEgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0ZGMDBGRiIpKTsKICAgICAgQ29sb3IuTUFST09OID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM4MDAwMDAiKSk7CiAgICAgIENvbG9yLk1FRElVTUFRVUFNQVJJTkUgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzY2Q0RBQSIpKTsKICAgICAgQ29sb3IuTUVESVVNQkxVRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjMDAwMENEIikpOwogICAgICBDb2xvci5NRURJVU1PUkNISUQgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0JBNTVEMyIpKTsKICAgICAgQ29sb3IuTUVESVVNUFVSUExFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM5MzcwREIiKSk7CiAgICAgIENvbG9yLk1FRElVTVNFQUdSRUVOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiMzQ0IzNzEiKSk7CiAgICAgIENvbG9yLk1FRElVTVNMQVRFQkxVRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjN0I2OEVFIikpOwogICAgICBDb2xvci5NRURJVU1TUFJJTkdHUkVFTiA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjMDBGQTlBIikpOwogICAgICBDb2xvci5NRURJVU1UVVJRVU9JU0UgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzQ4RDFDQyIpKTsKICAgICAgQ29sb3IuTUVESVVNVklPTEVUUkVEID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNDNzE1ODUiKSk7CiAgICAgIENvbG9yLk1JRE5JR0hUQkxVRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjMTkxOTcwIikpOwogICAgICBDb2xvci5NSU5UQ1JFQU0gPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0Y1RkZGQSIpKTsKICAgICAgQ29sb3IuTUlTVFlST1NFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRkU0RTEiKSk7CiAgICAgIENvbG9yLk1PQ0NBU0lOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRkU0QjUiKSk7CiAgICAgIENvbG9yLk5BVkFKT1dISVRFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRkRFQUQiKSk7CiAgICAgIENvbG9yLk5BVlkgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzAwMDA4MCIpKTsKICAgICAgQ29sb3IuT0xETEFDRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkRGNUU2IikpOwogICAgICBDb2xvci5PTElWRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjODA4MDAwIikpOwogICAgICBDb2xvci5PTElWRURSQUIgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzZCOEUyMyIpKTsKICAgICAgQ29sb3IuT1JBTkdFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRkE1MDAiKSk7CiAgICAgIENvbG9yLk9SQU5HRVJFRCA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkY0NTAwIikpOwogICAgICBDb2xvci5PUkNISUQgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0RBNzBENiIpKTsKICAgICAgQ29sb3IuUEFMRUdPTERFTlJPRCA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRUVFOEFBIikpOwogICAgICBDb2xvci5QQUxFR1JFRU4gPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzk4RkI5OCIpKTsKICAgICAgQ29sb3IuUEFMRVRVUlFVT0lTRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjQUZFRUVFIikpOwogICAgICBDb2xvci5QQUxFVklPTEVUUkVEID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNEQjcwOTMiKSk7CiAgICAgIENvbG9yLlBBUEFZQVdISVAgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0ZGRUZENSIpKTsKICAgICAgQ29sb3IuUEVBQ0hQVUZGID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRkRBQjkiKSk7CiAgICAgIENvbG9yLlBFUlUgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0NEODUzRiIpKTsKICAgICAgQ29sb3IuUElOSyA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkZDMENCIikpOwogICAgICBDb2xvci5QTFVNID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNEREEwREQiKSk7CiAgICAgIENvbG9yLlBPV0RFUkJMVUUgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0IwRTBFNiIpKTsKICAgICAgQ29sb3IuUFVSUExFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM4MDAwODAiKSk7CiAgICAgIENvbG9yLlJFRCA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkYwMDAwIikpOwogICAgICBDb2xvci5ST1NZQlJPV04gPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0JDOEY4RiIpKTsKICAgICAgQ29sb3IuUk9ZQUxCTFVFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM0MTY5RTEiKSk7CiAgICAgIENvbG9yLlNBRERMRUJST1dOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM4QjQ1MTMiKSk7CiAgICAgIENvbG9yLlNBTE1PTiA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkE4MDcyIikpOwogICAgICBDb2xvci5TQU5EWUJST1dOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGNEE0NjAiKSk7CiAgICAgIENvbG9yLlNFQUdSRUVOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiMyRThCNTciKSk7CiAgICAgIENvbG9yLlNFQVNIRUxMID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGRkY1RUUiKSk7CiAgICAgIENvbG9yLlNJRU5OQSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjQTA1MjJEIikpOwogICAgICBDb2xvci5TSUxWRVIgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0MwQzBDMCIpKTsKICAgICAgQ29sb3IuU0tZQkxVRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjODdDRUVCIikpOwogICAgICBDb2xvci5TTEFURUJMVUUgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzZBNUFDRCIpKTsKICAgICAgQ29sb3IuU0xBVEVHUkFZID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM3MDgwOTAiKSk7CiAgICAgIENvbG9yLlNMQVRFR1JFWSA9IENvbG9yLlNMQVRFR1JBWTsKICAgICAgQ29sb3IuU05PVyA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkZGQUZBIikpOwogICAgICBDb2xvci5TUFJJTkdHUkVFTiA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjMDBGRjdGIikpOwogICAgICBDb2xvci5TVEVFTEJMVUUgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzQ2ODJCNCIpKTsKICAgICAgQ29sb3IuVEFOID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNEMkI0OEMiKSk7CiAgICAgIENvbG9yLlRFQUwgPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiIzAwODA4MCIpKTsKICAgICAgQ29sb3IuVEhJU1RMRSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRDhCRkQ4IikpOwogICAgICBDb2xvci5UT01BVE8gPSBPYmplY3QuZnJlZXplKENvbG9yLmZyb21Dc3NDb2xvclN0cmluZygiI0ZGNjM0NyIpKTsKICAgICAgQ29sb3IuVFVSUVVPSVNFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiM0MEUwRDAiKSk7CiAgICAgIENvbG9yLlZJT0xFVCA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRUU4MkVFIikpOwogICAgICBDb2xvci5XSEVBVCA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRjVERUIzIikpOwogICAgICBDb2xvci5XSElURSA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkZGRkZGIikpOwogICAgICBDb2xvci5XSElURVNNT0tFID0gT2JqZWN0LmZyZWV6ZShDb2xvci5mcm9tQ3NzQ29sb3JTdHJpbmcoIiNGNUY1RjUiKSk7CiAgICAgIENvbG9yLllFTExPVyA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjRkZGRjAwIikpOwogICAgICBDb2xvci5ZRUxMT1dHUkVFTiA9IE9iamVjdC5mcmVlemUoQ29sb3IuZnJvbUNzc0NvbG9yU3RyaW5nKCIjOUFDRDMyIikpOwogICAgICBDb2xvci5UUkFOU1BBUkVOVCA9IE9iamVjdC5mcmVlemUobmV3IENvbG9yKDAsIDAsIDAsIDApKTsKICAgICAgQ29sb3JfZGVmYXVsdCA9IENvbG9yOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUG9seWxpbmVHZW9tZXRyeS5qcwogIGZ1bmN0aW9uIGludGVycG9sYXRlQ29sb3JzKHAwLCBwMSwgY29sb3IwLCBjb2xvcjEsIG51bVBvaW50cykgewogICAgY29uc3QgY29sb3JzID0gc2NyYXRjaEludGVycG9sYXRlQ29sb3JzQXJyYXk7CiAgICBjb2xvcnMubGVuZ3RoID0gbnVtUG9pbnRzOwogICAgbGV0IGk7CiAgICBjb25zdCByMCA9IGNvbG9yMC5yZWQ7CiAgICBjb25zdCBnMCA9IGNvbG9yMC5ncmVlbjsKICAgIGNvbnN0IGIwID0gY29sb3IwLmJsdWU7CiAgICBjb25zdCBhMCA9IGNvbG9yMC5hbHBoYTsKICAgIGNvbnN0IHIxID0gY29sb3IxLnJlZDsKICAgIGNvbnN0IGcxID0gY29sb3IxLmdyZWVuOwogICAgY29uc3QgYjEgPSBjb2xvcjEuYmx1ZTsKICAgIGNvbnN0IGExID0gY29sb3IxLmFscGhhOwogICAgaWYgKENvbG9yX2RlZmF1bHQuZXF1YWxzKGNvbG9yMCwgY29sb3IxKSkgewogICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtUG9pbnRzOyBpKyspIHsKICAgICAgICBjb2xvcnNbaV0gPSBDb2xvcl9kZWZhdWx0LmNsb25lKGNvbG9yMCk7CiAgICAgIH0KICAgICAgcmV0dXJuIGNvbG9yczsKICAgIH0KICAgIGNvbnN0IHJlZFBlclZlcnRleCA9IChyMSAtIHIwKSAvIG51bVBvaW50czsKICAgIGNvbnN0IGdyZWVuUGVyVmVydGV4ID0gKGcxIC0gZzApIC8gbnVtUG9pbnRzOwogICAgY29uc3QgYmx1ZVBlclZlcnRleCA9IChiMSAtIGIwKSAvIG51bVBvaW50czsKICAgIGNvbnN0IGFscGhhUGVyVmVydGV4ID0gKGExIC0gYTApIC8gbnVtUG9pbnRzOwogICAgZm9yIChpID0gMDsgaSA8IG51bVBvaW50czsgaSsrKSB7CiAgICAgIGNvbG9yc1tpXSA9IG5ldyBDb2xvcl9kZWZhdWx0KAogICAgICAgIHIwICsgaSAqIHJlZFBlclZlcnRleCwKICAgICAgICBnMCArIGkgKiBncmVlblBlclZlcnRleCwKICAgICAgICBiMCArIGkgKiBibHVlUGVyVmVydGV4LAogICAgICAgIGEwICsgaSAqIGFscGhhUGVyVmVydGV4CiAgICAgICk7CiAgICB9CiAgICByZXR1cm4gY29sb3JzOwogIH0KICBmdW5jdGlvbiBQb2x5bGluZUdlb21ldHJ5KG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IG9wdGlvbnMucG9zaXRpb25zOwogICAgY29uc3QgY29sb3JzID0gb3B0aW9ucy5jb2xvcnM7CiAgICBjb25zdCB3aWR0aCA9IG9wdGlvbnMud2lkdGggPz8gMTsKICAgIGNvbnN0IGNvbG9yc1BlclZlcnRleCA9IG9wdGlvbnMuY29sb3JzUGVyVmVydGV4ID8/IGZhbHNlOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocG9zaXRpb25zKSB8fCBwb3NpdGlvbnMubGVuZ3RoIDwgMikgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiQXQgbGVhc3QgdHdvIHBvc2l0aW9ucyBhcmUgcmVxdWlyZWQuIik7CiAgICB9CiAgICBpZiAodHlwZW9mIHdpZHRoICE9PSAibnVtYmVyIikgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgid2lkdGggbXVzdCBiZSBhIG51bWJlciIpOwogICAgfQogICAgaWYgKGRlZmluZWRfZGVmYXVsdChjb2xvcnMpICYmIChjb2xvcnNQZXJWZXJ0ZXggJiYgY29sb3JzLmxlbmd0aCA8IHBvc2l0aW9ucy5sZW5ndGggfHwgIWNvbG9yc1BlclZlcnRleCAmJiBjb2xvcnMubGVuZ3RoIDwgcG9zaXRpb25zLmxlbmd0aCAtIDEpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJjb2xvcnMgaGFzIGFuIGludmFsaWQgbGVuZ3RoLiIpOwogICAgfQogICAgdGhpcy5fcG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgdGhpcy5fY29sb3JzID0gY29sb3JzOwogICAgdGhpcy5fd2lkdGggPSB3aWR0aDsKICAgIHRoaXMuX2NvbG9yc1BlclZlcnRleCA9IGNvbG9yc1BlclZlcnRleDsKICAgIHRoaXMuX3ZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LmNsb25lKAogICAgICBvcHRpb25zLnZlcnRleEZvcm1hdCA/PyBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5ERUZBVUxUCiAgICApOwogICAgdGhpcy5fYXJjVHlwZSA9IG9wdGlvbnMuYXJjVHlwZSA/PyBBcmNUeXBlX2RlZmF1bHQuR0VPREVTSUM7CiAgICB0aGlzLl9ncmFudWxhcml0eSA9IG9wdGlvbnMuZ3JhbnVsYXJpdHkgPz8gTWF0aF9kZWZhdWx0LlJBRElBTlNfUEVSX0RFR1JFRTsKICAgIHRoaXMuX2VsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKG9wdGlvbnMuZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQpOwogICAgdGhpcy5fd29ya2VyTmFtZSA9ICJjcmVhdGVQb2x5bGluZUdlb21ldHJ5IjsKICAgIGxldCBudW1Db21wb25lbnRzID0gMSArIHBvc2l0aW9ucy5sZW5ndGggKiBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgbnVtQ29tcG9uZW50cyArPSBkZWZpbmVkX2RlZmF1bHQoY29sb3JzKSA/IDEgKyBjb2xvcnMubGVuZ3RoICogQ29sb3JfZGVmYXVsdC5wYWNrZWRMZW5ndGggOiAxOwogICAgdGhpcy5wYWNrZWRMZW5ndGggPSBudW1Db21wb25lbnRzICsgRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoICsgVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFja2VkTGVuZ3RoICsgNDsKICB9CiAgdmFyIHNjcmF0Y2hJbnRlcnBvbGF0ZUNvbG9yc0FycmF5LCBzY3JhdGNoRWxsaXBzb2lkOCwgc2NyYXRjaFZlcnRleEZvcm1hdDEwLCBzY3JhdGNoT3B0aW9uczE2LCBzY3JhdGNoQ2FydGVzaWFuMzgsIHNjcmF0Y2hQb3NpdGlvbjQsIHNjcmF0Y2hQcmV2UG9zaXRpb24sIHNjcmF0Y2hOZXh0UG9zaXRpb24sIFBvbHlsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9Qb2x5bGluZUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9Qb2x5bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9BcmNUeXBlKCk7CiAgICAgIGluaXRfYXJyYXlSZW1vdmVEdXBsaWNhdGVzKCk7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ29sb3IoKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZXMoKTsKICAgICAgaW5pdF9HZW9tZXRyeVR5cGUoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1BvbHlsaW5lUGlwZWxpbmUoKTsKICAgICAgaW5pdF9QcmltaXRpdmVUeXBlKCk7CiAgICAgIGluaXRfVmVydGV4Rm9ybWF0KCk7CiAgICAgIHNjcmF0Y2hJbnRlcnBvbGF0ZUNvbG9yc0FycmF5ID0gW107CiAgICAgIFBvbHlsaW5lR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHZhbHVlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInZhbHVlIGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFycmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gdmFsdWUuX3Bvc2l0aW9uczsKICAgICAgICBsZXQgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gbGVuZ3RoOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSwgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoKSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhwb3NpdGlvbnNbaV0sIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgY29sb3JzID0gdmFsdWUuX2NvbG9yczsKICAgICAgICBsZW5ndGggPSBkZWZpbmVkX2RlZmF1bHQoY29sb3JzKSA/IGNvbG9ycy5sZW5ndGggOiAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSBsZW5ndGg7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpLCBzdGFydGluZ0luZGV4ICs9IENvbG9yX2RlZmF1bHQucGFja2VkTGVuZ3RoKSB7CiAgICAgICAgICBDb2xvcl9kZWZhdWx0LnBhY2soY29sb3JzW2ldLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgfQogICAgICAgIEVsbGlwc29pZF9kZWZhdWx0LnBhY2sodmFsdWUuX2VsbGlwc29pZCwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2sodmFsdWUuX3ZlcnRleEZvcm1hdCwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fd2lkdGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IHZhbHVlLl9jb2xvcnNQZXJWZXJ0ZXggPyAxIDogMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2FyY1R5cGU7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleF0gPSB2YWx1ZS5fZ3JhbnVsYXJpdHk7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBzY3JhdGNoRWxsaXBzb2lkOCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKEVsbGlwc29pZF9kZWZhdWx0LlVOSVRfU1BIRVJFKTsKICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDEwID0gbmV3IFZlcnRleEZvcm1hdF9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hPcHRpb25zMTYgPSB7CiAgICAgICAgcG9zaXRpb25zOiB2b2lkIDAsCiAgICAgICAgY29sb3JzOiB2b2lkIDAsCiAgICAgICAgZWxsaXBzb2lkOiBzY3JhdGNoRWxsaXBzb2lkOCwKICAgICAgICB2ZXJ0ZXhGb3JtYXQ6IHNjcmF0Y2hWZXJ0ZXhGb3JtYXQxMCwKICAgICAgICB3aWR0aDogdm9pZCAwLAogICAgICAgIGNvbG9yc1BlclZlcnRleDogdm9pZCAwLAogICAgICAgIGFyY1R5cGU6IHZvaWQgMCwKICAgICAgICBncmFudWxhcml0eTogdm9pZCAwCiAgICAgIH07CiAgICAgIFBvbHlsaW5lR2VvbWV0cnkudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFycmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgbGV0IGxlbmd0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpLCBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGgpIHsKICAgICAgICAgIHBvc2l0aW9uc1tpXSA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIH0KICAgICAgICBsZW5ndGggPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IGNvbG9ycyA9IGxlbmd0aCA+IDAgPyBuZXcgQXJyYXkobGVuZ3RoKSA6IHZvaWQgMDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2ksIHN0YXJ0aW5nSW5kZXggKz0gQ29sb3JfZGVmYXVsdC5wYWNrZWRMZW5ndGgpIHsKICAgICAgICAgIGNvbG9yc1tpXSA9IENvbG9yX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoRWxsaXBzb2lkOCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgYXJyYXksCiAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDEwCiAgICAgICAgKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCB3aWR0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgY29sb3JzUGVyVmVydGV4ID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9PT0gMTsKICAgICAgICBjb25zdCBhcmNUeXBlID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTYucG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxNi5jb2xvcnMgPSBjb2xvcnM7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE2LndpZHRoID0gd2lkdGg7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE2LmNvbG9yc1BlclZlcnRleCA9IGNvbG9yc1BlclZlcnRleDsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTYuYXJjVHlwZSA9IGFyY1R5cGU7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE2LmdyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICAgICAgICByZXR1cm4gbmV3IFBvbHlsaW5lR2VvbWV0cnkoc2NyYXRjaE9wdGlvbnMxNik7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5fcG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgICAgIHJlc3VsdC5fY29sb3JzID0gY29sb3JzOwogICAgICAgIHJlc3VsdC5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoZWxsaXBzb2lkLCByZXN1bHQuX2VsbGlwc29pZCk7CiAgICAgICAgcmVzdWx0Ll92ZXJ0ZXhGb3JtYXQgPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5jbG9uZSh2ZXJ0ZXhGb3JtYXQsIHJlc3VsdC5fdmVydGV4Rm9ybWF0KTsKICAgICAgICByZXN1bHQuX3dpZHRoID0gd2lkdGg7CiAgICAgICAgcmVzdWx0Ll9jb2xvcnNQZXJWZXJ0ZXggPSBjb2xvcnNQZXJWZXJ0ZXg7CiAgICAgICAgcmVzdWx0Ll9hcmNUeXBlID0gYXJjVHlwZTsKICAgICAgICByZXN1bHQuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjM4ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUG9zaXRpb240ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUHJldlBvc2l0aW9uID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoTmV4dFBvc2l0aW9uID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBQb2x5bGluZUdlb21ldHJ5LmNyZWF0ZUdlb21ldHJ5ID0gZnVuY3Rpb24ocG9seWxpbmVHZW9tZXRyeSkgewogICAgICAgIGNvbnN0IHdpZHRoID0gcG9seWxpbmVHZW9tZXRyeS5fd2lkdGg7CiAgICAgICAgY29uc3QgdmVydGV4Rm9ybWF0ID0gcG9seWxpbmVHZW9tZXRyeS5fdmVydGV4Rm9ybWF0OwogICAgICAgIGxldCBjb2xvcnMgPSBwb2x5bGluZUdlb21ldHJ5Ll9jb2xvcnM7CiAgICAgICAgY29uc3QgY29sb3JzUGVyVmVydGV4ID0gcG9seWxpbmVHZW9tZXRyeS5fY29sb3JzUGVyVmVydGV4OwogICAgICAgIGNvbnN0IGFyY1R5cGUgPSBwb2x5bGluZUdlb21ldHJ5Ll9hcmNUeXBlOwogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gcG9seWxpbmVHZW9tZXRyeS5fZ3JhbnVsYXJpdHk7CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gcG9seWxpbmVHZW9tZXRyeS5fZWxsaXBzb2lkOwogICAgICAgIGxldCBpOwogICAgICAgIGxldCBqOwogICAgICAgIGxldCBrOwogICAgICAgIGNvbnN0IHJlbW92ZWRJbmRpY2VzID0gW107CiAgICAgICAgbGV0IHBvc2l0aW9ucyA9IGFycmF5UmVtb3ZlRHVwbGljYXRlc19kZWZhdWx0KAogICAgICAgICAgcG9seWxpbmVHZW9tZXRyeS5fcG9zaXRpb25zLAogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFsc0Vwc2lsb24sCiAgICAgICAgICBmYWxzZSwKICAgICAgICAgIHJlbW92ZWRJbmRpY2VzCiAgICAgICAgKTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGNvbG9ycykgJiYgcmVtb3ZlZEluZGljZXMubGVuZ3RoID4gMCkgewogICAgICAgICAgbGV0IHJlbW92ZWRBcnJheUluZGV4ID0gMDsKICAgICAgICAgIGxldCBuZXh0UmVtb3ZlZEluZGV4ID0gcmVtb3ZlZEluZGljZXNbMF07CiAgICAgICAgICBjb2xvcnMgPSBjb2xvcnMuZmlsdGVyKGZ1bmN0aW9uKGNvbG9yLCBpbmRleDIpIHsKICAgICAgICAgICAgbGV0IHJlbW92ZSA9IGZhbHNlOwogICAgICAgICAgICBpZiAoY29sb3JzUGVyVmVydGV4KSB7CiAgICAgICAgICAgICAgcmVtb3ZlID0gaW5kZXgyID09PSBuZXh0UmVtb3ZlZEluZGV4IHx8IGluZGV4MiA9PT0gMCAmJiBuZXh0UmVtb3ZlZEluZGV4ID09PSAxOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJlbW92ZSA9IGluZGV4MiArIDEgPT09IG5leHRSZW1vdmVkSW5kZXg7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJlbW92ZSkgewogICAgICAgICAgICAgIHJlbW92ZWRBcnJheUluZGV4Kys7CiAgICAgICAgICAgICAgbmV4dFJlbW92ZWRJbmRleCA9IHJlbW92ZWRJbmRpY2VzW3JlbW92ZWRBcnJheUluZGV4XTsKICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgbGV0IHBvc2l0aW9uc0xlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgaWYgKHBvc2l0aW9uc0xlbmd0aCA8IDIgfHwgd2lkdGggPD0gMCkgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgaWYgKGFyY1R5cGUgPT09IEFyY1R5cGVfZGVmYXVsdC5HRU9ERVNJQyB8fCBhcmNUeXBlID09PSBBcmNUeXBlX2RlZmF1bHQuUkhVTUIpIHsKICAgICAgICAgIGxldCBzdWJkaXZpc2lvblNpemU7CiAgICAgICAgICBsZXQgbnVtYmVyT2ZQb2ludHNGdW5jdGlvbjsKICAgICAgICAgIGlmIChhcmNUeXBlID09PSBBcmNUeXBlX2RlZmF1bHQuR0VPREVTSUMpIHsKICAgICAgICAgICAgc3ViZGl2aXNpb25TaXplID0gTWF0aF9kZWZhdWx0LmNob3JkTGVuZ3RoKAogICAgICAgICAgICAgIGdyYW51bGFyaXR5LAogICAgICAgICAgICAgIGVsbGlwc29pZC5tYXhpbXVtUmFkaXVzCiAgICAgICAgICAgICk7CiAgICAgICAgICAgIG51bWJlck9mUG9pbnRzRnVuY3Rpb24gPSBQb2x5bGluZVBpcGVsaW5lX2RlZmF1bHQubnVtYmVyT2ZQb2ludHM7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdWJkaXZpc2lvblNpemUgPSBncmFudWxhcml0eTsKICAgICAgICAgICAgbnVtYmVyT2ZQb2ludHNGdW5jdGlvbiA9IFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdC5udW1iZXJPZlBvaW50c1JodW1iTGluZTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGhlaWdodHMgPSBQb2x5bGluZVBpcGVsaW5lX2RlZmF1bHQuZXh0cmFjdEhlaWdodHMocG9zaXRpb25zLCBlbGxpcHNvaWQpOwogICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChjb2xvcnMpKSB7CiAgICAgICAgICAgIGxldCBjb2xvckxlbmd0aCA9IDE7CiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBwb3NpdGlvbnNMZW5ndGggLSAxOyArK2kpIHsKICAgICAgICAgICAgICBjb2xvckxlbmd0aCArPSBudW1iZXJPZlBvaW50c0Z1bmN0aW9uKAogICAgICAgICAgICAgICAgcG9zaXRpb25zW2ldLAogICAgICAgICAgICAgICAgcG9zaXRpb25zW2kgKyAxXSwKICAgICAgICAgICAgICAgIHN1YmRpdmlzaW9uU2l6ZQogICAgICAgICAgICAgICk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgbmV3Q29sb3JzID0gbmV3IEFycmF5KGNvbG9yTGVuZ3RoKTsKICAgICAgICAgICAgbGV0IG5ld0NvbG9ySW5kZXggPSAwOwogICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcG9zaXRpb25zTGVuZ3RoIC0gMTsgKytpKSB7CiAgICAgICAgICAgICAgY29uc3QgcDAgPSBwb3NpdGlvbnNbaV07CiAgICAgICAgICAgICAgY29uc3QgcDEgPSBwb3NpdGlvbnNbaSArIDFdOwogICAgICAgICAgICAgIGNvbnN0IGMwID0gY29sb3JzW2ldOwogICAgICAgICAgICAgIGNvbnN0IG51bUNvbG9ycyA9IG51bWJlck9mUG9pbnRzRnVuY3Rpb24ocDAsIHAxLCBzdWJkaXZpc2lvblNpemUpOwogICAgICAgICAgICAgIGlmIChjb2xvcnNQZXJWZXJ0ZXggJiYgaSA8IGNvbG9yTGVuZ3RoKSB7CiAgICAgICAgICAgICAgICBjb25zdCBjMSA9IGNvbG9yc1tpICsgMV07CiAgICAgICAgICAgICAgICBjb25zdCBpbnRlcnBvbGF0ZWRDb2xvcnMgPSBpbnRlcnBvbGF0ZUNvbG9ycygKICAgICAgICAgICAgICAgICAgcDAsCiAgICAgICAgICAgICAgICAgIHAxLAogICAgICAgICAgICAgICAgICBjMCwKICAgICAgICAgICAgICAgICAgYzEsCiAgICAgICAgICAgICAgICAgIG51bUNvbG9ycwogICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgIGNvbnN0IGludGVycG9sYXRlZENvbG9yc0xlbmd0aCA9IGludGVycG9sYXRlZENvbG9ycy5sZW5ndGg7CiAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgaW50ZXJwb2xhdGVkQ29sb3JzTGVuZ3RoOyArK2opIHsKICAgICAgICAgICAgICAgICAgbmV3Q29sb3JzW25ld0NvbG9ySW5kZXgrK10gPSBpbnRlcnBvbGF0ZWRDb2xvcnNbal07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBudW1Db2xvcnM7ICsraikgewogICAgICAgICAgICAgICAgICBuZXdDb2xvcnNbbmV3Q29sb3JJbmRleCsrXSA9IENvbG9yX2RlZmF1bHQuY2xvbmUoYzApOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBuZXdDb2xvcnNbbmV3Q29sb3JJbmRleF0gPSBDb2xvcl9kZWZhdWx0LmNsb25lKGNvbG9yc1tjb2xvcnMubGVuZ3RoIC0gMV0pOwogICAgICAgICAgICBjb2xvcnMgPSBuZXdDb2xvcnM7CiAgICAgICAgICAgIHNjcmF0Y2hJbnRlcnBvbGF0ZUNvbG9yc0FycmF5Lmxlbmd0aCA9IDA7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoYXJjVHlwZSA9PT0gQXJjVHlwZV9kZWZhdWx0LkdFT0RFU0lDKSB7CiAgICAgICAgICAgIHBvc2l0aW9ucyA9IFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdC5nZW5lcmF0ZUNhcnRlc2lhbkFyYyh7CiAgICAgICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgICAgIG1pbkRpc3RhbmNlOiBzdWJkaXZpc2lvblNpemUsCiAgICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICAgIGhlaWdodDogaGVpZ2h0cwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHBvc2l0aW9ucyA9IFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdC5nZW5lcmF0ZUNhcnRlc2lhblJodW1iQXJjKHsKICAgICAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICAgICAgZ3JhbnVsYXJpdHk6IHN1YmRpdmlzaW9uU2l6ZSwKICAgICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHRzCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBwb3NpdGlvbnNMZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgICAgIGNvbnN0IHNpemUgPSBwb3NpdGlvbnNMZW5ndGggKiA0IC0gNDsKICAgICAgICBjb25zdCBmaW5hbFBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkoc2l6ZSAqIDMpOwogICAgICAgIGNvbnN0IHByZXZQb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KHNpemUgKiAzKTsKICAgICAgICBjb25zdCBuZXh0UG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShzaXplICogMyk7CiAgICAgICAgY29uc3QgZXhwYW5kQW5kV2lkdGggPSBuZXcgRmxvYXQzMkFycmF5KHNpemUgKiAyKTsKICAgICAgICBjb25zdCBzdCA9IHZlcnRleEZvcm1hdC5zdCA/IG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSAqIDIpIDogdm9pZCAwOwogICAgICAgIGNvbnN0IGZpbmFsQ29sb3JzID0gZGVmaW5lZF9kZWZhdWx0KGNvbG9ycykgPyBuZXcgVWludDhBcnJheShzaXplICogNCkgOiB2b2lkIDA7CiAgICAgICAgbGV0IHBvc2l0aW9uSW5kZXggPSAwOwogICAgICAgIGxldCBleHBhbmRBbmRXaWR0aEluZGV4ID0gMDsKICAgICAgICBsZXQgc3RJbmRleCA9IDA7CiAgICAgICAgbGV0IGNvbG9ySW5kZXggPSAwOwogICAgICAgIGxldCBwb3NpdGlvbjsKICAgICAgICBmb3IgKGogPSAwOyBqIDwgcG9zaXRpb25zTGVuZ3RoOyArK2opIHsKICAgICAgICAgIGlmIChqID09PSAwKSB7CiAgICAgICAgICAgIHBvc2l0aW9uID0gc2NyYXRjaENhcnRlc2lhbjM4OwogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QocG9zaXRpb25zWzBdLCBwb3NpdGlvbnNbMV0sIHBvc2l0aW9uKTsKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChwb3NpdGlvbnNbMF0sIHBvc2l0aW9uLCBwb3NpdGlvbik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uc1tqIC0gMV07CiAgICAgICAgICB9CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocG9zaXRpb24sIHNjcmF0Y2hQcmV2UG9zaXRpb24pOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKHBvc2l0aW9uc1tqXSwgc2NyYXRjaFBvc2l0aW9uNCk7CiAgICAgICAgICBpZiAoaiA9PT0gcG9zaXRpb25zTGVuZ3RoIC0gMSkgewogICAgICAgICAgICBwb3NpdGlvbiA9IHNjcmF0Y2hDYXJ0ZXNpYW4zODsKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KAogICAgICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbnNMZW5ndGggLSAxXSwKICAgICAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25zTGVuZ3RoIC0gMl0sCiAgICAgICAgICAgICAgcG9zaXRpb24KICAgICAgICAgICAgKTsKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChwb3NpdGlvbnNbcG9zaXRpb25zTGVuZ3RoIC0gMV0sIHBvc2l0aW9uLCBwb3NpdGlvbik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uc1tqICsgMV07CiAgICAgICAgICB9CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUocG9zaXRpb24sIHNjcmF0Y2hOZXh0UG9zaXRpb24pOwogICAgICAgICAgbGV0IGNvbG9yMCwgY29sb3IxOwogICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChmaW5hbENvbG9ycykpIHsKICAgICAgICAgICAgaWYgKGogIT09IDAgJiYgIWNvbG9yc1BlclZlcnRleCkgewogICAgICAgICAgICAgIGNvbG9yMCA9IGNvbG9yc1tqIC0gMV07CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgY29sb3IwID0gY29sb3JzW2pdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChqICE9PSBwb3NpdGlvbnNMZW5ndGggLSAxKSB7CiAgICAgICAgICAgICAgY29sb3IxID0gY29sb3JzW2pdOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBzdGFydEsgPSBqID09PSAwID8gMiA6IDA7CiAgICAgICAgICBjb25zdCBlbmRLID0gaiA9PT0gcG9zaXRpb25zTGVuZ3RoIC0gMSA/IDIgOiA0OwogICAgICAgICAgZm9yIChrID0gc3RhcnRLOyBrIDwgZW5kSzsgKytrKSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHNjcmF0Y2hQb3NpdGlvbjQsIGZpbmFsUG9zaXRpb25zLCBwb3NpdGlvbkluZGV4KTsKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soc2NyYXRjaFByZXZQb3NpdGlvbiwgcHJldlBvc2l0aW9ucywgcG9zaXRpb25JbmRleCk7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHNjcmF0Y2hOZXh0UG9zaXRpb24sIG5leHRQb3NpdGlvbnMsIHBvc2l0aW9uSW5kZXgpOwogICAgICAgICAgICBwb3NpdGlvbkluZGV4ICs9IDM7CiAgICAgICAgICAgIGNvbnN0IGRpcmVjdGlvbjIgPSBrIC0gMiA8IDAgPyAtMSA6IDE7CiAgICAgICAgICAgIGV4cGFuZEFuZFdpZHRoW2V4cGFuZEFuZFdpZHRoSW5kZXgrK10gPSAyICogKGsgJSAyKSAtIDE7CiAgICAgICAgICAgIGV4cGFuZEFuZFdpZHRoW2V4cGFuZEFuZFdpZHRoSW5kZXgrK10gPSBkaXJlY3Rpb24yICogd2lkdGg7CiAgICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICAgICAgICBzdFtzdEluZGV4KytdID0gaiAvIChwb3NpdGlvbnNMZW5ndGggLSAxKTsKICAgICAgICAgICAgICBzdFtzdEluZGV4KytdID0gTWF0aC5tYXgoZXhwYW5kQW5kV2lkdGhbZXhwYW5kQW5kV2lkdGhJbmRleCAtIDJdLCAwKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGZpbmFsQ29sb3JzKSkgewogICAgICAgICAgICAgIGNvbnN0IGNvbG9yID0gayA8IDIgPyBjb2xvcjAgOiBjb2xvcjE7CiAgICAgICAgICAgICAgZmluYWxDb2xvcnNbY29sb3JJbmRleCsrXSA9IENvbG9yX2RlZmF1bHQuZmxvYXRUb0J5dGUoY29sb3IucmVkKTsKICAgICAgICAgICAgICBmaW5hbENvbG9yc1tjb2xvckluZGV4KytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShjb2xvci5ncmVlbik7CiAgICAgICAgICAgICAgZmluYWxDb2xvcnNbY29sb3JJbmRleCsrXSA9IENvbG9yX2RlZmF1bHQuZmxvYXRUb0J5dGUoY29sb3IuYmx1ZSk7CiAgICAgICAgICAgICAgZmluYWxDb2xvcnNbY29sb3JJbmRleCsrXSA9IENvbG9yX2RlZmF1bHQuZmxvYXRUb0J5dGUoY29sb3IuYWxwaGEpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoKTsKICAgICAgICBhdHRyaWJ1dGVzLnBvc2l0aW9uID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFLAogICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgIHZhbHVlczogZmluYWxQb3NpdGlvbnMKICAgICAgICB9KTsKICAgICAgICBhdHRyaWJ1dGVzLnByZXZQb3NpdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICB2YWx1ZXM6IHByZXZQb3NpdGlvbnMKICAgICAgICB9KTsKICAgICAgICBhdHRyaWJ1dGVzLm5leHRQb3NpdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICB2YWx1ZXM6IG5leHRQb3NpdGlvbnMKICAgICAgICB9KTsKICAgICAgICBhdHRyaWJ1dGVzLmV4cGFuZEFuZFdpZHRoID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAyLAogICAgICAgICAgdmFsdWVzOiBleHBhbmRBbmRXaWR0aAogICAgICAgIH0pOwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICAgIGF0dHJpYnV0ZXMuc3QgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAyLAogICAgICAgICAgICB2YWx1ZXM6IHN0CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChmaW5hbENvbG9ycykpIHsKICAgICAgICAgIGF0dHJpYnV0ZXMuY29sb3IgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEUsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDQsCiAgICAgICAgICAgIHZhbHVlczogZmluYWxDb2xvcnMsCiAgICAgICAgICAgIG5vcm1hbGl6ZTogdHJ1ZQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheShzaXplLCBwb3NpdGlvbnNMZW5ndGggKiA2IC0gNik7CiAgICAgICAgbGV0IGluZGV4ID0gMDsKICAgICAgICBsZXQgaW5kaWNlc0luZGV4ID0gMDsKICAgICAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnNMZW5ndGggLSAxOwogICAgICAgIGZvciAoaiA9IDA7IGogPCBsZW5ndGg7ICsraikgewogICAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBpbmRleDsKICAgICAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaW5kZXggKyAyOwogICAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBpbmRleCArIDE7CiAgICAgICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGluZGV4ICsgMTsKICAgICAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaW5kZXggKyAyOwogICAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBpbmRleCArIDM7CiAgICAgICAgICBpbmRleCArPSA0OwogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgICAgYXR0cmlidXRlcywKICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBQcmltaXRpdmVUeXBlX2RlZmF1bHQuVFJJQU5HTEVTLAogICAgICAgICAgYm91bmRpbmdTcGhlcmU6IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbVBvaW50cyhwb3NpdGlvbnMpLAogICAgICAgICAgZ2VvbWV0cnlUeXBlOiBHZW9tZXRyeVR5cGVfZGVmYXVsdC5QT0xZTElORVMKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgUG9seWxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gUG9seWxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVBvbHlsaW5lR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlUG9seWxpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlUG9seWxpbmVHZW9tZXRyeV9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVQb2x5bGluZUdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVQb2x5bGluZUdlb21ldHJ5KHBvbHlsaW5lR2VvbWV0cnksIG9mZnNldCkgewogICAgaWYgKGRlZmluZWRfZGVmYXVsdChvZmZzZXQpKSB7CiAgICAgIHBvbHlsaW5lR2VvbWV0cnkgPSBQb2x5bGluZUdlb21ldHJ5X2RlZmF1bHQudW5wYWNrKHBvbHlsaW5lR2VvbWV0cnksIG9mZnNldCk7CiAgICB9CiAgICBwb2x5bGluZUdlb21ldHJ5Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShwb2x5bGluZUdlb21ldHJ5Ll9lbGxpcHNvaWQpOwogICAgcmV0dXJuIFBvbHlsaW5lR2VvbWV0cnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeShwb2x5bGluZUdlb21ldHJ5KTsKICB9CiAgdmFyIGNyZWF0ZVBvbHlsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVQb2x5bGluZUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVQb2x5bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfUG9seWxpbmVHZW9tZXRyeSgpOwogICAgICBjcmVhdGVQb2x5bGluZUdlb21ldHJ5X2RlZmF1bHQgPSBjcmVhdGVQb2x5bGluZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUG9seWxpbmVWb2x1bWVHZW9tZXRyeS5qcwogIGZ1bmN0aW9uIGNvbXB1dGVBdHRyaWJ1dGVzMihjb21iaW5lZFBvc2l0aW9ucywgc2hhcGUsIGJvdW5kaW5nUmVjdGFuZ2xlLCB2ZXJ0ZXhGb3JtYXQpIHsKICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoKTsKICAgIGlmICh2ZXJ0ZXhGb3JtYXQucG9zaXRpb24pIHsKICAgICAgYXR0cmlidXRlcy5wb3NpdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IGNvbWJpbmVkUG9zaXRpb25zCiAgICAgIH0pOwogICAgfQogICAgY29uc3Qgc2hhcGVMZW5ndGggPSBzaGFwZS5sZW5ndGg7CiAgICBjb25zdCB2ZXJ0ZXhDb3VudCA9IGNvbWJpbmVkUG9zaXRpb25zLmxlbmd0aCAvIDM7CiAgICBjb25zdCBsZW5ndGggPSAodmVydGV4Q291bnQgLSBzaGFwZUxlbmd0aCAqIDIpIC8gKHNoYXBlTGVuZ3RoICogMik7CiAgICBjb25zdCBmaXJzdEVuZEluZGljZXMgPSBQb2x5Z29uUGlwZWxpbmVfZGVmYXVsdC50cmlhbmd1bGF0ZShzaGFwZSk7CiAgICBjb25zdCBpbmRpY2VzQ291bnQgPSAobGVuZ3RoIC0gMSkgKiBzaGFwZUxlbmd0aCAqIDYgKyBmaXJzdEVuZEluZGljZXMubGVuZ3RoICogMjsKICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSh2ZXJ0ZXhDb3VudCwgaW5kaWNlc0NvdW50KTsKICAgIGxldCBpLCBqOwogICAgbGV0IGxsLCB1bCwgdXIsIGxyOwogICAgY29uc3Qgb2Zmc2V0ID0gc2hhcGVMZW5ndGggKiAyOwogICAgbGV0IGluZGV4ID0gMDsKICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGggLSAxOyBpKyspIHsKICAgICAgZm9yIChqID0gMDsgaiA8IHNoYXBlTGVuZ3RoIC0gMTsgaisrKSB7CiAgICAgICAgbGwgPSBqICogMiArIGkgKiBzaGFwZUxlbmd0aCAqIDI7CiAgICAgICAgbHIgPSBsbCArIG9mZnNldDsKICAgICAgICB1bCA9IGxsICsgMTsKICAgICAgICB1ciA9IHVsICsgb2Zmc2V0OwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSB1bDsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gbGw7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHVyOwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSB1cjsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gbGw7CiAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGxyOwogICAgICB9CiAgICAgIGxsID0gc2hhcGVMZW5ndGggKiAyIC0gMiArIGkgKiBzaGFwZUxlbmd0aCAqIDI7CiAgICAgIHVsID0gbGwgKyAxOwogICAgICB1ciA9IHVsICsgb2Zmc2V0OwogICAgICBsciA9IGxsICsgb2Zmc2V0OwogICAgICBpbmRpY2VzW2luZGV4KytdID0gdWw7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBsbDsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHVyOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gdXI7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBsbDsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGxyOwogICAgfQogICAgaWYgKHZlcnRleEZvcm1hdC5zdCB8fCB2ZXJ0ZXhGb3JtYXQudGFuZ2VudCB8fCB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgIGNvbnN0IHN0ID0gbmV3IEZsb2F0MzJBcnJheSh2ZXJ0ZXhDb3VudCAqIDIpOwogICAgICBjb25zdCBsZW5ndGhTdCA9IDEgLyAobGVuZ3RoIC0gMSk7CiAgICAgIGNvbnN0IGhlaWdodFN0ID0gMSAvIGJvdW5kaW5nUmVjdGFuZ2xlLmhlaWdodDsKICAgICAgY29uc3QgaGVpZ2h0T2Zmc2V0ID0gYm91bmRpbmdSZWN0YW5nbGUuaGVpZ2h0IC8gMjsKICAgICAgbGV0IHMsIHQ7CiAgICAgIGxldCBzdGluZGV4ID0gMDsKICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgcyA9IGkgKiBsZW5ndGhTdDsKICAgICAgICB0ID0gaGVpZ2h0U3QgKiAoc2hhcGVbMF0ueSArIGhlaWdodE9mZnNldCk7CiAgICAgICAgc3Rbc3RpbmRleCsrXSA9IHM7CiAgICAgICAgc3Rbc3RpbmRleCsrXSA9IHQ7CiAgICAgICAgZm9yIChqID0gMTsgaiA8IHNoYXBlTGVuZ3RoOyBqKyspIHsKICAgICAgICAgIHQgPSBoZWlnaHRTdCAqIChzaGFwZVtqXS55ICsgaGVpZ2h0T2Zmc2V0KTsKICAgICAgICAgIHN0W3N0aW5kZXgrK10gPSBzOwogICAgICAgICAgc3Rbc3RpbmRleCsrXSA9IHQ7CiAgICAgICAgICBzdFtzdGluZGV4KytdID0gczsKICAgICAgICAgIHN0W3N0aW5kZXgrK10gPSB0OwogICAgICAgIH0KICAgICAgICB0ID0gaGVpZ2h0U3QgKiAoc2hhcGVbMF0ueSArIGhlaWdodE9mZnNldCk7CiAgICAgICAgc3Rbc3RpbmRleCsrXSA9IHM7CiAgICAgICAgc3Rbc3RpbmRleCsrXSA9IHQ7CiAgICAgIH0KICAgICAgZm9yIChqID0gMDsgaiA8IHNoYXBlTGVuZ3RoOyBqKyspIHsKICAgICAgICBzID0gMDsKICAgICAgICB0ID0gaGVpZ2h0U3QgKiAoc2hhcGVbal0ueSArIGhlaWdodE9mZnNldCk7CiAgICAgICAgc3Rbc3RpbmRleCsrXSA9IHM7CiAgICAgICAgc3Rbc3RpbmRleCsrXSA9IHQ7CiAgICAgIH0KICAgICAgZm9yIChqID0gMDsgaiA8IHNoYXBlTGVuZ3RoOyBqKyspIHsKICAgICAgICBzID0gKGxlbmd0aCAtIDEpICogbGVuZ3RoU3Q7CiAgICAgICAgdCA9IGhlaWdodFN0ICogKHNoYXBlW2pdLnkgKyBoZWlnaHRPZmZzZXQpOwogICAgICAgIHN0W3N0aW5kZXgrK10gPSBzOwogICAgICAgIHN0W3N0aW5kZXgrK10gPSB0OwogICAgICB9CiAgICAgIGF0dHJpYnV0ZXMuc3QgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMiwKICAgICAgICB2YWx1ZXM6IG5ldyBGbG9hdDMyQXJyYXkoc3QpCiAgICAgIH0pOwogICAgfQogICAgY29uc3QgZW5kT2Zmc2V0ID0gdmVydGV4Q291bnQgLSBzaGFwZUxlbmd0aCAqIDI7CiAgICBmb3IgKGkgPSAwOyBpIDwgZmlyc3RFbmRJbmRpY2VzLmxlbmd0aDsgaSArPSAzKSB7CiAgICAgIGNvbnN0IHYwMiA9IGZpcnN0RW5kSW5kaWNlc1tpXSArIGVuZE9mZnNldDsKICAgICAgY29uc3QgdjEyID0gZmlyc3RFbmRJbmRpY2VzW2kgKyAxXSArIGVuZE9mZnNldDsKICAgICAgY29uc3QgdjIyID0gZmlyc3RFbmRJbmRpY2VzW2kgKyAyXSArIGVuZE9mZnNldDsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHYwMjsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHYxMjsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHYyMjsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHYyMiArIHNoYXBlTGVuZ3RoOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gdjEyICsgc2hhcGVMZW5ndGg7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSB2MDIgKyBzaGFwZUxlbmd0aDsKICAgIH0KICAgIGxldCBnZW9tZXRyeSA9IG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgYXR0cmlidXRlcywKICAgICAgaW5kaWNlcywKICAgICAgYm91bmRpbmdTcGhlcmU6IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbVZlcnRpY2VzKGNvbWJpbmVkUG9zaXRpb25zKSwKICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUwogICAgfSk7CiAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCkgewogICAgICBnZW9tZXRyeSA9IEdlb21ldHJ5UGlwZWxpbmVfZGVmYXVsdC5jb21wdXRlTm9ybWFsKGdlb21ldHJ5KTsKICAgIH0KICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCB8fCB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgIHRyeSB7CiAgICAgICAgZ2VvbWV0cnkgPSBHZW9tZXRyeVBpcGVsaW5lX2RlZmF1bHQuY29tcHV0ZVRhbmdlbnRBbmRCaXRhbmdlbnQoZ2VvbWV0cnkpOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgb25lVGltZVdhcm5pbmdfZGVmYXVsdCgKICAgICAgICAgICJwb2x5bGluZS12b2x1bWUtdGFuZ2VudC1iaXRhbmdlbnQiLAogICAgICAgICAgIlVuYWJsZSB0byBjb21wdXRlIHRhbmdlbnRzIGFuZCBiaXRhbmdlbnRzIGZvciBwb2x5bGluZSB2b2x1bWUgZ2VvbWV0cnkiCiAgICAgICAgKTsKICAgICAgfQogICAgICBpZiAoIXZlcnRleEZvcm1hdC50YW5nZW50KSB7CiAgICAgICAgZ2VvbWV0cnkuYXR0cmlidXRlcy50YW5nZW50ID0gdm9pZCAwOwogICAgICB9CiAgICAgIGlmICghdmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMuYml0YW5nZW50ID0gdm9pZCAwOwogICAgICB9CiAgICAgIGlmICghdmVydGV4Rm9ybWF0LnN0KSB7CiAgICAgICAgZ2VvbWV0cnkuYXR0cmlidXRlcy5zdCA9IHZvaWQgMDsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGdlb21ldHJ5OwogIH0KICBmdW5jdGlvbiBQb2x5bGluZVZvbHVtZUdlb21ldHJ5KG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IG9wdGlvbnMucG9seWxpbmVQb3NpdGlvbnM7CiAgICBjb25zdCBzaGFwZSA9IG9wdGlvbnMuc2hhcGVQb3NpdGlvbnM7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwb3NpdGlvbnMpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJvcHRpb25zLnBvbHlsaW5lUG9zaXRpb25zIGlzIHJlcXVpcmVkLiIpOwogICAgfQogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoc2hhcGUpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJvcHRpb25zLnNoYXBlUG9zaXRpb25zIGlzIHJlcXVpcmVkLiIpOwogICAgfQogICAgdGhpcy5fcG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgdGhpcy5fc2hhcGUgPSBzaGFwZTsKICAgIHRoaXMuX2VsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKG9wdGlvbnMuZWxsaXBzb2lkID8/IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQpOwogICAgdGhpcy5fY29ybmVyVHlwZSA9IG9wdGlvbnMuY29ybmVyVHlwZSA/PyBDb3JuZXJUeXBlX2RlZmF1bHQuUk9VTkRFRDsKICAgIHRoaXMuX3ZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LmNsb25lKAogICAgICBvcHRpb25zLnZlcnRleEZvcm1hdCA/PyBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5ERUZBVUxUCiAgICApOwogICAgdGhpcy5fZ3JhbnVsYXJpdHkgPSBvcHRpb25zLmdyYW51bGFyaXR5ID8/IE1hdGhfZGVmYXVsdC5SQURJQU5TX1BFUl9ERUdSRUU7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZVBvbHlsaW5lVm9sdW1lR2VvbWV0cnkiOwogICAgbGV0IG51bUNvbXBvbmVudHMgPSAxICsgcG9zaXRpb25zLmxlbmd0aCAqIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICBudW1Db21wb25lbnRzICs9IDEgKyBzaGFwZS5sZW5ndGggKiBDYXJ0ZXNpYW4yX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgdGhpcy5wYWNrZWRMZW5ndGggPSBudW1Db21wb25lbnRzICsgRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoICsgVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFja2VkTGVuZ3RoICsgMjsKICB9CiAgdmFyIHNjcmF0Y2hFbGxpcHNvaWQ5LCBzY3JhdGNoVmVydGV4Rm9ybWF0MTEsIHNjcmF0Y2hPcHRpb25zMTcsIGJyU2NyYXRjaCwgUG9seWxpbmVWb2x1bWVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X1BvbHlsaW5lVm9sdW1lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1BvbHlsaW5lVm9sdW1lR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X2FycmF5UmVtb3ZlRHVwbGljYXRlcygpOwogICAgICBpbml0X0JvdW5kaW5nUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4yKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NvbXBvbmVudERhdGF0eXBlKCk7CiAgICAgIGluaXRfQ29ybmVyVHlwZSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZXMoKTsKICAgICAgaW5pdF9HZW9tZXRyeVBpcGVsaW5lKCk7CiAgICAgIGluaXRfSW5kZXhEYXRhdHlwZSgpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9vbmVUaW1lV2FybmluZygpOwogICAgICBpbml0X1BvbHlnb25QaXBlbGluZSgpOwogICAgICBpbml0X1BvbHlsaW5lVm9sdW1lR2VvbWV0cnlMaWJyYXJ5KCk7CiAgICAgIGluaXRfUHJpbWl0aXZlVHlwZSgpOwogICAgICBpbml0X1ZlcnRleEZvcm1hdCgpOwogICAgICBpbml0X1dpbmRpbmdPcmRlcigpOwogICAgICBQb2x5bGluZVZvbHVtZUdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh2YWx1ZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ2YWx1ZSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhcnJheSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhcnJheSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGxldCBpOwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IHZhbHVlLl9wb3NpdGlvbnM7CiAgICAgICAgbGV0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IGxlbmd0aDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2ksIHN0YXJ0aW5nSW5kZXggKz0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCkgewogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2socG9zaXRpb25zW2ldLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHNoYXBlID0gdmFsdWUuX3NoYXBlOwogICAgICAgIGxlbmd0aCA9IHNoYXBlLmxlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gbGVuZ3RoOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSwgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4yX2RlZmF1bHQucGFja2VkTGVuZ3RoKSB7CiAgICAgICAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQucGFjayhzaGFwZVtpXSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIH0KICAgICAgICBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrKHZhbHVlLl9lbGxpcHNvaWQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrKHZhbHVlLl92ZXJ0ZXhGb3JtYXQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2Nvcm5lclR5cGU7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleF0gPSB2YWx1ZS5fZ3JhbnVsYXJpdHk7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBzY3JhdGNoRWxsaXBzb2lkOSA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKEVsbGlwc29pZF9kZWZhdWx0LlVOSVRfU1BIRVJFKTsKICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDExID0gbmV3IFZlcnRleEZvcm1hdF9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hPcHRpb25zMTcgPSB7CiAgICAgICAgcG9seWxpbmVQb3NpdGlvbnM6IHZvaWQgMCwKICAgICAgICBzaGFwZVBvc2l0aW9uczogdm9pZCAwLAogICAgICAgIGVsbGlwc29pZDogc2NyYXRjaEVsbGlwc29pZDksCiAgICAgICAgdmVydGV4Rm9ybWF0OiBzY3JhdGNoVmVydGV4Rm9ybWF0MTEsCiAgICAgICAgY29ybmVyVHlwZTogdm9pZCAwLAogICAgICAgIGdyYW51bGFyaXR5OiB2b2lkIDAKICAgICAgfTsKICAgICAgUG9seWxpbmVWb2x1bWVHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYXJyYXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYXJyYXkgaXMgcmVxdWlyZWQiKTsKICAgICAgICB9CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBsZXQgaTsKICAgICAgICBsZXQgbGVuZ3RoID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgQXJyYXkobGVuZ3RoKTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2ksIHN0YXJ0aW5nSW5kZXggKz0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCkgewogICAgICAgICAgcG9zaXRpb25zW2ldID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgfQogICAgICAgIGxlbmd0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3Qgc2hhcGUgPSBuZXcgQXJyYXkobGVuZ3RoKTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2ksIHN0YXJ0aW5nSW5kZXggKz0gQ2FydGVzaWFuMl9kZWZhdWx0LnBhY2tlZExlbmd0aCkgewogICAgICAgICAgc2hhcGVbaV0gPSBDYXJ0ZXNpYW4yX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoRWxsaXBzb2lkOSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgYXJyYXksCiAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDExCiAgICAgICAgKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCBjb3JuZXJUeXBlID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTcucG9seWxpbmVQb3NpdGlvbnMgPSBwb3NpdGlvbnM7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE3LnNoYXBlUG9zaXRpb25zID0gc2hhcGU7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE3LmNvcm5lclR5cGUgPSBjb3JuZXJUeXBlOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxNy5ncmFudWxhcml0eSA9IGdyYW51bGFyaXR5OwogICAgICAgICAgcmV0dXJuIG5ldyBQb2x5bGluZVZvbHVtZUdlb21ldHJ5KHNjcmF0Y2hPcHRpb25zMTcpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuX3Bvc2l0aW9ucyA9IHBvc2l0aW9uczsKICAgICAgICByZXN1bHQuX3NoYXBlID0gc2hhcGU7CiAgICAgICAgcmVzdWx0Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShlbGxpcHNvaWQsIHJlc3VsdC5fZWxsaXBzb2lkKTsKICAgICAgICByZXN1bHQuX3ZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LmNsb25lKHZlcnRleEZvcm1hdCwgcmVzdWx0Ll92ZXJ0ZXhGb3JtYXQpOwogICAgICAgIHJlc3VsdC5fY29ybmVyVHlwZSA9IGNvcm5lclR5cGU7CiAgICAgICAgcmVzdWx0Ll9ncmFudWxhcml0eSA9IGdyYW51bGFyaXR5OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIGJyU2NyYXRjaCA9IG5ldyBCb3VuZGluZ1JlY3RhbmdsZV9kZWZhdWx0KCk7CiAgICAgIFBvbHlsaW5lVm9sdW1lR2VvbWV0cnkuY3JlYXRlR2VvbWV0cnkgPSBmdW5jdGlvbihwb2x5bGluZVZvbHVtZUdlb21ldHJ5KSB7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gcG9seWxpbmVWb2x1bWVHZW9tZXRyeS5fcG9zaXRpb25zOwogICAgICAgIGNvbnN0IGNsZWFuUG9zaXRpb25zID0gYXJyYXlSZW1vdmVEdXBsaWNhdGVzX2RlZmF1bHQoCiAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbgogICAgICAgICk7CiAgICAgICAgbGV0IHNoYXBlMkQgPSBwb2x5bGluZVZvbHVtZUdlb21ldHJ5Ll9zaGFwZTsKICAgICAgICBzaGFwZTJEID0gUG9seWxpbmVWb2x1bWVHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5yZW1vdmVEdXBsaWNhdGVzRnJvbVNoYXBlKHNoYXBlMkQpOwogICAgICAgIGlmIChjbGVhblBvc2l0aW9ucy5sZW5ndGggPCAyIHx8IHNoYXBlMkQubGVuZ3RoIDwgMykgewogICAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgICB9CiAgICAgICAgaWYgKFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LmNvbXB1dGVXaW5kaW5nT3JkZXIyRChzaGFwZTJEKSA9PT0gV2luZGluZ09yZGVyX2RlZmF1bHQuQ0xPQ0tXSVNFKSB7CiAgICAgICAgICBzaGFwZTJELnJldmVyc2UoKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgYm91bmRpbmdSZWN0YW5nbGUgPSBCb3VuZGluZ1JlY3RhbmdsZV9kZWZhdWx0LmZyb21Qb2ludHMoc2hhcGUyRCwgYnJTY3JhdGNoKTsKICAgICAgICBjb25zdCBjb21wdXRlZFBvc2l0aW9ucyA9IFBvbHlsaW5lVm9sdW1lR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZVBvc2l0aW9ucygKICAgICAgICAgIGNsZWFuUG9zaXRpb25zLAogICAgICAgICAgc2hhcGUyRCwKICAgICAgICAgIGJvdW5kaW5nUmVjdGFuZ2xlLAogICAgICAgICAgcG9seWxpbmVWb2x1bWVHZW9tZXRyeSwKICAgICAgICAgIHRydWUKICAgICAgICApOwogICAgICAgIHJldHVybiBjb21wdXRlQXR0cmlidXRlczIoCiAgICAgICAgICBjb21wdXRlZFBvc2l0aW9ucywKICAgICAgICAgIHNoYXBlMkQsCiAgICAgICAgICBib3VuZGluZ1JlY3RhbmdsZSwKICAgICAgICAgIHBvbHlsaW5lVm9sdW1lR2VvbWV0cnkuX3ZlcnRleEZvcm1hdAogICAgICAgICk7CiAgICAgIH07CiAgICAgIFBvbHlsaW5lVm9sdW1lR2VvbWV0cnlfZGVmYXVsdCA9IFBvbHlsaW5lVm9sdW1lR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVQb2x5bGluZVZvbHVtZUdlb21ldHJ5LmpzCiAgdmFyIGNyZWF0ZVBvbHlsaW5lVm9sdW1lR2VvbWV0cnlfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZVBvbHlsaW5lVm9sdW1lR2VvbWV0cnlfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlUG9seWxpbmVWb2x1bWVHZW9tZXRyeV9kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gY3JlYXRlUG9seWxpbmVWb2x1bWVHZW9tZXRyeShwb2x5bGluZVZvbHVtZUdlb21ldHJ5LCBvZmZzZXQpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob2Zmc2V0KSkgewogICAgICBwb2x5bGluZVZvbHVtZUdlb21ldHJ5ID0gUG9seWxpbmVWb2x1bWVHZW9tZXRyeV9kZWZhdWx0LnVucGFjaygKICAgICAgICBwb2x5bGluZVZvbHVtZUdlb21ldHJ5LAogICAgICAgIG9mZnNldAogICAgICApOwogICAgfQogICAgcG9seWxpbmVWb2x1bWVHZW9tZXRyeS5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoCiAgICAgIHBvbHlsaW5lVm9sdW1lR2VvbWV0cnkuX2VsbGlwc29pZAogICAgKTsKICAgIHJldHVybiBQb2x5bGluZVZvbHVtZUdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkocG9seWxpbmVWb2x1bWVHZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVQb2x5bGluZVZvbHVtZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlUG9seWxpbmVWb2x1bWVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlUG9seWxpbmVWb2x1bWVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X1BvbHlsaW5lVm9sdW1lR2VvbWV0cnkoKTsKICAgICAgY3JlYXRlUG9seWxpbmVWb2x1bWVHZW9tZXRyeV9kZWZhdWx0ID0gY3JlYXRlUG9seWxpbmVWb2x1bWVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1BvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gY29tcHV0ZUF0dHJpYnV0ZXMzKHBvc2l0aW9ucywgc2hhcGUpIHsKICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoKTsKICAgIGF0dHJpYnV0ZXMucG9zaXRpb24gPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgdmFsdWVzOiBwb3NpdGlvbnMKICAgIH0pOwogICAgY29uc3Qgc2hhcGVMZW5ndGggPSBzaGFwZS5sZW5ndGg7CiAgICBjb25zdCB2ZXJ0ZXhDb3VudCA9IGF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLmxlbmd0aCAvIDM7CiAgICBjb25zdCBwb3NpdGlvbkxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGggLyAzOwogICAgY29uc3Qgc2hhcGVDb3VudCA9IHBvc2l0aW9uTGVuZ3RoIC8gc2hhcGVMZW5ndGg7CiAgICBjb25zdCBpbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgIHZlcnRleENvdW50LAogICAgICAyICogc2hhcGVMZW5ndGggKiAoc2hhcGVDb3VudCArIDEpCiAgICApOwogICAgbGV0IGksIGo7CiAgICBsZXQgaW5kZXggPSAwOwogICAgaSA9IDA7CiAgICBsZXQgb2Zmc2V0ID0gaSAqIHNoYXBlTGVuZ3RoOwogICAgZm9yIChqID0gMDsgaiA8IHNoYXBlTGVuZ3RoIC0gMTsgaisrKSB7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBqICsgb2Zmc2V0OwogICAgICBpbmRpY2VzW2luZGV4KytdID0gaiArIG9mZnNldCArIDE7CiAgICB9CiAgICBpbmRpY2VzW2luZGV4KytdID0gc2hhcGVMZW5ndGggLSAxICsgb2Zmc2V0OwogICAgaW5kaWNlc1tpbmRleCsrXSA9IG9mZnNldDsKICAgIGkgPSBzaGFwZUNvdW50IC0gMTsKICAgIG9mZnNldCA9IGkgKiBzaGFwZUxlbmd0aDsKICAgIGZvciAoaiA9IDA7IGogPCBzaGFwZUxlbmd0aCAtIDE7IGorKykgewogICAgICBpbmRpY2VzW2luZGV4KytdID0gaiArIG9mZnNldDsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGogKyBvZmZzZXQgKyAxOwogICAgfQogICAgaW5kaWNlc1tpbmRleCsrXSA9IHNoYXBlTGVuZ3RoIC0gMSArIG9mZnNldDsKICAgIGluZGljZXNbaW5kZXgrK10gPSBvZmZzZXQ7CiAgICBmb3IgKGkgPSAwOyBpIDwgc2hhcGVDb3VudCAtIDE7IGkrKykgewogICAgICBjb25zdCBmaXJzdE9mZnNldCA9IHNoYXBlTGVuZ3RoICogaTsKICAgICAgY29uc3Qgc2Vjb25kT2Zmc2V0ID0gZmlyc3RPZmZzZXQgKyBzaGFwZUxlbmd0aDsKICAgICAgZm9yIChqID0gMDsgaiA8IHNoYXBlTGVuZ3RoOyBqKyspIHsKICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gaiArIGZpcnN0T2Zmc2V0OwogICAgICAgIGluZGljZXNbaW5kZXgrK10gPSBqICsgc2Vjb25kT2Zmc2V0OwogICAgICB9CiAgICB9CiAgICBjb25zdCBnZW9tZXRyeSA9IG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgYXR0cmlidXRlcywKICAgICAgaW5kaWNlczogSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkodmVydGV4Q291bnQsIGluZGljZXMpLAogICAgICBib3VuZGluZ1NwaGVyZTogQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5mcm9tVmVydGljZXMocG9zaXRpb25zKSwKICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LkxJTkVTCiAgICB9KTsKICAgIHJldHVybiBnZW9tZXRyeTsKICB9CiAgZnVuY3Rpb24gUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgY29uc3QgcG9zaXRpb25zID0gb3B0aW9ucy5wb2x5bGluZVBvc2l0aW9uczsKICAgIGNvbnN0IHNoYXBlID0gb3B0aW9ucy5zaGFwZVBvc2l0aW9uczsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHBvc2l0aW9ucykpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9wdGlvbnMucG9seWxpbmVQb3NpdGlvbnMgaXMgcmVxdWlyZWQuIik7CiAgICB9CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChzaGFwZSkpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9wdGlvbnMuc2hhcGVQb3NpdGlvbnMgaXMgcmVxdWlyZWQuIik7CiAgICB9CiAgICB0aGlzLl9wb3NpdGlvbnMgPSBwb3NpdGlvbnM7CiAgICB0aGlzLl9zaGFwZSA9IHNoYXBlOwogICAgdGhpcy5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUob3B0aW9ucy5lbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdCk7CiAgICB0aGlzLl9jb3JuZXJUeXBlID0gb3B0aW9ucy5jb3JuZXJUeXBlID8/IENvcm5lclR5cGVfZGVmYXVsdC5ST1VOREVEOwogICAgdGhpcy5fZ3JhbnVsYXJpdHkgPSBvcHRpb25zLmdyYW51bGFyaXR5ID8/IE1hdGhfZGVmYXVsdC5SQURJQU5TX1BFUl9ERUdSRUU7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZVBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5IjsKICAgIGxldCBudW1Db21wb25lbnRzID0gMSArIHBvc2l0aW9ucy5sZW5ndGggKiBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgbnVtQ29tcG9uZW50cyArPSAxICsgc2hhcGUubGVuZ3RoICogQ2FydGVzaWFuMl9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgIHRoaXMucGFja2VkTGVuZ3RoID0gbnVtQ29tcG9uZW50cyArIEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIDI7CiAgfQogIHZhciBzY3JhdGNoRWxsaXBzb2lkMTAsIHNjcmF0Y2hPcHRpb25zMTgsIGJyU2NyYXRjaDIsIFBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1BvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9hcnJheVJlbW92ZUR1cGxpY2F0ZXMoKTsKICAgICAgaW5pdF9Cb3VuZGluZ1JlY3RhbmdsZSgpOwogICAgICBpbml0X0JvdW5kaW5nU3BoZXJlKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMigpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X0Nvcm5lclR5cGUoKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9HZW9tZXRyeSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGVzKCk7CiAgICAgIGluaXRfSW5kZXhEYXRhdHlwZSgpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9Qb2x5Z29uUGlwZWxpbmUoKTsKICAgICAgaW5pdF9Qb2x5bGluZVZvbHVtZUdlb21ldHJ5TGlicmFyeSgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgaW5pdF9XaW5kaW5nT3JkZXIoKTsKICAgICAgUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHZhbHVlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInZhbHVlIGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFycmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gdmFsdWUuX3Bvc2l0aW9uczsKICAgICAgICBsZXQgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gbGVuZ3RoOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSwgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoKSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhwb3NpdGlvbnNbaV0sIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc2hhcGUgPSB2YWx1ZS5fc2hhcGU7CiAgICAgICAgbGVuZ3RoID0gc2hhcGUubGVuZ3RoOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSBsZW5ndGg7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpLCBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjJfZGVmYXVsdC5wYWNrZWRMZW5ndGgpIHsKICAgICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdC5wYWNrKHNoYXBlW2ldLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgfQogICAgICAgIEVsbGlwc29pZF9kZWZhdWx0LnBhY2sodmFsdWUuX2VsbGlwc29pZCwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fY29ybmVyVHlwZTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLl9ncmFudWxhcml0eTsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hFbGxpcHNvaWQxMCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKEVsbGlwc29pZF9kZWZhdWx0LlVOSVRfU1BIRVJFKTsKICAgICAgc2NyYXRjaE9wdGlvbnMxOCA9IHsKICAgICAgICBwb2x5bGluZVBvc2l0aW9uczogdm9pZCAwLAogICAgICAgIHNoYXBlUG9zaXRpb25zOiB2b2lkIDAsCiAgICAgICAgZWxsaXBzb2lkOiBzY3JhdGNoRWxsaXBzb2lkMTAsCiAgICAgICAgaGVpZ2h0OiB2b2lkIDAsCiAgICAgICAgY29ybmVyVHlwZTogdm9pZCAwLAogICAgICAgIGdyYW51bGFyaXR5OiB2b2lkIDAKICAgICAgfTsKICAgICAgUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFycmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgbGV0IGxlbmd0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpLCBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGgpIHsKICAgICAgICAgIHBvc2l0aW9uc1tpXSA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIH0KICAgICAgICBsZW5ndGggPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHNoYXBlID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpLCBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjJfZGVmYXVsdC5wYWNrZWRMZW5ndGgpIHsKICAgICAgICAgIHNoYXBlW2ldID0gQ2FydGVzaWFuMl9kZWZhdWx0LnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCwgc2NyYXRjaEVsbGlwc29pZDEwKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCBjb3JuZXJUeXBlID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMTgucG9seWxpbmVQb3NpdGlvbnMgPSBwb3NpdGlvbnM7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE4LnNoYXBlUG9zaXRpb25zID0gc2hhcGU7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE4LmNvcm5lclR5cGUgPSBjb3JuZXJUeXBlOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxOC5ncmFudWxhcml0eSA9IGdyYW51bGFyaXR5OwogICAgICAgICAgcmV0dXJuIG5ldyBQb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeShzY3JhdGNoT3B0aW9uczE4KTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0Ll9wb3NpdGlvbnMgPSBwb3NpdGlvbnM7CiAgICAgICAgcmVzdWx0Ll9zaGFwZSA9IHNoYXBlOwogICAgICAgIHJlc3VsdC5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoZWxsaXBzb2lkLCByZXN1bHQuX2VsbGlwc29pZCk7CiAgICAgICAgcmVzdWx0Ll9jb3JuZXJUeXBlID0gY29ybmVyVHlwZTsKICAgICAgICByZXN1bHQuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgYnJTY3JhdGNoMiA9IG5ldyBCb3VuZGluZ1JlY3RhbmdsZV9kZWZhdWx0KCk7CiAgICAgIFBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5LmNyZWF0ZUdlb21ldHJ5ID0gZnVuY3Rpb24ocG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkpIHsKICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBwb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeS5fcG9zaXRpb25zOwogICAgICAgIGNvbnN0IGNsZWFuUG9zaXRpb25zID0gYXJyYXlSZW1vdmVEdXBsaWNhdGVzX2RlZmF1bHQoCiAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbgogICAgICAgICk7CiAgICAgICAgbGV0IHNoYXBlMkQgPSBwb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeS5fc2hhcGU7CiAgICAgICAgc2hhcGUyRCA9IFBvbHlsaW5lVm9sdW1lR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQucmVtb3ZlRHVwbGljYXRlc0Zyb21TaGFwZShzaGFwZTJEKTsKICAgICAgICBpZiAoY2xlYW5Qb3NpdGlvbnMubGVuZ3RoIDwgMiB8fCBzaGFwZTJELmxlbmd0aCA8IDMpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGlmIChQb2x5Z29uUGlwZWxpbmVfZGVmYXVsdC5jb21wdXRlV2luZGluZ09yZGVyMkQoc2hhcGUyRCkgPT09IFdpbmRpbmdPcmRlcl9kZWZhdWx0LkNMT0NLV0lTRSkgewogICAgICAgICAgc2hhcGUyRC5yZXZlcnNlKCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGJvdW5kaW5nUmVjdGFuZ2xlID0gQm91bmRpbmdSZWN0YW5nbGVfZGVmYXVsdC5mcm9tUG9pbnRzKHNoYXBlMkQsIGJyU2NyYXRjaDIpOwogICAgICAgIGNvbnN0IGNvbXB1dGVkUG9zaXRpb25zID0gUG9seWxpbmVWb2x1bWVHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlUG9zaXRpb25zKAogICAgICAgICAgY2xlYW5Qb3NpdGlvbnMsCiAgICAgICAgICBzaGFwZTJELAogICAgICAgICAgYm91bmRpbmdSZWN0YW5nbGUsCiAgICAgICAgICBwb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeSwKICAgICAgICAgIGZhbHNlCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gY29tcHV0ZUF0dHJpYnV0ZXMzKGNvbXB1dGVkUG9zaXRpb25zLCBzaGFwZTJEKTsKICAgICAgfTsKICAgICAgUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdCA9IFBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnlfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZVBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZVBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVQb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeShwb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgcG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkgPSBQb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjaygKICAgICAgICBwb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeSwKICAgICAgICBvZmZzZXQKICAgICAgKTsKICAgIH0KICAgIHBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZSgKICAgICAgcG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkuX2VsbGlwc29pZAogICAgKTsKICAgIHJldHVybiBQb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LmNyZWF0ZUdlb21ldHJ5KAogICAgICBwb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeQogICAgKTsKICB9CiAgdmFyIGNyZWF0ZVBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkoKTsKICAgICAgY3JlYXRlUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZVBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUmVjdGFuZ2xlR2VvbWV0cnlMaWJyYXJ5LmpzCiAgZnVuY3Rpb24gZ2V0Um90YXRpb25PcHRpb25zKG53Q29ybmVyLCByb3RhdGlvbiwgZ3JhbnVsYXJpdHlYLCBncmFudWxhcml0eVksIGNlbnRlciwgd2lkdGgsIGhlaWdodCkgewogICAgY29uc3QgY29zUm90YXRpb24gPSBNYXRoLmNvcyhyb3RhdGlvbik7CiAgICBjb25zdCBncmFuWUNvcyA9IGdyYW51bGFyaXR5WSAqIGNvc1JvdGF0aW9uOwogICAgY29uc3QgZ3JhblhDb3MgPSBncmFudWxhcml0eVggKiBjb3NSb3RhdGlvbjsKICAgIGNvbnN0IHNpblJvdGF0aW9uID0gTWF0aC5zaW4ocm90YXRpb24pOwogICAgY29uc3QgZ3JhbllTaW4gPSBncmFudWxhcml0eVkgKiBzaW5Sb3RhdGlvbjsKICAgIGNvbnN0IGdyYW5YU2luID0gZ3JhbnVsYXJpdHlYICogc2luUm90YXRpb247CiAgICBwcm9qLl9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgbndDYXJ0ZXNpYW4gPSBwcm9qLnByb2plY3QobndDb3JuZXIsIG53Q2FydGVzaWFuKTsKICAgIG53Q2FydGVzaWFuID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KG53Q2FydGVzaWFuLCBjZW50ZXJDYXJ0ZXNpYW4sIG53Q2FydGVzaWFuKTsKICAgIGNvbnN0IHJvdGF0aW9uTWF0cml4ID0gTWF0cml4Ml9kZWZhdWx0LmZyb21Sb3RhdGlvbihyb3RhdGlvbiwgcm90YXRpb25NYXRyaXhTY3JhdGNoKTsKICAgIG53Q2FydGVzaWFuID0gTWF0cml4Ml9kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3IoCiAgICAgIHJvdGF0aW9uTWF0cml4LAogICAgICBud0NhcnRlc2lhbiwKICAgICAgbndDYXJ0ZXNpYW4KICAgICk7CiAgICBud0NhcnRlc2lhbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQobndDYXJ0ZXNpYW4sIGNlbnRlckNhcnRlc2lhbiwgbndDYXJ0ZXNpYW4pOwogICAgbndDb3JuZXIgPSBwcm9qLnVucHJvamVjdChud0NhcnRlc2lhbiwgbndDb3JuZXIpOwogICAgd2lkdGggLT0gMTsKICAgIGhlaWdodCAtPSAxOwogICAgY29uc3QgbGF0aXR1ZGUgPSBud0Nvcm5lci5sYXRpdHVkZTsKICAgIGNvbnN0IGxhdGl0dWRlMCA9IGxhdGl0dWRlICsgd2lkdGggKiBncmFuWFNpbjsKICAgIGNvbnN0IGxhdGl0dWRlMSA9IGxhdGl0dWRlIC0gZ3JhbllDb3MgKiBoZWlnaHQ7CiAgICBjb25zdCBsYXRpdHVkZTIgPSBsYXRpdHVkZSAtIGdyYW5ZQ29zICogaGVpZ2h0ICsgd2lkdGggKiBncmFuWFNpbjsKICAgIGNvbnN0IG5vcnRoID0gTWF0aC5tYXgobGF0aXR1ZGUsIGxhdGl0dWRlMCwgbGF0aXR1ZGUxLCBsYXRpdHVkZTIpOwogICAgY29uc3Qgc291dGggPSBNYXRoLm1pbihsYXRpdHVkZSwgbGF0aXR1ZGUwLCBsYXRpdHVkZTEsIGxhdGl0dWRlMik7CiAgICBjb25zdCBsb25naXR1ZGUgPSBud0Nvcm5lci5sb25naXR1ZGU7CiAgICBjb25zdCBsb25naXR1ZGUwID0gbG9uZ2l0dWRlICsgd2lkdGggKiBncmFuWENvczsKICAgIGNvbnN0IGxvbmdpdHVkZTEgPSBsb25naXR1ZGUgKyBoZWlnaHQgKiBncmFuWVNpbjsKICAgIGNvbnN0IGxvbmdpdHVkZTIgPSBsb25naXR1ZGUgKyBoZWlnaHQgKiBncmFuWVNpbiArIHdpZHRoICogZ3JhblhDb3M7CiAgICBjb25zdCBlYXN0ID0gTWF0aC5tYXgobG9uZ2l0dWRlLCBsb25naXR1ZGUwLCBsb25naXR1ZGUxLCBsb25naXR1ZGUyKTsKICAgIGNvbnN0IHdlc3QgPSBNYXRoLm1pbihsb25naXR1ZGUsIGxvbmdpdHVkZTAsIGxvbmdpdHVkZTEsIGxvbmdpdHVkZTIpOwogICAgcmV0dXJuIHsKICAgICAgbm9ydGgsCiAgICAgIHNvdXRoLAogICAgICBlYXN0LAogICAgICB3ZXN0LAogICAgICBncmFuWUNvcywKICAgICAgZ3JhbllTaW4sCiAgICAgIGdyYW5YQ29zLAogICAgICBncmFuWFNpbiwKICAgICAgbndDb3JuZXIKICAgIH07CiAgfQogIHZhciBjb3MzLCBzaW4zLCBzcXJ0LCBSZWN0YW5nbGVHZW9tZXRyeUxpYnJhcnksIHJvdGF0aW9uTWF0cml4U2NyYXRjaCwgbndDYXJ0ZXNpYW4sIGNlbnRlclNjcmF0Y2gzLCBjZW50ZXJDYXJ0ZXNpYW4sIHByb2osIFJlY3RhbmdsZUdlb21ldHJ5TGlicmFyeV9kZWZhdWx0OwogIHZhciBpbml0X1JlY3RhbmdsZUdlb21ldHJ5TGlicmFyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUmVjdGFuZ2xlR2VvbWV0cnlMaWJyYXJ5LmpzIigpIHsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfR2VvZ3JhcGhpY1Byb2plY3Rpb24oKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfTWF0cml4MigpOwogICAgICBpbml0X1JlY3RhbmdsZSgpOwogICAgICBjb3MzID0gTWF0aC5jb3M7CiAgICAgIHNpbjMgPSBNYXRoLnNpbjsKICAgICAgc3FydCA9IE1hdGguc3FydDsKICAgICAgUmVjdGFuZ2xlR2VvbWV0cnlMaWJyYXJ5ID0ge307CiAgICAgIFJlY3RhbmdsZUdlb21ldHJ5TGlicmFyeS5jb21wdXRlUG9zaXRpb24gPSBmdW5jdGlvbihjb21wdXRlZE9wdGlvbnMsIGVsbGlwc29pZCwgY29tcHV0ZVNULCByb3csIGNvbCwgcG9zaXRpb24sIHN0KSB7CiAgICAgICAgY29uc3QgcmFkaWlTcXVhcmVkID0gZWxsaXBzb2lkLnJhZGlpU3F1YXJlZDsKICAgICAgICBjb25zdCBud0Nvcm5lciA9IGNvbXB1dGVkT3B0aW9ucy5ud0Nvcm5lcjsKICAgICAgICBjb25zdCByZWN0YW5nbGUgPSBjb21wdXRlZE9wdGlvbnMuYm91bmRpbmdSZWN0YW5nbGU7CiAgICAgICAgbGV0IHN0TGF0aXR1ZGUgPSBud0Nvcm5lci5sYXRpdHVkZSAtIGNvbXB1dGVkT3B0aW9ucy5ncmFuWUNvcyAqIHJvdyArIGNvbCAqIGNvbXB1dGVkT3B0aW9ucy5ncmFuWFNpbjsKICAgICAgICBjb25zdCBjb3NMYXRpdHVkZSA9IGNvczMoc3RMYXRpdHVkZSk7CiAgICAgICAgY29uc3QgblogPSBzaW4zKHN0TGF0aXR1ZGUpOwogICAgICAgIGNvbnN0IGtaID0gcmFkaWlTcXVhcmVkLnogKiBuWjsKICAgICAgICBsZXQgc3RMb25naXR1ZGUgPSBud0Nvcm5lci5sb25naXR1ZGUgKyByb3cgKiBjb21wdXRlZE9wdGlvbnMuZ3JhbllTaW4gKyBjb2wgKiBjb21wdXRlZE9wdGlvbnMuZ3JhblhDb3M7CiAgICAgICAgY29uc3QgblggPSBjb3NMYXRpdHVkZSAqIGNvczMoc3RMb25naXR1ZGUpOwogICAgICAgIGNvbnN0IG5ZID0gY29zTGF0aXR1ZGUgKiBzaW4zKHN0TG9uZ2l0dWRlKTsKICAgICAgICBjb25zdCBrWCA9IHJhZGlpU3F1YXJlZC54ICogblg7CiAgICAgICAgY29uc3Qga1kgPSByYWRpaVNxdWFyZWQueSAqIG5ZOwogICAgICAgIGNvbnN0IGdhbW1hID0gc3FydChrWCAqIG5YICsga1kgKiBuWSArIGtaICogblopOwogICAgICAgIHBvc2l0aW9uLnggPSBrWCAvIGdhbW1hOwogICAgICAgIHBvc2l0aW9uLnkgPSBrWSAvIGdhbW1hOwogICAgICAgIHBvc2l0aW9uLnogPSBrWiAvIGdhbW1hOwogICAgICAgIGlmIChjb21wdXRlU1QpIHsKICAgICAgICAgIGNvbnN0IHN0TndDb3JuZXIgPSBjb21wdXRlZE9wdGlvbnMuc3ROd0Nvcm5lcjsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoc3ROd0Nvcm5lcikpIHsKICAgICAgICAgICAgc3RMYXRpdHVkZSA9IHN0TndDb3JuZXIubGF0aXR1ZGUgLSBjb21wdXRlZE9wdGlvbnMuc3RHcmFuWUNvcyAqIHJvdyArIGNvbCAqIGNvbXB1dGVkT3B0aW9ucy5zdEdyYW5YU2luOwogICAgICAgICAgICBzdExvbmdpdHVkZSA9IHN0TndDb3JuZXIubG9uZ2l0dWRlICsgcm93ICogY29tcHV0ZWRPcHRpb25zLnN0R3JhbllTaW4gKyBjb2wgKiBjb21wdXRlZE9wdGlvbnMuc3RHcmFuWENvczsKICAgICAgICAgICAgc3QueCA9IChzdExvbmdpdHVkZSAtIGNvbXB1dGVkT3B0aW9ucy5zdFdlc3QpICogY29tcHV0ZWRPcHRpb25zLmxvblNjYWxhcjsKICAgICAgICAgICAgc3QueSA9IChzdExhdGl0dWRlIC0gY29tcHV0ZWRPcHRpb25zLnN0U291dGgpICogY29tcHV0ZWRPcHRpb25zLmxhdFNjYWxhcjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0LnggPSAoc3RMb25naXR1ZGUgLSByZWN0YW5nbGUud2VzdCkgKiBjb21wdXRlZE9wdGlvbnMubG9uU2NhbGFyOwogICAgICAgICAgICBzdC55ID0gKHN0TGF0aXR1ZGUgLSByZWN0YW5nbGUuc291dGgpICogY29tcHV0ZWRPcHRpb25zLmxhdFNjYWxhcjsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH07CiAgICAgIHJvdGF0aW9uTWF0cml4U2NyYXRjaCA9IG5ldyBNYXRyaXgyX2RlZmF1bHQoKTsKICAgICAgbndDYXJ0ZXNpYW4gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNlbnRlclNjcmF0Y2gzID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIGNlbnRlckNhcnRlc2lhbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgcHJvaiA9IG5ldyBHZW9ncmFwaGljUHJvamVjdGlvbl9kZWZhdWx0KCk7CiAgICAgIFJlY3RhbmdsZUdlb21ldHJ5TGlicmFyeS5jb21wdXRlT3B0aW9ucyA9IGZ1bmN0aW9uKHJlY3RhbmdsZSwgZ3JhbnVsYXJpdHksIHJvdGF0aW9uLCBzdFJvdGF0aW9uLCBib3VuZGluZ1JlY3RhbmdsZVNjcmF0Y2gsIG53Q29ybmVyUmVzdWx0LCBzdE53Q29ybmVyUmVzdWx0KSB7CiAgICAgICAgbGV0IGVhc3QgPSByZWN0YW5nbGUuZWFzdDsKICAgICAgICBsZXQgd2VzdCA9IHJlY3RhbmdsZS53ZXN0OwogICAgICAgIGxldCBub3J0aCA9IHJlY3RhbmdsZS5ub3J0aDsKICAgICAgICBsZXQgc291dGggPSByZWN0YW5nbGUuc291dGg7CiAgICAgICAgbGV0IG5vcnRoQ2FwID0gZmFsc2U7CiAgICAgICAgbGV0IHNvdXRoQ2FwID0gZmFsc2U7CiAgICAgICAgaWYgKG5vcnRoID09PSBNYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08pIHsKICAgICAgICAgIG5vcnRoQ2FwID0gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKHNvdXRoID09PSAtTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPKSB7CiAgICAgICAgICBzb3V0aENhcCA9IHRydWU7CiAgICAgICAgfQogICAgICAgIGxldCBkeDsKICAgICAgICBjb25zdCBkeSA9IG5vcnRoIC0gc291dGg7CiAgICAgICAgaWYgKHdlc3QgPiBlYXN0KSB7CiAgICAgICAgICBkeCA9IE1hdGhfZGVmYXVsdC5UV09fUEkgLSB3ZXN0ICsgZWFzdDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZHggPSBlYXN0IC0gd2VzdDsKICAgICAgICB9CiAgICAgICAgY29uc3Qgd2lkdGggPSBNYXRoLmNlaWwoZHggLyBncmFudWxhcml0eSkgKyAxOwogICAgICAgIGNvbnN0IGhlaWdodCA9IE1hdGguY2VpbChkeSAvIGdyYW51bGFyaXR5KSArIDE7CiAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHlYID0gZHggLyAod2lkdGggLSAxKTsKICAgICAgICBjb25zdCBncmFudWxhcml0eVkgPSBkeSAvIChoZWlnaHQgLSAxKTsKICAgICAgICBjb25zdCBud0Nvcm5lciA9IFJlY3RhbmdsZV9kZWZhdWx0Lm5vcnRod2VzdChyZWN0YW5nbGUsIG53Q29ybmVyUmVzdWx0KTsKICAgICAgICBjb25zdCBjZW50ZXIgPSBSZWN0YW5nbGVfZGVmYXVsdC5jZW50ZXIocmVjdGFuZ2xlLCBjZW50ZXJTY3JhdGNoMyk7CiAgICAgICAgaWYgKHJvdGF0aW9uICE9PSAwIHx8IHN0Um90YXRpb24gIT09IDApIHsKICAgICAgICAgIGlmIChjZW50ZXIubG9uZ2l0dWRlIDwgbndDb3JuZXIubG9uZ2l0dWRlKSB7CiAgICAgICAgICAgIGNlbnRlci5sb25naXR1ZGUgKz0gTWF0aF9kZWZhdWx0LlRXT19QSTsKICAgICAgICAgIH0KICAgICAgICAgIHByb2ouX2VsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmRlZmF1bHQ7CiAgICAgICAgICBjZW50ZXJDYXJ0ZXNpYW4gPSBwcm9qLnByb2plY3QoY2VudGVyLCBjZW50ZXJDYXJ0ZXNpYW4pOwogICAgICAgIH0KICAgICAgICBjb25zdCBncmFuWUNvcyA9IGdyYW51bGFyaXR5WTsKICAgICAgICBjb25zdCBncmFuWENvcyA9IGdyYW51bGFyaXR5WDsKICAgICAgICBjb25zdCBncmFuWVNpbiA9IDA7CiAgICAgICAgY29uc3QgZ3JhblhTaW4gPSAwOwogICAgICAgIGNvbnN0IGJvdW5kaW5nUmVjdGFuZ2xlID0gUmVjdGFuZ2xlX2RlZmF1bHQuY2xvbmUoCiAgICAgICAgICByZWN0YW5nbGUsCiAgICAgICAgICBib3VuZGluZ1JlY3RhbmdsZVNjcmF0Y2gKICAgICAgICApOwogICAgICAgIGNvbnN0IGNvbXB1dGVkT3B0aW9ucyA9IHsKICAgICAgICAgIGdyYW5ZQ29zLAogICAgICAgICAgZ3JhbllTaW4sCiAgICAgICAgICBncmFuWENvcywKICAgICAgICAgIGdyYW5YU2luLAogICAgICAgICAgbndDb3JuZXIsCiAgICAgICAgICBib3VuZGluZ1JlY3RhbmdsZSwKICAgICAgICAgIHdpZHRoLAogICAgICAgICAgaGVpZ2h0LAogICAgICAgICAgbm9ydGhDYXAsCiAgICAgICAgICBzb3V0aENhcAogICAgICAgIH07CiAgICAgICAgaWYgKHJvdGF0aW9uICE9PSAwKSB7CiAgICAgICAgICBjb25zdCByb3RhdGlvbk9wdGlvbnMgPSBnZXRSb3RhdGlvbk9wdGlvbnMoCiAgICAgICAgICAgIG53Q29ybmVyLAogICAgICAgICAgICByb3RhdGlvbiwKICAgICAgICAgICAgZ3JhbnVsYXJpdHlYLAogICAgICAgICAgICBncmFudWxhcml0eVksCiAgICAgICAgICAgIGNlbnRlciwKICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgIGhlaWdodAogICAgICAgICAgKTsKICAgICAgICAgIG5vcnRoID0gcm90YXRpb25PcHRpb25zLm5vcnRoOwogICAgICAgICAgc291dGggPSByb3RhdGlvbk9wdGlvbnMuc291dGg7CiAgICAgICAgICBlYXN0ID0gcm90YXRpb25PcHRpb25zLmVhc3Q7CiAgICAgICAgICB3ZXN0ID0gcm90YXRpb25PcHRpb25zLndlc3Q7CiAgICAgICAgICBpZiAobm9ydGggPCAtTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPIHx8IG5vcnRoID4gTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPIHx8IHNvdXRoIDwgLU1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTyB8fCBzb3V0aCA+IE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTykgewogICAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgICAiUm90YXRlZCByZWN0YW5nbGUgaXMgaW52YWxpZC4gIEl0IGNyb3NzZXMgb3ZlciBlaXRoZXIgdGhlIG5vcnRoIG9yIHNvdXRoIHBvbGUuIgogICAgICAgICAgICApOwogICAgICAgICAgfQogICAgICAgICAgY29tcHV0ZWRPcHRpb25zLmdyYW5ZQ29zID0gcm90YXRpb25PcHRpb25zLmdyYW5ZQ29zOwogICAgICAgICAgY29tcHV0ZWRPcHRpb25zLmdyYW5ZU2luID0gcm90YXRpb25PcHRpb25zLmdyYW5ZU2luOwogICAgICAgICAgY29tcHV0ZWRPcHRpb25zLmdyYW5YQ29zID0gcm90YXRpb25PcHRpb25zLmdyYW5YQ29zOwogICAgICAgICAgY29tcHV0ZWRPcHRpb25zLmdyYW5YU2luID0gcm90YXRpb25PcHRpb25zLmdyYW5YU2luOwogICAgICAgICAgYm91bmRpbmdSZWN0YW5nbGUubm9ydGggPSBub3J0aDsKICAgICAgICAgIGJvdW5kaW5nUmVjdGFuZ2xlLnNvdXRoID0gc291dGg7CiAgICAgICAgICBib3VuZGluZ1JlY3RhbmdsZS5lYXN0ID0gZWFzdDsKICAgICAgICAgIGJvdW5kaW5nUmVjdGFuZ2xlLndlc3QgPSB3ZXN0OwogICAgICAgIH0KICAgICAgICBpZiAoc3RSb3RhdGlvbiAhPT0gMCkgewogICAgICAgICAgcm90YXRpb24gPSByb3RhdGlvbiAtIHN0Um90YXRpb247CiAgICAgICAgICBjb25zdCBzdE53Q29ybmVyID0gUmVjdGFuZ2xlX2RlZmF1bHQubm9ydGh3ZXN0KGJvdW5kaW5nUmVjdGFuZ2xlLCBzdE53Q29ybmVyUmVzdWx0KTsKICAgICAgICAgIGNvbnN0IHN0Um90YXRpb25PcHRpb25zID0gZ2V0Um90YXRpb25PcHRpb25zKAogICAgICAgICAgICBzdE53Q29ybmVyLAogICAgICAgICAgICByb3RhdGlvbiwKICAgICAgICAgICAgZ3JhbnVsYXJpdHlYLAogICAgICAgICAgICBncmFudWxhcml0eVksCiAgICAgICAgICAgIGNlbnRlciwKICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgIGhlaWdodAogICAgICAgICAgKTsKICAgICAgICAgIGNvbXB1dGVkT3B0aW9ucy5zdEdyYW5ZQ29zID0gc3RSb3RhdGlvbk9wdGlvbnMuZ3JhbllDb3M7CiAgICAgICAgICBjb21wdXRlZE9wdGlvbnMuc3RHcmFuWENvcyA9IHN0Um90YXRpb25PcHRpb25zLmdyYW5YQ29zOwogICAgICAgICAgY29tcHV0ZWRPcHRpb25zLnN0R3JhbllTaW4gPSBzdFJvdGF0aW9uT3B0aW9ucy5ncmFuWVNpbjsKICAgICAgICAgIGNvbXB1dGVkT3B0aW9ucy5zdEdyYW5YU2luID0gc3RSb3RhdGlvbk9wdGlvbnMuZ3JhblhTaW47CiAgICAgICAgICBjb21wdXRlZE9wdGlvbnMuc3ROd0Nvcm5lciA9IHN0TndDb3JuZXI7CiAgICAgICAgICBjb21wdXRlZE9wdGlvbnMuc3RXZXN0ID0gc3RSb3RhdGlvbk9wdGlvbnMud2VzdDsKICAgICAgICAgIGNvbXB1dGVkT3B0aW9ucy5zdFNvdXRoID0gc3RSb3RhdGlvbk9wdGlvbnMuc291dGg7CiAgICAgICAgfQogICAgICAgIHJldHVybiBjb21wdXRlZE9wdGlvbnM7CiAgICAgIH07CiAgICAgIFJlY3RhbmdsZUdlb21ldHJ5TGlicmFyeV9kZWZhdWx0ID0gUmVjdGFuZ2xlR2VvbWV0cnlMaWJyYXJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUmVjdGFuZ2xlR2VvbWV0cnkuanMKICBmdW5jdGlvbiBjcmVhdGVBdHRyaWJ1dGVzKHZlcnRleEZvcm1hdCwgYXR0cmlidXRlcykgewogICAgY29uc3QgZ2VvID0gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICBhdHRyaWJ1dGVzOiBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoKSwKICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LlRSSUFOR0xFUwogICAgfSk7CiAgICBnZW8uYXR0cmlidXRlcy5wb3NpdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFLAogICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICB2YWx1ZXM6IGF0dHJpYnV0ZXMucG9zaXRpb25zCiAgICB9KTsKICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgIGdlby5hdHRyaWJ1dGVzLm5vcm1hbCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgIHZhbHVlczogYXR0cmlidXRlcy5ub3JtYWxzCiAgICAgIH0pOwogICAgfQogICAgaWYgKHZlcnRleEZvcm1hdC50YW5nZW50KSB7CiAgICAgIGdlby5hdHRyaWJ1dGVzLnRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IGF0dHJpYnV0ZXMudGFuZ2VudHMKICAgICAgfSk7CiAgICB9CiAgICBpZiAodmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICBnZW8uYXR0cmlidXRlcy5iaXRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IGF0dHJpYnV0ZXMuYml0YW5nZW50cwogICAgICB9KTsKICAgIH0KICAgIHJldHVybiBnZW87CiAgfQogIGZ1bmN0aW9uIGNhbGN1bGF0ZUF0dHJpYnV0ZXMocG9zaXRpb25zLCB2ZXJ0ZXhGb3JtYXQsIGVsbGlwc29pZCwgdGFuZ2VudFJvdGF0aW9uTWF0cml4KSB7CiAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgY29uc3Qgbm9ybWFscyA9IHZlcnRleEZvcm1hdC5ub3JtYWwgPyBuZXcgRmxvYXQzMkFycmF5KGxlbmd0aCkgOiB2b2lkIDA7CiAgICBjb25zdCB0YW5nZW50cyA9IHZlcnRleEZvcm1hdC50YW5nZW50ID8gbmV3IEZsb2F0MzJBcnJheShsZW5ndGgpIDogdm9pZCAwOwogICAgY29uc3QgYml0YW5nZW50cyA9IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQgPyBuZXcgRmxvYXQzMkFycmF5KGxlbmd0aCkgOiB2b2lkIDA7CiAgICBsZXQgYXR0ckluZGV4ID0gMDsKICAgIGNvbnN0IGJpdGFuZ2VudCA9IGJpdGFuZ2VudFNjcmF0Y2gyOwogICAgY29uc3QgdGFuZ2VudCA9IHRhbmdlbnRTY3JhdGNoMjsKICAgIGxldCBub3JtYWwyID0gbm9ybWFsU2NyYXRjaDQ7CiAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCB8fCB2ZXJ0ZXhGb3JtYXQudGFuZ2VudCB8fCB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHsKICAgICAgICBjb25zdCBwID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIGksIHBvc2l0aW9uU2NyYXRjaDIpOwogICAgICAgIGNvbnN0IGF0dHJJbmRleDEgPSBhdHRySW5kZXggKyAxOwogICAgICAgIGNvbnN0IGF0dHJJbmRleDIgPSBhdHRySW5kZXggKyAyOwogICAgICAgIG5vcm1hbDIgPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKHAsIG5vcm1hbDIpOwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCB8fCB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoQ2FydGVzaWFuM19kZWZhdWx0LlVOSVRfWiwgbm9ybWFsMiwgdGFuZ2VudCk7CiAgICAgICAgICBNYXRyaXgzX2RlZmF1bHQubXVsdGlwbHlCeVZlY3Rvcih0YW5nZW50Um90YXRpb25NYXRyaXgsIHRhbmdlbnQsIHRhbmdlbnQpOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSh0YW5nZW50LCB0YW5nZW50KTsKICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoCiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKG5vcm1hbDIsIHRhbmdlbnQsIGJpdGFuZ2VudCksCiAgICAgICAgICAgICAgYml0YW5nZW50CiAgICAgICAgICAgICk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgICAgICBub3JtYWxzW2F0dHJJbmRleF0gPSBub3JtYWwyLng7CiAgICAgICAgICBub3JtYWxzW2F0dHJJbmRleDFdID0gbm9ybWFsMi55OwogICAgICAgICAgbm9ybWFsc1thdHRySW5kZXgyXSA9IG5vcm1hbDIuejsKICAgICAgICB9CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC50YW5nZW50KSB7CiAgICAgICAgICB0YW5nZW50c1thdHRySW5kZXhdID0gdGFuZ2VudC54OwogICAgICAgICAgdGFuZ2VudHNbYXR0ckluZGV4MV0gPSB0YW5nZW50Lnk7CiAgICAgICAgICB0YW5nZW50c1thdHRySW5kZXgyXSA9IHRhbmdlbnQuejsKICAgICAgICB9CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgIGJpdGFuZ2VudHNbYXR0ckluZGV4XSA9IGJpdGFuZ2VudC54OwogICAgICAgICAgYml0YW5nZW50c1thdHRySW5kZXgxXSA9IGJpdGFuZ2VudC55OwogICAgICAgICAgYml0YW5nZW50c1thdHRySW5kZXgyXSA9IGJpdGFuZ2VudC56OwogICAgICAgIH0KICAgICAgICBhdHRySW5kZXggKz0gMzsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZXModmVydGV4Rm9ybWF0LCB7CiAgICAgIHBvc2l0aW9ucywKICAgICAgbm9ybWFscywKICAgICAgdGFuZ2VudHMsCiAgICAgIGJpdGFuZ2VudHMKICAgIH0pOwogIH0KICBmdW5jdGlvbiBjYWxjdWxhdGVBdHRyaWJ1dGVzV2FsbChwb3NpdGlvbnMsIHZlcnRleEZvcm1hdCwgZWxsaXBzb2lkKSB7CiAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgY29uc3Qgbm9ybWFscyA9IHZlcnRleEZvcm1hdC5ub3JtYWwgPyBuZXcgRmxvYXQzMkFycmF5KGxlbmd0aCkgOiB2b2lkIDA7CiAgICBjb25zdCB0YW5nZW50cyA9IHZlcnRleEZvcm1hdC50YW5nZW50ID8gbmV3IEZsb2F0MzJBcnJheShsZW5ndGgpIDogdm9pZCAwOwogICAgY29uc3QgYml0YW5nZW50cyA9IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQgPyBuZXcgRmxvYXQzMkFycmF5KGxlbmd0aCkgOiB2b2lkIDA7CiAgICBsZXQgbm9ybWFsSW5kZXggPSAwOwogICAgbGV0IHRhbmdlbnRJbmRleCA9IDA7CiAgICBsZXQgYml0YW5nZW50SW5kZXggPSAwOwogICAgbGV0IHJlY29tcHV0ZU5vcm1hbCA9IHRydWU7CiAgICBsZXQgYml0YW5nZW50ID0gYml0YW5nZW50U2NyYXRjaDI7CiAgICBsZXQgdGFuZ2VudCA9IHRhbmdlbnRTY3JhdGNoMjsKICAgIGxldCBub3JtYWwyID0gbm9ybWFsU2NyYXRjaDQ7CiAgICBpZiAodmVydGV4Rm9ybWF0Lm5vcm1hbCB8fCB2ZXJ0ZXhGb3JtYXQudGFuZ2VudCB8fCB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50KSB7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDYpIHsKICAgICAgICBjb25zdCBwID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIGksIHBvc2l0aW9uU2NyYXRjaDIpOwogICAgICAgIGNvbnN0IHAxID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIChpICsgNikgJSBsZW5ndGgsIHYxU2NyYXRjaCk7CiAgICAgICAgaWYgKHJlY29tcHV0ZU5vcm1hbCkgewogICAgICAgICAgY29uc3QgcDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHBvc2l0aW9ucywgKGkgKyAzKSAlIGxlbmd0aCwgdjJTY3JhdGNoKTsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChwMSwgcCwgcDEpOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHAyLCBwLCBwMik7CiAgICAgICAgICBub3JtYWwyID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MocDIsIHAxLCBub3JtYWwyKSwgbm9ybWFsMik7CiAgICAgICAgICByZWNvbXB1dGVOb3JtYWwgPSBmYWxzZTsKICAgICAgICB9CiAgICAgICAgaWYgKENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKHAxLCBwLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjEwKSkgewogICAgICAgICAgcmVjb21wdXRlTm9ybWFsID0gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC50YW5nZW50IHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgIGJpdGFuZ2VudCA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwocCwgYml0YW5nZW50KTsKICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICAgICAgICB0YW5nZW50ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoYml0YW5nZW50LCBub3JtYWwyLCB0YW5nZW50KSwKICAgICAgICAgICAgICB0YW5nZW50CiAgICAgICAgICAgICk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsKSB7CiAgICAgICAgICBub3JtYWxzW25vcm1hbEluZGV4KytdID0gbm9ybWFsMi54OwogICAgICAgICAgbm9ybWFsc1tub3JtYWxJbmRleCsrXSA9IG5vcm1hbDIueTsKICAgICAgICAgIG5vcm1hbHNbbm9ybWFsSW5kZXgrK10gPSBub3JtYWwyLno7CiAgICAgICAgICBub3JtYWxzW25vcm1hbEluZGV4KytdID0gbm9ybWFsMi54OwogICAgICAgICAgbm9ybWFsc1tub3JtYWxJbmRleCsrXSA9IG5vcm1hbDIueTsKICAgICAgICAgIG5vcm1hbHNbbm9ybWFsSW5kZXgrK10gPSBub3JtYWwyLno7CiAgICAgICAgfQogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQudGFuZ2VudCkgewogICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC54OwogICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC55OwogICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC56OwogICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC54OwogICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC55OwogICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC56OwogICAgICAgIH0KICAgICAgICBpZiAodmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgICAgYml0YW5nZW50c1tiaXRhbmdlbnRJbmRleCsrXSA9IGJpdGFuZ2VudC54OwogICAgICAgICAgYml0YW5nZW50c1tiaXRhbmdlbnRJbmRleCsrXSA9IGJpdGFuZ2VudC55OwogICAgICAgICAgYml0YW5nZW50c1tiaXRhbmdlbnRJbmRleCsrXSA9IGJpdGFuZ2VudC56OwogICAgICAgICAgYml0YW5nZW50c1tiaXRhbmdlbnRJbmRleCsrXSA9IGJpdGFuZ2VudC54OwogICAgICAgICAgYml0YW5nZW50c1tiaXRhbmdlbnRJbmRleCsrXSA9IGJpdGFuZ2VudC55OwogICAgICAgICAgYml0YW5nZW50c1tiaXRhbmdlbnRJbmRleCsrXSA9IGJpdGFuZ2VudC56OwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZXModmVydGV4Rm9ybWF0LCB7CiAgICAgIHBvc2l0aW9ucywKICAgICAgbm9ybWFscywKICAgICAgdGFuZ2VudHMsCiAgICAgIGJpdGFuZ2VudHMKICAgIH0pOwogIH0KICBmdW5jdGlvbiBjb25zdHJ1Y3RSZWN0YW5nbGUocmVjdGFuZ2xlR2VvbWV0cnksIGNvbXB1dGVkT3B0aW9ucykgewogICAgY29uc3QgdmVydGV4Rm9ybWF0ID0gcmVjdGFuZ2xlR2VvbWV0cnkuX3ZlcnRleEZvcm1hdDsKICAgIGNvbnN0IGVsbGlwc29pZCA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9lbGxpcHNvaWQ7CiAgICBjb25zdCBoZWlnaHQgPSBjb21wdXRlZE9wdGlvbnMuaGVpZ2h0OwogICAgY29uc3Qgd2lkdGggPSBjb21wdXRlZE9wdGlvbnMud2lkdGg7CiAgICBjb25zdCBub3J0aENhcCA9IGNvbXB1dGVkT3B0aW9ucy5ub3J0aENhcDsKICAgIGNvbnN0IHNvdXRoQ2FwID0gY29tcHV0ZWRPcHRpb25zLnNvdXRoQ2FwOwogICAgbGV0IHJvd1N0YXJ0ID0gMDsKICAgIGxldCByb3dFbmQgPSBoZWlnaHQ7CiAgICBsZXQgcm93SGVpZ2h0ID0gaGVpZ2h0OwogICAgbGV0IHNpemUgPSAwOwogICAgaWYgKG5vcnRoQ2FwKSB7CiAgICAgIHJvd1N0YXJ0ID0gMTsKICAgICAgcm93SGVpZ2h0IC09IDE7CiAgICAgIHNpemUgKz0gMTsKICAgIH0KICAgIGlmIChzb3V0aENhcCkgewogICAgICByb3dFbmQgLT0gMTsKICAgICAgcm93SGVpZ2h0IC09IDE7CiAgICAgIHNpemUgKz0gMTsKICAgIH0KICAgIHNpemUgKz0gd2lkdGggKiByb3dIZWlnaHQ7CiAgICBjb25zdCBwb3NpdGlvbnMgPSB2ZXJ0ZXhGb3JtYXQucG9zaXRpb24gPyBuZXcgRmxvYXQ2NEFycmF5KHNpemUgKiAzKSA6IHZvaWQgMDsKICAgIGNvbnN0IHRleHR1cmVDb29yZGluYXRlcyA9IHZlcnRleEZvcm1hdC5zdCA/IG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSAqIDIpIDogdm9pZCAwOwogICAgbGV0IHBvc0luZGV4ID0gMDsKICAgIGxldCBzdEluZGV4ID0gMDsKICAgIGNvbnN0IHBvc2l0aW9uID0gcG9zaXRpb25TY3JhdGNoMjsKICAgIGNvbnN0IHN0ID0gc3RTY3JhdGNoMjsKICAgIGxldCBtaW5YID0gTnVtYmVyLk1BWF9WQUxVRTsKICAgIGxldCBtaW5ZID0gTnVtYmVyLk1BWF9WQUxVRTsKICAgIGxldCBtYXhYID0gLU51bWJlci5NQVhfVkFMVUU7CiAgICBsZXQgbWF4WSA9IC1OdW1iZXIuTUFYX1ZBTFVFOwogICAgZm9yIChsZXQgcm93ID0gcm93U3RhcnQ7IHJvdyA8IHJvd0VuZDsgKytyb3cpIHsKICAgICAgZm9yIChsZXQgY29sID0gMDsgY29sIDwgd2lkdGg7ICsrY29sKSB7CiAgICAgICAgUmVjdGFuZ2xlR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZVBvc2l0aW9uKAogICAgICAgICAgY29tcHV0ZWRPcHRpb25zLAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgdmVydGV4Rm9ybWF0LnN0LAogICAgICAgICAgcm93LAogICAgICAgICAgY29sLAogICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICBzdAogICAgICAgICk7CiAgICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24ueDsKICAgICAgICBwb3NpdGlvbnNbcG9zSW5kZXgrK10gPSBwb3NpdGlvbi55OwogICAgICAgIHBvc2l0aW9uc1twb3NJbmRleCsrXSA9IHBvc2l0aW9uLno7CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5zdCkgewogICAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW3N0SW5kZXgrK10gPSBzdC54OwogICAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW3N0SW5kZXgrK10gPSBzdC55OwogICAgICAgICAgbWluWCA9IE1hdGgubWluKG1pblgsIHN0LngpOwogICAgICAgICAgbWluWSA9IE1hdGgubWluKG1pblksIHN0LnkpOwogICAgICAgICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIHN0LngpOwogICAgICAgICAgbWF4WSA9IE1hdGgubWF4KG1heFksIHN0LnkpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKG5vcnRoQ2FwKSB7CiAgICAgIFJlY3RhbmdsZUdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVQb3NpdGlvbigKICAgICAgICBjb21wdXRlZE9wdGlvbnMsCiAgICAgICAgZWxsaXBzb2lkLAogICAgICAgIHZlcnRleEZvcm1hdC5zdCwKICAgICAgICAwLAogICAgICAgIDAsCiAgICAgICAgcG9zaXRpb24sCiAgICAgICAgc3QKICAgICAgKTsKICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24ueDsKICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24ueTsKICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24uejsKICAgICAgaWYgKHZlcnRleEZvcm1hdC5zdCkgewogICAgICAgIHRleHR1cmVDb29yZGluYXRlc1tzdEluZGV4KytdID0gc3QueDsKICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXNbc3RJbmRleCsrXSA9IHN0Lnk7CiAgICAgICAgbWluWCA9IHN0Lng7CiAgICAgICAgbWluWSA9IHN0Lnk7CiAgICAgICAgbWF4WCA9IHN0Lng7CiAgICAgICAgbWF4WSA9IHN0Lnk7CiAgICAgIH0KICAgIH0KICAgIGlmIChzb3V0aENhcCkgewogICAgICBSZWN0YW5nbGVHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlUG9zaXRpb24oCiAgICAgICAgY29tcHV0ZWRPcHRpb25zLAogICAgICAgIGVsbGlwc29pZCwKICAgICAgICB2ZXJ0ZXhGb3JtYXQuc3QsCiAgICAgICAgaGVpZ2h0IC0gMSwKICAgICAgICAwLAogICAgICAgIHBvc2l0aW9uLAogICAgICAgIHN0CiAgICAgICk7CiAgICAgIHBvc2l0aW9uc1twb3NJbmRleCsrXSA9IHBvc2l0aW9uLng7CiAgICAgIHBvc2l0aW9uc1twb3NJbmRleCsrXSA9IHBvc2l0aW9uLnk7CiAgICAgIHBvc2l0aW9uc1twb3NJbmRleF0gPSBwb3NpdGlvbi56OwogICAgICBpZiAodmVydGV4Rm9ybWF0LnN0KSB7CiAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW3N0SW5kZXgrK10gPSBzdC54OwogICAgICAgIHRleHR1cmVDb29yZGluYXRlc1tzdEluZGV4XSA9IHN0Lnk7CiAgICAgICAgbWluWCA9IE1hdGgubWluKG1pblgsIHN0LngpOwogICAgICAgIG1pblkgPSBNYXRoLm1pbihtaW5ZLCBzdC55KTsKICAgICAgICBtYXhYID0gTWF0aC5tYXgobWF4WCwgc3QueCk7CiAgICAgICAgbWF4WSA9IE1hdGgubWF4KG1heFksIHN0LnkpOwogICAgICB9CiAgICB9CiAgICBpZiAodmVydGV4Rm9ybWF0LnN0ICYmIChtaW5YIDwgMCB8fCBtaW5ZIDwgMCB8fCBtYXhYID4gMSB8fCBtYXhZID4gMSkpIHsKICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCB0ZXh0dXJlQ29vcmRpbmF0ZXMubGVuZ3RoOyBrICs9IDIpIHsKICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXNba10gPSAodGV4dHVyZUNvb3JkaW5hdGVzW2tdIC0gbWluWCkgLyAobWF4WCAtIG1pblgpOwogICAgICAgIHRleHR1cmVDb29yZGluYXRlc1trICsgMV0gPSAodGV4dHVyZUNvb3JkaW5hdGVzW2sgKyAxXSAtIG1pblkpIC8gKG1heFkgLSBtaW5ZKTsKICAgICAgfQogICAgfQogICAgY29uc3QgZ2VvID0gY2FsY3VsYXRlQXR0cmlidXRlcygKICAgICAgcG9zaXRpb25zLAogICAgICB2ZXJ0ZXhGb3JtYXQsCiAgICAgIGVsbGlwc29pZCwKICAgICAgY29tcHV0ZWRPcHRpb25zLnRhbmdlbnRSb3RhdGlvbk1hdHJpeAogICAgKTsKICAgIGxldCBpbmRpY2VzU2l6ZSA9IDYgKiAod2lkdGggLSAxKSAqIChyb3dIZWlnaHQgLSAxKTsKICAgIGlmIChub3J0aENhcCkgewogICAgICBpbmRpY2VzU2l6ZSArPSAzICogKHdpZHRoIC0gMSk7CiAgICB9CiAgICBpZiAoc291dGhDYXApIHsKICAgICAgaW5kaWNlc1NpemUgKz0gMyAqICh3aWR0aCAtIDEpOwogICAgfQogICAgY29uc3QgaW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KHNpemUsIGluZGljZXNTaXplKTsKICAgIGxldCBpbmRleCA9IDA7CiAgICBsZXQgaW5kaWNlc0luZGV4ID0gMDsKICAgIGxldCBpOwogICAgZm9yIChpID0gMDsgaSA8IHJvd0hlaWdodCAtIDE7ICsraSkgewogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHdpZHRoIC0gMTsgKytqKSB7CiAgICAgICAgY29uc3QgdXBwZXJMZWZ0ID0gaW5kZXg7CiAgICAgICAgY29uc3QgbG93ZXJMZWZ0ID0gdXBwZXJMZWZ0ICsgd2lkdGg7CiAgICAgICAgY29uc3QgbG93ZXJSaWdodCA9IGxvd2VyTGVmdCArIDE7CiAgICAgICAgY29uc3QgdXBwZXJSaWdodCA9IHVwcGVyTGVmdCArIDE7CiAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSB1cHBlckxlZnQ7CiAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBsb3dlckxlZnQ7CiAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSB1cHBlclJpZ2h0OwogICAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gdXBwZXJSaWdodDsKICAgICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGxvd2VyTGVmdDsKICAgICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGxvd2VyUmlnaHQ7CiAgICAgICAgKytpbmRleDsKICAgICAgfQogICAgICArK2luZGV4OwogICAgfQogICAgaWYgKG5vcnRoQ2FwIHx8IHNvdXRoQ2FwKSB7CiAgICAgIGxldCBub3J0aEluZGV4ID0gc2l6ZSAtIDE7CiAgICAgIGNvbnN0IHNvdXRoSW5kZXggPSBzaXplIC0gMTsKICAgICAgaWYgKG5vcnRoQ2FwICYmIHNvdXRoQ2FwKSB7CiAgICAgICAgbm9ydGhJbmRleCA9IHNpemUgLSAyOwogICAgICB9CiAgICAgIGxldCBwMTsKICAgICAgbGV0IHAyOwogICAgICBpbmRleCA9IDA7CiAgICAgIGlmIChub3J0aENhcCkgewogICAgICAgIGZvciAoaSA9IDA7IGkgPCB3aWR0aCAtIDE7IGkrKykgewogICAgICAgICAgcDEgPSBpbmRleDsKICAgICAgICAgIHAyID0gcDEgKyAxOwogICAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBub3J0aEluZGV4OwogICAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwMTsKICAgICAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gcDI7CiAgICAgICAgICArK2luZGV4OwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoc291dGhDYXApIHsKICAgICAgICBpbmRleCA9IChyb3dIZWlnaHQgLSAxKSAqIHdpZHRoOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCB3aWR0aCAtIDE7IGkrKykgewogICAgICAgICAgcDEgPSBpbmRleDsKICAgICAgICAgIHAyID0gcDEgKyAxOwogICAgICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBwMTsKICAgICAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gc291dGhJbmRleDsKICAgICAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gcDI7CiAgICAgICAgICArK2luZGV4OwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgZ2VvLmluZGljZXMgPSBpbmRpY2VzOwogICAgaWYgKHZlcnRleEZvcm1hdC5zdCkgewogICAgICBnZW8uYXR0cmlidXRlcy5zdCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAyLAogICAgICAgIHZhbHVlczogdGV4dHVyZUNvb3JkaW5hdGVzCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIGdlbzsKICB9CiAgZnVuY3Rpb24gYWRkV2FsbFBvc2l0aW9uczIod2FsbFBvc2l0aW9ucywgcG9zSW5kZXgsIGksIHRvcFBvc2l0aW9ucywgYm90dG9tUG9zaXRpb25zKSB7CiAgICB3YWxsUG9zaXRpb25zW3Bvc0luZGV4KytdID0gdG9wUG9zaXRpb25zW2ldOwogICAgd2FsbFBvc2l0aW9uc1twb3NJbmRleCsrXSA9IHRvcFBvc2l0aW9uc1tpICsgMV07CiAgICB3YWxsUG9zaXRpb25zW3Bvc0luZGV4KytdID0gdG9wUG9zaXRpb25zW2kgKyAyXTsKICAgIHdhbGxQb3NpdGlvbnNbcG9zSW5kZXgrK10gPSBib3R0b21Qb3NpdGlvbnNbaV07CiAgICB3YWxsUG9zaXRpb25zW3Bvc0luZGV4KytdID0gYm90dG9tUG9zaXRpb25zW2kgKyAxXTsKICAgIHdhbGxQb3NpdGlvbnNbcG9zSW5kZXhdID0gYm90dG9tUG9zaXRpb25zW2kgKyAyXTsKICAgIHJldHVybiB3YWxsUG9zaXRpb25zOwogIH0KICBmdW5jdGlvbiBhZGRXYWxsVGV4dHVyZUNvb3JkaW5hdGVzKHdhbGxUZXh0dXJlcywgc3RJbmRleCwgaSwgc3QpIHsKICAgIHdhbGxUZXh0dXJlc1tzdEluZGV4KytdID0gc3RbaV07CiAgICB3YWxsVGV4dHVyZXNbc3RJbmRleCsrXSA9IHN0W2kgKyAxXTsKICAgIHdhbGxUZXh0dXJlc1tzdEluZGV4KytdID0gc3RbaV07CiAgICB3YWxsVGV4dHVyZXNbc3RJbmRleF0gPSBzdFtpICsgMV07CiAgICByZXR1cm4gd2FsbFRleHR1cmVzOwogIH0KICBmdW5jdGlvbiBjb25zdHJ1Y3RFeHRydWRlZFJlY3RhbmdsZShyZWN0YW5nbGVHZW9tZXRyeSwgY29tcHV0ZWRPcHRpb25zKSB7CiAgICBjb25zdCBzaGFkb3dWb2x1bWUgPSByZWN0YW5nbGVHZW9tZXRyeS5fc2hhZG93Vm9sdW1lOwogICAgY29uc3Qgb2Zmc2V0QXR0cmlidXRlVmFsdWUgPSByZWN0YW5nbGVHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlOwogICAgY29uc3QgdmVydGV4Rm9ybWF0ID0gcmVjdGFuZ2xlR2VvbWV0cnkuX3ZlcnRleEZvcm1hdDsKICAgIGNvbnN0IG1pbkhlaWdodCA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9leHRydWRlZEhlaWdodDsKICAgIGNvbnN0IG1heEhlaWdodCA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9zdXJmYWNlSGVpZ2h0OwogICAgY29uc3QgZWxsaXBzb2lkID0gcmVjdGFuZ2xlR2VvbWV0cnkuX2VsbGlwc29pZDsKICAgIGNvbnN0IGhlaWdodCA9IGNvbXB1dGVkT3B0aW9ucy5oZWlnaHQ7CiAgICBjb25zdCB3aWR0aCA9IGNvbXB1dGVkT3B0aW9ucy53aWR0aDsKICAgIGxldCBpOwogICAgaWYgKHNoYWRvd1ZvbHVtZSkgewogICAgICBjb25zdCBuZXdWZXJ0ZXhGb3JtYXQgPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5jbG9uZSgKICAgICAgICB2ZXJ0ZXhGb3JtYXQsCiAgICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDEyCiAgICAgICk7CiAgICAgIG5ld1ZlcnRleEZvcm1hdC5ub3JtYWwgPSB0cnVlOwogICAgICByZWN0YW5nbGVHZW9tZXRyeS5fdmVydGV4Rm9ybWF0ID0gbmV3VmVydGV4Rm9ybWF0OwogICAgfQogICAgY29uc3QgdG9wQm90dG9tR2VvID0gY29uc3RydWN0UmVjdGFuZ2xlKHJlY3RhbmdsZUdlb21ldHJ5LCBjb21wdXRlZE9wdGlvbnMpOwogICAgaWYgKHNoYWRvd1ZvbHVtZSkgewogICAgICByZWN0YW5nbGVHZW9tZXRyeS5fdmVydGV4Rm9ybWF0ID0gdmVydGV4Rm9ybWF0OwogICAgfQogICAgbGV0IHRvcFBvc2l0aW9ucyA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LnNjYWxlVG9HZW9kZXRpY0hlaWdodCgKICAgICAgdG9wQm90dG9tR2VvLmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLAogICAgICBtYXhIZWlnaHQsCiAgICAgIGVsbGlwc29pZCwKICAgICAgZmFsc2UKICAgICk7CiAgICB0b3BQb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KHRvcFBvc2l0aW9ucyk7CiAgICBsZXQgbGVuZ3RoID0gdG9wUG9zaXRpb25zLmxlbmd0aDsKICAgIGNvbnN0IG5ld0xlbmd0aCA9IGxlbmd0aCAqIDI7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KG5ld0xlbmd0aCk7CiAgICBwb3NpdGlvbnMuc2V0KHRvcFBvc2l0aW9ucyk7CiAgICBjb25zdCBib3R0b21Qb3NpdGlvbnMgPSBQb2x5Z29uUGlwZWxpbmVfZGVmYXVsdC5zY2FsZVRvR2VvZGV0aWNIZWlnaHQoCiAgICAgIHRvcEJvdHRvbUdlby5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcywKICAgICAgbWluSGVpZ2h0LAogICAgICBlbGxpcHNvaWQKICAgICk7CiAgICBwb3NpdGlvbnMuc2V0KGJvdHRvbVBvc2l0aW9ucywgbGVuZ3RoKTsKICAgIHRvcEJvdHRvbUdlby5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcyA9IHBvc2l0aW9uczsKICAgIGNvbnN0IG5vcm1hbHMgPSB2ZXJ0ZXhGb3JtYXQubm9ybWFsID8gbmV3IEZsb2F0MzJBcnJheShuZXdMZW5ndGgpIDogdm9pZCAwOwogICAgY29uc3QgdGFuZ2VudHMgPSB2ZXJ0ZXhGb3JtYXQudGFuZ2VudCA/IG5ldyBGbG9hdDMyQXJyYXkobmV3TGVuZ3RoKSA6IHZvaWQgMDsKICAgIGNvbnN0IGJpdGFuZ2VudHMgPSB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50ID8gbmV3IEZsb2F0MzJBcnJheShuZXdMZW5ndGgpIDogdm9pZCAwOwogICAgY29uc3QgdGV4dHVyZXMgPSB2ZXJ0ZXhGb3JtYXQuc3QgPyBuZXcgRmxvYXQzMkFycmF5KG5ld0xlbmd0aCAvIDMgKiAyKSA6IHZvaWQgMDsKICAgIGxldCB0b3BTdDsKICAgIGxldCB0b3BOb3JtYWxzOwogICAgaWYgKHZlcnRleEZvcm1hdC5ub3JtYWwpIHsKICAgICAgdG9wTm9ybWFscyA9IHRvcEJvdHRvbUdlby5hdHRyaWJ1dGVzLm5vcm1hbC52YWx1ZXM7CiAgICAgIG5vcm1hbHMuc2V0KHRvcE5vcm1hbHMpOwogICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICB0b3BOb3JtYWxzW2ldID0gLXRvcE5vcm1hbHNbaV07CiAgICAgIH0KICAgICAgbm9ybWFscy5zZXQodG9wTm9ybWFscywgbGVuZ3RoKTsKICAgICAgdG9wQm90dG9tR2VvLmF0dHJpYnV0ZXMubm9ybWFsLnZhbHVlcyA9IG5vcm1hbHM7CiAgICB9CiAgICBpZiAoc2hhZG93Vm9sdW1lKSB7CiAgICAgIHRvcE5vcm1hbHMgPSB0b3BCb3R0b21HZW8uYXR0cmlidXRlcy5ub3JtYWwudmFsdWVzOwogICAgICBpZiAoIXZlcnRleEZvcm1hdC5ub3JtYWwpIHsKICAgICAgICB0b3BCb3R0b21HZW8uYXR0cmlidXRlcy5ub3JtYWwgPSB2b2lkIDA7CiAgICAgIH0KICAgICAgY29uc3QgZXh0cnVkZU5vcm1hbHMgPSBuZXcgRmxvYXQzMkFycmF5KG5ld0xlbmd0aCk7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgIHRvcE5vcm1hbHNbaV0gPSAtdG9wTm9ybWFsc1tpXTsKICAgICAgfQogICAgICBleHRydWRlTm9ybWFscy5zZXQodG9wTm9ybWFscywgbGVuZ3RoKTsKICAgICAgdG9wQm90dG9tR2VvLmF0dHJpYnV0ZXMuZXh0cnVkZURpcmVjdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgIHZhbHVlczogZXh0cnVkZU5vcm1hbHMKICAgICAgfSk7CiAgICB9CiAgICBsZXQgb2Zmc2V0VmFsdWU7CiAgICBjb25zdCBoYXNPZmZzZXRzID0gZGVmaW5lZF9kZWZhdWx0KG9mZnNldEF0dHJpYnV0ZVZhbHVlKTsKICAgIGlmIChoYXNPZmZzZXRzKSB7CiAgICAgIGNvbnN0IHNpemUgPSBsZW5ndGggLyAzICogMjsKICAgICAgbGV0IG9mZnNldEF0dHJpYnV0ZSA9IG5ldyBVaW50OEFycmF5KHNpemUpOwogICAgICBpZiAob2Zmc2V0QXR0cmlidXRlVmFsdWUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuVE9QKSB7CiAgICAgICAgb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlLmZpbGwoMSwgMCwgc2l6ZSAvIDIpOwogICAgICB9IGVsc2UgewogICAgICAgIG9mZnNldFZhbHVlID0gb2Zmc2V0QXR0cmlidXRlVmFsdWUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuTk9ORSA/IDAgOiAxOwogICAgICAgIG9mZnNldEF0dHJpYnV0ZSA9IG9mZnNldEF0dHJpYnV0ZS5maWxsKG9mZnNldFZhbHVlKTsKICAgICAgfQogICAgICB0b3BCb3R0b21HZW8uYXR0cmlidXRlcy5hcHBseU9mZnNldCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9CWVRFLAogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDEsCiAgICAgICAgdmFsdWVzOiBvZmZzZXRBdHRyaWJ1dGUKICAgICAgfSk7CiAgICB9CiAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQpIHsKICAgICAgY29uc3QgdG9wVGFuZ2VudHMgPSB0b3BCb3R0b21HZW8uYXR0cmlidXRlcy50YW5nZW50LnZhbHVlczsKICAgICAgdGFuZ2VudHMuc2V0KHRvcFRhbmdlbnRzKTsKICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgdG9wVGFuZ2VudHNbaV0gPSAtdG9wVGFuZ2VudHNbaV07CiAgICAgIH0KICAgICAgdGFuZ2VudHMuc2V0KHRvcFRhbmdlbnRzLCBsZW5ndGgpOwogICAgICB0b3BCb3R0b21HZW8uYXR0cmlidXRlcy50YW5nZW50LnZhbHVlcyA9IHRhbmdlbnRzOwogICAgfQogICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgY29uc3QgdG9wQml0YW5nZW50cyA9IHRvcEJvdHRvbUdlby5hdHRyaWJ1dGVzLmJpdGFuZ2VudC52YWx1ZXM7CiAgICAgIGJpdGFuZ2VudHMuc2V0KHRvcEJpdGFuZ2VudHMpOwogICAgICBiaXRhbmdlbnRzLnNldCh0b3BCaXRhbmdlbnRzLCBsZW5ndGgpOwogICAgICB0b3BCb3R0b21HZW8uYXR0cmlidXRlcy5iaXRhbmdlbnQudmFsdWVzID0gYml0YW5nZW50czsKICAgIH0KICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgdG9wU3QgPSB0b3BCb3R0b21HZW8uYXR0cmlidXRlcy5zdC52YWx1ZXM7CiAgICAgIHRleHR1cmVzLnNldCh0b3BTdCk7CiAgICAgIHRleHR1cmVzLnNldCh0b3BTdCwgbGVuZ3RoIC8gMyAqIDIpOwogICAgICB0b3BCb3R0b21HZW8uYXR0cmlidXRlcy5zdC52YWx1ZXMgPSB0ZXh0dXJlczsKICAgIH0KICAgIGNvbnN0IGluZGljZXMgPSB0b3BCb3R0b21HZW8uaW5kaWNlczsKICAgIGNvbnN0IGluZGljZXNMZW5ndGggPSBpbmRpY2VzLmxlbmd0aDsKICAgIGNvbnN0IHBvc0xlbmd0aCA9IGxlbmd0aCAvIDM7CiAgICBjb25zdCBuZXdJbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgIG5ld0xlbmd0aCAvIDMsCiAgICAgIGluZGljZXNMZW5ndGggKiAyCiAgICApOwogICAgbmV3SW5kaWNlcy5zZXQoaW5kaWNlcyk7CiAgICBmb3IgKGkgPSAwOyBpIDwgaW5kaWNlc0xlbmd0aDsgaSArPSAzKSB7CiAgICAgIG5ld0luZGljZXNbaSArIGluZGljZXNMZW5ndGhdID0gaW5kaWNlc1tpICsgMl0gKyBwb3NMZW5ndGg7CiAgICAgIG5ld0luZGljZXNbaSArIDEgKyBpbmRpY2VzTGVuZ3RoXSA9IGluZGljZXNbaSArIDFdICsgcG9zTGVuZ3RoOwogICAgICBuZXdJbmRpY2VzW2kgKyAyICsgaW5kaWNlc0xlbmd0aF0gPSBpbmRpY2VzW2ldICsgcG9zTGVuZ3RoOwogICAgfQogICAgdG9wQm90dG9tR2VvLmluZGljZXMgPSBuZXdJbmRpY2VzOwogICAgY29uc3Qgbm9ydGhDYXAgPSBjb21wdXRlZE9wdGlvbnMubm9ydGhDYXA7CiAgICBjb25zdCBzb3V0aENhcCA9IGNvbXB1dGVkT3B0aW9ucy5zb3V0aENhcDsKICAgIGxldCByb3dIZWlnaHQgPSBoZWlnaHQ7CiAgICBsZXQgd2lkdGhNdWx0aXBsaWVyID0gMjsKICAgIGxldCBwZXJpbWV0ZXJQb3NpdGlvbnMgPSAwOwogICAgbGV0IGNvcm5lcnMgPSA0OwogICAgbGV0IGR1cGxpYXRlQ29ybmVycyA9IDQ7CiAgICBpZiAobm9ydGhDYXApIHsKICAgICAgd2lkdGhNdWx0aXBsaWVyIC09IDE7CiAgICAgIHJvd0hlaWdodCAtPSAxOwogICAgICBwZXJpbWV0ZXJQb3NpdGlvbnMgKz0gMTsKICAgICAgY29ybmVycyAtPSAyOwogICAgICBkdXBsaWF0ZUNvcm5lcnMgLT0gMTsKICAgIH0KICAgIGlmIChzb3V0aENhcCkgewogICAgICB3aWR0aE11bHRpcGxpZXIgLT0gMTsKICAgICAgcm93SGVpZ2h0IC09IDE7CiAgICAgIHBlcmltZXRlclBvc2l0aW9ucyArPSAxOwogICAgICBjb3JuZXJzIC09IDI7CiAgICAgIGR1cGxpYXRlQ29ybmVycyAtPSAxOwogICAgfQogICAgcGVyaW1ldGVyUG9zaXRpb25zICs9IHdpZHRoTXVsdGlwbGllciAqIHdpZHRoICsgMiAqIHJvd0hlaWdodCAtIGNvcm5lcnM7CiAgICBjb25zdCB3YWxsQ291bnQgPSAocGVyaW1ldGVyUG9zaXRpb25zICsgZHVwbGlhdGVDb3JuZXJzKSAqIDI7CiAgICBsZXQgd2FsbFBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkod2FsbENvdW50ICogMyk7CiAgICBjb25zdCB3YWxsRXh0cnVkZU5vcm1hbHMgPSBzaGFkb3dWb2x1bWUgPyBuZXcgRmxvYXQzMkFycmF5KHdhbGxDb3VudCAqIDMpIDogdm9pZCAwOwogICAgbGV0IHdhbGxPZmZzZXRBdHRyaWJ1dGUgPSBoYXNPZmZzZXRzID8gbmV3IFVpbnQ4QXJyYXkod2FsbENvdW50KSA6IHZvaWQgMDsKICAgIGxldCB3YWxsVGV4dHVyZXMgPSB2ZXJ0ZXhGb3JtYXQuc3QgPyBuZXcgRmxvYXQzMkFycmF5KHdhbGxDb3VudCAqIDIpIDogdm9pZCAwOwogICAgY29uc3QgY29tcHV0ZVRvcE9mZnNldHMgPSBvZmZzZXRBdHRyaWJ1dGVWYWx1ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5UT1A7CiAgICBpZiAoaGFzT2Zmc2V0cyAmJiAhY29tcHV0ZVRvcE9mZnNldHMpIHsKICAgICAgb2Zmc2V0VmFsdWUgPSBvZmZzZXRBdHRyaWJ1dGVWYWx1ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5BTEwgPyAxIDogMDsKICAgICAgd2FsbE9mZnNldEF0dHJpYnV0ZSA9IHdhbGxPZmZzZXRBdHRyaWJ1dGUuZmlsbChvZmZzZXRWYWx1ZSk7CiAgICB9CiAgICBsZXQgcG9zSW5kZXggPSAwOwogICAgbGV0IHN0SW5kZXggPSAwOwogICAgbGV0IGV4dHJ1ZGVOb3JtYWxJbmRleCA9IDA7CiAgICBsZXQgd2FsbE9mZnNldEluZGV4ID0gMDsKICAgIGNvbnN0IGFyZWEyID0gd2lkdGggKiByb3dIZWlnaHQ7CiAgICBsZXQgdGhyZWVJOwogICAgZm9yIChpID0gMDsgaSA8IGFyZWEyOyBpICs9IHdpZHRoKSB7CiAgICAgIHRocmVlSSA9IGkgKiAzOwogICAgICB3YWxsUG9zaXRpb25zID0gYWRkV2FsbFBvc2l0aW9uczIoCiAgICAgICAgd2FsbFBvc2l0aW9ucywKICAgICAgICBwb3NJbmRleCwKICAgICAgICB0aHJlZUksCiAgICAgICAgdG9wUG9zaXRpb25zLAogICAgICAgIGJvdHRvbVBvc2l0aW9ucwogICAgICApOwogICAgICBwb3NJbmRleCArPSA2OwogICAgICBpZiAodmVydGV4Rm9ybWF0LnN0KSB7CiAgICAgICAgd2FsbFRleHR1cmVzID0gYWRkV2FsbFRleHR1cmVDb29yZGluYXRlcygKICAgICAgICAgIHdhbGxUZXh0dXJlcywKICAgICAgICAgIHN0SW5kZXgsCiAgICAgICAgICBpICogMiwKICAgICAgICAgIHRvcFN0CiAgICAgICAgKTsKICAgICAgICBzdEluZGV4ICs9IDQ7CiAgICAgIH0KICAgICAgaWYgKHNoYWRvd1ZvbHVtZSkgewogICAgICAgIGV4dHJ1ZGVOb3JtYWxJbmRleCArPSAzOwogICAgICAgIHdhbGxFeHRydWRlTm9ybWFsc1tleHRydWRlTm9ybWFsSW5kZXgrK10gPSB0b3BOb3JtYWxzW3RocmVlSV07CiAgICAgICAgd2FsbEV4dHJ1ZGVOb3JtYWxzW2V4dHJ1ZGVOb3JtYWxJbmRleCsrXSA9IHRvcE5vcm1hbHNbdGhyZWVJICsgMV07CiAgICAgICAgd2FsbEV4dHJ1ZGVOb3JtYWxzW2V4dHJ1ZGVOb3JtYWxJbmRleCsrXSA9IHRvcE5vcm1hbHNbdGhyZWVJICsgMl07CiAgICAgIH0KICAgICAgaWYgKGNvbXB1dGVUb3BPZmZzZXRzKSB7CiAgICAgICAgd2FsbE9mZnNldEF0dHJpYnV0ZVt3YWxsT2Zmc2V0SW5kZXgrK10gPSAxOwogICAgICAgIHdhbGxPZmZzZXRJbmRleCArPSAxOwogICAgICB9CiAgICB9CiAgICBpZiAoIXNvdXRoQ2FwKSB7CiAgICAgIGZvciAoaSA9IGFyZWEyIC0gd2lkdGg7IGkgPCBhcmVhMjsgaSsrKSB7CiAgICAgICAgdGhyZWVJID0gaSAqIDM7CiAgICAgICAgd2FsbFBvc2l0aW9ucyA9IGFkZFdhbGxQb3NpdGlvbnMyKAogICAgICAgICAgd2FsbFBvc2l0aW9ucywKICAgICAgICAgIHBvc0luZGV4LAogICAgICAgICAgdGhyZWVJLAogICAgICAgICAgdG9wUG9zaXRpb25zLAogICAgICAgICAgYm90dG9tUG9zaXRpb25zCiAgICAgICAgKTsKICAgICAgICBwb3NJbmRleCArPSA2OwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICAgIHdhbGxUZXh0dXJlcyA9IGFkZFdhbGxUZXh0dXJlQ29vcmRpbmF0ZXMoCiAgICAgICAgICAgIHdhbGxUZXh0dXJlcywKICAgICAgICAgICAgc3RJbmRleCwKICAgICAgICAgICAgaSAqIDIsCiAgICAgICAgICAgIHRvcFN0CiAgICAgICAgICApOwogICAgICAgICAgc3RJbmRleCArPSA0OwogICAgICAgIH0KICAgICAgICBpZiAoc2hhZG93Vm9sdW1lKSB7CiAgICAgICAgICBleHRydWRlTm9ybWFsSW5kZXggKz0gMzsKICAgICAgICAgIHdhbGxFeHRydWRlTm9ybWFsc1tleHRydWRlTm9ybWFsSW5kZXgrK10gPSB0b3BOb3JtYWxzW3RocmVlSV07CiAgICAgICAgICB3YWxsRXh0cnVkZU5vcm1hbHNbZXh0cnVkZU5vcm1hbEluZGV4KytdID0gdG9wTm9ybWFsc1t0aHJlZUkgKyAxXTsKICAgICAgICAgIHdhbGxFeHRydWRlTm9ybWFsc1tleHRydWRlTm9ybWFsSW5kZXgrK10gPSB0b3BOb3JtYWxzW3RocmVlSSArIDJdOwogICAgICAgIH0KICAgICAgICBpZiAoY29tcHV0ZVRvcE9mZnNldHMpIHsKICAgICAgICAgIHdhbGxPZmZzZXRBdHRyaWJ1dGVbd2FsbE9mZnNldEluZGV4KytdID0gMTsKICAgICAgICAgIHdhbGxPZmZzZXRJbmRleCArPSAxOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgY29uc3Qgc291dGhJbmRleCA9IG5vcnRoQ2FwID8gYXJlYTIgKyAxIDogYXJlYTI7CiAgICAgIHRocmVlSSA9IHNvdXRoSW5kZXggKiAzOwogICAgICBmb3IgKGkgPSAwOyBpIDwgMjsgaSsrKSB7CiAgICAgICAgd2FsbFBvc2l0aW9ucyA9IGFkZFdhbGxQb3NpdGlvbnMyKAogICAgICAgICAgd2FsbFBvc2l0aW9ucywKICAgICAgICAgIHBvc0luZGV4LAogICAgICAgICAgdGhyZWVJLAogICAgICAgICAgdG9wUG9zaXRpb25zLAogICAgICAgICAgYm90dG9tUG9zaXRpb25zCiAgICAgICAgKTsKICAgICAgICBwb3NJbmRleCArPSA2OwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICAgIHdhbGxUZXh0dXJlcyA9IGFkZFdhbGxUZXh0dXJlQ29vcmRpbmF0ZXMoCiAgICAgICAgICAgIHdhbGxUZXh0dXJlcywKICAgICAgICAgICAgc3RJbmRleCwKICAgICAgICAgICAgc291dGhJbmRleCAqIDIsCiAgICAgICAgICAgIHRvcFN0CiAgICAgICAgICApOwogICAgICAgICAgc3RJbmRleCArPSA0OwogICAgICAgIH0KICAgICAgICBpZiAoc2hhZG93Vm9sdW1lKSB7CiAgICAgICAgICBleHRydWRlTm9ybWFsSW5kZXggKz0gMzsKICAgICAgICAgIHdhbGxFeHRydWRlTm9ybWFsc1tleHRydWRlTm9ybWFsSW5kZXgrK10gPSB0b3BOb3JtYWxzW3RocmVlSV07CiAgICAgICAgICB3YWxsRXh0cnVkZU5vcm1hbHNbZXh0cnVkZU5vcm1hbEluZGV4KytdID0gdG9wTm9ybWFsc1t0aHJlZUkgKyAxXTsKICAgICAgICAgIHdhbGxFeHRydWRlTm9ybWFsc1tleHRydWRlTm9ybWFsSW5kZXgrK10gPSB0b3BOb3JtYWxzW3RocmVlSSArIDJdOwogICAgICAgIH0KICAgICAgICBpZiAoY29tcHV0ZVRvcE9mZnNldHMpIHsKICAgICAgICAgIHdhbGxPZmZzZXRBdHRyaWJ1dGVbd2FsbE9mZnNldEluZGV4KytdID0gMTsKICAgICAgICAgIHdhbGxPZmZzZXRJbmRleCArPSAxOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgZm9yIChpID0gYXJlYTIgLSAxOyBpID4gMDsgaSAtPSB3aWR0aCkgewogICAgICB0aHJlZUkgPSBpICogMzsKICAgICAgd2FsbFBvc2l0aW9ucyA9IGFkZFdhbGxQb3NpdGlvbnMyKAogICAgICAgIHdhbGxQb3NpdGlvbnMsCiAgICAgICAgcG9zSW5kZXgsCiAgICAgICAgdGhyZWVJLAogICAgICAgIHRvcFBvc2l0aW9ucywKICAgICAgICBib3R0b21Qb3NpdGlvbnMKICAgICAgKTsKICAgICAgcG9zSW5kZXggKz0gNjsKICAgICAgaWYgKHZlcnRleEZvcm1hdC5zdCkgewogICAgICAgIHdhbGxUZXh0dXJlcyA9IGFkZFdhbGxUZXh0dXJlQ29vcmRpbmF0ZXMoCiAgICAgICAgICB3YWxsVGV4dHVyZXMsCiAgICAgICAgICBzdEluZGV4LAogICAgICAgICAgaSAqIDIsCiAgICAgICAgICB0b3BTdAogICAgICAgICk7CiAgICAgICAgc3RJbmRleCArPSA0OwogICAgICB9CiAgICAgIGlmIChzaGFkb3dWb2x1bWUpIHsKICAgICAgICBleHRydWRlTm9ybWFsSW5kZXggKz0gMzsKICAgICAgICB3YWxsRXh0cnVkZU5vcm1hbHNbZXh0cnVkZU5vcm1hbEluZGV4KytdID0gdG9wTm9ybWFsc1t0aHJlZUldOwogICAgICAgIHdhbGxFeHRydWRlTm9ybWFsc1tleHRydWRlTm9ybWFsSW5kZXgrK10gPSB0b3BOb3JtYWxzW3RocmVlSSArIDFdOwogICAgICAgIHdhbGxFeHRydWRlTm9ybWFsc1tleHRydWRlTm9ybWFsSW5kZXgrK10gPSB0b3BOb3JtYWxzW3RocmVlSSArIDJdOwogICAgICB9CiAgICAgIGlmIChjb21wdXRlVG9wT2Zmc2V0cykgewogICAgICAgIHdhbGxPZmZzZXRBdHRyaWJ1dGVbd2FsbE9mZnNldEluZGV4KytdID0gMTsKICAgICAgICB3YWxsT2Zmc2V0SW5kZXggKz0gMTsKICAgICAgfQogICAgfQogICAgaWYgKCFub3J0aENhcCkgewogICAgICBmb3IgKGkgPSB3aWR0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgdGhyZWVJID0gaSAqIDM7CiAgICAgICAgd2FsbFBvc2l0aW9ucyA9IGFkZFdhbGxQb3NpdGlvbnMyKAogICAgICAgICAgd2FsbFBvc2l0aW9ucywKICAgICAgICAgIHBvc0luZGV4LAogICAgICAgICAgdGhyZWVJLAogICAgICAgICAgdG9wUG9zaXRpb25zLAogICAgICAgICAgYm90dG9tUG9zaXRpb25zCiAgICAgICAgKTsKICAgICAgICBwb3NJbmRleCArPSA2OwogICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQuc3QpIHsKICAgICAgICAgIHdhbGxUZXh0dXJlcyA9IGFkZFdhbGxUZXh0dXJlQ29vcmRpbmF0ZXMoCiAgICAgICAgICAgIHdhbGxUZXh0dXJlcywKICAgICAgICAgICAgc3RJbmRleCwKICAgICAgICAgICAgaSAqIDIsCiAgICAgICAgICAgIHRvcFN0CiAgICAgICAgICApOwogICAgICAgICAgc3RJbmRleCArPSA0OwogICAgICAgIH0KICAgICAgICBpZiAoc2hhZG93Vm9sdW1lKSB7CiAgICAgICAgICBleHRydWRlTm9ybWFsSW5kZXggKz0gMzsKICAgICAgICAgIHdhbGxFeHRydWRlTm9ybWFsc1tleHRydWRlTm9ybWFsSW5kZXgrK10gPSB0b3BOb3JtYWxzW3RocmVlSV07CiAgICAgICAgICB3YWxsRXh0cnVkZU5vcm1hbHNbZXh0cnVkZU5vcm1hbEluZGV4KytdID0gdG9wTm9ybWFsc1t0aHJlZUkgKyAxXTsKICAgICAgICAgIHdhbGxFeHRydWRlTm9ybWFsc1tleHRydWRlTm9ybWFsSW5kZXgrK10gPSB0b3BOb3JtYWxzW3RocmVlSSArIDJdOwogICAgICAgIH0KICAgICAgICBpZiAoY29tcHV0ZVRvcE9mZnNldHMpIHsKICAgICAgICAgIHdhbGxPZmZzZXRBdHRyaWJ1dGVbd2FsbE9mZnNldEluZGV4KytdID0gMTsKICAgICAgICAgIHdhbGxPZmZzZXRJbmRleCArPSAxOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgY29uc3Qgbm9ydGhJbmRleCA9IGFyZWEyOwogICAgICB0aHJlZUkgPSBub3J0aEluZGV4ICogMzsKICAgICAgZm9yIChpID0gMDsgaSA8IDI7IGkrKykgewogICAgICAgIHdhbGxQb3NpdGlvbnMgPSBhZGRXYWxsUG9zaXRpb25zMigKICAgICAgICAgIHdhbGxQb3NpdGlvbnMsCiAgICAgICAgICBwb3NJbmRleCwKICAgICAgICAgIHRocmVlSSwKICAgICAgICAgIHRvcFBvc2l0aW9ucywKICAgICAgICAgIGJvdHRvbVBvc2l0aW9ucwogICAgICAgICk7CiAgICAgICAgcG9zSW5kZXggKz0gNjsKICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnN0KSB7CiAgICAgICAgICB3YWxsVGV4dHVyZXMgPSBhZGRXYWxsVGV4dHVyZUNvb3JkaW5hdGVzKAogICAgICAgICAgICB3YWxsVGV4dHVyZXMsCiAgICAgICAgICAgIHN0SW5kZXgsCiAgICAgICAgICAgIG5vcnRoSW5kZXggKiAyLAogICAgICAgICAgICB0b3BTdAogICAgICAgICAgKTsKICAgICAgICAgIHN0SW5kZXggKz0gNDsKICAgICAgICB9CiAgICAgICAgaWYgKHNoYWRvd1ZvbHVtZSkgewogICAgICAgICAgZXh0cnVkZU5vcm1hbEluZGV4ICs9IDM7CiAgICAgICAgICB3YWxsRXh0cnVkZU5vcm1hbHNbZXh0cnVkZU5vcm1hbEluZGV4KytdID0gdG9wTm9ybWFsc1t0aHJlZUldOwogICAgICAgICAgd2FsbEV4dHJ1ZGVOb3JtYWxzW2V4dHJ1ZGVOb3JtYWxJbmRleCsrXSA9IHRvcE5vcm1hbHNbdGhyZWVJICsgMV07CiAgICAgICAgICB3YWxsRXh0cnVkZU5vcm1hbHNbZXh0cnVkZU5vcm1hbEluZGV4KytdID0gdG9wTm9ybWFsc1t0aHJlZUkgKyAyXTsKICAgICAgICB9CiAgICAgICAgaWYgKGNvbXB1dGVUb3BPZmZzZXRzKSB7CiAgICAgICAgICB3YWxsT2Zmc2V0QXR0cmlidXRlW3dhbGxPZmZzZXRJbmRleCsrXSA9IDE7CiAgICAgICAgICB3YWxsT2Zmc2V0SW5kZXggKz0gMTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGxldCBnZW8gPSBjYWxjdWxhdGVBdHRyaWJ1dGVzV2FsbCh3YWxsUG9zaXRpb25zLCB2ZXJ0ZXhGb3JtYXQsIGVsbGlwc29pZCk7CiAgICBpZiAodmVydGV4Rm9ybWF0LnN0KSB7CiAgICAgIGdlby5hdHRyaWJ1dGVzLnN0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDIsCiAgICAgICAgdmFsdWVzOiB3YWxsVGV4dHVyZXMKICAgICAgfSk7CiAgICB9CiAgICBpZiAoc2hhZG93Vm9sdW1lKSB7CiAgICAgIGdlby5hdHRyaWJ1dGVzLmV4dHJ1ZGVEaXJlY3Rpb24gPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICB2YWx1ZXM6IHdhbGxFeHRydWRlTm9ybWFscwogICAgICB9KTsKICAgIH0KICAgIGlmIChoYXNPZmZzZXRzKSB7CiAgICAgIGdlby5hdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEUsCiAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMSwKICAgICAgICB2YWx1ZXM6IHdhbGxPZmZzZXRBdHRyaWJ1dGUKICAgICAgfSk7CiAgICB9CiAgICBjb25zdCB3YWxsSW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KAogICAgICB3YWxsQ291bnQsCiAgICAgIHBlcmltZXRlclBvc2l0aW9ucyAqIDYKICAgICk7CiAgICBsZXQgdXBwZXJMZWZ0OwogICAgbGV0IGxvd2VyTGVmdDsKICAgIGxldCBsb3dlclJpZ2h0OwogICAgbGV0IHVwcGVyUmlnaHQ7CiAgICBsZW5ndGggPSB3YWxsUG9zaXRpb25zLmxlbmd0aCAvIDM7CiAgICBsZXQgaW5kZXggPSAwOwogICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aCAtIDE7IGkgKz0gMikgewogICAgICB1cHBlckxlZnQgPSBpOwogICAgICB1cHBlclJpZ2h0ID0gKHVwcGVyTGVmdCArIDIpICUgbGVuZ3RoOwogICAgICBjb25zdCBwMSA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkod2FsbFBvc2l0aW9ucywgdXBwZXJMZWZ0ICogMywgdjFTY3JhdGNoKTsKICAgICAgY29uc3QgcDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHdhbGxQb3NpdGlvbnMsIHVwcGVyUmlnaHQgKiAzLCB2MlNjcmF0Y2gpOwogICAgICBpZiAoQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFsc0Vwc2lsb24ocDEsIHAyLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjEwKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGxvd2VyTGVmdCA9ICh1cHBlckxlZnQgKyAxKSAlIGxlbmd0aDsKICAgICAgbG93ZXJSaWdodCA9IChsb3dlckxlZnQgKyAyKSAlIGxlbmd0aDsKICAgICAgd2FsbEluZGljZXNbaW5kZXgrK10gPSB1cHBlckxlZnQ7CiAgICAgIHdhbGxJbmRpY2VzW2luZGV4KytdID0gbG93ZXJMZWZ0OwogICAgICB3YWxsSW5kaWNlc1tpbmRleCsrXSA9IHVwcGVyUmlnaHQ7CiAgICAgIHdhbGxJbmRpY2VzW2luZGV4KytdID0gdXBwZXJSaWdodDsKICAgICAgd2FsbEluZGljZXNbaW5kZXgrK10gPSBsb3dlckxlZnQ7CiAgICAgIHdhbGxJbmRpY2VzW2luZGV4KytdID0gbG93ZXJSaWdodDsKICAgIH0KICAgIGdlby5pbmRpY2VzID0gd2FsbEluZGljZXM7CiAgICBnZW8gPSBHZW9tZXRyeVBpcGVsaW5lX2RlZmF1bHQuY29tYmluZUluc3RhbmNlcyhbCiAgICAgIG5ldyBHZW9tZXRyeUluc3RhbmNlX2RlZmF1bHQoewogICAgICAgIGdlb21ldHJ5OiB0b3BCb3R0b21HZW8KICAgICAgfSksCiAgICAgIG5ldyBHZW9tZXRyeUluc3RhbmNlX2RlZmF1bHQoewogICAgICAgIGdlb21ldHJ5OiBnZW8KICAgICAgfSkKICAgIF0pOwogICAgcmV0dXJuIGdlb1swXTsKICB9CiAgZnVuY3Rpb24gY29tcHV0ZVJlY3RhbmdsZTMocmVjdGFuZ2xlLCBncmFudWxhcml0eSwgcm90YXRpb24sIGVsbGlwc29pZCwgcmVzdWx0KSB7CiAgICBpZiAocm90YXRpb24gPT09IDApIHsKICAgICAgcmV0dXJuIFJlY3RhbmdsZV9kZWZhdWx0LmNsb25lKHJlY3RhbmdsZSwgcmVzdWx0KTsKICAgIH0KICAgIGNvbnN0IGNvbXB1dGVkT3B0aW9ucyA9IFJlY3RhbmdsZUdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVPcHRpb25zKAogICAgICByZWN0YW5nbGUsCiAgICAgIGdyYW51bGFyaXR5LAogICAgICByb3RhdGlvbiwKICAgICAgMCwKICAgICAgcmVjdGFuZ2xlU2NyYXRjaCwKICAgICAgbndTY3JhdGNoCiAgICApOwogICAgY29uc3QgaGVpZ2h0ID0gY29tcHV0ZWRPcHRpb25zLmhlaWdodDsKICAgIGNvbnN0IHdpZHRoID0gY29tcHV0ZWRPcHRpb25zLndpZHRoOwogICAgY29uc3QgcG9zaXRpb25zID0gc2NyYXRjaFJlY3RhbmdsZVBvaW50czsKICAgIFJlY3RhbmdsZUdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVQb3NpdGlvbigKICAgICAgY29tcHV0ZWRPcHRpb25zLAogICAgICBlbGxpcHNvaWQsCiAgICAgIGZhbHNlLAogICAgICAwLAogICAgICAwLAogICAgICBwb3NpdGlvbnNbMF0KICAgICk7CiAgICBSZWN0YW5nbGVHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlUG9zaXRpb24oCiAgICAgIGNvbXB1dGVkT3B0aW9ucywKICAgICAgZWxsaXBzb2lkLAogICAgICBmYWxzZSwKICAgICAgMCwKICAgICAgd2lkdGggLSAxLAogICAgICBwb3NpdGlvbnNbMV0KICAgICk7CiAgICBSZWN0YW5nbGVHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlUG9zaXRpb24oCiAgICAgIGNvbXB1dGVkT3B0aW9ucywKICAgICAgZWxsaXBzb2lkLAogICAgICBmYWxzZSwKICAgICAgaGVpZ2h0IC0gMSwKICAgICAgMCwKICAgICAgcG9zaXRpb25zWzJdCiAgICApOwogICAgUmVjdGFuZ2xlR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZVBvc2l0aW9uKAogICAgICBjb21wdXRlZE9wdGlvbnMsCiAgICAgIGVsbGlwc29pZCwKICAgICAgZmFsc2UsCiAgICAgIGhlaWdodCAtIDEsCiAgICAgIHdpZHRoIC0gMSwKICAgICAgcG9zaXRpb25zWzNdCiAgICApOwogICAgcmV0dXJuIFJlY3RhbmdsZV9kZWZhdWx0LmZyb21DYXJ0ZXNpYW5BcnJheShwb3NpdGlvbnMsIGVsbGlwc29pZCwgcmVzdWx0KTsKICB9CiAgZnVuY3Rpb24gUmVjdGFuZ2xlR2VvbWV0cnkob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgY29uc3QgcmVjdGFuZ2xlID0gb3B0aW9ucy5yZWN0YW5nbGU7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInJlY3RhbmdsZSIsIHJlY3RhbmdsZSk7CiAgICBSZWN0YW5nbGVfZGVmYXVsdC5fdmFsaWRhdGUocmVjdGFuZ2xlKTsKICAgIGlmIChyZWN0YW5nbGUubm9ydGggPCByZWN0YW5nbGUuc291dGgpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgIm9wdGlvbnMucmVjdGFuZ2xlLm5vcnRoIG11c3QgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIG9wdGlvbnMucmVjdGFuZ2xlLnNvdXRoIgogICAgICApOwogICAgfQogICAgY29uc3QgaGVpZ2h0ID0gb3B0aW9ucy5oZWlnaHQgPz8gMDsKICAgIGNvbnN0IGV4dHJ1ZGVkSGVpZ2h0ID0gb3B0aW9ucy5leHRydWRlZEhlaWdodCA/PyBoZWlnaHQ7CiAgICB0aGlzLl9yZWN0YW5nbGUgPSBSZWN0YW5nbGVfZGVmYXVsdC5jbG9uZShyZWN0YW5nbGUpOwogICAgdGhpcy5fZ3JhbnVsYXJpdHkgPSBvcHRpb25zLmdyYW51bGFyaXR5ID8/IE1hdGhfZGVmYXVsdC5SQURJQU5TX1BFUl9ERUdSRUU7CiAgICB0aGlzLl9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShvcHRpb25zLmVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0KTsKICAgIHRoaXMuX3N1cmZhY2VIZWlnaHQgPSBNYXRoLm1heChoZWlnaHQsIGV4dHJ1ZGVkSGVpZ2h0KTsKICAgIHRoaXMuX3JvdGF0aW9uID0gb3B0aW9ucy5yb3RhdGlvbiA/PyAwOwogICAgdGhpcy5fc3RSb3RhdGlvbiA9IG9wdGlvbnMuc3RSb3RhdGlvbiA/PyAwOwogICAgdGhpcy5fdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQuY2xvbmUoCiAgICAgIG9wdGlvbnMudmVydGV4Rm9ybWF0ID8/IFZlcnRleEZvcm1hdF9kZWZhdWx0LkRFRkFVTFQKICAgICk7CiAgICB0aGlzLl9leHRydWRlZEhlaWdodCA9IE1hdGgubWluKGhlaWdodCwgZXh0cnVkZWRIZWlnaHQpOwogICAgdGhpcy5fc2hhZG93Vm9sdW1lID0gb3B0aW9ucy5zaGFkb3dWb2x1bWUgPz8gZmFsc2U7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZVJlY3RhbmdsZUdlb21ldHJ5IjsKICAgIHRoaXMuX29mZnNldEF0dHJpYnV0ZSA9IG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlOwogICAgdGhpcy5fcm90YXRlZFJlY3RhbmdsZSA9IHZvaWQgMDsKICAgIHRoaXMuX3RleHR1cmVDb29yZGluYXRlUm90YXRpb25Qb2ludHMgPSB2b2lkIDA7CiAgfQogIGZ1bmN0aW9uIHRleHR1cmVDb29yZGluYXRlUm90YXRpb25Qb2ludHMzKHJlY3RhbmdsZUdlb21ldHJ5KSB7CiAgICBpZiAocmVjdGFuZ2xlR2VvbWV0cnkuX3N0Um90YXRpb24gPT09IDApIHsKICAgICAgcmV0dXJuIFswLCAwLCAwLCAxLCAxLCAwXTsKICAgIH0KICAgIGNvbnN0IHJlY3RhbmdsZSA9IFJlY3RhbmdsZV9kZWZhdWx0LmNsb25lKAogICAgICByZWN0YW5nbGVHZW9tZXRyeS5fcmVjdGFuZ2xlLAogICAgICB1bnJvdGF0ZWRUZXh0dXJlUmVjdGFuZ2xlU2NyYXRjaAogICAgKTsKICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gcmVjdGFuZ2xlR2VvbWV0cnkuX2dyYW51bGFyaXR5OwogICAgY29uc3QgZWxsaXBzb2lkID0gcmVjdGFuZ2xlR2VvbWV0cnkuX2VsbGlwc29pZDsKICAgIGNvbnN0IHJvdGF0aW9uID0gcmVjdGFuZ2xlR2VvbWV0cnkuX3JvdGF0aW9uIC0gcmVjdGFuZ2xlR2VvbWV0cnkuX3N0Um90YXRpb247CiAgICBjb25zdCB1bnJvdGF0ZWRUZXh0dXJlUmVjdGFuZ2xlID0gY29tcHV0ZVJlY3RhbmdsZTMoCiAgICAgIHJlY3RhbmdsZSwKICAgICAgZ3JhbnVsYXJpdHksCiAgICAgIHJvdGF0aW9uLAogICAgICBlbGxpcHNvaWQsCiAgICAgIHVucm90YXRlZFRleHR1cmVSZWN0YW5nbGVTY3JhdGNoCiAgICApOwogICAgY29uc3QgcG9pbnRzMkQgPSBwb2ludHMyRFNjcmF0Y2gyOwogICAgcG9pbnRzMkRbMF0ueCA9IHVucm90YXRlZFRleHR1cmVSZWN0YW5nbGUud2VzdDsKICAgIHBvaW50czJEWzBdLnkgPSB1bnJvdGF0ZWRUZXh0dXJlUmVjdGFuZ2xlLnNvdXRoOwogICAgcG9pbnRzMkRbMV0ueCA9IHVucm90YXRlZFRleHR1cmVSZWN0YW5nbGUud2VzdDsKICAgIHBvaW50czJEWzFdLnkgPSB1bnJvdGF0ZWRUZXh0dXJlUmVjdGFuZ2xlLm5vcnRoOwogICAgcG9pbnRzMkRbMl0ueCA9IHVucm90YXRlZFRleHR1cmVSZWN0YW5nbGUuZWFzdDsKICAgIHBvaW50czJEWzJdLnkgPSB1bnJvdGF0ZWRUZXh0dXJlUmVjdGFuZ2xlLnNvdXRoOwogICAgY29uc3QgYm91bmRpbmdSZWN0YW5nbGUgPSByZWN0YW5nbGVHZW9tZXRyeS5yZWN0YW5nbGU7CiAgICBjb25zdCB0b0Rlc2lyZWRJbkNvbXB1dGVkID0gTWF0cml4Ml9kZWZhdWx0LmZyb21Sb3RhdGlvbigKICAgICAgcmVjdGFuZ2xlR2VvbWV0cnkuX3N0Um90YXRpb24sCiAgICAgIHJvdGF0aW9uMkRTY3JhdGNoMgogICAgKTsKICAgIGNvbnN0IGJvdW5kaW5nUmVjdGFuZ2xlQ2VudGVyID0gUmVjdGFuZ2xlX2RlZmF1bHQuY2VudGVyKAogICAgICBib3VuZGluZ1JlY3RhbmdsZSwKICAgICAgcmVjdGFuZ2xlQ2VudGVyU2NyYXRjaDIKICAgICk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7ICsraSkgewogICAgICBjb25zdCBwb2ludDJEID0gcG9pbnRzMkRbaV07CiAgICAgIHBvaW50MkQueCAtPSBib3VuZGluZ1JlY3RhbmdsZUNlbnRlci5sb25naXR1ZGU7CiAgICAgIHBvaW50MkQueSAtPSBib3VuZGluZ1JlY3RhbmdsZUNlbnRlci5sYXRpdHVkZTsKICAgICAgTWF0cml4Ml9kZWZhdWx0Lm11bHRpcGx5QnlWZWN0b3IodG9EZXNpcmVkSW5Db21wdXRlZCwgcG9pbnQyRCwgcG9pbnQyRCk7CiAgICAgIHBvaW50MkQueCArPSBib3VuZGluZ1JlY3RhbmdsZUNlbnRlci5sb25naXR1ZGU7CiAgICAgIHBvaW50MkQueSArPSBib3VuZGluZ1JlY3RhbmdsZUNlbnRlci5sYXRpdHVkZTsKICAgICAgcG9pbnQyRC54ID0gKHBvaW50MkQueCAtIGJvdW5kaW5nUmVjdGFuZ2xlLndlc3QpIC8gYm91bmRpbmdSZWN0YW5nbGUud2lkdGg7CiAgICAgIHBvaW50MkQueSA9IChwb2ludDJELnkgLSBib3VuZGluZ1JlY3RhbmdsZS5zb3V0aCkgLyBib3VuZGluZ1JlY3RhbmdsZS5oZWlnaHQ7CiAgICB9CiAgICBjb25zdCBtaW5YWUNvcm5lciA9IHBvaW50czJEWzBdOwogICAgY29uc3QgbWF4WUNvcm5lciA9IHBvaW50czJEWzFdOwogICAgY29uc3QgbWF4WENvcm5lciA9IHBvaW50czJEWzJdOwogICAgY29uc3QgcmVzdWx0ID0gbmV3IEFycmF5KDYpOwogICAgQ2FydGVzaWFuMl9kZWZhdWx0LnBhY2sobWluWFlDb3JuZXIsIHJlc3VsdCk7CiAgICBDYXJ0ZXNpYW4yX2RlZmF1bHQucGFjayhtYXhZQ29ybmVyLCByZXN1bHQsIDIpOwogICAgQ2FydGVzaWFuMl9kZWZhdWx0LnBhY2sobWF4WENvcm5lciwgcmVzdWx0LCA0KTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQogIHZhciBwb3NpdGlvblNjcmF0Y2gyLCBub3JtYWxTY3JhdGNoNCwgdGFuZ2VudFNjcmF0Y2gyLCBiaXRhbmdlbnRTY3JhdGNoMiwgcmVjdGFuZ2xlU2NyYXRjaCwgc3RTY3JhdGNoMiwgYm90dG9tQm91bmRpbmdTcGhlcmUzLCB0b3BCb3VuZGluZ1NwaGVyZTMsIHYxU2NyYXRjaCwgdjJTY3JhdGNoLCBzY3JhdGNoVmVydGV4Rm9ybWF0MTIsIHNjcmF0Y2hSZWN0YW5nbGVQb2ludHMsIG53U2NyYXRjaCwgc3ROd1NjcmF0Y2gsIHNjcmF0Y2hSZWN0YW5nbGUsIHNjcmF0Y2hFbGxpcHNvaWQxMSwgc2NyYXRjaE9wdGlvbnMxOSwgdGFuZ2VudFJvdGF0aW9uTWF0cml4U2NyYXRjaCwgcXVhdGVybmlvblNjcmF0Y2g0LCBjZW50ZXJTY3JhdGNoNCwgdW5yb3RhdGVkVGV4dHVyZVJlY3RhbmdsZVNjcmF0Y2gsIHBvaW50czJEU2NyYXRjaDIsIHJvdGF0aW9uMkRTY3JhdGNoMiwgcmVjdGFuZ2xlQ2VudGVyU2NyYXRjaDIsIFJlY3RhbmdsZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfUmVjdGFuZ2xlR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1JlY3RhbmdsZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZXMoKTsKICAgICAgaW5pdF9HZW9tZXRyeUluc3RhbmNlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeVBpcGVsaW5lKCk7CiAgICAgIGluaXRfSW5kZXhEYXRhdHlwZSgpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9NYXRyaXgyKCk7CiAgICAgIGluaXRfTWF0cml4MygpOwogICAgICBpbml0X1BvbHlnb25QaXBlbGluZSgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgaW5pdF9RdWF0ZXJuaW9uKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlR2VvbWV0cnlMaWJyYXJ5KCk7CiAgICAgIGluaXRfVmVydGV4Rm9ybWF0KCk7CiAgICAgIHBvc2l0aW9uU2NyYXRjaDIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIG5vcm1hbFNjcmF0Y2g0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICB0YW5nZW50U2NyYXRjaDIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGJpdGFuZ2VudFNjcmF0Y2gyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICByZWN0YW5nbGVTY3JhdGNoID0gbmV3IFJlY3RhbmdsZV9kZWZhdWx0KCk7CiAgICAgIHN0U2NyYXRjaDIgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIGJvdHRvbUJvdW5kaW5nU3BoZXJlMyA9IG5ldyBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0KCk7CiAgICAgIHRvcEJvdW5kaW5nU3BoZXJlMyA9IG5ldyBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0KCk7CiAgICAgIHYxU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgdjJTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoVmVydGV4Rm9ybWF0MTIgPSBuZXcgVmVydGV4Rm9ybWF0X2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFJlY3RhbmdsZVBvaW50cyA9IFsKICAgICAgICBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCksCiAgICAgICAgbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpLAogICAgICAgIG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKSwKICAgICAgICBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCkKICAgICAgXTsKICAgICAgbndTY3JhdGNoID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHN0TndTY3JhdGNoID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIFJlY3RhbmdsZUdlb21ldHJ5LnBhY2tlZExlbmd0aCA9IFJlY3RhbmdsZV9kZWZhdWx0LnBhY2tlZExlbmd0aCArIEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIDc7CiAgICAgIFJlY3RhbmdsZUdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgiYXJyYXkiLCBhcnJheSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBSZWN0YW5nbGVfZGVmYXVsdC5wYWNrKHZhbHVlLl9yZWN0YW5nbGUsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFJlY3RhbmdsZV9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrKHZhbHVlLl9lbGxpcHNvaWQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrKHZhbHVlLl92ZXJ0ZXhGb3JtYXQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2dyYW51bGFyaXR5OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fc3VyZmFjZUhlaWdodDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX3JvdGF0aW9uOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fc3RSb3RhdGlvbjsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2V4dHJ1ZGVkSGVpZ2h0OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fc2hhZG93Vm9sdW1lID8gMSA6IDA7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleF0gPSB2YWx1ZS5fb2Zmc2V0QXR0cmlidXRlID8/IC0xOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgc2NyYXRjaFJlY3RhbmdsZSA9IG5ldyBSZWN0YW5nbGVfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoRWxsaXBzb2lkMTEgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShFbGxpcHNvaWRfZGVmYXVsdC5VTklUX1NQSEVSRSk7CiAgICAgIHNjcmF0Y2hPcHRpb25zMTkgPSB7CiAgICAgICAgcmVjdGFuZ2xlOiBzY3JhdGNoUmVjdGFuZ2xlLAogICAgICAgIGVsbGlwc29pZDogc2NyYXRjaEVsbGlwc29pZDExLAogICAgICAgIHZlcnRleEZvcm1hdDogc2NyYXRjaFZlcnRleEZvcm1hdDEyLAogICAgICAgIGdyYW51bGFyaXR5OiB2b2lkIDAsCiAgICAgICAgaGVpZ2h0OiB2b2lkIDAsCiAgICAgICAgcm90YXRpb246IHZvaWQgMCwKICAgICAgICBzdFJvdGF0aW9uOiB2b2lkIDAsCiAgICAgICAgZXh0cnVkZWRIZWlnaHQ6IHZvaWQgMCwKICAgICAgICBzaGFkb3dWb2x1bWU6IHZvaWQgMCwKICAgICAgICBvZmZzZXRBdHRyaWJ1dGU6IHZvaWQgMAogICAgICB9OwogICAgICBSZWN0YW5nbGVHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJhcnJheSIsIGFycmF5KTsKICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGNvbnN0IHJlY3RhbmdsZSA9IFJlY3RhbmdsZV9kZWZhdWx0LnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCwgc2NyYXRjaFJlY3RhbmdsZSk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBSZWN0YW5nbGVfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoRWxsaXBzb2lkMTEpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnVucGFjaygKICAgICAgICAgIGFycmF5LAogICAgICAgICAgc3RhcnRpbmdJbmRleCwKICAgICAgICAgIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQxMgogICAgICAgICk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHN1cmZhY2VIZWlnaHQgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IHJvdGF0aW9uID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBzdFJvdGF0aW9uID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3Qgc2hhZG93Vm9sdW1lID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9PT0gMTsKICAgICAgICBjb25zdCBvZmZzZXRBdHRyaWJ1dGUgPSBhcnJheVtzdGFydGluZ0luZGV4XTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE5LmdyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE5LmhlaWdodCA9IHN1cmZhY2VIZWlnaHQ7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE5LnJvdGF0aW9uID0gcm90YXRpb247CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE5LnN0Um90YXRpb24gPSBzdFJvdGF0aW9uOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxOS5leHRydWRlZEhlaWdodCA9IGV4dHJ1ZGVkSGVpZ2h0OwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMxOS5zaGFkb3dWb2x1bWUgPSBzaGFkb3dWb2x1bWU7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczE5Lm9mZnNldEF0dHJpYnV0ZSA9IG9mZnNldEF0dHJpYnV0ZSA9PT0gLTEgPyB2b2lkIDAgOiBvZmZzZXRBdHRyaWJ1dGU7CiAgICAgICAgICByZXR1cm4gbmV3IFJlY3RhbmdsZUdlb21ldHJ5KHNjcmF0Y2hPcHRpb25zMTkpOwogICAgICAgIH0KICAgICAgICByZXN1bHQuX3JlY3RhbmdsZSA9IFJlY3RhbmdsZV9kZWZhdWx0LmNsb25lKHJlY3RhbmdsZSwgcmVzdWx0Ll9yZWN0YW5nbGUpOwogICAgICAgIHJlc3VsdC5fZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoZWxsaXBzb2lkLCByZXN1bHQuX2VsbGlwc29pZCk7CiAgICAgICAgcmVzdWx0Ll92ZXJ0ZXhGb3JtYXQgPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5jbG9uZSh2ZXJ0ZXhGb3JtYXQsIHJlc3VsdC5fdmVydGV4Rm9ybWF0KTsKICAgICAgICByZXN1bHQuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICAgICAgcmVzdWx0Ll9zdXJmYWNlSGVpZ2h0ID0gc3VyZmFjZUhlaWdodDsKICAgICAgICByZXN1bHQuX3JvdGF0aW9uID0gcm90YXRpb247CiAgICAgICAgcmVzdWx0Ll9zdFJvdGF0aW9uID0gc3RSb3RhdGlvbjsKICAgICAgICByZXN1bHQuX2V4dHJ1ZGVkSGVpZ2h0ID0gZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgcmVzdWx0Ll9zaGFkb3dWb2x1bWUgPSBzaGFkb3dWb2x1bWU7CiAgICAgICAgcmVzdWx0Ll9vZmZzZXRBdHRyaWJ1dGUgPSBvZmZzZXRBdHRyaWJ1dGUgPT09IC0xID8gdm9pZCAwIDogb2Zmc2V0QXR0cmlidXRlOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIFJlY3RhbmdsZUdlb21ldHJ5LmNvbXB1dGVSZWN0YW5nbGUgPSBmdW5jdGlvbihvcHRpb25zLCByZXN1bHQpIHsKICAgICAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICAgICAgY29uc3QgcmVjdGFuZ2xlID0gb3B0aW9ucy5yZWN0YW5nbGU7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJyZWN0YW5nbGUiLCByZWN0YW5nbGUpOwogICAgICAgIFJlY3RhbmdsZV9kZWZhdWx0Ll92YWxpZGF0ZShyZWN0YW5nbGUpOwogICAgICAgIGlmIChyZWN0YW5nbGUubm9ydGggPCByZWN0YW5nbGUuc291dGgpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICAgICAib3B0aW9ucy5yZWN0YW5nbGUubm9ydGggbXVzdCBiZSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gb3B0aW9ucy5yZWN0YW5nbGUuc291dGgiCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IG9wdGlvbnMuZ3JhbnVsYXJpdHkgPz8gTWF0aF9kZWZhdWx0LlJBRElBTlNfUEVSX0RFR1JFRTsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBvcHRpb25zLmVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgICAgIGNvbnN0IHJvdGF0aW9uID0gb3B0aW9ucy5yb3RhdGlvbiA/PyAwOwogICAgICAgIHJldHVybiBjb21wdXRlUmVjdGFuZ2xlMyhyZWN0YW5nbGUsIGdyYW51bGFyaXR5LCByb3RhdGlvbiwgZWxsaXBzb2lkLCByZXN1bHQpOwogICAgICB9OwogICAgICB0YW5nZW50Um90YXRpb25NYXRyaXhTY3JhdGNoID0gbmV3IE1hdHJpeDNfZGVmYXVsdCgpOwogICAgICBxdWF0ZXJuaW9uU2NyYXRjaDQgPSBuZXcgUXVhdGVybmlvbl9kZWZhdWx0KCk7CiAgICAgIGNlbnRlclNjcmF0Y2g0ID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIFJlY3RhbmdsZUdlb21ldHJ5LmNyZWF0ZUdlb21ldHJ5ID0gZnVuY3Rpb24ocmVjdGFuZ2xlR2VvbWV0cnkpIHsKICAgICAgICBpZiAoTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICByZWN0YW5nbGVHZW9tZXRyeS5fcmVjdGFuZ2xlLm5vcnRoLAogICAgICAgICAgcmVjdGFuZ2xlR2VvbWV0cnkuX3JlY3RhbmdsZS5zb3V0aCwKICAgICAgICAgIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTAKICAgICAgICApIHx8IE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgcmVjdGFuZ2xlR2VvbWV0cnkuX3JlY3RhbmdsZS5lYXN0LAogICAgICAgICAgcmVjdGFuZ2xlR2VvbWV0cnkuX3JlY3RhbmdsZS53ZXN0LAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xMAogICAgICAgICkpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGxldCByZWN0YW5nbGUgPSByZWN0YW5nbGVHZW9tZXRyeS5fcmVjdGFuZ2xlOwogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9lbGxpcHNvaWQ7CiAgICAgICAgY29uc3Qgcm90YXRpb24gPSByZWN0YW5nbGVHZW9tZXRyeS5fcm90YXRpb247CiAgICAgICAgY29uc3Qgc3RSb3RhdGlvbiA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9zdFJvdGF0aW9uOwogICAgICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IHJlY3RhbmdsZUdlb21ldHJ5Ll92ZXJ0ZXhGb3JtYXQ7CiAgICAgICAgY29uc3QgY29tcHV0ZWRPcHRpb25zID0gUmVjdGFuZ2xlR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZU9wdGlvbnMoCiAgICAgICAgICByZWN0YW5nbGUsCiAgICAgICAgICByZWN0YW5nbGVHZW9tZXRyeS5fZ3JhbnVsYXJpdHksCiAgICAgICAgICByb3RhdGlvbiwKICAgICAgICAgIHN0Um90YXRpb24sCiAgICAgICAgICByZWN0YW5nbGVTY3JhdGNoLAogICAgICAgICAgbndTY3JhdGNoLAogICAgICAgICAgc3ROd1NjcmF0Y2gKICAgICAgICApOwogICAgICAgIGNvbnN0IHRhbmdlbnRSb3RhdGlvbk1hdHJpeCA9IHRhbmdlbnRSb3RhdGlvbk1hdHJpeFNjcmF0Y2g7CiAgICAgICAgaWYgKHN0Um90YXRpb24gIT09IDAgfHwgcm90YXRpb24gIT09IDApIHsKICAgICAgICAgIGNvbnN0IGNlbnRlciA9IFJlY3RhbmdsZV9kZWZhdWx0LmNlbnRlcihyZWN0YW5nbGUsIGNlbnRlclNjcmF0Y2g0KTsKICAgICAgICAgIGNvbnN0IGF4aXMgPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsQ2FydG9ncmFwaGljKGNlbnRlciwgdjFTY3JhdGNoKTsKICAgICAgICAgIFF1YXRlcm5pb25fZGVmYXVsdC5mcm9tQXhpc0FuZ2xlKGF4aXMsIC1zdFJvdGF0aW9uLCBxdWF0ZXJuaW9uU2NyYXRjaDQpOwogICAgICAgICAgTWF0cml4M19kZWZhdWx0LmZyb21RdWF0ZXJuaW9uKHF1YXRlcm5pb25TY3JhdGNoNCwgdGFuZ2VudFJvdGF0aW9uTWF0cml4KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgTWF0cml4M19kZWZhdWx0LmNsb25lKE1hdHJpeDNfZGVmYXVsdC5JREVOVElUWSwgdGFuZ2VudFJvdGF0aW9uTWF0cml4KTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc3VyZmFjZUhlaWdodCA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9zdXJmYWNlSGVpZ2h0OwogICAgICAgIGNvbnN0IGV4dHJ1ZGVkSGVpZ2h0ID0gcmVjdGFuZ2xlR2VvbWV0cnkuX2V4dHJ1ZGVkSGVpZ2h0OwogICAgICAgIGNvbnN0IGV4dHJ1ZGUgPSAhTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICBzdXJmYWNlSGVpZ2h0LAogICAgICAgICAgZXh0cnVkZWRIZWlnaHQsCiAgICAgICAgICAwLAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04yCiAgICAgICAgKTsKICAgICAgICBjb21wdXRlZE9wdGlvbnMubG9uU2NhbGFyID0gMSAvIHJlY3RhbmdsZUdlb21ldHJ5Ll9yZWN0YW5nbGUud2lkdGg7CiAgICAgICAgY29tcHV0ZWRPcHRpb25zLmxhdFNjYWxhciA9IDEgLyByZWN0YW5nbGVHZW9tZXRyeS5fcmVjdGFuZ2xlLmhlaWdodDsKICAgICAgICBjb21wdXRlZE9wdGlvbnMudGFuZ2VudFJvdGF0aW9uTWF0cml4ID0gdGFuZ2VudFJvdGF0aW9uTWF0cml4OwogICAgICAgIGxldCBnZW9tZXRyeTsKICAgICAgICBsZXQgYm91bmRpbmdTcGhlcmU7CiAgICAgICAgcmVjdGFuZ2xlID0gcmVjdGFuZ2xlR2VvbWV0cnkuX3JlY3RhbmdsZTsKICAgICAgICBpZiAoZXh0cnVkZSkgewogICAgICAgICAgZ2VvbWV0cnkgPSBjb25zdHJ1Y3RFeHRydWRlZFJlY3RhbmdsZShyZWN0YW5nbGVHZW9tZXRyeSwgY29tcHV0ZWRPcHRpb25zKTsKICAgICAgICAgIGNvbnN0IHRvcEJTID0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5mcm9tUmVjdGFuZ2xlM0QoCiAgICAgICAgICAgIHJlY3RhbmdsZSwKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICBzdXJmYWNlSGVpZ2h0LAogICAgICAgICAgICB0b3BCb3VuZGluZ1NwaGVyZTMKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBib3R0b21CUyA9IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbVJlY3RhbmdsZTNEKAogICAgICAgICAgICByZWN0YW5nbGUsCiAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgZXh0cnVkZWRIZWlnaHQsCiAgICAgICAgICAgIGJvdHRvbUJvdW5kaW5nU3BoZXJlMwogICAgICAgICAgKTsKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlID0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC51bmlvbih0b3BCUywgYm90dG9tQlMpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBnZW9tZXRyeSA9IGNvbnN0cnVjdFJlY3RhbmdsZShyZWN0YW5nbGVHZW9tZXRyeSwgY29tcHV0ZWRPcHRpb25zKTsKICAgICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzID0gUG9seWdvblBpcGVsaW5lX2RlZmF1bHQuc2NhbGVUb0dlb2RldGljSGVpZ2h0KAogICAgICAgICAgICBnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcywKICAgICAgICAgICAgc3VyZmFjZUhlaWdodCwKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICBmYWxzZQogICAgICAgICAgKTsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocmVjdGFuZ2xlR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZSkpIHsKICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gZ2VvbWV0cnkuYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMubGVuZ3RoOwogICAgICAgICAgICBjb25zdCBvZmZzZXRWYWx1ZSA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuTk9ORSA/IDAgOiAxOwogICAgICAgICAgICBjb25zdCBhcHBseU9mZnNldCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCAvIDMpLmZpbGwob2Zmc2V0VmFsdWUpOwogICAgICAgICAgICBnZW9tZXRyeS5hdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEUsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMSwKICAgICAgICAgICAgICB2YWx1ZXM6IGFwcGx5T2Zmc2V0CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgYm91bmRpbmdTcGhlcmUgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21SZWN0YW5nbGUzRCgKICAgICAgICAgICAgcmVjdGFuZ2xlLAogICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgIHN1cmZhY2VIZWlnaHQKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGlmICghdmVydGV4Rm9ybWF0LnBvc2l0aW9uKSB7CiAgICAgICAgICBkZWxldGUgZ2VvbWV0cnkuYXR0cmlidXRlcy5wb3NpdGlvbjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBHZW9tZXRyeV9kZWZhdWx0KHsKICAgICAgICAgIGF0dHJpYnV0ZXM6IGdlb21ldHJ5LmF0dHJpYnV0ZXMsCiAgICAgICAgICBpbmRpY2VzOiBnZW9tZXRyeS5pbmRpY2VzLAogICAgICAgICAgcHJpbWl0aXZlVHlwZTogZ2VvbWV0cnkucHJpbWl0aXZlVHlwZSwKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlLAogICAgICAgICAgb2Zmc2V0QXR0cmlidXRlOiByZWN0YW5nbGVHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIFJlY3RhbmdsZUdlb21ldHJ5LmNyZWF0ZVNoYWRvd1ZvbHVtZSA9IGZ1bmN0aW9uKHJlY3RhbmdsZUdlb21ldHJ5LCBtaW5IZWlnaHRGdW5jLCBtYXhIZWlnaHRGdW5jKSB7CiAgICAgICAgY29uc3QgZ3JhbnVsYXJpdHkgPSByZWN0YW5nbGVHZW9tZXRyeS5fZ3JhbnVsYXJpdHk7CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gcmVjdGFuZ2xlR2VvbWV0cnkuX2VsbGlwc29pZDsKICAgICAgICBjb25zdCBtaW5IZWlnaHQgPSBtaW5IZWlnaHRGdW5jKGdyYW51bGFyaXR5LCBlbGxpcHNvaWQpOwogICAgICAgIGNvbnN0IG1heEhlaWdodCA9IG1heEhlaWdodEZ1bmMoZ3JhbnVsYXJpdHksIGVsbGlwc29pZCk7CiAgICAgICAgcmV0dXJuIG5ldyBSZWN0YW5nbGVHZW9tZXRyeSh7CiAgICAgICAgICByZWN0YW5nbGU6IHJlY3RhbmdsZUdlb21ldHJ5Ll9yZWN0YW5nbGUsCiAgICAgICAgICByb3RhdGlvbjogcmVjdGFuZ2xlR2VvbWV0cnkuX3JvdGF0aW9uLAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgc3RSb3RhdGlvbjogcmVjdGFuZ2xlR2VvbWV0cnkuX3N0Um90YXRpb24sCiAgICAgICAgICBncmFudWxhcml0eSwKICAgICAgICAgIGV4dHJ1ZGVkSGVpZ2h0OiBtYXhIZWlnaHQsCiAgICAgICAgICBoZWlnaHQ6IG1pbkhlaWdodCwKICAgICAgICAgIHZlcnRleEZvcm1hdDogVmVydGV4Rm9ybWF0X2RlZmF1bHQuUE9TSVRJT05fT05MWSwKICAgICAgICAgIHNoYWRvd1ZvbHVtZTogdHJ1ZQogICAgICAgIH0pOwogICAgICB9OwogICAgICB1bnJvdGF0ZWRUZXh0dXJlUmVjdGFuZ2xlU2NyYXRjaCA9IG5ldyBSZWN0YW5nbGVfZGVmYXVsdCgpOwogICAgICBwb2ludHMyRFNjcmF0Y2gyID0gW25ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKSwgbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpLCBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCldOwogICAgICByb3RhdGlvbjJEU2NyYXRjaDIgPSBuZXcgTWF0cml4Ml9kZWZhdWx0KCk7CiAgICAgIHJlY3RhbmdsZUNlbnRlclNjcmF0Y2gyID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKFJlY3RhbmdsZUdlb21ldHJ5LnByb3RvdHlwZSwgewogICAgICAgIC8qKgogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgcmVjdGFuZ2xlOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh0aGlzLl9yb3RhdGVkUmVjdGFuZ2xlKSkgewogICAgICAgICAgICAgIHRoaXMuX3JvdGF0ZWRSZWN0YW5nbGUgPSBjb21wdXRlUmVjdGFuZ2xlMygKICAgICAgICAgICAgICAgIHRoaXMuX3JlY3RhbmdsZSwKICAgICAgICAgICAgICAgIHRoaXMuX2dyYW51bGFyaXR5LAogICAgICAgICAgICAgICAgdGhpcy5fcm90YXRpb24sCiAgICAgICAgICAgICAgICB0aGlzLl9lbGxpcHNvaWQKICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB0aGlzLl9yb3RhdGVkUmVjdGFuZ2xlOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogRm9yIHJlbWFwcGluZyB0ZXh0dXJlIGNvb3JkaW5hdGVzIHdoZW4gcmVuZGVyaW5nIFJlY3RhbmdsZUdlb21ldHJpZXMgYXMgR3JvdW5kUHJpbWl0aXZlcy4KICAgICAgICAgKiBUaGlzIHZlcnNpb24gcGVybWl0cyBza2V3IGluIHRleHR1cmVzIGJ5IGNvbXB1dGluZyBvZmZzZXRzIGRpcmVjdGx5IGluIGNhcnRvZ3JhcGhpYyBzcGFjZSBhbmQKICAgICAgICAgKiBtb3JlIGFjY3VyYXRlbHkgYXBwcm94aW1hdGVzIHJlbmRlcmluZyBSZWN0YW5nbGVHZW9tZXRyaWVzIHdpdGggaGVpZ2h0IGFzIHN0YW5kYXJkIFByaW1pdGl2ZXMuCiAgICAgICAgICogQHNlZSBHZW9tZXRyeSNfdGV4dHVyZUNvb3JkaW5hdGVSb3RhdGlvblBvaW50cwogICAgICAgICAqIEBwcml2YXRlCiAgICAgICAgICovCiAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVSb3RhdGlvblBvaW50czogewogICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQodGhpcy5fdGV4dHVyZUNvb3JkaW5hdGVSb3RhdGlvblBvaW50cykpIHsKICAgICAgICAgICAgICB0aGlzLl90ZXh0dXJlQ29vcmRpbmF0ZVJvdGF0aW9uUG9pbnRzID0gdGV4dHVyZUNvb3JkaW5hdGVSb3RhdGlvblBvaW50czModGhpcyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3RleHR1cmVDb29yZGluYXRlUm90YXRpb25Qb2ludHM7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9KTsKICAgICAgUmVjdGFuZ2xlR2VvbWV0cnlfZGVmYXVsdCA9IFJlY3RhbmdsZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlUmVjdGFuZ2xlR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlUmVjdGFuZ2xlR2VvbWV0cnlfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZVJlY3RhbmdsZUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZVJlY3RhbmdsZUdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVSZWN0YW5nbGVHZW9tZXRyeShyZWN0YW5nbGVHZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgcmVjdGFuZ2xlR2VvbWV0cnkgPSBSZWN0YW5nbGVHZW9tZXRyeV9kZWZhdWx0LnVucGFjayhyZWN0YW5nbGVHZW9tZXRyeSwgb2Zmc2V0KTsKICAgIH0KICAgIHJlY3RhbmdsZUdlb21ldHJ5Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShyZWN0YW5nbGVHZW9tZXRyeS5fZWxsaXBzb2lkKTsKICAgIHJlY3RhbmdsZUdlb21ldHJ5Ll9yZWN0YW5nbGUgPSBSZWN0YW5nbGVfZGVmYXVsdC5jbG9uZShyZWN0YW5nbGVHZW9tZXRyeS5fcmVjdGFuZ2xlKTsKICAgIHJldHVybiBSZWN0YW5nbGVHZW9tZXRyeV9kZWZhdWx0LmNyZWF0ZUdlb21ldHJ5KHJlY3RhbmdsZUdlb21ldHJ5KTsKICB9CiAgdmFyIGNyZWF0ZVJlY3RhbmdsZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlUmVjdGFuZ2xlR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVJlY3RhbmdsZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlR2VvbWV0cnkoKTsKICAgICAgY3JlYXRlUmVjdGFuZ2xlR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZVJlY3RhbmdsZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUmVjdGFuZ2xlT3V0bGluZUdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gY29uc3RydWN0UmVjdGFuZ2xlMihnZW9tZXRyeSwgY29tcHV0ZWRPcHRpb25zKSB7CiAgICBjb25zdCBlbGxpcHNvaWQgPSBnZW9tZXRyeS5fZWxsaXBzb2lkOwogICAgY29uc3QgaGVpZ2h0ID0gY29tcHV0ZWRPcHRpb25zLmhlaWdodDsKICAgIGNvbnN0IHdpZHRoID0gY29tcHV0ZWRPcHRpb25zLndpZHRoOwogICAgY29uc3Qgbm9ydGhDYXAgPSBjb21wdXRlZE9wdGlvbnMubm9ydGhDYXA7CiAgICBjb25zdCBzb3V0aENhcCA9IGNvbXB1dGVkT3B0aW9ucy5zb3V0aENhcDsKICAgIGxldCByb3dIZWlnaHQgPSBoZWlnaHQ7CiAgICBsZXQgd2lkdGhNdWx0aXBsaWVyID0gMjsKICAgIGxldCBzaXplID0gMDsKICAgIGxldCBjb3JuZXJzID0gNDsKICAgIGlmIChub3J0aENhcCkgewogICAgICB3aWR0aE11bHRpcGxpZXIgLT0gMTsKICAgICAgcm93SGVpZ2h0IC09IDE7CiAgICAgIHNpemUgKz0gMTsKICAgICAgY29ybmVycyAtPSAyOwogICAgfQogICAgaWYgKHNvdXRoQ2FwKSB7CiAgICAgIHdpZHRoTXVsdGlwbGllciAtPSAxOwogICAgICByb3dIZWlnaHQgLT0gMTsKICAgICAgc2l6ZSArPSAxOwogICAgICBjb3JuZXJzIC09IDI7CiAgICB9CiAgICBzaXplICs9IHdpZHRoTXVsdGlwbGllciAqIHdpZHRoICsgMiAqIHJvd0hlaWdodCAtIGNvcm5lcnM7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KHNpemUgKiAzKTsKICAgIGxldCBwb3NJbmRleCA9IDA7CiAgICBsZXQgcm93ID0gMDsKICAgIGxldCBjb2w7CiAgICBjb25zdCBwb3NpdGlvbiA9IHBvc2l0aW9uU2NyYXRjaDM7CiAgICBpZiAobm9ydGhDYXApIHsKICAgICAgUmVjdGFuZ2xlR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZVBvc2l0aW9uKAogICAgICAgIGNvbXB1dGVkT3B0aW9ucywKICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgZmFsc2UsCiAgICAgICAgcm93LAogICAgICAgIDAsCiAgICAgICAgcG9zaXRpb24KICAgICAgKTsKICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24ueDsKICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24ueTsKICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24uejsKICAgIH0gZWxzZSB7CiAgICAgIGZvciAoY29sID0gMDsgY29sIDwgd2lkdGg7IGNvbCsrKSB7CiAgICAgICAgUmVjdGFuZ2xlR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZVBvc2l0aW9uKAogICAgICAgICAgY29tcHV0ZWRPcHRpb25zLAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgZmFsc2UsCiAgICAgICAgICByb3csCiAgICAgICAgICBjb2wsCiAgICAgICAgICBwb3NpdGlvbgogICAgICAgICk7CiAgICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24ueDsKICAgICAgICBwb3NpdGlvbnNbcG9zSW5kZXgrK10gPSBwb3NpdGlvbi55OwogICAgICAgIHBvc2l0aW9uc1twb3NJbmRleCsrXSA9IHBvc2l0aW9uLno7CiAgICAgIH0KICAgIH0KICAgIGNvbCA9IHdpZHRoIC0gMTsKICAgIGZvciAocm93ID0gMTsgcm93IDwgaGVpZ2h0OyByb3crKykgewogICAgICBSZWN0YW5nbGVHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlUG9zaXRpb24oCiAgICAgICAgY29tcHV0ZWRPcHRpb25zLAogICAgICAgIGVsbGlwc29pZCwKICAgICAgICBmYWxzZSwKICAgICAgICByb3csCiAgICAgICAgY29sLAogICAgICAgIHBvc2l0aW9uCiAgICAgICk7CiAgICAgIHBvc2l0aW9uc1twb3NJbmRleCsrXSA9IHBvc2l0aW9uLng7CiAgICAgIHBvc2l0aW9uc1twb3NJbmRleCsrXSA9IHBvc2l0aW9uLnk7CiAgICAgIHBvc2l0aW9uc1twb3NJbmRleCsrXSA9IHBvc2l0aW9uLno7CiAgICB9CiAgICByb3cgPSBoZWlnaHQgLSAxOwogICAgaWYgKCFzb3V0aENhcCkgewogICAgICBmb3IgKGNvbCA9IHdpZHRoIC0gMjsgY29sID49IDA7IGNvbC0tKSB7CiAgICAgICAgUmVjdGFuZ2xlR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZVBvc2l0aW9uKAogICAgICAgICAgY29tcHV0ZWRPcHRpb25zLAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgZmFsc2UsCiAgICAgICAgICByb3csCiAgICAgICAgICBjb2wsCiAgICAgICAgICBwb3NpdGlvbgogICAgICAgICk7CiAgICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24ueDsKICAgICAgICBwb3NpdGlvbnNbcG9zSW5kZXgrK10gPSBwb3NpdGlvbi55OwogICAgICAgIHBvc2l0aW9uc1twb3NJbmRleCsrXSA9IHBvc2l0aW9uLno7CiAgICAgIH0KICAgIH0KICAgIGNvbCA9IDA7CiAgICBmb3IgKHJvdyA9IGhlaWdodCAtIDI7IHJvdyA+IDA7IHJvdy0tKSB7CiAgICAgIFJlY3RhbmdsZUdlb21ldHJ5TGlicmFyeV9kZWZhdWx0LmNvbXB1dGVQb3NpdGlvbigKICAgICAgICBjb21wdXRlZE9wdGlvbnMsCiAgICAgICAgZWxsaXBzb2lkLAogICAgICAgIGZhbHNlLAogICAgICAgIHJvdywKICAgICAgICBjb2wsCiAgICAgICAgcG9zaXRpb24KICAgICAgKTsKICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24ueDsKICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24ueTsKICAgICAgcG9zaXRpb25zW3Bvc0luZGV4KytdID0gcG9zaXRpb24uejsKICAgIH0KICAgIGNvbnN0IGluZGljZXNTaXplID0gcG9zaXRpb25zLmxlbmd0aCAvIDMgKiAyOwogICAgY29uc3QgaW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KAogICAgICBwb3NpdGlvbnMubGVuZ3RoIC8gMywKICAgICAgaW5kaWNlc1NpemUKICAgICk7CiAgICBsZXQgaW5kZXggPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoIC8gMyAtIDE7IGkrKykgewogICAgICBpbmRpY2VzW2luZGV4KytdID0gaTsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGkgKyAxOwogICAgfQogICAgaW5kaWNlc1tpbmRleCsrXSA9IHBvc2l0aW9ucy5sZW5ndGggLyAzIC0gMTsKICAgIGluZGljZXNbaW5kZXgrK10gPSAwOwogICAgY29uc3QgZ2VvID0gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICBhdHRyaWJ1dGVzOiBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoKSwKICAgICAgcHJpbWl0aXZlVHlwZTogUHJpbWl0aXZlVHlwZV9kZWZhdWx0LkxJTkVTCiAgICB9KTsKICAgIGdlby5hdHRyaWJ1dGVzLnBvc2l0aW9uID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgIHZhbHVlczogcG9zaXRpb25zCiAgICB9KTsKICAgIGdlby5pbmRpY2VzID0gaW5kaWNlczsKICAgIHJldHVybiBnZW87CiAgfQogIGZ1bmN0aW9uIGNvbnN0cnVjdEV4dHJ1ZGVkUmVjdGFuZ2xlMihyZWN0YW5nbGVHZW9tZXRyeSwgY29tcHV0ZWRPcHRpb25zKSB7CiAgICBjb25zdCBtYXhIZWlnaHQgPSByZWN0YW5nbGVHZW9tZXRyeS5fc3VyZmFjZUhlaWdodDsKICAgIGNvbnN0IG1pbkhlaWdodCA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9leHRydWRlZEhlaWdodDsKICAgIGNvbnN0IGVsbGlwc29pZCA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9lbGxpcHNvaWQ7CiAgICBjb25zdCBnZW8gPSBjb25zdHJ1Y3RSZWN0YW5nbGUyKHJlY3RhbmdsZUdlb21ldHJ5LCBjb21wdXRlZE9wdGlvbnMpOwogICAgY29uc3QgaGVpZ2h0ID0gY29tcHV0ZWRPcHRpb25zLmhlaWdodDsKICAgIGNvbnN0IHdpZHRoID0gY29tcHV0ZWRPcHRpb25zLndpZHRoOwogICAgY29uc3QgdG9wUG9zaXRpb25zID0gUG9seWdvblBpcGVsaW5lX2RlZmF1bHQuc2NhbGVUb0dlb2RldGljSGVpZ2h0KAogICAgICBnZW8uYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMsCiAgICAgIG1heEhlaWdodCwKICAgICAgZWxsaXBzb2lkLAogICAgICBmYWxzZQogICAgKTsKICAgIGxldCBsZW5ndGggPSB0b3BQb3NpdGlvbnMubGVuZ3RoOwogICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShsZW5ndGggKiAyKTsKICAgIHBvc2l0aW9ucy5zZXQodG9wUG9zaXRpb25zKTsKICAgIGNvbnN0IGJvdHRvbVBvc2l0aW9ucyA9IFBvbHlnb25QaXBlbGluZV9kZWZhdWx0LnNjYWxlVG9HZW9kZXRpY0hlaWdodCgKICAgICAgZ2VvLmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLAogICAgICBtaW5IZWlnaHQsCiAgICAgIGVsbGlwc29pZAogICAgKTsKICAgIHBvc2l0aW9ucy5zZXQoYm90dG9tUG9zaXRpb25zLCBsZW5ndGgpOwogICAgZ2VvLmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzID0gcG9zaXRpb25zOwogICAgY29uc3Qgbm9ydGhDYXAgPSBjb21wdXRlZE9wdGlvbnMubm9ydGhDYXA7CiAgICBjb25zdCBzb3V0aENhcCA9IGNvbXB1dGVkT3B0aW9ucy5zb3V0aENhcDsKICAgIGxldCBjb3JuZXJzID0gNDsKICAgIGlmIChub3J0aENhcCkgewogICAgICBjb3JuZXJzIC09IDE7CiAgICB9CiAgICBpZiAoc291dGhDYXApIHsKICAgICAgY29ybmVycyAtPSAxOwogICAgfQogICAgY29uc3QgaW5kaWNlc1NpemUgPSAocG9zaXRpb25zLmxlbmd0aCAvIDMgKyBjb3JuZXJzKSAqIDI7CiAgICBjb25zdCBpbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgIHBvc2l0aW9ucy5sZW5ndGggLyAzLAogICAgICBpbmRpY2VzU2l6ZQogICAgKTsKICAgIGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGggLyA2OwogICAgbGV0IGluZGV4ID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoIC0gMTsgaSsrKSB7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gaSArIDE7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSBpICsgbGVuZ3RoOwogICAgICBpbmRpY2VzW2luZGV4KytdID0gaSArIGxlbmd0aCArIDE7CiAgICB9CiAgICBpbmRpY2VzW2luZGV4KytdID0gbGVuZ3RoIC0gMTsKICAgIGluZGljZXNbaW5kZXgrK10gPSAwOwogICAgaW5kaWNlc1tpbmRleCsrXSA9IGxlbmd0aCArIGxlbmd0aCAtIDE7CiAgICBpbmRpY2VzW2luZGV4KytdID0gbGVuZ3RoOwogICAgaW5kaWNlc1tpbmRleCsrXSA9IDA7CiAgICBpbmRpY2VzW2luZGV4KytdID0gbGVuZ3RoOwogICAgbGV0IGJvdHRvbUNvcm5lcjsKICAgIGlmIChub3J0aENhcCkgewogICAgICBib3R0b21Db3JuZXIgPSBoZWlnaHQgLSAxOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgdG9wUmlnaHRDb3JuZXIgPSB3aWR0aCAtIDE7CiAgICAgIGluZGljZXNbaW5kZXgrK10gPSB0b3BSaWdodENvcm5lcjsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IHRvcFJpZ2h0Q29ybmVyICsgbGVuZ3RoOwogICAgICBib3R0b21Db3JuZXIgPSB3aWR0aCArIGhlaWdodCAtIDI7CiAgICB9CiAgICBpbmRpY2VzW2luZGV4KytdID0gYm90dG9tQ29ybmVyOwogICAgaW5kaWNlc1tpbmRleCsrXSA9IGJvdHRvbUNvcm5lciArIGxlbmd0aDsKICAgIGlmICghc291dGhDYXApIHsKICAgICAgY29uc3QgYm90dG9tTGVmdENvcm5lciA9IHdpZHRoICsgYm90dG9tQ29ybmVyIC0gMTsKICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGJvdHRvbUxlZnRDb3JuZXI7CiAgICAgIGluZGljZXNbaW5kZXhdID0gYm90dG9tTGVmdENvcm5lciArIGxlbmd0aDsKICAgIH0KICAgIGdlby5pbmRpY2VzID0gaW5kaWNlczsKICAgIHJldHVybiBnZW87CiAgfQogIGZ1bmN0aW9uIFJlY3RhbmdsZU91dGxpbmVHZW9tZXRyeShvcHRpb25zKSB7CiAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICBjb25zdCByZWN0YW5nbGUgPSBvcHRpb25zLnJlY3RhbmdsZTsKICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gb3B0aW9ucy5ncmFudWxhcml0eSA/PyBNYXRoX2RlZmF1bHQuUkFESUFOU19QRVJfREVHUkVFOwogICAgY29uc3QgZWxsaXBzb2lkID0gb3B0aW9ucy5lbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgIGNvbnN0IHJvdGF0aW9uID0gb3B0aW9ucy5yb3RhdGlvbiA/PyAwOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVjdGFuZ2xlKSkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgicmVjdGFuZ2xlIGlzIHJlcXVpcmVkLiIpOwogICAgfQogICAgUmVjdGFuZ2xlX2RlZmF1bHQuX3ZhbGlkYXRlKHJlY3RhbmdsZSk7CiAgICBpZiAocmVjdGFuZ2xlLm5vcnRoIDwgcmVjdGFuZ2xlLnNvdXRoKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICJvcHRpb25zLnJlY3RhbmdsZS5ub3J0aCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiBvcHRpb25zLnJlY3RhbmdsZS5zb3V0aCIKICAgICAgKTsKICAgIH0KICAgIGNvbnN0IGhlaWdodCA9IG9wdGlvbnMuaGVpZ2h0ID8/IDA7CiAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IG9wdGlvbnMuZXh0cnVkZWRIZWlnaHQgPz8gaGVpZ2h0OwogICAgdGhpcy5fcmVjdGFuZ2xlID0gUmVjdGFuZ2xlX2RlZmF1bHQuY2xvbmUocmVjdGFuZ2xlKTsKICAgIHRoaXMuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICB0aGlzLl9lbGxpcHNvaWQgPSBlbGxpcHNvaWQ7CiAgICB0aGlzLl9zdXJmYWNlSGVpZ2h0ID0gTWF0aC5tYXgoaGVpZ2h0LCBleHRydWRlZEhlaWdodCk7CiAgICB0aGlzLl9yb3RhdGlvbiA9IHJvdGF0aW9uOwogICAgdGhpcy5fZXh0cnVkZWRIZWlnaHQgPSBNYXRoLm1pbihoZWlnaHQsIGV4dHJ1ZGVkSGVpZ2h0KTsKICAgIHRoaXMuX29mZnNldEF0dHJpYnV0ZSA9IG9wdGlvbnMub2Zmc2V0QXR0cmlidXRlOwogICAgdGhpcy5fd29ya2VyTmFtZSA9ICJjcmVhdGVSZWN0YW5nbGVPdXRsaW5lR2VvbWV0cnkiOwogIH0KICB2YXIgYm90dG9tQm91bmRpbmdTcGhlcmU0LCB0b3BCb3VuZGluZ1NwaGVyZTQsIHBvc2l0aW9uU2NyYXRjaDMsIHJlY3RhbmdsZVNjcmF0Y2gyLCBzY3JhdGNoUmVjdGFuZ2xlMiwgc2NyYXRjaEVsbGlwc29pZDEyLCBzY3JhdGNoT3B0aW9uczIwLCBud1NjcmF0Y2gyLCBSZWN0YW5nbGVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9SZWN0YW5nbGVPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1JlY3RhbmdsZU91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfQ29tcG9uZW50RGF0YXR5cGUoKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9HZW9tZXRyeSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGVzKCk7CiAgICAgIGluaXRfR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1BvbHlnb25QaXBlbGluZSgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgaW5pdF9SZWN0YW5nbGUoKTsKICAgICAgaW5pdF9SZWN0YW5nbGVHZW9tZXRyeUxpYnJhcnkoKTsKICAgICAgYm90dG9tQm91bmRpbmdTcGhlcmU0ID0gbmV3IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQoKTsKICAgICAgdG9wQm91bmRpbmdTcGhlcmU0ID0gbmV3IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQoKTsKICAgICAgcG9zaXRpb25TY3JhdGNoMyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgcmVjdGFuZ2xlU2NyYXRjaDIgPSBuZXcgUmVjdGFuZ2xlX2RlZmF1bHQoKTsKICAgICAgUmVjdGFuZ2xlT3V0bGluZUdlb21ldHJ5LnBhY2tlZExlbmd0aCA9IFJlY3RhbmdsZV9kZWZhdWx0LnBhY2tlZExlbmd0aCArIEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIDU7CiAgICAgIFJlY3RhbmdsZU91dGxpbmVHZW9tZXRyeS5wYWNrID0gZnVuY3Rpb24odmFsdWUsIGFycmF5LCBzdGFydGluZ0luZGV4KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQodmFsdWUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgidmFsdWUgaXMgcmVxdWlyZWQiKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYXJyYXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYXJyYXkgaXMgcmVxdWlyZWQiKTsKICAgICAgICB9CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBSZWN0YW5nbGVfZGVmYXVsdC5wYWNrKHZhbHVlLl9yZWN0YW5nbGUsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFJlY3RhbmdsZV9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrKHZhbHVlLl9lbGxpcHNvaWQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2dyYW51bGFyaXR5OwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fc3VyZmFjZUhlaWdodDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX3JvdGF0aW9uOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fZXh0cnVkZWRIZWlnaHQ7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleF0gPSB2YWx1ZS5fb2Zmc2V0QXR0cmlidXRlID8/IC0xOwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgc2NyYXRjaFJlY3RhbmdsZTIgPSBuZXcgUmVjdGFuZ2xlX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEVsbGlwc29pZDEyID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoRWxsaXBzb2lkX2RlZmF1bHQuVU5JVF9TUEhFUkUpOwogICAgICBzY3JhdGNoT3B0aW9uczIwID0gewogICAgICAgIHJlY3RhbmdsZTogc2NyYXRjaFJlY3RhbmdsZTIsCiAgICAgICAgZWxsaXBzb2lkOiBzY3JhdGNoRWxsaXBzb2lkMTIsCiAgICAgICAgZ3JhbnVsYXJpdHk6IHZvaWQgMCwKICAgICAgICBoZWlnaHQ6IHZvaWQgMCwKICAgICAgICByb3RhdGlvbjogdm9pZCAwLAogICAgICAgIGV4dHJ1ZGVkSGVpZ2h0OiB2b2lkIDAsCiAgICAgICAgb2Zmc2V0QXR0cmlidXRlOiB2b2lkIDAKICAgICAgfTsKICAgICAgUmVjdGFuZ2xlT3V0bGluZUdlb21ldHJ5LnVucGFjayA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydGluZ0luZGV4LCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhcnJheSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhcnJheSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGNvbnN0IHJlY3RhbmdsZSA9IFJlY3RhbmdsZV9kZWZhdWx0LnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCwgc2NyYXRjaFJlY3RhbmdsZTIpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gUmVjdGFuZ2xlX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCwgc2NyYXRjaEVsbGlwc29pZDEyKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgaGVpZ2h0ID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCByb3RhdGlvbiA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgZXh0cnVkZWRIZWlnaHQgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IG9mZnNldEF0dHJpYnV0ZSA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMjAuZ3JhbnVsYXJpdHkgPSBncmFudWxhcml0eTsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMjAuaGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMyMC5yb3RhdGlvbiA9IHJvdGF0aW9uOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMyMC5leHRydWRlZEhlaWdodCA9IGV4dHJ1ZGVkSGVpZ2h0OwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMyMC5vZmZzZXRBdHRyaWJ1dGUgPSBvZmZzZXRBdHRyaWJ1dGUgPT09IC0xID8gdm9pZCAwIDogb2Zmc2V0QXR0cmlidXRlOwogICAgICAgICAgcmV0dXJuIG5ldyBSZWN0YW5nbGVPdXRsaW5lR2VvbWV0cnkoc2NyYXRjaE9wdGlvbnMyMCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5fcmVjdGFuZ2xlID0gUmVjdGFuZ2xlX2RlZmF1bHQuY2xvbmUocmVjdGFuZ2xlLCByZXN1bHQuX3JlY3RhbmdsZSk7CiAgICAgICAgcmVzdWx0Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShlbGxpcHNvaWQsIHJlc3VsdC5fZWxsaXBzb2lkKTsKICAgICAgICByZXN1bHQuX3N1cmZhY2VIZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgcmVzdWx0Ll9yb3RhdGlvbiA9IHJvdGF0aW9uOwogICAgICAgIHJlc3VsdC5fZXh0cnVkZWRIZWlnaHQgPSBleHRydWRlZEhlaWdodDsKICAgICAgICByZXN1bHQuX29mZnNldEF0dHJpYnV0ZSA9IG9mZnNldEF0dHJpYnV0ZSA9PT0gLTEgPyB2b2lkIDAgOiBvZmZzZXRBdHRyaWJ1dGU7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgbndTY3JhdGNoMiA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBSZWN0YW5nbGVPdXRsaW5lR2VvbWV0cnkuY3JlYXRlR2VvbWV0cnkgPSBmdW5jdGlvbihyZWN0YW5nbGVHZW9tZXRyeSkgewogICAgICAgIGNvbnN0IHJlY3RhbmdsZSA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9yZWN0YW5nbGU7CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gcmVjdGFuZ2xlR2VvbWV0cnkuX2VsbGlwc29pZDsKICAgICAgICBjb25zdCBjb21wdXRlZE9wdGlvbnMgPSBSZWN0YW5nbGVHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdC5jb21wdXRlT3B0aW9ucygKICAgICAgICAgIHJlY3RhbmdsZSwKICAgICAgICAgIHJlY3RhbmdsZUdlb21ldHJ5Ll9ncmFudWxhcml0eSwKICAgICAgICAgIHJlY3RhbmdsZUdlb21ldHJ5Ll9yb3RhdGlvbiwKICAgICAgICAgIDAsCiAgICAgICAgICByZWN0YW5nbGVTY3JhdGNoMiwKICAgICAgICAgIG53U2NyYXRjaDIKICAgICAgICApOwogICAgICAgIGxldCBnZW9tZXRyeTsKICAgICAgICBsZXQgYm91bmRpbmdTcGhlcmU7CiAgICAgICAgaWYgKE1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgcmVjdGFuZ2xlLm5vcnRoLAogICAgICAgICAgcmVjdGFuZ2xlLnNvdXRoLAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xMAogICAgICAgICkgfHwgTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oCiAgICAgICAgICByZWN0YW5nbGUuZWFzdCwKICAgICAgICAgIHJlY3RhbmdsZS53ZXN0LAogICAgICAgICAgTWF0aF9kZWZhdWx0LkVQU0lMT04xMAogICAgICAgICkpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHN1cmZhY2VIZWlnaHQgPSByZWN0YW5nbGVHZW9tZXRyeS5fc3VyZmFjZUhlaWdodDsKICAgICAgICBjb25zdCBleHRydWRlZEhlaWdodCA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9leHRydWRlZEhlaWdodDsKICAgICAgICBjb25zdCBleHRydWRlID0gIU1hdGhfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKAogICAgICAgICAgc3VyZmFjZUhlaWdodCwKICAgICAgICAgIGV4dHJ1ZGVkSGVpZ2h0LAogICAgICAgICAgMCwKICAgICAgICAgIE1hdGhfZGVmYXVsdC5FUFNJTE9OMgogICAgICAgICk7CiAgICAgICAgbGV0IG9mZnNldFZhbHVlOwogICAgICAgIGlmIChleHRydWRlKSB7CiAgICAgICAgICBnZW9tZXRyeSA9IGNvbnN0cnVjdEV4dHJ1ZGVkUmVjdGFuZ2xlMihyZWN0YW5nbGVHZW9tZXRyeSwgY29tcHV0ZWRPcHRpb25zKTsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocmVjdGFuZ2xlR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZSkpIHsKICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IGdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzLmxlbmd0aCAvIDM7CiAgICAgICAgICAgIGxldCBvZmZzZXRBdHRyaWJ1dGUgPSBuZXcgVWludDhBcnJheShzaXplKTsKICAgICAgICAgICAgaWYgKHJlY3RhbmdsZUdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuVE9QKSB7CiAgICAgICAgICAgICAgb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlLmZpbGwoMSwgMCwgc2l6ZSAvIDIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIG9mZnNldFZhbHVlID0gcmVjdGFuZ2xlR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZSA9PT0gR2VvbWV0cnlPZmZzZXRBdHRyaWJ1dGVfZGVmYXVsdC5OT05FID8gMCA6IDE7CiAgICAgICAgICAgICAgb2Zmc2V0QXR0cmlidXRlID0gb2Zmc2V0QXR0cmlidXRlLmZpbGwob2Zmc2V0VmFsdWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMuYXBwbHlPZmZzZXQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuVU5TSUdORURfQllURSwKICAgICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAxLAogICAgICAgICAgICAgIHZhbHVlczogb2Zmc2V0QXR0cmlidXRlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgdG9wQlMgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21SZWN0YW5nbGUzRCgKICAgICAgICAgICAgcmVjdGFuZ2xlLAogICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgIHN1cmZhY2VIZWlnaHQsCiAgICAgICAgICAgIHRvcEJvdW5kaW5nU3BoZXJlNAogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IGJvdHRvbUJTID0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5mcm9tUmVjdGFuZ2xlM0QoCiAgICAgICAgICAgIHJlY3RhbmdsZSwKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICBleHRydWRlZEhlaWdodCwKICAgICAgICAgICAgYm90dG9tQm91bmRpbmdTcGhlcmU0CiAgICAgICAgICApOwogICAgICAgICAgYm91bmRpbmdTcGhlcmUgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LnVuaW9uKHRvcEJTLCBib3R0b21CUyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGdlb21ldHJ5ID0gY29uc3RydWN0UmVjdGFuZ2xlMihyZWN0YW5nbGVHZW9tZXRyeSwgY29tcHV0ZWRPcHRpb25zKTsKICAgICAgICAgIGdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzID0gUG9seWdvblBpcGVsaW5lX2RlZmF1bHQuc2NhbGVUb0dlb2RldGljSGVpZ2h0KAogICAgICAgICAgICBnZW9tZXRyeS5hdHRyaWJ1dGVzLnBvc2l0aW9uLnZhbHVlcywKICAgICAgICAgICAgc3VyZmFjZUhlaWdodCwKICAgICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgICBmYWxzZQogICAgICAgICAgKTsKICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocmVjdGFuZ2xlR2VvbWV0cnkuX29mZnNldEF0dHJpYnV0ZSkpIHsKICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gZ2VvbWV0cnkuYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXMubGVuZ3RoOwogICAgICAgICAgICBvZmZzZXRWYWx1ZSA9IHJlY3RhbmdsZUdlb21ldHJ5Ll9vZmZzZXRBdHRyaWJ1dGUgPT09IEdlb21ldHJ5T2Zmc2V0QXR0cmlidXRlX2RlZmF1bHQuTk9ORSA/IDAgOiAxOwogICAgICAgICAgICBjb25zdCBhcHBseU9mZnNldCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCAvIDMpLmZpbGwob2Zmc2V0VmFsdWUpOwogICAgICAgICAgICBnZW9tZXRyeS5hdHRyaWJ1dGVzLmFwcGx5T2Zmc2V0ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEUsCiAgICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMSwKICAgICAgICAgICAgICB2YWx1ZXM6IGFwcGx5T2Zmc2V0CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgYm91bmRpbmdTcGhlcmUgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21SZWN0YW5nbGUzRCgKICAgICAgICAgICAgcmVjdGFuZ2xlLAogICAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAgIHN1cmZhY2VIZWlnaHQKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgICAgICBhdHRyaWJ1dGVzOiBnZW9tZXRyeS5hdHRyaWJ1dGVzLAogICAgICAgICAgaW5kaWNlczogZ2VvbWV0cnkuaW5kaWNlcywKICAgICAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5MSU5FUywKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlLAogICAgICAgICAgb2Zmc2V0QXR0cmlidXRlOiByZWN0YW5nbGVHZW9tZXRyeS5fb2Zmc2V0QXR0cmlidXRlCiAgICAgICAgfSk7CiAgICAgIH07CiAgICAgIFJlY3RhbmdsZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gUmVjdGFuZ2xlT3V0bGluZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlUmVjdGFuZ2xlT3V0bGluZUdlb21ldHJ5LmpzCiAgdmFyIGNyZWF0ZVJlY3RhbmdsZU91dGxpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlUmVjdGFuZ2xlT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZVJlY3RhbmdsZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gY3JlYXRlUmVjdGFuZ2xlT3V0bGluZUdlb21ldHJ5KHJlY3RhbmdsZUdlb21ldHJ5LCBvZmZzZXQpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob2Zmc2V0KSkgewogICAgICByZWN0YW5nbGVHZW9tZXRyeSA9IFJlY3RhbmdsZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjaygKICAgICAgICByZWN0YW5nbGVHZW9tZXRyeSwKICAgICAgICBvZmZzZXQKICAgICAgKTsKICAgIH0KICAgIHJlY3RhbmdsZUdlb21ldHJ5Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShyZWN0YW5nbGVHZW9tZXRyeS5fZWxsaXBzb2lkKTsKICAgIHJlY3RhbmdsZUdlb21ldHJ5Ll9yZWN0YW5nbGUgPSBSZWN0YW5nbGVfZGVmYXVsdC5jbG9uZShyZWN0YW5nbGVHZW9tZXRyeS5fcmVjdGFuZ2xlKTsKICAgIHJldHVybiBSZWN0YW5nbGVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeShyZWN0YW5nbGVHZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVSZWN0YW5nbGVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVSZWN0YW5nbGVPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVJlY3RhbmdsZU91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X1JlY3RhbmdsZSgpOwogICAgICBpbml0X1JlY3RhbmdsZU91dGxpbmVHZW9tZXRyeSgpOwogICAgICBjcmVhdGVSZWN0YW5nbGVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZVJlY3RhbmdsZU91dGxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1NpbXBsZVBvbHlsaW5lR2VvbWV0cnkuanMKICBmdW5jdGlvbiBpbnRlcnBvbGF0ZUNvbG9yczIocDAsIHAxLCBjb2xvcjAsIGNvbG9yMSwgbWluRGlzdGFuY2UsIGFycmF5LCBvZmZzZXQpIHsKICAgIGNvbnN0IG51bVBvaW50cyA9IFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdC5udW1iZXJPZlBvaW50cyhwMCwgcDEsIG1pbkRpc3RhbmNlKTsKICAgIGxldCBpOwogICAgY29uc3QgcjAgPSBjb2xvcjAucmVkOwogICAgY29uc3QgZzAgPSBjb2xvcjAuZ3JlZW47CiAgICBjb25zdCBiMCA9IGNvbG9yMC5ibHVlOwogICAgY29uc3QgYTAgPSBjb2xvcjAuYWxwaGE7CiAgICBjb25zdCByMSA9IGNvbG9yMS5yZWQ7CiAgICBjb25zdCBnMSA9IGNvbG9yMS5ncmVlbjsKICAgIGNvbnN0IGIxID0gY29sb3IxLmJsdWU7CiAgICBjb25zdCBhMSA9IGNvbG9yMS5hbHBoYTsKICAgIGlmIChDb2xvcl9kZWZhdWx0LmVxdWFscyhjb2xvcjAsIGNvbG9yMSkpIHsKICAgICAgZm9yIChpID0gMDsgaSA8IG51bVBvaW50czsgaSsrKSB7CiAgICAgICAgYXJyYXlbb2Zmc2V0KytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShyMCk7CiAgICAgICAgYXJyYXlbb2Zmc2V0KytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShnMCk7CiAgICAgICAgYXJyYXlbb2Zmc2V0KytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShiMCk7CiAgICAgICAgYXJyYXlbb2Zmc2V0KytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShhMCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG9mZnNldDsKICAgIH0KICAgIGNvbnN0IHJlZFBlclZlcnRleCA9IChyMSAtIHIwKSAvIG51bVBvaW50czsKICAgIGNvbnN0IGdyZWVuUGVyVmVydGV4ID0gKGcxIC0gZzApIC8gbnVtUG9pbnRzOwogICAgY29uc3QgYmx1ZVBlclZlcnRleCA9IChiMSAtIGIwKSAvIG51bVBvaW50czsKICAgIGNvbnN0IGFscGhhUGVyVmVydGV4ID0gKGExIC0gYTApIC8gbnVtUG9pbnRzOwogICAgbGV0IGluZGV4ID0gb2Zmc2V0OwogICAgZm9yIChpID0gMDsgaSA8IG51bVBvaW50czsgaSsrKSB7CiAgICAgIGFycmF5W2luZGV4KytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShyMCArIGkgKiByZWRQZXJWZXJ0ZXgpOwogICAgICBhcnJheVtpbmRleCsrXSA9IENvbG9yX2RlZmF1bHQuZmxvYXRUb0J5dGUoZzAgKyBpICogZ3JlZW5QZXJWZXJ0ZXgpOwogICAgICBhcnJheVtpbmRleCsrXSA9IENvbG9yX2RlZmF1bHQuZmxvYXRUb0J5dGUoYjAgKyBpICogYmx1ZVBlclZlcnRleCk7CiAgICAgIGFycmF5W2luZGV4KytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShhMCArIGkgKiBhbHBoYVBlclZlcnRleCk7CiAgICB9CiAgICByZXR1cm4gaW5kZXg7CiAgfQogIGZ1bmN0aW9uIFNpbXBsZVBvbHlsaW5lR2VvbWV0cnkob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgY29uc3QgcG9zaXRpb25zID0gb3B0aW9ucy5wb3NpdGlvbnM7CiAgICBjb25zdCBjb2xvcnMgPSBvcHRpb25zLmNvbG9yczsKICAgIGNvbnN0IGNvbG9yc1BlclZlcnRleCA9IG9wdGlvbnMuY29sb3JzUGVyVmVydGV4ID8/IGZhbHNlOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocG9zaXRpb25zKSB8fCBwb3NpdGlvbnMubGVuZ3RoIDwgMikgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiQXQgbGVhc3QgdHdvIHBvc2l0aW9ucyBhcmUgcmVxdWlyZWQuIik7CiAgICB9CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGNvbG9ycykgJiYgKGNvbG9yc1BlclZlcnRleCAmJiBjb2xvcnMubGVuZ3RoIDwgcG9zaXRpb25zLmxlbmd0aCB8fCAhY29sb3JzUGVyVmVydGV4ICYmIGNvbG9ycy5sZW5ndGggPCBwb3NpdGlvbnMubGVuZ3RoIC0gMSkpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImNvbG9ycyBoYXMgYW4gaW52YWxpZCBsZW5ndGguIik7CiAgICB9CiAgICB0aGlzLl9wb3NpdGlvbnMgPSBwb3NpdGlvbnM7CiAgICB0aGlzLl9jb2xvcnMgPSBjb2xvcnM7CiAgICB0aGlzLl9jb2xvcnNQZXJWZXJ0ZXggPSBjb2xvcnNQZXJWZXJ0ZXg7CiAgICB0aGlzLl9hcmNUeXBlID0gb3B0aW9ucy5hcmNUeXBlID8/IEFyY1R5cGVfZGVmYXVsdC5HRU9ERVNJQzsKICAgIHRoaXMuX2dyYW51bGFyaXR5ID0gb3B0aW9ucy5ncmFudWxhcml0eSA/PyBNYXRoX2RlZmF1bHQuUkFESUFOU19QRVJfREVHUkVFOwogICAgdGhpcy5fZWxsaXBzb2lkID0gb3B0aW9ucy5lbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgIHRoaXMuX3dvcmtlck5hbWUgPSAiY3JlYXRlU2ltcGxlUG9seWxpbmVHZW9tZXRyeSI7CiAgICBsZXQgbnVtQ29tcG9uZW50cyA9IDEgKyBwb3NpdGlvbnMubGVuZ3RoICogQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgIG51bUNvbXBvbmVudHMgKz0gZGVmaW5lZF9kZWZhdWx0KGNvbG9ycykgPyAxICsgY29sb3JzLmxlbmd0aCAqIENvbG9yX2RlZmF1bHQucGFja2VkTGVuZ3RoIDogMTsKICAgIHRoaXMucGFja2VkTGVuZ3RoID0gbnVtQ29tcG9uZW50cyArIEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIDM7CiAgfQogIHZhciBzY3JhdGNoQXJyYXkxLCBzY3JhdGNoQXJyYXkyLCBnZW5lcmF0ZUFyY09wdGlvbnNTY3JhdGNoLCBTaW1wbGVQb2x5bGluZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfU2ltcGxlUG9seWxpbmVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvU2ltcGxlUG9seWxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfQXJjVHlwZSgpOwogICAgICBpbml0X0JvdW5kaW5nU3BoZXJlKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NvbG9yKCk7CiAgICAgIGluaXRfQ29tcG9uZW50RGF0YXR5cGUoKTsKICAgICAgaW5pdF9Gcm96ZW4oKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9HZW9tZXRyeSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlKCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGVzKCk7CiAgICAgIGluaXRfSW5kZXhEYXRhdHlwZSgpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9Qb2x5bGluZVBpcGVsaW5lKCk7CiAgICAgIGluaXRfUHJpbWl0aXZlVHlwZSgpOwogICAgICBTaW1wbGVQb2x5bGluZUdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh2YWx1ZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ2YWx1ZSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhcnJheSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhcnJheSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGxldCBpOwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IHZhbHVlLl9wb3NpdGlvbnM7CiAgICAgICAgbGV0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IGxlbmd0aDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2ksIHN0YXJ0aW5nSW5kZXggKz0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCkgewogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2socG9zaXRpb25zW2ldLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGNvbG9ycyA9IHZhbHVlLl9jb2xvcnM7CiAgICAgICAgbGVuZ3RoID0gZGVmaW5lZF9kZWZhdWx0KGNvbG9ycykgPyBjb2xvcnMubGVuZ3RoIDogMDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gbGVuZ3RoOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSwgc3RhcnRpbmdJbmRleCArPSBDb2xvcl9kZWZhdWx0LnBhY2tlZExlbmd0aCkgewogICAgICAgICAgQ29sb3JfZGVmYXVsdC5wYWNrKGNvbG9yc1tpXSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIH0KICAgICAgICBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrKHZhbHVlLl9lbGxpcHNvaWQsIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gdmFsdWUuX2NvbG9yc1BlclZlcnRleCA/IDEgOiAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSB2YWx1ZS5fYXJjVHlwZTsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4XSA9IHZhbHVlLl9ncmFudWxhcml0eTsKICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgIH07CiAgICAgIFNpbXBsZVBvbHlsaW5lR2VvbWV0cnkudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFycmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgbGV0IGxlbmd0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpLCBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGgpIHsKICAgICAgICAgIHBvc2l0aW9uc1tpXSA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIH0KICAgICAgICBsZW5ndGggPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IGNvbG9ycyA9IGxlbmd0aCA+IDAgPyBuZXcgQXJyYXkobGVuZ3RoKSA6IHZvaWQgMDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2ksIHN0YXJ0aW5nSW5kZXggKz0gQ29sb3JfZGVmYXVsdC5wYWNrZWRMZW5ndGgpIHsKICAgICAgICAgIGNvbG9yc1tpXSA9IENvbG9yX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCBjb2xvcnNQZXJWZXJ0ZXggPSBhcnJheVtzdGFydGluZ0luZGV4KytdID09PSAxOwogICAgICAgIGNvbnN0IGFyY1R5cGUgPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gYXJyYXlbc3RhcnRpbmdJbmRleF07CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmV0dXJuIG5ldyBTaW1wbGVQb2x5bGluZUdlb21ldHJ5KHsKICAgICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgICBjb2xvcnMsCiAgICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgICAgY29sb3JzUGVyVmVydGV4LAogICAgICAgICAgICBhcmNUeXBlLAogICAgICAgICAgICBncmFudWxhcml0eQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5fcG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgICAgIHJlc3VsdC5fY29sb3JzID0gY29sb3JzOwogICAgICAgIHJlc3VsdC5fZWxsaXBzb2lkID0gZWxsaXBzb2lkOwogICAgICAgIHJlc3VsdC5fY29sb3JzUGVyVmVydGV4ID0gY29sb3JzUGVyVmVydGV4OwogICAgICAgIHJlc3VsdC5fYXJjVHlwZSA9IGFyY1R5cGU7CiAgICAgICAgcmVzdWx0Ll9ncmFudWxhcml0eSA9IGdyYW51bGFyaXR5OwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hBcnJheTEgPSBuZXcgQXJyYXkoMik7CiAgICAgIHNjcmF0Y2hBcnJheTIgPSBuZXcgQXJyYXkoMik7CiAgICAgIGdlbmVyYXRlQXJjT3B0aW9uc1NjcmF0Y2ggPSB7CiAgICAgICAgcG9zaXRpb25zOiBzY3JhdGNoQXJyYXkxLAogICAgICAgIGhlaWdodDogc2NyYXRjaEFycmF5MiwKICAgICAgICBlbGxpcHNvaWQ6IHZvaWQgMCwKICAgICAgICBtaW5EaXN0YW5jZTogdm9pZCAwLAogICAgICAgIGdyYW51bGFyaXR5OiB2b2lkIDAKICAgICAgfTsKICAgICAgU2ltcGxlUG9seWxpbmVHZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKHNpbXBsZVBvbHlsaW5lR2VvbWV0cnkpIHsKICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBzaW1wbGVQb2x5bGluZUdlb21ldHJ5Ll9wb3NpdGlvbnM7CiAgICAgICAgY29uc3QgY29sb3JzID0gc2ltcGxlUG9seWxpbmVHZW9tZXRyeS5fY29sb3JzOwogICAgICAgIGNvbnN0IGNvbG9yc1BlclZlcnRleCA9IHNpbXBsZVBvbHlsaW5lR2VvbWV0cnkuX2NvbG9yc1BlclZlcnRleDsKICAgICAgICBjb25zdCBhcmNUeXBlID0gc2ltcGxlUG9seWxpbmVHZW9tZXRyeS5fYXJjVHlwZTsKICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IHNpbXBsZVBvbHlsaW5lR2VvbWV0cnkuX2dyYW51bGFyaXR5OwogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IHNpbXBsZVBvbHlsaW5lR2VvbWV0cnkuX2VsbGlwc29pZDsKICAgICAgICBjb25zdCBtaW5EaXN0YW5jZSA9IE1hdGhfZGVmYXVsdC5jaG9yZExlbmd0aCgKICAgICAgICAgIGdyYW51bGFyaXR5LAogICAgICAgICAgZWxsaXBzb2lkLm1heGltdW1SYWRpdXMKICAgICAgICApOwogICAgICAgIGNvbnN0IHBlclNlZ21lbnRDb2xvcnMgPSBkZWZpbmVkX2RlZmF1bHQoY29sb3JzKSAmJiAhY29sb3JzUGVyVmVydGV4OwogICAgICAgIGxldCBpOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgbGV0IHBvc2l0aW9uVmFsdWVzOwogICAgICAgIGxldCBudW1iZXJPZlBvc2l0aW9uczsKICAgICAgICBsZXQgY29sb3JWYWx1ZXM7CiAgICAgICAgbGV0IGNvbG9yOwogICAgICAgIGxldCBvZmZzZXQgPSAwOwogICAgICAgIGlmIChhcmNUeXBlID09PSBBcmNUeXBlX2RlZmF1bHQuR0VPREVTSUMgfHwgYXJjVHlwZSA9PT0gQXJjVHlwZV9kZWZhdWx0LlJIVU1CKSB7CiAgICAgICAgICBsZXQgc3ViZGl2aXNpb25TaXplOwogICAgICAgICAgbGV0IG51bWJlck9mUG9pbnRzRnVuY3Rpb247CiAgICAgICAgICBsZXQgZ2VuZXJhdGVBcmNGdW5jdGlvbjsKICAgICAgICAgIGlmIChhcmNUeXBlID09PSBBcmNUeXBlX2RlZmF1bHQuR0VPREVTSUMpIHsKICAgICAgICAgICAgc3ViZGl2aXNpb25TaXplID0gTWF0aF9kZWZhdWx0LmNob3JkTGVuZ3RoKAogICAgICAgICAgICAgIGdyYW51bGFyaXR5LAogICAgICAgICAgICAgIGVsbGlwc29pZC5tYXhpbXVtUmFkaXVzCiAgICAgICAgICAgICk7CiAgICAgICAgICAgIG51bWJlck9mUG9pbnRzRnVuY3Rpb24gPSBQb2x5bGluZVBpcGVsaW5lX2RlZmF1bHQubnVtYmVyT2ZQb2ludHM7CiAgICAgICAgICAgIGdlbmVyYXRlQXJjRnVuY3Rpb24gPSBQb2x5bGluZVBpcGVsaW5lX2RlZmF1bHQuZ2VuZXJhdGVBcmM7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdWJkaXZpc2lvblNpemUgPSBncmFudWxhcml0eTsKICAgICAgICAgICAgbnVtYmVyT2ZQb2ludHNGdW5jdGlvbiA9IFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdC5udW1iZXJPZlBvaW50c1JodW1iTGluZTsKICAgICAgICAgICAgZ2VuZXJhdGVBcmNGdW5jdGlvbiA9IFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdC5nZW5lcmF0ZVJodW1iQXJjOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgaGVpZ2h0cyA9IFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdC5leHRyYWN0SGVpZ2h0cyhwb3NpdGlvbnMsIGVsbGlwc29pZCk7CiAgICAgICAgICBjb25zdCBnZW5lcmF0ZUFyY09wdGlvbnMgPSBnZW5lcmF0ZUFyY09wdGlvbnNTY3JhdGNoOwogICAgICAgICAgaWYgKGFyY1R5cGUgPT09IEFyY1R5cGVfZGVmYXVsdC5HRU9ERVNJQykgewogICAgICAgICAgICBnZW5lcmF0ZUFyY09wdGlvbnMubWluRGlzdGFuY2UgPSBtaW5EaXN0YW5jZTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGdlbmVyYXRlQXJjT3B0aW9ucy5ncmFudWxhcml0eSA9IGdyYW51bGFyaXR5OwogICAgICAgICAgfQogICAgICAgICAgZ2VuZXJhdGVBcmNPcHRpb25zLmVsbGlwc29pZCA9IGVsbGlwc29pZDsKICAgICAgICAgIGlmIChwZXJTZWdtZW50Q29sb3JzKSB7CiAgICAgICAgICAgIGxldCBwb3NpdGlvbkNvdW50ID0gMDsKICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aCAtIDE7IGkrKykgewogICAgICAgICAgICAgIHBvc2l0aW9uQ291bnQgKz0gbnVtYmVyT2ZQb2ludHNGdW5jdGlvbigKICAgICAgICAgICAgICAgIHBvc2l0aW9uc1tpXSwKICAgICAgICAgICAgICAgIHBvc2l0aW9uc1tpICsgMV0sCiAgICAgICAgICAgICAgICBzdWJkaXZpc2lvblNpemUKICAgICAgICAgICAgICApICsgMTsKICAgICAgICAgICAgfQogICAgICAgICAgICBwb3NpdGlvblZhbHVlcyA9IG5ldyBGbG9hdDY0QXJyYXkocG9zaXRpb25Db3VudCAqIDMpOwogICAgICAgICAgICBjb2xvclZhbHVlcyA9IG5ldyBVaW50OEFycmF5KHBvc2l0aW9uQ291bnQgKiA0KTsKICAgICAgICAgICAgZ2VuZXJhdGVBcmNPcHRpb25zLnBvc2l0aW9ucyA9IHNjcmF0Y2hBcnJheTE7CiAgICAgICAgICAgIGdlbmVyYXRlQXJjT3B0aW9ucy5oZWlnaHQgPSBzY3JhdGNoQXJyYXkyOwogICAgICAgICAgICBsZXQgY2kgPSAwOwogICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoIC0gMTsgKytpKSB7CiAgICAgICAgICAgICAgc2NyYXRjaEFycmF5MVswXSA9IHBvc2l0aW9uc1tpXTsKICAgICAgICAgICAgICBzY3JhdGNoQXJyYXkxWzFdID0gcG9zaXRpb25zW2kgKyAxXTsKICAgICAgICAgICAgICBzY3JhdGNoQXJyYXkyWzBdID0gaGVpZ2h0c1tpXTsKICAgICAgICAgICAgICBzY3JhdGNoQXJyYXkyWzFdID0gaGVpZ2h0c1tpICsgMV07CiAgICAgICAgICAgICAgY29uc3QgcG9zID0gZ2VuZXJhdGVBcmNGdW5jdGlvbihnZW5lcmF0ZUFyY09wdGlvbnMpOwogICAgICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoY29sb3JzKSkgewogICAgICAgICAgICAgICAgY29uc3Qgc2VnTGVuID0gcG9zLmxlbmd0aCAvIDM7CiAgICAgICAgICAgICAgICBjb2xvciA9IGNvbG9yc1tpXTsKICAgICAgICAgICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgc2VnTGVuOyArK2spIHsKICAgICAgICAgICAgICAgICAgY29sb3JWYWx1ZXNbY2krK10gPSBDb2xvcl9kZWZhdWx0LmZsb2F0VG9CeXRlKGNvbG9yLnJlZCk7CiAgICAgICAgICAgICAgICAgIGNvbG9yVmFsdWVzW2NpKytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShjb2xvci5ncmVlbik7CiAgICAgICAgICAgICAgICAgIGNvbG9yVmFsdWVzW2NpKytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShjb2xvci5ibHVlKTsKICAgICAgICAgICAgICAgICAgY29sb3JWYWx1ZXNbY2krK10gPSBDb2xvcl9kZWZhdWx0LmZsb2F0VG9CeXRlKGNvbG9yLmFscGhhKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcG9zaXRpb25WYWx1ZXMuc2V0KHBvcywgb2Zmc2V0KTsKICAgICAgICAgICAgICBvZmZzZXQgKz0gcG9zLmxlbmd0aDsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZ2VuZXJhdGVBcmNPcHRpb25zLnBvc2l0aW9ucyA9IHBvc2l0aW9uczsKICAgICAgICAgICAgZ2VuZXJhdGVBcmNPcHRpb25zLmhlaWdodCA9IGhlaWdodHM7CiAgICAgICAgICAgIHBvc2l0aW9uVmFsdWVzID0gbmV3IEZsb2F0NjRBcnJheSgKICAgICAgICAgICAgICBnZW5lcmF0ZUFyY0Z1bmN0aW9uKGdlbmVyYXRlQXJjT3B0aW9ucykKICAgICAgICAgICAgKTsKICAgICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChjb2xvcnMpKSB7CiAgICAgICAgICAgICAgY29sb3JWYWx1ZXMgPSBuZXcgVWludDhBcnJheShwb3NpdGlvblZhbHVlcy5sZW5ndGggLyAzICogNCk7CiAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aCAtIDE7ICsraSkgewogICAgICAgICAgICAgICAgY29uc3QgcDAgPSBwb3NpdGlvbnNbaV07CiAgICAgICAgICAgICAgICBjb25zdCBwMSA9IHBvc2l0aW9uc1tpICsgMV07CiAgICAgICAgICAgICAgICBjb25zdCBjMCA9IGNvbG9yc1tpXTsKICAgICAgICAgICAgICAgIGNvbnN0IGMxID0gY29sb3JzW2kgKyAxXTsKICAgICAgICAgICAgICAgIG9mZnNldCA9IGludGVycG9sYXRlQ29sb3JzMigKICAgICAgICAgICAgICAgICAgcDAsCiAgICAgICAgICAgICAgICAgIHAxLAogICAgICAgICAgICAgICAgICBjMCwKICAgICAgICAgICAgICAgICAgYzEsCiAgICAgICAgICAgICAgICAgIG1pbkRpc3RhbmNlLAogICAgICAgICAgICAgICAgICBjb2xvclZhbHVlcywKICAgICAgICAgICAgICAgICAgb2Zmc2V0CiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCBsYXN0Q29sb3IgPSBjb2xvcnNbbGVuZ3RoIC0gMV07CiAgICAgICAgICAgICAgY29sb3JWYWx1ZXNbb2Zmc2V0KytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShsYXN0Q29sb3IucmVkKTsKICAgICAgICAgICAgICBjb2xvclZhbHVlc1tvZmZzZXQrK10gPSBDb2xvcl9kZWZhdWx0LmZsb2F0VG9CeXRlKGxhc3RDb2xvci5ncmVlbik7CiAgICAgICAgICAgICAgY29sb3JWYWx1ZXNbb2Zmc2V0KytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShsYXN0Q29sb3IuYmx1ZSk7CiAgICAgICAgICAgICAgY29sb3JWYWx1ZXNbb2Zmc2V0KytdID0gQ29sb3JfZGVmYXVsdC5mbG9hdFRvQnl0ZShsYXN0Q29sb3IuYWxwaGEpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG51bWJlck9mUG9zaXRpb25zID0gcGVyU2VnbWVudENvbG9ycyA/IGxlbmd0aCAqIDIgLSAyIDogbGVuZ3RoOwogICAgICAgICAgcG9zaXRpb25WYWx1ZXMgPSBuZXcgRmxvYXQ2NEFycmF5KG51bWJlck9mUG9zaXRpb25zICogMyk7CiAgICAgICAgICBjb2xvclZhbHVlcyA9IGRlZmluZWRfZGVmYXVsdChjb2xvcnMpID8gbmV3IFVpbnQ4QXJyYXkobnVtYmVyT2ZQb3NpdGlvbnMgKiA0KSA6IHZvaWQgMDsKICAgICAgICAgIGxldCBwb3NpdGlvbkluZGV4ID0gMDsKICAgICAgICAgIGxldCBjb2xvckluZGV4ID0gMDsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgICBjb25zdCBwID0gcG9zaXRpb25zW2ldOwogICAgICAgICAgICBpZiAocGVyU2VnbWVudENvbG9ycyAmJiBpID4gMCkgewogICAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKHAsIHBvc2l0aW9uVmFsdWVzLCBwb3NpdGlvbkluZGV4KTsKICAgICAgICAgICAgICBwb3NpdGlvbkluZGV4ICs9IDM7CiAgICAgICAgICAgICAgY29sb3IgPSBjb2xvcnNbaSAtIDFdOwogICAgICAgICAgICAgIGNvbG9yVmFsdWVzW2NvbG9ySW5kZXgrK10gPSBDb2xvcl9kZWZhdWx0LmZsb2F0VG9CeXRlKGNvbG9yLnJlZCk7CiAgICAgICAgICAgICAgY29sb3JWYWx1ZXNbY29sb3JJbmRleCsrXSA9IENvbG9yX2RlZmF1bHQuZmxvYXRUb0J5dGUoY29sb3IuZ3JlZW4pOwogICAgICAgICAgICAgIGNvbG9yVmFsdWVzW2NvbG9ySW5kZXgrK10gPSBDb2xvcl9kZWZhdWx0LmZsb2F0VG9CeXRlKGNvbG9yLmJsdWUpOwogICAgICAgICAgICAgIGNvbG9yVmFsdWVzW2NvbG9ySW5kZXgrK10gPSBDb2xvcl9kZWZhdWx0LmZsb2F0VG9CeXRlKGNvbG9yLmFscGhhKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocGVyU2VnbWVudENvbG9ycyAmJiBpID09PSBsZW5ndGggLSAxKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2socCwgcG9zaXRpb25WYWx1ZXMsIHBvc2l0aW9uSW5kZXgpOwogICAgICAgICAgICBwb3NpdGlvbkluZGV4ICs9IDM7CiAgICAgICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoY29sb3JzKSkgewogICAgICAgICAgICAgIGNvbG9yID0gY29sb3JzW2ldOwogICAgICAgICAgICAgIGNvbG9yVmFsdWVzW2NvbG9ySW5kZXgrK10gPSBDb2xvcl9kZWZhdWx0LmZsb2F0VG9CeXRlKGNvbG9yLnJlZCk7CiAgICAgICAgICAgICAgY29sb3JWYWx1ZXNbY29sb3JJbmRleCsrXSA9IENvbG9yX2RlZmF1bHQuZmxvYXRUb0J5dGUoY29sb3IuZ3JlZW4pOwogICAgICAgICAgICAgIGNvbG9yVmFsdWVzW2NvbG9ySW5kZXgrK10gPSBDb2xvcl9kZWZhdWx0LmZsb2F0VG9CeXRlKGNvbG9yLmJsdWUpOwogICAgICAgICAgICAgIGNvbG9yVmFsdWVzW2NvbG9ySW5kZXgrK10gPSBDb2xvcl9kZWZhdWx0LmZsb2F0VG9CeXRlKGNvbG9yLmFscGhhKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlc19kZWZhdWx0KCk7CiAgICAgICAgYXR0cmlidXRlcy5wb3NpdGlvbiA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkRPVUJMRSwKICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICB2YWx1ZXM6IHBvc2l0aW9uVmFsdWVzCiAgICAgICAgfSk7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChjb2xvcnMpKSB7CiAgICAgICAgICBhdHRyaWJ1dGVzLmNvbG9yID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9CWVRFLAogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiA0LAogICAgICAgICAgICB2YWx1ZXM6IGNvbG9yVmFsdWVzLAogICAgICAgICAgICBub3JtYWxpemU6IHRydWUKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBudW1iZXJPZlBvc2l0aW9ucyA9IHBvc2l0aW9uVmFsdWVzLmxlbmd0aCAvIDM7CiAgICAgICAgY29uc3QgbnVtYmVyT2ZJbmRpY2VzID0gKG51bWJlck9mUG9zaXRpb25zIC0gMSkgKiAyOwogICAgICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgICAgIG51bWJlck9mUG9zaXRpb25zLAogICAgICAgICAgbnVtYmVyT2ZJbmRpY2VzCiAgICAgICAgKTsKICAgICAgICBsZXQgaW5kZXggPSAwOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1iZXJPZlBvc2l0aW9ucyAtIDE7ICsraSkgewogICAgICAgICAgaW5kaWNlc1tpbmRleCsrXSA9IGk7CiAgICAgICAgICBpbmRpY2VzW2luZGV4KytdID0gaSArIDE7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgICAgICBhdHRyaWJ1dGVzLAogICAgICAgICAgaW5kaWNlcywKICAgICAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5MSU5FUywKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlOiBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21Qb2ludHMocG9zaXRpb25zKQogICAgICAgIH0pOwogICAgICB9OwogICAgICBTaW1wbGVQb2x5bGluZUdlb21ldHJ5X2RlZmF1bHQgPSBTaW1wbGVQb2x5bGluZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlU2ltcGxlUG9seWxpbmVHZW9tZXRyeS5qcwogIHZhciBjcmVhdGVTaW1wbGVQb2x5bGluZUdlb21ldHJ5X2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChjcmVhdGVTaW1wbGVQb2x5bGluZUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZVNpbXBsZVBvbHlsaW5lR2VvbWV0cnlfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZVNpbXBsZVBvbHlsaW5lR2VvbWV0cnkoc2ltcGxlUG9seWxpbmVHZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgc2ltcGxlUG9seWxpbmVHZW9tZXRyeSA9IFNpbXBsZVBvbHlsaW5lR2VvbWV0cnlfZGVmYXVsdC51bnBhY2soCiAgICAgICAgc2ltcGxlUG9seWxpbmVHZW9tZXRyeSwKICAgICAgICBvZmZzZXQKICAgICAgKTsKICAgIH0KICAgIHNpbXBsZVBvbHlsaW5lR2VvbWV0cnkuX2VsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKAogICAgICBzaW1wbGVQb2x5bGluZUdlb21ldHJ5Ll9lbGxpcHNvaWQKICAgICk7CiAgICByZXR1cm4gU2ltcGxlUG9seWxpbmVHZW9tZXRyeV9kZWZhdWx0LmNyZWF0ZUdlb21ldHJ5KHNpbXBsZVBvbHlsaW5lR2VvbWV0cnkpOwogIH0KICB2YXIgY3JlYXRlU2ltcGxlUG9seWxpbmVHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X2NyZWF0ZVNpbXBsZVBvbHlsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVNpbXBsZVBvbHlsaW5lR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9TaW1wbGVQb2x5bGluZUdlb21ldHJ5KCk7CiAgICAgIGNyZWF0ZVNpbXBsZVBvbHlsaW5lR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZVNpbXBsZVBvbHlsaW5lR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9TcGhlcmVHZW9tZXRyeS5qcwogIGZ1bmN0aW9uIFNwaGVyZUdlb21ldHJ5KG9wdGlvbnMpIHsKICAgIGNvbnN0IHJhZGl1cyA9IG9wdGlvbnMucmFkaXVzID8/IDE7CiAgICBjb25zdCByYWRpaSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQocmFkaXVzLCByYWRpdXMsIHJhZGl1cyk7CiAgICBjb25zdCBlbGxpcHNvaWRPcHRpb25zID0gewogICAgICByYWRpaSwKICAgICAgc3RhY2tQYXJ0aXRpb25zOiBvcHRpb25zLnN0YWNrUGFydGl0aW9ucywKICAgICAgc2xpY2VQYXJ0aXRpb25zOiBvcHRpb25zLnNsaWNlUGFydGl0aW9ucywKICAgICAgdmVydGV4Rm9ybWF0OiBvcHRpb25zLnZlcnRleEZvcm1hdAogICAgfTsKICAgIHRoaXMuX2VsbGlwc29pZEdlb21ldHJ5ID0gbmV3IEVsbGlwc29pZEdlb21ldHJ5X2RlZmF1bHQoZWxsaXBzb2lkT3B0aW9ucyk7CiAgICB0aGlzLl93b3JrZXJOYW1lID0gImNyZWF0ZVNwaGVyZUdlb21ldHJ5IjsKICB9CiAgdmFyIHNjcmF0Y2hFbGxpcHNvaWRHZW9tZXRyeSwgc2NyYXRjaE9wdGlvbnMyMSwgU3BoZXJlR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9TcGhlcmVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvU3BoZXJlR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWRHZW9tZXRyeSgpOwogICAgICBpbml0X1ZlcnRleEZvcm1hdCgpOwogICAgICBTcGhlcmVHZW9tZXRyeS5wYWNrZWRMZW5ndGggPSBFbGxpcHNvaWRHZW9tZXRyeV9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgU3BoZXJlR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgcmV0dXJuIEVsbGlwc29pZEdlb21ldHJ5X2RlZmF1bHQucGFjayh2YWx1ZS5fZWxsaXBzb2lkR2VvbWV0cnksIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgfTsKICAgICAgc2NyYXRjaEVsbGlwc29pZEdlb21ldHJ5ID0gbmV3IEVsbGlwc29pZEdlb21ldHJ5X2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE9wdGlvbnMyMSA9IHsKICAgICAgICByYWRpdXM6IHZvaWQgMCwKICAgICAgICByYWRpaTogbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpLAogICAgICAgIHZlcnRleEZvcm1hdDogbmV3IFZlcnRleEZvcm1hdF9kZWZhdWx0KCksCiAgICAgICAgc3RhY2tQYXJ0aXRpb25zOiB2b2lkIDAsCiAgICAgICAgc2xpY2VQYXJ0aXRpb25zOiB2b2lkIDAKICAgICAgfTsKICAgICAgU3BoZXJlR2VvbWV0cnkudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIGNvbnN0IGVsbGlwc29pZEdlb21ldHJ5ID0gRWxsaXBzb2lkR2VvbWV0cnlfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICBhcnJheSwKICAgICAgICAgIHN0YXJ0aW5nSW5kZXgsCiAgICAgICAgICBzY3JhdGNoRWxsaXBzb2lkR2VvbWV0cnkKICAgICAgICApOwogICAgICAgIHNjcmF0Y2hPcHRpb25zMjEudmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQuY2xvbmUoCiAgICAgICAgICBlbGxpcHNvaWRHZW9tZXRyeS5fdmVydGV4Rm9ybWF0LAogICAgICAgICAgc2NyYXRjaE9wdGlvbnMyMS52ZXJ0ZXhGb3JtYXQKICAgICAgICApOwogICAgICAgIHNjcmF0Y2hPcHRpb25zMjEuc3RhY2tQYXJ0aXRpb25zID0gZWxsaXBzb2lkR2VvbWV0cnkuX3N0YWNrUGFydGl0aW9uczsKICAgICAgICBzY3JhdGNoT3B0aW9uczIxLnNsaWNlUGFydGl0aW9ucyA9IGVsbGlwc29pZEdlb21ldHJ5Ll9zbGljZVBhcnRpdGlvbnM7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgc2NyYXRjaE9wdGlvbnMyMS5yYWRpdXMgPSBlbGxpcHNvaWRHZW9tZXRyeS5fcmFkaWkueDsKICAgICAgICAgIHJldHVybiBuZXcgU3BoZXJlR2VvbWV0cnkoc2NyYXRjaE9wdGlvbnMyMSk7CiAgICAgICAgfQogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShlbGxpcHNvaWRHZW9tZXRyeS5fcmFkaWksIHNjcmF0Y2hPcHRpb25zMjEucmFkaWkpOwogICAgICAgIHJlc3VsdC5fZWxsaXBzb2lkR2VvbWV0cnkgPSBuZXcgRWxsaXBzb2lkR2VvbWV0cnlfZGVmYXVsdChzY3JhdGNoT3B0aW9uczIxKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBTcGhlcmVHZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKHNwaGVyZUdlb21ldHJ5KSB7CiAgICAgICAgcmV0dXJuIEVsbGlwc29pZEdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkoc3BoZXJlR2VvbWV0cnkuX2VsbGlwc29pZEdlb21ldHJ5KTsKICAgICAgfTsKICAgICAgU3BoZXJlR2VvbWV0cnlfZGVmYXVsdCA9IFNwaGVyZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlU3BoZXJlR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlU3BoZXJlR2VvbWV0cnlfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZVNwaGVyZUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZVNwaGVyZUdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVTcGhlcmVHZW9tZXRyeShzcGhlcmVHZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgc3BoZXJlR2VvbWV0cnkgPSBTcGhlcmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjayhzcGhlcmVHZW9tZXRyeSwgb2Zmc2V0KTsKICAgIH0KICAgIHJldHVybiBTcGhlcmVHZW9tZXRyeV9kZWZhdWx0LmNyZWF0ZUdlb21ldHJ5KHNwaGVyZUdlb21ldHJ5KTsKICB9CiAgdmFyIGNyZWF0ZVNwaGVyZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlU3BoZXJlR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVNwaGVyZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfU3BoZXJlR2VvbWV0cnkoKTsKICAgICAgY3JlYXRlU3BoZXJlR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZVNwaGVyZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvU3BoZXJlT3V0bGluZUdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gU3BoZXJlT3V0bGluZUdlb21ldHJ5KG9wdGlvbnMpIHsKICAgIGNvbnN0IHJhZGl1cyA9IG9wdGlvbnMucmFkaXVzID8/IDE7CiAgICBjb25zdCByYWRpaSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQocmFkaXVzLCByYWRpdXMsIHJhZGl1cyk7CiAgICBjb25zdCBlbGxpcHNvaWRPcHRpb25zID0gewogICAgICByYWRpaSwKICAgICAgc3RhY2tQYXJ0aXRpb25zOiBvcHRpb25zLnN0YWNrUGFydGl0aW9ucywKICAgICAgc2xpY2VQYXJ0aXRpb25zOiBvcHRpb25zLnNsaWNlUGFydGl0aW9ucywKICAgICAgc3ViZGl2aXNpb25zOiBvcHRpb25zLnN1YmRpdmlzaW9ucwogICAgfTsKICAgIHRoaXMuX2VsbGlwc29pZEdlb21ldHJ5ID0gbmV3IEVsbGlwc29pZE91dGxpbmVHZW9tZXRyeV9kZWZhdWx0KGVsbGlwc29pZE9wdGlvbnMpOwogICAgdGhpcy5fd29ya2VyTmFtZSA9ICJjcmVhdGVTcGhlcmVPdXRsaW5lR2VvbWV0cnkiOwogIH0KICB2YXIgc2NyYXRjaEVsbGlwc29pZEdlb21ldHJ5Miwgc2NyYXRjaE9wdGlvbnMyMiwgU3BoZXJlT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfU3BoZXJlT3V0bGluZUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9TcGhlcmVPdXRsaW5lR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnkoKTsKICAgICAgU3BoZXJlT3V0bGluZUdlb21ldHJ5LnBhY2tlZExlbmd0aCA9IEVsbGlwc29pZE91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgU3BoZXJlT3V0bGluZUdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoInZhbHVlIiwgdmFsdWUpOwogICAgICAgIHJldHVybiBFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdC5wYWNrKAogICAgICAgICAgdmFsdWUuX2VsbGlwc29pZEdlb21ldHJ5LAogICAgICAgICAgYXJyYXksCiAgICAgICAgICBzdGFydGluZ0luZGV4CiAgICAgICAgKTsKICAgICAgfTsKICAgICAgc2NyYXRjaEVsbGlwc29pZEdlb21ldHJ5MiA9IG5ldyBFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoT3B0aW9uczIyID0gewogICAgICAgIHJhZGl1czogdm9pZCAwLAogICAgICAgIHJhZGlpOiBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCksCiAgICAgICAgc3RhY2tQYXJ0aXRpb25zOiB2b2lkIDAsCiAgICAgICAgc2xpY2VQYXJ0aXRpb25zOiB2b2lkIDAsCiAgICAgICAgc3ViZGl2aXNpb25zOiB2b2lkIDAKICAgICAgfTsKICAgICAgU3BoZXJlT3V0bGluZUdlb21ldHJ5LnVucGFjayA9IGZ1bmN0aW9uKGFycmF5LCBzdGFydGluZ0luZGV4LCByZXN1bHQpIHsKICAgICAgICBjb25zdCBlbGxpcHNvaWRHZW9tZXRyeSA9IEVsbGlwc29pZE91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjaygKICAgICAgICAgIGFycmF5LAogICAgICAgICAgc3RhcnRpbmdJbmRleCwKICAgICAgICAgIHNjcmF0Y2hFbGxpcHNvaWRHZW9tZXRyeTIKICAgICAgICApOwogICAgICAgIHNjcmF0Y2hPcHRpb25zMjIuc3RhY2tQYXJ0aXRpb25zID0gZWxsaXBzb2lkR2VvbWV0cnkuX3N0YWNrUGFydGl0aW9uczsKICAgICAgICBzY3JhdGNoT3B0aW9uczIyLnNsaWNlUGFydGl0aW9ucyA9IGVsbGlwc29pZEdlb21ldHJ5Ll9zbGljZVBhcnRpdGlvbnM7CiAgICAgICAgc2NyYXRjaE9wdGlvbnMyMi5zdWJkaXZpc2lvbnMgPSBlbGxpcHNvaWRHZW9tZXRyeS5fc3ViZGl2aXNpb25zOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMjIucmFkaXVzID0gZWxsaXBzb2lkR2VvbWV0cnkuX3JhZGlpLng7CiAgICAgICAgICByZXR1cm4gbmV3IFNwaGVyZU91dGxpbmVHZW9tZXRyeShzY3JhdGNoT3B0aW9uczIyKTsKICAgICAgICB9CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGVsbGlwc29pZEdlb21ldHJ5Ll9yYWRpaSwgc2NyYXRjaE9wdGlvbnMyMi5yYWRpaSk7CiAgICAgICAgcmVzdWx0Ll9lbGxpcHNvaWRHZW9tZXRyeSA9IG5ldyBFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdChzY3JhdGNoT3B0aW9uczIyKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBTcGhlcmVPdXRsaW5lR2VvbWV0cnkuY3JlYXRlR2VvbWV0cnkgPSBmdW5jdGlvbihzcGhlcmVHZW9tZXRyeSkgewogICAgICAgIHJldHVybiBFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeSgKICAgICAgICAgIHNwaGVyZUdlb21ldHJ5Ll9lbGxpcHNvaWRHZW9tZXRyeQogICAgICAgICk7CiAgICAgIH07CiAgICAgIFNwaGVyZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gU3BoZXJlT3V0bGluZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlU3BoZXJlT3V0bGluZUdlb21ldHJ5LmpzCiAgdmFyIGNyZWF0ZVNwaGVyZU91dGxpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlU3BoZXJlT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZVNwaGVyZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gY3JlYXRlU3BoZXJlT3V0bGluZUdlb21ldHJ5KHNwaGVyZUdlb21ldHJ5LCBvZmZzZXQpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob2Zmc2V0KSkgewogICAgICBzcGhlcmVHZW9tZXRyeSA9IFNwaGVyZU91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjayhzcGhlcmVHZW9tZXRyeSwgb2Zmc2V0KTsKICAgIH0KICAgIHJldHVybiBTcGhlcmVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdC5jcmVhdGVHZW9tZXRyeShzcGhlcmVHZW9tZXRyeSk7CiAgfQogIHZhciBjcmVhdGVTcGhlcmVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVTcGhlcmVPdXRsaW5lR2VvbWV0cnkgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVNwaGVyZU91dGxpbmVHZW9tZXRyeS5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X1NwaGVyZU91dGxpbmVHZW9tZXRyeSgpOwogICAgICBjcmVhdGVTcGhlcmVPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdCA9IGNyZWF0ZVNwaGVyZU91dGxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVZlY3RvclRpbGVDbGFtcGVkUG9seWxpbmVzLmpzCiAgdmFyIGNyZWF0ZVZlY3RvclRpbGVDbGFtcGVkUG9seWxpbmVzX2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChjcmVhdGVWZWN0b3JUaWxlQ2xhbXBlZFBvbHlsaW5lc19leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVWZWN0b3JUaWxlQ2xhbXBlZFBvbHlsaW5lc19kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gZGVjb2RlUG9zaXRpb25zKHVCdWZmZXIsIHZCdWZmZXIsIGhlaWdodEJ1ZmZlciwgcmVjdGFuZ2xlLCBtaW5pbXVtSGVpZ2h0LCBtYXhpbXVtSGVpZ2h0LCBlbGxpcHNvaWQpIHsKICAgIGNvbnN0IHBvc2l0aW9uc0xlbmd0aCA9IHVCdWZmZXIubGVuZ3RoOwogICAgY29uc3QgZGVjb2RlZFBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkocG9zaXRpb25zTGVuZ3RoICogMyk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBvc2l0aW9uc0xlbmd0aDsgKytpKSB7CiAgICAgIGNvbnN0IHUzID0gdUJ1ZmZlcltpXTsKICAgICAgY29uc3QgdjMgPSB2QnVmZmVyW2ldOwogICAgICBjb25zdCBoID0gaGVpZ2h0QnVmZmVyW2ldOwogICAgICBjb25zdCBsb24gPSBNYXRoX2RlZmF1bHQubGVycChyZWN0YW5nbGUud2VzdCwgcmVjdGFuZ2xlLmVhc3QsIHUzIC8gTUFYX1NIT1JUKTsKICAgICAgY29uc3QgbGF0ID0gTWF0aF9kZWZhdWx0LmxlcnAoCiAgICAgICAgcmVjdGFuZ2xlLnNvdXRoLAogICAgICAgIHJlY3RhbmdsZS5ub3J0aCwKICAgICAgICB2MyAvIE1BWF9TSE9SVAogICAgICApOwogICAgICBjb25zdCBhbHQgPSBNYXRoX2RlZmF1bHQubGVycChtaW5pbXVtSGVpZ2h0LCBtYXhpbXVtSGVpZ2h0LCBoIC8gTUFYX1NIT1JUKTsKICAgICAgY29uc3QgY2FydG9ncmFwaGljMiA9IENhcnRvZ3JhcGhpY19kZWZhdWx0LmZyb21SYWRpYW5zKAogICAgICAgIGxvbiwKICAgICAgICBsYXQsCiAgICAgICAgYWx0LAogICAgICAgIHNjcmF0Y2hCVkNhcnRvZ3JhcGhpYwogICAgICApOwogICAgICBjb25zdCBkZWNvZGVkUG9zaXRpb24gPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oCiAgICAgICAgY2FydG9ncmFwaGljMiwKICAgICAgICBzY3JhdGNoRW5jb2RlZFBvc2l0aW9uCiAgICAgICk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKGRlY29kZWRQb3NpdGlvbiwgZGVjb2RlZFBvc2l0aW9ucywgaSAqIDMpOwogICAgfQogICAgcmV0dXJuIGRlY29kZWRQb3NpdGlvbnM7CiAgfQogIGZ1bmN0aW9uIGdldFBvc2l0aW9uT2Zmc2V0cyhjb3VudHMpIHsKICAgIGNvbnN0IGNvdW50c0xlbmd0aCA9IGNvdW50cy5sZW5ndGg7CiAgICBjb25zdCBwb3NpdGlvbk9mZnNldHMgPSBuZXcgVWludDMyQXJyYXkoY291bnRzTGVuZ3RoICsgMSk7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnRzTGVuZ3RoOyArK2kpIHsKICAgICAgcG9zaXRpb25PZmZzZXRzW2ldID0gb2Zmc2V0OwogICAgICBvZmZzZXQgKz0gY291bnRzW2ldOwogICAgfQogICAgcG9zaXRpb25PZmZzZXRzW2NvdW50c0xlbmd0aF0gPSBvZmZzZXQ7CiAgICByZXR1cm4gcG9zaXRpb25PZmZzZXRzOwogIH0KICBmdW5jdGlvbiByZW1vdmVEdXBsaWNhdGVzKHVCdWZmZXIsIHZCdWZmZXIsIGhlaWdodEJ1ZmZlciwgY291bnRzKSB7CiAgICBjb25zdCBjb3VudHNMZW5ndGggPSBjb3VudHMubGVuZ3RoOwogICAgY29uc3QgcG9zaXRpb25zTGVuZ3RoID0gdUJ1ZmZlci5sZW5ndGg7CiAgICBjb25zdCBtYXJrUmVtb3ZhbCA9IG5ldyBVaW50OEFycmF5KHBvc2l0aW9uc0xlbmd0aCk7CiAgICBjb25zdCBwcmV2aW91cyA9IHByZXZpb3VzQ29tcHJlc3NlZENhcnRvZ3JhcGhpY1NjcmF0Y2g7CiAgICBjb25zdCBjdXJyZW50ID0gY3VycmVudENvbXByZXNzZWRDYXJ0b2dyYXBoaWNTY3JhdGNoOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50c0xlbmd0aDsgaSsrKSB7CiAgICAgIGNvbnN0IGNvdW50ID0gY291bnRzW2ldOwogICAgICBsZXQgdXBkYXRlZENvdW50ID0gY291bnQ7CiAgICAgIGZvciAobGV0IGogPSAxOyBqIDwgY291bnQ7IGorKykgewogICAgICAgIGNvbnN0IGluZGV4ID0gb2Zmc2V0ICsgajsKICAgICAgICBjb25zdCBwcmV2aW91c0luZGV4ID0gaW5kZXggLSAxOwogICAgICAgIGN1cnJlbnQubG9uZ2l0dWRlID0gdUJ1ZmZlcltpbmRleF07CiAgICAgICAgY3VycmVudC5sYXRpdHVkZSA9IHZCdWZmZXJbaW5kZXhdOwogICAgICAgIHByZXZpb3VzLmxvbmdpdHVkZSA9IHVCdWZmZXJbcHJldmlvdXNJbmRleF07CiAgICAgICAgcHJldmlvdXMubGF0aXR1ZGUgPSB2QnVmZmVyW3ByZXZpb3VzSW5kZXhdOwogICAgICAgIGlmIChDYXJ0b2dyYXBoaWNfZGVmYXVsdC5lcXVhbHMoY3VycmVudCwgcHJldmlvdXMpKSB7CiAgICAgICAgICB1cGRhdGVkQ291bnQtLTsKICAgICAgICAgIG1hcmtSZW1vdmFsW3ByZXZpb3VzSW5kZXhdID0gMTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY291bnRzW2ldID0gdXBkYXRlZENvdW50OwogICAgICBvZmZzZXQgKz0gY291bnQ7CiAgICB9CiAgICBsZXQgbmV4dEF2YWlsYWJsZUluZGV4ID0gMDsKICAgIGZvciAobGV0IGsgPSAwOyBrIDwgcG9zaXRpb25zTGVuZ3RoOyBrKyspIHsKICAgICAgaWYgKG1hcmtSZW1vdmFsW2tdICE9PSAxKSB7CiAgICAgICAgdUJ1ZmZlcltuZXh0QXZhaWxhYmxlSW5kZXhdID0gdUJ1ZmZlcltrXTsKICAgICAgICB2QnVmZmVyW25leHRBdmFpbGFibGVJbmRleF0gPSB2QnVmZmVyW2tdOwogICAgICAgIGhlaWdodEJ1ZmZlcltuZXh0QXZhaWxhYmxlSW5kZXhdID0gaGVpZ2h0QnVmZmVyW2tdOwogICAgICAgIG5leHRBdmFpbGFibGVJbmRleCsrOwogICAgICB9CiAgICB9CiAgfQogIGZ1bmN0aW9uIFZlcnRleEF0dHJpYnV0ZXNBbmRJbmRpY2VzKHZvbHVtZXNDb3VudCkgewogICAgY29uc3QgdmVydGV4Q291bnQgPSB2b2x1bWVzQ291bnQgKiA4OwogICAgY29uc3QgdmVjM0Zsb2F0cyA9IHZlcnRleENvdW50ICogMzsKICAgIGNvbnN0IHZlYzRGbG9hdHMgPSB2ZXJ0ZXhDb3VudCAqIDQ7CiAgICB0aGlzLnN0YXJ0RWxsaXBzb2lkTm9ybWFscyA9IG5ldyBGbG9hdDMyQXJyYXkodmVjM0Zsb2F0cyk7CiAgICB0aGlzLmVuZEVsbGlwc29pZE5vcm1hbHMgPSBuZXcgRmxvYXQzMkFycmF5KHZlYzNGbG9hdHMpOwogICAgdGhpcy5zdGFydFBvc2l0aW9uQW5kSGVpZ2h0cyA9IG5ldyBGbG9hdDMyQXJyYXkodmVjNEZsb2F0cyk7CiAgICB0aGlzLnN0YXJ0RmFjZU5vcm1hbEFuZFZlcnRleENvcm5lcklkcyA9IG5ldyBGbG9hdDMyQXJyYXkodmVjNEZsb2F0cyk7CiAgICB0aGlzLmVuZFBvc2l0aW9uQW5kSGVpZ2h0cyA9IG5ldyBGbG9hdDMyQXJyYXkodmVjNEZsb2F0cyk7CiAgICB0aGlzLmVuZEZhY2VOb3JtYWxBbmRIYWxmV2lkdGhzID0gbmV3IEZsb2F0MzJBcnJheSh2ZWM0RmxvYXRzKTsKICAgIHRoaXMudmVydGV4QmF0Y2hJZHMgPSBuZXcgVWludDE2QXJyYXkodmVydGV4Q291bnQpOwogICAgdGhpcy5pbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkodmVydGV4Q291bnQsIDM2ICogdm9sdW1lc0NvdW50KTsKICAgIHRoaXMudmVjM09mZnNldCA9IDA7CiAgICB0aGlzLnZlYzRPZmZzZXQgPSAwOwogICAgdGhpcy5iYXRjaElkT2Zmc2V0ID0gMDsKICAgIHRoaXMuaW5kZXhPZmZzZXQgPSAwOwogICAgdGhpcy52b2x1bWVTdGFydEluZGV4ID0gMDsKICB9CiAgZnVuY3Rpb24gY29tcHV0ZU1pdGVyZWROb3JtYWwocHJldmlvdXNQb3NpdGlvbiwgcG9zaXRpb24sIG5leHRQb3NpdGlvbiwgZWxsaXBzb2lkU3VyZmFjZU5vcm1hbCwgcmVzdWx0KSB7CiAgICBjb25zdCB0b3dhcmROZXh0ID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KAogICAgICBuZXh0UG9zaXRpb24sCiAgICAgIHBvc2l0aW9uLAogICAgICB0b3dhcmROZXh0U2NyYXRjaAogICAgKTsKICAgIGxldCB0b3dhcmRDdXJyID0gQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KAogICAgICBwb3NpdGlvbiwKICAgICAgcHJldmlvdXNQb3NpdGlvbiwKICAgICAgdG93YXJkQ3VyclNjcmF0Y2gKICAgICk7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKHRvd2FyZE5leHQsIHRvd2FyZE5leHQpOwogICAgQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSh0b3dhcmRDdXJyLCB0b3dhcmRDdXJyKTsKICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZG90KHRvd2FyZE5leHQsIHRvd2FyZEN1cnIpIDwgTUlURVJfQlJFQUspIHsKICAgICAgdG93YXJkQ3VyciA9IENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICAgIHRvd2FyZEN1cnIsCiAgICAgICAgLTEsCiAgICAgICAgdG93YXJkQ3VyclNjcmF0Y2gKICAgICAgKTsKICAgIH0KICAgIENhcnRlc2lhbjNfZGVmYXVsdC5hZGQodG93YXJkTmV4dCwgdG93YXJkQ3VyciwgcmVzdWx0KTsKICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzKHJlc3VsdCwgQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8pKSB7CiAgICAgIHJlc3VsdCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChwcmV2aW91c1Bvc2l0aW9uLCBwb3NpdGlvbik7CiAgICB9CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MocmVzdWx0LCBlbGxpcHNvaWRTdXJmYWNlTm9ybWFsLCByZXN1bHQpOwogICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKGVsbGlwc29pZFN1cmZhY2VOb3JtYWwsIHJlc3VsdCwgcmVzdWx0KTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUocmVzdWx0LCByZXN1bHQpOwogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgZnVuY3Rpb24gY3JlYXRlVmVjdG9yVGlsZUNsYW1wZWRQb2x5bGluZXMocGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cykgewogICAgY29uc3QgZW5jb2RlZFBvc2l0aW9ucyA9IG5ldyBVaW50MTZBcnJheShwYXJhbWV0ZXJzLnBvc2l0aW9ucyk7CiAgICBjb25zdCB3aWR0aHMgPSBuZXcgVWludDE2QXJyYXkocGFyYW1ldGVycy53aWR0aHMpOwogICAgY29uc3QgY291bnRzID0gbmV3IFVpbnQzMkFycmF5KHBhcmFtZXRlcnMuY291bnRzKTsKICAgIGNvbnN0IGJhdGNoSWRzID0gbmV3IFVpbnQxNkFycmF5KHBhcmFtZXRlcnMuYmF0Y2hJZHMpOwogICAgY29uc3QgcmVjdGFuZ2xlID0gc2NyYXRjaFJlY3RhbmdsZTM7CiAgICBjb25zdCBlbGxpcHNvaWQgPSBzY3JhdGNoRWxsaXBzb2lkMTM7CiAgICBjb25zdCBjZW50ZXIgPSBzY3JhdGNoQ2VudGVyNDsKICAgIGNvbnN0IHBhY2tlZEJ1ZmZlciA9IG5ldyBGbG9hdDY0QXJyYXkocGFyYW1ldGVycy5wYWNrZWRCdWZmZXIpOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICBjb25zdCBtaW5pbXVtSGVpZ2h0ID0gcGFja2VkQnVmZmVyW29mZnNldCsrXTsKICAgIGNvbnN0IG1heGltdW1IZWlnaHQgPSBwYWNrZWRCdWZmZXJbb2Zmc2V0KytdOwogICAgUmVjdGFuZ2xlX2RlZmF1bHQudW5wYWNrKHBhY2tlZEJ1ZmZlciwgb2Zmc2V0LCByZWN0YW5nbGUpOwogICAgb2Zmc2V0ICs9IFJlY3RhbmdsZV9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgIEVsbGlwc29pZF9kZWZhdWx0LnVucGFjayhwYWNrZWRCdWZmZXIsIG9mZnNldCwgZWxsaXBzb2lkKTsKICAgIG9mZnNldCArPSBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKHBhY2tlZEJ1ZmZlciwgb2Zmc2V0LCBjZW50ZXIpOwogICAgbGV0IGk7CiAgICBsZXQgcG9zaXRpb25zTGVuZ3RoID0gZW5jb2RlZFBvc2l0aW9ucy5sZW5ndGggLyAzOwogICAgY29uc3QgdUJ1ZmZlciA9IGVuY29kZWRQb3NpdGlvbnMuc3ViYXJyYXkoMCwgcG9zaXRpb25zTGVuZ3RoKTsKICAgIGNvbnN0IHZCdWZmZXIgPSBlbmNvZGVkUG9zaXRpb25zLnN1YmFycmF5KAogICAgICBwb3NpdGlvbnNMZW5ndGgsCiAgICAgIDIgKiBwb3NpdGlvbnNMZW5ndGgKICAgICk7CiAgICBjb25zdCBoZWlnaHRCdWZmZXIgPSBlbmNvZGVkUG9zaXRpb25zLnN1YmFycmF5KAogICAgICAyICogcG9zaXRpb25zTGVuZ3RoLAogICAgICAzICogcG9zaXRpb25zTGVuZ3RoCiAgICApOwogICAgQXR0cmlidXRlQ29tcHJlc3Npb25fZGVmYXVsdC56aWdaYWdEZWx0YURlY29kZSh1QnVmZmVyLCB2QnVmZmVyLCBoZWlnaHRCdWZmZXIpOwogICAgcmVtb3ZlRHVwbGljYXRlcyh1QnVmZmVyLCB2QnVmZmVyLCBoZWlnaHRCdWZmZXIsIGNvdW50cyk7CiAgICBjb25zdCBjb3VudHNMZW5ndGggPSBjb3VudHMubGVuZ3RoOwogICAgbGV0IHZvbHVtZXNDb3VudCA9IDA7CiAgICBmb3IgKGkgPSAwOyBpIDwgY291bnRzTGVuZ3RoOyBpKyspIHsKICAgICAgY29uc3QgcG9seWxpbmVQb3NpdGlvbkNvdW50ID0gY291bnRzW2ldOwogICAgICB2b2x1bWVzQ291bnQgKz0gcG9seWxpbmVQb3NpdGlvbkNvdW50IC0gMTsKICAgIH0KICAgIGNvbnN0IGF0dHJpYnNBbmRJbmRpY2VzID0gbmV3IFZlcnRleEF0dHJpYnV0ZXNBbmRJbmRpY2VzKHZvbHVtZXNDb3VudCk7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBkZWNvZGVQb3NpdGlvbnMoCiAgICAgIHVCdWZmZXIsCiAgICAgIHZCdWZmZXIsCiAgICAgIGhlaWdodEJ1ZmZlciwKICAgICAgcmVjdGFuZ2xlLAogICAgICBtaW5pbXVtSGVpZ2h0LAogICAgICBtYXhpbXVtSGVpZ2h0LAogICAgICBlbGxpcHNvaWQsCiAgICAgIGNlbnRlcgogICAgKTsKICAgIHBvc2l0aW9uc0xlbmd0aCA9IHVCdWZmZXIubGVuZ3RoOwogICAgY29uc3QgcG9zaXRpb25zUlRDID0gbmV3IEZsb2F0MzJBcnJheShwb3NpdGlvbnNMZW5ndGggKiAzKTsKICAgIGZvciAoaSA9IDA7IGkgPCBwb3NpdGlvbnNMZW5ndGg7ICsraSkgewogICAgICBwb3NpdGlvbnNSVENbaSAqIDNdID0gcG9zaXRpb25zW2kgKiAzXSAtIGNlbnRlci54OwogICAgICBwb3NpdGlvbnNSVENbaSAqIDMgKyAxXSA9IHBvc2l0aW9uc1tpICogMyArIDFdIC0gY2VudGVyLnk7CiAgICAgIHBvc2l0aW9uc1JUQ1tpICogMyArIDJdID0gcG9zaXRpb25zW2kgKiAzICsgMl0gLSBjZW50ZXIuejsKICAgIH0KICAgIGxldCBjdXJyZW50UG9zaXRpb25JbmRleCA9IDA7CiAgICBsZXQgY3VycmVudEhlaWdodEluZGV4ID0gMDsKICAgIGZvciAoaSA9IDA7IGkgPCBjb3VudHNMZW5ndGg7IGkrKykgewogICAgICBjb25zdCBwb2x5bGluZVZvbHVtZUNvdW50ID0gY291bnRzW2ldIC0gMTsKICAgICAgY29uc3QgaGFsZldpZHRoID0gd2lkdGhzW2ldICogMC41OwogICAgICBjb25zdCBiYXRjaElkID0gYmF0Y2hJZHNbaV07CiAgICAgIGNvbnN0IHZvbHVtZUZpcnN0UG9zaXRpb25JbmRleCA9IGN1cnJlbnRQb3NpdGlvbkluZGV4OwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHBvbHlsaW5lVm9sdW1lQ291bnQ7IGorKykgewogICAgICAgIGNvbnN0IHZvbHVtZVN0YXJ0ID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjaygKICAgICAgICAgIHBvc2l0aW9uc1JUQywKICAgICAgICAgIGN1cnJlbnRQb3NpdGlvbkluZGV4LAogICAgICAgICAgc2NyYXRjaFAwCiAgICAgICAgKTsKICAgICAgICBjb25zdCB2b2x1bWVFbmQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgcG9zaXRpb25zUlRDLAogICAgICAgICAgY3VycmVudFBvc2l0aW9uSW5kZXggKyAzLAogICAgICAgICAgc2NyYXRjaFAxCiAgICAgICAgKTsKICAgICAgICBsZXQgc3RhcnRIZWlnaHQgPSBoZWlnaHRCdWZmZXJbY3VycmVudEhlaWdodEluZGV4XTsKICAgICAgICBsZXQgZW5kSGVpZ2h0ID0gaGVpZ2h0QnVmZmVyW2N1cnJlbnRIZWlnaHRJbmRleCArIDFdOwogICAgICAgIHN0YXJ0SGVpZ2h0ID0gTWF0aF9kZWZhdWx0LmxlcnAoCiAgICAgICAgICBtaW5pbXVtSGVpZ2h0LAogICAgICAgICAgbWF4aW11bUhlaWdodCwKICAgICAgICAgIHN0YXJ0SGVpZ2h0IC8gTUFYX1NIT1JUCiAgICAgICAgKTsKICAgICAgICBlbmRIZWlnaHQgPSBNYXRoX2RlZmF1bHQubGVycCgKICAgICAgICAgIG1pbmltdW1IZWlnaHQsCiAgICAgICAgICBtYXhpbXVtSGVpZ2h0LAogICAgICAgICAgZW5kSGVpZ2h0IC8gTUFYX1NIT1JUCiAgICAgICAgKTsKICAgICAgICBjdXJyZW50SGVpZ2h0SW5kZXgrKzsKICAgICAgICBsZXQgcHJlU3RhcnQgPSBzY3JhdGNoUHJldjsKICAgICAgICBsZXQgcG9zdEVuZCA9IHNjcmF0Y2hOZXh0OwogICAgICAgIGlmIChqID09PSAwKSB7CiAgICAgICAgICBjb25zdCBmaW5hbFBvc2l0aW9uSW5kZXggPSB2b2x1bWVGaXJzdFBvc2l0aW9uSW5kZXggKyBwb2x5bGluZVZvbHVtZUNvdW50ICogMzsKICAgICAgICAgIGNvbnN0IGZpbmFsUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgICBwb3NpdGlvbnNSVEMsCiAgICAgICAgICAgIGZpbmFsUG9zaXRpb25JbmRleCwKICAgICAgICAgICAgc2NyYXRjaFByZXYKICAgICAgICAgICk7CiAgICAgICAgICBpZiAoQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFscyhmaW5hbFBvc2l0aW9uLCB2b2x1bWVTdGFydCkpIHsKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjayhwb3NpdGlvbnNSVEMsIGZpbmFsUG9zaXRpb25JbmRleCAtIDMsIHByZVN0YXJ0KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGNvbnN0IG9mZnNldFBhc3RTdGFydCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgICAgICAgICB2b2x1bWVTdGFydCwKICAgICAgICAgICAgICB2b2x1bWVFbmQsCiAgICAgICAgICAgICAgc2NyYXRjaFByZXYKICAgICAgICAgICAgKTsKICAgICAgICAgICAgcHJlU3RhcnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKG9mZnNldFBhc3RTdGFydCwgdm9sdW1lU3RhcnQsIHNjcmF0Y2hQcmV2KTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjayhwb3NpdGlvbnNSVEMsIGN1cnJlbnRQb3NpdGlvbkluZGV4IC0gMywgcHJlU3RhcnQpOwogICAgICAgIH0KICAgICAgICBpZiAoaiA9PT0gcG9seWxpbmVWb2x1bWVDb3VudCAtIDEpIHsKICAgICAgICAgIGNvbnN0IGZpcnN0UG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgICBwb3NpdGlvbnNSVEMsCiAgICAgICAgICAgIHZvbHVtZUZpcnN0UG9zaXRpb25JbmRleCwKICAgICAgICAgICAgc2NyYXRjaE5leHQKICAgICAgICAgICk7CiAgICAgICAgICBpZiAoQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFscyhmaXJzdFBvc2l0aW9uLCB2b2x1bWVFbmQpKSB7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICAgICAgcG9zaXRpb25zUlRDLAogICAgICAgICAgICAgIHZvbHVtZUZpcnN0UG9zaXRpb25JbmRleCArIDMsCiAgICAgICAgICAgICAgcG9zdEVuZAogICAgICAgICAgICApOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgY29uc3Qgb2Zmc2V0UGFzdEVuZCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgICAgICAgICB2b2x1bWVFbmQsCiAgICAgICAgICAgICAgdm9sdW1lU3RhcnQsCiAgICAgICAgICAgICAgc2NyYXRjaE5leHQKICAgICAgICAgICAgKTsKICAgICAgICAgICAgcG9zdEVuZCA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQob2Zmc2V0UGFzdEVuZCwgdm9sdW1lRW5kLCBzY3JhdGNoTmV4dCk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2socG9zaXRpb25zUlRDLCBjdXJyZW50UG9zaXRpb25JbmRleCArIDYsIHBvc3RFbmQpOwogICAgICAgIH0KICAgICAgICBhdHRyaWJzQW5kSW5kaWNlcy5hZGRWb2x1bWUoCiAgICAgICAgICBwcmVTdGFydCwKICAgICAgICAgIHZvbHVtZVN0YXJ0LAogICAgICAgICAgdm9sdW1lRW5kLAogICAgICAgICAgcG9zdEVuZCwKICAgICAgICAgIHN0YXJ0SGVpZ2h0LAogICAgICAgICAgZW5kSGVpZ2h0LAogICAgICAgICAgaGFsZldpZHRoLAogICAgICAgICAgYmF0Y2hJZCwKICAgICAgICAgIGNlbnRlciwKICAgICAgICAgIGVsbGlwc29pZAogICAgICAgICk7CiAgICAgICAgY3VycmVudFBvc2l0aW9uSW5kZXggKz0gMzsKICAgICAgfQogICAgICBjdXJyZW50UG9zaXRpb25JbmRleCArPSAzOwogICAgICBjdXJyZW50SGVpZ2h0SW5kZXgrKzsKICAgIH0KICAgIGNvbnN0IGluZGljZXMgPSBhdHRyaWJzQW5kSW5kaWNlcy5pbmRpY2VzOwogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKGF0dHJpYnNBbmRJbmRpY2VzLnN0YXJ0RWxsaXBzb2lkTm9ybWFscy5idWZmZXIpOwogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKGF0dHJpYnNBbmRJbmRpY2VzLmVuZEVsbGlwc29pZE5vcm1hbHMuYnVmZmVyKTsKICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaChhdHRyaWJzQW5kSW5kaWNlcy5zdGFydFBvc2l0aW9uQW5kSGVpZ2h0cy5idWZmZXIpOwogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKAogICAgICBhdHRyaWJzQW5kSW5kaWNlcy5zdGFydEZhY2VOb3JtYWxBbmRWZXJ0ZXhDb3JuZXJJZHMuYnVmZmVyCiAgICApOwogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKGF0dHJpYnNBbmRJbmRpY2VzLmVuZFBvc2l0aW9uQW5kSGVpZ2h0cy5idWZmZXIpOwogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKGF0dHJpYnNBbmRJbmRpY2VzLmVuZEZhY2VOb3JtYWxBbmRIYWxmV2lkdGhzLmJ1ZmZlcik7CiAgICB0cmFuc2ZlcmFibGVPYmplY3RzLnB1c2goYXR0cmlic0FuZEluZGljZXMudmVydGV4QmF0Y2hJZHMuYnVmZmVyKTsKICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaChpbmRpY2VzLmJ1ZmZlcik7CiAgICBsZXQgcmVzdWx0cyA9IHsKICAgICAgaW5kZXhEYXRhdHlwZTogaW5kaWNlcy5CWVRFU19QRVJfRUxFTUVOVCA9PT0gMiA/IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9TSE9SVCA6IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9JTlQsCiAgICAgIHN0YXJ0RWxsaXBzb2lkTm9ybWFsczogYXR0cmlic0FuZEluZGljZXMuc3RhcnRFbGxpcHNvaWROb3JtYWxzLmJ1ZmZlciwKICAgICAgZW5kRWxsaXBzb2lkTm9ybWFsczogYXR0cmlic0FuZEluZGljZXMuZW5kRWxsaXBzb2lkTm9ybWFscy5idWZmZXIsCiAgICAgIHN0YXJ0UG9zaXRpb25BbmRIZWlnaHRzOiBhdHRyaWJzQW5kSW5kaWNlcy5zdGFydFBvc2l0aW9uQW5kSGVpZ2h0cy5idWZmZXIsCiAgICAgIHN0YXJ0RmFjZU5vcm1hbEFuZFZlcnRleENvcm5lcklkczogYXR0cmlic0FuZEluZGljZXMuc3RhcnRGYWNlTm9ybWFsQW5kVmVydGV4Q29ybmVySWRzLmJ1ZmZlciwKICAgICAgZW5kUG9zaXRpb25BbmRIZWlnaHRzOiBhdHRyaWJzQW5kSW5kaWNlcy5lbmRQb3NpdGlvbkFuZEhlaWdodHMuYnVmZmVyLAogICAgICBlbmRGYWNlTm9ybWFsQW5kSGFsZldpZHRoczogYXR0cmlic0FuZEluZGljZXMuZW5kRmFjZU5vcm1hbEFuZEhhbGZXaWR0aHMuYnVmZmVyLAogICAgICB2ZXJ0ZXhCYXRjaElkczogYXR0cmlic0FuZEluZGljZXMudmVydGV4QmF0Y2hJZHMuYnVmZmVyLAogICAgICBpbmRpY2VzOiBpbmRpY2VzLmJ1ZmZlcgogICAgfTsKICAgIGlmIChwYXJhbWV0ZXJzLmtlZXBEZWNvZGVkUG9zaXRpb25zKSB7CiAgICAgIGNvbnN0IHBvc2l0aW9uT2Zmc2V0cyA9IGdldFBvc2l0aW9uT2Zmc2V0cyhjb3VudHMpOwogICAgICB0cmFuc2ZlcmFibGVPYmplY3RzLnB1c2gocG9zaXRpb25zLmJ1ZmZlciwgcG9zaXRpb25PZmZzZXRzLmJ1ZmZlcik7CiAgICAgIHJlc3VsdHMgPSBjb21iaW5lX2RlZmF1bHQocmVzdWx0cywgewogICAgICAgIGRlY29kZWRQb3NpdGlvbnM6IHBvc2l0aW9ucy5idWZmZXIsCiAgICAgICAgZGVjb2RlZFBvc2l0aW9uT2Zmc2V0czogcG9zaXRpb25PZmZzZXRzLmJ1ZmZlcgogICAgICB9KTsKICAgIH0KICAgIHJldHVybiByZXN1bHRzOwogIH0KICB2YXIgTUFYX1NIT1JULCBNSVRFUl9CUkVBSywgc2NyYXRjaEJWQ2FydG9ncmFwaGljLCBzY3JhdGNoRW5jb2RlZFBvc2l0aW9uLCBwcmV2aW91c0NvbXByZXNzZWRDYXJ0b2dyYXBoaWNTY3JhdGNoLCBjdXJyZW50Q29tcHJlc3NlZENhcnRvZ3JhcGhpY1NjcmF0Y2gsIHRvd2FyZEN1cnJTY3JhdGNoLCB0b3dhcmROZXh0U2NyYXRjaCwgUkVGRVJFTkNFX0lORElDRVMyLCBSRUZFUkVOQ0VfSU5ESUNFU19MRU5HVEgyLCBwb3NpdGlvblNjcmF0Y2g0LCBzY3JhdGNoU3RhcnRFbGxpcHNvaWROb3JtYWwsIHNjcmF0Y2hTdGFydEZhY2VOb3JtYWwsIHNjcmF0Y2hFbmRFbGxpcHNvaWROb3JtYWwsIHNjcmF0Y2hFbmRGYWNlTm9ybWFsLCBzY3JhdGNoUmVjdGFuZ2xlMywgc2NyYXRjaEVsbGlwc29pZDEzLCBzY3JhdGNoQ2VudGVyNCwgc2NyYXRjaFByZXYsIHNjcmF0Y2hQMCwgc2NyYXRjaFAxLCBzY3JhdGNoTmV4dCwgY3JlYXRlVmVjdG9yVGlsZUNsYW1wZWRQb2x5bGluZXNfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVWZWN0b3JUaWxlQ2xhbXBlZFBvbHlsaW5lcyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlVmVjdG9yVGlsZUNsYW1wZWRQb2x5bGluZXMuanMiKCkgewogICAgICBpbml0X0F0dHJpYnV0ZUNvbXByZXNzaW9uKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X2NvbWJpbmUoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1JlY3RhbmdsZSgpOwogICAgICBpbml0X2NyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXIoKTsKICAgICAgTUFYX1NIT1JUID0gMzI3Njc7CiAgICAgIE1JVEVSX0JSRUFLID0gTWF0aC5jb3MoTWF0aF9kZWZhdWx0LnRvUmFkaWFucygxNTApKTsKICAgICAgc2NyYXRjaEJWQ2FydG9ncmFwaGljID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hFbmNvZGVkUG9zaXRpb24gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHByZXZpb3VzQ29tcHJlc3NlZENhcnRvZ3JhcGhpY1NjcmF0Y2ggPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgY3VycmVudENvbXByZXNzZWRDYXJ0b2dyYXBoaWNTY3JhdGNoID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHRvd2FyZEN1cnJTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICB0b3dhcmROZXh0U2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgUkVGRVJFTkNFX0lORElDRVMyID0gWwogICAgICAgIDAsCiAgICAgICAgMiwKICAgICAgICA2LAogICAgICAgIDAsCiAgICAgICAgNiwKICAgICAgICA0LAogICAgICAgIC8vIHJpZ2h0CiAgICAgICAgMCwKICAgICAgICAxLAogICAgICAgIDMsCiAgICAgICAgMCwKICAgICAgICAzLAogICAgICAgIDIsCiAgICAgICAgLy8gc3RhcnQgZmFjZQogICAgICAgIDAsCiAgICAgICAgNCwKICAgICAgICA1LAogICAgICAgIDAsCiAgICAgICAgNSwKICAgICAgICAxLAogICAgICAgIC8vIGJvdHRvbQogICAgICAgIDUsCiAgICAgICAgMywKICAgICAgICAxLAogICAgICAgIDUsCiAgICAgICAgNywKICAgICAgICAzLAogICAgICAgIC8vIGxlZnQKICAgICAgICA3LAogICAgICAgIDUsCiAgICAgICAgNCwKICAgICAgICA3LAogICAgICAgIDQsCiAgICAgICAgNiwKICAgICAgICAvLyBlbmQgZmFjZQogICAgICAgIDcsCiAgICAgICAgNiwKICAgICAgICAyLAogICAgICAgIDcsCiAgICAgICAgMiwKICAgICAgICAzCiAgICAgICAgLy8gdG9wCiAgICAgIF07CiAgICAgIFJFRkVSRU5DRV9JTkRJQ0VTX0xFTkdUSDIgPSBSRUZFUkVOQ0VfSU5ESUNFUzIubGVuZ3RoOwogICAgICBwb3NpdGlvblNjcmF0Y2g0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoU3RhcnRFbGxpcHNvaWROb3JtYWwgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hTdGFydEZhY2VOb3JtYWwgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hFbmRFbGxpcHNvaWROb3JtYWwgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hFbmRGYWNlTm9ybWFsID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBWZXJ0ZXhBdHRyaWJ1dGVzQW5kSW5kaWNlcy5wcm90b3R5cGUuYWRkVm9sdW1lID0gZnVuY3Rpb24ocHJlU3RhcnRSVEMsIHN0YXJ0UlRDLCBlbmRSVEMsIHBvc3RFbmRSVEMsIHN0YXJ0SGVpZ2h0LCBlbmRIZWlnaHQsIGhhbGZXaWR0aCwgYmF0Y2hJZCwgY2VudGVyLCBlbGxpcHNvaWQpIHsKICAgICAgICBsZXQgcG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHN0YXJ0UlRDLCBjZW50ZXIsIHBvc2l0aW9uU2NyYXRjaDQpOwogICAgICAgIGNvbnN0IHN0YXJ0RWxsaXBzb2lkTm9ybWFsID0gZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbCgKICAgICAgICAgIHBvc2l0aW9uLAogICAgICAgICAgc2NyYXRjaFN0YXJ0RWxsaXBzb2lkTm9ybWFsCiAgICAgICAgKTsKICAgICAgICBwb3NpdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoZW5kUlRDLCBjZW50ZXIsIHBvc2l0aW9uU2NyYXRjaDQpOwogICAgICAgIGNvbnN0IGVuZEVsbGlwc29pZE5vcm1hbCA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwoCiAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgIHNjcmF0Y2hFbmRFbGxpcHNvaWROb3JtYWwKICAgICAgICApOwogICAgICAgIGNvbnN0IHN0YXJ0RmFjZU5vcm1hbCA9IGNvbXB1dGVNaXRlcmVkTm9ybWFsKAogICAgICAgICAgcHJlU3RhcnRSVEMsCiAgICAgICAgICBzdGFydFJUQywKICAgICAgICAgIGVuZFJUQywKICAgICAgICAgIHN0YXJ0RWxsaXBzb2lkTm9ybWFsLAogICAgICAgICAgc2NyYXRjaFN0YXJ0RmFjZU5vcm1hbAogICAgICAgICk7CiAgICAgICAgY29uc3QgZW5kRmFjZU5vcm1hbCA9IGNvbXB1dGVNaXRlcmVkTm9ybWFsKAogICAgICAgICAgcG9zdEVuZFJUQywKICAgICAgICAgIGVuZFJUQywKICAgICAgICAgIHN0YXJ0UlRDLAogICAgICAgICAgZW5kRWxsaXBzb2lkTm9ybWFsLAogICAgICAgICAgc2NyYXRjaEVuZEZhY2VOb3JtYWwKICAgICAgICApOwogICAgICAgIGNvbnN0IHN0YXJ0RWxsaXBzb2lkTm9ybWFscyA9IHRoaXMuc3RhcnRFbGxpcHNvaWROb3JtYWxzOwogICAgICAgIGNvbnN0IGVuZEVsbGlwc29pZE5vcm1hbHMgPSB0aGlzLmVuZEVsbGlwc29pZE5vcm1hbHM7CiAgICAgICAgY29uc3Qgc3RhcnRQb3NpdGlvbkFuZEhlaWdodHMgPSB0aGlzLnN0YXJ0UG9zaXRpb25BbmRIZWlnaHRzOwogICAgICAgIGNvbnN0IHN0YXJ0RmFjZU5vcm1hbEFuZFZlcnRleENvcm5lcklkcyA9IHRoaXMuc3RhcnRGYWNlTm9ybWFsQW5kVmVydGV4Q29ybmVySWRzOwogICAgICAgIGNvbnN0IGVuZFBvc2l0aW9uQW5kSGVpZ2h0cyA9IHRoaXMuZW5kUG9zaXRpb25BbmRIZWlnaHRzOwogICAgICAgIGNvbnN0IGVuZEZhY2VOb3JtYWxBbmRIYWxmV2lkdGhzID0gdGhpcy5lbmRGYWNlTm9ybWFsQW5kSGFsZldpZHRoczsKICAgICAgICBjb25zdCB2ZXJ0ZXhCYXRjaElkcyA9IHRoaXMudmVydGV4QmF0Y2hJZHM7CiAgICAgICAgbGV0IGJhdGNoSWRPZmZzZXQgPSB0aGlzLmJhdGNoSWRPZmZzZXQ7CiAgICAgICAgbGV0IHZlYzNPZmZzZXQgPSB0aGlzLnZlYzNPZmZzZXQ7CiAgICAgICAgbGV0IHZlYzRPZmZzZXQgPSB0aGlzLnZlYzRPZmZzZXQ7CiAgICAgICAgbGV0IGk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IDg7IGkrKykgewogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soc3RhcnRFbGxpcHNvaWROb3JtYWwsIHN0YXJ0RWxsaXBzb2lkTm9ybWFscywgdmVjM09mZnNldCk7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhlbmRFbGxpcHNvaWROb3JtYWwsIGVuZEVsbGlwc29pZE5vcm1hbHMsIHZlYzNPZmZzZXQpOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soc3RhcnRSVEMsIHN0YXJ0UG9zaXRpb25BbmRIZWlnaHRzLCB2ZWM0T2Zmc2V0KTsKICAgICAgICAgIHN0YXJ0UG9zaXRpb25BbmRIZWlnaHRzW3ZlYzRPZmZzZXQgKyAzXSA9IHN0YXJ0SGVpZ2h0OwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soZW5kUlRDLCBlbmRQb3NpdGlvbkFuZEhlaWdodHMsIHZlYzRPZmZzZXQpOwogICAgICAgICAgZW5kUG9zaXRpb25BbmRIZWlnaHRzW3ZlYzRPZmZzZXQgKyAzXSA9IGVuZEhlaWdodDsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKAogICAgICAgICAgICBzdGFydEZhY2VOb3JtYWwsCiAgICAgICAgICAgIHN0YXJ0RmFjZU5vcm1hbEFuZFZlcnRleENvcm5lcklkcywKICAgICAgICAgICAgdmVjNE9mZnNldAogICAgICAgICAgKTsKICAgICAgICAgIHN0YXJ0RmFjZU5vcm1hbEFuZFZlcnRleENvcm5lcklkc1t2ZWM0T2Zmc2V0ICsgM10gPSBpOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soZW5kRmFjZU5vcm1hbCwgZW5kRmFjZU5vcm1hbEFuZEhhbGZXaWR0aHMsIHZlYzRPZmZzZXQpOwogICAgICAgICAgZW5kRmFjZU5vcm1hbEFuZEhhbGZXaWR0aHNbdmVjNE9mZnNldCArIDNdID0gaGFsZldpZHRoOwogICAgICAgICAgdmVydGV4QmF0Y2hJZHNbYmF0Y2hJZE9mZnNldCsrXSA9IGJhdGNoSWQ7CiAgICAgICAgICB2ZWMzT2Zmc2V0ICs9IDM7CiAgICAgICAgICB2ZWM0T2Zmc2V0ICs9IDQ7CiAgICAgICAgfQogICAgICAgIHRoaXMuYmF0Y2hJZE9mZnNldCA9IGJhdGNoSWRPZmZzZXQ7CiAgICAgICAgdGhpcy52ZWMzT2Zmc2V0ID0gdmVjM09mZnNldDsKICAgICAgICB0aGlzLnZlYzRPZmZzZXQgPSB2ZWM0T2Zmc2V0OwogICAgICAgIGNvbnN0IGluZGljZXMgPSB0aGlzLmluZGljZXM7CiAgICAgICAgY29uc3Qgdm9sdW1lU3RhcnRJbmRleCA9IHRoaXMudm9sdW1lU3RhcnRJbmRleDsKICAgICAgICBjb25zdCBpbmRleE9mZnNldCA9IHRoaXMuaW5kZXhPZmZzZXQ7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IFJFRkVSRU5DRV9JTkRJQ0VTX0xFTkdUSDI7IGkrKykgewogICAgICAgICAgaW5kaWNlc1tpbmRleE9mZnNldCArIGldID0gUkVGRVJFTkNFX0lORElDRVMyW2ldICsgdm9sdW1lU3RhcnRJbmRleDsKICAgICAgICB9CiAgICAgICAgdGhpcy52b2x1bWVTdGFydEluZGV4ICs9IDg7CiAgICAgICAgdGhpcy5pbmRleE9mZnNldCArPSBSRUZFUkVOQ0VfSU5ESUNFU19MRU5HVEgyOwogICAgICB9OwogICAgICBzY3JhdGNoUmVjdGFuZ2xlMyA9IG5ldyBSZWN0YW5nbGVfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoRWxsaXBzb2lkMTMgPSBuZXcgRWxsaXBzb2lkX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENlbnRlcjQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQcmV2ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUDAgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hQMSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE5leHQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNyZWF0ZVZlY3RvclRpbGVDbGFtcGVkUG9seWxpbmVzX2RlZmF1bHQgPSBjcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyX2RlZmF1bHQoY3JlYXRlVmVjdG9yVGlsZUNsYW1wZWRQb2x5bGluZXMpOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1NjZW5lL1ZlY3RvcjNEVGlsZUJhdGNoLmpzCiAgZnVuY3Rpb24gVmVjdG9yM0RUaWxlQmF0Y2gob3B0aW9ucykgewogICAgdGhpcy5vZmZzZXQgPSBvcHRpb25zLm9mZnNldDsKICAgIHRoaXMuY291bnQgPSBvcHRpb25zLmNvdW50OwogICAgdGhpcy5jb2xvciA9IG9wdGlvbnMuY29sb3I7CiAgICB0aGlzLmJhdGNoSWRzID0gb3B0aW9ucy5iYXRjaElkczsKICB9CiAgdmFyIFZlY3RvcjNEVGlsZUJhdGNoX2RlZmF1bHQ7CiAgdmFyIGluaXRfVmVjdG9yM0RUaWxlQmF0Y2ggPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9TY2VuZS9WZWN0b3IzRFRpbGVCYXRjaC5qcyIoKSB7CiAgICAgIFZlY3RvcjNEVGlsZUJhdGNoX2RlZmF1bHQgPSBWZWN0b3IzRFRpbGVCYXRjaDsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVZlY3RvclRpbGVHZW9tZXRyaWVzLmpzCiAgdmFyIGNyZWF0ZVZlY3RvclRpbGVHZW9tZXRyaWVzX2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChjcmVhdGVWZWN0b3JUaWxlR2VvbWV0cmllc19leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVWZWN0b3JUaWxlR2VvbWV0cmllc19kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gYm94TW9kZWxNYXRyaXhBbmRCb3VuZGluZ1ZvbHVtZShib3hlcywgaW5kZXgpIHsKICAgIGxldCBib3hJbmRleCA9IGluZGV4ICogcGFja2VkQm94TGVuZ3RoOwogICAgY29uc3QgZGltZW5zaW9ucyA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soYm94ZXMsIGJveEluZGV4LCBzY3JhdGNoQ2FydGVzaWFuMTEpOwogICAgYm94SW5kZXggKz0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgIGNvbnN0IGJveE1vZGVsTWF0cml4ID0gTWF0cml4NF9kZWZhdWx0LnVucGFjaygKICAgICAgYm94ZXMsCiAgICAgIGJveEluZGV4LAogICAgICBzY3JhdGNoTW9kZWxNYXRyaXhBbmRCVi5tb2RlbE1hdHJpeAogICAgKTsKICAgIE1hdHJpeDRfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGUoYm94TW9kZWxNYXRyaXgsIGRpbWVuc2lvbnMsIGJveE1vZGVsTWF0cml4KTsKICAgIGNvbnN0IGJvdW5kaW5nVm9sdW1lID0gc2NyYXRjaE1vZGVsTWF0cml4QW5kQlYuYm91bmRpbmdWb2x1bWU7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sIGJvdW5kaW5nVm9sdW1lLmNlbnRlcik7CiAgICBib3VuZGluZ1ZvbHVtZS5yYWRpdXMgPSBNYXRoLnNxcnQoMyk7CiAgICByZXR1cm4gc2NyYXRjaE1vZGVsTWF0cml4QW5kQlY7CiAgfQogIGZ1bmN0aW9uIGN5bGluZGVyTW9kZWxNYXRyaXhBbmRCb3VuZGluZ1ZvbHVtZShjeWxpbmRlcnMsIGluZGV4KSB7CiAgICBsZXQgY3lsaW5kZXJJbmRleCA9IGluZGV4ICogcGFja2VkQ3lsaW5kZXJMZW5ndGg7CiAgICBjb25zdCBjeWxpbmRlclJhZGl1cyA9IGN5bGluZGVyc1tjeWxpbmRlckluZGV4KytdOwogICAgY29uc3QgbGVuZ3RoID0gY3lsaW5kZXJzW2N5bGluZGVySW5kZXgrK107CiAgICBjb25zdCBzY2FsZSA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tRWxlbWVudHMoCiAgICAgIGN5bGluZGVyUmFkaXVzLAogICAgICBjeWxpbmRlclJhZGl1cywKICAgICAgbGVuZ3RoLAogICAgICBzY3JhdGNoQ2FydGVzaWFuMTEKICAgICk7CiAgICBjb25zdCBjeWxpbmRlck1vZGVsTWF0cml4ID0gTWF0cml4NF9kZWZhdWx0LnVucGFjaygKICAgICAgY3lsaW5kZXJzLAogICAgICBjeWxpbmRlckluZGV4LAogICAgICBzY3JhdGNoTW9kZWxNYXRyaXhBbmRCVi5tb2RlbE1hdHJpeAogICAgKTsKICAgIE1hdHJpeDRfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGUoY3lsaW5kZXJNb2RlbE1hdHJpeCwgc2NhbGUsIGN5bGluZGVyTW9kZWxNYXRyaXgpOwogICAgY29uc3QgYm91bmRpbmdWb2x1bWUgPSBzY3JhdGNoTW9kZWxNYXRyaXhBbmRCVi5ib3VuZGluZ1ZvbHVtZTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywgYm91bmRpbmdWb2x1bWUuY2VudGVyKTsKICAgIGJvdW5kaW5nVm9sdW1lLnJhZGl1cyA9IE1hdGguc3FydCgyKTsKICAgIHJldHVybiBzY3JhdGNoTW9kZWxNYXRyaXhBbmRCVjsKICB9CiAgZnVuY3Rpb24gZWxsaXBzb2lkTW9kZWxNYXRyaXhBbmRCb3VuZGluZ1ZvbHVtZShlbGxpcHNvaWRzLCBpbmRleCkgewogICAgbGV0IGVsbGlwc29pZEluZGV4ID0gaW5kZXggKiBwYWNrZWRFbGxpcHNvaWRMZW5ndGg7CiAgICBjb25zdCByYWRpaSA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soZWxsaXBzb2lkcywgZWxsaXBzb2lkSW5kZXgsIHNjcmF0Y2hDYXJ0ZXNpYW4xMSk7CiAgICBlbGxpcHNvaWRJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgY29uc3QgZWxsaXBzb2lkTW9kZWxNYXRyaXggPSBNYXRyaXg0X2RlZmF1bHQudW5wYWNrKAogICAgICBlbGxpcHNvaWRzLAogICAgICBlbGxpcHNvaWRJbmRleCwKICAgICAgc2NyYXRjaE1vZGVsTWF0cml4QW5kQlYubW9kZWxNYXRyaXgKICAgICk7CiAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlCeVNjYWxlKGVsbGlwc29pZE1vZGVsTWF0cml4LCByYWRpaSwgZWxsaXBzb2lkTW9kZWxNYXRyaXgpOwogICAgY29uc3QgYm91bmRpbmdWb2x1bWUgPSBzY3JhdGNoTW9kZWxNYXRyaXhBbmRCVi5ib3VuZGluZ1ZvbHVtZTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywgYm91bmRpbmdWb2x1bWUuY2VudGVyKTsKICAgIGJvdW5kaW5nVm9sdW1lLnJhZGl1cyA9IDE7CiAgICByZXR1cm4gc2NyYXRjaE1vZGVsTWF0cml4QW5kQlY7CiAgfQogIGZ1bmN0aW9uIHNwaGVyZU1vZGVsTWF0cml4QW5kQm91bmRpbmdWb2x1bWUoc3BoZXJlcywgaW5kZXgpIHsKICAgIGxldCBzcGhlcmVJbmRleCA9IGluZGV4ICogcGFja2VkU3BoZXJlTGVuZ3RoOwogICAgY29uc3Qgc3BoZXJlUmFkaXVzID0gc3BoZXJlc1tzcGhlcmVJbmRleCsrXTsKICAgIGNvbnN0IHNwaGVyZVRyYW5zbGF0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjaygKICAgICAgc3BoZXJlcywKICAgICAgc3BoZXJlSW5kZXgsCiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4xMQogICAgKTsKICAgIGNvbnN0IHNwaGVyZU1vZGVsTWF0cml4ID0gTWF0cml4NF9kZWZhdWx0LmZyb21UcmFuc2xhdGlvbigKICAgICAgc3BoZXJlVHJhbnNsYXRpb24sCiAgICAgIHNjcmF0Y2hNb2RlbE1hdHJpeEFuZEJWLm1vZGVsTWF0cml4CiAgICApOwogICAgTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5QnlVbmlmb3JtU2NhbGUoCiAgICAgIHNwaGVyZU1vZGVsTWF0cml4LAogICAgICBzcGhlcmVSYWRpdXMsCiAgICAgIHNwaGVyZU1vZGVsTWF0cml4CiAgICApOwogICAgY29uc3QgYm91bmRpbmdWb2x1bWUgPSBzY3JhdGNoTW9kZWxNYXRyaXhBbmRCVi5ib3VuZGluZ1ZvbHVtZTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywgYm91bmRpbmdWb2x1bWUuY2VudGVyKTsKICAgIGJvdW5kaW5nVm9sdW1lLnJhZGl1cyA9IDE7CiAgICByZXR1cm4gc2NyYXRjaE1vZGVsTWF0cml4QW5kQlY7CiAgfQogIGZ1bmN0aW9uIGNyZWF0ZVByaW1pdGl2ZShvcHRpb25zLCBwcmltaXRpdmUsIHByaW1pdGl2ZUJhdGNoSWRzLCBnZW9tZXRyeSwgZ2V0TW9kZWxNYXRyaXhBbmRCb3VuZGluZ1ZvbHVtZSkgewogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocHJpbWl0aXZlKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBudW1iZXJPZlByaW1pdGl2ZXMgPSBwcmltaXRpdmVCYXRjaElkcy5sZW5ndGg7CiAgICBjb25zdCBnZW9tZXRyeVBvc2l0aW9ucyA9IGdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzOwogICAgY29uc3QgZ2VvbWV0cnlJbmRpY2VzID0gZ2VvbWV0cnkuaW5kaWNlczsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IG9wdGlvbnMucG9zaXRpb25zOwogICAgY29uc3QgdmVydGV4QmF0Y2hJZHMgPSBvcHRpb25zLnZlcnRleEJhdGNoSWRzOwogICAgY29uc3QgaW5kaWNlcyA9IG9wdGlvbnMuaW5kaWNlczsKICAgIGNvbnN0IGJhdGNoSWRzID0gb3B0aW9ucy5iYXRjaElkczsKICAgIGNvbnN0IGJhdGNoVGFibGVDb2xvcnMgPSBvcHRpb25zLmJhdGNoVGFibGVDb2xvcnM7CiAgICBjb25zdCBiYXRjaGVkSW5kaWNlcyA9IG9wdGlvbnMuYmF0Y2hlZEluZGljZXM7CiAgICBjb25zdCBpbmRleE9mZnNldHMgPSBvcHRpb25zLmluZGV4T2Zmc2V0czsKICAgIGNvbnN0IGluZGV4Q291bnRzID0gb3B0aW9ucy5pbmRleENvdW50czsKICAgIGNvbnN0IGJvdW5kaW5nVm9sdW1lcyA9IG9wdGlvbnMuYm91bmRpbmdWb2x1bWVzOwogICAgY29uc3QgbW9kZWxNYXRyaXggPSBvcHRpb25zLm1vZGVsTWF0cml4OwogICAgY29uc3QgY2VudGVyID0gb3B0aW9ucy5jZW50ZXI7CiAgICBsZXQgcG9zaXRpb25PZmZzZXQgPSBvcHRpb25zLnBvc2l0aW9uT2Zmc2V0OwogICAgbGV0IGJhdGNoSWRJbmRleCA9IG9wdGlvbnMuYmF0Y2hJZEluZGV4OwogICAgbGV0IGluZGV4T2Zmc2V0ID0gb3B0aW9ucy5pbmRleE9mZnNldDsKICAgIGNvbnN0IGJhdGNoZWRJbmRpY2VzT2Zmc2V0ID0gb3B0aW9ucy5iYXRjaGVkSW5kaWNlc09mZnNldDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZQcmltaXRpdmVzOyArK2kpIHsKICAgICAgY29uc3QgcHJpbWl0aXZlTW9kZWxNYXRyaXhBbmRCViA9IGdldE1vZGVsTWF0cml4QW5kQm91bmRpbmdWb2x1bWUoCiAgICAgICAgcHJpbWl0aXZlLAogICAgICAgIGkKICAgICAgKTsKICAgICAgY29uc3QgcHJpbWl0aXZlTW9kZWxNYXRyaXggPSBwcmltaXRpdmVNb2RlbE1hdHJpeEFuZEJWLm1vZGVsTWF0cml4OwogICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHkobW9kZWxNYXRyaXgsIHByaW1pdGl2ZU1vZGVsTWF0cml4LCBwcmltaXRpdmVNb2RlbE1hdHJpeCk7CiAgICAgIGNvbnN0IGJhdGNoSWQgPSBwcmltaXRpdmVCYXRjaElkc1tpXTsKICAgICAgY29uc3QgcG9zaXRpb25zTGVuZ3RoID0gZ2VvbWV0cnlQb3NpdGlvbnMubGVuZ3RoOwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHBvc2l0aW9uc0xlbmd0aDsgaiArPSAzKSB7CiAgICAgICAgY29uc3QgcG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKGdlb21ldHJ5UG9zaXRpb25zLCBqLCBzY3JhdGNoUG9zaXRpb241KTsKICAgICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlCeVBvaW50KHByaW1pdGl2ZU1vZGVsTWF0cml4LCBwb3NpdGlvbiwgcG9zaXRpb24pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChwb3NpdGlvbiwgY2VudGVyLCBwb3NpdGlvbik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2socG9zaXRpb24sIHBvc2l0aW9ucywgcG9zaXRpb25PZmZzZXQgKiAzICsgaik7CiAgICAgICAgdmVydGV4QmF0Y2hJZHNbYmF0Y2hJZEluZGV4KytdID0gYmF0Y2hJZDsKICAgICAgfQogICAgICBjb25zdCBpbmRpY2VzTGVuZ3RoID0gZ2VvbWV0cnlJbmRpY2VzLmxlbmd0aDsKICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCBpbmRpY2VzTGVuZ3RoOyArK2spIHsKICAgICAgICBpbmRpY2VzW2luZGV4T2Zmc2V0ICsga10gPSBnZW9tZXRyeUluZGljZXNba10gKyBwb3NpdGlvbk9mZnNldDsKICAgICAgfQogICAgICBjb25zdCBvZmZzZXQgPSBpICsgYmF0Y2hlZEluZGljZXNPZmZzZXQ7CiAgICAgIGJhdGNoZWRJbmRpY2VzW29mZnNldF0gPSBuZXcgVmVjdG9yM0RUaWxlQmF0Y2hfZGVmYXVsdCh7CiAgICAgICAgb2Zmc2V0OiBpbmRleE9mZnNldCwKICAgICAgICBjb3VudDogaW5kaWNlc0xlbmd0aCwKICAgICAgICBjb2xvcjogQ29sb3JfZGVmYXVsdC5mcm9tUmdiYShiYXRjaFRhYmxlQ29sb3JzW2JhdGNoSWRdKSwKICAgICAgICBiYXRjaElkczogW2JhdGNoSWRdCiAgICAgIH0pOwogICAgICBiYXRjaElkc1tvZmZzZXRdID0gYmF0Y2hJZDsKICAgICAgaW5kZXhPZmZzZXRzW29mZnNldF0gPSBpbmRleE9mZnNldDsKICAgICAgaW5kZXhDb3VudHNbb2Zmc2V0XSA9IGluZGljZXNMZW5ndGg7CiAgICAgIGJvdW5kaW5nVm9sdW1lc1tvZmZzZXRdID0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC50cmFuc2Zvcm0oCiAgICAgICAgcHJpbWl0aXZlTW9kZWxNYXRyaXhBbmRCVi5ib3VuZGluZ1ZvbHVtZSwKICAgICAgICBwcmltaXRpdmVNb2RlbE1hdHJpeAogICAgICApOwogICAgICBwb3NpdGlvbk9mZnNldCArPSBwb3NpdGlvbnNMZW5ndGggLyAzOwogICAgICBpbmRleE9mZnNldCArPSBpbmRpY2VzTGVuZ3RoOwogICAgfQogICAgb3B0aW9ucy5wb3NpdGlvbk9mZnNldCA9IHBvc2l0aW9uT2Zmc2V0OwogICAgb3B0aW9ucy5iYXRjaElkSW5kZXggPSBiYXRjaElkSW5kZXg7CiAgICBvcHRpb25zLmluZGV4T2Zmc2V0ID0gaW5kZXhPZmZzZXQ7CiAgICBvcHRpb25zLmJhdGNoZWRJbmRpY2VzT2Zmc2V0ICs9IG51bWJlck9mUHJpbWl0aXZlczsKICB9CiAgZnVuY3Rpb24gdW5wYWNrQnVmZmVyKGJ1ZmZlcikgewogICAgY29uc3QgcGFja2VkQnVmZmVyID0gbmV3IEZsb2F0NjRBcnJheShidWZmZXIpOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKHBhY2tlZEJ1ZmZlciwgb2Zmc2V0LCBzY3JhdGNoQ2VudGVyNSk7CiAgICBvZmZzZXQgKz0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgIE1hdHJpeDRfZGVmYXVsdC51bnBhY2socGFja2VkQnVmZmVyLCBvZmZzZXQsIHNjcmF0Y2hNYXRyaXg0KTsKICB9CiAgZnVuY3Rpb24gcGFja2VkQmF0Y2hlZEluZGljZXNMZW5ndGgoYmF0Y2hlZEluZGljZXMpIHsKICAgIGNvbnN0IGxlbmd0aCA9IGJhdGNoZWRJbmRpY2VzLmxlbmd0aDsKICAgIGxldCBjb3VudCA9IDA7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgIGNvdW50ICs9IENvbG9yX2RlZmF1bHQucGFja2VkTGVuZ3RoICsgMyArIGJhdGNoZWRJbmRpY2VzW2ldLmJhdGNoSWRzLmxlbmd0aDsKICAgIH0KICAgIHJldHVybiBjb3VudDsKICB9CiAgZnVuY3Rpb24gcGFja0J1ZmZlcihpbmRpY2VzQnl0ZXNQZXJFbGVtZW50LCBiYXRjaGVkSW5kaWNlcywgYm91bmRpbmdWb2x1bWVzKSB7CiAgICBjb25zdCBudW1CVnMgPSBib3VuZGluZ1ZvbHVtZXMubGVuZ3RoOwogICAgY29uc3QgbGVuZ3RoID0gMSArIDEgKyBudW1CVnMgKiBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LnBhY2tlZExlbmd0aCArIDEgKyBwYWNrZWRCYXRjaGVkSW5kaWNlc0xlbmd0aChiYXRjaGVkSW5kaWNlcyk7CiAgICBjb25zdCBwYWNrZWRCdWZmZXIgPSBuZXcgRmxvYXQ2NEFycmF5KGxlbmd0aCk7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIHBhY2tlZEJ1ZmZlcltvZmZzZXQrK10gPSBpbmRpY2VzQnl0ZXNQZXJFbGVtZW50OwogICAgcGFja2VkQnVmZmVyW29mZnNldCsrXSA9IG51bUJWczsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQlZzOyArK2kpIHsKICAgICAgQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5wYWNrKGJvdW5kaW5nVm9sdW1lc1tpXSwgcGFja2VkQnVmZmVyLCBvZmZzZXQpOwogICAgICBvZmZzZXQgKz0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICB9CiAgICBjb25zdCBpbmRpY2VzTGVuZ3RoID0gYmF0Y2hlZEluZGljZXMubGVuZ3RoOwogICAgcGFja2VkQnVmZmVyW29mZnNldCsrXSA9IGluZGljZXNMZW5ndGg7CiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGluZGljZXNMZW5ndGg7ICsraikgewogICAgICBjb25zdCBiYXRjaGVkSW5kZXggPSBiYXRjaGVkSW5kaWNlc1tqXTsKICAgICAgQ29sb3JfZGVmYXVsdC5wYWNrKGJhdGNoZWRJbmRleC5jb2xvciwgcGFja2VkQnVmZmVyLCBvZmZzZXQpOwogICAgICBvZmZzZXQgKz0gQ29sb3JfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgIHBhY2tlZEJ1ZmZlcltvZmZzZXQrK10gPSBiYXRjaGVkSW5kZXgub2Zmc2V0OwogICAgICBwYWNrZWRCdWZmZXJbb2Zmc2V0KytdID0gYmF0Y2hlZEluZGV4LmNvdW50OwogICAgICBjb25zdCBiYXRjaElkcyA9IGJhdGNoZWRJbmRleC5iYXRjaElkczsKICAgICAgY29uc3QgYmF0Y2hJZHNMZW5ndGggPSBiYXRjaElkcy5sZW5ndGg7CiAgICAgIHBhY2tlZEJ1ZmZlcltvZmZzZXQrK10gPSBiYXRjaElkc0xlbmd0aDsKICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCBiYXRjaElkc0xlbmd0aDsgKytrKSB7CiAgICAgICAgcGFja2VkQnVmZmVyW29mZnNldCsrXSA9IGJhdGNoSWRzW2tdOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcGFja2VkQnVmZmVyOwogIH0KICBmdW5jdGlvbiBjcmVhdGVWZWN0b3JUaWxlR2VvbWV0cmllcyhwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICBjb25zdCBib3hlcyA9IGRlZmluZWRfZGVmYXVsdChwYXJhbWV0ZXJzLmJveGVzKSA/IG5ldyBGbG9hdDMyQXJyYXkocGFyYW1ldGVycy5ib3hlcykgOiB2b2lkIDA7CiAgICBjb25zdCBib3hCYXRjaElkcyA9IGRlZmluZWRfZGVmYXVsdChwYXJhbWV0ZXJzLmJveEJhdGNoSWRzKSA/IG5ldyBVaW50MTZBcnJheShwYXJhbWV0ZXJzLmJveEJhdGNoSWRzKSA6IHZvaWQgMDsKICAgIGNvbnN0IGN5bGluZGVycyA9IGRlZmluZWRfZGVmYXVsdChwYXJhbWV0ZXJzLmN5bGluZGVycykgPyBuZXcgRmxvYXQzMkFycmF5KHBhcmFtZXRlcnMuY3lsaW5kZXJzKSA6IHZvaWQgMDsKICAgIGNvbnN0IGN5bGluZGVyQmF0Y2hJZHMgPSBkZWZpbmVkX2RlZmF1bHQocGFyYW1ldGVycy5jeWxpbmRlckJhdGNoSWRzKSA/IG5ldyBVaW50MTZBcnJheShwYXJhbWV0ZXJzLmN5bGluZGVyQmF0Y2hJZHMpIDogdm9pZCAwOwogICAgY29uc3QgZWxsaXBzb2lkcyA9IGRlZmluZWRfZGVmYXVsdChwYXJhbWV0ZXJzLmVsbGlwc29pZHMpID8gbmV3IEZsb2F0MzJBcnJheShwYXJhbWV0ZXJzLmVsbGlwc29pZHMpIDogdm9pZCAwOwogICAgY29uc3QgZWxsaXBzb2lkQmF0Y2hJZHMgPSBkZWZpbmVkX2RlZmF1bHQocGFyYW1ldGVycy5lbGxpcHNvaWRCYXRjaElkcykgPyBuZXcgVWludDE2QXJyYXkocGFyYW1ldGVycy5lbGxpcHNvaWRCYXRjaElkcykgOiB2b2lkIDA7CiAgICBjb25zdCBzcGhlcmVzID0gZGVmaW5lZF9kZWZhdWx0KHBhcmFtZXRlcnMuc3BoZXJlcykgPyBuZXcgRmxvYXQzMkFycmF5KHBhcmFtZXRlcnMuc3BoZXJlcykgOiB2b2lkIDA7CiAgICBjb25zdCBzcGhlcmVCYXRjaElkcyA9IGRlZmluZWRfZGVmYXVsdChwYXJhbWV0ZXJzLnNwaGVyZUJhdGNoSWRzKSA/IG5ldyBVaW50MTZBcnJheShwYXJhbWV0ZXJzLnNwaGVyZUJhdGNoSWRzKSA6IHZvaWQgMDsKICAgIGNvbnN0IG51bWJlck9mQm94ZXMgPSBkZWZpbmVkX2RlZmF1bHQoYm94ZXMpID8gYm94QmF0Y2hJZHMubGVuZ3RoIDogMDsKICAgIGNvbnN0IG51bWJlck9mQ3lsaW5kZXJzID0gZGVmaW5lZF9kZWZhdWx0KGN5bGluZGVycykgPyBjeWxpbmRlckJhdGNoSWRzLmxlbmd0aCA6IDA7CiAgICBjb25zdCBudW1iZXJPZkVsbGlwc29pZHMgPSBkZWZpbmVkX2RlZmF1bHQoZWxsaXBzb2lkcykgPyBlbGxpcHNvaWRCYXRjaElkcy5sZW5ndGggOiAwOwogICAgY29uc3QgbnVtYmVyT2ZTcGhlcmVzID0gZGVmaW5lZF9kZWZhdWx0KHNwaGVyZXMpID8gc3BoZXJlQmF0Y2hJZHMubGVuZ3RoIDogMDsKICAgIGNvbnN0IGJveEdlb21ldHJ5ID0gQm94R2VvbWV0cnlfZGVmYXVsdC5nZXRVbml0Qm94KCk7CiAgICBjb25zdCBjeWxpbmRlckdlb21ldHJ5ID0gQ3lsaW5kZXJHZW9tZXRyeV9kZWZhdWx0LmdldFVuaXRDeWxpbmRlcigpOwogICAgY29uc3QgZWxsaXBzb2lkR2VvbWV0cnkgPSBFbGxpcHNvaWRHZW9tZXRyeV9kZWZhdWx0LmdldFVuaXRFbGxpcHNvaWQoKTsKICAgIGNvbnN0IGJveFBvc2l0aW9ucyA9IGJveEdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzOwogICAgY29uc3QgY3lsaW5kZXJQb3NpdGlvbnMgPSBjeWxpbmRlckdlb21ldHJ5LmF0dHJpYnV0ZXMucG9zaXRpb24udmFsdWVzOwogICAgY29uc3QgZWxsaXBzb2lkUG9zaXRpb25zID0gZWxsaXBzb2lkR2VvbWV0cnkuYXR0cmlidXRlcy5wb3NpdGlvbi52YWx1ZXM7CiAgICBsZXQgbnVtYmVyT2ZQb3NpdGlvbnMgPSBib3hQb3NpdGlvbnMubGVuZ3RoICogbnVtYmVyT2ZCb3hlczsKICAgIG51bWJlck9mUG9zaXRpb25zICs9IGN5bGluZGVyUG9zaXRpb25zLmxlbmd0aCAqIG51bWJlck9mQ3lsaW5kZXJzOwogICAgbnVtYmVyT2ZQb3NpdGlvbnMgKz0gZWxsaXBzb2lkUG9zaXRpb25zLmxlbmd0aCAqIChudW1iZXJPZkVsbGlwc29pZHMgKyBudW1iZXJPZlNwaGVyZXMpOwogICAgY29uc3QgYm94SW5kaWNlcyA9IGJveEdlb21ldHJ5LmluZGljZXM7CiAgICBjb25zdCBjeWxpbmRlckluZGljZXMgPSBjeWxpbmRlckdlb21ldHJ5LmluZGljZXM7CiAgICBjb25zdCBlbGxpcHNvaWRJbmRpY2VzID0gZWxsaXBzb2lkR2VvbWV0cnkuaW5kaWNlczsKICAgIGxldCBudW1iZXJPZkluZGljZXMgPSBib3hJbmRpY2VzLmxlbmd0aCAqIG51bWJlck9mQm94ZXM7CiAgICBudW1iZXJPZkluZGljZXMgKz0gY3lsaW5kZXJJbmRpY2VzLmxlbmd0aCAqIG51bWJlck9mQ3lsaW5kZXJzOwogICAgbnVtYmVyT2ZJbmRpY2VzICs9IGVsbGlwc29pZEluZGljZXMubGVuZ3RoICogKG51bWJlck9mRWxsaXBzb2lkcyArIG51bWJlck9mU3BoZXJlcyk7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KG51bWJlck9mUG9zaXRpb25zKTsKICAgIGNvbnN0IHZlcnRleEJhdGNoSWRzID0gbmV3IFVpbnQxNkFycmF5KG51bWJlck9mUG9zaXRpb25zIC8gMyk7CiAgICBjb25zdCBpbmRpY2VzID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgIG51bWJlck9mUG9zaXRpb25zIC8gMywKICAgICAgbnVtYmVyT2ZJbmRpY2VzCiAgICApOwogICAgY29uc3QgbnVtYmVyT2ZHZW9tZXRyaWVzID0gbnVtYmVyT2ZCb3hlcyArIG51bWJlck9mQ3lsaW5kZXJzICsgbnVtYmVyT2ZFbGxpcHNvaWRzICsgbnVtYmVyT2ZTcGhlcmVzOwogICAgY29uc3QgYmF0Y2hJZHMgPSBuZXcgVWludDE2QXJyYXkobnVtYmVyT2ZHZW9tZXRyaWVzKTsKICAgIGNvbnN0IGJhdGNoZWRJbmRpY2VzID0gbmV3IEFycmF5KG51bWJlck9mR2VvbWV0cmllcyk7CiAgICBjb25zdCBpbmRleE9mZnNldHMgPSBuZXcgVWludDMyQXJyYXkobnVtYmVyT2ZHZW9tZXRyaWVzKTsKICAgIGNvbnN0IGluZGV4Q291bnRzID0gbmV3IFVpbnQzMkFycmF5KG51bWJlck9mR2VvbWV0cmllcyk7CiAgICBjb25zdCBib3VuZGluZ1ZvbHVtZXMgPSBuZXcgQXJyYXkobnVtYmVyT2ZHZW9tZXRyaWVzKTsKICAgIHVucGFja0J1ZmZlcihwYXJhbWV0ZXJzLnBhY2tlZEJ1ZmZlcik7CiAgICBjb25zdCBvcHRpb25zID0gewogICAgICBiYXRjaFRhYmxlQ29sb3JzOiBuZXcgVWludDMyQXJyYXkocGFyYW1ldGVycy5iYXRjaFRhYmxlQ29sb3JzKSwKICAgICAgcG9zaXRpb25zLAogICAgICB2ZXJ0ZXhCYXRjaElkcywKICAgICAgaW5kaWNlcywKICAgICAgYmF0Y2hJZHMsCiAgICAgIGJhdGNoZWRJbmRpY2VzLAogICAgICBpbmRleE9mZnNldHMsCiAgICAgIGluZGV4Q291bnRzLAogICAgICBib3VuZGluZ1ZvbHVtZXMsCiAgICAgIHBvc2l0aW9uT2Zmc2V0OiAwLAogICAgICBiYXRjaElkSW5kZXg6IDAsCiAgICAgIGluZGV4T2Zmc2V0OiAwLAogICAgICBiYXRjaGVkSW5kaWNlc09mZnNldDogMCwKICAgICAgbW9kZWxNYXRyaXg6IHNjcmF0Y2hNYXRyaXg0LAogICAgICBjZW50ZXI6IHNjcmF0Y2hDZW50ZXI1CiAgICB9OwogICAgY3JlYXRlUHJpbWl0aXZlKAogICAgICBvcHRpb25zLAogICAgICBib3hlcywKICAgICAgYm94QmF0Y2hJZHMsCiAgICAgIGJveEdlb21ldHJ5LAogICAgICBib3hNb2RlbE1hdHJpeEFuZEJvdW5kaW5nVm9sdW1lCiAgICApOwogICAgY3JlYXRlUHJpbWl0aXZlKAogICAgICBvcHRpb25zLAogICAgICBjeWxpbmRlcnMsCiAgICAgIGN5bGluZGVyQmF0Y2hJZHMsCiAgICAgIGN5bGluZGVyR2VvbWV0cnksCiAgICAgIGN5bGluZGVyTW9kZWxNYXRyaXhBbmRCb3VuZGluZ1ZvbHVtZQogICAgKTsKICAgIGNyZWF0ZVByaW1pdGl2ZSgKICAgICAgb3B0aW9ucywKICAgICAgZWxsaXBzb2lkcywKICAgICAgZWxsaXBzb2lkQmF0Y2hJZHMsCiAgICAgIGVsbGlwc29pZEdlb21ldHJ5LAogICAgICBlbGxpcHNvaWRNb2RlbE1hdHJpeEFuZEJvdW5kaW5nVm9sdW1lCiAgICApOwogICAgY3JlYXRlUHJpbWl0aXZlKAogICAgICBvcHRpb25zLAogICAgICBzcGhlcmVzLAogICAgICBzcGhlcmVCYXRjaElkcywKICAgICAgZWxsaXBzb2lkR2VvbWV0cnksCiAgICAgIHNwaGVyZU1vZGVsTWF0cml4QW5kQm91bmRpbmdWb2x1bWUKICAgICk7CiAgICBjb25zdCBwYWNrZWRCdWZmZXIgPSBwYWNrQnVmZmVyKAogICAgICBpbmRpY2VzLkJZVEVTX1BFUl9FTEVNRU5ULAogICAgICBiYXRjaGVkSW5kaWNlcywKICAgICAgYm91bmRpbmdWb2x1bWVzCiAgICApOwogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKAogICAgICBwb3NpdGlvbnMuYnVmZmVyLAogICAgICB2ZXJ0ZXhCYXRjaElkcy5idWZmZXIsCiAgICAgIGluZGljZXMuYnVmZmVyCiAgICApOwogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKAogICAgICBiYXRjaElkcy5idWZmZXIsCiAgICAgIGluZGV4T2Zmc2V0cy5idWZmZXIsCiAgICAgIGluZGV4Q291bnRzLmJ1ZmZlcgogICAgKTsKICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaChwYWNrZWRCdWZmZXIuYnVmZmVyKTsKICAgIHJldHVybiB7CiAgICAgIHBvc2l0aW9uczogcG9zaXRpb25zLmJ1ZmZlciwKICAgICAgdmVydGV4QmF0Y2hJZHM6IHZlcnRleEJhdGNoSWRzLmJ1ZmZlciwKICAgICAgaW5kaWNlczogaW5kaWNlcy5idWZmZXIsCiAgICAgIGluZGV4T2Zmc2V0czogaW5kZXhPZmZzZXRzLmJ1ZmZlciwKICAgICAgaW5kZXhDb3VudHM6IGluZGV4Q291bnRzLmJ1ZmZlciwKICAgICAgYmF0Y2hJZHM6IGJhdGNoSWRzLmJ1ZmZlciwKICAgICAgcGFja2VkQnVmZmVyOiBwYWNrZWRCdWZmZXIuYnVmZmVyCiAgICB9OwogIH0KICB2YXIgc2NyYXRjaENhcnRlc2lhbjExLCBwYWNrZWRCb3hMZW5ndGgsIHBhY2tlZEN5bGluZGVyTGVuZ3RoLCBwYWNrZWRFbGxpcHNvaWRMZW5ndGgsIHBhY2tlZFNwaGVyZUxlbmd0aCwgc2NyYXRjaE1vZGVsTWF0cml4QW5kQlYsIHNjcmF0Y2hQb3NpdGlvbjUsIHNjcmF0Y2hDZW50ZXI1LCBzY3JhdGNoTWF0cml4NCwgY3JlYXRlVmVjdG9yVGlsZUdlb21ldHJpZXNfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVWZWN0b3JUaWxlR2VvbWV0cmllcyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlVmVjdG9yVGlsZUdlb21ldHJpZXMuanMiKCkgewogICAgICBpbml0X0JvdW5kaW5nU3BoZXJlKCk7CiAgICAgIGluaXRfQm94R2VvbWV0cnkoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ29sb3IoKTsKICAgICAgaW5pdF9DeWxpbmRlckdlb21ldHJ5KCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZEdlb21ldHJ5KCk7CiAgICAgIGluaXRfSW5kZXhEYXRhdHlwZSgpOwogICAgICBpbml0X01hdHJpeDQoKTsKICAgICAgaW5pdF9WZWN0b3IzRFRpbGVCYXRjaCgpOwogICAgICBpbml0X2NyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXIoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjExID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBwYWNrZWRCb3hMZW5ndGggPSBNYXRyaXg0X2RlZmF1bHQucGFja2VkTGVuZ3RoICsgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgcGFja2VkQ3lsaW5kZXJMZW5ndGggPSBNYXRyaXg0X2RlZmF1bHQucGFja2VkTGVuZ3RoICsgMjsKICAgICAgcGFja2VkRWxsaXBzb2lkTGVuZ3RoID0gTWF0cml4NF9kZWZhdWx0LnBhY2tlZExlbmd0aCArIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgIHBhY2tlZFNwaGVyZUxlbmd0aCA9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyAxOwogICAgICBzY3JhdGNoTW9kZWxNYXRyaXhBbmRCViA9IHsKICAgICAgICBtb2RlbE1hdHJpeDogbmV3IE1hdHJpeDRfZGVmYXVsdCgpLAogICAgICAgIGJvdW5kaW5nVm9sdW1lOiBuZXcgQm91bmRpbmdTcGhlcmVfZGVmYXVsdCgpCiAgICAgIH07CiAgICAgIHNjcmF0Y2hQb3NpdGlvbjUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDZW50ZXI1ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoTWF0cml4NCA9IG5ldyBNYXRyaXg0X2RlZmF1bHQoKTsKICAgICAgY3JlYXRlVmVjdG9yVGlsZUdlb21ldHJpZXNfZGVmYXVsdCA9IGNyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXJfZGVmYXVsdChjcmVhdGVWZWN0b3JUaWxlR2VvbWV0cmllcyk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVWZWN0b3JUaWxlUG9pbnRzLmpzCiAgdmFyIGNyZWF0ZVZlY3RvclRpbGVQb2ludHNfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZVZlY3RvclRpbGVQb2ludHNfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlVmVjdG9yVGlsZVBvaW50c19kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gdW5wYWNrQnVmZmVyMihwYWNrZWRCdWZmZXIpIHsKICAgIHBhY2tlZEJ1ZmZlciA9IG5ldyBGbG9hdDY0QXJyYXkocGFja2VkQnVmZmVyKTsKICAgIGxldCBvZmZzZXQgPSAwOwogICAgc2NyYXRjaE1pbk1heEhlaWdodHMubWluID0gcGFja2VkQnVmZmVyW29mZnNldCsrXTsKICAgIHNjcmF0Y2hNaW5NYXhIZWlnaHRzLm1heCA9IHBhY2tlZEJ1ZmZlcltvZmZzZXQrK107CiAgICBSZWN0YW5nbGVfZGVmYXVsdC51bnBhY2socGFja2VkQnVmZmVyLCBvZmZzZXQsIHNjcmF0Y2hSZWN0YW5nbGU0KTsKICAgIG9mZnNldCArPSBSZWN0YW5nbGVfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICBFbGxpcHNvaWRfZGVmYXVsdC51bnBhY2socGFja2VkQnVmZmVyLCBvZmZzZXQsIHNjcmF0Y2hFbGxpcHNvaWQxNCk7CiAgfQogIGZ1bmN0aW9uIGNyZWF0ZVZlY3RvclRpbGVQb2ludHMocGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cykgewogICAgY29uc3QgcG9zaXRpb25zID0gbmV3IFVpbnQxNkFycmF5KHBhcmFtZXRlcnMucG9zaXRpb25zKTsKICAgIHVucGFja0J1ZmZlcjIocGFyYW1ldGVycy5wYWNrZWRCdWZmZXIpOwogICAgY29uc3QgcmVjdGFuZ2xlID0gc2NyYXRjaFJlY3RhbmdsZTQ7CiAgICBjb25zdCBlbGxpcHNvaWQgPSBzY3JhdGNoRWxsaXBzb2lkMTQ7CiAgICBjb25zdCBtaW5pbXVtSGVpZ2h0ID0gc2NyYXRjaE1pbk1heEhlaWdodHMubWluOwogICAgY29uc3QgbWF4aW11bUhlaWdodCA9IHNjcmF0Y2hNaW5NYXhIZWlnaHRzLm1heDsKICAgIGNvbnN0IHBvc2l0aW9uc0xlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGggLyAzOwogICAgY29uc3QgdUJ1ZmZlciA9IHBvc2l0aW9ucy5zdWJhcnJheSgwLCBwb3NpdGlvbnNMZW5ndGgpOwogICAgY29uc3QgdkJ1ZmZlciA9IHBvc2l0aW9ucy5zdWJhcnJheShwb3NpdGlvbnNMZW5ndGgsIDIgKiBwb3NpdGlvbnNMZW5ndGgpOwogICAgY29uc3QgaGVpZ2h0QnVmZmVyID0gcG9zaXRpb25zLnN1YmFycmF5KAogICAgICAyICogcG9zaXRpb25zTGVuZ3RoLAogICAgICAzICogcG9zaXRpb25zTGVuZ3RoCiAgICApOwogICAgQXR0cmlidXRlQ29tcHJlc3Npb25fZGVmYXVsdC56aWdaYWdEZWx0YURlY29kZSh1QnVmZmVyLCB2QnVmZmVyLCBoZWlnaHRCdWZmZXIpOwogICAgY29uc3QgZGVjb2RlZCA9IG5ldyBGbG9hdDY0QXJyYXkocG9zaXRpb25zLmxlbmd0aCk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBvc2l0aW9uc0xlbmd0aDsgKytpKSB7CiAgICAgIGNvbnN0IHUzID0gdUJ1ZmZlcltpXTsKICAgICAgY29uc3QgdjMgPSB2QnVmZmVyW2ldOwogICAgICBjb25zdCBoID0gaGVpZ2h0QnVmZmVyW2ldOwogICAgICBjb25zdCBsb24gPSBNYXRoX2RlZmF1bHQubGVycChyZWN0YW5nbGUud2VzdCwgcmVjdGFuZ2xlLmVhc3QsIHUzIC8gbWF4U2hvcnQpOwogICAgICBjb25zdCBsYXQgPSBNYXRoX2RlZmF1bHQubGVycChyZWN0YW5nbGUuc291dGgsIHJlY3RhbmdsZS5ub3J0aCwgdjMgLyBtYXhTaG9ydCk7CiAgICAgIGNvbnN0IGFsdCA9IE1hdGhfZGVmYXVsdC5sZXJwKG1pbmltdW1IZWlnaHQsIG1heGltdW1IZWlnaHQsIGggLyBtYXhTaG9ydCk7CiAgICAgIGNvbnN0IGNhcnRvZ3JhcGhpYzIgPSBDYXJ0b2dyYXBoaWNfZGVmYXVsdC5mcm9tUmFkaWFucygKICAgICAgICBsb24sCiAgICAgICAgbGF0LAogICAgICAgIGFsdCwKICAgICAgICBzY3JhdGNoQlZDYXJ0b2dyYXBoaWMyCiAgICAgICk7CiAgICAgIGNvbnN0IGRlY29kZWRQb3NpdGlvbiA9IGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbigKICAgICAgICBjYXJ0b2dyYXBoaWMyLAogICAgICAgIHNjcmF0Y2hFbmNvZGVkUG9zaXRpb24yCiAgICAgICk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKGRlY29kZWRQb3NpdGlvbiwgZGVjb2RlZCwgaSAqIDMpOwogICAgfQogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKGRlY29kZWQuYnVmZmVyKTsKICAgIHJldHVybiB7CiAgICAgIHBvc2l0aW9uczogZGVjb2RlZC5idWZmZXIKICAgIH07CiAgfQogIHZhciBtYXhTaG9ydCwgc2NyYXRjaEJWQ2FydG9ncmFwaGljMiwgc2NyYXRjaEVuY29kZWRQb3NpdGlvbjIsIHNjcmF0Y2hSZWN0YW5nbGU0LCBzY3JhdGNoRWxsaXBzb2lkMTQsIHNjcmF0Y2hNaW5NYXhIZWlnaHRzLCBjcmVhdGVWZWN0b3JUaWxlUG9pbnRzX2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlVmVjdG9yVGlsZVBvaW50cyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlVmVjdG9yVGlsZVBvaW50cy5qcyIoKSB7CiAgICAgIGluaXRfQXR0cmlidXRlQ29tcHJlc3Npb24oKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1JlY3RhbmdsZSgpOwogICAgICBpbml0X2NyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXIoKTsKICAgICAgbWF4U2hvcnQgPSAzMjc2NzsKICAgICAgc2NyYXRjaEJWQ2FydG9ncmFwaGljMiA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoRW5jb2RlZFBvc2l0aW9uMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFJlY3RhbmdsZTQgPSBuZXcgUmVjdGFuZ2xlX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEVsbGlwc29pZDE0ID0gbmV3IEVsbGlwc29pZF9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hNaW5NYXhIZWlnaHRzID0gewogICAgICAgIG1pbjogdm9pZCAwLAogICAgICAgIG1heDogdm9pZCAwCiAgICAgIH07CiAgICAgIGNyZWF0ZVZlY3RvclRpbGVQb2ludHNfZGVmYXVsdCA9IGNyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXJfZGVmYXVsdChjcmVhdGVWZWN0b3JUaWxlUG9pbnRzKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVZlY3RvclRpbGVQb2x5Z29ucy5qcwogIHZhciBjcmVhdGVWZWN0b3JUaWxlUG9seWdvbnNfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZVZlY3RvclRpbGVQb2x5Z29uc19leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVWZWN0b3JUaWxlUG9seWdvbnNfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIHVucGFja0J1ZmZlcjMoYnVmZmVyKSB7CiAgICBjb25zdCBwYWNrZWRCdWZmZXIgPSBuZXcgRmxvYXQ2NEFycmF5KGJ1ZmZlcik7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIHNjcmF0Y2hTY2FsYXJzLmluZGV4Qnl0ZXNQZXJFbGVtZW50ID0gcGFja2VkQnVmZmVyW29mZnNldCsrXTsKICAgIHNjcmF0Y2hTY2FsYXJzLm1pbiA9IHBhY2tlZEJ1ZmZlcltvZmZzZXQrK107CiAgICBzY3JhdGNoU2NhbGFycy5tYXggPSBwYWNrZWRCdWZmZXJbb2Zmc2V0KytdOwogICAgQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjayhwYWNrZWRCdWZmZXIsIG9mZnNldCwgc2NyYXRjaENlbnRlcjYpOwogICAgb2Zmc2V0ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICBFbGxpcHNvaWRfZGVmYXVsdC51bnBhY2socGFja2VkQnVmZmVyLCBvZmZzZXQsIHNjcmF0Y2hFbGxpcHNvaWQxNSk7CiAgICBvZmZzZXQgKz0gRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgUmVjdGFuZ2xlX2RlZmF1bHQudW5wYWNrKHBhY2tlZEJ1ZmZlciwgb2Zmc2V0LCBzY3JhdGNoUmVjdGFuZ2xlNSk7CiAgfQogIGZ1bmN0aW9uIHBhY2tlZEJhdGNoZWRJbmRpY2VzTGVuZ3RoMihiYXRjaGVkSW5kaWNlcykgewogICAgY29uc3QgbGVuZ3RoID0gYmF0Y2hlZEluZGljZXMubGVuZ3RoOwogICAgbGV0IGNvdW50ID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgY291bnQgKz0gQ29sb3JfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyAzICsgYmF0Y2hlZEluZGljZXNbaV0uYmF0Y2hJZHMubGVuZ3RoOwogICAgfQogICAgcmV0dXJuIGNvdW50OwogIH0KICBmdW5jdGlvbiBwYWNrQnVmZmVyMihpbmRleERhdGF0eXBlLCBib3VuZGluZ1ZvbHVtZXMsIGJhdGNoZWRJbmRpY2VzKSB7CiAgICBjb25zdCBudW1CVnMgPSBib3VuZGluZ1ZvbHVtZXMubGVuZ3RoOwogICAgY29uc3QgbGVuZ3RoID0gMSArIDEgKyBudW1CVnMgKiBPcmllbnRlZEJvdW5kaW5nQm94X2RlZmF1bHQucGFja2VkTGVuZ3RoICsgMSArIHBhY2tlZEJhdGNoZWRJbmRpY2VzTGVuZ3RoMihiYXRjaGVkSW5kaWNlcyk7CiAgICBjb25zdCBwYWNrZWRCdWZmZXIgPSBuZXcgRmxvYXQ2NEFycmF5KGxlbmd0aCk7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIHBhY2tlZEJ1ZmZlcltvZmZzZXQrK10gPSBpbmRleERhdGF0eXBlOwogICAgcGFja2VkQnVmZmVyW29mZnNldCsrXSA9IG51bUJWczsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQlZzOyArK2kpIHsKICAgICAgT3JpZW50ZWRCb3VuZGluZ0JveF9kZWZhdWx0LnBhY2soYm91bmRpbmdWb2x1bWVzW2ldLCBwYWNrZWRCdWZmZXIsIG9mZnNldCk7CiAgICAgIG9mZnNldCArPSBPcmllbnRlZEJvdW5kaW5nQm94X2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgfQogICAgY29uc3QgaW5kaWNlc0xlbmd0aCA9IGJhdGNoZWRJbmRpY2VzLmxlbmd0aDsKICAgIHBhY2tlZEJ1ZmZlcltvZmZzZXQrK10gPSBpbmRpY2VzTGVuZ3RoOwogICAgZm9yIChsZXQgaiA9IDA7IGogPCBpbmRpY2VzTGVuZ3RoOyArK2opIHsKICAgICAgY29uc3QgYmF0Y2hlZEluZGV4ID0gYmF0Y2hlZEluZGljZXNbal07CiAgICAgIENvbG9yX2RlZmF1bHQucGFjayhiYXRjaGVkSW5kZXguY29sb3IsIHBhY2tlZEJ1ZmZlciwgb2Zmc2V0KTsKICAgICAgb2Zmc2V0ICs9IENvbG9yX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICBwYWNrZWRCdWZmZXJbb2Zmc2V0KytdID0gYmF0Y2hlZEluZGV4Lm9mZnNldDsKICAgICAgcGFja2VkQnVmZmVyW29mZnNldCsrXSA9IGJhdGNoZWRJbmRleC5jb3VudDsKICAgICAgY29uc3QgYmF0Y2hJZHMgPSBiYXRjaGVkSW5kZXguYmF0Y2hJZHM7CiAgICAgIGNvbnN0IGJhdGNoSWRzTGVuZ3RoID0gYmF0Y2hJZHMubGVuZ3RoOwogICAgICBwYWNrZWRCdWZmZXJbb2Zmc2V0KytdID0gYmF0Y2hJZHNMZW5ndGg7CiAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgYmF0Y2hJZHNMZW5ndGg7ICsraykgewogICAgICAgIHBhY2tlZEJ1ZmZlcltvZmZzZXQrK10gPSBiYXRjaElkc1trXTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHBhY2tlZEJ1ZmZlcjsKICB9CiAgZnVuY3Rpb24gY3JlYXRlVmVjdG9yVGlsZVBvbHlnb25zKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIHVucGFja0J1ZmZlcjMocGFyYW1ldGVycy5wYWNrZWRCdWZmZXIpOwogICAgbGV0IGluZGljZXM7CiAgICBjb25zdCBpbmRleEJ5dGVzUGVyRWxlbWVudCA9IHNjcmF0Y2hTY2FsYXJzLmluZGV4Qnl0ZXNQZXJFbGVtZW50OwogICAgaWYgKGluZGV4Qnl0ZXNQZXJFbGVtZW50ID09PSAyKSB7CiAgICAgIGluZGljZXMgPSBuZXcgVWludDE2QXJyYXkocGFyYW1ldGVycy5pbmRpY2VzKTsKICAgIH0gZWxzZSB7CiAgICAgIGluZGljZXMgPSBuZXcgVWludDMyQXJyYXkocGFyYW1ldGVycy5pbmRpY2VzKTsKICAgIH0KICAgIGNvbnN0IHBvc2l0aW9ucyA9IG5ldyBVaW50MTZBcnJheShwYXJhbWV0ZXJzLnBvc2l0aW9ucyk7CiAgICBjb25zdCBjb3VudHMgPSBuZXcgVWludDMyQXJyYXkocGFyYW1ldGVycy5jb3VudHMpOwogICAgY29uc3QgaW5kZXhDb3VudHMgPSBuZXcgVWludDMyQXJyYXkocGFyYW1ldGVycy5pbmRleENvdW50cyk7CiAgICBjb25zdCBiYXRjaElkcyA9IG5ldyBVaW50MzJBcnJheShwYXJhbWV0ZXJzLmJhdGNoSWRzKTsKICAgIGNvbnN0IGJhdGNoVGFibGVDb2xvcnMgPSBuZXcgVWludDMyQXJyYXkocGFyYW1ldGVycy5iYXRjaFRhYmxlQ29sb3JzKTsKICAgIGNvbnN0IGJvdW5kaW5nVm9sdW1lcyA9IG5ldyBBcnJheShjb3VudHMubGVuZ3RoKTsKICAgIGNvbnN0IGNlbnRlciA9IHNjcmF0Y2hDZW50ZXI2OwogICAgY29uc3QgZWxsaXBzb2lkID0gc2NyYXRjaEVsbGlwc29pZDE1OwogICAgbGV0IHJlY3RhbmdsZSA9IHNjcmF0Y2hSZWN0YW5nbGU1OwogICAgY29uc3QgbWluSGVpZ2h0ID0gc2NyYXRjaFNjYWxhcnMubWluOwogICAgY29uc3QgbWF4SGVpZ2h0ID0gc2NyYXRjaFNjYWxhcnMubWF4OwogICAgbGV0IG1pbmltdW1IZWlnaHRzID0gcGFyYW1ldGVycy5taW5pbXVtSGVpZ2h0czsKICAgIGxldCBtYXhpbXVtSGVpZ2h0cyA9IHBhcmFtZXRlcnMubWF4aW11bUhlaWdodHM7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG1pbmltdW1IZWlnaHRzKSAmJiBkZWZpbmVkX2RlZmF1bHQobWF4aW11bUhlaWdodHMpKSB7CiAgICAgIG1pbmltdW1IZWlnaHRzID0gbmV3IEZsb2F0MzJBcnJheShtaW5pbXVtSGVpZ2h0cyk7CiAgICAgIG1heGltdW1IZWlnaHRzID0gbmV3IEZsb2F0MzJBcnJheShtYXhpbXVtSGVpZ2h0cyk7CiAgICB9CiAgICBsZXQgaTsKICAgIGxldCBqOwogICAgbGV0IHJnYmE7CiAgICBjb25zdCBwb3NpdGlvbnNMZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoIC8gMjsKICAgIGNvbnN0IHVCdWZmZXIgPSBwb3NpdGlvbnMuc3ViYXJyYXkoMCwgcG9zaXRpb25zTGVuZ3RoKTsKICAgIGNvbnN0IHZCdWZmZXIgPSBwb3NpdGlvbnMuc3ViYXJyYXkocG9zaXRpb25zTGVuZ3RoLCAyICogcG9zaXRpb25zTGVuZ3RoKTsKICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uX2RlZmF1bHQuemlnWmFnRGVsdGFEZWNvZGUodUJ1ZmZlciwgdkJ1ZmZlcik7CiAgICBjb25zdCBkZWNvZGVkUG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShwb3NpdGlvbnNMZW5ndGggKiAzKTsKICAgIGZvciAoaSA9IDA7IGkgPCBwb3NpdGlvbnNMZW5ndGg7ICsraSkgewogICAgICBjb25zdCB1MyA9IHVCdWZmZXJbaV07CiAgICAgIGNvbnN0IHYzID0gdkJ1ZmZlcltpXTsKICAgICAgY29uc3QgeCA9IE1hdGhfZGVmYXVsdC5sZXJwKHJlY3RhbmdsZS53ZXN0LCByZWN0YW5nbGUuZWFzdCwgdTMgLyBtYXhTaG9ydDIpOwogICAgICBjb25zdCB5ID0gTWF0aF9kZWZhdWx0LmxlcnAocmVjdGFuZ2xlLnNvdXRoLCByZWN0YW5nbGUubm9ydGgsIHYzIC8gbWF4U2hvcnQyKTsKICAgICAgY29uc3QgY2FydCA9IENhcnRvZ3JhcGhpY19kZWZhdWx0LmZyb21SYWRpYW5zKHgsIHksIDAsIHNjcmF0Y2hCVkNhcnRvZ3JhcGhpYzMpOwogICAgICBjb25zdCBkZWNvZGVkUG9zaXRpb24gPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oCiAgICAgICAgY2FydCwKICAgICAgICBzY3JhdGNoRW5jb2RlZFBvc2l0aW9uMwogICAgICApOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhkZWNvZGVkUG9zaXRpb24sIGRlY29kZWRQb3NpdGlvbnMsIGkgKiAzKTsKICAgIH0KICAgIGNvbnN0IGNvdW50c0xlbmd0aCA9IGNvdW50cy5sZW5ndGg7CiAgICBjb25zdCBvZmZzZXRzID0gbmV3IEFycmF5KGNvdW50c0xlbmd0aCk7CiAgICBjb25zdCBpbmRleE9mZnNldHMgPSBuZXcgQXJyYXkoY291bnRzTGVuZ3RoKTsKICAgIGxldCBjdXJyZW50T2Zmc2V0ID0gMDsKICAgIGxldCBjdXJyZW50SW5kZXhPZmZzZXQgPSAwOwogICAgZm9yIChpID0gMDsgaSA8IGNvdW50c0xlbmd0aDsgKytpKSB7CiAgICAgIG9mZnNldHNbaV0gPSBjdXJyZW50T2Zmc2V0OwogICAgICBpbmRleE9mZnNldHNbaV0gPSBjdXJyZW50SW5kZXhPZmZzZXQ7CiAgICAgIGN1cnJlbnRPZmZzZXQgKz0gY291bnRzW2ldOwogICAgICBjdXJyZW50SW5kZXhPZmZzZXQgKz0gaW5kZXhDb3VudHNbaV07CiAgICB9CiAgICBjb25zdCBiYXRjaGVkUG9zaXRpb25zID0gbmV3IEZsb2F0MzJBcnJheShwb3NpdGlvbnNMZW5ndGggKiAzICogMik7CiAgICBjb25zdCBiYXRjaGVkSWRzID0gbmV3IFVpbnQxNkFycmF5KHBvc2l0aW9uc0xlbmd0aCAqIDIpOwogICAgY29uc3QgYmF0Y2hlZEluZGV4T2Zmc2V0cyA9IG5ldyBVaW50MzJBcnJheShpbmRleE9mZnNldHMubGVuZ3RoKTsKICAgIGNvbnN0IGJhdGNoZWRJbmRleENvdW50cyA9IG5ldyBVaW50MzJBcnJheShpbmRleENvdW50cy5sZW5ndGgpOwogICAgbGV0IGJhdGNoZWRJbmRpY2VzID0gW107CiAgICBjb25zdCBjb2xvclRvQnVmZmVycyA9IHt9OwogICAgZm9yIChpID0gMDsgaSA8IGNvdW50c0xlbmd0aDsgKytpKSB7CiAgICAgIHJnYmEgPSBiYXRjaFRhYmxlQ29sb3JzW2ldOwogICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChjb2xvclRvQnVmZmVyc1tyZ2JhXSkpIHsKICAgICAgICBjb2xvclRvQnVmZmVyc1tyZ2JhXSA9IHsKICAgICAgICAgIHBvc2l0aW9uTGVuZ3RoOiBjb3VudHNbaV0sCiAgICAgICAgICBpbmRleExlbmd0aDogaW5kZXhDb3VudHNbaV0sCiAgICAgICAgICBvZmZzZXQ6IDAsCiAgICAgICAgICBpbmRleE9mZnNldDogMCwKICAgICAgICAgIGJhdGNoSWRzOiBbaV0KICAgICAgICB9OwogICAgICB9IGVsc2UgewogICAgICAgIGNvbG9yVG9CdWZmZXJzW3JnYmFdLnBvc2l0aW9uTGVuZ3RoICs9IGNvdW50c1tpXTsKICAgICAgICBjb2xvclRvQnVmZmVyc1tyZ2JhXS5pbmRleExlbmd0aCArPSBpbmRleENvdW50c1tpXTsKICAgICAgICBjb2xvclRvQnVmZmVyc1tyZ2JhXS5iYXRjaElkcy5wdXNoKGkpOwogICAgICB9CiAgICB9CiAgICBsZXQgYnVmZmVyOwogICAgbGV0IGJ5Q29sb3JQb3NpdGlvbk9mZnNldCA9IDA7CiAgICBsZXQgYnlDb2xvckluZGV4T2Zmc2V0ID0gMDsKICAgIGZvciAocmdiYSBpbiBjb2xvclRvQnVmZmVycykgewogICAgICBpZiAoY29sb3JUb0J1ZmZlcnMuaGFzT3duUHJvcGVydHkocmdiYSkpIHsKICAgICAgICBidWZmZXIgPSBjb2xvclRvQnVmZmVyc1tyZ2JhXTsKICAgICAgICBidWZmZXIub2Zmc2V0ID0gYnlDb2xvclBvc2l0aW9uT2Zmc2V0OwogICAgICAgIGJ1ZmZlci5pbmRleE9mZnNldCA9IGJ5Q29sb3JJbmRleE9mZnNldDsKICAgICAgICBjb25zdCBwb3NpdGlvbkxlbmd0aCA9IGJ1ZmZlci5wb3NpdGlvbkxlbmd0aCAqIDI7CiAgICAgICAgY29uc3QgaW5kZXhMZW5ndGggPSBidWZmZXIuaW5kZXhMZW5ndGggKiAyICsgYnVmZmVyLnBvc2l0aW9uTGVuZ3RoICogNjsKICAgICAgICBieUNvbG9yUG9zaXRpb25PZmZzZXQgKz0gcG9zaXRpb25MZW5ndGg7CiAgICAgICAgYnlDb2xvckluZGV4T2Zmc2V0ICs9IGluZGV4TGVuZ3RoOwogICAgICAgIGJ1ZmZlci5pbmRleExlbmd0aCA9IGluZGV4TGVuZ3RoOwogICAgICB9CiAgICB9CiAgICBjb25zdCBiYXRjaGVkRHJhd0NhbGxzID0gW107CiAgICBmb3IgKHJnYmEgaW4gY29sb3JUb0J1ZmZlcnMpIHsKICAgICAgaWYgKGNvbG9yVG9CdWZmZXJzLmhhc093blByb3BlcnR5KHJnYmEpKSB7CiAgICAgICAgYnVmZmVyID0gY29sb3JUb0J1ZmZlcnNbcmdiYV07CiAgICAgICAgYmF0Y2hlZERyYXdDYWxscy5wdXNoKHsKICAgICAgICAgIGNvbG9yOiBDb2xvcl9kZWZhdWx0LmZyb21SZ2JhKHBhcnNlSW50KHJnYmEpKSwKICAgICAgICAgIG9mZnNldDogYnVmZmVyLmluZGV4T2Zmc2V0LAogICAgICAgICAgY291bnQ6IGJ1ZmZlci5pbmRleExlbmd0aCwKICAgICAgICAgIGJhdGNoSWRzOiBidWZmZXIuYmF0Y2hJZHMKICAgICAgICB9KTsKICAgICAgfQogICAgfQogICAgZm9yIChpID0gMDsgaSA8IGNvdW50c0xlbmd0aDsgKytpKSB7CiAgICAgIHJnYmEgPSBiYXRjaFRhYmxlQ29sb3JzW2ldOwogICAgICBidWZmZXIgPSBjb2xvclRvQnVmZmVyc1tyZ2JhXTsKICAgICAgY29uc3QgcG9zaXRpb25PZmZzZXQgPSBidWZmZXIub2Zmc2V0OwogICAgICBsZXQgcG9zaXRpb25JbmRleCA9IHBvc2l0aW9uT2Zmc2V0ICogMzsKICAgICAgbGV0IGJhdGNoSWRJbmRleCA9IHBvc2l0aW9uT2Zmc2V0OwogICAgICBjb25zdCBwb2x5Z29uT2Zmc2V0ID0gb2Zmc2V0c1tpXTsKICAgICAgY29uc3QgcG9seWdvbkNvdW50ID0gY291bnRzW2ldOwogICAgICBjb25zdCBiYXRjaElkID0gYmF0Y2hJZHNbaV07CiAgICAgIGxldCBwb2x5Z29uTWluaW11bUhlaWdodCA9IG1pbkhlaWdodDsKICAgICAgbGV0IHBvbHlnb25NYXhpbXVtSGVpZ2h0ID0gbWF4SGVpZ2h0OwogICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG1pbmltdW1IZWlnaHRzKSAmJiBkZWZpbmVkX2RlZmF1bHQobWF4aW11bUhlaWdodHMpKSB7CiAgICAgICAgcG9seWdvbk1pbmltdW1IZWlnaHQgPSBtaW5pbXVtSGVpZ2h0c1tpXTsKICAgICAgICBwb2x5Z29uTWF4aW11bUhlaWdodCA9IG1heGltdW1IZWlnaHRzW2ldOwogICAgICB9CiAgICAgIGxldCBtaW5MYXQgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICAgIGxldCBtYXhMYXQgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICAgIGxldCBtaW5Mb24gPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICAgIGxldCBtYXhMb24gPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICAgIGZvciAoaiA9IDA7IGogPCBwb2x5Z29uQ291bnQ7ICsraikgewogICAgICAgIGNvbnN0IHBvc2l0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjaygKICAgICAgICAgIGRlY29kZWRQb3NpdGlvbnMsCiAgICAgICAgICBwb2x5Z29uT2Zmc2V0ICogMyArIGogKiAzLAogICAgICAgICAgc2NyYXRjaEVuY29kZWRQb3NpdGlvbjMKICAgICAgICApOwogICAgICAgIGVsbGlwc29pZC5zY2FsZVRvR2VvZGV0aWNTdXJmYWNlKHBvc2l0aW9uLCBwb3NpdGlvbik7CiAgICAgICAgY29uc3QgY2FydG8gPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMoCiAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgIHNjcmF0Y2hCVkNhcnRvZ3JhcGhpYzMKICAgICAgICApOwogICAgICAgIGNvbnN0IGxhdCA9IGNhcnRvLmxhdGl0dWRlOwogICAgICAgIGNvbnN0IGxvbiA9IGNhcnRvLmxvbmdpdHVkZTsKICAgICAgICBtaW5MYXQgPSBNYXRoLm1pbihsYXQsIG1pbkxhdCk7CiAgICAgICAgbWF4TGF0ID0gTWF0aC5tYXgobGF0LCBtYXhMYXQpOwogICAgICAgIG1pbkxvbiA9IE1hdGgubWluKGxvbiwgbWluTG9uKTsKICAgICAgICBtYXhMb24gPSBNYXRoLm1heChsb24sIG1heExvbik7CiAgICAgICAgY29uc3Qgbm9ybWFsMiA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwocG9zaXRpb24sIHNjcmF0Y2hOb3JtYWw3KTsKICAgICAgICBsZXQgc2NhbGVkTm9ybWFsID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgICBub3JtYWwyLAogICAgICAgICAgcG9seWdvbk1pbmltdW1IZWlnaHQsCiAgICAgICAgICBzY3JhdGNoU2NhbGVkTm9ybWFsCiAgICAgICAgKTsKICAgICAgICBjb25zdCBtaW5IZWlnaHRQb3NpdGlvbiA9IENhcnRlc2lhbjNfZGVmYXVsdC5hZGQoCiAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgIHNjYWxlZE5vcm1hbCwKICAgICAgICAgIHNjcmF0Y2hNaW5IZWlnaHRQb3NpdGlvbgogICAgICAgICk7CiAgICAgICAgc2NhbGVkTm9ybWFsID0gQ2FydGVzaWFuM19kZWZhdWx0Lm11bHRpcGx5QnlTY2FsYXIoCiAgICAgICAgICBub3JtYWwyLAogICAgICAgICAgcG9seWdvbk1heGltdW1IZWlnaHQsCiAgICAgICAgICBzY2FsZWROb3JtYWwKICAgICAgICApOwogICAgICAgIGNvbnN0IG1heEhlaWdodFBvc2l0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmFkZCgKICAgICAgICAgIHBvc2l0aW9uLAogICAgICAgICAgc2NhbGVkTm9ybWFsLAogICAgICAgICAgc2NyYXRjaE1heEhlaWdodFBvc2l0aW9uCiAgICAgICAgKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QobWF4SGVpZ2h0UG9zaXRpb24sIGNlbnRlciwgbWF4SGVpZ2h0UG9zaXRpb24pOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChtaW5IZWlnaHRQb3NpdGlvbiwgY2VudGVyLCBtaW5IZWlnaHRQb3NpdGlvbik7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2sobWF4SGVpZ2h0UG9zaXRpb24sIGJhdGNoZWRQb3NpdGlvbnMsIHBvc2l0aW9uSW5kZXgpOwogICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKG1pbkhlaWdodFBvc2l0aW9uLCBiYXRjaGVkUG9zaXRpb25zLCBwb3NpdGlvbkluZGV4ICsgMyk7CiAgICAgICAgYmF0Y2hlZElkc1tiYXRjaElkSW5kZXhdID0gYmF0Y2hJZDsKICAgICAgICBiYXRjaGVkSWRzW2JhdGNoSWRJbmRleCArIDFdID0gYmF0Y2hJZDsKICAgICAgICBwb3NpdGlvbkluZGV4ICs9IDY7CiAgICAgICAgYmF0Y2hJZEluZGV4ICs9IDI7CiAgICAgIH0KICAgICAgcmVjdGFuZ2xlID0gc2NyYXRjaEJWUmVjdGFuZ2xlOwogICAgICByZWN0YW5nbGUud2VzdCA9IG1pbkxvbjsKICAgICAgcmVjdGFuZ2xlLmVhc3QgPSBtYXhMb247CiAgICAgIHJlY3RhbmdsZS5zb3V0aCA9IG1pbkxhdDsKICAgICAgcmVjdGFuZ2xlLm5vcnRoID0gbWF4TGF0OwogICAgICBib3VuZGluZ1ZvbHVtZXNbaV0gPSBPcmllbnRlZEJvdW5kaW5nQm94X2RlZmF1bHQuZnJvbVJlY3RhbmdsZSgKICAgICAgICByZWN0YW5nbGUsCiAgICAgICAgbWluSGVpZ2h0LAogICAgICAgIG1heEhlaWdodCwKICAgICAgICBlbGxpcHNvaWQKICAgICAgKTsKICAgICAgbGV0IGluZGljZXNJbmRleCA9IGJ1ZmZlci5pbmRleE9mZnNldDsKICAgICAgY29uc3QgaW5kZXhPZmZzZXQgPSBpbmRleE9mZnNldHNbaV07CiAgICAgIGNvbnN0IGluZGV4Q291bnQgPSBpbmRleENvdW50c1tpXTsKICAgICAgYmF0Y2hlZEluZGV4T2Zmc2V0c1tpXSA9IGluZGljZXNJbmRleDsKICAgICAgZm9yIChqID0gMDsgaiA8IGluZGV4Q291bnQ7IGogKz0gMykgewogICAgICAgIGNvbnN0IGkwID0gaW5kaWNlc1tpbmRleE9mZnNldCArIGpdIC0gcG9seWdvbk9mZnNldDsKICAgICAgICBjb25zdCBpMSA9IGluZGljZXNbaW5kZXhPZmZzZXQgKyBqICsgMV0gLSBwb2x5Z29uT2Zmc2V0OwogICAgICAgIGNvbnN0IGkyID0gaW5kaWNlc1tpbmRleE9mZnNldCArIGogKyAyXSAtIHBvbHlnb25PZmZzZXQ7CiAgICAgICAgYmF0Y2hlZEluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaTAgKiAyICsgcG9zaXRpb25PZmZzZXQ7CiAgICAgICAgYmF0Y2hlZEluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaTEgKiAyICsgcG9zaXRpb25PZmZzZXQ7CiAgICAgICAgYmF0Y2hlZEluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaTIgKiAyICsgcG9zaXRpb25PZmZzZXQ7CiAgICAgICAgYmF0Y2hlZEluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaTIgKiAyICsgMSArIHBvc2l0aW9uT2Zmc2V0OwogICAgICAgIGJhdGNoZWRJbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGkxICogMiArIDEgKyBwb3NpdGlvbk9mZnNldDsKICAgICAgICBiYXRjaGVkSW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBpMCAqIDIgKyAxICsgcG9zaXRpb25PZmZzZXQ7CiAgICAgIH0KICAgICAgZm9yIChqID0gMDsgaiA8IHBvbHlnb25Db3VudDsgKytqKSB7CiAgICAgICAgY29uc3QgdjAyID0gajsKICAgICAgICBjb25zdCB2MTIgPSAoaiArIDEpICUgcG9seWdvbkNvdW50OwogICAgICAgIGJhdGNoZWRJbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHYwMiAqIDIgKyAxICsgcG9zaXRpb25PZmZzZXQ7CiAgICAgICAgYmF0Y2hlZEluZGljZXNbaW5kaWNlc0luZGV4KytdID0gdjEyICogMiArIHBvc2l0aW9uT2Zmc2V0OwogICAgICAgIGJhdGNoZWRJbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHYwMiAqIDIgKyBwb3NpdGlvbk9mZnNldDsKICAgICAgICBiYXRjaGVkSW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSB2MDIgKiAyICsgMSArIHBvc2l0aW9uT2Zmc2V0OwogICAgICAgIGJhdGNoZWRJbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IHYxMiAqIDIgKyAxICsgcG9zaXRpb25PZmZzZXQ7CiAgICAgICAgYmF0Y2hlZEluZGljZXNbaW5kaWNlc0luZGV4KytdID0gdjEyICogMiArIHBvc2l0aW9uT2Zmc2V0OwogICAgICB9CiAgICAgIGJ1ZmZlci5vZmZzZXQgKz0gcG9seWdvbkNvdW50ICogMjsKICAgICAgYnVmZmVyLmluZGV4T2Zmc2V0ID0gaW5kaWNlc0luZGV4OwogICAgICBiYXRjaGVkSW5kZXhDb3VudHNbaV0gPSBpbmRpY2VzSW5kZXggLSBiYXRjaGVkSW5kZXhPZmZzZXRzW2ldOwogICAgfQogICAgYmF0Y2hlZEluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgYmF0Y2hlZFBvc2l0aW9ucy5sZW5ndGggLyAzLAogICAgICBiYXRjaGVkSW5kaWNlcwogICAgKTsKICAgIGNvbnN0IGJhdGNoZWRJbmRpY2VzTGVuZ3RoID0gYmF0Y2hlZERyYXdDYWxscy5sZW5ndGg7CiAgICBmb3IgKGxldCBtID0gMDsgbSA8IGJhdGNoZWRJbmRpY2VzTGVuZ3RoOyArK20pIHsKICAgICAgY29uc3QgdGVtcElkcyA9IGJhdGNoZWREcmF3Q2FsbHNbbV0uYmF0Y2hJZHM7CiAgICAgIGxldCBjb3VudCA9IDA7CiAgICAgIGNvbnN0IHRlbXBJZHNMZW5ndGggPSB0ZW1wSWRzLmxlbmd0aDsKICAgICAgZm9yIChsZXQgbiA9IDA7IG4gPCB0ZW1wSWRzTGVuZ3RoOyArK24pIHsKICAgICAgICBjb3VudCArPSBiYXRjaGVkSW5kZXhDb3VudHNbdGVtcElkc1tuXV07CiAgICAgIH0KICAgICAgYmF0Y2hlZERyYXdDYWxsc1ttXS5jb3VudCA9IGNvdW50OwogICAgfQogICAgY29uc3QgaW5kZXhEYXRhdHlwZSA9IGJhdGNoZWRJbmRpY2VzLkJZVEVTX1BFUl9FTEVNRU5UID09PSAyID8gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX1NIT1JUIDogSW5kZXhEYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0lOVDsKICAgIGNvbnN0IHBhY2tlZEJ1ZmZlciA9IHBhY2tCdWZmZXIyKAogICAgICBpbmRleERhdGF0eXBlLAogICAgICBib3VuZGluZ1ZvbHVtZXMsCiAgICAgIGJhdGNoZWREcmF3Q2FsbHMKICAgICk7CiAgICB0cmFuc2ZlcmFibGVPYmplY3RzLnB1c2goCiAgICAgIGJhdGNoZWRQb3NpdGlvbnMuYnVmZmVyLAogICAgICBiYXRjaGVkSW5kaWNlcy5idWZmZXIsCiAgICAgIGJhdGNoZWRJbmRleE9mZnNldHMuYnVmZmVyLAogICAgICBiYXRjaGVkSW5kZXhDb3VudHMuYnVmZmVyLAogICAgICBiYXRjaGVkSWRzLmJ1ZmZlciwKICAgICAgcGFja2VkQnVmZmVyLmJ1ZmZlcgogICAgKTsKICAgIHJldHVybiB7CiAgICAgIHBvc2l0aW9uczogYmF0Y2hlZFBvc2l0aW9ucy5idWZmZXIsCiAgICAgIGluZGljZXM6IGJhdGNoZWRJbmRpY2VzLmJ1ZmZlciwKICAgICAgaW5kZXhPZmZzZXRzOiBiYXRjaGVkSW5kZXhPZmZzZXRzLmJ1ZmZlciwKICAgICAgaW5kZXhDb3VudHM6IGJhdGNoZWRJbmRleENvdW50cy5idWZmZXIsCiAgICAgIGJhdGNoSWRzOiBiYXRjaGVkSWRzLmJ1ZmZlciwKICAgICAgcGFja2VkQnVmZmVyOiBwYWNrZWRCdWZmZXIuYnVmZmVyCiAgICB9OwogIH0KICB2YXIgc2NyYXRjaENlbnRlcjYsIHNjcmF0Y2hFbGxpcHNvaWQxNSwgc2NyYXRjaFJlY3RhbmdsZTUsIHNjcmF0Y2hTY2FsYXJzLCBtYXhTaG9ydDIsIHNjcmF0Y2hFbmNvZGVkUG9zaXRpb24zLCBzY3JhdGNoTm9ybWFsNywgc2NyYXRjaFNjYWxlZE5vcm1hbCwgc2NyYXRjaE1pbkhlaWdodFBvc2l0aW9uLCBzY3JhdGNoTWF4SGVpZ2h0UG9zaXRpb24sIHNjcmF0Y2hCVkNhcnRvZ3JhcGhpYzMsIHNjcmF0Y2hCVlJlY3RhbmdsZSwgY3JlYXRlVmVjdG9yVGlsZVBvbHlnb25zX2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlVmVjdG9yVGlsZVBvbHlnb25zID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVWZWN0b3JUaWxlUG9seWdvbnMuanMiKCkgewogICAgICBpbml0X0F0dHJpYnV0ZUNvbXByZXNzaW9uKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X0NvbG9yKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0luZGV4RGF0YXR5cGUoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfT3JpZW50ZWRCb3VuZGluZ0JveCgpOwogICAgICBpbml0X1JlY3RhbmdsZSgpOwogICAgICBpbml0X2NyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXIoKTsKICAgICAgc2NyYXRjaENlbnRlcjYgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hFbGxpcHNvaWQxNSA9IG5ldyBFbGxpcHNvaWRfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoUmVjdGFuZ2xlNSA9IG5ldyBSZWN0YW5nbGVfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoU2NhbGFycyA9IHsKICAgICAgICBtaW46IHZvaWQgMCwKICAgICAgICBtYXg6IHZvaWQgMCwKICAgICAgICBpbmRleEJ5dGVzUGVyRWxlbWVudDogdm9pZCAwCiAgICAgIH07CiAgICAgIG1heFNob3J0MiA9IDMyNzY3OwogICAgICBzY3JhdGNoRW5jb2RlZFBvc2l0aW9uMyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE5vcm1hbDcgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hTY2FsZWROb3JtYWwgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hNaW5IZWlnaHRQb3NpdGlvbiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaE1heEhlaWdodFBvc2l0aW9uID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQlZDYXJ0b2dyYXBoaWMzID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hCVlJlY3RhbmdsZSA9IG5ldyBSZWN0YW5nbGVfZGVmYXVsdCgpOwogICAgICBjcmVhdGVWZWN0b3JUaWxlUG9seWdvbnNfZGVmYXVsdCA9IGNyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXJfZGVmYXVsdChjcmVhdGVWZWN0b3JUaWxlUG9seWdvbnMpOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvZGVjb2RlVmVjdG9yUG9seWxpbmVQb3NpdGlvbnMuanMKICBmdW5jdGlvbiBkZWNvZGVWZWN0b3JQb2x5bGluZVBvc2l0aW9ucyhwb3NpdGlvbnMsIHJlY3RhbmdsZSwgbWluaW11bUhlaWdodCwgbWF4aW11bUhlaWdodCwgZWxsaXBzb2lkKSB7CiAgICBjb25zdCBwb3NpdGlvbnNMZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoIC8gMzsKICAgIGNvbnN0IHVCdWZmZXIgPSBwb3NpdGlvbnMuc3ViYXJyYXkoMCwgcG9zaXRpb25zTGVuZ3RoKTsKICAgIGNvbnN0IHZCdWZmZXIgPSBwb3NpdGlvbnMuc3ViYXJyYXkocG9zaXRpb25zTGVuZ3RoLCAyICogcG9zaXRpb25zTGVuZ3RoKTsKICAgIGNvbnN0IGhlaWdodEJ1ZmZlciA9IHBvc2l0aW9ucy5zdWJhcnJheSgKICAgICAgMiAqIHBvc2l0aW9uc0xlbmd0aCwKICAgICAgMyAqIHBvc2l0aW9uc0xlbmd0aAogICAgKTsKICAgIEF0dHJpYnV0ZUNvbXByZXNzaW9uX2RlZmF1bHQuemlnWmFnRGVsdGFEZWNvZGUodUJ1ZmZlciwgdkJ1ZmZlciwgaGVpZ2h0QnVmZmVyKTsKICAgIGNvbnN0IGRlY29kZWQgPSBuZXcgRmxvYXQ2NEFycmF5KHBvc2l0aW9ucy5sZW5ndGgpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb3NpdGlvbnNMZW5ndGg7ICsraSkgewogICAgICBjb25zdCB1MyA9IHVCdWZmZXJbaV07CiAgICAgIGNvbnN0IHYzID0gdkJ1ZmZlcltpXTsKICAgICAgY29uc3QgaCA9IGhlaWdodEJ1ZmZlcltpXTsKICAgICAgY29uc3QgbG9uID0gTWF0aF9kZWZhdWx0LmxlcnAocmVjdGFuZ2xlLndlc3QsIHJlY3RhbmdsZS5lYXN0LCB1MyAvIG1heFNob3J0Myk7CiAgICAgIGNvbnN0IGxhdCA9IE1hdGhfZGVmYXVsdC5sZXJwKHJlY3RhbmdsZS5zb3V0aCwgcmVjdGFuZ2xlLm5vcnRoLCB2MyAvIG1heFNob3J0Myk7CiAgICAgIGNvbnN0IGFsdCA9IE1hdGhfZGVmYXVsdC5sZXJwKG1pbmltdW1IZWlnaHQsIG1heGltdW1IZWlnaHQsIGggLyBtYXhTaG9ydDMpOwogICAgICBjb25zdCBjYXJ0b2dyYXBoaWMyID0gQ2FydG9ncmFwaGljX2RlZmF1bHQuZnJvbVJhZGlhbnMoCiAgICAgICAgbG9uLAogICAgICAgIGxhdCwKICAgICAgICBhbHQsCiAgICAgICAgc2NyYXRjaEJWQ2FydG9ncmFwaGljNAogICAgICApOwogICAgICBjb25zdCBkZWNvZGVkUG9zaXRpb24gPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oCiAgICAgICAgY2FydG9ncmFwaGljMiwKICAgICAgICBzY3JhdGNoRW5jb2RlZFBvc2l0aW9uNAogICAgICApOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhkZWNvZGVkUG9zaXRpb24sIGRlY29kZWQsIGkgKiAzKTsKICAgIH0KICAgIHJldHVybiBkZWNvZGVkOwogIH0KICB2YXIgbWF4U2hvcnQzLCBzY3JhdGNoQlZDYXJ0b2dyYXBoaWM0LCBzY3JhdGNoRW5jb2RlZFBvc2l0aW9uNCwgZGVjb2RlVmVjdG9yUG9seWxpbmVQb3NpdGlvbnNfZGVmYXVsdDsKICB2YXIgaW5pdF9kZWNvZGVWZWN0b3JQb2x5bGluZVBvc2l0aW9ucyA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvZGVjb2RlVmVjdG9yUG9seWxpbmVQb3NpdGlvbnMuanMiKCkgewogICAgICBpbml0X0F0dHJpYnV0ZUNvbXByZXNzaW9uKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgbWF4U2hvcnQzID0gMzI3Njc7CiAgICAgIHNjcmF0Y2hCVkNhcnRvZ3JhcGhpYzQgPSBuZXcgQ2FydG9ncmFwaGljX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEVuY29kZWRQb3NpdGlvbjQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGRlY29kZVZlY3RvclBvbHlsaW5lUG9zaXRpb25zX2RlZmF1bHQgPSBkZWNvZGVWZWN0b3JQb2x5bGluZVBvc2l0aW9uczsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVZlY3RvclRpbGVQb2x5bGluZXMuanMKICB2YXIgY3JlYXRlVmVjdG9yVGlsZVBvbHlsaW5lc19leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlVmVjdG9yVGlsZVBvbHlsaW5lc19leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVWZWN0b3JUaWxlUG9seWxpbmVzX2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiB1bnBhY2tCdWZmZXI0KHBhY2tlZEJ1ZmZlcikgewogICAgcGFja2VkQnVmZmVyID0gbmV3IEZsb2F0NjRBcnJheShwYWNrZWRCdWZmZXIpOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICBzY3JhdGNoTWluTWF4SGVpZ2h0czIubWluID0gcGFja2VkQnVmZmVyW29mZnNldCsrXTsKICAgIHNjcmF0Y2hNaW5NYXhIZWlnaHRzMi5tYXggPSBwYWNrZWRCdWZmZXJbb2Zmc2V0KytdOwogICAgUmVjdGFuZ2xlX2RlZmF1bHQudW5wYWNrKHBhY2tlZEJ1ZmZlciwgb2Zmc2V0LCBzY3JhdGNoUmVjdGFuZ2xlNik7CiAgICBvZmZzZXQgKz0gUmVjdGFuZ2xlX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgRWxsaXBzb2lkX2RlZmF1bHQudW5wYWNrKHBhY2tlZEJ1ZmZlciwgb2Zmc2V0LCBzY3JhdGNoRWxsaXBzb2lkMTYpOwogICAgb2Zmc2V0ICs9IEVsbGlwc29pZF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2socGFja2VkQnVmZmVyLCBvZmZzZXQsIHNjcmF0Y2hDZW50ZXI3KTsKICB9CiAgZnVuY3Rpb24gZ2V0UG9zaXRpb25PZmZzZXRzMihjb3VudHMpIHsKICAgIGNvbnN0IGNvdW50c0xlbmd0aCA9IGNvdW50cy5sZW5ndGg7CiAgICBjb25zdCBwb3NpdGlvbk9mZnNldHMgPSBuZXcgVWludDMyQXJyYXkoY291bnRzTGVuZ3RoICsgMSk7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnRzTGVuZ3RoOyArK2kpIHsKICAgICAgcG9zaXRpb25PZmZzZXRzW2ldID0gb2Zmc2V0OwogICAgICBvZmZzZXQgKz0gY291bnRzW2ldOwogICAgfQogICAgcG9zaXRpb25PZmZzZXRzW2NvdW50c0xlbmd0aF0gPSBvZmZzZXQ7CiAgICByZXR1cm4gcG9zaXRpb25PZmZzZXRzOwogIH0KICBmdW5jdGlvbiBjcmVhdGVWZWN0b3JUaWxlUG9seWxpbmVzKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIGNvbnN0IGVuY29kZWRQb3NpdGlvbnMgPSBuZXcgVWludDE2QXJyYXkocGFyYW1ldGVycy5wb3NpdGlvbnMpOwogICAgY29uc3Qgd2lkdGhzID0gbmV3IFVpbnQxNkFycmF5KHBhcmFtZXRlcnMud2lkdGhzKTsKICAgIGNvbnN0IGNvdW50cyA9IG5ldyBVaW50MzJBcnJheShwYXJhbWV0ZXJzLmNvdW50cyk7CiAgICBjb25zdCBiYXRjaElkcyA9IG5ldyBVaW50MTZBcnJheShwYXJhbWV0ZXJzLmJhdGNoSWRzKTsKICAgIHVucGFja0J1ZmZlcjQocGFyYW1ldGVycy5wYWNrZWRCdWZmZXIpOwogICAgY29uc3QgcmVjdGFuZ2xlID0gc2NyYXRjaFJlY3RhbmdsZTY7CiAgICBjb25zdCBlbGxpcHNvaWQgPSBzY3JhdGNoRWxsaXBzb2lkMTY7CiAgICBjb25zdCBjZW50ZXIgPSBzY3JhdGNoQ2VudGVyNzsKICAgIGNvbnN0IG1pbmltdW1IZWlnaHQgPSBzY3JhdGNoTWluTWF4SGVpZ2h0czIubWluOwogICAgY29uc3QgbWF4aW11bUhlaWdodCA9IHNjcmF0Y2hNaW5NYXhIZWlnaHRzMi5tYXg7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBkZWNvZGVWZWN0b3JQb2x5bGluZVBvc2l0aW9uc19kZWZhdWx0KAogICAgICBlbmNvZGVkUG9zaXRpb25zLAogICAgICByZWN0YW5nbGUsCiAgICAgIG1pbmltdW1IZWlnaHQsCiAgICAgIG1heGltdW1IZWlnaHQsCiAgICAgIGVsbGlwc29pZAogICAgKTsKICAgIGNvbnN0IHBvc2l0aW9uc0xlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGggLyAzOwogICAgY29uc3Qgc2l6ZSA9IHBvc2l0aW9uc0xlbmd0aCAqIDQgLSA0OwogICAgY29uc3QgY3VyUG9zaXRpb25zID0gbmV3IEZsb2F0MzJBcnJheShzaXplICogMyk7CiAgICBjb25zdCBwcmV2UG9zaXRpb25zID0gbmV3IEZsb2F0MzJBcnJheShzaXplICogMyk7CiAgICBjb25zdCBuZXh0UG9zaXRpb25zID0gbmV3IEZsb2F0MzJBcnJheShzaXplICogMyk7CiAgICBjb25zdCBleHBhbmRBbmRXaWR0aCA9IG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSAqIDIpOwogICAgY29uc3QgdmVydGV4QmF0Y2hJZHMgPSBuZXcgVWludDE2QXJyYXkoc2l6ZSk7CiAgICBsZXQgcG9zaXRpb25JbmRleCA9IDA7CiAgICBsZXQgZXhwYW5kQW5kV2lkdGhJbmRleCA9IDA7CiAgICBsZXQgYmF0Y2hJZEluZGV4ID0gMDsKICAgIGxldCBpOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICBsZXQgbGVuZ3RoID0gY291bnRzLmxlbmd0aDsKICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBjb25zdCBjb3VudCA9IGNvdW50c1tpXTsKICAgICAgY29uc3Qgd2lkdGggPSB3aWR0aHNbaV07CiAgICAgIGNvbnN0IGJhdGNoSWQgPSBiYXRjaElkc1tpXTsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBjb3VudDsgKytqKSB7CiAgICAgICAgbGV0IHByZXZpb3VzOwogICAgICAgIGlmIChqID09PSAwKSB7CiAgICAgICAgICBjb25zdCBwMCA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2socG9zaXRpb25zLCBvZmZzZXQgKiAzLCBzY3JhdGNoUDAyKTsKICAgICAgICAgIGNvbnN0IHAxID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjayhwb3NpdGlvbnMsIChvZmZzZXQgKyAxKSAqIDMsIHNjcmF0Y2hQMTIpOwogICAgICAgICAgcHJldmlvdXMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QocDAsIHAxLCBzY3JhdGNoUHJldjIpOwogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmFkZChwMCwgcHJldmlvdXMsIHByZXZpb3VzKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcHJldmlvdXMgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICAgIChvZmZzZXQgKyBqIC0gMSkgKiAzLAogICAgICAgICAgICBzY3JhdGNoUHJldjIKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGN1cnJlbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgKG9mZnNldCArIGopICogMywKICAgICAgICAgIHNjcmF0Y2hDdXIKICAgICAgICApOwogICAgICAgIGxldCBuZXh0OwogICAgICAgIGlmIChqID09PSBjb3VudCAtIDEpIHsKICAgICAgICAgIGNvbnN0IHAyID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjaygKICAgICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgICAob2Zmc2V0ICsgY291bnQgLSAxKSAqIDMsCiAgICAgICAgICAgIHNjcmF0Y2hQMDIKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBwMyA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soCiAgICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgICAgKG9mZnNldCArIGNvdW50IC0gMikgKiAzLAogICAgICAgICAgICBzY3JhdGNoUDEyCiAgICAgICAgICApOwogICAgICAgICAgbmV4dCA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdChwMiwgcDMsIHNjcmF0Y2hOZXh0Mik7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuYWRkKHAyLCBuZXh0LCBuZXh0KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbmV4dCA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2socG9zaXRpb25zLCAob2Zmc2V0ICsgaiArIDEpICogMywgc2NyYXRjaE5leHQyKTsKICAgICAgICB9CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnN1YnRyYWN0KHByZXZpb3VzLCBjZW50ZXIsIHByZXZpb3VzKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoY3VycmVudCwgY2VudGVyLCBjdXJyZW50KTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QobmV4dCwgY2VudGVyLCBuZXh0KTsKICAgICAgICBjb25zdCBzdGFydEsgPSBqID09PSAwID8gMiA6IDA7CiAgICAgICAgY29uc3QgZW5kSyA9IGogPT09IGNvdW50IC0gMSA/IDIgOiA0OwogICAgICAgIGZvciAobGV0IGsgPSBzdGFydEs7IGsgPCBlbmRLOyArK2spIHsKICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKGN1cnJlbnQsIGN1clBvc2l0aW9ucywgcG9zaXRpb25JbmRleCk7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhwcmV2aW91cywgcHJldlBvc2l0aW9ucywgcG9zaXRpb25JbmRleCk7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhuZXh0LCBuZXh0UG9zaXRpb25zLCBwb3NpdGlvbkluZGV4KTsKICAgICAgICAgIHBvc2l0aW9uSW5kZXggKz0gMzsKICAgICAgICAgIGNvbnN0IGRpcmVjdGlvbjIgPSBrIC0gMiA8IDAgPyAtMSA6IDE7CiAgICAgICAgICBleHBhbmRBbmRXaWR0aFtleHBhbmRBbmRXaWR0aEluZGV4KytdID0gMiAqIChrICUgMikgLSAxOwogICAgICAgICAgZXhwYW5kQW5kV2lkdGhbZXhwYW5kQW5kV2lkdGhJbmRleCsrXSA9IGRpcmVjdGlvbjIgKiB3aWR0aDsKICAgICAgICAgIHZlcnRleEJhdGNoSWRzW2JhdGNoSWRJbmRleCsrXSA9IGJhdGNoSWQ7CiAgICAgICAgfQogICAgICB9CiAgICAgIG9mZnNldCArPSBjb3VudDsKICAgIH0KICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheShzaXplLCBwb3NpdGlvbnNMZW5ndGggKiA2IC0gNik7CiAgICBsZXQgaW5kZXggPSAwOwogICAgbGV0IGluZGljZXNJbmRleCA9IDA7CiAgICBsZW5ndGggPSBwb3NpdGlvbnNMZW5ndGggLSAxOwogICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaW5kZXg7CiAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaW5kZXggKyAyOwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGluZGV4ICsgMTsKICAgICAgaW5kaWNlc1tpbmRpY2VzSW5kZXgrK10gPSBpbmRleCArIDE7CiAgICAgIGluZGljZXNbaW5kaWNlc0luZGV4KytdID0gaW5kZXggKyAyOwogICAgICBpbmRpY2VzW2luZGljZXNJbmRleCsrXSA9IGluZGV4ICsgMzsKICAgICAgaW5kZXggKz0gNDsKICAgIH0KICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaCgKICAgICAgY3VyUG9zaXRpb25zLmJ1ZmZlciwKICAgICAgcHJldlBvc2l0aW9ucy5idWZmZXIsCiAgICAgIG5leHRQb3NpdGlvbnMuYnVmZmVyCiAgICApOwogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKAogICAgICBleHBhbmRBbmRXaWR0aC5idWZmZXIsCiAgICAgIHZlcnRleEJhdGNoSWRzLmJ1ZmZlciwKICAgICAgaW5kaWNlcy5idWZmZXIKICAgICk7CiAgICBsZXQgcmVzdWx0cyA9IHsKICAgICAgaW5kZXhEYXRhdHlwZTogaW5kaWNlcy5CWVRFU19QRVJfRUxFTUVOVCA9PT0gMiA/IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9TSE9SVCA6IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9JTlQsCiAgICAgIGN1cnJlbnRQb3NpdGlvbnM6IGN1clBvc2l0aW9ucy5idWZmZXIsCiAgICAgIHByZXZpb3VzUG9zaXRpb25zOiBwcmV2UG9zaXRpb25zLmJ1ZmZlciwKICAgICAgbmV4dFBvc2l0aW9uczogbmV4dFBvc2l0aW9ucy5idWZmZXIsCiAgICAgIGV4cGFuZEFuZFdpZHRoOiBleHBhbmRBbmRXaWR0aC5idWZmZXIsCiAgICAgIGJhdGNoSWRzOiB2ZXJ0ZXhCYXRjaElkcy5idWZmZXIsCiAgICAgIGluZGljZXM6IGluZGljZXMuYnVmZmVyCiAgICB9OwogICAgaWYgKHBhcmFtZXRlcnMua2VlcERlY29kZWRQb3NpdGlvbnMpIHsKICAgICAgY29uc3QgcG9zaXRpb25PZmZzZXRzID0gZ2V0UG9zaXRpb25PZmZzZXRzMihjb3VudHMpOwogICAgICB0cmFuc2ZlcmFibGVPYmplY3RzLnB1c2gocG9zaXRpb25zLmJ1ZmZlciwgcG9zaXRpb25PZmZzZXRzLmJ1ZmZlcik7CiAgICAgIHJlc3VsdHMgPSBjb21iaW5lX2RlZmF1bHQocmVzdWx0cywgewogICAgICAgIGRlY29kZWRQb3NpdGlvbnM6IHBvc2l0aW9ucy5idWZmZXIsCiAgICAgICAgZGVjb2RlZFBvc2l0aW9uT2Zmc2V0czogcG9zaXRpb25PZmZzZXRzLmJ1ZmZlcgogICAgICB9KTsKICAgIH0KICAgIHJldHVybiByZXN1bHRzOwogIH0KICB2YXIgc2NyYXRjaFJlY3RhbmdsZTYsIHNjcmF0Y2hFbGxpcHNvaWQxNiwgc2NyYXRjaENlbnRlcjcsIHNjcmF0Y2hNaW5NYXhIZWlnaHRzMiwgc2NyYXRjaFAwMiwgc2NyYXRjaFAxMiwgc2NyYXRjaFByZXYyLCBzY3JhdGNoQ3VyLCBzY3JhdGNoTmV4dDIsIGNyZWF0ZVZlY3RvclRpbGVQb2x5bGluZXNfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVWZWN0b3JUaWxlUG9seWxpbmVzID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVWZWN0b3JUaWxlUG9seWxpbmVzLmpzIigpIHsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfY29tYmluZSgpOwogICAgICBpbml0X2RlY29kZVZlY3RvclBvbHlsaW5lUG9zaXRpb25zKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfSW5kZXhEYXRhdHlwZSgpOwogICAgICBpbml0X1JlY3RhbmdsZSgpOwogICAgICBpbml0X2NyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXIoKTsKICAgICAgc2NyYXRjaFJlY3RhbmdsZTYgPSBuZXcgUmVjdGFuZ2xlX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaEVsbGlwc29pZDE2ID0gbmV3IEVsbGlwc29pZF9kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDZW50ZXI3ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoTWluTWF4SGVpZ2h0czIgPSB7CiAgICAgICAgbWluOiB2b2lkIDAsCiAgICAgICAgbWF4OiB2b2lkIDAKICAgICAgfTsKICAgICAgc2NyYXRjaFAwMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFAxMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaFByZXYyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ3VyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoTmV4dDIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNyZWF0ZVZlY3RvclRpbGVQb2x5bGluZXNfZGVmYXVsdCA9IGNyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXJfZGVmYXVsdChjcmVhdGVWZWN0b3JUaWxlUG9seWxpbmVzKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0VsbGlwc29pZGFsT2NjbHVkZXIuanMKICBmdW5jdGlvbiBFbGxpcHNvaWRhbE9jY2x1ZGVyKGVsbGlwc29pZCwgY2FtZXJhUG9zaXRpb24pIHsKICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgiZWxsaXBzb2lkIiwgZWxsaXBzb2lkKTsKICAgIHRoaXMuX2VsbGlwc29pZCA9IGVsbGlwc29pZDsKICAgIHRoaXMuX2NhbWVyYVBvc2l0aW9uID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgdGhpcy5fY2FtZXJhUG9zaXRpb25JblNjYWxlZFNwYWNlID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgdGhpcy5fZGlzdGFuY2VUb0xpbWJJblNjYWxlZFNwYWNlU3F1YXJlZCA9IDA7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGNhbWVyYVBvc2l0aW9uKSkgewogICAgICB0aGlzLmNhbWVyYVBvc2l0aW9uID0gY2FtZXJhUG9zaXRpb247CiAgICB9CiAgfQogIGZ1bmN0aW9uIGdldFBvc3NpYmx5U2hydW5rRWxsaXBzb2lkKGVsbGlwc29pZCwgbWluaW11bUhlaWdodCwgcmVzdWx0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG1pbmltdW1IZWlnaHQpICYmIG1pbmltdW1IZWlnaHQgPCAwICYmIGVsbGlwc29pZC5taW5pbXVtUmFkaXVzID4gLW1pbmltdW1IZWlnaHQpIHsKICAgICAgY29uc3QgZWxsaXBzb2lkU2hydW5rUmFkaWkgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUVsZW1lbnRzKAogICAgICAgIGVsbGlwc29pZC5yYWRpaS54ICsgbWluaW11bUhlaWdodCwKICAgICAgICBlbGxpcHNvaWQucmFkaWkueSArIG1pbmltdW1IZWlnaHQsCiAgICAgICAgZWxsaXBzb2lkLnJhZGlpLnogKyBtaW5pbXVtSGVpZ2h0LAogICAgICAgIHNjcmF0Y2hFbGxpcHNvaWRTaHJ1bmtSYWRpaQogICAgICApOwogICAgICBlbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5mcm9tQ2FydGVzaWFuMyhlbGxpcHNvaWRTaHJ1bmtSYWRpaSwgcmVzdWx0KTsKICAgIH0KICAgIHJldHVybiBlbGxpcHNvaWQ7CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVIb3Jpem9uQ3VsbGluZ1BvaW50RnJvbVBvc2l0aW9ucyhlbGxpcHNvaWQsIGRpcmVjdGlvblRvUG9pbnQsIHBvc2l0aW9ucywgcmVzdWx0KSB7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImRpcmVjdGlvblRvUG9pbnQiLCBkaXJlY3Rpb25Ub1BvaW50KTsKICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgicG9zaXRpb25zIiwgcG9zaXRpb25zKTsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgfQogICAgY29uc3Qgc2NhbGVkU3BhY2VEaXJlY3Rpb25Ub1BvaW50ID0gY29tcHV0ZVNjYWxlZFNwYWNlRGlyZWN0aW9uVG9Qb2ludCgKICAgICAgZWxsaXBzb2lkLAogICAgICBkaXJlY3Rpb25Ub1BvaW50CiAgICApOwogICAgbGV0IHJlc3VsdE1hZ25pdHVkZSA9IDA7CiAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gcG9zaXRpb25zLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7CiAgICAgIGNvbnN0IHBvc2l0aW9uID0gcG9zaXRpb25zW2ldOwogICAgICBjb25zdCBjYW5kaWRhdGVNYWduaXR1ZGUgPSBjb21wdXRlTWFnbml0dWRlKAogICAgICAgIGVsbGlwc29pZCwKICAgICAgICBwb3NpdGlvbiwKICAgICAgICBzY2FsZWRTcGFjZURpcmVjdGlvblRvUG9pbnQKICAgICAgKTsKICAgICAgaWYgKGNhbmRpZGF0ZU1hZ25pdHVkZSA8IDApIHsKICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICB9CiAgICAgIHJlc3VsdE1hZ25pdHVkZSA9IE1hdGgubWF4KHJlc3VsdE1hZ25pdHVkZSwgY2FuZGlkYXRlTWFnbml0dWRlKTsKICAgIH0KICAgIHJldHVybiBtYWduaXR1ZGVUb1BvaW50KHNjYWxlZFNwYWNlRGlyZWN0aW9uVG9Qb2ludCwgcmVzdWx0TWFnbml0dWRlLCByZXN1bHQpOwogIH0KICBmdW5jdGlvbiBjb21wdXRlSG9yaXpvbkN1bGxpbmdQb2ludEZyb21WZXJ0aWNlcyhlbGxpcHNvaWQsIGRpcmVjdGlvblRvUG9pbnQsIHZlcnRpY2VzLCBzdHJpZGUsIGNlbnRlciwgcmVzdWx0KSB7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5vYmplY3QoImRpcmVjdGlvblRvUG9pbnQiLCBkaXJlY3Rpb25Ub1BvaW50KTsKICAgIENoZWNrX2RlZmF1bHQuZGVmaW5lZCgidmVydGljZXMiLCB2ZXJ0aWNlcyk7CiAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInN0cmlkZSIsIHN0cmlkZSk7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgIHJlc3VsdCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgIH0KICAgIHN0cmlkZSA9IHN0cmlkZSA/PyAzOwogICAgY2VudGVyID0gY2VudGVyID8/IENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPOwogICAgY29uc3Qgc2NhbGVkU3BhY2VEaXJlY3Rpb25Ub1BvaW50ID0gY29tcHV0ZVNjYWxlZFNwYWNlRGlyZWN0aW9uVG9Qb2ludCgKICAgICAgZWxsaXBzb2lkLAogICAgICBkaXJlY3Rpb25Ub1BvaW50CiAgICApOwogICAgbGV0IHJlc3VsdE1hZ25pdHVkZSA9IDA7CiAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gdmVydGljZXMubGVuZ3RoOyBpIDwgbGVuOyBpICs9IHN0cmlkZSkgewogICAgICBwb3NpdGlvblNjcmF0Y2g1LnggPSB2ZXJ0aWNlc1tpXSArIGNlbnRlci54OwogICAgICBwb3NpdGlvblNjcmF0Y2g1LnkgPSB2ZXJ0aWNlc1tpICsgMV0gKyBjZW50ZXIueTsKICAgICAgcG9zaXRpb25TY3JhdGNoNS56ID0gdmVydGljZXNbaSArIDJdICsgY2VudGVyLno7CiAgICAgIGNvbnN0IGNhbmRpZGF0ZU1hZ25pdHVkZSA9IGNvbXB1dGVNYWduaXR1ZGUoCiAgICAgICAgZWxsaXBzb2lkLAogICAgICAgIHBvc2l0aW9uU2NyYXRjaDUsCiAgICAgICAgc2NhbGVkU3BhY2VEaXJlY3Rpb25Ub1BvaW50CiAgICAgICk7CiAgICAgIGlmIChjYW5kaWRhdGVNYWduaXR1ZGUgPCAwKSB7CiAgICAgICAgcmV0dXJuIHZvaWQgMDsKICAgICAgfQogICAgICByZXN1bHRNYWduaXR1ZGUgPSBNYXRoLm1heChyZXN1bHRNYWduaXR1ZGUsIGNhbmRpZGF0ZU1hZ25pdHVkZSk7CiAgICB9CiAgICByZXR1cm4gbWFnbml0dWRlVG9Qb2ludChzY2FsZWRTcGFjZURpcmVjdGlvblRvUG9pbnQsIHJlc3VsdE1hZ25pdHVkZSwgcmVzdWx0KTsKICB9CiAgZnVuY3Rpb24gaXNTY2FsZWRTcGFjZVBvaW50VmlzaWJsZShvY2NsdWRlZVNjYWxlZFNwYWNlUG9zaXRpb24sIGNhbWVyYVBvc2l0aW9uSW5TY2FsZWRTcGFjZSwgZGlzdGFuY2VUb0xpbWJJblNjYWxlZFNwYWNlU3F1YXJlZCkgewogICAgY29uc3QgY3YgPSBjYW1lcmFQb3NpdGlvbkluU2NhbGVkU3BhY2U7CiAgICBjb25zdCB2aE1hZ25pdHVkZVNxdWFyZWQgPSBkaXN0YW5jZVRvTGltYkluU2NhbGVkU3BhY2VTcXVhcmVkOwogICAgY29uc3QgdnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgIG9jY2x1ZGVlU2NhbGVkU3BhY2VQb3NpdGlvbiwKICAgICAgY3YsCiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4xOQogICAgKTsKICAgIGNvbnN0IHZ0RG90VmMgPSAtQ2FydGVzaWFuM19kZWZhdWx0LmRvdCh2dCwgY3YpOwogICAgY29uc3QgaXNPY2NsdWRlZCA9IHZoTWFnbml0dWRlU3F1YXJlZCA8IDAgPyB2dERvdFZjID4gMCA6IHZ0RG90VmMgPiB2aE1hZ25pdHVkZVNxdWFyZWQgJiYgdnREb3RWYyAqIHZ0RG90VmMgLyBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlU3F1YXJlZCh2dCkgPiB2aE1hZ25pdHVkZVNxdWFyZWQ7CiAgICByZXR1cm4gIWlzT2NjbHVkZWQ7CiAgfQogIGZ1bmN0aW9uIGNvbXB1dGVNYWduaXR1ZGUoZWxsaXBzb2lkLCBwb3NpdGlvbiwgc2NhbGVkU3BhY2VEaXJlY3Rpb25Ub1BvaW50KSB7CiAgICBjb25zdCBzY2FsZWRTcGFjZVBvc2l0aW9uID0gZWxsaXBzb2lkLnRyYW5zZm9ybVBvc2l0aW9uVG9TY2FsZWRTcGFjZSgKICAgICAgcG9zaXRpb24sCiAgICAgIHNjYWxlZFNwYWNlU2NyYXRjaAogICAgKTsKICAgIGxldCBtYWduaXR1ZGVTcXVhcmVkID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZVNxdWFyZWQoc2NhbGVkU3BhY2VQb3NpdGlvbik7CiAgICBsZXQgbWFnbml0dWRlID0gTWF0aC5zcXJ0KG1hZ25pdHVkZVNxdWFyZWQpOwogICAgY29uc3QgZGlyZWN0aW9uMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5kaXZpZGVCeVNjYWxhcigKICAgICAgc2NhbGVkU3BhY2VQb3NpdGlvbiwKICAgICAgbWFnbml0dWRlLAogICAgICBkaXJlY3Rpb25TY3JhdGNoCiAgICApOwogICAgbWFnbml0dWRlU3F1YXJlZCA9IE1hdGgubWF4KDEsIG1hZ25pdHVkZVNxdWFyZWQpOwogICAgbWFnbml0dWRlID0gTWF0aC5tYXgoMSwgbWFnbml0dWRlKTsKICAgIGNvbnN0IGNvc0FscGhhID0gQ2FydGVzaWFuM19kZWZhdWx0LmRvdChkaXJlY3Rpb24yLCBzY2FsZWRTcGFjZURpcmVjdGlvblRvUG9pbnQpOwogICAgY29uc3Qgc2luQWxwaGEgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKAogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoZGlyZWN0aW9uMiwgc2NhbGVkU3BhY2VEaXJlY3Rpb25Ub1BvaW50LCBkaXJlY3Rpb24yKQogICAgKTsKICAgIGNvbnN0IGNvc0JldGEgPSAxIC8gbWFnbml0dWRlOwogICAgY29uc3Qgc2luQmV0YSA9IE1hdGguc3FydChtYWduaXR1ZGVTcXVhcmVkIC0gMSkgKiBjb3NCZXRhOwogICAgcmV0dXJuIDEgLyAoY29zQWxwaGEgKiBjb3NCZXRhIC0gc2luQWxwaGEgKiBzaW5CZXRhKTsKICB9CiAgZnVuY3Rpb24gbWFnbml0dWRlVG9Qb2ludChzY2FsZWRTcGFjZURpcmVjdGlvblRvUG9pbnQsIHJlc3VsdE1hZ25pdHVkZSwgcmVzdWx0KSB7CiAgICBpZiAocmVzdWx0TWFnbml0dWRlIDw9IDAgfHwgcmVzdWx0TWFnbml0dWRlID09PSAxIC8gMCB8fCByZXN1bHRNYWduaXR1ZGUgIT09IHJlc3VsdE1hZ25pdHVkZSkgewogICAgICByZXR1cm4gdm9pZCAwOwogICAgfQogICAgcmV0dXJuIENhcnRlc2lhbjNfZGVmYXVsdC5tdWx0aXBseUJ5U2NhbGFyKAogICAgICBzY2FsZWRTcGFjZURpcmVjdGlvblRvUG9pbnQsCiAgICAgIHJlc3VsdE1hZ25pdHVkZSwKICAgICAgcmVzdWx0CiAgICApOwogIH0KICBmdW5jdGlvbiBjb21wdXRlU2NhbGVkU3BhY2VEaXJlY3Rpb25Ub1BvaW50KGVsbGlwc29pZCwgZGlyZWN0aW9uVG9Qb2ludCkgewogICAgaWYgKENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHMoZGlyZWN0aW9uVG9Qb2ludCwgQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8pKSB7CiAgICAgIHJldHVybiBkaXJlY3Rpb25Ub1BvaW50OwogICAgfQogICAgZWxsaXBzb2lkLnRyYW5zZm9ybVBvc2l0aW9uVG9TY2FsZWRTcGFjZSgKICAgICAgZGlyZWN0aW9uVG9Qb2ludCwKICAgICAgZGlyZWN0aW9uVG9Qb2ludFNjcmF0Y2gKICAgICk7CiAgICByZXR1cm4gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZShkaXJlY3Rpb25Ub1BvaW50U2NyYXRjaCwgZGlyZWN0aW9uVG9Qb2ludFNjcmF0Y2gpOwogIH0KICB2YXIgc2NyYXRjaENhcnRlc2lhbjE5LCBzY3JhdGNoQ2FtZXJhUG9zaXRpb25JblNjYWxlZFNwYWNlU2hydW5rLCBzY3JhdGNoRWxsaXBzb2lkU2hydW5rLCBzdWJzYW1wbGVTY3JhdGNoLCBzY3JhdGNoRWxsaXBzb2lkU2hydW5rUmFkaWksIHBvc2l0aW9uU2NyYXRjaDUsIHNjYWxlZFNwYWNlU2NyYXRjaCwgZGlyZWN0aW9uU2NyYXRjaCwgZGlyZWN0aW9uVG9Qb2ludFNjcmF0Y2gsIEVsbGlwc29pZGFsT2NjbHVkZXJfZGVmYXVsdDsKICB2YXIgaW5pdF9FbGxpcHNvaWRhbE9jY2x1ZGVyID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9FbGxpcHNvaWRhbE9jY2x1ZGVyLmpzIigpIHsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9SZWN0YW5nbGUoKTsKICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoRWxsaXBzb2lkYWxPY2NsdWRlci5wcm90b3R5cGUsIHsKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBvY2NsdWRpbmcgZWxsaXBzb2lkLgogICAgICAgICAqIEBtZW1iZXJvZiBFbGxpcHNvaWRhbE9jY2x1ZGVyLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtFbGxpcHNvaWR9CiAgICAgICAgICovCiAgICAgICAgZWxsaXBzb2lkOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fZWxsaXBzb2lkOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyBvciBzZXRzIHRoZSBwb3NpdGlvbiBvZiB0aGUgY2FtZXJhLgogICAgICAgICAqIEBtZW1iZXJvZiBFbGxpcHNvaWRhbE9jY2x1ZGVyLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtDYXJ0ZXNpYW4zfQogICAgICAgICAqLwogICAgICAgIGNhbWVyYVBvc2l0aW9uOiB7CiAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5fY2FtZXJhUG9zaXRpb247CiAgICAgICAgICB9LAogICAgICAgICAgc2V0OiBmdW5jdGlvbihjYW1lcmFQb3NpdGlvbikgewogICAgICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSB0aGlzLl9lbGxpcHNvaWQ7CiAgICAgICAgICAgIGNvbnN0IGN2ID0gZWxsaXBzb2lkLnRyYW5zZm9ybVBvc2l0aW9uVG9TY2FsZWRTcGFjZSgKICAgICAgICAgICAgICBjYW1lcmFQb3NpdGlvbiwKICAgICAgICAgICAgICB0aGlzLl9jYW1lcmFQb3NpdGlvbkluU2NhbGVkU3BhY2UKICAgICAgICAgICAgKTsKICAgICAgICAgICAgY29uc3QgdmhNYWduaXR1ZGVTcXVhcmVkID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZVNxdWFyZWQoY3YpIC0gMTsKICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGNhbWVyYVBvc2l0aW9uLCB0aGlzLl9jYW1lcmFQb3NpdGlvbik7CiAgICAgICAgICAgIHRoaXMuX2NhbWVyYVBvc2l0aW9uSW5TY2FsZWRTcGFjZSA9IGN2OwogICAgICAgICAgICB0aGlzLl9kaXN0YW5jZVRvTGltYkluU2NhbGVkU3BhY2VTcXVhcmVkID0gdmhNYWduaXR1ZGVTcXVhcmVkOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4xOSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgRWxsaXBzb2lkYWxPY2NsdWRlci5wcm90b3R5cGUuaXNQb2ludFZpc2libGUgPSBmdW5jdGlvbihvY2NsdWRlZSkgewogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IHRoaXMuX2VsbGlwc29pZDsKICAgICAgICBjb25zdCBvY2NsdWRlZVNjYWxlZFNwYWNlUG9zaXRpb24gPSBlbGxpcHNvaWQudHJhbnNmb3JtUG9zaXRpb25Ub1NjYWxlZFNwYWNlKAogICAgICAgICAgb2NjbHVkZWUsCiAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuMTkKICAgICAgICApOwogICAgICAgIHJldHVybiBpc1NjYWxlZFNwYWNlUG9pbnRWaXNpYmxlKAogICAgICAgICAgb2NjbHVkZWVTY2FsZWRTcGFjZVBvc2l0aW9uLAogICAgICAgICAgdGhpcy5fY2FtZXJhUG9zaXRpb25JblNjYWxlZFNwYWNlLAogICAgICAgICAgdGhpcy5fZGlzdGFuY2VUb0xpbWJJblNjYWxlZFNwYWNlU3F1YXJlZAogICAgICAgICk7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZGFsT2NjbHVkZXIucHJvdG90eXBlLmlzU2NhbGVkU3BhY2VQb2ludFZpc2libGUgPSBmdW5jdGlvbihvY2NsdWRlZVNjYWxlZFNwYWNlUG9zaXRpb24pIHsKICAgICAgICByZXR1cm4gaXNTY2FsZWRTcGFjZVBvaW50VmlzaWJsZSgKICAgICAgICAgIG9jY2x1ZGVlU2NhbGVkU3BhY2VQb3NpdGlvbiwKICAgICAgICAgIHRoaXMuX2NhbWVyYVBvc2l0aW9uSW5TY2FsZWRTcGFjZSwKICAgICAgICAgIHRoaXMuX2Rpc3RhbmNlVG9MaW1iSW5TY2FsZWRTcGFjZVNxdWFyZWQKICAgICAgICApOwogICAgICB9OwogICAgICBzY3JhdGNoQ2FtZXJhUG9zaXRpb25JblNjYWxlZFNwYWNlU2hydW5rID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBFbGxpcHNvaWRhbE9jY2x1ZGVyLnByb3RvdHlwZS5pc1NjYWxlZFNwYWNlUG9pbnRWaXNpYmxlUG9zc2libHlVbmRlckVsbGlwc29pZCA9IGZ1bmN0aW9uKG9jY2x1ZGVlU2NhbGVkU3BhY2VQb3NpdGlvbiwgbWluaW11bUhlaWdodCkgewogICAgICAgIGNvbnN0IGVsbGlwc29pZCA9IHRoaXMuX2VsbGlwc29pZDsKICAgICAgICBsZXQgdmhNYWduaXR1ZGVTcXVhcmVkOwogICAgICAgIGxldCBjdjsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG1pbmltdW1IZWlnaHQpICYmIG1pbmltdW1IZWlnaHQgPCAwICYmIGVsbGlwc29pZC5taW5pbXVtUmFkaXVzID4gLW1pbmltdW1IZWlnaHQpIHsKICAgICAgICAgIGN2ID0gc2NyYXRjaENhbWVyYVBvc2l0aW9uSW5TY2FsZWRTcGFjZVNocnVuazsKICAgICAgICAgIGN2LnggPSB0aGlzLl9jYW1lcmFQb3NpdGlvbi54IC8gKGVsbGlwc29pZC5yYWRpaS54ICsgbWluaW11bUhlaWdodCk7CiAgICAgICAgICBjdi55ID0gdGhpcy5fY2FtZXJhUG9zaXRpb24ueSAvIChlbGxpcHNvaWQucmFkaWkueSArIG1pbmltdW1IZWlnaHQpOwogICAgICAgICAgY3YueiA9IHRoaXMuX2NhbWVyYVBvc2l0aW9uLnogLyAoZWxsaXBzb2lkLnJhZGlpLnogKyBtaW5pbXVtSGVpZ2h0KTsKICAgICAgICAgIHZoTWFnbml0dWRlU3F1YXJlZCA9IGN2LnggKiBjdi54ICsgY3YueSAqIGN2LnkgKyBjdi56ICogY3YueiAtIDE7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGN2ID0gdGhpcy5fY2FtZXJhUG9zaXRpb25JblNjYWxlZFNwYWNlOwogICAgICAgICAgdmhNYWduaXR1ZGVTcXVhcmVkID0gdGhpcy5fZGlzdGFuY2VUb0xpbWJJblNjYWxlZFNwYWNlU3F1YXJlZDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGlzU2NhbGVkU3BhY2VQb2ludFZpc2libGUoCiAgICAgICAgICBvY2NsdWRlZVNjYWxlZFNwYWNlUG9zaXRpb24sCiAgICAgICAgICBjdiwKICAgICAgICAgIHZoTWFnbml0dWRlU3F1YXJlZAogICAgICAgICk7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZGFsT2NjbHVkZXIucHJvdG90eXBlLmNvbXB1dGVIb3Jpem9uQ3VsbGluZ1BvaW50ID0gZnVuY3Rpb24oZGlyZWN0aW9uVG9Qb2ludCwgcG9zaXRpb25zLCByZXN1bHQpIHsKICAgICAgICByZXR1cm4gY29tcHV0ZUhvcml6b25DdWxsaW5nUG9pbnRGcm9tUG9zaXRpb25zKAogICAgICAgICAgdGhpcy5fZWxsaXBzb2lkLAogICAgICAgICAgZGlyZWN0aW9uVG9Qb2ludCwKICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgIHJlc3VsdAogICAgICAgICk7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hFbGxpcHNvaWRTaHJ1bmsgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShFbGxpcHNvaWRfZGVmYXVsdC5VTklUX1NQSEVSRSk7CiAgICAgIEVsbGlwc29pZGFsT2NjbHVkZXIucHJvdG90eXBlLmNvbXB1dGVIb3Jpem9uQ3VsbGluZ1BvaW50UG9zc2libHlVbmRlckVsbGlwc29pZCA9IGZ1bmN0aW9uKGRpcmVjdGlvblRvUG9pbnQsIHBvc2l0aW9ucywgbWluaW11bUhlaWdodCwgcmVzdWx0KSB7CiAgICAgICAgY29uc3QgcG9zc2libHlTaHJ1bmtFbGxpcHNvaWQgPSBnZXRQb3NzaWJseVNocnVua0VsbGlwc29pZCgKICAgICAgICAgIHRoaXMuX2VsbGlwc29pZCwKICAgICAgICAgIG1pbmltdW1IZWlnaHQsCiAgICAgICAgICBzY3JhdGNoRWxsaXBzb2lkU2hydW5rCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gY29tcHV0ZUhvcml6b25DdWxsaW5nUG9pbnRGcm9tUG9zaXRpb25zKAogICAgICAgICAgcG9zc2libHlTaHJ1bmtFbGxpcHNvaWQsCiAgICAgICAgICBkaXJlY3Rpb25Ub1BvaW50LAogICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgcmVzdWx0CiAgICAgICAgKTsKICAgICAgfTsKICAgICAgRWxsaXBzb2lkYWxPY2NsdWRlci5wcm90b3R5cGUuY29tcHV0ZUhvcml6b25DdWxsaW5nUG9pbnRGcm9tVmVydGljZXMgPSBmdW5jdGlvbihkaXJlY3Rpb25Ub1BvaW50LCB2ZXJ0aWNlcywgc3RyaWRlLCBjZW50ZXIsIHJlc3VsdCkgewogICAgICAgIHJldHVybiBjb21wdXRlSG9yaXpvbkN1bGxpbmdQb2ludEZyb21WZXJ0aWNlcygKICAgICAgICAgIHRoaXMuX2VsbGlwc29pZCwKICAgICAgICAgIGRpcmVjdGlvblRvUG9pbnQsCiAgICAgICAgICB2ZXJ0aWNlcywKICAgICAgICAgIHN0cmlkZSwKICAgICAgICAgIGNlbnRlciwKICAgICAgICAgIHJlc3VsdAogICAgICAgICk7CiAgICAgIH07CiAgICAgIEVsbGlwc29pZGFsT2NjbHVkZXIucHJvdG90eXBlLmNvbXB1dGVIb3Jpem9uQ3VsbGluZ1BvaW50RnJvbVZlcnRpY2VzUG9zc2libHlVbmRlckVsbGlwc29pZCA9IGZ1bmN0aW9uKGRpcmVjdGlvblRvUG9pbnQsIHZlcnRpY2VzLCBzdHJpZGUsIGNlbnRlciwgbWluaW11bUhlaWdodCwgcmVzdWx0KSB7CiAgICAgICAgY29uc3QgcG9zc2libHlTaHJ1bmtFbGxpcHNvaWQgPSBnZXRQb3NzaWJseVNocnVua0VsbGlwc29pZCgKICAgICAgICAgIHRoaXMuX2VsbGlwc29pZCwKICAgICAgICAgIG1pbmltdW1IZWlnaHQsCiAgICAgICAgICBzY3JhdGNoRWxsaXBzb2lkU2hydW5rCiAgICAgICAgKTsKICAgICAgICByZXR1cm4gY29tcHV0ZUhvcml6b25DdWxsaW5nUG9pbnRGcm9tVmVydGljZXMoCiAgICAgICAgICBwb3NzaWJseVNocnVua0VsbGlwc29pZCwKICAgICAgICAgIGRpcmVjdGlvblRvUG9pbnQsCiAgICAgICAgICB2ZXJ0aWNlcywKICAgICAgICAgIHN0cmlkZSwKICAgICAgICAgIGNlbnRlciwKICAgICAgICAgIHJlc3VsdAogICAgICAgICk7CiAgICAgIH07CiAgICAgIHN1YnNhbXBsZVNjcmF0Y2ggPSBbXTsKICAgICAgRWxsaXBzb2lkYWxPY2NsdWRlci5wcm90b3R5cGUuY29tcHV0ZUhvcml6b25DdWxsaW5nUG9pbnRGcm9tUmVjdGFuZ2xlID0gZnVuY3Rpb24ocmVjdGFuZ2xlLCBlbGxpcHNvaWQsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm9iamVjdCgicmVjdGFuZ2xlIiwgcmVjdGFuZ2xlKTsKICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBSZWN0YW5nbGVfZGVmYXVsdC5zdWJzYW1wbGUoCiAgICAgICAgICByZWN0YW5nbGUsCiAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICAwLAogICAgICAgICAgc3Vic2FtcGxlU2NyYXRjaAogICAgICAgICk7CiAgICAgICAgY29uc3QgYnMgPSBCb3VuZGluZ1NwaGVyZV9kZWZhdWx0LmZyb21Qb2ludHMocG9zaXRpb25zKTsKICAgICAgICBpZiAoQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZShicy5jZW50ZXIpIDwgMC4xICogZWxsaXBzb2lkLm1pbmltdW1SYWRpdXMpIHsKICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzLmNvbXB1dGVIb3Jpem9uQ3VsbGluZ1BvaW50KGJzLmNlbnRlciwgcG9zaXRpb25zLCByZXN1bHQpOwogICAgICB9OwogICAgICBzY3JhdGNoRWxsaXBzb2lkU2hydW5rUmFkaWkgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHBvc2l0aW9uU2NyYXRjaDUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjYWxlZFNwYWNlU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZGlyZWN0aW9uU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgZGlyZWN0aW9uVG9Qb2ludFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIEVsbGlwc29pZGFsT2NjbHVkZXJfZGVmYXVsdCA9IEVsbGlwc29pZGFsT2NjbHVkZXI7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9WZXJ0aWNhbEV4YWdnZXJhdGlvbi5qcwogIHZhciBWZXJ0aWNhbEV4YWdnZXJhdGlvbiwgc2NyYXRjaENhcnRvZ3JhcGhpYzYsIFZlcnRpY2FsRXhhZ2dlcmF0aW9uX2RlZmF1bHQ7CiAgdmFyIGluaXRfVmVydGljYWxFeGFnZ2VyYXRpb24gPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1ZlcnRpY2FsRXhhZ2dlcmF0aW9uLmpzIigpIHsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIFZlcnRpY2FsRXhhZ2dlcmF0aW9uID0ge307CiAgICAgIFZlcnRpY2FsRXhhZ2dlcmF0aW9uLmdldEhlaWdodCA9IGZ1bmN0aW9uKGhlaWdodCwgc2NhbGUsIHJlbGF0aXZlSGVpZ2h0KSB7CiAgICAgICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUoc2NhbGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgic2NhbGUgbXVzdCBiZSBhIGZpbml0ZSBudW1iZXIuIik7CiAgICAgICAgfQogICAgICAgIGlmICghTnVtYmVyLmlzRmluaXRlKHJlbGF0aXZlSGVpZ2h0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInJlbGF0aXZlSGVpZ2h0IG11c3QgYmUgYSBmaW5pdGUgbnVtYmVyLiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gKGhlaWdodCAtIHJlbGF0aXZlSGVpZ2h0KSAqIHNjYWxlICsgcmVsYXRpdmVIZWlnaHQ7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWM2ID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIFZlcnRpY2FsRXhhZ2dlcmF0aW9uLmdldFBvc2l0aW9uID0gZnVuY3Rpb24ocG9zaXRpb24sIGVsbGlwc29pZCwgdmVydGljYWxFeGFnZ2VyYXRpb24sIHZlcnRpY2FsRXhhZ2dlcmF0aW9uUmVsYXRpdmVIZWlnaHQsIHJlc3VsdCkgewogICAgICAgIGNvbnN0IGNhcnRvZ3JhcGhpYzIgPSBlbGxpcHNvaWQuY2FydGVzaWFuVG9DYXJ0b2dyYXBoaWMoCiAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWM2CiAgICAgICAgKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChjYXJ0b2dyYXBoaWMyKSkgewogICAgICAgICAgcmV0dXJuIENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShwb3NpdGlvbiwgcmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbmV3SGVpZ2h0ID0gVmVydGljYWxFeGFnZ2VyYXRpb24uZ2V0SGVpZ2h0KAogICAgICAgICAgY2FydG9ncmFwaGljMi5oZWlnaHQsCiAgICAgICAgICB2ZXJ0aWNhbEV4YWdnZXJhdGlvbiwKICAgICAgICAgIHZlcnRpY2FsRXhhZ2dlcmF0aW9uUmVsYXRpdmVIZWlnaHQKICAgICAgICApOwogICAgICAgIHJldHVybiBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbVJhZGlhbnMoCiAgICAgICAgICBjYXJ0b2dyYXBoaWMyLmxvbmdpdHVkZSwKICAgICAgICAgIGNhcnRvZ3JhcGhpYzIubGF0aXR1ZGUsCiAgICAgICAgICBuZXdIZWlnaHQsCiAgICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgICByZXN1bHQKICAgICAgICApOwogICAgICB9OwogICAgICBWZXJ0aWNhbEV4YWdnZXJhdGlvbl9kZWZhdWx0ID0gVmVydGljYWxFeGFnZ2VyYXRpb247CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9UZXJyYWluUXVhbnRpemF0aW9uLmpzCiAgdmFyIFRlcnJhaW5RdWFudGl6YXRpb24sIFRlcnJhaW5RdWFudGl6YXRpb25fZGVmYXVsdDsKICB2YXIgaW5pdF9UZXJyYWluUXVhbnRpemF0aW9uID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9UZXJyYWluUXVhbnRpemF0aW9uLmpzIigpIHsKICAgICAgVGVycmFpblF1YW50aXphdGlvbiA9IHsKICAgICAgICAvKioKICAgICAgICAgKiBUaGUgdmVydGljZXMgYXJlIG5vdCBjb21wcmVzc2VkLgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBOT05FOiAwLAogICAgICAgIC8qKgogICAgICAgICAqIFRoZSB2ZXJ0aWNlcyBhcmUgY29tcHJlc3NlZCB0byAxMiBiaXRzLgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBCSVRTMTI6IDEKICAgICAgfTsKICAgICAgVGVycmFpblF1YW50aXphdGlvbl9kZWZhdWx0ID0gT2JqZWN0LmZyZWV6ZShUZXJyYWluUXVhbnRpemF0aW9uKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1RlcnJhaW5FbmNvZGluZy5qcwogIGZ1bmN0aW9uIFRlcnJhaW5FbmNvZGluZyhjZW50ZXIsIGF4aXNBbGlnbmVkQm91bmRpbmdCb3gsIG1pbmltdW1IZWlnaHQsIG1heGltdW1IZWlnaHQsIGZyb21FTlUsIGhhc1ZlcnRleE5vcm1hbHMsIGhhc1dlYk1lcmNhdG9yVCwgaGFzR2VvZGV0aWNTdXJmYWNlTm9ybWFscywgZXhhZ2dlcmF0aW9uLCBleGFnZ2VyYXRpb25SZWxhdGl2ZUhlaWdodCkgewogICAgbGV0IHF1YW50aXphdGlvbiA9IFRlcnJhaW5RdWFudGl6YXRpb25fZGVmYXVsdC5OT05FOwogICAgbGV0IHRvRU5VOwogICAgbGV0IG1hdHJpeDsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoYXhpc0FsaWduZWRCb3VuZGluZ0JveCkgJiYgZGVmaW5lZF9kZWZhdWx0KG1pbmltdW1IZWlnaHQpICYmIGRlZmluZWRfZGVmYXVsdChtYXhpbXVtSGVpZ2h0KSAmJiBkZWZpbmVkX2RlZmF1bHQoZnJvbUVOVSkpIHsKICAgICAgY29uc3QgbWluaW11bSA9IGF4aXNBbGlnbmVkQm91bmRpbmdCb3gubWluaW11bTsKICAgICAgY29uc3QgbWF4aW11bSA9IGF4aXNBbGlnbmVkQm91bmRpbmdCb3gubWF4aW11bTsKICAgICAgY29uc3QgZGltZW5zaW9ucyA9IENhcnRlc2lhbjNfZGVmYXVsdC5zdWJ0cmFjdCgKICAgICAgICBtYXhpbXVtLAogICAgICAgIG1pbmltdW0sCiAgICAgICAgY2FydGVzaWFuM0RpbVNjcmF0Y2gKICAgICAgKTsKICAgICAgY29uc3QgaERpbSA9IG1heGltdW1IZWlnaHQgLSBtaW5pbXVtSGVpZ2h0OwogICAgICBjb25zdCBtYXhEaW0gPSBNYXRoLm1heChDYXJ0ZXNpYW4zX2RlZmF1bHQubWF4aW11bUNvbXBvbmVudChkaW1lbnNpb25zKSwgaERpbSk7CiAgICAgIGlmIChtYXhEaW0gPCBTSElGVF9MRUZUXzEyIC0gMSkgewogICAgICAgIHF1YW50aXphdGlvbiA9IFRlcnJhaW5RdWFudGl6YXRpb25fZGVmYXVsdC5CSVRTMTI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcXVhbnRpemF0aW9uID0gVGVycmFpblF1YW50aXphdGlvbl9kZWZhdWx0Lk5PTkU7CiAgICAgIH0KICAgICAgdG9FTlUgPSBNYXRyaXg0X2RlZmF1bHQuaW52ZXJzZVRyYW5zZm9ybWF0aW9uKGZyb21FTlUsIG5ldyBNYXRyaXg0X2RlZmF1bHQoKSk7CiAgICAgIGNvbnN0IHRyYW5zbGF0aW9uMiA9IENhcnRlc2lhbjNfZGVmYXVsdC5uZWdhdGUobWluaW11bSwgY2FydGVzaWFuM1NjcmF0Y2gpOwogICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHkoCiAgICAgICAgTWF0cml4NF9kZWZhdWx0LmZyb21UcmFuc2xhdGlvbih0cmFuc2xhdGlvbjIsIG1hdHJpeDRTY3JhdGNoKSwKICAgICAgICB0b0VOVSwKICAgICAgICB0b0VOVQogICAgICApOwogICAgICBjb25zdCBzY2FsZSA9IGNhcnRlc2lhbjNTY3JhdGNoOwogICAgICBzY2FsZS54ID0gMSAvIGRpbWVuc2lvbnMueDsKICAgICAgc2NhbGUueSA9IDEgLyBkaW1lbnNpb25zLnk7CiAgICAgIHNjYWxlLnogPSAxIC8gZGltZW5zaW9ucy56OwogICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHkoTWF0cml4NF9kZWZhdWx0LmZyb21TY2FsZShzY2FsZSwgbWF0cml4NFNjcmF0Y2gpLCB0b0VOVSwgdG9FTlUpOwogICAgICBtYXRyaXggPSBNYXRyaXg0X2RlZmF1bHQuY2xvbmUoZnJvbUVOVSk7CiAgICAgIE1hdHJpeDRfZGVmYXVsdC5zZXRUcmFuc2xhdGlvbihtYXRyaXgsIENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPLCBtYXRyaXgpOwogICAgICBmcm9tRU5VID0gTWF0cml4NF9kZWZhdWx0LmNsb25lKGZyb21FTlUsIG5ldyBNYXRyaXg0X2RlZmF1bHQoKSk7CiAgICAgIGNvbnN0IHRyYW5zbGF0aW9uTWF0cml4ID0gTWF0cml4NF9kZWZhdWx0LmZyb21UcmFuc2xhdGlvbihtaW5pbXVtLCBtYXRyaXg0U2NyYXRjaCk7CiAgICAgIGNvbnN0IHNjYWxlTWF0cml4MiA9IE1hdHJpeDRfZGVmYXVsdC5mcm9tU2NhbGUoZGltZW5zaW9ucywgbWF0cml4NFNjcmF0Y2gyKTsKICAgICAgY29uc3Qgc3QgPSBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHkodHJhbnNsYXRpb25NYXRyaXgsIHNjYWxlTWF0cml4MiwgbWF0cml4NFNjcmF0Y2gpOwogICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHkoZnJvbUVOVSwgc3QsIGZyb21FTlUpOwogICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHkobWF0cml4LCBzdCwgbWF0cml4KTsKICAgIH0KICAgIHRoaXMucXVhbnRpemF0aW9uID0gcXVhbnRpemF0aW9uOwogICAgdGhpcy5taW5pbXVtSGVpZ2h0ID0gbWluaW11bUhlaWdodDsKICAgIHRoaXMubWF4aW11bUhlaWdodCA9IG1heGltdW1IZWlnaHQ7CiAgICB0aGlzLmNlbnRlciA9IENhcnRlc2lhbjNfZGVmYXVsdC5jbG9uZShjZW50ZXIpOwogICAgdGhpcy50b1NjYWxlZEVOVSA9IHRvRU5VOwogICAgdGhpcy5mcm9tU2NhbGVkRU5VID0gZnJvbUVOVTsKICAgIHRoaXMubWF0cml4ID0gbWF0cml4OwogICAgdGhpcy5oYXNWZXJ0ZXhOb3JtYWxzID0gaGFzVmVydGV4Tm9ybWFsczsKICAgIHRoaXMuaGFzV2ViTWVyY2F0b3JUID0gaGFzV2ViTWVyY2F0b3JUID8/IGZhbHNlOwogICAgdGhpcy5oYXNHZW9kZXRpY1N1cmZhY2VOb3JtYWxzID0gaGFzR2VvZGV0aWNTdXJmYWNlTm9ybWFscyA/PyBmYWxzZTsKICAgIHRoaXMuZXhhZ2dlcmF0aW9uID0gZXhhZ2dlcmF0aW9uID8/IDE7CiAgICB0aGlzLmV4YWdnZXJhdGlvblJlbGF0aXZlSGVpZ2h0ID0gZXhhZ2dlcmF0aW9uUmVsYXRpdmVIZWlnaHQgPz8gMDsKICAgIHRoaXMuc3RyaWRlID0gMDsKICAgIHRoaXMuX29mZnNldEdlb2RldGljU3VyZmFjZU5vcm1hbCA9IDA7CiAgICB0aGlzLl9vZmZzZXRWZXJ0ZXhOb3JtYWwgPSAwOwogICAgdGhpcy5fY2FsY3VsYXRlU3RyaWRlQW5kT2Zmc2V0cygpOwogIH0KICB2YXIgY2FydGVzaWFuM1NjcmF0Y2gsIGNhcnRlc2lhbjNEaW1TY3JhdGNoLCBjYXJ0ZXNpYW4yU2NyYXRjaCwgbWF0cml4NFNjcmF0Y2gsIG1hdHJpeDRTY3JhdGNoMiwgU0hJRlRfTEVGVF8xMiwgc2NyYXRjaFBvc2l0aW9uNiwgc2NyYXRjaEdlb2RldGljU3VyZmFjZU5vcm1hbCwgYXR0cmlidXRlc0luZGljZXNOb25lLCBhdHRyaWJ1dGVzSW5kaWNlc0JpdHMxMiwgVGVycmFpbkVuY29kaW5nX2RlZmF1bHQ7CiAgdmFyIGluaXRfVGVycmFpbkVuY29kaW5nID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9UZXJyYWluRW5jb2RpbmcuanMiKCkgewogICAgICBpbml0X0F0dHJpYnV0ZUNvbXByZXNzaW9uKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMigpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfTWF0cml4NCgpOwogICAgICBpbml0X1ZlcnRpY2FsRXhhZ2dlcmF0aW9uKCk7CiAgICAgIGluaXRfVGVycmFpblF1YW50aXphdGlvbigpOwogICAgICBjYXJ0ZXNpYW4zU2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgY2FydGVzaWFuM0RpbVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhcnRlc2lhbjJTY3JhdGNoID0gbmV3IENhcnRlc2lhbjJfZGVmYXVsdCgpOwogICAgICBtYXRyaXg0U2NyYXRjaCA9IG5ldyBNYXRyaXg0X2RlZmF1bHQoKTsKICAgICAgbWF0cml4NFNjcmF0Y2gyID0gbmV3IE1hdHJpeDRfZGVmYXVsdCgpOwogICAgICBTSElGVF9MRUZUXzEyID0gTWF0aC5wb3coMiwgMTIpOwogICAgICBUZXJyYWluRW5jb2RpbmcucHJvdG90eXBlLmVuY29kZSA9IGZ1bmN0aW9uKHZlcnRleEJ1ZmZlciwgYnVmZmVySW5kZXgsIHBvc2l0aW9uLCB1diwgaGVpZ2h0LCBub3JtYWxUb1BhY2ssIHdlYk1lcmNhdG9yVCwgZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKSB7CiAgICAgICAgY29uc3QgdTMgPSB1di54OwogICAgICAgIGNvbnN0IHYzID0gdXYueTsKICAgICAgICBpZiAodGhpcy5xdWFudGl6YXRpb24gPT09IFRlcnJhaW5RdWFudGl6YXRpb25fZGVmYXVsdC5CSVRTMTIpIHsKICAgICAgICAgIHBvc2l0aW9uID0gTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5QnlQb2ludCgKICAgICAgICAgICAgdGhpcy50b1NjYWxlZEVOVSwKICAgICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICAgIGNhcnRlc2lhbjNTY3JhdGNoCiAgICAgICAgICApOwogICAgICAgICAgcG9zaXRpb24ueCA9IE1hdGhfZGVmYXVsdC5jbGFtcChwb3NpdGlvbi54LCAwLCAxKTsKICAgICAgICAgIHBvc2l0aW9uLnkgPSBNYXRoX2RlZmF1bHQuY2xhbXAocG9zaXRpb24ueSwgMCwgMSk7CiAgICAgICAgICBwb3NpdGlvbi56ID0gTWF0aF9kZWZhdWx0LmNsYW1wKHBvc2l0aW9uLnosIDAsIDEpOwogICAgICAgICAgY29uc3QgaERpbSA9IHRoaXMubWF4aW11bUhlaWdodCAtIHRoaXMubWluaW11bUhlaWdodDsKICAgICAgICAgIGNvbnN0IGggPSBNYXRoX2RlZmF1bHQuY2xhbXAoKGhlaWdodCAtIHRoaXMubWluaW11bUhlaWdodCkgLyBoRGltLCAwLCAxKTsKICAgICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHMocG9zaXRpb24ueCwgcG9zaXRpb24ueSwgY2FydGVzaWFuMlNjcmF0Y2gpOwogICAgICAgICAgY29uc3QgY29tcHJlc3NlZDAgPSBBdHRyaWJ1dGVDb21wcmVzc2lvbl9kZWZhdWx0LmNvbXByZXNzVGV4dHVyZUNvb3JkaW5hdGVzKGNhcnRlc2lhbjJTY3JhdGNoKTsKICAgICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHMocG9zaXRpb24ueiwgaCwgY2FydGVzaWFuMlNjcmF0Y2gpOwogICAgICAgICAgY29uc3QgY29tcHJlc3NlZDEgPSBBdHRyaWJ1dGVDb21wcmVzc2lvbl9kZWZhdWx0LmNvbXByZXNzVGV4dHVyZUNvb3JkaW5hdGVzKGNhcnRlc2lhbjJTY3JhdGNoKTsKICAgICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHModTMsIHYzLCBjYXJ0ZXNpYW4yU2NyYXRjaCk7CiAgICAgICAgICBjb25zdCBjb21wcmVzc2VkMiA9IEF0dHJpYnV0ZUNvbXByZXNzaW9uX2RlZmF1bHQuY29tcHJlc3NUZXh0dXJlQ29vcmRpbmF0ZXMoY2FydGVzaWFuMlNjcmF0Y2gpOwogICAgICAgICAgdmVydGV4QnVmZmVyW2J1ZmZlckluZGV4KytdID0gY29tcHJlc3NlZDA7CiAgICAgICAgICB2ZXJ0ZXhCdWZmZXJbYnVmZmVySW5kZXgrK10gPSBjb21wcmVzc2VkMTsKICAgICAgICAgIHZlcnRleEJ1ZmZlcltidWZmZXJJbmRleCsrXSA9IGNvbXByZXNzZWQyOwogICAgICAgICAgaWYgKHRoaXMuaGFzV2ViTWVyY2F0b3JUKSB7CiAgICAgICAgICAgIENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHMod2ViTWVyY2F0b3JULCAwLCBjYXJ0ZXNpYW4yU2NyYXRjaCk7CiAgICAgICAgICAgIGNvbnN0IGNvbXByZXNzZWQzID0gQXR0cmlidXRlQ29tcHJlc3Npb25fZGVmYXVsdC5jb21wcmVzc1RleHR1cmVDb29yZGluYXRlcyhjYXJ0ZXNpYW4yU2NyYXRjaCk7CiAgICAgICAgICAgIHZlcnRleEJ1ZmZlcltidWZmZXJJbmRleCsrXSA9IGNvbXByZXNzZWQzOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QocG9zaXRpb24sIHRoaXMuY2VudGVyLCBjYXJ0ZXNpYW4zU2NyYXRjaCk7CiAgICAgICAgICB2ZXJ0ZXhCdWZmZXJbYnVmZmVySW5kZXgrK10gPSBjYXJ0ZXNpYW4zU2NyYXRjaC54OwogICAgICAgICAgdmVydGV4QnVmZmVyW2J1ZmZlckluZGV4KytdID0gY2FydGVzaWFuM1NjcmF0Y2gueTsKICAgICAgICAgIHZlcnRleEJ1ZmZlcltidWZmZXJJbmRleCsrXSA9IGNhcnRlc2lhbjNTY3JhdGNoLno7CiAgICAgICAgICB2ZXJ0ZXhCdWZmZXJbYnVmZmVySW5kZXgrK10gPSBoZWlnaHQ7CiAgICAgICAgICB2ZXJ0ZXhCdWZmZXJbYnVmZmVySW5kZXgrK10gPSB1MzsKICAgICAgICAgIHZlcnRleEJ1ZmZlcltidWZmZXJJbmRleCsrXSA9IHYzOwogICAgICAgICAgaWYgKHRoaXMuaGFzV2ViTWVyY2F0b3JUKSB7CiAgICAgICAgICAgIHZlcnRleEJ1ZmZlcltidWZmZXJJbmRleCsrXSA9IHdlYk1lcmNhdG9yVDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMuaGFzVmVydGV4Tm9ybWFscykgewogICAgICAgICAgdmVydGV4QnVmZmVyW2J1ZmZlckluZGV4KytdID0gQXR0cmlidXRlQ29tcHJlc3Npb25fZGVmYXVsdC5vY3RQYWNrRmxvYXQobm9ybWFsVG9QYWNrKTsKICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMuaGFzR2VvZGV0aWNTdXJmYWNlTm9ybWFscykgewogICAgICAgICAgdmVydGV4QnVmZmVyW2J1ZmZlckluZGV4KytdID0gZ2VvZGV0aWNTdXJmYWNlTm9ybWFsLng7CiAgICAgICAgICB2ZXJ0ZXhCdWZmZXJbYnVmZmVySW5kZXgrK10gPSBnZW9kZXRpY1N1cmZhY2VOb3JtYWwueTsKICAgICAgICAgIHZlcnRleEJ1ZmZlcltidWZmZXJJbmRleCsrXSA9IGdlb2RldGljU3VyZmFjZU5vcm1hbC56OwogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVmZmVySW5kZXg7CiAgICAgIH07CiAgICAgIHNjcmF0Y2hQb3NpdGlvbjYgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hHZW9kZXRpY1N1cmZhY2VOb3JtYWwgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIFRlcnJhaW5FbmNvZGluZy5wcm90b3R5cGUuYWRkR2VvZGV0aWNTdXJmYWNlTm9ybWFscyA9IGZ1bmN0aW9uKG9sZEJ1ZmZlciwgbmV3QnVmZmVyLCBlbGxpcHNvaWQpIHsKICAgICAgICBpZiAodGhpcy5oYXNHZW9kZXRpY1N1cmZhY2VOb3JtYWxzKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IG9sZFN0cmlkZSA9IHRoaXMuc3RyaWRlOwogICAgICAgIGNvbnN0IHZlcnRleENvdW50ID0gb2xkQnVmZmVyLmxlbmd0aCAvIG9sZFN0cmlkZTsKICAgICAgICB0aGlzLmhhc0dlb2RldGljU3VyZmFjZU5vcm1hbHMgPSB0cnVlOwogICAgICAgIHRoaXMuX2NhbGN1bGF0ZVN0cmlkZUFuZE9mZnNldHMoKTsKICAgICAgICBjb25zdCBuZXdTdHJpZGUgPSB0aGlzLnN0cmlkZTsKICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdmVydGV4Q291bnQ7IGluZGV4KyspIHsKICAgICAgICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IG9sZFN0cmlkZTsgb2Zmc2V0KyspIHsKICAgICAgICAgICAgY29uc3Qgb2xkSW5kZXggPSBpbmRleCAqIG9sZFN0cmlkZSArIG9mZnNldDsKICAgICAgICAgICAgY29uc3QgbmV3SW5kZXggPSBpbmRleCAqIG5ld1N0cmlkZSArIG9mZnNldDsKICAgICAgICAgICAgbmV3QnVmZmVyW25ld0luZGV4XSA9IG9sZEJ1ZmZlcltvbGRJbmRleF07CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMuZGVjb2RlUG9zaXRpb24obmV3QnVmZmVyLCBpbmRleCwgc2NyYXRjaFBvc2l0aW9uNik7CiAgICAgICAgICBjb25zdCBnZW9kZXRpY1N1cmZhY2VOb3JtYWwgPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKAogICAgICAgICAgICBwb3NpdGlvbiwKICAgICAgICAgICAgc2NyYXRjaEdlb2RldGljU3VyZmFjZU5vcm1hbAogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IGJ1ZmZlckluZGV4ID0gaW5kZXggKiBuZXdTdHJpZGUgKyB0aGlzLl9vZmZzZXRHZW9kZXRpY1N1cmZhY2VOb3JtYWw7CiAgICAgICAgICBuZXdCdWZmZXJbYnVmZmVySW5kZXhdID0gZ2VvZGV0aWNTdXJmYWNlTm9ybWFsLng7CiAgICAgICAgICBuZXdCdWZmZXJbYnVmZmVySW5kZXggKyAxXSA9IGdlb2RldGljU3VyZmFjZU5vcm1hbC55OwogICAgICAgICAgbmV3QnVmZmVyW2J1ZmZlckluZGV4ICsgMl0gPSBnZW9kZXRpY1N1cmZhY2VOb3JtYWwuejsKICAgICAgICB9CiAgICAgIH07CiAgICAgIFRlcnJhaW5FbmNvZGluZy5wcm90b3R5cGUucmVtb3ZlR2VvZGV0aWNTdXJmYWNlTm9ybWFscyA9IGZ1bmN0aW9uKG9sZEJ1ZmZlciwgbmV3QnVmZmVyKSB7CiAgICAgICAgaWYgKCF0aGlzLmhhc0dlb2RldGljU3VyZmFjZU5vcm1hbHMpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgY29uc3Qgb2xkU3RyaWRlID0gdGhpcy5zdHJpZGU7CiAgICAgICAgY29uc3QgdmVydGV4Q291bnQgPSBvbGRCdWZmZXIubGVuZ3RoIC8gb2xkU3RyaWRlOwogICAgICAgIHRoaXMuaGFzR2VvZGV0aWNTdXJmYWNlTm9ybWFscyA9IGZhbHNlOwogICAgICAgIHRoaXMuX2NhbGN1bGF0ZVN0cmlkZUFuZE9mZnNldHMoKTsKICAgICAgICBjb25zdCBuZXdTdHJpZGUgPSB0aGlzLnN0cmlkZTsKICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdmVydGV4Q291bnQ7IGluZGV4KyspIHsKICAgICAgICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IG5ld1N0cmlkZTsgb2Zmc2V0KyspIHsKICAgICAgICAgICAgY29uc3Qgb2xkSW5kZXggPSBpbmRleCAqIG9sZFN0cmlkZSArIG9mZnNldDsKICAgICAgICAgICAgY29uc3QgbmV3SW5kZXggPSBpbmRleCAqIG5ld1N0cmlkZSArIG9mZnNldDsKICAgICAgICAgICAgbmV3QnVmZmVyW25ld0luZGV4XSA9IG9sZEJ1ZmZlcltvbGRJbmRleF07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9OwogICAgICBUZXJyYWluRW5jb2RpbmcucHJvdG90eXBlLmRlY29kZVBvc2l0aW9uID0gZnVuY3Rpb24oYnVmZmVyLCBpbmRleCwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICAgIH0KICAgICAgICBpbmRleCAqPSB0aGlzLnN0cmlkZTsKICAgICAgICBpZiAodGhpcy5xdWFudGl6YXRpb24gPT09IFRlcnJhaW5RdWFudGl6YXRpb25fZGVmYXVsdC5CSVRTMTIpIHsKICAgICAgICAgIGNvbnN0IHh5ID0gQXR0cmlidXRlQ29tcHJlc3Npb25fZGVmYXVsdC5kZWNvbXByZXNzVGV4dHVyZUNvb3JkaW5hdGVzKAogICAgICAgICAgICBidWZmZXJbaW5kZXhdLAogICAgICAgICAgICBjYXJ0ZXNpYW4yU2NyYXRjaAogICAgICAgICAgKTsKICAgICAgICAgIHJlc3VsdC54ID0geHkueDsKICAgICAgICAgIHJlc3VsdC55ID0geHkueTsKICAgICAgICAgIGNvbnN0IHpoID0gQXR0cmlidXRlQ29tcHJlc3Npb25fZGVmYXVsdC5kZWNvbXByZXNzVGV4dHVyZUNvb3JkaW5hdGVzKAogICAgICAgICAgICBidWZmZXJbaW5kZXggKyAxXSwKICAgICAgICAgICAgY2FydGVzaWFuMlNjcmF0Y2gKICAgICAgICAgICk7CiAgICAgICAgICByZXN1bHQueiA9IHpoLng7CiAgICAgICAgICByZXR1cm4gTWF0cml4NF9kZWZhdWx0Lm11bHRpcGx5QnlQb2ludCh0aGlzLmZyb21TY2FsZWRFTlUsIHJlc3VsdCwgcmVzdWx0KTsKICAgICAgICB9CiAgICAgICAgcmVzdWx0LnggPSBidWZmZXJbaW5kZXhdOwogICAgICAgIHJlc3VsdC55ID0gYnVmZmVyW2luZGV4ICsgMV07CiAgICAgICAgcmVzdWx0LnogPSBidWZmZXJbaW5kZXggKyAyXTsKICAgICAgICByZXR1cm4gQ2FydGVzaWFuM19kZWZhdWx0LmFkZChyZXN1bHQsIHRoaXMuY2VudGVyLCByZXN1bHQpOwogICAgICB9OwogICAgICBUZXJyYWluRW5jb2RpbmcucHJvdG90eXBlLmdldEV4YWdnZXJhdGVkUG9zaXRpb24gPSBmdW5jdGlvbihidWZmZXIsIGluZGV4LCByZXN1bHQpIHsKICAgICAgICByZXN1bHQgPSB0aGlzLmRlY29kZVBvc2l0aW9uKGJ1ZmZlciwgaW5kZXgsIHJlc3VsdCk7CiAgICAgICAgY29uc3QgZXhhZ2dlcmF0aW9uID0gdGhpcy5leGFnZ2VyYXRpb247CiAgICAgICAgY29uc3QgZXhhZ2dlcmF0aW9uUmVsYXRpdmVIZWlnaHQgPSB0aGlzLmV4YWdnZXJhdGlvblJlbGF0aXZlSGVpZ2h0OwogICAgICAgIGNvbnN0IGhhc0V4YWdnZXJhdGlvbiA9IGV4YWdnZXJhdGlvbiAhPT0gMTsKICAgICAgICBpZiAoaGFzRXhhZ2dlcmF0aW9uICYmIHRoaXMuaGFzR2VvZGV0aWNTdXJmYWNlTm9ybWFscykgewogICAgICAgICAgY29uc3QgZ2VvZGV0aWNTdXJmYWNlTm9ybWFsID0gdGhpcy5kZWNvZGVHZW9kZXRpY1N1cmZhY2VOb3JtYWwoCiAgICAgICAgICAgIGJ1ZmZlciwKICAgICAgICAgICAgaW5kZXgsCiAgICAgICAgICAgIHNjcmF0Y2hHZW9kZXRpY1N1cmZhY2VOb3JtYWwKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCByYXdIZWlnaHQgPSB0aGlzLmRlY29kZUhlaWdodChidWZmZXIsIGluZGV4KTsKICAgICAgICAgIGNvbnN0IGhlaWdodERpZmZlcmVuY2UgPSBWZXJ0aWNhbEV4YWdnZXJhdGlvbl9kZWZhdWx0LmdldEhlaWdodCgKICAgICAgICAgICAgcmF3SGVpZ2h0LAogICAgICAgICAgICBleGFnZ2VyYXRpb24sCiAgICAgICAgICAgIGV4YWdnZXJhdGlvblJlbGF0aXZlSGVpZ2h0CiAgICAgICAgICApIC0gcmF3SGVpZ2h0OwogICAgICAgICAgcmVzdWx0LnggKz0gZ2VvZGV0aWNTdXJmYWNlTm9ybWFsLnggKiBoZWlnaHREaWZmZXJlbmNlOwogICAgICAgICAgcmVzdWx0LnkgKz0gZ2VvZGV0aWNTdXJmYWNlTm9ybWFsLnkgKiBoZWlnaHREaWZmZXJlbmNlOwogICAgICAgICAgcmVzdWx0LnogKz0gZ2VvZGV0aWNTdXJmYWNlTm9ybWFsLnogKiBoZWlnaHREaWZmZXJlbmNlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBUZXJyYWluRW5jb2RpbmcucHJvdG90eXBlLmRlY29kZVRleHR1cmVDb29yZGluYXRlcyA9IGZ1bmN0aW9uKGJ1ZmZlciwgaW5kZXgsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHJlc3VsdCA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKTsKICAgICAgICB9CiAgICAgICAgaW5kZXggKj0gdGhpcy5zdHJpZGU7CiAgICAgICAgaWYgKHRoaXMucXVhbnRpemF0aW9uID09PSBUZXJyYWluUXVhbnRpemF0aW9uX2RlZmF1bHQuQklUUzEyKSB7CiAgICAgICAgICByZXR1cm4gQXR0cmlidXRlQ29tcHJlc3Npb25fZGVmYXVsdC5kZWNvbXByZXNzVGV4dHVyZUNvb3JkaW5hdGVzKAogICAgICAgICAgICBidWZmZXJbaW5kZXggKyAyXSwKICAgICAgICAgICAgcmVzdWx0CiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICByZXR1cm4gQ2FydGVzaWFuMl9kZWZhdWx0LmZyb21FbGVtZW50cyhidWZmZXJbaW5kZXggKyA0XSwgYnVmZmVyW2luZGV4ICsgNV0sIHJlc3VsdCk7CiAgICAgIH07CiAgICAgIFRlcnJhaW5FbmNvZGluZy5wcm90b3R5cGUuZGVjb2RlSGVpZ2h0ID0gZnVuY3Rpb24oYnVmZmVyLCBpbmRleCkgewogICAgICAgIGluZGV4ICo9IHRoaXMuc3RyaWRlOwogICAgICAgIGlmICh0aGlzLnF1YW50aXphdGlvbiA9PT0gVGVycmFpblF1YW50aXphdGlvbl9kZWZhdWx0LkJJVFMxMikgewogICAgICAgICAgY29uc3QgemggPSBBdHRyaWJ1dGVDb21wcmVzc2lvbl9kZWZhdWx0LmRlY29tcHJlc3NUZXh0dXJlQ29vcmRpbmF0ZXMoCiAgICAgICAgICAgIGJ1ZmZlcltpbmRleCArIDFdLAogICAgICAgICAgICBjYXJ0ZXNpYW4yU2NyYXRjaAogICAgICAgICAgKTsKICAgICAgICAgIHJldHVybiB6aC55ICogKHRoaXMubWF4aW11bUhlaWdodCAtIHRoaXMubWluaW11bUhlaWdodCkgKyB0aGlzLm1pbmltdW1IZWlnaHQ7CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWZmZXJbaW5kZXggKyAzXTsKICAgICAgfTsKICAgICAgVGVycmFpbkVuY29kaW5nLnByb3RvdHlwZS5kZWNvZGVXZWJNZXJjYXRvclQgPSBmdW5jdGlvbihidWZmZXIsIGluZGV4KSB7CiAgICAgICAgaW5kZXggKj0gdGhpcy5zdHJpZGU7CiAgICAgICAgaWYgKHRoaXMucXVhbnRpemF0aW9uID09PSBUZXJyYWluUXVhbnRpemF0aW9uX2RlZmF1bHQuQklUUzEyKSB7CiAgICAgICAgICByZXR1cm4gQXR0cmlidXRlQ29tcHJlc3Npb25fZGVmYXVsdC5kZWNvbXByZXNzVGV4dHVyZUNvb3JkaW5hdGVzKAogICAgICAgICAgICBidWZmZXJbaW5kZXggKyAzXSwKICAgICAgICAgICAgY2FydGVzaWFuMlNjcmF0Y2gKICAgICAgICAgICkueDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJ1ZmZlcltpbmRleCArIDZdOwogICAgICB9OwogICAgICBUZXJyYWluRW5jb2RpbmcucHJvdG90eXBlLmdldE9jdEVuY29kZWROb3JtYWwgPSBmdW5jdGlvbihidWZmZXIsIGluZGV4LCByZXN1bHQpIHsKICAgICAgICBpbmRleCA9IGluZGV4ICogdGhpcy5zdHJpZGUgKyB0aGlzLl9vZmZzZXRWZXJ0ZXhOb3JtYWw7CiAgICAgICAgY29uc3QgdGVtcCA9IGJ1ZmZlcltpbmRleF0gLyAyNTY7CiAgICAgICAgY29uc3QgeCA9IE1hdGguZmxvb3IodGVtcCk7CiAgICAgICAgY29uc3QgeSA9ICh0ZW1wIC0geCkgKiAyNTY7CiAgICAgICAgcmV0dXJuIENhcnRlc2lhbjJfZGVmYXVsdC5mcm9tRWxlbWVudHMoeCwgeSwgcmVzdWx0KTsKICAgICAgfTsKICAgICAgVGVycmFpbkVuY29kaW5nLnByb3RvdHlwZS5kZWNvZGVHZW9kZXRpY1N1cmZhY2VOb3JtYWwgPSBmdW5jdGlvbihidWZmZXIsIGluZGV4LCByZXN1bHQpIHsKICAgICAgICBpbmRleCA9IGluZGV4ICogdGhpcy5zdHJpZGUgKyB0aGlzLl9vZmZzZXRHZW9kZXRpY1N1cmZhY2VOb3JtYWw7CiAgICAgICAgcmVzdWx0LnggPSBidWZmZXJbaW5kZXhdOwogICAgICAgIHJlc3VsdC55ID0gYnVmZmVyW2luZGV4ICsgMV07CiAgICAgICAgcmVzdWx0LnogPSBidWZmZXJbaW5kZXggKyAyXTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBUZXJyYWluRW5jb2RpbmcucHJvdG90eXBlLl9jYWxjdWxhdGVTdHJpZGVBbmRPZmZzZXRzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgbGV0IHZlcnRleFN0cmlkZSA9IDA7CiAgICAgICAgc3dpdGNoICh0aGlzLnF1YW50aXphdGlvbikgewogICAgICAgICAgY2FzZSBUZXJyYWluUXVhbnRpemF0aW9uX2RlZmF1bHQuQklUUzEyOgogICAgICAgICAgICB2ZXJ0ZXhTdHJpZGUgKz0gMzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB2ZXJ0ZXhTdHJpZGUgKz0gNjsKICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMuaGFzV2ViTWVyY2F0b3JUKSB7CiAgICAgICAgICB2ZXJ0ZXhTdHJpZGUgKz0gMTsKICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMuaGFzVmVydGV4Tm9ybWFscykgewogICAgICAgICAgdGhpcy5fb2Zmc2V0VmVydGV4Tm9ybWFsID0gdmVydGV4U3RyaWRlOwogICAgICAgICAgdmVydGV4U3RyaWRlICs9IDE7CiAgICAgICAgfQogICAgICAgIGlmICh0aGlzLmhhc0dlb2RldGljU3VyZmFjZU5vcm1hbHMpIHsKICAgICAgICAgIHRoaXMuX29mZnNldEdlb2RldGljU3VyZmFjZU5vcm1hbCA9IHZlcnRleFN0cmlkZTsKICAgICAgICAgIHZlcnRleFN0cmlkZSArPSAzOwogICAgICAgIH0KICAgICAgICB0aGlzLnN0cmlkZSA9IHZlcnRleFN0cmlkZTsKICAgICAgfTsKICAgICAgYXR0cmlidXRlc0luZGljZXNOb25lID0gewogICAgICAgIHBvc2l0aW9uM0RBbmRIZWlnaHQ6IDAsCiAgICAgICAgdGV4dHVyZUNvb3JkQW5kRW5jb2RlZE5vcm1hbHM6IDEsCiAgICAgICAgZ2VvZGV0aWNTdXJmYWNlTm9ybWFsOiAyCiAgICAgIH07CiAgICAgIGF0dHJpYnV0ZXNJbmRpY2VzQml0czEyID0gewogICAgICAgIGNvbXByZXNzZWQwOiAwLAogICAgICAgIGNvbXByZXNzZWQxOiAxLAogICAgICAgIGdlb2RldGljU3VyZmFjZU5vcm1hbDogMgogICAgICB9OwogICAgICBUZXJyYWluRW5jb2RpbmcucHJvdG90eXBlLmdldEF0dHJpYnV0ZXMgPSBmdW5jdGlvbihidWZmZXIpIHsKICAgICAgICBjb25zdCBkYXRhdHlwZSA9IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQ7CiAgICAgICAgY29uc3Qgc2l6ZUluQnl0ZXMgPSBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LmdldFNpemVJbkJ5dGVzKGRhdGF0eXBlKTsKICAgICAgICBjb25zdCBzdHJpZGVJbkJ5dGVzID0gdGhpcy5zdHJpZGUgKiBzaXplSW5CeXRlczsKICAgICAgICBsZXQgb2Zmc2V0SW5CeXRlcyA9IDA7CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IFtdOwogICAgICAgIGZ1bmN0aW9uIGFkZEF0dHJpYnV0ZShpbmRleCwgY29tcG9uZW50c1BlckF0dHJpYnV0ZSkgewogICAgICAgICAgYXR0cmlidXRlcy5wdXNoKHsKICAgICAgICAgICAgaW5kZXgsCiAgICAgICAgICAgIHZlcnRleEJ1ZmZlcjogYnVmZmVyLAogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogZGF0YXR5cGUsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGUsCiAgICAgICAgICAgIG9mZnNldEluQnl0ZXMsCiAgICAgICAgICAgIHN0cmlkZUluQnl0ZXMKICAgICAgICAgIH0pOwogICAgICAgICAgb2Zmc2V0SW5CeXRlcyArPSBjb21wb25lbnRzUGVyQXR0cmlidXRlICogc2l6ZUluQnl0ZXM7CiAgICAgICAgfQogICAgICAgIGlmICh0aGlzLnF1YW50aXphdGlvbiA9PT0gVGVycmFpblF1YW50aXphdGlvbl9kZWZhdWx0Lk5PTkUpIHsKICAgICAgICAgIGFkZEF0dHJpYnV0ZShhdHRyaWJ1dGVzSW5kaWNlc05vbmUucG9zaXRpb24zREFuZEhlaWdodCwgNCk7CiAgICAgICAgICBsZXQgY29tcG9uZW50c1RleENvb3JkQW5kTm9ybWFscyA9IDI7CiAgICAgICAgICBjb21wb25lbnRzVGV4Q29vcmRBbmROb3JtYWxzICs9IHRoaXMuaGFzV2ViTWVyY2F0b3JUID8gMSA6IDA7CiAgICAgICAgICBjb21wb25lbnRzVGV4Q29vcmRBbmROb3JtYWxzICs9IHRoaXMuaGFzVmVydGV4Tm9ybWFscyA/IDEgOiAwOwogICAgICAgICAgYWRkQXR0cmlidXRlKAogICAgICAgICAgICBhdHRyaWJ1dGVzSW5kaWNlc05vbmUudGV4dHVyZUNvb3JkQW5kRW5jb2RlZE5vcm1hbHMsCiAgICAgICAgICAgIGNvbXBvbmVudHNUZXhDb29yZEFuZE5vcm1hbHMKICAgICAgICAgICk7CiAgICAgICAgICBpZiAodGhpcy5oYXNHZW9kZXRpY1N1cmZhY2VOb3JtYWxzKSB7CiAgICAgICAgICAgIGFkZEF0dHJpYnV0ZShhdHRyaWJ1dGVzSW5kaWNlc05vbmUuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsLCAzKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgdXNpbmdBdHRyaWJ1dGUwQ29tcG9uZW50NCA9IHRoaXMuaGFzV2ViTWVyY2F0b3JUIHx8IHRoaXMuaGFzVmVydGV4Tm9ybWFsczsKICAgICAgICAgIGNvbnN0IHVzaW5nQXR0cmlidXRlMUNvbXBvbmVudDEgPSB0aGlzLmhhc1dlYk1lcmNhdG9yVCAmJiB0aGlzLmhhc1ZlcnRleE5vcm1hbHM7CiAgICAgICAgICBhZGRBdHRyaWJ1dGUoCiAgICAgICAgICAgIGF0dHJpYnV0ZXNJbmRpY2VzQml0czEyLmNvbXByZXNzZWQwLAogICAgICAgICAgICB1c2luZ0F0dHJpYnV0ZTBDb21wb25lbnQ0ID8gNCA6IDMKICAgICAgICAgICk7CiAgICAgICAgICBpZiAodXNpbmdBdHRyaWJ1dGUxQ29tcG9uZW50MSkgewogICAgICAgICAgICBhZGRBdHRyaWJ1dGUoYXR0cmlidXRlc0luZGljZXNCaXRzMTIuY29tcHJlc3NlZDEsIDEpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHRoaXMuaGFzR2VvZGV0aWNTdXJmYWNlTm9ybWFscykgewogICAgICAgICAgICBhZGRBdHRyaWJ1dGUoYXR0cmlidXRlc0luZGljZXNCaXRzMTIuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsLCAzKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZXM7CiAgICAgIH07CiAgICAgIFRlcnJhaW5FbmNvZGluZy5wcm90b3R5cGUuZ2V0QXR0cmlidXRlTG9jYXRpb25zID0gZnVuY3Rpb24oKSB7CiAgICAgICAgaWYgKHRoaXMucXVhbnRpemF0aW9uID09PSBUZXJyYWluUXVhbnRpemF0aW9uX2RlZmF1bHQuTk9ORSkgewogICAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZXNJbmRpY2VzTm9uZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZXNJbmRpY2VzQml0czEyOwogICAgICB9OwogICAgICBUZXJyYWluRW5jb2RpbmcuY2xvbmUgPSBmdW5jdGlvbihlbmNvZGluZywgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZW5jb2RpbmcpKSB7CiAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQgPSBuZXcgVGVycmFpbkVuY29kaW5nKCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5xdWFudGl6YXRpb24gPSBlbmNvZGluZy5xdWFudGl6YXRpb247CiAgICAgICAgcmVzdWx0Lm1pbmltdW1IZWlnaHQgPSBlbmNvZGluZy5taW5pbXVtSGVpZ2h0OwogICAgICAgIHJlc3VsdC5tYXhpbXVtSGVpZ2h0ID0gZW5jb2RpbmcubWF4aW11bUhlaWdodDsKICAgICAgICByZXN1bHQuY2VudGVyID0gQ2FydGVzaWFuM19kZWZhdWx0LmNsb25lKGVuY29kaW5nLmNlbnRlcik7CiAgICAgICAgcmVzdWx0LnRvU2NhbGVkRU5VID0gTWF0cml4NF9kZWZhdWx0LmNsb25lKGVuY29kaW5nLnRvU2NhbGVkRU5VKTsKICAgICAgICByZXN1bHQuZnJvbVNjYWxlZEVOVSA9IE1hdHJpeDRfZGVmYXVsdC5jbG9uZShlbmNvZGluZy5mcm9tU2NhbGVkRU5VKTsKICAgICAgICByZXN1bHQubWF0cml4ID0gTWF0cml4NF9kZWZhdWx0LmNsb25lKGVuY29kaW5nLm1hdHJpeCk7CiAgICAgICAgcmVzdWx0Lmhhc1ZlcnRleE5vcm1hbHMgPSBlbmNvZGluZy5oYXNWZXJ0ZXhOb3JtYWxzOwogICAgICAgIHJlc3VsdC5oYXNXZWJNZXJjYXRvclQgPSBlbmNvZGluZy5oYXNXZWJNZXJjYXRvclQ7CiAgICAgICAgcmVzdWx0Lmhhc0dlb2RldGljU3VyZmFjZU5vcm1hbHMgPSBlbmNvZGluZy5oYXNHZW9kZXRpY1N1cmZhY2VOb3JtYWxzOwogICAgICAgIHJlc3VsdC5leGFnZ2VyYXRpb24gPSBlbmNvZGluZy5leGFnZ2VyYXRpb247CiAgICAgICAgcmVzdWx0LmV4YWdnZXJhdGlvblJlbGF0aXZlSGVpZ2h0ID0gZW5jb2RpbmcuZXhhZ2dlcmF0aW9uUmVsYXRpdmVIZWlnaHQ7CiAgICAgICAgcmVzdWx0Ll9jYWxjdWxhdGVTdHJpZGVBbmRPZmZzZXRzKCk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgVGVycmFpbkVuY29kaW5nX2RlZmF1bHQgPSBUZXJyYWluRW5jb2Rpbmc7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVWZXJ0aWNlc0Zyb21Hb29nbGVFYXJ0aEVudGVycHJpc2VCdWZmZXIuanMKICB2YXIgY3JlYXRlVmVydGljZXNGcm9tR29vZ2xlRWFydGhFbnRlcnByaXNlQnVmZmVyX2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChjcmVhdGVWZXJ0aWNlc0Zyb21Hb29nbGVFYXJ0aEVudGVycHJpc2VCdWZmZXJfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlVmVydGljZXNGcm9tR29vZ2xlRWFydGhFbnRlcnByaXNlQnVmZmVyX2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBpbmRleE9mRXBzaWxvbihhcnIsIGVsZW0sIGVsZW1UeXBlKSB7CiAgICBlbGVtVHlwZSA9IGVsZW1UeXBlID8/IE1hdGhfZGVmYXVsdDsKICAgIGNvbnN0IGNvdW50ID0gYXJyLmxlbmd0aDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7ICsraSkgewogICAgICBpZiAoZWxlbVR5cGUuZXF1YWxzRXBzaWxvbihhcnJbaV0sIGVsZW0sIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTIpKSB7CiAgICAgICAgcmV0dXJuIGk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiAtMTsKICB9CiAgZnVuY3Rpb24gY3JlYXRlVmVydGljZXNGcm9tR29vZ2xlRWFydGhFbnRlcnByaXNlQnVmZmVyKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIHBhcmFtZXRlcnMuZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUocGFyYW1ldGVycy5lbGxpcHNvaWQpOwogICAgcGFyYW1ldGVycy5yZWN0YW5nbGUgPSBSZWN0YW5nbGVfZGVmYXVsdC5jbG9uZShwYXJhbWV0ZXJzLnJlY3RhbmdsZSk7CiAgICBjb25zdCBzdGF0aXN0aWNzMiA9IHByb2Nlc3NCdWZmZXIoCiAgICAgIHBhcmFtZXRlcnMuYnVmZmVyLAogICAgICBwYXJhbWV0ZXJzLnJlbGF0aXZlVG9DZW50ZXIsCiAgICAgIHBhcmFtZXRlcnMuZWxsaXBzb2lkLAogICAgICBwYXJhbWV0ZXJzLnJlY3RhbmdsZSwKICAgICAgcGFyYW1ldGVycy5uYXRpdmVSZWN0YW5nbGUsCiAgICAgIHBhcmFtZXRlcnMuZXhhZ2dlcmF0aW9uLAogICAgICBwYXJhbWV0ZXJzLmV4YWdnZXJhdGlvblJlbGF0aXZlSGVpZ2h0LAogICAgICBwYXJhbWV0ZXJzLnNraXJ0SGVpZ2h0LAogICAgICBwYXJhbWV0ZXJzLmluY2x1ZGVXZWJNZXJjYXRvclQsCiAgICAgIHBhcmFtZXRlcnMubmVnYXRpdmVBbHRpdHVkZUV4cG9uZW50QmlhcywKICAgICAgcGFyYW1ldGVycy5uZWdhdGl2ZUVsZXZhdGlvblRocmVzaG9sZAogICAgKTsKICAgIGNvbnN0IHZlcnRpY2VzID0gc3RhdGlzdGljczIudmVydGljZXM7CiAgICB0cmFuc2ZlcmFibGVPYmplY3RzLnB1c2godmVydGljZXMuYnVmZmVyKTsKICAgIGNvbnN0IGluZGljZXMgPSBzdGF0aXN0aWNzMi5pbmRpY2VzOwogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKGluZGljZXMuYnVmZmVyKTsKICAgIHJldHVybiB7CiAgICAgIHZlcnRpY2VzOiB2ZXJ0aWNlcy5idWZmZXIsCiAgICAgIGluZGljZXM6IGluZGljZXMuYnVmZmVyLAogICAgICBudW1iZXJPZkF0dHJpYnV0ZXM6IHN0YXRpc3RpY3MyLmVuY29kaW5nLnN0cmlkZSwKICAgICAgbWluaW11bUhlaWdodDogc3RhdGlzdGljczIubWluaW11bUhlaWdodCwKICAgICAgbWF4aW11bUhlaWdodDogc3RhdGlzdGljczIubWF4aW11bUhlaWdodCwKICAgICAgYm91bmRpbmdTcGhlcmUzRDogc3RhdGlzdGljczIuYm91bmRpbmdTcGhlcmUzRCwKICAgICAgb3JpZW50ZWRCb3VuZGluZ0JveDogc3RhdGlzdGljczIub3JpZW50ZWRCb3VuZGluZ0JveCwKICAgICAgb2NjbHVkZWVQb2ludEluU2NhbGVkU3BhY2U6IHN0YXRpc3RpY3MyLm9jY2x1ZGVlUG9pbnRJblNjYWxlZFNwYWNlLAogICAgICBlbmNvZGluZzogc3RhdGlzdGljczIuZW5jb2RpbmcsCiAgICAgIHZlcnRleENvdW50V2l0aG91dFNraXJ0czogc3RhdGlzdGljczIudmVydGV4Q291bnRXaXRob3V0U2tpcnRzLAogICAgICBpbmRleENvdW50V2l0aG91dFNraXJ0czogc3RhdGlzdGljczIuaW5kZXhDb3VudFdpdGhvdXRTa2lydHMsCiAgICAgIHdlc3RJbmRpY2VzU291dGhUb05vcnRoOiBzdGF0aXN0aWNzMi53ZXN0SW5kaWNlc1NvdXRoVG9Ob3J0aCwKICAgICAgc291dGhJbmRpY2VzRWFzdFRvV2VzdDogc3RhdGlzdGljczIuc291dGhJbmRpY2VzRWFzdFRvV2VzdCwKICAgICAgZWFzdEluZGljZXNOb3J0aFRvU291dGg6IHN0YXRpc3RpY3MyLmVhc3RJbmRpY2VzTm9ydGhUb1NvdXRoLAogICAgICBub3J0aEluZGljZXNXZXN0VG9FYXN0OiBzdGF0aXN0aWNzMi5ub3J0aEluZGljZXNXZXN0VG9FYXN0CiAgICB9OwogIH0KICBmdW5jdGlvbiBwcm9jZXNzQnVmZmVyKGJ1ZmZlciwgcmVsYXRpdmVUb0NlbnRlciwgZWxsaXBzb2lkLCByZWN0YW5nbGUsIG5hdGl2ZVJlY3RhbmdsZSwgZXhhZ2dlcmF0aW9uLCBleGFnZ2VyYXRpb25SZWxhdGl2ZUhlaWdodCwgc2tpcnRIZWlnaHQsIGluY2x1ZGVXZWJNZXJjYXRvclQsIG5lZ2F0aXZlQWx0aXR1ZGVFeHBvbmVudEJpYXMsIG5lZ2F0aXZlRWxldmF0aW9uVGhyZXNob2xkKSB7CiAgICBsZXQgZ2VvZ3JhcGhpY1dlc3Q7CiAgICBsZXQgZ2VvZ3JhcGhpY1NvdXRoOwogICAgbGV0IGdlb2dyYXBoaWNFYXN0OwogICAgbGV0IGdlb2dyYXBoaWNOb3J0aDsKICAgIGxldCByZWN0YW5nbGVXaWR0aCwgcmVjdGFuZ2xlSGVpZ2h0OwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVjdGFuZ2xlKSkgewogICAgICBnZW9ncmFwaGljV2VzdCA9IE1hdGhfZGVmYXVsdC50b1JhZGlhbnMobmF0aXZlUmVjdGFuZ2xlLndlc3QpOwogICAgICBnZW9ncmFwaGljU291dGggPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKG5hdGl2ZVJlY3RhbmdsZS5zb3V0aCk7CiAgICAgIGdlb2dyYXBoaWNFYXN0ID0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucyhuYXRpdmVSZWN0YW5nbGUuZWFzdCk7CiAgICAgIGdlb2dyYXBoaWNOb3J0aCA9IE1hdGhfZGVmYXVsdC50b1JhZGlhbnMobmF0aXZlUmVjdGFuZ2xlLm5vcnRoKTsKICAgICAgcmVjdGFuZ2xlV2lkdGggPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKHJlY3RhbmdsZS53aWR0aCk7CiAgICAgIHJlY3RhbmdsZUhlaWdodCA9IE1hdGhfZGVmYXVsdC50b1JhZGlhbnMocmVjdGFuZ2xlLmhlaWdodCk7CiAgICB9IGVsc2UgewogICAgICBnZW9ncmFwaGljV2VzdCA9IHJlY3RhbmdsZS53ZXN0OwogICAgICBnZW9ncmFwaGljU291dGggPSByZWN0YW5nbGUuc291dGg7CiAgICAgIGdlb2dyYXBoaWNFYXN0ID0gcmVjdGFuZ2xlLmVhc3Q7CiAgICAgIGdlb2dyYXBoaWNOb3J0aCA9IHJlY3RhbmdsZS5ub3J0aDsKICAgICAgcmVjdGFuZ2xlV2lkdGggPSByZWN0YW5nbGUud2lkdGg7CiAgICAgIHJlY3RhbmdsZUhlaWdodCA9IHJlY3RhbmdsZS5oZWlnaHQ7CiAgICB9CiAgICBjb25zdCBxdWFkQm9yZGVyTGF0aXR1ZGVzID0gW2dlb2dyYXBoaWNTb3V0aCwgZ2VvZ3JhcGhpY05vcnRoXTsKICAgIGNvbnN0IHF1YWRCb3JkZXJMb25naXR1ZGVzID0gW2dlb2dyYXBoaWNXZXN0LCBnZW9ncmFwaGljRWFzdF07CiAgICBjb25zdCBmcm9tRU5VID0gVHJhbnNmb3Jtc19kZWZhdWx0LmVhc3ROb3J0aFVwVG9GaXhlZEZyYW1lKAogICAgICByZWxhdGl2ZVRvQ2VudGVyLAogICAgICBlbGxpcHNvaWQKICAgICk7CiAgICBjb25zdCB0b0VOVSA9IE1hdHJpeDRfZGVmYXVsdC5pbnZlcnNlVHJhbnNmb3JtYXRpb24oZnJvbUVOVSwgbWF0cml4NFNjcmF0Y2gzKTsKICAgIGxldCBzb3V0aE1lcmNhdG9yWTsKICAgIGxldCBvbmVPdmVyTWVyY2F0b3JIZWlnaHQ7CiAgICBpZiAoaW5jbHVkZVdlYk1lcmNhdG9yVCkgewogICAgICBzb3V0aE1lcmNhdG9yWSA9IFdlYk1lcmNhdG9yUHJvamVjdGlvbl9kZWZhdWx0Lmdlb2RldGljTGF0aXR1ZGVUb01lcmNhdG9yQW5nbGUoZ2VvZ3JhcGhpY1NvdXRoKTsKICAgICAgb25lT3Zlck1lcmNhdG9ySGVpZ2h0ID0gMSAvIChXZWJNZXJjYXRvclByb2plY3Rpb25fZGVmYXVsdC5nZW9kZXRpY0xhdGl0dWRlVG9NZXJjYXRvckFuZ2xlKGdlb2dyYXBoaWNOb3J0aCkgLSBzb3V0aE1lcmNhdG9yWSk7CiAgICB9CiAgICBjb25zdCBoYXNFeGFnZ2VyYXRpb24gPSBleGFnZ2VyYXRpb24gIT09IDE7CiAgICBjb25zdCBpbmNsdWRlR2VvZGV0aWNTdXJmYWNlTm9ybWFscyA9IGhhc0V4YWdnZXJhdGlvbjsKICAgIGNvbnN0IGR2ID0gbmV3IERhdGFWaWV3KGJ1ZmZlcik7CiAgICBsZXQgbWluSGVpZ2h0ID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgbGV0IG1heEhlaWdodCA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgIGNvbnN0IG1pbmltdW0gPSBtaW5pbXVtU2NyYXRjaDsKICAgIG1pbmltdW0ueCA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTsKICAgIG1pbmltdW0ueSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTsKICAgIG1pbmltdW0ueiA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTsKICAgIGNvbnN0IG1heGltdW0gPSBtYXhpbXVtU2NyYXRjaDsKICAgIG1heGltdW0ueCA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgIG1heGltdW0ueSA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgIG1heGltdW0ueiA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgIGxldCBvZmZzZXQgPSAwOwogICAgbGV0IHNpemUgPSAwOwogICAgbGV0IGluZGljZXNTaXplID0gMDsKICAgIGxldCBxdWFkU2l6ZTsKICAgIGxldCBxdWFkOwogICAgZm9yIChxdWFkID0gMDsgcXVhZCA8IDQ7ICsrcXVhZCkgewogICAgICBsZXQgbyA9IG9mZnNldDsKICAgICAgcXVhZFNpemUgPSBkdi5nZXRVaW50MzIobywgdHJ1ZSk7CiAgICAgIG8gKz0gc2l6ZU9mVWludDMyOwogICAgICBjb25zdCB4ID0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucyhkdi5nZXRGbG9hdDY0KG8sIHRydWUpICogMTgwKTsKICAgICAgbyArPSBzaXplT2ZEb3VibGU7CiAgICAgIGlmIChpbmRleE9mRXBzaWxvbihxdWFkQm9yZGVyTG9uZ2l0dWRlcywgeCkgPT09IC0xKSB7CiAgICAgICAgcXVhZEJvcmRlckxvbmdpdHVkZXMucHVzaCh4KTsKICAgICAgfQogICAgICBjb25zdCB5ID0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucyhkdi5nZXRGbG9hdDY0KG8sIHRydWUpICogMTgwKTsKICAgICAgbyArPSBzaXplT2ZEb3VibGU7CiAgICAgIGlmIChpbmRleE9mRXBzaWxvbihxdWFkQm9yZGVyTGF0aXR1ZGVzLCB5KSA9PT0gLTEpIHsKICAgICAgICBxdWFkQm9yZGVyTGF0aXR1ZGVzLnB1c2goeSk7CiAgICAgIH0KICAgICAgbyArPSAyICogc2l6ZU9mRG91YmxlOwogICAgICBsZXQgYyA9IGR2LmdldEludDMyKG8sIHRydWUpOwogICAgICBvICs9IHNpemVPZkludDMyOwogICAgICBzaXplICs9IGM7CiAgICAgIGMgPSBkdi5nZXRJbnQzMihvLCB0cnVlKTsKICAgICAgaW5kaWNlc1NpemUgKz0gYyAqIDM7CiAgICAgIG9mZnNldCArPSBxdWFkU2l6ZSArIHNpemVPZlVpbnQzMjsKICAgIH0KICAgIGNvbnN0IHF1YWRCb3JkZXJQb2ludHMgPSBbXTsKICAgIGNvbnN0IHF1YWRCb3JkZXJJbmRpY2VzID0gW107CiAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgQXJyYXkoc2l6ZSk7CiAgICBjb25zdCB1dnMgPSBuZXcgQXJyYXkoc2l6ZSk7CiAgICBjb25zdCBoZWlnaHRzID0gbmV3IEFycmF5KHNpemUpOwogICAgY29uc3Qgd2ViTWVyY2F0b3JUcyA9IGluY2x1ZGVXZWJNZXJjYXRvclQgPyBuZXcgQXJyYXkoc2l6ZSkgOiBbXTsKICAgIGNvbnN0IGdlb2RldGljU3VyZmFjZU5vcm1hbHMgPSBpbmNsdWRlR2VvZGV0aWNTdXJmYWNlTm9ybWFscyA/IG5ldyBBcnJheShzaXplKSA6IFtdOwogICAgY29uc3QgaW5kaWNlcyA9IG5ldyBBcnJheShpbmRpY2VzU2l6ZSk7CiAgICBjb25zdCB3ZXN0Qm9yZGVyID0gW107CiAgICBjb25zdCBzb3V0aEJvcmRlciA9IFtdOwogICAgY29uc3QgZWFzdEJvcmRlciA9IFtdOwogICAgY29uc3Qgbm9ydGhCb3JkZXIgPSBbXTsKICAgIGxldCBwb2ludE9mZnNldCA9IDA7CiAgICBsZXQgaW5kaWNlc09mZnNldCA9IDA7CiAgICBvZmZzZXQgPSAwOwogICAgZm9yIChxdWFkID0gMDsgcXVhZCA8IDQ7ICsrcXVhZCkgewogICAgICBxdWFkU2l6ZSA9IGR2LmdldFVpbnQzMihvZmZzZXQsIHRydWUpOwogICAgICBvZmZzZXQgKz0gc2l6ZU9mVWludDMyOwogICAgICBjb25zdCBzdGFydFF1YWQgPSBvZmZzZXQ7CiAgICAgIGNvbnN0IG9yaWdpblggPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKGR2LmdldEZsb2F0NjQob2Zmc2V0LCB0cnVlKSAqIDE4MCk7CiAgICAgIG9mZnNldCArPSBzaXplT2ZEb3VibGU7CiAgICAgIGNvbnN0IG9yaWdpblkgPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKGR2LmdldEZsb2F0NjQob2Zmc2V0LCB0cnVlKSAqIDE4MCk7CiAgICAgIG9mZnNldCArPSBzaXplT2ZEb3VibGU7CiAgICAgIGNvbnN0IHN0ZXBYID0gTWF0aF9kZWZhdWx0LnRvUmFkaWFucyhkdi5nZXRGbG9hdDY0KG9mZnNldCwgdHJ1ZSkgKiAxODApOwogICAgICBjb25zdCBoYWxmU3RlcFggPSBzdGVwWCAqIDAuNTsKICAgICAgb2Zmc2V0ICs9IHNpemVPZkRvdWJsZTsKICAgICAgY29uc3Qgc3RlcFkgPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zKGR2LmdldEZsb2F0NjQob2Zmc2V0LCB0cnVlKSAqIDE4MCk7CiAgICAgIGNvbnN0IGhhbGZTdGVwWSA9IHN0ZXBZICogMC41OwogICAgICBvZmZzZXQgKz0gc2l6ZU9mRG91YmxlOwogICAgICBjb25zdCBudW1Qb2ludHMgPSBkdi5nZXRJbnQzMihvZmZzZXQsIHRydWUpOwogICAgICBvZmZzZXQgKz0gc2l6ZU9mSW50MzI7CiAgICAgIGNvbnN0IG51bUZhY2VzID0gZHYuZ2V0SW50MzIob2Zmc2V0LCB0cnVlKTsKICAgICAgb2Zmc2V0ICs9IHNpemVPZkludDMyOwogICAgICBvZmZzZXQgKz0gc2l6ZU9mSW50MzI7CiAgICAgIGNvbnN0IGluZGljZXNNYXBwaW5nID0gbmV3IEFycmF5KG51bVBvaW50cyk7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtUG9pbnRzOyArK2kpIHsKICAgICAgICBjb25zdCBsb25naXR1ZGUgPSBvcmlnaW5YICsgZHYuZ2V0VWludDgob2Zmc2V0KyspICogc3RlcFg7CiAgICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzcubG9uZ2l0dWRlID0gbG9uZ2l0dWRlOwogICAgICAgIGNvbnN0IGxhdGl0dWRlID0gb3JpZ2luWSArIGR2LmdldFVpbnQ4KG9mZnNldCsrKSAqIHN0ZXBZOwogICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWM3LmxhdGl0dWRlID0gbGF0aXR1ZGU7CiAgICAgICAgbGV0IGhlaWdodCA9IGR2LmdldEZsb2F0MzIob2Zmc2V0LCB0cnVlKTsKICAgICAgICBvZmZzZXQgKz0gc2l6ZU9mRmxvYXQ7CiAgICAgICAgaWYgKGhlaWdodCAhPT0gMCAmJiBoZWlnaHQgPCBuZWdhdGl2ZUVsZXZhdGlvblRocmVzaG9sZCkgewogICAgICAgICAgaGVpZ2h0ICo9IC1NYXRoLnBvdygyLCBuZWdhdGl2ZUFsdGl0dWRlRXhwb25lbnRCaWFzKTsKICAgICAgICB9CiAgICAgICAgaGVpZ2h0ICo9IDYzNzEwMTA7CiAgICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzcuaGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgIGlmIChpbmRleE9mRXBzaWxvbihxdWFkQm9yZGVyTG9uZ2l0dWRlcywgbG9uZ2l0dWRlKSAhPT0gLTEgfHwgaW5kZXhPZkVwc2lsb24ocXVhZEJvcmRlckxhdGl0dWRlcywgbGF0aXR1ZGUpICE9PSAtMSkgewogICAgICAgICAgY29uc3QgaW5kZXggPSBpbmRleE9mRXBzaWxvbigKICAgICAgICAgICAgcXVhZEJvcmRlclBvaW50cywKICAgICAgICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzcsCiAgICAgICAgICAgIENhcnRvZ3JhcGhpY19kZWZhdWx0CiAgICAgICAgICApOwogICAgICAgICAgaWYgKGluZGV4ID09PSAtMSkgewogICAgICAgICAgICBxdWFkQm9yZGVyUG9pbnRzLnB1c2goQ2FydG9ncmFwaGljX2RlZmF1bHQuY2xvbmUoc2NyYXRjaENhcnRvZ3JhcGhpYzcpKTsKICAgICAgICAgICAgcXVhZEJvcmRlckluZGljZXMucHVzaChwb2ludE9mZnNldCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpbmRpY2VzTWFwcGluZ1tpXSA9IHF1YWRCb3JkZXJJbmRpY2VzW2luZGV4XTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGluZGljZXNNYXBwaW5nW2ldID0gcG9pbnRPZmZzZXQ7CiAgICAgICAgaWYgKE1hdGguYWJzKGxvbmdpdHVkZSAtIGdlb2dyYXBoaWNXZXN0KSA8IGhhbGZTdGVwWCkgewogICAgICAgICAgd2VzdEJvcmRlci5wdXNoKHsKICAgICAgICAgICAgaW5kZXg6IHBvaW50T2Zmc2V0LAogICAgICAgICAgICBjYXJ0b2dyYXBoaWM6IENhcnRvZ3JhcGhpY19kZWZhdWx0LmNsb25lKHNjcmF0Y2hDYXJ0b2dyYXBoaWM3KQogICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIGlmIChNYXRoLmFicyhsb25naXR1ZGUgLSBnZW9ncmFwaGljRWFzdCkgPCBoYWxmU3RlcFgpIHsKICAgICAgICAgIGVhc3RCb3JkZXIucHVzaCh7CiAgICAgICAgICAgIGluZGV4OiBwb2ludE9mZnNldCwKICAgICAgICAgICAgY2FydG9ncmFwaGljOiBDYXJ0b2dyYXBoaWNfZGVmYXVsdC5jbG9uZShzY3JhdGNoQ2FydG9ncmFwaGljNykKICAgICAgICAgIH0pOwogICAgICAgIH0gZWxzZSBpZiAoTWF0aC5hYnMobGF0aXR1ZGUgLSBnZW9ncmFwaGljU291dGgpIDwgaGFsZlN0ZXBZKSB7CiAgICAgICAgICBzb3V0aEJvcmRlci5wdXNoKHsKICAgICAgICAgICAgaW5kZXg6IHBvaW50T2Zmc2V0LAogICAgICAgICAgICBjYXJ0b2dyYXBoaWM6IENhcnRvZ3JhcGhpY19kZWZhdWx0LmNsb25lKHNjcmF0Y2hDYXJ0b2dyYXBoaWM3KQogICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIGlmIChNYXRoLmFicyhsYXRpdHVkZSAtIGdlb2dyYXBoaWNOb3J0aCkgPCBoYWxmU3RlcFkpIHsKICAgICAgICAgIG5vcnRoQm9yZGVyLnB1c2goewogICAgICAgICAgICBpbmRleDogcG9pbnRPZmZzZXQsCiAgICAgICAgICAgIGNhcnRvZ3JhcGhpYzogQ2FydG9ncmFwaGljX2RlZmF1bHQuY2xvbmUoc2NyYXRjaENhcnRvZ3JhcGhpYzcpCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgbWluSGVpZ2h0ID0gTWF0aC5taW4oaGVpZ2h0LCBtaW5IZWlnaHQpOwogICAgICAgIG1heEhlaWdodCA9IE1hdGgubWF4KGhlaWdodCwgbWF4SGVpZ2h0KTsKICAgICAgICBoZWlnaHRzW3BvaW50T2Zmc2V0XSA9IGhlaWdodDsKICAgICAgICBjb25zdCBwb3MgPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oc2NyYXRjaENhcnRvZ3JhcGhpYzcpOwogICAgICAgIHBvc2l0aW9uc1twb2ludE9mZnNldF0gPSBwb3M7CiAgICAgICAgaWYgKGluY2x1ZGVXZWJNZXJjYXRvclQpIHsKICAgICAgICAgIHdlYk1lcmNhdG9yVHNbcG9pbnRPZmZzZXRdID0gKFdlYk1lcmNhdG9yUHJvamVjdGlvbl9kZWZhdWx0Lmdlb2RldGljTGF0aXR1ZGVUb01lcmNhdG9yQW5nbGUobGF0aXR1ZGUpIC0gc291dGhNZXJjYXRvclkpICogb25lT3Zlck1lcmNhdG9ySGVpZ2h0OwogICAgICAgIH0KICAgICAgICBpZiAoaW5jbHVkZUdlb2RldGljU3VyZmFjZU5vcm1hbHMpIHsKICAgICAgICAgIGNvbnN0IG5vcm1hbDIgPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKHBvcyk7CiAgICAgICAgICBnZW9kZXRpY1N1cmZhY2VOb3JtYWxzW3BvaW50T2Zmc2V0XSA9IG5vcm1hbDI7CiAgICAgICAgfQogICAgICAgIE1hdHJpeDRfZGVmYXVsdC5tdWx0aXBseUJ5UG9pbnQodG9FTlUsIHBvcywgc2NyYXRjaENhcnRlc2lhbjIwKTsKICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubWluaW11bUJ5Q29tcG9uZW50KHNjcmF0Y2hDYXJ0ZXNpYW4yMCwgbWluaW11bSwgbWluaW11bSk7CiAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm1heGltdW1CeUNvbXBvbmVudChzY3JhdGNoQ2FydGVzaWFuMjAsIG1heGltdW0sIG1heGltdW0pOwogICAgICAgIGxldCB1MyA9IChsb25naXR1ZGUgLSBnZW9ncmFwaGljV2VzdCkgLyAoZ2VvZ3JhcGhpY0Vhc3QgLSBnZW9ncmFwaGljV2VzdCk7CiAgICAgICAgdTMgPSBNYXRoX2RlZmF1bHQuY2xhbXAodTMsIDAsIDEpOwogICAgICAgIGxldCB2MyA9IChsYXRpdHVkZSAtIGdlb2dyYXBoaWNTb3V0aCkgLyAoZ2VvZ3JhcGhpY05vcnRoIC0gZ2VvZ3JhcGhpY1NvdXRoKTsKICAgICAgICB2MyA9IE1hdGhfZGVmYXVsdC5jbGFtcCh2MywgMCwgMSk7CiAgICAgICAgdXZzW3BvaW50T2Zmc2V0XSA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQodTMsIHYzKTsKICAgICAgICArK3BvaW50T2Zmc2V0OwogICAgICB9CiAgICAgIGNvbnN0IGZhY2VzRWxlbWVudENvdW50ID0gbnVtRmFjZXMgKiAzOwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGZhY2VzRWxlbWVudENvdW50OyArK2osICsraW5kaWNlc09mZnNldCkgewogICAgICAgIGluZGljZXNbaW5kaWNlc09mZnNldF0gPSBpbmRpY2VzTWFwcGluZ1tkdi5nZXRVaW50MTYob2Zmc2V0LCB0cnVlKV07CiAgICAgICAgb2Zmc2V0ICs9IHNpemVPZlVpbnQxNjsKICAgICAgfQogICAgICBpZiAocXVhZFNpemUgIT09IG9mZnNldCAtIHN0YXJ0UXVhZCkgewogICAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3JfZGVmYXVsdCgiSW52YWxpZCB0ZXJyYWluIHRpbGUuIik7CiAgICAgIH0KICAgIH0KICAgIHBvc2l0aW9ucy5sZW5ndGggPSBwb2ludE9mZnNldDsKICAgIHV2cy5sZW5ndGggPSBwb2ludE9mZnNldDsKICAgIGhlaWdodHMubGVuZ3RoID0gcG9pbnRPZmZzZXQ7CiAgICBpZiAoaW5jbHVkZVdlYk1lcmNhdG9yVCkgewogICAgICB3ZWJNZXJjYXRvclRzLmxlbmd0aCA9IHBvaW50T2Zmc2V0OwogICAgfQogICAgaWYgKGluY2x1ZGVHZW9kZXRpY1N1cmZhY2VOb3JtYWxzKSB7CiAgICAgIGdlb2RldGljU3VyZmFjZU5vcm1hbHMubGVuZ3RoID0gcG9pbnRPZmZzZXQ7CiAgICB9CiAgICBjb25zdCB2ZXJ0ZXhDb3VudFdpdGhvdXRTa2lydHMgPSBwb2ludE9mZnNldDsKICAgIGNvbnN0IGluZGV4Q291bnRXaXRob3V0U2tpcnRzID0gaW5kaWNlc09mZnNldDsKICAgIGNvbnN0IHNraXJ0T3B0aW9ucyA9IHsKICAgICAgaE1pbjogbWluSGVpZ2h0LAogICAgICBsYXN0Qm9yZGVyUG9pbnQ6IHZvaWQgMCwKICAgICAgc2tpcnRIZWlnaHQsCiAgICAgIHRvRU5VLAogICAgICBlbGxpcHNvaWQsCiAgICAgIG1pbmltdW0sCiAgICAgIG1heGltdW0KICAgIH07CiAgICB3ZXN0Qm9yZGVyLnNvcnQoZnVuY3Rpb24oYTMsIGIpIHsKICAgICAgcmV0dXJuIGIuY2FydG9ncmFwaGljLmxhdGl0dWRlIC0gYTMuY2FydG9ncmFwaGljLmxhdGl0dWRlOwogICAgfSk7CiAgICBzb3V0aEJvcmRlci5zb3J0KGZ1bmN0aW9uKGEzLCBiKSB7CiAgICAgIHJldHVybiBhMy5jYXJ0b2dyYXBoaWMubG9uZ2l0dWRlIC0gYi5jYXJ0b2dyYXBoaWMubG9uZ2l0dWRlOwogICAgfSk7CiAgICBlYXN0Qm9yZGVyLnNvcnQoZnVuY3Rpb24oYTMsIGIpIHsKICAgICAgcmV0dXJuIGEzLmNhcnRvZ3JhcGhpYy5sYXRpdHVkZSAtIGIuY2FydG9ncmFwaGljLmxhdGl0dWRlOwogICAgfSk7CiAgICBub3J0aEJvcmRlci5zb3J0KGZ1bmN0aW9uKGEzLCBiKSB7CiAgICAgIHJldHVybiBiLmNhcnRvZ3JhcGhpYy5sb25naXR1ZGUgLSBhMy5jYXJ0b2dyYXBoaWMubG9uZ2l0dWRlOwogICAgfSk7CiAgICBjb25zdCBwZXJjZW50YWdlID0gMWUtNTsKICAgIGFkZFNraXJ0KAogICAgICBwb3NpdGlvbnMsCiAgICAgIGhlaWdodHMsCiAgICAgIHV2cywKICAgICAgd2ViTWVyY2F0b3JUcywKICAgICAgZ2VvZGV0aWNTdXJmYWNlTm9ybWFscywKICAgICAgaW5kaWNlcywKICAgICAgc2tpcnRPcHRpb25zLAogICAgICB3ZXN0Qm9yZGVyLAogICAgICAtcGVyY2VudGFnZSAqIHJlY3RhbmdsZVdpZHRoLAogICAgICB0cnVlLAogICAgICAtcGVyY2VudGFnZSAqIHJlY3RhbmdsZUhlaWdodAogICAgKTsKICAgIGFkZFNraXJ0KAogICAgICBwb3NpdGlvbnMsCiAgICAgIGhlaWdodHMsCiAgICAgIHV2cywKICAgICAgd2ViTWVyY2F0b3JUcywKICAgICAgZ2VvZGV0aWNTdXJmYWNlTm9ybWFscywKICAgICAgaW5kaWNlcywKICAgICAgc2tpcnRPcHRpb25zLAogICAgICBzb3V0aEJvcmRlciwKICAgICAgLXBlcmNlbnRhZ2UgKiByZWN0YW5nbGVIZWlnaHQsCiAgICAgIGZhbHNlCiAgICApOwogICAgYWRkU2tpcnQoCiAgICAgIHBvc2l0aW9ucywKICAgICAgaGVpZ2h0cywKICAgICAgdXZzLAogICAgICB3ZWJNZXJjYXRvclRzLAogICAgICBnZW9kZXRpY1N1cmZhY2VOb3JtYWxzLAogICAgICBpbmRpY2VzLAogICAgICBza2lydE9wdGlvbnMsCiAgICAgIGVhc3RCb3JkZXIsCiAgICAgIHBlcmNlbnRhZ2UgKiByZWN0YW5nbGVXaWR0aCwKICAgICAgdHJ1ZSwKICAgICAgcGVyY2VudGFnZSAqIHJlY3RhbmdsZUhlaWdodAogICAgKTsKICAgIGFkZFNraXJ0KAogICAgICBwb3NpdGlvbnMsCiAgICAgIGhlaWdodHMsCiAgICAgIHV2cywKICAgICAgd2ViTWVyY2F0b3JUcywKICAgICAgZ2VvZGV0aWNTdXJmYWNlTm9ybWFscywKICAgICAgaW5kaWNlcywKICAgICAgc2tpcnRPcHRpb25zLAogICAgICBub3J0aEJvcmRlciwKICAgICAgcGVyY2VudGFnZSAqIHJlY3RhbmdsZUhlaWdodCwKICAgICAgZmFsc2UKICAgICk7CiAgICBpZiAod2VzdEJvcmRlci5sZW5ndGggPiAwICYmIG5vcnRoQm9yZGVyLmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgZmlyc3RCb3JkZXJJbmRleCA9IHdlc3RCb3JkZXJbMF0uaW5kZXg7CiAgICAgIGNvbnN0IGZpcnN0U2tpcnRJbmRleCA9IHZlcnRleENvdW50V2l0aG91dFNraXJ0czsKICAgICAgY29uc3QgbGFzdEJvcmRlckluZGV4ID0gbm9ydGhCb3JkZXJbbm9ydGhCb3JkZXIubGVuZ3RoIC0gMV0uaW5kZXg7CiAgICAgIGNvbnN0IGxhc3RTa2lydEluZGV4ID0gcG9zaXRpb25zLmxlbmd0aCAtIDE7CiAgICAgIGluZGljZXMucHVzaCgKICAgICAgICBsYXN0Qm9yZGVySW5kZXgsCiAgICAgICAgbGFzdFNraXJ0SW5kZXgsCiAgICAgICAgZmlyc3RTa2lydEluZGV4LAogICAgICAgIGZpcnN0U2tpcnRJbmRleCwKICAgICAgICBmaXJzdEJvcmRlckluZGV4LAogICAgICAgIGxhc3RCb3JkZXJJbmRleAogICAgICApOwogICAgfQogICAgc2l6ZSA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICBjb25zdCBib3VuZGluZ1NwaGVyZTNEID0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5mcm9tUG9pbnRzKHBvc2l0aW9ucyk7CiAgICBsZXQgb3JpZW50ZWRCb3VuZGluZ0JveDsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocmVjdGFuZ2xlKSkgewogICAgICBvcmllbnRlZEJvdW5kaW5nQm94ID0gT3JpZW50ZWRCb3VuZGluZ0JveF9kZWZhdWx0LmZyb21SZWN0YW5nbGUoCiAgICAgICAgcmVjdGFuZ2xlLAogICAgICAgIG1pbkhlaWdodCwKICAgICAgICBtYXhIZWlnaHQsCiAgICAgICAgZWxsaXBzb2lkCiAgICAgICk7CiAgICB9CiAgICBjb25zdCBvY2NsdWRlciA9IG5ldyBFbGxpcHNvaWRhbE9jY2x1ZGVyX2RlZmF1bHQoZWxsaXBzb2lkKTsKICAgIGNvbnN0IG9jY2x1ZGVlUG9pbnRJblNjYWxlZFNwYWNlID0gb2NjbHVkZXIuY29tcHV0ZUhvcml6b25DdWxsaW5nUG9pbnRQb3NzaWJseVVuZGVyRWxsaXBzb2lkKAogICAgICByZWxhdGl2ZVRvQ2VudGVyLAogICAgICBwb3NpdGlvbnMsCiAgICAgIG1pbkhlaWdodAogICAgKTsKICAgIGNvbnN0IGFhQm94ID0gbmV3IEF4aXNBbGlnbmVkQm91bmRpbmdCb3hfZGVmYXVsdChtaW5pbXVtLCBtYXhpbXVtLCByZWxhdGl2ZVRvQ2VudGVyKTsKICAgIGNvbnN0IGVuY29kaW5nID0gbmV3IFRlcnJhaW5FbmNvZGluZ19kZWZhdWx0KAogICAgICByZWxhdGl2ZVRvQ2VudGVyLAogICAgICBhYUJveCwKICAgICAgc2tpcnRPcHRpb25zLmhNaW4sCiAgICAgIG1heEhlaWdodCwKICAgICAgZnJvbUVOVSwKICAgICAgZmFsc2UsCiAgICAgIGluY2x1ZGVXZWJNZXJjYXRvclQsCiAgICAgIGluY2x1ZGVHZW9kZXRpY1N1cmZhY2VOb3JtYWxzLAogICAgICBleGFnZ2VyYXRpb24sCiAgICAgIGV4YWdnZXJhdGlvblJlbGF0aXZlSGVpZ2h0CiAgICApOwogICAgY29uc3QgdmVydGljZXMgPSBuZXcgRmxvYXQzMkFycmF5KHNpemUgKiBlbmNvZGluZy5zdHJpZGUpOwogICAgbGV0IGJ1ZmZlckluZGV4ID0gMDsKICAgIGZvciAobGV0IGsgPSAwOyBrIDwgc2l6ZTsgKytrKSB7CiAgICAgIGJ1ZmZlckluZGV4ID0gZW5jb2RpbmcuZW5jb2RlKAogICAgICAgIHZlcnRpY2VzLAogICAgICAgIGJ1ZmZlckluZGV4LAogICAgICAgIHBvc2l0aW9uc1trXSwKICAgICAgICB1dnNba10sCiAgICAgICAgaGVpZ2h0c1trXSwKICAgICAgICB2b2lkIDAsCiAgICAgICAgd2ViTWVyY2F0b3JUc1trXSwKICAgICAgICBnZW9kZXRpY1N1cmZhY2VOb3JtYWxzW2tdCiAgICAgICk7CiAgICB9CiAgICBjb25zdCB3ZXN0SW5kaWNlc1NvdXRoVG9Ob3J0aCA9IHdlc3RCb3JkZXIubWFwKGZ1bmN0aW9uKHZlcnRleCkgewogICAgICByZXR1cm4gdmVydGV4LmluZGV4OwogICAgfSkucmV2ZXJzZSgpOwogICAgY29uc3Qgc291dGhJbmRpY2VzRWFzdFRvV2VzdCA9IHNvdXRoQm9yZGVyLm1hcChmdW5jdGlvbih2ZXJ0ZXgpIHsKICAgICAgcmV0dXJuIHZlcnRleC5pbmRleDsKICAgIH0pLnJldmVyc2UoKTsKICAgIGNvbnN0IGVhc3RJbmRpY2VzTm9ydGhUb1NvdXRoID0gZWFzdEJvcmRlci5tYXAoZnVuY3Rpb24odmVydGV4KSB7CiAgICAgIHJldHVybiB2ZXJ0ZXguaW5kZXg7CiAgICB9KS5yZXZlcnNlKCk7CiAgICBjb25zdCBub3J0aEluZGljZXNXZXN0VG9FYXN0ID0gbm9ydGhCb3JkZXIubWFwKGZ1bmN0aW9uKHZlcnRleCkgewogICAgICByZXR1cm4gdmVydGV4LmluZGV4OwogICAgfSkucmV2ZXJzZSgpOwogICAgc291dGhJbmRpY2VzRWFzdFRvV2VzdC51bnNoaWZ0KAogICAgICBlYXN0SW5kaWNlc05vcnRoVG9Tb3V0aFtlYXN0SW5kaWNlc05vcnRoVG9Tb3V0aC5sZW5ndGggLSAxXQogICAgKTsKICAgIHNvdXRoSW5kaWNlc0Vhc3RUb1dlc3QucHVzaCh3ZXN0SW5kaWNlc1NvdXRoVG9Ob3J0aFswXSk7CiAgICBub3J0aEluZGljZXNXZXN0VG9FYXN0LnVuc2hpZnQoCiAgICAgIHdlc3RJbmRpY2VzU291dGhUb05vcnRoW3dlc3RJbmRpY2VzU291dGhUb05vcnRoLmxlbmd0aCAtIDFdCiAgICApOwogICAgbm9ydGhJbmRpY2VzV2VzdFRvRWFzdC5wdXNoKGVhc3RJbmRpY2VzTm9ydGhUb1NvdXRoWzBdKTsKICAgIHJldHVybiB7CiAgICAgIHZlcnRpY2VzLAogICAgICBpbmRpY2VzOiBuZXcgVWludDE2QXJyYXkoaW5kaWNlcyksCiAgICAgIG1heGltdW1IZWlnaHQ6IG1heEhlaWdodCwKICAgICAgbWluaW11bUhlaWdodDogbWluSGVpZ2h0LAogICAgICBlbmNvZGluZywKICAgICAgYm91bmRpbmdTcGhlcmUzRCwKICAgICAgb3JpZW50ZWRCb3VuZGluZ0JveCwKICAgICAgb2NjbHVkZWVQb2ludEluU2NhbGVkU3BhY2UsCiAgICAgIHZlcnRleENvdW50V2l0aG91dFNraXJ0cywKICAgICAgaW5kZXhDb3VudFdpdGhvdXRTa2lydHMsCiAgICAgIHdlc3RJbmRpY2VzU291dGhUb05vcnRoLAogICAgICBzb3V0aEluZGljZXNFYXN0VG9XZXN0LAogICAgICBlYXN0SW5kaWNlc05vcnRoVG9Tb3V0aCwKICAgICAgbm9ydGhJbmRpY2VzV2VzdFRvRWFzdAogICAgfTsKICB9CiAgZnVuY3Rpb24gYWRkU2tpcnQocG9zaXRpb25zLCBoZWlnaHRzLCB1dnMsIHdlYk1lcmNhdG9yVHMsIGdlb2RldGljU3VyZmFjZU5vcm1hbHMsIGluZGljZXMsIHNraXJ0T3B0aW9ucywgYm9yZGVyUG9pbnRzLCBmdWRnZUZhY3RvciwgZWFzdE9yV2VzdCwgY29ybmVyRnVkZ2UpIHsKICAgIGNvbnN0IGNvdW50ID0gYm9yZGVyUG9pbnRzLmxlbmd0aDsKICAgIGZvciAobGV0IGogPSAwOyBqIDwgY291bnQ7ICsraikgewogICAgICBjb25zdCBib3JkZXJQb2ludCA9IGJvcmRlclBvaW50c1tqXTsKICAgICAgY29uc3QgYm9yZGVyQ2FydG9ncmFwaGljID0gYm9yZGVyUG9pbnQuY2FydG9ncmFwaGljOwogICAgICBjb25zdCBib3JkZXJJbmRleCA9IGJvcmRlclBvaW50LmluZGV4OwogICAgICBjb25zdCBjdXJyZW50SW5kZXggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgICBjb25zdCBsb25naXR1ZGUgPSBib3JkZXJDYXJ0b2dyYXBoaWMubG9uZ2l0dWRlOwogICAgICBsZXQgbGF0aXR1ZGUgPSBib3JkZXJDYXJ0b2dyYXBoaWMubGF0aXR1ZGU7CiAgICAgIGxhdGl0dWRlID0gTWF0aF9kZWZhdWx0LmNsYW1wKAogICAgICAgIGxhdGl0dWRlLAogICAgICAgIC1NYXRoX2RlZmF1bHQuUElfT1ZFUl9UV08sCiAgICAgICAgTWF0aF9kZWZhdWx0LlBJX09WRVJfVFdPCiAgICAgICk7CiAgICAgIGNvbnN0IGhlaWdodCA9IGJvcmRlckNhcnRvZ3JhcGhpYy5oZWlnaHQgLSBza2lydE9wdGlvbnMuc2tpcnRIZWlnaHQ7CiAgICAgIHNraXJ0T3B0aW9ucy5oTWluID0gTWF0aC5taW4oc2tpcnRPcHRpb25zLmhNaW4sIGhlaWdodCk7CiAgICAgIENhcnRvZ3JhcGhpY19kZWZhdWx0LmZyb21SYWRpYW5zKGxvbmdpdHVkZSwgbGF0aXR1ZGUsIGhlaWdodCwgc2NyYXRjaENhcnRvZ3JhcGhpYzcpOwogICAgICBpZiAoZWFzdE9yV2VzdCkgewogICAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWM3LmxvbmdpdHVkZSArPSBmdWRnZUZhY3RvcjsKICAgICAgfQogICAgICBpZiAoIWVhc3RPcldlc3QpIHsKICAgICAgICBzY3JhdGNoQ2FydG9ncmFwaGljNy5sYXRpdHVkZSArPSBmdWRnZUZhY3RvcjsKICAgICAgfSBlbHNlIGlmIChqID09PSBjb3VudCAtIDEpIHsKICAgICAgICBzY3JhdGNoQ2FydG9ncmFwaGljNy5sYXRpdHVkZSArPSBjb3JuZXJGdWRnZTsKICAgICAgfSBlbHNlIGlmIChqID09PSAwKSB7CiAgICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzcubGF0aXR1ZGUgLT0gY29ybmVyRnVkZ2U7CiAgICAgIH0KICAgICAgY29uc3QgcG9zID0gc2tpcnRPcHRpb25zLmVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbihzY3JhdGNoQ2FydG9ncmFwaGljNyk7CiAgICAgIHBvc2l0aW9ucy5wdXNoKHBvcyk7CiAgICAgIGhlaWdodHMucHVzaChoZWlnaHQpOwogICAgICB1dnMucHVzaChDYXJ0ZXNpYW4yX2RlZmF1bHQuY2xvbmUodXZzW2JvcmRlckluZGV4XSkpOwogICAgICBpZiAod2ViTWVyY2F0b3JUcy5sZW5ndGggPiAwKSB7CiAgICAgICAgd2ViTWVyY2F0b3JUcy5wdXNoKHdlYk1lcmNhdG9yVHNbYm9yZGVySW5kZXhdKTsKICAgICAgfQogICAgICBpZiAoZ2VvZGV0aWNTdXJmYWNlTm9ybWFscy5sZW5ndGggPiAwKSB7CiAgICAgICAgZ2VvZGV0aWNTdXJmYWNlTm9ybWFscy5wdXNoKGdlb2RldGljU3VyZmFjZU5vcm1hbHNbYm9yZGVySW5kZXhdKTsKICAgICAgfQogICAgICBNYXRyaXg0X2RlZmF1bHQubXVsdGlwbHlCeVBvaW50KHNraXJ0T3B0aW9ucy50b0VOVSwgcG9zLCBzY3JhdGNoQ2FydGVzaWFuMjApOwogICAgICBjb25zdCBtaW5pbXVtID0gc2tpcnRPcHRpb25zLm1pbmltdW07CiAgICAgIGNvbnN0IG1heGltdW0gPSBza2lydE9wdGlvbnMubWF4aW11bTsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0Lm1pbmltdW1CeUNvbXBvbmVudChzY3JhdGNoQ2FydGVzaWFuMjAsIG1pbmltdW0sIG1pbmltdW0pOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubWF4aW11bUJ5Q29tcG9uZW50KHNjcmF0Y2hDYXJ0ZXNpYW4yMCwgbWF4aW11bSwgbWF4aW11bSk7CiAgICAgIGNvbnN0IGxhc3RCb3JkZXJQb2ludCA9IHNraXJ0T3B0aW9ucy5sYXN0Qm9yZGVyUG9pbnQ7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobGFzdEJvcmRlclBvaW50KSkgewogICAgICAgIGNvbnN0IGxhc3RCb3JkZXJJbmRleCA9IGxhc3RCb3JkZXJQb2ludC5pbmRleDsKICAgICAgICBpbmRpY2VzLnB1c2goCiAgICAgICAgICBsYXN0Qm9yZGVySW5kZXgsCiAgICAgICAgICBjdXJyZW50SW5kZXggLSAxLAogICAgICAgICAgY3VycmVudEluZGV4LAogICAgICAgICAgY3VycmVudEluZGV4LAogICAgICAgICAgYm9yZGVySW5kZXgsCiAgICAgICAgICBsYXN0Qm9yZGVySW5kZXgKICAgICAgICApOwogICAgICB9CiAgICAgIHNraXJ0T3B0aW9ucy5sYXN0Qm9yZGVyUG9pbnQgPSBib3JkZXJQb2ludDsKICAgIH0KICB9CiAgdmFyIHNpemVPZlVpbnQxNiwgc2l6ZU9mSW50MzIsIHNpemVPZlVpbnQzMiwgc2l6ZU9mRmxvYXQsIHNpemVPZkRvdWJsZSwgc2NyYXRjaENhcnRvZ3JhcGhpYzcsIHNjcmF0Y2hDYXJ0ZXNpYW4yMCwgbWluaW11bVNjcmF0Y2gsIG1heGltdW1TY3JhdGNoLCBtYXRyaXg0U2NyYXRjaDMsIGNyZWF0ZVZlcnRpY2VzRnJvbUdvb2dsZUVhcnRoRW50ZXJwcmlzZUJ1ZmZlcl9kZWZhdWx0OwogIHZhciBpbml0X2NyZWF0ZVZlcnRpY2VzRnJvbUdvb2dsZUVhcnRoRW50ZXJwcmlzZUJ1ZmZlciA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlVmVydGljZXNGcm9tR29vZ2xlRWFydGhFbnRlcnByaXNlQnVmZmVyLmpzIigpIHsKICAgICAgaW5pdF9BeGlzQWxpZ25lZEJvdW5kaW5nQm94KCk7CiAgICAgIGluaXRfQm91bmRpbmdTcGhlcmUoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4yKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NhcnRvZ3JhcGhpYygpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9FbGxpcHNvaWRhbE9jY2x1ZGVyKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X01hdHJpeDQoKTsKICAgICAgaW5pdF9PcmllbnRlZEJvdW5kaW5nQm94KCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfUnVudGltZUVycm9yKCk7CiAgICAgIGluaXRfVGVycmFpbkVuY29kaW5nKCk7CiAgICAgIGluaXRfVHJhbnNmb3JtcygpOwogICAgICBpbml0X1dlYk1lcmNhdG9yUHJvamVjdGlvbigpOwogICAgICBpbml0X2NyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXIoKTsKICAgICAgc2l6ZU9mVWludDE2ID0gVWludDE2QXJyYXkuQllURVNfUEVSX0VMRU1FTlQ7CiAgICAgIHNpemVPZkludDMyID0gSW50MzJBcnJheS5CWVRFU19QRVJfRUxFTUVOVDsKICAgICAgc2l6ZU9mVWludDMyID0gVWludDMyQXJyYXkuQllURVNfUEVSX0VMRU1FTlQ7CiAgICAgIHNpemVPZkZsb2F0ID0gRmxvYXQzMkFycmF5LkJZVEVTX1BFUl9FTEVNRU5UOwogICAgICBzaXplT2ZEb3VibGUgPSBGbG9hdDY0QXJyYXkuQllURVNfUEVSX0VMRU1FTlQ7CiAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWM3ID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4yMCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgbWluaW11bVNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIG1heGltdW1TY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBtYXRyaXg0U2NyYXRjaDMgPSBuZXcgTWF0cml4NF9kZWZhdWx0KCk7CiAgICAgIGNyZWF0ZVZlcnRpY2VzRnJvbUdvb2dsZUVhcnRoRW50ZXJwcmlzZUJ1ZmZlcl9kZWZhdWx0ID0gY3JlYXRlVGFza1Byb2Nlc3Nvcldvcmtlcl9kZWZhdWx0KAogICAgICAgIGNyZWF0ZVZlcnRpY2VzRnJvbUdvb2dsZUVhcnRoRW50ZXJwcmlzZUJ1ZmZlcgogICAgICApOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvSGVpZ2h0bWFwRW5jb2RpbmcuanMKICB2YXIgSGVpZ2h0bWFwRW5jb2RpbmcsIEhlaWdodG1hcEVuY29kaW5nX2RlZmF1bHQ7CiAgdmFyIGluaXRfSGVpZ2h0bWFwRW5jb2RpbmcgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0hlaWdodG1hcEVuY29kaW5nLmpzIigpIHsKICAgICAgSGVpZ2h0bWFwRW5jb2RpbmcgPSB7CiAgICAgICAgLyoqCiAgICAgICAgICogTm8gZW5jb2RpbmcKICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgTk9ORTogMCwKICAgICAgICAvKioKICAgICAgICAgKiBMRVJDIGVuY29kaW5nCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqCiAgICAgICAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL0VzcmkvbGVyY3xUaGUgTEVSQyBzcGVjaWZpY2F0aW9ufQogICAgICAgICAqLwogICAgICAgIExFUkM6IDEKICAgICAgfTsKICAgICAgSGVpZ2h0bWFwRW5jb2RpbmdfZGVmYXVsdCA9IE9iamVjdC5mcmVlemUoSGVpZ2h0bWFwRW5jb2RpbmcpOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvSGVpZ2h0bWFwVGVzc2VsbGF0b3IuanMKICB2YXIgSGVpZ2h0bWFwVGVzc2VsbGF0b3IsIGNhcnRlc2lhbjNTY3JhdGNoNywgbWF0cml4NFNjcmF0Y2g0LCBtaW5pbXVtU2NyYXRjaDIsIG1heGltdW1TY3JhdGNoMiwgSGVpZ2h0bWFwVGVzc2VsbGF0b3JfZGVmYXVsdDsKICB2YXIgaW5pdF9IZWlnaHRtYXBUZXNzZWxsYXRvciA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvSGVpZ2h0bWFwVGVzc2VsbGF0b3IuanMiKCkgewogICAgICBpbml0X0F4aXNBbGlnbmVkQm91bmRpbmdCb3goKTsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkYWxPY2NsdWRlcigpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9NYXRyaXg0KCk7CiAgICAgIGluaXRfT3JpZW50ZWRCb3VuZGluZ0JveCgpOwogICAgICBpbml0X1JlY3RhbmdsZSgpOwogICAgICBpbml0X1RlcnJhaW5FbmNvZGluZygpOwogICAgICBpbml0X1RyYW5zZm9ybXMoKTsKICAgICAgaW5pdF9XZWJNZXJjYXRvclByb2plY3Rpb24oKTsKICAgICAgSGVpZ2h0bWFwVGVzc2VsbGF0b3IgPSB7fTsKICAgICAgSGVpZ2h0bWFwVGVzc2VsbGF0b3IuREVGQVVMVF9TVFJVQ1RVUkUgPSBPYmplY3QuZnJlZXplKHsKICAgICAgICBoZWlnaHRTY2FsZTogMSwKICAgICAgICBoZWlnaHRPZmZzZXQ6IDAsCiAgICAgICAgZWxlbWVudHNQZXJIZWlnaHQ6IDEsCiAgICAgICAgc3RyaWRlOiAxLAogICAgICAgIGVsZW1lbnRNdWx0aXBsaWVyOiAyNTYsCiAgICAgICAgaXNCaWdFbmRpYW46IGZhbHNlCiAgICAgIH0pOwogICAgICBjYXJ0ZXNpYW4zU2NyYXRjaDcgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIG1hdHJpeDRTY3JhdGNoNCA9IG5ldyBNYXRyaXg0X2RlZmF1bHQoKTsKICAgICAgbWluaW11bVNjcmF0Y2gyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBtYXhpbXVtU2NyYXRjaDIgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIEhlaWdodG1hcFRlc3NlbGxhdG9yLmNvbXB1dGVWZXJ0aWNlcyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChvcHRpb25zKSB8fCAhZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMuaGVpZ2h0bWFwKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9wdGlvbnMuaGVpZ2h0bWFwIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChvcHRpb25zLndpZHRoKSB8fCAhZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMuaGVpZ2h0KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9wdGlvbnMud2lkdGggYW5kIG9wdGlvbnMuaGVpZ2h0IGFyZSByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQob3B0aW9ucy5uYXRpdmVSZWN0YW5nbGUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgib3B0aW9ucy5uYXRpdmVSZWN0YW5nbGUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG9wdGlvbnMuc2tpcnRIZWlnaHQpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgib3B0aW9ucy5za2lydEhlaWdodCBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgY29zNCA9IE1hdGguY29zOwogICAgICAgIGNvbnN0IHNpbjQgPSBNYXRoLnNpbjsKICAgICAgICBjb25zdCBzcXJ0MiA9IE1hdGguc3FydDsKICAgICAgICBjb25zdCBhdGFuID0gTWF0aC5hdGFuOwogICAgICAgIGNvbnN0IGV4cCA9IE1hdGguZXhwOwogICAgICAgIGNvbnN0IHBpT3ZlclR3byA9IE1hdGhfZGVmYXVsdC5QSV9PVkVSX1RXTzsKICAgICAgICBjb25zdCB0b1JhZGlhbnMgPSBNYXRoX2RlZmF1bHQudG9SYWRpYW5zOwogICAgICAgIGNvbnN0IGhlaWdodG1hcCA9IG9wdGlvbnMuaGVpZ2h0bWFwOwogICAgICAgIGNvbnN0IHdpZHRoID0gb3B0aW9ucy53aWR0aDsKICAgICAgICBjb25zdCBoZWlnaHQgPSBvcHRpb25zLmhlaWdodDsKICAgICAgICBjb25zdCBza2lydEhlaWdodCA9IG9wdGlvbnMuc2tpcnRIZWlnaHQ7CiAgICAgICAgY29uc3QgaGFzU2tpcnRzID0gc2tpcnRIZWlnaHQgPiAwOwogICAgICAgIGNvbnN0IGlzR2VvZ3JhcGhpYyA9IG9wdGlvbnMuaXNHZW9ncmFwaGljID8/IHRydWU7CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gb3B0aW9ucy5lbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgICAgICBjb25zdCBvbmVPdmVyR2xvYmVTZW1pbWFqb3JBeGlzID0gMSAvIGVsbGlwc29pZC5tYXhpbXVtUmFkaXVzOwogICAgICAgIGNvbnN0IG5hdGl2ZVJlY3RhbmdsZSA9IFJlY3RhbmdsZV9kZWZhdWx0LmNsb25lKG9wdGlvbnMubmF0aXZlUmVjdGFuZ2xlKTsKICAgICAgICBjb25zdCByZWN0YW5nbGUgPSBSZWN0YW5nbGVfZGVmYXVsdC5jbG9uZShvcHRpb25zLnJlY3RhbmdsZSk7CiAgICAgICAgbGV0IGdlb2dyYXBoaWNXZXN0OwogICAgICAgIGxldCBnZW9ncmFwaGljU291dGg7CiAgICAgICAgbGV0IGdlb2dyYXBoaWNFYXN0OwogICAgICAgIGxldCBnZW9ncmFwaGljTm9ydGg7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVjdGFuZ2xlKSkgewogICAgICAgICAgaWYgKGlzR2VvZ3JhcGhpYykgewogICAgICAgICAgICBnZW9ncmFwaGljV2VzdCA9IHRvUmFkaWFucyhuYXRpdmVSZWN0YW5nbGUud2VzdCk7CiAgICAgICAgICAgIGdlb2dyYXBoaWNTb3V0aCA9IHRvUmFkaWFucyhuYXRpdmVSZWN0YW5nbGUuc291dGgpOwogICAgICAgICAgICBnZW9ncmFwaGljRWFzdCA9IHRvUmFkaWFucyhuYXRpdmVSZWN0YW5nbGUuZWFzdCk7CiAgICAgICAgICAgIGdlb2dyYXBoaWNOb3J0aCA9IHRvUmFkaWFucyhuYXRpdmVSZWN0YW5nbGUubm9ydGgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZ2VvZ3JhcGhpY1dlc3QgPSBuYXRpdmVSZWN0YW5nbGUud2VzdCAqIG9uZU92ZXJHbG9iZVNlbWltYWpvckF4aXM7CiAgICAgICAgICAgIGdlb2dyYXBoaWNTb3V0aCA9IHBpT3ZlclR3byAtIDIgKiBhdGFuKGV4cCgtbmF0aXZlUmVjdGFuZ2xlLnNvdXRoICogb25lT3Zlckdsb2JlU2VtaW1ham9yQXhpcykpOwogICAgICAgICAgICBnZW9ncmFwaGljRWFzdCA9IG5hdGl2ZVJlY3RhbmdsZS5lYXN0ICogb25lT3Zlckdsb2JlU2VtaW1ham9yQXhpczsKICAgICAgICAgICAgZ2VvZ3JhcGhpY05vcnRoID0gcGlPdmVyVHdvIC0gMiAqIGF0YW4oZXhwKC1uYXRpdmVSZWN0YW5nbGUubm9ydGggKiBvbmVPdmVyR2xvYmVTZW1pbWFqb3JBeGlzKSk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGdlb2dyYXBoaWNXZXN0ID0gcmVjdGFuZ2xlLndlc3Q7CiAgICAgICAgICBnZW9ncmFwaGljU291dGggPSByZWN0YW5nbGUuc291dGg7CiAgICAgICAgICBnZW9ncmFwaGljRWFzdCA9IHJlY3RhbmdsZS5lYXN0OwogICAgICAgICAgZ2VvZ3JhcGhpY05vcnRoID0gcmVjdGFuZ2xlLm5vcnRoOwogICAgICAgIH0KICAgICAgICBsZXQgcmVsYXRpdmVUb0NlbnRlciA9IG9wdGlvbnMucmVsYXRpdmVUb0NlbnRlcjsKICAgICAgICBjb25zdCBoYXNSZWxhdGl2ZVRvQ2VudGVyID0gZGVmaW5lZF9kZWZhdWx0KHJlbGF0aXZlVG9DZW50ZXIpOwogICAgICAgIHJlbGF0aXZlVG9DZW50ZXIgPSBoYXNSZWxhdGl2ZVRvQ2VudGVyID8gcmVsYXRpdmVUb0NlbnRlciA6IENhcnRlc2lhbjNfZGVmYXVsdC5aRVJPOwogICAgICAgIGNvbnN0IGluY2x1ZGVXZWJNZXJjYXRvclQgPSBvcHRpb25zLmluY2x1ZGVXZWJNZXJjYXRvclQgPz8gZmFsc2U7CiAgICAgICAgY29uc3QgZXhhZ2dlcmF0aW9uID0gb3B0aW9ucy5leGFnZ2VyYXRpb24gPz8gMTsKICAgICAgICBjb25zdCBleGFnZ2VyYXRpb25SZWxhdGl2ZUhlaWdodCA9IG9wdGlvbnMuZXhhZ2dlcmF0aW9uUmVsYXRpdmVIZWlnaHQgPz8gMDsKICAgICAgICBjb25zdCBoYXNFeGFnZ2VyYXRpb24gPSBleGFnZ2VyYXRpb24gIT09IDE7CiAgICAgICAgY29uc3QgaW5jbHVkZUdlb2RldGljU3VyZmFjZU5vcm1hbHMgPSBoYXNFeGFnZ2VyYXRpb247CiAgICAgICAgY29uc3Qgc3RydWN0dXJlID0gb3B0aW9ucy5zdHJ1Y3R1cmUgPz8gSGVpZ2h0bWFwVGVzc2VsbGF0b3IuREVGQVVMVF9TVFJVQ1RVUkU7CiAgICAgICAgY29uc3QgaGVpZ2h0U2NhbGUgPSBzdHJ1Y3R1cmUuaGVpZ2h0U2NhbGUgPz8gSGVpZ2h0bWFwVGVzc2VsbGF0b3IuREVGQVVMVF9TVFJVQ1RVUkUuaGVpZ2h0U2NhbGU7CiAgICAgICAgY29uc3QgaGVpZ2h0T2Zmc2V0ID0gc3RydWN0dXJlLmhlaWdodE9mZnNldCA/PyBIZWlnaHRtYXBUZXNzZWxsYXRvci5ERUZBVUxUX1NUUlVDVFVSRS5oZWlnaHRPZmZzZXQ7CiAgICAgICAgY29uc3QgZWxlbWVudHNQZXJIZWlnaHQgPSBzdHJ1Y3R1cmUuZWxlbWVudHNQZXJIZWlnaHQgPz8gSGVpZ2h0bWFwVGVzc2VsbGF0b3IuREVGQVVMVF9TVFJVQ1RVUkUuZWxlbWVudHNQZXJIZWlnaHQ7CiAgICAgICAgY29uc3Qgc3RyaWRlID0gc3RydWN0dXJlLnN0cmlkZSA/PyBIZWlnaHRtYXBUZXNzZWxsYXRvci5ERUZBVUxUX1NUUlVDVFVSRS5zdHJpZGU7CiAgICAgICAgY29uc3QgZWxlbWVudE11bHRpcGxpZXIgPSBzdHJ1Y3R1cmUuZWxlbWVudE11bHRpcGxpZXIgPz8gSGVpZ2h0bWFwVGVzc2VsbGF0b3IuREVGQVVMVF9TVFJVQ1RVUkUuZWxlbWVudE11bHRpcGxpZXI7CiAgICAgICAgY29uc3QgaXNCaWdFbmRpYW4gPSBzdHJ1Y3R1cmUuaXNCaWdFbmRpYW4gPz8gSGVpZ2h0bWFwVGVzc2VsbGF0b3IuREVGQVVMVF9TVFJVQ1RVUkUuaXNCaWdFbmRpYW47CiAgICAgICAgbGV0IHJlY3RhbmdsZVdpZHRoID0gUmVjdGFuZ2xlX2RlZmF1bHQuY29tcHV0ZVdpZHRoKG5hdGl2ZVJlY3RhbmdsZSk7CiAgICAgICAgbGV0IHJlY3RhbmdsZUhlaWdodCA9IFJlY3RhbmdsZV9kZWZhdWx0LmNvbXB1dGVIZWlnaHQobmF0aXZlUmVjdGFuZ2xlKTsKICAgICAgICBjb25zdCBncmFudWxhcml0eVggPSByZWN0YW5nbGVXaWR0aCAvICh3aWR0aCAtIDEpOwogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5WSA9IHJlY3RhbmdsZUhlaWdodCAvIChoZWlnaHQgLSAxKTsKICAgICAgICBpZiAoIWlzR2VvZ3JhcGhpYykgewogICAgICAgICAgcmVjdGFuZ2xlV2lkdGggKj0gb25lT3Zlckdsb2JlU2VtaW1ham9yQXhpczsKICAgICAgICAgIHJlY3RhbmdsZUhlaWdodCAqPSBvbmVPdmVyR2xvYmVTZW1pbWFqb3JBeGlzOwogICAgICAgIH0KICAgICAgICBjb25zdCByYWRpaVNxdWFyZWQgPSBlbGxpcHNvaWQucmFkaWlTcXVhcmVkOwogICAgICAgIGNvbnN0IHJhZGlpU3F1YXJlZFggPSByYWRpaVNxdWFyZWQueDsKICAgICAgICBjb25zdCByYWRpaVNxdWFyZWRZID0gcmFkaWlTcXVhcmVkLnk7CiAgICAgICAgY29uc3QgcmFkaWlTcXVhcmVkWiA9IHJhZGlpU3F1YXJlZC56OwogICAgICAgIGxldCBtaW5pbXVtSGVpZ2h0ID0gNjU1MzY7CiAgICAgICAgbGV0IG1heGltdW1IZWlnaHQgPSAtNjU1MzY7CiAgICAgICAgY29uc3QgZnJvbUVOVSA9IFRyYW5zZm9ybXNfZGVmYXVsdC5lYXN0Tm9ydGhVcFRvRml4ZWRGcmFtZSgKICAgICAgICAgIHJlbGF0aXZlVG9DZW50ZXIsCiAgICAgICAgICBlbGxpcHNvaWQKICAgICAgICApOwogICAgICAgIGNvbnN0IHRvRU5VID0gTWF0cml4NF9kZWZhdWx0LmludmVyc2VUcmFuc2Zvcm1hdGlvbihmcm9tRU5VLCBtYXRyaXg0U2NyYXRjaDQpOwogICAgICAgIGxldCBzb3V0aE1lcmNhdG9yWTsKICAgICAgICBsZXQgb25lT3Zlck1lcmNhdG9ySGVpZ2h0OwogICAgICAgIGlmIChpbmNsdWRlV2ViTWVyY2F0b3JUKSB7CiAgICAgICAgICBzb3V0aE1lcmNhdG9yWSA9IFdlYk1lcmNhdG9yUHJvamVjdGlvbl9kZWZhdWx0Lmdlb2RldGljTGF0aXR1ZGVUb01lcmNhdG9yQW5nbGUoZ2VvZ3JhcGhpY1NvdXRoKTsKICAgICAgICAgIG9uZU92ZXJNZXJjYXRvckhlaWdodCA9IDEgLyAoV2ViTWVyY2F0b3JQcm9qZWN0aW9uX2RlZmF1bHQuZ2VvZGV0aWNMYXRpdHVkZVRvTWVyY2F0b3JBbmdsZShnZW9ncmFwaGljTm9ydGgpIC0gc291dGhNZXJjYXRvclkpOwogICAgICAgIH0KICAgICAgICBjb25zdCBtaW5pbXVtID0gbWluaW11bVNjcmF0Y2gyOwogICAgICAgIG1pbmltdW0ueCA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTsKICAgICAgICBtaW5pbXVtLnkgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICAgICAgbWluaW11bS56ID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgICAgIGNvbnN0IG1heGltdW0gPSBtYXhpbXVtU2NyYXRjaDI7CiAgICAgICAgbWF4aW11bS54ID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZOwogICAgICAgIG1heGltdW0ueSA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgICAgICBtYXhpbXVtLnogPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICAgICAgbGV0IGhNaW4gPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICAgICAgY29uc3QgZ3JpZFZlcnRleENvdW50ID0gd2lkdGggKiBoZWlnaHQ7CiAgICAgICAgY29uc3QgZWRnZVZlcnRleENvdW50ID0gc2tpcnRIZWlnaHQgPiAwID8gd2lkdGggKiAyICsgaGVpZ2h0ICogMiA6IDA7CiAgICAgICAgY29uc3QgdmVydGV4Q291bnQgPSBncmlkVmVydGV4Q291bnQgKyBlZGdlVmVydGV4Q291bnQ7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEFycmF5KHZlcnRleENvdW50KTsKICAgICAgICBjb25zdCBoZWlnaHRzID0gbmV3IEFycmF5KHZlcnRleENvdW50KTsKICAgICAgICBjb25zdCB1dnMgPSBuZXcgQXJyYXkodmVydGV4Q291bnQpOwogICAgICAgIGNvbnN0IHdlYk1lcmNhdG9yVHMgPSBpbmNsdWRlV2ViTWVyY2F0b3JUID8gbmV3IEFycmF5KHZlcnRleENvdW50KSA6IFtdOwogICAgICAgIGNvbnN0IGdlb2RldGljU3VyZmFjZU5vcm1hbHMgPSBpbmNsdWRlR2VvZGV0aWNTdXJmYWNlTm9ybWFscyA/IG5ldyBBcnJheSh2ZXJ0ZXhDb3VudCkgOiBbXTsKICAgICAgICBsZXQgc3RhcnRSb3cgPSAwOwogICAgICAgIGxldCBlbmRSb3cgPSBoZWlnaHQ7CiAgICAgICAgbGV0IHN0YXJ0Q29sID0gMDsKICAgICAgICBsZXQgZW5kQ29sID0gd2lkdGg7CiAgICAgICAgaWYgKGhhc1NraXJ0cykgewogICAgICAgICAgLS1zdGFydFJvdzsKICAgICAgICAgICsrZW5kUm93OwogICAgICAgICAgLS1zdGFydENvbDsKICAgICAgICAgICsrZW5kQ29sOwogICAgICAgIH0KICAgICAgICBjb25zdCBza2lydE9mZnNldFBlcmNlbnRhZ2UgPSAxZS01OwogICAgICAgIGZvciAobGV0IHJvd0luZGV4ID0gc3RhcnRSb3c7IHJvd0luZGV4IDwgZW5kUm93OyArK3Jvd0luZGV4KSB7CiAgICAgICAgICBsZXQgcm93ID0gcm93SW5kZXg7CiAgICAgICAgICBpZiAocm93IDwgMCkgewogICAgICAgICAgICByb3cgPSAwOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHJvdyA+PSBoZWlnaHQpIHsKICAgICAgICAgICAgcm93ID0gaGVpZ2h0IC0gMTsKICAgICAgICAgIH0KICAgICAgICAgIGxldCBsYXRpdHVkZSA9IG5hdGl2ZVJlY3RhbmdsZS5ub3J0aCAtIGdyYW51bGFyaXR5WSAqIHJvdzsKICAgICAgICAgIGlmICghaXNHZW9ncmFwaGljKSB7CiAgICAgICAgICAgIGxhdGl0dWRlID0gcGlPdmVyVHdvIC0gMiAqIGF0YW4oZXhwKC1sYXRpdHVkZSAqIG9uZU92ZXJHbG9iZVNlbWltYWpvckF4aXMpKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGxhdGl0dWRlID0gdG9SYWRpYW5zKGxhdGl0dWRlKTsKICAgICAgICAgIH0KICAgICAgICAgIGxldCB2MyA9IChsYXRpdHVkZSAtIGdlb2dyYXBoaWNTb3V0aCkgLyAoZ2VvZ3JhcGhpY05vcnRoIC0gZ2VvZ3JhcGhpY1NvdXRoKTsKICAgICAgICAgIHYzID0gTWF0aF9kZWZhdWx0LmNsYW1wKHYzLCAwLCAxKTsKICAgICAgICAgIGNvbnN0IGlzTm9ydGhFZGdlID0gcm93SW5kZXggPT09IHN0YXJ0Um93OwogICAgICAgICAgY29uc3QgaXNTb3V0aEVkZ2UgPSByb3dJbmRleCA9PT0gZW5kUm93IC0gMTsKICAgICAgICAgIGlmIChza2lydEhlaWdodCA+IDApIHsKICAgICAgICAgICAgaWYgKGlzTm9ydGhFZGdlKSB7CiAgICAgICAgICAgICAgbGF0aXR1ZGUgKz0gc2tpcnRPZmZzZXRQZXJjZW50YWdlICogcmVjdGFuZ2xlSGVpZ2h0OwogICAgICAgICAgICB9IGVsc2UgaWYgKGlzU291dGhFZGdlKSB7CiAgICAgICAgICAgICAgbGF0aXR1ZGUgLT0gc2tpcnRPZmZzZXRQZXJjZW50YWdlICogcmVjdGFuZ2xlSGVpZ2h0OwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBjb3NMYXRpdHVkZSA9IGNvczQobGF0aXR1ZGUpOwogICAgICAgICAgY29uc3QgblogPSBzaW40KGxhdGl0dWRlKTsKICAgICAgICAgIGNvbnN0IGtaID0gcmFkaWlTcXVhcmVkWiAqIG5aOwogICAgICAgICAgbGV0IHdlYk1lcmNhdG9yVDsKICAgICAgICAgIGlmIChpbmNsdWRlV2ViTWVyY2F0b3JUKSB7CiAgICAgICAgICAgIHdlYk1lcmNhdG9yVCA9IChXZWJNZXJjYXRvclByb2plY3Rpb25fZGVmYXVsdC5nZW9kZXRpY0xhdGl0dWRlVG9NZXJjYXRvckFuZ2xlKGxhdGl0dWRlKSAtIHNvdXRoTWVyY2F0b3JZKSAqIG9uZU92ZXJNZXJjYXRvckhlaWdodDsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAobGV0IGNvbEluZGV4ID0gc3RhcnRDb2w7IGNvbEluZGV4IDwgZW5kQ29sOyArK2NvbEluZGV4KSB7CiAgICAgICAgICAgIGxldCBjb2wgPSBjb2xJbmRleDsKICAgICAgICAgICAgaWYgKGNvbCA8IDApIHsKICAgICAgICAgICAgICBjb2wgPSAwOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChjb2wgPj0gd2lkdGgpIHsKICAgICAgICAgICAgICBjb2wgPSB3aWR0aCAtIDE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgdGVycmFpbk9mZnNldCA9IHJvdyAqICh3aWR0aCAqIHN0cmlkZSkgKyBjb2wgKiBzdHJpZGU7CiAgICAgICAgICAgIGxldCBoZWlnaHRTYW1wbGU7CiAgICAgICAgICAgIGlmIChlbGVtZW50c1BlckhlaWdodCA9PT0gMSkgewogICAgICAgICAgICAgIGhlaWdodFNhbXBsZSA9IGhlaWdodG1hcFt0ZXJyYWluT2Zmc2V0XTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBoZWlnaHRTYW1wbGUgPSAwOwogICAgICAgICAgICAgIGxldCBlbGVtZW50T2Zmc2V0OwogICAgICAgICAgICAgIGlmIChpc0JpZ0VuZGlhbikgewogICAgICAgICAgICAgICAgZm9yIChlbGVtZW50T2Zmc2V0ID0gMDsgZWxlbWVudE9mZnNldCA8IGVsZW1lbnRzUGVySGVpZ2h0OyArK2VsZW1lbnRPZmZzZXQpIHsKICAgICAgICAgICAgICAgICAgaGVpZ2h0U2FtcGxlID0gaGVpZ2h0U2FtcGxlICogZWxlbWVudE11bHRpcGxpZXIgKyBoZWlnaHRtYXBbdGVycmFpbk9mZnNldCArIGVsZW1lbnRPZmZzZXRdOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBmb3IgKGVsZW1lbnRPZmZzZXQgPSBlbGVtZW50c1BlckhlaWdodCAtIDE7IGVsZW1lbnRPZmZzZXQgPj0gMDsgLS1lbGVtZW50T2Zmc2V0KSB7CiAgICAgICAgICAgICAgICAgIGhlaWdodFNhbXBsZSA9IGhlaWdodFNhbXBsZSAqIGVsZW1lbnRNdWx0aXBsaWVyICsgaGVpZ2h0bWFwW3RlcnJhaW5PZmZzZXQgKyBlbGVtZW50T2Zmc2V0XTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaGVpZ2h0U2FtcGxlID0gaGVpZ2h0U2FtcGxlICogaGVpZ2h0U2NhbGUgKyBoZWlnaHRPZmZzZXQ7CiAgICAgICAgICAgIG1heGltdW1IZWlnaHQgPSBNYXRoLm1heChtYXhpbXVtSGVpZ2h0LCBoZWlnaHRTYW1wbGUpOwogICAgICAgICAgICBtaW5pbXVtSGVpZ2h0ID0gTWF0aC5taW4obWluaW11bUhlaWdodCwgaGVpZ2h0U2FtcGxlKTsKICAgICAgICAgICAgbGV0IGxvbmdpdHVkZSA9IG5hdGl2ZVJlY3RhbmdsZS53ZXN0ICsgZ3JhbnVsYXJpdHlYICogY29sOwogICAgICAgICAgICBpZiAoIWlzR2VvZ3JhcGhpYykgewogICAgICAgICAgICAgIGxvbmdpdHVkZSA9IGxvbmdpdHVkZSAqIG9uZU92ZXJHbG9iZVNlbWltYWpvckF4aXM7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgbG9uZ2l0dWRlID0gdG9SYWRpYW5zKGxvbmdpdHVkZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGV0IHUzID0gKGxvbmdpdHVkZSAtIGdlb2dyYXBoaWNXZXN0KSAvIChnZW9ncmFwaGljRWFzdCAtIGdlb2dyYXBoaWNXZXN0KTsKICAgICAgICAgICAgdTMgPSBNYXRoX2RlZmF1bHQuY2xhbXAodTMsIDAsIDEpOwogICAgICAgICAgICBsZXQgaW5kZXggPSByb3cgKiB3aWR0aCArIGNvbDsKICAgICAgICAgICAgaWYgKHNraXJ0SGVpZ2h0ID4gMCkgewogICAgICAgICAgICAgIGNvbnN0IGlzV2VzdEVkZ2UgPSBjb2xJbmRleCA9PT0gc3RhcnRDb2w7CiAgICAgICAgICAgICAgY29uc3QgaXNFYXN0RWRnZSA9IGNvbEluZGV4ID09PSBlbmRDb2wgLSAxOwogICAgICAgICAgICAgIGNvbnN0IGlzRWRnZTIgPSBpc05vcnRoRWRnZSB8fCBpc1NvdXRoRWRnZSB8fCBpc1dlc3RFZGdlIHx8IGlzRWFzdEVkZ2U7CiAgICAgICAgICAgICAgY29uc3QgaXNDb3JuZXIgPSAoaXNOb3J0aEVkZ2UgfHwgaXNTb3V0aEVkZ2UpICYmIChpc1dlc3RFZGdlIHx8IGlzRWFzdEVkZ2UpOwogICAgICAgICAgICAgIGlmIChpc0Nvcm5lcikgewogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0VkZ2UyKSB7CiAgICAgICAgICAgICAgICBoZWlnaHRTYW1wbGUgLT0gc2tpcnRIZWlnaHQ7CiAgICAgICAgICAgICAgICBpZiAoaXNXZXN0RWRnZSkgewogICAgICAgICAgICAgICAgICBpbmRleCA9IGdyaWRWZXJ0ZXhDb3VudCArIChoZWlnaHQgLSByb3cgLSAxKTsKICAgICAgICAgICAgICAgICAgbG9uZ2l0dWRlIC09IHNraXJ0T2Zmc2V0UGVyY2VudGFnZSAqIHJlY3RhbmdsZVdpZHRoOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1NvdXRoRWRnZSkgewogICAgICAgICAgICAgICAgICBpbmRleCA9IGdyaWRWZXJ0ZXhDb3VudCArIGhlaWdodCArICh3aWR0aCAtIGNvbCAtIDEpOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0Vhc3RFZGdlKSB7CiAgICAgICAgICAgICAgICAgIGluZGV4ID0gZ3JpZFZlcnRleENvdW50ICsgaGVpZ2h0ICsgd2lkdGggKyByb3c7CiAgICAgICAgICAgICAgICAgIGxvbmdpdHVkZSArPSBza2lydE9mZnNldFBlcmNlbnRhZ2UgKiByZWN0YW5nbGVXaWR0aDsKICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNOb3J0aEVkZ2UpIHsKICAgICAgICAgICAgICAgICAgaW5kZXggPSBncmlkVmVydGV4Q291bnQgKyBoZWlnaHQgKyB3aWR0aCArIGhlaWdodCArIGNvbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgblggPSBjb3NMYXRpdHVkZSAqIGNvczQobG9uZ2l0dWRlKTsKICAgICAgICAgICAgY29uc3QgblkgPSBjb3NMYXRpdHVkZSAqIHNpbjQobG9uZ2l0dWRlKTsKICAgICAgICAgICAgY29uc3Qga1ggPSByYWRpaVNxdWFyZWRYICogblg7CiAgICAgICAgICAgIGNvbnN0IGtZID0gcmFkaWlTcXVhcmVkWSAqIG5ZOwogICAgICAgICAgICBjb25zdCBnYW1tYSA9IHNxcnQyKGtYICogblggKyBrWSAqIG5ZICsga1ogKiBuWik7CiAgICAgICAgICAgIGNvbnN0IG9uZU92ZXJHYW1tYSA9IDEgLyBnYW1tYTsKICAgICAgICAgICAgY29uc3QgclN1cmZhY2VYID0ga1ggKiBvbmVPdmVyR2FtbWE7CiAgICAgICAgICAgIGNvbnN0IHJTdXJmYWNlWSA9IGtZICogb25lT3ZlckdhbW1hOwogICAgICAgICAgICBjb25zdCByU3VyZmFjZVogPSBrWiAqIG9uZU92ZXJHYW1tYTsKICAgICAgICAgICAgY29uc3QgcG9zaXRpb24gPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgICAgICAgIHBvc2l0aW9uLnggPSByU3VyZmFjZVggKyBuWCAqIGhlaWdodFNhbXBsZTsKICAgICAgICAgICAgcG9zaXRpb24ueSA9IHJTdXJmYWNlWSArIG5ZICogaGVpZ2h0U2FtcGxlOwogICAgICAgICAgICBwb3NpdGlvbi56ID0gclN1cmZhY2VaICsgblogKiBoZWlnaHRTYW1wbGU7CiAgICAgICAgICAgIE1hdHJpeDRfZGVmYXVsdC5tdWx0aXBseUJ5UG9pbnQodG9FTlUsIHBvc2l0aW9uLCBjYXJ0ZXNpYW4zU2NyYXRjaDcpOwogICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubWluaW11bUJ5Q29tcG9uZW50KGNhcnRlc2lhbjNTY3JhdGNoNywgbWluaW11bSwgbWluaW11bSk7CiAgICAgICAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tYXhpbXVtQnlDb21wb25lbnQoY2FydGVzaWFuM1NjcmF0Y2g3LCBtYXhpbXVtLCBtYXhpbXVtKTsKICAgICAgICAgICAgaE1pbiA9IE1hdGgubWluKGhNaW4sIGhlaWdodFNhbXBsZSk7CiAgICAgICAgICAgIHBvc2l0aW9uc1tpbmRleF0gPSBwb3NpdGlvbjsKICAgICAgICAgICAgdXZzW2luZGV4XSA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQodTMsIHYzKTsKICAgICAgICAgICAgaGVpZ2h0c1tpbmRleF0gPSBoZWlnaHRTYW1wbGU7CiAgICAgICAgICAgIGlmIChpbmNsdWRlV2ViTWVyY2F0b3JUKSB7CiAgICAgICAgICAgICAgd2ViTWVyY2F0b3JUc1tpbmRleF0gPSB3ZWJNZXJjYXRvclQ7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGluY2x1ZGVHZW9kZXRpY1N1cmZhY2VOb3JtYWxzKSB7CiAgICAgICAgICAgICAgZ2VvZGV0aWNTdXJmYWNlTm9ybWFsc1tpbmRleF0gPSBlbGxpcHNvaWQuZ2VvZGV0aWNTdXJmYWNlTm9ybWFsKHBvc2l0aW9uKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBib3VuZGluZ1NwaGVyZTNEID0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5mcm9tUG9pbnRzKHBvc2l0aW9ucyk7CiAgICAgICAgbGV0IG9yaWVudGVkQm91bmRpbmdCb3g7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChyZWN0YW5nbGUpKSB7CiAgICAgICAgICBvcmllbnRlZEJvdW5kaW5nQm94ID0gT3JpZW50ZWRCb3VuZGluZ0JveF9kZWZhdWx0LmZyb21SZWN0YW5nbGUoCiAgICAgICAgICAgIHJlY3RhbmdsZSwKICAgICAgICAgICAgbWluaW11bUhlaWdodCwKICAgICAgICAgICAgbWF4aW11bUhlaWdodCwKICAgICAgICAgICAgZWxsaXBzb2lkCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBsZXQgb2NjbHVkZWVQb2ludEluU2NhbGVkU3BhY2U7CiAgICAgICAgaWYgKGhhc1JlbGF0aXZlVG9DZW50ZXIpIHsKICAgICAgICAgIGNvbnN0IG9jY2x1ZGVyID0gbmV3IEVsbGlwc29pZGFsT2NjbHVkZXJfZGVmYXVsdChlbGxpcHNvaWQpOwogICAgICAgICAgb2NjbHVkZWVQb2ludEluU2NhbGVkU3BhY2UgPSBvY2NsdWRlci5jb21wdXRlSG9yaXpvbkN1bGxpbmdQb2ludFBvc3NpYmx5VW5kZXJFbGxpcHNvaWQoCiAgICAgICAgICAgIHJlbGF0aXZlVG9DZW50ZXIsCiAgICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgICAgbWluaW11bUhlaWdodAogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgYWFCb3ggPSBuZXcgQXhpc0FsaWduZWRCb3VuZGluZ0JveF9kZWZhdWx0KG1pbmltdW0sIG1heGltdW0sIHJlbGF0aXZlVG9DZW50ZXIpOwogICAgICAgIGNvbnN0IGVuY29kaW5nID0gbmV3IFRlcnJhaW5FbmNvZGluZ19kZWZhdWx0KAogICAgICAgICAgcmVsYXRpdmVUb0NlbnRlciwKICAgICAgICAgIGFhQm94LAogICAgICAgICAgaE1pbiwKICAgICAgICAgIG1heGltdW1IZWlnaHQsCiAgICAgICAgICBmcm9tRU5VLAogICAgICAgICAgZmFsc2UsCiAgICAgICAgICBpbmNsdWRlV2ViTWVyY2F0b3JULAogICAgICAgICAgaW5jbHVkZUdlb2RldGljU3VyZmFjZU5vcm1hbHMsCiAgICAgICAgICBleGFnZ2VyYXRpb24sCiAgICAgICAgICBleGFnZ2VyYXRpb25SZWxhdGl2ZUhlaWdodAogICAgICAgICk7CiAgICAgICAgY29uc3QgdmVydGljZXMgPSBuZXcgRmxvYXQzMkFycmF5KHZlcnRleENvdW50ICogZW5jb2Rpbmcuc3RyaWRlKTsKICAgICAgICBsZXQgYnVmZmVySW5kZXggPSAwOwogICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdmVydGV4Q291bnQ7ICsraikgewogICAgICAgICAgYnVmZmVySW5kZXggPSBlbmNvZGluZy5lbmNvZGUoCiAgICAgICAgICAgIHZlcnRpY2VzLAogICAgICAgICAgICBidWZmZXJJbmRleCwKICAgICAgICAgICAgcG9zaXRpb25zW2pdLAogICAgICAgICAgICB1dnNbal0sCiAgICAgICAgICAgIGhlaWdodHNbal0sCiAgICAgICAgICAgIHZvaWQgMCwKICAgICAgICAgICAgd2ViTWVyY2F0b3JUc1tqXSwKICAgICAgICAgICAgZ2VvZGV0aWNTdXJmYWNlTm9ybWFsc1tqXQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHZlcnRpY2VzLAogICAgICAgICAgbWF4aW11bUhlaWdodCwKICAgICAgICAgIG1pbmltdW1IZWlnaHQsCiAgICAgICAgICBlbmNvZGluZywKICAgICAgICAgIGJvdW5kaW5nU3BoZXJlM0QsCiAgICAgICAgICBvcmllbnRlZEJvdW5kaW5nQm94LAogICAgICAgICAgb2NjbHVkZWVQb2ludEluU2NhbGVkU3BhY2UKICAgICAgICB9OwogICAgICB9OwogICAgICBIZWlnaHRtYXBUZXNzZWxsYXRvcl9kZWZhdWx0ID0gSGVpZ2h0bWFwVGVzc2VsbGF0b3I7CiAgICB9CiAgfSk7CgogIC8vIG5vZGVfbW9kdWxlcy9sZXJjL0xlcmNEZWNvZGUuanMKICB2YXIgcmVxdWlyZV9MZXJjRGVjb2RlID0gX19jb21tb25KUyh7CiAgICAibm9kZV9tb2R1bGVzL2xlcmMvTGVyY0RlY29kZS5qcyIoZXhwb3J0czIsIG1vZHVsZSkgewogICAgICAvKiBDb3B5cmlnaHQgMjAxNS0yMDE4IEVzcmkuIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdCBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAgQHByZXNlcnZlICovCiAgICAgIChmdW5jdGlvbigpIHsKICAgICAgICB2YXIgTGVyY0RlY29kZSA9IChmdW5jdGlvbigpIHsKICAgICAgICAgIHZhciBDbnRaSW1hZ2UgPSB7fTsKICAgICAgICAgIENudFpJbWFnZS5kZWZhdWx0Tm9EYXRhVmFsdWUgPSAtMzQwMjc5OTkzODc5MDE0ODRlMjI7CiAgICAgICAgICBDbnRaSW1hZ2UuZGVjb2RlID0gZnVuY3Rpb24oaW5wdXQsIG9wdGlvbnMpIHsKICAgICAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307CiAgICAgICAgICAgIHZhciBza2lwTWFzayA9IG9wdGlvbnMuZW5jb2RlZE1hc2tEYXRhIHx8IG9wdGlvbnMuZW5jb2RlZE1hc2tEYXRhID09PSBudWxsOwogICAgICAgICAgICB2YXIgcGFyc2VkRGF0YSA9IHBhcnNlKGlucHV0LCBvcHRpb25zLmlucHV0T2Zmc2V0IHx8IDAsIHNraXBNYXNrKTsKICAgICAgICAgICAgdmFyIG5vRGF0YVZhbHVlID0gb3B0aW9ucy5ub0RhdGFWYWx1ZSAhPT0gbnVsbCA/IG9wdGlvbnMubm9EYXRhVmFsdWUgOiBDbnRaSW1hZ2UuZGVmYXVsdE5vRGF0YVZhbHVlOwogICAgICAgICAgICB2YXIgdW5jb21wcmVzc2VkRGF0YSA9IHVuY29tcHJlc3NQaXhlbFZhbHVlcygKICAgICAgICAgICAgICBwYXJzZWREYXRhLAogICAgICAgICAgICAgIG9wdGlvbnMucGl4ZWxUeXBlIHx8IEZsb2F0MzJBcnJheSwKICAgICAgICAgICAgICBvcHRpb25zLmVuY29kZWRNYXNrRGF0YSwKICAgICAgICAgICAgICBub0RhdGFWYWx1ZSwKICAgICAgICAgICAgICBvcHRpb25zLnJldHVybk1hc2sKICAgICAgICAgICAgKTsKICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHsKICAgICAgICAgICAgICB3aWR0aDogcGFyc2VkRGF0YS53aWR0aCwKICAgICAgICAgICAgICBoZWlnaHQ6IHBhcnNlZERhdGEuaGVpZ2h0LAogICAgICAgICAgICAgIHBpeGVsRGF0YTogdW5jb21wcmVzc2VkRGF0YS5yZXN1bHRQaXhlbHMsCiAgICAgICAgICAgICAgbWluVmFsdWU6IHVuY29tcHJlc3NlZERhdGEubWluVmFsdWUsCiAgICAgICAgICAgICAgbWF4VmFsdWU6IHBhcnNlZERhdGEucGl4ZWxzLm1heFZhbHVlLAogICAgICAgICAgICAgIG5vRGF0YVZhbHVlCiAgICAgICAgICAgIH07CiAgICAgICAgICAgIGlmICh1bmNvbXByZXNzZWREYXRhLnJlc3VsdE1hc2spIHsKICAgICAgICAgICAgICByZXN1bHQubWFza0RhdGEgPSB1bmNvbXByZXNzZWREYXRhLnJlc3VsdE1hc2s7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKG9wdGlvbnMucmV0dXJuRW5jb2RlZE1hc2sgJiYgcGFyc2VkRGF0YS5tYXNrKSB7CiAgICAgICAgICAgICAgcmVzdWx0LmVuY29kZWRNYXNrRGF0YSA9IHBhcnNlZERhdGEubWFzay5iaXRzZXQgPyBwYXJzZWREYXRhLm1hc2suYml0c2V0IDogbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAob3B0aW9ucy5yZXR1cm5GaWxlSW5mbykgewogICAgICAgICAgICAgIHJlc3VsdC5maWxlSW5mbyA9IGZvcm1hdEZpbGVJbmZvKHBhcnNlZERhdGEpOwogICAgICAgICAgICAgIGlmIChvcHRpb25zLmNvbXB1dGVVc2VkQml0RGVwdGhzKSB7CiAgICAgICAgICAgICAgICByZXN1bHQuZmlsZUluZm8uYml0RGVwdGhzID0gY29tcHV0ZVVzZWRCaXREZXB0aHMocGFyc2VkRGF0YSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIHVuY29tcHJlc3NQaXhlbFZhbHVlcyA9IGZ1bmN0aW9uKGRhdGEsIFR5cGVkQXJyYXlDbGFzcywgbWFza0JpdHNldCwgbm9EYXRhVmFsdWUsIHN0b3JlRGVjb2RlZE1hc2spIHsKICAgICAgICAgICAgdmFyIGJsb2NrSWR4ID0gMDsKICAgICAgICAgICAgdmFyIG51bVggPSBkYXRhLnBpeGVscy5udW1CbG9ja3NYOwogICAgICAgICAgICB2YXIgbnVtWSA9IGRhdGEucGl4ZWxzLm51bUJsb2Nrc1k7CiAgICAgICAgICAgIHZhciBibG9ja1dpZHRoID0gTWF0aC5mbG9vcihkYXRhLndpZHRoIC8gbnVtWCk7CiAgICAgICAgICAgIHZhciBibG9ja0hlaWdodCA9IE1hdGguZmxvb3IoZGF0YS5oZWlnaHQgLyBudW1ZKTsKICAgICAgICAgICAgdmFyIHNjYWxlID0gMiAqIGRhdGEubWF4WkVycm9yOwogICAgICAgICAgICB2YXIgbWluVmFsdWUgPSBOdW1iZXIuTUFYX1ZBTFVFLCBjdXJyZW50VmFsdWU7CiAgICAgICAgICAgIG1hc2tCaXRzZXQgPSBtYXNrQml0c2V0IHx8IChkYXRhLm1hc2sgPyBkYXRhLm1hc2suYml0c2V0IDogbnVsbCk7CiAgICAgICAgICAgIHZhciByZXN1bHRQaXhlbHMsIHJlc3VsdE1hc2s7CiAgICAgICAgICAgIHJlc3VsdFBpeGVscyA9IG5ldyBUeXBlZEFycmF5Q2xhc3MoZGF0YS53aWR0aCAqIGRhdGEuaGVpZ2h0KTsKICAgICAgICAgICAgaWYgKHN0b3JlRGVjb2RlZE1hc2sgJiYgbWFza0JpdHNldCkgewogICAgICAgICAgICAgIHJlc3VsdE1hc2sgPSBuZXcgVWludDhBcnJheShkYXRhLndpZHRoICogZGF0YS5oZWlnaHQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBibG9ja0RhdGFCdWZmZXIgPSBuZXcgRmxvYXQzMkFycmF5KGJsb2NrV2lkdGggKiBibG9ja0hlaWdodCk7CiAgICAgICAgICAgIHZhciB4eCwgeXk7CiAgICAgICAgICAgIGZvciAodmFyIHkgPSAwOyB5IDw9IG51bVk7IHkrKykgewogICAgICAgICAgICAgIHZhciB0aGlzQmxvY2tIZWlnaHQgPSB5ICE9PSBudW1ZID8gYmxvY2tIZWlnaHQgOiBkYXRhLmhlaWdodCAlIG51bVk7CiAgICAgICAgICAgICAgaWYgKHRoaXNCbG9ja0hlaWdodCA9PT0gMCkgewogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGZvciAodmFyIHggPSAwOyB4IDw9IG51bVg7IHgrKykgewogICAgICAgICAgICAgICAgdmFyIHRoaXNCbG9ja1dpZHRoID0geCAhPT0gbnVtWCA/IGJsb2NrV2lkdGggOiBkYXRhLndpZHRoICUgbnVtWDsKICAgICAgICAgICAgICAgIGlmICh0aGlzQmxvY2tXaWR0aCA9PT0gMCkgewogICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHZhciBvdXRQdHIgPSB5ICogZGF0YS53aWR0aCAqIGJsb2NrSGVpZ2h0ICsgeCAqIGJsb2NrV2lkdGg7CiAgICAgICAgICAgICAgICB2YXIgb3V0U3RyaWRlID0gZGF0YS53aWR0aCAtIHRoaXNCbG9ja1dpZHRoOwogICAgICAgICAgICAgICAgdmFyIGJsb2NrID0gZGF0YS5waXhlbHMuYmxvY2tzW2Jsb2NrSWR4XTsKICAgICAgICAgICAgICAgIHZhciBibG9ja0RhdGEsIGJsb2NrUHRyLCBjb25zdFZhbHVlOwogICAgICAgICAgICAgICAgaWYgKGJsb2NrLmVuY29kaW5nIDwgMikgewogICAgICAgICAgICAgICAgICBpZiAoYmxvY2suZW5jb2RpbmcgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICBibG9ja0RhdGEgPSBibG9jay5yYXdEYXRhOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIHVuc3R1ZmYoYmxvY2suc3R1ZmZlZERhdGEsIGJsb2NrLmJpdHNQZXJQaXhlbCwgYmxvY2subnVtVmFsaWRQaXhlbHMsIGJsb2NrLm9mZnNldCwgc2NhbGUsIGJsb2NrRGF0YUJ1ZmZlciwgZGF0YS5waXhlbHMubWF4VmFsdWUpOwogICAgICAgICAgICAgICAgICAgIGJsb2NrRGF0YSA9IGJsb2NrRGF0YUJ1ZmZlcjsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBibG9ja1B0ciA9IDA7CiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGJsb2NrLmVuY29kaW5nID09PSAyKSB7CiAgICAgICAgICAgICAgICAgIGNvbnN0VmFsdWUgPSAwOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgY29uc3RWYWx1ZSA9IGJsb2NrLm9mZnNldDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHZhciBtYXNrQnl0ZTsKICAgICAgICAgICAgICAgIGlmIChtYXNrQml0c2V0KSB7CiAgICAgICAgICAgICAgICAgIGZvciAoeXkgPSAwOyB5eSA8IHRoaXNCbG9ja0hlaWdodDsgeXkrKykgewogICAgICAgICAgICAgICAgICAgIGlmIChvdXRQdHIgJiA3KSB7CiAgICAgICAgICAgICAgICAgICAgICBtYXNrQnl0ZSA9IG1hc2tCaXRzZXRbb3V0UHRyID4+IDNdOwogICAgICAgICAgICAgICAgICAgICAgbWFza0J5dGUgPDw9IG91dFB0ciAmIDc7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZvciAoeHggPSAwOyB4eCA8IHRoaXNCbG9ja1dpZHRoOyB4eCsrKSB7CiAgICAgICAgICAgICAgICAgICAgICBpZiAoIShvdXRQdHIgJiA3KSkgewogICAgICAgICAgICAgICAgICAgICAgICBtYXNrQnl0ZSA9IG1hc2tCaXRzZXRbb3V0UHRyID4+IDNdOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2tCeXRlICYgMTI4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHRNYXNrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0TWFza1tvdXRQdHJdID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50VmFsdWUgPSBibG9jay5lbmNvZGluZyA8IDIgPyBibG9ja0RhdGFbYmxvY2tQdHIrK10gOiBjb25zdFZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICBtaW5WYWx1ZSA9IG1pblZhbHVlID4gY3VycmVudFZhbHVlID8gY3VycmVudFZhbHVlIDogbWluVmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdFBpeGVsc1tvdXRQdHIrK10gPSBjdXJyZW50VmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0TWFzaykgewogICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdE1hc2tbb3V0UHRyXSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0UGl4ZWxzW291dFB0cisrXSA9IG5vRGF0YVZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgbWFza0J5dGUgPDw9IDE7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIG91dFB0ciArPSBvdXRTdHJpZGU7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGlmIChibG9jay5lbmNvZGluZyA8IDIpIHsKICAgICAgICAgICAgICAgICAgICBmb3IgKHl5ID0gMDsgeXkgPCB0aGlzQmxvY2tIZWlnaHQ7IHl5KyspIHsKICAgICAgICAgICAgICAgICAgICAgIGZvciAoeHggPSAwOyB4eCA8IHRoaXNCbG9ja1dpZHRoOyB4eCsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRWYWx1ZSA9IGJsb2NrRGF0YVtibG9ja1B0cisrXTsKICAgICAgICAgICAgICAgICAgICAgICAgbWluVmFsdWUgPSBtaW5WYWx1ZSA+IGN1cnJlbnRWYWx1ZSA/IGN1cnJlbnRWYWx1ZSA6IG1pblZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRQaXhlbHNbb3V0UHRyKytdID0gY3VycmVudFZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgb3V0UHRyICs9IG91dFN0cmlkZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgbWluVmFsdWUgPSBtaW5WYWx1ZSA+IGNvbnN0VmFsdWUgPyBjb25zdFZhbHVlIDogbWluVmFsdWU7CiAgICAgICAgICAgICAgICAgICAgZm9yICh5eSA9IDA7IHl5IDwgdGhpc0Jsb2NrSGVpZ2h0OyB5eSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICBmb3IgKHh4ID0gMDsgeHggPCB0aGlzQmxvY2tXaWR0aDsgeHgrKykgewogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRQaXhlbHNbb3V0UHRyKytdID0gY29uc3RWYWx1ZTsKICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIG91dFB0ciArPSBvdXRTdHJpZGU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoYmxvY2suZW5jb2RpbmcgPT09IDEgJiYgYmxvY2tQdHIgIT09IGJsb2NrLm51bVZhbGlkUGl4ZWxzKSB7CiAgICAgICAgICAgICAgICAgIHRocm93ICJCbG9jayBhbmQgTWFzayBkbyBub3QgbWF0Y2giOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYmxvY2tJZHgrKzsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICByZXN1bHRQaXhlbHMsCiAgICAgICAgICAgICAgcmVzdWx0TWFzaywKICAgICAgICAgICAgICBtaW5WYWx1ZQogICAgICAgICAgICB9OwogICAgICAgICAgfTsKICAgICAgICAgIHZhciBmb3JtYXRGaWxlSW5mbyA9IGZ1bmN0aW9uKGRhdGEpIHsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAiZmlsZUlkZW50aWZpZXJTdHJpbmciOiBkYXRhLmZpbGVJZGVudGlmaWVyU3RyaW5nLAogICAgICAgICAgICAgICJmaWxlVmVyc2lvbiI6IGRhdGEuZmlsZVZlcnNpb24sCiAgICAgICAgICAgICAgImltYWdlVHlwZSI6IGRhdGEuaW1hZ2VUeXBlLAogICAgICAgICAgICAgICJoZWlnaHQiOiBkYXRhLmhlaWdodCwKICAgICAgICAgICAgICAid2lkdGgiOiBkYXRhLndpZHRoLAogICAgICAgICAgICAgICJtYXhaRXJyb3IiOiBkYXRhLm1heFpFcnJvciwKICAgICAgICAgICAgICAiZW9mT2Zmc2V0IjogZGF0YS5lb2ZPZmZzZXQsCiAgICAgICAgICAgICAgIm1hc2siOiBkYXRhLm1hc2sgPyB7CiAgICAgICAgICAgICAgICAibnVtQmxvY2tzWCI6IGRhdGEubWFzay5udW1CbG9ja3NYLAogICAgICAgICAgICAgICAgIm51bUJsb2Nrc1kiOiBkYXRhLm1hc2subnVtQmxvY2tzWSwKICAgICAgICAgICAgICAgICJudW1CeXRlcyI6IGRhdGEubWFzay5udW1CeXRlcywKICAgICAgICAgICAgICAgICJtYXhWYWx1ZSI6IGRhdGEubWFzay5tYXhWYWx1ZQogICAgICAgICAgICAgIH0gOiBudWxsLAogICAgICAgICAgICAgICJwaXhlbHMiOiB7CiAgICAgICAgICAgICAgICAibnVtQmxvY2tzWCI6IGRhdGEucGl4ZWxzLm51bUJsb2Nrc1gsCiAgICAgICAgICAgICAgICAibnVtQmxvY2tzWSI6IGRhdGEucGl4ZWxzLm51bUJsb2Nrc1ksCiAgICAgICAgICAgICAgICAibnVtQnl0ZXMiOiBkYXRhLnBpeGVscy5udW1CeXRlcywKICAgICAgICAgICAgICAgICJtYXhWYWx1ZSI6IGRhdGEucGl4ZWxzLm1heFZhbHVlLAogICAgICAgICAgICAgICAgIm5vRGF0YVZhbHVlIjogZGF0YS5ub0RhdGFWYWx1ZQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfTsKICAgICAgICAgIH07CiAgICAgICAgICB2YXIgY29tcHV0ZVVzZWRCaXREZXB0aHMgPSBmdW5jdGlvbihkYXRhKSB7CiAgICAgICAgICAgIHZhciBudW1CbG9ja3MgPSBkYXRhLnBpeGVscy5udW1CbG9ja3NYICogZGF0YS5waXhlbHMubnVtQmxvY2tzWTsKICAgICAgICAgICAgdmFyIGJpdERlcHRocyA9IHt9OwogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bUJsb2NrczsgaSsrKSB7CiAgICAgICAgICAgICAgdmFyIGJsb2NrID0gZGF0YS5waXhlbHMuYmxvY2tzW2ldOwogICAgICAgICAgICAgIGlmIChibG9jay5lbmNvZGluZyA9PT0gMCkgewogICAgICAgICAgICAgICAgYml0RGVwdGhzLmZsb2F0MzIgPSB0cnVlOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAoYmxvY2suZW5jb2RpbmcgPT09IDEpIHsKICAgICAgICAgICAgICAgIGJpdERlcHRoc1tibG9jay5iaXRzUGVyUGl4ZWxdID0gdHJ1ZTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgYml0RGVwdGhzWzBdID0gdHJ1ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKGJpdERlcHRocyk7CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIHBhcnNlID0gZnVuY3Rpb24oaW5wdXQsIGZwLCBza2lwTWFzaykgewogICAgICAgICAgICB2YXIgZGF0YSA9IHt9OwogICAgICAgICAgICB2YXIgZmlsZUlkVmlldyA9IG5ldyBVaW50OEFycmF5KGlucHV0LCBmcCwgMTApOwogICAgICAgICAgICBkYXRhLmZpbGVJZGVudGlmaWVyU3RyaW5nID0gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBmaWxlSWRWaWV3KTsKICAgICAgICAgICAgaWYgKGRhdGEuZmlsZUlkZW50aWZpZXJTdHJpbmcudHJpbSgpICE9PSAiQ250WkltYWdlIikgewogICAgICAgICAgICAgIHRocm93ICJVbmV4cGVjdGVkIGZpbGUgaWRlbnRpZmllciBzdHJpbmc6ICIgKyBkYXRhLmZpbGVJZGVudGlmaWVyU3RyaW5nOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZwICs9IDEwOwogICAgICAgICAgICB2YXIgdmlldyA9IG5ldyBEYXRhVmlldyhpbnB1dCwgZnAsIDI0KTsKICAgICAgICAgICAgZGF0YS5maWxlVmVyc2lvbiA9IHZpZXcuZ2V0SW50MzIoMCwgdHJ1ZSk7CiAgICAgICAgICAgIGRhdGEuaW1hZ2VUeXBlID0gdmlldy5nZXRJbnQzMig0LCB0cnVlKTsKICAgICAgICAgICAgZGF0YS5oZWlnaHQgPSB2aWV3LmdldFVpbnQzMig4LCB0cnVlKTsKICAgICAgICAgICAgZGF0YS53aWR0aCA9IHZpZXcuZ2V0VWludDMyKDEyLCB0cnVlKTsKICAgICAgICAgICAgZGF0YS5tYXhaRXJyb3IgPSB2aWV3LmdldEZsb2F0NjQoMTYsIHRydWUpOwogICAgICAgICAgICBmcCArPSAyNDsKICAgICAgICAgICAgaWYgKCFza2lwTWFzaykgewogICAgICAgICAgICAgIHZpZXcgPSBuZXcgRGF0YVZpZXcoaW5wdXQsIGZwLCAxNik7CiAgICAgICAgICAgICAgZGF0YS5tYXNrID0ge307CiAgICAgICAgICAgICAgZGF0YS5tYXNrLm51bUJsb2Nrc1kgPSB2aWV3LmdldFVpbnQzMigwLCB0cnVlKTsKICAgICAgICAgICAgICBkYXRhLm1hc2subnVtQmxvY2tzWCA9IHZpZXcuZ2V0VWludDMyKDQsIHRydWUpOwogICAgICAgICAgICAgIGRhdGEubWFzay5udW1CeXRlcyA9IHZpZXcuZ2V0VWludDMyKDgsIHRydWUpOwogICAgICAgICAgICAgIGRhdGEubWFzay5tYXhWYWx1ZSA9IHZpZXcuZ2V0RmxvYXQzMigxMiwgdHJ1ZSk7CiAgICAgICAgICAgICAgZnAgKz0gMTY7CiAgICAgICAgICAgICAgaWYgKGRhdGEubWFzay5udW1CeXRlcyA+IDApIHsKICAgICAgICAgICAgICAgIHZhciBiaXRzZXQgPSBuZXcgVWludDhBcnJheShNYXRoLmNlaWwoZGF0YS53aWR0aCAqIGRhdGEuaGVpZ2h0IC8gOCkpOwogICAgICAgICAgICAgICAgdmlldyA9IG5ldyBEYXRhVmlldyhpbnB1dCwgZnAsIGRhdGEubWFzay5udW1CeXRlcyk7CiAgICAgICAgICAgICAgICB2YXIgY250ID0gdmlldy5nZXRJbnQxNigwLCB0cnVlKTsKICAgICAgICAgICAgICAgIHZhciBpcCA9IDIsIG9wID0gMDsKICAgICAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAgICAgaWYgKGNudCA+IDApIHsKICAgICAgICAgICAgICAgICAgICB3aGlsZSAoY250LS0pIHsKICAgICAgICAgICAgICAgICAgICAgIGJpdHNldFtvcCsrXSA9IHZpZXcuZ2V0VWludDgoaXArKyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIHZhciB2YWwgPSB2aWV3LmdldFVpbnQ4KGlwKyspOwogICAgICAgICAgICAgICAgICAgIGNudCA9IC1jbnQ7CiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGNudC0tKSB7CiAgICAgICAgICAgICAgICAgICAgICBiaXRzZXRbb3ArK10gPSB2YWw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGNudCA9IHZpZXcuZ2V0SW50MTYoaXAsIHRydWUpOwogICAgICAgICAgICAgICAgICBpcCArPSAyOwogICAgICAgICAgICAgICAgfSB3aGlsZSAoaXAgPCBkYXRhLm1hc2subnVtQnl0ZXMpOwogICAgICAgICAgICAgICAgaWYgKGNudCAhPT0gLTMyNzY4IHx8IG9wIDwgYml0c2V0Lmxlbmd0aCkgewogICAgICAgICAgICAgICAgICB0aHJvdyAiVW5leHBlY3RlZCBlbmQgb2YgbWFzayBSTEUgZW5jb2RpbmciOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZGF0YS5tYXNrLmJpdHNldCA9IGJpdHNldDsKICAgICAgICAgICAgICAgIGZwICs9IGRhdGEubWFzay5udW1CeXRlczsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKChkYXRhLm1hc2subnVtQnl0ZXMgfCBkYXRhLm1hc2subnVtQmxvY2tzWSB8IGRhdGEubWFzay5tYXhWYWx1ZSkgPT09IDApIHsKICAgICAgICAgICAgICAgIGRhdGEubWFzay5iaXRzZXQgPSBuZXcgVWludDhBcnJheShNYXRoLmNlaWwoZGF0YS53aWR0aCAqIGRhdGEuaGVpZ2h0IC8gOCkpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICB2aWV3ID0gbmV3IERhdGFWaWV3KGlucHV0LCBmcCwgMTYpOwogICAgICAgICAgICBkYXRhLnBpeGVscyA9IHt9OwogICAgICAgICAgICBkYXRhLnBpeGVscy5udW1CbG9ja3NZID0gdmlldy5nZXRVaW50MzIoMCwgdHJ1ZSk7CiAgICAgICAgICAgIGRhdGEucGl4ZWxzLm51bUJsb2Nrc1ggPSB2aWV3LmdldFVpbnQzMig0LCB0cnVlKTsKICAgICAgICAgICAgZGF0YS5waXhlbHMubnVtQnl0ZXMgPSB2aWV3LmdldFVpbnQzMig4LCB0cnVlKTsKICAgICAgICAgICAgZGF0YS5waXhlbHMubWF4VmFsdWUgPSB2aWV3LmdldEZsb2F0MzIoMTIsIHRydWUpOwogICAgICAgICAgICBmcCArPSAxNjsKICAgICAgICAgICAgdmFyIG51bUJsb2Nrc1ggPSBkYXRhLnBpeGVscy5udW1CbG9ja3NYOwogICAgICAgICAgICB2YXIgbnVtQmxvY2tzWSA9IGRhdGEucGl4ZWxzLm51bUJsb2Nrc1k7CiAgICAgICAgICAgIHZhciBhY3R1YWxOdW1CbG9ja3NYID0gbnVtQmxvY2tzWCArIChkYXRhLndpZHRoICUgbnVtQmxvY2tzWCA+IDAgPyAxIDogMCk7CiAgICAgICAgICAgIHZhciBhY3R1YWxOdW1CbG9ja3NZID0gbnVtQmxvY2tzWSArIChkYXRhLmhlaWdodCAlIG51bUJsb2Nrc1kgPiAwID8gMSA6IDApOwogICAgICAgICAgICBkYXRhLnBpeGVscy5ibG9ja3MgPSBuZXcgQXJyYXkoYWN0dWFsTnVtQmxvY2tzWCAqIGFjdHVhbE51bUJsb2Nrc1kpOwogICAgICAgICAgICB2YXIgYmxvY2tJID0gMDsKICAgICAgICAgICAgZm9yICh2YXIgYmxvY2tZID0gMDsgYmxvY2tZIDwgYWN0dWFsTnVtQmxvY2tzWTsgYmxvY2tZKyspIHsKICAgICAgICAgICAgICBmb3IgKHZhciBibG9ja1ggPSAwOyBibG9ja1ggPCBhY3R1YWxOdW1CbG9ja3NYOyBibG9ja1grKykgewogICAgICAgICAgICAgICAgdmFyIHNpemUgPSAwOwogICAgICAgICAgICAgICAgdmFyIGJ5dGVzTGVmdCA9IGlucHV0LmJ5dGVMZW5ndGggLSBmcDsKICAgICAgICAgICAgICAgIHZpZXcgPSBuZXcgRGF0YVZpZXcoaW5wdXQsIGZwLCBNYXRoLm1pbigxMCwgYnl0ZXNMZWZ0KSk7CiAgICAgICAgICAgICAgICB2YXIgYmxvY2sgPSB7fTsKICAgICAgICAgICAgICAgIGRhdGEucGl4ZWxzLmJsb2Nrc1tibG9ja0krK10gPSBibG9jazsKICAgICAgICAgICAgICAgIHZhciBoZWFkZXJCeXRlID0gdmlldy5nZXRVaW50OCgwKTsKICAgICAgICAgICAgICAgIHNpemUrKzsKICAgICAgICAgICAgICAgIGJsb2NrLmVuY29kaW5nID0gaGVhZGVyQnl0ZSAmIDYzOwogICAgICAgICAgICAgICAgaWYgKGJsb2NrLmVuY29kaW5nID4gMykgewogICAgICAgICAgICAgICAgICB0aHJvdyAiSW52YWxpZCBibG9jayBlbmNvZGluZyAoIiArIGJsb2NrLmVuY29kaW5nICsgIikiOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKGJsb2NrLmVuY29kaW5nID09PSAyKSB7CiAgICAgICAgICAgICAgICAgIGZwKys7CiAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKGhlYWRlckJ5dGUgIT09IDAgJiYgaGVhZGVyQnl0ZSAhPT0gMikgewogICAgICAgICAgICAgICAgICBoZWFkZXJCeXRlID4+PSA2OwogICAgICAgICAgICAgICAgICBibG9jay5vZmZzZXRUeXBlID0gaGVhZGVyQnl0ZTsKICAgICAgICAgICAgICAgICAgaWYgKGhlYWRlckJ5dGUgPT09IDIpIHsKICAgICAgICAgICAgICAgICAgICBibG9jay5vZmZzZXQgPSB2aWV3LmdldEludDgoMSk7CiAgICAgICAgICAgICAgICAgICAgc2l6ZSsrOwogICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGhlYWRlckJ5dGUgPT09IDEpIHsKICAgICAgICAgICAgICAgICAgICBibG9jay5vZmZzZXQgPSB2aWV3LmdldEludDE2KDEsIHRydWUpOwogICAgICAgICAgICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChoZWFkZXJCeXRlID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgYmxvY2sub2Zmc2V0ID0gdmlldy5nZXRGbG9hdDMyKDEsIHRydWUpOwogICAgICAgICAgICAgICAgICAgIHNpemUgKz0gNDsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyAiSW52YWxpZCBibG9jayBvZmZzZXQgdHlwZSI7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKGJsb2NrLmVuY29kaW5nID09PSAxKSB7CiAgICAgICAgICAgICAgICAgICAgaGVhZGVyQnl0ZSA9IHZpZXcuZ2V0VWludDgoc2l6ZSk7CiAgICAgICAgICAgICAgICAgICAgc2l6ZSsrOwogICAgICAgICAgICAgICAgICAgIGJsb2NrLmJpdHNQZXJQaXhlbCA9IGhlYWRlckJ5dGUgJiA2MzsKICAgICAgICAgICAgICAgICAgICBoZWFkZXJCeXRlID4+PSA2OwogICAgICAgICAgICAgICAgICAgIGJsb2NrLm51bVZhbGlkUGl4ZWxzVHlwZSA9IGhlYWRlckJ5dGU7CiAgICAgICAgICAgICAgICAgICAgaWYgKGhlYWRlckJ5dGUgPT09IDIpIHsKICAgICAgICAgICAgICAgICAgICAgIGJsb2NrLm51bVZhbGlkUGl4ZWxzID0gdmlldy5nZXRVaW50OChzaXplKTsKICAgICAgICAgICAgICAgICAgICAgIHNpemUrKzsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGhlYWRlckJ5dGUgPT09IDEpIHsKICAgICAgICAgICAgICAgICAgICAgIGJsb2NrLm51bVZhbGlkUGl4ZWxzID0gdmlldy5nZXRVaW50MTYoc2l6ZSwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChoZWFkZXJCeXRlID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICBibG9jay5udW1WYWxpZFBpeGVscyA9IHZpZXcuZ2V0VWludDMyKHNpemUsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgc2l6ZSArPSA0OwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICB0aHJvdyAiSW52YWxpZCB2YWxpZCBwaXhlbCBjb3VudCB0eXBlIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZwICs9IHNpemU7CiAgICAgICAgICAgICAgICBpZiAoYmxvY2suZW5jb2RpbmcgPT09IDMpIHsKICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB2YXIgYXJyYXlCdWYsIHN0b3JlODsKICAgICAgICAgICAgICAgIGlmIChibG9jay5lbmNvZGluZyA9PT0gMCkgewogICAgICAgICAgICAgICAgICB2YXIgbnVtUGl4ZWxzID0gKGRhdGEucGl4ZWxzLm51bUJ5dGVzIC0gMSkgLyA0OwogICAgICAgICAgICAgICAgICBpZiAobnVtUGl4ZWxzICE9PSBNYXRoLmZsb29yKG51bVBpeGVscykpIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyAidW5jb21wcmVzc2VkIGJsb2NrIGhhcyBpbnZhbGlkIGxlbmd0aCI7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgYXJyYXlCdWYgPSBuZXcgQXJyYXlCdWZmZXIobnVtUGl4ZWxzICogNCk7CiAgICAgICAgICAgICAgICAgIHN0b3JlOCA9IG5ldyBVaW50OEFycmF5KGFycmF5QnVmKTsKICAgICAgICAgICAgICAgICAgc3RvcmU4LnNldChuZXcgVWludDhBcnJheShpbnB1dCwgZnAsIG51bVBpeGVscyAqIDQpKTsKICAgICAgICAgICAgICAgICAgdmFyIHJhd0RhdGEgPSBuZXcgRmxvYXQzMkFycmF5KGFycmF5QnVmKTsKICAgICAgICAgICAgICAgICAgYmxvY2sucmF3RGF0YSA9IHJhd0RhdGE7CiAgICAgICAgICAgICAgICAgIGZwICs9IG51bVBpeGVscyAqIDQ7CiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGJsb2NrLmVuY29kaW5nID09PSAxKSB7CiAgICAgICAgICAgICAgICAgIHZhciBkYXRhQnl0ZXMgPSBNYXRoLmNlaWwoYmxvY2subnVtVmFsaWRQaXhlbHMgKiBibG9jay5iaXRzUGVyUGl4ZWwgLyA4KTsKICAgICAgICAgICAgICAgICAgdmFyIGRhdGFXb3JkcyA9IE1hdGguY2VpbChkYXRhQnl0ZXMgLyA0KTsKICAgICAgICAgICAgICAgICAgYXJyYXlCdWYgPSBuZXcgQXJyYXlCdWZmZXIoZGF0YVdvcmRzICogNCk7CiAgICAgICAgICAgICAgICAgIHN0b3JlOCA9IG5ldyBVaW50OEFycmF5KGFycmF5QnVmKTsKICAgICAgICAgICAgICAgICAgc3RvcmU4LnNldChuZXcgVWludDhBcnJheShpbnB1dCwgZnAsIGRhdGFCeXRlcykpOwogICAgICAgICAgICAgICAgICBibG9jay5zdHVmZmVkRGF0YSA9IG5ldyBVaW50MzJBcnJheShhcnJheUJ1Zik7CiAgICAgICAgICAgICAgICAgIGZwICs9IGRhdGFCeXRlczsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZGF0YS5lb2ZPZmZzZXQgPSBmcDsKICAgICAgICAgICAgcmV0dXJuIGRhdGE7CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIHVuc3R1ZmYgPSBmdW5jdGlvbihzcmMsIGJpdHNQZXJQaXhlbCwgbnVtUGl4ZWxzLCBvZmZzZXQsIHNjYWxlLCBkZXN0LCBtYXhWYWx1ZSkgewogICAgICAgICAgICB2YXIgYml0TWFzayA9ICgxIDw8IGJpdHNQZXJQaXhlbCkgLSAxOwogICAgICAgICAgICB2YXIgaSA9IDAsIG87CiAgICAgICAgICAgIHZhciBiaXRzTGVmdCA9IDA7CiAgICAgICAgICAgIHZhciBuLCBidWZmZXI7CiAgICAgICAgICAgIHZhciBubWF4ID0gTWF0aC5jZWlsKChtYXhWYWx1ZSAtIG9mZnNldCkgLyBzY2FsZSk7CiAgICAgICAgICAgIHZhciBudW1JbnZhbGlkVGFpbEJ5dGVzID0gc3JjLmxlbmd0aCAqIDQgLSBNYXRoLmNlaWwoYml0c1BlclBpeGVsICogbnVtUGl4ZWxzIC8gOCk7CiAgICAgICAgICAgIHNyY1tzcmMubGVuZ3RoIC0gMV0gPDw9IDggKiBudW1JbnZhbGlkVGFpbEJ5dGVzOwogICAgICAgICAgICBmb3IgKG8gPSAwOyBvIDwgbnVtUGl4ZWxzOyBvKyspIHsKICAgICAgICAgICAgICBpZiAoYml0c0xlZnQgPT09IDApIHsKICAgICAgICAgICAgICAgIGJ1ZmZlciA9IHNyY1tpKytdOwogICAgICAgICAgICAgICAgYml0c0xlZnQgPSAzMjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKGJpdHNMZWZ0ID49IGJpdHNQZXJQaXhlbCkgewogICAgICAgICAgICAgICAgbiA9IGJ1ZmZlciA+Pj4gYml0c0xlZnQgLSBiaXRzUGVyUGl4ZWwgJiBiaXRNYXNrOwogICAgICAgICAgICAgICAgYml0c0xlZnQgLT0gYml0c1BlclBpeGVsOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB2YXIgbWlzc2luZ0JpdHMgPSBiaXRzUGVyUGl4ZWwgLSBiaXRzTGVmdDsKICAgICAgICAgICAgICAgIG4gPSAoYnVmZmVyICYgYml0TWFzaykgPDwgbWlzc2luZ0JpdHMgJiBiaXRNYXNrOwogICAgICAgICAgICAgICAgYnVmZmVyID0gc3JjW2krK107CiAgICAgICAgICAgICAgICBiaXRzTGVmdCA9IDMyIC0gbWlzc2luZ0JpdHM7CiAgICAgICAgICAgICAgICBuICs9IGJ1ZmZlciA+Pj4gYml0c0xlZnQ7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGRlc3Rbb10gPSBuIDwgbm1heCA/IG9mZnNldCArIG4gKiBzY2FsZSA6IG1heFZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBkZXN0OwogICAgICAgICAgfTsKICAgICAgICAgIHJldHVybiBDbnRaSW1hZ2U7CiAgICAgICAgfSkoKTsKICAgICAgICB2YXIgTGVyYzJEZWNvZGUgPSAoZnVuY3Rpb24oKSB7CiAgICAgICAgICAidXNlIHN0cmljdCI7CiAgICAgICAgICB2YXIgQml0U3R1ZmZlciA9IHsKICAgICAgICAgICAgLy9tZXRob2RzIGVuZGluZyB3aXRoIDIgYXJlIGZvciB0aGUgbmV3IGJ5dGUgb3JkZXIgdXNlZCBieSBMZXJjMi4zIGFuZCBhYm92ZS4KICAgICAgICAgICAgLy9vcmlnaW5hbFVuc3R1ZmYgaXMgdXNlZCB0byB1bnBhY2sgSHVmZm1hbiBjb2RlIHRhYmxlLiBjb2RlIGlzIGR1cGxpY2F0ZWQgdG8gdW5zdHVmZnggZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnMuCiAgICAgICAgICAgIHVuc3R1ZmY6IGZ1bmN0aW9uKHNyYywgZGVzdCwgYml0c1BlclBpeGVsLCBudW1QaXhlbHMsIGx1dEFyciwgb2Zmc2V0LCBzY2FsZSwgbWF4VmFsdWUpIHsKICAgICAgICAgICAgICB2YXIgYml0TWFzayA9ICgxIDw8IGJpdHNQZXJQaXhlbCkgLSAxOwogICAgICAgICAgICAgIHZhciBpID0gMCwgbzsKICAgICAgICAgICAgICB2YXIgYml0c0xlZnQgPSAwOwogICAgICAgICAgICAgIHZhciBuLCBidWZmZXIsIG1pc3NpbmdCaXRzLCBubWF4OwogICAgICAgICAgICAgIHZhciBudW1JbnZhbGlkVGFpbEJ5dGVzID0gc3JjLmxlbmd0aCAqIDQgLSBNYXRoLmNlaWwoYml0c1BlclBpeGVsICogbnVtUGl4ZWxzIC8gOCk7CiAgICAgICAgICAgICAgc3JjW3NyYy5sZW5ndGggLSAxXSA8PD0gOCAqIG51bUludmFsaWRUYWlsQnl0ZXM7CiAgICAgICAgICAgICAgaWYgKGx1dEFycikgewogICAgICAgICAgICAgICAgZm9yIChvID0gMDsgbyA8IG51bVBpeGVsczsgbysrKSB7CiAgICAgICAgICAgICAgICAgIGlmIChiaXRzTGVmdCA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgIGJ1ZmZlciA9IHNyY1tpKytdOwogICAgICAgICAgICAgICAgICAgIGJpdHNMZWZ0ID0gMzI7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKGJpdHNMZWZ0ID49IGJpdHNQZXJQaXhlbCkgewogICAgICAgICAgICAgICAgICAgIG4gPSBidWZmZXIgPj4+IGJpdHNMZWZ0IC0gYml0c1BlclBpeGVsICYgYml0TWFzazsKICAgICAgICAgICAgICAgICAgICBiaXRzTGVmdCAtPSBiaXRzUGVyUGl4ZWw7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgbWlzc2luZ0JpdHMgPSBiaXRzUGVyUGl4ZWwgLSBiaXRzTGVmdDsKICAgICAgICAgICAgICAgICAgICBuID0gKGJ1ZmZlciAmIGJpdE1hc2spIDw8IG1pc3NpbmdCaXRzICYgYml0TWFzazsKICAgICAgICAgICAgICAgICAgICBidWZmZXIgPSBzcmNbaSsrXTsKICAgICAgICAgICAgICAgICAgICBiaXRzTGVmdCA9IDMyIC0gbWlzc2luZ0JpdHM7CiAgICAgICAgICAgICAgICAgICAgbiArPSBidWZmZXIgPj4+IGJpdHNMZWZ0OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGRlc3Rbb10gPSBsdXRBcnJbbl07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIG5tYXggPSBNYXRoLmNlaWwoKG1heFZhbHVlIC0gb2Zmc2V0KSAvIHNjYWxlKTsKICAgICAgICAgICAgICAgIGZvciAobyA9IDA7IG8gPCBudW1QaXhlbHM7IG8rKykgewogICAgICAgICAgICAgICAgICBpZiAoYml0c0xlZnQgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICBidWZmZXIgPSBzcmNbaSsrXTsKICAgICAgICAgICAgICAgICAgICBiaXRzTGVmdCA9IDMyOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChiaXRzTGVmdCA+PSBiaXRzUGVyUGl4ZWwpIHsKICAgICAgICAgICAgICAgICAgICBuID0gYnVmZmVyID4+PiBiaXRzTGVmdCAtIGJpdHNQZXJQaXhlbCAmIGJpdE1hc2s7CiAgICAgICAgICAgICAgICAgICAgYml0c0xlZnQgLT0gYml0c1BlclBpeGVsOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIG1pc3NpbmdCaXRzID0gYml0c1BlclBpeGVsIC0gYml0c0xlZnQ7CiAgICAgICAgICAgICAgICAgICAgbiA9IChidWZmZXIgJiBiaXRNYXNrKSA8PCBtaXNzaW5nQml0cyAmIGJpdE1hc2s7CiAgICAgICAgICAgICAgICAgICAgYnVmZmVyID0gc3JjW2krK107CiAgICAgICAgICAgICAgICAgICAgYml0c0xlZnQgPSAzMiAtIG1pc3NpbmdCaXRzOwogICAgICAgICAgICAgICAgICAgIG4gKz0gYnVmZmVyID4+PiBiaXRzTGVmdDsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBkZXN0W29dID0gbiA8IG5tYXggPyBvZmZzZXQgKyBuICogc2NhbGUgOiBtYXhWYWx1ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHVuc3R1ZmZMVVQ6IGZ1bmN0aW9uKHNyYywgYml0c1BlclBpeGVsLCBudW1QaXhlbHMsIG9mZnNldCwgc2NhbGUsIG1heFZhbHVlKSB7CiAgICAgICAgICAgICAgdmFyIGJpdE1hc2sgPSAoMSA8PCBiaXRzUGVyUGl4ZWwpIC0gMTsKICAgICAgICAgICAgICB2YXIgaSA9IDAsIG8gPSAwLCBtaXNzaW5nQml0cyA9IDAsIGJpdHNMZWZ0ID0gMCwgbiA9IDA7CiAgICAgICAgICAgICAgdmFyIGJ1ZmZlcjsKICAgICAgICAgICAgICB2YXIgZGVzdCA9IFtdOwogICAgICAgICAgICAgIHZhciBudW1JbnZhbGlkVGFpbEJ5dGVzID0gc3JjLmxlbmd0aCAqIDQgLSBNYXRoLmNlaWwoYml0c1BlclBpeGVsICogbnVtUGl4ZWxzIC8gOCk7CiAgICAgICAgICAgICAgc3JjW3NyYy5sZW5ndGggLSAxXSA8PD0gOCAqIG51bUludmFsaWRUYWlsQnl0ZXM7CiAgICAgICAgICAgICAgdmFyIG5tYXggPSBNYXRoLmNlaWwoKG1heFZhbHVlIC0gb2Zmc2V0KSAvIHNjYWxlKTsKICAgICAgICAgICAgICBmb3IgKG8gPSAwOyBvIDwgbnVtUGl4ZWxzOyBvKyspIHsKICAgICAgICAgICAgICAgIGlmIChiaXRzTGVmdCA9PT0gMCkgewogICAgICAgICAgICAgICAgICBidWZmZXIgPSBzcmNbaSsrXTsKICAgICAgICAgICAgICAgICAgYml0c0xlZnQgPSAzMjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChiaXRzTGVmdCA+PSBiaXRzUGVyUGl4ZWwpIHsKICAgICAgICAgICAgICAgICAgbiA9IGJ1ZmZlciA+Pj4gYml0c0xlZnQgLSBiaXRzUGVyUGl4ZWwgJiBiaXRNYXNrOwogICAgICAgICAgICAgICAgICBiaXRzTGVmdCAtPSBiaXRzUGVyUGl4ZWw7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBtaXNzaW5nQml0cyA9IGJpdHNQZXJQaXhlbCAtIGJpdHNMZWZ0OwogICAgICAgICAgICAgICAgICBuID0gKGJ1ZmZlciAmIGJpdE1hc2spIDw8IG1pc3NpbmdCaXRzICYgYml0TWFzazsKICAgICAgICAgICAgICAgICAgYnVmZmVyID0gc3JjW2krK107CiAgICAgICAgICAgICAgICAgIGJpdHNMZWZ0ID0gMzIgLSBtaXNzaW5nQml0czsKICAgICAgICAgICAgICAgICAgbiArPSBidWZmZXIgPj4+IGJpdHNMZWZ0OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZGVzdFtvXSA9IG4gPCBubWF4ID8gb2Zmc2V0ICsgbiAqIHNjYWxlIDogbWF4VmFsdWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGRlc3QudW5zaGlmdChvZmZzZXQpOwogICAgICAgICAgICAgIHJldHVybiBkZXN0OwogICAgICAgICAgICB9LAogICAgICAgICAgICB1bnN0dWZmMjogZnVuY3Rpb24oc3JjLCBkZXN0LCBiaXRzUGVyUGl4ZWwsIG51bVBpeGVscywgbHV0QXJyLCBvZmZzZXQsIHNjYWxlLCBtYXhWYWx1ZSkgewogICAgICAgICAgICAgIHZhciBiaXRNYXNrID0gKDEgPDwgYml0c1BlclBpeGVsKSAtIDE7CiAgICAgICAgICAgICAgdmFyIGkgPSAwLCBvOwogICAgICAgICAgICAgIHZhciBiaXRzTGVmdCA9IDAsIGJpdFBvcyA9IDA7CiAgICAgICAgICAgICAgdmFyIG4sIGJ1ZmZlciwgbWlzc2luZ0JpdHM7CiAgICAgICAgICAgICAgaWYgKGx1dEFycikgewogICAgICAgICAgICAgICAgZm9yIChvID0gMDsgbyA8IG51bVBpeGVsczsgbysrKSB7CiAgICAgICAgICAgICAgICAgIGlmIChiaXRzTGVmdCA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgIGJ1ZmZlciA9IHNyY1tpKytdOwogICAgICAgICAgICAgICAgICAgIGJpdHNMZWZ0ID0gMzI7CiAgICAgICAgICAgICAgICAgICAgYml0UG9zID0gMDsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAoYml0c0xlZnQgPj0gYml0c1BlclBpeGVsKSB7CiAgICAgICAgICAgICAgICAgICAgbiA9IGJ1ZmZlciA+Pj4gYml0UG9zICYgYml0TWFzazsKICAgICAgICAgICAgICAgICAgICBiaXRzTGVmdCAtPSBiaXRzUGVyUGl4ZWw7CiAgICAgICAgICAgICAgICAgICAgYml0UG9zICs9IGJpdHNQZXJQaXhlbDsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBtaXNzaW5nQml0cyA9IGJpdHNQZXJQaXhlbCAtIGJpdHNMZWZ0OwogICAgICAgICAgICAgICAgICAgIG4gPSBidWZmZXIgPj4+IGJpdFBvcyAmIGJpdE1hc2s7CiAgICAgICAgICAgICAgICAgICAgYnVmZmVyID0gc3JjW2krK107CiAgICAgICAgICAgICAgICAgICAgYml0c0xlZnQgPSAzMiAtIG1pc3NpbmdCaXRzOwogICAgICAgICAgICAgICAgICAgIG4gfD0gKGJ1ZmZlciAmICgxIDw8IG1pc3NpbmdCaXRzKSAtIDEpIDw8IGJpdHNQZXJQaXhlbCAtIG1pc3NpbmdCaXRzOwogICAgICAgICAgICAgICAgICAgIGJpdFBvcyA9IG1pc3NpbmdCaXRzOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGRlc3Rbb10gPSBsdXRBcnJbbl07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHZhciBubWF4ID0gTWF0aC5jZWlsKChtYXhWYWx1ZSAtIG9mZnNldCkgLyBzY2FsZSk7CiAgICAgICAgICAgICAgICBmb3IgKG8gPSAwOyBvIDwgbnVtUGl4ZWxzOyBvKyspIHsKICAgICAgICAgICAgICAgICAgaWYgKGJpdHNMZWZ0ID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgYnVmZmVyID0gc3JjW2krK107CiAgICAgICAgICAgICAgICAgICAgYml0c0xlZnQgPSAzMjsKICAgICAgICAgICAgICAgICAgICBiaXRQb3MgPSAwOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChiaXRzTGVmdCA+PSBiaXRzUGVyUGl4ZWwpIHsKICAgICAgICAgICAgICAgICAgICBuID0gYnVmZmVyID4+PiBiaXRQb3MgJiBiaXRNYXNrOwogICAgICAgICAgICAgICAgICAgIGJpdHNMZWZ0IC09IGJpdHNQZXJQaXhlbDsKICAgICAgICAgICAgICAgICAgICBiaXRQb3MgKz0gYml0c1BlclBpeGVsOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIG1pc3NpbmdCaXRzID0gYml0c1BlclBpeGVsIC0gYml0c0xlZnQ7CiAgICAgICAgICAgICAgICAgICAgbiA9IGJ1ZmZlciA+Pj4gYml0UG9zICYgYml0TWFzazsKICAgICAgICAgICAgICAgICAgICBidWZmZXIgPSBzcmNbaSsrXTsKICAgICAgICAgICAgICAgICAgICBiaXRzTGVmdCA9IDMyIC0gbWlzc2luZ0JpdHM7CiAgICAgICAgICAgICAgICAgICAgbiB8PSAoYnVmZmVyICYgKDEgPDwgbWlzc2luZ0JpdHMpIC0gMSkgPDwgYml0c1BlclBpeGVsIC0gbWlzc2luZ0JpdHM7CiAgICAgICAgICAgICAgICAgICAgYml0UG9zID0gbWlzc2luZ0JpdHM7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgZGVzdFtvXSA9IG4gPCBubWF4ID8gb2Zmc2V0ICsgbiAqIHNjYWxlIDogbWF4VmFsdWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiBkZXN0OwogICAgICAgICAgICB9LAogICAgICAgICAgICB1bnN0dWZmTFVUMjogZnVuY3Rpb24oc3JjLCBiaXRzUGVyUGl4ZWwsIG51bVBpeGVscywgb2Zmc2V0LCBzY2FsZSwgbWF4VmFsdWUpIHsKICAgICAgICAgICAgICB2YXIgYml0TWFzayA9ICgxIDw8IGJpdHNQZXJQaXhlbCkgLSAxOwogICAgICAgICAgICAgIHZhciBpID0gMCwgbyA9IDAsIG1pc3NpbmdCaXRzID0gMCwgYml0c0xlZnQgPSAwLCBuID0gMCwgYml0UG9zID0gMDsKICAgICAgICAgICAgICB2YXIgYnVmZmVyOwogICAgICAgICAgICAgIHZhciBkZXN0ID0gW107CiAgICAgICAgICAgICAgdmFyIG5tYXggPSBNYXRoLmNlaWwoKG1heFZhbHVlIC0gb2Zmc2V0KSAvIHNjYWxlKTsKICAgICAgICAgICAgICBmb3IgKG8gPSAwOyBvIDwgbnVtUGl4ZWxzOyBvKyspIHsKICAgICAgICAgICAgICAgIGlmIChiaXRzTGVmdCA9PT0gMCkgewogICAgICAgICAgICAgICAgICBidWZmZXIgPSBzcmNbaSsrXTsKICAgICAgICAgICAgICAgICAgYml0c0xlZnQgPSAzMjsKICAgICAgICAgICAgICAgICAgYml0UG9zID0gMDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChiaXRzTGVmdCA+PSBiaXRzUGVyUGl4ZWwpIHsKICAgICAgICAgICAgICAgICAgbiA9IGJ1ZmZlciA+Pj4gYml0UG9zICYgYml0TWFzazsKICAgICAgICAgICAgICAgICAgYml0c0xlZnQgLT0gYml0c1BlclBpeGVsOwogICAgICAgICAgICAgICAgICBiaXRQb3MgKz0gYml0c1BlclBpeGVsOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgbWlzc2luZ0JpdHMgPSBiaXRzUGVyUGl4ZWwgLSBiaXRzTGVmdDsKICAgICAgICAgICAgICAgICAgbiA9IGJ1ZmZlciA+Pj4gYml0UG9zICYgYml0TWFzazsKICAgICAgICAgICAgICAgICAgYnVmZmVyID0gc3JjW2krK107CiAgICAgICAgICAgICAgICAgIGJpdHNMZWZ0ID0gMzIgLSBtaXNzaW5nQml0czsKICAgICAgICAgICAgICAgICAgbiB8PSAoYnVmZmVyICYgKDEgPDwgbWlzc2luZ0JpdHMpIC0gMSkgPDwgYml0c1BlclBpeGVsIC0gbWlzc2luZ0JpdHM7CiAgICAgICAgICAgICAgICAgIGJpdFBvcyA9IG1pc3NpbmdCaXRzOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZGVzdFtvXSA9IG4gPCBubWF4ID8gb2Zmc2V0ICsgbiAqIHNjYWxlIDogbWF4VmFsdWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGRlc3QudW5zaGlmdChvZmZzZXQpOwogICAgICAgICAgICAgIHJldHVybiBkZXN0OwogICAgICAgICAgICB9LAogICAgICAgICAgICBvcmlnaW5hbFVuc3R1ZmY6IGZ1bmN0aW9uKHNyYywgZGVzdCwgYml0c1BlclBpeGVsLCBudW1QaXhlbHMpIHsKICAgICAgICAgICAgICB2YXIgYml0TWFzayA9ICgxIDw8IGJpdHNQZXJQaXhlbCkgLSAxOwogICAgICAgICAgICAgIHZhciBpID0gMCwgbzsKICAgICAgICAgICAgICB2YXIgYml0c0xlZnQgPSAwOwogICAgICAgICAgICAgIHZhciBuLCBidWZmZXIsIG1pc3NpbmdCaXRzOwogICAgICAgICAgICAgIHZhciBudW1JbnZhbGlkVGFpbEJ5dGVzID0gc3JjLmxlbmd0aCAqIDQgLSBNYXRoLmNlaWwoYml0c1BlclBpeGVsICogbnVtUGl4ZWxzIC8gOCk7CiAgICAgICAgICAgICAgc3JjW3NyYy5sZW5ndGggLSAxXSA8PD0gOCAqIG51bUludmFsaWRUYWlsQnl0ZXM7CiAgICAgICAgICAgICAgZm9yIChvID0gMDsgbyA8IG51bVBpeGVsczsgbysrKSB7CiAgICAgICAgICAgICAgICBpZiAoYml0c0xlZnQgPT09IDApIHsKICAgICAgICAgICAgICAgICAgYnVmZmVyID0gc3JjW2krK107CiAgICAgICAgICAgICAgICAgIGJpdHNMZWZ0ID0gMzI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoYml0c0xlZnQgPj0gYml0c1BlclBpeGVsKSB7CiAgICAgICAgICAgICAgICAgIG4gPSBidWZmZXIgPj4+IGJpdHNMZWZ0IC0gYml0c1BlclBpeGVsICYgYml0TWFzazsKICAgICAgICAgICAgICAgICAgYml0c0xlZnQgLT0gYml0c1BlclBpeGVsOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgbWlzc2luZ0JpdHMgPSBiaXRzUGVyUGl4ZWwgLSBiaXRzTGVmdDsKICAgICAgICAgICAgICAgICAgbiA9IChidWZmZXIgJiBiaXRNYXNrKSA8PCBtaXNzaW5nQml0cyAmIGJpdE1hc2s7CiAgICAgICAgICAgICAgICAgIGJ1ZmZlciA9IHNyY1tpKytdOwogICAgICAgICAgICAgICAgICBiaXRzTGVmdCA9IDMyIC0gbWlzc2luZ0JpdHM7CiAgICAgICAgICAgICAgICAgIG4gKz0gYnVmZmVyID4+PiBiaXRzTGVmdDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGRlc3Rbb10gPSBuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gZGVzdDsKICAgICAgICAgICAgfSwKICAgICAgICAgICAgb3JpZ2luYWxVbnN0dWZmMjogZnVuY3Rpb24oc3JjLCBkZXN0LCBiaXRzUGVyUGl4ZWwsIG51bVBpeGVscykgewogICAgICAgICAgICAgIHZhciBiaXRNYXNrID0gKDEgPDwgYml0c1BlclBpeGVsKSAtIDE7CiAgICAgICAgICAgICAgdmFyIGkgPSAwLCBvOwogICAgICAgICAgICAgIHZhciBiaXRzTGVmdCA9IDAsIGJpdFBvcyA9IDA7CiAgICAgICAgICAgICAgdmFyIG4sIGJ1ZmZlciwgbWlzc2luZ0JpdHM7CiAgICAgICAgICAgICAgZm9yIChvID0gMDsgbyA8IG51bVBpeGVsczsgbysrKSB7CiAgICAgICAgICAgICAgICBpZiAoYml0c0xlZnQgPT09IDApIHsKICAgICAgICAgICAgICAgICAgYnVmZmVyID0gc3JjW2krK107CiAgICAgICAgICAgICAgICAgIGJpdHNMZWZ0ID0gMzI7CiAgICAgICAgICAgICAgICAgIGJpdFBvcyA9IDA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoYml0c0xlZnQgPj0gYml0c1BlclBpeGVsKSB7CiAgICAgICAgICAgICAgICAgIG4gPSBidWZmZXIgPj4+IGJpdFBvcyAmIGJpdE1hc2s7CiAgICAgICAgICAgICAgICAgIGJpdHNMZWZ0IC09IGJpdHNQZXJQaXhlbDsKICAgICAgICAgICAgICAgICAgYml0UG9zICs9IGJpdHNQZXJQaXhlbDsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIG1pc3NpbmdCaXRzID0gYml0c1BlclBpeGVsIC0gYml0c0xlZnQ7CiAgICAgICAgICAgICAgICAgIG4gPSBidWZmZXIgPj4+IGJpdFBvcyAmIGJpdE1hc2s7CiAgICAgICAgICAgICAgICAgIGJ1ZmZlciA9IHNyY1tpKytdOwogICAgICAgICAgICAgICAgICBiaXRzTGVmdCA9IDMyIC0gbWlzc2luZ0JpdHM7CiAgICAgICAgICAgICAgICAgIG4gfD0gKGJ1ZmZlciAmICgxIDw8IG1pc3NpbmdCaXRzKSAtIDEpIDw8IGJpdHNQZXJQaXhlbCAtIG1pc3NpbmdCaXRzOwogICAgICAgICAgICAgICAgICBiaXRQb3MgPSBtaXNzaW5nQml0czsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGRlc3Rbb10gPSBuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gZGVzdDsKICAgICAgICAgICAgfQogICAgICAgICAgfTsKICAgICAgICAgIHZhciBMZXJjMkhlbHBlcnMgPSB7CiAgICAgICAgICAgIEhVRkZNQU5fTFVUX0JJVFNfTUFYOiAxMiwKICAgICAgICAgICAgLy91c2UgMl4xMiBsdXQsIHRyZWF0IGl0IGxpa2UgY29uc3RhbnQKICAgICAgICAgICAgY29tcHV0ZUNoZWNrc3VtRmxldGNoZXIzMjogZnVuY3Rpb24oaW5wdXQpIHsKICAgICAgICAgICAgICB2YXIgc3VtMSA9IDY1NTM1LCBzdW0yID0gNjU1MzU7CiAgICAgICAgICAgICAgdmFyIGxlbiA9IGlucHV0Lmxlbmd0aDsKICAgICAgICAgICAgICB2YXIgd29yZHMgPSBNYXRoLmZsb29yKGxlbiAvIDIpOwogICAgICAgICAgICAgIHZhciBpID0gMDsKICAgICAgICAgICAgICB3aGlsZSAod29yZHMpIHsKICAgICAgICAgICAgICAgIHZhciB0bGVuID0gd29yZHMgPj0gMzU5ID8gMzU5IDogd29yZHM7CiAgICAgICAgICAgICAgICB3b3JkcyAtPSB0bGVuOwogICAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgICBzdW0xICs9IGlucHV0W2krK10gPDwgODsKICAgICAgICAgICAgICAgICAgc3VtMiArPSBzdW0xICs9IGlucHV0W2krK107CiAgICAgICAgICAgICAgICB9IHdoaWxlICgtLXRsZW4pOwogICAgICAgICAgICAgICAgc3VtMSA9IChzdW0xICYgNjU1MzUpICsgKHN1bTEgPj4+IDE2KTsKICAgICAgICAgICAgICAgIHN1bTIgPSAoc3VtMiAmIDY1NTM1KSArIChzdW0yID4+PiAxNik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChsZW4gJiAxKSB7CiAgICAgICAgICAgICAgICBzdW0yICs9IHN1bTEgKz0gaW5wdXRbaV0gPDwgODsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgc3VtMSA9IChzdW0xICYgNjU1MzUpICsgKHN1bTEgPj4+IDE2KTsKICAgICAgICAgICAgICBzdW0yID0gKHN1bTIgJiA2NTUzNSkgKyAoc3VtMiA+Pj4gMTYpOwogICAgICAgICAgICAgIHJldHVybiAoc3VtMiA8PCAxNiB8IHN1bTEpID4+PiAwOwogICAgICAgICAgICB9LAogICAgICAgICAgICByZWFkSGVhZGVySW5mbzogZnVuY3Rpb24oaW5wdXQsIGRhdGEpIHsKICAgICAgICAgICAgICB2YXIgcHRyID0gZGF0YS5wdHI7CiAgICAgICAgICAgICAgdmFyIGZpbGVJZFZpZXcgPSBuZXcgVWludDhBcnJheShpbnB1dCwgcHRyLCA2KTsKICAgICAgICAgICAgICB2YXIgaGVhZGVySW5mbyA9IHt9OwogICAgICAgICAgICAgIGhlYWRlckluZm8uZmlsZUlkZW50aWZpZXJTdHJpbmcgPSBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIGZpbGVJZFZpZXcpOwogICAgICAgICAgICAgIGlmIChoZWFkZXJJbmZvLmZpbGVJZGVudGlmaWVyU3RyaW5nLmxhc3RJbmRleE9mKCJMZXJjMiIsIDApICE9PSAwKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAiVW5leHBlY3RlZCBmaWxlIGlkZW50aWZpZXIgc3RyaW5nIChleHBlY3QgTGVyYzIgKTogIiArIGhlYWRlckluZm8uZmlsZUlkZW50aWZpZXJTdHJpbmc7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHB0ciArPSA2OwogICAgICAgICAgICAgIHZhciB2aWV3ID0gbmV3IERhdGFWaWV3KGlucHV0LCBwdHIsIDgpOwogICAgICAgICAgICAgIHZhciBmaWxlVmVyc2lvbiA9IHZpZXcuZ2V0SW50MzIoMCwgdHJ1ZSk7CiAgICAgICAgICAgICAgaGVhZGVySW5mby5maWxlVmVyc2lvbiA9IGZpbGVWZXJzaW9uOwogICAgICAgICAgICAgIHB0ciArPSA0OwogICAgICAgICAgICAgIGlmIChmaWxlVmVyc2lvbiA+PSAzKSB7CiAgICAgICAgICAgICAgICBoZWFkZXJJbmZvLmNoZWNrc3VtID0gdmlldy5nZXRVaW50MzIoNCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICBwdHIgKz0gNDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmlldyA9IG5ldyBEYXRhVmlldyhpbnB1dCwgcHRyLCAxMik7CiAgICAgICAgICAgICAgaGVhZGVySW5mby5oZWlnaHQgPSB2aWV3LmdldFVpbnQzMigwLCB0cnVlKTsKICAgICAgICAgICAgICBoZWFkZXJJbmZvLndpZHRoID0gdmlldy5nZXRVaW50MzIoNCwgdHJ1ZSk7CiAgICAgICAgICAgICAgcHRyICs9IDg7CiAgICAgICAgICAgICAgaWYgKGZpbGVWZXJzaW9uID49IDQpIHsKICAgICAgICAgICAgICAgIGhlYWRlckluZm8ubnVtRGltcyA9IHZpZXcuZ2V0VWludDMyKDgsIHRydWUpOwogICAgICAgICAgICAgICAgcHRyICs9IDQ7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGhlYWRlckluZm8ubnVtRGltcyA9IDE7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHZpZXcgPSBuZXcgRGF0YVZpZXcoaW5wdXQsIHB0ciwgNDApOwogICAgICAgICAgICAgIGhlYWRlckluZm8ubnVtVmFsaWRQaXhlbCA9IHZpZXcuZ2V0VWludDMyKDAsIHRydWUpOwogICAgICAgICAgICAgIGhlYWRlckluZm8ubWljcm9CbG9ja1NpemUgPSB2aWV3LmdldEludDMyKDQsIHRydWUpOwogICAgICAgICAgICAgIGhlYWRlckluZm8uYmxvYlNpemUgPSB2aWV3LmdldEludDMyKDgsIHRydWUpOwogICAgICAgICAgICAgIGhlYWRlckluZm8uaW1hZ2VUeXBlID0gdmlldy5nZXRJbnQzMigxMiwgdHJ1ZSk7CiAgICAgICAgICAgICAgaGVhZGVySW5mby5tYXhaRXJyb3IgPSB2aWV3LmdldEZsb2F0NjQoMTYsIHRydWUpOwogICAgICAgICAgICAgIGhlYWRlckluZm8uek1pbiA9IHZpZXcuZ2V0RmxvYXQ2NCgyNCwgdHJ1ZSk7CiAgICAgICAgICAgICAgaGVhZGVySW5mby56TWF4ID0gdmlldy5nZXRGbG9hdDY0KDMyLCB0cnVlKTsKICAgICAgICAgICAgICBwdHIgKz0gNDA7CiAgICAgICAgICAgICAgZGF0YS5oZWFkZXJJbmZvID0gaGVhZGVySW5mbzsKICAgICAgICAgICAgICBkYXRhLnB0ciA9IHB0cjsKICAgICAgICAgICAgICB2YXIgY2hlY2tzdW0sIGtleUxlbmd0aDsKICAgICAgICAgICAgICBpZiAoZmlsZVZlcnNpb24gPj0gMykgewogICAgICAgICAgICAgICAga2V5TGVuZ3RoID0gZmlsZVZlcnNpb24gPj0gNCA/IDUyIDogNDg7CiAgICAgICAgICAgICAgICBjaGVja3N1bSA9IHRoaXMuY29tcHV0ZUNoZWNrc3VtRmxldGNoZXIzMihuZXcgVWludDhBcnJheShpbnB1dCwgcHRyIC0ga2V5TGVuZ3RoLCBoZWFkZXJJbmZvLmJsb2JTaXplIC0gMTQpKTsKICAgICAgICAgICAgICAgIGlmIChjaGVja3N1bSAhPT0gaGVhZGVySW5mby5jaGVja3N1bSkgewogICAgICAgICAgICAgICAgICB0aHJvdyAiQ2hlY2tzdW0gZmFpbGVkLiI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9LAogICAgICAgICAgICBjaGVja01pbk1heFJhbmdlczogZnVuY3Rpb24oaW5wdXQsIGRhdGEpIHsKICAgICAgICAgICAgICB2YXIgaGVhZGVySW5mbyA9IGRhdGEuaGVhZGVySW5mbzsKICAgICAgICAgICAgICB2YXIgT3V0UGl4ZWxUeXBlQXJyYXkgPSB0aGlzLmdldERhdGFUeXBlQXJyYXkoaGVhZGVySW5mby5pbWFnZVR5cGUpOwogICAgICAgICAgICAgIHZhciByYW5nZUJ5dGVzID0gaGVhZGVySW5mby5udW1EaW1zICogdGhpcy5nZXREYXRhVHlwZVNpemUoaGVhZGVySW5mby5pbWFnZVR5cGUpOwogICAgICAgICAgICAgIHZhciBtaW5WYWx1ZXMgPSB0aGlzLnJlYWRTdWJBcnJheShpbnB1dCwgZGF0YS5wdHIsIE91dFBpeGVsVHlwZUFycmF5LCByYW5nZUJ5dGVzKTsKICAgICAgICAgICAgICB2YXIgbWF4VmFsdWVzID0gdGhpcy5yZWFkU3ViQXJyYXkoaW5wdXQsIGRhdGEucHRyICsgcmFuZ2VCeXRlcywgT3V0UGl4ZWxUeXBlQXJyYXksIHJhbmdlQnl0ZXMpOwogICAgICAgICAgICAgIGRhdGEucHRyICs9IDIgKiByYW5nZUJ5dGVzOwogICAgICAgICAgICAgIHZhciBpLCBlcXVhbCA9IHRydWU7CiAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGhlYWRlckluZm8ubnVtRGltczsgaSsrKSB7CiAgICAgICAgICAgICAgICBpZiAobWluVmFsdWVzW2ldICE9PSBtYXhWYWx1ZXNbaV0pIHsKICAgICAgICAgICAgICAgICAgZXF1YWwgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGhlYWRlckluZm8ubWluVmFsdWVzID0gbWluVmFsdWVzOwogICAgICAgICAgICAgIGhlYWRlckluZm8ubWF4VmFsdWVzID0gbWF4VmFsdWVzOwogICAgICAgICAgICAgIHJldHVybiBlcXVhbDsKICAgICAgICAgICAgfSwKICAgICAgICAgICAgcmVhZFN1YkFycmF5OiBmdW5jdGlvbihpbnB1dCwgcHRyLCBPdXRQaXhlbFR5cGVBcnJheSwgbnVtQnl0ZXMpIHsKICAgICAgICAgICAgICB2YXIgcmF3RGF0YTsKICAgICAgICAgICAgICBpZiAoT3V0UGl4ZWxUeXBlQXJyYXkgPT09IFVpbnQ4QXJyYXkpIHsKICAgICAgICAgICAgICAgIHJhd0RhdGEgPSBuZXcgVWludDhBcnJheShpbnB1dCwgcHRyLCBudW1CeXRlcyk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHZhciBhcnJheUJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcihudW1CeXRlcyk7CiAgICAgICAgICAgICAgICB2YXIgc3RvcmU4ID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWYpOwogICAgICAgICAgICAgICAgc3RvcmU4LnNldChuZXcgVWludDhBcnJheShpbnB1dCwgcHRyLCBudW1CeXRlcykpOwogICAgICAgICAgICAgICAgcmF3RGF0YSA9IG5ldyBPdXRQaXhlbFR5cGVBcnJheShhcnJheUJ1Zik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiByYXdEYXRhOwogICAgICAgICAgICB9LAogICAgICAgICAgICByZWFkTWFzazogZnVuY3Rpb24oaW5wdXQsIGRhdGEpIHsKICAgICAgICAgICAgICB2YXIgcHRyID0gZGF0YS5wdHI7CiAgICAgICAgICAgICAgdmFyIGhlYWRlckluZm8gPSBkYXRhLmhlYWRlckluZm87CiAgICAgICAgICAgICAgdmFyIG51bVBpeGVscyA9IGhlYWRlckluZm8ud2lkdGggKiBoZWFkZXJJbmZvLmhlaWdodDsKICAgICAgICAgICAgICB2YXIgbnVtVmFsaWRQaXhlbCA9IGhlYWRlckluZm8ubnVtVmFsaWRQaXhlbDsKICAgICAgICAgICAgICB2YXIgdmlldyA9IG5ldyBEYXRhVmlldyhpbnB1dCwgcHRyLCA0KTsKICAgICAgICAgICAgICB2YXIgbWFzayA9IHt9OwogICAgICAgICAgICAgIG1hc2subnVtQnl0ZXMgPSB2aWV3LmdldFVpbnQzMigwLCB0cnVlKTsKICAgICAgICAgICAgICBwdHIgKz0gNDsKICAgICAgICAgICAgICBpZiAoKDAgPT09IG51bVZhbGlkUGl4ZWwgfHwgbnVtUGl4ZWxzID09PSBudW1WYWxpZFBpeGVsKSAmJiAwICE9PSBtYXNrLm51bUJ5dGVzKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAiaW52YWxpZCBtYXNrIjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmFyIGJpdHNldCwgcmVzdWx0TWFzazsKICAgICAgICAgICAgICBpZiAobnVtVmFsaWRQaXhlbCA9PT0gMCkgewogICAgICAgICAgICAgICAgYml0c2V0ID0gbmV3IFVpbnQ4QXJyYXkoTWF0aC5jZWlsKG51bVBpeGVscyAvIDgpKTsKICAgICAgICAgICAgICAgIG1hc2suYml0c2V0ID0gYml0c2V0OwogICAgICAgICAgICAgICAgcmVzdWx0TWFzayA9IG5ldyBVaW50OEFycmF5KG51bVBpeGVscyk7CiAgICAgICAgICAgICAgICBkYXRhLnBpeGVscy5yZXN1bHRNYXNrID0gcmVzdWx0TWFzazsKICAgICAgICAgICAgICAgIHB0ciArPSBtYXNrLm51bUJ5dGVzOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAobWFzay5udW1CeXRlcyA+IDApIHsKICAgICAgICAgICAgICAgIGJpdHNldCA9IG5ldyBVaW50OEFycmF5KE1hdGguY2VpbChudW1QaXhlbHMgLyA4KSk7CiAgICAgICAgICAgICAgICB2aWV3ID0gbmV3IERhdGFWaWV3KGlucHV0LCBwdHIsIG1hc2subnVtQnl0ZXMpOwogICAgICAgICAgICAgICAgdmFyIGNudCA9IHZpZXcuZ2V0SW50MTYoMCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICB2YXIgaXAgPSAyLCBvcCA9IDAsIHZhbCA9IDA7CiAgICAgICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgICAgIGlmIChjbnQgPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGNudC0tKSB7CiAgICAgICAgICAgICAgICAgICAgICBiaXRzZXRbb3ArK10gPSB2aWV3LmdldFVpbnQ4KGlwKyspOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB2YWwgPSB2aWV3LmdldFVpbnQ4KGlwKyspOwogICAgICAgICAgICAgICAgICAgIGNudCA9IC1jbnQ7CiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGNudC0tKSB7CiAgICAgICAgICAgICAgICAgICAgICBiaXRzZXRbb3ArK10gPSB2YWw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGNudCA9IHZpZXcuZ2V0SW50MTYoaXAsIHRydWUpOwogICAgICAgICAgICAgICAgICBpcCArPSAyOwogICAgICAgICAgICAgICAgfSB3aGlsZSAoaXAgPCBtYXNrLm51bUJ5dGVzKTsKICAgICAgICAgICAgICAgIGlmIChjbnQgIT09IC0zMjc2OCB8fCBvcCA8IGJpdHNldC5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgdGhyb3cgIlVuZXhwZWN0ZWQgZW5kIG9mIG1hc2sgUkxFIGVuY29kaW5nIjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJlc3VsdE1hc2sgPSBuZXcgVWludDhBcnJheShudW1QaXhlbHMpOwogICAgICAgICAgICAgICAgdmFyIG1iID0gMCwgayA9IDA7CiAgICAgICAgICAgICAgICBmb3IgKGsgPSAwOyBrIDwgbnVtUGl4ZWxzOyBrKyspIHsKICAgICAgICAgICAgICAgICAgaWYgKGsgJiA3KSB7CiAgICAgICAgICAgICAgICAgICAgbWIgPSBiaXRzZXRbayA+PiAzXTsKICAgICAgICAgICAgICAgICAgICBtYiA8PD0gayAmIDc7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgbWIgPSBiaXRzZXRbayA+PiAzXTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAobWIgJiAxMjgpIHsKICAgICAgICAgICAgICAgICAgICByZXN1bHRNYXNrW2tdID0gMTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZGF0YS5waXhlbHMucmVzdWx0TWFzayA9IHJlc3VsdE1hc2s7CiAgICAgICAgICAgICAgICBtYXNrLmJpdHNldCA9IGJpdHNldDsKICAgICAgICAgICAgICAgIHB0ciArPSBtYXNrLm51bUJ5dGVzOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBkYXRhLnB0ciA9IHB0cjsKICAgICAgICAgICAgICBkYXRhLm1hc2sgPSBtYXNrOwogICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9LAogICAgICAgICAgICByZWFkRGF0YU9uZVN3ZWVwOiBmdW5jdGlvbihpbnB1dCwgZGF0YSwgT3V0UGl4ZWxUeXBlQXJyYXkpIHsKICAgICAgICAgICAgICB2YXIgcHRyID0gZGF0YS5wdHI7CiAgICAgICAgICAgICAgdmFyIGhlYWRlckluZm8gPSBkYXRhLmhlYWRlckluZm87CiAgICAgICAgICAgICAgdmFyIG51bURpbXMgPSBoZWFkZXJJbmZvLm51bURpbXM7CiAgICAgICAgICAgICAgdmFyIG51bVBpeGVscyA9IGhlYWRlckluZm8ud2lkdGggKiBoZWFkZXJJbmZvLmhlaWdodDsKICAgICAgICAgICAgICB2YXIgaW1hZ2VUeXBlID0gaGVhZGVySW5mby5pbWFnZVR5cGU7CiAgICAgICAgICAgICAgdmFyIG51bUJ5dGVzID0gaGVhZGVySW5mby5udW1WYWxpZFBpeGVsICogTGVyYzJIZWxwZXJzLmdldERhdGFUeXBlU2l6ZShpbWFnZVR5cGUpICogbnVtRGltczsKICAgICAgICAgICAgICB2YXIgcmF3RGF0YTsKICAgICAgICAgICAgICB2YXIgbWFzayA9IGRhdGEucGl4ZWxzLnJlc3VsdE1hc2s7CiAgICAgICAgICAgICAgaWYgKE91dFBpeGVsVHlwZUFycmF5ID09PSBVaW50OEFycmF5KSB7CiAgICAgICAgICAgICAgICByYXdEYXRhID0gbmV3IFVpbnQ4QXJyYXkoaW5wdXQsIHB0ciwgbnVtQnl0ZXMpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB2YXIgYXJyYXlCdWYgPSBuZXcgQXJyYXlCdWZmZXIobnVtQnl0ZXMpOwogICAgICAgICAgICAgICAgdmFyIHN0b3JlOCA9IG5ldyBVaW50OEFycmF5KGFycmF5QnVmKTsKICAgICAgICAgICAgICAgIHN0b3JlOC5zZXQobmV3IFVpbnQ4QXJyYXkoaW5wdXQsIHB0ciwgbnVtQnl0ZXMpKTsKICAgICAgICAgICAgICAgIHJhd0RhdGEgPSBuZXcgT3V0UGl4ZWxUeXBlQXJyYXkoYXJyYXlCdWYpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAocmF3RGF0YS5sZW5ndGggPT09IG51bVBpeGVscyAqIG51bURpbXMpIHsKICAgICAgICAgICAgICAgIGRhdGEucGl4ZWxzLnJlc3VsdFBpeGVscyA9IHJhd0RhdGE7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGRhdGEucGl4ZWxzLnJlc3VsdFBpeGVscyA9IG5ldyBPdXRQaXhlbFR5cGVBcnJheShudW1QaXhlbHMgKiBudW1EaW1zKTsKICAgICAgICAgICAgICAgIHZhciB6ID0gMCwgayA9IDAsIGkgPSAwLCBuU3RhcnQgPSAwOwogICAgICAgICAgICAgICAgaWYgKG51bURpbXMgPiAxKSB7CiAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1EaW1zOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICBuU3RhcnQgPSBpICogbnVtUGl4ZWxzOwogICAgICAgICAgICAgICAgICAgIGZvciAoayA9IDA7IGsgPCBudW1QaXhlbHM7IGsrKykgewogICAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2tba10pIHsKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5waXhlbHMucmVzdWx0UGl4ZWxzW25TdGFydCArIGtdID0gcmF3RGF0YVt6KytdOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgZm9yIChrID0gMDsgayA8IG51bVBpeGVsczsgaysrKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2tba10pIHsKICAgICAgICAgICAgICAgICAgICAgIGRhdGEucGl4ZWxzLnJlc3VsdFBpeGVsc1trXSA9IHJhd0RhdGFbeisrXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcHRyICs9IG51bUJ5dGVzOwogICAgICAgICAgICAgIGRhdGEucHRyID0gcHRyOwogICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9LAogICAgICAgICAgICByZWFkSHVmZm1hblRyZWU6IGZ1bmN0aW9uKGlucHV0LCBkYXRhKSB7CiAgICAgICAgICAgICAgdmFyIEJJVFNfTUFYID0gdGhpcy5IVUZGTUFOX0xVVF9CSVRTX01BWDsKICAgICAgICAgICAgICB2YXIgdmlldyA9IG5ldyBEYXRhVmlldyhpbnB1dCwgZGF0YS5wdHIsIDE2KTsKICAgICAgICAgICAgICBkYXRhLnB0ciArPSAxNjsKICAgICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHZpZXcuZ2V0SW50MzIoMCwgdHJ1ZSk7CiAgICAgICAgICAgICAgaWYgKHZlcnNpb24gPCAyKSB7CiAgICAgICAgICAgICAgICB0aHJvdyAidW5zdXBwb3J0ZWQgSHVmZm1hbiB2ZXJzaW9uIjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmFyIHNpemUgPSB2aWV3LmdldEludDMyKDQsIHRydWUpOwogICAgICAgICAgICAgIHZhciBpMCA9IHZpZXcuZ2V0SW50MzIoOCwgdHJ1ZSk7CiAgICAgICAgICAgICAgdmFyIGkxID0gdmlldy5nZXRJbnQzMigxMiwgdHJ1ZSk7CiAgICAgICAgICAgICAgaWYgKGkwID49IGkxKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHZhciBibG9ja0RhdGFCdWZmZXIgPSBuZXcgVWludDMyQXJyYXkoaTEgLSBpMCk7CiAgICAgICAgICAgICAgTGVyYzJIZWxwZXJzLmRlY29kZUJpdHMoaW5wdXQsIGRhdGEsIGJsb2NrRGF0YUJ1ZmZlcik7CiAgICAgICAgICAgICAgdmFyIGNvZGVUYWJsZSA9IFtdOwogICAgICAgICAgICAgIHZhciBpLCBqLCBrLCBsZW47CiAgICAgICAgICAgICAgZm9yIChpID0gaTA7IGkgPCBpMTsgaSsrKSB7CiAgICAgICAgICAgICAgICBqID0gaSAtIChpIDwgc2l6ZSA/IDAgOiBzaXplKTsKICAgICAgICAgICAgICAgIGNvZGVUYWJsZVtqXSA9IHsgZmlyc3Q6IGJsb2NrRGF0YUJ1ZmZlcltpIC0gaTBdLCBzZWNvbmQ6IG51bGwgfTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmFyIGRhdGFCeXRlcyA9IGlucHV0LmJ5dGVMZW5ndGggLSBkYXRhLnB0cjsKICAgICAgICAgICAgICB2YXIgZGF0YVdvcmRzID0gTWF0aC5jZWlsKGRhdGFCeXRlcyAvIDQpOwogICAgICAgICAgICAgIHZhciBhcnJheUJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcihkYXRhV29yZHMgKiA0KTsKICAgICAgICAgICAgICB2YXIgc3RvcmU4ID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWYpOwogICAgICAgICAgICAgIHN0b3JlOC5zZXQobmV3IFVpbnQ4QXJyYXkoaW5wdXQsIGRhdGEucHRyLCBkYXRhQnl0ZXMpKTsKICAgICAgICAgICAgICB2YXIgc3R1ZmZlZERhdGEgPSBuZXcgVWludDMyQXJyYXkoYXJyYXlCdWYpOwogICAgICAgICAgICAgIHZhciBiaXRQb3MgPSAwLCB3b3JkLCBzcmNQdHIgPSAwOwogICAgICAgICAgICAgIHdvcmQgPSBzdHVmZmVkRGF0YVswXTsKICAgICAgICAgICAgICBmb3IgKGkgPSBpMDsgaSA8IGkxOyBpKyspIHsKICAgICAgICAgICAgICAgIGogPSBpIC0gKGkgPCBzaXplID8gMCA6IHNpemUpOwogICAgICAgICAgICAgICAgbGVuID0gY29kZVRhYmxlW2pdLmZpcnN0OwogICAgICAgICAgICAgICAgaWYgKGxlbiA+IDApIHsKICAgICAgICAgICAgICAgICAgY29kZVRhYmxlW2pdLnNlY29uZCA9IHdvcmQgPDwgYml0UG9zID4+PiAzMiAtIGxlbjsKICAgICAgICAgICAgICAgICAgaWYgKDMyIC0gYml0UG9zID49IGxlbikgewogICAgICAgICAgICAgICAgICAgIGJpdFBvcyArPSBsZW47CiAgICAgICAgICAgICAgICAgICAgaWYgKGJpdFBvcyA9PT0gMzIpIHsKICAgICAgICAgICAgICAgICAgICAgIGJpdFBvcyA9IDA7CiAgICAgICAgICAgICAgICAgICAgICBzcmNQdHIrKzsKICAgICAgICAgICAgICAgICAgICAgIHdvcmQgPSBzdHVmZmVkRGF0YVtzcmNQdHJdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBiaXRQb3MgKz0gbGVuIC0gMzI7CiAgICAgICAgICAgICAgICAgICAgc3JjUHRyKys7CiAgICAgICAgICAgICAgICAgICAgd29yZCA9IHN0dWZmZWREYXRhW3NyY1B0cl07CiAgICAgICAgICAgICAgICAgICAgY29kZVRhYmxlW2pdLnNlY29uZCB8PSB3b3JkID4+PiAzMiAtIGJpdFBvczsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB2YXIgbnVtQml0c0xVVCA9IDAsIG51bUJpdHNMVVRRaWNrID0gMDsKICAgICAgICAgICAgICB2YXIgdHJlZSA9IG5ldyBUcmVlTm9kZSgpOwogICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb2RlVGFibGUubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIGlmIChjb2RlVGFibGVbaV0gIT09IHZvaWQgMCkgewogICAgICAgICAgICAgICAgICBudW1CaXRzTFVUID0gTWF0aC5tYXgobnVtQml0c0xVVCwgY29kZVRhYmxlW2ldLmZpcnN0KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKG51bUJpdHNMVVQgPj0gQklUU19NQVgpIHsKICAgICAgICAgICAgICAgIG51bUJpdHNMVVRRaWNrID0gQklUU19NQVg7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIG51bUJpdHNMVVRRaWNrID0gbnVtQml0c0xVVDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKG51bUJpdHNMVVQgPj0gMzApIHsKICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCJXQVJuaW5nLCBsYXJnZSBOVU0gTFVUIEJJVFMgSVMgIiArIG51bUJpdHNMVVQpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB2YXIgZGVjb2RlTHV0ID0gW10sIGVudHJ5LCBjb2RlLCBudW1FbnRyaWVzLCBqaiwgY3VycmVudEJpdCwgbm9kZTsKICAgICAgICAgICAgICBmb3IgKGkgPSBpMDsgaSA8IGkxOyBpKyspIHsKICAgICAgICAgICAgICAgIGogPSBpIC0gKGkgPCBzaXplID8gMCA6IHNpemUpOwogICAgICAgICAgICAgICAgbGVuID0gY29kZVRhYmxlW2pdLmZpcnN0OwogICAgICAgICAgICAgICAgaWYgKGxlbiA+IDApIHsKICAgICAgICAgICAgICAgICAgZW50cnkgPSBbbGVuLCBqXTsKICAgICAgICAgICAgICAgICAgaWYgKGxlbiA8PSBudW1CaXRzTFVUUWljaykgewogICAgICAgICAgICAgICAgICAgIGNvZGUgPSBjb2RlVGFibGVbal0uc2Vjb25kIDw8IG51bUJpdHNMVVRRaWNrIC0gbGVuOwogICAgICAgICAgICAgICAgICAgIG51bUVudHJpZXMgPSAxIDw8IG51bUJpdHNMVVRRaWNrIC0gbGVuOwogICAgICAgICAgICAgICAgICAgIGZvciAoayA9IDA7IGsgPCBudW1FbnRyaWVzOyBrKyspIHsKICAgICAgICAgICAgICAgICAgICAgIGRlY29kZUx1dFtjb2RlIHwga10gPSBlbnRyeTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgY29kZSA9IGNvZGVUYWJsZVtqXS5zZWNvbmQ7CiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IHRyZWU7CiAgICAgICAgICAgICAgICAgICAgZm9yIChqaiA9IGxlbiAtIDE7IGpqID49IDA7IGpqLS0pIHsKICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRCaXQgPSBjb2RlID4+PiBqaiAmIDE7CiAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudEJpdCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW5vZGUucmlnaHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJpZ2h0ID0gbmV3IFRyZWVOb2RlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgbm9kZSA9IG5vZGUucmlnaHQ7CiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW5vZGUubGVmdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUubGVmdCA9IG5ldyBUcmVlTm9kZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUgPSBub2RlLmxlZnQ7CiAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICBpZiAoamogPT09IDAgJiYgIW5vZGUudmFsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUudmFsID0gZW50cnlbMV07CiAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICBkZWNvZGVMdXQsCiAgICAgICAgICAgICAgICBudW1CaXRzTFVUUWljaywKICAgICAgICAgICAgICAgIG51bUJpdHNMVVQsCiAgICAgICAgICAgICAgICB0cmVlLAogICAgICAgICAgICAgICAgc3R1ZmZlZERhdGEsCiAgICAgICAgICAgICAgICBzcmNQdHIsCiAgICAgICAgICAgICAgICBiaXRQb3MKICAgICAgICAgICAgICB9OwogICAgICAgICAgICB9LAogICAgICAgICAgICByZWFkSHVmZm1hbjogZnVuY3Rpb24oaW5wdXQsIGRhdGEsIE91dFBpeGVsVHlwZUFycmF5KSB7CiAgICAgICAgICAgICAgdmFyIGhlYWRlckluZm8gPSBkYXRhLmhlYWRlckluZm87CiAgICAgICAgICAgICAgdmFyIG51bURpbXMgPSBoZWFkZXJJbmZvLm51bURpbXM7CiAgICAgICAgICAgICAgdmFyIGhlaWdodCA9IGRhdGEuaGVhZGVySW5mby5oZWlnaHQ7CiAgICAgICAgICAgICAgdmFyIHdpZHRoID0gZGF0YS5oZWFkZXJJbmZvLndpZHRoOwogICAgICAgICAgICAgIHZhciBudW1QaXhlbHMgPSB3aWR0aCAqIGhlaWdodDsKICAgICAgICAgICAgICB2YXIgaHVmZm1hbkluZm8gPSB0aGlzLnJlYWRIdWZmbWFuVHJlZShpbnB1dCwgZGF0YSk7CiAgICAgICAgICAgICAgdmFyIGRlY29kZUx1dCA9IGh1ZmZtYW5JbmZvLmRlY29kZUx1dDsKICAgICAgICAgICAgICB2YXIgdHJlZSA9IGh1ZmZtYW5JbmZvLnRyZWU7CiAgICAgICAgICAgICAgdmFyIHN0dWZmZWREYXRhID0gaHVmZm1hbkluZm8uc3R1ZmZlZERhdGE7CiAgICAgICAgICAgICAgdmFyIHNyY1B0ciA9IGh1ZmZtYW5JbmZvLnNyY1B0cjsKICAgICAgICAgICAgICB2YXIgYml0UG9zID0gaHVmZm1hbkluZm8uYml0UG9zOwogICAgICAgICAgICAgIHZhciBudW1CaXRzTFVUUWljayA9IGh1ZmZtYW5JbmZvLm51bUJpdHNMVVRRaWNrOwogICAgICAgICAgICAgIHZhciBudW1CaXRzTFVUID0gaHVmZm1hbkluZm8ubnVtQml0c0xVVDsKICAgICAgICAgICAgICB2YXIgb2Zmc2V0ID0gZGF0YS5oZWFkZXJJbmZvLmltYWdlVHlwZSA9PT0gMCA/IDEyOCA6IDA7CiAgICAgICAgICAgICAgdmFyIG5vZGUsIHZhbCwgZGVsdGEsIG1hc2sgPSBkYXRhLnBpeGVscy5yZXN1bHRNYXNrLCB2YWxUbXAsIHZhbFRtcFF1aWNrLCBjdXJyZW50Qml0OwogICAgICAgICAgICAgIHZhciBpLCBqLCBrLCBpaTsKICAgICAgICAgICAgICB2YXIgcHJldlZhbCA9IDA7CiAgICAgICAgICAgICAgaWYgKGJpdFBvcyA+IDApIHsKICAgICAgICAgICAgICAgIHNyY1B0cisrOwogICAgICAgICAgICAgICAgYml0UG9zID0gMDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmFyIHdvcmQgPSBzdHVmZmVkRGF0YVtzcmNQdHJdOwogICAgICAgICAgICAgIHZhciBkZWx0YUVuY29kZSA9IGRhdGEuZW5jb2RlTW9kZSA9PT0gMTsKICAgICAgICAgICAgICB2YXIgcmVzdWx0UGl4ZWxzQWxsRGltID0gbmV3IE91dFBpeGVsVHlwZUFycmF5KG51bVBpeGVscyAqIG51bURpbXMpOwogICAgICAgICAgICAgIHZhciByZXN1bHRQaXhlbHMgPSByZXN1bHRQaXhlbHNBbGxEaW07CiAgICAgICAgICAgICAgdmFyIGlEaW07CiAgICAgICAgICAgICAgZm9yIChpRGltID0gMDsgaURpbSA8IGhlYWRlckluZm8ubnVtRGltczsgaURpbSsrKSB7CiAgICAgICAgICAgICAgICBpZiAobnVtRGltcyA+IDEpIHsKICAgICAgICAgICAgICAgICAgcmVzdWx0UGl4ZWxzID0gbmV3IE91dFBpeGVsVHlwZUFycmF5KHJlc3VsdFBpeGVsc0FsbERpbS5idWZmZXIsIG51bVBpeGVscyAqIGlEaW0sIG51bVBpeGVscyk7CiAgICAgICAgICAgICAgICAgIHByZXZWYWwgPSAwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKGRhdGEuaGVhZGVySW5mby5udW1WYWxpZFBpeGVsID09PSB3aWR0aCAqIGhlaWdodCkgewogICAgICAgICAgICAgICAgICBmb3IgKGsgPSAwLCBpID0gMDsgaSA8IGhlaWdodDsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHdpZHRoOyBqKyssIGsrKykgewogICAgICAgICAgICAgICAgICAgICAgdmFsID0gMDsKICAgICAgICAgICAgICAgICAgICAgIHZhbFRtcCA9IHdvcmQgPDwgYml0UG9zID4+PiAzMiAtIG51bUJpdHNMVVRRaWNrOwogICAgICAgICAgICAgICAgICAgICAgdmFsVG1wUXVpY2sgPSB2YWxUbXA7CiAgICAgICAgICAgICAgICAgICAgICBpZiAoMzIgLSBiaXRQb3MgPCBudW1CaXRzTFVUUWljaykgewogICAgICAgICAgICAgICAgICAgICAgICB2YWxUbXAgfD0gc3R1ZmZlZERhdGFbc3JjUHRyICsgMV0gPj4+IDY0IC0gYml0UG9zIC0gbnVtQml0c0xVVFFpY2s7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbFRtcFF1aWNrID0gdmFsVG1wOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgaWYgKGRlY29kZUx1dFt2YWxUbXBRdWlja10pIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gZGVjb2RlTHV0W3ZhbFRtcFF1aWNrXVsxXTsKICAgICAgICAgICAgICAgICAgICAgICAgYml0UG9zICs9IGRlY29kZUx1dFt2YWxUbXBRdWlja11bMF07CiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICB2YWxUbXAgPSB3b3JkIDw8IGJpdFBvcyA+Pj4gMzIgLSBudW1CaXRzTFVUOwogICAgICAgICAgICAgICAgICAgICAgICB2YWxUbXBRdWljayA9IHZhbFRtcDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKDMyIC0gYml0UG9zIDwgbnVtQml0c0xVVCkgewogICAgICAgICAgICAgICAgICAgICAgICAgIHZhbFRtcCB8PSBzdHVmZmVkRGF0YVtzcmNQdHIgKyAxXSA+Pj4gNjQgLSBiaXRQb3MgLSBudW1CaXRzTFVUOwogICAgICAgICAgICAgICAgICAgICAgICAgIHZhbFRtcFF1aWNrID0gdmFsVG1wOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUgPSB0cmVlOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGlpID0gMDsgaWkgPCBudW1CaXRzTFVUOyBpaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudEJpdCA9IHZhbFRtcCA+Pj4gbnVtQml0c0xVVCAtIGlpIC0gMSAmIDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGN1cnJlbnRCaXQgPyBub2RlLnJpZ2h0IDogbm9kZS5sZWZ0OwogICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghKG5vZGUubGVmdCB8fCBub2RlLnJpZ2h0KSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gbm9kZS52YWw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXRQb3MgPSBiaXRQb3MgKyBpaSArIDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIGlmIChiaXRQb3MgPj0gMzIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgYml0UG9zIC09IDMyOwogICAgICAgICAgICAgICAgICAgICAgICBzcmNQdHIrKzsKICAgICAgICAgICAgICAgICAgICAgICAgd29yZCA9IHN0dWZmZWREYXRhW3NyY1B0cl07CiAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICBkZWx0YSA9IHZhbCAtIG9mZnNldDsKICAgICAgICAgICAgICAgICAgICAgIGlmIChkZWx0YUVuY29kZSkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoaiA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBkZWx0YSArPSBwcmV2VmFsOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGkgPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsdGEgKz0gcmVzdWx0UGl4ZWxzW2sgLSB3aWR0aF07CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsdGEgKz0gcHJldlZhbDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBkZWx0YSAmPSAyNTU7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdFBpeGVsc1trXSA9IGRlbHRhOwogICAgICAgICAgICAgICAgICAgICAgICBwcmV2VmFsID0gZGVsdGE7CiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRQaXhlbHNba10gPSBkZWx0YTsKICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGZvciAoayA9IDAsIGkgPSAwOyBpIDwgaGVpZ2h0OyBpKyspIHsKICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgd2lkdGg7IGorKywgaysrKSB7CiAgICAgICAgICAgICAgICAgICAgICBpZiAobWFza1trXSkgewogICAgICAgICAgICAgICAgICAgICAgICB2YWwgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICB2YWxUbXAgPSB3b3JkIDw8IGJpdFBvcyA+Pj4gMzIgLSBudW1CaXRzTFVUUWljazsKICAgICAgICAgICAgICAgICAgICAgICAgdmFsVG1wUXVpY2sgPSB2YWxUbXA7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgzMiAtIGJpdFBvcyA8IG51bUJpdHNMVVRRaWNrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsVG1wIHw9IHN0dWZmZWREYXRhW3NyY1B0ciArIDFdID4+PiA2NCAtIGJpdFBvcyAtIG51bUJpdHNMVVRRaWNrOwogICAgICAgICAgICAgICAgICAgICAgICAgIHZhbFRtcFF1aWNrID0gdmFsVG1wOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZWNvZGVMdXRbdmFsVG1wUXVpY2tdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gZGVjb2RlTHV0W3ZhbFRtcFF1aWNrXVsxXTsKICAgICAgICAgICAgICAgICAgICAgICAgICBiaXRQb3MgKz0gZGVjb2RlTHV0W3ZhbFRtcFF1aWNrXVswXTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxUbXAgPSB3b3JkIDw8IGJpdFBvcyA+Pj4gMzIgLSBudW1CaXRzTFVUOwogICAgICAgICAgICAgICAgICAgICAgICAgIHZhbFRtcFF1aWNrID0gdmFsVG1wOwogICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgzMiAtIGJpdFBvcyA8IG51bUJpdHNMVVQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbFRtcCB8PSBzdHVmZmVkRGF0YVtzcmNQdHIgKyAxXSA+Pj4gNjQgLSBiaXRQb3MgLSBudW1CaXRzTFVUOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsVG1wUXVpY2sgPSB2YWxUbXA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUgPSB0cmVlOwogICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaWkgPSAwOyBpaSA8IG51bUJpdHNMVVQ7IGlpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRCaXQgPSB2YWxUbXAgPj4+IG51bUJpdHNMVVQgLSBpaSAtIDEgJiAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGN1cnJlbnRCaXQgPyBub2RlLnJpZ2h0IDogbm9kZS5sZWZ0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEobm9kZS5sZWZ0IHx8IG5vZGUucmlnaHQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbCA9IG5vZGUudmFsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaXRQb3MgPSBiaXRQb3MgKyBpaSArIDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoYml0UG9zID49IDMyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgYml0UG9zIC09IDMyOwogICAgICAgICAgICAgICAgICAgICAgICAgIHNyY1B0cisrOwogICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmQgPSBzdHVmZmVkRGF0YVtzcmNQdHJdOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGRlbHRhID0gdmFsIC0gb2Zmc2V0OwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGVsdGFFbmNvZGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaiA+IDAgJiYgbWFza1trIC0gMV0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbHRhICs9IHByZXZWYWw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpID4gMCAmJiBtYXNrW2sgLSB3aWR0aF0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbHRhICs9IHJlc3VsdFBpeGVsc1trIC0gd2lkdGhdOwogICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWx0YSArPSBwcmV2VmFsOwogICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICBkZWx0YSAmPSAyNTU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0UGl4ZWxzW2tdID0gZGVsdGE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldlZhbCA9IGRlbHRhOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdFBpeGVsc1trXSA9IGRlbHRhOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBkYXRhLnB0ciA9IGRhdGEucHRyICsgKHNyY1B0ciArIDEpICogNCArIChiaXRQb3MgPiAwID8gNCA6IDApOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBkYXRhLnBpeGVscy5yZXN1bHRQaXhlbHMgPSByZXN1bHRQaXhlbHNBbGxEaW07CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGRlY29kZUJpdHM6IGZ1bmN0aW9uKGlucHV0LCBkYXRhLCBibG9ja0RhdGFCdWZmZXIsIG9mZnNldCwgaURpbSkgewogICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHZhciBoZWFkZXJJbmZvID0gZGF0YS5oZWFkZXJJbmZvOwogICAgICAgICAgICAgICAgdmFyIGZpbGVWZXJzaW9uID0gaGVhZGVySW5mby5maWxlVmVyc2lvbjsKICAgICAgICAgICAgICAgIHZhciBibG9ja1B0ciA9IDA7CiAgICAgICAgICAgICAgICB2YXIgdmlldyA9IG5ldyBEYXRhVmlldyhpbnB1dCwgZGF0YS5wdHIsIDUpOwogICAgICAgICAgICAgICAgdmFyIGhlYWRlckJ5dGUgPSB2aWV3LmdldFVpbnQ4KDApOwogICAgICAgICAgICAgICAgYmxvY2tQdHIrKzsKICAgICAgICAgICAgICAgIHZhciBiaXRzNjcgPSBoZWFkZXJCeXRlID4+IDY7CiAgICAgICAgICAgICAgICB2YXIgbiA9IGJpdHM2NyA9PT0gMCA/IDQgOiAzIC0gYml0czY3OwogICAgICAgICAgICAgICAgdmFyIGRvTHV0ID0gKGhlYWRlckJ5dGUgJiAzMikgPiAwID8gdHJ1ZSA6IGZhbHNlOwogICAgICAgICAgICAgICAgdmFyIG51bUJpdHMgPSBoZWFkZXJCeXRlICYgMzE7CiAgICAgICAgICAgICAgICB2YXIgbnVtRWxlbWVudHMgPSAwOwogICAgICAgICAgICAgICAgaWYgKG4gPT09IDEpIHsKICAgICAgICAgICAgICAgICAgbnVtRWxlbWVudHMgPSB2aWV3LmdldFVpbnQ4KGJsb2NrUHRyKTsKICAgICAgICAgICAgICAgICAgYmxvY2tQdHIrKzsKICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobiA9PT0gMikgewogICAgICAgICAgICAgICAgICBudW1FbGVtZW50cyA9IHZpZXcuZ2V0VWludDE2KGJsb2NrUHRyLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgYmxvY2tQdHIgKz0gMjsKICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobiA9PT0gNCkgewogICAgICAgICAgICAgICAgICBudW1FbGVtZW50cyA9IHZpZXcuZ2V0VWludDMyKGJsb2NrUHRyLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgYmxvY2tQdHIgKz0gNDsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIHRocm93ICJJbnZhbGlkIHZhbGlkIHBpeGVsIGNvdW50IHR5cGUiOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIHNjYWxlID0gMiAqIGhlYWRlckluZm8ubWF4WkVycm9yOwogICAgICAgICAgICAgICAgdmFyIHN0dWZmZWREYXRhLCBhcnJheUJ1Ziwgc3RvcmU4LCBkYXRhQnl0ZXMsIGRhdGFXb3JkczsKICAgICAgICAgICAgICAgIHZhciBsdXRBcnIsIGx1dERhdGEsIGx1dEJ5dGVzLCBsdXRCaXRzUGVyRWxlbWVudCwgYml0c1BlclBpeGVsOwogICAgICAgICAgICAgICAgdmFyIHpNYXggPSBoZWFkZXJJbmZvLm51bURpbXMgPiAxID8gaGVhZGVySW5mby5tYXhWYWx1ZXNbaURpbV0gOiBoZWFkZXJJbmZvLnpNYXg7CiAgICAgICAgICAgICAgICBpZiAoZG9MdXQpIHsKICAgICAgICAgICAgICAgICAgZGF0YS5jb3VudGVyLmx1dCsrOwogICAgICAgICAgICAgICAgICBsdXRCeXRlcyA9IHZpZXcuZ2V0VWludDgoYmxvY2tQdHIpOwogICAgICAgICAgICAgICAgICBsdXRCaXRzUGVyRWxlbWVudCA9IG51bUJpdHM7CiAgICAgICAgICAgICAgICAgIGJsb2NrUHRyKys7CiAgICAgICAgICAgICAgICAgIGRhdGFCeXRlcyA9IE1hdGguY2VpbCgobHV0Qnl0ZXMgLSAxKSAqIG51bUJpdHMgLyA4KTsKICAgICAgICAgICAgICAgICAgZGF0YVdvcmRzID0gTWF0aC5jZWlsKGRhdGFCeXRlcyAvIDQpOwogICAgICAgICAgICAgICAgICBhcnJheUJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcihkYXRhV29yZHMgKiA0KTsKICAgICAgICAgICAgICAgICAgc3RvcmU4ID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWYpOwogICAgICAgICAgICAgICAgICBkYXRhLnB0ciArPSBibG9ja1B0cjsKICAgICAgICAgICAgICAgICAgc3RvcmU4LnNldChuZXcgVWludDhBcnJheShpbnB1dCwgZGF0YS5wdHIsIGRhdGFCeXRlcykpOwogICAgICAgICAgICAgICAgICBsdXREYXRhID0gbmV3IFVpbnQzMkFycmF5KGFycmF5QnVmKTsKICAgICAgICAgICAgICAgICAgZGF0YS5wdHIgKz0gZGF0YUJ5dGVzOwogICAgICAgICAgICAgICAgICBiaXRzUGVyUGl4ZWwgPSAwOwogICAgICAgICAgICAgICAgICB3aGlsZSAobHV0Qnl0ZXMgLSAxID4+PiBiaXRzUGVyUGl4ZWwpIHsKICAgICAgICAgICAgICAgICAgICBiaXRzUGVyUGl4ZWwrKzsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBkYXRhQnl0ZXMgPSBNYXRoLmNlaWwobnVtRWxlbWVudHMgKiBiaXRzUGVyUGl4ZWwgLyA4KTsKICAgICAgICAgICAgICAgICAgZGF0YVdvcmRzID0gTWF0aC5jZWlsKGRhdGFCeXRlcyAvIDQpOwogICAgICAgICAgICAgICAgICBhcnJheUJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcihkYXRhV29yZHMgKiA0KTsKICAgICAgICAgICAgICAgICAgc3RvcmU4ID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWYpOwogICAgICAgICAgICAgICAgICBzdG9yZTguc2V0KG5ldyBVaW50OEFycmF5KGlucHV0LCBkYXRhLnB0ciwgZGF0YUJ5dGVzKSk7CiAgICAgICAgICAgICAgICAgIHN0dWZmZWREYXRhID0gbmV3IFVpbnQzMkFycmF5KGFycmF5QnVmKTsKICAgICAgICAgICAgICAgICAgZGF0YS5wdHIgKz0gZGF0YUJ5dGVzOwogICAgICAgICAgICAgICAgICBpZiAoZmlsZVZlcnNpb24gPj0gMykgewogICAgICAgICAgICAgICAgICAgIGx1dEFyciA9IEJpdFN0dWZmZXIudW5zdHVmZkxVVDIobHV0RGF0YSwgbnVtQml0cywgbHV0Qnl0ZXMgLSAxLCBvZmZzZXQsIHNjYWxlLCB6TWF4KTsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBsdXRBcnIgPSBCaXRTdHVmZmVyLnVuc3R1ZmZMVVQobHV0RGF0YSwgbnVtQml0cywgbHV0Qnl0ZXMgLSAxLCBvZmZzZXQsIHNjYWxlLCB6TWF4KTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAoZmlsZVZlcnNpb24gPj0gMykgewogICAgICAgICAgICAgICAgICAgIEJpdFN0dWZmZXIudW5zdHVmZjIoc3R1ZmZlZERhdGEsIGJsb2NrRGF0YUJ1ZmZlciwgYml0c1BlclBpeGVsLCBudW1FbGVtZW50cywgbHV0QXJyKTsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBCaXRTdHVmZmVyLnVuc3R1ZmYoc3R1ZmZlZERhdGEsIGJsb2NrRGF0YUJ1ZmZlciwgYml0c1BlclBpeGVsLCBudW1FbGVtZW50cywgbHV0QXJyKTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgZGF0YS5jb3VudGVyLmJpdHN0dWZmZXIrKzsKICAgICAgICAgICAgICAgICAgYml0c1BlclBpeGVsID0gbnVtQml0czsKICAgICAgICAgICAgICAgICAgZGF0YS5wdHIgKz0gYmxvY2tQdHI7CiAgICAgICAgICAgICAgICAgIGlmIChiaXRzUGVyUGl4ZWwgPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgZGF0YUJ5dGVzID0gTWF0aC5jZWlsKG51bUVsZW1lbnRzICogYml0c1BlclBpeGVsIC8gOCk7CiAgICAgICAgICAgICAgICAgICAgZGF0YVdvcmRzID0gTWF0aC5jZWlsKGRhdGFCeXRlcyAvIDQpOwogICAgICAgICAgICAgICAgICAgIGFycmF5QnVmID0gbmV3IEFycmF5QnVmZmVyKGRhdGFXb3JkcyAqIDQpOwogICAgICAgICAgICAgICAgICAgIHN0b3JlOCA9IG5ldyBVaW50OEFycmF5KGFycmF5QnVmKTsKICAgICAgICAgICAgICAgICAgICBzdG9yZTguc2V0KG5ldyBVaW50OEFycmF5KGlucHV0LCBkYXRhLnB0ciwgZGF0YUJ5dGVzKSk7CiAgICAgICAgICAgICAgICAgICAgc3R1ZmZlZERhdGEgPSBuZXcgVWludDMyQXJyYXkoYXJyYXlCdWYpOwogICAgICAgICAgICAgICAgICAgIGRhdGEucHRyICs9IGRhdGFCeXRlczsKICAgICAgICAgICAgICAgICAgICBpZiAoZmlsZVZlcnNpb24gPj0gMykgewogICAgICAgICAgICAgICAgICAgICAgaWYgKG9mZnNldCA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIEJpdFN0dWZmZXIub3JpZ2luYWxVbnN0dWZmMihzdHVmZmVkRGF0YSwgYmxvY2tEYXRhQnVmZmVyLCBiaXRzUGVyUGl4ZWwsIG51bUVsZW1lbnRzKTsKICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIEJpdFN0dWZmZXIudW5zdHVmZjIoc3R1ZmZlZERhdGEsIGJsb2NrRGF0YUJ1ZmZlciwgYml0c1BlclBpeGVsLCBudW1FbGVtZW50cywgZmFsc2UsIG9mZnNldCwgc2NhbGUsIHpNYXgpOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICBpZiAob2Zmc2V0ID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgQml0U3R1ZmZlci5vcmlnaW5hbFVuc3R1ZmYoc3R1ZmZlZERhdGEsIGJsb2NrRGF0YUJ1ZmZlciwgYml0c1BlclBpeGVsLCBudW1FbGVtZW50cyk7CiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBCaXRTdHVmZmVyLnVuc3R1ZmYoc3R1ZmZlZERhdGEsIGJsb2NrRGF0YUJ1ZmZlciwgYml0c1BlclBpeGVsLCBudW1FbGVtZW50cywgZmFsc2UsIG9mZnNldCwgc2NhbGUsIHpNYXgpOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgcmVhZFRpbGVzOiBmdW5jdGlvbihpbnB1dCwgZGF0YSwgT3V0UGl4ZWxUeXBlQXJyYXkpIHsKICAgICAgICAgICAgICB2YXIgaGVhZGVySW5mbyA9IGRhdGEuaGVhZGVySW5mbzsKICAgICAgICAgICAgICB2YXIgd2lkdGggPSBoZWFkZXJJbmZvLndpZHRoOwogICAgICAgICAgICAgIHZhciBoZWlnaHQgPSBoZWFkZXJJbmZvLmhlaWdodDsKICAgICAgICAgICAgICB2YXIgbWljcm9CbG9ja1NpemUgPSBoZWFkZXJJbmZvLm1pY3JvQmxvY2tTaXplOwogICAgICAgICAgICAgIHZhciBpbWFnZVR5cGUgPSBoZWFkZXJJbmZvLmltYWdlVHlwZTsKICAgICAgICAgICAgICB2YXIgZGF0YVR5cGVTaXplID0gTGVyYzJIZWxwZXJzLmdldERhdGFUeXBlU2l6ZShpbWFnZVR5cGUpOwogICAgICAgICAgICAgIHZhciBudW1CbG9ja3NYID0gTWF0aC5jZWlsKHdpZHRoIC8gbWljcm9CbG9ja1NpemUpOwogICAgICAgICAgICAgIHZhciBudW1CbG9ja3NZID0gTWF0aC5jZWlsKGhlaWdodCAvIG1pY3JvQmxvY2tTaXplKTsKICAgICAgICAgICAgICBkYXRhLnBpeGVscy5udW1CbG9ja3NZID0gbnVtQmxvY2tzWTsKICAgICAgICAgICAgICBkYXRhLnBpeGVscy5udW1CbG9ja3NYID0gbnVtQmxvY2tzWDsKICAgICAgICAgICAgICBkYXRhLnBpeGVscy5wdHIgPSAwOwogICAgICAgICAgICAgIHZhciByb3cgPSAwLCBjb2wgPSAwLCBibG9ja1kgPSAwLCBibG9ja1ggPSAwLCB0aGlzQmxvY2tIZWlnaHQgPSAwLCB0aGlzQmxvY2tXaWR0aCA9IDAsIGJ5dGVzTGVmdCA9IDAsIGhlYWRlckJ5dGUgPSAwLCBiaXRzNjcgPSAwLCB0ZXN0Q29kZSA9IDAsIG91dFB0ciA9IDAsIG91dFN0cmlkZSA9IDAsIG51bUJ5dGVzID0gMCwgYnl0ZXNsZWZ0ID0gMCwgeiA9IDAsIGJsb2NrUHRyID0gMDsKICAgICAgICAgICAgICB2YXIgdmlldywgYmxvY2ssIGFycmF5QnVmLCBzdG9yZTgsIHJhd0RhdGE7CiAgICAgICAgICAgICAgdmFyIGJsb2NrRW5jb2Rpbmc7CiAgICAgICAgICAgICAgdmFyIGJsb2NrRGF0YUJ1ZmZlciA9IG5ldyBPdXRQaXhlbFR5cGVBcnJheShtaWNyb0Jsb2NrU2l6ZSAqIG1pY3JvQmxvY2tTaXplKTsKICAgICAgICAgICAgICB2YXIgbGFzdEJsb2NrSGVpZ2h0ID0gaGVpZ2h0ICUgbWljcm9CbG9ja1NpemUgfHwgbWljcm9CbG9ja1NpemU7CiAgICAgICAgICAgICAgdmFyIGxhc3RCbG9ja1dpZHRoID0gd2lkdGggJSBtaWNyb0Jsb2NrU2l6ZSB8fCBtaWNyb0Jsb2NrU2l6ZTsKICAgICAgICAgICAgICB2YXIgb2Zmc2V0VHlwZSwgb2Zmc2V0OwogICAgICAgICAgICAgIHZhciBudW1EaW1zID0gaGVhZGVySW5mby5udW1EaW1zLCBpRGltOwogICAgICAgICAgICAgIHZhciBtYXNrID0gZGF0YS5waXhlbHMucmVzdWx0TWFzazsKICAgICAgICAgICAgICB2YXIgcmVzdWx0UGl4ZWxzID0gZGF0YS5waXhlbHMucmVzdWx0UGl4ZWxzOwogICAgICAgICAgICAgIGZvciAoYmxvY2tZID0gMDsgYmxvY2tZIDwgbnVtQmxvY2tzWTsgYmxvY2tZKyspIHsKICAgICAgICAgICAgICAgIHRoaXNCbG9ja0hlaWdodCA9IGJsb2NrWSAhPT0gbnVtQmxvY2tzWSAtIDEgPyBtaWNyb0Jsb2NrU2l6ZSA6IGxhc3RCbG9ja0hlaWdodDsKICAgICAgICAgICAgICAgIGZvciAoYmxvY2tYID0gMDsgYmxvY2tYIDwgbnVtQmxvY2tzWDsgYmxvY2tYKyspIHsKICAgICAgICAgICAgICAgICAgdGhpc0Jsb2NrV2lkdGggPSBibG9ja1ggIT09IG51bUJsb2Nrc1ggLSAxID8gbWljcm9CbG9ja1NpemUgOiBsYXN0QmxvY2tXaWR0aDsKICAgICAgICAgICAgICAgICAgb3V0UHRyID0gYmxvY2tZICogd2lkdGggKiBtaWNyb0Jsb2NrU2l6ZSArIGJsb2NrWCAqIG1pY3JvQmxvY2tTaXplOwogICAgICAgICAgICAgICAgICBvdXRTdHJpZGUgPSB3aWR0aCAtIHRoaXNCbG9ja1dpZHRoOwogICAgICAgICAgICAgICAgICBmb3IgKGlEaW0gPSAwOyBpRGltIDwgbnVtRGltczsgaURpbSsrKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKG51bURpbXMgPiAxKSB7CiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRQaXhlbHMgPSBuZXcgT3V0UGl4ZWxUeXBlQXJyYXkoZGF0YS5waXhlbHMucmVzdWx0UGl4ZWxzLmJ1ZmZlciwgd2lkdGggKiBoZWlnaHQgKiBpRGltICogZGF0YVR5cGVTaXplLCB3aWR0aCAqIGhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJ5dGVzTGVmdCA9IGlucHV0LmJ5dGVMZW5ndGggLSBkYXRhLnB0cjsKICAgICAgICAgICAgICAgICAgICB2aWV3ID0gbmV3IERhdGFWaWV3KGlucHV0LCBkYXRhLnB0ciwgTWF0aC5taW4oMTAsIGJ5dGVzTGVmdCkpOwogICAgICAgICAgICAgICAgICAgIGJsb2NrID0ge307CiAgICAgICAgICAgICAgICAgICAgYmxvY2tQdHIgPSAwOwogICAgICAgICAgICAgICAgICAgIGhlYWRlckJ5dGUgPSB2aWV3LmdldFVpbnQ4KDApOwogICAgICAgICAgICAgICAgICAgIGJsb2NrUHRyKys7CiAgICAgICAgICAgICAgICAgICAgYml0czY3ID0gaGVhZGVyQnl0ZSA+PiA2ICYgMjU1OwogICAgICAgICAgICAgICAgICAgIHRlc3RDb2RlID0gaGVhZGVyQnl0ZSA+PiAyICYgMTU7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRlc3RDb2RlICE9PSAoYmxvY2tYICogbWljcm9CbG9ja1NpemUgPj4gMyAmIDE1KSkgewogICAgICAgICAgICAgICAgICAgICAgdGhyb3cgImludGVncml0eSBpc3N1ZSI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJsb2NrRW5jb2RpbmcgPSBoZWFkZXJCeXRlICYgMzsKICAgICAgICAgICAgICAgICAgICBpZiAoYmxvY2tFbmNvZGluZyA+IDMpIHsKICAgICAgICAgICAgICAgICAgICAgIGRhdGEucHRyICs9IGJsb2NrUHRyOwogICAgICAgICAgICAgICAgICAgICAgdGhyb3cgIkludmFsaWQgYmxvY2sgZW5jb2RpbmcgKCIgKyBibG9ja0VuY29kaW5nICsgIikiOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYmxvY2tFbmNvZGluZyA9PT0gMikgewogICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb3VudGVyLmNvbnN0YW50Kys7CiAgICAgICAgICAgICAgICAgICAgICBkYXRhLnB0ciArPSBibG9ja1B0cjsKICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYmxvY2tFbmNvZGluZyA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgZGF0YS5jb3VudGVyLnVuY29tcHJlc3NlZCsrOwogICAgICAgICAgICAgICAgICAgICAgZGF0YS5wdHIgKz0gYmxvY2tQdHI7CiAgICAgICAgICAgICAgICAgICAgICBudW1CeXRlcyA9IHRoaXNCbG9ja0hlaWdodCAqIHRoaXNCbG9ja1dpZHRoICogZGF0YVR5cGVTaXplOwogICAgICAgICAgICAgICAgICAgICAgYnl0ZXNsZWZ0ID0gaW5wdXQuYnl0ZUxlbmd0aCAtIGRhdGEucHRyOwogICAgICAgICAgICAgICAgICAgICAgbnVtQnl0ZXMgPSBudW1CeXRlcyA8IGJ5dGVzbGVmdCA/IG51bUJ5dGVzIDogYnl0ZXNsZWZ0OwogICAgICAgICAgICAgICAgICAgICAgYXJyYXlCdWYgPSBuZXcgQXJyYXlCdWZmZXIobnVtQnl0ZXMgJSBkYXRhVHlwZVNpemUgPT09IDAgPyBudW1CeXRlcyA6IG51bUJ5dGVzICsgZGF0YVR5cGVTaXplIC0gbnVtQnl0ZXMgJSBkYXRhVHlwZVNpemUpOwogICAgICAgICAgICAgICAgICAgICAgc3RvcmU4ID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWYpOwogICAgICAgICAgICAgICAgICAgICAgc3RvcmU4LnNldChuZXcgVWludDhBcnJheShpbnB1dCwgZGF0YS5wdHIsIG51bUJ5dGVzKSk7CiAgICAgICAgICAgICAgICAgICAgICByYXdEYXRhID0gbmV3IE91dFBpeGVsVHlwZUFycmF5KGFycmF5QnVmKTsKICAgICAgICAgICAgICAgICAgICAgIHogPSAwOwogICAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2spIHsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChyb3cgPSAwOyByb3cgPCB0aGlzQmxvY2tIZWlnaHQ7IHJvdysrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb2wgPSAwOyBjb2wgPCB0aGlzQmxvY2tXaWR0aDsgY29sKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXNrW291dFB0cl0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0UGl4ZWxzW291dFB0cl0gPSByYXdEYXRhW3orK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRQdHIrKzsKICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0UHRyICs9IG91dFN0cmlkZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChyb3cgPSAwOyByb3cgPCB0aGlzQmxvY2tIZWlnaHQ7IHJvdysrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb2wgPSAwOyBjb2wgPCB0aGlzQmxvY2tXaWR0aDsgY29sKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdFBpeGVsc1tvdXRQdHIrK10gPSByYXdEYXRhW3orK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgIG91dFB0ciArPSBvdXRTdHJpZGU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIGRhdGEucHRyICs9IHogKiBkYXRhVHlwZVNpemU7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgIG9mZnNldFR5cGUgPSBMZXJjMkhlbHBlcnMuZ2V0RGF0YVR5cGVVc2VkKGltYWdlVHlwZSwgYml0czY3KTsKICAgICAgICAgICAgICAgICAgICAgIG9mZnNldCA9IExlcmMySGVscGVycy5nZXRPbmVQaXhlbChibG9jaywgYmxvY2tQdHIsIG9mZnNldFR5cGUsIHZpZXcpOwogICAgICAgICAgICAgICAgICAgICAgYmxvY2tQdHIgKz0gTGVyYzJIZWxwZXJzLmdldERhdGFUeXBlU2l6ZShvZmZzZXRUeXBlKTsKICAgICAgICAgICAgICAgICAgICAgIGlmIChibG9ja0VuY29kaW5nID09PSAzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEucHRyICs9IGJsb2NrUHRyOwogICAgICAgICAgICAgICAgICAgICAgICBkYXRhLmNvdW50ZXIuY29uc3RhbnRvZmZzZXQrKzsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2spIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHJvdyA9IDA7IHJvdyA8IHRoaXNCbG9ja0hlaWdodDsgcm93KyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29sID0gMDsgY29sIDwgdGhpc0Jsb2NrV2lkdGg7IGNvbCsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXNrW291dFB0cl0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRQaXhlbHNbb3V0UHRyXSA9IG9mZnNldDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRQdHIrKzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dFB0ciArPSBvdXRTdHJpZGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAocm93ID0gMDsgcm93IDwgdGhpc0Jsb2NrSGVpZ2h0OyByb3crKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb2wgPSAwOyBjb2wgPCB0aGlzQmxvY2tXaWR0aDsgY29sKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0UGl4ZWxzW291dFB0cisrXSA9IG9mZnNldDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dFB0ciArPSBvdXRTdHJpZGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnB0ciArPSBibG9ja1B0cjsKICAgICAgICAgICAgICAgICAgICAgICAgTGVyYzJIZWxwZXJzLmRlY29kZUJpdHMoaW5wdXQsIGRhdGEsIGJsb2NrRGF0YUJ1ZmZlciwgb2Zmc2V0LCBpRGltKTsKICAgICAgICAgICAgICAgICAgICAgICAgYmxvY2tQdHIgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAobWFzaykgewogICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAocm93ID0gMDsgcm93IDwgdGhpc0Jsb2NrSGVpZ2h0OyByb3crKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb2wgPSAwOyBjb2wgPCB0aGlzQmxvY2tXaWR0aDsgY29sKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hc2tbb3V0UHRyXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdFBpeGVsc1tvdXRQdHJdID0gYmxvY2tEYXRhQnVmZmVyW2Jsb2NrUHRyKytdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dFB0cisrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0UHRyICs9IG91dFN0cmlkZTsKICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChyb3cgPSAwOyByb3cgPCB0aGlzQmxvY2tIZWlnaHQ7IHJvdysrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbCA9IDA7IGNvbCA8IHRoaXNCbG9ja1dpZHRoOyBjb2wrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRQaXhlbHNbb3V0UHRyKytdID0gYmxvY2tEYXRhQnVmZmVyW2Jsb2NrUHRyKytdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0UHRyICs9IG91dFN0cmlkZTsKICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIC8qKioqKioqKioqKioqKioqKgogICAgICAgICAgICAqICBwcml2YXRlIG1ldGhvZHMgKGhlbHBlciBtZXRob2RzKQogICAgICAgICAgICAqKioqKioqKioqKioqKioqKi8KICAgICAgICAgICAgZm9ybWF0RmlsZUluZm86IGZ1bmN0aW9uKGRhdGEpIHsKICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgImZpbGVJZGVudGlmaWVyU3RyaW5nIjogZGF0YS5oZWFkZXJJbmZvLmZpbGVJZGVudGlmaWVyU3RyaW5nLAogICAgICAgICAgICAgICAgImZpbGVWZXJzaW9uIjogZGF0YS5oZWFkZXJJbmZvLmZpbGVWZXJzaW9uLAogICAgICAgICAgICAgICAgImltYWdlVHlwZSI6IGRhdGEuaGVhZGVySW5mby5pbWFnZVR5cGUsCiAgICAgICAgICAgICAgICAiaGVpZ2h0IjogZGF0YS5oZWFkZXJJbmZvLmhlaWdodCwKICAgICAgICAgICAgICAgICJ3aWR0aCI6IGRhdGEuaGVhZGVySW5mby53aWR0aCwKICAgICAgICAgICAgICAgICJudW1WYWxpZFBpeGVsIjogZGF0YS5oZWFkZXJJbmZvLm51bVZhbGlkUGl4ZWwsCiAgICAgICAgICAgICAgICAibWljcm9CbG9ja1NpemUiOiBkYXRhLmhlYWRlckluZm8ubWljcm9CbG9ja1NpemUsCiAgICAgICAgICAgICAgICAiYmxvYlNpemUiOiBkYXRhLmhlYWRlckluZm8uYmxvYlNpemUsCiAgICAgICAgICAgICAgICAibWF4WkVycm9yIjogZGF0YS5oZWFkZXJJbmZvLm1heFpFcnJvciwKICAgICAgICAgICAgICAgICJwaXhlbFR5cGUiOiBMZXJjMkhlbHBlcnMuZ2V0UGl4ZWxUeXBlKGRhdGEuaGVhZGVySW5mby5pbWFnZVR5cGUpLAogICAgICAgICAgICAgICAgImVvZk9mZnNldCI6IGRhdGEuZW9mT2Zmc2V0LAogICAgICAgICAgICAgICAgIm1hc2siOiBkYXRhLm1hc2sgPyB7CiAgICAgICAgICAgICAgICAgICJudW1CeXRlcyI6IGRhdGEubWFzay5udW1CeXRlcwogICAgICAgICAgICAgICAgfSA6IG51bGwsCiAgICAgICAgICAgICAgICAicGl4ZWxzIjogewogICAgICAgICAgICAgICAgICAibnVtQmxvY2tzWCI6IGRhdGEucGl4ZWxzLm51bUJsb2Nrc1gsCiAgICAgICAgICAgICAgICAgICJudW1CbG9ja3NZIjogZGF0YS5waXhlbHMubnVtQmxvY2tzWSwKICAgICAgICAgICAgICAgICAgLy8ibnVtQnl0ZXMiOiBkYXRhLnBpeGVscy5udW1CeXRlcywKICAgICAgICAgICAgICAgICAgIm1heFZhbHVlIjogZGF0YS5oZWFkZXJJbmZvLnpNYXgsCiAgICAgICAgICAgICAgICAgICJtaW5WYWx1ZSI6IGRhdGEuaGVhZGVySW5mby56TWluLAogICAgICAgICAgICAgICAgICAibm9EYXRhVmFsdWUiOiBkYXRhLm5vRGF0YVZhbHVlCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfSwKICAgICAgICAgICAgY29uc3RydWN0Q29uc3RhbnRTdXJmYWNlOiBmdW5jdGlvbihkYXRhKSB7CiAgICAgICAgICAgICAgdmFyIHZhbCA9IGRhdGEuaGVhZGVySW5mby56TWF4OwogICAgICAgICAgICAgIHZhciBudW1EaW1zID0gZGF0YS5oZWFkZXJJbmZvLm51bURpbXM7CiAgICAgICAgICAgICAgdmFyIG51bVBpeGVscyA9IGRhdGEuaGVhZGVySW5mby5oZWlnaHQgKiBkYXRhLmhlYWRlckluZm8ud2lkdGg7CiAgICAgICAgICAgICAgdmFyIG51bVBpeGVsQWxsRGltcyA9IG51bVBpeGVscyAqIG51bURpbXM7CiAgICAgICAgICAgICAgdmFyIGkgPSAwLCBrID0gMCwgblN0YXJ0ID0gMDsKICAgICAgICAgICAgICB2YXIgbWFzayA9IGRhdGEucGl4ZWxzLnJlc3VsdE1hc2s7CiAgICAgICAgICAgICAgaWYgKG1hc2spIHsKICAgICAgICAgICAgICAgIGlmIChudW1EaW1zID4gMSkgewogICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtRGltczsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgblN0YXJ0ID0gaSAqIG51bVBpeGVsczsKICAgICAgICAgICAgICAgICAgICBmb3IgKGsgPSAwOyBrIDwgbnVtUGl4ZWxzOyBrKyspIHsKICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXNrW2tdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEucGl4ZWxzLnJlc3VsdFBpeGVsc1tuU3RhcnQgKyBrXSA9IHZhbDsKICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIGZvciAoayA9IDA7IGsgPCBudW1QaXhlbHM7IGsrKykgewogICAgICAgICAgICAgICAgICAgIGlmIChtYXNrW2tdKSB7CiAgICAgICAgICAgICAgICAgICAgICBkYXRhLnBpeGVscy5yZXN1bHRQaXhlbHNba10gPSB2YWw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGlmIChkYXRhLnBpeGVscy5yZXN1bHRQaXhlbHMuZmlsbCkgewogICAgICAgICAgICAgICAgICBkYXRhLnBpeGVscy5yZXN1bHRQaXhlbHMuZmlsbCh2YWwpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgZm9yIChrID0gMDsgayA8IG51bVBpeGVsQWxsRGltczsgaysrKSB7CiAgICAgICAgICAgICAgICAgICAgZGF0YS5waXhlbHMucmVzdWx0UGl4ZWxzW2tdID0gdmFsOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfSwKICAgICAgICAgICAgZ2V0RGF0YVR5cGVBcnJheTogZnVuY3Rpb24odCkgewogICAgICAgICAgICAgIHZhciB0cDsKICAgICAgICAgICAgICBzd2l0Y2ggKHQpIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgdHAgPSBJbnQ4QXJyYXk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICB0cCA9IFVpbnQ4QXJyYXk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgICB0cCA9IEludDE2QXJyYXk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICAgICAgICB0cCA9IFVpbnQxNkFycmF5OwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgNDoKICAgICAgICAgICAgICAgICAgdHAgPSBJbnQzMkFycmF5OwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgNToKICAgICAgICAgICAgICAgICAgdHAgPSBVaW50MzJBcnJheTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDY6CiAgICAgICAgICAgICAgICAgIHRwID0gRmxvYXQzMkFycmF5OwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgNzoKICAgICAgICAgICAgICAgICAgdHAgPSBGbG9hdDY0QXJyYXk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgdHAgPSBGbG9hdDMyQXJyYXk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiB0cDsKICAgICAgICAgICAgfSwKICAgICAgICAgICAgZ2V0UGl4ZWxUeXBlOiBmdW5jdGlvbih0KSB7CiAgICAgICAgICAgICAgdmFyIHRwOwogICAgICAgICAgICAgIHN3aXRjaCAodCkgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICB0cCA9ICJTOCI7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICB0cCA9ICJVOCI7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgICB0cCA9ICJTMTYiOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgICAgICAgdHAgPSAiVTE2IjsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDQ6CiAgICAgICAgICAgICAgICAgIHRwID0gIlMzMiI7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSA1OgogICAgICAgICAgICAgICAgICB0cCA9ICJVMzIiOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgNjoKICAgICAgICAgICAgICAgICAgdHAgPSAiRjMyIjsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDc6CiAgICAgICAgICAgICAgICAgIHRwID0gIkY2NCI7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgdHAgPSAiRjMyIjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIHRwOwogICAgICAgICAgICB9LAogICAgICAgICAgICBpc1ZhbGlkUGl4ZWxWYWx1ZTogZnVuY3Rpb24odCwgdmFsKSB7CiAgICAgICAgICAgICAgaWYgKHZhbCA9PSBudWxsKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHZhciBpc1ZhbGlkOwogICAgICAgICAgICAgIHN3aXRjaCAodCkgewogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICBpc1ZhbGlkID0gdmFsID49IC0xMjggJiYgdmFsIDw9IDEyNzsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICAgIGlzVmFsaWQgPSB2YWwgPj0gMCAmJiB2YWwgPD0gMjU1OwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgICAgICAgaXNWYWxpZCA9IHZhbCA+PSAtMzI3NjggJiYgdmFsIDw9IDMyNzY3OwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgICAgICAgaXNWYWxpZCA9IHZhbCA+PSAwICYmIHZhbCA8PSA2NTUzNjsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDQ6CiAgICAgICAgICAgICAgICAgIGlzVmFsaWQgPSB2YWwgPj0gLTIxNDc0ODM2NDggJiYgdmFsIDw9IDIxNDc0ODM2NDc7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSA1OgogICAgICAgICAgICAgICAgICBpc1ZhbGlkID0gdmFsID49IDAgJiYgdmFsIDw9IDQyOTQ5NjcyOTY7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSA2OgogICAgICAgICAgICAgICAgICBpc1ZhbGlkID0gdmFsID49IC0zNDAyNzk5OTM4NzkwMTQ4NGUyMiAmJiB2YWwgPD0gMzQwMjc5OTkzODc5MDE0ODRlMjI7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSA3OgogICAgICAgICAgICAgICAgICBpc1ZhbGlkID0gdmFsID49IDVlLTMyNCAmJiB2YWwgPD0gMTc5NzY5MzEzNDg2MjMxNTdlMjkyOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgIGlzVmFsaWQgPSBmYWxzZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWQ7CiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGdldERhdGFUeXBlU2l6ZTogZnVuY3Rpb24odCkgewogICAgICAgICAgICAgIHZhciBzID0gMDsKICAgICAgICAgICAgICBzd2l0Y2ggKHQpIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIC8vdWJ5dGUKICAgICAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICAgICAgcyA9IDE7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgLy9zaG9ydAogICAgICAgICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICAgICAgICBzID0gMjsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDQ6CiAgICAgICAgICAgICAgICBjYXNlIDU6CiAgICAgICAgICAgICAgICBjYXNlIDY6CiAgICAgICAgICAgICAgICAgIHMgPSA0OwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgNzoKICAgICAgICAgICAgICAgICAgcyA9IDg7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgcyA9IHQ7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiBzOwogICAgICAgICAgICB9LAogICAgICAgICAgICBnZXREYXRhVHlwZVVzZWQ6IGZ1bmN0aW9uKGR0LCB0YykgewogICAgICAgICAgICAgIHZhciB0ID0gZHQ7CiAgICAgICAgICAgICAgc3dpdGNoIChkdCkgewogICAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgLy9zaG9ydAogICAgICAgICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICAgICAgICB0ID0gZHQgLSB0YzsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgICAgICAvL3VzaG9ydAogICAgICAgICAgICAgICAgY2FzZSA1OgogICAgICAgICAgICAgICAgICB0ID0gZHQgLSAyICogdGM7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSA2OgogICAgICAgICAgICAgICAgICBpZiAoMCA9PT0gdGMpIHsKICAgICAgICAgICAgICAgICAgICB0ID0gZHQ7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoMSA9PT0gdGMpIHsKICAgICAgICAgICAgICAgICAgICB0ID0gMjsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB0ID0gMTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgNzoKICAgICAgICAgICAgICAgICAgaWYgKDAgPT09IHRjKSB7CiAgICAgICAgICAgICAgICAgICAgdCA9IGR0OwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIHQgPSBkdCAtIDIgKiB0YyArIDE7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICB0ID0gZHQ7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gdDsKICAgICAgICAgICAgfSwKICAgICAgICAgICAgZ2V0T25lUGl4ZWw6IGZ1bmN0aW9uKGJsb2NrLCBibG9ja1B0ciwgb2Zmc2V0VHlwZSwgdmlldykgewogICAgICAgICAgICAgIHZhciB0ZW1wID0gMDsKICAgICAgICAgICAgICBzd2l0Y2ggKG9mZnNldFR5cGUpIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgdGVtcCA9IHZpZXcuZ2V0SW50OChibG9ja1B0cik7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICB0ZW1wID0gdmlldy5nZXRVaW50OChibG9ja1B0cik7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgICB0ZW1wID0gdmlldy5nZXRJbnQxNihibG9ja1B0ciwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICAgICAgICB0ZW1wID0gdmlldy5nZXRVaW50MTYoYmxvY2tQdHIsIHRydWUpOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgNDoKICAgICAgICAgICAgICAgICAgdGVtcCA9IHZpZXcuZ2V0SW50MzIoYmxvY2tQdHIsIHRydWUpOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgNToKICAgICAgICAgICAgICAgICAgdGVtcCA9IHZpZXcuZ2V0VUludDMyKGJsb2NrUHRyLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDY6CiAgICAgICAgICAgICAgICAgIHRlbXAgPSB2aWV3LmdldEZsb2F0MzIoYmxvY2tQdHIsIHRydWUpOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgNzoKICAgICAgICAgICAgICAgICAgdGVtcCA9IHZpZXcuZ2V0RmxvYXQ2NChibG9ja1B0ciwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgdGhyb3cgInRoZSBkZWNvZGVyIGRvZXMgbm90IHVuZGVyc3RhbmQgdGhpcyBwaXhlbCB0eXBlIjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIHRlbXA7CiAgICAgICAgICAgIH0KICAgICAgICAgIH07CiAgICAgICAgICB2YXIgVHJlZU5vZGUgPSBmdW5jdGlvbih2YWwsIGxlZnQsIHJpZ2h0KSB7CiAgICAgICAgICAgIHRoaXMudmFsID0gdmFsOwogICAgICAgICAgICB0aGlzLmxlZnQgPSBsZWZ0OwogICAgICAgICAgICB0aGlzLnJpZ2h0ID0gcmlnaHQ7CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIExlcmMyRGVjb2RlMiA9IHsKICAgICAgICAgICAgLyoKICAgICAgICAgICAgKiAqKioqKioqKnJlbW92ZWQgb3B0aW9ucyBjb21wYXJlZCB0byBMRVJDMS4gV2UgY2FuIGJyaW5nIHNvbWUgb2YgdGhlbSBiYWNrIGlmIG5lZWRlZC4KICAgICAgICAgICAgICogcmVtb3ZlZCBwaXhlbCB0eXBlLiBMRVJDMiBpcyB0eXBlZCBhbmQgZG9lc24ndCByZXF1aXJlIHVzZXIgdG8gZ2l2ZSBwaXhlbCB0eXBlCiAgICAgICAgICAgICAqIGNoYW5nZWQgZW5jb2RlZE1hc2tEYXRhIHRvIG1hc2tEYXRhLiBMRVJDMiAncyBqcyB2ZXJzaW9uIG1ha2UgaXQgZmFzdGVyIHRvIHVzZSBtYXNrRGF0YSBkaXJlY3RseS4KICAgICAgICAgICAgICogcmVtb3ZlZCByZXR1cm5NYXNrLiBtYXNrIGlzIHVzZWQgYnkgTEVSQzIgaW50ZXJuYWxseSBhbmQgaXMgY29zdCBmcmVlLiBJbiBjYXNlIG9mIHVzZXIgaW5wdXQgbWFzaywgaXQncyByZXR1cm5lZCBhcyB3ZWxsIGFuZCBoYXMgbmVnbGlibGUgY29zdC4KICAgICAgICAgICAgICogcmVtb3ZlZCBub2RhdGF2YWx1ZS4gQmVjYXVzZSBMRVJDMiBwaXhlbHMgYXJlIHR5cGVkLCBub2RhdGF2YWx1ZSB3aWxsIHNhY3JpZnkgYSB1c2VmdWwgdmFsdWUgZm9yIG1hbnkgdHlwZXMgKDhiaXQsIDE2Yml0KSBldGMsCiAgICAgICAgICAgICAqICAgICAgIHVzZXIgaGFzIHRvIGJlIGtub3dsZWRnYWJsZSBlbm91Z2ggYWJvdXQgcmFzdGVyIGFuZCB0aGVpciBkYXRhIHRvIGF2b2lkIHVzYWJpbGl0eSBpc3N1ZXMuIHNvIG5vZGF0YSB2YWx1ZSBpcyBzaW1wbHkgcmVtb3ZlZCBub3cuCiAgICAgICAgICAgICAqICAgICAgIFdlIGNhbiBhZGQgaXQgYmFjayBsYXRlciBpZiB0aGVpcidzIGEgY2xlYXIgcmVxdWlyZW1lbnQuCiAgICAgICAgICAgICAqIHJlbW92ZWQgZW5jb2RlZE1hc2suIFRoaXMgb3B0aW9uIHdhcyBub3QgaW1wbGVtZW50ZWQgaW4gTGVyY0RlY29kZS4gSXQgY2FuIGJlIGRvbmUgYWZ0ZXIgZGVjb2RpbmcgKGxlc3MgZWZmaWNpZW50KQogICAgICAgICAgICAgKiByZW1vdmVkIGNvbXB1dGVVc2VkQml0RGVwdGhzLgogICAgICAgICAgICAgKgogICAgICAgICAgICAgKgogICAgICAgICAgICAgKiByZXNwb25zZSBjaGFuZ2VzIGNvbXBhcmVkIHRvIExFUkMxCiAgICAgICAgICAgICAqIDEuIGVuY29kZWRNYXNrRGF0YSBpcyBub3QgYXZhaWxhYmxlCiAgICAgICAgICAgICAqIDIuIG5vRGF0YVZhbHVlIGlzIG9wdGlvbmFsIChyZXR1cm5zIG9ubHkgaWYgdXNlcidzIG5vRGF0YVZhbHVlIGlzIHdpdGggaW4gdGhlIHZhbGlkIGRhdGEgdHlwZSByYW5nZSkKICAgICAgICAgICAgICogMy4gbWFza0RhdGEgaXMgYWx3YXlzIGF2YWlsYWJsZQogICAgICAgICAgICAqLwogICAgICAgICAgICAvKioqKioqKioqKioqKioqKioKICAgICAgICAgICAgKiAgcHVibGljIHByb3BlcnRpZXMKICAgICAgICAgICAgKioqKioqKioqKioqKioqKioqLwogICAgICAgICAgICAvL0hVRkZNQU5fTFVUX0JJVFNfTUFYOiAxMiwgLy91c2UgMl4xMiBsdXQsIG5vdCBjb25maWd1cmFibGUKICAgICAgICAgICAgLyoqKioqKioqKioqKioqKioqCiAgICAgICAgICAgICogIHB1YmxpYyBtZXRob2RzCiAgICAgICAgICAgICoqKioqKioqKioqKioqKioqLwogICAgICAgICAgICAvKioKICAgICAgICAgICAgICogRGVjb2RlIGEgTEVSQzIgYnl0ZSBzdHJlYW0gYW5kIHJldHVybiBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgcGl4ZWwgZGF0YSBhbmQgb3B0aW9uYWwgbWV0YWRhdGEuCiAgICAgICAgICAgICAqCiAgICAgICAgICAgICAqIEBwYXJhbSB7QXJyYXlCdWZmZXJ9IGlucHV0IFRoZSBMRVJDIGlucHV0IGJ5dGUgc3RyZWFtCiAgICAgICAgICAgICAqIEBwYXJhbSB7b2JqZWN0fSBbb3B0aW9uc10gb3B0aW9ucyBEZWNvZGluZyBvcHRpb25zCiAgICAgICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5pbnB1dE9mZnNldF0gVGhlIG51bWJlciBvZiBieXRlcyB0byBza2lwIGluIHRoZSBpbnB1dCBieXRlIHN0cmVhbS4gQSB2YWxpZCBMRVJDIGZpbGUgaXMgZXhwZWN0ZWQgYXQgdGhhdCBwb3NpdGlvbgogICAgICAgICAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLnJldHVybkZpbGVJbmZvXSBJZiB0cnVlLCB0aGUgcmV0dXJuIHZhbHVlIHdpbGwgaGF2ZSBhIGZpbGVJbmZvIHByb3BlcnR5IHRoYXQgY29udGFpbnMgbWV0YWRhdGEgb2J0YWluZWQgZnJvbSB0aGUgTEVSQyBoZWFkZXJzIGFuZCB0aGUgZGVjb2RpbmcgcHJvY2VzcwogICAgICAgICAgICAgKi8KICAgICAgICAgICAgZGVjb2RlOiBmdW5jdGlvbihpbnB1dCwgb3B0aW9ucykgewogICAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9OwogICAgICAgICAgICAgIHZhciBub0RhdGFWYWx1ZSA9IG9wdGlvbnMubm9EYXRhVmFsdWU7CiAgICAgICAgICAgICAgdmFyIGkgPSAwLCBkYXRhID0ge307CiAgICAgICAgICAgICAgZGF0YS5wdHIgPSBvcHRpb25zLmlucHV0T2Zmc2V0IHx8IDA7CiAgICAgICAgICAgICAgZGF0YS5waXhlbHMgPSB7fTsKICAgICAgICAgICAgICBpZiAoIUxlcmMySGVscGVycy5yZWFkSGVhZGVySW5mbyhpbnB1dCwgZGF0YSkpIHsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmFyIGhlYWRlckluZm8gPSBkYXRhLmhlYWRlckluZm87CiAgICAgICAgICAgICAgdmFyIGZpbGVWZXJzaW9uID0gaGVhZGVySW5mby5maWxlVmVyc2lvbjsKICAgICAgICAgICAgICB2YXIgT3V0UGl4ZWxUeXBlQXJyYXkgPSBMZXJjMkhlbHBlcnMuZ2V0RGF0YVR5cGVBcnJheShoZWFkZXJJbmZvLmltYWdlVHlwZSk7CiAgICAgICAgICAgICAgTGVyYzJIZWxwZXJzLnJlYWRNYXNrKGlucHV0LCBkYXRhKTsKICAgICAgICAgICAgICBpZiAoaGVhZGVySW5mby5udW1WYWxpZFBpeGVsICE9PSBoZWFkZXJJbmZvLndpZHRoICogaGVhZGVySW5mby5oZWlnaHQgJiYgIWRhdGEucGl4ZWxzLnJlc3VsdE1hc2spIHsKICAgICAgICAgICAgICAgIGRhdGEucGl4ZWxzLnJlc3VsdE1hc2sgPSBvcHRpb25zLm1hc2tEYXRhOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB2YXIgbnVtUGl4ZWxzID0gaGVhZGVySW5mby53aWR0aCAqIGhlYWRlckluZm8uaGVpZ2h0OwogICAgICAgICAgICAgIGRhdGEucGl4ZWxzLnJlc3VsdFBpeGVscyA9IG5ldyBPdXRQaXhlbFR5cGVBcnJheShudW1QaXhlbHMgKiBoZWFkZXJJbmZvLm51bURpbXMpOwogICAgICAgICAgICAgIGRhdGEuY291bnRlciA9IHsKICAgICAgICAgICAgICAgIG9uZXN3ZWVwOiAwLAogICAgICAgICAgICAgICAgdW5jb21wcmVzc2VkOiAwLAogICAgICAgICAgICAgICAgbHV0OiAwLAogICAgICAgICAgICAgICAgYml0c3R1ZmZlcjogMCwKICAgICAgICAgICAgICAgIGNvbnN0YW50OiAwLAogICAgICAgICAgICAgICAgY29uc3RhbnRvZmZzZXQ6IDAKICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgIGlmIChoZWFkZXJJbmZvLm51bVZhbGlkUGl4ZWwgIT09IDApIHsKICAgICAgICAgICAgICAgIGlmIChoZWFkZXJJbmZvLnpNYXggPT09IGhlYWRlckluZm8uek1pbikgewogICAgICAgICAgICAgICAgICBMZXJjMkhlbHBlcnMuY29uc3RydWN0Q29uc3RhbnRTdXJmYWNlKGRhdGEpOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChmaWxlVmVyc2lvbiA+PSA0ICYmIExlcmMySGVscGVycy5jaGVja01pbk1heFJhbmdlcyhpbnB1dCwgZGF0YSkpIHsKICAgICAgICAgICAgICAgICAgTGVyYzJIZWxwZXJzLmNvbnN0cnVjdENvbnN0YW50U3VyZmFjZShkYXRhKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIHZhciB2aWV3ID0gbmV3IERhdGFWaWV3KGlucHV0LCBkYXRhLnB0ciwgMik7CiAgICAgICAgICAgICAgICAgIHZhciBiUmVhZERhdGFPbmVTd2VlcCA9IHZpZXcuZ2V0VWludDgoMCk7CiAgICAgICAgICAgICAgICAgIGRhdGEucHRyKys7CiAgICAgICAgICAgICAgICAgIGlmIChiUmVhZERhdGFPbmVTd2VlcCkgewogICAgICAgICAgICAgICAgICAgIExlcmMySGVscGVycy5yZWFkRGF0YU9uZVN3ZWVwKGlucHV0LCBkYXRhLCBPdXRQaXhlbFR5cGVBcnJheSk7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGVWZXJzaW9uID4gMSAmJiBoZWFkZXJJbmZvLmltYWdlVHlwZSA8PSAxICYmIE1hdGguYWJzKGhlYWRlckluZm8ubWF4WkVycm9yIC0gMC41KSA8IDFlLTUpIHsKICAgICAgICAgICAgICAgICAgICAgIHZhciBmbGFnSHVmZm1hbiA9IHZpZXcuZ2V0VWludDgoMSk7CiAgICAgICAgICAgICAgICAgICAgICBkYXRhLnB0cisrOwogICAgICAgICAgICAgICAgICAgICAgZGF0YS5lbmNvZGVNb2RlID0gZmxhZ0h1ZmZtYW47CiAgICAgICAgICAgICAgICAgICAgICBpZiAoZmxhZ0h1ZmZtYW4gPiAyIHx8IGZpbGVWZXJzaW9uIDwgNCAmJiBmbGFnSHVmZm1hbiA+IDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgIkludmFsaWQgSHVmZm1hbiBmbGFnICIgKyBmbGFnSHVmZm1hbjsKICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIGlmIChmbGFnSHVmZm1hbikgewogICAgICAgICAgICAgICAgICAgICAgICBMZXJjMkhlbHBlcnMucmVhZEh1ZmZtYW4oaW5wdXQsIGRhdGEsIE91dFBpeGVsVHlwZUFycmF5KTsKICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIExlcmMySGVscGVycy5yZWFkVGlsZXMoaW5wdXQsIGRhdGEsIE91dFBpeGVsVHlwZUFycmF5KTsKICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgTGVyYzJIZWxwZXJzLnJlYWRUaWxlcyhpbnB1dCwgZGF0YSwgT3V0UGl4ZWxUeXBlQXJyYXkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBkYXRhLmVvZk9mZnNldCA9IGRhdGEucHRyOwogICAgICAgICAgICAgIHZhciBkaWZmOwogICAgICAgICAgICAgIGlmIChvcHRpb25zLmlucHV0T2Zmc2V0KSB7CiAgICAgICAgICAgICAgICBkaWZmID0gZGF0YS5oZWFkZXJJbmZvLmJsb2JTaXplICsgb3B0aW9ucy5pbnB1dE9mZnNldCAtIGRhdGEucHRyOwogICAgICAgICAgICAgICAgaWYgKE1hdGguYWJzKGRpZmYpID49IDEpIHsKICAgICAgICAgICAgICAgICAgZGF0YS5lb2ZPZmZzZXQgPSBvcHRpb25zLmlucHV0T2Zmc2V0ICsgZGF0YS5oZWFkZXJJbmZvLmJsb2JTaXplOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBkaWZmID0gZGF0YS5oZWFkZXJJbmZvLmJsb2JTaXplIC0gZGF0YS5wdHI7CiAgICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMoZGlmZikgPj0gMSkgewogICAgICAgICAgICAgICAgICBkYXRhLmVvZk9mZnNldCA9IGRhdGEuaGVhZGVySW5mby5ibG9iU2l6ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHsKICAgICAgICAgICAgICAgIHdpZHRoOiBoZWFkZXJJbmZvLndpZHRoLAogICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWFkZXJJbmZvLmhlaWdodCwKICAgICAgICAgICAgICAgIHBpeGVsRGF0YTogZGF0YS5waXhlbHMucmVzdWx0UGl4ZWxzLAogICAgICAgICAgICAgICAgbWluVmFsdWU6IGhlYWRlckluZm8uek1pbiwKICAgICAgICAgICAgICAgIG1heFZhbHVlOiBoZWFkZXJJbmZvLnpNYXgsCiAgICAgICAgICAgICAgICB2YWxpZFBpeGVsQ291bnQ6IGhlYWRlckluZm8ubnVtVmFsaWRQaXhlbCwKICAgICAgICAgICAgICAgIGRpbUNvdW50OiBoZWFkZXJJbmZvLm51bURpbXMsCiAgICAgICAgICAgICAgICBkaW1TdGF0czogewogICAgICAgICAgICAgICAgICBtaW5WYWx1ZXM6IGhlYWRlckluZm8ubWluVmFsdWVzLAogICAgICAgICAgICAgICAgICBtYXhWYWx1ZXM6IGhlYWRlckluZm8ubWF4VmFsdWVzCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgbWFza0RhdGE6IGRhdGEucGl4ZWxzLnJlc3VsdE1hc2sKICAgICAgICAgICAgICAgIC8vbm9EYXRhVmFsdWU6IG5vRGF0YVZhbHVlCiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICBpZiAoZGF0YS5waXhlbHMucmVzdWx0TWFzayAmJiBMZXJjMkhlbHBlcnMuaXNWYWxpZFBpeGVsVmFsdWUoaGVhZGVySW5mby5pbWFnZVR5cGUsIG5vRGF0YVZhbHVlKSkgewogICAgICAgICAgICAgICAgdmFyIG1hc2sgPSBkYXRhLnBpeGVscy5yZXN1bHRNYXNrOwogICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IG51bVBpeGVsczsgaSsrKSB7CiAgICAgICAgICAgICAgICAgIGlmICghbWFza1tpXSkgewogICAgICAgICAgICAgICAgICAgIHJlc3VsdC5waXhlbERhdGFbaV0gPSBub0RhdGFWYWx1ZTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmVzdWx0Lm5vRGF0YVZhbHVlID0gbm9EYXRhVmFsdWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGRhdGEubm9EYXRhVmFsdWUgPSBub0RhdGFWYWx1ZTsKICAgICAgICAgICAgICBpZiAob3B0aW9ucy5yZXR1cm5GaWxlSW5mbykgewogICAgICAgICAgICAgICAgcmVzdWx0LmZpbGVJbmZvID0gTGVyYzJIZWxwZXJzLmZvcm1hdEZpbGVJbmZvKGRhdGEpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgICAgICB9LAogICAgICAgICAgICBnZXRCYW5kQ291bnQ6IGZ1bmN0aW9uKGlucHV0KSB7CiAgICAgICAgICAgICAgdmFyIGNvdW50ID0gMDsKICAgICAgICAgICAgICB2YXIgaSA9IDA7CiAgICAgICAgICAgICAgdmFyIHRlbXAgPSB7fTsKICAgICAgICAgICAgICB0ZW1wLnB0ciA9IDA7CiAgICAgICAgICAgICAgdGVtcC5waXhlbHMgPSB7fTsKICAgICAgICAgICAgICB3aGlsZSAoaSA8IGlucHV0LmJ5dGVMZW5ndGggLSA1OCkgewogICAgICAgICAgICAgICAgTGVyYzJIZWxwZXJzLnJlYWRIZWFkZXJJbmZvKGlucHV0LCB0ZW1wKTsKICAgICAgICAgICAgICAgIGkgKz0gdGVtcC5oZWFkZXJJbmZvLmJsb2JTaXplOwogICAgICAgICAgICAgICAgY291bnQrKzsKICAgICAgICAgICAgICAgIHRlbXAucHRyID0gaTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIGNvdW50OwogICAgICAgICAgICB9CiAgICAgICAgICB9OwogICAgICAgICAgcmV0dXJuIExlcmMyRGVjb2RlMjsKICAgICAgICB9KSgpOwogICAgICAgIHZhciBpc1BsYXRmb3JtTGl0dGxlRW5kaWFuID0gKGZ1bmN0aW9uKCkgewogICAgICAgICAgdmFyIGEzID0gbmV3IEFycmF5QnVmZmVyKDQpOwogICAgICAgICAgdmFyIGIgPSBuZXcgVWludDhBcnJheShhMyk7CiAgICAgICAgICB2YXIgYyA9IG5ldyBVaW50MzJBcnJheShhMyk7CiAgICAgICAgICBjWzBdID0gMTsKICAgICAgICAgIHJldHVybiBiWzBdID09PSAxOwogICAgICAgIH0pKCk7CiAgICAgICAgdmFyIExlcmMyID0gewogICAgICAgICAgLyoqKioqKioqKioqKndyYXBwZXIqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwogICAgICAgICAgLyoqCiAgICAgICAgICAgKiBBIHdyYXBwZXIgZm9yIGRlY29kaW5nIGJvdGggTEVSQzEgYW5kIExFUkMyIGJ5dGUgc3RyZWFtcyBjYXBhYmxlIG9mIGhhbmRsaW5nIG11bHRpYmFuZCBwaXhlbCBibG9ja3MgZm9yIHZhcmlvdXMgcGl4ZWwgdHlwZXMuCiAgICAgICAgICAgKgogICAgICAgICAgICogQGFsaWFzIG1vZHVsZTpMZXJjCiAgICAgICAgICAgKiBAcGFyYW0ge0FycmF5QnVmZmVyfSBpbnB1dCBUaGUgTEVSQyBpbnB1dCBieXRlIHN0cmVhbQogICAgICAgICAgICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXSBUaGUgZGVjb2Rpbmcgb3B0aW9ucyBiZWxvdyBhcmUgb3B0aW9uYWwuCiAgICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMuaW5wdXRPZmZzZXRdIFRoZSBudW1iZXIgb2YgYnl0ZXMgdG8gc2tpcCBpbiB0aGUgaW5wdXQgYnl0ZSBzdHJlYW0uIEEgdmFsaWQgTGVyYyBmaWxlIGlzIGV4cGVjdGVkIGF0IHRoYXQgcG9zaXRpb24uCiAgICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdGlvbnMucGl4ZWxUeXBlXSAoTEVSQzEgb25seSkgRGVmYXVsdCB2YWx1ZSBpcyBGMzIuIFZhbGlkIHBpeGVsIHR5cGVzIGZvciBpbnB1dCBhcmUgVTgvUzgvUzE2L1UxNi9TMzIvVTMyL0YzMi4KICAgICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5ub0RhdGFWYWx1ZV0gKExFUkMxIG9ubHkpLiBJdCBpcyByZWNvbW1lbmRlZCB0byB1c2UgdGhlIHJldHVybmVkIG1hc2sgaW5zdGVhZCBvZiBzZXR0aW5nIHRoaXMgdmFsdWUuCiAgICAgICAgICAgKiBAcmV0dXJucyB7e3dpZHRoLCBoZWlnaHQsIHBpeGVscywgcGl4ZWxUeXBlLCBtYXNrLCBzdGF0aXN0aWNzfX0KICAgICAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IHdpZHRoIFdpZHRoIG9mIGRlY29kZWQgaW1hZ2UuCiAgICAgICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBoZWlnaHQgSGVpZ2h0IG9mIGRlY29kZWQgaW1hZ2UuCiAgICAgICAgICAgICAqIEBwcm9wZXJ0eSB7YXJyYXl9IHBpeGVscyBbYmFuZDEsIGJhbmQyLCDigKZdIEVhY2ggYmFuZCBpcyBhIHR5cGVkIGFycmF5IG9mIHdpZHRoKmhlaWdodC4KICAgICAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd9IHBpeGVsVHlwZSBUaGUgdHlwZSBvZiBwaXhlbHMgcmVwcmVzZW50ZWQgaW4gdGhlIG91dHB1dC4KICAgICAgICAgICAgICogQHByb3BlcnR5IHttYXNrfSBtYXNrIFR5cGVkIGFycmF5IHdpdGggYSBzaXplIG9mIHdpZHRoKmhlaWdodCwgb3IgbnVsbCBpZiBhbGwgcGl4ZWxzIGFyZSB2YWxpZC4KICAgICAgICAgICAgICogQHByb3BlcnR5IHthcnJheX0gc3RhdGlzdGljcyBbc3RhdGlzdGljc19iYW5kMSwgc3RhdGlzdGljc19iYW5kMiwg4oCmXSBFYWNoIGVsZW1lbnQgaXMgYSBzdGF0aXN0aWNzIG9iamVjdCByZXByZXNlbnRpbmcgbWluIGFuZCBtYXggdmFsdWVzCiAgICAgICAgICAqKi8KICAgICAgICAgIGRlY29kZTogZnVuY3Rpb24oZW5jb2RlZERhdGEsIG9wdGlvbnMpIHsKICAgICAgICAgICAgaWYgKCFpc1BsYXRmb3JtTGl0dGxlRW5kaWFuKSB7CiAgICAgICAgICAgICAgdGhyb3cgIkJpZyBlbmRpYW4gc3lzdGVtIGlzIG5vdCBzdXBwb3J0ZWQuIjsKICAgICAgICAgICAgfQogICAgICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTsKICAgICAgICAgICAgdmFyIGlucHV0T2Zmc2V0ID0gb3B0aW9ucy5pbnB1dE9mZnNldCB8fCAwOwogICAgICAgICAgICB2YXIgZmlsZUlkVmlldyA9IG5ldyBVaW50OEFycmF5KGVuY29kZWREYXRhLCBpbnB1dE9mZnNldCwgMTApOwogICAgICAgICAgICB2YXIgZmlsZUlkZW50aWZpZXJTdHJpbmcgPSBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIGZpbGVJZFZpZXcpOwogICAgICAgICAgICB2YXIgbGVyYywgbWFqb3JWZXJzaW9uOwogICAgICAgICAgICBpZiAoZmlsZUlkZW50aWZpZXJTdHJpbmcudHJpbSgpID09PSAiQ250WkltYWdlIikgewogICAgICAgICAgICAgIGxlcmMgPSBMZXJjRGVjb2RlOwogICAgICAgICAgICAgIG1ham9yVmVyc2lvbiA9IDE7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoZmlsZUlkZW50aWZpZXJTdHJpbmcuc3Vic3RyaW5nKDAsIDUpID09PSAiTGVyYzIiKSB7CiAgICAgICAgICAgICAgbGVyYyA9IExlcmMyRGVjb2RlOwogICAgICAgICAgICAgIG1ham9yVmVyc2lvbiA9IDI7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdGhyb3cgIlVuZXhwZWN0ZWQgZmlsZSBpZGVudGlmaWVyIHN0cmluZzogIiArIGZpbGVJZGVudGlmaWVyU3RyaW5nOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBpUGxhbmUgPSAwLCBlb2YgPSBlbmNvZGVkRGF0YS5ieXRlTGVuZ3RoIC0gMTAsIGVuY29kZWRNYXNrRGF0YSwgYmFuZE1hc2tzID0gW10sIGJhbmRNYXNrLCBtYXNrRGF0YTsKICAgICAgICAgICAgdmFyIGRlY29kZWRQaXhlbEJsb2NrID0gewogICAgICAgICAgICAgIHdpZHRoOiAwLAogICAgICAgICAgICAgIGhlaWdodDogMCwKICAgICAgICAgICAgICBwaXhlbHM6IFtdLAogICAgICAgICAgICAgIHBpeGVsVHlwZTogb3B0aW9ucy5waXhlbFR5cGUsCiAgICAgICAgICAgICAgbWFzazogbnVsbCwKICAgICAgICAgICAgICBzdGF0aXN0aWNzOiBbXQogICAgICAgICAgICB9OwogICAgICAgICAgICB3aGlsZSAoaW5wdXRPZmZzZXQgPCBlb2YpIHsKICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gbGVyYy5kZWNvZGUoZW5jb2RlZERhdGEsIHsKICAgICAgICAgICAgICAgIGlucHV0T2Zmc2V0LAogICAgICAgICAgICAgICAgLy9mb3IgYm90aCBsZXJjMSBhbmQgbGVyYzIKICAgICAgICAgICAgICAgIGVuY29kZWRNYXNrRGF0YSwKICAgICAgICAgICAgICAgIC8vbGVyYzEgb25seQogICAgICAgICAgICAgICAgbWFza0RhdGEsCiAgICAgICAgICAgICAgICAvL2xlcmMyIG9ubHkKICAgICAgICAgICAgICAgIHJldHVybk1hc2s6IGlQbGFuZSA9PT0gMCA/IHRydWUgOiBmYWxzZSwKICAgICAgICAgICAgICAgIC8vbGVyYzEgb25seQogICAgICAgICAgICAgICAgcmV0dXJuRW5jb2RlZE1hc2s6IGlQbGFuZSA9PT0gMCA/IHRydWUgOiBmYWxzZSwKICAgICAgICAgICAgICAgIC8vbGVyYzEgb25seQogICAgICAgICAgICAgICAgcmV0dXJuRmlsZUluZm86IHRydWUsCiAgICAgICAgICAgICAgICAvL2ZvciBib3RoIGxlcmMxIGFuZCBsZXJjMgogICAgICAgICAgICAgICAgcGl4ZWxUeXBlOiBvcHRpb25zLnBpeGVsVHlwZSB8fCBudWxsLAogICAgICAgICAgICAgICAgLy9sZXJjMSBvbmx5CiAgICAgICAgICAgICAgICBub0RhdGFWYWx1ZTogb3B0aW9ucy5ub0RhdGFWYWx1ZSB8fCBudWxsCiAgICAgICAgICAgICAgICAvL2xlcmMxIG9ubHkKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICBpbnB1dE9mZnNldCA9IHJlc3VsdC5maWxlSW5mby5lb2ZPZmZzZXQ7CiAgICAgICAgICAgICAgaWYgKGlQbGFuZSA9PT0gMCkgewogICAgICAgICAgICAgICAgZW5jb2RlZE1hc2tEYXRhID0gcmVzdWx0LmVuY29kZWRNYXNrRGF0YTsKICAgICAgICAgICAgICAgIG1hc2tEYXRhID0gcmVzdWx0Lm1hc2tEYXRhOwogICAgICAgICAgICAgICAgZGVjb2RlZFBpeGVsQmxvY2sud2lkdGggPSByZXN1bHQud2lkdGg7CiAgICAgICAgICAgICAgICBkZWNvZGVkUGl4ZWxCbG9jay5oZWlnaHQgPSByZXN1bHQuaGVpZ2h0OwogICAgICAgICAgICAgICAgZGVjb2RlZFBpeGVsQmxvY2suZGltQ291bnQgPSByZXN1bHQuZGltQ291bnQgfHwgMTsKICAgICAgICAgICAgICAgIGRlY29kZWRQaXhlbEJsb2NrLnBpeGVsVHlwZSA9IHJlc3VsdC5waXhlbFR5cGUgfHwgcmVzdWx0LmZpbGVJbmZvLnBpeGVsVHlwZTsKICAgICAgICAgICAgICAgIGRlY29kZWRQaXhlbEJsb2NrLm1hc2sgPSByZXN1bHQubWFza0RhdGE7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChtYWpvclZlcnNpb24gPiAxICYmIHJlc3VsdC5maWxlSW5mby5tYXNrICYmIHJlc3VsdC5maWxlSW5mby5tYXNrLm51bUJ5dGVzID4gMCkgewogICAgICAgICAgICAgICAgYmFuZE1hc2tzLnB1c2gocmVzdWx0Lm1hc2tEYXRhKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaVBsYW5lKys7CiAgICAgICAgICAgICAgZGVjb2RlZFBpeGVsQmxvY2sucGl4ZWxzLnB1c2gocmVzdWx0LnBpeGVsRGF0YSk7CiAgICAgICAgICAgICAgZGVjb2RlZFBpeGVsQmxvY2suc3RhdGlzdGljcy5wdXNoKHsKICAgICAgICAgICAgICAgIG1pblZhbHVlOiByZXN1bHQubWluVmFsdWUsCiAgICAgICAgICAgICAgICBtYXhWYWx1ZTogcmVzdWx0Lm1heFZhbHVlLAogICAgICAgICAgICAgICAgbm9EYXRhVmFsdWU6IHJlc3VsdC5ub0RhdGFWYWx1ZSwKICAgICAgICAgICAgICAgIGRpbVN0YXRzOiByZXN1bHQuZGltU3RhdHMKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgaSwgaiwgbnVtUGl4ZWxzOwogICAgICAgICAgICBpZiAobWFqb3JWZXJzaW9uID4gMSAmJiBiYW5kTWFza3MubGVuZ3RoID4gMSkgewogICAgICAgICAgICAgIG51bVBpeGVscyA9IGRlY29kZWRQaXhlbEJsb2NrLndpZHRoICogZGVjb2RlZFBpeGVsQmxvY2suaGVpZ2h0OwogICAgICAgICAgICAgIGRlY29kZWRQaXhlbEJsb2NrLmJhbmRNYXNrcyA9IGJhbmRNYXNrczsKICAgICAgICAgICAgICBtYXNrRGF0YSA9IG5ldyBVaW50OEFycmF5KG51bVBpeGVscyk7CiAgICAgICAgICAgICAgbWFza0RhdGEuc2V0KGJhbmRNYXNrc1swXSk7CiAgICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8IGJhbmRNYXNrcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgYmFuZE1hc2sgPSBiYW5kTWFza3NbaV07CiAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbnVtUGl4ZWxzOyBqKyspIHsKICAgICAgICAgICAgICAgICAgbWFza0RhdGFbal0gPSBtYXNrRGF0YVtqXSAmIGJhbmRNYXNrW2pdOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBkZWNvZGVkUGl4ZWxCbG9jay5tYXNrRGF0YSA9IG1hc2tEYXRhOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBkZWNvZGVkUGl4ZWxCbG9jazsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSAiZnVuY3Rpb24iICYmIGRlZmluZS5hbWQpIHsKICAgICAgICAgIGRlZmluZShbXSwgZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBMZXJjMjsKICAgICAgICAgIH0pOwogICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG1vZHVsZSAhPT0gInVuZGVmaW5lZCIgJiYgbW9kdWxlLmV4cG9ydHMpIHsKICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gTGVyYzI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuTGVyYyA9IExlcmMyOwogICAgICAgIH0KICAgICAgfSkoKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVZlcnRpY2VzRnJvbUhlaWdodG1hcC5qcwogIHZhciBjcmVhdGVWZXJ0aWNlc0Zyb21IZWlnaHRtYXBfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZVZlcnRpY2VzRnJvbUhlaWdodG1hcF9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVWZXJ0aWNlc0Zyb21IZWlnaHRtYXBfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGNyZWF0ZVZlcnRpY2VzRnJvbUhlaWdodG1hcChwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICBpZiAocGFyYW1ldGVycy5lbmNvZGluZyA9PT0gSGVpZ2h0bWFwRW5jb2RpbmdfZGVmYXVsdC5MRVJDKSB7CiAgICAgIGxldCByZXN1bHQ7CiAgICAgIHRyeSB7CiAgICAgICAgcmVzdWx0ID0gaW1wb3J0X2xlcmMuZGVmYXVsdC5kZWNvZGUocGFyYW1ldGVycy5oZWlnaHRtYXApOwogICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3JfZGVmYXVsdChlcnJvcik7CiAgICAgIH0KICAgICAgY29uc3QgbGVyY1N0YXRpc3RpY3MgPSByZXN1bHQuc3RhdGlzdGljc1swXTsKICAgICAgaWYgKGxlcmNTdGF0aXN0aWNzLm1pblZhbHVlID09PSBOdW1iZXIuTUFYX1ZBTFVFKSB7CiAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KCJJbnZhbGlkIHRpbGUgZGF0YSIpOwogICAgICB9CiAgICAgIHBhcmFtZXRlcnMuaGVpZ2h0bWFwID0gcmVzdWx0LnBpeGVsc1swXTsKICAgICAgcGFyYW1ldGVycy53aWR0aCA9IHJlc3VsdC53aWR0aDsKICAgICAgcGFyYW1ldGVycy5oZWlnaHQgPSByZXN1bHQuaGVpZ2h0OwogICAgfQogICAgcGFyYW1ldGVycy5lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShwYXJhbWV0ZXJzLmVsbGlwc29pZCk7CiAgICBwYXJhbWV0ZXJzLnJlY3RhbmdsZSA9IFJlY3RhbmdsZV9kZWZhdWx0LmNsb25lKHBhcmFtZXRlcnMucmVjdGFuZ2xlKTsKICAgIGNvbnN0IHN0YXRpc3RpY3MyID0gSGVpZ2h0bWFwVGVzc2VsbGF0b3JfZGVmYXVsdC5jb21wdXRlVmVydGljZXMocGFyYW1ldGVycyk7CiAgICBjb25zdCB2ZXJ0aWNlcyA9IHN0YXRpc3RpY3MyLnZlcnRpY2VzOwogICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKHZlcnRpY2VzLmJ1ZmZlcik7CiAgICByZXR1cm4gewogICAgICB2ZXJ0aWNlczogdmVydGljZXMuYnVmZmVyLAogICAgICBudW1iZXJPZkF0dHJpYnV0ZXM6IHN0YXRpc3RpY3MyLmVuY29kaW5nLnN0cmlkZSwKICAgICAgbWluaW11bUhlaWdodDogc3RhdGlzdGljczIubWluaW11bUhlaWdodCwKICAgICAgbWF4aW11bUhlaWdodDogc3RhdGlzdGljczIubWF4aW11bUhlaWdodCwKICAgICAgZ3JpZFdpZHRoOiBwYXJhbWV0ZXJzLndpZHRoLAogICAgICBncmlkSGVpZ2h0OiBwYXJhbWV0ZXJzLmhlaWdodCwKICAgICAgYm91bmRpbmdTcGhlcmUzRDogc3RhdGlzdGljczIuYm91bmRpbmdTcGhlcmUzRCwKICAgICAgb3JpZW50ZWRCb3VuZGluZ0JveDogc3RhdGlzdGljczIub3JpZW50ZWRCb3VuZGluZ0JveCwKICAgICAgb2NjbHVkZWVQb2ludEluU2NhbGVkU3BhY2U6IHN0YXRpc3RpY3MyLm9jY2x1ZGVlUG9pbnRJblNjYWxlZFNwYWNlLAogICAgICBlbmNvZGluZzogc3RhdGlzdGljczIuZW5jb2RpbmcsCiAgICAgIHdlc3RJbmRpY2VzU291dGhUb05vcnRoOiBzdGF0aXN0aWNzMi53ZXN0SW5kaWNlc1NvdXRoVG9Ob3J0aCwKICAgICAgc291dGhJbmRpY2VzRWFzdFRvV2VzdDogc3RhdGlzdGljczIuc291dGhJbmRpY2VzRWFzdFRvV2VzdCwKICAgICAgZWFzdEluZGljZXNOb3J0aFRvU291dGg6IHN0YXRpc3RpY3MyLmVhc3RJbmRpY2VzTm9ydGhUb1NvdXRoLAogICAgICBub3J0aEluZGljZXNXZXN0VG9FYXN0OiBzdGF0aXN0aWNzMi5ub3J0aEluZGljZXNXZXN0VG9FYXN0CiAgICB9OwogIH0KICB2YXIgaW1wb3J0X2xlcmMsIGNyZWF0ZVZlcnRpY2VzRnJvbUhlaWdodG1hcF9kZWZhdWx0OwogIHZhciBpbml0X2NyZWF0ZVZlcnRpY2VzRnJvbUhlaWdodG1hcCA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlVmVydGljZXNGcm9tSGVpZ2h0bWFwLmpzIigpIHsKICAgICAgaW5pdF9FbGxpcHNvaWQoKTsKICAgICAgaW5pdF9IZWlnaHRtYXBFbmNvZGluZygpOwogICAgICBpbml0X0hlaWdodG1hcFRlc3NlbGxhdG9yKCk7CiAgICAgIGluaXRfUmVjdGFuZ2xlKCk7CiAgICAgIGluaXRfUnVudGltZUVycm9yKCk7CiAgICAgIGltcG9ydF9sZXJjID0gX190b0VTTShyZXF1aXJlX0xlcmNEZWNvZGUoKSwgMSk7CiAgICAgIGluaXRfY3JlYXRlVGFza1Byb2Nlc3NvcldvcmtlcigpOwogICAgICBjcmVhdGVWZXJ0aWNlc0Zyb21IZWlnaHRtYXBfZGVmYXVsdCA9IGNyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXJfZGVmYXVsdChjcmVhdGVWZXJ0aWNlc0Zyb21IZWlnaHRtYXApOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvVGVycmFpblByb3ZpZGVyLmpzCiAgZnVuY3Rpb24gVGVycmFpblByb3ZpZGVyKCkgewogICAgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdC50aHJvd0luc3RhbnRpYXRpb25FcnJvcigpOwogIH0KICBmdW5jdGlvbiBnZXRFZGdlSW5kaWNlcyh3aWR0aCwgaGVpZ2h0KSB7CiAgICBjb25zdCB3ZXN0SW5kaWNlc1NvdXRoVG9Ob3J0aCA9IG5ldyBBcnJheShoZWlnaHQpOwogICAgY29uc3Qgc291dGhJbmRpY2VzRWFzdFRvV2VzdCA9IG5ldyBBcnJheSh3aWR0aCk7CiAgICBjb25zdCBlYXN0SW5kaWNlc05vcnRoVG9Tb3V0aCA9IG5ldyBBcnJheShoZWlnaHQpOwogICAgY29uc3Qgbm9ydGhJbmRpY2VzV2VzdFRvRWFzdCA9IG5ldyBBcnJheSh3aWR0aCk7CiAgICBsZXQgaTsKICAgIGZvciAoaSA9IDA7IGkgPCB3aWR0aDsgKytpKSB7CiAgICAgIG5vcnRoSW5kaWNlc1dlc3RUb0Vhc3RbaV0gPSBpOwogICAgICBzb3V0aEluZGljZXNFYXN0VG9XZXN0W2ldID0gd2lkdGggKiBoZWlnaHQgLSAxIC0gaTsKICAgIH0KICAgIGZvciAoaSA9IDA7IGkgPCBoZWlnaHQ7ICsraSkgewogICAgICBlYXN0SW5kaWNlc05vcnRoVG9Tb3V0aFtpXSA9IChpICsgMSkgKiB3aWR0aCAtIDE7CiAgICAgIHdlc3RJbmRpY2VzU291dGhUb05vcnRoW2ldID0gKGhlaWdodCAtIGkgLSAxKSAqIHdpZHRoOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgd2VzdEluZGljZXNTb3V0aFRvTm9ydGgsCiAgICAgIHNvdXRoSW5kaWNlc0Vhc3RUb1dlc3QsCiAgICAgIGVhc3RJbmRpY2VzTm9ydGhUb1NvdXRoLAogICAgICBub3J0aEluZGljZXNXZXN0VG9FYXN0CiAgICB9OwogIH0KICBmdW5jdGlvbiBhZGRSZWd1bGFyR3JpZEluZGljZXMod2lkdGgsIGhlaWdodCwgaW5kaWNlcywgb2Zmc2V0KSB7CiAgICBsZXQgaW5kZXggPSAwOwogICAgZm9yIChsZXQgaiA9IDA7IGogPCBoZWlnaHQgLSAxOyArK2opIHsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB3aWR0aCAtIDE7ICsraSkgewogICAgICAgIGNvbnN0IHVwcGVyTGVmdCA9IGluZGV4OwogICAgICAgIGNvbnN0IGxvd2VyTGVmdCA9IHVwcGVyTGVmdCArIHdpZHRoOwogICAgICAgIGNvbnN0IGxvd2VyUmlnaHQgPSBsb3dlckxlZnQgKyAxOwogICAgICAgIGNvbnN0IHVwcGVyUmlnaHQgPSB1cHBlckxlZnQgKyAxOwogICAgICAgIGluZGljZXNbb2Zmc2V0KytdID0gdXBwZXJMZWZ0OwogICAgICAgIGluZGljZXNbb2Zmc2V0KytdID0gbG93ZXJMZWZ0OwogICAgICAgIGluZGljZXNbb2Zmc2V0KytdID0gdXBwZXJSaWdodDsKICAgICAgICBpbmRpY2VzW29mZnNldCsrXSA9IHVwcGVyUmlnaHQ7CiAgICAgICAgaW5kaWNlc1tvZmZzZXQrK10gPSBsb3dlckxlZnQ7CiAgICAgICAgaW5kaWNlc1tvZmZzZXQrK10gPSBsb3dlclJpZ2h0OwogICAgICAgICsraW5kZXg7CiAgICAgIH0KICAgICAgKytpbmRleDsKICAgIH0KICB9CiAgZnVuY3Rpb24gYWRkU2tpcnRJbmRpY2VzKGVkZ2VJbmRpY2VzLCB2ZXJ0ZXhJbmRleCwgaW5kaWNlcywgb2Zmc2V0KSB7CiAgICBsZXQgcHJldmlvdXNJbmRleCA9IGVkZ2VJbmRpY2VzWzBdOwogICAgY29uc3QgbGVuZ3RoID0gZWRnZUluZGljZXMubGVuZ3RoOwogICAgZm9yIChsZXQgaSA9IDE7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBjb25zdCBpbmRleCA9IGVkZ2VJbmRpY2VzW2ldOwogICAgICBpbmRpY2VzW29mZnNldCsrXSA9IHByZXZpb3VzSW5kZXg7CiAgICAgIGluZGljZXNbb2Zmc2V0KytdID0gaW5kZXg7CiAgICAgIGluZGljZXNbb2Zmc2V0KytdID0gdmVydGV4SW5kZXg7CiAgICAgIGluZGljZXNbb2Zmc2V0KytdID0gdmVydGV4SW5kZXg7CiAgICAgIGluZGljZXNbb2Zmc2V0KytdID0gaW5kZXg7CiAgICAgIGluZGljZXNbb2Zmc2V0KytdID0gdmVydGV4SW5kZXggKyAxOwogICAgICBwcmV2aW91c0luZGV4ID0gaW5kZXg7CiAgICAgICsrdmVydGV4SW5kZXg7CiAgICB9CiAgICByZXR1cm4gb2Zmc2V0OwogIH0KICB2YXIgcmVndWxhckdyaWRJbmRpY2VzQ2FjaGUsIHJlZ3VsYXJHcmlkQW5kRWRnZUluZGljZXNDYWNoZSwgcmVndWxhckdyaWRBbmRTa2lydEFuZEVkZ2VJbmRpY2VzQ2FjaGUsIFRlcnJhaW5Qcm92aWRlcl9kZWZhdWx0OwogIHZhciBpbml0X1RlcnJhaW5Qcm92aWRlciA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvVGVycmFpblByb3ZpZGVyLmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRGV2ZWxvcGVyRXJyb3IoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhUZXJyYWluUHJvdmlkZXIucHJvdG90eXBlLCB7CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyBhbiBldmVudCB0aGF0IGlzIHJhaXNlZCB3aGVuIHRoZSB0ZXJyYWluIHByb3ZpZGVyIGVuY291bnRlcnMgYW4gYXN5bmNocm9ub3VzIGVycm9yLiAgQnkgc3Vic2NyaWJpbmcKICAgICAgICAgKiB0byB0aGUgZXZlbnQsIHlvdSB3aWxsIGJlIG5vdGlmaWVkIG9mIHRoZSBlcnJvciBhbmQgY2FuIHBvdGVudGlhbGx5IHJlY292ZXIgZnJvbSBpdC4gIEV2ZW50IGxpc3RlbmVycwogICAgICAgICAqIGFyZSBwYXNzZWQgYW4gaW5zdGFuY2Ugb2Yge0BsaW5rIFRpbGVQcm92aWRlckVycm9yfS4KICAgICAgICAgKiBAbWVtYmVyb2YgVGVycmFpblByb3ZpZGVyLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtFdmVudDxUZXJyYWluUHJvdmlkZXIuRXJyb3JFdmVudD59CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgZXJyb3JFdmVudDogewogICAgICAgICAgZ2V0OiBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0LnRocm93SW5zdGFudGlhdGlvbkVycm9yCiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSBjcmVkaXQgdG8gZGlzcGxheSB3aGVuIHRoaXMgdGVycmFpbiBwcm92aWRlciBpcyBhY3RpdmUuICBUeXBpY2FsbHkgdGhpcyBpcyB1c2VkIHRvIGNyZWRpdAogICAgICAgICAqIHRoZSBzb3VyY2Ugb2YgdGhlIHRlcnJhaW4uCiAgICAgICAgICogQG1lbWJlcm9mIFRlcnJhaW5Qcm92aWRlci5wcm90b3R5cGUKICAgICAgICAgKiBAdHlwZSB7Q3JlZGl0fQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIGNyZWRpdDogewogICAgICAgICAgZ2V0OiBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0LnRocm93SW5zdGFudGlhdGlvbkVycm9yCiAgICAgICAgfSwKICAgICAgICAvKioKICAgICAgICAgKiBHZXRzIHRoZSB0aWxpbmcgc2NoZW1lIHVzZWQgYnkgdGhlIHByb3ZpZGVyLgogICAgICAgICAqIEBtZW1iZXJvZiBUZXJyYWluUHJvdmlkZXIucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge1RpbGluZ1NjaGVtZX0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICB0aWxpbmdTY2hlbWU6IHsKICAgICAgICAgIGdldDogRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdC50aHJvd0luc3RhbnRpYXRpb25FcnJvcgogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyBhIHZhbHVlIGluZGljYXRpbmcgd2hldGhlciBvciBub3QgdGhlIHByb3ZpZGVyIGluY2x1ZGVzIGEgd2F0ZXIgbWFzay4gIFRoZSB3YXRlciBtYXNrCiAgICAgICAgICogaW5kaWNhdGVzIHdoaWNoIGFyZWFzIG9mIHRoZSBnbG9iZSBhcmUgd2F0ZXIgcmF0aGVyIHRoYW4gbGFuZCwgc28gdGhleSBjYW4gYmUgcmVuZGVyZWQKICAgICAgICAgKiBhcyBhIHJlZmxlY3RpdmUgc3VyZmFjZSB3aXRoIGFuaW1hdGVkIHdhdmVzLgogICAgICAgICAqIEBtZW1iZXJvZiBUZXJyYWluUHJvdmlkZXIucHJvdG90eXBlCiAgICAgICAgICogQHR5cGUge2Jvb2xlYW59CiAgICAgICAgICogQHJlYWRvbmx5CiAgICAgICAgICovCiAgICAgICAgaGFzV2F0ZXJNYXNrOiB7CiAgICAgICAgICBnZXQ6IERldmVsb3BlckVycm9yX2RlZmF1bHQudGhyb3dJbnN0YW50aWF0aW9uRXJyb3IKICAgICAgICB9LAogICAgICAgIC8qKgogICAgICAgICAqIEdldHMgYSB2YWx1ZSBpbmRpY2F0aW5nIHdoZXRoZXIgb3Igbm90IHRoZSByZXF1ZXN0ZWQgdGlsZXMgaW5jbHVkZSB2ZXJ0ZXggbm9ybWFscy4KICAgICAgICAgKiBAbWVtYmVyb2YgVGVycmFpblByb3ZpZGVyLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtib29sZWFufQogICAgICAgICAqIEByZWFkb25seQogICAgICAgICAqLwogICAgICAgIGhhc1ZlcnRleE5vcm1hbHM6IHsKICAgICAgICAgIGdldDogRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdC50aHJvd0luc3RhbnRpYXRpb25FcnJvcgogICAgICAgIH0sCiAgICAgICAgLyoqCiAgICAgICAgICogR2V0cyBhbiBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCB0byBkZXRlcm1pbmUgYXZhaWxhYmlsaXR5IG9mIHRlcnJhaW4gZnJvbSB0aGlzIHByb3ZpZGVyLCBzdWNoIGFzCiAgICAgICAgICogYXQgcG9pbnRzIGFuZCBpbiByZWN0YW5nbGVzLiBUaGlzIHByb3BlcnR5IG1heSBiZSB1bmRlZmluZWQgaWYgYXZhaWxhYmlsaXR5CiAgICAgICAgICogaW5mb3JtYXRpb24gaXMgbm90IGF2YWlsYWJsZS4KICAgICAgICAgKiBAbWVtYmVyb2YgVGVycmFpblByb3ZpZGVyLnByb3RvdHlwZQogICAgICAgICAqIEB0eXBlIHtUaWxlQXZhaWxhYmlsaXR5fHVuZGVmaW5lZH0KICAgICAgICAgKiBAcmVhZG9ubHkKICAgICAgICAgKi8KICAgICAgICBhdmFpbGFiaWxpdHk6IHsKICAgICAgICAgIGdldDogRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdC50aHJvd0luc3RhbnRpYXRpb25FcnJvcgogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJlZ3VsYXJHcmlkSW5kaWNlc0NhY2hlID0gW107CiAgICAgIFRlcnJhaW5Qcm92aWRlci5nZXRSZWd1bGFyR3JpZEluZGljZXMgPSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7CiAgICAgICAgaWYgKHdpZHRoICogaGVpZ2h0ID49IE1hdGhfZGVmYXVsdC5GT1VSX0dJR0FCWVRFUykgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJUaGUgdG90YWwgbnVtYmVyIG9mIHZlcnRpY2VzICh3aWR0aCAqIGhlaWdodCkgbXVzdCBiZSBsZXNzIHRoYW4gNCwyOTQsOTY3LDI5Ni4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBsZXQgYnlXaWR0aCA9IHJlZ3VsYXJHcmlkSW5kaWNlc0NhY2hlW3dpZHRoXTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChieVdpZHRoKSkgewogICAgICAgICAgcmVndWxhckdyaWRJbmRpY2VzQ2FjaGVbd2lkdGhdID0gYnlXaWR0aCA9IFtdOwogICAgICAgIH0KICAgICAgICBsZXQgaW5kaWNlcyA9IGJ5V2lkdGhbaGVpZ2h0XTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpbmRpY2VzKSkgewogICAgICAgICAgaWYgKHdpZHRoICogaGVpZ2h0IDwgTWF0aF9kZWZhdWx0LlNJWFRZX0ZPVVJfS0lMT0JZVEVTKSB7CiAgICAgICAgICAgIGluZGljZXMgPSBieVdpZHRoW2hlaWdodF0gPSBuZXcgVWludDE2QXJyYXkoCiAgICAgICAgICAgICAgKHdpZHRoIC0gMSkgKiAoaGVpZ2h0IC0gMSkgKiA2CiAgICAgICAgICAgICk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpbmRpY2VzID0gYnlXaWR0aFtoZWlnaHRdID0gbmV3IFVpbnQzMkFycmF5KAogICAgICAgICAgICAgICh3aWR0aCAtIDEpICogKGhlaWdodCAtIDEpICogNgogICAgICAgICAgICApOwogICAgICAgICAgfQogICAgICAgICAgYWRkUmVndWxhckdyaWRJbmRpY2VzKHdpZHRoLCBoZWlnaHQsIGluZGljZXMsIDApOwogICAgICAgIH0KICAgICAgICByZXR1cm4gaW5kaWNlczsKICAgICAgfTsKICAgICAgcmVndWxhckdyaWRBbmRFZGdlSW5kaWNlc0NhY2hlID0gW107CiAgICAgIFRlcnJhaW5Qcm92aWRlci5nZXRSZWd1bGFyR3JpZEluZGljZXNBbmRFZGdlSW5kaWNlcyA9IGZ1bmN0aW9uKHdpZHRoLCBoZWlnaHQpIHsKICAgICAgICBpZiAod2lkdGggKiBoZWlnaHQgPj0gTWF0aF9kZWZhdWx0LkZPVVJfR0lHQUJZVEVTKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAgICAgIlRoZSB0b3RhbCBudW1iZXIgb2YgdmVydGljZXMgKHdpZHRoICogaGVpZ2h0KSBtdXN0IGJlIGxlc3MgdGhhbiA0LDI5NCw5NjcsMjk2LiIKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIGxldCBieVdpZHRoID0gcmVndWxhckdyaWRBbmRFZGdlSW5kaWNlc0NhY2hlW3dpZHRoXTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChieVdpZHRoKSkgewogICAgICAgICAgcmVndWxhckdyaWRBbmRFZGdlSW5kaWNlc0NhY2hlW3dpZHRoXSA9IGJ5V2lkdGggPSBbXTsKICAgICAgICB9CiAgICAgICAgbGV0IGluZGljZXNBbmRFZGdlcyA9IGJ5V2lkdGhbaGVpZ2h0XTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChpbmRpY2VzQW5kRWRnZXMpKSB7CiAgICAgICAgICBjb25zdCBpbmRpY2VzID0gVGVycmFpblByb3ZpZGVyLmdldFJlZ3VsYXJHcmlkSW5kaWNlcyh3aWR0aCwgaGVpZ2h0KTsKICAgICAgICAgIGNvbnN0IGVkZ2VJbmRpY2VzID0gZ2V0RWRnZUluZGljZXMod2lkdGgsIGhlaWdodCk7CiAgICAgICAgICBjb25zdCB3ZXN0SW5kaWNlc1NvdXRoVG9Ob3J0aCA9IGVkZ2VJbmRpY2VzLndlc3RJbmRpY2VzU291dGhUb05vcnRoOwogICAgICAgICAgY29uc3Qgc291dGhJbmRpY2VzRWFzdFRvV2VzdCA9IGVkZ2VJbmRpY2VzLnNvdXRoSW5kaWNlc0Vhc3RUb1dlc3Q7CiAgICAgICAgICBjb25zdCBlYXN0SW5kaWNlc05vcnRoVG9Tb3V0aCA9IGVkZ2VJbmRpY2VzLmVhc3RJbmRpY2VzTm9ydGhUb1NvdXRoOwogICAgICAgICAgY29uc3Qgbm9ydGhJbmRpY2VzV2VzdFRvRWFzdCA9IGVkZ2VJbmRpY2VzLm5vcnRoSW5kaWNlc1dlc3RUb0Vhc3Q7CiAgICAgICAgICBpbmRpY2VzQW5kRWRnZXMgPSBieVdpZHRoW2hlaWdodF0gPSB7CiAgICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICAgIHdlc3RJbmRpY2VzU291dGhUb05vcnRoLAogICAgICAgICAgICBzb3V0aEluZGljZXNFYXN0VG9XZXN0LAogICAgICAgICAgICBlYXN0SW5kaWNlc05vcnRoVG9Tb3V0aCwKICAgICAgICAgICAgbm9ydGhJbmRpY2VzV2VzdFRvRWFzdAogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGluZGljZXNBbmRFZGdlczsKICAgICAgfTsKICAgICAgcmVndWxhckdyaWRBbmRTa2lydEFuZEVkZ2VJbmRpY2VzQ2FjaGUgPSBbXTsKICAgICAgVGVycmFpblByb3ZpZGVyLmdldFJlZ3VsYXJHcmlkQW5kU2tpcnRJbmRpY2VzQW5kRWRnZUluZGljZXMgPSBmdW5jdGlvbih3aWR0aCwgaGVpZ2h0KSB7CiAgICAgICAgaWYgKHdpZHRoICogaGVpZ2h0ID49IE1hdGhfZGVmYXVsdC5GT1VSX0dJR0FCWVRFUykgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgICAgICJUaGUgdG90YWwgbnVtYmVyIG9mIHZlcnRpY2VzICh3aWR0aCAqIGhlaWdodCkgbXVzdCBiZSBsZXNzIHRoYW4gNCwyOTQsOTY3LDI5Ni4iCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBsZXQgYnlXaWR0aCA9IHJlZ3VsYXJHcmlkQW5kU2tpcnRBbmRFZGdlSW5kaWNlc0NhY2hlW3dpZHRoXTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChieVdpZHRoKSkgewogICAgICAgICAgcmVndWxhckdyaWRBbmRTa2lydEFuZEVkZ2VJbmRpY2VzQ2FjaGVbd2lkdGhdID0gYnlXaWR0aCA9IFtdOwogICAgICAgIH0KICAgICAgICBsZXQgaW5kaWNlc0FuZEVkZ2VzID0gYnlXaWR0aFtoZWlnaHRdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGluZGljZXNBbmRFZGdlcykpIHsKICAgICAgICAgIGNvbnN0IGdyaWRWZXJ0ZXhDb3VudCA9IHdpZHRoICogaGVpZ2h0OwogICAgICAgICAgY29uc3QgZ3JpZEluZGV4Q291bnQgPSAod2lkdGggLSAxKSAqIChoZWlnaHQgLSAxKSAqIDY7CiAgICAgICAgICBjb25zdCBlZGdlVmVydGV4Q291bnQgPSB3aWR0aCAqIDIgKyBoZWlnaHQgKiAyOwogICAgICAgICAgY29uc3QgZWRnZUluZGV4Q291bnQgPSBNYXRoLm1heCgwLCBlZGdlVmVydGV4Q291bnQgLSA0KSAqIDY7CiAgICAgICAgICBjb25zdCB2ZXJ0ZXhDb3VudCA9IGdyaWRWZXJ0ZXhDb3VudCArIGVkZ2VWZXJ0ZXhDb3VudDsKICAgICAgICAgIGNvbnN0IGluZGV4Q291bnQgPSBncmlkSW5kZXhDb3VudCArIGVkZ2VJbmRleENvdW50OwogICAgICAgICAgY29uc3QgZWRnZUluZGljZXMgPSBnZXRFZGdlSW5kaWNlcyh3aWR0aCwgaGVpZ2h0KTsKICAgICAgICAgIGNvbnN0IHdlc3RJbmRpY2VzU291dGhUb05vcnRoID0gZWRnZUluZGljZXMud2VzdEluZGljZXNTb3V0aFRvTm9ydGg7CiAgICAgICAgICBjb25zdCBzb3V0aEluZGljZXNFYXN0VG9XZXN0ID0gZWRnZUluZGljZXMuc291dGhJbmRpY2VzRWFzdFRvV2VzdDsKICAgICAgICAgIGNvbnN0IGVhc3RJbmRpY2VzTm9ydGhUb1NvdXRoID0gZWRnZUluZGljZXMuZWFzdEluZGljZXNOb3J0aFRvU291dGg7CiAgICAgICAgICBjb25zdCBub3J0aEluZGljZXNXZXN0VG9FYXN0ID0gZWRnZUluZGljZXMubm9ydGhJbmRpY2VzV2VzdFRvRWFzdDsKICAgICAgICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSh2ZXJ0ZXhDb3VudCwgaW5kZXhDb3VudCk7CiAgICAgICAgICBhZGRSZWd1bGFyR3JpZEluZGljZXMod2lkdGgsIGhlaWdodCwgaW5kaWNlcywgMCk7CiAgICAgICAgICBUZXJyYWluUHJvdmlkZXIuYWRkU2tpcnRJbmRpY2VzKAogICAgICAgICAgICB3ZXN0SW5kaWNlc1NvdXRoVG9Ob3J0aCwKICAgICAgICAgICAgc291dGhJbmRpY2VzRWFzdFRvV2VzdCwKICAgICAgICAgICAgZWFzdEluZGljZXNOb3J0aFRvU291dGgsCiAgICAgICAgICAgIG5vcnRoSW5kaWNlc1dlc3RUb0Vhc3QsCiAgICAgICAgICAgIGdyaWRWZXJ0ZXhDb3VudCwKICAgICAgICAgICAgaW5kaWNlcywKICAgICAgICAgICAgZ3JpZEluZGV4Q291bnQKICAgICAgICAgICk7CiAgICAgICAgICBpbmRpY2VzQW5kRWRnZXMgPSBieVdpZHRoW2hlaWdodF0gPSB7CiAgICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICAgIHdlc3RJbmRpY2VzU291dGhUb05vcnRoLAogICAgICAgICAgICBzb3V0aEluZGljZXNFYXN0VG9XZXN0LAogICAgICAgICAgICBlYXN0SW5kaWNlc05vcnRoVG9Tb3V0aCwKICAgICAgICAgICAgbm9ydGhJbmRpY2VzV2VzdFRvRWFzdCwKICAgICAgICAgICAgaW5kZXhDb3VudFdpdGhvdXRTa2lydHM6IGdyaWRJbmRleENvdW50CiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICByZXR1cm4gaW5kaWNlc0FuZEVkZ2VzOwogICAgICB9OwogICAgICBUZXJyYWluUHJvdmlkZXIuYWRkU2tpcnRJbmRpY2VzID0gZnVuY3Rpb24od2VzdEluZGljZXNTb3V0aFRvTm9ydGgsIHNvdXRoSW5kaWNlc0Vhc3RUb1dlc3QsIGVhc3RJbmRpY2VzTm9ydGhUb1NvdXRoLCBub3J0aEluZGljZXNXZXN0VG9FYXN0LCB2ZXJ0ZXhDb3VudCwgaW5kaWNlcywgb2Zmc2V0KSB7CiAgICAgICAgbGV0IHZlcnRleEluZGV4ID0gdmVydGV4Q291bnQ7CiAgICAgICAgb2Zmc2V0ID0gYWRkU2tpcnRJbmRpY2VzKAogICAgICAgICAgd2VzdEluZGljZXNTb3V0aFRvTm9ydGgsCiAgICAgICAgICB2ZXJ0ZXhJbmRleCwKICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICBvZmZzZXQKICAgICAgICApOwogICAgICAgIHZlcnRleEluZGV4ICs9IHdlc3RJbmRpY2VzU291dGhUb05vcnRoLmxlbmd0aDsKICAgICAgICBvZmZzZXQgPSBhZGRTa2lydEluZGljZXMoCiAgICAgICAgICBzb3V0aEluZGljZXNFYXN0VG9XZXN0LAogICAgICAgICAgdmVydGV4SW5kZXgsCiAgICAgICAgICBpbmRpY2VzLAogICAgICAgICAgb2Zmc2V0CiAgICAgICAgKTsKICAgICAgICB2ZXJ0ZXhJbmRleCArPSBzb3V0aEluZGljZXNFYXN0VG9XZXN0Lmxlbmd0aDsKICAgICAgICBvZmZzZXQgPSBhZGRTa2lydEluZGljZXMoCiAgICAgICAgICBlYXN0SW5kaWNlc05vcnRoVG9Tb3V0aCwKICAgICAgICAgIHZlcnRleEluZGV4LAogICAgICAgICAgaW5kaWNlcywKICAgICAgICAgIG9mZnNldAogICAgICAgICk7CiAgICAgICAgdmVydGV4SW5kZXggKz0gZWFzdEluZGljZXNOb3J0aFRvU291dGgubGVuZ3RoOwogICAgICAgIGFkZFNraXJ0SW5kaWNlcyhub3J0aEluZGljZXNXZXN0VG9FYXN0LCB2ZXJ0ZXhJbmRleCwgaW5kaWNlcywgb2Zmc2V0KTsKICAgICAgfTsKICAgICAgVGVycmFpblByb3ZpZGVyLmhlaWdodG1hcFRlcnJhaW5RdWFsaXR5ID0gMC4yNTsKICAgICAgVGVycmFpblByb3ZpZGVyLmdldEVzdGltYXRlZExldmVsWmVyb0dlb21ldHJpY0Vycm9yRm9yQUhlaWdodG1hcCA9IGZ1bmN0aW9uKGVsbGlwc29pZCwgdGlsZUltYWdlV2lkdGgsIG51bWJlck9mVGlsZXNBdExldmVsWmVybykgewogICAgICAgIHJldHVybiBlbGxpcHNvaWQubWF4aW11bVJhZGl1cyAqIDIgKiBNYXRoLlBJICogVGVycmFpblByb3ZpZGVyLmhlaWdodG1hcFRlcnJhaW5RdWFsaXR5IC8gKHRpbGVJbWFnZVdpZHRoICogbnVtYmVyT2ZUaWxlc0F0TGV2ZWxaZXJvKTsKICAgICAgfTsKICAgICAgVGVycmFpblByb3ZpZGVyLnByb3RvdHlwZS5yZXF1ZXN0VGlsZUdlb21ldHJ5ID0gRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdC50aHJvd0luc3RhbnRpYXRpb25FcnJvcjsKICAgICAgVGVycmFpblByb3ZpZGVyLnByb3RvdHlwZS5nZXRMZXZlbE1heGltdW1HZW9tZXRyaWNFcnJvciA9IERldmVsb3BlckVycm9yX2RlZmF1bHQudGhyb3dJbnN0YW50aWF0aW9uRXJyb3I7CiAgICAgIFRlcnJhaW5Qcm92aWRlci5wcm90b3R5cGUuZ2V0VGlsZURhdGFBdmFpbGFibGUgPSBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0LnRocm93SW5zdGFudGlhdGlvbkVycm9yOwogICAgICBUZXJyYWluUHJvdmlkZXIucHJvdG90eXBlLmxvYWRUaWxlRGF0YUF2YWlsYWJpbGl0eSA9IERldmVsb3BlckVycm9yX2RlZmF1bHQudGhyb3dJbnN0YW50aWF0aW9uRXJyb3I7CiAgICAgIFRlcnJhaW5Qcm92aWRlcl9kZWZhdWx0ID0gVGVycmFpblByb3ZpZGVyOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlVmVydGljZXNGcm9tUXVhbnRpemVkVGVycmFpbk1lc2guanMKICB2YXIgY3JlYXRlVmVydGljZXNGcm9tUXVhbnRpemVkVGVycmFpbk1lc2hfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGNyZWF0ZVZlcnRpY2VzRnJvbVF1YW50aXplZFRlcnJhaW5NZXNoX2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IGNyZWF0ZVZlcnRpY2VzRnJvbVF1YW50aXplZFRlcnJhaW5NZXNoX2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVWZXJ0aWNlc0Zyb21RdWFudGl6ZWRUZXJyYWluTWVzaChwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICBjb25zdCBxdWFudGl6ZWRWZXJ0aWNlcyA9IHBhcmFtZXRlcnMucXVhbnRpemVkVmVydGljZXM7CiAgICBjb25zdCBxdWFudGl6ZWRWZXJ0ZXhDb3VudCA9IHF1YW50aXplZFZlcnRpY2VzLmxlbmd0aCAvIDM7CiAgICBjb25zdCBvY3RFbmNvZGVkTm9ybWFscyA9IHBhcmFtZXRlcnMub2N0RW5jb2RlZE5vcm1hbHM7CiAgICBjb25zdCBlZGdlVmVydGV4Q291bnQgPSBwYXJhbWV0ZXJzLndlc3RJbmRpY2VzLmxlbmd0aCArIHBhcmFtZXRlcnMuZWFzdEluZGljZXMubGVuZ3RoICsgcGFyYW1ldGVycy5zb3V0aEluZGljZXMubGVuZ3RoICsgcGFyYW1ldGVycy5ub3J0aEluZGljZXMubGVuZ3RoOwogICAgY29uc3QgaW5jbHVkZVdlYk1lcmNhdG9yVCA9IHBhcmFtZXRlcnMuaW5jbHVkZVdlYk1lcmNhdG9yVDsKICAgIGNvbnN0IGV4YWdnZXJhdGlvbiA9IHBhcmFtZXRlcnMuZXhhZ2dlcmF0aW9uOwogICAgY29uc3QgZXhhZ2dlcmF0aW9uUmVsYXRpdmVIZWlnaHQgPSBwYXJhbWV0ZXJzLmV4YWdnZXJhdGlvblJlbGF0aXZlSGVpZ2h0OwogICAgY29uc3QgaGFzRXhhZ2dlcmF0aW9uID0gZXhhZ2dlcmF0aW9uICE9PSAxOwogICAgY29uc3QgaW5jbHVkZUdlb2RldGljU3VyZmFjZU5vcm1hbHMgPSBoYXNFeGFnZ2VyYXRpb247CiAgICBjb25zdCByZWN0YW5nbGUgPSBSZWN0YW5nbGVfZGVmYXVsdC5jbG9uZShwYXJhbWV0ZXJzLnJlY3RhbmdsZSk7CiAgICBjb25zdCB3ZXN0ID0gcmVjdGFuZ2xlLndlc3Q7CiAgICBjb25zdCBzb3V0aCA9IHJlY3RhbmdsZS5zb3V0aDsKICAgIGNvbnN0IGVhc3QgPSByZWN0YW5nbGUuZWFzdDsKICAgIGNvbnN0IG5vcnRoID0gcmVjdGFuZ2xlLm5vcnRoOwogICAgY29uc3QgZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUocGFyYW1ldGVycy5lbGxpcHNvaWQpOwogICAgY29uc3QgbWluaW11bUhlaWdodCA9IHBhcmFtZXRlcnMubWluaW11bUhlaWdodDsKICAgIGNvbnN0IG1heGltdW1IZWlnaHQgPSBwYXJhbWV0ZXJzLm1heGltdW1IZWlnaHQ7CiAgICBjb25zdCBjZW50ZXIgPSBwYXJhbWV0ZXJzLnJlbGF0aXZlVG9DZW50ZXI7CiAgICBjb25zdCBmcm9tRU5VID0gVHJhbnNmb3Jtc19kZWZhdWx0LmVhc3ROb3J0aFVwVG9GaXhlZEZyYW1lKGNlbnRlciwgZWxsaXBzb2lkKTsKICAgIGNvbnN0IHRvRU5VID0gTWF0cml4NF9kZWZhdWx0LmludmVyc2VUcmFuc2Zvcm1hdGlvbihmcm9tRU5VLCBuZXcgTWF0cml4NF9kZWZhdWx0KCkpOwogICAgbGV0IHNvdXRoTWVyY2F0b3JZOwogICAgbGV0IG9uZU92ZXJNZXJjYXRvckhlaWdodDsKICAgIGlmIChpbmNsdWRlV2ViTWVyY2F0b3JUKSB7CiAgICAgIHNvdXRoTWVyY2F0b3JZID0gV2ViTWVyY2F0b3JQcm9qZWN0aW9uX2RlZmF1bHQuZ2VvZGV0aWNMYXRpdHVkZVRvTWVyY2F0b3JBbmdsZShzb3V0aCk7CiAgICAgIG9uZU92ZXJNZXJjYXRvckhlaWdodCA9IDEgLyAoV2ViTWVyY2F0b3JQcm9qZWN0aW9uX2RlZmF1bHQuZ2VvZGV0aWNMYXRpdHVkZVRvTWVyY2F0b3JBbmdsZShub3J0aCkgLSBzb3V0aE1lcmNhdG9yWSk7CiAgICB9CiAgICBjb25zdCB1QnVmZmVyID0gcXVhbnRpemVkVmVydGljZXMuc3ViYXJyYXkoMCwgcXVhbnRpemVkVmVydGV4Q291bnQpOwogICAgY29uc3QgdkJ1ZmZlciA9IHF1YW50aXplZFZlcnRpY2VzLnN1YmFycmF5KAogICAgICBxdWFudGl6ZWRWZXJ0ZXhDb3VudCwKICAgICAgMiAqIHF1YW50aXplZFZlcnRleENvdW50CiAgICApOwogICAgY29uc3QgaGVpZ2h0QnVmZmVyID0gcXVhbnRpemVkVmVydGljZXMuc3ViYXJyYXkoCiAgICAgIHF1YW50aXplZFZlcnRleENvdW50ICogMiwKICAgICAgMyAqIHF1YW50aXplZFZlcnRleENvdW50CiAgICApOwogICAgY29uc3QgaGFzVmVydGV4Tm9ybWFscyA9IGRlZmluZWRfZGVmYXVsdChvY3RFbmNvZGVkTm9ybWFscyk7CiAgICBjb25zdCB1dnMgPSBuZXcgQXJyYXkocXVhbnRpemVkVmVydGV4Q291bnQpOwogICAgY29uc3QgaGVpZ2h0cyA9IG5ldyBBcnJheShxdWFudGl6ZWRWZXJ0ZXhDb3VudCk7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgQXJyYXkocXVhbnRpemVkVmVydGV4Q291bnQpOwogICAgY29uc3Qgd2ViTWVyY2F0b3JUcyA9IGluY2x1ZGVXZWJNZXJjYXRvclQgPyBuZXcgQXJyYXkocXVhbnRpemVkVmVydGV4Q291bnQpIDogW107CiAgICBjb25zdCBnZW9kZXRpY1N1cmZhY2VOb3JtYWxzID0gaW5jbHVkZUdlb2RldGljU3VyZmFjZU5vcm1hbHMgPyBuZXcgQXJyYXkocXVhbnRpemVkVmVydGV4Q291bnQpIDogW107CiAgICBjb25zdCBtaW5pbXVtID0gc2NyYXRjaE1pbmltdW07CiAgICBtaW5pbXVtLnggPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICBtaW5pbXVtLnkgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICBtaW5pbXVtLnogPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICBjb25zdCBtYXhpbXVtID0gc2NyYXRjaE1heGltdW07CiAgICBtYXhpbXVtLnggPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICBtYXhpbXVtLnkgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICBtYXhpbXVtLnogPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICBsZXQgbWluTG9uZ2l0dWRlID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgbGV0IG1heExvbmdpdHVkZSA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgIGxldCBtaW5MYXRpdHVkZSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTsKICAgIGxldCBtYXhMYXRpdHVkZSA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcXVhbnRpemVkVmVydGV4Q291bnQ7ICsraSkgewogICAgICBjb25zdCByYXdVID0gdUJ1ZmZlcltpXTsKICAgICAgY29uc3QgcmF3ViA9IHZCdWZmZXJbaV07CiAgICAgIGNvbnN0IHUzID0gcmF3VSAvIG1heFNob3J0NDsKICAgICAgY29uc3QgdjMgPSByYXdWIC8gbWF4U2hvcnQ0OwogICAgICBjb25zdCBoZWlnaHQgPSBNYXRoX2RlZmF1bHQubGVycCgKICAgICAgICBtaW5pbXVtSGVpZ2h0LAogICAgICAgIG1heGltdW1IZWlnaHQsCiAgICAgICAgaGVpZ2h0QnVmZmVyW2ldIC8gbWF4U2hvcnQ0CiAgICAgICk7CiAgICAgIGNhcnRvZ3JhcGhpY1NjcmF0Y2gubG9uZ2l0dWRlID0gTWF0aF9kZWZhdWx0LmxlcnAod2VzdCwgZWFzdCwgdTMpOwogICAgICBjYXJ0b2dyYXBoaWNTY3JhdGNoLmxhdGl0dWRlID0gTWF0aF9kZWZhdWx0LmxlcnAoc291dGgsIG5vcnRoLCB2Myk7CiAgICAgIGNhcnRvZ3JhcGhpY1NjcmF0Y2guaGVpZ2h0ID0gaGVpZ2h0OwogICAgICBtaW5Mb25naXR1ZGUgPSBNYXRoLm1pbihjYXJ0b2dyYXBoaWNTY3JhdGNoLmxvbmdpdHVkZSwgbWluTG9uZ2l0dWRlKTsKICAgICAgbWF4TG9uZ2l0dWRlID0gTWF0aC5tYXgoY2FydG9ncmFwaGljU2NyYXRjaC5sb25naXR1ZGUsIG1heExvbmdpdHVkZSk7CiAgICAgIG1pbkxhdGl0dWRlID0gTWF0aC5taW4oY2FydG9ncmFwaGljU2NyYXRjaC5sYXRpdHVkZSwgbWluTGF0aXR1ZGUpOwogICAgICBtYXhMYXRpdHVkZSA9IE1hdGgubWF4KGNhcnRvZ3JhcGhpY1NjcmF0Y2gubGF0aXR1ZGUsIG1heExhdGl0dWRlKTsKICAgICAgY29uc3QgcG9zaXRpb24gPSBlbGxpcHNvaWQuY2FydG9ncmFwaGljVG9DYXJ0ZXNpYW4oY2FydG9ncmFwaGljU2NyYXRjaCk7CiAgICAgIHV2c1tpXSA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQodTMsIHYzKTsKICAgICAgaGVpZ2h0c1tpXSA9IGhlaWdodDsKICAgICAgcG9zaXRpb25zW2ldID0gcG9zaXRpb247CiAgICAgIGlmIChpbmNsdWRlV2ViTWVyY2F0b3JUKSB7CiAgICAgICAgd2ViTWVyY2F0b3JUc1tpXSA9IChXZWJNZXJjYXRvclByb2plY3Rpb25fZGVmYXVsdC5nZW9kZXRpY0xhdGl0dWRlVG9NZXJjYXRvckFuZ2xlKAogICAgICAgICAgY2FydG9ncmFwaGljU2NyYXRjaC5sYXRpdHVkZQogICAgICAgICkgLSBzb3V0aE1lcmNhdG9yWSkgKiBvbmVPdmVyTWVyY2F0b3JIZWlnaHQ7CiAgICAgIH0KICAgICAgaWYgKGluY2x1ZGVHZW9kZXRpY1N1cmZhY2VOb3JtYWxzKSB7CiAgICAgICAgZ2VvZGV0aWNTdXJmYWNlTm9ybWFsc1tpXSA9IGVsbGlwc29pZC5nZW9kZXRpY1N1cmZhY2VOb3JtYWwocG9zaXRpb24pOwogICAgICB9CiAgICAgIE1hdHJpeDRfZGVmYXVsdC5tdWx0aXBseUJ5UG9pbnQodG9FTlUsIHBvc2l0aW9uLCBjYXJ0ZXNpYW4zU2NyYXRjaDgpOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubWluaW11bUJ5Q29tcG9uZW50KGNhcnRlc2lhbjNTY3JhdGNoOCwgbWluaW11bSwgbWluaW11bSk7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5tYXhpbXVtQnlDb21wb25lbnQoY2FydGVzaWFuM1NjcmF0Y2g4LCBtYXhpbXVtLCBtYXhpbXVtKTsKICAgIH0KICAgIGNvbnN0IHdlc3RJbmRpY2VzU291dGhUb05vcnRoID0gY29weUFuZFNvcnQoCiAgICAgIHBhcmFtZXRlcnMud2VzdEluZGljZXMsCiAgICAgIGZ1bmN0aW9uKGEzLCBiKSB7CiAgICAgICAgcmV0dXJuIHV2c1thM10ueSAtIHV2c1tiXS55OwogICAgICB9CiAgICApOwogICAgY29uc3QgZWFzdEluZGljZXNOb3J0aFRvU291dGggPSBjb3B5QW5kU29ydCgKICAgICAgcGFyYW1ldGVycy5lYXN0SW5kaWNlcywKICAgICAgZnVuY3Rpb24oYTMsIGIpIHsKICAgICAgICByZXR1cm4gdXZzW2JdLnkgLSB1dnNbYTNdLnk7CiAgICAgIH0KICAgICk7CiAgICBjb25zdCBzb3V0aEluZGljZXNFYXN0VG9XZXN0ID0gY29weUFuZFNvcnQoCiAgICAgIHBhcmFtZXRlcnMuc291dGhJbmRpY2VzLAogICAgICBmdW5jdGlvbihhMywgYikgewogICAgICAgIHJldHVybiB1dnNbYl0ueCAtIHV2c1thM10ueDsKICAgICAgfQogICAgKTsKICAgIGNvbnN0IG5vcnRoSW5kaWNlc1dlc3RUb0Vhc3QgPSBjb3B5QW5kU29ydCgKICAgICAgcGFyYW1ldGVycy5ub3J0aEluZGljZXMsCiAgICAgIGZ1bmN0aW9uKGEzLCBiKSB7CiAgICAgICAgcmV0dXJuIHV2c1thM10ueCAtIHV2c1tiXS54OwogICAgICB9CiAgICApOwogICAgbGV0IG9jY2x1ZGVlUG9pbnRJblNjYWxlZFNwYWNlOwogICAgaWYgKG1pbmltdW1IZWlnaHQgPCAwKSB7CiAgICAgIGNvbnN0IG9jY2x1ZGVyID0gbmV3IEVsbGlwc29pZGFsT2NjbHVkZXJfZGVmYXVsdChlbGxpcHNvaWQpOwogICAgICBvY2NsdWRlZVBvaW50SW5TY2FsZWRTcGFjZSA9IG9jY2x1ZGVyLmNvbXB1dGVIb3Jpem9uQ3VsbGluZ1BvaW50UG9zc2libHlVbmRlckVsbGlwc29pZCgKICAgICAgICBjZW50ZXIsCiAgICAgICAgcG9zaXRpb25zLAogICAgICAgIG1pbmltdW1IZWlnaHQKICAgICAgKTsKICAgIH0KICAgIGxldCBoTWluID0gbWluaW11bUhlaWdodDsKICAgIGhNaW4gPSBNYXRoLm1pbigKICAgICAgaE1pbiwKICAgICAgZmluZE1pbk1heFNraXJ0cygKICAgICAgICBwYXJhbWV0ZXJzLndlc3RJbmRpY2VzLAogICAgICAgIHBhcmFtZXRlcnMud2VzdFNraXJ0SGVpZ2h0LAogICAgICAgIGhlaWdodHMsCiAgICAgICAgdXZzLAogICAgICAgIHJlY3RhbmdsZSwKICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgdG9FTlUsCiAgICAgICAgbWluaW11bSwKICAgICAgICBtYXhpbXVtCiAgICAgICkKICAgICk7CiAgICBoTWluID0gTWF0aC5taW4oCiAgICAgIGhNaW4sCiAgICAgIGZpbmRNaW5NYXhTa2lydHMoCiAgICAgICAgcGFyYW1ldGVycy5zb3V0aEluZGljZXMsCiAgICAgICAgcGFyYW1ldGVycy5zb3V0aFNraXJ0SGVpZ2h0LAogICAgICAgIGhlaWdodHMsCiAgICAgICAgdXZzLAogICAgICAgIHJlY3RhbmdsZSwKICAgICAgICBlbGxpcHNvaWQsCiAgICAgICAgdG9FTlUsCiAgICAgICAgbWluaW11bSwKICAgICAgICBtYXhpbXVtCiAgICAgICkKICAgICk7CiAgICBoTWluID0gTWF0aC5taW4oCiAgICAgIGhNaW4sCiAgICAgIGZpbmRNaW5NYXhTa2lydHMoCiAgICAgICAgcGFyYW1ldGVycy5lYXN0SW5kaWNlcywKICAgICAgICBwYXJhbWV0ZXJzLmVhc3RTa2lydEhlaWdodCwKICAgICAgICBoZWlnaHRzLAogICAgICAgIHV2cywKICAgICAgICByZWN0YW5nbGUsCiAgICAgICAgZWxsaXBzb2lkLAogICAgICAgIHRvRU5VLAogICAgICAgIG1pbmltdW0sCiAgICAgICAgbWF4aW11bQogICAgICApCiAgICApOwogICAgaE1pbiA9IE1hdGgubWluKAogICAgICBoTWluLAogICAgICBmaW5kTWluTWF4U2tpcnRzKAogICAgICAgIHBhcmFtZXRlcnMubm9ydGhJbmRpY2VzLAogICAgICAgIHBhcmFtZXRlcnMubm9ydGhTa2lydEhlaWdodCwKICAgICAgICBoZWlnaHRzLAogICAgICAgIHV2cywKICAgICAgICByZWN0YW5nbGUsCiAgICAgICAgZWxsaXBzb2lkLAogICAgICAgIHRvRU5VLAogICAgICAgIG1pbmltdW0sCiAgICAgICAgbWF4aW11bQogICAgICApCiAgICApOwogICAgY29uc3QgYWFCb3ggPSBuZXcgQXhpc0FsaWduZWRCb3VuZGluZ0JveF9kZWZhdWx0KG1pbmltdW0sIG1heGltdW0sIGNlbnRlcik7CiAgICBjb25zdCBlbmNvZGluZyA9IG5ldyBUZXJyYWluRW5jb2RpbmdfZGVmYXVsdCgKICAgICAgY2VudGVyLAogICAgICBhYUJveCwKICAgICAgaE1pbiwKICAgICAgbWF4aW11bUhlaWdodCwKICAgICAgZnJvbUVOVSwKICAgICAgaGFzVmVydGV4Tm9ybWFscywKICAgICAgaW5jbHVkZVdlYk1lcmNhdG9yVCwKICAgICAgaW5jbHVkZUdlb2RldGljU3VyZmFjZU5vcm1hbHMsCiAgICAgIGV4YWdnZXJhdGlvbiwKICAgICAgZXhhZ2dlcmF0aW9uUmVsYXRpdmVIZWlnaHQKICAgICk7CiAgICBjb25zdCB2ZXJ0ZXhTdHJpZGUgPSBlbmNvZGluZy5zdHJpZGU7CiAgICBjb25zdCBzaXplID0gcXVhbnRpemVkVmVydGV4Q291bnQgKiB2ZXJ0ZXhTdHJpZGUgKyBlZGdlVmVydGV4Q291bnQgKiB2ZXJ0ZXhTdHJpZGU7CiAgICBjb25zdCB2ZXJ0ZXhCdWZmZXIgPSBuZXcgRmxvYXQzMkFycmF5KHNpemUpOwogICAgbGV0IGJ1ZmZlckluZGV4ID0gMDsKICAgIGZvciAobGV0IGogPSAwOyBqIDwgcXVhbnRpemVkVmVydGV4Q291bnQ7ICsraikgewogICAgICBpZiAoaGFzVmVydGV4Tm9ybWFscykgewogICAgICAgIGNvbnN0IG4gPSBqICogMjsKICAgICAgICB0b1BhY2sueCA9IG9jdEVuY29kZWROb3JtYWxzW25dOwogICAgICAgIHRvUGFjay55ID0gb2N0RW5jb2RlZE5vcm1hbHNbbiArIDFdOwogICAgICB9CiAgICAgIGJ1ZmZlckluZGV4ID0gZW5jb2RpbmcuZW5jb2RlKAogICAgICAgIHZlcnRleEJ1ZmZlciwKICAgICAgICBidWZmZXJJbmRleCwKICAgICAgICBwb3NpdGlvbnNbal0sCiAgICAgICAgdXZzW2pdLAogICAgICAgIGhlaWdodHNbal0sCiAgICAgICAgdG9QYWNrLAogICAgICAgIHdlYk1lcmNhdG9yVHNbal0sCiAgICAgICAgZ2VvZGV0aWNTdXJmYWNlTm9ybWFsc1tqXQogICAgICApOwogICAgfQogICAgY29uc3QgZWRnZVRyaWFuZ2xlQ291bnQgPSBNYXRoLm1heCgwLCAoZWRnZVZlcnRleENvdW50IC0gNCkgKiAyKTsKICAgIGNvbnN0IGluZGV4QnVmZmVyTGVuZ3RoID0gcGFyYW1ldGVycy5pbmRpY2VzLmxlbmd0aCArIGVkZ2VUcmlhbmdsZUNvdW50ICogMzsKICAgIGNvbnN0IGluZGV4QnVmZmVyID0gSW5kZXhEYXRhdHlwZV9kZWZhdWx0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgIHF1YW50aXplZFZlcnRleENvdW50ICsgZWRnZVZlcnRleENvdW50LAogICAgICBpbmRleEJ1ZmZlckxlbmd0aAogICAgKTsKICAgIGluZGV4QnVmZmVyLnNldChwYXJhbWV0ZXJzLmluZGljZXMsIDApOwogICAgY29uc3QgcGVyY2VudGFnZSA9IDFlLTQ7CiAgICBjb25zdCBsb25PZmZzZXQgPSAobWF4TG9uZ2l0dWRlIC0gbWluTG9uZ2l0dWRlKSAqIHBlcmNlbnRhZ2U7CiAgICBjb25zdCBsYXRPZmZzZXQgPSAobWF4TGF0aXR1ZGUgLSBtaW5MYXRpdHVkZSkgKiBwZXJjZW50YWdlOwogICAgY29uc3Qgd2VzdExvbmdpdHVkZU9mZnNldCA9IC1sb25PZmZzZXQ7CiAgICBjb25zdCB3ZXN0TGF0aXR1ZGVPZmZzZXQgPSAwOwogICAgY29uc3QgZWFzdExvbmdpdHVkZU9mZnNldCA9IGxvbk9mZnNldDsKICAgIGNvbnN0IGVhc3RMYXRpdHVkZU9mZnNldCA9IDA7CiAgICBjb25zdCBub3J0aExvbmdpdHVkZU9mZnNldCA9IDA7CiAgICBjb25zdCBub3J0aExhdGl0dWRlT2Zmc2V0ID0gbGF0T2Zmc2V0OwogICAgY29uc3Qgc291dGhMb25naXR1ZGVPZmZzZXQgPSAwOwogICAgY29uc3Qgc291dGhMYXRpdHVkZU9mZnNldCA9IC1sYXRPZmZzZXQ7CiAgICBsZXQgdmVydGV4QnVmZmVySW5kZXggPSBxdWFudGl6ZWRWZXJ0ZXhDb3VudCAqIHZlcnRleFN0cmlkZTsKICAgIGFkZFNraXJ0MigKICAgICAgdmVydGV4QnVmZmVyLAogICAgICB2ZXJ0ZXhCdWZmZXJJbmRleCwKICAgICAgd2VzdEluZGljZXNTb3V0aFRvTm9ydGgsCiAgICAgIGVuY29kaW5nLAogICAgICBoZWlnaHRzLAogICAgICB1dnMsCiAgICAgIG9jdEVuY29kZWROb3JtYWxzLAogICAgICBlbGxpcHNvaWQsCiAgICAgIHJlY3RhbmdsZSwKICAgICAgcGFyYW1ldGVycy53ZXN0U2tpcnRIZWlnaHQsCiAgICAgIHNvdXRoTWVyY2F0b3JZLAogICAgICBvbmVPdmVyTWVyY2F0b3JIZWlnaHQsCiAgICAgIHdlc3RMb25naXR1ZGVPZmZzZXQsCiAgICAgIHdlc3RMYXRpdHVkZU9mZnNldAogICAgKTsKICAgIHZlcnRleEJ1ZmZlckluZGV4ICs9IHBhcmFtZXRlcnMud2VzdEluZGljZXMubGVuZ3RoICogdmVydGV4U3RyaWRlOwogICAgYWRkU2tpcnQyKAogICAgICB2ZXJ0ZXhCdWZmZXIsCiAgICAgIHZlcnRleEJ1ZmZlckluZGV4LAogICAgICBzb3V0aEluZGljZXNFYXN0VG9XZXN0LAogICAgICBlbmNvZGluZywKICAgICAgaGVpZ2h0cywKICAgICAgdXZzLAogICAgICBvY3RFbmNvZGVkTm9ybWFscywKICAgICAgZWxsaXBzb2lkLAogICAgICByZWN0YW5nbGUsCiAgICAgIHBhcmFtZXRlcnMuc291dGhTa2lydEhlaWdodCwKICAgICAgc291dGhNZXJjYXRvclksCiAgICAgIG9uZU92ZXJNZXJjYXRvckhlaWdodCwKICAgICAgc291dGhMb25naXR1ZGVPZmZzZXQsCiAgICAgIHNvdXRoTGF0aXR1ZGVPZmZzZXQKICAgICk7CiAgICB2ZXJ0ZXhCdWZmZXJJbmRleCArPSBwYXJhbWV0ZXJzLnNvdXRoSW5kaWNlcy5sZW5ndGggKiB2ZXJ0ZXhTdHJpZGU7CiAgICBhZGRTa2lydDIoCiAgICAgIHZlcnRleEJ1ZmZlciwKICAgICAgdmVydGV4QnVmZmVySW5kZXgsCiAgICAgIGVhc3RJbmRpY2VzTm9ydGhUb1NvdXRoLAogICAgICBlbmNvZGluZywKICAgICAgaGVpZ2h0cywKICAgICAgdXZzLAogICAgICBvY3RFbmNvZGVkTm9ybWFscywKICAgICAgZWxsaXBzb2lkLAogICAgICByZWN0YW5nbGUsCiAgICAgIHBhcmFtZXRlcnMuZWFzdFNraXJ0SGVpZ2h0LAogICAgICBzb3V0aE1lcmNhdG9yWSwKICAgICAgb25lT3Zlck1lcmNhdG9ySGVpZ2h0LAogICAgICBlYXN0TG9uZ2l0dWRlT2Zmc2V0LAogICAgICBlYXN0TGF0aXR1ZGVPZmZzZXQKICAgICk7CiAgICB2ZXJ0ZXhCdWZmZXJJbmRleCArPSBwYXJhbWV0ZXJzLmVhc3RJbmRpY2VzLmxlbmd0aCAqIHZlcnRleFN0cmlkZTsKICAgIGFkZFNraXJ0MigKICAgICAgdmVydGV4QnVmZmVyLAogICAgICB2ZXJ0ZXhCdWZmZXJJbmRleCwKICAgICAgbm9ydGhJbmRpY2VzV2VzdFRvRWFzdCwKICAgICAgZW5jb2RpbmcsCiAgICAgIGhlaWdodHMsCiAgICAgIHV2cywKICAgICAgb2N0RW5jb2RlZE5vcm1hbHMsCiAgICAgIGVsbGlwc29pZCwKICAgICAgcmVjdGFuZ2xlLAogICAgICBwYXJhbWV0ZXJzLm5vcnRoU2tpcnRIZWlnaHQsCiAgICAgIHNvdXRoTWVyY2F0b3JZLAogICAgICBvbmVPdmVyTWVyY2F0b3JIZWlnaHQsCiAgICAgIG5vcnRoTG9uZ2l0dWRlT2Zmc2V0LAogICAgICBub3J0aExhdGl0dWRlT2Zmc2V0CiAgICApOwogICAgVGVycmFpblByb3ZpZGVyX2RlZmF1bHQuYWRkU2tpcnRJbmRpY2VzKAogICAgICB3ZXN0SW5kaWNlc1NvdXRoVG9Ob3J0aCwKICAgICAgc291dGhJbmRpY2VzRWFzdFRvV2VzdCwKICAgICAgZWFzdEluZGljZXNOb3J0aFRvU291dGgsCiAgICAgIG5vcnRoSW5kaWNlc1dlc3RUb0Vhc3QsCiAgICAgIHF1YW50aXplZFZlcnRleENvdW50LAogICAgICBpbmRleEJ1ZmZlciwKICAgICAgcGFyYW1ldGVycy5pbmRpY2VzLmxlbmd0aAogICAgKTsKICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaCh2ZXJ0ZXhCdWZmZXIuYnVmZmVyLCBpbmRleEJ1ZmZlci5idWZmZXIpOwogICAgcmV0dXJuIHsKICAgICAgdmVydGljZXM6IHZlcnRleEJ1ZmZlci5idWZmZXIsCiAgICAgIGluZGljZXM6IGluZGV4QnVmZmVyLmJ1ZmZlciwKICAgICAgd2VzdEluZGljZXNTb3V0aFRvTm9ydGgsCiAgICAgIHNvdXRoSW5kaWNlc0Vhc3RUb1dlc3QsCiAgICAgIGVhc3RJbmRpY2VzTm9ydGhUb1NvdXRoLAogICAgICBub3J0aEluZGljZXNXZXN0VG9FYXN0LAogICAgICB2ZXJ0ZXhTdHJpZGUsCiAgICAgIGNlbnRlciwKICAgICAgbWluaW11bUhlaWdodCwKICAgICAgbWF4aW11bUhlaWdodCwKICAgICAgb2NjbHVkZWVQb2ludEluU2NhbGVkU3BhY2UsCiAgICAgIGVuY29kaW5nLAogICAgICBpbmRleENvdW50V2l0aG91dFNraXJ0czogcGFyYW1ldGVycy5pbmRpY2VzLmxlbmd0aAogICAgfTsKICB9CiAgZnVuY3Rpb24gZmluZE1pbk1heFNraXJ0cyhlZGdlSW5kaWNlcywgZWRnZUhlaWdodCwgaGVpZ2h0cywgdXZzLCByZWN0YW5nbGUsIGVsbGlwc29pZCwgdG9FTlUsIG1pbmltdW0sIG1heGltdW0pIHsKICAgIGxldCBoTWluID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgY29uc3Qgbm9ydGggPSByZWN0YW5nbGUubm9ydGg7CiAgICBjb25zdCBzb3V0aCA9IHJlY3RhbmdsZS5zb3V0aDsKICAgIGxldCBlYXN0ID0gcmVjdGFuZ2xlLmVhc3Q7CiAgICBjb25zdCB3ZXN0ID0gcmVjdGFuZ2xlLndlc3Q7CiAgICBpZiAoZWFzdCA8IHdlc3QpIHsKICAgICAgZWFzdCArPSBNYXRoX2RlZmF1bHQuVFdPX1BJOwogICAgfQogICAgY29uc3QgbGVuZ3RoID0gZWRnZUluZGljZXMubGVuZ3RoOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBjb25zdCBpbmRleCA9IGVkZ2VJbmRpY2VzW2ldOwogICAgICBjb25zdCBoID0gaGVpZ2h0c1tpbmRleF07CiAgICAgIGNvbnN0IHV2ID0gdXZzW2luZGV4XTsKICAgICAgY2FydG9ncmFwaGljU2NyYXRjaC5sb25naXR1ZGUgPSBNYXRoX2RlZmF1bHQubGVycCh3ZXN0LCBlYXN0LCB1di54KTsKICAgICAgY2FydG9ncmFwaGljU2NyYXRjaC5sYXRpdHVkZSA9IE1hdGhfZGVmYXVsdC5sZXJwKHNvdXRoLCBub3J0aCwgdXYueSk7CiAgICAgIGNhcnRvZ3JhcGhpY1NjcmF0Y2guaGVpZ2h0ID0gaCAtIGVkZ2VIZWlnaHQ7CiAgICAgIGNvbnN0IHBvc2l0aW9uID0gZWxsaXBzb2lkLmNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuKAogICAgICAgIGNhcnRvZ3JhcGhpY1NjcmF0Y2gsCiAgICAgICAgY2FydGVzaWFuM1NjcmF0Y2g4CiAgICAgICk7CiAgICAgIE1hdHJpeDRfZGVmYXVsdC5tdWx0aXBseUJ5UG9pbnQodG9FTlUsIHBvc2l0aW9uLCBwb3NpdGlvbik7CiAgICAgIENhcnRlc2lhbjNfZGVmYXVsdC5taW5pbXVtQnlDb21wb25lbnQocG9zaXRpb24sIG1pbmltdW0sIG1pbmltdW0pOwogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQubWF4aW11bUJ5Q29tcG9uZW50KHBvc2l0aW9uLCBtYXhpbXVtLCBtYXhpbXVtKTsKICAgICAgaE1pbiA9IE1hdGgubWluKGhNaW4sIGNhcnRvZ3JhcGhpY1NjcmF0Y2guaGVpZ2h0KTsKICAgIH0KICAgIHJldHVybiBoTWluOwogIH0KICBmdW5jdGlvbiBhZGRTa2lydDIodmVydGV4QnVmZmVyLCB2ZXJ0ZXhCdWZmZXJJbmRleCwgZWRnZVZlcnRpY2VzLCBlbmNvZGluZywgaGVpZ2h0cywgdXZzLCBvY3RFbmNvZGVkTm9ybWFscywgZWxsaXBzb2lkLCByZWN0YW5nbGUsIHNraXJ0TGVuZ3RoLCBzb3V0aE1lcmNhdG9yWSwgb25lT3Zlck1lcmNhdG9ySGVpZ2h0LCBsb25naXR1ZGVPZmZzZXQsIGxhdGl0dWRlT2Zmc2V0KSB7CiAgICBjb25zdCBoYXNWZXJ0ZXhOb3JtYWxzID0gZGVmaW5lZF9kZWZhdWx0KG9jdEVuY29kZWROb3JtYWxzKTsKICAgIGNvbnN0IG5vcnRoID0gcmVjdGFuZ2xlLm5vcnRoOwogICAgY29uc3Qgc291dGggPSByZWN0YW5nbGUuc291dGg7CiAgICBsZXQgZWFzdCA9IHJlY3RhbmdsZS5lYXN0OwogICAgY29uc3Qgd2VzdCA9IHJlY3RhbmdsZS53ZXN0OwogICAgaWYgKGVhc3QgPCB3ZXN0KSB7CiAgICAgIGVhc3QgKz0gTWF0aF9kZWZhdWx0LlRXT19QSTsKICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IGVkZ2VWZXJ0aWNlcy5sZW5ndGg7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgIGNvbnN0IGluZGV4ID0gZWRnZVZlcnRpY2VzW2ldOwogICAgICBjb25zdCBoID0gaGVpZ2h0c1tpbmRleF07CiAgICAgIGNvbnN0IHV2ID0gdXZzW2luZGV4XTsKICAgICAgY2FydG9ncmFwaGljU2NyYXRjaC5sb25naXR1ZGUgPSBNYXRoX2RlZmF1bHQubGVycCh3ZXN0LCBlYXN0LCB1di54KSArIGxvbmdpdHVkZU9mZnNldDsKICAgICAgY2FydG9ncmFwaGljU2NyYXRjaC5sYXRpdHVkZSA9IE1hdGhfZGVmYXVsdC5sZXJwKHNvdXRoLCBub3J0aCwgdXYueSkgKyBsYXRpdHVkZU9mZnNldDsKICAgICAgY2FydG9ncmFwaGljU2NyYXRjaC5oZWlnaHQgPSBoIC0gc2tpcnRMZW5ndGg7CiAgICAgIGNvbnN0IHBvc2l0aW9uID0gZWxsaXBzb2lkLmNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuKAogICAgICAgIGNhcnRvZ3JhcGhpY1NjcmF0Y2gsCiAgICAgICAgY2FydGVzaWFuM1NjcmF0Y2g4CiAgICAgICk7CiAgICAgIGlmIChoYXNWZXJ0ZXhOb3JtYWxzKSB7CiAgICAgICAgY29uc3QgbiA9IGluZGV4ICogMjsKICAgICAgICB0b1BhY2sueCA9IG9jdEVuY29kZWROb3JtYWxzW25dOwogICAgICAgIHRvUGFjay55ID0gb2N0RW5jb2RlZE5vcm1hbHNbbiArIDFdOwogICAgICB9CiAgICAgIGxldCB3ZWJNZXJjYXRvclQ7CiAgICAgIGlmIChlbmNvZGluZy5oYXNXZWJNZXJjYXRvclQpIHsKICAgICAgICB3ZWJNZXJjYXRvclQgPSAoV2ViTWVyY2F0b3JQcm9qZWN0aW9uX2RlZmF1bHQuZ2VvZGV0aWNMYXRpdHVkZVRvTWVyY2F0b3JBbmdsZSgKICAgICAgICAgIGNhcnRvZ3JhcGhpY1NjcmF0Y2gubGF0aXR1ZGUKICAgICAgICApIC0gc291dGhNZXJjYXRvclkpICogb25lT3Zlck1lcmNhdG9ySGVpZ2h0OwogICAgICB9CiAgICAgIGxldCBnZW9kZXRpY1N1cmZhY2VOb3JtYWw7CiAgICAgIGlmIChlbmNvZGluZy5oYXNHZW9kZXRpY1N1cmZhY2VOb3JtYWxzKSB7CiAgICAgICAgZ2VvZGV0aWNTdXJmYWNlTm9ybWFsID0gZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbChwb3NpdGlvbik7CiAgICAgIH0KICAgICAgdmVydGV4QnVmZmVySW5kZXggPSBlbmNvZGluZy5lbmNvZGUoCiAgICAgICAgdmVydGV4QnVmZmVyLAogICAgICAgIHZlcnRleEJ1ZmZlckluZGV4LAogICAgICAgIHBvc2l0aW9uLAogICAgICAgIHV2LAogICAgICAgIGNhcnRvZ3JhcGhpY1NjcmF0Y2guaGVpZ2h0LAogICAgICAgIHRvUGFjaywKICAgICAgICB3ZWJNZXJjYXRvclQsCiAgICAgICAgZ2VvZGV0aWNTdXJmYWNlTm9ybWFsCiAgICAgICk7CiAgICB9CiAgfQogIGZ1bmN0aW9uIGNvcHlBbmRTb3J0KHR5cGVkQXJyYXksIGNvbXBhcmF0b3IpIHsKICAgIGxldCBjb3B5OwogICAgaWYgKHR5cGVvZiB0eXBlZEFycmF5LnNsaWNlID09PSAiZnVuY3Rpb24iKSB7CiAgICAgIGNvcHkgPSB0eXBlZEFycmF5LnNsaWNlKCk7CiAgICAgIGlmICh0eXBlb2YgY29weS5zb3J0ICE9PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgY29weSA9IHZvaWQgMDsKICAgICAgfQogICAgfQogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoY29weSkpIHsKICAgICAgY29weSA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHR5cGVkQXJyYXkpOwogICAgfQogICAgY29weS5zb3J0KGNvbXBhcmF0b3IpOwogICAgcmV0dXJuIGNvcHk7CiAgfQogIHZhciBtYXhTaG9ydDQsIGNhcnRlc2lhbjNTY3JhdGNoOCwgc2NyYXRjaE1pbmltdW0sIHNjcmF0Y2hNYXhpbXVtLCBjYXJ0b2dyYXBoaWNTY3JhdGNoLCB0b1BhY2ssIGNyZWF0ZVZlcnRpY2VzRnJvbVF1YW50aXplZFRlcnJhaW5NZXNoX2RlZmF1bHQ7CiAgdmFyIGluaXRfY3JlYXRlVmVydGljZXNGcm9tUXVhbnRpemVkVGVycmFpbk1lc2ggPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVZlcnRpY2VzRnJvbVF1YW50aXplZFRlcnJhaW5NZXNoLmpzIigpIHsKICAgICAgaW5pdF9BeGlzQWxpZ25lZEJvdW5kaW5nQm94KCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMigpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9DYXJ0b2dyYXBoaWMoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkYWxPY2NsdWRlcigpOwogICAgICBpbml0X0luZGV4RGF0YXR5cGUoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfTWF0cml4NCgpOwogICAgICBpbml0X1JlY3RhbmdsZSgpOwogICAgICBpbml0X1RlcnJhaW5FbmNvZGluZygpOwogICAgICBpbml0X1RlcnJhaW5Qcm92aWRlcigpOwogICAgICBpbml0X1RyYW5zZm9ybXMoKTsKICAgICAgaW5pdF9XZWJNZXJjYXRvclByb2plY3Rpb24oKTsKICAgICAgaW5pdF9jcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyKCk7CiAgICAgIG1heFNob3J0NCA9IDMyNzY3OwogICAgICBjYXJ0ZXNpYW4zU2NyYXRjaDggPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hNaW5pbXVtID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoTWF4aW11bSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgY2FydG9ncmFwaGljU2NyYXRjaCA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICB0b1BhY2sgPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIGNyZWF0ZVZlcnRpY2VzRnJvbVF1YW50aXplZFRlcnJhaW5NZXNoX2RlZmF1bHQgPSBjcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyX2RlZmF1bHQoCiAgICAgICAgY3JlYXRlVmVydGljZXNGcm9tUXVhbnRpemVkVGVycmFpbk1lc2gKICAgICAgKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1dhbGxHZW9tZXRyeUxpYnJhcnkuanMKICBmdW5jdGlvbiBsYXRMb25FcXVhbHMoYzAsIGMxKSB7CiAgICByZXR1cm4gTWF0aF9kZWZhdWx0LmVxdWFsc0Vwc2lsb24oYzAubGF0aXR1ZGUsIGMxLmxhdGl0dWRlLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjEwKSAmJiBNYXRoX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihjMC5sb25naXR1ZGUsIGMxLmxvbmdpdHVkZSwgTWF0aF9kZWZhdWx0LkVQU0lMT04xMCk7CiAgfQogIGZ1bmN0aW9uIHJlbW92ZUR1cGxpY2F0ZXMyKGVsbGlwc29pZCwgcG9zaXRpb25zLCB0b3BIZWlnaHRzLCBib3R0b21IZWlnaHRzKSB7CiAgICBwb3NpdGlvbnMgPSBhcnJheVJlbW92ZUR1cGxpY2F0ZXNfZGVmYXVsdChwb3NpdGlvbnMsIENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKTsKICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICBpZiAobGVuZ3RoIDwgMikgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBoYXNCb3R0b21IZWlnaHRzID0gZGVmaW5lZF9kZWZhdWx0KGJvdHRvbUhlaWdodHMpOwogICAgY29uc3QgaGFzVG9wSGVpZ2h0cyA9IGRlZmluZWRfZGVmYXVsdCh0b3BIZWlnaHRzKTsKICAgIGNvbnN0IGNsZWFuZWRQb3NpdGlvbnMgPSBuZXcgQXJyYXkobGVuZ3RoKTsKICAgIGNvbnN0IGNsZWFuZWRUb3BIZWlnaHRzID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICBjb25zdCBjbGVhbmVkQm90dG9tSGVpZ2h0cyA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgY29uc3QgdjAyID0gcG9zaXRpb25zWzBdOwogICAgY2xlYW5lZFBvc2l0aW9uc1swXSA9IHYwMjsKICAgIGNvbnN0IGMwID0gZWxsaXBzb2lkLmNhcnRlc2lhblRvQ2FydG9ncmFwaGljKHYwMiwgc2NyYXRjaENhcnRvZ3JhcGhpYzEzKTsKICAgIGlmIChoYXNUb3BIZWlnaHRzKSB7CiAgICAgIGMwLmhlaWdodCA9IHRvcEhlaWdodHNbMF07CiAgICB9CiAgICBjbGVhbmVkVG9wSGVpZ2h0c1swXSA9IGMwLmhlaWdodDsKICAgIGlmIChoYXNCb3R0b21IZWlnaHRzKSB7CiAgICAgIGNsZWFuZWRCb3R0b21IZWlnaHRzWzBdID0gYm90dG9tSGVpZ2h0c1swXTsKICAgIH0gZWxzZSB7CiAgICAgIGNsZWFuZWRCb3R0b21IZWlnaHRzWzBdID0gMDsKICAgIH0KICAgIGNvbnN0IHN0YXJ0VG9wSGVpZ2h0ID0gY2xlYW5lZFRvcEhlaWdodHNbMF07CiAgICBjb25zdCBzdGFydEJvdHRvbUhlaWdodCA9IGNsZWFuZWRCb3R0b21IZWlnaHRzWzBdOwogICAgbGV0IGhhc0FsbFNhbWVIZWlnaHRzID0gc3RhcnRUb3BIZWlnaHQgPT09IHN0YXJ0Qm90dG9tSGVpZ2h0OwogICAgbGV0IGluZGV4ID0gMTsKICAgIGZvciAobGV0IGkgPSAxOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgY29uc3QgdjEyID0gcG9zaXRpb25zW2ldOwogICAgICBjb25zdCBjMSA9IGVsbGlwc29pZC5jYXJ0ZXNpYW5Ub0NhcnRvZ3JhcGhpYyh2MTIsIHNjcmF0Y2hDYXJ0b2dyYXBoaWMyMyk7CiAgICAgIGlmIChoYXNUb3BIZWlnaHRzKSB7CiAgICAgICAgYzEuaGVpZ2h0ID0gdG9wSGVpZ2h0c1tpXTsKICAgICAgfQogICAgICBoYXNBbGxTYW1lSGVpZ2h0cyA9IGhhc0FsbFNhbWVIZWlnaHRzICYmIGMxLmhlaWdodCA9PT0gMDsKICAgICAgaWYgKCFsYXRMb25FcXVhbHMoYzAsIGMxKSkgewogICAgICAgIGNsZWFuZWRQb3NpdGlvbnNbaW5kZXhdID0gdjEyOwogICAgICAgIGNsZWFuZWRUb3BIZWlnaHRzW2luZGV4XSA9IGMxLmhlaWdodDsKICAgICAgICBpZiAoaGFzQm90dG9tSGVpZ2h0cykgewogICAgICAgICAgY2xlYW5lZEJvdHRvbUhlaWdodHNbaW5kZXhdID0gYm90dG9tSGVpZ2h0c1tpXTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY2xlYW5lZEJvdHRvbUhlaWdodHNbaW5kZXhdID0gMDsKICAgICAgICB9CiAgICAgICAgaGFzQWxsU2FtZUhlaWdodHMgPSBoYXNBbGxTYW1lSGVpZ2h0cyAmJiBjbGVhbmVkVG9wSGVpZ2h0c1tpbmRleF0gPT09IGNsZWFuZWRCb3R0b21IZWlnaHRzW2luZGV4XTsKICAgICAgICBDYXJ0b2dyYXBoaWNfZGVmYXVsdC5jbG9uZShjMSwgYzApOwogICAgICAgICsraW5kZXg7CiAgICAgIH0gZWxzZSBpZiAoYzAuaGVpZ2h0IDwgYzEuaGVpZ2h0KSB7CiAgICAgICAgY2xlYW5lZFRvcEhlaWdodHNbaW5kZXggLSAxXSA9IGMxLmhlaWdodDsKICAgICAgfQogICAgfQogICAgaWYgKGhhc0FsbFNhbWVIZWlnaHRzIHx8IGluZGV4IDwgMikgewogICAgICByZXR1cm47CiAgICB9CiAgICBjbGVhbmVkUG9zaXRpb25zLmxlbmd0aCA9IGluZGV4OwogICAgY2xlYW5lZFRvcEhlaWdodHMubGVuZ3RoID0gaW5kZXg7CiAgICBjbGVhbmVkQm90dG9tSGVpZ2h0cy5sZW5ndGggPSBpbmRleDsKICAgIHJldHVybiB7CiAgICAgIHBvc2l0aW9uczogY2xlYW5lZFBvc2l0aW9ucywKICAgICAgdG9wSGVpZ2h0czogY2xlYW5lZFRvcEhlaWdodHMsCiAgICAgIGJvdHRvbUhlaWdodHM6IGNsZWFuZWRCb3R0b21IZWlnaHRzCiAgICB9OwogIH0KICB2YXIgV2FsbEdlb21ldHJ5TGlicmFyeSwgc2NyYXRjaENhcnRvZ3JhcGhpYzEzLCBzY3JhdGNoQ2FydG9ncmFwaGljMjMsIHBvc2l0aW9uc0FycmF5U2NyYXRjaCwgaGVpZ2h0c0FycmF5U2NyYXRjaCwgZ2VuZXJhdGVBcmNPcHRpb25zU2NyYXRjaDIsIFdhbGxHZW9tZXRyeUxpYnJhcnlfZGVmYXVsdDsKICB2YXIgaW5pdF9XYWxsR2VvbWV0cnlMaWJyYXJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9XYWxsR2VvbWV0cnlMaWJyYXJ5LmpzIigpIHsKICAgICAgaW5pdF9hcnJheVJlbW92ZUR1cGxpY2F0ZXMoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW5pdF9Qb2x5bGluZVBpcGVsaW5lKCk7CiAgICAgIFdhbGxHZW9tZXRyeUxpYnJhcnkgPSB7fTsKICAgICAgc2NyYXRjaENhcnRvZ3JhcGhpYzEzID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0b2dyYXBoaWMyMyA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBwb3NpdGlvbnNBcnJheVNjcmF0Y2ggPSBuZXcgQXJyYXkoMik7CiAgICAgIGhlaWdodHNBcnJheVNjcmF0Y2ggPSBuZXcgQXJyYXkoMik7CiAgICAgIGdlbmVyYXRlQXJjT3B0aW9uc1NjcmF0Y2gyID0gewogICAgICAgIHBvc2l0aW9uczogdm9pZCAwLAogICAgICAgIGhlaWdodDogdm9pZCAwLAogICAgICAgIGdyYW51bGFyaXR5OiB2b2lkIDAsCiAgICAgICAgZWxsaXBzb2lkOiB2b2lkIDAKICAgICAgfTsKICAgICAgV2FsbEdlb21ldHJ5TGlicmFyeS5jb21wdXRlUG9zaXRpb25zID0gZnVuY3Rpb24oZWxsaXBzb2lkLCB3YWxsUG9zaXRpb25zLCBtYXhpbXVtSGVpZ2h0cywgbWluaW11bUhlaWdodHMsIGdyYW51bGFyaXR5LCBkdXBsaWNhdGVDb3JuZXJzKSB7CiAgICAgICAgY29uc3QgbyA9IHJlbW92ZUR1cGxpY2F0ZXMyKAogICAgICAgICAgZWxsaXBzb2lkLAogICAgICAgICAgd2FsbFBvc2l0aW9ucywKICAgICAgICAgIG1heGltdW1IZWlnaHRzLAogICAgICAgICAgbWluaW11bUhlaWdodHMKICAgICAgICApOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KG8pKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIHdhbGxQb3NpdGlvbnMgPSBvLnBvc2l0aW9uczsKICAgICAgICBtYXhpbXVtSGVpZ2h0cyA9IG8udG9wSGVpZ2h0czsKICAgICAgICBtaW5pbXVtSGVpZ2h0cyA9IG8uYm90dG9tSGVpZ2h0czsKICAgICAgICBjb25zdCBsZW5ndGggPSB3YWxsUG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBjb25zdCBudW1Db3JuZXJzID0gbGVuZ3RoIC0gMjsKICAgICAgICBsZXQgdG9wUG9zaXRpb25zOwogICAgICAgIGxldCBib3R0b21Qb3NpdGlvbnM7CiAgICAgICAgY29uc3QgbWluRGlzdGFuY2UgPSBNYXRoX2RlZmF1bHQuY2hvcmRMZW5ndGgoCiAgICAgICAgICBncmFudWxhcml0eSwKICAgICAgICAgIGVsbGlwc29pZC5tYXhpbXVtUmFkaXVzCiAgICAgICAgKTsKICAgICAgICBjb25zdCBnZW5lcmF0ZUFyY09wdGlvbnMgPSBnZW5lcmF0ZUFyY09wdGlvbnNTY3JhdGNoMjsKICAgICAgICBnZW5lcmF0ZUFyY09wdGlvbnMubWluRGlzdGFuY2UgPSBtaW5EaXN0YW5jZTsKICAgICAgICBnZW5lcmF0ZUFyY09wdGlvbnMuZWxsaXBzb2lkID0gZWxsaXBzb2lkOwogICAgICAgIGlmIChkdXBsaWNhdGVDb3JuZXJzKSB7CiAgICAgICAgICBsZXQgY291bnQgPSAwOwogICAgICAgICAgbGV0IGk7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoIC0gMTsgaSsrKSB7CiAgICAgICAgICAgIGNvdW50ICs9IFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdC5udW1iZXJPZlBvaW50cygKICAgICAgICAgICAgICB3YWxsUG9zaXRpb25zW2ldLAogICAgICAgICAgICAgIHdhbGxQb3NpdGlvbnNbaSArIDFdLAogICAgICAgICAgICAgIG1pbkRpc3RhbmNlCiAgICAgICAgICAgICkgKyAxOwogICAgICAgICAgfQogICAgICAgICAgdG9wUG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShjb3VudCAqIDMpOwogICAgICAgICAgYm90dG9tUG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheShjb3VudCAqIDMpOwogICAgICAgICAgY29uc3QgZ2VuZXJhdGVBcmNQb3NpdGlvbnMgPSBwb3NpdGlvbnNBcnJheVNjcmF0Y2g7CiAgICAgICAgICBjb25zdCBnZW5lcmF0ZUFyY0hlaWdodHMgPSBoZWlnaHRzQXJyYXlTY3JhdGNoOwogICAgICAgICAgZ2VuZXJhdGVBcmNPcHRpb25zLnBvc2l0aW9ucyA9IGdlbmVyYXRlQXJjUG9zaXRpb25zOwogICAgICAgICAgZ2VuZXJhdGVBcmNPcHRpb25zLmhlaWdodCA9IGdlbmVyYXRlQXJjSGVpZ2h0czsKICAgICAgICAgIGxldCBvZmZzZXQgPSAwOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aCAtIDE7IGkrKykgewogICAgICAgICAgICBnZW5lcmF0ZUFyY1Bvc2l0aW9uc1swXSA9IHdhbGxQb3NpdGlvbnNbaV07CiAgICAgICAgICAgIGdlbmVyYXRlQXJjUG9zaXRpb25zWzFdID0gd2FsbFBvc2l0aW9uc1tpICsgMV07CiAgICAgICAgICAgIGdlbmVyYXRlQXJjSGVpZ2h0c1swXSA9IG1heGltdW1IZWlnaHRzW2ldOwogICAgICAgICAgICBnZW5lcmF0ZUFyY0hlaWdodHNbMV0gPSBtYXhpbXVtSGVpZ2h0c1tpICsgMV07CiAgICAgICAgICAgIGNvbnN0IHBvcyA9IFBvbHlsaW5lUGlwZWxpbmVfZGVmYXVsdC5nZW5lcmF0ZUFyYyhnZW5lcmF0ZUFyY09wdGlvbnMpOwogICAgICAgICAgICB0b3BQb3NpdGlvbnMuc2V0KHBvcywgb2Zmc2V0KTsKICAgICAgICAgICAgZ2VuZXJhdGVBcmNIZWlnaHRzWzBdID0gbWluaW11bUhlaWdodHNbaV07CiAgICAgICAgICAgIGdlbmVyYXRlQXJjSGVpZ2h0c1sxXSA9IG1pbmltdW1IZWlnaHRzW2kgKyAxXTsKICAgICAgICAgICAgYm90dG9tUG9zaXRpb25zLnNldCgKICAgICAgICAgICAgICBQb2x5bGluZVBpcGVsaW5lX2RlZmF1bHQuZ2VuZXJhdGVBcmMoZ2VuZXJhdGVBcmNPcHRpb25zKSwKICAgICAgICAgICAgICBvZmZzZXQKICAgICAgICAgICAgKTsKICAgICAgICAgICAgb2Zmc2V0ICs9IHBvcy5sZW5ndGg7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGdlbmVyYXRlQXJjT3B0aW9ucy5wb3NpdGlvbnMgPSB3YWxsUG9zaXRpb25zOwogICAgICAgICAgZ2VuZXJhdGVBcmNPcHRpb25zLmhlaWdodCA9IG1heGltdW1IZWlnaHRzOwogICAgICAgICAgdG9wUG9zaXRpb25zID0gbmV3IEZsb2F0NjRBcnJheSgKICAgICAgICAgICAgUG9seWxpbmVQaXBlbGluZV9kZWZhdWx0LmdlbmVyYXRlQXJjKGdlbmVyYXRlQXJjT3B0aW9ucykKICAgICAgICAgICk7CiAgICAgICAgICBnZW5lcmF0ZUFyY09wdGlvbnMuaGVpZ2h0ID0gbWluaW11bUhlaWdodHM7CiAgICAgICAgICBib3R0b21Qb3NpdGlvbnMgPSBuZXcgRmxvYXQ2NEFycmF5KAogICAgICAgICAgICBQb2x5bGluZVBpcGVsaW5lX2RlZmF1bHQuZ2VuZXJhdGVBcmMoZ2VuZXJhdGVBcmNPcHRpb25zKQogICAgICAgICAgKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGJvdHRvbVBvc2l0aW9ucywKICAgICAgICAgIHRvcFBvc2l0aW9ucywKICAgICAgICAgIG51bUNvcm5lcnMKICAgICAgICB9OwogICAgICB9OwogICAgICBXYWxsR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQgPSBXYWxsR2VvbWV0cnlMaWJyYXJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvV2FsbEdlb21ldHJ5LmpzCiAgZnVuY3Rpb24gV2FsbEdlb21ldHJ5KG9wdGlvbnMpIHsKICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgIGNvbnN0IHdhbGxQb3NpdGlvbnMgPSBvcHRpb25zLnBvc2l0aW9uczsKICAgIGNvbnN0IG1heGltdW1IZWlnaHRzID0gb3B0aW9ucy5tYXhpbXVtSGVpZ2h0czsKICAgIGNvbnN0IG1pbmltdW1IZWlnaHRzID0gb3B0aW9ucy5taW5pbXVtSGVpZ2h0czsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHdhbGxQb3NpdGlvbnMpKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJvcHRpb25zLnBvc2l0aW9ucyBpcyByZXF1aXJlZC4iKTsKICAgIH0KICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobWF4aW11bUhlaWdodHMpICYmIG1heGltdW1IZWlnaHRzLmxlbmd0aCAhPT0gd2FsbFBvc2l0aW9ucy5sZW5ndGgpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoCiAgICAgICAgIm9wdGlvbnMucG9zaXRpb25zIGFuZCBvcHRpb25zLm1heGltdW1IZWlnaHRzIG11c3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGguIgogICAgICApOwogICAgfQogICAgaWYgKGRlZmluZWRfZGVmYXVsdChtaW5pbXVtSGVpZ2h0cykgJiYgbWluaW11bUhlaWdodHMubGVuZ3RoICE9PSB3YWxsUG9zaXRpb25zLmxlbmd0aCkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAib3B0aW9ucy5wb3NpdGlvbnMgYW5kIG9wdGlvbnMubWluaW11bUhlaWdodHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aC4iCiAgICAgICk7CiAgICB9CiAgICBjb25zdCB2ZXJ0ZXhGb3JtYXQgPSBvcHRpb25zLnZlcnRleEZvcm1hdCA/PyBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5ERUZBVUxUOwogICAgY29uc3QgZ3JhbnVsYXJpdHkgPSBvcHRpb25zLmdyYW51bGFyaXR5ID8/IE1hdGhfZGVmYXVsdC5SQURJQU5TX1BFUl9ERUdSRUU7CiAgICBjb25zdCBlbGxpcHNvaWQgPSBvcHRpb25zLmVsbGlwc29pZCA/PyBFbGxpcHNvaWRfZGVmYXVsdC5kZWZhdWx0OwogICAgdGhpcy5fcG9zaXRpb25zID0gd2FsbFBvc2l0aW9uczsKICAgIHRoaXMuX21pbmltdW1IZWlnaHRzID0gbWluaW11bUhlaWdodHM7CiAgICB0aGlzLl9tYXhpbXVtSGVpZ2h0cyA9IG1heGltdW1IZWlnaHRzOwogICAgdGhpcy5fdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQuY2xvbmUodmVydGV4Rm9ybWF0KTsKICAgIHRoaXMuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICB0aGlzLl9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShlbGxpcHNvaWQpOwogICAgdGhpcy5fd29ya2VyTmFtZSA9ICJjcmVhdGVXYWxsR2VvbWV0cnkiOwogICAgbGV0IG51bUNvbXBvbmVudHMgPSAxICsgd2FsbFBvc2l0aW9ucy5sZW5ndGggKiBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoICsgMjsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobWluaW11bUhlaWdodHMpKSB7CiAgICAgIG51bUNvbXBvbmVudHMgKz0gbWluaW11bUhlaWdodHMubGVuZ3RoOwogICAgfQogICAgaWYgKGRlZmluZWRfZGVmYXVsdChtYXhpbXVtSGVpZ2h0cykpIHsKICAgICAgbnVtQ29tcG9uZW50cyArPSBtYXhpbXVtSGVpZ2h0cy5sZW5ndGg7CiAgICB9CiAgICB0aGlzLnBhY2tlZExlbmd0aCA9IG51bUNvbXBvbmVudHMgKyBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrZWRMZW5ndGggKyAxOwogIH0KICB2YXIgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjEsIHNjcmF0Y2hDYXJ0ZXNpYW4zUG9zaXRpb24yLCBzY3JhdGNoQ2FydGVzaWFuM1Bvc2l0aW9uNCwgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjUsIHNjcmF0Y2hCaXRhbmdlbnQ1LCBzY3JhdGNoVGFuZ2VudDUsIHNjcmF0Y2hOb3JtYWw4LCBzY3JhdGNoRWxsaXBzb2lkMTcsIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQxMywgc2NyYXRjaE9wdGlvbnMyMywgV2FsbEdlb21ldHJ5X2RlZmF1bHQ7CiAgdmFyIGluaXRfV2FsbEdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9XYWxsR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0JvdW5kaW5nU3BoZXJlKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NvbXBvbmVudERhdGF0eXBlKCk7CiAgICAgIGluaXRfRnJvemVuKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfR2VvbWV0cnkoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZSgpOwogICAgICBpbml0X0dlb21ldHJ5QXR0cmlidXRlcygpOwogICAgICBpbml0X0luZGV4RGF0YXR5cGUoKTsKICAgICAgaW5pdF9NYXRoKCk7CiAgICAgIGluaXRfUHJpbWl0aXZlVHlwZSgpOwogICAgICBpbml0X1ZlcnRleEZvcm1hdCgpOwogICAgICBpbml0X1dhbGxHZW9tZXRyeUxpYnJhcnkoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjEgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4zUG9zaXRpb24yID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoQ2FydGVzaWFuM1Bvc2l0aW9uNCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hCaXRhbmdlbnQ1ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoVGFuZ2VudDUgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHNjcmF0Y2hOb3JtYWw4ID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBXYWxsR2VvbWV0cnkucGFjayA9IGZ1bmN0aW9uKHZhbHVlLCBhcnJheSwgc3RhcnRpbmdJbmRleCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHZhbHVlKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInZhbHVlIGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFycmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gdmFsdWUuX3Bvc2l0aW9uczsKICAgICAgICBsZXQgbGVuZ3RoID0gcG9zaXRpb25zLmxlbmd0aDsKICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gbGVuZ3RoOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSwgc3RhcnRpbmdJbmRleCArPSBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFja2VkTGVuZ3RoKSB7CiAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhwb3NpdGlvbnNbaV0sIGFycmF5LCBzdGFydGluZ0luZGV4KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbWluaW11bUhlaWdodHMgPSB2YWx1ZS5fbWluaW11bUhlaWdodHM7CiAgICAgICAgbGVuZ3RoID0gZGVmaW5lZF9kZWZhdWx0KG1pbmltdW1IZWlnaHRzKSA/IG1pbmltdW1IZWlnaHRzLmxlbmd0aCA6IDA7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IGxlbmd0aDsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG1pbmltdW1IZWlnaHRzKSkgewogICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSBtaW5pbXVtSGVpZ2h0c1tpXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgbWF4aW11bUhlaWdodHMgPSB2YWx1ZS5fbWF4aW11bUhlaWdodHM7CiAgICAgICAgbGVuZ3RoID0gZGVmaW5lZF9kZWZhdWx0KG1heGltdW1IZWlnaHRzKSA/IG1heGltdW1IZWlnaHRzLmxlbmd0aCA6IDA7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IGxlbmd0aDsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG1heGltdW1IZWlnaHRzKSkgewogICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSBtYXhpbXVtSGVpZ2h0c1tpXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgRWxsaXBzb2lkX2RlZmF1bHQucGFjayh2YWx1ZS5fZWxsaXBzb2lkLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgVmVydGV4Rm9ybWF0X2RlZmF1bHQucGFjayh2YWx1ZS5fdmVydGV4Rm9ybWF0LCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBWZXJ0ZXhGb3JtYXRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleF0gPSB2YWx1ZS5fZ3JhbnVsYXJpdHk7CiAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICB9OwogICAgICBzY3JhdGNoRWxsaXBzb2lkMTcgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShFbGxpcHNvaWRfZGVmYXVsdC5VTklUX1NQSEVSRSk7CiAgICAgIHNjcmF0Y2hWZXJ0ZXhGb3JtYXQxMyA9IG5ldyBWZXJ0ZXhGb3JtYXRfZGVmYXVsdCgpOwogICAgICBzY3JhdGNoT3B0aW9uczIzID0gewogICAgICAgIHBvc2l0aW9uczogdm9pZCAwLAogICAgICAgIG1pbmltdW1IZWlnaHRzOiB2b2lkIDAsCiAgICAgICAgbWF4aW11bUhlaWdodHM6IHZvaWQgMCwKICAgICAgICBlbGxpcHNvaWQ6IHNjcmF0Y2hFbGxpcHNvaWQxNywKICAgICAgICB2ZXJ0ZXhGb3JtYXQ6IHNjcmF0Y2hWZXJ0ZXhGb3JtYXQxMywKICAgICAgICBncmFudWxhcml0eTogdm9pZCAwCiAgICAgIH07CiAgICAgIFdhbGxHZW9tZXRyeS51bnBhY2sgPSBmdW5jdGlvbihhcnJheSwgc3RhcnRpbmdJbmRleCwgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoYXJyYXkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgiYXJyYXkgaXMgcmVxdWlyZWQiKTsKICAgICAgICB9CiAgICAgICAgc3RhcnRpbmdJbmRleCA9IHN0YXJ0aW5nSW5kZXggPz8gMDsKICAgICAgICBsZXQgaTsKICAgICAgICBsZXQgbGVuZ3RoID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgQXJyYXkobGVuZ3RoKTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2ksIHN0YXJ0aW5nSW5kZXggKz0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCkgewogICAgICAgICAgcG9zaXRpb25zW2ldID0gQ2FydGVzaWFuM19kZWZhdWx0LnVucGFjayhhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgfQogICAgICAgIGxlbmd0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgbGV0IG1pbmltdW1IZWlnaHRzOwogICAgICAgIGlmIChsZW5ndGggPiAwKSB7CiAgICAgICAgICBtaW5pbXVtSGVpZ2h0cyA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgIG1pbmltdW1IZWlnaHRzW2ldID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbGVuZ3RoID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICBsZXQgbWF4aW11bUhlaWdodHM7CiAgICAgICAgaWYgKGxlbmd0aCA+IDApIHsKICAgICAgICAgIG1heGltdW1IZWlnaHRzID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgbWF4aW11bUhlaWdodHNbaV0gPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHNjcmF0Y2hFbGxpcHNvaWQxNyk7CiAgICAgICAgc3RhcnRpbmdJbmRleCArPSBFbGxpcHNvaWRfZGVmYXVsdC5wYWNrZWRMZW5ndGg7CiAgICAgICAgY29uc3QgdmVydGV4Rm9ybWF0ID0gVmVydGV4Rm9ybWF0X2RlZmF1bHQudW5wYWNrKAogICAgICAgICAgYXJyYXksCiAgICAgICAgICBzdGFydGluZ0luZGV4LAogICAgICAgICAgc2NyYXRjaFZlcnRleEZvcm1hdDEzCiAgICAgICAgKTsKICAgICAgICBzdGFydGluZ0luZGV4ICs9IFZlcnRleEZvcm1hdF9kZWZhdWx0LnBhY2tlZExlbmd0aDsKICAgICAgICBjb25zdCBncmFudWxhcml0eSA9IGFycmF5W3N0YXJ0aW5nSW5kZXhdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHJlc3VsdCkpIHsKICAgICAgICAgIHNjcmF0Y2hPcHRpb25zMjMucG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMyMy5taW5pbXVtSGVpZ2h0cyA9IG1pbmltdW1IZWlnaHRzOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMyMy5tYXhpbXVtSGVpZ2h0cyA9IG1heGltdW1IZWlnaHRzOwogICAgICAgICAgc2NyYXRjaE9wdGlvbnMyMy5ncmFudWxhcml0eSA9IGdyYW51bGFyaXR5OwogICAgICAgICAgcmV0dXJuIG5ldyBXYWxsR2VvbWV0cnkoc2NyYXRjaE9wdGlvbnMyMyk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5fcG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgICAgIHJlc3VsdC5fbWluaW11bUhlaWdodHMgPSBtaW5pbXVtSGVpZ2h0czsKICAgICAgICByZXN1bHQuX21heGltdW1IZWlnaHRzID0gbWF4aW11bUhlaWdodHM7CiAgICAgICAgcmVzdWx0Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShlbGxpcHNvaWQsIHJlc3VsdC5fZWxsaXBzb2lkKTsKICAgICAgICByZXN1bHQuX3ZlcnRleEZvcm1hdCA9IFZlcnRleEZvcm1hdF9kZWZhdWx0LmNsb25lKHZlcnRleEZvcm1hdCwgcmVzdWx0Ll92ZXJ0ZXhGb3JtYXQpOwogICAgICAgIHJlc3VsdC5fZ3JhbnVsYXJpdHkgPSBncmFudWxhcml0eTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBXYWxsR2VvbWV0cnkuZnJvbUNvbnN0YW50SGVpZ2h0cyA9IGZ1bmN0aW9uKG9wdGlvbnMpIHsKICAgICAgICBvcHRpb25zID0gb3B0aW9ucyA/PyBGcm96ZW5fZGVmYXVsdC5FTVBUWV9PQkpFQ1Q7CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gb3B0aW9ucy5wb3NpdGlvbnM7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocG9zaXRpb25zKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9wdGlvbnMucG9zaXRpb25zIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBsZXQgbWluSGVpZ2h0czsKICAgICAgICBsZXQgbWF4SGVpZ2h0czsKICAgICAgICBjb25zdCBtaW4zID0gb3B0aW9ucy5taW5pbXVtSGVpZ2h0OwogICAgICAgIGNvbnN0IG1heDMgPSBvcHRpb25zLm1heGltdW1IZWlnaHQ7CiAgICAgICAgY29uc3QgZG9NaW4gPSBkZWZpbmVkX2RlZmF1bHQobWluMyk7CiAgICAgICAgY29uc3QgZG9NYXggPSBkZWZpbmVkX2RlZmF1bHQobWF4Myk7CiAgICAgICAgaWYgKGRvTWluIHx8IGRvTWF4KSB7CiAgICAgICAgICBjb25zdCBsZW5ndGggPSBwb3NpdGlvbnMubGVuZ3RoOwogICAgICAgICAgbWluSGVpZ2h0cyA9IGRvTWluID8gbmV3IEFycmF5KGxlbmd0aCkgOiB2b2lkIDA7CiAgICAgICAgICBtYXhIZWlnaHRzID0gZG9NYXggPyBuZXcgQXJyYXkobGVuZ3RoKSA6IHZvaWQgMDsKICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgaWYgKGRvTWluKSB7CiAgICAgICAgICAgICAgbWluSGVpZ2h0c1tpXSA9IG1pbjM7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGRvTWF4KSB7CiAgICAgICAgICAgICAgbWF4SGVpZ2h0c1tpXSA9IG1heDM7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgbmV3T3B0aW9ucyA9IHsKICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgIG1heGltdW1IZWlnaHRzOiBtYXhIZWlnaHRzLAogICAgICAgICAgbWluaW11bUhlaWdodHM6IG1pbkhlaWdodHMsCiAgICAgICAgICBlbGxpcHNvaWQ6IG9wdGlvbnMuZWxsaXBzb2lkLAogICAgICAgICAgdmVydGV4Rm9ybWF0OiBvcHRpb25zLnZlcnRleEZvcm1hdAogICAgICAgIH07CiAgICAgICAgcmV0dXJuIG5ldyBXYWxsR2VvbWV0cnkobmV3T3B0aW9ucyk7CiAgICAgIH07CiAgICAgIFdhbGxHZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKHdhbGxHZW9tZXRyeSkgewogICAgICAgIGNvbnN0IHdhbGxQb3NpdGlvbnMgPSB3YWxsR2VvbWV0cnkuX3Bvc2l0aW9uczsKICAgICAgICBjb25zdCBtaW5pbXVtSGVpZ2h0cyA9IHdhbGxHZW9tZXRyeS5fbWluaW11bUhlaWdodHM7CiAgICAgICAgY29uc3QgbWF4aW11bUhlaWdodHMgPSB3YWxsR2VvbWV0cnkuX21heGltdW1IZWlnaHRzOwogICAgICAgIGNvbnN0IHZlcnRleEZvcm1hdCA9IHdhbGxHZW9tZXRyeS5fdmVydGV4Rm9ybWF0OwogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gd2FsbEdlb21ldHJ5Ll9ncmFudWxhcml0eTsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSB3YWxsR2VvbWV0cnkuX2VsbGlwc29pZDsKICAgICAgICBjb25zdCBwb3MgPSBXYWxsR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZVBvc2l0aW9ucygKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIHdhbGxQb3NpdGlvbnMsCiAgICAgICAgICBtYXhpbXVtSGVpZ2h0cywKICAgICAgICAgIG1pbmltdW1IZWlnaHRzLAogICAgICAgICAgZ3JhbnVsYXJpdHksCiAgICAgICAgICB0cnVlCiAgICAgICAgKTsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwb3MpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IGJvdHRvbVBvc2l0aW9ucyA9IHBvcy5ib3R0b21Qb3NpdGlvbnM7CiAgICAgICAgY29uc3QgdG9wUG9zaXRpb25zID0gcG9zLnRvcFBvc2l0aW9uczsKICAgICAgICBjb25zdCBudW1Db3JuZXJzID0gcG9zLm51bUNvcm5lcnM7CiAgICAgICAgbGV0IGxlbmd0aCA9IHRvcFBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgbGV0IHNpemUgPSBsZW5ndGggKiAyOwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IHZlcnRleEZvcm1hdC5wb3NpdGlvbiA/IG5ldyBGbG9hdDY0QXJyYXkoc2l6ZSkgOiB2b2lkIDA7CiAgICAgICAgY29uc3Qgbm9ybWFscyA9IHZlcnRleEZvcm1hdC5ub3JtYWwgPyBuZXcgRmxvYXQzMkFycmF5KHNpemUpIDogdm9pZCAwOwogICAgICAgIGNvbnN0IHRhbmdlbnRzID0gdmVydGV4Rm9ybWF0LnRhbmdlbnQgPyBuZXcgRmxvYXQzMkFycmF5KHNpemUpIDogdm9pZCAwOwogICAgICAgIGNvbnN0IGJpdGFuZ2VudHMgPSB2ZXJ0ZXhGb3JtYXQuYml0YW5nZW50ID8gbmV3IEZsb2F0MzJBcnJheShzaXplKSA6IHZvaWQgMDsKICAgICAgICBjb25zdCB0ZXh0dXJlQ29vcmRpbmF0ZXMgPSB2ZXJ0ZXhGb3JtYXQuc3QgPyBuZXcgRmxvYXQzMkFycmF5KHNpemUgLyAzICogMikgOiB2b2lkIDA7CiAgICAgICAgbGV0IHBvc2l0aW9uSW5kZXggPSAwOwogICAgICAgIGxldCBub3JtYWxJbmRleCA9IDA7CiAgICAgICAgbGV0IGJpdGFuZ2VudEluZGV4ID0gMDsKICAgICAgICBsZXQgdGFuZ2VudEluZGV4ID0gMDsKICAgICAgICBsZXQgc3RJbmRleCA9IDA7CiAgICAgICAgbGV0IG5vcm1hbDIgPSBzY3JhdGNoTm9ybWFsODsKICAgICAgICBsZXQgdGFuZ2VudCA9IHNjcmF0Y2hUYW5nZW50NTsKICAgICAgICBsZXQgYml0YW5nZW50ID0gc2NyYXRjaEJpdGFuZ2VudDU7CiAgICAgICAgbGV0IHJlY29tcHV0ZU5vcm1hbCA9IHRydWU7CiAgICAgICAgbGVuZ3RoIC89IDM7CiAgICAgICAgbGV0IGk7CiAgICAgICAgbGV0IHMgPSAwOwogICAgICAgIGNvbnN0IGRzID0gMSAvIChsZW5ndGggLSBudW1Db3JuZXJzIC0gMSk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICBjb25zdCBpMyA9IGkgKiAzOwogICAgICAgICAgY29uc3QgdG9wUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgICB0b3BQb3NpdGlvbnMsCiAgICAgICAgICAgIGkzLAogICAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuM1Bvc2l0aW9uMQogICAgICAgICAgKTsKICAgICAgICAgIGNvbnN0IGJvdHRvbVBvc2l0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgICAgYm90dG9tUG9zaXRpb25zLAogICAgICAgICAgICBpMywKICAgICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjIKICAgICAgICAgICk7CiAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnBvc2l0aW9uKSB7CiAgICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gYm90dG9tUG9zaXRpb24ueDsKICAgICAgICAgICAgcG9zaXRpb25zW3Bvc2l0aW9uSW5kZXgrK10gPSBib3R0b21Qb3NpdGlvbi55OwogICAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IGJvdHRvbVBvc2l0aW9uLno7CiAgICAgICAgICAgIHBvc2l0aW9uc1twb3NpdGlvbkluZGV4KytdID0gdG9wUG9zaXRpb24ueDsKICAgICAgICAgICAgcG9zaXRpb25zW3Bvc2l0aW9uSW5kZXgrK10gPSB0b3BQb3NpdGlvbi55OwogICAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IHRvcFBvc2l0aW9uLno7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnN0KSB7CiAgICAgICAgICAgIHRleHR1cmVDb29yZGluYXRlc1tzdEluZGV4KytdID0gczsKICAgICAgICAgICAgdGV4dHVyZUNvb3JkaW5hdGVzW3N0SW5kZXgrK10gPSAwOwogICAgICAgICAgICB0ZXh0dXJlQ29vcmRpbmF0ZXNbc3RJbmRleCsrXSA9IHM7CiAgICAgICAgICAgIHRleHR1cmVDb29yZGluYXRlc1tzdEluZGV4KytdID0gMTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2ZXJ0ZXhGb3JtYXQubm9ybWFsIHx8IHZlcnRleEZvcm1hdC50YW5nZW50IHx8IHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgICAgbGV0IG5leHRUb3AgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuY2xvbmUoCiAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LlpFUk8sCiAgICAgICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjUKICAgICAgICAgICAgKTsKICAgICAgICAgICAgY29uc3QgZ3JvdW5kUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgICAgICAgICAgdG9wUG9zaXRpb24sCiAgICAgICAgICAgICAgZWxsaXBzb2lkLmdlb2RldGljU3VyZmFjZU5vcm1hbCgKICAgICAgICAgICAgICAgIHRvcFBvc2l0aW9uLAogICAgICAgICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjIKICAgICAgICAgICAgICApLAogICAgICAgICAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4zUG9zaXRpb24yCiAgICAgICAgICAgICk7CiAgICAgICAgICAgIGlmIChpICsgMSA8IGxlbmd0aCkgewogICAgICAgICAgICAgIG5leHRUb3AgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgICAgICAgdG9wUG9zaXRpb25zLAogICAgICAgICAgICAgICAgaTMgKyAzLAogICAgICAgICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjUKICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChyZWNvbXB1dGVOb3JtYWwpIHsKICAgICAgICAgICAgICBjb25zdCBzY2FsZWRuZXh0UG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgICAgICAgICAgICBuZXh0VG9wLAogICAgICAgICAgICAgICAgdG9wUG9zaXRpb24sCiAgICAgICAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuM1Bvc2l0aW9uNAogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgY29uc3Qgc2NhbGVkR3JvdW5kUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgICAgICAgICAgICBncm91bmRQb3NpdGlvbiwKICAgICAgICAgICAgICAgIHRvcFBvc2l0aW9uLAogICAgICAgICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjEKICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIG5vcm1hbDIgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKHNjYWxlZEdyb3VuZFBvc2l0aW9uLCBzY2FsZWRuZXh0UG9zaXRpb24sIG5vcm1hbDIpLAogICAgICAgICAgICAgICAgbm9ybWFsMgogICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgcmVjb21wdXRlTm9ybWFsID0gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKENhcnRlc2lhbjNfZGVmYXVsdC5lcXVhbHNFcHNpbG9uKHRvcFBvc2l0aW9uLCBuZXh0VG9wLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjEwKSkgewogICAgICAgICAgICAgIHJlY29tcHV0ZU5vcm1hbCA9IHRydWU7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcyArPSBkczsKICAgICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQpIHsKICAgICAgICAgICAgICAgIHRhbmdlbnQgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubm9ybWFsaXplKAogICAgICAgICAgICAgICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QobmV4dFRvcCwgdG9wUG9zaXRpb24sIHRhbmdlbnQpLAogICAgICAgICAgICAgICAgICB0YW5nZW50CiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgICAgICAgICAgYml0YW5nZW50ID0gQ2FydGVzaWFuM19kZWZhdWx0Lm5vcm1hbGl6ZSgKICAgICAgICAgICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKG5vcm1hbDIsIHRhbmdlbnQsIGJpdGFuZ2VudCksCiAgICAgICAgICAgICAgICAgIGJpdGFuZ2VudAogICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5ub3JtYWwpIHsKICAgICAgICAgICAgICBub3JtYWxzW25vcm1hbEluZGV4KytdID0gbm9ybWFsMi54OwogICAgICAgICAgICAgIG5vcm1hbHNbbm9ybWFsSW5kZXgrK10gPSBub3JtYWwyLnk7CiAgICAgICAgICAgICAgbm9ybWFsc1tub3JtYWxJbmRleCsrXSA9IG5vcm1hbDIuejsKICAgICAgICAgICAgICBub3JtYWxzW25vcm1hbEluZGV4KytdID0gbm9ybWFsMi54OwogICAgICAgICAgICAgIG5vcm1hbHNbbm9ybWFsSW5kZXgrK10gPSBub3JtYWwyLnk7CiAgICAgICAgICAgICAgbm9ybWFsc1tub3JtYWxJbmRleCsrXSA9IG5vcm1hbDIuejsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnRhbmdlbnQpIHsKICAgICAgICAgICAgICB0YW5nZW50c1t0YW5nZW50SW5kZXgrK10gPSB0YW5nZW50Lng7CiAgICAgICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC55OwogICAgICAgICAgICAgIHRhbmdlbnRzW3RhbmdlbnRJbmRleCsrXSA9IHRhbmdlbnQuejsKICAgICAgICAgICAgICB0YW5nZW50c1t0YW5nZW50SW5kZXgrK10gPSB0YW5nZW50Lng7CiAgICAgICAgICAgICAgdGFuZ2VudHNbdGFuZ2VudEluZGV4KytdID0gdGFuZ2VudC55OwogICAgICAgICAgICAgIHRhbmdlbnRzW3RhbmdlbnRJbmRleCsrXSA9IHRhbmdlbnQuejsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodmVydGV4Rm9ybWF0LmJpdGFuZ2VudCkgewogICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQueDsKICAgICAgICAgICAgICBiaXRhbmdlbnRzW2JpdGFuZ2VudEluZGV4KytdID0gYml0YW5nZW50Lnk7CiAgICAgICAgICAgICAgYml0YW5nZW50c1tiaXRhbmdlbnRJbmRleCsrXSA9IGJpdGFuZ2VudC56OwogICAgICAgICAgICAgIGJpdGFuZ2VudHNbYml0YW5nZW50SW5kZXgrK10gPSBiaXRhbmdlbnQueDsKICAgICAgICAgICAgICBiaXRhbmdlbnRzW2JpdGFuZ2VudEluZGV4KytdID0gYml0YW5nZW50Lnk7CiAgICAgICAgICAgICAgYml0YW5nZW50c1tiaXRhbmdlbnRJbmRleCsrXSA9IGJpdGFuZ2VudC56OwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoKTsKICAgICAgICBpZiAodmVydGV4Rm9ybWF0LnBvc2l0aW9uKSB7CiAgICAgICAgICBhdHRyaWJ1dGVzLnBvc2l0aW9uID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5ET1VCTEUsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDMsCiAgICAgICAgICAgIHZhbHVlczogcG9zaXRpb25zCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5ub3JtYWwpIHsKICAgICAgICAgIGF0dHJpYnV0ZXMubm9ybWFsID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgdmFsdWVzOiBub3JtYWxzCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC50YW5nZW50KSB7CiAgICAgICAgICBhdHRyaWJ1dGVzLnRhbmdlbnQgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVfZGVmYXVsdCh7CiAgICAgICAgICAgIGNvbXBvbmVudERhdGF0eXBlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LkZMT0FULAogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgICB2YWx1ZXM6IHRhbmdlbnRzCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5iaXRhbmdlbnQpIHsKICAgICAgICAgIGF0dHJpYnV0ZXMuYml0YW5nZW50ID0gbmV3IEdlb21ldHJ5QXR0cmlidXRlX2RlZmF1bHQoewogICAgICAgICAgICBjb21wb25lbnREYXRhdHlwZTogQ29tcG9uZW50RGF0YXR5cGVfZGVmYXVsdC5GTE9BVCwKICAgICAgICAgICAgY29tcG9uZW50c1BlckF0dHJpYnV0ZTogMywKICAgICAgICAgICAgdmFsdWVzOiBiaXRhbmdlbnRzCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaWYgKHZlcnRleEZvcm1hdC5zdCkgewogICAgICAgICAgYXR0cmlidXRlcy5zdCA9IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRkxPQVQsCiAgICAgICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IDIsCiAgICAgICAgICAgIHZhbHVlczogdGV4dHVyZUNvb3JkaW5hdGVzCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbnVtVmVydGljZXMgPSBzaXplIC8gMzsKICAgICAgICBzaXplIC09IDYgKiAobnVtQ29ybmVycyArIDEpOwogICAgICAgIGNvbnN0IGluZGljZXMgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheShudW1WZXJ0aWNlcywgc2l6ZSk7CiAgICAgICAgbGV0IGVkZ2VJbmRleCA9IDA7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IG51bVZlcnRpY2VzIC0gMjsgaSArPSAyKSB7CiAgICAgICAgICBjb25zdCBMTCA9IGk7CiAgICAgICAgICBjb25zdCBMUiA9IGkgKyAyOwogICAgICAgICAgY29uc3QgcGwgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgICBwb3NpdGlvbnMsCiAgICAgICAgICAgIExMICogMywKICAgICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjEKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBwciA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgICAgTFIgKiAzLAogICAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuM1Bvc2l0aW9uMgogICAgICAgICAgKTsKICAgICAgICAgIGlmIChDYXJ0ZXNpYW4zX2RlZmF1bHQuZXF1YWxzRXBzaWxvbihwbCwgcHIsIE1hdGhfZGVmYXVsdC5FUFNJTE9OMTApKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgVUwgPSBpICsgMTsKICAgICAgICAgIGNvbnN0IFVSID0gaSArIDM7CiAgICAgICAgICBpbmRpY2VzW2VkZ2VJbmRleCsrXSA9IFVMOwogICAgICAgICAgaW5kaWNlc1tlZGdlSW5kZXgrK10gPSBMTDsKICAgICAgICAgIGluZGljZXNbZWRnZUluZGV4KytdID0gVVI7CiAgICAgICAgICBpbmRpY2VzW2VkZ2VJbmRleCsrXSA9IFVSOwogICAgICAgICAgaW5kaWNlc1tlZGdlSW5kZXgrK10gPSBMTDsKICAgICAgICAgIGluZGljZXNbZWRnZUluZGV4KytdID0gTFI7CiAgICAgICAgfQogICAgICAgIHJldHVybiBuZXcgR2VvbWV0cnlfZGVmYXVsdCh7CiAgICAgICAgICBhdHRyaWJ1dGVzLAogICAgICAgICAgaW5kaWNlcywKICAgICAgICAgIHByaW1pdGl2ZVR5cGU6IFByaW1pdGl2ZVR5cGVfZGVmYXVsdC5UUklBTkdMRVMsCiAgICAgICAgICBib3VuZGluZ1NwaGVyZTogbmV3IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbVZlcnRpY2VzKHBvc2l0aW9ucykKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgV2FsbEdlb21ldHJ5X2RlZmF1bHQgPSBXYWxsR2VvbWV0cnk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVXYWxsR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlV2FsbEdlb21ldHJ5X2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChjcmVhdGVXYWxsR2VvbWV0cnlfZXhwb3J0cywgewogICAgZGVmYXVsdDogKCkgPT4gY3JlYXRlV2FsbEdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVXYWxsR2VvbWV0cnkod2FsbEdlb21ldHJ5LCBvZmZzZXQpIHsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob2Zmc2V0KSkgewogICAgICB3YWxsR2VvbWV0cnkgPSBXYWxsR2VvbWV0cnlfZGVmYXVsdC51bnBhY2sod2FsbEdlb21ldHJ5LCBvZmZzZXQpOwogICAgfQogICAgd2FsbEdlb21ldHJ5Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZSh3YWxsR2VvbWV0cnkuX2VsbGlwc29pZCk7CiAgICByZXR1cm4gV2FsbEdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkod2FsbEdlb21ldHJ5KTsKICB9CiAgdmFyIGNyZWF0ZVdhbGxHZW9tZXRyeV9kZWZhdWx0OwogIHZhciBpbml0X2NyZWF0ZVdhbGxHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlV2FsbEdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfV2FsbEdlb21ldHJ5KCk7CiAgICAgIGNyZWF0ZVdhbGxHZW9tZXRyeV9kZWZhdWx0ID0gY3JlYXRlV2FsbEdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvV2FsbE91dGxpbmVHZW9tZXRyeS5qcwogIGZ1bmN0aW9uIFdhbGxPdXRsaW5lR2VvbWV0cnkob3B0aW9ucykgewogICAgb3B0aW9ucyA9IG9wdGlvbnMgPz8gRnJvemVuX2RlZmF1bHQuRU1QVFlfT0JKRUNUOwogICAgY29uc3Qgd2FsbFBvc2l0aW9ucyA9IG9wdGlvbnMucG9zaXRpb25zOwogICAgY29uc3QgbWF4aW11bUhlaWdodHMgPSBvcHRpb25zLm1heGltdW1IZWlnaHRzOwogICAgY29uc3QgbWluaW11bUhlaWdodHMgPSBvcHRpb25zLm1pbmltdW1IZWlnaHRzOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQod2FsbFBvc2l0aW9ucykpIHsKICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIm9wdGlvbnMucG9zaXRpb25zIGlzIHJlcXVpcmVkLiIpOwogICAgfQogICAgaWYgKGRlZmluZWRfZGVmYXVsdChtYXhpbXVtSGVpZ2h0cykgJiYgbWF4aW11bUhlaWdodHMubGVuZ3RoICE9PSB3YWxsUG9zaXRpb25zLmxlbmd0aCkgewogICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgKICAgICAgICAib3B0aW9ucy5wb3NpdGlvbnMgYW5kIG9wdGlvbnMubWF4aW11bUhlaWdodHMgbXVzdCBoYXZlIHRoZSBzYW1lIGxlbmd0aC4iCiAgICAgICk7CiAgICB9CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG1pbmltdW1IZWlnaHRzKSAmJiBtaW5pbXVtSGVpZ2h0cy5sZW5ndGggIT09IHdhbGxQb3NpdGlvbnMubGVuZ3RoKSB7CiAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KAogICAgICAgICJvcHRpb25zLnBvc2l0aW9ucyBhbmQgb3B0aW9ucy5taW5pbXVtSGVpZ2h0cyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoLiIKICAgICAgKTsKICAgIH0KICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gb3B0aW9ucy5ncmFudWxhcml0eSA/PyBNYXRoX2RlZmF1bHQuUkFESUFOU19QRVJfREVHUkVFOwogICAgY29uc3QgZWxsaXBzb2lkID0gb3B0aW9ucy5lbGxpcHNvaWQgPz8gRWxsaXBzb2lkX2RlZmF1bHQuZGVmYXVsdDsKICAgIHRoaXMuX3Bvc2l0aW9ucyA9IHdhbGxQb3NpdGlvbnM7CiAgICB0aGlzLl9taW5pbXVtSGVpZ2h0cyA9IG1pbmltdW1IZWlnaHRzOwogICAgdGhpcy5fbWF4aW11bUhlaWdodHMgPSBtYXhpbXVtSGVpZ2h0czsKICAgIHRoaXMuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICB0aGlzLl9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShlbGxpcHNvaWQpOwogICAgdGhpcy5fd29ya2VyTmFtZSA9ICJjcmVhdGVXYWxsT3V0bGluZUdlb21ldHJ5IjsKICAgIGxldCBudW1Db21wb25lbnRzID0gMSArIHdhbGxQb3NpdGlvbnMubGVuZ3RoICogQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCArIDI7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG1pbmltdW1IZWlnaHRzKSkgewogICAgICBudW1Db21wb25lbnRzICs9IG1pbmltdW1IZWlnaHRzLmxlbmd0aDsKICAgIH0KICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobWF4aW11bUhlaWdodHMpKSB7CiAgICAgIG51bUNvbXBvbmVudHMgKz0gbWF4aW11bUhlaWdodHMubGVuZ3RoOwogICAgfQogICAgdGhpcy5wYWNrZWRMZW5ndGggPSBudW1Db21wb25lbnRzICsgRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoICsgMTsKICB9CiAgdmFyIHNjcmF0Y2hDYXJ0ZXNpYW4zUG9zaXRpb24xMiwgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjIyLCBzY3JhdGNoRWxsaXBzb2lkMTgsIHNjcmF0Y2hPcHRpb25zMjQsIFdhbGxPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9XYWxsT3V0bGluZUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9XYWxsT3V0bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjMoKTsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X0Zyb3plbigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9EZXZlbG9wZXJFcnJvcigpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0dlb21ldHJ5KCk7CiAgICAgIGluaXRfR2VvbWV0cnlBdHRyaWJ1dGUoKTsKICAgICAgaW5pdF9HZW9tZXRyeUF0dHJpYnV0ZXMoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X1ByaW1pdGl2ZVR5cGUoKTsKICAgICAgaW5pdF9XYWxsR2VvbWV0cnlMaWJyYXJ5KCk7CiAgICAgIHNjcmF0Y2hDYXJ0ZXNpYW4zUG9zaXRpb24xMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjIyID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBXYWxsT3V0bGluZUdlb21ldHJ5LnBhY2sgPSBmdW5jdGlvbih2YWx1ZSwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh2YWx1ZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ2YWx1ZSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChhcnJheSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJhcnJheSBpcyByZXF1aXJlZCIpOwogICAgICAgIH0KICAgICAgICBzdGFydGluZ0luZGV4ID0gc3RhcnRpbmdJbmRleCA/PyAwOwogICAgICAgIGxldCBpOwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IHZhbHVlLl9wb3NpdGlvbnM7CiAgICAgICAgbGV0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgYXJyYXlbc3RhcnRpbmdJbmRleCsrXSA9IGxlbmd0aDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2ksIHN0YXJ0aW5nSW5kZXggKz0gQ2FydGVzaWFuM19kZWZhdWx0LnBhY2tlZExlbmd0aCkgewogICAgICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2socG9zaXRpb25zW2ldLCBhcnJheSwgc3RhcnRpbmdJbmRleCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG1pbmltdW1IZWlnaHRzID0gdmFsdWUuX21pbmltdW1IZWlnaHRzOwogICAgICAgIGxlbmd0aCA9IGRlZmluZWRfZGVmYXVsdChtaW5pbXVtSGVpZ2h0cykgPyBtaW5pbXVtSGVpZ2h0cy5sZW5ndGggOiAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSBsZW5ndGg7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChtaW5pbXVtSGVpZ2h0cykpIHsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gbWluaW11bUhlaWdodHNbaV07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnN0IG1heGltdW1IZWlnaHRzID0gdmFsdWUuX21heGltdW1IZWlnaHRzOwogICAgICAgIGxlbmd0aCA9IGRlZmluZWRfZGVmYXVsdChtYXhpbXVtSGVpZ2h0cykgPyBtYXhpbXVtSGVpZ2h0cy5sZW5ndGggOiAwOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXgrK10gPSBsZW5ndGg7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChtYXhpbXVtSGVpZ2h0cykpIHsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgICBhcnJheVtzdGFydGluZ0luZGV4KytdID0gbWF4aW11bUhlaWdodHNbaV07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIEVsbGlwc29pZF9kZWZhdWx0LnBhY2sodmFsdWUuX2VsbGlwc29pZCwgYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGFycmF5W3N0YXJ0aW5nSW5kZXhdID0gdmFsdWUuX2dyYW51bGFyaXR5OwogICAgICAgIHJldHVybiBhcnJheTsKICAgICAgfTsKICAgICAgc2NyYXRjaEVsbGlwc29pZDE4ID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUoRWxsaXBzb2lkX2RlZmF1bHQuVU5JVF9TUEhFUkUpOwogICAgICBzY3JhdGNoT3B0aW9uczI0ID0gewogICAgICAgIHBvc2l0aW9uczogdm9pZCAwLAogICAgICAgIG1pbmltdW1IZWlnaHRzOiB2b2lkIDAsCiAgICAgICAgbWF4aW11bUhlaWdodHM6IHZvaWQgMCwKICAgICAgICBlbGxpcHNvaWQ6IHNjcmF0Y2hFbGxpcHNvaWQxOCwKICAgICAgICBncmFudWxhcml0eTogdm9pZCAwCiAgICAgIH07CiAgICAgIFdhbGxPdXRsaW5lR2VvbWV0cnkudW5wYWNrID0gZnVuY3Rpb24oYXJyYXksIHN0YXJ0aW5nSW5kZXgsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGFycmF5KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoImFycmF5IGlzIHJlcXVpcmVkIik7CiAgICAgICAgfQogICAgICAgIHN0YXJ0aW5nSW5kZXggPSBzdGFydGluZ0luZGV4ID8/IDA7CiAgICAgICAgbGV0IGk7CiAgICAgICAgbGV0IGxlbmd0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgY29uc3QgcG9zaXRpb25zID0gbmV3IEFycmF5KGxlbmd0aCk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpLCBzdGFydGluZ0luZGV4ICs9IENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrZWRMZW5ndGgpIHsKICAgICAgICAgIHBvc2l0aW9uc1tpXSA9IENhcnRlc2lhbjNfZGVmYXVsdC51bnBhY2soYXJyYXksIHN0YXJ0aW5nSW5kZXgpOwogICAgICAgIH0KICAgICAgICBsZW5ndGggPSBhcnJheVtzdGFydGluZ0luZGV4KytdOwogICAgICAgIGxldCBtaW5pbXVtSGVpZ2h0czsKICAgICAgICBpZiAobGVuZ3RoID4gMCkgewogICAgICAgICAgbWluaW11bUhlaWdodHMgPSBuZXcgQXJyYXkobGVuZ3RoKTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgICBtaW5pbXVtSGVpZ2h0c1tpXSA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGxlbmd0aCA9IGFycmF5W3N0YXJ0aW5nSW5kZXgrK107CiAgICAgICAgbGV0IG1heGltdW1IZWlnaHRzOwogICAgICAgIGlmIChsZW5ndGggPiAwKSB7CiAgICAgICAgICBtYXhpbXVtSGVpZ2h0cyA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgIG1heGltdW1IZWlnaHRzW2ldID0gYXJyYXlbc3RhcnRpbmdJbmRleCsrXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQudW5wYWNrKGFycmF5LCBzdGFydGluZ0luZGV4LCBzY3JhdGNoRWxsaXBzb2lkMTgpOwogICAgICAgIHN0YXJ0aW5nSW5kZXggKz0gRWxsaXBzb2lkX2RlZmF1bHQucGFja2VkTGVuZ3RoOwogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gYXJyYXlbc3RhcnRpbmdJbmRleF07CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgc2NyYXRjaE9wdGlvbnMyNC5wb3NpdGlvbnMgPSBwb3NpdGlvbnM7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczI0Lm1pbmltdW1IZWlnaHRzID0gbWluaW11bUhlaWdodHM7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczI0Lm1heGltdW1IZWlnaHRzID0gbWF4aW11bUhlaWdodHM7CiAgICAgICAgICBzY3JhdGNoT3B0aW9uczI0LmdyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICAgICAgICByZXR1cm4gbmV3IFdhbGxPdXRsaW5lR2VvbWV0cnkoc2NyYXRjaE9wdGlvbnMyNCk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdC5fcG9zaXRpb25zID0gcG9zaXRpb25zOwogICAgICAgIHJlc3VsdC5fbWluaW11bUhlaWdodHMgPSBtaW5pbXVtSGVpZ2h0czsKICAgICAgICByZXN1bHQuX21heGltdW1IZWlnaHRzID0gbWF4aW11bUhlaWdodHM7CiAgICAgICAgcmVzdWx0Ll9lbGxpcHNvaWQgPSBFbGxpcHNvaWRfZGVmYXVsdC5jbG9uZShlbGxpcHNvaWQsIHJlc3VsdC5fZWxsaXBzb2lkKTsKICAgICAgICByZXN1bHQuX2dyYW51bGFyaXR5ID0gZ3JhbnVsYXJpdHk7CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgV2FsbE91dGxpbmVHZW9tZXRyeS5mcm9tQ29uc3RhbnRIZWlnaHRzID0gZnVuY3Rpb24ob3B0aW9ucykgewogICAgICAgIG9wdGlvbnMgPSBvcHRpb25zID8/IEZyb3plbl9kZWZhdWx0LkVNUFRZX09CSkVDVDsKICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBvcHRpb25zLnBvc2l0aW9uczsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChwb3NpdGlvbnMpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgib3B0aW9ucy5wb3NpdGlvbnMgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGxldCBtaW5IZWlnaHRzOwogICAgICAgIGxldCBtYXhIZWlnaHRzOwogICAgICAgIGNvbnN0IG1pbjMgPSBvcHRpb25zLm1pbmltdW1IZWlnaHQ7CiAgICAgICAgY29uc3QgbWF4MyA9IG9wdGlvbnMubWF4aW11bUhlaWdodDsKICAgICAgICBjb25zdCBkb01pbiA9IGRlZmluZWRfZGVmYXVsdChtaW4zKTsKICAgICAgICBjb25zdCBkb01heCA9IGRlZmluZWRfZGVmYXVsdChtYXgzKTsKICAgICAgICBpZiAoZG9NaW4gfHwgZG9NYXgpIHsKICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgICBtaW5IZWlnaHRzID0gZG9NaW4gPyBuZXcgQXJyYXkobGVuZ3RoKSA6IHZvaWQgMDsKICAgICAgICAgIG1heEhlaWdodHMgPSBkb01heCA/IG5ldyBBcnJheShsZW5ndGgpIDogdm9pZCAwOwogICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgICBpZiAoZG9NaW4pIHsKICAgICAgICAgICAgICBtaW5IZWlnaHRzW2ldID0gbWluMzsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoZG9NYXgpIHsKICAgICAgICAgICAgICBtYXhIZWlnaHRzW2ldID0gbWF4MzsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBuZXdPcHRpb25zID0gewogICAgICAgICAgcG9zaXRpb25zLAogICAgICAgICAgbWF4aW11bUhlaWdodHM6IG1heEhlaWdodHMsCiAgICAgICAgICBtaW5pbXVtSGVpZ2h0czogbWluSGVpZ2h0cywKICAgICAgICAgIGVsbGlwc29pZDogb3B0aW9ucy5lbGxpcHNvaWQKICAgICAgICB9OwogICAgICAgIHJldHVybiBuZXcgV2FsbE91dGxpbmVHZW9tZXRyeShuZXdPcHRpb25zKTsKICAgICAgfTsKICAgICAgV2FsbE91dGxpbmVHZW9tZXRyeS5jcmVhdGVHZW9tZXRyeSA9IGZ1bmN0aW9uKHdhbGxHZW9tZXRyeSkgewogICAgICAgIGNvbnN0IHdhbGxQb3NpdGlvbnMgPSB3YWxsR2VvbWV0cnkuX3Bvc2l0aW9uczsKICAgICAgICBjb25zdCBtaW5pbXVtSGVpZ2h0cyA9IHdhbGxHZW9tZXRyeS5fbWluaW11bUhlaWdodHM7CiAgICAgICAgY29uc3QgbWF4aW11bUhlaWdodHMgPSB3YWxsR2VvbWV0cnkuX21heGltdW1IZWlnaHRzOwogICAgICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gd2FsbEdlb21ldHJ5Ll9ncmFudWxhcml0eTsKICAgICAgICBjb25zdCBlbGxpcHNvaWQgPSB3YWxsR2VvbWV0cnkuX2VsbGlwc29pZDsKICAgICAgICBjb25zdCBwb3MgPSBXYWxsR2VvbWV0cnlMaWJyYXJ5X2RlZmF1bHQuY29tcHV0ZVBvc2l0aW9ucygKICAgICAgICAgIGVsbGlwc29pZCwKICAgICAgICAgIHdhbGxQb3NpdGlvbnMsCiAgICAgICAgICBtYXhpbXVtSGVpZ2h0cywKICAgICAgICAgIG1pbmltdW1IZWlnaHRzLAogICAgICAgICAgZ3JhbnVsYXJpdHksCiAgICAgICAgICBmYWxzZQogICAgICAgICk7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocG9zKSkgewogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBjb25zdCBib3R0b21Qb3NpdGlvbnMgPSBwb3MuYm90dG9tUG9zaXRpb25zOwogICAgICAgIGNvbnN0IHRvcFBvc2l0aW9ucyA9IHBvcy50b3BQb3NpdGlvbnM7CiAgICAgICAgbGV0IGxlbmd0aCA9IHRvcFBvc2l0aW9ucy5sZW5ndGg7CiAgICAgICAgbGV0IHNpemUgPSBsZW5ndGggKiAyOwogICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkoc2l6ZSk7CiAgICAgICAgbGV0IHBvc2l0aW9uSW5kZXggPSAwOwogICAgICAgIGxlbmd0aCAvPSAzOwogICAgICAgIGxldCBpOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgY29uc3QgaTMgPSBpICogMzsKICAgICAgICAgIGNvbnN0IHRvcFBvc2l0aW9uID0gQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheSgKICAgICAgICAgICAgdG9wUG9zaXRpb25zLAogICAgICAgICAgICBpMywKICAgICAgICAgICAgc2NyYXRjaENhcnRlc2lhbjNQb3NpdGlvbjEyCiAgICAgICAgICApOwogICAgICAgICAgY29uc3QgYm90dG9tUG9zaXRpb24gPSBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KAogICAgICAgICAgICBib3R0b21Qb3NpdGlvbnMsCiAgICAgICAgICAgIGkzLAogICAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuM1Bvc2l0aW9uMjIKICAgICAgICAgICk7CiAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IGJvdHRvbVBvc2l0aW9uLng7CiAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IGJvdHRvbVBvc2l0aW9uLnk7CiAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IGJvdHRvbVBvc2l0aW9uLno7CiAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IHRvcFBvc2l0aW9uLng7CiAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IHRvcFBvc2l0aW9uLnk7CiAgICAgICAgICBwb3NpdGlvbnNbcG9zaXRpb25JbmRleCsrXSA9IHRvcFBvc2l0aW9uLno7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBuZXcgR2VvbWV0cnlBdHRyaWJ1dGVzX2RlZmF1bHQoewogICAgICAgICAgcG9zaXRpb246IG5ldyBHZW9tZXRyeUF0dHJpYnV0ZV9kZWZhdWx0KHsKICAgICAgICAgICAgY29tcG9uZW50RGF0YXR5cGU6IENvbXBvbmVudERhdGF0eXBlX2RlZmF1bHQuRE9VQkxFLAogICAgICAgICAgICBjb21wb25lbnRzUGVyQXR0cmlidXRlOiAzLAogICAgICAgICAgICB2YWx1ZXM6IHBvc2l0aW9ucwogICAgICAgICAgfSkKICAgICAgICB9KTsKICAgICAgICBjb25zdCBudW1WZXJ0aWNlcyA9IHNpemUgLyAzOwogICAgICAgIHNpemUgPSAyICogbnVtVmVydGljZXMgLSA0ICsgbnVtVmVydGljZXM7CiAgICAgICAgY29uc3QgaW5kaWNlcyA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KG51bVZlcnRpY2VzLCBzaXplKTsKICAgICAgICBsZXQgZWRnZUluZGV4ID0gMDsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtVmVydGljZXMgLSAyOyBpICs9IDIpIHsKICAgICAgICAgIGNvbnN0IExMID0gaTsKICAgICAgICAgIGNvbnN0IExSID0gaSArIDI7CiAgICAgICAgICBjb25zdCBwbCA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgICAgTEwgKiAzLAogICAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuM1Bvc2l0aW9uMTIKICAgICAgICAgICk7CiAgICAgICAgICBjb25zdCBwciA9IENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkoCiAgICAgICAgICAgIHBvc2l0aW9ucywKICAgICAgICAgICAgTFIgKiAzLAogICAgICAgICAgICBzY3JhdGNoQ2FydGVzaWFuM1Bvc2l0aW9uMjIKICAgICAgICAgICk7CiAgICAgICAgICBpZiAoQ2FydGVzaWFuM19kZWZhdWx0LmVxdWFsc0Vwc2lsb24ocGwsIHByLCBNYXRoX2RlZmF1bHQuRVBTSUxPTjEwKSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IFVMID0gaSArIDE7CiAgICAgICAgICBjb25zdCBVUiA9IGkgKyAzOwogICAgICAgICAgaW5kaWNlc1tlZGdlSW5kZXgrK10gPSBVTDsKICAgICAgICAgIGluZGljZXNbZWRnZUluZGV4KytdID0gTEw7CiAgICAgICAgICBpbmRpY2VzW2VkZ2VJbmRleCsrXSA9IFVMOwogICAgICAgICAgaW5kaWNlc1tlZGdlSW5kZXgrK10gPSBVUjsKICAgICAgICAgIGluZGljZXNbZWRnZUluZGV4KytdID0gTEw7CiAgICAgICAgICBpbmRpY2VzW2VkZ2VJbmRleCsrXSA9IExSOwogICAgICAgIH0KICAgICAgICBpbmRpY2VzW2VkZ2VJbmRleCsrXSA9IG51bVZlcnRpY2VzIC0gMjsKICAgICAgICBpbmRpY2VzW2VkZ2VJbmRleCsrXSA9IG51bVZlcnRpY2VzIC0gMTsKICAgICAgICByZXR1cm4gbmV3IEdlb21ldHJ5X2RlZmF1bHQoewogICAgICAgICAgYXR0cmlidXRlcywKICAgICAgICAgIGluZGljZXMsCiAgICAgICAgICBwcmltaXRpdmVUeXBlOiBQcmltaXRpdmVUeXBlX2RlZmF1bHQuTElORVMsCiAgICAgICAgICBib3VuZGluZ1NwaGVyZTogbmV3IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQuZnJvbVZlcnRpY2VzKHBvc2l0aW9ucykKICAgICAgICB9KTsKICAgICAgfTsKICAgICAgV2FsbE91dGxpbmVHZW9tZXRyeV9kZWZhdWx0ID0gV2FsbE91dGxpbmVHZW9tZXRyeTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZVdhbGxPdXRsaW5lR2VvbWV0cnkuanMKICB2YXIgY3JlYXRlV2FsbE91dGxpbmVHZW9tZXRyeV9leHBvcnRzID0ge307CiAgX19leHBvcnQoY3JlYXRlV2FsbE91dGxpbmVHZW9tZXRyeV9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVXYWxsT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiBjcmVhdGVXYWxsT3V0bGluZUdlb21ldHJ5KHdhbGxHZW9tZXRyeSwgb2Zmc2V0KSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG9mZnNldCkpIHsKICAgICAgd2FsbEdlb21ldHJ5ID0gV2FsbE91dGxpbmVHZW9tZXRyeV9kZWZhdWx0LnVucGFjayh3YWxsR2VvbWV0cnksIG9mZnNldCk7CiAgICB9CiAgICB3YWxsR2VvbWV0cnkuX2VsbGlwc29pZCA9IEVsbGlwc29pZF9kZWZhdWx0LmNsb25lKHdhbGxHZW9tZXRyeS5fZWxsaXBzb2lkKTsKICAgIHJldHVybiBXYWxsT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQuY3JlYXRlR2VvbWV0cnkod2FsbEdlb21ldHJ5KTsKICB9CiAgdmFyIGNyZWF0ZVdhbGxPdXRsaW5lR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVXYWxsT3V0bGluZUdlb21ldHJ5ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVXYWxsT3V0bGluZUdlb21ldHJ5LmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfV2FsbE91dGxpbmVHZW9tZXRyeSgpOwogICAgICBjcmVhdGVXYWxsT3V0bGluZUdlb21ldHJ5X2RlZmF1bHQgPSBjcmVhdGVXYWxsT3V0bGluZUdlb21ldHJ5OwogICAgfQogIH0pOwoKICAvLyBub2RlX21vZHVsZXMvZHJhY28zZC9kcmFjb19kZWNvZGVyX25vZGVqcy5qcwogIHZhciByZXF1aXJlX2RyYWNvX2RlY29kZXJfbm9kZWpzID0gX19jb21tb25KUyh7CiAgICAibm9kZV9tb2R1bGVzL2RyYWNvM2QvZHJhY29fZGVjb2Rlcl9ub2RlanMuanMiKGV4cG9ydHMyLCBtb2R1bGUpIHsKICAgICAgdmFyICRqc2NvbXAgPSAkanNjb21wIHx8IHt9OwogICAgICAkanNjb21wLnNjb3BlID0ge307CiAgICAgICRqc2NvbXAuYXJyYXlJdGVyYXRvckltcGwgPSBmdW5jdGlvbihrKSB7CiAgICAgICAgdmFyIG4gPSAwOwogICAgICAgIHJldHVybiBmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiBuIDwgay5sZW5ndGggPyB7IGRvbmU6IGZhbHNlLCB2YWx1ZToga1tuKytdIH0gOiB7IGRvbmU6IHRydWUgfTsKICAgICAgICB9OwogICAgICB9OwogICAgICAkanNjb21wLmFycmF5SXRlcmF0b3IgPSBmdW5jdGlvbihrKSB7CiAgICAgICAgcmV0dXJuIHsgbmV4dDogJGpzY29tcC5hcnJheUl0ZXJhdG9ySW1wbChrKSB9OwogICAgICB9OwogICAgICAkanNjb21wLm1ha2VJdGVyYXRvciA9IGZ1bmN0aW9uKGspIHsKICAgICAgICB2YXIgbiA9ICJ1bmRlZmluZWQiICE9IHR5cGVvZiBTeW1ib2wgJiYgU3ltYm9sLml0ZXJhdG9yICYmIGtbU3ltYm9sLml0ZXJhdG9yXTsKICAgICAgICByZXR1cm4gbiA/IG4uY2FsbChrKSA6ICRqc2NvbXAuYXJyYXlJdGVyYXRvcihrKTsKICAgICAgfTsKICAgICAgJGpzY29tcC5BU1NVTUVfRVM1ID0gZmFsc2U7CiAgICAgICRqc2NvbXAuQVNTVU1FX05PX05BVElWRV9NQVAgPSBmYWxzZTsKICAgICAgJGpzY29tcC5BU1NVTUVfTk9fTkFUSVZFX1NFVCA9IGZhbHNlOwogICAgICAkanNjb21wLlNJTVBMRV9GUk9VTkRfUE9MWUZJTEwgPSBmYWxzZTsKICAgICAgJGpzY29tcC5JU09MQVRFX1BPTFlGSUxMUyA9IGZhbHNlOwogICAgICAkanNjb21wLkZPUkNFX1BPTFlGSUxMX1BST01JU0UgPSBmYWxzZTsKICAgICAgJGpzY29tcC5GT1JDRV9QT0xZRklMTF9QUk9NSVNFX1dIRU5fTk9fVU5IQU5ETEVEX1JFSkVDVElPTiA9IGZhbHNlOwogICAgICAkanNjb21wLmdldEdsb2JhbCA9IGZ1bmN0aW9uKGspIHsKICAgICAgICBrID0gWyJvYmplY3QiID09IHR5cGVvZiBnbG9iYWxUaGlzICYmIGdsb2JhbFRoaXMsIGssICJvYmplY3QiID09IHR5cGVvZiB3aW5kb3cgJiYgd2luZG93LCAib2JqZWN0IiA9PSB0eXBlb2Ygc2VsZiAmJiBzZWxmLCAib2JqZWN0IiA9PSB0eXBlb2YgZ2xvYmFsICYmIGdsb2JhbF07CiAgICAgICAgZm9yICh2YXIgbiA9IDA7IG4gPCBrLmxlbmd0aDsgKytuKSB7CiAgICAgICAgICB2YXIgbCA9IGtbbl07CiAgICAgICAgICBpZiAobCAmJiBsLk1hdGggPT0gTWF0aCkgcmV0dXJuIGw7CiAgICAgICAgfQogICAgICAgIHRocm93IEVycm9yKCJDYW5ub3QgZmluZCBnbG9iYWwgb2JqZWN0Iik7CiAgICAgIH07CiAgICAgICRqc2NvbXAuZ2xvYmFsID0gJGpzY29tcC5nZXRHbG9iYWwoZXhwb3J0czIpOwogICAgICAkanNjb21wLmRlZmluZVByb3BlcnR5ID0gJGpzY29tcC5BU1NVTUVfRVM1IHx8ICJmdW5jdGlvbiIgPT0gdHlwZW9mIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzID8gT2JqZWN0LmRlZmluZVByb3BlcnR5IDogZnVuY3Rpb24oaywgbiwgbCkgewogICAgICAgIGlmIChrID09IEFycmF5LnByb3RvdHlwZSB8fCBrID09IE9iamVjdC5wcm90b3R5cGUpIHJldHVybiBrOwogICAgICAgIGtbbl0gPSBsLnZhbHVlOwogICAgICAgIHJldHVybiBrOwogICAgICB9OwogICAgICAkanNjb21wLklTX1NZTUJPTF9OQVRJVkUgPSAiZnVuY3Rpb24iID09PSB0eXBlb2YgU3ltYm9sICYmICJzeW1ib2wiID09PSB0eXBlb2YgU3ltYm9sKCJ4Iik7CiAgICAgICRqc2NvbXAuVFJVU1RfRVM2X1BPTFlGSUxMUyA9ICEkanNjb21wLklTT0xBVEVfUE9MWUZJTExTIHx8ICRqc2NvbXAuSVNfU1lNQk9MX05BVElWRTsKICAgICAgJGpzY29tcC5wb2x5ZmlsbHMgPSB7fTsKICAgICAgJGpzY29tcC5wcm9wZXJ0eVRvUG9seWZpbGxTeW1ib2wgPSB7fTsKICAgICAgJGpzY29tcC5QT0xZRklMTF9QUkVGSVggPSAiJGpzY3AkIjsKICAgICAgJGpzY29tcC5wb2x5ZmlsbCA9IGZ1bmN0aW9uKGssIG4sIGwsIHApIHsKICAgICAgICBuICYmICgkanNjb21wLklTT0xBVEVfUE9MWUZJTExTID8gJGpzY29tcC5wb2x5ZmlsbElzb2xhdGVkKGssIG4sIGwsIHApIDogJGpzY29tcC5wb2x5ZmlsbFVuaXNvbGF0ZWQoaywgbiwgbCwgcCkpOwogICAgICB9OwogICAgICAkanNjb21wLnBvbHlmaWxsVW5pc29sYXRlZCA9IGZ1bmN0aW9uKGssIG4sIGwsIHApIHsKICAgICAgICBsID0gJGpzY29tcC5nbG9iYWw7CiAgICAgICAgayA9IGsuc3BsaXQoIi4iKTsKICAgICAgICBmb3IgKHAgPSAwOyBwIDwgay5sZW5ndGggLSAxOyBwKyspIHsKICAgICAgICAgIHZhciBoID0ga1twXTsKICAgICAgICAgIGlmICghKGggaW4gbCkpIHJldHVybjsKICAgICAgICAgIGwgPSBsW2hdOwogICAgICAgIH0KICAgICAgICBrID0ga1trLmxlbmd0aCAtIDFdOwogICAgICAgIHAgPSBsW2tdOwogICAgICAgIG4gPSBuKHApOwogICAgICAgIG4gIT0gcCAmJiBudWxsICE9IG4gJiYgJGpzY29tcC5kZWZpbmVQcm9wZXJ0eShsLCBrLCB7IGNvbmZpZ3VyYWJsZTogdHJ1ZSwgd3JpdGFibGU6IHRydWUsIHZhbHVlOiBuIH0pOwogICAgICB9OwogICAgICAkanNjb21wLnBvbHlmaWxsSXNvbGF0ZWQgPSBmdW5jdGlvbihrLCBuLCBsLCBwKSB7CiAgICAgICAgdmFyIGggPSBrLnNwbGl0KCIuIik7CiAgICAgICAgayA9IDEgPT09IGgubGVuZ3RoOwogICAgICAgIHAgPSBoWzBdOwogICAgICAgIHAgPSAhayAmJiBwIGluICRqc2NvbXAucG9seWZpbGxzID8gJGpzY29tcC5wb2x5ZmlsbHMgOiAkanNjb21wLmdsb2JhbDsKICAgICAgICBmb3IgKHZhciBBID0gMDsgQSA8IGgubGVuZ3RoIC0gMTsgQSsrKSB7CiAgICAgICAgICB2YXIgZiA9IGhbQV07CiAgICAgICAgICBpZiAoIShmIGluIHApKSByZXR1cm47CiAgICAgICAgICBwID0gcFtmXTsKICAgICAgICB9CiAgICAgICAgaCA9IGhbaC5sZW5ndGggLSAxXTsKICAgICAgICBsID0gJGpzY29tcC5JU19TWU1CT0xfTkFUSVZFICYmICJlczYiID09PSBsID8gcFtoXSA6IG51bGw7CiAgICAgICAgbiA9IG4obCk7CiAgICAgICAgbnVsbCAhPSBuICYmIChrID8gJGpzY29tcC5kZWZpbmVQcm9wZXJ0eSgkanNjb21wLnBvbHlmaWxscywgaCwgeyBjb25maWd1cmFibGU6IHRydWUsIHdyaXRhYmxlOiB0cnVlLCB2YWx1ZTogbiB9KSA6IG4gIT09IGwgJiYgKHZvaWQgMCA9PT0gJGpzY29tcC5wcm9wZXJ0eVRvUG9seWZpbGxTeW1ib2xbaF0gJiYgKGwgPSAxZTkgKiBNYXRoLnJhbmRvbSgpID4+PiAwLCAkanNjb21wLnByb3BlcnR5VG9Qb2x5ZmlsbFN5bWJvbFtoXSA9ICRqc2NvbXAuSVNfU1lNQk9MX05BVElWRSA/ICRqc2NvbXAuZ2xvYmFsLlN5bWJvbChoKSA6ICRqc2NvbXAuUE9MWUZJTExfUFJFRklYICsgbCArICIkIiArIGgpLCAkanNjb21wLmRlZmluZVByb3BlcnR5KHAsICRqc2NvbXAucHJvcGVydHlUb1BvbHlmaWxsU3ltYm9sW2hdLCB7IGNvbmZpZ3VyYWJsZTogdHJ1ZSwgd3JpdGFibGU6IHRydWUsIHZhbHVlOiBuIH0pKSk7CiAgICAgIH07CiAgICAgICRqc2NvbXAucG9seWZpbGwoIlByb21pc2UiLCBmdW5jdGlvbihrKSB7CiAgICAgICAgZnVuY3Rpb24gbigpIHsKICAgICAgICAgIHRoaXMuYmF0Y2hfID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gbChmKSB7CiAgICAgICAgICByZXR1cm4gZiBpbnN0YW5jZW9mIGggPyBmIDogbmV3IGgoZnVuY3Rpb24ocSwgdjMpIHsKICAgICAgICAgICAgcShmKTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBpZiAoayAmJiAoISgkanNjb21wLkZPUkNFX1BPTFlGSUxMX1BST01JU0UgfHwgJGpzY29tcC5GT1JDRV9QT0xZRklMTF9QUk9NSVNFX1dIRU5fTk9fVU5IQU5ETEVEX1JFSkVDVElPTiAmJiAidW5kZWZpbmVkIiA9PT0gdHlwZW9mICRqc2NvbXAuZ2xvYmFsLlByb21pc2VSZWplY3Rpb25FdmVudCkgfHwgISRqc2NvbXAuZ2xvYmFsLlByb21pc2UgfHwgLTEgPT09ICRqc2NvbXAuZ2xvYmFsLlByb21pc2UudG9TdHJpbmcoKS5pbmRleE9mKCJbbmF0aXZlIGNvZGVdIikpKSByZXR1cm4gazsKICAgICAgICBuLnByb3RvdHlwZS5hc3luY0V4ZWN1dGUgPSBmdW5jdGlvbihmKSB7CiAgICAgICAgICBpZiAobnVsbCA9PSB0aGlzLmJhdGNoXykgewogICAgICAgICAgICB0aGlzLmJhdGNoXyA9IFtdOwogICAgICAgICAgICB2YXIgcSA9IHRoaXM7CiAgICAgICAgICAgIHRoaXMuYXN5bmNFeGVjdXRlRnVuY3Rpb24oZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcS5leGVjdXRlQmF0Y2hfKCk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5iYXRjaF8ucHVzaChmKTsKICAgICAgICB9OwogICAgICAgIHZhciBwID0gJGpzY29tcC5nbG9iYWwuc2V0VGltZW91dDsKICAgICAgICBuLnByb3RvdHlwZS5hc3luY0V4ZWN1dGVGdW5jdGlvbiA9IGZ1bmN0aW9uKGYpIHsKICAgICAgICAgIHAoZiwgMCk7CiAgICAgICAgfTsKICAgICAgICBuLnByb3RvdHlwZS5leGVjdXRlQmF0Y2hfID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICBmb3IgKDsgdGhpcy5iYXRjaF8gJiYgdGhpcy5iYXRjaF8ubGVuZ3RoOyApIHsKICAgICAgICAgICAgdmFyIGYgPSB0aGlzLmJhdGNoXzsKICAgICAgICAgICAgdGhpcy5iYXRjaF8gPSBbXTsKICAgICAgICAgICAgZm9yICh2YXIgcSA9IDA7IHEgPCBmLmxlbmd0aDsgKytxKSB7CiAgICAgICAgICAgICAgdmFyIHYzID0gZltxXTsKICAgICAgICAgICAgICBmW3FdID0gbnVsbDsKICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgdjMoKTsKICAgICAgICAgICAgICB9IGNhdGNoICh6KSB7CiAgICAgICAgICAgICAgICB0aGlzLmFzeW5jVGhyb3dfKHopOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgdGhpcy5iYXRjaF8gPSBudWxsOwogICAgICAgIH07CiAgICAgICAgbi5wcm90b3R5cGUuYXN5bmNUaHJvd18gPSBmdW5jdGlvbihmKSB7CiAgICAgICAgICB0aGlzLmFzeW5jRXhlY3V0ZUZ1bmN0aW9uKGZ1bmN0aW9uKCkgewogICAgICAgICAgICB0aHJvdyBmOwogICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICB2YXIgaCA9IGZ1bmN0aW9uKGYpIHsKICAgICAgICAgIHRoaXMuc3RhdGVfID0gMDsKICAgICAgICAgIHRoaXMucmVzdWx0XyA9IHZvaWQgMDsKICAgICAgICAgIHRoaXMub25TZXR0bGVkQ2FsbGJhY2tzXyA9IFtdOwogICAgICAgICAgdGhpcy5pc1JlamVjdGlvbkhhbmRsZWRfID0gZmFsc2U7CiAgICAgICAgICB2YXIgcSA9IHRoaXMuY3JlYXRlUmVzb2x2ZUFuZFJlamVjdF8oKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGYocS5yZXNvbHZlLCBxLnJlamVjdCk7CiAgICAgICAgICB9IGNhdGNoICh2MykgewogICAgICAgICAgICBxLnJlamVjdCh2Myk7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICBoLnByb3RvdHlwZS5jcmVhdGVSZXNvbHZlQW5kUmVqZWN0XyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgZnVuY3Rpb24gZih6KSB7CiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihPKSB7CiAgICAgICAgICAgICAgdjMgfHwgKHYzID0gdHJ1ZSwgei5jYWxsKHEsIE8pKTsKICAgICAgICAgICAgfTsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBxID0gdGhpcywgdjMgPSBmYWxzZTsKICAgICAgICAgIHJldHVybiB7IHJlc29sdmU6IGYodGhpcy5yZXNvbHZlVG9fKSwgcmVqZWN0OiBmKHRoaXMucmVqZWN0XykgfTsKICAgICAgICB9OwogICAgICAgIGgucHJvdG90eXBlLnJlc29sdmVUb18gPSBmdW5jdGlvbihmKSB7CiAgICAgICAgICBpZiAoZiA9PT0gdGhpcykgdGhpcy5yZWplY3RfKG5ldyBUeXBlRXJyb3IoIkEgUHJvbWlzZSBjYW5ub3QgcmVzb2x2ZSB0byBpdHNlbGYiKSk7CiAgICAgICAgICBlbHNlIGlmIChmIGluc3RhbmNlb2YgaCkgdGhpcy5zZXR0bGVTYW1lQXNQcm9taXNlXyhmKTsKICAgICAgICAgIGVsc2UgewogICAgICAgICAgICBhOiBzd2l0Y2ggKHR5cGVvZiBmKSB7CiAgICAgICAgICAgICAgY2FzZSAib2JqZWN0IjoKICAgICAgICAgICAgICAgIHZhciBxID0gbnVsbCAhPSBmOwogICAgICAgICAgICAgICAgYnJlYWsgYTsKICAgICAgICAgICAgICBjYXNlICJmdW5jdGlvbiI6CiAgICAgICAgICAgICAgICBxID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrIGE7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHEgPSBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBxID8gdGhpcy5yZXNvbHZlVG9Ob25Qcm9taXNlT2JqXyhmKSA6IHRoaXMuZnVsZmlsbF8oZik7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICBoLnByb3RvdHlwZS5yZXNvbHZlVG9Ob25Qcm9taXNlT2JqXyA9IGZ1bmN0aW9uKGYpIHsKICAgICAgICAgIHZhciBxID0gdm9pZCAwOwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcSA9IGYudGhlbjsKICAgICAgICAgIH0gY2F0Y2ggKHYzKSB7CiAgICAgICAgICAgIHRoaXMucmVqZWN0Xyh2Myk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgICJmdW5jdGlvbiIgPT0gdHlwZW9mIHEgPyB0aGlzLnNldHRsZVNhbWVBc1RoZW5hYmxlXyhxLCBmKSA6IHRoaXMuZnVsZmlsbF8oZik7CiAgICAgICAgfTsKICAgICAgICBoLnByb3RvdHlwZS5yZWplY3RfID0gZnVuY3Rpb24oZikgewogICAgICAgICAgdGhpcy5zZXR0bGVfKDIsIGYpOwogICAgICAgIH07CiAgICAgICAgaC5wcm90b3R5cGUuZnVsZmlsbF8gPSBmdW5jdGlvbihmKSB7CiAgICAgICAgICB0aGlzLnNldHRsZV8oMSwgZik7CiAgICAgICAgfTsKICAgICAgICBoLnByb3RvdHlwZS5zZXR0bGVfID0gZnVuY3Rpb24oZiwgcSkgewogICAgICAgICAgaWYgKDAgIT0gdGhpcy5zdGF0ZV8pIHRocm93IEVycm9yKCJDYW5ub3Qgc2V0dGxlKCIgKyBmICsgIiwgIiArIHEgKyAiKTogUHJvbWlzZSBhbHJlYWR5IHNldHRsZWQgaW4gc3RhdGUiICsgdGhpcy5zdGF0ZV8pOwogICAgICAgICAgdGhpcy5zdGF0ZV8gPSBmOwogICAgICAgICAgdGhpcy5yZXN1bHRfID0gcTsKICAgICAgICAgIDIgPT09IHRoaXMuc3RhdGVfICYmIHRoaXMuc2NoZWR1bGVVbmhhbmRsZWRSZWplY3Rpb25DaGVja18oKTsKICAgICAgICAgIHRoaXMuZXhlY3V0ZU9uU2V0dGxlZENhbGxiYWNrc18oKTsKICAgICAgICB9OwogICAgICAgIGgucHJvdG90eXBlLnNjaGVkdWxlVW5oYW5kbGVkUmVqZWN0aW9uQ2hlY2tfID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICB2YXIgZiA9IHRoaXM7CiAgICAgICAgICBwKGZ1bmN0aW9uKCkgewogICAgICAgICAgICBpZiAoZi5ub3RpZnlVbmhhbmRsZWRSZWplY3Rpb25fKCkpIHsKICAgICAgICAgICAgICB2YXIgcSA9ICRqc2NvbXAuZ2xvYmFsLmNvbnNvbGU7CiAgICAgICAgICAgICAgInVuZGVmaW5lZCIgIT09IHR5cGVvZiBxICYmIHEuZXJyb3IoZi5yZXN1bHRfKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSwgMSk7CiAgICAgICAgfTsKICAgICAgICBoLnByb3RvdHlwZS5ub3RpZnlVbmhhbmRsZWRSZWplY3Rpb25fID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICBpZiAodGhpcy5pc1JlamVjdGlvbkhhbmRsZWRfKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICB2YXIgZiA9ICRqc2NvbXAuZ2xvYmFsLkN1c3RvbUV2ZW50LCBxID0gJGpzY29tcC5nbG9iYWwuRXZlbnQsIHYzID0gJGpzY29tcC5nbG9iYWwuZGlzcGF0Y2hFdmVudDsKICAgICAgICAgIGlmICgidW5kZWZpbmVkIiA9PT0gdHlwZW9mIHYzKSByZXR1cm4gdHJ1ZTsKICAgICAgICAgICJmdW5jdGlvbiIgPT09IHR5cGVvZiBmID8gZiA9IG5ldyBmKCJ1bmhhbmRsZWRyZWplY3Rpb24iLCB7IGNhbmNlbGFibGU6IHRydWUgfSkgOiAiZnVuY3Rpb24iID09PSB0eXBlb2YgcSA/IGYgPSBuZXcgcSgidW5oYW5kbGVkcmVqZWN0aW9uIiwgeyBjYW5jZWxhYmxlOiB0cnVlIH0pIDogKGYgPSAkanNjb21wLmdsb2JhbC5kb2N1bWVudC5jcmVhdGVFdmVudCgiQ3VzdG9tRXZlbnQiKSwgZi5pbml0Q3VzdG9tRXZlbnQoInVuaGFuZGxlZHJlamVjdGlvbiIsIGZhbHNlLCB0cnVlLCBmKSk7CiAgICAgICAgICBmLnByb21pc2UgPSB0aGlzOwogICAgICAgICAgZi5yZWFzb24gPSB0aGlzLnJlc3VsdF87CiAgICAgICAgICByZXR1cm4gdjMoZik7CiAgICAgICAgfTsKICAgICAgICBoLnByb3RvdHlwZS5leGVjdXRlT25TZXR0bGVkQ2FsbGJhY2tzXyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgaWYgKG51bGwgIT0gdGhpcy5vblNldHRsZWRDYWxsYmFja3NfKSB7CiAgICAgICAgICAgIGZvciAodmFyIGYgPSAwOyBmIDwgdGhpcy5vblNldHRsZWRDYWxsYmFja3NfLmxlbmd0aDsgKytmKSBBLmFzeW5jRXhlY3V0ZSh0aGlzLm9uU2V0dGxlZENhbGxiYWNrc19bZl0pOwogICAgICAgICAgICB0aGlzLm9uU2V0dGxlZENhbGxiYWNrc18gPSBudWxsOwogICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgdmFyIEEgPSBuZXcgbigpOwogICAgICAgIGgucHJvdG90eXBlLnNldHRsZVNhbWVBc1Byb21pc2VfID0gZnVuY3Rpb24oZikgewogICAgICAgICAgdmFyIHEgPSB0aGlzLmNyZWF0ZVJlc29sdmVBbmRSZWplY3RfKCk7CiAgICAgICAgICBmLmNhbGxXaGVuU2V0dGxlZF8ocS5yZXNvbHZlLCBxLnJlamVjdCk7CiAgICAgICAgfTsKICAgICAgICBoLnByb3RvdHlwZS5zZXR0bGVTYW1lQXNUaGVuYWJsZV8gPSBmdW5jdGlvbihmLCBxKSB7CiAgICAgICAgICB2YXIgdjMgPSB0aGlzLmNyZWF0ZVJlc29sdmVBbmRSZWplY3RfKCk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBmLmNhbGwocSwgdjMucmVzb2x2ZSwgdjMucmVqZWN0KTsKICAgICAgICAgIH0gY2F0Y2ggKHopIHsKICAgICAgICAgICAgdjMucmVqZWN0KHopOwogICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgaC5wcm90b3R5cGUudGhlbiA9IGZ1bmN0aW9uKGYsIHEpIHsKICAgICAgICAgIGZ1bmN0aW9uIHYzKHQsIHgpIHsKICAgICAgICAgICAgcmV0dXJuICJmdW5jdGlvbiIgPT0gdHlwZW9mIHQgPyBmdW5jdGlvbihEKSB7CiAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHoodChEKSk7CiAgICAgICAgICAgICAgfSBjYXRjaCAoUikgewogICAgICAgICAgICAgICAgTyhSKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gOiB4OwogICAgICAgICAgfQogICAgICAgICAgdmFyIHosIE8sIGJhID0gbmV3IGgoZnVuY3Rpb24odCwgeCkgewogICAgICAgICAgICB6ID0gdDsKICAgICAgICAgICAgTyA9IHg7CiAgICAgICAgICB9KTsKICAgICAgICAgIHRoaXMuY2FsbFdoZW5TZXR0bGVkXyh2MyhmLCB6KSwgdjMocSwgTykpOwogICAgICAgICAgcmV0dXJuIGJhOwogICAgICAgIH07CiAgICAgICAgaC5wcm90b3R5cGUuY2F0Y2ggPSBmdW5jdGlvbihmKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy50aGVuKHZvaWQgMCwgZik7CiAgICAgICAgfTsKICAgICAgICBoLnByb3RvdHlwZS5jYWxsV2hlblNldHRsZWRfID0gZnVuY3Rpb24oZiwgcSkgewogICAgICAgICAgZnVuY3Rpb24gdjMoKSB7CiAgICAgICAgICAgIHN3aXRjaCAoei5zdGF0ZV8pIHsKICAgICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICBmKHoucmVzdWx0Xyk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgICBxKHoucmVzdWx0Xyk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoIlVuZXhwZWN0ZWQgc3RhdGU6ICIgKyB6LnN0YXRlXyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHZhciB6ID0gdGhpczsKICAgICAgICAgIG51bGwgPT0gdGhpcy5vblNldHRsZWRDYWxsYmFja3NfID8gQS5hc3luY0V4ZWN1dGUodjMpIDogdGhpcy5vblNldHRsZWRDYWxsYmFja3NfLnB1c2godjMpOwogICAgICAgICAgdGhpcy5pc1JlamVjdGlvbkhhbmRsZWRfID0gdHJ1ZTsKICAgICAgICB9OwogICAgICAgIGgucmVzb2x2ZSA9IGw7CiAgICAgICAgaC5yZWplY3QgPSBmdW5jdGlvbihmKSB7CiAgICAgICAgICByZXR1cm4gbmV3IGgoZnVuY3Rpb24ocSwgdjMpIHsKICAgICAgICAgICAgdjMoZik7CiAgICAgICAgICB9KTsKICAgICAgICB9OwogICAgICAgIGgucmFjZSA9IGZ1bmN0aW9uKGYpIHsKICAgICAgICAgIHJldHVybiBuZXcgaChmdW5jdGlvbihxLCB2MykgewogICAgICAgICAgICBmb3IgKHZhciB6ID0gJGpzY29tcC5tYWtlSXRlcmF0b3IoZiksIE8gPSB6Lm5leHQoKTsgIU8uZG9uZTsgTyA9IHoubmV4dCgpKSBsKE8udmFsdWUpLmNhbGxXaGVuU2V0dGxlZF8ocSwgdjMpOwogICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICBoLmFsbCA9IGZ1bmN0aW9uKGYpIHsKICAgICAgICAgIHZhciBxID0gJGpzY29tcC5tYWtlSXRlcmF0b3IoZiksIHYzID0gcS5uZXh0KCk7CiAgICAgICAgICByZXR1cm4gdjMuZG9uZSA/IGwoW10pIDogbmV3IGgoZnVuY3Rpb24oeiwgTykgewogICAgICAgICAgICBmdW5jdGlvbiBiYShEKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKFIpIHsKICAgICAgICAgICAgICAgIHRbRF0gPSBSOwogICAgICAgICAgICAgICAgeC0tOwogICAgICAgICAgICAgICAgMCA9PSB4ICYmIHoodCk7CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgdCA9IFtdLCB4ID0gMDsKICAgICAgICAgICAgZG8KICAgICAgICAgICAgICB0LnB1c2godm9pZCAwKSwgeCsrLCBsKHYzLnZhbHVlKS5jYWxsV2hlblNldHRsZWRfKGJhKHQubGVuZ3RoIC0gMSksIE8pLCB2MyA9IHEubmV4dCgpOwogICAgICAgICAgICB3aGlsZSAoIXYzLmRvbmUpOwogICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgICByZXR1cm4gaDsKICAgICAgfSwgImVzNiIsICJlczMiKTsKICAgICAgJGpzY29tcC5vd25zID0gZnVuY3Rpb24oaywgbikgewogICAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoaywgbik7CiAgICAgIH07CiAgICAgICRqc2NvbXAuYXNzaWduID0gJGpzY29tcC5UUlVTVF9FUzZfUE9MWUZJTExTICYmICJmdW5jdGlvbiIgPT0gdHlwZW9mIE9iamVjdC5hc3NpZ24gPyBPYmplY3QuYXNzaWduIDogZnVuY3Rpb24oaywgbikgewogICAgICAgIGZvciAodmFyIGwgPSAxOyBsIDwgYXJndW1lbnRzLmxlbmd0aDsgbCsrKSB7CiAgICAgICAgICB2YXIgcCA9IGFyZ3VtZW50c1tsXTsKICAgICAgICAgIGlmIChwKSBmb3IgKHZhciBoIGluIHApICRqc2NvbXAub3ducyhwLCBoKSAmJiAoa1toXSA9IHBbaF0pOwogICAgICAgIH0KICAgICAgICByZXR1cm4gazsKICAgICAgfTsKICAgICAgJGpzY29tcC5wb2x5ZmlsbCgiT2JqZWN0LmFzc2lnbiIsIGZ1bmN0aW9uKGspIHsKICAgICAgICByZXR1cm4gayB8fCAkanNjb21wLmFzc2lnbjsKICAgICAgfSwgImVzNiIsICJlczMiKTsKICAgICAgJGpzY29tcC5jaGVja1N0cmluZ0FyZ3MgPSBmdW5jdGlvbihrLCBuLCBsKSB7CiAgICAgICAgaWYgKG51bGwgPT0gaykgdGhyb3cgbmV3IFR5cGVFcnJvcigiVGhlICd0aGlzJyB2YWx1ZSBmb3IgU3RyaW5nLnByb3RvdHlwZS4iICsgbCArICIgbXVzdCBub3QgYmUgbnVsbCBvciB1bmRlZmluZWQiKTsKICAgICAgICBpZiAobiBpbnN0YW5jZW9mIFJlZ0V4cCkgdGhyb3cgbmV3IFR5cGVFcnJvcigiRmlyc3QgYXJndW1lbnQgdG8gU3RyaW5nLnByb3RvdHlwZS4iICsgbCArICIgbXVzdCBub3QgYmUgYSByZWd1bGFyIGV4cHJlc3Npb24iKTsKICAgICAgICByZXR1cm4gayArICIiOwogICAgICB9OwogICAgICAkanNjb21wLnBvbHlmaWxsKCJTdHJpbmcucHJvdG90eXBlLnN0YXJ0c1dpdGgiLCBmdW5jdGlvbihrKSB7CiAgICAgICAgcmV0dXJuIGsgPyBrIDogZnVuY3Rpb24obiwgbCkgewogICAgICAgICAgdmFyIHAgPSAkanNjb21wLmNoZWNrU3RyaW5nQXJncyh0aGlzLCBuLCAic3RhcnRzV2l0aCIpOwogICAgICAgICAgbiArPSAiIjsKICAgICAgICAgIHZhciBoID0gcC5sZW5ndGgsIEEgPSBuLmxlbmd0aDsKICAgICAgICAgIGwgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihsIHwgMCwgcC5sZW5ndGgpKTsKICAgICAgICAgIGZvciAodmFyIGYgPSAwOyBmIDwgQSAmJiBsIDwgaDsgKSBpZiAocFtsKytdICE9IG5bZisrXSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgcmV0dXJuIGYgPj0gQTsKICAgICAgICB9OwogICAgICB9LCAiZXM2IiwgImVzMyIpOwogICAgICAkanNjb21wLnBvbHlmaWxsKCJBcnJheS5wcm90b3R5cGUuY29weVdpdGhpbiIsIGZ1bmN0aW9uKGspIHsKICAgICAgICBmdW5jdGlvbiBuKGwpIHsKICAgICAgICAgIGwgPSBOdW1iZXIobCk7CiAgICAgICAgICByZXR1cm4gSW5maW5pdHkgPT09IGwgfHwgLUluZmluaXR5ID09PSBsID8gbCA6IGwgfCAwOwogICAgICAgIH0KICAgICAgICByZXR1cm4gayA/IGsgOiBmdW5jdGlvbihsLCBwLCBoKSB7CiAgICAgICAgICB2YXIgQSA9IHRoaXMubGVuZ3RoOwogICAgICAgICAgbCA9IG4obCk7CiAgICAgICAgICBwID0gbihwKTsKICAgICAgICAgIGggPSB2b2lkIDAgPT09IGggPyBBIDogbihoKTsKICAgICAgICAgIGwgPSAwID4gbCA/IE1hdGgubWF4KEEgKyBsLCAwKSA6IE1hdGgubWluKGwsIEEpOwogICAgICAgICAgcCA9IDAgPiBwID8gTWF0aC5tYXgoQSArIHAsIDApIDogTWF0aC5taW4ocCwgQSk7CiAgICAgICAgICBoID0gMCA+IGggPyBNYXRoLm1heChBICsgaCwgMCkgOiBNYXRoLm1pbihoLCBBKTsKICAgICAgICAgIGlmIChsIDwgcCkgZm9yICg7IHAgPCBoOyApIHAgaW4gdGhpcyA/IHRoaXNbbCsrXSA9IHRoaXNbcCsrXSA6IChkZWxldGUgdGhpc1tsKytdLCBwKyspOwogICAgICAgICAgZWxzZSBmb3IgKGggPSBNYXRoLm1pbihoLCBBICsgcCAtIGwpLCBsICs9IGggLSBwOyBoID4gcDsgKSAtLWggaW4gdGhpcyA/IHRoaXNbLS1sXSA9IHRoaXNbaF0gOiBkZWxldGUgdGhpc1stLWxdOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfTsKICAgICAgfSwgImVzNiIsICJlczMiKTsKICAgICAgJGpzY29tcC50eXBlZEFycmF5Q29weVdpdGhpbiA9IGZ1bmN0aW9uKGspIHsKICAgICAgICByZXR1cm4gayA/IGsgOiBBcnJheS5wcm90b3R5cGUuY29weVdpdGhpbjsKICAgICAgfTsKICAgICAgJGpzY29tcC5wb2x5ZmlsbCgiSW50OEFycmF5LnByb3RvdHlwZS5jb3B5V2l0aGluIiwgJGpzY29tcC50eXBlZEFycmF5Q29weVdpdGhpbiwgImVzNiIsICJlczUiKTsKICAgICAgJGpzY29tcC5wb2x5ZmlsbCgiVWludDhBcnJheS5wcm90b3R5cGUuY29weVdpdGhpbiIsICRqc2NvbXAudHlwZWRBcnJheUNvcHlXaXRoaW4sICJlczYiLCAiZXM1Iik7CiAgICAgICRqc2NvbXAucG9seWZpbGwoIlVpbnQ4Q2xhbXBlZEFycmF5LnByb3RvdHlwZS5jb3B5V2l0aGluIiwgJGpzY29tcC50eXBlZEFycmF5Q29weVdpdGhpbiwgImVzNiIsICJlczUiKTsKICAgICAgJGpzY29tcC5wb2x5ZmlsbCgiSW50MTZBcnJheS5wcm90b3R5cGUuY29weVdpdGhpbiIsICRqc2NvbXAudHlwZWRBcnJheUNvcHlXaXRoaW4sICJlczYiLCAiZXM1Iik7CiAgICAgICRqc2NvbXAucG9seWZpbGwoIlVpbnQxNkFycmF5LnByb3RvdHlwZS5jb3B5V2l0aGluIiwgJGpzY29tcC50eXBlZEFycmF5Q29weVdpdGhpbiwgImVzNiIsICJlczUiKTsKICAgICAgJGpzY29tcC5wb2x5ZmlsbCgiSW50MzJBcnJheS5wcm90b3R5cGUuY29weVdpdGhpbiIsICRqc2NvbXAudHlwZWRBcnJheUNvcHlXaXRoaW4sICJlczYiLCAiZXM1Iik7CiAgICAgICRqc2NvbXAucG9seWZpbGwoIlVpbnQzMkFycmF5LnByb3RvdHlwZS5jb3B5V2l0aGluIiwgJGpzY29tcC50eXBlZEFycmF5Q29weVdpdGhpbiwgImVzNiIsICJlczUiKTsKICAgICAgJGpzY29tcC5wb2x5ZmlsbCgiRmxvYXQzMkFycmF5LnByb3RvdHlwZS5jb3B5V2l0aGluIiwgJGpzY29tcC50eXBlZEFycmF5Q29weVdpdGhpbiwgImVzNiIsICJlczUiKTsKICAgICAgJGpzY29tcC5wb2x5ZmlsbCgiRmxvYXQ2NEFycmF5LnByb3RvdHlwZS5jb3B5V2l0aGluIiwgJGpzY29tcC50eXBlZEFycmF5Q29weVdpdGhpbiwgImVzNiIsICJlczUiKTsKICAgICAgdmFyIERyYWNvRGVjb2Rlck1vZHVsZSA9IChmdW5jdGlvbigpIHsKICAgICAgICB2YXIgayA9ICJ1bmRlZmluZWQiICE9PSB0eXBlb2YgZG9jdW1lbnQgJiYgZG9jdW1lbnQuY3VycmVudFNjcmlwdCA/IGRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjIDogdm9pZCAwOwogICAgICAgICJ1bmRlZmluZWQiICE9PSB0eXBlb2YgX19maWxlbmFtZSAmJiAoayA9IGsgfHwgX19maWxlbmFtZSk7CiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG4pIHsKICAgICAgICAgIGZ1bmN0aW9uIGwoZSkgewogICAgICAgICAgICByZXR1cm4gYTMubG9jYXRlRmlsZSA/IGEzLmxvY2F0ZUZpbGUoZSwgVSkgOiBVICsgZTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHAoZSwgYiwgYykgewogICAgICAgICAgICB2YXIgZCA9IGIgKyBjOwogICAgICAgICAgICBmb3IgKGMgPSBiOyBlW2NdICYmICEoYyA+PSBkKTsgKSArK2M7CiAgICAgICAgICAgIGlmICgxNiA8IGMgLSBiICYmIGUuYnVmZmVyICYmIHZhKSByZXR1cm4gdmEuZGVjb2RlKGUuc3ViYXJyYXkoYiwgYykpOwogICAgICAgICAgICBmb3IgKGQgPSAiIjsgYiA8IGM7ICkgewogICAgICAgICAgICAgIHZhciBnID0gZVtiKytdOwogICAgICAgICAgICAgIGlmIChnICYgMTI4KSB7CiAgICAgICAgICAgICAgICB2YXIgdTMgPSBlW2IrK10gJiA2MzsKICAgICAgICAgICAgICAgIGlmICgxOTIgPT0gKGcgJiAyMjQpKSBkICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGcgJiAzMSkgPDwgNiB8IHUzKTsKICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICB2YXIgWCA9IGVbYisrXSAmIDYzOwogICAgICAgICAgICAgICAgICBnID0gMjI0ID09IChnICYgMjQwKSA/IChnICYgMTUpIDw8IDEyIHwgdTMgPDwgNiB8IFggOiAoZyAmIDcpIDw8IDE4IHwgdTMgPDwgMTIgfCBYIDw8IDYgfCBlW2IrK10gJiA2MzsKICAgICAgICAgICAgICAgICAgNjU1MzYgPiBnID8gZCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGcpIDogKGcgLT0gNjU1MzYsIGQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSg1NTI5NiB8IGcgPj4gMTAsIDU2MzIwIHwgZyAmIDEwMjMpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9IGVsc2UgZCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGcpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBkOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gaChlLCBiKSB7CiAgICAgICAgICAgIHJldHVybiBlID8gcChlYSwgZSwgYikgOiAiIjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEEoKSB7CiAgICAgICAgICAgIHZhciBlID0gamEuYnVmZmVyOwogICAgICAgICAgICBhMy5IRUFQOCA9IFkgPSBuZXcgSW50OEFycmF5KGUpOwogICAgICAgICAgICBhMy5IRUFQMTYgPSBuZXcgSW50MTZBcnJheShlKTsKICAgICAgICAgICAgYTMuSEVBUDMyID0gY2EgPSBuZXcgSW50MzJBcnJheShlKTsKICAgICAgICAgICAgYTMuSEVBUFU4ID0gZWEgPSBuZXcgVWludDhBcnJheShlKTsKICAgICAgICAgICAgYTMuSEVBUFUxNiA9IG5ldyBVaW50MTZBcnJheShlKTsKICAgICAgICAgICAgYTMuSEVBUFUzMiA9IFYgPSBuZXcgVWludDMyQXJyYXkoZSk7CiAgICAgICAgICAgIGEzLkhFQVBGMzIgPSBuZXcgRmxvYXQzMkFycmF5KGUpOwogICAgICAgICAgICBhMy5IRUFQRjY0ID0gbmV3IEZsb2F0NjRBcnJheShlKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGYoZSkgewogICAgICAgICAgICBpZiAoYTMub25BYm9ydCkgYTMub25BYm9ydChlKTsKICAgICAgICAgICAgZSA9ICJBYm9ydGVkKCIgKyBlICsgIikiOwogICAgICAgICAgICBkYShlKTsKICAgICAgICAgICAgd2EgPSB0cnVlOwogICAgICAgICAgICBlID0gbmV3IFdlYkFzc2VtYmx5LlJ1bnRpbWVFcnJvcihlICsgIi4gQnVpbGQgd2l0aCAtc0FTU0VSVElPTlMgZm9yIG1vcmUgaW5mby4iKTsKICAgICAgICAgICAga2EoZSk7CiAgICAgICAgICAgIHRocm93IGU7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBxKGUpIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBpZiAoZSA9PSBQICYmIGZhKSByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoZmEpOwogICAgICAgICAgICAgIGlmIChtYSkgcmV0dXJuIG1hKGUpOwogICAgICAgICAgICAgIHRocm93ICJib3RoIGFzeW5jIGFuZCBzeW5jIGZldGNoaW5nIG9mIHRoZSB3YXNtIGZhaWxlZCI7CiAgICAgICAgICAgIH0gY2F0Y2ggKGIpIHsKICAgICAgICAgICAgICBmKGIpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiB2MygpIHsKICAgICAgICAgICAgaWYgKCFmYSAmJiAoeGEgfHwgaGEpKSB7CiAgICAgICAgICAgICAgaWYgKCJmdW5jdGlvbiIgPT0gdHlwZW9mIGZldGNoICYmICFQLnN0YXJ0c1dpdGgoImZpbGU6Ly8iKSkgcmV0dXJuIGZldGNoKFAsIHsgY3JlZGVudGlhbHM6ICJzYW1lLW9yaWdpbiIgfSkudGhlbihmdW5jdGlvbihlKSB7CiAgICAgICAgICAgICAgICBpZiAoIWUub2spIHRocm93ICJmYWlsZWQgdG8gbG9hZCB3YXNtIGJpbmFyeSBmaWxlIGF0ICciICsgUCArICInIjsKICAgICAgICAgICAgICAgIHJldHVybiBlLmFycmF5QnVmZmVyKCk7CiAgICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gcShQKTsKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICBpZiAobmEpIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihlLCBiKSB7CiAgICAgICAgICAgICAgICBuYShQLCBmdW5jdGlvbihjKSB7CiAgICAgICAgICAgICAgICAgIGUobmV3IFVpbnQ4QXJyYXkoYykpOwogICAgICAgICAgICAgICAgfSwgYik7CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHEoUCk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24geihlKSB7CiAgICAgICAgICAgIGZvciAoOyAwIDwgZS5sZW5ndGg7ICkgZS5zaGlmdCgpKGEzKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIE8oZSkgewogICAgICAgICAgICB0aGlzLmV4Y1B0ciA9IGU7CiAgICAgICAgICAgIHRoaXMucHRyID0gZSAtIDI0OwogICAgICAgICAgICB0aGlzLnNldF90eXBlID0gZnVuY3Rpb24oYikgewogICAgICAgICAgICAgIFZbdGhpcy5wdHIgKyA0ID4+IDJdID0gYjsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgdGhpcy5nZXRfdHlwZSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiBWW3RoaXMucHRyICsgNCA+PiAyXTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgdGhpcy5zZXRfZGVzdHJ1Y3RvciA9IGZ1bmN0aW9uKGIpIHsKICAgICAgICAgICAgICBWW3RoaXMucHRyICsgOCA+PiAyXSA9IGI7CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIHRoaXMuZ2V0X2Rlc3RydWN0b3IgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gVlt0aGlzLnB0ciArIDggPj4gMl07CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIHRoaXMuc2V0X3JlZmNvdW50ID0gZnVuY3Rpb24oYikgewogICAgICAgICAgICAgIGNhW3RoaXMucHRyID4+IDJdID0gYjsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgdGhpcy5zZXRfY2F1Z2h0ID0gZnVuY3Rpb24oYikgewogICAgICAgICAgICAgIFlbdGhpcy5wdHIgKyAxMiA+PiAwXSA9IGIgPyAxIDogMDsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgdGhpcy5nZXRfY2F1Z2h0ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIDAgIT0gWVt0aGlzLnB0ciArIDEyID4+IDBdOwogICAgICAgICAgICB9OwogICAgICAgICAgICB0aGlzLnNldF9yZXRocm93biA9IGZ1bmN0aW9uKGIpIHsKICAgICAgICAgICAgICBZW3RoaXMucHRyICsgMTMgPj4gMF0gPSBiID8gMSA6IDA7CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIHRoaXMuZ2V0X3JldGhyb3duID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIDAgIT0gWVt0aGlzLnB0ciArIDEzID4+IDBdOwogICAgICAgICAgICB9OwogICAgICAgICAgICB0aGlzLmluaXQgPSBmdW5jdGlvbihiLCBjKSB7CiAgICAgICAgICAgICAgdGhpcy5zZXRfYWRqdXN0ZWRfcHRyKDApOwogICAgICAgICAgICAgIHRoaXMuc2V0X3R5cGUoYik7CiAgICAgICAgICAgICAgdGhpcy5zZXRfZGVzdHJ1Y3RvcihjKTsKICAgICAgICAgICAgICB0aGlzLnNldF9yZWZjb3VudCgwKTsKICAgICAgICAgICAgICB0aGlzLnNldF9jYXVnaHQoZmFsc2UpOwogICAgICAgICAgICAgIHRoaXMuc2V0X3JldGhyb3duKGZhbHNlKTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgdGhpcy5hZGRfcmVmID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgY2FbdGhpcy5wdHIgPj4gMl0gKz0gMTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgdGhpcy5yZWxlYXNlX3JlZiA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHZhciBiID0gY2FbdGhpcy5wdHIgPj4gMl07CiAgICAgICAgICAgICAgY2FbdGhpcy5wdHIgPj4gMl0gPSBiIC0gMTsKICAgICAgICAgICAgICByZXR1cm4gMSA9PT0gYjsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgdGhpcy5zZXRfYWRqdXN0ZWRfcHRyID0gZnVuY3Rpb24oYikgewogICAgICAgICAgICAgIFZbdGhpcy5wdHIgKyAxNiA+PiAyXSA9IGI7CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIHRoaXMuZ2V0X2FkanVzdGVkX3B0ciA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiBWW3RoaXMucHRyICsgMTYgPj4gMl07CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIHRoaXMuZ2V0X2V4Y2VwdGlvbl9wdHIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICBpZiAoeWEodGhpcy5nZXRfdHlwZSgpKSkgcmV0dXJuIFZbdGhpcy5leGNQdHIgPj4gMl07CiAgICAgICAgICAgICAgdmFyIGIgPSB0aGlzLmdldF9hZGp1c3RlZF9wdHIoKTsKICAgICAgICAgICAgICByZXR1cm4gMCAhPT0gYiA/IGIgOiB0aGlzLmV4Y1B0cjsKICAgICAgICAgICAgfTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGJhKCkgewogICAgICAgICAgICBmdW5jdGlvbiBlKCkgewogICAgICAgICAgICAgIGlmICghbGEgJiYgKGxhID0gdHJ1ZSwgYTMuY2FsbGVkUnVuID0gdHJ1ZSwgIXdhKSkgewogICAgICAgICAgICAgICAgemEgPSB0cnVlOwogICAgICAgICAgICAgICAgeihvYSk7CiAgICAgICAgICAgICAgICBBYShhMyk7CiAgICAgICAgICAgICAgICBpZiAoYTMub25SdW50aW1lSW5pdGlhbGl6ZWQpIGEzLm9uUnVudGltZUluaXRpYWxpemVkKCk7CiAgICAgICAgICAgICAgICBpZiAoYTMucG9zdFJ1bikgZm9yICgiZnVuY3Rpb24iID09IHR5cGVvZiBhMy5wb3N0UnVuICYmIChhMy5wb3N0UnVuID0gW2EzLnBvc3RSdW5dKTsgYTMucG9zdFJ1bi5sZW5ndGg7ICkgQmEudW5zaGlmdChhMy5wb3N0UnVuLnNoaWZ0KCkpOwogICAgICAgICAgICAgICAgeihCYSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICghKDAgPCBhYSkpIHsKICAgICAgICAgICAgICBpZiAoYTMucHJlUnVuKSBmb3IgKCJmdW5jdGlvbiIgPT0gdHlwZW9mIGEzLnByZVJ1biAmJiAoYTMucHJlUnVuID0gW2EzLnByZVJ1bl0pOyBhMy5wcmVSdW4ubGVuZ3RoOyApIENhLnVuc2hpZnQoYTMucHJlUnVuLnNoaWZ0KCkpOwogICAgICAgICAgICAgIHooQ2EpOwogICAgICAgICAgICAgIDAgPCBhYSB8fCAoYTMuc2V0U3RhdHVzID8gKGEzLnNldFN0YXR1cygiUnVubmluZy4uLiIpLCBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsKICAgICAgICAgICAgICAgICAgYTMuc2V0U3RhdHVzKCIiKTsKICAgICAgICAgICAgICAgIH0sIDEpOwogICAgICAgICAgICAgICAgZSgpOwogICAgICAgICAgICAgIH0sIDEpKSA6IGUoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHQoKSB7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiB4KGUpIHsKICAgICAgICAgICAgcmV0dXJuIChlIHx8IHQpLl9fY2FjaGVfXzsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEQoZSwgYikgewogICAgICAgICAgICB2YXIgYyA9IHgoYiksIGQgPSBjW2VdOwogICAgICAgICAgICBpZiAoZCkgcmV0dXJuIGQ7CiAgICAgICAgICAgIGQgPSBPYmplY3QuY3JlYXRlKChiIHx8IHQpLnByb3RvdHlwZSk7CiAgICAgICAgICAgIGQucHRyID0gZTsKICAgICAgICAgICAgcmV0dXJuIGNbZV0gPSBkOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gUihlKSB7CiAgICAgICAgICAgIGlmICgic3RyaW5nIiA9PT0gdHlwZW9mIGUpIHsKICAgICAgICAgICAgICBmb3IgKHZhciBiID0gMCwgYyA9IDA7IGMgPCBlLmxlbmd0aDsgKytjKSB7CiAgICAgICAgICAgICAgICB2YXIgZCA9IGUuY2hhckNvZGVBdChjKTsKICAgICAgICAgICAgICAgIDEyNyA+PSBkID8gYisrIDogMjA0NyA+PSBkID8gYiArPSAyIDogNTUyOTYgPD0gZCAmJiA1NzM0MyA+PSBkID8gKGIgKz0gNCwgKytjKSA6IGIgKz0gMzsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYiA9IEFycmF5KGIgKyAxKTsKICAgICAgICAgICAgICBjID0gMDsKICAgICAgICAgICAgICBkID0gYi5sZW5ndGg7CiAgICAgICAgICAgICAgaWYgKDAgPCBkKSB7CiAgICAgICAgICAgICAgICBkID0gYyArIGQgLSAxOwogICAgICAgICAgICAgICAgZm9yICh2YXIgZyA9IDA7IGcgPCBlLmxlbmd0aDsgKytnKSB7CiAgICAgICAgICAgICAgICAgIHZhciB1MyA9IGUuY2hhckNvZGVBdChnKTsKICAgICAgICAgICAgICAgICAgaWYgKDU1Mjk2IDw9IHUzICYmIDU3MzQzID49IHUzKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIFggPSBlLmNoYXJDb2RlQXQoKytnKTsKICAgICAgICAgICAgICAgICAgICB1MyA9IDY1NTM2ICsgKCh1MyAmIDEwMjMpIDw8IDEwKSB8IFggJiAxMDIzOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmICgxMjcgPj0gdTMpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoYyA+PSBkKSBicmVhazsKICAgICAgICAgICAgICAgICAgICBiW2MrK10gPSB1MzsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBpZiAoMjA0NyA+PSB1MykgewogICAgICAgICAgICAgICAgICAgICAgaWYgKGMgKyAxID49IGQpIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgYltjKytdID0gMTkyIHwgdTMgPj4gNjsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgaWYgKDY1NTM1ID49IHUzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjICsgMiA+PSBkKSBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgYltjKytdID0gMjI0IHwgdTMgPj4gMTI7CiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoYyArIDMgPj0gZCkgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGJbYysrXSA9IDI0MCB8IHUzID4+IDE4OwogICAgICAgICAgICAgICAgICAgICAgICBiW2MrK10gPSAxMjggfCB1MyA+PiAxMiAmIDYzOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgYltjKytdID0gMTI4IHwgdTMgPj4gNiAmIDYzOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBiW2MrK10gPSAxMjggfCB1MyAmIDYzOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBiW2NdID0gMDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgZSA9IHIuYWxsb2MoYiwgWSk7CiAgICAgICAgICAgICAgci5jb3B5KGIsIFksIGUpOwogICAgICAgICAgICAgIHJldHVybiBlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBlOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gcGEoZSkgewogICAgICAgICAgICBpZiAoIm9iamVjdCIgPT09IHR5cGVvZiBlKSB7CiAgICAgICAgICAgICAgdmFyIGIgPSByLmFsbG9jKGUsIFkpOwogICAgICAgICAgICAgIHIuY29weShlLCBZLCBiKTsKICAgICAgICAgICAgICByZXR1cm4gYjsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIFooKSB7CiAgICAgICAgICAgIHRocm93ICJjYW5ub3QgY29uc3RydWN0IGEgVm9pZFB0ciwgbm8gY29uc3RydWN0b3IgaW4gSURMIjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIFMoKSB7CiAgICAgICAgICAgIHRoaXMucHRyID0gRGEoKTsKICAgICAgICAgICAgeChTKVt0aGlzLnB0cl0gPSB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gUSgpIHsKICAgICAgICAgICAgdGhpcy5wdHIgPSBFYSgpOwogICAgICAgICAgICB4KFEpW3RoaXMucHRyXSA9IHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBXKCkgewogICAgICAgICAgICB0aGlzLnB0ciA9IEZhKCk7CiAgICAgICAgICAgIHgoVylbdGhpcy5wdHJdID0gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHcoKSB7CiAgICAgICAgICAgIHRoaXMucHRyID0gR2EoKTsKICAgICAgICAgICAgeCh3KVt0aGlzLnB0cl0gPSB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gQygpIHsKICAgICAgICAgICAgdGhpcy5wdHIgPSBIYSgpOwogICAgICAgICAgICB4KEMpW3RoaXMucHRyXSA9IHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBGKCkgewogICAgICAgICAgICB0aGlzLnB0ciA9IElhKCk7CiAgICAgICAgICAgIHgoRilbdGhpcy5wdHJdID0gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEcoKSB7CiAgICAgICAgICAgIHRoaXMucHRyID0gSmEoKTsKICAgICAgICAgICAgeChHKVt0aGlzLnB0cl0gPSB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gRSgpIHsKICAgICAgICAgICAgdGhpcy5wdHIgPSBLYSgpOwogICAgICAgICAgICB4KEUpW3RoaXMucHRyXSA9IHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBUKCkgewogICAgICAgICAgICB0aGlzLnB0ciA9IExhKCk7CiAgICAgICAgICAgIHgoVClbdGhpcy5wdHJdID0gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEIoKSB7CiAgICAgICAgICAgIHRocm93ICJjYW5ub3QgY29uc3RydWN0IGEgU3RhdHVzLCBubyBjb25zdHJ1Y3RvciBpbiBJREwiOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gSCgpIHsKICAgICAgICAgICAgdGhpcy5wdHIgPSBNYSgpOwogICAgICAgICAgICB4KEgpW3RoaXMucHRyXSA9IHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBJKCkgewogICAgICAgICAgICB0aGlzLnB0ciA9IE5hKCk7CiAgICAgICAgICAgIHgoSSlbdGhpcy5wdHJdID0gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIEooKSB7CiAgICAgICAgICAgIHRoaXMucHRyID0gT2EoKTsKICAgICAgICAgICAgeChKKVt0aGlzLnB0cl0gPSB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gSygpIHsKICAgICAgICAgICAgdGhpcy5wdHIgPSBQYSgpOwogICAgICAgICAgICB4KEspW3RoaXMucHRyXSA9IHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBMKCkgewogICAgICAgICAgICB0aGlzLnB0ciA9IFFhKCk7CiAgICAgICAgICAgIHgoTClbdGhpcy5wdHJdID0gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIE0oKSB7CiAgICAgICAgICAgIHRoaXMucHRyID0gUmEoKTsKICAgICAgICAgICAgeChNKVt0aGlzLnB0cl0gPSB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gTigpIHsKICAgICAgICAgICAgdGhpcy5wdHIgPSBTYSgpOwogICAgICAgICAgICB4KE4pW3RoaXMucHRyXSA9IHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiB5KCkgewogICAgICAgICAgICB0aGlzLnB0ciA9IFRhKCk7CiAgICAgICAgICAgIHgoeSlbdGhpcy5wdHJdID0gdGhpczsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIG0oKSB7CiAgICAgICAgICAgIHRoaXMucHRyID0gVWEoKTsKICAgICAgICAgICAgeChtKVt0aGlzLnB0cl0gPSB0aGlzOwogICAgICAgICAgfQogICAgICAgICAgbiA9IHZvaWQgMCA9PT0gbiA/IHt9IDogbjsKICAgICAgICAgIHZhciBhMyA9ICJ1bmRlZmluZWQiICE9IHR5cGVvZiBuID8gbiA6IHt9LCBBYSwga2E7CiAgICAgICAgICBhMy5yZWFkeSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKGUsIGIpIHsKICAgICAgICAgICAgQWEgPSBlOwogICAgICAgICAgICBrYSA9IGI7CiAgICAgICAgICB9KTsKICAgICAgICAgIHZhciBWYSA9IGZhbHNlLCBXYSA9IGZhbHNlOwogICAgICAgICAgYTMub25SdW50aW1lSW5pdGlhbGl6ZWQgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgVmEgPSB0cnVlOwogICAgICAgICAgICBpZiAoV2EgJiYgImZ1bmN0aW9uIiA9PT0gdHlwZW9mIGEzLm9uTW9kdWxlTG9hZGVkKSBhMy5vbk1vZHVsZUxvYWRlZChhMyk7CiAgICAgICAgICB9OwogICAgICAgICAgYTMub25Nb2R1bGVQYXJzZWQgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgV2EgPSB0cnVlOwogICAgICAgICAgICBpZiAoVmEgJiYgImZ1bmN0aW9uIiA9PT0gdHlwZW9mIGEzLm9uTW9kdWxlTG9hZGVkKSBhMy5vbk1vZHVsZUxvYWRlZChhMyk7CiAgICAgICAgICB9OwogICAgICAgICAgYTMuaXNWZXJzaW9uU3VwcG9ydGVkID0gZnVuY3Rpb24oZSkgewogICAgICAgICAgICBpZiAoInN0cmluZyIgIT09IHR5cGVvZiBlKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIGUgPSBlLnNwbGl0KCIuIik7CiAgICAgICAgICAgIHJldHVybiAyID4gZS5sZW5ndGggfHwgMyA8IGUubGVuZ3RoID8gZmFsc2UgOiAxID09IGVbMF0gJiYgMCA8PSBlWzFdICYmIDUgPj0gZVsxXSA/IHRydWUgOiAwICE9IGVbMF0gfHwgMTAgPCBlWzFdID8gZmFsc2UgOiB0cnVlOwogICAgICAgICAgfTsKICAgICAgICAgIHZhciBYYSA9IE9iamVjdC5hc3NpZ24oe30sIGEzKSwgeGEgPSAib2JqZWN0IiA9PSB0eXBlb2Ygd2luZG93LCBoYSA9ICJmdW5jdGlvbiIgPT0gdHlwZW9mIGltcG9ydFNjcmlwdHMsIFlhID0gIm9iamVjdCIgPT0gdHlwZW9mIHByb2Nlc3MgJiYgIm9iamVjdCIgPT0gdHlwZW9mIHByb2Nlc3MudmVyc2lvbnMgJiYgInN0cmluZyIgPT0gdHlwZW9mIHByb2Nlc3MudmVyc2lvbnMubm9kZSwgVSA9ICIiOwogICAgICAgICAgaWYgKFlhKSB7CiAgICAgICAgICAgIHZhciBaYSA9IF9fcmVxdWlyZSgiZnMiKSwgcWEgPSBfX3JlcXVpcmUoInBhdGgiKTsKICAgICAgICAgICAgVSA9IGhhID8gcWEuZGlybmFtZShVKSArICIvIiA6IF9fZGlybmFtZSArICIvIjsKICAgICAgICAgICAgdmFyICRhID0gZnVuY3Rpb24oZSwgYikgewogICAgICAgICAgICAgIGUgPSBlLnN0YXJ0c1dpdGgoImZpbGU6Ly8iKSA/IG5ldyBVUkwoZSkgOiBxYS5ub3JtYWxpemUoZSk7CiAgICAgICAgICAgICAgcmV0dXJuIFphLnJlYWRGaWxlU3luYyhlLCBiID8gdm9pZCAwIDogInV0ZjgiKTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgdmFyIG1hID0gZnVuY3Rpb24oZSkgewogICAgICAgICAgICAgIGUgPSAkYShlLCB0cnVlKTsKICAgICAgICAgICAgICBlLmJ1ZmZlciB8fCAoZSA9IG5ldyBVaW50OEFycmF5KGUpKTsKICAgICAgICAgICAgICByZXR1cm4gZTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgdmFyIG5hID0gZnVuY3Rpb24oZSwgYiwgYykgewogICAgICAgICAgICAgIGUgPSBlLnN0YXJ0c1dpdGgoImZpbGU6Ly8iKSA/IG5ldyBVUkwoZSkgOiBxYS5ub3JtYWxpemUoZSk7CiAgICAgICAgICAgICAgWmEucmVhZEZpbGUoZSwgZnVuY3Rpb24oZCwgZykgewogICAgICAgICAgICAgICAgZCA/IGMoZCkgOiBiKGcuYnVmZmVyKTsKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgMSA8IHByb2Nlc3MuYXJndi5sZW5ndGggJiYgcHJvY2Vzcy5hcmd2WzFdLnJlcGxhY2UoL1xcL2csICIvIik7CiAgICAgICAgICAgIHByb2Nlc3MuYXJndi5zbGljZSgyKTsKICAgICAgICAgICAgYTMuaW5zcGVjdCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiAiW0Vtc2NyaXB0ZW4gTW9kdWxlIG9iamVjdF0iOwogICAgICAgICAgICB9OwogICAgICAgICAgfSBlbHNlIGlmICh4YSB8fCBoYSkgaGEgPyBVID0gc2VsZi5sb2NhdGlvbi5ocmVmIDogInVuZGVmaW5lZCIgIT0gdHlwZW9mIGRvY3VtZW50ICYmIGRvY3VtZW50LmN1cnJlbnRTY3JpcHQgJiYgKFUgPSBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYyksIGsgJiYgKFUgPSBrKSwgVSA9IDAgIT09IFUuaW5kZXhPZigiYmxvYjoiKSA/IFUuc3Vic3RyKDAsIFUucmVwbGFjZSgvWz8jXS4qLywgIiIpLmxhc3RJbmRleE9mKCIvIikgKyAxKSA6ICIiLCAkYSA9IGZ1bmN0aW9uKGUpIHsKICAgICAgICAgICAgdmFyIGIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsKICAgICAgICAgICAgYi5vcGVuKCJHRVQiLCBlLCBmYWxzZSk7CiAgICAgICAgICAgIGIuc2VuZChudWxsKTsKICAgICAgICAgICAgcmV0dXJuIGIucmVzcG9uc2VUZXh0OwogICAgICAgICAgfSwgaGEgJiYgKG1hID0gZnVuY3Rpb24oZSkgewogICAgICAgICAgICB2YXIgYiA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpOwogICAgICAgICAgICBiLm9wZW4oIkdFVCIsIGUsIGZhbHNlKTsKICAgICAgICAgICAgYi5yZXNwb25zZVR5cGUgPSAiYXJyYXlidWZmZXIiOwogICAgICAgICAgICBiLnNlbmQobnVsbCk7CiAgICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShiLnJlc3BvbnNlKTsKICAgICAgICAgIH0pLCBuYSA9IGZ1bmN0aW9uKGUsIGIsIGMpIHsKICAgICAgICAgICAgdmFyIGQgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsKICAgICAgICAgICAgZC5vcGVuKCJHRVQiLCBlLCB0cnVlKTsKICAgICAgICAgICAgZC5yZXNwb25zZVR5cGUgPSAiYXJyYXlidWZmZXIiOwogICAgICAgICAgICBkLm9ubG9hZCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIDIwMCA9PSBkLnN0YXR1cyB8fCAwID09IGQuc3RhdHVzICYmIGQucmVzcG9uc2UgPyBiKGQucmVzcG9uc2UpIDogYygpOwogICAgICAgICAgICB9OwogICAgICAgICAgICBkLm9uZXJyb3IgPSBjOwogICAgICAgICAgICBkLnNlbmQobnVsbCk7CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIHVkID0gYTMucHJpbnQgfHwgY29uc29sZS5sb2cuYmluZChjb25zb2xlKSwgZGEgPSBhMy5wcmludEVyciB8fCBjb25zb2xlLndhcm4uYmluZChjb25zb2xlKTsKICAgICAgICAgIE9iamVjdC5hc3NpZ24oYTMsIFhhKTsKICAgICAgICAgIFhhID0gbnVsbDsKICAgICAgICAgIHZhciBmYTsKICAgICAgICAgIGEzLndhc21CaW5hcnkgJiYgKGZhID0gYTMud2FzbUJpbmFyeSk7CiAgICAgICAgICAib2JqZWN0IiAhPSB0eXBlb2YgV2ViQXNzZW1ibHkgJiYgZigibm8gbmF0aXZlIHdhc20gc3VwcG9ydCBkZXRlY3RlZCIpOwogICAgICAgICAgdmFyIGphLCB3YSA9IGZhbHNlLCB2YSA9ICJ1bmRlZmluZWQiICE9IHR5cGVvZiBUZXh0RGVjb2RlciA/IG5ldyBUZXh0RGVjb2RlcigidXRmOCIpIDogdm9pZCAwLCBZLCBlYSwgY2EsIFYsIENhID0gW10sIG9hID0gW10sIEJhID0gW10sIHphID0gZmFsc2UsIGFhID0gMCwgcmEgPSBudWxsLCBpYSA9IG51bGw7CiAgICAgICAgICB2YXIgUCA9ICJkcmFjb19kZWNvZGVyLndhc20iOwogICAgICAgICAgUC5zdGFydHNXaXRoKCJkYXRhOmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTtiYXNlNjQsIikgfHwgKFAgPSBsKFApKTsKICAgICAgICAgIHZhciB2ZCA9IDAsIHdkID0gW251bGwsIFtdLCBbXV0sIHhkID0geyBiOiBmdW5jdGlvbihlLCBiLCBjKSB7CiAgICAgICAgICAgIG5ldyBPKGUpLmluaXQoYiwgYyk7CiAgICAgICAgICAgIHZkKys7CiAgICAgICAgICAgIHRocm93IGU7CiAgICAgICAgICB9LCBhOiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgZigiIik7CiAgICAgICAgICB9LCBnOiBmdW5jdGlvbihlLCBiLCBjKSB7CiAgICAgICAgICAgIGVhLmNvcHlXaXRoaW4oZSwgYiwgYiArIGMpOwogICAgICAgICAgfSwgZTogZnVuY3Rpb24oZSkgewogICAgICAgICAgICB2YXIgYiA9IGVhLmxlbmd0aDsKICAgICAgICAgICAgZSA+Pj49IDA7CiAgICAgICAgICAgIGlmICgyMTQ3NDgzNjQ4IDwgZSkgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICBmb3IgKHZhciBjID0gMTsgNCA+PSBjOyBjICo9IDIpIHsKICAgICAgICAgICAgICB2YXIgZCA9IGIgKiAoMSArIDAuMiAvIGMpOwogICAgICAgICAgICAgIGQgPSBNYXRoLm1pbihkLCBlICsgMTAwNjYzMjk2KTsKICAgICAgICAgICAgICB2YXIgZyA9IE1hdGg7CiAgICAgICAgICAgICAgZCA9IE1hdGgubWF4KGUsIGQpOwogICAgICAgICAgICAgIGcgPSBnLm1pbi5jYWxsKGcsIDIxNDc0ODM2NDgsIGQgKyAoNjU1MzYgLSBkICUgNjU1MzYpICUgNjU1MzYpOwogICAgICAgICAgICAgIGE6IHsKICAgICAgICAgICAgICAgIGQgPSBqYS5idWZmZXI7CiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICBqYS5ncm93KGcgLSBkLmJ5dGVMZW5ndGggKyA2NTUzNSA+Pj4gMTYpOwogICAgICAgICAgICAgICAgICBBKCk7CiAgICAgICAgICAgICAgICAgIHZhciB1MyA9IDE7CiAgICAgICAgICAgICAgICAgIGJyZWFrIGE7CiAgICAgICAgICAgICAgICB9IGNhdGNoIChYKSB7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB1MyA9IHZvaWQgMDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHUzKSByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9LCBmOiBmdW5jdGlvbihlKSB7CiAgICAgICAgICAgIHJldHVybiA1MjsKICAgICAgICAgIH0sIGQ6IGZ1bmN0aW9uKGUsIGIsIGMsIGQsIGcpIHsKICAgICAgICAgICAgcmV0dXJuIDcwOwogICAgICAgICAgfSwgYzogZnVuY3Rpb24oZSwgYiwgYywgZCkgewogICAgICAgICAgICBmb3IgKHZhciBnID0gMCwgdTMgPSAwOyB1MyA8IGM7IHUzKyspIHsKICAgICAgICAgICAgICB2YXIgWCA9IFZbYiA+PiAyXSwgYWIgPSBWW2IgKyA0ID4+IDJdOwogICAgICAgICAgICAgIGIgKz0gODsKICAgICAgICAgICAgICBmb3IgKHZhciBzYSA9IDA7IHNhIDwgYWI7IHNhKyspIHsKICAgICAgICAgICAgICAgIHZhciB0YSA9IGVhW1ggKyBzYV0sIHVhID0gd2RbZV07CiAgICAgICAgICAgICAgICAwID09PSB0YSB8fCAxMCA9PT0gdGEgPyAoKDEgPT09IGUgPyB1ZCA6IGRhKShwKHVhLCAwKSksIHVhLmxlbmd0aCA9IDApIDogdWEucHVzaCh0YSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGcgKz0gYWI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgVltkID4+IDJdID0gZzsKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgICB9IH07CiAgICAgICAgICAoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIGZ1bmN0aW9uIGUoZywgdTMpIHsKICAgICAgICAgICAgICBhMy5hc20gPSBnLmV4cG9ydHM7CiAgICAgICAgICAgICAgamEgPSBhMy5hc20uaDsKICAgICAgICAgICAgICBBKCk7CiAgICAgICAgICAgICAgb2EudW5zaGlmdChhMy5hc20uaSk7CiAgICAgICAgICAgICAgYWEtLTsKICAgICAgICAgICAgICBhMy5tb25pdG9yUnVuRGVwZW5kZW5jaWVzICYmIGEzLm1vbml0b3JSdW5EZXBlbmRlbmNpZXMoYWEpOwogICAgICAgICAgICAgIDAgPT0gYWEgJiYgKG51bGwgIT09IHJhICYmIChjbGVhckludGVydmFsKHJhKSwgcmEgPSBudWxsKSwgaWEgJiYgKGcgPSBpYSwgaWEgPSBudWxsLCBnKCkpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmdW5jdGlvbiBiKGcpIHsKICAgICAgICAgICAgICBlKGcuaW5zdGFuY2UpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZ1bmN0aW9uIGMoZykgewogICAgICAgICAgICAgIHJldHVybiB2MygpLnRoZW4oZnVuY3Rpb24odTMpIHsKICAgICAgICAgICAgICAgIHJldHVybiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZSh1MywgZCk7CiAgICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbih1MykgewogICAgICAgICAgICAgICAgcmV0dXJuIHUzOwogICAgICAgICAgICAgIH0pLnRoZW4oZywgZnVuY3Rpb24odTMpIHsKICAgICAgICAgICAgICAgIGRhKCJmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiAiICsgdTMpOwogICAgICAgICAgICAgICAgZih1Myk7CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGQgPSB7IGE6IHhkIH07CiAgICAgICAgICAgIGFhKys7CiAgICAgICAgICAgIGEzLm1vbml0b3JSdW5EZXBlbmRlbmNpZXMgJiYgYTMubW9uaXRvclJ1bkRlcGVuZGVuY2llcyhhYSk7CiAgICAgICAgICAgIGlmIChhMy5pbnN0YW50aWF0ZVdhc20pIHRyeSB7CiAgICAgICAgICAgICAgcmV0dXJuIGEzLmluc3RhbnRpYXRlV2FzbShkLCBlKTsKICAgICAgICAgICAgfSBjYXRjaCAoZykgewogICAgICAgICAgICAgIGRhKCJNb2R1bGUuaW5zdGFudGlhdGVXYXNtIGNhbGxiYWNrIGZhaWxlZCB3aXRoIGVycm9yOiAiICsgZyksIGthKGcpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIChmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByZXR1cm4gZmEgfHwgImZ1bmN0aW9uIiAhPSB0eXBlb2YgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGVTdHJlYW1pbmcgfHwgUC5zdGFydHNXaXRoKCJkYXRhOmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTtiYXNlNjQsIikgfHwgUC5zdGFydHNXaXRoKCJmaWxlOi8vIikgfHwgWWEgfHwgImZ1bmN0aW9uIiAhPSB0eXBlb2YgZmV0Y2ggPyBjKGIpIDogZmV0Y2goUCwgeyBjcmVkZW50aWFsczogInNhbWUtb3JpZ2luIiB9KS50aGVuKGZ1bmN0aW9uKGcpIHsKICAgICAgICAgICAgICAgIHJldHVybiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZyhnLCBkKS50aGVuKGIsIGZ1bmN0aW9uKHUzKSB7CiAgICAgICAgICAgICAgICAgIGRhKCJ3YXNtIHN0cmVhbWluZyBjb21waWxlIGZhaWxlZDogIiArIHUzKTsKICAgICAgICAgICAgICAgICAgZGEoImZhbGxpbmcgYmFjayB0byBBcnJheUJ1ZmZlciBpbnN0YW50aWF0aW9uIik7CiAgICAgICAgICAgICAgICAgIHJldHVybiBjKGIpOwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0pKCkuY2F0Y2goa2EpOwogICAgICAgICAgICByZXR1cm4ge307CiAgICAgICAgICB9KSgpOwogICAgICAgICAgdmFyIGJiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9Wb2lkUHRyX19fZGVzdHJveV9fXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChiYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfVm9pZFB0cl9fX2Rlc3Ryb3lfX18wID0gYTMuYXNtLmspLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBEYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2RlckJ1ZmZlcl9EZWNvZGVyQnVmZmVyXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChEYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2RlckJ1ZmZlcl9EZWNvZGVyQnVmZmVyXzAgPSBhMy5hc20ubCkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGNiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyQnVmZmVyX0luaXRfMiA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGNiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyQnVmZmVyX0luaXRfMiA9IGEzLmFzbS5tKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgZGIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJCdWZmZXJfX19kZXN0cm95X19fMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGRiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyQnVmZmVyX19fZGVzdHJveV9fXzAgPSBhMy5hc20ubikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIEVhID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9BdHRyaWJ1dGVUcmFuc2Zvcm1EYXRhX0F0dHJpYnV0ZVRyYW5zZm9ybURhdGFfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKEVhID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9BdHRyaWJ1dGVUcmFuc2Zvcm1EYXRhX0F0dHJpYnV0ZVRyYW5zZm9ybURhdGFfMCA9IGEzLmFzbS5vKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgZWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0F0dHJpYnV0ZVRyYW5zZm9ybURhdGFfdHJhbnNmb3JtX3R5cGVfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGViID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9BdHRyaWJ1dGVUcmFuc2Zvcm1EYXRhX3RyYW5zZm9ybV90eXBlXzAgPSBhMy5hc20ucCkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGZiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9BdHRyaWJ1dGVUcmFuc2Zvcm1EYXRhX19fZGVzdHJveV9fXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChmYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfQXR0cmlidXRlVHJhbnNmb3JtRGF0YV9fX2Rlc3Ryb3lfX18wID0gYTMuYXNtLnEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBGYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfR2VvbWV0cnlBdHRyaWJ1dGVfR2VvbWV0cnlBdHRyaWJ1dGVfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKEZhID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9HZW9tZXRyeUF0dHJpYnV0ZV9HZW9tZXRyeUF0dHJpYnV0ZV8wID0gYTMuYXNtLnIpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBnYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfR2VvbWV0cnlBdHRyaWJ1dGVfX19kZXN0cm95X19fMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGdiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9HZW9tZXRyeUF0dHJpYnV0ZV9fX2Rlc3Ryb3lfX18wID0gYTMuYXNtLnMpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBHYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfUG9pbnRBdHRyaWJ1dGVfUG9pbnRBdHRyaWJ1dGVfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKEdhID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9Qb2ludEF0dHJpYnV0ZV9Qb2ludEF0dHJpYnV0ZV8wID0gYTMuYXNtLnQpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBoYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfUG9pbnRBdHRyaWJ1dGVfc2l6ZV8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoaGIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50QXR0cmlidXRlX3NpemVfMCA9IGEzLmFzbS51KS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgaWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50QXR0cmlidXRlX0dldEF0dHJpYnV0ZVRyYW5zZm9ybURhdGFfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGliID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9Qb2ludEF0dHJpYnV0ZV9HZXRBdHRyaWJ1dGVUcmFuc2Zvcm1EYXRhXzAgPSBhMy5hc20udikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGpiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9Qb2ludEF0dHJpYnV0ZV9hdHRyaWJ1dGVfdHlwZV8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoamIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50QXR0cmlidXRlX2F0dHJpYnV0ZV90eXBlXzAgPSBhMy5hc20udykuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGtiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9Qb2ludEF0dHJpYnV0ZV9kYXRhX3R5cGVfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGtiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9Qb2ludEF0dHJpYnV0ZV9kYXRhX3R5cGVfMCA9IGEzLmFzbS54KS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgbGIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50QXR0cmlidXRlX251bV9jb21wb25lbnRzXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChsYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfUG9pbnRBdHRyaWJ1dGVfbnVtX2NvbXBvbmVudHNfMCA9IGEzLmFzbS55KS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgbWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50QXR0cmlidXRlX25vcm1hbGl6ZWRfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKG1iID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9Qb2ludEF0dHJpYnV0ZV9ub3JtYWxpemVkXzAgPSBhMy5hc20ueikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIG5iID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9Qb2ludEF0dHJpYnV0ZV9ieXRlX3N0cmlkZV8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAobmIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50QXR0cmlidXRlX2J5dGVfc3RyaWRlXzAgPSBhMy5hc20uQSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIG9iID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9Qb2ludEF0dHJpYnV0ZV9ieXRlX29mZnNldF8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAob2IgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50QXR0cmlidXRlX2J5dGVfb2Zmc2V0XzAgPSBhMy5hc20uQikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIHBiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9Qb2ludEF0dHJpYnV0ZV91bmlxdWVfaWRfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKHBiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9Qb2ludEF0dHJpYnV0ZV91bmlxdWVfaWRfMCA9IGEzLmFzbS5DKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgcWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50QXR0cmlidXRlX19fZGVzdHJveV9fXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChxYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfUG9pbnRBdHRyaWJ1dGVfX19kZXN0cm95X19fMCA9IGEzLmFzbS5EKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgSGEgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0F0dHJpYnV0ZVF1YW50aXphdGlvblRyYW5zZm9ybV9BdHRyaWJ1dGVRdWFudGl6YXRpb25UcmFuc2Zvcm1fMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKEhhID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9BdHRyaWJ1dGVRdWFudGl6YXRpb25UcmFuc2Zvcm1fQXR0cmlidXRlUXVhbnRpemF0aW9uVHJhbnNmb3JtXzAgPSBhMy5hc20uRSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIHJiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9BdHRyaWJ1dGVRdWFudGl6YXRpb25UcmFuc2Zvcm1fSW5pdEZyb21BdHRyaWJ1dGVfMSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKHJiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9BdHRyaWJ1dGVRdWFudGl6YXRpb25UcmFuc2Zvcm1fSW5pdEZyb21BdHRyaWJ1dGVfMSA9IGEzLmFzbS5GKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgc2IgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0F0dHJpYnV0ZVF1YW50aXphdGlvblRyYW5zZm9ybV9xdWFudGl6YXRpb25fYml0c18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoc2IgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0F0dHJpYnV0ZVF1YW50aXphdGlvblRyYW5zZm9ybV9xdWFudGl6YXRpb25fYml0c18wID0gYTMuYXNtLkcpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCB0YiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfQXR0cmlidXRlUXVhbnRpemF0aW9uVHJhbnNmb3JtX21pbl92YWx1ZV8xID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAodGIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0F0dHJpYnV0ZVF1YW50aXphdGlvblRyYW5zZm9ybV9taW5fdmFsdWVfMSA9IGEzLmFzbS5IKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgdWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0F0dHJpYnV0ZVF1YW50aXphdGlvblRyYW5zZm9ybV9yYW5nZV8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAodWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0F0dHJpYnV0ZVF1YW50aXphdGlvblRyYW5zZm9ybV9yYW5nZV8wID0gYTMuYXNtLkkpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCB2YiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfQXR0cmlidXRlUXVhbnRpemF0aW9uVHJhbnNmb3JtX19fZGVzdHJveV9fXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuICh2YiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfQXR0cmlidXRlUXVhbnRpemF0aW9uVHJhbnNmb3JtX19fZGVzdHJveV9fXzAgPSBhMy5hc20uSikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIElhID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9BdHRyaWJ1dGVPY3RhaGVkcm9uVHJhbnNmb3JtX0F0dHJpYnV0ZU9jdGFoZWRyb25UcmFuc2Zvcm1fMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKElhID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9BdHRyaWJ1dGVPY3RhaGVkcm9uVHJhbnNmb3JtX0F0dHJpYnV0ZU9jdGFoZWRyb25UcmFuc2Zvcm1fMCA9IGEzLmFzbS5LKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgd2IgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0F0dHJpYnV0ZU9jdGFoZWRyb25UcmFuc2Zvcm1fSW5pdEZyb21BdHRyaWJ1dGVfMSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKHdiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9BdHRyaWJ1dGVPY3RhaGVkcm9uVHJhbnNmb3JtX0luaXRGcm9tQXR0cmlidXRlXzEgPSBhMy5hc20uTCkuYXBwbHkoCiAgICAgICAgICAgICAgbnVsbCwKICAgICAgICAgICAgICBhcmd1bWVudHMKICAgICAgICAgICAgKTsKICAgICAgICAgIH0sIHhiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9BdHRyaWJ1dGVPY3RhaGVkcm9uVHJhbnNmb3JtX3F1YW50aXphdGlvbl9iaXRzXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuICh4YiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfQXR0cmlidXRlT2N0YWhlZHJvblRyYW5zZm9ybV9xdWFudGl6YXRpb25fYml0c18wID0gYTMuYXNtLk0pLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCB5YiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfQXR0cmlidXRlT2N0YWhlZHJvblRyYW5zZm9ybV9fX2Rlc3Ryb3lfX18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoeWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0F0dHJpYnV0ZU9jdGFoZWRyb25UcmFuc2Zvcm1fX19kZXN0cm95X19fMCA9IGEzLmFzbS5OKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgSmEgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50Q2xvdWRfUG9pbnRDbG91ZF8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoSmEgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50Q2xvdWRfUG9pbnRDbG91ZF8wID0gYTMuYXNtLk8pLmFwcGx5KAogICAgICAgICAgICAgIG51bGwsCiAgICAgICAgICAgICAgYXJndW1lbnRzCiAgICAgICAgICAgICk7CiAgICAgICAgICB9LCB6YiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfUG9pbnRDbG91ZF9udW1fYXR0cmlidXRlc18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoemIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50Q2xvdWRfbnVtX2F0dHJpYnV0ZXNfMCA9IGEzLmFzbS5QKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgQWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50Q2xvdWRfbnVtX3BvaW50c18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoQWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50Q2xvdWRfbnVtX3BvaW50c18wID0gYTMuYXNtLlEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBCYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfUG9pbnRDbG91ZF9fX2Rlc3Ryb3lfX18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoQmIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1BvaW50Q2xvdWRfX19kZXN0cm95X19fMCA9IGEzLmFzbS5SKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgS2EgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01lc2hfTWVzaF8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoS2EgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01lc2hfTWVzaF8wID0gYTMuYXNtLlMpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBDYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWVzaF9udW1fZmFjZXNfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKENiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9NZXNoX251bV9mYWNlc18wID0gYTMuYXNtLlQpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBEYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWVzaF9udW1fYXR0cmlidXRlc18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoRGIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01lc2hfbnVtX2F0dHJpYnV0ZXNfMCA9IGEzLmFzbS5VKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgRWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01lc2hfbnVtX3BvaW50c18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoRWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01lc2hfbnVtX3BvaW50c18wID0gYTMuYXNtLlYpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBGYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWVzaF9fX2Rlc3Ryb3lfX18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoRmIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01lc2hfX19kZXN0cm95X19fMCA9IGEzLmFzbS5XKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgTGEgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01ldGFkYXRhX01ldGFkYXRhXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChMYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWV0YWRhdGFfTWV0YWRhdGFfMCA9IGEzLmFzbS5YKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgR2IgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01ldGFkYXRhX19fZGVzdHJveV9fXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChHYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWV0YWRhdGFfX19kZXN0cm95X19fMCA9IGEzLmFzbS5ZKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgSGIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1N0YXR1c19jb2RlXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChIYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfU3RhdHVzX2NvZGVfMCA9IGEzLmFzbS5aKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgSWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1N0YXR1c19va18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoSWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1N0YXR1c19va18wID0gYTMuYXNtLl8pLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBKYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfU3RhdHVzX2Vycm9yX21zZ18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoSmIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1N0YXR1c19lcnJvcl9tc2dfMCA9IGEzLmFzbS4kKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgS2IgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1N0YXR1c19fX2Rlc3Ryb3lfX18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoS2IgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX1N0YXR1c19fX2Rlc3Ryb3lfX18wID0gYTMuYXNtLmFhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgTWEgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvRmxvYXQzMkFycmF5X0RyYWNvRmxvYXQzMkFycmF5XzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChNYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29GbG9hdDMyQXJyYXlfRHJhY29GbG9hdDMyQXJyYXlfMCA9IGEzLmFzbS5iYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIExiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb0Zsb2F0MzJBcnJheV9HZXRWYWx1ZV8xID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoTGIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvRmxvYXQzMkFycmF5X0dldFZhbHVlXzEgPSBhMy5hc20uY2EpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBNYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29GbG9hdDMyQXJyYXlfc2l6ZV8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoTWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvRmxvYXQzMkFycmF5X3NpemVfMCA9IGEzLmFzbS5kYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIE5iID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb0Zsb2F0MzJBcnJheV9fX2Rlc3Ryb3lfX18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoTmIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvRmxvYXQzMkFycmF5X19fZGVzdHJveV9fXzAgPSBhMy5hc20uZWEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBOYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29JbnQ4QXJyYXlfRHJhY29JbnQ4QXJyYXlfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKE5hID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb0ludDhBcnJheV9EcmFjb0ludDhBcnJheV8wID0gYTMuYXNtLmZhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgT2IgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvSW50OEFycmF5X0dldFZhbHVlXzEgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChPYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29JbnQ4QXJyYXlfR2V0VmFsdWVfMSA9IGEzLmFzbS5nYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIFBiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb0ludDhBcnJheV9zaXplXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChQYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29JbnQ4QXJyYXlfc2l6ZV8wID0gYTMuYXNtLmhhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgUWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvSW50OEFycmF5X19fZGVzdHJveV9fXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChRYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29JbnQ4QXJyYXlfX19kZXN0cm95X19fMCA9IGEzLmFzbS5pYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIE9hID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb1VJbnQ4QXJyYXlfRHJhY29VSW50OEFycmF5XzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChPYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29VSW50OEFycmF5X0RyYWNvVUludDhBcnJheV8wID0gYTMuYXNtLmphKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgUmIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvVUludDhBcnJheV9HZXRWYWx1ZV8xID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoUmIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvVUludDhBcnJheV9HZXRWYWx1ZV8xID0gYTMuYXNtLmthKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgU2IgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvVUludDhBcnJheV9zaXplXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChTYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29VSW50OEFycmF5X3NpemVfMCA9IGEzLmFzbS5sYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIFRiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb1VJbnQ4QXJyYXlfX19kZXN0cm95X19fMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKFRiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb1VJbnQ4QXJyYXlfX19kZXN0cm95X19fMCA9IGEzLmFzbS5tYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIFBhID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb0ludDE2QXJyYXlfRHJhY29JbnQxNkFycmF5XzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChQYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29JbnQxNkFycmF5X0RyYWNvSW50MTZBcnJheV8wID0gYTMuYXNtLm5hKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgVWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvSW50MTZBcnJheV9HZXRWYWx1ZV8xID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoVWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvSW50MTZBcnJheV9HZXRWYWx1ZV8xID0gYTMuYXNtLm9hKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgVmIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvSW50MTZBcnJheV9zaXplXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChWYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29JbnQxNkFycmF5X3NpemVfMCA9IGEzLmFzbS5wYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIFdiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb0ludDE2QXJyYXlfX19kZXN0cm95X19fMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKFdiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb0ludDE2QXJyYXlfX19kZXN0cm95X19fMCA9IGEzLmFzbS5xYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIFFhID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb1VJbnQxNkFycmF5X0RyYWNvVUludDE2QXJyYXlfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKFFhID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb1VJbnQxNkFycmF5X0RyYWNvVUludDE2QXJyYXlfMCA9IGEzLmFzbS5yYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIFhiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb1VJbnQxNkFycmF5X0dldFZhbHVlXzEgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChYYiA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29VSW50MTZBcnJheV9HZXRWYWx1ZV8xID0gYTMuYXNtLnNhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgWWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvVUludDE2QXJyYXlfc2l6ZV8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoWWIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvVUludDE2QXJyYXlfc2l6ZV8wID0gYTMuYXNtLnRhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgWmIgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvVUludDE2QXJyYXlfX19kZXN0cm95X19fMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKFpiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb1VJbnQxNkFycmF5X19fZGVzdHJveV9fXzAgPSBhMy5hc20udWEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBSYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29JbnQzMkFycmF5X0RyYWNvSW50MzJBcnJheV8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoUmEgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvSW50MzJBcnJheV9EcmFjb0ludDMyQXJyYXlfMCA9IGEzLmFzbS52YSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sICRiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb0ludDMyQXJyYXlfR2V0VmFsdWVfMSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKCRiID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb0ludDMyQXJyYXlfR2V0VmFsdWVfMSA9IGEzLmFzbS53YSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGFjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb0ludDMyQXJyYXlfc2l6ZV8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoYWMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvSW50MzJBcnJheV9zaXplXzAgPSBhMy5hc20ueGEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBiYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29JbnQzMkFycmF5X19fZGVzdHJveV9fXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChiYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29JbnQzMkFycmF5X19fZGVzdHJveV9fXzAgPSBhMy5hc20ueWEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBTYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29VSW50MzJBcnJheV9EcmFjb1VJbnQzMkFycmF5XzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChTYSA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29VSW50MzJBcnJheV9EcmFjb1VJbnQzMkFycmF5XzAgPSBhMy5hc20uemEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBjYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29VSW50MzJBcnJheV9HZXRWYWx1ZV8xID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoY2MgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RyYWNvVUludDMyQXJyYXlfR2V0VmFsdWVfMSA9IGEzLmFzbS5BYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGRjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb1VJbnQzMkFycmF5X3NpemVfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGRjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb1VJbnQzMkFycmF5X3NpemVfMCA9IGEzLmFzbS5CYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGVjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EcmFjb1VJbnQzMkFycmF5X19fZGVzdHJveV9fXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChlYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRHJhY29VSW50MzJBcnJheV9fX2Rlc3Ryb3lfX18wID0gYTMuYXNtLkNhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgVGEgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01ldGFkYXRhUXVlcmllcl9NZXRhZGF0YVF1ZXJpZXJfMCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKFRhID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9NZXRhZGF0YVF1ZXJpZXJfTWV0YWRhdGFRdWVyaWVyXzAgPSBhMy5hc20uRGEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBmYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWV0YWRhdGFRdWVyaWVyX0hhc0VudHJ5XzIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChmYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWV0YWRhdGFRdWVyaWVyX0hhc0VudHJ5XzIgPSBhMy5hc20uRWEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBnYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWV0YWRhdGFRdWVyaWVyX0dldEludEVudHJ5XzIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChnYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWV0YWRhdGFRdWVyaWVyX0dldEludEVudHJ5XzIgPSBhMy5hc20uRmEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBoYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWV0YWRhdGFRdWVyaWVyX0dldEludEVudHJ5QXJyYXlfMyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGhjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9NZXRhZGF0YVF1ZXJpZXJfR2V0SW50RW50cnlBcnJheV8zID0gYTMuYXNtLkdhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgaWMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01ldGFkYXRhUXVlcmllcl9HZXREb3VibGVFbnRyeV8yID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoaWMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01ldGFkYXRhUXVlcmllcl9HZXREb3VibGVFbnRyeV8yID0gYTMuYXNtLkhhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgamMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01ldGFkYXRhUXVlcmllcl9HZXRTdHJpbmdFbnRyeV8yID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoamMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01ldGFkYXRhUXVlcmllcl9HZXRTdHJpbmdFbnRyeV8yID0gYTMuYXNtLklhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwga2MgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01ldGFkYXRhUXVlcmllcl9OdW1FbnRyaWVzXzEgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChrYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWV0YWRhdGFRdWVyaWVyX051bUVudHJpZXNfMSA9IGEzLmFzbS5KYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGxjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9NZXRhZGF0YVF1ZXJpZXJfR2V0RW50cnlOYW1lXzIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChsYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfTWV0YWRhdGFRdWVyaWVyX0dldEVudHJ5TmFtZV8yID0gYTMuYXNtLkthKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgbWMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01ldGFkYXRhUXVlcmllcl9fX2Rlc3Ryb3lfX18wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAobWMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX01ldGFkYXRhUXVlcmllcl9fX2Rlc3Ryb3lfX18wID0gYTMuYXNtLkxhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgVWEgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfRGVjb2Rlcl8wID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoVWEgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfRGVjb2Rlcl8wID0gYTMuYXNtLk1hKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgbmMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfRGVjb2RlQXJyYXlUb1BvaW50Q2xvdWRfMyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKG5jID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0RlY29kZUFycmF5VG9Qb2ludENsb3VkXzMgPSBhMy5hc20uTmEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBvYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9EZWNvZGVBcnJheVRvTWVzaF8zID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAob2MgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfRGVjb2RlQXJyYXlUb01lc2hfMyA9IGEzLmFzbS5PYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIHBjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZUlkXzIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChwYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVJZF8yID0gYTMuYXNtLlBhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgcWMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0QXR0cmlidXRlSWRCeU5hbWVfMiA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKHFjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZUlkQnlOYW1lXzIgPSBhMy5hc20uUWEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCByYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVJZEJ5TWV0YWRhdGFFbnRyeV8zID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAocmMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0QXR0cmlidXRlSWRCeU1ldGFkYXRhRW50cnlfMyA9IGEzLmFzbS5SYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIHNjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZV8yID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoc2MgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0QXR0cmlidXRlXzIgPSBhMy5hc20uU2EpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCB0YyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVCeVVuaXF1ZUlkXzIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuICh0YyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVCeVVuaXF1ZUlkXzIgPSBhMy5hc20uVGEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCB1YyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRNZXRhZGF0YV8xID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAodWMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0TWV0YWRhdGFfMSA9IGEzLmFzbS5VYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIHZjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZU1ldGFkYXRhXzIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuICh2YyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVNZXRhZGF0YV8yID0gYTMuYXNtLlZhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgd2MgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0RmFjZUZyb21NZXNoXzMgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuICh3YyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRGYWNlRnJvbU1lc2hfMyA9IGEzLmFzbS5XYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIHhjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldFRyaWFuZ2xlU3RyaXBzRnJvbU1lc2hfMiA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKHhjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldFRyaWFuZ2xlU3RyaXBzRnJvbU1lc2hfMiA9IGEzLmFzbS5YYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIHljID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldFRyaWFuZ2xlc1VJbnQxNkFycmF5XzMgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuICh5YyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRUcmlhbmdsZXNVSW50MTZBcnJheV8zID0gYTMuYXNtLllhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgemMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0VHJpYW5nbGVzVUludDMyQXJyYXlfMyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKHpjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldFRyaWFuZ2xlc1VJbnQzMkFycmF5XzMgPSBhMy5hc20uWmEpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBBYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVGbG9hdF8zID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoQWMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0QXR0cmlidXRlRmxvYXRfMyA9IGEzLmFzbS5fYSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIEJjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZUZsb2F0Rm9yQWxsUG9pbnRzXzMgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChCYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVGbG9hdEZvckFsbFBvaW50c18zID0gYTMuYXNtLiRhKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgQ2MgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0QXR0cmlidXRlSW50Rm9yQWxsUG9pbnRzXzMgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChDYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVJbnRGb3JBbGxQb2ludHNfMyA9IGEzLmFzbS5hYikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIERjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZUludDhGb3JBbGxQb2ludHNfMyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKERjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZUludDhGb3JBbGxQb2ludHNfMyA9IGEzLmFzbS5iYikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIEVjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZVVJbnQ4Rm9yQWxsUG9pbnRzXzMgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChFYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVVSW50OEZvckFsbFBvaW50c18zID0gYTMuYXNtLmNiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgRmMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0QXR0cmlidXRlSW50MTZGb3JBbGxQb2ludHNfMyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKEZjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZUludDE2Rm9yQWxsUG9pbnRzXzMgPSBhMy5hc20uZGIpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBHYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVVSW50MTZGb3JBbGxQb2ludHNfMyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKEdjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZVVJbnQxNkZvckFsbFBvaW50c18zID0gYTMuYXNtLmViKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgSGMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0QXR0cmlidXRlSW50MzJGb3JBbGxQb2ludHNfMyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKEhjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZUludDMyRm9yQWxsUG9pbnRzXzMgPSBhMy5hc20uZmIpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBJYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVVSW50MzJGb3JBbGxQb2ludHNfMyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKEljID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEF0dHJpYnV0ZVVJbnQzMkZvckFsbFBvaW50c18zID0gYTMuYXNtLmdiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgSmMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0QXR0cmlidXRlRGF0YUFycmF5Rm9yQWxsUG9pbnRzXzUgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChKYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9HZXRBdHRyaWJ1dGVEYXRhQXJyYXlGb3JBbGxQb2ludHNfNSA9IGEzLmFzbS5oYikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIEtjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX1NraXBBdHRyaWJ1dGVUcmFuc2Zvcm1fMSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKEtjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX1NraXBBdHRyaWJ1dGVUcmFuc2Zvcm1fMSA9IGEzLmFzbS5pYikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIExjID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0dldEVuY29kZWRHZW9tZXRyeVR5cGVfRGVwcmVjYXRlZF8xID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoTGMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfR2V0RW5jb2RlZEdlb21ldHJ5VHlwZV9EZXByZWNhdGVkXzEgPSBhMy5hc20uamIpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBNYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9EZWNvZGVCdWZmZXJUb1BvaW50Q2xvdWRfMiA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKE1jID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX0RlY29kZUJ1ZmZlclRvUG9pbnRDbG91ZF8yID0gYTMuYXNtLmtiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgTmMgPSBhMy5fZW1zY3JpcHRlbl9iaW5kX0RlY29kZXJfRGVjb2RlQnVmZmVyVG9NZXNoXzIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChOYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9EZWNvZGVCdWZmZXJUb01lc2hfMiA9IGEzLmFzbS5sYikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIE9jID0gYTMuX2Vtc2NyaXB0ZW5fYmluZF9EZWNvZGVyX19fZGVzdHJveV9fXzAgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChPYyA9IGEzLl9lbXNjcmlwdGVuX2JpbmRfRGVjb2Rlcl9fX2Rlc3Ryb3lfX18wID0gYTMuYXNtLm1iKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgUGMgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0F0dHJpYnV0ZVRyYW5zZm9ybVR5cGVfQVRUUklCVVRFX0lOVkFMSURfVFJBTlNGT1JNID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoUGMgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0F0dHJpYnV0ZVRyYW5zZm9ybVR5cGVfQVRUUklCVVRFX0lOVkFMSURfVFJBTlNGT1JNID0gYTMuYXNtLm5iKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgUWMgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0F0dHJpYnV0ZVRyYW5zZm9ybVR5cGVfQVRUUklCVVRFX05PX1RSQU5TRk9STSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKFFjID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19BdHRyaWJ1dGVUcmFuc2Zvcm1UeXBlX0FUVFJJQlVURV9OT19UUkFOU0ZPUk0gPSBhMy5hc20ub2IpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBSYyA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fQXR0cmlidXRlVHJhbnNmb3JtVHlwZV9BVFRSSUJVVEVfUVVBTlRJWkFUSU9OX1RSQU5TRk9STSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKFJjID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19BdHRyaWJ1dGVUcmFuc2Zvcm1UeXBlX0FUVFJJQlVURV9RVUFOVElaQVRJT05fVFJBTlNGT1JNID0gYTMuYXNtLnBiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgU2MgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0F0dHJpYnV0ZVRyYW5zZm9ybVR5cGVfQVRUUklCVVRFX09DVEFIRURST05fVFJBTlNGT1JNID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoU2MgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0F0dHJpYnV0ZVRyYW5zZm9ybVR5cGVfQVRUUklCVVRFX09DVEFIRURST05fVFJBTlNGT1JNID0gYTMuYXNtLnFiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgVGMgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0dlb21ldHJ5QXR0cmlidXRlX1R5cGVfSU5WQUxJRCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKFRjID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19HZW9tZXRyeUF0dHJpYnV0ZV9UeXBlX0lOVkFMSUQgPSBhMy5hc20ucmIpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBVYyA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fR2VvbWV0cnlBdHRyaWJ1dGVfVHlwZV9QT1NJVElPTiA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKFVjID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19HZW9tZXRyeUF0dHJpYnV0ZV9UeXBlX1BPU0lUSU9OID0gYTMuYXNtLnNiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgVmMgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0dlb21ldHJ5QXR0cmlidXRlX1R5cGVfTk9STUFMID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoVmMgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0dlb21ldHJ5QXR0cmlidXRlX1R5cGVfTk9STUFMID0gYTMuYXNtLnRiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgV2MgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0dlb21ldHJ5QXR0cmlidXRlX1R5cGVfQ09MT1IgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChXYyA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fR2VvbWV0cnlBdHRyaWJ1dGVfVHlwZV9DT0xPUiA9IGEzLmFzbS51YikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIFhjID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19HZW9tZXRyeUF0dHJpYnV0ZV9UeXBlX1RFWF9DT09SRCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKFhjID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19HZW9tZXRyeUF0dHJpYnV0ZV9UeXBlX1RFWF9DT09SRCA9IGEzLmFzbS52YikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIFljID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19HZW9tZXRyeUF0dHJpYnV0ZV9UeXBlX0dFTkVSSUMgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChZYyA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fR2VvbWV0cnlBdHRyaWJ1dGVfVHlwZV9HRU5FUklDID0gYTMuYXNtLndiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgWmMgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0VuY29kZWRHZW9tZXRyeVR5cGVfSU5WQUxJRF9HRU9NRVRSWV9UWVBFID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoWmMgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0VuY29kZWRHZW9tZXRyeVR5cGVfSU5WQUxJRF9HRU9NRVRSWV9UWVBFID0gYTMuYXNtLnhiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgJGMgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0VuY29kZWRHZW9tZXRyeVR5cGVfUE9JTlRfQ0xPVUQgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuICgkYyA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fRW5jb2RlZEdlb21ldHJ5VHlwZV9QT0lOVF9DTE9VRCA9IGEzLmFzbS55YikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGFkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19FbmNvZGVkR2VvbWV0cnlUeXBlX1RSSUFOR1VMQVJfTUVTSCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGFkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19FbmNvZGVkR2VvbWV0cnlUeXBlX1RSSUFOR1VMQVJfTUVTSCA9IGEzLmFzbS56YikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGJkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19EYXRhVHlwZV9EVF9JTlZBTElEID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoYmQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0RhdGFUeXBlX0RUX0lOVkFMSUQgPSBhMy5hc20uQWIpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBjZCA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fRGF0YVR5cGVfRFRfSU5UOCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGNkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19EYXRhVHlwZV9EVF9JTlQ4ID0gYTMuYXNtLkJiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgZGQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0RhdGFUeXBlX0RUX1VJTlQ4ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoZGQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0RhdGFUeXBlX0RUX1VJTlQ4ID0gYTMuYXNtLkNiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgZWQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0RhdGFUeXBlX0RUX0lOVDE2ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoZWQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0RhdGFUeXBlX0RUX0lOVDE2ID0gYTMuYXNtLkRiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgZmQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0RhdGFUeXBlX0RUX1VJTlQxNiA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGZkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19EYXRhVHlwZV9EVF9VSU5UMTYgPSBhMy5hc20uRWIpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBnZCA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fRGF0YVR5cGVfRFRfSU5UMzIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChnZCA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fRGF0YVR5cGVfRFRfSU5UMzIgPSBhMy5hc20uRmIpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBoZCA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fRGF0YVR5cGVfRFRfVUlOVDMyID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoaGQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0RhdGFUeXBlX0RUX1VJTlQzMiA9IGEzLmFzbS5HYikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGlkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19EYXRhVHlwZV9EVF9JTlQ2NCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKGlkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19EYXRhVHlwZV9EVF9JTlQ2NCA9IGEzLmFzbS5IYikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIGpkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19EYXRhVHlwZV9EVF9VSU5UNjQgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChqZCA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fRGF0YVR5cGVfRFRfVUlOVDY0ID0gYTMuYXNtLkliKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwga2QgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0RhdGFUeXBlX0RUX0ZMT0FUMzIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChrZCA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fRGF0YVR5cGVfRFRfRkxPQVQzMiA9IGEzLmFzbS5KYikuYXBwbHkoCiAgICAgICAgICAgICAgbnVsbCwKICAgICAgICAgICAgICBhcmd1bWVudHMKICAgICAgICAgICAgKTsKICAgICAgICAgIH0sIGxkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19EYXRhVHlwZV9EVF9GTE9BVDY0ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAobGQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0RhdGFUeXBlX0RUX0ZMT0FUNjQgPSBhMy5hc20uS2IpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBtZCA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fRGF0YVR5cGVfRFRfQk9PTCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKG1kID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19EYXRhVHlwZV9EVF9CT09MID0gYTMuYXNtLkxiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgbmQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0RhdGFUeXBlX0RUX1RZUEVTX0NPVU5UID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAobmQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX0RhdGFUeXBlX0RUX1RZUEVTX0NPVU5UID0gYTMuYXNtLk1iKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgb2QgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX1N0YXR1c0NvZGVfT0sgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChvZCA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fU3RhdHVzQ29kZV9PSyA9IGEzLmFzbS5OYikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIHBkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19TdGF0dXNDb2RlX0RSQUNPX0VSUk9SID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAocGQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX1N0YXR1c0NvZGVfRFJBQ09fRVJST1IgPSBhMy5hc20uT2IpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9LCBxZCA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fU3RhdHVzQ29kZV9JT19FUlJPUiA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKHFkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19TdGF0dXNDb2RlX0lPX0VSUk9SID0gYTMuYXNtLlBiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgcmQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX1N0YXR1c0NvZGVfSU5WQUxJRF9QQVJBTUVURVIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChyZCA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fU3RhdHVzQ29kZV9JTlZBTElEX1BBUkFNRVRFUiA9IGEzLmFzbS5RYikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH0sIHNkID0gYTMuX2Vtc2NyaXB0ZW5fZW51bV9kcmFjb19TdGF0dXNDb2RlX1VOU1VQUE9SVEVEX1ZFUlNJT04gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChzZCA9IGEzLl9lbXNjcmlwdGVuX2VudW1fZHJhY29fU3RhdHVzQ29kZV9VTlNVUFBPUlRFRF9WRVJTSU9OID0gYTMuYXNtLlJiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfSwgdGQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX1N0YXR1c0NvZGVfVU5LTk9XTl9WRVJTSU9OID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAodGQgPSBhMy5fZW1zY3JpcHRlbl9lbnVtX2RyYWNvX1N0YXR1c0NvZGVfVU5LTk9XTl9WRVJTSU9OID0gYTMuYXNtLlNiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfTsKICAgICAgICAgIGEzLl9tYWxsb2MgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChhMy5fbWFsbG9jID0gYTMuYXNtLlRiKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfTsKICAgICAgICAgIGEzLl9mcmVlID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoYTMuX2ZyZWUgPSBhMy5hc20uVWIpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIHlhID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoeWEgPSBhMy5hc20uVmIpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9OwogICAgICAgICAgYTMuX19fc3RhcnRfZW1fanMgPSAxNTg1NjsKICAgICAgICAgIGEzLl9fX3N0b3BfZW1fanMgPSAxNTk1NDsKICAgICAgICAgIHZhciBsYTsKICAgICAgICAgIGlhID0gZnVuY3Rpb24gYigpIHsKICAgICAgICAgICAgbGEgfHwgYmEoKTsKICAgICAgICAgICAgbGEgfHwgKGlhID0gYik7CiAgICAgICAgICB9OwogICAgICAgICAgaWYgKGEzLnByZUluaXQpIGZvciAoImZ1bmN0aW9uIiA9PSB0eXBlb2YgYTMucHJlSW5pdCAmJiAoYTMucHJlSW5pdCA9IFthMy5wcmVJbml0XSk7IDAgPCBhMy5wcmVJbml0Lmxlbmd0aDsgKSBhMy5wcmVJbml0LnBvcCgpKCk7CiAgICAgICAgICBiYSgpOwogICAgICAgICAgdC5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHQucHJvdG90eXBlKTsKICAgICAgICAgIHQucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gdDsKICAgICAgICAgIHQucHJvdG90eXBlLl9fY2xhc3NfXyA9IHQ7CiAgICAgICAgICB0Ll9fY2FjaGVfXyA9IHt9OwogICAgICAgICAgYTMuV3JhcHBlck9iamVjdCA9IHQ7CiAgICAgICAgICBhMy5nZXRDYWNoZSA9IHg7CiAgICAgICAgICBhMy53cmFwUG9pbnRlciA9IEQ7CiAgICAgICAgICBhMy5jYXN0T2JqZWN0ID0gZnVuY3Rpb24oYiwgYykgewogICAgICAgICAgICByZXR1cm4gRChiLnB0ciwgYyk7CiAgICAgICAgICB9OwogICAgICAgICAgYTMuTlVMTCA9IEQoMCk7CiAgICAgICAgICBhMy5kZXN0cm95ID0gZnVuY3Rpb24oYikgewogICAgICAgICAgICBpZiAoIWIuX19kZXN0cm95X18pIHRocm93ICJFcnJvcjogQ2Fubm90IGRlc3Ryb3kgb2JqZWN0LiAoRGlkIHlvdSBjcmVhdGUgaXQgeW91cnNlbGY/KSI7CiAgICAgICAgICAgIGIuX19kZXN0cm95X18oKTsKICAgICAgICAgICAgZGVsZXRlIHgoYi5fX2NsYXNzX18pW2IucHRyXTsKICAgICAgICAgIH07CiAgICAgICAgICBhMy5jb21wYXJlID0gZnVuY3Rpb24oYiwgYykgewogICAgICAgICAgICByZXR1cm4gYi5wdHIgPT09IGMucHRyOwogICAgICAgICAgfTsKICAgICAgICAgIGEzLmdldFBvaW50ZXIgPSBmdW5jdGlvbihiKSB7CiAgICAgICAgICAgIHJldHVybiBiLnB0cjsKICAgICAgICAgIH07CiAgICAgICAgICBhMy5nZXRDbGFzcyA9IGZ1bmN0aW9uKGIpIHsKICAgICAgICAgICAgcmV0dXJuIGIuX19jbGFzc19fOwogICAgICAgICAgfTsKICAgICAgICAgIHZhciByID0geyBidWZmZXI6IDAsIHNpemU6IDAsIHBvczogMCwgdGVtcHM6IFtdLCBuZWVkZWQ6IDAsIHByZXBhcmU6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBpZiAoci5uZWVkZWQpIHsKICAgICAgICAgICAgICBmb3IgKHZhciBiID0gMDsgYiA8IHIudGVtcHMubGVuZ3RoOyBiKyspIGEzLl9mcmVlKHIudGVtcHNbYl0pOwogICAgICAgICAgICAgIHIudGVtcHMubGVuZ3RoID0gMDsKICAgICAgICAgICAgICBhMy5fZnJlZShyLmJ1ZmZlcik7CiAgICAgICAgICAgICAgci5idWZmZXIgPSAwOwogICAgICAgICAgICAgIHIuc2l6ZSArPSByLm5lZWRlZDsKICAgICAgICAgICAgICByLm5lZWRlZCA9IDA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgci5idWZmZXIgfHwgKHIuc2l6ZSArPSAxMjgsIHIuYnVmZmVyID0gYTMuX21hbGxvYyhyLnNpemUpLCByLmJ1ZmZlciB8fCBmKHZvaWQgMCkpOwogICAgICAgICAgICByLnBvcyA9IDA7CiAgICAgICAgICB9LCBhbGxvYzogZnVuY3Rpb24oYiwgYykgewogICAgICAgICAgICByLmJ1ZmZlciB8fCBmKHZvaWQgMCk7CiAgICAgICAgICAgIGIgPSBiLmxlbmd0aCAqIGMuQllURVNfUEVSX0VMRU1FTlQ7CiAgICAgICAgICAgIGIgPSBiICsgNyAmIC04OwogICAgICAgICAgICByLnBvcyArIGIgPj0gci5zaXplID8gKDAgPCBiIHx8IGYodm9pZCAwKSwgci5uZWVkZWQgKz0gYiwgYyA9IGEzLl9tYWxsb2MoYiksIHIudGVtcHMucHVzaChjKSkgOiAoYyA9IHIuYnVmZmVyICsgci5wb3MsIHIucG9zICs9IGIpOwogICAgICAgICAgICByZXR1cm4gYzsKICAgICAgICAgIH0sIGNvcHk6IGZ1bmN0aW9uKGIsIGMsIGQpIHsKICAgICAgICAgICAgZCA+Pj49IDA7CiAgICAgICAgICAgIHN3aXRjaCAoYy5CWVRFU19QRVJfRUxFTUVOVCkgewogICAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgICAgIGQgPj4+PSAxOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICAgICAgZCA+Pj49IDI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgICAgICBkID4+Pj0gMzsKICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IgKHZhciBnID0gMDsgZyA8IGIubGVuZ3RoOyBnKyspIGNbZCArIGddID0gYltnXTsKICAgICAgICAgIH0gfTsKICAgICAgICAgIFoucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSh0LnByb3RvdHlwZSk7CiAgICAgICAgICBaLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IFo7CiAgICAgICAgICBaLnByb3RvdHlwZS5fX2NsYXNzX18gPSBaOwogICAgICAgICAgWi5fX2NhY2hlX18gPSB7fTsKICAgICAgICAgIGEzLlZvaWRQdHIgPSBaOwogICAgICAgICAgWi5wcm90b3R5cGUuX19kZXN0cm95X18gPSBaLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBiYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgUy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHQucHJvdG90eXBlKTsKICAgICAgICAgIFMucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gUzsKICAgICAgICAgIFMucHJvdG90eXBlLl9fY2xhc3NfXyA9IFM7CiAgICAgICAgICBTLl9fY2FjaGVfXyA9IHt9OwogICAgICAgICAgYTMuRGVjb2RlckJ1ZmZlciA9IFM7CiAgICAgICAgICBTLnByb3RvdHlwZS5Jbml0ID0gUy5wcm90b3R5cGUuSW5pdCA9IGZ1bmN0aW9uKGIsIGMpIHsKICAgICAgICAgICAgdmFyIGQgPSB0aGlzLnB0cjsKICAgICAgICAgICAgci5wcmVwYXJlKCk7CiAgICAgICAgICAgICJvYmplY3QiID09IHR5cGVvZiBiICYmIChiID0gcGEoYikpOwogICAgICAgICAgICBjICYmICJvYmplY3QiID09PSB0eXBlb2YgYyAmJiAoYyA9IGMucHRyKTsKICAgICAgICAgICAgY2IoZCwgYiwgYyk7CiAgICAgICAgICB9OwogICAgICAgICAgUy5wcm90b3R5cGUuX19kZXN0cm95X18gPSBTLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBkYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgUS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHQucHJvdG90eXBlKTsKICAgICAgICAgIFEucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gUTsKICAgICAgICAgIFEucHJvdG90eXBlLl9fY2xhc3NfXyA9IFE7CiAgICAgICAgICBRLl9fY2FjaGVfXyA9IHt9OwogICAgICAgICAgYTMuQXR0cmlidXRlVHJhbnNmb3JtRGF0YSA9IFE7CiAgICAgICAgICBRLnByb3RvdHlwZS50cmFuc2Zvcm1fdHlwZSA9IFEucHJvdG90eXBlLnRyYW5zZm9ybV90eXBlID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBlYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgUS5wcm90b3R5cGUuX19kZXN0cm95X18gPSBRLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBmYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgVy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHQucHJvdG90eXBlKTsKICAgICAgICAgIFcucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gVzsKICAgICAgICAgIFcucHJvdG90eXBlLl9fY2xhc3NfXyA9IFc7CiAgICAgICAgICBXLl9fY2FjaGVfXyA9IHt9OwogICAgICAgICAgYTMuR2VvbWV0cnlBdHRyaWJ1dGUgPSBXOwogICAgICAgICAgVy5wcm90b3R5cGUuX19kZXN0cm95X18gPSBXLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBnYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgdy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHQucHJvdG90eXBlKTsKICAgICAgICAgIHcucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gdzsKICAgICAgICAgIHcucHJvdG90eXBlLl9fY2xhc3NfXyA9IHc7CiAgICAgICAgICB3Ll9fY2FjaGVfXyA9IHt9OwogICAgICAgICAgYTMuUG9pbnRBdHRyaWJ1dGUgPSB3OwogICAgICAgICAgdy5wcm90b3R5cGUuc2l6ZSA9IHcucHJvdG90eXBlLnNpemUgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIGhiKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICB3LnByb3RvdHlwZS5HZXRBdHRyaWJ1dGVUcmFuc2Zvcm1EYXRhID0gdy5wcm90b3R5cGUuR2V0QXR0cmlidXRlVHJhbnNmb3JtRGF0YSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gRChpYih0aGlzLnB0ciksIFEpOwogICAgICAgICAgfTsKICAgICAgICAgIHcucHJvdG90eXBlLmF0dHJpYnV0ZV90eXBlID0gdy5wcm90b3R5cGUuYXR0cmlidXRlX3R5cGUgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIGpiKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICB3LnByb3RvdHlwZS5kYXRhX3R5cGUgPSB3LnByb3RvdHlwZS5kYXRhX3R5cGUgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIGtiKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICB3LnByb3RvdHlwZS5udW1fY29tcG9uZW50cyA9IHcucHJvdG90eXBlLm51bV9jb21wb25lbnRzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBsYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgdy5wcm90b3R5cGUubm9ybWFsaXplZCA9IHcucHJvdG90eXBlLm5vcm1hbGl6ZWQgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuICEhbWIodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIHcucHJvdG90eXBlLmJ5dGVfc3RyaWRlID0gdy5wcm90b3R5cGUuYnl0ZV9zdHJpZGUgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIG5iKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICB3LnByb3RvdHlwZS5ieXRlX29mZnNldCA9IHcucHJvdG90eXBlLmJ5dGVfb2Zmc2V0ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBvYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgdy5wcm90b3R5cGUudW5pcXVlX2lkID0gdy5wcm90b3R5cGUudW5pcXVlX2lkID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBwYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgdy5wcm90b3R5cGUuX19kZXN0cm95X18gPSB3LnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBxYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgQy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHQucHJvdG90eXBlKTsKICAgICAgICAgIEMucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gQzsKICAgICAgICAgIEMucHJvdG90eXBlLl9fY2xhc3NfXyA9IEM7CiAgICAgICAgICBDLl9fY2FjaGVfXyA9IHt9OwogICAgICAgICAgYTMuQXR0cmlidXRlUXVhbnRpemF0aW9uVHJhbnNmb3JtID0gQzsKICAgICAgICAgIEMucHJvdG90eXBlLkluaXRGcm9tQXR0cmlidXRlID0gQy5wcm90b3R5cGUuSW5pdEZyb21BdHRyaWJ1dGUgPSBmdW5jdGlvbihiKSB7CiAgICAgICAgICAgIHZhciBjID0gdGhpcy5wdHI7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICByZXR1cm4gISFyYihjLCBiKTsKICAgICAgICAgIH07CiAgICAgICAgICBDLnByb3RvdHlwZS5xdWFudGl6YXRpb25fYml0cyA9IEMucHJvdG90eXBlLnF1YW50aXphdGlvbl9iaXRzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBzYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgQy5wcm90b3R5cGUubWluX3ZhbHVlID0gQy5wcm90b3R5cGUubWluX3ZhbHVlID0gZnVuY3Rpb24oYikgewogICAgICAgICAgICB2YXIgYyA9IHRoaXMucHRyOwogICAgICAgICAgICBiICYmICJvYmplY3QiID09PSB0eXBlb2YgYiAmJiAoYiA9IGIucHRyKTsKICAgICAgICAgICAgcmV0dXJuIHRiKGMsIGIpOwogICAgICAgICAgfTsKICAgICAgICAgIEMucHJvdG90eXBlLnJhbmdlID0gQy5wcm90b3R5cGUucmFuZ2UgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIHViKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICBDLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IEMucHJvdG90eXBlLl9fZGVzdHJveV9fID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHZiKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICBGLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUodC5wcm90b3R5cGUpOwogICAgICAgICAgRi5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBGOwogICAgICAgICAgRi5wcm90b3R5cGUuX19jbGFzc19fID0gRjsKICAgICAgICAgIEYuX19jYWNoZV9fID0ge307CiAgICAgICAgICBhMy5BdHRyaWJ1dGVPY3RhaGVkcm9uVHJhbnNmb3JtID0gRjsKICAgICAgICAgIEYucHJvdG90eXBlLkluaXRGcm9tQXR0cmlidXRlID0gRi5wcm90b3R5cGUuSW5pdEZyb21BdHRyaWJ1dGUgPSBmdW5jdGlvbihiKSB7CiAgICAgICAgICAgIHZhciBjID0gdGhpcy5wdHI7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICByZXR1cm4gISF3YihjLCBiKTsKICAgICAgICAgIH07CiAgICAgICAgICBGLnByb3RvdHlwZS5xdWFudGl6YXRpb25fYml0cyA9IEYucHJvdG90eXBlLnF1YW50aXphdGlvbl9iaXRzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB4Yih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgRi5wcm90b3R5cGUuX19kZXN0cm95X18gPSBGLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICB5Yih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgRy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHQucHJvdG90eXBlKTsKICAgICAgICAgIEcucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gRzsKICAgICAgICAgIEcucHJvdG90eXBlLl9fY2xhc3NfXyA9IEc7CiAgICAgICAgICBHLl9fY2FjaGVfXyA9IHt9OwogICAgICAgICAgYTMuUG9pbnRDbG91ZCA9IEc7CiAgICAgICAgICBHLnByb3RvdHlwZS5udW1fYXR0cmlidXRlcyA9IEcucHJvdG90eXBlLm51bV9hdHRyaWJ1dGVzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiB6Yih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgRy5wcm90b3R5cGUubnVtX3BvaW50cyA9IEcucHJvdG90eXBlLm51bV9wb2ludHMgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIEFiKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICBHLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IEcucHJvdG90eXBlLl9fZGVzdHJveV9fID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIEJiKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICBFLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUodC5wcm90b3R5cGUpOwogICAgICAgICAgRS5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBFOwogICAgICAgICAgRS5wcm90b3R5cGUuX19jbGFzc19fID0gRTsKICAgICAgICAgIEUuX19jYWNoZV9fID0ge307CiAgICAgICAgICBhMy5NZXNoID0gRTsKICAgICAgICAgIEUucHJvdG90eXBlLm51bV9mYWNlcyA9IEUucHJvdG90eXBlLm51bV9mYWNlcyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gQ2IodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIEUucHJvdG90eXBlLm51bV9hdHRyaWJ1dGVzID0gRS5wcm90b3R5cGUubnVtX2F0dHJpYnV0ZXMgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIERiKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICBFLnByb3RvdHlwZS5udW1fcG9pbnRzID0gRS5wcm90b3R5cGUubnVtX3BvaW50cyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gRWIodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIEUucHJvdG90eXBlLl9fZGVzdHJveV9fID0gRS5wcm90b3R5cGUuX19kZXN0cm95X18gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgRmIodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIFQucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSh0LnByb3RvdHlwZSk7CiAgICAgICAgICBULnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IFQ7CiAgICAgICAgICBULnByb3RvdHlwZS5fX2NsYXNzX18gPSBUOwogICAgICAgICAgVC5fX2NhY2hlX18gPSB7fTsKICAgICAgICAgIGEzLk1ldGFkYXRhID0gVDsKICAgICAgICAgIFQucHJvdG90eXBlLl9fZGVzdHJveV9fID0gVC5wcm90b3R5cGUuX19kZXN0cm95X18gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgR2IodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIEIucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSh0LnByb3RvdHlwZSk7CiAgICAgICAgICBCLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEI7CiAgICAgICAgICBCLnByb3RvdHlwZS5fX2NsYXNzX18gPSBCOwogICAgICAgICAgQi5fX2NhY2hlX18gPSB7fTsKICAgICAgICAgIGEzLlN0YXR1cyA9IEI7CiAgICAgICAgICBCLnByb3RvdHlwZS5jb2RlID0gQi5wcm90b3R5cGUuY29kZSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gSGIodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIEIucHJvdG90eXBlLm9rID0gQi5wcm90b3R5cGUub2sgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuICEhSWIodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIEIucHJvdG90eXBlLmVycm9yX21zZyA9IEIucHJvdG90eXBlLmVycm9yX21zZyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gaChKYih0aGlzLnB0cikpOwogICAgICAgICAgfTsKICAgICAgICAgIEIucHJvdG90eXBlLl9fZGVzdHJveV9fID0gQi5wcm90b3R5cGUuX19kZXN0cm95X18gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgS2IodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIEgucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSh0LnByb3RvdHlwZSk7CiAgICAgICAgICBILnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEg7CiAgICAgICAgICBILnByb3RvdHlwZS5fX2NsYXNzX18gPSBIOwogICAgICAgICAgSC5fX2NhY2hlX18gPSB7fTsKICAgICAgICAgIGEzLkRyYWNvRmxvYXQzMkFycmF5ID0gSDsKICAgICAgICAgIEgucHJvdG90eXBlLkdldFZhbHVlID0gSC5wcm90b3R5cGUuR2V0VmFsdWUgPSBmdW5jdGlvbihiKSB7CiAgICAgICAgICAgIHZhciBjID0gdGhpcy5wdHI7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICByZXR1cm4gTGIoYywgYik7CiAgICAgICAgICB9OwogICAgICAgICAgSC5wcm90b3R5cGUuc2l6ZSA9IEgucHJvdG90eXBlLnNpemUgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIE1iKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICBILnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IEgucHJvdG90eXBlLl9fZGVzdHJveV9fID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIE5iKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICBJLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUodC5wcm90b3R5cGUpOwogICAgICAgICAgSS5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBJOwogICAgICAgICAgSS5wcm90b3R5cGUuX19jbGFzc19fID0gSTsKICAgICAgICAgIEkuX19jYWNoZV9fID0ge307CiAgICAgICAgICBhMy5EcmFjb0ludDhBcnJheSA9IEk7CiAgICAgICAgICBJLnByb3RvdHlwZS5HZXRWYWx1ZSA9IEkucHJvdG90eXBlLkdldFZhbHVlID0gZnVuY3Rpb24oYikgewogICAgICAgICAgICB2YXIgYyA9IHRoaXMucHRyOwogICAgICAgICAgICBiICYmICJvYmplY3QiID09PSB0eXBlb2YgYiAmJiAoYiA9IGIucHRyKTsKICAgICAgICAgICAgcmV0dXJuIE9iKGMsIGIpOwogICAgICAgICAgfTsKICAgICAgICAgIEkucHJvdG90eXBlLnNpemUgPSBJLnByb3RvdHlwZS5zaXplID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBQYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgSS5wcm90b3R5cGUuX19kZXN0cm95X18gPSBJLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBRYih0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgSi5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHQucHJvdG90eXBlKTsKICAgICAgICAgIEoucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gSjsKICAgICAgICAgIEoucHJvdG90eXBlLl9fY2xhc3NfXyA9IEo7CiAgICAgICAgICBKLl9fY2FjaGVfXyA9IHt9OwogICAgICAgICAgYTMuRHJhY29VSW50OEFycmF5ID0gSjsKICAgICAgICAgIEoucHJvdG90eXBlLkdldFZhbHVlID0gSi5wcm90b3R5cGUuR2V0VmFsdWUgPSBmdW5jdGlvbihiKSB7CiAgICAgICAgICAgIHZhciBjID0gdGhpcy5wdHI7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICByZXR1cm4gUmIoYywgYik7CiAgICAgICAgICB9OwogICAgICAgICAgSi5wcm90b3R5cGUuc2l6ZSA9IEoucHJvdG90eXBlLnNpemUgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIFNiKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICBKLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IEoucHJvdG90eXBlLl9fZGVzdHJveV9fID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIFRiKHRoaXMucHRyKTsKICAgICAgICAgIH07CiAgICAgICAgICBLLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUodC5wcm90b3R5cGUpOwogICAgICAgICAgSy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBLOwogICAgICAgICAgSy5wcm90b3R5cGUuX19jbGFzc19fID0gSzsKICAgICAgICAgIEsuX19jYWNoZV9fID0ge307CiAgICAgICAgICBhMy5EcmFjb0ludDE2QXJyYXkgPSBLOwogICAgICAgICAgSy5wcm90b3R5cGUuR2V0VmFsdWUgPSBLLnByb3RvdHlwZS5HZXRWYWx1ZSA9IGZ1bmN0aW9uKGIpIHsKICAgICAgICAgICAgdmFyIGMgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIHJldHVybiBVYihjLCBiKTsKICAgICAgICAgIH07CiAgICAgICAgICBLLnByb3RvdHlwZS5zaXplID0gSy5wcm90b3R5cGUuc2l6ZSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gVmIodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIEsucHJvdG90eXBlLl9fZGVzdHJveV9fID0gSy5wcm90b3R5cGUuX19kZXN0cm95X18gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgV2IodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIEwucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSh0LnByb3RvdHlwZSk7CiAgICAgICAgICBMLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEw7CiAgICAgICAgICBMLnByb3RvdHlwZS5fX2NsYXNzX18gPSBMOwogICAgICAgICAgTC5fX2NhY2hlX18gPSB7fTsKICAgICAgICAgIGEzLkRyYWNvVUludDE2QXJyYXkgPSBMOwogICAgICAgICAgTC5wcm90b3R5cGUuR2V0VmFsdWUgPSBMLnByb3RvdHlwZS5HZXRWYWx1ZSA9IGZ1bmN0aW9uKGIpIHsKICAgICAgICAgICAgdmFyIGMgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIHJldHVybiBYYihjLCBiKTsKICAgICAgICAgIH07CiAgICAgICAgICBMLnByb3RvdHlwZS5zaXplID0gTC5wcm90b3R5cGUuc2l6ZSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gWWIodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIEwucHJvdG90eXBlLl9fZGVzdHJveV9fID0gTC5wcm90b3R5cGUuX19kZXN0cm95X18gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgWmIodGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIE0ucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSh0LnByb3RvdHlwZSk7CiAgICAgICAgICBNLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE07CiAgICAgICAgICBNLnByb3RvdHlwZS5fX2NsYXNzX18gPSBNOwogICAgICAgICAgTS5fX2NhY2hlX18gPSB7fTsKICAgICAgICAgIGEzLkRyYWNvSW50MzJBcnJheSA9IE07CiAgICAgICAgICBNLnByb3RvdHlwZS5HZXRWYWx1ZSA9IE0ucHJvdG90eXBlLkdldFZhbHVlID0gZnVuY3Rpb24oYikgewogICAgICAgICAgICB2YXIgYyA9IHRoaXMucHRyOwogICAgICAgICAgICBiICYmICJvYmplY3QiID09PSB0eXBlb2YgYiAmJiAoYiA9IGIucHRyKTsKICAgICAgICAgICAgcmV0dXJuICRiKGMsIGIpOwogICAgICAgICAgfTsKICAgICAgICAgIE0ucHJvdG90eXBlLnNpemUgPSBNLnByb3RvdHlwZS5zaXplID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBhYyh0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgTS5wcm90b3R5cGUuX19kZXN0cm95X18gPSBNLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBiYyh0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgTi5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHQucHJvdG90eXBlKTsKICAgICAgICAgIE4ucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gTjsKICAgICAgICAgIE4ucHJvdG90eXBlLl9fY2xhc3NfXyA9IE47CiAgICAgICAgICBOLl9fY2FjaGVfXyA9IHt9OwogICAgICAgICAgYTMuRHJhY29VSW50MzJBcnJheSA9IE47CiAgICAgICAgICBOLnByb3RvdHlwZS5HZXRWYWx1ZSA9IE4ucHJvdG90eXBlLkdldFZhbHVlID0gZnVuY3Rpb24oYikgewogICAgICAgICAgICB2YXIgYyA9IHRoaXMucHRyOwogICAgICAgICAgICBiICYmICJvYmplY3QiID09PSB0eXBlb2YgYiAmJiAoYiA9IGIucHRyKTsKICAgICAgICAgICAgcmV0dXJuIGNjKGMsIGIpOwogICAgICAgICAgfTsKICAgICAgICAgIE4ucHJvdG90eXBlLnNpemUgPSBOLnByb3RvdHlwZS5zaXplID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiBkYyh0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgTi5wcm90b3R5cGUuX19kZXN0cm95X18gPSBOLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBlYyh0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgeS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHQucHJvdG90eXBlKTsKICAgICAgICAgIHkucHJvdG90eXBlLmNvbnN0cnVjdG9yID0geTsKICAgICAgICAgIHkucHJvdG90eXBlLl9fY2xhc3NfXyA9IHk7CiAgICAgICAgICB5Ll9fY2FjaGVfXyA9IHt9OwogICAgICAgICAgYTMuTWV0YWRhdGFRdWVyaWVyID0geTsKICAgICAgICAgIHkucHJvdG90eXBlLkhhc0VudHJ5ID0geS5wcm90b3R5cGUuSGFzRW50cnkgPSBmdW5jdGlvbihiLCBjKSB7CiAgICAgICAgICAgIHZhciBkID0gdGhpcy5wdHI7CiAgICAgICAgICAgIHIucHJlcGFyZSgpOwogICAgICAgICAgICBiICYmICJvYmplY3QiID09PSB0eXBlb2YgYiAmJiAoYiA9IGIucHRyKTsKICAgICAgICAgICAgYyA9IGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjID8gYy5wdHIgOiBSKGMpOwogICAgICAgICAgICByZXR1cm4gISFmYyhkLCBiLCBjKTsKICAgICAgICAgIH07CiAgICAgICAgICB5LnByb3RvdHlwZS5HZXRJbnRFbnRyeSA9IHkucHJvdG90eXBlLkdldEludEVudHJ5ID0gZnVuY3Rpb24oYiwgYykgewogICAgICAgICAgICB2YXIgZCA9IHRoaXMucHRyOwogICAgICAgICAgICByLnByZXBhcmUoKTsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgPSBjICYmICJvYmplY3QiID09PSB0eXBlb2YgYyA/IGMucHRyIDogUihjKTsKICAgICAgICAgICAgcmV0dXJuIGdjKGQsIGIsIGMpOwogICAgICAgICAgfTsKICAgICAgICAgIHkucHJvdG90eXBlLkdldEludEVudHJ5QXJyYXkgPSB5LnByb3RvdHlwZS5HZXRJbnRFbnRyeUFycmF5ID0gZnVuY3Rpb24oYiwgYywgZCkgewogICAgICAgICAgICB2YXIgZyA9IHRoaXMucHRyOwogICAgICAgICAgICByLnByZXBhcmUoKTsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgPSBjICYmICJvYmplY3QiID09PSB0eXBlb2YgYyA/IGMucHRyIDogUihjKTsKICAgICAgICAgICAgZCAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGQgJiYgKGQgPSBkLnB0cik7CiAgICAgICAgICAgIGhjKGcsIGIsIGMsIGQpOwogICAgICAgICAgfTsKICAgICAgICAgIHkucHJvdG90eXBlLkdldERvdWJsZUVudHJ5ID0geS5wcm90b3R5cGUuR2V0RG91YmxlRW50cnkgPSBmdW5jdGlvbihiLCBjKSB7CiAgICAgICAgICAgIHZhciBkID0gdGhpcy5wdHI7CiAgICAgICAgICAgIHIucHJlcGFyZSgpOwogICAgICAgICAgICBiICYmICJvYmplY3QiID09PSB0eXBlb2YgYiAmJiAoYiA9IGIucHRyKTsKICAgICAgICAgICAgYyA9IGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjID8gYy5wdHIgOiBSKGMpOwogICAgICAgICAgICByZXR1cm4gaWMoZCwgYiwgYyk7CiAgICAgICAgICB9OwogICAgICAgICAgeS5wcm90b3R5cGUuR2V0U3RyaW5nRW50cnkgPSB5LnByb3RvdHlwZS5HZXRTdHJpbmdFbnRyeSA9IGZ1bmN0aW9uKGIsIGMpIHsKICAgICAgICAgICAgdmFyIGQgPSB0aGlzLnB0cjsKICAgICAgICAgICAgci5wcmVwYXJlKCk7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICBjID0gYyAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGMgPyBjLnB0ciA6IFIoYyk7CiAgICAgICAgICAgIHJldHVybiBoKGpjKGQsIGIsIGMpKTsKICAgICAgICAgIH07CiAgICAgICAgICB5LnByb3RvdHlwZS5OdW1FbnRyaWVzID0geS5wcm90b3R5cGUuTnVtRW50cmllcyA9IGZ1bmN0aW9uKGIpIHsKICAgICAgICAgICAgdmFyIGMgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIHJldHVybiBrYyhjLCBiKTsKICAgICAgICAgIH07CiAgICAgICAgICB5LnByb3RvdHlwZS5HZXRFbnRyeU5hbWUgPSB5LnByb3RvdHlwZS5HZXRFbnRyeU5hbWUgPSBmdW5jdGlvbihiLCBjKSB7CiAgICAgICAgICAgIHZhciBkID0gdGhpcy5wdHI7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICBjICYmICJvYmplY3QiID09PSB0eXBlb2YgYyAmJiAoYyA9IGMucHRyKTsKICAgICAgICAgICAgcmV0dXJuIGgobGMoZCwgYiwgYykpOwogICAgICAgICAgfTsKICAgICAgICAgIHkucHJvdG90eXBlLl9fZGVzdHJveV9fID0geS5wcm90b3R5cGUuX19kZXN0cm95X18gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgbWModGhpcy5wdHIpOwogICAgICAgICAgfTsKICAgICAgICAgIG0ucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSh0LnByb3RvdHlwZSk7CiAgICAgICAgICBtLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IG07CiAgICAgICAgICBtLnByb3RvdHlwZS5fX2NsYXNzX18gPSBtOwogICAgICAgICAgbS5fX2NhY2hlX18gPSB7fTsKICAgICAgICAgIGEzLkRlY29kZXIgPSBtOwogICAgICAgICAgbS5wcm90b3R5cGUuRGVjb2RlQXJyYXlUb1BvaW50Q2xvdWQgPSBtLnByb3RvdHlwZS5EZWNvZGVBcnJheVRvUG9pbnRDbG91ZCA9IGZ1bmN0aW9uKGIsIGMsIGQpIHsKICAgICAgICAgICAgdmFyIGcgPSB0aGlzLnB0cjsKICAgICAgICAgICAgci5wcmVwYXJlKCk7CiAgICAgICAgICAgICJvYmplY3QiID09IHR5cGVvZiBiICYmIChiID0gcGEoYikpOwogICAgICAgICAgICBjICYmICJvYmplY3QiID09PSB0eXBlb2YgYyAmJiAoYyA9IGMucHRyKTsKICAgICAgICAgICAgZCAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGQgJiYgKGQgPSBkLnB0cik7CiAgICAgICAgICAgIHJldHVybiBEKG5jKGcsIGIsIGMsIGQpLCBCKTsKICAgICAgICAgIH07CiAgICAgICAgICBtLnByb3RvdHlwZS5EZWNvZGVBcnJheVRvTWVzaCA9IG0ucHJvdG90eXBlLkRlY29kZUFycmF5VG9NZXNoID0gZnVuY3Rpb24oYiwgYywgZCkgewogICAgICAgICAgICB2YXIgZyA9IHRoaXMucHRyOwogICAgICAgICAgICByLnByZXBhcmUoKTsKICAgICAgICAgICAgIm9iamVjdCIgPT0gdHlwZW9mIGIgJiYgKGIgPSBwYShiKSk7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICBkICYmICJvYmplY3QiID09PSB0eXBlb2YgZCAmJiAoZCA9IGQucHRyKTsKICAgICAgICAgICAgcmV0dXJuIEQob2MoZywgYiwgYywgZCksIEIpOwogICAgICAgICAgfTsKICAgICAgICAgIG0ucHJvdG90eXBlLkdldEF0dHJpYnV0ZUlkID0gbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlSWQgPSBmdW5jdGlvbihiLCBjKSB7CiAgICAgICAgICAgIHZhciBkID0gdGhpcy5wdHI7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICBjICYmICJvYmplY3QiID09PSB0eXBlb2YgYyAmJiAoYyA9IGMucHRyKTsKICAgICAgICAgICAgcmV0dXJuIHBjKGQsIGIsIGMpOwogICAgICAgICAgfTsKICAgICAgICAgIG0ucHJvdG90eXBlLkdldEF0dHJpYnV0ZUlkQnlOYW1lID0gbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlSWRCeU5hbWUgPSBmdW5jdGlvbihiLCBjKSB7CiAgICAgICAgICAgIHZhciBkID0gdGhpcy5wdHI7CiAgICAgICAgICAgIHIucHJlcGFyZSgpOwogICAgICAgICAgICBiICYmICJvYmplY3QiID09PSB0eXBlb2YgYiAmJiAoYiA9IGIucHRyKTsKICAgICAgICAgICAgYyA9IGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjID8gYy5wdHIgOiBSKGMpOwogICAgICAgICAgICByZXR1cm4gcWMoZCwgYiwgYyk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlSWRCeU1ldGFkYXRhRW50cnkgPSBtLnByb3RvdHlwZS5HZXRBdHRyaWJ1dGVJZEJ5TWV0YWRhdGFFbnRyeSA9IGZ1bmN0aW9uKGIsIGMsIGQpIHsKICAgICAgICAgICAgdmFyIGcgPSB0aGlzLnB0cjsKICAgICAgICAgICAgci5wcmVwYXJlKCk7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICBjID0gYyAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGMgPyBjLnB0ciA6IFIoYyk7CiAgICAgICAgICAgIGQgPSBkICYmICJvYmplY3QiID09PSB0eXBlb2YgZCA/IGQucHRyIDogUihkKTsKICAgICAgICAgICAgcmV0dXJuIHJjKGcsIGIsIGMsIGQpOwogICAgICAgICAgfTsKICAgICAgICAgIG0ucHJvdG90eXBlLkdldEF0dHJpYnV0ZSA9IG0ucHJvdG90eXBlLkdldEF0dHJpYnV0ZSA9IGZ1bmN0aW9uKGIsIGMpIHsKICAgICAgICAgICAgdmFyIGQgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICByZXR1cm4gRChzYyhkLCBiLCBjKSwgdyk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlQnlVbmlxdWVJZCA9IG0ucHJvdG90eXBlLkdldEF0dHJpYnV0ZUJ5VW5pcXVlSWQgPSBmdW5jdGlvbihiLCBjKSB7CiAgICAgICAgICAgIHZhciBkID0gdGhpcy5wdHI7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICBjICYmICJvYmplY3QiID09PSB0eXBlb2YgYyAmJiAoYyA9IGMucHRyKTsKICAgICAgICAgICAgcmV0dXJuIEQodGMoZCwgYiwgYyksIHcpOwogICAgICAgICAgfTsKICAgICAgICAgIG0ucHJvdG90eXBlLkdldE1ldGFkYXRhID0gbS5wcm90b3R5cGUuR2V0TWV0YWRhdGEgPSBmdW5jdGlvbihiKSB7CiAgICAgICAgICAgIHZhciBjID0gdGhpcy5wdHI7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICByZXR1cm4gRCh1YyhjLCBiKSwgVCk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlTWV0YWRhdGEgPSBtLnByb3RvdHlwZS5HZXRBdHRyaWJ1dGVNZXRhZGF0YSA9IGZ1bmN0aW9uKGIsIGMpIHsKICAgICAgICAgICAgdmFyIGQgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICByZXR1cm4gRCh2YyhkLCBiLCBjKSwgVCk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0RmFjZUZyb21NZXNoID0gbS5wcm90b3R5cGUuR2V0RmFjZUZyb21NZXNoID0gZnVuY3Rpb24oYiwgYywgZCkgewogICAgICAgICAgICB2YXIgZyA9IHRoaXMucHRyOwogICAgICAgICAgICBiICYmICJvYmplY3QiID09PSB0eXBlb2YgYiAmJiAoYiA9IGIucHRyKTsKICAgICAgICAgICAgYyAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGMgJiYgKGMgPSBjLnB0cik7CiAgICAgICAgICAgIGQgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBkICYmIChkID0gZC5wdHIpOwogICAgICAgICAgICByZXR1cm4gISF3YyhnLCBiLCBjLCBkKTsKICAgICAgICAgIH07CiAgICAgICAgICBtLnByb3RvdHlwZS5HZXRUcmlhbmdsZVN0cmlwc0Zyb21NZXNoID0gbS5wcm90b3R5cGUuR2V0VHJpYW5nbGVTdHJpcHNGcm9tTWVzaCA9IGZ1bmN0aW9uKGIsIGMpIHsKICAgICAgICAgICAgdmFyIGQgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICByZXR1cm4geGMoZCwgYiwgYyk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0VHJpYW5nbGVzVUludDE2QXJyYXkgPSBtLnByb3RvdHlwZS5HZXRUcmlhbmdsZXNVSW50MTZBcnJheSA9IGZ1bmN0aW9uKGIsIGMsIGQpIHsKICAgICAgICAgICAgdmFyIGcgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICBkICYmICJvYmplY3QiID09PSB0eXBlb2YgZCAmJiAoZCA9IGQucHRyKTsKICAgICAgICAgICAgcmV0dXJuICEheWMoZywgYiwgYywgZCk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0VHJpYW5nbGVzVUludDMyQXJyYXkgPSBtLnByb3RvdHlwZS5HZXRUcmlhbmdsZXNVSW50MzJBcnJheSA9IGZ1bmN0aW9uKGIsIGMsIGQpIHsKICAgICAgICAgICAgdmFyIGcgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICBkICYmICJvYmplY3QiID09PSB0eXBlb2YgZCAmJiAoZCA9IGQucHRyKTsKICAgICAgICAgICAgcmV0dXJuICEhemMoZywgYiwgYywgZCk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlRmxvYXQgPSBtLnByb3RvdHlwZS5HZXRBdHRyaWJ1dGVGbG9hdCA9IGZ1bmN0aW9uKGIsIGMsIGQpIHsKICAgICAgICAgICAgdmFyIGcgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICBkICYmICJvYmplY3QiID09PSB0eXBlb2YgZCAmJiAoZCA9IGQucHRyKTsKICAgICAgICAgICAgcmV0dXJuICEhQWMoZywgYiwgYywgZCk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlRmxvYXRGb3JBbGxQb2ludHMgPSBtLnByb3RvdHlwZS5HZXRBdHRyaWJ1dGVGbG9hdEZvckFsbFBvaW50cyA9IGZ1bmN0aW9uKGIsIGMsIGQpIHsKICAgICAgICAgICAgdmFyIGcgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICBkICYmICJvYmplY3QiID09PSB0eXBlb2YgZCAmJiAoZCA9IGQucHRyKTsKICAgICAgICAgICAgcmV0dXJuICEhQmMoZywgYiwgYywgZCk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlSW50Rm9yQWxsUG9pbnRzID0gbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlSW50Rm9yQWxsUG9pbnRzID0gZnVuY3Rpb24oYiwgYywgZCkgewogICAgICAgICAgICB2YXIgZyA9IHRoaXMucHRyOwogICAgICAgICAgICBiICYmICJvYmplY3QiID09PSB0eXBlb2YgYiAmJiAoYiA9IGIucHRyKTsKICAgICAgICAgICAgYyAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGMgJiYgKGMgPSBjLnB0cik7CiAgICAgICAgICAgIGQgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBkICYmIChkID0gZC5wdHIpOwogICAgICAgICAgICByZXR1cm4gISFDYyhnLCBiLCBjLCBkKTsKICAgICAgICAgIH07CiAgICAgICAgICBtLnByb3RvdHlwZS5HZXRBdHRyaWJ1dGVJbnQ4Rm9yQWxsUG9pbnRzID0gbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlSW50OEZvckFsbFBvaW50cyA9IGZ1bmN0aW9uKGIsIGMsIGQpIHsKICAgICAgICAgICAgdmFyIGcgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICBkICYmICJvYmplY3QiID09PSB0eXBlb2YgZCAmJiAoZCA9IGQucHRyKTsKICAgICAgICAgICAgcmV0dXJuICEhRGMoZywgYiwgYywgZCk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlVUludDhGb3JBbGxQb2ludHMgPSBtLnByb3RvdHlwZS5HZXRBdHRyaWJ1dGVVSW50OEZvckFsbFBvaW50cyA9IGZ1bmN0aW9uKGIsIGMsIGQpIHsKICAgICAgICAgICAgdmFyIGcgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICBkICYmICJvYmplY3QiID09PSB0eXBlb2YgZCAmJiAoZCA9IGQucHRyKTsKICAgICAgICAgICAgcmV0dXJuICEhRWMoZywgYiwgYywgZCk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlSW50MTZGb3JBbGxQb2ludHMgPSBtLnByb3RvdHlwZS5HZXRBdHRyaWJ1dGVJbnQxNkZvckFsbFBvaW50cyA9IGZ1bmN0aW9uKGIsIGMsIGQpIHsKICAgICAgICAgICAgdmFyIGcgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICBkICYmICJvYmplY3QiID09PSB0eXBlb2YgZCAmJiAoZCA9IGQucHRyKTsKICAgICAgICAgICAgcmV0dXJuICEhRmMoZywgYiwgYywgZCk7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlVUludDE2Rm9yQWxsUG9pbnRzID0gbS5wcm90b3R5cGUuR2V0QXR0cmlidXRlVUludDE2Rm9yQWxsUG9pbnRzID0gZnVuY3Rpb24oYiwgYywgZCkgewogICAgICAgICAgICB2YXIgZyA9IHRoaXMucHRyOwogICAgICAgICAgICBiICYmICJvYmplY3QiID09PSB0eXBlb2YgYiAmJiAoYiA9IGIucHRyKTsKICAgICAgICAgICAgYyAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGMgJiYgKGMgPSBjLnB0cik7CiAgICAgICAgICAgIGQgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBkICYmIChkID0gZC5wdHIpOwogICAgICAgICAgICByZXR1cm4gISFHYyhnLCBiLCBjLCBkKTsKICAgICAgICAgIH07CiAgICAgICAgICBtLnByb3RvdHlwZS5HZXRBdHRyaWJ1dGVJbnQzMkZvckFsbFBvaW50cyA9IG0ucHJvdG90eXBlLkdldEF0dHJpYnV0ZUludDMyRm9yQWxsUG9pbnRzID0gZnVuY3Rpb24oYiwgYywgZCkgewogICAgICAgICAgICB2YXIgZyA9IHRoaXMucHRyOwogICAgICAgICAgICBiICYmICJvYmplY3QiID09PSB0eXBlb2YgYiAmJiAoYiA9IGIucHRyKTsKICAgICAgICAgICAgYyAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGMgJiYgKGMgPSBjLnB0cik7CiAgICAgICAgICAgIGQgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBkICYmIChkID0gZC5wdHIpOwogICAgICAgICAgICByZXR1cm4gISFIYyhnLCBiLCBjLCBkKTsKICAgICAgICAgIH07CiAgICAgICAgICBtLnByb3RvdHlwZS5HZXRBdHRyaWJ1dGVVSW50MzJGb3JBbGxQb2ludHMgPSBtLnByb3RvdHlwZS5HZXRBdHRyaWJ1dGVVSW50MzJGb3JBbGxQb2ludHMgPSBmdW5jdGlvbihiLCBjLCBkKSB7CiAgICAgICAgICAgIHZhciBnID0gdGhpcy5wdHI7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICBjICYmICJvYmplY3QiID09PSB0eXBlb2YgYyAmJiAoYyA9IGMucHRyKTsKICAgICAgICAgICAgZCAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGQgJiYgKGQgPSBkLnB0cik7CiAgICAgICAgICAgIHJldHVybiAhIUljKGcsIGIsIGMsIGQpOwogICAgICAgICAgfTsKICAgICAgICAgIG0ucHJvdG90eXBlLkdldEF0dHJpYnV0ZURhdGFBcnJheUZvckFsbFBvaW50cyA9IG0ucHJvdG90eXBlLkdldEF0dHJpYnV0ZURhdGFBcnJheUZvckFsbFBvaW50cyA9IGZ1bmN0aW9uKGIsIGMsIGQsIGcsIHUzKSB7CiAgICAgICAgICAgIHZhciBYID0gdGhpcy5wdHI7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICBjICYmICJvYmplY3QiID09PSB0eXBlb2YgYyAmJiAoYyA9IGMucHRyKTsKICAgICAgICAgICAgZCAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGQgJiYgKGQgPSBkLnB0cik7CiAgICAgICAgICAgIGcgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBnICYmIChnID0gZy5wdHIpOwogICAgICAgICAgICB1MyAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIHUzICYmICh1MyA9IHUzLnB0cik7CiAgICAgICAgICAgIHJldHVybiAhIUpjKFgsIGIsIGMsIGQsIGcsIHUzKTsKICAgICAgICAgIH07CiAgICAgICAgICBtLnByb3RvdHlwZS5Ta2lwQXR0cmlidXRlVHJhbnNmb3JtID0gbS5wcm90b3R5cGUuU2tpcEF0dHJpYnV0ZVRyYW5zZm9ybSA9IGZ1bmN0aW9uKGIpIHsKICAgICAgICAgICAgdmFyIGMgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIEtjKGMsIGIpOwogICAgICAgICAgfTsKICAgICAgICAgIG0ucHJvdG90eXBlLkdldEVuY29kZWRHZW9tZXRyeVR5cGVfRGVwcmVjYXRlZCA9IG0ucHJvdG90eXBlLkdldEVuY29kZWRHZW9tZXRyeVR5cGVfRGVwcmVjYXRlZCA9IGZ1bmN0aW9uKGIpIHsKICAgICAgICAgICAgdmFyIGMgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIHJldHVybiBMYyhjLCBiKTsKICAgICAgICAgIH07CiAgICAgICAgICBtLnByb3RvdHlwZS5EZWNvZGVCdWZmZXJUb1BvaW50Q2xvdWQgPSBtLnByb3RvdHlwZS5EZWNvZGVCdWZmZXJUb1BvaW50Q2xvdWQgPSBmdW5jdGlvbihiLCBjKSB7CiAgICAgICAgICAgIHZhciBkID0gdGhpcy5wdHI7CiAgICAgICAgICAgIGIgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBiICYmIChiID0gYi5wdHIpOwogICAgICAgICAgICBjICYmICJvYmplY3QiID09PSB0eXBlb2YgYyAmJiAoYyA9IGMucHRyKTsKICAgICAgICAgICAgcmV0dXJuIEQoTWMoZCwgYiwgYyksIEIpOwogICAgICAgICAgfTsKICAgICAgICAgIG0ucHJvdG90eXBlLkRlY29kZUJ1ZmZlclRvTWVzaCA9IG0ucHJvdG90eXBlLkRlY29kZUJ1ZmZlclRvTWVzaCA9IGZ1bmN0aW9uKGIsIGMpIHsKICAgICAgICAgICAgdmFyIGQgPSB0aGlzLnB0cjsKICAgICAgICAgICAgYiAmJiAib2JqZWN0IiA9PT0gdHlwZW9mIGIgJiYgKGIgPSBiLnB0cik7CiAgICAgICAgICAgIGMgJiYgIm9iamVjdCIgPT09IHR5cGVvZiBjICYmIChjID0gYy5wdHIpOwogICAgICAgICAgICByZXR1cm4gRChOYyhkLCBiLCBjKSwgQik7CiAgICAgICAgICB9OwogICAgICAgICAgbS5wcm90b3R5cGUuX19kZXN0cm95X18gPSBtLnByb3RvdHlwZS5fX2Rlc3Ryb3lfXyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICBPYyh0aGlzLnB0cik7CiAgICAgICAgICB9OwogICAgICAgICAgKGZ1bmN0aW9uKCkgewogICAgICAgICAgICBmdW5jdGlvbiBiKCkgewogICAgICAgICAgICAgIGEzLkFUVFJJQlVURV9JTlZBTElEX1RSQU5TRk9STSA9IFBjKCk7CiAgICAgICAgICAgICAgYTMuQVRUUklCVVRFX05PX1RSQU5TRk9STSA9IFFjKCk7CiAgICAgICAgICAgICAgYTMuQVRUUklCVVRFX1FVQU5USVpBVElPTl9UUkFOU0ZPUk0gPSBSYygpOwogICAgICAgICAgICAgIGEzLkFUVFJJQlVURV9PQ1RBSEVEUk9OX1RSQU5TRk9STSA9IFNjKCk7CiAgICAgICAgICAgICAgYTMuSU5WQUxJRCA9IFRjKCk7CiAgICAgICAgICAgICAgYTMuUE9TSVRJT04gPSBVYygpOwogICAgICAgICAgICAgIGEzLk5PUk1BTCA9IFZjKCk7CiAgICAgICAgICAgICAgYTMuQ09MT1IgPSBXYygpOwogICAgICAgICAgICAgIGEzLlRFWF9DT09SRCA9IFhjKCk7CiAgICAgICAgICAgICAgYTMuR0VORVJJQyA9IFljKCk7CiAgICAgICAgICAgICAgYTMuSU5WQUxJRF9HRU9NRVRSWV9UWVBFID0gWmMoKTsKICAgICAgICAgICAgICBhMy5QT0lOVF9DTE9VRCA9ICRjKCk7CiAgICAgICAgICAgICAgYTMuVFJJQU5HVUxBUl9NRVNIID0gYWQoKTsKICAgICAgICAgICAgICBhMy5EVF9JTlZBTElEID0gYmQoKTsKICAgICAgICAgICAgICBhMy5EVF9JTlQ4ID0gY2QoKTsKICAgICAgICAgICAgICBhMy5EVF9VSU5UOCA9IGRkKCk7CiAgICAgICAgICAgICAgYTMuRFRfSU5UMTYgPSBlZCgpOwogICAgICAgICAgICAgIGEzLkRUX1VJTlQxNiA9IGZkKCk7CiAgICAgICAgICAgICAgYTMuRFRfSU5UMzIgPSBnZCgpOwogICAgICAgICAgICAgIGEzLkRUX1VJTlQzMiA9IGhkKCk7CiAgICAgICAgICAgICAgYTMuRFRfSU5UNjQgPSBpZCgpOwogICAgICAgICAgICAgIGEzLkRUX1VJTlQ2NCA9IGpkKCk7CiAgICAgICAgICAgICAgYTMuRFRfRkxPQVQzMiA9IGtkKCk7CiAgICAgICAgICAgICAgYTMuRFRfRkxPQVQ2NCA9IGxkKCk7CiAgICAgICAgICAgICAgYTMuRFRfQk9PTCA9IG1kKCk7CiAgICAgICAgICAgICAgYTMuRFRfVFlQRVNfQ09VTlQgPSBuZCgpOwogICAgICAgICAgICAgIGEzLk9LID0gb2QoKTsKICAgICAgICAgICAgICBhMy5EUkFDT19FUlJPUiA9IHBkKCk7CiAgICAgICAgICAgICAgYTMuSU9fRVJST1IgPSBxZCgpOwogICAgICAgICAgICAgIGEzLklOVkFMSURfUEFSQU1FVEVSID0gcmQoKTsKICAgICAgICAgICAgICBhMy5VTlNVUFBPUlRFRF9WRVJTSU9OID0gc2QoKTsKICAgICAgICAgICAgICBhMy5VTktOT1dOX1ZFUlNJT04gPSB0ZCgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHphID8gYigpIDogb2EudW5zaGlmdChiKTsKICAgICAgICAgIH0pKCk7CiAgICAgICAgICBpZiAoImZ1bmN0aW9uIiA9PT0gdHlwZW9mIGEzLm9uTW9kdWxlUGFyc2VkKSBhMy5vbk1vZHVsZVBhcnNlZCgpOwogICAgICAgICAgYTMuRGVjb2Rlci5wcm90b3R5cGUuR2V0RW5jb2RlZEdlb21ldHJ5VHlwZSA9IGZ1bmN0aW9uKGIpIHsKICAgICAgICAgICAgaWYgKGIuX19jbGFzc19fICYmIGIuX19jbGFzc19fID09PSBhMy5EZWNvZGVyQnVmZmVyKSByZXR1cm4gYTMuRGVjb2Rlci5wcm90b3R5cGUuR2V0RW5jb2RlZEdlb21ldHJ5VHlwZV9EZXByZWNhdGVkKGIpOwogICAgICAgICAgICBpZiAoOCA+IGIuYnl0ZUxlbmd0aCkgcmV0dXJuIGEzLklOVkFMSURfR0VPTUVUUllfVFlQRTsKICAgICAgICAgICAgc3dpdGNoIChiWzddKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgcmV0dXJuIGEzLlBPSU5UX0NMT1VEOwogICAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICAgIHJldHVybiBhMy5UUklBTkdVTEFSX01FU0g7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHJldHVybiBhMy5JTlZBTElEX0dFT01FVFJZX1RZUEU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH07CiAgICAgICAgICByZXR1cm4gbi5yZWFkeTsKICAgICAgICB9OwogICAgICB9KSgpOwogICAgICAib2JqZWN0IiA9PT0gdHlwZW9mIGV4cG9ydHMyICYmICJvYmplY3QiID09PSB0eXBlb2YgbW9kdWxlID8gbW9kdWxlLmV4cG9ydHMgPSBEcmFjb0RlY29kZXJNb2R1bGUgOiAiZnVuY3Rpb24iID09PSB0eXBlb2YgZGVmaW5lICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoW10sIGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBEcmFjb0RlY29kZXJNb2R1bGU7CiAgICAgIH0pIDogIm9iamVjdCIgPT09IHR5cGVvZiBleHBvcnRzMiAmJiAoZXhwb3J0czIuRHJhY29EZWNvZGVyTW9kdWxlID0gRHJhY29EZWNvZGVyTW9kdWxlKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2RlY29kZURyYWNvLmpzCiAgdmFyIGRlY29kZURyYWNvX2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChkZWNvZGVEcmFjb19leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBkZWNvZGVEcmFjb19kZWZhdWx0CiAgfSk7CiAgZnVuY3Rpb24gZGVjb2RlSW5kZXhBcnJheShkcmFjb0dlb21ldHJ5LCBkcmFjb0RlY29kZXIpIHsKICAgIGNvbnN0IG51bVBvaW50cyA9IGRyYWNvR2VvbWV0cnkubnVtX3BvaW50cygpOwogICAgY29uc3QgbnVtRmFjZXMgPSBkcmFjb0dlb21ldHJ5Lm51bV9mYWNlcygpOwogICAgY29uc3QgZmFjZUluZGljZXMgPSBuZXcgZHJhY28uRHJhY29JbnQzMkFycmF5KCk7CiAgICBjb25zdCBudW1JbmRpY2VzID0gbnVtRmFjZXMgKiAzOwogICAgY29uc3QgaW5kZXhBcnJheSA9IEluZGV4RGF0YXR5cGVfZGVmYXVsdC5jcmVhdGVUeXBlZEFycmF5KG51bVBvaW50cywgbnVtSW5kaWNlcyk7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtRmFjZXM7ICsraSkgewogICAgICBkcmFjb0RlY29kZXIuR2V0RmFjZUZyb21NZXNoKGRyYWNvR2VvbWV0cnksIGksIGZhY2VJbmRpY2VzKTsKICAgICAgaW5kZXhBcnJheVtvZmZzZXQgKyAwXSA9IGZhY2VJbmRpY2VzLkdldFZhbHVlKDApOwogICAgICBpbmRleEFycmF5W29mZnNldCArIDFdID0gZmFjZUluZGljZXMuR2V0VmFsdWUoMSk7CiAgICAgIGluZGV4QXJyYXlbb2Zmc2V0ICsgMl0gPSBmYWNlSW5kaWNlcy5HZXRWYWx1ZSgyKTsKICAgICAgb2Zmc2V0ICs9IDM7CiAgICB9CiAgICBkcmFjby5kZXN0cm95KGZhY2VJbmRpY2VzKTsKICAgIHJldHVybiB7CiAgICAgIHR5cGVkQXJyYXk6IGluZGV4QXJyYXksCiAgICAgIG51bWJlck9mSW5kaWNlczogbnVtSW5kaWNlcwogICAgfTsKICB9CiAgZnVuY3Rpb24gZGVjb2RlUXVhbnRpemVkRHJhY29UeXBlZEFycmF5KGRyYWNvR2VvbWV0cnksIGRyYWNvRGVjb2RlciwgZHJhY29BdHRyaWJ1dGUsIHF1YW50aXphdGlvbiwgdmVydGV4QXJyYXlMZW5ndGgpIHsKICAgIGxldCB2ZXJ0ZXhBcnJheTsKICAgIGxldCBhdHRyaWJ1dGVEYXRhOwogICAgaWYgKHF1YW50aXphdGlvbi5xdWFudGl6YXRpb25CaXRzIDw9IDgpIHsKICAgICAgYXR0cmlidXRlRGF0YSA9IG5ldyBkcmFjby5EcmFjb1VJbnQ4QXJyYXkoKTsKICAgICAgdmVydGV4QXJyYXkgPSBuZXcgVWludDhBcnJheSh2ZXJ0ZXhBcnJheUxlbmd0aCk7CiAgICAgIGRyYWNvRGVjb2Rlci5HZXRBdHRyaWJ1dGVVSW50OEZvckFsbFBvaW50cygKICAgICAgICBkcmFjb0dlb21ldHJ5LAogICAgICAgIGRyYWNvQXR0cmlidXRlLAogICAgICAgIGF0dHJpYnV0ZURhdGEKICAgICAgKTsKICAgIH0gZWxzZSBpZiAocXVhbnRpemF0aW9uLnF1YW50aXphdGlvbkJpdHMgPD0gMTYpIHsKICAgICAgYXR0cmlidXRlRGF0YSA9IG5ldyBkcmFjby5EcmFjb1VJbnQxNkFycmF5KCk7CiAgICAgIHZlcnRleEFycmF5ID0gbmV3IFVpbnQxNkFycmF5KHZlcnRleEFycmF5TGVuZ3RoKTsKICAgICAgZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZVVJbnQxNkZvckFsbFBvaW50cygKICAgICAgICBkcmFjb0dlb21ldHJ5LAogICAgICAgIGRyYWNvQXR0cmlidXRlLAogICAgICAgIGF0dHJpYnV0ZURhdGEKICAgICAgKTsKICAgIH0gZWxzZSB7CiAgICAgIGF0dHJpYnV0ZURhdGEgPSBuZXcgZHJhY28uRHJhY29GbG9hdDMyQXJyYXkoKTsKICAgICAgdmVydGV4QXJyYXkgPSBuZXcgRmxvYXQzMkFycmF5KHZlcnRleEFycmF5TGVuZ3RoKTsKICAgICAgZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZUZsb2F0Rm9yQWxsUG9pbnRzKAogICAgICAgIGRyYWNvR2VvbWV0cnksCiAgICAgICAgZHJhY29BdHRyaWJ1dGUsCiAgICAgICAgYXR0cmlidXRlRGF0YQogICAgICApOwogICAgfQogICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2ZXJ0ZXhBcnJheUxlbmd0aDsgKytpKSB7CiAgICAgIHZlcnRleEFycmF5W2ldID0gYXR0cmlidXRlRGF0YS5HZXRWYWx1ZShpKTsKICAgIH0KICAgIGRyYWNvLmRlc3Ryb3koYXR0cmlidXRlRGF0YSk7CiAgICByZXR1cm4gdmVydGV4QXJyYXk7CiAgfQogIGZ1bmN0aW9uIGRlY29kZURyYWNvVHlwZWRBcnJheShkcmFjb0dlb21ldHJ5LCBkcmFjb0RlY29kZXIsIGRyYWNvQXR0cmlidXRlLCB2ZXJ0ZXhBcnJheUxlbmd0aCkgewogICAgbGV0IHZlcnRleEFycmF5OwogICAgbGV0IGF0dHJpYnV0ZURhdGE7CiAgICBzd2l0Y2ggKGRyYWNvQXR0cmlidXRlLmRhdGFfdHlwZSgpKSB7CiAgICAgIGNhc2UgMToKICAgICAgY2FzZSAxMToKICAgICAgICBhdHRyaWJ1dGVEYXRhID0gbmV3IGRyYWNvLkRyYWNvSW50OEFycmF5KCk7CiAgICAgICAgdmVydGV4QXJyYXkgPSBuZXcgSW50OEFycmF5KHZlcnRleEFycmF5TGVuZ3RoKTsKICAgICAgICBkcmFjb0RlY29kZXIuR2V0QXR0cmlidXRlSW50OEZvckFsbFBvaW50cygKICAgICAgICAgIGRyYWNvR2VvbWV0cnksCiAgICAgICAgICBkcmFjb0F0dHJpYnV0ZSwKICAgICAgICAgIGF0dHJpYnV0ZURhdGEKICAgICAgICApOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDI6CiAgICAgICAgYXR0cmlidXRlRGF0YSA9IG5ldyBkcmFjby5EcmFjb1VJbnQ4QXJyYXkoKTsKICAgICAgICB2ZXJ0ZXhBcnJheSA9IG5ldyBVaW50OEFycmF5KHZlcnRleEFycmF5TGVuZ3RoKTsKICAgICAgICBkcmFjb0RlY29kZXIuR2V0QXR0cmlidXRlVUludDhGb3JBbGxQb2ludHMoCiAgICAgICAgICBkcmFjb0dlb21ldHJ5LAogICAgICAgICAgZHJhY29BdHRyaWJ1dGUsCiAgICAgICAgICBhdHRyaWJ1dGVEYXRhCiAgICAgICAgKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAzOgogICAgICAgIGF0dHJpYnV0ZURhdGEgPSBuZXcgZHJhY28uRHJhY29JbnQxNkFycmF5KCk7CiAgICAgICAgdmVydGV4QXJyYXkgPSBuZXcgSW50MTZBcnJheSh2ZXJ0ZXhBcnJheUxlbmd0aCk7CiAgICAgICAgZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZUludDE2Rm9yQWxsUG9pbnRzKAogICAgICAgICAgZHJhY29HZW9tZXRyeSwKICAgICAgICAgIGRyYWNvQXR0cmlidXRlLAogICAgICAgICAgYXR0cmlidXRlRGF0YQogICAgICAgICk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgNDoKICAgICAgICBhdHRyaWJ1dGVEYXRhID0gbmV3IGRyYWNvLkRyYWNvVUludDE2QXJyYXkoKTsKICAgICAgICB2ZXJ0ZXhBcnJheSA9IG5ldyBVaW50MTZBcnJheSh2ZXJ0ZXhBcnJheUxlbmd0aCk7CiAgICAgICAgZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZVVJbnQxNkZvckFsbFBvaW50cygKICAgICAgICAgIGRyYWNvR2VvbWV0cnksCiAgICAgICAgICBkcmFjb0F0dHJpYnV0ZSwKICAgICAgICAgIGF0dHJpYnV0ZURhdGEKICAgICAgICApOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDU6CiAgICAgIGNhc2UgNzoKICAgICAgICBhdHRyaWJ1dGVEYXRhID0gbmV3IGRyYWNvLkRyYWNvSW50MzJBcnJheSgpOwogICAgICAgIHZlcnRleEFycmF5ID0gbmV3IEludDMyQXJyYXkodmVydGV4QXJyYXlMZW5ndGgpOwogICAgICAgIGRyYWNvRGVjb2Rlci5HZXRBdHRyaWJ1dGVJbnQzMkZvckFsbFBvaW50cygKICAgICAgICAgIGRyYWNvR2VvbWV0cnksCiAgICAgICAgICBkcmFjb0F0dHJpYnV0ZSwKICAgICAgICAgIGF0dHJpYnV0ZURhdGEKICAgICAgICApOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDY6CiAgICAgIGNhc2UgODoKICAgICAgICBhdHRyaWJ1dGVEYXRhID0gbmV3IGRyYWNvLkRyYWNvVUludDMyQXJyYXkoKTsKICAgICAgICB2ZXJ0ZXhBcnJheSA9IG5ldyBVaW50MzJBcnJheSh2ZXJ0ZXhBcnJheUxlbmd0aCk7CiAgICAgICAgZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZVVJbnQzMkZvckFsbFBvaW50cygKICAgICAgICAgIGRyYWNvR2VvbWV0cnksCiAgICAgICAgICBkcmFjb0F0dHJpYnV0ZSwKICAgICAgICAgIGF0dHJpYnV0ZURhdGEKICAgICAgICApOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDk6CiAgICAgIGNhc2UgMTA6CiAgICAgICAgYXR0cmlidXRlRGF0YSA9IG5ldyBkcmFjby5EcmFjb0Zsb2F0MzJBcnJheSgpOwogICAgICAgIHZlcnRleEFycmF5ID0gbmV3IEZsb2F0MzJBcnJheSh2ZXJ0ZXhBcnJheUxlbmd0aCk7CiAgICAgICAgZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZUZsb2F0Rm9yQWxsUG9pbnRzKAogICAgICAgICAgZHJhY29HZW9tZXRyeSwKICAgICAgICAgIGRyYWNvQXR0cmlidXRlLAogICAgICAgICAgYXR0cmlidXRlRGF0YQogICAgICAgICk7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHZlcnRleEFycmF5TGVuZ3RoOyArK2kpIHsKICAgICAgdmVydGV4QXJyYXlbaV0gPSBhdHRyaWJ1dGVEYXRhLkdldFZhbHVlKGkpOwogICAgfQogICAgZHJhY28uZGVzdHJveShhdHRyaWJ1dGVEYXRhKTsKICAgIHJldHVybiB2ZXJ0ZXhBcnJheTsKICB9CiAgZnVuY3Rpb24gZGVjb2RlQXR0cmlidXRlKGRyYWNvR2VvbWV0cnksIGRyYWNvRGVjb2RlciwgZHJhY29BdHRyaWJ1dGUpIHsKICAgIGNvbnN0IG51bVBvaW50cyA9IGRyYWNvR2VvbWV0cnkubnVtX3BvaW50cygpOwogICAgY29uc3QgbnVtQ29tcG9uZW50cyA9IGRyYWNvQXR0cmlidXRlLm51bV9jb21wb25lbnRzKCk7CiAgICBsZXQgcXVhbnRpemF0aW9uOwogICAgbGV0IHRyYW5zZm9ybTIgPSBuZXcgZHJhY28uQXR0cmlidXRlUXVhbnRpemF0aW9uVHJhbnNmb3JtKCk7CiAgICBpZiAodHJhbnNmb3JtMi5Jbml0RnJvbUF0dHJpYnV0ZShkcmFjb0F0dHJpYnV0ZSkpIHsKICAgICAgY29uc3QgbWluVmFsdWVzID0gbmV3IEFycmF5KG51bUNvbXBvbmVudHMpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUNvbXBvbmVudHM7ICsraSkgewogICAgICAgIG1pblZhbHVlc1tpXSA9IHRyYW5zZm9ybTIubWluX3ZhbHVlKGkpOwogICAgICB9CiAgICAgIHF1YW50aXphdGlvbiA9IHsKICAgICAgICBxdWFudGl6YXRpb25CaXRzOiB0cmFuc2Zvcm0yLnF1YW50aXphdGlvbl9iaXRzKCksCiAgICAgICAgbWluVmFsdWVzLAogICAgICAgIHJhbmdlOiB0cmFuc2Zvcm0yLnJhbmdlKCksCiAgICAgICAgb2N0RW5jb2RlZDogZmFsc2UKICAgICAgfTsKICAgIH0KICAgIGRyYWNvLmRlc3Ryb3kodHJhbnNmb3JtMik7CiAgICB0cmFuc2Zvcm0yID0gbmV3IGRyYWNvLkF0dHJpYnV0ZU9jdGFoZWRyb25UcmFuc2Zvcm0oKTsKICAgIGlmICh0cmFuc2Zvcm0yLkluaXRGcm9tQXR0cmlidXRlKGRyYWNvQXR0cmlidXRlKSkgewogICAgICBxdWFudGl6YXRpb24gPSB7CiAgICAgICAgcXVhbnRpemF0aW9uQml0czogdHJhbnNmb3JtMi5xdWFudGl6YXRpb25fYml0cygpLAogICAgICAgIG9jdEVuY29kZWQ6IHRydWUKICAgICAgfTsKICAgIH0KICAgIGRyYWNvLmRlc3Ryb3kodHJhbnNmb3JtMik7CiAgICBjb25zdCB2ZXJ0ZXhBcnJheUxlbmd0aCA9IG51bVBvaW50cyAqIG51bUNvbXBvbmVudHM7CiAgICBsZXQgdmVydGV4QXJyYXk7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHF1YW50aXphdGlvbikpIHsKICAgICAgdmVydGV4QXJyYXkgPSBkZWNvZGVRdWFudGl6ZWREcmFjb1R5cGVkQXJyYXkoCiAgICAgICAgZHJhY29HZW9tZXRyeSwKICAgICAgICBkcmFjb0RlY29kZXIsCiAgICAgICAgZHJhY29BdHRyaWJ1dGUsCiAgICAgICAgcXVhbnRpemF0aW9uLAogICAgICAgIHZlcnRleEFycmF5TGVuZ3RoCiAgICAgICk7CiAgICB9IGVsc2UgewogICAgICB2ZXJ0ZXhBcnJheSA9IGRlY29kZURyYWNvVHlwZWRBcnJheSgKICAgICAgICBkcmFjb0dlb21ldHJ5LAogICAgICAgIGRyYWNvRGVjb2RlciwKICAgICAgICBkcmFjb0F0dHJpYnV0ZSwKICAgICAgICB2ZXJ0ZXhBcnJheUxlbmd0aAogICAgICApOwogICAgfQogICAgY29uc3QgY29tcG9uZW50RGF0YXR5cGUgPSBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LmZyb21UeXBlZEFycmF5KHZlcnRleEFycmF5KTsKICAgIHJldHVybiB7CiAgICAgIGFycmF5OiB2ZXJ0ZXhBcnJheSwKICAgICAgZGF0YTogewogICAgICAgIGNvbXBvbmVudHNQZXJBdHRyaWJ1dGU6IG51bUNvbXBvbmVudHMsCiAgICAgICAgY29tcG9uZW50RGF0YXR5cGUsCiAgICAgICAgYnl0ZU9mZnNldDogZHJhY29BdHRyaWJ1dGUuYnl0ZV9vZmZzZXQoKSwKICAgICAgICBieXRlU3RyaWRlOiBDb21wb25lbnREYXRhdHlwZV9kZWZhdWx0LmdldFNpemVJbkJ5dGVzKGNvbXBvbmVudERhdGF0eXBlKSAqIG51bUNvbXBvbmVudHMsCiAgICAgICAgbm9ybWFsaXplZDogZHJhY29BdHRyaWJ1dGUubm9ybWFsaXplZCgpLAogICAgICAgIHF1YW50aXphdGlvbgogICAgICB9CiAgICB9OwogIH0KICBmdW5jdGlvbiBkZWNvZGVQb2ludENsb3VkKHBhcmFtZXRlcnMpIHsKICAgIGNvbnN0IGRyYWNvRGVjb2RlciA9IG5ldyBkcmFjby5EZWNvZGVyKCk7CiAgICBpZiAocGFyYW1ldGVycy5kZXF1YW50aXplSW5TaGFkZXIpIHsKICAgICAgZHJhY29EZWNvZGVyLlNraXBBdHRyaWJ1dGVUcmFuc2Zvcm0oZHJhY28uUE9TSVRJT04pOwogICAgICBkcmFjb0RlY29kZXIuU2tpcEF0dHJpYnV0ZVRyYW5zZm9ybShkcmFjby5OT1JNQUwpOwogICAgfQogICAgY29uc3QgYnVmZmVyID0gbmV3IGRyYWNvLkRlY29kZXJCdWZmZXIoKTsKICAgIGJ1ZmZlci5Jbml0KHBhcmFtZXRlcnMuYnVmZmVyLCBwYXJhbWV0ZXJzLmJ1ZmZlci5sZW5ndGgpOwogICAgY29uc3QgZ2VvbWV0cnlUeXBlID0gZHJhY29EZWNvZGVyLkdldEVuY29kZWRHZW9tZXRyeVR5cGUoYnVmZmVyKTsKICAgIGlmIChnZW9tZXRyeVR5cGUgIT09IGRyYWNvLlBPSU5UX0NMT1VEKSB7CiAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3JfZGVmYXVsdCgiRHJhY28gZ2VvbWV0cnkgdHlwZSBtdXN0IGJlIFBPSU5UX0NMT1VELiIpOwogICAgfQogICAgY29uc3QgZHJhY29Qb2ludENsb3VkID0gbmV3IGRyYWNvLlBvaW50Q2xvdWQoKTsKICAgIGNvbnN0IGRlY29kaW5nU3RhdHVzID0gZHJhY29EZWNvZGVyLkRlY29kZUJ1ZmZlclRvUG9pbnRDbG91ZCgKICAgICAgYnVmZmVyLAogICAgICBkcmFjb1BvaW50Q2xvdWQKICAgICk7CiAgICBpZiAoIWRlY29kaW5nU3RhdHVzLm9rKCkgfHwgZHJhY29Qb2ludENsb3VkLnB0ciA9PT0gMCkgewogICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yX2RlZmF1bHQoCiAgICAgICAgYEVycm9yIGRlY29kaW5nIGRyYWNvIHBvaW50IGNsb3VkOiAke2RlY29kaW5nU3RhdHVzLmVycm9yX21zZygpfWAKICAgICAgKTsKICAgIH0KICAgIGRyYWNvLmRlc3Ryb3koYnVmZmVyKTsKICAgIGNvbnN0IHJlc3VsdCA9IHt9OwogICAgY29uc3QgcHJvcGVydGllcyA9IHBhcmFtZXRlcnMucHJvcGVydGllczsKICAgIGZvciAoY29uc3QgcHJvcGVydHlOYW1lIGluIHByb3BlcnRpZXMpIHsKICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcGVydHlOYW1lKSkgewogICAgICAgIGxldCBkcmFjb0F0dHJpYnV0ZTsKICAgICAgICBpZiAocHJvcGVydHlOYW1lID09PSAiUE9TSVRJT04iIHx8IHByb3BlcnR5TmFtZSA9PT0gIk5PUk1BTCIpIHsKICAgICAgICAgIGNvbnN0IGRyYWNvQXR0cmlidXRlSWQgPSBkcmFjb0RlY29kZXIuR2V0QXR0cmlidXRlSWQoCiAgICAgICAgICAgIGRyYWNvUG9pbnRDbG91ZCwKICAgICAgICAgICAgZHJhY29bcHJvcGVydHlOYW1lXQogICAgICAgICAgKTsKICAgICAgICAgIGRyYWNvQXR0cmlidXRlID0gZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZSgKICAgICAgICAgICAgZHJhY29Qb2ludENsb3VkLAogICAgICAgICAgICBkcmFjb0F0dHJpYnV0ZUlkCiAgICAgICAgICApOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb25zdCBhdHRyaWJ1dGVJZCA9IHByb3BlcnRpZXNbcHJvcGVydHlOYW1lXTsKICAgICAgICAgIGRyYWNvQXR0cmlidXRlID0gZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZUJ5VW5pcXVlSWQoCiAgICAgICAgICAgIGRyYWNvUG9pbnRDbG91ZCwKICAgICAgICAgICAgYXR0cmlidXRlSWQKICAgICAgICAgICk7CiAgICAgICAgfQogICAgICAgIHJlc3VsdFtwcm9wZXJ0eU5hbWVdID0gZGVjb2RlQXR0cmlidXRlKAogICAgICAgICAgZHJhY29Qb2ludENsb3VkLAogICAgICAgICAgZHJhY29EZWNvZGVyLAogICAgICAgICAgZHJhY29BdHRyaWJ1dGUKICAgICAgICApOwogICAgICB9CiAgICB9CiAgICBkcmFjby5kZXN0cm95KGRyYWNvUG9pbnRDbG91ZCk7CiAgICBkcmFjby5kZXN0cm95KGRyYWNvRGVjb2Rlcik7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICBmdW5jdGlvbiBkZWNvZGVQcmltaXRpdmUocGFyYW1ldGVycykgewogICAgY29uc3QgZHJhY29EZWNvZGVyID0gbmV3IGRyYWNvLkRlY29kZXIoKTsKICAgIGlmIChwYXJhbWV0ZXJzLmRlcXVhbnRpemVJblNoYWRlcikgewogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhcmFtZXRlcnMuYXR0cmlidXRlc1RvU2tpcFRyYW5zZm9ybS5sZW5ndGg7ICsraSkgewogICAgICAgIGRyYWNvRGVjb2Rlci5Ta2lwQXR0cmlidXRlVHJhbnNmb3JtKAogICAgICAgICAgZHJhY29bcGFyYW1ldGVycy5hdHRyaWJ1dGVzVG9Ta2lwVHJhbnNmb3JtW2ldXQogICAgICAgICk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGJ1ZmZlclZpZXcgPSBwYXJhbWV0ZXJzLmJ1ZmZlclZpZXc7CiAgICBjb25zdCBidWZmZXIgPSBuZXcgZHJhY28uRGVjb2RlckJ1ZmZlcigpOwogICAgYnVmZmVyLkluaXQocGFyYW1ldGVycy5hcnJheSwgYnVmZmVyVmlldy5ieXRlTGVuZ3RoKTsKICAgIGNvbnN0IGdlb21ldHJ5VHlwZSA9IGRyYWNvRGVjb2Rlci5HZXRFbmNvZGVkR2VvbWV0cnlUeXBlKGJ1ZmZlcik7CiAgICBpZiAoZ2VvbWV0cnlUeXBlICE9PSBkcmFjby5UUklBTkdVTEFSX01FU0gpIHsKICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KCJVbnN1cHBvcnRlZCBkcmFjbyBtZXNoIGdlb21ldHJ5IHR5cGUuIik7CiAgICB9CiAgICBjb25zdCBkcmFjb0dlb21ldHJ5ID0gbmV3IGRyYWNvLk1lc2goKTsKICAgIGNvbnN0IGRlY29kaW5nU3RhdHVzID0gZHJhY29EZWNvZGVyLkRlY29kZUJ1ZmZlclRvTWVzaChidWZmZXIsIGRyYWNvR2VvbWV0cnkpOwogICAgaWYgKCFkZWNvZGluZ1N0YXR1cy5vaygpIHx8IGRyYWNvR2VvbWV0cnkucHRyID09PSAwKSB7CiAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3JfZGVmYXVsdCgKICAgICAgICBgRXJyb3IgZGVjb2RpbmcgZHJhY28gbWVzaCBnZW9tZXRyeTogJHtkZWNvZGluZ1N0YXR1cy5lcnJvcl9tc2coKX1gCiAgICAgICk7CiAgICB9CiAgICBkcmFjby5kZXN0cm95KGJ1ZmZlcik7CiAgICBjb25zdCBhdHRyaWJ1dGVEYXRhID0ge307CiAgICBjb25zdCBjb21wcmVzc2VkQXR0cmlidXRlcyA9IHBhcmFtZXRlcnMuY29tcHJlc3NlZEF0dHJpYnV0ZXM7CiAgICBmb3IgKGNvbnN0IGF0dHJpYnV0ZU5hbWUgaW4gY29tcHJlc3NlZEF0dHJpYnV0ZXMpIHsKICAgICAgaWYgKGNvbXByZXNzZWRBdHRyaWJ1dGVzLmhhc093blByb3BlcnR5KGF0dHJpYnV0ZU5hbWUpKSB7CiAgICAgICAgY29uc3QgY29tcHJlc3NlZEF0dHJpYnV0ZSA9IGNvbXByZXNzZWRBdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdOwogICAgICAgIGNvbnN0IGRyYWNvQXR0cmlidXRlID0gZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZUJ5VW5pcXVlSWQoCiAgICAgICAgICBkcmFjb0dlb21ldHJ5LAogICAgICAgICAgY29tcHJlc3NlZEF0dHJpYnV0ZQogICAgICAgICk7CiAgICAgICAgYXR0cmlidXRlRGF0YVthdHRyaWJ1dGVOYW1lXSA9IGRlY29kZUF0dHJpYnV0ZSgKICAgICAgICAgIGRyYWNvR2VvbWV0cnksCiAgICAgICAgICBkcmFjb0RlY29kZXIsCiAgICAgICAgICBkcmFjb0F0dHJpYnV0ZQogICAgICAgICk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHJlc3VsdCA9IHsKICAgICAgaW5kZXhBcnJheTogZGVjb2RlSW5kZXhBcnJheShkcmFjb0dlb21ldHJ5LCBkcmFjb0RlY29kZXIpLAogICAgICBhdHRyaWJ1dGVEYXRhCiAgICB9OwogICAgZHJhY28uZGVzdHJveShkcmFjb0dlb21ldHJ5KTsKICAgIGRyYWNvLmRlc3Ryb3koZHJhY29EZWNvZGVyKTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGFzeW5jIGZ1bmN0aW9uIGRlY29kZShwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHBhcmFtZXRlcnMuYnVmZmVyVmlldykpIHsKICAgICAgcmV0dXJuIGRlY29kZVByaW1pdGl2ZShwYXJhbWV0ZXJzKTsKICAgIH0KICAgIHJldHVybiBkZWNvZGVQb2ludENsb3VkKHBhcmFtZXRlcnMpOwogIH0KICBhc3luYyBmdW5jdGlvbiBpbml0V29ya2VyKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIGNvbnN0IHdhc21Db25maWcgPSBwYXJhbWV0ZXJzLndlYkFzc2VtYmx5Q29uZmlnOwogICAgaWYgKGRlZmluZWRfZGVmYXVsdCh3YXNtQ29uZmlnKSAmJiBkZWZpbmVkX2RlZmF1bHQod2FzbUNvbmZpZy53YXNtQmluYXJ5RmlsZSkpIHsKICAgICAgZHJhY28gPSBhd2FpdCAoMCwgaW1wb3J0X2RyYWNvX2RlY29kZXJfbm9kZWpzLmRlZmF1bHQpKHdhc21Db25maWcpOwogICAgfSBlbHNlIHsKICAgICAgZHJhY28gPSBhd2FpdCAoMCwgaW1wb3J0X2RyYWNvX2RlY29kZXJfbm9kZWpzLmRlZmF1bHQpKCk7CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgYXN5bmMgZnVuY3Rpb24gZGVjb2RlRHJhY28ocGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cykgewogICAgY29uc3Qgd2FzbUNvbmZpZyA9IHBhcmFtZXRlcnMud2ViQXNzZW1ibHlDb25maWc7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHdhc21Db25maWcpKSB7CiAgICAgIHJldHVybiBpbml0V29ya2VyKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpOwogICAgfQogICAgcmV0dXJuIGRlY29kZShwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKTsKICB9CiAgdmFyIGltcG9ydF9kcmFjb19kZWNvZGVyX25vZGVqcywgZHJhY28sIGRlY29kZURyYWNvX2RlZmF1bHQ7CiAgdmFyIGluaXRfZGVjb2RlRHJhY28gPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2RlY29kZURyYWNvLmpzIigpIHsKICAgICAgaW5pdF9Db21wb25lbnREYXRhdHlwZSgpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfUnVudGltZUVycm9yKCk7CiAgICAgIGluaXRfY3JlYXRlVGFza1Byb2Nlc3NvcldvcmtlcigpOwogICAgICBpbXBvcnRfZHJhY29fZGVjb2Rlcl9ub2RlanMgPSBfX3RvRVNNKHJlcXVpcmVfZHJhY29fZGVjb2Rlcl9ub2RlanMoKSwgMSk7CiAgICAgIGRlY29kZURyYWNvX2RlZmF1bHQgPSBjcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyX2RlZmF1bHQoZGVjb2RlRHJhY28pOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlRGF0YS5qcwogIGZ1bmN0aW9uIGRlY29kZUdvb2dsZUVhcnRoRW50ZXJwcmlzZURhdGEoa2V5LCBkYXRhKSB7CiAgICBpZiAoZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlRGF0YS5wYXNzVGhyb3VnaERhdGFGb3JUZXN0aW5nKSB7CiAgICAgIHJldHVybiBkYXRhOwogICAgfQogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJrZXkiLCBrZXkpOwogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJkYXRhIiwgZGF0YSk7CiAgICBjb25zdCBrZXlMZW5ndGggPSBrZXkuYnl0ZUxlbmd0aDsKICAgIGlmIChrZXlMZW5ndGggPT09IDAgfHwga2V5TGVuZ3RoICUgNCAhPT0gMCkgewogICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yX2RlZmF1bHQoCiAgICAgICAgIlRoZSBsZW5ndGggb2Yga2V5IG11c3QgYmUgZ3JlYXRlciB0aGFuIDAgYW5kIGEgbXVsdGlwbGUgb2YgNC4iCiAgICAgICk7CiAgICB9CiAgICBjb25zdCBkYXRhVmlldyA9IG5ldyBEYXRhVmlldyhkYXRhKTsKICAgIGNvbnN0IG1hZ2ljID0gZGF0YVZpZXcuZ2V0VWludDMyKDAsIHRydWUpOwogICAgaWYgKG1hZ2ljID09PSBjb21wcmVzc2VkTWFnaWMgfHwgbWFnaWMgPT09IGNvbXByZXNzZWRNYWdpY1N3YXApIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9CiAgICBjb25zdCBrZXlWaWV3ID0gbmV3IERhdGFWaWV3KGtleSk7CiAgICBsZXQgZHAgPSAwOwogICAgY29uc3QgZHBlbmQgPSBkYXRhLmJ5dGVMZW5ndGg7CiAgICBjb25zdCBkcGVuZDY0ID0gZHBlbmQgLSBkcGVuZCAlIDg7CiAgICBjb25zdCBrcGVuZCA9IGtleUxlbmd0aDsKICAgIGxldCBrcDsKICAgIGxldCBvZmYgPSA4OwogICAgd2hpbGUgKGRwIDwgZHBlbmQ2NCkgewogICAgICBvZmYgPSAob2ZmICsgOCkgJSAyNDsKICAgICAga3AgPSBvZmY7CiAgICAgIHdoaWxlIChkcCA8IGRwZW5kNjQgJiYga3AgPCBrcGVuZCkgewogICAgICAgIGRhdGFWaWV3LnNldFVpbnQzMigKICAgICAgICAgIGRwLAogICAgICAgICAgZGF0YVZpZXcuZ2V0VWludDMyKGRwLCB0cnVlKSBeIGtleVZpZXcuZ2V0VWludDMyKGtwLCB0cnVlKSwKICAgICAgICAgIHRydWUKICAgICAgICApOwogICAgICAgIGRhdGFWaWV3LnNldFVpbnQzMigKICAgICAgICAgIGRwICsgNCwKICAgICAgICAgIGRhdGFWaWV3LmdldFVpbnQzMihkcCArIDQsIHRydWUpIF4ga2V5Vmlldy5nZXRVaW50MzIoa3AgKyA0LCB0cnVlKSwKICAgICAgICAgIHRydWUKICAgICAgICApOwogICAgICAgIGRwICs9IDg7CiAgICAgICAga3AgKz0gMjQ7CiAgICAgIH0KICAgIH0KICAgIGlmIChkcCA8IGRwZW5kKSB7CiAgICAgIGlmIChrcCA+PSBrcGVuZCkgewogICAgICAgIG9mZiA9IChvZmYgKyA4KSAlIDI0OwogICAgICAgIGtwID0gb2ZmOwogICAgICB9CiAgICAgIHdoaWxlIChkcCA8IGRwZW5kKSB7CiAgICAgICAgZGF0YVZpZXcuc2V0VWludDgoZHAsIGRhdGFWaWV3LmdldFVpbnQ4KGRwKSBeIGtleVZpZXcuZ2V0VWludDgoa3ApKTsKICAgICAgICBkcCsrOwogICAgICAgIGtwKys7CiAgICAgIH0KICAgIH0KICB9CiAgdmFyIGNvbXByZXNzZWRNYWdpYywgY29tcHJlc3NlZE1hZ2ljU3dhcCwgZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlRGF0YV9kZWZhdWx0OwogIHZhciBpbml0X2RlY29kZUdvb2dsZUVhcnRoRW50ZXJwcmlzZURhdGEgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2RlY29kZUdvb2dsZUVhcnRoRW50ZXJwcmlzZURhdGEuanMiKCkgewogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfUnVudGltZUVycm9yKCk7CiAgICAgIGNvbXByZXNzZWRNYWdpYyA9IDE5NTMwMjk4MDU7CiAgICAgIGNvbXByZXNzZWRNYWdpY1N3YXAgPSAyOTE3MDM0MTAwOwogICAgICBkZWNvZGVHb29nbGVFYXJ0aEVudGVycHJpc2VEYXRhLnBhc3NUaHJvdWdoRGF0YUZvclRlc3RpbmcgPSBmYWxzZTsKICAgICAgZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlRGF0YV9kZWZhdWx0ID0gZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlRGF0YTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL2lzQml0U2V0LmpzCiAgZnVuY3Rpb24gaXNCaXRTZXQoYml0cywgbWFzaykgewogICAgcmV0dXJuIChiaXRzICYgbWFzaykgIT09IDA7CiAgfQogIHZhciBpc0JpdFNldF9kZWZhdWx0OwogIHZhciBpbml0X2lzQml0U2V0ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9pc0JpdFNldC5qcyIoKSB7CiAgICAgIGlzQml0U2V0X2RlZmF1bHQgPSBpc0JpdFNldDsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dvb2dsZUVhcnRoRW50ZXJwcmlzZVRpbGVJbmZvcm1hdGlvbi5qcwogIGZ1bmN0aW9uIEdvb2dsZUVhcnRoRW50ZXJwcmlzZVRpbGVJbmZvcm1hdGlvbihiaXRzLCBjbm9kZVZlcnNpb24sIGltYWdlcnlWZXJzaW9uLCB0ZXJyYWluVmVyc2lvbiwgaW1hZ2VyeVByb3ZpZGVyLCB0ZXJyYWluUHJvdmlkZXIpIHsKICAgIHRoaXMuX2JpdHMgPSBiaXRzOwogICAgdGhpcy5jbm9kZVZlcnNpb24gPSBjbm9kZVZlcnNpb247CiAgICB0aGlzLmltYWdlcnlWZXJzaW9uID0gaW1hZ2VyeVZlcnNpb247CiAgICB0aGlzLnRlcnJhaW5WZXJzaW9uID0gdGVycmFpblZlcnNpb247CiAgICB0aGlzLmltYWdlcnlQcm92aWRlciA9IGltYWdlcnlQcm92aWRlcjsKICAgIHRoaXMudGVycmFpblByb3ZpZGVyID0gdGVycmFpblByb3ZpZGVyOwogICAgdGhpcy5hbmNlc3Rvckhhc1RlcnJhaW4gPSBmYWxzZTsKICAgIHRoaXMudGVycmFpblN0YXRlID0gdm9pZCAwOwogIH0KICB2YXIgY2hpbGRyZW5CaXRtYXNrcywgYW55Q2hpbGRCaXRtYXNrLCBjYWNoZUZsYWdCaXRtYXNrLCBpbWFnZUJpdG1hc2ssIHRlcnJhaW5CaXRtYXNrLCBHb29nbGVFYXJ0aEVudGVycHJpc2VUaWxlSW5mb3JtYXRpb25fZGVmYXVsdDsKICB2YXIgaW5pdF9Hb29nbGVFYXJ0aEVudGVycHJpc2VUaWxlSW5mb3JtYXRpb24gPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0dvb2dsZUVhcnRoRW50ZXJwcmlzZVRpbGVJbmZvcm1hdGlvbi5qcyIoKSB7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X2lzQml0U2V0KCk7CiAgICAgIGNoaWxkcmVuQml0bWFza3MgPSBbMSwgMiwgNCwgOF07CiAgICAgIGFueUNoaWxkQml0bWFzayA9IDE1OwogICAgICBjYWNoZUZsYWdCaXRtYXNrID0gMTY7CiAgICAgIGltYWdlQml0bWFzayA9IDY0OwogICAgICB0ZXJyYWluQml0bWFzayA9IDEyODsKICAgICAgR29vZ2xlRWFydGhFbnRlcnByaXNlVGlsZUluZm9ybWF0aW9uLmNsb25lID0gZnVuY3Rpb24oaW5mbywgcmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IEdvb2dsZUVhcnRoRW50ZXJwcmlzZVRpbGVJbmZvcm1hdGlvbigKICAgICAgICAgICAgaW5mby5fYml0cywKICAgICAgICAgICAgaW5mby5jbm9kZVZlcnNpb24sCiAgICAgICAgICAgIGluZm8uaW1hZ2VyeVZlcnNpb24sCiAgICAgICAgICAgIGluZm8udGVycmFpblZlcnNpb24sCiAgICAgICAgICAgIGluZm8uaW1hZ2VyeVByb3ZpZGVyLAogICAgICAgICAgICBpbmZvLnRlcnJhaW5Qcm92aWRlcgogICAgICAgICAgKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmVzdWx0Ll9iaXRzID0gaW5mby5fYml0czsKICAgICAgICAgIHJlc3VsdC5jbm9kZVZlcnNpb24gPSBpbmZvLmNub2RlVmVyc2lvbjsKICAgICAgICAgIHJlc3VsdC5pbWFnZXJ5VmVyc2lvbiA9IGluZm8uaW1hZ2VyeVZlcnNpb247CiAgICAgICAgICByZXN1bHQudGVycmFpblZlcnNpb24gPSBpbmZvLnRlcnJhaW5WZXJzaW9uOwogICAgICAgICAgcmVzdWx0LmltYWdlcnlQcm92aWRlciA9IGluZm8uaW1hZ2VyeVByb3ZpZGVyOwogICAgICAgICAgcmVzdWx0LnRlcnJhaW5Qcm92aWRlciA9IGluZm8udGVycmFpblByb3ZpZGVyOwogICAgICAgIH0KICAgICAgICByZXN1bHQuYW5jZXN0b3JIYXNUZXJyYWluID0gaW5mby5hbmNlc3Rvckhhc1RlcnJhaW47CiAgICAgICAgcmVzdWx0LnRlcnJhaW5TdGF0ZSA9IGluZm8udGVycmFpblN0YXRlOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH07CiAgICAgIEdvb2dsZUVhcnRoRW50ZXJwcmlzZVRpbGVJbmZvcm1hdGlvbi5wcm90b3R5cGUuc2V0UGFyZW50ID0gZnVuY3Rpb24ocGFyZW50KSB7CiAgICAgICAgdGhpcy5hbmNlc3Rvckhhc1RlcnJhaW4gPSBwYXJlbnQuYW5jZXN0b3JIYXNUZXJyYWluIHx8IHRoaXMuaGFzVGVycmFpbigpOwogICAgICB9OwogICAgICBHb29nbGVFYXJ0aEVudGVycHJpc2VUaWxlSW5mb3JtYXRpb24ucHJvdG90eXBlLmhhc1N1YnRyZWUgPSBmdW5jdGlvbigpIHsKICAgICAgICByZXR1cm4gaXNCaXRTZXRfZGVmYXVsdCh0aGlzLl9iaXRzLCBjYWNoZUZsYWdCaXRtYXNrKTsKICAgICAgfTsKICAgICAgR29vZ2xlRWFydGhFbnRlcnByaXNlVGlsZUluZm9ybWF0aW9uLnByb3RvdHlwZS5oYXNJbWFnZXJ5ID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIGlzQml0U2V0X2RlZmF1bHQodGhpcy5fYml0cywgaW1hZ2VCaXRtYXNrKTsKICAgICAgfTsKICAgICAgR29vZ2xlRWFydGhFbnRlcnByaXNlVGlsZUluZm9ybWF0aW9uLnByb3RvdHlwZS5oYXNUZXJyYWluID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIGlzQml0U2V0X2RlZmF1bHQodGhpcy5fYml0cywgdGVycmFpbkJpdG1hc2spOwogICAgICB9OwogICAgICBHb29nbGVFYXJ0aEVudGVycHJpc2VUaWxlSW5mb3JtYXRpb24ucHJvdG90eXBlLmhhc0NoaWxkcmVuID0gZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIGlzQml0U2V0X2RlZmF1bHQodGhpcy5fYml0cywgYW55Q2hpbGRCaXRtYXNrKTsKICAgICAgfTsKICAgICAgR29vZ2xlRWFydGhFbnRlcnByaXNlVGlsZUluZm9ybWF0aW9uLnByb3RvdHlwZS5oYXNDaGlsZCA9IGZ1bmN0aW9uKGluZGV4KSB7CiAgICAgICAgcmV0dXJuIGlzQml0U2V0X2RlZmF1bHQodGhpcy5fYml0cywgY2hpbGRyZW5CaXRtYXNrc1tpbmRleF0pOwogICAgICB9OwogICAgICBHb29nbGVFYXJ0aEVudGVycHJpc2VUaWxlSW5mb3JtYXRpb24ucHJvdG90eXBlLmdldENoaWxkQml0bWFzayA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiB0aGlzLl9iaXRzICYgYW55Q2hpbGRCaXRtYXNrOwogICAgICB9OwogICAgICBHb29nbGVFYXJ0aEVudGVycHJpc2VUaWxlSW5mb3JtYXRpb25fZGVmYXVsdCA9IEdvb2dsZUVhcnRoRW50ZXJwcmlzZVRpbGVJbmZvcm1hdGlvbjsKICAgIH0KICB9KTsKCiAgLy8gbm9kZV9tb2R1bGVzL3Bha28vbGliL3psaWIvYWRsZXIzMi5qcwogIHZhciByZXF1aXJlX2FkbGVyMzIgPSBfX2NvbW1vbkpTKHsKICAgICJub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9hZGxlcjMyLmpzIihleHBvcnRzMiwgbW9kdWxlKSB7CiAgICAgICJ1c2Ugc3RyaWN0IjsKICAgICAgdmFyIGFkbGVyMzIgPSAoYWRsZXIsIGJ1ZiwgbGVuLCBwb3MpID0+IHsKICAgICAgICBsZXQgczEgPSBhZGxlciAmIDY1NTM1IHwgMCwgczIgPSBhZGxlciA+Pj4gMTYgJiA2NTUzNSB8IDAsIG4gPSAwOwogICAgICAgIHdoaWxlIChsZW4gIT09IDApIHsKICAgICAgICAgIG4gPSBsZW4gPiAyZTMgPyAyZTMgOiBsZW47CiAgICAgICAgICBsZW4gLT0gbjsKICAgICAgICAgIGRvIHsKICAgICAgICAgICAgczEgPSBzMSArIGJ1Zltwb3MrK10gfCAwOwogICAgICAgICAgICBzMiA9IHMyICsgczEgfCAwOwogICAgICAgICAgfSB3aGlsZSAoLS1uKTsKICAgICAgICAgIHMxICU9IDY1NTIxOwogICAgICAgICAgczIgJT0gNjU1MjE7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzMSB8IHMyIDw8IDE2IHwgMDsKICAgICAgfTsKICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhZGxlcjMyOwogICAgfQogIH0pOwoKICAvLyBub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9jcmMzMi5qcwogIHZhciByZXF1aXJlX2NyYzMyID0gX19jb21tb25KUyh7CiAgICAibm9kZV9tb2R1bGVzL3Bha28vbGliL3psaWIvY3JjMzIuanMiKGV4cG9ydHMyLCBtb2R1bGUpIHsKICAgICAgInVzZSBzdHJpY3QiOwogICAgICB2YXIgbWFrZVRhYmxlID0gKCkgPT4gewogICAgICAgIGxldCBjLCB0YWJsZSA9IFtdOwogICAgICAgIGZvciAodmFyIG4gPSAwOyBuIDwgMjU2OyBuKyspIHsKICAgICAgICAgIGMgPSBuOwogICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCA4OyBrKyspIHsKICAgICAgICAgICAgYyA9IGMgJiAxID8gMzk4ODI5MjM4NCBeIGMgPj4+IDEgOiBjID4+PiAxOwogICAgICAgICAgfQogICAgICAgICAgdGFibGVbbl0gPSBjOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGFibGU7CiAgICAgIH07CiAgICAgIHZhciBjcmNUYWJsZSA9IG5ldyBVaW50MzJBcnJheShtYWtlVGFibGUoKSk7CiAgICAgIHZhciBjcmMzMiA9IChjcmMsIGJ1ZiwgbGVuLCBwb3MpID0+IHsKICAgICAgICBjb25zdCB0ID0gY3JjVGFibGU7CiAgICAgICAgY29uc3QgZW5kID0gcG9zICsgbGVuOwogICAgICAgIGNyYyBePSAtMTsKICAgICAgICBmb3IgKGxldCBpID0gcG9zOyBpIDwgZW5kOyBpKyspIHsKICAgICAgICAgIGNyYyA9IGNyYyA+Pj4gOCBeIHRbKGNyYyBeIGJ1ZltpXSkgJiAyNTVdOwogICAgICAgIH0KICAgICAgICByZXR1cm4gY3JjIF4gLTE7CiAgICAgIH07CiAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JjMzI7CiAgICB9CiAgfSk7CgogIC8vIG5vZGVfbW9kdWxlcy9wYWtvL2xpYi96bGliL2luZmZhc3QuanMKICB2YXIgcmVxdWlyZV9pbmZmYXN0ID0gX19jb21tb25KUyh7CiAgICAibm9kZV9tb2R1bGVzL3Bha28vbGliL3psaWIvaW5mZmFzdC5qcyIoZXhwb3J0czIsIG1vZHVsZSkgewogICAgICAidXNlIHN0cmljdCI7CiAgICAgIHZhciBCQUQgPSAxNjIwOTsKICAgICAgdmFyIFRZUEUgPSAxNjE5MTsKICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmZsYXRlX2Zhc3Qoc3RybSwgc3RhcnQpIHsKICAgICAgICBsZXQgX2luOwogICAgICAgIGxldCBsYXN0OwogICAgICAgIGxldCBfb3V0OwogICAgICAgIGxldCBiZWc7CiAgICAgICAgbGV0IGVuZDsKICAgICAgICBsZXQgZG1heDsKICAgICAgICBsZXQgd3NpemU7CiAgICAgICAgbGV0IHdoYXZlOwogICAgICAgIGxldCB3bmV4dDsKICAgICAgICBsZXQgc193aW5kb3c7CiAgICAgICAgbGV0IGhvbGQ7CiAgICAgICAgbGV0IGJpdHM7CiAgICAgICAgbGV0IGxjb2RlOwogICAgICAgIGxldCBkY29kZTsKICAgICAgICBsZXQgbG1hc2s7CiAgICAgICAgbGV0IGRtYXNrOwogICAgICAgIGxldCBoZXJlOwogICAgICAgIGxldCBvcDsKICAgICAgICBsZXQgbGVuOwogICAgICAgIGxldCBkaXN0OwogICAgICAgIGxldCBmcm9tOwogICAgICAgIGxldCBmcm9tX3NvdXJjZTsKICAgICAgICBsZXQgaW5wdXQsIG91dHB1dDsKICAgICAgICBjb25zdCBzdGF0ZSA9IHN0cm0uc3RhdGU7CiAgICAgICAgX2luID0gc3RybS5uZXh0X2luOwogICAgICAgIGlucHV0ID0gc3RybS5pbnB1dDsKICAgICAgICBsYXN0ID0gX2luICsgKHN0cm0uYXZhaWxfaW4gLSA1KTsKICAgICAgICBfb3V0ID0gc3RybS5uZXh0X291dDsKICAgICAgICBvdXRwdXQgPSBzdHJtLm91dHB1dDsKICAgICAgICBiZWcgPSBfb3V0IC0gKHN0YXJ0IC0gc3RybS5hdmFpbF9vdXQpOwogICAgICAgIGVuZCA9IF9vdXQgKyAoc3RybS5hdmFpbF9vdXQgLSAyNTcpOwogICAgICAgIGRtYXggPSBzdGF0ZS5kbWF4OwogICAgICAgIHdzaXplID0gc3RhdGUud3NpemU7CiAgICAgICAgd2hhdmUgPSBzdGF0ZS53aGF2ZTsKICAgICAgICB3bmV4dCA9IHN0YXRlLnduZXh0OwogICAgICAgIHNfd2luZG93ID0gc3RhdGUud2luZG93OwogICAgICAgIGhvbGQgPSBzdGF0ZS5ob2xkOwogICAgICAgIGJpdHMgPSBzdGF0ZS5iaXRzOwogICAgICAgIGxjb2RlID0gc3RhdGUubGVuY29kZTsKICAgICAgICBkY29kZSA9IHN0YXRlLmRpc3Rjb2RlOwogICAgICAgIGxtYXNrID0gKDEgPDwgc3RhdGUubGVuYml0cykgLSAxOwogICAgICAgIGRtYXNrID0gKDEgPDwgc3RhdGUuZGlzdGJpdHMpIC0gMTsKICAgICAgICB0b3A6CiAgICAgICAgICBkbyB7CiAgICAgICAgICAgIGlmIChiaXRzIDwgMTUpIHsKICAgICAgICAgICAgICBob2xkICs9IGlucHV0W19pbisrXSA8PCBiaXRzOwogICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgICBob2xkICs9IGlucHV0W19pbisrXSA8PCBiaXRzOwogICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgfQogICAgICAgICAgICBoZXJlID0gbGNvZGVbaG9sZCAmIGxtYXNrXTsKICAgICAgICAgICAgZG9sZW46CiAgICAgICAgICAgICAgZm9yICg7IDsgKSB7CiAgICAgICAgICAgICAgICBvcCA9IGhlcmUgPj4+IDI0OwogICAgICAgICAgICAgICAgaG9sZCA+Pj49IG9wOwogICAgICAgICAgICAgICAgYml0cyAtPSBvcDsKICAgICAgICAgICAgICAgIG9wID0gaGVyZSA+Pj4gMTYgJiAyNTU7CiAgICAgICAgICAgICAgICBpZiAob3AgPT09IDApIHsKICAgICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBoZXJlICYgNjU1MzU7CiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG9wICYgMTYpIHsKICAgICAgICAgICAgICAgICAgbGVuID0gaGVyZSAmIDY1NTM1OwogICAgICAgICAgICAgICAgICBvcCAmPSAxNTsKICAgICAgICAgICAgICAgICAgaWYgKG9wKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGJpdHMgPCBvcCkgewogICAgICAgICAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtfaW4rK10gPDwgYml0czsKICAgICAgICAgICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgbGVuICs9IGhvbGQgJiAoMSA8PCBvcCkgLSAxOwogICAgICAgICAgICAgICAgICAgIGhvbGQgPj4+PSBvcDsKICAgICAgICAgICAgICAgICAgICBiaXRzIC09IG9wOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChiaXRzIDwgMTUpIHsKICAgICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W19pbisrXSA8PCBiaXRzOwogICAgICAgICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W19pbisrXSA8PCBiaXRzOwogICAgICAgICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBoZXJlID0gZGNvZGVbaG9sZCAmIGRtYXNrXTsKICAgICAgICAgICAgICAgICAgZG9kaXN0OgogICAgICAgICAgICAgICAgICAgIGZvciAoOyA7ICkgewogICAgICAgICAgICAgICAgICAgICAgb3AgPSBoZXJlID4+PiAyNDsKICAgICAgICAgICAgICAgICAgICAgIGhvbGQgPj4+PSBvcDsKICAgICAgICAgICAgICAgICAgICAgIGJpdHMgLT0gb3A7CiAgICAgICAgICAgICAgICAgICAgICBvcCA9IGhlcmUgPj4+IDE2ICYgMjU1OwogICAgICAgICAgICAgICAgICAgICAgaWYgKG9wICYgMTYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZGlzdCA9IGhlcmUgJiA2NTUzNTsKICAgICAgICAgICAgICAgICAgICAgICAgb3AgJj0gMTU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiaXRzIDwgb3ApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W19pbisrXSA8PCBiaXRzOwogICAgICAgICAgICAgICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYml0cyA8IG9wKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W19pbisrXSA8PCBiaXRzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBkaXN0ICs9IGhvbGQgJiAoMSA8PCBvcCkgLSAxOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGlzdCA+IGRtYXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJpbnZhbGlkIGRpc3RhbmNlIHRvbyBmYXIgYmFjayI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDsKICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhayB0b3A7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaG9sZCA+Pj49IG9wOwogICAgICAgICAgICAgICAgICAgICAgICBiaXRzIC09IG9wOwogICAgICAgICAgICAgICAgICAgICAgICBvcCA9IF9vdXQgLSBiZWc7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkaXN0ID4gb3ApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBvcCA9IGRpc3QgLSBvcDsKICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3AgPiB3aGF2ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLnNhbmUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RybS5tc2cgPSAiaW52YWxpZCBkaXN0YW5jZSB0b28gZmFyIGJhY2siOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhayB0b3A7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgIGZyb20gPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgIGZyb21fc291cmNlID0gc193aW5kb3c7CiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHduZXh0ID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tICs9IHdzaXplIC0gb3A7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3AgPCBsZW4pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuIC09IG9wOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBzX3dpbmRvd1tmcm9tKytdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IHdoaWxlICgtLW9wKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbSA9IF9vdXQgLSBkaXN0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tX3NvdXJjZSA9IG91dHB1dDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHduZXh0IDwgb3ApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb20gKz0gd3NpemUgKyB3bmV4dCAtIG9wOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3AgLT0gd25leHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3AgPCBsZW4pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuIC09IG9wOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBzX3dpbmRvd1tmcm9tKytdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IHdoaWxlICgtLW9wKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3bmV4dCA8IGxlbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wID0gd25leHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuIC09IG9wOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gc193aW5kb3dbZnJvbSsrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IHdoaWxlICgtLW9wKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tID0gX291dCAtIGRpc3Q7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbV9zb3VyY2UgPSBvdXRwdXQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbSArPSB3bmV4dCAtIG9wOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wIDwgbGVuKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbiAtPSBvcDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gc193aW5kb3dbZnJvbSsrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSB3aGlsZSAoLS1vcCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb20gPSBfb3V0IC0gZGlzdDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbV9zb3VyY2UgPSBvdXRwdXQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChsZW4gPiAyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IGZyb21fc291cmNlW2Zyb20rK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IGZyb21fc291cmNlW2Zyb20rK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IGZyb21fc291cmNlW2Zyb20rK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW4gLT0gMzsKICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxlbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBmcm9tX3NvdXJjZVtmcm9tKytdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxlbiA+IDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBmcm9tX3NvdXJjZVtmcm9tKytdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tID0gX291dCAtIGRpc3Q7CiAgICAgICAgICAgICAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBvdXRwdXRbZnJvbSsrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gb3V0cHV0W2Zyb20rK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IG91dHB1dFtmcm9tKytdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuIC09IDM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgfSB3aGlsZSAobGVuID4gMik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxlbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBvdXRwdXRbZnJvbSsrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsZW4gPiAxKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gb3V0cHV0W2Zyb20rK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChvcCAmIDY0KSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICBoZXJlID0gZGNvZGVbKGhlcmUgJiA2NTUzNSkgKyAoaG9sZCAmICgxIDw8IG9wKSAtIDEpXTsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWUgZG9kaXN0OwogICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3RybS5tc2cgPSAiaW52YWxpZCBkaXN0YW5jZSBjb2RlIjsKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgdG9wOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSBlbHNlIGlmICgob3AgJiA2NCkgPT09IDApIHsKICAgICAgICAgICAgICAgICAgaGVyZSA9IGxjb2RlWyhoZXJlICYgNjU1MzUpICsgKGhvbGQgJiAoMSA8PCBvcCkgLSAxKV07CiAgICAgICAgICAgICAgICAgIGNvbnRpbnVlIGRvbGVuOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvcCAmIDMyKSB7CiAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBUWVBFOwogICAgICAgICAgICAgICAgICBicmVhayB0b3A7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJpbnZhbGlkIGxpdGVyYWwvbGVuZ3RoIGNvZGUiOwogICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEOwogICAgICAgICAgICAgICAgICBicmVhayB0b3A7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICB9IHdoaWxlIChfaW4gPCBsYXN0ICYmIF9vdXQgPCBlbmQpOwogICAgICAgIGxlbiA9IGJpdHMgPj4gMzsKICAgICAgICBfaW4gLT0gbGVuOwogICAgICAgIGJpdHMgLT0gbGVuIDw8IDM7CiAgICAgICAgaG9sZCAmPSAoMSA8PCBiaXRzKSAtIDE7CiAgICAgICAgc3RybS5uZXh0X2luID0gX2luOwogICAgICAgIHN0cm0ubmV4dF9vdXQgPSBfb3V0OwogICAgICAgIHN0cm0uYXZhaWxfaW4gPSBfaW4gPCBsYXN0ID8gNSArIChsYXN0IC0gX2luKSA6IDUgLSAoX2luIC0gbGFzdCk7CiAgICAgICAgc3RybS5hdmFpbF9vdXQgPSBfb3V0IDwgZW5kID8gMjU3ICsgKGVuZCAtIF9vdXQpIDogMjU3IC0gKF9vdXQgLSBlbmQpOwogICAgICAgIHN0YXRlLmhvbGQgPSBob2xkOwogICAgICAgIHN0YXRlLmJpdHMgPSBiaXRzOwogICAgICAgIHJldHVybjsKICAgICAgfTsKICAgIH0KICB9KTsKCiAgLy8gbm9kZV9tb2R1bGVzL3Bha28vbGliL3psaWIvaW5mdHJlZXMuanMKICB2YXIgcmVxdWlyZV9pbmZ0cmVlcyA9IF9fY29tbW9uSlMoewogICAgIm5vZGVfbW9kdWxlcy9wYWtvL2xpYi96bGliL2luZnRyZWVzLmpzIihleHBvcnRzMiwgbW9kdWxlKSB7CiAgICAgICJ1c2Ugc3RyaWN0IjsKICAgICAgdmFyIE1BWEJJVFMgPSAxNTsKICAgICAgdmFyIEVOT1VHSF9MRU5TID0gODUyOwogICAgICB2YXIgRU5PVUdIX0RJU1RTID0gNTkyOwogICAgICB2YXIgQ09ERVMgPSAwOwogICAgICB2YXIgTEVOUyA9IDE7CiAgICAgIHZhciBESVNUUyA9IDI7CiAgICAgIHZhciBsYmFzZSA9IG5ldyBVaW50MTZBcnJheShbCiAgICAgICAgLyogTGVuZ3RoIGNvZGVzIDI1Ny4uMjg1IGJhc2UgKi8KICAgICAgICAzLAogICAgICAgIDQsCiAgICAgICAgNSwKICAgICAgICA2LAogICAgICAgIDcsCiAgICAgICAgOCwKICAgICAgICA5LAogICAgICAgIDEwLAogICAgICAgIDExLAogICAgICAgIDEzLAogICAgICAgIDE1LAogICAgICAgIDE3LAogICAgICAgIDE5LAogICAgICAgIDIzLAogICAgICAgIDI3LAogICAgICAgIDMxLAogICAgICAgIDM1LAogICAgICAgIDQzLAogICAgICAgIDUxLAogICAgICAgIDU5LAogICAgICAgIDY3LAogICAgICAgIDgzLAogICAgICAgIDk5LAogICAgICAgIDExNSwKICAgICAgICAxMzEsCiAgICAgICAgMTYzLAogICAgICAgIDE5NSwKICAgICAgICAyMjcsCiAgICAgICAgMjU4LAogICAgICAgIDAsCiAgICAgICAgMAogICAgICBdKTsKICAgICAgdmFyIGxleHQgPSBuZXcgVWludDhBcnJheShbCiAgICAgICAgLyogTGVuZ3RoIGNvZGVzIDI1Ny4uMjg1IGV4dHJhICovCiAgICAgICAgMTYsCiAgICAgICAgMTYsCiAgICAgICAgMTYsCiAgICAgICAgMTYsCiAgICAgICAgMTYsCiAgICAgICAgMTYsCiAgICAgICAgMTYsCiAgICAgICAgMTYsCiAgICAgICAgMTcsCiAgICAgICAgMTcsCiAgICAgICAgMTcsCiAgICAgICAgMTcsCiAgICAgICAgMTgsCiAgICAgICAgMTgsCiAgICAgICAgMTgsCiAgICAgICAgMTgsCiAgICAgICAgMTksCiAgICAgICAgMTksCiAgICAgICAgMTksCiAgICAgICAgMTksCiAgICAgICAgMjAsCiAgICAgICAgMjAsCiAgICAgICAgMjAsCiAgICAgICAgMjAsCiAgICAgICAgMjEsCiAgICAgICAgMjEsCiAgICAgICAgMjEsCiAgICAgICAgMjEsCiAgICAgICAgMTYsCiAgICAgICAgNzIsCiAgICAgICAgNzgKICAgICAgXSk7CiAgICAgIHZhciBkYmFzZSA9IG5ldyBVaW50MTZBcnJheShbCiAgICAgICAgLyogRGlzdGFuY2UgY29kZXMgMC4uMjkgYmFzZSAqLwogICAgICAgIDEsCiAgICAgICAgMiwKICAgICAgICAzLAogICAgICAgIDQsCiAgICAgICAgNSwKICAgICAgICA3LAogICAgICAgIDksCiAgICAgICAgMTMsCiAgICAgICAgMTcsCiAgICAgICAgMjUsCiAgICAgICAgMzMsCiAgICAgICAgNDksCiAgICAgICAgNjUsCiAgICAgICAgOTcsCiAgICAgICAgMTI5LAogICAgICAgIDE5MywKICAgICAgICAyNTcsCiAgICAgICAgMzg1LAogICAgICAgIDUxMywKICAgICAgICA3NjksCiAgICAgICAgMTAyNSwKICAgICAgICAxNTM3LAogICAgICAgIDIwNDksCiAgICAgICAgMzA3MywKICAgICAgICA0MDk3LAogICAgICAgIDYxNDUsCiAgICAgICAgODE5MywKICAgICAgICAxMjI4OSwKICAgICAgICAxNjM4NSwKICAgICAgICAyNDU3NywKICAgICAgICAwLAogICAgICAgIDAKICAgICAgXSk7CiAgICAgIHZhciBkZXh0ID0gbmV3IFVpbnQ4QXJyYXkoWwogICAgICAgIC8qIERpc3RhbmNlIGNvZGVzIDAuLjI5IGV4dHJhICovCiAgICAgICAgMTYsCiAgICAgICAgMTYsCiAgICAgICAgMTYsCiAgICAgICAgMTYsCiAgICAgICAgMTcsCiAgICAgICAgMTcsCiAgICAgICAgMTgsCiAgICAgICAgMTgsCiAgICAgICAgMTksCiAgICAgICAgMTksCiAgICAgICAgMjAsCiAgICAgICAgMjAsCiAgICAgICAgMjEsCiAgICAgICAgMjEsCiAgICAgICAgMjIsCiAgICAgICAgMjIsCiAgICAgICAgMjMsCiAgICAgICAgMjMsCiAgICAgICAgMjQsCiAgICAgICAgMjQsCiAgICAgICAgMjUsCiAgICAgICAgMjUsCiAgICAgICAgMjYsCiAgICAgICAgMjYsCiAgICAgICAgMjcsCiAgICAgICAgMjcsCiAgICAgICAgMjgsCiAgICAgICAgMjgsCiAgICAgICAgMjksCiAgICAgICAgMjksCiAgICAgICAgNjQsCiAgICAgICAgNjQKICAgICAgXSk7CiAgICAgIHZhciBpbmZsYXRlX3RhYmxlID0gKHR5cGUsIGxlbnMsIGxlbnNfaW5kZXgsIGNvZGVzLCB0YWJsZSwgdGFibGVfaW5kZXgsIHdvcmssIG9wdHMpID0+IHsKICAgICAgICBjb25zdCBiaXRzID0gb3B0cy5iaXRzOwogICAgICAgIGxldCBsZW4gPSAwOwogICAgICAgIGxldCBzeW0gPSAwOwogICAgICAgIGxldCBtaW4zID0gMCwgbWF4MyA9IDA7CiAgICAgICAgbGV0IHJvb3QgPSAwOwogICAgICAgIGxldCBjdXJyID0gMDsKICAgICAgICBsZXQgZHJvcCA9IDA7CiAgICAgICAgbGV0IGxlZnQgPSAwOwogICAgICAgIGxldCB1c2VkID0gMDsKICAgICAgICBsZXQgaHVmZiA9IDA7CiAgICAgICAgbGV0IGluY3I7CiAgICAgICAgbGV0IGZpbGw7CiAgICAgICAgbGV0IGxvdzsKICAgICAgICBsZXQgbWFzazsKICAgICAgICBsZXQgbmV4dDsKICAgICAgICBsZXQgYmFzZSA9IG51bGw7CiAgICAgICAgbGV0IG1hdGNoOwogICAgICAgIGNvbnN0IGNvdW50ID0gbmV3IFVpbnQxNkFycmF5KE1BWEJJVFMgKyAxKTsKICAgICAgICBjb25zdCBvZmZzID0gbmV3IFVpbnQxNkFycmF5KE1BWEJJVFMgKyAxKTsKICAgICAgICBsZXQgZXh0cmEgPSBudWxsOwogICAgICAgIGxldCBoZXJlX2JpdHMsIGhlcmVfb3AsIGhlcmVfdmFsOwogICAgICAgIGZvciAobGVuID0gMDsgbGVuIDw9IE1BWEJJVFM7IGxlbisrKSB7CiAgICAgICAgICBjb3VudFtsZW5dID0gMDsKICAgICAgICB9CiAgICAgICAgZm9yIChzeW0gPSAwOyBzeW0gPCBjb2Rlczsgc3ltKyspIHsKICAgICAgICAgIGNvdW50W2xlbnNbbGVuc19pbmRleCArIHN5bV1dKys7CiAgICAgICAgfQogICAgICAgIHJvb3QgPSBiaXRzOwogICAgICAgIGZvciAobWF4MyA9IE1BWEJJVFM7IG1heDMgPj0gMTsgbWF4My0tKSB7CiAgICAgICAgICBpZiAoY291bnRbbWF4M10gIT09IDApIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChyb290ID4gbWF4MykgewogICAgICAgICAgcm9vdCA9IG1heDM7CiAgICAgICAgfQogICAgICAgIGlmIChtYXgzID09PSAwKSB7CiAgICAgICAgICB0YWJsZVt0YWJsZV9pbmRleCsrXSA9IDEgPDwgMjQgfCA2NCA8PCAxNiB8IDA7CiAgICAgICAgICB0YWJsZVt0YWJsZV9pbmRleCsrXSA9IDEgPDwgMjQgfCA2NCA8PCAxNiB8IDA7CiAgICAgICAgICBvcHRzLmJpdHMgPSAxOwogICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQogICAgICAgIGZvciAobWluMyA9IDE7IG1pbjMgPCBtYXgzOyBtaW4zKyspIHsKICAgICAgICAgIGlmIChjb3VudFttaW4zXSAhPT0gMCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHJvb3QgPCBtaW4zKSB7CiAgICAgICAgICByb290ID0gbWluMzsKICAgICAgICB9CiAgICAgICAgbGVmdCA9IDE7CiAgICAgICAgZm9yIChsZW4gPSAxOyBsZW4gPD0gTUFYQklUUzsgbGVuKyspIHsKICAgICAgICAgIGxlZnQgPDw9IDE7CiAgICAgICAgICBsZWZ0IC09IGNvdW50W2xlbl07CiAgICAgICAgICBpZiAobGVmdCA8IDApIHsKICAgICAgICAgICAgcmV0dXJuIC0xOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAobGVmdCA+IDAgJiYgKHR5cGUgPT09IENPREVTIHx8IG1heDMgIT09IDEpKSB7CiAgICAgICAgICByZXR1cm4gLTE7CiAgICAgICAgfQogICAgICAgIG9mZnNbMV0gPSAwOwogICAgICAgIGZvciAobGVuID0gMTsgbGVuIDwgTUFYQklUUzsgbGVuKyspIHsKICAgICAgICAgIG9mZnNbbGVuICsgMV0gPSBvZmZzW2xlbl0gKyBjb3VudFtsZW5dOwogICAgICAgIH0KICAgICAgICBmb3IgKHN5bSA9IDA7IHN5bSA8IGNvZGVzOyBzeW0rKykgewogICAgICAgICAgaWYgKGxlbnNbbGVuc19pbmRleCArIHN5bV0gIT09IDApIHsKICAgICAgICAgICAgd29ya1tvZmZzW2xlbnNbbGVuc19pbmRleCArIHN5bV1dKytdID0gc3ltOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAodHlwZSA9PT0gQ09ERVMpIHsKICAgICAgICAgIGJhc2UgPSBleHRyYSA9IHdvcms7CiAgICAgICAgICBtYXRjaCA9IDIwOwogICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gTEVOUykgewogICAgICAgICAgYmFzZSA9IGxiYXNlOwogICAgICAgICAgZXh0cmEgPSBsZXh0OwogICAgICAgICAgbWF0Y2ggPSAyNTc7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGJhc2UgPSBkYmFzZTsKICAgICAgICAgIGV4dHJhID0gZGV4dDsKICAgICAgICAgIG1hdGNoID0gMDsKICAgICAgICB9CiAgICAgICAgaHVmZiA9IDA7CiAgICAgICAgc3ltID0gMDsKICAgICAgICBsZW4gPSBtaW4zOwogICAgICAgIG5leHQgPSB0YWJsZV9pbmRleDsKICAgICAgICBjdXJyID0gcm9vdDsKICAgICAgICBkcm9wID0gMDsKICAgICAgICBsb3cgPSAtMTsKICAgICAgICB1c2VkID0gMSA8PCByb290OwogICAgICAgIG1hc2sgPSB1c2VkIC0gMTsKICAgICAgICBpZiAodHlwZSA9PT0gTEVOUyAmJiB1c2VkID4gRU5PVUdIX0xFTlMgfHwgdHlwZSA9PT0gRElTVFMgJiYgdXNlZCA+IEVOT1VHSF9ESVNUUykgewogICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfQogICAgICAgIGZvciAoOyA7ICkgewogICAgICAgICAgaGVyZV9iaXRzID0gbGVuIC0gZHJvcDsKICAgICAgICAgIGlmICh3b3JrW3N5bV0gKyAxIDwgbWF0Y2gpIHsKICAgICAgICAgICAgaGVyZV9vcCA9IDA7CiAgICAgICAgICAgIGhlcmVfdmFsID0gd29ya1tzeW1dOwogICAgICAgICAgfSBlbHNlIGlmICh3b3JrW3N5bV0gPj0gbWF0Y2gpIHsKICAgICAgICAgICAgaGVyZV9vcCA9IGV4dHJhW3dvcmtbc3ltXSAtIG1hdGNoXTsKICAgICAgICAgICAgaGVyZV92YWwgPSBiYXNlW3dvcmtbc3ltXSAtIG1hdGNoXTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGhlcmVfb3AgPSAzMiArIDY0OwogICAgICAgICAgICBoZXJlX3ZhbCA9IDA7CiAgICAgICAgICB9CiAgICAgICAgICBpbmNyID0gMSA8PCBsZW4gLSBkcm9wOwogICAgICAgICAgZmlsbCA9IDEgPDwgY3VycjsKICAgICAgICAgIG1pbjMgPSBmaWxsOwogICAgICAgICAgZG8gewogICAgICAgICAgICBmaWxsIC09IGluY3I7CiAgICAgICAgICAgIHRhYmxlW25leHQgKyAoaHVmZiA+PiBkcm9wKSArIGZpbGxdID0gaGVyZV9iaXRzIDw8IDI0IHwgaGVyZV9vcCA8PCAxNiB8IGhlcmVfdmFsIHwgMDsKICAgICAgICAgIH0gd2hpbGUgKGZpbGwgIT09IDApOwogICAgICAgICAgaW5jciA9IDEgPDwgbGVuIC0gMTsKICAgICAgICAgIHdoaWxlIChodWZmICYgaW5jcikgewogICAgICAgICAgICBpbmNyID4+PSAxOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGluY3IgIT09IDApIHsKICAgICAgICAgICAgaHVmZiAmPSBpbmNyIC0gMTsKICAgICAgICAgICAgaHVmZiArPSBpbmNyOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaHVmZiA9IDA7CiAgICAgICAgICB9CiAgICAgICAgICBzeW0rKzsKICAgICAgICAgIGlmICgtLWNvdW50W2xlbl0gPT09IDApIHsKICAgICAgICAgICAgaWYgKGxlbiA9PT0gbWF4MykgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxlbiA9IGxlbnNbbGVuc19pbmRleCArIHdvcmtbc3ltXV07CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobGVuID4gcm9vdCAmJiAoaHVmZiAmIG1hc2spICE9PSBsb3cpIHsKICAgICAgICAgICAgaWYgKGRyb3AgPT09IDApIHsKICAgICAgICAgICAgICBkcm9wID0gcm9vdDsKICAgICAgICAgICAgfQogICAgICAgICAgICBuZXh0ICs9IG1pbjM7CiAgICAgICAgICAgIGN1cnIgPSBsZW4gLSBkcm9wOwogICAgICAgICAgICBsZWZ0ID0gMSA8PCBjdXJyOwogICAgICAgICAgICB3aGlsZSAoY3VyciArIGRyb3AgPCBtYXgzKSB7CiAgICAgICAgICAgICAgbGVmdCAtPSBjb3VudFtjdXJyICsgZHJvcF07CiAgICAgICAgICAgICAgaWYgKGxlZnQgPD0gMCkgewogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGN1cnIrKzsKICAgICAgICAgICAgICBsZWZ0IDw8PSAxOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHVzZWQgKz0gMSA8PCBjdXJyOwogICAgICAgICAgICBpZiAodHlwZSA9PT0gTEVOUyAmJiB1c2VkID4gRU5PVUdIX0xFTlMgfHwgdHlwZSA9PT0gRElTVFMgJiYgdXNlZCA+IEVOT1VHSF9ESVNUUykgewogICAgICAgICAgICAgIHJldHVybiAxOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxvdyA9IGh1ZmYgJiBtYXNrOwogICAgICAgICAgICB0YWJsZVtsb3ddID0gcm9vdCA8PCAyNCB8IGN1cnIgPDwgMTYgfCBuZXh0IC0gdGFibGVfaW5kZXggfCAwOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoaHVmZiAhPT0gMCkgewogICAgICAgICAgdGFibGVbbmV4dCArIGh1ZmZdID0gbGVuIC0gZHJvcCA8PCAyNCB8IDY0IDw8IDE2IHwgMDsKICAgICAgICB9CiAgICAgICAgb3B0cy5iaXRzID0gcm9vdDsKICAgICAgICByZXR1cm4gMDsKICAgICAgfTsKICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpbmZsYXRlX3RhYmxlOwogICAgfQogIH0pOwoKICAvLyBub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9jb25zdGFudHMuanMKICB2YXIgcmVxdWlyZV9jb25zdGFudHMgPSBfX2NvbW1vbkpTKHsKICAgICJub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9jb25zdGFudHMuanMiKGV4cG9ydHMyLCBtb2R1bGUpIHsKICAgICAgInVzZSBzdHJpY3QiOwogICAgICBtb2R1bGUuZXhwb3J0cyA9IHsKICAgICAgICAvKiBBbGxvd2VkIGZsdXNoIHZhbHVlczsgc2VlIGRlZmxhdGUoKSBhbmQgaW5mbGF0ZSgpIGJlbG93IGZvciBkZXRhaWxzICovCiAgICAgICAgWl9OT19GTFVTSDogMCwKICAgICAgICBaX1BBUlRJQUxfRkxVU0g6IDEsCiAgICAgICAgWl9TWU5DX0ZMVVNIOiAyLAogICAgICAgIFpfRlVMTF9GTFVTSDogMywKICAgICAgICBaX0ZJTklTSDogNCwKICAgICAgICBaX0JMT0NLOiA1LAogICAgICAgIFpfVFJFRVM6IDYsCiAgICAgICAgLyogUmV0dXJuIGNvZGVzIGZvciB0aGUgY29tcHJlc3Npb24vZGVjb21wcmVzc2lvbiBmdW5jdGlvbnMuIE5lZ2F0aXZlIHZhbHVlcwogICAgICAgICogYXJlIGVycm9ycywgcG9zaXRpdmUgdmFsdWVzIGFyZSB1c2VkIGZvciBzcGVjaWFsIGJ1dCBub3JtYWwgZXZlbnRzLgogICAgICAgICovCiAgICAgICAgWl9PSzogMCwKICAgICAgICBaX1NUUkVBTV9FTkQ6IDEsCiAgICAgICAgWl9ORUVEX0RJQ1Q6IDIsCiAgICAgICAgWl9FUlJOTzogLTEsCiAgICAgICAgWl9TVFJFQU1fRVJST1I6IC0yLAogICAgICAgIFpfREFUQV9FUlJPUjogLTMsCiAgICAgICAgWl9NRU1fRVJST1I6IC00LAogICAgICAgIFpfQlVGX0VSUk9SOiAtNSwKICAgICAgICAvL1pfVkVSU0lPTl9FUlJPUjogLTYsCiAgICAgICAgLyogY29tcHJlc3Npb24gbGV2ZWxzICovCiAgICAgICAgWl9OT19DT01QUkVTU0lPTjogMCwKICAgICAgICBaX0JFU1RfU1BFRUQ6IDEsCiAgICAgICAgWl9CRVNUX0NPTVBSRVNTSU9OOiA5LAogICAgICAgIFpfREVGQVVMVF9DT01QUkVTU0lPTjogLTEsCiAgICAgICAgWl9GSUxURVJFRDogMSwKICAgICAgICBaX0hVRkZNQU5fT05MWTogMiwKICAgICAgICBaX1JMRTogMywKICAgICAgICBaX0ZJWEVEOiA0LAogICAgICAgIFpfREVGQVVMVF9TVFJBVEVHWTogMCwKICAgICAgICAvKiBQb3NzaWJsZSB2YWx1ZXMgb2YgdGhlIGRhdGFfdHlwZSBmaWVsZCAodGhvdWdoIHNlZSBpbmZsYXRlKCkpICovCiAgICAgICAgWl9CSU5BUlk6IDAsCiAgICAgICAgWl9URVhUOiAxLAogICAgICAgIC8vWl9BU0NJSTogICAgICAgICAgICAgICAgMSwgLy8gPSBaX1RFWFQgKGRlcHJlY2F0ZWQpCiAgICAgICAgWl9VTktOT1dOOiAyLAogICAgICAgIC8qIFRoZSBkZWZsYXRlIGNvbXByZXNzaW9uIG1ldGhvZCAqLwogICAgICAgIFpfREVGTEFURUQ6IDgKICAgICAgICAvL1pfTlVMTDogICAgICAgICAgICAgICAgIG51bGwgLy8gVXNlIC0xIG9yIG51bGwgaW5saW5lLCBkZXBlbmRpbmcgb24gdmFyIHR5cGUKICAgICAgfTsKICAgIH0KICB9KTsKCiAgLy8gbm9kZV9tb2R1bGVzL3Bha28vbGliL3psaWIvaW5mbGF0ZS5qcwogIHZhciByZXF1aXJlX2luZmxhdGUgPSBfX2NvbW1vbkpTKHsKICAgICJub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9pbmZsYXRlLmpzIihleHBvcnRzMiwgbW9kdWxlKSB7CiAgICAgICJ1c2Ugc3RyaWN0IjsKICAgICAgdmFyIGFkbGVyMzIgPSByZXF1aXJlX2FkbGVyMzIoKTsKICAgICAgdmFyIGNyYzMyID0gcmVxdWlyZV9jcmMzMigpOwogICAgICB2YXIgaW5mbGF0ZV9mYXN0ID0gcmVxdWlyZV9pbmZmYXN0KCk7CiAgICAgIHZhciBpbmZsYXRlX3RhYmxlID0gcmVxdWlyZV9pbmZ0cmVlcygpOwogICAgICB2YXIgQ09ERVMgPSAwOwogICAgICB2YXIgTEVOUyA9IDE7CiAgICAgIHZhciBESVNUUyA9IDI7CiAgICAgIHZhciB7CiAgICAgICAgWl9GSU5JU0gsCiAgICAgICAgWl9CTE9DSywKICAgICAgICBaX1RSRUVTLAogICAgICAgIFpfT0ssCiAgICAgICAgWl9TVFJFQU1fRU5ELAogICAgICAgIFpfTkVFRF9ESUNULAogICAgICAgIFpfU1RSRUFNX0VSUk9SLAogICAgICAgIFpfREFUQV9FUlJPUiwKICAgICAgICBaX01FTV9FUlJPUiwKICAgICAgICBaX0JVRl9FUlJPUiwKICAgICAgICBaX0RFRkxBVEVECiAgICAgIH0gPSByZXF1aXJlX2NvbnN0YW50cygpOwogICAgICB2YXIgSEVBRCA9IDE2MTgwOwogICAgICB2YXIgRkxBR1MgPSAxNjE4MTsKICAgICAgdmFyIFRJTUUgPSAxNjE4MjsKICAgICAgdmFyIE9TID0gMTYxODM7CiAgICAgIHZhciBFWExFTiA9IDE2MTg0OwogICAgICB2YXIgRVhUUkEgPSAxNjE4NTsKICAgICAgdmFyIE5BTUUgPSAxNjE4NjsKICAgICAgdmFyIENPTU1FTlQgPSAxNjE4NzsKICAgICAgdmFyIEhDUkMgPSAxNjE4ODsKICAgICAgdmFyIERJQ1RJRCA9IDE2MTg5OwogICAgICB2YXIgRElDVCA9IDE2MTkwOwogICAgICB2YXIgVFlQRSA9IDE2MTkxOwogICAgICB2YXIgVFlQRURPID0gMTYxOTI7CiAgICAgIHZhciBTVE9SRUQgPSAxNjE5MzsKICAgICAgdmFyIENPUFlfID0gMTYxOTQ7CiAgICAgIHZhciBDT1BZID0gMTYxOTU7CiAgICAgIHZhciBUQUJMRSA9IDE2MTk2OwogICAgICB2YXIgTEVOTEVOUyA9IDE2MTk3OwogICAgICB2YXIgQ09ERUxFTlMgPSAxNjE5ODsKICAgICAgdmFyIExFTl8gPSAxNjE5OTsKICAgICAgdmFyIExFTiA9IDE2MjAwOwogICAgICB2YXIgTEVORVhUID0gMTYyMDE7CiAgICAgIHZhciBESVNUID0gMTYyMDI7CiAgICAgIHZhciBESVNURVhUID0gMTYyMDM7CiAgICAgIHZhciBNQVRDSCA9IDE2MjA0OwogICAgICB2YXIgTElUID0gMTYyMDU7CiAgICAgIHZhciBDSEVDSyA9IDE2MjA2OwogICAgICB2YXIgTEVOR1RIID0gMTYyMDc7CiAgICAgIHZhciBET05FID0gMTYyMDg7CiAgICAgIHZhciBCQUQgPSAxNjIwOTsKICAgICAgdmFyIE1FTSA9IDE2MjEwOwogICAgICB2YXIgU1lOQyA9IDE2MjExOwogICAgICB2YXIgRU5PVUdIX0xFTlMgPSA4NTI7CiAgICAgIHZhciBFTk9VR0hfRElTVFMgPSA1OTI7CiAgICAgIHZhciBNQVhfV0JJVFMgPSAxNTsKICAgICAgdmFyIERFRl9XQklUUyA9IE1BWF9XQklUUzsKICAgICAgdmFyIHpzd2FwMzIgPSAocSkgPT4gewogICAgICAgIHJldHVybiAocSA+Pj4gMjQgJiAyNTUpICsgKHEgPj4+IDggJiA2NTI4MCkgKyAoKHEgJiA2NTI4MCkgPDwgOCkgKyAoKHEgJiAyNTUpIDw8IDI0KTsKICAgICAgfTsKICAgICAgZnVuY3Rpb24gSW5mbGF0ZVN0YXRlKCkgewogICAgICAgIHRoaXMuc3RybSA9IG51bGw7CiAgICAgICAgdGhpcy5tb2RlID0gMDsKICAgICAgICB0aGlzLmxhc3QgPSBmYWxzZTsKICAgICAgICB0aGlzLndyYXAgPSAwOwogICAgICAgIHRoaXMuaGF2ZWRpY3QgPSBmYWxzZTsKICAgICAgICB0aGlzLmZsYWdzID0gMDsKICAgICAgICB0aGlzLmRtYXggPSAwOwogICAgICAgIHRoaXMuY2hlY2sgPSAwOwogICAgICAgIHRoaXMudG90YWwgPSAwOwogICAgICAgIHRoaXMuaGVhZCA9IG51bGw7CiAgICAgICAgdGhpcy53Yml0cyA9IDA7CiAgICAgICAgdGhpcy53c2l6ZSA9IDA7CiAgICAgICAgdGhpcy53aGF2ZSA9IDA7CiAgICAgICAgdGhpcy53bmV4dCA9IDA7CiAgICAgICAgdGhpcy53aW5kb3cgPSBudWxsOwogICAgICAgIHRoaXMuaG9sZCA9IDA7CiAgICAgICAgdGhpcy5iaXRzID0gMDsKICAgICAgICB0aGlzLmxlbmd0aCA9IDA7CiAgICAgICAgdGhpcy5vZmZzZXQgPSAwOwogICAgICAgIHRoaXMuZXh0cmEgPSAwOwogICAgICAgIHRoaXMubGVuY29kZSA9IG51bGw7CiAgICAgICAgdGhpcy5kaXN0Y29kZSA9IG51bGw7CiAgICAgICAgdGhpcy5sZW5iaXRzID0gMDsKICAgICAgICB0aGlzLmRpc3RiaXRzID0gMDsKICAgICAgICB0aGlzLm5jb2RlID0gMDsKICAgICAgICB0aGlzLm5sZW4gPSAwOwogICAgICAgIHRoaXMubmRpc3QgPSAwOwogICAgICAgIHRoaXMuaGF2ZSA9IDA7CiAgICAgICAgdGhpcy5uZXh0ID0gbnVsbDsKICAgICAgICB0aGlzLmxlbnMgPSBuZXcgVWludDE2QXJyYXkoMzIwKTsKICAgICAgICB0aGlzLndvcmsgPSBuZXcgVWludDE2QXJyYXkoMjg4KTsKICAgICAgICB0aGlzLmxlbmR5biA9IG51bGw7CiAgICAgICAgdGhpcy5kaXN0ZHluID0gbnVsbDsKICAgICAgICB0aGlzLnNhbmUgPSAwOwogICAgICAgIHRoaXMuYmFjayA9IDA7CiAgICAgICAgdGhpcy53YXMgPSAwOwogICAgICB9CiAgICAgIHZhciBpbmZsYXRlU3RhdGVDaGVjayA9IChzdHJtKSA9PiB7CiAgICAgICAgaWYgKCFzdHJtKSB7CiAgICAgICAgICByZXR1cm4gMTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc3RhdGUgPSBzdHJtLnN0YXRlOwogICAgICAgIGlmICghc3RhdGUgfHwgc3RhdGUuc3RybSAhPT0gc3RybSB8fCBzdGF0ZS5tb2RlIDwgSEVBRCB8fCBzdGF0ZS5tb2RlID4gU1lOQykgewogICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfQogICAgICAgIHJldHVybiAwOwogICAgICB9OwogICAgICB2YXIgaW5mbGF0ZVJlc2V0S2VlcCA9IChzdHJtKSA9PiB7CiAgICAgICAgaWYgKGluZmxhdGVTdGF0ZUNoZWNrKHN0cm0pKSB7CiAgICAgICAgICByZXR1cm4gWl9TVFJFQU1fRVJST1I7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHN0YXRlID0gc3RybS5zdGF0ZTsKICAgICAgICBzdHJtLnRvdGFsX2luID0gc3RybS50b3RhbF9vdXQgPSBzdGF0ZS50b3RhbCA9IDA7CiAgICAgICAgc3RybS5tc2cgPSAiIjsKICAgICAgICBpZiAoc3RhdGUud3JhcCkgewogICAgICAgICAgc3RybS5hZGxlciA9IHN0YXRlLndyYXAgJiAxOwogICAgICAgIH0KICAgICAgICBzdGF0ZS5tb2RlID0gSEVBRDsKICAgICAgICBzdGF0ZS5sYXN0ID0gMDsKICAgICAgICBzdGF0ZS5oYXZlZGljdCA9IDA7CiAgICAgICAgc3RhdGUuZmxhZ3MgPSAtMTsKICAgICAgICBzdGF0ZS5kbWF4ID0gMzI3Njg7CiAgICAgICAgc3RhdGUuaGVhZCA9IG51bGw7CiAgICAgICAgc3RhdGUuaG9sZCA9IDA7CiAgICAgICAgc3RhdGUuYml0cyA9IDA7CiAgICAgICAgc3RhdGUubGVuY29kZSA9IHN0YXRlLmxlbmR5biA9IG5ldyBJbnQzMkFycmF5KEVOT1VHSF9MRU5TKTsKICAgICAgICBzdGF0ZS5kaXN0Y29kZSA9IHN0YXRlLmRpc3RkeW4gPSBuZXcgSW50MzJBcnJheShFTk9VR0hfRElTVFMpOwogICAgICAgIHN0YXRlLnNhbmUgPSAxOwogICAgICAgIHN0YXRlLmJhY2sgPSAtMTsKICAgICAgICByZXR1cm4gWl9PSzsKICAgICAgfTsKICAgICAgdmFyIGluZmxhdGVSZXNldCA9IChzdHJtKSA9PiB7CiAgICAgICAgaWYgKGluZmxhdGVTdGF0ZUNoZWNrKHN0cm0pKSB7CiAgICAgICAgICByZXR1cm4gWl9TVFJFQU1fRVJST1I7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHN0YXRlID0gc3RybS5zdGF0ZTsKICAgICAgICBzdGF0ZS53c2l6ZSA9IDA7CiAgICAgICAgc3RhdGUud2hhdmUgPSAwOwogICAgICAgIHN0YXRlLnduZXh0ID0gMDsKICAgICAgICByZXR1cm4gaW5mbGF0ZVJlc2V0S2VlcChzdHJtKTsKICAgICAgfTsKICAgICAgdmFyIGluZmxhdGVSZXNldDIgPSAoc3RybSwgd2luZG93Qml0cykgPT4gewogICAgICAgIGxldCB3cmFwOwogICAgICAgIGlmIChpbmZsYXRlU3RhdGVDaGVjayhzdHJtKSkgewogICAgICAgICAgcmV0dXJuIFpfU1RSRUFNX0VSUk9SOwogICAgICAgIH0KICAgICAgICBjb25zdCBzdGF0ZSA9IHN0cm0uc3RhdGU7CiAgICAgICAgaWYgKHdpbmRvd0JpdHMgPCAwKSB7CiAgICAgICAgICB3cmFwID0gMDsKICAgICAgICAgIHdpbmRvd0JpdHMgPSAtd2luZG93Qml0czsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgd3JhcCA9ICh3aW5kb3dCaXRzID4+IDQpICsgNTsKICAgICAgICAgIGlmICh3aW5kb3dCaXRzIDwgNDgpIHsKICAgICAgICAgICAgd2luZG93Qml0cyAmPSAxNTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHdpbmRvd0JpdHMgJiYgKHdpbmRvd0JpdHMgPCA4IHx8IHdpbmRvd0JpdHMgPiAxNSkpIHsKICAgICAgICAgIHJldHVybiBaX1NUUkVBTV9FUlJPUjsKICAgICAgICB9CiAgICAgICAgaWYgKHN0YXRlLndpbmRvdyAhPT0gbnVsbCAmJiBzdGF0ZS53Yml0cyAhPT0gd2luZG93Qml0cykgewogICAgICAgICAgc3RhdGUud2luZG93ID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgc3RhdGUud3JhcCA9IHdyYXA7CiAgICAgICAgc3RhdGUud2JpdHMgPSB3aW5kb3dCaXRzOwogICAgICAgIHJldHVybiBpbmZsYXRlUmVzZXQoc3RybSk7CiAgICAgIH07CiAgICAgIHZhciBpbmZsYXRlSW5pdDIgPSAoc3RybSwgd2luZG93Qml0cykgPT4gewogICAgICAgIGlmICghc3RybSkgewogICAgICAgICAgcmV0dXJuIFpfU1RSRUFNX0VSUk9SOwogICAgICAgIH0KICAgICAgICBjb25zdCBzdGF0ZSA9IG5ldyBJbmZsYXRlU3RhdGUoKTsKICAgICAgICBzdHJtLnN0YXRlID0gc3RhdGU7CiAgICAgICAgc3RhdGUuc3RybSA9IHN0cm07CiAgICAgICAgc3RhdGUud2luZG93ID0gbnVsbDsKICAgICAgICBzdGF0ZS5tb2RlID0gSEVBRDsKICAgICAgICBjb25zdCByZXQgPSBpbmZsYXRlUmVzZXQyKHN0cm0sIHdpbmRvd0JpdHMpOwogICAgICAgIGlmIChyZXQgIT09IFpfT0spIHsKICAgICAgICAgIHN0cm0uc3RhdGUgPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgICB9OwogICAgICB2YXIgaW5mbGF0ZUluaXQgPSAoc3RybSkgPT4gewogICAgICAgIHJldHVybiBpbmZsYXRlSW5pdDIoc3RybSwgREVGX1dCSVRTKTsKICAgICAgfTsKICAgICAgdmFyIHZpcmdpbiA9IHRydWU7CiAgICAgIHZhciBsZW5maXg7CiAgICAgIHZhciBkaXN0Zml4OwogICAgICB2YXIgZml4ZWR0YWJsZXMgPSAoc3RhdGUpID0+IHsKICAgICAgICBpZiAodmlyZ2luKSB7CiAgICAgICAgICBsZW5maXggPSBuZXcgSW50MzJBcnJheSg1MTIpOwogICAgICAgICAgZGlzdGZpeCA9IG5ldyBJbnQzMkFycmF5KDMyKTsKICAgICAgICAgIGxldCBzeW0gPSAwOwogICAgICAgICAgd2hpbGUgKHN5bSA8IDE0NCkgewogICAgICAgICAgICBzdGF0ZS5sZW5zW3N5bSsrXSA9IDg7CiAgICAgICAgICB9CiAgICAgICAgICB3aGlsZSAoc3ltIDwgMjU2KSB7CiAgICAgICAgICAgIHN0YXRlLmxlbnNbc3ltKytdID0gOTsKICAgICAgICAgIH0KICAgICAgICAgIHdoaWxlIChzeW0gPCAyODApIHsKICAgICAgICAgICAgc3RhdGUubGVuc1tzeW0rK10gPSA3OwogICAgICAgICAgfQogICAgICAgICAgd2hpbGUgKHN5bSA8IDI4OCkgewogICAgICAgICAgICBzdGF0ZS5sZW5zW3N5bSsrXSA9IDg7CiAgICAgICAgICB9CiAgICAgICAgICBpbmZsYXRlX3RhYmxlKExFTlMsIHN0YXRlLmxlbnMsIDAsIDI4OCwgbGVuZml4LCAwLCBzdGF0ZS53b3JrLCB7IGJpdHM6IDkgfSk7CiAgICAgICAgICBzeW0gPSAwOwogICAgICAgICAgd2hpbGUgKHN5bSA8IDMyKSB7CiAgICAgICAgICAgIHN0YXRlLmxlbnNbc3ltKytdID0gNTsKICAgICAgICAgIH0KICAgICAgICAgIGluZmxhdGVfdGFibGUoRElTVFMsIHN0YXRlLmxlbnMsIDAsIDMyLCBkaXN0Zml4LCAwLCBzdGF0ZS53b3JrLCB7IGJpdHM6IDUgfSk7CiAgICAgICAgICB2aXJnaW4gPSBmYWxzZTsKICAgICAgICB9CiAgICAgICAgc3RhdGUubGVuY29kZSA9IGxlbmZpeDsKICAgICAgICBzdGF0ZS5sZW5iaXRzID0gOTsKICAgICAgICBzdGF0ZS5kaXN0Y29kZSA9IGRpc3RmaXg7CiAgICAgICAgc3RhdGUuZGlzdGJpdHMgPSA1OwogICAgICB9OwogICAgICB2YXIgdXBkYXRld2luZG93ID0gKHN0cm0sIHNyYywgZW5kLCBjb3B5KSA9PiB7CiAgICAgICAgbGV0IGRpc3Q7CiAgICAgICAgY29uc3Qgc3RhdGUgPSBzdHJtLnN0YXRlOwogICAgICAgIGlmIChzdGF0ZS53aW5kb3cgPT09IG51bGwpIHsKICAgICAgICAgIHN0YXRlLndzaXplID0gMSA8PCBzdGF0ZS53Yml0czsKICAgICAgICAgIHN0YXRlLnduZXh0ID0gMDsKICAgICAgICAgIHN0YXRlLndoYXZlID0gMDsKICAgICAgICAgIHN0YXRlLndpbmRvdyA9IG5ldyBVaW50OEFycmF5KHN0YXRlLndzaXplKTsKICAgICAgICB9CiAgICAgICAgaWYgKGNvcHkgPj0gc3RhdGUud3NpemUpIHsKICAgICAgICAgIHN0YXRlLndpbmRvdy5zZXQoc3JjLnN1YmFycmF5KGVuZCAtIHN0YXRlLndzaXplLCBlbmQpLCAwKTsKICAgICAgICAgIHN0YXRlLnduZXh0ID0gMDsKICAgICAgICAgIHN0YXRlLndoYXZlID0gc3RhdGUud3NpemU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGRpc3QgPSBzdGF0ZS53c2l6ZSAtIHN0YXRlLnduZXh0OwogICAgICAgICAgaWYgKGRpc3QgPiBjb3B5KSB7CiAgICAgICAgICAgIGRpc3QgPSBjb3B5OwogICAgICAgICAgfQogICAgICAgICAgc3RhdGUud2luZG93LnNldChzcmMuc3ViYXJyYXkoZW5kIC0gY29weSwgZW5kIC0gY29weSArIGRpc3QpLCBzdGF0ZS53bmV4dCk7CiAgICAgICAgICBjb3B5IC09IGRpc3Q7CiAgICAgICAgICBpZiAoY29weSkgewogICAgICAgICAgICBzdGF0ZS53aW5kb3cuc2V0KHNyYy5zdWJhcnJheShlbmQgLSBjb3B5LCBlbmQpLCAwKTsKICAgICAgICAgICAgc3RhdGUud25leHQgPSBjb3B5OwogICAgICAgICAgICBzdGF0ZS53aGF2ZSA9IHN0YXRlLndzaXplOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RhdGUud25leHQgKz0gZGlzdDsKICAgICAgICAgICAgaWYgKHN0YXRlLnduZXh0ID09PSBzdGF0ZS53c2l6ZSkgewogICAgICAgICAgICAgIHN0YXRlLnduZXh0ID0gMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoc3RhdGUud2hhdmUgPCBzdGF0ZS53c2l6ZSkgewogICAgICAgICAgICAgIHN0YXRlLndoYXZlICs9IGRpc3Q7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIDA7CiAgICAgIH07CiAgICAgIHZhciBpbmZsYXRlID0gKHN0cm0sIGZsdXNoKSA9PiB7CiAgICAgICAgbGV0IHN0YXRlOwogICAgICAgIGxldCBpbnB1dCwgb3V0cHV0OwogICAgICAgIGxldCBuZXh0OwogICAgICAgIGxldCBwdXQ7CiAgICAgICAgbGV0IGhhdmUsIGxlZnQ7CiAgICAgICAgbGV0IGhvbGQ7CiAgICAgICAgbGV0IGJpdHM7CiAgICAgICAgbGV0IF9pbiwgX291dDsKICAgICAgICBsZXQgY29weTsKICAgICAgICBsZXQgZnJvbTsKICAgICAgICBsZXQgZnJvbV9zb3VyY2U7CiAgICAgICAgbGV0IGhlcmUgPSAwOwogICAgICAgIGxldCBoZXJlX2JpdHMsIGhlcmVfb3AsIGhlcmVfdmFsOwogICAgICAgIGxldCBsYXN0X2JpdHMsIGxhc3Rfb3AsIGxhc3RfdmFsOwogICAgICAgIGxldCBsZW47CiAgICAgICAgbGV0IHJldDsKICAgICAgICBjb25zdCBoYnVmID0gbmV3IFVpbnQ4QXJyYXkoNCk7CiAgICAgICAgbGV0IG9wdHM7CiAgICAgICAgbGV0IG47CiAgICAgICAgY29uc3Qgb3JkZXIgPSAoCiAgICAgICAgICAvKiBwZXJtdXRhdGlvbiBvZiBjb2RlIGxlbmd0aHMgKi8KICAgICAgICAgIG5ldyBVaW50OEFycmF5KFsxNiwgMTcsIDE4LCAwLCA4LCA3LCA5LCA2LCAxMCwgNSwgMTEsIDQsIDEyLCAzLCAxMywgMiwgMTQsIDEsIDE1XSkKICAgICAgICApOwogICAgICAgIGlmIChpbmZsYXRlU3RhdGVDaGVjayhzdHJtKSB8fCAhc3RybS5vdXRwdXQgfHwgIXN0cm0uaW5wdXQgJiYgc3RybS5hdmFpbF9pbiAhPT0gMCkgewogICAgICAgICAgcmV0dXJuIFpfU1RSRUFNX0VSUk9SOwogICAgICAgIH0KICAgICAgICBzdGF0ZSA9IHN0cm0uc3RhdGU7CiAgICAgICAgaWYgKHN0YXRlLm1vZGUgPT09IFRZUEUpIHsKICAgICAgICAgIHN0YXRlLm1vZGUgPSBUWVBFRE87CiAgICAgICAgfQogICAgICAgIHB1dCA9IHN0cm0ubmV4dF9vdXQ7CiAgICAgICAgb3V0cHV0ID0gc3RybS5vdXRwdXQ7CiAgICAgICAgbGVmdCA9IHN0cm0uYXZhaWxfb3V0OwogICAgICAgIG5leHQgPSBzdHJtLm5leHRfaW47CiAgICAgICAgaW5wdXQgPSBzdHJtLmlucHV0OwogICAgICAgIGhhdmUgPSBzdHJtLmF2YWlsX2luOwogICAgICAgIGhvbGQgPSBzdGF0ZS5ob2xkOwogICAgICAgIGJpdHMgPSBzdGF0ZS5iaXRzOwogICAgICAgIF9pbiA9IGhhdmU7CiAgICAgICAgX291dCA9IGxlZnQ7CiAgICAgICAgcmV0ID0gWl9PSzsKICAgICAgICBpbmZfbGVhdmU6CiAgICAgICAgICBmb3IgKDsgOyApIHsKICAgICAgICAgICAgc3dpdGNoIChzdGF0ZS5tb2RlKSB7CiAgICAgICAgICAgICAgY2FzZSBIRUFEOgogICAgICAgICAgICAgICAgaWYgKHN0YXRlLndyYXAgPT09IDApIHsKICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IFRZUEVETzsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB3aGlsZSAoYml0cyA8IDE2KSB7CiAgICAgICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGhhdmUtLTsKICAgICAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7CiAgICAgICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChzdGF0ZS53cmFwICYgMiAmJiBob2xkID09PSAzNTYxNSkgewogICAgICAgICAgICAgICAgICBpZiAoc3RhdGUud2JpdHMgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICBzdGF0ZS53Yml0cyA9IDE1OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHN0YXRlLmNoZWNrID0gMDsKICAgICAgICAgICAgICAgICAgaGJ1ZlswXSA9IGhvbGQgJiAyNTU7CiAgICAgICAgICAgICAgICAgIGhidWZbMV0gPSBob2xkID4+PiA4ICYgMjU1OwogICAgICAgICAgICAgICAgICBzdGF0ZS5jaGVjayA9IGNyYzMyKHN0YXRlLmNoZWNrLCBoYnVmLCAyLCAwKTsKICAgICAgICAgICAgICAgICAgaG9sZCA9IDA7CiAgICAgICAgICAgICAgICAgIGJpdHMgPSAwOwogICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gRkxBR1M7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHN0YXRlLmhlYWQpIHsKICAgICAgICAgICAgICAgICAgc3RhdGUuaGVhZC5kb25lID0gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoIShzdGF0ZS53cmFwICYgMSkgfHwgLyogY2hlY2sgaWYgemxpYiBoZWFkZXIgYWxsb3dlZCAqLwogICAgICAgICAgICAgICAgKCgoaG9sZCAmIDI1NSkgPDwgOCkgKyAoaG9sZCA+PiA4KSkgJSAzMSkgewogICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJpbmNvcnJlY3QgaGVhZGVyIGNoZWNrIjsKICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoKGhvbGQgJiAxNSkgIT09IFpfREVGTEFURUQpIHsKICAgICAgICAgICAgICAgICAgc3RybS5tc2cgPSAidW5rbm93biBjb21wcmVzc2lvbiBtZXRob2QiOwogICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGhvbGQgPj4+PSA0OwogICAgICAgICAgICAgICAgYml0cyAtPSA0OwogICAgICAgICAgICAgICAgbGVuID0gKGhvbGQgJiAxNSkgKyA4OwogICAgICAgICAgICAgICAgaWYgKHN0YXRlLndiaXRzID09PSAwKSB7CiAgICAgICAgICAgICAgICAgIHN0YXRlLndiaXRzID0gbGVuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKGxlbiA+IDE1IHx8IGxlbiA+IHN0YXRlLndiaXRzKSB7CiAgICAgICAgICAgICAgICAgIHN0cm0ubXNnID0gImludmFsaWQgd2luZG93IHNpemUiOwogICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHN0YXRlLmRtYXggPSAxIDw8IHN0YXRlLndiaXRzOwogICAgICAgICAgICAgICAgc3RhdGUuZmxhZ3MgPSAwOwogICAgICAgICAgICAgICAgc3RybS5hZGxlciA9IHN0YXRlLmNoZWNrID0gMTsKICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBob2xkICYgNTEyID8gRElDVElEIDogVFlQRTsKICAgICAgICAgICAgICAgIGhvbGQgPSAwOwogICAgICAgICAgICAgICAgYml0cyA9IDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIEZMQUdTOgogICAgICAgICAgICAgICAgd2hpbGUgKGJpdHMgPCAxNikgewogICAgICAgICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgIGJyZWFrIGluZl9sZWF2ZTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBoYXZlLS07CiAgICAgICAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzOwogICAgICAgICAgICAgICAgICBiaXRzICs9IDg7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdGF0ZS5mbGFncyA9IGhvbGQ7CiAgICAgICAgICAgICAgICBpZiAoKHN0YXRlLmZsYWdzICYgMjU1KSAhPT0gWl9ERUZMQVRFRCkgewogICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJ1bmtub3duIGNvbXByZXNzaW9uIG1ldGhvZCI7CiAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHN0YXRlLmZsYWdzICYgNTczNDQpIHsKICAgICAgICAgICAgICAgICAgc3RybS5tc2cgPSAidW5rbm93biBoZWFkZXIgZmxhZ3Mgc2V0IjsKICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoc3RhdGUuaGVhZCkgewogICAgICAgICAgICAgICAgICBzdGF0ZS5oZWFkLnRleHQgPSBob2xkID4+IDggJiAxOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHN0YXRlLmZsYWdzICYgNTEyICYmIHN0YXRlLndyYXAgJiA0KSB7CiAgICAgICAgICAgICAgICAgIGhidWZbMF0gPSBob2xkICYgMjU1OwogICAgICAgICAgICAgICAgICBoYnVmWzFdID0gaG9sZCA+Pj4gOCAmIDI1NTsKICAgICAgICAgICAgICAgICAgc3RhdGUuY2hlY2sgPSBjcmMzMihzdGF0ZS5jaGVjaywgaGJ1ZiwgMiwgMCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBob2xkID0gMDsKICAgICAgICAgICAgICAgIGJpdHMgPSAwOwogICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IFRJTUU7CiAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLwogICAgICAgICAgICAgIGNhc2UgVElNRToKICAgICAgICAgICAgICAgIHdoaWxlIChiaXRzIDwgMzIpIHsKICAgICAgICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaGF2ZS0tOwogICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0czsKICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHN0YXRlLmhlYWQpIHsKICAgICAgICAgICAgICAgICAgc3RhdGUuaGVhZC50aW1lID0gaG9sZDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5mbGFncyAmIDUxMiAmJiBzdGF0ZS53cmFwICYgNCkgewogICAgICAgICAgICAgICAgICBoYnVmWzBdID0gaG9sZCAmIDI1NTsKICAgICAgICAgICAgICAgICAgaGJ1ZlsxXSA9IGhvbGQgPj4+IDggJiAyNTU7CiAgICAgICAgICAgICAgICAgIGhidWZbMl0gPSBob2xkID4+PiAxNiAmIDI1NTsKICAgICAgICAgICAgICAgICAgaGJ1ZlszXSA9IGhvbGQgPj4+IDI0ICYgMjU1OwogICAgICAgICAgICAgICAgICBzdGF0ZS5jaGVjayA9IGNyYzMyKHN0YXRlLmNoZWNrLCBoYnVmLCA0LCAwKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGhvbGQgPSAwOwogICAgICAgICAgICAgICAgYml0cyA9IDA7CiAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gT1M7CiAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLwogICAgICAgICAgICAgIGNhc2UgT1M6CiAgICAgICAgICAgICAgICB3aGlsZSAoYml0cyA8IDE2KSB7CiAgICAgICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGhhdmUtLTsKICAgICAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7CiAgICAgICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5oZWFkKSB7CiAgICAgICAgICAgICAgICAgIHN0YXRlLmhlYWQueGZsYWdzID0gaG9sZCAmIDI1NTsKICAgICAgICAgICAgICAgICAgc3RhdGUuaGVhZC5vcyA9IGhvbGQgPj4gODsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5mbGFncyAmIDUxMiAmJiBzdGF0ZS53cmFwICYgNCkgewogICAgICAgICAgICAgICAgICBoYnVmWzBdID0gaG9sZCAmIDI1NTsKICAgICAgICAgICAgICAgICAgaGJ1ZlsxXSA9IGhvbGQgPj4+IDggJiAyNTU7CiAgICAgICAgICAgICAgICAgIHN0YXRlLmNoZWNrID0gY3JjMzIoc3RhdGUuY2hlY2ssIGhidWYsIDIsIDApOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaG9sZCA9IDA7CiAgICAgICAgICAgICAgICBiaXRzID0gMDsKICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBFWExFTjsKICAgICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovCiAgICAgICAgICAgICAgY2FzZSBFWExFTjoKICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5mbGFncyAmIDEwMjQpIHsKICAgICAgICAgICAgICAgICAgd2hpbGUgKGJpdHMgPCAxNikgewogICAgICAgICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGhhdmUtLTsKICAgICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0czsKICAgICAgICAgICAgICAgICAgICBiaXRzICs9IDg7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgc3RhdGUubGVuZ3RoID0gaG9sZDsKICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLmhlYWQpIHsKICAgICAgICAgICAgICAgICAgICBzdGF0ZS5oZWFkLmV4dHJhX2xlbiA9IGhvbGQ7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLmZsYWdzICYgNTEyICYmIHN0YXRlLndyYXAgJiA0KSB7CiAgICAgICAgICAgICAgICAgICAgaGJ1ZlswXSA9IGhvbGQgJiAyNTU7CiAgICAgICAgICAgICAgICAgICAgaGJ1ZlsxXSA9IGhvbGQgPj4+IDggJiAyNTU7CiAgICAgICAgICAgICAgICAgICAgc3RhdGUuY2hlY2sgPSBjcmMzMihzdGF0ZS5jaGVjaywgaGJ1ZiwgMiwgMCk7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaG9sZCA9IDA7CiAgICAgICAgICAgICAgICAgIGJpdHMgPSAwOwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0ZS5oZWFkKSB7CiAgICAgICAgICAgICAgICAgIHN0YXRlLmhlYWQuZXh0cmEgPSBudWxsOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IEVYVFJBOwogICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi8KICAgICAgICAgICAgICBjYXNlIEVYVFJBOgogICAgICAgICAgICAgICAgaWYgKHN0YXRlLmZsYWdzICYgMTAyNCkgewogICAgICAgICAgICAgICAgICBjb3B5ID0gc3RhdGUubGVuZ3RoOwogICAgICAgICAgICAgICAgICBpZiAoY29weSA+IGhhdmUpIHsKICAgICAgICAgICAgICAgICAgICBjb3B5ID0gaGF2ZTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAoY29weSkgewogICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5oZWFkKSB7CiAgICAgICAgICAgICAgICAgICAgICBsZW4gPSBzdGF0ZS5oZWFkLmV4dHJhX2xlbiAtIHN0YXRlLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgIGlmICghc3RhdGUuaGVhZC5leHRyYSkgewogICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5oZWFkLmV4dHJhID0gbmV3IFVpbnQ4QXJyYXkoc3RhdGUuaGVhZC5leHRyYV9sZW4pOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgc3RhdGUuaGVhZC5leHRyYS5zZXQoCiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0LnN1YmFycmF5KAogICAgICAgICAgICAgICAgICAgICAgICAgIG5leHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXh0cmEgZmllbGQgaXMgbGltaXRlZCB0byA2NTUzNiBieXRlcwogICAgICAgICAgICAgICAgICAgICAgICAgIC8vIC0gbm8gbmVlZCBmb3IgYWRkaXRpb25hbCBzaXplIGNoZWNrCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dCArIGNvcHkKICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgLypsZW4gKyBjb3B5ID4gc3RhdGUuaGVhZC5leHRyYV9tYXggLSBsZW4gPyBzdGF0ZS5oZWFkLmV4dHJhX21heCA6IGNvcHksKi8KICAgICAgICAgICAgICAgICAgICAgICAgbGVuCiAgICAgICAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdGUuZmxhZ3MgJiA1MTIgJiYgc3RhdGUud3JhcCAmIDQpIHsKICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmNoZWNrID0gY3JjMzIoc3RhdGUuY2hlY2ssIGlucHV0LCBjb3B5LCBuZXh0KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaGF2ZSAtPSBjb3B5OwogICAgICAgICAgICAgICAgICAgIG5leHQgKz0gY29weTsKICAgICAgICAgICAgICAgICAgICBzdGF0ZS5sZW5ndGggLT0gY29weTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAoc3RhdGUubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdGF0ZS5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IE5BTUU7CiAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLwogICAgICAgICAgICAgIGNhc2UgTkFNRToKICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5mbGFncyAmIDIwNDgpIHsKICAgICAgICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgY29weSA9IDA7CiAgICAgICAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAgICAgICBsZW4gPSBpbnB1dFtuZXh0ICsgY29weSsrXTsKICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdGUuaGVhZCAmJiBsZW4gJiYgc3RhdGUubGVuZ3RoIDwgNjU1MzYpIHsKICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmhlYWQubmFtZSArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGxlbik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9IHdoaWxlIChsZW4gJiYgY29weSA8IGhhdmUpOwogICAgICAgICAgICAgICAgICBpZiAoc3RhdGUuZmxhZ3MgJiA1MTIgJiYgc3RhdGUud3JhcCAmIDQpIHsKICAgICAgICAgICAgICAgICAgICBzdGF0ZS5jaGVjayA9IGNyYzMyKHN0YXRlLmNoZWNrLCBpbnB1dCwgY29weSwgbmV4dCk7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaGF2ZSAtPSBjb3B5OwogICAgICAgICAgICAgICAgICBuZXh0ICs9IGNvcHk7CiAgICAgICAgICAgICAgICAgIGlmIChsZW4pIHsKICAgICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RhdGUuaGVhZCkgewogICAgICAgICAgICAgICAgICBzdGF0ZS5oZWFkLm5hbWUgPSBudWxsOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3RhdGUubGVuZ3RoID0gMDsKICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBDT01NRU5UOwogICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi8KICAgICAgICAgICAgICBjYXNlIENPTU1FTlQ6CiAgICAgICAgICAgICAgICBpZiAoc3RhdGUuZmxhZ3MgJiA0MDk2KSB7CiAgICAgICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGNvcHkgPSAwOwogICAgICAgICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgICAgICAgbGVuID0gaW5wdXRbbmV4dCArIGNvcHkrK107CiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLmhlYWQgJiYgbGVuICYmIHN0YXRlLmxlbmd0aCA8IDY1NTM2KSB7CiAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5oZWFkLmNvbW1lbnQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShsZW4pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgfSB3aGlsZSAobGVuICYmIGNvcHkgPCBoYXZlKTsKICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLmZsYWdzICYgNTEyICYmIHN0YXRlLndyYXAgJiA0KSB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGUuY2hlY2sgPSBjcmMzMihzdGF0ZS5jaGVjaywgaW5wdXQsIGNvcHksIG5leHQpOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGhhdmUgLT0gY29weTsKICAgICAgICAgICAgICAgICAgbmV4dCArPSBjb3B5OwogICAgICAgICAgICAgICAgICBpZiAobGVuKSB7CiAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXRlLmhlYWQpIHsKICAgICAgICAgICAgICAgICAgc3RhdGUuaGVhZC5jb21tZW50ID0gbnVsbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBIQ1JDOwogICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi8KICAgICAgICAgICAgICBjYXNlIEhDUkM6CiAgICAgICAgICAgICAgICBpZiAoc3RhdGUuZmxhZ3MgJiA1MTIpIHsKICAgICAgICAgICAgICAgICAgd2hpbGUgKGJpdHMgPCAxNikgewogICAgICAgICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGhhdmUtLTsKICAgICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0czsKICAgICAgICAgICAgICAgICAgICBiaXRzICs9IDg7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLndyYXAgJiA0ICYmIGhvbGQgIT09IChzdGF0ZS5jaGVjayAmIDY1NTM1KSkgewogICAgICAgICAgICAgICAgICAgIHN0cm0ubXNnID0gImhlYWRlciBjcmMgbWlzbWF0Y2giOwogICAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaG9sZCA9IDA7CiAgICAgICAgICAgICAgICAgIGJpdHMgPSAwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHN0YXRlLmhlYWQpIHsKICAgICAgICAgICAgICAgICAgc3RhdGUuaGVhZC5oY3JjID0gc3RhdGUuZmxhZ3MgPj4gOSAmIDE7CiAgICAgICAgICAgICAgICAgIHN0YXRlLmhlYWQuZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdHJtLmFkbGVyID0gc3RhdGUuY2hlY2sgPSAwOwogICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IFRZUEU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIERJQ1RJRDoKICAgICAgICAgICAgICAgIHdoaWxlIChiaXRzIDwgMzIpIHsKICAgICAgICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaGF2ZS0tOwogICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0czsKICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3RybS5hZGxlciA9IHN0YXRlLmNoZWNrID0genN3YXAzMihob2xkKTsKICAgICAgICAgICAgICAgIGhvbGQgPSAwOwogICAgICAgICAgICAgICAgYml0cyA9IDA7CiAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gRElDVDsKICAgICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovCiAgICAgICAgICAgICAgY2FzZSBESUNUOgogICAgICAgICAgICAgICAgaWYgKHN0YXRlLmhhdmVkaWN0ID09PSAwKSB7CiAgICAgICAgICAgICAgICAgIHN0cm0ubmV4dF9vdXQgPSBwdXQ7CiAgICAgICAgICAgICAgICAgIHN0cm0uYXZhaWxfb3V0ID0gbGVmdDsKICAgICAgICAgICAgICAgICAgc3RybS5uZXh0X2luID0gbmV4dDsKICAgICAgICAgICAgICAgICAgc3RybS5hdmFpbF9pbiA9IGhhdmU7CiAgICAgICAgICAgICAgICAgIHN0YXRlLmhvbGQgPSBob2xkOwogICAgICAgICAgICAgICAgICBzdGF0ZS5iaXRzID0gYml0czsKICAgICAgICAgICAgICAgICAgcmV0dXJuIFpfTkVFRF9ESUNUOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3RybS5hZGxlciA9IHN0YXRlLmNoZWNrID0gMTsKICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBUWVBFOwogICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi8KICAgICAgICAgICAgICBjYXNlIFRZUEU6CiAgICAgICAgICAgICAgICBpZiAoZmx1c2ggPT09IFpfQkxPQ0sgfHwgZmx1c2ggPT09IFpfVFJFRVMpIHsKICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi8KICAgICAgICAgICAgICBjYXNlIFRZUEVETzoKICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5sYXN0KSB7CiAgICAgICAgICAgICAgICAgIGhvbGQgPj4+PSBiaXRzICYgNzsKICAgICAgICAgICAgICAgICAgYml0cyAtPSBiaXRzICYgNzsKICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IENIRUNLOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHdoaWxlIChiaXRzIDwgMykgewogICAgICAgICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgIGJyZWFrIGluZl9sZWF2ZTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBoYXZlLS07CiAgICAgICAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzOwogICAgICAgICAgICAgICAgICBiaXRzICs9IDg7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdGF0ZS5sYXN0ID0gaG9sZCAmIDE7CiAgICAgICAgICAgICAgICBob2xkID4+Pj0gMTsKICAgICAgICAgICAgICAgIGJpdHMgLT0gMTsKICAgICAgICAgICAgICAgIHN3aXRjaCAoaG9sZCAmIDMpIHsKICAgICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBTVE9SRUQ7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICAgICAgICBmaXhlZHRhYmxlcyhzdGF0ZSk7CiAgICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IExFTl87CiAgICAgICAgICAgICAgICAgICAgaWYgKGZsdXNoID09PSBaX1RSRUVTKSB7CiAgICAgICAgICAgICAgICAgICAgICBob2xkID4+Pj0gMjsKICAgICAgICAgICAgICAgICAgICAgIGJpdHMgLT0gMjsKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGluZl9sZWF2ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gVEFCTEU7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJpbnZhbGlkIGJsb2NrIHR5cGUiOwogICAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBob2xkID4+Pj0gMjsKICAgICAgICAgICAgICAgIGJpdHMgLT0gMjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGNhc2UgU1RPUkVEOgogICAgICAgICAgICAgICAgaG9sZCA+Pj49IGJpdHMgJiA3OwogICAgICAgICAgICAgICAgYml0cyAtPSBiaXRzICYgNzsKICAgICAgICAgICAgICAgIHdoaWxlIChiaXRzIDwgMzIpIHsKICAgICAgICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaGF2ZS0tOwogICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0czsKICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKChob2xkICYgNjU1MzUpICE9PSAoaG9sZCA+Pj4gMTYgXiA2NTUzNSkpIHsKICAgICAgICAgICAgICAgICAgc3RybS5tc2cgPSAiaW52YWxpZCBzdG9yZWQgYmxvY2sgbGVuZ3RocyI7CiAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3RhdGUubGVuZ3RoID0gaG9sZCAmIDY1NTM1OwogICAgICAgICAgICAgICAgaG9sZCA9IDA7CiAgICAgICAgICAgICAgICBiaXRzID0gMDsKICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBDT1BZXzsKICAgICAgICAgICAgICAgIGlmIChmbHVzaCA9PT0gWl9UUkVFUykgewogICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLwogICAgICAgICAgICAgIGNhc2UgQ09QWV86CiAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQ09QWTsKICAgICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovCiAgICAgICAgICAgICAgY2FzZSBDT1BZOgogICAgICAgICAgICAgICAgY29weSA9IHN0YXRlLmxlbmd0aDsKICAgICAgICAgICAgICAgIGlmIChjb3B5KSB7CiAgICAgICAgICAgICAgICAgIGlmIChjb3B5ID4gaGF2ZSkgewogICAgICAgICAgICAgICAgICAgIGNvcHkgPSBoYXZlOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChjb3B5ID4gbGVmdCkgewogICAgICAgICAgICAgICAgICAgIGNvcHkgPSBsZWZ0OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChjb3B5ID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIG91dHB1dC5zZXQoaW5wdXQuc3ViYXJyYXkobmV4dCwgbmV4dCArIGNvcHkpLCBwdXQpOwogICAgICAgICAgICAgICAgICBoYXZlIC09IGNvcHk7CiAgICAgICAgICAgICAgICAgIG5leHQgKz0gY29weTsKICAgICAgICAgICAgICAgICAgbGVmdCAtPSBjb3B5OwogICAgICAgICAgICAgICAgICBwdXQgKz0gY29weTsKICAgICAgICAgICAgICAgICAgc3RhdGUubGVuZ3RoIC09IGNvcHk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IFRZUEU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIFRBQkxFOgogICAgICAgICAgICAgICAgd2hpbGUgKGJpdHMgPCAxNCkgewogICAgICAgICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgIGJyZWFrIGluZl9sZWF2ZTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBoYXZlLS07CiAgICAgICAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzOwogICAgICAgICAgICAgICAgICBiaXRzICs9IDg7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdGF0ZS5ubGVuID0gKGhvbGQgJiAzMSkgKyAyNTc7CiAgICAgICAgICAgICAgICBob2xkID4+Pj0gNTsKICAgICAgICAgICAgICAgIGJpdHMgLT0gNTsKICAgICAgICAgICAgICAgIHN0YXRlLm5kaXN0ID0gKGhvbGQgJiAzMSkgKyAxOwogICAgICAgICAgICAgICAgaG9sZCA+Pj49IDU7CiAgICAgICAgICAgICAgICBiaXRzIC09IDU7CiAgICAgICAgICAgICAgICBzdGF0ZS5uY29kZSA9IChob2xkICYgMTUpICsgNDsKICAgICAgICAgICAgICAgIGhvbGQgPj4+PSA0OwogICAgICAgICAgICAgICAgYml0cyAtPSA0OwogICAgICAgICAgICAgICAgaWYgKHN0YXRlLm5sZW4gPiAyODYgfHwgc3RhdGUubmRpc3QgPiAzMCkgewogICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJ0b28gbWFueSBsZW5ndGggb3IgZGlzdGFuY2Ugc3ltYm9scyI7CiAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3RhdGUuaGF2ZSA9IDA7CiAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gTEVOTEVOUzsKICAgICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovCiAgICAgICAgICAgICAgY2FzZSBMRU5MRU5TOgogICAgICAgICAgICAgICAgd2hpbGUgKHN0YXRlLmhhdmUgPCBzdGF0ZS5uY29kZSkgewogICAgICAgICAgICAgICAgICB3aGlsZSAoYml0cyA8IDMpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBoYXZlLS07CiAgICAgICAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7CiAgICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHN0YXRlLmxlbnNbb3JkZXJbc3RhdGUuaGF2ZSsrXV0gPSBob2xkICYgNzsKICAgICAgICAgICAgICAgICAgaG9sZCA+Pj49IDM7CiAgICAgICAgICAgICAgICAgIGJpdHMgLT0gMzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHdoaWxlIChzdGF0ZS5oYXZlIDwgMTkpIHsKICAgICAgICAgICAgICAgICAgc3RhdGUubGVuc1tvcmRlcltzdGF0ZS5oYXZlKytdXSA9IDA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdGF0ZS5sZW5jb2RlID0gc3RhdGUubGVuZHluOwogICAgICAgICAgICAgICAgc3RhdGUubGVuYml0cyA9IDc7CiAgICAgICAgICAgICAgICBvcHRzID0geyBiaXRzOiBzdGF0ZS5sZW5iaXRzIH07CiAgICAgICAgICAgICAgICByZXQgPSBpbmZsYXRlX3RhYmxlKENPREVTLCBzdGF0ZS5sZW5zLCAwLCAxOSwgc3RhdGUubGVuY29kZSwgMCwgc3RhdGUud29yaywgb3B0cyk7CiAgICAgICAgICAgICAgICBzdGF0ZS5sZW5iaXRzID0gb3B0cy5iaXRzOwogICAgICAgICAgICAgICAgaWYgKHJldCkgewogICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJpbnZhbGlkIGNvZGUgbGVuZ3RocyBzZXQiOwogICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHN0YXRlLmhhdmUgPSAwOwogICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IENPREVMRU5TOwogICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi8KICAgICAgICAgICAgICBjYXNlIENPREVMRU5TOgogICAgICAgICAgICAgICAgd2hpbGUgKHN0YXRlLmhhdmUgPCBzdGF0ZS5ubGVuICsgc3RhdGUubmRpc3QpIHsKICAgICAgICAgICAgICAgICAgZm9yICg7IDsgKSB7CiAgICAgICAgICAgICAgICAgICAgaGVyZSA9IHN0YXRlLmxlbmNvZGVbaG9sZCAmICgxIDw8IHN0YXRlLmxlbmJpdHMpIC0gMV07CiAgICAgICAgICAgICAgICAgICAgaGVyZV9iaXRzID0gaGVyZSA+Pj4gMjQ7CiAgICAgICAgICAgICAgICAgICAgaGVyZV9vcCA9IGhlcmUgPj4+IDE2ICYgMjU1OwogICAgICAgICAgICAgICAgICAgIGhlcmVfdmFsID0gaGVyZSAmIDY1NTM1OwogICAgICAgICAgICAgICAgICAgIGlmIChoZXJlX2JpdHMgPD0gYml0cykgewogICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGhhdmUtLTsKICAgICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0czsKICAgICAgICAgICAgICAgICAgICBiaXRzICs9IDg7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKGhlcmVfdmFsIDwgMTYpIHsKICAgICAgICAgICAgICAgICAgICBob2xkID4+Pj0gaGVyZV9iaXRzOwogICAgICAgICAgICAgICAgICAgIGJpdHMgLT0gaGVyZV9iaXRzOwogICAgICAgICAgICAgICAgICAgIHN0YXRlLmxlbnNbc3RhdGUuaGF2ZSsrXSA9IGhlcmVfdmFsOwogICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIGlmIChoZXJlX3ZhbCA9PT0gMTYpIHsKICAgICAgICAgICAgICAgICAgICAgIG4gPSBoZXJlX2JpdHMgKyAyOwogICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGJpdHMgPCBuKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGhhdmUtLTsKICAgICAgICAgICAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7CiAgICAgICAgICAgICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIGhvbGQgPj4+PSBoZXJlX2JpdHM7CiAgICAgICAgICAgICAgICAgICAgICBiaXRzIC09IGhlcmVfYml0czsKICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5oYXZlID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN0cm0ubXNnID0gImludmFsaWQgYml0IGxlbmd0aCByZXBlYXQiOwogICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIGxlbiA9IHN0YXRlLmxlbnNbc3RhdGUuaGF2ZSAtIDFdOwogICAgICAgICAgICAgICAgICAgICAgY29weSA9IDMgKyAoaG9sZCAmIDMpOwogICAgICAgICAgICAgICAgICAgICAgaG9sZCA+Pj49IDI7CiAgICAgICAgICAgICAgICAgICAgICBiaXRzIC09IDI7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChoZXJlX3ZhbCA9PT0gMTcpIHsKICAgICAgICAgICAgICAgICAgICAgIG4gPSBoZXJlX2JpdHMgKyAzOwogICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGJpdHMgPCBuKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGhhdmUtLTsKICAgICAgICAgICAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7CiAgICAgICAgICAgICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIGhvbGQgPj4+PSBoZXJlX2JpdHM7CiAgICAgICAgICAgICAgICAgICAgICBiaXRzIC09IGhlcmVfYml0czsKICAgICAgICAgICAgICAgICAgICAgIGxlbiA9IDA7CiAgICAgICAgICAgICAgICAgICAgICBjb3B5ID0gMyArIChob2xkICYgNyk7CiAgICAgICAgICAgICAgICAgICAgICBob2xkID4+Pj0gMzsKICAgICAgICAgICAgICAgICAgICAgIGJpdHMgLT0gMzsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgbiA9IGhlcmVfYml0cyArIDc7CiAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoYml0cyA8IG4pIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaGF2ZS0tOwogICAgICAgICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0czsKICAgICAgICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgaG9sZCA+Pj49IGhlcmVfYml0czsKICAgICAgICAgICAgICAgICAgICAgIGJpdHMgLT0gaGVyZV9iaXRzOwogICAgICAgICAgICAgICAgICAgICAgbGVuID0gMDsKICAgICAgICAgICAgICAgICAgICAgIGNvcHkgPSAxMSArIChob2xkICYgMTI3KTsKICAgICAgICAgICAgICAgICAgICAgIGhvbGQgPj4+PSA3OwogICAgICAgICAgICAgICAgICAgICAgYml0cyAtPSA3OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdGUuaGF2ZSArIGNvcHkgPiBzdGF0ZS5ubGVuICsgc3RhdGUubmRpc3QpIHsKICAgICAgICAgICAgICAgICAgICAgIHN0cm0ubXNnID0gImludmFsaWQgYml0IGxlbmd0aCByZXBlYXQiOwogICAgICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDsKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB3aGlsZSAoY29weS0tKSB7CiAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5sZW5zW3N0YXRlLmhhdmUrK10gPSBsZW47CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoc3RhdGUubW9kZSA9PT0gQkFEKSB7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHN0YXRlLmxlbnNbMjU2XSA9PT0gMCkgewogICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJpbnZhbGlkIGNvZGUgLS0gbWlzc2luZyBlbmQtb2YtYmxvY2siOwogICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHN0YXRlLmxlbmJpdHMgPSA5OwogICAgICAgICAgICAgICAgb3B0cyA9IHsgYml0czogc3RhdGUubGVuYml0cyB9OwogICAgICAgICAgICAgICAgcmV0ID0gaW5mbGF0ZV90YWJsZShMRU5TLCBzdGF0ZS5sZW5zLCAwLCBzdGF0ZS5ubGVuLCBzdGF0ZS5sZW5jb2RlLCAwLCBzdGF0ZS53b3JrLCBvcHRzKTsKICAgICAgICAgICAgICAgIHN0YXRlLmxlbmJpdHMgPSBvcHRzLmJpdHM7CiAgICAgICAgICAgICAgICBpZiAocmV0KSB7CiAgICAgICAgICAgICAgICAgIHN0cm0ubXNnID0gImludmFsaWQgbGl0ZXJhbC9sZW5ndGhzIHNldCI7CiAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3RhdGUuZGlzdGJpdHMgPSA2OwogICAgICAgICAgICAgICAgc3RhdGUuZGlzdGNvZGUgPSBzdGF0ZS5kaXN0ZHluOwogICAgICAgICAgICAgICAgb3B0cyA9IHsgYml0czogc3RhdGUuZGlzdGJpdHMgfTsKICAgICAgICAgICAgICAgIHJldCA9IGluZmxhdGVfdGFibGUoRElTVFMsIHN0YXRlLmxlbnMsIHN0YXRlLm5sZW4sIHN0YXRlLm5kaXN0LCBzdGF0ZS5kaXN0Y29kZSwgMCwgc3RhdGUud29yaywgb3B0cyk7CiAgICAgICAgICAgICAgICBzdGF0ZS5kaXN0Yml0cyA9IG9wdHMuYml0czsKICAgICAgICAgICAgICAgIGlmIChyZXQpIHsKICAgICAgICAgICAgICAgICAgc3RybS5tc2cgPSAiaW52YWxpZCBkaXN0YW5jZXMgc2V0IjsKICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gTEVOXzsKICAgICAgICAgICAgICAgIGlmIChmbHVzaCA9PT0gWl9UUkVFUykgewogICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLwogICAgICAgICAgICAgIGNhc2UgTEVOXzoKICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBMRU47CiAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLwogICAgICAgICAgICAgIGNhc2UgTEVOOgogICAgICAgICAgICAgICAgaWYgKGhhdmUgPj0gNiAmJiBsZWZ0ID49IDI1OCkgewogICAgICAgICAgICAgICAgICBzdHJtLm5leHRfb3V0ID0gcHV0OwogICAgICAgICAgICAgICAgICBzdHJtLmF2YWlsX291dCA9IGxlZnQ7CiAgICAgICAgICAgICAgICAgIHN0cm0ubmV4dF9pbiA9IG5leHQ7CiAgICAgICAgICAgICAgICAgIHN0cm0uYXZhaWxfaW4gPSBoYXZlOwogICAgICAgICAgICAgICAgICBzdGF0ZS5ob2xkID0gaG9sZDsKICAgICAgICAgICAgICAgICAgc3RhdGUuYml0cyA9IGJpdHM7CiAgICAgICAgICAgICAgICAgIGluZmxhdGVfZmFzdChzdHJtLCBfb3V0KTsKICAgICAgICAgICAgICAgICAgcHV0ID0gc3RybS5uZXh0X291dDsKICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gc3RybS5vdXRwdXQ7CiAgICAgICAgICAgICAgICAgIGxlZnQgPSBzdHJtLmF2YWlsX291dDsKICAgICAgICAgICAgICAgICAgbmV4dCA9IHN0cm0ubmV4dF9pbjsKICAgICAgICAgICAgICAgICAgaW5wdXQgPSBzdHJtLmlucHV0OwogICAgICAgICAgICAgICAgICBoYXZlID0gc3RybS5hdmFpbF9pbjsKICAgICAgICAgICAgICAgICAgaG9sZCA9IHN0YXRlLmhvbGQ7CiAgICAgICAgICAgICAgICAgIGJpdHMgPSBzdGF0ZS5iaXRzOwogICAgICAgICAgICAgICAgICBpZiAoc3RhdGUubW9kZSA9PT0gVFlQRSkgewogICAgICAgICAgICAgICAgICAgIHN0YXRlLmJhY2sgPSAtMTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHN0YXRlLmJhY2sgPSAwOwogICAgICAgICAgICAgICAgZm9yICg7IDsgKSB7CiAgICAgICAgICAgICAgICAgIGhlcmUgPSBzdGF0ZS5sZW5jb2RlW2hvbGQgJiAoMSA8PCBzdGF0ZS5sZW5iaXRzKSAtIDFdOwogICAgICAgICAgICAgICAgICBoZXJlX2JpdHMgPSBoZXJlID4+PiAyNDsKICAgICAgICAgICAgICAgICAgaGVyZV9vcCA9IGhlcmUgPj4+IDE2ICYgMjU1OwogICAgICAgICAgICAgICAgICBoZXJlX3ZhbCA9IGhlcmUgJiA2NTUzNTsKICAgICAgICAgICAgICAgICAgaWYgKGhlcmVfYml0cyA8PSBiaXRzKSB7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaGF2ZS0tOwogICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0czsKICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKGhlcmVfb3AgJiYgKGhlcmVfb3AgJiAyNDApID09PSAwKSB7CiAgICAgICAgICAgICAgICAgIGxhc3RfYml0cyA9IGhlcmVfYml0czsKICAgICAgICAgICAgICAgICAgbGFzdF9vcCA9IGhlcmVfb3A7CiAgICAgICAgICAgICAgICAgIGxhc3RfdmFsID0gaGVyZV92YWw7CiAgICAgICAgICAgICAgICAgIGZvciAoOyA7ICkgewogICAgICAgICAgICAgICAgICAgIGhlcmUgPSBzdGF0ZS5sZW5jb2RlW2xhc3RfdmFsICsgKChob2xkICYgKDEgPDwgbGFzdF9iaXRzICsgbGFzdF9vcCkgLSAxKSA+PiBsYXN0X2JpdHMpXTsKICAgICAgICAgICAgICAgICAgICBoZXJlX2JpdHMgPSBoZXJlID4+PiAyNDsKICAgICAgICAgICAgICAgICAgICBoZXJlX29wID0gaGVyZSA+Pj4gMTYgJiAyNTU7CiAgICAgICAgICAgICAgICAgICAgaGVyZV92YWwgPSBoZXJlICYgNjU1MzU7CiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RfYml0cyArIGhlcmVfYml0cyA8PSBiaXRzKSB7CiAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGluZl9sZWF2ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaGF2ZS0tOwogICAgICAgICAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzOwogICAgICAgICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBob2xkID4+Pj0gbGFzdF9iaXRzOwogICAgICAgICAgICAgICAgICBiaXRzIC09IGxhc3RfYml0czsKICAgICAgICAgICAgICAgICAgc3RhdGUuYmFjayArPSBsYXN0X2JpdHM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBob2xkID4+Pj0gaGVyZV9iaXRzOwogICAgICAgICAgICAgICAgYml0cyAtPSBoZXJlX2JpdHM7CiAgICAgICAgICAgICAgICBzdGF0ZS5iYWNrICs9IGhlcmVfYml0czsKICAgICAgICAgICAgICAgIHN0YXRlLmxlbmd0aCA9IGhlcmVfdmFsOwogICAgICAgICAgICAgICAgaWYgKGhlcmVfb3AgPT09IDApIHsKICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IExJVDsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoaGVyZV9vcCAmIDMyKSB7CiAgICAgICAgICAgICAgICAgIHN0YXRlLmJhY2sgPSAtMTsKICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IFRZUEU7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKGhlcmVfb3AgJiA2NCkgewogICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJpbnZhbGlkIGxpdGVyYWwvbGVuZ3RoIGNvZGUiOwogICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHN0YXRlLmV4dHJhID0gaGVyZV9vcCAmIDE1OwogICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IExFTkVYVDsKICAgICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovCiAgICAgICAgICAgICAgY2FzZSBMRU5FWFQ6CiAgICAgICAgICAgICAgICBpZiAoc3RhdGUuZXh0cmEpIHsKICAgICAgICAgICAgICAgICAgbiA9IHN0YXRlLmV4dHJhOwogICAgICAgICAgICAgICAgICB3aGlsZSAoYml0cyA8IG4pIHsKICAgICAgICAgICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBoYXZlLS07CiAgICAgICAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7CiAgICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHN0YXRlLmxlbmd0aCArPSBob2xkICYgKDEgPDwgc3RhdGUuZXh0cmEpIC0gMTsKICAgICAgICAgICAgICAgICAgaG9sZCA+Pj49IHN0YXRlLmV4dHJhOwogICAgICAgICAgICAgICAgICBiaXRzIC09IHN0YXRlLmV4dHJhOwogICAgICAgICAgICAgICAgICBzdGF0ZS5iYWNrICs9IHN0YXRlLmV4dHJhOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3RhdGUud2FzID0gc3RhdGUubGVuZ3RoOwogICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IERJU1Q7CiAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLwogICAgICAgICAgICAgIGNhc2UgRElTVDoKICAgICAgICAgICAgICAgIGZvciAoOyA7ICkgewogICAgICAgICAgICAgICAgICBoZXJlID0gc3RhdGUuZGlzdGNvZGVbaG9sZCAmICgxIDw8IHN0YXRlLmRpc3RiaXRzKSAtIDFdOwogICAgICAgICAgICAgICAgICBoZXJlX2JpdHMgPSBoZXJlID4+PiAyNDsKICAgICAgICAgICAgICAgICAgaGVyZV9vcCA9IGhlcmUgPj4+IDE2ICYgMjU1OwogICAgICAgICAgICAgICAgICBoZXJlX3ZhbCA9IGhlcmUgJiA2NTUzNTsKICAgICAgICAgICAgICAgICAgaWYgKGhlcmVfYml0cyA8PSBiaXRzKSB7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaGF2ZS0tOwogICAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0czsKICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKChoZXJlX29wICYgMjQwKSA9PT0gMCkgewogICAgICAgICAgICAgICAgICBsYXN0X2JpdHMgPSBoZXJlX2JpdHM7CiAgICAgICAgICAgICAgICAgIGxhc3Rfb3AgPSBoZXJlX29wOwogICAgICAgICAgICAgICAgICBsYXN0X3ZhbCA9IGhlcmVfdmFsOwogICAgICAgICAgICAgICAgICBmb3IgKDsgOyApIHsKICAgICAgICAgICAgICAgICAgICBoZXJlID0gc3RhdGUuZGlzdGNvZGVbbGFzdF92YWwgKyAoKGhvbGQgJiAoMSA8PCBsYXN0X2JpdHMgKyBsYXN0X29wKSAtIDEpID4+IGxhc3RfYml0cyldOwogICAgICAgICAgICAgICAgICAgIGhlcmVfYml0cyA9IGhlcmUgPj4+IDI0OwogICAgICAgICAgICAgICAgICAgIGhlcmVfb3AgPSBoZXJlID4+PiAxNiAmIDI1NTsKICAgICAgICAgICAgICAgICAgICBoZXJlX3ZhbCA9IGhlcmUgJiA2NTUzNTsKICAgICAgICAgICAgICAgICAgICBpZiAobGFzdF9iaXRzICsgaGVyZV9iaXRzIDw9IGJpdHMpIHsKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBoYXZlLS07CiAgICAgICAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7CiAgICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGhvbGQgPj4+PSBsYXN0X2JpdHM7CiAgICAgICAgICAgICAgICAgIGJpdHMgLT0gbGFzdF9iaXRzOwogICAgICAgICAgICAgICAgICBzdGF0ZS5iYWNrICs9IGxhc3RfYml0czsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGhvbGQgPj4+PSBoZXJlX2JpdHM7CiAgICAgICAgICAgICAgICBiaXRzIC09IGhlcmVfYml0czsKICAgICAgICAgICAgICAgIHN0YXRlLmJhY2sgKz0gaGVyZV9iaXRzOwogICAgICAgICAgICAgICAgaWYgKGhlcmVfb3AgJiA2NCkgewogICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJpbnZhbGlkIGRpc3RhbmNlIGNvZGUiOwogICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHN0YXRlLm9mZnNldCA9IGhlcmVfdmFsOwogICAgICAgICAgICAgICAgc3RhdGUuZXh0cmEgPSBoZXJlX29wICYgMTU7CiAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gRElTVEVYVDsKICAgICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovCiAgICAgICAgICAgICAgY2FzZSBESVNURVhUOgogICAgICAgICAgICAgICAgaWYgKHN0YXRlLmV4dHJhKSB7CiAgICAgICAgICAgICAgICAgIG4gPSBzdGF0ZS5leHRyYTsKICAgICAgICAgICAgICAgICAgd2hpbGUgKGJpdHMgPCBuKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGluZl9sZWF2ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaGF2ZS0tOwogICAgICAgICAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzOwogICAgICAgICAgICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBzdGF0ZS5vZmZzZXQgKz0gaG9sZCAmICgxIDw8IHN0YXRlLmV4dHJhKSAtIDE7CiAgICAgICAgICAgICAgICAgIGhvbGQgPj4+PSBzdGF0ZS5leHRyYTsKICAgICAgICAgICAgICAgICAgYml0cyAtPSBzdGF0ZS5leHRyYTsKICAgICAgICAgICAgICAgICAgc3RhdGUuYmFjayArPSBzdGF0ZS5leHRyYTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5vZmZzZXQgPiBzdGF0ZS5kbWF4KSB7CiAgICAgICAgICAgICAgICAgIHN0cm0ubXNnID0gImludmFsaWQgZGlzdGFuY2UgdG9vIGZhciBiYWNrIjsKICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gTUFUQ0g7CiAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLwogICAgICAgICAgICAgIGNhc2UgTUFUQ0g6CiAgICAgICAgICAgICAgICBpZiAobGVmdCA9PT0gMCkgewogICAgICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjb3B5ID0gX291dCAtIGxlZnQ7CiAgICAgICAgICAgICAgICBpZiAoc3RhdGUub2Zmc2V0ID4gY29weSkgewogICAgICAgICAgICAgICAgICBjb3B5ID0gc3RhdGUub2Zmc2V0IC0gY29weTsKICAgICAgICAgICAgICAgICAgaWYgKGNvcHkgPiBzdGF0ZS53aGF2ZSkgewogICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5zYW5lKSB7CiAgICAgICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJpbnZhbGlkIGRpc3RhbmNlIHRvbyBmYXIgYmFjayI7CiAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEOwogICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChjb3B5ID4gc3RhdGUud25leHQpIHsKICAgICAgICAgICAgICAgICAgICBjb3B5IC09IHN0YXRlLnduZXh0OwogICAgICAgICAgICAgICAgICAgIGZyb20gPSBzdGF0ZS53c2l6ZSAtIGNvcHk7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgZnJvbSA9IHN0YXRlLnduZXh0IC0gY29weTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAoY29weSA+IHN0YXRlLmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgIGNvcHkgPSBzdGF0ZS5sZW5ndGg7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgZnJvbV9zb3VyY2UgPSBzdGF0ZS53aW5kb3c7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBmcm9tX3NvdXJjZSA9IG91dHB1dDsKICAgICAgICAgICAgICAgICAgZnJvbSA9IHB1dCAtIHN0YXRlLm9mZnNldDsKICAgICAgICAgICAgICAgICAgY29weSA9IHN0YXRlLmxlbmd0aDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChjb3B5ID4gbGVmdCkgewogICAgICAgICAgICAgICAgICBjb3B5ID0gbGVmdDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGxlZnQgLT0gY29weTsKICAgICAgICAgICAgICAgIHN0YXRlLmxlbmd0aCAtPSBjb3B5OwogICAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgICBvdXRwdXRbcHV0KytdID0gZnJvbV9zb3VyY2VbZnJvbSsrXTsKICAgICAgICAgICAgICAgIH0gd2hpbGUgKC0tY29weSk7CiAgICAgICAgICAgICAgICBpZiAoc3RhdGUubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBMRU47CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIExJVDoKICAgICAgICAgICAgICAgIGlmIChsZWZ0ID09PSAwKSB7CiAgICAgICAgICAgICAgICAgIGJyZWFrIGluZl9sZWF2ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIG91dHB1dFtwdXQrK10gPSBzdGF0ZS5sZW5ndGg7CiAgICAgICAgICAgICAgICBsZWZ0LS07CiAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gTEVOOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSBDSEVDSzoKICAgICAgICAgICAgICAgIGlmIChzdGF0ZS53cmFwKSB7CiAgICAgICAgICAgICAgICAgIHdoaWxlIChiaXRzIDwgMzIpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBoYXZlLS07CiAgICAgICAgICAgICAgICAgICAgaG9sZCB8PSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7CiAgICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIF9vdXQgLT0gbGVmdDsKICAgICAgICAgICAgICAgICAgc3RybS50b3RhbF9vdXQgKz0gX291dDsKICAgICAgICAgICAgICAgICAgc3RhdGUudG90YWwgKz0gX291dDsKICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLndyYXAgJiA0ICYmIF9vdXQpIHsKICAgICAgICAgICAgICAgICAgICBzdHJtLmFkbGVyID0gc3RhdGUuY2hlY2sgPSAvKlVQREFURV9DSEVDSyhzdGF0ZS5jaGVjaywgcHV0IC0gX291dCwgX291dCk7Ki8KICAgICAgICAgICAgICAgICAgICBzdGF0ZS5mbGFncyA/IGNyYzMyKHN0YXRlLmNoZWNrLCBvdXRwdXQsIF9vdXQsIHB1dCAtIF9vdXQpIDogYWRsZXIzMihzdGF0ZS5jaGVjaywgb3V0cHV0LCBfb3V0LCBwdXQgLSBfb3V0KTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBfb3V0ID0gbGVmdDsKICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLndyYXAgJiA0ICYmIChzdGF0ZS5mbGFncyA/IGhvbGQgOiB6c3dhcDMyKGhvbGQpKSAhPT0gc3RhdGUuY2hlY2spIHsKICAgICAgICAgICAgICAgICAgICBzdHJtLm1zZyA9ICJpbmNvcnJlY3QgZGF0YSBjaGVjayI7CiAgICAgICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBob2xkID0gMDsKICAgICAgICAgICAgICAgICAgYml0cyA9IDA7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gTEVOR1RIOwogICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi8KICAgICAgICAgICAgICBjYXNlIExFTkdUSDoKICAgICAgICAgICAgICAgIGlmIChzdGF0ZS53cmFwICYmIHN0YXRlLmZsYWdzKSB7CiAgICAgICAgICAgICAgICAgIHdoaWxlIChiaXRzIDwgMzIpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgaW5mX2xlYXZlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBoYXZlLS07CiAgICAgICAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7CiAgICAgICAgICAgICAgICAgICAgYml0cyArPSA4OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZS53cmFwICYgNCAmJiBob2xkICE9PSAoc3RhdGUudG90YWwgJiA0Mjk0OTY3Mjk1KSkgewogICAgICAgICAgICAgICAgICAgIHN0cm0ubXNnID0gImluY29ycmVjdCBsZW5ndGggY2hlY2siOwogICAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaG9sZCA9IDA7CiAgICAgICAgICAgICAgICAgIGJpdHMgPSAwOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IERPTkU7CiAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLwogICAgICAgICAgICAgIGNhc2UgRE9ORToKICAgICAgICAgICAgICAgIHJldCA9IFpfU1RSRUFNX0VORDsKICAgICAgICAgICAgICAgIGJyZWFrIGluZl9sZWF2ZTsKICAgICAgICAgICAgICBjYXNlIEJBRDoKICAgICAgICAgICAgICAgIHJldCA9IFpfREFUQV9FUlJPUjsKICAgICAgICAgICAgICAgIGJyZWFrIGluZl9sZWF2ZTsKICAgICAgICAgICAgICBjYXNlIE1FTToKICAgICAgICAgICAgICAgIHJldHVybiBaX01FTV9FUlJPUjsKICAgICAgICAgICAgICBjYXNlIFNZTkM6CiAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqLwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICByZXR1cm4gWl9TVFJFQU1fRVJST1I7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICBzdHJtLm5leHRfb3V0ID0gcHV0OwogICAgICAgIHN0cm0uYXZhaWxfb3V0ID0gbGVmdDsKICAgICAgICBzdHJtLm5leHRfaW4gPSBuZXh0OwogICAgICAgIHN0cm0uYXZhaWxfaW4gPSBoYXZlOwogICAgICAgIHN0YXRlLmhvbGQgPSBob2xkOwogICAgICAgIHN0YXRlLmJpdHMgPSBiaXRzOwogICAgICAgIGlmIChzdGF0ZS53c2l6ZSB8fCBfb3V0ICE9PSBzdHJtLmF2YWlsX291dCAmJiBzdGF0ZS5tb2RlIDwgQkFEICYmIChzdGF0ZS5tb2RlIDwgQ0hFQ0sgfHwgZmx1c2ggIT09IFpfRklOSVNIKSkgewogICAgICAgICAgaWYgKHVwZGF0ZXdpbmRvdyhzdHJtLCBzdHJtLm91dHB1dCwgc3RybS5uZXh0X291dCwgX291dCAtIHN0cm0uYXZhaWxfb3V0KSkgewogICAgICAgICAgICBzdGF0ZS5tb2RlID0gTUVNOwogICAgICAgICAgICByZXR1cm4gWl9NRU1fRVJST1I7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIF9pbiAtPSBzdHJtLmF2YWlsX2luOwogICAgICAgIF9vdXQgLT0gc3RybS5hdmFpbF9vdXQ7CiAgICAgICAgc3RybS50b3RhbF9pbiArPSBfaW47CiAgICAgICAgc3RybS50b3RhbF9vdXQgKz0gX291dDsKICAgICAgICBzdGF0ZS50b3RhbCArPSBfb3V0OwogICAgICAgIGlmIChzdGF0ZS53cmFwICYgNCAmJiBfb3V0KSB7CiAgICAgICAgICBzdHJtLmFkbGVyID0gc3RhdGUuY2hlY2sgPSAvKlVQREFURV9DSEVDSyhzdGF0ZS5jaGVjaywgc3RybS5uZXh0X291dCAtIF9vdXQsIF9vdXQpOyovCiAgICAgICAgICBzdGF0ZS5mbGFncyA/IGNyYzMyKHN0YXRlLmNoZWNrLCBvdXRwdXQsIF9vdXQsIHN0cm0ubmV4dF9vdXQgLSBfb3V0KSA6IGFkbGVyMzIoc3RhdGUuY2hlY2ssIG91dHB1dCwgX291dCwgc3RybS5uZXh0X291dCAtIF9vdXQpOwogICAgICAgIH0KICAgICAgICBzdHJtLmRhdGFfdHlwZSA9IHN0YXRlLmJpdHMgKyAoc3RhdGUubGFzdCA/IDY0IDogMCkgKyAoc3RhdGUubW9kZSA9PT0gVFlQRSA/IDEyOCA6IDApICsgKHN0YXRlLm1vZGUgPT09IExFTl8gfHwgc3RhdGUubW9kZSA9PT0gQ09QWV8gPyAyNTYgOiAwKTsKICAgICAgICBpZiAoKF9pbiA9PT0gMCAmJiBfb3V0ID09PSAwIHx8IGZsdXNoID09PSBaX0ZJTklTSCkgJiYgcmV0ID09PSBaX09LKSB7CiAgICAgICAgICByZXQgPSBaX0JVRl9FUlJPUjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsKICAgICAgfTsKICAgICAgdmFyIGluZmxhdGVFbmQgPSAoc3RybSkgPT4gewogICAgICAgIGlmIChpbmZsYXRlU3RhdGVDaGVjayhzdHJtKSkgewogICAgICAgICAgcmV0dXJuIFpfU1RSRUFNX0VSUk9SOwogICAgICAgIH0KICAgICAgICBsZXQgc3RhdGUgPSBzdHJtLnN0YXRlOwogICAgICAgIGlmIChzdGF0ZS53aW5kb3cpIHsKICAgICAgICAgIHN0YXRlLndpbmRvdyA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHN0cm0uc3RhdGUgPSBudWxsOwogICAgICAgIHJldHVybiBaX09LOwogICAgICB9OwogICAgICB2YXIgaW5mbGF0ZUdldEhlYWRlciA9IChzdHJtLCBoZWFkKSA9PiB7CiAgICAgICAgaWYgKGluZmxhdGVTdGF0ZUNoZWNrKHN0cm0pKSB7CiAgICAgICAgICByZXR1cm4gWl9TVFJFQU1fRVJST1I7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHN0YXRlID0gc3RybS5zdGF0ZTsKICAgICAgICBpZiAoKHN0YXRlLndyYXAgJiAyKSA9PT0gMCkgewogICAgICAgICAgcmV0dXJuIFpfU1RSRUFNX0VSUk9SOwogICAgICAgIH0KICAgICAgICBzdGF0ZS5oZWFkID0gaGVhZDsKICAgICAgICBoZWFkLmRvbmUgPSBmYWxzZTsKICAgICAgICByZXR1cm4gWl9PSzsKICAgICAgfTsKICAgICAgdmFyIGluZmxhdGVTZXREaWN0aW9uYXJ5ID0gKHN0cm0sIGRpY3Rpb25hcnkpID0+IHsKICAgICAgICBjb25zdCBkaWN0TGVuZ3RoID0gZGljdGlvbmFyeS5sZW5ndGg7CiAgICAgICAgbGV0IHN0YXRlOwogICAgICAgIGxldCBkaWN0aWQ7CiAgICAgICAgbGV0IHJldDsKICAgICAgICBpZiAoaW5mbGF0ZVN0YXRlQ2hlY2soc3RybSkpIHsKICAgICAgICAgIHJldHVybiBaX1NUUkVBTV9FUlJPUjsKICAgICAgICB9CiAgICAgICAgc3RhdGUgPSBzdHJtLnN0YXRlOwogICAgICAgIGlmIChzdGF0ZS53cmFwICE9PSAwICYmIHN0YXRlLm1vZGUgIT09IERJQ1QpIHsKICAgICAgICAgIHJldHVybiBaX1NUUkVBTV9FUlJPUjsKICAgICAgICB9CiAgICAgICAgaWYgKHN0YXRlLm1vZGUgPT09IERJQ1QpIHsKICAgICAgICAgIGRpY3RpZCA9IDE7CiAgICAgICAgICBkaWN0aWQgPSBhZGxlcjMyKGRpY3RpZCwgZGljdGlvbmFyeSwgZGljdExlbmd0aCwgMCk7CiAgICAgICAgICBpZiAoZGljdGlkICE9PSBzdGF0ZS5jaGVjaykgewogICAgICAgICAgICByZXR1cm4gWl9EQVRBX0VSUk9SOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXQgPSB1cGRhdGV3aW5kb3coc3RybSwgZGljdGlvbmFyeSwgZGljdExlbmd0aCwgZGljdExlbmd0aCk7CiAgICAgICAgaWYgKHJldCkgewogICAgICAgICAgc3RhdGUubW9kZSA9IE1FTTsKICAgICAgICAgIHJldHVybiBaX01FTV9FUlJPUjsKICAgICAgICB9CiAgICAgICAgc3RhdGUuaGF2ZWRpY3QgPSAxOwogICAgICAgIHJldHVybiBaX09LOwogICAgICB9OwogICAgICBtb2R1bGUuZXhwb3J0cy5pbmZsYXRlUmVzZXQgPSBpbmZsYXRlUmVzZXQ7CiAgICAgIG1vZHVsZS5leHBvcnRzLmluZmxhdGVSZXNldDIgPSBpbmZsYXRlUmVzZXQyOwogICAgICBtb2R1bGUuZXhwb3J0cy5pbmZsYXRlUmVzZXRLZWVwID0gaW5mbGF0ZVJlc2V0S2VlcDsKICAgICAgbW9kdWxlLmV4cG9ydHMuaW5mbGF0ZUluaXQgPSBpbmZsYXRlSW5pdDsKICAgICAgbW9kdWxlLmV4cG9ydHMuaW5mbGF0ZUluaXQyID0gaW5mbGF0ZUluaXQyOwogICAgICBtb2R1bGUuZXhwb3J0cy5pbmZsYXRlID0gaW5mbGF0ZTsKICAgICAgbW9kdWxlLmV4cG9ydHMuaW5mbGF0ZUVuZCA9IGluZmxhdGVFbmQ7CiAgICAgIG1vZHVsZS5leHBvcnRzLmluZmxhdGVHZXRIZWFkZXIgPSBpbmZsYXRlR2V0SGVhZGVyOwogICAgICBtb2R1bGUuZXhwb3J0cy5pbmZsYXRlU2V0RGljdGlvbmFyeSA9IGluZmxhdGVTZXREaWN0aW9uYXJ5OwogICAgICBtb2R1bGUuZXhwb3J0cy5pbmZsYXRlSW5mbyA9ICJwYWtvIGluZmxhdGUgKGZyb20gTm9kZWNhIHByb2plY3QpIjsKICAgIH0KICB9KTsKCiAgLy8gbm9kZV9tb2R1bGVzL3Bha28vbGliL3V0aWxzL2NvbW1vbi5qcwogIHZhciByZXF1aXJlX2NvbW1vbiA9IF9fY29tbW9uSlMoewogICAgIm5vZGVfbW9kdWxlcy9wYWtvL2xpYi91dGlscy9jb21tb24uanMiKGV4cG9ydHMyLCBtb2R1bGUpIHsKICAgICAgInVzZSBzdHJpY3QiOwogICAgICB2YXIgX2hhcyA9IChvYmosIGtleSkgPT4gewogICAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpOwogICAgICB9OwogICAgICBtb2R1bGUuZXhwb3J0cy5hc3NpZ24gPSBmdW5jdGlvbihvYmopIHsKICAgICAgICBjb25zdCBzb3VyY2VzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTsKICAgICAgICB3aGlsZSAoc291cmNlcy5sZW5ndGgpIHsKICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IHNvdXJjZXMuc2hpZnQoKTsKICAgICAgICAgIGlmICghc291cmNlKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHR5cGVvZiBzb3VyY2UgIT09ICJvYmplY3QiKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3Ioc291cmNlICsgIm11c3QgYmUgbm9uLW9iamVjdCIpOwogICAgICAgICAgfQogICAgICAgICAgZm9yIChjb25zdCBwIGluIHNvdXJjZSkgewogICAgICAgICAgICBpZiAoX2hhcyhzb3VyY2UsIHApKSB7CiAgICAgICAgICAgICAgb2JqW3BdID0gc291cmNlW3BdOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBvYmo7CiAgICAgIH07CiAgICAgIG1vZHVsZS5leHBvcnRzLmZsYXR0ZW5DaHVua3MgPSAoY2h1bmtzKSA9PiB7CiAgICAgICAgbGV0IGxlbiA9IDA7CiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGwgPSBjaHVua3MubGVuZ3RoOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICBsZW4gKz0gY2h1bmtzW2ldLmxlbmd0aDsKICAgICAgICB9CiAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkobGVuKTsKICAgICAgICBmb3IgKGxldCBpID0gMCwgcG9zID0gMCwgbCA9IGNodW5rcy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgICAgIGxldCBjaHVuayA9IGNodW5rc1tpXTsKICAgICAgICAgIHJlc3VsdC5zZXQoY2h1bmssIHBvcyk7CiAgICAgICAgICBwb3MgKz0gY2h1bmsubGVuZ3RoOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgfQogIH0pOwoKICAvLyBub2RlX21vZHVsZXMvcGFrby9saWIvdXRpbHMvc3RyaW5ncy5qcwogIHZhciByZXF1aXJlX3N0cmluZ3MgPSBfX2NvbW1vbkpTKHsKICAgICJub2RlX21vZHVsZXMvcGFrby9saWIvdXRpbHMvc3RyaW5ncy5qcyIoZXhwb3J0czIsIG1vZHVsZSkgewogICAgICAidXNlIHN0cmljdCI7CiAgICAgIHZhciBTVFJfQVBQTFlfVUlBX09LID0gdHJ1ZTsKICAgICAgdHJ5IHsKICAgICAgICBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIG5ldyBVaW50OEFycmF5KDEpKTsKICAgICAgfSBjYXRjaCAoX18pIHsKICAgICAgICBTVFJfQVBQTFlfVUlBX09LID0gZmFsc2U7CiAgICAgIH0KICAgICAgdmFyIF91dGY4bGVuID0gbmV3IFVpbnQ4QXJyYXkoMjU2KTsKICAgICAgZm9yIChsZXQgcSA9IDA7IHEgPCAyNTY7IHErKykgewogICAgICAgIF91dGY4bGVuW3FdID0gcSA+PSAyNTIgPyA2IDogcSA+PSAyNDggPyA1IDogcSA+PSAyNDAgPyA0IDogcSA+PSAyMjQgPyAzIDogcSA+PSAxOTIgPyAyIDogMTsKICAgICAgfQogICAgICBfdXRmOGxlblsyNTRdID0gX3V0ZjhsZW5bMjU0XSA9IDE7CiAgICAgIG1vZHVsZS5leHBvcnRzLnN0cmluZzJidWYgPSAoc3RyKSA9PiB7CiAgICAgICAgaWYgKHR5cGVvZiBUZXh0RW5jb2RlciA9PT0gImZ1bmN0aW9uIiAmJiBUZXh0RW5jb2Rlci5wcm90b3R5cGUuZW5jb2RlKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHN0cik7CiAgICAgICAgfQogICAgICAgIGxldCBidWYsIGMsIGMyLCBtX3BvcywgaSwgc3RyX2xlbiA9IHN0ci5sZW5ndGgsIGJ1Zl9sZW4gPSAwOwogICAgICAgIGZvciAobV9wb3MgPSAwOyBtX3BvcyA8IHN0cl9sZW47IG1fcG9zKyspIHsKICAgICAgICAgIGMgPSBzdHIuY2hhckNvZGVBdChtX3Bvcyk7CiAgICAgICAgICBpZiAoKGMgJiA2NDUxMikgPT09IDU1Mjk2ICYmIG1fcG9zICsgMSA8IHN0cl9sZW4pIHsKICAgICAgICAgICAgYzIgPSBzdHIuY2hhckNvZGVBdChtX3BvcyArIDEpOwogICAgICAgICAgICBpZiAoKGMyICYgNjQ1MTIpID09PSA1NjMyMCkgewogICAgICAgICAgICAgIGMgPSA2NTUzNiArIChjIC0gNTUyOTYgPDwgMTApICsgKGMyIC0gNTYzMjApOwogICAgICAgICAgICAgIG1fcG9zKys7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJ1Zl9sZW4gKz0gYyA8IDEyOCA/IDEgOiBjIDwgMjA0OCA/IDIgOiBjIDwgNjU1MzYgPyAzIDogNDsKICAgICAgICB9CiAgICAgICAgYnVmID0gbmV3IFVpbnQ4QXJyYXkoYnVmX2xlbik7CiAgICAgICAgZm9yIChpID0gMCwgbV9wb3MgPSAwOyBpIDwgYnVmX2xlbjsgbV9wb3MrKykgewogICAgICAgICAgYyA9IHN0ci5jaGFyQ29kZUF0KG1fcG9zKTsKICAgICAgICAgIGlmICgoYyAmIDY0NTEyKSA9PT0gNTUyOTYgJiYgbV9wb3MgKyAxIDwgc3RyX2xlbikgewogICAgICAgICAgICBjMiA9IHN0ci5jaGFyQ29kZUF0KG1fcG9zICsgMSk7CiAgICAgICAgICAgIGlmICgoYzIgJiA2NDUxMikgPT09IDU2MzIwKSB7CiAgICAgICAgICAgICAgYyA9IDY1NTM2ICsgKGMgLSA1NTI5NiA8PCAxMCkgKyAoYzIgLSA1NjMyMCk7CiAgICAgICAgICAgICAgbV9wb3MrKzsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGMgPCAxMjgpIHsKICAgICAgICAgICAgYnVmW2krK10gPSBjOwogICAgICAgICAgfSBlbHNlIGlmIChjIDwgMjA0OCkgewogICAgICAgICAgICBidWZbaSsrXSA9IDE5MiB8IGMgPj4+IDY7CiAgICAgICAgICAgIGJ1ZltpKytdID0gMTI4IHwgYyAmIDYzOwogICAgICAgICAgfSBlbHNlIGlmIChjIDwgNjU1MzYpIHsKICAgICAgICAgICAgYnVmW2krK10gPSAyMjQgfCBjID4+PiAxMjsKICAgICAgICAgICAgYnVmW2krK10gPSAxMjggfCBjID4+PiA2ICYgNjM7CiAgICAgICAgICAgIGJ1ZltpKytdID0gMTI4IHwgYyAmIDYzOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYnVmW2krK10gPSAyNDAgfCBjID4+PiAxODsKICAgICAgICAgICAgYnVmW2krK10gPSAxMjggfCBjID4+PiAxMiAmIDYzOwogICAgICAgICAgICBidWZbaSsrXSA9IDEyOCB8IGMgPj4+IDYgJiA2MzsKICAgICAgICAgICAgYnVmW2krK10gPSAxMjggfCBjICYgNjM7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBidWY7CiAgICAgIH07CiAgICAgIHZhciBidWYyYmluc3RyaW5nID0gKGJ1ZiwgbGVuKSA9PiB7CiAgICAgICAgaWYgKGxlbiA8IDY1NTM0KSB7CiAgICAgICAgICBpZiAoYnVmLnN1YmFycmF5ICYmIFNUUl9BUFBMWV9VSUFfT0spIHsKICAgICAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgYnVmLmxlbmd0aCA9PT0gbGVuID8gYnVmIDogYnVmLnN1YmFycmF5KDAsIGxlbikpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBsZXQgcmVzdWx0ID0gIiI7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykgewogICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgfTsKICAgICAgbW9kdWxlLmV4cG9ydHMuYnVmMnN0cmluZyA9IChidWYsIG1heDMpID0+IHsKICAgICAgICBjb25zdCBsZW4gPSBtYXgzIHx8IGJ1Zi5sZW5ndGg7CiAgICAgICAgaWYgKHR5cGVvZiBUZXh0RGVjb2RlciA9PT0gImZ1bmN0aW9uIiAmJiBUZXh0RGVjb2Rlci5wcm90b3R5cGUuZGVjb2RlKSB7CiAgICAgICAgICByZXR1cm4gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGJ1Zi5zdWJhcnJheSgwLCBtYXgzKSk7CiAgICAgICAgfQogICAgICAgIGxldCBpLCBvdXQ7CiAgICAgICAgY29uc3QgdXRmMTZidWYgPSBuZXcgQXJyYXkobGVuICogMik7CiAgICAgICAgZm9yIChvdXQgPSAwLCBpID0gMDsgaSA8IGxlbjsgKSB7CiAgICAgICAgICBsZXQgYyA9IGJ1ZltpKytdOwogICAgICAgICAgaWYgKGMgPCAxMjgpIHsKICAgICAgICAgICAgdXRmMTZidWZbb3V0KytdID0gYzsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBsZXQgY19sZW4gPSBfdXRmOGxlbltjXTsKICAgICAgICAgIGlmIChjX2xlbiA+IDQpIHsKICAgICAgICAgICAgdXRmMTZidWZbb3V0KytdID0gNjU1MzM7CiAgICAgICAgICAgIGkgKz0gY19sZW4gLSAxOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGMgJj0gY19sZW4gPT09IDIgPyAzMSA6IGNfbGVuID09PSAzID8gMTUgOiA3OwogICAgICAgICAgd2hpbGUgKGNfbGVuID4gMSAmJiBpIDwgbGVuKSB7CiAgICAgICAgICAgIGMgPSBjIDw8IDYgfCBidWZbaSsrXSAmIDYzOwogICAgICAgICAgICBjX2xlbi0tOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGNfbGVuID4gMSkgewogICAgICAgICAgICB1dGYxNmJ1ZltvdXQrK10gPSA2NTUzMzsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoYyA8IDY1NTM2KSB7CiAgICAgICAgICAgIHV0ZjE2YnVmW291dCsrXSA9IGM7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBjIC09IDY1NTM2OwogICAgICAgICAgICB1dGYxNmJ1ZltvdXQrK10gPSA1NTI5NiB8IGMgPj4gMTAgJiAxMDIzOwogICAgICAgICAgICB1dGYxNmJ1ZltvdXQrK10gPSA1NjMyMCB8IGMgJiAxMDIzOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gYnVmMmJpbnN0cmluZyh1dGYxNmJ1Ziwgb3V0KTsKICAgICAgfTsKICAgICAgbW9kdWxlLmV4cG9ydHMudXRmOGJvcmRlciA9IChidWYsIG1heDMpID0+IHsKICAgICAgICBtYXgzID0gbWF4MyB8fCBidWYubGVuZ3RoOwogICAgICAgIGlmIChtYXgzID4gYnVmLmxlbmd0aCkgewogICAgICAgICAgbWF4MyA9IGJ1Zi5sZW5ndGg7CiAgICAgICAgfQogICAgICAgIGxldCBwb3MgPSBtYXgzIC0gMTsKICAgICAgICB3aGlsZSAocG9zID49IDAgJiYgKGJ1Zltwb3NdICYgMTkyKSA9PT0gMTI4KSB7CiAgICAgICAgICBwb3MtLTsKICAgICAgICB9CiAgICAgICAgaWYgKHBvcyA8IDApIHsKICAgICAgICAgIHJldHVybiBtYXgzOwogICAgICAgIH0KICAgICAgICBpZiAocG9zID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gbWF4MzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHBvcyArIF91dGY4bGVuW2J1Zltwb3NdXSA+IG1heDMgPyBwb3MgOiBtYXgzOwogICAgICB9OwogICAgfQogIH0pOwoKICAvLyBub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9tZXNzYWdlcy5qcwogIHZhciByZXF1aXJlX21lc3NhZ2VzID0gX19jb21tb25KUyh7CiAgICAibm9kZV9tb2R1bGVzL3Bha28vbGliL3psaWIvbWVzc2FnZXMuanMiKGV4cG9ydHMyLCBtb2R1bGUpIHsKICAgICAgInVzZSBzdHJpY3QiOwogICAgICBtb2R1bGUuZXhwb3J0cyA9IHsKICAgICAgICAyOiAibmVlZCBkaWN0aW9uYXJ5IiwKICAgICAgICAvKiBaX05FRURfRElDVCAgICAgICAyICAqLwogICAgICAgIDE6ICJzdHJlYW0gZW5kIiwKICAgICAgICAvKiBaX1NUUkVBTV9FTkQgICAgICAxICAqLwogICAgICAgIDA6ICIiLAogICAgICAgIC8qIFpfT0sgICAgICAgICAgICAgIDAgICovCiAgICAgICAgIi0xIjogImZpbGUgZXJyb3IiLAogICAgICAgIC8qIFpfRVJSTk8gICAgICAgICAoLTEpICovCiAgICAgICAgIi0yIjogInN0cmVhbSBlcnJvciIsCiAgICAgICAgLyogWl9TVFJFQU1fRVJST1IgICgtMikgKi8KICAgICAgICAiLTMiOiAiZGF0YSBlcnJvciIsCiAgICAgICAgLyogWl9EQVRBX0VSUk9SICAgICgtMykgKi8KICAgICAgICAiLTQiOiAiaW5zdWZmaWNpZW50IG1lbW9yeSIsCiAgICAgICAgLyogWl9NRU1fRVJST1IgICAgICgtNCkgKi8KICAgICAgICAiLTUiOiAiYnVmZmVyIGVycm9yIiwKICAgICAgICAvKiBaX0JVRl9FUlJPUiAgICAgKC01KSAqLwogICAgICAgICItNiI6ICJpbmNvbXBhdGlibGUgdmVyc2lvbiIKICAgICAgICAvKiBaX1ZFUlNJT05fRVJST1IgKC02KSAqLwogICAgICB9OwogICAgfQogIH0pOwoKICAvLyBub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi96c3RyZWFtLmpzCiAgdmFyIHJlcXVpcmVfenN0cmVhbSA9IF9fY29tbW9uSlMoewogICAgIm5vZGVfbW9kdWxlcy9wYWtvL2xpYi96bGliL3pzdHJlYW0uanMiKGV4cG9ydHMyLCBtb2R1bGUpIHsKICAgICAgInVzZSBzdHJpY3QiOwogICAgICBmdW5jdGlvbiBaU3RyZWFtKCkgewogICAgICAgIHRoaXMuaW5wdXQgPSBudWxsOwogICAgICAgIHRoaXMubmV4dF9pbiA9IDA7CiAgICAgICAgdGhpcy5hdmFpbF9pbiA9IDA7CiAgICAgICAgdGhpcy50b3RhbF9pbiA9IDA7CiAgICAgICAgdGhpcy5vdXRwdXQgPSBudWxsOwogICAgICAgIHRoaXMubmV4dF9vdXQgPSAwOwogICAgICAgIHRoaXMuYXZhaWxfb3V0ID0gMDsKICAgICAgICB0aGlzLnRvdGFsX291dCA9IDA7CiAgICAgICAgdGhpcy5tc2cgPSAiIjsKICAgICAgICB0aGlzLnN0YXRlID0gbnVsbDsKICAgICAgICB0aGlzLmRhdGFfdHlwZSA9IDI7CiAgICAgICAgdGhpcy5hZGxlciA9IDA7CiAgICAgIH0KICAgICAgbW9kdWxlLmV4cG9ydHMgPSBaU3RyZWFtOwogICAgfQogIH0pOwoKICAvLyBub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9nemhlYWRlci5qcwogIHZhciByZXF1aXJlX2d6aGVhZGVyID0gX19jb21tb25KUyh7CiAgICAibm9kZV9tb2R1bGVzL3Bha28vbGliL3psaWIvZ3poZWFkZXIuanMiKGV4cG9ydHMyLCBtb2R1bGUpIHsKICAgICAgInVzZSBzdHJpY3QiOwogICAgICBmdW5jdGlvbiBHWmhlYWRlcigpIHsKICAgICAgICB0aGlzLnRleHQgPSAwOwogICAgICAgIHRoaXMudGltZSA9IDA7CiAgICAgICAgdGhpcy54ZmxhZ3MgPSAwOwogICAgICAgIHRoaXMub3MgPSAwOwogICAgICAgIHRoaXMuZXh0cmEgPSBudWxsOwogICAgICAgIHRoaXMuZXh0cmFfbGVuID0gMDsKICAgICAgICB0aGlzLm5hbWUgPSAiIjsKICAgICAgICB0aGlzLmNvbW1lbnQgPSAiIjsKICAgICAgICB0aGlzLmhjcmMgPSAwOwogICAgICAgIHRoaXMuZG9uZSA9IGZhbHNlOwogICAgICB9CiAgICAgIG1vZHVsZS5leHBvcnRzID0gR1poZWFkZXI7CiAgICB9CiAgfSk7CgogIC8vIG5vZGVfbW9kdWxlcy9wYWtvL2xpYi9pbmZsYXRlLmpzCiAgdmFyIHJlcXVpcmVfaW5mbGF0ZTIgPSBfX2NvbW1vbkpTKHsKICAgICJub2RlX21vZHVsZXMvcGFrby9saWIvaW5mbGF0ZS5qcyIoZXhwb3J0czIsIG1vZHVsZSkgewogICAgICAidXNlIHN0cmljdCI7CiAgICAgIHZhciB6bGliX2luZmxhdGUgPSByZXF1aXJlX2luZmxhdGUoKTsKICAgICAgdmFyIHV0aWxzID0gcmVxdWlyZV9jb21tb24oKTsKICAgICAgdmFyIHN0cmluZ3MgPSByZXF1aXJlX3N0cmluZ3MoKTsKICAgICAgdmFyIG1zZyA9IHJlcXVpcmVfbWVzc2FnZXMoKTsKICAgICAgdmFyIFpTdHJlYW0gPSByZXF1aXJlX3pzdHJlYW0oKTsKICAgICAgdmFyIEdaaGVhZGVyID0gcmVxdWlyZV9nemhlYWRlcigpOwogICAgICB2YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nOwogICAgICB2YXIgewogICAgICAgIFpfTk9fRkxVU0gsCiAgICAgICAgWl9GSU5JU0gsCiAgICAgICAgWl9PSywKICAgICAgICBaX1NUUkVBTV9FTkQsCiAgICAgICAgWl9ORUVEX0RJQ1QsCiAgICAgICAgWl9TVFJFQU1fRVJST1IsCiAgICAgICAgWl9EQVRBX0VSUk9SLAogICAgICAgIFpfTUVNX0VSUk9SCiAgICAgIH0gPSByZXF1aXJlX2NvbnN0YW50cygpOwogICAgICBmdW5jdGlvbiBJbmZsYXRlKG9wdGlvbnMpIHsKICAgICAgICB0aGlzLm9wdGlvbnMgPSB1dGlscy5hc3NpZ24oewogICAgICAgICAgY2h1bmtTaXplOiAxMDI0ICogNjQsCiAgICAgICAgICB3aW5kb3dCaXRzOiAxNSwKICAgICAgICAgIHRvOiAiIgogICAgICAgIH0sIG9wdGlvbnMgfHwge30pOwogICAgICAgIGNvbnN0IG9wdCA9IHRoaXMub3B0aW9uczsKICAgICAgICBpZiAob3B0LnJhdyAmJiBvcHQud2luZG93Qml0cyA+PSAwICYmIG9wdC53aW5kb3dCaXRzIDwgMTYpIHsKICAgICAgICAgIG9wdC53aW5kb3dCaXRzID0gLW9wdC53aW5kb3dCaXRzOwogICAgICAgICAgaWYgKG9wdC53aW5kb3dCaXRzID09PSAwKSB7CiAgICAgICAgICAgIG9wdC53aW5kb3dCaXRzID0gLTE1OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAob3B0LndpbmRvd0JpdHMgPj0gMCAmJiBvcHQud2luZG93Qml0cyA8IDE2ICYmICEob3B0aW9ucyAmJiBvcHRpb25zLndpbmRvd0JpdHMpKSB7CiAgICAgICAgICBvcHQud2luZG93Qml0cyArPSAzMjsKICAgICAgICB9CiAgICAgICAgaWYgKG9wdC53aW5kb3dCaXRzID4gMTUgJiYgb3B0LndpbmRvd0JpdHMgPCA0OCkgewogICAgICAgICAgaWYgKChvcHQud2luZG93Qml0cyAmIDE1KSA9PT0gMCkgewogICAgICAgICAgICBvcHQud2luZG93Qml0cyB8PSAxNTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgdGhpcy5lcnIgPSAwOwogICAgICAgIHRoaXMubXNnID0gIiI7CiAgICAgICAgdGhpcy5lbmRlZCA9IGZhbHNlOwogICAgICAgIHRoaXMuY2h1bmtzID0gW107CiAgICAgICAgdGhpcy5zdHJtID0gbmV3IFpTdHJlYW0oKTsKICAgICAgICB0aGlzLnN0cm0uYXZhaWxfb3V0ID0gMDsKICAgICAgICBsZXQgc3RhdHVzID0gemxpYl9pbmZsYXRlLmluZmxhdGVJbml0MigKICAgICAgICAgIHRoaXMuc3RybSwKICAgICAgICAgIG9wdC53aW5kb3dCaXRzCiAgICAgICAgKTsKICAgICAgICBpZiAoc3RhdHVzICE9PSBaX09LKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnW3N0YXR1c10pOwogICAgICAgIH0KICAgICAgICB0aGlzLmhlYWRlciA9IG5ldyBHWmhlYWRlcigpOwogICAgICAgIHpsaWJfaW5mbGF0ZS5pbmZsYXRlR2V0SGVhZGVyKHRoaXMuc3RybSwgdGhpcy5oZWFkZXIpOwogICAgICAgIGlmIChvcHQuZGljdGlvbmFyeSkgewogICAgICAgICAgaWYgKHR5cGVvZiBvcHQuZGljdGlvbmFyeSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgb3B0LmRpY3Rpb25hcnkgPSBzdHJpbmdzLnN0cmluZzJidWYob3B0LmRpY3Rpb25hcnkpOwogICAgICAgICAgfSBlbHNlIGlmICh0b1N0cmluZy5jYWxsKG9wdC5kaWN0aW9uYXJ5KSA9PT0gIltvYmplY3QgQXJyYXlCdWZmZXJdIikgewogICAgICAgICAgICBvcHQuZGljdGlvbmFyeSA9IG5ldyBVaW50OEFycmF5KG9wdC5kaWN0aW9uYXJ5KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChvcHQucmF3KSB7CiAgICAgICAgICAgIHN0YXR1cyA9IHpsaWJfaW5mbGF0ZS5pbmZsYXRlU2V0RGljdGlvbmFyeSh0aGlzLnN0cm0sIG9wdC5kaWN0aW9uYXJ5KTsKICAgICAgICAgICAgaWYgKHN0YXR1cyAhPT0gWl9PSykgewogICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihtc2dbc3RhdHVzXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgSW5mbGF0ZS5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uKGRhdGEsIGZsdXNoX21vZGUpIHsKICAgICAgICBjb25zdCBzdHJtID0gdGhpcy5zdHJtOwogICAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IHRoaXMub3B0aW9ucy5jaHVua1NpemU7CiAgICAgICAgY29uc3QgZGljdGlvbmFyeSA9IHRoaXMub3B0aW9ucy5kaWN0aW9uYXJ5OwogICAgICAgIGxldCBzdGF0dXMsIF9mbHVzaF9tb2RlLCBsYXN0X2F2YWlsX291dDsKICAgICAgICBpZiAodGhpcy5lbmRlZCkgcmV0dXJuIGZhbHNlOwogICAgICAgIGlmIChmbHVzaF9tb2RlID09PSB+fmZsdXNoX21vZGUpIF9mbHVzaF9tb2RlID0gZmx1c2hfbW9kZTsKICAgICAgICBlbHNlIF9mbHVzaF9tb2RlID0gZmx1c2hfbW9kZSA9PT0gdHJ1ZSA/IFpfRklOSVNIIDogWl9OT19GTFVTSDsKICAgICAgICBpZiAodG9TdHJpbmcuY2FsbChkYXRhKSA9PT0gIltvYmplY3QgQXJyYXlCdWZmZXJdIikgewogICAgICAgICAgc3RybS5pbnB1dCA9IG5ldyBVaW50OEFycmF5KGRhdGEpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdHJtLmlucHV0ID0gZGF0YTsKICAgICAgICB9CiAgICAgICAgc3RybS5uZXh0X2luID0gMDsKICAgICAgICBzdHJtLmF2YWlsX2luID0gc3RybS5pbnB1dC5sZW5ndGg7CiAgICAgICAgZm9yICg7IDsgKSB7CiAgICAgICAgICBpZiAoc3RybS5hdmFpbF9vdXQgPT09IDApIHsKICAgICAgICAgICAgc3RybS5vdXRwdXQgPSBuZXcgVWludDhBcnJheShjaHVua1NpemUpOwogICAgICAgICAgICBzdHJtLm5leHRfb3V0ID0gMDsKICAgICAgICAgICAgc3RybS5hdmFpbF9vdXQgPSBjaHVua1NpemU7CiAgICAgICAgICB9CiAgICAgICAgICBzdGF0dXMgPSB6bGliX2luZmxhdGUuaW5mbGF0ZShzdHJtLCBfZmx1c2hfbW9kZSk7CiAgICAgICAgICBpZiAoc3RhdHVzID09PSBaX05FRURfRElDVCAmJiBkaWN0aW9uYXJ5KSB7CiAgICAgICAgICAgIHN0YXR1cyA9IHpsaWJfaW5mbGF0ZS5pbmZsYXRlU2V0RGljdGlvbmFyeShzdHJtLCBkaWN0aW9uYXJ5KTsKICAgICAgICAgICAgaWYgKHN0YXR1cyA9PT0gWl9PSykgewogICAgICAgICAgICAgIHN0YXR1cyA9IHpsaWJfaW5mbGF0ZS5pbmZsYXRlKHN0cm0sIF9mbHVzaF9tb2RlKTsKICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0dXMgPT09IFpfREFUQV9FUlJPUikgewogICAgICAgICAgICAgIHN0YXR1cyA9IFpfTkVFRF9ESUNUOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB3aGlsZSAoc3RybS5hdmFpbF9pbiA+IDAgJiYgc3RhdHVzID09PSBaX1NUUkVBTV9FTkQgJiYgc3RybS5zdGF0ZS53cmFwID4gMCAmJiBkYXRhW3N0cm0ubmV4dF9pbl0gIT09IDApIHsKICAgICAgICAgICAgemxpYl9pbmZsYXRlLmluZmxhdGVSZXNldChzdHJtKTsKICAgICAgICAgICAgc3RhdHVzID0gemxpYl9pbmZsYXRlLmluZmxhdGUoc3RybSwgX2ZsdXNoX21vZGUpOwogICAgICAgICAgfQogICAgICAgICAgc3dpdGNoIChzdGF0dXMpIHsKICAgICAgICAgICAgY2FzZSBaX1NUUkVBTV9FUlJPUjoKICAgICAgICAgICAgY2FzZSBaX0RBVEFfRVJST1I6CiAgICAgICAgICAgIGNhc2UgWl9ORUVEX0RJQ1Q6CiAgICAgICAgICAgIGNhc2UgWl9NRU1fRVJST1I6CiAgICAgICAgICAgICAgdGhpcy5vbkVuZChzdGF0dXMpOwogICAgICAgICAgICAgIHRoaXMuZW5kZWQgPSB0cnVlOwogICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICAgIGxhc3RfYXZhaWxfb3V0ID0gc3RybS5hdmFpbF9vdXQ7CiAgICAgICAgICBpZiAoc3RybS5uZXh0X291dCkgewogICAgICAgICAgICBpZiAoc3RybS5hdmFpbF9vdXQgPT09IDAgfHwgc3RhdHVzID09PSBaX1NUUkVBTV9FTkQpIHsKICAgICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnRvID09PSAic3RyaW5nIikgewogICAgICAgICAgICAgICAgbGV0IG5leHRfb3V0X3V0ZjggPSBzdHJpbmdzLnV0Zjhib3JkZXIoc3RybS5vdXRwdXQsIHN0cm0ubmV4dF9vdXQpOwogICAgICAgICAgICAgICAgbGV0IHRhaWwgPSBzdHJtLm5leHRfb3V0IC0gbmV4dF9vdXRfdXRmODsKICAgICAgICAgICAgICAgIGxldCB1dGY4c3RyID0gc3RyaW5ncy5idWYyc3RyaW5nKHN0cm0ub3V0cHV0LCBuZXh0X291dF91dGY4KTsKICAgICAgICAgICAgICAgIHN0cm0ubmV4dF9vdXQgPSB0YWlsOwogICAgICAgICAgICAgICAgc3RybS5hdmFpbF9vdXQgPSBjaHVua1NpemUgLSB0YWlsOwogICAgICAgICAgICAgICAgaWYgKHRhaWwpIHN0cm0ub3V0cHV0LnNldChzdHJtLm91dHB1dC5zdWJhcnJheShuZXh0X291dF91dGY4LCBuZXh0X291dF91dGY4ICsgdGFpbCksIDApOwogICAgICAgICAgICAgICAgdGhpcy5vbkRhdGEodXRmOHN0cik7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRoaXMub25EYXRhKHN0cm0ub3V0cHV0Lmxlbmd0aCA9PT0gc3RybS5uZXh0X291dCA/IHN0cm0ub3V0cHV0IDogc3RybS5vdXRwdXQuc3ViYXJyYXkoMCwgc3RybS5uZXh0X291dCkpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKHN0YXR1cyA9PT0gWl9PSyAmJiBsYXN0X2F2YWlsX291dCA9PT0gMCkgY29udGludWU7CiAgICAgICAgICBpZiAoc3RhdHVzID09PSBaX1NUUkVBTV9FTkQpIHsKICAgICAgICAgICAgc3RhdHVzID0gemxpYl9pbmZsYXRlLmluZmxhdGVFbmQodGhpcy5zdHJtKTsKICAgICAgICAgICAgdGhpcy5vbkVuZChzdGF0dXMpOwogICAgICAgICAgICB0aGlzLmVuZGVkID0gdHJ1ZTsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoc3RybS5hdmFpbF9pbiA9PT0gMCkgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9OwogICAgICBJbmZsYXRlLnByb3RvdHlwZS5vbkRhdGEgPSBmdW5jdGlvbihjaHVuaykgewogICAgICAgIHRoaXMuY2h1bmtzLnB1c2goY2h1bmspOwogICAgICB9OwogICAgICBJbmZsYXRlLnByb3RvdHlwZS5vbkVuZCA9IGZ1bmN0aW9uKHN0YXR1cykgewogICAgICAgIGlmIChzdGF0dXMgPT09IFpfT0spIHsKICAgICAgICAgIGlmICh0aGlzLm9wdGlvbnMudG8gPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgIHRoaXMucmVzdWx0ID0gdGhpcy5jaHVua3Muam9pbigiIik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aGlzLnJlc3VsdCA9IHV0aWxzLmZsYXR0ZW5DaHVua3ModGhpcy5jaHVua3MpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB0aGlzLmNodW5rcyA9IFtdOwogICAgICAgIHRoaXMuZXJyID0gc3RhdHVzOwogICAgICAgIHRoaXMubXNnID0gdGhpcy5zdHJtLm1zZzsKICAgICAgfTsKICAgICAgZnVuY3Rpb24gaW5mbGF0ZShpbnB1dCwgb3B0aW9ucykgewogICAgICAgIGNvbnN0IGluZmxhdG9yID0gbmV3IEluZmxhdGUob3B0aW9ucyk7CiAgICAgICAgaW5mbGF0b3IucHVzaChpbnB1dCk7CiAgICAgICAgaWYgKGluZmxhdG9yLmVycikgdGhyb3cgaW5mbGF0b3IubXNnIHx8IG1zZ1tpbmZsYXRvci5lcnJdOwogICAgICAgIHJldHVybiBpbmZsYXRvci5yZXN1bHQ7CiAgICAgIH0KICAgICAgZnVuY3Rpb24gaW5mbGF0ZVJhdyhpbnB1dCwgb3B0aW9ucykgewogICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9OwogICAgICAgIG9wdGlvbnMucmF3ID0gdHJ1ZTsKICAgICAgICByZXR1cm4gaW5mbGF0ZShpbnB1dCwgb3B0aW9ucyk7CiAgICAgIH0KICAgICAgbW9kdWxlLmV4cG9ydHMuSW5mbGF0ZSA9IEluZmxhdGU7CiAgICAgIG1vZHVsZS5leHBvcnRzLmluZmxhdGUgPSBpbmZsYXRlOwogICAgICBtb2R1bGUuZXhwb3J0cy5pbmZsYXRlUmF3ID0gaW5mbGF0ZVJhdzsKICAgICAgbW9kdWxlLmV4cG9ydHMudW5nemlwID0gaW5mbGF0ZTsKICAgICAgbW9kdWxlLmV4cG9ydHMuY29uc3RhbnRzID0gcmVxdWlyZV9jb25zdGFudHMoKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2RlY29kZUdvb2dsZUVhcnRoRW50ZXJwcmlzZVBhY2tldC5qcwogIHZhciBkZWNvZGVHb29nbGVFYXJ0aEVudGVycHJpc2VQYWNrZXRfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGRlY29kZUdvb2dsZUVhcnRoRW50ZXJwcmlzZVBhY2tldF9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBkZWNvZGVHb29nbGVFYXJ0aEVudGVycHJpc2VQYWNrZXRfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGRlY29kZUdvb2dsZUVhcnRoRW50ZXJwcmlzZVBhY2tldChwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICBjb25zdCB0eXBlID0gVHlwZXMuZnJvbVN0cmluZyhwYXJhbWV0ZXJzLnR5cGUpOwogICAgbGV0IGJ1ZmZlciA9IHBhcmFtZXRlcnMuYnVmZmVyOwogICAgZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlRGF0YV9kZWZhdWx0KHBhcmFtZXRlcnMua2V5LCBidWZmZXIpOwogICAgY29uc3QgdW5jb21wcmVzc2VkVGVycmFpbiA9IHVuY29tcHJlc3NQYWNrZXQoYnVmZmVyKTsKICAgIGJ1ZmZlciA9IHVuY29tcHJlc3NlZFRlcnJhaW4uYnVmZmVyOwogICAgY29uc3QgbGVuZ3RoID0gdW5jb21wcmVzc2VkVGVycmFpbi5sZW5ndGg7CiAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgY2FzZSBUeXBlcy5NRVRBREFUQToKICAgICAgICByZXR1cm4gcHJvY2Vzc01ldGFkYXRhKGJ1ZmZlciwgbGVuZ3RoLCBwYXJhbWV0ZXJzLnF1YWRLZXkpOwogICAgICBjYXNlIFR5cGVzLlRFUlJBSU46CiAgICAgICAgcmV0dXJuIHByb2Nlc3NUZXJyYWluKGJ1ZmZlciwgbGVuZ3RoLCB0cmFuc2ZlcmFibGVPYmplY3RzKTsKICAgICAgY2FzZSBUeXBlcy5EQlJPT1Q6CiAgICAgICAgdHJhbnNmZXJhYmxlT2JqZWN0cy5wdXNoKGJ1ZmZlcik7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGJ1ZmZlcgogICAgICAgIH07CiAgICB9CiAgfQogIGZ1bmN0aW9uIHByb2Nlc3NNZXRhZGF0YShidWZmZXIsIHRvdGFsU2l6ZSwgcXVhZEtleSkgewogICAgY29uc3QgZHYgPSBuZXcgRGF0YVZpZXcoYnVmZmVyKTsKICAgIGxldCBvZmZzZXQgPSAwOwogICAgY29uc3QgbWFnaWMgPSBkdi5nZXRVaW50MzIob2Zmc2V0LCB0cnVlKTsKICAgIG9mZnNldCArPSBzaXplT2ZVaW50MzIyOwogICAgaWYgKG1hZ2ljICE9PSBxdE1hZ2ljKSB7CiAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3JfZGVmYXVsdCgiSW52YWxpZCBtYWdpYyIpOwogICAgfQogICAgY29uc3QgZGF0YVR5cGVJZCA9IGR2LmdldFVpbnQzMihvZmZzZXQsIHRydWUpOwogICAgb2Zmc2V0ICs9IHNpemVPZlVpbnQzMjI7CiAgICBpZiAoZGF0YVR5cGVJZCAhPT0gMSkgewogICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yX2RlZmF1bHQoIkludmFsaWQgZGF0YSB0eXBlLiBNdXN0IGJlIDEgZm9yIFF1YWRUcmVlUGFja2V0Iik7CiAgICB9CiAgICBjb25zdCBxdWFkVmVyc2lvbiA9IGR2LmdldFVpbnQzMihvZmZzZXQsIHRydWUpOwogICAgb2Zmc2V0ICs9IHNpemVPZlVpbnQzMjI7CiAgICBpZiAocXVhZFZlcnNpb24gIT09IDIpIHsKICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KAogICAgICAgICJJbnZhbGlkIFF1YWRUcmVlUGFja2V0IHZlcnNpb24uIE9ubHkgdmVyc2lvbiAyIGlzIHN1cHBvcnRlZC4iCiAgICAgICk7CiAgICB9CiAgICBjb25zdCBudW1JbnN0YW5jZXMgPSBkdi5nZXRJbnQzMihvZmZzZXQsIHRydWUpOwogICAgb2Zmc2V0ICs9IHNpemVPZkludDMyMjsKICAgIGNvbnN0IGRhdGFJbnN0YW5jZVNpemUgPSBkdi5nZXRJbnQzMihvZmZzZXQsIHRydWUpOwogICAgb2Zmc2V0ICs9IHNpemVPZkludDMyMjsKICAgIGlmIChkYXRhSW5zdGFuY2VTaXplICE9PSAzMikgewogICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yX2RlZmF1bHQoIkludmFsaWQgaW5zdGFuY2Ugc2l6ZS4iKTsKICAgIH0KICAgIGNvbnN0IGRhdGFCdWZmZXJPZmZzZXQgPSBkdi5nZXRJbnQzMihvZmZzZXQsIHRydWUpOwogICAgb2Zmc2V0ICs9IHNpemVPZkludDMyMjsKICAgIGNvbnN0IGRhdGFCdWZmZXJTaXplID0gZHYuZ2V0SW50MzIob2Zmc2V0LCB0cnVlKTsKICAgIG9mZnNldCArPSBzaXplT2ZJbnQzMjI7CiAgICBjb25zdCBtZXRhQnVmZmVyU2l6ZSA9IGR2LmdldEludDMyKG9mZnNldCwgdHJ1ZSk7CiAgICBvZmZzZXQgKz0gc2l6ZU9mSW50MzIyOwogICAgaWYgKGRhdGFCdWZmZXJPZmZzZXQgIT09IG51bUluc3RhbmNlcyAqIGRhdGFJbnN0YW5jZVNpemUgKyBvZmZzZXQpIHsKICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KCJJbnZhbGlkIGRhdGFCdWZmZXJPZmZzZXQiKTsKICAgIH0KICAgIGlmIChkYXRhQnVmZmVyT2Zmc2V0ICsgZGF0YUJ1ZmZlclNpemUgKyBtZXRhQnVmZmVyU2l6ZSAhPT0gdG90YWxTaXplKSB7CiAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3JfZGVmYXVsdCgiSW52YWxpZCBwYWNrZXQgb2Zmc2V0cyIpOwogICAgfQogICAgY29uc3QgaW5zdGFuY2VzID0gW107CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUluc3RhbmNlczsgKytpKSB7CiAgICAgIGNvbnN0IGJpdGZpZWxkID0gZHYuZ2V0VWludDgob2Zmc2V0KTsKICAgICAgKytvZmZzZXQ7CiAgICAgICsrb2Zmc2V0OwogICAgICBjb25zdCBjbm9kZVZlcnNpb24gPSBkdi5nZXRVaW50MTYob2Zmc2V0LCB0cnVlKTsKICAgICAgb2Zmc2V0ICs9IHNpemVPZlVpbnQxNjI7CiAgICAgIGNvbnN0IGltYWdlVmVyc2lvbiA9IGR2LmdldFVpbnQxNihvZmZzZXQsIHRydWUpOwogICAgICBvZmZzZXQgKz0gc2l6ZU9mVWludDE2MjsKICAgICAgY29uc3QgdGVycmFpblZlcnNpb24gPSBkdi5nZXRVaW50MTYob2Zmc2V0LCB0cnVlKTsKICAgICAgb2Zmc2V0ICs9IHNpemVPZlVpbnQxNjI7CiAgICAgIG9mZnNldCArPSBzaXplT2ZVaW50MTYyOwogICAgICBvZmZzZXQgKz0gc2l6ZU9mVWludDE2MjsKICAgICAgb2Zmc2V0ICs9IHNpemVPZkludDMyMjsKICAgICAgb2Zmc2V0ICs9IHNpemVPZkludDMyMjsKICAgICAgb2Zmc2V0ICs9IDg7CiAgICAgIGNvbnN0IGltYWdlUHJvdmlkZXIgPSBkdi5nZXRVaW50OChvZmZzZXQrKyk7CiAgICAgIGNvbnN0IHRlcnJhaW5Qcm92aWRlciA9IGR2LmdldFVpbnQ4KG9mZnNldCsrKTsKICAgICAgb2Zmc2V0ICs9IHNpemVPZlVpbnQxNjI7CiAgICAgIGluc3RhbmNlcy5wdXNoKAogICAgICAgIG5ldyBHb29nbGVFYXJ0aEVudGVycHJpc2VUaWxlSW5mb3JtYXRpb25fZGVmYXVsdCgKICAgICAgICAgIGJpdGZpZWxkLAogICAgICAgICAgY25vZGVWZXJzaW9uLAogICAgICAgICAgaW1hZ2VWZXJzaW9uLAogICAgICAgICAgdGVycmFpblZlcnNpb24sCiAgICAgICAgICBpbWFnZVByb3ZpZGVyLAogICAgICAgICAgdGVycmFpblByb3ZpZGVyCiAgICAgICAgKQogICAgICApOwogICAgfQogICAgY29uc3QgdGlsZUluZm8gPSBbXTsKICAgIGxldCBpbmRleCA9IDA7CiAgICBmdW5jdGlvbiBwb3B1bGF0ZVRpbGVzKHBhcmVudEtleSwgcGFyZW50LCBsZXZlbDIpIHsKICAgICAgbGV0IGlzTGVhZiA9IGZhbHNlOwogICAgICBpZiAobGV2ZWwyID09PSA0KSB7CiAgICAgICAgaWYgKHBhcmVudC5oYXNTdWJ0cmVlKCkpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgaXNMZWFmID0gdHJ1ZTsKICAgICAgfQogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDQ7ICsraSkgewogICAgICAgIGNvbnN0IGNoaWxkS2V5ID0gcGFyZW50S2V5ICsgaS50b1N0cmluZygpOwogICAgICAgIGlmIChpc0xlYWYpIHsKICAgICAgICAgIHRpbGVJbmZvW2NoaWxkS2V5XSA9IG51bGw7CiAgICAgICAgfSBlbHNlIGlmIChsZXZlbDIgPCA0KSB7CiAgICAgICAgICBpZiAoIXBhcmVudC5oYXNDaGlsZChpKSkgewogICAgICAgICAgICB0aWxlSW5mb1tjaGlsZEtleV0gPSBudWxsOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgaWYgKGluZGV4ID09PSBudW1JbnN0YW5jZXMpIHsKICAgICAgICAgICAgICBjb25zb2xlLmxvZygiSW5jb3JyZWN0IG51bWJlciBvZiBpbnN0YW5jZXMiKTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgaW5zdGFuY2UgPSBpbnN0YW5jZXNbaW5kZXgrK107CiAgICAgICAgICAgIHRpbGVJbmZvW2NoaWxkS2V5XSA9IGluc3RhbmNlOwogICAgICAgICAgICBwb3B1bGF0ZVRpbGVzKGNoaWxkS2V5LCBpbnN0YW5jZSwgbGV2ZWwyICsgMSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBsZXQgbGV2ZWwgPSAwOwogICAgY29uc3Qgcm9vdCA9IGluc3RhbmNlc1tpbmRleCsrXTsKICAgIGlmIChxdWFkS2V5ID09PSAiIikgewogICAgICArK2xldmVsOwogICAgfSBlbHNlIHsKICAgICAgdGlsZUluZm9bcXVhZEtleV0gPSByb290OwogICAgfQogICAgcG9wdWxhdGVUaWxlcyhxdWFkS2V5LCByb290LCBsZXZlbCk7CiAgICByZXR1cm4gdGlsZUluZm87CiAgfQogIGZ1bmN0aW9uIHByb2Nlc3NUZXJyYWluKGJ1ZmZlciwgdG90YWxTaXplLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICBjb25zdCBkdiA9IG5ldyBEYXRhVmlldyhidWZmZXIpOwogICAgY29uc3QgYWR2YW5jZU1lc2ggPSBmdW5jdGlvbihwb3MpIHsKICAgICAgZm9yIChsZXQgc3ViID0gMDsgc3ViIDwgbnVtU3ViTWVzaGVzUGVyTWVzaDsgKytzdWIpIHsKICAgICAgICBjb25zdCBzaXplID0gZHYuZ2V0VWludDMyKHBvcywgdHJ1ZSk7CiAgICAgICAgcG9zICs9IHNpemVPZlVpbnQzMjI7CiAgICAgICAgcG9zICs9IHNpemU7CiAgICAgICAgaWYgKHBvcyA+IHRvdGFsU2l6ZSkgewogICAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KCJNYWxmb3JtZWQgdGVycmFpbiBwYWNrZXQgZm91bmQuIik7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBwb3M7CiAgICB9OwogICAgbGV0IG9mZnNldCA9IDA7CiAgICBjb25zdCB0ZXJyYWluTWVzaGVzID0gW107CiAgICB3aGlsZSAodGVycmFpbk1lc2hlcy5sZW5ndGggPCBudW1NZXNoZXNQZXJQYWNrZXQpIHsKICAgICAgY29uc3Qgc3RhcnQgPSBvZmZzZXQ7CiAgICAgIG9mZnNldCA9IGFkdmFuY2VNZXNoKG9mZnNldCk7CiAgICAgIGNvbnN0IG1lc2ggPSBidWZmZXIuc2xpY2Uoc3RhcnQsIG9mZnNldCk7CiAgICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaChtZXNoKTsKICAgICAgdGVycmFpbk1lc2hlcy5wdXNoKG1lc2gpOwogICAgfQogICAgcmV0dXJuIHRlcnJhaW5NZXNoZXM7CiAgfQogIGZ1bmN0aW9uIHVuY29tcHJlc3NQYWNrZXQoZGF0YSkgewogICAgY29uc3QgZHYgPSBuZXcgRGF0YVZpZXcoZGF0YSk7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIGNvbnN0IG1hZ2ljID0gZHYuZ2V0VWludDMyKG9mZnNldCwgdHJ1ZSk7CiAgICBvZmZzZXQgKz0gc2l6ZU9mVWludDMyMjsKICAgIGlmIChtYWdpYyAhPT0gY29tcHJlc3NlZE1hZ2ljMiAmJiBtYWdpYyAhPT0gY29tcHJlc3NlZE1hZ2ljU3dhcDIpIHsKICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KCJJbnZhbGlkIG1hZ2ljIik7CiAgICB9CiAgICBjb25zdCBzaXplID0gZHYuZ2V0VWludDMyKG9mZnNldCwgbWFnaWMgPT09IGNvbXByZXNzZWRNYWdpYzIpOwogICAgb2Zmc2V0ICs9IHNpemVPZlVpbnQzMjI7CiAgICBjb25zdCBjb21wcmVzc2VkUGFja2V0ID0gbmV3IFVpbnQ4QXJyYXkoZGF0YSwgb2Zmc2V0KTsKICAgIGNvbnN0IHVuY29tcHJlc3NlZFBhY2tldCA9IGltcG9ydF9pbmZsYXRlLmRlZmF1bHQuaW5mbGF0ZShjb21wcmVzc2VkUGFja2V0KTsKICAgIGlmICh1bmNvbXByZXNzZWRQYWNrZXQubGVuZ3RoICE9PSBzaXplKSB7CiAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3JfZGVmYXVsdCgiU2l6ZSBvZiBwYWNrZXQgZG9lc24ndCBtYXRjaCBoZWFkZXIiKTsKICAgIH0KICAgIHJldHVybiB1bmNvbXByZXNzZWRQYWNrZXQ7CiAgfQogIHZhciBpbXBvcnRfaW5mbGF0ZSwgc2l6ZU9mVWludDE2Miwgc2l6ZU9mSW50MzIyLCBzaXplT2ZVaW50MzIyLCBUeXBlcywgcXRNYWdpYywgbnVtTWVzaGVzUGVyUGFja2V0LCBudW1TdWJNZXNoZXNQZXJNZXNoLCBjb21wcmVzc2VkTWFnaWMyLCBjb21wcmVzc2VkTWFnaWNTd2FwMiwgZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlUGFja2V0X2RlZmF1bHQ7CiAgdmFyIGluaXRfZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlUGFja2V0ID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9kZWNvZGVHb29nbGVFYXJ0aEVudGVycHJpc2VQYWNrZXQuanMiKCkgewogICAgICBpbml0X2RlY29kZUdvb2dsZUVhcnRoRW50ZXJwcmlzZURhdGEoKTsKICAgICAgaW5pdF9Hb29nbGVFYXJ0aEVudGVycHJpc2VUaWxlSW5mb3JtYXRpb24oKTsKICAgICAgaW5pdF9SdW50aW1lRXJyb3IoKTsKICAgICAgaW1wb3J0X2luZmxhdGUgPSBfX3RvRVNNKHJlcXVpcmVfaW5mbGF0ZTIoKSwgMSk7CiAgICAgIGluaXRfY3JlYXRlVGFza1Byb2Nlc3NvcldvcmtlcigpOwogICAgICBzaXplT2ZVaW50MTYyID0gVWludDE2QXJyYXkuQllURVNfUEVSX0VMRU1FTlQ7CiAgICAgIHNpemVPZkludDMyMiA9IEludDMyQXJyYXkuQllURVNfUEVSX0VMRU1FTlQ7CiAgICAgIHNpemVPZlVpbnQzMjIgPSBVaW50MzJBcnJheS5CWVRFU19QRVJfRUxFTUVOVDsKICAgICAgVHlwZXMgPSB7CiAgICAgICAgTUVUQURBVEE6IDAsCiAgICAgICAgVEVSUkFJTjogMSwKICAgICAgICBEQlJPT1Q6IDIKICAgICAgfTsKICAgICAgVHlwZXMuZnJvbVN0cmluZyA9IGZ1bmN0aW9uKHMpIHsKICAgICAgICBpZiAocyA9PT0gIk1ldGFkYXRhIikgewogICAgICAgICAgcmV0dXJuIFR5cGVzLk1FVEFEQVRBOwogICAgICAgIH0gZWxzZSBpZiAocyA9PT0gIlRlcnJhaW4iKSB7CiAgICAgICAgICByZXR1cm4gVHlwZXMuVEVSUkFJTjsKICAgICAgICB9IGVsc2UgaWYgKHMgPT09ICJEYlJvb3QiKSB7CiAgICAgICAgICByZXR1cm4gVHlwZXMuREJST09UOwogICAgICAgIH0KICAgICAgfTsKICAgICAgcXRNYWdpYyA9IDMyMzAxOwogICAgICBudW1NZXNoZXNQZXJQYWNrZXQgPSA1OwogICAgICBudW1TdWJNZXNoZXNQZXJNZXNoID0gNDsKICAgICAgY29tcHJlc3NlZE1hZ2ljMiA9IDE5NTMwMjk4MDU7CiAgICAgIGNvbXByZXNzZWRNYWdpY1N3YXAyID0gMjkxNzAzNDEwMDsKICAgICAgZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlUGFja2V0X2RlZmF1bHQgPSBjcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyX2RlZmF1bHQoZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlUGFja2V0KTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL3NyZ2JUb0xpbmVhci5qcwogIGZ1bmN0aW9uIHNyZ2JUb0xpbmVhcih2YWx1ZSkgewogICAgQ2hlY2tfZGVmYXVsdC5kZWZpbmVkKCJ2YWx1ZSIsIHZhbHVlKTsKICAgIGlmICh2YWx1ZSA8PSAwLjA0MDQ1KSB7CiAgICAgIHJldHVybiB2YWx1ZSAqIDAuMDc3Mzk5MzgwODA0OTUzNTc7CiAgICB9CiAgICByZXR1cm4gTWF0aC5wb3coCiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1sb3NzLW9mLXByZWNpc2lvbgogICAgICAodmFsdWUgKyAwLjA1NSkgKiAwLjk0Nzg2NzI5ODU3ODE5OTEsCiAgICAgIDIuNAogICAgKTsKICB9CiAgdmFyIHNyZ2JUb0xpbmVhcl9kZWZhdWx0OwogIHZhciBpbml0X3NyZ2JUb0xpbmVhciA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvc3JnYlRvTGluZWFyLmpzIigpIHsKICAgICAgaW5pdF9DaGVjaygpOwogICAgICBzcmdiVG9MaW5lYXJfZGVmYXVsdCA9IHNyZ2JUb0xpbmVhcjsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2RlY29kZUkzUy5qcwogIHZhciBkZWNvZGVJM1NfZXhwb3J0cyA9IHt9OwogIF9fZXhwb3J0KGRlY29kZUkzU19leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBkZWNvZGVJM1NfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIGJpbGluZWFySW50ZXJwb2xhdGUodHgsIHR5LCBoMDAsIGgxMCwgaDAxLCBoMTEpIHsKICAgIGNvbnN0IGEzID0gaDAwICogKDEgLSB0eCkgKyBoMTAgKiB0eDsKICAgIGNvbnN0IGIgPSBoMDEgKiAoMSAtIHR4KSArIGgxMSAqIHR4OwogICAgcmV0dXJuIGEzICogKDEgLSB0eSkgKyBiICogdHk7CiAgfQogIGZ1bmN0aW9uIHNhbXBsZU1hcCh1MywgdjMsIHdpZHRoLCBkYXRhKSB7CiAgICBjb25zdCBhZGRyZXNzID0gdTMgKyB2MyAqIHdpZHRoOwogICAgcmV0dXJuIGRhdGFbYWRkcmVzc107CiAgfQogIGZ1bmN0aW9uIHNhbXBsZUdlb2lkKHNhbXBsZVgsIHNhbXBsZVksIGdlb2lkRGF0YSkgewogICAgY29uc3QgZXh0ZW50ID0gZ2VvaWREYXRhLm5hdGl2ZUV4dGVudDsKICAgIGxldCB4ID0gKHNhbXBsZVggLSBleHRlbnQud2VzdCkgLyAoZXh0ZW50LmVhc3QgLSBleHRlbnQud2VzdCkgKiAoZ2VvaWREYXRhLndpZHRoIC0gMSk7CiAgICBsZXQgeSA9IChzYW1wbGVZIC0gZXh0ZW50LnNvdXRoKSAvIChleHRlbnQubm9ydGggLSBleHRlbnQuc291dGgpICogKGdlb2lkRGF0YS5oZWlnaHQgLSAxKTsKICAgIGNvbnN0IHhpID0gTWF0aC5mbG9vcih4KTsKICAgIGxldCB5aSA9IE1hdGguZmxvb3IoeSk7CiAgICB4IC09IHhpOwogICAgeSAtPSB5aTsKICAgIGNvbnN0IHhOZXh0ID0geGkgPCBnZW9pZERhdGEud2lkdGggPyB4aSArIDEgOiB4aTsKICAgIGxldCB5TmV4dCA9IHlpIDwgZ2VvaWREYXRhLmhlaWdodCA/IHlpICsgMSA6IHlpOwogICAgeWkgPSBnZW9pZERhdGEuaGVpZ2h0IC0gMSAtIHlpOwogICAgeU5leHQgPSBnZW9pZERhdGEuaGVpZ2h0IC0gMSAtIHlOZXh0OwogICAgY29uc3QgaDAwID0gc2FtcGxlTWFwKHhpLCB5aSwgZ2VvaWREYXRhLndpZHRoLCBnZW9pZERhdGEuYnVmZmVyKTsKICAgIGNvbnN0IGgxMCA9IHNhbXBsZU1hcCh4TmV4dCwgeWksIGdlb2lkRGF0YS53aWR0aCwgZ2VvaWREYXRhLmJ1ZmZlcik7CiAgICBjb25zdCBoMDEgPSBzYW1wbGVNYXAoeGksIHlOZXh0LCBnZW9pZERhdGEud2lkdGgsIGdlb2lkRGF0YS5idWZmZXIpOwogICAgY29uc3QgaDExID0gc2FtcGxlTWFwKHhOZXh0LCB5TmV4dCwgZ2VvaWREYXRhLndpZHRoLCBnZW9pZERhdGEuYnVmZmVyKTsKICAgIGxldCBmaW5hbEhlaWdodCA9IGJpbGluZWFySW50ZXJwb2xhdGUoeCwgeSwgaDAwLCBoMTAsIGgwMSwgaDExKTsKICAgIGZpbmFsSGVpZ2h0ID0gZmluYWxIZWlnaHQgKiBnZW9pZERhdGEuc2NhbGUgKyBnZW9pZERhdGEub2Zmc2V0OwogICAgcmV0dXJuIGZpbmFsSGVpZ2h0OwogIH0KICBmdW5jdGlvbiBzYW1wbGVHZW9pZEZyb21MaXN0KGxvbiwgbGF0LCBnZW9pZERhdGFMaXN0KSB7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGdlb2lkRGF0YUxpc3QubGVuZ3RoOyBpKyspIHsKICAgICAgY29uc3QgbG9jYWxFeHRlbnQgPSBnZW9pZERhdGFMaXN0W2ldLm5hdGl2ZUV4dGVudDsKICAgICAgbGV0IGxvY2FsUHQgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGlmIChnZW9pZERhdGFMaXN0W2ldLnByb2plY3Rpb25UeXBlID09PSAiV2ViTWVyY2F0b3IiKSB7CiAgICAgICAgY29uc3QgcmFkaWkgPSBnZW9pZERhdGFMaXN0W2ldLnByb2plY3Rpb24uX2VsbGlwc29pZC5fcmFkaWk7CiAgICAgICAgY29uc3Qgd2ViTWVyY2F0b3JQcm9qID0gbmV3IFdlYk1lcmNhdG9yUHJvamVjdGlvbl9kZWZhdWx0KAogICAgICAgICAgbmV3IEVsbGlwc29pZF9kZWZhdWx0KHJhZGlpLngsIHJhZGlpLnksIHJhZGlpLnopCiAgICAgICAgKTsKICAgICAgICBsb2NhbFB0ID0gd2ViTWVyY2F0b3JQcm9qLnByb2plY3QobmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KGxvbiwgbGF0LCAwKSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbG9jYWxQdC54ID0gbG9uOwogICAgICAgIGxvY2FsUHQueSA9IGxhdDsKICAgICAgfQogICAgICBpZiAobG9jYWxQdC54ID4gbG9jYWxFeHRlbnQud2VzdCAmJiBsb2NhbFB0LnggPCBsb2NhbEV4dGVudC5lYXN0ICYmIGxvY2FsUHQueSA+IGxvY2FsRXh0ZW50LnNvdXRoICYmIGxvY2FsUHQueSA8IGxvY2FsRXh0ZW50Lm5vcnRoKSB7CiAgICAgICAgcmV0dXJuIHNhbXBsZUdlb2lkKGxvY2FsUHQueCwgbG9jYWxQdC55LCBnZW9pZERhdGFMaXN0W2ldKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIDA7CiAgfQogIGZ1bmN0aW9uIG9ydGhvbWV0cmljVG9FbGxpcHNvaWRhbCh2ZXJ0ZXhDb3VudCwgcG9zaXRpb24sIHNjYWxlX3gsIHNjYWxlX3ksIGNlbnRlciwgZ2VvaWREYXRhTGlzdCwgZmFzdCkgewogICAgaWYgKGZhc3QpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgY2VudGVySGVpZ2h0ID0gc2FtcGxlR2VvaWRGcm9tTGlzdCgKICAgICAgY2VudGVyLmxvbmdpdHVkZSwKICAgICAgY2VudGVyLmxhdGl0dWRlLAogICAgICBnZW9pZERhdGFMaXN0CiAgICApOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2ZXJ0ZXhDb3VudDsgKytpKSB7CiAgICAgIGNvbnN0IGhlaWdodCA9IHNhbXBsZUdlb2lkRnJvbUxpc3QoCiAgICAgICAgY2VudGVyLmxvbmdpdHVkZSArIE1hdGhfZGVmYXVsdC50b1JhZGlhbnMoc2NhbGVfeCAqIHBvc2l0aW9uW2kgKiAzXSksCiAgICAgICAgY2VudGVyLmxhdGl0dWRlICsgTWF0aF9kZWZhdWx0LnRvUmFkaWFucyhzY2FsZV95ICogcG9zaXRpb25baSAqIDMgKyAxXSksCiAgICAgICAgZ2VvaWREYXRhTGlzdAogICAgICApOwogICAgICBwb3NpdGlvbltpICogMyArIDJdICs9IGhlaWdodCAtIGNlbnRlckhlaWdodDsKICAgIH0KICB9CiAgZnVuY3Rpb24gdHJhbnNmb3JtVG9Mb2NhbCh2ZXJ0ZXhDb3VudCwgcG9zaXRpb25zLCBub3JtYWxzLCBjYXJ0b2dyYXBoaWNDZW50ZXIsIGNhcnRlc2lhbkNlbnRlciwgcGFyZW50Um90YXRpb24sIGVsbGlwc29pZFJhZGlpU3F1YXJlLCBzY2FsZV94LCBzY2FsZV95KSB7CiAgICBpZiAodmVydGV4Q291bnQgPT09IDAgfHwgIWRlZmluZWRfZGVmYXVsdChwb3NpdGlvbnMpIHx8IHBvc2l0aW9ucy5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgZWxsaXBzb2lkID0gbmV3IEVsbGlwc29pZF9kZWZhdWx0KAogICAgICBNYXRoLnNxcnQoZWxsaXBzb2lkUmFkaWlTcXVhcmUueCksCiAgICAgIE1hdGguc3FydChlbGxpcHNvaWRSYWRpaVNxdWFyZS55KSwKICAgICAgTWF0aC5zcXJ0KGVsbGlwc29pZFJhZGlpU3F1YXJlLnopCiAgICApOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2ZXJ0ZXhDb3VudDsgKytpKSB7CiAgICAgIGNvbnN0IGluZGV4T2Zmc2V0ID0gaSAqIDM7CiAgICAgIGNvbnN0IGluZGV4T2Zmc2V0MSA9IGluZGV4T2Zmc2V0ICsgMTsKICAgICAgY29uc3QgaW5kZXhPZmZzZXQyID0gaW5kZXhPZmZzZXQgKyAyOwogICAgICBjb25zdCBjYXJ0b2dyYXBoaWMyID0gbmV3IENhcnRvZ3JhcGhpY19kZWZhdWx0KCk7CiAgICAgIGNhcnRvZ3JhcGhpYzIubG9uZ2l0dWRlID0gY2FydG9ncmFwaGljQ2VudGVyLmxvbmdpdHVkZSArIE1hdGhfZGVmYXVsdC50b1JhZGlhbnMoc2NhbGVfeCAqIHBvc2l0aW9uc1tpbmRleE9mZnNldF0pOwogICAgICBjYXJ0b2dyYXBoaWMyLmxhdGl0dWRlID0gY2FydG9ncmFwaGljQ2VudGVyLmxhdGl0dWRlICsgTWF0aF9kZWZhdWx0LnRvUmFkaWFucyhzY2FsZV95ICogcG9zaXRpb25zW2luZGV4T2Zmc2V0MV0pOwogICAgICBjYXJ0b2dyYXBoaWMyLmhlaWdodCA9IGNhcnRvZ3JhcGhpY0NlbnRlci5oZWlnaHQgKyBwb3NpdGlvbnNbaW5kZXhPZmZzZXQyXTsKICAgICAgY29uc3QgcG9zaXRpb24gPSB7fTsKICAgICAgZWxsaXBzb2lkLmNhcnRvZ3JhcGhpY1RvQ2FydGVzaWFuKGNhcnRvZ3JhcGhpYzIsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24ueCAtPSBjYXJ0ZXNpYW5DZW50ZXIueDsKICAgICAgcG9zaXRpb24ueSAtPSBjYXJ0ZXNpYW5DZW50ZXIueTsKICAgICAgcG9zaXRpb24ueiAtPSBjYXJ0ZXNpYW5DZW50ZXIuejsKICAgICAgY29uc3Qgcm90YXRlZFBvc2l0aW9uID0ge307CiAgICAgIE1hdHJpeDNfZGVmYXVsdC5tdWx0aXBseUJ5VmVjdG9yKHBhcmVudFJvdGF0aW9uLCBwb3NpdGlvbiwgcm90YXRlZFBvc2l0aW9uKTsKICAgICAgcG9zaXRpb25zW2luZGV4T2Zmc2V0XSA9IHJvdGF0ZWRQb3NpdGlvbi54OwogICAgICBwb3NpdGlvbnNbaW5kZXhPZmZzZXQxXSA9IHJvdGF0ZWRQb3NpdGlvbi55OwogICAgICBwb3NpdGlvbnNbaW5kZXhPZmZzZXQyXSA9IHJvdGF0ZWRQb3NpdGlvbi56OwogICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG5vcm1hbHMpKSB7CiAgICAgICAgY29uc3Qgbm9ybWFsMiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoCiAgICAgICAgICBub3JtYWxzW2luZGV4T2Zmc2V0XSwKICAgICAgICAgIG5vcm1hbHNbaW5kZXhPZmZzZXQxXSwKICAgICAgICAgIG5vcm1hbHNbaW5kZXhPZmZzZXQyXQogICAgICAgICk7CiAgICAgICAgY29uc3Qgcm90YXRlZE5vcm1hbCA9IHt9OwogICAgICAgIE1hdHJpeDNfZGVmYXVsdC5tdWx0aXBseUJ5VmVjdG9yKHBhcmVudFJvdGF0aW9uLCBub3JtYWwyLCByb3RhdGVkTm9ybWFsKTsKICAgICAgICBub3JtYWxzW2luZGV4T2Zmc2V0XSA9IHJvdGF0ZWROb3JtYWwueDsKICAgICAgICBub3JtYWxzW2luZGV4T2Zmc2V0MV0gPSByb3RhdGVkTm9ybWFsLnk7CiAgICAgICAgbm9ybWFsc1tpbmRleE9mZnNldDJdID0gcm90YXRlZE5vcm1hbC56OwogICAgICB9CiAgICB9CiAgfQogIGZ1bmN0aW9uIGNyb3BVVnModmVydGV4Q291bnQsIHV2MHMsIHV2UmVnaW9ucykgewogICAgZm9yIChsZXQgdmVydGV4SW5kZXggPSAwOyB2ZXJ0ZXhJbmRleCA8IHZlcnRleENvdW50OyArK3ZlcnRleEluZGV4KSB7CiAgICAgIGNvbnN0IG1pblUgPSB1dlJlZ2lvbnNbdmVydGV4SW5kZXggKiA0XSAvIDY1NTM1OwogICAgICBjb25zdCBtaW5WID0gdXZSZWdpb25zW3ZlcnRleEluZGV4ICogNCArIDFdIC8gNjU1MzU7CiAgICAgIGNvbnN0IHNjYWxlVSA9ICh1dlJlZ2lvbnNbdmVydGV4SW5kZXggKiA0ICsgMl0gLSB1dlJlZ2lvbnNbdmVydGV4SW5kZXggKiA0XSkgLyA2NTUzNTsKICAgICAgY29uc3Qgc2NhbGVWID0gKHV2UmVnaW9uc1t2ZXJ0ZXhJbmRleCAqIDQgKyAzXSAtIHV2UmVnaW9uc1t2ZXJ0ZXhJbmRleCAqIDQgKyAxXSkgLyA2NTUzNTsKICAgICAgdXYwc1t2ZXJ0ZXhJbmRleCAqIDJdICo9IHNjYWxlVTsKICAgICAgdXYwc1t2ZXJ0ZXhJbmRleCAqIDJdICs9IG1pblU7CiAgICAgIHV2MHNbdmVydGV4SW5kZXggKiAyICsgMV0gKj0gc2NhbGVWOwogICAgICB1djBzW3ZlcnRleEluZGV4ICogMiArIDFdICs9IG1pblY7CiAgICB9CiAgfQogIGZ1bmN0aW9uIGdlbmVyYXRlSW5kZXhBcnJheSh2ZXJ0ZXhDb3VudCwgaW5kaWNlcywgY29sb3JzLCBzcGxpdEdlb21ldHJ5QnlDb2xvclRyYW5zcGFyZW5jeSkgewogICAgY29uc3QgaW5kZXhBcnJheSA9IG5ldyBVaW50MzJBcnJheSh2ZXJ0ZXhDb3VudCk7CiAgICBjb25zdCB2ZXJ0ZXhJbmRleEZuID0gZGVmaW5lZF9kZWZhdWx0KGluZGljZXMpID8gKHZlcnRleEluZGV4KSA9PiBpbmRpY2VzW3ZlcnRleEluZGV4XSA6ICh2ZXJ0ZXhJbmRleCkgPT4gdmVydGV4SW5kZXg7CiAgICBsZXQgdHJhbnNwYXJlbnRWZXJ0ZXhPZmZzZXQgPSAwOwogICAgaWYgKHNwbGl0R2VvbWV0cnlCeUNvbG9yVHJhbnNwYXJlbmN5ICYmIGRlZmluZWRfZGVmYXVsdChjb2xvcnMpKSB7CiAgICAgIGNvbnN0IGlzVmVydGV4VHJhbnNwYXJlbnRGbiA9ICh2ZXJ0ZXhJbmRleCkgPT4gY29sb3JzW3ZlcnRleEluZGV4Rm4odmVydGV4SW5kZXgpICogNCArIDNdIDwgMjU1OwogICAgICBmb3IgKGxldCB2ZXJ0ZXhJbmRleCA9IDA7IHZlcnRleEluZGV4IDwgdmVydGV4Q291bnQ7IHZlcnRleEluZGV4ICs9IDMpIHsKICAgICAgICBpZiAoIWlzVmVydGV4VHJhbnNwYXJlbnRGbih2ZXJ0ZXhJbmRleCkgJiYgIWlzVmVydGV4VHJhbnNwYXJlbnRGbih2ZXJ0ZXhJbmRleCArIDEpICYmICFpc1ZlcnRleFRyYW5zcGFyZW50Rm4odmVydGV4SW5kZXggKyAyKSkgewogICAgICAgICAgaW5kZXhBcnJheVt0cmFuc3BhcmVudFZlcnRleE9mZnNldCsrXSA9IHZlcnRleEluZGV4Rm4odmVydGV4SW5kZXgpOwogICAgICAgICAgaW5kZXhBcnJheVt0cmFuc3BhcmVudFZlcnRleE9mZnNldCsrXSA9IHZlcnRleEluZGV4Rm4odmVydGV4SW5kZXggKyAxKTsKICAgICAgICAgIGluZGV4QXJyYXlbdHJhbnNwYXJlbnRWZXJ0ZXhPZmZzZXQrK10gPSB2ZXJ0ZXhJbmRleEZuKHZlcnRleEluZGV4ICsgMik7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICh0cmFuc3BhcmVudFZlcnRleE9mZnNldCA+IDApIHsKICAgICAgICBsZXQgb2Zmc2V0ID0gdHJhbnNwYXJlbnRWZXJ0ZXhPZmZzZXQ7CiAgICAgICAgZm9yIChsZXQgdmVydGV4SW5kZXggPSAwOyB2ZXJ0ZXhJbmRleCA8IHZlcnRleENvdW50OyB2ZXJ0ZXhJbmRleCArPSAzKSB7CiAgICAgICAgICBpZiAoaXNWZXJ0ZXhUcmFuc3BhcmVudEZuKHZlcnRleEluZGV4KSB8fCBpc1ZlcnRleFRyYW5zcGFyZW50Rm4odmVydGV4SW5kZXggKyAxKSB8fCBpc1ZlcnRleFRyYW5zcGFyZW50Rm4odmVydGV4SW5kZXggKyAyKSkgewogICAgICAgICAgICBpbmRleEFycmF5W29mZnNldCsrXSA9IHZlcnRleEluZGV4Rm4odmVydGV4SW5kZXgpOwogICAgICAgICAgICBpbmRleEFycmF5W29mZnNldCsrXSA9IHZlcnRleEluZGV4Rm4odmVydGV4SW5kZXggKyAxKTsKICAgICAgICAgICAgaW5kZXhBcnJheVtvZmZzZXQrK10gPSB2ZXJ0ZXhJbmRleEZuKHZlcnRleEluZGV4ICsgMik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGZvciAobGV0IHZlcnRleEluZGV4ID0gMDsgdmVydGV4SW5kZXggPCB2ZXJ0ZXhDb3VudDsgKyt2ZXJ0ZXhJbmRleCkgewogICAgICAgICAgaW5kZXhBcnJheVt2ZXJ0ZXhJbmRleF0gPSB2ZXJ0ZXhJbmRleEZuKHZlcnRleEluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRyYW5zcGFyZW50VmVydGV4T2Zmc2V0ID0gdmVydGV4Q291bnQ7CiAgICAgIGZvciAobGV0IHZlcnRleEluZGV4ID0gMDsgdmVydGV4SW5kZXggPCB2ZXJ0ZXhDb3VudDsgKyt2ZXJ0ZXhJbmRleCkgewogICAgICAgIGluZGV4QXJyYXlbdmVydGV4SW5kZXhdID0gdmVydGV4SW5kZXhGbih2ZXJ0ZXhJbmRleCk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7CiAgICAgIGluZGV4QXJyYXksCiAgICAgIHRyYW5zcGFyZW50VmVydGV4T2Zmc2V0CiAgICB9OwogIH0KICBmdW5jdGlvbiBnZXRGZWF0dXJlSGFzaChzeW1ib2xvZ3lEYXRhLCBvdXRsaW5lc0hhc2gsIGZlYXR1cmVJbmRleCkgewogICAgY29uc3QgZmVhdHVyZUhhc2ggPSBvdXRsaW5lc0hhc2hbZmVhdHVyZUluZGV4XTsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZmVhdHVyZUhhc2gpKSB7CiAgICAgIHJldHVybiBmZWF0dXJlSGFzaDsKICAgIH0KICAgIGNvbnN0IG5ld0ZlYXR1cmVIYXNoID0gb3V0bGluZXNIYXNoW2ZlYXR1cmVJbmRleF0gPSB7CiAgICAgIHBvc2l0aW9uczoge30sCiAgICAgIGluZGljZXM6IHt9LAogICAgICBlZGdlczoge30KICAgIH07CiAgICBjb25zdCBmZWF0dXJlU3ltYm9sb2d5ID0gc3ltYm9sb2d5RGF0YVtmZWF0dXJlSW5kZXhdID8/IHN5bWJvbG9neURhdGEuZGVmYXVsdDsKICAgIG5ld0ZlYXR1cmVIYXNoLmhhc091dGxpbmUgPSBkZWZpbmVkX2RlZmF1bHQoZmVhdHVyZVN5bWJvbG9neT8uZWRnZXMpOwogICAgcmV0dXJuIG5ld0ZlYXR1cmVIYXNoOwogIH0KICBmdW5jdGlvbiBhZGRWZXJ0ZXhUb0hhc2goaW5kZXhIYXNoLCBwb3NpdGlvbkhhc2gsIHZlcnRleEluZGV4LCBwb3NpdGlvbnMpIHsKICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGluZGV4SGFzaFt2ZXJ0ZXhJbmRleF0pKSB7CiAgICAgIGNvbnN0IHN0YXJ0UG9zaXRpb25JbmRleCA9IHZlcnRleEluZGV4ICogMzsKICAgICAgbGV0IGNvb3JkaW5hdGVIYXNoID0gcG9zaXRpb25IYXNoOwogICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgMzsgaW5kZXgrKykgewogICAgICAgIGNvbnN0IGNvb3JkaW5hdGUgPSBwb3NpdGlvbnNbc3RhcnRQb3NpdGlvbkluZGV4ICsgaW5kZXhdOwogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGNvb3JkaW5hdGVIYXNoW2Nvb3JkaW5hdGVdKSkgewogICAgICAgICAgY29vcmRpbmF0ZUhhc2hbY29vcmRpbmF0ZV0gPSB7fTsKICAgICAgICB9CiAgICAgICAgY29vcmRpbmF0ZUhhc2ggPSBjb29yZGluYXRlSGFzaFtjb29yZGluYXRlXTsKICAgICAgfQogICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChjb29yZGluYXRlSGFzaC5pbmRleCkpIHsKICAgICAgICBjb29yZGluYXRlSGFzaC5pbmRleCA9IHZlcnRleEluZGV4OwogICAgICB9CiAgICAgIGluZGV4SGFzaFt2ZXJ0ZXhJbmRleF0gPSBjb29yZGluYXRlSGFzaC5pbmRleDsKICAgIH0KICB9CiAgZnVuY3Rpb24gYWRkRWRnZVRvSGFzaChlZGdlSGFzaCwgdmVydGV4QUluZGV4LCB2ZXJ0ZXhCSW5kZXgsIHZlcnRleEFJbmRleFVuaXF1ZSwgdmVydGV4QkluZGV4VW5pcXVlLCBub3JtYWxJbmRleCkgewogICAgbGV0IHN0YXJ0VmVydGV4SW5kZXg7CiAgICBsZXQgZW5kVmVydGV4SW5kZXg7CiAgICBpZiAodmVydGV4QUluZGV4VW5pcXVlIDwgdmVydGV4QkluZGV4VW5pcXVlKSB7CiAgICAgIHN0YXJ0VmVydGV4SW5kZXggPSB2ZXJ0ZXhBSW5kZXhVbmlxdWU7CiAgICAgIGVuZFZlcnRleEluZGV4ID0gdmVydGV4QkluZGV4VW5pcXVlOwogICAgfSBlbHNlIHsKICAgICAgc3RhcnRWZXJ0ZXhJbmRleCA9IHZlcnRleEJJbmRleFVuaXF1ZTsKICAgICAgZW5kVmVydGV4SW5kZXggPSB2ZXJ0ZXhBSW5kZXhVbmlxdWU7CiAgICB9CiAgICBsZXQgZWRnZVN0YXJ0ID0gZWRnZUhhc2hbc3RhcnRWZXJ0ZXhJbmRleF07CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChlZGdlU3RhcnQpKSB7CiAgICAgIGVkZ2VTdGFydCA9IGVkZ2VIYXNoW3N0YXJ0VmVydGV4SW5kZXhdID0ge307CiAgICB9CiAgICBsZXQgZWRnZUVuZCA9IGVkZ2VTdGFydFtlbmRWZXJ0ZXhJbmRleF07CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChlZGdlRW5kKSkgewogICAgICBlZGdlRW5kID0gZWRnZVN0YXJ0W2VuZFZlcnRleEluZGV4XSA9IHsKICAgICAgICBub3JtYWxzSW5kZXg6IFtdLAogICAgICAgIG91dGxpbmVzOiBbXQogICAgICB9OwogICAgfQogICAgZWRnZUVuZC5ub3JtYWxzSW5kZXgucHVzaChub3JtYWxJbmRleCk7CiAgICBpZiAoZWRnZUVuZC5vdXRsaW5lcy5sZW5ndGggPT09IDAgfHwgdmVydGV4QUluZGV4ICE9PSB2ZXJ0ZXhBSW5kZXhVbmlxdWUgfHwgdmVydGV4QkluZGV4ICE9PSB2ZXJ0ZXhCSW5kZXhVbmlxdWUpIHsKICAgICAgZWRnZUVuZC5vdXRsaW5lcy5wdXNoKHZlcnRleEFJbmRleCwgdmVydGV4QkluZGV4KTsKICAgIH0KICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVPdXRsaW5lc0hhc2goc3ltYm9sb2d5RGF0YSwgZmVhdHVyZUluZGV4QXJyYXksIGluZGV4QXJyYXksIHBvc2l0aW9ucykgewogICAgY29uc3Qgb3V0bGluZXNIYXNoID0gW107CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluZGV4QXJyYXkubGVuZ3RoOyBpICs9IDMpIHsKICAgICAgY29uc3QgZmVhdHVyZUluZGV4ID0gZGVmaW5lZF9kZWZhdWx0KGZlYXR1cmVJbmRleEFycmF5KSA/IGZlYXR1cmVJbmRleEFycmF5W2luZGV4QXJyYXlbaV1dIDogImRlZmF1bHQiOwogICAgICBjb25zdCBmZWF0dXJlSGFzaCA9IGdldEZlYXR1cmVIYXNoKAogICAgICAgIHN5bWJvbG9neURhdGEsCiAgICAgICAgb3V0bGluZXNIYXNoLAogICAgICAgIGZlYXR1cmVJbmRleAogICAgICApOwogICAgICBpZiAoIWZlYXR1cmVIYXNoLmhhc091dGxpbmUpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBpbmRleEhhc2ggPSBmZWF0dXJlSGFzaC5pbmRpY2VzOwogICAgICBjb25zdCBwb3NpdGlvbkhhc2ggPSBmZWF0dXJlSGFzaC5wb3NpdGlvbnM7CiAgICAgIGZvciAobGV0IHZlcnRleCA9IDA7IHZlcnRleCA8IDM7IHZlcnRleCsrKSB7CiAgICAgICAgY29uc3QgdmVydGV4SW5kZXggPSBpbmRleEFycmF5W2kgKyB2ZXJ0ZXhdOwogICAgICAgIGFkZFZlcnRleFRvSGFzaChpbmRleEhhc2gsIHBvc2l0aW9uSGFzaCwgdmVydGV4SW5kZXgsIHBvc2l0aW9ucyk7CiAgICAgIH0KICAgICAgY29uc3QgZWRnZUhhc2ggPSBmZWF0dXJlSGFzaC5lZGdlczsKICAgICAgZm9yIChsZXQgdmVydGV4ID0gMDsgdmVydGV4IDwgMzsgdmVydGV4KyspIHsKICAgICAgICBjb25zdCB2ZXJ0ZXhJbmRleCA9IGluZGV4QXJyYXlbaSArIHZlcnRleF07CiAgICAgICAgY29uc3QgbmV4dFZlcnRleEluZGV4ID0gaW5kZXhBcnJheVtpICsgKHZlcnRleCArIDEpICUgM107CiAgICAgICAgY29uc3QgdW5pcXVlVmVydGV4SW5kZXggPSBpbmRleEhhc2hbdmVydGV4SW5kZXhdOwogICAgICAgIGNvbnN0IHVuaXF1ZU5leHRWZXJ0ZXhJbmRleCA9IGluZGV4SGFzaFtuZXh0VmVydGV4SW5kZXhdOwogICAgICAgIGFkZEVkZ2VUb0hhc2goCiAgICAgICAgICBlZGdlSGFzaCwKICAgICAgICAgIHZlcnRleEluZGV4LAogICAgICAgICAgbmV4dFZlcnRleEluZGV4LAogICAgICAgICAgdW5pcXVlVmVydGV4SW5kZXgsCiAgICAgICAgICB1bmlxdWVOZXh0VmVydGV4SW5kZXgsCiAgICAgICAgICBpCiAgICAgICAgKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG91dGxpbmVzSGFzaDsKICB9CiAgZnVuY3Rpb24gY2FsY3VsYXRlRmFjZU5vcm1hbChub3JtYWxzLCB2ZXJ0ZXhBSW5kZXgsIGluZGV4QXJyYXksIHBvc2l0aW9ucykgewogICAgY29uc3QgcG9zaXRpb25BSW5kZXggPSBpbmRleEFycmF5W3ZlcnRleEFJbmRleF0gKiAzOwogICAgY29uc3QgcG9zaXRpb25CSW5kZXggPSBpbmRleEFycmF5W3ZlcnRleEFJbmRleCArIDFdICogMzsKICAgIGNvbnN0IHBvc2l0aW9uQ0luZGV4ID0gaW5kZXhBcnJheVt2ZXJ0ZXhBSW5kZXggKyAyXSAqIDM7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuZnJvbUFycmF5KHBvc2l0aW9ucywgcG9zaXRpb25BSW5kZXgsIGNhbGN1bGF0ZUZhY2VOb3JtYWxBKTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkocG9zaXRpb25zLCBwb3NpdGlvbkJJbmRleCwgY2FsY3VsYXRlRmFjZU5vcm1hbEIpOwogICAgQ2FydGVzaWFuM19kZWZhdWx0LmZyb21BcnJheShwb3NpdGlvbnMsIHBvc2l0aW9uQ0luZGV4LCBjYWxjdWxhdGVGYWNlTm9ybWFsQyk7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgIGNhbGN1bGF0ZUZhY2VOb3JtYWxCLAogICAgICBjYWxjdWxhdGVGYWNlTm9ybWFsQSwKICAgICAgY2FsY3VsYXRlRmFjZU5vcm1hbEIKICAgICk7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuc3VidHJhY3QoCiAgICAgIGNhbGN1bGF0ZUZhY2VOb3JtYWxDLAogICAgICBjYWxjdWxhdGVGYWNlTm9ybWFsQSwKICAgICAgY2FsY3VsYXRlRmFjZU5vcm1hbEMKICAgICk7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuY3Jvc3MoCiAgICAgIGNhbGN1bGF0ZUZhY2VOb3JtYWxCLAogICAgICBjYWxjdWxhdGVGYWNlTm9ybWFsQywKICAgICAgY2FsY3VsYXRlRmFjZU5vcm1hbEEKICAgICk7CiAgICBjb25zdCBtYWduaXR1ZGUgPSBDYXJ0ZXNpYW4zX2RlZmF1bHQubWFnbml0dWRlKGNhbGN1bGF0ZUZhY2VOb3JtYWxBKTsKICAgIGlmIChtYWduaXR1ZGUgIT09IDApIHsKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmRpdmlkZUJ5U2NhbGFyKAogICAgICAgIGNhbGN1bGF0ZUZhY2VOb3JtYWxBLAogICAgICAgIG1hZ25pdHVkZSwKICAgICAgICBjYWxjdWxhdGVGYWNlTm9ybWFsQQogICAgICApOwogICAgfQogICAgY29uc3Qgbm9ybWFsQUluZGV4ID0gdmVydGV4QUluZGV4ICogMzsKICAgIGNvbnN0IG5vcm1hbEJJbmRleCA9ICh2ZXJ0ZXhBSW5kZXggKyAxKSAqIDM7CiAgICBjb25zdCBub3JtYWxDSW5kZXggPSAodmVydGV4QUluZGV4ICsgMikgKiAzOwogICAgQ2FydGVzaWFuM19kZWZhdWx0LnBhY2soY2FsY3VsYXRlRmFjZU5vcm1hbEEsIG5vcm1hbHMsIG5vcm1hbEFJbmRleCk7CiAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQucGFjayhjYWxjdWxhdGVGYWNlTm9ybWFsQSwgbm9ybWFscywgbm9ybWFsQkluZGV4KTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5wYWNrKGNhbGN1bGF0ZUZhY2VOb3JtYWxBLCBub3JtYWxzLCBub3JtYWxDSW5kZXgpOwogIH0KICBmdW5jdGlvbiBpc0VkZ2VTbW9vdGgobm9ybWFscywgbm9ybWFsQUluZGV4LCBub3JtYWxCSW5kZXgpIHsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkobm9ybWFscywgbm9ybWFsQUluZGV4LCBpc0VkZ2VTbW9vdGhBKTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5mcm9tQXJyYXkobm9ybWFscywgbm9ybWFsQkluZGV4LCBpc0VkZ2VTbW9vdGhCKTsKICAgIGNvbnN0IGNvc2luZSA9IENhcnRlc2lhbjNfZGVmYXVsdC5kb3QoaXNFZGdlU21vb3RoQSwgaXNFZGdlU21vb3RoQik7CiAgICBjb25zdCBzaW5lID0gQ2FydGVzaWFuM19kZWZhdWx0Lm1hZ25pdHVkZSgKICAgICAgQ2FydGVzaWFuM19kZWZhdWx0LmNyb3NzKGlzRWRnZVNtb290aEEsIGlzRWRnZVNtb290aEIsIGlzRWRnZVNtb290aEEpCiAgICApOwogICAgcmV0dXJuIE1hdGguYXRhbjIoc2luZSwgY29zaW5lKSA8IDAuMjU7CiAgfQogIGZ1bmN0aW9uIGFkZE91dGxpbmVzRm9yRWRnZShvdXRsaW5lcywgZWRnZURhdGEsIGluZGV4QXJyYXksIHBvc2l0aW9ucywgbm9ybWFscykgewogICAgaWYgKGVkZ2VEYXRhLm5vcm1hbHNJbmRleC5sZW5ndGggPiAxKSB7CiAgICAgIGNvbnN0IG5vcm1hbHNCeUluZGV4ID0gcG9zaXRpb25zLmxlbmd0aCA9PT0gbm9ybWFscy5sZW5ndGg7CiAgICAgIGZvciAobGV0IGluZGV4QSA9IDA7IGluZGV4QSA8IGVkZ2VEYXRhLm5vcm1hbHNJbmRleC5sZW5ndGg7IGluZGV4QSsrKSB7CiAgICAgICAgY29uc3QgdmVydGV4QUluZGV4ID0gZWRnZURhdGEubm9ybWFsc0luZGV4W2luZGV4QV07CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQobm9ybWFsc1t2ZXJ0ZXhBSW5kZXggKiAzXSkpIHsKICAgICAgICAgIGNhbGN1bGF0ZUZhY2VOb3JtYWwobm9ybWFscywgdmVydGV4QUluZGV4LCBpbmRleEFycmF5LCBwb3NpdGlvbnMpOwogICAgICAgIH0KICAgICAgICBpZiAoaW5kZXhBID09PSAwKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaW5kZXhCID0gMDsgaW5kZXhCIDwgaW5kZXhBOyBpbmRleEIrKykgewogICAgICAgICAgY29uc3QgdmVydGV4QkluZGV4ID0gZWRnZURhdGEubm9ybWFsc0luZGV4W2luZGV4Ql07CiAgICAgICAgICBjb25zdCBub3JtYWxBSW5kZXggPSBub3JtYWxzQnlJbmRleCA/IGluZGV4QXJyYXlbdmVydGV4QUluZGV4XSAqIDMgOiB2ZXJ0ZXhBSW5kZXggKiAzOwogICAgICAgICAgY29uc3Qgbm9ybWFsQkluZGV4ID0gbm9ybWFsc0J5SW5kZXggPyBpbmRleEFycmF5W3ZlcnRleEJJbmRleF0gKiAzIDogdmVydGV4QkluZGV4ICogMzsKICAgICAgICAgIGlmIChpc0VkZ2VTbW9vdGgobm9ybWFscywgbm9ybWFsQUluZGV4LCBub3JtYWxCSW5kZXgpKSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIG91dGxpbmVzLnB1c2goLi4uZWRnZURhdGEub3V0bGluZXMpOwogIH0KICBmdW5jdGlvbiBhZGRPdXRsaW5lc0ZvckZlYXR1cmUob3V0bGluZXMsIGVkZ2VIYXNoLCBpbmRleEFycmF5LCBwb3NpdGlvbnMsIG5vcm1hbHMpIHsKICAgIGNvbnN0IGVkZ2VTdGFydEtleXMgPSBPYmplY3Qua2V5cyhlZGdlSGFzaCk7CiAgICBmb3IgKGxldCBzdGFydEluZGV4ID0gMDsgc3RhcnRJbmRleCA8IGVkZ2VTdGFydEtleXMubGVuZ3RoOyBzdGFydEluZGV4KyspIHsKICAgICAgY29uc3QgZWRnZUVuZHMgPSBlZGdlSGFzaFtlZGdlU3RhcnRLZXlzW3N0YXJ0SW5kZXhdXTsKICAgICAgY29uc3QgZWRnZUVuZEtleXMgPSBPYmplY3Qua2V5cyhlZGdlRW5kcyk7CiAgICAgIGZvciAobGV0IGVuZEluZGV4ID0gMDsgZW5kSW5kZXggPCBlZGdlRW5kS2V5cy5sZW5ndGg7IGVuZEluZGV4KyspIHsKICAgICAgICBjb25zdCBlZGdlRGF0YSA9IGVkZ2VFbmRzW2VkZ2VFbmRLZXlzW2VuZEluZGV4XV07CiAgICAgICAgYWRkT3V0bGluZXNGb3JFZGdlKG91dGxpbmVzLCBlZGdlRGF0YSwgaW5kZXhBcnJheSwgcG9zaXRpb25zLCBub3JtYWxzKTsKICAgICAgfQogICAgfQogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZU91dGxpbmVzRnJvbUhhc2gob3V0bGluZXNIYXNoLCBpbmRleEFycmF5LCBwb3NpdGlvbnMsIG5vcm1hbHMpIHsKICAgIGNvbnN0IG91dGxpbmVzID0gW107CiAgICBjb25zdCBmZWF0dXJlcyA9IE9iamVjdC5rZXlzKG91dGxpbmVzSGFzaCk7CiAgICBmb3IgKGxldCBmZWF0dXJlSW5kZXggPSAwOyBmZWF0dXJlSW5kZXggPCBmZWF0dXJlcy5sZW5ndGg7IGZlYXR1cmVJbmRleCsrKSB7CiAgICAgIGNvbnN0IGVkZ2VIYXNoID0gb3V0bGluZXNIYXNoW2ZlYXR1cmVzW2ZlYXR1cmVJbmRleF1dLmVkZ2VzOwogICAgICBhZGRPdXRsaW5lc0ZvckZlYXR1cmUob3V0bGluZXMsIGVkZ2VIYXNoLCBpbmRleEFycmF5LCBwb3NpdGlvbnMsIG5vcm1hbHMpOwogICAgfQogICAgcmV0dXJuIG91dGxpbmVzOwogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZU91dGxpbmVzSW5kZXhBcnJheShzeW1ib2xvZ3lEYXRhLCBmZWF0dXJlSW5kZXhBcnJheSwgaW5kZXhBcnJheSwgcG9zaXRpb25zLCBub3JtYWxzKSB7CiAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChzeW1ib2xvZ3lEYXRhKSB8fCBPYmplY3Qua2V5cyhzeW1ib2xvZ3lEYXRhKS5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIHZvaWQgMDsKICAgIH0KICAgIGNvbnN0IG91dGxpbmVzSGFzaCA9IGdlbmVyYXRlT3V0bGluZXNIYXNoKAogICAgICBzeW1ib2xvZ3lEYXRhLAogICAgICBmZWF0dXJlSW5kZXhBcnJheSwKICAgICAgaW5kZXhBcnJheSwKICAgICAgcG9zaXRpb25zCiAgICApOwogICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQobm9ybWFscykgfHwgaW5kZXhBcnJheS5sZW5ndGggKiAzICE9PSBub3JtYWxzLmxlbmd0aCkgewogICAgICBub3JtYWxzID0gW107CiAgICB9CiAgICBjb25zdCBvdXRsaW5lcyA9IGdlbmVyYXRlT3V0bGluZXNGcm9tSGFzaCgKICAgICAgb3V0bGluZXNIYXNoLAogICAgICBpbmRleEFycmF5LAogICAgICBwb3NpdGlvbnMsCiAgICAgIG5vcm1hbHMKICAgICk7CiAgICBjb25zdCBvdXRsaW5lc0luZGV4QXJyYXkgPSBvdXRsaW5lcy5sZW5ndGggPiAwID8gbmV3IFVpbnQzMkFycmF5KG91dGxpbmVzKSA6IHZvaWQgMDsKICAgIHJldHVybiBvdXRsaW5lc0luZGV4QXJyYXk7CiAgfQogIGZ1bmN0aW9uIGNvbnZlcnRDb2xvcnNBcnJheShjb2xvcnMpIHsKICAgIGNvbnN0IGNvbG9yc0FycmF5ID0gbmV3IEZsb2F0MzJBcnJheShjb2xvcnMubGVuZ3RoKTsKICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBjb2xvcnMubGVuZ3RoOyBpbmRleCArPSA0KSB7CiAgICAgIGNvbG9yc0FycmF5W2luZGV4XSA9IHNyZ2JUb0xpbmVhcl9kZWZhdWx0KENvbG9yX2RlZmF1bHQuYnl0ZVRvRmxvYXQoY29sb3JzW2luZGV4XSkpOwogICAgICBjb2xvcnNBcnJheVtpbmRleCArIDFdID0gc3JnYlRvTGluZWFyX2RlZmF1bHQoQ29sb3JfZGVmYXVsdC5ieXRlVG9GbG9hdChjb2xvcnNbaW5kZXggKyAxXSkpOwogICAgICBjb2xvcnNBcnJheVtpbmRleCArIDJdID0gc3JnYlRvTGluZWFyX2RlZmF1bHQoQ29sb3JfZGVmYXVsdC5ieXRlVG9GbG9hdChjb2xvcnNbaW5kZXggKyAyXSkpOwogICAgICBjb2xvcnNBcnJheVtpbmRleCArIDNdID0gQ29sb3JfZGVmYXVsdC5ieXRlVG9GbG9hdChjb2xvcnNbaW5kZXggKyAzXSk7CiAgICB9CiAgICByZXR1cm4gY29sb3JzQXJyYXk7CiAgfQogIGZ1bmN0aW9uIGdlbmVyYXRlTm9ybWFscyh2ZXJ0ZXhDb3VudCwgaW5kaWNlcywgcG9zaXRpb25zLCBub3JtYWxzLCB1djBzLCBjb2xvcnMsIGZlYXR1cmVJbmRleCkgewogICAgY29uc3QgcmVzdWx0ID0gewogICAgICBub3JtYWxzOiB2b2lkIDAsCiAgICAgIHBvc2l0aW9uczogdm9pZCAwLAogICAgICB1djBzOiB2b2lkIDAsCiAgICAgIGNvbG9yczogdm9pZCAwLAogICAgICBmZWF0dXJlSW5kZXg6IHZvaWQgMCwKICAgICAgdmVydGV4Q291bnQ6IHZvaWQgMAogICAgfTsKICAgIGlmICh2ZXJ0ZXhDb3VudCA9PT0gMCB8fCAhZGVmaW5lZF9kZWZhdWx0KHBvc2l0aW9ucykgfHwgcG9zaXRpb25zLmxlbmd0aCA9PT0gMCB8fCBkZWZpbmVkX2RlZmF1bHQobm9ybWFscykpIHsKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoaW5kaWNlcykpIHsKICAgICAgcmVzdWx0LnZlcnRleENvdW50ID0gaW5kaWNlcy5sZW5ndGg7CiAgICAgIHJlc3VsdC5wb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KGluZGljZXMubGVuZ3RoICogMyk7CiAgICAgIHJlc3VsdC51djBzID0gZGVmaW5lZF9kZWZhdWx0KHV2MHMpID8gbmV3IEZsb2F0MzJBcnJheShpbmRpY2VzLmxlbmd0aCAqIDIpIDogdm9pZCAwOwogICAgICByZXN1bHQuY29sb3JzID0gZGVmaW5lZF9kZWZhdWx0KGNvbG9ycykgPyBuZXcgVWludDhBcnJheShpbmRpY2VzLmxlbmd0aCAqIDQpIDogdm9pZCAwOwogICAgICByZXN1bHQuZmVhdHVyZUluZGV4ID0gZGVmaW5lZF9kZWZhdWx0KGZlYXR1cmVJbmRleCkgPyBuZXcgQXJyYXkoaW5kaWNlcy5sZW5ndGgpIDogdm9pZCAwOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICBjb25zdCBpbmRleCA9IGluZGljZXNbaV07CiAgICAgICAgcmVzdWx0LnBvc2l0aW9uc1tpICogM10gPSBwb3NpdGlvbnNbaW5kZXggKiAzXTsKICAgICAgICByZXN1bHQucG9zaXRpb25zW2kgKiAzICsgMV0gPSBwb3NpdGlvbnNbaW5kZXggKiAzICsgMV07CiAgICAgICAgcmVzdWx0LnBvc2l0aW9uc1tpICogMyArIDJdID0gcG9zaXRpb25zW2luZGV4ICogMyArIDJdOwogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocmVzdWx0LnV2MHMpKSB7CiAgICAgICAgICByZXN1bHQudXYwc1tpICogMl0gPSB1djBzW2luZGV4ICogMl07CiAgICAgICAgICByZXN1bHQudXYwc1tpICogMiArIDFdID0gdXYwc1tpbmRleCAqIDIgKyAxXTsKICAgICAgICB9CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChyZXN1bHQuY29sb3JzKSkgewogICAgICAgICAgcmVzdWx0LmNvbG9yc1tpICogNF0gPSBjb2xvcnNbaW5kZXggKiA0XTsKICAgICAgICAgIHJlc3VsdC5jb2xvcnNbaSAqIDQgKyAxXSA9IGNvbG9yc1tpbmRleCAqIDQgKyAxXTsKICAgICAgICAgIHJlc3VsdC5jb2xvcnNbaSAqIDQgKyAyXSA9IGNvbG9yc1tpbmRleCAqIDQgKyAyXTsKICAgICAgICAgIHJlc3VsdC5jb2xvcnNbaSAqIDQgKyAzXSA9IGNvbG9yc1tpbmRleCAqIDQgKyAzXTsKICAgICAgICB9CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChyZXN1bHQuZmVhdHVyZUluZGV4KSkgewogICAgICAgICAgcmVzdWx0LmZlYXR1cmVJbmRleFtpXSA9IGZlYXR1cmVJbmRleFtpbmRleF07CiAgICAgICAgfQogICAgICB9CiAgICAgIHZlcnRleENvdW50ID0gaW5kaWNlcy5sZW5ndGg7CiAgICAgIHBvc2l0aW9ucyA9IHJlc3VsdC5wb3NpdGlvbnM7CiAgICB9CiAgICBpbmRpY2VzID0gbmV3IEFycmF5KHZlcnRleENvdW50KTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdmVydGV4Q291bnQ7IGkrKykgewogICAgICBpbmRpY2VzW2ldID0gaTsKICAgIH0KICAgIHJlc3VsdC5ub3JtYWxzID0gbmV3IEZsb2F0MzJBcnJheShpbmRpY2VzLmxlbmd0aCAqIDMpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSArPSAzKSB7CiAgICAgIGNhbGN1bGF0ZUZhY2VOb3JtYWwocmVzdWx0Lm5vcm1hbHMsIGksIGluZGljZXMsIHBvc2l0aW9ucyk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZUdsdGZCdWZmZXIodmVydGV4Q291bnQsIGluZGljZXMsIHBvc2l0aW9ucywgbm9ybWFscywgdXYwcywgY29sb3JzLCBmZWF0dXJlSW5kZXgsIHBhcmFtZXRlcnMpIHsKICAgIGlmICh2ZXJ0ZXhDb3VudCA9PT0gMCB8fCAhZGVmaW5lZF9kZWZhdWx0KHBvc2l0aW9ucykgfHwgcG9zaXRpb25zLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gewogICAgICAgIGJ1ZmZlcnM6IFtdLAogICAgICAgIGJ1ZmZlclZpZXdzOiBbXSwKICAgICAgICBhY2Nlc3NvcnM6IFtdLAogICAgICAgIG1lc2hlczogW10sCiAgICAgICAgbm9kZXM6IFtdLAogICAgICAgIG5vZGVzSW5TY2VuZTogW10KICAgICAgfTsKICAgIH0KICAgIGNvbnN0IGJ1ZmZlcnMgPSBbXTsKICAgIGNvbnN0IGJ1ZmZlclZpZXdzID0gW107CiAgICBjb25zdCBhY2Nlc3NvcnMgPSBbXTsKICAgIGNvbnN0IG1lc2hlcyA9IFtdOwogICAgY29uc3Qgbm9kZXMgPSBbXTsKICAgIGNvbnN0IG5vZGVzSW5TY2VuZSA9IFtdOwogICAgY29uc3Qgcm9vdEV4dGVuc2lvbnMgPSB7fTsKICAgIGNvbnN0IGV4dGVuc2lvbnNVc2VkID0gW107CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGluZGljZXMpKSB7CiAgICAgIHZlcnRleENvdW50ID0gaW5kaWNlcy5sZW5ndGg7CiAgICB9CiAgICBjb25zdCB7IGluZGV4QXJyYXksIHRyYW5zcGFyZW50VmVydGV4T2Zmc2V0IH0gPSBnZW5lcmF0ZUluZGV4QXJyYXkoCiAgICAgIHZlcnRleENvdW50LAogICAgICBpbmRpY2VzLAogICAgICBjb2xvcnMsCiAgICAgIHBhcmFtZXRlcnMuc3BsaXRHZW9tZXRyeUJ5Q29sb3JUcmFuc3BhcmVuY3kKICAgICk7CiAgICBjb25zdCBpbmRpY2VzQmxvYiA9IG5ldyBCbG9iKFtpbmRleEFycmF5XSwgeyB0eXBlOiAiYXBwbGljYXRpb24vYmluYXJ5IiB9KTsKICAgIGNvbnN0IGluZGljZXNVUkwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGluZGljZXNCbG9iKTsKICAgIGNvbnN0IGVuZEluZGV4ID0gdmVydGV4Q291bnQ7CiAgICBjb25zdCBmZWF0dXJlSW5kZXhBcnJheSA9IHBhcmFtZXRlcnMuZW5hYmxlRmVhdHVyZXMgJiYgZGVmaW5lZF9kZWZhdWx0KGZlYXR1cmVJbmRleCkgPyBuZXcgRmxvYXQzMkFycmF5KGZlYXR1cmVJbmRleC5sZW5ndGgpIDogdm9pZCAwOwogICAgbGV0IGZlYXR1cmVDb3VudCA9IDA7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGZlYXR1cmVJbmRleEFycmF5KSkgewogICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgZmVhdHVyZUluZGV4Lmxlbmd0aDsgKytpbmRleCkgewogICAgICAgIGZlYXR1cmVJbmRleEFycmF5W2luZGV4XSA9IGZlYXR1cmVJbmRleFtpbmRleF07CiAgICAgICAgY29uc3QgY291bnRCeUluZGV4ID0gZmVhdHVyZUluZGV4W2luZGV4XSArIDE7CiAgICAgICAgaWYgKGZlYXR1cmVDb3VudCA8IGNvdW50QnlJbmRleCkgewogICAgICAgICAgZmVhdHVyZUNvdW50ID0gY291bnRCeUluZGV4OwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgbGV0IG91dGxpbmVzSW5kaWNlc1VSTDsKICAgIGNvbnN0IG91dGxpbmVzSW5kZXhBcnJheSA9IGdlbmVyYXRlT3V0bGluZXNJbmRleEFycmF5KAogICAgICBwYXJhbWV0ZXJzLnN5bWJvbG9neURhdGEsCiAgICAgIGZlYXR1cmVJbmRleCwKICAgICAgaW5kZXhBcnJheSwKICAgICAgcG9zaXRpb25zLAogICAgICBub3JtYWxzCiAgICApOwogICAgaWYgKGRlZmluZWRfZGVmYXVsdChvdXRsaW5lc0luZGV4QXJyYXkpKSB7CiAgICAgIGNvbnN0IG91dGxpbmVzSW5kaWNlc0Jsb2IgPSBuZXcgQmxvYihbb3V0bGluZXNJbmRleEFycmF5XSwgewogICAgICAgIHR5cGU6ICJhcHBsaWNhdGlvbi9iaW5hcnkiCiAgICAgIH0pOwogICAgICBvdXRsaW5lc0luZGljZXNVUkwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKG91dGxpbmVzSW5kaWNlc0Jsb2IpOwogICAgfQogICAgY29uc3QgbWVzaFBvc2l0aW9ucyA9IHBvc2l0aW9ucy5zdWJhcnJheSgwLCBlbmRJbmRleCAqIDMpOwogICAgY29uc3QgcG9zaXRpb25zQmxvYiA9IG5ldyBCbG9iKFttZXNoUG9zaXRpb25zXSwgewogICAgICB0eXBlOiAiYXBwbGljYXRpb24vYmluYXJ5IgogICAgfSk7CiAgICBjb25zdCBwb3NpdGlvbnNVUkwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKHBvc2l0aW9uc0Jsb2IpOwogICAgbGV0IG1pblggPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7CiAgICBsZXQgbWF4WCA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTsKICAgIGxldCBtaW5ZID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOwogICAgbGV0IG1heFkgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7CiAgICBsZXQgbWluWiA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTsKICAgIGxldCBtYXhaID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtZXNoUG9zaXRpb25zLmxlbmd0aCAvIDM7IGkrKykgewogICAgICBtaW5YID0gTWF0aC5taW4obWluWCwgbWVzaFBvc2l0aW9uc1tpICogMyArIDBdKTsKICAgICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIG1lc2hQb3NpdGlvbnNbaSAqIDMgKyAwXSk7CiAgICAgIG1pblkgPSBNYXRoLm1pbihtaW5ZLCBtZXNoUG9zaXRpb25zW2kgKiAzICsgMV0pOwogICAgICBtYXhZID0gTWF0aC5tYXgobWF4WSwgbWVzaFBvc2l0aW9uc1tpICogMyArIDFdKTsKICAgICAgbWluWiA9IE1hdGgubWluKG1pblosIG1lc2hQb3NpdGlvbnNbaSAqIDMgKyAyXSk7CiAgICAgIG1heFogPSBNYXRoLm1heChtYXhaLCBtZXNoUG9zaXRpb25zW2kgKiAzICsgMl0pOwogICAgfQogICAgY29uc3QgbWVzaE5vcm1hbHMgPSBub3JtYWxzID8gbm9ybWFscy5zdWJhcnJheSgwLCBlbmRJbmRleCAqIDMpIDogdm9pZCAwOwogICAgbGV0IG5vcm1hbHNVUkw7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG1lc2hOb3JtYWxzKSkgewogICAgICBjb25zdCBub3JtYWxzQmxvYiA9IG5ldyBCbG9iKFttZXNoTm9ybWFsc10sIHsKICAgICAgICB0eXBlOiAiYXBwbGljYXRpb24vYmluYXJ5IgogICAgICB9KTsKICAgICAgbm9ybWFsc1VSTCA9IFVSTC5jcmVhdGVPYmplY3RVUkwobm9ybWFsc0Jsb2IpOwogICAgfQogICAgY29uc3QgbWVzaFV2MHMgPSB1djBzID8gdXYwcy5zdWJhcnJheSgwLCBlbmRJbmRleCAqIDIpIDogdm9pZCAwOwogICAgbGV0IHV2MFVSTDsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobWVzaFV2MHMpKSB7CiAgICAgIGNvbnN0IHV2MEJsb2IgPSBuZXcgQmxvYihbbWVzaFV2MHNdLCB7IHR5cGU6ICJhcHBsaWNhdGlvbi9iaW5hcnkiIH0pOwogICAgICB1djBVUkwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKHV2MEJsb2IpOwogICAgfQogICAgY29uc3QgbWVzaENvbG9yc0luQnl0ZXMgPSBkZWZpbmVkX2RlZmF1bHQoY29sb3JzKSA/IGNvbnZlcnRDb2xvcnNBcnJheShjb2xvcnMuc3ViYXJyYXkoMCwgZW5kSW5kZXggKiA0KSkgOiB2b2lkIDA7CiAgICBsZXQgY29sb3JzVVJMOwogICAgaWYgKGRlZmluZWRfZGVmYXVsdChtZXNoQ29sb3JzSW5CeXRlcykpIHsKICAgICAgY29uc3QgY29sb3JzQmxvYiA9IG5ldyBCbG9iKFttZXNoQ29sb3JzSW5CeXRlc10sIHsKICAgICAgICB0eXBlOiAiYXBwbGljYXRpb24vYmluYXJ5IgogICAgICB9KTsKICAgICAgY29sb3JzVVJMID0gVVJMLmNyZWF0ZU9iamVjdFVSTChjb2xvcnNCbG9iKTsKICAgIH0KICAgIGNvbnN0IG1lc2hGZWF0dXJlSWQwID0gZGVmaW5lZF9kZWZhdWx0KGZlYXR1cmVJbmRleEFycmF5KSA/IGZlYXR1cmVJbmRleEFycmF5LnN1YmFycmF5KDAsIGVuZEluZGV4KSA6IHZvaWQgMDsKICAgIGxldCBmZWF0dXJlSWQwVVJMOwogICAgaWYgKGRlZmluZWRfZGVmYXVsdChtZXNoRmVhdHVyZUlkMCkpIHsKICAgICAgY29uc3QgZmVhdHVyZUlkMEJsb2IgPSBuZXcgQmxvYihbbWVzaEZlYXR1cmVJZDBdLCB7CiAgICAgICAgdHlwZTogImFwcGxpY2F0aW9uL2JpbmFyeSIKICAgICAgfSk7CiAgICAgIGZlYXR1cmVJZDBVUkwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGZlYXR1cmVJZDBCbG9iKTsKICAgIH0KICAgIGNvbnN0IG1lc2hQcm9wZXJ0eVRhYmxlMCA9IGRlZmluZWRfZGVmYXVsdChmZWF0dXJlSW5kZXhBcnJheSkgPyBuZXcgRmxvYXQzMkFycmF5KGZlYXR1cmVDb3VudCkgOiB2b2lkIDA7CiAgICBsZXQgcHJvcGVydHlUYWJsZTBVUkw7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG1lc2hQcm9wZXJ0eVRhYmxlMCkpIHsKICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IG1lc2hQcm9wZXJ0eVRhYmxlMC5sZW5ndGg7ICsraW5kZXgpIHsKICAgICAgICBtZXNoUHJvcGVydHlUYWJsZTBbaW5kZXhdID0gaW5kZXg7CiAgICAgIH0KICAgICAgY29uc3QgcHJvcGVydHlUYWJsZTBCbG9iID0gbmV3IEJsb2IoW21lc2hQcm9wZXJ0eVRhYmxlMF0sIHsKICAgICAgICB0eXBlOiAiYXBwbGljYXRpb24vYmluYXJ5IgogICAgICB9KTsKICAgICAgcHJvcGVydHlUYWJsZTBVUkwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKHByb3BlcnR5VGFibGUwQmxvYik7CiAgICB9CiAgICBjb25zdCBhdHRyaWJ1dGVzID0ge307CiAgICBjb25zdCBleHRlbnNpb25zID0ge307CiAgICBhdHRyaWJ1dGVzLlBPU0lUSU9OID0gYWNjZXNzb3JzLmxlbmd0aDsKICAgIGJ1ZmZlcnMucHVzaCh7CiAgICAgIHVyaTogcG9zaXRpb25zVVJMLAogICAgICBieXRlTGVuZ3RoOiBtZXNoUG9zaXRpb25zLmJ5dGVMZW5ndGgKICAgIH0pOwogICAgYnVmZmVyVmlld3MucHVzaCh7CiAgICAgIGJ1ZmZlcjogYnVmZmVycy5sZW5ndGggLSAxLAogICAgICBieXRlT2Zmc2V0OiAwLAogICAgICBieXRlTGVuZ3RoOiBtZXNoUG9zaXRpb25zLmJ5dGVMZW5ndGgsCiAgICAgIHRhcmdldDogMzQ5NjIKICAgIH0pOwogICAgYWNjZXNzb3JzLnB1c2goewogICAgICBidWZmZXJWaWV3OiBidWZmZXJWaWV3cy5sZW5ndGggLSAxLAogICAgICBieXRlT2Zmc2V0OiAwLAogICAgICBjb21wb25lbnRUeXBlOiA1MTI2LAogICAgICBjb3VudDogbWVzaFBvc2l0aW9ucy5sZW5ndGggLyAzLAogICAgICB0eXBlOiAiVkVDMyIsCiAgICAgIG1heDogW21pblgsIG1pblksIG1pblpdLAogICAgICBtaW46IFttYXhYLCBtYXhZLCBtYXhaXQogICAgfSk7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KG5vcm1hbHNVUkwpKSB7CiAgICAgIGF0dHJpYnV0ZXMuTk9STUFMID0gYWNjZXNzb3JzLmxlbmd0aDsKICAgICAgYnVmZmVycy5wdXNoKHsKICAgICAgICB1cmk6IG5vcm1hbHNVUkwsCiAgICAgICAgYnl0ZUxlbmd0aDogbWVzaE5vcm1hbHMuYnl0ZUxlbmd0aAogICAgICB9KTsKICAgICAgYnVmZmVyVmlld3MucHVzaCh7CiAgICAgICAgYnVmZmVyOiBidWZmZXJzLmxlbmd0aCAtIDEsCiAgICAgICAgYnl0ZU9mZnNldDogMCwKICAgICAgICBieXRlTGVuZ3RoOiBtZXNoTm9ybWFscy5ieXRlTGVuZ3RoLAogICAgICAgIHRhcmdldDogMzQ5NjIKICAgICAgfSk7CiAgICAgIGFjY2Vzc29ycy5wdXNoKHsKICAgICAgICBidWZmZXJWaWV3OiBidWZmZXJWaWV3cy5sZW5ndGggLSAxLAogICAgICAgIGJ5dGVPZmZzZXQ6IDAsCiAgICAgICAgY29tcG9uZW50VHlwZTogNTEyNiwKICAgICAgICBjb3VudDogbWVzaE5vcm1hbHMubGVuZ3RoIC8gMywKICAgICAgICB0eXBlOiAiVkVDMyIKICAgICAgfSk7CiAgICB9CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHV2MFVSTCkpIHsKICAgICAgYXR0cmlidXRlcy5URVhDT09SRF8wID0gYWNjZXNzb3JzLmxlbmd0aDsKICAgICAgYnVmZmVycy5wdXNoKHsKICAgICAgICB1cmk6IHV2MFVSTCwKICAgICAgICBieXRlTGVuZ3RoOiBtZXNoVXYwcy5ieXRlTGVuZ3RoCiAgICAgIH0pOwogICAgICBidWZmZXJWaWV3cy5wdXNoKHsKICAgICAgICBidWZmZXI6IGJ1ZmZlcnMubGVuZ3RoIC0gMSwKICAgICAgICBieXRlT2Zmc2V0OiAwLAogICAgICAgIGJ5dGVMZW5ndGg6IG1lc2hVdjBzLmJ5dGVMZW5ndGgsCiAgICAgICAgdGFyZ2V0OiAzNDk2MgogICAgICB9KTsKICAgICAgYWNjZXNzb3JzLnB1c2goewogICAgICAgIGJ1ZmZlclZpZXc6IGJ1ZmZlclZpZXdzLmxlbmd0aCAtIDEsCiAgICAgICAgYnl0ZU9mZnNldDogMCwKICAgICAgICBjb21wb25lbnRUeXBlOiA1MTI2LAogICAgICAgIGNvdW50OiBtZXNoVXYwcy5sZW5ndGggLyAyLAogICAgICAgIHR5cGU6ICJWRUMyIgogICAgICB9KTsKICAgIH0KICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoY29sb3JzVVJMKSkgewogICAgICBhdHRyaWJ1dGVzLkNPTE9SXzAgPSBhY2Nlc3NvcnMubGVuZ3RoOwogICAgICBidWZmZXJzLnB1c2goewogICAgICAgIHVyaTogY29sb3JzVVJMLAogICAgICAgIGJ5dGVMZW5ndGg6IG1lc2hDb2xvcnNJbkJ5dGVzLmJ5dGVMZW5ndGgKICAgICAgfSk7CiAgICAgIGJ1ZmZlclZpZXdzLnB1c2goewogICAgICAgIGJ1ZmZlcjogYnVmZmVycy5sZW5ndGggLSAxLAogICAgICAgIGJ5dGVPZmZzZXQ6IDAsCiAgICAgICAgYnl0ZUxlbmd0aDogbWVzaENvbG9yc0luQnl0ZXMuYnl0ZUxlbmd0aCwKICAgICAgICB0YXJnZXQ6IDM0OTYyCiAgICAgIH0pOwogICAgICBhY2Nlc3NvcnMucHVzaCh7CiAgICAgICAgYnVmZmVyVmlldzogYnVmZmVyVmlld3MubGVuZ3RoIC0gMSwKICAgICAgICBieXRlT2Zmc2V0OiAwLAogICAgICAgIGNvbXBvbmVudFR5cGU6IDUxMjYsCiAgICAgICAgY291bnQ6IG1lc2hDb2xvcnNJbkJ5dGVzLmxlbmd0aCAvIDQsCiAgICAgICAgdHlwZTogIlZFQzQiCiAgICAgIH0pOwogICAgfQogICAgaWYgKGRlZmluZWRfZGVmYXVsdChmZWF0dXJlSWQwVVJMKSkgewogICAgICBhdHRyaWJ1dGVzLl9GRUFUVVJFX0lEXzAgPSBhY2Nlc3NvcnMubGVuZ3RoOwogICAgICBidWZmZXJzLnB1c2goewogICAgICAgIHVyaTogZmVhdHVyZUlkMFVSTCwKICAgICAgICBieXRlTGVuZ3RoOiBtZXNoRmVhdHVyZUlkMC5ieXRlTGVuZ3RoCiAgICAgIH0pOwogICAgICBidWZmZXJWaWV3cy5wdXNoKHsKICAgICAgICBidWZmZXI6IGJ1ZmZlcnMubGVuZ3RoIC0gMSwKICAgICAgICBieXRlT2Zmc2V0OiAwLAogICAgICAgIGJ5dGVMZW5ndGg6IG1lc2hGZWF0dXJlSWQwLmJ5dGVMZW5ndGgsCiAgICAgICAgdGFyZ2V0OiAzNDk2MwogICAgICB9KTsKICAgICAgYWNjZXNzb3JzLnB1c2goewogICAgICAgIGJ1ZmZlclZpZXc6IGJ1ZmZlclZpZXdzLmxlbmd0aCAtIDEsCiAgICAgICAgYnl0ZU9mZnNldDogMCwKICAgICAgICBjb21wb25lbnRUeXBlOiA1MTI2LAogICAgICAgIGNvdW50OiBtZXNoRmVhdHVyZUlkMC5sZW5ndGgsCiAgICAgICAgdHlwZTogIlNDQUxBUiIKICAgICAgfSk7CiAgICAgIGV4dGVuc2lvbnMuRVhUX21lc2hfZmVhdHVyZXMgPSB7CiAgICAgICAgZmVhdHVyZUlkczogWwogICAgICAgICAgewogICAgICAgICAgICBhdHRyaWJ1dGU6IDAsCiAgICAgICAgICAgIHByb3BlcnR5VGFibGU6IDAsCiAgICAgICAgICAgIGZlYXR1cmVDb3VudAogICAgICAgICAgfQogICAgICAgIF0KICAgICAgfTsKICAgICAgZXh0ZW5zaW9uc1VzZWQucHVzaCgiRVhUX21lc2hfZmVhdHVyZXMiKTsKICAgIH0KICAgIGlmIChkZWZpbmVkX2RlZmF1bHQocHJvcGVydHlUYWJsZTBVUkwpKSB7CiAgICAgIGJ1ZmZlcnMucHVzaCh7CiAgICAgICAgdXJpOiBwcm9wZXJ0eVRhYmxlMFVSTCwKICAgICAgICBieXRlTGVuZ3RoOiBtZXNoUHJvcGVydHlUYWJsZTAuYnl0ZUxlbmd0aAogICAgICB9KTsKICAgICAgYnVmZmVyVmlld3MucHVzaCh7CiAgICAgICAgYnVmZmVyOiBidWZmZXJzLmxlbmd0aCAtIDEsCiAgICAgICAgYnl0ZU9mZnNldDogMCwKICAgICAgICBieXRlTGVuZ3RoOiBtZXNoUHJvcGVydHlUYWJsZTAuYnl0ZUxlbmd0aCwKICAgICAgICB0YXJnZXQ6IDM0OTYzCiAgICAgIH0pOwogICAgICByb290RXh0ZW5zaW9ucy5FWFRfc3RydWN0dXJhbF9tZXRhZGF0YSA9IHsKICAgICAgICBzY2hlbWE6IHsKICAgICAgICAgIGlkOiAiaTNzLW1ldGFkYXRhLXNjaGVtYS0wMDEiLAogICAgICAgICAgbmFtZTogIkkzUyBtZXRhZGF0YSBzY2hlbWEgMDAxIiwKICAgICAgICAgIGRlc2NyaXB0aW9uOiAiVGhlIHNjaGVtYSBmb3IgSTNTIG1ldGFkYXRhIiwKICAgICAgICAgIHZlcnNpb246ICIxLjAiLAogICAgICAgICAgY2xhc3NlczogewogICAgICAgICAgICBmZWF0dXJlOiB7CiAgICAgICAgICAgICAgbmFtZTogImZlYXR1cmUiLAogICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAiRmVhdHVyZSBtZXRhZGF0YSIsCiAgICAgICAgICAgICAgcHJvcGVydGllczogewogICAgICAgICAgICAgICAgaW5kZXg6IHsKICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb246ICJUaGUgZmVhdHVyZSBpbmRleCIsCiAgICAgICAgICAgICAgICAgIHR5cGU6ICJTQ0FMQVIiLAogICAgICAgICAgICAgICAgICBjb21wb25lbnRUeXBlOiAiRkxPQVQzMiIsCiAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiB0cnVlCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICBwcm9wZXJ0eVRhYmxlczogWwogICAgICAgICAgewogICAgICAgICAgICBuYW1lOiAiZmVhdHVyZS1pbmRpY2VzLW1hcHBpbmciLAogICAgICAgICAgICBjbGFzczogImZlYXR1cmUiLAogICAgICAgICAgICBjb3VudDogZmVhdHVyZUNvdW50LAogICAgICAgICAgICBwcm9wZXJ0aWVzOiB7CiAgICAgICAgICAgICAgaW5kZXg6IHsKICAgICAgICAgICAgICAgIHZhbHVlczogYnVmZmVyVmlld3MubGVuZ3RoIC0gMQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIF0KICAgICAgfTsKICAgICAgZXh0ZW5zaW9uc1VzZWQucHVzaCgiRVhUX3N0cnVjdHVyYWxfbWV0YWRhdGEiKTsKICAgIH0KICAgIGlmIChkZWZpbmVkX2RlZmF1bHQob3V0bGluZXNJbmRpY2VzVVJMKSkgewogICAgICBidWZmZXJzLnB1c2goewogICAgICAgIHVyaTogb3V0bGluZXNJbmRpY2VzVVJMLAogICAgICAgIGJ5dGVMZW5ndGg6IG91dGxpbmVzSW5kZXhBcnJheS5ieXRlTGVuZ3RoCiAgICAgIH0pOwogICAgICBidWZmZXJWaWV3cy5wdXNoKHsKICAgICAgICBidWZmZXI6IGJ1ZmZlcnMubGVuZ3RoIC0gMSwKICAgICAgICBieXRlT2Zmc2V0OiAwLAogICAgICAgIGJ5dGVMZW5ndGg6IG91dGxpbmVzSW5kZXhBcnJheS5ieXRlTGVuZ3RoLAogICAgICAgIHRhcmdldDogMzQ5NjMKICAgICAgfSk7CiAgICAgIGFjY2Vzc29ycy5wdXNoKHsKICAgICAgICBidWZmZXJWaWV3OiBidWZmZXJWaWV3cy5sZW5ndGggLSAxLAogICAgICAgIGJ5dGVPZmZzZXQ6IDAsCiAgICAgICAgY29tcG9uZW50VHlwZTogNTEyNSwKICAgICAgICBjb3VudDogb3V0bGluZXNJbmRleEFycmF5Lmxlbmd0aCwKICAgICAgICB0eXBlOiAiU0NBTEFSIgogICAgICB9KTsKICAgICAgZXh0ZW5zaW9ucy5DRVNJVU1fcHJpbWl0aXZlX291dGxpbmUgPSB7CiAgICAgICAgaW5kaWNlczogYWNjZXNzb3JzLmxlbmd0aCAtIDEKICAgICAgfTsKICAgICAgZXh0ZW5zaW9uc1VzZWQucHVzaCgiQ0VTSVVNX3ByaW1pdGl2ZV9vdXRsaW5lIik7CiAgICB9CiAgICBidWZmZXJzLnB1c2goewogICAgICB1cmk6IGluZGljZXNVUkwsCiAgICAgIGJ5dGVMZW5ndGg6IGluZGV4QXJyYXkuYnl0ZUxlbmd0aAogICAgfSk7CiAgICBidWZmZXJWaWV3cy5wdXNoKHsKICAgICAgYnVmZmVyOiBidWZmZXJzLmxlbmd0aCAtIDEsCiAgICAgIGJ5dGVPZmZzZXQ6IDAsCiAgICAgIGJ5dGVMZW5ndGg6IGluZGV4QXJyYXkuYnl0ZUxlbmd0aCwKICAgICAgdGFyZ2V0OiAzNDk2MwogICAgfSk7CiAgICBjb25zdCBtZXNoUHJpbWl0aXZlcyA9IFtdOwogICAgaWYgKHRyYW5zcGFyZW50VmVydGV4T2Zmc2V0ID4gMCkgewogICAgICBhY2Nlc3NvcnMucHVzaCh7CiAgICAgICAgYnVmZmVyVmlldzogYnVmZmVyVmlld3MubGVuZ3RoIC0gMSwKICAgICAgICBieXRlT2Zmc2V0OiAwLAogICAgICAgIGNvbXBvbmVudFR5cGU6IDUxMjUsCiAgICAgICAgY291bnQ6IHRyYW5zcGFyZW50VmVydGV4T2Zmc2V0LAogICAgICAgIHR5cGU6ICJTQ0FMQVIiCiAgICAgIH0pOwogICAgICBtZXNoUHJpbWl0aXZlcy5wdXNoKHsKICAgICAgICBhdHRyaWJ1dGVzLAogICAgICAgIGluZGljZXM6IGFjY2Vzc29ycy5sZW5ndGggLSAxLAogICAgICAgIG1hdGVyaWFsOiBtZXNoUHJpbWl0aXZlcy5sZW5ndGgsCiAgICAgICAgZXh0ZW5zaW9ucwogICAgICB9KTsKICAgIH0KICAgIGlmICh0cmFuc3BhcmVudFZlcnRleE9mZnNldCA8IHZlcnRleENvdW50KSB7CiAgICAgIGFjY2Vzc29ycy5wdXNoKHsKICAgICAgICBidWZmZXJWaWV3OiBidWZmZXJWaWV3cy5sZW5ndGggLSAxLAogICAgICAgIGJ5dGVPZmZzZXQ6IDQgKiB0cmFuc3BhcmVudFZlcnRleE9mZnNldCwKICAgICAgICAvLyBza2lwIDQgYnl0ZXMgZm9yIGVhY2ggb3BhcXVlIHZlcnRleAogICAgICAgIGNvbXBvbmVudFR5cGU6IDUxMjUsCiAgICAgICAgY291bnQ6IHZlcnRleENvdW50IC0gdHJhbnNwYXJlbnRWZXJ0ZXhPZmZzZXQsCiAgICAgICAgdHlwZTogIlNDQUxBUiIKICAgICAgfSk7CiAgICAgIG1lc2hQcmltaXRpdmVzLnB1c2goewogICAgICAgIGF0dHJpYnV0ZXMsCiAgICAgICAgaW5kaWNlczogYWNjZXNzb3JzLmxlbmd0aCAtIDEsCiAgICAgICAgbWF0ZXJpYWw6IG1lc2hQcmltaXRpdmVzLmxlbmd0aCwKICAgICAgICBleHRlbnNpb25zLAogICAgICAgIGV4dHJhOiB7CiAgICAgICAgICBpc1RyYW5zcGFyZW50OiB0cnVlCiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICAgIG1lc2hlcy5wdXNoKHsKICAgICAgcHJpbWl0aXZlczogbWVzaFByaW1pdGl2ZXMKICAgIH0pOwogICAgbm9kZXNJblNjZW5lLnB1c2goMCk7CiAgICBub2Rlcy5wdXNoKHsgbWVzaDogMCB9KTsKICAgIHJldHVybiB7CiAgICAgIGJ1ZmZlcnMsCiAgICAgIGJ1ZmZlclZpZXdzLAogICAgICBhY2Nlc3NvcnMsCiAgICAgIG1lc2hlcywKICAgICAgbm9kZXMsCiAgICAgIG5vZGVzSW5TY2VuZSwKICAgICAgcm9vdEV4dGVuc2lvbnMsCiAgICAgIGV4dGVuc2lvbnNVc2VkCiAgICB9OwogIH0KICBmdW5jdGlvbiBkZWNvZGUyKGRhdGEsIHNjaGVtYSwgYnVmZmVySW5mbywgZmVhdHVyZURhdGEpIHsKICAgIGNvbnN0IG1hZ2ljTnVtYmVyID0gbmV3IFVpbnQ4QXJyYXkoZGF0YSwgMCwgNSk7CiAgICBpZiAobWFnaWNOdW1iZXJbMF0gPT09ICJEIi5jaGFyQ29kZUF0KCkgJiYgbWFnaWNOdW1iZXJbMV0gPT09ICJSIi5jaGFyQ29kZUF0KCkgJiYgbWFnaWNOdW1iZXJbMl0gPT09ICJBIi5jaGFyQ29kZUF0KCkgJiYgbWFnaWNOdW1iZXJbM10gPT09ICJDIi5jaGFyQ29kZUF0KCkgJiYgbWFnaWNOdW1iZXJbNF0gPT09ICJPIi5jaGFyQ29kZUF0KCkpIHsKICAgICAgcmV0dXJuIGRlY29kZURyYWNvRW5jb2RlZEdlb21ldHJ5KGRhdGEsIGJ1ZmZlckluZm8pOwogICAgfQogICAgcmV0dXJuIGRlY29kZUJpbmFyeUdlb21ldHJ5KGRhdGEsIHNjaGVtYSwgYnVmZmVySW5mbywgZmVhdHVyZURhdGEpOwogIH0KICBmdW5jdGlvbiBkZWNvZGVEcmFjb0VuY29kZWRHZW9tZXRyeShkYXRhKSB7CiAgICBjb25zdCBkcmFjb0RlY29kZXJNb2R1bGUgPSBkcmFjbzI7CiAgICBjb25zdCBidWZmZXIgPSBuZXcgZHJhY29EZWNvZGVyTW9kdWxlLkRlY29kZXJCdWZmZXIoKTsKICAgIGNvbnN0IGJ5dGVBcnJheSA9IG5ldyBVaW50OEFycmF5KGRhdGEpOwogICAgYnVmZmVyLkluaXQoYnl0ZUFycmF5LCBieXRlQXJyYXkubGVuZ3RoKTsKICAgIGNvbnN0IGRyYWNvRGVjb2RlciA9IG5ldyBkcmFjb0RlY29kZXJNb2R1bGUuRGVjb2RlcigpOwogICAgY29uc3QgZ2VvbWV0cnlUeXBlID0gZHJhY29EZWNvZGVyLkdldEVuY29kZWRHZW9tZXRyeVR5cGUoYnVmZmVyKTsKICAgIGNvbnN0IG1ldGFkYXRhUXVlcmllciA9IG5ldyBkcmFjb0RlY29kZXJNb2R1bGUuTWV0YWRhdGFRdWVyaWVyKCk7CiAgICBsZXQgZHJhY29HZW9tZXRyeTsKICAgIGxldCBzdGF0dXM7CiAgICBpZiAoZ2VvbWV0cnlUeXBlID09PSBkcmFjb0RlY29kZXJNb2R1bGUuVFJJQU5HVUxBUl9NRVNIKSB7CiAgICAgIGRyYWNvR2VvbWV0cnkgPSBuZXcgZHJhY29EZWNvZGVyTW9kdWxlLk1lc2goKTsKICAgICAgc3RhdHVzID0gZHJhY29EZWNvZGVyLkRlY29kZUJ1ZmZlclRvTWVzaChidWZmZXIsIGRyYWNvR2VvbWV0cnkpOwogICAgfQogICAgY29uc3QgZGVjb2RlZEdlb21ldHJ5ID0gewogICAgICB2ZXJ0ZXhDb3VudDogWzBdLAogICAgICBmZWF0dXJlQ291bnQ6IDAKICAgIH07CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHN0YXR1cykgJiYgc3RhdHVzLm9rKCkgJiYgZHJhY29HZW9tZXRyeS5wdHIgIT09IDApIHsKICAgICAgY29uc3QgZmFjZUNvdW50ID0gZHJhY29HZW9tZXRyeS5udW1fZmFjZXMoKTsKICAgICAgY29uc3QgYXR0cmlidXRlc0NvdW50ID0gZHJhY29HZW9tZXRyeS5udW1fYXR0cmlidXRlcygpOwogICAgICBjb25zdCB2ZXJ0ZXhDb3VudCA9IGRyYWNvR2VvbWV0cnkubnVtX3BvaW50cygpOwogICAgICBkZWNvZGVkR2VvbWV0cnkuaW5kaWNlcyA9IG5ldyBVaW50MzJBcnJheShmYWNlQ291bnQgKiAzKTsKICAgICAgY29uc3QgZmFjZXMyID0gZGVjb2RlZEdlb21ldHJ5LmluZGljZXM7CiAgICAgIGRlY29kZWRHZW9tZXRyeS52ZXJ0ZXhDb3VudFswXSA9IHZlcnRleENvdW50OwogICAgICBkZWNvZGVkR2VvbWV0cnkuc2NhbGVfeCA9IDE7CiAgICAgIGRlY29kZWRHZW9tZXRyeS5zY2FsZV95ID0gMTsKICAgICAgY29uc3QgZmFjZSA9IG5ldyBkcmFjb0RlY29kZXJNb2R1bGUuRHJhY29JbnQzMkFycmF5KDMpOwogICAgICBmb3IgKGxldCBmYWNlSW5kZXggPSAwOyBmYWNlSW5kZXggPCBmYWNlQ291bnQ7ICsrZmFjZUluZGV4KSB7CiAgICAgICAgZHJhY29EZWNvZGVyLkdldEZhY2VGcm9tTWVzaChkcmFjb0dlb21ldHJ5LCBmYWNlSW5kZXgsIGZhY2UpOwogICAgICAgIGZhY2VzMltmYWNlSW5kZXggKiAzXSA9IGZhY2UuR2V0VmFsdWUoMCk7CiAgICAgICAgZmFjZXMyW2ZhY2VJbmRleCAqIDMgKyAxXSA9IGZhY2UuR2V0VmFsdWUoMSk7CiAgICAgICAgZmFjZXMyW2ZhY2VJbmRleCAqIDMgKyAyXSA9IGZhY2UuR2V0VmFsdWUoMik7CiAgICAgIH0KICAgICAgZHJhY29EZWNvZGVyTW9kdWxlLmRlc3Ryb3koZmFjZSk7CiAgICAgIGZvciAobGV0IGF0dHJJbmRleCA9IDA7IGF0dHJJbmRleCA8IGF0dHJpYnV0ZXNDb3VudDsgKythdHRySW5kZXgpIHsKICAgICAgICBjb25zdCBkcmFjb0F0dHJpYnV0ZSA9IGRyYWNvRGVjb2Rlci5HZXRBdHRyaWJ1dGUoCiAgICAgICAgICBkcmFjb0dlb21ldHJ5LAogICAgICAgICAgYXR0ckluZGV4CiAgICAgICAgKTsKICAgICAgICBjb25zdCBhdHRyaWJ1dGVEYXRhID0gZGVjb2RlRHJhY29BdHRyaWJ1dGUoCiAgICAgICAgICBkcmFjb0RlY29kZXJNb2R1bGUsCiAgICAgICAgICBkcmFjb0RlY29kZXIsCiAgICAgICAgICBkcmFjb0dlb21ldHJ5LAogICAgICAgICAgZHJhY29BdHRyaWJ1dGUsCiAgICAgICAgICB2ZXJ0ZXhDb3VudAogICAgICAgICk7CiAgICAgICAgY29uc3QgZHJhY29BdHRyaWJ1dGVUeXBlID0gZHJhY29BdHRyaWJ1dGUuYXR0cmlidXRlX3R5cGUoKTsKICAgICAgICBsZXQgYXR0cmlidXRlaTNzTmFtZSA9ICJ1bmtub3duIjsKICAgICAgICBpZiAoZHJhY29BdHRyaWJ1dGVUeXBlID09PSBkcmFjb0RlY29kZXJNb2R1bGUuUE9TSVRJT04pIHsKICAgICAgICAgIGF0dHJpYnV0ZWkzc05hbWUgPSAicG9zaXRpb25zIjsKICAgICAgICB9IGVsc2UgaWYgKGRyYWNvQXR0cmlidXRlVHlwZSA9PT0gZHJhY29EZWNvZGVyTW9kdWxlLk5PUk1BTCkgewogICAgICAgICAgYXR0cmlidXRlaTNzTmFtZSA9ICJub3JtYWxzIjsKICAgICAgICB9IGVsc2UgaWYgKGRyYWNvQXR0cmlidXRlVHlwZSA9PT0gZHJhY29EZWNvZGVyTW9kdWxlLkNPTE9SKSB7CiAgICAgICAgICBhdHRyaWJ1dGVpM3NOYW1lID0gImNvbG9ycyI7CiAgICAgICAgfSBlbHNlIGlmIChkcmFjb0F0dHJpYnV0ZVR5cGUgPT09IGRyYWNvRGVjb2Rlck1vZHVsZS5URVhfQ09PUkQpIHsKICAgICAgICAgIGF0dHJpYnV0ZWkzc05hbWUgPSAidXYwcyI7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG1ldGFkYXRhID0gZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZU1ldGFkYXRhKAogICAgICAgICAgZHJhY29HZW9tZXRyeSwKICAgICAgICAgIGF0dHJJbmRleAogICAgICAgICk7CiAgICAgICAgaWYgKG1ldGFkYXRhLnB0ciAhPT0gMCkgewogICAgICAgICAgY29uc3QgbnVtRW50cmllcyA9IG1ldGFkYXRhUXVlcmllci5OdW1FbnRyaWVzKG1ldGFkYXRhKTsKICAgICAgICAgIGZvciAobGV0IGVudHJ5ID0gMDsgZW50cnkgPCBudW1FbnRyaWVzOyArK2VudHJ5KSB7CiAgICAgICAgICAgIGNvbnN0IGVudHJ5TmFtZSA9IG1ldGFkYXRhUXVlcmllci5HZXRFbnRyeU5hbWUobWV0YWRhdGEsIGVudHJ5KTsKICAgICAgICAgICAgaWYgKGVudHJ5TmFtZSA9PT0gImkzcy1zY2FsZV94IikgewogICAgICAgICAgICAgIGRlY29kZWRHZW9tZXRyeS5zY2FsZV94ID0gbWV0YWRhdGFRdWVyaWVyLkdldERvdWJsZUVudHJ5KAogICAgICAgICAgICAgICAgbWV0YWRhdGEsCiAgICAgICAgICAgICAgICAiaTNzLXNjYWxlX3giCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgfSBlbHNlIGlmIChlbnRyeU5hbWUgPT09ICJpM3Mtc2NhbGVfeSIpIHsKICAgICAgICAgICAgICBkZWNvZGVkR2VvbWV0cnkuc2NhbGVfeSA9IG1ldGFkYXRhUXVlcmllci5HZXREb3VibGVFbnRyeSgKICAgICAgICAgICAgICAgIG1ldGFkYXRhLAogICAgICAgICAgICAgICAgImkzcy1zY2FsZV95IgogICAgICAgICAgICAgICk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoZW50cnlOYW1lID09PSAiaTNzLWF0dHJpYnV0ZS10eXBlIikgewogICAgICAgICAgICAgIGF0dHJpYnV0ZWkzc05hbWUgPSBtZXRhZGF0YVF1ZXJpZXIuR2V0U3RyaW5nRW50cnkoCiAgICAgICAgICAgICAgICBtZXRhZGF0YSwKICAgICAgICAgICAgICAgICJpM3MtYXR0cmlidXRlLXR5cGUiCiAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGRlY29kZWRHZW9tZXRyeVthdHRyaWJ1dGVpM3NOYW1lXSkpIHsKICAgICAgICAgIGNvbnNvbGUubG9nKCJBdHRyaWJ1dGUgYWxyZWFkeSBleGlzdHMiLCBhdHRyaWJ1dGVpM3NOYW1lKTsKICAgICAgICB9CiAgICAgICAgZGVjb2RlZEdlb21ldHJ5W2F0dHJpYnV0ZWkzc05hbWVdID0gYXR0cmlidXRlRGF0YTsKICAgICAgICBpZiAoYXR0cmlidXRlaTNzTmFtZSA9PT0gImZlYXR1cmUtaW5kZXgiKSB7CiAgICAgICAgICBkZWNvZGVkR2VvbWV0cnkuZmVhdHVyZUNvdW50Kys7CiAgICAgICAgfQogICAgICB9CiAgICAgIGRyYWNvRGVjb2Rlck1vZHVsZS5kZXN0cm95KGRyYWNvR2VvbWV0cnkpOwogICAgfQogICAgZHJhY29EZWNvZGVyTW9kdWxlLmRlc3Ryb3kobWV0YWRhdGFRdWVyaWVyKTsKICAgIGRyYWNvRGVjb2Rlck1vZHVsZS5kZXN0cm95KGRyYWNvRGVjb2Rlcik7CiAgICByZXR1cm4gZGVjb2RlZEdlb21ldHJ5OwogIH0KICBmdW5jdGlvbiBkZWNvZGVEcmFjb0F0dHJpYnV0ZShkcmFjb0RlY29kZXJNb2R1bGUsIGRyYWNvRGVjb2RlciwgZHJhY29HZW9tZXRyeSwgZHJhY29BdHRyaWJ1dGUsIHZlcnRleENvdW50KSB7CiAgICBjb25zdCBidWZmZXJTaXplID0gZHJhY29BdHRyaWJ1dGUubnVtX2NvbXBvbmVudHMoKSAqIHZlcnRleENvdW50OwogICAgbGV0IGRyYWNvQXR0cmlidXRlRGF0YTsKICAgIGNvbnN0IGhhbmRsZXJzID0gWwogICAgICBmdW5jdGlvbigpIHsKICAgICAgfSwKICAgICAgLy8gRFRfSU5WQUxJRCAtIDAKICAgICAgZnVuY3Rpb24oKSB7CiAgICAgICAgZHJhY29BdHRyaWJ1dGVEYXRhID0gbmV3IGRyYWNvRGVjb2Rlck1vZHVsZS5EcmFjb0ludDhBcnJheShidWZmZXJTaXplKTsKICAgICAgICBjb25zdCBzdWNjZXNzID0gZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZUludDhGb3JBbGxQb2ludHMoCiAgICAgICAgICBkcmFjb0dlb21ldHJ5LAogICAgICAgICAgZHJhY29BdHRyaWJ1dGUsCiAgICAgICAgICBkcmFjb0F0dHJpYnV0ZURhdGEKICAgICAgICApOwogICAgICAgIGlmICghc3VjY2VzcykgewogICAgICAgICAgY29uc29sZS5lcnJvcigiQmFkIHN0cmVhbSIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBhdHRyaWJ1dGVEYXRhMiA9IG5ldyBJbnQ4QXJyYXkoYnVmZmVyU2l6ZSk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBidWZmZXJTaXplOyArK2kpIHsKICAgICAgICAgIGF0dHJpYnV0ZURhdGEyW2ldID0gZHJhY29BdHRyaWJ1dGVEYXRhLkdldFZhbHVlKGkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYXR0cmlidXRlRGF0YTI7CiAgICAgIH0sCiAgICAgIGZ1bmN0aW9uKCkgewogICAgICAgIGRyYWNvQXR0cmlidXRlRGF0YSA9IG5ldyBkcmFjb0RlY29kZXJNb2R1bGUuRHJhY29JbnQ4QXJyYXkoYnVmZmVyU2l6ZSk7CiAgICAgICAgY29uc3Qgc3VjY2VzcyA9IGRyYWNvRGVjb2Rlci5HZXRBdHRyaWJ1dGVVSW50OEZvckFsbFBvaW50cygKICAgICAgICAgIGRyYWNvR2VvbWV0cnksCiAgICAgICAgICBkcmFjb0F0dHJpYnV0ZSwKICAgICAgICAgIGRyYWNvQXR0cmlidXRlRGF0YQogICAgICAgICk7CiAgICAgICAgaWYgKCFzdWNjZXNzKSB7CiAgICAgICAgICBjb25zb2xlLmVycm9yKCJCYWQgc3RyZWFtIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGF0dHJpYnV0ZURhdGEyID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyU2l6ZSk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBidWZmZXJTaXplOyArK2kpIHsKICAgICAgICAgIGF0dHJpYnV0ZURhdGEyW2ldID0gZHJhY29BdHRyaWJ1dGVEYXRhLkdldFZhbHVlKGkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYXR0cmlidXRlRGF0YTI7CiAgICAgIH0sCiAgICAgIGZ1bmN0aW9uKCkgewogICAgICAgIGRyYWNvQXR0cmlidXRlRGF0YSA9IG5ldyBkcmFjb0RlY29kZXJNb2R1bGUuRHJhY29JbnQxNkFycmF5KGJ1ZmZlclNpemUpOwogICAgICAgIGNvbnN0IHN1Y2Nlc3MgPSBkcmFjb0RlY29kZXIuR2V0QXR0cmlidXRlSW50MTZGb3JBbGxQb2ludHMoCiAgICAgICAgICBkcmFjb0dlb21ldHJ5LAogICAgICAgICAgZHJhY29BdHRyaWJ1dGUsCiAgICAgICAgICBkcmFjb0F0dHJpYnV0ZURhdGEKICAgICAgICApOwogICAgICAgIGlmICghc3VjY2VzcykgewogICAgICAgICAgY29uc29sZS5lcnJvcigiQmFkIHN0cmVhbSIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBhdHRyaWJ1dGVEYXRhMiA9IG5ldyBJbnQxNkFycmF5KGJ1ZmZlclNpemUpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnVmZmVyU2l6ZTsgKytpKSB7CiAgICAgICAgICBhdHRyaWJ1dGVEYXRhMltpXSA9IGRyYWNvQXR0cmlidXRlRGF0YS5HZXRWYWx1ZShpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZURhdGEyOwogICAgICB9LAogICAgICBmdW5jdGlvbigpIHsKICAgICAgICBkcmFjb0F0dHJpYnV0ZURhdGEgPSBuZXcgZHJhY29EZWNvZGVyTW9kdWxlLkRyYWNvSW50MTZBcnJheShidWZmZXJTaXplKTsKICAgICAgICBjb25zdCBzdWNjZXNzID0gZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZVVJbnQxNkZvckFsbFBvaW50cygKICAgICAgICAgIGRyYWNvR2VvbWV0cnksCiAgICAgICAgICBkcmFjb0F0dHJpYnV0ZSwKICAgICAgICAgIGRyYWNvQXR0cmlidXRlRGF0YQogICAgICAgICk7CiAgICAgICAgaWYgKCFzdWNjZXNzKSB7CiAgICAgICAgICBjb25zb2xlLmVycm9yKCJCYWQgc3RyZWFtIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGF0dHJpYnV0ZURhdGEyID0gbmV3IFVpbnQxNkFycmF5KGJ1ZmZlclNpemUpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnVmZmVyU2l6ZTsgKytpKSB7CiAgICAgICAgICBhdHRyaWJ1dGVEYXRhMltpXSA9IGRyYWNvQXR0cmlidXRlRGF0YS5HZXRWYWx1ZShpKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZURhdGEyOwogICAgICB9LAogICAgICBmdW5jdGlvbigpIHsKICAgICAgICBkcmFjb0F0dHJpYnV0ZURhdGEgPSBuZXcgZHJhY29EZWNvZGVyTW9kdWxlLkRyYWNvSW50MzJBcnJheShidWZmZXJTaXplKTsKICAgICAgICBjb25zdCBzdWNjZXNzID0gZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZUludDMyRm9yQWxsUG9pbnRzKAogICAgICAgICAgZHJhY29HZW9tZXRyeSwKICAgICAgICAgIGRyYWNvQXR0cmlidXRlLAogICAgICAgICAgZHJhY29BdHRyaWJ1dGVEYXRhCiAgICAgICAgKTsKICAgICAgICBpZiAoIXN1Y2Nlc3MpIHsKICAgICAgICAgIGNvbnNvbGUuZXJyb3IoIkJhZCBzdHJlYW0iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgYXR0cmlidXRlRGF0YTIgPSBuZXcgSW50MzJBcnJheShidWZmZXJTaXplKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1ZmZlclNpemU7ICsraSkgewogICAgICAgICAgYXR0cmlidXRlRGF0YTJbaV0gPSBkcmFjb0F0dHJpYnV0ZURhdGEuR2V0VmFsdWUoaSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBhdHRyaWJ1dGVEYXRhMjsKICAgICAgfSwKICAgICAgZnVuY3Rpb24oKSB7CiAgICAgICAgZHJhY29BdHRyaWJ1dGVEYXRhID0gbmV3IGRyYWNvRGVjb2Rlck1vZHVsZS5EcmFjb0ludDMyQXJyYXkoYnVmZmVyU2l6ZSk7CiAgICAgICAgY29uc3Qgc3VjY2VzcyA9IGRyYWNvRGVjb2Rlci5HZXRBdHRyaWJ1dGVVSW50MzJGb3JBbGxQb2ludHMoCiAgICAgICAgICBkcmFjb0dlb21ldHJ5LAogICAgICAgICAgZHJhY29BdHRyaWJ1dGUsCiAgICAgICAgICBkcmFjb0F0dHJpYnV0ZURhdGEKICAgICAgICApOwogICAgICAgIGlmICghc3VjY2VzcykgewogICAgICAgICAgY29uc29sZS5lcnJvcigiQmFkIHN0cmVhbSIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBhdHRyaWJ1dGVEYXRhMiA9IG5ldyBVaW50MzJBcnJheShidWZmZXJTaXplKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1ZmZlclNpemU7ICsraSkgewogICAgICAgICAgYXR0cmlidXRlRGF0YTJbaV0gPSBkcmFjb0F0dHJpYnV0ZURhdGEuR2V0VmFsdWUoaSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBhdHRyaWJ1dGVEYXRhMjsKICAgICAgfSwKICAgICAgZnVuY3Rpb24oKSB7CiAgICAgIH0sCiAgICAgIGZ1bmN0aW9uKCkgewogICAgICB9LAogICAgICBmdW5jdGlvbigpIHsKICAgICAgICBkcmFjb0F0dHJpYnV0ZURhdGEgPSBuZXcgZHJhY29EZWNvZGVyTW9kdWxlLkRyYWNvRmxvYXQzMkFycmF5KGJ1ZmZlclNpemUpOwogICAgICAgIGNvbnN0IHN1Y2Nlc3MgPSBkcmFjb0RlY29kZXIuR2V0QXR0cmlidXRlRmxvYXRGb3JBbGxQb2ludHMoCiAgICAgICAgICBkcmFjb0dlb21ldHJ5LAogICAgICAgICAgZHJhY29BdHRyaWJ1dGUsCiAgICAgICAgICBkcmFjb0F0dHJpYnV0ZURhdGEKICAgICAgICApOwogICAgICAgIGlmICghc3VjY2VzcykgewogICAgICAgICAgY29uc29sZS5lcnJvcigiQmFkIHN0cmVhbSIpOwogICAgICAgIH0KICAgICAgICBjb25zdCBhdHRyaWJ1dGVEYXRhMiA9IG5ldyBGbG9hdDMyQXJyYXkoYnVmZmVyU2l6ZSk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBidWZmZXJTaXplOyArK2kpIHsKICAgICAgICAgIGF0dHJpYnV0ZURhdGEyW2ldID0gZHJhY29BdHRyaWJ1dGVEYXRhLkdldFZhbHVlKGkpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYXR0cmlidXRlRGF0YTI7CiAgICAgIH0sCiAgICAgIGZ1bmN0aW9uKCkgewogICAgICB9LAogICAgICBmdW5jdGlvbigpIHsKICAgICAgICBkcmFjb0F0dHJpYnV0ZURhdGEgPSBuZXcgZHJhY29EZWNvZGVyTW9kdWxlLkRyYWNvVUludDhBcnJheShidWZmZXJTaXplKTsKICAgICAgICBjb25zdCBzdWNjZXNzID0gZHJhY29EZWNvZGVyLkdldEF0dHJpYnV0ZVVJbnQ4Rm9yQWxsUG9pbnRzKAogICAgICAgICAgZHJhY29HZW9tZXRyeSwKICAgICAgICAgIGRyYWNvQXR0cmlidXRlLAogICAgICAgICAgZHJhY29BdHRyaWJ1dGVEYXRhCiAgICAgICAgKTsKICAgICAgICBpZiAoIXN1Y2Nlc3MpIHsKICAgICAgICAgIGNvbnNvbGUuZXJyb3IoIkJhZCBzdHJlYW0iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgYXR0cmlidXRlRGF0YTIgPSBuZXcgVWludDhBcnJheShidWZmZXJTaXplKTsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1ZmZlclNpemU7ICsraSkgewogICAgICAgICAgYXR0cmlidXRlRGF0YTJbaV0gPSBkcmFjb0F0dHJpYnV0ZURhdGEuR2V0VmFsdWUoaSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBhdHRyaWJ1dGVEYXRhMjsKICAgICAgfQogICAgXTsKICAgIGNvbnN0IGF0dHJpYnV0ZURhdGEgPSBoYW5kbGVyc1tkcmFjb0F0dHJpYnV0ZS5kYXRhX3R5cGUoKV0oKTsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZHJhY29BdHRyaWJ1dGVEYXRhKSkgewogICAgICBkcmFjb0RlY29kZXJNb2R1bGUuZGVzdHJveShkcmFjb0F0dHJpYnV0ZURhdGEpOwogICAgfQogICAgcmV0dXJuIGF0dHJpYnV0ZURhdGE7CiAgfQogIGZ1bmN0aW9uIGRlY29kZUJpbmFyeUdlb21ldHJ5KGRhdGEsIHNjaGVtYSwgYnVmZmVySW5mbywgZmVhdHVyZURhdGEpIHsKICAgIGNvbnN0IGRlY29kZWRHZW9tZXRyeSA9IHsKICAgICAgdmVydGV4Q291bnQ6IDAKICAgIH07CiAgICBjb25zdCBkYXRhVmlldyA9IG5ldyBEYXRhVmlldyhkYXRhKTsKICAgIHRyeSB7CiAgICAgIGxldCBvZmZzZXQgPSAwOwogICAgICBkZWNvZGVkR2VvbWV0cnkudmVydGV4Q291bnQgPSBkYXRhVmlldy5nZXRVaW50MzIob2Zmc2V0LCAxKTsKICAgICAgb2Zmc2V0ICs9IDQ7CiAgICAgIGRlY29kZWRHZW9tZXRyeS5mZWF0dXJlQ291bnQgPSBkYXRhVmlldy5nZXRVaW50MzIob2Zmc2V0LCAxKTsKICAgICAgb2Zmc2V0ICs9IDQ7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoYnVmZmVySW5mbykpIHsKICAgICAgICBmb3IgKGxldCBhdHRySW5kZXggPSAwOyBhdHRySW5kZXggPCBidWZmZXJJbmZvLmF0dHJpYnV0ZXMubGVuZ3RoOyBhdHRySW5kZXgrKykgewogICAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChiaW5hcnlBdHRyaWJ1dGVEZWNvZGVyc1tidWZmZXJJbmZvLmF0dHJpYnV0ZXNbYXR0ckluZGV4XV0pKSB7CiAgICAgICAgICAgIG9mZnNldCA9IGJpbmFyeUF0dHJpYnV0ZURlY29kZXJzW2J1ZmZlckluZm8uYXR0cmlidXRlc1thdHRySW5kZXhdXSgKICAgICAgICAgICAgICBkZWNvZGVkR2VvbWV0cnksCiAgICAgICAgICAgICAgZGF0YSwKICAgICAgICAgICAgICBvZmZzZXQKICAgICAgICAgICAgKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoCiAgICAgICAgICAgICAgIlVua25vd24gZGVjb2RlciBmb3IiLAogICAgICAgICAgICAgIGJ1ZmZlckluZm8uYXR0cmlidXRlc1thdHRySW5kZXhdCiAgICAgICAgICAgICk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGxldCBvcmRlcmluZyA9IHNjaGVtYS5vcmRlcmluZzsKICAgICAgICBsZXQgZmVhdHVyZUF0dHJpYnV0ZU9yZGVyID0gc2NoZW1hLmZlYXR1cmVBdHRyaWJ1dGVPcmRlcjsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGZlYXR1cmVEYXRhKSAmJiBkZWZpbmVkX2RlZmF1bHQoZmVhdHVyZURhdGEuZ2VvbWV0cnlEYXRhKSAmJiBkZWZpbmVkX2RlZmF1bHQoZmVhdHVyZURhdGEuZ2VvbWV0cnlEYXRhWzBdKSAmJiBkZWZpbmVkX2RlZmF1bHQoZmVhdHVyZURhdGEuZ2VvbWV0cnlEYXRhWzBdLnBhcmFtcykpIHsKICAgICAgICAgIG9yZGVyaW5nID0gT2JqZWN0LmtleXMoCiAgICAgICAgICAgIGZlYXR1cmVEYXRhLmdlb21ldHJ5RGF0YVswXS5wYXJhbXMudmVydGV4QXR0cmlidXRlcwogICAgICAgICAgKTsKICAgICAgICAgIGZlYXR1cmVBdHRyaWJ1dGVPcmRlciA9IE9iamVjdC5rZXlzKAogICAgICAgICAgICBmZWF0dXJlRGF0YS5nZW9tZXRyeURhdGFbMF0ucGFyYW1zLmZlYXR1cmVBdHRyaWJ1dGVzCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9yZGVyaW5nLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBjb25zdCBkZWNvZGVyID0gYmluYXJ5QXR0cmlidXRlRGVjb2RlcnNbb3JkZXJpbmdbaV1dOwogICAgICAgICAgb2Zmc2V0ID0gZGVjb2RlcihkZWNvZGVkR2VvbWV0cnksIGRhdGEsIG9mZnNldCk7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgZmVhdHVyZUF0dHJpYnV0ZU9yZGVyLmxlbmd0aDsgaisrKSB7CiAgICAgICAgICBjb25zdCBjdXJEZWNvZGVyID0gYmluYXJ5QXR0cmlidXRlRGVjb2RlcnNbZmVhdHVyZUF0dHJpYnV0ZU9yZGVyW2pdXTsKICAgICAgICAgIG9mZnNldCA9IGN1ckRlY29kZXIoZGVjb2RlZEdlb21ldHJ5LCBkYXRhLCBvZmZzZXQpOwogICAgICAgIH0KICAgICAgfQogICAgfSBjYXRjaCAoZSkgewogICAgICBjb25zb2xlLmVycm9yKGUpOwogICAgfQogICAgZGVjb2RlZEdlb21ldHJ5LnNjYWxlX3ggPSAxOwogICAgZGVjb2RlZEdlb21ldHJ5LnNjYWxlX3kgPSAxOwogICAgcmV0dXJuIGRlY29kZWRHZW9tZXRyeTsKICB9CiAgZnVuY3Rpb24gZGVjb2RlQW5kQ3JlYXRlR2x0ZihwYXJhbWV0ZXJzKSB7CiAgICBjb25zdCBnZW9tZXRyeURhdGEgPSBkZWNvZGUyKAogICAgICBwYXJhbWV0ZXJzLmJpbmFyeURhdGEsCiAgICAgIHBhcmFtZXRlcnMuc2NoZW1hLAogICAgICBwYXJhbWV0ZXJzLmJ1ZmZlckluZm8sCiAgICAgIHBhcmFtZXRlcnMuZmVhdHVyZURhdGEKICAgICk7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHBhcmFtZXRlcnMuZ2VvaWREYXRhTGlzdCkgJiYgcGFyYW1ldGVycy5nZW9pZERhdGFMaXN0Lmxlbmd0aCA+IDApIHsKICAgICAgb3J0aG9tZXRyaWNUb0VsbGlwc29pZGFsKAogICAgICAgIGdlb21ldHJ5RGF0YS52ZXJ0ZXhDb3VudCwKICAgICAgICBnZW9tZXRyeURhdGEucG9zaXRpb25zLAogICAgICAgIGdlb21ldHJ5RGF0YS5zY2FsZV94LAogICAgICAgIGdlb21ldHJ5RGF0YS5zY2FsZV95LAogICAgICAgIHBhcmFtZXRlcnMuY2FydG9ncmFwaGljQ2VudGVyLAogICAgICAgIHBhcmFtZXRlcnMuZ2VvaWREYXRhTGlzdCwKICAgICAgICBmYWxzZQogICAgICApOwogICAgfQogICAgdHJhbnNmb3JtVG9Mb2NhbCgKICAgICAgZ2VvbWV0cnlEYXRhLnZlcnRleENvdW50LAogICAgICBnZW9tZXRyeURhdGEucG9zaXRpb25zLAogICAgICBnZW9tZXRyeURhdGEubm9ybWFscywKICAgICAgcGFyYW1ldGVycy5jYXJ0b2dyYXBoaWNDZW50ZXIsCiAgICAgIHBhcmFtZXRlcnMuY2FydGVzaWFuQ2VudGVyLAogICAgICBwYXJhbWV0ZXJzLnBhcmVudFJvdGF0aW9uLAogICAgICBwYXJhbWV0ZXJzLmVsbGlwc29pZFJhZGlpU3F1YXJlLAogICAgICBnZW9tZXRyeURhdGEuc2NhbGVfeCwKICAgICAgZ2VvbWV0cnlEYXRhLnNjYWxlX3kKICAgICk7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KGdlb21ldHJ5RGF0YS51djBzKSAmJiBkZWZpbmVkX2RlZmF1bHQoZ2VvbWV0cnlEYXRhWyJ1di1yZWdpb24iXSkpIHsKICAgICAgY3JvcFVWcygKICAgICAgICBnZW9tZXRyeURhdGEudmVydGV4Q291bnQsCiAgICAgICAgZ2VvbWV0cnlEYXRhLnV2MHMsCiAgICAgICAgZ2VvbWV0cnlEYXRhWyJ1di1yZWdpb24iXQogICAgICApOwogICAgfQogICAgbGV0IGZlYXR1cmVJbmRleDsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQoZ2VvbWV0cnlEYXRhWyJmZWF0dXJlLWluZGV4Il0pKSB7CiAgICAgIGZlYXR1cmVJbmRleCA9IGdlb21ldHJ5RGF0YVsiZmVhdHVyZS1pbmRleCJdOwogICAgfSBlbHNlIGlmIChkZWZpbmVkX2RlZmF1bHQoZ2VvbWV0cnlEYXRhWyJmYWNlUmFuZ2UiXSkpIHsKICAgICAgZmVhdHVyZUluZGV4ID0gbmV3IEFycmF5KGdlb21ldHJ5RGF0YS52ZXJ0ZXhDb3VudCk7CiAgICAgIGZvciAobGV0IHJhbmdlID0gMDsgcmFuZ2UgPCBnZW9tZXRyeURhdGFbImZhY2VSYW5nZSJdLmxlbmd0aCAtIDE7IHJhbmdlICs9IDIpIHsKICAgICAgICBjb25zdCBjdXJJbmRleCA9IHJhbmdlIC8gMjsKICAgICAgICBjb25zdCByYW5nZVN0YXJ0ID0gZ2VvbWV0cnlEYXRhWyJmYWNlUmFuZ2UiXVtyYW5nZV07CiAgICAgICAgY29uc3QgcmFuZ2VFbmQgPSBnZW9tZXRyeURhdGFbImZhY2VSYW5nZSJdW3JhbmdlICsgMV07CiAgICAgICAgZm9yIChsZXQgaSA9IHJhbmdlU3RhcnQ7IGkgPD0gcmFuZ2VFbmQ7IGkrKykgewogICAgICAgICAgZmVhdHVyZUluZGV4W2kgKiAzXSA9IGN1ckluZGV4OwogICAgICAgICAgZmVhdHVyZUluZGV4W2kgKiAzICsgMV0gPSBjdXJJbmRleDsKICAgICAgICAgIGZlYXR1cmVJbmRleFtpICogMyArIDJdID0gY3VySW5kZXg7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAocGFyYW1ldGVycy5jYWxjdWxhdGVOb3JtYWxzKSB7CiAgICAgIGNvbnN0IGRhdGEgPSBnZW5lcmF0ZU5vcm1hbHMoCiAgICAgICAgZ2VvbWV0cnlEYXRhLnZlcnRleENvdW50LAogICAgICAgIGdlb21ldHJ5RGF0YS5pbmRpY2VzLAogICAgICAgIGdlb21ldHJ5RGF0YS5wb3NpdGlvbnMsCiAgICAgICAgZ2VvbWV0cnlEYXRhLm5vcm1hbHMsCiAgICAgICAgZ2VvbWV0cnlEYXRhLnV2MHMsCiAgICAgICAgZ2VvbWV0cnlEYXRhLmNvbG9ycywKICAgICAgICBmZWF0dXJlSW5kZXgKICAgICAgKTsKICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChkYXRhLm5vcm1hbHMpKSB7CiAgICAgICAgZ2VvbWV0cnlEYXRhLm5vcm1hbHMgPSBkYXRhLm5vcm1hbHM7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChkYXRhLnZlcnRleENvdW50KSkgewogICAgICAgICAgZ2VvbWV0cnlEYXRhLnZlcnRleENvdW50ID0gZGF0YS52ZXJ0ZXhDb3VudDsKICAgICAgICAgIGdlb21ldHJ5RGF0YS5pbmRpY2VzID0gZGF0YS5pbmRpY2VzOwogICAgICAgICAgZ2VvbWV0cnlEYXRhLnBvc2l0aW9ucyA9IGRhdGEucG9zaXRpb25zOwogICAgICAgICAgZ2VvbWV0cnlEYXRhLnV2MHMgPSBkYXRhLnV2MHM7CiAgICAgICAgICBnZW9tZXRyeURhdGEuY29sb3JzID0gZGF0YS5jb2xvcnM7CiAgICAgICAgICBmZWF0dXJlSW5kZXggPSBkYXRhLmZlYXR1cmVJbmRleDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IG1lc2hEYXRhID0gZ2VuZXJhdGVHbHRmQnVmZmVyKAogICAgICBnZW9tZXRyeURhdGEudmVydGV4Q291bnQsCiAgICAgIGdlb21ldHJ5RGF0YS5pbmRpY2VzLAogICAgICBnZW9tZXRyeURhdGEucG9zaXRpb25zLAogICAgICBnZW9tZXRyeURhdGEubm9ybWFscywKICAgICAgZ2VvbWV0cnlEYXRhLnV2MHMsCiAgICAgIGdlb21ldHJ5RGF0YS5jb2xvcnMsCiAgICAgIGZlYXR1cmVJbmRleCwKICAgICAgcGFyYW1ldGVycwogICAgKTsKICAgIGNvbnN0IGN1c3RvbUF0dHJpYnV0ZXMgPSB7CiAgICAgIHBvc2l0aW9uczogZ2VvbWV0cnlEYXRhLnBvc2l0aW9ucywKICAgICAgaW5kaWNlczogZ2VvbWV0cnlEYXRhLmluZGljZXMsCiAgICAgIGZlYXR1cmVJbmRleCwKICAgICAgc291cmNlVVJMOiBwYXJhbWV0ZXJzLnVybCwKICAgICAgY2FydGVzaWFuQ2VudGVyOiBwYXJhbWV0ZXJzLmNhcnRlc2lhbkNlbnRlciwKICAgICAgcGFyZW50Um90YXRpb246IHBhcmFtZXRlcnMucGFyZW50Um90YXRpb24KICAgIH07CiAgICBtZXNoRGF0YS5fY3VzdG9tQXR0cmlidXRlcyA9IGN1c3RvbUF0dHJpYnV0ZXM7CiAgICBjb25zdCByZXN1bHRzID0gewogICAgICBtZXNoRGF0YQogICAgfTsKICAgIHJldHVybiByZXN1bHRzOwogIH0KICBhc3luYyBmdW5jdGlvbiBpbml0V29ya2VyMihwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICBjb25zdCB3YXNtQ29uZmlnID0gcGFyYW1ldGVycy53ZWJBc3NlbWJseUNvbmZpZzsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQod2FzbUNvbmZpZykgJiYgZGVmaW5lZF9kZWZhdWx0KHdhc21Db25maWcud2FzbUJpbmFyeUZpbGUpKSB7CiAgICAgIGRyYWNvMiA9IGF3YWl0ICgwLCBpbXBvcnRfZHJhY29fZGVjb2Rlcl9ub2RlanMyLmRlZmF1bHQpKHdhc21Db25maWcpOwogICAgfSBlbHNlIHsKICAgICAgZHJhY28yID0gYXdhaXQgKDAsIGltcG9ydF9kcmFjb19kZWNvZGVyX25vZGVqczIuZGVmYXVsdCkoKTsKICAgIH0KICAgIHJldHVybiB0cnVlOwogIH0KICBmdW5jdGlvbiBkZWNvZGVJM1MocGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cykgewogICAgY29uc3Qgd2FzbUNvbmZpZyA9IHBhcmFtZXRlcnMud2ViQXNzZW1ibHlDb25maWc7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHdhc21Db25maWcpKSB7CiAgICAgIHJldHVybiBpbml0V29ya2VyMihwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKTsKICAgIH0KICAgIHJldHVybiBkZWNvZGVBbmRDcmVhdGVHbHRmKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpOwogIH0KICB2YXIgaW1wb3J0X2RyYWNvX2RlY29kZXJfbm9kZWpzMiwgZHJhY28yLCBjYWxjdWxhdGVGYWNlTm9ybWFsQSwgY2FsY3VsYXRlRmFjZU5vcm1hbEIsIGNhbGN1bGF0ZUZhY2VOb3JtYWxDLCBpc0VkZ2VTbW9vdGhBLCBpc0VkZ2VTbW9vdGhCLCBiaW5hcnlBdHRyaWJ1dGVEZWNvZGVycywgZGVjb2RlSTNTX2RlZmF1bHQ7CiAgdmFyIGluaXRfZGVjb2RlSTNTID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9kZWNvZGVJM1MuanMiKCkgewogICAgICBpbml0X2NyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXIoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfV2ViTWVyY2F0b3JQcm9qZWN0aW9uKCk7CiAgICAgIGluaXRfRWxsaXBzb2lkKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NvbG9yKCk7CiAgICAgIGluaXRfTWF0cml4MygpOwogICAgICBpbml0X01hdGgoKTsKICAgICAgaW1wb3J0X2RyYWNvX2RlY29kZXJfbm9kZWpzMiA9IF9fdG9FU00ocmVxdWlyZV9kcmFjb19kZWNvZGVyX25vZGVqcygpLCAxKTsKICAgICAgaW5pdF9zcmdiVG9MaW5lYXIoKTsKICAgICAgY2FsY3VsYXRlRmFjZU5vcm1hbEEgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIGNhbGN1bGF0ZUZhY2VOb3JtYWxCID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBjYWxjdWxhdGVGYWNlTm9ybWFsQyA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgaXNFZGdlU21vb3RoQSA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgaXNFZGdlU21vb3RoQiA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgYmluYXJ5QXR0cmlidXRlRGVjb2RlcnMgPSB7CiAgICAgICAgcG9zaXRpb246IGZ1bmN0aW9uKGRlY29kZWRHZW9tZXRyeSwgZGF0YSwgb2Zmc2V0KSB7CiAgICAgICAgICBjb25zdCBjb3VudCA9IGRlY29kZWRHZW9tZXRyeS52ZXJ0ZXhDb3VudCAqIDM7CiAgICAgICAgICBkZWNvZGVkR2VvbWV0cnkucG9zaXRpb25zID0gbmV3IEZsb2F0MzJBcnJheShkYXRhLCBvZmZzZXQsIGNvdW50KTsKICAgICAgICAgIG9mZnNldCArPSBjb3VudCAqIDQ7CiAgICAgICAgICByZXR1cm4gb2Zmc2V0OwogICAgICAgIH0sCiAgICAgICAgbm9ybWFsOiBmdW5jdGlvbihkZWNvZGVkR2VvbWV0cnksIGRhdGEsIG9mZnNldCkgewogICAgICAgICAgY29uc3QgY291bnQgPSBkZWNvZGVkR2VvbWV0cnkudmVydGV4Q291bnQgKiAzOwogICAgICAgICAgZGVjb2RlZEdlb21ldHJ5Lm5vcm1hbHMgPSBuZXcgRmxvYXQzMkFycmF5KGRhdGEsIG9mZnNldCwgY291bnQpOwogICAgICAgICAgb2Zmc2V0ICs9IGNvdW50ICogNDsKICAgICAgICAgIHJldHVybiBvZmZzZXQ7CiAgICAgICAgfSwKICAgICAgICB1djA6IGZ1bmN0aW9uKGRlY29kZWRHZW9tZXRyeSwgZGF0YSwgb2Zmc2V0KSB7CiAgICAgICAgICBjb25zdCBjb3VudCA9IGRlY29kZWRHZW9tZXRyeS52ZXJ0ZXhDb3VudCAqIDI7CiAgICAgICAgICBkZWNvZGVkR2VvbWV0cnkudXYwcyA9IG5ldyBGbG9hdDMyQXJyYXkoZGF0YSwgb2Zmc2V0LCBjb3VudCk7CiAgICAgICAgICBvZmZzZXQgKz0gY291bnQgKiA0OwogICAgICAgICAgcmV0dXJuIG9mZnNldDsKICAgICAgICB9LAogICAgICAgIGNvbG9yOiBmdW5jdGlvbihkZWNvZGVkR2VvbWV0cnksIGRhdGEsIG9mZnNldCkgewogICAgICAgICAgY29uc3QgY291bnQgPSBkZWNvZGVkR2VvbWV0cnkudmVydGV4Q291bnQgKiA0OwogICAgICAgICAgZGVjb2RlZEdlb21ldHJ5LmNvbG9ycyA9IG5ldyBVaW50OEFycmF5KGRhdGEsIG9mZnNldCwgY291bnQpOwogICAgICAgICAgb2Zmc2V0ICs9IGNvdW50OwogICAgICAgICAgcmV0dXJuIG9mZnNldDsKICAgICAgICB9LAogICAgICAgIGZlYXR1cmVJZDogZnVuY3Rpb24oZGVjb2RlZEdlb21ldHJ5LCBkYXRhLCBvZmZzZXQpIHsKICAgICAgICAgIGNvbnN0IGNvdW50ID0gZGVjb2RlZEdlb21ldHJ5LmZlYXR1cmVDb3VudDsKICAgICAgICAgIG9mZnNldCArPSBjb3VudCAqIDg7CiAgICAgICAgICByZXR1cm4gb2Zmc2V0OwogICAgICAgIH0sCiAgICAgICAgaWQ6IGZ1bmN0aW9uKGRlY29kZWRHZW9tZXRyeSwgZGF0YSwgb2Zmc2V0KSB7CiAgICAgICAgICBjb25zdCBjb3VudCA9IGRlY29kZWRHZW9tZXRyeS5mZWF0dXJlQ291bnQ7CiAgICAgICAgICBvZmZzZXQgKz0gY291bnQgKiA4OwogICAgICAgICAgcmV0dXJuIG9mZnNldDsKICAgICAgICB9LAogICAgICAgIGZhY2VSYW5nZTogZnVuY3Rpb24oZGVjb2RlZEdlb21ldHJ5LCBkYXRhLCBvZmZzZXQpIHsKICAgICAgICAgIGNvbnN0IGNvdW50ID0gZGVjb2RlZEdlb21ldHJ5LmZlYXR1cmVDb3VudCAqIDI7CiAgICAgICAgICBkZWNvZGVkR2VvbWV0cnkuZmFjZVJhbmdlID0gbmV3IFVpbnQzMkFycmF5KGRhdGEsIG9mZnNldCwgY291bnQpOwogICAgICAgICAgb2Zmc2V0ICs9IGNvdW50ICogNDsKICAgICAgICAgIHJldHVybiBvZmZzZXQ7CiAgICAgICAgfSwKICAgICAgICB1dlJlZ2lvbjogZnVuY3Rpb24oZGVjb2RlZEdlb21ldHJ5LCBkYXRhLCBvZmZzZXQpIHsKICAgICAgICAgIGNvbnN0IGNvdW50ID0gZGVjb2RlZEdlb21ldHJ5LnZlcnRleENvdW50ICogNDsKICAgICAgICAgIGRlY29kZWRHZW9tZXRyeVsidXYtcmVnaW9uIl0gPSBuZXcgVWludDE2QXJyYXkoZGF0YSwgb2Zmc2V0LCBjb3VudCk7CiAgICAgICAgICBvZmZzZXQgKz0gY291bnQgKiAyOwogICAgICAgICAgcmV0dXJuIG9mZnNldDsKICAgICAgICB9LAogICAgICAgIHJlZ2lvbjogZnVuY3Rpb24oZGVjb2RlZEdlb21ldHJ5LCBkYXRhLCBvZmZzZXQpIHsKICAgICAgICAgIGNvbnN0IGNvdW50ID0gZGVjb2RlZEdlb21ldHJ5LnZlcnRleENvdW50ICogNDsKICAgICAgICAgIGRlY29kZWRHZW9tZXRyeVsidXYtcmVnaW9uIl0gPSBuZXcgVWludDE2QXJyYXkoZGF0YSwgb2Zmc2V0LCBjb3VudCk7CiAgICAgICAgICBvZmZzZXQgKz0gY291bnQgKiAyOwogICAgICAgICAgcmV0dXJuIG9mZnNldDsKICAgICAgICB9CiAgICAgIH07CiAgICAgIGRlY29kZUkzU19kZWZhdWx0ID0gY3JlYXRlVGFza1Byb2Nlc3Nvcldvcmtlcl9kZWZhdWx0KGRlY29kZUkzUyk7CiAgICB9CiAgfSk7CgogIC8vIG5vZGVfbW9kdWxlcy9AY2VzaXVtL3dhc20tc3BsYXRzL3dhc21fc3BsYXRzLmpzCiAgZnVuY3Rpb24gZ2V0VWludDhBcnJheU1lbW9yeTAoKSB7CiAgICBpZiAoY2FjaGVkVWludDhBcnJheU1lbW9yeTAgPT09IG51bGwgfHwgY2FjaGVkVWludDhBcnJheU1lbW9yeTAuYnl0ZUxlbmd0aCA9PT0gMCkgewogICAgICBjYWNoZWRVaW50OEFycmF5TWVtb3J5MCA9IG5ldyBVaW50OEFycmF5KHdhc20ubWVtb3J5LmJ1ZmZlcik7CiAgICB9CiAgICByZXR1cm4gY2FjaGVkVWludDhBcnJheU1lbW9yeTA7CiAgfQogIGZ1bmN0aW9uIGdldFN0cmluZ0Zyb21XYXNtMChwdHIsIGxlbikgewogICAgcHRyID0gcHRyID4+PiAwOwogICAgcmV0dXJuIGNhY2hlZFRleHREZWNvZGVyLmRlY29kZShnZXRVaW50OEFycmF5TWVtb3J5MCgpLnN1YmFycmF5KHB0ciwgcHRyICsgbGVuKSk7CiAgfQogIGZ1bmN0aW9uIGdldFVpbnQzMkFycmF5TWVtb3J5MCgpIHsKICAgIGlmIChjYWNoZWRVaW50MzJBcnJheU1lbW9yeTAgPT09IG51bGwgfHwgY2FjaGVkVWludDMyQXJyYXlNZW1vcnkwLmJ5dGVMZW5ndGggPT09IDApIHsKICAgICAgY2FjaGVkVWludDMyQXJyYXlNZW1vcnkwID0gbmV3IFVpbnQzMkFycmF5KHdhc20ubWVtb3J5LmJ1ZmZlcik7CiAgICB9CiAgICByZXR1cm4gY2FjaGVkVWludDMyQXJyYXlNZW1vcnkwOwogIH0KICBmdW5jdGlvbiBnZXRBcnJheVUzMkZyb21XYXNtMChwdHIsIGxlbikgewogICAgcHRyID0gcHRyID4+PiAwOwogICAgcmV0dXJuIGdldFVpbnQzMkFycmF5TWVtb3J5MCgpLnN1YmFycmF5KHB0ciAvIDQsIHB0ciAvIDQgKyBsZW4pOwogIH0KICBmdW5jdGlvbiBwYXNzQXJyYXkzMlRvV2FzbTAoYXJnLCBtYWxsb2MpIHsKICAgIGNvbnN0IHB0ciA9IG1hbGxvYyhhcmcubGVuZ3RoICogNCwgNCkgPj4+IDA7CiAgICBnZXRVaW50MzJBcnJheU1lbW9yeTAoKS5zZXQoYXJnLCBwdHIgLyA0KTsKICAgIFdBU01fVkVDVE9SX0xFTiA9IGFyZy5sZW5ndGg7CiAgICByZXR1cm4gcHRyOwogIH0KICBmdW5jdGlvbiB0YWtlRnJvbUV4dGVybnJlZlRhYmxlMChpZHgpIHsKICAgIGNvbnN0IHZhbHVlID0gd2FzbS5fX3diaW5kZ2VuX2V4cG9ydF8wLmdldChpZHgpOwogICAgd2FzbS5fX2V4dGVybnJlZl90YWJsZV9kZWFsbG9jKGlkeCk7CiAgICByZXR1cm4gdmFsdWU7CiAgfQogIGZ1bmN0aW9uIGdlbmVyYXRlX3NwbGF0X3RleHR1cmUocG9zaXRpb25zLCBzY2FsZXMsIHJvdGF0aW9ucywgY29sb3JzLCBjb3VudCkgewogICAgY29uc3QgcmV0ID0gd2FzbS5nZW5lcmF0ZV9zcGxhdF90ZXh0dXJlKHBvc2l0aW9ucywgc2NhbGVzLCByb3RhdGlvbnMsIGNvbG9ycywgY291bnQpOwogICAgaWYgKHJldFsyXSkgewogICAgICB0aHJvdyB0YWtlRnJvbUV4dGVybnJlZlRhYmxlMChyZXRbMV0pOwogICAgfQogICAgcmV0dXJuIFRleHR1cmVEYXRhLl9fd3JhcChyZXRbMF0pOwogIH0KICBmdW5jdGlvbiByYWRpeF9zb3J0X2dhdXNzaWFuc19pbmRleGVzKHBvc2l0aW9uc19hcnIsIG1vZGVsX3ZpZXdfYXJyLCBjb3VudCkgewogICAgY29uc3QgcmV0ID0gd2FzbS5yYWRpeF9zb3J0X2dhdXNzaWFuc19pbmRleGVzKHBvc2l0aW9uc19hcnIsIG1vZGVsX3ZpZXdfYXJyLCBjb3VudCk7CiAgICBpZiAocmV0WzJdKSB7CiAgICAgIHRocm93IHRha2VGcm9tRXh0ZXJucmVmVGFibGUwKHJldFsxXSk7CiAgICB9CiAgICByZXR1cm4gdGFrZUZyb21FeHRlcm5yZWZUYWJsZTAocmV0WzBdKTsKICB9CiAgYXN5bmMgZnVuY3Rpb24gX193YmdfbG9hZChtb2R1bGUsIGltcG9ydHMpIHsKICAgIGlmICh0eXBlb2YgUmVzcG9uc2UgPT09ICJmdW5jdGlvbiIgJiYgbW9kdWxlIGluc3RhbmNlb2YgUmVzcG9uc2UpIHsKICAgICAgaWYgKHR5cGVvZiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZyA9PT0gImZ1bmN0aW9uIikgewogICAgICAgIHRyeSB7CiAgICAgICAgICByZXR1cm4gYXdhaXQgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGVTdHJlYW1pbmcobW9kdWxlLCBpbXBvcnRzKTsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICBpZiAobW9kdWxlLmhlYWRlcnMuZ2V0KCJDb250ZW50LVR5cGUiKSAhPSAiYXBwbGljYXRpb24vd2FzbSIpIHsKICAgICAgICAgICAgY29uc29sZS53YXJuKCJgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGVTdHJlYW1pbmdgIGZhaWxlZCBiZWNhdXNlIHlvdXIgc2VydmVyIGRvZXMgbm90IHNlcnZlIFdhc20gd2l0aCBgYXBwbGljYXRpb24vd2FzbWAgTUlNRSB0eXBlLiBGYWxsaW5nIGJhY2sgdG8gYFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlYCB3aGljaCBpcyBzbG93ZXIuIE9yaWdpbmFsIGVycm9yOlxuIiwgZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB0aHJvdyBlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBieXRlcyA9IGF3YWl0IG1vZHVsZS5hcnJheUJ1ZmZlcigpOwogICAgICByZXR1cm4gYXdhaXQgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGUoYnl0ZXMsIGltcG9ydHMpOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZShtb2R1bGUsIGltcG9ydHMpOwogICAgICBpZiAoaW5zdGFuY2UgaW5zdGFuY2VvZiBXZWJBc3NlbWJseS5JbnN0YW5jZSkgewogICAgICAgIHJldHVybiB7IGluc3RhbmNlLCBtb2R1bGUgfTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gaW5zdGFuY2U7CiAgICAgIH0KICAgIH0KICB9CiAgZnVuY3Rpb24gX193YmdfZ2V0X2ltcG9ydHMoKSB7CiAgICBjb25zdCBpbXBvcnRzID0ge307CiAgICBpbXBvcnRzLndiZyA9IHt9OwogICAgaW1wb3J0cy53YmcuX193YmdfYnVmZmVyXzYwOWNjM2VlZTUxZWQxNTggPSBmdW5jdGlvbihhcmcwKSB7CiAgICAgIGNvbnN0IHJldCA9IGFyZzAuYnVmZmVyOwogICAgICByZXR1cm4gcmV0OwogICAgfTsKICAgIGltcG9ydHMud2JnLl9fd2JnX2xlbmd0aF8zYjRmMDIyMTg4YWU4ZGI2ID0gZnVuY3Rpb24oYXJnMCkgewogICAgICBjb25zdCByZXQgPSBhcmcwLmxlbmd0aDsKICAgICAgcmV0dXJuIHJldDsKICAgIH07CiAgICBpbXBvcnRzLndiZy5fX3diZ19sZW5ndGhfYTQ0NjE5M2RjMjJjMTJmOCA9IGZ1bmN0aW9uKGFyZzApIHsKICAgICAgY29uc3QgcmV0ID0gYXJnMC5sZW5ndGg7CiAgICAgIHJldHVybiByZXQ7CiAgICB9OwogICAgaW1wb3J0cy53YmcuX193YmdfbmV3Xzc4MGFiZWU1YzE3MzlmZDcgPSBmdW5jdGlvbihhcmcwKSB7CiAgICAgIGNvbnN0IHJldCA9IG5ldyBGbG9hdDMyQXJyYXkoYXJnMCk7CiAgICAgIHJldHVybiByZXQ7CiAgICB9OwogICAgaW1wb3J0cy53YmcuX193YmdfbmV3X2ExMjAwMmE3ZjkxYzc1YmUgPSBmdW5jdGlvbihhcmcwKSB7CiAgICAgIGNvbnN0IHJldCA9IG5ldyBVaW50OEFycmF5KGFyZzApOwogICAgICByZXR1cm4gcmV0OwogICAgfTsKICAgIGltcG9ydHMud2JnLl9fd2JnX25ld19lM2IzMjFkY2ZlZjg5ZmM3ID0gZnVuY3Rpb24oYXJnMCkgewogICAgICBjb25zdCByZXQgPSBuZXcgVWludDMyQXJyYXkoYXJnMCk7CiAgICAgIHJldHVybiByZXQ7CiAgICB9OwogICAgaW1wb3J0cy53YmcuX193YmdfbmV3d2l0aGJ5dGVvZmZzZXRhbmRsZW5ndGhfZjFkZWFkNDRkMWZjNzIxMiA9IGZ1bmN0aW9uKGFyZzAsIGFyZzEsIGFyZzIpIHsKICAgICAgY29uc3QgcmV0ID0gbmV3IFVpbnQzMkFycmF5KGFyZzAsIGFyZzEgPj4+IDAsIGFyZzIgPj4+IDApOwogICAgICByZXR1cm4gcmV0OwogICAgfTsKICAgIGltcG9ydHMud2JnLl9fd2JnX3NldF8xMGJhZDliZWUwZTljNThiID0gZnVuY3Rpb24oYXJnMCwgYXJnMSwgYXJnMikgewogICAgICBhcmcwLnNldChhcmcxLCBhcmcyID4+PiAwKTsKICAgIH07CiAgICBpbXBvcnRzLndiZy5fX3diZ19zZXRfNjU1OTViZGQ4NjhiMzAwOSA9IGZ1bmN0aW9uKGFyZzAsIGFyZzEsIGFyZzIpIHsKICAgICAgYXJnMC5zZXQoYXJnMSwgYXJnMiA+Pj4gMCk7CiAgICB9OwogICAgaW1wb3J0cy53YmcuX193YmluZGdlbl9pbml0X2V4dGVybnJlZl90YWJsZSA9IGZ1bmN0aW9uKCkgewogICAgICBjb25zdCB0YWJsZSA9IHdhc20uX193YmluZGdlbl9leHBvcnRfMDsKICAgICAgY29uc3Qgb2Zmc2V0ID0gdGFibGUuZ3Jvdyg0KTsKICAgICAgdGFibGUuc2V0KDAsIHZvaWQgMCk7CiAgICAgIHRhYmxlLnNldChvZmZzZXQgKyAwLCB2b2lkIDApOwogICAgICB0YWJsZS5zZXQob2Zmc2V0ICsgMSwgbnVsbCk7CiAgICAgIHRhYmxlLnNldChvZmZzZXQgKyAyLCB0cnVlKTsKICAgICAgdGFibGUuc2V0KG9mZnNldCArIDMsIGZhbHNlKTsKICAgICAgOwogICAgfTsKICAgIGltcG9ydHMud2JnLl9fd2JpbmRnZW5fbWVtb3J5ID0gZnVuY3Rpb24oKSB7CiAgICAgIGNvbnN0IHJldCA9IHdhc20ubWVtb3J5OwogICAgICByZXR1cm4gcmV0OwogICAgfTsKICAgIGltcG9ydHMud2JnLl9fd2JpbmRnZW5fc3RyaW5nX25ldyA9IGZ1bmN0aW9uKGFyZzAsIGFyZzEpIHsKICAgICAgY29uc3QgcmV0ID0gZ2V0U3RyaW5nRnJvbVdhc20wKGFyZzAsIGFyZzEpOwogICAgICByZXR1cm4gcmV0OwogICAgfTsKICAgIGltcG9ydHMud2JnLl9fd2JpbmRnZW5fdGhyb3cgPSBmdW5jdGlvbihhcmcwLCBhcmcxKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcihnZXRTdHJpbmdGcm9tV2FzbTAoYXJnMCwgYXJnMSkpOwogICAgfTsKICAgIHJldHVybiBpbXBvcnRzOwogIH0KICBmdW5jdGlvbiBfX3diZ19pbml0X21lbW9yeShpbXBvcnRzLCBtZW1vcnkpIHsKICB9CiAgZnVuY3Rpb24gX193YmdfZmluYWxpemVfaW5pdChpbnN0YW5jZSwgbW9kdWxlKSB7CiAgICB3YXNtID0gaW5zdGFuY2UuZXhwb3J0czsKICAgIF9fd2JnX2luaXQuX193YmluZGdlbl93YXNtX21vZHVsZSA9IG1vZHVsZTsKICAgIGNhY2hlZFVpbnQzMkFycmF5TWVtb3J5MCA9IG51bGw7CiAgICBjYWNoZWRVaW50OEFycmF5TWVtb3J5MCA9IG51bGw7CiAgICB3YXNtLl9fd2JpbmRnZW5fc3RhcnQoKTsKICAgIHJldHVybiB3YXNtOwogIH0KICBmdW5jdGlvbiBpbml0U3luYyhtb2R1bGUpIHsKICAgIGlmICh3YXNtICE9PSB2b2lkIDApIHJldHVybiB3YXNtOwogICAgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICJ1bmRlZmluZWQiKSB7CiAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YobW9kdWxlKSA9PT0gT2JqZWN0LnByb3RvdHlwZSkgewogICAgICAgICh7IG1vZHVsZSB9ID0gbW9kdWxlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zb2xlLndhcm4oInVzaW5nIGRlcHJlY2F0ZWQgcGFyYW1ldGVycyBmb3IgYGluaXRTeW5jKClgOyBwYXNzIGEgc2luZ2xlIG9iamVjdCBpbnN0ZWFkIik7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGltcG9ydHMgPSBfX3diZ19nZXRfaW1wb3J0cygpOwogICAgX193YmdfaW5pdF9tZW1vcnkoaW1wb3J0cyk7CiAgICBpZiAoIShtb2R1bGUgaW5zdGFuY2VvZiBXZWJBc3NlbWJseS5Nb2R1bGUpKSB7CiAgICAgIG1vZHVsZSA9IG5ldyBXZWJBc3NlbWJseS5Nb2R1bGUobW9kdWxlKTsKICAgIH0KICAgIGNvbnN0IGluc3RhbmNlID0gbmV3IFdlYkFzc2VtYmx5Lkluc3RhbmNlKG1vZHVsZSwgaW1wb3J0cyk7CiAgICByZXR1cm4gX193YmdfZmluYWxpemVfaW5pdChpbnN0YW5jZSwgbW9kdWxlKTsKICB9CiAgYXN5bmMgZnVuY3Rpb24gX193YmdfaW5pdChtb2R1bGVfb3JfcGF0aCkgewogICAgaWYgKHdhc20gIT09IHZvaWQgMCkgcmV0dXJuIHdhc207CiAgICBpZiAodHlwZW9mIG1vZHVsZV9vcl9wYXRoICE9PSAidW5kZWZpbmVkIikgewogICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKG1vZHVsZV9vcl9wYXRoKSA9PT0gT2JqZWN0LnByb3RvdHlwZSkgewogICAgICAgICh7IG1vZHVsZV9vcl9wYXRoIH0gPSBtb2R1bGVfb3JfcGF0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc29sZS53YXJuKCJ1c2luZyBkZXByZWNhdGVkIHBhcmFtZXRlcnMgZm9yIHRoZSBpbml0aWFsaXphdGlvbiBmdW5jdGlvbjsgcGFzcyBhIHNpbmdsZSBvYmplY3QgaW5zdGVhZCIpOwogICAgICB9CiAgICB9CiAgICBpZiAodHlwZW9mIG1vZHVsZV9vcl9wYXRoID09PSAidW5kZWZpbmVkIikgewogICAgICBtb2R1bGVfb3JfcGF0aCA9IG5ldyBVUkwoIndhc21fc3BsYXRzX2JnLndhc20iLCBpbXBvcnRfbWV0YTIudXJsKTsKICAgIH0KICAgIGNvbnN0IGltcG9ydHMgPSBfX3diZ19nZXRfaW1wb3J0cygpOwogICAgaWYgKHR5cGVvZiBtb2R1bGVfb3JfcGF0aCA9PT0gInN0cmluZyIgfHwgdHlwZW9mIFJlcXVlc3QgPT09ICJmdW5jdGlvbiIgJiYgbW9kdWxlX29yX3BhdGggaW5zdGFuY2VvZiBSZXF1ZXN0IHx8IHR5cGVvZiBVUkwgPT09ICJmdW5jdGlvbiIgJiYgbW9kdWxlX29yX3BhdGggaW5zdGFuY2VvZiBVUkwpIHsKICAgICAgbW9kdWxlX29yX3BhdGggPSBmZXRjaChtb2R1bGVfb3JfcGF0aCk7CiAgICB9CiAgICBfX3diZ19pbml0X21lbW9yeShpbXBvcnRzKTsKICAgIGNvbnN0IHsgaW5zdGFuY2UsIG1vZHVsZSB9ID0gYXdhaXQgX193YmdfbG9hZChhd2FpdCBtb2R1bGVfb3JfcGF0aCwgaW1wb3J0cyk7CiAgICByZXR1cm4gX193YmdfZmluYWxpemVfaW5pdChpbnN0YW5jZSwgbW9kdWxlKTsKICB9CiAgdmFyIGltcG9ydF9tZXRhMiwgd2FzbSwgY2FjaGVkVGV4dERlY29kZXIsIGNhY2hlZFVpbnQ4QXJyYXlNZW1vcnkwLCBjYWNoZWRVaW50MzJBcnJheU1lbW9yeTAsIFdBU01fVkVDVE9SX0xFTiwgVGV4dHVyZURhdGFGaW5hbGl6YXRpb24sIFRleHR1cmVEYXRhOwogIHZhciBpbml0X3dhc21fc3BsYXRzID0gX19lc20oewogICAgIm5vZGVfbW9kdWxlcy9AY2VzaXVtL3dhc20tc3BsYXRzL3dhc21fc3BsYXRzLmpzIigpIHsKICAgICAgaW1wb3J0X21ldGEyID0ge307CiAgICAgIGNhY2hlZFRleHREZWNvZGVyID0gdHlwZW9mIFRleHREZWNvZGVyICE9PSAidW5kZWZpbmVkIiA/IG5ldyBUZXh0RGVjb2RlcigidXRmLTgiLCB7IGlnbm9yZUJPTTogdHJ1ZSwgZmF0YWw6IHRydWUgfSkgOiB7IGRlY29kZTogKCkgPT4gewogICAgICAgIHRocm93IEVycm9yKCJUZXh0RGVjb2RlciBub3QgYXZhaWxhYmxlIik7CiAgICAgIH0gfTsKICAgICAgaWYgKHR5cGVvZiBUZXh0RGVjb2RlciAhPT0gInVuZGVmaW5lZCIpIHsKICAgICAgICBjYWNoZWRUZXh0RGVjb2Rlci5kZWNvZGUoKTsKICAgICAgfQogICAgICBjYWNoZWRVaW50OEFycmF5TWVtb3J5MCA9IG51bGw7CiAgICAgIGNhY2hlZFVpbnQzMkFycmF5TWVtb3J5MCA9IG51bGw7CiAgICAgIFdBU01fVkVDVE9SX0xFTiA9IDA7CiAgICAgIFRleHR1cmVEYXRhRmluYWxpemF0aW9uID0gdHlwZW9mIEZpbmFsaXphdGlvblJlZ2lzdHJ5ID09PSAidW5kZWZpbmVkIiA/IHsgcmVnaXN0ZXI6ICgpID0+IHsKICAgICAgfSwgdW5yZWdpc3RlcjogKCkgPT4gewogICAgICB9IH0gOiBuZXcgRmluYWxpemF0aW9uUmVnaXN0cnkoKHB0cikgPT4gd2FzbS5fX3diZ190ZXh0dXJlZGF0YV9mcmVlKHB0ciA+Pj4gMCwgMSkpOwogICAgICBUZXh0dXJlRGF0YSA9IGNsYXNzIF9UZXh0dXJlRGF0YSB7CiAgICAgICAgc3RhdGljIF9fd3JhcChwdHIpIHsKICAgICAgICAgIHB0ciA9IHB0ciA+Pj4gMDsKICAgICAgICAgIGNvbnN0IG9iaiA9IE9iamVjdC5jcmVhdGUoX1RleHR1cmVEYXRhLnByb3RvdHlwZSk7CiAgICAgICAgICBvYmouX193YmdfcHRyID0gcHRyOwogICAgICAgICAgVGV4dHVyZURhdGFGaW5hbGl6YXRpb24ucmVnaXN0ZXIob2JqLCBvYmouX193YmdfcHRyLCBvYmopOwogICAgICAgICAgcmV0dXJuIG9iajsKICAgICAgICB9CiAgICAgICAgX19kZXN0cm95X2ludG9fcmF3KCkgewogICAgICAgICAgY29uc3QgcHRyID0gdGhpcy5fX3diZ19wdHI7CiAgICAgICAgICB0aGlzLl9fd2JnX3B0ciA9IDA7CiAgICAgICAgICBUZXh0dXJlRGF0YUZpbmFsaXphdGlvbi51bnJlZ2lzdGVyKHRoaXMpOwogICAgICAgICAgcmV0dXJuIHB0cjsKICAgICAgICB9CiAgICAgICAgZnJlZSgpIHsKICAgICAgICAgIGNvbnN0IHB0ciA9IHRoaXMuX19kZXN0cm95X2ludG9fcmF3KCk7CiAgICAgICAgICB3YXNtLl9fd2JnX3RleHR1cmVkYXRhX2ZyZWUocHRyLCAwKTsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0dGVyIGZvciB0aGUgdW5kZXJseWluZyB0ZXh0dXJlIGRhdGEuIEFsd2F5cyByZXR1cm5zIGEgY29weS4KICAgICAgICAgKiBAcmV0dXJucyB7VWludDMyQXJyYXl9CiAgICAgICAgICovCiAgICAgICAgZ2V0IGRhdGEoKSB7CiAgICAgICAgICBjb25zdCByZXQgPSB3YXNtLnRleHR1cmVkYXRhX2RhdGEodGhpcy5fX3diZ19wdHIpOwogICAgICAgICAgdmFyIHYxMiA9IGdldEFycmF5VTMyRnJvbVdhc20wKHJldFswXSwgcmV0WzFdKS5zbGljZSgpOwogICAgICAgICAgd2FzbS5fX3diaW5kZ2VuX2ZyZWUocmV0WzBdLCByZXRbMV0gKiA0LCA0KTsKICAgICAgICAgIHJldHVybiB2MTI7CiAgICAgICAgfQogICAgICAgIC8qKgogICAgICAgICAqIEdldHRlciBmb3IgdGhlIHdpZHRoIG9mIHRoZSB0ZXh0dXJlIGluIHBpeGVscy4KICAgICAgICAgKiBAcmV0dXJucyB7bnVtYmVyfQogICAgICAgICAqLwogICAgICAgIGdldCB3aWR0aCgpIHsKICAgICAgICAgIGNvbnN0IHJldCA9IHdhc20udGV4dHVyZWRhdGFfd2lkdGgodGhpcy5fX3diZ19wdHIpOwogICAgICAgICAgcmV0dXJuIHJldCA+Pj4gMDsKICAgICAgICB9CiAgICAgICAgLyoqCiAgICAgICAgICogR2V0dGVyIGZvciB0aGUgaGVpZ2h0IG9mIHRoZSB0ZXh0dXJlIGluIHBpeGVscy4KICAgICAgICAgKiBAcmV0dXJucyB7bnVtYmVyfQogICAgICAgICAqLwogICAgICAgIGdldCBoZWlnaHQoKSB7CiAgICAgICAgICBjb25zdCByZXQgPSB3YXNtLnRleHR1cmVkYXRhX2hlaWdodCh0aGlzLl9fd2JnX3B0cik7CiAgICAgICAgICByZXR1cm4gcmV0ID4+PiAwOwogICAgICAgIH0KICAgICAgICAvKioKICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IHRleHR1cmUgZGF0YSBvYmplY3Qgd2l0aCB0aGUgdW5kZXJseWluZyBkYXRhLCB3aWR0aCwgYW5kIGhlaWdodC4KICAgICAgICAgKiBAcGFyYW0ge1VpbnQzMkFycmF5fSBkYXRhCiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoCiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodAogICAgICAgICAqIEByZXR1cm5zIHtUZXh0dXJlRGF0YX0KICAgICAgICAgKi8KICAgICAgICBzdGF0aWMgbmV3KGRhdGEsIHdpZHRoLCBoZWlnaHQpIHsKICAgICAgICAgIGNvbnN0IHB0cjAgPSBwYXNzQXJyYXkzMlRvV2FzbTAoZGF0YSwgd2FzbS5fX3diaW5kZ2VuX21hbGxvYyk7CiAgICAgICAgICBjb25zdCBsZW4wID0gV0FTTV9WRUNUT1JfTEVOOwogICAgICAgICAgY29uc3QgcmV0ID0gd2FzbS50ZXh0dXJlZGF0YV9uZXcocHRyMCwgbGVuMCwgd2lkdGgsIGhlaWdodCk7CiAgICAgICAgICByZXR1cm4gX1RleHR1cmVEYXRhLl9fd3JhcChyZXQpOwogICAgICAgIH0KICAgICAgfTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2dhdXNzaWFuU3BsYXRTb3J0ZXIuanMKICB2YXIgZ2F1c3NpYW5TcGxhdFNvcnRlcl9leHBvcnRzID0ge307CiAgX19leHBvcnQoZ2F1c3NpYW5TcGxhdFNvcnRlcl9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBnYXVzc2lhblNwbGF0U29ydGVyX2RlZmF1bHQKICB9KTsKICBhc3luYyBmdW5jdGlvbiBpbml0V29ya2VyMyhwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICBjb25zdCB3YXNtQ29uZmlnID0gcGFyYW1ldGVycy53ZWJBc3NlbWJseUNvbmZpZzsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQod2FzbUNvbmZpZykgJiYgZGVmaW5lZF9kZWZhdWx0KHdhc21Db25maWcud2FzbUJpbmFyeSkpIHsKICAgICAgaW5pdFN5bmMoeyBtb2R1bGU6IHdhc21Db25maWcud2FzbUJpbmFyeSB9KTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgfQogIGZ1bmN0aW9uIGdlbmVyYXRlR2F1c3NpYW5Tb3J0V29ya2VyKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIGNvbnN0IHdhc21Db25maWcgPSBwYXJhbWV0ZXJzLndlYkFzc2VtYmx5Q29uZmlnOwogICAgaWYgKGRlZmluZWRfZGVmYXVsdCh3YXNtQ29uZmlnKSkgewogICAgICByZXR1cm4gaW5pdFdvcmtlcjMocGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cyk7CiAgICB9CiAgICBjb25zdCB7IHByaW1pdGl2ZSwgc29ydFR5cGUgfSA9IHBhcmFtZXRlcnM7CiAgICBpZiAoc29ydFR5cGUgPT09ICJJbmRleCIpIHsKICAgICAgcmV0dXJuIHJhZGl4X3NvcnRfZ2F1c3NpYW5zX2luZGV4ZXMoCiAgICAgICAgcHJpbWl0aXZlLnBvc2l0aW9ucywKICAgICAgICBwcmltaXRpdmUubW9kZWxWaWV3LAogICAgICAgIHByaW1pdGl2ZS5jb3VudAogICAgICApOwogICAgfQogIH0KICB2YXIgZ2F1c3NpYW5TcGxhdFNvcnRlcl9kZWZhdWx0OwogIHZhciBpbml0X2dhdXNzaWFuU3BsYXRTb3J0ZXIgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2dhdXNzaWFuU3BsYXRTb3J0ZXIuanMiKCkgewogICAgICBpbml0X2NyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXIoKTsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfd2FzbV9zcGxhdHMoKTsKICAgICAgZ2F1c3NpYW5TcGxhdFNvcnRlcl9kZWZhdWx0ID0gY3JlYXRlVGFza1Byb2Nlc3Nvcldvcmtlcl9kZWZhdWx0KGdlbmVyYXRlR2F1c3NpYW5Tb3J0V29ya2VyKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2dhdXNzaWFuU3BsYXRUZXh0dXJlR2VuZXJhdG9yLmpzCiAgdmFyIGdhdXNzaWFuU3BsYXRUZXh0dXJlR2VuZXJhdG9yX2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChnYXVzc2lhblNwbGF0VGV4dHVyZUdlbmVyYXRvcl9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBnYXVzc2lhblNwbGF0VGV4dHVyZUdlbmVyYXRvcl9kZWZhdWx0CiAgfSk7CiAgYXN5bmMgZnVuY3Rpb24gaW5pdFdvcmtlcjQocGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cykgewogICAgY29uc3Qgd2FzbUNvbmZpZyA9IHBhcmFtZXRlcnMud2ViQXNzZW1ibHlDb25maWc7CiAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHdhc21Db25maWcpICYmIGRlZmluZWRfZGVmYXVsdCh3YXNtQ29uZmlnLndhc21CaW5hcnkpKSB7CiAgICAgIGluaXRTeW5jKHsgbW9kdWxlOiB3YXNtQ29uZmlnLndhc21CaW5hcnkgfSk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICBhc3luYyBmdW5jdGlvbiBnZW5lcmF0ZVNwbGF0VGV4dHVyZVdvcmtlcihwYXJhbWV0ZXJzLCB0cmFuc2ZlcmFibGVPYmplY3RzKSB7CiAgICBjb25zdCB3YXNtQ29uZmlnID0gcGFyYW1ldGVycy53ZWJBc3NlbWJseUNvbmZpZzsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQod2FzbUNvbmZpZykpIHsKICAgICAgcmV0dXJuIGluaXRXb3JrZXI0KHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpOwogICAgfQogICAgY29uc3QgeyBhdHRyaWJ1dGVzLCBjb3VudCB9ID0gcGFyYW1ldGVyczsKICAgIGNvbnN0IHJlc3VsdCA9IGdlbmVyYXRlX3NwbGF0X3RleHR1cmUoCiAgICAgIGF0dHJpYnV0ZXMucG9zaXRpb25zLAogICAgICBhdHRyaWJ1dGVzLnNjYWxlcywKICAgICAgYXR0cmlidXRlcy5yb3RhdGlvbnMsCiAgICAgIGF0dHJpYnV0ZXMuY29sb3JzLAogICAgICBjb3VudAogICAgKTsKICAgIHJldHVybiB7CiAgICAgIGRhdGE6IHJlc3VsdC5kYXRhLAogICAgICB3aWR0aDogcmVzdWx0LndpZHRoLAogICAgICBoZWlnaHQ6IHJlc3VsdC5oZWlnaHQKICAgIH07CiAgfQogIHZhciBnYXVzc2lhblNwbGF0VGV4dHVyZUdlbmVyYXRvcl9kZWZhdWx0OwogIHZhciBpbml0X2dhdXNzaWFuU3BsYXRUZXh0dXJlR2VuZXJhdG9yID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9nYXVzc2lhblNwbGF0VGV4dHVyZUdlbmVyYXRvci5qcyIoKSB7CiAgICAgIGluaXRfY3JlYXRlVGFza1Byb2Nlc3NvcldvcmtlcigpOwogICAgICBpbml0X2RlZmluZWQoKTsKICAgICAgaW5pdF93YXNtX3NwbGF0cygpOwogICAgICBnYXVzc2lhblNwbGF0VGV4dHVyZUdlbmVyYXRvcl9kZWZhdWx0ID0gY3JlYXRlVGFza1Byb2Nlc3Nvcldvcmtlcl9kZWZhdWx0KGdlbmVyYXRlU3BsYXRUZXh0dXJlV29ya2VyKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9SZW5kZXJlci9QaXhlbERhdGF0eXBlLmpzCiAgdmFyIFBpeGVsRGF0YXR5cGUsIFBpeGVsRGF0YXR5cGVfZGVmYXVsdDsKICB2YXIgaW5pdF9QaXhlbERhdGF0eXBlID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvUmVuZGVyZXIvUGl4ZWxEYXRhdHlwZS5qcyIoKSB7CiAgICAgIGluaXRfV2ViR0xDb25zdGFudHMoKTsKICAgICAgUGl4ZWxEYXRhdHlwZSA9IHsKICAgICAgICBVTlNJR05FRF9CWVRFOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlVOU0lHTkVEX0JZVEUsCiAgICAgICAgVU5TSUdORURfU0hPUlQ6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuVU5TSUdORURfU0hPUlQsCiAgICAgICAgVU5TSUdORURfSU5UOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlVOU0lHTkVEX0lOVCwKICAgICAgICBGTE9BVDogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5GTE9BVCwKICAgICAgICBIQUxGX0ZMT0FUOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkhBTEZfRkxPQVRfT0VTLAogICAgICAgIFVOU0lHTkVEX0lOVF8yNF84OiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlVOU0lHTkVEX0lOVF8yNF84LAogICAgICAgIFVOU0lHTkVEX1NIT1JUXzRfNF80XzQ6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuVU5TSUdORURfU0hPUlRfNF80XzRfNCwKICAgICAgICBVTlNJR05FRF9TSE9SVF81XzVfNV8xOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlVOU0lHTkVEX1NIT1JUXzVfNV81XzEsCiAgICAgICAgVU5TSUdORURfU0hPUlRfNV82XzU6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuVU5TSUdORURfU0hPUlRfNV82XzUKICAgICAgfTsKICAgICAgUGl4ZWxEYXRhdHlwZS50b1dlYkdMQ29uc3RhbnQgPSBmdW5jdGlvbihwaXhlbERhdGF0eXBlLCBjb250ZXh0KSB7CiAgICAgICAgc3dpdGNoIChwaXhlbERhdGF0eXBlKSB7CiAgICAgICAgICBjYXNlIFBpeGVsRGF0YXR5cGUuVU5TSUdORURfQllURToKICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuVU5TSUdORURfQllURTsKICAgICAgICAgIGNhc2UgUGl4ZWxEYXRhdHlwZS5VTlNJR05FRF9TSE9SVDoKICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuVU5TSUdORURfU0hPUlQ7CiAgICAgICAgICBjYXNlIFBpeGVsRGF0YXR5cGUuVU5TSUdORURfSU5UOgogICAgICAgICAgICByZXR1cm4gV2ViR0xDb25zdGFudHNfZGVmYXVsdC5VTlNJR05FRF9JTlQ7CiAgICAgICAgICBjYXNlIFBpeGVsRGF0YXR5cGUuRkxPQVQ6CiAgICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkZMT0FUOwogICAgICAgICAgY2FzZSBQaXhlbERhdGF0eXBlLkhBTEZfRkxPQVQ6CiAgICAgICAgICAgIHJldHVybiBjb250ZXh0LndlYmdsMiA/IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuSEFMRl9GTE9BVCA6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuSEFMRl9GTE9BVF9PRVM7CiAgICAgICAgICBjYXNlIFBpeGVsRGF0YXR5cGUuVU5TSUdORURfSU5UXzI0Xzg6CiAgICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlVOU0lHTkVEX0lOVF8yNF84OwogICAgICAgICAgY2FzZSBQaXhlbERhdGF0eXBlLlVOU0lHTkVEX1NIT1JUXzRfNF80XzQ6CiAgICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlVOU0lHTkVEX1NIT1JUXzRfNF80XzQ7CiAgICAgICAgICBjYXNlIFBpeGVsRGF0YXR5cGUuVU5TSUdORURfU0hPUlRfNV81XzVfMToKICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuVU5TSUdORURfU0hPUlRfNV81XzVfMTsKICAgICAgICAgIGNhc2UgUGl4ZWxEYXRhdHlwZS5VTlNJR05FRF9TSE9SVF81XzZfNToKICAgICAgICAgICAgcmV0dXJuIFBpeGVsRGF0YXR5cGUuVU5TSUdORURfU0hPUlRfNV82XzU7CiAgICAgICAgfQogICAgICB9OwogICAgICBQaXhlbERhdGF0eXBlLmlzUGFja2VkID0gZnVuY3Rpb24ocGl4ZWxEYXRhdHlwZSkgewogICAgICAgIHJldHVybiBwaXhlbERhdGF0eXBlID09PSBQaXhlbERhdGF0eXBlLlVOU0lHTkVEX0lOVF8yNF84IHx8IHBpeGVsRGF0YXR5cGUgPT09IFBpeGVsRGF0YXR5cGUuVU5TSUdORURfU0hPUlRfNF80XzRfNCB8fCBwaXhlbERhdGF0eXBlID09PSBQaXhlbERhdGF0eXBlLlVOU0lHTkVEX1NIT1JUXzVfNV81XzEgfHwgcGl4ZWxEYXRhdHlwZSA9PT0gUGl4ZWxEYXRhdHlwZS5VTlNJR05FRF9TSE9SVF81XzZfNTsKICAgICAgfTsKICAgICAgUGl4ZWxEYXRhdHlwZS5zaXplSW5CeXRlcyA9IGZ1bmN0aW9uKHBpeGVsRGF0YXR5cGUpIHsKICAgICAgICBzd2l0Y2ggKHBpeGVsRGF0YXR5cGUpIHsKICAgICAgICAgIGNhc2UgUGl4ZWxEYXRhdHlwZS5VTlNJR05FRF9CWVRFOgogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICAgIGNhc2UgUGl4ZWxEYXRhdHlwZS5VTlNJR05FRF9TSE9SVDoKICAgICAgICAgIGNhc2UgUGl4ZWxEYXRhdHlwZS5VTlNJR05FRF9TSE9SVF80XzRfNF80OgogICAgICAgICAgY2FzZSBQaXhlbERhdGF0eXBlLlVOU0lHTkVEX1NIT1JUXzVfNV81XzE6CiAgICAgICAgICBjYXNlIFBpeGVsRGF0YXR5cGUuVU5TSUdORURfU0hPUlRfNV82XzU6CiAgICAgICAgICBjYXNlIFBpeGVsRGF0YXR5cGUuSEFMRl9GTE9BVDoKICAgICAgICAgICAgcmV0dXJuIDI7CiAgICAgICAgICBjYXNlIFBpeGVsRGF0YXR5cGUuVU5TSUdORURfSU5UOgogICAgICAgICAgY2FzZSBQaXhlbERhdGF0eXBlLkZMT0FUOgogICAgICAgICAgY2FzZSBQaXhlbERhdGF0eXBlLlVOU0lHTkVEX0lOVF8yNF84OgogICAgICAgICAgICByZXR1cm4gNDsKICAgICAgICB9CiAgICAgIH07CiAgICAgIFBpeGVsRGF0YXR5cGUudmFsaWRhdGUgPSBmdW5jdGlvbihwaXhlbERhdGF0eXBlKSB7CiAgICAgICAgcmV0dXJuIHBpeGVsRGF0YXR5cGUgPT09IFBpeGVsRGF0YXR5cGUuVU5TSUdORURfQllURSB8fCBwaXhlbERhdGF0eXBlID09PSBQaXhlbERhdGF0eXBlLlVOU0lHTkVEX1NIT1JUIHx8IHBpeGVsRGF0YXR5cGUgPT09IFBpeGVsRGF0YXR5cGUuVU5TSUdORURfSU5UIHx8IHBpeGVsRGF0YXR5cGUgPT09IFBpeGVsRGF0YXR5cGUuRkxPQVQgfHwgcGl4ZWxEYXRhdHlwZSA9PT0gUGl4ZWxEYXRhdHlwZS5IQUxGX0ZMT0FUIHx8IHBpeGVsRGF0YXR5cGUgPT09IFBpeGVsRGF0YXR5cGUuVU5TSUdORURfSU5UXzI0XzggfHwgcGl4ZWxEYXRhdHlwZSA9PT0gUGl4ZWxEYXRhdHlwZS5VTlNJR05FRF9TSE9SVF80XzRfNF80IHx8IHBpeGVsRGF0YXR5cGUgPT09IFBpeGVsRGF0YXR5cGUuVU5TSUdORURfU0hPUlRfNV81XzVfMSB8fCBwaXhlbERhdGF0eXBlID09PSBQaXhlbERhdGF0eXBlLlVOU0lHTkVEX1NIT1JUXzVfNl81OwogICAgICB9OwogICAgICBQaXhlbERhdGF0eXBlLmdldFR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IGZ1bmN0aW9uKHBpeGVsRGF0YXR5cGUpIHsKICAgICAgICBjb25zdCBzaXplSW5CeXRlcyA9IFBpeGVsRGF0YXR5cGUuc2l6ZUluQnl0ZXMocGl4ZWxEYXRhdHlwZSk7CiAgICAgICAgaWYgKHNpemVJbkJ5dGVzID09PSBVaW50OEFycmF5LkJZVEVTX1BFUl9FTEVNRU5UKSB7CiAgICAgICAgICByZXR1cm4gVWludDhBcnJheTsKICAgICAgICB9IGVsc2UgaWYgKHNpemVJbkJ5dGVzID09PSBVaW50MTZBcnJheS5CWVRFU19QRVJfRUxFTUVOVCkgewogICAgICAgICAgcmV0dXJuIFVpbnQxNkFycmF5OwogICAgICAgIH0gZWxzZSBpZiAoc2l6ZUluQnl0ZXMgPT09IEZsb2F0MzJBcnJheS5CWVRFU19QRVJfRUxFTUVOVCAmJiBwaXhlbERhdGF0eXBlID09PSBQaXhlbERhdGF0eXBlLkZMT0FUKSB7CiAgICAgICAgICByZXR1cm4gRmxvYXQzMkFycmF5OwogICAgICAgIH0KICAgICAgICByZXR1cm4gVWludDMyQXJyYXk7CiAgICAgIH07CiAgICAgIFBpeGVsRGF0YXR5cGVfZGVmYXVsdCA9IE9iamVjdC5mcmVlemUoUGl4ZWxEYXRhdHlwZSk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9QaXhlbEZvcm1hdC5qcwogIHZhciBQaXhlbEZvcm1hdCwgUGl4ZWxGb3JtYXRfZGVmYXVsdDsKICB2YXIgaW5pdF9QaXhlbEZvcm1hdCA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvUGl4ZWxGb3JtYXQuanMiKCkgewogICAgICBpbml0X1BpeGVsRGF0YXR5cGUoKTsKICAgICAgaW5pdF9XZWJHTENvbnN0YW50cygpOwogICAgICBQaXhlbEZvcm1hdCA9IHsKICAgICAgICAvKioKICAgICAgICAgKiBBIHBpeGVsIGZvcm1hdCBjb250YWluaW5nIGEgZGVwdGggdmFsdWUuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIERFUFRIX0NPTVBPTkVOVDogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5ERVBUSF9DT01QT05FTlQsCiAgICAgICAgLyoqCiAgICAgICAgICogQSBwaXhlbCBmb3JtYXQgY29udGFpbmluZyBhIGRlcHRoIGFuZCBzdGVuY2lsIHZhbHVlLCBtb3N0IG9mdGVuIHVzZWQgd2l0aCB7QGxpbmsgUGl4ZWxEYXRhdHlwZS5VTlNJR05FRF9JTlRfMjRfOH0uCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIERFUFRIX1NURU5DSUw6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuREVQVEhfU1RFTkNJTCwKICAgICAgICAvKioKICAgICAgICAgKiBBIHBpeGVsIGZvcm1hdCBjb250YWluaW5nIGFuIGFscGhhIGNoYW5uZWwuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIEFMUEhBOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkFMUEhBLAogICAgICAgIC8qKgogICAgICAgICAqIEEgcGl4ZWwgZm9ybWF0IGNvbnRhaW5pbmcgYSByZWQgY2hhbm5lbAogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBSRUQ6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUkVELAogICAgICAgIC8qKgogICAgICAgICAqIEEgcGl4ZWwgZm9ybWF0IGNvbnRhaW5pbmcgcmVkIGFuZCBncmVlbiBjaGFubmVscy4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgUkc6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUkcsCiAgICAgICAgLyoqCiAgICAgICAgICogQSBwaXhlbCBmb3JtYXQgY29udGFpbmluZyByZWQsIGdyZWVuLCBhbmQgYmx1ZSBjaGFubmVscy4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgUkdCOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlJHQiwKICAgICAgICAvKioKICAgICAgICAgKiBBIHBpeGVsIGZvcm1hdCBjb250YWluaW5nIHJlZCwgZ3JlZW4sIGJsdWUsIGFuZCBhbHBoYSBjaGFubmVscy4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgUkdCQTogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5SR0JBLAogICAgICAgIC8qKgogICAgICAgICAqIEEgcGl4ZWwgZm9ybWF0IGNvbnRhaW5pbmcgYSByZWQgY2hhbm5lbCBhcyBhbiBpbnRlZ2VyLgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgUkVEX0lOVEVHRVI6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUkVEX0lOVEVHRVIsCiAgICAgICAgLyoqCiAgICAgICAgICogQSBwaXhlbCBmb3JtYXQgY29udGFpbmluZyByZWQgYW5kIGdyZWVuIGNoYW5uZWxzIGFzIGludGVnZXJzLgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgUkdfSU5URUdFUjogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5SR19JTlRFR0VSLAogICAgICAgIC8qKgogICAgICAgICAqIEEgcGl4ZWwgZm9ybWF0IGNvbnRhaW5pbmcgcmVkLCBncmVlbiwgYW5kIGJsdWUgY2hhbm5lbHMgYXMgaW50ZWdlcnMuCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBSR0JfSU5URUdFUjogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5SR0JfSU5URUdFUiwKICAgICAgICAvKioKICAgICAgICAgKiBBIHBpeGVsIGZvcm1hdCBjb250YWluaW5nIHJlZCwgZ3JlZW4sIGJsdWUsIGFuZCBhbHBoYSBjaGFubmVscyBhcyBpbnRlZ2Vycy4KICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFJHQkFfSU5URUdFUjogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5SR0JBX0lOVEVHRVIsCiAgICAgICAgLyoqCiAgICAgICAgICogQSBwaXhlbCBmb3JtYXQgY29udGFpbmluZyBhIGx1bWluYW5jZSAoaW50ZW5zaXR5KSBjaGFubmVsLgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBMVU1JTkFOQ0U6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuTFVNSU5BTkNFLAogICAgICAgIC8qKgogICAgICAgICAqIEEgcGl4ZWwgZm9ybWF0IGNvbnRhaW5pbmcgbHVtaW5hbmNlIChpbnRlbnNpdHkpIGFuZCBhbHBoYSBjaGFubmVscy4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgTFVNSU5BTkNFX0FMUEhBOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkxVTUlOQU5DRV9BTFBIQSwKICAgICAgICAvKioKICAgICAgICAgKiBBIHBpeGVsIGZvcm1hdCBjb250YWluaW5nIHJlZCwgZ3JlZW4sIGFuZCBibHVlIGNoYW5uZWxzIHRoYXQgaXMgRFhUMSBjb21wcmVzc2VkLgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBSR0JfRFhUMTogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5DT01QUkVTU0VEX1JHQl9TM1RDX0RYVDFfRVhULAogICAgICAgIC8qKgogICAgICAgICAqIEEgcGl4ZWwgZm9ybWF0IGNvbnRhaW5pbmcgcmVkLCBncmVlbiwgYmx1ZSwgYW5kIGFscGhhIGNoYW5uZWxzIHRoYXQgaXMgRFhUMSBjb21wcmVzc2VkLgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBSR0JBX0RYVDE6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuQ09NUFJFU1NFRF9SR0JBX1MzVENfRFhUMV9FWFQsCiAgICAgICAgLyoqCiAgICAgICAgICogQSBwaXhlbCBmb3JtYXQgY29udGFpbmluZyByZWQsIGdyZWVuLCBibHVlLCBhbmQgYWxwaGEgY2hhbm5lbHMgdGhhdCBpcyBEWFQzIGNvbXByZXNzZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFJHQkFfRFhUMzogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5DT01QUkVTU0VEX1JHQkFfUzNUQ19EWFQzX0VYVCwKICAgICAgICAvKioKICAgICAgICAgKiBBIHBpeGVsIGZvcm1hdCBjb250YWluaW5nIHJlZCwgZ3JlZW4sIGJsdWUsIGFuZCBhbHBoYSBjaGFubmVscyB0aGF0IGlzIERYVDUgY29tcHJlc3NlZC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgUkdCQV9EWFQ1OiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkNPTVBSRVNTRURfUkdCQV9TM1RDX0RYVDVfRVhULAogICAgICAgIC8qKgogICAgICAgICAqIEEgcGl4ZWwgZm9ybWF0IGNvbnRhaW5pbmcgcmVkLCBncmVlbiwgYW5kIGJsdWUgY2hhbm5lbHMgdGhhdCBpcyBQVlIgNGJwcCBjb21wcmVzc2VkLgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBSR0JfUFZSVENfNEJQUFYxOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkNPTVBSRVNTRURfUkdCX1BWUlRDXzRCUFBWMV9JTUcsCiAgICAgICAgLyoqCiAgICAgICAgICogQSBwaXhlbCBmb3JtYXQgY29udGFpbmluZyByZWQsIGdyZWVuLCBhbmQgYmx1ZSBjaGFubmVscyB0aGF0IGlzIFBWUiAyYnBwIGNvbXByZXNzZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFJHQl9QVlJUQ18yQlBQVjE6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuQ09NUFJFU1NFRF9SR0JfUFZSVENfMkJQUFYxX0lNRywKICAgICAgICAvKioKICAgICAgICAgKiBBIHBpeGVsIGZvcm1hdCBjb250YWluaW5nIHJlZCwgZ3JlZW4sIGJsdWUsIGFuZCBhbHBoYSBjaGFubmVscyB0aGF0IGlzIFBWUiA0YnBwIGNvbXByZXNzZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFJHQkFfUFZSVENfNEJQUFYxOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkNPTVBSRVNTRURfUkdCQV9QVlJUQ180QlBQVjFfSU1HLAogICAgICAgIC8qKgogICAgICAgICAqIEEgcGl4ZWwgZm9ybWF0IGNvbnRhaW5pbmcgcmVkLCBncmVlbiwgYmx1ZSwgYW5kIGFscGhhIGNoYW5uZWxzIHRoYXQgaXMgUFZSIDJicHAgY29tcHJlc3NlZC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgUkdCQV9QVlJUQ18yQlBQVjE6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuQ09NUFJFU1NFRF9SR0JBX1BWUlRDXzJCUFBWMV9JTUcsCiAgICAgICAgLyoqCiAgICAgICAgICogQSBwaXhlbCBmb3JtYXQgY29udGFpbmluZyByZWQsIGdyZWVuLCBibHVlLCBhbmQgYWxwaGEgY2hhbm5lbHMgdGhhdCBpcyBBU1RDIGNvbXByZXNzZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFJHQkFfQVNUQzogV2ViR0xDb25zdGFudHNfZGVmYXVsdC5DT01QUkVTU0VEX1JHQkFfQVNUQ180eDRfV0VCR0wsCiAgICAgICAgLyoqCiAgICAgICAgICogQSBwaXhlbCBmb3JtYXQgY29udGFpbmluZyByZWQsIGdyZWVuLCBhbmQgYmx1ZSBjaGFubmVscyB0aGF0IGlzIEVUQzEgY29tcHJlc3NlZC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgUkdCX0VUQzE6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuQ09NUFJFU1NFRF9SR0JfRVRDMV9XRUJHTCwKICAgICAgICAvKioKICAgICAgICAgKiBBIHBpeGVsIGZvcm1hdCBjb250YWluaW5nIHJlZCwgZ3JlZW4sIGFuZCBibHVlIGNoYW5uZWxzIHRoYXQgaXMgRVRDMiBjb21wcmVzc2VkLgogICAgICAgICAqCiAgICAgICAgICogQHR5cGUge251bWJlcn0KICAgICAgICAgKiBAY29uc3RhbnQKICAgICAgICAgKi8KICAgICAgICBSR0I4X0VUQzI6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuQ09NUFJFU1NFRF9SR0I4X0VUQzIsCiAgICAgICAgLyoqCiAgICAgICAgICogQSBwaXhlbCBmb3JtYXQgY29udGFpbmluZyByZWQsIGdyZWVuLCBibHVlLCBhbmQgYWxwaGEgY2hhbm5lbHMgdGhhdCBpcyBFVEMyIGNvbXByZXNzZWQuCiAgICAgICAgICoKICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfQogICAgICAgICAqIEBjb25zdGFudAogICAgICAgICAqLwogICAgICAgIFJHQkE4X0VUQzJfRUFDOiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkNPTVBSRVNTRURfUkdCQThfRVRDMl9FQUMsCiAgICAgICAgLyoqCiAgICAgICAgICogQSBwaXhlbCBmb3JtYXQgY29udGFpbmluZyByZWQsIGdyZWVuLCBibHVlLCBhbmQgYWxwaGEgY2hhbm5lbHMgdGhhdCBpcyBCQzcgY29tcHJlc3NlZC4KICAgICAgICAgKgogICAgICAgICAqIEB0eXBlIHtudW1iZXJ9CiAgICAgICAgICogQGNvbnN0YW50CiAgICAgICAgICovCiAgICAgICAgUkdCQV9CQzc6IFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuQ09NUFJFU1NFRF9SR0JBX0JQVENfVU5PUk0KICAgICAgfTsKICAgICAgUGl4ZWxGb3JtYXQuY29tcG9uZW50c0xlbmd0aCA9IGZ1bmN0aW9uKHBpeGVsRm9ybWF0KSB7CiAgICAgICAgc3dpdGNoIChwaXhlbEZvcm1hdCkgewogICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SR0I6CiAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LlJHQl9JTlRFR0VSOgogICAgICAgICAgICByZXR1cm4gMzsKICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCQToKICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCQV9JTlRFR0VSOgogICAgICAgICAgICByZXR1cm4gNDsKICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuTFVNSU5BTkNFX0FMUEhBOgogICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SRzoKICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdfSU5URUdFUjoKICAgICAgICAgICAgcmV0dXJuIDI7CiAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LkFMUEhBOgogICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SRUQ6CiAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LlJFRF9JTlRFR0VSOgogICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5MVU1JTkFOQ0U6CiAgICAgICAgICAgIHJldHVybiAxOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgfQogICAgICB9OwogICAgICBQaXhlbEZvcm1hdC52YWxpZGF0ZSA9IGZ1bmN0aW9uKHBpeGVsRm9ybWF0KSB7CiAgICAgICAgcmV0dXJuIHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5ERVBUSF9DT01QT05FTlQgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LkRFUFRIX1NURU5DSUwgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LkFMUEhBIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SRUQgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0IgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQkEgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJFRF9JTlRFR0VSIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR19JTlRFR0VSIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JfSU5URUdFUiB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCQV9JTlRFR0VSIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5MVU1JTkFOQ0UgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LkxVTUlOQU5DRV9BTFBIQSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCX0RYVDEgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQkFfRFhUMSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCQV9EWFQzIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JBX0RYVDUgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQl9QVlJUQ180QlBQVjEgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQl9QVlJUQ18yQlBQVjEgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQkFfUFZSVENfNEJQUFYxIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JBX1BWUlRDXzJCUFBWMSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCQV9BU1RDIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JfRVRDMSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCOF9FVEMyIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JBOF9FVEMyX0VBQyB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCQV9CQzc7CiAgICAgIH07CiAgICAgIFBpeGVsRm9ybWF0LmlzQ29sb3JGb3JtYXQgPSBmdW5jdGlvbihwaXhlbEZvcm1hdCkgewogICAgICAgIHJldHVybiBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkVEIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5BTFBIQSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JBIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5MVU1JTkFOQ0UgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LkxVTUlOQU5DRV9BTFBIQTsKICAgICAgfTsKICAgICAgUGl4ZWxGb3JtYXQuaXNEZXB0aEZvcm1hdCA9IGZ1bmN0aW9uKHBpeGVsRm9ybWF0KSB7CiAgICAgICAgcmV0dXJuIHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5ERVBUSF9DT01QT05FTlQgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LkRFUFRIX1NURU5DSUw7CiAgICAgIH07CiAgICAgIFBpeGVsRm9ybWF0LmlzQ29tcHJlc3NlZEZvcm1hdCA9IGZ1bmN0aW9uKHBpeGVsRm9ybWF0KSB7CiAgICAgICAgcmV0dXJuIHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JfRFhUMSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCQV9EWFQxIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JBX0RYVDMgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQkFfRFhUNSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCX1BWUlRDXzRCUFBWMSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCX1BWUlRDXzJCUFBWMSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCQV9QVlJUQ180QlBQVjEgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQkFfUFZSVENfMkJQUFYxIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JBX0FTVEMgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQl9FVEMxIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0I4X0VUQzIgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQkE4X0VUQzJfRUFDIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JBX0JDNzsKICAgICAgfTsKICAgICAgUGl4ZWxGb3JtYXQuaXNEWFRGb3JtYXQgPSBmdW5jdGlvbihwaXhlbEZvcm1hdCkgewogICAgICAgIHJldHVybiBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCX0RYVDEgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQkFfRFhUMSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCQV9EWFQzIHx8IHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JBX0RYVDU7CiAgICAgIH07CiAgICAgIFBpeGVsRm9ybWF0LmlzUFZSVENGb3JtYXQgPSBmdW5jdGlvbihwaXhlbEZvcm1hdCkgewogICAgICAgIHJldHVybiBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCX1BWUlRDXzRCUFBWMSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCX1BWUlRDXzJCUFBWMSB8fCBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCQV9QVlJUQ180QlBQVjEgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQkFfUFZSVENfMkJQUFYxOwogICAgICB9OwogICAgICBQaXhlbEZvcm1hdC5pc0FTVENGb3JtYXQgPSBmdW5jdGlvbihwaXhlbEZvcm1hdCkgewogICAgICAgIHJldHVybiBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCQV9BU1RDOwogICAgICB9OwogICAgICBQaXhlbEZvcm1hdC5pc0VUQzFGb3JtYXQgPSBmdW5jdGlvbihwaXhlbEZvcm1hdCkgewogICAgICAgIHJldHVybiBwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuUkdCX0VUQzE7CiAgICAgIH07CiAgICAgIFBpeGVsRm9ybWF0LmlzRVRDMkZvcm1hdCA9IGZ1bmN0aW9uKHBpeGVsRm9ybWF0KSB7CiAgICAgICAgcmV0dXJuIHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0I4X0VUQzIgfHwgcGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LlJHQkE4X0VUQzJfRUFDOwogICAgICB9OwogICAgICBQaXhlbEZvcm1hdC5pc0JDN0Zvcm1hdCA9IGZ1bmN0aW9uKHBpeGVsRm9ybWF0KSB7CiAgICAgICAgcmV0dXJuIHBpeGVsRm9ybWF0ID09PSBQaXhlbEZvcm1hdC5SR0JBX0JDNzsKICAgICAgfTsKICAgICAgUGl4ZWxGb3JtYXQuY29tcHJlc3NlZFRleHR1cmVTaXplSW5CeXRlcyA9IGZ1bmN0aW9uKHBpeGVsRm9ybWF0LCB3aWR0aCwgaGVpZ2h0KSB7CiAgICAgICAgc3dpdGNoIChwaXhlbEZvcm1hdCkgewogICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SR0JfRFhUMToKICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCQV9EWFQxOgogICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SR0JfRVRDMToKICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCOF9FVEMyOgogICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigod2lkdGggKyAzKSAvIDQpICogTWF0aC5mbG9vcigoaGVpZ2h0ICsgMykgLyA0KSAqIDg7CiAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LlJHQkFfRFhUMzoKICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCQV9EWFQ1OgogICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SR0JBX0FTVEM6CiAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LlJHQkE4X0VUQzJfRUFDOgogICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigod2lkdGggKyAzKSAvIDQpICogTWF0aC5mbG9vcigoaGVpZ2h0ICsgMykgLyA0KSAqIDE2OwogICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SR0JfUFZSVENfNEJQUFYxOgogICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SR0JBX1BWUlRDXzRCUFBWMToKICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKE1hdGgubWF4KHdpZHRoLCA4KSAqIE1hdGgubWF4KGhlaWdodCwgOCkgKiA0ICsgNykgLyA4KTsKICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCX1BWUlRDXzJCUFBWMToKICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCQV9QVlJUQ18yQlBQVjE6CiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKAogICAgICAgICAgICAgIChNYXRoLm1heCh3aWR0aCwgMTYpICogTWF0aC5tYXgoaGVpZ2h0LCA4KSAqIDIgKyA3KSAvIDgKICAgICAgICAgICAgKTsKICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCQV9CQzc6CiAgICAgICAgICAgIHJldHVybiBNYXRoLmNlaWwod2lkdGggLyA0KSAqIE1hdGguY2VpbChoZWlnaHQgLyA0KSAqIDE2OwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQogICAgICB9OwogICAgICBQaXhlbEZvcm1hdC50ZXh0dXJlU2l6ZUluQnl0ZXMgPSBmdW5jdGlvbihwaXhlbEZvcm1hdCwgcGl4ZWxEYXRhdHlwZSwgd2lkdGgsIGhlaWdodCkgewogICAgICAgIGxldCBjb21wb25lbnRzTGVuZ3RoID0gUGl4ZWxGb3JtYXQuY29tcG9uZW50c0xlbmd0aChwaXhlbEZvcm1hdCk7CiAgICAgICAgaWYgKFBpeGVsRGF0YXR5cGVfZGVmYXVsdC5pc1BhY2tlZChwaXhlbERhdGF0eXBlKSkgewogICAgICAgICAgY29tcG9uZW50c0xlbmd0aCA9IDE7CiAgICAgICAgfQogICAgICAgIHJldHVybiBjb21wb25lbnRzTGVuZ3RoICogUGl4ZWxEYXRhdHlwZV9kZWZhdWx0LnNpemVJbkJ5dGVzKHBpeGVsRGF0YXR5cGUpICogd2lkdGggKiBoZWlnaHQ7CiAgICAgIH07CiAgICAgIFBpeGVsRm9ybWF0LnRleHR1cmUzRFNpemVJbkJ5dGVzID0gZnVuY3Rpb24ocGl4ZWxGb3JtYXQsIHBpeGVsRGF0YXR5cGUsIHdpZHRoLCBoZWlnaHQsIGRlcHRoMikgewogICAgICAgIGxldCBjb21wb25lbnRzTGVuZ3RoID0gUGl4ZWxGb3JtYXQuY29tcG9uZW50c0xlbmd0aChwaXhlbEZvcm1hdCk7CiAgICAgICAgaWYgKFBpeGVsRGF0YXR5cGVfZGVmYXVsdC5pc1BhY2tlZChwaXhlbERhdGF0eXBlKSkgewogICAgICAgICAgY29tcG9uZW50c0xlbmd0aCA9IDE7CiAgICAgICAgfQogICAgICAgIHJldHVybiBjb21wb25lbnRzTGVuZ3RoICogUGl4ZWxEYXRhdHlwZV9kZWZhdWx0LnNpemVJbkJ5dGVzKHBpeGVsRGF0YXR5cGUpICogd2lkdGggKiBoZWlnaHQgKiBkZXB0aDI7CiAgICAgIH07CiAgICAgIFBpeGVsRm9ybWF0LmFsaWdubWVudEluQnl0ZXMgPSBmdW5jdGlvbihwaXhlbEZvcm1hdCwgcGl4ZWxEYXRhdHlwZSwgd2lkdGgpIHsKICAgICAgICBjb25zdCBtb2QgPSBQaXhlbEZvcm1hdC50ZXh0dXJlU2l6ZUluQnl0ZXMocGl4ZWxGb3JtYXQsIHBpeGVsRGF0YXR5cGUsIHdpZHRoLCAxKSAlIDQ7CiAgICAgICAgcmV0dXJuIG1vZCA9PT0gMCA/IDQgOiBtb2QgPT09IDIgPyAyIDogMTsKICAgICAgfTsKICAgICAgUGl4ZWxGb3JtYXQuY3JlYXRlVHlwZWRBcnJheSA9IGZ1bmN0aW9uKHBpeGVsRm9ybWF0LCBwaXhlbERhdGF0eXBlLCB3aWR0aCwgaGVpZ2h0KSB7CiAgICAgICAgY29uc3QgY29uc3RydWN0b3IgPSBQaXhlbERhdGF0eXBlX2RlZmF1bHQuZ2V0VHlwZWRBcnJheUNvbnN0cnVjdG9yKHBpeGVsRGF0YXR5cGUpOwogICAgICAgIGNvbnN0IHNpemUgPSBQaXhlbEZvcm1hdC5jb21wb25lbnRzTGVuZ3RoKHBpeGVsRm9ybWF0KSAqIHdpZHRoICogaGVpZ2h0OwogICAgICAgIHJldHVybiBuZXcgY29uc3RydWN0b3Ioc2l6ZSk7CiAgICAgIH07CiAgICAgIFBpeGVsRm9ybWF0LmZsaXBZID0gZnVuY3Rpb24oYnVmZmVyVmlldywgcGl4ZWxGb3JtYXQsIHBpeGVsRGF0YXR5cGUsIHdpZHRoLCBoZWlnaHQpIHsKICAgICAgICBpZiAoaGVpZ2h0ID09PSAxKSB7CiAgICAgICAgICByZXR1cm4gYnVmZmVyVmlldzsKICAgICAgICB9CiAgICAgICAgY29uc3QgZmxpcHBlZCA9IFBpeGVsRm9ybWF0LmNyZWF0ZVR5cGVkQXJyYXkoCiAgICAgICAgICBwaXhlbEZvcm1hdCwKICAgICAgICAgIHBpeGVsRGF0YXR5cGUsCiAgICAgICAgICB3aWR0aCwKICAgICAgICAgIGhlaWdodAogICAgICAgICk7CiAgICAgICAgY29uc3QgbnVtYmVyT2ZDb21wb25lbnRzID0gUGl4ZWxGb3JtYXQuY29tcG9uZW50c0xlbmd0aChwaXhlbEZvcm1hdCk7CiAgICAgICAgY29uc3QgdGV4dHVyZVdpZHRoID0gd2lkdGggKiBudW1iZXJPZkNvbXBvbmVudHM7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZWlnaHQ7ICsraSkgewogICAgICAgICAgY29uc3Qgcm93ID0gaSAqIHdpZHRoICogbnVtYmVyT2ZDb21wb25lbnRzOwogICAgICAgICAgY29uc3QgZmxpcHBlZFJvdyA9IChoZWlnaHQgLSBpIC0gMSkgKiB3aWR0aCAqIG51bWJlck9mQ29tcG9uZW50czsKICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGV4dHVyZVdpZHRoOyArK2opIHsKICAgICAgICAgICAgZmxpcHBlZFtmbGlwcGVkUm93ICsgal0gPSBidWZmZXJWaWV3W3JvdyArIGpdOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gZmxpcHBlZDsKICAgICAgfTsKICAgICAgUGl4ZWxGb3JtYXQudG9JbnRlcm5hbEZvcm1hdCA9IGZ1bmN0aW9uKHBpeGVsRm9ybWF0LCBwaXhlbERhdGF0eXBlLCBjb250ZXh0KSB7CiAgICAgICAgaWYgKCFjb250ZXh0LndlYmdsMikgewogICAgICAgICAgcmV0dXJuIHBpeGVsRm9ybWF0OwogICAgICAgIH0KICAgICAgICBpZiAocGl4ZWxGb3JtYXQgPT09IFBpeGVsRm9ybWF0LkRFUFRIX1NURU5DSUwpIHsKICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkRFUFRIMjRfU1RFTkNJTDg7CiAgICAgICAgfQogICAgICAgIGlmIChwaXhlbEZvcm1hdCA9PT0gUGl4ZWxGb3JtYXQuREVQVEhfQ09NUE9ORU5UKSB7CiAgICAgICAgICBpZiAocGl4ZWxEYXRhdHlwZSA9PT0gUGl4ZWxEYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX1NIT1JUKSB7CiAgICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkRFUFRIX0NPTVBPTkVOVDE2OwogICAgICAgICAgfSBlbHNlIGlmIChwaXhlbERhdGF0eXBlID09PSBQaXhlbERhdGF0eXBlX2RlZmF1bHQuVU5TSUdORURfSU5UKSB7CiAgICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LkRFUFRIX0NPTVBPTkVOVDI0OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAocGl4ZWxEYXRhdHlwZSA9PT0gUGl4ZWxEYXRhdHlwZV9kZWZhdWx0LkZMT0FUKSB7CiAgICAgICAgICBzd2l0Y2ggKHBpeGVsRm9ybWF0KSB7CiAgICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCQToKICAgICAgICAgICAgICByZXR1cm4gV2ViR0xDb25zdGFudHNfZGVmYXVsdC5SR0JBMzJGOwogICAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LlJHQjoKICAgICAgICAgICAgICByZXR1cm4gV2ViR0xDb25zdGFudHNfZGVmYXVsdC5SR0IzMkY7CiAgICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkc6CiAgICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUkczMkY7CiAgICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkVEOgogICAgICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlIzMkY7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChwaXhlbERhdGF0eXBlID09PSBQaXhlbERhdGF0eXBlX2RlZmF1bHQuSEFMRl9GTE9BVCkgewogICAgICAgICAgc3dpdGNoIChwaXhlbEZvcm1hdCkgewogICAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LlJHQkE6CiAgICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUkdCQTE2RjsKICAgICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SR0I6CiAgICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUkdCMTZGOwogICAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LlJHOgogICAgICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlJHMTZGOwogICAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LlJFRDoKICAgICAgICAgICAgICByZXR1cm4gV2ViR0xDb25zdGFudHNfZGVmYXVsdC5SMTZGOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAocGl4ZWxEYXRhdHlwZSA9PT0gUGl4ZWxEYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEUpIHsKICAgICAgICAgIHN3aXRjaCAocGl4ZWxGb3JtYXQpIHsKICAgICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SR0JBOgogICAgICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlJHQkE4OwogICAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LlJHQjoKICAgICAgICAgICAgICByZXR1cm4gV2ViR0xDb25zdGFudHNfZGVmYXVsdC5SR0I4OwogICAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LlJHOgogICAgICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlJHODsKICAgICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SRUQ6CiAgICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUjg7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChwaXhlbERhdGF0eXBlID09PSBQaXhlbERhdGF0eXBlX2RlZmF1bHQuSU5UKSB7CiAgICAgICAgICBzd2l0Y2ggKHBpeGVsRm9ybWF0KSB7CiAgICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCQV9JTlRFR0VSOgogICAgICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlJHQkEzMkk7CiAgICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCX0lOVEVHRVI6CiAgICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUkdCMzJJOwogICAgICAgICAgICBjYXNlIFBpeGVsRm9ybWF0LlJHX0lOVEVHRVI6CiAgICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUkczMkk7CiAgICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkVEX0lOVEVHRVI6CiAgICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUjMySTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHBpeGVsRGF0YXR5cGUgPT09IFBpeGVsRGF0YXR5cGVfZGVmYXVsdC5VTlNJR05FRF9JTlQpIHsKICAgICAgICAgIHN3aXRjaCAocGl4ZWxGb3JtYXQpIHsKICAgICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SR0JBX0lOVEVHRVI6CiAgICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUkdCQTMyVUk7CiAgICAgICAgICAgIGNhc2UgUGl4ZWxGb3JtYXQuUkdCX0lOVEVHRVI6CiAgICAgICAgICAgICAgcmV0dXJuIFdlYkdMQ29uc3RhbnRzX2RlZmF1bHQuUkdCMzJVSTsKICAgICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SR19JTlRFR0VSOgogICAgICAgICAgICAgIHJldHVybiBXZWJHTENvbnN0YW50c19kZWZhdWx0LlJHMzJVSTsKICAgICAgICAgICAgY2FzZSBQaXhlbEZvcm1hdC5SRURfSU5URUdFUjoKICAgICAgICAgICAgICByZXR1cm4gV2ViR0xDb25zdGFudHNfZGVmYXVsdC5SMzJVSTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHBpeGVsRm9ybWF0OwogICAgICB9OwogICAgICBQaXhlbEZvcm1hdF9kZWZhdWx0ID0gT2JqZWN0LmZyZWV6ZShQaXhlbEZvcm1hdCk7CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvQ29yZS9WdWxrYW5Db25zdGFudHMuanMKICB2YXIgVnVsa2FuQ29uc3RhbnRzLCBWdWxrYW5Db25zdGFudHNfZGVmYXVsdDsKICB2YXIgaW5pdF9WdWxrYW5Db25zdGFudHMgPSBfX2VzbSh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL1Z1bGthbkNvbnN0YW50cy5qcyIoKSB7CiAgICAgIFZ1bGthbkNvbnN0YW50cyA9IHsKICAgICAgICBWS19GT1JNQVRfVU5ERUZJTkVEOiAwLAogICAgICAgIFZLX0ZPUk1BVF9SNEc0X1VOT1JNX1BBQ0s4OiAxLAogICAgICAgIFZLX0ZPUk1BVF9SNEc0QjRBNF9VTk9STV9QQUNLMTY6IDIsCiAgICAgICAgVktfRk9STUFUX0I0RzRSNEE0X1VOT1JNX1BBQ0sxNjogMywKICAgICAgICBWS19GT1JNQVRfUjVHNkI1X1VOT1JNX1BBQ0sxNjogNCwKICAgICAgICBWS19GT1JNQVRfQjVHNlI1X1VOT1JNX1BBQ0sxNjogNSwKICAgICAgICBWS19GT1JNQVRfUjVHNUI1QTFfVU5PUk1fUEFDSzE2OiA2LAogICAgICAgIFZLX0ZPUk1BVF9CNUc1UjVBMV9VTk9STV9QQUNLMTY6IDcsCiAgICAgICAgVktfRk9STUFUX0ExUjVHNUI1X1VOT1JNX1BBQ0sxNjogOCwKICAgICAgICBWS19GT1JNQVRfUjhfVU5PUk06IDksCiAgICAgICAgVktfRk9STUFUX1I4X1NOT1JNOiAxMCwKICAgICAgICBWS19GT1JNQVRfUjhfVVNDQUxFRDogMTEsCiAgICAgICAgVktfRk9STUFUX1I4X1NTQ0FMRUQ6IDEyLAogICAgICAgIFZLX0ZPUk1BVF9SOF9VSU5UOiAxMywKICAgICAgICBWS19GT1JNQVRfUjhfU0lOVDogMTQsCiAgICAgICAgVktfRk9STUFUX1I4X1NSR0I6IDE1LAogICAgICAgIFZLX0ZPUk1BVF9SOEc4X1VOT1JNOiAxNiwKICAgICAgICBWS19GT1JNQVRfUjhHOF9TTk9STTogMTcsCiAgICAgICAgVktfRk9STUFUX1I4RzhfVVNDQUxFRDogMTgsCiAgICAgICAgVktfRk9STUFUX1I4RzhfU1NDQUxFRDogMTksCiAgICAgICAgVktfRk9STUFUX1I4RzhfVUlOVDogMjAsCiAgICAgICAgVktfRk9STUFUX1I4RzhfU0lOVDogMjEsCiAgICAgICAgVktfRk9STUFUX1I4RzhfU1JHQjogMjIsCiAgICAgICAgVktfRk9STUFUX1I4RzhCOF9VTk9STTogMjMsCiAgICAgICAgVktfRk9STUFUX1I4RzhCOF9TTk9STTogMjQsCiAgICAgICAgVktfRk9STUFUX1I4RzhCOF9VU0NBTEVEOiAyNSwKICAgICAgICBWS19GT1JNQVRfUjhHOEI4X1NTQ0FMRUQ6IDI2LAogICAgICAgIFZLX0ZPUk1BVF9SOEc4QjhfVUlOVDogMjcsCiAgICAgICAgVktfRk9STUFUX1I4RzhCOF9TSU5UOiAyOCwKICAgICAgICBWS19GT1JNQVRfUjhHOEI4X1NSR0I6IDI5LAogICAgICAgIFZLX0ZPUk1BVF9COEc4UjhfVU5PUk06IDMwLAogICAgICAgIFZLX0ZPUk1BVF9COEc4UjhfU05PUk06IDMxLAogICAgICAgIFZLX0ZPUk1BVF9COEc4UjhfVVNDQUxFRDogMzIsCiAgICAgICAgVktfRk9STUFUX0I4RzhSOF9TU0NBTEVEOiAzMywKICAgICAgICBWS19GT1JNQVRfQjhHOFI4X1VJTlQ6IDM0LAogICAgICAgIFZLX0ZPUk1BVF9COEc4UjhfU0lOVDogMzUsCiAgICAgICAgVktfRk9STUFUX0I4RzhSOF9TUkdCOiAzNiwKICAgICAgICBWS19GT1JNQVRfUjhHOEI4QThfVU5PUk06IDM3LAogICAgICAgIFZLX0ZPUk1BVF9SOEc4QjhBOF9TTk9STTogMzgsCiAgICAgICAgVktfRk9STUFUX1I4RzhCOEE4X1VTQ0FMRUQ6IDM5LAogICAgICAgIFZLX0ZPUk1BVF9SOEc4QjhBOF9TU0NBTEVEOiA0MCwKICAgICAgICBWS19GT1JNQVRfUjhHOEI4QThfVUlOVDogNDEsCiAgICAgICAgVktfRk9STUFUX1I4RzhCOEE4X1NJTlQ6IDQyLAogICAgICAgIFZLX0ZPUk1BVF9SOEc4QjhBOF9TUkdCOiA0MywKICAgICAgICBWS19GT1JNQVRfQjhHOFI4QThfVU5PUk06IDQ0LAogICAgICAgIFZLX0ZPUk1BVF9COEc4UjhBOF9TTk9STTogNDUsCiAgICAgICAgVktfRk9STUFUX0I4RzhSOEE4X1VTQ0FMRUQ6IDQ2LAogICAgICAgIFZLX0ZPUk1BVF9COEc4UjhBOF9TU0NBTEVEOiA0NywKICAgICAgICBWS19GT1JNQVRfQjhHOFI4QThfVUlOVDogNDgsCiAgICAgICAgVktfRk9STUFUX0I4RzhSOEE4X1NJTlQ6IDQ5LAogICAgICAgIFZLX0ZPUk1BVF9COEc4UjhBOF9TUkdCOiA1MCwKICAgICAgICBWS19GT1JNQVRfQThCOEc4UjhfVU5PUk1fUEFDSzMyOiA1MSwKICAgICAgICBWS19GT1JNQVRfQThCOEc4UjhfU05PUk1fUEFDSzMyOiA1MiwKICAgICAgICBWS19GT1JNQVRfQThCOEc4UjhfVVNDQUxFRF9QQUNLMzI6IDUzLAogICAgICAgIFZLX0ZPUk1BVF9BOEI4RzhSOF9TU0NBTEVEX1BBQ0szMjogNTQsCiAgICAgICAgVktfRk9STUFUX0E4QjhHOFI4X1VJTlRfUEFDSzMyOiA1NSwKICAgICAgICBWS19GT1JNQVRfQThCOEc4UjhfU0lOVF9QQUNLMzI6IDU2LAogICAgICAgIFZLX0ZPUk1BVF9BOEI4RzhSOF9TUkdCX1BBQ0szMjogNTcsCiAgICAgICAgVktfRk9STUFUX0EyUjEwRzEwQjEwX1VOT1JNX1BBQ0szMjogNTgsCiAgICAgICAgVktfRk9STUFUX0EyUjEwRzEwQjEwX1NOT1JNX1BBQ0szMjogNTksCiAgICAgICAgVktfRk9STUFUX0EyUjEwRzEwQjEwX1VTQ0FMRURfUEFDSzMyOiA2MCwKICAgICAgICBWS19GT1JNQVRfQTJSMTBHMTBCMTBfU1NDQUxFRF9QQUNLMzI6IDYxLAogICAgICAgIFZLX0ZPUk1BVF9BMlIxMEcxMEIxMF9VSU5UX1BBQ0szMjogNjIsCiAgICAgICAgVktfRk9STUFUX0EyUjEwRzEwQjEwX1NJTlRfUEFDSzMyOiA2MywKICAgICAgICBWS19GT1JNQVRfQTJCMTBHMTBSMTBfVU5PUk1fUEFDSzMyOiA2NCwKICAgICAgICBWS19GT1JNQVRfQTJCMTBHMTBSMTBfU05PUk1fUEFDSzMyOiA2NSwKICAgICAgICBWS19GT1JNQVRfQTJCMTBHMTBSMTBfVVNDQUxFRF9QQUNLMzI6IDY2LAogICAgICAgIFZLX0ZPUk1BVF9BMkIxMEcxMFIxMF9TU0NBTEVEX1BBQ0szMjogNjcsCiAgICAgICAgVktfRk9STUFUX0EyQjEwRzEwUjEwX1VJTlRfUEFDSzMyOiA2OCwKICAgICAgICBWS19GT1JNQVRfQTJCMTBHMTBSMTBfU0lOVF9QQUNLMzI6IDY5LAogICAgICAgIFZLX0ZPUk1BVF9SMTZfVU5PUk06IDcwLAogICAgICAgIFZLX0ZPUk1BVF9SMTZfU05PUk06IDcxLAogICAgICAgIFZLX0ZPUk1BVF9SMTZfVVNDQUxFRDogNzIsCiAgICAgICAgVktfRk9STUFUX1IxNl9TU0NBTEVEOiA3MywKICAgICAgICBWS19GT1JNQVRfUjE2X1VJTlQ6IDc0LAogICAgICAgIFZLX0ZPUk1BVF9SMTZfU0lOVDogNzUsCiAgICAgICAgVktfRk9STUFUX1IxNl9TRkxPQVQ6IDc2LAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZfVU5PUk06IDc3LAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZfU05PUk06IDc4LAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZfVVNDQUxFRDogNzksCiAgICAgICAgVktfRk9STUFUX1IxNkcxNl9TU0NBTEVEOiA4MCwKICAgICAgICBWS19GT1JNQVRfUjE2RzE2X1VJTlQ6IDgxLAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZfU0lOVDogODIsCiAgICAgICAgVktfRk9STUFUX1IxNkcxNl9TRkxPQVQ6IDgzLAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZCMTZfVU5PUk06IDg0LAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZCMTZfU05PUk06IDg1LAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZCMTZfVVNDQUxFRDogODYsCiAgICAgICAgVktfRk9STUFUX1IxNkcxNkIxNl9TU0NBTEVEOiA4NywKICAgICAgICBWS19GT1JNQVRfUjE2RzE2QjE2X1VJTlQ6IDg4LAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZCMTZfU0lOVDogODksCiAgICAgICAgVktfRk9STUFUX1IxNkcxNkIxNl9TRkxPQVQ6IDkwLAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZCMTZBMTZfVU5PUk06IDkxLAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZCMTZBMTZfU05PUk06IDkyLAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZCMTZBMTZfVVNDQUxFRDogOTMsCiAgICAgICAgVktfRk9STUFUX1IxNkcxNkIxNkExNl9TU0NBTEVEOiA5NCwKICAgICAgICBWS19GT1JNQVRfUjE2RzE2QjE2QTE2X1VJTlQ6IDk1LAogICAgICAgIFZLX0ZPUk1BVF9SMTZHMTZCMTZBMTZfU0lOVDogOTYsCiAgICAgICAgVktfRk9STUFUX1IxNkcxNkIxNkExNl9TRkxPQVQ6IDk3LAogICAgICAgIFZLX0ZPUk1BVF9SMzJfVUlOVDogOTgsCiAgICAgICAgVktfRk9STUFUX1IzMl9TSU5UOiA5OSwKICAgICAgICBWS19GT1JNQVRfUjMyX1NGTE9BVDogMTAwLAogICAgICAgIFZLX0ZPUk1BVF9SMzJHMzJfVUlOVDogMTAxLAogICAgICAgIFZLX0ZPUk1BVF9SMzJHMzJfU0lOVDogMTAyLAogICAgICAgIFZLX0ZPUk1BVF9SMzJHMzJfU0ZMT0FUOiAxMDMsCiAgICAgICAgVktfRk9STUFUX1IzMkczMkIzMl9VSU5UOiAxMDQsCiAgICAgICAgVktfRk9STUFUX1IzMkczMkIzMl9TSU5UOiAxMDUsCiAgICAgICAgVktfRk9STUFUX1IzMkczMkIzMl9TRkxPQVQ6IDEwNiwKICAgICAgICBWS19GT1JNQVRfUjMyRzMyQjMyQTMyX1VJTlQ6IDEwNywKICAgICAgICBWS19GT1JNQVRfUjMyRzMyQjMyQTMyX1NJTlQ6IDEwOCwKICAgICAgICBWS19GT1JNQVRfUjMyRzMyQjMyQTMyX1NGTE9BVDogMTA5LAogICAgICAgIFZLX0ZPUk1BVF9SNjRfVUlOVDogMTEwLAogICAgICAgIFZLX0ZPUk1BVF9SNjRfU0lOVDogMTExLAogICAgICAgIFZLX0ZPUk1BVF9SNjRfU0ZMT0FUOiAxMTIsCiAgICAgICAgVktfRk9STUFUX1I2NEc2NF9VSU5UOiAxMTMsCiAgICAgICAgVktfRk9STUFUX1I2NEc2NF9TSU5UOiAxMTQsCiAgICAgICAgVktfRk9STUFUX1I2NEc2NF9TRkxPQVQ6IDExNSwKICAgICAgICBWS19GT1JNQVRfUjY0RzY0QjY0X1VJTlQ6IDExNiwKICAgICAgICBWS19GT1JNQVRfUjY0RzY0QjY0X1NJTlQ6IDExNywKICAgICAgICBWS19GT1JNQVRfUjY0RzY0QjY0X1NGTE9BVDogMTE4LAogICAgICAgIFZLX0ZPUk1BVF9SNjRHNjRCNjRBNjRfVUlOVDogMTE5LAogICAgICAgIFZLX0ZPUk1BVF9SNjRHNjRCNjRBNjRfU0lOVDogMTIwLAogICAgICAgIFZLX0ZPUk1BVF9SNjRHNjRCNjRBNjRfU0ZMT0FUOiAxMjEsCiAgICAgICAgVktfRk9STUFUX0IxMEcxMVIxMV9VRkxPQVRfUEFDSzMyOiAxMjIsCiAgICAgICAgVktfRk9STUFUX0U1QjlHOVI5X1VGTE9BVF9QQUNLMzI6IDEyMywKICAgICAgICBWS19GT1JNQVRfRDE2X1VOT1JNOiAxMjQsCiAgICAgICAgVktfRk9STUFUX1g4X0QyNF9VTk9STV9QQUNLMzI6IDEyNSwKICAgICAgICBWS19GT1JNQVRfRDMyX1NGTE9BVDogMTI2LAogICAgICAgIFZLX0ZPUk1BVF9TOF9VSU5UOiAxMjcsCiAgICAgICAgVktfRk9STUFUX0QxNl9VTk9STV9TOF9VSU5UOiAxMjgsCiAgICAgICAgVktfRk9STUFUX0QyNF9VTk9STV9TOF9VSU5UOiAxMjksCiAgICAgICAgVktfRk9STUFUX0QzMl9TRkxPQVRfUzhfVUlOVDogMTMwLAogICAgICAgIFZLX0ZPUk1BVF9CQzFfUkdCX1VOT1JNX0JMT0NLOiAxMzEsCiAgICAgICAgVktfRk9STUFUX0JDMV9SR0JfU1JHQl9CTE9DSzogMTMyLAogICAgICAgIFZLX0ZPUk1BVF9CQzFfUkdCQV9VTk9STV9CTE9DSzogMTMzLAogICAgICAgIFZLX0ZPUk1BVF9CQzFfUkdCQV9TUkdCX0JMT0NLOiAxMzQsCiAgICAgICAgVktfRk9STUFUX0JDMl9VTk9STV9CTE9DSzogMTM1LAogICAgICAgIFZLX0ZPUk1BVF9CQzJfU1JHQl9CTE9DSzogMTM2LAogICAgICAgIFZLX0ZPUk1BVF9CQzNfVU5PUk1fQkxPQ0s6IDEzNywKICAgICAgICBWS19GT1JNQVRfQkMzX1NSR0JfQkxPQ0s6IDEzOCwKICAgICAgICBWS19GT1JNQVRfQkM0X1VOT1JNX0JMT0NLOiAxMzksCiAgICAgICAgVktfRk9STUFUX0JDNF9TTk9STV9CTE9DSzogMTQwLAogICAgICAgIFZLX0ZPUk1BVF9CQzVfVU5PUk1fQkxPQ0s6IDE0MSwKICAgICAgICBWS19GT1JNQVRfQkM1X1NOT1JNX0JMT0NLOiAxNDIsCiAgICAgICAgVktfRk9STUFUX0JDNkhfVUZMT0FUX0JMT0NLOiAxNDMsCiAgICAgICAgVktfRk9STUFUX0JDNkhfU0ZMT0FUX0JMT0NLOiAxNDQsCiAgICAgICAgVktfRk9STUFUX0JDN19VTk9STV9CTE9DSzogMTQ1LAogICAgICAgIFZLX0ZPUk1BVF9CQzdfU1JHQl9CTE9DSzogMTQ2LAogICAgICAgIFZLX0ZPUk1BVF9FVEMyX1I4RzhCOF9VTk9STV9CTE9DSzogMTQ3LAogICAgICAgIFZLX0ZPUk1BVF9FVEMyX1I4RzhCOF9TUkdCX0JMT0NLOiAxNDgsCiAgICAgICAgVktfRk9STUFUX0VUQzJfUjhHOEI4QTFfVU5PUk1fQkxPQ0s6IDE0OSwKICAgICAgICBWS19GT1JNQVRfRVRDMl9SOEc4QjhBMV9TUkdCX0JMT0NLOiAxNTAsCiAgICAgICAgVktfRk9STUFUX0VUQzJfUjhHOEI4QThfVU5PUk1fQkxPQ0s6IDE1MSwKICAgICAgICBWS19GT1JNQVRfRVRDMl9SOEc4QjhBOF9TUkdCX0JMT0NLOiAxNTIsCiAgICAgICAgVktfRk9STUFUX0VBQ19SMTFfVU5PUk1fQkxPQ0s6IDE1MywKICAgICAgICBWS19GT1JNQVRfRUFDX1IxMV9TTk9STV9CTE9DSzogMTU0LAogICAgICAgIFZLX0ZPUk1BVF9FQUNfUjExRzExX1VOT1JNX0JMT0NLOiAxNTUsCiAgICAgICAgVktfRk9STUFUX0VBQ19SMTFHMTFfU05PUk1fQkxPQ0s6IDE1NiwKICAgICAgICBWS19GT1JNQVRfQVNUQ180eDRfVU5PUk1fQkxPQ0s6IDE1NywKICAgICAgICBWS19GT1JNQVRfQVNUQ180eDRfU1JHQl9CTE9DSzogMTU4LAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzV4NF9VTk9STV9CTE9DSzogMTU5LAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzV4NF9TUkdCX0JMT0NLOiAxNjAsCiAgICAgICAgVktfRk9STUFUX0FTVENfNXg1X1VOT1JNX0JMT0NLOiAxNjEsCiAgICAgICAgVktfRk9STUFUX0FTVENfNXg1X1NSR0JfQkxPQ0s6IDE2MiwKICAgICAgICBWS19GT1JNQVRfQVNUQ182eDVfVU5PUk1fQkxPQ0s6IDE2MywKICAgICAgICBWS19GT1JNQVRfQVNUQ182eDVfU1JHQl9CTE9DSzogMTY0LAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzZ4Nl9VTk9STV9CTE9DSzogMTY1LAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzZ4Nl9TUkdCX0JMT0NLOiAxNjYsCiAgICAgICAgVktfRk9STUFUX0FTVENfOHg1X1VOT1JNX0JMT0NLOiAxNjcsCiAgICAgICAgVktfRk9STUFUX0FTVENfOHg1X1NSR0JfQkxPQ0s6IDE2OCwKICAgICAgICBWS19GT1JNQVRfQVNUQ184eDZfVU5PUk1fQkxPQ0s6IDE2OSwKICAgICAgICBWS19GT1JNQVRfQVNUQ184eDZfU1JHQl9CTE9DSzogMTcwLAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzh4OF9VTk9STV9CTE9DSzogMTcxLAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzh4OF9TUkdCX0JMT0NLOiAxNzIsCiAgICAgICAgVktfRk9STUFUX0FTVENfMTB4NV9VTk9STV9CTE9DSzogMTczLAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzEweDVfU1JHQl9CTE9DSzogMTc0LAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzEweDZfVU5PUk1fQkxPQ0s6IDE3NSwKICAgICAgICBWS19GT1JNQVRfQVNUQ18xMHg2X1NSR0JfQkxPQ0s6IDE3NiwKICAgICAgICBWS19GT1JNQVRfQVNUQ18xMHg4X1VOT1JNX0JMT0NLOiAxNzcsCiAgICAgICAgVktfRk9STUFUX0FTVENfMTB4OF9TUkdCX0JMT0NLOiAxNzgsCiAgICAgICAgVktfRk9STUFUX0FTVENfMTB4MTBfVU5PUk1fQkxPQ0s6IDE3OSwKICAgICAgICBWS19GT1JNQVRfQVNUQ18xMHgxMF9TUkdCX0JMT0NLOiAxODAsCiAgICAgICAgVktfRk9STUFUX0FTVENfMTJ4MTBfVU5PUk1fQkxPQ0s6IDE4MSwKICAgICAgICBWS19GT1JNQVRfQVNUQ18xMngxMF9TUkdCX0JMT0NLOiAxODIsCiAgICAgICAgVktfRk9STUFUX0FTVENfMTJ4MTJfVU5PUk1fQkxPQ0s6IDE4MywKICAgICAgICBWS19GT1JNQVRfQVNUQ18xMngxMl9TUkdCX0JMT0NLOiAxODQsCiAgICAgICAgVktfRk9STUFUX0c4QjhHOFI4XzQyMl9VTk9STTogMTAwMDE1NmUzLAogICAgICAgIFZLX0ZPUk1BVF9COEc4UjhHOF80MjJfVU5PUk06IDEwMDAxNTYwMDEsCiAgICAgICAgVktfRk9STUFUX0c4X0I4X1I4XzNQTEFORV80MjBfVU5PUk06IDEwMDAxNTYwMDIsCiAgICAgICAgVktfRk9STUFUX0c4X0I4UjhfMlBMQU5FXzQyMF9VTk9STTogMTAwMDE1NjAwMywKICAgICAgICBWS19GT1JNQVRfRzhfQjhfUjhfM1BMQU5FXzQyMl9VTk9STTogMTAwMDE1NjAwNCwKICAgICAgICBWS19GT1JNQVRfRzhfQjhSOF8yUExBTkVfNDIyX1VOT1JNOiAxMDAwMTU2MDA1LAogICAgICAgIFZLX0ZPUk1BVF9HOF9COF9SOF8zUExBTkVfNDQ0X1VOT1JNOiAxMDAwMTU2MDA2LAogICAgICAgIFZLX0ZPUk1BVF9SMTBYNl9VTk9STV9QQUNLMTY6IDEwMDAxNTYwMDcsCiAgICAgICAgVktfRk9STUFUX1IxMFg2RzEwWDZfVU5PUk1fMlBBQ0sxNjogMTAwMDE1NjAwOCwKICAgICAgICBWS19GT1JNQVRfUjEwWDZHMTBYNkIxMFg2QTEwWDZfVU5PUk1fNFBBQ0sxNjogMTAwMDE1NjAwOSwKICAgICAgICBWS19GT1JNQVRfRzEwWDZCMTBYNkcxMFg2UjEwWDZfNDIyX1VOT1JNXzRQQUNLMTY6IDEwMDAxNTYwMTAsCiAgICAgICAgVktfRk9STUFUX0IxMFg2RzEwWDZSMTBYNkcxMFg2XzQyMl9VTk9STV80UEFDSzE2OiAxMDAwMTU2MDExLAogICAgICAgIFZLX0ZPUk1BVF9HMTBYNl9CMTBYNl9SMTBYNl8zUExBTkVfNDIwX1VOT1JNXzNQQUNLMTY6IDEwMDAxNTYwMTIsCiAgICAgICAgVktfRk9STUFUX0cxMFg2X0IxMFg2UjEwWDZfMlBMQU5FXzQyMF9VTk9STV8zUEFDSzE2OiAxMDAwMTU2MDEzLAogICAgICAgIFZLX0ZPUk1BVF9HMTBYNl9CMTBYNl9SMTBYNl8zUExBTkVfNDIyX1VOT1JNXzNQQUNLMTY6IDEwMDAxNTYwMTQsCiAgICAgICAgVktfRk9STUFUX0cxMFg2X0IxMFg2UjEwWDZfMlBMQU5FXzQyMl9VTk9STV8zUEFDSzE2OiAxMDAwMTU2MDE1LAogICAgICAgIFZLX0ZPUk1BVF9HMTBYNl9CMTBYNl9SMTBYNl8zUExBTkVfNDQ0X1VOT1JNXzNQQUNLMTY6IDEwMDAxNTYwMTYsCiAgICAgICAgVktfRk9STUFUX1IxMlg0X1VOT1JNX1BBQ0sxNjogMTAwMDE1NjAxNywKICAgICAgICBWS19GT1JNQVRfUjEyWDRHMTJYNF9VTk9STV8yUEFDSzE2OiAxMDAwMTU2MDE4LAogICAgICAgIFZLX0ZPUk1BVF9SMTJYNEcxMlg0QjEyWDRBMTJYNF9VTk9STV80UEFDSzE2OiAxMDAwMTU2MDE5LAogICAgICAgIFZLX0ZPUk1BVF9HMTJYNEIxMlg0RzEyWDRSMTJYNF80MjJfVU5PUk1fNFBBQ0sxNjogMTAwMDE1NjAyMCwKICAgICAgICBWS19GT1JNQVRfQjEyWDRHMTJYNFIxMlg0RzEyWDRfNDIyX1VOT1JNXzRQQUNLMTY6IDEwMDAxNTYwMjEsCiAgICAgICAgVktfRk9STUFUX0cxMlg0X0IxMlg0X1IxMlg0XzNQTEFORV80MjBfVU5PUk1fM1BBQ0sxNjogMTAwMDE1NjAyMiwKICAgICAgICBWS19GT1JNQVRfRzEyWDRfQjEyWDRSMTJYNF8yUExBTkVfNDIwX1VOT1JNXzNQQUNLMTY6IDEwMDAxNTYwMjMsCiAgICAgICAgVktfRk9STUFUX0cxMlg0X0IxMlg0X1IxMlg0XzNQTEFORV80MjJfVU5PUk1fM1BBQ0sxNjogMTAwMDE1NjAyNCwKICAgICAgICBWS19GT1JNQVRfRzEyWDRfQjEyWDRSMTJYNF8yUExBTkVfNDIyX1VOT1JNXzNQQUNLMTY6IDEwMDAxNTYwMjUsCiAgICAgICAgVktfRk9STUFUX0cxMlg0X0IxMlg0X1IxMlg0XzNQTEFORV80NDRfVU5PUk1fM1BBQ0sxNjogMTAwMDE1NjAyNiwKICAgICAgICBWS19GT1JNQVRfRzE2QjE2RzE2UjE2XzQyMl9VTk9STTogMTAwMDE1NjAyNywKICAgICAgICBWS19GT1JNQVRfQjE2RzE2UjE2RzE2XzQyMl9VTk9STTogMTAwMDE1NjAyOCwKICAgICAgICBWS19GT1JNQVRfRzE2X0IxNl9SMTZfM1BMQU5FXzQyMF9VTk9STTogMTAwMDE1NjAyOSwKICAgICAgICBWS19GT1JNQVRfRzE2X0IxNlIxNl8yUExBTkVfNDIwX1VOT1JNOiAxMDAwMTU2MDMwLAogICAgICAgIFZLX0ZPUk1BVF9HMTZfQjE2X1IxNl8zUExBTkVfNDIyX1VOT1JNOiAxMDAwMTU2MDMxLAogICAgICAgIFZLX0ZPUk1BVF9HMTZfQjE2UjE2XzJQTEFORV80MjJfVU5PUk06IDEwMDAxNTYwMzIsCiAgICAgICAgVktfRk9STUFUX0cxNl9CMTZfUjE2XzNQTEFORV80NDRfVU5PUk06IDEwMDAxNTYwMzMsCiAgICAgICAgVktfRk9STUFUX1BWUlRDMV8yQlBQX1VOT1JNX0JMT0NLX0lNRzogMTAwMDA1NGUzLAogICAgICAgIFZLX0ZPUk1BVF9QVlJUQzFfNEJQUF9VTk9STV9CTE9DS19JTUc6IDEwMDAwNTQwMDEsCiAgICAgICAgVktfRk9STUFUX1BWUlRDMl8yQlBQX1VOT1JNX0JMT0NLX0lNRzogMTAwMDA1NDAwMiwKICAgICAgICBWS19GT1JNQVRfUFZSVEMyXzRCUFBfVU5PUk1fQkxPQ0tfSU1HOiAxMDAwMDU0MDAzLAogICAgICAgIFZLX0ZPUk1BVF9QVlJUQzFfMkJQUF9TUkdCX0JMT0NLX0lNRzogMTAwMDA1NDAwNCwKICAgICAgICBWS19GT1JNQVRfUFZSVEMxXzRCUFBfU1JHQl9CTE9DS19JTUc6IDEwMDAwNTQwMDUsCiAgICAgICAgVktfRk9STUFUX1BWUlRDMl8yQlBQX1NSR0JfQkxPQ0tfSU1HOiAxMDAwMDU0MDA2LAogICAgICAgIFZLX0ZPUk1BVF9QVlJUQzJfNEJQUF9TUkdCX0JMT0NLX0lNRzogMTAwMDA1NDAwNywKICAgICAgICBWS19GT1JNQVRfQVNUQ180eDRfU0ZMT0FUX0JMT0NLX0VYVDogMTAwMDA2NmUzLAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzV4NF9TRkxPQVRfQkxPQ0tfRVhUOiAxMDAwMDY2MDAxLAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzV4NV9TRkxPQVRfQkxPQ0tfRVhUOiAxMDAwMDY2MDAyLAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzZ4NV9TRkxPQVRfQkxPQ0tfRVhUOiAxMDAwMDY2MDAzLAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzZ4Nl9TRkxPQVRfQkxPQ0tfRVhUOiAxMDAwMDY2MDA0LAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzh4NV9TRkxPQVRfQkxPQ0tfRVhUOiAxMDAwMDY2MDA1LAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzh4Nl9TRkxPQVRfQkxPQ0tfRVhUOiAxMDAwMDY2MDA2LAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzh4OF9TRkxPQVRfQkxPQ0tfRVhUOiAxMDAwMDY2MDA3LAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzEweDVfU0ZMT0FUX0JMT0NLX0VYVDogMTAwMDA2NjAwOCwKICAgICAgICBWS19GT1JNQVRfQVNUQ18xMHg2X1NGTE9BVF9CTE9DS19FWFQ6IDEwMDAwNjYwMDksCiAgICAgICAgVktfRk9STUFUX0FTVENfMTB4OF9TRkxPQVRfQkxPQ0tfRVhUOiAxMDAwMDY2MDEwLAogICAgICAgIFZLX0ZPUk1BVF9BU1RDXzEweDEwX1NGTE9BVF9CTE9DS19FWFQ6IDEwMDAwNjYwMTEsCiAgICAgICAgVktfRk9STUFUX0FTVENfMTJ4MTBfU0ZMT0FUX0JMT0NLX0VYVDogMTAwMDA2NjAxMiwKICAgICAgICBWS19GT1JNQVRfQVNUQ18xMngxMl9TRkxPQVRfQkxPQ0tfRVhUOiAxMDAwMDY2MDEzLAogICAgICAgIFZLX0ZPUk1BVF9HOEI4RzhSOF80MjJfVU5PUk1fS0hSOiAxMDAwMTU2ZTMsCiAgICAgICAgVktfRk9STUFUX0I4RzhSOEc4XzQyMl9VTk9STV9LSFI6IDEwMDAxNTYwMDEsCiAgICAgICAgVktfRk9STUFUX0c4X0I4X1I4XzNQTEFORV80MjBfVU5PUk1fS0hSOiAxMDAwMTU2MDAyLAogICAgICAgIFZLX0ZPUk1BVF9HOF9COFI4XzJQTEFORV80MjBfVU5PUk1fS0hSOiAxMDAwMTU2MDAzLAogICAgICAgIFZLX0ZPUk1BVF9HOF9COF9SOF8zUExBTkVfNDIyX1VOT1JNX0tIUjogMTAwMDE1NjAwNCwKICAgICAgICBWS19GT1JNQVRfRzhfQjhSOF8yUExBTkVfNDIyX1VOT1JNX0tIUjogMTAwMDE1NjAwNSwKICAgICAgICBWS19GT1JNQVRfRzhfQjhfUjhfM1BMQU5FXzQ0NF9VTk9STV9LSFI6IDEwMDAxNTYwMDYsCiAgICAgICAgVktfRk9STUFUX1IxMFg2X1VOT1JNX1BBQ0sxNl9LSFI6IDEwMDAxNTYwMDcsCiAgICAgICAgVktfRk9STUFUX1IxMFg2RzEwWDZfVU5PUk1fMlBBQ0sxNl9LSFI6IDEwMDAxNTYwMDgsCiAgICAgICAgVktfRk9STUFUX1IxMFg2RzEwWDZCMTBYNkExMFg2X1VOT1JNXzRQQUNLMTZfS0hSOiAxMDAwMTU2MDA5LAogICAgICAgIFZLX0ZPUk1BVF9HMTBYNkIxMFg2RzEwWDZSMTBYNl80MjJfVU5PUk1fNFBBQ0sxNl9LSFI6IDEwMDAxNTYwMTAsCiAgICAgICAgVktfRk9STUFUX0IxMFg2RzEwWDZSMTBYNkcxMFg2XzQyMl9VTk9STV80UEFDSzE2X0tIUjogMTAwMDE1NjAxMSwKICAgICAgICBWS19GT1JNQVRfRzEwWDZfQjEwWDZfUjEwWDZfM1BMQU5FXzQyMF9VTk9STV8zUEFDSzE2X0tIUjogMTAwMDE1NjAxMiwKICAgICAgICBWS19GT1JNQVRfRzEwWDZfQjEwWDZSMTBYNl8yUExBTkVfNDIwX1VOT1JNXzNQQUNLMTZfS0hSOiAxMDAwMTU2MDEzLAogICAgICAgIFZLX0ZPUk1BVF9HMTBYNl9CMTBYNl9SMTBYNl8zUExBTkVfNDIyX1VOT1JNXzNQQUNLMTZfS0hSOiAxMDAwMTU2MDE0LAogICAgICAgIFZLX0ZPUk1BVF9HMTBYNl9CMTBYNlIxMFg2XzJQTEFORV80MjJfVU5PUk1fM1BBQ0sxNl9LSFI6IDEwMDAxNTYwMTUsCiAgICAgICAgVktfRk9STUFUX0cxMFg2X0IxMFg2X1IxMFg2XzNQTEFORV80NDRfVU5PUk1fM1BBQ0sxNl9LSFI6IDEwMDAxNTYwMTYsCiAgICAgICAgVktfRk9STUFUX1IxMlg0X1VOT1JNX1BBQ0sxNl9LSFI6IDEwMDAxNTYwMTcsCiAgICAgICAgVktfRk9STUFUX1IxMlg0RzEyWDRfVU5PUk1fMlBBQ0sxNl9LSFI6IDEwMDAxNTYwMTgsCiAgICAgICAgVktfRk9STUFUX1IxMlg0RzEyWDRCMTJYNEExMlg0X1VOT1JNXzRQQUNLMTZfS0hSOiAxMDAwMTU2MDE5LAogICAgICAgIFZLX0ZPUk1BVF9HMTJYNEIxMlg0RzEyWDRSMTJYNF80MjJfVU5PUk1fNFBBQ0sxNl9LSFI6IDEwMDAxNTYwMjAsCiAgICAgICAgVktfRk9STUFUX0IxMlg0RzEyWDRSMTJYNEcxMlg0XzQyMl9VTk9STV80UEFDSzE2X0tIUjogMTAwMDE1NjAyMSwKICAgICAgICBWS19GT1JNQVRfRzEyWDRfQjEyWDRfUjEyWDRfM1BMQU5FXzQyMF9VTk9STV8zUEFDSzE2X0tIUjogMTAwMDE1NjAyMiwKICAgICAgICBWS19GT1JNQVRfRzEyWDRfQjEyWDRSMTJYNF8yUExBTkVfNDIwX1VOT1JNXzNQQUNLMTZfS0hSOiAxMDAwMTU2MDIzLAogICAgICAgIFZLX0ZPUk1BVF9HMTJYNF9CMTJYNF9SMTJYNF8zUExBTkVfNDIyX1VOT1JNXzNQQUNLMTZfS0hSOiAxMDAwMTU2MDI0LAogICAgICAgIFZLX0ZPUk1BVF9HMTJYNF9CMTJYNFIxMlg0XzJQTEFORV80MjJfVU5PUk1fM1BBQ0sxNl9LSFI6IDEwMDAxNTYwMjUsCiAgICAgICAgVktfRk9STUFUX0cxMlg0X0IxMlg0X1IxMlg0XzNQTEFORV80NDRfVU5PUk1fM1BBQ0sxNl9LSFI6IDEwMDAxNTYwMjYsCiAgICAgICAgVktfRk9STUFUX0cxNkIxNkcxNlIxNl80MjJfVU5PUk1fS0hSOiAxMDAwMTU2MDI3LAogICAgICAgIFZLX0ZPUk1BVF9CMTZHMTZSMTZHMTZfNDIyX1VOT1JNX0tIUjogMTAwMDE1NjAyOCwKICAgICAgICBWS19GT1JNQVRfRzE2X0IxNl9SMTZfM1BMQU5FXzQyMF9VTk9STV9LSFI6IDEwMDAxNTYwMjksCiAgICAgICAgVktfRk9STUFUX0cxNl9CMTZSMTZfMlBMQU5FXzQyMF9VTk9STV9LSFI6IDEwMDAxNTYwMzAsCiAgICAgICAgVktfRk9STUFUX0cxNl9CMTZfUjE2XzNQTEFORV80MjJfVU5PUk1fS0hSOiAxMDAwMTU2MDMxLAogICAgICAgIFZLX0ZPUk1BVF9HMTZfQjE2UjE2XzJQTEFORV80MjJfVU5PUk1fS0hSOiAxMDAwMTU2MDMyLAogICAgICAgIFZLX0ZPUk1BVF9HMTZfQjE2X1IxNl8zUExBTkVfNDQ0X1VOT1JNX0tIUjogMTAwMDE1NjAzMwogICAgICB9OwogICAgICBWdWxrYW5Db25zdGFudHNfZGVmYXVsdCA9IE9iamVjdC5mcmVlemUoVnVsa2FuQ29uc3RhbnRzKTsKICAgIH0KICB9KTsKCiAgLy8gbm9kZV9tb2R1bGVzL2t0eC1wYXJzZS9kaXN0L2t0eC1wYXJzZS5tb2Rlcm4uanMKICBmdW5jdGlvbiBjcmVhdGVEZWZhdWx0Q29udGFpbmVyKCkgewogICAgcmV0dXJuIHsKICAgICAgdmtGb3JtYXQ6IFZLX0ZPUk1BVF9VTkRFRklORUQsCiAgICAgIHR5cGVTaXplOiAxLAogICAgICBwaXhlbFdpZHRoOiAwLAogICAgICBwaXhlbEhlaWdodDogMCwKICAgICAgcGl4ZWxEZXB0aDogMCwKICAgICAgbGF5ZXJDb3VudDogMCwKICAgICAgZmFjZUNvdW50OiAxLAogICAgICBsZXZlbENvdW50OiAwLAogICAgICBzdXBlcmNvbXByZXNzaW9uU2NoZW1lOiBLSFJfU1VQRVJDT01QUkVTU0lPTl9OT05FLAogICAgICBsZXZlbHM6IFtdLAogICAgICBkYXRhRm9ybWF0RGVzY3JpcHRvcjogW3sKICAgICAgICB2ZW5kb3JJZDogS0hSX0RGX1ZFTkRPUklEX0tIUk9OT1MsCiAgICAgICAgZGVzY3JpcHRvclR5cGU6IEtIUl9ERl9LSFJfREVTQ1JJUFRPUlRZUEVfQkFTSUNGT1JNQVQsCiAgICAgICAgdmVyc2lvbk51bWJlcjogS0hSX0RGX1ZFUlNJT04sCiAgICAgICAgY29sb3JNb2RlbDogS0hSX0RGX01PREVMX1VOU1BFQ0lGSUVELAogICAgICAgIGNvbG9yUHJpbWFyaWVzOiBLSFJfREZfUFJJTUFSSUVTX0JUNzA5LAogICAgICAgIHRyYW5zZmVyRnVuY3Rpb246IEtIUl9ERl9UUkFOU0ZFUl9TUkdCLAogICAgICAgIGZsYWdzOiBLSFJfREZfRkxBR19BTFBIQV9TVFJBSUdIVCwKICAgICAgICB0ZXhlbEJsb2NrRGltZW5zaW9uOiBbMCwgMCwgMCwgMF0sCiAgICAgICAgYnl0ZXNQbGFuZTogWzAsIDAsIDAsIDAsIDAsIDAsIDAsIDBdLAogICAgICAgIHNhbXBsZXM6IFtdCiAgICAgIH1dLAogICAgICBrZXlWYWx1ZToge30sCiAgICAgIGdsb2JhbERhdGE6IG51bGwKICAgIH07CiAgfQogIGZ1bmN0aW9uIGRlY29kZVRleHQoYnVmZmVyKSB7CiAgICByZXR1cm4gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGJ1ZmZlcik7CiAgfQogIGZ1bmN0aW9uIHJlYWQyKGRhdGEpIHsKICAgIGNvbnN0IGlkID0gbmV3IFVpbnQ4QXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCwgS1RYMl9JRC5sZW5ndGgpOwogICAgaWYgKGlkWzBdICE9PSBLVFgyX0lEWzBdIHx8IC8vICfCtCcKICAgIGlkWzFdICE9PSBLVFgyX0lEWzFdIHx8IC8vICdLJwogICAgaWRbMl0gIT09IEtUWDJfSURbMl0gfHwgLy8gJ1QnCiAgICBpZFszXSAhPT0gS1RYMl9JRFszXSB8fCAvLyAnWCcKICAgIGlkWzRdICE9PSBLVFgyX0lEWzRdIHx8IC8vICcgJwogICAgaWRbNV0gIT09IEtUWDJfSURbNV0gfHwgLy8gJzInCiAgICBpZFs2XSAhPT0gS1RYMl9JRFs2XSB8fCAvLyAnMCcKICAgIGlkWzddICE9PSBLVFgyX0lEWzddIHx8IC8vICfCqicKICAgIGlkWzhdICE9PSBLVFgyX0lEWzhdIHx8IC8vICdccicKICAgIGlkWzldICE9PSBLVFgyX0lEWzldIHx8IC8vICdcbicKICAgIGlkWzEwXSAhPT0gS1RYMl9JRFsxMF0gfHwgLy8gJ1x4MUEnCiAgICBpZFsxMV0gIT09IEtUWDJfSURbMTFdKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiTWlzc2luZyBLVFggMi4wIGlkZW50aWZpZXIuIik7CiAgICB9CiAgICBjb25zdCBjb250YWluZXIgPSBjcmVhdGVEZWZhdWx0Q29udGFpbmVyKCk7CiAgICBjb25zdCBoZWFkZXJCeXRlTGVuZ3RoID0gMTcgKiBVaW50MzJBcnJheS5CWVRFU19QRVJfRUxFTUVOVDsKICAgIGNvbnN0IGhlYWRlclJlYWRlciA9IG5ldyBCdWZmZXJSZWFkZXIoZGF0YSwgS1RYMl9JRC5sZW5ndGgsIGhlYWRlckJ5dGVMZW5ndGgsIHRydWUpOwogICAgY29udGFpbmVyLnZrRm9ybWF0ID0gaGVhZGVyUmVhZGVyLl9uZXh0VWludDMyKCk7CiAgICBjb250YWluZXIudHlwZVNpemUgPSBoZWFkZXJSZWFkZXIuX25leHRVaW50MzIoKTsKICAgIGNvbnRhaW5lci5waXhlbFdpZHRoID0gaGVhZGVyUmVhZGVyLl9uZXh0VWludDMyKCk7CiAgICBjb250YWluZXIucGl4ZWxIZWlnaHQgPSBoZWFkZXJSZWFkZXIuX25leHRVaW50MzIoKTsKICAgIGNvbnRhaW5lci5waXhlbERlcHRoID0gaGVhZGVyUmVhZGVyLl9uZXh0VWludDMyKCk7CiAgICBjb250YWluZXIubGF5ZXJDb3VudCA9IGhlYWRlclJlYWRlci5fbmV4dFVpbnQzMigpOwogICAgY29udGFpbmVyLmZhY2VDb3VudCA9IGhlYWRlclJlYWRlci5fbmV4dFVpbnQzMigpOwogICAgY29udGFpbmVyLmxldmVsQ291bnQgPSBoZWFkZXJSZWFkZXIuX25leHRVaW50MzIoKTsKICAgIGNvbnRhaW5lci5zdXBlcmNvbXByZXNzaW9uU2NoZW1lID0gaGVhZGVyUmVhZGVyLl9uZXh0VWludDMyKCk7CiAgICBjb25zdCBkZmRCeXRlT2Zmc2V0ID0gaGVhZGVyUmVhZGVyLl9uZXh0VWludDMyKCk7CiAgICBjb25zdCBkZmRCeXRlTGVuZ3RoID0gaGVhZGVyUmVhZGVyLl9uZXh0VWludDMyKCk7CiAgICBjb25zdCBrdmRCeXRlT2Zmc2V0ID0gaGVhZGVyUmVhZGVyLl9uZXh0VWludDMyKCk7CiAgICBjb25zdCBrdmRCeXRlTGVuZ3RoID0gaGVhZGVyUmVhZGVyLl9uZXh0VWludDMyKCk7CiAgICBjb25zdCBzZ2RCeXRlT2Zmc2V0ID0gaGVhZGVyUmVhZGVyLl9uZXh0VWludDY0KCk7CiAgICBjb25zdCBzZ2RCeXRlTGVuZ3RoID0gaGVhZGVyUmVhZGVyLl9uZXh0VWludDY0KCk7CiAgICBjb25zdCBsZXZlbEJ5dGVMZW5ndGggPSBNYXRoLm1heChjb250YWluZXIubGV2ZWxDb3VudCwgMSkgKiAzICogODsKICAgIGNvbnN0IGxldmVsUmVhZGVyID0gbmV3IEJ1ZmZlclJlYWRlcihkYXRhLCBLVFgyX0lELmxlbmd0aCArIGhlYWRlckJ5dGVMZW5ndGgsIGxldmVsQnl0ZUxlbmd0aCwgdHJ1ZSk7CiAgICBmb3IgKGxldCBpID0gMCwgaWwgPSBNYXRoLm1heChjb250YWluZXIubGV2ZWxDb3VudCwgMSk7IGkgPCBpbDsgaSsrKSB7CiAgICAgIGNvbnRhaW5lci5sZXZlbHMucHVzaCh7CiAgICAgICAgbGV2ZWxEYXRhOiBuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0ICsgbGV2ZWxSZWFkZXIuX25leHRVaW50NjQoKSwgbGV2ZWxSZWFkZXIuX25leHRVaW50NjQoKSksCiAgICAgICAgdW5jb21wcmVzc2VkQnl0ZUxlbmd0aDogbGV2ZWxSZWFkZXIuX25leHRVaW50NjQoKQogICAgICB9KTsKICAgIH0KICAgIGNvbnN0IGRmZFJlYWRlciA9IG5ldyBCdWZmZXJSZWFkZXIoZGF0YSwgZGZkQnl0ZU9mZnNldCwgZGZkQnl0ZUxlbmd0aCwgdHJ1ZSk7CiAgICBkZmRSZWFkZXIuX3NraXAoNCk7CiAgICBjb25zdCB2ZW5kb3JJZCA9IGRmZFJlYWRlci5fbmV4dFVpbnQxNigpOwogICAgY29uc3QgZGVzY3JpcHRvclR5cGUgPSBkZmRSZWFkZXIuX25leHRVaW50MTYoKTsKICAgIGNvbnN0IHZlcnNpb25OdW1iZXIgPSBkZmRSZWFkZXIuX25leHRVaW50MTYoKTsKICAgIGNvbnN0IGRlc2NyaXB0b3JCbG9ja1NpemUgPSBkZmRSZWFkZXIuX25leHRVaW50MTYoKTsKICAgIGNvbnN0IGNvbG9yTW9kZWwgPSBkZmRSZWFkZXIuX25leHRVaW50OCgpOwogICAgY29uc3QgY29sb3JQcmltYXJpZXMgPSBkZmRSZWFkZXIuX25leHRVaW50OCgpOwogICAgY29uc3QgdHJhbnNmZXJGdW5jdGlvbiA9IGRmZFJlYWRlci5fbmV4dFVpbnQ4KCk7CiAgICBjb25zdCBmbGFncyA9IGRmZFJlYWRlci5fbmV4dFVpbnQ4KCk7CiAgICBjb25zdCB0ZXhlbEJsb2NrRGltZW5zaW9uID0gW2RmZFJlYWRlci5fbmV4dFVpbnQ4KCksIGRmZFJlYWRlci5fbmV4dFVpbnQ4KCksIGRmZFJlYWRlci5fbmV4dFVpbnQ4KCksIGRmZFJlYWRlci5fbmV4dFVpbnQ4KCldOwogICAgY29uc3QgYnl0ZXNQbGFuZSA9IFtkZmRSZWFkZXIuX25leHRVaW50OCgpLCBkZmRSZWFkZXIuX25leHRVaW50OCgpLCBkZmRSZWFkZXIuX25leHRVaW50OCgpLCBkZmRSZWFkZXIuX25leHRVaW50OCgpLCBkZmRSZWFkZXIuX25leHRVaW50OCgpLCBkZmRSZWFkZXIuX25leHRVaW50OCgpLCBkZmRSZWFkZXIuX25leHRVaW50OCgpLCBkZmRSZWFkZXIuX25leHRVaW50OCgpXTsKICAgIGNvbnN0IHNhbXBsZXMgPSBbXTsKICAgIGNvbnN0IGRmZCA9IHsKICAgICAgdmVuZG9ySWQsCiAgICAgIGRlc2NyaXB0b3JUeXBlLAogICAgICB2ZXJzaW9uTnVtYmVyLAogICAgICBjb2xvck1vZGVsLAogICAgICBjb2xvclByaW1hcmllcywKICAgICAgdHJhbnNmZXJGdW5jdGlvbiwKICAgICAgZmxhZ3MsCiAgICAgIHRleGVsQmxvY2tEaW1lbnNpb24sCiAgICAgIGJ5dGVzUGxhbmUsCiAgICAgIHNhbXBsZXMKICAgIH07CiAgICBjb25zdCBzYW1wbGVTdGFydCA9IDY7CiAgICBjb25zdCBzYW1wbGVXb3JkcyA9IDQ7CiAgICBjb25zdCBudW1TYW1wbGVzID0gKGRlc2NyaXB0b3JCbG9ja1NpemUgLyA0IC0gc2FtcGxlU3RhcnQpIC8gc2FtcGxlV29yZHM7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bVNhbXBsZXM7IGkrKykgewogICAgICBjb25zdCBzYW1wbGUgPSB7CiAgICAgICAgYml0T2Zmc2V0OiBkZmRSZWFkZXIuX25leHRVaW50MTYoKSwKICAgICAgICBiaXRMZW5ndGg6IGRmZFJlYWRlci5fbmV4dFVpbnQ4KCksCiAgICAgICAgY2hhbm5lbFR5cGU6IGRmZFJlYWRlci5fbmV4dFVpbnQ4KCksCiAgICAgICAgc2FtcGxlUG9zaXRpb246IFtkZmRSZWFkZXIuX25leHRVaW50OCgpLCBkZmRSZWFkZXIuX25leHRVaW50OCgpLCBkZmRSZWFkZXIuX25leHRVaW50OCgpLCBkZmRSZWFkZXIuX25leHRVaW50OCgpXSwKICAgICAgICBzYW1wbGVMb3dlcjogTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZLAogICAgICAgIHNhbXBsZVVwcGVyOiBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkKICAgICAgfTsKICAgICAgaWYgKHNhbXBsZS5jaGFubmVsVHlwZSAmIEtIUl9ERl9TQU1QTEVfREFUQVRZUEVfU0lHTkVEKSB7CiAgICAgICAgc2FtcGxlLnNhbXBsZUxvd2VyID0gZGZkUmVhZGVyLl9uZXh0SW50MzIoKTsKICAgICAgICBzYW1wbGUuc2FtcGxlVXBwZXIgPSBkZmRSZWFkZXIuX25leHRJbnQzMigpOwogICAgICB9IGVsc2UgewogICAgICAgIHNhbXBsZS5zYW1wbGVMb3dlciA9IGRmZFJlYWRlci5fbmV4dFVpbnQzMigpOwogICAgICAgIHNhbXBsZS5zYW1wbGVVcHBlciA9IGRmZFJlYWRlci5fbmV4dFVpbnQzMigpOwogICAgICB9CiAgICAgIGRmZC5zYW1wbGVzW2ldID0gc2FtcGxlOwogICAgfQogICAgY29udGFpbmVyLmRhdGFGb3JtYXREZXNjcmlwdG9yLmxlbmd0aCA9IDA7CiAgICBjb250YWluZXIuZGF0YUZvcm1hdERlc2NyaXB0b3IucHVzaChkZmQpOwogICAgY29uc3Qga3ZkUmVhZGVyID0gbmV3IEJ1ZmZlclJlYWRlcihkYXRhLCBrdmRCeXRlT2Zmc2V0LCBrdmRCeXRlTGVuZ3RoLCB0cnVlKTsKICAgIHdoaWxlIChrdmRSZWFkZXIuX29mZnNldCA8IGt2ZEJ5dGVMZW5ndGgpIHsKICAgICAgY29uc3Qga2V5VmFsdWVCeXRlTGVuZ3RoID0ga3ZkUmVhZGVyLl9uZXh0VWludDMyKCk7CiAgICAgIGNvbnN0IGtleURhdGEgPSBrdmRSZWFkZXIuX3NjYW4oa2V5VmFsdWVCeXRlTGVuZ3RoKTsKICAgICAgY29uc3Qga2V5ID0gZGVjb2RlVGV4dChrZXlEYXRhKTsKICAgICAgY29udGFpbmVyLmtleVZhbHVlW2tleV0gPSBrdmRSZWFkZXIuX25leHRVaW50OEFycmF5KGtleVZhbHVlQnl0ZUxlbmd0aCAtIGtleURhdGEuYnl0ZUxlbmd0aCAtIDEpOwogICAgICBpZiAoa2V5Lm1hdGNoKC9ea3R4L2kpKSB7CiAgICAgICAgY29uc3QgdGV4dCA9IGRlY29kZVRleHQoY29udGFpbmVyLmtleVZhbHVlW2tleV0pOwogICAgICAgIGNvbnRhaW5lci5rZXlWYWx1ZVtrZXldID0gdGV4dC5zdWJzdHJpbmcoMCwgdGV4dC5sYXN0SW5kZXhPZigiXDAiKSk7CiAgICAgIH0KICAgICAgY29uc3Qga3ZQYWRkaW5nID0ga2V5VmFsdWVCeXRlTGVuZ3RoICUgNCA/IDQgLSBrZXlWYWx1ZUJ5dGVMZW5ndGggJSA0IDogMDsKICAgICAga3ZkUmVhZGVyLl9za2lwKGt2UGFkZGluZyk7CiAgICB9CiAgICBpZiAoc2dkQnl0ZUxlbmd0aCA8PSAwKSByZXR1cm4gY29udGFpbmVyOwogICAgY29uc3Qgc2dkUmVhZGVyID0gbmV3IEJ1ZmZlclJlYWRlcihkYXRhLCBzZ2RCeXRlT2Zmc2V0LCBzZ2RCeXRlTGVuZ3RoLCB0cnVlKTsKICAgIGNvbnN0IGVuZHBvaW50Q291bnQgPSBzZ2RSZWFkZXIuX25leHRVaW50MTYoKTsKICAgIGNvbnN0IHNlbGVjdG9yQ291bnQgPSBzZ2RSZWFkZXIuX25leHRVaW50MTYoKTsKICAgIGNvbnN0IGVuZHBvaW50c0J5dGVMZW5ndGggPSBzZ2RSZWFkZXIuX25leHRVaW50MzIoKTsKICAgIGNvbnN0IHNlbGVjdG9yc0J5dGVMZW5ndGggPSBzZ2RSZWFkZXIuX25leHRVaW50MzIoKTsKICAgIGNvbnN0IHRhYmxlc0J5dGVMZW5ndGggPSBzZ2RSZWFkZXIuX25leHRVaW50MzIoKTsKICAgIGNvbnN0IGV4dGVuZGVkQnl0ZUxlbmd0aCA9IHNnZFJlYWRlci5fbmV4dFVpbnQzMigpOwogICAgY29uc3QgaW1hZ2VEZXNjcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDAsIGlsID0gTWF0aC5tYXgoY29udGFpbmVyLmxldmVsQ291bnQsIDEpOyBpIDwgaWw7IGkrKykgewogICAgICBpbWFnZURlc2NzLnB1c2goewogICAgICAgIGltYWdlRmxhZ3M6IHNnZFJlYWRlci5fbmV4dFVpbnQzMigpLAogICAgICAgIHJnYlNsaWNlQnl0ZU9mZnNldDogc2dkUmVhZGVyLl9uZXh0VWludDMyKCksCiAgICAgICAgcmdiU2xpY2VCeXRlTGVuZ3RoOiBzZ2RSZWFkZXIuX25leHRVaW50MzIoKSwKICAgICAgICBhbHBoYVNsaWNlQnl0ZU9mZnNldDogc2dkUmVhZGVyLl9uZXh0VWludDMyKCksCiAgICAgICAgYWxwaGFTbGljZUJ5dGVMZW5ndGg6IHNnZFJlYWRlci5fbmV4dFVpbnQzMigpCiAgICAgIH0pOwogICAgfQogICAgY29uc3QgZW5kcG9pbnRzQnl0ZU9mZnNldCA9IHNnZEJ5dGVPZmZzZXQgKyBzZ2RSZWFkZXIuX29mZnNldDsKICAgIGNvbnN0IHNlbGVjdG9yc0J5dGVPZmZzZXQgPSBlbmRwb2ludHNCeXRlT2Zmc2V0ICsgZW5kcG9pbnRzQnl0ZUxlbmd0aDsKICAgIGNvbnN0IHRhYmxlc0J5dGVPZmZzZXQgPSBzZWxlY3RvcnNCeXRlT2Zmc2V0ICsgc2VsZWN0b3JzQnl0ZUxlbmd0aDsKICAgIGNvbnN0IGV4dGVuZGVkQnl0ZU9mZnNldCA9IHRhYmxlc0J5dGVPZmZzZXQgKyB0YWJsZXNCeXRlTGVuZ3RoOwogICAgY29uc3QgZW5kcG9pbnRzRGF0YSA9IG5ldyBVaW50OEFycmF5KGRhdGEuYnVmZmVyLCBkYXRhLmJ5dGVPZmZzZXQgKyBlbmRwb2ludHNCeXRlT2Zmc2V0LCBlbmRwb2ludHNCeXRlTGVuZ3RoKTsKICAgIGNvbnN0IHNlbGVjdG9yc0RhdGEgPSBuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0ICsgc2VsZWN0b3JzQnl0ZU9mZnNldCwgc2VsZWN0b3JzQnl0ZUxlbmd0aCk7CiAgICBjb25zdCB0YWJsZXNEYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCArIHRhYmxlc0J5dGVPZmZzZXQsIHRhYmxlc0J5dGVMZW5ndGgpOwogICAgY29uc3QgZXh0ZW5kZWREYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCArIGV4dGVuZGVkQnl0ZU9mZnNldCwgZXh0ZW5kZWRCeXRlTGVuZ3RoKTsKICAgIGNvbnRhaW5lci5nbG9iYWxEYXRhID0gewogICAgICBlbmRwb2ludENvdW50LAogICAgICBzZWxlY3RvckNvdW50LAogICAgICBpbWFnZURlc2NzLAogICAgICBlbmRwb2ludHNEYXRhLAogICAgICBzZWxlY3RvcnNEYXRhLAogICAgICB0YWJsZXNEYXRhLAogICAgICBleHRlbmRlZERhdGEKICAgIH07CiAgICByZXR1cm4gY29udGFpbmVyOwogIH0KICB2YXIgS0hSX1NVUEVSQ09NUFJFU1NJT05fTk9ORSwgS0hSX0RGX0tIUl9ERVNDUklQVE9SVFlQRV9CQVNJQ0ZPUk1BVCwgS0hSX0RGX1ZFTkRPUklEX0tIUk9OT1MsIEtIUl9ERl9WRVJTSU9OLCBLSFJfREZfTU9ERUxfVU5TUEVDSUZJRUQsIEtIUl9ERl9GTEFHX0FMUEhBX1NUUkFJR0hULCBLSFJfREZfVFJBTlNGRVJfU1JHQiwgS0hSX0RGX1BSSU1BUklFU19CVDcwOSwgS0hSX0RGX1NBTVBMRV9EQVRBVFlQRV9TSUdORUQsIFZLX0ZPUk1BVF9VTkRFRklORUQsIEJ1ZmZlclJlYWRlciwgTlVMLCBLVFgyX0lEOwogIHZhciBpbml0X2t0eF9wYXJzZV9tb2Rlcm4gPSBfX2VzbSh7CiAgICAibm9kZV9tb2R1bGVzL2t0eC1wYXJzZS9kaXN0L2t0eC1wYXJzZS5tb2Rlcm4uanMiKCkgewogICAgICBLSFJfU1VQRVJDT01QUkVTU0lPTl9OT05FID0gMDsKICAgICAgS0hSX0RGX0tIUl9ERVNDUklQVE9SVFlQRV9CQVNJQ0ZPUk1BVCA9IDA7CiAgICAgIEtIUl9ERl9WRU5ET1JJRF9LSFJPTk9TID0gMDsKICAgICAgS0hSX0RGX1ZFUlNJT04gPSAyOwogICAgICBLSFJfREZfTU9ERUxfVU5TUEVDSUZJRUQgPSAwOwogICAgICBLSFJfREZfRkxBR19BTFBIQV9TVFJBSUdIVCA9IDA7CiAgICAgIEtIUl9ERl9UUkFOU0ZFUl9TUkdCID0gMjsKICAgICAgS0hSX0RGX1BSSU1BUklFU19CVDcwOSA9IDE7CiAgICAgIEtIUl9ERl9TQU1QTEVfREFUQVRZUEVfU0lHTkVEID0gNjQ7CiAgICAgIFZLX0ZPUk1BVF9VTkRFRklORUQgPSAwOwogICAgICBCdWZmZXJSZWFkZXIgPSBjbGFzcyB7CiAgICAgICAgY29uc3RydWN0b3IoZGF0YSwgYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCwgbGl0dGxlRW5kaWFuMikgewogICAgICAgICAgdGhpcy5fZGF0YVZpZXcgPSB2b2lkIDA7CiAgICAgICAgICB0aGlzLl9saXR0bGVFbmRpYW4gPSB2b2lkIDA7CiAgICAgICAgICB0aGlzLl9vZmZzZXQgPSB2b2lkIDA7CiAgICAgICAgICB0aGlzLl9kYXRhVmlldyA9IG5ldyBEYXRhVmlldyhkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0ICsgYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCk7CiAgICAgICAgICB0aGlzLl9saXR0bGVFbmRpYW4gPSBsaXR0bGVFbmRpYW4yOwogICAgICAgICAgdGhpcy5fb2Zmc2V0ID0gMDsKICAgICAgICB9CiAgICAgICAgX25leHRVaW50OCgpIHsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5fZGF0YVZpZXcuZ2V0VWludDgodGhpcy5fb2Zmc2V0KTsKICAgICAgICAgIHRoaXMuX29mZnNldCArPSAxOwogICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgIH0KICAgICAgICBfbmV4dFVpbnQxNigpIHsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5fZGF0YVZpZXcuZ2V0VWludDE2KHRoaXMuX29mZnNldCwgdGhpcy5fbGl0dGxlRW5kaWFuKTsKICAgICAgICAgIHRoaXMuX29mZnNldCArPSAyOwogICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgIH0KICAgICAgICBfbmV4dFVpbnQzMigpIHsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5fZGF0YVZpZXcuZ2V0VWludDMyKHRoaXMuX29mZnNldCwgdGhpcy5fbGl0dGxlRW5kaWFuKTsKICAgICAgICAgIHRoaXMuX29mZnNldCArPSA0OwogICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgIH0KICAgICAgICBfbmV4dFVpbnQ2NCgpIHsKICAgICAgICAgIGNvbnN0IGxlZnQgPSB0aGlzLl9kYXRhVmlldy5nZXRVaW50MzIodGhpcy5fb2Zmc2V0LCB0aGlzLl9saXR0bGVFbmRpYW4pOwogICAgICAgICAgY29uc3QgcmlnaHQgPSB0aGlzLl9kYXRhVmlldy5nZXRVaW50MzIodGhpcy5fb2Zmc2V0ICsgNCwgdGhpcy5fbGl0dGxlRW5kaWFuKTsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gbGVmdCArIDIgKiogMzIgKiByaWdodDsKICAgICAgICAgIHRoaXMuX29mZnNldCArPSA4OwogICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgIH0KICAgICAgICBfbmV4dEludDMyKCkgewogICAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLl9kYXRhVmlldy5nZXRJbnQzMih0aGlzLl9vZmZzZXQsIHRoaXMuX2xpdHRsZUVuZGlhbik7CiAgICAgICAgICB0aGlzLl9vZmZzZXQgKz0gNDsKICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICB9CiAgICAgICAgX25leHRVaW50OEFycmF5KGxlbikgewogICAgICAgICAgY29uc3QgdmFsdWUgPSBuZXcgVWludDhBcnJheSh0aGlzLl9kYXRhVmlldy5idWZmZXIsIHRoaXMuX2RhdGFWaWV3LmJ5dGVPZmZzZXQgKyB0aGlzLl9vZmZzZXQsIGxlbik7CiAgICAgICAgICB0aGlzLl9vZmZzZXQgKz0gbGVuOwogICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgIH0KICAgICAgICBfc2tpcChieXRlcykgewogICAgICAgICAgdGhpcy5fb2Zmc2V0ICs9IGJ5dGVzOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfQogICAgICAgIF9zY2FuKG1heEJ5dGVMZW5ndGgsIHRlcm0gPSAwKSB7CiAgICAgICAgICBjb25zdCBieXRlT2Zmc2V0ID0gdGhpcy5fb2Zmc2V0OwogICAgICAgICAgbGV0IGJ5dGVMZW5ndGggPSAwOwogICAgICAgICAgd2hpbGUgKHRoaXMuX2RhdGFWaWV3LmdldFVpbnQ4KHRoaXMuX29mZnNldCkgIT09IHRlcm0gJiYgYnl0ZUxlbmd0aCA8IG1heEJ5dGVMZW5ndGgpIHsKICAgICAgICAgICAgYnl0ZUxlbmd0aCsrOwogICAgICAgICAgICB0aGlzLl9vZmZzZXQrKzsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChieXRlTGVuZ3RoIDwgbWF4Qnl0ZUxlbmd0aCkgdGhpcy5fb2Zmc2V0Kys7CiAgICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkodGhpcy5fZGF0YVZpZXcuYnVmZmVyLCB0aGlzLl9kYXRhVmlldy5ieXRlT2Zmc2V0ICsgYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCk7CiAgICAgICAgfQogICAgICB9OwogICAgICBOVUwgPSBuZXcgVWludDhBcnJheShbMF0pOwogICAgICBLVFgyX0lEID0gWwogICAgICAgIC8vICfCtCcsICdLJywgJ1QnLCAnWCcsICcyJywgJzAnLCAnwqonLCAnXHInLCAnXG4nLCAnXHgxQScsICdcbicKICAgICAgICAxNzEsCiAgICAgICAgNzUsCiAgICAgICAgODQsCiAgICAgICAgODgsCiAgICAgICAgMzIsCiAgICAgICAgNTAsCiAgICAgICAgNDgsCiAgICAgICAgMTg3LAogICAgICAgIDEzLAogICAgICAgIDEwLAogICAgICAgIDI2LAogICAgICAgIDEwCiAgICAgIF07CiAgICB9CiAgfSk7CgogIC8vIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvVGhpcmRQYXJ0eS9Xb3JrZXJzL2Jhc2lzX3RyYW5zY29kZXIuanMKICB2YXIgcmVxdWlyZV9iYXNpc190cmFuc2NvZGVyID0gX19jb21tb25KUyh7CiAgICAicGFja2FnZXMvZW5naW5lL1NvdXJjZS9UaGlyZFBhcnR5L1dvcmtlcnMvYmFzaXNfdHJhbnNjb2Rlci5qcyIoZXhwb3J0czIsIG1vZHVsZSkgewogICAgICB2YXIgQkFTSVMgPSAoZnVuY3Rpb24oKSB7CiAgICAgICAgdmFyIF9zY3JpcHREaXIgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICJ1bmRlZmluZWQiICYmIGRvY3VtZW50LmN1cnJlbnRTY3JpcHQgPyBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYyA6IHZvaWQgMDsKICAgICAgICBpZiAodHlwZW9mIF9fZmlsZW5hbWUgIT09ICJ1bmRlZmluZWQiKSBfc2NyaXB0RGlyID0gX3NjcmlwdERpciB8fCBfX2ZpbGVuYW1lOwogICAgICAgIHJldHVybiAoZnVuY3Rpb24oQkFTSVMyKSB7CiAgICAgICAgICBCQVNJUzIgPSBCQVNJUzIgfHwge307CiAgICAgICAgICB2YXIgTW9kdWxlID0gdHlwZW9mIEJBU0lTMiAhPT0gInVuZGVmaW5lZCIgPyBCQVNJUzIgOiB7fTsKICAgICAgICAgIHZhciByZWFkeVByb21pc2VSZXNvbHZlLCByZWFkeVByb21pc2VSZWplY3Q7CiAgICAgICAgICBNb2R1bGVbInJlYWR5Il0gPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICAgICAgcmVhZHlQcm9taXNlUmVzb2x2ZSA9IHJlc29sdmU7CiAgICAgICAgICAgIHJlYWR5UHJvbWlzZVJlamVjdCA9IHJlamVjdDsKICAgICAgICAgIH0pOwogICAgICAgICAgdmFyIG1vZHVsZU92ZXJyaWRlcyA9IHt9OwogICAgICAgICAgdmFyIGtleTsKICAgICAgICAgIGZvciAoa2V5IGluIE1vZHVsZSkgewogICAgICAgICAgICBpZiAoTW9kdWxlLmhhc093blByb3BlcnR5KGtleSkpIHsKICAgICAgICAgICAgICBtb2R1bGVPdmVycmlkZXNba2V5XSA9IE1vZHVsZVtrZXldOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgYXJndW1lbnRzXyA9IFtdOwogICAgICAgICAgdmFyIHRoaXNQcm9ncmFtID0gIi4vdGhpcy5wcm9ncmFtIjsKICAgICAgICAgIHZhciBxdWl0XyA9IGZ1bmN0aW9uKHN0YXR1cywgdG9UaHJvdykgewogICAgICAgICAgICB0aHJvdyB0b1Rocm93OwogICAgICAgICAgfTsKICAgICAgICAgIHZhciBFTlZJUk9OTUVOVF9JU19XRUIgPSBmYWxzZTsKICAgICAgICAgIHZhciBFTlZJUk9OTUVOVF9JU19XT1JLRVIgPSBmYWxzZTsKICAgICAgICAgIHZhciBFTlZJUk9OTUVOVF9JU19OT0RFID0gZmFsc2U7CiAgICAgICAgICB2YXIgRU5WSVJPTk1FTlRfSVNfU0hFTEwgPSBmYWxzZTsKICAgICAgICAgIEVOVklST05NRU5UX0lTX1dFQiA9IHR5cGVvZiB3aW5kb3cgPT09ICJvYmplY3QiOwogICAgICAgICAgRU5WSVJPTk1FTlRfSVNfV09SS0VSID0gdHlwZW9mIGltcG9ydFNjcmlwdHMgPT09ICJmdW5jdGlvbiI7CiAgICAgICAgICBFTlZJUk9OTUVOVF9JU19OT0RFID0gdHlwZW9mIHByb2Nlc3MgPT09ICJvYmplY3QiICYmIHR5cGVvZiBwcm9jZXNzLnZlcnNpb25zID09PSAib2JqZWN0IiAmJiB0eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucy5ub2RlID09PSAic3RyaW5nIjsKICAgICAgICAgIEVOVklST05NRU5UX0lTX1NIRUxMID0gIUVOVklST05NRU5UX0lTX1dFQiAmJiAhRU5WSVJPTk1FTlRfSVNfTk9ERSAmJiAhRU5WSVJPTk1FTlRfSVNfV09SS0VSOwogICAgICAgICAgdmFyIHNjcmlwdERpcmVjdG9yeSA9ICIiOwogICAgICAgICAgZnVuY3Rpb24gbG9jYXRlRmlsZShwYXRoKSB7CiAgICAgICAgICAgIGlmIChNb2R1bGVbImxvY2F0ZUZpbGUiXSkgewogICAgICAgICAgICAgIHJldHVybiBNb2R1bGVbImxvY2F0ZUZpbGUiXShwYXRoLCBzY3JpcHREaXJlY3RvcnkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBzY3JpcHREaXJlY3RvcnkgKyBwYXRoOwogICAgICAgICAgfQogICAgICAgICAgdmFyIHJlYWRfLCByZWFkQXN5bmMsIHJlYWRCaW5hcnksIHNldFdpbmRvd1RpdGxlOwogICAgICAgICAgdmFyIG5vZGVGUzsKICAgICAgICAgIHZhciBub2RlUGF0aDsKICAgICAgICAgIGlmIChFTlZJUk9OTUVOVF9JU19OT0RFKSB7CiAgICAgICAgICAgIGlmIChFTlZJUk9OTUVOVF9JU19XT1JLRVIpIHsKICAgICAgICAgICAgICBzY3JpcHREaXJlY3RvcnkgPSBfX3JlcXVpcmUoInBhdGgiKS5kaXJuYW1lKHNjcmlwdERpcmVjdG9yeSkgKyAiLyI7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgc2NyaXB0RGlyZWN0b3J5ID0gX19kaXJuYW1lICsgIi8iOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJlYWRfID0gZnVuY3Rpb24gc2hlbGxfcmVhZChmaWxlbmFtZSwgYmluYXJ5KSB7CiAgICAgICAgICAgICAgaWYgKCFub2RlRlMpIG5vZGVGUyA9IF9fcmVxdWlyZSgiZnMiKTsKICAgICAgICAgICAgICBpZiAoIW5vZGVQYXRoKSBub2RlUGF0aCA9IF9fcmVxdWlyZSgicGF0aCIpOwogICAgICAgICAgICAgIGZpbGVuYW1lID0gbm9kZVBhdGhbIm5vcm1hbGl6ZSJdKGZpbGVuYW1lKTsKICAgICAgICAgICAgICByZXR1cm4gbm9kZUZTWyJyZWFkRmlsZVN5bmMiXShmaWxlbmFtZSwgYmluYXJ5ID8gbnVsbCA6ICJ1dGY4Iik7CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIHJlYWRCaW5hcnkgPSBmdW5jdGlvbiByZWFkQmluYXJ5MihmaWxlbmFtZSkgewogICAgICAgICAgICAgIHZhciByZXQgPSByZWFkXyhmaWxlbmFtZSwgdHJ1ZSk7CiAgICAgICAgICAgICAgaWYgKCFyZXQuYnVmZmVyKSB7CiAgICAgICAgICAgICAgICByZXQgPSBuZXcgVWludDhBcnJheShyZXQpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBhc3NlcnQocmV0LmJ1ZmZlcik7CiAgICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgaWYgKHByb2Nlc3NbImFyZ3YiXS5sZW5ndGggPiAxKSB7CiAgICAgICAgICAgICAgdGhpc1Byb2dyYW0gPSBwcm9jZXNzWyJhcmd2Il1bMV0ucmVwbGFjZSgvXFwvZywgIi8iKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBhcmd1bWVudHNfID0gcHJvY2Vzc1siYXJndiJdLnNsaWNlKDIpOwogICAgICAgICAgICBwcm9jZXNzWyJvbiJdKCJ1bmNhdWdodEV4Y2VwdGlvbiIsIGZ1bmN0aW9uKGV4KSB7CiAgICAgICAgICAgICAgaWYgKCEoZXggaW5zdGFuY2VvZiBFeGl0U3RhdHVzKSkgewogICAgICAgICAgICAgICAgdGhyb3cgZXg7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgcHJvY2Vzc1sib24iXSgidW5oYW5kbGVkUmVqZWN0aW9uIiwgYWJvcnQpOwogICAgICAgICAgICBxdWl0XyA9IGZ1bmN0aW9uKHN0YXR1cykgewogICAgICAgICAgICAgIHByb2Nlc3NbImV4aXQiXShzdGF0dXMpOwogICAgICAgICAgICB9OwogICAgICAgICAgICBNb2R1bGVbImluc3BlY3QiXSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiAiW0Vtc2NyaXB0ZW4gTW9kdWxlIG9iamVjdF0iOwogICAgICAgICAgICB9OwogICAgICAgICAgfSBlbHNlIGlmIChFTlZJUk9OTUVOVF9JU19TSEVMTCkgewogICAgICAgICAgICBpZiAodHlwZW9mIHJlYWQgIT0gInVuZGVmaW5lZCIpIHsKICAgICAgICAgICAgICByZWFkXyA9IGZ1bmN0aW9uIHNoZWxsX3JlYWQoZikgewogICAgICAgICAgICAgICAgcmV0dXJuIHJlYWQoZik7CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZWFkQmluYXJ5ID0gZnVuY3Rpb24gcmVhZEJpbmFyeTIoZikgewogICAgICAgICAgICAgIHZhciBkYXRhOwogICAgICAgICAgICAgIGlmICh0eXBlb2YgcmVhZGJ1ZmZlciA9PT0gImZ1bmN0aW9uIikgewogICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KHJlYWRidWZmZXIoZikpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBkYXRhID0gcmVhZChmLCAiYmluYXJ5Iik7CiAgICAgICAgICAgICAgYXNzZXJ0KHR5cGVvZiBkYXRhID09PSAib2JqZWN0Iik7CiAgICAgICAgICAgICAgcmV0dXJuIGRhdGE7CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIGlmICh0eXBlb2Ygc2NyaXB0QXJncyAhPSAidW5kZWZpbmVkIikgewogICAgICAgICAgICAgIGFyZ3VtZW50c18gPSBzY3JpcHRBcmdzOwogICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmd1bWVudHMgIT0gInVuZGVmaW5lZCIpIHsKICAgICAgICAgICAgICBhcmd1bWVudHNfID0gYXJndW1lbnRzOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh0eXBlb2YgcXVpdCA9PT0gImZ1bmN0aW9uIikgewogICAgICAgICAgICAgIHF1aXRfID0gZnVuY3Rpb24oc3RhdHVzKSB7CiAgICAgICAgICAgICAgICBxdWl0KHN0YXR1cyk7CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodHlwZW9mIHByaW50ICE9PSAidW5kZWZpbmVkIikgewogICAgICAgICAgICAgIGlmICh0eXBlb2YgY29uc29sZSA9PT0gInVuZGVmaW5lZCIpIGNvbnNvbGUgPSB7fTsKICAgICAgICAgICAgICBjb25zb2xlLmxvZyA9IHByaW50OwogICAgICAgICAgICAgIGNvbnNvbGUud2FybiA9IGNvbnNvbGUuZXJyb3IgPSB0eXBlb2YgcHJpbnRFcnIgIT09ICJ1bmRlZmluZWQiID8gcHJpbnRFcnIgOiBwcmludDsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIGlmIChFTlZJUk9OTUVOVF9JU19XRUIgfHwgRU5WSVJPTk1FTlRfSVNfV09SS0VSKSB7CiAgICAgICAgICAgIGlmIChFTlZJUk9OTUVOVF9JU19XT1JLRVIpIHsKICAgICAgICAgICAgICBzY3JpcHREaXJlY3RvcnkgPSBzZWxmLmxvY2F0aW9uLmhyZWY7CiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAidW5kZWZpbmVkIiAmJiBkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7CiAgICAgICAgICAgICAgc2NyaXB0RGlyZWN0b3J5ID0gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKF9zY3JpcHREaXIpIHsKICAgICAgICAgICAgICBzY3JpcHREaXJlY3RvcnkgPSBfc2NyaXB0RGlyOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChzY3JpcHREaXJlY3RvcnkuaW5kZXhPZigiYmxvYjoiKSAhPT0gMCkgewogICAgICAgICAgICAgIHNjcmlwdERpcmVjdG9yeSA9IHNjcmlwdERpcmVjdG9yeS5zdWJzdHIoMCwgc2NyaXB0RGlyZWN0b3J5Lmxhc3RJbmRleE9mKCIvIikgKyAxKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBzY3JpcHREaXJlY3RvcnkgPSAiIjsKICAgICAgICAgICAgfQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgcmVhZF8gPSBmdW5jdGlvbih1cmwpIHsKICAgICAgICAgICAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsKICAgICAgICAgICAgICAgIHhoci5vcGVuKCJHRVQiLCB1cmwsIGZhbHNlKTsKICAgICAgICAgICAgICAgIHhoci5zZW5kKG51bGwpOwogICAgICAgICAgICAgICAgcmV0dXJuIHhoci5yZXNwb25zZVRleHQ7CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICBpZiAoRU5WSVJPTk1FTlRfSVNfV09SS0VSKSB7CiAgICAgICAgICAgICAgICByZWFkQmluYXJ5ID0gZnVuY3Rpb24odXJsKSB7CiAgICAgICAgICAgICAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsKICAgICAgICAgICAgICAgICAgeGhyLm9wZW4oIkdFVCIsIHVybCwgZmFsc2UpOwogICAgICAgICAgICAgICAgICB4aHIucmVzcG9uc2VUeXBlID0gImFycmF5YnVmZmVyIjsKICAgICAgICAgICAgICAgICAgeGhyLnNlbmQobnVsbCk7CiAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheSh4aHIucmVzcG9uc2UpOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmVhZEFzeW5jID0gZnVuY3Rpb24odXJsLCBvbmxvYWQsIG9uZXJyb3IpIHsKICAgICAgICAgICAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTsKICAgICAgICAgICAgICAgIHhoci5vcGVuKCJHRVQiLCB1cmwsIHRydWUpOwogICAgICAgICAgICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9ICJhcnJheWJ1ZmZlciI7CiAgICAgICAgICAgICAgICB4aHIub25sb2FkID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICAgIGlmICh4aHIuc3RhdHVzID09IDIwMCB8fCB4aHIuc3RhdHVzID09IDAgJiYgeGhyLnJlc3BvbnNlKSB7CiAgICAgICAgICAgICAgICAgICAgb25sb2FkKHhoci5yZXNwb25zZSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIG9uZXJyb3IoKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB4aHIub25lcnJvciA9IG9uZXJyb3I7CiAgICAgICAgICAgICAgICB4aHIuc2VuZChudWxsKTsKICAgICAgICAgICAgICB9OwogICAgICAgICAgICB9CiAgICAgICAgICAgIHNldFdpbmRvd1RpdGxlID0gZnVuY3Rpb24odGl0bGUpIHsKICAgICAgICAgICAgICBkb2N1bWVudC50aXRsZSA9IHRpdGxlOwogICAgICAgICAgICB9OwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBvdXQgPSBNb2R1bGVbInByaW50Il0gfHwgY29uc29sZS5sb2cuYmluZChjb25zb2xlKTsKICAgICAgICAgIHZhciBlcnIgPSBNb2R1bGVbInByaW50RXJyIl0gfHwgY29uc29sZS53YXJuLmJpbmQoY29uc29sZSk7CiAgICAgICAgICBmb3IgKGtleSBpbiBtb2R1bGVPdmVycmlkZXMpIHsKICAgICAgICAgICAgaWYgKG1vZHVsZU92ZXJyaWRlcy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7CiAgICAgICAgICAgICAgTW9kdWxlW2tleV0gPSBtb2R1bGVPdmVycmlkZXNba2V5XTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgbW9kdWxlT3ZlcnJpZGVzID0gbnVsbDsKICAgICAgICAgIGlmIChNb2R1bGVbImFyZ3VtZW50cyJdKSBhcmd1bWVudHNfID0gTW9kdWxlWyJhcmd1bWVudHMiXTsKICAgICAgICAgIGlmIChNb2R1bGVbInRoaXNQcm9ncmFtIl0pIHRoaXNQcm9ncmFtID0gTW9kdWxlWyJ0aGlzUHJvZ3JhbSJdOwogICAgICAgICAgaWYgKE1vZHVsZVsicXVpdCJdKSBxdWl0XyA9IE1vZHVsZVsicXVpdCJdOwogICAgICAgICAgdmFyIHRlbXBSZXQwID0gMDsKICAgICAgICAgIHZhciBzZXRUZW1wUmV0MCA9IGZ1bmN0aW9uKHZhbHVlKSB7CiAgICAgICAgICAgIHRlbXBSZXQwID0gdmFsdWU7CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIHdhc21CaW5hcnk7CiAgICAgICAgICBpZiAoTW9kdWxlWyJ3YXNtQmluYXJ5Il0pIHdhc21CaW5hcnkgPSBNb2R1bGVbIndhc21CaW5hcnkiXTsKICAgICAgICAgIHZhciBub0V4aXRSdW50aW1lID0gTW9kdWxlWyJub0V4aXRSdW50aW1lIl0gfHwgdHJ1ZTsKICAgICAgICAgIGlmICh0eXBlb2YgV2ViQXNzZW1ibHkgIT09ICJvYmplY3QiKSB7CiAgICAgICAgICAgIGFib3J0KCJubyBuYXRpdmUgd2FzbSBzdXBwb3J0IGRldGVjdGVkIik7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgd2FzbU1lbW9yeTsKICAgICAgICAgIHZhciBBQk9SVCA9IGZhbHNlOwogICAgICAgICAgdmFyIEVYSVRTVEFUVVM7CiAgICAgICAgICBmdW5jdGlvbiBhc3NlcnQoY29uZGl0aW9uLCB0ZXh0KSB7CiAgICAgICAgICAgIGlmICghY29uZGl0aW9uKSB7CiAgICAgICAgICAgICAgYWJvcnQoIkFzc2VydGlvbiBmYWlsZWQ6ICIgKyB0ZXh0KTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgdmFyIFVURjhEZWNvZGVyID0gdHlwZW9mIFRleHREZWNvZGVyICE9PSAidW5kZWZpbmVkIiA/IG5ldyBUZXh0RGVjb2RlcigidXRmOCIpIDogdm9pZCAwOwogICAgICAgICAgZnVuY3Rpb24gVVRGOEFycmF5VG9TdHJpbmcoaGVhcCwgaWR4LCBtYXhCeXRlc1RvUmVhZCkgewogICAgICAgICAgICB2YXIgZW5kSWR4ID0gaWR4ICsgbWF4Qnl0ZXNUb1JlYWQ7CiAgICAgICAgICAgIHZhciBlbmRQdHIgPSBpZHg7CiAgICAgICAgICAgIHdoaWxlIChoZWFwW2VuZFB0cl0gJiYgIShlbmRQdHIgPj0gZW5kSWR4KSkgKytlbmRQdHI7CiAgICAgICAgICAgIGlmIChlbmRQdHIgLSBpZHggPiAxNiAmJiBoZWFwLnN1YmFycmF5ICYmIFVURjhEZWNvZGVyKSB7CiAgICAgICAgICAgICAgcmV0dXJuIFVURjhEZWNvZGVyLmRlY29kZShoZWFwLnN1YmFycmF5KGlkeCwgZW5kUHRyKSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdmFyIHN0ciA9ICIiOwogICAgICAgICAgICAgIHdoaWxlIChpZHggPCBlbmRQdHIpIHsKICAgICAgICAgICAgICAgIHZhciB1MCA9IGhlYXBbaWR4KytdOwogICAgICAgICAgICAgICAgaWYgKCEodTAgJiAxMjgpKSB7CiAgICAgICAgICAgICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHUwKTsKICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB2YXIgdTEyID0gaGVhcFtpZHgrK10gJiA2MzsKICAgICAgICAgICAgICAgIGlmICgodTAgJiAyMjQpID09IDE5MikgewogICAgICAgICAgICAgICAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgodTAgJiAzMSkgPDwgNiB8IHUxMik7CiAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIHUyMiA9IGhlYXBbaWR4KytdICYgNjM7CiAgICAgICAgICAgICAgICBpZiAoKHUwICYgMjQwKSA9PSAyMjQpIHsKICAgICAgICAgICAgICAgICAgdTAgPSAodTAgJiAxNSkgPDwgMTIgfCB1MTIgPDwgNiB8IHUyMjsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIHUwID0gKHUwICYgNykgPDwgMTggfCB1MTIgPDwgMTIgfCB1MjIgPDwgNiB8IGhlYXBbaWR4KytdICYgNjM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAodTAgPCA2NTUzNikgewogICAgICAgICAgICAgICAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSh1MCk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICB2YXIgY2ggPSB1MCAtIDY1NTM2OwogICAgICAgICAgICAgICAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSg1NTI5NiB8IGNoID4+IDEwLCA1NjMyMCB8IGNoICYgMTAyMyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBzdHI7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBVVEY4VG9TdHJpbmcocHRyLCBtYXhCeXRlc1RvUmVhZCkgewogICAgICAgICAgICByZXR1cm4gcHRyID8gVVRGOEFycmF5VG9TdHJpbmcoSEVBUFU4LCBwdHIsIG1heEJ5dGVzVG9SZWFkKSA6ICIiOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gc3RyaW5nVG9VVEY4QXJyYXkoc3RyLCBoZWFwLCBvdXRJZHgsIG1heEJ5dGVzVG9Xcml0ZSkgewogICAgICAgICAgICBpZiAoIShtYXhCeXRlc1RvV3JpdGUgPiAwKSkgcmV0dXJuIDA7CiAgICAgICAgICAgIHZhciBzdGFydElkeCA9IG91dElkeDsKICAgICAgICAgICAgdmFyIGVuZElkeCA9IG91dElkeCArIG1heEJ5dGVzVG9Xcml0ZSAtIDE7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgICAgdmFyIHUzID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICAgICAgICAgICAgaWYgKHUzID49IDU1Mjk2ICYmIHUzIDw9IDU3MzQzKSB7CiAgICAgICAgICAgICAgICB2YXIgdTEyID0gc3RyLmNoYXJDb2RlQXQoKytpKTsKICAgICAgICAgICAgICAgIHUzID0gNjU1MzYgKyAoKHUzICYgMTAyMykgPDwgMTApIHwgdTEyICYgMTAyMzsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHUzIDw9IDEyNykgewogICAgICAgICAgICAgICAgaWYgKG91dElkeCA+PSBlbmRJZHgpIGJyZWFrOwogICAgICAgICAgICAgICAgaGVhcFtvdXRJZHgrK10gPSB1MzsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKHUzIDw9IDIwNDcpIHsKICAgICAgICAgICAgICAgIGlmIChvdXRJZHggKyAxID49IGVuZElkeCkgYnJlYWs7CiAgICAgICAgICAgICAgICBoZWFwW291dElkeCsrXSA9IDE5MiB8IHUzID4+IDY7CiAgICAgICAgICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUzICYgNjM7CiAgICAgICAgICAgICAgfSBlbHNlIGlmICh1MyA8PSA2NTUzNSkgewogICAgICAgICAgICAgICAgaWYgKG91dElkeCArIDIgPj0gZW5kSWR4KSBicmVhazsKICAgICAgICAgICAgICAgIGhlYXBbb3V0SWR4KytdID0gMjI0IHwgdTMgPj4gMTI7CiAgICAgICAgICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUzID4+IDYgJiA2MzsKICAgICAgICAgICAgICAgIGhlYXBbb3V0SWR4KytdID0gMTI4IHwgdTMgJiA2MzsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgaWYgKG91dElkeCArIDMgPj0gZW5kSWR4KSBicmVhazsKICAgICAgICAgICAgICAgIGhlYXBbb3V0SWR4KytdID0gMjQwIHwgdTMgPj4gMTg7CiAgICAgICAgICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUzID4+IDEyICYgNjM7CiAgICAgICAgICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUzID4+IDYgJiA2MzsKICAgICAgICAgICAgICAgIGhlYXBbb3V0SWR4KytdID0gMTI4IHwgdTMgJiA2MzsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaGVhcFtvdXRJZHhdID0gMDsKICAgICAgICAgICAgcmV0dXJuIG91dElkeCAtIHN0YXJ0SWR4OwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gc3RyaW5nVG9VVEY4KHN0ciwgb3V0UHRyLCBtYXhCeXRlc1RvV3JpdGUpIHsKICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1RvVVRGOEFycmF5KHN0ciwgSEVBUFU4LCBvdXRQdHIsIG1heEJ5dGVzVG9Xcml0ZSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBsZW5ndGhCeXRlc1VURjgoc3RyKSB7CiAgICAgICAgICAgIHZhciBsZW4gPSAwOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7ICsraSkgewogICAgICAgICAgICAgIHZhciB1MyA9IHN0ci5jaGFyQ29kZUF0KGkpOwogICAgICAgICAgICAgIGlmICh1MyA+PSA1NTI5NiAmJiB1MyA8PSA1NzM0MykgdTMgPSA2NTUzNiArICgodTMgJiAxMDIzKSA8PCAxMCkgfCBzdHIuY2hhckNvZGVBdCgrK2kpICYgMTAyMzsKICAgICAgICAgICAgICBpZiAodTMgPD0gMTI3KSArK2xlbjsKICAgICAgICAgICAgICBlbHNlIGlmICh1MyA8PSAyMDQ3KSBsZW4gKz0gMjsKICAgICAgICAgICAgICBlbHNlIGlmICh1MyA8PSA2NTUzNSkgbGVuICs9IDM7CiAgICAgICAgICAgICAgZWxzZSBsZW4gKz0gNDsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbGVuOwogICAgICAgICAgfQogICAgICAgICAgdmFyIFVURjE2RGVjb2RlciA9IHR5cGVvZiBUZXh0RGVjb2RlciAhPT0gInVuZGVmaW5lZCIgPyBuZXcgVGV4dERlY29kZXIoInV0Zi0xNmxlIikgOiB2b2lkIDA7CiAgICAgICAgICBmdW5jdGlvbiBVVEYxNlRvU3RyaW5nKHB0ciwgbWF4Qnl0ZXNUb1JlYWQpIHsKICAgICAgICAgICAgdmFyIGVuZFB0ciA9IHB0cjsKICAgICAgICAgICAgdmFyIGlkeCA9IGVuZFB0ciA+PiAxOwogICAgICAgICAgICB2YXIgbWF4SWR4ID0gaWR4ICsgbWF4Qnl0ZXNUb1JlYWQgLyAyOwogICAgICAgICAgICB3aGlsZSAoIShpZHggPj0gbWF4SWR4KSAmJiBIRUFQVTE2W2lkeF0pICsraWR4OwogICAgICAgICAgICBlbmRQdHIgPSBpZHggPDwgMTsKICAgICAgICAgICAgaWYgKGVuZFB0ciAtIHB0ciA+IDMyICYmIFVURjE2RGVjb2RlcikgewogICAgICAgICAgICAgIHJldHVybiBVVEYxNkRlY29kZXIuZGVjb2RlKEhFQVBVOC5zdWJhcnJheShwdHIsIGVuZFB0cikpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHZhciBzdHIgPSAiIjsKICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgIShpID49IG1heEJ5dGVzVG9SZWFkIC8gMik7ICsraSkgewogICAgICAgICAgICAgICAgdmFyIGNvZGVVbml0ID0gSEVBUDE2W3B0ciArIGkgKiAyID4+IDFdOwogICAgICAgICAgICAgICAgaWYgKGNvZGVVbml0ID09IDApIGJyZWFrOwogICAgICAgICAgICAgICAgc3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoY29kZVVuaXQpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gc3RyOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdUb1VURjE2KHN0ciwgb3V0UHRyLCBtYXhCeXRlc1RvV3JpdGUpIHsKICAgICAgICAgICAgaWYgKG1heEJ5dGVzVG9Xcml0ZSA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgbWF4Qnl0ZXNUb1dyaXRlID0gMjE0NzQ4MzY0NzsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAobWF4Qnl0ZXNUb1dyaXRlIDwgMikgcmV0dXJuIDA7CiAgICAgICAgICAgIG1heEJ5dGVzVG9Xcml0ZSAtPSAyOwogICAgICAgICAgICB2YXIgc3RhcnRQdHIgPSBvdXRQdHI7CiAgICAgICAgICAgIHZhciBudW1DaGFyc1RvV3JpdGUgPSBtYXhCeXRlc1RvV3JpdGUgPCBzdHIubGVuZ3RoICogMiA/IG1heEJ5dGVzVG9Xcml0ZSAvIDIgOiBzdHIubGVuZ3RoOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bUNoYXJzVG9Xcml0ZTsgKytpKSB7CiAgICAgICAgICAgICAgdmFyIGNvZGVVbml0ID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICAgICAgICAgICAgSEVBUDE2W291dFB0ciA+PiAxXSA9IGNvZGVVbml0OwogICAgICAgICAgICAgIG91dFB0ciArPSAyOwogICAgICAgICAgICB9CiAgICAgICAgICAgIEhFQVAxNltvdXRQdHIgPj4gMV0gPSAwOwogICAgICAgICAgICByZXR1cm4gb3V0UHRyIC0gc3RhcnRQdHI7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBsZW5ndGhCeXRlc1VURjE2KHN0cikgewogICAgICAgICAgICByZXR1cm4gc3RyLmxlbmd0aCAqIDI7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBVVEYzMlRvU3RyaW5nKHB0ciwgbWF4Qnl0ZXNUb1JlYWQpIHsKICAgICAgICAgICAgdmFyIGkgPSAwOwogICAgICAgICAgICB2YXIgc3RyID0gIiI7CiAgICAgICAgICAgIHdoaWxlICghKGkgPj0gbWF4Qnl0ZXNUb1JlYWQgLyA0KSkgewogICAgICAgICAgICAgIHZhciB1dGYzMiA9IEhFQVAzMltwdHIgKyBpICogNCA+PiAyXTsKICAgICAgICAgICAgICBpZiAodXRmMzIgPT0gMCkgYnJlYWs7CiAgICAgICAgICAgICAgKytpOwogICAgICAgICAgICAgIGlmICh1dGYzMiA+PSA2NTUzNikgewogICAgICAgICAgICAgICAgdmFyIGNoID0gdXRmMzIgLSA2NTUzNjsKICAgICAgICAgICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2IHwgY2ggPj4gMTAsIDU2MzIwIHwgY2ggJiAxMDIzKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgc3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUodXRmMzIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gc3RyOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gc3RyaW5nVG9VVEYzMihzdHIsIG91dFB0ciwgbWF4Qnl0ZXNUb1dyaXRlKSB7CiAgICAgICAgICAgIGlmIChtYXhCeXRlc1RvV3JpdGUgPT09IHZvaWQgMCkgewogICAgICAgICAgICAgIG1heEJ5dGVzVG9Xcml0ZSA9IDIxNDc0ODM2NDc7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKG1heEJ5dGVzVG9Xcml0ZSA8IDQpIHJldHVybiAwOwogICAgICAgICAgICB2YXIgc3RhcnRQdHIgPSBvdXRQdHI7CiAgICAgICAgICAgIHZhciBlbmRQdHIgPSBzdGFydFB0ciArIG1heEJ5dGVzVG9Xcml0ZSAtIDQ7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgICAgdmFyIGNvZGVVbml0ID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICAgICAgICAgICAgaWYgKGNvZGVVbml0ID49IDU1Mjk2ICYmIGNvZGVVbml0IDw9IDU3MzQzKSB7CiAgICAgICAgICAgICAgICB2YXIgdHJhaWxTdXJyb2dhdGUgPSBzdHIuY2hhckNvZGVBdCgrK2kpOwogICAgICAgICAgICAgICAgY29kZVVuaXQgPSA2NTUzNiArICgoY29kZVVuaXQgJiAxMDIzKSA8PCAxMCkgfCB0cmFpbFN1cnJvZ2F0ZSAmIDEwMjM7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIEhFQVAzMltvdXRQdHIgPj4gMl0gPSBjb2RlVW5pdDsKICAgICAgICAgICAgICBvdXRQdHIgKz0gNDsKICAgICAgICAgICAgICBpZiAob3V0UHRyICsgNCA+IGVuZFB0cikgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgSEVBUDMyW291dFB0ciA+PiAyXSA9IDA7CiAgICAgICAgICAgIHJldHVybiBvdXRQdHIgLSBzdGFydFB0cjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGxlbmd0aEJ5dGVzVVRGMzIoc3RyKSB7CiAgICAgICAgICAgIHZhciBsZW4gPSAwOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7ICsraSkgewogICAgICAgICAgICAgIHZhciBjb2RlVW5pdCA9IHN0ci5jaGFyQ29kZUF0KGkpOwogICAgICAgICAgICAgIGlmIChjb2RlVW5pdCA+PSA1NTI5NiAmJiBjb2RlVW5pdCA8PSA1NzM0MykgKytpOwogICAgICAgICAgICAgIGxlbiArPSA0OwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBsZW47CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBhbGlnblVwKHgsIG11bHRpcGxlKSB7CiAgICAgICAgICAgIGlmICh4ICUgbXVsdGlwbGUgPiAwKSB7CiAgICAgICAgICAgICAgeCArPSBtdWx0aXBsZSAtIHggJSBtdWx0aXBsZTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4geDsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBidWZmZXIsIEhFQVA4LCBIRUFQVTgsIEhFQVAxNiwgSEVBUFUxNiwgSEVBUDMyLCBIRUFQVTMyLCBIRUFQRjMyLCBIRUFQRjY0OwogICAgICAgICAgZnVuY3Rpb24gdXBkYXRlR2xvYmFsQnVmZmVyQW5kVmlld3MoYnVmKSB7CiAgICAgICAgICAgIGJ1ZmZlciA9IGJ1ZjsKICAgICAgICAgICAgTW9kdWxlWyJIRUFQOCJdID0gSEVBUDggPSBuZXcgSW50OEFycmF5KGJ1Zik7CiAgICAgICAgICAgIE1vZHVsZVsiSEVBUDE2Il0gPSBIRUFQMTYgPSBuZXcgSW50MTZBcnJheShidWYpOwogICAgICAgICAgICBNb2R1bGVbIkhFQVAzMiJdID0gSEVBUDMyID0gbmV3IEludDMyQXJyYXkoYnVmKTsKICAgICAgICAgICAgTW9kdWxlWyJIRUFQVTgiXSA9IEhFQVBVOCA9IG5ldyBVaW50OEFycmF5KGJ1Zik7CiAgICAgICAgICAgIE1vZHVsZVsiSEVBUFUxNiJdID0gSEVBUFUxNiA9IG5ldyBVaW50MTZBcnJheShidWYpOwogICAgICAgICAgICBNb2R1bGVbIkhFQVBVMzIiXSA9IEhFQVBVMzIgPSBuZXcgVWludDMyQXJyYXkoYnVmKTsKICAgICAgICAgICAgTW9kdWxlWyJIRUFQRjMyIl0gPSBIRUFQRjMyID0gbmV3IEZsb2F0MzJBcnJheShidWYpOwogICAgICAgICAgICBNb2R1bGVbIkhFQVBGNjQiXSA9IEhFQVBGNjQgPSBuZXcgRmxvYXQ2NEFycmF5KGJ1Zik7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgSU5JVElBTF9NRU1PUlkgPSBNb2R1bGVbIklOSVRJQUxfTUVNT1JZIl0gfHwgMTY3NzcyMTY7CiAgICAgICAgICB2YXIgd2FzbVRhYmxlOwogICAgICAgICAgdmFyIF9fQVRQUkVSVU5fXyA9IFtdOwogICAgICAgICAgdmFyIF9fQVRJTklUX18gPSBbXTsKICAgICAgICAgIHZhciBfX0FUTUFJTl9fID0gW107CiAgICAgICAgICB2YXIgX19BVFBPU1RSVU5fXyA9IFtdOwogICAgICAgICAgdmFyIHJ1bnRpbWVJbml0aWFsaXplZCA9IGZhbHNlOwogICAgICAgICAgZnVuY3Rpb24gcHJlUnVuKCkgewogICAgICAgICAgICBpZiAoTW9kdWxlWyJwcmVSdW4iXSkgewogICAgICAgICAgICAgIGlmICh0eXBlb2YgTW9kdWxlWyJwcmVSdW4iXSA9PSAiZnVuY3Rpb24iKSBNb2R1bGVbInByZVJ1biJdID0gW01vZHVsZVsicHJlUnVuIl1dOwogICAgICAgICAgICAgIHdoaWxlIChNb2R1bGVbInByZVJ1biJdLmxlbmd0aCkgewogICAgICAgICAgICAgICAgYWRkT25QcmVSdW4oTW9kdWxlWyJwcmVSdW4iXS5zaGlmdCgpKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2FsbFJ1bnRpbWVDYWxsYmFja3MoX19BVFBSRVJVTl9fKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGluaXRSdW50aW1lKCkgewogICAgICAgICAgICBydW50aW1lSW5pdGlhbGl6ZWQgPSB0cnVlOwogICAgICAgICAgICBjYWxsUnVudGltZUNhbGxiYWNrcyhfX0FUSU5JVF9fKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHByZU1haW4oKSB7CiAgICAgICAgICAgIGNhbGxSdW50aW1lQ2FsbGJhY2tzKF9fQVRNQUlOX18pOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gcG9zdFJ1bigpIHsKICAgICAgICAgICAgaWYgKE1vZHVsZVsicG9zdFJ1biJdKSB7CiAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNb2R1bGVbInBvc3RSdW4iXSA9PSAiZnVuY3Rpb24iKSBNb2R1bGVbInBvc3RSdW4iXSA9IFtNb2R1bGVbInBvc3RSdW4iXV07CiAgICAgICAgICAgICAgd2hpbGUgKE1vZHVsZVsicG9zdFJ1biJdLmxlbmd0aCkgewogICAgICAgICAgICAgICAgYWRkT25Qb3N0UnVuKE1vZHVsZVsicG9zdFJ1biJdLnNoaWZ0KCkpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBjYWxsUnVudGltZUNhbGxiYWNrcyhfX0FUUE9TVFJVTl9fKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGFkZE9uUHJlUnVuKGNiKSB7CiAgICAgICAgICAgIF9fQVRQUkVSVU5fXy51bnNoaWZ0KGNiKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGFkZE9uSW5pdChjYikgewogICAgICAgICAgICBfX0FUSU5JVF9fLnVuc2hpZnQoY2IpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gYWRkT25Qb3N0UnVuKGNiKSB7CiAgICAgICAgICAgIF9fQVRQT1NUUlVOX18udW5zaGlmdChjYik7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgcnVuRGVwZW5kZW5jaWVzID0gMDsKICAgICAgICAgIHZhciBydW5EZXBlbmRlbmN5V2F0Y2hlciA9IG51bGw7CiAgICAgICAgICB2YXIgZGVwZW5kZW5jaWVzRnVsZmlsbGVkID0gbnVsbDsKICAgICAgICAgIGZ1bmN0aW9uIGFkZFJ1bkRlcGVuZGVuY3koaWQpIHsKICAgICAgICAgICAgcnVuRGVwZW5kZW5jaWVzKys7CiAgICAgICAgICAgIGlmIChNb2R1bGVbIm1vbml0b3JSdW5EZXBlbmRlbmNpZXMiXSkgewogICAgICAgICAgICAgIE1vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdKHJ1bkRlcGVuZGVuY2llcyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVJ1bkRlcGVuZGVuY3koaWQpIHsKICAgICAgICAgICAgcnVuRGVwZW5kZW5jaWVzLS07CiAgICAgICAgICAgIGlmIChNb2R1bGVbIm1vbml0b3JSdW5EZXBlbmRlbmNpZXMiXSkgewogICAgICAgICAgICAgIE1vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdKHJ1bkRlcGVuZGVuY2llcyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJ1bkRlcGVuZGVuY2llcyA9PSAwKSB7CiAgICAgICAgICAgICAgaWYgKHJ1bkRlcGVuZGVuY3lXYXRjaGVyICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKHJ1bkRlcGVuZGVuY3lXYXRjaGVyKTsKICAgICAgICAgICAgICAgIHJ1bkRlcGVuZGVuY3lXYXRjaGVyID0gbnVsbDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKGRlcGVuZGVuY2llc0Z1bGZpbGxlZCkgewogICAgICAgICAgICAgICAgdmFyIGNhbGxiYWNrID0gZGVwZW5kZW5jaWVzRnVsZmlsbGVkOwogICAgICAgICAgICAgICAgZGVwZW5kZW5jaWVzRnVsZmlsbGVkID0gbnVsbDsKICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBNb2R1bGVbInByZWxvYWRlZEltYWdlcyJdID0ge307CiAgICAgICAgICBNb2R1bGVbInByZWxvYWRlZEF1ZGlvcyJdID0ge307CiAgICAgICAgICBmdW5jdGlvbiBhYm9ydCh3aGF0KSB7CiAgICAgICAgICAgIGlmIChNb2R1bGVbIm9uQWJvcnQiXSkgewogICAgICAgICAgICAgIE1vZHVsZVsib25BYm9ydCJdKHdoYXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHdoYXQgKz0gIiI7CiAgICAgICAgICAgIGVycih3aGF0KTsKICAgICAgICAgICAgQUJPUlQgPSB0cnVlOwogICAgICAgICAgICBFWElUU1RBVFVTID0gMTsKICAgICAgICAgICAgd2hhdCA9ICJhYm9ydCgiICsgd2hhdCArICIpLiBCdWlsZCB3aXRoIC1zIEFTU0VSVElPTlM9MSBmb3IgbW9yZSBpbmZvLiI7CiAgICAgICAgICAgIHZhciBlID0gbmV3IFdlYkFzc2VtYmx5LlJ1bnRpbWVFcnJvcih3aGF0KTsKICAgICAgICAgICAgcmVhZHlQcm9taXNlUmVqZWN0KGUpOwogICAgICAgICAgICB0aHJvdyBlOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gaGFzUHJlZml4KHN0ciwgcHJlZml4KSB7CiAgICAgICAgICAgIHJldHVybiBTdHJpbmcucHJvdG90eXBlLnN0YXJ0c1dpdGggPyBzdHIuc3RhcnRzV2l0aChwcmVmaXgpIDogc3RyLmluZGV4T2YocHJlZml4KSA9PT0gMDsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBkYXRhVVJJUHJlZml4ID0gImRhdGE6YXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtO2Jhc2U2NCwiOwogICAgICAgICAgZnVuY3Rpb24gaXNEYXRhVVJJKGZpbGVuYW1lKSB7CiAgICAgICAgICAgIHJldHVybiBoYXNQcmVmaXgoZmlsZW5hbWUsIGRhdGFVUklQcmVmaXgpOwogICAgICAgICAgfQogICAgICAgICAgdmFyIGZpbGVVUklQcmVmaXggPSAiZmlsZTovLyI7CiAgICAgICAgICBmdW5jdGlvbiBpc0ZpbGVVUkkoZmlsZW5hbWUpIHsKICAgICAgICAgICAgcmV0dXJuIGhhc1ByZWZpeChmaWxlbmFtZSwgZmlsZVVSSVByZWZpeCk7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgd2FzbUJpbmFyeUZpbGUgPSAiYmFzaXNfdHJhbnNjb2Rlci53YXNtIjsKICAgICAgICAgIGlmICghaXNEYXRhVVJJKHdhc21CaW5hcnlGaWxlKSkgewogICAgICAgICAgICB3YXNtQmluYXJ5RmlsZSA9IGxvY2F0ZUZpbGUod2FzbUJpbmFyeUZpbGUpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZ2V0QmluYXJ5KGZpbGUpIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBpZiAoZmlsZSA9PSB3YXNtQmluYXJ5RmlsZSAmJiB3YXNtQmluYXJ5KSB7CiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkod2FzbUJpbmFyeSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChyZWFkQmluYXJ5KSB7CiAgICAgICAgICAgICAgICByZXR1cm4gcmVhZEJpbmFyeShmaWxlKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgdGhyb3cgImJvdGggYXN5bmMgYW5kIHN5bmMgZmV0Y2hpbmcgb2YgdGhlIHdhc20gZmFpbGVkIjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gY2F0Y2ggKGVycjIpIHsKICAgICAgICAgICAgICBhYm9ydChlcnIyKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZ2V0QmluYXJ5UHJvbWlzZSgpIHsKICAgICAgICAgICAgaWYgKCF3YXNtQmluYXJ5ICYmIChFTlZJUk9OTUVOVF9JU19XRUIgfHwgRU5WSVJPTk1FTlRfSVNfV09SS0VSKSkgewogICAgICAgICAgICAgIGlmICh0eXBlb2YgZmV0Y2ggPT09ICJmdW5jdGlvbiIgJiYgIWlzRmlsZVVSSSh3YXNtQmluYXJ5RmlsZSkpIHsKICAgICAgICAgICAgICAgIHJldHVybiBmZXRjaCh3YXNtQmluYXJ5RmlsZSwgeyBjcmVkZW50aWFsczogInNhbWUtb3JpZ2luIiB9KS50aGVuKGZ1bmN0aW9uKHJlc3BvbnNlKSB7CiAgICAgICAgICAgICAgICAgIGlmICghcmVzcG9uc2VbIm9rIl0pIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyAiZmFpbGVkIHRvIGxvYWQgd2FzbSBiaW5hcnkgZmlsZSBhdCAnIiArIHdhc21CaW5hcnlGaWxlICsgIiciOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZVsiYXJyYXlCdWZmZXIiXSgpOwogICAgICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICAgIHJldHVybiBnZXRCaW5hcnkod2FzbUJpbmFyeUZpbGUpOwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGlmIChyZWFkQXN5bmMpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgICAgICAgICAgICAgIHJlYWRBc3luYyh3YXNtQmluYXJ5RmlsZSwgZnVuY3Rpb24ocmVzcG9uc2UpIHsKICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUobmV3IFVpbnQ4QXJyYXkocmVzcG9uc2UpKTsKICAgICAgICAgICAgICAgICAgICB9LCByZWplY3QpOwogICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGdldEJpbmFyeSh3YXNtQmluYXJ5RmlsZSk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gY3JlYXRlV2FzbSgpIHsKICAgICAgICAgICAgdmFyIGluZm8gPSB7ICJhIjogYXNtTGlicmFyeUFyZyB9OwogICAgICAgICAgICBmdW5jdGlvbiByZWNlaXZlSW5zdGFuY2UoaW5zdGFuY2UsIG1vZHVsZTIpIHsKICAgICAgICAgICAgICB2YXIgZXhwb3J0czQgPSBpbnN0YW5jZS5leHBvcnRzOwogICAgICAgICAgICAgIE1vZHVsZVsiYXNtIl0gPSBleHBvcnRzNDsKICAgICAgICAgICAgICB3YXNtTWVtb3J5ID0gTW9kdWxlWyJhc20iXVsiSyJdOwogICAgICAgICAgICAgIHVwZGF0ZUdsb2JhbEJ1ZmZlckFuZFZpZXdzKHdhc21NZW1vcnkuYnVmZmVyKTsKICAgICAgICAgICAgICB3YXNtVGFibGUgPSBNb2R1bGVbImFzbSJdWyJPIl07CiAgICAgICAgICAgICAgYWRkT25Jbml0KE1vZHVsZVsiYXNtIl1bIkwiXSk7CiAgICAgICAgICAgICAgcmVtb3ZlUnVuRGVwZW5kZW5jeSgid2FzbS1pbnN0YW50aWF0ZSIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGFkZFJ1bkRlcGVuZGVuY3koIndhc20taW5zdGFudGlhdGUiKTsKICAgICAgICAgICAgZnVuY3Rpb24gcmVjZWl2ZUluc3RhbnRpYXRlZFNvdXJjZShvdXRwdXQpIHsKICAgICAgICAgICAgICByZWNlaXZlSW5zdGFuY2Uob3V0cHV0WyJpbnN0YW5jZSJdKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmdW5jdGlvbiBpbnN0YW50aWF0ZUFycmF5QnVmZmVyKHJlY2VpdmVyKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGdldEJpbmFyeVByb21pc2UoKS50aGVuKGZ1bmN0aW9uKGJpbmFyeSkgewogICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGJpbmFyeSwgaW5mbyk7CiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgICAgICAgIH0pLnRoZW4ocmVjZWl2ZXIsIGZ1bmN0aW9uKHJlYXNvbikgewogICAgICAgICAgICAgICAgZXJyKCJmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiAiICsgcmVhc29uKTsKICAgICAgICAgICAgICAgIGFib3J0KHJlYXNvbik7CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZnVuY3Rpb24gaW5zdGFudGlhdGVBc3luYygpIHsKICAgICAgICAgICAgICBpZiAoIXdhc21CaW5hcnkgJiYgdHlwZW9mIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nID09PSAiZnVuY3Rpb24iICYmICFpc0RhdGFVUkkod2FzbUJpbmFyeUZpbGUpICYmICFpc0ZpbGVVUkkod2FzbUJpbmFyeUZpbGUpICYmIHR5cGVvZiBmZXRjaCA9PT0gImZ1bmN0aW9uIikgewogICAgICAgICAgICAgICAgcmV0dXJuIGZldGNoKHdhc21CaW5hcnlGaWxlLCB7IGNyZWRlbnRpYWxzOiAic2FtZS1vcmlnaW4iIH0pLnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHsKICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nKHJlc3BvbnNlLCBpbmZvKTsKICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC50aGVuKHJlY2VpdmVJbnN0YW50aWF0ZWRTb3VyY2UsIGZ1bmN0aW9uKHJlYXNvbikgewogICAgICAgICAgICAgICAgICAgIGVycigid2FzbSBzdHJlYW1pbmcgY29tcGlsZSBmYWlsZWQ6ICIgKyByZWFzb24pOwogICAgICAgICAgICAgICAgICAgIGVycigiZmFsbGluZyBiYWNrIHRvIEFycmF5QnVmZmVyIGluc3RhbnRpYXRpb24iKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zdGFudGlhdGVBcnJheUJ1ZmZlcihyZWNlaXZlSW5zdGFudGlhdGVkU291cmNlKTsKICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgcmV0dXJuIGluc3RhbnRpYXRlQXJyYXlCdWZmZXIocmVjZWl2ZUluc3RhbnRpYXRlZFNvdXJjZSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChNb2R1bGVbImluc3RhbnRpYXRlV2FzbSJdKSB7CiAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHZhciBleHBvcnRzMyA9IE1vZHVsZVsiaW5zdGFudGlhdGVXYXNtIl0oaW5mbywgcmVjZWl2ZUluc3RhbmNlKTsKICAgICAgICAgICAgICAgIHJldHVybiBleHBvcnRzMzsKICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICBlcnIoIk1vZHVsZS5pbnN0YW50aWF0ZVdhc20gY2FsbGJhY2sgZmFpbGVkIHdpdGggZXJyb3I6ICIgKyBlKTsKICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaW5zdGFudGlhdGVBc3luYygpLmNhdGNoKHJlYWR5UHJvbWlzZVJlamVjdCk7CiAgICAgICAgICAgIHJldHVybiB7fTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGNhbGxSdW50aW1lQ2FsbGJhY2tzKGNhbGxiYWNrcykgewogICAgICAgICAgICB3aGlsZSAoY2FsbGJhY2tzLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgICB2YXIgY2FsbGJhY2sgPSBjYWxsYmFja3Muc2hpZnQoKTsKICAgICAgICAgICAgICBpZiAodHlwZW9mIGNhbGxiYWNrID09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgICAgICAgIGNhbGxiYWNrKE1vZHVsZSk7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBjYWxsYmFjay5mdW5jOwogICAgICAgICAgICAgIGlmICh0eXBlb2YgZnVuYyA9PT0gIm51bWJlciIpIHsKICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjay5hcmcgPT09IHZvaWQgMCkgewogICAgICAgICAgICAgICAgICB3YXNtVGFibGUuZ2V0KGZ1bmMpKCk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICB3YXNtVGFibGUuZ2V0KGZ1bmMpKGNhbGxiYWNrLmFyZyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGZ1bmMoY2FsbGJhY2suYXJnID09PSB2b2lkIDAgPyBudWxsIDogY2FsbGJhY2suYXJnKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHZhciBzdHJ1Y3RSZWdpc3RyYXRpb25zID0ge307CiAgICAgICAgICBmdW5jdGlvbiBydW5EZXN0cnVjdG9ycyhkZXN0cnVjdG9ycykgewogICAgICAgICAgICB3aGlsZSAoZGVzdHJ1Y3RvcnMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgdmFyIHB0ciA9IGRlc3RydWN0b3JzLnBvcCgpOwogICAgICAgICAgICAgIHZhciBkZWwgPSBkZXN0cnVjdG9ycy5wb3AoKTsKICAgICAgICAgICAgICBkZWwocHRyKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gc2ltcGxlUmVhZFZhbHVlRnJvbVBvaW50ZXIocG9pbnRlcikgewogICAgICAgICAgICByZXR1cm4gdGhpc1siZnJvbVdpcmVUeXBlIl0oSEVBUFUzMltwb2ludGVyID4+IDJdKTsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBhd2FpdGluZ0RlcGVuZGVuY2llcyA9IHt9OwogICAgICAgICAgdmFyIHJlZ2lzdGVyZWRUeXBlcyA9IHt9OwogICAgICAgICAgdmFyIHR5cGVEZXBlbmRlbmNpZXMgPSB7fTsKICAgICAgICAgIHZhciBjaGFyXzAgPSA0ODsKICAgICAgICAgIHZhciBjaGFyXzkgPSA1NzsKICAgICAgICAgIGZ1bmN0aW9uIG1ha2VMZWdhbEZ1bmN0aW9uTmFtZShuYW1lKSB7CiAgICAgICAgICAgIGlmICh2b2lkIDAgPT09IG5hbWUpIHsKICAgICAgICAgICAgICByZXR1cm4gIl91bmtub3duIjsKICAgICAgICAgICAgfQogICAgICAgICAgICBuYW1lID0gbmFtZS5yZXBsYWNlKC9bXmEtekEtWjAtOV9dL2csICIkIik7CiAgICAgICAgICAgIHZhciBmID0gbmFtZS5jaGFyQ29kZUF0KDApOwogICAgICAgICAgICBpZiAoZiA+PSBjaGFyXzAgJiYgZiA8PSBjaGFyXzkpIHsKICAgICAgICAgICAgICByZXR1cm4gIl8iICsgbmFtZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByZXR1cm4gbmFtZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gY3JlYXRlTmFtZWRGdW5jdGlvbihuYW1lLCBib2R5KSB7CiAgICAgICAgICAgIG5hbWUgPSBtYWtlTGVnYWxGdW5jdGlvbk5hbWUobmFtZSk7CiAgICAgICAgICAgIHJldHVybiBuZXcgRnVuY3Rpb24oImJvZHkiLCAicmV0dXJuIGZ1bmN0aW9uICIgKyBuYW1lICsgJygpIHtcbiAgICAidXNlIHN0cmljdCI7ICAgIHJldHVybiBib2R5LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59O1xuJykoYm9keSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBleHRlbmRFcnJvcihiYXNlRXJyb3JUeXBlLCBlcnJvck5hbWUpIHsKICAgICAgICAgICAgdmFyIGVycm9yQ2xhc3MgPSBjcmVhdGVOYW1lZEZ1bmN0aW9uKGVycm9yTmFtZSwgZnVuY3Rpb24obWVzc2FnZSkgewogICAgICAgICAgICAgIHRoaXMubmFtZSA9IGVycm9yTmFtZTsKICAgICAgICAgICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlOwogICAgICAgICAgICAgIHZhciBzdGFjayA9IG5ldyBFcnJvcihtZXNzYWdlKS5zdGFjazsKICAgICAgICAgICAgICBpZiAoc3RhY2sgIT09IHZvaWQgMCkgewogICAgICAgICAgICAgICAgdGhpcy5zdGFjayA9IHRoaXMudG9TdHJpbmcoKSArICJcbiIgKyBzdGFjay5yZXBsYWNlKC9eRXJyb3IoOlteXG5dKik/XG4vLCAiIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgZXJyb3JDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKGJhc2VFcnJvclR5cGUucHJvdG90eXBlKTsKICAgICAgICAgICAgZXJyb3JDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBlcnJvckNsYXNzOwogICAgICAgICAgICBlcnJvckNsYXNzLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIGlmICh0aGlzLm1lc3NhZ2UgPT09IHZvaWQgMCkgewogICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubmFtZTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubmFtZSArICI6ICIgKyB0aGlzLm1lc3NhZ2U7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9OwogICAgICAgICAgICByZXR1cm4gZXJyb3JDbGFzczsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBJbnRlcm5hbEVycm9yID0gdm9pZCAwOwogICAgICAgICAgZnVuY3Rpb24gdGhyb3dJbnRlcm5hbEVycm9yKG1lc3NhZ2UpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IobWVzc2FnZSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiB3aGVuRGVwZW5kZW50VHlwZXNBcmVSZXNvbHZlZChteVR5cGVzLCBkZXBlbmRlbnRUeXBlcywgZ2V0VHlwZUNvbnZlcnRlcnMpIHsKICAgICAgICAgICAgbXlUeXBlcy5mb3JFYWNoKGZ1bmN0aW9uKHR5cGUpIHsKICAgICAgICAgICAgICB0eXBlRGVwZW5kZW5jaWVzW3R5cGVdID0gZGVwZW5kZW50VHlwZXM7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBmdW5jdGlvbiBvbkNvbXBsZXRlKHR5cGVDb252ZXJ0ZXJzMikgewogICAgICAgICAgICAgIHZhciBteVR5cGVDb252ZXJ0ZXJzID0gZ2V0VHlwZUNvbnZlcnRlcnModHlwZUNvbnZlcnRlcnMyKTsKICAgICAgICAgICAgICBpZiAobXlUeXBlQ29udmVydGVycy5sZW5ndGggIT09IG15VHlwZXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICB0aHJvd0ludGVybmFsRXJyb3IoIk1pc21hdGNoZWQgdHlwZSBjb252ZXJ0ZXIgY291bnQiKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBteVR5cGVzLmxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgICAgICByZWdpc3RlclR5cGUobXlUeXBlc1tpXSwgbXlUeXBlQ29udmVydGVyc1tpXSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciB0eXBlQ29udmVydGVycyA9IG5ldyBBcnJheShkZXBlbmRlbnRUeXBlcy5sZW5ndGgpOwogICAgICAgICAgICB2YXIgdW5yZWdpc3RlcmVkVHlwZXMgPSBbXTsKICAgICAgICAgICAgdmFyIHJlZ2lzdGVyZWQgPSAwOwogICAgICAgICAgICBkZXBlbmRlbnRUeXBlcy5mb3JFYWNoKGZ1bmN0aW9uKGR0LCBpKSB7CiAgICAgICAgICAgICAgaWYgKHJlZ2lzdGVyZWRUeXBlcy5oYXNPd25Qcm9wZXJ0eShkdCkpIHsKICAgICAgICAgICAgICAgIHR5cGVDb252ZXJ0ZXJzW2ldID0gcmVnaXN0ZXJlZFR5cGVzW2R0XTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgdW5yZWdpc3RlcmVkVHlwZXMucHVzaChkdCk7CiAgICAgICAgICAgICAgICBpZiAoIWF3YWl0aW5nRGVwZW5kZW5jaWVzLmhhc093blByb3BlcnR5KGR0KSkgewogICAgICAgICAgICAgICAgICBhd2FpdGluZ0RlcGVuZGVuY2llc1tkdF0gPSBbXTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGF3YWl0aW5nRGVwZW5kZW5jaWVzW2R0XS5wdXNoKGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgICB0eXBlQ29udmVydGVyc1tpXSA9IHJlZ2lzdGVyZWRUeXBlc1tkdF07CiAgICAgICAgICAgICAgICAgICsrcmVnaXN0ZXJlZDsKICAgICAgICAgICAgICAgICAgaWYgKHJlZ2lzdGVyZWQgPT09IHVucmVnaXN0ZXJlZFR5cGVzLmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgIG9uQ29tcGxldGUodHlwZUNvbnZlcnRlcnMpOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBpZiAoMCA9PT0gdW5yZWdpc3RlcmVkVHlwZXMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgb25Db21wbGV0ZSh0eXBlQ29udmVydGVycyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIF9fZW1iaW5kX2ZpbmFsaXplX3ZhbHVlX29iamVjdChzdHJ1Y3RUeXBlKSB7CiAgICAgICAgICAgIHZhciByZWcgPSBzdHJ1Y3RSZWdpc3RyYXRpb25zW3N0cnVjdFR5cGVdOwogICAgICAgICAgICBkZWxldGUgc3RydWN0UmVnaXN0cmF0aW9uc1tzdHJ1Y3RUeXBlXTsKICAgICAgICAgICAgdmFyIHJhd0NvbnN0cnVjdG9yID0gcmVnLnJhd0NvbnN0cnVjdG9yOwogICAgICAgICAgICB2YXIgcmF3RGVzdHJ1Y3RvciA9IHJlZy5yYXdEZXN0cnVjdG9yOwogICAgICAgICAgICB2YXIgZmllbGRSZWNvcmRzID0gcmVnLmZpZWxkczsKICAgICAgICAgICAgdmFyIGZpZWxkVHlwZXMgPSBmaWVsZFJlY29yZHMubWFwKGZ1bmN0aW9uKGZpZWxkKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZpZWxkLmdldHRlclJldHVyblR5cGU7CiAgICAgICAgICAgIH0pLmNvbmNhdChmaWVsZFJlY29yZHMubWFwKGZ1bmN0aW9uKGZpZWxkKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGZpZWxkLnNldHRlckFyZ3VtZW50VHlwZTsKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICB3aGVuRGVwZW5kZW50VHlwZXNBcmVSZXNvbHZlZChbc3RydWN0VHlwZV0sIGZpZWxkVHlwZXMsIGZ1bmN0aW9uKGZpZWxkVHlwZXMyKSB7CiAgICAgICAgICAgICAgdmFyIGZpZWxkcyA9IHt9OwogICAgICAgICAgICAgIGZpZWxkUmVjb3Jkcy5mb3JFYWNoKGZ1bmN0aW9uKGZpZWxkLCBpKSB7CiAgICAgICAgICAgICAgICB2YXIgZmllbGROYW1lID0gZmllbGQuZmllbGROYW1lOwogICAgICAgICAgICAgICAgdmFyIGdldHRlclJldHVyblR5cGUgPSBmaWVsZFR5cGVzMltpXTsKICAgICAgICAgICAgICAgIHZhciBnZXR0ZXIgPSBmaWVsZC5nZXR0ZXI7CiAgICAgICAgICAgICAgICB2YXIgZ2V0dGVyQ29udGV4dCA9IGZpZWxkLmdldHRlckNvbnRleHQ7CiAgICAgICAgICAgICAgICB2YXIgc2V0dGVyQXJndW1lbnRUeXBlID0gZmllbGRUeXBlczJbaSArIGZpZWxkUmVjb3Jkcy5sZW5ndGhdOwogICAgICAgICAgICAgICAgdmFyIHNldHRlciA9IGZpZWxkLnNldHRlcjsKICAgICAgICAgICAgICAgIHZhciBzZXR0ZXJDb250ZXh0ID0gZmllbGQuc2V0dGVyQ29udGV4dDsKICAgICAgICAgICAgICAgIGZpZWxkc1tmaWVsZE5hbWVdID0geyByZWFkOiBmdW5jdGlvbihwdHIpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuIGdldHRlclJldHVyblR5cGVbImZyb21XaXJlVHlwZSJdKGdldHRlcihnZXR0ZXJDb250ZXh0LCBwdHIpKTsKICAgICAgICAgICAgICAgIH0sIHdyaXRlOiBmdW5jdGlvbihwdHIsIG8pIHsKICAgICAgICAgICAgICAgICAgdmFyIGRlc3RydWN0b3JzID0gW107CiAgICAgICAgICAgICAgICAgIHNldHRlcihzZXR0ZXJDb250ZXh0LCBwdHIsIHNldHRlckFyZ3VtZW50VHlwZVsidG9XaXJlVHlwZSJdKGRlc3RydWN0b3JzLCBvKSk7CiAgICAgICAgICAgICAgICAgIHJ1bkRlc3RydWN0b3JzKGRlc3RydWN0b3JzKTsKICAgICAgICAgICAgICAgIH0gfTsKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICByZXR1cm4gW3sgbmFtZTogcmVnLm5hbWUsICJmcm9tV2lyZVR5cGUiOiBmdW5jdGlvbihwdHIpIHsKICAgICAgICAgICAgICAgIHZhciBydiA9IHt9OwogICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBmaWVsZHMpIHsKICAgICAgICAgICAgICAgICAgcnZbaV0gPSBmaWVsZHNbaV0ucmVhZChwdHIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmF3RGVzdHJ1Y3RvcihwdHIpOwogICAgICAgICAgICAgICAgcmV0dXJuIHJ2OwogICAgICAgICAgICAgIH0sICJ0b1dpcmVUeXBlIjogZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsIG8pIHsKICAgICAgICAgICAgICAgIGZvciAodmFyIGZpZWxkTmFtZSBpbiBmaWVsZHMpIHsKICAgICAgICAgICAgICAgICAgaWYgKCEoZmllbGROYW1lIGluIG8pKSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignTWlzc2luZyBmaWVsZDogICInICsgZmllbGROYW1lICsgJyInKTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIHB0ciA9IHJhd0NvbnN0cnVjdG9yKCk7CiAgICAgICAgICAgICAgICBmb3IgKGZpZWxkTmFtZSBpbiBmaWVsZHMpIHsKICAgICAgICAgICAgICAgICAgZmllbGRzW2ZpZWxkTmFtZV0ud3JpdGUocHRyLCBvW2ZpZWxkTmFtZV0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKGRlc3RydWN0b3JzICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIGRlc3RydWN0b3JzLnB1c2gocmF3RGVzdHJ1Y3RvciwgcHRyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybiBwdHI7CiAgICAgICAgICAgICAgfSwgImFyZ1BhY2tBZHZhbmNlIjogOCwgInJlYWRWYWx1ZUZyb21Qb2ludGVyIjogc2ltcGxlUmVhZFZhbHVlRnJvbVBvaW50ZXIsIGRlc3RydWN0b3JGdW5jdGlvbjogcmF3RGVzdHJ1Y3RvciB9XTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBnZXRTaGlmdEZyb21TaXplKHNpemUpIHsKICAgICAgICAgICAgc3dpdGNoIChzaXplKSB7CiAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgcmV0dXJuIDE7CiAgICAgICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICAgICAgcmV0dXJuIDI7CiAgICAgICAgICAgICAgY2FzZSA4OgogICAgICAgICAgICAgICAgcmV0dXJuIDM7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIlVua25vd24gdHlwZSBzaXplOiAiICsgc2l6ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGVtYmluZF9pbml0X2NoYXJDb2RlcygpIHsKICAgICAgICAgICAgdmFyIGNvZGVzID0gbmV3IEFycmF5KDI1Nik7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMjU2OyArK2kpIHsKICAgICAgICAgICAgICBjb2Rlc1tpXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoaSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZW1iaW5kX2NoYXJDb2RlcyA9IGNvZGVzOwogICAgICAgICAgfQogICAgICAgICAgdmFyIGVtYmluZF9jaGFyQ29kZXMgPSB2b2lkIDA7CiAgICAgICAgICBmdW5jdGlvbiByZWFkTGF0aW4xU3RyaW5nKHB0cikgewogICAgICAgICAgICB2YXIgcmV0ID0gIiI7CiAgICAgICAgICAgIHZhciBjID0gcHRyOwogICAgICAgICAgICB3aGlsZSAoSEVBUFU4W2NdKSB7CiAgICAgICAgICAgICAgcmV0ICs9IGVtYmluZF9jaGFyQ29kZXNbSEVBUFU4W2MrK11dOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiByZXQ7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgQmluZGluZ0Vycm9yID0gdm9pZCAwOwogICAgICAgICAgZnVuY3Rpb24gdGhyb3dCaW5kaW5nRXJyb3IobWVzc2FnZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgQmluZGluZ0Vycm9yKG1lc3NhZ2UpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gcmVnaXN0ZXJUeXBlKHJhd1R5cGUsIHJlZ2lzdGVyZWRJbnN0YW5jZSwgb3B0aW9ucykgewogICAgICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTsKICAgICAgICAgICAgaWYgKCEoImFyZ1BhY2tBZHZhbmNlIiBpbiByZWdpc3RlcmVkSW5zdGFuY2UpKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigicmVnaXN0ZXJUeXBlIHJlZ2lzdGVyZWRJbnN0YW5jZSByZXF1aXJlcyBhcmdQYWNrQWR2YW5jZSIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBuYW1lID0gcmVnaXN0ZXJlZEluc3RhbmNlLm5hbWU7CiAgICAgICAgICAgIGlmICghcmF3VHlwZSkgewogICAgICAgICAgICAgIHRocm93QmluZGluZ0Vycm9yKCd0eXBlICInICsgbmFtZSArICciIG11c3QgaGF2ZSBhIHBvc2l0aXZlIGludGVnZXIgdHlwZWlkIHBvaW50ZXInKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocmVnaXN0ZXJlZFR5cGVzLmhhc093blByb3BlcnR5KHJhd1R5cGUpKSB7CiAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuaWdub3JlRHVwbGljYXRlUmVnaXN0cmF0aW9ucykgewogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiQ2Fubm90IHJlZ2lzdGVyIHR5cGUgJyIgKyBuYW1lICsgIicgdHdpY2UiKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVnaXN0ZXJlZFR5cGVzW3Jhd1R5cGVdID0gcmVnaXN0ZXJlZEluc3RhbmNlOwogICAgICAgICAgICBkZWxldGUgdHlwZURlcGVuZGVuY2llc1tyYXdUeXBlXTsKICAgICAgICAgICAgaWYgKGF3YWl0aW5nRGVwZW5kZW5jaWVzLmhhc093blByb3BlcnR5KHJhd1R5cGUpKSB7CiAgICAgICAgICAgICAgdmFyIGNhbGxiYWNrcyA9IGF3YWl0aW5nRGVwZW5kZW5jaWVzW3Jhd1R5cGVdOwogICAgICAgICAgICAgIGRlbGV0ZSBhd2FpdGluZ0RlcGVuZGVuY2llc1tyYXdUeXBlXTsKICAgICAgICAgICAgICBjYWxsYmFja3MuZm9yRWFjaChmdW5jdGlvbihjYikgewogICAgICAgICAgICAgICAgY2IoKTsKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbWJpbmRfcmVnaXN0ZXJfYm9vbChyYXdUeXBlLCBuYW1lLCBzaXplLCB0cnVlVmFsdWUsIGZhbHNlVmFsdWUpIHsKICAgICAgICAgICAgdmFyIHNoaWZ0ID0gZ2V0U2hpZnRGcm9tU2l6ZShzaXplKTsKICAgICAgICAgICAgbmFtZSA9IHJlYWRMYXRpbjFTdHJpbmcobmFtZSk7CiAgICAgICAgICAgIHJlZ2lzdGVyVHlwZShyYXdUeXBlLCB7IG5hbWUsICJmcm9tV2lyZVR5cGUiOiBmdW5jdGlvbih3dCkgewogICAgICAgICAgICAgIHJldHVybiAhIXd0OwogICAgICAgICAgICB9LCAidG9XaXJlVHlwZSI6IGZ1bmN0aW9uKGRlc3RydWN0b3JzLCBvKSB7CiAgICAgICAgICAgICAgcmV0dXJuIG8gPyB0cnVlVmFsdWUgOiBmYWxzZVZhbHVlOwogICAgICAgICAgICB9LCAiYXJnUGFja0FkdmFuY2UiOiA4LCAicmVhZFZhbHVlRnJvbVBvaW50ZXIiOiBmdW5jdGlvbihwb2ludGVyKSB7CiAgICAgICAgICAgICAgdmFyIGhlYXA7CiAgICAgICAgICAgICAgaWYgKHNpemUgPT09IDEpIHsKICAgICAgICAgICAgICAgIGhlYXAgPSBIRUFQODsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKHNpemUgPT09IDIpIHsKICAgICAgICAgICAgICAgIGhlYXAgPSBIRUFQMTY7CiAgICAgICAgICAgICAgfSBlbHNlIGlmIChzaXplID09PSA0KSB7CiAgICAgICAgICAgICAgICBoZWFwID0gSEVBUDMyOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJVbmtub3duIGJvb2xlYW4gdHlwZSBzaXplOiAiICsgbmFtZSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShoZWFwW3BvaW50ZXIgPj4gc2hpZnRdKTsKICAgICAgICAgICAgfSwgZGVzdHJ1Y3RvckZ1bmN0aW9uOiBudWxsIH0pOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gQ2xhc3NIYW5kbGVfaXNBbGlhc09mKG90aGVyKSB7CiAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBDbGFzc0hhbmRsZSkpIHsKICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCEob3RoZXIgaW5zdGFuY2VvZiBDbGFzc0hhbmRsZSkpIHsKICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGxlZnRDbGFzcyA9IHRoaXMuJCQucHRyVHlwZS5yZWdpc3RlcmVkQ2xhc3M7CiAgICAgICAgICAgIHZhciBsZWZ0ID0gdGhpcy4kJC5wdHI7CiAgICAgICAgICAgIHZhciByaWdodENsYXNzID0gb3RoZXIuJCQucHRyVHlwZS5yZWdpc3RlcmVkQ2xhc3M7CiAgICAgICAgICAgIHZhciByaWdodCA9IG90aGVyLiQkLnB0cjsKICAgICAgICAgICAgd2hpbGUgKGxlZnRDbGFzcy5iYXNlQ2xhc3MpIHsKICAgICAgICAgICAgICBsZWZ0ID0gbGVmdENsYXNzLnVwY2FzdChsZWZ0KTsKICAgICAgICAgICAgICBsZWZ0Q2xhc3MgPSBsZWZ0Q2xhc3MuYmFzZUNsYXNzOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHdoaWxlIChyaWdodENsYXNzLmJhc2VDbGFzcykgewogICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHRDbGFzcy51cGNhc3QocmlnaHQpOwogICAgICAgICAgICAgIHJpZ2h0Q2xhc3MgPSByaWdodENsYXNzLmJhc2VDbGFzczsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbGVmdENsYXNzID09PSByaWdodENsYXNzICYmIGxlZnQgPT09IHJpZ2h0OwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gc2hhbGxvd0NvcHlJbnRlcm5hbFBvaW50ZXIobykgewogICAgICAgICAgICByZXR1cm4geyBjb3VudDogby5jb3VudCwgZGVsZXRlU2NoZWR1bGVkOiBvLmRlbGV0ZVNjaGVkdWxlZCwgcHJlc2VydmVQb2ludGVyT25EZWxldGU6IG8ucHJlc2VydmVQb2ludGVyT25EZWxldGUsIHB0cjogby5wdHIsIHB0clR5cGU6IG8ucHRyVHlwZSwgc21hcnRQdHI6IG8uc21hcnRQdHIsIHNtYXJ0UHRyVHlwZTogby5zbWFydFB0clR5cGUgfTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHRocm93SW5zdGFuY2VBbHJlYWR5RGVsZXRlZChvYmopIHsKICAgICAgICAgICAgZnVuY3Rpb24gZ2V0SW5zdGFuY2VUeXBlTmFtZShoYW5kbGUpIHsKICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlLiQkLnB0clR5cGUucmVnaXN0ZXJlZENsYXNzLm5hbWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoZ2V0SW5zdGFuY2VUeXBlTmFtZShvYmopICsgIiBpbnN0YW5jZSBhbHJlYWR5IGRlbGV0ZWQiKTsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBmaW5hbGl6YXRpb25Hcm91cCA9IGZhbHNlOwogICAgICAgICAgZnVuY3Rpb24gZGV0YWNoRmluYWxpemVyKGhhbmRsZSkgewogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gcnVuRGVzdHJ1Y3RvcigkJCkgewogICAgICAgICAgICBpZiAoJCQuc21hcnRQdHIpIHsKICAgICAgICAgICAgICAkJC5zbWFydFB0clR5cGUucmF3RGVzdHJ1Y3RvcigkJC5zbWFydFB0cik7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgJCQucHRyVHlwZS5yZWdpc3RlcmVkQ2xhc3MucmF3RGVzdHJ1Y3RvcigkJC5wdHIpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiByZWxlYXNlQ2xhc3NIYW5kbGUoJCQpIHsKICAgICAgICAgICAgJCQuY291bnQudmFsdWUgLT0gMTsKICAgICAgICAgICAgdmFyIHRvRGVsZXRlID0gMCA9PT0gJCQuY291bnQudmFsdWU7CiAgICAgICAgICAgIGlmICh0b0RlbGV0ZSkgewogICAgICAgICAgICAgIHJ1bkRlc3RydWN0b3IoJCQpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBhdHRhY2hGaW5hbGl6ZXIoaGFuZGxlKSB7CiAgICAgICAgICAgIGlmICgidW5kZWZpbmVkIiA9PT0gdHlwZW9mIEZpbmFsaXphdGlvbkdyb3VwKSB7CiAgICAgICAgICAgICAgYXR0YWNoRmluYWxpemVyID0gZnVuY3Rpb24oaGFuZGxlMikgewogICAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZTI7CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZpbmFsaXphdGlvbkdyb3VwID0gbmV3IEZpbmFsaXphdGlvbkdyb3VwKGZ1bmN0aW9uKGl0ZXIpIHsKICAgICAgICAgICAgICBmb3IgKHZhciByZXN1bHQgPSBpdGVyLm5leHQoKTsgIXJlc3VsdC5kb25lOyByZXN1bHQgPSBpdGVyLm5leHQoKSkgewogICAgICAgICAgICAgICAgdmFyICQkID0gcmVzdWx0LnZhbHVlOwogICAgICAgICAgICAgICAgaWYgKCEkJC5wdHIpIHsKICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCJvYmplY3QgYWxyZWFkeSBkZWxldGVkOiAiICsgJCQucHRyKTsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIHJlbGVhc2VDbGFzc0hhbmRsZSgkJCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgYXR0YWNoRmluYWxpemVyID0gZnVuY3Rpb24oaGFuZGxlMikgewogICAgICAgICAgICAgIGZpbmFsaXphdGlvbkdyb3VwLnJlZ2lzdGVyKGhhbmRsZTIsIGhhbmRsZTIuJCQsIGhhbmRsZTIuJCQpOwogICAgICAgICAgICAgIHJldHVybiBoYW5kbGUyOwogICAgICAgICAgICB9OwogICAgICAgICAgICBkZXRhY2hGaW5hbGl6ZXIgPSBmdW5jdGlvbihoYW5kbGUyKSB7CiAgICAgICAgICAgICAgZmluYWxpemF0aW9uR3JvdXAudW5yZWdpc3RlcihoYW5kbGUyLiQkKTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgcmV0dXJuIGF0dGFjaEZpbmFsaXplcihoYW5kbGUpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gQ2xhc3NIYW5kbGVfY2xvbmUoKSB7CiAgICAgICAgICAgIGlmICghdGhpcy4kJC5wdHIpIHsKICAgICAgICAgICAgICB0aHJvd0luc3RhbmNlQWxyZWFkeURlbGV0ZWQodGhpcyk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHRoaXMuJCQucHJlc2VydmVQb2ludGVyT25EZWxldGUpIHsKICAgICAgICAgICAgICB0aGlzLiQkLmNvdW50LnZhbHVlICs9IDE7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdmFyIGNsb25lMiA9IGF0dGFjaEZpbmFsaXplcihPYmplY3QuY3JlYXRlKE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzKSwgeyAkJDogeyB2YWx1ZTogc2hhbGxvd0NvcHlJbnRlcm5hbFBvaW50ZXIodGhpcy4kJCkgfSB9KSk7CiAgICAgICAgICAgICAgY2xvbmUyLiQkLmNvdW50LnZhbHVlICs9IDE7CiAgICAgICAgICAgICAgY2xvbmUyLiQkLmRlbGV0ZVNjaGVkdWxlZCA9IGZhbHNlOwogICAgICAgICAgICAgIHJldHVybiBjbG9uZTI7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIENsYXNzSGFuZGxlX2RlbGV0ZSgpIHsKICAgICAgICAgICAgaWYgKCF0aGlzLiQkLnB0cikgewogICAgICAgICAgICAgIHRocm93SW5zdGFuY2VBbHJlYWR5RGVsZXRlZCh0aGlzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodGhpcy4kJC5kZWxldGVTY2hlZHVsZWQgJiYgIXRoaXMuJCQucHJlc2VydmVQb2ludGVyT25EZWxldGUpIHsKICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiT2JqZWN0IGFscmVhZHkgc2NoZWR1bGVkIGZvciBkZWxldGlvbiIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRldGFjaEZpbmFsaXplcih0aGlzKTsKICAgICAgICAgICAgcmVsZWFzZUNsYXNzSGFuZGxlKHRoaXMuJCQpOwogICAgICAgICAgICBpZiAoIXRoaXMuJCQucHJlc2VydmVQb2ludGVyT25EZWxldGUpIHsKICAgICAgICAgICAgICB0aGlzLiQkLnNtYXJ0UHRyID0gdm9pZCAwOwogICAgICAgICAgICAgIHRoaXMuJCQucHRyID0gdm9pZCAwOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBDbGFzc0hhbmRsZV9pc0RlbGV0ZWQoKSB7CiAgICAgICAgICAgIHJldHVybiAhdGhpcy4kJC5wdHI7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgZGVsYXlGdW5jdGlvbiA9IHZvaWQgMDsKICAgICAgICAgIHZhciBkZWxldGlvblF1ZXVlID0gW107CiAgICAgICAgICBmdW5jdGlvbiBmbHVzaFBlbmRpbmdEZWxldGVzKCkgewogICAgICAgICAgICB3aGlsZSAoZGVsZXRpb25RdWV1ZS5sZW5ndGgpIHsKICAgICAgICAgICAgICB2YXIgb2JqID0gZGVsZXRpb25RdWV1ZS5wb3AoKTsKICAgICAgICAgICAgICBvYmouJCQuZGVsZXRlU2NoZWR1bGVkID0gZmFsc2U7CiAgICAgICAgICAgICAgb2JqWyJkZWxldGUiXSgpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBDbGFzc0hhbmRsZV9kZWxldGVMYXRlcigpIHsKICAgICAgICAgICAgaWYgKCF0aGlzLiQkLnB0cikgewogICAgICAgICAgICAgIHRocm93SW5zdGFuY2VBbHJlYWR5RGVsZXRlZCh0aGlzKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodGhpcy4kJC5kZWxldGVTY2hlZHVsZWQgJiYgIXRoaXMuJCQucHJlc2VydmVQb2ludGVyT25EZWxldGUpIHsKICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiT2JqZWN0IGFscmVhZHkgc2NoZWR1bGVkIGZvciBkZWxldGlvbiIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRlbGV0aW9uUXVldWUucHVzaCh0aGlzKTsKICAgICAgICAgICAgaWYgKGRlbGV0aW9uUXVldWUubGVuZ3RoID09PSAxICYmIGRlbGF5RnVuY3Rpb24pIHsKICAgICAgICAgICAgICBkZWxheUZ1bmN0aW9uKGZsdXNoUGVuZGluZ0RlbGV0ZXMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuJCQuZGVsZXRlU2NoZWR1bGVkID0gdHJ1ZTsKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBpbml0X0NsYXNzSGFuZGxlKCkgewogICAgICAgICAgICBDbGFzc0hhbmRsZS5wcm90b3R5cGVbImlzQWxpYXNPZiJdID0gQ2xhc3NIYW5kbGVfaXNBbGlhc09mOwogICAgICAgICAgICBDbGFzc0hhbmRsZS5wcm90b3R5cGVbImNsb25lIl0gPSBDbGFzc0hhbmRsZV9jbG9uZTsKICAgICAgICAgICAgQ2xhc3NIYW5kbGUucHJvdG90eXBlWyJkZWxldGUiXSA9IENsYXNzSGFuZGxlX2RlbGV0ZTsKICAgICAgICAgICAgQ2xhc3NIYW5kbGUucHJvdG90eXBlWyJpc0RlbGV0ZWQiXSA9IENsYXNzSGFuZGxlX2lzRGVsZXRlZDsKICAgICAgICAgICAgQ2xhc3NIYW5kbGUucHJvdG90eXBlWyJkZWxldGVMYXRlciJdID0gQ2xhc3NIYW5kbGVfZGVsZXRlTGF0ZXI7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBDbGFzc0hhbmRsZSgpIHsKICAgICAgICAgIH0KICAgICAgICAgIHZhciByZWdpc3RlcmVkUG9pbnRlcnMgPSB7fTsKICAgICAgICAgIGZ1bmN0aW9uIGVuc3VyZU92ZXJsb2FkVGFibGUocHJvdG8sIG1ldGhvZE5hbWUsIGh1bWFuTmFtZSkgewogICAgICAgICAgICBpZiAodm9pZCAwID09PSBwcm90b1ttZXRob2ROYW1lXS5vdmVybG9hZFRhYmxlKSB7CiAgICAgICAgICAgICAgdmFyIHByZXZGdW5jID0gcHJvdG9bbWV0aG9kTmFtZV07CiAgICAgICAgICAgICAgcHJvdG9bbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICAgIGlmICghcHJvdG9bbWV0aG9kTmFtZV0ub3ZlcmxvYWRUYWJsZS5oYXNPd25Qcm9wZXJ0eShhcmd1bWVudHMubGVuZ3RoKSkgewogICAgICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiRnVuY3Rpb24gJyIgKyBodW1hbk5hbWUgKyAiJyBjYWxsZWQgd2l0aCBhbiBpbnZhbGlkIG51bWJlciBvZiBhcmd1bWVudHMgKCIgKyBhcmd1bWVudHMubGVuZ3RoICsgIikgLSBleHBlY3RzIG9uZSBvZiAoIiArIHByb3RvW21ldGhvZE5hbWVdLm92ZXJsb2FkVGFibGUgKyAiKSEiKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybiBwcm90b1ttZXRob2ROYW1lXS5vdmVybG9hZFRhYmxlW2FyZ3VtZW50cy5sZW5ndGhdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICBwcm90b1ttZXRob2ROYW1lXS5vdmVybG9hZFRhYmxlID0gW107CiAgICAgICAgICAgICAgcHJvdG9bbWV0aG9kTmFtZV0ub3ZlcmxvYWRUYWJsZVtwcmV2RnVuYy5hcmdDb3VudF0gPSBwcmV2RnVuYzsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZXhwb3NlUHVibGljU3ltYm9sKG5hbWUsIHZhbHVlLCBudW1Bcmd1bWVudHMpIHsKICAgICAgICAgICAgaWYgKE1vZHVsZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICAgICAgICAgIGlmICh2b2lkIDAgPT09IG51bUFyZ3VtZW50cyB8fCB2b2lkIDAgIT09IE1vZHVsZVtuYW1lXS5vdmVybG9hZFRhYmxlICYmIHZvaWQgMCAhPT0gTW9kdWxlW25hbWVdLm92ZXJsb2FkVGFibGVbbnVtQXJndW1lbnRzXSkgewogICAgICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoIkNhbm5vdCByZWdpc3RlciBwdWJsaWMgbmFtZSAnIiArIG5hbWUgKyAiJyB0d2ljZSIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBlbnN1cmVPdmVybG9hZFRhYmxlKE1vZHVsZSwgbmFtZSwgbmFtZSk7CiAgICAgICAgICAgICAgaWYgKE1vZHVsZS5oYXNPd25Qcm9wZXJ0eShudW1Bcmd1bWVudHMpKSB7CiAgICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiQ2Fubm90IHJlZ2lzdGVyIG11bHRpcGxlIG92ZXJsb2FkcyBvZiBhIGZ1bmN0aW9uIHdpdGggdGhlIHNhbWUgbnVtYmVyIG9mIGFyZ3VtZW50cyAoIiArIG51bUFyZ3VtZW50cyArICIpISIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBNb2R1bGVbbmFtZV0ub3ZlcmxvYWRUYWJsZVtudW1Bcmd1bWVudHNdID0gdmFsdWU7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgTW9kdWxlW25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgaWYgKHZvaWQgMCAhPT0gbnVtQXJndW1lbnRzKSB7CiAgICAgICAgICAgICAgICBNb2R1bGVbbmFtZV0ubnVtQXJndW1lbnRzID0gbnVtQXJndW1lbnRzOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gUmVnaXN0ZXJlZENsYXNzKG5hbWUsIGNvbnN0cnVjdG9yLCBpbnN0YW5jZVByb3RvdHlwZSwgcmF3RGVzdHJ1Y3RvciwgYmFzZUNsYXNzLCBnZXRBY3R1YWxUeXBlLCB1cGNhc3QsIGRvd25jYXN0KSB7CiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBjb25zdHJ1Y3RvcjsKICAgICAgICAgICAgdGhpcy5pbnN0YW5jZVByb3RvdHlwZSA9IGluc3RhbmNlUHJvdG90eXBlOwogICAgICAgICAgICB0aGlzLnJhd0Rlc3RydWN0b3IgPSByYXdEZXN0cnVjdG9yOwogICAgICAgICAgICB0aGlzLmJhc2VDbGFzcyA9IGJhc2VDbGFzczsKICAgICAgICAgICAgdGhpcy5nZXRBY3R1YWxUeXBlID0gZ2V0QWN0dWFsVHlwZTsKICAgICAgICAgICAgdGhpcy51cGNhc3QgPSB1cGNhc3Q7CiAgICAgICAgICAgIHRoaXMuZG93bmNhc3QgPSBkb3duY2FzdDsKICAgICAgICAgICAgdGhpcy5wdXJlVmlydHVhbEZ1bmN0aW9ucyA9IFtdOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gdXBjYXN0UG9pbnRlcihwdHIsIHB0ckNsYXNzLCBkZXNpcmVkQ2xhc3MpIHsKICAgICAgICAgICAgd2hpbGUgKHB0ckNsYXNzICE9PSBkZXNpcmVkQ2xhc3MpIHsKICAgICAgICAgICAgICBpZiAoIXB0ckNsYXNzLnVwY2FzdCkgewogICAgICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoIkV4cGVjdGVkIG51bGwgb3IgaW5zdGFuY2Ugb2YgIiArIGRlc2lyZWRDbGFzcy5uYW1lICsgIiwgZ290IGFuIGluc3RhbmNlIG9mICIgKyBwdHJDbGFzcy5uYW1lKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcHRyID0gcHRyQ2xhc3MudXBjYXN0KHB0cik7CiAgICAgICAgICAgICAgcHRyQ2xhc3MgPSBwdHJDbGFzcy5iYXNlQ2xhc3M7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHB0cjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGNvbnN0Tm9TbWFydFB0clJhd1BvaW50ZXJUb1dpcmVUeXBlKGRlc3RydWN0b3JzLCBoYW5kbGUpIHsKICAgICAgICAgICAgaWYgKGhhbmRsZSA9PT0gbnVsbCkgewogICAgICAgICAgICAgIGlmICh0aGlzLmlzUmVmZXJlbmNlKSB7CiAgICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigibnVsbCBpcyBub3QgYSB2YWxpZCAiICsgdGhpcy5uYW1lKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCFoYW5kbGUuJCQpIHsKICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcignQ2Fubm90IHBhc3MgIicgKyBfZW1iaW5kX3JlcHIoaGFuZGxlKSArICciIGFzIGEgJyArIHRoaXMubmFtZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCFoYW5kbGUuJCQucHRyKSB7CiAgICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoIkNhbm5vdCBwYXNzIGRlbGV0ZWQgb2JqZWN0IGFzIGEgcG9pbnRlciBvZiB0eXBlICIgKyB0aGlzLm5hbWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBoYW5kbGVDbGFzcyA9IGhhbmRsZS4kJC5wdHJUeXBlLnJlZ2lzdGVyZWRDbGFzczsKICAgICAgICAgICAgdmFyIHB0ciA9IHVwY2FzdFBvaW50ZXIoaGFuZGxlLiQkLnB0ciwgaGFuZGxlQ2xhc3MsIHRoaXMucmVnaXN0ZXJlZENsYXNzKTsKICAgICAgICAgICAgcmV0dXJuIHB0cjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGdlbmVyaWNQb2ludGVyVG9XaXJlVHlwZShkZXN0cnVjdG9ycywgaGFuZGxlKSB7CiAgICAgICAgICAgIHZhciBwdHI7CiAgICAgICAgICAgIGlmIChoYW5kbGUgPT09IG51bGwpIHsKICAgICAgICAgICAgICBpZiAodGhpcy5pc1JlZmVyZW5jZSkgewogICAgICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoIm51bGwgaXMgbm90IGEgdmFsaWQgIiArIHRoaXMubmFtZSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICh0aGlzLmlzU21hcnRQb2ludGVyKSB7CiAgICAgICAgICAgICAgICBwdHIgPSB0aGlzLnJhd0NvbnN0cnVjdG9yKCk7CiAgICAgICAgICAgICAgICBpZiAoZGVzdHJ1Y3RvcnMgIT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgZGVzdHJ1Y3RvcnMucHVzaCh0aGlzLnJhd0Rlc3RydWN0b3IsIHB0cik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXR1cm4gcHRyOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCFoYW5kbGUuJCQpIHsKICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcignQ2Fubm90IHBhc3MgIicgKyBfZW1iaW5kX3JlcHIoaGFuZGxlKSArICciIGFzIGEgJyArIHRoaXMubmFtZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCFoYW5kbGUuJCQucHRyKSB7CiAgICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoIkNhbm5vdCBwYXNzIGRlbGV0ZWQgb2JqZWN0IGFzIGEgcG9pbnRlciBvZiB0eXBlICIgKyB0aGlzLm5hbWUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICghdGhpcy5pc0NvbnN0ICYmIGhhbmRsZS4kJC5wdHJUeXBlLmlzQ29uc3QpIHsKICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiQ2Fubm90IGNvbnZlcnQgYXJndW1lbnQgb2YgdHlwZSAiICsgKGhhbmRsZS4kJC5zbWFydFB0clR5cGUgPyBoYW5kbGUuJCQuc21hcnRQdHJUeXBlLm5hbWUgOiBoYW5kbGUuJCQucHRyVHlwZS5uYW1lKSArICIgdG8gcGFyYW1ldGVyIHR5cGUgIiArIHRoaXMubmFtZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGhhbmRsZUNsYXNzID0gaGFuZGxlLiQkLnB0clR5cGUucmVnaXN0ZXJlZENsYXNzOwogICAgICAgICAgICBwdHIgPSB1cGNhc3RQb2ludGVyKGhhbmRsZS4kJC5wdHIsIGhhbmRsZUNsYXNzLCB0aGlzLnJlZ2lzdGVyZWRDbGFzcyk7CiAgICAgICAgICAgIGlmICh0aGlzLmlzU21hcnRQb2ludGVyKSB7CiAgICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gaGFuZGxlLiQkLnNtYXJ0UHRyKSB7CiAgICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiUGFzc2luZyByYXcgcG9pbnRlciB0byBzbWFydCBwb2ludGVyIGlzIGlsbGVnYWwiKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNoYXJpbmdQb2xpY3kpIHsKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgaWYgKGhhbmRsZS4kJC5zbWFydFB0clR5cGUgPT09IHRoaXMpIHsKICAgICAgICAgICAgICAgICAgICBwdHIgPSBoYW5kbGUuJCQuc21hcnRQdHI7CiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoIkNhbm5vdCBjb252ZXJ0IGFyZ3VtZW50IG9mIHR5cGUgIiArIChoYW5kbGUuJCQuc21hcnRQdHJUeXBlID8gaGFuZGxlLiQkLnNtYXJ0UHRyVHlwZS5uYW1lIDogaGFuZGxlLiQkLnB0clR5cGUubmFtZSkgKyAiIHRvIHBhcmFtZXRlciB0eXBlICIgKyB0aGlzLm5hbWUpOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICBwdHIgPSBoYW5kbGUuJCQuc21hcnRQdHI7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgICBpZiAoaGFuZGxlLiQkLnNtYXJ0UHRyVHlwZSA9PT0gdGhpcykgewogICAgICAgICAgICAgICAgICAgIHB0ciA9IGhhbmRsZS4kJC5zbWFydFB0cjsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB2YXIgY2xvbmVkSGFuZGxlID0gaGFuZGxlWyJjbG9uZSJdKCk7CiAgICAgICAgICAgICAgICAgICAgcHRyID0gdGhpcy5yYXdTaGFyZShwdHIsIF9fZW12YWxfcmVnaXN0ZXIoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICAgICAgICBjbG9uZWRIYW5kbGVbImRlbGV0ZSJdKCk7CiAgICAgICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgICAgIGlmIChkZXN0cnVjdG9ycyAhPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgICAgZGVzdHJ1Y3RvcnMucHVzaCh0aGlzLnJhd0Rlc3RydWN0b3IsIHB0cik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoIlVuc3VwcG9ydGluZyBzaGFyaW5nIHBvbGljeSIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gcHRyOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gbm9uQ29uc3ROb1NtYXJ0UHRyUmF3UG9pbnRlclRvV2lyZVR5cGUoZGVzdHJ1Y3RvcnMsIGhhbmRsZSkgewogICAgICAgICAgICBpZiAoaGFuZGxlID09PSBudWxsKSB7CiAgICAgICAgICAgICAgaWYgKHRoaXMuaXNSZWZlcmVuY2UpIHsKICAgICAgICAgICAgICAgIHRocm93QmluZGluZ0Vycm9yKCJudWxsIGlzIG5vdCBhIHZhbGlkICIgKyB0aGlzLm5hbWUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoIWhhbmRsZS4kJCkgewogICAgICAgICAgICAgIHRocm93QmluZGluZ0Vycm9yKCdDYW5ub3QgcGFzcyAiJyArIF9lbWJpbmRfcmVwcihoYW5kbGUpICsgJyIgYXMgYSAnICsgdGhpcy5uYW1lKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoIWhhbmRsZS4kJC5wdHIpIHsKICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiQ2Fubm90IHBhc3MgZGVsZXRlZCBvYmplY3QgYXMgYSBwb2ludGVyIG9mIHR5cGUgIiArIHRoaXMubmFtZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGhhbmRsZS4kJC5wdHJUeXBlLmlzQ29uc3QpIHsKICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiQ2Fubm90IGNvbnZlcnQgYXJndW1lbnQgb2YgdHlwZSAiICsgaGFuZGxlLiQkLnB0clR5cGUubmFtZSArICIgdG8gcGFyYW1ldGVyIHR5cGUgIiArIHRoaXMubmFtZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGhhbmRsZUNsYXNzID0gaGFuZGxlLiQkLnB0clR5cGUucmVnaXN0ZXJlZENsYXNzOwogICAgICAgICAgICB2YXIgcHRyID0gdXBjYXN0UG9pbnRlcihoYW5kbGUuJCQucHRyLCBoYW5kbGVDbGFzcywgdGhpcy5yZWdpc3RlcmVkQ2xhc3MpOwogICAgICAgICAgICByZXR1cm4gcHRyOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gUmVnaXN0ZXJlZFBvaW50ZXJfZ2V0UG9pbnRlZShwdHIpIHsKICAgICAgICAgICAgaWYgKHRoaXMucmF3R2V0UG9pbnRlZSkgewogICAgICAgICAgICAgIHB0ciA9IHRoaXMucmF3R2V0UG9pbnRlZShwdHIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBwdHI7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBSZWdpc3RlcmVkUG9pbnRlcl9kZXN0cnVjdG9yKHB0cikgewogICAgICAgICAgICBpZiAodGhpcy5yYXdEZXN0cnVjdG9yKSB7CiAgICAgICAgICAgICAgdGhpcy5yYXdEZXN0cnVjdG9yKHB0cik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIFJlZ2lzdGVyZWRQb2ludGVyX2RlbGV0ZU9iamVjdChoYW5kbGUpIHsKICAgICAgICAgICAgaWYgKGhhbmRsZSAhPT0gbnVsbCkgewogICAgICAgICAgICAgIGhhbmRsZVsiZGVsZXRlIl0oKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZG93bmNhc3RQb2ludGVyKHB0ciwgcHRyQ2xhc3MsIGRlc2lyZWRDbGFzcykgewogICAgICAgICAgICBpZiAocHRyQ2xhc3MgPT09IGRlc2lyZWRDbGFzcykgewogICAgICAgICAgICAgIHJldHVybiBwdHI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gZGVzaXJlZENsYXNzLmJhc2VDbGFzcykgewogICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBydiA9IGRvd25jYXN0UG9pbnRlcihwdHIsIHB0ckNsYXNzLCBkZXNpcmVkQ2xhc3MuYmFzZUNsYXNzKTsKICAgICAgICAgICAgaWYgKHJ2ID09PSBudWxsKSB7CiAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGRlc2lyZWRDbGFzcy5kb3duY2FzdChydik7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBnZXRJbmhlcml0ZWRJbnN0YW5jZUNvdW50KCkgewogICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMocmVnaXN0ZXJlZEluc3RhbmNlcykubGVuZ3RoOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZ2V0TGl2ZUluaGVyaXRlZEluc3RhbmNlcygpIHsKICAgICAgICAgICAgdmFyIHJ2ID0gW107CiAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcmVnaXN0ZXJlZEluc3RhbmNlcykgewogICAgICAgICAgICAgIGlmIChyZWdpc3RlcmVkSW5zdGFuY2VzLmhhc093blByb3BlcnR5KGspKSB7CiAgICAgICAgICAgICAgICBydi5wdXNoKHJlZ2lzdGVyZWRJbnN0YW5jZXNba10pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gcnY7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBzZXREZWxheUZ1bmN0aW9uKGZuKSB7CiAgICAgICAgICAgIGRlbGF5RnVuY3Rpb24gPSBmbjsKICAgICAgICAgICAgaWYgKGRlbGV0aW9uUXVldWUubGVuZ3RoICYmIGRlbGF5RnVuY3Rpb24pIHsKICAgICAgICAgICAgICBkZWxheUZ1bmN0aW9uKGZsdXNoUGVuZGluZ0RlbGV0ZXMpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBpbml0X2VtYmluZCgpIHsKICAgICAgICAgICAgTW9kdWxlWyJnZXRJbmhlcml0ZWRJbnN0YW5jZUNvdW50Il0gPSBnZXRJbmhlcml0ZWRJbnN0YW5jZUNvdW50OwogICAgICAgICAgICBNb2R1bGVbImdldExpdmVJbmhlcml0ZWRJbnN0YW5jZXMiXSA9IGdldExpdmVJbmhlcml0ZWRJbnN0YW5jZXM7CiAgICAgICAgICAgIE1vZHVsZVsiZmx1c2hQZW5kaW5nRGVsZXRlcyJdID0gZmx1c2hQZW5kaW5nRGVsZXRlczsKICAgICAgICAgICAgTW9kdWxlWyJzZXREZWxheUZ1bmN0aW9uIl0gPSBzZXREZWxheUZ1bmN0aW9uOwogICAgICAgICAgfQogICAgICAgICAgdmFyIHJlZ2lzdGVyZWRJbnN0YW5jZXMgPSB7fTsKICAgICAgICAgIGZ1bmN0aW9uIGdldEJhc2VzdFBvaW50ZXIoY2xhc3NfLCBwdHIpIHsKICAgICAgICAgICAgaWYgKHB0ciA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoInB0ciBzaG91bGQgbm90IGJlIHVuZGVmaW5lZCIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHdoaWxlIChjbGFzc18uYmFzZUNsYXNzKSB7CiAgICAgICAgICAgICAgcHRyID0gY2xhc3NfLnVwY2FzdChwdHIpOwogICAgICAgICAgICAgIGNsYXNzXyA9IGNsYXNzXy5iYXNlQ2xhc3M7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHB0cjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGdldEluaGVyaXRlZEluc3RhbmNlKGNsYXNzXywgcHRyKSB7CiAgICAgICAgICAgIHB0ciA9IGdldEJhc2VzdFBvaW50ZXIoY2xhc3NfLCBwdHIpOwogICAgICAgICAgICByZXR1cm4gcmVnaXN0ZXJlZEluc3RhbmNlc1twdHJdOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gbWFrZUNsYXNzSGFuZGxlKHByb3RvdHlwZSwgcmVjb3JkKSB7CiAgICAgICAgICAgIGlmICghcmVjb3JkLnB0clR5cGUgfHwgIXJlY29yZC5wdHIpIHsKICAgICAgICAgICAgICB0aHJvd0ludGVybmFsRXJyb3IoIm1ha2VDbGFzc0hhbmRsZSByZXF1aXJlcyBwdHIgYW5kIHB0clR5cGUiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgaGFzU21hcnRQdHJUeXBlID0gISFyZWNvcmQuc21hcnRQdHJUeXBlOwogICAgICAgICAgICB2YXIgaGFzU21hcnRQdHIgPSAhIXJlY29yZC5zbWFydFB0cjsKICAgICAgICAgICAgaWYgKGhhc1NtYXJ0UHRyVHlwZSAhPT0gaGFzU21hcnRQdHIpIHsKICAgICAgICAgICAgICB0aHJvd0ludGVybmFsRXJyb3IoIkJvdGggc21hcnRQdHJUeXBlIGFuZCBzbWFydFB0ciBtdXN0IGJlIHNwZWNpZmllZCIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJlY29yZC5jb3VudCA9IHsgdmFsdWU6IDEgfTsKICAgICAgICAgICAgcmV0dXJuIGF0dGFjaEZpbmFsaXplcihPYmplY3QuY3JlYXRlKHByb3RvdHlwZSwgeyAkJDogeyB2YWx1ZTogcmVjb3JkIH0gfSkpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gUmVnaXN0ZXJlZFBvaW50ZXJfZnJvbVdpcmVUeXBlKHB0cikgewogICAgICAgICAgICB2YXIgcmF3UG9pbnRlciA9IHRoaXMuZ2V0UG9pbnRlZShwdHIpOwogICAgICAgICAgICBpZiAoIXJhd1BvaW50ZXIpIHsKICAgICAgICAgICAgICB0aGlzLmRlc3RydWN0b3IocHRyKTsKICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgcmVnaXN0ZXJlZEluc3RhbmNlID0gZ2V0SW5oZXJpdGVkSW5zdGFuY2UodGhpcy5yZWdpc3RlcmVkQ2xhc3MsIHJhd1BvaW50ZXIpOwogICAgICAgICAgICBpZiAodm9pZCAwICE9PSByZWdpc3RlcmVkSW5zdGFuY2UpIHsKICAgICAgICAgICAgICBpZiAoMCA9PT0gcmVnaXN0ZXJlZEluc3RhbmNlLiQkLmNvdW50LnZhbHVlKSB7CiAgICAgICAgICAgICAgICByZWdpc3RlcmVkSW5zdGFuY2UuJCQucHRyID0gcmF3UG9pbnRlcjsKICAgICAgICAgICAgICAgIHJlZ2lzdGVyZWRJbnN0YW5jZS4kJC5zbWFydFB0ciA9IHB0cjsKICAgICAgICAgICAgICAgIHJldHVybiByZWdpc3RlcmVkSW5zdGFuY2VbImNsb25lIl0oKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgdmFyIHJ2ID0gcmVnaXN0ZXJlZEluc3RhbmNlWyJjbG9uZSJdKCk7CiAgICAgICAgICAgICAgICB0aGlzLmRlc3RydWN0b3IocHRyKTsKICAgICAgICAgICAgICAgIHJldHVybiBydjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZnVuY3Rpb24gbWFrZURlZmF1bHRIYW5kbGUoKSB7CiAgICAgICAgICAgICAgaWYgKHRoaXMuaXNTbWFydFBvaW50ZXIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBtYWtlQ2xhc3NIYW5kbGUodGhpcy5yZWdpc3RlcmVkQ2xhc3MuaW5zdGFuY2VQcm90b3R5cGUsIHsgcHRyVHlwZTogdGhpcy5wb2ludGVlVHlwZSwgcHRyOiByYXdQb2ludGVyLCBzbWFydFB0clR5cGU6IHRoaXMsIHNtYXJ0UHRyOiBwdHIgfSk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHJldHVybiBtYWtlQ2xhc3NIYW5kbGUodGhpcy5yZWdpc3RlcmVkQ2xhc3MuaW5zdGFuY2VQcm90b3R5cGUsIHsgcHRyVHlwZTogdGhpcywgcHRyIH0pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgYWN0dWFsVHlwZSA9IHRoaXMucmVnaXN0ZXJlZENsYXNzLmdldEFjdHVhbFR5cGUocmF3UG9pbnRlcik7CiAgICAgICAgICAgIHZhciByZWdpc3RlcmVkUG9pbnRlclJlY29yZCA9IHJlZ2lzdGVyZWRQb2ludGVyc1thY3R1YWxUeXBlXTsKICAgICAgICAgICAgaWYgKCFyZWdpc3RlcmVkUG9pbnRlclJlY29yZCkgewogICAgICAgICAgICAgIHJldHVybiBtYWtlRGVmYXVsdEhhbmRsZS5jYWxsKHRoaXMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciB0b1R5cGU7CiAgICAgICAgICAgIGlmICh0aGlzLmlzQ29uc3QpIHsKICAgICAgICAgICAgICB0b1R5cGUgPSByZWdpc3RlcmVkUG9pbnRlclJlY29yZC5jb25zdFBvaW50ZXJUeXBlOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRvVHlwZSA9IHJlZ2lzdGVyZWRQb2ludGVyUmVjb3JkLnBvaW50ZXJUeXBlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBkcCA9IGRvd25jYXN0UG9pbnRlcihyYXdQb2ludGVyLCB0aGlzLnJlZ2lzdGVyZWRDbGFzcywgdG9UeXBlLnJlZ2lzdGVyZWRDbGFzcyk7CiAgICAgICAgICAgIGlmIChkcCA9PT0gbnVsbCkgewogICAgICAgICAgICAgIHJldHVybiBtYWtlRGVmYXVsdEhhbmRsZS5jYWxsKHRoaXMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh0aGlzLmlzU21hcnRQb2ludGVyKSB7CiAgICAgICAgICAgICAgcmV0dXJuIG1ha2VDbGFzc0hhbmRsZSh0b1R5cGUucmVnaXN0ZXJlZENsYXNzLmluc3RhbmNlUHJvdG90eXBlLCB7IHB0clR5cGU6IHRvVHlwZSwgcHRyOiBkcCwgc21hcnRQdHJUeXBlOiB0aGlzLCBzbWFydFB0cjogcHRyIH0pOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJldHVybiBtYWtlQ2xhc3NIYW5kbGUodG9UeXBlLnJlZ2lzdGVyZWRDbGFzcy5pbnN0YW5jZVByb3RvdHlwZSwgeyBwdHJUeXBlOiB0b1R5cGUsIHB0cjogZHAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGluaXRfUmVnaXN0ZXJlZFBvaW50ZXIoKSB7CiAgICAgICAgICAgIFJlZ2lzdGVyZWRQb2ludGVyLnByb3RvdHlwZS5nZXRQb2ludGVlID0gUmVnaXN0ZXJlZFBvaW50ZXJfZ2V0UG9pbnRlZTsKICAgICAgICAgICAgUmVnaXN0ZXJlZFBvaW50ZXIucHJvdG90eXBlLmRlc3RydWN0b3IgPSBSZWdpc3RlcmVkUG9pbnRlcl9kZXN0cnVjdG9yOwogICAgICAgICAgICBSZWdpc3RlcmVkUG9pbnRlci5wcm90b3R5cGVbImFyZ1BhY2tBZHZhbmNlIl0gPSA4OwogICAgICAgICAgICBSZWdpc3RlcmVkUG9pbnRlci5wcm90b3R5cGVbInJlYWRWYWx1ZUZyb21Qb2ludGVyIl0gPSBzaW1wbGVSZWFkVmFsdWVGcm9tUG9pbnRlcjsKICAgICAgICAgICAgUmVnaXN0ZXJlZFBvaW50ZXIucHJvdG90eXBlWyJkZWxldGVPYmplY3QiXSA9IFJlZ2lzdGVyZWRQb2ludGVyX2RlbGV0ZU9iamVjdDsKICAgICAgICAgICAgUmVnaXN0ZXJlZFBvaW50ZXIucHJvdG90eXBlWyJmcm9tV2lyZVR5cGUiXSA9IFJlZ2lzdGVyZWRQb2ludGVyX2Zyb21XaXJlVHlwZTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIFJlZ2lzdGVyZWRQb2ludGVyKG5hbWUsIHJlZ2lzdGVyZWRDbGFzcywgaXNSZWZlcmVuY2UsIGlzQ29uc3QsIGlzU21hcnRQb2ludGVyLCBwb2ludGVlVHlwZSwgc2hhcmluZ1BvbGljeSwgcmF3R2V0UG9pbnRlZSwgcmF3Q29uc3RydWN0b3IsIHJhd1NoYXJlLCByYXdEZXN0cnVjdG9yKSB7CiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgICAgICAgIHRoaXMucmVnaXN0ZXJlZENsYXNzID0gcmVnaXN0ZXJlZENsYXNzOwogICAgICAgICAgICB0aGlzLmlzUmVmZXJlbmNlID0gaXNSZWZlcmVuY2U7CiAgICAgICAgICAgIHRoaXMuaXNDb25zdCA9IGlzQ29uc3Q7CiAgICAgICAgICAgIHRoaXMuaXNTbWFydFBvaW50ZXIgPSBpc1NtYXJ0UG9pbnRlcjsKICAgICAgICAgICAgdGhpcy5wb2ludGVlVHlwZSA9IHBvaW50ZWVUeXBlOwogICAgICAgICAgICB0aGlzLnNoYXJpbmdQb2xpY3kgPSBzaGFyaW5nUG9saWN5OwogICAgICAgICAgICB0aGlzLnJhd0dldFBvaW50ZWUgPSByYXdHZXRQb2ludGVlOwogICAgICAgICAgICB0aGlzLnJhd0NvbnN0cnVjdG9yID0gcmF3Q29uc3RydWN0b3I7CiAgICAgICAgICAgIHRoaXMucmF3U2hhcmUgPSByYXdTaGFyZTsKICAgICAgICAgICAgdGhpcy5yYXdEZXN0cnVjdG9yID0gcmF3RGVzdHJ1Y3RvcjsKICAgICAgICAgICAgaWYgKCFpc1NtYXJ0UG9pbnRlciAmJiByZWdpc3RlcmVkQ2xhc3MuYmFzZUNsYXNzID09PSB2b2lkIDApIHsKICAgICAgICAgICAgICBpZiAoaXNDb25zdCkgewogICAgICAgICAgICAgICAgdGhpc1sidG9XaXJlVHlwZSJdID0gY29uc3ROb1NtYXJ0UHRyUmF3UG9pbnRlclRvV2lyZVR5cGU7CiAgICAgICAgICAgICAgICB0aGlzLmRlc3RydWN0b3JGdW5jdGlvbiA9IG51bGw7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRoaXNbInRvV2lyZVR5cGUiXSA9IG5vbkNvbnN0Tm9TbWFydFB0clJhd1BvaW50ZXJUb1dpcmVUeXBlOwogICAgICAgICAgICAgICAgdGhpcy5kZXN0cnVjdG9yRnVuY3Rpb24gPSBudWxsOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB0aGlzWyJ0b1dpcmVUeXBlIl0gPSBnZW5lcmljUG9pbnRlclRvV2lyZVR5cGU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VQdWJsaWNTeW1ib2wobmFtZSwgdmFsdWUsIG51bUFyZ3VtZW50cykgewogICAgICAgICAgICBpZiAoIU1vZHVsZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICAgICAgICAgIHRocm93SW50ZXJuYWxFcnJvcigiUmVwbGFjaW5nIG5vbmV4aXN0YW50IHB1YmxpYyBzeW1ib2wiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodm9pZCAwICE9PSBNb2R1bGVbbmFtZV0ub3ZlcmxvYWRUYWJsZSAmJiB2b2lkIDAgIT09IG51bUFyZ3VtZW50cykgewogICAgICAgICAgICAgIE1vZHVsZVtuYW1lXS5vdmVybG9hZFRhYmxlW251bUFyZ3VtZW50c10gPSB2YWx1ZTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBNb2R1bGVbbmFtZV0gPSB2YWx1ZTsKICAgICAgICAgICAgICBNb2R1bGVbbmFtZV0uYXJnQ291bnQgPSBudW1Bcmd1bWVudHM7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGR5bkNhbGxMZWdhY3koc2lnLCBwdHIsIGFyZ3MpIHsKICAgICAgICAgICAgdmFyIGYgPSBNb2R1bGVbImR5bkNhbGxfIiArIHNpZ107CiAgICAgICAgICAgIHJldHVybiBhcmdzICYmIGFyZ3MubGVuZ3RoID8gZi5hcHBseShudWxsLCBbcHRyXS5jb25jYXQoYXJncykpIDogZi5jYWxsKG51bGwsIHB0cik7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBkeW5DYWxsKHNpZywgcHRyLCBhcmdzKSB7CiAgICAgICAgICAgIGlmIChzaWcuaW5kZXhPZigiaiIpICE9IC0xKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGR5bkNhbGxMZWdhY3koc2lnLCBwdHIsIGFyZ3MpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiB3YXNtVGFibGUuZ2V0KHB0cikuYXBwbHkobnVsbCwgYXJncyk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBnZXREeW5DYWxsZXIoc2lnLCBwdHIpIHsKICAgICAgICAgICAgdmFyIGFyZ0NhY2hlID0gW107CiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICBhcmdDYWNoZS5sZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoOwogICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBhcmdDYWNoZVtpXSA9IGFyZ3VtZW50c1tpXTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIGR5bkNhbGwoc2lnLCBwdHIsIGFyZ0NhY2hlKTsKICAgICAgICAgICAgfTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGVtYmluZF9fcmVxdWlyZUZ1bmN0aW9uKHNpZ25hdHVyZSwgcmF3RnVuY3Rpb24pIHsKICAgICAgICAgICAgc2lnbmF0dXJlID0gcmVhZExhdGluMVN0cmluZyhzaWduYXR1cmUpOwogICAgICAgICAgICBmdW5jdGlvbiBtYWtlRHluQ2FsbGVyKCkgewogICAgICAgICAgICAgIGlmIChzaWduYXR1cmUuaW5kZXhPZigiaiIpICE9IC0xKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZ2V0RHluQ2FsbGVyKHNpZ25hdHVyZSwgcmF3RnVuY3Rpb24pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gd2FzbVRhYmxlLmdldChyYXdGdW5jdGlvbik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGZwID0gbWFrZUR5bkNhbGxlcigpOwogICAgICAgICAgICBpZiAodHlwZW9mIGZwICE9PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICAgICAgdGhyb3dCaW5kaW5nRXJyb3IoInVua25vd24gZnVuY3Rpb24gcG9pbnRlciB3aXRoIHNpZ25hdHVyZSAiICsgc2lnbmF0dXJlICsgIjogIiArIHJhd0Z1bmN0aW9uKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZnA7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgVW5ib3VuZFR5cGVFcnJvciA9IHZvaWQgMDsKICAgICAgICAgIGZ1bmN0aW9uIGdldFR5cGVOYW1lKHR5cGUpIHsKICAgICAgICAgICAgdmFyIHB0ciA9IF9fX2dldFR5cGVOYW1lKHR5cGUpOwogICAgICAgICAgICB2YXIgcnYgPSByZWFkTGF0aW4xU3RyaW5nKHB0cik7CiAgICAgICAgICAgIF9mcmVlKHB0cik7CiAgICAgICAgICAgIHJldHVybiBydjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHRocm93VW5ib3VuZFR5cGVFcnJvcihtZXNzYWdlLCB0eXBlcykgewogICAgICAgICAgICB2YXIgdW5ib3VuZFR5cGVzID0gW107CiAgICAgICAgICAgIHZhciBzZWVuID0ge307CiAgICAgICAgICAgIGZ1bmN0aW9uIHZpc2l0KHR5cGUpIHsKICAgICAgICAgICAgICBpZiAoc2Vlblt0eXBlXSkgewogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAocmVnaXN0ZXJlZFR5cGVzW3R5cGVdKSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICh0eXBlRGVwZW5kZW5jaWVzW3R5cGVdKSB7CiAgICAgICAgICAgICAgICB0eXBlRGVwZW5kZW5jaWVzW3R5cGVdLmZvckVhY2godmlzaXQpOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB1bmJvdW5kVHlwZXMucHVzaCh0eXBlKTsKICAgICAgICAgICAgICBzZWVuW3R5cGVdID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0eXBlcy5mb3JFYWNoKHZpc2l0KTsKICAgICAgICAgICAgdGhyb3cgbmV3IFVuYm91bmRUeXBlRXJyb3IobWVzc2FnZSArICI6ICIgKyB1bmJvdW5kVHlwZXMubWFwKGdldFR5cGVOYW1lKS5qb2luKFsiLCAiXSkpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbWJpbmRfcmVnaXN0ZXJfY2xhc3MocmF3VHlwZSwgcmF3UG9pbnRlclR5cGUsIHJhd0NvbnN0UG9pbnRlclR5cGUsIGJhc2VDbGFzc1Jhd1R5cGUsIGdldEFjdHVhbFR5cGVTaWduYXR1cmUsIGdldEFjdHVhbFR5cGUsIHVwY2FzdFNpZ25hdHVyZSwgdXBjYXN0LCBkb3duY2FzdFNpZ25hdHVyZSwgZG93bmNhc3QsIG5hbWUsIGRlc3RydWN0b3JTaWduYXR1cmUsIHJhd0Rlc3RydWN0b3IpIHsKICAgICAgICAgICAgbmFtZSA9IHJlYWRMYXRpbjFTdHJpbmcobmFtZSk7CiAgICAgICAgICAgIGdldEFjdHVhbFR5cGUgPSBlbWJpbmRfX3JlcXVpcmVGdW5jdGlvbihnZXRBY3R1YWxUeXBlU2lnbmF0dXJlLCBnZXRBY3R1YWxUeXBlKTsKICAgICAgICAgICAgaWYgKHVwY2FzdCkgewogICAgICAgICAgICAgIHVwY2FzdCA9IGVtYmluZF9fcmVxdWlyZUZ1bmN0aW9uKHVwY2FzdFNpZ25hdHVyZSwgdXBjYXN0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoZG93bmNhc3QpIHsKICAgICAgICAgICAgICBkb3duY2FzdCA9IGVtYmluZF9fcmVxdWlyZUZ1bmN0aW9uKGRvd25jYXN0U2lnbmF0dXJlLCBkb3duY2FzdCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmF3RGVzdHJ1Y3RvciA9IGVtYmluZF9fcmVxdWlyZUZ1bmN0aW9uKGRlc3RydWN0b3JTaWduYXR1cmUsIHJhd0Rlc3RydWN0b3IpOwogICAgICAgICAgICB2YXIgbGVnYWxGdW5jdGlvbk5hbWUgPSBtYWtlTGVnYWxGdW5jdGlvbk5hbWUobmFtZSk7CiAgICAgICAgICAgIGV4cG9zZVB1YmxpY1N5bWJvbChsZWdhbEZ1bmN0aW9uTmFtZSwgZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgdGhyb3dVbmJvdW5kVHlwZUVycm9yKCJDYW5ub3QgY29uc3RydWN0ICIgKyBuYW1lICsgIiBkdWUgdG8gdW5ib3VuZCB0eXBlcyIsIFtiYXNlQ2xhc3NSYXdUeXBlXSk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICB3aGVuRGVwZW5kZW50VHlwZXNBcmVSZXNvbHZlZChbcmF3VHlwZSwgcmF3UG9pbnRlclR5cGUsIHJhd0NvbnN0UG9pbnRlclR5cGVdLCBiYXNlQ2xhc3NSYXdUeXBlID8gW2Jhc2VDbGFzc1Jhd1R5cGVdIDogW10sIGZ1bmN0aW9uKGJhc2UpIHsKICAgICAgICAgICAgICBiYXNlID0gYmFzZVswXTsKICAgICAgICAgICAgICB2YXIgYmFzZUNsYXNzOwogICAgICAgICAgICAgIHZhciBiYXNlUHJvdG90eXBlOwogICAgICAgICAgICAgIGlmIChiYXNlQ2xhc3NSYXdUeXBlKSB7CiAgICAgICAgICAgICAgICBiYXNlQ2xhc3MgPSBiYXNlLnJlZ2lzdGVyZWRDbGFzczsKICAgICAgICAgICAgICAgIGJhc2VQcm90b3R5cGUgPSBiYXNlQ2xhc3MuaW5zdGFuY2VQcm90b3R5cGU7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGJhc2VQcm90b3R5cGUgPSBDbGFzc0hhbmRsZS5wcm90b3R5cGU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHZhciBjb25zdHJ1Y3RvciA9IGNyZWF0ZU5hbWVkRnVuY3Rpb24obGVnYWxGdW5jdGlvbk5hbWUsIGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzKSAhPT0gaW5zdGFuY2VQcm90b3R5cGUpIHsKICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEJpbmRpbmdFcnJvcigiVXNlICduZXcnIHRvIGNvbnN0cnVjdCAiICsgbmFtZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAodm9pZCAwID09PSByZWdpc3RlcmVkQ2xhc3MuY29uc3RydWN0b3JfYm9keSkgewogICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQmluZGluZ0Vycm9yKG5hbWUgKyAiIGhhcyBubyBhY2Nlc3NpYmxlIGNvbnN0cnVjdG9yIik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB2YXIgYm9keSA9IHJlZ2lzdGVyZWRDbGFzcy5jb25zdHJ1Y3Rvcl9ib2R5W2FyZ3VtZW50cy5sZW5ndGhdOwogICAgICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gYm9keSkgewogICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQmluZGluZ0Vycm9yKCJUcmllZCB0byBpbnZva2UgY3RvciBvZiAiICsgbmFtZSArICIgd2l0aCBpbnZhbGlkIG51bWJlciBvZiBwYXJhbWV0ZXJzICgiICsgYXJndW1lbnRzLmxlbmd0aCArICIpIC0gZXhwZWN0ZWQgKCIgKyBPYmplY3Qua2V5cyhyZWdpc3RlcmVkQ2xhc3MuY29uc3RydWN0b3JfYm9keSkudG9TdHJpbmcoKSArICIpIHBhcmFtZXRlcnMgaW5zdGVhZCEiKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybiBib2R5LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgdmFyIGluc3RhbmNlUHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShiYXNlUHJvdG90eXBlLCB7IGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBjb25zdHJ1Y3RvciB9IH0pOwogICAgICAgICAgICAgIGNvbnN0cnVjdG9yLnByb3RvdHlwZSA9IGluc3RhbmNlUHJvdG90eXBlOwogICAgICAgICAgICAgIHZhciByZWdpc3RlcmVkQ2xhc3MgPSBuZXcgUmVnaXN0ZXJlZENsYXNzKG5hbWUsIGNvbnN0cnVjdG9yLCBpbnN0YW5jZVByb3RvdHlwZSwgcmF3RGVzdHJ1Y3RvciwgYmFzZUNsYXNzLCBnZXRBY3R1YWxUeXBlLCB1cGNhc3QsIGRvd25jYXN0KTsKICAgICAgICAgICAgICB2YXIgcmVmZXJlbmNlQ29udmVydGVyID0gbmV3IFJlZ2lzdGVyZWRQb2ludGVyKG5hbWUsIHJlZ2lzdGVyZWRDbGFzcywgdHJ1ZSwgZmFsc2UsIGZhbHNlKTsKICAgICAgICAgICAgICB2YXIgcG9pbnRlckNvbnZlcnRlciA9IG5ldyBSZWdpc3RlcmVkUG9pbnRlcihuYW1lICsgIioiLCByZWdpc3RlcmVkQ2xhc3MsIGZhbHNlLCBmYWxzZSwgZmFsc2UpOwogICAgICAgICAgICAgIHZhciBjb25zdFBvaW50ZXJDb252ZXJ0ZXIgPSBuZXcgUmVnaXN0ZXJlZFBvaW50ZXIobmFtZSArICIgY29uc3QqIiwgcmVnaXN0ZXJlZENsYXNzLCBmYWxzZSwgdHJ1ZSwgZmFsc2UpOwogICAgICAgICAgICAgIHJlZ2lzdGVyZWRQb2ludGVyc1tyYXdUeXBlXSA9IHsgcG9pbnRlclR5cGU6IHBvaW50ZXJDb252ZXJ0ZXIsIGNvbnN0UG9pbnRlclR5cGU6IGNvbnN0UG9pbnRlckNvbnZlcnRlciB9OwogICAgICAgICAgICAgIHJlcGxhY2VQdWJsaWNTeW1ib2wobGVnYWxGdW5jdGlvbk5hbWUsIGNvbnN0cnVjdG9yKTsKICAgICAgICAgICAgICByZXR1cm4gW3JlZmVyZW5jZUNvbnZlcnRlciwgcG9pbnRlckNvbnZlcnRlciwgY29uc3RQb2ludGVyQ29udmVydGVyXTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBoZWFwMzJWZWN0b3JUb0FycmF5KGNvdW50LCBmaXJzdEVsZW1lbnQpIHsKICAgICAgICAgICAgdmFyIGFycmF5ID0gW107CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewogICAgICAgICAgICAgIGFycmF5LnB1c2goSEVBUDMyWyhmaXJzdEVsZW1lbnQgPj4gMikgKyBpXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbWJpbmRfcmVnaXN0ZXJfY2xhc3NfY29uc3RydWN0b3IocmF3Q2xhc3NUeXBlLCBhcmdDb3VudCwgcmF3QXJnVHlwZXNBZGRyLCBpbnZva2VyU2lnbmF0dXJlLCBpbnZva2VyLCByYXdDb25zdHJ1Y3RvcikgewogICAgICAgICAgICBhc3NlcnQoYXJnQ291bnQgPiAwKTsKICAgICAgICAgICAgdmFyIHJhd0FyZ1R5cGVzID0gaGVhcDMyVmVjdG9yVG9BcnJheShhcmdDb3VudCwgcmF3QXJnVHlwZXNBZGRyKTsKICAgICAgICAgICAgaW52b2tlciA9IGVtYmluZF9fcmVxdWlyZUZ1bmN0aW9uKGludm9rZXJTaWduYXR1cmUsIGludm9rZXIpOwogICAgICAgICAgICB2YXIgYXJncyA9IFtyYXdDb25zdHJ1Y3Rvcl07CiAgICAgICAgICAgIHZhciBkZXN0cnVjdG9ycyA9IFtdOwogICAgICAgICAgICB3aGVuRGVwZW5kZW50VHlwZXNBcmVSZXNvbHZlZChbXSwgW3Jhd0NsYXNzVHlwZV0sIGZ1bmN0aW9uKGNsYXNzVHlwZSkgewogICAgICAgICAgICAgIGNsYXNzVHlwZSA9IGNsYXNzVHlwZVswXTsKICAgICAgICAgICAgICB2YXIgaHVtYW5OYW1lID0gImNvbnN0cnVjdG9yICIgKyBjbGFzc1R5cGUubmFtZTsKICAgICAgICAgICAgICBpZiAodm9pZCAwID09PSBjbGFzc1R5cGUucmVnaXN0ZXJlZENsYXNzLmNvbnN0cnVjdG9yX2JvZHkpIHsKICAgICAgICAgICAgICAgIGNsYXNzVHlwZS5yZWdpc3RlcmVkQ2xhc3MuY29uc3RydWN0b3JfYm9keSA9IFtdOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAodm9pZCAwICE9PSBjbGFzc1R5cGUucmVnaXN0ZXJlZENsYXNzLmNvbnN0cnVjdG9yX2JvZHlbYXJnQ291bnQgLSAxXSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEJpbmRpbmdFcnJvcigiQ2Fubm90IHJlZ2lzdGVyIG11bHRpcGxlIGNvbnN0cnVjdG9ycyB3aXRoIGlkZW50aWNhbCBudW1iZXIgb2YgcGFyYW1ldGVycyAoIiArIChhcmdDb3VudCAtIDEpICsgIikgZm9yIGNsYXNzICciICsgY2xhc3NUeXBlLm5hbWUgKyAiJyEgT3ZlcmxvYWQgcmVzb2x1dGlvbiBpcyBjdXJyZW50bHkgb25seSBwZXJmb3JtZWQgdXNpbmcgdGhlIHBhcmFtZXRlciBjb3VudCwgbm90IGFjdHVhbCB0eXBlIGluZm8hIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNsYXNzVHlwZS5yZWdpc3RlcmVkQ2xhc3MuY29uc3RydWN0b3JfYm9keVthcmdDb3VudCAtIDFdID0gZnVuY3Rpb24gdW5ib3VuZFR5cGVIYW5kbGVyKCkgewogICAgICAgICAgICAgICAgdGhyb3dVbmJvdW5kVHlwZUVycm9yKCJDYW5ub3QgY29uc3RydWN0ICIgKyBjbGFzc1R5cGUubmFtZSArICIgZHVlIHRvIHVuYm91bmQgdHlwZXMiLCByYXdBcmdUeXBlcyk7CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICB3aGVuRGVwZW5kZW50VHlwZXNBcmVSZXNvbHZlZChbXSwgcmF3QXJnVHlwZXMsIGZ1bmN0aW9uKGFyZ1R5cGVzKSB7CiAgICAgICAgICAgICAgICBjbGFzc1R5cGUucmVnaXN0ZXJlZENsYXNzLmNvbnN0cnVjdG9yX2JvZHlbYXJnQ291bnQgLSAxXSA9IGZ1bmN0aW9uIGNvbnN0cnVjdG9yX2JvZHkoKSB7CiAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoICE9PSBhcmdDb3VudCAtIDEpIHsKICAgICAgICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcihodW1hbk5hbWUgKyAiIGNhbGxlZCB3aXRoICIgKyBhcmd1bWVudHMubGVuZ3RoICsgIiBhcmd1bWVudHMsIGV4cGVjdGVkICIgKyAoYXJnQ291bnQgLSAxKSk7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgZGVzdHJ1Y3RvcnMubGVuZ3RoID0gMDsKICAgICAgICAgICAgICAgICAgYXJncy5sZW5ndGggPSBhcmdDb3VudDsKICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmdDb3VudDsgKytpKSB7CiAgICAgICAgICAgICAgICAgICAgYXJnc1tpXSA9IGFyZ1R5cGVzW2ldWyJ0b1dpcmVUeXBlIl0oZGVzdHJ1Y3RvcnMsIGFyZ3VtZW50c1tpIC0gMV0pOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHZhciBwdHIgPSBpbnZva2VyLmFwcGx5KG51bGwsIGFyZ3MpOwogICAgICAgICAgICAgICAgICBydW5EZXN0cnVjdG9ycyhkZXN0cnVjdG9ycyk7CiAgICAgICAgICAgICAgICAgIHJldHVybiBhcmdUeXBlc1swXVsiZnJvbVdpcmVUeXBlIl0ocHRyKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICByZXR1cm4gW107CiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgcmV0dXJuIFtdOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIG5ld18oY29uc3RydWN0b3IsIGFyZ3VtZW50TGlzdCkgewogICAgICAgICAgICBpZiAoIShjb25zdHJ1Y3RvciBpbnN0YW5jZW9mIEZ1bmN0aW9uKSkgewogICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIm5ld18gY2FsbGVkIHdpdGggY29uc3RydWN0b3IgdHlwZSAiICsgdHlwZW9mIGNvbnN0cnVjdG9yICsgIiB3aGljaCBpcyBub3QgYSBmdW5jdGlvbiIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBkdW1teSA9IGNyZWF0ZU5hbWVkRnVuY3Rpb24oY29uc3RydWN0b3IubmFtZSB8fCAidW5rbm93bkZ1bmN0aW9uTmFtZSIsIGZ1bmN0aW9uKCkgewogICAgICAgICAgICB9KTsKICAgICAgICAgICAgZHVtbXkucHJvdG90eXBlID0gY29uc3RydWN0b3IucHJvdG90eXBlOwogICAgICAgICAgICB2YXIgb2JqID0gbmV3IGR1bW15KCk7CiAgICAgICAgICAgIHZhciByID0gY29uc3RydWN0b3IuYXBwbHkob2JqLCBhcmd1bWVudExpc3QpOwogICAgICAgICAgICByZXR1cm4gciBpbnN0YW5jZW9mIE9iamVjdCA/IHIgOiBvYmo7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBjcmFmdEludm9rZXJGdW5jdGlvbihodW1hbk5hbWUsIGFyZ1R5cGVzLCBjbGFzc1R5cGUsIGNwcEludm9rZXJGdW5jLCBjcHBUYXJnZXRGdW5jKSB7CiAgICAgICAgICAgIHZhciBhcmdDb3VudCA9IGFyZ1R5cGVzLmxlbmd0aDsKICAgICAgICAgICAgaWYgKGFyZ0NvdW50IDwgMikgewogICAgICAgICAgICAgIHRocm93QmluZGluZ0Vycm9yKCJhcmdUeXBlcyBhcnJheSBzaXplIG1pc21hdGNoISBNdXN0IGF0IGxlYXN0IGdldCByZXR1cm4gdmFsdWUgYW5kICd0aGlzJyB0eXBlcyEiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgaXNDbGFzc01ldGhvZEZ1bmMgPSBhcmdUeXBlc1sxXSAhPT0gbnVsbCAmJiBjbGFzc1R5cGUgIT09IG51bGw7CiAgICAgICAgICAgIHZhciBuZWVkc0Rlc3RydWN0b3JTdGFjayA9IGZhbHNlOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ1R5cGVzLmxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgICAgaWYgKGFyZ1R5cGVzW2ldICE9PSBudWxsICYmIGFyZ1R5cGVzW2ldLmRlc3RydWN0b3JGdW5jdGlvbiA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgICBuZWVkc0Rlc3RydWN0b3JTdGFjayA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIHJldHVybnMgPSBhcmdUeXBlc1swXS5uYW1lICE9PSAidm9pZCI7CiAgICAgICAgICAgIHZhciBhcmdzTGlzdCA9ICIiOwogICAgICAgICAgICB2YXIgYXJnc0xpc3RXaXJlZCA9ICIiOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ0NvdW50IC0gMjsgKytpKSB7CiAgICAgICAgICAgICAgYXJnc0xpc3QgKz0gKGkgIT09IDAgPyAiLCAiIDogIiIpICsgImFyZyIgKyBpOwogICAgICAgICAgICAgIGFyZ3NMaXN0V2lyZWQgKz0gKGkgIT09IDAgPyAiLCAiIDogIiIpICsgImFyZyIgKyBpICsgIldpcmVkIjsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgaW52b2tlckZuQm9keSA9ICJyZXR1cm4gZnVuY3Rpb24gIiArIG1ha2VMZWdhbEZ1bmN0aW9uTmFtZShodW1hbk5hbWUpICsgIigiICsgYXJnc0xpc3QgKyAiKSB7XG5pZiAoYXJndW1lbnRzLmxlbmd0aCAhPT0gIiArIChhcmdDb3VudCAtIDIpICsgIikge1xudGhyb3dCaW5kaW5nRXJyb3IoJ2Z1bmN0aW9uICIgKyBodW1hbk5hbWUgKyAiIGNhbGxlZCB3aXRoICcgKyBhcmd1bWVudHMubGVuZ3RoICsgJyBhcmd1bWVudHMsIGV4cGVjdGVkICIgKyAoYXJnQ291bnQgLSAyKSArICIgYXJncyEnKTtcbn1cbiI7CiAgICAgICAgICAgIGlmIChuZWVkc0Rlc3RydWN0b3JTdGFjaykgewogICAgICAgICAgICAgIGludm9rZXJGbkJvZHkgKz0gInZhciBkZXN0cnVjdG9ycyA9IFtdO1xuIjsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgZHRvclN0YWNrID0gbmVlZHNEZXN0cnVjdG9yU3RhY2sgPyAiZGVzdHJ1Y3RvcnMiIDogIm51bGwiOwogICAgICAgICAgICB2YXIgYXJnczEgPSBbInRocm93QmluZGluZ0Vycm9yIiwgImludm9rZXIiLCAiZm4iLCAicnVuRGVzdHJ1Y3RvcnMiLCAicmV0VHlwZSIsICJjbGFzc1BhcmFtIl07CiAgICAgICAgICAgIHZhciBhcmdzMiA9IFt0aHJvd0JpbmRpbmdFcnJvciwgY3BwSW52b2tlckZ1bmMsIGNwcFRhcmdldEZ1bmMsIHJ1bkRlc3RydWN0b3JzLCBhcmdUeXBlc1swXSwgYXJnVHlwZXNbMV1dOwogICAgICAgICAgICBpZiAoaXNDbGFzc01ldGhvZEZ1bmMpIHsKICAgICAgICAgICAgICBpbnZva2VyRm5Cb2R5ICs9ICJ2YXIgdGhpc1dpcmVkID0gY2xhc3NQYXJhbS50b1dpcmVUeXBlKCIgKyBkdG9yU3RhY2sgKyAiLCB0aGlzKTtcbiI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdDb3VudCAtIDI7ICsraSkgewogICAgICAgICAgICAgIGludm9rZXJGbkJvZHkgKz0gInZhciBhcmciICsgaSArICJXaXJlZCA9IGFyZ1R5cGUiICsgaSArICIudG9XaXJlVHlwZSgiICsgZHRvclN0YWNrICsgIiwgYXJnIiArIGkgKyAiKTsgLy8gIiArIGFyZ1R5cGVzW2kgKyAyXS5uYW1lICsgIlxuIjsKICAgICAgICAgICAgICBhcmdzMS5wdXNoKCJhcmdUeXBlIiArIGkpOwogICAgICAgICAgICAgIGFyZ3MyLnB1c2goYXJnVHlwZXNbaSArIDJdKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoaXNDbGFzc01ldGhvZEZ1bmMpIHsKICAgICAgICAgICAgICBhcmdzTGlzdFdpcmVkID0gInRoaXNXaXJlZCIgKyAoYXJnc0xpc3RXaXJlZC5sZW5ndGggPiAwID8gIiwgIiA6ICIiKSArIGFyZ3NMaXN0V2lyZWQ7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaW52b2tlckZuQm9keSArPSAocmV0dXJucyA/ICJ2YXIgcnYgPSAiIDogIiIpICsgImludm9rZXIoZm4iICsgKGFyZ3NMaXN0V2lyZWQubGVuZ3RoID4gMCA/ICIsICIgOiAiIikgKyBhcmdzTGlzdFdpcmVkICsgIik7XG4iOwogICAgICAgICAgICBpZiAobmVlZHNEZXN0cnVjdG9yU3RhY2spIHsKICAgICAgICAgICAgICBpbnZva2VyRm5Cb2R5ICs9ICJydW5EZXN0cnVjdG9ycyhkZXN0cnVjdG9ycyk7XG4iOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGZvciAodmFyIGkgPSBpc0NsYXNzTWV0aG9kRnVuYyA/IDEgOiAyOyBpIDwgYXJnVHlwZXMubGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgICAgIHZhciBwYXJhbU5hbWUgPSBpID09PSAxID8gInRoaXNXaXJlZCIgOiAiYXJnIiArIChpIC0gMikgKyAiV2lyZWQiOwogICAgICAgICAgICAgICAgaWYgKGFyZ1R5cGVzW2ldLmRlc3RydWN0b3JGdW5jdGlvbiAhPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICBpbnZva2VyRm5Cb2R5ICs9IHBhcmFtTmFtZSArICJfZHRvcigiICsgcGFyYW1OYW1lICsgIik7IC8vICIgKyBhcmdUeXBlc1tpXS5uYW1lICsgIlxuIjsKICAgICAgICAgICAgICAgICAgYXJnczEucHVzaChwYXJhbU5hbWUgKyAiX2R0b3IiKTsKICAgICAgICAgICAgICAgICAgYXJnczIucHVzaChhcmdUeXBlc1tpXS5kZXN0cnVjdG9yRnVuY3Rpb24pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocmV0dXJucykgewogICAgICAgICAgICAgIGludm9rZXJGbkJvZHkgKz0gInZhciByZXQgPSByZXRUeXBlLmZyb21XaXJlVHlwZShydik7XG5yZXR1cm4gcmV0O1xuIjsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgfQogICAgICAgICAgICBpbnZva2VyRm5Cb2R5ICs9ICJ9XG4iOwogICAgICAgICAgICBhcmdzMS5wdXNoKGludm9rZXJGbkJvZHkpOwogICAgICAgICAgICB2YXIgaW52b2tlckZ1bmN0aW9uID0gbmV3XyhGdW5jdGlvbiwgYXJnczEpLmFwcGx5KG51bGwsIGFyZ3MyKTsKICAgICAgICAgICAgcmV0dXJuIGludm9rZXJGdW5jdGlvbjsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIF9fZW1iaW5kX3JlZ2lzdGVyX2NsYXNzX2Z1bmN0aW9uKHJhd0NsYXNzVHlwZSwgbWV0aG9kTmFtZSwgYXJnQ291bnQsIHJhd0FyZ1R5cGVzQWRkciwgaW52b2tlclNpZ25hdHVyZSwgcmF3SW52b2tlciwgY29udGV4dCwgaXNQdXJlVmlydHVhbCkgewogICAgICAgICAgICB2YXIgcmF3QXJnVHlwZXMgPSBoZWFwMzJWZWN0b3JUb0FycmF5KGFyZ0NvdW50LCByYXdBcmdUeXBlc0FkZHIpOwogICAgICAgICAgICBtZXRob2ROYW1lID0gcmVhZExhdGluMVN0cmluZyhtZXRob2ROYW1lKTsKICAgICAgICAgICAgcmF3SW52b2tlciA9IGVtYmluZF9fcmVxdWlyZUZ1bmN0aW9uKGludm9rZXJTaWduYXR1cmUsIHJhd0ludm9rZXIpOwogICAgICAgICAgICB3aGVuRGVwZW5kZW50VHlwZXNBcmVSZXNvbHZlZChbXSwgW3Jhd0NsYXNzVHlwZV0sIGZ1bmN0aW9uKGNsYXNzVHlwZSkgewogICAgICAgICAgICAgIGNsYXNzVHlwZSA9IGNsYXNzVHlwZVswXTsKICAgICAgICAgICAgICB2YXIgaHVtYW5OYW1lID0gY2xhc3NUeXBlLm5hbWUgKyAiLiIgKyBtZXRob2ROYW1lOwogICAgICAgICAgICAgIGlmIChpc1B1cmVWaXJ0dWFsKSB7CiAgICAgICAgICAgICAgICBjbGFzc1R5cGUucmVnaXN0ZXJlZENsYXNzLnB1cmVWaXJ0dWFsRnVuY3Rpb25zLnB1c2gobWV0aG9kTmFtZSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGZ1bmN0aW9uIHVuYm91bmRUeXBlc0hhbmRsZXIoKSB7CiAgICAgICAgICAgICAgICB0aHJvd1VuYm91bmRUeXBlRXJyb3IoIkNhbm5vdCBjYWxsICIgKyBodW1hbk5hbWUgKyAiIGR1ZSB0byB1bmJvdW5kIHR5cGVzIiwgcmF3QXJnVHlwZXMpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB2YXIgcHJvdG8gPSBjbGFzc1R5cGUucmVnaXN0ZXJlZENsYXNzLmluc3RhbmNlUHJvdG90eXBlOwogICAgICAgICAgICAgIHZhciBtZXRob2QgPSBwcm90b1ttZXRob2ROYW1lXTsKICAgICAgICAgICAgICBpZiAodm9pZCAwID09PSBtZXRob2QgfHwgdm9pZCAwID09PSBtZXRob2Qub3ZlcmxvYWRUYWJsZSAmJiBtZXRob2QuY2xhc3NOYW1lICE9PSBjbGFzc1R5cGUubmFtZSAmJiBtZXRob2QuYXJnQ291bnQgPT09IGFyZ0NvdW50IC0gMikgewogICAgICAgICAgICAgICAgdW5ib3VuZFR5cGVzSGFuZGxlci5hcmdDb3VudCA9IGFyZ0NvdW50IC0gMjsKICAgICAgICAgICAgICAgIHVuYm91bmRUeXBlc0hhbmRsZXIuY2xhc3NOYW1lID0gY2xhc3NUeXBlLm5hbWU7CiAgICAgICAgICAgICAgICBwcm90b1ttZXRob2ROYW1lXSA9IHVuYm91bmRUeXBlc0hhbmRsZXI7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGVuc3VyZU92ZXJsb2FkVGFibGUocHJvdG8sIG1ldGhvZE5hbWUsIGh1bWFuTmFtZSk7CiAgICAgICAgICAgICAgICBwcm90b1ttZXRob2ROYW1lXS5vdmVybG9hZFRhYmxlW2FyZ0NvdW50IC0gMl0gPSB1bmJvdW5kVHlwZXNIYW5kbGVyOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB3aGVuRGVwZW5kZW50VHlwZXNBcmVSZXNvbHZlZChbXSwgcmF3QXJnVHlwZXMsIGZ1bmN0aW9uKGFyZ1R5cGVzKSB7CiAgICAgICAgICAgICAgICB2YXIgbWVtYmVyRnVuY3Rpb24gPSBjcmFmdEludm9rZXJGdW5jdGlvbihodW1hbk5hbWUsIGFyZ1R5cGVzLCBjbGFzc1R5cGUsIHJhd0ludm9rZXIsIGNvbnRleHQpOwogICAgICAgICAgICAgICAgaWYgKHZvaWQgMCA9PT0gcHJvdG9bbWV0aG9kTmFtZV0ub3ZlcmxvYWRUYWJsZSkgewogICAgICAgICAgICAgICAgICBtZW1iZXJGdW5jdGlvbi5hcmdDb3VudCA9IGFyZ0NvdW50IC0gMjsKICAgICAgICAgICAgICAgICAgcHJvdG9bbWV0aG9kTmFtZV0gPSBtZW1iZXJGdW5jdGlvbjsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgIHByb3RvW21ldGhvZE5hbWVdLm92ZXJsb2FkVGFibGVbYXJnQ291bnQgLSAyXSA9IG1lbWJlckZ1bmN0aW9uOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmV0dXJuIFtdOwogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIHJldHVybiBbXTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfX2VtYmluZF9yZWdpc3Rlcl9jb25zdGFudChuYW1lLCB0eXBlLCB2YWx1ZSkgewogICAgICAgICAgICBuYW1lID0gcmVhZExhdGluMVN0cmluZyhuYW1lKTsKICAgICAgICAgICAgd2hlbkRlcGVuZGVudFR5cGVzQXJlUmVzb2x2ZWQoW10sIFt0eXBlXSwgZnVuY3Rpb24odHlwZTIpIHsKICAgICAgICAgICAgICB0eXBlMiA9IHR5cGUyWzBdOwogICAgICAgICAgICAgIE1vZHVsZVtuYW1lXSA9IHR5cGUyWyJmcm9tV2lyZVR5cGUiXSh2YWx1ZSk7CiAgICAgICAgICAgICAgcmV0dXJuIFtdOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBlbXZhbF9mcmVlX2xpc3QgPSBbXTsKICAgICAgICAgIHZhciBlbXZhbF9oYW5kbGVfYXJyYXkgPSBbe30sIHsgdmFsdWU6IHZvaWQgMCB9LCB7IHZhbHVlOiBudWxsIH0sIHsgdmFsdWU6IHRydWUgfSwgeyB2YWx1ZTogZmFsc2UgfV07CiAgICAgICAgICBmdW5jdGlvbiBfX2VtdmFsX2RlY3JlZihoYW5kbGUpIHsKICAgICAgICAgICAgaWYgKGhhbmRsZSA+IDQgJiYgMCA9PT0gLS1lbXZhbF9oYW5kbGVfYXJyYXlbaGFuZGxlXS5yZWZjb3VudCkgewogICAgICAgICAgICAgIGVtdmFsX2hhbmRsZV9hcnJheVtoYW5kbGVdID0gdm9pZCAwOwogICAgICAgICAgICAgIGVtdmFsX2ZyZWVfbGlzdC5wdXNoKGhhbmRsZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGNvdW50X2VtdmFsX2hhbmRsZXMoKSB7CiAgICAgICAgICAgIHZhciBjb3VudCA9IDA7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSA1OyBpIDwgZW12YWxfaGFuZGxlX2FycmF5Lmxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgICAgaWYgKGVtdmFsX2hhbmRsZV9hcnJheVtpXSAhPT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgICArK2NvdW50OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gY291bnQ7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBnZXRfZmlyc3RfZW12YWwoKSB7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSA1OyBpIDwgZW12YWxfaGFuZGxlX2FycmF5Lmxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgICAgaWYgKGVtdmFsX2hhbmRsZV9hcnJheVtpXSAhPT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZW12YWxfaGFuZGxlX2FycmF5W2ldOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGluaXRfZW12YWwoKSB7CiAgICAgICAgICAgIE1vZHVsZVsiY291bnRfZW12YWxfaGFuZGxlcyJdID0gY291bnRfZW12YWxfaGFuZGxlczsKICAgICAgICAgICAgTW9kdWxlWyJnZXRfZmlyc3RfZW12YWwiXSA9IGdldF9maXJzdF9lbXZhbDsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIF9fZW12YWxfcmVnaXN0ZXIodmFsdWUpIHsKICAgICAgICAgICAgc3dpdGNoICh2YWx1ZSkgewogICAgICAgICAgICAgIGNhc2Ugdm9pZCAwOiB7CiAgICAgICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY2FzZSBudWxsOiB7CiAgICAgICAgICAgICAgICByZXR1cm4gMjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY2FzZSB0cnVlOiB7CiAgICAgICAgICAgICAgICByZXR1cm4gMzsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY2FzZSBmYWxzZTogewogICAgICAgICAgICAgICAgcmV0dXJuIDQ7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGRlZmF1bHQ6IHsKICAgICAgICAgICAgICAgIHZhciBoYW5kbGUgPSBlbXZhbF9mcmVlX2xpc3QubGVuZ3RoID8gZW12YWxfZnJlZV9saXN0LnBvcCgpIDogZW12YWxfaGFuZGxlX2FycmF5Lmxlbmd0aDsKICAgICAgICAgICAgICAgIGVtdmFsX2hhbmRsZV9hcnJheVtoYW5kbGVdID0geyByZWZjb3VudDogMSwgdmFsdWUgfTsKICAgICAgICAgICAgICAgIHJldHVybiBoYW5kbGU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfX2VtYmluZF9yZWdpc3Rlcl9lbXZhbChyYXdUeXBlLCBuYW1lKSB7CiAgICAgICAgICAgIG5hbWUgPSByZWFkTGF0aW4xU3RyaW5nKG5hbWUpOwogICAgICAgICAgICByZWdpc3RlclR5cGUocmF3VHlwZSwgeyBuYW1lLCAiZnJvbVdpcmVUeXBlIjogZnVuY3Rpb24oaGFuZGxlKSB7CiAgICAgICAgICAgICAgdmFyIHJ2ID0gZW12YWxfaGFuZGxlX2FycmF5W2hhbmRsZV0udmFsdWU7CiAgICAgICAgICAgICAgX19lbXZhbF9kZWNyZWYoaGFuZGxlKTsKICAgICAgICAgICAgICByZXR1cm4gcnY7CiAgICAgICAgICAgIH0sICJ0b1dpcmVUeXBlIjogZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsIHZhbHVlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIF9fZW12YWxfcmVnaXN0ZXIodmFsdWUpOwogICAgICAgICAgICB9LCAiYXJnUGFja0FkdmFuY2UiOiA4LCAicmVhZFZhbHVlRnJvbVBvaW50ZXIiOiBzaW1wbGVSZWFkVmFsdWVGcm9tUG9pbnRlciwgZGVzdHJ1Y3RvckZ1bmN0aW9uOiBudWxsIH0pOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gZW51bVJlYWRWYWx1ZUZyb21Qb2ludGVyKG5hbWUsIHNoaWZ0LCBzaWduZWQpIHsKICAgICAgICAgICAgc3dpdGNoIChzaGlmdCkgewogICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihwb2ludGVyKSB7CiAgICAgICAgICAgICAgICAgIHZhciBoZWFwID0gc2lnbmVkID8gSEVBUDggOiBIRUFQVTg7CiAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShoZWFwW3BvaW50ZXJdKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHBvaW50ZXIpIHsKICAgICAgICAgICAgICAgICAgdmFyIGhlYXAgPSBzaWduZWQgPyBIRUFQMTYgOiBIRUFQVTE2OwogICAgICAgICAgICAgICAgICByZXR1cm4gdGhpc1siZnJvbVdpcmVUeXBlIl0oaGVhcFtwb2ludGVyID4+IDFdKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHBvaW50ZXIpIHsKICAgICAgICAgICAgICAgICAgdmFyIGhlYXAgPSBzaWduZWQgPyBIRUFQMzIgOiBIRUFQVTMyOwogICAgICAgICAgICAgICAgICByZXR1cm4gdGhpc1siZnJvbVdpcmVUeXBlIl0oaGVhcFtwb2ludGVyID4+IDJdKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIlVua25vd24gaW50ZWdlciB0eXBlOiAiICsgbmFtZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIF9fZW1iaW5kX3JlZ2lzdGVyX2VudW0ocmF3VHlwZSwgbmFtZSwgc2l6ZSwgaXNTaWduZWQpIHsKICAgICAgICAgICAgdmFyIHNoaWZ0ID0gZ2V0U2hpZnRGcm9tU2l6ZShzaXplKTsKICAgICAgICAgICAgbmFtZSA9IHJlYWRMYXRpbjFTdHJpbmcobmFtZSk7CiAgICAgICAgICAgIGZ1bmN0aW9uIGN0b3IoKSB7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY3Rvci52YWx1ZXMgPSB7fTsKICAgICAgICAgICAgcmVnaXN0ZXJUeXBlKHJhd1R5cGUsIHsgbmFtZSwgY29uc3RydWN0b3I6IGN0b3IsICJmcm9tV2lyZVR5cGUiOiBmdW5jdGlvbihjKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudmFsdWVzW2NdOwogICAgICAgICAgICB9LCAidG9XaXJlVHlwZSI6IGZ1bmN0aW9uKGRlc3RydWN0b3JzLCBjKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGMudmFsdWU7CiAgICAgICAgICAgIH0sICJhcmdQYWNrQWR2YW5jZSI6IDgsICJyZWFkVmFsdWVGcm9tUG9pbnRlciI6IGVudW1SZWFkVmFsdWVGcm9tUG9pbnRlcihuYW1lLCBzaGlmdCwgaXNTaWduZWQpLCBkZXN0cnVjdG9yRnVuY3Rpb246IG51bGwgfSk7CiAgICAgICAgICAgIGV4cG9zZVB1YmxpY1N5bWJvbChuYW1lLCBjdG9yKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIHJlcXVpcmVSZWdpc3RlcmVkVHlwZShyYXdUeXBlLCBodW1hbk5hbWUpIHsKICAgICAgICAgICAgdmFyIGltcGwgPSByZWdpc3RlcmVkVHlwZXNbcmF3VHlwZV07CiAgICAgICAgICAgIGlmICh2b2lkIDAgPT09IGltcGwpIHsKICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcihodW1hbk5hbWUgKyAiIGhhcyB1bmtub3duIHR5cGUgIiArIGdldFR5cGVOYW1lKHJhd1R5cGUpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gaW1wbDsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIF9fZW1iaW5kX3JlZ2lzdGVyX2VudW1fdmFsdWUocmF3RW51bVR5cGUsIG5hbWUsIGVudW1WYWx1ZSkgewogICAgICAgICAgICB2YXIgZW51bVR5cGUgPSByZXF1aXJlUmVnaXN0ZXJlZFR5cGUocmF3RW51bVR5cGUsICJlbnVtIik7CiAgICAgICAgICAgIG5hbWUgPSByZWFkTGF0aW4xU3RyaW5nKG5hbWUpOwogICAgICAgICAgICB2YXIgRW51bSA9IGVudW1UeXBlLmNvbnN0cnVjdG9yOwogICAgICAgICAgICB2YXIgVmFsdWUgPSBPYmplY3QuY3JlYXRlKGVudW1UeXBlLmNvbnN0cnVjdG9yLnByb3RvdHlwZSwgeyB2YWx1ZTogeyB2YWx1ZTogZW51bVZhbHVlIH0sIGNvbnN0cnVjdG9yOiB7IHZhbHVlOiBjcmVhdGVOYW1lZEZ1bmN0aW9uKGVudW1UeXBlLm5hbWUgKyAiXyIgKyBuYW1lLCBmdW5jdGlvbigpIHsKICAgICAgICAgICAgfSkgfSB9KTsKICAgICAgICAgICAgRW51bS52YWx1ZXNbZW51bVZhbHVlXSA9IFZhbHVlOwogICAgICAgICAgICBFbnVtW25hbWVdID0gVmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfZW1iaW5kX3JlcHIodjMpIHsKICAgICAgICAgICAgaWYgKHYzID09PSBudWxsKSB7CiAgICAgICAgICAgICAgcmV0dXJuICJudWxsIjsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgdCA9IHR5cGVvZiB2MzsKICAgICAgICAgICAgaWYgKHQgPT09ICJvYmplY3QiIHx8IHQgPT09ICJhcnJheSIgfHwgdCA9PT0gImZ1bmN0aW9uIikgewogICAgICAgICAgICAgIHJldHVybiB2My50b1N0cmluZygpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHJldHVybiAiIiArIHYzOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBmbG9hdFJlYWRWYWx1ZUZyb21Qb2ludGVyKG5hbWUsIHNoaWZ0KSB7CiAgICAgICAgICAgIHN3aXRjaCAoc2hpZnQpIHsKICAgICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24ocG9pbnRlcikgewogICAgICAgICAgICAgICAgICByZXR1cm4gdGhpc1siZnJvbVdpcmVUeXBlIl0oSEVBUEYzMltwb2ludGVyID4+IDJdKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHBvaW50ZXIpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXNbImZyb21XaXJlVHlwZSJdKEhFQVBGNjRbcG9pbnRlciA+PiAzXSk7CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJVbmtub3duIGZsb2F0IHR5cGU6ICIgKyBuYW1lKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbWJpbmRfcmVnaXN0ZXJfZmxvYXQocmF3VHlwZSwgbmFtZSwgc2l6ZSkgewogICAgICAgICAgICB2YXIgc2hpZnQgPSBnZXRTaGlmdEZyb21TaXplKHNpemUpOwogICAgICAgICAgICBuYW1lID0gcmVhZExhdGluMVN0cmluZyhuYW1lKTsKICAgICAgICAgICAgcmVnaXN0ZXJUeXBlKHJhd1R5cGUsIHsgbmFtZSwgImZyb21XaXJlVHlwZSI6IGZ1bmN0aW9uKHZhbHVlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgICAgICB9LCAidG9XaXJlVHlwZSI6IGZ1bmN0aW9uKGRlc3RydWN0b3JzLCB2YWx1ZSkgewogICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICJudW1iZXIiICYmIHR5cGVvZiB2YWx1ZSAhPT0gImJvb2xlYW4iKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY29udmVydCAiJyArIF9lbWJpbmRfcmVwcih2YWx1ZSkgKyAnIiB0byAnICsgdGhpcy5uYW1lKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgICAgICB9LCAiYXJnUGFja0FkdmFuY2UiOiA4LCAicmVhZFZhbHVlRnJvbVBvaW50ZXIiOiBmbG9hdFJlYWRWYWx1ZUZyb21Qb2ludGVyKG5hbWUsIHNoaWZ0KSwgZGVzdHJ1Y3RvckZ1bmN0aW9uOiBudWxsIH0pOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbWJpbmRfcmVnaXN0ZXJfZnVuY3Rpb24obmFtZSwgYXJnQ291bnQsIHJhd0FyZ1R5cGVzQWRkciwgc2lnbmF0dXJlLCByYXdJbnZva2VyLCBmbikgewogICAgICAgICAgICB2YXIgYXJnVHlwZXMgPSBoZWFwMzJWZWN0b3JUb0FycmF5KGFyZ0NvdW50LCByYXdBcmdUeXBlc0FkZHIpOwogICAgICAgICAgICBuYW1lID0gcmVhZExhdGluMVN0cmluZyhuYW1lKTsKICAgICAgICAgICAgcmF3SW52b2tlciA9IGVtYmluZF9fcmVxdWlyZUZ1bmN0aW9uKHNpZ25hdHVyZSwgcmF3SW52b2tlcik7CiAgICAgICAgICAgIGV4cG9zZVB1YmxpY1N5bWJvbChuYW1lLCBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICB0aHJvd1VuYm91bmRUeXBlRXJyb3IoIkNhbm5vdCBjYWxsICIgKyBuYW1lICsgIiBkdWUgdG8gdW5ib3VuZCB0eXBlcyIsIGFyZ1R5cGVzKTsKICAgICAgICAgICAgfSwgYXJnQ291bnQgLSAxKTsKICAgICAgICAgICAgd2hlbkRlcGVuZGVudFR5cGVzQXJlUmVzb2x2ZWQoW10sIGFyZ1R5cGVzLCBmdW5jdGlvbihhcmdUeXBlczIpIHsKICAgICAgICAgICAgICB2YXIgaW52b2tlckFyZ3NBcnJheSA9IFthcmdUeXBlczJbMF0sIG51bGxdLmNvbmNhdChhcmdUeXBlczIuc2xpY2UoMSkpOwogICAgICAgICAgICAgIHJlcGxhY2VQdWJsaWNTeW1ib2wobmFtZSwgY3JhZnRJbnZva2VyRnVuY3Rpb24obmFtZSwgaW52b2tlckFyZ3NBcnJheSwgbnVsbCwgcmF3SW52b2tlciwgZm4pLCBhcmdDb3VudCAtIDEpOwogICAgICAgICAgICAgIHJldHVybiBbXTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBpbnRlZ2VyUmVhZFZhbHVlRnJvbVBvaW50ZXIobmFtZSwgc2hpZnQsIHNpZ25lZCkgewogICAgICAgICAgICBzd2l0Y2ggKHNoaWZ0KSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgcmV0dXJuIHNpZ25lZCA/IGZ1bmN0aW9uIHJlYWRTOEZyb21Qb2ludGVyKHBvaW50ZXIpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuIEhFQVA4W3BvaW50ZXJdOwogICAgICAgICAgICAgICAgfSA6IGZ1bmN0aW9uIHJlYWRVOEZyb21Qb2ludGVyKHBvaW50ZXIpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuIEhFQVBVOFtwb2ludGVyXTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgcmV0dXJuIHNpZ25lZCA/IGZ1bmN0aW9uIHJlYWRTMTZGcm9tUG9pbnRlcihwb2ludGVyKSB7CiAgICAgICAgICAgICAgICAgIHJldHVybiBIRUFQMTZbcG9pbnRlciA+PiAxXTsKICAgICAgICAgICAgICAgIH0gOiBmdW5jdGlvbiByZWFkVTE2RnJvbVBvaW50ZXIocG9pbnRlcikgewogICAgICAgICAgICAgICAgICByZXR1cm4gSEVBUFUxNltwb2ludGVyID4+IDFdOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgICByZXR1cm4gc2lnbmVkID8gZnVuY3Rpb24gcmVhZFMzMkZyb21Qb2ludGVyKHBvaW50ZXIpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuIEhFQVAzMltwb2ludGVyID4+IDJdOwogICAgICAgICAgICAgICAgfSA6IGZ1bmN0aW9uIHJlYWRVMzJGcm9tUG9pbnRlcihwb2ludGVyKSB7CiAgICAgICAgICAgICAgICAgIHJldHVybiBIRUFQVTMyW3BvaW50ZXIgPj4gMl07CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCJVbmtub3duIGludGVnZXIgdHlwZTogIiArIG5hbWUpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfX2VtYmluZF9yZWdpc3Rlcl9pbnRlZ2VyKHByaW1pdGl2ZVR5cGUsIG5hbWUsIHNpemUsIG1pblJhbmdlLCBtYXhSYW5nZSkgewogICAgICAgICAgICBuYW1lID0gcmVhZExhdGluMVN0cmluZyhuYW1lKTsKICAgICAgICAgICAgaWYgKG1heFJhbmdlID09PSAtMSkgewogICAgICAgICAgICAgIG1heFJhbmdlID0gNDI5NDk2NzI5NTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgc2hpZnQgPSBnZXRTaGlmdEZyb21TaXplKHNpemUpOwogICAgICAgICAgICB2YXIgZnJvbVdpcmVUeXBlID0gZnVuY3Rpb24odmFsdWUpIHsKICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgICAgIH07CiAgICAgICAgICAgIGlmIChtaW5SYW5nZSA9PT0gMCkgewogICAgICAgICAgICAgIHZhciBiaXRzaGlmdCA9IDMyIC0gOCAqIHNpemU7CiAgICAgICAgICAgICAgZnJvbVdpcmVUeXBlID0gZnVuY3Rpb24odmFsdWUpIHsKICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZSA8PCBiaXRzaGlmdCA+Pj4gYml0c2hpZnQ7CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgaXNVbnNpZ25lZFR5cGUgPSBuYW1lLmluZGV4T2YoInVuc2lnbmVkIikgIT0gLTE7CiAgICAgICAgICAgIHJlZ2lzdGVyVHlwZShwcmltaXRpdmVUeXBlLCB7IG5hbWUsICJmcm9tV2lyZVR5cGUiOiBmcm9tV2lyZVR5cGUsICJ0b1dpcmVUeXBlIjogZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsIHZhbHVlKSB7CiAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gIm51bWJlciIgJiYgdHlwZW9mIHZhbHVlICE9PSAiYm9vbGVhbiIpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0ICInICsgX2VtYmluZF9yZXByKHZhbHVlKSArICciIHRvICcgKyB0aGlzLm5hbWUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAodmFsdWUgPCBtaW5SYW5nZSB8fCB2YWx1ZSA+IG1heFJhbmdlKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdQYXNzaW5nIGEgbnVtYmVyICInICsgX2VtYmluZF9yZXByKHZhbHVlKSArICciIGZyb20gSlMgc2lkZSB0byBDL0MrKyBzaWRlIHRvIGFuIGFyZ3VtZW50IG9mIHR5cGUgIicgKyBuYW1lICsgJyIsIHdoaWNoIGlzIG91dHNpZGUgdGhlIHZhbGlkIHJhbmdlIFsnICsgbWluUmFuZ2UgKyAiLCAiICsgbWF4UmFuZ2UgKyAiXSEiKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIGlzVW5zaWduZWRUeXBlID8gdmFsdWUgPj4+IDAgOiB2YWx1ZSB8IDA7CiAgICAgICAgICAgIH0sICJhcmdQYWNrQWR2YW5jZSI6IDgsICJyZWFkVmFsdWVGcm9tUG9pbnRlciI6IGludGVnZXJSZWFkVmFsdWVGcm9tUG9pbnRlcihuYW1lLCBzaGlmdCwgbWluUmFuZ2UgIT09IDApLCBkZXN0cnVjdG9yRnVuY3Rpb246IG51bGwgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfX2VtYmluZF9yZWdpc3Rlcl9tZW1vcnlfdmlldyhyYXdUeXBlLCBkYXRhVHlwZUluZGV4LCBuYW1lKSB7CiAgICAgICAgICAgIHZhciB0eXBlTWFwcGluZyA9IFtJbnQ4QXJyYXksIFVpbnQ4QXJyYXksIEludDE2QXJyYXksIFVpbnQxNkFycmF5LCBJbnQzMkFycmF5LCBVaW50MzJBcnJheSwgRmxvYXQzMkFycmF5LCBGbG9hdDY0QXJyYXldOwogICAgICAgICAgICB2YXIgVEEgPSB0eXBlTWFwcGluZ1tkYXRhVHlwZUluZGV4XTsKICAgICAgICAgICAgZnVuY3Rpb24gZGVjb2RlTWVtb3J5VmlldyhoYW5kbGUpIHsKICAgICAgICAgICAgICBoYW5kbGUgPSBoYW5kbGUgPj4gMjsKICAgICAgICAgICAgICB2YXIgaGVhcCA9IEhFQVBVMzI7CiAgICAgICAgICAgICAgdmFyIHNpemUgPSBoZWFwW2hhbmRsZV07CiAgICAgICAgICAgICAgdmFyIGRhdGEgPSBoZWFwW2hhbmRsZSArIDFdOwogICAgICAgICAgICAgIHJldHVybiBuZXcgVEEoYnVmZmVyLCBkYXRhLCBzaXplKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBuYW1lID0gcmVhZExhdGluMVN0cmluZyhuYW1lKTsKICAgICAgICAgICAgcmVnaXN0ZXJUeXBlKHJhd1R5cGUsIHsgbmFtZSwgImZyb21XaXJlVHlwZSI6IGRlY29kZU1lbW9yeVZpZXcsICJhcmdQYWNrQWR2YW5jZSI6IDgsICJyZWFkVmFsdWVGcm9tUG9pbnRlciI6IGRlY29kZU1lbW9yeVZpZXcgfSwgeyBpZ25vcmVEdXBsaWNhdGVSZWdpc3RyYXRpb25zOiB0cnVlIH0pOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZyhyYXdUeXBlLCBuYW1lKSB7CiAgICAgICAgICAgIG5hbWUgPSByZWFkTGF0aW4xU3RyaW5nKG5hbWUpOwogICAgICAgICAgICB2YXIgc3RkU3RyaW5nSXNVVEY4ID0gbmFtZSA9PT0gInN0ZDo6c3RyaW5nIjsKICAgICAgICAgICAgcmVnaXN0ZXJUeXBlKHJhd1R5cGUsIHsgbmFtZSwgImZyb21XaXJlVHlwZSI6IGZ1bmN0aW9uKHZhbHVlKSB7CiAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IEhFQVBVMzJbdmFsdWUgPj4gMl07CiAgICAgICAgICAgICAgdmFyIHN0cjsKICAgICAgICAgICAgICBpZiAoc3RkU3RyaW5nSXNVVEY4KSB7CiAgICAgICAgICAgICAgICB2YXIgZGVjb2RlU3RhcnRQdHIgPSB2YWx1ZSArIDQ7CiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8PSBsZW5ndGg7ICsraSkgewogICAgICAgICAgICAgICAgICB2YXIgY3VycmVudEJ5dGVQdHIgPSB2YWx1ZSArIDQgKyBpOwogICAgICAgICAgICAgICAgICBpZiAoaSA9PSBsZW5ndGggfHwgSEVBUFU4W2N1cnJlbnRCeXRlUHRyXSA9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIG1heFJlYWQgPSBjdXJyZW50Qnl0ZVB0ciAtIGRlY29kZVN0YXJ0UHRyOwogICAgICAgICAgICAgICAgICAgIHZhciBzdHJpbmdTZWdtZW50ID0gVVRGOFRvU3RyaW5nKGRlY29kZVN0YXJ0UHRyLCBtYXhSZWFkKTsKICAgICAgICAgICAgICAgICAgICBpZiAoc3RyID09PSB2b2lkIDApIHsKICAgICAgICAgICAgICAgICAgICAgIHN0ciA9IHN0cmluZ1NlZ21lbnQ7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDApOwogICAgICAgICAgICAgICAgICAgICAgc3RyICs9IHN0cmluZ1NlZ21lbnQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRlY29kZVN0YXJ0UHRyID0gY3VycmVudEJ5dGVQdHIgKyAxOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHZhciBhMyA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgICAgICAgICBhM1tpXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoSEVBUFU4W3ZhbHVlICsgNCArIGldKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHN0ciA9IGEzLmpvaW4oIiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBfZnJlZSh2YWx1ZSk7CiAgICAgICAgICAgICAgcmV0dXJuIHN0cjsKICAgICAgICAgICAgfSwgInRvV2lyZVR5cGUiOiBmdW5jdGlvbihkZXN0cnVjdG9ycywgdmFsdWUpIHsKICAgICAgICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgewogICAgICAgICAgICAgICAgdmFsdWUgPSBuZXcgVWludDhBcnJheSh2YWx1ZSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHZhciBnZXRMZW5ndGg7CiAgICAgICAgICAgICAgdmFyIHZhbHVlSXNPZlR5cGVTdHJpbmcgPSB0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciOwogICAgICAgICAgICAgIGlmICghKHZhbHVlSXNPZlR5cGVTdHJpbmcgfHwgdmFsdWUgaW5zdGFuY2VvZiBVaW50OEFycmF5IHx8IHZhbHVlIGluc3RhbmNlb2YgVWludDhDbGFtcGVkQXJyYXkgfHwgdmFsdWUgaW5zdGFuY2VvZiBJbnQ4QXJyYXkpKSB7CiAgICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiQ2Fubm90IHBhc3Mgbm9uLXN0cmluZyB0byBzdGQ6OnN0cmluZyIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoc3RkU3RyaW5nSXNVVEY4ICYmIHZhbHVlSXNPZlR5cGVTdHJpbmcpIHsKICAgICAgICAgICAgICAgIGdldExlbmd0aCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgICByZXR1cm4gbGVuZ3RoQnl0ZXNVVEY4KHZhbHVlKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGdldExlbmd0aCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUubGVuZ3RoOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGdldExlbmd0aCgpOwogICAgICAgICAgICAgIHZhciBwdHIgPSBfbWFsbG9jKDQgKyBsZW5ndGggKyAxKTsKICAgICAgICAgICAgICBIRUFQVTMyW3B0ciA+PiAyXSA9IGxlbmd0aDsKICAgICAgICAgICAgICBpZiAoc3RkU3RyaW5nSXNVVEY4ICYmIHZhbHVlSXNPZlR5cGVTdHJpbmcpIHsKICAgICAgICAgICAgICAgIHN0cmluZ1RvVVRGOCh2YWx1ZSwgcHRyICsgNCwgbGVuZ3RoICsgMSk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGlmICh2YWx1ZUlzT2ZUeXBlU3RyaW5nKSB7CiAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgY2hhckNvZGUgPSB2YWx1ZS5jaGFyQ29kZUF0KGkpOwogICAgICAgICAgICAgICAgICAgIGlmIChjaGFyQ29kZSA+IDI1NSkgewogICAgICAgICAgICAgICAgICAgICAgX2ZyZWUocHRyKTsKICAgICAgICAgICAgICAgICAgICAgIHRocm93QmluZGluZ0Vycm9yKCJTdHJpbmcgaGFzIFVURi0xNiBjb2RlIHVuaXRzIHRoYXQgZG8gbm90IGZpdCBpbiA4IGJpdHMiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgSEVBUFU4W3B0ciArIDQgKyBpXSA9IGNoYXJDb2RlOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgICAgICAgICAgSEVBUFU4W3B0ciArIDQgKyBpXSA9IHZhbHVlW2ldOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChkZXN0cnVjdG9ycyAhPT0gbnVsbCkgewogICAgICAgICAgICAgICAgZGVzdHJ1Y3RvcnMucHVzaChfZnJlZSwgcHRyKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIHB0cjsKICAgICAgICAgICAgfSwgImFyZ1BhY2tBZHZhbmNlIjogOCwgInJlYWRWYWx1ZUZyb21Qb2ludGVyIjogc2ltcGxlUmVhZFZhbHVlRnJvbVBvaW50ZXIsIGRlc3RydWN0b3JGdW5jdGlvbjogZnVuY3Rpb24ocHRyKSB7CiAgICAgICAgICAgICAgX2ZyZWUocHRyKTsKICAgICAgICAgICAgfSB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIF9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nKHJhd1R5cGUsIGNoYXJTaXplLCBuYW1lKSB7CiAgICAgICAgICAgIG5hbWUgPSByZWFkTGF0aW4xU3RyaW5nKG5hbWUpOwogICAgICAgICAgICB2YXIgZGVjb2RlU3RyaW5nLCBlbmNvZGVTdHJpbmcsIGdldEhlYXAsIGxlbmd0aEJ5dGVzVVRGLCBzaGlmdDsKICAgICAgICAgICAgaWYgKGNoYXJTaXplID09PSAyKSB7CiAgICAgICAgICAgICAgZGVjb2RlU3RyaW5nID0gVVRGMTZUb1N0cmluZzsKICAgICAgICAgICAgICBlbmNvZGVTdHJpbmcgPSBzdHJpbmdUb1VURjE2OwogICAgICAgICAgICAgIGxlbmd0aEJ5dGVzVVRGID0gbGVuZ3RoQnl0ZXNVVEYxNjsKICAgICAgICAgICAgICBnZXRIZWFwID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gSEVBUFUxNjsKICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgIHNoaWZ0ID0gMTsKICAgICAgICAgICAgfSBlbHNlIGlmIChjaGFyU2l6ZSA9PT0gNCkgewogICAgICAgICAgICAgIGRlY29kZVN0cmluZyA9IFVURjMyVG9TdHJpbmc7CiAgICAgICAgICAgICAgZW5jb2RlU3RyaW5nID0gc3RyaW5nVG9VVEYzMjsKICAgICAgICAgICAgICBsZW5ndGhCeXRlc1VURiA9IGxlbmd0aEJ5dGVzVVRGMzI7CiAgICAgICAgICAgICAgZ2V0SGVhcCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgcmV0dXJuIEhFQVBVMzI7CiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICBzaGlmdCA9IDI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVnaXN0ZXJUeXBlKHJhd1R5cGUsIHsgbmFtZSwgImZyb21XaXJlVHlwZSI6IGZ1bmN0aW9uKHZhbHVlKSB7CiAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IEhFQVBVMzJbdmFsdWUgPj4gMl07CiAgICAgICAgICAgICAgdmFyIEhFQVAgPSBnZXRIZWFwKCk7CiAgICAgICAgICAgICAgdmFyIHN0cjsKICAgICAgICAgICAgICB2YXIgZGVjb2RlU3RhcnRQdHIgPSB2YWx1ZSArIDQ7CiAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPD0gbGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgICAgIHZhciBjdXJyZW50Qnl0ZVB0ciA9IHZhbHVlICsgNCArIGkgKiBjaGFyU2l6ZTsKICAgICAgICAgICAgICAgIGlmIChpID09IGxlbmd0aCB8fCBIRUFQW2N1cnJlbnRCeXRlUHRyID4+IHNoaWZ0XSA9PSAwKSB7CiAgICAgICAgICAgICAgICAgIHZhciBtYXhSZWFkQnl0ZXMgPSBjdXJyZW50Qnl0ZVB0ciAtIGRlY29kZVN0YXJ0UHRyOwogICAgICAgICAgICAgICAgICB2YXIgc3RyaW5nU2VnbWVudCA9IGRlY29kZVN0cmluZyhkZWNvZGVTdGFydFB0ciwgbWF4UmVhZEJ5dGVzKTsKICAgICAgICAgICAgICAgICAgaWYgKHN0ciA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgICAgICAgc3RyID0gc3RyaW5nU2VnbWVudDsKICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgwKTsKICAgICAgICAgICAgICAgICAgICBzdHIgKz0gc3RyaW5nU2VnbWVudDsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBkZWNvZGVTdGFydFB0ciA9IGN1cnJlbnRCeXRlUHRyICsgY2hhclNpemU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIF9mcmVlKHZhbHVlKTsKICAgICAgICAgICAgICByZXR1cm4gc3RyOwogICAgICAgICAgICB9LCAidG9XaXJlVHlwZSI6IGZ1bmN0aW9uKGRlc3RydWN0b3JzLCB2YWx1ZSkgewogICAgICAgICAgICAgIGlmICghKHR5cGVvZiB2YWx1ZSA9PT0gInN0cmluZyIpKSB7CiAgICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiQ2Fubm90IHBhc3Mgbm9uLXN0cmluZyB0byBDKysgc3RyaW5nIHR5cGUgIiArIG5hbWUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gbGVuZ3RoQnl0ZXNVVEYodmFsdWUpOwogICAgICAgICAgICAgIHZhciBwdHIgPSBfbWFsbG9jKDQgKyBsZW5ndGggKyBjaGFyU2l6ZSk7CiAgICAgICAgICAgICAgSEVBUFUzMltwdHIgPj4gMl0gPSBsZW5ndGggPj4gc2hpZnQ7CiAgICAgICAgICAgICAgZW5jb2RlU3RyaW5nKHZhbHVlLCBwdHIgKyA0LCBsZW5ndGggKyBjaGFyU2l6ZSk7CiAgICAgICAgICAgICAgaWYgKGRlc3RydWN0b3JzICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICBkZXN0cnVjdG9ycy5wdXNoKF9mcmVlLCBwdHIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gcHRyOwogICAgICAgICAgICB9LCAiYXJnUGFja0FkdmFuY2UiOiA4LCAicmVhZFZhbHVlRnJvbVBvaW50ZXIiOiBzaW1wbGVSZWFkVmFsdWVGcm9tUG9pbnRlciwgZGVzdHJ1Y3RvckZ1bmN0aW9uOiBmdW5jdGlvbihwdHIpIHsKICAgICAgICAgICAgICBfZnJlZShwdHIpOwogICAgICAgICAgICB9IH0pOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbWJpbmRfcmVnaXN0ZXJfdmFsdWVfb2JqZWN0KHJhd1R5cGUsIG5hbWUsIGNvbnN0cnVjdG9yU2lnbmF0dXJlLCByYXdDb25zdHJ1Y3RvciwgZGVzdHJ1Y3RvclNpZ25hdHVyZSwgcmF3RGVzdHJ1Y3RvcikgewogICAgICAgICAgICBzdHJ1Y3RSZWdpc3RyYXRpb25zW3Jhd1R5cGVdID0geyBuYW1lOiByZWFkTGF0aW4xU3RyaW5nKG5hbWUpLCByYXdDb25zdHJ1Y3RvcjogZW1iaW5kX19yZXF1aXJlRnVuY3Rpb24oY29uc3RydWN0b3JTaWduYXR1cmUsIHJhd0NvbnN0cnVjdG9yKSwgcmF3RGVzdHJ1Y3RvcjogZW1iaW5kX19yZXF1aXJlRnVuY3Rpb24oZGVzdHJ1Y3RvclNpZ25hdHVyZSwgcmF3RGVzdHJ1Y3RvciksIGZpZWxkczogW10gfTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIF9fZW1iaW5kX3JlZ2lzdGVyX3ZhbHVlX29iamVjdF9maWVsZChzdHJ1Y3RUeXBlLCBmaWVsZE5hbWUsIGdldHRlclJldHVyblR5cGUsIGdldHRlclNpZ25hdHVyZSwgZ2V0dGVyLCBnZXR0ZXJDb250ZXh0LCBzZXR0ZXJBcmd1bWVudFR5cGUsIHNldHRlclNpZ25hdHVyZSwgc2V0dGVyLCBzZXR0ZXJDb250ZXh0KSB7CiAgICAgICAgICAgIHN0cnVjdFJlZ2lzdHJhdGlvbnNbc3RydWN0VHlwZV0uZmllbGRzLnB1c2goeyBmaWVsZE5hbWU6IHJlYWRMYXRpbjFTdHJpbmcoZmllbGROYW1lKSwgZ2V0dGVyUmV0dXJuVHlwZSwgZ2V0dGVyOiBlbWJpbmRfX3JlcXVpcmVGdW5jdGlvbihnZXR0ZXJTaWduYXR1cmUsIGdldHRlciksIGdldHRlckNvbnRleHQsIHNldHRlckFyZ3VtZW50VHlwZSwgc2V0dGVyOiBlbWJpbmRfX3JlcXVpcmVGdW5jdGlvbihzZXR0ZXJTaWduYXR1cmUsIHNldHRlciksIHNldHRlckNvbnRleHQgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfX2VtYmluZF9yZWdpc3Rlcl92b2lkKHJhd1R5cGUsIG5hbWUpIHsKICAgICAgICAgICAgbmFtZSA9IHJlYWRMYXRpbjFTdHJpbmcobmFtZSk7CiAgICAgICAgICAgIHJlZ2lzdGVyVHlwZShyYXdUeXBlLCB7IGlzVm9pZDogdHJ1ZSwgbmFtZSwgImFyZ1BhY2tBZHZhbmNlIjogMCwgImZyb21XaXJlVHlwZSI6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHJldHVybiB2b2lkIDA7CiAgICAgICAgICAgIH0sICJ0b1dpcmVUeXBlIjogZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsIG8pIHsKICAgICAgICAgICAgICByZXR1cm4gdm9pZCAwOwogICAgICAgICAgICB9IH0pOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gcmVxdWlyZUhhbmRsZShoYW5kbGUpIHsKICAgICAgICAgICAgaWYgKCFoYW5kbGUpIHsKICAgICAgICAgICAgICB0aHJvd0JpbmRpbmdFcnJvcigiQ2Fubm90IHVzZSBkZWxldGVkIHZhbC4gaGFuZGxlID0gIiArIGhhbmRsZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGVtdmFsX2hhbmRsZV9hcnJheVtoYW5kbGVdLnZhbHVlOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbXZhbF9hcyhoYW5kbGUsIHJldHVyblR5cGUsIGRlc3RydWN0b3JzUmVmKSB7CiAgICAgICAgICAgIGhhbmRsZSA9IHJlcXVpcmVIYW5kbGUoaGFuZGxlKTsKICAgICAgICAgICAgcmV0dXJuVHlwZSA9IHJlcXVpcmVSZWdpc3RlcmVkVHlwZShyZXR1cm5UeXBlLCAiZW12YWw6OmFzIik7CiAgICAgICAgICAgIHZhciBkZXN0cnVjdG9ycyA9IFtdOwogICAgICAgICAgICB2YXIgcmQgPSBfX2VtdmFsX3JlZ2lzdGVyKGRlc3RydWN0b3JzKTsKICAgICAgICAgICAgSEVBUDMyW2Rlc3RydWN0b3JzUmVmID4+IDJdID0gcmQ7CiAgICAgICAgICAgIHJldHVybiByZXR1cm5UeXBlWyJ0b1dpcmVUeXBlIl0oZGVzdHJ1Y3RvcnMsIGhhbmRsZSk7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgZW12YWxfc3ltYm9scyA9IHt9OwogICAgICAgICAgZnVuY3Rpb24gZ2V0U3RyaW5nT3JTeW1ib2woYWRkcmVzcykgewogICAgICAgICAgICB2YXIgc3ltYm9sID0gZW12YWxfc3ltYm9sc1thZGRyZXNzXTsKICAgICAgICAgICAgaWYgKHN5bWJvbCA9PT0gdm9pZCAwKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHJlYWRMYXRpbjFTdHJpbmcoYWRkcmVzcyk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgcmV0dXJuIHN5bWJvbDsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgdmFyIGVtdmFsX21ldGhvZENhbGxlcnMgPSBbXTsKICAgICAgICAgIGZ1bmN0aW9uIF9fZW12YWxfY2FsbF92b2lkX21ldGhvZChjYWxsZXIsIGhhbmRsZSwgbWV0aG9kTmFtZSwgYXJncykgewogICAgICAgICAgICBjYWxsZXIgPSBlbXZhbF9tZXRob2RDYWxsZXJzW2NhbGxlcl07CiAgICAgICAgICAgIGhhbmRsZSA9IHJlcXVpcmVIYW5kbGUoaGFuZGxlKTsKICAgICAgICAgICAgbWV0aG9kTmFtZSA9IGdldFN0cmluZ09yU3ltYm9sKG1ldGhvZE5hbWUpOwogICAgICAgICAgICBjYWxsZXIoaGFuZGxlLCBtZXRob2ROYW1lLCBudWxsLCBhcmdzKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGVtdmFsX2dldF9nbG9iYWwoKSB7CiAgICAgICAgICAgIGlmICh0eXBlb2YgZ2xvYmFsVGhpcyA9PT0gIm9iamVjdCIpIHsKICAgICAgICAgICAgICByZXR1cm4gZ2xvYmFsVGhpczsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gKC8qIEBfX1BVUkVfXyAqLyAoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIEZ1bmN0aW9uOwogICAgICAgICAgICB9KSgpKSgicmV0dXJuIHRoaXMiKSgpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbXZhbF9nZXRfZ2xvYmFsKG5hbWUpIHsKICAgICAgICAgICAgaWYgKG5hbWUgPT09IDApIHsKICAgICAgICAgICAgICByZXR1cm4gX19lbXZhbF9yZWdpc3RlcihlbXZhbF9nZXRfZ2xvYmFsKCkpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIG5hbWUgPSBnZXRTdHJpbmdPclN5bWJvbChuYW1lKTsKICAgICAgICAgICAgICByZXR1cm4gX19lbXZhbF9yZWdpc3RlcihlbXZhbF9nZXRfZ2xvYmFsKClbbmFtZV0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfX2VtdmFsX2FkZE1ldGhvZENhbGxlcihjYWxsZXIpIHsKICAgICAgICAgICAgdmFyIGlkID0gZW12YWxfbWV0aG9kQ2FsbGVycy5sZW5ndGg7CiAgICAgICAgICAgIGVtdmFsX21ldGhvZENhbGxlcnMucHVzaChjYWxsZXIpOwogICAgICAgICAgICByZXR1cm4gaWQ7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfX2VtdmFsX2xvb2t1cFR5cGVzKGFyZ0NvdW50LCBhcmdUeXBlcykgewogICAgICAgICAgICB2YXIgYTMgPSBuZXcgQXJyYXkoYXJnQ291bnQpOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ0NvdW50OyArK2kpIHsKICAgICAgICAgICAgICBhM1tpXSA9IHJlcXVpcmVSZWdpc3RlcmVkVHlwZShIRUFQMzJbKGFyZ1R5cGVzID4+IDIpICsgaV0sICJwYXJhbWV0ZXIgIiArIGkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBhMzsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIF9fZW12YWxfZ2V0X21ldGhvZF9jYWxsZXIoYXJnQ291bnQsIGFyZ1R5cGVzKSB7CiAgICAgICAgICAgIHZhciB0eXBlcyA9IF9fZW12YWxfbG9va3VwVHlwZXMoYXJnQ291bnQsIGFyZ1R5cGVzKTsKICAgICAgICAgICAgdmFyIHJldFR5cGUgPSB0eXBlc1swXTsKICAgICAgICAgICAgdmFyIHNpZ25hdHVyZU5hbWUgPSByZXRUeXBlLm5hbWUgKyAiXyQiICsgdHlwZXMuc2xpY2UoMSkubWFwKGZ1bmN0aW9uKHQpIHsKICAgICAgICAgICAgICByZXR1cm4gdC5uYW1lOwogICAgICAgICAgICB9KS5qb2luKCJfIikgKyAiJCI7CiAgICAgICAgICAgIHZhciBwYXJhbXMgPSBbInJldFR5cGUiXTsKICAgICAgICAgICAgdmFyIGFyZ3MgPSBbcmV0VHlwZV07CiAgICAgICAgICAgIHZhciBhcmdzTGlzdCA9ICIiOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ0NvdW50IC0gMTsgKytpKSB7CiAgICAgICAgICAgICAgYXJnc0xpc3QgKz0gKGkgIT09IDAgPyAiLCAiIDogIiIpICsgImFyZyIgKyBpOwogICAgICAgICAgICAgIHBhcmFtcy5wdXNoKCJhcmdUeXBlIiArIGkpOwogICAgICAgICAgICAgIGFyZ3MucHVzaCh0eXBlc1sxICsgaV0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBmdW5jdGlvbk5hbWUgPSBtYWtlTGVnYWxGdW5jdGlvbk5hbWUoIm1ldGhvZENhbGxlcl8iICsgc2lnbmF0dXJlTmFtZSk7CiAgICAgICAgICAgIHZhciBmdW5jdGlvbkJvZHkgPSAicmV0dXJuIGZ1bmN0aW9uICIgKyBmdW5jdGlvbk5hbWUgKyAiKGhhbmRsZSwgbmFtZSwgZGVzdHJ1Y3RvcnMsIGFyZ3MpIHtcbiI7CiAgICAgICAgICAgIHZhciBvZmZzZXQgPSAwOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ0NvdW50IC0gMTsgKytpKSB7CiAgICAgICAgICAgICAgZnVuY3Rpb25Cb2R5ICs9ICIgICAgdmFyIGFyZyIgKyBpICsgIiA9IGFyZ1R5cGUiICsgaSArICIucmVhZFZhbHVlRnJvbVBvaW50ZXIoYXJncyIgKyAob2Zmc2V0ID8gIisiICsgb2Zmc2V0IDogIiIpICsgIik7XG4iOwogICAgICAgICAgICAgIG9mZnNldCArPSB0eXBlc1tpICsgMV1bImFyZ1BhY2tBZHZhbmNlIl07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZnVuY3Rpb25Cb2R5ICs9ICIgICAgdmFyIHJ2ID0gaGFuZGxlW25hbWVdKCIgKyBhcmdzTGlzdCArICIpO1xuIjsKICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdDb3VudCAtIDE7ICsraSkgewogICAgICAgICAgICAgIGlmICh0eXBlc1tpICsgMV1bImRlbGV0ZU9iamVjdCJdKSB7CiAgICAgICAgICAgICAgICBmdW5jdGlvbkJvZHkgKz0gIiAgICBhcmdUeXBlIiArIGkgKyAiLmRlbGV0ZU9iamVjdChhcmciICsgaSArICIpO1xuIjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCFyZXRUeXBlLmlzVm9pZCkgewogICAgICAgICAgICAgIGZ1bmN0aW9uQm9keSArPSAiICAgIHJldHVybiByZXRUeXBlLnRvV2lyZVR5cGUoZGVzdHJ1Y3RvcnMsIHJ2KTtcbiI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZnVuY3Rpb25Cb2R5ICs9ICJ9O1xuIjsKICAgICAgICAgICAgcGFyYW1zLnB1c2goZnVuY3Rpb25Cb2R5KTsKICAgICAgICAgICAgdmFyIGludm9rZXJGdW5jdGlvbiA9IG5ld18oRnVuY3Rpb24sIHBhcmFtcykuYXBwbHkobnVsbCwgYXJncyk7CiAgICAgICAgICAgIHJldHVybiBfX2VtdmFsX2FkZE1ldGhvZENhbGxlcihpbnZva2VyRnVuY3Rpb24pOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbXZhbF9nZXRfbW9kdWxlX3Byb3BlcnR5KG5hbWUpIHsKICAgICAgICAgICAgbmFtZSA9IGdldFN0cmluZ09yU3ltYm9sKG5hbWUpOwogICAgICAgICAgICByZXR1cm4gX19lbXZhbF9yZWdpc3RlcihNb2R1bGVbbmFtZV0pOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbXZhbF9nZXRfcHJvcGVydHkoaGFuZGxlLCBrZXkyKSB7CiAgICAgICAgICAgIGhhbmRsZSA9IHJlcXVpcmVIYW5kbGUoaGFuZGxlKTsKICAgICAgICAgICAga2V5MiA9IHJlcXVpcmVIYW5kbGUoa2V5Mik7CiAgICAgICAgICAgIHJldHVybiBfX2VtdmFsX3JlZ2lzdGVyKGhhbmRsZVtrZXkyXSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfX2VtdmFsX2luY3JlZihoYW5kbGUpIHsKICAgICAgICAgICAgaWYgKGhhbmRsZSA+IDQpIHsKICAgICAgICAgICAgICBlbXZhbF9oYW5kbGVfYXJyYXlbaGFuZGxlXS5yZWZjb3VudCArPSAxOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBjcmFmdEVtdmFsQWxsb2NhdG9yKGFyZ0NvdW50KSB7CiAgICAgICAgICAgIHZhciBhcmdzTGlzdCA9ICIiOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ0NvdW50OyArK2kpIHsKICAgICAgICAgICAgICBhcmdzTGlzdCArPSAoaSAhPT0gMCA/ICIsICIgOiAiIikgKyAiYXJnIiArIGk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGZ1bmN0aW9uQm9keSA9ICJyZXR1cm4gZnVuY3Rpb24gZW12YWxfYWxsb2NhdG9yXyIgKyBhcmdDb3VudCArICIoY29uc3RydWN0b3IsIGFyZ1R5cGVzLCBhcmdzKSB7XG4iOwogICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ0NvdW50OyArK2kpIHsKICAgICAgICAgICAgICBmdW5jdGlvbkJvZHkgKz0gInZhciBhcmdUeXBlIiArIGkgKyAiID0gcmVxdWlyZVJlZ2lzdGVyZWRUeXBlKE1vZHVsZVsnSEVBUDMyJ11bKGFyZ1R5cGVzID4+PiAyKSArICIgKyBpICsgJ10sICJwYXJhbWV0ZXIgJyArIGkgKyAnIik7XG52YXIgYXJnJyArIGkgKyAiID0gYXJnVHlwZSIgKyBpICsgIi5yZWFkVmFsdWVGcm9tUG9pbnRlcihhcmdzKTtcbmFyZ3MgKz0gYXJnVHlwZSIgKyBpICsgIlsnYXJnUGFja0FkdmFuY2UnXTtcbiI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZnVuY3Rpb25Cb2R5ICs9ICJ2YXIgb2JqID0gbmV3IGNvbnN0cnVjdG9yKCIgKyBhcmdzTGlzdCArICIpO1xucmV0dXJuIF9fZW12YWxfcmVnaXN0ZXIob2JqKTtcbn1cbiI7CiAgICAgICAgICAgIHJldHVybiBuZXcgRnVuY3Rpb24oInJlcXVpcmVSZWdpc3RlcmVkVHlwZSIsICJNb2R1bGUiLCAiX19lbXZhbF9yZWdpc3RlciIsIGZ1bmN0aW9uQm9keSkocmVxdWlyZVJlZ2lzdGVyZWRUeXBlLCBNb2R1bGUsIF9fZW12YWxfcmVnaXN0ZXIpOwogICAgICAgICAgfQogICAgICAgICAgdmFyIGVtdmFsX25ld2VycyA9IHt9OwogICAgICAgICAgZnVuY3Rpb24gX19lbXZhbF9uZXcoaGFuZGxlLCBhcmdDb3VudCwgYXJnVHlwZXMsIGFyZ3MpIHsKICAgICAgICAgICAgaGFuZGxlID0gcmVxdWlyZUhhbmRsZShoYW5kbGUpOwogICAgICAgICAgICB2YXIgbmV3ZXIgPSBlbXZhbF9uZXdlcnNbYXJnQ291bnRdOwogICAgICAgICAgICBpZiAoIW5ld2VyKSB7CiAgICAgICAgICAgICAgbmV3ZXIgPSBjcmFmdEVtdmFsQWxsb2NhdG9yKGFyZ0NvdW50KTsKICAgICAgICAgICAgICBlbXZhbF9uZXdlcnNbYXJnQ291bnRdID0gbmV3ZXI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIG5ld2VyKGhhbmRsZSwgYXJnVHlwZXMsIGFyZ3MpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbXZhbF9uZXdfY3N0cmluZyh2MykgewogICAgICAgICAgICByZXR1cm4gX19lbXZhbF9yZWdpc3RlcihnZXRTdHJpbmdPclN5bWJvbCh2MykpOwogICAgICAgICAgfQogICAgICAgICAgZnVuY3Rpb24gX19lbXZhbF9ydW5fZGVzdHJ1Y3RvcnMoaGFuZGxlKSB7CiAgICAgICAgICAgIHZhciBkZXN0cnVjdG9ycyA9IGVtdmFsX2hhbmRsZV9hcnJheVtoYW5kbGVdLnZhbHVlOwogICAgICAgICAgICBydW5EZXN0cnVjdG9ycyhkZXN0cnVjdG9ycyk7CiAgICAgICAgICAgIF9fZW12YWxfZGVjcmVmKGhhbmRsZSk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfYWJvcnQoKSB7CiAgICAgICAgICAgIGFib3J0KCk7CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfZW1zY3JpcHRlbl9tZW1jcHlfYmlnKGRlc3QsIHNyYywgbnVtKSB7CiAgICAgICAgICAgIEhFQVBVOC5jb3B5V2l0aGluKGRlc3QsIHNyYywgc3JjICsgbnVtKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGVtc2NyaXB0ZW5fcmVhbGxvY19idWZmZXIoc2l6ZSkgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIHdhc21NZW1vcnkuZ3JvdyhzaXplIC0gYnVmZmVyLmJ5dGVMZW5ndGggKyA2NTUzNSA+Pj4gMTYpOwogICAgICAgICAgICAgIHVwZGF0ZUdsb2JhbEJ1ZmZlckFuZFZpZXdzKHdhc21NZW1vcnkuYnVmZmVyKTsKICAgICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmdW5jdGlvbiBfZW1zY3JpcHRlbl9yZXNpemVfaGVhcChyZXF1ZXN0ZWRTaXplKSB7CiAgICAgICAgICAgIHZhciBvbGRTaXplID0gSEVBUFU4Lmxlbmd0aDsKICAgICAgICAgICAgcmVxdWVzdGVkU2l6ZSA9IHJlcXVlc3RlZFNpemUgPj4+IDA7CiAgICAgICAgICAgIHZhciBtYXhIZWFwU2l6ZSA9IDIxNDc0ODM2NDg7CiAgICAgICAgICAgIGlmIChyZXF1ZXN0ZWRTaXplID4gbWF4SGVhcFNpemUpIHsKICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yICh2YXIgY3V0RG93biA9IDE7IGN1dERvd24gPD0gNDsgY3V0RG93biAqPSAyKSB7CiAgICAgICAgICAgICAgdmFyIG92ZXJHcm93bkhlYXBTaXplID0gb2xkU2l6ZSAqICgxICsgMC4yIC8gY3V0RG93bik7CiAgICAgICAgICAgICAgb3Zlckdyb3duSGVhcFNpemUgPSBNYXRoLm1pbihvdmVyR3Jvd25IZWFwU2l6ZSwgcmVxdWVzdGVkU2l6ZSArIDEwMDY2MzI5Nik7CiAgICAgICAgICAgICAgdmFyIG5ld1NpemUgPSBNYXRoLm1pbihtYXhIZWFwU2l6ZSwgYWxpZ25VcChNYXRoLm1heChyZXF1ZXN0ZWRTaXplLCBvdmVyR3Jvd25IZWFwU2l6ZSksIDY1NTM2KSk7CiAgICAgICAgICAgICAgdmFyIHJlcGxhY2VtZW50ID0gZW1zY3JpcHRlbl9yZWFsbG9jX2J1ZmZlcihuZXdTaXplKTsKICAgICAgICAgICAgICBpZiAocmVwbGFjZW1lbnQpIHsKICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgU1lTQ0FMTFMgPSB7IG1hcHBpbmdzOiB7fSwgYnVmZmVyczogW251bGwsIFtdLCBbXV0sIHByaW50Q2hhcjogZnVuY3Rpb24oc3RyZWFtLCBjdXJyKSB7CiAgICAgICAgICAgIHZhciBidWZmZXIyID0gU1lTQ0FMTFMuYnVmZmVyc1tzdHJlYW1dOwogICAgICAgICAgICBpZiAoY3VyciA9PT0gMCB8fCBjdXJyID09PSAxMCkgewogICAgICAgICAgICAgIChzdHJlYW0gPT09IDEgPyBvdXQgOiBlcnIpKFVURjhBcnJheVRvU3RyaW5nKGJ1ZmZlcjIsIDApKTsKICAgICAgICAgICAgICBidWZmZXIyLmxlbmd0aCA9IDA7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgYnVmZmVyMi5wdXNoKGN1cnIpOwogICAgICAgICAgICB9CiAgICAgICAgICB9LCB2YXJhcmdzOiB2b2lkIDAsIGdldDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIFNZU0NBTExTLnZhcmFyZ3MgKz0gNDsKICAgICAgICAgICAgdmFyIHJldCA9IEhFQVAzMltTWVNDQUxMUy52YXJhcmdzIC0gNCA+PiAyXTsKICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgIH0sIGdldFN0cjogZnVuY3Rpb24ocHRyKSB7CiAgICAgICAgICAgIHZhciByZXQgPSBVVEY4VG9TdHJpbmcocHRyKTsKICAgICAgICAgICAgcmV0dXJuIHJldDsKICAgICAgICAgIH0sIGdldDY0OiBmdW5jdGlvbihsb3csIGhpZ2gpIHsKICAgICAgICAgICAgcmV0dXJuIGxvdzsKICAgICAgICAgIH0gfTsKICAgICAgICAgIGZ1bmN0aW9uIF9mZF9jbG9zZShmZCkgewogICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIF9mZF9zZWVrKGZkLCBvZmZzZXRfbG93LCBvZmZzZXRfaGlnaCwgd2hlbmNlLCBuZXdPZmZzZXQpIHsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIF9mZF93cml0ZShmZCwgaW92LCBpb3ZjbnQsIHBudW0pIHsKICAgICAgICAgICAgdmFyIG51bSA9IDA7CiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW92Y250OyBpKyspIHsKICAgICAgICAgICAgICB2YXIgcHRyID0gSEVBUDMyW2lvdiArIGkgKiA4ID4+IDJdOwogICAgICAgICAgICAgIHZhciBsZW4gPSBIRUFQMzJbaW92ICsgKGkgKiA4ICsgNCkgPj4gMl07CiAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBsZW47IGorKykgewogICAgICAgICAgICAgICAgU1lTQ0FMTFMucHJpbnRDaGFyKGZkLCBIRUFQVThbcHRyICsgal0pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBudW0gKz0gbGVuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIEhFQVAzMltwbnVtID4+IDJdID0gbnVtOwogICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIF9zZXRUZW1wUmV0MCgkaSkgewogICAgICAgICAgICBzZXRUZW1wUmV0MCgkaSB8IDApOwogICAgICAgICAgfQogICAgICAgICAgSW50ZXJuYWxFcnJvciA9IE1vZHVsZVsiSW50ZXJuYWxFcnJvciJdID0gZXh0ZW5kRXJyb3IoRXJyb3IsICJJbnRlcm5hbEVycm9yIik7CiAgICAgICAgICBlbWJpbmRfaW5pdF9jaGFyQ29kZXMoKTsKICAgICAgICAgIEJpbmRpbmdFcnJvciA9IE1vZHVsZVsiQmluZGluZ0Vycm9yIl0gPSBleHRlbmRFcnJvcihFcnJvciwgIkJpbmRpbmdFcnJvciIpOwogICAgICAgICAgaW5pdF9DbGFzc0hhbmRsZSgpOwogICAgICAgICAgaW5pdF9SZWdpc3RlcmVkUG9pbnRlcigpOwogICAgICAgICAgaW5pdF9lbWJpbmQoKTsKICAgICAgICAgIFVuYm91bmRUeXBlRXJyb3IgPSBNb2R1bGVbIlVuYm91bmRUeXBlRXJyb3IiXSA9IGV4dGVuZEVycm9yKEVycm9yLCAiVW5ib3VuZFR5cGVFcnJvciIpOwogICAgICAgICAgaW5pdF9lbXZhbCgpOwogICAgICAgICAgdmFyIGFzbUxpYnJhcnlBcmcgPSB7ICJ0IjogX19lbWJpbmRfZmluYWxpemVfdmFsdWVfb2JqZWN0LCAiSSI6IF9fZW1iaW5kX3JlZ2lzdGVyX2Jvb2wsICJ4IjogX19lbWJpbmRfcmVnaXN0ZXJfY2xhc3MsICJ3IjogX19lbWJpbmRfcmVnaXN0ZXJfY2xhc3NfY29uc3RydWN0b3IsICJkIjogX19lbWJpbmRfcmVnaXN0ZXJfY2xhc3NfZnVuY3Rpb24sICJrIjogX19lbWJpbmRfcmVnaXN0ZXJfY29uc3RhbnQsICJIIjogX19lbWJpbmRfcmVnaXN0ZXJfZW12YWwsICJuIjogX19lbWJpbmRfcmVnaXN0ZXJfZW51bSwgImEiOiBfX2VtYmluZF9yZWdpc3Rlcl9lbnVtX3ZhbHVlLCAiQSI6IF9fZW1iaW5kX3JlZ2lzdGVyX2Zsb2F0LCAiaSI6IF9fZW1iaW5kX3JlZ2lzdGVyX2Z1bmN0aW9uLCAiaiI6IF9fZW1iaW5kX3JlZ2lzdGVyX2ludGVnZXIsICJoIjogX19lbWJpbmRfcmVnaXN0ZXJfbWVtb3J5X3ZpZXcsICJCIjogX19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZywgInYiOiBfX2VtYmluZF9yZWdpc3Rlcl9zdGRfd3N0cmluZywgInUiOiBfX2VtYmluZF9yZWdpc3Rlcl92YWx1ZV9vYmplY3QsICJjIjogX19lbWJpbmRfcmVnaXN0ZXJfdmFsdWVfb2JqZWN0X2ZpZWxkLCAiSiI6IF9fZW1iaW5kX3JlZ2lzdGVyX3ZvaWQsICJtIjogX19lbXZhbF9hcywgInMiOiBfX2VtdmFsX2NhbGxfdm9pZF9tZXRob2QsICJiIjogX19lbXZhbF9kZWNyZWYsICJ5IjogX19lbXZhbF9nZXRfZ2xvYmFsLCAicCI6IF9fZW12YWxfZ2V0X21ldGhvZF9jYWxsZXIsICJyIjogX19lbXZhbF9nZXRfbW9kdWxlX3Byb3BlcnR5LCAiZSI6IF9fZW12YWxfZ2V0X3Byb3BlcnR5LCAiZyI6IF9fZW12YWxfaW5jcmVmLCAicSI6IF9fZW12YWxfbmV3LCAiZiI6IF9fZW12YWxfbmV3X2NzdHJpbmcsICJsIjogX19lbXZhbF9ydW5fZGVzdHJ1Y3RvcnMsICJvIjogX2Fib3J0LCAiRSI6IF9lbXNjcmlwdGVuX21lbWNweV9iaWcsICJGIjogX2Vtc2NyaXB0ZW5fcmVzaXplX2hlYXAsICJHIjogX2ZkX2Nsb3NlLCAiQyI6IF9mZF9zZWVrLCAieiI6IF9mZF93cml0ZSwgIkQiOiBfc2V0VGVtcFJldDAgfTsKICAgICAgICAgIHZhciBhc20gPSBjcmVhdGVXYXNtKCk7CiAgICAgICAgICB2YXIgX19fd2FzbV9jYWxsX2N0b3JzID0gTW9kdWxlWyJfX193YXNtX2NhbGxfY3RvcnMiXSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKF9fX3dhc21fY2FsbF9jdG9ycyA9IE1vZHVsZVsiX19fd2FzbV9jYWxsX2N0b3JzIl0gPSBNb2R1bGVbImFzbSJdWyJMIl0pLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICB9OwogICAgICAgICAgdmFyIF9tYWxsb2MgPSBNb2R1bGVbIl9tYWxsb2MiXSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICByZXR1cm4gKF9tYWxsb2MgPSBNb2R1bGVbIl9tYWxsb2MiXSA9IE1vZHVsZVsiYXNtIl1bIk0iXSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH07CiAgICAgICAgICB2YXIgX2ZyZWUgPSBNb2R1bGVbIl9mcmVlIl0gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChfZnJlZSA9IE1vZHVsZVsiX2ZyZWUiXSA9IE1vZHVsZVsiYXNtIl1bIk4iXSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH07CiAgICAgICAgICB2YXIgX19fZ2V0VHlwZU5hbWUgPSBNb2R1bGVbIl9fX2dldFR5cGVOYW1lIl0gPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgcmV0dXJuIChfX19nZXRUeXBlTmFtZSA9IE1vZHVsZVsiX19fZ2V0VHlwZU5hbWUiXSA9IE1vZHVsZVsiYXNtIl1bIlAiXSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH07CiAgICAgICAgICB2YXIgX19fZW1iaW5kX3JlZ2lzdGVyX25hdGl2ZV9hbmRfYnVpbHRpbl90eXBlcyA9IE1vZHVsZVsiX19fZW1iaW5kX3JlZ2lzdGVyX25hdGl2ZV9hbmRfYnVpbHRpbl90eXBlcyJdID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoX19fZW1iaW5kX3JlZ2lzdGVyX25hdGl2ZV9hbmRfYnVpbHRpbl90eXBlcyA9IE1vZHVsZVsiX19fZW1iaW5kX3JlZ2lzdGVyX25hdGl2ZV9hbmRfYnVpbHRpbl90eXBlcyJdID0gTW9kdWxlWyJhc20iXVsiUSJdKS5hcHBseShudWxsLCBhcmd1bWVudHMpOwogICAgICAgICAgfTsKICAgICAgICAgIHZhciBkeW5DYWxsX2ppamkgPSBNb2R1bGVbImR5bkNhbGxfamlqaSJdID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHJldHVybiAoZHluQ2FsbF9qaWppID0gTW9kdWxlWyJkeW5DYWxsX2ppamkiXSA9IE1vZHVsZVsiYXNtIl1bIlIiXSkuYXBwbHkobnVsbCwgYXJndW1lbnRzKTsKICAgICAgICAgIH07CiAgICAgICAgICB2YXIgY2FsbGVkUnVuOwogICAgICAgICAgZnVuY3Rpb24gRXhpdFN0YXR1cyhzdGF0dXMpIHsKICAgICAgICAgICAgdGhpcy5uYW1lID0gIkV4aXRTdGF0dXMiOwogICAgICAgICAgICB0aGlzLm1lc3NhZ2UgPSAiUHJvZ3JhbSB0ZXJtaW5hdGVkIHdpdGggZXhpdCgiICsgc3RhdHVzICsgIikiOwogICAgICAgICAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgICAgICAgIH0KICAgICAgICAgIGRlcGVuZGVuY2llc0Z1bGZpbGxlZCA9IGZ1bmN0aW9uIHJ1bkNhbGxlcigpIHsKICAgICAgICAgICAgaWYgKCFjYWxsZWRSdW4pIHJ1bigpOwogICAgICAgICAgICBpZiAoIWNhbGxlZFJ1bikgZGVwZW5kZW5jaWVzRnVsZmlsbGVkID0gcnVuQ2FsbGVyOwogICAgICAgICAgfTsKICAgICAgICAgIGZ1bmN0aW9uIHJ1bihhcmdzKSB7CiAgICAgICAgICAgIGFyZ3MgPSBhcmdzIHx8IGFyZ3VtZW50c187CiAgICAgICAgICAgIGlmIChydW5EZXBlbmRlbmNpZXMgPiAwKSB7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHByZVJ1bigpOwogICAgICAgICAgICBpZiAocnVuRGVwZW5kZW5jaWVzID4gMCkgewogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBmdW5jdGlvbiBkb1J1bigpIHsKICAgICAgICAgICAgICBpZiAoY2FsbGVkUnVuKSByZXR1cm47CiAgICAgICAgICAgICAgY2FsbGVkUnVuID0gdHJ1ZTsKICAgICAgICAgICAgICBNb2R1bGVbImNhbGxlZFJ1biJdID0gdHJ1ZTsKICAgICAgICAgICAgICBpZiAoQUJPUlQpIHJldHVybjsKICAgICAgICAgICAgICBpbml0UnVudGltZSgpOwogICAgICAgICAgICAgIHByZU1haW4oKTsKICAgICAgICAgICAgICByZWFkeVByb21pc2VSZXNvbHZlKE1vZHVsZSk7CiAgICAgICAgICAgICAgaWYgKE1vZHVsZVsib25SdW50aW1lSW5pdGlhbGl6ZWQiXSkgTW9kdWxlWyJvblJ1bnRpbWVJbml0aWFsaXplZCJdKCk7CiAgICAgICAgICAgICAgcG9zdFJ1bigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChNb2R1bGVbInNldFN0YXR1cyJdKSB7CiAgICAgICAgICAgICAgTW9kdWxlWyJzZXRTdGF0dXMiXSgiUnVubmluZy4uLiIpOwogICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgICBNb2R1bGVbInNldFN0YXR1cyJdKCIiKTsKICAgICAgICAgICAgICAgIH0sIDEpOwogICAgICAgICAgICAgICAgZG9SdW4oKTsKICAgICAgICAgICAgICB9LCAxKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBkb1J1bigpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBNb2R1bGVbInJ1biJdID0gcnVuOwogICAgICAgICAgaWYgKE1vZHVsZVsicHJlSW5pdCJdKSB7CiAgICAgICAgICAgIGlmICh0eXBlb2YgTW9kdWxlWyJwcmVJbml0Il0gPT0gImZ1bmN0aW9uIikgTW9kdWxlWyJwcmVJbml0Il0gPSBbTW9kdWxlWyJwcmVJbml0Il1dOwogICAgICAgICAgICB3aGlsZSAoTW9kdWxlWyJwcmVJbml0Il0ubGVuZ3RoID4gMCkgewogICAgICAgICAgICAgIE1vZHVsZVsicHJlSW5pdCJdLnBvcCgpKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHJ1bigpOwogICAgICAgICAgcmV0dXJuIEJBU0lTMi5yZWFkeTsKICAgICAgICB9KTsKICAgICAgfSkoKTsKICAgICAgaWYgKHR5cGVvZiBleHBvcnRzMiA9PT0gIm9iamVjdCIgJiYgdHlwZW9mIG1vZHVsZSA9PT0gIm9iamVjdCIpCiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBCQVNJUzsKICAgICAgZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gImZ1bmN0aW9uIiAmJiBkZWZpbmVbImFtZCJdKQogICAgICAgIGRlZmluZShbXSwgZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gQkFTSVM7CiAgICAgICAgfSk7CiAgICAgIGVsc2UgaWYgKHR5cGVvZiBleHBvcnRzMiA9PT0gIm9iamVjdCIpCiAgICAgICAgZXhwb3J0czJbIkJBU0lTIl0gPSBCQVNJUzsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL3RyYW5zY29kZUtUWDIuanMKICB2YXIgdHJhbnNjb2RlS1RYMl9leHBvcnRzID0ge307CiAgX19leHBvcnQodHJhbnNjb2RlS1RYMl9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiB0cmFuc2NvZGVLVFgyX2RlZmF1bHQKICB9KTsKICBmdW5jdGlvbiB0cmFuc2NvZGUocGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cykgewogICAgQ2hlY2tfZGVmYXVsdC50eXBlT2Yub2JqZWN0KCJ0cmFuc2NvZGVyTW9kdWxlIiwgdHJhbnNjb2Rlck1vZHVsZSk7CiAgICBjb25zdCBkYXRhID0gcGFyYW1ldGVycy5rdHgyQnVmZmVyOwogICAgY29uc3Qgc3VwcG9ydGVkVGFyZ2V0Rm9ybWF0cyA9IHBhcmFtZXRlcnMuc3VwcG9ydGVkVGFyZ2V0Rm9ybWF0czsKICAgIGxldCBoZWFkZXI7CiAgICB0cnkgewogICAgICBoZWFkZXIgPSByZWFkMihkYXRhKTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KCJJbnZhbGlkIEtUWDIgZmlsZS4iKTsKICAgIH0KICAgIGlmIChoZWFkZXIubGF5ZXJDb3VudCAhPT0gMCkgewogICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yX2RlZmF1bHQoIktUWDIgdGV4dHVyZSBhcnJheXMgYXJlIG5vdCBzdXBwb3J0ZWQuIik7CiAgICB9CiAgICBpZiAoaGVhZGVyLnBpeGVsRGVwdGggIT09IDApIHsKICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KCJLVFgyIDNEIHRleHR1cmVzIGFyZSB1bnN1cHBvcnRlZC4iKTsKICAgIH0KICAgIGNvbnN0IGRmZCA9IGhlYWRlci5kYXRhRm9ybWF0RGVzY3JpcHRvclswXTsKICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBBcnJheShoZWFkZXIubGV2ZWxDb3VudCk7CiAgICBpZiAoaGVhZGVyLnZrRm9ybWF0ID09PSAwICYmIChkZmQuY29sb3JNb2RlbCA9PT0gY29sb3JNb2RlbEVUQzFTIHx8IGRmZC5jb2xvck1vZGVsID09PSBjb2xvck1vZGVsVUFTVEMpKSB7CiAgICAgIHRyYW5zY29kZUNvbXByZXNzZWQoCiAgICAgICAgZGF0YSwKICAgICAgICBoZWFkZXIsCiAgICAgICAgc3VwcG9ydGVkVGFyZ2V0Rm9ybWF0cywKICAgICAgICB0cmFuc2NvZGVyTW9kdWxlLAogICAgICAgIHRyYW5zZmVyYWJsZU9iamVjdHMsCiAgICAgICAgcmVzdWx0CiAgICAgICk7CiAgICB9IGVsc2UgewogICAgICB0cmFuc2ZlcmFibGVPYmplY3RzLnB1c2goZGF0YS5idWZmZXIpOwogICAgICBwYXJzZVVuY29tcHJlc3NlZChoZWFkZXIsIHJlc3VsdCk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICBmdW5jdGlvbiBwYXJzZVVuY29tcHJlc3NlZChoZWFkZXIsIHJlc3VsdCkgewogICAgY29uc3QgaW50ZXJuYWxGb3JtYXQgPSBoZWFkZXIudmtGb3JtYXQgPT09IFZ1bGthbkNvbnN0YW50c19kZWZhdWx0LlZLX0ZPUk1BVF9SOEc4QjhfU1JHQiA/IFBpeGVsRm9ybWF0X2RlZmF1bHQuUkdCIDogUGl4ZWxGb3JtYXRfZGVmYXVsdC5SR0JBOwogICAgbGV0IGRhdGF0eXBlOwogICAgaWYgKGhlYWRlci52a0Zvcm1hdCA9PT0gVnVsa2FuQ29uc3RhbnRzX2RlZmF1bHQuVktfRk9STUFUX1I4RzhCOEE4X1VOT1JNKSB7CiAgICAgIGRhdGF0eXBlID0gUGl4ZWxEYXRhdHlwZV9kZWZhdWx0LlVOU0lHTkVEX0JZVEU7CiAgICB9IGVsc2UgaWYgKGhlYWRlci52a0Zvcm1hdCA9PT0gVnVsa2FuQ29uc3RhbnRzX2RlZmF1bHQuVktfRk9STUFUX1IxNkcxNkIxNkExNl9TRkxPQVQpIHsKICAgICAgZGF0YXR5cGUgPSBQaXhlbERhdGF0eXBlX2RlZmF1bHQuSEFMRl9GTE9BVDsKICAgIH0gZWxzZSBpZiAoaGVhZGVyLnZrRm9ybWF0ID09PSBWdWxrYW5Db25zdGFudHNfZGVmYXVsdC5WS19GT1JNQVRfUjMyRzMyQjMyQTMyX1NGTE9BVCkgewogICAgICBkYXRhdHlwZSA9IFBpeGVsRGF0YXR5cGVfZGVmYXVsdC5GTE9BVDsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaGVhZGVyLmxldmVscy5sZW5ndGg7ICsraSkgewogICAgICBjb25zdCBsZXZlbCA9IHt9OwogICAgICByZXN1bHRbaV0gPSBsZXZlbDsKICAgICAgY29uc3QgbGV2ZWxCdWZmZXIgPSBoZWFkZXIubGV2ZWxzW2ldLmxldmVsRGF0YTsKICAgICAgY29uc3Qgd2lkdGggPSBoZWFkZXIucGl4ZWxXaWR0aCA+PiBpOwogICAgICBjb25zdCBoZWlnaHQgPSBoZWFkZXIucGl4ZWxIZWlnaHQgPj4gaTsKICAgICAgY29uc3QgZmFjZUxlbmd0aCA9IHdpZHRoICogaGVpZ2h0ICogUGl4ZWxGb3JtYXRfZGVmYXVsdC5jb21wb25lbnRzTGVuZ3RoKGludGVybmFsRm9ybWF0KTsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBoZWFkZXIuZmFjZUNvdW50OyArK2opIHsKICAgICAgICBjb25zdCBmYWNlQnl0ZU9mZnNldCA9IGxldmVsQnVmZmVyLmJ5dGVPZmZzZXQgKyBmYWNlTGVuZ3RoICogaGVhZGVyLnR5cGVTaXplICogajsKICAgICAgICBsZXQgZmFjZVZpZXc7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoZGF0YXR5cGUpIHx8IFBpeGVsRGF0YXR5cGVfZGVmYXVsdC5zaXplSW5CeXRlcyhkYXRhdHlwZSkgPT09IDEpIHsKICAgICAgICAgIGZhY2VWaWV3ID0gbmV3IFVpbnQ4QXJyYXkoCiAgICAgICAgICAgIGxldmVsQnVmZmVyLmJ1ZmZlciwKICAgICAgICAgICAgZmFjZUJ5dGVPZmZzZXQsCiAgICAgICAgICAgIGZhY2VMZW5ndGgKICAgICAgICAgICk7CiAgICAgICAgfSBlbHNlIGlmIChQaXhlbERhdGF0eXBlX2RlZmF1bHQuc2l6ZUluQnl0ZXMoZGF0YXR5cGUpID09PSAyKSB7CiAgICAgICAgICBmYWNlVmlldyA9IG5ldyBVaW50MTZBcnJheSgKICAgICAgICAgICAgbGV2ZWxCdWZmZXIuYnVmZmVyLAogICAgICAgICAgICBmYWNlQnl0ZU9mZnNldCwKICAgICAgICAgICAgZmFjZUxlbmd0aAogICAgICAgICAgKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZmFjZVZpZXcgPSBuZXcgRmxvYXQzMkFycmF5KAogICAgICAgICAgICBsZXZlbEJ1ZmZlci5idWZmZXIsCiAgICAgICAgICAgIGZhY2VCeXRlT2Zmc2V0LAogICAgICAgICAgICBmYWNlTGVuZ3RoCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICBsZXZlbFtmYWNlT3JkZXJbal1dID0gewogICAgICAgICAgaW50ZXJuYWxGb3JtYXQsCiAgICAgICAgICBkYXRhdHlwZSwKICAgICAgICAgIHdpZHRoLAogICAgICAgICAgaGVpZ2h0LAogICAgICAgICAgbGV2ZWxCdWZmZXI6IGZhY2VWaWV3CiAgICAgICAgfTsKICAgICAgfQogICAgfQogIH0KICBmdW5jdGlvbiB0cmFuc2NvZGVDb21wcmVzc2VkKGRhdGEsIGhlYWRlciwgc3VwcG9ydGVkVGFyZ2V0Rm9ybWF0cywgdHJhbnNjb2Rlck1vZHVsZTIsIHRyYW5zZmVyYWJsZU9iamVjdHMsIHJlc3VsdCkgewogICAgY29uc3Qga3R4MkZpbGUgPSBuZXcgdHJhbnNjb2Rlck1vZHVsZTIuS1RYMkZpbGUoZGF0YSk7CiAgICBsZXQgd2lkdGggPSBrdHgyRmlsZS5nZXRXaWR0aCgpOwogICAgbGV0IGhlaWdodCA9IGt0eDJGaWxlLmdldEhlaWdodCgpOwogICAgY29uc3QgbGV2ZWxzID0ga3R4MkZpbGUuZ2V0TGV2ZWxzKCk7CiAgICBjb25zdCBoYXNBbHBoYSA9IGt0eDJGaWxlLmdldEhhc0FscGhhKCk7CiAgICBpZiAoISh3aWR0aCA+IDApIHx8ICEoaGVpZ2h0ID4gMCkgfHwgIShsZXZlbHMgPiAwKSkgewogICAgICBrdHgyRmlsZS5jbG9zZSgpOwogICAgICBrdHgyRmlsZS5kZWxldGUoKTsKICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KCJJbnZhbGlkIEtUWDIgZmlsZSIpOwogICAgfQogICAgbGV0IGludGVybmFsRm9ybWF0LCB0cmFuc2NvZGVyRm9ybWF0OwogICAgY29uc3QgZGZkID0gaGVhZGVyLmRhdGFGb3JtYXREZXNjcmlwdG9yWzBdOwogICAgY29uc3QgQmFzaXNGb3JtYXQgPSB0cmFuc2NvZGVyTW9kdWxlMi50cmFuc2NvZGVyX3RleHR1cmVfZm9ybWF0OwogICAgaWYgKGRmZC5jb2xvck1vZGVsID09PSBjb2xvck1vZGVsRVRDMVMpIHsKICAgICAgaWYgKHN1cHBvcnRlZFRhcmdldEZvcm1hdHMuZXRjKSB7CiAgICAgICAgaW50ZXJuYWxGb3JtYXQgPSBoYXNBbHBoYSA/IFBpeGVsRm9ybWF0X2RlZmF1bHQuUkdCQThfRVRDMl9FQUMgOiBQaXhlbEZvcm1hdF9kZWZhdWx0LlJHQjhfRVRDMjsKICAgICAgICB0cmFuc2NvZGVyRm9ybWF0ID0gaGFzQWxwaGEgPyBCYXNpc0Zvcm1hdC5jVEZFVEMyX1JHQkEgOiBCYXNpc0Zvcm1hdC5jVEZFVEMxX1JHQjsKICAgICAgfSBlbHNlIGlmIChzdXBwb3J0ZWRUYXJnZXRGb3JtYXRzLmV0YzEgJiYgIWhhc0FscGhhKSB7CiAgICAgICAgaW50ZXJuYWxGb3JtYXQgPSBQaXhlbEZvcm1hdF9kZWZhdWx0LlJHQl9FVEMxOwogICAgICAgIHRyYW5zY29kZXJGb3JtYXQgPSBCYXNpc0Zvcm1hdC5jVEZFVEMxX1JHQjsKICAgICAgfSBlbHNlIGlmIChzdXBwb3J0ZWRUYXJnZXRGb3JtYXRzLnMzdGMpIHsKICAgICAgICBpbnRlcm5hbEZvcm1hdCA9IGhhc0FscGhhID8gUGl4ZWxGb3JtYXRfZGVmYXVsdC5SR0JBX0RYVDUgOiBQaXhlbEZvcm1hdF9kZWZhdWx0LlJHQl9EWFQxOwogICAgICAgIHRyYW5zY29kZXJGb3JtYXQgPSBoYXNBbHBoYSA/IEJhc2lzRm9ybWF0LmNURkJDM19SR0JBIDogQmFzaXNGb3JtYXQuY1RGQkMxX1JHQjsKICAgICAgfSBlbHNlIGlmIChzdXBwb3J0ZWRUYXJnZXRGb3JtYXRzLnB2cnRjKSB7CiAgICAgICAgaW50ZXJuYWxGb3JtYXQgPSBoYXNBbHBoYSA/IFBpeGVsRm9ybWF0X2RlZmF1bHQuUkdCQV9QVlJUQ180QlBQVjEgOiBQaXhlbEZvcm1hdF9kZWZhdWx0LlJHQl9QVlJUQ180QlBQVjE7CiAgICAgICAgdHJhbnNjb2RlckZvcm1hdCA9IGhhc0FscGhhID8gQmFzaXNGb3JtYXQuY1RGUFZSVEMxXzRfUkdCQSA6IEJhc2lzRm9ybWF0LmNURlBWUlRDMV80X1JHQjsKICAgICAgfSBlbHNlIGlmIChzdXBwb3J0ZWRUYXJnZXRGb3JtYXRzLmFzdGMpIHsKICAgICAgICBpbnRlcm5hbEZvcm1hdCA9IFBpeGVsRm9ybWF0X2RlZmF1bHQuUkdCQV9BU1RDOwogICAgICAgIHRyYW5zY29kZXJGb3JtYXQgPSBCYXNpc0Zvcm1hdC5jVEZBU1RDXzR4NF9SR0JBOwogICAgICB9IGVsc2UgaWYgKHN1cHBvcnRlZFRhcmdldEZvcm1hdHMuYmM3KSB7CiAgICAgICAgaW50ZXJuYWxGb3JtYXQgPSBQaXhlbEZvcm1hdF9kZWZhdWx0LlJHQkFfQkM3OwogICAgICAgIHRyYW5zY29kZXJGb3JtYXQgPSBCYXNpc0Zvcm1hdC5jVEZCQzdfUkdCQTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yX2RlZmF1bHQoCiAgICAgICAgICAiTm8gdHJhbnNjb2RpbmcgZm9ybWF0IHRhcmdldCBhdmFpbGFibGUgZm9yIEVUQzFTIGNvbXByZXNzZWQga3R4Mi4iCiAgICAgICAgKTsKICAgICAgfQogICAgfSBlbHNlIGlmIChkZmQuY29sb3JNb2RlbCA9PT0gY29sb3JNb2RlbFVBU1RDKSB7CiAgICAgIGlmIChzdXBwb3J0ZWRUYXJnZXRGb3JtYXRzLmFzdGMpIHsKICAgICAgICBpbnRlcm5hbEZvcm1hdCA9IFBpeGVsRm9ybWF0X2RlZmF1bHQuUkdCQV9BU1RDOwogICAgICAgIHRyYW5zY29kZXJGb3JtYXQgPSBCYXNpc0Zvcm1hdC5jVEZBU1RDXzR4NF9SR0JBOwogICAgICB9IGVsc2UgaWYgKHN1cHBvcnRlZFRhcmdldEZvcm1hdHMuYmM3KSB7CiAgICAgICAgaW50ZXJuYWxGb3JtYXQgPSBQaXhlbEZvcm1hdF9kZWZhdWx0LlJHQkFfQkM3OwogICAgICAgIHRyYW5zY29kZXJGb3JtYXQgPSBCYXNpc0Zvcm1hdC5jVEZCQzdfUkdCQTsKICAgICAgfSBlbHNlIGlmIChzdXBwb3J0ZWRUYXJnZXRGb3JtYXRzLnMzdGMpIHsKICAgICAgICBpbnRlcm5hbEZvcm1hdCA9IGhhc0FscGhhID8gUGl4ZWxGb3JtYXRfZGVmYXVsdC5SR0JBX0RYVDUgOiBQaXhlbEZvcm1hdF9kZWZhdWx0LlJHQl9EWFQxOwogICAgICAgIHRyYW5zY29kZXJGb3JtYXQgPSBoYXNBbHBoYSA/IEJhc2lzRm9ybWF0LmNURkJDM19SR0JBIDogQmFzaXNGb3JtYXQuY1RGQkMxX1JHQjsKICAgICAgfSBlbHNlIGlmIChzdXBwb3J0ZWRUYXJnZXRGb3JtYXRzLmV0YykgewogICAgICAgIGludGVybmFsRm9ybWF0ID0gaGFzQWxwaGEgPyBQaXhlbEZvcm1hdF9kZWZhdWx0LlJHQkE4X0VUQzJfRUFDIDogUGl4ZWxGb3JtYXRfZGVmYXVsdC5SR0I4X0VUQzI7CiAgICAgICAgdHJhbnNjb2RlckZvcm1hdCA9IGhhc0FscGhhID8gQmFzaXNGb3JtYXQuY1RGRVRDMl9SR0JBIDogQmFzaXNGb3JtYXQuY1RGRVRDMV9SR0I7CiAgICAgIH0gZWxzZSBpZiAoc3VwcG9ydGVkVGFyZ2V0Rm9ybWF0cy5ldGMxICYmICFoYXNBbHBoYSkgewogICAgICAgIGludGVybmFsRm9ybWF0ID0gUGl4ZWxGb3JtYXRfZGVmYXVsdC5SR0JfRVRDMTsKICAgICAgICB0cmFuc2NvZGVyRm9ybWF0ID0gQmFzaXNGb3JtYXQuY1RGRVRDMV9SR0I7CiAgICAgIH0gZWxzZSBpZiAoc3VwcG9ydGVkVGFyZ2V0Rm9ybWF0cy5wdnJ0YykgewogICAgICAgIGludGVybmFsRm9ybWF0ID0gaGFzQWxwaGEgPyBQaXhlbEZvcm1hdF9kZWZhdWx0LlJHQkFfUFZSVENfNEJQUFYxIDogUGl4ZWxGb3JtYXRfZGVmYXVsdC5SR0JfUFZSVENfNEJQUFYxOwogICAgICAgIHRyYW5zY29kZXJGb3JtYXQgPSBoYXNBbHBoYSA/IEJhc2lzRm9ybWF0LmNURlBWUlRDMV80X1JHQkEgOiBCYXNpc0Zvcm1hdC5jVEZQVlJUQzFfNF9SR0I7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KAogICAgICAgICAgIk5vIHRyYW5zY29kaW5nIGZvcm1hdCB0YXJnZXQgYXZhaWxhYmxlIGZvciBVQVNUQyBjb21wcmVzc2VkIGt0eDIuIgogICAgICAgICk7CiAgICAgIH0KICAgIH0KICAgIGlmICgha3R4MkZpbGUuc3RhcnRUcmFuc2NvZGluZygpKSB7CiAgICAgIGt0eDJGaWxlLmNsb3NlKCk7CiAgICAgIGt0eDJGaWxlLmRlbGV0ZSgpOwogICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yX2RlZmF1bHQoInN0YXJ0VHJhbnNjb2RpbmcoKSBmYWlsZWQiKTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaGVhZGVyLmxldmVscy5sZW5ndGg7ICsraSkgewogICAgICBjb25zdCBsZXZlbCA9IHt9OwogICAgICByZXN1bHRbaV0gPSBsZXZlbDsKICAgICAgd2lkdGggPSBoZWFkZXIucGl4ZWxXaWR0aCA+PiBpOwogICAgICBoZWlnaHQgPSBoZWFkZXIucGl4ZWxIZWlnaHQgPj4gaTsKICAgICAgY29uc3QgZHN0U2l6ZSA9IGt0eDJGaWxlLmdldEltYWdlVHJhbnNjb2RlZFNpemVJbkJ5dGVzKAogICAgICAgIGksCiAgICAgICAgLy8gbGV2ZWwgaW5kZXgKICAgICAgICAwLAogICAgICAgIC8vIGxheWVyIGluZGV4CiAgICAgICAgMCwKICAgICAgICAvLyBmYWNlIGluZGV4CiAgICAgICAgdHJhbnNjb2RlckZvcm1hdC52YWx1ZQogICAgICApOwogICAgICBjb25zdCBkc3QgPSBuZXcgVWludDhBcnJheShkc3RTaXplKTsKICAgICAgY29uc3QgdHJhbnNjb2RlZCA9IGt0eDJGaWxlLnRyYW5zY29kZUltYWdlKAogICAgICAgIGRzdCwKICAgICAgICBpLAogICAgICAgIC8vIGxldmVsIGluZGV4CiAgICAgICAgMCwKICAgICAgICAvLyBsYXllciBpbmRleAogICAgICAgIDAsCiAgICAgICAgLy8gZmFjZSBpbmRleAogICAgICAgIHRyYW5zY29kZXJGb3JtYXQudmFsdWUsCiAgICAgICAgMCwKICAgICAgICAvLyBnZXRfYWxwaGFfZm9yX29wYXF1ZV9mb3JtYXRzCiAgICAgICAgLTEsCiAgICAgICAgLy8gY2hhbm5lbDAKICAgICAgICAtMQogICAgICAgIC8vIGNoYW5uZWwxCiAgICAgICk7CiAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHRyYW5zY29kZWQpKSB7CiAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcl9kZWZhdWx0KCJ0cmFuc2NvZGVJbWFnZSgpIGZhaWxlZC4iKTsKICAgICAgfQogICAgICB0cmFuc2ZlcmFibGVPYmplY3RzLnB1c2goZHN0LmJ1ZmZlcik7CiAgICAgIGxldmVsW2ZhY2VPcmRlclswXV0gPSB7CiAgICAgICAgaW50ZXJuYWxGb3JtYXQsCiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0LAogICAgICAgIGxldmVsQnVmZmVyOiBkc3QKICAgICAgfTsKICAgIH0KICAgIGt0eDJGaWxlLmNsb3NlKCk7CiAgICBrdHgyRmlsZS5kZWxldGUoKTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGFzeW5jIGZ1bmN0aW9uIGluaXRXb3JrZXI1KHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIGNvbnN0IHdhc21Db25maWcgPSBwYXJhbWV0ZXJzLndlYkFzc2VtYmx5Q29uZmlnOwogICAgY29uc3QgYmFzaXNUcmFuc2NvZGVyID0gaW1wb3J0X2Jhc2lzX3RyYW5zY29kZXIuZGVmYXVsdCA/PyBzZWxmLkJBU0lTOwogICAgaWYgKGRlZmluZWRfZGVmYXVsdCh3YXNtQ29uZmlnLndhc21CaW5hcnlGaWxlKSkgewogICAgICB0cmFuc2NvZGVyTW9kdWxlID0gYXdhaXQgYmFzaXNUcmFuc2NvZGVyKHdhc21Db25maWcpOwogICAgfSBlbHNlIHsKICAgICAgdHJhbnNjb2Rlck1vZHVsZSA9IGF3YWl0IGJhc2lzVHJhbnNjb2RlcigpOwogICAgfQogICAgdHJhbnNjb2Rlck1vZHVsZS5pbml0aWFsaXplQmFzaXMoKTsKICAgIHJldHVybiB0cnVlOwogIH0KICBmdW5jdGlvbiB0cmFuc2NvZGVLVFgyKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpIHsKICAgIGNvbnN0IHdhc21Db25maWcgPSBwYXJhbWV0ZXJzLndlYkFzc2VtYmx5Q29uZmlnOwogICAgaWYgKGRlZmluZWRfZGVmYXVsdCh3YXNtQ29uZmlnKSkgewogICAgICByZXR1cm4gaW5pdFdvcmtlcjUocGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cyk7CiAgICB9CiAgICByZXR1cm4gdHJhbnNjb2RlKHBhcmFtZXRlcnMsIHRyYW5zZmVyYWJsZU9iamVjdHMpOwogIH0KICB2YXIgaW1wb3J0X2Jhc2lzX3RyYW5zY29kZXIsIGZhY2VPcmRlciwgY29sb3JNb2RlbEVUQzFTLCBjb2xvck1vZGVsVUFTVEMsIHRyYW5zY29kZXJNb2R1bGUsIHRyYW5zY29kZUtUWDJfZGVmYXVsdDsKICB2YXIgaW5pdF90cmFuc2NvZGVLVFgyID0gX19lc20oewogICAgInBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy90cmFuc2NvZGVLVFgyLmpzIigpIHsKICAgICAgaW5pdF9kZWZpbmVkKCk7CiAgICAgIGluaXRfQ2hlY2soKTsKICAgICAgaW5pdF9QaXhlbEZvcm1hdCgpOwogICAgICBpbml0X1J1bnRpbWVFcnJvcigpOwogICAgICBpbml0X1Z1bGthbkNvbnN0YW50cygpOwogICAgICBpbml0X1BpeGVsRGF0YXR5cGUoKTsKICAgICAgaW5pdF9jcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyKCk7CiAgICAgIGluaXRfa3R4X3BhcnNlX21vZGVybigpOwogICAgICBpbXBvcnRfYmFzaXNfdHJhbnNjb2RlciA9IF9fdG9FU00ocmVxdWlyZV9iYXNpc190cmFuc2NvZGVyKCksIDEpOwogICAgICBmYWNlT3JkZXIgPSBbCiAgICAgICAgInBvc2l0aXZlWCIsCiAgICAgICAgIm5lZ2F0aXZlWCIsCiAgICAgICAgInBvc2l0aXZlWSIsCiAgICAgICAgIm5lZ2F0aXZlWSIsCiAgICAgICAgInBvc2l0aXZlWiIsCiAgICAgICAgIm5lZ2F0aXZlWiIKICAgICAgXTsKICAgICAgY29sb3JNb2RlbEVUQzFTID0gMTYzOwogICAgICBjb2xvck1vZGVsVUFTVEMgPSAxNjY7CiAgICAgIHRyYW5zY29kZUtUWDJfZGVmYXVsdCA9IGNyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXJfZGVmYXVsdCh0cmFuc2NvZGVLVFgyKTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL3RyYW5zZmVyVHlwZWRBcnJheVRlc3QuanMKICB2YXIgdHJhbnNmZXJUeXBlZEFycmF5VGVzdF9leHBvcnRzID0ge307CiAgdmFyIGluaXRfdHJhbnNmZXJUeXBlZEFycmF5VGVzdCA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvdHJhbnNmZXJUeXBlZEFycmF5VGVzdC5qcyIoKSB7CiAgICAgIHNlbGYub25tZXNzYWdlID0gZnVuY3Rpb24oZXZlbnQpIHsKICAgICAgICBjb25zdCBhcnJheSA9IGV2ZW50LmRhdGEuYXJyYXk7CiAgICAgICAgY29uc3QgcG9zdE1lc3NhZ2UyID0gc2VsZi53ZWJraXRQb3N0TWVzc2FnZSB8fCBzZWxmLnBvc3RNZXNzYWdlOwogICAgICAgIHRyeSB7CiAgICAgICAgICBwb3N0TWVzc2FnZTIoCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICBhcnJheQogICAgICAgICAgICB9LAogICAgICAgICAgICBbYXJyYXkuYnVmZmVyXQogICAgICAgICAgKTsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICBwb3N0TWVzc2FnZTIoe30pOwogICAgICAgIH0KICAgICAgfTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Db3JlL0ludGVyc2VjdGlvbnMyRC5qcwogIHZhciBJbnRlcnNlY3Rpb25zMkQsIEludGVyc2VjdGlvbnMyRF9kZWZhdWx0OwogIHZhciBpbml0X0ludGVyc2VjdGlvbnMyRCA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL0NvcmUvSW50ZXJzZWN0aW9uczJELmpzIigpIHsKICAgICAgaW5pdF9DYXJ0ZXNpYW4yKCk7CiAgICAgIGluaXRfQ2FydGVzaWFuMygpOwogICAgICBpbml0X0NoZWNrKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIEludGVyc2VjdGlvbnMyRCA9IHt9OwogICAgICBJbnRlcnNlY3Rpb25zMkQuY2xpcFRyaWFuZ2xlQXRBeGlzQWxpZ25lZFRocmVzaG9sZCA9IGZ1bmN0aW9uKHRocmVzaG9sZCwga2VlcEFib3ZlLCB1MCwgdTEyLCB1MjIsIHJlc3VsdCkgewogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHRocmVzaG9sZCkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ0aHJlc2hvbGQgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KGtlZXBBYm92ZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJrZWVwQWJvdmUgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHUwKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInUwIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh1MTIpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgidTEgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHUyMikpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ1MiBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gW107CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHJlc3VsdC5sZW5ndGggPSAwOwogICAgICAgIH0KICAgICAgICBsZXQgdTBCZWhpbmQ7CiAgICAgICAgbGV0IHUxQmVoaW5kOwogICAgICAgIGxldCB1MkJlaGluZDsKICAgICAgICBpZiAoa2VlcEFib3ZlKSB7CiAgICAgICAgICB1MEJlaGluZCA9IHUwIDwgdGhyZXNob2xkOwogICAgICAgICAgdTFCZWhpbmQgPSB1MTIgPCB0aHJlc2hvbGQ7CiAgICAgICAgICB1MkJlaGluZCA9IHUyMiA8IHRocmVzaG9sZDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdTBCZWhpbmQgPSB1MCA+IHRocmVzaG9sZDsKICAgICAgICAgIHUxQmVoaW5kID0gdTEyID4gdGhyZXNob2xkOwogICAgICAgICAgdTJCZWhpbmQgPSB1MjIgPiB0aHJlc2hvbGQ7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG51bUJlaGluZCA9IHUwQmVoaW5kICsgdTFCZWhpbmQgKyB1MkJlaGluZDsKICAgICAgICBsZXQgdTAxUmF0aW87CiAgICAgICAgbGV0IHUwMlJhdGlvOwogICAgICAgIGxldCB1MTJSYXRpbzsKICAgICAgICBsZXQgdTEwUmF0aW87CiAgICAgICAgbGV0IHUyMFJhdGlvOwogICAgICAgIGxldCB1MjFSYXRpbzsKICAgICAgICBpZiAobnVtQmVoaW5kID09PSAxKSB7CiAgICAgICAgICBpZiAodTBCZWhpbmQpIHsKICAgICAgICAgICAgdTAxUmF0aW8gPSAodGhyZXNob2xkIC0gdTApIC8gKHUxMiAtIHUwKTsKICAgICAgICAgICAgdTAyUmF0aW8gPSAodGhyZXNob2xkIC0gdTApIC8gKHUyMiAtIHUwKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2goMSk7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKDIpOwogICAgICAgICAgICBpZiAodTAyUmF0aW8gIT09IDEpIHsKICAgICAgICAgICAgICByZXN1bHQucHVzaCgtMSk7CiAgICAgICAgICAgICAgcmVzdWx0LnB1c2goMCk7CiAgICAgICAgICAgICAgcmVzdWx0LnB1c2goMik7CiAgICAgICAgICAgICAgcmVzdWx0LnB1c2godTAyUmF0aW8pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh1MDFSYXRpbyAhPT0gMSkgewogICAgICAgICAgICAgIHJlc3VsdC5wdXNoKC0xKTsKICAgICAgICAgICAgICByZXN1bHQucHVzaCgwKTsKICAgICAgICAgICAgICByZXN1bHQucHVzaCgxKTsKICAgICAgICAgICAgICByZXN1bHQucHVzaCh1MDFSYXRpbyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSBpZiAodTFCZWhpbmQpIHsKICAgICAgICAgICAgdTEyUmF0aW8gPSAodGhyZXNob2xkIC0gdTEyKSAvICh1MjIgLSB1MTIpOwogICAgICAgICAgICB1MTBSYXRpbyA9ICh0aHJlc2hvbGQgLSB1MTIpIC8gKHUwIC0gdTEyKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2goMik7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKDApOwogICAgICAgICAgICBpZiAodTEwUmF0aW8gIT09IDEpIHsKICAgICAgICAgICAgICByZXN1bHQucHVzaCgtMSk7CiAgICAgICAgICAgICAgcmVzdWx0LnB1c2goMSk7CiAgICAgICAgICAgICAgcmVzdWx0LnB1c2goMCk7CiAgICAgICAgICAgICAgcmVzdWx0LnB1c2godTEwUmF0aW8pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh1MTJSYXRpbyAhPT0gMSkgewogICAgICAgICAgICAgIHJlc3VsdC5wdXNoKC0xKTsKICAgICAgICAgICAgICByZXN1bHQucHVzaCgxKTsKICAgICAgICAgICAgICByZXN1bHQucHVzaCgyKTsKICAgICAgICAgICAgICByZXN1bHQucHVzaCh1MTJSYXRpbyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSBpZiAodTJCZWhpbmQpIHsKICAgICAgICAgICAgdTIwUmF0aW8gPSAodGhyZXNob2xkIC0gdTIyKSAvICh1MCAtIHUyMik7CiAgICAgICAgICAgIHUyMVJhdGlvID0gKHRocmVzaG9sZCAtIHUyMikgLyAodTEyIC0gdTIyKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2goMCk7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKDEpOwogICAgICAgICAgICBpZiAodTIxUmF0aW8gIT09IDEpIHsKICAgICAgICAgICAgICByZXN1bHQucHVzaCgtMSk7CiAgICAgICAgICAgICAgcmVzdWx0LnB1c2goMik7CiAgICAgICAgICAgICAgcmVzdWx0LnB1c2goMSk7CiAgICAgICAgICAgICAgcmVzdWx0LnB1c2godTIxUmF0aW8pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh1MjBSYXRpbyAhPT0gMSkgewogICAgICAgICAgICAgIHJlc3VsdC5wdXNoKC0xKTsKICAgICAgICAgICAgICByZXN1bHQucHVzaCgyKTsKICAgICAgICAgICAgICByZXN1bHQucHVzaCgwKTsKICAgICAgICAgICAgICByZXN1bHQucHVzaCh1MjBSYXRpbyk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKG51bUJlaGluZCA9PT0gMikgewogICAgICAgICAgaWYgKCF1MEJlaGluZCAmJiB1MCAhPT0gdGhyZXNob2xkKSB7CiAgICAgICAgICAgIHUxMFJhdGlvID0gKHRocmVzaG9sZCAtIHUxMikgLyAodTAgLSB1MTIpOwogICAgICAgICAgICB1MjBSYXRpbyA9ICh0aHJlc2hvbGQgLSB1MjIpIC8gKHUwIC0gdTIyKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2goMCk7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKC0xKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2goMSk7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKDApOwogICAgICAgICAgICByZXN1bHQucHVzaCh1MTBSYXRpbyk7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKC0xKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2goMik7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKDApOwogICAgICAgICAgICByZXN1bHQucHVzaCh1MjBSYXRpbyk7CiAgICAgICAgICB9IGVsc2UgaWYgKCF1MUJlaGluZCAmJiB1MTIgIT09IHRocmVzaG9sZCkgewogICAgICAgICAgICB1MjFSYXRpbyA9ICh0aHJlc2hvbGQgLSB1MjIpIC8gKHUxMiAtIHUyMik7CiAgICAgICAgICAgIHUwMVJhdGlvID0gKHRocmVzaG9sZCAtIHUwKSAvICh1MTIgLSB1MCk7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKDEpOwogICAgICAgICAgICByZXN1bHQucHVzaCgtMSk7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKDIpOwogICAgICAgICAgICByZXN1bHQucHVzaCgxKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2godTIxUmF0aW8pOwogICAgICAgICAgICByZXN1bHQucHVzaCgtMSk7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKDApOwogICAgICAgICAgICByZXN1bHQucHVzaCgxKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2godTAxUmF0aW8pOwogICAgICAgICAgfSBlbHNlIGlmICghdTJCZWhpbmQgJiYgdTIyICE9PSB0aHJlc2hvbGQpIHsKICAgICAgICAgICAgdTAyUmF0aW8gPSAodGhyZXNob2xkIC0gdTApIC8gKHUyMiAtIHUwKTsKICAgICAgICAgICAgdTEyUmF0aW8gPSAodGhyZXNob2xkIC0gdTEyKSAvICh1MjIgLSB1MTIpOwogICAgICAgICAgICByZXN1bHQucHVzaCgyKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2goLTEpOwogICAgICAgICAgICByZXN1bHQucHVzaCgwKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2goMik7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKHUwMlJhdGlvKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2goLTEpOwogICAgICAgICAgICByZXN1bHQucHVzaCgxKTsKICAgICAgICAgICAgcmVzdWx0LnB1c2goMik7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKHUxMlJhdGlvKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKG51bUJlaGluZCAhPT0gMykgewogICAgICAgICAgcmVzdWx0LnB1c2goMCk7CiAgICAgICAgICByZXN1bHQucHVzaCgxKTsKICAgICAgICAgIHJlc3VsdC5wdXNoKDIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBJbnRlcnNlY3Rpb25zMkQuY29tcHV0ZUJhcnljZW50cmljQ29vcmRpbmF0ZXMgPSBmdW5jdGlvbih4LCB5LCB4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCByZXN1bHQpIHsKICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh4KSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInggaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHkpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgieSBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoeDEpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgieDEgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHkxKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoInkxIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh4MikpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ4MiBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQoeTIpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRGV2ZWxvcGVyRXJyb3JfZGVmYXVsdCgieTIgaXMgcmVxdWlyZWQuIik7CiAgICAgICAgfQogICAgICAgIGlmICghZGVmaW5lZF9kZWZhdWx0KHgzKSkgewogICAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIngzIGlzIHJlcXVpcmVkLiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdCh5MykpIHsKICAgICAgICAgIHRocm93IG5ldyBEZXZlbG9wZXJFcnJvcl9kZWZhdWx0KCJ5MyBpcyByZXF1aXJlZC4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgeDFteDMgPSB4MSAtIHgzOwogICAgICAgIGNvbnN0IHgzbXgyID0geDMgLSB4MjsKICAgICAgICBjb25zdCB5Mm15MyA9IHkyIC0geTM7CiAgICAgICAgY29uc3QgeTFteTMgPSB5MSAtIHkzOwogICAgICAgIGNvbnN0IGludmVyc2VEZXRlcm1pbmFudCA9IDEgLyAoeTJteTMgKiB4MW14MyArIHgzbXgyICogeTFteTMpOwogICAgICAgIGNvbnN0IHlteTMgPSB5IC0geTM7CiAgICAgICAgY29uc3QgeG14MyA9IHggLSB4MzsKICAgICAgICBjb25zdCBsMSA9ICh5Mm15MyAqIHhteDMgKyB4M214MiAqIHlteTMpICogaW52ZXJzZURldGVybWluYW50OwogICAgICAgIGNvbnN0IGwyID0gKC15MW15MyAqIHhteDMgKyB4MW14MyAqIHlteTMpICogaW52ZXJzZURldGVybWluYW50OwogICAgICAgIGNvbnN0IGwzID0gMSAtIGwxIC0gbDI7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICByZXN1bHQueCA9IGwxOwogICAgICAgICAgcmVzdWx0LnkgPSBsMjsKICAgICAgICAgIHJlc3VsdC56ID0gbDM7CiAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IENhcnRlc2lhbjNfZGVmYXVsdChsMSwgbDIsIGwzKTsKICAgICAgfTsKICAgICAgSW50ZXJzZWN0aW9uczJELmNvbXB1dGVMaW5lU2VnbWVudExpbmVTZWdtZW50SW50ZXJzZWN0aW9uID0gZnVuY3Rpb24oeDAwLCB5MDAsIHgwMSwgeTAxLCB4MTAsIHkxMCwgeDExLCB5MTEsIHJlc3VsdCkgewogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigieDAwIiwgeDAwKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInkwMCIsIHkwMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJ4MDEiLCB4MDEpOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigieTAxIiwgeTAxKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoIngxMCIsIHgxMCk7CiAgICAgICAgQ2hlY2tfZGVmYXVsdC50eXBlT2YubnVtYmVyKCJ5MTAiLCB5MTApOwogICAgICAgIENoZWNrX2RlZmF1bHQudHlwZU9mLm51bWJlcigieDExIiwgeDExKTsKICAgICAgICBDaGVja19kZWZhdWx0LnR5cGVPZi5udW1iZXIoInkxMSIsIHkxMSk7CiAgICAgICAgY29uc3QgbnVtZXJhdG9yMUEgPSAoeDExIC0geDEwKSAqICh5MDAgLSB5MTApIC0gKHkxMSAtIHkxMCkgKiAoeDAwIC0geDEwKTsKICAgICAgICBjb25zdCBudW1lcmF0b3IxQiA9ICh4MDEgLSB4MDApICogKHkwMCAtIHkxMCkgLSAoeTAxIC0geTAwKSAqICh4MDAgLSB4MTApOwogICAgICAgIGNvbnN0IGRlbm9taW5hdG9yMSA9ICh5MTEgLSB5MTApICogKHgwMSAtIHgwMCkgLSAoeDExIC0geDEwKSAqICh5MDEgLSB5MDApOwogICAgICAgIGlmIChkZW5vbWluYXRvcjEgPT09IDApIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgY29uc3QgdWExID0gbnVtZXJhdG9yMUEgLyBkZW5vbWluYXRvcjE7CiAgICAgICAgY29uc3QgdWIxID0gbnVtZXJhdG9yMUIgLyBkZW5vbWluYXRvcjE7CiAgICAgICAgaWYgKHVhMSA+PSAwICYmIHVhMSA8PSAxICYmIHViMSA+PSAwICYmIHViMSA8PSAxKSB7CiAgICAgICAgICBpZiAoIWRlZmluZWRfZGVmYXVsdChyZXN1bHQpKSB7CiAgICAgICAgICAgIHJlc3VsdCA9IG5ldyBDYXJ0ZXNpYW4yX2RlZmF1bHQoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJlc3VsdC54ID0geDAwICsgdWExICogKHgwMSAtIHgwMCk7CiAgICAgICAgICByZXN1bHQueSA9IHkwMCArIHVhMSAqICh5MDEgLSB5MDApOwogICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICB9CiAgICAgIH07CiAgICAgIEludGVyc2VjdGlvbnMyRF9kZWZhdWx0ID0gSW50ZXJzZWN0aW9uczJEOwogICAgfQogIH0pOwoKICAvLyBwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvdXBzYW1wbGVRdWFudGl6ZWRUZXJyYWluTWVzaC5qcwogIHZhciB1cHNhbXBsZVF1YW50aXplZFRlcnJhaW5NZXNoX2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydCh1cHNhbXBsZVF1YW50aXplZFRlcnJhaW5NZXNoX2V4cG9ydHMsIHsKICAgIGRlZmF1bHQ6ICgpID0+IHVwc2FtcGxlUXVhbnRpemVkVGVycmFpbk1lc2hfZGVmYXVsdAogIH0pOwogIGZ1bmN0aW9uIHVwc2FtcGxlUXVhbnRpemVkVGVycmFpbk1lc2gocGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cykgewogICAgY29uc3QgaXNFYXN0Q2hpbGQgPSBwYXJhbWV0ZXJzLmlzRWFzdENoaWxkOwogICAgY29uc3QgaXNOb3J0aENoaWxkID0gcGFyYW1ldGVycy5pc05vcnRoQ2hpbGQ7CiAgICBjb25zdCBtaW5VID0gaXNFYXN0Q2hpbGQgPyBoYWxmTWF4U2hvcnQgOiAwOwogICAgY29uc3QgbWF4VSA9IGlzRWFzdENoaWxkID8gbWF4U2hvcnQ1IDogaGFsZk1heFNob3J0OwogICAgY29uc3QgbWluViA9IGlzTm9ydGhDaGlsZCA/IGhhbGZNYXhTaG9ydCA6IDA7CiAgICBjb25zdCBtYXhWID0gaXNOb3J0aENoaWxkID8gbWF4U2hvcnQ1IDogaGFsZk1heFNob3J0OwogICAgY29uc3QgdUJ1ZmZlciA9IHVTY3JhdGNoOwogICAgY29uc3QgdkJ1ZmZlciA9IHZTY3JhdGNoOwogICAgY29uc3QgaGVpZ2h0QnVmZmVyID0gaGVpZ2h0U2NyYXRjaDsKICAgIGNvbnN0IG5vcm1hbEJ1ZmZlciA9IG5vcm1hbHNTY3JhdGNoOwogICAgdUJ1ZmZlci5sZW5ndGggPSAwOwogICAgdkJ1ZmZlci5sZW5ndGggPSAwOwogICAgaGVpZ2h0QnVmZmVyLmxlbmd0aCA9IDA7CiAgICBub3JtYWxCdWZmZXIubGVuZ3RoID0gMDsKICAgIGNvbnN0IGluZGljZXMgPSBpbmRpY2VzU2NyYXRjaDsKICAgIGluZGljZXMubGVuZ3RoID0gMDsKICAgIGNvbnN0IHZlcnRleE1hcCA9IHt9OwogICAgY29uc3QgcGFyZW50VmVydGljZXMgPSBwYXJhbWV0ZXJzLnZlcnRpY2VzOwogICAgbGV0IHBhcmVudEluZGljZXMgPSBwYXJhbWV0ZXJzLmluZGljZXM7CiAgICBwYXJlbnRJbmRpY2VzID0gcGFyZW50SW5kaWNlcy5zdWJhcnJheSgwLCBwYXJhbWV0ZXJzLmluZGV4Q291bnRXaXRob3V0U2tpcnRzKTsKICAgIGNvbnN0IGVuY29kaW5nID0gVGVycmFpbkVuY29kaW5nX2RlZmF1bHQuY2xvbmUocGFyYW1ldGVycy5lbmNvZGluZyk7CiAgICBjb25zdCBoYXNWZXJ0ZXhOb3JtYWxzID0gZW5jb2RpbmcuaGFzVmVydGV4Tm9ybWFsczsKICAgIGxldCB2ZXJ0ZXhDb3VudCA9IDA7CiAgICBjb25zdCBxdWFudGl6ZWRWZXJ0ZXhDb3VudCA9IHBhcmFtZXRlcnMudmVydGV4Q291bnRXaXRob3V0U2tpcnRzOwogICAgY29uc3QgcGFyZW50TWluaW11bUhlaWdodCA9IHBhcmFtZXRlcnMubWluaW11bUhlaWdodDsKICAgIGNvbnN0IHBhcmVudE1heGltdW1IZWlnaHQgPSBwYXJhbWV0ZXJzLm1heGltdW1IZWlnaHQ7CiAgICBjb25zdCBwYXJlbnRVQnVmZmVyID0gbmV3IEFycmF5KHF1YW50aXplZFZlcnRleENvdW50KTsKICAgIGNvbnN0IHBhcmVudFZCdWZmZXIgPSBuZXcgQXJyYXkocXVhbnRpemVkVmVydGV4Q291bnQpOwogICAgY29uc3QgcGFyZW50SGVpZ2h0QnVmZmVyID0gbmV3IEFycmF5KHF1YW50aXplZFZlcnRleENvdW50KTsKICAgIGNvbnN0IHBhcmVudE5vcm1hbEJ1ZmZlciA9IGhhc1ZlcnRleE5vcm1hbHMgPyBuZXcgQXJyYXkocXVhbnRpemVkVmVydGV4Q291bnQgKiAyKSA6IHZvaWQgMDsKICAgIGNvbnN0IHRocmVzaG9sZCA9IDIwOwogICAgbGV0IGhlaWdodDsKICAgIGxldCBpLCBuOwogICAgbGV0IHUzLCB2MzsKICAgIGZvciAoaSA9IDAsIG4gPSAwOyBpIDwgcXVhbnRpemVkVmVydGV4Q291bnQ7ICsraSwgbiArPSAyKSB7CiAgICAgIGNvbnN0IHRleENvb3JkcyA9IGVuY29kaW5nLmRlY29kZVRleHR1cmVDb29yZGluYXRlcygKICAgICAgICBwYXJlbnRWZXJ0aWNlcywKICAgICAgICBpLAogICAgICAgIGRlY29kZVRleENvb3Jkc1NjcmF0Y2gKICAgICAgKTsKICAgICAgaGVpZ2h0ID0gZW5jb2RpbmcuZGVjb2RlSGVpZ2h0KHBhcmVudFZlcnRpY2VzLCBpKTsKICAgICAgdTMgPSBNYXRoX2RlZmF1bHQuY2xhbXAodGV4Q29vcmRzLnggKiBtYXhTaG9ydDUgfCAwLCAwLCBtYXhTaG9ydDUpOwogICAgICB2MyA9IE1hdGhfZGVmYXVsdC5jbGFtcCh0ZXhDb29yZHMueSAqIG1heFNob3J0NSB8IDAsIDAsIG1heFNob3J0NSk7CiAgICAgIHBhcmVudEhlaWdodEJ1ZmZlcltpXSA9IE1hdGhfZGVmYXVsdC5jbGFtcCgKICAgICAgICAoaGVpZ2h0IC0gcGFyZW50TWluaW11bUhlaWdodCkgLyAocGFyZW50TWF4aW11bUhlaWdodCAtIHBhcmVudE1pbmltdW1IZWlnaHQpICogbWF4U2hvcnQ1IHwgMCwKICAgICAgICAwLAogICAgICAgIG1heFNob3J0NQogICAgICApOwogICAgICBpZiAodTMgPCB0aHJlc2hvbGQpIHsKICAgICAgICB1MyA9IDA7CiAgICAgIH0KICAgICAgaWYgKHYzIDwgdGhyZXNob2xkKSB7CiAgICAgICAgdjMgPSAwOwogICAgICB9CiAgICAgIGlmIChtYXhTaG9ydDUgLSB1MyA8IHRocmVzaG9sZCkgewogICAgICAgIHUzID0gbWF4U2hvcnQ1OwogICAgICB9CiAgICAgIGlmIChtYXhTaG9ydDUgLSB2MyA8IHRocmVzaG9sZCkgewogICAgICAgIHYzID0gbWF4U2hvcnQ1OwogICAgICB9CiAgICAgIHBhcmVudFVCdWZmZXJbaV0gPSB1MzsKICAgICAgcGFyZW50VkJ1ZmZlcltpXSA9IHYzOwogICAgICBpZiAoaGFzVmVydGV4Tm9ybWFscykgewogICAgICAgIGNvbnN0IGVuY29kZWROb3JtYWwgPSBlbmNvZGluZy5nZXRPY3RFbmNvZGVkTm9ybWFsKAogICAgICAgICAgcGFyZW50VmVydGljZXMsCiAgICAgICAgICBpLAogICAgICAgICAgb2N0RW5jb2RlZE5vcm1hbFNjcmF0Y2gKICAgICAgICApOwogICAgICAgIHBhcmVudE5vcm1hbEJ1ZmZlcltuXSA9IGVuY29kZWROb3JtYWwueDsKICAgICAgICBwYXJlbnROb3JtYWxCdWZmZXJbbiArIDFdID0gZW5jb2RlZE5vcm1hbC55OwogICAgICB9CiAgICAgIGlmICgoaXNFYXN0Q2hpbGQgJiYgdTMgPj0gaGFsZk1heFNob3J0IHx8ICFpc0Vhc3RDaGlsZCAmJiB1MyA8PSBoYWxmTWF4U2hvcnQpICYmIChpc05vcnRoQ2hpbGQgJiYgdjMgPj0gaGFsZk1heFNob3J0IHx8ICFpc05vcnRoQ2hpbGQgJiYgdjMgPD0gaGFsZk1heFNob3J0KSkgewogICAgICAgIHZlcnRleE1hcFtpXSA9IHZlcnRleENvdW50OwogICAgICAgIHVCdWZmZXIucHVzaCh1Myk7CiAgICAgICAgdkJ1ZmZlci5wdXNoKHYzKTsKICAgICAgICBoZWlnaHRCdWZmZXIucHVzaChwYXJlbnRIZWlnaHRCdWZmZXJbaV0pOwogICAgICAgIGlmIChoYXNWZXJ0ZXhOb3JtYWxzKSB7CiAgICAgICAgICBub3JtYWxCdWZmZXIucHVzaChwYXJlbnROb3JtYWxCdWZmZXJbbl0pOwogICAgICAgICAgbm9ybWFsQnVmZmVyLnB1c2gocGFyZW50Tm9ybWFsQnVmZmVyW24gKyAxXSk7CiAgICAgICAgfQogICAgICAgICsrdmVydGV4Q291bnQ7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHRyaWFuZ2xlVmVydGljZXMgPSBbXTsKICAgIHRyaWFuZ2xlVmVydGljZXMucHVzaChuZXcgVmVydGV4KCkpOwogICAgdHJpYW5nbGVWZXJ0aWNlcy5wdXNoKG5ldyBWZXJ0ZXgoKSk7CiAgICB0cmlhbmdsZVZlcnRpY2VzLnB1c2gobmV3IFZlcnRleCgpKTsKICAgIGNvbnN0IGNsaXBwZWRUcmlhbmdsZVZlcnRpY2VzID0gW107CiAgICBjbGlwcGVkVHJpYW5nbGVWZXJ0aWNlcy5wdXNoKG5ldyBWZXJ0ZXgoKSk7CiAgICBjbGlwcGVkVHJpYW5nbGVWZXJ0aWNlcy5wdXNoKG5ldyBWZXJ0ZXgoKSk7CiAgICBjbGlwcGVkVHJpYW5nbGVWZXJ0aWNlcy5wdXNoKG5ldyBWZXJ0ZXgoKSk7CiAgICBsZXQgY2xpcHBlZEluZGV4OwogICAgbGV0IGNsaXBwZWQyOwogICAgZm9yIChpID0gMDsgaSA8IHBhcmVudEluZGljZXMubGVuZ3RoOyBpICs9IDMpIHsKICAgICAgY29uc3QgaTAgPSBwYXJlbnRJbmRpY2VzW2ldOwogICAgICBjb25zdCBpMSA9IHBhcmVudEluZGljZXNbaSArIDFdOwogICAgICBjb25zdCBpMiA9IHBhcmVudEluZGljZXNbaSArIDJdOwogICAgICBjb25zdCB1MCA9IHBhcmVudFVCdWZmZXJbaTBdOwogICAgICBjb25zdCB1MTIgPSBwYXJlbnRVQnVmZmVyW2kxXTsKICAgICAgY29uc3QgdTIyID0gcGFyZW50VUJ1ZmZlcltpMl07CiAgICAgIHRyaWFuZ2xlVmVydGljZXNbMF0uaW5pdGlhbGl6ZUluZGV4ZWQoCiAgICAgICAgcGFyZW50VUJ1ZmZlciwKICAgICAgICBwYXJlbnRWQnVmZmVyLAogICAgICAgIHBhcmVudEhlaWdodEJ1ZmZlciwKICAgICAgICBwYXJlbnROb3JtYWxCdWZmZXIsCiAgICAgICAgaTAKICAgICAgKTsKICAgICAgdHJpYW5nbGVWZXJ0aWNlc1sxXS5pbml0aWFsaXplSW5kZXhlZCgKICAgICAgICBwYXJlbnRVQnVmZmVyLAogICAgICAgIHBhcmVudFZCdWZmZXIsCiAgICAgICAgcGFyZW50SGVpZ2h0QnVmZmVyLAogICAgICAgIHBhcmVudE5vcm1hbEJ1ZmZlciwKICAgICAgICBpMQogICAgICApOwogICAgICB0cmlhbmdsZVZlcnRpY2VzWzJdLmluaXRpYWxpemVJbmRleGVkKAogICAgICAgIHBhcmVudFVCdWZmZXIsCiAgICAgICAgcGFyZW50VkJ1ZmZlciwKICAgICAgICBwYXJlbnRIZWlnaHRCdWZmZXIsCiAgICAgICAgcGFyZW50Tm9ybWFsQnVmZmVyLAogICAgICAgIGkyCiAgICAgICk7CiAgICAgIGNvbnN0IGNsaXBwZWQgPSBJbnRlcnNlY3Rpb25zMkRfZGVmYXVsdC5jbGlwVHJpYW5nbGVBdEF4aXNBbGlnbmVkVGhyZXNob2xkKAogICAgICAgIGhhbGZNYXhTaG9ydCwKICAgICAgICBpc0Vhc3RDaGlsZCwKICAgICAgICB1MCwKICAgICAgICB1MTIsCiAgICAgICAgdTIyLAogICAgICAgIGNsaXBTY3JhdGNoCiAgICAgICk7CiAgICAgIGNsaXBwZWRJbmRleCA9IDA7CiAgICAgIGlmIChjbGlwcGVkSW5kZXggPj0gY2xpcHBlZC5sZW5ndGgpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjbGlwcGVkSW5kZXggPSBjbGlwcGVkVHJpYW5nbGVWZXJ0aWNlc1swXS5pbml0aWFsaXplRnJvbUNsaXBSZXN1bHQoCiAgICAgICAgY2xpcHBlZCwKICAgICAgICBjbGlwcGVkSW5kZXgsCiAgICAgICAgdHJpYW5nbGVWZXJ0aWNlcwogICAgICApOwogICAgICBpZiAoY2xpcHBlZEluZGV4ID49IGNsaXBwZWQubGVuZ3RoKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY2xpcHBlZEluZGV4ID0gY2xpcHBlZFRyaWFuZ2xlVmVydGljZXNbMV0uaW5pdGlhbGl6ZUZyb21DbGlwUmVzdWx0KAogICAgICAgIGNsaXBwZWQsCiAgICAgICAgY2xpcHBlZEluZGV4LAogICAgICAgIHRyaWFuZ2xlVmVydGljZXMKICAgICAgKTsKICAgICAgaWYgKGNsaXBwZWRJbmRleCA+PSBjbGlwcGVkLmxlbmd0aCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNsaXBwZWRJbmRleCA9IGNsaXBwZWRUcmlhbmdsZVZlcnRpY2VzWzJdLmluaXRpYWxpemVGcm9tQ2xpcFJlc3VsdCgKICAgICAgICBjbGlwcGVkLAogICAgICAgIGNsaXBwZWRJbmRleCwKICAgICAgICB0cmlhbmdsZVZlcnRpY2VzCiAgICAgICk7CiAgICAgIGNsaXBwZWQyID0gSW50ZXJzZWN0aW9uczJEX2RlZmF1bHQuY2xpcFRyaWFuZ2xlQXRBeGlzQWxpZ25lZFRocmVzaG9sZCgKICAgICAgICBoYWxmTWF4U2hvcnQsCiAgICAgICAgaXNOb3J0aENoaWxkLAogICAgICAgIGNsaXBwZWRUcmlhbmdsZVZlcnRpY2VzWzBdLmdldFYoKSwKICAgICAgICBjbGlwcGVkVHJpYW5nbGVWZXJ0aWNlc1sxXS5nZXRWKCksCiAgICAgICAgY2xpcHBlZFRyaWFuZ2xlVmVydGljZXNbMl0uZ2V0VigpLAogICAgICAgIGNsaXBTY3JhdGNoMgogICAgICApOwogICAgICBhZGRDbGlwcGVkUG9seWdvbigKICAgICAgICB1QnVmZmVyLAogICAgICAgIHZCdWZmZXIsCiAgICAgICAgaGVpZ2h0QnVmZmVyLAogICAgICAgIG5vcm1hbEJ1ZmZlciwKICAgICAgICBpbmRpY2VzLAogICAgICAgIHZlcnRleE1hcCwKICAgICAgICBjbGlwcGVkMiwKICAgICAgICBjbGlwcGVkVHJpYW5nbGVWZXJ0aWNlcywKICAgICAgICBoYXNWZXJ0ZXhOb3JtYWxzCiAgICAgICk7CiAgICAgIGlmIChjbGlwcGVkSW5kZXggPCBjbGlwcGVkLmxlbmd0aCkgewogICAgICAgIGNsaXBwZWRUcmlhbmdsZVZlcnRpY2VzWzJdLmNsb25lKGNsaXBwZWRUcmlhbmdsZVZlcnRpY2VzWzFdKTsKICAgICAgICBjbGlwcGVkVHJpYW5nbGVWZXJ0aWNlc1syXS5pbml0aWFsaXplRnJvbUNsaXBSZXN1bHQoCiAgICAgICAgICBjbGlwcGVkLAogICAgICAgICAgY2xpcHBlZEluZGV4LAogICAgICAgICAgdHJpYW5nbGVWZXJ0aWNlcwogICAgICAgICk7CiAgICAgICAgY2xpcHBlZDIgPSBJbnRlcnNlY3Rpb25zMkRfZGVmYXVsdC5jbGlwVHJpYW5nbGVBdEF4aXNBbGlnbmVkVGhyZXNob2xkKAogICAgICAgICAgaGFsZk1heFNob3J0LAogICAgICAgICAgaXNOb3J0aENoaWxkLAogICAgICAgICAgY2xpcHBlZFRyaWFuZ2xlVmVydGljZXNbMF0uZ2V0VigpLAogICAgICAgICAgY2xpcHBlZFRyaWFuZ2xlVmVydGljZXNbMV0uZ2V0VigpLAogICAgICAgICAgY2xpcHBlZFRyaWFuZ2xlVmVydGljZXNbMl0uZ2V0VigpLAogICAgICAgICAgY2xpcFNjcmF0Y2gyCiAgICAgICAgKTsKICAgICAgICBhZGRDbGlwcGVkUG9seWdvbigKICAgICAgICAgIHVCdWZmZXIsCiAgICAgICAgICB2QnVmZmVyLAogICAgICAgICAgaGVpZ2h0QnVmZmVyLAogICAgICAgICAgbm9ybWFsQnVmZmVyLAogICAgICAgICAgaW5kaWNlcywKICAgICAgICAgIHZlcnRleE1hcCwKICAgICAgICAgIGNsaXBwZWQyLAogICAgICAgICAgY2xpcHBlZFRyaWFuZ2xlVmVydGljZXMsCiAgICAgICAgICBoYXNWZXJ0ZXhOb3JtYWxzCiAgICAgICAgKTsKICAgICAgfQogICAgfQogICAgY29uc3QgdU9mZnNldCA9IGlzRWFzdENoaWxkID8gLW1heFNob3J0NSA6IDA7CiAgICBjb25zdCB2T2Zmc2V0ID0gaXNOb3J0aENoaWxkID8gLW1heFNob3J0NSA6IDA7CiAgICBjb25zdCB3ZXN0SW5kaWNlcyA9IFtdOwogICAgY29uc3Qgc291dGhJbmRpY2VzID0gW107CiAgICBjb25zdCBlYXN0SW5kaWNlcyA9IFtdOwogICAgY29uc3Qgbm9ydGhJbmRpY2VzID0gW107CiAgICBsZXQgbWluaW11bUhlaWdodCA9IE51bWJlci5NQVhfVkFMVUU7CiAgICBsZXQgbWF4aW11bUhlaWdodCA9IC1taW5pbXVtSGVpZ2h0OwogICAgY29uc3QgY2FydGVzaWFuVmVydGljZXMgPSB2ZXJ0aWNlc1NjcmF0Y2g7CiAgICBjYXJ0ZXNpYW5WZXJ0aWNlcy5sZW5ndGggPSAwOwogICAgY29uc3QgZWxsaXBzb2lkID0gRWxsaXBzb2lkX2RlZmF1bHQuY2xvbmUocGFyYW1ldGVycy5lbGxpcHNvaWQpOwogICAgY29uc3QgcmVjdGFuZ2xlID0gUmVjdGFuZ2xlX2RlZmF1bHQuY2xvbmUocGFyYW1ldGVycy5jaGlsZFJlY3RhbmdsZSk7CiAgICBjb25zdCBub3J0aCA9IHJlY3RhbmdsZS5ub3J0aDsKICAgIGNvbnN0IHNvdXRoID0gcmVjdGFuZ2xlLnNvdXRoOwogICAgbGV0IGVhc3QgPSByZWN0YW5nbGUuZWFzdDsKICAgIGNvbnN0IHdlc3QgPSByZWN0YW5nbGUud2VzdDsKICAgIGlmIChlYXN0IDwgd2VzdCkgewogICAgICBlYXN0ICs9IE1hdGhfZGVmYXVsdC5UV09fUEk7CiAgICB9CiAgICBmb3IgKGkgPSAwOyBpIDwgdUJ1ZmZlci5sZW5ndGg7ICsraSkgewogICAgICB1MyA9IE1hdGgucm91bmQodUJ1ZmZlcltpXSk7CiAgICAgIGlmICh1MyA8PSBtaW5VKSB7CiAgICAgICAgd2VzdEluZGljZXMucHVzaChpKTsKICAgICAgICB1MyA9IDA7CiAgICAgIH0gZWxzZSBpZiAodTMgPj0gbWF4VSkgewogICAgICAgIGVhc3RJbmRpY2VzLnB1c2goaSk7CiAgICAgICAgdTMgPSBtYXhTaG9ydDU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdTMgPSB1MyAqIDIgKyB1T2Zmc2V0OwogICAgICB9CiAgICAgIHVCdWZmZXJbaV0gPSB1MzsKICAgICAgdjMgPSBNYXRoLnJvdW5kKHZCdWZmZXJbaV0pOwogICAgICBpZiAodjMgPD0gbWluVikgewogICAgICAgIHNvdXRoSW5kaWNlcy5wdXNoKGkpOwogICAgICAgIHYzID0gMDsKICAgICAgfSBlbHNlIGlmICh2MyA+PSBtYXhWKSB7CiAgICAgICAgbm9ydGhJbmRpY2VzLnB1c2goaSk7CiAgICAgICAgdjMgPSBtYXhTaG9ydDU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdjMgPSB2MyAqIDIgKyB2T2Zmc2V0OwogICAgICB9CiAgICAgIHZCdWZmZXJbaV0gPSB2MzsKICAgICAgaGVpZ2h0ID0gTWF0aF9kZWZhdWx0LmxlcnAoCiAgICAgICAgcGFyZW50TWluaW11bUhlaWdodCwKICAgICAgICBwYXJlbnRNYXhpbXVtSGVpZ2h0LAogICAgICAgIGhlaWdodEJ1ZmZlcltpXSAvIG1heFNob3J0NQogICAgICApOwogICAgICBpZiAoaGVpZ2h0IDwgbWluaW11bUhlaWdodCkgewogICAgICAgIG1pbmltdW1IZWlnaHQgPSBoZWlnaHQ7CiAgICAgIH0KICAgICAgaWYgKGhlaWdodCA+IG1heGltdW1IZWlnaHQpIHsKICAgICAgICBtYXhpbXVtSGVpZ2h0ID0gaGVpZ2h0OwogICAgICB9CiAgICAgIGhlaWdodEJ1ZmZlcltpXSA9IGhlaWdodDsKICAgICAgY2FydG9ncmFwaGljU2NyYXRjaDIubG9uZ2l0dWRlID0gTWF0aF9kZWZhdWx0LmxlcnAod2VzdCwgZWFzdCwgdTMgLyBtYXhTaG9ydDUpOwogICAgICBjYXJ0b2dyYXBoaWNTY3JhdGNoMi5sYXRpdHVkZSA9IE1hdGhfZGVmYXVsdC5sZXJwKHNvdXRoLCBub3J0aCwgdjMgLyBtYXhTaG9ydDUpOwogICAgICBjYXJ0b2dyYXBoaWNTY3JhdGNoMi5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgIGVsbGlwc29pZC5jYXJ0b2dyYXBoaWNUb0NhcnRlc2lhbihjYXJ0b2dyYXBoaWNTY3JhdGNoMiwgY2FydGVzaWFuM1NjcmF0Y2g5KTsKICAgICAgY2FydGVzaWFuVmVydGljZXMucHVzaChjYXJ0ZXNpYW4zU2NyYXRjaDkueCk7CiAgICAgIGNhcnRlc2lhblZlcnRpY2VzLnB1c2goY2FydGVzaWFuM1NjcmF0Y2g5LnkpOwogICAgICBjYXJ0ZXNpYW5WZXJ0aWNlcy5wdXNoKGNhcnRlc2lhbjNTY3JhdGNoOS56KTsKICAgIH0KICAgIGNvbnN0IGJvdW5kaW5nU3BoZXJlID0gQm91bmRpbmdTcGhlcmVfZGVmYXVsdC5mcm9tVmVydGljZXMoCiAgICAgIGNhcnRlc2lhblZlcnRpY2VzLAogICAgICBDYXJ0ZXNpYW4zX2RlZmF1bHQuWkVSTywKICAgICAgMywKICAgICAgYm91bmRpbmdTcGhlcmVTY3JhdGNoCiAgICApOwogICAgY29uc3Qgb3JpZW50ZWRCb3VuZGluZ0JveCA9IE9yaWVudGVkQm91bmRpbmdCb3hfZGVmYXVsdC5mcm9tUmVjdGFuZ2xlKAogICAgICByZWN0YW5nbGUsCiAgICAgIG1pbmltdW1IZWlnaHQsCiAgICAgIG1heGltdW1IZWlnaHQsCiAgICAgIGVsbGlwc29pZCwKICAgICAgb3JpZW50ZWRCb3VuZGluZ0JveFNjcmF0Y2gKICAgICk7CiAgICBjb25zdCBvY2NsdWRlciA9IG5ldyBFbGxpcHNvaWRhbE9jY2x1ZGVyX2RlZmF1bHQoZWxsaXBzb2lkKTsKICAgIGNvbnN0IGhvcml6b25PY2NsdXNpb25Qb2ludCA9IG9jY2x1ZGVyLmNvbXB1dGVIb3Jpem9uQ3VsbGluZ1BvaW50RnJvbVZlcnRpY2VzUG9zc2libHlVbmRlckVsbGlwc29pZCgKICAgICAgYm91bmRpbmdTcGhlcmUuY2VudGVyLAogICAgICBjYXJ0ZXNpYW5WZXJ0aWNlcywKICAgICAgMywKICAgICAgYm91bmRpbmdTcGhlcmUuY2VudGVyLAogICAgICBtaW5pbXVtSGVpZ2h0LAogICAgICBob3Jpem9uT2NjbHVzaW9uUG9pbnRTY3JhdGNoCiAgICApOwogICAgY29uc3QgaGVpZ2h0UmFuZ2UgPSBtYXhpbXVtSGVpZ2h0IC0gbWluaW11bUhlaWdodDsKICAgIGNvbnN0IHZlcnRpY2VzID0gbmV3IFVpbnQxNkFycmF5KAogICAgICB1QnVmZmVyLmxlbmd0aCArIHZCdWZmZXIubGVuZ3RoICsgaGVpZ2h0QnVmZmVyLmxlbmd0aAogICAgKTsKICAgIGZvciAoaSA9IDA7IGkgPCB1QnVmZmVyLmxlbmd0aDsgKytpKSB7CiAgICAgIHZlcnRpY2VzW2ldID0gdUJ1ZmZlcltpXTsKICAgIH0KICAgIGxldCBzdGFydCA9IHVCdWZmZXIubGVuZ3RoOwogICAgZm9yIChpID0gMDsgaSA8IHZCdWZmZXIubGVuZ3RoOyArK2kpIHsKICAgICAgdmVydGljZXNbc3RhcnQgKyBpXSA9IHZCdWZmZXJbaV07CiAgICB9CiAgICBzdGFydCArPSB2QnVmZmVyLmxlbmd0aDsKICAgIGZvciAoaSA9IDA7IGkgPCBoZWlnaHRCdWZmZXIubGVuZ3RoOyArK2kpIHsKICAgICAgdmVydGljZXNbc3RhcnQgKyBpXSA9IG1heFNob3J0NSAqIChoZWlnaHRCdWZmZXJbaV0gLSBtaW5pbXVtSGVpZ2h0KSAvIGhlaWdodFJhbmdlOwogICAgfQogICAgY29uc3QgaW5kaWNlc1R5cGVkQXJyYXkgPSBJbmRleERhdGF0eXBlX2RlZmF1bHQuY3JlYXRlVHlwZWRBcnJheSgKICAgICAgdUJ1ZmZlci5sZW5ndGgsCiAgICAgIGluZGljZXMKICAgICk7CiAgICBsZXQgZW5jb2RlZE5vcm1hbHM7CiAgICBpZiAoaGFzVmVydGV4Tm9ybWFscykgewogICAgICBjb25zdCBub3JtYWxBcnJheSA9IG5ldyBVaW50OEFycmF5KG5vcm1hbEJ1ZmZlcik7CiAgICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaCgKICAgICAgICB2ZXJ0aWNlcy5idWZmZXIsCiAgICAgICAgaW5kaWNlc1R5cGVkQXJyYXkuYnVmZmVyLAogICAgICAgIG5vcm1hbEFycmF5LmJ1ZmZlcgogICAgICApOwogICAgICBlbmNvZGVkTm9ybWFscyA9IG5vcm1hbEFycmF5LmJ1ZmZlcjsKICAgIH0gZWxzZSB7CiAgICAgIHRyYW5zZmVyYWJsZU9iamVjdHMucHVzaCh2ZXJ0aWNlcy5idWZmZXIsIGluZGljZXNUeXBlZEFycmF5LmJ1ZmZlcik7CiAgICB9CiAgICByZXR1cm4gewogICAgICB2ZXJ0aWNlczogdmVydGljZXMuYnVmZmVyLAogICAgICBlbmNvZGVkTm9ybWFscywKICAgICAgaW5kaWNlczogaW5kaWNlc1R5cGVkQXJyYXkuYnVmZmVyLAogICAgICBtaW5pbXVtSGVpZ2h0LAogICAgICBtYXhpbXVtSGVpZ2h0LAogICAgICB3ZXN0SW5kaWNlcywKICAgICAgc291dGhJbmRpY2VzLAogICAgICBlYXN0SW5kaWNlcywKICAgICAgbm9ydGhJbmRpY2VzLAogICAgICBib3VuZGluZ1NwaGVyZSwKICAgICAgb3JpZW50ZWRCb3VuZGluZ0JveCwKICAgICAgaG9yaXpvbk9jY2x1c2lvblBvaW50CiAgICB9OwogIH0KICBmdW5jdGlvbiBWZXJ0ZXgoKSB7CiAgICB0aGlzLnZlcnRleEJ1ZmZlciA9IHZvaWQgMDsKICAgIHRoaXMuaW5kZXggPSB2b2lkIDA7CiAgICB0aGlzLmZpcnN0ID0gdm9pZCAwOwogICAgdGhpcy5zZWNvbmQgPSB2b2lkIDA7CiAgICB0aGlzLnJhdGlvID0gdm9pZCAwOwogIH0KICBmdW5jdGlvbiBsZXJwT2N0RW5jb2RlZE5vcm1hbCh2ZXJ0ZXgsIHJlc3VsdCkgewogICAgKytkZXB0aDsKICAgIGxldCBmaXJzdCA9IGNhcnRlc2lhblNjcmF0Y2gxW2RlcHRoXTsKICAgIGxldCBzZWNvbmQgPSBjYXJ0ZXNpYW5TY3JhdGNoMltkZXB0aF07CiAgICBmaXJzdCA9IEF0dHJpYnV0ZUNvbXByZXNzaW9uX2RlZmF1bHQub2N0RGVjb2RlKAogICAgICB2ZXJ0ZXguZmlyc3QuZ2V0Tm9ybWFsWCgpLAogICAgICB2ZXJ0ZXguZmlyc3QuZ2V0Tm9ybWFsWSgpLAogICAgICBmaXJzdAogICAgKTsKICAgIHNlY29uZCA9IEF0dHJpYnV0ZUNvbXByZXNzaW9uX2RlZmF1bHQub2N0RGVjb2RlKAogICAgICB2ZXJ0ZXguc2Vjb25kLmdldE5vcm1hbFgoKSwKICAgICAgdmVydGV4LnNlY29uZC5nZXROb3JtYWxZKCksCiAgICAgIHNlY29uZAogICAgKTsKICAgIGNhcnRlc2lhbjNTY3JhdGNoOSA9IENhcnRlc2lhbjNfZGVmYXVsdC5sZXJwKAogICAgICBmaXJzdCwKICAgICAgc2Vjb25kLAogICAgICB2ZXJ0ZXgucmF0aW8sCiAgICAgIGNhcnRlc2lhbjNTY3JhdGNoOQogICAgKTsKICAgIENhcnRlc2lhbjNfZGVmYXVsdC5ub3JtYWxpemUoY2FydGVzaWFuM1NjcmF0Y2g5LCBjYXJ0ZXNpYW4zU2NyYXRjaDkpOwogICAgQXR0cmlidXRlQ29tcHJlc3Npb25fZGVmYXVsdC5vY3RFbmNvZGUoY2FydGVzaWFuM1NjcmF0Y2g5LCByZXN1bHQpOwogICAgLS1kZXB0aDsKICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGZ1bmN0aW9uIGFkZENsaXBwZWRQb2x5Z29uKHVCdWZmZXIsIHZCdWZmZXIsIGhlaWdodEJ1ZmZlciwgbm9ybWFsQnVmZmVyLCBpbmRpY2VzLCB2ZXJ0ZXhNYXAsIGNsaXBwZWQsIHRyaWFuZ2xlVmVydGljZXMsIGhhc1ZlcnRleE5vcm1hbHMpIHsKICAgIGlmIChjbGlwcGVkLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgbnVtVmVydGljZXMgPSAwOwogICAgbGV0IGNsaXBwZWRJbmRleCA9IDA7CiAgICB3aGlsZSAoY2xpcHBlZEluZGV4IDwgY2xpcHBlZC5sZW5ndGgpIHsKICAgICAgY2xpcHBlZEluZGV4ID0gcG9seWdvblZlcnRpY2VzW251bVZlcnRpY2VzKytdLmluaXRpYWxpemVGcm9tQ2xpcFJlc3VsdCgKICAgICAgICBjbGlwcGVkLAogICAgICAgIGNsaXBwZWRJbmRleCwKICAgICAgICB0cmlhbmdsZVZlcnRpY2VzCiAgICAgICk7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bVZlcnRpY2VzOyArK2kpIHsKICAgICAgY29uc3QgcG9seWdvblZlcnRleCA9IHBvbHlnb25WZXJ0aWNlc1tpXTsKICAgICAgaWYgKCFwb2x5Z29uVmVydGV4LmlzSW5kZXhlZCgpKSB7CiAgICAgICAgY29uc3Qga2V5ID0gcG9seWdvblZlcnRleC5nZXRLZXkoKTsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHZlcnRleE1hcFtrZXldKSkgewogICAgICAgICAgcG9seWdvblZlcnRleC5uZXdJbmRleCA9IHZlcnRleE1hcFtrZXldOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb25zdCBuZXdJbmRleCA9IHVCdWZmZXIubGVuZ3RoOwogICAgICAgICAgdUJ1ZmZlci5wdXNoKHBvbHlnb25WZXJ0ZXguZ2V0VSgpKTsKICAgICAgICAgIHZCdWZmZXIucHVzaChwb2x5Z29uVmVydGV4LmdldFYoKSk7CiAgICAgICAgICBoZWlnaHRCdWZmZXIucHVzaChwb2x5Z29uVmVydGV4LmdldEgoKSk7CiAgICAgICAgICBpZiAoaGFzVmVydGV4Tm9ybWFscykgewogICAgICAgICAgICBub3JtYWxCdWZmZXIucHVzaChwb2x5Z29uVmVydGV4LmdldE5vcm1hbFgoKSk7CiAgICAgICAgICAgIG5vcm1hbEJ1ZmZlci5wdXNoKHBvbHlnb25WZXJ0ZXguZ2V0Tm9ybWFsWSgpKTsKICAgICAgICAgIH0KICAgICAgICAgIHBvbHlnb25WZXJ0ZXgubmV3SW5kZXggPSBuZXdJbmRleDsKICAgICAgICAgIHZlcnRleE1hcFtrZXldID0gbmV3SW5kZXg7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHBvbHlnb25WZXJ0ZXgubmV3SW5kZXggPSB2ZXJ0ZXhNYXBbcG9seWdvblZlcnRleC5pbmRleF07CiAgICAgICAgcG9seWdvblZlcnRleC51QnVmZmVyID0gdUJ1ZmZlcjsKICAgICAgICBwb2x5Z29uVmVydGV4LnZCdWZmZXIgPSB2QnVmZmVyOwogICAgICAgIHBvbHlnb25WZXJ0ZXguaGVpZ2h0QnVmZmVyID0gaGVpZ2h0QnVmZmVyOwogICAgICAgIGlmIChoYXNWZXJ0ZXhOb3JtYWxzKSB7CiAgICAgICAgICBwb2x5Z29uVmVydGV4Lm5vcm1hbEJ1ZmZlciA9IG5vcm1hbEJ1ZmZlcjsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChudW1WZXJ0aWNlcyA9PT0gMykgewogICAgICBpbmRpY2VzLnB1c2gocG9seWdvblZlcnRpY2VzWzBdLm5ld0luZGV4KTsKICAgICAgaW5kaWNlcy5wdXNoKHBvbHlnb25WZXJ0aWNlc1sxXS5uZXdJbmRleCk7CiAgICAgIGluZGljZXMucHVzaChwb2x5Z29uVmVydGljZXNbMl0ubmV3SW5kZXgpOwogICAgfSBlbHNlIGlmIChudW1WZXJ0aWNlcyA9PT0gNCkgewogICAgICBpbmRpY2VzLnB1c2gocG9seWdvblZlcnRpY2VzWzBdLm5ld0luZGV4KTsKICAgICAgaW5kaWNlcy5wdXNoKHBvbHlnb25WZXJ0aWNlc1sxXS5uZXdJbmRleCk7CiAgICAgIGluZGljZXMucHVzaChwb2x5Z29uVmVydGljZXNbMl0ubmV3SW5kZXgpOwogICAgICBpbmRpY2VzLnB1c2gocG9seWdvblZlcnRpY2VzWzBdLm5ld0luZGV4KTsKICAgICAgaW5kaWNlcy5wdXNoKHBvbHlnb25WZXJ0aWNlc1syXS5uZXdJbmRleCk7CiAgICAgIGluZGljZXMucHVzaChwb2x5Z29uVmVydGljZXNbM10ubmV3SW5kZXgpOwogICAgfQogIH0KICB2YXIgbWF4U2hvcnQ1LCBoYWxmTWF4U2hvcnQsIGNsaXBTY3JhdGNoLCBjbGlwU2NyYXRjaDIsIHZlcnRpY2VzU2NyYXRjaCwgY2FydG9ncmFwaGljU2NyYXRjaDIsIGNhcnRlc2lhbjNTY3JhdGNoOSwgdVNjcmF0Y2gsIHZTY3JhdGNoLCBoZWlnaHRTY3JhdGNoLCBpbmRpY2VzU2NyYXRjaCwgbm9ybWFsc1NjcmF0Y2gsIGhvcml6b25PY2NsdXNpb25Qb2ludFNjcmF0Y2gsIGJvdW5kaW5nU3BoZXJlU2NyYXRjaCwgb3JpZW50ZWRCb3VuZGluZ0JveFNjcmF0Y2gsIGRlY29kZVRleENvb3Jkc1NjcmF0Y2gsIG9jdEVuY29kZWROb3JtYWxTY3JhdGNoLCBlbmNvZGVkU2NyYXRjaCwgZGVwdGgsIGNhcnRlc2lhblNjcmF0Y2gxLCBjYXJ0ZXNpYW5TY3JhdGNoMiwgcG9seWdvblZlcnRpY2VzLCB1cHNhbXBsZVF1YW50aXplZFRlcnJhaW5NZXNoX2RlZmF1bHQ7CiAgdmFyIGluaXRfdXBzYW1wbGVRdWFudGl6ZWRUZXJyYWluTWVzaCA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvdXBzYW1wbGVRdWFudGl6ZWRUZXJyYWluTWVzaC5qcyIoKSB7CiAgICAgIGluaXRfQXR0cmlidXRlQ29tcHJlc3Npb24oKTsKICAgICAgaW5pdF9Cb3VuZGluZ1NwaGVyZSgpOwogICAgICBpbml0X0NhcnRlc2lhbjIoKTsKICAgICAgaW5pdF9DYXJ0ZXNpYW4zKCk7CiAgICAgIGluaXRfQ2FydG9ncmFwaGljKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X0VsbGlwc29pZCgpOwogICAgICBpbml0X0VsbGlwc29pZGFsT2NjbHVkZXIoKTsKICAgICAgaW5pdF9JbmRleERhdGF0eXBlKCk7CiAgICAgIGluaXRfSW50ZXJzZWN0aW9uczJEKCk7CiAgICAgIGluaXRfTWF0aCgpOwogICAgICBpbml0X09yaWVudGVkQm91bmRpbmdCb3goKTsKICAgICAgaW5pdF9SZWN0YW5nbGUoKTsKICAgICAgaW5pdF9UZXJyYWluRW5jb2RpbmcoKTsKICAgICAgaW5pdF9jcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyKCk7CiAgICAgIG1heFNob3J0NSA9IDMyNzY3OwogICAgICBoYWxmTWF4U2hvcnQgPSBtYXhTaG9ydDUgLyAyIHwgMDsKICAgICAgY2xpcFNjcmF0Y2ggPSBbXTsKICAgICAgY2xpcFNjcmF0Y2gyID0gW107CiAgICAgIHZlcnRpY2VzU2NyYXRjaCA9IFtdOwogICAgICBjYXJ0b2dyYXBoaWNTY3JhdGNoMiA9IG5ldyBDYXJ0b2dyYXBoaWNfZGVmYXVsdCgpOwogICAgICBjYXJ0ZXNpYW4zU2NyYXRjaDkgPSBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCk7CiAgICAgIHVTY3JhdGNoID0gW107CiAgICAgIHZTY3JhdGNoID0gW107CiAgICAgIGhlaWdodFNjcmF0Y2ggPSBbXTsKICAgICAgaW5kaWNlc1NjcmF0Y2ggPSBbXTsKICAgICAgbm9ybWFsc1NjcmF0Y2ggPSBbXTsKICAgICAgaG9yaXpvbk9jY2x1c2lvblBvaW50U2NyYXRjaCA9IG5ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKTsKICAgICAgYm91bmRpbmdTcGhlcmVTY3JhdGNoID0gbmV3IEJvdW5kaW5nU3BoZXJlX2RlZmF1bHQoKTsKICAgICAgb3JpZW50ZWRCb3VuZGluZ0JveFNjcmF0Y2ggPSBuZXcgT3JpZW50ZWRCb3VuZGluZ0JveF9kZWZhdWx0KCk7CiAgICAgIGRlY29kZVRleENvb3Jkc1NjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIG9jdEVuY29kZWROb3JtYWxTY3JhdGNoID0gbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpOwogICAgICBWZXJ0ZXgucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24ocmVzdWx0KSB7CiAgICAgICAgaWYgKCFkZWZpbmVkX2RlZmF1bHQocmVzdWx0KSkgewogICAgICAgICAgcmVzdWx0ID0gbmV3IFZlcnRleCgpOwogICAgICAgIH0KICAgICAgICByZXN1bHQudUJ1ZmZlciA9IHRoaXMudUJ1ZmZlcjsKICAgICAgICByZXN1bHQudkJ1ZmZlciA9IHRoaXMudkJ1ZmZlcjsKICAgICAgICByZXN1bHQuaGVpZ2h0QnVmZmVyID0gdGhpcy5oZWlnaHRCdWZmZXI7CiAgICAgICAgcmVzdWx0Lm5vcm1hbEJ1ZmZlciA9IHRoaXMubm9ybWFsQnVmZmVyOwogICAgICAgIHJlc3VsdC5pbmRleCA9IHRoaXMuaW5kZXg7CiAgICAgICAgcmVzdWx0LmZpcnN0ID0gdGhpcy5maXJzdDsKICAgICAgICByZXN1bHQuc2Vjb25kID0gdGhpcy5zZWNvbmQ7CiAgICAgICAgcmVzdWx0LnJhdGlvID0gdGhpcy5yYXRpbzsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9OwogICAgICBWZXJ0ZXgucHJvdG90eXBlLmluaXRpYWxpemVJbmRleGVkID0gZnVuY3Rpb24odUJ1ZmZlciwgdkJ1ZmZlciwgaGVpZ2h0QnVmZmVyLCBub3JtYWxCdWZmZXIsIGluZGV4KSB7CiAgICAgICAgdGhpcy51QnVmZmVyID0gdUJ1ZmZlcjsKICAgICAgICB0aGlzLnZCdWZmZXIgPSB2QnVmZmVyOwogICAgICAgIHRoaXMuaGVpZ2h0QnVmZmVyID0gaGVpZ2h0QnVmZmVyOwogICAgICAgIHRoaXMubm9ybWFsQnVmZmVyID0gbm9ybWFsQnVmZmVyOwogICAgICAgIHRoaXMuaW5kZXggPSBpbmRleDsKICAgICAgICB0aGlzLmZpcnN0ID0gdm9pZCAwOwogICAgICAgIHRoaXMuc2Vjb25kID0gdm9pZCAwOwogICAgICAgIHRoaXMucmF0aW8gPSB2b2lkIDA7CiAgICAgIH07CiAgICAgIFZlcnRleC5wcm90b3R5cGUuaW5pdGlhbGl6ZUZyb21DbGlwUmVzdWx0ID0gZnVuY3Rpb24oY2xpcFJlc3VsdCwgaW5kZXgsIHZlcnRpY2VzKSB7CiAgICAgICAgbGV0IG5leHRJbmRleCA9IGluZGV4ICsgMTsKICAgICAgICBpZiAoY2xpcFJlc3VsdFtpbmRleF0gIT09IC0xKSB7CiAgICAgICAgICB2ZXJ0aWNlc1tjbGlwUmVzdWx0W2luZGV4XV0uY2xvbmUodGhpcyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMudmVydGV4QnVmZmVyID0gdm9pZCAwOwogICAgICAgICAgdGhpcy5pbmRleCA9IHZvaWQgMDsKICAgICAgICAgIHRoaXMuZmlyc3QgPSB2ZXJ0aWNlc1tjbGlwUmVzdWx0W25leHRJbmRleF1dOwogICAgICAgICAgKytuZXh0SW5kZXg7CiAgICAgICAgICB0aGlzLnNlY29uZCA9IHZlcnRpY2VzW2NsaXBSZXN1bHRbbmV4dEluZGV4XV07CiAgICAgICAgICArK25leHRJbmRleDsKICAgICAgICAgIHRoaXMucmF0aW8gPSBjbGlwUmVzdWx0W25leHRJbmRleF07CiAgICAgICAgICArK25leHRJbmRleDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5leHRJbmRleDsKICAgICAgfTsKICAgICAgVmVydGV4LnByb3RvdHlwZS5nZXRLZXkgPSBmdW5jdGlvbigpIHsKICAgICAgICBpZiAodGhpcy5pc0luZGV4ZWQoKSkgewogICAgICAgICAgcmV0dXJuIHRoaXMuaW5kZXg7CiAgICAgICAgfQogICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh7CiAgICAgICAgICBmaXJzdDogdGhpcy5maXJzdC5nZXRLZXkoKSwKICAgICAgICAgIHNlY29uZDogdGhpcy5zZWNvbmQuZ2V0S2V5KCksCiAgICAgICAgICByYXRpbzogdGhpcy5yYXRpbwogICAgICAgIH0pOwogICAgICB9OwogICAgICBWZXJ0ZXgucHJvdG90eXBlLmlzSW5kZXhlZCA9IGZ1bmN0aW9uKCkgewogICAgICAgIHJldHVybiBkZWZpbmVkX2RlZmF1bHQodGhpcy5pbmRleCk7CiAgICAgIH07CiAgICAgIFZlcnRleC5wcm90b3R5cGUuZ2V0SCA9IGZ1bmN0aW9uKCkgewogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQodGhpcy5pbmRleCkpIHsKICAgICAgICAgIHJldHVybiB0aGlzLmhlaWdodEJ1ZmZlclt0aGlzLmluZGV4XTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIE1hdGhfZGVmYXVsdC5sZXJwKHRoaXMuZmlyc3QuZ2V0SCgpLCB0aGlzLnNlY29uZC5nZXRIKCksIHRoaXMucmF0aW8pOwogICAgICB9OwogICAgICBWZXJ0ZXgucHJvdG90eXBlLmdldFUgPSBmdW5jdGlvbigpIHsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHRoaXMuaW5kZXgpKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy51QnVmZmVyW3RoaXMuaW5kZXhdOwogICAgICAgIH0KICAgICAgICByZXR1cm4gTWF0aF9kZWZhdWx0LmxlcnAodGhpcy5maXJzdC5nZXRVKCksIHRoaXMuc2Vjb25kLmdldFUoKSwgdGhpcy5yYXRpbyk7CiAgICAgIH07CiAgICAgIFZlcnRleC5wcm90b3R5cGUuZ2V0ViA9IGZ1bmN0aW9uKCkgewogICAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQodGhpcy5pbmRleCkpIHsKICAgICAgICAgIHJldHVybiB0aGlzLnZCdWZmZXJbdGhpcy5pbmRleF07CiAgICAgICAgfQogICAgICAgIHJldHVybiBNYXRoX2RlZmF1bHQubGVycCh0aGlzLmZpcnN0LmdldFYoKSwgdGhpcy5zZWNvbmQuZ2V0VigpLCB0aGlzLnJhdGlvKTsKICAgICAgfTsKICAgICAgZW5jb2RlZFNjcmF0Y2ggPSBuZXcgQ2FydGVzaWFuMl9kZWZhdWx0KCk7CiAgICAgIGRlcHRoID0gLTE7CiAgICAgIGNhcnRlc2lhblNjcmF0Y2gxID0gW25ldyBDYXJ0ZXNpYW4zX2RlZmF1bHQoKSwgbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpXTsKICAgICAgY2FydGVzaWFuU2NyYXRjaDIgPSBbbmV3IENhcnRlc2lhbjNfZGVmYXVsdCgpLCBuZXcgQ2FydGVzaWFuM19kZWZhdWx0KCldOwogICAgICBWZXJ0ZXgucHJvdG90eXBlLmdldE5vcm1hbFggPSBmdW5jdGlvbigpIHsKICAgICAgICBpZiAoZGVmaW5lZF9kZWZhdWx0KHRoaXMuaW5kZXgpKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5ub3JtYWxCdWZmZXJbdGhpcy5pbmRleCAqIDJdOwogICAgICAgIH0KICAgICAgICBlbmNvZGVkU2NyYXRjaCA9IGxlcnBPY3RFbmNvZGVkTm9ybWFsKHRoaXMsIGVuY29kZWRTY3JhdGNoKTsKICAgICAgICByZXR1cm4gZW5jb2RlZFNjcmF0Y2gueDsKICAgICAgfTsKICAgICAgVmVydGV4LnByb3RvdHlwZS5nZXROb3JtYWxZID0gZnVuY3Rpb24oKSB7CiAgICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdCh0aGlzLmluZGV4KSkgewogICAgICAgICAgcmV0dXJuIHRoaXMubm9ybWFsQnVmZmVyW3RoaXMuaW5kZXggKiAyICsgMV07CiAgICAgICAgfQogICAgICAgIGVuY29kZWRTY3JhdGNoID0gbGVycE9jdEVuY29kZWROb3JtYWwodGhpcywgZW5jb2RlZFNjcmF0Y2gpOwogICAgICAgIHJldHVybiBlbmNvZGVkU2NyYXRjaC55OwogICAgICB9OwogICAgICBwb2x5Z29uVmVydGljZXMgPSBbXTsKICAgICAgcG9seWdvblZlcnRpY2VzLnB1c2gobmV3IFZlcnRleCgpKTsKICAgICAgcG9seWdvblZlcnRpY2VzLnB1c2gobmV3IFZlcnRleCgpKTsKICAgICAgcG9seWdvblZlcnRpY2VzLnB1c2gobmV3IFZlcnRleCgpKTsKICAgICAgcG9seWdvblZlcnRpY2VzLnB1c2gobmV3IFZlcnRleCgpKTsKICAgICAgdXBzYW1wbGVRdWFudGl6ZWRUZXJyYWluTWVzaF9kZWZhdWx0ID0gY3JlYXRlVGFza1Byb2Nlc3Nvcldvcmtlcl9kZWZhdWx0KHVwc2FtcGxlUXVhbnRpemVkVGVycmFpbk1lc2gpOwogICAgfQogIH0pOwoKICAvLyBpbXBvcnQoIi4vKiovKi5qcyIpIGluIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVHZW9tZXRyeS5qcwogIHZhciBnbG9iSW1wb3J0X2pzOwogIHZhciBpbml0XyA9IF9fZXNtKHsKICAgICdpbXBvcnQoIi4vKiovKi5qcyIpIGluIHBhY2thZ2VzL2VuZ2luZS9Tb3VyY2UvV29ya2Vycy9jcmVhdGVHZW9tZXRyeS5qcycoKSB7CiAgICAgIGdsb2JJbXBvcnRfanMgPSBfX2dsb2IoewogICAgICAgICIuL2NvbWJpbmVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY29tYmluZUdlb21ldHJ5KCksIGNvbWJpbmVHZW9tZXRyeV9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlQm94R2VvbWV0cnkuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZUJveEdlb21ldHJ5KCksIGNyZWF0ZUJveEdlb21ldHJ5X2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVCb3hPdXRsaW5lR2VvbWV0cnkuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZUJveE91dGxpbmVHZW9tZXRyeSgpLCBjcmVhdGVCb3hPdXRsaW5lR2VvbWV0cnlfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZUNpcmNsZUdlb21ldHJ5LmpzIjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAoaW5pdF9jcmVhdGVDaXJjbGVHZW9tZXRyeSgpLCBjcmVhdGVDaXJjbGVHZW9tZXRyeV9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlQ2lyY2xlT3V0bGluZUdlb21ldHJ5LmpzIjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAoaW5pdF9jcmVhdGVDaXJjbGVPdXRsaW5lR2VvbWV0cnkoKSwgY3JlYXRlQ2lyY2xlT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVDb3BsYW5hclBvbHlnb25HZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnkoKSwgY3JlYXRlQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnlfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZUNvcGxhbmFyUG9seWdvbk91dGxpbmVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5KCksIGNyZWF0ZUNvcGxhbmFyUG9seWdvbk91dGxpbmVHZW9tZXRyeV9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlQ29ycmlkb3JHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlQ29ycmlkb3JHZW9tZXRyeSgpLCBjcmVhdGVDb3JyaWRvckdlb21ldHJ5X2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVDb3JyaWRvck91dGxpbmVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnkoKSwgY3JlYXRlQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnlfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZUN5bGluZGVyR2VvbWV0cnkuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZUN5bGluZGVyR2VvbWV0cnkoKSwgY3JlYXRlQ3lsaW5kZXJHZW9tZXRyeV9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlQ3lsaW5kZXJPdXRsaW5lR2VvbWV0cnkuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZUN5bGluZGVyT3V0bGluZUdlb21ldHJ5KCksIGNyZWF0ZUN5bGluZGVyT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVFbGxpcHNlR2VvbWV0cnkuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZUVsbGlwc2VHZW9tZXRyeSgpLCBjcmVhdGVFbGxpcHNlR2VvbWV0cnlfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZUVsbGlwc2VPdXRsaW5lR2VvbWV0cnkuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZUVsbGlwc2VPdXRsaW5lR2VvbWV0cnkoKSwgY3JlYXRlRWxsaXBzZU91dGxpbmVHZW9tZXRyeV9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlRWxsaXBzb2lkR2VvbWV0cnkuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZUVsbGlwc29pZEdlb21ldHJ5KCksIGNyZWF0ZUVsbGlwc29pZEdlb21ldHJ5X2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnkuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZUVsbGlwc29pZE91dGxpbmVHZW9tZXRyeSgpLCBjcmVhdGVFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnlfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZUZydXN0dW1HZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlRnJ1c3R1bUdlb21ldHJ5KCksIGNyZWF0ZUZydXN0dW1HZW9tZXRyeV9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlRnJ1c3R1bU91dGxpbmVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlRnJ1c3R1bU91dGxpbmVHZW9tZXRyeSgpLCBjcmVhdGVGcnVzdHVtT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlR2VvbWV0cnkoKSwgY3JlYXRlR2VvbWV0cnlfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZUdyb3VuZFBvbHlsaW5lR2VvbWV0cnkuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZUdyb3VuZFBvbHlsaW5lR2VvbWV0cnkoKSwgY3JlYXRlR3JvdW5kUG9seWxpbmVHZW9tZXRyeV9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlUGxhbmVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlUGxhbmVHZW9tZXRyeSgpLCBjcmVhdGVQbGFuZUdlb21ldHJ5X2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVQbGFuZU91dGxpbmVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlUGxhbmVPdXRsaW5lR2VvbWV0cnkoKSwgY3JlYXRlUGxhbmVPdXRsaW5lR2VvbWV0cnlfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZVBvbHlnb25HZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlUG9seWdvbkdlb21ldHJ5KCksIGNyZWF0ZVBvbHlnb25HZW9tZXRyeV9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlUG9seWdvbk91dGxpbmVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlUG9seWdvbk91dGxpbmVHZW9tZXRyeSgpLCBjcmVhdGVQb2x5Z29uT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVQb2x5bGluZUdlb21ldHJ5LmpzIjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAoaW5pdF9jcmVhdGVQb2x5bGluZUdlb21ldHJ5KCksIGNyZWF0ZVBvbHlsaW5lR2VvbWV0cnlfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZVBvbHlsaW5lVm9sdW1lR2VvbWV0cnkuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZVBvbHlsaW5lVm9sdW1lR2VvbWV0cnkoKSwgY3JlYXRlUG9seWxpbmVWb2x1bWVHZW9tZXRyeV9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZVBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5KCksIGNyZWF0ZVBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5X2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVSZWN0YW5nbGVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlUmVjdGFuZ2xlR2VvbWV0cnkoKSwgY3JlYXRlUmVjdGFuZ2xlR2VvbWV0cnlfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZVJlY3RhbmdsZU91dGxpbmVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlUmVjdGFuZ2xlT3V0bGluZUdlb21ldHJ5KCksIGNyZWF0ZVJlY3RhbmdsZU91dGxpbmVHZW9tZXRyeV9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlU2ltcGxlUG9seWxpbmVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlU2ltcGxlUG9seWxpbmVHZW9tZXRyeSgpLCBjcmVhdGVTaW1wbGVQb2x5bGluZUdlb21ldHJ5X2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVTcGhlcmVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlU3BoZXJlR2VvbWV0cnkoKSwgY3JlYXRlU3BoZXJlR2VvbWV0cnlfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZVNwaGVyZU91dGxpbmVHZW9tZXRyeS5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlU3BoZXJlT3V0bGluZUdlb21ldHJ5KCksIGNyZWF0ZVNwaGVyZU91dGxpbmVHZW9tZXRyeV9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlVGFza1Byb2Nlc3Nvcldvcmtlci5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlVGFza1Byb2Nlc3NvcldvcmtlcigpLCBjcmVhdGVUYXNrUHJvY2Vzc29yV29ya2VyX2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVWZWN0b3JUaWxlQ2xhbXBlZFBvbHlsaW5lcy5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlVmVjdG9yVGlsZUNsYW1wZWRQb2x5bGluZXMoKSwgY3JlYXRlVmVjdG9yVGlsZUNsYW1wZWRQb2x5bGluZXNfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZVZlY3RvclRpbGVHZW9tZXRyaWVzLmpzIjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAoaW5pdF9jcmVhdGVWZWN0b3JUaWxlR2VvbWV0cmllcygpLCBjcmVhdGVWZWN0b3JUaWxlR2VvbWV0cmllc19leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlVmVjdG9yVGlsZVBvaW50cy5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfY3JlYXRlVmVjdG9yVGlsZVBvaW50cygpLCBjcmVhdGVWZWN0b3JUaWxlUG9pbnRzX2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVWZWN0b3JUaWxlUG9seWdvbnMuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZVZlY3RvclRpbGVQb2x5Z29ucygpLCBjcmVhdGVWZWN0b3JUaWxlUG9seWdvbnNfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZVZlY3RvclRpbGVQb2x5bGluZXMuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZVZlY3RvclRpbGVQb2x5bGluZXMoKSwgY3JlYXRlVmVjdG9yVGlsZVBvbHlsaW5lc19leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlVmVydGljZXNGcm9tR29vZ2xlRWFydGhFbnRlcnByaXNlQnVmZmVyLmpzIjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAoaW5pdF9jcmVhdGVWZXJ0aWNlc0Zyb21Hb29nbGVFYXJ0aEVudGVycHJpc2VCdWZmZXIoKSwgY3JlYXRlVmVydGljZXNGcm9tR29vZ2xlRWFydGhFbnRlcnByaXNlQnVmZmVyX2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVWZXJ0aWNlc0Zyb21IZWlnaHRtYXAuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2NyZWF0ZVZlcnRpY2VzRnJvbUhlaWdodG1hcCgpLCBjcmVhdGVWZXJ0aWNlc0Zyb21IZWlnaHRtYXBfZXhwb3J0cykpLAogICAgICAgICIuL2NyZWF0ZVZlcnRpY2VzRnJvbVF1YW50aXplZFRlcnJhaW5NZXNoLmpzIjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAoaW5pdF9jcmVhdGVWZXJ0aWNlc0Zyb21RdWFudGl6ZWRUZXJyYWluTWVzaCgpLCBjcmVhdGVWZXJ0aWNlc0Zyb21RdWFudGl6ZWRUZXJyYWluTWVzaF9leHBvcnRzKSksCiAgICAgICAgIi4vY3JlYXRlV2FsbEdlb21ldHJ5LmpzIjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAoaW5pdF9jcmVhdGVXYWxsR2VvbWV0cnkoKSwgY3JlYXRlV2FsbEdlb21ldHJ5X2V4cG9ydHMpKSwKICAgICAgICAiLi9jcmVhdGVXYWxsT3V0bGluZUdlb21ldHJ5LmpzIjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAoaW5pdF9jcmVhdGVXYWxsT3V0bGluZUdlb21ldHJ5KCksIGNyZWF0ZVdhbGxPdXRsaW5lR2VvbWV0cnlfZXhwb3J0cykpLAogICAgICAgICIuL2RlY29kZURyYWNvLmpzIjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAoaW5pdF9kZWNvZGVEcmFjbygpLCBkZWNvZGVEcmFjb19leHBvcnRzKSksCiAgICAgICAgIi4vZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlUGFja2V0LmpzIjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAoaW5pdF9kZWNvZGVHb29nbGVFYXJ0aEVudGVycHJpc2VQYWNrZXQoKSwgZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlUGFja2V0X2V4cG9ydHMpKSwKICAgICAgICAiLi9kZWNvZGVJM1MuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2RlY29kZUkzUygpLCBkZWNvZGVJM1NfZXhwb3J0cykpLAogICAgICAgICIuL2dhdXNzaWFuU3BsYXRTb3J0ZXIuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2dhdXNzaWFuU3BsYXRTb3J0ZXIoKSwgZ2F1c3NpYW5TcGxhdFNvcnRlcl9leHBvcnRzKSksCiAgICAgICAgIi4vZ2F1c3NpYW5TcGxhdFRleHR1cmVHZW5lcmF0b3IuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X2dhdXNzaWFuU3BsYXRUZXh0dXJlR2VuZXJhdG9yKCksIGdhdXNzaWFuU3BsYXRUZXh0dXJlR2VuZXJhdG9yX2V4cG9ydHMpKSwKICAgICAgICAiLi90cmFuc2NvZGVLVFgyLmpzIjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiAoaW5pdF90cmFuc2NvZGVLVFgyKCksIHRyYW5zY29kZUtUWDJfZXhwb3J0cykpLAogICAgICAgICIuL3RyYW5zZmVyVHlwZWRBcnJheVRlc3QuanMiOiAoKSA9PiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IChpbml0X3RyYW5zZmVyVHlwZWRBcnJheVRlc3QoKSwgdHJhbnNmZXJUeXBlZEFycmF5VGVzdF9leHBvcnRzKSksCiAgICAgICAgIi4vdXBzYW1wbGVRdWFudGl6ZWRUZXJyYWluTWVzaC5qcyI6ICgpID0+IFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gKGluaXRfdXBzYW1wbGVRdWFudGl6ZWRUZXJyYWluTWVzaCgpLCB1cHNhbXBsZVF1YW50aXplZFRlcnJhaW5NZXNoX2V4cG9ydHMpKQogICAgICB9KTsKICAgIH0KICB9KTsKCiAgLy8gcGFja2FnZXMvZW5naW5lL1NvdXJjZS9Xb3JrZXJzL2NyZWF0ZUdlb21ldHJ5LmpzCiAgdmFyIGNyZWF0ZUdlb21ldHJ5X2V4cG9ydHMgPSB7fTsKICBfX2V4cG9ydChjcmVhdGVHZW9tZXRyeV9leHBvcnRzLCB7CiAgICBkZWZhdWx0OiAoKSA9PiBjcmVhdGVHZW9tZXRyeV9kZWZhdWx0CiAgfSk7CiAgYXN5bmMgZnVuY3Rpb24gZ2V0TW9kdWxlKG1vZHVsZU5hbWUsIG1vZHVsZVBhdGgpIHsKICAgIGxldCBtb2R1bGUgPSBtb2R1bGVDYWNoZVttb2R1bGVQYXRoXSA/PyBtb2R1bGVDYWNoZVttb2R1bGVOYW1lXTsKICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobW9kdWxlKSkgewogICAgICByZXR1cm4gbW9kdWxlOwogICAgfQogICAgaWYgKGRlZmluZWRfZGVmYXVsdChtb2R1bGVQYXRoKSkgewogICAgICBpZiAodHlwZW9mIGV4cG9ydHMgPT09ICJvYmplY3QiKSB7CiAgICAgICAgbW9kdWxlID0gX19yZXF1aXJlKG1vZHVsZVBhdGgpOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGltcG9ydChtb2R1bGVQYXRoKTsKICAgICAgICBtb2R1bGUgPSByZXN1bHQuZGVmYXVsdDsKICAgICAgfQogICAgICBtb2R1bGVDYWNoZVttb2R1bGVQYXRoXSA9IG1vZHVsZTsKICAgICAgcmV0dXJuIG1vZHVsZTsKICAgIH0KICAgIGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gIm9iamVjdCIpIHsKICAgICAgbW9kdWxlID0gX19yZXF1aXJlKGBXb3JrZXJzLyR7bW9kdWxlTmFtZX1gKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IGRlZmluZWRfZGVmYXVsdChtb2R1bGVQYXRoKSA/IGF3YWl0IGltcG9ydChtb2R1bGVQYXRoKSA6IGF3YWl0IGdsb2JJbXBvcnRfanMoYC4vJHttb2R1bGVOYW1lfS5qc2ApOwogICAgICBtb2R1bGUgPSByZXN1bHQuZGVmYXVsdDsKICAgIH0KICAgIG1vZHVsZUNhY2hlW21vZHVsZU5hbWVdID0gbW9kdWxlOwogICAgcmV0dXJuIG1vZHVsZTsKICB9CiAgYXN5bmMgZnVuY3Rpb24gY3JlYXRlR2VvbWV0cnkocGFyYW1ldGVycywgdHJhbnNmZXJhYmxlT2JqZWN0cykgewogICAgY29uc3Qgc3ViVGFza3MgPSBwYXJhbWV0ZXJzLnN1YlRhc2tzOwogICAgY29uc3QgbGVuZ3RoID0gc3ViVGFza3MubGVuZ3RoOwogICAgY29uc3QgcmVzdWx0c09yUHJvbWlzZXMgPSBuZXcgQXJyYXkobGVuZ3RoKTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgY29uc3QgdGFzayA9IHN1YlRhc2tzW2ldOwogICAgICBjb25zdCBnZW9tZXRyeSA9IHRhc2suZ2VvbWV0cnk7CiAgICAgIGNvbnN0IG1vZHVsZU5hbWUgPSB0YXNrLm1vZHVsZU5hbWU7CiAgICAgIGNvbnN0IG1vZHVsZVBhdGggPSB0YXNrLm1vZHVsZVBhdGg7CiAgICAgIGlmIChkZWZpbmVkX2RlZmF1bHQobW9kdWxlTmFtZSkgJiYgZGVmaW5lZF9kZWZhdWx0KG1vZHVsZVBhdGgpKSB7CiAgICAgICAgdGhyb3cgbmV3IERldmVsb3BlckVycm9yX2RlZmF1bHQoIk11c3Qgb25seSBzZXQgbW9kdWxlTmFtZSBvciBtb2R1bGVQYXRoIik7CiAgICAgIH0KICAgICAgaWYgKGRlZmluZWRfZGVmYXVsdChtb2R1bGVOYW1lKSB8fCBkZWZpbmVkX2RlZmF1bHQobW9kdWxlUGF0aCkpIHsKICAgICAgICByZXN1bHRzT3JQcm9taXNlc1tpXSA9IGdldE1vZHVsZShtb2R1bGVOYW1lLCBtb2R1bGVQYXRoKS50aGVuKAogICAgICAgICAgKGNyZWF0ZUZ1bmN0aW9uKSA9PiBjcmVhdGVGdW5jdGlvbihnZW9tZXRyeSwgdGFzay5vZmZzZXQpCiAgICAgICAgKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXN1bHRzT3JQcm9taXNlc1tpXSA9IGdlb21ldHJ5OwogICAgICB9CiAgICB9CiAgICByZXR1cm4gUHJvbWlzZS5hbGwocmVzdWx0c09yUHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24ocmVzdWx0cykgewogICAgICByZXR1cm4gUHJpbWl0aXZlUGlwZWxpbmVfZGVmYXVsdC5wYWNrQ3JlYXRlR2VvbWV0cnlSZXN1bHRzKAogICAgICAgIHJlc3VsdHMsCiAgICAgICAgdHJhbnNmZXJhYmxlT2JqZWN0cwogICAgICApOwogICAgfSk7CiAgfQogIHZhciBtb2R1bGVDYWNoZSwgY3JlYXRlR2VvbWV0cnlfZGVmYXVsdDsKICB2YXIgaW5pdF9jcmVhdGVHZW9tZXRyeSA9IF9fZXNtKHsKICAgICJwYWNrYWdlcy9lbmdpbmUvU291cmNlL1dvcmtlcnMvY3JlYXRlR2VvbWV0cnkuanMiKCkgewogICAgICBpbml0X0RldmVsb3BlckVycm9yKCk7CiAgICAgIGluaXRfZGVmaW5lZCgpOwogICAgICBpbml0X1ByaW1pdGl2ZVBpcGVsaW5lKCk7CiAgICAgIGluaXRfY3JlYXRlVGFza1Byb2Nlc3NvcldvcmtlcigpOwogICAgICBpbml0XygpOwogICAgICBtb2R1bGVDYWNoZSA9IHt9OwogICAgICBjcmVhdGVHZW9tZXRyeV9kZWZhdWx0ID0gY3JlYXRlVGFza1Byb2Nlc3Nvcldvcmtlcl9kZWZhdWx0KGNyZWF0ZUdlb21ldHJ5KTsKICAgIH0KICB9KTsKCiAgLy8gPHN0ZGluPgogIHZhciBzdGRpbl9leHBvcnRzID0ge307CiAgX19leHBvcnQoc3RkaW5fZXhwb3J0cywgewogICAgY29tYmluZUdlb21ldHJ5OiAoKSA9PiBjb21iaW5lR2VvbWV0cnkyLAogICAgY3JlYXRlQm94R2VvbWV0cnk6ICgpID0+IGNyZWF0ZUJveEdlb21ldHJ5MiwKICAgIGNyZWF0ZUJveE91dGxpbmVHZW9tZXRyeTogKCkgPT4gY3JlYXRlQm94T3V0bGluZUdlb21ldHJ5MiwKICAgIGNyZWF0ZUNpcmNsZUdlb21ldHJ5OiAoKSA9PiBjcmVhdGVDaXJjbGVHZW9tZXRyeTIsCiAgICBjcmVhdGVDaXJjbGVPdXRsaW5lR2VvbWV0cnk6ICgpID0+IGNyZWF0ZUNpcmNsZU91dGxpbmVHZW9tZXRyeTIsCiAgICBjcmVhdGVDb3BsYW5hclBvbHlnb25HZW9tZXRyeTogKCkgPT4gY3JlYXRlQ29wbGFuYXJQb2x5Z29uR2VvbWV0cnkyLAogICAgY3JlYXRlQ29wbGFuYXJQb2x5Z29uT3V0bGluZUdlb21ldHJ5OiAoKSA9PiBjcmVhdGVDb3BsYW5hclBvbHlnb25PdXRsaW5lR2VvbWV0cnkyLAogICAgY3JlYXRlQ29ycmlkb3JHZW9tZXRyeTogKCkgPT4gY3JlYXRlQ29ycmlkb3JHZW9tZXRyeTIsCiAgICBjcmVhdGVDb3JyaWRvck91dGxpbmVHZW9tZXRyeTogKCkgPT4gY3JlYXRlQ29ycmlkb3JPdXRsaW5lR2VvbWV0cnkyLAogICAgY3JlYXRlQ3lsaW5kZXJHZW9tZXRyeTogKCkgPT4gY3JlYXRlQ3lsaW5kZXJHZW9tZXRyeTIsCiAgICBjcmVhdGVDeWxpbmRlck91dGxpbmVHZW9tZXRyeTogKCkgPT4gY3JlYXRlQ3lsaW5kZXJPdXRsaW5lR2VvbWV0cnkyLAogICAgY3JlYXRlRWxsaXBzZUdlb21ldHJ5OiAoKSA9PiBjcmVhdGVFbGxpcHNlR2VvbWV0cnkyLAogICAgY3JlYXRlRWxsaXBzZU91dGxpbmVHZW9tZXRyeTogKCkgPT4gY3JlYXRlRWxsaXBzZU91dGxpbmVHZW9tZXRyeTIsCiAgICBjcmVhdGVFbGxpcHNvaWRHZW9tZXRyeTogKCkgPT4gY3JlYXRlRWxsaXBzb2lkR2VvbWV0cnkyLAogICAgY3JlYXRlRWxsaXBzb2lkT3V0bGluZUdlb21ldHJ5OiAoKSA9PiBjcmVhdGVFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnkyLAogICAgY3JlYXRlRnJ1c3R1bUdlb21ldHJ5OiAoKSA9PiBjcmVhdGVGcnVzdHVtR2VvbWV0cnkyLAogICAgY3JlYXRlRnJ1c3R1bU91dGxpbmVHZW9tZXRyeTogKCkgPT4gY3JlYXRlRnJ1c3R1bU91dGxpbmVHZW9tZXRyeTIsCiAgICBjcmVhdGVHZW9tZXRyeTogKCkgPT4gY3JlYXRlR2VvbWV0cnkyLAogICAgY3JlYXRlR3JvdW5kUG9seWxpbmVHZW9tZXRyeTogKCkgPT4gY3JlYXRlR3JvdW5kUG9seWxpbmVHZW9tZXRyeTIsCiAgICBjcmVhdGVQbGFuZUdlb21ldHJ5OiAoKSA9PiBjcmVhdGVQbGFuZUdlb21ldHJ5MiwKICAgIGNyZWF0ZVBsYW5lT3V0bGluZUdlb21ldHJ5OiAoKSA9PiBjcmVhdGVQbGFuZU91dGxpbmVHZW9tZXRyeTIsCiAgICBjcmVhdGVQb2x5Z29uR2VvbWV0cnk6ICgpID0+IGNyZWF0ZVBvbHlnb25HZW9tZXRyeTIsCiAgICBjcmVhdGVQb2x5Z29uT3V0bGluZUdlb21ldHJ5OiAoKSA9PiBjcmVhdGVQb2x5Z29uT3V0bGluZUdlb21ldHJ5MiwKICAgIGNyZWF0ZVBvbHlsaW5lR2VvbWV0cnk6ICgpID0+IGNyZWF0ZVBvbHlsaW5lR2VvbWV0cnkyLAogICAgY3JlYXRlUG9seWxpbmVWb2x1bWVHZW9tZXRyeTogKCkgPT4gY3JlYXRlUG9seWxpbmVWb2x1bWVHZW9tZXRyeTIsCiAgICBjcmVhdGVQb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeTogKCkgPT4gY3JlYXRlUG9seWxpbmVWb2x1bWVPdXRsaW5lR2VvbWV0cnkyLAogICAgY3JlYXRlUmVjdGFuZ2xlR2VvbWV0cnk6ICgpID0+IGNyZWF0ZVJlY3RhbmdsZUdlb21ldHJ5MiwKICAgIGNyZWF0ZVJlY3RhbmdsZU91dGxpbmVHZW9tZXRyeTogKCkgPT4gY3JlYXRlUmVjdGFuZ2xlT3V0bGluZUdlb21ldHJ5MiwKICAgIGNyZWF0ZVNpbXBsZVBvbHlsaW5lR2VvbWV0cnk6ICgpID0+IGNyZWF0ZVNpbXBsZVBvbHlsaW5lR2VvbWV0cnkyLAogICAgY3JlYXRlU3BoZXJlR2VvbWV0cnk6ICgpID0+IGNyZWF0ZVNwaGVyZUdlb21ldHJ5MiwKICAgIGNyZWF0ZVNwaGVyZU91dGxpbmVHZW9tZXRyeTogKCkgPT4gY3JlYXRlU3BoZXJlT3V0bGluZUdlb21ldHJ5MiwKICAgIGNyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXI6ICgpID0+IGNyZWF0ZVRhc2tQcm9jZXNzb3JXb3JrZXIyLAogICAgY3JlYXRlVmVjdG9yVGlsZUNsYW1wZWRQb2x5bGluZXM6ICgpID0+IGNyZWF0ZVZlY3RvclRpbGVDbGFtcGVkUG9seWxpbmVzMiwKICAgIGNyZWF0ZVZlY3RvclRpbGVHZW9tZXRyaWVzOiAoKSA9PiBjcmVhdGVWZWN0b3JUaWxlR2VvbWV0cmllczIsCiAgICBjcmVhdGVWZWN0b3JUaWxlUG9pbnRzOiAoKSA9PiBjcmVhdGVWZWN0b3JUaWxlUG9pbnRzMiwKICAgIGNyZWF0ZVZlY3RvclRpbGVQb2x5Z29uczogKCkgPT4gY3JlYXRlVmVjdG9yVGlsZVBvbHlnb25zMiwKICAgIGNyZWF0ZVZlY3RvclRpbGVQb2x5bGluZXM6ICgpID0+IGNyZWF0ZVZlY3RvclRpbGVQb2x5bGluZXMyLAogICAgY3JlYXRlVmVydGljZXNGcm9tR29vZ2xlRWFydGhFbnRlcnByaXNlQnVmZmVyOiAoKSA9PiBjcmVhdGVWZXJ0aWNlc0Zyb21Hb29nbGVFYXJ0aEVudGVycHJpc2VCdWZmZXIyLAogICAgY3JlYXRlVmVydGljZXNGcm9tSGVpZ2h0bWFwOiAoKSA9PiBjcmVhdGVWZXJ0aWNlc0Zyb21IZWlnaHRtYXAyLAogICAgY3JlYXRlVmVydGljZXNGcm9tUXVhbnRpemVkVGVycmFpbk1lc2g6ICgpID0+IGNyZWF0ZVZlcnRpY2VzRnJvbVF1YW50aXplZFRlcnJhaW5NZXNoMiwKICAgIGNyZWF0ZVdhbGxHZW9tZXRyeTogKCkgPT4gY3JlYXRlV2FsbEdlb21ldHJ5MiwKICAgIGNyZWF0ZVdhbGxPdXRsaW5lR2VvbWV0cnk6ICgpID0+IGNyZWF0ZVdhbGxPdXRsaW5lR2VvbWV0cnkyLAogICAgZGVjb2RlRHJhY286ICgpID0+IGRlY29kZURyYWNvMiwKICAgIGRlY29kZUdvb2dsZUVhcnRoRW50ZXJwcmlzZVBhY2tldDogKCkgPT4gZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlUGFja2V0MiwKICAgIGRlY29kZUkzUzogKCkgPT4gZGVjb2RlSTNTMiwKICAgIGdhdXNzaWFuU3BsYXRTb3J0ZXI6ICgpID0+IGdhdXNzaWFuU3BsYXRTb3J0ZXIsCiAgICBnYXVzc2lhblNwbGF0VGV4dHVyZUdlbmVyYXRvcjogKCkgPT4gZ2F1c3NpYW5TcGxhdFRleHR1cmVHZW5lcmF0b3IsCiAgICB0cmFuc2NvZGVLVFgyOiAoKSA9PiB0cmFuc2NvZGVLVFgyMiwKICAgIHRyYW5zZmVyVHlwZWRBcnJheVRlc3Q6ICgpID0+IHRyYW5zZmVyVHlwZWRBcnJheVRlc3QsCiAgICB1cHNhbXBsZVF1YW50aXplZFRlcnJhaW5NZXNoOiAoKSA9PiB1cHNhbXBsZVF1YW50aXplZFRlcnJhaW5NZXNoMgogIH0pOwogIHZhciBjb21iaW5lR2VvbWV0cnkyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NvbWJpbmVHZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVCb3hHZW9tZXRyeTIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlQm94R2VvbWV0cnkoKSk7CiAgfTsKICB2YXIgY3JlYXRlQm94T3V0bGluZUdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVCb3hPdXRsaW5lR2VvbWV0cnkoKSk7CiAgfTsKICB2YXIgY3JlYXRlQ2lyY2xlR2VvbWV0cnkyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZUNpcmNsZUdlb21ldHJ5KCkpOwogIH07CiAgdmFyIGNyZWF0ZUNpcmNsZU91dGxpbmVHZW9tZXRyeTIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlQ2lyY2xlT3V0bGluZUdlb21ldHJ5KCkpOwogIH07CiAgdmFyIGNyZWF0ZUNvcGxhbmFyUG9seWdvbkdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVDb3BsYW5hclBvbHlnb25HZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVDb3BsYW5hclBvbHlnb25PdXRsaW5lR2VvbWV0cnkyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZUNvcGxhbmFyUG9seWdvbk91dGxpbmVHZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVDb3JyaWRvckdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVDb3JyaWRvckdlb21ldHJ5KCkpOwogIH07CiAgdmFyIGNyZWF0ZUNvcnJpZG9yT3V0bGluZUdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVDb3JyaWRvck91dGxpbmVHZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVDeWxpbmRlckdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVDeWxpbmRlckdlb21ldHJ5KCkpOwogIH07CiAgdmFyIGNyZWF0ZUN5bGluZGVyT3V0bGluZUdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVDeWxpbmRlck91dGxpbmVHZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVFbGxpcHNlR2VvbWV0cnkyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZUVsbGlwc2VHZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVFbGxpcHNlT3V0bGluZUdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVFbGxpcHNlT3V0bGluZUdlb21ldHJ5KCkpOwogIH07CiAgdmFyIGNyZWF0ZUVsbGlwc29pZEdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVFbGxpcHNvaWRHZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVFbGxpcHNvaWRPdXRsaW5lR2VvbWV0cnkyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZUVsbGlwc29pZE91dGxpbmVHZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVGcnVzdHVtR2VvbWV0cnkyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZUZydXN0dW1HZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVGcnVzdHVtT3V0bGluZUdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVGcnVzdHVtT3V0bGluZUdlb21ldHJ5KCkpOwogIH07CiAgdmFyIGNyZWF0ZUdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVHZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVHcm91bmRQb2x5bGluZUdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVHcm91bmRQb2x5bGluZUdlb21ldHJ5KCkpOwogIH07CiAgdmFyIGNyZWF0ZVBsYW5lR2VvbWV0cnkyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZVBsYW5lR2VvbWV0cnkoKSk7CiAgfTsKICB2YXIgY3JlYXRlUGxhbmVPdXRsaW5lR2VvbWV0cnkyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZVBsYW5lT3V0bGluZUdlb21ldHJ5KCkpOwogIH07CiAgdmFyIGNyZWF0ZVBvbHlnb25HZW9tZXRyeTIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlUG9seWdvbkdlb21ldHJ5KCkpOwogIH07CiAgdmFyIGNyZWF0ZVBvbHlnb25PdXRsaW5lR2VvbWV0cnkyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZVBvbHlnb25PdXRsaW5lR2VvbWV0cnkoKSk7CiAgfTsKICB2YXIgY3JlYXRlUG9seWxpbmVHZW9tZXRyeTIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlUG9seWxpbmVHZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVQb2x5bGluZVZvbHVtZUdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVQb2x5bGluZVZvbHVtZUdlb21ldHJ5KCkpOwogIH07CiAgdmFyIGNyZWF0ZVBvbHlsaW5lVm9sdW1lT3V0bGluZUdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVQb2x5bGluZVZvbHVtZU91dGxpbmVHZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVSZWN0YW5nbGVHZW9tZXRyeTIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlUmVjdGFuZ2xlR2VvbWV0cnkoKSk7CiAgfTsKICB2YXIgY3JlYXRlUmVjdGFuZ2xlT3V0bGluZUdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVSZWN0YW5nbGVPdXRsaW5lR2VvbWV0cnkoKSk7CiAgfTsKICB2YXIgY3JlYXRlU2ltcGxlUG9seWxpbmVHZW9tZXRyeTIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlU2ltcGxlUG9seWxpbmVHZW9tZXRyeSgpKTsKICB9OwogIHZhciBjcmVhdGVTcGhlcmVHZW9tZXRyeTIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlU3BoZXJlR2VvbWV0cnkoKSk7CiAgfTsKICB2YXIgY3JlYXRlU3BoZXJlT3V0bGluZUdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVTcGhlcmVPdXRsaW5lR2VvbWV0cnkoKSk7CiAgfTsKICB2YXIgY3JlYXRlVGFza1Byb2Nlc3NvcldvcmtlcjIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlVGFza1Byb2Nlc3NvcldvcmtlcigpKTsKICB9OwogIHZhciBjcmVhdGVWZWN0b3JUaWxlQ2xhbXBlZFBvbHlsaW5lczIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlVmVjdG9yVGlsZUNsYW1wZWRQb2x5bGluZXMoKSk7CiAgfTsKICB2YXIgY3JlYXRlVmVjdG9yVGlsZUdlb21ldHJpZXMyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZVZlY3RvclRpbGVHZW9tZXRyaWVzKCkpOwogIH07CiAgdmFyIGNyZWF0ZVZlY3RvclRpbGVQb2ludHMyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZVZlY3RvclRpbGVQb2ludHMoKSk7CiAgfTsKICB2YXIgY3JlYXRlVmVjdG9yVGlsZVBvbHlnb25zMiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVWZWN0b3JUaWxlUG9seWdvbnMoKSk7CiAgfTsKICB2YXIgY3JlYXRlVmVjdG9yVGlsZVBvbHlsaW5lczIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlVmVjdG9yVGlsZVBvbHlsaW5lcygpKTsKICB9OwogIHZhciBjcmVhdGVWZXJ0aWNlc0Zyb21Hb29nbGVFYXJ0aEVudGVycHJpc2VCdWZmZXIyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZVZlcnRpY2VzRnJvbUdvb2dsZUVhcnRoRW50ZXJwcmlzZUJ1ZmZlcigpKTsKICB9OwogIHZhciBjcmVhdGVWZXJ0aWNlc0Zyb21IZWlnaHRtYXAyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2NyZWF0ZVZlcnRpY2VzRnJvbUhlaWdodG1hcCgpKTsKICB9OwogIHZhciBjcmVhdGVWZXJ0aWNlc0Zyb21RdWFudGl6ZWRUZXJyYWluTWVzaDIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlVmVydGljZXNGcm9tUXVhbnRpemVkVGVycmFpbk1lc2goKSk7CiAgfTsKICB2YXIgY3JlYXRlV2FsbEdlb21ldHJ5MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9jcmVhdGVXYWxsR2VvbWV0cnkoKSk7CiAgfTsKICB2YXIgY3JlYXRlV2FsbE91dGxpbmVHZW9tZXRyeTIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfY3JlYXRlV2FsbE91dGxpbmVHZW9tZXRyeSgpKTsKICB9OwogIHZhciBkZWNvZGVEcmFjbzIgPSAoKSA9PiB7CiAgICBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IGluaXRfZGVjb2RlRHJhY28oKSk7CiAgfTsKICB2YXIgZGVjb2RlR29vZ2xlRWFydGhFbnRlcnByaXNlUGFja2V0MiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9kZWNvZGVHb29nbGVFYXJ0aEVudGVycHJpc2VQYWNrZXQoKSk7CiAgfTsKICB2YXIgZGVjb2RlSTNTMiA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9kZWNvZGVJM1MoKSk7CiAgfTsKICB2YXIgZ2F1c3NpYW5TcGxhdFNvcnRlciA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF9nYXVzc2lhblNwbGF0U29ydGVyKCkpOwogIH07CiAgdmFyIGdhdXNzaWFuU3BsYXRUZXh0dXJlR2VuZXJhdG9yID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X2dhdXNzaWFuU3BsYXRUZXh0dXJlR2VuZXJhdG9yKCkpOwogIH07CiAgdmFyIHRyYW5zY29kZUtUWDIyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X3RyYW5zY29kZUtUWDIoKSk7CiAgfTsKICB2YXIgdHJhbnNmZXJUeXBlZEFycmF5VGVzdCA9ICgpID0+IHsKICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4gaW5pdF90cmFuc2ZlclR5cGVkQXJyYXlUZXN0KCkpOwogIH07CiAgdmFyIHVwc2FtcGxlUXVhbnRpemVkVGVycmFpbk1lc2gyID0gKCkgPT4gewogICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBpbml0X3Vwc2FtcGxlUXVhbnRpemVkVGVycmFpbk1lc2goKSk7CiAgfTsKICByZXR1cm4gX190b0NvbW1vbkpTKHN0ZGluX2V4cG9ydHMpOwp9KSgpOwo=");
}
});
// node_modules/mersenne-twister/src/mersenne-twister.js
var require_mersenne_twister = __commonJS({
"node_modules/mersenne-twister/src/mersenne-twister.js"(exports2, module2) {
var import_InlineWorkers1347 = __toESM(require_InlineWorkers());
var MersenneTwister4 = function(seed) {
if (seed == void 0) {
seed = (/* @__PURE__ */ new Date()).getTime();
}
this.N = 624;
this.M = 397;
this.MATRIX_A = 2567483615;
this.UPPER_MASK = 2147483648;
this.LOWER_MASK = 2147483647;
this.mt = new Array(this.N);
this.mti = this.N + 1;
if (seed.constructor == Array) {
this.init_by_array(seed, seed.length);
} else {
this.init_seed(seed);
}
};
MersenneTwister4.prototype.init_seed = function(s) {
this.mt[0] = s >>> 0;
for (this.mti = 1; this.mti < this.N; this.mti++) {
var s = this.mt[this.mti - 1] ^ this.mt[this.mti - 1] >>> 30;
this.mt[this.mti] = (((s & 4294901760) >>> 16) * 1812433253 << 16) + (s & 65535) * 1812433253 + this.mti;
this.mt[this.mti] >>>= 0;
}
};
MersenneTwister4.prototype.init_by_array = function(init_key, key_length) {
var i, j, k;
this.init_seed(19650218);
i = 1;
j = 0;
k = this.N > key_length ? this.N : key_length;
for (; k; k--) {
var s = this.mt[i - 1] ^ this.mt[i - 1] >>> 30;
this.mt[i] = (this.mt[i] ^ (((s & 4294901760) >>> 16) * 1664525 << 16) + (s & 65535) * 1664525) + init_key[j] + j;
this.mt[i] >>>= 0;
i++;
j++;
if (i >= this.N) {
this.mt[0] = this.mt[this.N - 1];
i = 1;
}
if (j >= key_length) j = 0;
}
for (k = this.N - 1; k; k--) {
var s = this.mt[i - 1] ^ this.mt[i - 1] >>> 30;
this.mt[i] = (this.mt[i] ^ (((s & 4294901760) >>> 16) * 1566083941 << 16) + (s & 65535) * 1566083941) - i;
this.mt[i] >>>= 0;
i++;
if (i >= this.N) {
this.mt[0] = this.mt[this.N - 1];
i = 1;
}
}
this.mt[0] = 2147483648;
};
MersenneTwister4.prototype.random_int = function() {
var y;
var mag01 = new Array(0, this.MATRIX_A);
if (this.mti >= this.N) {
var kk;
if (this.mti == this.N + 1)
this.init_seed(5489);
for (kk = 0; kk < this.N - this.M; kk++) {
y = this.mt[kk] & this.UPPER_MASK | this.mt[kk + 1] & this.LOWER_MASK;
this.mt[kk] = this.mt[kk + this.M] ^ y >>> 1 ^ mag01[y & 1];
}
for (; kk < this.N - 1; kk++) {
y = this.mt[kk] & this.UPPER_MASK | this.mt[kk + 1] & this.LOWER_MASK;
this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ y >>> 1 ^ mag01[y & 1];
}
y = this.mt[this.N - 1] & this.UPPER_MASK | this.mt[0] & this.LOWER_MASK;
this.mt[this.N - 1] = this.mt[this.M - 1] ^ y >>> 1 ^ mag01[y & 1];
this.mti = 0;
}
y = this.mt[this.mti++];
y ^= y >>> 11;
y ^= y << 7 & 2636928640;
y ^= y << 15 & 4022730752;
y ^= y >>> 18;
return y >>> 0;
};
MersenneTwister4.prototype.random_int31 = function() {
return this.random_int() >>> 1;
};
MersenneTwister4.prototype.random_incl = function() {
return this.random_int() * (1 / 4294967295);
};
MersenneTwister4.prototype.random = function() {
return this.random_int() * (1 / 4294967296);
};
MersenneTwister4.prototype.random_excl = function() {
return (this.random_int() + 0.5) * (1 / 4294967296);
};
MersenneTwister4.prototype.random_long = function() {
var a3 = this.random_int() >>> 5, b = this.random_int() >>> 6;
return (a3 * 67108864 + b) * (1 / 9007199254740992);
};
module2.exports = MersenneTwister4;
}
});
// node_modules/urijs/src/punycode.js
var require_punycode = __commonJS({
"node_modules/urijs/src/punycode.js"(exports2, module2) {
var import_InlineWorkers1347 = __toESM(require_InlineWorkers());
/*! https://mths.be/punycode v1.4.0 by @mathias */
(function(root) {
var freeExports = typeof exports2 == "object" && exports2 && !exports2.nodeType && exports2;
var freeModule = typeof module2 == "object" && module2 && !module2.nodeType && module2;
var freeGlobal = typeof global == "object" && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal) {
root = freeGlobal;
}
var punycode, maxInt = 2147483647, base = 36, tMin = 1, tMax = 26, skew = 38, damp = 700, initialBias = 72, initialN = 128, delimiter = "-", regexPunycode = /^xn--/, regexNonASCII = /[^\x20-\x7E]/, regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, errors = {
"overflow": "Overflow: input needs wider integers to process",
"not-basic": "Illegal input >= 0x80 (not a basic code point)",
"invalid-input": "Invalid input"
}, baseMinusTMin = base - tMin, floor = Math.floor, stringFromCharCode = String.fromCharCode, key;
function error(type) {
throw new RangeError(errors[type]);
}
function map(array, fn) {
var length2 = array.length;
var result = [];
while (length2--) {
result[length2] = fn(array[length2]);
}
return result;
}
function mapDomain(string, fn) {
var parts = string.split("@");
var result = "";
if (parts.length > 1) {
result = parts[0] + "@";
string = parts[1];
}
string = string.replace(regexSeparators, ".");
var labels = string.split(".");
var encoded = map(labels, fn).join(".");
return result + encoded;
}
function ucs2decode(string) {
var output = [], counter = 0, length2 = string.length, value, extra;
while (counter < length2) {
value = string.charCodeAt(counter++);
if (value >= 55296 && value <= 56319 && counter < length2) {
extra = string.charCodeAt(counter++);
if ((extra & 64512) == 56320) {
output.push(((value & 1023) << 10) + (extra & 1023) + 65536);
} else {
output.push(value);
counter--;
}
} else {
output.push(value);
}
}
return output;
}
function ucs2encode(array) {
return map(array, function(value) {
var output = "";
if (value > 65535) {
value -= 65536;
output += stringFromCharCode(value >>> 10 & 1023 | 55296);
value = 56320 | value & 1023;
}
output += stringFromCharCode(value);
return output;
}).join("");
}
function basicToDigit(codePoint) {
if (codePoint - 48 < 10) {
return codePoint - 22;
}
if (codePoint - 65 < 26) {
return codePoint - 65;
}
if (codePoint - 97 < 26) {
return codePoint - 97;
}
return base;
}
function digitToBasic(digit, flag) {
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
}
function adapt(delta, numPoints, firstTime) {
var k = 0;
delta = firstTime ? floor(delta / damp) : delta >> 1;
delta += floor(delta / numPoints);
for (; delta > baseMinusTMin * tMax >> 1; k += base) {
delta = floor(delta / baseMinusTMin);
}
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
}
function decode(input) {
var output = [], inputLength = input.length, out, i = 0, n = initialN, bias = initialBias, basic, j, index, oldi, w, k, digit, t, baseMinusT;
basic = input.lastIndexOf(delimiter);
if (basic < 0) {
basic = 0;
}
for (j = 0; j < basic; ++j) {
if (input.charCodeAt(j) >= 128) {
error("not-basic");
}
output.push(input.charCodeAt(j));
}
for (index = basic > 0 ? basic + 1 : 0; index < inputLength; ) {
for (oldi = i, w = 1, k = base; ; k += base) {
if (index >= inputLength) {
error("invalid-input");
}
digit = basicToDigit(input.charCodeAt(index++));
if (digit >= base || digit > floor((maxInt - i) / w)) {
error("overflow");
}
i += digit * w;
t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
if (digit < t) {
break;
}
baseMinusT = base - t;
if (w > floor(maxInt / baseMinusT)) {
error("overflow");
}
w *= baseMinusT;
}
out = output.length + 1;
bias = adapt(i - oldi, out, oldi == 0);
if (floor(i / out) > maxInt - n) {
error("overflow");
}
n += floor(i / out);
i %= out;
output.splice(i++, 0, n);
}
return ucs2encode(output);
}
function encode(input) {
var n, delta, handledCPCount, basicLength, bias, j, m, q, k, t, currentValue, output = [], inputLength, handledCPCountPlusOne, baseMinusT, qMinusT;
input = ucs2decode(input);
inputLength = input.length;
n = initialN;
delta = 0;
bias = initialBias;
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < 128) {
output.push(stringFromCharCode(currentValue));
}
}
handledCPCount = basicLength = output.length;
if (basicLength) {
output.push(delimiter);
}
while (handledCPCount < inputLength) {
for (m = maxInt, j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue >= n && currentValue < m) {
m = currentValue;
}
}
handledCPCountPlusOne = handledCPCount + 1;
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
error("overflow");
}
delta += (m - n) * handledCPCountPlusOne;
n = m;
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < n && ++delta > maxInt) {
error("overflow");
}
if (currentValue == n) {
for (q = delta, k = base; ; k += base) {
t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
if (q < t) {
break;
}
qMinusT = q - t;
baseMinusT = base - t;
output.push(
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
);
q = floor(qMinusT / baseMinusT);
}
output.push(stringFromCharCode(digitToBasic(q, 0)));
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
delta = 0;
++handledCPCount;
}
}
++delta;
++n;
}
return output.join("");
}
function toUnicode(input) {
return mapDomain(input, function(string) {
return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string;
});
}
function toASCII(input) {
return mapDomain(input, function(string) {
return regexNonASCII.test(string) ? "xn--" + encode(string) : string;
});
}
punycode = {
/**
* A string representing the current Punycode.js version number.
* @memberOf punycode
* @type String
*/
"version": "1.3.2",
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to Unicode code points, and back.
* @see
* For best rendering performance, use the tightest possible bounding volume. Although
*
* When
* Draws the {@link DrawCommand#boundingVolume} for this command, assuming it is a sphere, when the command executes.
*
* Requires that the texture has a mipmap. The mip level is chosen by the view angle and screen-space size of the texture.
*
* Requires that the texture has a mipmap. The mip level is chosen by the view angle and screen-space size of the texture.
*
* This option provides a good balance of visual quality and speed when sampling from a mipmapped texture.
*
* Requires that the texture has a mipmap. The mip level is chosen by the view angle and screen-space size of the texture.
*
* This option provides a good balance of visual quality and speed when sampling from a mipmapped texture.
*
* Requires that the texture has a mipmap. The mip level is chosen by the view angle and screen-space size of the texture.
* \n * All color values (diffuse, specular, emissive) are in linear color space.\n * The conversion is described in\n * {@link http://content.gpwiki.org/index.php/D3DBook:High-Dynamic_Range_Rendering#Luminance_Transform|Luminance Transform}\n * The conversion is described in\n * {@link http://content.gpwiki.org/index.php/D3DBook:High-Dynamic_Range_Rendering#Luminance_Transform|Luminance Transform}\n * \n * This uses standard position attributes, \n * Use this version when passing in a custom pixel ratio. For example, passing in 1.0 will return meters per native device pixel.\n * \n * Use this version when scaling by pixel ratio.\n * \n * This function only handles the lighting calculations. Metallic/roughness\n * and specular/glossy must be handled separately. See {@MaterialStageFS}\n * \n * The order of the coefficients is [L00, L1_1, L10, L11, L2_2, L2_1, L20, L21, L22].\n * \n * This technique, called GPU RTE, eliminates jittering artifacts when using large coordinates as\n * described in {@link http://help.agi.com/AGIComponents/html/BlogPrecisionsPrecisions.htm|Precisions, Precisions}.\n * \n * There are also precision limitations in WebGL 1. highp int is still limited\n * to 24 bits. Above the value of 2^24 = 16777216, precision loss may occur.\n * \n * An example use case for this function would be moving the vertex in window coordinates\n * before converting back to clip coordinates. Use the original vertex clip coordinates.\n * \n * Use this when the vertex shader does not call {@link czm_vertexLogDepth}, for example, when\n * ray-casting geometry using a full screen quad.\n * \n * Use this when the vertex shader calls {@link czm_vertexLogDepth}.\n *
* x, y, width,
* and height properties in an vec4's x, y, z,
* and w components, respectively.
*
* @example
* // GLSL declaration
* uniform vec4 czm_viewport;
*
* // Scale the window coordinate components to [0, 1] by dividing
* // by the viewport's width and height.
* vec2 v = gl_FragCoord.xy / czm_viewport.zw;
*
* @see Context#getViewport
*/
czm_viewport: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC4,
getValue: function(uniformState) {
return uniformState.viewportCartesian4;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 orthographic projection matrix that
* transforms window coordinates to clip coordinates. Clip coordinates is the
* coordinate system for a vertex shader's gl_Position output.
*
* This transform is useful when a vertex shader inputs or manipulates window coordinates
* as done by {@link BillboardCollection}.
*
* Do not confuse {@link czm_viewportTransformation} with czm_viewportOrthographic.
* The former transforms from normalized device coordinates to window coordinates; the later transforms
* from window coordinates to clip coordinates, and is often used to assign to gl_Position.
*
* @example
* // GLSL declaration
* uniform mat4 czm_viewportOrthographic;
*
* // Example
* gl_Position = czm_viewportOrthographic * vec4(windowPosition, 0.0, 1.0);
*
* @see UniformState#viewportOrthographic
* @see czm_viewport
* @see czm_viewportTransformation
* @see BillboardCollection
*/
czm_viewportOrthographic: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.viewportOrthographic;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 transformation matrix that
* transforms normalized device coordinates to window coordinates. The context's
* full viewport is used, and the depth range is assumed to be near = 0
* and far = 1.
*
* This transform is useful when there is a need to manipulate window coordinates
* in a vertex shader as done by {@link BillboardCollection}. In many cases,
* this matrix will not be used directly; instead, {@link czm_modelToWindowCoordinates}
* will be used to transform directly from model to window coordinates.
*
* Do not confuse czm_viewportTransformation with {@link czm_viewportOrthographic}.
* The former transforms from normalized device coordinates to window coordinates; the later transforms
* from window coordinates to clip coordinates, and is often used to assign to gl_Position.
*
* @example
* // GLSL declaration
* uniform mat4 czm_viewportTransformation;
*
* // Use czm_viewportTransformation as part of the
* // transform from model to window coordinates.
* vec4 q = czm_modelViewProjection * positionMC; // model to clip coordinates
* q.xyz /= q.w; // clip to normalized device coordinates (ndc)
* q.xyz = (czm_viewportTransformation * vec4(q.xyz, 1.0)).xyz; // ndc to window coordinates
*
* @see UniformState#viewportTransformation
* @see czm_viewport
* @see czm_viewportOrthographic
* @see czm_modelToWindowCoordinates
* @see BillboardCollection
*/
czm_viewportTransformation: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.viewportTransformation;
}
}),
/**
* An automatic GLSL uniform representing the depth of the scene
* after the globe pass and then updated after the 3D Tiles pass.
* The depth is packed into an RGBA texture.
*
* @example
* // GLSL declaration
* uniform sampler2D czm_globeDepthTexture;
*
* // Get the depth at the current fragment
* vec2 coords = gl_FragCoord.xy / czm_viewport.zw;
* float depth = czm_unpackDepth(texture(czm_globeDepthTexture, coords));
*/
czm_globeDepthTexture: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.SAMPLER_2D,
getValue: function(uniformState) {
return uniformState.globeDepthTexture;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 model transformation matrix that
* transforms model coordinates to world coordinates.
*
* @example
* // GLSL declaration
* uniform mat4 czm_model;
*
* // Example
* vec4 worldPosition = czm_model * modelPosition;
*
* @see UniformState#model
* @see czm_inverseModel
* @see czm_modelView
* @see czm_modelViewProjection
*/
czm_model: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.model;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 model transformation matrix that
* transforms world coordinates to model coordinates.
*
* @example
* // GLSL declaration
* uniform mat4 czm_inverseModel;
*
* // Example
* vec4 modelPosition = czm_inverseModel * worldPosition;
*
* @see UniformState#inverseModel
* @see czm_model
* @see czm_inverseModelView
*/
czm_inverseModel: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.inverseModel;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 view transformation matrix that
* transforms world coordinates to eye coordinates.
*
* @example
* // GLSL declaration
* uniform mat4 czm_view;
*
* // Example
* vec4 eyePosition = czm_view * worldPosition;
*
* @see UniformState#view
* @see czm_viewRotation
* @see czm_modelView
* @see czm_viewProjection
* @see czm_modelViewProjection
* @see czm_inverseView
*/
czm_view: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.view;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 view transformation matrix that
* transforms 3D world coordinates to eye coordinates. In 3D mode, this is identical to
* {@link czm_view}, but in 2D and Columbus View it represents the view matrix
* as if the camera were at an equivalent location in 3D mode. This is useful for lighting
* 2D and Columbus View in the same way that 3D is lit.
*
* @example
* // GLSL declaration
* uniform mat4 czm_view3D;
*
* // Example
* vec4 eyePosition3D = czm_view3D * worldPosition3D;
*
* @see UniformState#view3D
* @see czm_view
*/
czm_view3D: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.view3D;
}
}),
/**
* An automatic GLSL uniform representing a 3x3 view rotation matrix that
* transforms vectors in world coordinates to eye coordinates.
*
* @example
* // GLSL declaration
* uniform mat3 czm_viewRotation;
*
* // Example
* vec3 eyeVector = czm_viewRotation * worldVector;
*
* @see UniformState#viewRotation
* @see czm_view
* @see czm_inverseView
* @see czm_inverseViewRotation
*/
czm_viewRotation: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT3,
getValue: function(uniformState) {
return uniformState.viewRotation;
}
}),
/**
* An automatic GLSL uniform representing a 3x3 view rotation matrix that
* transforms vectors in 3D world coordinates to eye coordinates. In 3D mode, this is identical to
* {@link czm_viewRotation}, but in 2D and Columbus View it represents the view matrix
* as if the camera were at an equivalent location in 3D mode. This is useful for lighting
* 2D and Columbus View in the same way that 3D is lit.
*
* @example
* // GLSL declaration
* uniform mat3 czm_viewRotation3D;
*
* // Example
* vec3 eyeVector = czm_viewRotation3D * worldVector;
*
* @see UniformState#viewRotation3D
* @see czm_viewRotation
*/
czm_viewRotation3D: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT3,
getValue: function(uniformState) {
return uniformState.viewRotation3D;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 transformation matrix that
* transforms from eye coordinates to world coordinates.
*
* @example
* // GLSL declaration
* uniform mat4 czm_inverseView;
*
* // Example
* vec4 worldPosition = czm_inverseView * eyePosition;
*
* @see UniformState#inverseView
* @see czm_view
* @see czm_inverseNormal
*/
czm_inverseView: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.inverseView;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 transformation matrix that
* transforms from 3D eye coordinates to world coordinates. In 3D mode, this is identical to
* {@link czm_inverseView}, but in 2D and Columbus View it represents the inverse view matrix
* as if the camera were at an equivalent location in 3D mode. This is useful for lighting
* 2D and Columbus View in the same way that 3D is lit.
*
* @example
* // GLSL declaration
* uniform mat4 czm_inverseView3D;
*
* // Example
* vec4 worldPosition = czm_inverseView3D * eyePosition;
*
* @see UniformState#inverseView3D
* @see czm_inverseView
*/
czm_inverseView3D: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.inverseView3D;
}
}),
/**
* An automatic GLSL uniform representing a 3x3 rotation matrix that
* transforms vectors from eye coordinates to world coordinates.
*
* @example
* // GLSL declaration
* uniform mat3 czm_inverseViewRotation;
*
* // Example
* vec4 worldVector = czm_inverseViewRotation * eyeVector;
*
* @see UniformState#inverseView
* @see czm_view
* @see czm_viewRotation
* @see czm_inverseViewRotation
*/
czm_inverseViewRotation: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT3,
getValue: function(uniformState) {
return uniformState.inverseViewRotation;
}
}),
/**
* An automatic GLSL uniform representing a 3x3 rotation matrix that
* transforms vectors from 3D eye coordinates to world coordinates. In 3D mode, this is identical to
* {@link czm_inverseViewRotation}, but in 2D and Columbus View it represents the inverse view matrix
* as if the camera were at an equivalent location in 3D mode. This is useful for lighting
* 2D and Columbus View in the same way that 3D is lit.
*
* @example
* // GLSL declaration
* uniform mat3 czm_inverseViewRotation3D;
*
* // Example
* vec4 worldVector = czm_inverseViewRotation3D * eyeVector;
*
* @see UniformState#inverseView3D
* @see czm_inverseViewRotation
*/
czm_inverseViewRotation3D: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT3,
getValue: function(uniformState) {
return uniformState.inverseViewRotation3D;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 projection transformation matrix that
* transforms eye coordinates to clip coordinates. Clip coordinates is the
* coordinate system for a vertex shader's gl_Position output.
*
* @example
* // GLSL declaration
* uniform mat4 czm_projection;
*
* // Example
* gl_Position = czm_projection * eyePosition;
*
* @see UniformState#projection
* @see czm_viewProjection
* @see czm_modelViewProjection
* @see czm_infiniteProjection
*/
czm_projection: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.projection;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 inverse projection transformation matrix that
* transforms from clip coordinates to eye coordinates. Clip coordinates is the
* coordinate system for a vertex shader's gl_Position output.
*
* @example
* // GLSL declaration
* uniform mat4 czm_inverseProjection;
*
* // Example
* vec4 eyePosition = czm_inverseProjection * clipPosition;
*
* @see UniformState#inverseProjection
* @see czm_projection
*/
czm_inverseProjection: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.inverseProjection;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 projection transformation matrix with the far plane at infinity,
* that transforms eye coordinates to clip coordinates. Clip coordinates is the
* coordinate system for a vertex shader's gl_Position output. An infinite far plane is used
* in algorithms like shadow volumes and GPU ray casting with proxy geometry to ensure that triangles
* are not clipped by the far plane.
*
* @example
* // GLSL declaration
* uniform mat4 czm_infiniteProjection;
*
* // Example
* gl_Position = czm_infiniteProjection * eyePosition;
*
* @see UniformState#infiniteProjection
* @see czm_projection
* @see czm_modelViewInfiniteProjection
*/
czm_infiniteProjection: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.infiniteProjection;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
* transforms model coordinates to eye coordinates.
*
* Positions should be transformed to eye coordinates using czm_modelView and
* normals should be transformed using {@link czm_normal}.
*
* @example
* // GLSL declaration
* uniform mat4 czm_modelView;
*
* // Example
* vec4 eyePosition = czm_modelView * modelPosition;
*
* // The above is equivalent to, but more efficient than:
* vec4 eyePosition = czm_view * czm_model * modelPosition;
*
* @see UniformState#modelView
* @see czm_model
* @see czm_view
* @see czm_modelViewProjection
* @see czm_normal
*/
czm_modelView: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.modelView;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
* transforms 3D model coordinates to eye coordinates. In 3D mode, this is identical to
* {@link czm_modelView}, but in 2D and Columbus View it represents the model-view matrix
* as if the camera were at an equivalent location in 3D mode. This is useful for lighting
* 2D and Columbus View in the same way that 3D is lit.
*
* Positions should be transformed to eye coordinates using czm_modelView3D and
* normals should be transformed using {@link czm_normal3D}.
*
* @example
* // GLSL declaration
* uniform mat4 czm_modelView3D;
*
* // Example
* vec4 eyePosition = czm_modelView3D * modelPosition;
*
* // The above is equivalent to, but more efficient than:
* vec4 eyePosition = czm_view3D * czm_model * modelPosition;
*
* @see UniformState#modelView3D
* @see czm_modelView
*/
czm_modelView3D: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.modelView3D;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 model-view transformation matrix that
* transforms model coordinates, relative to the eye, to eye coordinates. This is used
* in conjunction with {@link czm_translateRelativeToEye}.
*
* @example
* // GLSL declaration
* uniform mat4 czm_modelViewRelativeToEye;
*
* // Example
* attribute vec3 positionHigh;
* attribute vec3 positionLow;
*
* void main()
* {
* vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
* gl_Position = czm_projection * (czm_modelViewRelativeToEye * p);
* }
*
* @see czm_modelViewProjectionRelativeToEye
* @see czm_translateRelativeToEye
* @see EncodedCartesian3
*/
czm_modelViewRelativeToEye: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.modelViewRelativeToEye;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 transformation matrix that
* transforms from eye coordinates to model coordinates.
*
* @example
* // GLSL declaration
* uniform mat4 czm_inverseModelView;
*
* // Example
* vec4 modelPosition = czm_inverseModelView * eyePosition;
*
* @see UniformState#inverseModelView
* @see czm_modelView
*/
czm_inverseModelView: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.inverseModelView;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 transformation matrix that
* transforms from eye coordinates to 3D model coordinates. In 3D mode, this is identical to
* {@link czm_inverseModelView}, but in 2D and Columbus View it represents the inverse model-view matrix
* as if the camera were at an equivalent location in 3D mode. This is useful for lighting
* 2D and Columbus View in the same way that 3D is lit.
*
* @example
* // GLSL declaration
* uniform mat4 czm_inverseModelView3D;
*
* // Example
* vec4 modelPosition = czm_inverseModelView3D * eyePosition;
*
* @see UniformState#inverseModelView
* @see czm_inverseModelView
* @see czm_modelView3D
*/
czm_inverseModelView3D: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.inverseModelView3D;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that
* transforms world coordinates to clip coordinates. Clip coordinates is the
* coordinate system for a vertex shader's gl_Position output.
*
* @example
* // GLSL declaration
* uniform mat4 czm_viewProjection;
*
* // Example
* vec4 gl_Position = czm_viewProjection * czm_model * modelPosition;
*
* // The above is equivalent to, but more efficient than:
* gl_Position = czm_projection * czm_view * czm_model * modelPosition;
*
* @see UniformState#viewProjection
* @see czm_view
* @see czm_projection
* @see czm_modelViewProjection
* @see czm_inverseViewProjection
*/
czm_viewProjection: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.viewProjection;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that
* transforms clip coordinates to world coordinates. Clip coordinates is the
* coordinate system for a vertex shader's gl_Position output.
*
* @example
* // GLSL declaration
* uniform mat4 czm_inverseViewProjection;
*
* // Example
* vec4 worldPosition = czm_inverseViewProjection * clipPosition;
*
* @see UniformState#inverseViewProjection
* @see czm_viewProjection
*/
czm_inverseViewProjection: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.inverseViewProjection;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
* transforms model coordinates to clip coordinates. Clip coordinates is the
* coordinate system for a vertex shader's gl_Position output.
*
* @example
* // GLSL declaration
* uniform mat4 czm_modelViewProjection;
*
* // Example
* vec4 gl_Position = czm_modelViewProjection * modelPosition;
*
* // The above is equivalent to, but more efficient than:
* gl_Position = czm_projection * czm_view * czm_model * modelPosition;
*
* @see UniformState#modelViewProjection
* @see czm_model
* @see czm_view
* @see czm_projection
* @see czm_modelView
* @see czm_viewProjection
* @see czm_modelViewInfiniteProjection
* @see czm_inverseModelViewProjection
*/
czm_modelViewProjection: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.modelViewProjection;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 inverse model-view-projection transformation matrix that
* transforms clip coordinates to model coordinates. Clip coordinates is the
* coordinate system for a vertex shader's gl_Position output.
*
* @example
* // GLSL declaration
* uniform mat4 czm_inverseModelViewProjection;
*
* // Example
* vec4 modelPosition = czm_inverseModelViewProjection * clipPosition;
*
* @see UniformState#modelViewProjection
* @see czm_modelViewProjection
*/
czm_inverseModelViewProjection: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.inverseModelViewProjection;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
* transforms model coordinates, relative to the eye, to clip coordinates. Clip coordinates is the
* coordinate system for a vertex shader's gl_Position output. This is used in
* conjunction with {@link czm_translateRelativeToEye}.
*
* @example
* // GLSL declaration
* uniform mat4 czm_modelViewProjectionRelativeToEye;
*
* // Example
* attribute vec3 positionHigh;
* attribute vec3 positionLow;
*
* void main()
* {
* vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
* gl_Position = czm_modelViewProjectionRelativeToEye * p;
* }
*
* @see czm_modelViewRelativeToEye
* @see czm_translateRelativeToEye
* @see EncodedCartesian3
*/
czm_modelViewProjectionRelativeToEye: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.modelViewProjectionRelativeToEye;
}
}),
/**
* An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that
* transforms model coordinates to clip coordinates. Clip coordinates is the
* coordinate system for a vertex shader's gl_Position output. The projection matrix places
* the far plane at infinity. This is useful in algorithms like shadow volumes and GPU ray casting with
* proxy geometry to ensure that triangles are not clipped by the far plane.
*
* @example
* // GLSL declaration
* uniform mat4 czm_modelViewInfiniteProjection;
*
* // Example
* vec4 gl_Position = czm_modelViewInfiniteProjection * modelPosition;
*
* // The above is equivalent to, but more efficient than:
* gl_Position = czm_infiniteProjection * czm_view * czm_model * modelPosition;
*
* @see UniformState#modelViewInfiniteProjection
* @see czm_model
* @see czm_view
* @see czm_infiniteProjection
* @see czm_modelViewProjection
*/
czm_modelViewInfiniteProjection: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.modelViewInfiniteProjection;
}
}),
/**
* An automatic GLSL uniform that indicates if the current camera is orthographic in 3D.
*
* @see UniformState#orthographicIn3D
*/
czm_orthographicIn3D: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.orthographicIn3D ? 1 : 0;
}
}),
/**
* An automatic GLSL uniform representing a 3x3 normal transformation matrix that
* transforms normal vectors in model coordinates to eye coordinates.
*
* Positions should be transformed to eye coordinates using {@link czm_modelView} and
* normals should be transformed using czm_normal.
*
* @example
* // GLSL declaration
* uniform mat3 czm_normal;
*
* // Example
* vec3 eyeNormal = czm_normal * normal;
*
* @see UniformState#normal
* @see czm_inverseNormal
* @see czm_modelView
*/
czm_normal: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT3,
getValue: function(uniformState) {
return uniformState.normal;
}
}),
/**
* An automatic GLSL uniform representing a 3x3 normal transformation matrix that
* transforms normal vectors in 3D model coordinates to eye coordinates.
* In 3D mode, this is identical to
* {@link czm_normal}, but in 2D and Columbus View it represents the normal transformation
* matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting
* 2D and Columbus View in the same way that 3D is lit.
*
* Positions should be transformed to eye coordinates using {@link czm_modelView3D} and
* normals should be transformed using czm_normal3D.
*
* @example
* // GLSL declaration
* uniform mat3 czm_normal3D;
*
* // Example
* vec3 eyeNormal = czm_normal3D * normal;
*
* @see UniformState#normal3D
* @see czm_normal
*/
czm_normal3D: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT3,
getValue: function(uniformState) {
return uniformState.normal3D;
}
}),
/**
* An automatic GLSL uniform representing a 3x3 normal transformation matrix that
* transforms normal vectors in eye coordinates to model coordinates. This is
* the opposite of the transform provided by {@link czm_normal}.
*
* @example
* // GLSL declaration
* uniform mat3 czm_inverseNormal;
*
* // Example
* vec3 normalMC = czm_inverseNormal * normalEC;
*
* @see UniformState#inverseNormal
* @see czm_normal
* @see czm_modelView
* @see czm_inverseView
*/
czm_inverseNormal: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT3,
getValue: function(uniformState) {
return uniformState.inverseNormal;
}
}),
/**
* An automatic GLSL uniform representing a 3x3 normal transformation matrix that
* transforms normal vectors in eye coordinates to 3D model coordinates. This is
* the opposite of the transform provided by {@link czm_normal}.
* In 3D mode, this is identical to
* {@link czm_inverseNormal}, but in 2D and Columbus View it represents the inverse normal transformation
* matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting
* 2D and Columbus View in the same way that 3D is lit.
*
* @example
* // GLSL declaration
* uniform mat3 czm_inverseNormal3D;
*
* // Example
* vec3 normalMC = czm_inverseNormal3D * normalEC;
*
* @see UniformState#inverseNormal3D
* @see czm_inverseNormal
*/
czm_inverseNormal3D: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT3,
getValue: function(uniformState) {
return uniformState.inverseNormal3D;
}
}),
/**
* An automatic GLSL uniform containing the height in meters of the
* eye (camera) above or below the ellipsoid.
*
* @see UniformState#eyeHeight
*/
czm_eyeHeight: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.eyeHeight;
}
}),
/**
* An automatic GLSL uniform containing height (x) and height squared (y)
* in meters of the eye (camera) above the 2D world plane. This uniform is only valid
* when the {@link SceneMode} is SCENE2D.
*
* @see UniformState#eyeHeight2D
*/
czm_eyeHeight2D: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC2,
getValue: function(uniformState) {
return uniformState.eyeHeight2D;
}
}),
/**
* An automatic GLSL uniform containing the ellipsoid surface normal
* at the position below the eye (camera), in eye coordinates.
* This uniform is only valid when the {@link SceneMode} is SCENE3D.
*/
czm_eyeEllipsoidNormalEC: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.eyeEllipsoidNormalEC;
}
}),
/**
* An automatic GLSL uniform containing the ellipsoid radii of curvature at the camera position.
* The .x component is the prime vertical radius of curvature (east-west direction)
* .y is the meridional radius of curvature (north-south direction)
* This uniform is only valid when the {@link SceneMode} is SCENE3D.
*/
czm_eyeEllipsoidCurvature: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC2,
getValue: function(uniformState) {
return uniformState.eyeEllipsoidCurvature;
}
}),
/**
* An automatic GLSL uniform containing the transform from model coordinates
* to an east-north-up coordinate system centered at the position on the
* ellipsoid below the camera.
* This uniform is only valid when the {@link SceneMode} is SCENE3D.
*/
czm_modelToEnu: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.modelToEnu;
}
}),
/**
* An automatic GLSL uniform containing the the inverse of
* {@link AutomaticUniforms.czm_modelToEnu}.
* This uniform is only valid when the {@link SceneMode} is SCENE3D.
*/
czm_enuToModel: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT4,
getValue: function(uniformState) {
return uniformState.enuToModel;
}
}),
/**
* An automatic GLSL uniform containing the near distance (x) and the far distance (y)
* of the frustum defined by the camera. This is the largest possible frustum, not an individual
* frustum used for multi-frustum rendering.
*
* @example
* // GLSL declaration
* uniform vec2 czm_entireFrustum;
*
* // Example
* float frustumLength = czm_entireFrustum.y - czm_entireFrustum.x;
*
* @see UniformState#entireFrustum
* @see czm_currentFrustum
*/
czm_entireFrustum: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC2,
getValue: function(uniformState) {
return uniformState.entireFrustum;
}
}),
/**
* An automatic GLSL uniform containing the near distance (x) and the far distance (y)
* of the frustum defined by the camera. This is the individual
* frustum used for multi-frustum rendering.
*
* @example
* // GLSL declaration
* uniform vec2 czm_currentFrustum;
*
* // Example
* float frustumLength = czm_currentFrustum.y - czm_currentFrustum.x;
*
* @see UniformState#currentFrustum
* @see czm_entireFrustum
*/
czm_currentFrustum: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC2,
getValue: function(uniformState) {
return uniformState.currentFrustum;
}
}),
/**
* The distances to the frustum planes. The top, bottom, left and right distances are
* the x, y, z, and w components, respectively.
*/
czm_frustumPlanes: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC4,
getValue: function(uniformState) {
return uniformState.frustumPlanes;
}
}),
/**
* Gets the far plane's distance from the near plane, plus 1.0.
*/
czm_farDepthFromNearPlusOne: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.farDepthFromNearPlusOne;
}
}),
/**
* Gets the log2 of {@link AutomaticUniforms#czm_farDepthFromNearPlusOne}.
*/
czm_log2FarDepthFromNearPlusOne: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.log2FarDepthFromNearPlusOne;
}
}),
/**
* Gets 1.0 divided by {@link AutomaticUniforms#czm_log2FarDepthFromNearPlusOne}.
*/
czm_oneOverLog2FarDepthFromNearPlusOne: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.oneOverLog2FarDepthFromNearPlusOne;
}
}),
/**
* An automatic GLSL uniform representing the sun position in world coordinates.
*
* @example
* // GLSL declaration
* uniform vec3 czm_sunPositionWC;
*
* @see UniformState#sunPositionWC
* @see czm_sunPositionColumbusView
* @see czm_sunDirectionWC
*/
czm_sunPositionWC: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.sunPositionWC;
}
}),
/**
* An automatic GLSL uniform representing the sun position in Columbus view world coordinates.
*
* @example
* // GLSL declaration
* uniform vec3 czm_sunPositionColumbusView;
*
* @see UniformState#sunPositionColumbusView
* @see czm_sunPositionWC
*/
czm_sunPositionColumbusView: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.sunPositionColumbusView;
}
}),
/**
* An automatic GLSL uniform representing the normalized direction to the sun in eye coordinates.
*
* @example
* // GLSL declaration
* uniform vec3 czm_sunDirectionEC;
*
* // Example
* float diffuse = max(dot(czm_sunDirectionEC, normalEC), 0.0);
*
* @see UniformState#sunDirectionEC
* @see czm_moonDirectionEC
* @see czm_sunDirectionWC
*/
czm_sunDirectionEC: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.sunDirectionEC;
}
}),
/**
* An automatic GLSL uniform representing the normalized direction to the sun in world coordinates.
*
* @example
* // GLSL declaration
* uniform vec3 czm_sunDirectionWC;
*
* // Example
* float diffuse = max(dot(czm_sunDirectionWC, normalWC), 0.0);
*
* @see UniformState#sunDirectionWC
* @see czm_sunPositionWC
* @see czm_sunDirectionEC
*/
czm_sunDirectionWC: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.sunDirectionWC;
}
}),
/**
* An automatic GLSL uniform representing the normalized direction to the moon in eye coordinates.
*
* @example
* // GLSL declaration
* uniform vec3 czm_moonDirectionEC;
*
* // Example
* float diffuse = max(dot(czm_moonDirectionEC, normalEC), 0.0);
*
* @see UniformState#moonDirectionEC
* @see czm_sunDirectionEC
*/
czm_moonDirectionEC: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.moonDirectionEC;
}
}),
/**
* An automatic GLSL uniform representing the normalized direction to the scene's light source in eye coordinates.
* This is commonly used for directional lighting computations.
*
* @example
* // GLSL declaration
* uniform vec3 czm_lightDirectionEC;
*
* // Example
* float diffuse = max(dot(czm_lightDirectionEC, normalEC), 0.0);
*
* @see UniformState#lightDirectionEC
* @see czm_lightDirectionWC
*/
czm_lightDirectionEC: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.lightDirectionEC;
}
}),
/**
* An automatic GLSL uniform representing the normalized direction to the scene's light source in world coordinates.
* This is commonly used for directional lighting computations.
*
* @example
* // GLSL declaration
* uniform vec3 czm_lightDirectionWC;
*
* // Example
* float diffuse = max(dot(czm_lightDirectionWC, normalWC), 0.0);
*
* @see UniformState#lightDirectionWC
* @see czm_lightDirectionEC
*/
czm_lightDirectionWC: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.lightDirectionWC;
}
}),
/**
* An automatic GLSL uniform that represents the color of light emitted by the scene's light source. This
* is equivalent to the light color multiplied by the light intensity limited to a maximum luminance of 1.0
* suitable for non-HDR lighting.
*
* @example
* // GLSL declaration
* uniform vec3 czm_lightColor;
*
* // Example
* vec3 diffuseColor = czm_lightColor * max(dot(czm_lightDirectionWC, normalWC), 0.0);
*
* @see UniformState#lightColor
* @see czm_lightColorHdr
*/
czm_lightColor: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.lightColor;
}
}),
/**
* An automatic GLSL uniform that represents the high dynamic range color of light emitted by the scene's light
* source. This is equivalent to the light color multiplied by the light intensity suitable for HDR lighting.
*
* @example
* // GLSL declaration
* uniform vec3 czm_lightColorHdr;
*
* // Example
* vec3 diffuseColor = czm_lightColorHdr * max(dot(czm_lightDirectionWC, normalWC), 0.0);
*
* @see UniformState#lightColorHdr
* @see czm_lightColor
*/
czm_lightColorHdr: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.lightColorHdr;
}
}),
/**
* An automatic GLSL uniform representing the high bits of the camera position in model
* coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering
* as described in {@link http://help.agi.com/AGIComponents/html/BlogPrecisionsPrecisions.htm|Precisions, Precisions}.
*
* @example
* // GLSL declaration
* uniform vec3 czm_encodedCameraPositionMCHigh;
*
* @see czm_encodedCameraPositionMCLow
* @see czm_modelViewRelativeToEye
* @see czm_modelViewProjectionRelativeToEye
*/
czm_encodedCameraPositionMCHigh: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.encodedCameraPositionMCHigh;
}
}),
/**
* An automatic GLSL uniform representing the low bits of the camera position in model
* coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering
* as described in {@linkhttp://help.agi.com/AGIComponents/html/BlogPrecisionsPrecisions.htm|Precisions, Precisions}.
*
* @example
* // GLSL declaration
* uniform vec3 czm_encodedCameraPositionMCLow;
*
* @see czm_encodedCameraPositionMCHigh
* @see czm_modelViewRelativeToEye
* @see czm_modelViewProjectionRelativeToEye
*/
czm_encodedCameraPositionMCLow: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.encodedCameraPositionMCLow;
}
}),
/**
* An automatic GLSL uniform representing the position of the viewer (camera) in world coordinates.
*
* @example
* // GLSL declaration
* uniform vec3 czm_viewerPositionWC;
*/
czm_viewerPositionWC: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return Matrix4_default.getTranslation(
uniformState.inverseView,
viewerPositionWCScratch
);
}
}),
/**
* An automatic GLSL uniform representing the frame number. This uniform is automatically incremented
* every frame.
*
* @example
* // GLSL declaration
* uniform float czm_frameNumber;
*/
czm_frameNumber: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.frameState.frameNumber;
}
}),
/**
* An automatic GLSL uniform representing the current morph transition time between
* 2D/Columbus View and 3D, with 0.0 being 2D or Columbus View and 1.0 being 3D.
*
* @example
* // GLSL declaration
* uniform float czm_morphTime;
*
* // Example
* vec4 p = czm_columbusViewMorph(position2D, position3D, czm_morphTime);
*/
czm_morphTime: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.frameState.morphTime;
}
}),
/**
* An automatic GLSL uniform representing the current {@link SceneMode}, expressed
* as a float.
*
* @example
* // GLSL declaration
* uniform float czm_sceneMode;
*
* // Example
* if (czm_sceneMode == czm_sceneMode2D)
* {
* eyeHeightSq = czm_eyeHeight2D.y;
* }
*
* @see czm_sceneMode2D
* @see czm_sceneModeColumbusView
* @see czm_sceneMode3D
* @see czm_sceneModeMorphing
*/
czm_sceneMode: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.frameState.mode;
}
}),
/**
* An automatic GLSL uniform representing the current rendering pass.
*
* @example
* // GLSL declaration
* uniform float czm_pass;
*
* // Example
* if ((czm_pass == czm_passTranslucent) && isOpaque())
* {
* gl_Position *= 0.0; // Cull opaque geometry in the translucent pass
* }
*/
czm_pass: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.pass;
}
}),
/**
* An automatic GLSL uniform representing the current scene background color.
*
* @example
* // GLSL declaration
* uniform vec4 czm_backgroundColor;
*
* // Example: If the given color's RGB matches the background color, invert it.
* vec4 adjustColorForContrast(vec4 color)
* {
* if (czm_backgroundColor.rgb == color.rgb)
* {
* color.rgb = vec3(1.0) - color.rgb;
* }
*
* return color;
* }
*/
czm_backgroundColor: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC4,
getValue: function(uniformState) {
return uniformState.backgroundColor;
}
}),
/**
* An automatic GLSL uniform containing the BRDF look up texture used for image-based lighting computations.
*
* @example
* // GLSL declaration
* uniform sampler2D czm_brdfLut;
*
* // Example: For a given roughness and NdotV value, find the material's BRDF information in the red and green channels
* float roughness = 0.5;
* float NdotV = dot(normal, view);
* vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg;
*/
czm_brdfLut: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.SAMPLER_2D,
getValue: function(uniformState) {
return uniformState.brdfLut;
}
}),
/**
* An automatic GLSL uniform containing the environment map used within the scene.
*
* @example
* // GLSL declaration
* uniform samplerCube czm_environmentMap;
*
* // Example: Create a perfect reflection of the environment map on a model
* float reflected = reflect(view, normal);
* vec4 reflectedColor = texture(czm_environmentMap, reflected);
*/
czm_environmentMap: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.SAMPLER_CUBE,
getValue: function(uniformState) {
return uniformState.environmentMap;
}
}),
/**
* An automatic GLSL uniform containing the specular environment cube map used within the scene.
*
* @example
* // GLSL declaration
* uniform samplerCube czm_specularEnvironmentMaps;
*/
czm_specularEnvironmentMaps: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.SAMPLER_CUBE,
getValue: function(uniformState) {
return uniformState.specularEnvironmentMaps;
}
}),
/**
* An automatic GLSL uniform containing the maximum valid level-of-detail of the specular environment cube map used within the scene.
*
* @example
* // GLSL declaration
* uniform float czm_specularEnvironmentMapsMaximumLOD;
*/
czm_specularEnvironmentMapsMaximumLOD: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.specularEnvironmentMapsMaximumLOD;
}
}),
/**
* An automatic GLSL uniform containing the spherical harmonic coefficients used within the scene.
*
* @example
* // GLSL declaration
* uniform vec3[9] czm_sphericalHarmonicCoefficients;
*/
czm_sphericalHarmonicCoefficients: new AutomaticUniform({
size: 9,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.sphericalHarmonicCoefficients;
}
}),
/**
* An automatic GLSL uniform representing a 3x3 rotation matrix that transforms
* from True Equator Mean Equinox (TEME) axes to the pseudo-fixed axes at the current scene time.
*
* @example
* // GLSL declaration
* uniform mat3 czm_temeToPseudoFixed;
*
* // Example
* vec3 pseudoFixed = czm_temeToPseudoFixed * teme;
*
* @see UniformState#temeToPseudoFixedMatrix
* @see Transforms.computeTemeToPseudoFixedMatrix
*/
czm_temeToPseudoFixed: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_MAT3,
getValue: function(uniformState) {
return uniformState.temeToPseudoFixedMatrix;
}
}),
/**
* An automatic GLSL uniform representing the ratio of canvas coordinate space to canvas pixel space.
*
* @example
* uniform float czm_pixelRatio;
*/
czm_pixelRatio: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.pixelRatio;
}
}),
/**
* An automatic GLSL uniform scalar used to mix a color with the fog color based on the distance to the camera.
*
* @see czm_fog
*/
czm_fogDensity: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.fogDensity;
}
}),
/**
* An automatic GLSL uniform scalar used to mix a color with the fog color based on the distance to the camera.
*
* @see czm_fog
*/
czm_fogVisualDensityScalar: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.fogVisualDensityScalar;
}
}),
/**
* An automatic GLSL uniform scalar used to set a minimum brightness when dynamic lighting is applied to fog.
*
* @see czm_fog
*/
czm_fogMinimumBrightness: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.fogMinimumBrightness;
}
}),
/**
* An automatic uniform representing the color shift for the atmosphere in HSB color space
*
* @example
* uniform vec3 czm_atmosphereHsbShift;
*/
czm_atmosphereHsbShift: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.atmosphereHsbShift;
}
}),
/**
* An automatic uniform representing the intensity of the light that is used for computing the atmosphere color
*
* @example
* uniform float czm_atmosphereLightIntensity;
*/
czm_atmosphereLightIntensity: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.atmosphereLightIntensity;
}
}),
/**
* An automatic uniform representing the Rayleigh scattering coefficient used when computing the atmosphere scattering
*
* @example
* uniform vec3 czm_atmosphereRayleighCoefficient;
*/
czm_atmosphereRayleighCoefficient: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.atmosphereRayleighCoefficient;
}
}),
/**
* An automatic uniform representing the Rayleigh scale height in meters used for computing atmosphere scattering.
*
* @example
* uniform vec3 czm_atmosphereRayleighScaleHeight;
*/
czm_atmosphereRayleighScaleHeight: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.atmosphereRayleighScaleHeight;
}
}),
/**
* An automatic uniform representing the Mie scattering coefficient used when computing atmosphere scattering.
*
* @example
* uniform vec3 czm_atmosphereMieCoefficient;
*/
czm_atmosphereMieCoefficient: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.atmosphereMieCoefficient;
}
}),
/**
* An automatic uniform storign the Mie scale height used when computing atmosphere scattering.
*
* @example
* uniform float czm_atmosphereMieScaleHeight;
*/
czm_atmosphereMieScaleHeight: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.atmosphereMieScaleHeight;
}
}),
/**
* An automatic uniform representing the anisotropy of the medium to consider for Mie scattering.
*
* @example
* uniform float czm_atmosphereAnisotropy;
*/
czm_atmosphereMieAnisotropy: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.atmosphereMieAnisotropy;
}
}),
/**
* An automatic uniform representing which light source to use for dynamic lighting
*
* @example
* uniform float czm_atmosphereDynamicLighting
*/
czm_atmosphereDynamicLighting: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.atmosphereDynamicLighting;
}
}),
/**
* An automatic GLSL uniform representing the splitter position to use when rendering with a splitter.
* This will be in pixel coordinates relative to the canvas.
*
* @example
* // GLSL declaration
* uniform float czm_splitPosition;
*/
czm_splitPosition: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.splitPosition;
}
}),
/**
* An automatic GLSL uniform scalar representing the geometric tolerance per meter
*/
czm_geometricToleranceOverMeter: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.geometricToleranceOverMeter;
}
}),
/**
* An automatic GLSL uniform representing the distance from the camera at which to disable the depth test of billboards, labels and points
* to, for example, prevent clipping against terrain. When set to zero, the depth test should always be applied. When less than zero,
* the depth test should never be applied.
*/
czm_minimumDisableDepthTestDistance: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.minimumDisableDepthTestDistance;
}
}),
/**
* An automatic GLSL uniform that will be the highlight color of unclassified 3D Tiles.
*/
czm_invertClassificationColor: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC4,
getValue: function(uniformState) {
return uniformState.invertClassificationColor;
}
}),
/**
* An automatic GLSL uniform that is used for gamma correction.
*/
czm_gamma: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT,
getValue: function(uniformState) {
return uniformState.gamma;
}
}),
/**
* An automatic GLSL uniform that stores the ellipsoid radii.
*/
czm_ellipsoidRadii: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.ellipsoid.radii;
}
}),
/**
* An automatic GLSL uniform that stores the ellipsoid inverse radii.
*/
czm_ellipsoidInverseRadii: new AutomaticUniform({
size: 1,
datatype: WebGLConstants_default.FLOAT_VEC3,
getValue: function(uniformState) {
return uniformState.ellipsoid.oneOverRadii;
}
})
};
var AutomaticUniforms_default = AutomaticUniforms;
// packages/engine/Source/Renderer/Buffer.js
var import_InlineWorkers17 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/createGuid.js
var import_InlineWorkers13 = __toESM(require_InlineWorkers(), 1);
function createGuid() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v3 = c === "x" ? r : r & 3 | 8;
return v3.toString(16);
});
}
var createGuid_default = createGuid;
// packages/engine/Source/Core/destroyObject.js
var import_InlineWorkers14 = __toESM(require_InlineWorkers(), 1);
function returnTrue() {
return true;
}
function destroyObject(object2, message) {
message = message ?? "This object was destroyed, i.e., destroy() was called.";
function throwOnDestroyed() {
throw new DeveloperError_default(message);
}
for (const key in object2) {
if (typeof object2[key] === "function") {
object2[key] = throwOnDestroyed;
}
}
object2.isDestroyed = returnTrue;
return void 0;
}
var destroyObject_default = destroyObject;
// packages/engine/Source/Core/IndexDatatype.js
var import_InlineWorkers15 = __toESM(require_InlineWorkers(), 1);
var IndexDatatype = {
/**
* 8-bit unsigned byte corresponding to UNSIGNED_BYTE and the type
* of an element in Uint8Array.
*
* @type {number}
* @constant
*/
UNSIGNED_BYTE: WebGLConstants_default.UNSIGNED_BYTE,
/**
* 16-bit unsigned short corresponding to UNSIGNED_SHORT and the type
* of an element in Uint16Array.
*
* @type {number}
* @constant
*/
UNSIGNED_SHORT: WebGLConstants_default.UNSIGNED_SHORT,
/**
* 32-bit unsigned int corresponding to UNSIGNED_INT and the type
* of an element in Uint32Array.
*
* @type {number}
* @constant
*/
UNSIGNED_INT: WebGLConstants_default.UNSIGNED_INT
};
IndexDatatype.getSizeInBytes = function(indexDatatype) {
switch (indexDatatype) {
case IndexDatatype.UNSIGNED_BYTE:
return Uint8Array.BYTES_PER_ELEMENT;
case IndexDatatype.UNSIGNED_SHORT:
return Uint16Array.BYTES_PER_ELEMENT;
case IndexDatatype.UNSIGNED_INT:
return Uint32Array.BYTES_PER_ELEMENT;
}
throw new DeveloperError_default(
"indexDatatype is required and must be a valid IndexDatatype constant."
);
};
IndexDatatype.fromSizeInBytes = function(sizeInBytes) {
switch (sizeInBytes) {
case 2:
return IndexDatatype.UNSIGNED_SHORT;
case 4:
return IndexDatatype.UNSIGNED_INT;
case 1:
return IndexDatatype.UNSIGNED_BYTE;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default(
"Size in bytes cannot be mapped to an IndexDatatype"
);
}
};
IndexDatatype.validate = function(indexDatatype) {
return defined_default(indexDatatype) && (indexDatatype === IndexDatatype.UNSIGNED_BYTE || indexDatatype === IndexDatatype.UNSIGNED_SHORT || indexDatatype === IndexDatatype.UNSIGNED_INT);
};
IndexDatatype.createTypedArray = function(numberOfVertices, indicesLengthOrArray) {
if (!defined_default(numberOfVertices)) {
throw new DeveloperError_default("numberOfVertices is required.");
}
if (numberOfVertices >= Math_default.SIXTY_FOUR_KILOBYTES) {
return new Uint32Array(indicesLengthOrArray);
}
return new Uint16Array(indicesLengthOrArray);
};
IndexDatatype.createTypedArrayFromArrayBuffer = function(numberOfVertices, sourceArray, byteOffset, length2) {
if (!defined_default(numberOfVertices)) {
throw new DeveloperError_default("numberOfVertices is required.");
}
if (!defined_default(sourceArray)) {
throw new DeveloperError_default("sourceArray is required.");
}
if (!defined_default(byteOffset)) {
throw new DeveloperError_default("byteOffset is required.");
}
if (numberOfVertices >= Math_default.SIXTY_FOUR_KILOBYTES) {
return new Uint32Array(sourceArray, byteOffset, length2);
}
return new Uint16Array(sourceArray, byteOffset, length2);
};
IndexDatatype.fromTypedArray = function(array) {
if (array instanceof Uint8Array) {
return IndexDatatype.UNSIGNED_BYTE;
}
if (array instanceof Uint16Array) {
return IndexDatatype.UNSIGNED_SHORT;
}
if (array instanceof Uint32Array) {
return IndexDatatype.UNSIGNED_INT;
}
throw new DeveloperError_default(
"array must be a Uint8Array, Uint16Array, or Uint32Array."
);
};
var IndexDatatype_default = Object.freeze(IndexDatatype);
// packages/engine/Source/Renderer/BufferUsage.js
var import_InlineWorkers16 = __toESM(require_InlineWorkers(), 1);
var BufferUsage = {
STREAM_DRAW: WebGLConstants_default.STREAM_DRAW,
STATIC_DRAW: WebGLConstants_default.STATIC_DRAW,
DYNAMIC_DRAW: WebGLConstants_default.DYNAMIC_DRAW,
validate: function(bufferUsage) {
return bufferUsage === BufferUsage.STREAM_DRAW || bufferUsage === BufferUsage.STATIC_DRAW || bufferUsage === BufferUsage.DYNAMIC_DRAW;
}
};
var BufferUsage_default = Object.freeze(BufferUsage);
// packages/engine/Source/Renderer/Buffer.js
function Buffer2(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.defined("options.context", options.context);
if (!defined_default(options.typedArray) && !defined_default(options.sizeInBytes)) {
throw new DeveloperError_default(
"Either options.sizeInBytes or options.typedArray is required."
);
}
if (defined_default(options.typedArray) && defined_default(options.sizeInBytes)) {
throw new DeveloperError_default(
"Cannot pass in both options.sizeInBytes and options.typedArray."
);
}
if (defined_default(options.typedArray)) {
Check_default.typeOf.object("options.typedArray", options.typedArray);
Check_default.typeOf.number(
"options.typedArray.byteLength",
options.typedArray.byteLength
);
}
if (!BufferUsage_default.validate(options.usage)) {
throw new DeveloperError_default("usage is invalid.");
}
const gl = options.context._gl;
const bufferTarget = options.bufferTarget;
const typedArray = options.typedArray;
let sizeInBytes = options.sizeInBytes;
const usage = options.usage;
const hasArray = defined_default(typedArray);
if (hasArray) {
sizeInBytes = typedArray.byteLength;
}
Check_default.typeOf.number.greaterThan("sizeInBytes", sizeInBytes, 0);
const buffer2 = gl.createBuffer();
gl.bindBuffer(bufferTarget, buffer2);
gl.bufferData(bufferTarget, hasArray ? typedArray : sizeInBytes, usage);
gl.bindBuffer(bufferTarget, null);
this._id = createGuid_default();
this._gl = gl;
this._webgl2 = options.context._webgl2;
this._bufferTarget = bufferTarget;
this._sizeInBytes = sizeInBytes;
this._usage = usage;
this._buffer = buffer2;
this.vertexArrayDestroyable = true;
}
Buffer2.createVertexBuffer = function(options) {
Check_default.defined("options.context", options.context);
return new Buffer2({
context: options.context,
bufferTarget: WebGLConstants_default.ARRAY_BUFFER,
typedArray: options.typedArray,
sizeInBytes: options.sizeInBytes,
usage: options.usage
});
};
Buffer2.createIndexBuffer = function(options) {
Check_default.defined("options.context", options.context);
if (!IndexDatatype_default.validate(options.indexDatatype)) {
throw new DeveloperError_default("Invalid indexDatatype.");
}
if (options.indexDatatype === IndexDatatype_default.UNSIGNED_INT && !options.context.elementIndexUint) {
throw new DeveloperError_default(
"IndexDatatype.UNSIGNED_INT requires OES_element_index_uint, which is not supported on this system. Check context.elementIndexUint."
);
}
const context = options.context;
const indexDatatype = options.indexDatatype;
const bytesPerIndex = IndexDatatype_default.getSizeInBytes(indexDatatype);
const buffer2 = new Buffer2({
context,
bufferTarget: WebGLConstants_default.ELEMENT_ARRAY_BUFFER,
typedArray: options.typedArray,
sizeInBytes: options.sizeInBytes,
usage: options.usage
});
const numberOfIndices = buffer2.sizeInBytes / bytesPerIndex;
Object.defineProperties(buffer2, {
indexDatatype: {
get: function() {
return indexDatatype;
}
},
bytesPerIndex: {
get: function() {
return bytesPerIndex;
}
},
numberOfIndices: {
get: function() {
return numberOfIndices;
}
}
});
return buffer2;
};
Object.defineProperties(Buffer2.prototype, {
sizeInBytes: {
get: function() {
return this._sizeInBytes;
}
},
usage: {
get: function() {
return this._usage;
}
}
});
Buffer2.prototype._getBuffer = function() {
return this._buffer;
};
Buffer2.prototype.copyFromArrayView = function(arrayView, offsetInBytes) {
offsetInBytes = offsetInBytes ?? 0;
Check_default.defined("arrayView", arrayView);
Check_default.typeOf.number.lessThanOrEquals(
"offsetInBytes + arrayView.byteLength",
offsetInBytes + arrayView.byteLength,
this._sizeInBytes
);
const gl = this._gl;
const target = this._bufferTarget;
gl.bindBuffer(target, this._buffer);
gl.bufferSubData(target, offsetInBytes, arrayView);
gl.bindBuffer(target, null);
};
Buffer2.prototype.copyFromBuffer = function(readBuffer, readOffset, writeOffset, sizeInBytes) {
if (!this._webgl2) {
throw new DeveloperError_default("A WebGL 2 context is required.");
}
if (!defined_default(readBuffer)) {
throw new DeveloperError_default("readBuffer must be defined.");
}
if (!defined_default(sizeInBytes) || sizeInBytes <= 0) {
throw new DeveloperError_default(
"sizeInBytes must be defined and be greater than zero."
);
}
if (!defined_default(readOffset) || readOffset < 0 || readOffset + sizeInBytes > readBuffer._sizeInBytes) {
throw new DeveloperError_default(
"readOffset must be greater than or equal to zero and readOffset + sizeInBytes must be less than of equal to readBuffer.sizeInBytes."
);
}
if (!defined_default(writeOffset) || writeOffset < 0 || writeOffset + sizeInBytes > this._sizeInBytes) {
throw new DeveloperError_default(
"writeOffset must be greater than or equal to zero and writeOffset + sizeInBytes must be less than of equal to this.sizeInBytes."
);
}
if (this._buffer === readBuffer._buffer && (writeOffset >= readOffset && writeOffset < readOffset + sizeInBytes || readOffset > writeOffset && readOffset < writeOffset + sizeInBytes)) {
throw new DeveloperError_default(
"When readBuffer is equal to this, the ranges [readOffset + sizeInBytes) and [writeOffset, writeOffset + sizeInBytes) must not overlap."
);
}
if (this._bufferTarget === WebGLConstants_default.ELEMENT_ARRAY_BUFFER && readBuffer._bufferTarget !== WebGLConstants_default.ELEMENT_ARRAY_BUFFER || this._bufferTarget !== WebGLConstants_default.ELEMENT_ARRAY_BUFFER && readBuffer._bufferTarget === WebGLConstants_default.ELEMENT_ARRAY_BUFFER) {
throw new DeveloperError_default(
"Can not copy an index buffer into another buffer type."
);
}
const readTarget = WebGLConstants_default.COPY_READ_BUFFER;
const writeTarget = WebGLConstants_default.COPY_WRITE_BUFFER;
const gl = this._gl;
gl.bindBuffer(writeTarget, this._buffer);
gl.bindBuffer(readTarget, readBuffer._buffer);
gl.copyBufferSubData(
readTarget,
writeTarget,
readOffset,
writeOffset,
sizeInBytes
);
gl.bindBuffer(writeTarget, null);
gl.bindBuffer(readTarget, null);
};
Buffer2.prototype.getBufferData = function(arrayView, sourceOffset, destinationOffset, length2) {
sourceOffset = sourceOffset ?? 0;
destinationOffset = destinationOffset ?? 0;
if (!this._webgl2) {
throw new DeveloperError_default("A WebGL 2 context is required.");
}
if (!defined_default(arrayView)) {
throw new DeveloperError_default("arrayView is required.");
}
let copyLength;
let elementSize;
let arrayLength = arrayView.byteLength;
if (!defined_default(length2)) {
if (defined_default(arrayLength)) {
copyLength = arrayLength - destinationOffset;
elementSize = 1;
} else {
arrayLength = arrayView.length;
copyLength = arrayLength - destinationOffset;
elementSize = arrayView.BYTES_PER_ELEMENT;
}
} else {
copyLength = length2;
if (defined_default(arrayLength)) {
elementSize = 1;
} else {
arrayLength = arrayView.length;
elementSize = arrayView.BYTES_PER_ELEMENT;
}
}
if (destinationOffset < 0 || destinationOffset > arrayLength) {
throw new DeveloperError_default(
"destinationOffset must be greater than zero and less than the arrayView length."
);
}
if (destinationOffset + copyLength > arrayLength) {
throw new DeveloperError_default(
"destinationOffset + length must be less than or equal to the arrayViewLength."
);
}
if (sourceOffset < 0 || sourceOffset > this._sizeInBytes) {
throw new DeveloperError_default(
"sourceOffset must be greater than zero and less than the buffers size."
);
}
if (sourceOffset + copyLength * elementSize > this._sizeInBytes) {
throw new DeveloperError_default(
"sourceOffset + length must be less than the buffers size."
);
}
const gl = this._gl;
const target = WebGLConstants_default.COPY_READ_BUFFER;
gl.bindBuffer(target, this._buffer);
gl.getBufferSubData(
target,
sourceOffset,
arrayView,
destinationOffset,
length2
);
gl.bindBuffer(target, null);
};
Buffer2.prototype.isDestroyed = function() {
return false;
};
Buffer2.prototype.destroy = function() {
this._gl.deleteBuffer(this._buffer);
return destroyObject_default(this);
};
var Buffer_default = Buffer2;
// packages/engine/Source/Renderer/ClearCommand.js
var import_InlineWorkers21 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/Color.js
var import_InlineWorkers20 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/FeatureDetection.js
var import_InlineWorkers19 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/Fullscreen.js
var import_InlineWorkers18 = __toESM(require_InlineWorkers(), 1);
var _supportsFullscreen;
var _names = {
requestFullscreen: void 0,
exitFullscreen: void 0,
fullscreenEnabled: void 0,
fullscreenElement: void 0,
fullscreenchange: void 0,
fullscreenerror: void 0
};
var Fullscreen = {};
Object.defineProperties(Fullscreen, {
/**
* The element that is currently fullscreen, if any. To simply check if the
* browser is in fullscreen mode or not, use {@link Fullscreen#fullscreen}.
* @memberof Fullscreen
* @type {object}
* @readonly
*/
element: {
get: function() {
if (!Fullscreen.supportsFullscreen()) {
return void 0;
}
return document[_names.fullscreenElement];
}
},
/**
* The name of the event on the document that is fired when fullscreen is
* entered or exited. This event name is intended for use with addEventListener.
* In your event handler, to determine if the browser is in fullscreen mode or not,
* use {@link Fullscreen#fullscreen}.
* @memberof Fullscreen
* @type {string}
* @readonly
*/
changeEventName: {
get: function() {
if (!Fullscreen.supportsFullscreen()) {
return void 0;
}
return _names.fullscreenchange;
}
},
/**
* The name of the event that is fired when a fullscreen error
* occurs. This event name is intended for use with addEventListener.
* @memberof Fullscreen
* @type {string}
* @readonly
*/
errorEventName: {
get: function() {
if (!Fullscreen.supportsFullscreen()) {
return void 0;
}
return _names.fullscreenerror;
}
},
/**
* Determine whether the browser will allow an element to be made fullscreen, or not.
* For example, by default, iframes cannot go fullscreen unless the containing page
* adds an "allowfullscreen" attribute (or prefixed equivalent).
* @memberof Fullscreen
* @type {boolean}
* @readonly
*/
enabled: {
get: function() {
if (!Fullscreen.supportsFullscreen()) {
return void 0;
}
return document[_names.fullscreenEnabled];
}
},
/**
* Determines if the browser is currently in fullscreen mode.
* @memberof Fullscreen
* @type {boolean}
* @readonly
*/
fullscreen: {
get: function() {
if (!Fullscreen.supportsFullscreen()) {
return void 0;
}
return Fullscreen.element !== null;
}
}
});
Fullscreen.supportsFullscreen = function() {
if (defined_default(_supportsFullscreen)) {
return _supportsFullscreen;
}
_supportsFullscreen = false;
const body = document.body;
if (typeof body.requestFullscreen === "function") {
_names.requestFullscreen = "requestFullscreen";
_names.exitFullscreen = "exitFullscreen";
_names.fullscreenEnabled = "fullscreenEnabled";
_names.fullscreenElement = "fullscreenElement";
_names.fullscreenchange = "fullscreenchange";
_names.fullscreenerror = "fullscreenerror";
_supportsFullscreen = true;
return _supportsFullscreen;
}
const prefixes = ["webkit", "moz", "o", "ms", "khtml"];
let name;
for (let i = 0, len = prefixes.length; i < len; ++i) {
const prefix = prefixes[i];
name = `${prefix}RequestFullscreen`;
if (typeof body[name] === "function") {
_names.requestFullscreen = name;
_supportsFullscreen = true;
} else {
name = `${prefix}RequestFullScreen`;
if (typeof body[name] === "function") {
_names.requestFullscreen = name;
_supportsFullscreen = true;
}
}
name = `${prefix}ExitFullscreen`;
if (typeof document[name] === "function") {
_names.exitFullscreen = name;
} else {
name = `${prefix}CancelFullScreen`;
if (typeof document[name] === "function") {
_names.exitFullscreen = name;
}
}
name = `${prefix}FullscreenEnabled`;
if (document[name] !== void 0) {
_names.fullscreenEnabled = name;
} else {
name = `${prefix}FullScreenEnabled`;
if (document[name] !== void 0) {
_names.fullscreenEnabled = name;
}
}
name = `${prefix}FullscreenElement`;
if (document[name] !== void 0) {
_names.fullscreenElement = name;
} else {
name = `${prefix}FullScreenElement`;
if (document[name] !== void 0) {
_names.fullscreenElement = name;
}
}
name = `${prefix}fullscreenchange`;
if (document[`on${name}`] !== void 0) {
if (prefix === "ms") {
name = "MSFullscreenChange";
}
_names.fullscreenchange = name;
}
name = `${prefix}fullscreenerror`;
if (document[`on${name}`] !== void 0) {
if (prefix === "ms") {
name = "MSFullscreenError";
}
_names.fullscreenerror = name;
}
}
return _supportsFullscreen;
};
Fullscreen.requestFullscreen = function(element, vrDevice) {
if (!Fullscreen.supportsFullscreen()) {
return;
}
element[_names.requestFullscreen]({ vrDisplay: vrDevice });
};
Fullscreen.exitFullscreen = function() {
if (!Fullscreen.supportsFullscreen()) {
return;
}
document[_names.exitFullscreen]();
};
Fullscreen._names = _names;
var Fullscreen_default = Fullscreen;
// packages/engine/Source/Core/FeatureDetection.js
var theNavigator;
if (typeof navigator !== "undefined") {
theNavigator = navigator;
} else {
theNavigator = {};
}
function extractVersion(versionString) {
const parts = versionString.split(".");
for (let i = 0, len = parts.length; i < len; ++i) {
parts[i] = parseInt(parts[i], 10);
}
return parts;
}
var isChromeResult;
var chromeVersionResult;
function isChrome() {
if (!defined_default(isChromeResult)) {
isChromeResult = false;
if (!isEdge()) {
const fields = / Chrome\/([\.0-9]+)/.exec(theNavigator.userAgent);
if (fields !== null) {
isChromeResult = true;
chromeVersionResult = extractVersion(fields[1]);
}
}
}
return isChromeResult;
}
function chromeVersion() {
return isChrome() && chromeVersionResult;
}
var isSafariResult;
var safariVersionResult;
function isSafari() {
if (!defined_default(isSafariResult)) {
isSafariResult = false;
if (!isChrome() && !isEdge() && / Safari\/[\.0-9]+/.test(theNavigator.userAgent)) {
const fields = / Version\/([\.0-9]+)/.exec(theNavigator.userAgent);
if (fields !== null) {
isSafariResult = true;
safariVersionResult = extractVersion(fields[1]);
}
}
}
return isSafariResult;
}
function safariVersion() {
return isSafari() && safariVersionResult;
}
var isWebkitResult;
var webkitVersionResult;
function isWebkit() {
if (!defined_default(isWebkitResult)) {
isWebkitResult = false;
const fields = / AppleWebKit\/([\.0-9]+)(\+?)/.exec(theNavigator.userAgent);
if (fields !== null) {
isWebkitResult = true;
webkitVersionResult = extractVersion(fields[1]);
webkitVersionResult.isNightly = !!fields[2];
}
}
return isWebkitResult;
}
function webkitVersion() {
return isWebkit() && webkitVersionResult;
}
var isInternetExplorerResult;
var internetExplorerVersionResult;
function isInternetExplorer() {
if (!defined_default(isInternetExplorerResult)) {
isInternetExplorerResult = false;
let fields;
if (theNavigator.appName === "Microsoft Internet Explorer") {
fields = /MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(theNavigator.userAgent);
if (fields !== null) {
isInternetExplorerResult = true;
internetExplorerVersionResult = extractVersion(fields[1]);
}
} else if (theNavigator.appName === "Netscape") {
fields = /Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(
theNavigator.userAgent
);
if (fields !== null) {
isInternetExplorerResult = true;
internetExplorerVersionResult = extractVersion(fields[1]);
}
}
}
return isInternetExplorerResult;
}
function internetExplorerVersion() {
return isInternetExplorer() && internetExplorerVersionResult;
}
var isEdgeResult;
var edgeVersionResult;
function isEdge() {
if (!defined_default(isEdgeResult)) {
isEdgeResult = false;
const fields = / Edg\/([\.0-9]+)/.exec(theNavigator.userAgent);
if (fields !== null) {
isEdgeResult = true;
edgeVersionResult = extractVersion(fields[1]);
}
}
return isEdgeResult;
}
function edgeVersion() {
return isEdge() && edgeVersionResult;
}
var isFirefoxResult;
var firefoxVersionResult;
function isFirefox() {
if (!defined_default(isFirefoxResult)) {
isFirefoxResult = false;
const fields = /Firefox\/([\.0-9]+)/.exec(theNavigator.userAgent);
if (fields !== null) {
isFirefoxResult = true;
firefoxVersionResult = extractVersion(fields[1]);
}
}
return isFirefoxResult;
}
var isWindowsResult;
function isWindows() {
if (!defined_default(isWindowsResult)) {
isWindowsResult = /Windows/i.test(theNavigator.appVersion);
}
return isWindowsResult;
}
var isIPadOrIOSResult;
function isIPadOrIOS() {
if (!defined_default(isIPadOrIOSResult)) {
isIPadOrIOSResult = navigator.platform === "iPhone" || navigator.platform === "iPod" || navigator.platform === "iPad";
}
return isIPadOrIOSResult;
}
function firefoxVersion() {
return isFirefox() && firefoxVersionResult;
}
var hasPointerEvents;
function supportsPointerEvents() {
if (!defined_default(hasPointerEvents)) {
hasPointerEvents = !isFirefox() && typeof PointerEvent !== "undefined" && (!defined_default(theNavigator.pointerEnabled) || theNavigator.pointerEnabled);
}
return hasPointerEvents;
}
var imageRenderingValueResult;
var supportsImageRenderingPixelatedResult;
function supportsImageRenderingPixelated() {
if (!defined_default(supportsImageRenderingPixelatedResult)) {
const canvas = document.createElement("canvas");
canvas.setAttribute(
"style",
"image-rendering: -moz-crisp-edges;image-rendering: pixelated;"
);
const tmp2 = canvas.style.imageRendering;
supportsImageRenderingPixelatedResult = defined_default(tmp2) && tmp2 !== "";
if (supportsImageRenderingPixelatedResult) {
imageRenderingValueResult = tmp2;
}
}
return supportsImageRenderingPixelatedResult;
}
function imageRenderingValue() {
return supportsImageRenderingPixelated() ? imageRenderingValueResult : void 0;
}
function supportsWebP() {
if (!supportsWebP.initialized) {
throw new DeveloperError_default(
"You must call FeatureDetection.supportsWebP.initialize and wait for the promise to resolve before calling FeatureDetection.supportsWebP"
);
}
return supportsWebP._result;
}
supportsWebP._promise = void 0;
supportsWebP._result = void 0;
supportsWebP.initialize = function() {
if (defined_default(supportsWebP._promise)) {
return supportsWebP._promise;
}
supportsWebP._promise = new Promise((resolve2) => {
const image = new Image();
image.onload = function() {
supportsWebP._result = image.width > 0 && image.height > 0;
resolve2(supportsWebP._result);
};
image.onerror = function() {
supportsWebP._result = false;
resolve2(supportsWebP._result);
};
image.src = "data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA";
});
return supportsWebP._promise;
};
Object.defineProperties(supportsWebP, {
initialized: {
get: function() {
return defined_default(supportsWebP._result);
}
}
});
var typedArrayTypes = [];
if (typeof ArrayBuffer !== "undefined") {
typedArrayTypes.push(
Int8Array,
Uint8Array,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array
);
if (typeof Uint8ClampedArray !== "undefined") {
typedArrayTypes.push(Uint8ClampedArray);
}
if (typeof Uint8ClampedArray !== "undefined") {
typedArrayTypes.push(Uint8ClampedArray);
}
if (typeof BigInt64Array !== "undefined") {
typedArrayTypes.push(BigInt64Array);
}
if (typeof BigUint64Array !== "undefined") {
typedArrayTypes.push(BigUint64Array);
}
}
var FeatureDetection = {
isChrome,
chromeVersion,
isSafari,
safariVersion,
isWebkit,
webkitVersion,
isInternetExplorer,
internetExplorerVersion,
isEdge,
edgeVersion,
isFirefox,
firefoxVersion,
isWindows,
isIPadOrIOS,
hardwareConcurrency: theNavigator.hardwareConcurrency ?? 3,
supportsPointerEvents,
supportsImageRenderingPixelated,
supportsWebP,
imageRenderingValue,
typedArrayTypes
};
FeatureDetection.supportsBasis = function(scene) {
return FeatureDetection.supportsWebAssembly() && scene.context.supportsBasis;
};
FeatureDetection.supportsFullscreen = function() {
return Fullscreen_default.supportsFullscreen();
};
FeatureDetection.supportsTypedArrays = function() {
return typeof ArrayBuffer !== "undefined";
};
FeatureDetection.supportsBigInt64Array = function() {
return typeof BigInt64Array !== "undefined";
};
FeatureDetection.supportsBigUint64Array = function() {
return typeof BigUint64Array !== "undefined";
};
FeatureDetection.supportsBigInt = function() {
return typeof BigInt !== "undefined";
};
FeatureDetection.supportsWebWorkers = function() {
return typeof Worker !== "undefined";
};
FeatureDetection.supportsWebAssembly = function() {
return typeof WebAssembly !== "undefined";
};
FeatureDetection.supportsWebgl2 = function(scene) {
Check_default.defined("scene", scene);
return scene.context.webgl2;
};
FeatureDetection.supportsEsmWebWorkers = function() {
return !isFirefox() || parseInt(firefoxVersionResult) >= 114;
};
var FeatureDetection_default = FeatureDetection;
// packages/engine/Source/Core/Color.js
function hue2rgb(m1, m2, h) {
if (h < 0) {
h += 1;
}
if (h > 1) {
h -= 1;
}
if (h * 6 < 1) {
return m1 + (m2 - m1) * 6 * h;
}
if (h * 2 < 1) {
return m2;
}
if (h * 3 < 2) {
return m1 + (m2 - m1) * (2 / 3 - h) * 6;
}
return m1;
}
function Color(red, green, blue, alpha) {
this.red = red ?? 1;
this.green = green ?? 1;
this.blue = blue ?? 1;
this.alpha = alpha ?? 1;
}
Color.fromCartesian4 = function(cartesian11, result) {
Check_default.typeOf.object("cartesian", cartesian11);
if (!defined_default(result)) {
return new Color(cartesian11.x, cartesian11.y, cartesian11.z, cartesian11.w);
}
result.red = cartesian11.x;
result.green = cartesian11.y;
result.blue = cartesian11.z;
result.alpha = cartesian11.w;
return result;
};
Color.fromBytes = function(red, green, blue, alpha, result) {
red = Color.byteToFloat(red ?? 255);
green = Color.byteToFloat(green ?? 255);
blue = Color.byteToFloat(blue ?? 255);
alpha = Color.byteToFloat(alpha ?? 255);
if (!defined_default(result)) {
return new Color(red, green, blue, alpha);
}
result.red = red;
result.green = green;
result.blue = blue;
result.alpha = alpha;
return result;
};
Color.fromAlpha = function(color, alpha, result) {
Check_default.typeOf.object("color", color);
Check_default.typeOf.number("alpha", alpha);
if (!defined_default(result)) {
return new Color(color.red, color.green, color.blue, alpha);
}
result.red = color.red;
result.green = color.green;
result.blue = color.blue;
result.alpha = alpha;
return result;
};
var scratchArrayBuffer;
var scratchUint32Array;
var scratchUint8Array;
if (FeatureDetection_default.supportsTypedArrays()) {
scratchArrayBuffer = new ArrayBuffer(4);
scratchUint32Array = new Uint32Array(scratchArrayBuffer);
scratchUint8Array = new Uint8Array(scratchArrayBuffer);
}
Color.fromRgba = function(rgba, result) {
scratchUint32Array[0] = rgba;
return Color.fromBytes(
scratchUint8Array[0],
scratchUint8Array[1],
scratchUint8Array[2],
scratchUint8Array[3],
result
);
};
Color.fromHsl = function(hue, saturation, lightness, alpha, result) {
hue = (hue ?? 0) % 1;
saturation = saturation ?? 0;
lightness = lightness ?? 0;
alpha = alpha ?? 1;
let red = lightness;
let green = lightness;
let blue = lightness;
if (saturation !== 0) {
let m2;
if (lightness < 0.5) {
m2 = lightness * (1 + saturation);
} else {
m2 = lightness + saturation - lightness * saturation;
}
const m1 = 2 * lightness - m2;
red = hue2rgb(m1, m2, hue + 1 / 3);
green = hue2rgb(m1, m2, hue);
blue = hue2rgb(m1, m2, hue - 1 / 3);
}
if (!defined_default(result)) {
return new Color(red, green, blue, alpha);
}
result.red = red;
result.green = green;
result.blue = blue;
result.alpha = alpha;
return result;
};
Color.fromRandom = function(options, result) {
options = options ?? Frozen_default.EMPTY_OBJECT;
let red = options.red;
if (!defined_default(red)) {
const minimumRed = options.minimumRed ?? 0;
const maximumRed = options.maximumRed ?? 1;
Check_default.typeOf.number.lessThanOrEquals("minimumRed", minimumRed, maximumRed);
red = minimumRed + Math_default.nextRandomNumber() * (maximumRed - minimumRed);
}
let green = options.green;
if (!defined_default(green)) {
const minimumGreen = options.minimumGreen ?? 0;
const maximumGreen = options.maximumGreen ?? 1;
Check_default.typeOf.number.lessThanOrEquals(
"minimumGreen",
minimumGreen,
maximumGreen
);
green = minimumGreen + Math_default.nextRandomNumber() * (maximumGreen - minimumGreen);
}
let blue = options.blue;
if (!defined_default(blue)) {
const minimumBlue = options.minimumBlue ?? 0;
const maximumBlue = options.maximumBlue ?? 1;
Check_default.typeOf.number.lessThanOrEquals(
"minimumBlue",
minimumBlue,
maximumBlue
);
blue = minimumBlue + Math_default.nextRandomNumber() * (maximumBlue - minimumBlue);
}
let alpha = options.alpha;
if (!defined_default(alpha)) {
const minimumAlpha = options.minimumAlpha ?? 0;
const maximumAlpha = options.maximumAlpha ?? 1;
Check_default.typeOf.number.lessThanOrEquals(
"minimumAlpha",
minimumAlpha,
maximumAlpha
);
alpha = minimumAlpha + Math_default.nextRandomNumber() * (maximumAlpha - minimumAlpha);
}
if (!defined_default(result)) {
return new Color(red, green, blue, alpha);
}
result.red = red;
result.green = green;
result.blue = blue;
result.alpha = alpha;
return result;
};
var rgbaMatcher = /^#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])?$/i;
var rrggbbaaMatcher = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?$/i;
var rgbParenthesesMatcher = /^rgba?\s*\(\s*([0-9.]+%?)\s*[,\s]+\s*([0-9.]+%?)\s*[,\s]+\s*([0-9.]+%?)(?:\s*[,\s/]+\s*([0-9.]+))?\s*\)$/i;
var hslParenthesesMatcher = /^hsla?\s*\(\s*([0-9.]+)\s*[,\s]+\s*([0-9.]+%)\s*[,\s]+\s*([0-9.]+%)(?:\s*[,\s/]+\s*([0-9.]+))?\s*\)$/i;
Color.fromCssColorString = function(color, result) {
Check_default.typeOf.string("color", color);
if (!defined_default(result)) {
result = new Color();
}
color = color.trim();
const namedColor = Color[color.toUpperCase()];
if (defined_default(namedColor)) {
Color.clone(namedColor, result);
return result;
}
let matches = rgbaMatcher.exec(color);
if (matches !== null) {
result.red = parseInt(matches[1], 16) / 15;
result.green = parseInt(matches[2], 16) / 15;
result.blue = parseInt(matches[3], 16) / 15;
result.alpha = parseInt(matches[4] ?? "f", 16) / 15;
return result;
}
matches = rrggbbaaMatcher.exec(color);
if (matches !== null) {
result.red = parseInt(matches[1], 16) / 255;
result.green = parseInt(matches[2], 16) / 255;
result.blue = parseInt(matches[3], 16) / 255;
result.alpha = parseInt(matches[4] ?? "ff", 16) / 255;
return result;
}
matches = rgbParenthesesMatcher.exec(color);
if (matches !== null) {
result.red = parseFloat(matches[1]) / ("%" === matches[1].substr(-1) ? 100 : 255);
result.green = parseFloat(matches[2]) / ("%" === matches[2].substr(-1) ? 100 : 255);
result.blue = parseFloat(matches[3]) / ("%" === matches[3].substr(-1) ? 100 : 255);
result.alpha = parseFloat(matches[4] ?? "1.0");
return result;
}
matches = hslParenthesesMatcher.exec(color);
if (matches !== null) {
return Color.fromHsl(
parseFloat(matches[1]) / 360,
parseFloat(matches[2]) / 100,
parseFloat(matches[3]) / 100,
parseFloat(matches[4] ?? "1.0"),
result
);
}
result = void 0;
return result;
};
Color.packedLength = 4;
Color.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
array[startingIndex++] = value.red;
array[startingIndex++] = value.green;
array[startingIndex++] = value.blue;
array[startingIndex] = value.alpha;
return array;
};
Color.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new Color();
}
result.red = array[startingIndex++];
result.green = array[startingIndex++];
result.blue = array[startingIndex++];
result.alpha = array[startingIndex];
return result;
};
Color.byteToFloat = function(number) {
return number / 255;
};
Color.floatToByte = function(number) {
return number === 1 ? 255 : number * 256 | 0;
};
Color.clone = function(color, result) {
if (!defined_default(color)) {
return void 0;
}
if (!defined_default(result)) {
return new Color(color.red, color.green, color.blue, color.alpha);
}
result.red = color.red;
result.green = color.green;
result.blue = color.blue;
result.alpha = color.alpha;
return result;
};
Color.equals = function(left, right) {
return left === right || //
defined_default(left) && //
defined_default(right) && //
left.red === right.red && //
left.green === right.green && //
left.blue === right.blue && //
left.alpha === right.alpha;
};
Color.equalsArray = function(color, array, offset) {
return color.red === array[offset] && color.green === array[offset + 1] && color.blue === array[offset + 2] && color.alpha === array[offset + 3];
};
Color.prototype.clone = function(result) {
return Color.clone(this, result);
};
Color.prototype.equals = function(other) {
return Color.equals(this, other);
};
Color.prototype.equalsEpsilon = function(other, epsilon) {
return this === other || //
defined_default(other) && //
Math.abs(this.red - other.red) <= epsilon && //
Math.abs(this.green - other.green) <= epsilon && //
Math.abs(this.blue - other.blue) <= epsilon && //
Math.abs(this.alpha - other.alpha) <= epsilon;
};
Color.prototype.toString = function() {
return `(${this.red}, ${this.green}, ${this.blue}, ${this.alpha})`;
};
Color.prototype.toCssColorString = function() {
const red = Color.floatToByte(this.red);
const green = Color.floatToByte(this.green);
const blue = Color.floatToByte(this.blue);
if (this.alpha === 1) {
return `rgb(${red},${green},${blue})`;
}
return `rgba(${red},${green},${blue},${this.alpha})`;
};
Color.prototype.toCssHexString = function() {
let r = Color.floatToByte(this.red).toString(16);
if (r.length < 2) {
r = `0${r}`;
}
let g = Color.floatToByte(this.green).toString(16);
if (g.length < 2) {
g = `0${g}`;
}
let b = Color.floatToByte(this.blue).toString(16);
if (b.length < 2) {
b = `0${b}`;
}
if (this.alpha < 1) {
let hexAlpha = Color.floatToByte(this.alpha).toString(16);
if (hexAlpha.length < 2) {
hexAlpha = `0${hexAlpha}`;
}
return `#${r}${g}${b}${hexAlpha}`;
}
return `#${r}${g}${b}`;
};
Color.prototype.toBytes = function(result) {
const red = Color.floatToByte(this.red);
const green = Color.floatToByte(this.green);
const blue = Color.floatToByte(this.blue);
const alpha = Color.floatToByte(this.alpha);
if (!defined_default(result)) {
return [red, green, blue, alpha];
}
result[0] = red;
result[1] = green;
result[2] = blue;
result[3] = alpha;
return result;
};
Color.prototype.toRgba = function() {
scratchUint8Array[0] = Color.floatToByte(this.red);
scratchUint8Array[1] = Color.floatToByte(this.green);
scratchUint8Array[2] = Color.floatToByte(this.blue);
scratchUint8Array[3] = Color.floatToByte(this.alpha);
return scratchUint32Array[0];
};
Color.prototype.brighten = function(magnitude, result) {
Check_default.typeOf.number("magnitude", magnitude);
Check_default.typeOf.number.greaterThanOrEquals("magnitude", magnitude, 0);
Check_default.typeOf.object("result", result);
magnitude = 1 - magnitude;
result.red = 1 - (1 - this.red) * magnitude;
result.green = 1 - (1 - this.green) * magnitude;
result.blue = 1 - (1 - this.blue) * magnitude;
result.alpha = this.alpha;
return result;
};
Color.prototype.darken = function(magnitude, result) {
Check_default.typeOf.number("magnitude", magnitude);
Check_default.typeOf.number.greaterThanOrEquals("magnitude", magnitude, 0);
Check_default.typeOf.object("result", result);
magnitude = 1 - magnitude;
result.red = this.red * magnitude;
result.green = this.green * magnitude;
result.blue = this.blue * magnitude;
result.alpha = this.alpha;
return result;
};
Color.prototype.withAlpha = function(alpha, result) {
return Color.fromAlpha(this, alpha, result);
};
Color.add = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result.red = left.red + right.red;
result.green = left.green + right.green;
result.blue = left.blue + right.blue;
result.alpha = left.alpha + right.alpha;
return result;
};
Color.subtract = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result.red = left.red - right.red;
result.green = left.green - right.green;
result.blue = left.blue - right.blue;
result.alpha = left.alpha - right.alpha;
return result;
};
Color.multiply = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result.red = left.red * right.red;
result.green = left.green * right.green;
result.blue = left.blue * right.blue;
result.alpha = left.alpha * right.alpha;
return result;
};
Color.divide = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result.red = left.red / right.red;
result.green = left.green / right.green;
result.blue = left.blue / right.blue;
result.alpha = left.alpha / right.alpha;
return result;
};
Color.mod = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result.red = left.red % right.red;
result.green = left.green % right.green;
result.blue = left.blue % right.blue;
result.alpha = left.alpha % right.alpha;
return result;
};
Color.lerp = function(start, end, t, result) {
Check_default.typeOf.object("start", start);
Check_default.typeOf.object("end", end);
Check_default.typeOf.number("t", t);
Check_default.typeOf.object("result", result);
result.red = Math_default.lerp(start.red, end.red, t);
result.green = Math_default.lerp(start.green, end.green, t);
result.blue = Math_default.lerp(start.blue, end.blue, t);
result.alpha = Math_default.lerp(start.alpha, end.alpha, t);
return result;
};
Color.multiplyByScalar = function(color, scalar, result) {
Check_default.typeOf.object("color", color);
Check_default.typeOf.number("scalar", scalar);
Check_default.typeOf.object("result", result);
result.red = color.red * scalar;
result.green = color.green * scalar;
result.blue = color.blue * scalar;
result.alpha = color.alpha * scalar;
return result;
};
Color.divideByScalar = function(color, scalar, result) {
Check_default.typeOf.object("color", color);
Check_default.typeOf.number("scalar", scalar);
Check_default.typeOf.object("result", result);
result.red = color.red / scalar;
result.green = color.green / scalar;
result.blue = color.blue / scalar;
result.alpha = color.alpha / scalar;
return result;
};
Color.ALICEBLUE = Object.freeze(Color.fromCssColorString("#F0F8FF"));
Color.ANTIQUEWHITE = Object.freeze(Color.fromCssColorString("#FAEBD7"));
Color.AQUA = Object.freeze(Color.fromCssColorString("#00FFFF"));
Color.AQUAMARINE = Object.freeze(Color.fromCssColorString("#7FFFD4"));
Color.AZURE = Object.freeze(Color.fromCssColorString("#F0FFFF"));
Color.BEIGE = Object.freeze(Color.fromCssColorString("#F5F5DC"));
Color.BISQUE = Object.freeze(Color.fromCssColorString("#FFE4C4"));
Color.BLACK = Object.freeze(Color.fromCssColorString("#000000"));
Color.BLANCHEDALMOND = Object.freeze(Color.fromCssColorString("#FFEBCD"));
Color.BLUE = Object.freeze(Color.fromCssColorString("#0000FF"));
Color.BLUEVIOLET = Object.freeze(Color.fromCssColorString("#8A2BE2"));
Color.BROWN = Object.freeze(Color.fromCssColorString("#A52A2A"));
Color.BURLYWOOD = Object.freeze(Color.fromCssColorString("#DEB887"));
Color.CADETBLUE = Object.freeze(Color.fromCssColorString("#5F9EA0"));
Color.CHARTREUSE = Object.freeze(Color.fromCssColorString("#7FFF00"));
Color.CHOCOLATE = Object.freeze(Color.fromCssColorString("#D2691E"));
Color.CORAL = Object.freeze(Color.fromCssColorString("#FF7F50"));
Color.CORNFLOWERBLUE = Object.freeze(Color.fromCssColorString("#6495ED"));
Color.CORNSILK = Object.freeze(Color.fromCssColorString("#FFF8DC"));
Color.CRIMSON = Object.freeze(Color.fromCssColorString("#DC143C"));
Color.CYAN = Object.freeze(Color.fromCssColorString("#00FFFF"));
Color.DARKBLUE = Object.freeze(Color.fromCssColorString("#00008B"));
Color.DARKCYAN = Object.freeze(Color.fromCssColorString("#008B8B"));
Color.DARKGOLDENROD = Object.freeze(Color.fromCssColorString("#B8860B"));
Color.DARKGRAY = Object.freeze(Color.fromCssColorString("#A9A9A9"));
Color.DARKGREEN = Object.freeze(Color.fromCssColorString("#006400"));
Color.DARKGREY = Color.DARKGRAY;
Color.DARKKHAKI = Object.freeze(Color.fromCssColorString("#BDB76B"));
Color.DARKMAGENTA = Object.freeze(Color.fromCssColorString("#8B008B"));
Color.DARKOLIVEGREEN = Object.freeze(Color.fromCssColorString("#556B2F"));
Color.DARKORANGE = Object.freeze(Color.fromCssColorString("#FF8C00"));
Color.DARKORCHID = Object.freeze(Color.fromCssColorString("#9932CC"));
Color.DARKRED = Object.freeze(Color.fromCssColorString("#8B0000"));
Color.DARKSALMON = Object.freeze(Color.fromCssColorString("#E9967A"));
Color.DARKSEAGREEN = Object.freeze(Color.fromCssColorString("#8FBC8F"));
Color.DARKSLATEBLUE = Object.freeze(Color.fromCssColorString("#483D8B"));
Color.DARKSLATEGRAY = Object.freeze(Color.fromCssColorString("#2F4F4F"));
Color.DARKSLATEGREY = Color.DARKSLATEGRAY;
Color.DARKTURQUOISE = Object.freeze(Color.fromCssColorString("#00CED1"));
Color.DARKVIOLET = Object.freeze(Color.fromCssColorString("#9400D3"));
Color.DEEPPINK = Object.freeze(Color.fromCssColorString("#FF1493"));
Color.DEEPSKYBLUE = Object.freeze(Color.fromCssColorString("#00BFFF"));
Color.DIMGRAY = Object.freeze(Color.fromCssColorString("#696969"));
Color.DIMGREY = Color.DIMGRAY;
Color.DODGERBLUE = Object.freeze(Color.fromCssColorString("#1E90FF"));
Color.FIREBRICK = Object.freeze(Color.fromCssColorString("#B22222"));
Color.FLORALWHITE = Object.freeze(Color.fromCssColorString("#FFFAF0"));
Color.FORESTGREEN = Object.freeze(Color.fromCssColorString("#228B22"));
Color.FUCHSIA = Object.freeze(Color.fromCssColorString("#FF00FF"));
Color.GAINSBORO = Object.freeze(Color.fromCssColorString("#DCDCDC"));
Color.GHOSTWHITE = Object.freeze(Color.fromCssColorString("#F8F8FF"));
Color.GOLD = Object.freeze(Color.fromCssColorString("#FFD700"));
Color.GOLDENROD = Object.freeze(Color.fromCssColorString("#DAA520"));
Color.GRAY = Object.freeze(Color.fromCssColorString("#808080"));
Color.GREEN = Object.freeze(Color.fromCssColorString("#008000"));
Color.GREENYELLOW = Object.freeze(Color.fromCssColorString("#ADFF2F"));
Color.GREY = Color.GRAY;
Color.HONEYDEW = Object.freeze(Color.fromCssColorString("#F0FFF0"));
Color.HOTPINK = Object.freeze(Color.fromCssColorString("#FF69B4"));
Color.INDIANRED = Object.freeze(Color.fromCssColorString("#CD5C5C"));
Color.INDIGO = Object.freeze(Color.fromCssColorString("#4B0082"));
Color.IVORY = Object.freeze(Color.fromCssColorString("#FFFFF0"));
Color.KHAKI = Object.freeze(Color.fromCssColorString("#F0E68C"));
Color.LAVENDER = Object.freeze(Color.fromCssColorString("#E6E6FA"));
Color.LAVENDAR_BLUSH = Object.freeze(Color.fromCssColorString("#FFF0F5"));
Color.LAWNGREEN = Object.freeze(Color.fromCssColorString("#7CFC00"));
Color.LEMONCHIFFON = Object.freeze(Color.fromCssColorString("#FFFACD"));
Color.LIGHTBLUE = Object.freeze(Color.fromCssColorString("#ADD8E6"));
Color.LIGHTCORAL = Object.freeze(Color.fromCssColorString("#F08080"));
Color.LIGHTCYAN = Object.freeze(Color.fromCssColorString("#E0FFFF"));
Color.LIGHTGOLDENRODYELLOW = Object.freeze(Color.fromCssColorString("#FAFAD2"));
Color.LIGHTGRAY = Object.freeze(Color.fromCssColorString("#D3D3D3"));
Color.LIGHTGREEN = Object.freeze(Color.fromCssColorString("#90EE90"));
Color.LIGHTGREY = Color.LIGHTGRAY;
Color.LIGHTPINK = Object.freeze(Color.fromCssColorString("#FFB6C1"));
Color.LIGHTSEAGREEN = Object.freeze(Color.fromCssColorString("#20B2AA"));
Color.LIGHTSKYBLUE = Object.freeze(Color.fromCssColorString("#87CEFA"));
Color.LIGHTSLATEGRAY = Object.freeze(Color.fromCssColorString("#778899"));
Color.LIGHTSLATEGREY = Color.LIGHTSLATEGRAY;
Color.LIGHTSTEELBLUE = Object.freeze(Color.fromCssColorString("#B0C4DE"));
Color.LIGHTYELLOW = Object.freeze(Color.fromCssColorString("#FFFFE0"));
Color.LIME = Object.freeze(Color.fromCssColorString("#00FF00"));
Color.LIMEGREEN = Object.freeze(Color.fromCssColorString("#32CD32"));
Color.LINEN = Object.freeze(Color.fromCssColorString("#FAF0E6"));
Color.MAGENTA = Object.freeze(Color.fromCssColorString("#FF00FF"));
Color.MAROON = Object.freeze(Color.fromCssColorString("#800000"));
Color.MEDIUMAQUAMARINE = Object.freeze(Color.fromCssColorString("#66CDAA"));
Color.MEDIUMBLUE = Object.freeze(Color.fromCssColorString("#0000CD"));
Color.MEDIUMORCHID = Object.freeze(Color.fromCssColorString("#BA55D3"));
Color.MEDIUMPURPLE = Object.freeze(Color.fromCssColorString("#9370DB"));
Color.MEDIUMSEAGREEN = Object.freeze(Color.fromCssColorString("#3CB371"));
Color.MEDIUMSLATEBLUE = Object.freeze(Color.fromCssColorString("#7B68EE"));
Color.MEDIUMSPRINGGREEN = Object.freeze(Color.fromCssColorString("#00FA9A"));
Color.MEDIUMTURQUOISE = Object.freeze(Color.fromCssColorString("#48D1CC"));
Color.MEDIUMVIOLETRED = Object.freeze(Color.fromCssColorString("#C71585"));
Color.MIDNIGHTBLUE = Object.freeze(Color.fromCssColorString("#191970"));
Color.MINTCREAM = Object.freeze(Color.fromCssColorString("#F5FFFA"));
Color.MISTYROSE = Object.freeze(Color.fromCssColorString("#FFE4E1"));
Color.MOCCASIN = Object.freeze(Color.fromCssColorString("#FFE4B5"));
Color.NAVAJOWHITE = Object.freeze(Color.fromCssColorString("#FFDEAD"));
Color.NAVY = Object.freeze(Color.fromCssColorString("#000080"));
Color.OLDLACE = Object.freeze(Color.fromCssColorString("#FDF5E6"));
Color.OLIVE = Object.freeze(Color.fromCssColorString("#808000"));
Color.OLIVEDRAB = Object.freeze(Color.fromCssColorString("#6B8E23"));
Color.ORANGE = Object.freeze(Color.fromCssColorString("#FFA500"));
Color.ORANGERED = Object.freeze(Color.fromCssColorString("#FF4500"));
Color.ORCHID = Object.freeze(Color.fromCssColorString("#DA70D6"));
Color.PALEGOLDENROD = Object.freeze(Color.fromCssColorString("#EEE8AA"));
Color.PALEGREEN = Object.freeze(Color.fromCssColorString("#98FB98"));
Color.PALETURQUOISE = Object.freeze(Color.fromCssColorString("#AFEEEE"));
Color.PALEVIOLETRED = Object.freeze(Color.fromCssColorString("#DB7093"));
Color.PAPAYAWHIP = Object.freeze(Color.fromCssColorString("#FFEFD5"));
Color.PEACHPUFF = Object.freeze(Color.fromCssColorString("#FFDAB9"));
Color.PERU = Object.freeze(Color.fromCssColorString("#CD853F"));
Color.PINK = Object.freeze(Color.fromCssColorString("#FFC0CB"));
Color.PLUM = Object.freeze(Color.fromCssColorString("#DDA0DD"));
Color.POWDERBLUE = Object.freeze(Color.fromCssColorString("#B0E0E6"));
Color.PURPLE = Object.freeze(Color.fromCssColorString("#800080"));
Color.RED = Object.freeze(Color.fromCssColorString("#FF0000"));
Color.ROSYBROWN = Object.freeze(Color.fromCssColorString("#BC8F8F"));
Color.ROYALBLUE = Object.freeze(Color.fromCssColorString("#4169E1"));
Color.SADDLEBROWN = Object.freeze(Color.fromCssColorString("#8B4513"));
Color.SALMON = Object.freeze(Color.fromCssColorString("#FA8072"));
Color.SANDYBROWN = Object.freeze(Color.fromCssColorString("#F4A460"));
Color.SEAGREEN = Object.freeze(Color.fromCssColorString("#2E8B57"));
Color.SEASHELL = Object.freeze(Color.fromCssColorString("#FFF5EE"));
Color.SIENNA = Object.freeze(Color.fromCssColorString("#A0522D"));
Color.SILVER = Object.freeze(Color.fromCssColorString("#C0C0C0"));
Color.SKYBLUE = Object.freeze(Color.fromCssColorString("#87CEEB"));
Color.SLATEBLUE = Object.freeze(Color.fromCssColorString("#6A5ACD"));
Color.SLATEGRAY = Object.freeze(Color.fromCssColorString("#708090"));
Color.SLATEGREY = Color.SLATEGRAY;
Color.SNOW = Object.freeze(Color.fromCssColorString("#FFFAFA"));
Color.SPRINGGREEN = Object.freeze(Color.fromCssColorString("#00FF7F"));
Color.STEELBLUE = Object.freeze(Color.fromCssColorString("#4682B4"));
Color.TAN = Object.freeze(Color.fromCssColorString("#D2B48C"));
Color.TEAL = Object.freeze(Color.fromCssColorString("#008080"));
Color.THISTLE = Object.freeze(Color.fromCssColorString("#D8BFD8"));
Color.TOMATO = Object.freeze(Color.fromCssColorString("#FF6347"));
Color.TURQUOISE = Object.freeze(Color.fromCssColorString("#40E0D0"));
Color.VIOLET = Object.freeze(Color.fromCssColorString("#EE82EE"));
Color.WHEAT = Object.freeze(Color.fromCssColorString("#F5DEB3"));
Color.WHITE = Object.freeze(Color.fromCssColorString("#FFFFFF"));
Color.WHITESMOKE = Object.freeze(Color.fromCssColorString("#F5F5F5"));
Color.YELLOW = Object.freeze(Color.fromCssColorString("#FFFF00"));
Color.YELLOWGREEN = Object.freeze(Color.fromCssColorString("#9ACD32"));
Color.TRANSPARENT = Object.freeze(new Color(0, 0, 0, 0));
var Color_default = Color;
// packages/engine/Source/Renderer/ClearCommand.js
function ClearCommand(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.color = options.color;
this.depth = options.depth;
this.stencil = options.stencil;
this.renderState = options.renderState;
this.framebuffer = options.framebuffer;
this.owner = options.owner;
this.pass = options.pass;
}
ClearCommand.ALL = Object.freeze(
new ClearCommand({
color: new Color_default(0, 0, 0, 0),
depth: 1,
stencil: 0
})
);
ClearCommand.prototype.execute = function(context, passState) {
context.clear(this, passState);
};
var ClearCommand_default = ClearCommand;
// packages/engine/Source/Renderer/ComputeCommand.js
var import_InlineWorkers23 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Renderer/Pass.js
var import_InlineWorkers22 = __toESM(require_InlineWorkers(), 1);
var Pass = {
// If you add/modify/remove Pass constants, also change the automatic GLSL constants
// that start with 'czm_pass'
//
// Commands are executed in order by pass up to the translucent pass.
// Translucent geometry needs special handling (sorting/OIT). The compute pass
// is executed first and the overlay pass is executed last. Both are not sorted
// by frustum.
ENVIRONMENT: 0,
COMPUTE: 1,
GLOBE: 2,
TERRAIN_CLASSIFICATION: 3,
CESIUM_3D_TILE: 4,
CESIUM_3D_TILE_CLASSIFICATION: 5,
CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW: 6,
OPAQUE: 7,
TRANSLUCENT: 8,
VOXELS: 9,
GAUSSIAN_SPLATS: 10,
OVERLAY: 11,
NUMBER_OF_PASSES: 12
};
var Pass_default = Object.freeze(Pass);
// packages/engine/Source/Renderer/ComputeCommand.js
function ComputeCommand(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.vertexArray = options.vertexArray;
this.fragmentShaderSource = options.fragmentShaderSource;
this.shaderProgram = options.shaderProgram;
this.uniformMap = options.uniformMap;
this.outputTexture = options.outputTexture;
this.preExecute = options.preExecute;
this.postExecute = options.postExecute;
this.canceled = options.canceled;
this.persists = options.persists ?? false;
this.pass = Pass_default.COMPUTE;
this.owner = options.owner;
}
ComputeCommand.prototype.execute = function(computeEngine) {
computeEngine.execute(this);
};
var ComputeCommand_default = ComputeCommand;
// packages/engine/Source/Renderer/ComputeEngine.js
var import_InlineWorkers85 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/BoundingRectangle.js
var import_InlineWorkers70 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/Cartesian2.js
var import_InlineWorkers24 = __toESM(require_InlineWorkers(), 1);
function Cartesian2(x, y) {
this.x = x ?? 0;
this.y = y ?? 0;
}
Cartesian2.fromElements = function(x, y, result) {
if (!defined_default(result)) {
return new Cartesian2(x, y);
}
result.x = x;
result.y = y;
return result;
};
Cartesian2.clone = function(cartesian11, result) {
if (!defined_default(cartesian11)) {
return void 0;
}
if (!defined_default(result)) {
return new Cartesian2(cartesian11.x, cartesian11.y);
}
result.x = cartesian11.x;
result.y = cartesian11.y;
return result;
};
Cartesian2.fromCartesian3 = Cartesian2.clone;
Cartesian2.fromCartesian4 = Cartesian2.clone;
Cartesian2.packedLength = 2;
Cartesian2.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
array[startingIndex++] = value.x;
array[startingIndex] = value.y;
return array;
};
Cartesian2.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new Cartesian2();
}
result.x = array[startingIndex++];
result.y = array[startingIndex];
return result;
};
Cartesian2.packArray = function(array, result) {
Check_default.defined("array", array);
const length2 = array.length;
const resultLength = length2 * 2;
if (!defined_default(result)) {
result = new Array(resultLength);
} else if (!Array.isArray(result) && result.length !== resultLength) {
throw new DeveloperError_default(
"If result is a typed array, it must have exactly array.length * 2 elements"
);
} else if (result.length !== resultLength) {
result.length = resultLength;
}
for (let i = 0; i < length2; ++i) {
Cartesian2.pack(array[i], result, i * 2);
}
return result;
};
Cartesian2.unpackArray = function(array, result) {
Check_default.defined("array", array);
Check_default.typeOf.number.greaterThanOrEquals("array.length", array.length, 2);
if (array.length % 2 !== 0) {
throw new DeveloperError_default("array length must be a multiple of 2.");
}
const length2 = array.length;
if (!defined_default(result)) {
result = new Array(length2 / 2);
} else {
result.length = length2 / 2;
}
for (let i = 0; i < length2; i += 2) {
const index = i / 2;
result[index] = Cartesian2.unpack(array, i, result[index]);
}
return result;
};
Cartesian2.fromArray = Cartesian2.unpack;
Cartesian2.maximumComponent = function(cartesian11) {
Check_default.typeOf.object("cartesian", cartesian11);
return Math.max(cartesian11.x, cartesian11.y);
};
Cartesian2.minimumComponent = function(cartesian11) {
Check_default.typeOf.object("cartesian", cartesian11);
return Math.min(cartesian11.x, cartesian11.y);
};
Cartesian2.minimumByComponent = function(first, second, result) {
Check_default.typeOf.object("first", first);
Check_default.typeOf.object("second", second);
Check_default.typeOf.object("result", result);
result.x = Math.min(first.x, second.x);
result.y = Math.min(first.y, second.y);
return result;
};
Cartesian2.maximumByComponent = function(first, second, result) {
Check_default.typeOf.object("first", first);
Check_default.typeOf.object("second", second);
Check_default.typeOf.object("result", result);
result.x = Math.max(first.x, second.x);
result.y = Math.max(first.y, second.y);
return result;
};
Cartesian2.clamp = function(value, min3, max3, result) {
Check_default.typeOf.object("value", value);
Check_default.typeOf.object("min", min3);
Check_default.typeOf.object("max", max3);
Check_default.typeOf.object("result", result);
const x = Math_default.clamp(value.x, min3.x, max3.x);
const y = Math_default.clamp(value.y, min3.y, max3.y);
result.x = x;
result.y = y;
return result;
};
Cartesian2.magnitudeSquared = function(cartesian11) {
Check_default.typeOf.object("cartesian", cartesian11);
return cartesian11.x * cartesian11.x + cartesian11.y * cartesian11.y;
};
Cartesian2.magnitude = function(cartesian11) {
return Math.sqrt(Cartesian2.magnitudeSquared(cartesian11));
};
var distanceScratch3 = new Cartesian2();
Cartesian2.distance = function(left, right) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Cartesian2.subtract(left, right, distanceScratch3);
return Cartesian2.magnitude(distanceScratch3);
};
Cartesian2.distanceSquared = function(left, right) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Cartesian2.subtract(left, right, distanceScratch3);
return Cartesian2.magnitudeSquared(distanceScratch3);
};
Cartesian2.normalize = function(cartesian11, result) {
Check_default.typeOf.object("cartesian", cartesian11);
Check_default.typeOf.object("result", result);
const magnitude = Cartesian2.magnitude(cartesian11);
result.x = cartesian11.x / magnitude;
result.y = cartesian11.y / magnitude;
if (isNaN(result.x) || isNaN(result.y)) {
throw new DeveloperError_default("normalized result is not a number");
}
return result;
};
Cartesian2.dot = function(left, right) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
return left.x * right.x + left.y * right.y;
};
Cartesian2.cross = function(left, right) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
return left.x * right.y - left.y * right.x;
};
Cartesian2.multiplyComponents = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result.x = left.x * right.x;
result.y = left.y * right.y;
return result;
};
Cartesian2.divideComponents = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result.x = left.x / right.x;
result.y = left.y / right.y;
return result;
};
Cartesian2.add = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result.x = left.x + right.x;
result.y = left.y + right.y;
return result;
};
Cartesian2.subtract = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result.x = left.x - right.x;
result.y = left.y - right.y;
return result;
};
Cartesian2.multiplyByScalar = function(cartesian11, scalar, result) {
Check_default.typeOf.object("cartesian", cartesian11);
Check_default.typeOf.number("scalar", scalar);
Check_default.typeOf.object("result", result);
result.x = cartesian11.x * scalar;
result.y = cartesian11.y * scalar;
return result;
};
Cartesian2.divideByScalar = function(cartesian11, scalar, result) {
Check_default.typeOf.object("cartesian", cartesian11);
Check_default.typeOf.number("scalar", scalar);
Check_default.typeOf.object("result", result);
result.x = cartesian11.x / scalar;
result.y = cartesian11.y / scalar;
return result;
};
Cartesian2.negate = function(cartesian11, result) {
Check_default.typeOf.object("cartesian", cartesian11);
Check_default.typeOf.object("result", result);
result.x = -cartesian11.x;
result.y = -cartesian11.y;
return result;
};
Cartesian2.abs = function(cartesian11, result) {
Check_default.typeOf.object("cartesian", cartesian11);
Check_default.typeOf.object("result", result);
result.x = Math.abs(cartesian11.x);
result.y = Math.abs(cartesian11.y);
return result;
};
var lerpScratch3 = new Cartesian2();
Cartesian2.lerp = function(start, end, t, result) {
Check_default.typeOf.object("start", start);
Check_default.typeOf.object("end", end);
Check_default.typeOf.number("t", t);
Check_default.typeOf.object("result", result);
Cartesian2.multiplyByScalar(end, t, lerpScratch3);
result = Cartesian2.multiplyByScalar(start, 1 - t, result);
return Cartesian2.add(lerpScratch3, result, result);
};
var angleBetweenScratch3 = new Cartesian2();
var angleBetweenScratch22 = new Cartesian2();
Cartesian2.angleBetween = function(left, right) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Cartesian2.normalize(left, angleBetweenScratch3);
Cartesian2.normalize(right, angleBetweenScratch22);
return Math_default.acosClamped(
Cartesian2.dot(angleBetweenScratch3, angleBetweenScratch22)
);
};
var mostOrthogonalAxisScratch3 = new Cartesian2();
Cartesian2.mostOrthogonalAxis = function(cartesian11, result) {
Check_default.typeOf.object("cartesian", cartesian11);
Check_default.typeOf.object("result", result);
const f = Cartesian2.normalize(cartesian11, mostOrthogonalAxisScratch3);
Cartesian2.abs(f, f);
if (f.x <= f.y) {
result = Cartesian2.clone(Cartesian2.UNIT_X, result);
} else {
result = Cartesian2.clone(Cartesian2.UNIT_Y, result);
}
return result;
};
Cartesian2.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left.x === right.x && left.y === right.y;
};
Cartesian2.equalsArray = function(cartesian11, array, offset) {
return cartesian11.x === array[offset] && cartesian11.y === array[offset + 1];
};
Cartesian2.equalsEpsilon = function(left, right, relativeEpsilon, absoluteEpsilon) {
return left === right || defined_default(left) && defined_default(right) && Math_default.equalsEpsilon(
left.x,
right.x,
relativeEpsilon,
absoluteEpsilon
) && Math_default.equalsEpsilon(
left.y,
right.y,
relativeEpsilon,
absoluteEpsilon
);
};
Cartesian2.ZERO = Object.freeze(new Cartesian2(0, 0));
Cartesian2.ONE = Object.freeze(new Cartesian2(1, 1));
Cartesian2.UNIT_X = Object.freeze(new Cartesian2(1, 0));
Cartesian2.UNIT_Y = Object.freeze(new Cartesian2(0, 1));
Cartesian2.prototype.clone = function(result) {
return Cartesian2.clone(this, result);
};
Cartesian2.prototype.equals = function(right) {
return Cartesian2.equals(this, right);
};
Cartesian2.prototype.equalsEpsilon = function(right, relativeEpsilon, absoluteEpsilon) {
return Cartesian2.equalsEpsilon(
this,
right,
relativeEpsilon,
absoluteEpsilon
);
};
Cartesian2.prototype.toString = function() {
return `(${this.x}, ${this.y})`;
};
var Cartesian2_default = Cartesian2;
// packages/engine/Source/Core/Cartographic.js
var import_InlineWorkers26 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/scaleToGeodeticSurface.js
var import_InlineWorkers25 = __toESM(require_InlineWorkers(), 1);
var scaleToGeodeticSurfaceIntersection = new Cartesian3_default();
var scaleToGeodeticSurfaceGradient = new Cartesian3_default();
function scaleToGeodeticSurface(cartesian11, oneOverRadii, oneOverRadiiSquared, centerToleranceSquared, result) {
if (!defined_default(cartesian11)) {
throw new DeveloperError_default("cartesian is required.");
}
if (!defined_default(oneOverRadii)) {
throw new DeveloperError_default("oneOverRadii is required.");
}
if (!defined_default(oneOverRadiiSquared)) {
throw new DeveloperError_default("oneOverRadiiSquared is required.");
}
if (!defined_default(centerToleranceSquared)) {
throw new DeveloperError_default("centerToleranceSquared is required.");
}
const positionX = cartesian11.x;
const positionY = cartesian11.y;
const positionZ = cartesian11.z;
const oneOverRadiiX = oneOverRadii.x;
const oneOverRadiiY = oneOverRadii.y;
const oneOverRadiiZ = oneOverRadii.z;
const x2 = positionX * positionX * oneOverRadiiX * oneOverRadiiX;
const y2 = positionY * positionY * oneOverRadiiY * oneOverRadiiY;
const z2 = positionZ * positionZ * oneOverRadiiZ * oneOverRadiiZ;
const squaredNorm = x2 + y2 + z2;
const ratio = Math.sqrt(1 / squaredNorm);
const intersection = Cartesian3_default.multiplyByScalar(
cartesian11,
ratio,
scaleToGeodeticSurfaceIntersection
);
if (squaredNorm < centerToleranceSquared) {
return !isFinite(ratio) ? void 0 : Cartesian3_default.clone(intersection, result);
}
const oneOverRadiiSquaredX = oneOverRadiiSquared.x;
const oneOverRadiiSquaredY = oneOverRadiiSquared.y;
const oneOverRadiiSquaredZ = oneOverRadiiSquared.z;
const gradient = scaleToGeodeticSurfaceGradient;
gradient.x = intersection.x * oneOverRadiiSquaredX * 2;
gradient.y = intersection.y * oneOverRadiiSquaredY * 2;
gradient.z = intersection.z * oneOverRadiiSquaredZ * 2;
let lambda = (1 - ratio) * Cartesian3_default.magnitude(cartesian11) / (0.5 * Cartesian3_default.magnitude(gradient));
let correction = 0;
let func;
let denominator;
let xMultiplier;
let yMultiplier;
let zMultiplier;
let xMultiplier2;
let yMultiplier2;
let zMultiplier2;
let xMultiplier3;
let yMultiplier3;
let zMultiplier3;
do {
lambda -= correction;
xMultiplier = 1 / (1 + lambda * oneOverRadiiSquaredX);
yMultiplier = 1 / (1 + lambda * oneOverRadiiSquaredY);
zMultiplier = 1 / (1 + lambda * oneOverRadiiSquaredZ);
xMultiplier2 = xMultiplier * xMultiplier;
yMultiplier2 = yMultiplier * yMultiplier;
zMultiplier2 = zMultiplier * zMultiplier;
xMultiplier3 = xMultiplier2 * xMultiplier;
yMultiplier3 = yMultiplier2 * yMultiplier;
zMultiplier3 = zMultiplier2 * zMultiplier;
func = x2 * xMultiplier2 + y2 * yMultiplier2 + z2 * zMultiplier2 - 1;
denominator = x2 * xMultiplier3 * oneOverRadiiSquaredX + y2 * yMultiplier3 * oneOverRadiiSquaredY + z2 * zMultiplier3 * oneOverRadiiSquaredZ;
const derivative = -2 * denominator;
correction = func / derivative;
} while (Math.abs(func) > Math_default.EPSILON12);
if (!defined_default(result)) {
return new Cartesian3_default(
positionX * xMultiplier,
positionY * yMultiplier,
positionZ * zMultiplier
);
}
result.x = positionX * xMultiplier;
result.y = positionY * yMultiplier;
result.z = positionZ * zMultiplier;
return result;
}
var scaleToGeodeticSurface_default = scaleToGeodeticSurface;
// packages/engine/Source/Core/Cartographic.js
function Cartographic(longitude, latitude, height) {
this.longitude = longitude ?? 0;
this.latitude = latitude ?? 0;
this.height = height ?? 0;
}
Cartographic.fromRadians = function(longitude, latitude, height, result) {
Check_default.typeOf.number("longitude", longitude);
Check_default.typeOf.number("latitude", latitude);
height = height ?? 0;
if (!defined_default(result)) {
return new Cartographic(longitude, latitude, height);
}
result.longitude = longitude;
result.latitude = latitude;
result.height = height;
return result;
};
Cartographic.fromDegrees = function(longitude, latitude, height, result) {
Check_default.typeOf.number("longitude", longitude);
Check_default.typeOf.number("latitude", latitude);
longitude = Math_default.toRadians(longitude);
latitude = Math_default.toRadians(latitude);
return Cartographic.fromRadians(longitude, latitude, height, result);
};
var cartesianToCartographicN = new Cartesian3_default();
var cartesianToCartographicP = new Cartesian3_default();
var cartesianToCartographicH = new Cartesian3_default();
Cartographic._ellipsoidOneOverRadii = new Cartesian3_default(
1 / 6378137,
1 / 6378137,
1 / 6356752314245179e-9
);
Cartographic._ellipsoidOneOverRadiiSquared = new Cartesian3_default(
1 / (6378137 * 6378137),
1 / (6378137 * 6378137),
1 / (6356752314245179e-9 * 6356752314245179e-9)
);
Cartographic._ellipsoidCenterToleranceSquared = Math_default.EPSILON1;
Cartographic.fromCartesian = function(cartesian11, ellipsoid, result) {
const oneOverRadii = defined_default(ellipsoid) ? ellipsoid.oneOverRadii : Cartographic._ellipsoidOneOverRadii;
const oneOverRadiiSquared = defined_default(ellipsoid) ? ellipsoid.oneOverRadiiSquared : Cartographic._ellipsoidOneOverRadiiSquared;
const centerToleranceSquared = defined_default(ellipsoid) ? ellipsoid._centerToleranceSquared : Cartographic._ellipsoidCenterToleranceSquared;
const p = scaleToGeodeticSurface_default(
cartesian11,
oneOverRadii,
oneOverRadiiSquared,
centerToleranceSquared,
cartesianToCartographicP
);
if (!defined_default(p)) {
return void 0;
}
let n = Cartesian3_default.multiplyComponents(
p,
oneOverRadiiSquared,
cartesianToCartographicN
);
n = Cartesian3_default.normalize(n, n);
const h = Cartesian3_default.subtract(cartesian11, p, cartesianToCartographicH);
const longitude = Math.atan2(n.y, n.x);
const latitude = Math.asin(n.z);
const height = Math_default.sign(Cartesian3_default.dot(h, cartesian11)) * Cartesian3_default.magnitude(h);
if (!defined_default(result)) {
return new Cartographic(longitude, latitude, height);
}
result.longitude = longitude;
result.latitude = latitude;
result.height = height;
return result;
};
Cartographic.toCartesian = function(cartographic2, ellipsoid, result) {
Check_default.defined("cartographic", cartographic2);
return Cartesian3_default.fromRadians(
cartographic2.longitude,
cartographic2.latitude,
cartographic2.height,
ellipsoid,
result
);
};
Cartographic.clone = function(cartographic2, result) {
if (!defined_default(cartographic2)) {
return void 0;
}
if (!defined_default(result)) {
return new Cartographic(
cartographic2.longitude,
cartographic2.latitude,
cartographic2.height
);
}
result.longitude = cartographic2.longitude;
result.latitude = cartographic2.latitude;
result.height = cartographic2.height;
return result;
};
Cartographic.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left.longitude === right.longitude && left.latitude === right.latitude && left.height === right.height;
};
Cartographic.equalsEpsilon = function(left, right, epsilon) {
epsilon = epsilon ?? 0;
return left === right || defined_default(left) && defined_default(right) && Math.abs(left.longitude - right.longitude) <= epsilon && Math.abs(left.latitude - right.latitude) <= epsilon && Math.abs(left.height - right.height) <= epsilon;
};
Cartographic.ZERO = Object.freeze(new Cartographic(0, 0, 0));
Cartographic.prototype.clone = function(result) {
return Cartographic.clone(this, result);
};
Cartographic.prototype.equals = function(right) {
return Cartographic.equals(this, right);
};
Cartographic.prototype.equalsEpsilon = function(right, epsilon) {
return Cartographic.equalsEpsilon(this, right, epsilon);
};
Cartographic.prototype.toString = function() {
return `(${this.longitude}, ${this.latitude}, ${this.height})`;
};
var Cartographic_default = Cartographic;
// packages/engine/Source/Core/Ellipsoid.js
var import_InlineWorkers27 = __toESM(require_InlineWorkers(), 1);
function initialize(ellipsoid, x, y, z) {
x = x ?? 0;
y = y ?? 0;
z = z ?? 0;
Check_default.typeOf.number.greaterThanOrEquals("x", x, 0);
Check_default.typeOf.number.greaterThanOrEquals("y", y, 0);
Check_default.typeOf.number.greaterThanOrEquals("z", z, 0);
ellipsoid._radii = new Cartesian3_default(x, y, z);
ellipsoid._radiiSquared = new Cartesian3_default(x * x, y * y, z * z);
ellipsoid._radiiToTheFourth = new Cartesian3_default(
x * x * x * x,
y * y * y * y,
z * z * z * z
);
ellipsoid._oneOverRadii = new Cartesian3_default(
x === 0 ? 0 : 1 / x,
y === 0 ? 0 : 1 / y,
z === 0 ? 0 : 1 / z
);
ellipsoid._oneOverRadiiSquared = new Cartesian3_default(
x === 0 ? 0 : 1 / (x * x),
y === 0 ? 0 : 1 / (y * y),
z === 0 ? 0 : 1 / (z * z)
);
ellipsoid._minimumRadius = Math.min(x, y, z);
ellipsoid._maximumRadius = Math.max(x, y, z);
ellipsoid._centerToleranceSquared = Math_default.EPSILON1;
if (ellipsoid._radiiSquared.z !== 0) {
ellipsoid._squaredXOverSquaredZ = ellipsoid._radiiSquared.x / ellipsoid._radiiSquared.z;
}
}
function Ellipsoid(x, y, z) {
this._radii = void 0;
this._radiiSquared = void 0;
this._radiiToTheFourth = void 0;
this._oneOverRadii = void 0;
this._oneOverRadiiSquared = void 0;
this._minimumRadius = void 0;
this._maximumRadius = void 0;
this._centerToleranceSquared = void 0;
this._squaredXOverSquaredZ = void 0;
initialize(this, x, y, z);
}
Object.defineProperties(Ellipsoid.prototype, {
/**
* Gets the radii of the ellipsoid.
* @memberof Ellipsoid.prototype
* @type {Cartesian3}
* @readonly
*/
radii: {
get: function() {
return this._radii;
}
},
/**
* Gets the squared radii of the ellipsoid.
* @memberof Ellipsoid.prototype
* @type {Cartesian3}
* @readonly
*/
radiiSquared: {
get: function() {
return this._radiiSquared;
}
},
/**
* Gets the radii of the ellipsoid raise to the fourth power.
* @memberof Ellipsoid.prototype
* @type {Cartesian3}
* @readonly
*/
radiiToTheFourth: {
get: function() {
return this._radiiToTheFourth;
}
},
/**
* Gets one over the radii of the ellipsoid.
* @memberof Ellipsoid.prototype
* @type {Cartesian3}
* @readonly
*/
oneOverRadii: {
get: function() {
return this._oneOverRadii;
}
},
/**
* Gets one over the squared radii of the ellipsoid.
* @memberof Ellipsoid.prototype
* @type {Cartesian3}
* @readonly
*/
oneOverRadiiSquared: {
get: function() {
return this._oneOverRadiiSquared;
}
},
/**
* Gets the minimum radius of the ellipsoid.
* @memberof Ellipsoid.prototype
* @type {number}
* @readonly
*/
minimumRadius: {
get: function() {
return this._minimumRadius;
}
},
/**
* Gets the maximum radius of the ellipsoid.
* @memberof Ellipsoid.prototype
* @type {number}
* @readonly
*/
maximumRadius: {
get: function() {
return this._maximumRadius;
}
}
});
Ellipsoid.clone = function(ellipsoid, result) {
if (!defined_default(ellipsoid)) {
return void 0;
}
const radii = ellipsoid._radii;
if (!defined_default(result)) {
return new Ellipsoid(radii.x, radii.y, radii.z);
}
Cartesian3_default.clone(radii, result._radii);
Cartesian3_default.clone(ellipsoid._radiiSquared, result._radiiSquared);
Cartesian3_default.clone(ellipsoid._radiiToTheFourth, result._radiiToTheFourth);
Cartesian3_default.clone(ellipsoid._oneOverRadii, result._oneOverRadii);
Cartesian3_default.clone(ellipsoid._oneOverRadiiSquared, result._oneOverRadiiSquared);
result._minimumRadius = ellipsoid._minimumRadius;
result._maximumRadius = ellipsoid._maximumRadius;
result._centerToleranceSquared = ellipsoid._centerToleranceSquared;
return result;
};
Ellipsoid.fromCartesian3 = function(cartesian11, result) {
if (!defined_default(result)) {
result = new Ellipsoid();
}
if (!defined_default(cartesian11)) {
return result;
}
initialize(result, cartesian11.x, cartesian11.y, cartesian11.z);
return result;
};
Ellipsoid.WGS84 = Object.freeze(
new Ellipsoid(6378137, 6378137, 6356752314245179e-9)
);
Ellipsoid.UNIT_SPHERE = Object.freeze(new Ellipsoid(1, 1, 1));
Ellipsoid.MOON = Object.freeze(
new Ellipsoid(
Math_default.LUNAR_RADIUS,
Math_default.LUNAR_RADIUS,
Math_default.LUNAR_RADIUS
)
);
Ellipsoid.MARS = Object.freeze(new Ellipsoid(3396190, 3396190, 3376200));
Ellipsoid._default = Ellipsoid.WGS84;
Object.defineProperties(Ellipsoid, {
/**
* The default ellipsoid used when not otherwise specified.
* @memberof Ellipsoid
* @type {Ellipsoid}
* @example
* Cesium.Ellipsoid.default = Cesium.Ellipsoid.MOON;
*
* // Apollo 11 landing site
* const position = Cesium.Cartesian3.fromRadians(
* 0.67416,
* 23.47315,
* );
*/
default: {
get: function() {
return Ellipsoid._default;
},
set: function(value) {
Check_default.typeOf.object("value", value);
Ellipsoid._default = value;
Cartesian3_default._ellipsoidRadiiSquared = value.radiiSquared;
Cartographic_default._ellipsoidOneOverRadii = value.oneOverRadii;
Cartographic_default._ellipsoidOneOverRadiiSquared = value.oneOverRadiiSquared;
Cartographic_default._ellipsoidCenterToleranceSquared = value._centerToleranceSquared;
}
}
});
Ellipsoid.prototype.clone = function(result) {
return Ellipsoid.clone(this, result);
};
Ellipsoid.packedLength = Cartesian3_default.packedLength;
Ellipsoid.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
Cartesian3_default.pack(value._radii, array, startingIndex);
return array;
};
Ellipsoid.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const radii = Cartesian3_default.unpack(array, startingIndex);
return Ellipsoid.fromCartesian3(radii, result);
};
Ellipsoid.prototype.geocentricSurfaceNormal = Cartesian3_default.normalize;
Ellipsoid.prototype.geodeticSurfaceNormalCartographic = function(cartographic2, result) {
Check_default.typeOf.object("cartographic", cartographic2);
const longitude = cartographic2.longitude;
const latitude = cartographic2.latitude;
const cosLatitude = Math.cos(latitude);
const x = cosLatitude * Math.cos(longitude);
const y = cosLatitude * Math.sin(longitude);
const z = Math.sin(latitude);
if (!defined_default(result)) {
result = new Cartesian3_default();
}
result.x = x;
result.y = y;
result.z = z;
return Cartesian3_default.normalize(result, result);
};
Ellipsoid.prototype.geodeticSurfaceNormal = function(cartesian11, result) {
Check_default.typeOf.object("cartesian", cartesian11);
if (isNaN(cartesian11.x) || isNaN(cartesian11.y) || isNaN(cartesian11.z)) {
throw new DeveloperError_default("cartesian has a NaN component");
}
if (Cartesian3_default.equalsEpsilon(cartesian11, Cartesian3_default.ZERO, Math_default.EPSILON14)) {
return void 0;
}
if (!defined_default(result)) {
result = new Cartesian3_default();
}
result = Cartesian3_default.multiplyComponents(
cartesian11,
this._oneOverRadiiSquared,
result
);
return Cartesian3_default.normalize(result, result);
};
var cartographicToCartesianNormal = new Cartesian3_default();
var cartographicToCartesianK = new Cartesian3_default();
Ellipsoid.prototype.cartographicToCartesian = function(cartographic2, result) {
const n = cartographicToCartesianNormal;
const k = cartographicToCartesianK;
this.geodeticSurfaceNormalCartographic(cartographic2, n);
Cartesian3_default.multiplyComponents(this._radiiSquared, n, k);
const gamma = Math.sqrt(Cartesian3_default.dot(n, k));
Cartesian3_default.divideByScalar(k, gamma, k);
Cartesian3_default.multiplyByScalar(n, cartographic2.height, n);
if (!defined_default(result)) {
result = new Cartesian3_default();
}
return Cartesian3_default.add(k, n, result);
};
Ellipsoid.prototype.cartographicArrayToCartesianArray = function(cartographics, result) {
Check_default.defined("cartographics", cartographics);
const length2 = cartographics.length;
if (!defined_default(result)) {
result = new Array(length2);
} else {
result.length = length2;
}
for (let i = 0; i < length2; i++) {
result[i] = this.cartographicToCartesian(cartographics[i], result[i]);
}
return result;
};
var cartesianToCartographicN2 = new Cartesian3_default();
var cartesianToCartographicP2 = new Cartesian3_default();
var cartesianToCartographicH2 = new Cartesian3_default();
Ellipsoid.prototype.cartesianToCartographic = function(cartesian11, result) {
const p = this.scaleToGeodeticSurface(cartesian11, cartesianToCartographicP2);
if (!defined_default(p)) {
return void 0;
}
const n = this.geodeticSurfaceNormal(p, cartesianToCartographicN2);
const h = Cartesian3_default.subtract(cartesian11, p, cartesianToCartographicH2);
const longitude = Math.atan2(n.y, n.x);
const latitude = Math.asin(n.z);
const height = Math_default.sign(Cartesian3_default.dot(h, cartesian11)) * Cartesian3_default.magnitude(h);
if (!defined_default(result)) {
return new Cartographic_default(longitude, latitude, height);
}
result.longitude = longitude;
result.latitude = latitude;
result.height = height;
return result;
};
Ellipsoid.prototype.cartesianArrayToCartographicArray = function(cartesians, result) {
Check_default.defined("cartesians", cartesians);
const length2 = cartesians.length;
if (!defined_default(result)) {
result = new Array(length2);
} else {
result.length = length2;
}
for (let i = 0; i < length2; ++i) {
result[i] = this.cartesianToCartographic(cartesians[i], result[i]);
}
return result;
};
Ellipsoid.prototype.scaleToGeodeticSurface = function(cartesian11, result) {
return scaleToGeodeticSurface_default(
cartesian11,
this._oneOverRadii,
this._oneOverRadiiSquared,
this._centerToleranceSquared,
result
);
};
Ellipsoid.prototype.scaleToGeocentricSurface = function(cartesian11, result) {
Check_default.typeOf.object("cartesian", cartesian11);
if (!defined_default(result)) {
result = new Cartesian3_default();
}
const positionX = cartesian11.x;
const positionY = cartesian11.y;
const positionZ = cartesian11.z;
const oneOverRadiiSquared = this._oneOverRadiiSquared;
const beta = 1 / Math.sqrt(
positionX * positionX * oneOverRadiiSquared.x + positionY * positionY * oneOverRadiiSquared.y + positionZ * positionZ * oneOverRadiiSquared.z
);
return Cartesian3_default.multiplyByScalar(cartesian11, beta, result);
};
Ellipsoid.prototype.transformPositionToScaledSpace = function(position, result) {
if (!defined_default(result)) {
result = new Cartesian3_default();
}
return Cartesian3_default.multiplyComponents(position, this._oneOverRadii, result);
};
Ellipsoid.prototype.transformPositionFromScaledSpace = function(position, result) {
if (!defined_default(result)) {
result = new Cartesian3_default();
}
return Cartesian3_default.multiplyComponents(position, this._radii, result);
};
Ellipsoid.prototype.equals = function(right) {
return this === right || defined_default(right) && Cartesian3_default.equals(this._radii, right._radii);
};
Ellipsoid.prototype.toString = function() {
return this._radii.toString();
};
Ellipsoid.prototype.getSurfaceNormalIntersectionWithZAxis = function(position, buffer2, result) {
Check_default.typeOf.object("position", position);
if (!Math_default.equalsEpsilon(
this._radii.x,
this._radii.y,
Math_default.EPSILON15
)) {
throw new DeveloperError_default(
"Ellipsoid must be an ellipsoid of revolution (radii.x == radii.y)"
);
}
Check_default.typeOf.number.greaterThan("Ellipsoid.radii.z", this._radii.z, 0);
buffer2 = buffer2 ?? 0;
const squaredXOverSquaredZ = this._squaredXOverSquaredZ;
if (!defined_default(result)) {
result = new Cartesian3_default();
}
result.x = 0;
result.y = 0;
result.z = position.z * (1 - squaredXOverSquaredZ);
if (Math.abs(result.z) >= this._radii.z - buffer2) {
return void 0;
}
return result;
};
var scratchEndpoint = new Cartesian3_default();
Ellipsoid.prototype.getLocalCurvature = function(surfacePosition, result) {
Check_default.typeOf.object("surfacePosition", surfacePosition);
if (!defined_default(result)) {
result = new Cartesian2_default();
}
const primeVerticalEndpoint = this.getSurfaceNormalIntersectionWithZAxis(
surfacePosition,
0,
scratchEndpoint
);
const primeVerticalRadius = Cartesian3_default.distance(
surfacePosition,
primeVerticalEndpoint
);
const radiusRatio = this.minimumRadius * primeVerticalRadius / this.maximumRadius ** 2;
const meridionalRadius = primeVerticalRadius * radiusRatio ** 2;
return Cartesian2_default.fromElements(
1 / primeVerticalRadius,
1 / meridionalRadius,
result
);
};
var abscissas = [
0.14887433898163,
0.43339539412925,
0.67940956829902,
0.86506336668898,
0.97390652851717,
0
];
var weights = [
0.29552422471475,
0.26926671930999,
0.21908636251598,
0.14945134915058,
0.066671344308684,
0
];
function gaussLegendreQuadrature(a3, b, func) {
Check_default.typeOf.number("a", a3);
Check_default.typeOf.number("b", b);
Check_default.typeOf.func("func", func);
const xMean = 0.5 * (b + a3);
const xRange = 0.5 * (b - a3);
let sum = 0;
for (let i = 0; i < 5; i++) {
const dx = xRange * abscissas[i];
sum += weights[i] * (func(xMean + dx) + func(xMean - dx));
}
sum *= xRange;
return sum;
}
Ellipsoid.prototype.surfaceArea = function(rectangle) {
Check_default.typeOf.object("rectangle", rectangle);
const minLongitude = rectangle.west;
let maxLongitude = rectangle.east;
const minLatitude = rectangle.south;
const maxLatitude = rectangle.north;
while (maxLongitude < minLongitude) {
maxLongitude += Math_default.TWO_PI;
}
const radiiSquared = this._radiiSquared;
const a22 = radiiSquared.x;
const b2 = radiiSquared.y;
const c22 = radiiSquared.z;
const a2b2 = a22 * b2;
return gaussLegendreQuadrature(minLatitude, maxLatitude, function(lat) {
const sinPhi = Math.cos(lat);
const cosPhi = Math.sin(lat);
return Math.cos(lat) * gaussLegendreQuadrature(minLongitude, maxLongitude, function(lon) {
const cosTheta = Math.cos(lon);
const sinTheta = Math.sin(lon);
return Math.sqrt(
a2b2 * cosPhi * cosPhi + c22 * (b2 * cosTheta * cosTheta + a22 * sinTheta * sinTheta) * sinPhi * sinPhi
);
});
});
};
var Ellipsoid_default = Ellipsoid;
// packages/engine/Source/Core/GeographicProjection.js
var import_InlineWorkers28 = __toESM(require_InlineWorkers(), 1);
function GeographicProjection(ellipsoid) {
this._ellipsoid = ellipsoid ?? Ellipsoid_default.default;
this._semimajorAxis = this._ellipsoid.maximumRadius;
this._oneOverSemimajorAxis = 1 / this._semimajorAxis;
}
Object.defineProperties(GeographicProjection.prototype, {
/**
* Gets the {@link Ellipsoid}.
*
* @memberof GeographicProjection.prototype
*
* @type {Ellipsoid}
* @readonly
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
}
});
GeographicProjection.prototype.project = function(cartographic2, result) {
const semimajorAxis = this._semimajorAxis;
const x = cartographic2.longitude * semimajorAxis;
const y = cartographic2.latitude * semimajorAxis;
const z = cartographic2.height;
if (!defined_default(result)) {
return new Cartesian3_default(x, y, z);
}
result.x = x;
result.y = y;
result.z = z;
return result;
};
GeographicProjection.prototype.unproject = function(cartesian11, result) {
if (!defined_default(cartesian11)) {
throw new DeveloperError_default("cartesian is required");
}
const oneOverEarthSemimajorAxis = this._oneOverSemimajorAxis;
const longitude = cartesian11.x * oneOverEarthSemimajorAxis;
const latitude = cartesian11.y * oneOverEarthSemimajorAxis;
const height = cartesian11.z;
if (!defined_default(result)) {
return new Cartographic_default(longitude, latitude, height);
}
result.longitude = longitude;
result.latitude = latitude;
result.height = height;
return result;
};
var GeographicProjection_default = GeographicProjection;
// packages/engine/Source/Core/Intersect.js
var import_InlineWorkers29 = __toESM(require_InlineWorkers(), 1);
var Intersect = {
/**
* Represents that an object is not contained within the frustum.
*
* @type {number}
* @constant
*/
OUTSIDE: -1,
/**
* Represents that an object intersects one of the frustum's planes.
*
* @type {number}
* @constant
*/
INTERSECTING: 0,
/**
* Represents that an object is fully within the frustum.
*
* @type {number}
* @constant
*/
INSIDE: 1
};
var Intersect_default = Object.freeze(Intersect);
// packages/engine/Source/Core/Rectangle.js
var import_InlineWorkers69 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/Transforms.js
var import_InlineWorkers68 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/EarthOrientationParameters.js
var import_InlineWorkers62 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/binarySearch.js
var import_InlineWorkers30 = __toESM(require_InlineWorkers(), 1);
function binarySearch(array, itemToFind, comparator) {
Check_default.defined("array", array);
Check_default.defined("itemToFind", itemToFind);
Check_default.defined("comparator", comparator);
let low = 0;
let high = array.length - 1;
let i;
let comparison;
while (low <= high) {
i = ~~((low + high) / 2);
comparison = comparator(array[i], itemToFind);
if (comparison < 0) {
low = i + 1;
continue;
}
if (comparison > 0) {
high = i - 1;
continue;
}
return i;
}
return ~(high + 1);
}
var binarySearch_default = binarySearch;
// packages/engine/Source/Core/EarthOrientationParametersSample.js
var import_InlineWorkers31 = __toESM(require_InlineWorkers(), 1);
function EarthOrientationParametersSample(xPoleWander, yPoleWander, xPoleOffset, yPoleOffset, ut1MinusUtc) {
this.xPoleWander = xPoleWander;
this.yPoleWander = yPoleWander;
this.xPoleOffset = xPoleOffset;
this.yPoleOffset = yPoleOffset;
this.ut1MinusUtc = ut1MinusUtc;
}
var EarthOrientationParametersSample_default = EarthOrientationParametersSample;
// packages/engine/Source/Core/JulianDate.js
var import_InlineWorkers37 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/GregorianDate.js
var import_InlineWorkers33 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/isLeapYear.js
var import_InlineWorkers32 = __toESM(require_InlineWorkers(), 1);
function isLeapYear(year) {
if (year === null || isNaN(year)) {
throw new DeveloperError_default("year is required and must be a number.");
}
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
}
var isLeapYear_default = isLeapYear;
// packages/engine/Source/Core/GregorianDate.js
var daysInYear = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
function GregorianDate(year, month, day, hour, minute, second, millisecond, isLeapSecond) {
const minimumYear = 1;
const minimumMonth = 1;
const minimumDay = 1;
const minimumHour = 0;
const minimumMinute = 0;
const minimumSecond = 0;
const minimumMillisecond = 0;
year = year ?? minimumYear;
month = month ?? minimumMonth;
day = day ?? minimumDay;
hour = hour ?? minimumHour;
minute = minute ?? minimumMinute;
second = second ?? minimumSecond;
millisecond = millisecond ?? minimumMillisecond;
isLeapSecond = isLeapSecond ?? false;
validateRange();
validateDate();
this.year = year;
this.month = month;
this.day = day;
this.hour = hour;
this.minute = minute;
this.second = second;
this.millisecond = millisecond;
this.isLeapSecond = isLeapSecond;
function validateRange() {
const maximumYear = 9999;
const maximumMonth = 12;
const maximumDay = 31;
const maximumHour = 23;
const maximumMinute = 59;
const maximumSecond = 59;
const excludedMaximumMilisecond = 1e3;
Check_default.typeOf.number.greaterThanOrEquals("Year", year, minimumYear);
Check_default.typeOf.number.lessThanOrEquals("Year", year, maximumYear);
Check_default.typeOf.number.greaterThanOrEquals("Month", month, minimumMonth);
Check_default.typeOf.number.lessThanOrEquals("Month", month, maximumMonth);
Check_default.typeOf.number.greaterThanOrEquals("Day", day, minimumDay);
Check_default.typeOf.number.lessThanOrEquals("Day", day, maximumDay);
Check_default.typeOf.number.greaterThanOrEquals("Hour", hour, minimumHour);
Check_default.typeOf.number.lessThanOrEquals("Hour", hour, maximumHour);
Check_default.typeOf.number.greaterThanOrEquals("Minute", minute, minimumMinute);
Check_default.typeOf.number.lessThanOrEquals("Minute", minute, maximumMinute);
Check_default.typeOf.bool("IsLeapSecond", isLeapSecond);
Check_default.typeOf.number.greaterThanOrEquals("Second", second, minimumSecond);
Check_default.typeOf.number.lessThanOrEquals(
"Second",
second,
isLeapSecond ? maximumSecond + 1 : maximumSecond
);
Check_default.typeOf.number.greaterThanOrEquals(
"Millisecond",
millisecond,
minimumMillisecond
);
Check_default.typeOf.number.lessThan(
"Millisecond",
millisecond,
excludedMaximumMilisecond
);
}
function validateDate() {
const daysInMonth2 = month === 2 && isLeapYear_default(year) ? daysInYear[month - 1] + 1 : daysInYear[month - 1];
if (day > daysInMonth2) {
throw new DeveloperError_default("Month and Day represents invalid date");
}
}
}
var GregorianDate_default = GregorianDate;
// packages/engine/Source/Core/LeapSecond.js
var import_InlineWorkers34 = __toESM(require_InlineWorkers(), 1);
function LeapSecond(date, offset) {
this.julianDate = date;
this.offset = offset;
}
var LeapSecond_default = LeapSecond;
// packages/engine/Source/Core/TimeConstants.js
var import_InlineWorkers35 = __toESM(require_InlineWorkers(), 1);
var TimeConstants = {
/**
* The number of seconds in one millisecond: 0.001
* @type {number}
* @constant
*/
SECONDS_PER_MILLISECOND: 1e-3,
/**
* The number of seconds in one minute: 60.
* @type {number}
* @constant
*/
SECONDS_PER_MINUTE: 60,
/**
* The number of minutes in one hour: 60.
* @type {number}
* @constant
*/
MINUTES_PER_HOUR: 60,
/**
* The number of hours in one day: 24.
* @type {number}
* @constant
*/
HOURS_PER_DAY: 24,
/**
* The number of seconds in one hour: 3600.
* @type {number}
* @constant
*/
SECONDS_PER_HOUR: 3600,
/**
* The number of minutes in one day: 1440.
* @type {number}
* @constant
*/
MINUTES_PER_DAY: 1440,
/**
* The number of seconds in one day, ignoring leap seconds: 86400.
* @type {number}
* @constant
*/
SECONDS_PER_DAY: 86400,
/**
* The number of days in one Julian century: 36525.
* @type {number}
* @constant
*/
DAYS_PER_JULIAN_CENTURY: 36525,
/**
* One trillionth of a second.
* @type {number}
* @constant
*/
PICOSECOND: 1e-9,
/**
* The number of days to subtract from a Julian date to determine the
* modified Julian date, which gives the number of days since midnight
* on November 17, 1858.
* @type {number}
* @constant
*/
MODIFIED_JULIAN_DATE_DIFFERENCE: 24000005e-1
};
var TimeConstants_default = Object.freeze(TimeConstants);
// packages/engine/Source/Core/TimeStandard.js
var import_InlineWorkers36 = __toESM(require_InlineWorkers(), 1);
var TimeStandard = {
/**
* Represents the coordinated Universal Time (UTC) time standard.
*
* UTC is related to TAI according to the relationship
* UTC = TAI - deltaT where deltaT is the number of leap
* seconds which have been introduced as of the time in TAI.
*
* @type {number}
* @constant
*/
UTC: 0,
/**
* Represents the International Atomic Time (TAI) time standard.
* TAI is the principal time standard to which the other time standards are related.
*
* @type {number}
* @constant
*/
TAI: 1
};
var TimeStandard_default = Object.freeze(TimeStandard);
// packages/engine/Source/Core/JulianDate.js
var gregorianDateScratch = new GregorianDate_default();
var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var daysInLeapFebruary = 29;
function compareLeapSecondDates(leapSecond, dateToFind) {
return JulianDate.compare(leapSecond.julianDate, dateToFind.julianDate);
}
var binarySearchScratchLeapSecond = new LeapSecond_default();
function convertUtcToTai(julianDate) {
binarySearchScratchLeapSecond.julianDate = julianDate;
const leapSeconds = JulianDate.leapSeconds;
let index = binarySearch_default(
leapSeconds,
binarySearchScratchLeapSecond,
compareLeapSecondDates
);
if (index < 0) {
index = ~index;
}
if (index >= leapSeconds.length) {
index = leapSeconds.length - 1;
}
let offset = leapSeconds[index].offset;
if (index > 0) {
const difference = JulianDate.secondsDifference(
leapSeconds[index].julianDate,
julianDate
);
if (difference > offset) {
index--;
offset = leapSeconds[index].offset;
}
}
JulianDate.addSeconds(julianDate, offset, julianDate);
}
function convertTaiToUtc(julianDate, result) {
binarySearchScratchLeapSecond.julianDate = julianDate;
const leapSeconds = JulianDate.leapSeconds;
let index = binarySearch_default(
leapSeconds,
binarySearchScratchLeapSecond,
compareLeapSecondDates
);
if (index < 0) {
index = ~index;
}
if (index === 0) {
return JulianDate.addSeconds(julianDate, -leapSeconds[0].offset, result);
}
if (index >= leapSeconds.length) {
return JulianDate.addSeconds(
julianDate,
-leapSeconds[index - 1].offset,
result
);
}
const difference = JulianDate.secondsDifference(
leapSeconds[index].julianDate,
julianDate
);
if (difference === 0) {
return JulianDate.addSeconds(
julianDate,
-leapSeconds[index].offset,
result
);
}
if (difference <= 1) {
return void 0;
}
return JulianDate.addSeconds(
julianDate,
-leapSeconds[--index].offset,
result
);
}
function setComponents(wholeDays, secondsOfDay, julianDate) {
const extraDays = secondsOfDay / TimeConstants_default.SECONDS_PER_DAY | 0;
wholeDays += extraDays;
secondsOfDay -= TimeConstants_default.SECONDS_PER_DAY * extraDays;
if (secondsOfDay < 0) {
wholeDays--;
secondsOfDay += TimeConstants_default.SECONDS_PER_DAY;
}
julianDate.dayNumber = wholeDays;
julianDate.secondsOfDay = secondsOfDay;
return julianDate;
}
function computeJulianDateComponents(year, month, day, hour, minute, second, millisecond) {
const a3 = (month - 14) / 12 | 0;
const b = year + 4800 + a3;
let dayNumber = (1461 * b / 4 | 0) + (367 * (month - 2 - 12 * a3) / 12 | 0) - (3 * ((b + 100) / 100 | 0) / 4 | 0) + day - 32075;
hour = hour - 12;
if (hour < 0) {
hour += 24;
}
const secondsOfDay = second + (hour * TimeConstants_default.SECONDS_PER_HOUR + minute * TimeConstants_default.SECONDS_PER_MINUTE + millisecond * TimeConstants_default.SECONDS_PER_MILLISECOND);
if (secondsOfDay >= 43200) {
dayNumber -= 1;
}
return [dayNumber, secondsOfDay];
}
var matchCalendarYear = /^(\d{4})$/;
var matchCalendarMonth = /^(\d{4})-(\d{2})$/;
var matchOrdinalDate = /^(\d{4})-?(\d{3})$/;
var matchWeekDate = /^(\d{4})-?W(\d{2})-?(\d{1})?$/;
var matchCalendarDate = /^(\d{4})-?(\d{2})-?(\d{2})$/;
var utcOffset = /([Z+\-])?(\d{2})?:?(\d{2})?$/;
var matchHours = /^(\d{2})(\.\d+)?/.source + utcOffset.source;
var matchHoursMinutes = /^(\d{2}):?(\d{2})(\.\d+)?/.source + utcOffset.source;
var matchHoursMinutesSeconds = /^(\d{2}):?(\d{2}):?(\d{2})(\.\d+)?/.source + utcOffset.source;
var iso8601ErrorMessage = "Invalid ISO 8601 date.";
function JulianDate(julianDayNumber, secondsOfDay, timeStandard) {
this.dayNumber = void 0;
this.secondsOfDay = void 0;
julianDayNumber = julianDayNumber ?? 0;
secondsOfDay = secondsOfDay ?? 0;
timeStandard = timeStandard ?? TimeStandard_default.UTC;
const wholeDays = julianDayNumber | 0;
secondsOfDay = secondsOfDay + (julianDayNumber - wholeDays) * TimeConstants_default.SECONDS_PER_DAY;
setComponents(wholeDays, secondsOfDay, this);
if (timeStandard === TimeStandard_default.UTC) {
convertUtcToTai(this);
}
}
JulianDate.fromGregorianDate = function(date, result) {
if (!(date instanceof GregorianDate_default)) {
throw new DeveloperError_default("date must be a valid GregorianDate.");
}
const components = computeJulianDateComponents(
date.year,
date.month,
date.day,
date.hour,
date.minute,
date.second,
date.millisecond
);
if (!defined_default(result)) {
return new JulianDate(components[0], components[1], TimeStandard_default.UTC);
}
setComponents(components[0], components[1], result);
convertUtcToTai(result);
return result;
};
JulianDate.fromDate = function(date, result) {
if (!(date instanceof Date) || isNaN(date.getTime())) {
throw new DeveloperError_default("date must be a valid JavaScript Date.");
}
const components = computeJulianDateComponents(
date.getUTCFullYear(),
date.getUTCMonth() + 1,
date.getUTCDate(),
date.getUTCHours(),
date.getUTCMinutes(),
date.getUTCSeconds(),
date.getUTCMilliseconds()
);
if (!defined_default(result)) {
return new JulianDate(components[0], components[1], TimeStandard_default.UTC);
}
setComponents(components[0], components[1], result);
convertUtcToTai(result);
return result;
};
JulianDate.fromIso8601 = function(iso8601String, result) {
if (typeof iso8601String !== "string") {
throw new DeveloperError_default(iso8601ErrorMessage);
}
iso8601String = iso8601String.replace(",", ".");
let tokens = iso8601String.split("T");
let year;
let month = 1;
let day = 1;
let hour = 0;
let minute = 0;
let second = 0;
let millisecond = 0;
const date = tokens[0];
const time = tokens[1];
let tmp2;
let inLeapYear;
if (!defined_default(date)) {
throw new DeveloperError_default(iso8601ErrorMessage);
}
let dashCount;
tokens = date.match(matchCalendarDate);
if (tokens !== null) {
dashCount = date.split("-").length - 1;
if (dashCount > 0 && dashCount !== 2) {
throw new DeveloperError_default(iso8601ErrorMessage);
}
year = +tokens[1];
month = +tokens[2];
day = +tokens[3];
} else {
tokens = date.match(matchCalendarMonth);
if (tokens !== null) {
year = +tokens[1];
month = +tokens[2];
} else {
tokens = date.match(matchCalendarYear);
if (tokens !== null) {
year = +tokens[1];
} else {
let dayOfYear;
tokens = date.match(matchOrdinalDate);
if (tokens !== null) {
year = +tokens[1];
dayOfYear = +tokens[2];
inLeapYear = isLeapYear_default(year);
if (dayOfYear < 1 || inLeapYear && dayOfYear > 366 || !inLeapYear && dayOfYear > 365) {
throw new DeveloperError_default(iso8601ErrorMessage);
}
} else {
tokens = date.match(matchWeekDate);
if (tokens !== null) {
year = +tokens[1];
const weekNumber = +tokens[2];
const dayOfWeek = +tokens[3] || 0;
dashCount = date.split("-").length - 1;
if (dashCount > 0 && (!defined_default(tokens[3]) && dashCount !== 1 || defined_default(tokens[3]) && dashCount !== 2)) {
throw new DeveloperError_default(iso8601ErrorMessage);
}
const january4 = new Date(Date.UTC(year, 0, 4));
dayOfYear = weekNumber * 7 + dayOfWeek - january4.getUTCDay() - 3;
} else {
throw new DeveloperError_default(iso8601ErrorMessage);
}
}
tmp2 = new Date(Date.UTC(year, 0, 1));
tmp2.setUTCDate(dayOfYear);
month = tmp2.getUTCMonth() + 1;
day = tmp2.getUTCDate();
}
}
}
inLeapYear = isLeapYear_default(year);
if (month < 1 || month > 12 || day < 1 || (month !== 2 || !inLeapYear) && day > daysInMonth[month - 1] || inLeapYear && month === 2 && day > daysInLeapFebruary) {
throw new DeveloperError_default(iso8601ErrorMessage);
}
let offsetIndex;
if (defined_default(time)) {
tokens = time.match(matchHoursMinutesSeconds);
if (tokens !== null) {
dashCount = time.split(":").length - 1;
if (dashCount > 0 && dashCount !== 2 && dashCount !== 3) {
throw new DeveloperError_default(iso8601ErrorMessage);
}
hour = +tokens[1];
minute = +tokens[2];
second = +tokens[3];
millisecond = +(tokens[4] || 0) * 1e3;
offsetIndex = 5;
} else {
tokens = time.match(matchHoursMinutes);
if (tokens !== null) {
dashCount = time.split(":").length - 1;
if (dashCount > 2) {
throw new DeveloperError_default(iso8601ErrorMessage);
}
hour = +tokens[1];
minute = +tokens[2];
second = +(tokens[3] || 0) * 60;
offsetIndex = 4;
} else {
tokens = time.match(matchHours);
if (tokens !== null) {
hour = +tokens[1];
minute = +(tokens[2] || 0) * 60;
offsetIndex = 3;
} else {
throw new DeveloperError_default(iso8601ErrorMessage);
}
}
}
if (minute >= 60 || second >= 61 || hour > 24 || hour === 24 && (minute > 0 || second > 0 || millisecond > 0)) {
throw new DeveloperError_default(iso8601ErrorMessage);
}
const offset = tokens[offsetIndex];
const offsetHours = +tokens[offsetIndex + 1];
const offsetMinutes = +(tokens[offsetIndex + 2] || 0);
switch (offset) {
case "+":
hour = hour - offsetHours;
minute = minute - offsetMinutes;
break;
case "-":
hour = hour + offsetHours;
minute = minute + offsetMinutes;
break;
case "Z":
break;
default:
minute = minute + new Date(
Date.UTC(year, month - 1, day, hour, minute)
).getTimezoneOffset();
break;
}
}
const isLeapSecond = second === 60;
if (isLeapSecond) {
second--;
}
while (minute >= 60) {
minute -= 60;
hour++;
}
while (hour >= 24) {
hour -= 24;
day++;
}
tmp2 = inLeapYear && month === 2 ? daysInLeapFebruary : daysInMonth[month - 1];
while (day > tmp2) {
day -= tmp2;
month++;
if (month > 12) {
month -= 12;
year++;
}
tmp2 = inLeapYear && month === 2 ? daysInLeapFebruary : daysInMonth[month - 1];
}
while (minute < 0) {
minute += 60;
hour--;
}
while (hour < 0) {
hour += 24;
day--;
}
while (day < 1) {
month--;
if (month < 1) {
month += 12;
year--;
}
tmp2 = inLeapYear && month === 2 ? daysInLeapFebruary : daysInMonth[month - 1];
day += tmp2;
}
const components = computeJulianDateComponents(
year,
month,
day,
hour,
minute,
second,
millisecond
);
if (!defined_default(result)) {
result = new JulianDate(components[0], components[1], TimeStandard_default.UTC);
} else {
setComponents(components[0], components[1], result);
convertUtcToTai(result);
}
if (isLeapSecond) {
JulianDate.addSeconds(result, 1, result);
}
return result;
};
JulianDate.now = function(result) {
return JulianDate.fromDate(/* @__PURE__ */ new Date(), result);
};
var toGregorianDateScratch = new JulianDate(0, 0, TimeStandard_default.TAI);
JulianDate.toGregorianDate = function(julianDate, result) {
if (!defined_default(julianDate)) {
throw new DeveloperError_default("julianDate is required.");
}
let isLeapSecond = false;
let thisUtc = convertTaiToUtc(julianDate, toGregorianDateScratch);
if (!defined_default(thisUtc)) {
JulianDate.addSeconds(julianDate, -1, toGregorianDateScratch);
thisUtc = convertTaiToUtc(toGregorianDateScratch, toGregorianDateScratch);
isLeapSecond = true;
}
let julianDayNumber = thisUtc.dayNumber;
const secondsOfDay = thisUtc.secondsOfDay;
if (secondsOfDay >= 43200) {
julianDayNumber += 1;
}
let L = julianDayNumber + 68569 | 0;
const N = 4 * L / 146097 | 0;
L = L - ((146097 * N + 3) / 4 | 0) | 0;
const I = 4e3 * (L + 1) / 1461001 | 0;
L = L - (1461 * I / 4 | 0) + 31 | 0;
const J = 80 * L / 2447 | 0;
const day = L - (2447 * J / 80 | 0) | 0;
L = J / 11 | 0;
const month = J + 2 - 12 * L | 0;
const year = 100 * (N - 49) + I + L | 0;
let hour = secondsOfDay / TimeConstants_default.SECONDS_PER_HOUR | 0;
let remainingSeconds = secondsOfDay - hour * TimeConstants_default.SECONDS_PER_HOUR;
const minute = remainingSeconds / TimeConstants_default.SECONDS_PER_MINUTE | 0;
remainingSeconds = remainingSeconds - minute * TimeConstants_default.SECONDS_PER_MINUTE;
let second = remainingSeconds | 0;
const millisecond = (remainingSeconds - second) / TimeConstants_default.SECONDS_PER_MILLISECOND;
hour += 12;
if (hour > 23) {
hour -= 24;
}
if (isLeapSecond) {
second += 1;
}
if (!defined_default(result)) {
return new GregorianDate_default(
year,
month,
day,
hour,
minute,
second,
millisecond,
isLeapSecond
);
}
result.year = year;
result.month = month;
result.day = day;
result.hour = hour;
result.minute = minute;
result.second = second;
result.millisecond = millisecond;
result.isLeapSecond = isLeapSecond;
return result;
};
JulianDate.toDate = function(julianDate) {
if (!defined_default(julianDate)) {
throw new DeveloperError_default("julianDate is required.");
}
const gDate = JulianDate.toGregorianDate(julianDate, gregorianDateScratch);
let second = gDate.second;
if (gDate.isLeapSecond) {
second -= 1;
}
return new Date(
Date.UTC(
gDate.year,
gDate.month - 1,
gDate.day,
gDate.hour,
gDate.minute,
second,
gDate.millisecond
)
);
};
JulianDate.toIso8601 = function(julianDate, precision) {
if (!defined_default(julianDate)) {
throw new DeveloperError_default("julianDate is required.");
}
const gDate = JulianDate.toGregorianDate(julianDate, gregorianDateScratch);
let year = gDate.year;
let month = gDate.month;
let day = gDate.day;
let hour = gDate.hour;
const minute = gDate.minute;
const second = gDate.second;
const millisecond = gDate.millisecond;
if (year === 1e4 && month === 1 && day === 1 && hour === 0 && minute === 0 && second === 0 && millisecond === 0) {
year = 9999;
month = 12;
day = 31;
hour = 24;
}
let millisecondStr;
if (!defined_default(precision) && millisecond !== 0) {
const millisecondHundreds = millisecond * 0.01;
millisecondStr = millisecondHundreds < 1e-6 ? millisecondHundreds.toFixed(20).replace(".", "").replace(/0+$/, "") : millisecondHundreds.toString().replace(".", "");
return `${year.toString().padStart(4, "0")}-${month.toString().padStart(2, "0")}-${day.toString().padStart(2, "0")}T${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}:${second.toString().padStart(2, "0")}.${millisecondStr}Z`;
}
if (!defined_default(precision) || precision === 0) {
return `${year.toString().padStart(4, "0")}-${month.toString().padStart(2, "0")}-${day.toString().padStart(2, "0")}T${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}:${second.toString().padStart(2, "0")}Z`;
}
millisecondStr = (millisecond * 0.01).toFixed(precision).replace(".", "").slice(0, precision);
return `${year.toString().padStart(4, "0")}-${month.toString().padStart(2, "0")}-${day.toString().padStart(2, "0")}T${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}:${second.toString().padStart(2, "0")}.${millisecondStr}Z`;
};
JulianDate.clone = function(julianDate, result) {
if (!defined_default(julianDate)) {
return void 0;
}
if (!defined_default(result)) {
return new JulianDate(
julianDate.dayNumber,
julianDate.secondsOfDay,
TimeStandard_default.TAI
);
}
result.dayNumber = julianDate.dayNumber;
result.secondsOfDay = julianDate.secondsOfDay;
return result;
};
JulianDate.compare = function(left, right) {
if (!defined_default(left)) {
throw new DeveloperError_default("left is required.");
}
if (!defined_default(right)) {
throw new DeveloperError_default("right is required.");
}
const julianDayNumberDifference = left.dayNumber - right.dayNumber;
if (julianDayNumberDifference !== 0) {
return julianDayNumberDifference;
}
return left.secondsOfDay - right.secondsOfDay;
};
JulianDate.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left.dayNumber === right.dayNumber && left.secondsOfDay === right.secondsOfDay;
};
JulianDate.equalsEpsilon = function(left, right, epsilon) {
epsilon = epsilon ?? 0;
return left === right || defined_default(left) && defined_default(right) && Math.abs(JulianDate.secondsDifference(left, right)) <= epsilon;
};
JulianDate.totalDays = function(julianDate) {
if (!defined_default(julianDate)) {
throw new DeveloperError_default("julianDate is required.");
}
return julianDate.dayNumber + julianDate.secondsOfDay / TimeConstants_default.SECONDS_PER_DAY;
};
JulianDate.secondsDifference = function(left, right) {
if (!defined_default(left)) {
throw new DeveloperError_default("left is required.");
}
if (!defined_default(right)) {
throw new DeveloperError_default("right is required.");
}
const dayDifference = (left.dayNumber - right.dayNumber) * TimeConstants_default.SECONDS_PER_DAY;
return dayDifference + (left.secondsOfDay - right.secondsOfDay);
};
JulianDate.daysDifference = function(left, right) {
if (!defined_default(left)) {
throw new DeveloperError_default("left is required.");
}
if (!defined_default(right)) {
throw new DeveloperError_default("right is required.");
}
const dayDifference = left.dayNumber - right.dayNumber;
const secondDifference = (left.secondsOfDay - right.secondsOfDay) / TimeConstants_default.SECONDS_PER_DAY;
return dayDifference + secondDifference;
};
JulianDate.computeTaiMinusUtc = function(julianDate) {
binarySearchScratchLeapSecond.julianDate = julianDate;
const leapSeconds = JulianDate.leapSeconds;
let index = binarySearch_default(
leapSeconds,
binarySearchScratchLeapSecond,
compareLeapSecondDates
);
if (index < 0) {
index = ~index;
--index;
if (index < 0) {
index = 0;
}
}
return leapSeconds[index].offset;
};
JulianDate.addSeconds = function(julianDate, seconds, result) {
if (!defined_default(julianDate)) {
throw new DeveloperError_default("julianDate is required.");
}
if (!defined_default(seconds)) {
throw new DeveloperError_default("seconds is required.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
return setComponents(
julianDate.dayNumber,
julianDate.secondsOfDay + seconds,
result
);
};
JulianDate.addMinutes = function(julianDate, minutes, result) {
if (!defined_default(julianDate)) {
throw new DeveloperError_default("julianDate is required.");
}
if (!defined_default(minutes)) {
throw new DeveloperError_default("minutes is required.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
const newSecondsOfDay = julianDate.secondsOfDay + minutes * TimeConstants_default.SECONDS_PER_MINUTE;
return setComponents(julianDate.dayNumber, newSecondsOfDay, result);
};
JulianDate.addHours = function(julianDate, hours, result) {
if (!defined_default(julianDate)) {
throw new DeveloperError_default("julianDate is required.");
}
if (!defined_default(hours)) {
throw new DeveloperError_default("hours is required.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
const newSecondsOfDay = julianDate.secondsOfDay + hours * TimeConstants_default.SECONDS_PER_HOUR;
return setComponents(julianDate.dayNumber, newSecondsOfDay, result);
};
JulianDate.addDays = function(julianDate, days, result) {
if (!defined_default(julianDate)) {
throw new DeveloperError_default("julianDate is required.");
}
if (!defined_default(days)) {
throw new DeveloperError_default("days is required.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
const newJulianDayNumber = julianDate.dayNumber + days;
return setComponents(newJulianDayNumber, julianDate.secondsOfDay, result);
};
JulianDate.lessThan = function(left, right) {
return JulianDate.compare(left, right) < 0;
};
JulianDate.lessThanOrEquals = function(left, right) {
return JulianDate.compare(left, right) <= 0;
};
JulianDate.greaterThan = function(left, right) {
return JulianDate.compare(left, right) > 0;
};
JulianDate.greaterThanOrEquals = function(left, right) {
return JulianDate.compare(left, right) >= 0;
};
JulianDate.prototype.clone = function(result) {
return JulianDate.clone(this, result);
};
JulianDate.prototype.equals = function(right) {
return JulianDate.equals(this, right);
};
JulianDate.prototype.equalsEpsilon = function(right, epsilon) {
return JulianDate.equalsEpsilon(this, right, epsilon);
};
JulianDate.prototype.toString = function() {
return JulianDate.toIso8601(this);
};
JulianDate.leapSeconds = [
new LeapSecond_default(new JulianDate(2441317, 43210, TimeStandard_default.TAI), 10),
// January 1, 1972 00:00:00 UTC
new LeapSecond_default(new JulianDate(2441499, 43211, TimeStandard_default.TAI), 11),
// July 1, 1972 00:00:00 UTC
new LeapSecond_default(new JulianDate(2441683, 43212, TimeStandard_default.TAI), 12),
// January 1, 1973 00:00:00 UTC
new LeapSecond_default(new JulianDate(2442048, 43213, TimeStandard_default.TAI), 13),
// January 1, 1974 00:00:00 UTC
new LeapSecond_default(new JulianDate(2442413, 43214, TimeStandard_default.TAI), 14),
// January 1, 1975 00:00:00 UTC
new LeapSecond_default(new JulianDate(2442778, 43215, TimeStandard_default.TAI), 15),
// January 1, 1976 00:00:00 UTC
new LeapSecond_default(new JulianDate(2443144, 43216, TimeStandard_default.TAI), 16),
// January 1, 1977 00:00:00 UTC
new LeapSecond_default(new JulianDate(2443509, 43217, TimeStandard_default.TAI), 17),
// January 1, 1978 00:00:00 UTC
new LeapSecond_default(new JulianDate(2443874, 43218, TimeStandard_default.TAI), 18),
// January 1, 1979 00:00:00 UTC
new LeapSecond_default(new JulianDate(2444239, 43219, TimeStandard_default.TAI), 19),
// January 1, 1980 00:00:00 UTC
new LeapSecond_default(new JulianDate(2444786, 43220, TimeStandard_default.TAI), 20),
// July 1, 1981 00:00:00 UTC
new LeapSecond_default(new JulianDate(2445151, 43221, TimeStandard_default.TAI), 21),
// July 1, 1982 00:00:00 UTC
new LeapSecond_default(new JulianDate(2445516, 43222, TimeStandard_default.TAI), 22),
// July 1, 1983 00:00:00 UTC
new LeapSecond_default(new JulianDate(2446247, 43223, TimeStandard_default.TAI), 23),
// July 1, 1985 00:00:00 UTC
new LeapSecond_default(new JulianDate(2447161, 43224, TimeStandard_default.TAI), 24),
// January 1, 1988 00:00:00 UTC
new LeapSecond_default(new JulianDate(2447892, 43225, TimeStandard_default.TAI), 25),
// January 1, 1990 00:00:00 UTC
new LeapSecond_default(new JulianDate(2448257, 43226, TimeStandard_default.TAI), 26),
// January 1, 1991 00:00:00 UTC
new LeapSecond_default(new JulianDate(2448804, 43227, TimeStandard_default.TAI), 27),
// July 1, 1992 00:00:00 UTC
new LeapSecond_default(new JulianDate(2449169, 43228, TimeStandard_default.TAI), 28),
// July 1, 1993 00:00:00 UTC
new LeapSecond_default(new JulianDate(2449534, 43229, TimeStandard_default.TAI), 29),
// July 1, 1994 00:00:00 UTC
new LeapSecond_default(new JulianDate(2450083, 43230, TimeStandard_default.TAI), 30),
// January 1, 1996 00:00:00 UTC
new LeapSecond_default(new JulianDate(2450630, 43231, TimeStandard_default.TAI), 31),
// July 1, 1997 00:00:00 UTC
new LeapSecond_default(new JulianDate(2451179, 43232, TimeStandard_default.TAI), 32),
// January 1, 1999 00:00:00 UTC
new LeapSecond_default(new JulianDate(2453736, 43233, TimeStandard_default.TAI), 33),
// January 1, 2006 00:00:00 UTC
new LeapSecond_default(new JulianDate(2454832, 43234, TimeStandard_default.TAI), 34),
// January 1, 2009 00:00:00 UTC
new LeapSecond_default(new JulianDate(2456109, 43235, TimeStandard_default.TAI), 35),
// July 1, 2012 00:00:00 UTC
new LeapSecond_default(new JulianDate(2457204, 43236, TimeStandard_default.TAI), 36),
// July 1, 2015 00:00:00 UTC
new LeapSecond_default(new JulianDate(2457754, 43237, TimeStandard_default.TAI), 37)
// January 1, 2017 00:00:00 UTC
];
var JulianDate_default = JulianDate;
// packages/engine/Source/Core/Resource.js
var import_InlineWorkers61 = __toESM(require_InlineWorkers(), 1);
var import_urijs6 = __toESM(require_URI(), 1);
// packages/engine/Source/Core/appendForwardSlash.js
var import_InlineWorkers38 = __toESM(require_InlineWorkers(), 1);
function appendForwardSlash(url2) {
if (url2.length === 0 || url2[url2.length - 1] !== "/") {
url2 = `${url2}/`;
}
return url2;
}
var appendForwardSlash_default = appendForwardSlash;
// packages/engine/Source/Core/clone.js
var import_InlineWorkers39 = __toESM(require_InlineWorkers(), 1);
function clone(object2, deep) {
if (object2 === null || typeof object2 !== "object") {
return object2;
}
deep = deep ?? false;
const result = new object2.constructor();
for (const propertyName in object2) {
if (object2.hasOwnProperty(propertyName)) {
let value = object2[propertyName];
if (deep) {
value = clone(value, deep);
}
result[propertyName] = value;
}
}
return result;
}
var clone_default = clone;
// packages/engine/Source/Core/combine.js
var import_InlineWorkers40 = __toESM(require_InlineWorkers(), 1);
function combine(object1, object2, deep) {
deep = deep ?? false;
const result = {};
const object1Defined = defined_default(object1);
const object2Defined = defined_default(object2);
let property;
let object1Value;
let object2Value;
if (object1Defined) {
for (property in object1) {
if (object1.hasOwnProperty(property)) {
object1Value = object1[property];
if (object2Defined && deep && typeof object1Value === "object" && object2.hasOwnProperty(property)) {
object2Value = object2[property];
if (typeof object2Value === "object") {
result[property] = combine(object1Value, object2Value, deep);
} else {
result[property] = object1Value;
}
} else {
result[property] = object1Value;
}
}
}
}
if (object2Defined) {
for (property in object2) {
if (object2.hasOwnProperty(property) && !result.hasOwnProperty(property)) {
object2Value = object2[property];
result[property] = object2Value;
}
}
}
return result;
}
var combine_default = combine;
// packages/engine/Source/Core/defer.js
var import_InlineWorkers41 = __toESM(require_InlineWorkers(), 1);
function defer() {
let resolve2;
let reject;
const promise = new Promise(function(res, rej) {
resolve2 = res;
reject = rej;
});
return {
resolve: resolve2,
reject,
promise
};
}
var defer_default = defer;
// packages/engine/Source/Core/getAbsoluteUri.js
var import_InlineWorkers42 = __toESM(require_InlineWorkers(), 1);
var import_urijs = __toESM(require_URI(), 1);
function getAbsoluteUri(relative, base) {
let documentObject;
if (typeof document !== "undefined") {
documentObject = document;
}
return getAbsoluteUri._implementation(relative, base, documentObject);
}
getAbsoluteUri._implementation = function(relative, base, documentObject) {
if (!defined_default(relative)) {
throw new DeveloperError_default("relative uri is required.");
}
if (!defined_default(base)) {
if (typeof documentObject === "undefined") {
return relative;
}
base = documentObject.baseURI ?? documentObject.location.href;
}
const relativeUri = new import_urijs.default(relative);
if (relativeUri.scheme() !== "") {
return relativeUri.toString();
}
return relativeUri.absoluteTo(base).toString();
};
var getAbsoluteUri_default = getAbsoluteUri;
// packages/engine/Source/Core/getBaseUri.js
var import_InlineWorkers43 = __toESM(require_InlineWorkers(), 1);
var import_urijs2 = __toESM(require_URI(), 1);
function getBaseUri(uri, includeQuery) {
if (!defined_default(uri)) {
throw new DeveloperError_default("uri is required.");
}
let basePath = "";
const i = uri.lastIndexOf("/");
if (i !== -1) {
basePath = uri.substring(0, i + 1);
}
if (!includeQuery) {
return basePath;
}
uri = new import_urijs2.default(uri);
if (uri.query().length !== 0) {
basePath += `?${uri.query()}`;
}
if (uri.fragment().length !== 0) {
basePath += `#${uri.fragment()}`;
}
return basePath;
}
var getBaseUri_default = getBaseUri;
// packages/engine/Source/Core/getExtensionFromUri.js
var import_InlineWorkers44 = __toESM(require_InlineWorkers(), 1);
var import_urijs3 = __toESM(require_URI(), 1);
function getExtensionFromUri(uri) {
if (!defined_default(uri)) {
throw new DeveloperError_default("uri is required.");
}
const uriObject = new import_urijs3.default(uri);
uriObject.normalize();
let path = uriObject.path();
let index = path.lastIndexOf("/");
if (index !== -1) {
path = path.substr(index + 1);
}
index = path.lastIndexOf(".");
if (index === -1) {
path = "";
} else {
path = path.substr(index + 1);
}
return path;
}
var getExtensionFromUri_default = getExtensionFromUri;
// packages/engine/Source/Core/getImagePixels.js
var import_InlineWorkers45 = __toESM(require_InlineWorkers(), 1);
var context2DsByWidthAndHeight = {};
function getImagePixels(image, width, height) {
if (!defined_default(width)) {
width = image.width;
}
if (!defined_default(height)) {
height = image.height;
}
let context2DsByHeight = context2DsByWidthAndHeight[width];
if (!defined_default(context2DsByHeight)) {
context2DsByHeight = {};
context2DsByWidthAndHeight[width] = context2DsByHeight;
}
let context2d = context2DsByHeight[height];
if (!defined_default(context2d)) {
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
context2d = canvas.getContext("2d", { willReadFrequently: true });
context2d.globalCompositeOperation = "copy";
context2DsByHeight[height] = context2d;
}
context2d.drawImage(image, 0, 0, width, height);
return context2d.getImageData(0, 0, width, height).data;
}
var getImagePixels_default = getImagePixels;
// packages/engine/Source/Core/isBlobUri.js
var import_InlineWorkers46 = __toESM(require_InlineWorkers(), 1);
var blobUriRegex = /^blob:/i;
function isBlobUri(uri) {
Check_default.typeOf.string("uri", uri);
return blobUriRegex.test(uri);
}
var isBlobUri_default = isBlobUri;
// packages/engine/Source/Core/isCrossOriginUrl.js
var import_InlineWorkers47 = __toESM(require_InlineWorkers(), 1);
var a;
function isCrossOriginUrl(url2) {
if (!defined_default(a)) {
a = document.createElement("a");
}
a.href = window.location.href;
const host = a.host;
const protocol = a.protocol;
a.href = url2;
a.href = a.href;
return protocol !== a.protocol || host !== a.host;
}
var isCrossOriginUrl_default = isCrossOriginUrl;
// packages/engine/Source/Core/isDataUri.js
var import_InlineWorkers48 = __toESM(require_InlineWorkers(), 1);
var dataUriRegex = /^data:/i;
function isDataUri(uri) {
Check_default.typeOf.string("uri", uri);
return dataUriRegex.test(uri);
}
var isDataUri_default = isDataUri;
// packages/engine/Source/Core/loadAndExecuteScript.js
var import_InlineWorkers49 = __toESM(require_InlineWorkers(), 1);
function loadAndExecuteScript(url2) {
const script = document.createElement("script");
script.async = true;
script.src = url2;
return new Promise((resolve2, reject) => {
if (window.crossOriginIsolated) {
script.setAttribute("crossorigin", "anonymous");
}
const head = document.getElementsByTagName("head")[0];
script.onload = function() {
script.onload = void 0;
head.removeChild(script);
resolve2();
};
script.onerror = function(e) {
reject(e);
};
head.appendChild(script);
});
}
var loadAndExecuteScript_default = loadAndExecuteScript;
// packages/engine/Source/Core/objectToQuery.js
var import_InlineWorkers50 = __toESM(require_InlineWorkers(), 1);
function objectToQuery(obj) {
if (!defined_default(obj)) {
throw new DeveloperError_default("obj is required.");
}
let result = "";
for (const propName in obj) {
if (obj.hasOwnProperty(propName)) {
const value = obj[propName];
const part = `${encodeURIComponent(propName)}=`;
if (Array.isArray(value)) {
for (let i = 0, len = value.length; i < len; ++i) {
result += `${part + encodeURIComponent(value[i])}&`;
}
} else {
result += `${part + encodeURIComponent(value)}&`;
}
}
}
result = result.slice(0, -1);
return result;
}
var objectToQuery_default = objectToQuery;
// packages/engine/Source/Core/queryToObject.js
var import_InlineWorkers51 = __toESM(require_InlineWorkers(), 1);
function queryToObject(queryString) {
if (!defined_default(queryString)) {
throw new DeveloperError_default("queryString is required.");
}
const result = {};
if (queryString === "") {
return result;
}
const parts = queryString.replace(/\+/g, "%20").split(/[&;]/);
for (let i = 0, len = parts.length; i < len; ++i) {
const subparts = parts[i].split("=");
const name = decodeURIComponent(subparts[0]);
let value = subparts[1];
if (defined_default(value)) {
value = decodeURIComponent(value);
} else {
value = "";
}
const resultValue = result[name];
if (typeof resultValue === "string") {
result[name] = [resultValue, value];
} else if (Array.isArray(resultValue)) {
resultValue.push(value);
} else {
result[name] = value;
}
}
return result;
}
var queryToObject_default = queryToObject;
// packages/engine/Source/Core/Request.js
var import_InlineWorkers54 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/RequestState.js
var import_InlineWorkers52 = __toESM(require_InlineWorkers(), 1);
var RequestState = {
/**
* Initial unissued state.
*
* @type {number}
* @constant
*/
UNISSUED: 0,
/**
* Issued but not yet active. Will become active when open slots are available.
*
* @type {number}
* @constant
*/
ISSUED: 1,
/**
* Actual http request has been sent.
*
* @type {number}
* @constant
*/
ACTIVE: 2,
/**
* Request completed successfully.
*
* @type {number}
* @constant
*/
RECEIVED: 3,
/**
* Request was cancelled, either explicitly or automatically because of low priority.
*
* @type {number}
* @constant
*/
CANCELLED: 4,
/**
* Request failed.
*
* @type {number}
* @constant
*/
FAILED: 5
};
var RequestState_default = Object.freeze(RequestState);
// packages/engine/Source/Core/RequestType.js
var import_InlineWorkers53 = __toESM(require_InlineWorkers(), 1);
var RequestType = {
/**
* Terrain request.
*
* @type {number}
* @constant
*/
TERRAIN: 0,
/**
* Imagery request.
*
* @type {number}
* @constant
*/
IMAGERY: 1,
/**
* 3D Tiles request.
*
* @type {number}
* @constant
*/
TILES3D: 2,
/**
* Other request.
*
* @type {number}
* @constant
*/
OTHER: 3
};
var RequestType_default = Object.freeze(RequestType);
// packages/engine/Source/Core/Request.js
function Request(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const throttleByServer = options.throttleByServer ?? false;
const throttle = options.throttle ?? false;
this.url = options.url;
this.requestFunction = options.requestFunction;
this.cancelFunction = options.cancelFunction;
this.priorityFunction = options.priorityFunction;
this.priority = options.priority ?? 0;
this.throttle = throttle;
this.throttleByServer = throttleByServer;
this.type = options.type ?? RequestType_default.OTHER;
this.serverKey = options.serverKey;
this.state = RequestState_default.UNISSUED;
this.deferred = void 0;
this.cancelled = false;
}
Request.prototype.cancel = function() {
this.cancelled = true;
};
Request.prototype.clone = function(result) {
if (!defined_default(result)) {
return new Request(this);
}
result.url = this.url;
result.requestFunction = this.requestFunction;
result.cancelFunction = this.cancelFunction;
result.priorityFunction = this.priorityFunction;
result.priority = this.priority;
result.throttle = this.throttle;
result.throttleByServer = this.throttleByServer;
result.type = this.type;
result.serverKey = this.serverKey;
result.state = RequestState_default.UNISSUED;
result.deferred = void 0;
result.cancelled = false;
return result;
};
var Request_default = Request;
// packages/engine/Source/Core/RequestErrorEvent.js
var import_InlineWorkers56 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/parseResponseHeaders.js
var import_InlineWorkers55 = __toESM(require_InlineWorkers(), 1);
function parseResponseHeaders(headerString) {
const headers = {};
if (!headerString) {
return headers;
}
const headerPairs = headerString.split("\r\n");
for (let i = 0; i < headerPairs.length; ++i) {
const headerPair = headerPairs[i];
const index = headerPair.indexOf(": ");
if (index > 0) {
const key = headerPair.substring(0, index);
const val = headerPair.substring(index + 2);
headers[key] = val;
}
}
return headers;
}
var parseResponseHeaders_default = parseResponseHeaders;
// packages/engine/Source/Core/RequestErrorEvent.js
function RequestErrorEvent(statusCode, response, responseHeaders) {
this.statusCode = statusCode;
this.response = response;
this.responseHeaders = responseHeaders;
if (typeof this.responseHeaders === "string") {
this.responseHeaders = parseResponseHeaders_default(this.responseHeaders);
}
}
RequestErrorEvent.prototype.toString = function() {
let str = "Request has failed.";
if (defined_default(this.statusCode)) {
str += ` Status Code: ${this.statusCode}`;
}
return str;
};
var RequestErrorEvent_default = RequestErrorEvent;
// packages/engine/Source/Core/RequestScheduler.js
var import_InlineWorkers59 = __toESM(require_InlineWorkers(), 1);
var import_urijs4 = __toESM(require_URI(), 1);
// packages/engine/Source/Core/Event.js
var import_InlineWorkers57 = __toESM(require_InlineWorkers(), 1);
function Event() {
this._listeners = [];
this._scopes = [];
this._toRemove = [];
this._insideRaiseEvent = false;
}
Object.defineProperties(Event.prototype, {
/**
* The number of listeners currently subscribed to the event.
* @memberof Event.prototype
* @type {number}
* @readonly
*/
numberOfListeners: {
get: function() {
return this._listeners.length - this._toRemove.length;
}
}
});
Event.prototype.addEventListener = function(listener, scope) {
Check_default.typeOf.func("listener", listener);
this._listeners.push(listener);
this._scopes.push(scope);
const event = this;
return function() {
event.removeEventListener(listener, scope);
};
};
Event.prototype.removeEventListener = function(listener, scope) {
Check_default.typeOf.func("listener", listener);
const listeners = this._listeners;
const scopes = this._scopes;
let index = -1;
for (let i = 0; i < listeners.length; i++) {
if (listeners[i] === listener && scopes[i] === scope) {
index = i;
break;
}
}
if (index !== -1) {
if (this._insideRaiseEvent) {
this._toRemove.push(index);
listeners[index] = void 0;
scopes[index] = void 0;
} else {
listeners.splice(index, 1);
scopes.splice(index, 1);
}
return true;
}
return false;
};
function compareNumber(a3, b) {
return b - a3;
}
Event.prototype.raiseEvent = function() {
this._insideRaiseEvent = true;
let i;
const listeners = this._listeners;
const scopes = this._scopes;
let length2 = listeners.length;
for (i = 0; i < length2; i++) {
const listener = listeners[i];
if (defined_default(listener)) {
listeners[i].apply(scopes[i], arguments);
}
}
const toRemove = this._toRemove;
length2 = toRemove.length;
if (length2 > 0) {
toRemove.sort(compareNumber);
for (i = 0; i < length2; i++) {
const index = toRemove[i];
listeners.splice(index, 1);
scopes.splice(index, 1);
}
toRemove.length = 0;
}
this._insideRaiseEvent = false;
};
var Event_default = Event;
// packages/engine/Source/Core/Heap.js
var import_InlineWorkers58 = __toESM(require_InlineWorkers(), 1);
function Heap(options) {
Check_default.typeOf.object("options", options);
Check_default.defined("options.comparator", options.comparator);
this._comparator = options.comparator;
this._array = [];
this._length = 0;
this._maximumLength = void 0;
}
Object.defineProperties(Heap.prototype, {
/**
* Gets the length of the heap.
*
* @memberof Heap.prototype
*
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._length;
}
},
/**
* Gets the internal array.
*
* @memberof Heap.prototype
*
* @type {Array}
* @readonly
*/
internalArray: {
get: function() {
return this._array;
}
},
/**
* Gets and sets the maximum length of the heap.
*
* @memberof Heap.prototype
*
* @type {number}
*/
maximumLength: {
get: function() {
return this._maximumLength;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("maximumLength", value, 0);
const originalLength = this._length;
if (value < originalLength) {
const array = this._array;
for (let i = value; i < originalLength; ++i) {
array[i] = void 0;
}
this._length = value;
array.length = value;
}
this._maximumLength = value;
}
},
/**
* The comparator to use for the heap. If comparator(a, b) is less than 0, sort a to a lower index than b, otherwise sort to a higher index.
*
* @memberof Heap.prototype
*
* @type {Heap.ComparatorCallback}
*/
comparator: {
get: function() {
return this._comparator;
}
}
});
function swap(array, a3, b) {
const temp = array[a3];
array[a3] = array[b];
array[b] = temp;
}
Heap.prototype.reserve = function(length2) {
length2 = length2 ?? this._length;
this._array.length = length2;
};
Heap.prototype.heapify = function(index) {
index = index ?? 0;
const length2 = this._length;
const comparator = this._comparator;
const array = this._array;
let candidate = -1;
let inserting = true;
while (inserting) {
const right = 2 * (index + 1);
const left = right - 1;
if (left < length2 && comparator(array[left], array[index]) < 0) {
candidate = left;
} else {
candidate = index;
}
if (right < length2 && comparator(array[right], array[candidate]) < 0) {
candidate = right;
}
if (candidate !== index) {
swap(array, candidate, index);
index = candidate;
} else {
inserting = false;
}
}
};
Heap.prototype.resort = function() {
const length2 = this._length;
for (let i = Math.ceil(length2 / 2); i >= 0; --i) {
this.heapify(i);
}
};
Heap.prototype.insert = function(element) {
Check_default.defined("element", element);
const array = this._array;
const comparator = this._comparator;
const maximumLength = this._maximumLength;
let index = this._length++;
if (index < array.length) {
array[index] = element;
} else {
array.push(element);
}
while (index !== 0) {
const parent = Math.floor((index - 1) / 2);
if (comparator(array[index], array[parent]) < 0) {
swap(array, index, parent);
index = parent;
} else {
break;
}
}
let removedElement;
if (defined_default(maximumLength) && this._length > maximumLength) {
removedElement = array[maximumLength];
this._length = maximumLength;
}
return removedElement;
};
Heap.prototype.pop = function(index) {
index = index ?? 0;
if (this._length === 0) {
return void 0;
}
Check_default.typeOf.number.lessThan("index", index, this._length);
const array = this._array;
const root = array[index];
swap(array, index, --this._length);
this.heapify(index);
array[this._length] = void 0;
return root;
};
var Heap_default = Heap;
// packages/engine/Source/Core/RequestScheduler.js
function sortRequests(a3, b) {
return a3.priority - b.priority;
}
var statistics = {
numberOfAttemptedRequests: 0,
numberOfActiveRequests: 0,
numberOfCancelledRequests: 0,
numberOfCancelledActiveRequests: 0,
numberOfFailedRequests: 0,
numberOfActiveRequestsEver: 0,
lastNumberOfActiveRequests: 0
};
var priorityHeapLength = 20;
var requestHeap = new Heap_default({
comparator: sortRequests
});
requestHeap.maximumLength = priorityHeapLength;
requestHeap.reserve(priorityHeapLength);
var activeRequests = [];
var numberOfActiveRequestsByServer = {};
var pageUri = typeof document !== "undefined" ? new import_urijs4.default(document.location.href) : new import_urijs4.default();
var requestCompletedEvent = new Event_default();
function RequestScheduler() {
}
RequestScheduler.maximumRequests = 50;
RequestScheduler.maximumRequestsPerServer = 18;
RequestScheduler.requestsByServer = {};
RequestScheduler.throttleRequests = true;
RequestScheduler.debugShowStatistics = false;
RequestScheduler.requestCompletedEvent = requestCompletedEvent;
Object.defineProperties(RequestScheduler, {
/**
* Returns the statistics used by the request scheduler.
*
* @memberof RequestScheduler
*
* @type {object}
* @readonly
* @private
*/
statistics: {
get: function() {
return statistics;
}
},
/**
* The maximum size of the priority heap. This limits the number of requests that are sorted by priority. Only applies to requests that are not yet active.
*
* @memberof RequestScheduler
*
* @type {number}
* @default 20
* @private
*/
priorityHeapLength: {
get: function() {
return priorityHeapLength;
},
set: function(value) {
if (value < priorityHeapLength) {
while (requestHeap.length > value) {
const request = requestHeap.pop();
cancelRequest(request);
}
}
priorityHeapLength = value;
requestHeap.maximumLength = value;
requestHeap.reserve(value);
}
}
});
function updatePriority(request) {
if (defined_default(request.priorityFunction)) {
request.priority = request.priorityFunction();
}
}
RequestScheduler.serverHasOpenSlots = function(serverKey, desiredRequests) {
desiredRequests = desiredRequests ?? 1;
const maxRequests = RequestScheduler.requestsByServer[serverKey] ?? RequestScheduler.maximumRequestsPerServer;
const hasOpenSlotsServer = numberOfActiveRequestsByServer[serverKey] + desiredRequests <= maxRequests;
return hasOpenSlotsServer;
};
RequestScheduler.heapHasOpenSlots = function(desiredRequests) {
const hasOpenSlotsHeap = requestHeap.length + desiredRequests <= priorityHeapLength;
return hasOpenSlotsHeap;
};
function issueRequest(request) {
if (request.state === RequestState_default.UNISSUED) {
request.state = RequestState_default.ISSUED;
request.deferred = defer_default();
}
return request.deferred.promise;
}
function getRequestReceivedFunction(request) {
return function(results) {
if (request.state === RequestState_default.CANCELLED) {
return;
}
const deferred = request.deferred;
--statistics.numberOfActiveRequests;
--numberOfActiveRequestsByServer[request.serverKey];
requestCompletedEvent.raiseEvent();
request.state = RequestState_default.RECEIVED;
request.deferred = void 0;
deferred.resolve(results);
};
}
function getRequestFailedFunction(request) {
return function(error) {
if (request.state === RequestState_default.CANCELLED) {
return;
}
++statistics.numberOfFailedRequests;
--statistics.numberOfActiveRequests;
--numberOfActiveRequestsByServer[request.serverKey];
requestCompletedEvent.raiseEvent(error);
request.state = RequestState_default.FAILED;
request.deferred.reject(error);
};
}
function startRequest(request) {
const promise = issueRequest(request);
request.state = RequestState_default.ACTIVE;
activeRequests.push(request);
++statistics.numberOfActiveRequests;
++statistics.numberOfActiveRequestsEver;
++numberOfActiveRequestsByServer[request.serverKey];
request.requestFunction().then(getRequestReceivedFunction(request)).catch(getRequestFailedFunction(request));
return promise;
}
function cancelRequest(request) {
const active = request.state === RequestState_default.ACTIVE;
request.state = RequestState_default.CANCELLED;
++statistics.numberOfCancelledRequests;
if (defined_default(request.deferred)) {
const deferred = request.deferred;
request.deferred = void 0;
deferred.reject();
}
if (active) {
--statistics.numberOfActiveRequests;
--numberOfActiveRequestsByServer[request.serverKey];
++statistics.numberOfCancelledActiveRequests;
}
if (defined_default(request.cancelFunction)) {
request.cancelFunction();
}
}
RequestScheduler.update = function() {
let i;
let request;
let removeCount = 0;
const activeLength = activeRequests.length;
for (i = 0; i < activeLength; ++i) {
request = activeRequests[i];
if (request.cancelled) {
cancelRequest(request);
}
if (request.state !== RequestState_default.ACTIVE) {
++removeCount;
continue;
}
if (removeCount > 0) {
activeRequests[i - removeCount] = request;
}
}
activeRequests.length -= removeCount;
const issuedRequests = requestHeap.internalArray;
const issuedLength = requestHeap.length;
for (i = 0; i < issuedLength; ++i) {
updatePriority(issuedRequests[i]);
}
requestHeap.resort();
const openSlots = Math.max(
RequestScheduler.maximumRequests - activeRequests.length,
0
);
let filledSlots = 0;
while (filledSlots < openSlots && requestHeap.length > 0) {
request = requestHeap.pop();
if (request.cancelled) {
cancelRequest(request);
continue;
}
if (request.throttleByServer && !RequestScheduler.serverHasOpenSlots(request.serverKey)) {
cancelRequest(request);
continue;
}
startRequest(request);
++filledSlots;
}
updateStatistics();
};
RequestScheduler.getServerKey = function(url2) {
Check_default.typeOf.string("url", url2);
let uri = new import_urijs4.default(url2);
if (uri.scheme() === "") {
uri = uri.absoluteTo(pageUri);
uri.normalize();
}
let serverKey = uri.authority();
if (!/:/.test(serverKey)) {
serverKey = `${serverKey}:${uri.scheme() === "https" ? "443" : "80"}`;
}
const length2 = numberOfActiveRequestsByServer[serverKey];
if (!defined_default(length2)) {
numberOfActiveRequestsByServer[serverKey] = 0;
}
return serverKey;
};
RequestScheduler.request = function(request) {
Check_default.typeOf.object("request", request);
Check_default.typeOf.string("request.url", request.url);
Check_default.typeOf.func("request.requestFunction", request.requestFunction);
if (isDataUri_default(request.url) || isBlobUri_default(request.url)) {
requestCompletedEvent.raiseEvent();
request.state = RequestState_default.RECEIVED;
return request.requestFunction();
}
++statistics.numberOfAttemptedRequests;
if (!defined_default(request.serverKey)) {
request.serverKey = RequestScheduler.getServerKey(request.url);
}
if (RequestScheduler.throttleRequests && request.throttleByServer && !RequestScheduler.serverHasOpenSlots(request.serverKey)) {
return void 0;
}
if (!RequestScheduler.throttleRequests || !request.throttle) {
return startRequest(request);
}
if (activeRequests.length >= RequestScheduler.maximumRequests) {
return void 0;
}
updatePriority(request);
const removedRequest = requestHeap.insert(request);
if (defined_default(removedRequest)) {
if (removedRequest === request) {
return void 0;
}
cancelRequest(removedRequest);
}
return issueRequest(request);
};
function updateStatistics() {
if (!RequestScheduler.debugShowStatistics) {
return;
}
if (statistics.numberOfActiveRequests === 0 && statistics.lastNumberOfActiveRequests > 0) {
if (statistics.numberOfAttemptedRequests > 0) {
console.log(
`Number of attempted requests: ${statistics.numberOfAttemptedRequests}`
);
statistics.numberOfAttemptedRequests = 0;
}
if (statistics.numberOfCancelledRequests > 0) {
console.log(
`Number of cancelled requests: ${statistics.numberOfCancelledRequests}`
);
statistics.numberOfCancelledRequests = 0;
}
if (statistics.numberOfCancelledActiveRequests > 0) {
console.log(
`Number of cancelled active requests: ${statistics.numberOfCancelledActiveRequests}`
);
statistics.numberOfCancelledActiveRequests = 0;
}
if (statistics.numberOfFailedRequests > 0) {
console.log(
`Number of failed requests: ${statistics.numberOfFailedRequests}`
);
statistics.numberOfFailedRequests = 0;
}
}
statistics.lastNumberOfActiveRequests = statistics.numberOfActiveRequests;
}
RequestScheduler.clearForSpecs = function() {
while (requestHeap.length > 0) {
const request = requestHeap.pop();
cancelRequest(request);
}
const length2 = activeRequests.length;
for (let i = 0; i < length2; ++i) {
cancelRequest(activeRequests[i]);
}
activeRequests.length = 0;
numberOfActiveRequestsByServer = {};
statistics.numberOfAttemptedRequests = 0;
statistics.numberOfActiveRequests = 0;
statistics.numberOfCancelledRequests = 0;
statistics.numberOfCancelledActiveRequests = 0;
statistics.numberOfFailedRequests = 0;
statistics.numberOfActiveRequestsEver = 0;
statistics.lastNumberOfActiveRequests = 0;
};
RequestScheduler.numberOfActiveRequestsByServer = function(serverKey) {
return numberOfActiveRequestsByServer[serverKey];
};
RequestScheduler.requestHeap = requestHeap;
var RequestScheduler_default = RequestScheduler;
// packages/engine/Source/Core/TrustedServers.js
var import_InlineWorkers60 = __toESM(require_InlineWorkers(), 1);
var import_urijs5 = __toESM(require_URI(), 1);
var TrustedServers = {};
var _servers = {};
TrustedServers.add = function(host, port) {
if (!defined_default(host)) {
throw new DeveloperError_default("host is required.");
}
if (!defined_default(port) || port <= 0) {
throw new DeveloperError_default("port is required to be greater than 0.");
}
const authority = `${host.toLowerCase()}:${port}`;
if (!defined_default(_servers[authority])) {
_servers[authority] = true;
}
};
TrustedServers.remove = function(host, port) {
if (!defined_default(host)) {
throw new DeveloperError_default("host is required.");
}
if (!defined_default(port) || port <= 0) {
throw new DeveloperError_default("port is required to be greater than 0.");
}
const authority = `${host.toLowerCase()}:${port}`;
if (defined_default(_servers[authority])) {
delete _servers[authority];
}
};
function getAuthority(url2) {
const uri = new import_urijs5.default(url2);
uri.normalize();
let authority = uri.authority();
if (authority.length === 0) {
return void 0;
}
uri.authority(authority);
if (authority.indexOf("@") !== -1) {
const parts = authority.split("@");
authority = parts[1];
}
if (authority.indexOf(":") === -1) {
let scheme = uri.scheme();
if (scheme.length === 0) {
scheme = window.location.protocol;
scheme = scheme.substring(0, scheme.length - 1);
}
if (scheme === "http") {
authority += ":80";
} else if (scheme === "https") {
authority += ":443";
} else {
return void 0;
}
}
return authority;
}
TrustedServers.contains = function(url2) {
if (!defined_default(url2)) {
throw new DeveloperError_default("url is required.");
}
const authority = getAuthority(url2);
if (defined_default(authority) && defined_default(_servers[authority])) {
return true;
}
return false;
};
TrustedServers.clear = function() {
_servers = {};
};
var TrustedServers_default = TrustedServers;
// packages/engine/Source/Core/Resource.js
var xhrBlobSupported = (function() {
try {
const xhr = new XMLHttpRequest();
xhr.open("GET", "#", true);
xhr.responseType = "blob";
return xhr.responseType === "blob";
} catch (e) {
return false;
}
})();
function Resource(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
if (typeof options === "string") {
options = {
url: options
};
}
Check_default.typeOf.string("options.url", options.url);
this._url = void 0;
this._templateValues = defaultClone(options.templateValues, {});
this._queryParameters = defaultClone(options.queryParameters, {});
this.headers = defaultClone(options.headers, {});
this.request = options.request ?? new Request_default();
this.proxy = options.proxy;
this.retryCallback = options.retryCallback;
this.retryAttempts = options.retryAttempts ?? 0;
this._retryCount = 0;
const parseUrl2 = options.parseUrl ?? true;
if (parseUrl2) {
this.parseUrl(options.url, true, true);
} else {
this._url = options.url;
}
this._credits = options.credits;
}
function defaultClone(value, defaultValue2) {
return defined_default(value) ? clone_default(value) : defaultValue2;
}
Resource.createIfNeeded = function(resource) {
if (resource instanceof Resource) {
return resource.getDerivedResource({
request: resource.request
});
}
if (typeof resource !== "string") {
return resource;
}
return new Resource({
url: resource
});
};
var supportsImageBitmapOptionsPromise;
Resource.supportsImageBitmapOptions = function() {
if (defined_default(supportsImageBitmapOptionsPromise)) {
return supportsImageBitmapOptionsPromise;
}
if (typeof createImageBitmap !== "function") {
supportsImageBitmapOptionsPromise = Promise.resolve(false);
return supportsImageBitmapOptionsPromise;
}
const imageDataUri = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAABGdBTUEAAE4g3rEiDgAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADElEQVQI12Ng6GAAAAEUAIngE3ZiAAAAAElFTkSuQmCC";
supportsImageBitmapOptionsPromise = Resource.fetchBlob({
url: imageDataUri
}).then(function(blob) {
const imageBitmapOptions = {
imageOrientation: "flipY",
// default is "from-image"
premultiplyAlpha: "none",
// default is "default"
colorSpaceConversion: "none"
// default is "default"
};
return Promise.all([
createImageBitmap(blob, imageBitmapOptions),
createImageBitmap(blob)
]);
}).then(function(imageBitmaps) {
const colorWithOptions = getImagePixels_default(imageBitmaps[0]);
const colorWithDefaults = getImagePixels_default(imageBitmaps[1]);
return colorWithOptions[1] !== colorWithDefaults[1];
}).catch(function() {
return false;
});
return supportsImageBitmapOptionsPromise;
};
Object.defineProperties(Resource, {
/**
* Returns true if blobs are supported.
*
* @memberof Resource
* @type {boolean}
*
* @readonly
*/
isBlobSupported: {
get: function() {
return xhrBlobSupported;
}
}
});
Object.defineProperties(Resource.prototype, {
/**
* Query parameters appended to the url.
*
* @memberof Resource.prototype
* @type {object}
*
* @readonly
*/
queryParameters: {
get: function() {
return this._queryParameters;
}
},
/**
* The key/value pairs used to replace template parameters in the url.
*
* @memberof Resource.prototype
* @type {object}
*
* @readonly
*/
templateValues: {
get: function() {
return this._templateValues;
}
},
/**
* The url to the resource with template values replaced, query string appended and encoded by proxy if one was set.
*
* @memberof Resource.prototype
* @type {string}
*/
url: {
get: function() {
return this.getUrlComponent(true, true);
},
set: function(value) {
this.parseUrl(value, false, false);
}
},
/**
* The file extension of the resource.
*
* @memberof Resource.prototype
* @type {string}
*
* @readonly
*/
extension: {
get: function() {
return getExtensionFromUri_default(this._url);
}
},
/**
* True if the Resource refers to a data URI.
*
* @memberof Resource.prototype
* @type {boolean}
*/
isDataUri: {
get: function() {
return isDataUri_default(this._url);
}
},
/**
* True if the Resource refers to a blob URI.
*
* @memberof Resource.prototype
* @type {boolean}
*/
isBlobUri: {
get: function() {
return isBlobUri_default(this._url);
}
},
/**
* True if the Resource refers to a cross origin URL.
*
* @memberof Resource.prototype
* @type {boolean}
*/
isCrossOriginUrl: {
get: function() {
return isCrossOriginUrl_default(this._url);
}
},
/**
* True if the Resource has request headers. This is equivalent to checking if the headers property has any keys.
*
* @memberof Resource.prototype
* @type {boolean}
*/
hasHeaders: {
get: function() {
return Object.keys(this.headers).length > 0;
}
},
/**
* Gets the credits required for attribution of an asset.
* @private
*/
credits: {
get: function() {
return this._credits;
}
}
});
Resource.prototype.toString = function() {
return this.getUrlComponent(true, true);
};
Resource.prototype.parseUrl = function(url2, merge2, preserveQuery, baseUrl) {
let uri = new import_urijs6.default(url2);
const query = parseQueryString(uri.query());
this._queryParameters = merge2 ? combineQueryParameters(query, this.queryParameters, preserveQuery) : query;
uri.search("");
uri.fragment("");
if (defined_default(baseUrl) && uri.scheme() === "") {
uri = uri.absoluteTo(getAbsoluteUri_default(baseUrl));
}
this._url = uri.toString();
};
function parseQueryString(queryString) {
if (queryString.length === 0) {
return {};
}
if (queryString.indexOf("=") === -1) {
return { [queryString]: void 0 };
}
return queryToObject_default(queryString);
}
function combineQueryParameters(q12, q22, preserveQueryParameters) {
if (!preserveQueryParameters) {
return combine_default(q12, q22);
}
const result = clone_default(q12, true);
for (const param in q22) {
if (q22.hasOwnProperty(param)) {
let value = result[param];
const q2Value = q22[param];
if (defined_default(value)) {
if (!Array.isArray(value)) {
value = result[param] = [value];
}
result[param] = value.concat(q2Value);
} else {
result[param] = Array.isArray(q2Value) ? q2Value.slice() : q2Value;
}
}
}
return result;
}
Resource.prototype.getUrlComponent = function(query, proxy) {
if (this.isDataUri) {
return this._url;
}
let url2 = this._url;
if (query) {
url2 = `${url2}${stringifyQuery(this.queryParameters)}`;
}
url2 = url2.replace(/%7B/g, "{").replace(/%7D/g, "}");
const templateValues = this._templateValues;
if (Object.keys(templateValues).length > 0) {
url2 = url2.replace(/{(.*?)}/g, function(match, key) {
const replacement = templateValues[key];
if (defined_default(replacement)) {
return encodeURIComponent(replacement);
}
return match;
});
}
if (proxy && defined_default(this.proxy)) {
url2 = this.proxy.getURL(url2);
}
return url2;
};
function stringifyQuery(queryObject) {
const keys = Object.keys(queryObject);
if (keys.length === 0) {
return "";
}
if (keys.length === 1 && !defined_default(queryObject[keys[0]])) {
return `?${keys[0]}`;
}
return `?${objectToQuery_default(queryObject)}`;
}
Resource.prototype.setQueryParameters = function(params, useAsDefault) {
if (useAsDefault) {
this._queryParameters = combineQueryParameters(
this._queryParameters,
params,
false
);
} else {
this._queryParameters = combineQueryParameters(
params,
this._queryParameters,
false
);
}
};
Resource.prototype.appendQueryParameters = function(params) {
this._queryParameters = combineQueryParameters(
params,
this._queryParameters,
true
);
};
Resource.prototype.setTemplateValues = function(template, useAsDefault) {
if (useAsDefault) {
this._templateValues = combine_default(this._templateValues, template);
} else {
this._templateValues = combine_default(template, this._templateValues);
}
};
Resource.prototype.getDerivedResource = function(options) {
const resource = this.clone();
resource._retryCount = 0;
if (defined_default(options.url)) {
const preserveQuery = options.preserveQueryParameters ?? false;
resource.parseUrl(options.url, true, preserveQuery, this._url);
}
if (defined_default(options.queryParameters)) {
resource._queryParameters = combine_default(
options.queryParameters,
resource.queryParameters
);
}
if (defined_default(options.templateValues)) {
resource._templateValues = combine_default(
options.templateValues,
resource.templateValues
);
}
if (defined_default(options.headers)) {
resource.headers = combine_default(options.headers, resource.headers);
}
if (defined_default(options.proxy)) {
resource.proxy = options.proxy;
}
if (defined_default(options.request)) {
resource.request = options.request;
}
if (defined_default(options.retryCallback)) {
resource.retryCallback = options.retryCallback;
}
if (defined_default(options.retryAttempts)) {
resource.retryAttempts = options.retryAttempts;
}
return resource;
};
Resource.prototype.retryOnError = function(error) {
const retryCallback2 = this.retryCallback;
if (typeof retryCallback2 !== "function" || this._retryCount >= this.retryAttempts) {
return Promise.resolve(false);
}
const that = this;
return Promise.resolve(retryCallback2(this, error)).then(function(result) {
++that._retryCount;
return result;
});
};
Resource.prototype.clone = function(result) {
if (!defined_default(result)) {
return new Resource({
url: this._url,
queryParameters: this.queryParameters,
templateValues: this.templateValues,
headers: this.headers,
proxy: this.proxy,
retryCallback: this.retryCallback,
retryAttempts: this.retryAttempts,
request: this.request.clone(),
parseUrl: false,
credits: defined_default(this.credits) ? this.credits.slice() : void 0
});
}
result._url = this._url;
result._queryParameters = clone_default(this._queryParameters);
result._templateValues = clone_default(this._templateValues);
result.headers = clone_default(this.headers);
result.proxy = this.proxy;
result.retryCallback = this.retryCallback;
result.retryAttempts = this.retryAttempts;
result._retryCount = 0;
result.request = this.request.clone();
return result;
};
Resource.prototype.getBaseUri = function(includeQuery) {
return getBaseUri_default(this.getUrlComponent(includeQuery), includeQuery);
};
Resource.prototype.appendForwardSlash = function() {
this._url = appendForwardSlash_default(this._url);
};
Resource.prototype.fetchArrayBuffer = function() {
return this.fetch({
responseType: "arraybuffer"
});
};
Resource.fetchArrayBuffer = function(options) {
const resource = new Resource(options);
return resource.fetchArrayBuffer();
};
Resource.prototype.fetchBlob = function() {
return this.fetch({
responseType: "blob"
});
};
Resource.fetchBlob = function(options) {
const resource = new Resource(options);
return resource.fetchBlob();
};
Resource.prototype.fetchImage = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const preferImageBitmap = options.preferImageBitmap ?? false;
const preferBlob = options.preferBlob ?? false;
const flipY = options.flipY ?? false;
const skipColorSpaceConversion = options.skipColorSpaceConversion ?? false;
checkAndResetRequest(this.request);
if (!xhrBlobSupported || this.isDataUri || this.isBlobUri || !this.hasHeaders && !preferBlob) {
return fetchImage({
resource: this,
flipY,
skipColorSpaceConversion,
preferImageBitmap
});
}
const blobPromise = this.fetchBlob();
if (!defined_default(blobPromise)) {
return;
}
let supportsImageBitmap;
let useImageBitmap;
let generatedBlobResource;
let generatedBlob;
return Resource.supportsImageBitmapOptions().then(function(result) {
supportsImageBitmap = result;
useImageBitmap = supportsImageBitmap && preferImageBitmap;
return blobPromise;
}).then(function(blob) {
if (!defined_default(blob)) {
return;
}
generatedBlob = blob;
if (useImageBitmap) {
return Resource.createImageBitmapFromBlob(blob, {
flipY,
premultiplyAlpha: false,
skipColorSpaceConversion
});
}
const blobUrl = window.URL.createObjectURL(blob);
generatedBlobResource = new Resource({
url: blobUrl
});
return fetchImage({
resource: generatedBlobResource,
flipY,
skipColorSpaceConversion,
preferImageBitmap: false
});
}).then(function(image) {
if (!defined_default(image)) {
return;
}
image.blob = generatedBlob;
if (useImageBitmap) {
return image;
}
window.URL.revokeObjectURL(generatedBlobResource.url);
return image;
}).catch(function(error) {
if (defined_default(generatedBlobResource)) {
window.URL.revokeObjectURL(generatedBlobResource.url);
}
error.blob = generatedBlob;
return Promise.reject(error);
});
};
function fetchImage(options) {
const resource = options.resource;
const flipY = options.flipY;
const skipColorSpaceConversion = options.skipColorSpaceConversion;
const preferImageBitmap = options.preferImageBitmap;
const request = resource.request;
request.url = resource.url;
request.requestFunction = function() {
let crossOrigin = false;
if (!resource.isDataUri && !resource.isBlobUri) {
crossOrigin = resource.isCrossOriginUrl;
}
const deferred = defer_default();
Resource._Implementations.createImage(
request,
crossOrigin,
deferred,
flipY,
skipColorSpaceConversion,
preferImageBitmap
);
return deferred.promise;
};
const promise = RequestScheduler_default.request(request);
if (!defined_default(promise)) {
return;
}
return promise.catch(function(e) {
if (request.state !== RequestState_default.FAILED) {
return Promise.reject(e);
}
return resource.retryOnError(e).then(function(retry) {
if (retry) {
request.state = RequestState_default.UNISSUED;
request.deferred = void 0;
return fetchImage({
resource,
flipY,
skipColorSpaceConversion,
preferImageBitmap
});
}
return Promise.reject(e);
});
});
}
Resource.fetchImage = function(options) {
const resource = new Resource(options);
return resource.fetchImage({
flipY: options.flipY,
skipColorSpaceConversion: options.skipColorSpaceConversion,
preferBlob: options.preferBlob,
preferImageBitmap: options.preferImageBitmap
});
};
Resource.prototype.fetchText = function() {
return this.fetch({
responseType: "text"
});
};
Resource.fetchText = function(options) {
const resource = new Resource(options);
return resource.fetchText();
};
Resource.prototype.fetchJson = function() {
const promise = this.fetch({
responseType: "text",
headers: {
Accept: "application/json,*/*;q=0.01"
}
});
if (!defined_default(promise)) {
return void 0;
}
return promise.then(function(value) {
if (!defined_default(value)) {
return;
}
return JSON.parse(value);
});
};
Resource.fetchJson = function(options) {
const resource = new Resource(options);
return resource.fetchJson();
};
Resource.prototype.fetchXML = function() {
return this.fetch({
responseType: "document",
overrideMimeType: "text/xml"
});
};
Resource.fetchXML = function(options) {
const resource = new Resource(options);
return resource.fetchXML();
};
Resource.prototype.fetchJsonp = function(callbackParameterName) {
callbackParameterName = callbackParameterName ?? "callback";
checkAndResetRequest(this.request);
let functionName;
do {
functionName = `loadJsonp${Math_default.nextRandomNumber().toString().substring(2, 8)}`;
} while (defined_default(window[functionName]));
return fetchJsonp(this, callbackParameterName, functionName);
};
function fetchJsonp(resource, callbackParameterName, functionName) {
const callbackQuery = {};
callbackQuery[callbackParameterName] = functionName;
resource.setQueryParameters(callbackQuery);
const request = resource.request;
const url2 = resource.url;
request.url = url2;
request.requestFunction = function() {
const deferred = defer_default();
window[functionName] = function(data) {
deferred.resolve(data);
try {
delete window[functionName];
} catch (e) {
window[functionName] = void 0;
}
};
Resource._Implementations.loadAndExecuteScript(url2, functionName, deferred);
return deferred.promise;
};
const promise = RequestScheduler_default.request(request);
if (!defined_default(promise)) {
return;
}
return promise.catch(function(e) {
if (request.state !== RequestState_default.FAILED) {
return Promise.reject(e);
}
return resource.retryOnError(e).then(function(retry) {
if (retry) {
request.state = RequestState_default.UNISSUED;
request.deferred = void 0;
return fetchJsonp(resource, callbackParameterName, functionName);
}
return Promise.reject(e);
});
});
}
Resource.fetchJsonp = function(options) {
const resource = new Resource(options);
return resource.fetchJsonp(options.callbackParameterName);
};
Resource.prototype._makeRequest = function(options) {
const resource = this;
checkAndResetRequest(resource.request);
const request = resource.request;
const url2 = resource.url;
request.url = url2;
request.requestFunction = function() {
const responseType = options.responseType;
const headers = combine_default(options.headers, resource.headers);
const overrideMimeType = options.overrideMimeType;
const method = options.method;
const data = options.data;
const deferred = defer_default();
const xhr = Resource._Implementations.loadWithXhr(
url2,
responseType,
method,
data,
headers,
deferred,
overrideMimeType
);
if (defined_default(xhr) && defined_default(xhr.abort)) {
request.cancelFunction = function() {
xhr.abort();
};
}
return deferred.promise;
};
const promise = RequestScheduler_default.request(request);
if (!defined_default(promise)) {
return;
}
return promise.then(function(data) {
request.cancelFunction = void 0;
return data;
}).catch(function(e) {
request.cancelFunction = void 0;
if (request.state !== RequestState_default.FAILED) {
return Promise.reject(e);
}
return resource.retryOnError(e).then(function(retry) {
if (retry) {
request.state = RequestState_default.UNISSUED;
request.deferred = void 0;
return resource.fetch(options);
}
return Promise.reject(e);
});
});
};
function checkAndResetRequest(request) {
if (request.state === RequestState_default.ISSUED || request.state === RequestState_default.ACTIVE) {
throw new RuntimeError_default("The Resource is already being fetched.");
}
request.state = RequestState_default.UNISSUED;
request.deferred = void 0;
}
var dataUriRegex2 = /^data:(.*?)(;base64)?,(.*)$/;
function decodeDataUriText(isBase64, data) {
const result = decodeURIComponent(data);
if (isBase64) {
return atob(result);
}
return result;
}
function decodeDataUriArrayBuffer(isBase64, data) {
const byteString = decodeDataUriText(isBase64, data);
const buffer2 = new ArrayBuffer(byteString.length);
const view = new Uint8Array(buffer2);
for (let i = 0; i < byteString.length; i++) {
view[i] = byteString.charCodeAt(i);
}
return buffer2;
}
function decodeDataUri(dataUriRegexResult, responseType) {
responseType = responseType ?? "";
const mimeType = dataUriRegexResult[1];
const isBase64 = !!dataUriRegexResult[2];
const data = dataUriRegexResult[3];
let buffer2;
let parser3;
switch (responseType) {
case "":
case "text":
return decodeDataUriText(isBase64, data);
case "arraybuffer":
return decodeDataUriArrayBuffer(isBase64, data);
case "blob":
buffer2 = decodeDataUriArrayBuffer(isBase64, data);
return new Blob([buffer2], {
type: mimeType
});
case "document":
parser3 = new DOMParser();
return parser3.parseFromString(
decodeDataUriText(isBase64, data),
mimeType
);
case "json":
return JSON.parse(decodeDataUriText(isBase64, data));
default:
throw new DeveloperError_default(`Unhandled responseType: ${responseType}`);
}
}
Resource.prototype.fetch = function(options) {
options = defaultClone(options, {});
options.method = "GET";
return this._makeRequest(options);
};
Resource.fetch = function(options) {
const resource = new Resource(options);
return resource.fetch({
// Make copy of just the needed fields because headers can be passed to both the constructor and to fetch
responseType: options.responseType,
overrideMimeType: options.overrideMimeType
});
};
Resource.prototype.delete = function(options) {
options = defaultClone(options, {});
options.method = "DELETE";
return this._makeRequest(options);
};
Resource.delete = function(options) {
const resource = new Resource(options);
return resource.delete({
// Make copy of just the needed fields because headers can be passed to both the constructor and to fetch
responseType: options.responseType,
overrideMimeType: options.overrideMimeType,
data: options.data
});
};
Resource.prototype.head = function(options) {
options = defaultClone(options, {});
options.method = "HEAD";
return this._makeRequest(options);
};
Resource.head = function(options) {
const resource = new Resource(options);
return resource.head({
// Make copy of just the needed fields because headers can be passed to both the constructor and to fetch
responseType: options.responseType,
overrideMimeType: options.overrideMimeType
});
};
Resource.prototype.options = function(options) {
options = defaultClone(options, {});
options.method = "OPTIONS";
return this._makeRequest(options);
};
Resource.options = function(options) {
const resource = new Resource(options);
return resource.options({
// Make copy of just the needed fields because headers can be passed to both the constructor and to fetch
responseType: options.responseType,
overrideMimeType: options.overrideMimeType
});
};
Resource.prototype.post = function(data, options) {
Check_default.defined("data", data);
options = defaultClone(options, {});
options.method = "POST";
options.data = data;
return this._makeRequest(options);
};
Resource.post = function(options) {
const resource = new Resource(options);
return resource.post(options.data, {
// Make copy of just the needed fields because headers can be passed to both the constructor and to post
responseType: options.responseType,
overrideMimeType: options.overrideMimeType
});
};
Resource.prototype.put = function(data, options) {
Check_default.defined("data", data);
options = defaultClone(options, {});
options.method = "PUT";
options.data = data;
return this._makeRequest(options);
};
Resource.put = function(options) {
const resource = new Resource(options);
return resource.put(options.data, {
// Make copy of just the needed fields because headers can be passed to both the constructor and to post
responseType: options.responseType,
overrideMimeType: options.overrideMimeType
});
};
Resource.prototype.patch = function(data, options) {
Check_default.defined("data", data);
options = defaultClone(options, {});
options.method = "PATCH";
options.data = data;
return this._makeRequest(options);
};
Resource.patch = function(options) {
const resource = new Resource(options);
return resource.patch(options.data, {
// Make copy of just the needed fields because headers can be passed to both the constructor and to post
responseType: options.responseType,
overrideMimeType: options.overrideMimeType
});
};
Resource._Implementations = {};
Resource._Implementations.loadImageElement = function(url2, crossOrigin, deferred) {
const image = new Image();
image.onload = function() {
if (image.naturalWidth === 0 && image.naturalHeight === 0 && image.width === 0 && image.height === 0) {
image.width = 300;
image.height = 150;
}
deferred.resolve(image);
};
image.onerror = function(e) {
deferred.reject(e);
};
if (crossOrigin) {
if (TrustedServers_default.contains(url2)) {
image.crossOrigin = "use-credentials";
} else {
image.crossOrigin = "";
}
}
image.src = url2;
};
Resource._Implementations.createImage = function(request, crossOrigin, deferred, flipY, skipColorSpaceConversion, preferImageBitmap) {
const url2 = request.url;
Resource.supportsImageBitmapOptions().then(function(supportsImageBitmap) {
if (!(supportsImageBitmap && preferImageBitmap)) {
Resource._Implementations.loadImageElement(url2, crossOrigin, deferred);
return;
}
const responseType = "blob";
const method = "GET";
const xhrDeferred = defer_default();
const xhr = Resource._Implementations.loadWithXhr(
url2,
responseType,
method,
void 0,
void 0,
xhrDeferred,
void 0,
void 0,
void 0
);
if (defined_default(xhr) && defined_default(xhr.abort)) {
request.cancelFunction = function() {
xhr.abort();
};
}
return xhrDeferred.promise.then(function(blob) {
if (!defined_default(blob)) {
deferred.reject(
new RuntimeError_default(
`Successfully retrieved ${url2} but it contained no content.`
)
);
return;
}
return Resource.createImageBitmapFromBlob(blob, {
flipY,
premultiplyAlpha: false,
skipColorSpaceConversion
});
}).then(function(image) {
deferred.resolve(image);
});
}).catch(function(e) {
deferred.reject(e);
});
};
Resource.createImageBitmapFromBlob = function(blob, options) {
Check_default.defined("options", options);
Check_default.typeOf.bool("options.flipY", options.flipY);
Check_default.typeOf.bool("options.premultiplyAlpha", options.premultiplyAlpha);
Check_default.typeOf.bool(
"options.skipColorSpaceConversion",
options.skipColorSpaceConversion
);
return createImageBitmap(blob, {
imageOrientation: options.flipY ? "flipY" : "from-image",
premultiplyAlpha: options.premultiplyAlpha ? "premultiply" : "none",
colorSpaceConversion: options.skipColorSpaceConversion ? "none" : "default"
});
};
function loadWithHttpRequest(url2, responseType, method, data, headers, deferred, overrideMimeType) {
fetch(url2, {
method,
headers
}).then(async (response) => {
if (!response.ok) {
const responseHeaders = {};
response.headers.forEach((value, key) => {
responseHeaders[key] = value;
});
deferred.reject(
new RequestErrorEvent_default(response.status, response, responseHeaders)
);
return;
}
switch (responseType) {
case "text":
deferred.resolve(response.text());
break;
case "json":
deferred.resolve(response.json());
break;
default:
deferred.resolve(new Uint8Array(await response.arrayBuffer()).buffer);
break;
}
}).catch(() => {
deferred.reject(new RequestErrorEvent_default());
});
}
var noXMLHttpRequest = typeof XMLHttpRequest === "undefined";
Resource._Implementations.loadWithXhr = function(url2, responseType, method, data, headers, deferred, overrideMimeType) {
const dataUriRegexResult = dataUriRegex2.exec(url2);
if (dataUriRegexResult !== null) {
deferred.resolve(decodeDataUri(dataUriRegexResult, responseType));
return;
}
if (noXMLHttpRequest) {
loadWithHttpRequest(
url2,
responseType,
method,
data,
headers,
deferred,
overrideMimeType
);
return;
}
const xhr = new XMLHttpRequest();
if (TrustedServers_default.contains(url2)) {
xhr.withCredentials = true;
}
xhr.open(method, url2, true);
if (defined_default(overrideMimeType) && defined_default(xhr.overrideMimeType)) {
xhr.overrideMimeType(overrideMimeType);
}
if (defined_default(headers)) {
for (const key in headers) {
if (headers.hasOwnProperty(key)) {
xhr.setRequestHeader(key, headers[key]);
}
}
}
if (defined_default(responseType)) {
xhr.responseType = responseType;
}
let localFile = false;
if (typeof url2 === "string") {
localFile = url2.indexOf("file://") === 0 || typeof window !== "undefined" && window.location.origin === "file://";
}
xhr.onload = function() {
if ((xhr.status < 200 || xhr.status >= 300) && !(localFile && xhr.status === 0)) {
deferred.reject(
new RequestErrorEvent_default(
xhr.status,
xhr.response,
xhr.getAllResponseHeaders()
)
);
return;
}
const response = xhr.response;
const browserResponseType = xhr.responseType;
if (method === "HEAD" || method === "OPTIONS") {
const responseHeaderString = xhr.getAllResponseHeaders();
const splitHeaders = responseHeaderString.trim().split(/[\r\n]+/);
const responseHeaders = {};
splitHeaders.forEach(function(line) {
const parts = line.split(": ");
const header = parts.shift();
responseHeaders[header] = parts.join(": ");
});
deferred.resolve(responseHeaders);
return;
}
if (xhr.status === 204) {
deferred.resolve(void 0);
} else if (defined_default(response) && (!defined_default(responseType) || browserResponseType === responseType)) {
deferred.resolve(response);
} else if (responseType === "json" && typeof response === "string") {
try {
deferred.resolve(JSON.parse(response));
} catch (e) {
deferred.reject(e);
}
} else if ((browserResponseType === "" || browserResponseType === "document") && defined_default(xhr.responseXML) && xhr.responseXML.hasChildNodes()) {
deferred.resolve(xhr.responseXML);
} else if ((browserResponseType === "" || browserResponseType === "text") && defined_default(xhr.responseText)) {
deferred.resolve(xhr.responseText);
} else {
deferred.reject(
new RuntimeError_default("Invalid XMLHttpRequest response type.")
);
}
};
xhr.onerror = function(e) {
deferred.reject(new RequestErrorEvent_default());
};
xhr.send(data);
return xhr;
};
Resource._Implementations.loadAndExecuteScript = function(url2, functionName, deferred) {
return loadAndExecuteScript_default(url2, functionName).catch(function(e) {
deferred.reject(e);
});
};
Resource._DefaultImplementations = {};
Resource._DefaultImplementations.createImage = Resource._Implementations.createImage;
Resource._DefaultImplementations.loadWithXhr = Resource._Implementations.loadWithXhr;
Resource._DefaultImplementations.loadAndExecuteScript = Resource._Implementations.loadAndExecuteScript;
Resource.DEFAULT = Object.freeze(
new Resource({
url: typeof document === "undefined" ? "" : document.location.href.split("?")[0]
})
);
var Resource_default = Resource;
// packages/engine/Source/Core/EarthOrientationParameters.js
function EarthOrientationParameters(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._dates = void 0;
this._samples = void 0;
this._dateColumn = -1;
this._xPoleWanderRadiansColumn = -1;
this._yPoleWanderRadiansColumn = -1;
this._ut1MinusUtcSecondsColumn = -1;
this._xCelestialPoleOffsetRadiansColumn = -1;
this._yCelestialPoleOffsetRadiansColumn = -1;
this._taiMinusUtcSecondsColumn = -1;
this._columnCount = 0;
this._lastIndex = -1;
this._addNewLeapSeconds = options.addNewLeapSeconds ?? true;
if (defined_default(options.data)) {
onDataReady(this, options.data);
} else {
onDataReady(this, {
columnNames: [
"dateIso8601",
"modifiedJulianDateUtc",
"xPoleWanderRadians",
"yPoleWanderRadians",
"ut1MinusUtcSeconds",
"lengthOfDayCorrectionSeconds",
"xCelestialPoleOffsetRadians",
"yCelestialPoleOffsetRadians",
"taiMinusUtcSeconds"
],
samples: []
});
}
}
EarthOrientationParameters.fromUrl = async function(url2, options) {
Check_default.defined("url", url2);
options = options ?? Frozen_default.EMPTY_OBJECT;
const resource = Resource_default.createIfNeeded(url2);
let eopData;
try {
eopData = await resource.fetchJson();
} catch (e) {
throw new RuntimeError_default(
`An error occurred while retrieving the EOP data from the URL ${resource.url}.`
);
}
return new EarthOrientationParameters({
addNewLeapSeconds: options.addNewLeapSeconds,
data: eopData
});
};
EarthOrientationParameters.NONE = Object.freeze({
compute: function(date, result) {
if (!defined_default(result)) {
result = new EarthOrientationParametersSample_default(0, 0, 0, 0, 0);
} else {
result.xPoleWander = 0;
result.yPoleWander = 0;
result.xPoleOffset = 0;
result.yPoleOffset = 0;
result.ut1MinusUtc = 0;
}
return result;
}
});
EarthOrientationParameters.prototype.compute = function(date, result) {
if (!defined_default(this._samples)) {
return void 0;
}
if (!defined_default(result)) {
result = new EarthOrientationParametersSample_default(0, 0, 0, 0, 0);
}
if (this._samples.length === 0) {
result.xPoleWander = 0;
result.yPoleWander = 0;
result.xPoleOffset = 0;
result.yPoleOffset = 0;
result.ut1MinusUtc = 0;
return result;
}
const dates = this._dates;
const lastIndex = this._lastIndex;
let before = 0;
let after = 0;
if (defined_default(lastIndex)) {
const previousIndexDate = dates[lastIndex];
const nextIndexDate = dates[lastIndex + 1];
const isAfterPrevious = JulianDate_default.lessThanOrEquals(
previousIndexDate,
date
);
const isAfterLastSample = !defined_default(nextIndexDate);
const isBeforeNext = isAfterLastSample || JulianDate_default.greaterThanOrEquals(nextIndexDate, date);
if (isAfterPrevious && isBeforeNext) {
before = lastIndex;
if (!isAfterLastSample && nextIndexDate.equals(date)) {
++before;
}
after = before + 1;
interpolate(this, dates, this._samples, date, before, after, result);
return result;
}
}
let index = binarySearch_default(dates, date, JulianDate_default.compare, this._dateColumn);
if (index >= 0) {
if (index < dates.length - 1 && dates[index + 1].equals(date)) {
++index;
}
before = index;
after = index;
} else {
after = ~index;
before = after - 1;
if (before < 0) {
before = 0;
}
}
this._lastIndex = before;
interpolate(this, dates, this._samples, date, before, after, result);
return result;
};
function compareLeapSecondDates2(leapSecond, dateToFind) {
return JulianDate_default.compare(leapSecond.julianDate, dateToFind);
}
function onDataReady(eop, eopData) {
if (!defined_default(eopData.columnNames)) {
throw new RuntimeError_default(
"Error in loaded EOP data: The columnNames property is required."
);
}
if (!defined_default(eopData.samples)) {
throw new RuntimeError_default(
"Error in loaded EOP data: The samples property is required."
);
}
const dateColumn = eopData.columnNames.indexOf("modifiedJulianDateUtc");
const xPoleWanderRadiansColumn = eopData.columnNames.indexOf("xPoleWanderRadians");
const yPoleWanderRadiansColumn = eopData.columnNames.indexOf("yPoleWanderRadians");
const ut1MinusUtcSecondsColumn = eopData.columnNames.indexOf("ut1MinusUtcSeconds");
const xCelestialPoleOffsetRadiansColumn = eopData.columnNames.indexOf(
"xCelestialPoleOffsetRadians"
);
const yCelestialPoleOffsetRadiansColumn = eopData.columnNames.indexOf(
"yCelestialPoleOffsetRadians"
);
const taiMinusUtcSecondsColumn = eopData.columnNames.indexOf("taiMinusUtcSeconds");
if (dateColumn < 0 || xPoleWanderRadiansColumn < 0 || yPoleWanderRadiansColumn < 0 || ut1MinusUtcSecondsColumn < 0 || xCelestialPoleOffsetRadiansColumn < 0 || yCelestialPoleOffsetRadiansColumn < 0 || taiMinusUtcSecondsColumn < 0) {
throw new RuntimeError_default(
"Error in loaded EOP data: The columnNames property must include modifiedJulianDateUtc, xPoleWanderRadians, yPoleWanderRadians, ut1MinusUtcSeconds, xCelestialPoleOffsetRadians, yCelestialPoleOffsetRadians, and taiMinusUtcSeconds columns"
);
}
const samples = eop._samples = eopData.samples;
const dates = eop._dates = [];
eop._dateColumn = dateColumn;
eop._xPoleWanderRadiansColumn = xPoleWanderRadiansColumn;
eop._yPoleWanderRadiansColumn = yPoleWanderRadiansColumn;
eop._ut1MinusUtcSecondsColumn = ut1MinusUtcSecondsColumn;
eop._xCelestialPoleOffsetRadiansColumn = xCelestialPoleOffsetRadiansColumn;
eop._yCelestialPoleOffsetRadiansColumn = yCelestialPoleOffsetRadiansColumn;
eop._taiMinusUtcSecondsColumn = taiMinusUtcSecondsColumn;
eop._columnCount = eopData.columnNames.length;
eop._lastIndex = void 0;
let lastTaiMinusUtc;
const addNewLeapSeconds = eop._addNewLeapSeconds;
for (let i = 0, len = samples.length; i < len; i += eop._columnCount) {
const mjd = samples[i + dateColumn];
const taiMinusUtc = samples[i + taiMinusUtcSecondsColumn];
const day = mjd + TimeConstants_default.MODIFIED_JULIAN_DATE_DIFFERENCE;
const date = new JulianDate_default(day, taiMinusUtc, TimeStandard_default.TAI);
dates.push(date);
if (addNewLeapSeconds) {
if (taiMinusUtc !== lastTaiMinusUtc && defined_default(lastTaiMinusUtc)) {
const leapSeconds = JulianDate_default.leapSeconds;
const leapSecondIndex = binarySearch_default(
leapSeconds,
date,
compareLeapSecondDates2
);
if (leapSecondIndex < 0) {
const leapSecond = new LeapSecond_default(date, taiMinusUtc);
leapSeconds.splice(~leapSecondIndex, 0, leapSecond);
}
}
lastTaiMinusUtc = taiMinusUtc;
}
}
}
function fillResultFromIndex(eop, samples, index, columnCount, result) {
const start = index * columnCount;
result.xPoleWander = samples[start + eop._xPoleWanderRadiansColumn];
result.yPoleWander = samples[start + eop._yPoleWanderRadiansColumn];
result.xPoleOffset = samples[start + eop._xCelestialPoleOffsetRadiansColumn];
result.yPoleOffset = samples[start + eop._yCelestialPoleOffsetRadiansColumn];
result.ut1MinusUtc = samples[start + eop._ut1MinusUtcSecondsColumn];
}
function linearInterp(dx, y1, y2) {
return y1 + dx * (y2 - y1);
}
function interpolate(eop, dates, samples, date, before, after, result) {
const columnCount = eop._columnCount;
if (after > dates.length - 1) {
result.xPoleWander = 0;
result.yPoleWander = 0;
result.xPoleOffset = 0;
result.yPoleOffset = 0;
result.ut1MinusUtc = 0;
return result;
}
const beforeDate = dates[before];
const afterDate = dates[after];
if (beforeDate.equals(afterDate) || date.equals(beforeDate)) {
fillResultFromIndex(eop, samples, before, columnCount, result);
return result;
} else if (date.equals(afterDate)) {
fillResultFromIndex(eop, samples, after, columnCount, result);
return result;
}
const factor2 = JulianDate_default.secondsDifference(date, beforeDate) / JulianDate_default.secondsDifference(afterDate, beforeDate);
const startBefore = before * columnCount;
const startAfter = after * columnCount;
let beforeUt1MinusUtc = samples[startBefore + eop._ut1MinusUtcSecondsColumn];
let afterUt1MinusUtc = samples[startAfter + eop._ut1MinusUtcSecondsColumn];
const offsetDifference = afterUt1MinusUtc - beforeUt1MinusUtc;
if (offsetDifference > 0.5 || offsetDifference < -0.5) {
const beforeTaiMinusUtc = samples[startBefore + eop._taiMinusUtcSecondsColumn];
const afterTaiMinusUtc = samples[startAfter + eop._taiMinusUtcSecondsColumn];
if (beforeTaiMinusUtc !== afterTaiMinusUtc) {
if (afterDate.equals(date)) {
beforeUt1MinusUtc = afterUt1MinusUtc;
} else {
afterUt1MinusUtc -= afterTaiMinusUtc - beforeTaiMinusUtc;
}
}
}
result.xPoleWander = linearInterp(
factor2,
samples[startBefore + eop._xPoleWanderRadiansColumn],
samples[startAfter + eop._xPoleWanderRadiansColumn]
);
result.yPoleWander = linearInterp(
factor2,
samples[startBefore + eop._yPoleWanderRadiansColumn],
samples[startAfter + eop._yPoleWanderRadiansColumn]
);
result.xPoleOffset = linearInterp(
factor2,
samples[startBefore + eop._xCelestialPoleOffsetRadiansColumn],
samples[startAfter + eop._xCelestialPoleOffsetRadiansColumn]
);
result.yPoleOffset = linearInterp(
factor2,
samples[startBefore + eop._yCelestialPoleOffsetRadiansColumn],
samples[startAfter + eop._yCelestialPoleOffsetRadiansColumn]
);
result.ut1MinusUtc = linearInterp(
factor2,
beforeUt1MinusUtc,
afterUt1MinusUtc
);
return result;
}
var EarthOrientationParameters_default = EarthOrientationParameters;
// packages/engine/Source/Core/HeadingPitchRoll.js
var import_InlineWorkers63 = __toESM(require_InlineWorkers(), 1);
function HeadingPitchRoll(heading, pitch, roll) {
this.heading = heading ?? 0;
this.pitch = pitch ?? 0;
this.roll = roll ?? 0;
}
HeadingPitchRoll.fromQuaternion = function(quaternion, result) {
if (!defined_default(quaternion)) {
throw new DeveloperError_default("quaternion is required");
}
if (!defined_default(result)) {
result = new HeadingPitchRoll();
}
const test = 2 * (quaternion.w * quaternion.y - quaternion.z * quaternion.x);
const denominatorRoll = 1 - 2 * (quaternion.x * quaternion.x + quaternion.y * quaternion.y);
const numeratorRoll = 2 * (quaternion.w * quaternion.x + quaternion.y * quaternion.z);
const denominatorHeading = 1 - 2 * (quaternion.y * quaternion.y + quaternion.z * quaternion.z);
const numeratorHeading = 2 * (quaternion.w * quaternion.z + quaternion.x * quaternion.y);
result.heading = -Math.atan2(numeratorHeading, denominatorHeading);
result.roll = Math.atan2(numeratorRoll, denominatorRoll);
result.pitch = -Math_default.asinClamped(test);
return result;
};
HeadingPitchRoll.fromDegrees = function(heading, pitch, roll, result) {
if (!defined_default(heading)) {
throw new DeveloperError_default("heading is required");
}
if (!defined_default(pitch)) {
throw new DeveloperError_default("pitch is required");
}
if (!defined_default(roll)) {
throw new DeveloperError_default("roll is required");
}
if (!defined_default(result)) {
result = new HeadingPitchRoll();
}
result.heading = heading * Math_default.RADIANS_PER_DEGREE;
result.pitch = pitch * Math_default.RADIANS_PER_DEGREE;
result.roll = roll * Math_default.RADIANS_PER_DEGREE;
return result;
};
HeadingPitchRoll.clone = function(headingPitchRoll, result) {
if (!defined_default(headingPitchRoll)) {
return void 0;
}
if (!defined_default(result)) {
return new HeadingPitchRoll(
headingPitchRoll.heading,
headingPitchRoll.pitch,
headingPitchRoll.roll
);
}
result.heading = headingPitchRoll.heading;
result.pitch = headingPitchRoll.pitch;
result.roll = headingPitchRoll.roll;
return result;
};
HeadingPitchRoll.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left.heading === right.heading && left.pitch === right.pitch && left.roll === right.roll;
};
HeadingPitchRoll.equalsEpsilon = function(left, right, relativeEpsilon, absoluteEpsilon) {
return left === right || defined_default(left) && defined_default(right) && Math_default.equalsEpsilon(
left.heading,
right.heading,
relativeEpsilon,
absoluteEpsilon
) && Math_default.equalsEpsilon(
left.pitch,
right.pitch,
relativeEpsilon,
absoluteEpsilon
) && Math_default.equalsEpsilon(
left.roll,
right.roll,
relativeEpsilon,
absoluteEpsilon
);
};
HeadingPitchRoll.prototype.clone = function(result) {
return HeadingPitchRoll.clone(this, result);
};
HeadingPitchRoll.prototype.equals = function(right) {
return HeadingPitchRoll.equals(this, right);
};
HeadingPitchRoll.prototype.equalsEpsilon = function(right, relativeEpsilon, absoluteEpsilon) {
return HeadingPitchRoll.equalsEpsilon(
this,
right,
relativeEpsilon,
absoluteEpsilon
);
};
HeadingPitchRoll.prototype.toString = function() {
return `(${this.heading}, ${this.pitch}, ${this.roll})`;
};
var HeadingPitchRoll_default = HeadingPitchRoll;
// packages/engine/Source/Core/Iau2006XysData.js
var import_InlineWorkers66 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/buildModuleUrl.js
var import_InlineWorkers64 = __toESM(require_InlineWorkers(), 1);
var import_meta = {};
var cesiumScriptRegex = /((?:.*\/)|^)Cesium\.js(?:\?|\#|$)/;
function getBaseUrlFromCesiumScript() {
const scripts = document.getElementsByTagName("script");
for (let i = 0, len = scripts.length; i < len; ++i) {
const src = scripts[i].getAttribute("src");
const result = cesiumScriptRegex.exec(src);
if (result !== null) {
return result[1];
}
}
return void 0;
}
var a2;
function tryMakeAbsolute(url2) {
if (typeof document === "undefined") {
return url2;
}
if (!defined_default(a2)) {
a2 = document.createElement("a");
}
a2.href = url2;
return a2.href;
}
var baseResource;
function getCesiumBaseUrl() {
if (defined_default(baseResource)) {
return baseResource;
}
let baseUrlString;
if (typeof CESIUM_BASE_URL !== "undefined") {
baseUrlString = CESIUM_BASE_URL;
} else if (defined_default(import_meta?.url)) {
baseUrlString = getAbsoluteUri_default(".", import_meta.url);
} else if (typeof define === "object" && defined_default(define.amd) && !define.amd.toUrlUndefined && defined_default(__require.toUrl)) {
baseUrlString = getAbsoluteUri_default(
"..",
buildModuleUrl("Core/buildModuleUrl.js")
);
} else {
baseUrlString = getBaseUrlFromCesiumScript();
}
if (!defined_default(baseUrlString)) {
throw new DeveloperError_default(
"Unable to determine Cesium base URL automatically, try defining a global variable called CESIUM_BASE_URL."
);
}
baseResource = new Resource_default({
url: tryMakeAbsolute(baseUrlString)
});
baseResource.appendForwardSlash();
return baseResource;
}
function buildModuleUrlFromRequireToUrl(moduleID) {
return tryMakeAbsolute(__require.toUrl(`../${moduleID}`));
}
function buildModuleUrlFromBaseUrl(moduleID) {
const resource = getCesiumBaseUrl().getDerivedResource({
url: moduleID
});
return resource.url;
}
var implementation;
function buildModuleUrl(relativeUrl) {
if (!defined_default(implementation)) {
if (typeof define === "object" && defined_default(define.amd) && !define.amd.toUrlUndefined && defined_default(__require.toUrl)) {
implementation = buildModuleUrlFromRequireToUrl;
} else {
implementation = buildModuleUrlFromBaseUrl;
}
}
const url2 = implementation(relativeUrl);
return url2;
}
buildModuleUrl._cesiumScriptRegex = cesiumScriptRegex;
buildModuleUrl._buildModuleUrlFromBaseUrl = buildModuleUrlFromBaseUrl;
buildModuleUrl._clearBaseResource = function() {
baseResource = void 0;
};
buildModuleUrl.setBaseUrl = function(value) {
baseResource = Resource_default.DEFAULT.getDerivedResource({
url: value
});
};
buildModuleUrl.getCesiumBaseUrl = getCesiumBaseUrl;
var buildModuleUrl_default = buildModuleUrl;
// packages/engine/Source/Core/Iau2006XysSample.js
var import_InlineWorkers65 = __toESM(require_InlineWorkers(), 1);
function Iau2006XysSample(x, y, s) {
this.x = x;
this.y = y;
this.s = s;
}
var Iau2006XysSample_default = Iau2006XysSample;
// packages/engine/Source/Core/Iau2006XysData.js
function Iau2006XysData(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._xysFileUrlTemplate = Resource_default.createIfNeeded(
options.xysFileUrlTemplate
);
this._interpolationOrder = options.interpolationOrder ?? 9;
this._sampleZeroJulianEphemerisDate = options.sampleZeroJulianEphemerisDate ?? 24423965e-1;
this._sampleZeroDateTT = new JulianDate_default(
this._sampleZeroJulianEphemerisDate,
0,
TimeStandard_default.TAI
);
this._stepSizeDays = options.stepSizeDays ?? 1;
this._samplesPerXysFile = options.samplesPerXysFile ?? 1e3;
this._totalSamples = options.totalSamples ?? 27426;
this._samples = new Array(this._totalSamples * 3);
this._chunkDownloadsInProgress = [];
const order = this._interpolationOrder;
const denom = this._denominators = new Array(order + 1);
const xTable = this._xTable = new Array(order + 1);
const stepN = Math.pow(this._stepSizeDays, order);
for (let i = 0; i <= order; ++i) {
denom[i] = stepN;
xTable[i] = i * this._stepSizeDays;
for (let j = 0; j <= order; ++j) {
if (j !== i) {
denom[i] *= i - j;
}
}
denom[i] = 1 / denom[i];
}
this._work = new Array(order + 1);
this._coef = new Array(order + 1);
}
var julianDateScratch = new JulianDate_default(0, 0, TimeStandard_default.TAI);
function getDaysSinceEpoch(xys, dayTT, secondTT) {
const dateTT2 = julianDateScratch;
dateTT2.dayNumber = dayTT;
dateTT2.secondsOfDay = secondTT;
return JulianDate_default.daysDifference(dateTT2, xys._sampleZeroDateTT);
}
Iau2006XysData.prototype.preload = function(startDayTT, startSecondTT, stopDayTT, stopSecondTT) {
const startDaysSinceEpoch = getDaysSinceEpoch(
this,
startDayTT,
startSecondTT
);
const stopDaysSinceEpoch = getDaysSinceEpoch(this, stopDayTT, stopSecondTT);
let startIndex = startDaysSinceEpoch / this._stepSizeDays - this._interpolationOrder / 2 | 0;
if (startIndex < 0) {
startIndex = 0;
}
let stopIndex = stopDaysSinceEpoch / this._stepSizeDays - this._interpolationOrder / 2 | 0 + this._interpolationOrder;
if (stopIndex >= this._totalSamples) {
stopIndex = this._totalSamples - 1;
}
const startChunk = startIndex / this._samplesPerXysFile | 0;
const stopChunk = stopIndex / this._samplesPerXysFile | 0;
const promises = [];
for (let i = startChunk; i <= stopChunk; ++i) {
promises.push(requestXysChunk(this, i));
}
return Promise.all(promises);
};
Iau2006XysData.prototype.computeXysRadians = function(dayTT, secondTT, result) {
const daysSinceEpoch = getDaysSinceEpoch(this, dayTT, secondTT);
if (daysSinceEpoch < 0) {
return void 0;
}
const centerIndex = daysSinceEpoch / this._stepSizeDays | 0;
if (centerIndex >= this._totalSamples) {
return void 0;
}
const degree = this._interpolationOrder;
let firstIndex = centerIndex - (degree / 2 | 0);
if (firstIndex < 0) {
firstIndex = 0;
}
let lastIndex = firstIndex + degree;
if (lastIndex >= this._totalSamples) {
lastIndex = this._totalSamples - 1;
firstIndex = lastIndex - degree;
if (firstIndex < 0) {
firstIndex = 0;
}
}
let isDataMissing = false;
const samples = this._samples;
if (!defined_default(samples[firstIndex * 3])) {
requestXysChunk(this, firstIndex / this._samplesPerXysFile | 0);
isDataMissing = true;
}
if (!defined_default(samples[lastIndex * 3])) {
requestXysChunk(this, lastIndex / this._samplesPerXysFile | 0);
isDataMissing = true;
}
if (isDataMissing) {
return void 0;
}
if (!defined_default(result)) {
result = new Iau2006XysSample_default(0, 0, 0);
} else {
result.x = 0;
result.y = 0;
result.s = 0;
}
const x = daysSinceEpoch - firstIndex * this._stepSizeDays;
const work = this._work;
const denom = this._denominators;
const coef = this._coef;
const xTable = this._xTable;
let i, j;
for (i = 0; i <= degree; ++i) {
work[i] = x - xTable[i];
}
for (i = 0; i <= degree; ++i) {
coef[i] = 1;
for (j = 0; j <= degree; ++j) {
if (j !== i) {
coef[i] *= work[j];
}
}
coef[i] *= denom[i];
let sampleIndex = (firstIndex + i) * 3;
result.x += coef[i] * samples[sampleIndex++];
result.y += coef[i] * samples[sampleIndex++];
result.s += coef[i] * samples[sampleIndex];
}
return result;
};
function requestXysChunk(xysData, chunkIndex) {
if (xysData._chunkDownloadsInProgress[chunkIndex]) {
return xysData._chunkDownloadsInProgress[chunkIndex];
}
let chunkUrl;
const xysFileUrlTemplate = xysData._xysFileUrlTemplate;
if (defined_default(xysFileUrlTemplate)) {
chunkUrl = xysFileUrlTemplate.getDerivedResource({
templateValues: {
0: chunkIndex
}
});
} else {
chunkUrl = new Resource_default({
url: buildModuleUrl_default(`Assets/IAU2006_XYS/IAU2006_XYS_${chunkIndex}.json`)
});
}
const promise = chunkUrl.fetchJson().then(function(chunk) {
xysData._chunkDownloadsInProgress[chunkIndex] = false;
const samples = xysData._samples;
const newSamples = chunk.samples;
const startIndex = chunkIndex * xysData._samplesPerXysFile * 3;
for (let i = 0, len = newSamples.length; i < len; ++i) {
samples[startIndex + i] = newSamples[i];
}
});
xysData._chunkDownloadsInProgress[chunkIndex] = promise;
return promise;
}
var Iau2006XysData_default = Iau2006XysData;
// packages/engine/Source/Core/Quaternion.js
var import_InlineWorkers67 = __toESM(require_InlineWorkers(), 1);
function Quaternion(x, y, z, w) {
this.x = x ?? 0;
this.y = y ?? 0;
this.z = z ?? 0;
this.w = w ?? 0;
}
var fromAxisAngleScratch = new Cartesian3_default();
Quaternion.fromAxisAngle = function(axis, angle, result) {
Check_default.typeOf.object("axis", axis);
Check_default.typeOf.number("angle", angle);
const halfAngle = angle / 2;
const s = Math.sin(halfAngle);
fromAxisAngleScratch = Cartesian3_default.normalize(axis, fromAxisAngleScratch);
const x = fromAxisAngleScratch.x * s;
const y = fromAxisAngleScratch.y * s;
const z = fromAxisAngleScratch.z * s;
const w = Math.cos(halfAngle);
if (!defined_default(result)) {
return new Quaternion(x, y, z, w);
}
result.x = x;
result.y = y;
result.z = z;
result.w = w;
return result;
};
var fromRotationMatrixNext = [1, 2, 0];
var fromRotationMatrixQuat = new Array(3);
Quaternion.fromRotationMatrix = function(matrix, result) {
Check_default.typeOf.object("matrix", matrix);
let root;
let x;
let y;
let z;
let w;
const m00 = matrix[Matrix3_default.COLUMN0ROW0];
const m11 = matrix[Matrix3_default.COLUMN1ROW1];
const m22 = matrix[Matrix3_default.COLUMN2ROW2];
const trace = m00 + m11 + m22;
if (trace > 0) {
root = Math.sqrt(trace + 1);
w = 0.5 * root;
root = 0.5 / root;
x = (matrix[Matrix3_default.COLUMN1ROW2] - matrix[Matrix3_default.COLUMN2ROW1]) * root;
y = (matrix[Matrix3_default.COLUMN2ROW0] - matrix[Matrix3_default.COLUMN0ROW2]) * root;
z = (matrix[Matrix3_default.COLUMN0ROW1] - matrix[Matrix3_default.COLUMN1ROW0]) * root;
} else {
const next = fromRotationMatrixNext;
let i = 0;
if (m11 > m00) {
i = 1;
}
if (m22 > m00 && m22 > m11) {
i = 2;
}
const j = next[i];
const k = next[j];
root = Math.sqrt(
matrix[Matrix3_default.getElementIndex(i, i)] - matrix[Matrix3_default.getElementIndex(j, j)] - matrix[Matrix3_default.getElementIndex(k, k)] + 1
);
const quat = fromRotationMatrixQuat;
quat[i] = 0.5 * root;
root = 0.5 / root;
w = (matrix[Matrix3_default.getElementIndex(k, j)] - matrix[Matrix3_default.getElementIndex(j, k)]) * root;
quat[j] = (matrix[Matrix3_default.getElementIndex(j, i)] + matrix[Matrix3_default.getElementIndex(i, j)]) * root;
quat[k] = (matrix[Matrix3_default.getElementIndex(k, i)] + matrix[Matrix3_default.getElementIndex(i, k)]) * root;
x = -quat[0];
y = -quat[1];
z = -quat[2];
}
if (!defined_default(result)) {
return new Quaternion(x, y, z, w);
}
result.x = x;
result.y = y;
result.z = z;
result.w = w;
return result;
};
var scratchHPRQuaternion = new Quaternion();
var scratchHeadingQuaternion = new Quaternion();
var scratchPitchQuaternion = new Quaternion();
var scratchRollQuaternion = new Quaternion();
Quaternion.fromHeadingPitchRoll = function(headingPitchRoll, result) {
Check_default.typeOf.object("headingPitchRoll", headingPitchRoll);
scratchRollQuaternion = Quaternion.fromAxisAngle(
Cartesian3_default.UNIT_X,
headingPitchRoll.roll,
scratchHPRQuaternion
);
scratchPitchQuaternion = Quaternion.fromAxisAngle(
Cartesian3_default.UNIT_Y,
-headingPitchRoll.pitch,
result
);
result = Quaternion.multiply(
scratchPitchQuaternion,
scratchRollQuaternion,
scratchPitchQuaternion
);
scratchHeadingQuaternion = Quaternion.fromAxisAngle(
Cartesian3_default.UNIT_Z,
-headingPitchRoll.heading,
scratchHPRQuaternion
);
return Quaternion.multiply(scratchHeadingQuaternion, result, result);
};
var sampledQuaternionAxis = new Cartesian3_default();
var sampledQuaternionRotation = new Cartesian3_default();
var sampledQuaternionTempQuaternion = new Quaternion();
var sampledQuaternionQuaternion0 = new Quaternion();
var sampledQuaternionQuaternion0Conjugate = new Quaternion();
Quaternion.packedLength = 4;
Quaternion.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
array[startingIndex++] = value.x;
array[startingIndex++] = value.y;
array[startingIndex++] = value.z;
array[startingIndex] = value.w;
return array;
};
Quaternion.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new Quaternion();
}
result.x = array[startingIndex];
result.y = array[startingIndex + 1];
result.z = array[startingIndex + 2];
result.w = array[startingIndex + 3];
return result;
};
Quaternion.packedInterpolationLength = 3;
Quaternion.convertPackedArrayForInterpolation = function(packedArray, startingIndex, lastIndex, result) {
Quaternion.unpack(
packedArray,
lastIndex * 4,
sampledQuaternionQuaternion0Conjugate
);
Quaternion.conjugate(
sampledQuaternionQuaternion0Conjugate,
sampledQuaternionQuaternion0Conjugate
);
for (let i = 0, len = lastIndex - startingIndex + 1; i < len; i++) {
const offset = i * 3;
Quaternion.unpack(
packedArray,
(startingIndex + i) * 4,
sampledQuaternionTempQuaternion
);
Quaternion.multiply(
sampledQuaternionTempQuaternion,
sampledQuaternionQuaternion0Conjugate,
sampledQuaternionTempQuaternion
);
if (sampledQuaternionTempQuaternion.w < 0) {
Quaternion.negate(
sampledQuaternionTempQuaternion,
sampledQuaternionTempQuaternion
);
}
Quaternion.computeAxis(
sampledQuaternionTempQuaternion,
sampledQuaternionAxis
);
const angle = Quaternion.computeAngle(sampledQuaternionTempQuaternion);
if (!defined_default(result)) {
result = [];
}
result[offset] = sampledQuaternionAxis.x * angle;
result[offset + 1] = sampledQuaternionAxis.y * angle;
result[offset + 2] = sampledQuaternionAxis.z * angle;
}
};
Quaternion.unpackInterpolationResult = function(array, sourceArray, firstIndex, lastIndex, result) {
if (!defined_default(result)) {
result = new Quaternion();
}
Cartesian3_default.fromArray(array, 0, sampledQuaternionRotation);
const magnitude = Cartesian3_default.magnitude(sampledQuaternionRotation);
Quaternion.unpack(sourceArray, lastIndex * 4, sampledQuaternionQuaternion0);
if (magnitude === 0) {
Quaternion.clone(Quaternion.IDENTITY, sampledQuaternionTempQuaternion);
} else {
Quaternion.fromAxisAngle(
sampledQuaternionRotation,
magnitude,
sampledQuaternionTempQuaternion
);
}
return Quaternion.multiply(
sampledQuaternionTempQuaternion,
sampledQuaternionQuaternion0,
result
);
};
Quaternion.clone = function(quaternion, result) {
if (!defined_default(quaternion)) {
return void 0;
}
if (!defined_default(result)) {
return new Quaternion(
quaternion.x,
quaternion.y,
quaternion.z,
quaternion.w
);
}
result.x = quaternion.x;
result.y = quaternion.y;
result.z = quaternion.z;
result.w = quaternion.w;
return result;
};
Quaternion.conjugate = function(quaternion, result) {
Check_default.typeOf.object("quaternion", quaternion);
Check_default.typeOf.object("result", result);
result.x = -quaternion.x;
result.y = -quaternion.y;
result.z = -quaternion.z;
result.w = quaternion.w;
return result;
};
Quaternion.magnitudeSquared = function(quaternion) {
Check_default.typeOf.object("quaternion", quaternion);
return quaternion.x * quaternion.x + quaternion.y * quaternion.y + quaternion.z * quaternion.z + quaternion.w * quaternion.w;
};
Quaternion.magnitude = function(quaternion) {
return Math.sqrt(Quaternion.magnitudeSquared(quaternion));
};
Quaternion.normalize = function(quaternion, result) {
Check_default.typeOf.object("result", result);
const inverseMagnitude = 1 / Quaternion.magnitude(quaternion);
const x = quaternion.x * inverseMagnitude;
const y = quaternion.y * inverseMagnitude;
const z = quaternion.z * inverseMagnitude;
const w = quaternion.w * inverseMagnitude;
result.x = x;
result.y = y;
result.z = z;
result.w = w;
return result;
};
Quaternion.inverse = function(quaternion, result) {
Check_default.typeOf.object("result", result);
const magnitudeSquared = Quaternion.magnitudeSquared(quaternion);
result = Quaternion.conjugate(quaternion, result);
return Quaternion.multiplyByScalar(result, 1 / magnitudeSquared, result);
};
Quaternion.add = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result.x = left.x + right.x;
result.y = left.y + right.y;
result.z = left.z + right.z;
result.w = left.w + right.w;
return result;
};
Quaternion.subtract = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result.x = left.x - right.x;
result.y = left.y - right.y;
result.z = left.z - right.z;
result.w = left.w - right.w;
return result;
};
Quaternion.negate = function(quaternion, result) {
Check_default.typeOf.object("quaternion", quaternion);
Check_default.typeOf.object("result", result);
result.x = -quaternion.x;
result.y = -quaternion.y;
result.z = -quaternion.z;
result.w = -quaternion.w;
return result;
};
Quaternion.dot = function(left, right) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
return left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w;
};
Quaternion.multiply = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
const leftX = left.x;
const leftY = left.y;
const leftZ = left.z;
const leftW = left.w;
const rightX = right.x;
const rightY = right.y;
const rightZ = right.z;
const rightW = right.w;
const x = leftW * rightX + leftX * rightW + leftY * rightZ - leftZ * rightY;
const y = leftW * rightY - leftX * rightZ + leftY * rightW + leftZ * rightX;
const z = leftW * rightZ + leftX * rightY - leftY * rightX + leftZ * rightW;
const w = leftW * rightW - leftX * rightX - leftY * rightY - leftZ * rightZ;
result.x = x;
result.y = y;
result.z = z;
result.w = w;
return result;
};
Quaternion.multiplyByScalar = function(quaternion, scalar, result) {
Check_default.typeOf.object("quaternion", quaternion);
Check_default.typeOf.number("scalar", scalar);
Check_default.typeOf.object("result", result);
result.x = quaternion.x * scalar;
result.y = quaternion.y * scalar;
result.z = quaternion.z * scalar;
result.w = quaternion.w * scalar;
return result;
};
Quaternion.divideByScalar = function(quaternion, scalar, result) {
Check_default.typeOf.object("quaternion", quaternion);
Check_default.typeOf.number("scalar", scalar);
Check_default.typeOf.object("result", result);
result.x = quaternion.x / scalar;
result.y = quaternion.y / scalar;
result.z = quaternion.z / scalar;
result.w = quaternion.w / scalar;
return result;
};
Quaternion.computeAxis = function(quaternion, result) {
Check_default.typeOf.object("quaternion", quaternion);
Check_default.typeOf.object("result", result);
const w = quaternion.w;
if (Math.abs(w - 1) < Math_default.EPSILON6 || Math.abs(w + 1) < Math_default.EPSILON6) {
result.x = 1;
result.y = result.z = 0;
return result;
}
const scalar = 1 / Math.sqrt(1 - w * w);
result.x = quaternion.x * scalar;
result.y = quaternion.y * scalar;
result.z = quaternion.z * scalar;
return result;
};
Quaternion.computeAngle = function(quaternion) {
Check_default.typeOf.object("quaternion", quaternion);
if (Math.abs(quaternion.w - 1) < Math_default.EPSILON6) {
return 0;
}
return 2 * Math.acos(quaternion.w);
};
var lerpScratch4 = new Quaternion();
Quaternion.lerp = function(start, end, t, result) {
Check_default.typeOf.object("start", start);
Check_default.typeOf.object("end", end);
Check_default.typeOf.number("t", t);
Check_default.typeOf.object("result", result);
lerpScratch4 = Quaternion.multiplyByScalar(end, t, lerpScratch4);
result = Quaternion.multiplyByScalar(start, 1 - t, result);
return Quaternion.add(lerpScratch4, result, result);
};
var slerpEndNegated = new Quaternion();
var slerpScaledP = new Quaternion();
var slerpScaledR = new Quaternion();
Quaternion.slerp = function(start, end, t, result) {
Check_default.typeOf.object("start", start);
Check_default.typeOf.object("end", end);
Check_default.typeOf.number("t", t);
Check_default.typeOf.object("result", result);
let dot2 = Quaternion.dot(start, end);
let r = end;
if (dot2 < 0) {
dot2 = -dot2;
r = slerpEndNegated = Quaternion.negate(end, slerpEndNegated);
}
if (1 - dot2 < Math_default.EPSILON6) {
return Quaternion.lerp(start, r, t, result);
}
const theta = Math.acos(dot2);
slerpScaledP = Quaternion.multiplyByScalar(
start,
Math.sin((1 - t) * theta),
slerpScaledP
);
slerpScaledR = Quaternion.multiplyByScalar(
r,
Math.sin(t * theta),
slerpScaledR
);
result = Quaternion.add(slerpScaledP, slerpScaledR, result);
return Quaternion.multiplyByScalar(result, 1 / Math.sin(theta), result);
};
Quaternion.log = function(quaternion, result) {
Check_default.typeOf.object("quaternion", quaternion);
Check_default.typeOf.object("result", result);
const theta = Math_default.acosClamped(quaternion.w);
let thetaOverSinTheta = 0;
if (theta !== 0) {
thetaOverSinTheta = theta / Math.sin(theta);
}
return Cartesian3_default.multiplyByScalar(quaternion, thetaOverSinTheta, result);
};
Quaternion.exp = function(cartesian11, result) {
Check_default.typeOf.object("cartesian", cartesian11);
Check_default.typeOf.object("result", result);
const theta = Cartesian3_default.magnitude(cartesian11);
let sinThetaOverTheta = 0;
if (theta !== 0) {
sinThetaOverTheta = Math.sin(theta) / theta;
}
result.x = cartesian11.x * sinThetaOverTheta;
result.y = cartesian11.y * sinThetaOverTheta;
result.z = cartesian11.z * sinThetaOverTheta;
result.w = Math.cos(theta);
return result;
};
var squadScratchCartesian0 = new Cartesian3_default();
var squadScratchCartesian1 = new Cartesian3_default();
var squadScratchQuaternion0 = new Quaternion();
var squadScratchQuaternion1 = new Quaternion();
Quaternion.computeInnerQuadrangle = function(q0, q12, q22, result) {
Check_default.typeOf.object("q0", q0);
Check_default.typeOf.object("q1", q12);
Check_default.typeOf.object("q2", q22);
Check_default.typeOf.object("result", result);
const qInv = Quaternion.conjugate(q12, squadScratchQuaternion0);
Quaternion.multiply(qInv, q22, squadScratchQuaternion1);
const cart0 = Quaternion.log(squadScratchQuaternion1, squadScratchCartesian0);
Quaternion.multiply(qInv, q0, squadScratchQuaternion1);
const cart1 = Quaternion.log(squadScratchQuaternion1, squadScratchCartesian1);
Cartesian3_default.add(cart0, cart1, cart0);
Cartesian3_default.multiplyByScalar(cart0, 0.25, cart0);
Cartesian3_default.negate(cart0, cart0);
Quaternion.exp(cart0, squadScratchQuaternion0);
return Quaternion.multiply(q12, squadScratchQuaternion0, result);
};
Quaternion.squad = function(q0, q12, s0, s1, t, result) {
Check_default.typeOf.object("q0", q0);
Check_default.typeOf.object("q1", q12);
Check_default.typeOf.object("s0", s0);
Check_default.typeOf.object("s1", s1);
Check_default.typeOf.number("t", t);
Check_default.typeOf.object("result", result);
const slerp0 = Quaternion.slerp(q0, q12, t, squadScratchQuaternion0);
const slerp1 = Quaternion.slerp(s0, s1, t, squadScratchQuaternion1);
return Quaternion.slerp(slerp0, slerp1, 2 * t * (1 - t), result);
};
var fastSlerpScratchQuaternion = new Quaternion();
var opmu = 1.9011074535173003;
var u = FeatureDetection_default.supportsTypedArrays() ? new Float32Array(8) : [];
var v = FeatureDetection_default.supportsTypedArrays() ? new Float32Array(8) : [];
var bT = FeatureDetection_default.supportsTypedArrays() ? new Float32Array(8) : [];
var bD = FeatureDetection_default.supportsTypedArrays() ? new Float32Array(8) : [];
for (let i = 0; i < 7; ++i) {
const s = i + 1;
const t = 2 * s + 1;
u[i] = 1 / (s * t);
v[i] = s / t;
}
u[7] = opmu / (8 * 17);
v[7] = opmu * 8 / 17;
Quaternion.fastSlerp = function(start, end, t, result) {
Check_default.typeOf.object("start", start);
Check_default.typeOf.object("end", end);
Check_default.typeOf.number("t", t);
Check_default.typeOf.object("result", result);
let x = Quaternion.dot(start, end);
let sign3;
if (x >= 0) {
sign3 = 1;
} else {
sign3 = -1;
x = -x;
}
const xm1 = x - 1;
const d = 1 - t;
const sqrT = t * t;
const sqrD = d * d;
for (let i = 7; i >= 0; --i) {
bT[i] = (u[i] * sqrT - v[i]) * xm1;
bD[i] = (u[i] * sqrD - v[i]) * xm1;
}
const cT = sign3 * t * (1 + bT[0] * (1 + bT[1] * (1 + bT[2] * (1 + bT[3] * (1 + bT[4] * (1 + bT[5] * (1 + bT[6] * (1 + bT[7]))))))));
const cD = d * (1 + bD[0] * (1 + bD[1] * (1 + bD[2] * (1 + bD[3] * (1 + bD[4] * (1 + bD[5] * (1 + bD[6] * (1 + bD[7]))))))));
const temp = Quaternion.multiplyByScalar(
start,
cD,
fastSlerpScratchQuaternion
);
Quaternion.multiplyByScalar(end, cT, result);
return Quaternion.add(temp, result, result);
};
Quaternion.fastSquad = function(q0, q12, s0, s1, t, result) {
Check_default.typeOf.object("q0", q0);
Check_default.typeOf.object("q1", q12);
Check_default.typeOf.object("s0", s0);
Check_default.typeOf.object("s1", s1);
Check_default.typeOf.number("t", t);
Check_default.typeOf.object("result", result);
const slerp0 = Quaternion.fastSlerp(q0, q12, t, squadScratchQuaternion0);
const slerp1 = Quaternion.fastSlerp(s0, s1, t, squadScratchQuaternion1);
return Quaternion.fastSlerp(slerp0, slerp1, 2 * t * (1 - t), result);
};
Quaternion.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left.x === right.x && left.y === right.y && left.z === right.z && left.w === right.w;
};
Quaternion.equalsEpsilon = function(left, right, epsilon) {
epsilon = epsilon ?? 0;
return left === right || defined_default(left) && defined_default(right) && Math.abs(left.x - right.x) <= epsilon && Math.abs(left.y - right.y) <= epsilon && Math.abs(left.z - right.z) <= epsilon && Math.abs(left.w - right.w) <= epsilon;
};
Quaternion.ZERO = Object.freeze(new Quaternion(0, 0, 0, 0));
Quaternion.IDENTITY = Object.freeze(new Quaternion(0, 0, 0, 1));
Quaternion.prototype.clone = function(result) {
return Quaternion.clone(this, result);
};
Quaternion.prototype.equals = function(right) {
return Quaternion.equals(this, right);
};
Quaternion.prototype.equalsEpsilon = function(right, epsilon) {
return Quaternion.equalsEpsilon(this, right, epsilon);
};
Quaternion.prototype.toString = function() {
return `(${this.x}, ${this.y}, ${this.z}, ${this.w})`;
};
var Quaternion_default = Quaternion;
// packages/engine/Source/Core/Transforms.js
var Transforms = {};
var vectorProductLocalFrame = {
up: {
south: "east",
north: "west",
west: "south",
east: "north"
},
down: {
south: "west",
north: "east",
west: "north",
east: "south"
},
south: {
up: "west",
down: "east",
west: "down",
east: "up"
},
north: {
up: "east",
down: "west",
west: "up",
east: "down"
},
west: {
up: "north",
down: "south",
north: "down",
south: "up"
},
east: {
up: "south",
down: "north",
north: "up",
south: "down"
}
};
var degeneratePositionLocalFrame = {
north: [-1, 0, 0],
east: [0, 1, 0],
up: [0, 0, 1],
south: [1, 0, 0],
west: [0, -1, 0],
down: [0, 0, -1]
};
var localFrameToFixedFrameCache = {};
var scratchCalculateCartesian = {
east: new Cartesian3_default(),
north: new Cartesian3_default(),
up: new Cartesian3_default(),
west: new Cartesian3_default(),
south: new Cartesian3_default(),
down: new Cartesian3_default()
};
var scratchFirstCartesian = new Cartesian3_default();
var scratchSecondCartesian = new Cartesian3_default();
var scratchThirdCartesian = new Cartesian3_default();
Transforms.localFrameToFixedFrameGenerator = function(firstAxis, secondAxis) {
if (!vectorProductLocalFrame.hasOwnProperty(firstAxis) || !vectorProductLocalFrame[firstAxis].hasOwnProperty(secondAxis)) {
throw new DeveloperError_default(
"firstAxis and secondAxis must be east, north, up, west, south or down."
);
}
const thirdAxis = vectorProductLocalFrame[firstAxis][secondAxis];
let resultat;
const hashAxis = firstAxis + secondAxis;
if (defined_default(localFrameToFixedFrameCache[hashAxis])) {
resultat = localFrameToFixedFrameCache[hashAxis];
} else {
resultat = function(origin, ellipsoid, result) {
if (!defined_default(origin)) {
throw new DeveloperError_default("origin is required.");
}
if (isNaN(origin.x) || isNaN(origin.y) || isNaN(origin.z)) {
throw new DeveloperError_default("origin has a NaN component");
}
if (!defined_default(result)) {
result = new Matrix4_default();
}
if (Cartesian3_default.equalsEpsilon(origin, Cartesian3_default.ZERO, Math_default.EPSILON14)) {
Cartesian3_default.unpack(
degeneratePositionLocalFrame[firstAxis],
0,
scratchFirstCartesian
);
Cartesian3_default.unpack(
degeneratePositionLocalFrame[secondAxis],
0,
scratchSecondCartesian
);
Cartesian3_default.unpack(
degeneratePositionLocalFrame[thirdAxis],
0,
scratchThirdCartesian
);
} else if (Math_default.equalsEpsilon(origin.x, 0, Math_default.EPSILON14) && Math_default.equalsEpsilon(origin.y, 0, Math_default.EPSILON14)) {
const sign3 = Math_default.sign(origin.z);
Cartesian3_default.unpack(
degeneratePositionLocalFrame[firstAxis],
0,
scratchFirstCartesian
);
if (firstAxis !== "east" && firstAxis !== "west") {
Cartesian3_default.multiplyByScalar(
scratchFirstCartesian,
sign3,
scratchFirstCartesian
);
}
Cartesian3_default.unpack(
degeneratePositionLocalFrame[secondAxis],
0,
scratchSecondCartesian
);
if (secondAxis !== "east" && secondAxis !== "west") {
Cartesian3_default.multiplyByScalar(
scratchSecondCartesian,
sign3,
scratchSecondCartesian
);
}
Cartesian3_default.unpack(
degeneratePositionLocalFrame[thirdAxis],
0,
scratchThirdCartesian
);
if (thirdAxis !== "east" && thirdAxis !== "west") {
Cartesian3_default.multiplyByScalar(
scratchThirdCartesian,
sign3,
scratchThirdCartesian
);
}
} else {
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
ellipsoid.geodeticSurfaceNormal(origin, scratchCalculateCartesian.up);
const up = scratchCalculateCartesian.up;
const east = scratchCalculateCartesian.east;
east.x = -origin.y;
east.y = origin.x;
east.z = 0;
Cartesian3_default.normalize(east, scratchCalculateCartesian.east);
Cartesian3_default.cross(up, east, scratchCalculateCartesian.north);
Cartesian3_default.multiplyByScalar(
scratchCalculateCartesian.up,
-1,
scratchCalculateCartesian.down
);
Cartesian3_default.multiplyByScalar(
scratchCalculateCartesian.east,
-1,
scratchCalculateCartesian.west
);
Cartesian3_default.multiplyByScalar(
scratchCalculateCartesian.north,
-1,
scratchCalculateCartesian.south
);
scratchFirstCartesian = scratchCalculateCartesian[firstAxis];
scratchSecondCartesian = scratchCalculateCartesian[secondAxis];
scratchThirdCartesian = scratchCalculateCartesian[thirdAxis];
}
result[0] = scratchFirstCartesian.x;
result[1] = scratchFirstCartesian.y;
result[2] = scratchFirstCartesian.z;
result[3] = 0;
result[4] = scratchSecondCartesian.x;
result[5] = scratchSecondCartesian.y;
result[6] = scratchSecondCartesian.z;
result[7] = 0;
result[8] = scratchThirdCartesian.x;
result[9] = scratchThirdCartesian.y;
result[10] = scratchThirdCartesian.z;
result[11] = 0;
result[12] = origin.x;
result[13] = origin.y;
result[14] = origin.z;
result[15] = 1;
return result;
};
localFrameToFixedFrameCache[hashAxis] = resultat;
}
return resultat;
};
Transforms.eastNorthUpToFixedFrame = Transforms.localFrameToFixedFrameGenerator(
"east",
"north"
);
Transforms.northEastDownToFixedFrame = Transforms.localFrameToFixedFrameGenerator("north", "east");
Transforms.northUpEastToFixedFrame = Transforms.localFrameToFixedFrameGenerator(
"north",
"up"
);
Transforms.northWestUpToFixedFrame = Transforms.localFrameToFixedFrameGenerator(
"north",
"west"
);
var scratchHPRQuaternion2 = new Quaternion_default();
var scratchScale = new Cartesian3_default(1, 1, 1);
var scratchHPRMatrix4 = new Matrix4_default();
Transforms.headingPitchRollToFixedFrame = function(origin, headingPitchRoll, ellipsoid, fixedFrameTransform, result) {
Check_default.typeOf.object("HeadingPitchRoll", headingPitchRoll);
fixedFrameTransform = fixedFrameTransform ?? Transforms.eastNorthUpToFixedFrame;
const hprQuaternion = Quaternion_default.fromHeadingPitchRoll(
headingPitchRoll,
scratchHPRQuaternion2
);
const hprMatrix = Matrix4_default.fromTranslationQuaternionRotationScale(
Cartesian3_default.ZERO,
hprQuaternion,
scratchScale,
scratchHPRMatrix4
);
result = fixedFrameTransform(origin, ellipsoid, result);
return Matrix4_default.multiply(result, hprMatrix, result);
};
var scratchENUMatrix4 = new Matrix4_default();
var scratchHPRMatrix3 = new Matrix3_default();
Transforms.headingPitchRollQuaternion = function(origin, headingPitchRoll, ellipsoid, fixedFrameTransform, result) {
Check_default.typeOf.object("HeadingPitchRoll", headingPitchRoll);
const transform3 = Transforms.headingPitchRollToFixedFrame(
origin,
headingPitchRoll,
ellipsoid,
fixedFrameTransform,
scratchENUMatrix4
);
const rotation = Matrix4_default.getMatrix3(transform3, scratchHPRMatrix3);
return Quaternion_default.fromRotationMatrix(rotation, result);
};
var noScale = new Cartesian3_default(1, 1, 1);
var hprCenterScratch = new Cartesian3_default();
var ffScratch = new Matrix4_default();
var hprTransformScratch = new Matrix4_default();
var hprRotationScratch = new Matrix3_default();
var hprQuaternionScratch = new Quaternion_default();
Transforms.fixedFrameToHeadingPitchRoll = function(transform3, ellipsoid, fixedFrameTransform, result) {
Check_default.defined("transform", transform3);
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
fixedFrameTransform = fixedFrameTransform ?? Transforms.eastNorthUpToFixedFrame;
if (!defined_default(result)) {
result = new HeadingPitchRoll_default();
}
const center = Matrix4_default.getTranslation(transform3, hprCenterScratch);
if (Cartesian3_default.equals(center, Cartesian3_default.ZERO)) {
result.heading = 0;
result.pitch = 0;
result.roll = 0;
return result;
}
let toFixedFrame = Matrix4_default.inverseTransformation(
fixedFrameTransform(center, ellipsoid, ffScratch),
ffScratch
);
let transformCopy = Matrix4_default.setScale(transform3, noScale, hprTransformScratch);
transformCopy = Matrix4_default.setTranslation(
transformCopy,
Cartesian3_default.ZERO,
transformCopy
);
toFixedFrame = Matrix4_default.multiply(toFixedFrame, transformCopy, toFixedFrame);
let quaternionRotation = Quaternion_default.fromRotationMatrix(
Matrix4_default.getMatrix3(toFixedFrame, hprRotationScratch),
hprQuaternionScratch
);
quaternionRotation = Quaternion_default.normalize(
quaternionRotation,
quaternionRotation
);
return HeadingPitchRoll_default.fromQuaternion(quaternionRotation, result);
};
var gmstConstant0 = 6 * 3600 + 41 * 60 + 50.54841;
var gmstConstant1 = 8640184812866e-6;
var gmstConstant2 = 0.093104;
var gmstConstant3 = -62e-7;
var rateCoef = 11772758384668e-32;
var wgs84WRPrecessing = 72921158553e-15;
var twoPiOverSecondsInDay = Math_default.TWO_PI / 86400;
var dateInUtc = new JulianDate_default();
Transforms.computeIcrfToCentralBodyFixedMatrix = function(date, result) {
let transformMatrix2 = Transforms.computeIcrfToFixedMatrix(date, result);
if (!defined_default(transformMatrix2)) {
transformMatrix2 = Transforms.computeTemeToPseudoFixedMatrix(date, result);
}
return transformMatrix2;
};
Transforms.computeTemeToPseudoFixedMatrix = function(date, result) {
if (!defined_default(date)) {
throw new DeveloperError_default("date is required.");
}
dateInUtc = JulianDate_default.addSeconds(
date,
-JulianDate_default.computeTaiMinusUtc(date),
dateInUtc
);
const utcDayNumber = dateInUtc.dayNumber;
const utcSecondsIntoDay = dateInUtc.secondsOfDay;
let t;
const diffDays = utcDayNumber - 2451545;
if (utcSecondsIntoDay >= 43200) {
t = (diffDays + 0.5) / TimeConstants_default.DAYS_PER_JULIAN_CENTURY;
} else {
t = (diffDays - 0.5) / TimeConstants_default.DAYS_PER_JULIAN_CENTURY;
}
const gmst0 = gmstConstant0 + t * (gmstConstant1 + t * (gmstConstant2 + t * gmstConstant3));
const angle = gmst0 * twoPiOverSecondsInDay % Math_default.TWO_PI;
const ratio = wgs84WRPrecessing + rateCoef * (utcDayNumber - 24515455e-1);
const secondsSinceMidnight = (utcSecondsIntoDay + TimeConstants_default.SECONDS_PER_DAY * 0.5) % TimeConstants_default.SECONDS_PER_DAY;
const gha = angle + ratio * secondsSinceMidnight;
const cosGha = Math.cos(gha);
const sinGha = Math.sin(gha);
if (!defined_default(result)) {
return new Matrix3_default(
cosGha,
sinGha,
0,
-sinGha,
cosGha,
0,
0,
0,
1
);
}
result[0] = cosGha;
result[1] = -sinGha;
result[2] = 0;
result[3] = sinGha;
result[4] = cosGha;
result[5] = 0;
result[6] = 0;
result[7] = 0;
result[8] = 1;
return result;
};
Transforms.iau2006XysData = new Iau2006XysData_default();
Transforms.earthOrientationParameters = EarthOrientationParameters_default.NONE;
var ttMinusTai = 32.184;
var j2000ttDays = 2451545;
Transforms.preloadIcrfFixed = function(timeInterval) {
const startDayTT = timeInterval.start.dayNumber;
const startSecondTT = timeInterval.start.secondsOfDay + ttMinusTai;
const stopDayTT = timeInterval.stop.dayNumber;
const stopSecondTT = timeInterval.stop.secondsOfDay + ttMinusTai;
return Transforms.iau2006XysData.preload(
startDayTT,
startSecondTT,
stopDayTT,
stopSecondTT
);
};
Transforms.computeIcrfToFixedMatrix = function(date, result) {
if (!defined_default(date)) {
throw new DeveloperError_default("date is required.");
}
if (!defined_default(result)) {
result = new Matrix3_default();
}
const fixedToIcrfMtx = Transforms.computeFixedToIcrfMatrix(date, result);
if (!defined_default(fixedToIcrfMtx)) {
return void 0;
}
return Matrix3_default.transpose(fixedToIcrfMtx, result);
};
var TdtMinusTai = 32.184;
var J2000d = 2451545;
var scratchHpr = new HeadingPitchRoll_default();
var scratchRotationMatrix = new Matrix3_default();
var dateScratch = new JulianDate_default();
Transforms.computeMoonFixedToIcrfMatrix = function(date, result) {
if (!defined_default(date)) {
throw new DeveloperError_default("date is required.");
}
if (!defined_default(result)) {
result = new Matrix3_default();
}
const secondsTT = JulianDate_default.addSeconds(date, TdtMinusTai, dateScratch);
const d = JulianDate_default.totalDays(secondsTT) - J2000d;
const e1 = Math_default.toRadians(12.112) - Math_default.toRadians(0.052992) * d;
const e2 = Math_default.toRadians(24.224) - Math_default.toRadians(0.105984) * d;
const e3 = Math_default.toRadians(227.645) + Math_default.toRadians(13.012) * d;
const e4 = Math_default.toRadians(261.105) + Math_default.toRadians(13.340716) * d;
const e5 = Math_default.toRadians(358) + Math_default.toRadians(0.9856) * d;
scratchHpr.pitch = Math_default.toRadians(270 - 90) - Math_default.toRadians(3.878) * Math.sin(e1) - Math_default.toRadians(0.12) * Math.sin(e2) + Math_default.toRadians(0.07) * Math.sin(e3) - Math_default.toRadians(0.017) * Math.sin(e4);
scratchHpr.roll = Math_default.toRadians(66.53 - 90) + Math_default.toRadians(1.543) * Math.cos(e1) + Math_default.toRadians(0.24) * Math.cos(e2) - Math_default.toRadians(0.028) * Math.cos(e3) + Math_default.toRadians(7e-3) * Math.cos(e4);
scratchHpr.heading = Math_default.toRadians(244.375 - 90) + Math_default.toRadians(13.17635831) * d + Math_default.toRadians(3.558) * Math.sin(e1) + Math_default.toRadians(0.121) * Math.sin(e2) - Math_default.toRadians(0.064) * Math.sin(e3) + Math_default.toRadians(0.016) * Math.sin(e4) + Math_default.toRadians(0.025) * Math.sin(e5);
return Matrix3_default.fromHeadingPitchRoll(scratchHpr, scratchRotationMatrix);
};
Transforms.computeIcrfToMoonFixedMatrix = function(date, result) {
if (!defined_default(date)) {
throw new DeveloperError_default("date is required.");
}
if (!defined_default(result)) {
result = new Matrix3_default();
}
const fixedToIcrfMtx = Transforms.computeMoonFixedToIcrfMatrix(date, result);
if (!defined_default(fixedToIcrfMtx)) {
return void 0;
}
return Matrix3_default.transpose(fixedToIcrfMtx, result);
};
var xysScratch = new Iau2006XysSample_default(0, 0, 0);
var eopScratch = new EarthOrientationParametersSample_default(
0,
0,
0,
0,
0,
0
);
var rotation1Scratch = new Matrix3_default();
var rotation2Scratch = new Matrix3_default();
Transforms.computeFixedToIcrfMatrix = function(date, result) {
if (!defined_default(date)) {
throw new DeveloperError_default("date is required.");
}
if (!defined_default(result)) {
result = new Matrix3_default();
}
const eop = Transforms.earthOrientationParameters.compute(date, eopScratch);
if (!defined_default(eop)) {
return void 0;
}
const dayTT = date.dayNumber;
const secondTT = date.secondsOfDay + ttMinusTai;
const xys = Transforms.iau2006XysData.computeXysRadians(
dayTT,
secondTT,
xysScratch
);
if (!defined_default(xys)) {
return void 0;
}
const x = xys.x + eop.xPoleOffset;
const y = xys.y + eop.yPoleOffset;
const a3 = 1 / (1 + Math.sqrt(1 - x * x - y * y));
const rotation1 = rotation1Scratch;
rotation1[0] = 1 - a3 * x * x;
rotation1[3] = -a3 * x * y;
rotation1[6] = x;
rotation1[1] = -a3 * x * y;
rotation1[4] = 1 - a3 * y * y;
rotation1[7] = y;
rotation1[2] = -x;
rotation1[5] = -y;
rotation1[8] = 1 - a3 * (x * x + y * y);
const rotation2 = Matrix3_default.fromRotationZ(-xys.s, rotation2Scratch);
const matrixQ = Matrix3_default.multiply(rotation1, rotation2, rotation1Scratch);
const dateUt1day = date.dayNumber;
const dateUt1sec = date.secondsOfDay - JulianDate_default.computeTaiMinusUtc(date) + eop.ut1MinusUtc;
const daysSinceJ2000 = dateUt1day - 2451545;
const fractionOfDay = dateUt1sec / TimeConstants_default.SECONDS_PER_DAY;
let era = 0.779057273264 + fractionOfDay + 0.00273781191135448 * (daysSinceJ2000 + fractionOfDay);
era = era % 1 * Math_default.TWO_PI;
const earthRotation = Matrix3_default.fromRotationZ(era, rotation2Scratch);
const pfToIcrf = Matrix3_default.multiply(matrixQ, earthRotation, rotation1Scratch);
const cosxp = Math.cos(eop.xPoleWander);
const cosyp = Math.cos(eop.yPoleWander);
const sinxp = Math.sin(eop.xPoleWander);
const sinyp = Math.sin(eop.yPoleWander);
let ttt = dayTT - j2000ttDays + secondTT / TimeConstants_default.SECONDS_PER_DAY;
ttt /= 36525;
const sp = -47e-6 * ttt * Math_default.RADIANS_PER_DEGREE / 3600;
const cossp = Math.cos(sp);
const sinsp = Math.sin(sp);
const fToPfMtx = rotation2Scratch;
fToPfMtx[0] = cosxp * cossp;
fToPfMtx[1] = cosxp * sinsp;
fToPfMtx[2] = sinxp;
fToPfMtx[3] = -cosyp * sinsp + sinyp * sinxp * cossp;
fToPfMtx[4] = cosyp * cossp + sinyp * sinxp * sinsp;
fToPfMtx[5] = -sinyp * cosxp;
fToPfMtx[6] = -sinyp * sinsp - cosyp * sinxp * cossp;
fToPfMtx[7] = sinyp * cossp - cosyp * sinxp * sinsp;
fToPfMtx[8] = cosyp * cosxp;
return Matrix3_default.multiply(pfToIcrf, fToPfMtx, result);
};
var pointToWindowCoordinatesTemp = new Cartesian4_default();
Transforms.pointToWindowCoordinates = function(modelViewProjectionMatrix, viewportTransformation, point, result) {
result = Transforms.pointToGLWindowCoordinates(
modelViewProjectionMatrix,
viewportTransformation,
point,
result
);
result.y = 2 * viewportTransformation[5] - result.y;
return result;
};
Transforms.pointToGLWindowCoordinates = function(modelViewProjectionMatrix, viewportTransformation, point, result) {
if (!defined_default(modelViewProjectionMatrix)) {
throw new DeveloperError_default("modelViewProjectionMatrix is required.");
}
if (!defined_default(viewportTransformation)) {
throw new DeveloperError_default("viewportTransformation is required.");
}
if (!defined_default(point)) {
throw new DeveloperError_default("point is required.");
}
if (!defined_default(result)) {
result = new Cartesian2_default();
}
const tmp2 = pointToWindowCoordinatesTemp;
Matrix4_default.multiplyByVector(
modelViewProjectionMatrix,
Cartesian4_default.fromElements(point.x, point.y, point.z, 1, tmp2),
tmp2
);
Cartesian4_default.multiplyByScalar(tmp2, 1 / tmp2.w, tmp2);
Matrix4_default.multiplyByVector(viewportTransformation, tmp2, tmp2);
return Cartesian2_default.fromCartesian4(tmp2, result);
};
var normalScratch = new Cartesian3_default();
var rightScratch = new Cartesian3_default();
var upScratch = new Cartesian3_default();
Transforms.rotationMatrixFromPositionVelocity = function(position, velocity, ellipsoid, result) {
if (!defined_default(position)) {
throw new DeveloperError_default("position is required.");
}
if (!defined_default(velocity)) {
throw new DeveloperError_default("velocity is required.");
}
const normal2 = (ellipsoid ?? Ellipsoid_default.default).geodeticSurfaceNormal(
position,
normalScratch
);
let right = Cartesian3_default.cross(velocity, normal2, rightScratch);
if (Cartesian3_default.equalsEpsilon(right, Cartesian3_default.ZERO, Math_default.EPSILON6)) {
right = Cartesian3_default.clone(Cartesian3_default.UNIT_X, right);
}
const up = Cartesian3_default.cross(right, velocity, upScratch);
Cartesian3_default.normalize(up, up);
Cartesian3_default.cross(velocity, up, right);
Cartesian3_default.negate(right, right);
Cartesian3_default.normalize(right, right);
if (!defined_default(result)) {
result = new Matrix3_default();
}
result[0] = velocity.x;
result[1] = velocity.y;
result[2] = velocity.z;
result[3] = right.x;
result[4] = right.y;
result[5] = right.z;
result[6] = up.x;
result[7] = up.y;
result[8] = up.z;
return result;
};
var swizzleMatrix = new Matrix4_default(
0,
0,
1,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
1
);
var scratchCartographic = new Cartographic_default();
var scratchCartesian3Projection = new Cartesian3_default();
var scratchCenter = new Cartesian3_default();
var scratchRotation = new Matrix3_default();
var scratchFromENU = new Matrix4_default();
var scratchToENU = new Matrix4_default();
Transforms.basisTo2D = function(projection, matrix, result) {
if (!defined_default(projection)) {
throw new DeveloperError_default("projection is required.");
}
if (!defined_default(matrix)) {
throw new DeveloperError_default("matrix is required.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
const rtcCenter = Matrix4_default.getTranslation(matrix, scratchCenter);
const ellipsoid = projection.ellipsoid;
let projectedPosition2;
if (Cartesian3_default.equals(rtcCenter, Cartesian3_default.ZERO)) {
projectedPosition2 = Cartesian3_default.clone(
Cartesian3_default.ZERO,
scratchCartesian3Projection
);
} else {
const cartographic2 = ellipsoid.cartesianToCartographic(
rtcCenter,
scratchCartographic
);
projectedPosition2 = projection.project(
cartographic2,
scratchCartesian3Projection
);
Cartesian3_default.fromElements(
projectedPosition2.z,
projectedPosition2.x,
projectedPosition2.y,
projectedPosition2
);
}
const fromENU = Transforms.eastNorthUpToFixedFrame(
rtcCenter,
ellipsoid,
scratchFromENU
);
const toENU = Matrix4_default.inverseTransformation(fromENU, scratchToENU);
const rotation = Matrix4_default.getMatrix3(matrix, scratchRotation);
const local = Matrix4_default.multiplyByMatrix3(toENU, rotation, result);
Matrix4_default.multiply(swizzleMatrix, local, result);
Matrix4_default.setTranslation(result, projectedPosition2, result);
return result;
};
Transforms.ellipsoidTo2DModelMatrix = function(projection, center, result) {
if (!defined_default(projection)) {
throw new DeveloperError_default("projection is required.");
}
if (!defined_default(center)) {
throw new DeveloperError_default("center is required.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
const ellipsoid = projection.ellipsoid;
const fromENU = Transforms.eastNorthUpToFixedFrame(
center,
ellipsoid,
scratchFromENU
);
const toENU = Matrix4_default.inverseTransformation(fromENU, scratchToENU);
const cartographic2 = ellipsoid.cartesianToCartographic(
center,
scratchCartographic
);
const projectedPosition2 = projection.project(
cartographic2,
scratchCartesian3Projection
);
Cartesian3_default.fromElements(
projectedPosition2.z,
projectedPosition2.x,
projectedPosition2.y,
projectedPosition2
);
const translation3 = Matrix4_default.fromTranslation(
projectedPosition2,
scratchFromENU
);
Matrix4_default.multiply(swizzleMatrix, toENU, result);
Matrix4_default.multiply(translation3, result, result);
return result;
};
var Transforms_default = Transforms;
// packages/engine/Source/Core/Rectangle.js
function Rectangle(west, south, east, north) {
this.west = west ?? 0;
this.south = south ?? 0;
this.east = east ?? 0;
this.north = north ?? 0;
}
Object.defineProperties(Rectangle.prototype, {
/**
* Gets the width of the rectangle in radians.
* @memberof Rectangle.prototype
* @type {number}
* @readonly
*/
width: {
get: function() {
return Rectangle.computeWidth(this);
}
},
/**
* Gets the height of the rectangle in radians.
* @memberof Rectangle.prototype
* @type {number}
* @readonly
*/
height: {
get: function() {
return Rectangle.computeHeight(this);
}
}
});
Rectangle.packedLength = 4;
Rectangle.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
array[startingIndex++] = value.west;
array[startingIndex++] = value.south;
array[startingIndex++] = value.east;
array[startingIndex] = value.north;
return array;
};
Rectangle.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new Rectangle();
}
result.west = array[startingIndex++];
result.south = array[startingIndex++];
result.east = array[startingIndex++];
result.north = array[startingIndex];
return result;
};
Rectangle.computeWidth = function(rectangle) {
Check_default.typeOf.object("rectangle", rectangle);
let east = rectangle.east;
const west = rectangle.west;
if (east < west) {
east += Math_default.TWO_PI;
}
return east - west;
};
Rectangle.computeHeight = function(rectangle) {
Check_default.typeOf.object("rectangle", rectangle);
return rectangle.north - rectangle.south;
};
Rectangle.fromDegrees = function(west, south, east, north, result) {
west = Math_default.toRadians(west ?? 0);
south = Math_default.toRadians(south ?? 0);
east = Math_default.toRadians(east ?? 0);
north = Math_default.toRadians(north ?? 0);
if (!defined_default(result)) {
return new Rectangle(west, south, east, north);
}
result.west = west;
result.south = south;
result.east = east;
result.north = north;
return result;
};
Rectangle.fromRadians = function(west, south, east, north, result) {
if (!defined_default(result)) {
return new Rectangle(west, south, east, north);
}
result.west = west ?? 0;
result.south = south ?? 0;
result.east = east ?? 0;
result.north = north ?? 0;
return result;
};
Rectangle.fromCartographicArray = function(cartographics, result) {
Check_default.defined("cartographics", cartographics);
let west = Number.MAX_VALUE;
let east = -Number.MAX_VALUE;
let westOverIDL = Number.MAX_VALUE;
let eastOverIDL = -Number.MAX_VALUE;
let south = Number.MAX_VALUE;
let north = -Number.MAX_VALUE;
for (let i = 0, len = cartographics.length; i < len; i++) {
const position = cartographics[i];
west = Math.min(west, position.longitude);
east = Math.max(east, position.longitude);
south = Math.min(south, position.latitude);
north = Math.max(north, position.latitude);
const lonAdjusted = position.longitude >= 0 ? position.longitude : position.longitude + Math_default.TWO_PI;
westOverIDL = Math.min(westOverIDL, lonAdjusted);
eastOverIDL = Math.max(eastOverIDL, lonAdjusted);
}
if (east - west > eastOverIDL - westOverIDL) {
west = westOverIDL;
east = eastOverIDL;
if (east > Math_default.PI) {
east = east - Math_default.TWO_PI;
}
if (west > Math_default.PI) {
west = west - Math_default.TWO_PI;
}
}
if (!defined_default(result)) {
return new Rectangle(west, south, east, north);
}
result.west = west;
result.south = south;
result.east = east;
result.north = north;
return result;
};
Rectangle.fromCartesianArray = function(cartesians, ellipsoid, result) {
Check_default.defined("cartesians", cartesians);
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
let west = Number.MAX_VALUE;
let east = -Number.MAX_VALUE;
let westOverIDL = Number.MAX_VALUE;
let eastOverIDL = -Number.MAX_VALUE;
let south = Number.MAX_VALUE;
let north = -Number.MAX_VALUE;
for (let i = 0, len = cartesians.length; i < len; i++) {
const position = ellipsoid.cartesianToCartographic(cartesians[i]);
west = Math.min(west, position.longitude);
east = Math.max(east, position.longitude);
south = Math.min(south, position.latitude);
north = Math.max(north, position.latitude);
const lonAdjusted = position.longitude >= 0 ? position.longitude : position.longitude + Math_default.TWO_PI;
westOverIDL = Math.min(westOverIDL, lonAdjusted);
eastOverIDL = Math.max(eastOverIDL, lonAdjusted);
}
if (east - west > eastOverIDL - westOverIDL) {
west = westOverIDL;
east = eastOverIDL;
if (east > Math_default.PI) {
east = east - Math_default.TWO_PI;
}
if (west > Math_default.PI) {
west = west - Math_default.TWO_PI;
}
}
if (!defined_default(result)) {
return new Rectangle(west, south, east, north);
}
result.west = west;
result.south = south;
result.east = east;
result.north = north;
return result;
};
var fromBoundingSphereMatrixScratch = new Cartesian3_default();
var fromBoundingSphereEastScratch = new Cartesian3_default();
var fromBoundingSphereNorthScratch = new Cartesian3_default();
var fromBoundingSphereWestScratch = new Cartesian3_default();
var fromBoundingSphereSouthScratch = new Cartesian3_default();
var fromBoundingSpherePositionsScratch = new Array(5);
for (let n = 0; n < fromBoundingSpherePositionsScratch.length; ++n) {
fromBoundingSpherePositionsScratch[n] = new Cartesian3_default();
}
Rectangle.fromBoundingSphere = function(boundingSphere, ellipsoid, result) {
Check_default.typeOf.object("boundingSphere", boundingSphere);
const center = boundingSphere.center;
const radius = boundingSphere.radius;
if (!defined_default(ellipsoid)) {
ellipsoid = Ellipsoid_default.default;
}
if (!defined_default(result)) {
result = new Rectangle();
}
if (Cartesian3_default.equals(center, Cartesian3_default.ZERO)) {
Rectangle.clone(Rectangle.MAX_VALUE, result);
return result;
}
const fromENU = Transforms_default.eastNorthUpToFixedFrame(
center,
ellipsoid,
fromBoundingSphereMatrixScratch
);
const east = Matrix4_default.multiplyByPointAsVector(
fromENU,
Cartesian3_default.UNIT_X,
fromBoundingSphereEastScratch
);
Cartesian3_default.normalize(east, east);
const north = Matrix4_default.multiplyByPointAsVector(
fromENU,
Cartesian3_default.UNIT_Y,
fromBoundingSphereNorthScratch
);
Cartesian3_default.normalize(north, north);
Cartesian3_default.multiplyByScalar(north, radius, north);
Cartesian3_default.multiplyByScalar(east, radius, east);
const south = Cartesian3_default.negate(north, fromBoundingSphereSouthScratch);
const west = Cartesian3_default.negate(east, fromBoundingSphereWestScratch);
const positions = fromBoundingSpherePositionsScratch;
let corner = positions[0];
Cartesian3_default.add(center, north, corner);
corner = positions[1];
Cartesian3_default.add(center, west, corner);
corner = positions[2];
Cartesian3_default.add(center, south, corner);
corner = positions[3];
Cartesian3_default.add(center, east, corner);
positions[4] = center;
return Rectangle.fromCartesianArray(positions, ellipsoid, result);
};
Rectangle.clone = function(rectangle, result) {
if (!defined_default(rectangle)) {
return void 0;
}
if (!defined_default(result)) {
return new Rectangle(
rectangle.west,
rectangle.south,
rectangle.east,
rectangle.north
);
}
result.west = rectangle.west;
result.south = rectangle.south;
result.east = rectangle.east;
result.north = rectangle.north;
return result;
};
Rectangle.equalsEpsilon = function(left, right, absoluteEpsilon) {
absoluteEpsilon = absoluteEpsilon ?? 0;
return left === right || defined_default(left) && defined_default(right) && Math.abs(left.west - right.west) <= absoluteEpsilon && Math.abs(left.south - right.south) <= absoluteEpsilon && Math.abs(left.east - right.east) <= absoluteEpsilon && Math.abs(left.north - right.north) <= absoluteEpsilon;
};
Rectangle.prototype.clone = function(result) {
return Rectangle.clone(this, result);
};
Rectangle.prototype.equals = function(other) {
return Rectangle.equals(this, other);
};
Rectangle.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left.west === right.west && left.south === right.south && left.east === right.east && left.north === right.north;
};
Rectangle.prototype.equalsEpsilon = function(other, epsilon) {
return Rectangle.equalsEpsilon(this, other, epsilon);
};
Rectangle._validate = function(rectangle) {
Check_default.typeOf.object("rectangle", rectangle);
const north = rectangle.north;
Check_default.typeOf.number.greaterThanOrEquals(
"north",
north,
-Math_default.PI_OVER_TWO
);
Check_default.typeOf.number.lessThanOrEquals("north", north, Math_default.PI_OVER_TWO);
const south = rectangle.south;
Check_default.typeOf.number.greaterThanOrEquals(
"south",
south,
-Math_default.PI_OVER_TWO
);
Check_default.typeOf.number.lessThanOrEquals("south", south, Math_default.PI_OVER_TWO);
const west = rectangle.west;
Check_default.typeOf.number.greaterThanOrEquals("west", west, -Math.PI);
Check_default.typeOf.number.lessThanOrEquals("west", west, Math.PI);
const east = rectangle.east;
Check_default.typeOf.number.greaterThanOrEquals("east", east, -Math.PI);
Check_default.typeOf.number.lessThanOrEquals("east", east, Math.PI);
};
Rectangle.southwest = function(rectangle, result) {
Check_default.typeOf.object("rectangle", rectangle);
if (!defined_default(result)) {
return new Cartographic_default(rectangle.west, rectangle.south);
}
result.longitude = rectangle.west;
result.latitude = rectangle.south;
result.height = 0;
return result;
};
Rectangle.northwest = function(rectangle, result) {
Check_default.typeOf.object("rectangle", rectangle);
if (!defined_default(result)) {
return new Cartographic_default(rectangle.west, rectangle.north);
}
result.longitude = rectangle.west;
result.latitude = rectangle.north;
result.height = 0;
return result;
};
Rectangle.northeast = function(rectangle, result) {
Check_default.typeOf.object("rectangle", rectangle);
if (!defined_default(result)) {
return new Cartographic_default(rectangle.east, rectangle.north);
}
result.longitude = rectangle.east;
result.latitude = rectangle.north;
result.height = 0;
return result;
};
Rectangle.southeast = function(rectangle, result) {
Check_default.typeOf.object("rectangle", rectangle);
if (!defined_default(result)) {
return new Cartographic_default(rectangle.east, rectangle.south);
}
result.longitude = rectangle.east;
result.latitude = rectangle.south;
result.height = 0;
return result;
};
Rectangle.center = function(rectangle, result) {
Check_default.typeOf.object("rectangle", rectangle);
let east = rectangle.east;
const west = rectangle.west;
if (east < west) {
east += Math_default.TWO_PI;
}
const longitude = Math_default.negativePiToPi((west + east) * 0.5);
const latitude = (rectangle.south + rectangle.north) * 0.5;
if (!defined_default(result)) {
return new Cartographic_default(longitude, latitude);
}
result.longitude = longitude;
result.latitude = latitude;
result.height = 0;
return result;
};
Rectangle.intersection = function(rectangle, otherRectangle, result) {
Check_default.typeOf.object("rectangle", rectangle);
Check_default.typeOf.object("otherRectangle", otherRectangle);
let rectangleEast = rectangle.east;
let rectangleWest = rectangle.west;
let otherRectangleEast = otherRectangle.east;
let otherRectangleWest = otherRectangle.west;
if (rectangleEast < rectangleWest && otherRectangleEast > 0) {
rectangleEast += Math_default.TWO_PI;
} else if (otherRectangleEast < otherRectangleWest && rectangleEast > 0) {
otherRectangleEast += Math_default.TWO_PI;
}
if (rectangleEast < rectangleWest && otherRectangleWest < 0) {
otherRectangleWest += Math_default.TWO_PI;
} else if (otherRectangleEast < otherRectangleWest && rectangleWest < 0) {
rectangleWest += Math_default.TWO_PI;
}
const west = Math_default.negativePiToPi(
Math.max(rectangleWest, otherRectangleWest)
);
const east = Math_default.negativePiToPi(
Math.min(rectangleEast, otherRectangleEast)
);
if ((rectangle.west < rectangle.east || otherRectangle.west < otherRectangle.east) && east <= west) {
return void 0;
}
const south = Math.max(rectangle.south, otherRectangle.south);
const north = Math.min(rectangle.north, otherRectangle.north);
if (south >= north) {
return void 0;
}
if (!defined_default(result)) {
return new Rectangle(west, south, east, north);
}
result.west = west;
result.south = south;
result.east = east;
result.north = north;
return result;
};
Rectangle.simpleIntersection = function(rectangle, otherRectangle, result) {
Check_default.typeOf.object("rectangle", rectangle);
Check_default.typeOf.object("otherRectangle", otherRectangle);
const west = Math.max(rectangle.west, otherRectangle.west);
const south = Math.max(rectangle.south, otherRectangle.south);
const east = Math.min(rectangle.east, otherRectangle.east);
const north = Math.min(rectangle.north, otherRectangle.north);
if (south >= north || west >= east) {
return void 0;
}
if (!defined_default(result)) {
return new Rectangle(west, south, east, north);
}
result.west = west;
result.south = south;
result.east = east;
result.north = north;
return result;
};
Rectangle.union = function(rectangle, otherRectangle, result) {
Check_default.typeOf.object("rectangle", rectangle);
Check_default.typeOf.object("otherRectangle", otherRectangle);
if (!defined_default(result)) {
result = new Rectangle();
}
let rectangleEast = rectangle.east;
let rectangleWest = rectangle.west;
let otherRectangleEast = otherRectangle.east;
let otherRectangleWest = otherRectangle.west;
if (rectangleEast < rectangleWest && otherRectangleEast > 0) {
rectangleEast += Math_default.TWO_PI;
} else if (otherRectangleEast < otherRectangleWest && rectangleEast > 0) {
otherRectangleEast += Math_default.TWO_PI;
}
if (rectangleEast < rectangleWest && otherRectangleWest < 0) {
otherRectangleWest += Math_default.TWO_PI;
} else if (otherRectangleEast < otherRectangleWest && rectangleWest < 0) {
rectangleWest += Math_default.TWO_PI;
}
const west = Math_default.negativePiToPi(
Math.min(rectangleWest, otherRectangleWest)
);
const east = Math_default.negativePiToPi(
Math.max(rectangleEast, otherRectangleEast)
);
result.west = west;
result.south = Math.min(rectangle.south, otherRectangle.south);
result.east = east;
result.north = Math.max(rectangle.north, otherRectangle.north);
return result;
};
Rectangle.expand = function(rectangle, cartographic2, result) {
Check_default.typeOf.object("rectangle", rectangle);
Check_default.typeOf.object("cartographic", cartographic2);
if (!defined_default(result)) {
result = new Rectangle();
}
result.west = Math.min(rectangle.west, cartographic2.longitude);
result.south = Math.min(rectangle.south, cartographic2.latitude);
result.east = Math.max(rectangle.east, cartographic2.longitude);
result.north = Math.max(rectangle.north, cartographic2.latitude);
return result;
};
Rectangle.contains = function(rectangle, cartographic2) {
Check_default.typeOf.object("rectangle", rectangle);
Check_default.typeOf.object("cartographic", cartographic2);
let longitude = cartographic2.longitude;
const latitude = cartographic2.latitude;
const west = rectangle.west;
let east = rectangle.east;
if (east < west) {
east += Math_default.TWO_PI;
if (longitude < 0) {
longitude += Math_default.TWO_PI;
}
}
return (longitude > west || Math_default.equalsEpsilon(longitude, west, Math_default.EPSILON14)) && (longitude < east || Math_default.equalsEpsilon(longitude, east, Math_default.EPSILON14)) && latitude >= rectangle.south && latitude <= rectangle.north;
};
var subsampleLlaScratch = new Cartographic_default();
Rectangle.subsample = function(rectangle, ellipsoid, surfaceHeight, result) {
Check_default.typeOf.object("rectangle", rectangle);
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
surfaceHeight = surfaceHeight ?? 0;
if (!defined_default(result)) {
result = [];
}
let length2 = 0;
const north = rectangle.north;
const south = rectangle.south;
const east = rectangle.east;
const west = rectangle.west;
const lla = subsampleLlaScratch;
lla.height = surfaceHeight;
lla.longitude = west;
lla.latitude = north;
result[length2] = ellipsoid.cartographicToCartesian(lla, result[length2]);
length2++;
lla.longitude = east;
result[length2] = ellipsoid.cartographicToCartesian(lla, result[length2]);
length2++;
lla.latitude = south;
result[length2] = ellipsoid.cartographicToCartesian(lla, result[length2]);
length2++;
lla.longitude = west;
result[length2] = ellipsoid.cartographicToCartesian(lla, result[length2]);
length2++;
if (north < 0) {
lla.latitude = north;
} else if (south > 0) {
lla.latitude = south;
} else {
lla.latitude = 0;
}
for (let i = 1; i < 8; ++i) {
lla.longitude = -Math.PI + i * Math_default.PI_OVER_TWO;
if (Rectangle.contains(rectangle, lla)) {
result[length2] = ellipsoid.cartographicToCartesian(lla, result[length2]);
length2++;
}
}
if (lla.latitude === 0) {
lla.longitude = west;
result[length2] = ellipsoid.cartographicToCartesian(lla, result[length2]);
length2++;
lla.longitude = east;
result[length2] = ellipsoid.cartographicToCartesian(lla, result[length2]);
length2++;
}
result.length = length2;
return result;
};
Rectangle.subsection = function(rectangle, westLerp, southLerp, eastLerp, northLerp, result) {
Check_default.typeOf.object("rectangle", rectangle);
Check_default.typeOf.number.greaterThanOrEquals("westLerp", westLerp, 0);
Check_default.typeOf.number.lessThanOrEquals("westLerp", westLerp, 1);
Check_default.typeOf.number.greaterThanOrEquals("southLerp", southLerp, 0);
Check_default.typeOf.number.lessThanOrEquals("southLerp", southLerp, 1);
Check_default.typeOf.number.greaterThanOrEquals("eastLerp", eastLerp, 0);
Check_default.typeOf.number.lessThanOrEquals("eastLerp", eastLerp, 1);
Check_default.typeOf.number.greaterThanOrEquals("northLerp", northLerp, 0);
Check_default.typeOf.number.lessThanOrEquals("northLerp", northLerp, 1);
Check_default.typeOf.number.lessThanOrEquals("westLerp", westLerp, eastLerp);
Check_default.typeOf.number.lessThanOrEquals("southLerp", southLerp, northLerp);
if (!defined_default(result)) {
result = new Rectangle();
}
if (rectangle.west <= rectangle.east) {
const width = rectangle.east - rectangle.west;
result.west = rectangle.west + westLerp * width;
result.east = rectangle.west + eastLerp * width;
} else {
const width = Math_default.TWO_PI + rectangle.east - rectangle.west;
result.west = Math_default.negativePiToPi(rectangle.west + westLerp * width);
result.east = Math_default.negativePiToPi(rectangle.west + eastLerp * width);
}
const height = rectangle.north - rectangle.south;
result.south = rectangle.south + southLerp * height;
result.north = rectangle.south + northLerp * height;
if (westLerp === 1) {
result.west = rectangle.east;
}
if (eastLerp === 1) {
result.east = rectangle.east;
}
if (southLerp === 1) {
result.south = rectangle.north;
}
if (northLerp === 1) {
result.north = rectangle.north;
}
return result;
};
Rectangle.MAX_VALUE = Object.freeze(
new Rectangle(
-Math.PI,
-Math_default.PI_OVER_TWO,
Math.PI,
Math_default.PI_OVER_TWO
)
);
var Rectangle_default = Rectangle;
// packages/engine/Source/Core/BoundingRectangle.js
function BoundingRectangle(x, y, width, height) {
this.x = x ?? 0;
this.y = y ?? 0;
this.width = width ?? 0;
this.height = height ?? 0;
}
BoundingRectangle.packedLength = 4;
BoundingRectangle.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
array[startingIndex++] = value.x;
array[startingIndex++] = value.y;
array[startingIndex++] = value.width;
array[startingIndex] = value.height;
return array;
};
BoundingRectangle.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new BoundingRectangle();
}
result.x = array[startingIndex++];
result.y = array[startingIndex++];
result.width = array[startingIndex++];
result.height = array[startingIndex];
return result;
};
BoundingRectangle.fromPoints = function(positions, result) {
if (!defined_default(result)) {
result = new BoundingRectangle();
}
if (!defined_default(positions) || positions.length === 0) {
result.x = 0;
result.y = 0;
result.width = 0;
result.height = 0;
return result;
}
const length2 = positions.length;
let minimumX = positions[0].x;
let minimumY = positions[0].y;
let maximumX = positions[0].x;
let maximumY = positions[0].y;
for (let i = 1; i < length2; i++) {
const p = positions[i];
const x = p.x;
const y = p.y;
minimumX = Math.min(x, minimumX);
maximumX = Math.max(x, maximumX);
minimumY = Math.min(y, minimumY);
maximumY = Math.max(y, maximumY);
}
result.x = minimumX;
result.y = minimumY;
result.width = maximumX - minimumX;
result.height = maximumY - minimumY;
return result;
};
var defaultProjection = new GeographicProjection_default();
var fromRectangleLowerLeft = new Cartographic_default();
var fromRectangleUpperRight = new Cartographic_default();
BoundingRectangle.fromRectangle = function(rectangle, projection, result) {
if (!defined_default(result)) {
result = new BoundingRectangle();
}
if (!defined_default(rectangle)) {
result.x = 0;
result.y = 0;
result.width = 0;
result.height = 0;
return result;
}
defaultProjection._ellipsoid = Ellipsoid_default.default;
projection = projection ?? defaultProjection;
const lowerLeft = projection.project(
Rectangle_default.southwest(rectangle, fromRectangleLowerLeft)
);
const upperRight = projection.project(
Rectangle_default.northeast(rectangle, fromRectangleUpperRight)
);
Cartesian2_default.subtract(upperRight, lowerLeft, upperRight);
result.x = lowerLeft.x;
result.y = lowerLeft.y;
result.width = upperRight.x;
result.height = upperRight.y;
return result;
};
BoundingRectangle.clone = function(rectangle, result) {
if (!defined_default(rectangle)) {
return void 0;
}
if (!defined_default(result)) {
return new BoundingRectangle(
rectangle.x,
rectangle.y,
rectangle.width,
rectangle.height
);
}
result.x = rectangle.x;
result.y = rectangle.y;
result.width = rectangle.width;
result.height = rectangle.height;
return result;
};
BoundingRectangle.union = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
if (!defined_default(result)) {
result = new BoundingRectangle();
}
const lowerLeftX = Math.min(left.x, right.x);
const lowerLeftY = Math.min(left.y, right.y);
const upperRightX = Math.max(left.x + left.width, right.x + right.width);
const upperRightY = Math.max(left.y + left.height, right.y + right.height);
result.x = lowerLeftX;
result.y = lowerLeftY;
result.width = upperRightX - lowerLeftX;
result.height = upperRightY - lowerLeftY;
return result;
};
BoundingRectangle.expand = function(rectangle, point, result) {
Check_default.typeOf.object("rectangle", rectangle);
Check_default.typeOf.object("point", point);
result = BoundingRectangle.clone(rectangle, result);
const width = point.x - result.x;
const height = point.y - result.y;
if (width > result.width) {
result.width = width;
} else if (width < 0) {
result.width -= width;
result.x = point.x;
}
if (height > result.height) {
result.height = height;
} else if (height < 0) {
result.height -= height;
result.y = point.y;
}
return result;
};
BoundingRectangle.intersect = function(left, right) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
const leftX = left.x;
const leftY = left.y;
const rightX = right.x;
const rightY = right.y;
if (!(leftX > rightX + right.width || leftX + left.width < rightX || leftY + left.height < rightY || leftY > rightY + right.height)) {
return Intersect_default.INTERSECTING;
}
return Intersect_default.OUTSIDE;
};
BoundingRectangle.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left.x === right.x && left.y === right.y && left.width === right.width && left.height === right.height;
};
BoundingRectangle.prototype.clone = function(result) {
return BoundingRectangle.clone(this, result);
};
BoundingRectangle.prototype.intersect = function(right) {
return BoundingRectangle.intersect(this, right);
};
BoundingRectangle.prototype.equals = function(right) {
return BoundingRectangle.equals(this, right);
};
var BoundingRectangle_default = BoundingRectangle;
// packages/engine/Source/Core/PrimitiveType.js
var import_InlineWorkers71 = __toESM(require_InlineWorkers(), 1);
var PrimitiveType = {
/**
* Points primitive where each vertex (or index) is a separate point.
*
* @type {number}
* @constant
*/
POINTS: WebGLConstants_default.POINTS,
/**
* Lines primitive where each two vertices (or indices) is a line segment. Line segments are not necessarily connected.
*
* @type {number}
* @constant
*/
LINES: WebGLConstants_default.LINES,
/**
* Line loop primitive where each vertex (or index) after the first connects a line to
* the previous vertex, and the last vertex implicitly connects to the first.
*
* @type {number}
* @constant
*/
LINE_LOOP: WebGLConstants_default.LINE_LOOP,
/**
* Line strip primitive where each vertex (or index) after the first connects a line to the previous vertex.
*
* @type {number}
* @constant
*/
LINE_STRIP: WebGLConstants_default.LINE_STRIP,
/**
* Triangles primitive where each three vertices (or indices) is a triangle. Triangles do not necessarily share edges.
*
* @type {number}
* @constant
*/
TRIANGLES: WebGLConstants_default.TRIANGLES,
/**
* Triangle strip primitive where each vertex (or index) after the first two connect to
* the previous two vertices forming a triangle. For example, this can be used to model a wall.
*
* @type {number}
* @constant
*/
TRIANGLE_STRIP: WebGLConstants_default.TRIANGLE_STRIP,
/**
* Triangle fan primitive where each vertex (or index) after the first two connect to
* the previous vertex and the first vertex forming a triangle. For example, this can be used
* to model a cone or circle.
*
* @type {number}
* @constant
*/
TRIANGLE_FAN: WebGLConstants_default.TRIANGLE_FAN
};
PrimitiveType.isLines = function(primitiveType) {
return primitiveType === PrimitiveType.LINES || primitiveType === PrimitiveType.LINE_LOOP || primitiveType === PrimitiveType.LINE_STRIP;
};
PrimitiveType.isTriangles = function(primitiveType) {
return primitiveType === PrimitiveType.TRIANGLES || primitiveType === PrimitiveType.TRIANGLE_STRIP || primitiveType === PrimitiveType.TRIANGLE_FAN;
};
PrimitiveType.validate = function(primitiveType) {
return primitiveType === PrimitiveType.POINTS || primitiveType === PrimitiveType.LINES || primitiveType === PrimitiveType.LINE_LOOP || primitiveType === PrimitiveType.LINE_STRIP || primitiveType === PrimitiveType.TRIANGLES || primitiveType === PrimitiveType.TRIANGLE_STRIP || primitiveType === PrimitiveType.TRIANGLE_FAN;
};
var PrimitiveType_default = Object.freeze(PrimitiveType);
// packages/engine/Source/Shaders/ViewportQuadVS.js
var import_InlineWorkers72 = __toESM(require_InlineWorkers(), 1);
var ViewportQuadVS_default = "in vec4 position;\nin vec2 textureCoordinates;\n\nout vec2 v_textureCoordinates;\n\nvoid main() \n{\n gl_Position = position;\n v_textureCoordinates = textureCoordinates;\n}\n";
// packages/engine/Source/Renderer/DrawCommand.js
var import_InlineWorkers73 = __toESM(require_InlineWorkers(), 1);
var Flags = {
CULL: 1,
OCCLUDE: 2,
EXECUTE_IN_CLOSEST_FRUSTUM: 4,
DEBUG_SHOW_BOUNDING_VOLUME: 8,
CAST_SHADOWS: 16,
RECEIVE_SHADOWS: 32,
PICK_ONLY: 64,
DEPTH_FOR_TRANSLUCENT_CLASSIFICATION: 128
};
function DrawCommand(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._boundingVolume = options.boundingVolume;
this._orientedBoundingBox = options.orientedBoundingBox;
this._modelMatrix = options.modelMatrix;
this._primitiveType = options.primitiveType ?? PrimitiveType_default.TRIANGLES;
this._vertexArray = options.vertexArray;
this._count = options.count;
this._offset = options.offset ?? 0;
this._instanceCount = options.instanceCount ?? 0;
this._shaderProgram = options.shaderProgram;
this._uniformMap = options.uniformMap;
this._renderState = options.renderState;
this._framebuffer = options.framebuffer;
this._pass = options.pass;
this._owner = options.owner;
this._debugOverlappingFrustums = 0;
this._pickId = options.pickId;
this._pickMetadataAllowed = options.pickMetadataAllowed === true;
this._pickedMetadataInfo = void 0;
this._flags = 0;
this.cull = options.cull ?? true;
this.occlude = options.occlude ?? true;
this.executeInClosestFrustum = options.executeInClosestFrustum ?? false;
this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this.castShadows = options.castShadows ?? false;
this.receiveShadows = options.receiveShadows ?? false;
this.pickOnly = options.pickOnly ?? false;
this.depthForTranslucentClassification = options.depthForTranslucentClassification ?? false;
this.dirty = true;
this.lastDirtyTime = 0;
this.derivedCommands = {};
}
function hasFlag(command, flag) {
return (command._flags & flag) === flag;
}
function setFlag(command, flag, value) {
if (value) {
command._flags |= flag;
} else {
command._flags &= ~flag;
}
}
Object.defineProperties(DrawCommand.prototype, {
/**
* The bounding volume of the geometry in world space. This is used for culling and frustum selection.
* undefined is allowed, always try to provide a bounding volume to
* allow the tightest possible near and far planes to be computed for the scene, and
* minimize the number of frustums needed.
* true, the renderer frustum and horizon culls the command based on its {@link DrawCommand#boundingVolume}.
* If the command was already culled, set this to false for a performance improvement.
*
* @memberof DrawCommand.prototype
* @type {boolean}
* @default true
*/
cull: {
get: function() {
return hasFlag(this, Flags.CULL);
},
set: function(value) {
if (hasFlag(this, Flags.CULL) !== value) {
setFlag(this, Flags.CULL, value);
this.dirty = true;
}
}
},
/**
* When true, the horizon culls the command based on its {@link DrawCommand#boundingVolume}.
* {@link DrawCommand#cull} must also be true in order for the command to be culled.
*
* @memberof DrawCommand.prototype
* @type {boolean}
* @default true
*/
occlude: {
get: function() {
return hasFlag(this, Flags.OCCLUDE);
},
set: function(value) {
if (hasFlag(this, Flags.OCCLUDE) !== value) {
setFlag(this, Flags.OCCLUDE, value);
this.dirty = true;
}
}
},
/**
* The transformation from the geometry in model space to world space.
* undefined, the geometry is assumed to be defined in world space.
* false.
*
* @memberof DrawCommand.prototype
* @type {boolean}
* @default false
*/
executeInClosestFrustum: {
get: function() {
return hasFlag(this, Flags.EXECUTE_IN_CLOSEST_FRUSTUM);
},
set: function(value) {
if (hasFlag(this, Flags.EXECUTE_IN_CLOSEST_FRUSTUM) !== value) {
setFlag(this, Flags.EXECUTE_IN_CLOSEST_FRUSTUM, value);
this.dirty = true;
}
}
},
/**
* The object who created this command. This is useful for debugging command
* execution; it allows us to see who created a command when we only have a
* reference to the command, and can be used to selectively execute commands
* with {@link Scene#debugCommandFilter}.
*
* @memberof DrawCommand.prototype
* @type {object}
* @default undefined
*
* @see Scene#debugCommandFilter
*/
owner: {
get: function() {
return this._owner;
},
set: function(value) {
if (this._owner !== value) {
this._owner = value;
this.dirty = true;
}
}
},
/**
* This property is for debugging only; it is not for production use nor is it optimized.
* undefined, the command will only draw depth
* during the pick pass.
*
* @memberof DrawCommand.prototype
* @type {string|undefined}
* @default undefined
*/
pickId: {
get: function() {
return this._pickId;
},
set: function(value) {
if (this._pickId !== value) {
this._pickId = value;
this.dirty = true;
}
}
},
/**
* Whether metadata picking is allowed.
*
* This is essentially only set to `true` for draw commands that are
* part of a `ModelDrawCommand`, to check whether a derived command
* for metadata picking has to be created.
*
* @memberof DrawCommand.prototype
* @type {boolean}
* @default undefined
* @private
*/
pickMetadataAllowed: {
get: function() {
return this._pickMetadataAllowed;
}
},
/**
* Information about picked metadata.
*
* @memberof DrawCommand.prototype
* @type {PickedMetadataInfo|undefined}
* @default undefined
*/
pickedMetadataInfo: {
get: function() {
return this._pickedMetadataInfo;
},
set: function(value) {
if (this._pickedMetadataInfo !== value) {
this._pickedMetadataInfo = value;
this.dirty = true;
}
}
},
/**
* Whether this command should be executed in the pick pass only.
*
* @memberof DrawCommand.prototype
* @type {boolean}
* @default false
*/
pickOnly: {
get: function() {
return hasFlag(this, Flags.PICK_ONLY);
},
set: function(value) {
if (hasFlag(this, Flags.PICK_ONLY) !== value) {
setFlag(this, Flags.PICK_ONLY, value);
this.dirty = true;
}
}
},
/**
* Whether this command should be derived to draw depth for classification of translucent primitives.
*
* @memberof DrawCommand.prototype
* @type {boolean}
* @default false
*/
depthForTranslucentClassification: {
get: function() {
return hasFlag(this, Flags.DEPTH_FOR_TRANSLUCENT_CLASSIFICATION);
},
set: function(value) {
if (hasFlag(this, Flags.DEPTH_FOR_TRANSLUCENT_CLASSIFICATION) !== value) {
setFlag(this, Flags.DEPTH_FOR_TRANSLUCENT_CLASSIFICATION, value);
this.dirty = true;
}
}
}
});
DrawCommand.shallowClone = function(command, result) {
if (!defined_default(command)) {
return void 0;
}
if (!defined_default(result)) {
result = new DrawCommand();
}
result._boundingVolume = command._boundingVolume;
result._orientedBoundingBox = command._orientedBoundingBox;
result._modelMatrix = command._modelMatrix;
result._primitiveType = command._primitiveType;
result._vertexArray = command._vertexArray;
result._count = command._count;
result._offset = command._offset;
result._instanceCount = command._instanceCount;
result._shaderProgram = command._shaderProgram;
result._uniformMap = command._uniformMap;
result._renderState = command._renderState;
result._framebuffer = command._framebuffer;
result._pass = command._pass;
result._owner = command._owner;
result._debugOverlappingFrustums = command._debugOverlappingFrustums;
result._pickId = command._pickId;
result._pickMetadataAllowed = command._pickMetadataAllowed;
result._pickedMetadataInfo = command._pickedMetadataInfo;
result._flags = command._flags;
result.dirty = true;
result.lastDirtyTime = 0;
return result;
};
DrawCommand.prototype.execute = function(context, passState) {
context.draw(this, passState);
};
var DrawCommand_default = DrawCommand;
// packages/engine/Source/Renderer/Framebuffer.js
var import_InlineWorkers77 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PixelFormat.js
var import_InlineWorkers75 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Renderer/PixelDatatype.js
var import_InlineWorkers74 = __toESM(require_InlineWorkers(), 1);
var PixelDatatype = {
UNSIGNED_BYTE: WebGLConstants_default.UNSIGNED_BYTE,
UNSIGNED_SHORT: WebGLConstants_default.UNSIGNED_SHORT,
UNSIGNED_INT: WebGLConstants_default.UNSIGNED_INT,
FLOAT: WebGLConstants_default.FLOAT,
HALF_FLOAT: WebGLConstants_default.HALF_FLOAT_OES,
UNSIGNED_INT_24_8: WebGLConstants_default.UNSIGNED_INT_24_8,
UNSIGNED_SHORT_4_4_4_4: WebGLConstants_default.UNSIGNED_SHORT_4_4_4_4,
UNSIGNED_SHORT_5_5_5_1: WebGLConstants_default.UNSIGNED_SHORT_5_5_5_1,
UNSIGNED_SHORT_5_6_5: WebGLConstants_default.UNSIGNED_SHORT_5_6_5
};
PixelDatatype.toWebGLConstant = function(pixelDatatype, context) {
switch (pixelDatatype) {
case PixelDatatype.UNSIGNED_BYTE:
return WebGLConstants_default.UNSIGNED_BYTE;
case PixelDatatype.UNSIGNED_SHORT:
return WebGLConstants_default.UNSIGNED_SHORT;
case PixelDatatype.UNSIGNED_INT:
return WebGLConstants_default.UNSIGNED_INT;
case PixelDatatype.FLOAT:
return WebGLConstants_default.FLOAT;
case PixelDatatype.HALF_FLOAT:
return context.webgl2 ? WebGLConstants_default.HALF_FLOAT : WebGLConstants_default.HALF_FLOAT_OES;
case PixelDatatype.UNSIGNED_INT_24_8:
return WebGLConstants_default.UNSIGNED_INT_24_8;
case PixelDatatype.UNSIGNED_SHORT_4_4_4_4:
return WebGLConstants_default.UNSIGNED_SHORT_4_4_4_4;
case PixelDatatype.UNSIGNED_SHORT_5_5_5_1:
return WebGLConstants_default.UNSIGNED_SHORT_5_5_5_1;
case PixelDatatype.UNSIGNED_SHORT_5_6_5:
return PixelDatatype.UNSIGNED_SHORT_5_6_5;
}
};
PixelDatatype.isPacked = function(pixelDatatype) {
return pixelDatatype === PixelDatatype.UNSIGNED_INT_24_8 || pixelDatatype === PixelDatatype.UNSIGNED_SHORT_4_4_4_4 || pixelDatatype === PixelDatatype.UNSIGNED_SHORT_5_5_5_1 || pixelDatatype === PixelDatatype.UNSIGNED_SHORT_5_6_5;
};
PixelDatatype.sizeInBytes = function(pixelDatatype) {
switch (pixelDatatype) {
case PixelDatatype.UNSIGNED_BYTE:
return 1;
case PixelDatatype.UNSIGNED_SHORT:
case PixelDatatype.UNSIGNED_SHORT_4_4_4_4:
case PixelDatatype.UNSIGNED_SHORT_5_5_5_1:
case PixelDatatype.UNSIGNED_SHORT_5_6_5:
case PixelDatatype.HALF_FLOAT:
return 2;
case PixelDatatype.UNSIGNED_INT:
case PixelDatatype.FLOAT:
case PixelDatatype.UNSIGNED_INT_24_8:
return 4;
}
};
PixelDatatype.validate = function(pixelDatatype) {
return pixelDatatype === PixelDatatype.UNSIGNED_BYTE || pixelDatatype === PixelDatatype.UNSIGNED_SHORT || pixelDatatype === PixelDatatype.UNSIGNED_INT || pixelDatatype === PixelDatatype.FLOAT || pixelDatatype === PixelDatatype.HALF_FLOAT || pixelDatatype === PixelDatatype.UNSIGNED_INT_24_8 || pixelDatatype === PixelDatatype.UNSIGNED_SHORT_4_4_4_4 || pixelDatatype === PixelDatatype.UNSIGNED_SHORT_5_5_5_1 || pixelDatatype === PixelDatatype.UNSIGNED_SHORT_5_6_5;
};
PixelDatatype.getTypedArrayConstructor = function(pixelDatatype) {
const sizeInBytes = PixelDatatype.sizeInBytes(pixelDatatype);
if (sizeInBytes === Uint8Array.BYTES_PER_ELEMENT) {
return Uint8Array;
} else if (sizeInBytes === Uint16Array.BYTES_PER_ELEMENT) {
return Uint16Array;
} else if (sizeInBytes === Float32Array.BYTES_PER_ELEMENT && pixelDatatype === PixelDatatype.FLOAT) {
return Float32Array;
}
return Uint32Array;
};
var PixelDatatype_default = Object.freeze(PixelDatatype);
// packages/engine/Source/Core/PixelFormat.js
var PixelFormat = {
/**
* A pixel format containing a depth value.
*
* @type {number}
* @constant
*/
DEPTH_COMPONENT: WebGLConstants_default.DEPTH_COMPONENT,
/**
* A pixel format containing a depth and stencil value, most often used with {@link PixelDatatype.UNSIGNED_INT_24_8}.
*
* @type {number}
* @constant
*/
DEPTH_STENCIL: WebGLConstants_default.DEPTH_STENCIL,
/**
* A pixel format containing an alpha channel.
*
* @type {number}
* @constant
*/
ALPHA: WebGLConstants_default.ALPHA,
/**
* A pixel format containing a red channel
*
* @type {number}
* @constant
*/
RED: WebGLConstants_default.RED,
/**
* A pixel format containing red and green channels.
*
* @type {number}
* @constant
*/
RG: WebGLConstants_default.RG,
/**
* A pixel format containing red, green, and blue channels.
*
* @type {number}
* @constant
*/
RGB: WebGLConstants_default.RGB,
/**
* A pixel format containing red, green, blue, and alpha channels.
*
* @type {number}
* @constant
*/
RGBA: WebGLConstants_default.RGBA,
/**
* A pixel format containing a red channel as an integer.
* @type {number}
* @constant
*/
RED_INTEGER: WebGLConstants_default.RED_INTEGER,
/**
* A pixel format containing red and green channels as integers.
* @type {number}
* @constant
*/
RG_INTEGER: WebGLConstants_default.RG_INTEGER,
/**
* A pixel format containing red, green, and blue channels as integers.
* @type {number}
* @constant
*/
RGB_INTEGER: WebGLConstants_default.RGB_INTEGER,
/**
* A pixel format containing red, green, blue, and alpha channels as integers.
* @type {number}
* @constant
*/
RGBA_INTEGER: WebGLConstants_default.RGBA_INTEGER,
/**
* A pixel format containing a luminance (intensity) channel.
*
* @type {number}
* @constant
*/
LUMINANCE: WebGLConstants_default.LUMINANCE,
/**
* A pixel format containing luminance (intensity) and alpha channels.
*
* @type {number}
* @constant
*/
LUMINANCE_ALPHA: WebGLConstants_default.LUMINANCE_ALPHA,
/**
* A pixel format containing red, green, and blue channels that is DXT1 compressed.
*
* @type {number}
* @constant
*/
RGB_DXT1: WebGLConstants_default.COMPRESSED_RGB_S3TC_DXT1_EXT,
/**
* A pixel format containing red, green, blue, and alpha channels that is DXT1 compressed.
*
* @type {number}
* @constant
*/
RGBA_DXT1: WebGLConstants_default.COMPRESSED_RGBA_S3TC_DXT1_EXT,
/**
* A pixel format containing red, green, blue, and alpha channels that is DXT3 compressed.
*
* @type {number}
* @constant
*/
RGBA_DXT3: WebGLConstants_default.COMPRESSED_RGBA_S3TC_DXT3_EXT,
/**
* A pixel format containing red, green, blue, and alpha channels that is DXT5 compressed.
*
* @type {number}
* @constant
*/
RGBA_DXT5: WebGLConstants_default.COMPRESSED_RGBA_S3TC_DXT5_EXT,
/**
* A pixel format containing red, green, and blue channels that is PVR 4bpp compressed.
*
* @type {number}
* @constant
*/
RGB_PVRTC_4BPPV1: WebGLConstants_default.COMPRESSED_RGB_PVRTC_4BPPV1_IMG,
/**
* A pixel format containing red, green, and blue channels that is PVR 2bpp compressed.
*
* @type {number}
* @constant
*/
RGB_PVRTC_2BPPV1: WebGLConstants_default.COMPRESSED_RGB_PVRTC_2BPPV1_IMG,
/**
* A pixel format containing red, green, blue, and alpha channels that is PVR 4bpp compressed.
*
* @type {number}
* @constant
*/
RGBA_PVRTC_4BPPV1: WebGLConstants_default.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,
/**
* A pixel format containing red, green, blue, and alpha channels that is PVR 2bpp compressed.
*
* @type {number}
* @constant
*/
RGBA_PVRTC_2BPPV1: WebGLConstants_default.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG,
/**
* A pixel format containing red, green, blue, and alpha channels that is ASTC compressed.
*
* @type {number}
* @constant
*/
RGBA_ASTC: WebGLConstants_default.COMPRESSED_RGBA_ASTC_4x4_WEBGL,
/**
* A pixel format containing red, green, and blue channels that is ETC1 compressed.
*
* @type {number}
* @constant
*/
RGB_ETC1: WebGLConstants_default.COMPRESSED_RGB_ETC1_WEBGL,
/**
* A pixel format containing red, green, and blue channels that is ETC2 compressed.
*
* @type {number}
* @constant
*/
RGB8_ETC2: WebGLConstants_default.COMPRESSED_RGB8_ETC2,
/**
* A pixel format containing red, green, blue, and alpha channels that is ETC2 compressed.
*
* @type {number}
* @constant
*/
RGBA8_ETC2_EAC: WebGLConstants_default.COMPRESSED_RGBA8_ETC2_EAC,
/**
* A pixel format containing red, green, blue, and alpha channels that is BC7 compressed.
*
* @type {number}
* @constant
*/
RGBA_BC7: WebGLConstants_default.COMPRESSED_RGBA_BPTC_UNORM
};
PixelFormat.componentsLength = function(pixelFormat) {
switch (pixelFormat) {
case PixelFormat.RGB:
case PixelFormat.RGB_INTEGER:
return 3;
case PixelFormat.RGBA:
case PixelFormat.RGBA_INTEGER:
return 4;
case PixelFormat.LUMINANCE_ALPHA:
case PixelFormat.RG:
case PixelFormat.RG_INTEGER:
return 2;
case PixelFormat.ALPHA:
case PixelFormat.RED:
case PixelFormat.RED_INTEGER:
case PixelFormat.LUMINANCE:
return 1;
default:
return 1;
}
};
PixelFormat.validate = function(pixelFormat) {
return pixelFormat === PixelFormat.DEPTH_COMPONENT || pixelFormat === PixelFormat.DEPTH_STENCIL || pixelFormat === PixelFormat.ALPHA || pixelFormat === PixelFormat.RED || pixelFormat === PixelFormat.RG || pixelFormat === PixelFormat.RGB || pixelFormat === PixelFormat.RGBA || pixelFormat === PixelFormat.RED_INTEGER || pixelFormat === PixelFormat.RG_INTEGER || pixelFormat === PixelFormat.RGB_INTEGER || pixelFormat === PixelFormat.RGBA_INTEGER || pixelFormat === PixelFormat.LUMINANCE || pixelFormat === PixelFormat.LUMINANCE_ALPHA || pixelFormat === PixelFormat.RGB_DXT1 || pixelFormat === PixelFormat.RGBA_DXT1 || pixelFormat === PixelFormat.RGBA_DXT3 || pixelFormat === PixelFormat.RGBA_DXT5 || pixelFormat === PixelFormat.RGB_PVRTC_4BPPV1 || pixelFormat === PixelFormat.RGB_PVRTC_2BPPV1 || pixelFormat === PixelFormat.RGBA_PVRTC_4BPPV1 || pixelFormat === PixelFormat.RGBA_PVRTC_2BPPV1 || pixelFormat === PixelFormat.RGBA_ASTC || pixelFormat === PixelFormat.RGB_ETC1 || pixelFormat === PixelFormat.RGB8_ETC2 || pixelFormat === PixelFormat.RGBA8_ETC2_EAC || pixelFormat === PixelFormat.RGBA_BC7;
};
PixelFormat.isColorFormat = function(pixelFormat) {
return pixelFormat === PixelFormat.RED || pixelFormat === PixelFormat.ALPHA || pixelFormat === PixelFormat.RGB || pixelFormat === PixelFormat.RGBA || pixelFormat === PixelFormat.LUMINANCE || pixelFormat === PixelFormat.LUMINANCE_ALPHA;
};
PixelFormat.isDepthFormat = function(pixelFormat) {
return pixelFormat === PixelFormat.DEPTH_COMPONENT || pixelFormat === PixelFormat.DEPTH_STENCIL;
};
PixelFormat.isCompressedFormat = function(pixelFormat) {
return pixelFormat === PixelFormat.RGB_DXT1 || pixelFormat === PixelFormat.RGBA_DXT1 || pixelFormat === PixelFormat.RGBA_DXT3 || pixelFormat === PixelFormat.RGBA_DXT5 || pixelFormat === PixelFormat.RGB_PVRTC_4BPPV1 || pixelFormat === PixelFormat.RGB_PVRTC_2BPPV1 || pixelFormat === PixelFormat.RGBA_PVRTC_4BPPV1 || pixelFormat === PixelFormat.RGBA_PVRTC_2BPPV1 || pixelFormat === PixelFormat.RGBA_ASTC || pixelFormat === PixelFormat.RGB_ETC1 || pixelFormat === PixelFormat.RGB8_ETC2 || pixelFormat === PixelFormat.RGBA8_ETC2_EAC || pixelFormat === PixelFormat.RGBA_BC7;
};
PixelFormat.isDXTFormat = function(pixelFormat) {
return pixelFormat === PixelFormat.RGB_DXT1 || pixelFormat === PixelFormat.RGBA_DXT1 || pixelFormat === PixelFormat.RGBA_DXT3 || pixelFormat === PixelFormat.RGBA_DXT5;
};
PixelFormat.isPVRTCFormat = function(pixelFormat) {
return pixelFormat === PixelFormat.RGB_PVRTC_4BPPV1 || pixelFormat === PixelFormat.RGB_PVRTC_2BPPV1 || pixelFormat === PixelFormat.RGBA_PVRTC_4BPPV1 || pixelFormat === PixelFormat.RGBA_PVRTC_2BPPV1;
};
PixelFormat.isASTCFormat = function(pixelFormat) {
return pixelFormat === PixelFormat.RGBA_ASTC;
};
PixelFormat.isETC1Format = function(pixelFormat) {
return pixelFormat === PixelFormat.RGB_ETC1;
};
PixelFormat.isETC2Format = function(pixelFormat) {
return pixelFormat === PixelFormat.RGB8_ETC2 || pixelFormat === PixelFormat.RGBA8_ETC2_EAC;
};
PixelFormat.isBC7Format = function(pixelFormat) {
return pixelFormat === PixelFormat.RGBA_BC7;
};
PixelFormat.compressedTextureSizeInBytes = function(pixelFormat, width, height) {
switch (pixelFormat) {
case PixelFormat.RGB_DXT1:
case PixelFormat.RGBA_DXT1:
case PixelFormat.RGB_ETC1:
case PixelFormat.RGB8_ETC2:
return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8;
case PixelFormat.RGBA_DXT3:
case PixelFormat.RGBA_DXT5:
case PixelFormat.RGBA_ASTC:
case PixelFormat.RGBA8_ETC2_EAC:
return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 16;
case PixelFormat.RGB_PVRTC_4BPPV1:
case PixelFormat.RGBA_PVRTC_4BPPV1:
return Math.floor((Math.max(width, 8) * Math.max(height, 8) * 4 + 7) / 8);
case PixelFormat.RGB_PVRTC_2BPPV1:
case PixelFormat.RGBA_PVRTC_2BPPV1:
return Math.floor(
(Math.max(width, 16) * Math.max(height, 8) * 2 + 7) / 8
);
case PixelFormat.RGBA_BC7:
return Math.ceil(width / 4) * Math.ceil(height / 4) * 16;
default:
return 0;
}
};
PixelFormat.textureSizeInBytes = function(pixelFormat, pixelDatatype, width, height) {
let componentsLength = PixelFormat.componentsLength(pixelFormat);
if (PixelDatatype_default.isPacked(pixelDatatype)) {
componentsLength = 1;
}
return componentsLength * PixelDatatype_default.sizeInBytes(pixelDatatype) * width * height;
};
PixelFormat.texture3DSizeInBytes = function(pixelFormat, pixelDatatype, width, height, depth) {
let componentsLength = PixelFormat.componentsLength(pixelFormat);
if (PixelDatatype_default.isPacked(pixelDatatype)) {
componentsLength = 1;
}
return componentsLength * PixelDatatype_default.sizeInBytes(pixelDatatype) * width * height * depth;
};
PixelFormat.alignmentInBytes = function(pixelFormat, pixelDatatype, width) {
const mod2 = PixelFormat.textureSizeInBytes(pixelFormat, pixelDatatype, width, 1) % 4;
return mod2 === 0 ? 4 : mod2 === 2 ? 2 : 1;
};
PixelFormat.createTypedArray = function(pixelFormat, pixelDatatype, width, height) {
const constructor = PixelDatatype_default.getTypedArrayConstructor(pixelDatatype);
const size = PixelFormat.componentsLength(pixelFormat) * width * height;
return new constructor(size);
};
PixelFormat.flipY = function(bufferView, pixelFormat, pixelDatatype, width, height) {
if (height === 1) {
return bufferView;
}
const flipped = PixelFormat.createTypedArray(
pixelFormat,
pixelDatatype,
width,
height
);
const numberOfComponents = PixelFormat.componentsLength(pixelFormat);
const textureWidth = width * numberOfComponents;
for (let i = 0; i < height; ++i) {
const row = i * width * numberOfComponents;
const flippedRow = (height - i - 1) * width * numberOfComponents;
for (let j = 0; j < textureWidth; ++j) {
flipped[flippedRow + j] = bufferView[row + j];
}
}
return flipped;
};
PixelFormat.toInternalFormat = function(pixelFormat, pixelDatatype, context) {
if (!context.webgl2) {
return pixelFormat;
}
if (pixelFormat === PixelFormat.DEPTH_STENCIL) {
return WebGLConstants_default.DEPTH24_STENCIL8;
}
if (pixelFormat === PixelFormat.DEPTH_COMPONENT) {
if (pixelDatatype === PixelDatatype_default.UNSIGNED_SHORT) {
return WebGLConstants_default.DEPTH_COMPONENT16;
} else if (pixelDatatype === PixelDatatype_default.UNSIGNED_INT) {
return WebGLConstants_default.DEPTH_COMPONENT24;
}
}
if (pixelDatatype === PixelDatatype_default.FLOAT) {
switch (pixelFormat) {
case PixelFormat.RGBA:
return WebGLConstants_default.RGBA32F;
case PixelFormat.RGB:
return WebGLConstants_default.RGB32F;
case PixelFormat.RG:
return WebGLConstants_default.RG32F;
case PixelFormat.RED:
return WebGLConstants_default.R32F;
}
}
if (pixelDatatype === PixelDatatype_default.HALF_FLOAT) {
switch (pixelFormat) {
case PixelFormat.RGBA:
return WebGLConstants_default.RGBA16F;
case PixelFormat.RGB:
return WebGLConstants_default.RGB16F;
case PixelFormat.RG:
return WebGLConstants_default.RG16F;
case PixelFormat.RED:
return WebGLConstants_default.R16F;
}
}
if (pixelDatatype === PixelDatatype_default.UNSIGNED_BYTE) {
switch (pixelFormat) {
case PixelFormat.RGBA:
return WebGLConstants_default.RGBA8;
case PixelFormat.RGB:
return WebGLConstants_default.RGB8;
case PixelFormat.RG:
return WebGLConstants_default.RG8;
case PixelFormat.RED:
return WebGLConstants_default.R8;
}
}
if (pixelDatatype === PixelDatatype_default.INT) {
switch (pixelFormat) {
case PixelFormat.RGBA_INTEGER:
return WebGLConstants_default.RGBA32I;
case PixelFormat.RGB_INTEGER:
return WebGLConstants_default.RGB32I;
case PixelFormat.RG_INTEGER:
return WebGLConstants_default.RG32I;
case PixelFormat.RED_INTEGER:
return WebGLConstants_default.R32I;
}
}
if (pixelDatatype === PixelDatatype_default.UNSIGNED_INT) {
switch (pixelFormat) {
case PixelFormat.RGBA_INTEGER:
return WebGLConstants_default.RGBA32UI;
case PixelFormat.RGB_INTEGER:
return WebGLConstants_default.RGB32UI;
case PixelFormat.RG_INTEGER:
return WebGLConstants_default.RG32UI;
case PixelFormat.RED_INTEGER:
return WebGLConstants_default.R32UI;
}
}
return pixelFormat;
};
var PixelFormat_default = Object.freeze(PixelFormat);
// packages/engine/Source/Renderer/ContextLimits.js
var import_InlineWorkers76 = __toESM(require_InlineWorkers(), 1);
var ContextLimits = {
_maximumCombinedTextureImageUnits: 0,
_maximumCubeMapSize: 0,
_maximumFragmentUniformVectors: 0,
_maximumTextureImageUnits: 0,
_maximumRenderbufferSize: 0,
_maximumTextureSize: 0,
_maximumVaryingVectors: 0,
_maximumVertexAttributes: 0,
_maximumVertexTextureImageUnits: 0,
_maximumVertexUniformVectors: 0,
_minimumAliasedLineWidth: 0,
_maximumAliasedLineWidth: 0,
_minimumAliasedPointSize: 0,
_maximumAliasedPointSize: 0,
_maximumViewportWidth: 0,
_maximumViewportHeight: 0,
_maximumTextureFilterAnisotropy: 0,
_maximumDrawBuffers: 0,
_maximumColorAttachments: 0,
_maximumSamples: 0,
_highpFloatSupported: false,
_highpIntSupported: false
};
Object.defineProperties(ContextLimits, {
/**
* The maximum number of texture units that can be used from the vertex and fragment
* shader with this WebGL implementation. The minimum is eight. If both shaders access the
* same texture unit, this counts as two texture units.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_COMBINED_TEXTURE_IMAGE_UNITS.
*/
maximumCombinedTextureImageUnits: {
get: function() {
return ContextLimits._maximumCombinedTextureImageUnits;
}
},
/**
* The approximate maximum cube map width and height supported by this WebGL implementation.
* The minimum is 16, but most desktop and laptop implementations will support much larger sizes like 8,192.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_CUBE_MAP_TEXTURE_SIZE.
*/
maximumCubeMapSize: {
get: function() {
return ContextLimits._maximumCubeMapSize;
}
},
/**
* The maximum number of vec4, ivec4, and bvec4
* uniforms that can be used by a fragment shader with this WebGL implementation. The minimum is 16.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_FRAGMENT_UNIFORM_VECTORS.
*/
maximumFragmentUniformVectors: {
get: function() {
return ContextLimits._maximumFragmentUniformVectors;
}
},
/**
* The maximum number of texture units that can be used from the fragment shader with this WebGL implementation. The minimum is eight.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_TEXTURE_IMAGE_UNITS.
*/
maximumTextureImageUnits: {
get: function() {
return ContextLimits._maximumTextureImageUnits;
}
},
/**
* The maximum renderbuffer width and height supported by this WebGL implementation.
* The minimum is 16, but most desktop and laptop implementations will support much larger sizes like 8,192.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_RENDERBUFFER_SIZE.
*/
maximumRenderbufferSize: {
get: function() {
return ContextLimits._maximumRenderbufferSize;
}
},
/**
* The approximate maximum texture width and height supported by this WebGL implementation.
* The minimum is 64, but most desktop and laptop implementations will support much larger sizes like 8,192.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_TEXTURE_SIZE.
*/
maximumTextureSize: {
get: function() {
return ContextLimits._maximumTextureSize;
}
},
/**
* The maximum number of vec4 varying variables supported by this WebGL implementation.
* The minimum is eight. Matrices and arrays count as multiple vec4s.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VARYING_VECTORS.
*/
maximumVaryingVectors: {
get: function() {
return ContextLimits._maximumVaryingVectors;
}
},
/**
* The maximum number of vec4 vertex attributes supported by this WebGL implementation. The minimum is eight.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VERTEX_ATTRIBS.
*/
maximumVertexAttributes: {
get: function() {
return ContextLimits._maximumVertexAttributes;
}
},
/**
* The maximum number of texture units that can be used from the vertex shader with this WebGL implementation.
* The minimum is zero, which means the GL does not support vertex texture fetch.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VERTEX_TEXTURE_IMAGE_UNITS.
*/
maximumVertexTextureImageUnits: {
get: function() {
return ContextLimits._maximumVertexTextureImageUnits;
}
},
/**
* The maximum number of vec4, ivec4, and bvec4
* uniforms that can be used by a vertex shader with this WebGL implementation. The minimum is 16.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VERTEX_UNIFORM_VECTORS.
*/
maximumVertexUniformVectors: {
get: function() {
return ContextLimits._maximumVertexUniformVectors;
}
},
/**
* The minimum aliased line width, in pixels, supported by this WebGL implementation. It will be at most one.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with ALIASED_LINE_WIDTH_RANGE.
*/
minimumAliasedLineWidth: {
get: function() {
return ContextLimits._minimumAliasedLineWidth;
}
},
/**
* The maximum aliased line width, in pixels, supported by this WebGL implementation. It will be at least one.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with ALIASED_LINE_WIDTH_RANGE.
*/
maximumAliasedLineWidth: {
get: function() {
return ContextLimits._maximumAliasedLineWidth;
}
},
/**
* The minimum aliased point size, in pixels, supported by this WebGL implementation. It will be at most one.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with ALIASED_POINT_SIZE_RANGE.
*/
minimumAliasedPointSize: {
get: function() {
return ContextLimits._minimumAliasedPointSize;
}
},
/**
* The maximum aliased point size, in pixels, supported by this WebGL implementation. It will be at least one.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with ALIASED_POINT_SIZE_RANGE.
*/
maximumAliasedPointSize: {
get: function() {
return ContextLimits._maximumAliasedPointSize;
}
},
/**
* The maximum supported width of the viewport. It will be at least as large as the visible width of the associated canvas.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VIEWPORT_DIMS.
*/
maximumViewportWidth: {
get: function() {
return ContextLimits._maximumViewportWidth;
}
},
/**
* The maximum supported height of the viewport. It will be at least as large as the visible height of the associated canvas.
* @memberof ContextLimits
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VIEWPORT_DIMS.
*/
maximumViewportHeight: {
get: function() {
return ContextLimits._maximumViewportHeight;
}
},
/**
* The maximum degree of anisotropy for texture filtering
* @memberof ContextLimits
* @type {number}
*/
maximumTextureFilterAnisotropy: {
get: function() {
return ContextLimits._maximumTextureFilterAnisotropy;
}
},
/**
* The maximum number of simultaneous outputs that may be written in a fragment shader.
* @memberof ContextLimits
* @type {number}
*/
maximumDrawBuffers: {
get: function() {
return ContextLimits._maximumDrawBuffers;
}
},
/**
* The maximum number of color attachments supported.
* @memberof ContextLimits
* @type {number}
*/
maximumColorAttachments: {
get: function() {
return ContextLimits._maximumColorAttachments;
}
},
/**
* The maximum number of samples supported for multisampling.
* @memberof ContextLimits
* @type {number}
*/
maximumSamples: {
get: function() {
return ContextLimits._maximumSamples;
}
},
/**
* High precision float supported (highp) in fragment shaders.
* @memberof ContextLimits
* @type {boolean}
*/
highpFloatSupported: {
get: function() {
return ContextLimits._highpFloatSupported;
}
},
/**
* High precision int supported (highp) in fragment shaders.
* @memberof ContextLimits
* @type {boolean}
*/
highpIntSupported: {
get: function() {
return ContextLimits._highpIntSupported;
}
}
});
var ContextLimits_default = ContextLimits;
// packages/engine/Source/Renderer/Framebuffer.js
function attachTexture(framebuffer, attachment, texture) {
const gl = framebuffer._gl;
gl.framebufferTexture2D(
gl.FRAMEBUFFER,
attachment,
texture._target,
texture._texture,
0
);
}
function attachRenderbuffer(framebuffer, attachment, renderbuffer) {
const gl = framebuffer._gl;
gl.framebufferRenderbuffer(
gl.FRAMEBUFFER,
attachment,
gl.RENDERBUFFER,
renderbuffer._getRenderbuffer()
);
}
function Framebuffer(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const context = options.context;
Check_default.defined("options.context", context);
const gl = context._gl;
const maximumColorAttachments = ContextLimits_default.maximumColorAttachments;
this._gl = gl;
this._framebuffer = gl.createFramebuffer();
this._colorTextures = [];
this._colorRenderbuffers = [];
this._activeColorAttachments = [];
this._depthTexture = void 0;
this._depthRenderbuffer = void 0;
this._stencilRenderbuffer = void 0;
this._depthStencilTexture = void 0;
this._depthStencilRenderbuffer = void 0;
this.destroyAttachments = options.destroyAttachments ?? true;
if (defined_default(options.colorTextures) && defined_default(options.colorRenderbuffers)) {
throw new DeveloperError_default(
"Cannot have both color texture and color renderbuffer attachments."
);
}
if (defined_default(options.depthTexture) && defined_default(options.depthRenderbuffer)) {
throw new DeveloperError_default(
"Cannot have both a depth texture and depth renderbuffer attachment."
);
}
if (defined_default(options.depthStencilTexture) && defined_default(options.depthStencilRenderbuffer)) {
throw new DeveloperError_default(
"Cannot have both a depth-stencil texture and depth-stencil renderbuffer attachment."
);
}
const depthAttachment = defined_default(options.depthTexture) || defined_default(options.depthRenderbuffer);
const depthStencilAttachment = defined_default(options.depthStencilTexture) || defined_default(options.depthStencilRenderbuffer);
if (depthAttachment && depthStencilAttachment) {
throw new DeveloperError_default(
"Cannot have both a depth and depth-stencil attachment."
);
}
if (defined_default(options.stencilRenderbuffer) && depthStencilAttachment) {
throw new DeveloperError_default(
"Cannot have both a stencil and depth-stencil attachment."
);
}
if (depthAttachment && defined_default(options.stencilRenderbuffer)) {
throw new DeveloperError_default(
"Cannot have both a depth and stencil attachment."
);
}
this._bind();
if (defined_default(options.colorTextures)) {
const textures = options.colorTextures;
const length2 = this._colorTextures.length = this._activeColorAttachments.length = textures.length;
if (length2 > maximumColorAttachments) {
throw new DeveloperError_default(
"The number of color attachments exceeds the number supported."
);
}
for (let i = 0; i < length2; ++i) {
const texture = textures[i];
if (!PixelFormat_default.isColorFormat(texture.pixelFormat)) {
throw new DeveloperError_default(
"The color-texture pixel-format must be a color format."
);
}
if (texture.pixelDatatype === PixelDatatype_default.FLOAT && !context.colorBufferFloat) {
throw new DeveloperError_default(
"The color texture pixel datatype is FLOAT and the WebGL implementation does not support the EXT_color_buffer_float or WEBGL_color_buffer_float extensions. See Context.colorBufferFloat."
);
}
if (texture.pixelDatatype === PixelDatatype_default.HALF_FLOAT && !context.colorBufferHalfFloat) {
throw new DeveloperError_default(
"The color texture pixel datatype is HALF_FLOAT and the WebGL implementation does not support the EXT_color_buffer_half_float extension. See Context.colorBufferHalfFloat."
);
}
const attachmentEnum = this._gl.COLOR_ATTACHMENT0 + i;
attachTexture(this, attachmentEnum, texture);
this._activeColorAttachments[i] = attachmentEnum;
this._colorTextures[i] = texture;
}
}
if (defined_default(options.colorRenderbuffers)) {
const renderbuffers = options.colorRenderbuffers;
const length2 = this._colorRenderbuffers.length = this._activeColorAttachments.length = renderbuffers.length;
if (length2 > maximumColorAttachments) {
throw new DeveloperError_default(
"The number of color attachments exceeds the number supported."
);
}
for (let i = 0; i < length2; ++i) {
const renderbuffer = renderbuffers[i];
const attachmentEnum = this._gl.COLOR_ATTACHMENT0 + i;
attachRenderbuffer(this, attachmentEnum, renderbuffer);
this._activeColorAttachments[i] = attachmentEnum;
this._colorRenderbuffers[i] = renderbuffer;
}
}
if (defined_default(options.depthTexture)) {
const texture = options.depthTexture;
if (texture.pixelFormat !== PixelFormat_default.DEPTH_COMPONENT) {
throw new DeveloperError_default(
"The depth-texture pixel-format must be DEPTH_COMPONENT."
);
}
attachTexture(this, this._gl.DEPTH_ATTACHMENT, texture);
this._depthTexture = texture;
}
if (defined_default(options.depthRenderbuffer)) {
const renderbuffer = options.depthRenderbuffer;
attachRenderbuffer(this, this._gl.DEPTH_ATTACHMENT, renderbuffer);
this._depthRenderbuffer = renderbuffer;
}
if (defined_default(options.stencilRenderbuffer)) {
const renderbuffer = options.stencilRenderbuffer;
attachRenderbuffer(this, this._gl.STENCIL_ATTACHMENT, renderbuffer);
this._stencilRenderbuffer = renderbuffer;
}
if (defined_default(options.depthStencilTexture)) {
const texture = options.depthStencilTexture;
if (texture.pixelFormat !== PixelFormat_default.DEPTH_STENCIL) {
throw new DeveloperError_default(
"The depth-stencil pixel-format must be DEPTH_STENCIL."
);
}
attachTexture(this, this._gl.DEPTH_STENCIL_ATTACHMENT, texture);
this._depthStencilTexture = texture;
}
if (defined_default(options.depthStencilRenderbuffer)) {
const renderbuffer = options.depthStencilRenderbuffer;
attachRenderbuffer(this, this._gl.DEPTH_STENCIL_ATTACHMENT, renderbuffer);
this._depthStencilRenderbuffer = renderbuffer;
}
this._unBind();
}
Object.defineProperties(Framebuffer.prototype, {
/**
* The status of the framebuffer. If the status is not WebGLConstants.FRAMEBUFFER_COMPLETE,
* a {@link DeveloperError} will be thrown when attempting to render to the framebuffer.
* @memberof Framebuffer.prototype
* @type {number}
*/
status: {
get: function() {
this._bind();
const status = this._gl.checkFramebufferStatus(this._gl.FRAMEBUFFER);
this._unBind();
return status;
}
},
numberOfColorAttachments: {
get: function() {
return this._activeColorAttachments.length;
}
},
depthTexture: {
get: function() {
return this._depthTexture;
}
},
depthRenderbuffer: {
get: function() {
return this._depthRenderbuffer;
}
},
stencilRenderbuffer: {
get: function() {
return this._stencilRenderbuffer;
}
},
depthStencilTexture: {
get: function() {
return this._depthStencilTexture;
}
},
depthStencilRenderbuffer: {
get: function() {
return this._depthStencilRenderbuffer;
}
},
/**
* True if the framebuffer has a depth attachment. Depth attachments include
* depth and depth-stencil textures, and depth and depth-stencil renderbuffers. When
* rendering to a framebuffer, a depth attachment is required for the depth test to have effect.
* @memberof Framebuffer.prototype
* @type {boolean}
*/
hasDepthAttachment: {
get: function() {
return !!(this.depthTexture || this.depthRenderbuffer || this.depthStencilTexture || this.depthStencilRenderbuffer);
}
}
});
Framebuffer.prototype._bind = function() {
const gl = this._gl;
gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebuffer);
};
Framebuffer.prototype._unBind = function() {
const gl = this._gl;
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
};
Framebuffer.prototype.bindDraw = function() {
const gl = this._gl;
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this._framebuffer);
};
Framebuffer.prototype.bindRead = function() {
const gl = this._gl;
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this._framebuffer);
};
Framebuffer.prototype._getActiveColorAttachments = function() {
return this._activeColorAttachments;
};
Framebuffer.prototype.getColorTexture = function(index) {
if (!defined_default(index) || index < 0 || index >= this._colorTextures.length) {
throw new DeveloperError_default(
"index is required, must be greater than or equal to zero and must be less than the number of color attachments."
);
}
return this._colorTextures[index];
};
Framebuffer.prototype.getColorRenderbuffer = function(index) {
if (!defined_default(index) || index < 0 || index >= this._colorRenderbuffers.length) {
throw new DeveloperError_default(
"index is required, must be greater than or equal to zero and must be less than the number of color attachments."
);
}
return this._colorRenderbuffers[index];
};
Framebuffer.prototype.isDestroyed = function() {
return false;
};
Framebuffer.prototype.destroy = function() {
if (this.destroyAttachments) {
const textures = this._colorTextures;
for (let i = 0; i < textures.length; ++i) {
const texture = textures[i];
if (defined_default(texture)) {
texture.destroy();
}
}
const renderbuffers = this._colorRenderbuffers;
for (let i = 0; i < renderbuffers.length; ++i) {
const renderbuffer = renderbuffers[i];
if (defined_default(renderbuffer)) {
renderbuffer.destroy();
}
}
this._depthTexture = this._depthTexture && this._depthTexture.destroy();
this._depthRenderbuffer = this._depthRenderbuffer && this._depthRenderbuffer.destroy();
this._stencilRenderbuffer = this._stencilRenderbuffer && this._stencilRenderbuffer.destroy();
this._depthStencilTexture = this._depthStencilTexture && this._depthStencilTexture.destroy();
this._depthStencilRenderbuffer = this._depthStencilRenderbuffer && this._depthStencilRenderbuffer.destroy();
}
this._gl.deleteFramebuffer(this._framebuffer);
return destroyObject_default(this);
};
var Framebuffer_default = Framebuffer;
// packages/engine/Source/Renderer/RenderState.js
var import_InlineWorkers80 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/WindingOrder.js
var import_InlineWorkers78 = __toESM(require_InlineWorkers(), 1);
var WindingOrder = {
/**
* Vertices are in clockwise order.
*
* @type {number}
* @constant
*/
CLOCKWISE: WebGLConstants_default.CW,
/**
* Vertices are in counter-clockwise order.
*
* @type {number}
* @constant
*/
COUNTER_CLOCKWISE: WebGLConstants_default.CCW
};
WindingOrder.validate = function(windingOrder) {
return windingOrder === WindingOrder.CLOCKWISE || windingOrder === WindingOrder.COUNTER_CLOCKWISE;
};
var WindingOrder_default = Object.freeze(WindingOrder);
// packages/engine/Source/Renderer/freezeRenderState.js
var import_InlineWorkers79 = __toESM(require_InlineWorkers(), 1);
function freezeRenderState(renderState) {
if (typeof renderState !== "object" || renderState === null) {
return renderState;
}
let propName;
const propNames = Object.keys(renderState);
for (let i = 0; i < propNames.length; i++) {
propName = propNames[i];
if (renderState.hasOwnProperty(propName) && propName !== "_applyFunctions") {
renderState[propName] = freezeRenderState(renderState[propName]);
}
}
return Object.freeze(renderState);
}
var freezeRenderState_default = freezeRenderState;
// packages/engine/Source/Renderer/RenderState.js
function validateBlendEquation(blendEquation) {
return blendEquation === WebGLConstants_default.FUNC_ADD || blendEquation === WebGLConstants_default.FUNC_SUBTRACT || blendEquation === WebGLConstants_default.FUNC_REVERSE_SUBTRACT || blendEquation === WebGLConstants_default.MIN || blendEquation === WebGLConstants_default.MAX;
}
function validateBlendFunction(blendFunction) {
return blendFunction === WebGLConstants_default.ZERO || blendFunction === WebGLConstants_default.ONE || blendFunction === WebGLConstants_default.SRC_COLOR || blendFunction === WebGLConstants_default.ONE_MINUS_SRC_COLOR || blendFunction === WebGLConstants_default.DST_COLOR || blendFunction === WebGLConstants_default.ONE_MINUS_DST_COLOR || blendFunction === WebGLConstants_default.SRC_ALPHA || blendFunction === WebGLConstants_default.ONE_MINUS_SRC_ALPHA || blendFunction === WebGLConstants_default.DST_ALPHA || blendFunction === WebGLConstants_default.ONE_MINUS_DST_ALPHA || blendFunction === WebGLConstants_default.CONSTANT_COLOR || blendFunction === WebGLConstants_default.ONE_MINUS_CONSTANT_COLOR || blendFunction === WebGLConstants_default.CONSTANT_ALPHA || blendFunction === WebGLConstants_default.ONE_MINUS_CONSTANT_ALPHA || blendFunction === WebGLConstants_default.SRC_ALPHA_SATURATE;
}
function validateCullFace(cullFace) {
return cullFace === WebGLConstants_default.FRONT || cullFace === WebGLConstants_default.BACK || cullFace === WebGLConstants_default.FRONT_AND_BACK;
}
function validateDepthFunction(depthFunction) {
return depthFunction === WebGLConstants_default.NEVER || depthFunction === WebGLConstants_default.LESS || depthFunction === WebGLConstants_default.EQUAL || depthFunction === WebGLConstants_default.LEQUAL || depthFunction === WebGLConstants_default.GREATER || depthFunction === WebGLConstants_default.NOTEQUAL || depthFunction === WebGLConstants_default.GEQUAL || depthFunction === WebGLConstants_default.ALWAYS;
}
function validateStencilFunction(stencilFunction) {
return stencilFunction === WebGLConstants_default.NEVER || stencilFunction === WebGLConstants_default.LESS || stencilFunction === WebGLConstants_default.EQUAL || stencilFunction === WebGLConstants_default.LEQUAL || stencilFunction === WebGLConstants_default.GREATER || stencilFunction === WebGLConstants_default.NOTEQUAL || stencilFunction === WebGLConstants_default.GEQUAL || stencilFunction === WebGLConstants_default.ALWAYS;
}
function validateStencilOperation(stencilOperation) {
return stencilOperation === WebGLConstants_default.ZERO || stencilOperation === WebGLConstants_default.KEEP || stencilOperation === WebGLConstants_default.REPLACE || stencilOperation === WebGLConstants_default.INCR || stencilOperation === WebGLConstants_default.DECR || stencilOperation === WebGLConstants_default.INVERT || stencilOperation === WebGLConstants_default.INCR_WRAP || stencilOperation === WebGLConstants_default.DECR_WRAP;
}
function RenderState(renderState) {
const rs = renderState ?? Frozen_default.EMPTY_OBJECT;
const cull = rs.cull ?? Frozen_default.EMPTY_OBJECT;
const polygonOffset = rs.polygonOffset ?? Frozen_default.EMPTY_OBJECT;
const scissorTest = rs.scissorTest ?? Frozen_default.EMPTY_OBJECT;
const scissorTestRectangle = scissorTest.rectangle ?? Frozen_default.EMPTY_OBJECT;
const depthRange = rs.depthRange ?? Frozen_default.EMPTY_OBJECT;
const depthTest = rs.depthTest ?? Frozen_default.EMPTY_OBJECT;
const colorMask = rs.colorMask ?? Frozen_default.EMPTY_OBJECT;
const blending = rs.blending ?? Frozen_default.EMPTY_OBJECT;
const blendingColor = blending.color ?? Frozen_default.EMPTY_OBJECT;
const stencilTest = rs.stencilTest ?? Frozen_default.EMPTY_OBJECT;
const stencilTestFrontOperation = stencilTest.frontOperation ?? Frozen_default.EMPTY_OBJECT;
const stencilTestBackOperation = stencilTest.backOperation ?? Frozen_default.EMPTY_OBJECT;
const sampleCoverage = rs.sampleCoverage ?? Frozen_default.EMPTY_OBJECT;
const viewport = rs.viewport;
this.frontFace = rs.frontFace ?? WindingOrder_default.COUNTER_CLOCKWISE;
this.cull = {
enabled: cull.enabled ?? false,
face: cull.face ?? WebGLConstants_default.BACK
};
this.lineWidth = rs.lineWidth ?? 1;
this.polygonOffset = {
enabled: polygonOffset.enabled ?? false,
factor: polygonOffset.factor ?? 0,
units: polygonOffset.units ?? 0
};
this.scissorTest = {
enabled: scissorTest.enabled ?? false,
rectangle: BoundingRectangle_default.clone(scissorTestRectangle)
};
this.depthRange = {
near: depthRange.near ?? 0,
far: depthRange.far ?? 1
};
this.depthTest = {
enabled: depthTest.enabled ?? false,
func: depthTest.func ?? WebGLConstants_default.LESS
// func, because function is a JavaScript keyword
};
this.colorMask = {
red: colorMask.red ?? true,
green: colorMask.green ?? true,
blue: colorMask.blue ?? true,
alpha: colorMask.alpha ?? true
};
this.depthMask = rs.depthMask ?? true;
this.stencilMask = rs.stencilMask ?? ~0;
this.blending = {
enabled: blending.enabled ?? false,
color: new Color_default(
blendingColor.red ?? 0,
blendingColor.green ?? 0,
blendingColor.blue ?? 0,
blendingColor.alpha ?? 0
),
equationRgb: blending.equationRgb ?? WebGLConstants_default.FUNC_ADD,
equationAlpha: blending.equationAlpha ?? WebGLConstants_default.FUNC_ADD,
functionSourceRgb: blending.functionSourceRgb ?? WebGLConstants_default.ONE,
functionSourceAlpha: blending.functionSourceAlpha ?? WebGLConstants_default.ONE,
functionDestinationRgb: blending.functionDestinationRgb ?? WebGLConstants_default.ZERO,
functionDestinationAlpha: blending.functionDestinationAlpha ?? WebGLConstants_default.ZERO
};
this.stencilTest = {
enabled: stencilTest.enabled ?? false,
frontFunction: stencilTest.frontFunction ?? WebGLConstants_default.ALWAYS,
backFunction: stencilTest.backFunction ?? WebGLConstants_default.ALWAYS,
reference: stencilTest.reference ?? 0,
mask: stencilTest.mask ?? ~0,
frontOperation: {
fail: stencilTestFrontOperation.fail ?? WebGLConstants_default.KEEP,
zFail: stencilTestFrontOperation.zFail ?? WebGLConstants_default.KEEP,
zPass: stencilTestFrontOperation.zPass ?? WebGLConstants_default.KEEP
},
backOperation: {
fail: stencilTestBackOperation.fail ?? WebGLConstants_default.KEEP,
zFail: stencilTestBackOperation.zFail ?? WebGLConstants_default.KEEP,
zPass: stencilTestBackOperation.zPass ?? WebGLConstants_default.KEEP
}
};
this.sampleCoverage = {
enabled: sampleCoverage.enabled ?? false,
value: sampleCoverage.value ?? 1,
invert: sampleCoverage.invert ?? false
};
this.viewport = defined_default(viewport) ? new BoundingRectangle_default(
viewport.x,
viewport.y,
viewport.width,
viewport.height
) : void 0;
if (this.lineWidth < ContextLimits_default.minimumAliasedLineWidth || this.lineWidth > ContextLimits_default.maximumAliasedLineWidth) {
throw new DeveloperError_default(
"renderState.lineWidth is out of range. Check minimumAliasedLineWidth and maximumAliasedLineWidth."
);
}
if (!WindingOrder_default.validate(this.frontFace)) {
throw new DeveloperError_default("Invalid renderState.frontFace.");
}
if (!validateCullFace(this.cull.face)) {
throw new DeveloperError_default("Invalid renderState.cull.face.");
}
if (this.scissorTest.rectangle.width < 0 || this.scissorTest.rectangle.height < 0) {
throw new DeveloperError_default(
"renderState.scissorTest.rectangle.width and renderState.scissorTest.rectangle.height must be greater than or equal to zero."
);
}
if (this.depthRange.near > this.depthRange.far) {
throw new DeveloperError_default(
"renderState.depthRange.near can not be greater than renderState.depthRange.far."
);
}
if (this.depthRange.near < 0) {
throw new DeveloperError_default(
"renderState.depthRange.near must be greater than or equal to zero."
);
}
if (this.depthRange.far > 1) {
throw new DeveloperError_default(
"renderState.depthRange.far must be less than or equal to one."
);
}
if (!validateDepthFunction(this.depthTest.func)) {
throw new DeveloperError_default("Invalid renderState.depthTest.func.");
}
if (this.blending.color.red < 0 || this.blending.color.red > 1 || this.blending.color.green < 0 || this.blending.color.green > 1 || this.blending.color.blue < 0 || this.blending.color.blue > 1 || this.blending.color.alpha < 0 || this.blending.color.alpha > 1) {
throw new DeveloperError_default(
"renderState.blending.color components must be greater than or equal to zero and less than or equal to one."
);
}
if (!validateBlendEquation(this.blending.equationRgb)) {
throw new DeveloperError_default("Invalid renderState.blending.equationRgb.");
}
if (!validateBlendEquation(this.blending.equationAlpha)) {
throw new DeveloperError_default("Invalid renderState.blending.equationAlpha.");
}
if (!validateBlendFunction(this.blending.functionSourceRgb)) {
throw new DeveloperError_default("Invalid renderState.blending.functionSourceRgb.");
}
if (!validateBlendFunction(this.blending.functionSourceAlpha)) {
throw new DeveloperError_default(
"Invalid renderState.blending.functionSourceAlpha."
);
}
if (!validateBlendFunction(this.blending.functionDestinationRgb)) {
throw new DeveloperError_default(
"Invalid renderState.blending.functionDestinationRgb."
);
}
if (!validateBlendFunction(this.blending.functionDestinationAlpha)) {
throw new DeveloperError_default(
"Invalid renderState.blending.functionDestinationAlpha."
);
}
if (!validateStencilFunction(this.stencilTest.frontFunction)) {
throw new DeveloperError_default("Invalid renderState.stencilTest.frontFunction.");
}
if (!validateStencilFunction(this.stencilTest.backFunction)) {
throw new DeveloperError_default("Invalid renderState.stencilTest.backFunction.");
}
if (!validateStencilOperation(this.stencilTest.frontOperation.fail)) {
throw new DeveloperError_default(
"Invalid renderState.stencilTest.frontOperation.fail."
);
}
if (!validateStencilOperation(this.stencilTest.frontOperation.zFail)) {
throw new DeveloperError_default(
"Invalid renderState.stencilTest.frontOperation.zFail."
);
}
if (!validateStencilOperation(this.stencilTest.frontOperation.zPass)) {
throw new DeveloperError_default(
"Invalid renderState.stencilTest.frontOperation.zPass."
);
}
if (!validateStencilOperation(this.stencilTest.backOperation.fail)) {
throw new DeveloperError_default(
"Invalid renderState.stencilTest.backOperation.fail."
);
}
if (!validateStencilOperation(this.stencilTest.backOperation.zFail)) {
throw new DeveloperError_default(
"Invalid renderState.stencilTest.backOperation.zFail."
);
}
if (!validateStencilOperation(this.stencilTest.backOperation.zPass)) {
throw new DeveloperError_default(
"Invalid renderState.stencilTest.backOperation.zPass."
);
}
if (defined_default(this.viewport)) {
if (this.viewport.width < 0) {
throw new DeveloperError_default(
"renderState.viewport.width must be greater than or equal to zero."
);
}
if (this.viewport.height < 0) {
throw new DeveloperError_default(
"renderState.viewport.height must be greater than or equal to zero."
);
}
if (this.viewport.width > ContextLimits_default.maximumViewportWidth) {
throw new DeveloperError_default(
`renderState.viewport.width must be less than or equal to the maximum viewport width (${ContextLimits_default.maximumViewportWidth.toString()}). Check maximumViewportWidth.`
);
}
if (this.viewport.height > ContextLimits_default.maximumViewportHeight) {
throw new DeveloperError_default(
`renderState.viewport.height must be less than or equal to the maximum viewport height (${ContextLimits_default.maximumViewportHeight.toString()}). Check maximumViewportHeight.`
);
}
}
this.id = 0;
this._applyFunctions = [];
}
var nextRenderStateId = 0;
var renderStateCache = {};
RenderState.fromCache = function(renderState) {
const partialKey = JSON.stringify(renderState);
let cachedState = renderStateCache[partialKey];
if (defined_default(cachedState)) {
++cachedState.referenceCount;
return cachedState.state;
}
let states = new RenderState(renderState);
const fullKey = JSON.stringify(states);
cachedState = renderStateCache[fullKey];
if (!defined_default(cachedState)) {
states.id = nextRenderStateId++;
states = freezeRenderState_default(states);
cachedState = {
referenceCount: 0,
state: states
};
renderStateCache[fullKey] = cachedState;
}
++cachedState.referenceCount;
renderStateCache[partialKey] = {
referenceCount: 1,
state: cachedState.state
};
return cachedState.state;
};
RenderState.removeFromCache = function(renderState) {
const states = new RenderState(renderState);
const fullKey = JSON.stringify(states);
const fullCachedState = renderStateCache[fullKey];
const partialKey = JSON.stringify(renderState);
const cachedState = renderStateCache[partialKey];
if (defined_default(cachedState)) {
--cachedState.referenceCount;
if (cachedState.referenceCount === 0) {
delete renderStateCache[partialKey];
if (defined_default(fullCachedState)) {
--fullCachedState.referenceCount;
}
}
}
if (defined_default(fullCachedState) && fullCachedState.referenceCount === 0) {
delete renderStateCache[fullKey];
}
};
RenderState.getCache = function() {
return renderStateCache;
};
RenderState.clearCache = function() {
renderStateCache = {};
};
function enableOrDisable(gl, glEnum, enable) {
if (enable) {
gl.enable(glEnum);
} else {
gl.disable(glEnum);
}
}
function applyFrontFace(gl, renderState) {
gl.frontFace(renderState.frontFace);
}
function applyCull(gl, renderState) {
const cull = renderState.cull;
const enabled = cull.enabled;
enableOrDisable(gl, gl.CULL_FACE, enabled);
if (enabled) {
gl.cullFace(cull.face);
}
}
function applyLineWidth(gl, renderState) {
gl.lineWidth(renderState.lineWidth);
}
function applyPolygonOffset(gl, renderState) {
const polygonOffset = renderState.polygonOffset;
const enabled = polygonOffset.enabled;
enableOrDisable(gl, gl.POLYGON_OFFSET_FILL, enabled);
if (enabled) {
gl.polygonOffset(polygonOffset.factor, polygonOffset.units);
}
}
function applyScissorTest(gl, renderState, passState) {
const scissorTest = renderState.scissorTest;
const enabled = defined_default(passState.scissorTest) ? passState.scissorTest.enabled : scissorTest.enabled;
enableOrDisable(gl, gl.SCISSOR_TEST, enabled);
if (enabled) {
const rectangle = defined_default(passState.scissorTest) ? passState.scissorTest.rectangle : scissorTest.rectangle;
gl.scissor(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
}
}
function applyDepthRange(gl, renderState) {
const depthRange = renderState.depthRange;
gl.depthRange(depthRange.near, depthRange.far);
}
function applyDepthTest(gl, renderState) {
const depthTest = renderState.depthTest;
const enabled = depthTest.enabled;
enableOrDisable(gl, gl.DEPTH_TEST, enabled);
if (enabled) {
gl.depthFunc(depthTest.func);
}
}
function applyColorMask(gl, renderState) {
const colorMask = renderState.colorMask;
gl.colorMask(colorMask.red, colorMask.green, colorMask.blue, colorMask.alpha);
}
function applyDepthMask(gl, renderState) {
gl.depthMask(renderState.depthMask);
}
function applyStencilMask(gl, renderState) {
gl.stencilMask(renderState.stencilMask);
}
function applyBlendingColor(gl, color) {
gl.blendColor(color.red, color.green, color.blue, color.alpha);
}
function applyBlending(gl, renderState, passState) {
const blending = renderState.blending;
const enabled = defined_default(passState.blendingEnabled) ? passState.blendingEnabled : blending.enabled;
enableOrDisable(gl, gl.BLEND, enabled);
if (enabled) {
applyBlendingColor(gl, blending.color);
gl.blendEquationSeparate(blending.equationRgb, blending.equationAlpha);
gl.blendFuncSeparate(
blending.functionSourceRgb,
blending.functionDestinationRgb,
blending.functionSourceAlpha,
blending.functionDestinationAlpha
);
}
}
function applyStencilTest(gl, renderState) {
const stencilTest = renderState.stencilTest;
const enabled = stencilTest.enabled;
enableOrDisable(gl, gl.STENCIL_TEST, enabled);
if (enabled) {
const frontFunction = stencilTest.frontFunction;
const backFunction = stencilTest.backFunction;
const reference = stencilTest.reference;
const mask = stencilTest.mask;
gl.stencilFunc(frontFunction, reference, mask);
gl.stencilFuncSeparate(gl.BACK, backFunction, reference, mask);
gl.stencilFuncSeparate(gl.FRONT, frontFunction, reference, mask);
const frontOperation = stencilTest.frontOperation;
const frontOperationFail = frontOperation.fail;
const frontOperationZFail = frontOperation.zFail;
const frontOperationZPass = frontOperation.zPass;
gl.stencilOpSeparate(
gl.FRONT,
frontOperationFail,
frontOperationZFail,
frontOperationZPass
);
const backOperation = stencilTest.backOperation;
const backOperationFail = backOperation.fail;
const backOperationZFail = backOperation.zFail;
const backOperationZPass = backOperation.zPass;
gl.stencilOpSeparate(
gl.BACK,
backOperationFail,
backOperationZFail,
backOperationZPass
);
}
}
function applySampleCoverage(gl, renderState) {
const sampleCoverage = renderState.sampleCoverage;
const enabled = sampleCoverage.enabled;
enableOrDisable(gl, gl.SAMPLE_COVERAGE, enabled);
if (enabled) {
gl.sampleCoverage(sampleCoverage.value, sampleCoverage.invert);
}
}
var scratchViewport = new BoundingRectangle_default();
function applyViewport(gl, renderState, passState) {
let viewport = renderState.viewport ?? passState.viewport;
if (!defined_default(viewport)) {
viewport = scratchViewport;
viewport.width = passState.context.drawingBufferWidth;
viewport.height = passState.context.drawingBufferHeight;
}
passState.context.uniformState.viewport = viewport;
gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
}
RenderState.apply = function(gl, renderState, passState) {
applyFrontFace(gl, renderState);
applyCull(gl, renderState);
applyLineWidth(gl, renderState);
applyPolygonOffset(gl, renderState);
applyDepthRange(gl, renderState);
applyDepthTest(gl, renderState);
applyColorMask(gl, renderState);
applyDepthMask(gl, renderState);
applyStencilMask(gl, renderState);
applyStencilTest(gl, renderState);
applySampleCoverage(gl, renderState);
applyScissorTest(gl, renderState, passState);
applyBlending(gl, renderState, passState);
applyViewport(gl, renderState, passState);
};
function createFuncs(previousState, nextState) {
const funcs = [];
if (previousState.frontFace !== nextState.frontFace) {
funcs.push(applyFrontFace);
}
if (previousState.cull.enabled !== nextState.cull.enabled || previousState.cull.face !== nextState.cull.face) {
funcs.push(applyCull);
}
if (previousState.lineWidth !== nextState.lineWidth) {
funcs.push(applyLineWidth);
}
if (previousState.polygonOffset.enabled !== nextState.polygonOffset.enabled || previousState.polygonOffset.factor !== nextState.polygonOffset.factor || previousState.polygonOffset.units !== nextState.polygonOffset.units) {
funcs.push(applyPolygonOffset);
}
if (previousState.depthRange.near !== nextState.depthRange.near || previousState.depthRange.far !== nextState.depthRange.far) {
funcs.push(applyDepthRange);
}
if (previousState.depthTest.enabled !== nextState.depthTest.enabled || previousState.depthTest.func !== nextState.depthTest.func) {
funcs.push(applyDepthTest);
}
if (previousState.colorMask.red !== nextState.colorMask.red || previousState.colorMask.green !== nextState.colorMask.green || previousState.colorMask.blue !== nextState.colorMask.blue || previousState.colorMask.alpha !== nextState.colorMask.alpha) {
funcs.push(applyColorMask);
}
if (previousState.depthMask !== nextState.depthMask) {
funcs.push(applyDepthMask);
}
if (previousState.stencilMask !== nextState.stencilMask) {
funcs.push(applyStencilMask);
}
if (previousState.stencilTest.enabled !== nextState.stencilTest.enabled || previousState.stencilTest.frontFunction !== nextState.stencilTest.frontFunction || previousState.stencilTest.backFunction !== nextState.stencilTest.backFunction || previousState.stencilTest.reference !== nextState.stencilTest.reference || previousState.stencilTest.mask !== nextState.stencilTest.mask || previousState.stencilTest.frontOperation.fail !== nextState.stencilTest.frontOperation.fail || previousState.stencilTest.frontOperation.zFail !== nextState.stencilTest.frontOperation.zFail || previousState.stencilTest.backOperation.fail !== nextState.stencilTest.backOperation.fail || previousState.stencilTest.backOperation.zFail !== nextState.stencilTest.backOperation.zFail || previousState.stencilTest.backOperation.zPass !== nextState.stencilTest.backOperation.zPass) {
funcs.push(applyStencilTest);
}
if (previousState.sampleCoverage.enabled !== nextState.sampleCoverage.enabled || previousState.sampleCoverage.value !== nextState.sampleCoverage.value || previousState.sampleCoverage.invert !== nextState.sampleCoverage.invert) {
funcs.push(applySampleCoverage);
}
return funcs;
}
RenderState.partialApply = function(gl, previousRenderState, renderState, previousPassState, passState, clear2) {
if (previousRenderState !== renderState) {
let funcs = renderState._applyFunctions[previousRenderState.id];
if (!defined_default(funcs)) {
funcs = createFuncs(previousRenderState, renderState);
renderState._applyFunctions[previousRenderState.id] = funcs;
}
const len = funcs.length;
for (let i = 0; i < len; ++i) {
funcs[i](gl, renderState);
}
}
const previousScissorTest = defined_default(previousPassState.scissorTest) ? previousPassState.scissorTest : previousRenderState.scissorTest;
const scissorTest = defined_default(passState.scissorTest) ? passState.scissorTest : renderState.scissorTest;
if (previousScissorTest !== scissorTest || clear2) {
applyScissorTest(gl, renderState, passState);
}
const previousBlendingEnabled = defined_default(previousPassState.blendingEnabled) ? previousPassState.blendingEnabled : previousRenderState.blending.enabled;
const blendingEnabled = defined_default(passState.blendingEnabled) ? passState.blendingEnabled : renderState.blending.enabled;
if (previousBlendingEnabled !== blendingEnabled || blendingEnabled && previousRenderState.blending !== renderState.blending) {
applyBlending(gl, renderState, passState);
}
if (previousRenderState !== renderState || previousPassState !== passState || previousPassState.context !== passState.context) {
applyViewport(gl, renderState, passState);
}
};
RenderState.getState = function(renderState) {
if (!defined_default(renderState)) {
throw new DeveloperError_default("renderState is required.");
}
return {
frontFace: renderState.frontFace,
cull: {
enabled: renderState.cull.enabled,
face: renderState.cull.face
},
lineWidth: renderState.lineWidth,
polygonOffset: {
enabled: renderState.polygonOffset.enabled,
factor: renderState.polygonOffset.factor,
units: renderState.polygonOffset.units
},
scissorTest: {
enabled: renderState.scissorTest.enabled,
rectangle: BoundingRectangle_default.clone(renderState.scissorTest.rectangle)
},
depthRange: {
near: renderState.depthRange.near,
far: renderState.depthRange.far
},
depthTest: {
enabled: renderState.depthTest.enabled,
func: renderState.depthTest.func
},
colorMask: {
red: renderState.colorMask.red,
green: renderState.colorMask.green,
blue: renderState.colorMask.blue,
alpha: renderState.colorMask.alpha
},
depthMask: renderState.depthMask,
stencilMask: renderState.stencilMask,
blending: {
enabled: renderState.blending.enabled,
color: Color_default.clone(renderState.blending.color),
equationRgb: renderState.blending.equationRgb,
equationAlpha: renderState.blending.equationAlpha,
functionSourceRgb: renderState.blending.functionSourceRgb,
functionSourceAlpha: renderState.blending.functionSourceAlpha,
functionDestinationRgb: renderState.blending.functionDestinationRgb,
functionDestinationAlpha: renderState.blending.functionDestinationAlpha
},
stencilTest: {
enabled: renderState.stencilTest.enabled,
frontFunction: renderState.stencilTest.frontFunction,
backFunction: renderState.stencilTest.backFunction,
reference: renderState.stencilTest.reference,
mask: renderState.stencilTest.mask,
frontOperation: {
fail: renderState.stencilTest.frontOperation.fail,
zFail: renderState.stencilTest.frontOperation.zFail,
zPass: renderState.stencilTest.frontOperation.zPass
},
backOperation: {
fail: renderState.stencilTest.backOperation.fail,
zFail: renderState.stencilTest.backOperation.zFail,
zPass: renderState.stencilTest.backOperation.zPass
}
},
sampleCoverage: {
enabled: renderState.sampleCoverage.enabled,
value: renderState.sampleCoverage.value,
invert: renderState.sampleCoverage.invert
},
viewport: defined_default(renderState.viewport) ? BoundingRectangle_default.clone(renderState.viewport) : void 0
};
};
var RenderState_default = RenderState;
// packages/engine/Source/Renderer/ShaderProgram.js
var import_InlineWorkers84 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Renderer/createUniform.js
var import_InlineWorkers82 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/Matrix2.js
var import_InlineWorkers81 = __toESM(require_InlineWorkers(), 1);
function Matrix2(column0Row0, column1Row0, column0Row1, column1Row1) {
this[0] = column0Row0 ?? 0;
this[1] = column0Row1 ?? 0;
this[2] = column1Row0 ?? 0;
this[3] = column1Row1 ?? 0;
}
Matrix2.packedLength = 4;
Matrix2.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
array[startingIndex++] = value[0];
array[startingIndex++] = value[1];
array[startingIndex++] = value[2];
array[startingIndex++] = value[3];
return array;
};
Matrix2.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new Matrix2();
}
result[0] = array[startingIndex++];
result[1] = array[startingIndex++];
result[2] = array[startingIndex++];
result[3] = array[startingIndex++];
return result;
};
Matrix2.packArray = function(array, result) {
Check_default.defined("array", array);
const length2 = array.length;
const resultLength = length2 * 4;
if (!defined_default(result)) {
result = new Array(resultLength);
} else if (!Array.isArray(result) && result.length !== resultLength) {
throw new DeveloperError_default(
"If result is a typed array, it must have exactly array.length * 4 elements"
);
} else if (result.length !== resultLength) {
result.length = resultLength;
}
for (let i = 0; i < length2; ++i) {
Matrix2.pack(array[i], result, i * 4);
}
return result;
};
Matrix2.unpackArray = function(array, result) {
Check_default.defined("array", array);
Check_default.typeOf.number.greaterThanOrEquals("array.length", array.length, 4);
if (array.length % 4 !== 0) {
throw new DeveloperError_default("array length must be a multiple of 4.");
}
const length2 = array.length;
if (!defined_default(result)) {
result = new Array(length2 / 4);
} else {
result.length = length2 / 4;
}
for (let i = 0; i < length2; i += 4) {
const index = i / 4;
result[index] = Matrix2.unpack(array, i, result[index]);
}
return result;
};
Matrix2.clone = function(matrix, result) {
if (!defined_default(matrix)) {
return void 0;
}
if (!defined_default(result)) {
return new Matrix2(matrix[0], matrix[2], matrix[1], matrix[3]);
}
result[0] = matrix[0];
result[1] = matrix[1];
result[2] = matrix[2];
result[3] = matrix[3];
return result;
};
Matrix2.fromArray = Matrix2.unpack;
Matrix2.fromColumnMajorArray = function(values, result) {
Check_default.defined("values", values);
return Matrix2.clone(values, result);
};
Matrix2.fromRowMajorArray = function(values, result) {
Check_default.defined("values", values);
if (!defined_default(result)) {
return new Matrix2(values[0], values[1], values[2], values[3]);
}
result[0] = values[0];
result[1] = values[2];
result[2] = values[1];
result[3] = values[3];
return result;
};
Matrix2.fromScale = function(scale, result) {
Check_default.typeOf.object("scale", scale);
if (!defined_default(result)) {
return new Matrix2(scale.x, 0, 0, scale.y);
}
result[0] = scale.x;
result[1] = 0;
result[2] = 0;
result[3] = scale.y;
return result;
};
Matrix2.fromUniformScale = function(scale, result) {
Check_default.typeOf.number("scale", scale);
if (!defined_default(result)) {
return new Matrix2(scale, 0, 0, scale);
}
result[0] = scale;
result[1] = 0;
result[2] = 0;
result[3] = scale;
return result;
};
Matrix2.fromRotation = function(angle, result) {
Check_default.typeOf.number("angle", angle);
const cosAngle = Math.cos(angle);
const sinAngle = Math.sin(angle);
if (!defined_default(result)) {
return new Matrix2(cosAngle, -sinAngle, sinAngle, cosAngle);
}
result[0] = cosAngle;
result[1] = sinAngle;
result[2] = -sinAngle;
result[3] = cosAngle;
return result;
};
Matrix2.toArray = function(matrix, result) {
Check_default.typeOf.object("matrix", matrix);
if (!defined_default(result)) {
return [matrix[0], matrix[1], matrix[2], matrix[3]];
}
result[0] = matrix[0];
result[1] = matrix[1];
result[2] = matrix[2];
result[3] = matrix[3];
return result;
};
Matrix2.getElementIndex = function(column, row) {
Check_default.typeOf.number.greaterThanOrEquals("row", row, 0);
Check_default.typeOf.number.lessThanOrEquals("row", row, 1);
Check_default.typeOf.number.greaterThanOrEquals("column", column, 0);
Check_default.typeOf.number.lessThanOrEquals("column", column, 1);
return column * 2 + row;
};
Matrix2.getColumn = function(matrix, index, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.number.greaterThanOrEquals("index", index, 0);
Check_default.typeOf.number.lessThanOrEquals("index", index, 1);
Check_default.typeOf.object("result", result);
const startIndex = index * 2;
const x = matrix[startIndex];
const y = matrix[startIndex + 1];
result.x = x;
result.y = y;
return result;
};
Matrix2.setColumn = function(matrix, index, cartesian11, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.number.greaterThanOrEquals("index", index, 0);
Check_default.typeOf.number.lessThanOrEquals("index", index, 1);
Check_default.typeOf.object("cartesian", cartesian11);
Check_default.typeOf.object("result", result);
result = Matrix2.clone(matrix, result);
const startIndex = index * 2;
result[startIndex] = cartesian11.x;
result[startIndex + 1] = cartesian11.y;
return result;
};
Matrix2.getRow = function(matrix, index, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.number.greaterThanOrEquals("index", index, 0);
Check_default.typeOf.number.lessThanOrEquals("index", index, 1);
Check_default.typeOf.object("result", result);
const x = matrix[index];
const y = matrix[index + 2];
result.x = x;
result.y = y;
return result;
};
Matrix2.setRow = function(matrix, index, cartesian11, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.number.greaterThanOrEquals("index", index, 0);
Check_default.typeOf.number.lessThanOrEquals("index", index, 1);
Check_default.typeOf.object("cartesian", cartesian11);
Check_default.typeOf.object("result", result);
result = Matrix2.clone(matrix, result);
result[index] = cartesian11.x;
result[index + 2] = cartesian11.y;
return result;
};
var scaleScratch13 = new Cartesian2_default();
Matrix2.setScale = function(matrix, scale, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.object("scale", scale);
Check_default.typeOf.object("result", result);
const existingScale = Matrix2.getScale(matrix, scaleScratch13);
const scaleRatioX = scale.x / existingScale.x;
const scaleRatioY = scale.y / existingScale.y;
result[0] = matrix[0] * scaleRatioX;
result[1] = matrix[1] * scaleRatioX;
result[2] = matrix[2] * scaleRatioY;
result[3] = matrix[3] * scaleRatioY;
return result;
};
var scaleScratch23 = new Cartesian2_default();
Matrix2.setUniformScale = function(matrix, scale, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.number("scale", scale);
Check_default.typeOf.object("result", result);
const existingScale = Matrix2.getScale(matrix, scaleScratch23);
const scaleRatioX = scale / existingScale.x;
const scaleRatioY = scale / existingScale.y;
result[0] = matrix[0] * scaleRatioX;
result[1] = matrix[1] * scaleRatioX;
result[2] = matrix[2] * scaleRatioY;
result[3] = matrix[3] * scaleRatioY;
return result;
};
var scratchColumn3 = new Cartesian2_default();
Matrix2.getScale = function(matrix, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.object("result", result);
result.x = Cartesian2_default.magnitude(
Cartesian2_default.fromElements(matrix[0], matrix[1], scratchColumn3)
);
result.y = Cartesian2_default.magnitude(
Cartesian2_default.fromElements(matrix[2], matrix[3], scratchColumn3)
);
return result;
};
var scaleScratch33 = new Cartesian2_default();
Matrix2.getMaximumScale = function(matrix) {
Matrix2.getScale(matrix, scaleScratch33);
return Cartesian2_default.maximumComponent(scaleScratch33);
};
var scaleScratch43 = new Cartesian2_default();
Matrix2.setRotation = function(matrix, rotation, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.object("result", result);
const scale = Matrix2.getScale(matrix, scaleScratch43);
result[0] = rotation[0] * scale.x;
result[1] = rotation[1] * scale.x;
result[2] = rotation[2] * scale.y;
result[3] = rotation[3] * scale.y;
return result;
};
var scaleScratch53 = new Cartesian2_default();
Matrix2.getRotation = function(matrix, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.object("result", result);
const scale = Matrix2.getScale(matrix, scaleScratch53);
result[0] = matrix[0] / scale.x;
result[1] = matrix[1] / scale.x;
result[2] = matrix[2] / scale.y;
result[3] = matrix[3] / scale.y;
return result;
};
Matrix2.multiply = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
const column0Row0 = left[0] * right[0] + left[2] * right[1];
const column1Row0 = left[0] * right[2] + left[2] * right[3];
const column0Row1 = left[1] * right[0] + left[3] * right[1];
const column1Row1 = left[1] * right[2] + left[3] * right[3];
result[0] = column0Row0;
result[1] = column0Row1;
result[2] = column1Row0;
result[3] = column1Row1;
return result;
};
Matrix2.add = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result[0] = left[0] + right[0];
result[1] = left[1] + right[1];
result[2] = left[2] + right[2];
result[3] = left[3] + right[3];
return result;
};
Matrix2.subtract = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
Check_default.typeOf.object("result", result);
result[0] = left[0] - right[0];
result[1] = left[1] - right[1];
result[2] = left[2] - right[2];
result[3] = left[3] - right[3];
return result;
};
Matrix2.multiplyByVector = function(matrix, cartesian11, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.object("cartesian", cartesian11);
Check_default.typeOf.object("result", result);
const x = matrix[0] * cartesian11.x + matrix[2] * cartesian11.y;
const y = matrix[1] * cartesian11.x + matrix[3] * cartesian11.y;
result.x = x;
result.y = y;
return result;
};
Matrix2.multiplyByScalar = function(matrix, scalar, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.number("scalar", scalar);
Check_default.typeOf.object("result", result);
result[0] = matrix[0] * scalar;
result[1] = matrix[1] * scalar;
result[2] = matrix[2] * scalar;
result[3] = matrix[3] * scalar;
return result;
};
Matrix2.multiplyByScale = function(matrix, scale, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.object("scale", scale);
Check_default.typeOf.object("result", result);
result[0] = matrix[0] * scale.x;
result[1] = matrix[1] * scale.x;
result[2] = matrix[2] * scale.y;
result[3] = matrix[3] * scale.y;
return result;
};
Matrix2.multiplyByUniformScale = function(matrix, scale, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.number("scale", scale);
Check_default.typeOf.object("result", result);
result[0] = matrix[0] * scale;
result[1] = matrix[1] * scale;
result[2] = matrix[2] * scale;
result[3] = matrix[3] * scale;
return result;
};
Matrix2.negate = function(matrix, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.object("result", result);
result[0] = -matrix[0];
result[1] = -matrix[1];
result[2] = -matrix[2];
result[3] = -matrix[3];
return result;
};
Matrix2.transpose = function(matrix, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.object("result", result);
const column0Row0 = matrix[0];
const column0Row1 = matrix[2];
const column1Row0 = matrix[1];
const column1Row1 = matrix[3];
result[0] = column0Row0;
result[1] = column0Row1;
result[2] = column1Row0;
result[3] = column1Row1;
return result;
};
Matrix2.abs = function(matrix, result) {
Check_default.typeOf.object("matrix", matrix);
Check_default.typeOf.object("result", result);
result[0] = Math.abs(matrix[0]);
result[1] = Math.abs(matrix[1]);
result[2] = Math.abs(matrix[2]);
result[3] = Math.abs(matrix[3]);
return result;
};
Matrix2.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left[0] === right[0] && left[1] === right[1] && left[2] === right[2] && left[3] === right[3];
};
Matrix2.equalsArray = function(matrix, array, offset) {
return matrix[0] === array[offset] && matrix[1] === array[offset + 1] && matrix[2] === array[offset + 2] && matrix[3] === array[offset + 3];
};
Matrix2.equalsEpsilon = function(left, right, epsilon) {
epsilon = epsilon ?? 0;
return left === right || defined_default(left) && defined_default(right) && Math.abs(left[0] - right[0]) <= epsilon && Math.abs(left[1] - right[1]) <= epsilon && Math.abs(left[2] - right[2]) <= epsilon && Math.abs(left[3] - right[3]) <= epsilon;
};
Matrix2.IDENTITY = Object.freeze(new Matrix2(1, 0, 0, 1));
Matrix2.ZERO = Object.freeze(new Matrix2(0, 0, 0, 0));
Matrix2.COLUMN0ROW0 = 0;
Matrix2.COLUMN0ROW1 = 1;
Matrix2.COLUMN1ROW0 = 2;
Matrix2.COLUMN1ROW1 = 3;
Object.defineProperties(Matrix2.prototype, {
/**
* Gets the number of items in the collection.
* @memberof Matrix2.prototype
*
* @type {number}
*/
length: {
get: function() {
return Matrix2.packedLength;
}
}
});
Matrix2.prototype.clone = function(result) {
return Matrix2.clone(this, result);
};
Matrix2.prototype.equals = function(right) {
return Matrix2.equals(this, right);
};
Matrix2.prototype.equalsEpsilon = function(right, epsilon) {
return Matrix2.equalsEpsilon(this, right, epsilon);
};
Matrix2.prototype.toString = function() {
return `(${this[0]}, ${this[2]})
(${this[1]}, ${this[3]})`;
};
var Matrix2_default = Matrix2;
// packages/engine/Source/Renderer/createUniform.js
function createUniform(gl, activeUniform, uniformName, location2) {
switch (activeUniform.type) {
case gl.FLOAT:
return new UniformFloat(gl, activeUniform, uniformName, location2);
case gl.FLOAT_VEC2:
return new UniformFloatVec2(gl, activeUniform, uniformName, location2);
case gl.FLOAT_VEC3:
return new UniformFloatVec3(gl, activeUniform, uniformName, location2);
case gl.FLOAT_VEC4:
return new UniformFloatVec4(gl, activeUniform, uniformName, location2);
case gl.SAMPLER_2D:
case gl.SAMPLER_3D:
case gl.SAMPLER_CUBE:
return new UniformSampler(gl, activeUniform, uniformName, location2);
case gl.UNSIGNED_INT_SAMPLER_2D:
return new UniformSampler(gl, activeUniform, uniformName, location2);
case gl.INT:
case gl.BOOL:
return new UniformInt(gl, activeUniform, uniformName, location2);
case gl.INT_VEC2:
case gl.BOOL_VEC2:
return new UniformIntVec2(gl, activeUniform, uniformName, location2);
case gl.INT_VEC3:
case gl.BOOL_VEC3:
return new UniformIntVec3(gl, activeUniform, uniformName, location2);
case gl.INT_VEC4:
case gl.BOOL_VEC4:
return new UniformIntVec4(gl, activeUniform, uniformName, location2);
case gl.FLOAT_MAT2:
return new UniformMat2(gl, activeUniform, uniformName, location2);
case gl.FLOAT_MAT3:
return new UniformMat3(gl, activeUniform, uniformName, location2);
case gl.FLOAT_MAT4:
return new UniformMat4(gl, activeUniform, uniformName, location2);
default:
throw new RuntimeError_default(
`Unrecognized uniform type: ${activeUniform.type} for uniform "${uniformName}".`
);
}
}
function UniformFloat(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._value = 0;
this._gl = gl;
this._location = location2;
}
UniformFloat.prototype.set = function() {
if (this.value !== this._value) {
this._value = this.value;
this._gl.uniform1f(this._location, this.value);
}
};
function UniformFloatVec2(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._value = new Cartesian2_default();
this._gl = gl;
this._location = location2;
}
UniformFloatVec2.prototype.set = function() {
const v3 = this.value;
if (!Cartesian2_default.equals(v3, this._value)) {
Cartesian2_default.clone(v3, this._value);
this._gl.uniform2f(this._location, v3.x, v3.y);
}
};
function UniformFloatVec3(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._value = void 0;
this._gl = gl;
this._location = location2;
}
UniformFloatVec3.prototype.set = function() {
const v3 = this.value;
if (defined_default(v3.red)) {
if (!Color_default.equals(v3, this._value)) {
this._value = Color_default.clone(v3, this._value);
this._gl.uniform3f(this._location, v3.red, v3.green, v3.blue);
}
} else if (defined_default(v3.x)) {
if (!Cartesian3_default.equals(v3, this._value)) {
this._value = Cartesian3_default.clone(v3, this._value);
this._gl.uniform3f(this._location, v3.x, v3.y, v3.z);
}
} else {
throw new DeveloperError_default(`Invalid vec3 value for uniform "${this.name}".`);
}
};
function UniformFloatVec4(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._value = void 0;
this._gl = gl;
this._location = location2;
}
UniformFloatVec4.prototype.set = function() {
const v3 = this.value;
if (defined_default(v3.red)) {
if (!Color_default.equals(v3, this._value)) {
this._value = Color_default.clone(v3, this._value);
this._gl.uniform4f(this._location, v3.red, v3.green, v3.blue, v3.alpha);
}
} else if (defined_default(v3.x)) {
if (!Cartesian4_default.equals(v3, this._value)) {
this._value = Cartesian4_default.clone(v3, this._value);
this._gl.uniform4f(this._location, v3.x, v3.y, v3.z, v3.w);
}
} else {
throw new DeveloperError_default(`Invalid vec4 value for uniform "${this.name}".`);
}
};
function UniformSampler(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._gl = gl;
this._location = location2;
this.textureUnitIndex = void 0;
}
UniformSampler.prototype.set = function() {
const gl = this._gl;
gl.activeTexture(gl.TEXTURE0 + this.textureUnitIndex);
const v3 = this.value;
gl.bindTexture(v3._target, v3._texture);
};
UniformSampler.prototype._setSampler = function(textureUnitIndex) {
this.textureUnitIndex = textureUnitIndex;
this._gl.uniform1i(this._location, textureUnitIndex);
return textureUnitIndex + 1;
};
function UniformInt(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._value = 0;
this._gl = gl;
this._location = location2;
}
UniformInt.prototype.set = function() {
if (this.value !== this._value) {
this._value = this.value;
this._gl.uniform1i(this._location, this.value);
}
};
function UniformIntVec2(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._value = new Cartesian2_default();
this._gl = gl;
this._location = location2;
}
UniformIntVec2.prototype.set = function() {
const v3 = this.value;
if (!Cartesian2_default.equals(v3, this._value)) {
Cartesian2_default.clone(v3, this._value);
this._gl.uniform2i(this._location, v3.x, v3.y);
}
};
function UniformIntVec3(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._value = new Cartesian3_default();
this._gl = gl;
this._location = location2;
}
UniformIntVec3.prototype.set = function() {
const v3 = this.value;
if (!Cartesian3_default.equals(v3, this._value)) {
Cartesian3_default.clone(v3, this._value);
this._gl.uniform3i(this._location, v3.x, v3.y, v3.z);
}
};
function UniformIntVec4(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._value = new Cartesian4_default();
this._gl = gl;
this._location = location2;
}
UniformIntVec4.prototype.set = function() {
const v3 = this.value;
if (!Cartesian4_default.equals(v3, this._value)) {
Cartesian4_default.clone(v3, this._value);
this._gl.uniform4i(this._location, v3.x, v3.y, v3.z, v3.w);
}
};
var scratchUniformArray = new Float32Array(4);
function UniformMat2(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._value = new Matrix2_default();
this._gl = gl;
this._location = location2;
}
UniformMat2.prototype.set = function() {
if (!Matrix2_default.equalsArray(this.value, this._value, 0)) {
Matrix2_default.clone(this.value, this._value);
const array = Matrix2_default.toArray(this.value, scratchUniformArray);
this._gl.uniformMatrix2fv(this._location, false, array);
}
};
var scratchMat3Array = new Float32Array(9);
function UniformMat3(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._value = new Matrix3_default();
this._gl = gl;
this._location = location2;
}
UniformMat3.prototype.set = function() {
if (!Matrix3_default.equalsArray(this.value, this._value, 0)) {
Matrix3_default.clone(this.value, this._value);
const array = Matrix3_default.toArray(this.value, scratchMat3Array);
this._gl.uniformMatrix3fv(this._location, false, array);
}
};
var scratchMat4Array = new Float32Array(16);
function UniformMat4(gl, activeUniform, uniformName, location2) {
this.name = uniformName;
this.value = void 0;
this._value = new Matrix4_default();
this._gl = gl;
this._location = location2;
}
UniformMat4.prototype.set = function() {
if (!Matrix4_default.equalsArray(this.value, this._value, 0)) {
Matrix4_default.clone(this.value, this._value);
const array = Matrix4_default.toArray(this.value, scratchMat4Array);
this._gl.uniformMatrix4fv(this._location, false, array);
}
};
var createUniform_default = createUniform;
// packages/engine/Source/Renderer/createUniformArray.js
var import_InlineWorkers83 = __toESM(require_InlineWorkers(), 1);
function createUniformArray(gl, activeUniform, uniformName, locations) {
switch (activeUniform.type) {
case gl.FLOAT:
return new UniformArrayFloat(gl, activeUniform, uniformName, locations);
case gl.FLOAT_VEC2:
return new UniformArrayFloatVec2(
gl,
activeUniform,
uniformName,
locations
);
case gl.FLOAT_VEC3:
return new UniformArrayFloatVec3(
gl,
activeUniform,
uniformName,
locations
);
case gl.FLOAT_VEC4:
return new UniformArrayFloatVec4(
gl,
activeUniform,
uniformName,
locations
);
case gl.SAMPLER_2D:
case gl.SAMPLER_3D:
case gl.SAMPLER_CUBE:
return new UniformArraySampler(gl, activeUniform, uniformName, locations);
case gl.INT:
case gl.BOOL:
return new UniformArrayInt(gl, activeUniform, uniformName, locations);
case gl.INT_VEC2:
case gl.BOOL_VEC2:
return new UniformArrayIntVec2(gl, activeUniform, uniformName, locations);
case gl.INT_VEC3:
case gl.BOOL_VEC3:
return new UniformArrayIntVec3(gl, activeUniform, uniformName, locations);
case gl.INT_VEC4:
case gl.BOOL_VEC4:
return new UniformArrayIntVec4(gl, activeUniform, uniformName, locations);
case gl.FLOAT_MAT2:
return new UniformArrayMat2(gl, activeUniform, uniformName, locations);
case gl.FLOAT_MAT3:
return new UniformArrayMat3(gl, activeUniform, uniformName, locations);
case gl.FLOAT_MAT4:
return new UniformArrayMat4(gl, activeUniform, uniformName, locations);
default:
throw new RuntimeError_default(
`Unrecognized uniform type: ${activeUniform.type} for uniform "${uniformName}".`
);
}
}
function UniformArrayFloat(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Float32Array(length2);
this._gl = gl;
this._location = locations[0];
}
UniformArrayFloat.prototype.set = function() {
const value = this.value;
const length2 = value.length;
const arraybuffer = this._value;
let changed = false;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
if (v3 !== arraybuffer[i]) {
arraybuffer[i] = v3;
changed = true;
}
}
if (changed) {
this._gl.uniform1fv(this._location, arraybuffer);
}
};
function UniformArrayFloatVec2(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Float32Array(length2 * 2);
this._gl = gl;
this._location = locations[0];
}
UniformArrayFloatVec2.prototype.set = function() {
const value = this.value;
const length2 = value.length;
const arraybuffer = this._value;
let changed = false;
let j = 0;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
if (!Cartesian2_default.equalsArray(v3, arraybuffer, j)) {
Cartesian2_default.pack(v3, arraybuffer, j);
changed = true;
}
j += 2;
}
if (changed) {
this._gl.uniform2fv(this._location, arraybuffer);
}
};
function UniformArrayFloatVec3(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Float32Array(length2 * 3);
this._gl = gl;
this._location = locations[0];
}
UniformArrayFloatVec3.prototype.set = function() {
const value = this.value;
const length2 = value.length;
const arraybuffer = this._value;
let changed = false;
let j = 0;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
if (defined_default(v3.red)) {
if (v3.red !== arraybuffer[j] || v3.green !== arraybuffer[j + 1] || v3.blue !== arraybuffer[j + 2]) {
arraybuffer[j] = v3.red;
arraybuffer[j + 1] = v3.green;
arraybuffer[j + 2] = v3.blue;
changed = true;
}
} else if (defined_default(v3.x)) {
if (!Cartesian3_default.equalsArray(v3, arraybuffer, j)) {
Cartesian3_default.pack(v3, arraybuffer, j);
changed = true;
}
} else {
throw new DeveloperError_default("Invalid vec3 value.");
}
j += 3;
}
if (changed) {
this._gl.uniform3fv(this._location, arraybuffer);
}
};
function UniformArrayFloatVec4(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Float32Array(length2 * 4);
this._gl = gl;
this._location = locations[0];
}
UniformArrayFloatVec4.prototype.set = function() {
const value = this.value;
const length2 = value.length;
const arraybuffer = this._value;
let changed = false;
let j = 0;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
if (defined_default(v3.red)) {
if (!Color_default.equalsArray(v3, arraybuffer, j)) {
Color_default.pack(v3, arraybuffer, j);
changed = true;
}
} else if (defined_default(v3.x)) {
if (!Cartesian4_default.equalsArray(v3, arraybuffer, j)) {
Cartesian4_default.pack(v3, arraybuffer, j);
changed = true;
}
} else {
throw new DeveloperError_default("Invalid vec4 value.");
}
j += 4;
}
if (changed) {
this._gl.uniform4fv(this._location, arraybuffer);
}
};
function UniformArraySampler(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Float32Array(length2);
this._gl = gl;
this._locations = locations;
this.textureUnitIndex = void 0;
}
UniformArraySampler.prototype.set = function() {
const gl = this._gl;
const textureUnitIndex = gl.TEXTURE0 + this.textureUnitIndex;
const value = this.value;
const length2 = value.length;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
gl.activeTexture(textureUnitIndex + i);
gl.bindTexture(v3._target, v3._texture);
}
};
UniformArraySampler.prototype._setSampler = function(textureUnitIndex) {
this.textureUnitIndex = textureUnitIndex;
const locations = this._locations;
const length2 = locations.length;
for (let i = 0; i < length2; ++i) {
const index = textureUnitIndex + i;
this._gl.uniform1i(locations[i], index);
}
return textureUnitIndex + length2;
};
function UniformArrayInt(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Int32Array(length2);
this._gl = gl;
this._location = locations[0];
}
UniformArrayInt.prototype.set = function() {
const value = this.value;
const length2 = value.length;
const arraybuffer = this._value;
let changed = false;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
if (v3 !== arraybuffer[i]) {
arraybuffer[i] = v3;
changed = true;
}
}
if (changed) {
this._gl.uniform1iv(this._location, arraybuffer);
}
};
function UniformArrayIntVec2(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Int32Array(length2 * 2);
this._gl = gl;
this._location = locations[0];
}
UniformArrayIntVec2.prototype.set = function() {
const value = this.value;
const length2 = value.length;
const arraybuffer = this._value;
let changed = false;
let j = 0;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
if (!Cartesian2_default.equalsArray(v3, arraybuffer, j)) {
Cartesian2_default.pack(v3, arraybuffer, j);
changed = true;
}
j += 2;
}
if (changed) {
this._gl.uniform2iv(this._location, arraybuffer);
}
};
function UniformArrayIntVec3(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Int32Array(length2 * 3);
this._gl = gl;
this._location = locations[0];
}
UniformArrayIntVec3.prototype.set = function() {
const value = this.value;
const length2 = value.length;
const arraybuffer = this._value;
let changed = false;
let j = 0;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
if (!Cartesian3_default.equalsArray(v3, arraybuffer, j)) {
Cartesian3_default.pack(v3, arraybuffer, j);
changed = true;
}
j += 3;
}
if (changed) {
this._gl.uniform3iv(this._location, arraybuffer);
}
};
function UniformArrayIntVec4(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Int32Array(length2 * 4);
this._gl = gl;
this._location = locations[0];
}
UniformArrayIntVec4.prototype.set = function() {
const value = this.value;
const length2 = value.length;
const arraybuffer = this._value;
let changed = false;
let j = 0;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
if (!Cartesian4_default.equalsArray(v3, arraybuffer, j)) {
Cartesian4_default.pack(v3, arraybuffer, j);
changed = true;
}
j += 4;
}
if (changed) {
this._gl.uniform4iv(this._location, arraybuffer);
}
};
function UniformArrayMat2(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Float32Array(length2 * 4);
this._gl = gl;
this._location = locations[0];
}
UniformArrayMat2.prototype.set = function() {
const value = this.value;
const length2 = value.length;
const arraybuffer = this._value;
let changed = false;
let j = 0;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
if (!Matrix2_default.equalsArray(v3, arraybuffer, j)) {
Matrix2_default.pack(v3, arraybuffer, j);
changed = true;
}
j += 4;
}
if (changed) {
this._gl.uniformMatrix2fv(this._location, false, arraybuffer);
}
};
function UniformArrayMat3(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Float32Array(length2 * 9);
this._gl = gl;
this._location = locations[0];
}
UniformArrayMat3.prototype.set = function() {
const value = this.value;
const length2 = value.length;
const arraybuffer = this._value;
let changed = false;
let j = 0;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
if (!Matrix3_default.equalsArray(v3, arraybuffer, j)) {
Matrix3_default.pack(v3, arraybuffer, j);
changed = true;
}
j += 9;
}
if (changed) {
this._gl.uniformMatrix3fv(this._location, false, arraybuffer);
}
};
function UniformArrayMat4(gl, activeUniform, uniformName, locations) {
const length2 = locations.length;
this.name = uniformName;
this.value = new Array(length2);
this._value = new Float32Array(length2 * 16);
this._gl = gl;
this._location = locations[0];
}
UniformArrayMat4.prototype.set = function() {
const value = this.value;
const length2 = value.length;
const arraybuffer = this._value;
let changed = false;
let j = 0;
for (let i = 0; i < length2; ++i) {
const v3 = value[i];
if (!Matrix4_default.equalsArray(v3, arraybuffer, j)) {
Matrix4_default.pack(v3, arraybuffer, j);
changed = true;
}
j += 16;
}
if (changed) {
this._gl.uniformMatrix4fv(this._location, false, arraybuffer);
}
};
var createUniformArray_default = createUniformArray;
// packages/engine/Source/Renderer/ShaderProgram.js
var nextShaderProgramId = 0;
function ShaderProgram(options) {
let vertexShaderText = options.vertexShaderText;
let fragmentShaderText = options.fragmentShaderText;
if (typeof spector !== "undefined") {
vertexShaderText = vertexShaderText.replace(/^#line/gm, "//#line");
fragmentShaderText = fragmentShaderText.replace(/^#line/gm, "//#line");
}
const modifiedFS = handleUniformPrecisionMismatches(
vertexShaderText,
fragmentShaderText
);
this._gl = options.gl;
this._logShaderCompilation = options.logShaderCompilation;
this._debugShaders = options.debugShaders;
this._attributeLocations = options.attributeLocations;
this._program = void 0;
this._numberOfVertexAttributes = void 0;
this._vertexAttributes = void 0;
this._uniformsByName = void 0;
this._uniforms = void 0;
this._automaticUniforms = void 0;
this._manualUniforms = void 0;
this._duplicateUniformNames = modifiedFS.duplicateUniformNames;
this._cachedShader = void 0;
this.maximumTextureUnitIndex = void 0;
this._vertexShaderSource = options.vertexShaderSource;
this._vertexShaderText = options.vertexShaderText;
this._fragmentShaderSource = options.fragmentShaderSource;
this._fragmentShaderText = modifiedFS.fragmentShaderText;
this.id = nextShaderProgramId++;
}
ShaderProgram.fromCache = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.defined("options.context", options.context);
return options.context.shaderCache.getShaderProgram(options);
};
ShaderProgram.replaceCache = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.defined("options.context", options.context);
return options.context.shaderCache.replaceShaderProgram(options);
};
Object.defineProperties(ShaderProgram.prototype, {
/**
* GLSL source for the shader program's vertex shader.
* @memberof ShaderProgram.prototype
*
* @type {ShaderSource}
* @readonly
*/
vertexShaderSource: {
get: function() {
return this._vertexShaderSource;
}
},
/**
* GLSL source for the shader program's fragment shader.
* @memberof ShaderProgram.prototype
*
* @type {ShaderSource}
* @readonly
*/
fragmentShaderSource: {
get: function() {
return this._fragmentShaderSource;
}
},
vertexAttributes: {
get: function() {
initialize2(this);
return this._vertexAttributes;
}
},
numberOfVertexAttributes: {
get: function() {
initialize2(this);
return this._numberOfVertexAttributes;
}
},
allUniforms: {
get: function() {
initialize2(this);
return this._uniformsByName;
}
}
});
function extractUniforms(shaderText) {
const uniformNames = [];
const uniformLines = shaderText.match(/uniform.*?(?![^{]*})(?=[=\[;])/g);
if (defined_default(uniformLines)) {
const len = uniformLines.length;
for (let i = 0; i < len; i++) {
const line = uniformLines[i].trim();
const name = line.slice(line.lastIndexOf(" ") + 1);
uniformNames.push(name);
}
}
return uniformNames;
}
function handleUniformPrecisionMismatches(vertexShaderText, fragmentShaderText) {
const duplicateUniformNames = {};
if (!ContextLimits_default.highpFloatSupported || !ContextLimits_default.highpIntSupported) {
let i, j;
let uniformName;
let duplicateName;
const vertexShaderUniforms = extractUniforms(vertexShaderText);
const fragmentShaderUniforms = extractUniforms(fragmentShaderText);
const vertexUniformsCount = vertexShaderUniforms.length;
const fragmentUniformsCount = fragmentShaderUniforms.length;
for (i = 0; i < vertexUniformsCount; i++) {
for (j = 0; j < fragmentUniformsCount; j++) {
if (vertexShaderUniforms[i] === fragmentShaderUniforms[j]) {
uniformName = vertexShaderUniforms[i];
duplicateName = `czm_mediump_${uniformName}`;
const re = new RegExp(`${uniformName}\\b`, "g");
fragmentShaderText = fragmentShaderText.replace(re, duplicateName);
duplicateUniformNames[duplicateName] = uniformName;
}
}
}
}
return {
fragmentShaderText,
duplicateUniformNames
};
}
var consolePrefix = "[Cesium WebGL] ";
function createAndLinkProgram(gl, shader) {
const vsSource = shader._vertexShaderText;
const fsSource = shader._fragmentShaderText;
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vsSource);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fsSource);
gl.compileShader(fragmentShader);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
const attributeLocations8 = shader._attributeLocations;
if (defined_default(attributeLocations8)) {
for (const attribute in attributeLocations8) {
if (attributeLocations8.hasOwnProperty(attribute)) {
gl.bindAttribLocation(
program,
attributeLocations8[attribute],
attribute
);
}
}
}
gl.linkProgram(program);
let log;
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
if (shader._logShaderCompilation) {
log = gl.getShaderInfoLog(vertexShader);
if (defined_default(log) && log.length > 0) {
console.log(`${consolePrefix}Vertex shader compile log: ${log}`);
}
log = gl.getShaderInfoLog(fragmentShader);
if (defined_default(log) && log.length > 0) {
console.log(`${consolePrefix}Fragment shader compile log: ${log}`);
}
log = gl.getProgramInfoLog(program);
if (defined_default(log) && log.length > 0) {
console.log(`${consolePrefix}Shader program link log: ${log}`);
}
}
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);
return program;
}
let errorMessage;
const debugShaders = shader._debugShaders;
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
log = gl.getShaderInfoLog(fragmentShader);
console.error(`${consolePrefix}Fragment shader compile log: ${log}`);
console.error(`${consolePrefix} Fragment shader source:
${fsSource}`);
errorMessage = `Fragment shader failed to compile. Compile log: ${log}`;
} else if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
log = gl.getShaderInfoLog(vertexShader);
console.error(`${consolePrefix}Vertex shader compile log: ${log}`);
console.error(`${consolePrefix} Vertex shader source:
${vsSource}`);
errorMessage = `Vertex shader failed to compile. Compile log: ${log}`;
} else {
log = gl.getProgramInfoLog(program);
console.error(`${consolePrefix}Shader program link log: ${log}`);
logTranslatedSource(vertexShader, "vertex");
logTranslatedSource(fragmentShader, "fragment");
errorMessage = `Program failed to link. Link log: ${log}`;
}
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);
gl.deleteProgram(program);
throw new RuntimeError_default(errorMessage);
function logTranslatedSource(compiledShader, name) {
if (!defined_default(debugShaders)) {
return;
}
const translation3 = debugShaders.getTranslatedShaderSource(compiledShader);
if (translation3 === "") {
console.error(`${consolePrefix}${name} shader translation failed.`);
return;
}
console.error(
`${consolePrefix}Translated ${name} shaderSource:
${translation3}`
);
}
}
function findVertexAttributes(gl, program, numberOfAttributes2) {
const attributes = {};
for (let i = 0; i < numberOfAttributes2; ++i) {
const attr = gl.getActiveAttrib(program, i);
const location2 = gl.getAttribLocation(program, attr.name);
attributes[attr.name] = {
name: attr.name,
type: attr.type,
index: location2
};
}
return attributes;
}
function findUniforms(gl, program) {
const uniformsByName = {};
const uniforms = [];
const samplerUniforms = [];
const numberOfUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
for (let i = 0; i < numberOfUniforms; ++i) {
const activeUniform = gl.getActiveUniform(program, i);
const suffix = "[0]";
const uniformName = activeUniform.name.indexOf(
suffix,
activeUniform.name.length - suffix.length
) !== -1 ? activeUniform.name.slice(0, activeUniform.name.length - 3) : activeUniform.name;
if (uniformName.indexOf("gl_") !== 0) {
if (activeUniform.name.indexOf("[") < 0) {
const location2 = gl.getUniformLocation(program, uniformName);
if (location2 !== null) {
const uniform = createUniform_default(
gl,
activeUniform,
uniformName,
location2
);
uniformsByName[uniformName] = uniform;
uniforms.push(uniform);
if (uniform._setSampler) {
samplerUniforms.push(uniform);
}
}
} else {
let uniformArray;
let locations;
let value;
let loc;
const indexOfBracket = uniformName.indexOf("[");
if (indexOfBracket >= 0) {
uniformArray = uniformsByName[uniformName.slice(0, indexOfBracket)];
if (!defined_default(uniformArray)) {
continue;
}
locations = uniformArray._locations;
if (locations.length <= 1) {
value = uniformArray.value;
loc = gl.getUniformLocation(program, uniformName);
if (loc !== null) {
locations.push(loc);
value.push(gl.getUniform(program, loc));
}
}
} else {
locations = [];
for (let j = 0; j < activeUniform.size; ++j) {
loc = gl.getUniformLocation(program, `${uniformName}[${j}]`);
if (loc !== null) {
locations.push(loc);
}
}
uniformArray = createUniformArray_default(
gl,
activeUniform,
uniformName,
locations
);
uniformsByName[uniformName] = uniformArray;
uniforms.push(uniformArray);
if (uniformArray._setSampler) {
samplerUniforms.push(uniformArray);
}
}
}
}
}
return {
uniformsByName,
uniforms,
samplerUniforms
};
}
function partitionUniforms(shader, uniforms) {
const automaticUniforms = [];
const manualUniforms = [];
for (const uniform in uniforms) {
if (uniforms.hasOwnProperty(uniform)) {
const uniformObject = uniforms[uniform];
let uniformName = uniform;
const duplicateUniform = shader._duplicateUniformNames[uniformName];
if (defined_default(duplicateUniform)) {
uniformObject.name = duplicateUniform;
uniformName = duplicateUniform;
}
const automaticUniform = AutomaticUniforms_default[uniformName];
if (defined_default(automaticUniform)) {
automaticUniforms.push({
uniform: uniformObject,
automaticUniform
});
} else {
manualUniforms.push(uniformObject);
}
}
}
return {
automaticUniforms,
manualUniforms
};
}
function setSamplerUniforms(gl, program, samplerUniforms) {
gl.useProgram(program);
let textureUnitIndex = 0;
const length2 = samplerUniforms.length;
for (let i = 0; i < length2; ++i) {
textureUnitIndex = samplerUniforms[i]._setSampler(textureUnitIndex);
}
gl.useProgram(null);
return textureUnitIndex;
}
function initialize2(shader) {
if (defined_default(shader._program)) {
return;
}
reinitialize(shader);
}
function reinitialize(shader) {
const oldProgram = shader._program;
const gl = shader._gl;
const program = createAndLinkProgram(gl, shader, shader._debugShaders);
const numberOfVertexAttributes = gl.getProgramParameter(
program,
gl.ACTIVE_ATTRIBUTES
);
const uniforms = findUniforms(gl, program);
const partitionedUniforms = partitionUniforms(
shader,
uniforms.uniformsByName
);
shader._program = program;
shader._numberOfVertexAttributes = numberOfVertexAttributes;
shader._vertexAttributes = findVertexAttributes(
gl,
program,
numberOfVertexAttributes
);
shader._uniformsByName = uniforms.uniformsByName;
shader._uniforms = uniforms.uniforms;
shader._automaticUniforms = partitionedUniforms.automaticUniforms;
shader._manualUniforms = partitionedUniforms.manualUniforms;
shader.maximumTextureUnitIndex = setSamplerUniforms(
gl,
program,
uniforms.samplerUniforms
);
if (oldProgram) {
shader._gl.deleteProgram(oldProgram);
}
if (typeof spector !== "undefined") {
shader._program.__SPECTOR_rebuildProgram = function(vertexSourceCode, fragmentSourceCode, onCompiled, onError) {
const originalVS = shader._vertexShaderText;
const originalFS = shader._fragmentShaderText;
const regex = / ! = /g;
shader._vertexShaderText = vertexSourceCode.replace(regex, " != ");
shader._fragmentShaderText = fragmentSourceCode.replace(regex, " != ");
try {
reinitialize(shader);
onCompiled(shader._program);
} catch (e) {
shader._vertexShaderText = originalVS;
shader._fragmentShaderText = originalFS;
const errorMatcher = /(?:Compile|Link) error: ([^]*)/;
const match = errorMatcher.exec(e.message);
if (match) {
onError(match[1]);
} else {
onError(e.message);
}
}
};
}
}
ShaderProgram.prototype._bind = function() {
initialize2(this);
this._gl.useProgram(this._program);
};
ShaderProgram.prototype._setUniforms = function(uniformMap2, uniformState, validate2) {
let len;
let i;
if (defined_default(uniformMap2)) {
const manualUniforms = this._manualUniforms;
len = manualUniforms.length;
for (i = 0; i < len; ++i) {
const mu = manualUniforms[i];
if (!defined_default(uniformMap2[mu.name])) {
throw new DeveloperError_default(`Unknown uniform: ${mu.name}`);
}
mu.value = uniformMap2[mu.name]();
}
}
const automaticUniforms = this._automaticUniforms;
len = automaticUniforms.length;
for (i = 0; i < len; ++i) {
const au = automaticUniforms[i];
au.uniform.value = au.automaticUniform.getValue(uniformState);
}
const uniforms = this._uniforms;
len = uniforms.length;
for (i = 0; i < len; ++i) {
uniforms[i].set();
}
if (validate2) {
const gl = this._gl;
const program = this._program;
gl.validateProgram(program);
if (!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) {
throw new DeveloperError_default(
`Program validation failed. Program info log: ${gl.getProgramInfoLog(
program
)}`
);
}
}
};
ShaderProgram.prototype.isDestroyed = function() {
return false;
};
ShaderProgram.prototype.destroy = function() {
this._cachedShader.cache.releaseShaderProgram(this);
return void 0;
};
ShaderProgram.prototype.finalDestroy = function() {
this._gl.deleteProgram(this._program);
return destroyObject_default(this);
};
var ShaderProgram_default = ShaderProgram;
// packages/engine/Source/Renderer/ComputeEngine.js
function ComputeEngine(context) {
this._context = context;
}
var renderStateScratch;
var drawCommandScratch = new DrawCommand_default({
primitiveType: PrimitiveType_default.TRIANGLES
});
var clearCommandScratch = new ClearCommand_default({
color: new Color_default(0, 0, 0, 0)
});
function createFramebuffer(context, outputTexture) {
return new Framebuffer_default({
context,
colorTextures: [outputTexture],
destroyAttachments: false
});
}
function createViewportQuadShader(context, fragmentShaderSource) {
return ShaderProgram_default.fromCache({
context,
vertexShaderSource: ViewportQuadVS_default,
fragmentShaderSource,
attributeLocations: {
position: 0,
textureCoordinates: 1
}
});
}
function createRenderState(width, height) {
if (!defined_default(renderStateScratch) || renderStateScratch.viewport.width !== width || renderStateScratch.viewport.height !== height) {
renderStateScratch = RenderState_default.fromCache({
viewport: new BoundingRectangle_default(0, 0, width, height)
});
}
return renderStateScratch;
}
ComputeEngine.prototype.execute = function(computeCommand) {
Check_default.defined("computeCommand", computeCommand);
if (defined_default(computeCommand.preExecute)) {
computeCommand.preExecute(computeCommand);
}
if (!defined_default(computeCommand.fragmentShaderSource) && !defined_default(computeCommand.shaderProgram)) {
throw new DeveloperError_default(
"computeCommand.fragmentShaderSource or computeCommand.shaderProgram is required."
);
}
Check_default.defined("computeCommand.outputTexture", computeCommand.outputTexture);
const outputTexture = computeCommand.outputTexture;
const width = outputTexture.width;
const height = outputTexture.height;
const context = this._context;
const vertexArray = defined_default(computeCommand.vertexArray) ? computeCommand.vertexArray : context.getViewportQuadVertexArray();
const shaderProgram = defined_default(computeCommand.shaderProgram) ? computeCommand.shaderProgram : createViewportQuadShader(context, computeCommand.fragmentShaderSource);
const framebuffer = createFramebuffer(context, outputTexture);
const renderState = createRenderState(width, height);
const uniformMap2 = computeCommand.uniformMap;
const clearCommand = clearCommandScratch;
clearCommand.framebuffer = framebuffer;
clearCommand.renderState = renderState;
clearCommand.execute(context);
const drawCommand = drawCommandScratch;
drawCommand.vertexArray = vertexArray;
drawCommand.renderState = renderState;
drawCommand.shaderProgram = shaderProgram;
drawCommand.uniformMap = uniformMap2;
drawCommand.framebuffer = framebuffer;
drawCommand.execute(context);
framebuffer.destroy();
if (!computeCommand.persists) {
shaderProgram.destroy();
if (defined_default(computeCommand.vertexArray)) {
vertexArray.destroy();
}
}
if (defined_default(computeCommand.postExecute)) {
computeCommand.postExecute(outputTexture);
}
};
ComputeEngine.prototype.isDestroyed = function() {
return false;
};
ComputeEngine.prototype.destroy = function() {
return destroyObject_default(this);
};
var ComputeEngine_default = ComputeEngine;
// packages/engine/Source/Renderer/Context.js
var import_InlineWorkers271 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/ComponentDatatype.js
var import_InlineWorkers86 = __toESM(require_InlineWorkers(), 1);
var ComponentDatatype = {
/**
* 8-bit signed byte corresponding to gl.BYTE and the type
* of an element in Int8Array.
*
* @type {number}
* @constant
*/
BYTE: WebGLConstants_default.BYTE,
/**
* 8-bit unsigned byte corresponding to UNSIGNED_BYTE and the type
* of an element in Uint8Array.
*
* @type {number}
* @constant
*/
UNSIGNED_BYTE: WebGLConstants_default.UNSIGNED_BYTE,
/**
* 16-bit signed short corresponding to SHORT and the type
* of an element in Int16Array.
*
* @type {number}
* @constant
*/
SHORT: WebGLConstants_default.SHORT,
/**
* 16-bit unsigned short corresponding to UNSIGNED_SHORT and the type
* of an element in Uint16Array.
*
* @type {number}
* @constant
*/
UNSIGNED_SHORT: WebGLConstants_default.UNSIGNED_SHORT,
/**
* 32-bit signed int corresponding to INT and the type
* of an element in Int32Array.
*
* @memberOf ComponentDatatype
*
* @type {number}
* @constant
*/
INT: WebGLConstants_default.INT,
/**
* 32-bit unsigned int corresponding to UNSIGNED_INT and the type
* of an element in Uint32Array.
*
* @memberOf ComponentDatatype
*
* @type {number}
* @constant
*/
UNSIGNED_INT: WebGLConstants_default.UNSIGNED_INT,
/**
* 32-bit floating-point corresponding to FLOAT and the type
* of an element in Float32Array.
*
* @type {number}
* @constant
*/
FLOAT: WebGLConstants_default.FLOAT,
/**
* 64-bit floating-point corresponding to gl.DOUBLE (in Desktop OpenGL;
* this is not supported in WebGL, and is emulated in Cesium via {@link GeometryPipeline.encodeAttribute})
* and the type of an element in Float64Array.
*
* @memberOf ComponentDatatype
*
* @type {number}
* @constant
* @default 0x140A
*/
DOUBLE: WebGLConstants_default.DOUBLE
};
ComponentDatatype.getSizeInBytes = function(componentDatatype) {
if (!defined_default(componentDatatype)) {
throw new DeveloperError_default("value is required.");
}
switch (componentDatatype) {
case ComponentDatatype.BYTE:
return Int8Array.BYTES_PER_ELEMENT;
case ComponentDatatype.UNSIGNED_BYTE:
return Uint8Array.BYTES_PER_ELEMENT;
case ComponentDatatype.SHORT:
return Int16Array.BYTES_PER_ELEMENT;
case ComponentDatatype.UNSIGNED_SHORT:
return Uint16Array.BYTES_PER_ELEMENT;
case ComponentDatatype.INT:
return Int32Array.BYTES_PER_ELEMENT;
case ComponentDatatype.UNSIGNED_INT:
return Uint32Array.BYTES_PER_ELEMENT;
case ComponentDatatype.FLOAT:
return Float32Array.BYTES_PER_ELEMENT;
case ComponentDatatype.DOUBLE:
return Float64Array.BYTES_PER_ELEMENT;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("componentDatatype is not a valid value.");
}
};
ComponentDatatype.fromTypedArray = function(array) {
if (array instanceof Int8Array) {
return ComponentDatatype.BYTE;
}
if (array instanceof Uint8Array) {
return ComponentDatatype.UNSIGNED_BYTE;
}
if (array instanceof Int16Array) {
return ComponentDatatype.SHORT;
}
if (array instanceof Uint16Array) {
return ComponentDatatype.UNSIGNED_SHORT;
}
if (array instanceof Int32Array) {
return ComponentDatatype.INT;
}
if (array instanceof Uint32Array) {
return ComponentDatatype.UNSIGNED_INT;
}
if (array instanceof Float32Array) {
return ComponentDatatype.FLOAT;
}
if (array instanceof Float64Array) {
return ComponentDatatype.DOUBLE;
}
throw new DeveloperError_default(
"array must be an Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, or Float64Array."
);
};
ComponentDatatype.validate = function(componentDatatype) {
return defined_default(componentDatatype) && (componentDatatype === ComponentDatatype.BYTE || componentDatatype === ComponentDatatype.UNSIGNED_BYTE || componentDatatype === ComponentDatatype.SHORT || componentDatatype === ComponentDatatype.UNSIGNED_SHORT || componentDatatype === ComponentDatatype.INT || componentDatatype === ComponentDatatype.UNSIGNED_INT || componentDatatype === ComponentDatatype.FLOAT || componentDatatype === ComponentDatatype.DOUBLE);
};
ComponentDatatype.createTypedArray = function(componentDatatype, valuesOrLength) {
if (!defined_default(componentDatatype)) {
throw new DeveloperError_default("componentDatatype is required.");
}
if (!defined_default(valuesOrLength)) {
throw new DeveloperError_default("valuesOrLength is required.");
}
switch (componentDatatype) {
case ComponentDatatype.BYTE:
return new Int8Array(valuesOrLength);
case ComponentDatatype.UNSIGNED_BYTE:
return new Uint8Array(valuesOrLength);
case ComponentDatatype.SHORT:
return new Int16Array(valuesOrLength);
case ComponentDatatype.UNSIGNED_SHORT:
return new Uint16Array(valuesOrLength);
case ComponentDatatype.INT:
return new Int32Array(valuesOrLength);
case ComponentDatatype.UNSIGNED_INT:
return new Uint32Array(valuesOrLength);
case ComponentDatatype.FLOAT:
return new Float32Array(valuesOrLength);
case ComponentDatatype.DOUBLE:
return new Float64Array(valuesOrLength);
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("componentDatatype is not a valid value.");
}
};
ComponentDatatype.createArrayBufferView = function(componentDatatype, buffer2, byteOffset, length2) {
if (!defined_default(componentDatatype)) {
throw new DeveloperError_default("componentDatatype is required.");
}
if (!defined_default(buffer2)) {
throw new DeveloperError_default("buffer is required.");
}
byteOffset = byteOffset ?? 0;
length2 = length2 ?? (buffer2.byteLength - byteOffset) / ComponentDatatype.getSizeInBytes(componentDatatype);
switch (componentDatatype) {
case ComponentDatatype.BYTE:
return new Int8Array(buffer2, byteOffset, length2);
case ComponentDatatype.UNSIGNED_BYTE:
return new Uint8Array(buffer2, byteOffset, length2);
case ComponentDatatype.SHORT:
return new Int16Array(buffer2, byteOffset, length2);
case ComponentDatatype.UNSIGNED_SHORT:
return new Uint16Array(buffer2, byteOffset, length2);
case ComponentDatatype.INT:
return new Int32Array(buffer2, byteOffset, length2);
case ComponentDatatype.UNSIGNED_INT:
return new Uint32Array(buffer2, byteOffset, length2);
case ComponentDatatype.FLOAT:
return new Float32Array(buffer2, byteOffset, length2);
case ComponentDatatype.DOUBLE:
return new Float64Array(buffer2, byteOffset, length2);
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("componentDatatype is not a valid value.");
}
};
ComponentDatatype.fromName = function(name) {
switch (name) {
case "BYTE":
return ComponentDatatype.BYTE;
case "UNSIGNED_BYTE":
return ComponentDatatype.UNSIGNED_BYTE;
case "SHORT":
return ComponentDatatype.SHORT;
case "UNSIGNED_SHORT":
return ComponentDatatype.UNSIGNED_SHORT;
case "INT":
return ComponentDatatype.INT;
case "UNSIGNED_INT":
return ComponentDatatype.UNSIGNED_INT;
case "FLOAT":
return ComponentDatatype.FLOAT;
case "DOUBLE":
return ComponentDatatype.DOUBLE;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("name is not a valid value.");
}
};
var ComponentDatatype_default = Object.freeze(ComponentDatatype);
// packages/engine/Source/Core/Geometry.js
var import_InlineWorkers88 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/GeometryType.js
var import_InlineWorkers87 = __toESM(require_InlineWorkers(), 1);
var GeometryType = {
NONE: 0,
TRIANGLES: 1,
LINES: 2,
POLYLINES: 3
};
var GeometryType_default = Object.freeze(GeometryType);
// packages/engine/Source/Core/Geometry.js
function Geometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("options.attributes", options.attributes);
this.attributes = options.attributes;
this.indices = options.indices;
this.primitiveType = options.primitiveType ?? PrimitiveType_default.TRIANGLES;
this.boundingSphere = options.boundingSphere;
this.geometryType = options.geometryType ?? GeometryType_default.NONE;
this.boundingSphereCV = options.boundingSphereCV;
this.offsetAttribute = options.offsetAttribute;
}
Geometry.computeNumberOfVertices = function(geometry) {
Check_default.typeOf.object("geometry", geometry);
let numberOfVertices = -1;
for (const property in geometry.attributes) {
if (geometry.attributes.hasOwnProperty(property) && defined_default(geometry.attributes[property]) && defined_default(geometry.attributes[property].values)) {
const attribute = geometry.attributes[property];
const num = attribute.values.length / attribute.componentsPerAttribute;
if (numberOfVertices !== num && numberOfVertices !== -1) {
throw new DeveloperError_default(
"All attribute lists must have the same number of attributes."
);
}
numberOfVertices = num;
}
}
return numberOfVertices;
};
var rectangleCenterScratch = new Cartographic_default();
var enuCenterScratch = new Cartesian3_default();
var fixedFrameToEnuScratch = new Matrix4_default();
var boundingRectanglePointsCartographicScratch = [
new Cartographic_default(),
new Cartographic_default(),
new Cartographic_default()
];
var boundingRectanglePointsEnuScratch = [
new Cartesian2_default(),
new Cartesian2_default(),
new Cartesian2_default()
];
var points2DScratch = [new Cartesian2_default(), new Cartesian2_default(), new Cartesian2_default()];
var pointEnuScratch = new Cartesian3_default();
var enuRotationScratch = new Quaternion_default();
var enuRotationMatrixScratch = new Matrix4_default();
var rotation2DScratch = new Matrix2_default();
Geometry._textureCoordinateRotationPoints = function(positions, stRotation, ellipsoid, boundingRectangle) {
let i;
const rectangleCenter = Rectangle_default.center(
boundingRectangle,
rectangleCenterScratch
);
const enuCenter = Cartographic_default.toCartesian(
rectangleCenter,
ellipsoid,
enuCenterScratch
);
const enuToFixedFrame = Transforms_default.eastNorthUpToFixedFrame(
enuCenter,
ellipsoid,
fixedFrameToEnuScratch
);
const fixedFrameToEnu = Matrix4_default.inverse(
enuToFixedFrame,
fixedFrameToEnuScratch
);
const boundingPointsEnu = boundingRectanglePointsEnuScratch;
const boundingPointsCarto = boundingRectanglePointsCartographicScratch;
boundingPointsCarto[0].longitude = boundingRectangle.west;
boundingPointsCarto[0].latitude = boundingRectangle.south;
boundingPointsCarto[1].longitude = boundingRectangle.west;
boundingPointsCarto[1].latitude = boundingRectangle.north;
boundingPointsCarto[2].longitude = boundingRectangle.east;
boundingPointsCarto[2].latitude = boundingRectangle.south;
let posEnu = pointEnuScratch;
for (i = 0; i < 3; i++) {
Cartographic_default.toCartesian(boundingPointsCarto[i], ellipsoid, posEnu);
posEnu = Matrix4_default.multiplyByPointAsVector(fixedFrameToEnu, posEnu, posEnu);
boundingPointsEnu[i].x = posEnu.x;
boundingPointsEnu[i].y = posEnu.y;
}
const rotation = Quaternion_default.fromAxisAngle(
Cartesian3_default.UNIT_Z,
-stRotation,
enuRotationScratch
);
const textureMatrix = Matrix3_default.fromQuaternion(
rotation,
enuRotationMatrixScratch
);
const positionsLength = positions.length;
let enuMinX = Number.POSITIVE_INFINITY;
let enuMinY = Number.POSITIVE_INFINITY;
let enuMaxX = Number.NEGATIVE_INFINITY;
let enuMaxY = Number.NEGATIVE_INFINITY;
for (i = 0; i < positionsLength; i++) {
posEnu = Matrix4_default.multiplyByPointAsVector(
fixedFrameToEnu,
positions[i],
posEnu
);
posEnu = Matrix3_default.multiplyByVector(textureMatrix, posEnu, posEnu);
enuMinX = Math.min(enuMinX, posEnu.x);
enuMinY = Math.min(enuMinY, posEnu.y);
enuMaxX = Math.max(enuMaxX, posEnu.x);
enuMaxY = Math.max(enuMaxY, posEnu.y);
}
const toDesiredInComputed = Matrix2_default.fromRotation(
stRotation,
rotation2DScratch
);
const points2D = points2DScratch;
points2D[0].x = enuMinX;
points2D[0].y = enuMinY;
points2D[1].x = enuMinX;
points2D[1].y = enuMaxY;
points2D[2].x = enuMaxX;
points2D[2].y = enuMinY;
const boundingEnuMin = boundingPointsEnu[0];
const boundingPointsWidth = boundingPointsEnu[2].x - boundingEnuMin.x;
const boundingPointsHeight = boundingPointsEnu[1].y - boundingEnuMin.y;
for (i = 0; i < 3; i++) {
const point2D = points2D[i];
Matrix2_default.multiplyByVector(toDesiredInComputed, point2D, point2D);
point2D.x = (point2D.x - boundingEnuMin.x) / boundingPointsWidth;
point2D.y = (point2D.y - boundingEnuMin.y) / boundingPointsHeight;
}
const minXYCorner = points2D[0];
const maxYCorner = points2D[1];
const maxXCorner = points2D[2];
const result = new Array(6);
Cartesian2_default.pack(minXYCorner, result);
Cartesian2_default.pack(maxYCorner, result, 2);
Cartesian2_default.pack(maxXCorner, result, 4);
return result;
};
var Geometry_default = Geometry;
// packages/engine/Source/Core/GeometryAttribute.js
var import_InlineWorkers89 = __toESM(require_InlineWorkers(), 1);
function GeometryAttribute(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
if (!defined_default(options.componentDatatype)) {
throw new DeveloperError_default("options.componentDatatype is required.");
}
if (!defined_default(options.componentsPerAttribute)) {
throw new DeveloperError_default("options.componentsPerAttribute is required.");
}
if (options.componentsPerAttribute < 1 || options.componentsPerAttribute > 4) {
throw new DeveloperError_default(
"options.componentsPerAttribute must be between 1 and 4."
);
}
if (!defined_default(options.values)) {
throw new DeveloperError_default("options.values is required.");
}
this.componentDatatype = options.componentDatatype;
this.componentsPerAttribute = options.componentsPerAttribute;
this.normalize = options.normalize ?? false;
this.values = options.values;
}
var GeometryAttribute_default = GeometryAttribute;
// packages/engine/Source/Core/loadKTX2.js
var import_InlineWorkers93 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/KTX2Transcoder.js
var import_InlineWorkers92 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/CompressedTextureBuffer.js
var import_InlineWorkers90 = __toESM(require_InlineWorkers(), 1);
function CompressedTextureBuffer(internalFormat, pixelDatatype, width, height, buffer2) {
this._format = internalFormat;
this._datatype = pixelDatatype;
this._width = width;
this._height = height;
this._buffer = buffer2;
}
Object.defineProperties(CompressedTextureBuffer.prototype, {
/**
* The format of the compressed texture.
* @type {PixelFormat}
* @readonly
* @memberof CompressedTextureBuffer.prototype
*/
internalFormat: {
get: function() {
return this._format;
}
},
/**
* The datatype of the compressed texture.
* @type {PixelDatatype}
* @readonly
* @memberof CompressedTextureBuffer.prototype
*/
pixelDatatype: {
get: function() {
return this._datatype;
}
},
/**
* The width of the texture.
* @type {number}
* @readonly
* @memberof CompressedTextureBuffer.prototype
*/
width: {
get: function() {
return this._width;
}
},
/**
* The height of the texture.
* @type {number}
* @readonly
* @memberof CompressedTextureBuffer.prototype
*/
height: {
get: function() {
return this._height;
}
},
/**
* The compressed texture buffer.
* @type {Uint8Array}
* @readonly
* @memberof CompressedTextureBuffer.prototype
*/
bufferView: {
get: function() {
return this._buffer;
}
},
/**
* The compressed texture buffer. Alias for bufferView.
* @type {Uint8Array}
* @readonly
* @memberof CompressedTextureBuffer.prototype
*/
arrayBufferView: {
get: function() {
return this._buffer;
}
}
});
CompressedTextureBuffer.clone = function(object2) {
if (!defined_default(object2)) {
return void 0;
}
return new CompressedTextureBuffer(
object2._format,
object2._datatype,
object2._width,
object2._height,
object2._buffer
);
};
CompressedTextureBuffer.prototype.clone = function() {
return CompressedTextureBuffer.clone(this);
};
var CompressedTextureBuffer_default = CompressedTextureBuffer;
// packages/engine/Source/Core/TaskProcessor.js
var import_InlineWorkers91 = __toESM(require_InlineWorkers(), 1);
var import_urijs7 = __toESM(require_URI(), 1);
function canTransferArrayBuffer() {
if (!defined_default(TaskProcessor._canTransferArrayBuffer)) {
const worker = createWorker("transferTypedArrayTest");
worker.postMessage = worker.webkitPostMessage ?? worker.postMessage;
const value = 99;
const array = new Int8Array([value]);
try {
worker.postMessage(
{
array
},
[array.buffer]
);
} catch (e) {
TaskProcessor._canTransferArrayBuffer = false;
return TaskProcessor._canTransferArrayBuffer;
}
TaskProcessor._canTransferArrayBuffer = new Promise((resolve2) => {
worker.onmessage = function(event) {
const array2 = event.data.array;
const result = defined_default(array2) && array2[0] === value;
resolve2(result);
worker.terminate();
TaskProcessor._canTransferArrayBuffer = result;
};
});
}
return TaskProcessor._canTransferArrayBuffer;
}
var taskCompletedEvent = new Event_default();
function urlFromScript(script) {
let blob;
try {
blob = new Blob([script], {
type: "application/javascript"
});
} catch (e) {
const BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
const blobBuilder = new BlobBuilder();
blobBuilder.append(script);
blob = blobBuilder.getBlob("application/javascript");
}
const URL2 = window.URL || window.webkitURL;
return URL2.createObjectURL(blob);
}
function createWorker(url2) {
const uri = new import_urijs7.default(url2);
const isUri = uri.scheme().length !== 0 && uri.fragment().length === 0;
const moduleID = url2.replace(/\.js$/, "");
const options = {};
let workerPath;
let crossOriginUrl;
if (isCrossOriginUrl_default(url2)) {
crossOriginUrl = url2;
} else if (!isUri) {
const moduleAbsoluteUrl = buildModuleUrl_default(
`${TaskProcessor._workerModulePrefix}/${moduleID}.js`
);
if (isCrossOriginUrl_default(moduleAbsoluteUrl)) {
crossOriginUrl = moduleAbsoluteUrl;
}
}
if (crossOriginUrl) {
const script = `import "${crossOriginUrl}";`;
workerPath = urlFromScript(script);
options.type = "module";
return new Worker(workerPath, options);
}
if (!isUri && typeof CESIUM_WORKERS !== "undefined") {
const script = `
importScripts("${urlFromScript(CESIUM_WORKERS)}");
CesiumWorkers["${moduleID}"]();
`;
workerPath = urlFromScript(script);
return new Worker(workerPath, options);
}
workerPath = url2;
if (!isUri) {
workerPath = buildModuleUrl_default(
`${TaskProcessor._workerModulePrefix + moduleID}.js`
);
}
if (!FeatureDetection_default.supportsEsmWebWorkers()) {
throw new RuntimeError_default(
"This browser is not supported. Please update your browser to continue."
);
}
options.type = "module";
return new Worker(workerPath, options);
}
async function getWebAssemblyLoaderConfig(processor, wasmOptions) {
const config2 = {
modulePath: void 0,
wasmBinaryFile: void 0,
wasmBinary: void 0
};
if (!FeatureDetection_default.supportsWebAssembly()) {
if (!defined_default(wasmOptions.fallbackModulePath)) {
throw new RuntimeError_default(
`This browser does not support Web Assembly, and no backup module was provided for ${processor._workerPath}`
);
}
config2.modulePath = buildModuleUrl_default(wasmOptions.fallbackModulePath);
return config2;
}
config2.wasmBinaryFile = buildModuleUrl_default(wasmOptions.wasmBinaryFile);
const arrayBuffer = await Resource_default.fetchArrayBuffer({
url: config2.wasmBinaryFile
});
config2.wasmBinary = arrayBuffer;
return config2;
}
function TaskProcessor(workerPath, maximumActiveTasks) {
this._workerPath = workerPath;
this._maximumActiveTasks = maximumActiveTasks ?? Number.POSITIVE_INFINITY;
this._activeTasks = 0;
this._nextID = 0;
this._webAssemblyPromise = void 0;
}
var createOnmessageHandler = (worker, id, resolve2, reject) => {
const listener = ({ data }) => {
if (data.id !== id) {
return;
}
if (defined_default(data.error)) {
let error = data.error;
if (error.name === "RuntimeError") {
error = new RuntimeError_default(data.error.message);
error.stack = data.error.stack;
} else if (error.name === "DeveloperError") {
error = new DeveloperError_default(data.error.message);
error.stack = data.error.stack;
} else if (error.name === "Error") {
error = new Error(data.error.message);
error.stack = data.error.stack;
}
taskCompletedEvent.raiseEvent(error);
reject(error);
} else {
taskCompletedEvent.raiseEvent();
resolve2(data.result);
}
worker.removeEventListener("message", listener);
};
return listener;
};
var emptyTransferableObjectArray = [];
async function runTask(processor, parameters, transferableObjects) {
const canTransfer = await Promise.resolve(canTransferArrayBuffer());
if (!defined_default(transferableObjects)) {
transferableObjects = emptyTransferableObjectArray;
} else if (!canTransfer) {
transferableObjects.length = 0;
}
const id = processor._nextID++;
const promise = new Promise((resolve2, reject) => {
processor._worker.addEventListener(
"message",
createOnmessageHandler(processor._worker, id, resolve2, reject)
);
});
processor._worker.postMessage(
{
id,
baseUrl: buildModuleUrl_default.getCesiumBaseUrl().url,
parameters,
canTransferArrayBuffer: canTransfer
},
transferableObjects
);
return promise;
}
async function scheduleTask(processor, parameters, transferableObjects) {
++processor._activeTasks;
try {
const result = await runTask(processor, parameters, transferableObjects);
--processor._activeTasks;
return result;
} catch (error) {
--processor._activeTasks;
throw error;
}
}
TaskProcessor.prototype.scheduleTask = function(parameters, transferableObjects) {
if (!defined_default(this._worker)) {
this._worker = createWorker(this._workerPath);
}
if (this._activeTasks >= this._maximumActiveTasks) {
return void 0;
}
return scheduleTask(this, parameters, transferableObjects);
};
TaskProcessor.prototype.initWebAssemblyModule = async function(webAssemblyOptions) {
if (defined_default(this._webAssemblyPromise)) {
return this._webAssemblyPromise;
}
const init = async () => {
const worker = this._worker = createWorker(this._workerPath);
const wasmConfig = await getWebAssemblyLoaderConfig(
this,
webAssemblyOptions
);
const canTransfer = await Promise.resolve(canTransferArrayBuffer());
let transferableObjects;
const binary = wasmConfig.wasmBinary;
if (defined_default(binary) && canTransfer) {
transferableObjects = [binary];
}
const promise = new Promise((resolve2, reject) => {
worker.onmessage = function({ data }) {
if (defined_default(data)) {
resolve2(data.result);
} else {
reject(new RuntimeError_default("Could not configure wasm module"));
}
};
});
worker.postMessage(
{
canTransferArrayBuffer: canTransfer,
parameters: { webAssemblyConfig: wasmConfig }
},
transferableObjects
);
return promise;
};
this._webAssemblyPromise = init();
return this._webAssemblyPromise;
};
TaskProcessor.prototype.isDestroyed = function() {
return false;
};
TaskProcessor.prototype.destroy = function() {
if (defined_default(this._worker)) {
this._worker.terminate();
}
return destroyObject_default(this);
};
TaskProcessor.taskCompletedEvent = taskCompletedEvent;
TaskProcessor._defaultWorkerModulePrefix = "Workers/";
TaskProcessor._workerModulePrefix = TaskProcessor._defaultWorkerModulePrefix;
TaskProcessor._canTransferArrayBuffer = void 0;
var TaskProcessor_default = TaskProcessor;
// packages/engine/Source/Core/KTX2Transcoder.js
function KTX2Transcoder() {
}
KTX2Transcoder._transcodeTaskProcessor = new TaskProcessor_default(
"transcodeKTX2",
Number.POSITIVE_INFINITY
// KTX2 transcoding is used in place of Resource.fetchImage, so it can't reject as "just soooo busy right now"
);
KTX2Transcoder._readyPromise = void 0;
function makeReadyPromise() {
const readyPromise = KTX2Transcoder._transcodeTaskProcessor.initWebAssemblyModule({
wasmBinaryFile: "ThirdParty/basis_transcoder.wasm"
}).then(function(result) {
if (result) {
return KTX2Transcoder._transcodeTaskProcessor;
}
throw new RuntimeError_default("KTX2 transcoder could not be initialized.");
});
KTX2Transcoder._readyPromise = readyPromise;
}
KTX2Transcoder.transcode = function(ktx2Buffer, supportedTargetFormats) {
Check_default.defined("supportedTargetFormats", supportedTargetFormats);
if (!defined_default(KTX2Transcoder._readyPromise)) {
makeReadyPromise();
}
return KTX2Transcoder._readyPromise.then(function(taskProcessor3) {
let bufferView = ktx2Buffer;
if (ktx2Buffer instanceof ArrayBuffer) {
bufferView = new Uint8Array(ktx2Buffer);
}
const parameters = {
supportedTargetFormats,
ktx2Buffer: bufferView
};
return taskProcessor3.scheduleTask(parameters, [bufferView.buffer]);
}).then(function(result) {
const levelsLength = result.length;
const faceKeys = Object.keys(result[0]);
for (let i = 0; i < levelsLength; i++) {
const faces2 = result[i];
for (let j = 0; j < faceKeys.length; j++) {
const face = faces2[faceKeys[j]];
faces2[faceKeys[j]] = new CompressedTextureBuffer_default(
face.internalFormat,
face.datatype,
face.width,
face.height,
face.levelBuffer
);
}
}
if (faceKeys.length === 1) {
for (let i = 0; i < levelsLength; ++i) {
result[i] = result[i][faceKeys[0]];
}
if (levelsLength === 1) {
result = result[0];
}
}
return result;
}).catch(function(error) {
throw error;
});
};
var KTX2Transcoder_default = KTX2Transcoder;
// packages/engine/Source/Core/loadKTX2.js
var supportedTranscoderFormats;
loadKTX2.setKTX2SupportedFormats = function(s3tc, pvrtc, astc, etc, etc1, bc7) {
supportedTranscoderFormats = {
s3tc,
pvrtc,
astc,
etc,
etc1,
bc7
};
};
function loadKTX2(resourceOrUrlOrBuffer) {
Check_default.defined("resourceOrUrlOrBuffer", resourceOrUrlOrBuffer);
let loadPromise;
if (resourceOrUrlOrBuffer instanceof ArrayBuffer || ArrayBuffer.isView(resourceOrUrlOrBuffer)) {
loadPromise = Promise.resolve(resourceOrUrlOrBuffer);
} else {
const resource = Resource_default.createIfNeeded(resourceOrUrlOrBuffer);
loadPromise = resource.fetchArrayBuffer();
}
return loadPromise.then(function(data) {
return KTX2Transcoder_default.transcode(data, supportedTranscoderFormats);
});
}
var loadKTX2_default = loadKTX2;
// packages/engine/Source/Renderer/CubeMap.js
var import_InlineWorkers119 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/BoxGeometry.js
var import_InlineWorkers99 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/BoundingSphere.js
var import_InlineWorkers95 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/Interval.js
var import_InlineWorkers94 = __toESM(require_InlineWorkers(), 1);
function Interval(start, stop2) {
this.start = start ?? 0;
this.stop = stop2 ?? 0;
}
var Interval_default = Interval;
// packages/engine/Source/Core/BoundingSphere.js
function BoundingSphere(center, radius) {
this.center = Cartesian3_default.clone(center ?? Cartesian3_default.ZERO);
this.radius = radius ?? 0;
}
var fromPointsXMin = new Cartesian3_default();
var fromPointsYMin = new Cartesian3_default();
var fromPointsZMin = new Cartesian3_default();
var fromPointsXMax = new Cartesian3_default();
var fromPointsYMax = new Cartesian3_default();
var fromPointsZMax = new Cartesian3_default();
var fromPointsCurrentPos = new Cartesian3_default();
var fromPointsScratch = new Cartesian3_default();
var fromPointsRitterCenter = new Cartesian3_default();
var fromPointsMinBoxPt = new Cartesian3_default();
var fromPointsMaxBoxPt = new Cartesian3_default();
var fromPointsNaiveCenterScratch = new Cartesian3_default();
var volumeConstant = 4 / 3 * Math_default.PI;
BoundingSphere.fromPoints = function(positions, result) {
if (!defined_default(result)) {
result = new BoundingSphere();
}
if (!defined_default(positions) || positions.length === 0) {
result.center = Cartesian3_default.clone(Cartesian3_default.ZERO, result.center);
result.radius = 0;
return result;
}
const currentPos = Cartesian3_default.clone(positions[0], fromPointsCurrentPos);
const xMin = Cartesian3_default.clone(currentPos, fromPointsXMin);
const yMin = Cartesian3_default.clone(currentPos, fromPointsYMin);
const zMin = Cartesian3_default.clone(currentPos, fromPointsZMin);
const xMax = Cartesian3_default.clone(currentPos, fromPointsXMax);
const yMax = Cartesian3_default.clone(currentPos, fromPointsYMax);
const zMax = Cartesian3_default.clone(currentPos, fromPointsZMax);
const numPositions = positions.length;
let i;
for (i = 1; i < numPositions; i++) {
Cartesian3_default.clone(positions[i], currentPos);
const x = currentPos.x;
const y = currentPos.y;
const z = currentPos.z;
if (x < xMin.x) {
Cartesian3_default.clone(currentPos, xMin);
}
if (x > xMax.x) {
Cartesian3_default.clone(currentPos, xMax);
}
if (y < yMin.y) {
Cartesian3_default.clone(currentPos, yMin);
}
if (y > yMax.y) {
Cartesian3_default.clone(currentPos, yMax);
}
if (z < zMin.z) {
Cartesian3_default.clone(currentPos, zMin);
}
if (z > zMax.z) {
Cartesian3_default.clone(currentPos, zMax);
}
}
const xSpan = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(xMax, xMin, fromPointsScratch)
);
const ySpan = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(yMax, yMin, fromPointsScratch)
);
const zSpan = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(zMax, zMin, fromPointsScratch)
);
let diameter1 = xMin;
let diameter2 = xMax;
let maxSpan = xSpan;
if (ySpan > maxSpan) {
maxSpan = ySpan;
diameter1 = yMin;
diameter2 = yMax;
}
if (zSpan > maxSpan) {
maxSpan = zSpan;
diameter1 = zMin;
diameter2 = zMax;
}
const ritterCenter = fromPointsRitterCenter;
ritterCenter.x = (diameter1.x + diameter2.x) * 0.5;
ritterCenter.y = (diameter1.y + diameter2.y) * 0.5;
ritterCenter.z = (diameter1.z + diameter2.z) * 0.5;
let radiusSquared = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(diameter2, ritterCenter, fromPointsScratch)
);
let ritterRadius = Math.sqrt(radiusSquared);
const minBoxPt = fromPointsMinBoxPt;
minBoxPt.x = xMin.x;
minBoxPt.y = yMin.y;
minBoxPt.z = zMin.z;
const maxBoxPt = fromPointsMaxBoxPt;
maxBoxPt.x = xMax.x;
maxBoxPt.y = yMax.y;
maxBoxPt.z = zMax.z;
const naiveCenter = Cartesian3_default.midpoint(
minBoxPt,
maxBoxPt,
fromPointsNaiveCenterScratch
);
let naiveRadius = 0;
for (i = 0; i < numPositions; i++) {
Cartesian3_default.clone(positions[i], currentPos);
const r = Cartesian3_default.magnitude(
Cartesian3_default.subtract(currentPos, naiveCenter, fromPointsScratch)
);
if (r > naiveRadius) {
naiveRadius = r;
}
const oldCenterToPointSquared = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(currentPos, ritterCenter, fromPointsScratch)
);
if (oldCenterToPointSquared > radiusSquared) {
const oldCenterToPoint = Math.sqrt(oldCenterToPointSquared);
ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;
radiusSquared = ritterRadius * ritterRadius;
const oldToNew = oldCenterToPoint - ritterRadius;
ritterCenter.x = (ritterRadius * ritterCenter.x + oldToNew * currentPos.x) / oldCenterToPoint;
ritterCenter.y = (ritterRadius * ritterCenter.y + oldToNew * currentPos.y) / oldCenterToPoint;
ritterCenter.z = (ritterRadius * ritterCenter.z + oldToNew * currentPos.z) / oldCenterToPoint;
}
}
if (ritterRadius < naiveRadius) {
Cartesian3_default.clone(ritterCenter, result.center);
result.radius = ritterRadius;
} else {
Cartesian3_default.clone(naiveCenter, result.center);
result.radius = naiveRadius;
}
return result;
};
var defaultProjection2 = new GeographicProjection_default();
var fromRectangle2DLowerLeft = new Cartesian3_default();
var fromRectangle2DUpperRight = new Cartesian3_default();
var fromRectangle2DSouthwest = new Cartographic_default();
var fromRectangle2DNortheast = new Cartographic_default();
BoundingSphere.fromRectangle2D = function(rectangle, projection, result) {
return BoundingSphere.fromRectangleWithHeights2D(
rectangle,
projection,
0,
0,
result
);
};
BoundingSphere.fromRectangleWithHeights2D = function(rectangle, projection, minimumHeight, maximumHeight, result) {
if (!defined_default(result)) {
result = new BoundingSphere();
}
if (!defined_default(rectangle)) {
result.center = Cartesian3_default.clone(Cartesian3_default.ZERO, result.center);
result.radius = 0;
return result;
}
defaultProjection2._ellipsoid = Ellipsoid_default.default;
projection = projection ?? defaultProjection2;
Rectangle_default.southwest(rectangle, fromRectangle2DSouthwest);
fromRectangle2DSouthwest.height = minimumHeight;
Rectangle_default.northeast(rectangle, fromRectangle2DNortheast);
fromRectangle2DNortheast.height = maximumHeight;
const lowerLeft = projection.project(
fromRectangle2DSouthwest,
fromRectangle2DLowerLeft
);
const upperRight = projection.project(
fromRectangle2DNortheast,
fromRectangle2DUpperRight
);
const width = upperRight.x - lowerLeft.x;
const height = upperRight.y - lowerLeft.y;
const elevation = upperRight.z - lowerLeft.z;
result.radius = Math.sqrt(width * width + height * height + elevation * elevation) * 0.5;
const center = result.center;
center.x = lowerLeft.x + width * 0.5;
center.y = lowerLeft.y + height * 0.5;
center.z = lowerLeft.z + elevation * 0.5;
return result;
};
var fromRectangle3DScratch = [];
BoundingSphere.fromRectangle3D = function(rectangle, ellipsoid, surfaceHeight, result) {
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
surfaceHeight = surfaceHeight ?? 0;
if (!defined_default(result)) {
result = new BoundingSphere();
}
if (!defined_default(rectangle)) {
result.center = Cartesian3_default.clone(Cartesian3_default.ZERO, result.center);
result.radius = 0;
return result;
}
const positions = Rectangle_default.subsample(
rectangle,
ellipsoid,
surfaceHeight,
fromRectangle3DScratch
);
return BoundingSphere.fromPoints(positions, result);
};
BoundingSphere.fromVertices = function(positions, center, stride, result) {
if (!defined_default(result)) {
result = new BoundingSphere();
}
if (!defined_default(positions) || positions.length === 0) {
result.center = Cartesian3_default.clone(Cartesian3_default.ZERO, result.center);
result.radius = 0;
return result;
}
center = center ?? Cartesian3_default.ZERO;
stride = stride ?? 3;
Check_default.typeOf.number.greaterThanOrEquals("stride", stride, 3);
const currentPos = fromPointsCurrentPos;
currentPos.x = positions[0] + center.x;
currentPos.y = positions[1] + center.y;
currentPos.z = positions[2] + center.z;
const xMin = Cartesian3_default.clone(currentPos, fromPointsXMin);
const yMin = Cartesian3_default.clone(currentPos, fromPointsYMin);
const zMin = Cartesian3_default.clone(currentPos, fromPointsZMin);
const xMax = Cartesian3_default.clone(currentPos, fromPointsXMax);
const yMax = Cartesian3_default.clone(currentPos, fromPointsYMax);
const zMax = Cartesian3_default.clone(currentPos, fromPointsZMax);
const numElements = positions.length;
let i;
for (i = 0; i < numElements; i += stride) {
const x = positions[i] + center.x;
const y = positions[i + 1] + center.y;
const z = positions[i + 2] + center.z;
currentPos.x = x;
currentPos.y = y;
currentPos.z = z;
if (x < xMin.x) {
Cartesian3_default.clone(currentPos, xMin);
}
if (x > xMax.x) {
Cartesian3_default.clone(currentPos, xMax);
}
if (y < yMin.y) {
Cartesian3_default.clone(currentPos, yMin);
}
if (y > yMax.y) {
Cartesian3_default.clone(currentPos, yMax);
}
if (z < zMin.z) {
Cartesian3_default.clone(currentPos, zMin);
}
if (z > zMax.z) {
Cartesian3_default.clone(currentPos, zMax);
}
}
const xSpan = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(xMax, xMin, fromPointsScratch)
);
const ySpan = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(yMax, yMin, fromPointsScratch)
);
const zSpan = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(zMax, zMin, fromPointsScratch)
);
let diameter1 = xMin;
let diameter2 = xMax;
let maxSpan = xSpan;
if (ySpan > maxSpan) {
maxSpan = ySpan;
diameter1 = yMin;
diameter2 = yMax;
}
if (zSpan > maxSpan) {
maxSpan = zSpan;
diameter1 = zMin;
diameter2 = zMax;
}
const ritterCenter = fromPointsRitterCenter;
ritterCenter.x = (diameter1.x + diameter2.x) * 0.5;
ritterCenter.y = (diameter1.y + diameter2.y) * 0.5;
ritterCenter.z = (diameter1.z + diameter2.z) * 0.5;
let radiusSquared = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(diameter2, ritterCenter, fromPointsScratch)
);
let ritterRadius = Math.sqrt(radiusSquared);
const minBoxPt = fromPointsMinBoxPt;
minBoxPt.x = xMin.x;
minBoxPt.y = yMin.y;
minBoxPt.z = zMin.z;
const maxBoxPt = fromPointsMaxBoxPt;
maxBoxPt.x = xMax.x;
maxBoxPt.y = yMax.y;
maxBoxPt.z = zMax.z;
const naiveCenter = Cartesian3_default.midpoint(
minBoxPt,
maxBoxPt,
fromPointsNaiveCenterScratch
);
let naiveRadius = 0;
for (i = 0; i < numElements; i += stride) {
currentPos.x = positions[i] + center.x;
currentPos.y = positions[i + 1] + center.y;
currentPos.z = positions[i + 2] + center.z;
const r = Cartesian3_default.magnitude(
Cartesian3_default.subtract(currentPos, naiveCenter, fromPointsScratch)
);
if (r > naiveRadius) {
naiveRadius = r;
}
const oldCenterToPointSquared = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(currentPos, ritterCenter, fromPointsScratch)
);
if (oldCenterToPointSquared > radiusSquared) {
const oldCenterToPoint = Math.sqrt(oldCenterToPointSquared);
ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;
radiusSquared = ritterRadius * ritterRadius;
const oldToNew = oldCenterToPoint - ritterRadius;
ritterCenter.x = (ritterRadius * ritterCenter.x + oldToNew * currentPos.x) / oldCenterToPoint;
ritterCenter.y = (ritterRadius * ritterCenter.y + oldToNew * currentPos.y) / oldCenterToPoint;
ritterCenter.z = (ritterRadius * ritterCenter.z + oldToNew * currentPos.z) / oldCenterToPoint;
}
}
if (ritterRadius < naiveRadius) {
Cartesian3_default.clone(ritterCenter, result.center);
result.radius = ritterRadius;
} else {
Cartesian3_default.clone(naiveCenter, result.center);
result.radius = naiveRadius;
}
return result;
};
BoundingSphere.fromEncodedCartesianVertices = function(positionsHigh, positionsLow, result) {
if (!defined_default(result)) {
result = new BoundingSphere();
}
if (!defined_default(positionsHigh) || !defined_default(positionsLow) || positionsHigh.length !== positionsLow.length || positionsHigh.length === 0) {
result.center = Cartesian3_default.clone(Cartesian3_default.ZERO, result.center);
result.radius = 0;
return result;
}
const currentPos = fromPointsCurrentPos;
currentPos.x = positionsHigh[0] + positionsLow[0];
currentPos.y = positionsHigh[1] + positionsLow[1];
currentPos.z = positionsHigh[2] + positionsLow[2];
const xMin = Cartesian3_default.clone(currentPos, fromPointsXMin);
const yMin = Cartesian3_default.clone(currentPos, fromPointsYMin);
const zMin = Cartesian3_default.clone(currentPos, fromPointsZMin);
const xMax = Cartesian3_default.clone(currentPos, fromPointsXMax);
const yMax = Cartesian3_default.clone(currentPos, fromPointsYMax);
const zMax = Cartesian3_default.clone(currentPos, fromPointsZMax);
const numElements = positionsHigh.length;
let i;
for (i = 0; i < numElements; i += 3) {
const x = positionsHigh[i] + positionsLow[i];
const y = positionsHigh[i + 1] + positionsLow[i + 1];
const z = positionsHigh[i + 2] + positionsLow[i + 2];
currentPos.x = x;
currentPos.y = y;
currentPos.z = z;
if (x < xMin.x) {
Cartesian3_default.clone(currentPos, xMin);
}
if (x > xMax.x) {
Cartesian3_default.clone(currentPos, xMax);
}
if (y < yMin.y) {
Cartesian3_default.clone(currentPos, yMin);
}
if (y > yMax.y) {
Cartesian3_default.clone(currentPos, yMax);
}
if (z < zMin.z) {
Cartesian3_default.clone(currentPos, zMin);
}
if (z > zMax.z) {
Cartesian3_default.clone(currentPos, zMax);
}
}
const xSpan = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(xMax, xMin, fromPointsScratch)
);
const ySpan = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(yMax, yMin, fromPointsScratch)
);
const zSpan = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(zMax, zMin, fromPointsScratch)
);
let diameter1 = xMin;
let diameter2 = xMax;
let maxSpan = xSpan;
if (ySpan > maxSpan) {
maxSpan = ySpan;
diameter1 = yMin;
diameter2 = yMax;
}
if (zSpan > maxSpan) {
maxSpan = zSpan;
diameter1 = zMin;
diameter2 = zMax;
}
const ritterCenter = fromPointsRitterCenter;
ritterCenter.x = (diameter1.x + diameter2.x) * 0.5;
ritterCenter.y = (diameter1.y + diameter2.y) * 0.5;
ritterCenter.z = (diameter1.z + diameter2.z) * 0.5;
let radiusSquared = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(diameter2, ritterCenter, fromPointsScratch)
);
let ritterRadius = Math.sqrt(radiusSquared);
const minBoxPt = fromPointsMinBoxPt;
minBoxPt.x = xMin.x;
minBoxPt.y = yMin.y;
minBoxPt.z = zMin.z;
const maxBoxPt = fromPointsMaxBoxPt;
maxBoxPt.x = xMax.x;
maxBoxPt.y = yMax.y;
maxBoxPt.z = zMax.z;
const naiveCenter = Cartesian3_default.midpoint(
minBoxPt,
maxBoxPt,
fromPointsNaiveCenterScratch
);
let naiveRadius = 0;
for (i = 0; i < numElements; i += 3) {
currentPos.x = positionsHigh[i] + positionsLow[i];
currentPos.y = positionsHigh[i + 1] + positionsLow[i + 1];
currentPos.z = positionsHigh[i + 2] + positionsLow[i + 2];
const r = Cartesian3_default.magnitude(
Cartesian3_default.subtract(currentPos, naiveCenter, fromPointsScratch)
);
if (r > naiveRadius) {
naiveRadius = r;
}
const oldCenterToPointSquared = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(currentPos, ritterCenter, fromPointsScratch)
);
if (oldCenterToPointSquared > radiusSquared) {
const oldCenterToPoint = Math.sqrt(oldCenterToPointSquared);
ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;
radiusSquared = ritterRadius * ritterRadius;
const oldToNew = oldCenterToPoint - ritterRadius;
ritterCenter.x = (ritterRadius * ritterCenter.x + oldToNew * currentPos.x) / oldCenterToPoint;
ritterCenter.y = (ritterRadius * ritterCenter.y + oldToNew * currentPos.y) / oldCenterToPoint;
ritterCenter.z = (ritterRadius * ritterCenter.z + oldToNew * currentPos.z) / oldCenterToPoint;
}
}
if (ritterRadius < naiveRadius) {
Cartesian3_default.clone(ritterCenter, result.center);
result.radius = ritterRadius;
} else {
Cartesian3_default.clone(naiveCenter, result.center);
result.radius = naiveRadius;
}
return result;
};
BoundingSphere.fromCornerPoints = function(corner, oppositeCorner, result) {
Check_default.typeOf.object("corner", corner);
Check_default.typeOf.object("oppositeCorner", oppositeCorner);
if (!defined_default(result)) {
result = new BoundingSphere();
}
const center = Cartesian3_default.midpoint(corner, oppositeCorner, result.center);
result.radius = Cartesian3_default.distance(center, oppositeCorner);
return result;
};
BoundingSphere.fromEllipsoid = function(ellipsoid, result) {
Check_default.typeOf.object("ellipsoid", ellipsoid);
if (!defined_default(result)) {
result = new BoundingSphere();
}
Cartesian3_default.clone(Cartesian3_default.ZERO, result.center);
result.radius = ellipsoid.maximumRadius;
return result;
};
var fromBoundingSpheresScratch = new Cartesian3_default();
BoundingSphere.fromBoundingSpheres = function(boundingSpheres, result) {
if (!defined_default(result)) {
result = new BoundingSphere();
}
if (!defined_default(boundingSpheres) || boundingSpheres.length === 0) {
result.center = Cartesian3_default.clone(Cartesian3_default.ZERO, result.center);
result.radius = 0;
return result;
}
const length2 = boundingSpheres.length;
if (length2 === 1) {
return BoundingSphere.clone(boundingSpheres[0], result);
}
if (length2 === 2) {
return BoundingSphere.union(boundingSpheres[0], boundingSpheres[1], result);
}
const positions = [];
let i;
for (i = 0; i < length2; i++) {
positions.push(boundingSpheres[i].center);
}
result = BoundingSphere.fromPoints(positions, result);
const center = result.center;
let radius = result.radius;
for (i = 0; i < length2; i++) {
const tmp2 = boundingSpheres[i];
radius = Math.max(
radius,
Cartesian3_default.distance(center, tmp2.center, fromBoundingSpheresScratch) + tmp2.radius
);
}
result.radius = radius;
return result;
};
var fromOrientedBoundingBoxScratchU = new Cartesian3_default();
var fromOrientedBoundingBoxScratchV = new Cartesian3_default();
var fromOrientedBoundingBoxScratchW = new Cartesian3_default();
BoundingSphere.fromOrientedBoundingBox = function(orientedBoundingBox, result) {
Check_default.defined("orientedBoundingBox", orientedBoundingBox);
if (!defined_default(result)) {
result = new BoundingSphere();
}
const halfAxes = orientedBoundingBox.halfAxes;
const u3 = Matrix3_default.getColumn(halfAxes, 0, fromOrientedBoundingBoxScratchU);
const v3 = Matrix3_default.getColumn(halfAxes, 1, fromOrientedBoundingBoxScratchV);
const w = Matrix3_default.getColumn(halfAxes, 2, fromOrientedBoundingBoxScratchW);
Cartesian3_default.add(u3, v3, u3);
Cartesian3_default.add(u3, w, u3);
result.center = Cartesian3_default.clone(orientedBoundingBox.center, result.center);
result.radius = Cartesian3_default.magnitude(u3);
return result;
};
var scratchFromTransformationCenter = new Cartesian3_default();
var scratchFromTransformationScale = new Cartesian3_default();
BoundingSphere.fromTransformation = function(transformation, result) {
Check_default.typeOf.object("transformation", transformation);
if (!defined_default(result)) {
result = new BoundingSphere();
}
const center = Matrix4_default.getTranslation(
transformation,
scratchFromTransformationCenter
);
const scale = Matrix4_default.getScale(
transformation,
scratchFromTransformationScale
);
const radius = 0.5 * Cartesian3_default.magnitude(scale);
result.center = Cartesian3_default.clone(center, result.center);
result.radius = radius;
return result;
};
BoundingSphere.clone = function(sphere, result) {
if (!defined_default(sphere)) {
return void 0;
}
if (!defined_default(result)) {
return new BoundingSphere(sphere.center, sphere.radius);
}
result.center = Cartesian3_default.clone(sphere.center, result.center);
result.radius = sphere.radius;
return result;
};
BoundingSphere.packedLength = 4;
BoundingSphere.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const center = value.center;
array[startingIndex++] = center.x;
array[startingIndex++] = center.y;
array[startingIndex++] = center.z;
array[startingIndex] = value.radius;
return array;
};
BoundingSphere.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new BoundingSphere();
}
const center = result.center;
center.x = array[startingIndex++];
center.y = array[startingIndex++];
center.z = array[startingIndex++];
result.radius = array[startingIndex];
return result;
};
var unionScratch = new Cartesian3_default();
var unionScratchCenter = new Cartesian3_default();
BoundingSphere.union = function(left, right, result) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
if (!defined_default(result)) {
result = new BoundingSphere();
}
const leftCenter = left.center;
const leftRadius = left.radius;
const rightCenter = right.center;
const rightRadius = right.radius;
const toRightCenter = Cartesian3_default.subtract(
rightCenter,
leftCenter,
unionScratch
);
const centerSeparation = Cartesian3_default.magnitude(toRightCenter);
if (leftRadius >= centerSeparation + rightRadius) {
left.clone(result);
return result;
}
if (rightRadius >= centerSeparation + leftRadius) {
right.clone(result);
return result;
}
const halfDistanceBetweenTangentPoints = (leftRadius + centerSeparation + rightRadius) * 0.5;
const center = Cartesian3_default.multiplyByScalar(
toRightCenter,
(-leftRadius + halfDistanceBetweenTangentPoints) / centerSeparation,
unionScratchCenter
);
Cartesian3_default.add(center, leftCenter, center);
Cartesian3_default.clone(center, result.center);
result.radius = halfDistanceBetweenTangentPoints;
return result;
};
var expandScratch = new Cartesian3_default();
BoundingSphere.expand = function(sphere, point, result) {
Check_default.typeOf.object("sphere", sphere);
Check_default.typeOf.object("point", point);
result = BoundingSphere.clone(sphere, result);
const radius = Cartesian3_default.magnitude(
Cartesian3_default.subtract(point, result.center, expandScratch)
);
if (radius > result.radius) {
result.radius = radius;
}
return result;
};
BoundingSphere.intersectPlane = function(sphere, plane) {
Check_default.typeOf.object("sphere", sphere);
Check_default.typeOf.object("plane", plane);
const center = sphere.center;
const radius = sphere.radius;
const normal2 = plane.normal;
const distanceToPlane = Cartesian3_default.dot(normal2, center) + plane.distance;
if (distanceToPlane < -radius) {
return Intersect_default.OUTSIDE;
} else if (distanceToPlane < radius) {
return Intersect_default.INTERSECTING;
}
return Intersect_default.INSIDE;
};
BoundingSphere.transform = function(sphere, transform3, result) {
Check_default.typeOf.object("sphere", sphere);
Check_default.typeOf.object("transform", transform3);
if (!defined_default(result)) {
result = new BoundingSphere();
}
result.center = Matrix4_default.multiplyByPoint(
transform3,
sphere.center,
result.center
);
result.radius = Matrix4_default.getMaximumScale(transform3) * sphere.radius;
return result;
};
var distanceSquaredToScratch = new Cartesian3_default();
BoundingSphere.distanceSquaredTo = function(sphere, cartesian11) {
Check_default.typeOf.object("sphere", sphere);
Check_default.typeOf.object("cartesian", cartesian11);
const diff = Cartesian3_default.subtract(
sphere.center,
cartesian11,
distanceSquaredToScratch
);
const distance2 = Cartesian3_default.magnitude(diff) - sphere.radius;
if (distance2 <= 0) {
return 0;
}
return distance2 * distance2;
};
BoundingSphere.transformWithoutScale = function(sphere, transform3, result) {
Check_default.typeOf.object("sphere", sphere);
Check_default.typeOf.object("transform", transform3);
if (!defined_default(result)) {
result = new BoundingSphere();
}
result.center = Matrix4_default.multiplyByPoint(
transform3,
sphere.center,
result.center
);
result.radius = sphere.radius;
return result;
};
var scratchCartesian3 = new Cartesian3_default();
BoundingSphere.computePlaneDistances = function(sphere, position, direction2, result) {
Check_default.typeOf.object("sphere", sphere);
Check_default.typeOf.object("position", position);
Check_default.typeOf.object("direction", direction2);
if (!defined_default(result)) {
result = new Interval_default();
}
const toCenter = Cartesian3_default.subtract(
sphere.center,
position,
scratchCartesian3
);
const mag = Cartesian3_default.dot(direction2, toCenter);
result.start = mag - sphere.radius;
result.stop = mag + sphere.radius;
return result;
};
var projectTo2DNormalScratch = new Cartesian3_default();
var projectTo2DEastScratch = new Cartesian3_default();
var projectTo2DNorthScratch = new Cartesian3_default();
var projectTo2DWestScratch = new Cartesian3_default();
var projectTo2DSouthScratch = new Cartesian3_default();
var projectTo2DCartographicScratch = new Cartographic_default();
var projectTo2DPositionsScratch = new Array(8);
for (let n = 0; n < 8; ++n) {
projectTo2DPositionsScratch[n] = new Cartesian3_default();
}
var projectTo2DProjection = new GeographicProjection_default();
BoundingSphere.projectTo2D = function(sphere, projection, result) {
Check_default.typeOf.object("sphere", sphere);
projectTo2DProjection._ellipsoid = Ellipsoid_default.default;
projection = projection ?? projectTo2DProjection;
const ellipsoid = projection.ellipsoid;
let center = sphere.center;
const radius = sphere.radius;
let normal2;
if (Cartesian3_default.equals(center, Cartesian3_default.ZERO)) {
normal2 = Cartesian3_default.clone(Cartesian3_default.UNIT_X, projectTo2DNormalScratch);
} else {
normal2 = ellipsoid.geodeticSurfaceNormal(center, projectTo2DNormalScratch);
}
const east = Cartesian3_default.cross(
Cartesian3_default.UNIT_Z,
normal2,
projectTo2DEastScratch
);
Cartesian3_default.normalize(east, east);
const north = Cartesian3_default.cross(normal2, east, projectTo2DNorthScratch);
Cartesian3_default.normalize(north, north);
Cartesian3_default.multiplyByScalar(normal2, radius, normal2);
Cartesian3_default.multiplyByScalar(north, radius, north);
Cartesian3_default.multiplyByScalar(east, radius, east);
const south = Cartesian3_default.negate(north, projectTo2DSouthScratch);
const west = Cartesian3_default.negate(east, projectTo2DWestScratch);
const positions = projectTo2DPositionsScratch;
let corner = positions[0];
Cartesian3_default.add(normal2, north, corner);
Cartesian3_default.add(corner, east, corner);
corner = positions[1];
Cartesian3_default.add(normal2, north, corner);
Cartesian3_default.add(corner, west, corner);
corner = positions[2];
Cartesian3_default.add(normal2, south, corner);
Cartesian3_default.add(corner, west, corner);
corner = positions[3];
Cartesian3_default.add(normal2, south, corner);
Cartesian3_default.add(corner, east, corner);
Cartesian3_default.negate(normal2, normal2);
corner = positions[4];
Cartesian3_default.add(normal2, north, corner);
Cartesian3_default.add(corner, east, corner);
corner = positions[5];
Cartesian3_default.add(normal2, north, corner);
Cartesian3_default.add(corner, west, corner);
corner = positions[6];
Cartesian3_default.add(normal2, south, corner);
Cartesian3_default.add(corner, west, corner);
corner = positions[7];
Cartesian3_default.add(normal2, south, corner);
Cartesian3_default.add(corner, east, corner);
const length2 = positions.length;
for (let i = 0; i < length2; ++i) {
const position = positions[i];
Cartesian3_default.add(center, position, position);
const cartographic2 = ellipsoid.cartesianToCartographic(
position,
projectTo2DCartographicScratch
);
projection.project(cartographic2, position);
}
result = BoundingSphere.fromPoints(positions, result);
center = result.center;
const x = center.x;
const y = center.y;
const z = center.z;
center.x = z;
center.y = x;
center.z = y;
return result;
};
BoundingSphere.isOccluded = function(sphere, occluder) {
Check_default.typeOf.object("sphere", sphere);
Check_default.typeOf.object("occluder", occluder);
return !occluder.isBoundingSphereVisible(sphere);
};
BoundingSphere.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && Cartesian3_default.equals(left.center, right.center) && left.radius === right.radius;
};
BoundingSphere.prototype.intersectPlane = function(plane) {
return BoundingSphere.intersectPlane(this, plane);
};
BoundingSphere.prototype.distanceSquaredTo = function(cartesian11) {
return BoundingSphere.distanceSquaredTo(this, cartesian11);
};
BoundingSphere.prototype.computePlaneDistances = function(position, direction2, result) {
return BoundingSphere.computePlaneDistances(
this,
position,
direction2,
result
);
};
BoundingSphere.prototype.isOccluded = function(occluder) {
return BoundingSphere.isOccluded(this, occluder);
};
BoundingSphere.prototype.equals = function(right) {
return BoundingSphere.equals(this, right);
};
BoundingSphere.prototype.clone = function(result) {
return BoundingSphere.clone(this, result);
};
BoundingSphere.prototype.volume = function() {
const radius = this.radius;
return volumeConstant * radius * radius * radius;
};
var BoundingSphere_default = BoundingSphere;
// packages/engine/Source/Core/GeometryAttributes.js
var import_InlineWorkers96 = __toESM(require_InlineWorkers(), 1);
function GeometryAttributes(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.position = options.position;
this.normal = options.normal;
this.st = options.st;
this.bitangent = options.bitangent;
this.tangent = options.tangent;
this.color = options.color;
}
var GeometryAttributes_default = GeometryAttributes;
// packages/engine/Source/Core/GeometryOffsetAttribute.js
var import_InlineWorkers97 = __toESM(require_InlineWorkers(), 1);
var GeometryOffsetAttribute = {
NONE: 0,
TOP: 1,
ALL: 2
};
var GeometryOffsetAttribute_default = Object.freeze(GeometryOffsetAttribute);
// packages/engine/Source/Core/VertexFormat.js
var import_InlineWorkers98 = __toESM(require_InlineWorkers(), 1);
function VertexFormat(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.position = options.position ?? false;
this.normal = options.normal ?? false;
this.st = options.st ?? false;
this.bitangent = options.bitangent ?? false;
this.tangent = options.tangent ?? false;
this.color = options.color ?? false;
}
VertexFormat.POSITION_ONLY = Object.freeze(
new VertexFormat({
position: true
})
);
VertexFormat.POSITION_AND_NORMAL = Object.freeze(
new VertexFormat({
position: true,
normal: true
})
);
VertexFormat.POSITION_NORMAL_AND_ST = Object.freeze(
new VertexFormat({
position: true,
normal: true,
st: true
})
);
VertexFormat.POSITION_AND_ST = Object.freeze(
new VertexFormat({
position: true,
st: true
})
);
VertexFormat.POSITION_AND_COLOR = Object.freeze(
new VertexFormat({
position: true,
color: true
})
);
VertexFormat.ALL = Object.freeze(
new VertexFormat({
position: true,
normal: true,
st: true,
tangent: true,
bitangent: true
})
);
VertexFormat.DEFAULT = VertexFormat.POSITION_NORMAL_AND_ST;
VertexFormat.packedLength = 6;
VertexFormat.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
array[startingIndex++] = value.position ? 1 : 0;
array[startingIndex++] = value.normal ? 1 : 0;
array[startingIndex++] = value.st ? 1 : 0;
array[startingIndex++] = value.tangent ? 1 : 0;
array[startingIndex++] = value.bitangent ? 1 : 0;
array[startingIndex] = value.color ? 1 : 0;
return array;
};
VertexFormat.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new VertexFormat();
}
result.position = array[startingIndex++] === 1;
result.normal = array[startingIndex++] === 1;
result.st = array[startingIndex++] === 1;
result.tangent = array[startingIndex++] === 1;
result.bitangent = array[startingIndex++] === 1;
result.color = array[startingIndex] === 1;
return result;
};
VertexFormat.clone = function(vertexFormat, result) {
if (!defined_default(vertexFormat)) {
return void 0;
}
if (!defined_default(result)) {
result = new VertexFormat();
}
result.position = vertexFormat.position;
result.normal = vertexFormat.normal;
result.st = vertexFormat.st;
result.tangent = vertexFormat.tangent;
result.bitangent = vertexFormat.bitangent;
result.color = vertexFormat.color;
return result;
};
var VertexFormat_default = VertexFormat;
// packages/engine/Source/Core/BoxGeometry.js
var diffScratch = new Cartesian3_default();
function BoxGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const min3 = options.minimum;
const max3 = options.maximum;
Check_default.typeOf.object("min", min3);
Check_default.typeOf.object("max", max3);
if (defined_default(options.offsetAttribute) && options.offsetAttribute === GeometryOffsetAttribute_default.TOP) {
throw new DeveloperError_default(
"GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry."
);
}
const vertexFormat = options.vertexFormat ?? VertexFormat_default.DEFAULT;
this._minimum = Cartesian3_default.clone(min3);
this._maximum = Cartesian3_default.clone(max3);
this._vertexFormat = vertexFormat;
this._offsetAttribute = options.offsetAttribute;
this._workerName = "createBoxGeometry";
}
BoxGeometry.fromDimensions = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const dimensions = options.dimensions;
Check_default.typeOf.object("dimensions", dimensions);
Check_default.typeOf.number.greaterThanOrEquals("dimensions.x", dimensions.x, 0);
Check_default.typeOf.number.greaterThanOrEquals("dimensions.y", dimensions.y, 0);
Check_default.typeOf.number.greaterThanOrEquals("dimensions.z", dimensions.z, 0);
const corner = Cartesian3_default.multiplyByScalar(dimensions, 0.5, new Cartesian3_default());
return new BoxGeometry({
minimum: Cartesian3_default.negate(corner, new Cartesian3_default()),
maximum: corner,
vertexFormat: options.vertexFormat,
offsetAttribute: options.offsetAttribute
});
};
BoxGeometry.fromAxisAlignedBoundingBox = function(boundingBox) {
Check_default.typeOf.object("boundingBox", boundingBox);
return new BoxGeometry({
minimum: boundingBox.minimum,
maximum: boundingBox.maximum
});
};
BoxGeometry.packedLength = 2 * Cartesian3_default.packedLength + VertexFormat_default.packedLength + 1;
BoxGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
Cartesian3_default.pack(value._minimum, array, startingIndex);
Cartesian3_default.pack(
value._maximum,
array,
startingIndex + Cartesian3_default.packedLength
);
VertexFormat_default.pack(
value._vertexFormat,
array,
startingIndex + 2 * Cartesian3_default.packedLength
);
array[startingIndex + 2 * Cartesian3_default.packedLength + VertexFormat_default.packedLength] = value._offsetAttribute ?? -1;
return array;
};
var scratchMin = new Cartesian3_default();
var scratchMax = new Cartesian3_default();
var scratchVertexFormat = new VertexFormat_default();
var scratchOptions = {
minimum: scratchMin,
maximum: scratchMax,
vertexFormat: scratchVertexFormat,
offsetAttribute: void 0
};
BoxGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const min3 = Cartesian3_default.unpack(array, startingIndex, scratchMin);
const max3 = Cartesian3_default.unpack(
array,
startingIndex + Cartesian3_default.packedLength,
scratchMax
);
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex + 2 * Cartesian3_default.packedLength,
scratchVertexFormat
);
const offsetAttribute = array[startingIndex + 2 * Cartesian3_default.packedLength + VertexFormat_default.packedLength];
if (!defined_default(result)) {
scratchOptions.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new BoxGeometry(scratchOptions);
}
result._minimum = Cartesian3_default.clone(min3, result._minimum);
result._maximum = Cartesian3_default.clone(max3, result._maximum);
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
BoxGeometry.createGeometry = function(boxGeometry) {
const min3 = boxGeometry._minimum;
const max3 = boxGeometry._maximum;
const vertexFormat = boxGeometry._vertexFormat;
if (Cartesian3_default.equals(min3, max3)) {
return;
}
const attributes = new GeometryAttributes_default();
let indices;
let positions;
if (vertexFormat.position && (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent)) {
if (vertexFormat.position) {
positions = new Float64Array(6 * 4 * 3);
positions[0] = min3.x;
positions[1] = min3.y;
positions[2] = max3.z;
positions[3] = max3.x;
positions[4] = min3.y;
positions[5] = max3.z;
positions[6] = max3.x;
positions[7] = max3.y;
positions[8] = max3.z;
positions[9] = min3.x;
positions[10] = max3.y;
positions[11] = max3.z;
positions[12] = min3.x;
positions[13] = min3.y;
positions[14] = min3.z;
positions[15] = max3.x;
positions[16] = min3.y;
positions[17] = min3.z;
positions[18] = max3.x;
positions[19] = max3.y;
positions[20] = min3.z;
positions[21] = min3.x;
positions[22] = max3.y;
positions[23] = min3.z;
positions[24] = max3.x;
positions[25] = min3.y;
positions[26] = min3.z;
positions[27] = max3.x;
positions[28] = max3.y;
positions[29] = min3.z;
positions[30] = max3.x;
positions[31] = max3.y;
positions[32] = max3.z;
positions[33] = max3.x;
positions[34] = min3.y;
positions[35] = max3.z;
positions[36] = min3.x;
positions[37] = min3.y;
positions[38] = min3.z;
positions[39] = min3.x;
positions[40] = max3.y;
positions[41] = min3.z;
positions[42] = min3.x;
positions[43] = max3.y;
positions[44] = max3.z;
positions[45] = min3.x;
positions[46] = min3.y;
positions[47] = max3.z;
positions[48] = min3.x;
positions[49] = max3.y;
positions[50] = min3.z;
positions[51] = max3.x;
positions[52] = max3.y;
positions[53] = min3.z;
positions[54] = max3.x;
positions[55] = max3.y;
positions[56] = max3.z;
positions[57] = min3.x;
positions[58] = max3.y;
positions[59] = max3.z;
positions[60] = min3.x;
positions[61] = min3.y;
positions[62] = min3.z;
positions[63] = max3.x;
positions[64] = min3.y;
positions[65] = min3.z;
positions[66] = max3.x;
positions[67] = min3.y;
positions[68] = max3.z;
positions[69] = min3.x;
positions[70] = min3.y;
positions[71] = max3.z;
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
});
}
if (vertexFormat.normal) {
const normals = new Float32Array(6 * 4 * 3);
normals[0] = 0;
normals[1] = 0;
normals[2] = 1;
normals[3] = 0;
normals[4] = 0;
normals[5] = 1;
normals[6] = 0;
normals[7] = 0;
normals[8] = 1;
normals[9] = 0;
normals[10] = 0;
normals[11] = 1;
normals[12] = 0;
normals[13] = 0;
normals[14] = -1;
normals[15] = 0;
normals[16] = 0;
normals[17] = -1;
normals[18] = 0;
normals[19] = 0;
normals[20] = -1;
normals[21] = 0;
normals[22] = 0;
normals[23] = -1;
normals[24] = 1;
normals[25] = 0;
normals[26] = 0;
normals[27] = 1;
normals[28] = 0;
normals[29] = 0;
normals[30] = 1;
normals[31] = 0;
normals[32] = 0;
normals[33] = 1;
normals[34] = 0;
normals[35] = 0;
normals[36] = -1;
normals[37] = 0;
normals[38] = 0;
normals[39] = -1;
normals[40] = 0;
normals[41] = 0;
normals[42] = -1;
normals[43] = 0;
normals[44] = 0;
normals[45] = -1;
normals[46] = 0;
normals[47] = 0;
normals[48] = 0;
normals[49] = 1;
normals[50] = 0;
normals[51] = 0;
normals[52] = 1;
normals[53] = 0;
normals[54] = 0;
normals[55] = 1;
normals[56] = 0;
normals[57] = 0;
normals[58] = 1;
normals[59] = 0;
normals[60] = 0;
normals[61] = -1;
normals[62] = 0;
normals[63] = 0;
normals[64] = -1;
normals[65] = 0;
normals[66] = 0;
normals[67] = -1;
normals[68] = 0;
normals[69] = 0;
normals[70] = -1;
normals[71] = 0;
attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: normals
});
}
if (vertexFormat.st) {
const texCoords = new Float32Array(6 * 4 * 2);
texCoords[0] = 0;
texCoords[1] = 0;
texCoords[2] = 1;
texCoords[3] = 0;
texCoords[4] = 1;
texCoords[5] = 1;
texCoords[6] = 0;
texCoords[7] = 1;
texCoords[8] = 1;
texCoords[9] = 0;
texCoords[10] = 0;
texCoords[11] = 0;
texCoords[12] = 0;
texCoords[13] = 1;
texCoords[14] = 1;
texCoords[15] = 1;
texCoords[16] = 0;
texCoords[17] = 0;
texCoords[18] = 1;
texCoords[19] = 0;
texCoords[20] = 1;
texCoords[21] = 1;
texCoords[22] = 0;
texCoords[23] = 1;
texCoords[24] = 1;
texCoords[25] = 0;
texCoords[26] = 0;
texCoords[27] = 0;
texCoords[28] = 0;
texCoords[29] = 1;
texCoords[30] = 1;
texCoords[31] = 1;
texCoords[32] = 1;
texCoords[33] = 0;
texCoords[34] = 0;
texCoords[35] = 0;
texCoords[36] = 0;
texCoords[37] = 1;
texCoords[38] = 1;
texCoords[39] = 1;
texCoords[40] = 0;
texCoords[41] = 0;
texCoords[42] = 1;
texCoords[43] = 0;
texCoords[44] = 1;
texCoords[45] = 1;
texCoords[46] = 0;
texCoords[47] = 1;
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: texCoords
});
}
if (vertexFormat.tangent) {
const tangents = new Float32Array(6 * 4 * 3);
tangents[0] = 1;
tangents[1] = 0;
tangents[2] = 0;
tangents[3] = 1;
tangents[4] = 0;
tangents[5] = 0;
tangents[6] = 1;
tangents[7] = 0;
tangents[8] = 0;
tangents[9] = 1;
tangents[10] = 0;
tangents[11] = 0;
tangents[12] = -1;
tangents[13] = 0;
tangents[14] = 0;
tangents[15] = -1;
tangents[16] = 0;
tangents[17] = 0;
tangents[18] = -1;
tangents[19] = 0;
tangents[20] = 0;
tangents[21] = -1;
tangents[22] = 0;
tangents[23] = 0;
tangents[24] = 0;
tangents[25] = 1;
tangents[26] = 0;
tangents[27] = 0;
tangents[28] = 1;
tangents[29] = 0;
tangents[30] = 0;
tangents[31] = 1;
tangents[32] = 0;
tangents[33] = 0;
tangents[34] = 1;
tangents[35] = 0;
tangents[36] = 0;
tangents[37] = -1;
tangents[38] = 0;
tangents[39] = 0;
tangents[40] = -1;
tangents[41] = 0;
tangents[42] = 0;
tangents[43] = -1;
tangents[44] = 0;
tangents[45] = 0;
tangents[46] = -1;
tangents[47] = 0;
tangents[48] = -1;
tangents[49] = 0;
tangents[50] = 0;
tangents[51] = -1;
tangents[52] = 0;
tangents[53] = 0;
tangents[54] = -1;
tangents[55] = 0;
tangents[56] = 0;
tangents[57] = -1;
tangents[58] = 0;
tangents[59] = 0;
tangents[60] = 1;
tangents[61] = 0;
tangents[62] = 0;
tangents[63] = 1;
tangents[64] = 0;
tangents[65] = 0;
tangents[66] = 1;
tangents[67] = 0;
tangents[68] = 0;
tangents[69] = 1;
tangents[70] = 0;
tangents[71] = 0;
attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: tangents
});
}
if (vertexFormat.bitangent) {
const bitangents = new Float32Array(6 * 4 * 3);
bitangents[0] = 0;
bitangents[1] = 1;
bitangents[2] = 0;
bitangents[3] = 0;
bitangents[4] = 1;
bitangents[5] = 0;
bitangents[6] = 0;
bitangents[7] = 1;
bitangents[8] = 0;
bitangents[9] = 0;
bitangents[10] = 1;
bitangents[11] = 0;
bitangents[12] = 0;
bitangents[13] = 1;
bitangents[14] = 0;
bitangents[15] = 0;
bitangents[16] = 1;
bitangents[17] = 0;
bitangents[18] = 0;
bitangents[19] = 1;
bitangents[20] = 0;
bitangents[21] = 0;
bitangents[22] = 1;
bitangents[23] = 0;
bitangents[24] = 0;
bitangents[25] = 0;
bitangents[26] = 1;
bitangents[27] = 0;
bitangents[28] = 0;
bitangents[29] = 1;
bitangents[30] = 0;
bitangents[31] = 0;
bitangents[32] = 1;
bitangents[33] = 0;
bitangents[34] = 0;
bitangents[35] = 1;
bitangents[36] = 0;
bitangents[37] = 0;
bitangents[38] = 1;
bitangents[39] = 0;
bitangents[40] = 0;
bitangents[41] = 1;
bitangents[42] = 0;
bitangents[43] = 0;
bitangents[44] = 1;
bitangents[45] = 0;
bitangents[46] = 0;
bitangents[47] = 1;
bitangents[48] = 0;
bitangents[49] = 0;
bitangents[50] = 1;
bitangents[51] = 0;
bitangents[52] = 0;
bitangents[53] = 1;
bitangents[54] = 0;
bitangents[55] = 0;
bitangents[56] = 1;
bitangents[57] = 0;
bitangents[58] = 0;
bitangents[59] = 1;
bitangents[60] = 0;
bitangents[61] = 0;
bitangents[62] = 1;
bitangents[63] = 0;
bitangents[64] = 0;
bitangents[65] = 1;
bitangents[66] = 0;
bitangents[67] = 0;
bitangents[68] = 1;
bitangents[69] = 0;
bitangents[70] = 0;
bitangents[71] = 1;
attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: bitangents
});
}
indices = new Uint16Array(6 * 2 * 3);
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 0;
indices[4] = 2;
indices[5] = 3;
indices[6] = 4 + 2;
indices[7] = 4 + 1;
indices[8] = 4 + 0;
indices[9] = 4 + 3;
indices[10] = 4 + 2;
indices[11] = 4 + 0;
indices[12] = 8 + 0;
indices[13] = 8 + 1;
indices[14] = 8 + 2;
indices[15] = 8 + 0;
indices[16] = 8 + 2;
indices[17] = 8 + 3;
indices[18] = 12 + 2;
indices[19] = 12 + 1;
indices[20] = 12 + 0;
indices[21] = 12 + 3;
indices[22] = 12 + 2;
indices[23] = 12 + 0;
indices[24] = 16 + 2;
indices[25] = 16 + 1;
indices[26] = 16 + 0;
indices[27] = 16 + 3;
indices[28] = 16 + 2;
indices[29] = 16 + 0;
indices[30] = 20 + 0;
indices[31] = 20 + 1;
indices[32] = 20 + 2;
indices[33] = 20 + 0;
indices[34] = 20 + 2;
indices[35] = 20 + 3;
} else {
positions = new Float64Array(8 * 3);
positions[0] = min3.x;
positions[1] = min3.y;
positions[2] = min3.z;
positions[3] = max3.x;
positions[4] = min3.y;
positions[5] = min3.z;
positions[6] = max3.x;
positions[7] = max3.y;
positions[8] = min3.z;
positions[9] = min3.x;
positions[10] = max3.y;
positions[11] = min3.z;
positions[12] = min3.x;
positions[13] = min3.y;
positions[14] = max3.z;
positions[15] = max3.x;
positions[16] = min3.y;
positions[17] = max3.z;
positions[18] = max3.x;
positions[19] = max3.y;
positions[20] = max3.z;
positions[21] = min3.x;
positions[22] = max3.y;
positions[23] = max3.z;
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
});
indices = new Uint16Array(6 * 2 * 3);
indices[0] = 4;
indices[1] = 5;
indices[2] = 6;
indices[3] = 4;
indices[4] = 6;
indices[5] = 7;
indices[6] = 1;
indices[7] = 0;
indices[8] = 3;
indices[9] = 1;
indices[10] = 3;
indices[11] = 2;
indices[12] = 1;
indices[13] = 6;
indices[14] = 5;
indices[15] = 1;
indices[16] = 2;
indices[17] = 6;
indices[18] = 2;
indices[19] = 3;
indices[20] = 7;
indices[21] = 2;
indices[22] = 7;
indices[23] = 6;
indices[24] = 3;
indices[25] = 0;
indices[26] = 4;
indices[27] = 3;
indices[28] = 4;
indices[29] = 7;
indices[30] = 0;
indices[31] = 1;
indices[32] = 5;
indices[33] = 0;
indices[34] = 5;
indices[35] = 4;
}
const diff = Cartesian3_default.subtract(max3, min3, diffScratch);
const radius = Cartesian3_default.magnitude(diff) * 0.5;
if (defined_default(boxGeometry._offsetAttribute)) {
const length2 = positions.length;
const offsetValue = boxGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.TRIANGLES,
boundingSphere: new BoundingSphere_default(Cartesian3_default.ZERO, radius),
offsetAttribute: boxGeometry._offsetAttribute
});
};
var unitBoxGeometry;
BoxGeometry.getUnitBox = function() {
if (!defined_default(unitBoxGeometry)) {
unitBoxGeometry = BoxGeometry.createGeometry(
BoxGeometry.fromDimensions({
dimensions: new Cartesian3_default(1, 1, 1),
vertexFormat: VertexFormat_default.POSITION_ONLY
})
);
}
return unitBoxGeometry;
};
var BoxGeometry_default = BoxGeometry;
// packages/engine/Source/Core/GeometryPipeline.js
var import_InlineWorkers111 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/AttributeCompression.js
var import_InlineWorkers101 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/AttributeType.js
var import_InlineWorkers100 = __toESM(require_InlineWorkers(), 1);
var AttributeType = {
/**
* The attribute is a single component.
*
* @type {string}
* @constant
*/
SCALAR: "SCALAR",
/**
* The attribute is a two-component vector.
*
* @type {string}
* @constant
*/
VEC2: "VEC2",
/**
* The attribute is a three-component vector.
*
* @type {string}
* @constant
*/
VEC3: "VEC3",
/**
* The attribute is a four-component vector.
*
* @type {string}
* @constant
*/
VEC4: "VEC4",
/**
* The attribute is a 2x2 matrix.
*
* @type {string}
* @constant
*/
MAT2: "MAT2",
/**
* The attribute is a 3x3 matrix.
*
* @type {string}
* @constant
*/
MAT3: "MAT3",
/**
* The attribute is a 4x4 matrix.
*
* @type {string}
* @constant
*/
MAT4: "MAT4"
};
AttributeType.getMathType = function(attributeType) {
switch (attributeType) {
case AttributeType.SCALAR:
return Number;
case AttributeType.VEC2:
return Cartesian2_default;
case AttributeType.VEC3:
return Cartesian3_default;
case AttributeType.VEC4:
return Cartesian4_default;
case AttributeType.MAT2:
return Matrix2_default;
case AttributeType.MAT3:
return Matrix3_default;
case AttributeType.MAT4:
return Matrix4_default;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("attributeType is not a valid value.");
}
};
AttributeType.getNumberOfComponents = function(attributeType) {
switch (attributeType) {
case AttributeType.SCALAR:
return 1;
case AttributeType.VEC2:
return 2;
case AttributeType.VEC3:
return 3;
case AttributeType.VEC4:
case AttributeType.MAT2:
return 4;
case AttributeType.MAT3:
return 9;
case AttributeType.MAT4:
return 16;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("attributeType is not a valid value.");
}
};
AttributeType.getAttributeLocationCount = function(attributeType) {
switch (attributeType) {
case AttributeType.SCALAR:
case AttributeType.VEC2:
case AttributeType.VEC3:
case AttributeType.VEC4:
return 1;
case AttributeType.MAT2:
return 2;
case AttributeType.MAT3:
return 3;
case AttributeType.MAT4:
return 4;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("attributeType is not a valid value.");
}
};
AttributeType.getGlslType = function(attributeType) {
Check_default.typeOf.string("attributeType", attributeType);
switch (attributeType) {
case AttributeType.SCALAR:
return "float";
case AttributeType.VEC2:
return "vec2";
case AttributeType.VEC3:
return "vec3";
case AttributeType.VEC4:
return "vec4";
case AttributeType.MAT2:
return "mat2";
case AttributeType.MAT3:
return "mat3";
case AttributeType.MAT4:
return "mat4";
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("attributeType is not a valid value.");
}
};
var AttributeType_default = Object.freeze(AttributeType);
// packages/engine/Source/Core/AttributeCompression.js
var RIGHT_SHIFT = 1 / 256;
var LEFT_SHIFT = 256;
var AttributeCompression = {};
AttributeCompression.octEncodeInRange = function(vector, rangeMax, result) {
Check_default.defined("vector", vector);
Check_default.defined("result", result);
const magSquared = Cartesian3_default.magnitudeSquared(vector);
if (Math.abs(magSquared - 1) > Math_default.EPSILON6) {
throw new DeveloperError_default("vector must be normalized.");
}
result.x = vector.x / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z));
result.y = vector.y / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z));
if (vector.z < 0) {
const x = result.x;
const y = result.y;
result.x = (1 - Math.abs(y)) * Math_default.signNotZero(x);
result.y = (1 - Math.abs(x)) * Math_default.signNotZero(y);
}
result.x = Math_default.toSNorm(result.x, rangeMax);
result.y = Math_default.toSNorm(result.y, rangeMax);
return result;
};
AttributeCompression.octEncode = function(vector, result) {
return AttributeCompression.octEncodeInRange(vector, 255, result);
};
var octEncodeScratch = new Cartesian2_default();
var uint8ForceArray = new Uint8Array(1);
function forceUint8(value) {
uint8ForceArray[0] = value;
return uint8ForceArray[0];
}
AttributeCompression.octEncodeToCartesian4 = function(vector, result) {
AttributeCompression.octEncodeInRange(vector, 65535, octEncodeScratch);
result.x = forceUint8(octEncodeScratch.x * RIGHT_SHIFT);
result.y = forceUint8(octEncodeScratch.x);
result.z = forceUint8(octEncodeScratch.y * RIGHT_SHIFT);
result.w = forceUint8(octEncodeScratch.y);
return result;
};
AttributeCompression.octDecodeInRange = function(x, y, rangeMax, result) {
Check_default.defined("result", result);
if (x < 0 || x > rangeMax || y < 0 || y > rangeMax) {
throw new DeveloperError_default(
`x and y must be unsigned normalized integers between 0 and ${rangeMax}`
);
}
result.x = Math_default.fromSNorm(x, rangeMax);
result.y = Math_default.fromSNorm(y, rangeMax);
result.z = 1 - (Math.abs(result.x) + Math.abs(result.y));
if (result.z < 0) {
const oldVX = result.x;
result.x = (1 - Math.abs(result.y)) * Math_default.signNotZero(oldVX);
result.y = (1 - Math.abs(oldVX)) * Math_default.signNotZero(result.y);
}
return Cartesian3_default.normalize(result, result);
};
AttributeCompression.octDecode = function(x, y, result) {
return AttributeCompression.octDecodeInRange(x, y, 255, result);
};
AttributeCompression.octDecodeFromCartesian4 = function(encoded, result) {
Check_default.typeOf.object("encoded", encoded);
Check_default.typeOf.object("result", result);
const x = encoded.x;
const y = encoded.y;
const z = encoded.z;
const w = encoded.w;
if (x < 0 || x > 255 || y < 0 || y > 255 || z < 0 || z > 255 || w < 0 || w > 255) {
throw new DeveloperError_default(
"x, y, z, and w must be unsigned normalized integers between 0 and 255"
);
}
const xOct16 = x * LEFT_SHIFT + y;
const yOct16 = z * LEFT_SHIFT + w;
return AttributeCompression.octDecodeInRange(xOct16, yOct16, 65535, result);
};
AttributeCompression.octPackFloat = function(encoded) {
Check_default.defined("encoded", encoded);
return 256 * encoded.x + encoded.y;
};
var scratchEncodeCart2 = new Cartesian2_default();
AttributeCompression.octEncodeFloat = function(vector) {
AttributeCompression.octEncode(vector, scratchEncodeCart2);
return AttributeCompression.octPackFloat(scratchEncodeCart2);
};
AttributeCompression.octDecodeFloat = function(value, result) {
Check_default.defined("value", value);
const temp = value / 256;
const x = Math.floor(temp);
const y = (temp - x) * 256;
return AttributeCompression.octDecode(x, y, result);
};
AttributeCompression.octPack = function(v12, v22, v3, result) {
Check_default.defined("v1", v12);
Check_default.defined("v2", v22);
Check_default.defined("v3", v3);
Check_default.defined("result", result);
const encoded1 = AttributeCompression.octEncodeFloat(v12);
const encoded2 = AttributeCompression.octEncodeFloat(v22);
const encoded3 = AttributeCompression.octEncode(v3, scratchEncodeCart2);
result.x = 65536 * encoded3.x + encoded1;
result.y = 65536 * encoded3.y + encoded2;
return result;
};
AttributeCompression.octUnpack = function(packed, v12, v22, v3) {
Check_default.defined("packed", packed);
Check_default.defined("v1", v12);
Check_default.defined("v2", v22);
Check_default.defined("v3", v3);
let temp = packed.x / 65536;
const x = Math.floor(temp);
const encodedFloat1 = (temp - x) * 65536;
temp = packed.y / 65536;
const y = Math.floor(temp);
const encodedFloat2 = (temp - y) * 65536;
AttributeCompression.octDecodeFloat(encodedFloat1, v12);
AttributeCompression.octDecodeFloat(encodedFloat2, v22);
AttributeCompression.octDecode(x, y, v3);
};
AttributeCompression.compressTextureCoordinates = function(textureCoordinates) {
Check_default.defined("textureCoordinates", textureCoordinates);
const x = textureCoordinates.x * 4095 | 0;
const y = textureCoordinates.y * 4095 | 0;
return 4096 * x + y;
};
AttributeCompression.decompressTextureCoordinates = function(compressed, result) {
Check_default.defined("compressed", compressed);
Check_default.defined("result", result);
const temp = compressed / 4096;
const xZeroTo4095 = Math.floor(temp);
result.x = xZeroTo4095 / 4095;
result.y = (compressed - xZeroTo4095 * 4096) / 4095;
return result;
};
function zigZagDecode(value) {
return value >> 1 ^ -(value & 1);
}
AttributeCompression.zigZagDeltaDecode = function(uBuffer, vBuffer, heightBuffer) {
Check_default.defined("uBuffer", uBuffer);
Check_default.defined("vBuffer", vBuffer);
Check_default.typeOf.number.equals(
"uBuffer.length",
"vBuffer.length",
uBuffer.length,
vBuffer.length
);
if (defined_default(heightBuffer)) {
Check_default.typeOf.number.equals(
"uBuffer.length",
"heightBuffer.length",
uBuffer.length,
heightBuffer.length
);
}
const count = uBuffer.length;
let u3 = 0;
let v3 = 0;
let height = 0;
for (let i = 0; i < count; ++i) {
u3 += zigZagDecode(uBuffer[i]);
v3 += zigZagDecode(vBuffer[i]);
uBuffer[i] = u3;
vBuffer[i] = v3;
if (defined_default(heightBuffer)) {
height += zigZagDecode(heightBuffer[i]);
heightBuffer[i] = height;
}
}
};
AttributeCompression.dequantize = function(typedArray, componentDatatype, type, count) {
Check_default.defined("typedArray", typedArray);
Check_default.defined("componentDatatype", componentDatatype);
Check_default.defined("type", type);
Check_default.defined("count", count);
const componentsPerAttribute = AttributeType_default.getNumberOfComponents(type);
let divisor;
switch (componentDatatype) {
case ComponentDatatype_default.BYTE:
divisor = 127;
break;
case ComponentDatatype_default.UNSIGNED_BYTE:
divisor = 255;
break;
case ComponentDatatype_default.SHORT:
divisor = 32767;
break;
case ComponentDatatype_default.UNSIGNED_SHORT:
divisor = 65535;
break;
case ComponentDatatype_default.INT:
divisor = 2147483647;
break;
case ComponentDatatype_default.UNSIGNED_INT:
divisor = 4294967295;
break;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default(
`Cannot dequantize component datatype: ${componentDatatype}`
);
}
const dequantizedTypedArray = new Float32Array(
count * componentsPerAttribute
);
for (let i = 0; i < count; i++) {
for (let j = 0; j < componentsPerAttribute; j++) {
const index = i * componentsPerAttribute + j;
dequantizedTypedArray[index] = Math.max(
typedArray[index] / divisor,
-1
);
}
}
return dequantizedTypedArray;
};
AttributeCompression.decodeRGB565 = function(typedArray, result) {
Check_default.defined("typedArray", typedArray);
const expectedLength = typedArray.length * 3;
if (defined_default(result)) {
Check_default.typeOf.number.equals(
"result.length",
"typedArray.length * 3",
result.length,
expectedLength
);
}
const count = typedArray.length;
if (!defined_default(result)) {
result = new Float32Array(count * 3);
}
const mask5 = (1 << 5) - 1;
const mask6 = (1 << 6) - 1;
const normalize5 = 1 / 31;
const normalize6 = 1 / 63;
for (let i = 0; i < count; i++) {
const value = typedArray[i];
const red = value >> 11;
const green = value >> 5 & mask6;
const blue = value & mask5;
const offset = 3 * i;
result[offset] = red * normalize5;
result[offset + 1] = green * normalize6;
result[offset + 2] = blue * normalize5;
}
return result;
};
var AttributeCompression_default = AttributeCompression;
// packages/engine/Source/Core/barycentricCoordinates.js
var import_InlineWorkers102 = __toESM(require_InlineWorkers(), 1);
var scratchCartesian1 = new Cartesian3_default();
var scratchCartesian2 = new Cartesian3_default();
var scratchCartesian32 = new Cartesian3_default();
function barycentricCoordinates(point, p0, p1, p2, result) {
Check_default.defined("point", point);
Check_default.defined("p0", p0);
Check_default.defined("p1", p1);
Check_default.defined("p2", p2);
if (!defined_default(result)) {
result = new Cartesian3_default();
}
let v02;
let v12;
let v22;
let dot00;
let dot01;
let dot02;
let dot11;
let dot12;
if (!defined_default(p0.z)) {
if (Cartesian2_default.equalsEpsilon(point, p0, Math_default.EPSILON14)) {
return Cartesian3_default.clone(Cartesian3_default.UNIT_X, result);
}
if (Cartesian2_default.equalsEpsilon(point, p1, Math_default.EPSILON14)) {
return Cartesian3_default.clone(Cartesian3_default.UNIT_Y, result);
}
if (Cartesian2_default.equalsEpsilon(point, p2, Math_default.EPSILON14)) {
return Cartesian3_default.clone(Cartesian3_default.UNIT_Z, result);
}
v02 = Cartesian2_default.subtract(p1, p0, scratchCartesian1);
v12 = Cartesian2_default.subtract(p2, p0, scratchCartesian2);
v22 = Cartesian2_default.subtract(point, p0, scratchCartesian32);
dot00 = Cartesian2_default.dot(v02, v02);
dot01 = Cartesian2_default.dot(v02, v12);
dot02 = Cartesian2_default.dot(v02, v22);
dot11 = Cartesian2_default.dot(v12, v12);
dot12 = Cartesian2_default.dot(v12, v22);
} else {
if (Cartesian3_default.equalsEpsilon(point, p0, Math_default.EPSILON14)) {
return Cartesian3_default.clone(Cartesian3_default.UNIT_X, result);
}
if (Cartesian3_default.equalsEpsilon(point, p1, Math_default.EPSILON14)) {
return Cartesian3_default.clone(Cartesian3_default.UNIT_Y, result);
}
if (Cartesian3_default.equalsEpsilon(point, p2, Math_default.EPSILON14)) {
return Cartesian3_default.clone(Cartesian3_default.UNIT_Z, result);
}
v02 = Cartesian3_default.subtract(p1, p0, scratchCartesian1);
v12 = Cartesian3_default.subtract(p2, p0, scratchCartesian2);
v22 = Cartesian3_default.subtract(point, p0, scratchCartesian32);
dot00 = Cartesian3_default.dot(v02, v02);
dot01 = Cartesian3_default.dot(v02, v12);
dot02 = Cartesian3_default.dot(v02, v22);
dot11 = Cartesian3_default.dot(v12, v12);
dot12 = Cartesian3_default.dot(v12, v22);
}
result.y = dot11 * dot02 - dot01 * dot12;
result.z = dot00 * dot12 - dot01 * dot02;
const q = dot00 * dot11 - dot01 * dot01;
if (q === 0) {
return void 0;
}
result.y /= q;
result.z /= q;
result.x = 1 - result.y - result.z;
return result;
}
var barycentricCoordinates_default = barycentricCoordinates;
// packages/engine/Source/Core/EncodedCartesian3.js
var import_InlineWorkers103 = __toESM(require_InlineWorkers(), 1);
function EncodedCartesian3() {
this.high = Cartesian3_default.clone(Cartesian3_default.ZERO);
this.low = Cartesian3_default.clone(Cartesian3_default.ZERO);
}
EncodedCartesian3.encode = function(value, result) {
Check_default.typeOf.number("value", value);
if (!defined_default(result)) {
result = {
high: 0,
low: 0
};
}
let doubleHigh;
if (value >= 0) {
doubleHigh = Math.floor(value / 65536) * 65536;
result.high = doubleHigh;
result.low = value - doubleHigh;
} else {
doubleHigh = Math.floor(-value / 65536) * 65536;
result.high = -doubleHigh;
result.low = value + doubleHigh;
}
return result;
};
var scratchEncode = {
high: 0,
low: 0
};
EncodedCartesian3.fromCartesian = function(cartesian11, result) {
Check_default.typeOf.object("cartesian", cartesian11);
if (!defined_default(result)) {
result = new EncodedCartesian3();
}
const high = result.high;
const low = result.low;
EncodedCartesian3.encode(cartesian11.x, scratchEncode);
high.x = scratchEncode.high;
low.x = scratchEncode.low;
EncodedCartesian3.encode(cartesian11.y, scratchEncode);
high.y = scratchEncode.high;
low.y = scratchEncode.low;
EncodedCartesian3.encode(cartesian11.z, scratchEncode);
high.z = scratchEncode.high;
low.z = scratchEncode.low;
return result;
};
var encodedP = new EncodedCartesian3();
EncodedCartesian3.writeElements = function(cartesian11, cartesianArray, index) {
Check_default.defined("cartesianArray", cartesianArray);
Check_default.typeOf.number("index", index);
Check_default.typeOf.number.greaterThanOrEquals("index", index, 0);
EncodedCartesian3.fromCartesian(cartesian11, encodedP);
const high = encodedP.high;
const low = encodedP.low;
cartesianArray[index] = high.x;
cartesianArray[index + 1] = high.y;
cartesianArray[index + 2] = high.z;
cartesianArray[index + 3] = low.x;
cartesianArray[index + 4] = low.y;
cartesianArray[index + 5] = low.z;
};
var EncodedCartesian3_default = EncodedCartesian3;
// packages/engine/Source/Core/IntersectionTests.js
var import_InlineWorkers108 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/QuadraticRealPolynomial.js
var import_InlineWorkers104 = __toESM(require_InlineWorkers(), 1);
var QuadraticRealPolynomial = {};
QuadraticRealPolynomial.computeDiscriminant = function(a3, b, c) {
if (typeof a3 !== "number") {
throw new DeveloperError_default("a is a required number.");
}
if (typeof b !== "number") {
throw new DeveloperError_default("b is a required number.");
}
if (typeof c !== "number") {
throw new DeveloperError_default("c is a required number.");
}
const discriminant = b * b - 4 * a3 * c;
return discriminant;
};
function addWithCancellationCheck(left, right, tolerance) {
const difference = left + right;
if (Math_default.sign(left) !== Math_default.sign(right) && Math.abs(difference / Math.max(Math.abs(left), Math.abs(right))) < tolerance) {
return 0;
}
return difference;
}
QuadraticRealPolynomial.computeRealRoots = function(a3, b, c) {
if (typeof a3 !== "number") {
throw new DeveloperError_default("a is a required number.");
}
if (typeof b !== "number") {
throw new DeveloperError_default("b is a required number.");
}
if (typeof c !== "number") {
throw new DeveloperError_default("c is a required number.");
}
let ratio;
if (a3 === 0) {
if (b === 0) {
return [];
}
return [-c / b];
} else if (b === 0) {
if (c === 0) {
return [0, 0];
}
const cMagnitude = Math.abs(c);
const aMagnitude = Math.abs(a3);
if (cMagnitude < aMagnitude && cMagnitude / aMagnitude < Math_default.EPSILON14) {
return [0, 0];
} else if (cMagnitude > aMagnitude && aMagnitude / cMagnitude < Math_default.EPSILON14) {
return [];
}
ratio = -c / a3;
if (ratio < 0) {
return [];
}
const root = Math.sqrt(ratio);
return [-root, root];
} else if (c === 0) {
ratio = -b / a3;
if (ratio < 0) {
return [ratio, 0];
}
return [0, ratio];
}
const b2 = b * b;
const four_ac = 4 * a3 * c;
const radicand = addWithCancellationCheck(b2, -four_ac, Math_default.EPSILON14);
if (radicand < 0) {
return [];
}
const q = -0.5 * addWithCancellationCheck(
b,
Math_default.sign(b) * Math.sqrt(radicand),
Math_default.EPSILON14
);
if (b > 0) {
return [q / a3, c / q];
}
return [c / q, q / a3];
};
var QuadraticRealPolynomial_default = QuadraticRealPolynomial;
// packages/engine/Source/Core/QuarticRealPolynomial.js
var import_InlineWorkers106 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/CubicRealPolynomial.js
var import_InlineWorkers105 = __toESM(require_InlineWorkers(), 1);
var CubicRealPolynomial = {};
CubicRealPolynomial.computeDiscriminant = function(a3, b, c, d) {
if (typeof a3 !== "number") {
throw new DeveloperError_default("a is a required number.");
}
if (typeof b !== "number") {
throw new DeveloperError_default("b is a required number.");
}
if (typeof c !== "number") {
throw new DeveloperError_default("c is a required number.");
}
if (typeof d !== "number") {
throw new DeveloperError_default("d is a required number.");
}
const a22 = a3 * a3;
const b2 = b * b;
const c22 = c * c;
const d2 = d * d;
const discriminant = 18 * a3 * b * c * d + b2 * c22 - 27 * a22 * d2 - 4 * (a3 * c22 * c + b2 * b * d);
return discriminant;
};
function computeRealRoots(a3, b, c, d) {
const A = a3;
const B = b / 3;
const C = c / 3;
const D = d;
const AC = A * C;
const BD = B * D;
const B2 = B * B;
const C2 = C * C;
const delta1 = A * C - B2;
const delta2 = A * D - B * C;
const delta3 = B * D - C2;
const discriminant = 4 * delta1 * delta3 - delta2 * delta2;
let temp;
let temp1;
if (discriminant < 0) {
let ABar;
let CBar;
let DBar;
if (B2 * BD >= AC * C2) {
ABar = A;
CBar = delta1;
DBar = -2 * B * delta1 + A * delta2;
} else {
ABar = D;
CBar = delta3;
DBar = -D * delta2 + 2 * C * delta3;
}
const s = DBar < 0 ? -1 : 1;
const temp0 = -s * Math.abs(ABar) * Math.sqrt(-discriminant);
temp1 = -DBar + temp0;
const x = temp1 / 2;
const p = x < 0 ? -Math.pow(-x, 1 / 3) : Math.pow(x, 1 / 3);
const q = temp1 === temp0 ? -p : -CBar / p;
temp = CBar <= 0 ? p + q : -DBar / (p * p + q * q + CBar);
if (B2 * BD >= AC * C2) {
return [(temp - B) / A];
}
return [-D / (temp + C)];
}
const CBarA = delta1;
const DBarA = -2 * B * delta1 + A * delta2;
const CBarD = delta3;
const DBarD = -D * delta2 + 2 * C * delta3;
const squareRootOfDiscriminant = Math.sqrt(discriminant);
const halfSquareRootOf3 = Math.sqrt(3) / 2;
let theta = Math.abs(Math.atan2(A * squareRootOfDiscriminant, -DBarA) / 3);
temp = 2 * Math.sqrt(-CBarA);
let cosine = Math.cos(theta);
temp1 = temp * cosine;
let temp3 = temp * (-cosine / 2 - halfSquareRootOf3 * Math.sin(theta));
const numeratorLarge = temp1 + temp3 > 2 * B ? temp1 - B : temp3 - B;
const denominatorLarge = A;
const root1 = numeratorLarge / denominatorLarge;
theta = Math.abs(Math.atan2(D * squareRootOfDiscriminant, -DBarD) / 3);
temp = 2 * Math.sqrt(-CBarD);
cosine = Math.cos(theta);
temp1 = temp * cosine;
temp3 = temp * (-cosine / 2 - halfSquareRootOf3 * Math.sin(theta));
const numeratorSmall = -D;
const denominatorSmall = temp1 + temp3 < 2 * C ? temp1 + C : temp3 + C;
const root3 = numeratorSmall / denominatorSmall;
const E = denominatorLarge * denominatorSmall;
const F = -numeratorLarge * denominatorSmall - denominatorLarge * numeratorSmall;
const G = numeratorLarge * numeratorSmall;
const root2 = (C * F - B * G) / (-B * F + C * E);
if (root1 <= root2) {
if (root1 <= root3) {
if (root2 <= root3) {
return [root1, root2, root3];
}
return [root1, root3, root2];
}
return [root3, root1, root2];
}
if (root1 <= root3) {
return [root2, root1, root3];
}
if (root2 <= root3) {
return [root2, root3, root1];
}
return [root3, root2, root1];
}
CubicRealPolynomial.computeRealRoots = function(a3, b, c, d) {
if (typeof a3 !== "number") {
throw new DeveloperError_default("a is a required number.");
}
if (typeof b !== "number") {
throw new DeveloperError_default("b is a required number.");
}
if (typeof c !== "number") {
throw new DeveloperError_default("c is a required number.");
}
if (typeof d !== "number") {
throw new DeveloperError_default("d is a required number.");
}
let roots;
let ratio;
if (a3 === 0) {
return QuadraticRealPolynomial_default.computeRealRoots(b, c, d);
} else if (b === 0) {
if (c === 0) {
if (d === 0) {
return [0, 0, 0];
}
ratio = -d / a3;
const root = ratio < 0 ? -Math.pow(-ratio, 1 / 3) : Math.pow(ratio, 1 / 3);
return [root, root, root];
} else if (d === 0) {
roots = QuadraticRealPolynomial_default.computeRealRoots(a3, 0, c);
if (roots.Length === 0) {
return [0];
}
return [roots[0], 0, roots[1]];
}
return computeRealRoots(a3, 0, c, d);
} else if (c === 0) {
if (d === 0) {
ratio = -b / a3;
if (ratio < 0) {
return [ratio, 0, 0];
}
return [0, 0, ratio];
}
return computeRealRoots(a3, b, 0, d);
} else if (d === 0) {
roots = QuadraticRealPolynomial_default.computeRealRoots(a3, b, c);
if (roots.length === 0) {
return [0];
} else if (roots[1] <= 0) {
return [roots[0], roots[1], 0];
} else if (roots[0] >= 0) {
return [0, roots[0], roots[1]];
}
return [roots[0], 0, roots[1]];
}
return computeRealRoots(a3, b, c, d);
};
var CubicRealPolynomial_default = CubicRealPolynomial;
// packages/engine/Source/Core/QuarticRealPolynomial.js
var QuarticRealPolynomial = {};
QuarticRealPolynomial.computeDiscriminant = function(a3, b, c, d, e) {
if (typeof a3 !== "number") {
throw new DeveloperError_default("a is a required number.");
}
if (typeof b !== "number") {
throw new DeveloperError_default("b is a required number.");
}
if (typeof c !== "number") {
throw new DeveloperError_default("c is a required number.");
}
if (typeof d !== "number") {
throw new DeveloperError_default("d is a required number.");
}
if (typeof e !== "number") {
throw new DeveloperError_default("e is a required number.");
}
const a22 = a3 * a3;
const a32 = a22 * a3;
const b2 = b * b;
const b3 = b2 * b;
const c22 = c * c;
const c33 = c22 * c;
const d2 = d * d;
const d3 = d2 * d;
const e2 = e * e;
const e3 = e2 * e;
const discriminant = b2 * c22 * d2 - 4 * b3 * d3 - 4 * a3 * c33 * d2 + 18 * a3 * b * c * d3 - 27 * a22 * d2 * d2 + 256 * a32 * e3 + e * (18 * b3 * c * d - 4 * b2 * c33 + 16 * a3 * c22 * c22 - 80 * a3 * b * c22 * d - 6 * a3 * b2 * d2 + 144 * a22 * c * d2) + e2 * (144 * a3 * b2 * c - 27 * b2 * b2 - 128 * a22 * c22 - 192 * a22 * b * d);
return discriminant;
};
function original(a3, a22, a1, a0) {
const a3Squared = a3 * a3;
const p = a22 - 3 * a3Squared / 8;
const q = a1 - a22 * a3 / 2 + a3Squared * a3 / 8;
const r = a0 - a1 * a3 / 4 + a22 * a3Squared / 16 - 3 * a3Squared * a3Squared / 256;
const cubicRoots = CubicRealPolynomial_default.computeRealRoots(
1,
2 * p,
p * p - 4 * r,
-q * q
);
if (cubicRoots.length > 0) {
const temp = -a3 / 4;
const hSquared = cubicRoots[cubicRoots.length - 1];
if (Math.abs(hSquared) < Math_default.EPSILON14) {
const roots = QuadraticRealPolynomial_default.computeRealRoots(1, p, r);
if (roots.length === 2) {
const root0 = roots[0];
const root1 = roots[1];
let y;
if (root0 >= 0 && root1 >= 0) {
const y0 = Math.sqrt(root0);
const y1 = Math.sqrt(root1);
return [temp - y1, temp - y0, temp + y0, temp + y1];
} else if (root0 >= 0 && root1 < 0) {
y = Math.sqrt(root0);
return [temp - y, temp + y];
} else if (root0 < 0 && root1 >= 0) {
y = Math.sqrt(root1);
return [temp - y, temp + y];
}
}
return [];
} else if (hSquared > 0) {
const h = Math.sqrt(hSquared);
const m = (p + hSquared - q / h) / 2;
const n = (p + hSquared + q / h) / 2;
const roots1 = QuadraticRealPolynomial_default.computeRealRoots(1, h, m);
const roots2 = QuadraticRealPolynomial_default.computeRealRoots(1, -h, n);
if (roots1.length !== 0) {
roots1[0] += temp;
roots1[1] += temp;
if (roots2.length !== 0) {
roots2[0] += temp;
roots2[1] += temp;
if (roots1[1] <= roots2[0]) {
return [roots1[0], roots1[1], roots2[0], roots2[1]];
} else if (roots2[1] <= roots1[0]) {
return [roots2[0], roots2[1], roots1[0], roots1[1]];
} else if (roots1[0] >= roots2[0] && roots1[1] <= roots2[1]) {
return [roots2[0], roots1[0], roots1[1], roots2[1]];
} else if (roots2[0] >= roots1[0] && roots2[1] <= roots1[1]) {
return [roots1[0], roots2[0], roots2[1], roots1[1]];
} else if (roots1[0] > roots2[0] && roots1[0] < roots2[1]) {
return [roots2[0], roots1[0], roots2[1], roots1[1]];
}
return [roots1[0], roots2[0], roots1[1], roots2[1]];
}
return roots1;
}
if (roots2.length !== 0) {
roots2[0] += temp;
roots2[1] += temp;
return roots2;
}
return [];
}
}
return [];
}
function neumark(a3, a22, a1, a0) {
const a1Squared = a1 * a1;
const a2Squared = a22 * a22;
const a3Squared = a3 * a3;
const p = -2 * a22;
const q = a1 * a3 + a2Squared - 4 * a0;
const r = a3Squared * a0 - a1 * a22 * a3 + a1Squared;
const cubicRoots = CubicRealPolynomial_default.computeRealRoots(1, p, q, r);
if (cubicRoots.length > 0) {
const y = cubicRoots[0];
const temp = a22 - y;
const tempSquared = temp * temp;
const g1 = a3 / 2;
const h1 = temp / 2;
const m = tempSquared - 4 * a0;
const mError = tempSquared + 4 * Math.abs(a0);
const n = a3Squared - 4 * y;
const nError = a3Squared + 4 * Math.abs(y);
let g2;
let h2;
if (y < 0 || m * nError < n * mError) {
const squareRootOfN = Math.sqrt(n);
g2 = squareRootOfN / 2;
h2 = squareRootOfN === 0 ? 0 : (a3 * h1 - a1) / squareRootOfN;
} else {
const squareRootOfM = Math.sqrt(m);
g2 = squareRootOfM === 0 ? 0 : (a3 * h1 - a1) / squareRootOfM;
h2 = squareRootOfM / 2;
}
let G;
let g;
if (g1 === 0 && g2 === 0) {
G = 0;
g = 0;
} else if (Math_default.sign(g1) === Math_default.sign(g2)) {
G = g1 + g2;
g = y / G;
} else {
g = g1 - g2;
G = y / g;
}
let H;
let h;
if (h1 === 0 && h2 === 0) {
H = 0;
h = 0;
} else if (Math_default.sign(h1) === Math_default.sign(h2)) {
H = h1 + h2;
h = a0 / H;
} else {
h = h1 - h2;
H = a0 / h;
}
const roots1 = QuadraticRealPolynomial_default.computeRealRoots(1, G, H);
const roots2 = QuadraticRealPolynomial_default.computeRealRoots(1, g, h);
if (roots1.length !== 0) {
if (roots2.length !== 0) {
if (roots1[1] <= roots2[0]) {
return [roots1[0], roots1[1], roots2[0], roots2[1]];
} else if (roots2[1] <= roots1[0]) {
return [roots2[0], roots2[1], roots1[0], roots1[1]];
} else if (roots1[0] >= roots2[0] && roots1[1] <= roots2[1]) {
return [roots2[0], roots1[0], roots1[1], roots2[1]];
} else if (roots2[0] >= roots1[0] && roots2[1] <= roots1[1]) {
return [roots1[0], roots2[0], roots2[1], roots1[1]];
} else if (roots1[0] > roots2[0] && roots1[0] < roots2[1]) {
return [roots2[0], roots1[0], roots2[1], roots1[1]];
}
return [roots1[0], roots2[0], roots1[1], roots2[1]];
}
return roots1;
}
if (roots2.length !== 0) {
return roots2;
}
}
return [];
}
QuarticRealPolynomial.computeRealRoots = function(a3, b, c, d, e) {
if (typeof a3 !== "number") {
throw new DeveloperError_default("a is a required number.");
}
if (typeof b !== "number") {
throw new DeveloperError_default("b is a required number.");
}
if (typeof c !== "number") {
throw new DeveloperError_default("c is a required number.");
}
if (typeof d !== "number") {
throw new DeveloperError_default("d is a required number.");
}
if (typeof e !== "number") {
throw new DeveloperError_default("e is a required number.");
}
if (Math.abs(a3) < Math_default.EPSILON15) {
return CubicRealPolynomial_default.computeRealRoots(b, c, d, e);
}
const a32 = b / a3;
const a22 = c / a3;
const a1 = d / a3;
const a0 = e / a3;
let k = a32 < 0 ? 1 : 0;
k += a22 < 0 ? k + 1 : k;
k += a1 < 0 ? k + 1 : k;
k += a0 < 0 ? k + 1 : k;
switch (k) {
case 0:
return original(a32, a22, a1, a0);
case 1:
return neumark(a32, a22, a1, a0);
case 2:
return neumark(a32, a22, a1, a0);
case 3:
return original(a32, a22, a1, a0);
case 4:
return original(a32, a22, a1, a0);
case 5:
return neumark(a32, a22, a1, a0);
case 6:
return original(a32, a22, a1, a0);
case 7:
return original(a32, a22, a1, a0);
case 8:
return neumark(a32, a22, a1, a0);
case 9:
return original(a32, a22, a1, a0);
case 10:
return original(a32, a22, a1, a0);
case 11:
return neumark(a32, a22, a1, a0);
case 12:
return original(a32, a22, a1, a0);
case 13:
return original(a32, a22, a1, a0);
case 14:
return original(a32, a22, a1, a0);
case 15:
return original(a32, a22, a1, a0);
default:
return void 0;
}
};
var QuarticRealPolynomial_default = QuarticRealPolynomial;
// packages/engine/Source/Core/Ray.js
var import_InlineWorkers107 = __toESM(require_InlineWorkers(), 1);
function Ray(origin, direction2) {
direction2 = Cartesian3_default.clone(direction2 ?? Cartesian3_default.ZERO);
if (!Cartesian3_default.equals(direction2, Cartesian3_default.ZERO)) {
Cartesian3_default.normalize(direction2, direction2);
}
this.origin = Cartesian3_default.clone(origin ?? Cartesian3_default.ZERO);
this.direction = direction2;
}
Ray.clone = function(ray, result) {
if (!defined_default(ray)) {
return void 0;
}
if (!defined_default(result)) {
return new Ray(ray.origin, ray.direction);
}
result.origin = Cartesian3_default.clone(ray.origin);
result.direction = Cartesian3_default.clone(ray.direction);
return result;
};
Ray.getPoint = function(ray, t, result) {
Check_default.typeOf.object("ray", ray);
Check_default.typeOf.number("t", t);
if (!defined_default(result)) {
result = new Cartesian3_default();
}
result = Cartesian3_default.multiplyByScalar(ray.direction, t, result);
return Cartesian3_default.add(ray.origin, result, result);
};
var Ray_default = Ray;
// packages/engine/Source/Core/IntersectionTests.js
var IntersectionTests = {};
IntersectionTests.rayPlane = function(ray, plane, result) {
if (!defined_default(ray)) {
throw new DeveloperError_default("ray is required.");
}
if (!defined_default(plane)) {
throw new DeveloperError_default("plane is required.");
}
if (!defined_default(result)) {
result = new Cartesian3_default();
}
const origin = ray.origin;
const direction2 = ray.direction;
const normal2 = plane.normal;
const denominator = Cartesian3_default.dot(normal2, direction2);
if (Math.abs(denominator) < Math_default.EPSILON15) {
return void 0;
}
const t = (-plane.distance - Cartesian3_default.dot(normal2, origin)) / denominator;
if (t < 0) {
return void 0;
}
result = Cartesian3_default.multiplyByScalar(direction2, t, result);
return Cartesian3_default.add(origin, result, result);
};
var scratchEdge0 = new Cartesian3_default();
var scratchEdge1 = new Cartesian3_default();
var scratchPVec = new Cartesian3_default();
var scratchTVec = new Cartesian3_default();
var scratchQVec = new Cartesian3_default();
IntersectionTests.rayTriangleParametric = function(ray, p0, p1, p2, cullBackFaces) {
if (!defined_default(ray)) {
throw new DeveloperError_default("ray is required.");
}
if (!defined_default(p0)) {
throw new DeveloperError_default("p0 is required.");
}
if (!defined_default(p1)) {
throw new DeveloperError_default("p1 is required.");
}
if (!defined_default(p2)) {
throw new DeveloperError_default("p2 is required.");
}
cullBackFaces = cullBackFaces ?? false;
const origin = ray.origin;
const direction2 = ray.direction;
const edge0 = Cartesian3_default.subtract(p1, p0, scratchEdge0);
const edge1 = Cartesian3_default.subtract(p2, p0, scratchEdge1);
const p = Cartesian3_default.cross(direction2, edge1, scratchPVec);
const det = Cartesian3_default.dot(edge0, p);
let tvec;
let q;
let u3;
let v3;
let t;
if (cullBackFaces) {
if (det < Math_default.EPSILON6) {
return void 0;
}
tvec = Cartesian3_default.subtract(origin, p0, scratchTVec);
u3 = Cartesian3_default.dot(tvec, p);
if (u3 < 0 || u3 > det) {
return void 0;
}
q = Cartesian3_default.cross(tvec, edge0, scratchQVec);
v3 = Cartesian3_default.dot(direction2, q);
if (v3 < 0 || u3 + v3 > det) {
return void 0;
}
t = Cartesian3_default.dot(edge1, q) / det;
} else {
if (Math.abs(det) < Math_default.EPSILON6) {
return void 0;
}
const invDet = 1 / det;
tvec = Cartesian3_default.subtract(origin, p0, scratchTVec);
u3 = Cartesian3_default.dot(tvec, p) * invDet;
if (u3 < 0 || u3 > 1) {
return void 0;
}
q = Cartesian3_default.cross(tvec, edge0, scratchQVec);
v3 = Cartesian3_default.dot(direction2, q) * invDet;
if (v3 < 0 || u3 + v3 > 1) {
return void 0;
}
t = Cartesian3_default.dot(edge1, q) * invDet;
}
return t;
};
IntersectionTests.rayTriangle = function(ray, p0, p1, p2, cullBackFaces, result) {
const t = IntersectionTests.rayTriangleParametric(
ray,
p0,
p1,
p2,
cullBackFaces
);
if (!defined_default(t) || t < 0) {
return void 0;
}
if (!defined_default(result)) {
result = new Cartesian3_default();
}
Cartesian3_default.multiplyByScalar(ray.direction, t, result);
return Cartesian3_default.add(ray.origin, result, result);
};
var scratchLineSegmentTriangleRay = new Ray_default();
IntersectionTests.lineSegmentTriangle = function(v02, v12, p0, p1, p2, cullBackFaces, result) {
if (!defined_default(v02)) {
throw new DeveloperError_default("v0 is required.");
}
if (!defined_default(v12)) {
throw new DeveloperError_default("v1 is required.");
}
if (!defined_default(p0)) {
throw new DeveloperError_default("p0 is required.");
}
if (!defined_default(p1)) {
throw new DeveloperError_default("p1 is required.");
}
if (!defined_default(p2)) {
throw new DeveloperError_default("p2 is required.");
}
const ray = scratchLineSegmentTriangleRay;
Cartesian3_default.clone(v02, ray.origin);
Cartesian3_default.subtract(v12, v02, ray.direction);
Cartesian3_default.normalize(ray.direction, ray.direction);
const t = IntersectionTests.rayTriangleParametric(
ray,
p0,
p1,
p2,
cullBackFaces
);
if (!defined_default(t) || t < 0 || t > Cartesian3_default.distance(v02, v12)) {
return void 0;
}
if (!defined_default(result)) {
result = new Cartesian3_default();
}
Cartesian3_default.multiplyByScalar(ray.direction, t, result);
return Cartesian3_default.add(ray.origin, result, result);
};
function solveQuadratic(a3, b, c, result) {
const det = b * b - 4 * a3 * c;
if (det < 0) {
return void 0;
} else if (det > 0) {
const denom = 1 / (2 * a3);
const disc = Math.sqrt(det);
const root0 = (-b + disc) * denom;
const root1 = (-b - disc) * denom;
if (root0 < root1) {
result.root0 = root0;
result.root1 = root1;
} else {
result.root0 = root1;
result.root1 = root0;
}
return result;
}
const root = -b / (2 * a3);
if (root === 0) {
return void 0;
}
result.root0 = result.root1 = root;
return result;
}
var raySphereRoots = {
root0: 0,
root1: 0
};
function raySphere(ray, sphere, result) {
if (!defined_default(result)) {
result = new Interval_default();
}
const origin = ray.origin;
const direction2 = ray.direction;
const center = sphere.center;
const radiusSquared = sphere.radius * sphere.radius;
const diff = Cartesian3_default.subtract(origin, center, scratchPVec);
const a3 = Cartesian3_default.dot(direction2, direction2);
const b = 2 * Cartesian3_default.dot(direction2, diff);
const c = Cartesian3_default.magnitudeSquared(diff) - radiusSquared;
const roots = solveQuadratic(a3, b, c, raySphereRoots);
if (!defined_default(roots)) {
return void 0;
}
result.start = roots.root0;
result.stop = roots.root1;
return result;
}
IntersectionTests.raySphere = function(ray, sphere, result) {
if (!defined_default(ray)) {
throw new DeveloperError_default("ray is required.");
}
if (!defined_default(sphere)) {
throw new DeveloperError_default("sphere is required.");
}
result = raySphere(ray, sphere, result);
if (!defined_default(result) || result.stop < 0) {
return void 0;
}
result.start = Math.max(result.start, 0);
return result;
};
var scratchLineSegmentRay = new Ray_default();
IntersectionTests.lineSegmentSphere = function(p0, p1, sphere, result) {
if (!defined_default(p0)) {
throw new DeveloperError_default("p0 is required.");
}
if (!defined_default(p1)) {
throw new DeveloperError_default("p1 is required.");
}
if (!defined_default(sphere)) {
throw new DeveloperError_default("sphere is required.");
}
const ray = scratchLineSegmentRay;
Cartesian3_default.clone(p0, ray.origin);
const direction2 = Cartesian3_default.subtract(p1, p0, ray.direction);
const maxT = Cartesian3_default.magnitude(direction2);
Cartesian3_default.normalize(direction2, direction2);
result = raySphere(ray, sphere, result);
if (!defined_default(result) || result.stop < 0 || result.start > maxT) {
return void 0;
}
result.start = Math.max(result.start, 0);
result.stop = Math.min(result.stop, maxT);
return result;
};
var scratchQ = new Cartesian3_default();
var scratchW = new Cartesian3_default();
IntersectionTests.rayEllipsoid = function(ray, ellipsoid) {
if (!defined_default(ray)) {
throw new DeveloperError_default("ray is required.");
}
if (!defined_default(ellipsoid)) {
throw new DeveloperError_default("ellipsoid is required.");
}
const inverseRadii = ellipsoid.oneOverRadii;
const q = Cartesian3_default.multiplyComponents(inverseRadii, ray.origin, scratchQ);
const w = Cartesian3_default.multiplyComponents(
inverseRadii,
ray.direction,
scratchW
);
const q22 = Cartesian3_default.magnitudeSquared(q);
const qw = Cartesian3_default.dot(q, w);
let difference, w2, product, discriminant, temp;
if (q22 > 1) {
if (qw >= 0) {
return void 0;
}
const qw2 = qw * qw;
difference = q22 - 1;
w2 = Cartesian3_default.magnitudeSquared(w);
product = w2 * difference;
if (qw2 < product) {
return void 0;
} else if (qw2 > product) {
discriminant = qw * qw - product;
temp = -qw + Math.sqrt(discriminant);
const root0 = temp / w2;
const root1 = difference / temp;
if (root0 < root1) {
return new Interval_default(root0, root1);
}
return {
start: root1,
stop: root0
};
}
const root = Math.sqrt(difference / w2);
return new Interval_default(root, root);
} else if (q22 < 1) {
difference = q22 - 1;
w2 = Cartesian3_default.magnitudeSquared(w);
product = w2 * difference;
discriminant = qw * qw - product;
temp = -qw + Math.sqrt(discriminant);
return new Interval_default(0, temp / w2);
}
if (qw < 0) {
w2 = Cartesian3_default.magnitudeSquared(w);
return new Interval_default(0, -qw / w2);
}
return void 0;
};
function addWithCancellationCheck2(left, right, tolerance) {
const difference = left + right;
if (Math_default.sign(left) !== Math_default.sign(right) && Math.abs(difference / Math.max(Math.abs(left), Math.abs(right))) < tolerance) {
return 0;
}
return difference;
}
IntersectionTests.quadraticVectorExpression = function(A, b, c, x, w) {
const xSquared = x * x;
const wSquared = w * w;
const l2 = (A[Matrix3_default.COLUMN1ROW1] - A[Matrix3_default.COLUMN2ROW2]) * wSquared;
const l1 = w * (x * addWithCancellationCheck2(
A[Matrix3_default.COLUMN1ROW0],
A[Matrix3_default.COLUMN0ROW1],
Math_default.EPSILON15
) + b.y);
const l0 = A[Matrix3_default.COLUMN0ROW0] * xSquared + A[Matrix3_default.COLUMN2ROW2] * wSquared + x * b.x + c;
const r1 = wSquared * addWithCancellationCheck2(
A[Matrix3_default.COLUMN2ROW1],
A[Matrix3_default.COLUMN1ROW2],
Math_default.EPSILON15
);
const r0 = w * (x * addWithCancellationCheck2(A[Matrix3_default.COLUMN2ROW0], A[Matrix3_default.COLUMN0ROW2]) + b.z);
let cosines;
const solutions = [];
if (r0 === 0 && r1 === 0) {
cosines = QuadraticRealPolynomial_default.computeRealRoots(l2, l1, l0);
if (cosines.length === 0) {
return solutions;
}
const cosine0 = cosines[0];
const sine0 = Math.sqrt(Math.max(1 - cosine0 * cosine0, 0));
solutions.push(new Cartesian3_default(x, w * cosine0, w * -sine0));
solutions.push(new Cartesian3_default(x, w * cosine0, w * sine0));
if (cosines.length === 2) {
const cosine1 = cosines[1];
const sine1 = Math.sqrt(Math.max(1 - cosine1 * cosine1, 0));
solutions.push(new Cartesian3_default(x, w * cosine1, w * -sine1));
solutions.push(new Cartesian3_default(x, w * cosine1, w * sine1));
}
return solutions;
}
const r0Squared = r0 * r0;
const r1Squared = r1 * r1;
const l2Squared = l2 * l2;
const r0r1 = r0 * r1;
const c42 = l2Squared + r1Squared;
const c33 = 2 * (l1 * l2 + r0r1);
const c22 = 2 * l0 * l2 + l1 * l1 - r1Squared + r0Squared;
const c14 = 2 * (l0 * l1 - r0r1);
const c0 = l0 * l0 - r0Squared;
if (c42 === 0 && c33 === 0 && c22 === 0 && c14 === 0) {
return solutions;
}
cosines = QuarticRealPolynomial_default.computeRealRoots(c42, c33, c22, c14, c0);
const length2 = cosines.length;
if (length2 === 0) {
return solutions;
}
for (let i = 0; i < length2; ++i) {
const cosine = cosines[i];
const cosineSquared = cosine * cosine;
const sineSquared = Math.max(1 - cosineSquared, 0);
const sine = Math.sqrt(sineSquared);
let left;
if (Math_default.sign(l2) === Math_default.sign(l0)) {
left = addWithCancellationCheck2(
l2 * cosineSquared + l0,
l1 * cosine,
Math_default.EPSILON12
);
} else if (Math_default.sign(l0) === Math_default.sign(l1 * cosine)) {
left = addWithCancellationCheck2(
l2 * cosineSquared,
l1 * cosine + l0,
Math_default.EPSILON12
);
} else {
left = addWithCancellationCheck2(
l2 * cosineSquared + l1 * cosine,
l0,
Math_default.EPSILON12
);
}
const right = addWithCancellationCheck2(
r1 * cosine,
r0,
Math_default.EPSILON15
);
const product = left * right;
if (product < 0) {
solutions.push(new Cartesian3_default(x, w * cosine, w * sine));
} else if (product > 0) {
solutions.push(new Cartesian3_default(x, w * cosine, w * -sine));
} else if (sine !== 0) {
solutions.push(new Cartesian3_default(x, w * cosine, w * -sine));
solutions.push(new Cartesian3_default(x, w * cosine, w * sine));
++i;
} else {
solutions.push(new Cartesian3_default(x, w * cosine, w * sine));
}
}
return solutions;
};
var firstAxisScratch = new Cartesian3_default();
var secondAxisScratch = new Cartesian3_default();
var thirdAxisScratch = new Cartesian3_default();
var referenceScratch = new Cartesian3_default();
var bCart = new Cartesian3_default();
var bScratch = new Matrix3_default();
var btScratch = new Matrix3_default();
var diScratch = new Matrix3_default();
var dScratch = new Matrix3_default();
var cScratch = new Matrix3_default();
var tempMatrix = new Matrix3_default();
var aScratch = new Matrix3_default();
var sScratch = new Cartesian3_default();
var closestScratch = new Cartesian3_default();
var surfPointScratch = new Cartographic_default();
IntersectionTests.grazingAltitudeLocation = function(ray, ellipsoid) {
if (!defined_default(ray)) {
throw new DeveloperError_default("ray is required.");
}
if (!defined_default(ellipsoid)) {
throw new DeveloperError_default("ellipsoid is required.");
}
const position = ray.origin;
const direction2 = ray.direction;
if (!Cartesian3_default.equals(position, Cartesian3_default.ZERO)) {
const normal2 = ellipsoid.geodeticSurfaceNormal(position, firstAxisScratch);
if (Cartesian3_default.dot(direction2, normal2) >= 0) {
return position;
}
}
const intersects3 = defined_default(this.rayEllipsoid(ray, ellipsoid));
const f = ellipsoid.transformPositionToScaledSpace(
direction2,
firstAxisScratch
);
const firstAxis = Cartesian3_default.normalize(f, f);
const reference = Cartesian3_default.mostOrthogonalAxis(f, referenceScratch);
const secondAxis = Cartesian3_default.normalize(
Cartesian3_default.cross(reference, firstAxis, secondAxisScratch),
secondAxisScratch
);
const thirdAxis = Cartesian3_default.normalize(
Cartesian3_default.cross(firstAxis, secondAxis, thirdAxisScratch),
thirdAxisScratch
);
const B = bScratch;
B[0] = firstAxis.x;
B[1] = firstAxis.y;
B[2] = firstAxis.z;
B[3] = secondAxis.x;
B[4] = secondAxis.y;
B[5] = secondAxis.z;
B[6] = thirdAxis.x;
B[7] = thirdAxis.y;
B[8] = thirdAxis.z;
const B_T = Matrix3_default.transpose(B, btScratch);
const D_I = Matrix3_default.fromScale(ellipsoid.radii, diScratch);
const D = Matrix3_default.fromScale(ellipsoid.oneOverRadii, dScratch);
const C = cScratch;
C[0] = 0;
C[1] = -direction2.z;
C[2] = direction2.y;
C[3] = direction2.z;
C[4] = 0;
C[5] = -direction2.x;
C[6] = -direction2.y;
C[7] = direction2.x;
C[8] = 0;
const temp = Matrix3_default.multiply(
Matrix3_default.multiply(B_T, D, tempMatrix),
C,
tempMatrix
);
const A = Matrix3_default.multiply(
Matrix3_default.multiply(temp, D_I, aScratch),
B,
aScratch
);
const b = Matrix3_default.multiplyByVector(temp, position, bCart);
const solutions = IntersectionTests.quadraticVectorExpression(
A,
Cartesian3_default.negate(b, firstAxisScratch),
0,
0,
1
);
let s;
let altitude;
const length2 = solutions.length;
if (length2 > 0) {
let closest = Cartesian3_default.clone(Cartesian3_default.ZERO, closestScratch);
let maximumValue = Number.NEGATIVE_INFINITY;
for (let i = 0; i < length2; ++i) {
s = Matrix3_default.multiplyByVector(
D_I,
Matrix3_default.multiplyByVector(B, solutions[i], sScratch),
sScratch
);
const v3 = Cartesian3_default.normalize(
Cartesian3_default.subtract(s, position, referenceScratch),
referenceScratch
);
const dotProduct = Cartesian3_default.dot(v3, direction2);
if (dotProduct > maximumValue) {
maximumValue = dotProduct;
closest = Cartesian3_default.clone(s, closest);
}
}
const surfacePoint = ellipsoid.cartesianToCartographic(
closest,
surfPointScratch
);
maximumValue = Math_default.clamp(maximumValue, 0, 1);
altitude = Cartesian3_default.magnitude(
Cartesian3_default.subtract(closest, position, referenceScratch)
) * Math.sqrt(1 - maximumValue * maximumValue);
altitude = intersects3 ? -altitude : altitude;
surfacePoint.height = altitude;
return ellipsoid.cartographicToCartesian(surfacePoint, new Cartesian3_default());
}
return void 0;
};
var lineSegmentPlaneDifference = new Cartesian3_default();
IntersectionTests.lineSegmentPlane = function(endPoint0, endPoint1, plane, result) {
if (!defined_default(endPoint0)) {
throw new DeveloperError_default("endPoint0 is required.");
}
if (!defined_default(endPoint1)) {
throw new DeveloperError_default("endPoint1 is required.");
}
if (!defined_default(plane)) {
throw new DeveloperError_default("plane is required.");
}
if (!defined_default(result)) {
result = new Cartesian3_default();
}
const difference = Cartesian3_default.subtract(
endPoint1,
endPoint0,
lineSegmentPlaneDifference
);
const normal2 = plane.normal;
const nDotDiff = Cartesian3_default.dot(normal2, difference);
if (Math.abs(nDotDiff) < Math_default.EPSILON6) {
return void 0;
}
const nDotP0 = Cartesian3_default.dot(normal2, endPoint0);
const t = -(plane.distance + nDotP0) / nDotDiff;
if (t < 0 || t > 1) {
return void 0;
}
Cartesian3_default.multiplyByScalar(difference, t, result);
Cartesian3_default.add(endPoint0, result, result);
return result;
};
IntersectionTests.trianglePlaneIntersection = function(p0, p1, p2, plane) {
if (!defined_default(p0) || !defined_default(p1) || !defined_default(p2) || !defined_default(plane)) {
throw new DeveloperError_default("p0, p1, p2, and plane are required.");
}
const planeNormal = plane.normal;
const planeD = plane.distance;
const p0Behind = Cartesian3_default.dot(planeNormal, p0) + planeD < 0;
const p1Behind = Cartesian3_default.dot(planeNormal, p1) + planeD < 0;
const p2Behind = Cartesian3_default.dot(planeNormal, p2) + planeD < 0;
let numBehind = 0;
numBehind += p0Behind ? 1 : 0;
numBehind += p1Behind ? 1 : 0;
numBehind += p2Behind ? 1 : 0;
let u12, u22;
if (numBehind === 1 || numBehind === 2) {
u12 = new Cartesian3_default();
u22 = new Cartesian3_default();
}
if (numBehind === 1) {
if (p0Behind) {
IntersectionTests.lineSegmentPlane(p0, p1, plane, u12);
IntersectionTests.lineSegmentPlane(p0, p2, plane, u22);
return {
positions: [p0, p1, p2, u12, u22],
indices: [
// Behind
0,
3,
4,
// In front
1,
2,
4,
1,
4,
3
]
};
} else if (p1Behind) {
IntersectionTests.lineSegmentPlane(p1, p2, plane, u12);
IntersectionTests.lineSegmentPlane(p1, p0, plane, u22);
return {
positions: [p0, p1, p2, u12, u22],
indices: [
// Behind
1,
3,
4,
// In front
2,
0,
4,
2,
4,
3
]
};
} else if (p2Behind) {
IntersectionTests.lineSegmentPlane(p2, p0, plane, u12);
IntersectionTests.lineSegmentPlane(p2, p1, plane, u22);
return {
positions: [p0, p1, p2, u12, u22],
indices: [
// Behind
2,
3,
4,
// In front
0,
1,
4,
0,
4,
3
]
};
}
} else if (numBehind === 2) {
if (!p0Behind) {
IntersectionTests.lineSegmentPlane(p1, p0, plane, u12);
IntersectionTests.lineSegmentPlane(p2, p0, plane, u22);
return {
positions: [p0, p1, p2, u12, u22],
indices: [
// Behind
1,
2,
4,
1,
4,
3,
// In front
0,
3,
4
]
};
} else if (!p1Behind) {
IntersectionTests.lineSegmentPlane(p2, p1, plane, u12);
IntersectionTests.lineSegmentPlane(p0, p1, plane, u22);
return {
positions: [p0, p1, p2, u12, u22],
indices: [
// Behind
2,
0,
4,
2,
4,
3,
// In front
1,
3,
4
]
};
} else if (!p2Behind) {
IntersectionTests.lineSegmentPlane(p0, p2, plane, u12);
IntersectionTests.lineSegmentPlane(p1, p2, plane, u22);
return {
positions: [p0, p1, p2, u12, u22],
indices: [
// Behind
0,
1,
4,
0,
4,
3,
// In front
2,
3,
4
]
};
}
}
return void 0;
};
var IntersectionTests_default = IntersectionTests;
// packages/engine/Source/Core/Plane.js
var import_InlineWorkers109 = __toESM(require_InlineWorkers(), 1);
function Plane(normal2, distance2) {
Check_default.typeOf.object("normal", normal2);
if (!Math_default.equalsEpsilon(
Cartesian3_default.magnitude(normal2),
1,
Math_default.EPSILON6
)) {
throw new DeveloperError_default("normal must be normalized.");
}
Check_default.typeOf.number("distance", distance2);
this.normal = Cartesian3_default.clone(normal2);
this.distance = distance2;
}
Plane.fromPointNormal = function(point, normal2, result) {
Check_default.typeOf.object("point", point);
Check_default.typeOf.object("normal", normal2);
if (!Math_default.equalsEpsilon(
Cartesian3_default.magnitude(normal2),
1,
Math_default.EPSILON6
)) {
throw new DeveloperError_default("normal must be normalized.");
}
const distance2 = -Cartesian3_default.dot(normal2, point);
if (!defined_default(result)) {
return new Plane(normal2, distance2);
}
Cartesian3_default.clone(normal2, result.normal);
result.distance = distance2;
return result;
};
var scratchNormal = new Cartesian3_default();
Plane.fromCartesian4 = function(coefficients, result) {
Check_default.typeOf.object("coefficients", coefficients);
const normal2 = Cartesian3_default.fromCartesian4(coefficients, scratchNormal);
const distance2 = coefficients.w;
if (!Math_default.equalsEpsilon(
Cartesian3_default.magnitude(normal2),
1,
Math_default.EPSILON6
)) {
throw new DeveloperError_default("normal must be normalized.");
}
if (!defined_default(result)) {
return new Plane(normal2, distance2);
}
Cartesian3_default.clone(normal2, result.normal);
result.distance = distance2;
return result;
};
Plane.getPointDistance = function(plane, point) {
Check_default.typeOf.object("plane", plane);
Check_default.typeOf.object("point", point);
return Cartesian3_default.dot(plane.normal, point) + plane.distance;
};
var scratchCartesian = new Cartesian3_default();
Plane.projectPointOntoPlane = function(plane, point, result) {
Check_default.typeOf.object("plane", plane);
Check_default.typeOf.object("point", point);
if (!defined_default(result)) {
result = new Cartesian3_default();
}
const pointDistance = Plane.getPointDistance(plane, point);
const scaledNormal = Cartesian3_default.multiplyByScalar(
plane.normal,
pointDistance,
scratchCartesian
);
return Cartesian3_default.subtract(point, scaledNormal, result);
};
var scratchInverseTranspose = new Matrix4_default();
var scratchPlaneCartesian4 = new Cartesian4_default();
var scratchTransformNormal = new Cartesian3_default();
Plane.transform = function(plane, transform3, result) {
Check_default.typeOf.object("plane", plane);
Check_default.typeOf.object("transform", transform3);
const normal2 = plane.normal;
const distance2 = plane.distance;
const inverseTranspose2 = Matrix4_default.inverseTranspose(
transform3,
scratchInverseTranspose
);
let planeAsCartesian4 = Cartesian4_default.fromElements(
normal2.x,
normal2.y,
normal2.z,
distance2,
scratchPlaneCartesian4
);
planeAsCartesian4 = Matrix4_default.multiplyByVector(
inverseTranspose2,
planeAsCartesian4,
planeAsCartesian4
);
const transformedNormal = Cartesian3_default.fromCartesian4(
planeAsCartesian4,
scratchTransformNormal
);
planeAsCartesian4 = Cartesian4_default.divideByScalar(
planeAsCartesian4,
Cartesian3_default.magnitude(transformedNormal),
planeAsCartesian4
);
return Plane.fromCartesian4(planeAsCartesian4, result);
};
Plane.clone = function(plane, result) {
Check_default.typeOf.object("plane", plane);
if (!defined_default(result)) {
return new Plane(plane.normal, plane.distance);
}
Cartesian3_default.clone(plane.normal, result.normal);
result.distance = plane.distance;
return result;
};
Plane.equals = function(left, right) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
return left.distance === right.distance && Cartesian3_default.equals(left.normal, right.normal);
};
Plane.ORIGIN_XY_PLANE = Object.freeze(new Plane(Cartesian3_default.UNIT_Z, 0));
Plane.ORIGIN_YZ_PLANE = Object.freeze(new Plane(Cartesian3_default.UNIT_X, 0));
Plane.ORIGIN_ZX_PLANE = Object.freeze(new Plane(Cartesian3_default.UNIT_Y, 0));
var Plane_default = Plane;
// packages/engine/Source/Core/Tipsify.js
var import_InlineWorkers110 = __toESM(require_InlineWorkers(), 1);
var Tipsify = {};
Tipsify.calculateACMR = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const indices = options.indices;
let maximumIndex = options.maximumIndex;
const cacheSize = options.cacheSize ?? 24;
if (!defined_default(indices)) {
throw new DeveloperError_default("indices is required.");
}
const numIndices = indices.length;
if (numIndices < 3 || numIndices % 3 !== 0) {
throw new DeveloperError_default("indices length must be a multiple of three.");
}
if (maximumIndex <= 0) {
throw new DeveloperError_default("maximumIndex must be greater than zero.");
}
if (cacheSize < 3) {
throw new DeveloperError_default("cacheSize must be greater than two.");
}
if (!defined_default(maximumIndex)) {
maximumIndex = 0;
let currentIndex = 0;
let intoIndices = indices[currentIndex];
while (currentIndex < numIndices) {
if (intoIndices > maximumIndex) {
maximumIndex = intoIndices;
}
++currentIndex;
intoIndices = indices[currentIndex];
}
}
const vertexTimeStamps = [];
for (let i = 0; i < maximumIndex + 1; i++) {
vertexTimeStamps[i] = 0;
}
let s = cacheSize + 1;
for (let j = 0; j < numIndices; ++j) {
if (s - vertexTimeStamps[indices[j]] > cacheSize) {
vertexTimeStamps[indices[j]] = s;
++s;
}
}
return (s - cacheSize + 1) / (numIndices / 3);
};
Tipsify.tipsify = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const indices = options.indices;
const maximumIndex = options.maximumIndex;
const cacheSize = options.cacheSize ?? 24;
let cursor;
function skipDeadEnd(vertices2, deadEnd2, indices2, maximumIndexPlusOne2) {
while (deadEnd2.length >= 1) {
const d = deadEnd2[deadEnd2.length - 1];
deadEnd2.splice(deadEnd2.length - 1, 1);
if (vertices2[d].numLiveTriangles > 0) {
return d;
}
}
while (cursor < maximumIndexPlusOne2) {
if (vertices2[cursor].numLiveTriangles > 0) {
++cursor;
return cursor - 1;
}
++cursor;
}
return -1;
}
function getNextVertex(indices2, cacheSize2, oneRing2, vertices2, s2, deadEnd2, maximumIndexPlusOne2) {
let n = -1;
let p;
let m = -1;
let itOneRing = 0;
while (itOneRing < oneRing2.length) {
const index2 = oneRing2[itOneRing];
if (vertices2[index2].numLiveTriangles) {
p = 0;
if (s2 - vertices2[index2].timeStamp + 2 * vertices2[index2].numLiveTriangles <= cacheSize2) {
p = s2 - vertices2[index2].timeStamp;
}
if (p > m || m === -1) {
m = p;
n = index2;
}
}
++itOneRing;
}
if (n === -1) {
return skipDeadEnd(vertices2, deadEnd2, indices2, maximumIndexPlusOne2);
}
return n;
}
if (!defined_default(indices)) {
throw new DeveloperError_default("indices is required.");
}
const numIndices = indices.length;
if (numIndices < 3 || numIndices % 3 !== 0) {
throw new DeveloperError_default("indices length must be a multiple of three.");
}
if (maximumIndex <= 0) {
throw new DeveloperError_default("maximumIndex must be greater than zero.");
}
if (cacheSize < 3) {
throw new DeveloperError_default("cacheSize must be greater than two.");
}
let maximumIndexPlusOne = 0;
let currentIndex = 0;
let intoIndices = indices[currentIndex];
const endIndex = numIndices;
if (defined_default(maximumIndex)) {
maximumIndexPlusOne = maximumIndex + 1;
} else {
while (currentIndex < endIndex) {
if (intoIndices > maximumIndexPlusOne) {
maximumIndexPlusOne = intoIndices;
}
++currentIndex;
intoIndices = indices[currentIndex];
}
if (maximumIndexPlusOne === -1) {
return 0;
}
++maximumIndexPlusOne;
}
const vertices = [];
let i;
for (i = 0; i < maximumIndexPlusOne; i++) {
vertices[i] = {
numLiveTriangles: 0,
timeStamp: 0,
vertexTriangles: []
};
}
currentIndex = 0;
let triangle = 0;
while (currentIndex < endIndex) {
vertices[indices[currentIndex]].vertexTriangles.push(triangle);
++vertices[indices[currentIndex]].numLiveTriangles;
vertices[indices[currentIndex + 1]].vertexTriangles.push(triangle);
++vertices[indices[currentIndex + 1]].numLiveTriangles;
vertices[indices[currentIndex + 2]].vertexTriangles.push(triangle);
++vertices[indices[currentIndex + 2]].numLiveTriangles;
++triangle;
currentIndex += 3;
}
let f = 0;
let s = cacheSize + 1;
cursor = 1;
let oneRing = [];
const deadEnd = [];
let vertex;
let intoVertices;
let currentOutputIndex = 0;
const outputIndices = [];
const numTriangles = numIndices / 3;
const triangleEmitted = [];
for (i = 0; i < numTriangles; i++) {
triangleEmitted[i] = false;
}
let index;
let limit;
while (f !== -1) {
oneRing = [];
intoVertices = vertices[f];
limit = intoVertices.vertexTriangles.length;
for (let k = 0; k < limit; ++k) {
triangle = intoVertices.vertexTriangles[k];
if (!triangleEmitted[triangle]) {
triangleEmitted[triangle] = true;
currentIndex = triangle + triangle + triangle;
for (let j = 0; j < 3; ++j) {
index = indices[currentIndex];
oneRing.push(index);
deadEnd.push(index);
outputIndices[currentOutputIndex] = index;
++currentOutputIndex;
vertex = vertices[index];
--vertex.numLiveTriangles;
if (s - vertex.timeStamp > cacheSize) {
vertex.timeStamp = s;
++s;
}
++currentIndex;
}
}
}
f = getNextVertex(
indices,
cacheSize,
oneRing,
vertices,
s,
deadEnd,
maximumIndexPlusOne
);
}
return outputIndices;
};
var Tipsify_default = Tipsify;
// packages/engine/Source/Core/GeometryPipeline.js
var GeometryPipeline = {};
function addTriangle(lines, index, i0, i1, i2) {
lines[index++] = i0;
lines[index++] = i1;
lines[index++] = i1;
lines[index++] = i2;
lines[index++] = i2;
lines[index] = i0;
}
function trianglesToLines(triangles) {
const count = triangles.length;
const size = count / 3 * 6;
const lines = IndexDatatype_default.createTypedArray(count, size);
let index = 0;
for (let i = 0; i < count; i += 3, index += 6) {
addTriangle(lines, index, triangles[i], triangles[i + 1], triangles[i + 2]);
}
return lines;
}
function triangleStripToLines(triangles) {
const count = triangles.length;
if (count >= 3) {
const size = (count - 2) * 6;
const lines = IndexDatatype_default.createTypedArray(count, size);
addTriangle(lines, 0, triangles[0], triangles[1], triangles[2]);
let index = 6;
for (let i = 3; i < count; ++i, index += 6) {
addTriangle(
lines,
index,
triangles[i - 1],
triangles[i],
triangles[i - 2]
);
}
return lines;
}
return new Uint16Array();
}
function triangleFanToLines(triangles) {
if (triangles.length > 0) {
const count = triangles.length - 1;
const size = (count - 1) * 6;
const lines = IndexDatatype_default.createTypedArray(count, size);
const base = triangles[0];
let index = 0;
for (let i = 1; i < count; ++i, index += 6) {
addTriangle(lines, index, base, triangles[i], triangles[i + 1]);
}
return lines;
}
return new Uint16Array();
}
GeometryPipeline.toWireframe = function(geometry) {
if (!defined_default(geometry)) {
throw new DeveloperError_default("geometry is required.");
}
const indices = geometry.indices;
if (defined_default(indices)) {
switch (geometry.primitiveType) {
case PrimitiveType_default.TRIANGLES:
geometry.indices = trianglesToLines(indices);
break;
case PrimitiveType_default.TRIANGLE_STRIP:
geometry.indices = triangleStripToLines(indices);
break;
case PrimitiveType_default.TRIANGLE_FAN:
geometry.indices = triangleFanToLines(indices);
break;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default(
"geometry.primitiveType must be TRIANGLES, TRIANGLE_STRIP, or TRIANGLE_FAN."
);
}
geometry.primitiveType = PrimitiveType_default.LINES;
}
return geometry;
};
GeometryPipeline.createLineSegmentsForVectors = function(geometry, attributeName, length2) {
attributeName = attributeName ?? "normal";
if (!defined_default(geometry)) {
throw new DeveloperError_default("geometry is required.");
}
if (!defined_default(geometry.attributes.position)) {
throw new DeveloperError_default("geometry.attributes.position is required.");
}
if (!defined_default(geometry.attributes[attributeName])) {
throw new DeveloperError_default(
`geometry.attributes must have an attribute with the same name as the attributeName parameter, ${attributeName}.`
);
}
length2 = length2 ?? 1e4;
const positions = geometry.attributes.position.values;
const vectors = geometry.attributes[attributeName].values;
const positionsLength = positions.length;
const newPositions = new Float64Array(2 * positionsLength);
let j = 0;
for (let i = 0; i < positionsLength; i += 3) {
newPositions[j++] = positions[i];
newPositions[j++] = positions[i + 1];
newPositions[j++] = positions[i + 2];
newPositions[j++] = positions[i] + vectors[i] * length2;
newPositions[j++] = positions[i + 1] + vectors[i + 1] * length2;
newPositions[j++] = positions[i + 2] + vectors[i + 2] * length2;
}
let newBoundingSphere;
const bs = geometry.boundingSphere;
if (defined_default(bs)) {
newBoundingSphere = new BoundingSphere_default(bs.center, bs.radius + length2);
}
return new Geometry_default({
attributes: {
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: newPositions
})
},
primitiveType: PrimitiveType_default.LINES,
boundingSphere: newBoundingSphere
});
};
GeometryPipeline.createAttributeLocations = function(geometry) {
if (!defined_default(geometry)) {
throw new DeveloperError_default("geometry is required.");
}
const semantics = [
"position",
"positionHigh",
"positionLow",
// From VertexFormat.position - after 2D projection and high-precision encoding
"position3DHigh",
"position3DLow",
"position2DHigh",
"position2DLow",
// From Primitive
"pickColor",
// From VertexFormat
"normal",
"st",
"tangent",
"bitangent",
// For shadow volumes
"extrudeDirection",
// From compressing texture coordinates and normals
"compressedAttributes"
];
const attributes = geometry.attributes;
const indices = {};
let j = 0;
let i;
const len = semantics.length;
for (i = 0; i < len; ++i) {
const semantic = semantics[i];
if (defined_default(attributes[semantic])) {
indices[semantic] = j++;
}
}
for (const name in attributes) {
if (attributes.hasOwnProperty(name) && !defined_default(indices[name])) {
indices[name] = j++;
}
}
return indices;
};
GeometryPipeline.reorderForPreVertexCache = function(geometry) {
if (!defined_default(geometry)) {
throw new DeveloperError_default("geometry is required.");
}
const numVertices = Geometry_default.computeNumberOfVertices(geometry);
const indices = geometry.indices;
if (defined_default(indices)) {
const indexCrossReferenceOldToNew = new Int32Array(numVertices);
for (let i = 0; i < numVertices; i++) {
indexCrossReferenceOldToNew[i] = -1;
}
const indicesIn = indices;
const numIndices = indicesIn.length;
const indicesOut = IndexDatatype_default.createTypedArray(numVertices, numIndices);
let intoIndicesIn = 0;
let intoIndicesOut = 0;
let nextIndex = 0;
let tempIndex;
while (intoIndicesIn < numIndices) {
tempIndex = indexCrossReferenceOldToNew[indicesIn[intoIndicesIn]];
if (tempIndex !== -1) {
indicesOut[intoIndicesOut] = tempIndex;
} else {
tempIndex = indicesIn[intoIndicesIn];
indexCrossReferenceOldToNew[tempIndex] = nextIndex;
indicesOut[intoIndicesOut] = nextIndex;
++nextIndex;
}
++intoIndicesIn;
++intoIndicesOut;
}
geometry.indices = indicesOut;
const attributes = geometry.attributes;
for (const property in attributes) {
if (attributes.hasOwnProperty(property) && defined_default(attributes[property]) && defined_default(attributes[property].values)) {
const attribute = attributes[property];
const elementsIn = attribute.values;
let intoElementsIn = 0;
const numComponents = attribute.componentsPerAttribute;
const elementsOut = ComponentDatatype_default.createTypedArray(
attribute.componentDatatype,
nextIndex * numComponents
);
while (intoElementsIn < numVertices) {
const temp = indexCrossReferenceOldToNew[intoElementsIn];
if (temp !== -1) {
for (let j = 0; j < numComponents; j++) {
elementsOut[numComponents * temp + j] = elementsIn[numComponents * intoElementsIn + j];
}
}
++intoElementsIn;
}
attribute.values = elementsOut;
}
}
}
return geometry;
};
GeometryPipeline.reorderForPostVertexCache = function(geometry, cacheCapacity) {
if (!defined_default(geometry)) {
throw new DeveloperError_default("geometry is required.");
}
const indices = geometry.indices;
if (geometry.primitiveType === PrimitiveType_default.TRIANGLES && defined_default(indices)) {
const numIndices = indices.length;
let maximumIndex = 0;
for (let j = 0; j < numIndices; j++) {
if (indices[j] > maximumIndex) {
maximumIndex = indices[j];
}
}
geometry.indices = Tipsify_default.tipsify({
indices,
maximumIndex,
cacheSize: cacheCapacity
});
}
return geometry;
};
function copyAttributesDescriptions(attributes) {
const newAttributes = {};
for (const attribute in attributes) {
if (attributes.hasOwnProperty(attribute) && defined_default(attributes[attribute]) && defined_default(attributes[attribute].values)) {
const attr = attributes[attribute];
newAttributes[attribute] = new GeometryAttribute_default({
componentDatatype: attr.componentDatatype,
componentsPerAttribute: attr.componentsPerAttribute,
normalize: attr.normalize,
values: []
});
}
}
return newAttributes;
}
function copyVertex(destinationAttributes, sourceAttributes, index) {
for (const attribute in sourceAttributes) {
if (sourceAttributes.hasOwnProperty(attribute) && defined_default(sourceAttributes[attribute]) && defined_default(sourceAttributes[attribute].values)) {
const attr = sourceAttributes[attribute];
for (let k = 0; k < attr.componentsPerAttribute; ++k) {
destinationAttributes[attribute].values.push(
attr.values[index * attr.componentsPerAttribute + k]
);
}
}
}
}
GeometryPipeline.fitToUnsignedShortIndices = function(geometry) {
if (!defined_default(geometry)) {
throw new DeveloperError_default("geometry is required.");
}
if (defined_default(geometry.indices) && geometry.primitiveType !== PrimitiveType_default.TRIANGLES && geometry.primitiveType !== PrimitiveType_default.LINES && geometry.primitiveType !== PrimitiveType_default.POINTS) {
throw new DeveloperError_default(
"geometry.primitiveType must equal to PrimitiveType.TRIANGLES, PrimitiveType.LINES, or PrimitiveType.POINTS."
);
}
const geometries = [];
const numberOfVertices = Geometry_default.computeNumberOfVertices(geometry);
if (defined_default(geometry.indices) && numberOfVertices >= Math_default.SIXTY_FOUR_KILOBYTES) {
let oldToNewIndex = [];
let newIndices = [];
let currentIndex = 0;
let newAttributes = copyAttributesDescriptions(geometry.attributes);
const originalIndices = geometry.indices;
const numberOfIndices = originalIndices.length;
let indicesPerPrimitive;
if (geometry.primitiveType === PrimitiveType_default.TRIANGLES) {
indicesPerPrimitive = 3;
} else if (geometry.primitiveType === PrimitiveType_default.LINES) {
indicesPerPrimitive = 2;
} else if (geometry.primitiveType === PrimitiveType_default.POINTS) {
indicesPerPrimitive = 1;
}
for (let j = 0; j < numberOfIndices; j += indicesPerPrimitive) {
for (let k = 0; k < indicesPerPrimitive; ++k) {
const x = originalIndices[j + k];
let i = oldToNewIndex[x];
if (!defined_default(i)) {
i = currentIndex++;
oldToNewIndex[x] = i;
copyVertex(newAttributes, geometry.attributes, x);
}
newIndices.push(i);
}
if (currentIndex + indicesPerPrimitive >= Math_default.SIXTY_FOUR_KILOBYTES) {
geometries.push(
new Geometry_default({
attributes: newAttributes,
indices: newIndices,
primitiveType: geometry.primitiveType,
boundingSphere: geometry.boundingSphere,
boundingSphereCV: geometry.boundingSphereCV
})
);
oldToNewIndex = [];
newIndices = [];
currentIndex = 0;
newAttributes = copyAttributesDescriptions(geometry.attributes);
}
}
if (newIndices.length !== 0) {
geometries.push(
new Geometry_default({
attributes: newAttributes,
indices: newIndices,
primitiveType: geometry.primitiveType,
boundingSphere: geometry.boundingSphere,
boundingSphereCV: geometry.boundingSphereCV
})
);
}
} else {
geometries.push(geometry);
}
return geometries;
};
var scratchProjectTo2DCartesian3 = new Cartesian3_default();
var scratchProjectTo2DCartographic = new Cartographic_default();
GeometryPipeline.projectTo2D = function(geometry, attributeName, attributeName3D, attributeName2D, projection) {
if (!defined_default(geometry)) {
throw new DeveloperError_default("geometry is required.");
}
if (!defined_default(attributeName)) {
throw new DeveloperError_default("attributeName is required.");
}
if (!defined_default(attributeName3D)) {
throw new DeveloperError_default("attributeName3D is required.");
}
if (!defined_default(attributeName2D)) {
throw new DeveloperError_default("attributeName2D is required.");
}
if (!defined_default(geometry.attributes[attributeName])) {
throw new DeveloperError_default(
`geometry must have attribute matching the attributeName argument: ${attributeName}.`
);
}
if (geometry.attributes[attributeName].componentDatatype !== ComponentDatatype_default.DOUBLE) {
throw new DeveloperError_default(
"The attribute componentDatatype must be ComponentDatatype.DOUBLE."
);
}
const attribute = geometry.attributes[attributeName];
projection = defined_default(projection) ? projection : new GeographicProjection_default();
const ellipsoid = projection.ellipsoid;
const values3D = attribute.values;
const projectedValues = new Float64Array(values3D.length);
let index = 0;
for (let i = 0; i < values3D.length; i += 3) {
const value = Cartesian3_default.fromArray(
values3D,
i,
scratchProjectTo2DCartesian3
);
const lonLat = ellipsoid.cartesianToCartographic(
value,
scratchProjectTo2DCartographic
);
if (!defined_default(lonLat)) {
throw new DeveloperError_default(
`Could not project point (${value.x}, ${value.y}, ${value.z}) to 2D.`
);
}
const projectedLonLat = projection.project(
lonLat,
scratchProjectTo2DCartesian3
);
projectedValues[index++] = projectedLonLat.x;
projectedValues[index++] = projectedLonLat.y;
projectedValues[index++] = projectedLonLat.z;
}
geometry.attributes[attributeName3D] = attribute;
geometry.attributes[attributeName2D] = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: projectedValues
});
delete geometry.attributes[attributeName];
return geometry;
};
var encodedResult = {
high: 0,
low: 0
};
GeometryPipeline.encodeAttribute = function(geometry, attributeName, attributeHighName, attributeLowName) {
if (!defined_default(geometry)) {
throw new DeveloperError_default("geometry is required.");
}
if (!defined_default(attributeName)) {
throw new DeveloperError_default("attributeName is required.");
}
if (!defined_default(attributeHighName)) {
throw new DeveloperError_default("attributeHighName is required.");
}
if (!defined_default(attributeLowName)) {
throw new DeveloperError_default("attributeLowName is required.");
}
if (!defined_default(geometry.attributes[attributeName])) {
throw new DeveloperError_default(
`geometry must have attribute matching the attributeName argument: ${attributeName}.`
);
}
if (geometry.attributes[attributeName].componentDatatype !== ComponentDatatype_default.DOUBLE) {
throw new DeveloperError_default(
"The attribute componentDatatype must be ComponentDatatype.DOUBLE."
);
}
const attribute = geometry.attributes[attributeName];
const values = attribute.values;
const length2 = values.length;
const highValues = new Float32Array(length2);
const lowValues = new Float32Array(length2);
for (let i = 0; i < length2; ++i) {
EncodedCartesian3_default.encode(values[i], encodedResult);
highValues[i] = encodedResult.high;
lowValues[i] = encodedResult.low;
}
const componentsPerAttribute = attribute.componentsPerAttribute;
geometry.attributes[attributeHighName] = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute,
values: highValues
});
geometry.attributes[attributeLowName] = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute,
values: lowValues
});
delete geometry.attributes[attributeName];
return geometry;
};
var scratchCartesian33 = new Cartesian3_default();
function transformPoint(matrix, attribute) {
if (defined_default(attribute)) {
const values = attribute.values;
const length2 = values.length;
for (let i = 0; i < length2; i += 3) {
Cartesian3_default.unpack(values, i, scratchCartesian33);
Matrix4_default.multiplyByPoint(matrix, scratchCartesian33, scratchCartesian33);
Cartesian3_default.pack(scratchCartesian33, values, i);
}
}
}
function transformVector(matrix, attribute) {
if (defined_default(attribute)) {
const values = attribute.values;
const length2 = values.length;
for (let i = 0; i < length2; i += 3) {
Cartesian3_default.unpack(values, i, scratchCartesian33);
Matrix3_default.multiplyByVector(matrix, scratchCartesian33, scratchCartesian33);
scratchCartesian33 = Cartesian3_default.normalize(
scratchCartesian33,
scratchCartesian33
);
Cartesian3_default.pack(scratchCartesian33, values, i);
}
}
}
var inverseTranspose = new Matrix4_default();
var normalMatrix = new Matrix3_default();
GeometryPipeline.transformToWorldCoordinates = function(instance) {
if (!defined_default(instance)) {
throw new DeveloperError_default("instance is required.");
}
const modelMatrix = instance.modelMatrix;
if (Matrix4_default.equals(modelMatrix, Matrix4_default.IDENTITY)) {
return instance;
}
const attributes = instance.geometry.attributes;
transformPoint(modelMatrix, attributes.position);
transformPoint(modelMatrix, attributes.prevPosition);
transformPoint(modelMatrix, attributes.nextPosition);
if (defined_default(attributes.normal) || defined_default(attributes.tangent) || defined_default(attributes.bitangent)) {
Matrix4_default.inverse(modelMatrix, inverseTranspose);
Matrix4_default.transpose(inverseTranspose, inverseTranspose);
Matrix4_default.getMatrix3(inverseTranspose, normalMatrix);
transformVector(normalMatrix, attributes.normal);
transformVector(normalMatrix, attributes.tangent);
transformVector(normalMatrix, attributes.bitangent);
}
const boundingSphere = instance.geometry.boundingSphere;
if (defined_default(boundingSphere)) {
instance.geometry.boundingSphere = BoundingSphere_default.transform(
boundingSphere,
modelMatrix,
boundingSphere
);
}
instance.modelMatrix = Matrix4_default.clone(Matrix4_default.IDENTITY);
return instance;
};
function findAttributesInAllGeometries(instances, propertyName) {
const length2 = instances.length;
const attributesInAllGeometries = {};
const attributes0 = instances[0][propertyName].attributes;
let name;
for (name in attributes0) {
if (attributes0.hasOwnProperty(name) && defined_default(attributes0[name]) && defined_default(attributes0[name].values)) {
const attribute = attributes0[name];
let numberOfComponents = attribute.values.length;
let inAllGeometries = true;
for (let i = 1; i < length2; ++i) {
const otherAttribute = instances[i][propertyName].attributes[name];
if (!defined_default(otherAttribute) || attribute.componentDatatype !== otherAttribute.componentDatatype || attribute.componentsPerAttribute !== otherAttribute.componentsPerAttribute || attribute.normalize !== otherAttribute.normalize) {
inAllGeometries = false;
break;
}
numberOfComponents += otherAttribute.values.length;
}
if (inAllGeometries) {
attributesInAllGeometries[name] = new GeometryAttribute_default({
componentDatatype: attribute.componentDatatype,
componentsPerAttribute: attribute.componentsPerAttribute,
normalize: attribute.normalize,
values: ComponentDatatype_default.createTypedArray(
attribute.componentDatatype,
numberOfComponents
)
});
}
}
}
return attributesInAllGeometries;
}
var tempScratch = new Cartesian3_default();
function combineGeometries(instances, propertyName) {
const length2 = instances.length;
let name;
let i;
let j;
let k;
const m = instances[0].modelMatrix;
const haveIndices = defined_default(instances[0][propertyName].indices);
const primitiveType = instances[0][propertyName].primitiveType;
for (i = 1; i < length2; ++i) {
if (!Matrix4_default.equals(instances[i].modelMatrix, m)) {
throw new DeveloperError_default("All instances must have the same modelMatrix.");
}
if (defined_default(instances[i][propertyName].indices) !== haveIndices) {
throw new DeveloperError_default(
"All instance geometries must have an indices or not have one."
);
}
if (instances[i][propertyName].primitiveType !== primitiveType) {
throw new DeveloperError_default(
"All instance geometries must have the same primitiveType."
);
}
}
const attributes = findAttributesInAllGeometries(instances, propertyName);
let values;
let sourceValues;
let sourceValuesLength;
for (name in attributes) {
if (attributes.hasOwnProperty(name)) {
values = attributes[name].values;
k = 0;
for (i = 0; i < length2; ++i) {
sourceValues = instances[i][propertyName].attributes[name].values;
sourceValuesLength = sourceValues.length;
for (j = 0; j < sourceValuesLength; ++j) {
values[k++] = sourceValues[j];
}
}
}
}
let indices;
if (haveIndices) {
let numberOfIndices = 0;
for (i = 0; i < length2; ++i) {
numberOfIndices += instances[i][propertyName].indices.length;
}
const numberOfVertices = Geometry_default.computeNumberOfVertices(
new Geometry_default({
attributes,
primitiveType: PrimitiveType_default.POINTS
})
);
const destIndices = IndexDatatype_default.createTypedArray(
numberOfVertices,
numberOfIndices
);
let destOffset = 0;
let offset = 0;
for (i = 0; i < length2; ++i) {
const sourceIndices = instances[i][propertyName].indices;
const sourceIndicesLen = sourceIndices.length;
for (k = 0; k < sourceIndicesLen; ++k) {
destIndices[destOffset++] = offset + sourceIndices[k];
}
offset += Geometry_default.computeNumberOfVertices(instances[i][propertyName]);
}
indices = destIndices;
}
let center = new Cartesian3_default();
let radius = 0;
let bs;
for (i = 0; i < length2; ++i) {
bs = instances[i][propertyName].boundingSphere;
if (!defined_default(bs)) {
center = void 0;
break;
}
Cartesian3_default.add(bs.center, center, center);
}
if (defined_default(center)) {
Cartesian3_default.divideByScalar(center, length2, center);
for (i = 0; i < length2; ++i) {
bs = instances[i][propertyName].boundingSphere;
const tempRadius = Cartesian3_default.magnitude(
Cartesian3_default.subtract(bs.center, center, tempScratch)
) + bs.radius;
if (tempRadius > radius) {
radius = tempRadius;
}
}
}
return new Geometry_default({
attributes,
indices,
primitiveType,
boundingSphere: defined_default(center) ? new BoundingSphere_default(center, radius) : void 0
});
}
GeometryPipeline.combineInstances = function(instances) {
if (!defined_default(instances) || instances.length < 1) {
throw new DeveloperError_default(
"instances is required and must have length greater than zero."
);
}
const instanceGeometry = [];
const instanceSplitGeometry = [];
const length2 = instances.length;
for (let i = 0; i < length2; ++i) {
const instance = instances[i];
if (defined_default(instance.geometry)) {
instanceGeometry.push(instance);
} else if (defined_default(instance.westHemisphereGeometry) && defined_default(instance.eastHemisphereGeometry)) {
instanceSplitGeometry.push(instance);
}
}
const geometries = [];
if (instanceGeometry.length > 0) {
geometries.push(combineGeometries(instanceGeometry, "geometry"));
}
if (instanceSplitGeometry.length > 0) {
geometries.push(
combineGeometries(instanceSplitGeometry, "westHemisphereGeometry")
);
geometries.push(
combineGeometries(instanceSplitGeometry, "eastHemisphereGeometry")
);
}
return geometries;
};
var normal = new Cartesian3_default();
var v0 = new Cartesian3_default();
var v1 = new Cartesian3_default();
var v2 = new Cartesian3_default();
GeometryPipeline.computeNormal = function(geometry) {
if (!defined_default(geometry)) {
throw new DeveloperError_default("geometry is required.");
}
if (!defined_default(geometry.attributes.position) || !defined_default(geometry.attributes.position.values)) {
throw new DeveloperError_default(
"geometry.attributes.position.values is required."
);
}
if (!defined_default(geometry.indices)) {
throw new DeveloperError_default("geometry.indices is required.");
}
if (geometry.indices.length < 2 || geometry.indices.length % 3 !== 0) {
throw new DeveloperError_default(
"geometry.indices length must be greater than 0 and be a multiple of 3."
);
}
if (geometry.primitiveType !== PrimitiveType_default.TRIANGLES) {
throw new DeveloperError_default(
"geometry.primitiveType must be PrimitiveType.TRIANGLES."
);
}
const indices = geometry.indices;
const attributes = geometry.attributes;
const vertices = attributes.position.values;
const numVertices = attributes.position.values.length / 3;
const numIndices = indices.length;
const normalsPerVertex = new Array(numVertices);
const normalsPerTriangle = new Array(numIndices / 3);
const normalIndices = new Array(numIndices);
let i;
for (i = 0; i < numVertices; i++) {
normalsPerVertex[i] = {
indexOffset: 0,
count: 0,
currentCount: 0
};
}
let j = 0;
for (i = 0; i < numIndices; i += 3) {
const i0 = indices[i];
const i1 = indices[i + 1];
const i2 = indices[i + 2];
const i03 = i0 * 3;
const i13 = i1 * 3;
const i23 = i2 * 3;
v0.x = vertices[i03];
v0.y = vertices[i03 + 1];
v0.z = vertices[i03 + 2];
v1.x = vertices[i13];
v1.y = vertices[i13 + 1];
v1.z = vertices[i13 + 2];
v2.x = vertices[i23];
v2.y = vertices[i23 + 1];
v2.z = vertices[i23 + 2];
normalsPerVertex[i0].count++;
normalsPerVertex[i1].count++;
normalsPerVertex[i2].count++;
Cartesian3_default.subtract(v1, v0, v1);
Cartesian3_default.subtract(v2, v0, v2);
normalsPerTriangle[j] = Cartesian3_default.cross(v1, v2, new Cartesian3_default());
j++;
}
let indexOffset = 0;
for (i = 0; i < numVertices; i++) {
normalsPerVertex[i].indexOffset += indexOffset;
indexOffset += normalsPerVertex[i].count;
}
j = 0;
let vertexNormalData;
for (i = 0; i < numIndices; i += 3) {
vertexNormalData = normalsPerVertex[indices[i]];
let index = vertexNormalData.indexOffset + vertexNormalData.currentCount;
normalIndices[index] = j;
vertexNormalData.currentCount++;
vertexNormalData = normalsPerVertex[indices[i + 1]];
index = vertexNormalData.indexOffset + vertexNormalData.currentCount;
normalIndices[index] = j;
vertexNormalData.currentCount++;
vertexNormalData = normalsPerVertex[indices[i + 2]];
index = vertexNormalData.indexOffset + vertexNormalData.currentCount;
normalIndices[index] = j;
vertexNormalData.currentCount++;
j++;
}
const normalValues = new Float32Array(numVertices * 3);
for (i = 0; i < numVertices; i++) {
const i3 = i * 3;
vertexNormalData = normalsPerVertex[i];
Cartesian3_default.clone(Cartesian3_default.ZERO, normal);
if (vertexNormalData.count > 0) {
for (j = 0; j < vertexNormalData.count; j++) {
Cartesian3_default.add(
normal,
normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]],
normal
);
}
if (Cartesian3_default.equalsEpsilon(Cartesian3_default.ZERO, normal, Math_default.EPSILON10)) {
Cartesian3_default.clone(
normalsPerTriangle[normalIndices[vertexNormalData.indexOffset]],
normal
);
}
}
if (Cartesian3_default.equalsEpsilon(Cartesian3_default.ZERO, normal, Math_default.EPSILON10)) {
normal.z = 1;
}
Cartesian3_default.normalize(normal, normal);
normalValues[i3] = normal.x;
normalValues[i3 + 1] = normal.y;
normalValues[i3 + 2] = normal.z;
}
geometry.attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: normalValues
});
return geometry;
};
var normalScratch2 = new Cartesian3_default();
var normalScale = new Cartesian3_default();
var tScratch = new Cartesian3_default();
GeometryPipeline.computeTangentAndBitangent = function(geometry) {
if (!defined_default(geometry)) {
throw new DeveloperError_default("geometry is required.");
}
const attributes = geometry.attributes;
const indices = geometry.indices;
if (!defined_default(attributes.position) || !defined_default(attributes.position.values)) {
throw new DeveloperError_default(
"geometry.attributes.position.values is required."
);
}
if (!defined_default(attributes.normal) || !defined_default(attributes.normal.values)) {
throw new DeveloperError_default("geometry.attributes.normal.values is required.");
}
if (!defined_default(attributes.st) || !defined_default(attributes.st.values)) {
throw new DeveloperError_default("geometry.attributes.st.values is required.");
}
if (!defined_default(indices)) {
throw new DeveloperError_default("geometry.indices is required.");
}
if (indices.length < 2 || indices.length % 3 !== 0) {
throw new DeveloperError_default(
"geometry.indices length must be greater than 0 and be a multiple of 3."
);
}
if (geometry.primitiveType !== PrimitiveType_default.TRIANGLES) {
throw new DeveloperError_default(
"geometry.primitiveType must be PrimitiveType.TRIANGLES."
);
}
const vertices = geometry.attributes.position.values;
const normals = geometry.attributes.normal.values;
const st = geometry.attributes.st.values;
const numVertices = geometry.attributes.position.values.length / 3;
const numIndices = indices.length;
const tan1 = new Array(numVertices * 3);
let i;
for (i = 0; i < tan1.length; i++) {
tan1[i] = 0;
}
let i03;
let i13;
let i23;
for (i = 0; i < numIndices; i += 3) {
const i0 = indices[i];
const i1 = indices[i + 1];
const i2 = indices[i + 2];
i03 = i0 * 3;
i13 = i1 * 3;
i23 = i2 * 3;
const i02 = i0 * 2;
const i12 = i1 * 2;
const i22 = i2 * 2;
const ux = vertices[i03];
const uy = vertices[i03 + 1];
const uz = vertices[i03 + 2];
const wx = st[i02];
const wy = st[i02 + 1];
const t1 = st[i12 + 1] - wy;
const t2 = st[i22 + 1] - wy;
const r = 1 / ((st[i12] - wx) * t2 - (st[i22] - wx) * t1);
const sdirx = (t2 * (vertices[i13] - ux) - t1 * (vertices[i23] - ux)) * r;
const sdiry = (t2 * (vertices[i13 + 1] - uy) - t1 * (vertices[i23 + 1] - uy)) * r;
const sdirz = (t2 * (vertices[i13 + 2] - uz) - t1 * (vertices[i23 + 2] - uz)) * r;
tan1[i03] += sdirx;
tan1[i03 + 1] += sdiry;
tan1[i03 + 2] += sdirz;
tan1[i13] += sdirx;
tan1[i13 + 1] += sdiry;
tan1[i13 + 2] += sdirz;
tan1[i23] += sdirx;
tan1[i23 + 1] += sdiry;
tan1[i23 + 2] += sdirz;
}
const tangentValues = new Float32Array(numVertices * 3);
const bitangentValues = new Float32Array(numVertices * 3);
for (i = 0; i < numVertices; i++) {
i03 = i * 3;
i13 = i03 + 1;
i23 = i03 + 2;
const n = Cartesian3_default.fromArray(normals, i03, normalScratch2);
const t = Cartesian3_default.fromArray(tan1, i03, tScratch);
const scalar = Cartesian3_default.dot(n, t);
Cartesian3_default.multiplyByScalar(n, scalar, normalScale);
Cartesian3_default.normalize(Cartesian3_default.subtract(t, normalScale, t), t);
tangentValues[i03] = t.x;
tangentValues[i13] = t.y;
tangentValues[i23] = t.z;
Cartesian3_default.normalize(Cartesian3_default.cross(n, t, t), t);
bitangentValues[i03] = t.x;
bitangentValues[i13] = t.y;
bitangentValues[i23] = t.z;
}
geometry.attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: tangentValues
});
geometry.attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: bitangentValues
});
return geometry;
};
var scratchCartesian22 = new Cartesian2_default();
var toEncode1 = new Cartesian3_default();
var toEncode2 = new Cartesian3_default();
var toEncode3 = new Cartesian3_default();
var encodeResult2 = new Cartesian2_default();
GeometryPipeline.compressVertices = function(geometry) {
if (!defined_default(geometry)) {
throw new DeveloperError_default("geometry is required.");
}
const extrudeAttribute = geometry.attributes.extrudeDirection;
let i;
let numVertices;
if (defined_default(extrudeAttribute)) {
const extrudeDirections = extrudeAttribute.values;
numVertices = extrudeDirections.length / 3;
const compressedDirections = new Float32Array(numVertices * 2);
let i2 = 0;
for (i = 0; i < numVertices; ++i) {
Cartesian3_default.fromArray(extrudeDirections, i * 3, toEncode1);
if (Cartesian3_default.equals(toEncode1, Cartesian3_default.ZERO)) {
i2 += 2;
continue;
}
encodeResult2 = AttributeCompression_default.octEncodeInRange(
toEncode1,
65535,
encodeResult2
);
compressedDirections[i2++] = encodeResult2.x;
compressedDirections[i2++] = encodeResult2.y;
}
geometry.attributes.compressedAttributes = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: compressedDirections
});
delete geometry.attributes.extrudeDirection;
return geometry;
}
const normalAttribute = geometry.attributes.normal;
const stAttribute = geometry.attributes.st;
const hasNormal = defined_default(normalAttribute);
const hasSt = defined_default(stAttribute);
if (!hasNormal && !hasSt) {
return geometry;
}
const tangentAttribute = geometry.attributes.tangent;
const bitangentAttribute = geometry.attributes.bitangent;
const hasTangent = defined_default(tangentAttribute);
const hasBitangent = defined_default(bitangentAttribute);
let normals;
let st;
let tangents;
let bitangents;
if (hasNormal) {
normals = normalAttribute.values;
}
if (hasSt) {
st = stAttribute.values;
}
if (hasTangent) {
tangents = tangentAttribute.values;
}
if (hasBitangent) {
bitangents = bitangentAttribute.values;
}
const length2 = hasNormal ? normals.length : st.length;
const numComponents = hasNormal ? 3 : 2;
numVertices = length2 / numComponents;
let compressedLength = numVertices;
let numCompressedComponents = hasSt && hasNormal ? 2 : 1;
numCompressedComponents += hasTangent || hasBitangent ? 1 : 0;
compressedLength *= numCompressedComponents;
const compressedAttributes = new Float32Array(compressedLength);
let normalIndex = 0;
for (i = 0; i < numVertices; ++i) {
if (hasSt) {
Cartesian2_default.fromArray(st, i * 2, scratchCartesian22);
compressedAttributes[normalIndex++] = AttributeCompression_default.compressTextureCoordinates(scratchCartesian22);
}
const index = i * 3;
if (hasNormal && defined_default(tangents) && defined_default(bitangents)) {
Cartesian3_default.fromArray(normals, index, toEncode1);
Cartesian3_default.fromArray(tangents, index, toEncode2);
Cartesian3_default.fromArray(bitangents, index, toEncode3);
AttributeCompression_default.octPack(
toEncode1,
toEncode2,
toEncode3,
scratchCartesian22
);
compressedAttributes[normalIndex++] = scratchCartesian22.x;
compressedAttributes[normalIndex++] = scratchCartesian22.y;
} else {
if (hasNormal) {
Cartesian3_default.fromArray(normals, index, toEncode1);
compressedAttributes[normalIndex++] = AttributeCompression_default.octEncodeFloat(toEncode1);
}
if (hasTangent) {
Cartesian3_default.fromArray(tangents, index, toEncode1);
compressedAttributes[normalIndex++] = AttributeCompression_default.octEncodeFloat(toEncode1);
}
if (hasBitangent) {
Cartesian3_default.fromArray(bitangents, index, toEncode1);
compressedAttributes[normalIndex++] = AttributeCompression_default.octEncodeFloat(toEncode1);
}
}
}
geometry.attributes.compressedAttributes = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: numCompressedComponents,
values: compressedAttributes
});
if (hasNormal) {
delete geometry.attributes.normal;
}
if (hasSt) {
delete geometry.attributes.st;
}
if (hasBitangent) {
delete geometry.attributes.bitangent;
}
if (hasTangent) {
delete geometry.attributes.tangent;
}
return geometry;
};
function indexTriangles(geometry) {
if (defined_default(geometry.indices)) {
return geometry;
}
const numberOfVertices = Geometry_default.computeNumberOfVertices(geometry);
if (numberOfVertices < 3) {
throw new DeveloperError_default("The number of vertices must be at least three.");
}
if (numberOfVertices % 3 !== 0) {
throw new DeveloperError_default(
"The number of vertices must be a multiple of three."
);
}
const indices = IndexDatatype_default.createTypedArray(
numberOfVertices,
numberOfVertices
);
for (let i = 0; i < numberOfVertices; ++i) {
indices[i] = i;
}
geometry.indices = indices;
return geometry;
}
function indexTriangleFan(geometry) {
const numberOfVertices = Geometry_default.computeNumberOfVertices(geometry);
if (numberOfVertices < 3) {
throw new DeveloperError_default("The number of vertices must be at least three.");
}
const indices = IndexDatatype_default.createTypedArray(
numberOfVertices,
(numberOfVertices - 2) * 3
);
indices[0] = 1;
indices[1] = 0;
indices[2] = 2;
let indicesIndex = 3;
for (let i = 3; i < numberOfVertices; ++i) {
indices[indicesIndex++] = i - 1;
indices[indicesIndex++] = 0;
indices[indicesIndex++] = i;
}
geometry.indices = indices;
geometry.primitiveType = PrimitiveType_default.TRIANGLES;
return geometry;
}
function indexTriangleStrip(geometry) {
const numberOfVertices = Geometry_default.computeNumberOfVertices(geometry);
if (numberOfVertices < 3) {
throw new DeveloperError_default("The number of vertices must be at least 3.");
}
const indices = IndexDatatype_default.createTypedArray(
numberOfVertices,
(numberOfVertices - 2) * 3
);
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
if (numberOfVertices > 3) {
indices[3] = 0;
indices[4] = 2;
indices[5] = 3;
}
let indicesIndex = 6;
for (let i = 3; i < numberOfVertices - 1; i += 2) {
indices[indicesIndex++] = i;
indices[indicesIndex++] = i - 1;
indices[indicesIndex++] = i + 1;
if (i + 2 < numberOfVertices) {
indices[indicesIndex++] = i;
indices[indicesIndex++] = i + 1;
indices[indicesIndex++] = i + 2;
}
}
geometry.indices = indices;
geometry.primitiveType = PrimitiveType_default.TRIANGLES;
return geometry;
}
function indexLines(geometry) {
if (defined_default(geometry.indices)) {
return geometry;
}
const numberOfVertices = Geometry_default.computeNumberOfVertices(geometry);
if (numberOfVertices < 2) {
throw new DeveloperError_default("The number of vertices must be at least two.");
}
if (numberOfVertices % 2 !== 0) {
throw new DeveloperError_default("The number of vertices must be a multiple of 2.");
}
const indices = IndexDatatype_default.createTypedArray(
numberOfVertices,
numberOfVertices
);
for (let i = 0; i < numberOfVertices; ++i) {
indices[i] = i;
}
geometry.indices = indices;
return geometry;
}
function indexLineStrip(geometry) {
const numberOfVertices = Geometry_default.computeNumberOfVertices(geometry);
if (numberOfVertices < 2) {
throw new DeveloperError_default("The number of vertices must be at least two.");
}
const indices = IndexDatatype_default.createTypedArray(
numberOfVertices,
(numberOfVertices - 1) * 2
);
indices[0] = 0;
indices[1] = 1;
let indicesIndex = 2;
for (let i = 2; i < numberOfVertices; ++i) {
indices[indicesIndex++] = i - 1;
indices[indicesIndex++] = i;
}
geometry.indices = indices;
geometry.primitiveType = PrimitiveType_default.LINES;
return geometry;
}
function indexLineLoop(geometry) {
const numberOfVertices = Geometry_default.computeNumberOfVertices(geometry);
if (numberOfVertices < 2) {
throw new DeveloperError_default("The number of vertices must be at least two.");
}
const indices = IndexDatatype_default.createTypedArray(
numberOfVertices,
numberOfVertices * 2
);
indices[0] = 0;
indices[1] = 1;
let indicesIndex = 2;
for (let i = 2; i < numberOfVertices; ++i) {
indices[indicesIndex++] = i - 1;
indices[indicesIndex++] = i;
}
indices[indicesIndex++] = numberOfVertices - 1;
indices[indicesIndex] = 0;
geometry.indices = indices;
geometry.primitiveType = PrimitiveType_default.LINES;
return geometry;
}
function indexPrimitive(geometry) {
switch (geometry.primitiveType) {
case PrimitiveType_default.TRIANGLE_FAN:
return indexTriangleFan(geometry);
case PrimitiveType_default.TRIANGLE_STRIP:
return indexTriangleStrip(geometry);
case PrimitiveType_default.TRIANGLES:
return indexTriangles(geometry);
case PrimitiveType_default.LINE_STRIP:
return indexLineStrip(geometry);
case PrimitiveType_default.LINE_LOOP:
return indexLineLoop(geometry);
case PrimitiveType_default.LINES:
return indexLines(geometry);
}
return geometry;
}
function offsetPointFromXZPlane(p, isBehind) {
if (Math.abs(p.y) < Math_default.EPSILON6) {
if (isBehind) {
p.y = -Math_default.EPSILON6;
} else {
p.y = Math_default.EPSILON6;
}
}
}
function offsetTriangleFromXZPlane(p0, p1, p2) {
if (p0.y !== 0 && p1.y !== 0 && p2.y !== 0) {
offsetPointFromXZPlane(p0, p0.y < 0);
offsetPointFromXZPlane(p1, p1.y < 0);
offsetPointFromXZPlane(p2, p2.y < 0);
return;
}
const p0y = Math.abs(p0.y);
const p1y = Math.abs(p1.y);
const p2y = Math.abs(p2.y);
let sign3;
if (p0y > p1y) {
if (p0y > p2y) {
sign3 = Math_default.sign(p0.y);
} else {
sign3 = Math_default.sign(p2.y);
}
} else if (p1y > p2y) {
sign3 = Math_default.sign(p1.y);
} else {
sign3 = Math_default.sign(p2.y);
}
const isBehind = sign3 < 0;
offsetPointFromXZPlane(p0, isBehind);
offsetPointFromXZPlane(p1, isBehind);
offsetPointFromXZPlane(p2, isBehind);
}
var c3 = new Cartesian3_default();
function getXZIntersectionOffsetPoints(p, p1, u12, v12) {
Cartesian3_default.add(
p,
Cartesian3_default.multiplyByScalar(
Cartesian3_default.subtract(p1, p, c3),
p.y / (p.y - p1.y),
c3
),
u12
);
Cartesian3_default.clone(u12, v12);
offsetPointFromXZPlane(u12, true);
offsetPointFromXZPlane(v12, false);
}
var u1 = new Cartesian3_default();
var u2 = new Cartesian3_default();
var q1 = new Cartesian3_default();
var q2 = new Cartesian3_default();
var splitTriangleResult = {
positions: new Array(7),
indices: new Array(3 * 3)
};
function splitTriangle(p0, p1, p2) {
if (p0.x >= 0 || p1.x >= 0 || p2.x >= 0) {
return void 0;
}
offsetTriangleFromXZPlane(p0, p1, p2);
const p0Behind = p0.y < 0;
const p1Behind = p1.y < 0;
const p2Behind = p2.y < 0;
let numBehind = 0;
numBehind += p0Behind ? 1 : 0;
numBehind += p1Behind ? 1 : 0;
numBehind += p2Behind ? 1 : 0;
const indices = splitTriangleResult.indices;
if (numBehind === 1) {
indices[1] = 3;
indices[2] = 4;
indices[5] = 6;
indices[7] = 6;
indices[8] = 5;
if (p0Behind) {
getXZIntersectionOffsetPoints(p0, p1, u1, q1);
getXZIntersectionOffsetPoints(p0, p2, u2, q2);
indices[0] = 0;
indices[3] = 1;
indices[4] = 2;
indices[6] = 1;
} else if (p1Behind) {
getXZIntersectionOffsetPoints(p1, p2, u1, q1);
getXZIntersectionOffsetPoints(p1, p0, u2, q2);
indices[0] = 1;
indices[3] = 2;
indices[4] = 0;
indices[6] = 2;
} else if (p2Behind) {
getXZIntersectionOffsetPoints(p2, p0, u1, q1);
getXZIntersectionOffsetPoints(p2, p1, u2, q2);
indices[0] = 2;
indices[3] = 0;
indices[4] = 1;
indices[6] = 0;
}
} else if (numBehind === 2) {
indices[2] = 4;
indices[4] = 4;
indices[5] = 3;
indices[7] = 5;
indices[8] = 6;
if (!p0Behind) {
getXZIntersectionOffsetPoints(p0, p1, u1, q1);
getXZIntersectionOffsetPoints(p0, p2, u2, q2);
indices[0] = 1;
indices[1] = 2;
indices[3] = 1;
indices[6] = 0;
} else if (!p1Behind) {
getXZIntersectionOffsetPoints(p1, p2, u1, q1);
getXZIntersectionOffsetPoints(p1, p0, u2, q2);
indices[0] = 2;
indices[1] = 0;
indices[3] = 2;
indices[6] = 1;
} else if (!p2Behind) {
getXZIntersectionOffsetPoints(p2, p0, u1, q1);
getXZIntersectionOffsetPoints(p2, p1, u2, q2);
indices[0] = 0;
indices[1] = 1;
indices[3] = 0;
indices[6] = 2;
}
}
const positions = splitTriangleResult.positions;
positions[0] = p0;
positions[1] = p1;
positions[2] = p2;
positions.length = 3;
if (numBehind === 1 || numBehind === 2) {
positions[3] = u1;
positions[4] = u2;
positions[5] = q1;
positions[6] = q2;
positions.length = 7;
}
return splitTriangleResult;
}
function updateGeometryAfterSplit(geometry, computeBoundingSphere) {
const attributes = geometry.attributes;
if (attributes.position.values.length === 0) {
return void 0;
}
for (const property in attributes) {
if (attributes.hasOwnProperty(property) && defined_default(attributes[property]) && defined_default(attributes[property].values)) {
const attribute = attributes[property];
attribute.values = ComponentDatatype_default.createTypedArray(
attribute.componentDatatype,
attribute.values
);
}
}
const numberOfVertices = Geometry_default.computeNumberOfVertices(geometry);
geometry.indices = IndexDatatype_default.createTypedArray(
numberOfVertices,
geometry.indices
);
if (computeBoundingSphere) {
geometry.boundingSphere = BoundingSphere_default.fromVertices(
attributes.position.values
);
}
return geometry;
}
function copyGeometryForSplit(geometry) {
const attributes = geometry.attributes;
const copiedAttributes = {};
for (const property in attributes) {
if (attributes.hasOwnProperty(property) && defined_default(attributes[property]) && defined_default(attributes[property].values)) {
const attribute = attributes[property];
copiedAttributes[property] = new GeometryAttribute_default({
componentDatatype: attribute.componentDatatype,
componentsPerAttribute: attribute.componentsPerAttribute,
normalize: attribute.normalize,
values: []
});
}
}
return new Geometry_default({
attributes: copiedAttributes,
indices: [],
primitiveType: geometry.primitiveType
});
}
function updateInstanceAfterSplit(instance, westGeometry, eastGeometry) {
const computeBoundingSphere = defined_default(instance.geometry.boundingSphere);
westGeometry = updateGeometryAfterSplit(westGeometry, computeBoundingSphere);
eastGeometry = updateGeometryAfterSplit(eastGeometry, computeBoundingSphere);
if (defined_default(eastGeometry) && !defined_default(westGeometry)) {
instance.geometry = eastGeometry;
} else if (!defined_default(eastGeometry) && defined_default(westGeometry)) {
instance.geometry = westGeometry;
} else {
instance.westHemisphereGeometry = westGeometry;
instance.eastHemisphereGeometry = eastGeometry;
instance.geometry = void 0;
}
}
function generateBarycentricInterpolateFunction(CartesianType, numberOfComponents) {
const v0Scratch = new CartesianType();
const v1Scratch2 = new CartesianType();
const v2Scratch2 = new CartesianType();
return function(i0, i1, i2, coords, sourceValues, currentValues, insertedIndex, normalize2) {
const v02 = CartesianType.fromArray(
sourceValues,
i0 * numberOfComponents,
v0Scratch
);
const v12 = CartesianType.fromArray(
sourceValues,
i1 * numberOfComponents,
v1Scratch2
);
const v22 = CartesianType.fromArray(
sourceValues,
i2 * numberOfComponents,
v2Scratch2
);
CartesianType.multiplyByScalar(v02, coords.x, v02);
CartesianType.multiplyByScalar(v12, coords.y, v12);
CartesianType.multiplyByScalar(v22, coords.z, v22);
const value = CartesianType.add(v02, v12, v02);
CartesianType.add(value, v22, value);
if (normalize2) {
CartesianType.normalize(value, value);
}
CartesianType.pack(
value,
currentValues,
insertedIndex * numberOfComponents
);
};
}
var interpolateAndPackCartesian4 = generateBarycentricInterpolateFunction(
Cartesian4_default,
4
);
var interpolateAndPackCartesian3 = generateBarycentricInterpolateFunction(
Cartesian3_default,
3
);
var interpolateAndPackCartesian2 = generateBarycentricInterpolateFunction(
Cartesian2_default,
2
);
var interpolateAndPackBoolean = function(i0, i1, i2, coords, sourceValues, currentValues, insertedIndex) {
const v12 = sourceValues[i0] * coords.x;
const v22 = sourceValues[i1] * coords.y;
const v3 = sourceValues[i2] * coords.z;
currentValues[insertedIndex] = v12 + v22 + v3 > Math_default.EPSILON6 ? 1 : 0;
};
var p0Scratch = new Cartesian3_default();
var p1Scratch = new Cartesian3_default();
var p2Scratch = new Cartesian3_default();
var barycentricScratch = new Cartesian3_default();
function computeTriangleAttributes(i0, i1, i2, point, positions, normals, tangents, bitangents, texCoords, extrudeDirections, applyOffset, currentAttributes, customAttributeNames, customAttributesLength, allAttributes, insertedIndex) {
if (!defined_default(normals) && !defined_default(tangents) && !defined_default(bitangents) && !defined_default(texCoords) && !defined_default(extrudeDirections) && customAttributesLength === 0) {
return;
}
const p0 = Cartesian3_default.fromArray(positions, i0 * 3, p0Scratch);
const p1 = Cartesian3_default.fromArray(positions, i1 * 3, p1Scratch);
const p2 = Cartesian3_default.fromArray(positions, i2 * 3, p2Scratch);
const coords = barycentricCoordinates_default(point, p0, p1, p2, barycentricScratch);
if (!defined_default(coords)) {
return;
}
if (defined_default(normals)) {
interpolateAndPackCartesian3(
i0,
i1,
i2,
coords,
normals,
currentAttributes.normal.values,
insertedIndex,
true
);
}
if (defined_default(extrudeDirections)) {
const d0 = Cartesian3_default.fromArray(extrudeDirections, i0 * 3, p0Scratch);
const d1 = Cartesian3_default.fromArray(extrudeDirections, i1 * 3, p1Scratch);
const d2 = Cartesian3_default.fromArray(extrudeDirections, i2 * 3, p2Scratch);
Cartesian3_default.multiplyByScalar(d0, coords.x, d0);
Cartesian3_default.multiplyByScalar(d1, coords.y, d1);
Cartesian3_default.multiplyByScalar(d2, coords.z, d2);
let direction2;
if (!Cartesian3_default.equals(d0, Cartesian3_default.ZERO) || !Cartesian3_default.equals(d1, Cartesian3_default.ZERO) || !Cartesian3_default.equals(d2, Cartesian3_default.ZERO)) {
direction2 = Cartesian3_default.add(d0, d1, d0);
Cartesian3_default.add(direction2, d2, direction2);
Cartesian3_default.normalize(direction2, direction2);
} else {
direction2 = p0Scratch;
direction2.x = 0;
direction2.y = 0;
direction2.z = 0;
}
Cartesian3_default.pack(
direction2,
currentAttributes.extrudeDirection.values,
insertedIndex * 3
);
}
if (defined_default(applyOffset)) {
interpolateAndPackBoolean(
i0,
i1,
i2,
coords,
applyOffset,
currentAttributes.applyOffset.values,
insertedIndex
);
}
if (defined_default(tangents)) {
interpolateAndPackCartesian3(
i0,
i1,
i2,
coords,
tangents,
currentAttributes.tangent.values,
insertedIndex,
true
);
}
if (defined_default(bitangents)) {
interpolateAndPackCartesian3(
i0,
i1,
i2,
coords,
bitangents,
currentAttributes.bitangent.values,
insertedIndex,
true
);
}
if (defined_default(texCoords)) {
interpolateAndPackCartesian2(
i0,
i1,
i2,
coords,
texCoords,
currentAttributes.st.values,
insertedIndex
);
}
if (customAttributesLength > 0) {
for (let i = 0; i < customAttributesLength; i++) {
const attributeName = customAttributeNames[i];
genericInterpolate(
i0,
i1,
i2,
coords,
insertedIndex,
allAttributes[attributeName],
currentAttributes[attributeName]
);
}
}
}
function genericInterpolate(i0, i1, i2, coords, insertedIndex, sourceAttribute, currentAttribute) {
const componentsPerAttribute = sourceAttribute.componentsPerAttribute;
const sourceValues = sourceAttribute.values;
const currentValues = currentAttribute.values;
switch (componentsPerAttribute) {
case 4:
interpolateAndPackCartesian4(
i0,
i1,
i2,
coords,
sourceValues,
currentValues,
insertedIndex,
false
);
break;
case 3:
interpolateAndPackCartesian3(
i0,
i1,
i2,
coords,
sourceValues,
currentValues,
insertedIndex,
false
);
break;
case 2:
interpolateAndPackCartesian2(
i0,
i1,
i2,
coords,
sourceValues,
currentValues,
insertedIndex,
false
);
break;
default:
currentValues[insertedIndex] = sourceValues[i0] * coords.x + sourceValues[i1] * coords.y + sourceValues[i2] * coords.z;
}
}
function insertSplitPoint(currentAttributes, currentIndices, currentIndexMap, indices, currentIndex, point) {
const insertIndex = currentAttributes.position.values.length / 3;
if (currentIndex !== -1) {
const prevIndex = indices[currentIndex];
const newIndex = currentIndexMap[prevIndex];
if (newIndex === -1) {
currentIndexMap[prevIndex] = insertIndex;
currentAttributes.position.values.push(point.x, point.y, point.z);
currentIndices.push(insertIndex);
return insertIndex;
}
currentIndices.push(newIndex);
return newIndex;
}
currentAttributes.position.values.push(point.x, point.y, point.z);
currentIndices.push(insertIndex);
return insertIndex;
}
var NAMED_ATTRIBUTES = {
position: true,
normal: true,
bitangent: true,
tangent: true,
st: true,
extrudeDirection: true,
applyOffset: true
};
function splitLongitudeTriangles(instance) {
const geometry = instance.geometry;
const attributes = geometry.attributes;
const positions = attributes.position.values;
const normals = defined_default(attributes.normal) ? attributes.normal.values : void 0;
const bitangents = defined_default(attributes.bitangent) ? attributes.bitangent.values : void 0;
const tangents = defined_default(attributes.tangent) ? attributes.tangent.values : void 0;
const texCoords = defined_default(attributes.st) ? attributes.st.values : void 0;
const extrudeDirections = defined_default(attributes.extrudeDirection) ? attributes.extrudeDirection.values : void 0;
const applyOffset = defined_default(attributes.applyOffset) ? attributes.applyOffset.values : void 0;
const indices = geometry.indices;
const customAttributeNames = [];
for (const attributeName in attributes) {
if (attributes.hasOwnProperty(attributeName) && !NAMED_ATTRIBUTES[attributeName] && defined_default(attributes[attributeName])) {
customAttributeNames.push(attributeName);
}
}
const customAttributesLength = customAttributeNames.length;
const eastGeometry = copyGeometryForSplit(geometry);
const westGeometry = copyGeometryForSplit(geometry);
let currentAttributes;
let currentIndices;
let currentIndexMap;
let insertedIndex;
let i;
const westGeometryIndexMap = [];
westGeometryIndexMap.length = positions.length / 3;
const eastGeometryIndexMap = [];
eastGeometryIndexMap.length = positions.length / 3;
for (i = 0; i < westGeometryIndexMap.length; ++i) {
westGeometryIndexMap[i] = -1;
eastGeometryIndexMap[i] = -1;
}
const len = indices.length;
for (i = 0; i < len; i += 3) {
const i0 = indices[i];
const i1 = indices[i + 1];
const i2 = indices[i + 2];
let p0 = Cartesian3_default.fromArray(positions, i0 * 3);
let p1 = Cartesian3_default.fromArray(positions, i1 * 3);
let p2 = Cartesian3_default.fromArray(positions, i2 * 3);
const result = splitTriangle(p0, p1, p2);
if (defined_default(result) && result.positions.length > 3) {
const resultPositions = result.positions;
const resultIndices = result.indices;
const resultLength = resultIndices.length;
for (let j = 0; j < resultLength; ++j) {
const resultIndex = resultIndices[j];
const point = resultPositions[resultIndex];
if (point.y < 0) {
currentAttributes = westGeometry.attributes;
currentIndices = westGeometry.indices;
currentIndexMap = westGeometryIndexMap;
} else {
currentAttributes = eastGeometry.attributes;
currentIndices = eastGeometry.indices;
currentIndexMap = eastGeometryIndexMap;
}
insertedIndex = insertSplitPoint(
currentAttributes,
currentIndices,
currentIndexMap,
indices,
resultIndex < 3 ? i + resultIndex : -1,
point
);
computeTriangleAttributes(
i0,
i1,
i2,
point,
positions,
normals,
tangents,
bitangents,
texCoords,
extrudeDirections,
applyOffset,
currentAttributes,
customAttributeNames,
customAttributesLength,
attributes,
insertedIndex
);
}
} else {
if (defined_default(result)) {
p0 = result.positions[0];
p1 = result.positions[1];
p2 = result.positions[2];
}
if (p0.y < 0) {
currentAttributes = westGeometry.attributes;
currentIndices = westGeometry.indices;
currentIndexMap = westGeometryIndexMap;
} else {
currentAttributes = eastGeometry.attributes;
currentIndices = eastGeometry.indices;
currentIndexMap = eastGeometryIndexMap;
}
insertedIndex = insertSplitPoint(
currentAttributes,
currentIndices,
currentIndexMap,
indices,
i,
p0
);
computeTriangleAttributes(
i0,
i1,
i2,
p0,
positions,
normals,
tangents,
bitangents,
texCoords,
extrudeDirections,
applyOffset,
currentAttributes,
customAttributeNames,
customAttributesLength,
attributes,
insertedIndex
);
insertedIndex = insertSplitPoint(
currentAttributes,
currentIndices,
currentIndexMap,
indices,
i + 1,
p1
);
computeTriangleAttributes(
i0,
i1,
i2,
p1,
positions,
normals,
tangents,
bitangents,
texCoords,
extrudeDirections,
applyOffset,
currentAttributes,
customAttributeNames,
customAttributesLength,
attributes,
insertedIndex
);
insertedIndex = insertSplitPoint(
currentAttributes,
currentIndices,
currentIndexMap,
indices,
i + 2,
p2
);
computeTriangleAttributes(
i0,
i1,
i2,
p2,
positions,
normals,
tangents,
bitangents,
texCoords,
extrudeDirections,
applyOffset,
currentAttributes,
customAttributeNames,
customAttributesLength,
attributes,
insertedIndex
);
}
}
updateInstanceAfterSplit(instance, westGeometry, eastGeometry);
}
var xzPlane = Plane_default.fromPointNormal(Cartesian3_default.ZERO, Cartesian3_default.UNIT_Y);
var offsetScratch = new Cartesian3_default();
var offsetPointScratch = new Cartesian3_default();
function computeLineAttributes(i0, i1, point, positions, insertIndex, currentAttributes, applyOffset) {
if (!defined_default(applyOffset)) {
return;
}
const p0 = Cartesian3_default.fromArray(positions, i0 * 3, p0Scratch);
if (Cartesian3_default.equalsEpsilon(p0, point, Math_default.EPSILON10)) {
currentAttributes.applyOffset.values[insertIndex] = applyOffset[i0];
} else {
currentAttributes.applyOffset.values[insertIndex] = applyOffset[i1];
}
}
function splitLongitudeLines(instance) {
const geometry = instance.geometry;
const attributes = geometry.attributes;
const positions = attributes.position.values;
const applyOffset = defined_default(attributes.applyOffset) ? attributes.applyOffset.values : void 0;
const indices = geometry.indices;
const eastGeometry = copyGeometryForSplit(geometry);
const westGeometry = copyGeometryForSplit(geometry);
let i;
const length2 = indices.length;
const westGeometryIndexMap = [];
westGeometryIndexMap.length = positions.length / 3;
const eastGeometryIndexMap = [];
eastGeometryIndexMap.length = positions.length / 3;
for (i = 0; i < westGeometryIndexMap.length; ++i) {
westGeometryIndexMap[i] = -1;
eastGeometryIndexMap[i] = -1;
}
for (i = 0; i < length2; i += 2) {
const i0 = indices[i];
const i1 = indices[i + 1];
const p0 = Cartesian3_default.fromArray(positions, i0 * 3, p0Scratch);
const p1 = Cartesian3_default.fromArray(positions, i1 * 3, p1Scratch);
let insertIndex;
if (Math.abs(p0.y) < Math_default.EPSILON6) {
if (p0.y < 0) {
p0.y = -Math_default.EPSILON6;
} else {
p0.y = Math_default.EPSILON6;
}
}
if (Math.abs(p1.y) < Math_default.EPSILON6) {
if (p1.y < 0) {
p1.y = -Math_default.EPSILON6;
} else {
p1.y = Math_default.EPSILON6;
}
}
let p0Attributes = eastGeometry.attributes;
let p0Indices = eastGeometry.indices;
let p0IndexMap = eastGeometryIndexMap;
let p1Attributes = westGeometry.attributes;
let p1Indices = westGeometry.indices;
let p1IndexMap = westGeometryIndexMap;
const intersection = IntersectionTests_default.lineSegmentPlane(
p0,
p1,
xzPlane,
p2Scratch
);
if (defined_default(intersection)) {
const offset = Cartesian3_default.multiplyByScalar(
Cartesian3_default.UNIT_Y,
5 * Math_default.EPSILON9,
offsetScratch
);
if (p0.y < 0) {
Cartesian3_default.negate(offset, offset);
p0Attributes = westGeometry.attributes;
p0Indices = westGeometry.indices;
p0IndexMap = westGeometryIndexMap;
p1Attributes = eastGeometry.attributes;
p1Indices = eastGeometry.indices;
p1IndexMap = eastGeometryIndexMap;
}
const offsetPoint = Cartesian3_default.add(
intersection,
offset,
offsetPointScratch
);
insertIndex = insertSplitPoint(
p0Attributes,
p0Indices,
p0IndexMap,
indices,
i,
p0
);
computeLineAttributes(
i0,
i1,
p0,
positions,
insertIndex,
p0Attributes,
applyOffset
);
insertIndex = insertSplitPoint(
p0Attributes,
p0Indices,
p0IndexMap,
indices,
-1,
offsetPoint
);
computeLineAttributes(
i0,
i1,
offsetPoint,
positions,
insertIndex,
p0Attributes,
applyOffset
);
Cartesian3_default.negate(offset, offset);
Cartesian3_default.add(intersection, offset, offsetPoint);
insertIndex = insertSplitPoint(
p1Attributes,
p1Indices,
p1IndexMap,
indices,
-1,
offsetPoint
);
computeLineAttributes(
i0,
i1,
offsetPoint,
positions,
insertIndex,
p1Attributes,
applyOffset
);
insertIndex = insertSplitPoint(
p1Attributes,
p1Indices,
p1IndexMap,
indices,
i + 1,
p1
);
computeLineAttributes(
i0,
i1,
p1,
positions,
insertIndex,
p1Attributes,
applyOffset
);
} else {
let currentAttributes;
let currentIndices;
let currentIndexMap;
if (p0.y < 0) {
currentAttributes = westGeometry.attributes;
currentIndices = westGeometry.indices;
currentIndexMap = westGeometryIndexMap;
} else {
currentAttributes = eastGeometry.attributes;
currentIndices = eastGeometry.indices;
currentIndexMap = eastGeometryIndexMap;
}
insertIndex = insertSplitPoint(
currentAttributes,
currentIndices,
currentIndexMap,
indices,
i,
p0
);
computeLineAttributes(
i0,
i1,
p0,
positions,
insertIndex,
currentAttributes,
applyOffset
);
insertIndex = insertSplitPoint(
currentAttributes,
currentIndices,
currentIndexMap,
indices,
i + 1,
p1
);
computeLineAttributes(
i0,
i1,
p1,
positions,
insertIndex,
currentAttributes,
applyOffset
);
}
}
updateInstanceAfterSplit(instance, westGeometry, eastGeometry);
}
var cartesian2Scratch0 = new Cartesian2_default();
var cartesian2Scratch1 = new Cartesian2_default();
var cartesian3Scratch0 = new Cartesian3_default();
var cartesian3Scratch2 = new Cartesian3_default();
var cartesian3Scratch3 = new Cartesian3_default();
var cartesian3Scratch4 = new Cartesian3_default();
var cartesian3Scratch5 = new Cartesian3_default();
var cartesian3Scratch6 = new Cartesian3_default();
var cartesian4Scratch0 = new Cartesian4_default();
function updateAdjacencyAfterSplit(geometry) {
const attributes = geometry.attributes;
const positions = attributes.position.values;
const prevPositions = attributes.prevPosition.values;
const nextPositions = attributes.nextPosition.values;
const length2 = positions.length;
for (let j = 0; j < length2; j += 3) {
const position = Cartesian3_default.unpack(positions, j, cartesian3Scratch0);
if (position.x > 0) {
continue;
}
const prevPosition = Cartesian3_default.unpack(
prevPositions,
j,
cartesian3Scratch2
);
if (position.y < 0 && prevPosition.y > 0 || position.y > 0 && prevPosition.y < 0) {
if (j - 3 > 0) {
prevPositions[j] = positions[j - 3];
prevPositions[j + 1] = positions[j - 2];
prevPositions[j + 2] = positions[j - 1];
} else {
Cartesian3_default.pack(position, prevPositions, j);
}
}
const nextPosition = Cartesian3_default.unpack(
nextPositions,
j,
cartesian3Scratch3
);
if (position.y < 0 && nextPosition.y > 0 || position.y > 0 && nextPosition.y < 0) {
if (j + 3 < length2) {
nextPositions[j] = positions[j + 3];
nextPositions[j + 1] = positions[j + 4];
nextPositions[j + 2] = positions[j + 5];
} else {
Cartesian3_default.pack(position, nextPositions, j);
}
}
}
}
var offsetScalar = 5 * Math_default.EPSILON9;
var coplanarOffset = Math_default.EPSILON6;
function splitLongitudePolyline(instance) {
const geometry = instance.geometry;
const attributes = geometry.attributes;
const positions = attributes.position.values;
const prevPositions = attributes.prevPosition.values;
const nextPositions = attributes.nextPosition.values;
const expandAndWidths = attributes.expandAndWidth.values;
const texCoords = defined_default(attributes.st) ? attributes.st.values : void 0;
const colors = defined_default(attributes.color) ? attributes.color.values : void 0;
const eastGeometry = copyGeometryForSplit(geometry);
const westGeometry = copyGeometryForSplit(geometry);
let i;
let j;
let index;
let intersectionFound = false;
const length2 = positions.length / 3;
for (i = 0; i < length2; i += 4) {
const i0 = i;
const i2 = i + 2;
const p0 = Cartesian3_default.fromArray(positions, i0 * 3, cartesian3Scratch0);
const p2 = Cartesian3_default.fromArray(positions, i2 * 3, cartesian3Scratch2);
if (Math.abs(p0.y) < coplanarOffset) {
p0.y = coplanarOffset * (p2.y < 0 ? -1 : 1);
positions[i * 3 + 1] = p0.y;
positions[(i + 1) * 3 + 1] = p0.y;
for (j = i0 * 3; j < i0 * 3 + 4 * 3; j += 3) {
prevPositions[j] = positions[i * 3];
prevPositions[j + 1] = positions[i * 3 + 1];
prevPositions[j + 2] = positions[i * 3 + 2];
}
}
if (Math.abs(p2.y) < coplanarOffset) {
p2.y = coplanarOffset * (p0.y < 0 ? -1 : 1);
positions[(i + 2) * 3 + 1] = p2.y;
positions[(i + 3) * 3 + 1] = p2.y;
for (j = i0 * 3; j < i0 * 3 + 4 * 3; j += 3) {
nextPositions[j] = positions[(i + 2) * 3];
nextPositions[j + 1] = positions[(i + 2) * 3 + 1];
nextPositions[j + 2] = positions[(i + 2) * 3 + 2];
}
}
let p0Attributes = eastGeometry.attributes;
let p0Indices = eastGeometry.indices;
let p2Attributes = westGeometry.attributes;
let p2Indices = westGeometry.indices;
const intersection = IntersectionTests_default.lineSegmentPlane(
p0,
p2,
xzPlane,
cartesian3Scratch4
);
if (defined_default(intersection)) {
intersectionFound = true;
const offset = Cartesian3_default.multiplyByScalar(
Cartesian3_default.UNIT_Y,
offsetScalar,
cartesian3Scratch5
);
if (p0.y < 0) {
Cartesian3_default.negate(offset, offset);
p0Attributes = westGeometry.attributes;
p0Indices = westGeometry.indices;
p2Attributes = eastGeometry.attributes;
p2Indices = eastGeometry.indices;
}
const offsetPoint = Cartesian3_default.add(
intersection,
offset,
cartesian3Scratch6
);
p0Attributes.position.values.push(p0.x, p0.y, p0.z, p0.x, p0.y, p0.z);
p0Attributes.position.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
p0Attributes.position.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
p0Attributes.prevPosition.values.push(
prevPositions[i0 * 3],
prevPositions[i0 * 3 + 1],
prevPositions[i0 * 3 + 2]
);
p0Attributes.prevPosition.values.push(
prevPositions[i0 * 3 + 3],
prevPositions[i0 * 3 + 4],
prevPositions[i0 * 3 + 5]
);
p0Attributes.prevPosition.values.push(p0.x, p0.y, p0.z, p0.x, p0.y, p0.z);
p0Attributes.nextPosition.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
p0Attributes.nextPosition.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
p0Attributes.nextPosition.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
p0Attributes.nextPosition.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
Cartesian3_default.negate(offset, offset);
Cartesian3_default.add(intersection, offset, offsetPoint);
p2Attributes.position.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
p2Attributes.position.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
p2Attributes.position.values.push(p2.x, p2.y, p2.z, p2.x, p2.y, p2.z);
p2Attributes.prevPosition.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
p2Attributes.prevPosition.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
p2Attributes.prevPosition.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
p2Attributes.prevPosition.values.push(
offsetPoint.x,
offsetPoint.y,
offsetPoint.z
);
p2Attributes.nextPosition.values.push(p2.x, p2.y, p2.z, p2.x, p2.y, p2.z);
p2Attributes.nextPosition.values.push(
nextPositions[i2 * 3],
nextPositions[i2 * 3 + 1],
nextPositions[i2 * 3 + 2]
);
p2Attributes.nextPosition.values.push(
nextPositions[i2 * 3 + 3],
nextPositions[i2 * 3 + 4],
nextPositions[i2 * 3 + 5]
);
const ew0 = Cartesian2_default.fromArray(
expandAndWidths,
i0 * 2,
cartesian2Scratch0
);
const width = Math.abs(ew0.y);
p0Attributes.expandAndWidth.values.push(-1, width, 1, width);
p0Attributes.expandAndWidth.values.push(-1, -width, 1, -width);
p2Attributes.expandAndWidth.values.push(-1, width, 1, width);
p2Attributes.expandAndWidth.values.push(-1, -width, 1, -width);
let t = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(intersection, p0, cartesian3Scratch3)
);
t /= Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(p2, p0, cartesian3Scratch3)
);
if (defined_default(colors)) {
const c0 = Cartesian4_default.fromArray(colors, i0 * 4, cartesian4Scratch0);
const c22 = Cartesian4_default.fromArray(colors, i2 * 4, cartesian4Scratch0);
const r = Math_default.lerp(c0.x, c22.x, t);
const g = Math_default.lerp(c0.y, c22.y, t);
const b = Math_default.lerp(c0.z, c22.z, t);
const a3 = Math_default.lerp(c0.w, c22.w, t);
for (j = i0 * 4; j < i0 * 4 + 2 * 4; ++j) {
p0Attributes.color.values.push(colors[j]);
}
p0Attributes.color.values.push(r, g, b, a3);
p0Attributes.color.values.push(r, g, b, a3);
p2Attributes.color.values.push(r, g, b, a3);
p2Attributes.color.values.push(r, g, b, a3);
for (j = i2 * 4; j < i2 * 4 + 2 * 4; ++j) {
p2Attributes.color.values.push(colors[j]);
}
}
if (defined_default(texCoords)) {
const s0 = Cartesian2_default.fromArray(texCoords, i0 * 2, cartesian2Scratch0);
const s3 = Cartesian2_default.fromArray(
texCoords,
(i + 3) * 2,
cartesian2Scratch1
);
const sx = Math_default.lerp(s0.x, s3.x, t);
for (j = i0 * 2; j < i0 * 2 + 2 * 2; ++j) {
p0Attributes.st.values.push(texCoords[j]);
}
p0Attributes.st.values.push(sx, s0.y);
p0Attributes.st.values.push(sx, s3.y);
p2Attributes.st.values.push(sx, s0.y);
p2Attributes.st.values.push(sx, s3.y);
for (j = i2 * 2; j < i2 * 2 + 2 * 2; ++j) {
p2Attributes.st.values.push(texCoords[j]);
}
}
index = p0Attributes.position.values.length / 3 - 4;
p0Indices.push(index, index + 2, index + 1);
p0Indices.push(index + 1, index + 2, index + 3);
index = p2Attributes.position.values.length / 3 - 4;
p2Indices.push(index, index + 2, index + 1);
p2Indices.push(index + 1, index + 2, index + 3);
} else {
let currentAttributes;
let currentIndices;
if (p0.y < 0) {
currentAttributes = westGeometry.attributes;
currentIndices = westGeometry.indices;
} else {
currentAttributes = eastGeometry.attributes;
currentIndices = eastGeometry.indices;
}
currentAttributes.position.values.push(p0.x, p0.y, p0.z);
currentAttributes.position.values.push(p0.x, p0.y, p0.z);
currentAttributes.position.values.push(p2.x, p2.y, p2.z);
currentAttributes.position.values.push(p2.x, p2.y, p2.z);
for (j = i * 3; j < i * 3 + 4 * 3; ++j) {
currentAttributes.prevPosition.values.push(prevPositions[j]);
currentAttributes.nextPosition.values.push(nextPositions[j]);
}
for (j = i * 2; j < i * 2 + 4 * 2; ++j) {
currentAttributes.expandAndWidth.values.push(expandAndWidths[j]);
if (defined_default(texCoords)) {
currentAttributes.st.values.push(texCoords[j]);
}
}
if (defined_default(colors)) {
for (j = i * 4; j < i * 4 + 4 * 4; ++j) {
currentAttributes.color.values.push(colors[j]);
}
}
index = currentAttributes.position.values.length / 3 - 4;
currentIndices.push(index, index + 2, index + 1);
currentIndices.push(index + 1, index + 2, index + 3);
}
}
if (intersectionFound) {
updateAdjacencyAfterSplit(westGeometry);
updateAdjacencyAfterSplit(eastGeometry);
}
updateInstanceAfterSplit(instance, westGeometry, eastGeometry);
}
GeometryPipeline.splitLongitude = function(instance) {
if (!defined_default(instance)) {
throw new DeveloperError_default("instance is required.");
}
const geometry = instance.geometry;
const boundingSphere = geometry.boundingSphere;
if (defined_default(boundingSphere)) {
const minX = boundingSphere.center.x - boundingSphere.radius;
if (minX > 0 || BoundingSphere_default.intersectPlane(boundingSphere, Plane_default.ORIGIN_ZX_PLANE) !== Intersect_default.INTERSECTING) {
return instance;
}
}
if (geometry.geometryType !== GeometryType_default.NONE) {
switch (geometry.geometryType) {
case GeometryType_default.POLYLINES:
splitLongitudePolyline(instance);
break;
case GeometryType_default.TRIANGLES:
splitLongitudeTriangles(instance);
break;
case GeometryType_default.LINES:
splitLongitudeLines(instance);
break;
}
} else {
indexPrimitive(geometry);
if (geometry.primitiveType === PrimitiveType_default.TRIANGLES) {
splitLongitudeTriangles(instance);
} else if (geometry.primitiveType === PrimitiveType_default.LINES) {
splitLongitudeLines(instance);
}
}
return instance;
};
var GeometryPipeline_default = GeometryPipeline;
// packages/engine/Source/Renderer/CubeMapFace.js
var import_InlineWorkers112 = __toESM(require_InlineWorkers(), 1);
function CubeMapFace(context, texture, textureTarget, targetFace, internalFormat, pixelFormat, pixelDatatype, size, preMultiplyAlpha, flipY, initialized) {
this._context = context;
this._texture = texture;
this._textureTarget = textureTarget;
this._targetFace = targetFace;
this._pixelDatatype = pixelDatatype;
this._internalFormat = internalFormat;
this._pixelFormat = pixelFormat;
this._size = size;
this._preMultiplyAlpha = preMultiplyAlpha;
this._flipY = flipY;
this._initialized = initialized;
}
Object.defineProperties(CubeMapFace.prototype, {
pixelFormat: {
get: function() {
return this._pixelFormat;
}
},
pixelDatatype: {
get: function() {
return this._pixelDatatype;
}
},
_target: {
get: function() {
return this._targetFace;
}
}
});
CubeMapFace.prototype.copyFrom = function(options) {
Check_default.defined("options", options);
const {
xOffset = 0,
yOffset = 0,
source,
skipColorSpaceConversion = false
} = options;
Check_default.defined("options.source", source);
Check_default.typeOf.number.greaterThanOrEquals("xOffset", xOffset, 0);
Check_default.typeOf.number.greaterThanOrEquals("yOffset", yOffset, 0);
if (xOffset + source.width > this._size) {
throw new DeveloperError_default(
"xOffset + options.source.width must be less than or equal to width."
);
}
if (yOffset + source.height > this._size) {
throw new DeveloperError_default(
"yOffset + options.source.height must be less than or equal to height."
);
}
const { width, height } = source;
const gl = this._context._gl;
const target = this._textureTarget;
const targetFace = this._targetFace;
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(target, this._texture);
let arrayBufferView = source.arrayBufferView;
const size = this._size;
const pixelFormat = this._pixelFormat;
const internalFormat = this._internalFormat;
const pixelDatatype = this._pixelDatatype;
const preMultiplyAlpha = this._preMultiplyAlpha;
const flipY = this._flipY;
let unpackAlignment = 4;
if (defined_default(arrayBufferView)) {
unpackAlignment = PixelFormat_default.alignmentInBytes(
pixelFormat,
pixelDatatype,
width
);
}
gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);
if (skipColorSpaceConversion) {
gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
} else {
gl.pixelStorei(
gl.UNPACK_COLORSPACE_CONVERSION_WEBGL,
gl.BROWSER_DEFAULT_WEBGL
);
}
let uploaded = false;
if (!this._initialized) {
let pixels;
if (xOffset === 0 && yOffset === 0 && width === size && height === size) {
if (defined_default(arrayBufferView)) {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
if (flipY) {
arrayBufferView = PixelFormat_default.flipY(
arrayBufferView,
pixelFormat,
pixelDatatype,
size,
size
);
}
pixels = arrayBufferView;
} else {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
pixels = source;
}
uploaded = true;
} else {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
pixels = PixelFormat_default.createTypedArray(
pixelFormat,
pixelDatatype,
size,
size
);
}
gl.texImage2D(
targetFace,
0,
internalFormat,
size,
size,
0,
pixelFormat,
PixelDatatype_default.toWebGLConstant(pixelDatatype, this._context),
pixels
);
this._initialized = true;
}
if (!uploaded) {
if (defined_default(arrayBufferView)) {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
if (flipY) {
arrayBufferView = PixelFormat_default.flipY(
arrayBufferView,
pixelFormat,
pixelDatatype,
width,
height
);
}
gl.texSubImage2D(
targetFace,
0,
xOffset,
yOffset,
width,
height,
pixelFormat,
PixelDatatype_default.toWebGLConstant(pixelDatatype, this._context),
arrayBufferView
);
} else {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
gl.texSubImage2D(
targetFace,
0,
xOffset,
yOffset,
pixelFormat,
PixelDatatype_default.toWebGLConstant(pixelDatatype, this._context),
source
);
}
}
gl.bindTexture(target, null);
};
CubeMapFace.prototype.copyFromFramebuffer = function(xOffset, yOffset, framebufferXOffset, framebufferYOffset, width, height) {
xOffset = xOffset ?? 0;
yOffset = yOffset ?? 0;
framebufferXOffset = framebufferXOffset ?? 0;
framebufferYOffset = framebufferYOffset ?? 0;
width = width ?? this._size;
height = height ?? this._size;
Check_default.typeOf.number.greaterThanOrEquals("xOffset", xOffset, 0);
Check_default.typeOf.number.greaterThanOrEquals("yOffset", yOffset, 0);
Check_default.typeOf.number.greaterThanOrEquals(
"framebufferXOffset",
framebufferXOffset,
0
);
Check_default.typeOf.number.greaterThanOrEquals(
"framebufferYOffset",
framebufferYOffset,
0
);
if (xOffset + width > this._size) {
throw new DeveloperError_default(
"xOffset + source.width must be less than or equal to width."
);
}
if (yOffset + height > this._size) {
throw new DeveloperError_default(
"yOffset + source.height must be less than or equal to height."
);
}
if (this._pixelDatatype === PixelDatatype_default.FLOAT) {
throw new DeveloperError_default(
"Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT."
);
}
if (this._pixelDatatype === PixelDatatype_default.HALF_FLOAT) {
throw new DeveloperError_default(
"Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT."
);
}
const gl = this._context._gl;
const target = this._textureTarget;
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(target, this._texture);
gl.copyTexSubImage2D(
this._targetFace,
0,
xOffset,
yOffset,
framebufferXOffset,
framebufferYOffset,
width,
height
);
gl.bindTexture(target, null);
this._initialized = true;
};
CubeMapFace.prototype.copyMipmapFromFramebuffer = function(xOffset, yOffset, width, height, level) {
xOffset = xOffset ?? 0;
yOffset = yOffset ?? 0;
width = width ?? this._size;
height = height ?? this._size;
level = level ?? 0;
Check_default.typeOf.number.greaterThanOrEquals("xOffset", xOffset, 0);
Check_default.typeOf.number.greaterThanOrEquals("yOffset", yOffset, 0);
if (xOffset + width > this._size) {
throw new DeveloperError_default(
"xOffset + source.width must be less than or equal to width."
);
}
if (yOffset + height > this._size) {
throw new DeveloperError_default(
"yOffset + source.height must be less than or equal to height."
);
}
if (this._pixelDatatype === PixelDatatype_default.FLOAT) {
throw new DeveloperError_default(
"Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT."
);
}
if (this._pixelDatatype === PixelDatatype_default.HALF_FLOAT) {
throw new DeveloperError_default(
"Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT."
);
}
const gl = this._context._gl;
const target = this._textureTarget;
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(target, this._texture);
gl.copyTexImage2D(
this._targetFace,
level,
this._internalFormat,
xOffset,
yOffset,
width,
height,
0
);
gl.bindTexture(target, null);
this._initialized = true;
};
var CubeMapFace_default = CubeMapFace;
// packages/engine/Source/Renderer/MipmapHint.js
var import_InlineWorkers113 = __toESM(require_InlineWorkers(), 1);
var MipmapHint = {
DONT_CARE: WebGLConstants_default.DONT_CARE,
FASTEST: WebGLConstants_default.FASTEST,
NICEST: WebGLConstants_default.NICEST,
validate: function(mipmapHint) {
return mipmapHint === MipmapHint.DONT_CARE || mipmapHint === MipmapHint.FASTEST || mipmapHint === MipmapHint.NICEST;
}
};
var MipmapHint_default = Object.freeze(MipmapHint);
// packages/engine/Source/Renderer/Sampler.js
var import_InlineWorkers117 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Renderer/TextureMagnificationFilter.js
var import_InlineWorkers114 = __toESM(require_InlineWorkers(), 1);
var TextureMagnificationFilter = {
/**
* Samples the texture by returning the closest pixel.
*
* @type {number}
* @constant
*/
NEAREST: WebGLConstants_default.NEAREST,
/**
* Samples the texture through bi-linear interpolation of the four nearest pixels. This produces smoother results than NEAREST filtering.
*
* @type {number}
* @constant
*/
LINEAR: WebGLConstants_default.LINEAR
};
TextureMagnificationFilter.validate = function(textureMagnificationFilter) {
return textureMagnificationFilter === TextureMagnificationFilter.NEAREST || textureMagnificationFilter === TextureMagnificationFilter.LINEAR;
};
var TextureMagnificationFilter_default = Object.freeze(TextureMagnificationFilter);
// packages/engine/Source/Renderer/TextureMinificationFilter.js
var import_InlineWorkers115 = __toESM(require_InlineWorkers(), 1);
var TextureMinificationFilter = {
/**
* Samples the texture by returning the closest pixel.
*
* @type {number}
* @constant
*/
NEAREST: WebGLConstants_default.NEAREST,
/**
* Samples the texture through bi-linear interpolation of the four nearest pixels. This produces smoother results than NEAREST filtering.
*
* @type {number}
* @constant
*/
LINEAR: WebGLConstants_default.LINEAR,
/**
* Selects the nearest mip level and applies nearest sampling within that level.
* 1/pi.\n *\n * @alias czm_oneOverPi\n * @glslConstant\n *\n * @see CesiumMath.ONE_OVER_PI\n *\n * @example\n * // GLSL declaration\n * const float czm_oneOverPi = ...;\n *\n * // Example\n * float pi = 1.0 / czm_oneOverPi;\n */\nconst float czm_oneOverPi = 0.3183098861837907;\n";
// packages/engine/Source/Shaders/Builtin/Constants/oneOverTwoPi.js
var import_InlineWorkers132 = __toESM(require_InlineWorkers(), 1);
var oneOverTwoPi_default = "/**\n * A built-in GLSL floating-point constant for 1/2pi.\n *\n * @alias czm_oneOverTwoPi\n * @glslConstant\n *\n * @see CesiumMath.ONE_OVER_TWO_PI\n *\n * @example\n * // GLSL declaration\n * const float czm_oneOverTwoPi = ...;\n *\n * // Example\n * float pi = 2.0 * czm_oneOverTwoPi;\n */\nconst float czm_oneOverTwoPi = 0.15915494309189535;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passCesium3DTile.js
var import_InlineWorkers133 = __toESM(require_InlineWorkers(), 1);
var passCesium3DTile_default = "/**\n * The automatic GLSL constant for {@link Pass#CESIUM_3D_TILE}\n *\n * @name czm_passCesium3DTile\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passCesium3DTile = 4.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passCesium3DTileClassification.js
var import_InlineWorkers134 = __toESM(require_InlineWorkers(), 1);
var passCesium3DTileClassification_default = "/**\n * The automatic GLSL constant for {@link Pass#CESIUM_3D_TILE_CLASSIFICATION}\n *\n * @name czm_passCesium3DTileClassification\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passCesium3DTileClassification = 5.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passCesium3DTileClassificationIgnoreShow.js
var import_InlineWorkers135 = __toESM(require_InlineWorkers(), 1);
var passCesium3DTileClassificationIgnoreShow_default = "/**\n * The automatic GLSL constant for {@link Pass#CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW}\n *\n * @name czm_passCesium3DTileClassificationIgnoreShow\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passCesium3DTileClassificationIgnoreShow = 6.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passClassification.js
var import_InlineWorkers136 = __toESM(require_InlineWorkers(), 1);
var passClassification_default = "/**\n * The automatic GLSL constant for {@link Pass#CLASSIFICATION}\n *\n * @name czm_passClassification\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passClassification = 7.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passCompute.js
var import_InlineWorkers137 = __toESM(require_InlineWorkers(), 1);
var passCompute_default = "/**\n * The automatic GLSL constant for {@link Pass#COMPUTE}\n *\n * @name czm_passCompute\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passCompute = 1.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passEnvironment.js
var import_InlineWorkers138 = __toESM(require_InlineWorkers(), 1);
var passEnvironment_default = "/**\n * The automatic GLSL constant for {@link Pass#ENVIRONMENT}\n *\n * @name czm_passEnvironment\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passEnvironment = 0.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passGaussianSplats.js
var import_InlineWorkers139 = __toESM(require_InlineWorkers(), 1);
var passGaussianSplats_default = "/**\n * The automatic GLSL constant for {@link Pass#GAUSSIAN_SPLATS}\n *\n * @name czm_passGaussianSplats\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passGaussianSplats = 10.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passGlobe.js
var import_InlineWorkers140 = __toESM(require_InlineWorkers(), 1);
var passGlobe_default = "/**\n * The automatic GLSL constant for {@link Pass#GLOBE}\n *\n * @name czm_passGlobe\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passGlobe = 2.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passOpaque.js
var import_InlineWorkers141 = __toESM(require_InlineWorkers(), 1);
var passOpaque_default = "/**\n * The automatic GLSL constant for {@link Pass#OPAQUE}\n *\n * @name czm_passOpaque\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passOpaque = 7.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passOverlay.js
var import_InlineWorkers142 = __toESM(require_InlineWorkers(), 1);
var passOverlay_default = "/**\n * The automatic GLSL constant for {@link Pass#OVERLAY}\n *\n * @name czm_passOverlay\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passOverlay = 11.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passTerrainClassification.js
var import_InlineWorkers143 = __toESM(require_InlineWorkers(), 1);
var passTerrainClassification_default = "/**\n * The automatic GLSL constant for {@link Pass#TERRAIN_CLASSIFICATION}\n *\n * @name czm_passTerrainClassification\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passTerrainClassification = 3.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passTranslucent.js
var import_InlineWorkers144 = __toESM(require_InlineWorkers(), 1);
var passTranslucent_default = "/**\n * The automatic GLSL constant for {@link Pass#TRANSLUCENT}\n *\n * @name czm_passTranslucent\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passTranslucent = 8.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/passVoxels.js
var import_InlineWorkers145 = __toESM(require_InlineWorkers(), 1);
var passVoxels_default = "/**\n * The automatic GLSL constant for {@link Pass#VOXELS}\n *\n * @name czm_passVoxels\n * @glslConstant\n *\n * @see czm_pass\n */\nconst float czm_passVoxels = 9.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/pi.js
var import_InlineWorkers146 = __toESM(require_InlineWorkers(), 1);
var pi_default = "/**\n * A built-in GLSL floating-point constant for Math.PI.\n *\n * @alias czm_pi\n * @glslConstant\n *\n * @see CesiumMath.PI\n *\n * @example\n * // GLSL declaration\n * const float czm_pi = ...;\n *\n * // Example\n * float twoPi = 2.0 * czm_pi;\n */\nconst float czm_pi = 3.141592653589793;\n";
// packages/engine/Source/Shaders/Builtin/Constants/piOverFour.js
var import_InlineWorkers147 = __toESM(require_InlineWorkers(), 1);
var piOverFour_default = "/**\n * A built-in GLSL floating-point constant for pi/4.\n *\n * @alias czm_piOverFour\n * @glslConstant\n *\n * @see CesiumMath.PI_OVER_FOUR\n *\n * @example\n * // GLSL declaration\n * const float czm_piOverFour = ...;\n *\n * // Example\n * float pi = 4.0 * czm_piOverFour;\n */\nconst float czm_piOverFour = 0.7853981633974483;\n";
// packages/engine/Source/Shaders/Builtin/Constants/piOverSix.js
var import_InlineWorkers148 = __toESM(require_InlineWorkers(), 1);
var piOverSix_default = "/**\n * A built-in GLSL floating-point constant for pi/6.\n *\n * @alias czm_piOverSix\n * @glslConstant\n *\n * @see CesiumMath.PI_OVER_SIX\n *\n * @example\n * // GLSL declaration\n * const float czm_piOverSix = ...;\n *\n * // Example\n * float pi = 6.0 * czm_piOverSix;\n */\nconst float czm_piOverSix = 0.5235987755982988;\n";
// packages/engine/Source/Shaders/Builtin/Constants/piOverThree.js
var import_InlineWorkers149 = __toESM(require_InlineWorkers(), 1);
var piOverThree_default = "/**\n * A built-in GLSL floating-point constant for pi/3.\n *\n * @alias czm_piOverThree\n * @glslConstant\n *\n * @see CesiumMath.PI_OVER_THREE\n *\n * @example\n * // GLSL declaration\n * const float czm_piOverThree = ...;\n *\n * // Example\n * float pi = 3.0 * czm_piOverThree;\n */\nconst float czm_piOverThree = 1.0471975511965976;\n";
// packages/engine/Source/Shaders/Builtin/Constants/piOverTwo.js
var import_InlineWorkers150 = __toESM(require_InlineWorkers(), 1);
var piOverTwo_default = "/**\n * A built-in GLSL floating-point constant for pi/2.\n *\n * @alias czm_piOverTwo\n * @glslConstant\n *\n * @see CesiumMath.PI_OVER_TWO\n *\n * @example\n * // GLSL declaration\n * const float czm_piOverTwo = ...;\n *\n * // Example\n * float pi = 2.0 * czm_piOverTwo;\n */\nconst float czm_piOverTwo = 1.5707963267948966;\n";
// packages/engine/Source/Shaders/Builtin/Constants/radiansPerDegree.js
var import_InlineWorkers151 = __toESM(require_InlineWorkers(), 1);
var radiansPerDegree_default = "/**\n * A built-in GLSL floating-point constant for converting degrees to radians.\n *\n * @alias czm_radiansPerDegree\n * @glslConstant\n *\n * @see CesiumMath.RADIANS_PER_DEGREE\n *\n * @example\n * // GLSL declaration\n * const float czm_radiansPerDegree = ...;\n *\n * // Example\n * float rad = czm_radiansPerDegree * deg;\n */\nconst float czm_radiansPerDegree = 0.017453292519943295;\n";
// packages/engine/Source/Shaders/Builtin/Constants/sceneMode2D.js
var import_InlineWorkers152 = __toESM(require_InlineWorkers(), 1);
var sceneMode2D_default = "/**\n * The constant identifier for the 2D {@link SceneMode}\n *\n * @name czm_sceneMode2D\n * @glslConstant\n * @see czm_sceneMode\n * @see czm_sceneModeColumbusView\n * @see czm_sceneMode3D\n * @see czm_sceneModeMorphing\n */\nconst float czm_sceneMode2D = 2.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/sceneMode3D.js
var import_InlineWorkers153 = __toESM(require_InlineWorkers(), 1);
var sceneMode3D_default = "/**\n * The constant identifier for the 3D {@link SceneMode}\n *\n * @name czm_sceneMode3D\n * @glslConstant\n * @see czm_sceneMode\n * @see czm_sceneMode2D\n * @see czm_sceneModeColumbusView\n * @see czm_sceneModeMorphing\n */\nconst float czm_sceneMode3D = 3.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/sceneModeColumbusView.js
var import_InlineWorkers154 = __toESM(require_InlineWorkers(), 1);
var sceneModeColumbusView_default = "/**\n * The constant identifier for the Columbus View {@link SceneMode}\n *\n * @name czm_sceneModeColumbusView\n * @glslConstant\n * @see czm_sceneMode\n * @see czm_sceneMode2D\n * @see czm_sceneMode3D\n * @see czm_sceneModeMorphing\n */\nconst float czm_sceneModeColumbusView = 1.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/sceneModeMorphing.js
var import_InlineWorkers155 = __toESM(require_InlineWorkers(), 1);
var sceneModeMorphing_default = "/**\n * The constant identifier for the Morphing {@link SceneMode}\n *\n * @name czm_sceneModeMorphing\n * @glslConstant\n * @see czm_sceneMode\n * @see czm_sceneMode2D\n * @see czm_sceneModeColumbusView\n * @see czm_sceneMode3D\n */\nconst float czm_sceneModeMorphing = 0.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/solarRadius.js
var import_InlineWorkers156 = __toESM(require_InlineWorkers(), 1);
var solarRadius_default = "/**\n * A built-in GLSL floating-point constant for one solar radius.\n *\n * @alias czm_solarRadius\n * @glslConstant\n *\n * @see CesiumMath.SOLAR_RADIUS\n *\n * @example\n * // GLSL declaration\n * const float czm_solarRadius = ...;\n */\nconst float czm_solarRadius = 695500000.0;\n";
// packages/engine/Source/Shaders/Builtin/Constants/threePiOver2.js
var import_InlineWorkers157 = __toESM(require_InlineWorkers(), 1);
var threePiOver2_default = "/**\n * A built-in GLSL floating-point constant for 3pi/2.\n *\n * @alias czm_threePiOver2\n * @glslConstant\n *\n * @see CesiumMath.THREE_PI_OVER_TWO\n *\n * @example\n * // GLSL declaration\n * const float czm_threePiOver2 = ...;\n *\n * // Example\n * float pi = (2.0 / 3.0) * czm_threePiOver2;\n */\nconst float czm_threePiOver2 = 4.71238898038469;\n";
// packages/engine/Source/Shaders/Builtin/Constants/twoPi.js
var import_InlineWorkers158 = __toESM(require_InlineWorkers(), 1);
var twoPi_default = "/**\n * A built-in GLSL floating-point constant for 2pi.\n *\n * @alias czm_twoPi\n * @glslConstant\n *\n * @see CesiumMath.TWO_PI\n *\n * @example\n * // GLSL declaration\n * const float czm_twoPi = ...;\n *\n * // Example\n * float pi = czm_twoPi / 2.0;\n */\nconst float czm_twoPi = 6.283185307179586;\n";
// packages/engine/Source/Shaders/Builtin/Constants/webMercatorMaxLatitude.js
var import_InlineWorkers159 = __toESM(require_InlineWorkers(), 1);
var webMercatorMaxLatitude_default = "/**\n * The maximum latitude, in radians, both North and South, supported by a Web Mercator\n * (EPSG:3857) projection. Technically, the Mercator projection is defined\n * for any latitude up to (but not including) 90 degrees, but it makes sense\n * to cut it off sooner because it grows exponentially with increasing latitude.\n * The logic behind this particular cutoff value, which is the one used by\n * Google Maps, Bing Maps, and Esri, is that it makes the projection\n * square. That is, the rectangle is equal in the X and Y directions.\n *\n * The constant value is computed as follows:\n * czm_pi * 0.5 - (2.0 * atan(exp(-czm_pi)))\n *\n * @name czm_webMercatorMaxLatitude\n * @glslConstant\n */\nconst float czm_webMercatorMaxLatitude = 1.4844222297453324;\n";
// packages/engine/Source/Shaders/Builtin/Structs/depthRangeStruct.js
var import_InlineWorkers160 = __toESM(require_InlineWorkers(), 1);
var depthRangeStruct_default = "/**\n * @name czm_depthRangeStruct\n * @glslStruct\n */\nstruct czm_depthRangeStruct\n{\n float near;\n float far;\n};\n";
// packages/engine/Source/Shaders/Builtin/Structs/material.js
var import_InlineWorkers161 = __toESM(require_InlineWorkers(), 1);
var material_default = "/**\n * Holds material information that can be used for lighting. Returned by all czm_getMaterial functions.\n *\n * @name czm_material\n * @glslStruct\n *\n * @property {vec3} diffuse Incoming light that scatters evenly in all directions.\n * @property {float} specular Intensity of incoming light reflecting in a single direction.\n * @property {float} shininess The sharpness of the specular reflection. Higher values create a smaller, more focused specular highlight.\n * @property {vec3} normal Surface's normal in eye coordinates. It is used for effects such as normal mapping. The default is the surface's unmodified normal.\n * @property {vec3} emission Light emitted by the material equally in all directions. The default is vec3(0.0), which emits no light.\n * @property {float} alpha Alpha of this material. 0.0 is completely transparent; 1.0 is completely opaque.\n */\nstruct czm_material\n{\n vec3 diffuse;\n float specular;\n float shininess;\n vec3 normal;\n vec3 emission;\n float alpha;\n};\n";
// packages/engine/Source/Shaders/Builtin/Structs/materialInput.js
var import_InlineWorkers162 = __toESM(require_InlineWorkers(), 1);
var materialInput_default = "/**\n * Used as input to every material's czm_getMaterial function.\n *\n * @name czm_materialInput\n * @glslStruct\n *\n * @property {float} s 1D texture coordinates.\n * @property {vec2} st 2D texture coordinates.\n * @property {vec3} str 3D texture coordinates.\n * @property {vec3} normalEC Unperturbed surface normal in eye coordinates.\n * @property {mat3} tangentToEyeMatrix Matrix for converting a tangent space normal to eye space.\n * @property {vec3} positionToEyeEC Vector from the fragment to the eye in eye coordinates. The magnitude is the distance in meters from the fragment to the eye.\n * @property {float} height The height of the terrain in meters above or below the ellipsoid. Only available for globe materials.\n * @property {float} slope The slope of the terrain in radians. 0 is flat; pi/2 is vertical. Only available for globe materials.\n * @property {float} aspect The aspect of the terrain in radians. 0 is East, pi/2 is North, pi is West, 3pi/2 is South. Only available for globe materials.\n* @property {float} waterMask The value of the water mask. 0 is land, 1 is water. Only available for globe materials.\n */\nstruct czm_materialInput\n{\n float s;\n vec2 st;\n vec3 str;\n vec3 normalEC;\n mat3 tangentToEyeMatrix;\n vec3 positionToEyeEC;\n float height;\n float slope;\n float aspect;\n float waterMask;\n};\n";
// packages/engine/Source/Shaders/Builtin/Structs/modelMaterial.js
var import_InlineWorkers163 = __toESM(require_InlineWorkers(), 1);
var modelMaterial_default = "/**\n * Struct for representing a material for a {@link Model}. The model\n * rendering pipeline will pass this struct between material, custom shaders,\n * and lighting stages. This is not to be confused with {@link czm_material}\n * which is used by the older Fabric materials system, although they are similar.\n * color1 or color2.\n * @param {float} dist The distance to the edge in texture coordinates.\n * @param {float} [fuzzFactor=0.1] Controls the blurriness between the two colors.\n * @returns {vec4} The anti-aliased color.\n *\n * @example\n * // GLSL declarations\n * vec4 czm_antialias(vec4 color1, vec4 color2, vec4 currentColor, float dist, float fuzzFactor);\n * vec4 czm_antialias(vec4 color1, vec4 color2, vec4 currentColor, float dist);\n *\n * // get the color for a material that has a sharp edge at the line y = 0.5 in texture space\n * float dist = abs(textureCoordinates.t - 0.5);\n * vec4 currentColor = mix(bottomColor, topColor, step(0.5, textureCoordinates.t));\n * vec4 color = czm_antialias(bottomColor, topColor, currentColor, dist, 0.1);\n */\nvec4 czm_antialias(vec4 color1, vec4 color2, vec4 currentColor, float dist, float fuzzFactor)\n{\n float val1 = clamp(dist / fuzzFactor, 0.0, 1.0);\n float val2 = clamp((dist - 0.5) / fuzzFactor, 0.0, 1.0);\n val1 = val1 * (1.0 - val2);\n val1 = val1 * val1 * (3.0 - (2.0 * val1));\n val1 = pow(val1, 0.5); //makes the transition nicer\n \n vec4 midColor = (color1 + color2) * 0.5;\n return mix(midColor, currentColor, val1);\n}\n\nvec4 czm_antialias(vec4 color1, vec4 color2, vec4 currentColor, float dist)\n{\n return czm_antialias(color1, color2, currentColor, dist, 0.1);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/applyHSBShift.js
var import_InlineWorkers177 = __toESM(require_InlineWorkers(), 1);
var applyHSBShift_default = "/**\n * Apply a HSB color shift to an RGB color.\n *\n * @param {vec3} rgb The color in RGB space.\n * @param {vec3} hsbShift The amount to shift each component. The xyz components correspond to hue, saturation, and brightness. Shifting the hue by +/- 1.0 corresponds to shifting the hue by a full cycle. Saturation and brightness are clamped between 0 and 1 after the adjustment\n * @param {bool} ignoreBlackPixels If true, black pixels will be unchanged. This is necessary in some shaders such as atmosphere-related effects.\n *\n * @return {vec3} The RGB color after shifting in HSB space and clamping saturation and brightness to a valid range.\n */\nvec3 czm_applyHSBShift(vec3 rgb, vec3 hsbShift, bool ignoreBlackPixels) {\n // Convert rgb color to hsb\n vec3 hsb = czm_RGBToHSB(rgb);\n\n // Perform hsb shift\n // Hue cycles around so no clamp is needed.\n hsb.x += hsbShift.x; // hue\n hsb.y = clamp(hsb.y + hsbShift.y, 0.0, 1.0); // saturation\n\n // brightness\n //\n // Some shaders such as atmosphere-related effects need to leave black\n // pixels unchanged\n if (ignoreBlackPixels) {\n hsb.z = hsb.z > czm_epsilon7 ? hsb.z + hsbShift.z : 0.0;\n } else {\n hsb.z = hsb.z + hsbShift.z;\n }\n hsb.z = clamp(hsb.z, 0.0, 1.0);\n\n // Convert shifted hsb back to rgb\n return czm_HSBToRGB(hsb);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.js
var import_InlineWorkers178 = __toESM(require_InlineWorkers(), 1);
var approximateSphericalCoordinates_default = "/**\n * Approximately computes spherical coordinates given a normal.\n * Uses approximate inverse trigonometry for speed and consistency,\n * since inverse trigonometry can differ from vendor-to-vendor and when compared with the CPU.\n *\n * @name czm_approximateSphericalCoordinates\n * @glslFunction\n *\n * @param {vec3} normal arbitrary-length normal.\n *\n * @returns {vec2} Approximate latitude and longitude spherical coordinates.\n */\nvec2 czm_approximateSphericalCoordinates(vec3 normal) {\n // Project into plane with vertical for latitude\n float latitudeApproximation = czm_fastApproximateAtan(sqrt(normal.x * normal.x + normal.y * normal.y), normal.z);\n float longitudeApproximation = czm_fastApproximateAtan(normal.x, normal.y);\n return vec2(latitudeApproximation, longitudeApproximation);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/approximateTanh.js
var import_InlineWorkers179 = __toESM(require_InlineWorkers(), 1);
var approximateTanh_default = "/**\n * Compute a rational approximation to tanh(x)\n *\n * @param {float} x A real number input\n * @returns {float} An approximation for tanh(x)\n*/\nfloat czm_approximateTanh(float x) {\n float x2 = x * x;\n return max(-1.0, min(1.0, x * (27.0 + x2) / (27.0 + 9.0 * x2)));\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/backFacing.js
var import_InlineWorkers180 = __toESM(require_InlineWorkers(), 1);
var backFacing_default = "/**\n * Determines if the fragment is back facing\n *\n * @name czm_backFacing\n * @glslFunction \n * \n * @returns {bool} true if the fragment is back facing; otherwise, false.\n */\nbool czm_backFacing()\n{\n // !gl_FrontFacing doesn't work as expected on Mac/Intel so use the more verbose form instead. See https://github.com/CesiumGS/cesium/pull/8494.\n return gl_FrontFacing == false;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/branchFreeTernary.js
var import_InlineWorkers181 = __toESM(require_InlineWorkers(), 1);
var branchFreeTernary_default = "/**\n * Branchless ternary operator to be used when it's inexpensive to explicitly\n * evaluate both possibilities for a float expression.\n *\n * @name czm_branchFreeTernary\n * @glslFunction\n *\n * @param {bool} comparison A comparison statement\n * @param {float} a Value to return if the comparison is true.\n * @param {float} b Value to return if the comparison is false.\n *\n * @returns {float} equivalent of comparison ? a : b\n */\nfloat czm_branchFreeTernary(bool comparison, float a, float b) {\n float useA = float(comparison);\n return a * useA + b * (1.0 - useA);\n}\n\n/**\n * Branchless ternary operator to be used when it's inexpensive to explicitly\n * evaluate both possibilities for a vec2 expression.\n *\n * @name czm_branchFreeTernary\n * @glslFunction\n *\n * @param {bool} comparison A comparison statement\n * @param {vec2} a Value to return if the comparison is true.\n * @param {vec2} b Value to return if the comparison is false.\n *\n * @returns {vec2} equivalent of comparison ? a : b\n */\nvec2 czm_branchFreeTernary(bool comparison, vec2 a, vec2 b) {\n float useA = float(comparison);\n return a * useA + b * (1.0 - useA);\n}\n\n/**\n * Branchless ternary operator to be used when it's inexpensive to explicitly\n * evaluate both possibilities for a vec3 expression.\n *\n * @name czm_branchFreeTernary\n * @glslFunction\n *\n * @param {bool} comparison A comparison statement\n * @param {vec3} a Value to return if the comparison is true.\n * @param {vec3} b Value to return if the comparison is false.\n *\n * @returns {vec3} equivalent of comparison ? a : b\n */\nvec3 czm_branchFreeTernary(bool comparison, vec3 a, vec3 b) {\n float useA = float(comparison);\n return a * useA + b * (1.0 - useA);\n}\n\n/**\n * Branchless ternary operator to be used when it's inexpensive to explicitly\n * evaluate both possibilities for a vec4 expression.\n *\n * @name czm_branchFreeTernary\n * @glslFunction\n *\n * @param {bool} comparison A comparison statement\n * @param {vec3} a Value to return if the comparison is true.\n * @param {vec3} b Value to return if the comparison is false.\n *\n * @returns {vec3} equivalent of comparison ? a : b\n */\nvec4 czm_branchFreeTernary(bool comparison, vec4 a, vec4 b) {\n float useA = float(comparison);\n return a * useA + b * (1.0 - useA);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/cascadeColor.js
var import_InlineWorkers182 = __toESM(require_InlineWorkers(), 1);
var cascadeColor_default = "\nvec4 czm_cascadeColor(vec4 weights)\n{\n return vec4(1.0, 0.0, 0.0, 1.0) * weights.x +\n vec4(0.0, 1.0, 0.0, 1.0) * weights.y +\n vec4(0.0, 0.0, 1.0, 1.0) * weights.z +\n vec4(1.0, 0.0, 1.0, 1.0) * weights.w;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/cascadeDistance.js
var import_InlineWorkers183 = __toESM(require_InlineWorkers(), 1);
var cascadeDistance_default = "\nuniform vec4 shadowMap_cascadeDistances;\n\nfloat czm_cascadeDistance(vec4 weights)\n{\n return dot(shadowMap_cascadeDistances, weights);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/cascadeMatrix.js
var import_InlineWorkers184 = __toESM(require_InlineWorkers(), 1);
var cascadeMatrix_default = "\nuniform mat4 shadowMap_cascadeMatrices[4];\n\nmat4 czm_cascadeMatrix(vec4 weights)\n{\n return shadowMap_cascadeMatrices[0] * weights.x +\n shadowMap_cascadeMatrices[1] * weights.y +\n shadowMap_cascadeMatrices[2] * weights.z +\n shadowMap_cascadeMatrices[3] * weights.w;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/cascadeWeights.js
var import_InlineWorkers185 = __toESM(require_InlineWorkers(), 1);
var cascadeWeights_default = "\nuniform vec4 shadowMap_cascadeSplits[2];\n\nvec4 czm_cascadeWeights(float depthEye)\n{\n // One component is set to 1.0 and all others set to 0.0.\n vec4 near = step(shadowMap_cascadeSplits[0], vec4(depthEye));\n vec4 far = step(depthEye, shadowMap_cascadeSplits[1]);\n return near * far;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/clipPolygons.js
var import_InlineWorkers186 = __toESM(require_InlineWorkers(), 1);
var clipPolygons_default = "float getSignedDistance(vec2 uv, highp sampler2D clippingDistance) {\n float signedDistance = texture(clippingDistance, uv).r;\n return (signedDistance - 0.5) * 2.0;\n}\n\nvoid czm_clipPolygons(highp sampler2D clippingDistance, int extentsLength, vec2 clippingPosition, int regionIndex) {\n // Position is completely outside of polygons bounds\n vec2 rectUv = clippingPosition;\n if (regionIndex < 0 || rectUv.x <= 0.0 || rectUv.y <= 0.0 || rectUv.x >= 1.0 || rectUv.y >= 1.0) {\n #ifdef CLIPPING_INVERSE \n discard;\n #endif\n return;\n }\n\n vec2 clippingDistanceTextureDimensions = vec2(textureSize(clippingDistance, 0));\n vec2 sampleOffset = max(1.0 / clippingDistanceTextureDimensions, vec2(0.005));\n float dimension = float(extentsLength);\n if (extentsLength > 2) {\n dimension = ceil(log2(float(extentsLength)));\n }\n\n vec2 textureOffset = vec2(mod(float(regionIndex), dimension), floor(float(regionIndex) / dimension)) / dimension;\n vec2 uv = textureOffset + rectUv / dimension;\n\n float signedDistance = getSignedDistance(uv, clippingDistance);\n\n #ifdef CLIPPING_INVERSE\n if (signedDistance > 0.0) {\n discard;\n }\n #else\n if (signedDistance < 0.0) {\n discard;\n }\n #endif\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/columbusViewMorph.js
var import_InlineWorkers187 = __toESM(require_InlineWorkers(), 1);
var columbusViewMorph_default = "/**\n * DOC_TBA\n *\n * @name czm_columbusViewMorph\n * @glslFunction\n */\nvec4 czm_columbusViewMorph(vec4 position2D, vec4 position3D, float time)\n{\n // Just linear for now.\n vec3 p = mix(position2D.xyz, position3D.xyz, time);\n return vec4(p, 1.0);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/computeAtmosphereColor.js
var import_InlineWorkers188 = __toESM(require_InlineWorkers(), 1);
var computeAtmosphereColor_default = "/**\n * Compute the atmosphere color, applying Rayleigh and Mie scattering. This\n * builtin uses automatic uniforms so the atmophere settings are synced with the\n * state of the Scene, even in other contexts like Model.\n *\n * @name czm_computeAtmosphereColor\n * @glslFunction\n *\n * @param {vec3} positionWC Position of the fragment in world coords (low precision)\n * @param {vec3} lightDirection Light direction from the sun or other light source.\n * @param {vec3} rayleighColor The Rayleigh scattering color computed by a scattering function\n * @param {vec3} mieColor The Mie scattering color computed by a scattering function\n * @param {float} opacity The opacity computed by a scattering function.\n */\nvec4 czm_computeAtmosphereColor(\n vec3 positionWC,\n vec3 lightDirection,\n vec3 rayleighColor,\n vec3 mieColor,\n float opacity\n) {\n // Setup the primary ray: from the camera position to the vertex position.\n vec3 cameraToPositionWC = positionWC - czm_viewerPositionWC;\n vec3 cameraToPositionWCDirection = normalize(cameraToPositionWC);\n\n float cosAngle = dot(cameraToPositionWCDirection, lightDirection);\n float cosAngleSq = cosAngle * cosAngle;\n\n float G = czm_atmosphereMieAnisotropy;\n float GSq = G * G;\n\n // The Rayleigh phase function.\n float rayleighPhase = 3.0 / (50.2654824574) * (1.0 + cosAngleSq);\n // The Mie phase function.\n float miePhase = 3.0 / (25.1327412287) * ((1.0 - GSq) * (cosAngleSq + 1.0)) / (pow(1.0 + GSq - 2.0 * cosAngle * G, 1.5) * (2.0 + GSq));\n\n // The final color is generated by combining the effects of the Rayleigh and Mie scattering.\n vec3 rayleigh = rayleighPhase * rayleighColor;\n vec3 mie = miePhase * mieColor;\n\n vec3 color = (rayleigh + mie) * czm_atmosphereLightIntensity;\n\n return vec4(color, opacity);\n}\n\n/**\n * Compute the atmosphere color, applying Rayleigh and Mie scattering. This\n * builtin uses automatic uniforms so the atmophere settings are synced with the\n * state of the Scene, even in other contexts like Model.\n *\n * @name czm_computeAtmosphereColor\n * @glslFunction\n *\n * @param {czm_ray} primaryRay Ray from the origin to sky fragment to in world coords (low precision)\n * @param {vec3} lightDirection Light direction from the sun or other light source.\n * @param {vec3} rayleighColor The Rayleigh scattering color computed by a scattering function\n * @param {vec3} mieColor The Mie scattering color computed by a scattering function\n * @param {float} opacity The opacity computed by a scattering function.\n */\nvec4 czm_computeAtmosphereColor(\n czm_ray primaryRay,\n vec3 lightDirection,\n vec3 rayleighColor,\n vec3 mieColor,\n float opacity\n) {\n vec3 direction = normalize(primaryRay.direction);\n\n float cosAngle = dot(direction, lightDirection);\n float cosAngleSq = cosAngle * cosAngle;\n\n float G = czm_atmosphereMieAnisotropy;\n float GSq = G * G;\n\n // The Rayleigh phase function.\n float rayleighPhase = 3.0 / (50.2654824574) * (1.0 + cosAngleSq);\n // The Mie phase function.\n float miePhase = 3.0 / (25.1327412287) * ((1.0 - GSq) * (cosAngleSq + 1.0)) / (pow(1.0 + GSq - 2.0 * cosAngle * G, 1.5) * (2.0 + GSq));\n\n // The final color is generated by combining the effects of the Rayleigh and Mie scattering.\n vec3 rayleigh = rayleighPhase * rayleighColor;\n vec3 mie = miePhase * mieColor;\n\n vec3 color = (rayleigh + mie) * czm_atmosphereLightIntensity;\n\n return vec4(color, opacity);\n}\n\n";
// packages/engine/Source/Shaders/Builtin/Functions/computeGroundAtmosphereScattering.js
var import_InlineWorkers189 = __toESM(require_InlineWorkers(), 1);
var computeGroundAtmosphereScattering_default = "/**\n * Compute atmosphere scattering for the ground atmosphere and fog. This method\n * uses automatic uniforms so it is always synced with the scene settings.\n *\n * @name czm_computeGroundAtmosphereScattering\n * @glslfunction\n *\n * @param {vec3} positionWC The position of the fragment in world coordinates.\n * @param {vec3} lightDirection The direction of the light to calculate the scattering from.\n * @param {vec3} rayleighColor The variable the Rayleigh scattering will be written to.\n * @param {vec3} mieColor The variable the Mie scattering will be written to.\n * @param {float} opacity The variable the transmittance will be written to.\n */\nvoid czm_computeGroundAtmosphereScattering(vec3 positionWC, vec3 lightDirection, out vec3 rayleighColor, out vec3 mieColor, out float opacity) {\n vec3 cameraToPositionWC = positionWC - czm_viewerPositionWC;\n vec3 cameraToPositionWCDirection = normalize(cameraToPositionWC);\n czm_ray primaryRay = czm_ray(czm_viewerPositionWC, cameraToPositionWCDirection);\n\n float atmosphereInnerRadius = length(positionWC);\n\n czm_computeScattering(\n primaryRay,\n length(cameraToPositionWC),\n lightDirection,\n atmosphereInnerRadius,\n rayleighColor,\n mieColor,\n opacity\n );\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/computePosition.js
var import_InlineWorkers190 = __toESM(require_InlineWorkers(), 1);
var computePosition_default = "/**\n * Returns a position in model coordinates relative to eye taking into\n * account the current scene mode: 3D, 2D, or Columbus view.\n * position3DHigh, \n * position3DLow, position2DHigh, and position2DLow, \n * and should be used when writing a vertex shader for an {@link Appearance}.\n *
\n * The ellipsoid is assumed to be centered at the model coordinate's origin.\n *\n * @name czm_eastNorthUpToEyeCoordinates\n * @glslFunction\n *\n * @param {vec3} positionMC The position on the ellipsoid in model coordinates.\n * @param {vec3} normalEC The normalized ellipsoid surface normal, at positionMC, in eye coordinates.\n *\n * @returns {mat3} A 3x3 rotation matrix that transforms vectors from the east-north-up coordinate system to eye coordinates.\n *\n * @example\n * // Transform a vector defined in the east-north-up coordinate \n * // system, (0, 0, 1) which is the surface normal, to eye \n * // coordinates.\n * mat3 m = czm_eastNorthUpToEyeCoordinates(positionMC, normalEC);\n * vec3 normalEC = m * vec3(0.0, 0.0, 1.0);\n */\nmat3 czm_eastNorthUpToEyeCoordinates(vec3 positionMC, vec3 normalEC)\n{\n vec3 tangentMC = normalize(vec3(-positionMC.y, positionMC.x, 0.0)); // normalized surface tangent in model coordinates\n vec3 tangentEC = normalize(czm_normal3D * tangentMC); // normalized surface tangent in eye coordinates\n vec3 bitangentEC = normalize(cross(normalEC, tangentEC)); // normalized surface bitangent in eye coordinates\n\n return mat3(\n tangentEC.x, tangentEC.y, tangentEC.z,\n bitangentEC.x, bitangentEC.y, bitangentEC.z,\n normalEC.x, normalEC.y, normalEC.z);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/ellipsoidContainsPoint.js
var import_InlineWorkers196 = __toESM(require_InlineWorkers(), 1);
var ellipsoidContainsPoint_default = "/**\n * DOC_TBA\n *\n * @name czm_ellipsoidContainsPoint\n * @glslFunction\n *\n */\nbool czm_ellipsoidContainsPoint(vec3 ellipsoid_inverseRadii, vec3 point)\n{\n vec3 scaled = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(point, 1.0)).xyz;\n return (dot(scaled, scaled) <= 1.0);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/ellipsoidTextureCoordinates.js
var import_InlineWorkers197 = __toESM(require_InlineWorkers(), 1);
var ellipsoidTextureCoordinates_default = "/**\n * Approximate uv coordinates based on the ellipsoid normal.\n *\n * @name czm_ellipsoidTextureCoordinates\n * @glslFunction\n */\nvec2 czm_ellipsoidTextureCoordinates(vec3 normal)\n{\n return vec2(atan(normal.y, normal.x) * czm_oneOverTwoPi + 0.5, asin(normal.z) * czm_oneOverPi + 0.5);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/equalsEpsilon.js
var import_InlineWorkers198 = __toESM(require_InlineWorkers(), 1);
var equalsEpsilon_default = "/**\n * Compares left and right componentwise. Returns true\n * if they are within epsilon and false otherwise. The inputs\n * left and right can be floats, vec2s,\n * vec3s, or vec4s.\n *\n * @name czm_equalsEpsilon\n * @glslFunction\n *\n * @param {} left The first vector.\n * @param {} right The second vector.\n * @param {float} epsilon The epsilon to use for equality testing.\n * @returns {bool} true if the components are within epsilon and false otherwise.\n *\n * @example\n * // GLSL declarations\n * bool czm_equalsEpsilon(float left, float right, float epsilon);\n * bool czm_equalsEpsilon(vec2 left, vec2 right, float epsilon);\n * bool czm_equalsEpsilon(vec3 left, vec3 right, float epsilon);\n * bool czm_equalsEpsilon(vec4 left, vec4 right, float epsilon);\n */\nbool czm_equalsEpsilon(vec4 left, vec4 right, float epsilon) {\n return all(lessThanEqual(abs(left - right), vec4(epsilon)));\n}\n\nbool czm_equalsEpsilon(vec3 left, vec3 right, float epsilon) {\n return all(lessThanEqual(abs(left - right), vec3(epsilon)));\n}\n\nbool czm_equalsEpsilon(vec2 left, vec2 right, float epsilon) {\n return all(lessThanEqual(abs(left - right), vec2(epsilon)));\n}\n\nbool czm_equalsEpsilon(float left, float right, float epsilon) {\n return (abs(left - right) <= epsilon);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/eyeOffset.js
var import_InlineWorkers199 = __toESM(require_InlineWorkers(), 1);
var eyeOffset_default = "/**\n * DOC_TBA\n *\n * @name czm_eyeOffset\n * @glslFunction\n *\n * @param {vec4} positionEC DOC_TBA.\n * @param {vec3} eyeOffset DOC_TBA.\n *\n * @returns {vec4} DOC_TBA.\n */\nvec4 czm_eyeOffset(vec4 positionEC, vec3 eyeOffset)\n{\n // This equation is approximate in x and y.\n vec4 p = positionEC;\n vec4 zEyeOffset = normalize(p) * eyeOffset.z;\n p.xy += eyeOffset.xy + zEyeOffset.xy;\n p.z += zEyeOffset.z;\n return p;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/eyeToWindowCoordinates.js
var import_InlineWorkers200 = __toESM(require_InlineWorkers(), 1);
var eyeToWindowCoordinates_default = "/**\n * Transforms a position from eye to window coordinates. The transformation\n * from eye to clip coordinates is done using {@link czm_projection}.\n * The transform from normalized device coordinates to window coordinates is\n * done using {@link czm_viewportTransformation}, which assumes a depth range\n * of near = 0 and far = 1.\n *
\n * This transform is useful when there is a need to manipulate window coordinates\n * in a vertex shader as done by {@link BillboardCollection}.\n *\n * @name czm_eyeToWindowCoordinates\n * @glslFunction\n *\n * @param {vec4} position The position in eye coordinates to transform.\n *\n * @returns {vec4} The transformed position in window coordinates.\n *\n * @see czm_modelToWindowCoordinates\n * @see czm_projection\n * @see czm_viewportTransformation\n * @see BillboardCollection\n *\n * @example\n * vec4 positionWC = czm_eyeToWindowCoordinates(positionEC);\n */\nvec4 czm_eyeToWindowCoordinates(vec4 positionEC)\n{\n vec4 q = czm_projection * positionEC; // clip coordinates\n q.xyz /= q.w; // normalized device coordinates\n q.xyz = (czm_viewportTransformation * vec4(q.xyz, 1.0)).xyz; // window coordinates\n return q;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/fastApproximateAtan.js
var import_InlineWorkers201 = __toESM(require_InlineWorkers(), 1);
var fastApproximateAtan_default = `/**
* Approxiamtes atan over the range [0, 1]. Safe to flip output for negative input.
*
* Based on Michal Drobot's approximation from ShaderFastLibs, which in turn is based on
* "Efficient approximations for the arctangent function," Rajan, S. Sichun Wang Inkol, R. Joyal, A., May 2006.
* Adapted from ShaderFastLibs under MIT License.
*
* Chosen for the following characteristics over range [0, 1]:
* - basically no error at 0 and 1, important for getting around range limit (naive atan2 via atan requires infinite range atan)
* - no visible artifacts from first-derivative discontinuities, unlike latitude via range-reduced sqrt asin approximations (at equator)
*
* The original code is x * (-0.1784 * abs(x) - 0.0663 * x * x + 1.0301);
* Removed the abs() in here because it isn't needed, the input range is guaranteed as [0, 1] by how we're approximating atan2.
*
* @name czm_fastApproximateAtan
* @glslFunction
*
* @param {float} x Value between 0 and 1 inclusive.
*
* @returns {float} Approximation of atan(x)
*/
float czm_fastApproximateAtan(float x) {
return x * (-0.1784 * x - 0.0663 * x * x + 1.0301);
}
/**
* Approximation of atan2.
*
* Range reduction math based on nvidia's cg reference implementation for atan2: http://developer.download.nvidia.com/cg/atan2.html
* However, we replaced their atan curve with Michael Drobot's (see above).
*
* @name czm_fastApproximateAtan
* @glslFunction
*
* @param {float} x Value between -1 and 1 inclusive.
* @param {float} y Value between -1 and 1 inclusive.
*
* @returns {float} Approximation of atan2(x, y)
*/
float czm_fastApproximateAtan(float x, float y) {
// atan approximations are usually only reliable over [-1, 1], or, in our case, [0, 1] due to modifications.
// So range-reduce using abs and by flipping whether x or y is on top.
float t = abs(x); // t used as swap and atan result.
float opposite = abs(y);
float adjacent = max(t, opposite);
opposite = min(t, opposite);
t = czm_fastApproximateAtan(opposite / adjacent);
// Undo range reduction
t = czm_branchFreeTernary(abs(y) > abs(x), czm_piOverTwo - t, t);
t = czm_branchFreeTernary(x < 0.0, czm_pi - t, t);
t = czm_branchFreeTernary(y < 0.0, -t, t);
return t;
}
`;
// packages/engine/Source/Shaders/Builtin/Functions/fog.js
var import_InlineWorkers202 = __toESM(require_InlineWorkers(), 1);
var fog_default = "/**\n * Gets the color with fog at a distance from the camera.\n *\n * @name czm_fog\n * @glslFunction\n *\n * @param {float} distanceToCamera The distance to the camera in meters.\n * @param {vec3} color The original color.\n * @param {vec3} fogColor The color of the fog.\n *\n * @returns {vec3} The color adjusted for fog at the distance from the camera.\n */\nvec3 czm_fog(float distanceToCamera, vec3 color, vec3 fogColor)\n{\n float scalar = distanceToCamera * czm_fogDensity;\n float fog = 1.0 - exp(-(scalar * scalar));\n return mix(color, fogColor, fog);\n}\n\n/**\n * Gets the color with fog at a distance from the camera.\n *\n * @name czm_fog\n * @glslFunction\n *\n * @param {float} distanceToCamera The distance to the camera in meters.\n * @param {vec3} color The original color.\n * @param {vec3} fogColor The color of the fog.\n * @param {float} fogModifierConstant A constant to modify the appearance of fog.\n *\n * @returns {vec3} The color adjusted for fog at the distance from the camera.\n */\nvec3 czm_fog(float distanceToCamera, vec3 color, vec3 fogColor, float fogModifierConstant)\n{\n float scalar = distanceToCamera * czm_fogDensity;\n float fog = 1.0 - exp(-((fogModifierConstant * scalar + fogModifierConstant) * (scalar * (1.0 + fogModifierConstant))));\n return mix(color, fogColor, fog);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/gammaCorrect.js
var import_InlineWorkers203 = __toESM(require_InlineWorkers(), 1);
var gammaCorrect_default = "/**\n * Converts a color from RGB space to linear space.\n *\n * @name czm_gammaCorrect\n * @glslFunction\n *\n * @param {vec3} color The color in RGB space.\n * @returns {vec3} The color in linear space.\n */\nvec3 czm_gammaCorrect(vec3 color) {\n#ifdef HDR\n color = pow(color, vec3(czm_gamma));\n#endif\n return color;\n}\n\nvec4 czm_gammaCorrect(vec4 color) {\n#ifdef HDR\n color.rgb = pow(color.rgb, vec3(czm_gamma));\n#endif\n return color;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/geodeticSurfaceNormal.js
var import_InlineWorkers204 = __toESM(require_InlineWorkers(), 1);
var geodeticSurfaceNormal_default = "/**\n * DOC_TBA\n *\n * @name czm_geodeticSurfaceNormal\n * @glslFunction\n *\n * @param {vec3} positionOnEllipsoid DOC_TBA\n * @param {vec3} ellipsoidCenter DOC_TBA\n * @param {vec3} oneOverEllipsoidRadiiSquared DOC_TBA\n * \n * @returns {vec3} DOC_TBA.\n */\nvec3 czm_geodeticSurfaceNormal(vec3 positionOnEllipsoid, vec3 ellipsoidCenter, vec3 oneOverEllipsoidRadiiSquared)\n{\n return normalize((positionOnEllipsoid - ellipsoidCenter) * oneOverEllipsoidRadiiSquared);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/getDefaultMaterial.js
var import_InlineWorkers205 = __toESM(require_InlineWorkers(), 1);
var getDefaultMaterial_default = "/**\n * An czm_material with default values. Every material's czm_getMaterial\n * should use this default material as a base for the material it returns.\n * The default normal value is given by materialInput.normalEC.\n *\n * @name czm_getDefaultMaterial\n * @glslFunction\n *\n * @param {czm_materialInput} input The input used to construct the default material.\n *\n * @returns {czm_material} The default material.\n *\n * @see czm_materialInput\n * @see czm_material\n * @see czm_getMaterial\n */\nczm_material czm_getDefaultMaterial(czm_materialInput materialInput)\n{\n czm_material material;\n material.diffuse = vec3(0.0);\n material.specular = 0.0;\n material.shininess = 1.0;\n material.normal = materialInput.normalEC;\n material.emission = vec3(0.0);\n material.alpha = 1.0;\n return material;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/getDynamicAtmosphereLightDirection.js
var import_InlineWorkers206 = __toESM(require_InlineWorkers(), 1);
var getDynamicAtmosphereLightDirection_default = "/**\n * Select which direction vector to use for dynamic atmosphere lighting based on an enum value\n *\n * @name czm_getDynamicAtmosphereLightDirection\n * @glslfunction\n * @see DynamicAtmosphereLightingType.js\n *\n * @param {vec3} positionWC the position of the vertex/fragment in world coordinates. This is normalized and returned when dynamic lighting is turned off.\n * @param {float} lightEnum The enum value for selecting between light sources.\n * @return {vec3} The normalized light direction vector. Depending on the enum value, it is either positionWC, czm_lightDirectionWC or czm_sunDirectionWC\n */\nvec3 czm_getDynamicAtmosphereLightDirection(vec3 positionWC, float lightEnum) {\n const float NONE = 0.0;\n const float SCENE_LIGHT = 1.0;\n const float SUNLIGHT = 2.0;\n\n vec3 lightDirection =\n positionWC * float(lightEnum == NONE) +\n czm_lightDirectionWC * float(lightEnum == SCENE_LIGHT) +\n czm_sunDirectionWC * float(lightEnum == SUNLIGHT);\n return normalize(lightDirection);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/getLambertDiffuse.js
var import_InlineWorkers207 = __toESM(require_InlineWorkers(), 1);
var getLambertDiffuse_default = "/**\n * Calculates the intensity of diffusely reflected light.\n *\n * @name czm_getLambertDiffuse\n * @glslFunction\n *\n * @param {vec3} lightDirectionEC Unit vector pointing to the light source in eye coordinates.\n * @param {vec3} normalEC The surface normal in eye coordinates.\n *\n * @returns {float} The intensity of the diffuse reflection.\n *\n * @see czm_phong\n *\n * @example\n * float diffuseIntensity = czm_getLambertDiffuse(lightDirectionEC, normalEC);\n * float specularIntensity = czm_getSpecular(lightDirectionEC, toEyeEC, normalEC, 200);\n * vec3 color = (diffuseColor * diffuseIntensity) + (specularColor * specularIntensity);\n */\nfloat czm_getLambertDiffuse(vec3 lightDirectionEC, vec3 normalEC)\n{\n return max(dot(lightDirectionEC, normalEC), 0.0);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/getSpecular.js
var import_InlineWorkers208 = __toESM(require_InlineWorkers(), 1);
var getSpecular_default = "/**\n * Calculates the specular intensity of reflected light.\n *\n * @name czm_getSpecular\n * @glslFunction\n *\n * @param {vec3} lightDirectionEC Unit vector pointing to the light source in eye coordinates.\n * @param {vec3} toEyeEC Unit vector pointing to the eye position in eye coordinates.\n * @param {vec3} normalEC The surface normal in eye coordinates.\n * @param {float} shininess The sharpness of the specular reflection. Higher values create a smaller, more focused specular highlight.\n *\n * @returns {float} The intensity of the specular highlight.\n *\n * @see czm_phong\n *\n * @example\n * float diffuseIntensity = czm_getLambertDiffuse(lightDirectionEC, normalEC);\n * float specularIntensity = czm_getSpecular(lightDirectionEC, toEyeEC, normalEC, 200);\n * vec3 color = (diffuseColor * diffuseIntensity) + (specularColor * specularIntensity);\n */\nfloat czm_getSpecular(vec3 lightDirectionEC, vec3 toEyeEC, vec3 normalEC, float shininess)\n{\n vec3 toReflectedLight = reflect(-lightDirectionEC, normalEC);\n float specular = max(dot(toReflectedLight, toEyeEC), 0.0);\n\n // pow has undefined behavior if both parameters <= 0.\n // Prevent this by making sure shininess is at least czm_epsilon2.\n return pow(specular, max(shininess, czm_epsilon2));\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/getWaterNoise.js
var import_InlineWorkers209 = __toESM(require_InlineWorkers(), 1);
var getWaterNoise_default = "/**\n * @private\n */\nvec4 czm_getWaterNoise(sampler2D normalMap, vec2 uv, float time, float angleInRadians)\n{\n float cosAngle = cos(angleInRadians);\n float sinAngle = sin(angleInRadians);\n\n // time dependent sampling directions\n vec2 s0 = vec2(1.0/17.0, 0.0);\n vec2 s1 = vec2(-1.0/29.0, 0.0);\n vec2 s2 = vec2(1.0/101.0, 1.0/59.0);\n vec2 s3 = vec2(-1.0/109.0, -1.0/57.0);\n\n // rotate sampling direction by specified angle\n s0 = vec2((cosAngle * s0.x) - (sinAngle * s0.y), (sinAngle * s0.x) + (cosAngle * s0.y));\n s1 = vec2((cosAngle * s1.x) - (sinAngle * s1.y), (sinAngle * s1.x) + (cosAngle * s1.y));\n s2 = vec2((cosAngle * s2.x) - (sinAngle * s2.y), (sinAngle * s2.x) + (cosAngle * s2.y));\n s3 = vec2((cosAngle * s3.x) - (sinAngle * s3.y), (sinAngle * s3.x) + (cosAngle * s3.y));\n\n vec2 uv0 = (uv/103.0) + (time * s0);\n vec2 uv1 = uv/107.0 + (time * s1) + vec2(0.23);\n vec2 uv2 = uv/vec2(897.0, 983.0) + (time * s2) + vec2(0.51);\n vec2 uv3 = uv/vec2(991.0, 877.0) + (time * s3) + vec2(0.71);\n\n uv0 = fract(uv0);\n uv1 = fract(uv1);\n uv2 = fract(uv2);\n uv3 = fract(uv3);\n vec4 noise = (texture(normalMap, uv0)) +\n (texture(normalMap, uv1)) +\n (texture(normalMap, uv2)) +\n (texture(normalMap, uv3));\n\n // average and scale to between -1 and 1\n return ((noise / 4.0) - 0.5) * 2.0;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/hue.js
var import_InlineWorkers210 = __toESM(require_InlineWorkers(), 1);
var hue_default = "/**\n * Adjusts the hue of a color.\n * \n * @name czm_hue\n * @glslFunction\n * \n * @param {vec3} rgb The color.\n * @param {float} adjustment The amount to adjust the hue of the color in radians.\n *\n * @returns {float} The color with the hue adjusted.\n *\n * @example\n * vec3 adjustHue = czm_hue(color, czm_pi); // The same as czm_hue(color, -czm_pi)\n */\nvec3 czm_hue(vec3 rgb, float adjustment)\n{\n const mat3 toYIQ = mat3(0.299, 0.587, 0.114,\n 0.595716, -0.274453, -0.321263,\n 0.211456, -0.522591, 0.311135);\n const mat3 toRGB = mat3(1.0, 0.9563, 0.6210,\n 1.0, -0.2721, -0.6474,\n 1.0, -1.107, 1.7046);\n \n vec3 yiq = toYIQ * rgb;\n float hue = atan(yiq.z, yiq.y) + adjustment;\n float chroma = sqrt(yiq.z * yiq.z + yiq.y * yiq.y);\n \n vec3 color = vec3(yiq.x, chroma * cos(hue), chroma * sin(hue));\n return toRGB * color;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/inverseGamma.js
var import_InlineWorkers211 = __toESM(require_InlineWorkers(), 1);
var inverseGamma_default = "/**\n * Converts a color in linear space to RGB space.\n *\n * @name czm_inverseGamma\n * @glslFunction\n *\n * @param {vec3} color The color in linear space.\n * @returns {vec3} The color in RGB space.\n */\nvec3 czm_inverseGamma(vec3 color) {\n return pow(color, vec3(1.0 / czm_gamma));\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/isEmpty.js
var import_InlineWorkers212 = __toESM(require_InlineWorkers(), 1);
var isEmpty_default = "/**\n * Determines if a time interval is empty.\n *\n * @name czm_isEmpty\n * @glslFunction \n * \n * @param {czm_raySegment} interval The interval to test.\n * \n * @returns {bool} true if the time interval is empty; otherwise, false.\n *\n * @example\n * bool b0 = czm_isEmpty(czm_emptyRaySegment); // true\n * bool b1 = czm_isEmpty(czm_raySegment(0.0, 1.0)); // false\n * bool b2 = czm_isEmpty(czm_raySegment(1.0, 1.0)); // false, contains 1.0.\n */\nbool czm_isEmpty(czm_raySegment interval)\n{\n return (interval.stop < 0.0);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/isFull.js
var import_InlineWorkers213 = __toESM(require_InlineWorkers(), 1);
var isFull_default = "/**\n * Determines if a time interval is empty.\n *\n * @name czm_isFull\n * @glslFunction \n * \n * @param {czm_raySegment} interval The interval to test.\n * \n * @returns {bool} true if the time interval is empty; otherwise, false.\n *\n * @example\n * bool b0 = czm_isEmpty(czm_emptyRaySegment); // true\n * bool b1 = czm_isEmpty(czm_raySegment(0.0, 1.0)); // false\n * bool b2 = czm_isEmpty(czm_raySegment(1.0, 1.0)); // false, contains 1.0.\n */\nbool czm_isFull(czm_raySegment interval)\n{\n return (interval.start == 0.0 && interval.stop == czm_infinity);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/latitudeToWebMercatorFraction.js
var import_InlineWorkers214 = __toESM(require_InlineWorkers(), 1);
var latitudeToWebMercatorFraction_default = "/**\n * Computes the fraction of a Web Wercator rectangle at which a given geodetic latitude is located.\n *\n * @name czm_latitudeToWebMercatorFraction\n * @glslFunction\n *\n * @param {float} latitude The geodetic latitude, in radians.\n * @param {float} southMercatorY The Web Mercator coordinate of the southern boundary of the rectangle.\n * @param {float} oneOverMercatorHeight The total height of the rectangle in Web Mercator coordinates.\n *\n * @returns {float} The fraction of the rectangle at which the latitude occurs. If the latitude is the southern\n * boundary of the rectangle, the return value will be zero. If it is the northern boundary, the return\n * value will be 1.0. Latitudes in between are mapped according to the Web Mercator projection.\n */ \nfloat czm_latitudeToWebMercatorFraction(float latitude, float southMercatorY, float oneOverMercatorHeight)\n{\n float sinLatitude = sin(latitude);\n float mercatorY = 0.5 * log((1.0 + sinLatitude) / (1.0 - sinLatitude));\n \n return (mercatorY - southMercatorY) * oneOverMercatorHeight;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/lineDistance.js
var import_InlineWorkers215 = __toESM(require_InlineWorkers(), 1);
var lineDistance_default = "/**\n * Computes distance from an point in 2D to a line in 2D.\n *\n * @name czm_lineDistance\n * @glslFunction\n *\n * param {vec2} point1 A point along the line.\n * param {vec2} point2 A point along the line.\n * param {vec2} point A point that may or may not be on the line.\n * returns {float} The distance from the point to the line.\n */\nfloat czm_lineDistance(vec2 point1, vec2 point2, vec2 point) {\n return abs((point2.y - point1.y) * point.x - (point2.x - point1.x) * point.y + point2.x * point1.y - point2.y * point1.x) / distance(point2, point1);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/linearToSrgb.js
var import_InlineWorkers216 = __toESM(require_InlineWorkers(), 1);
var linearToSrgb_default = "/**\n * Converts a linear RGB color to an sRGB color.\n *\n * @param {vec3|vec4} linearIn The color in linear color space.\n * @returns {vec3|vec4} The color in sRGB color space. The vector type matches the input.\n */\nvec3 czm_linearToSrgb(vec3 linearIn) \n{\n return pow(linearIn, vec3(1.0/2.2));\n}\n\nvec4 czm_linearToSrgb(vec4 linearIn) \n{\n vec3 srgbOut = pow(linearIn.rgb, vec3(1.0/2.2));\n return vec4(srgbOut, linearIn.a);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/luminance.js
var import_InlineWorkers217 = __toESM(require_InlineWorkers(), 1);
var luminance_default = "/**\n * Computes the luminance of a color. \n *\n * @name czm_luminance\n * @glslFunction\n *\n * @param {vec3} rgb The color.\n * \n * @returns {float} The luminance.\n *\n * @example\n * float light = czm_luminance(vec3(0.0)); // 0.0\n * float dark = czm_luminance(vec3(1.0)); // ~1.0 \n */\nfloat czm_luminance(vec3 rgb)\n{\n // Algorithm from Chapter 10 of Graphics Shaders.\n const vec3 W = vec3(0.2125, 0.7154, 0.0721);\n return dot(rgb, W);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/maximumComponent.js
var import_InlineWorkers218 = __toESM(require_InlineWorkers(), 1);
var maximumComponent_default = "/**\n * Find the maximum component of a vector.\n *\n * @name czm_maximumComponent\n * @glslFunction\n *\n * @param {vec2|vec3|vec4} v The input vector.\n * @returns {float} The value of the largest component.\n */\nfloat czm_maximumComponent(vec2 v)\n{\n return max(v.x, v.y);\n}\nfloat czm_maximumComponent(vec3 v)\n{\n return max(max(v.x, v.y), v.z);\n}\nfloat czm_maximumComponent(vec4 v)\n{\n return max(max(max(v.x, v.y), v.z), v.w);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/metersPerPixel.js
var import_InlineWorkers219 = __toESM(require_InlineWorkers(), 1);
var metersPerPixel_default = "/**\n * Computes the size of a pixel in meters at a distance from the eye.\n * near = 0 and far = 1.\n *
\n * This transform is useful when there is a need to manipulate window coordinates\n * in a vertex shader as done by {@link BillboardCollection}.\n *
\n * This function should not be confused with {@link czm_viewportOrthographic},\n * which is an orthographic projection matrix that transforms from window \n * coordinates to clip coordinates.\n *\n * @name czm_modelToWindowCoordinates\n * @glslFunction\n *\n * @param {vec4} position The position in model coordinates to transform.\n *\n * @returns {vec4} The transformed position in window coordinates.\n *\n * @see czm_eyeToWindowCoordinates\n * @see czm_modelViewProjection\n * @see czm_viewportTransformation\n * @see czm_viewportOrthographic\n * @see BillboardCollection\n *\n * @example\n * vec4 positionWC = czm_modelToWindowCoordinates(positionMC);\n */\nvec4 czm_modelToWindowCoordinates(vec4 position)\n{\n vec4 positionEC = czm_modelView * position;\n vec4 q = czm_projection * positionEC;\n q.xyz /= q.w; // normalized device coordinates\n q.xyz = (czm_viewportTransformation * vec4(q.xyz, 1.0)).xyz; // window coordinates\n return q;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/multiplyWithColorBalance.js
var import_InlineWorkers221 = __toESM(require_InlineWorkers(), 1);
var multiplyWithColorBalance_default = "/**\n * DOC_TBA\n *\n * @name czm_multiplyWithColorBalance\n * @glslFunction\n */\nvec3 czm_multiplyWithColorBalance(vec3 left, vec3 right)\n{\n // Algorithm from Chapter 10 of Graphics Shaders.\n const vec3 W = vec3(0.2125, 0.7154, 0.0721);\n \n vec3 target = left * right;\n float leftLuminance = dot(left, W);\n float rightLuminance = dot(right, W);\n float targetLuminance = dot(target, W);\n \n return ((leftLuminance + rightLuminance) / (2.0 * targetLuminance)) * target;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/nearFarScalar.js
var import_InlineWorkers222 = __toESM(require_InlineWorkers(), 1);
var nearFarScalar_default = "/**\n * Computes a value that scales with distance. The scaling is clamped at the near and\n * far distances, and does not extrapolate. This function works with the\n * {@link NearFarScalar} JavaScript class.\n *\n * @name czm_nearFarScalar\n * @glslFunction\n *\n * @param {vec4} nearFarScalar A vector with 4 components: Near distance (x), Near value (y), Far distance (z), Far value (w).\n * @param {float} cameraDistSq The square of the current distance from the camera.\n *\n * @returns {float} The value at this distance.\n */\nfloat czm_nearFarScalar(vec4 nearFarScalar, float cameraDistSq)\n{\n float valueAtMin = nearFarScalar.y;\n float valueAtMax = nearFarScalar.w;\n float nearDistanceSq = nearFarScalar.x * nearFarScalar.x;\n float farDistanceSq = nearFarScalar.z * nearFarScalar.z;\n\n float t = (cameraDistSq - nearDistanceSq) / (farDistanceSq - nearDistanceSq);\n\n t = pow(clamp(t, 0.0, 1.0), 0.2);\n\n return mix(valueAtMin, valueAtMax, t);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/octDecode.js
var import_InlineWorkers223 = __toESM(require_InlineWorkers(), 1);
var octDecode_default = ` /**
* Decodes a unit-length vector in 'oct' encoding to a normalized 3-component Cartesian vector.
* The 'oct' encoding is described in "A Survey of Efficient Representations of Independent Unit Vectors",
* Cigolle et al 2014: http://jcgt.org/published/0003/02/01/
*
* @name czm_octDecode
* @param {vec2} encoded The oct-encoded, unit-length vector
* @param {float} range The maximum value of the SNORM range. The encoded vector is stored in log2(rangeMax+1) bits.
* @returns {vec3} The decoded and normalized vector
*/
vec3 czm_octDecode(vec2 encoded, float range)
{
if (encoded.x == 0.0 && encoded.y == 0.0) {
return vec3(0.0, 0.0, 0.0);
}
encoded = encoded / range * 2.0 - 1.0;
vec3 v = vec3(encoded.x, encoded.y, 1.0 - abs(encoded.x) - abs(encoded.y));
if (v.z < 0.0)
{
v.xy = (1.0 - abs(v.yx)) * czm_signNotZero(v.xy);
}
return normalize(v);
}
/**
* Decodes a unit-length vector in 'oct' encoding to a normalized 3-component Cartesian vector.
* The 'oct' encoding is described in "A Survey of Efficient Representations of Independent Unit Vectors",
* Cigolle et al 2014: http://jcgt.org/published/0003/02/01/
*
* @name czm_octDecode
* @param {vec2} encoded The oct-encoded, unit-length vector
* @returns {vec3} The decoded and normalized vector
*/
vec3 czm_octDecode(vec2 encoded)
{
return czm_octDecode(encoded, 255.0);
}
/**
* Decodes a unit-length vector in 'oct' encoding packed into a floating-point number to a normalized 3-component Cartesian vector.
* The 'oct' encoding is described in "A Survey of Efficient Representations of Independent Unit Vectors",
* Cigolle et al 2014: http://jcgt.org/published/0003/02/01/
*
* @name czm_octDecode
* @param {float} encoded The oct-encoded, unit-length vector
* @returns {vec3} The decoded and normalized vector
*/
vec3 czm_octDecode(float encoded)
{
float temp = encoded / 256.0;
float x = floor(temp);
float y = (temp - x) * 256.0;
return czm_octDecode(vec2(x, y));
}
/**
* Decodes three unit-length vectors in 'oct' encoding packed into two floating-point numbers to normalized 3-component Cartesian vectors.
* The 'oct' encoding is described in "A Survey of Efficient Representations of Independent Unit Vectors",
* Cigolle et al 2014: http://jcgt.org/published/0003/02/01/
*
* @name czm_octDecode
* @param {vec2} encoded The packed oct-encoded, unit-length vectors.
* @param {vec3} vector1 One decoded and normalized vector.
* @param {vec3} vector2 One decoded and normalized vector.
* @param {vec3} vector3 One decoded and normalized vector.
*/
void czm_octDecode(vec2 encoded, out vec3 vector1, out vec3 vector2, out vec3 vector3)
{
float temp = encoded.x / 65536.0;
float x = floor(temp);
float encodedFloat1 = (temp - x) * 65536.0;
temp = encoded.y / 65536.0;
float y = floor(temp);
float encodedFloat2 = (temp - y) * 65536.0;
vector1 = czm_octDecode(encodedFloat1);
vector2 = czm_octDecode(encodedFloat2);
vector3 = czm_octDecode(vec2(x, y));
}
`;
// packages/engine/Source/Shaders/Builtin/Functions/packDepth.js
var import_InlineWorkers224 = __toESM(require_InlineWorkers(), 1);
var packDepth_default = "/**\n * Packs a depth value into a vec4 that can be represented by unsigned bytes.\n *\n * @name czm_packDepth\n * @glslFunction\n *\n * @param {float} depth The floating-point depth.\n * @returns {vec4} The packed depth.\n */\nvec4 czm_packDepth(float depth)\n{\n // See Aras Pranckevi\u010Dius' post Encoding Floats to RGBA\n // http://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/\n vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * depth;\n enc = fract(enc);\n enc -= enc.yzww * vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 0.0);\n return enc;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/pbrLighting.js
var import_InlineWorkers225 = __toESM(require_InlineWorkers(), 1);
var pbrLighting_default = "vec3 lambertianDiffuse(vec3 diffuseColor)\n{\n return diffuseColor / czm_pi;\n}\n\nvec3 fresnelSchlick2(vec3 f0, vec3 f90, float VdotH)\n{\n float versine = 1.0 - VdotH;\n // pow(versine, 5.0) is slow. See https://stackoverflow.com/a/68793086/10082269\n float versineSquared = versine * versine;\n return f0 + (f90 - f0) * versineSquared * versineSquared * versine;\n}\n\n#ifdef USE_ANISOTROPY\n/**\n * @param {float} bitangentRoughness Material roughness (along the anisotropy bitangent)\n * @param {float} tangentialRoughness Anisotropic roughness (along the anisotropy tangent)\n * @param {vec3} lightDirection The direction from the fragment to the light source, transformed to tangent-bitangent-normal coordinates\n * @param {vec3} viewDirection The direction from the fragment to the camera, transformed to tangent-bitangent-normal coordinates\n */\nfloat smithVisibilityGGX_anisotropic(float bitangentRoughness, float tangentialRoughness, vec3 lightDirection, vec3 viewDirection)\n{\n vec3 roughnessScale = vec3(tangentialRoughness, bitangentRoughness, 1.0);\n float GGXV = lightDirection.z * length(roughnessScale * viewDirection);\n float GGXL = viewDirection.z * length(roughnessScale * lightDirection);\n float v = 0.5 / (GGXV + GGXL);\n return clamp(v, 0.0, 1.0);\n}\n\n/**\n * @param {float} bitangentRoughness Material roughness (along the anisotropy bitangent)\n * @param {float} tangentialRoughness Anisotropic roughness (along the anisotropy tangent)\n * @param {vec3} halfwayDirection The unit vector halfway between light and view directions, transformed to tangent-bitangent-normal coordinates\n */\nfloat GGX_anisotropic(float bitangentRoughness, float tangentialRoughness, vec3 halfwayDirection)\n{\n float roughnessSquared = bitangentRoughness * tangentialRoughness;\n vec3 f = halfwayDirection * vec3(bitangentRoughness, tangentialRoughness, roughnessSquared);\n float w2 = roughnessSquared / dot(f, f);\n return roughnessSquared * w2 * w2 / czm_pi;\n}\n#endif\n\n/**\n * Estimate the geometric self-shadowing of the microfacets in a surface,\n * using the Smith Joint GGX visibility function.\n * Note: Vis = G / (4 * NdotL * NdotV)\n * see Eric Heitz. 2014. Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs. Journal of Computer Graphics Techniques, 3\n * see Real-Time Rendering. Page 331 to 336.\n * see https://google.github.io/filament/Filament.md.html#materialsystem/specularbrdf/geometricshadowing(specularg)\n *\n * @param {float} alphaRoughness The roughness of the material, expressed as the square of perceptual roughness.\n * @param {float} NdotL The cosine of the angle between the surface normal and the direction to the light source.\n * @param {float} NdotV The cosine of the angle between the surface normal and the direction to the camera.\n */\nfloat smithVisibilityGGX(float alphaRoughness, float NdotL, float NdotV)\n{\n float alphaRoughnessSq = alphaRoughness * alphaRoughness;\n\n float GGXV = NdotL * sqrt(NdotV * NdotV * (1.0 - alphaRoughnessSq) + alphaRoughnessSq);\n float GGXL = NdotV * sqrt(NdotL * NdotL * (1.0 - alphaRoughnessSq) + alphaRoughnessSq);\n\n float GGX = GGXV + GGXL;\n if (GGX > 0.0)\n {\n return 0.5 / GGX;\n }\n return 0.0;\n}\n\n/**\n * Estimate the fraction of the microfacets in a surface that are aligned with \n * the halfway vector, which is aligned halfway between the directions from\n * the fragment to the camera and from the fragment to the light source.\n *\n * @param {float} alphaRoughness The roughness of the material, expressed as the square of perceptual roughness.\n * @param {float} NdotH The cosine of the angle between the surface normal and the halfway vector.\n * @return {float} The fraction of microfacets aligned to the halfway vector.\n */\nfloat GGX(float alphaRoughness, float NdotH)\n{\n float alphaRoughnessSquared = alphaRoughness * alphaRoughness;\n float f = (NdotH * alphaRoughnessSquared - NdotH) * NdotH + 1.0;\n return alphaRoughnessSquared / (czm_pi * f * f);\n}\n\n/**\n * Compute the strength of the specular reflection due to direct lighting.\n *\n * @param {vec3} normal The surface normal.\n * @param {vec3} lightDirection The unit vector pointing from the fragment to the light source.\n * @param {vec3} viewDirection The unit vector pointing from the fragment to the camera.\n * @param {vec3} halfwayDirection The unit vector pointing from the fragment to halfway between the light source and the camera.\n * @param {float} alphaRoughness The roughness of the material, expressed as the square of perceptual roughness.\n * @return {float} The strength of the specular reflection.\n */\nfloat computeDirectSpecularStrength(vec3 normal, vec3 lightDirection, vec3 viewDirection, vec3 halfwayDirection, float alphaRoughness)\n{\n float NdotL = clamp(dot(normal, lightDirection), 0.0, 1.0);\n float NdotV = clamp(dot(normal, viewDirection), 0.0, 1.0);\n float G = smithVisibilityGGX(alphaRoughness, NdotL, NdotV);\n float NdotH = clamp(dot(normal, halfwayDirection), 0.0, 1.0);\n float D = GGX(alphaRoughness, NdotH);\n return G * D;\n}\n\n/**\n * Compute the diffuse and specular contributions using physically based\n * rendering. This function only handles direct lighting.\n * time can be positive, negative, or zero.\n *\n * @name czm_pointAlongRay\n * @glslFunction\n *\n * @param {czm_ray} ray The ray to compute the point along.\n * @param {float} time The time along the ray.\n * \n * @returns {vec3} The point along the ray at the given time.\n * \n * @example\n * czm_ray ray = czm_ray(vec3(0.0), vec3(1.0, 0.0, 0.0)); // origin, direction\n * vec3 v = czm_pointAlongRay(ray, 2.0); // (2.0, 0.0, 0.0)\n */\nvec3 czm_pointAlongRay(czm_ray ray, float time)\n{\n return ray.origin + (time * ray.direction);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/rayEllipsoidIntersectionInterval.js
var import_InlineWorkers230 = __toESM(require_InlineWorkers(), 1);
var rayEllipsoidIntersectionInterval_default = "/**\n * DOC_TBA\n *\n * @name czm_rayEllipsoidIntersectionInterval\n * @glslFunction\n */\nczm_raySegment czm_rayEllipsoidIntersectionInterval(czm_ray ray, vec3 ellipsoid_center, vec3 ellipsoid_inverseRadii)\n{\n // ray and ellipsoid center in eye coordinates. radii in model coordinates.\n vec3 q = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ray.origin, 1.0)).xyz;\n vec3 w = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ray.direction, 0.0)).xyz;\n\n q = q - ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ellipsoid_center, 1.0)).xyz;\n\n float q2 = dot(q, q);\n float qw = dot(q, w);\n\n if (q2 > 1.0) // Outside ellipsoid.\n {\n if (qw >= 0.0) // Looking outward or tangent (0 intersections).\n {\n return czm_emptyRaySegment;\n }\n else // qw < 0.0.\n {\n float qw2 = qw * qw;\n float difference = q2 - 1.0; // Positively valued.\n float w2 = dot(w, w);\n float product = w2 * difference;\n\n if (qw2 < product) // Imaginary roots (0 intersections).\n {\n return czm_emptyRaySegment;\n }\n else if (qw2 > product) // Distinct roots (2 intersections).\n {\n float discriminant = qw * qw - product;\n float temp = -qw + sqrt(discriminant); // Avoid cancellation.\n float root0 = temp / w2;\n float root1 = difference / temp;\n if (root0 < root1)\n {\n czm_raySegment i = czm_raySegment(root0, root1);\n return i;\n }\n else\n {\n czm_raySegment i = czm_raySegment(root1, root0);\n return i;\n }\n }\n else // qw2 == product. Repeated roots (2 intersections).\n {\n float root = sqrt(difference / w2);\n czm_raySegment i = czm_raySegment(root, root);\n return i;\n }\n }\n }\n else if (q2 < 1.0) // Inside ellipsoid (2 intersections).\n {\n float difference = q2 - 1.0; // Negatively valued.\n float w2 = dot(w, w);\n float product = w2 * difference; // Negatively valued.\n float discriminant = qw * qw - product;\n float temp = -qw + sqrt(discriminant); // Positively valued.\n czm_raySegment i = czm_raySegment(0.0, temp / w2);\n return i;\n }\n else // q2 == 1.0. On ellipsoid.\n {\n if (qw < 0.0) // Looking inward.\n {\n float w2 = dot(w, w);\n czm_raySegment i = czm_raySegment(0.0, -qw / w2);\n return i;\n }\n else // qw >= 0.0. Looking outward or tangent.\n {\n return czm_emptyRaySegment;\n }\n }\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/raySphereIntersectionInterval.js
var import_InlineWorkers231 = __toESM(require_InlineWorkers(), 1);
var raySphereIntersectionInterval_default = "/**\n * Compute the intersection interval of a ray with a sphere.\n *\n * @name czm_raySphereIntersectionInterval\n * @glslFunction\n *\n * @param {czm_ray} ray The ray.\n * @param {vec3} center The center of the sphere.\n * @param {float} radius The radius of the sphere.\n * @return {czm_raySegment} The intersection interval of the ray with the sphere.\n */\nczm_raySegment czm_raySphereIntersectionInterval(czm_ray ray, vec3 center, float radius)\n{\n vec3 o = ray.origin;\n vec3 d = ray.direction;\n\n vec3 oc = o - center;\n\n float a = dot(d, d);\n float b = 2.0 * dot(d, oc);\n float c = dot(oc, oc) - (radius * radius);\n\n float det = (b * b) - (4.0 * a * c);\n\n if (det < 0.0) {\n return czm_emptyRaySegment;\n }\n\n float sqrtDet = sqrt(det);\n\n float t0 = (-b - sqrtDet) / (2.0 * a);\n float t1 = (-b + sqrtDet) / (2.0 * a);\n\n czm_raySegment result = czm_raySegment(t0, t1);\n return result;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/readDepth.js
var import_InlineWorkers232 = __toESM(require_InlineWorkers(), 1);
var readDepth_default = "float czm_readDepth(sampler2D depthTexture, vec2 texCoords)\n{\n return czm_reverseLogDepth(texture(depthTexture, texCoords).r);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/readNonPerspective.js
var import_InlineWorkers233 = __toESM(require_InlineWorkers(), 1);
var readNonPerspective_default = "/**\n * Reads a value previously transformed with {@link czm_writeNonPerspective}\n * by dividing it by `w`, the value used in the perspective divide.\n * This function is intended to be called in a fragment shader to access a\n * `varying` that should not be subject to perspective interpolation.\n * For example, screen-space texture coordinates. The value should have been\n * previously written in the vertex shader with a call to\n * {@link czm_writeNonPerspective}.\n *\n * @name czm_readNonPerspective\n * @glslFunction\n *\n * @param {float|vec2|vec3|vec4} value The non-perspective value to be read.\n * @param {float} oneOverW One over the perspective divide value, `w`. Usually this is simply `gl_FragCoord.w`.\n * @returns {float|vec2|vec3|vec4} The usable value.\n */\nfloat czm_readNonPerspective(float value, float oneOverW) {\n return value * oneOverW;\n}\n\nvec2 czm_readNonPerspective(vec2 value, float oneOverW) {\n return value * oneOverW;\n}\n\nvec3 czm_readNonPerspective(vec3 value, float oneOverW) {\n return value * oneOverW;\n}\n\nvec4 czm_readNonPerspective(vec4 value, float oneOverW) {\n return value * oneOverW;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/reverseLogDepth.js
var import_InlineWorkers234 = __toESM(require_InlineWorkers(), 1);
var reverseLogDepth_default = "float czm_reverseLogDepth(float logZ)\n{\n#ifdef LOG_DEPTH\n float near = czm_currentFrustum.x;\n float far = czm_currentFrustum.y;\n float log2Depth = logZ * czm_log2FarDepthFromNearPlusOne;\n float depthFromNear = exp2(log2Depth) - 1.0;\n return far * (1.0 - near / (depthFromNear + near)) / (far - near);\n#endif\n return logZ;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/round.js
var import_InlineWorkers235 = __toESM(require_InlineWorkers(), 1);
var round_default = "/**\n * Round a floating point value. This function exists because round() doesn't\n * exist in GLSL 1.00. \n *\n * @param {float|vec2|vec3|vec4} value The value to round\n * @param {float|vec2|vec3|vec3} The rounded value. The type matches the input.\n */\nfloat czm_round(float value) {\n return floor(value + 0.5);\n}\n\nvec2 czm_round(vec2 value) {\n return floor(value + 0.5);\n}\n\nvec3 czm_round(vec3 value) {\n return floor(value + 0.5);\n}\n\nvec4 czm_round(vec4 value) {\n return floor(value + 0.5);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/saturation.js
var import_InlineWorkers236 = __toESM(require_InlineWorkers(), 1);
var saturation_default = "/**\n * Adjusts the saturation of a color.\n * \n * @name czm_saturation\n * @glslFunction\n * \n * @param {vec3} rgb The color.\n * @param {float} adjustment The amount to adjust the saturation of the color.\n *\n * @returns {float} The color with the saturation adjusted.\n *\n * @example\n * vec3 greyScale = czm_saturation(color, 0.0);\n * vec3 doubleSaturation = czm_saturation(color, 2.0);\n */\nvec3 czm_saturation(vec3 rgb, float adjustment)\n{\n // Algorithm from Chapter 16 of OpenGL Shading Language\n const vec3 W = vec3(0.2125, 0.7154, 0.0721);\n vec3 intensity = vec3(dot(rgb, W));\n return mix(intensity, rgb, adjustment);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/shadowDepthCompare.js
var import_InlineWorkers237 = __toESM(require_InlineWorkers(), 1);
var shadowDepthCompare_default = "\nfloat czm_sampleShadowMap(highp samplerCube shadowMap, vec3 d)\n{\n return czm_unpackDepth(czm_textureCube(shadowMap, d));\n}\n\nfloat czm_sampleShadowMap(highp sampler2D shadowMap, vec2 uv)\n{\n#ifdef USE_SHADOW_DEPTH_TEXTURE\n return texture(shadowMap, uv).r;\n#else\n return czm_unpackDepth(texture(shadowMap, uv));\n#endif\n}\n\nfloat czm_shadowDepthCompare(samplerCube shadowMap, vec3 uv, float depth)\n{\n return step(depth, czm_sampleShadowMap(shadowMap, uv));\n}\n\nfloat czm_shadowDepthCompare(sampler2D shadowMap, vec2 uv, float depth)\n{\n return step(depth, czm_sampleShadowMap(shadowMap, uv));\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/shadowVisibility.js
var import_InlineWorkers238 = __toESM(require_InlineWorkers(), 1);
var shadowVisibility_default = "\nfloat czm_private_shadowVisibility(float visibility, float nDotL, float normalShadingSmooth, float darkness)\n{\n#ifdef USE_NORMAL_SHADING\n#ifdef USE_NORMAL_SHADING_SMOOTH\n float strength = clamp(nDotL / normalShadingSmooth, 0.0, 1.0);\n#else\n float strength = step(0.0, nDotL);\n#endif\n visibility *= strength;\n#endif\n\n visibility = max(visibility, darkness);\n return visibility;\n}\n\n#ifdef USE_CUBE_MAP_SHADOW\nfloat czm_shadowVisibility(samplerCube shadowMap, czm_shadowParameters shadowParameters)\n{\n float depthBias = shadowParameters.depthBias;\n float depth = shadowParameters.depth;\n float nDotL = shadowParameters.nDotL;\n float normalShadingSmooth = shadowParameters.normalShadingSmooth;\n float darkness = shadowParameters.darkness;\n vec3 uvw = shadowParameters.texCoords;\n\n depth -= depthBias;\n float visibility = czm_shadowDepthCompare(shadowMap, uvw, depth);\n return czm_private_shadowVisibility(visibility, nDotL, normalShadingSmooth, darkness);\n}\n#else\nfloat czm_shadowVisibility(sampler2D shadowMap, czm_shadowParameters shadowParameters)\n{\n float depthBias = shadowParameters.depthBias;\n float depth = shadowParameters.depth;\n float nDotL = shadowParameters.nDotL;\n float normalShadingSmooth = shadowParameters.normalShadingSmooth;\n float darkness = shadowParameters.darkness;\n vec2 uv = shadowParameters.texCoords;\n\n depth -= depthBias;\n#ifdef USE_SOFT_SHADOWS\n vec2 texelStepSize = shadowParameters.texelStepSize;\n float radius = 1.0;\n float dx0 = -texelStepSize.x * radius;\n float dy0 = -texelStepSize.y * radius;\n float dx1 = texelStepSize.x * radius;\n float dy1 = texelStepSize.y * radius;\n float visibility = (\n czm_shadowDepthCompare(shadowMap, uv, depth) +\n czm_shadowDepthCompare(shadowMap, uv + vec2(dx0, dy0), depth) +\n czm_shadowDepthCompare(shadowMap, uv + vec2(0.0, dy0), depth) +\n czm_shadowDepthCompare(shadowMap, uv + vec2(dx1, dy0), depth) +\n czm_shadowDepthCompare(shadowMap, uv + vec2(dx0, 0.0), depth) +\n czm_shadowDepthCompare(shadowMap, uv + vec2(dx1, 0.0), depth) +\n czm_shadowDepthCompare(shadowMap, uv + vec2(dx0, dy1), depth) +\n czm_shadowDepthCompare(shadowMap, uv + vec2(0.0, dy1), depth) +\n czm_shadowDepthCompare(shadowMap, uv + vec2(dx1, dy1), depth)\n ) * (1.0 / 9.0);\n#else\n float visibility = czm_shadowDepthCompare(shadowMap, uv, depth);\n#endif\n\n return czm_private_shadowVisibility(visibility, nDotL, normalShadingSmooth, darkness);\n}\n#endif\n";
// packages/engine/Source/Shaders/Builtin/Functions/signNotZero.js
var import_InlineWorkers239 = __toESM(require_InlineWorkers(), 1);
var signNotZero_default = "/**\n * Returns 1.0 if the given value is positive or zero, and -1.0 if it is negative. This is similar to the GLSL\n * built-in function sign except that returns 1.0 instead of 0.0 when the input value is 0.0.\n * \n * @name czm_signNotZero\n * @glslFunction\n *\n * @param {} value The value for which to determine the sign.\n * @returns {} 1.0 if the value is positive or zero, -1.0 if the value is negative.\n */\nfloat czm_signNotZero(float value)\n{\n return value >= 0.0 ? 1.0 : -1.0;\n}\n\nvec2 czm_signNotZero(vec2 value)\n{\n return vec2(czm_signNotZero(value.x), czm_signNotZero(value.y));\n}\n\nvec3 czm_signNotZero(vec3 value)\n{\n return vec3(czm_signNotZero(value.x), czm_signNotZero(value.y), czm_signNotZero(value.z));\n}\n\nvec4 czm_signNotZero(vec4 value)\n{\n return vec4(czm_signNotZero(value.x), czm_signNotZero(value.y), czm_signNotZero(value.z), czm_signNotZero(value.w));\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/sphericalHarmonics.js
var import_InlineWorkers240 = __toESM(require_InlineWorkers(), 1);
var sphericalHarmonics_default = "/**\n * Computes a color from the third order spherical harmonic coefficients and a normalized direction vector.\n * vec3) that was encoded with {@link EncodedCartesian3},\n * and then provided to the shader as separate high and low bits to\n * be relative to the eye. As shown in the example, the position can then be transformed in eye\n * or clip coordinates using {@link czm_modelViewRelativeToEye} or {@link czm_modelViewProjectionRelativeToEye},\n * respectively.\n * matrix can be\n * a mat2, mat3, or mat4.\n *\n * @name czm_transpose\n * @glslFunction\n *\n * @param {} matrix The matrix to transpose.\n *\n * @returns {} The transposed matrix.\n *\n * @example\n * // GLSL declarations\n * mat2 czm_transpose(mat2 matrix);\n * mat3 czm_transpose(mat3 matrix);\n * mat4 czm_transpose(mat4 matrix);\n *\n * // Transpose a 3x3 rotation matrix to find its inverse.\n * mat3 eastNorthUpToEye = czm_eastNorthUpToEyeCoordinates(\n * positionMC, normalEC);\n * mat3 eyeToEastNorthUp = czm_transpose(eastNorthUpToEye);\n */\nmat2 czm_transpose(mat2 matrix)\n{\n return mat2(\n matrix[0][0], matrix[1][0],\n matrix[0][1], matrix[1][1]);\n}\n\nmat3 czm_transpose(mat3 matrix)\n{\n return mat3(\n matrix[0][0], matrix[1][0], matrix[2][0],\n matrix[0][1], matrix[1][1], matrix[2][1],\n matrix[0][2], matrix[1][2], matrix[2][2]);\n}\n\nmat4 czm_transpose(mat4 matrix)\n{\n return mat4(\n matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0],\n matrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1],\n matrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2],\n matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/unpackClippingExtents.js
var import_InlineWorkers248 = __toESM(require_InlineWorkers(), 1);
var unpackClippingExtents_default = "vec2 getLookupUv(vec2 dimensions, int i) {\n int pixY = i / int(dimensions.x);\n int pixX = i - (pixY * int(dimensions.x));\n float pixelWidth = 1.0 / dimensions.x;\n float pixelHeight = 1.0 / dimensions.y;\n float u = (float(pixX) + 0.5) * pixelWidth; // sample from center of pixel\n float v = (float(pixY) + 0.5) * pixelHeight;\n return vec2(u, v);\n}\n\nvec4 czm_unpackClippingExtents(highp sampler2D extentsTexture, int index) {\n vec2 textureDimensions = vec2(textureSize(extentsTexture, 0));\n return texture(extentsTexture, getLookupUv(textureDimensions, index));\n}";
// packages/engine/Source/Shaders/Builtin/Functions/unpackDepth.js
var import_InlineWorkers249 = __toESM(require_InlineWorkers(), 1);
var unpackDepth_default = "/**\n * Unpacks a vec4 depth value to a float in [0, 1) range.\n *\n * @name czm_unpackDepth\n * @glslFunction\n *\n * @param {vec4} packedDepth The packed depth.\n *\n * @returns {float} The floating-point depth in [0, 1) range.\n */\nfloat czm_unpackDepth(vec4 packedDepth)\n{\n // See Aras Pranckevi\u010Dius' post Encoding Floats to RGBA\n // http://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/\n return dot(packedDepth, vec4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 16581375.0));\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/unpackFloat.js
var import_InlineWorkers250 = __toESM(require_InlineWorkers(), 1);
var unpackFloat_default = "/**\n * Unpack an IEEE 754 single-precision float that is packed as a little-endian unsigned normalized vec4.\n *\n * @name czm_unpackFloat\n * @glslFunction\n *\n * @param {vec4} packedFloat The packed float.\n *\n * @returns {float} The floating-point depth in arbitrary range.\n */\nfloat czm_unpackFloat(vec4 packedFloat)\n{\n // Convert to [0.0, 255.0] and round to integer\n packedFloat = floor(packedFloat * 255.0 + 0.5);\n float sign = 1.0 - step(128.0, packedFloat[3]) * 2.0;\n float exponent = 2.0 * mod(packedFloat[3], 128.0) + step(128.0, packedFloat[2]) - 127.0; \n if (exponent == -127.0)\n {\n return 0.0;\n }\n float mantissa = mod(packedFloat[2], 128.0) * 65536.0 + packedFloat[1] * 256.0 + packedFloat[0] + float(0x800000);\n float result = sign * exp2(exponent - 23.0) * mantissa;\n return result;\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/unpackUint.js
var import_InlineWorkers251 = __toESM(require_InlineWorkers(), 1);
var unpackUint_default = "/**\n * Unpack unsigned integers of 1-4 bytes. in WebGL 1, there is no uint type,\n * so the return value is an int.\n * czm_viewportTransformation. The transformation from\n * normalized device coordinates to clip coordinates is done using fragmentCoordinate.w,\n * which is expected to be the scalar used in the perspective divide. The transformation\n * from clip to eye coordinates is done using {@link czm_inverseProjection}.\n *\n * @name czm_windowToEyeCoordinates\n * @glslFunction\n *\n * @param {vec4} fragmentCoordinate The position in window coordinates to transform.\n *\n * @returns {vec4} The transformed position in eye coordinates.\n *\n * @see czm_modelToWindowCoordinates\n * @see czm_eyeToWindowCoordinates\n * @see czm_inverseProjection\n * @see czm_viewport\n * @see czm_viewportTransformation\n *\n * @example\n * vec4 positionEC = czm_windowToEyeCoordinates(gl_FragCoord);\n */\nvec4 czm_windowToEyeCoordinates(vec4 fragmentCoordinate)\n{\n vec2 screenCoordXY = (fragmentCoordinate.xy - czm_viewport.xy) / czm_viewport.zw;\n return czm_screenToEyeCoordinates(vec4(screenCoordXY, fragmentCoordinate.zw));\n}\n\nvec4 czm_screenToEyeCoordinates(vec2 screenCoordinateXY, float depthOrLogDepth)\n{\n // See reverseLogDepth.glsl. This is separate to re-use the pow.\n#if defined(LOG_DEPTH) || defined(LOG_DEPTH_READ_ONLY)\n float near = czm_currentFrustum.x;\n float far = czm_currentFrustum.y;\n float log2Depth = depthOrLogDepth * czm_log2FarDepthFromNearPlusOne;\n float depthFromNear = exp2(log2Depth) - 1.0;\n float depthFromCamera = depthFromNear + near;\n vec4 screenCoord = vec4(screenCoordinateXY, far * (1.0 - near / depthFromCamera) / (far - near), 1.0);\n vec4 eyeCoordinate = czm_screenToEyeCoordinates(screenCoord);\n eyeCoordinate.w = 1.0 / depthFromCamera; // Better precision\n#else\n vec4 screenCoord = vec4(screenCoordinateXY, depthOrLogDepth, 1.0);\n vec4 eyeCoordinate = czm_screenToEyeCoordinates(screenCoord);\n#endif\n return eyeCoordinate;\n}\n\n/**\n * Transforms a position given as window x/y and a depth or a log depth from window to eye coordinates.\n * This function produces more accurate results for window positions with log depth than\n * conventionally unpacking the log depth using czm_reverseLogDepth and using the standard version\n * of czm_windowToEyeCoordinates.\n *\n * @name czm_windowToEyeCoordinates\n * @glslFunction\n *\n * @param {vec2} fragmentCoordinateXY The XY position in window coordinates to transform.\n * @param {float} depthOrLogDepth A depth or log depth for the fragment.\n *\n * @see czm_modelToWindowCoordinates\n * @see czm_eyeToWindowCoordinates\n * @see czm_inverseProjection\n * @see czm_viewport\n * @see czm_viewportTransformation\n *\n * @returns {vec4} The transformed position in eye coordinates.\n */\nvec4 czm_windowToEyeCoordinates(vec2 fragmentCoordinateXY, float depthOrLogDepth)\n{\n vec2 screenCoordXY = (fragmentCoordinateXY.xy - czm_viewport.xy) / czm_viewport.zw;\n return czm_screenToEyeCoordinates(screenCoordXY, depthOrLogDepth);\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/writeDepthClamp.js
var import_InlineWorkers255 = __toESM(require_InlineWorkers(), 1);
var writeDepthClamp_default = "// emulated noperspective\n#if !defined(LOG_DEPTH)\nin float v_WindowZ;\n#endif\n\n/**\n * Emulates GL_DEPTH_CLAMP. Clamps a fragment to the near and far plane\n * by writing the fragment's depth. See czm_depthClamp for more details.\n *\n * @name czm_writeDepthClamp\n * @glslFunction\n *\n * @example\n * out_FragColor = color;\n * czm_writeDepthClamp();\n *\n * @see czm_depthClamp\n */\nvoid czm_writeDepthClamp()\n{\n#if (!defined(LOG_DEPTH) && (__VERSION__ == 300 || defined(GL_EXT_frag_depth)))\n gl_FragDepth = clamp(v_WindowZ * gl_FragCoord.w, 0.0, 1.0);\n#endif\n}\n";
// packages/engine/Source/Shaders/Builtin/Functions/writeLogDepth.js
var import_InlineWorkers256 = __toESM(require_InlineWorkers(), 1);
var writeLogDepth_default = "#ifdef LOG_DEPTH\nin float v_depthFromNearPlusOne;\n\n#ifdef POLYGON_OFFSET\nuniform vec2 u_polygonOffset;\n#endif\n\n#endif\n\n/**\n * Writes the fragment depth to the logarithmic depth buffer.\n * x) and the far distance (y) of the frustum defined by the camera.
* This is the largest possible frustum, not an individual frustum used for multi-frustum rendering.
* @memberof UniformState.prototype
* @type {Cartesian2}
*/
entireFrustum: {
get: function() {
return this._entireFrustum;
}
},
/**
* The near distance (x) and the far distance (y) of the frustum defined by the camera.
* This is the individual frustum used for multi-frustum rendering.
* @memberof UniformState.prototype
* @type {Cartesian2}
*/
currentFrustum: {
get: function() {
return this._currentFrustum;
}
},
/**
* The distances to the frustum planes. The top, bottom, left and right distances are
* the x, y, z, and w components, respectively.
* @memberof UniformState.prototype
* @type {Cartesian4}
*/
frustumPlanes: {
get: function() {
return this._frustumPlanes;
}
},
/**
* The far plane's distance from the near plane, plus 1.0.
*
* @memberof UniformState.prototype
* @type {number}
*/
farDepthFromNearPlusOne: {
get: function() {
return this._farDepthFromNearPlusOne;
}
},
/**
* The log2 of {@link UniformState#farDepthFromNearPlusOne}.
*
* @memberof UniformState.prototype
* @type {number}
*/
log2FarDepthFromNearPlusOne: {
get: function() {
return this._log2FarDepthFromNearPlusOne;
}
},
/**
* 1.0 divided by {@link UniformState#log2FarDepthFromNearPlusOne}.
*
* @memberof UniformState.prototype
* @type {number}
*/
oneOverLog2FarDepthFromNearPlusOne: {
get: function() {
return this._oneOverLog2FarDepthFromNearPlusOne;
}
},
/**
* The height in meters of the eye (camera) above or below the ellipsoid.
* @memberof UniformState.prototype
* @type {number}
*/
eyeHeight: {
get: function() {
return this._eyeHeight;
}
},
/**
* The height (x) and the height squared (y)
* in meters of the eye (camera) above the 2D world plane. This uniform is only valid
* when the {@link SceneMode} is SCENE2D.
* @memberof UniformState.prototype
* @type {Cartesian2}
*/
eyeHeight2D: {
get: function() {
return this._eyeHeight2D;
}
},
/**
* The ellipsoid surface normal at the camera position, in model coordinates.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
eyeEllipsoidNormalEC: {
get: function() {
return this._eyeEllipsoidNormalEC;
}
},
/**
* The ellipsoid radii of curvature at the camera position.
* The .x component is the prime vertical radius, .y is the meridional.
* @memberof UniformState.prototype
* @type {Cartesian2}
*/
eyeEllipsoidCurvature: {
get: function() {
return this._eyeEllipsoidCurvature;
}
},
/**
* A transform from model coordinates to an east-north-up coordinate system
* centered at the position on the ellipsoid below the camera
* @memberof UniformState.prototype
* @type {Matrix4}
*/
modelToEnu: {
get: function() {
return this._modelToEnu;
}
},
/**
* The inverse of {@link UniformState.prototype.modelToEnu}
* @memberof UniformState.prototype
* @type {Matrix4}
*/
enuToModel: {
get: function() {
return this._enuToModel;
}
},
/**
* The sun position in 3D world coordinates at the current scene time.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
sunPositionWC: {
get: function() {
return this._sunPositionWC;
}
},
/**
* The sun position in 2D world coordinates at the current scene time.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
sunPositionColumbusView: {
get: function() {
return this._sunPositionColumbusView;
}
},
/**
* A normalized vector to the sun in 3D world coordinates at the current scene time. Even in 2D or
* Columbus View mode, this returns the direction to the sun in the 3D scene.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
sunDirectionWC: {
get: function() {
return this._sunDirectionWC;
}
},
/**
* A normalized vector to the sun in eye coordinates at the current scene time. In 3D mode, this
* returns the actual vector from the camera position to the sun position. In 2D and Columbus View, it returns
* the vector from the equivalent 3D camera position to the position of the sun in the 3D scene.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
sunDirectionEC: {
get: function() {
return this._sunDirectionEC;
}
},
/**
* A normalized vector to the moon in eye coordinates at the current scene time. In 3D mode, this
* returns the actual vector from the camera position to the moon position. In 2D and Columbus View, it returns
* the vector from the equivalent 3D camera position to the position of the moon in the 3D scene.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
moonDirectionEC: {
get: function() {
return this._moonDirectionEC;
}
},
/**
* A normalized vector to the scene's light source in 3D world coordinates. Even in 2D or
* Columbus View mode, this returns the direction to the light in the 3D scene.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
lightDirectionWC: {
get: function() {
return this._lightDirectionWC;
}
},
/**
* A normalized vector to the scene's light source in eye coordinates. In 3D mode, this
* returns the actual vector from the camera position to the light. In 2D and Columbus View, it returns
* the vector from the equivalent 3D camera position in the 3D scene.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
lightDirectionEC: {
get: function() {
return this._lightDirectionEC;
}
},
/**
* The color of light emitted by the scene's light source. This is equivalent to the light
* color multiplied by the light intensity limited to a maximum luminance of 1.0 suitable
* for non-HDR lighting.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
lightColor: {
get: function() {
return this._lightColor;
}
},
/**
* The high dynamic range color of light emitted by the scene's light source. This is equivalent to
* the light color multiplied by the light intensity suitable for HDR lighting.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
lightColorHdr: {
get: function() {
return this._lightColorHdr;
}
},
/**
* The high bits of the camera position.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
encodedCameraPositionMCHigh: {
get: function() {
cleanEncodedCameraPositionMC(this);
return this._encodedCameraPositionMC.high;
}
},
/**
* The low bits of the camera position.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
encodedCameraPositionMCLow: {
get: function() {
cleanEncodedCameraPositionMC(this);
return this._encodedCameraPositionMC.low;
}
},
/**
* A 3x3 matrix that transforms from True Equator Mean Equinox (TEME) axes to the
* pseudo-fixed axes at the Scene's current time.
* @memberof UniformState.prototype
* @type {Matrix3}
*/
temeToPseudoFixedMatrix: {
get: function() {
return this._temeToPseudoFixed;
}
},
/**
* Gets the scaling factor for transforming from the canvas
* pixel space to canvas coordinate space.
* @memberof UniformState.prototype
* @type {number}
*/
pixelRatio: {
get: function() {
return this._pixelRatio;
}
},
/**
* A scalar used to mix a color with the fog color based on the distance to the camera.
* @memberof UniformState.prototype
* @type {number}
*/
fogDensity: {
get: function() {
return this._fogDensity;
}
},
/**
* A scalar used to mix a color with the fog color based on the distance to the camera.
* @memberof UniformState.prototype
* @type {number}
*/
fogVisualDensityScalar: {
get: function() {
return this._fogVisualDensityScalar;
}
},
/**
* A scalar used as a minimum value when brightening fog
* @memberof UniformState.prototype
* @type {number}
*/
fogMinimumBrightness: {
get: function() {
return this._fogMinimumBrightness;
}
},
/**
* A color shift to apply to the atmosphere color in HSB.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
atmosphereHsbShift: {
get: function() {
return this._atmosphereHsbShift;
}
},
/**
* The intensity of the light that is used for computing the atmosphere color
* @memberof UniformState.prototype
* @type {number}
*/
atmosphereLightIntensity: {
get: function() {
return this._atmosphereLightIntensity;
}
},
/**
* The Rayleigh scattering coefficient used in the atmospheric scattering equations for the sky atmosphere.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
atmosphereRayleighCoefficient: {
get: function() {
return this._atmosphereRayleighCoefficient;
}
},
/**
* The Rayleigh scale height used in the atmospheric scattering equations for the sky atmosphere, in meters.
* @memberof UniformState.prototype
* @type {number}
*/
atmosphereRayleighScaleHeight: {
get: function() {
return this._atmosphereRayleighScaleHeight;
}
},
/**
* The Mie scattering coefficient used in the atmospheric scattering equations for the sky atmosphere.
* @memberof UniformState.prototype
* @type {Cartesian3}
*/
atmosphereMieCoefficient: {
get: function() {
return this._atmosphereMieCoefficient;
}
},
/**
* The Mie scale height used in the atmospheric scattering equations for the sky atmosphere, in meters.
* @memberof UniformState.prototype
* @type {number}
*/
atmosphereMieScaleHeight: {
get: function() {
return this._atmosphereMieScaleHeight;
}
},
/**
* The anisotropy of the medium to consider for Mie scattering.
* @memberof UniformState.prototype
* @type {number}
*/
atmosphereMieAnisotropy: {
get: function() {
return this._atmosphereMieAnisotropy;
}
},
/**
* Which light source to use for dynamically lighting the atmosphere
*
* @memberof UniformState.prototype
* @type {DynamicAtmosphereLightingType}
*/
atmosphereDynamicLighting: {
get: function() {
return this._atmosphereDynamicLighting;
}
},
/**
* A scalar that represents the geometric tolerance per meter
* @memberof UniformState.prototype
* @type {number}
*/
geometricToleranceOverMeter: {
get: function() {
return this._geometricToleranceOverMeter;
}
},
/**
* @memberof UniformState.prototype
* @type {Pass}
*/
pass: {
get: function() {
return this._pass;
}
},
/**
* The current background color
* @memberof UniformState.prototype
* @type {Color}
*/
backgroundColor: {
get: function() {
return this._backgroundColor;
}
},
/**
* The look up texture used to find the BRDF for a material
* @memberof UniformState.prototype
* @type {Texture}
*/
brdfLut: {
get: function() {
return this._brdfLut;
}
},
/**
* The environment map of the scene
* @memberof UniformState.prototype
* @type {CubeMap}
*/
environmentMap: {
get: function() {
return this._environmentMap;
}
},
/**
* The spherical harmonic coefficients of the scene.
* @memberof UniformState.prototype
* @type {Cartesian3[]}
*/
sphericalHarmonicCoefficients: {
get: function() {
return this._sphericalHarmonicCoefficients;
}
},
/**
* The specular environment cube map of the scene.
* @memberof UniformState.prototype
* @type {Texture}
*/
specularEnvironmentMaps: {
get: function() {
return this._specularEnvironmentMaps;
}
},
/**
* The maximum level-of-detail of the specular environment cube map of the scene.
* @memberof UniformState.prototype
* @type {number}
*/
specularEnvironmentMapsMaximumLOD: {
get: function() {
return this._specularEnvironmentMapsMaximumLOD;
}
},
/**
* The splitter position to use when rendering with a splitter. This will be in pixel coordinates relative to the canvas.
* @memberof UniformState.prototype
* @type {number}
*/
splitPosition: {
get: function() {
return this._splitPosition;
}
},
/**
* The distance from the camera at which to disable the depth test of billboards, labels and points
* to, for example, prevent clipping against terrain. When set to zero, the depth test should always
* be applied. When less than zero, the depth test should never be applied.
*
* @memberof UniformState.prototype
* @type {number}
*/
minimumDisableDepthTestDistance: {
get: function() {
return this._minimumDisableDepthTestDistance;
}
},
/**
* The highlight color of unclassified 3D Tiles.
*
* @memberof UniformState.prototype
* @type {Color}
*/
invertClassificationColor: {
get: function() {
return this._invertClassificationColor;
}
},
/**
* Whether or not the current projection is orthographic in 3D.
*
* @memberOf UniformState.prototype
* @type {boolean}
*/
orthographicIn3D: {
get: function() {
return this._orthographicIn3D;
}
},
/**
* The current ellipsoid.
*
* @memberOf UniformState.prototype
* @type {Ellipsoid}
*/
ellipsoid: {
get: function() {
return this._ellipsoid ?? Ellipsoid_default.default;
}
}
});
function setView(uniformState, matrix) {
Matrix4_default.clone(matrix, uniformState._view);
Matrix4_default.getMatrix3(matrix, uniformState._viewRotation);
uniformState._view3DDirty = true;
uniformState._inverseView3DDirty = true;
uniformState._modelViewDirty = true;
uniformState._modelView3DDirty = true;
uniformState._modelViewRelativeToEyeDirty = true;
uniformState._inverseModelViewDirty = true;
uniformState._inverseModelView3DDirty = true;
uniformState._viewProjectionDirty = true;
uniformState._inverseViewProjectionDirty = true;
uniformState._modelViewProjectionDirty = true;
uniformState._modelViewProjectionRelativeToEyeDirty = true;
uniformState._modelViewInfiniteProjectionDirty = true;
uniformState._normalDirty = true;
uniformState._inverseNormalDirty = true;
uniformState._normal3DDirty = true;
uniformState._inverseNormal3DDirty = true;
}
function setInverseView(uniformState, matrix) {
Matrix4_default.clone(matrix, uniformState._inverseView);
Matrix4_default.getMatrix3(matrix, uniformState._inverseViewRotation);
}
function setProjection(uniformState, matrix) {
Matrix4_default.clone(matrix, uniformState._projection);
uniformState._inverseProjectionDirty = true;
uniformState._viewProjectionDirty = true;
uniformState._inverseViewProjectionDirty = true;
uniformState._modelViewProjectionDirty = true;
uniformState._modelViewProjectionRelativeToEyeDirty = true;
}
function setInfiniteProjection(uniformState, matrix) {
Matrix4_default.clone(matrix, uniformState._infiniteProjection);
uniformState._modelViewInfiniteProjectionDirty = true;
}
var surfacePositionScratch = new Cartesian3_default();
var enuTransformScratch = new Matrix4_default();
function setCamera(uniformState, camera) {
Cartesian3_default.clone(camera.positionWC, uniformState._cameraPosition);
Cartesian3_default.clone(camera.directionWC, uniformState._cameraDirection);
Cartesian3_default.clone(camera.rightWC, uniformState._cameraRight);
Cartesian3_default.clone(camera.upWC, uniformState._cameraUp);
const ellipsoid = uniformState._ellipsoid;
let surfacePosition;
const positionCartographic = camera.positionCartographic;
if (!defined_default(positionCartographic)) {
uniformState._eyeHeight = -ellipsoid.maximumRadius;
if (Cartesian3_default.magnitude(camera.positionWC) > 0) {
uniformState._eyeEllipsoidNormalEC = Cartesian3_default.normalize(
camera.positionWC,
uniformState._eyeEllipsoidNormalEC
);
}
surfacePosition = ellipsoid.scaleToGeodeticSurface(
camera.positionWC,
surfacePositionScratch
);
} else {
uniformState._eyeHeight = positionCartographic.height;
uniformState._eyeEllipsoidNormalEC = ellipsoid.geodeticSurfaceNormalCartographic(
positionCartographic,
uniformState._eyeEllipsoidNormalEC
);
surfacePosition = Cartesian3_default.fromRadians(
positionCartographic.longitude,
positionCartographic.latitude,
0,
ellipsoid,
surfacePositionScratch
);
}
uniformState._encodedCameraPositionMCDirty = true;
if (!defined_default(surfacePosition)) {
return;
}
uniformState._eyeEllipsoidNormalEC = Matrix3_default.multiplyByVector(
uniformState._viewRotation,
uniformState._eyeEllipsoidNormalEC,
uniformState._eyeEllipsoidNormalEC
);
const enuToWorld = Transforms_default.eastNorthUpToFixedFrame(
surfacePosition,
ellipsoid,
enuTransformScratch
);
uniformState._enuToModel = Matrix4_default.multiplyTransformation(
uniformState.inverseModel,
enuToWorld,
uniformState._enuToModel
);
uniformState._modelToEnu = Matrix4_default.inverseTransformation(
uniformState._enuToModel,
uniformState._modelToEnu
);
if (!Math_default.equalsEpsilon(
ellipsoid._radii.x,
ellipsoid._radii.y,
Math_default.EPSILON15
)) {
return;
}
uniformState._eyeEllipsoidCurvature = ellipsoid.getLocalCurvature(
surfacePosition,
uniformState._eyeEllipsoidCurvature
);
}
var transformMatrix = new Matrix3_default();
var sunCartographicScratch = new Cartographic_default();
function setSunAndMoonDirections(uniformState, frameState) {
Transforms_default.computeIcrfToCentralBodyFixedMatrix(
frameState.time,
transformMatrix
);
let position = Simon1994PlanetaryPositions_default.computeSunPositionInEarthInertialFrame(
frameState.time,
uniformState._sunPositionWC
);
Matrix3_default.multiplyByVector(transformMatrix, position, position);
Cartesian3_default.normalize(position, uniformState._sunDirectionWC);
position = Matrix3_default.multiplyByVector(
uniformState.viewRotation3D,
position,
uniformState._sunDirectionEC
);
Cartesian3_default.normalize(position, position);
position = Simon1994PlanetaryPositions_default.computeMoonPositionInEarthInertialFrame(
frameState.time,
uniformState._moonDirectionEC
);
Matrix3_default.multiplyByVector(transformMatrix, position, position);
Matrix3_default.multiplyByVector(uniformState.viewRotation3D, position, position);
Cartesian3_default.normalize(position, position);
const projection = frameState.mapProjection;
const ellipsoid = projection.ellipsoid;
const sunCartographic = ellipsoid.cartesianToCartographic(
uniformState._sunPositionWC,
sunCartographicScratch
);
projection.project(sunCartographic, uniformState._sunPositionColumbusView);
}
UniformState.prototype.updateCamera = function(camera) {
setView(this, camera.viewMatrix);
setInverseView(this, camera.inverseViewMatrix);
setCamera(this, camera);
this._entireFrustum.x = camera.frustum.near;
this._entireFrustum.y = camera.frustum.far;
this.updateFrustum(camera.frustum);
this._orthographicIn3D = this._mode !== SceneMode_default.SCENE2D && camera.frustum instanceof OrthographicFrustum_default;
};
UniformState.prototype.updateFrustum = function(frustum) {
setProjection(this, frustum.projectionMatrix);
if (defined_default(frustum.infiniteProjectionMatrix)) {
setInfiniteProjection(this, frustum.infiniteProjectionMatrix);
}
this._currentFrustum.x = frustum.near;
this._currentFrustum.y = frustum.far;
this._farDepthFromNearPlusOne = frustum.far - frustum.near + 1;
this._log2FarDepthFromNearPlusOne = Math_default.log2(
this._farDepthFromNearPlusOne
);
this._oneOverLog2FarDepthFromNearPlusOne = 1 / this._log2FarDepthFromNearPlusOne;
const offCenterFrustum = frustum.offCenterFrustum;
if (defined_default(offCenterFrustum)) {
frustum = offCenterFrustum;
}
this._frustumPlanes.x = frustum.top;
this._frustumPlanes.y = frustum.bottom;
this._frustumPlanes.z = frustum.left;
this._frustumPlanes.w = frustum.right;
};
UniformState.prototype.updatePass = function(pass) {
this._pass = pass;
};
var EMPTY_ARRAY = [];
var defaultLight = new SunLight_default();
UniformState.prototype.update = function(frameState) {
this._mode = frameState.mode;
this._mapProjection = frameState.mapProjection;
this._ellipsoid = frameState.mapProjection.ellipsoid;
this._pixelRatio = frameState.pixelRatio;
const camera = frameState.camera;
this.updateCamera(camera);
if (frameState.mode === SceneMode_default.SCENE2D) {
this._frustum2DWidth = camera.frustum.right - camera.frustum.left;
this._eyeHeight2D.x = this._frustum2DWidth * 0.5;
this._eyeHeight2D.y = this._eyeHeight2D.x * this._eyeHeight2D.x;
} else {
this._frustum2DWidth = 0;
this._eyeHeight2D.x = 0;
this._eyeHeight2D.y = 0;
}
setSunAndMoonDirections(this, frameState);
const light = frameState.light ?? defaultLight;
if (light instanceof SunLight_default) {
this._lightDirectionWC = Cartesian3_default.clone(
this._sunDirectionWC,
this._lightDirectionWC
);
this._lightDirectionEC = Cartesian3_default.clone(
this._sunDirectionEC,
this._lightDirectionEC
);
} else {
this._lightDirectionWC = Cartesian3_default.normalize(
Cartesian3_default.negate(light.direction, this._lightDirectionWC),
this._lightDirectionWC
);
this._lightDirectionEC = Matrix3_default.multiplyByVector(
this.viewRotation3D,
this._lightDirectionWC,
this._lightDirectionEC
);
}
const lightColor = light.color;
let lightColorHdr = Cartesian3_default.fromElements(
lightColor.red,
lightColor.green,
lightColor.blue,
this._lightColorHdr
);
lightColorHdr = Cartesian3_default.multiplyByScalar(
lightColorHdr,
light.intensity,
lightColorHdr
);
const maximumComponent = Cartesian3_default.maximumComponent(lightColorHdr);
if (maximumComponent > 1) {
Cartesian3_default.divideByScalar(
lightColorHdr,
maximumComponent,
this._lightColor
);
} else {
Cartesian3_default.clone(lightColorHdr, this._lightColor);
}
const brdfLutGenerator = frameState.brdfLutGenerator;
const brdfLut = defined_default(brdfLutGenerator) ? brdfLutGenerator.colorTexture : void 0;
this._brdfLut = brdfLut;
this._environmentMap = frameState.environmentMap ?? frameState.context.defaultCubeMap;
this._sphericalHarmonicCoefficients = frameState.sphericalHarmonicCoefficients ?? EMPTY_ARRAY;
this._specularEnvironmentMaps = frameState.specularEnvironmentMaps;
this._specularEnvironmentMapsMaximumLOD = frameState.specularEnvironmentMapsMaximumLOD;
this._fogDensity = frameState.fog.density;
this._fogVisualDensityScalar = frameState.fog.visualDensityScalar;
this._fogMinimumBrightness = frameState.fog.minimumBrightness;
const atmosphere = frameState.atmosphere;
if (defined_default(atmosphere)) {
this._atmosphereHsbShift = Cartesian3_default.fromElements(
atmosphere.hueShift,
atmosphere.saturationShift,
atmosphere.brightnessShift,
this._atmosphereHsbShift
);
this._atmosphereLightIntensity = atmosphere.lightIntensity;
this._atmosphereRayleighCoefficient = Cartesian3_default.clone(
atmosphere.rayleighCoefficient,
this._atmosphereRayleighCoefficient
);
this._atmosphereRayleighScaleHeight = atmosphere.rayleighScaleHeight;
this._atmosphereMieCoefficient = Cartesian3_default.clone(
atmosphere.mieCoefficient,
this._atmosphereMieCoefficient
);
this._atmosphereMieScaleHeight = atmosphere.mieScaleHeight;
this._atmosphereMieAnisotropy = atmosphere.mieAnisotropy;
this._atmosphereDynamicLighting = atmosphere.dynamicLighting;
}
this._invertClassificationColor = frameState.invertClassificationColor;
this._frameState = frameState;
this._temeToPseudoFixed = Transforms_default.computeTemeToPseudoFixedMatrix(
frameState.time,
this._temeToPseudoFixed
);
this._splitPosition = frameState.splitPosition * frameState.context.drawingBufferWidth;
const fov = camera.frustum.fov;
const viewport = this._viewport;
let pixelSizePerMeter;
if (defined_default(fov)) {
if (viewport.height > viewport.width) {
pixelSizePerMeter = Math.tan(0.5 * fov) * 2 / viewport.height;
} else {
pixelSizePerMeter = Math.tan(0.5 * fov) * 2 / viewport.width;
}
} else {
pixelSizePerMeter = 1 / Math.max(viewport.width, viewport.height);
}
this._geometricToleranceOverMeter = pixelSizePerMeter * frameState.maximumScreenSpaceError;
Color_default.clone(frameState.backgroundColor, this._backgroundColor);
this._minimumDisableDepthTestDistance = frameState.minimumDisableDepthTestDistance;
this._minimumDisableDepthTestDistance *= this._minimumDisableDepthTestDistance;
if (this._minimumDisableDepthTestDistance === Number.POSITIVE_INFINITY) {
this._minimumDisableDepthTestDistance = -1;
}
};
function cleanViewport(uniformState) {
if (uniformState._viewportDirty) {
const v3 = uniformState._viewport;
Matrix4_default.computeOrthographicOffCenter(
v3.x,
v3.x + v3.width,
v3.y,
v3.y + v3.height,
0,
1,
uniformState._viewportOrthographicMatrix
);
Matrix4_default.computeViewportTransformation(
v3,
0,
1,
uniformState._viewportTransformation
);
uniformState._viewportDirty = false;
}
}
function cleanInverseProjection(uniformState) {
if (uniformState._inverseProjectionDirty) {
uniformState._inverseProjectionDirty = false;
if (uniformState._mode !== SceneMode_default.SCENE2D && uniformState._mode !== SceneMode_default.MORPHING && !uniformState._orthographicIn3D) {
Matrix4_default.inverse(
uniformState._projection,
uniformState._inverseProjection
);
} else {
Matrix4_default.clone(Matrix4_default.ZERO, uniformState._inverseProjection);
}
}
}
function cleanModelView(uniformState) {
if (uniformState._modelViewDirty) {
uniformState._modelViewDirty = false;
Matrix4_default.multiplyTransformation(
uniformState._view,
uniformState._model,
uniformState._modelView
);
}
}
function cleanModelView3D(uniformState) {
if (uniformState._modelView3DDirty) {
uniformState._modelView3DDirty = false;
Matrix4_default.multiplyTransformation(
uniformState.view3D,
uniformState._model,
uniformState._modelView3D
);
}
}
function cleanInverseModelView(uniformState) {
if (uniformState._inverseModelViewDirty) {
uniformState._inverseModelViewDirty = false;
Matrix4_default.inverse(uniformState.modelView, uniformState._inverseModelView);
}
}
function cleanInverseModelView3D(uniformState) {
if (uniformState._inverseModelView3DDirty) {
uniformState._inverseModelView3DDirty = false;
Matrix4_default.inverse(uniformState.modelView3D, uniformState._inverseModelView3D);
}
}
function cleanViewProjection(uniformState) {
if (uniformState._viewProjectionDirty) {
uniformState._viewProjectionDirty = false;
Matrix4_default.multiply(
uniformState._projection,
uniformState._view,
uniformState._viewProjection
);
}
}
function cleanInverseViewProjection(uniformState) {
if (uniformState._inverseViewProjectionDirty) {
uniformState._inverseViewProjectionDirty = false;
Matrix4_default.inverse(
uniformState.viewProjection,
uniformState._inverseViewProjection
);
}
}
function cleanModelViewProjection(uniformState) {
if (uniformState._modelViewProjectionDirty) {
uniformState._modelViewProjectionDirty = false;
Matrix4_default.multiply(
uniformState._projection,
uniformState.modelView,
uniformState._modelViewProjection
);
}
}
function cleanModelViewRelativeToEye(uniformState) {
if (uniformState._modelViewRelativeToEyeDirty) {
uniformState._modelViewRelativeToEyeDirty = false;
const mv = uniformState.modelView;
const mvRte = uniformState._modelViewRelativeToEye;
mvRte[0] = mv[0];
mvRte[1] = mv[1];
mvRte[2] = mv[2];
mvRte[3] = mv[3];
mvRte[4] = mv[4];
mvRte[5] = mv[5];
mvRte[6] = mv[6];
mvRte[7] = mv[7];
mvRte[8] = mv[8];
mvRte[9] = mv[9];
mvRte[10] = mv[10];
mvRte[11] = mv[11];
mvRte[12] = 0;
mvRte[13] = 0;
mvRte[14] = 0;
mvRte[15] = mv[15];
}
}
function cleanInverseModelViewProjection(uniformState) {
if (uniformState._inverseModelViewProjectionDirty) {
uniformState._inverseModelViewProjectionDirty = false;
Matrix4_default.inverse(
uniformState.modelViewProjection,
uniformState._inverseModelViewProjection
);
}
}
function cleanModelViewProjectionRelativeToEye(uniformState) {
if (uniformState._modelViewProjectionRelativeToEyeDirty) {
uniformState._modelViewProjectionRelativeToEyeDirty = false;
Matrix4_default.multiply(
uniformState._projection,
uniformState.modelViewRelativeToEye,
uniformState._modelViewProjectionRelativeToEye
);
}
}
function cleanModelViewInfiniteProjection(uniformState) {
if (uniformState._modelViewInfiniteProjectionDirty) {
uniformState._modelViewInfiniteProjectionDirty = false;
Matrix4_default.multiply(
uniformState._infiniteProjection,
uniformState.modelView,
uniformState._modelViewInfiniteProjection
);
}
}
function cleanNormal(uniformState) {
if (uniformState._normalDirty) {
uniformState._normalDirty = false;
const m = uniformState._normal;
Matrix4_default.getMatrix3(uniformState.inverseModelView, m);
Matrix3_default.transpose(m, m);
}
}
function cleanNormal3D(uniformState) {
if (uniformState._normal3DDirty) {
uniformState._normal3DDirty = false;
const m = uniformState._normal3D;
Matrix4_default.getMatrix3(uniformState.inverseModelView3D, m);
Matrix3_default.transpose(m, m);
}
}
function cleanInverseNormal(uniformState) {
if (uniformState._inverseNormalDirty) {
uniformState._inverseNormalDirty = false;
const m = uniformState._inverseNormal;
Matrix4_default.getMatrix3(uniformState.modelView, m);
Matrix3_default.transpose(m, m);
}
}
function cleanInverseNormal3D(uniformState) {
if (uniformState._inverseNormal3DDirty) {
uniformState._inverseNormal3DDirty = false;
const m = uniformState._inverseNormal3D;
Matrix4_default.getMatrix3(uniformState.modelView3D, m);
Matrix3_default.transpose(m, m);
}
}
var cameraPositionMC = new Cartesian3_default();
function cleanEncodedCameraPositionMC(uniformState) {
if (uniformState._encodedCameraPositionMCDirty) {
uniformState._encodedCameraPositionMCDirty = false;
Matrix4_default.multiplyByPoint(
uniformState.inverseModel,
uniformState._cameraPosition,
cameraPositionMC
);
EncodedCartesian3_default.fromCartesian(
cameraPositionMC,
uniformState._encodedCameraPositionMC
);
}
}
var view2Dto3DPScratch = new Cartesian3_default();
var view2Dto3DRScratch = new Cartesian3_default();
var view2Dto3DUScratch = new Cartesian3_default();
var view2Dto3DDScratch = new Cartesian3_default();
var view2Dto3DCartographicScratch = new Cartographic_default();
var view2Dto3DCartesian3Scratch = new Cartesian3_default();
var view2Dto3DMatrix4Scratch = new Matrix4_default();
function view2Dto3D(position2D, direction2D, right2D, up2D, frustum2DWidth, mode2, projection, result) {
const p = view2Dto3DPScratch;
p.x = position2D.y;
p.y = position2D.z;
p.z = position2D.x;
const r = view2Dto3DRScratch;
r.x = right2D.y;
r.y = right2D.z;
r.z = right2D.x;
const u3 = view2Dto3DUScratch;
u3.x = up2D.y;
u3.y = up2D.z;
u3.z = up2D.x;
const d = view2Dto3DDScratch;
d.x = direction2D.y;
d.y = direction2D.z;
d.z = direction2D.x;
if (mode2 === SceneMode_default.SCENE2D) {
p.z = frustum2DWidth * 0.5;
}
const cartographic2 = projection.unproject(p, view2Dto3DCartographicScratch);
cartographic2.longitude = Math_default.clamp(
cartographic2.longitude,
-Math.PI,
Math.PI
);
cartographic2.latitude = Math_default.clamp(
cartographic2.latitude,
-Math_default.PI_OVER_TWO,
Math_default.PI_OVER_TWO
);
const ellipsoid = projection.ellipsoid;
const position3D = ellipsoid.cartographicToCartesian(
cartographic2,
view2Dto3DCartesian3Scratch
);
const enuToFixed = Transforms_default.eastNorthUpToFixedFrame(
position3D,
ellipsoid,
view2Dto3DMatrix4Scratch
);
Matrix4_default.multiplyByPointAsVector(enuToFixed, r, r);
Matrix4_default.multiplyByPointAsVector(enuToFixed, u3, u3);
Matrix4_default.multiplyByPointAsVector(enuToFixed, d, d);
if (!defined_default(result)) {
result = new Matrix4_default();
}
result[0] = r.x;
result[1] = u3.x;
result[2] = -d.x;
result[3] = 0;
result[4] = r.y;
result[5] = u3.y;
result[6] = -d.y;
result[7] = 0;
result[8] = r.z;
result[9] = u3.z;
result[10] = -d.z;
result[11] = 0;
result[12] = -Cartesian3_default.dot(r, position3D);
result[13] = -Cartesian3_default.dot(u3, position3D);
result[14] = Cartesian3_default.dot(d, position3D);
result[15] = 1;
return result;
}
function updateView3D(that) {
if (that._view3DDirty) {
if (that._mode === SceneMode_default.SCENE3D) {
Matrix4_default.clone(that._view, that._view3D);
} else {
view2Dto3D(
that._cameraPosition,
that._cameraDirection,
that._cameraRight,
that._cameraUp,
that._frustum2DWidth,
that._mode,
that._mapProjection,
that._view3D
);
}
Matrix4_default.getMatrix3(that._view3D, that._viewRotation3D);
that._view3DDirty = false;
}
}
function updateInverseView3D(that) {
if (that._inverseView3DDirty) {
Matrix4_default.inverseTransformation(that.view3D, that._inverseView3D);
Matrix4_default.getMatrix3(that._inverseView3D, that._inverseViewRotation3D);
that._inverseView3DDirty = false;
}
}
var UniformState_default = UniformState;
// packages/engine/Source/Renderer/Context.js
function Context(canvas, options) {
Check_default.defined("canvas", canvas);
const {
getWebGLStub,
requestWebgl1,
webgl: webglOptions = {},
allowTextureFilterAnisotropic = true
} = options ?? {};
webglOptions.alpha = webglOptions.alpha ?? false;
webglOptions.stencil = webglOptions.stencil ?? true;
webglOptions.powerPreference = webglOptions.powerPreference ?? "high-performance";
const glContext = defined_default(getWebGLStub) ? getWebGLStub(canvas, webglOptions) : getWebGLContext(canvas, webglOptions, requestWebgl1);
const webgl2Supported = typeof WebGL2RenderingContext !== "undefined";
const webgl2 = webgl2Supported && glContext instanceof WebGL2RenderingContext;
this._canvas = canvas;
this._originalGLContext = glContext;
this._gl = glContext;
this._webgl2 = webgl2;
this._id = createGuid_default();
this.validateFramebuffer = false;
this.validateShaderProgram = false;
this.logShaderCompilation = false;
this._throwOnWebGLError = false;
this._shaderCache = new ShaderCache_default(this);
this._textureCache = new TextureCache_default();
const gl = glContext;
this._stencilBits = gl.getParameter(gl.STENCIL_BITS);
ContextLimits_default._maximumCombinedTextureImageUnits = gl.getParameter(
gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS
);
ContextLimits_default._maximumCubeMapSize = gl.getParameter(
gl.MAX_CUBE_MAP_TEXTURE_SIZE
);
ContextLimits_default._maximumFragmentUniformVectors = gl.getParameter(
gl.MAX_FRAGMENT_UNIFORM_VECTORS
);
ContextLimits_default._maximumTextureImageUnits = gl.getParameter(
gl.MAX_TEXTURE_IMAGE_UNITS
);
ContextLimits_default._maximumRenderbufferSize = gl.getParameter(
gl.MAX_RENDERBUFFER_SIZE
);
ContextLimits_default._maximumTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
ContextLimits_default._maximumVaryingVectors = gl.getParameter(
gl.MAX_VARYING_VECTORS
);
ContextLimits_default._maximumVertexAttributes = gl.getParameter(
gl.MAX_VERTEX_ATTRIBS
);
ContextLimits_default._maximumVertexTextureImageUnits = gl.getParameter(
gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS
);
ContextLimits_default._maximumVertexUniformVectors = gl.getParameter(
gl.MAX_VERTEX_UNIFORM_VECTORS
);
ContextLimits_default._maximumSamples = this._webgl2 ? gl.getParameter(gl.MAX_SAMPLES) : 0;
const aliasedLineWidthRange = gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE);
ContextLimits_default._minimumAliasedLineWidth = aliasedLineWidthRange[0];
ContextLimits_default._maximumAliasedLineWidth = aliasedLineWidthRange[1];
const aliasedPointSizeRange = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE);
ContextLimits_default._minimumAliasedPointSize = aliasedPointSizeRange[0];
ContextLimits_default._maximumAliasedPointSize = aliasedPointSizeRange[1];
const maximumViewportDimensions = gl.getParameter(gl.MAX_VIEWPORT_DIMS);
ContextLimits_default._maximumViewportWidth = maximumViewportDimensions[0];
ContextLimits_default._maximumViewportHeight = maximumViewportDimensions[1];
const highpFloat = gl.getShaderPrecisionFormat(
gl.FRAGMENT_SHADER,
gl.HIGH_FLOAT
);
ContextLimits_default._highpFloatSupported = highpFloat.precision !== 0;
const highpInt = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT);
ContextLimits_default._highpIntSupported = highpInt.rangeMax !== 0;
this._antialias = gl.getContextAttributes().antialias;
this._standardDerivatives = !!getExtension(gl, ["OES_standard_derivatives"]);
this._blendMinmax = !!getExtension(gl, ["EXT_blend_minmax"]);
this._elementIndexUint = !!getExtension(gl, ["OES_element_index_uint"]);
this._depthTexture = !!getExtension(gl, [
"WEBGL_depth_texture",
"WEBKIT_WEBGL_depth_texture"
]);
this._fragDepth = !!getExtension(gl, ["EXT_frag_depth"]);
this._debugShaders = getExtension(gl, ["WEBGL_debug_shaders"]);
this._textureFloat = !!getExtension(gl, ["OES_texture_float"]);
this._textureHalfFloat = !!getExtension(gl, ["OES_texture_half_float"]);
this._textureFloatLinear = !!getExtension(gl, ["OES_texture_float_linear"]);
this._textureHalfFloatLinear = !!getExtension(gl, [
"OES_texture_half_float_linear"
]);
this._supportsTextureLod = !!getExtension(gl, ["EXT_shader_texture_lod"]);
this._colorBufferFloat = !!getExtension(gl, [
"EXT_color_buffer_float",
"WEBGL_color_buffer_float"
]);
this._floatBlend = !!getExtension(gl, ["EXT_float_blend"]);
this._colorBufferHalfFloat = !!getExtension(gl, [
"EXT_color_buffer_half_float"
]);
this._s3tc = !!getExtension(gl, [
"WEBGL_compressed_texture_s3tc",
"MOZ_WEBGL_compressed_texture_s3tc",
"WEBKIT_WEBGL_compressed_texture_s3tc"
]);
this._pvrtc = !!getExtension(gl, [
"WEBGL_compressed_texture_pvrtc",
"WEBKIT_WEBGL_compressed_texture_pvrtc"
]);
this._astc = !!getExtension(gl, ["WEBGL_compressed_texture_astc"]);
this._etc = !!getExtension(gl, ["WEBG_compressed_texture_etc"]);
this._etc1 = !!getExtension(gl, ["WEBGL_compressed_texture_etc1"]);
this._bc7 = !!getExtension(gl, ["EXT_texture_compression_bptc"]);
loadKTX2_default.setKTX2SupportedFormats(
this._s3tc,
this._pvrtc,
this._astc,
this._etc,
this._etc1,
this._bc7
);
const textureFilterAnisotropic = allowTextureFilterAnisotropic ? getExtension(gl, [
"EXT_texture_filter_anisotropic",
"WEBKIT_EXT_texture_filter_anisotropic"
]) : void 0;
this._textureFilterAnisotropic = textureFilterAnisotropic;
ContextLimits_default._maximumTextureFilterAnisotropy = defined_default(
textureFilterAnisotropic
) ? gl.getParameter(textureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 1;
let glCreateVertexArray;
let glBindVertexArray;
let glDeleteVertexArray;
let glDrawElementsInstanced;
let glDrawArraysInstanced;
let glVertexAttribDivisor;
let glDrawBuffers;
let vertexArrayObject;
let instancedArrays;
let drawBuffers;
if (webgl2) {
const that = this;
glCreateVertexArray = function() {
return that._gl.createVertexArray();
};
glBindVertexArray = function(vao) {
that._gl.bindVertexArray(vao);
};
glDeleteVertexArray = function(vao) {
that._gl.deleteVertexArray(vao);
};
glDrawElementsInstanced = function(mode2, count, type, offset, instanceCount) {
gl.drawElementsInstanced(mode2, count, type, offset, instanceCount);
};
glDrawArraysInstanced = function(mode2, first, count, instanceCount) {
gl.drawArraysInstanced(mode2, first, count, instanceCount);
};
glVertexAttribDivisor = function(index, divisor) {
gl.vertexAttribDivisor(index, divisor);
};
glDrawBuffers = function(buffers) {
gl.drawBuffers(buffers);
};
} else {
vertexArrayObject = getExtension(gl, ["OES_vertex_array_object"]);
if (defined_default(vertexArrayObject)) {
glCreateVertexArray = function() {
return vertexArrayObject.createVertexArrayOES();
};
glBindVertexArray = function(vertexArray) {
vertexArrayObject.bindVertexArrayOES(vertexArray);
};
glDeleteVertexArray = function(vertexArray) {
vertexArrayObject.deleteVertexArrayOES(vertexArray);
};
}
instancedArrays = getExtension(gl, ["ANGLE_instanced_arrays"]);
if (defined_default(instancedArrays)) {
glDrawElementsInstanced = function(mode2, count, type, offset, instanceCount) {
instancedArrays.drawElementsInstancedANGLE(
mode2,
count,
type,
offset,
instanceCount
);
};
glDrawArraysInstanced = function(mode2, first, count, instanceCount) {
instancedArrays.drawArraysInstancedANGLE(
mode2,
first,
count,
instanceCount
);
};
glVertexAttribDivisor = function(index, divisor) {
instancedArrays.vertexAttribDivisorANGLE(index, divisor);
};
}
drawBuffers = getExtension(gl, ["WEBGL_draw_buffers"]);
if (defined_default(drawBuffers)) {
glDrawBuffers = function(buffers) {
drawBuffers.drawBuffersWEBGL(buffers);
};
}
}
this.glCreateVertexArray = glCreateVertexArray;
this.glBindVertexArray = glBindVertexArray;
this.glDeleteVertexArray = glDeleteVertexArray;
this.glDrawElementsInstanced = glDrawElementsInstanced;
this.glDrawArraysInstanced = glDrawArraysInstanced;
this.glVertexAttribDivisor = glVertexAttribDivisor;
this.glDrawBuffers = glDrawBuffers;
this._vertexArrayObject = !!vertexArrayObject;
this._instancedArrays = !!instancedArrays;
this._drawBuffers = !!drawBuffers;
ContextLimits_default._maximumDrawBuffers = this.drawBuffers ? gl.getParameter(WebGLConstants_default.MAX_DRAW_BUFFERS) : 1;
ContextLimits_default._maximumColorAttachments = this.drawBuffers ? gl.getParameter(WebGLConstants_default.MAX_COLOR_ATTACHMENTS) : 1;
this._clearColor = new Color_default(0, 0, 0, 0);
this._clearDepth = 1;
this._clearStencil = 0;
const us = new UniformState_default();
const ps = new PassState_default(this);
const rs = RenderState_default.fromCache();
this._defaultPassState = ps;
this._defaultRenderState = rs;
this._defaultTexture = void 0;
this._defaultEmissiveTexture = void 0;
this._defaultNormalTexture = void 0;
this._defaultCubeMap = void 0;
this._us = us;
this._currentRenderState = rs;
this._currentPassState = ps;
this._currentFramebuffer = void 0;
this._maxFrameTextureUnitIndex = 0;
this._vertexAttribDivisors = [];
this._previousDrawInstanced = false;
for (let i = 0; i < ContextLimits_default._maximumVertexAttributes; i++) {
this._vertexAttribDivisors.push(0);
}
this._pickObjects = {};
this._nextPickColor = new Uint32Array(1);
this.options = {
getWebGLStub,
requestWebgl1,
webgl: webglOptions,
allowTextureFilterAnisotropic
};
this.cache = {};
RenderState_default.apply(gl, rs, ps);
}
function getWebGLContext(canvas, webglOptions, requestWebgl1) {
if (typeof WebGLRenderingContext === "undefined") {
throw new RuntimeError_default(
"The browser does not support WebGL. Visit http://get.webgl.org."
);
}
const webgl2Supported = typeof WebGL2RenderingContext !== "undefined";
if (!requestWebgl1 && !webgl2Supported) {
requestWebgl1 = true;
}
const contextType = requestWebgl1 ? "webgl" : "webgl2";
const glContext = canvas.getContext(contextType, webglOptions);
if (!defined_default(glContext)) {
throw new RuntimeError_default(
"The browser supports WebGL, but initialization failed."
);
}
return glContext;
}
function errorToString(gl, error) {
let message = "WebGL Error: ";
switch (error) {
case gl.INVALID_ENUM:
message += "INVALID_ENUM";
break;
case gl.INVALID_VALUE:
message += "INVALID_VALUE";
break;
case gl.INVALID_OPERATION:
message += "INVALID_OPERATION";
break;
case gl.OUT_OF_MEMORY:
message += "OUT_OF_MEMORY";
break;
case gl.CONTEXT_LOST_WEBGL:
message += "CONTEXT_LOST_WEBGL lost";
break;
default:
message += `Unknown (${error})`;
}
return message;
}
function createErrorMessage(gl, glFunc, glFuncArguments, error) {
let message = `${errorToString(gl, error)}: ${glFunc.name}(`;
for (let i = 0; i < glFuncArguments.length; ++i) {
if (i !== 0) {
message += ", ";
}
message += glFuncArguments[i];
}
message += ");";
return message;
}
function throwOnError(gl, glFunc, glFuncArguments) {
const error = gl.getError();
if (error !== gl.NO_ERROR) {
throw new RuntimeError_default(
createErrorMessage(gl, glFunc, glFuncArguments, error)
);
}
}
function makeGetterSetter(gl, propertyName, logFunction) {
return {
get: function() {
const value = gl[propertyName];
logFunction(gl, `get: ${propertyName}`, value);
return gl[propertyName];
},
set: function(value) {
gl[propertyName] = value;
logFunction(gl, `set: ${propertyName}`, value);
}
};
}
function wrapGL(gl, logFunction) {
if (!defined_default(logFunction)) {
return gl;
}
function wrapFunction2(property) {
return function() {
const result = property.apply(gl, arguments);
logFunction(gl, property, arguments);
return result;
};
}
const glWrapper = {};
for (const propertyName in gl) {
const property = gl[propertyName];
if (property instanceof Function) {
glWrapper[propertyName] = wrapFunction2(property);
} else {
Object.defineProperty(
glWrapper,
propertyName,
makeGetterSetter(gl, propertyName, logFunction)
);
}
}
return glWrapper;
}
function getExtension(gl, names) {
const length2 = names.length;
for (let i = 0; i < length2; ++i) {
const extension = gl.getExtension(names[i]);
if (extension) {
return extension;
}
}
return void 0;
}
var defaultFramebufferMarker = {};
Object.defineProperties(Context.prototype, {
id: {
get: function() {
return this._id;
}
},
webgl2: {
get: function() {
return this._webgl2;
}
},
canvas: {
get: function() {
return this._canvas;
}
},
shaderCache: {
get: function() {
return this._shaderCache;
}
},
textureCache: {
get: function() {
return this._textureCache;
}
},
uniformState: {
get: function() {
return this._us;
}
},
/**
* The number of stencil bits per pixel in the default bound framebuffer. The minimum is eight bits.
* @memberof Context.prototype
* @type {number}
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with STENCIL_BITS.
*/
stencilBits: {
get: function() {
return this._stencilBits;
}
},
/**
* true if the WebGL context supports stencil buffers.
* Stencil buffers are not supported by all systems.
* @memberof Context.prototype
* @type {boolean}
*/
stencilBuffer: {
get: function() {
return this._stencilBits >= 8;
}
},
/**
* true if the WebGL context supports antialiasing. By default
* antialiasing is requested, but it is not supported by all systems.
* @memberof Context.prototype
* @type {boolean}
*/
antialias: {
get: function() {
return this._antialias;
}
},
/**
* true if the WebGL context supports multisample antialiasing. Requires
* WebGL2.
* @memberof Context.prototype
* @type {boolean}
*/
msaa: {
get: function() {
return this._webgl2;
}
},
/**
* true if the OES_standard_derivatives extension is supported. This
* extension provides access to dFdx, dFdy, and fwidth
* functions from GLSL. A shader using these functions still needs to explicitly enable the
* extension with #extension GL_OES_standard_derivatives : enable.
* @memberof Context.prototype
* @type {boolean}
* @see {@link http://www.khronos.org/registry/gles/extensions/OES/OES_standard_derivatives.txt|OES_standard_derivatives}
*/
standardDerivatives: {
get: function() {
return this._standardDerivatives || this._webgl2;
}
},
/**
* true if the EXT_float_blend extension is supported. This
* extension enables blending with 32-bit float values.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/EXT_float_blend/}
*/
floatBlend: {
get: function() {
return this._floatBlend;
}
},
/**
* true if the EXT_blend_minmax extension is supported. This
* extension extends blending capabilities by adding two new blend equations:
* the minimum or maximum color components of the source and destination colors.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/EXT_blend_minmax/}
*/
blendMinmax: {
get: function() {
return this._blendMinmax || this._webgl2;
}
},
/**
* true if the OES_element_index_uint extension is supported. This
* extension allows the use of unsigned int indices, which can improve performance by
* eliminating batch breaking caused by unsigned short indices.
* @memberof Context.prototype
* @type {boolean}
* @see {@link http://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/|OES_element_index_uint}
*/
elementIndexUint: {
get: function() {
return this._elementIndexUint || this._webgl2;
}
},
/**
* true if WEBGL_depth_texture is supported. This extension provides
* access to depth textures that, for example, can be attached to framebuffers for shadow mapping.
* @memberof Context.prototype
* @type {boolean}
* @see {@link http://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/|WEBGL_depth_texture}
*/
depthTexture: {
get: function() {
return this._depthTexture || this._webgl2;
}
},
/**
* true if OES_texture_float is supported. This extension provides
* access to floating point textures that, for example, can be attached to framebuffers for high dynamic range.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/OES_texture_float/}
*/
floatingPointTexture: {
get: function() {
return this._webgl2 || this._textureFloat;
}
},
/**
* true if OES_texture_half_float is supported. This extension provides
* access to floating point textures that, for example, can be attached to framebuffers for high dynamic range.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/OES_texture_half_float/}
*/
halfFloatingPointTexture: {
get: function() {
return this._webgl2 || this._textureHalfFloat;
}
},
/**
* true if OES_texture_float_linear is supported. This extension provides
* access to linear sampling methods for minification and magnification filters of floating-point textures.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/OES_texture_float_linear/}
*/
textureFloatLinear: {
get: function() {
return this._textureFloatLinear;
}
},
/**
* true if OES_texture_half_float_linear is supported. This extension provides
* access to linear sampling methods for minification and magnification filters of half floating-point textures.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/OES_texture_half_float_linear/}
*/
textureHalfFloatLinear: {
get: function() {
return this._webgl2 && this._textureFloatLinear || !this._webgl2 && this._textureHalfFloatLinear;
}
},
/**
* true if EXT_shader_texture_lod is supported. This extension provides
* access to explicit LOD selection in texture sampling functions.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://registry.khronos.org/webgl/extensions/EXT_shader_texture_lod/}
*/
supportsTextureLod: {
get: function() {
return this._webgl2 || this._supportsTextureLod;
}
},
/**
* true if EXT_texture_filter_anisotropic is supported. This extension provides
* access to anisotropic filtering for textured surfaces at an oblique angle from the viewer.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/EXT_texture_filter_anisotropic/}
*/
textureFilterAnisotropic: {
get: function() {
return !!this._textureFilterAnisotropic;
}
},
/**
* true if WEBGL_compressed_texture_s3tc is supported. This extension provides
* access to DXT compressed textures.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/}
*/
s3tc: {
get: function() {
return this._s3tc;
}
},
/**
* true if WEBGL_compressed_texture_pvrtc is supported. This extension provides
* access to PVR compressed textures.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/}
*/
pvrtc: {
get: function() {
return this._pvrtc;
}
},
/**
* true if WEBGL_compressed_texture_astc is supported. This extension provides
* access to ASTC compressed textures.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_astc/}
*/
astc: {
get: function() {
return this._astc;
}
},
/**
* true if WEBGL_compressed_texture_etc is supported. This extension provides
* access to ETC compressed textures.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc/}
*/
etc: {
get: function() {
return this._etc;
}
},
/**
* true if WEBGL_compressed_texture_etc1 is supported. This extension provides
* access to ETC1 compressed textures.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc1/}
*/
etc1: {
get: function() {
return this._etc1;
}
},
/**
* true if EXT_texture_compression_bptc is supported. This extension provides
* access to BC7 compressed textures.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/EXT_texture_compression_bptc/}
*/
bc7: {
get: function() {
return this._bc7;
}
},
/**
* true if S3TC, PVRTC, ASTC, ETC, ETC1, or BC7 compression is supported.
* @memberof Context.prototype
* @type {boolean}
*/
supportsBasis: {
get: function() {
return this._s3tc || this._pvrtc || this._astc || this._etc || this._etc1 || this._bc7;
}
},
/**
* true if the OES_vertex_array_object extension is supported. This
* extension can improve performance by reducing the overhead of switching vertex arrays.
* When enabled, this extension is automatically used by {@link VertexArray}.
* @memberof Context.prototype
* @type {boolean}
* @see {@link http://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/|OES_vertex_array_object}
*/
vertexArrayObject: {
get: function() {
return this._vertexArrayObject || this._webgl2;
}
},
/**
* true if the EXT_frag_depth extension is supported. This
* extension provides access to the gl_FragDepthEXT built-in output variable
* from GLSL fragment shaders. A shader using these functions still needs to explicitly enable the
* extension with #extension GL_EXT_frag_depth : enable.
* @memberof Context.prototype
* @type {boolean}
* @see {@link http://www.khronos.org/registry/webgl/extensions/EXT_frag_depth/|EXT_frag_depth}
*/
fragmentDepth: {
get: function() {
return this._fragDepth || this._webgl2;
}
},
/**
* true if the ANGLE_instanced_arrays extension is supported. This
* extension provides access to instanced rendering.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays}
*/
instancedArrays: {
get: function() {
return this._instancedArrays || this._webgl2;
}
},
/**
* true if the EXT_color_buffer_float extension is supported. This
* extension makes the gl.RGBA32F format color renderable.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/WEBGL_color_buffer_float/}
* @see {@link https://www.khronos.org/registry/webgl/extensions/EXT_color_buffer_float/}
*/
colorBufferFloat: {
get: function() {
return this._colorBufferFloat;
}
},
/**
* true if the EXT_color_buffer_half_float extension is supported. This
* extension makes the format gl.RGBA16F format color renderable.
* @memberof Context.prototype
* @type {boolean}
* @see {@link https://www.khronos.org/registry/webgl/extensions/EXT_color_buffer_half_float/}
* @see {@link https://www.khronos.org/registry/webgl/extensions/EXT_color_buffer_float/}
*/
colorBufferHalfFloat: {
get: function() {
return this._webgl2 && this._colorBufferFloat || !this._webgl2 && this._colorBufferHalfFloat;
}
},
/**
* true if the WEBGL_draw_buffers extension is supported. This
* extensions provides support for multiple render targets. The framebuffer object can have mutiple
* color attachments and the GLSL fragment shader can write to the built-in output array gl_FragData.
* A shader using this feature needs to explicitly enable the extension with
* #extension GL_EXT_draw_buffers : enable.
* @memberof Context.prototype
* @type {boolean}
* @see {@link http://www.khronos.org/registry/webgl/extensions/WEBGL_draw_buffers/|WEBGL_draw_buffers}
*/
drawBuffers: {
get: function() {
return this._drawBuffers || this._webgl2;
}
},
debugShaders: {
get: function() {
return this._debugShaders;
}
},
throwOnWebGLError: {
get: function() {
return this._throwOnWebGLError;
},
set: function(value) {
this._throwOnWebGLError = value;
this._gl = wrapGL(
this._originalGLContext,
value ? throwOnError : void 0
);
}
},
/**
* A 1x1 RGBA texture initialized to [255, 255, 255, 255]. This can
* be used as a placeholder texture while other textures are downloaded.
* @memberof Context.prototype
* @type {Texture}
*/
defaultTexture: {
get: function() {
if (this._defaultTexture === void 0) {
this._defaultTexture = new Texture_default({
context: this,
source: {
width: 1,
height: 1,
arrayBufferView: new Uint8Array([255, 255, 255, 255])
},
flipY: false
});
}
return this._defaultTexture;
}
},
/**
* A 1x1 RGB texture initialized to [0, 0, 0] representing a material that is
* not emissive. This can be used as a placeholder texture for emissive
* textures while other textures are downloaded.
* @memberof Context.prototype
* @type {Texture}
*/
defaultEmissiveTexture: {
get: function() {
if (this._defaultEmissiveTexture === void 0) {
this._defaultEmissiveTexture = new Texture_default({
context: this,
pixelFormat: PixelFormat_default.RGB,
source: {
width: 1,
height: 1,
arrayBufferView: new Uint8Array([0, 0, 0])
},
flipY: false
});
}
return this._defaultEmissiveTexture;
}
},
/**
* A 1x1 RGBA texture initialized to [128, 128, 255] to encode a tangent
* space normal pointing in the +z direction, i.e. (0, 0, 1). This can
* be used as a placeholder normal texture while other textures are
* downloaded.
* @memberof Context.prototype
* @type {Texture}
*/
defaultNormalTexture: {
get: function() {
if (this._defaultNormalTexture === void 0) {
this._defaultNormalTexture = new Texture_default({
context: this,
pixelFormat: PixelFormat_default.RGB,
source: {
width: 1,
height: 1,
arrayBufferView: new Uint8Array([128, 128, 255])
},
flipY: false
});
}
return this._defaultNormalTexture;
}
},
/**
* A cube map, where each face is a 1x1 RGBA texture initialized to
* [255, 255, 255, 255]. This can be used as a placeholder cube map while
* other cube maps are downloaded.
* @memberof Context.prototype
* @type {CubeMap}
*/
defaultCubeMap: {
get: function() {
if (this._defaultCubeMap === void 0) {
const face = {
width: 1,
height: 1,
arrayBufferView: new Uint8Array([255, 255, 255, 255])
};
this._defaultCubeMap = new CubeMap_default({
context: this,
source: {
positiveX: face,
negativeX: face,
positiveY: face,
negativeY: face,
positiveZ: face,
negativeZ: face
},
flipY: false
});
}
return this._defaultCubeMap;
}
},
/**
* The drawingBufferHeight of the underlying GL context.
* @memberof Context.prototype
* @type {number}
* @see {@link https://www.khronos.org/registry/webgl/specs/1.0/#DOM-WebGLRenderingContext-drawingBufferHeight|drawingBufferHeight}
*/
drawingBufferHeight: {
get: function() {
return this._gl.drawingBufferHeight;
}
},
/**
* The drawingBufferWidth of the underlying GL context.
* @memberof Context.prototype
* @type {number}
* @see {@link https://www.khronos.org/registry/webgl/specs/1.0/#DOM-WebGLRenderingContext-drawingBufferWidth|drawingBufferWidth}
*/
drawingBufferWidth: {
get: function() {
return this._gl.drawingBufferWidth;
}
},
/**
* Gets an object representing the currently bound framebuffer. While this instance is not an actual
* {@link Framebuffer}, it is used to represent the default framebuffer in calls to
* {@link Texture.fromFramebuffer}.
* @memberof Context.prototype
* @type {object}
*/
defaultFramebuffer: {
get: function() {
return defaultFramebufferMarker;
}
}
});
function validateFramebuffer(context) {
if (context.validateFramebuffer) {
const gl = context._gl;
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status !== gl.FRAMEBUFFER_COMPLETE) {
let message;
switch (status) {
case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
message = "Framebuffer is not complete. Incomplete attachment: at least one attachment point with a renderbuffer or texture attached has its attached object no longer in existence or has an attached image with a width or height of zero, or the color attachment point has a non-color-renderable image attached, or the depth attachment point has a non-depth-renderable image attached, or the stencil attachment point has a non-stencil-renderable image attached. Color-renderable formats include GL_RGBA4, GL_RGB5_A1, and GL_RGB565. GL_DEPTH_COMPONENT16 is the only depth-renderable format. GL_STENCIL_INDEX8 is the only stencil-renderable format.";
break;
case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
message = "Framebuffer is not complete. Incomplete dimensions: not all attached images have the same width and height.";
break;
case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
message = "Framebuffer is not complete. Missing attachment: no images are attached to the framebuffer.";
break;
case gl.FRAMEBUFFER_UNSUPPORTED:
message = "Framebuffer is not complete. Unsupported: the combination of internal formats of the attached images violates an implementation-dependent set of restrictions.";
break;
}
throw new DeveloperError_default(message);
}
}
}
function applyRenderState(context, renderState, passState, clear2) {
const previousRenderState = context._currentRenderState;
const previousPassState = context._currentPassState;
context._currentRenderState = renderState;
context._currentPassState = passState;
RenderState_default.partialApply(
context._gl,
previousRenderState,
renderState,
previousPassState,
passState,
clear2
);
}
var scratchBackBufferArray;
if (typeof WebGLRenderingContext !== "undefined") {
scratchBackBufferArray = [WebGLConstants_default.BACK];
}
function bindFramebuffer(context, framebuffer) {
if (framebuffer !== context._currentFramebuffer) {
context._currentFramebuffer = framebuffer;
let buffers = scratchBackBufferArray;
if (defined_default(framebuffer)) {
framebuffer._bind();
validateFramebuffer(context);
buffers = framebuffer._getActiveColorAttachments();
} else {
const gl = context._gl;
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
}
if (context.drawBuffers) {
context.glDrawBuffers(buffers);
}
}
}
var defaultClearCommand = new ClearCommand_default();
Context.prototype.clear = function(clearCommand, passState) {
clearCommand = clearCommand ?? defaultClearCommand;
passState = passState ?? this._defaultPassState;
const gl = this._gl;
let bitmask = 0;
const c = clearCommand.color;
const d = clearCommand.depth;
const s = clearCommand.stencil;
if (defined_default(c)) {
if (!Color_default.equals(this._clearColor, c)) {
Color_default.clone(c, this._clearColor);
gl.clearColor(c.red, c.green, c.blue, c.alpha);
}
bitmask |= gl.COLOR_BUFFER_BIT;
}
if (defined_default(d)) {
if (d !== this._clearDepth) {
this._clearDepth = d;
gl.clearDepth(d);
}
bitmask |= gl.DEPTH_BUFFER_BIT;
}
if (defined_default(s)) {
if (s !== this._clearStencil) {
this._clearStencil = s;
gl.clearStencil(s);
}
bitmask |= gl.STENCIL_BUFFER_BIT;
}
const rs = clearCommand.renderState ?? this._defaultRenderState;
applyRenderState(this, rs, passState, true);
const framebuffer = clearCommand.framebuffer ?? passState.framebuffer;
bindFramebuffer(this, framebuffer);
gl.clear(bitmask);
};
function beginDraw(context, framebuffer, passState, shaderProgram, renderState) {
if (defined_default(framebuffer) && renderState.depthTest) {
if (renderState.depthTest.enabled && !framebuffer.hasDepthAttachment) {
throw new DeveloperError_default(
"The depth test can not be enabled (drawCommand.renderState.depthTest.enabled) because the framebuffer (drawCommand.framebuffer) does not have a depth or depth-stencil renderbuffer."
);
}
}
bindFramebuffer(context, framebuffer);
applyRenderState(context, renderState, passState, false);
shaderProgram._bind();
context._maxFrameTextureUnitIndex = Math.max(
context._maxFrameTextureUnitIndex,
shaderProgram.maximumTextureUnitIndex
);
}
function continueDraw(context, drawCommand, shaderProgram, uniformMap2) {
const primitiveType = drawCommand._primitiveType;
const va = drawCommand._vertexArray;
let offset = drawCommand._offset;
let count = drawCommand._count;
const instanceCount = drawCommand.instanceCount;
if (!PrimitiveType_default.validate(primitiveType)) {
throw new DeveloperError_default(
"drawCommand.primitiveType is required and must be valid."
);
}
Check_default.defined("drawCommand.vertexArray", va);
Check_default.typeOf.number.greaterThanOrEquals("drawCommand.offset", offset, 0);
if (defined_default(count)) {
Check_default.typeOf.number.greaterThanOrEquals("drawCommand.count", count, 0);
}
Check_default.typeOf.number.greaterThanOrEquals(
"drawCommand.instanceCount",
instanceCount,
0
);
if (instanceCount > 0 && !context.instancedArrays) {
throw new DeveloperError_default("Instanced arrays extension is not supported");
}
context._us.model = drawCommand._modelMatrix ?? Matrix4_default.IDENTITY;
shaderProgram._setUniforms(
uniformMap2,
context._us,
context.validateShaderProgram
);
va._bind();
const indexBuffer = va.indexBuffer;
if (defined_default(indexBuffer)) {
offset = offset * indexBuffer.bytesPerIndex;
if (defined_default(count)) {
count = Math.min(count, indexBuffer.numberOfIndices);
} else {
count = indexBuffer.numberOfIndices;
}
if (instanceCount === 0) {
context._gl.drawElements(
primitiveType,
count,
indexBuffer.indexDatatype,
offset
);
} else {
context.glDrawElementsInstanced(
primitiveType,
count,
indexBuffer.indexDatatype,
offset,
instanceCount
);
}
} else {
if (defined_default(count)) {
count = Math.min(count, va.numberOfVertices);
} else {
count = va.numberOfVertices;
}
if (instanceCount === 0) {
context._gl.drawArrays(primitiveType, offset, count);
} else {
context.glDrawArraysInstanced(
primitiveType,
offset,
count,
instanceCount
);
}
}
va._unBind();
}
Context.prototype.draw = function(drawCommand, passState, shaderProgram, uniformMap2) {
Check_default.defined("drawCommand", drawCommand);
Check_default.defined("drawCommand.shaderProgram", drawCommand._shaderProgram);
passState = passState ?? this._defaultPassState;
const framebuffer = drawCommand._framebuffer ?? passState.framebuffer;
const renderState = drawCommand._renderState ?? this._defaultRenderState;
shaderProgram = shaderProgram ?? drawCommand._shaderProgram;
uniformMap2 = uniformMap2 ?? drawCommand._uniformMap;
beginDraw(this, framebuffer, passState, shaderProgram, renderState);
continueDraw(this, drawCommand, shaderProgram, uniformMap2);
};
Context.prototype.beginFrame = function() {
};
Context.prototype.endFrame = function() {
const gl = this._gl;
gl.useProgram(null);
this._currentFramebuffer = void 0;
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
const buffers = scratchBackBufferArray;
if (this.drawBuffers) {
this.glDrawBuffers(buffers);
}
const length2 = this._maxFrameTextureUnitIndex;
this._maxFrameTextureUnitIndex = 0;
for (let i = 0; i < length2; ++i) {
gl.activeTexture(gl.TEXTURE0 + i);
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
}
};
Context.prototype.readPixels = function(readState) {
const gl = this._gl;
readState = readState ?? Frozen_default.EMPTY_OBJECT;
const x = Math.max(readState.x ?? 0, 0);
const y = Math.max(readState.y ?? 0, 0);
const width = readState.width ?? this.drawingBufferWidth;
const height = readState.height ?? this.drawingBufferHeight;
const framebuffer = readState.framebuffer;
Check_default.typeOf.number.greaterThan("readState.width", width, 0);
Check_default.typeOf.number.greaterThan("readState.height", height, 0);
let pixelDatatype = PixelDatatype_default.UNSIGNED_BYTE;
if (defined_default(framebuffer) && framebuffer.numberOfColorAttachments > 0) {
pixelDatatype = framebuffer.getColorTexture(0).pixelDatatype;
}
const pixels = PixelFormat_default.createTypedArray(
PixelFormat_default.RGBA,
pixelDatatype,
width,
height
);
bindFramebuffer(this, framebuffer);
gl.readPixels(
x,
y,
width,
height,
PixelFormat_default.RGBA,
PixelDatatype_default.toWebGLConstant(pixelDatatype, this),
pixels
);
return pixels;
};
var viewportQuadAttributeLocations = {
position: 0,
textureCoordinates: 1
};
Context.prototype.getViewportQuadVertexArray = function() {
let vertexArray = this.cache.viewportQuad_vertexArray;
if (!defined_default(vertexArray)) {
const geometry = new Geometry_default({
attributes: {
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: [-1, -1, 1, -1, 1, 1, -1, 1]
}),
textureCoordinates: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: [0, 0, 1, 0, 1, 1, 0, 1]
})
},
// Workaround Internet Explorer 11.0.8 lack of TRIANGLE_FAN
indices: new Uint16Array([0, 1, 2, 0, 2, 3]),
primitiveType: PrimitiveType_default.TRIANGLES
});
vertexArray = VertexArray_default.fromGeometry({
context: this,
geometry,
attributeLocations: viewportQuadAttributeLocations,
bufferUsage: BufferUsage_default.STATIC_DRAW,
interleave: true
});
this.cache.viewportQuad_vertexArray = vertexArray;
}
return vertexArray;
};
Context.prototype.createViewportQuadCommand = function(fragmentShaderSource, overrides) {
overrides = overrides ?? Frozen_default.EMPTY_OBJECT;
return new DrawCommand_default({
vertexArray: this.getViewportQuadVertexArray(),
primitiveType: PrimitiveType_default.TRIANGLES,
renderState: overrides.renderState,
shaderProgram: ShaderProgram_default.fromCache({
context: this,
vertexShaderSource: ViewportQuadVS_default,
fragmentShaderSource,
attributeLocations: viewportQuadAttributeLocations
}),
uniformMap: overrides.uniformMap,
owner: overrides.owner,
framebuffer: overrides.framebuffer,
pass: overrides.pass
});
};
Context.prototype.getObjectByPickColor = function(pickColor) {
Check_default.defined("pickColor", pickColor);
return this._pickObjects[pickColor.toRgba()];
};
function PickId(pickObjects, key, color) {
this._pickObjects = pickObjects;
this.key = key;
this.color = color;
}
Object.defineProperties(PickId.prototype, {
object: {
get: function() {
return this._pickObjects[this.key];
},
set: function(value) {
this._pickObjects[this.key] = value;
}
}
});
PickId.prototype.destroy = function() {
delete this._pickObjects[this.key];
return void 0;
};
Context.prototype.createPickId = function(object2) {
Check_default.defined("object", object2);
++this._nextPickColor[0];
const key = this._nextPickColor[0];
if (key === 0) {
throw new RuntimeError_default("Out of unique Pick IDs.");
}
this._pickObjects[key] = object2;
return new PickId(this._pickObjects, key, Color_default.fromRgba(key));
};
Context.prototype.isDestroyed = function() {
return false;
};
Context.prototype.destroy = function() {
const cache = this.cache;
for (const property in cache) {
if (cache.hasOwnProperty(property)) {
const propertyValue = cache[property];
if (defined_default(propertyValue.destroy)) {
propertyValue.destroy();
}
}
}
this._shaderCache = this._shaderCache.destroy();
this._textureCache = this._textureCache.destroy();
this._defaultTexture = this._defaultTexture && this._defaultTexture.destroy();
this._defaultEmissiveTexture = this._defaultEmissiveTexture && this._defaultEmissiveTexture.destroy();
this._defaultNormalTexture = this._defaultNormalTexture && this._defaultNormalTexture.destroy();
this._defaultCubeMap = this._defaultCubeMap && this._defaultCubeMap.destroy();
return destroyObject_default(this);
};
var Context_default = Context;
// packages/engine/Source/Renderer/FramebufferManager.js
var import_InlineWorkers275 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Renderer/MultisampleFramebuffer.js
var import_InlineWorkers272 = __toESM(require_InlineWorkers(), 1);
function MultisampleFramebuffer(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const {
context,
width,
height,
colorRenderbuffers,
colorTextures,
depthStencilRenderbuffer,
depthStencilTexture,
destroyAttachments
} = options;
Check_default.defined("options.context", context);
Check_default.defined("options.width", width);
Check_default.defined("options.height", height);
this._width = width;
this._height = height;
if (defined_default(colorRenderbuffers) !== defined_default(colorTextures)) {
throw new DeveloperError_default(
"Both color renderbuffer and texture attachments must be provided."
);
}
if (defined_default(depthStencilRenderbuffer) !== defined_default(depthStencilTexture)) {
throw new DeveloperError_default(
"Both depth-stencil renderbuffer and texture attachments must be provided."
);
}
this._renderFramebuffer = new Framebuffer_default({
context,
colorRenderbuffers,
depthStencilRenderbuffer,
destroyAttachments
});
this._colorFramebuffer = new Framebuffer_default({
context,
colorTextures,
depthStencilTexture,
destroyAttachments
});
}
MultisampleFramebuffer.prototype.getRenderFramebuffer = function() {
return this._renderFramebuffer;
};
MultisampleFramebuffer.prototype.getColorFramebuffer = function() {
return this._colorFramebuffer;
};
MultisampleFramebuffer.prototype.blitFramebuffers = function(context, blitStencil) {
this._renderFramebuffer.bindRead();
this._colorFramebuffer.bindDraw();
const gl = context._gl;
let mask = 0;
if (this._colorFramebuffer._colorTextures.length > 0) {
mask |= gl.COLOR_BUFFER_BIT;
}
if (defined_default(this._colorFramebuffer.depthStencilTexture)) {
mask |= gl.DEPTH_BUFFER_BIT | (blitStencil ? gl.STENCIL_BUFFER_BIT : 0);
}
gl.blitFramebuffer(
0,
0,
this._width,
this._height,
0,
0,
this._width,
this._height,
mask,
gl.NEAREST
);
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
};
MultisampleFramebuffer.prototype.isDestroyed = function() {
return false;
};
MultisampleFramebuffer.prototype.destroy = function() {
this._renderFramebuffer.destroy();
this._colorFramebuffer.destroy();
return destroyObject_default(this);
};
var MultisampleFramebuffer_default = MultisampleFramebuffer;
// packages/engine/Source/Renderer/Renderbuffer.js
var import_InlineWorkers274 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Renderer/RenderbufferFormat.js
var import_InlineWorkers273 = __toESM(require_InlineWorkers(), 1);
var RenderbufferFormat = {
RGBA4: WebGLConstants_default.RGBA4,
RGBA8: WebGLConstants_default.RGBA8,
RGBA16F: WebGLConstants_default.RGBA16F,
RGBA32F: WebGLConstants_default.RGBA32F,
RGB5_A1: WebGLConstants_default.RGB5_A1,
RGB565: WebGLConstants_default.RGB565,
DEPTH_COMPONENT16: WebGLConstants_default.DEPTH_COMPONENT16,
STENCIL_INDEX8: WebGLConstants_default.STENCIL_INDEX8,
DEPTH_STENCIL: WebGLConstants_default.DEPTH_STENCIL,
DEPTH24_STENCIL8: WebGLConstants_default.DEPTH24_STENCIL8,
validate: function(renderbufferFormat) {
return renderbufferFormat === RenderbufferFormat.RGBA4 || renderbufferFormat === RenderbufferFormat.RGBA8 || renderbufferFormat === RenderbufferFormat.RGBA16F || renderbufferFormat === RenderbufferFormat.RGBA32F || renderbufferFormat === RenderbufferFormat.RGB5_A1 || renderbufferFormat === RenderbufferFormat.RGB565 || renderbufferFormat === RenderbufferFormat.DEPTH_COMPONENT16 || renderbufferFormat === RenderbufferFormat.STENCIL_INDEX8 || renderbufferFormat === RenderbufferFormat.DEPTH_STENCIL || renderbufferFormat === RenderbufferFormat.DEPTH24_STENCIL8;
},
getColorFormat: function(datatype) {
if (datatype === WebGLConstants_default.FLOAT) {
return RenderbufferFormat.RGBA32F;
} else if (datatype === WebGLConstants_default.HALF_FLOAT_OES) {
return RenderbufferFormat.RGBA16F;
}
return RenderbufferFormat.RGBA8;
}
};
var RenderbufferFormat_default = Object.freeze(RenderbufferFormat);
// packages/engine/Source/Renderer/Renderbuffer.js
function Renderbuffer(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.defined("options.context", options.context);
const context = options.context;
const gl = context._gl;
const maximumRenderbufferSize = ContextLimits_default.maximumRenderbufferSize;
const format = options.format ?? RenderbufferFormat_default.RGBA4;
const width = defined_default(options.width) ? options.width : context.drawingBufferWidth;
const height = defined_default(options.height) ? options.height : context.drawingBufferHeight;
const numSamples = options.numSamples ?? 1;
if (!RenderbufferFormat_default.validate(format)) {
throw new DeveloperError_default("Invalid format.");
}
Check_default.typeOf.number.greaterThan("width", width, 0);
if (width > maximumRenderbufferSize) {
throw new DeveloperError_default(
`Width must be less than or equal to the maximum renderbuffer size (${maximumRenderbufferSize}). Check maximumRenderbufferSize.`
);
}
Check_default.typeOf.number.greaterThan("height", height, 0);
if (height > maximumRenderbufferSize) {
throw new DeveloperError_default(
`Height must be less than or equal to the maximum renderbuffer size (${maximumRenderbufferSize}). Check maximumRenderbufferSize.`
);
}
this._gl = gl;
this._format = format;
this._width = width;
this._height = height;
this._renderbuffer = this._gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, this._renderbuffer);
if (numSamples > 1) {
gl.renderbufferStorageMultisample(
gl.RENDERBUFFER,
numSamples,
format,
width,
height
);
} else {
gl.renderbufferStorage(gl.RENDERBUFFER, format, width, height);
}
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
}
Object.defineProperties(Renderbuffer.prototype, {
format: {
get: function() {
return this._format;
}
},
width: {
get: function() {
return this._width;
}
},
height: {
get: function() {
return this._height;
}
}
});
Renderbuffer.prototype._getRenderbuffer = function() {
return this._renderbuffer;
};
Renderbuffer.prototype.isDestroyed = function() {
return false;
};
Renderbuffer.prototype.destroy = function() {
this._gl.deleteRenderbuffer(this._renderbuffer);
return destroyObject_default(this);
};
var Renderbuffer_default = Renderbuffer;
// packages/engine/Source/Renderer/FramebufferManager.js
function FramebufferManager(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._numSamples = options.numSamples ?? 1;
this._colorAttachmentsLength = options.colorAttachmentsLength ?? 1;
this._color = options.color ?? true;
this._depth = options.depth ?? false;
this._depthStencil = options.depthStencil ?? false;
this._supportsDepthTexture = options.supportsDepthTexture ?? false;
if (!this._color && !this._depth && !this._depthStencil) {
throw new DeveloperError_default(
"Must enable at least one type of framebuffer attachment."
);
}
if (this._depth && this._depthStencil) {
throw new DeveloperError_default(
"Cannot have both a depth and depth-stencil attachment."
);
}
this._createColorAttachments = options.createColorAttachments ?? true;
this._createDepthAttachments = options.createDepthAttachments ?? true;
this._pixelDatatype = options.pixelDatatype;
this._pixelFormat = options.pixelFormat;
this._width = void 0;
this._height = void 0;
this._framebuffer = void 0;
this._multisampleFramebuffer = void 0;
this._colorTextures = void 0;
if (this._color) {
this._colorTextures = new Array(this._colorAttachmentsLength);
this._colorRenderbuffers = new Array(this._colorAttachmentsLength);
}
this._colorRenderbuffer = void 0;
this._depthStencilRenderbuffer = void 0;
this._depthStencilTexture = void 0;
this._depthRenderbuffer = void 0;
this._depthTexture = void 0;
this._attachmentsDirty = false;
}
Object.defineProperties(FramebufferManager.prototype, {
framebuffer: {
get: function() {
if (this._numSamples > 1) {
return this._multisampleFramebuffer.getRenderFramebuffer();
}
return this._framebuffer;
}
},
numSamples: {
get: function() {
return this._numSamples;
}
},
status: {
get: function() {
return this.framebuffer.status;
}
}
});
FramebufferManager.prototype.isDirty = function(width, height, numSamples, pixelDatatype, pixelFormat) {
numSamples = numSamples ?? 1;
const dimensionChanged = this._width !== width || this._height !== height;
const samplesChanged = this._numSamples !== numSamples;
const pixelChanged = defined_default(pixelDatatype) && this._pixelDatatype !== pixelDatatype || defined_default(pixelFormat) && this._pixelFormat !== pixelFormat;
const framebufferDefined = numSamples === 1 ? defined_default(this._framebuffer) : defined_default(this._multisampleFramebuffer);
return this._attachmentsDirty || dimensionChanged || samplesChanged || pixelChanged || !framebufferDefined || this._color && !defined_default(this._colorTextures[0]);
};
FramebufferManager.prototype.update = function(context, width, height, numSamples, pixelDatatype, pixelFormat) {
if (!defined_default(width) || !defined_default(height)) {
throw new DeveloperError_default("width and height must be defined.");
}
numSamples = context.msaa ? numSamples ?? 1 : 1;
pixelDatatype = pixelDatatype ?? (this._color ? this._pixelDatatype ?? PixelDatatype_default.UNSIGNED_BYTE : void 0);
pixelFormat = pixelFormat ?? (this._color ? this._pixelFormat ?? PixelFormat_default.RGBA : void 0);
if (this.isDirty(width, height, numSamples, pixelDatatype, pixelFormat)) {
this.destroy();
this._width = width;
this._height = height;
this._numSamples = numSamples;
this._pixelDatatype = pixelDatatype;
this._pixelFormat = pixelFormat;
this._attachmentsDirty = false;
if (this._color && this._createColorAttachments) {
for (let i = 0; i < this._colorAttachmentsLength; ++i) {
this._colorTextures[i] = new Texture_default({
context,
width,
height,
pixelFormat,
pixelDatatype,
sampler: Sampler_default.NEAREST
});
if (this._numSamples > 1) {
const format = RenderbufferFormat_default.getColorFormat(pixelDatatype);
this._colorRenderbuffers[i] = new Renderbuffer_default({
context,
width,
height,
format,
numSamples: this._numSamples
});
}
}
}
if (this._depthStencil && this._createDepthAttachments) {
if (this._supportsDepthTexture && context.depthTexture) {
this._depthStencilTexture = new Texture_default({
context,
width,
height,
pixelFormat: PixelFormat_default.DEPTH_STENCIL,
pixelDatatype: PixelDatatype_default.UNSIGNED_INT_24_8,
sampler: Sampler_default.NEAREST
});
if (this._numSamples > 1) {
this._depthStencilRenderbuffer = new Renderbuffer_default({
context,
width,
height,
format: RenderbufferFormat_default.DEPTH24_STENCIL8,
numSamples: this._numSamples
});
}
} else {
this._depthStencilRenderbuffer = new Renderbuffer_default({
context,
width,
height,
format: RenderbufferFormat_default.DEPTH_STENCIL
});
}
}
if (this._depth && this._createDepthAttachments) {
if (this._supportsDepthTexture && context.depthTexture) {
this._depthTexture = new Texture_default({
context,
width,
height,
pixelFormat: PixelFormat_default.DEPTH_COMPONENT,
pixelDatatype: PixelDatatype_default.UNSIGNED_INT,
sampler: Sampler_default.NEAREST
});
} else {
this._depthRenderbuffer = new Renderbuffer_default({
context,
width,
height,
format: RenderbufferFormat_default.DEPTH_COMPONENT16
});
}
}
if (this._numSamples > 1) {
this._multisampleFramebuffer = new MultisampleFramebuffer_default({
context,
width: this._width,
height: this._height,
colorTextures: this._colorTextures,
colorRenderbuffers: this._colorRenderbuffers,
depthStencilTexture: this._depthStencilTexture,
depthStencilRenderbuffer: this._depthStencilRenderbuffer,
destroyAttachments: false
});
} else {
this._framebuffer = new Framebuffer_default({
context,
colorTextures: this._colorTextures,
depthTexture: this._depthTexture,
depthRenderbuffer: this._depthRenderbuffer,
depthStencilTexture: this._depthStencilTexture,
depthStencilRenderbuffer: this._depthStencilRenderbuffer,
destroyAttachments: false
});
}
}
};
FramebufferManager.prototype.getColorTexture = function(index) {
index = index ?? 0;
if (index >= this._colorAttachmentsLength) {
throw new DeveloperError_default(
"index must be smaller than total number of color attachments."
);
}
return this._colorTextures[index];
};
FramebufferManager.prototype.setColorTexture = function(texture, index) {
index = index ?? 0;
if (this._createColorAttachments) {
throw new DeveloperError_default(
"createColorAttachments must be false if setColorTexture is called."
);
}
if (index >= this._colorAttachmentsLength) {
throw new DeveloperError_default(
"index must be smaller than total number of color attachments."
);
}
this._attachmentsDirty = texture !== this._colorTextures[index];
this._colorTextures[index] = texture;
};
FramebufferManager.prototype.getColorRenderbuffer = function(index) {
index = index ?? 0;
if (index >= this._colorAttachmentsLength) {
throw new DeveloperError_default(
"index must be smaller than total number of color attachments."
);
}
return this._colorRenderbuffers[index];
};
FramebufferManager.prototype.setColorRenderbuffer = function(renderbuffer, index) {
index = index ?? 0;
if (this._createColorAttachments) {
throw new DeveloperError_default(
"createColorAttachments must be false if setColorRenderbuffer is called."
);
}
if (index >= this._colorAttachmentsLength) {
throw new DeveloperError_default(
"index must be smaller than total number of color attachments."
);
}
this._attachmentsDirty = renderbuffer !== this._colorRenderbuffers[index];
this._colorRenderbuffers[index] = renderbuffer;
};
FramebufferManager.prototype.getDepthRenderbuffer = function() {
return this._depthRenderbuffer;
};
FramebufferManager.prototype.setDepthRenderbuffer = function(renderbuffer) {
if (this._createDepthAttachments) {
throw new DeveloperError_default(
"createDepthAttachments must be false if setDepthRenderbuffer is called."
);
}
this._attachmentsDirty = renderbuffer !== this._depthRenderbuffer;
this._depthRenderbuffer = renderbuffer;
};
FramebufferManager.prototype.getDepthTexture = function() {
return this._depthTexture;
};
FramebufferManager.prototype.setDepthTexture = function(texture) {
if (this._createDepthAttachments) {
throw new DeveloperError_default(
"createDepthAttachments must be false if setDepthTexture is called."
);
}
this._attachmentsDirty = texture !== this._depthTexture;
this._depthTexture = texture;
};
FramebufferManager.prototype.getDepthStencilRenderbuffer = function() {
return this._depthStencilRenderbuffer;
};
FramebufferManager.prototype.setDepthStencilRenderbuffer = function(renderbuffer) {
if (this._createDepthAttachments) {
throw new DeveloperError_default(
"createDepthAttachments must be false if setDepthStencilRenderbuffer is called."
);
}
this._attachmentsDirty = renderbuffer !== this._depthStencilRenderbuffer;
this._depthStencilRenderbuffer = renderbuffer;
};
FramebufferManager.prototype.getDepthStencilTexture = function() {
return this._depthStencilTexture;
};
FramebufferManager.prototype.setDepthStencilTexture = function(texture) {
if (this._createDepthAttachments) {
throw new DeveloperError_default(
"createDepthAttachments must be false if setDepthStencilTexture is called."
);
}
this._attachmentsDirty = texture !== this._depthStencilTexture;
this._depthStencilTexture = texture;
};
FramebufferManager.prototype.prepareTextures = function(context, blitStencil) {
if (this._numSamples > 1) {
this._multisampleFramebuffer.blitFramebuffers(context, blitStencil);
}
};
FramebufferManager.prototype.clear = function(context, clearCommand, passState) {
const framebuffer = clearCommand.framebuffer;
clearCommand.framebuffer = this.framebuffer;
clearCommand.execute(context, passState);
clearCommand.framebuffer = framebuffer;
};
FramebufferManager.prototype.destroyFramebuffer = function() {
this._framebuffer = this._framebuffer && this._framebuffer.destroy();
this._multisampleFramebuffer = this._multisampleFramebuffer && this._multisampleFramebuffer.destroy();
};
FramebufferManager.prototype.destroy = function() {
if (this._color) {
const colorTextures = this._colorTextures;
const colorRenderbuffers = this._colorRenderbuffers;
for (let i = 0; i < colorTextures.length; ++i) {
const texture = colorTextures[i];
if (this._createColorAttachments) {
if (defined_default(texture) && !texture.isDestroyed()) {
texture.destroy();
}
}
if (defined_default(texture) && texture.isDestroyed()) {
colorTextures[i] = void 0;
}
const renderbuffer = colorRenderbuffers[i];
if (this._createColorAttachments) {
if (defined_default(renderbuffer) && !renderbuffer.isDestroyed()) {
renderbuffer.destroy();
}
}
if (defined_default(renderbuffer) && renderbuffer.isDestroyed()) {
colorRenderbuffers[i] = void 0;
}
}
}
if (this._depthStencil) {
if (this._createDepthAttachments) {
this._depthStencilTexture = this._depthStencilTexture && this._depthStencilTexture.destroy();
this._depthStencilRenderbuffer = this._depthStencilRenderbuffer && this._depthStencilRenderbuffer.destroy();
}
if (defined_default(this._depthStencilTexture) && this._depthStencilTexture.isDestroyed()) {
this._depthStencilTexture = void 0;
}
if (defined_default(this._depthStencilRenderbuffer) && this._depthStencilRenderbuffer.isDestroyed()) {
this._depthStencilRenderbuffer = void 0;
}
}
if (this._depth) {
if (this._createDepthAttachments) {
this._depthTexture = this._depthTexture && this._depthTexture.destroy();
this._depthRenderbuffer = this._depthRenderbuffer && this._depthRenderbuffer.destroy();
}
if (defined_default(this._depthTexture) && this._depthTexture.isDestroyed()) {
this._depthTexture = void 0;
}
if (defined_default(this._depthRenderbuffer) && this._depthRenderbuffer.isDestroyed()) {
this._depthRenderbuffer = void 0;
}
}
this.destroyFramebuffer();
};
var FramebufferManager_default = FramebufferManager;
// packages/engine/Source/Renderer/ShaderBuilder.js
var import_InlineWorkers280 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Renderer/ShaderDestination.js
var import_InlineWorkers276 = __toESM(require_InlineWorkers(), 1);
var ShaderDestination = {
VERTEX: 0,
FRAGMENT: 1,
BOTH: 2
};
ShaderDestination.includesVertexShader = function(destination) {
Check_default.typeOf.number("destination", destination);
return destination === ShaderDestination.VERTEX || destination === ShaderDestination.BOTH;
};
ShaderDestination.includesFragmentShader = function(destination) {
Check_default.typeOf.number("destination", destination);
return destination === ShaderDestination.FRAGMENT || destination === ShaderDestination.BOTH;
};
var ShaderDestination_default = Object.freeze(ShaderDestination);
// packages/engine/Source/Renderer/ShaderStruct.js
var import_InlineWorkers277 = __toESM(require_InlineWorkers(), 1);
function ShaderStruct(name) {
this.name = name;
this.fields = [];
}
ShaderStruct.prototype.addField = function(type, identifier) {
const field = ` ${type} ${identifier};`;
this.fields.push(field);
};
ShaderStruct.prototype.generateGlslLines = function() {
let fields = this.fields;
if (fields.length === 0) {
fields = [" float _empty;"];
}
return [].concat(`struct ${this.name}`, "{", fields, "};");
};
var ShaderStruct_default = ShaderStruct;
// packages/engine/Source/Renderer/ShaderFunction.js
var import_InlineWorkers278 = __toESM(require_InlineWorkers(), 1);
function ShaderFunction(signature) {
this.signature = signature;
this.body = [];
}
ShaderFunction.prototype.addLines = function(lines) {
if (typeof lines !== "string" && !Array.isArray(lines)) {
throw new DeveloperError_default(
`Expected lines to be a string or an array of strings, actual value was ${lines}`
);
}
const body = this.body;
if (Array.isArray(lines)) {
const length2 = lines.length;
for (let i = 0; i < length2; i++) {
body.push(` ${lines[i]}`);
}
} else {
body.push(` ${lines}`);
}
};
ShaderFunction.prototype.generateGlslLines = function() {
return [].concat(this.signature, "{", this.body, "}");
};
var ShaderFunction_default = ShaderFunction;
// packages/engine/Source/Core/addAllToArray.js
var import_InlineWorkers279 = __toESM(require_InlineWorkers(), 1);
function addAllToArray(target, source) {
if (!defined_default(source)) {
return;
}
const sourceLength = source.length;
if (sourceLength === 0) {
return;
}
const targetLength = target.length;
target.length += sourceLength;
for (let i = 0; i < sourceLength; i++) {
target[targetLength + i] = source[i];
}
}
var addAllToArray_default = addAllToArray;
// packages/engine/Source/Renderer/ShaderBuilder.js
function ShaderBuilder() {
this._positionAttributeLine = void 0;
this._nextAttributeLocation = 1;
this._attributeLocations = {};
this._attributeLines = [];
this._structs = {};
this._functions = {};
this._vertexShaderParts = {
defineLines: [],
uniformLines: [],
shaderLines: [],
varyingLines: [],
// identifiers of structs/functions to include, listed in insertion order
structIds: [],
functionIds: []
};
this._fragmentShaderParts = {
defineLines: [],
uniformLines: [],
shaderLines: [],
varyingLines: [],
// identifiers of structs/functions to include, listed in insertion order
structIds: [],
functionIds: []
};
}
Object.defineProperties(ShaderBuilder.prototype, {
/**
* Get a dictionary of attribute names to the integer location in
* the vertex shader.
*
* @memberof ShaderBuilder.prototype
* @type {Objectundefined until the first update.
* @memberof TextureAtlas.prototype
* @type {Texture|undefined}
* @readonly
* @private
*/
texture: {
get: function() {
return this._texture;
}
},
/**
* The pixel format of the texture.
* @memberof TextureAtlas.prototype
* @type {PixelFormat}
* @readonly
* @private
*/
pixelFormat: {
get: function() {
return this._pixelFormat;
}
},
/**
* The sampler to use when sampling this texture. If undefined, the default sampler is used.
* @memberof TextureAtlas.prototype
* @type {Sampler|undefined}
* @readonly
* @private
*/
sampler: {
get: function() {
return this._sampler;
}
},
/**
* The number of images in the texture atlas. This value increases
* every time addImage or addImageSubRegion is called.
* Texture coordinates are subject to change if the texture atlas resizes, so it is
* important to check {@link TextureAtlas#guid} before using old values.
* @memberof TextureAtlas.prototype
* @type {number}
* @readonly
* @private
*/
numberOfImages: {
get: function() {
return this._nextIndex;
}
},
/**
* The atlas' globally unique identifier (GUID).
* The GUID changes whenever the texture atlas is modified.
* Classes that use a texture atlas should check if the GUID
* has changed before processing the atlas data.
* @memberof TextureAtlas.prototype
* @type {string}
* @readonly
* @private
*/
guid: {
get: function() {
return this._guid;
}
},
/**
* Returns the size in bytes of the texture.
* @memberof TextureAtlas.prototype
* @type {number}
* @readonly
* @private
*/
sizeInBytes: {
get: function() {
if (!defined_default(this._texture)) {
return 0;
}
return this._texture.sizeInBytes;
}
}
});
TextureAtlas.prototype.computeTextureCoordinates = function(index, result) {
Check_default.typeOf.number.greaterThanOrEquals("index", index, 0);
const texture = this._texture;
const rectangle = this._rectangles[index];
if (!defined_default(result)) {
result = new BoundingRectangle_default();
}
if (!defined_default(rectangle)) {
result.x = 0;
result.y = 0;
result.width = 0;
result.height = 0;
return result;
}
const atlasWidth = texture.width;
const atlasHeight = texture.height;
const width = rectangle.width;
const height = rectangle.height;
let x = rectangle.x;
let y = rectangle.y;
const parentIndex = this._subRegions.get(index);
if (defined_default(parentIndex)) {
const parentRectangle = this._rectangles[parentIndex];
x += parentRectangle.x;
y += parentRectangle.y;
}
result.x = x / atlasWidth;
result.y = y / atlasHeight;
result.width = width / atlasWidth;
result.height = height / atlasHeight;
return result;
};
TextureAtlas.prototype._copyFromTexture = function(context, width, height, rectangles) {
const pixelFormat = this._pixelFormat;
const sampler = this._sampler;
const newTexture = new Texture_default({
context,
height,
width,
pixelFormat,
sampler
});
const gl = context._gl;
const target = newTexture._textureTarget;
const oldTexture = this._texture;
const framebuffer = new Framebuffer_default({
context,
colorTextures: [oldTexture],
destroyAttachments: false
});
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(target, newTexture._texture);
framebuffer._bind();
const oldRectangles = this.rectangles;
const subRegions = this._subRegions;
for (let index = 0; index < oldRectangles.length; ++index) {
const rectangle = rectangles[index];
const frameBufferOffset = oldRectangles[index];
if (!defined_default(rectangle) || !defined_default(frameBufferOffset) || defined_default(subRegions.get(index))) {
continue;
}
const { x, y, width: width2, height: height2 } = rectangle;
gl.copyTexSubImage2D(
target,
0,
x,
y,
frameBufferOffset.x,
frameBufferOffset.y,
width2,
height2
);
}
gl.bindTexture(target, null);
newTexture._initialized = true;
framebuffer._unBind();
framebuffer.destroy();
return newTexture;
};
TextureAtlas.prototype._resize = function(context, queueOffset = 0) {
const borderPadding = this._borderWidthInPixels;
const oldRectangles = this._rectangles;
const queue = this._imagesToAddQueue;
const oldTexture = this._texture;
let width = oldTexture.width;
let height = oldTexture.height;
const subRegions = this._subRegions;
const toPack = oldRectangles.map((image, index) => {
return new AddImageRequest({ index, image });
}).filter(
(request, index) => defined_default(request.image) && !defined_default(subRegions.get(index))
);
let maxWidth = 0;
let maxHeight = 0;
let areaQueued = 0;
for (let i = queueOffset; i < queue.length; ++i) {
const { width: width2, height: height2 } = queue[i].image;
maxWidth = Math.max(maxWidth, width2);
maxHeight = Math.max(maxHeight, height2);
areaQueued += width2 * height2;
toPack.push(queue[i]);
}
width = Math.max(maxWidth, width);
height = Math.max(maxHeight, height);
if (!context.webgl2) {
width = Math_default.nextPowerOfTwo(width);
height = Math_default.nextPowerOfTwo(height);
}
const areaDifference = areaQueued;
let scalingFactor = 1;
while (areaDifference / width / height >= 1) {
scalingFactor *= 2;
if (width > height) {
height *= scalingFactor;
} else {
width *= scalingFactor;
}
}
toPack.sort(
({ image: imageA }, { image: imageB }) => imageB.height * imageB.width - imageA.height * imageA.width
);
const newRectangles = new Array(this._nextIndex);
for (const index of this._subRegions.keys()) {
if (defined_default(subRegions.get(index))) {
newRectangles[index] = oldRectangles[index];
}
}
let texturePacker, packed = false;
while (!packed) {
texturePacker = new TexturePacker_default({ height, width, borderPadding });
let i;
for (i = 0; i < toPack.length; ++i) {
const { index, image } = toPack[i];
if (!defined_default(image)) {
continue;
}
const repackedNode = texturePacker.pack(index, image);
if (!defined_default(repackedNode)) {
if (width > height) {
height *= 2;
} else {
width *= 2;
}
break;
}
newRectangles[index] = repackedNode.rectangle;
}
packed = i === toPack.length;
}
this._texturePacker = texturePacker;
this._texture = this._copyFromTexture(context, width, height, newRectangles);
oldTexture.destroy();
this._rectangles = newRectangles;
this._guid = createGuid_default();
};
TextureAtlas.prototype.getImageIndex = function(id) {
Check_default.typeOf.string("id", id);
return this._indexById.get(id);
};
TextureAtlas.prototype._copyImageToTexture = function({
index,
image,
resolve: resolve2,
reject
}) {
const texture = this._texture;
const rectangle = this._rectangles[index];
try {
texture.copyFrom({
source: image,
xOffset: rectangle.x,
yOffset: rectangle.y
});
if (defined_default(resolve2)) {
resolve2(index);
}
} catch (e) {
if (defined_default(reject)) {
reject(e);
return;
}
}
};
function AddImageRequest({ index, image, resolve: resolve2, reject }) {
this.index = index;
this.image = image;
this.resolve = resolve2;
this.reject = reject;
this.rectangle = void 0;
}
TextureAtlas.prototype._addImage = function(index, image) {
Check_default.typeOf.number.greaterThanOrEquals("index", index, 0);
Check_default.defined("image", image);
return new Promise((resolve2, reject) => {
this._imagesToAddQueue.push(
new AddImageRequest({
index,
image,
resolve: resolve2,
reject
})
);
this._imagesToAddQueue.sort(
({ image: imageA }, { image: imageB }) => imageB.height * imageB.width - imageA.height * imageA.width
);
});
};
TextureAtlas.prototype._processImageQueue = function(context) {
const queue = this._imagesToAddQueue;
if (queue.length === 0) {
return false;
}
this._rectangles.length = this._nextIndex;
let i, error;
for (i = 0; i < queue.length; ++i) {
const imageRequest = queue[i];
const { image, index } = imageRequest;
const node = this._texturePacker.pack(index, image);
if (!defined_default(node)) {
try {
this._resize(context, i);
} catch (e) {
error = e;
if (defined_default(imageRequest.reject)) {
imageRequest.reject(error);
}
}
break;
}
this._rectangles[index] = node.rectangle;
}
if (defined_default(error)) {
for (i = i + 1; i < queue.length; ++i) {
const { resolve: resolve2 } = queue[i];
if (defined_default(resolve2)) {
resolve2(-1);
}
}
queue.length = 0;
return false;
}
for (let i2 = 0; i2 < queue.length; ++i2) {
this._copyImageToTexture(queue[i2]);
}
queue.length = 0;
return true;
};
TextureAtlas.prototype.update = function(context) {
if (!defined_default(this._texture)) {
const width = this._initialSize.x;
const height = this._initialSize.y;
const pixelFormat = this._pixelFormat;
const sampler = this._sampler;
const borderPadding = this._borderWidthInPixels;
this._texture = new Texture_default({
context,
width,
height,
pixelFormat,
sampler
});
this._texturePacker = new TexturePacker_default({
height,
width,
borderPadding
});
}
return this._processImageQueue(context);
};
async function resolveImage(image, id) {
if (typeof image === "function") {
image = image(id);
}
if (typeof image === "string" || image instanceof Resource_default) {
const resource = Resource_default.createIfNeeded(image);
image = resource.fetchImage();
}
return image;
}
TextureAtlas.prototype.addImage = function(id, image) {
Check_default.typeOf.string("id", id);
Check_default.defined("image", image);
let promise = this._indexPromiseById.get(id);
if (defined_default(promise)) {
return promise;
}
const index = this._nextIndex++;
this._indexById.set(id, index);
const resolveAndAddImage = async () => {
image = await resolveImage(image, id);
Check_default.defined("image", image);
if (this.isDestroyed() || !defined_default(image)) {
return -1;
}
return this._addImage(index, image);
};
promise = resolveAndAddImage();
this._indexPromiseById.set(id, promise);
return promise;
};
TextureAtlas.prototype.addImageSubRegion = function(id, subRegion) {
Check_default.typeOf.string("id", id);
Check_default.defined("subRegion", subRegion);
const imageIndex = this._indexById.get(id);
if (!defined_default(imageIndex)) {
throw new RuntimeError_default(`image with id "${id}" not found in the atlas.`);
}
const indexPromise = this._indexPromiseById.get(id);
for (const [index2, parentIndex] of this._subRegions.entries()) {
if (imageIndex === parentIndex) {
const boundingRegion = this._rectangles[index2];
if (boundingRegion.equals(subRegion)) {
return indexPromise.then((resolvedImageIndex) => {
if (resolvedImageIndex === -1) {
return -1;
}
return index2;
});
}
}
}
const index = this._nextIndex++;
this._subRegions.set(index, imageIndex);
this._rectangles[index] = subRegion.clone();
return indexPromise.then((imageIndex2) => {
if (imageIndex2 === -1) {
return -1;
}
const rectangle = this._rectangles[imageIndex2];
Check_default.typeOf.number.lessThanOrEquals(
"subRegion.x",
subRegion.x,
rectangle.width
);
Check_default.typeOf.number.lessThanOrEquals(
"subRegion.x + subRegion.width",
subRegion.x + subRegion.width,
rectangle.width
);
Check_default.typeOf.number.lessThanOrEquals(
"subRegion.y",
subRegion.y,
rectangle.height
);
Check_default.typeOf.number.lessThanOrEquals(
"subRegion.y + subRegion.height",
subRegion.y + subRegion.height,
rectangle.height
);
return index;
});
};
TextureAtlas.prototype.isDestroyed = function() {
return false;
};
TextureAtlas.prototype.destroy = function() {
this._texture = this._texture && this._texture.destroy();
this._imagesToAddQueue.forEach(({ resolve: resolve2 }) => {
if (defined_default(resolve2)) {
resolve2(-1);
}
});
return destroyObject_default(this);
};
var TextureAtlas_default = TextureAtlas;
// packages/engine/Source/Renderer/VertexArrayFacade.js
var import_InlineWorkers285 = __toESM(require_InlineWorkers(), 1);
function VertexArrayFacade(context, attributes, sizeInVertices, instanced) {
Check_default.defined("context", context);
if (!attributes || attributes.length === 0) {
throw new DeveloperError_default("At least one attribute is required.");
}
const attrs = VertexArrayFacade._verifyAttributes(attributes);
sizeInVertices = sizeInVertices ?? 0;
const precreatedAttributes = [];
const attributesByUsage = {};
let attributesForUsage;
let usage;
const length2 = attrs.length;
for (let i = 0; i < length2; ++i) {
const attribute = attrs[i];
if (attribute.vertexBuffer) {
precreatedAttributes.push(attribute);
continue;
}
usage = attribute.usage;
attributesForUsage = attributesByUsage[usage];
if (!defined_default(attributesForUsage)) {
attributesForUsage = attributesByUsage[usage] = [];
}
attributesForUsage.push(attribute);
}
function compare(left, right) {
return ComponentDatatype_default.getSizeInBytes(right.componentDatatype) - ComponentDatatype_default.getSizeInBytes(left.componentDatatype);
}
this._allBuffers = [];
for (usage in attributesByUsage) {
if (attributesByUsage.hasOwnProperty(usage)) {
attributesForUsage = attributesByUsage[usage];
attributesForUsage.sort(compare);
const vertexSizeInBytes = VertexArrayFacade._vertexSizeInBytes(attributesForUsage);
const bufferUsage = attributesForUsage[0].usage;
const buffer2 = {
vertexSizeInBytes,
vertexBuffer: void 0,
usage: bufferUsage,
needsCommit: false,
arrayBuffer: void 0,
arrayViews: VertexArrayFacade._createArrayViews(
attributesForUsage,
vertexSizeInBytes
)
};
this._allBuffers.push(buffer2);
}
}
this._size = 0;
this._instanced = instanced ?? false;
this._precreated = precreatedAttributes;
this._context = context;
this.writers = void 0;
this.va = void 0;
this.resize(sizeInVertices);
}
VertexArrayFacade._verifyAttributes = function(attributes) {
const attrs = [];
for (let i = 0; i < attributes.length; ++i) {
const attribute = attributes[i];
const attr = {
index: attribute.index ?? i,
enabled: attribute.enabled ?? true,
componentsPerAttribute: attribute.componentsPerAttribute,
componentDatatype: attribute.componentDatatype ?? ComponentDatatype_default.FLOAT,
normalize: attribute.normalize ?? false,
// There will be either a vertexBuffer or an [optional] usage.
vertexBuffer: attribute.vertexBuffer,
usage: attribute.usage ?? BufferUsage_default.STATIC_DRAW
};
attrs.push(attr);
if (attr.componentsPerAttribute !== 1 && attr.componentsPerAttribute !== 2 && attr.componentsPerAttribute !== 3 && attr.componentsPerAttribute !== 4) {
throw new DeveloperError_default(
"attribute.componentsPerAttribute must be in the range [1, 4]."
);
}
const datatype = attr.componentDatatype;
if (!ComponentDatatype_default.validate(datatype)) {
throw new DeveloperError_default(
"Attribute must have a valid componentDatatype or not specify it."
);
}
if (!BufferUsage_default.validate(attr.usage)) {
throw new DeveloperError_default(
"Attribute must have a valid usage or not specify it."
);
}
}
const uniqueIndices = new Array(attrs.length);
for (let j = 0; j < attrs.length; ++j) {
const currentAttr = attrs[j];
const index = currentAttr.index;
if (uniqueIndices[index]) {
throw new DeveloperError_default(
`Index ${index} is used by more than one attribute.`
);
}
uniqueIndices[index] = true;
}
return attrs;
};
VertexArrayFacade._vertexSizeInBytes = function(attributes) {
let sizeInBytes = 0;
const length2 = attributes.length;
for (let i = 0; i < length2; ++i) {
const attribute = attributes[i];
sizeInBytes += attribute.componentsPerAttribute * ComponentDatatype_default.getSizeInBytes(attribute.componentDatatype);
}
const maxComponentSizeInBytes = length2 > 0 ? ComponentDatatype_default.getSizeInBytes(attributes[0].componentDatatype) : 0;
const remainder = maxComponentSizeInBytes > 0 ? sizeInBytes % maxComponentSizeInBytes : 0;
const padding = remainder === 0 ? 0 : maxComponentSizeInBytes - remainder;
sizeInBytes += padding;
return sizeInBytes;
};
VertexArrayFacade._createArrayViews = function(attributes, vertexSizeInBytes) {
const views = [];
let offsetInBytes = 0;
const length2 = attributes.length;
for (let i = 0; i < length2; ++i) {
const attribute = attributes[i];
const componentDatatype = attribute.componentDatatype;
views.push({
index: attribute.index,
enabled: attribute.enabled,
componentsPerAttribute: attribute.componentsPerAttribute,
componentDatatype,
normalize: attribute.normalize,
offsetInBytes,
vertexSizeInComponentType: vertexSizeInBytes / ComponentDatatype_default.getSizeInBytes(componentDatatype),
view: void 0
});
offsetInBytes += attribute.componentsPerAttribute * ComponentDatatype_default.getSizeInBytes(componentDatatype);
}
return views;
};
VertexArrayFacade.prototype.resize = function(sizeInVertices) {
this._size = sizeInVertices;
const allBuffers = this._allBuffers;
this.writers = [];
for (let i = 0, len = allBuffers.length; i < len; ++i) {
const buffer2 = allBuffers[i];
VertexArrayFacade._resize(buffer2, this._size);
VertexArrayFacade._appendWriters(this.writers, buffer2);
}
destroyVA(this);
};
VertexArrayFacade._resize = function(buffer2, size) {
if (buffer2.vertexSizeInBytes > 0) {
const arrayBuffer = new ArrayBuffer(size * buffer2.vertexSizeInBytes);
if (defined_default(buffer2.arrayBuffer)) {
const destView = new Uint8Array(arrayBuffer);
const sourceView = new Uint8Array(buffer2.arrayBuffer);
const sourceLength = sourceView.length;
for (let j = 0; j < sourceLength; ++j) {
destView[j] = sourceView[j];
}
}
const views = buffer2.arrayViews;
const length2 = views.length;
for (let i = 0; i < length2; ++i) {
const view = views[i];
view.view = ComponentDatatype_default.createArrayBufferView(
view.componentDatatype,
arrayBuffer,
view.offsetInBytes
);
}
buffer2.arrayBuffer = arrayBuffer;
}
};
var createWriters = [
// 1 component per attribute
function(buffer2, view, vertexSizeInComponentType) {
return function(index, attribute) {
view[index * vertexSizeInComponentType] = attribute;
buffer2.needsCommit = true;
};
},
// 2 component per attribute
function(buffer2, view, vertexSizeInComponentType) {
return function(index, component0, component1) {
const i = index * vertexSizeInComponentType;
view[i] = component0;
view[i + 1] = component1;
buffer2.needsCommit = true;
};
},
// 3 component per attribute
function(buffer2, view, vertexSizeInComponentType) {
return function(index, component0, component1, component2) {
const i = index * vertexSizeInComponentType;
view[i] = component0;
view[i + 1] = component1;
view[i + 2] = component2;
buffer2.needsCommit = true;
};
},
// 4 component per attribute
function(buffer2, view, vertexSizeInComponentType) {
return function(index, component0, component1, component2, component3) {
const i = index * vertexSizeInComponentType;
view[i] = component0;
view[i + 1] = component1;
view[i + 2] = component2;
view[i + 3] = component3;
buffer2.needsCommit = true;
};
}
];
VertexArrayFacade._appendWriters = function(writers, buffer2) {
const arrayViews = buffer2.arrayViews;
const length2 = arrayViews.length;
for (let i = 0; i < length2; ++i) {
const arrayView = arrayViews[i];
writers[arrayView.index] = createWriters[arrayView.componentsPerAttribute - 1](buffer2, arrayView.view, arrayView.vertexSizeInComponentType);
}
};
VertexArrayFacade.prototype.commit = function(indexBuffer) {
let recreateVA = false;
const allBuffers = this._allBuffers;
let buffer2;
let i;
let length2;
for (i = 0, length2 = allBuffers.length; i < length2; ++i) {
buffer2 = allBuffers[i];
recreateVA = commit(this, buffer2) || recreateVA;
}
if (recreateVA || !defined_default(this.va)) {
destroyVA(this);
const va = this.va = [];
const chunkSize = Math_default.SIXTY_FOUR_KILOBYTES - 4;
const numberOfVertexArrays = defined_default(indexBuffer) && !this._instanced ? Math.ceil(this._size / chunkSize) : 1;
for (let k = 0; k < numberOfVertexArrays; ++k) {
let attributes = [];
for (i = 0, length2 = allBuffers.length; i < length2; ++i) {
buffer2 = allBuffers[i];
const offset = k * (buffer2.vertexSizeInBytes * chunkSize);
VertexArrayFacade._appendAttributes(
attributes,
buffer2,
offset,
this._instanced
);
}
attributes = attributes.concat(this._precreated);
va.push({
va: new VertexArray_default({
context: this._context,
attributes,
indexBuffer
}),
indicesCount: 1.5 * (k !== numberOfVertexArrays - 1 ? chunkSize : this._size % chunkSize)
// TODO: not hardcode 1.5, this assumes 6 indices per 4 vertices (as for Billboard quads).
});
}
}
};
function commit(vertexArrayFacade, buffer2) {
if (buffer2.needsCommit && buffer2.vertexSizeInBytes > 0) {
buffer2.needsCommit = false;
const vertexBuffer = buffer2.vertexBuffer;
const vertexBufferSizeInBytes = vertexArrayFacade._size * buffer2.vertexSizeInBytes;
const vertexBufferDefined = defined_default(vertexBuffer);
if (!vertexBufferDefined || vertexBuffer.sizeInBytes < vertexBufferSizeInBytes) {
if (vertexBufferDefined) {
vertexBuffer.destroy();
}
buffer2.vertexBuffer = Buffer_default.createVertexBuffer({
context: vertexArrayFacade._context,
typedArray: buffer2.arrayBuffer,
usage: buffer2.usage
});
buffer2.vertexBuffer.vertexArrayDestroyable = false;
return true;
}
buffer2.vertexBuffer.copyFromArrayView(buffer2.arrayBuffer);
}
return false;
}
VertexArrayFacade._appendAttributes = function(attributes, buffer2, vertexBufferOffset, instanced) {
const arrayViews = buffer2.arrayViews;
const length2 = arrayViews.length;
for (let i = 0; i < length2; ++i) {
const view = arrayViews[i];
attributes.push({
index: view.index,
enabled: view.enabled,
componentsPerAttribute: view.componentsPerAttribute,
componentDatatype: view.componentDatatype,
normalize: view.normalize,
vertexBuffer: buffer2.vertexBuffer,
offsetInBytes: vertexBufferOffset + view.offsetInBytes,
strideInBytes: buffer2.vertexSizeInBytes,
instanceDivisor: instanced ? 1 : 0
});
}
};
VertexArrayFacade.prototype.subCommit = function(offsetInVertices, lengthInVertices) {
if (offsetInVertices < 0 || offsetInVertices >= this._size) {
throw new DeveloperError_default(
"offsetInVertices must be greater than or equal to zero and less than the vertex array size."
);
}
if (offsetInVertices + lengthInVertices > this._size) {
throw new DeveloperError_default(
"offsetInVertices + lengthInVertices cannot exceed the vertex array size."
);
}
const allBuffers = this._allBuffers;
for (let i = 0, len = allBuffers.length; i < len; ++i) {
subCommit(allBuffers[i], offsetInVertices, lengthInVertices);
}
};
function subCommit(buffer2, offsetInVertices, lengthInVertices) {
if (buffer2.needsCommit && buffer2.vertexSizeInBytes > 0) {
const byteOffset = buffer2.vertexSizeInBytes * offsetInVertices;
const byteLength = buffer2.vertexSizeInBytes * lengthInVertices;
buffer2.vertexBuffer.copyFromArrayView(
new Uint8Array(buffer2.arrayBuffer, byteOffset, byteLength),
byteOffset
);
}
}
VertexArrayFacade.prototype.endSubCommits = function() {
const allBuffers = this._allBuffers;
for (let i = 0, len = allBuffers.length; i < len; ++i) {
allBuffers[i].needsCommit = false;
}
};
function destroyVA(vertexArrayFacade) {
const va = vertexArrayFacade.va;
if (!defined_default(va)) {
return;
}
const length2 = va.length;
for (let i = 0; i < length2; ++i) {
va[i].va.destroy();
}
vertexArrayFacade.va = void 0;
}
VertexArrayFacade.prototype.isDestroyed = function() {
return false;
};
VertexArrayFacade.prototype.destroy = function() {
const allBuffers = this._allBuffers;
for (let i = 0, len = allBuffers.length; i < len; ++i) {
const buffer2 = allBuffers[i];
buffer2.vertexBuffer = buffer2.vertexBuffer && buffer2.vertexBuffer.destroy();
}
destroyVA(this);
return destroyObject_default(this);
};
var VertexArrayFacade_default = VertexArrayFacade;
// packages/engine/Source/Renderer/loadCubeMap.js
var import_InlineWorkers286 = __toESM(require_InlineWorkers(), 1);
function loadCubeMap(context, urls, skipColorSpaceConversion) {
Check_default.defined("context", context);
Check_default.defined("urls", urls);
if (Object.values(CubeMap_default.FaceName).some((faceName) => !defined_default(urls[faceName]))) {
throw new DeveloperError_default(
"urls must have positiveX, negativeX, positiveY, negativeY, positiveZ, and negativeZ properties."
);
}
const flipOptions = {
flipY: true,
skipColorSpaceConversion,
preferImageBitmap: true
};
const facePromises = [
Resource_default.createIfNeeded(urls.positiveX).fetchImage(flipOptions),
Resource_default.createIfNeeded(urls.negativeX).fetchImage(flipOptions),
Resource_default.createIfNeeded(urls.positiveY).fetchImage(flipOptions),
Resource_default.createIfNeeded(urls.negativeY).fetchImage(flipOptions),
Resource_default.createIfNeeded(urls.positiveZ).fetchImage(flipOptions),
Resource_default.createIfNeeded(urls.negativeZ).fetchImage(flipOptions)
];
return Promise.all(facePromises).then(function(images) {
return new CubeMap_default({
context,
source: {
positiveX: images[0],
negativeX: images[1],
positiveY: images[2],
negativeY: images[3],
positiveZ: images[4],
negativeZ: images[5]
}
});
});
}
var loadCubeMap_default = loadCubeMap;
// packages/engine/Source/DataSources/BillboardGraphics.js
var import_InlineWorkers289 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/createPropertyDescriptor.js
var import_InlineWorkers288 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/ConstantProperty.js
var import_InlineWorkers287 = __toESM(require_InlineWorkers(), 1);
function ConstantProperty(value) {
this._value = void 0;
this._hasClone = false;
this._hasEquals = false;
this._definitionChanged = new Event_default();
this.setValue(value);
}
Object.defineProperties(ConstantProperty.prototype, {
/**
* Gets a value indicating if this property is constant.
* This property always returns true.
* @memberof ConstantProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
value: true
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is changed whenever setValue is called with data different
* than the current value.
* @memberof ConstantProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
}
});
ConstantProperty.prototype.getValue = function(time, result) {
return this._hasClone ? this._value.clone(result) : this._value;
};
ConstantProperty.prototype.setValue = function(value) {
const oldValue2 = this._value;
if (oldValue2 !== value) {
const isDefined = defined_default(value);
const hasClone = isDefined && typeof value.clone === "function";
const hasEquals = isDefined && typeof value.equals === "function";
const changed = !hasEquals || !value.equals(oldValue2);
if (changed) {
this._hasClone = hasClone;
this._hasEquals = hasEquals;
this._value = !hasClone ? value : value.clone(this._value);
this._definitionChanged.raiseEvent(this);
}
}
};
ConstantProperty.prototype.equals = function(other) {
return this === other || //
other instanceof ConstantProperty && //
(!this._hasEquals && this._value === other._value || //
this._hasEquals && this._value.equals(other._value));
};
ConstantProperty.prototype.valueOf = function() {
return this._value;
};
ConstantProperty.prototype.toString = function() {
return String(this._value);
};
var ConstantProperty_default = ConstantProperty;
// packages/engine/Source/DataSources/createPropertyDescriptor.js
function createProperty(name, privateName, subscriptionName, configurable, createPropertyCallback) {
return {
configurable,
get: function() {
return this[privateName];
},
set: function(value) {
const oldValue2 = this[privateName];
const subscription = this[subscriptionName];
if (defined_default(subscription)) {
subscription();
this[subscriptionName] = void 0;
}
const hasValue = value !== void 0;
if (hasValue && (!defined_default(value) || !defined_default(value.getValue)) && defined_default(createPropertyCallback)) {
value = createPropertyCallback(value);
}
if (oldValue2 !== value) {
this[privateName] = value;
this._definitionChanged.raiseEvent(this, name, value, oldValue2);
}
if (defined_default(value) && defined_default(value.definitionChanged)) {
this[subscriptionName] = value.definitionChanged.addEventListener(
function() {
this._definitionChanged.raiseEvent(this, name, value, value);
},
this
);
}
}
};
}
function createConstantProperty(value) {
return new ConstantProperty_default(value);
}
function createPropertyDescriptor(name, configurable, createPropertyCallback) {
return createProperty(
name,
`_${name.toString()}`,
`_${name.toString()}Subscription`,
configurable ?? false,
createPropertyCallback ?? createConstantProperty
);
}
var createPropertyDescriptor_default = createPropertyDescriptor;
// packages/engine/Source/DataSources/BillboardGraphics.js
function BillboardGraphics(options) {
this._definitionChanged = new Event_default();
this._show = void 0;
this._showSubscription = void 0;
this._image = void 0;
this._imageSubscription = void 0;
this._scale = void 0;
this._scaleSubscription = void 0;
this._pixelOffset = void 0;
this._pixelOffsetSubscription = void 0;
this._eyeOffset = void 0;
this._eyeOffsetSubscription = void 0;
this._horizontalOrigin = void 0;
this._horizontalOriginSubscription = void 0;
this._verticalOrigin = void 0;
this._verticalOriginSubscription = void 0;
this._heightReference = void 0;
this._heightReferenceSubscription = void 0;
this._color = void 0;
this._colorSubscription = void 0;
this._rotation = void 0;
this._rotationSubscription = void 0;
this._alignedAxis = void 0;
this._alignedAxisSubscription = void 0;
this._sizeInMeters = void 0;
this._sizeInMetersSubscription = void 0;
this._width = void 0;
this._widthSubscription = void 0;
this._height = void 0;
this._heightSubscription = void 0;
this._scaleByDistance = void 0;
this._scaleByDistanceSubscription = void 0;
this._translucencyByDistance = void 0;
this._translucencyByDistanceSubscription = void 0;
this._pixelOffsetScaleByDistance = void 0;
this._pixelOffsetScaleByDistanceSubscription = void 0;
this._imageSubRegion = void 0;
this._imageSubRegionSubscription = void 0;
this._distanceDisplayCondition = void 0;
this._distanceDisplayConditionSubscription = void 0;
this._disableDepthTestDistance = void 0;
this._disableDepthTestDistanceSubscription = void 0;
this._splitDirection = void 0;
this._splitDirectionSubscription = void 0;
this.merge(options ?? Frozen_default.EMPTY_OBJECT);
}
Object.defineProperties(BillboardGraphics.prototype, {
/**
* Gets the event that is raised whenever a property or sub-property is changed or modified.
* @memberof BillboardGraphics.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the boolean Property specifying the visibility of the billboard.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
* @default true
*/
show: createPropertyDescriptor_default("show"),
/**
* Gets or sets the Property specifying the Image, URI, or Canvas to use for the billboard.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
*/
image: createPropertyDescriptor_default("image"),
/**
* Gets or sets the numeric Property specifying the uniform scale to apply to the image.
* A scale greater than 1.0 enlarges the billboard while a scale less than 1.0 shrinks it.
* 
* From left to right in the above image, the scales are 0.5, 1.0, and 2.0.
*
x increases from left to right, and y increases from top to bottom.
* *
default |
* b.pixeloffset = new Cartesian2(50, 25); |
*
x points towards the viewer's
* right, y points up, and z points into the screen.
* * An eye offset is commonly used to arrange multiple billboards or objects at the same position, e.g., to * arrange a billboard above its corresponding 3D model. *
* Below, the billboard is positioned at the center of the Earth but an eye offset makes it always * appear on top of the Earth regardless of the viewer's or Earth's orientation. **
![]() |
* ![]() |
*
b.eyeOffset = new Cartesian3(0.0, 8000000.0, 0.0);
* image.
* This has two common use cases. First, the same white texture may be used by many different billboards,
* each with a different color, to create colored billboards. Second, the color's alpha component can be
* used to make the billboard translucent as shown below. An alpha of 0.0 makes the billboard
* transparent, and 1.0 makes the billboard opaque.
* *
default![]() |
* alpha : 0.5![]() |
*
alignedAxis.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
* @default 0
*/
rotation: createPropertyDescriptor_default("rotation"),
/**
* Gets or sets the {@link Cartesian3} Property specifying the unit vector axis of rotation
* in the fixed frame. When set to Cartesian3.ZERO the rotation is from the top of the screen.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
* @default Cartesian3.ZERO
*/
alignedAxis: createPropertyDescriptor_default("alignedAxis"),
/**
* Gets or sets the boolean Property specifying if this billboard's size will be measured in meters.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
* @default false
*/
sizeInMeters: createPropertyDescriptor_default("sizeInMeters"),
/**
* Gets or sets the numeric Property specifying the width of the billboard in pixels.
* When undefined, the native width is used.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
*/
width: createPropertyDescriptor_default("width"),
/**
* Gets or sets the numeric Property specifying the height of the billboard in pixels.
* When undefined, the native height is used.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
*/
height: createPropertyDescriptor_default("height"),
/**
* Gets or sets {@link NearFarScalar} Property specifying the scale of the billboard based on the distance from the camera.
* A billboard's scale will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the billboard's scale remains clamped to the nearest bound.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
*/
scaleByDistance: createPropertyDescriptor_default("scaleByDistance"),
/**
* Gets or sets {@link NearFarScalar} Property specifying the translucency of the billboard based on the distance from the camera.
* A billboard's translucency will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the billboard's translucency remains clamped to the nearest bound.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
*/
translucencyByDistance: createPropertyDescriptor_default("translucencyByDistance"),
/**
* Gets or sets {@link NearFarScalar} Property specifying the pixel offset of the billboard based on the distance from the camera.
* A billboard's pixel offset will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the billboard's pixel offset remains clamped to the nearest bound.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
*/
pixelOffsetScaleByDistance: createPropertyDescriptor_default(
"pixelOffsetScaleByDistance"
),
/**
* Gets or sets the Property specifying a {@link BoundingRectangle} that defines a
* sub-region of the image to use for the billboard, rather than the entire image,
* measured in pixels from the bottom-left.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
*/
imageSubRegion: createPropertyDescriptor_default("imageSubRegion"),
/**
* Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this billboard will be displayed.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
*/
distanceDisplayCondition: createPropertyDescriptor_default(
"distanceDisplayCondition"
),
/**
* Gets or sets the distance from the camera at which to disable the depth test to, for example, prevent clipping against terrain.
* When set to zero, the depth test is always applied. When set to Number.POSITIVE_INFINITY, the depth test is never applied.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
*/
disableDepthTestDistance: createPropertyDescriptor_default(
"disableDepthTestDistance"
),
/**
* Gets or sets the Property specifying the {@link SplitDirection} of this billboard.
* @memberof BillboardGraphics.prototype
* @type {Property|undefined}
* @default SplitDirection.NONE
*/
splitDirection: createPropertyDescriptor_default("splitDirection")
});
BillboardGraphics.prototype.clone = function(result) {
if (!defined_default(result)) {
return new BillboardGraphics(this);
}
result.show = this._show;
result.image = this._image;
result.scale = this._scale;
result.pixelOffset = this._pixelOffset;
result.eyeOffset = this._eyeOffset;
result.horizontalOrigin = this._horizontalOrigin;
result.verticalOrigin = this._verticalOrigin;
result.heightReference = this._heightReference;
result.color = this._color;
result.rotation = this._rotation;
result.alignedAxis = this._alignedAxis;
result.sizeInMeters = this._sizeInMeters;
result.width = this._width;
result.height = this._height;
result.scaleByDistance = this._scaleByDistance;
result.translucencyByDistance = this._translucencyByDistance;
result.pixelOffsetScaleByDistance = this._pixelOffsetScaleByDistance;
result.imageSubRegion = this._imageSubRegion;
result.distanceDisplayCondition = this._distanceDisplayCondition;
result.disableDepthTestDistance = this._disableDepthTestDistance;
result.splitDirection = this._splitDirection;
return result;
};
BillboardGraphics.prototype.merge = function(source) {
if (!defined_default(source)) {
throw new DeveloperError_default("source is required.");
}
this.show = this._show ?? source.show;
this.image = this._image ?? source.image;
this.scale = this._scale ?? source.scale;
this.pixelOffset = this._pixelOffset ?? source.pixelOffset;
this.eyeOffset = this._eyeOffset ?? source.eyeOffset;
this.horizontalOrigin = this._horizontalOrigin ?? source.horizontalOrigin;
this.verticalOrigin = this._verticalOrigin ?? source.verticalOrigin;
this.heightReference = this._heightReference ?? source.heightReference;
this.color = this._color ?? source.color;
this.rotation = this._rotation ?? source.rotation;
this.alignedAxis = this._alignedAxis ?? source.alignedAxis;
this.sizeInMeters = this._sizeInMeters ?? source.sizeInMeters;
this.width = this._width ?? source.width;
this.height = this._height ?? source.height;
this.scaleByDistance = this._scaleByDistance ?? source.scaleByDistance;
this.translucencyByDistance = this._translucencyByDistance ?? source.translucencyByDistance;
this.pixelOffsetScaleByDistance = this._pixelOffsetScaleByDistance ?? source.pixelOffsetScaleByDistance;
this.imageSubRegion = this._imageSubRegion ?? source.imageSubRegion;
this.distanceDisplayCondition = this._distanceDisplayCondition ?? source.distanceDisplayCondition;
this.disableDepthTestDistance = this._disableDepthTestDistance ?? source.disableDepthTestDistance;
this.splitDirection = this.splitDirection ?? source.splitDirection;
};
var BillboardGraphics_default = BillboardGraphics;
// packages/engine/Source/DataSources/BillboardVisualizer.js
var import_InlineWorkers299 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/AssociativeArray.js
var import_InlineWorkers290 = __toESM(require_InlineWorkers(), 1);
function AssociativeArray() {
this._array = [];
this._hash = {};
}
Object.defineProperties(AssociativeArray.prototype, {
/**
* Gets the number of items in the collection.
* @memberof AssociativeArray.prototype
*
* @type {number}
*/
length: {
get: function() {
return this._array.length;
}
},
/**
* Gets an unordered array of all values in the collection.
* This is a live array that will automatically reflect the values in the collection,
* it should not be modified directly.
* @memberof AssociativeArray.prototype
*
* @type {Array}
*/
values: {
get: function() {
return this._array;
}
}
});
AssociativeArray.prototype.contains = function(key) {
if (typeof key !== "string" && typeof key !== "number") {
throw new DeveloperError_default("key is required to be a string or number.");
}
return defined_default(this._hash[key]);
};
AssociativeArray.prototype.set = function(key, value) {
if (typeof key !== "string" && typeof key !== "number") {
throw new DeveloperError_default("key is required to be a string or number.");
}
const oldValue2 = this._hash[key];
if (value !== oldValue2) {
this.remove(key);
this._hash[key] = value;
this._array.push(value);
}
};
AssociativeArray.prototype.get = function(key) {
if (typeof key !== "string" && typeof key !== "number") {
throw new DeveloperError_default("key is required to be a string or number.");
}
return this._hash[key];
};
AssociativeArray.prototype.remove = function(key) {
if (defined_default(key) && typeof key !== "string" && typeof key !== "number") {
throw new DeveloperError_default("key is required to be a string or number.");
}
const value = this._hash[key];
const hasValue = defined_default(value);
if (hasValue) {
const array = this._array;
array.splice(array.indexOf(value), 1);
delete this._hash[key];
}
return hasValue;
};
AssociativeArray.prototype.removeAll = function() {
const array = this._array;
if (array.length > 0) {
this._hash = {};
array.length = 0;
}
};
var AssociativeArray_default = AssociativeArray;
// packages/engine/Source/Core/DistanceDisplayCondition.js
var import_InlineWorkers291 = __toESM(require_InlineWorkers(), 1);
function DistanceDisplayCondition(near, far) {
near = near ?? 0;
this._near = near;
far = far ?? Number.MAX_VALUE;
this._far = far;
}
Object.defineProperties(DistanceDisplayCondition.prototype, {
/**
* The smallest distance in the interval where the object is visible.
* @memberof DistanceDisplayCondition.prototype
* @type {number}
* @default 0.0
*/
near: {
get: function() {
return this._near;
},
set: function(value) {
this._near = value;
}
},
/**
* The largest distance in the interval where the object is visible.
* @memberof DistanceDisplayCondition.prototype
* @type {number}
* @default Number.MAX_VALUE
*/
far: {
get: function() {
return this._far;
},
set: function(value) {
this._far = value;
}
}
});
DistanceDisplayCondition.packedLength = 2;
DistanceDisplayCondition.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
array[startingIndex++] = value.near;
array[startingIndex] = value.far;
return array;
};
DistanceDisplayCondition.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new DistanceDisplayCondition();
}
result.near = array[startingIndex++];
result.far = array[startingIndex];
return result;
};
DistanceDisplayCondition.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left.near === right.near && left.far === right.far;
};
DistanceDisplayCondition.clone = function(value, result) {
if (!defined_default(value)) {
return void 0;
}
if (!defined_default(result)) {
result = new DistanceDisplayCondition();
}
result.near = value.near;
result.far = value.far;
return result;
};
DistanceDisplayCondition.prototype.clone = function(result) {
return DistanceDisplayCondition.clone(this, result);
};
DistanceDisplayCondition.prototype.equals = function(other) {
return DistanceDisplayCondition.equals(this, other);
};
var DistanceDisplayCondition_default = DistanceDisplayCondition;
// packages/engine/Source/Core/NearFarScalar.js
var import_InlineWorkers292 = __toESM(require_InlineWorkers(), 1);
function NearFarScalar(near, nearValue, far, farValue) {
this.near = near ?? 0;
this.nearValue = nearValue ?? 0;
this.far = far ?? 1;
this.farValue = farValue ?? 0;
}
NearFarScalar.clone = function(nearFarScalar, result) {
if (!defined_default(nearFarScalar)) {
return void 0;
}
if (!defined_default(result)) {
return new NearFarScalar(
nearFarScalar.near,
nearFarScalar.nearValue,
nearFarScalar.far,
nearFarScalar.farValue
);
}
result.near = nearFarScalar.near;
result.nearValue = nearFarScalar.nearValue;
result.far = nearFarScalar.far;
result.farValue = nearFarScalar.farValue;
return result;
};
NearFarScalar.packedLength = 4;
NearFarScalar.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
array[startingIndex++] = value.near;
array[startingIndex++] = value.nearValue;
array[startingIndex++] = value.far;
array[startingIndex] = value.farValue;
return array;
};
NearFarScalar.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new NearFarScalar();
}
result.near = array[startingIndex++];
result.nearValue = array[startingIndex++];
result.far = array[startingIndex++];
result.farValue = array[startingIndex];
return result;
};
NearFarScalar.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left.near === right.near && left.nearValue === right.nearValue && left.far === right.far && left.farValue === right.farValue;
};
NearFarScalar.prototype.clone = function(result) {
return NearFarScalar.clone(this, result);
};
NearFarScalar.prototype.equals = function(right) {
return NearFarScalar.equals(this, right);
};
var NearFarScalar_default = NearFarScalar;
// packages/engine/Source/Scene/HeightReference.js
var import_InlineWorkers293 = __toESM(require_InlineWorkers(), 1);
var HeightReference = {
/**
* The position is absolute.
* @type {number}
* @constant
*/
NONE: 0,
/**
* The position is clamped to the terrain and 3D Tiles. When clamping to 3D Tilesets such as photorealistic 3D Tiles, ensure the tileset has {@link Cesium3DTileset#enableCollision} set to true. Otherwise, the entity may not be correctly clamped to the tileset surface.
* @type {number}
* @constant
*/
CLAMP_TO_GROUND: 1,
/**
* The position height is the height above the terrain and 3D Tiles.
* @type {number}
* @constant
*/
RELATIVE_TO_GROUND: 2,
/**
* The position is clamped to terain.
* @type {number}
* @constant
*/
CLAMP_TO_TERRAIN: 3,
/**
* The position height is the height above terrain.
* @type {number}
* @constant
*/
RELATIVE_TO_TERRAIN: 4,
/**
* The position is clamped to 3D Tiles.
* @type {number}
* @constant
*/
CLAMP_TO_3D_TILE: 5,
/**
* The position height is the height above 3D Tiles.
* @type {number}
* @constant
*/
RELATIVE_TO_3D_TILE: 6
};
var HeightReference_default = Object.freeze(HeightReference);
function isHeightReferenceClamp(heightReference) {
return heightReference === HeightReference.CLAMP_TO_GROUND || heightReference === HeightReference.CLAMP_TO_3D_TILE || heightReference === HeightReference.CLAMP_TO_TERRAIN;
}
function isHeightReferenceRelative(heightReference) {
return heightReference === HeightReference.RELATIVE_TO_GROUND || heightReference === HeightReference.RELATIVE_TO_3D_TILE || heightReference === HeightReference.RELATIVE_TO_TERRAIN;
}
// packages/engine/Source/Scene/HorizontalOrigin.js
var import_InlineWorkers294 = __toESM(require_InlineWorkers(), 1);
var HorizontalOrigin = {
/**
* The origin is at the horizontal center of the object.
*
* @type {number}
* @constant
*/
CENTER: 0,
/**
* The origin is on the left side of the object.
*
* @type {number}
* @constant
*/
LEFT: 1,
/**
* The origin is on the right side of the object.
*
* @type {number}
* @constant
*/
RIGHT: -1
};
var HorizontalOrigin_default = Object.freeze(HorizontalOrigin);
// packages/engine/Source/Scene/VerticalOrigin.js
var import_InlineWorkers295 = __toESM(require_InlineWorkers(), 1);
var VerticalOrigin = {
/**
* The origin is at the vertical center between BASELINE and TOP.
*
* @type {number}
* @constant
*/
CENTER: 0,
/**
* The origin is at the bottom of the object.
*
* @type {number}
* @constant
*/
BOTTOM: 1,
/**
* If the object contains text, the origin is at the baseline of the text, else the origin is at the bottom of the object.
*
* @type {number}
* @constant
*/
BASELINE: 2,
/**
* The origin is at the top of the object.
*
* @type {number}
* @constant
*/
TOP: -1
};
var VerticalOrigin_default = Object.freeze(VerticalOrigin);
// packages/engine/Source/DataSources/BoundingSphereState.js
var import_InlineWorkers296 = __toESM(require_InlineWorkers(), 1);
var BoundingSphereState = Object.freeze({
/**
* The BoundingSphere has been computed.
* @type BoundingSphereState
* @constant
*/
DONE: 0,
/**
* The BoundingSphere is still being computed.
* @type BoundingSphereState
* @constant
*/
PENDING: 1,
/**
* The BoundingSphere does not exist.
* @type BoundingSphereState
* @constant
*/
FAILED: 2
});
var BoundingSphereState_default = BoundingSphereState;
// packages/engine/Source/DataSources/Property.js
var import_InlineWorkers297 = __toESM(require_InlineWorkers(), 1);
function Property() {
DeveloperError_default.throwInstantiationError();
}
Object.defineProperties(Property.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof Property.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof Property.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: DeveloperError_default.throwInstantiationError
}
});
Property.prototype.getValue = DeveloperError_default.throwInstantiationError;
Property.prototype.equals = DeveloperError_default.throwInstantiationError;
Property.equals = function(left, right) {
return left === right || defined_default(left) && left.equals(right);
};
Property.arrayEquals = function(left, right) {
if (left === right) {
return true;
}
if (!defined_default(left) || !defined_default(right) || left.length !== right.length) {
return false;
}
const length2 = left.length;
for (let i = 0; i < length2; i++) {
if (!Property.equals(left[i], right[i])) {
return false;
}
}
return true;
};
Property.isConstant = function(property) {
return !defined_default(property) || property.isConstant;
};
Property.getValueOrUndefined = function(property, time, result) {
return defined_default(property) ? property.getValue(time, result) : void 0;
};
Property.getValueOrDefault = function(property, time, valueDefault, result) {
return defined_default(property) ? property.getValue(time, result) ?? valueDefault : valueDefault;
};
Property.getValueOrClonedDefault = function(property, time, valueDefault, result) {
let value;
if (defined_default(property)) {
value = property.getValue(time, result);
}
if (!defined_default(value)) {
value = valueDefault.clone(value);
}
return value;
};
var Property_default = Property;
// packages/engine/Source/Scene/SplitDirection.js
var import_InlineWorkers298 = __toESM(require_InlineWorkers(), 1);
var SplitDirection = {
/**
* Display the primitive or ImageryLayer to the left of the {@link Scene#splitPosition}.
*
* @type {number}
* @constant
*/
LEFT: -1,
/**
* Always display the primitive or ImageryLayer.
*
* @type {number}
* @constant
*/
NONE: 0,
/**
* Display the primitive or ImageryLayer to the right of the {@link Scene#splitPosition}.
*
* @type {number}
* @constant
*/
RIGHT: 1
};
var SplitDirection_default = Object.freeze(SplitDirection);
// packages/engine/Source/DataSources/BillboardVisualizer.js
var defaultColor = Color_default.WHITE;
var defaultEyeOffset = Cartesian3_default.ZERO;
var defaultHeightReference = HeightReference_default.NONE;
var defaultPixelOffset = Cartesian2_default.ZERO;
var defaultScale = 1;
var defaultRotation = 0;
var defaultAlignedAxis = Cartesian3_default.ZERO;
var defaultHorizontalOrigin = HorizontalOrigin_default.CENTER;
var defaultVerticalOrigin = VerticalOrigin_default.CENTER;
var defaultSizeInMeters = false;
var defaultSplitDirection = SplitDirection_default.NONE;
var positionScratch = new Cartesian3_default();
var colorScratch = new Color_default();
var eyeOffsetScratch = new Cartesian3_default();
var pixelOffsetScratch = new Cartesian2_default();
var scaleByDistanceScratch = new NearFarScalar_default();
var translucencyByDistanceScratch = new NearFarScalar_default();
var pixelOffsetScaleByDistanceScratch = new NearFarScalar_default();
var boundingRectangleScratch = new BoundingRectangle_default();
var distanceDisplayConditionScratch = new DistanceDisplayCondition_default();
function EntityData(entity) {
this.entity = entity;
this.billboard = void 0;
this.textureValue = void 0;
}
function BillboardVisualizer(entityCluster, entityCollection) {
if (!defined_default(entityCluster)) {
throw new DeveloperError_default("entityCluster is required.");
}
if (!defined_default(entityCollection)) {
throw new DeveloperError_default("entityCollection is required.");
}
entityCollection.collectionChanged.addEventListener(
BillboardVisualizer.prototype._onCollectionChanged,
this
);
this._cluster = entityCluster;
this._entityCollection = entityCollection;
this._items = new AssociativeArray_default();
this._onCollectionChanged(entityCollection, entityCollection.values, [], []);
}
BillboardVisualizer.prototype.update = function(time) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required.");
}
const items = this._items.values;
const cluster = this._cluster;
for (let i = 0, len = items.length; i < len; i++) {
const item = items[i];
const entity = item.entity;
const billboardGraphics = entity._billboard;
let textureValue;
let billboard = item.billboard;
let show = entity.isShowing && entity.isAvailable(time) && Property_default.getValueOrDefault(billboardGraphics._show, time, true);
let position;
if (show) {
position = Property_default.getValueOrUndefined(
entity._position,
time,
positionScratch
);
textureValue = Property_default.getValueOrUndefined(
billboardGraphics._image,
time
);
show = defined_default(position) && defined_default(textureValue);
}
if (!show) {
returnPrimitive(item, entity, cluster);
continue;
}
if (!Property_default.isConstant(entity._position)) {
cluster._clusterDirty = true;
}
if (!defined_default(billboard)) {
billboard = cluster.getBillboard(entity);
billboard.id = entity;
item.billboard = billboard;
item.textureValue = void 0;
}
billboard.show = show;
if (item.textureValue !== textureValue) {
billboard.image = textureValue;
item.textureValue = textureValue;
}
billboard.position = position;
billboard.color = Property_default.getValueOrDefault(
billboardGraphics._color,
time,
defaultColor,
colorScratch
);
billboard.eyeOffset = Property_default.getValueOrDefault(
billboardGraphics._eyeOffset,
time,
defaultEyeOffset,
eyeOffsetScratch
);
billboard.heightReference = Property_default.getValueOrDefault(
billboardGraphics._heightReference,
time,
defaultHeightReference
);
billboard.pixelOffset = Property_default.getValueOrDefault(
billboardGraphics._pixelOffset,
time,
defaultPixelOffset,
pixelOffsetScratch
);
billboard.scale = Property_default.getValueOrDefault(
billboardGraphics._scale,
time,
defaultScale
);
billboard.rotation = Property_default.getValueOrDefault(
billboardGraphics._rotation,
time,
defaultRotation
);
billboard.alignedAxis = Property_default.getValueOrDefault(
billboardGraphics._alignedAxis,
time,
defaultAlignedAxis
);
billboard.horizontalOrigin = Property_default.getValueOrDefault(
billboardGraphics._horizontalOrigin,
time,
defaultHorizontalOrigin
);
billboard.verticalOrigin = Property_default.getValueOrDefault(
billboardGraphics._verticalOrigin,
time,
defaultVerticalOrigin
);
billboard.width = Property_default.getValueOrUndefined(
billboardGraphics._width,
time
);
billboard.height = Property_default.getValueOrUndefined(
billboardGraphics._height,
time
);
billboard.scaleByDistance = Property_default.getValueOrUndefined(
billboardGraphics._scaleByDistance,
time,
scaleByDistanceScratch
);
billboard.translucencyByDistance = Property_default.getValueOrUndefined(
billboardGraphics._translucencyByDistance,
time,
translucencyByDistanceScratch
);
billboard.pixelOffsetScaleByDistance = Property_default.getValueOrUndefined(
billboardGraphics._pixelOffsetScaleByDistance,
time,
pixelOffsetScaleByDistanceScratch
);
billboard.sizeInMeters = Property_default.getValueOrDefault(
billboardGraphics._sizeInMeters,
time,
defaultSizeInMeters
);
billboard.distanceDisplayCondition = Property_default.getValueOrUndefined(
billboardGraphics._distanceDisplayCondition,
time,
distanceDisplayConditionScratch
);
billboard.disableDepthTestDistance = Property_default.getValueOrUndefined(
billboardGraphics._disableDepthTestDistance,
time
);
billboard.splitDirection = Property_default.getValueOrDefault(
billboardGraphics._splitDirection,
time,
defaultSplitDirection
);
const subRegion = Property_default.getValueOrUndefined(
billboardGraphics._imageSubRegion,
time,
boundingRectangleScratch
);
if (defined_default(subRegion)) {
billboard.setImageSubRegion(billboard.image, subRegion);
}
}
return true;
};
BillboardVisualizer.prototype.getBoundingSphere = function(entity, result) {
if (!defined_default(entity)) {
throw new DeveloperError_default("entity is required.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
const item = this._items.get(entity.id);
if (!defined_default(item) || !defined_default(item.billboard)) {
return BoundingSphereState_default.FAILED;
}
const billboard = item.billboard;
if (billboard.heightReference === HeightReference_default.NONE) {
result.center = Cartesian3_default.clone(billboard.position, result.center);
} else {
if (!defined_default(billboard._clampedPosition)) {
return BoundingSphereState_default.PENDING;
}
result.center = Cartesian3_default.clone(billboard._clampedPosition, result.center);
}
result.radius = 0;
return BoundingSphereState_default.DONE;
};
BillboardVisualizer.prototype.isDestroyed = function() {
return false;
};
BillboardVisualizer.prototype.destroy = function() {
this._entityCollection.collectionChanged.removeEventListener(
BillboardVisualizer.prototype._onCollectionChanged,
this
);
const entities = this._entityCollection.values;
for (let i = 0; i < entities.length; i++) {
this._cluster.removeBillboard(entities[i]);
}
return destroyObject_default(this);
};
BillboardVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed, changed) {
let i;
let entity;
const items = this._items;
const cluster = this._cluster;
for (i = added.length - 1; i > -1; i--) {
entity = added[i];
if (defined_default(entity._billboard) && defined_default(entity._position)) {
items.set(entity.id, new EntityData(entity));
}
}
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i];
if (defined_default(entity._billboard) && defined_default(entity._position)) {
if (!items.contains(entity.id)) {
items.set(entity.id, new EntityData(entity));
}
} else {
returnPrimitive(items.get(entity.id), entity, cluster);
items.remove(entity.id);
}
}
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i];
returnPrimitive(items.get(entity.id), entity, cluster);
items.remove(entity.id);
}
};
function returnPrimitive(item, entity, cluster) {
if (defined_default(item)) {
item.billboard = void 0;
cluster.removeBillboard(entity);
}
}
var BillboardVisualizer_default = BillboardVisualizer;
// packages/engine/Source/DataSources/BoxGeometryUpdater.js
var import_InlineWorkers422 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/BoxOutlineGeometry.js
var import_InlineWorkers300 = __toESM(require_InlineWorkers(), 1);
var diffScratch2 = new Cartesian3_default();
function BoxOutlineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const min3 = options.minimum;
const max3 = options.maximum;
Check_default.typeOf.object("min", min3);
Check_default.typeOf.object("max", max3);
if (defined_default(options.offsetAttribute) && options.offsetAttribute === GeometryOffsetAttribute_default.TOP) {
throw new DeveloperError_default(
"GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry."
);
}
this._min = Cartesian3_default.clone(min3);
this._max = Cartesian3_default.clone(max3);
this._offsetAttribute = options.offsetAttribute;
this._workerName = "createBoxOutlineGeometry";
}
BoxOutlineGeometry.fromDimensions = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const dimensions = options.dimensions;
Check_default.typeOf.object("dimensions", dimensions);
Check_default.typeOf.number.greaterThanOrEquals("dimensions.x", dimensions.x, 0);
Check_default.typeOf.number.greaterThanOrEquals("dimensions.y", dimensions.y, 0);
Check_default.typeOf.number.greaterThanOrEquals("dimensions.z", dimensions.z, 0);
const corner = Cartesian3_default.multiplyByScalar(dimensions, 0.5, new Cartesian3_default());
return new BoxOutlineGeometry({
minimum: Cartesian3_default.negate(corner, new Cartesian3_default()),
maximum: corner,
offsetAttribute: options.offsetAttribute
});
};
BoxOutlineGeometry.fromAxisAlignedBoundingBox = function(boundingBox) {
Check_default.typeOf.object("boundindBox", boundingBox);
return new BoxOutlineGeometry({
minimum: boundingBox.minimum,
maximum: boundingBox.maximum
});
};
BoxOutlineGeometry.packedLength = 2 * Cartesian3_default.packedLength + 1;
BoxOutlineGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
Cartesian3_default.pack(value._min, array, startingIndex);
Cartesian3_default.pack(value._max, array, startingIndex + Cartesian3_default.packedLength);
array[startingIndex + Cartesian3_default.packedLength * 2] = value._offsetAttribute ?? -1;
return array;
};
var scratchMin2 = new Cartesian3_default();
var scratchMax2 = new Cartesian3_default();
var scratchOptions2 = {
minimum: scratchMin2,
maximum: scratchMax2,
offsetAttribute: void 0
};
BoxOutlineGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const min3 = Cartesian3_default.unpack(array, startingIndex, scratchMin2);
const max3 = Cartesian3_default.unpack(
array,
startingIndex + Cartesian3_default.packedLength,
scratchMax2
);
const offsetAttribute = array[startingIndex + Cartesian3_default.packedLength * 2];
if (!defined_default(result)) {
scratchOptions2.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new BoxOutlineGeometry(scratchOptions2);
}
result._min = Cartesian3_default.clone(min3, result._min);
result._max = Cartesian3_default.clone(max3, result._max);
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
BoxOutlineGeometry.createGeometry = function(boxGeometry) {
const min3 = boxGeometry._min;
const max3 = boxGeometry._max;
if (Cartesian3_default.equals(min3, max3)) {
return;
}
const attributes = new GeometryAttributes_default();
const indices = new Uint16Array(12 * 2);
const positions = new Float64Array(8 * 3);
positions[0] = min3.x;
positions[1] = min3.y;
positions[2] = min3.z;
positions[3] = max3.x;
positions[4] = min3.y;
positions[5] = min3.z;
positions[6] = max3.x;
positions[7] = max3.y;
positions[8] = min3.z;
positions[9] = min3.x;
positions[10] = max3.y;
positions[11] = min3.z;
positions[12] = min3.x;
positions[13] = min3.y;
positions[14] = max3.z;
positions[15] = max3.x;
positions[16] = min3.y;
positions[17] = max3.z;
positions[18] = max3.x;
positions[19] = max3.y;
positions[20] = max3.z;
positions[21] = min3.x;
positions[22] = max3.y;
positions[23] = max3.z;
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
});
indices[0] = 4;
indices[1] = 5;
indices[2] = 5;
indices[3] = 6;
indices[4] = 6;
indices[5] = 7;
indices[6] = 7;
indices[7] = 4;
indices[8] = 0;
indices[9] = 1;
indices[10] = 1;
indices[11] = 2;
indices[12] = 2;
indices[13] = 3;
indices[14] = 3;
indices[15] = 0;
indices[16] = 0;
indices[17] = 4;
indices[18] = 1;
indices[19] = 5;
indices[20] = 2;
indices[21] = 6;
indices[22] = 3;
indices[23] = 7;
const diff = Cartesian3_default.subtract(max3, min3, diffScratch2);
const radius = Cartesian3_default.magnitude(diff) * 0.5;
if (defined_default(boxGeometry._offsetAttribute)) {
const length2 = positions.length;
const offsetValue = boxGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.LINES,
boundingSphere: new BoundingSphere_default(Cartesian3_default.ZERO, radius),
offsetAttribute: boxGeometry._offsetAttribute
});
};
var BoxOutlineGeometry_default = BoxOutlineGeometry;
// packages/engine/Source/Core/ColorGeometryInstanceAttribute.js
var import_InlineWorkers301 = __toESM(require_InlineWorkers(), 1);
function ColorGeometryInstanceAttribute(red, green, blue, alpha) {
red = red ?? 1;
green = green ?? 1;
blue = blue ?? 1;
alpha = alpha ?? 1;
this.value = new Uint8Array([
Color_default.floatToByte(red),
Color_default.floatToByte(green),
Color_default.floatToByte(blue),
Color_default.floatToByte(alpha)
]);
}
Object.defineProperties(ColorGeometryInstanceAttribute.prototype, {
/**
* The datatype of each component in the attribute, e.g., individual elements in
* {@link ColorGeometryInstanceAttribute#value}.
*
* @memberof ColorGeometryInstanceAttribute.prototype
*
* @type {ComponentDatatype}
* @readonly
*
* @default {@link ComponentDatatype.UNSIGNED_BYTE}
*/
componentDatatype: {
get: function() {
return ComponentDatatype_default.UNSIGNED_BYTE;
}
},
/**
* The number of components in the attributes, i.e., {@link ColorGeometryInstanceAttribute#value}.
*
* @memberof ColorGeometryInstanceAttribute.prototype
*
* @type {number}
* @readonly
*
* @default 4
*/
componentsPerAttribute: {
get: function() {
return 4;
}
},
/**
* When true and componentDatatype is an integer format,
* indicate that the components should be mapped to the range [0, 1] (unsigned)
* or [-1, 1] (signed) when they are accessed as floating-point for rendering.
*
* @memberof ColorGeometryInstanceAttribute.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
normalize: {
get: function() {
return true;
}
}
});
ColorGeometryInstanceAttribute.fromColor = function(color) {
if (!defined_default(color)) {
throw new DeveloperError_default("color is required.");
}
return new ColorGeometryInstanceAttribute(
color.red,
color.green,
color.blue,
color.alpha
);
};
ColorGeometryInstanceAttribute.toValue = function(color, result) {
if (!defined_default(color)) {
throw new DeveloperError_default("color is required.");
}
if (!defined_default(result)) {
return new Uint8Array(color.toBytes());
}
return color.toBytes(result);
};
ColorGeometryInstanceAttribute.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left.value[0] === right.value[0] && left.value[1] === right.value[1] && left.value[2] === right.value[2] && left.value[3] === right.value[3];
};
var ColorGeometryInstanceAttribute_default = ColorGeometryInstanceAttribute;
// packages/engine/Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js
var import_InlineWorkers302 = __toESM(require_InlineWorkers(), 1);
function DistanceDisplayConditionGeometryInstanceAttribute(near, far) {
near = near ?? 0;
far = far ?? Number.MAX_VALUE;
if (far <= near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
this.value = new Float32Array([near, far]);
}
Object.defineProperties(
DistanceDisplayConditionGeometryInstanceAttribute.prototype,
{
/**
* The datatype of each component in the attribute, e.g., individual elements in
* {@link DistanceDisplayConditionGeometryInstanceAttribute#value}.
*
* @memberof DistanceDisplayConditionGeometryInstanceAttribute.prototype
*
* @type {ComponentDatatype}
* @readonly
*
* @default {@link ComponentDatatype.FLOAT}
*/
componentDatatype: {
get: function() {
return ComponentDatatype_default.FLOAT;
}
},
/**
* The number of components in the attributes, i.e., {@link DistanceDisplayConditionGeometryInstanceAttribute#value}.
*
* @memberof DistanceDisplayConditionGeometryInstanceAttribute.prototype
*
* @type {number}
* @readonly
*
* @default 3
*/
componentsPerAttribute: {
get: function() {
return 2;
}
},
/**
* When true and componentDatatype is an integer format,
* indicate that the components should be mapped to the range [0, 1] (unsigned)
* or [-1, 1] (signed) when they are accessed as floating-point for rendering.
*
* @memberof DistanceDisplayConditionGeometryInstanceAttribute.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
normalize: {
get: function() {
return false;
}
}
}
);
DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition = function(distanceDisplayCondition) {
if (!defined_default(distanceDisplayCondition)) {
throw new DeveloperError_default("distanceDisplayCondition is required.");
}
if (distanceDisplayCondition.far <= distanceDisplayCondition.near) {
throw new DeveloperError_default(
"distanceDisplayCondition.far distance must be greater than distanceDisplayCondition.near distance."
);
}
return new DistanceDisplayConditionGeometryInstanceAttribute(
distanceDisplayCondition.near,
distanceDisplayCondition.far
);
};
DistanceDisplayConditionGeometryInstanceAttribute.toValue = function(distanceDisplayCondition, result) {
if (!defined_default(distanceDisplayCondition)) {
throw new DeveloperError_default("distanceDisplayCondition is required.");
}
if (!defined_default(result)) {
return new Float32Array([
distanceDisplayCondition.near,
distanceDisplayCondition.far
]);
}
result[0] = distanceDisplayCondition.near;
result[1] = distanceDisplayCondition.far;
return result;
};
var DistanceDisplayConditionGeometryInstanceAttribute_default = DistanceDisplayConditionGeometryInstanceAttribute;
// packages/engine/Source/Core/GeometryInstance.js
var import_InlineWorkers303 = __toESM(require_InlineWorkers(), 1);
function GeometryInstance(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
if (!defined_default(options.geometry)) {
throw new DeveloperError_default("options.geometry is required.");
}
this.geometry = options.geometry;
this.modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this.id = options.id;
this.pickPrimitive = options.pickPrimitive;
this.attributes = options.attributes ?? {};
this.westHemisphereGeometry = void 0;
this.eastHemisphereGeometry = void 0;
}
var GeometryInstance_default = GeometryInstance;
// packages/engine/Source/Core/Iso8601.js
var import_InlineWorkers305 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/TimeInterval.js
var import_InlineWorkers304 = __toESM(require_InlineWorkers(), 1);
function TimeInterval(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.start = defined_default(options.start) ? JulianDate_default.clone(options.start) : new JulianDate_default();
this.stop = defined_default(options.stop) ? JulianDate_default.clone(options.stop) : new JulianDate_default();
this.data = options.data;
this.isStartIncluded = options.isStartIncluded ?? true;
this.isStopIncluded = options.isStopIncluded ?? true;
}
Object.defineProperties(TimeInterval.prototype, {
/**
* Gets whether or not this interval is empty.
* @memberof TimeInterval.prototype
* @type {boolean}
* @readonly
*/
isEmpty: {
get: function() {
const stopComparedToStart = JulianDate_default.compare(this.stop, this.start);
return stopComparedToStart < 0 || stopComparedToStart === 0 && (!this.isStartIncluded || !this.isStopIncluded);
}
}
});
var scratchInterval = {
start: void 0,
stop: void 0,
isStartIncluded: void 0,
isStopIncluded: void 0,
data: void 0
};
TimeInterval.fromIso8601 = function(options, result) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.string("options.iso8601", options.iso8601);
const dates = options.iso8601.split("/");
if (dates.length !== 2) {
throw new DeveloperError_default(
"options.iso8601 is an invalid ISO 8601 interval."
);
}
const start = JulianDate_default.fromIso8601(dates[0]);
const stop2 = JulianDate_default.fromIso8601(dates[1]);
const isStartIncluded = options.isStartIncluded ?? true;
const isStopIncluded = options.isStopIncluded ?? true;
const data = options.data;
if (!defined_default(result)) {
scratchInterval.start = start;
scratchInterval.stop = stop2;
scratchInterval.isStartIncluded = isStartIncluded;
scratchInterval.isStopIncluded = isStopIncluded;
scratchInterval.data = data;
return new TimeInterval(scratchInterval);
}
result.start = start;
result.stop = stop2;
result.isStartIncluded = isStartIncluded;
result.isStopIncluded = isStopIncluded;
result.data = data;
return result;
};
TimeInterval.toIso8601 = function(timeInterval, precision) {
Check_default.typeOf.object("timeInterval", timeInterval);
return `${JulianDate_default.toIso8601(
timeInterval.start,
precision
)}/${JulianDate_default.toIso8601(timeInterval.stop, precision)}`;
};
TimeInterval.clone = function(timeInterval, result) {
if (!defined_default(timeInterval)) {
return void 0;
}
if (!defined_default(result)) {
return new TimeInterval(timeInterval);
}
result.start = timeInterval.start;
result.stop = timeInterval.stop;
result.isStartIncluded = timeInterval.isStartIncluded;
result.isStopIncluded = timeInterval.isStopIncluded;
result.data = timeInterval.data;
return result;
};
TimeInterval.equals = function(left, right, dataComparer) {
return left === right || defined_default(left) && defined_default(right) && (left.isEmpty && right.isEmpty || left.isStartIncluded === right.isStartIncluded && left.isStopIncluded === right.isStopIncluded && JulianDate_default.equals(left.start, right.start) && JulianDate_default.equals(left.stop, right.stop) && (left.data === right.data || defined_default(dataComparer) && dataComparer(left.data, right.data)));
};
TimeInterval.equalsEpsilon = function(left, right, epsilon, dataComparer) {
epsilon = epsilon ?? 0;
return left === right || defined_default(left) && defined_default(right) && (left.isEmpty && right.isEmpty || left.isStartIncluded === right.isStartIncluded && left.isStopIncluded === right.isStopIncluded && JulianDate_default.equalsEpsilon(left.start, right.start, epsilon) && JulianDate_default.equalsEpsilon(left.stop, right.stop, epsilon) && (left.data === right.data || defined_default(dataComparer) && dataComparer(left.data, right.data)));
};
TimeInterval.intersect = function(left, right, result, mergeCallback) {
Check_default.typeOf.object("left", left);
if (!defined_default(right)) {
return TimeInterval.clone(TimeInterval.EMPTY, result);
}
const leftStart = left.start;
const leftStop = left.stop;
const rightStart = right.start;
const rightStop = right.stop;
const intersectsStartRight = JulianDate_default.greaterThanOrEquals(rightStart, leftStart) && JulianDate_default.greaterThanOrEquals(leftStop, rightStart);
const intersectsStartLeft = !intersectsStartRight && JulianDate_default.lessThanOrEquals(rightStart, leftStart) && JulianDate_default.lessThanOrEquals(leftStart, rightStop);
if (!intersectsStartRight && !intersectsStartLeft) {
return TimeInterval.clone(TimeInterval.EMPTY, result);
}
const leftIsStartIncluded = left.isStartIncluded;
const leftIsStopIncluded = left.isStopIncluded;
const rightIsStartIncluded = right.isStartIncluded;
const rightIsStopIncluded = right.isStopIncluded;
const leftLessThanRight = JulianDate_default.lessThan(leftStop, rightStop);
if (!defined_default(result)) {
result = new TimeInterval();
}
result.start = intersectsStartRight ? rightStart : leftStart;
result.isStartIncluded = leftIsStartIncluded && rightIsStartIncluded || !JulianDate_default.equals(rightStart, leftStart) && (intersectsStartRight && rightIsStartIncluded || intersectsStartLeft && leftIsStartIncluded);
result.stop = leftLessThanRight ? leftStop : rightStop;
result.isStopIncluded = leftLessThanRight ? leftIsStopIncluded : leftIsStopIncluded && rightIsStopIncluded || !JulianDate_default.equals(rightStop, leftStop) && rightIsStopIncluded;
result.data = defined_default(mergeCallback) ? mergeCallback(left.data, right.data) : left.data;
return result;
};
TimeInterval.contains = function(timeInterval, julianDate) {
Check_default.typeOf.object("timeInterval", timeInterval);
Check_default.typeOf.object("julianDate", julianDate);
if (timeInterval.isEmpty) {
return false;
}
const startComparedToDate = JulianDate_default.compare(
timeInterval.start,
julianDate
);
if (startComparedToDate === 0) {
return timeInterval.isStartIncluded;
}
const dateComparedToStop = JulianDate_default.compare(julianDate, timeInterval.stop);
if (dateComparedToStop === 0) {
return timeInterval.isStopIncluded;
}
return startComparedToDate < 0 && dateComparedToStop < 0;
};
TimeInterval.prototype.clone = function(result) {
return TimeInterval.clone(this, result);
};
TimeInterval.prototype.equals = function(right, dataComparer) {
return TimeInterval.equals(this, right, dataComparer);
};
TimeInterval.prototype.equalsEpsilon = function(right, epsilon, dataComparer) {
return TimeInterval.equalsEpsilon(this, right, epsilon, dataComparer);
};
TimeInterval.prototype.toString = function() {
return TimeInterval.toIso8601(this);
};
TimeInterval.EMPTY = Object.freeze(
new TimeInterval({
start: new JulianDate_default(),
stop: new JulianDate_default(),
isStartIncluded: false,
isStopIncluded: false
})
);
var TimeInterval_default = TimeInterval;
// packages/engine/Source/Core/Iso8601.js
var MINIMUM_VALUE = Object.freeze(
JulianDate_default.fromIso8601("0000-01-01T00:00:00Z")
);
var MAXIMUM_VALUE = Object.freeze(
JulianDate_default.fromIso8601("9999-12-31T24:00:00Z")
);
var MAXIMUM_INTERVAL = Object.freeze(
new TimeInterval_default({
start: MINIMUM_VALUE,
stop: MAXIMUM_VALUE
})
);
var Iso8601 = {
/**
* A {@link JulianDate} representing the earliest time representable by an ISO8601 date.
* This is equivalent to the date string '0000-01-01T00:00:00Z'
*
* @type {JulianDate}
* @constant
*/
MINIMUM_VALUE,
/**
* A {@link JulianDate} representing the latest time representable by an ISO8601 date.
* This is equivalent to the date string '9999-12-31T24:00:00Z'
*
* @type {JulianDate}
* @constant
*/
MAXIMUM_VALUE,
/**
* A {@link TimeInterval} representing the largest interval representable by an ISO8601 interval.
* This is equivalent to the interval string '0000-01-01T00:00:00Z/9999-12-31T24:00:00Z'
*
* @type {TimeInterval}
* @constant
*/
MAXIMUM_INTERVAL
};
var Iso8601_default = Iso8601;
// packages/engine/Source/Core/OffsetGeometryInstanceAttribute.js
var import_InlineWorkers306 = __toESM(require_InlineWorkers(), 1);
function OffsetGeometryInstanceAttribute(x, y, z) {
x = x ?? 0;
y = y ?? 0;
z = z ?? 0;
this.value = new Float32Array([x, y, z]);
}
Object.defineProperties(OffsetGeometryInstanceAttribute.prototype, {
/**
* The datatype of each component in the attribute, e.g., individual elements in
* {@link OffsetGeometryInstanceAttribute#value}.
*
* @memberof OffsetGeometryInstanceAttribute.prototype
*
* @type {ComponentDatatype}
* @readonly
*
* @default {@link ComponentDatatype.FLOAT}
*/
componentDatatype: {
get: function() {
return ComponentDatatype_default.FLOAT;
}
},
/**
* The number of components in the attributes, i.e., {@link OffsetGeometryInstanceAttribute#value}.
*
* @memberof OffsetGeometryInstanceAttribute.prototype
*
* @type {number}
* @readonly
*
* @default 3
*/
componentsPerAttribute: {
get: function() {
return 3;
}
},
/**
* When true and componentDatatype is an integer format,
* indicate that the components should be mapped to the range [0, 1] (unsigned)
* or [-1, 1] (signed) when they are accessed as floating-point for rendering.
*
* @memberof OffsetGeometryInstanceAttribute.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
normalize: {
get: function() {
return false;
}
}
});
OffsetGeometryInstanceAttribute.fromCartesian3 = function(offset) {
Check_default.defined("offset", offset);
return new OffsetGeometryInstanceAttribute(offset.x, offset.y, offset.z);
};
OffsetGeometryInstanceAttribute.toValue = function(offset, result) {
Check_default.defined("offset", offset);
if (!defined_default(result)) {
result = new Float32Array([offset.x, offset.y, offset.z]);
}
result[0] = offset.x;
result[1] = offset.y;
result[2] = offset.z;
return result;
};
var OffsetGeometryInstanceAttribute_default = OffsetGeometryInstanceAttribute;
// packages/engine/Source/Core/ShowGeometryInstanceAttribute.js
var import_InlineWorkers307 = __toESM(require_InlineWorkers(), 1);
function ShowGeometryInstanceAttribute(show) {
show = show ?? true;
this.value = ShowGeometryInstanceAttribute.toValue(show);
}
Object.defineProperties(ShowGeometryInstanceAttribute.prototype, {
/**
* The datatype of each component in the attribute, e.g., individual elements in
* {@link ColorGeometryInstanceAttribute#value}.
*
* @memberof ShowGeometryInstanceAttribute.prototype
*
* @type {ComponentDatatype}
* @readonly
*
* @default {@link ComponentDatatype.UNSIGNED_BYTE}
*/
componentDatatype: {
get: function() {
return ComponentDatatype_default.UNSIGNED_BYTE;
}
},
/**
* The number of components in the attributes, i.e., {@link ColorGeometryInstanceAttribute#value}.
*
* @memberof ShowGeometryInstanceAttribute.prototype
*
* @type {number}
* @readonly
*
* @default 1
*/
componentsPerAttribute: {
get: function() {
return 1;
}
},
/**
* When true and componentDatatype is an integer format,
* indicate that the components should be mapped to the range [0, 1] (unsigned)
* or [-1, 1] (signed) when they are accessed as floating-point for rendering.
*
* @memberof ShowGeometryInstanceAttribute.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
normalize: {
get: function() {
return false;
}
}
});
ShowGeometryInstanceAttribute.toValue = function(show, result) {
if (!defined_default(show)) {
throw new DeveloperError_default("show is required.");
}
if (!defined_default(result)) {
return new Uint8Array([show]);
}
result[0] = show;
return result;
};
var ShowGeometryInstanceAttribute_default = ShowGeometryInstanceAttribute;
// packages/engine/Source/Scene/MaterialAppearance.js
var import_InlineWorkers339 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Appearances/AllMaterialAppearanceFS.js
var import_InlineWorkers308 = __toESM(require_InlineWorkers(), 1);
var AllMaterialAppearanceFS_default = "in vec3 v_positionEC;\nin vec3 v_normalEC;\nin vec3 v_tangentEC;\nin vec3 v_bitangentEC;\nin vec2 v_st;\n\nvoid main()\n{\n vec3 positionToEyeEC = -v_positionEC;\n mat3 tangentToEyeMatrix = czm_tangentToEyeSpaceMatrix(v_normalEC, v_tangentEC, v_bitangentEC);\n\n vec3 normalEC = normalize(v_normalEC);\n#ifdef FACE_FORWARD\n normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\n#endif\n\n czm_materialInput materialInput;\n materialInput.normalEC = normalEC;\n materialInput.tangentToEyeMatrix = tangentToEyeMatrix;\n materialInput.positionToEyeEC = positionToEyeEC;\n materialInput.st = v_st;\n czm_material material = czm_getMaterial(materialInput);\n\n#ifdef FLAT\n out_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n#else\n out_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\n#endif\n}\n";
// packages/engine/Source/Shaders/Appearances/AllMaterialAppearanceVS.js
var import_InlineWorkers309 = __toESM(require_InlineWorkers(), 1);
var AllMaterialAppearanceVS_default = "in vec3 position3DHigh;\nin vec3 position3DLow;\nin vec3 normal;\nin vec3 tangent;\nin vec3 bitangent;\nin vec2 st;\nin float batchId;\n\nout vec3 v_positionEC;\nout vec3 v_normalEC;\nout vec3 v_tangentEC;\nout vec3 v_bitangentEC;\nout vec2 v_st;\n\nvoid main()\n{\n vec4 p = czm_computePosition();\n\n v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates\n v_normalEC = czm_normal * normal; // normal in eye coordinates\n v_tangentEC = czm_normal * tangent; // tangent in eye coordinates\n v_bitangentEC = czm_normal * bitangent; // bitangent in eye coordinates\n v_st = st;\n\n gl_Position = czm_modelViewProjectionRelativeToEye * p;\n}\n";
// packages/engine/Source/Shaders/Appearances/BasicMaterialAppearanceFS.js
var import_InlineWorkers310 = __toESM(require_InlineWorkers(), 1);
var BasicMaterialAppearanceFS_default = "in vec3 v_positionEC;\nin vec3 v_normalEC;\n\nvoid main()\n{\n vec3 positionToEyeEC = -v_positionEC;\n\n vec3 normalEC = normalize(v_normalEC);\n#ifdef FACE_FORWARD\n normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\n#endif\n\n czm_materialInput materialInput;\n materialInput.normalEC = normalEC;\n materialInput.positionToEyeEC = positionToEyeEC;\n czm_material material = czm_getMaterial(materialInput);\n\n#ifdef FLAT\n out_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n#else\n out_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\n#endif\n}\n";
// packages/engine/Source/Shaders/Appearances/BasicMaterialAppearanceVS.js
var import_InlineWorkers311 = __toESM(require_InlineWorkers(), 1);
var BasicMaterialAppearanceVS_default = "in vec3 position3DHigh;\nin vec3 position3DLow;\nin vec3 normal;\nin float batchId;\n\nout vec3 v_positionEC;\nout vec3 v_normalEC;\n\nvoid main()\n{\n vec4 p = czm_computePosition();\n\n v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates\n v_normalEC = czm_normal * normal; // normal in eye coordinates\n\n gl_Position = czm_modelViewProjectionRelativeToEye * p;\n}\n";
// packages/engine/Source/Shaders/Appearances/TexturedMaterialAppearanceFS.js
var import_InlineWorkers312 = __toESM(require_InlineWorkers(), 1);
var TexturedMaterialAppearanceFS_default = "in vec3 v_positionEC;\nin vec3 v_normalEC;\nin vec2 v_st;\n\nvoid main()\n{\n vec3 positionToEyeEC = -v_positionEC;\n\n vec3 normalEC = normalize(v_normalEC);\n#ifdef FACE_FORWARD\n normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\n#endif\n\n czm_materialInput materialInput;\n materialInput.normalEC = normalEC;\n materialInput.positionToEyeEC = positionToEyeEC;\n materialInput.st = v_st;\n czm_material material = czm_getMaterial(materialInput);\n\n#ifdef FLAT\n out_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n#else\n out_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\n#endif\n}\n";
// packages/engine/Source/Shaders/Appearances/TexturedMaterialAppearanceVS.js
var import_InlineWorkers313 = __toESM(require_InlineWorkers(), 1);
var TexturedMaterialAppearanceVS_default = "in vec3 position3DHigh;\nin vec3 position3DLow;\nin vec3 normal;\nin vec2 st;\nin float batchId;\n\nout vec3 v_positionEC;\nout vec3 v_normalEC;\nout vec2 v_st;\n\nvoid main()\n{\n vec4 p = czm_computePosition();\n\n v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates\n v_normalEC = czm_normal * normal; // normal in eye coordinates\n v_st = st;\n\n gl_Position = czm_modelViewProjectionRelativeToEye * p;\n}\n";
// packages/engine/Source/Scene/Appearance.js
var import_InlineWorkers318 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/BlendingState.js
var import_InlineWorkers316 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/BlendEquation.js
var import_InlineWorkers314 = __toESM(require_InlineWorkers(), 1);
var BlendEquation = {
/**
* Pixel values are added componentwise. This is used in additive blending for translucency.
*
* @type {number}
* @constant
*/
ADD: WebGLConstants_default.FUNC_ADD,
/**
* Pixel values are subtracted componentwise (source - destination). This is used in alpha blending for translucency.
*
* @type {number}
* @constant
*/
SUBTRACT: WebGLConstants_default.FUNC_SUBTRACT,
/**
* Pixel values are subtracted componentwise (destination - source).
*
* @type {number}
* @constant
*/
REVERSE_SUBTRACT: WebGLConstants_default.FUNC_REVERSE_SUBTRACT,
/**
* Pixel values are given to the minimum function (min(source, destination)).
*
* This equation operates on each pixel color component.
*
* @type {number}
* @constant
*/
MIN: WebGLConstants_default.MIN,
/**
* Pixel values are given to the maximum function (max(source, destination)).
*
* This equation operates on each pixel color component.
*
* @type {number}
* @constant
*/
MAX: WebGLConstants_default.MAX
};
var BlendEquation_default = Object.freeze(BlendEquation);
// packages/engine/Source/Scene/BlendFunction.js
var import_InlineWorkers315 = __toESM(require_InlineWorkers(), 1);
var BlendFunction = {
/**
* The blend factor is zero.
*
* @type {number}
* @constant
*/
ZERO: WebGLConstants_default.ZERO,
/**
* The blend factor is one.
*
* @type {number}
* @constant
*/
ONE: WebGLConstants_default.ONE,
/**
* The blend factor is the source color.
*
* @type {number}
* @constant
*/
SOURCE_COLOR: WebGLConstants_default.SRC_COLOR,
/**
* The blend factor is one minus the source color.
*
* @type {number}
* @constant
*/
ONE_MINUS_SOURCE_COLOR: WebGLConstants_default.ONE_MINUS_SRC_COLOR,
/**
* The blend factor is the destination color.
*
* @type {number}
* @constant
*/
DESTINATION_COLOR: WebGLConstants_default.DST_COLOR,
/**
* The blend factor is one minus the destination color.
*
* @type {number}
* @constant
*/
ONE_MINUS_DESTINATION_COLOR: WebGLConstants_default.ONE_MINUS_DST_COLOR,
/**
* The blend factor is the source alpha.
*
* @type {number}
* @constant
*/
SOURCE_ALPHA: WebGLConstants_default.SRC_ALPHA,
/**
* The blend factor is one minus the source alpha.
*
* @type {number}
* @constant
*/
ONE_MINUS_SOURCE_ALPHA: WebGLConstants_default.ONE_MINUS_SRC_ALPHA,
/**
* The blend factor is the destination alpha.
*
* @type {number}
* @constant
*/
DESTINATION_ALPHA: WebGLConstants_default.DST_ALPHA,
/**
* The blend factor is one minus the destination alpha.
*
* @type {number}
* @constant
*/
ONE_MINUS_DESTINATION_ALPHA: WebGLConstants_default.ONE_MINUS_DST_ALPHA,
/**
* The blend factor is the constant color.
*
* @type {number}
* @constant
*/
CONSTANT_COLOR: WebGLConstants_default.CONSTANT_COLOR,
/**
* The blend factor is one minus the constant color.
*
* @type {number}
* @constant
*/
ONE_MINUS_CONSTANT_COLOR: WebGLConstants_default.ONE_MINUS_CONSTANT_COLOR,
/**
* The blend factor is the constant alpha.
*
* @type {number}
* @constant
*/
CONSTANT_ALPHA: WebGLConstants_default.CONSTANT_ALPHA,
/**
* The blend factor is one minus the constant alpha.
*
* @type {number}
* @constant
*/
ONE_MINUS_CONSTANT_ALPHA: WebGLConstants_default.ONE_MINUS_CONSTANT_ALPHA,
/**
* The blend factor is the saturated source alpha.
*
* @type {number}
* @constant
*/
SOURCE_ALPHA_SATURATE: WebGLConstants_default.SRC_ALPHA_SATURATE
};
var BlendFunction_default = Object.freeze(BlendFunction);
// packages/engine/Source/Scene/BlendingState.js
var BlendingState = {
/**
* Blending is disabled.
*
* @type {object}
* @constant
*/
DISABLED: Object.freeze({
enabled: false
}),
/**
* Blending is enabled using alpha blending, source(source.alpha) + destination(1 - source.alpha).
*
* @type {object}
* @constant
*/
ALPHA_BLEND: Object.freeze({
enabled: true,
equationRgb: BlendEquation_default.ADD,
equationAlpha: BlendEquation_default.ADD,
functionSourceRgb: BlendFunction_default.SOURCE_ALPHA,
functionSourceAlpha: BlendFunction_default.ONE,
functionDestinationRgb: BlendFunction_default.ONE_MINUS_SOURCE_ALPHA,
functionDestinationAlpha: BlendFunction_default.ONE_MINUS_SOURCE_ALPHA
}),
/**
* Blending is enabled using alpha blending with premultiplied alpha, source + destination(1 - source.alpha).
*
* @type {object}
* @constant
*/
PRE_MULTIPLIED_ALPHA_BLEND: Object.freeze({
enabled: true,
equationRgb: BlendEquation_default.ADD,
equationAlpha: BlendEquation_default.ADD,
functionSourceRgb: BlendFunction_default.ONE,
functionSourceAlpha: BlendFunction_default.ONE,
functionDestinationRgb: BlendFunction_default.ONE_MINUS_SOURCE_ALPHA,
functionDestinationAlpha: BlendFunction_default.ONE_MINUS_SOURCE_ALPHA
}),
/**
* Blending is enabled using additive blending, source(source.alpha) + destination.
*
* @type {object}
* @constant
*/
ADDITIVE_BLEND: Object.freeze({
enabled: true,
equationRgb: BlendEquation_default.ADD,
equationAlpha: BlendEquation_default.ADD,
functionSourceRgb: BlendFunction_default.SOURCE_ALPHA,
functionSourceAlpha: BlendFunction_default.ONE,
functionDestinationRgb: BlendFunction_default.ONE,
functionDestinationAlpha: BlendFunction_default.ONE
})
};
var BlendingState_default = Object.freeze(BlendingState);
// packages/engine/Source/Scene/CullFace.js
var import_InlineWorkers317 = __toESM(require_InlineWorkers(), 1);
var CullFace = {
/**
* Front-facing triangles are culled.
*
* @type {number}
* @constant
*/
FRONT: WebGLConstants_default.FRONT,
/**
* Back-facing triangles are culled.
*
* @type {number}
* @constant
*/
BACK: WebGLConstants_default.BACK,
/**
* Both front-facing and back-facing triangles are culled.
*
* @type {number}
* @constant
*/
FRONT_AND_BACK: WebGLConstants_default.FRONT_AND_BACK
};
var CullFace_default = Object.freeze(CullFace);
// packages/engine/Source/Scene/Appearance.js
function Appearance(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.material = options.material;
this.translucent = options.translucent ?? true;
this._vertexShaderSource = options.vertexShaderSource;
this._fragmentShaderSource = options.fragmentShaderSource;
this._renderState = options.renderState;
this._closed = options.closed ?? false;
}
Object.defineProperties(Appearance.prototype, {
/**
* The GLSL source code for the vertex shader.
*
* @memberof Appearance.prototype
*
* @type {string}
* @readonly
*/
vertexShaderSource: {
get: function() {
return this._vertexShaderSource;
}
},
/**
* The GLSL source code for the fragment shader. The full fragment shader
* source is built procedurally taking into account the {@link Appearance#material}.
* Use {@link Appearance#getFragmentShaderSource} to get the full source.
*
* @memberof Appearance.prototype
*
* @type {string}
* @readonly
*/
fragmentShaderSource: {
get: function() {
return this._fragmentShaderSource;
}
},
/**
* The WebGL fixed-function state to use when rendering the geometry.
*
* @memberof Appearance.prototype
*
* @type {object}
* @readonly
*/
renderState: {
get: function() {
return this._renderState;
}
},
/**
* When true, the geometry is expected to be closed.
*
* @memberof Appearance.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
closed: {
get: function() {
return this._closed;
}
}
});
Appearance.prototype.getFragmentShaderSource = function() {
const parts = [];
if (this.flat) {
parts.push("#define FLAT");
}
if (this.faceForward) {
parts.push("#define FACE_FORWARD");
}
if (defined_default(this.material)) {
parts.push(this.material.shaderSource);
}
parts.push(this.fragmentShaderSource);
return parts.join("\n");
};
Appearance.prototype.isTranslucent = function() {
return defined_default(this.material) && this.material.isTranslucent() || !defined_default(this.material) && this.translucent;
};
Appearance.prototype.getRenderState = function() {
const translucent = this.isTranslucent();
const rs = clone_default(this.renderState, false);
if (translucent) {
rs.depthMask = false;
rs.blending = BlendingState_default.ALPHA_BLEND;
} else {
rs.depthMask = true;
}
return rs;
};
Appearance.getDefaultRenderState = function(translucent, closed, existing) {
let rs = {
depthTest: {
enabled: true
}
};
if (translucent) {
rs.depthMask = false;
rs.blending = BlendingState_default.ALPHA_BLEND;
}
if (closed) {
rs.cull = {
enabled: true,
face: CullFace_default.BACK
};
}
if (defined_default(existing)) {
rs = combine_default(existing, rs, true);
}
return rs;
};
var Appearance_default = Appearance;
// packages/engine/Source/Scene/Material.js
var import_InlineWorkers338 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Materials/AspectRampMaterial.js
var import_InlineWorkers319 = __toESM(require_InlineWorkers(), 1);
var AspectRampMaterial_default = "uniform sampler2D image;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n vec4 rampColor = texture(image, vec2(materialInput.aspect / (2.0 * czm_pi), 0.5));\n rampColor = czm_gammaCorrect(rampColor);\n material.diffuse = rampColor.rgb;\n material.alpha = rampColor.a;\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/BumpMapMaterial.js
var import_InlineWorkers320 = __toESM(require_InlineWorkers(), 1);
var BumpMapMaterial_default = "uniform sampler2D image;\nuniform float strength;\nuniform vec2 repeat;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n vec2 st = materialInput.st;\n\n vec2 centerPixel = fract(repeat * st);\n float centerBump = texture(image, centerPixel).channel;\n\n float imageWidth = float(imageDimensions.x);\n vec2 rightPixel = fract(repeat * (st + vec2(1.0 / imageWidth, 0.0)));\n float rightBump = texture(image, rightPixel).channel;\n\n float imageHeight = float(imageDimensions.y);\n vec2 leftPixel = fract(repeat * (st + vec2(0.0, 1.0 / imageHeight)));\n float topBump = texture(image, leftPixel).channel;\n\n vec3 normalTangentSpace = normalize(vec3(centerBump - rightBump, centerBump - topBump, clamp(1.0 - strength, 0.1, 1.0)));\n vec3 normalEC = materialInput.tangentToEyeMatrix * normalTangentSpace;\n\n material.normal = normalEC;\n material.diffuse = vec3(0.01);\n\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/CheckerboardMaterial.js
var import_InlineWorkers321 = __toESM(require_InlineWorkers(), 1);
var CheckerboardMaterial_default = "uniform vec4 lightColor;\nuniform vec4 darkColor;\nuniform vec2 repeat;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n vec2 st = materialInput.st;\n\n // From Stefan Gustavson's Procedural Textures in GLSL in OpenGL Insights\n float b = mod(floor(repeat.s * st.s) + floor(repeat.t * st.t), 2.0); // 0.0 or 1.0\n\n // Find the distance from the closest separator (region between two colors)\n float scaledWidth = fract(repeat.s * st.s);\n scaledWidth = abs(scaledWidth - floor(scaledWidth + 0.5));\n float scaledHeight = fract(repeat.t * st.t);\n scaledHeight = abs(scaledHeight - floor(scaledHeight + 0.5));\n float value = min(scaledWidth, scaledHeight);\n\n vec4 currentColor = mix(lightColor, darkColor, b);\n vec4 color = czm_antialias(lightColor, darkColor, currentColor, value, 0.03);\n\n color = czm_gammaCorrect(color);\n material.diffuse = color.rgb;\n material.alpha = color.a;\n\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/DotMaterial.js
var import_InlineWorkers322 = __toESM(require_InlineWorkers(), 1);
var DotMaterial_default = "uniform vec4 lightColor;\nuniform vec4 darkColor;\nuniform vec2 repeat;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n // From Stefan Gustavson's Procedural Textures in GLSL in OpenGL Insights\n float b = smoothstep(0.3, 0.32, length(fract(repeat * materialInput.st) - 0.5)); // 0.0 or 1.0\n\n vec4 color = mix(lightColor, darkColor, b);\n color = czm_gammaCorrect(color);\n material.diffuse = color.rgb;\n material.alpha = color.a;\n\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/ElevationBandMaterial.js
var import_InlineWorkers323 = __toESM(require_InlineWorkers(), 1);
var ElevationBandMaterial_default = "uniform sampler2D heights;\nuniform sampler2D colors;\n\n// This material expects heights to be sorted from lowest to highest.\n\nfloat getHeight(int idx, float invTexSize)\n{\n vec2 uv = vec2((float(idx) + 0.5) * invTexSize, 0.5);\n#ifdef OES_texture_float\n return texture(heights, uv).x;\n#else\n return czm_unpackFloat(texture(heights, uv));\n#endif\n}\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n float height = materialInput.height;\n float invTexSize = 1.0 / float(heightsDimensions.x);\n\n float minHeight = getHeight(0, invTexSize);\n float maxHeight = getHeight(heightsDimensions.x - 1, invTexSize);\n\n // early-out when outside the height range\n if (height < minHeight || height > maxHeight) {\n material.diffuse = vec3(0.0);\n material.alpha = 0.0;\n return material;\n }\n\n // Binary search to find heights above and below.\n int idxBelow = 0;\n int idxAbove = heightsDimensions.x;\n float heightBelow = minHeight;\n float heightAbove = maxHeight;\n\n // while loop not allowed, so use for loop with max iterations.\n // maxIterations of 16 supports a texture size up to 65536 (2^16).\n const int maxIterations = 16;\n for (int i = 0; i < maxIterations; i++) {\n if (idxBelow >= idxAbove - 1) {\n break;\n }\n\n int idxMid = (idxBelow + idxAbove) / 2;\n float heightTex = getHeight(idxMid, invTexSize);\n\n if (height > heightTex) {\n idxBelow = idxMid;\n heightBelow = heightTex;\n } else {\n idxAbove = idxMid;\n heightAbove = heightTex;\n }\n }\n\n float lerper = heightBelow == heightAbove ? 1.0 : (height - heightBelow) / (heightAbove - heightBelow);\n vec2 colorUv = vec2(invTexSize * (float(idxBelow) + 0.5 + lerper), 0.5);\n vec4 color = texture(colors, colorUv);\n\n // undo preumultiplied alpha\n if (color.a > 0.0) \n {\n color.rgb /= color.a;\n }\n \n color.rgb = czm_gammaCorrect(color.rgb);\n\n material.diffuse = color.rgb;\n material.alpha = color.a;\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/ElevationContourMaterial.js
var import_InlineWorkers324 = __toESM(require_InlineWorkers(), 1);
var ElevationContourMaterial_default = "uniform vec4 color;\nuniform float spacing;\nuniform float width;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n float distanceToContour = mod(materialInput.height, spacing);\n\n#if (__VERSION__ == 300 || defined(GL_OES_standard_derivatives))\n float dxc = abs(dFdx(materialInput.height));\n float dyc = abs(dFdy(materialInput.height));\n float dF = max(dxc, dyc) * czm_pixelRatio * width;\n float alpha = (distanceToContour < dF) ? 1.0 : 0.0;\n#else\n // If no derivatives available (IE 10?), use pixel ratio\n float alpha = (distanceToContour < (czm_pixelRatio * width)) ? 1.0 : 0.0;\n#endif\n\n vec4 outColor = czm_gammaCorrect(vec4(color.rgb, alpha * color.a));\n material.diffuse = outColor.rgb;\n material.alpha = outColor.a;\n\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/ElevationRampMaterial.js
var import_InlineWorkers325 = __toESM(require_InlineWorkers(), 1);
var ElevationRampMaterial_default = "uniform sampler2D image;\nuniform float minimumHeight;\nuniform float maximumHeight;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n float scaledHeight = clamp((materialInput.height - minimumHeight) / (maximumHeight - minimumHeight), 0.0, 1.0);\n vec4 rampColor = texture(image, vec2(scaledHeight, 0.5));\n rampColor = czm_gammaCorrect(rampColor);\n material.diffuse = rampColor.rgb;\n material.alpha = rampColor.a;\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/FadeMaterial.js
var import_InlineWorkers326 = __toESM(require_InlineWorkers(), 1);
var FadeMaterial_default = "uniform vec4 fadeInColor;\nuniform vec4 fadeOutColor;\nuniform float maximumDistance;\nuniform bool repeat;\nuniform vec2 fadeDirection;\nuniform vec2 time;\n\nfloat getTime(float t, float coord)\n{\n float scalar = 1.0 / maximumDistance;\n float q = distance(t, coord) * scalar;\n if (repeat)\n {\n float r = distance(t, coord + 1.0) * scalar;\n float s = distance(t, coord - 1.0) * scalar;\n q = min(min(r, s), q);\n }\n return clamp(q, 0.0, 1.0);\n}\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n vec2 st = materialInput.st;\n float s = getTime(time.x, st.s) * fadeDirection.s;\n float t = getTime(time.y, st.t) * fadeDirection.t;\n\n float u = length(vec2(s, t));\n vec4 color = mix(fadeInColor, fadeOutColor, u);\n\n color = czm_gammaCorrect(color);\n material.emission = color.rgb;\n material.alpha = color.a;\n\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/GridMaterial.js
var import_InlineWorkers327 = __toESM(require_InlineWorkers(), 1);
var GridMaterial_default = 'uniform vec4 color;\nuniform float cellAlpha;\nuniform vec2 lineCount;\nuniform vec2 lineThickness;\nuniform vec2 lineOffset;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n vec2 st = materialInput.st;\n\n float scaledWidth = fract(lineCount.s * st.s - lineOffset.s);\n scaledWidth = abs(scaledWidth - floor(scaledWidth + 0.5));\n float scaledHeight = fract(lineCount.t * st.t - lineOffset.t);\n scaledHeight = abs(scaledHeight - floor(scaledHeight + 0.5));\n\n float value;\n\n // Fuzz Factor - Controls blurriness of lines\n#if (__VERSION__ == 300 || defined(GL_OES_standard_derivatives))\n const float fuzz = 1.2;\n vec2 thickness = (lineThickness * czm_pixelRatio) - 1.0;\n\n // From "3D Engine Design for Virtual Globes" by Cozzi and Ring, Listing 4.13.\n vec2 dx = abs(dFdx(st));\n vec2 dy = abs(dFdy(st));\n vec2 dF = vec2(max(dx.s, dy.s), max(dx.t, dy.t)) * lineCount;\n value = min(\n smoothstep(dF.s * thickness.s, dF.s * (fuzz + thickness.s), scaledWidth),\n smoothstep(dF.t * thickness.t, dF.t * (fuzz + thickness.t), scaledHeight));\n#else\n // If no derivatives available (IE 10?), revert to view-dependent fuzz\n const float fuzz = 0.05;\n\n vec2 range = 0.5 - (lineThickness * 0.05);\n value = min(\n 1.0 - smoothstep(range.s, range.s + fuzz, scaledWidth),\n 1.0 - smoothstep(range.t, range.t + fuzz, scaledHeight));\n#endif\n\n // Edges taken from RimLightingMaterial.glsl\n // See http://www.fundza.com/rman_shaders/surface/fake_rim/fake_rim1.html\n float dRim = 1.0 - abs(dot(materialInput.normalEC, normalize(materialInput.positionToEyeEC)));\n float sRim = smoothstep(0.8, 1.0, dRim);\n value *= (1.0 - sRim);\n\n vec4 halfColor;\n halfColor.rgb = color.rgb * 0.5;\n halfColor.a = color.a * (1.0 - ((1.0 - cellAlpha) * value));\n halfColor = czm_gammaCorrect(halfColor);\n material.diffuse = halfColor.rgb;\n material.emission = halfColor.rgb;\n material.alpha = halfColor.a;\n\n return material;\n}\n';
// packages/engine/Source/Shaders/Materials/NormalMapMaterial.js
var import_InlineWorkers328 = __toESM(require_InlineWorkers(), 1);
var NormalMapMaterial_default = "uniform sampler2D image;\nuniform float strength;\nuniform vec2 repeat;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n \n vec4 textureValue = texture(image, fract(repeat * materialInput.st));\n vec3 normalTangentSpace = textureValue.channels;\n normalTangentSpace.xy = normalTangentSpace.xy * 2.0 - 1.0;\n normalTangentSpace.z = clamp(1.0 - strength, 0.1, 1.0);\n normalTangentSpace = normalize(normalTangentSpace);\n vec3 normalEC = materialInput.tangentToEyeMatrix * normalTangentSpace;\n \n material.normal = normalEC;\n \n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/PolylineArrowMaterial.js
var import_InlineWorkers329 = __toESM(require_InlineWorkers(), 1);
var PolylineArrowMaterial_default = "uniform vec4 color;\n\nfloat getPointOnLine(vec2 p0, vec2 p1, float x)\n{\n float slope = (p0.y - p1.y) / (p0.x - p1.x);\n return slope * (x - p0.x) + p0.y;\n}\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n vec2 st = materialInput.st;\n\n#if (__VERSION__ == 300 || defined(GL_OES_standard_derivatives))\n float base = 1.0 - abs(fwidth(st.s)) * 10.0 * czm_pixelRatio;\n#else\n // If no derivatives available (IE 10?), 2.5% of the line will be the arrow head\n float base = 0.975;\n#endif\n\n vec2 center = vec2(1.0, 0.5);\n float ptOnUpperLine = getPointOnLine(vec2(base, 1.0), center, st.s);\n float ptOnLowerLine = getPointOnLine(vec2(base, 0.0), center, st.s);\n\n float halfWidth = 0.15;\n float s = step(0.5 - halfWidth, st.t);\n s *= 1.0 - step(0.5 + halfWidth, st.t);\n s *= 1.0 - step(base, st.s);\n\n float t = step(base, materialInput.st.s);\n t *= 1.0 - step(ptOnUpperLine, st.t);\n t *= step(ptOnLowerLine, st.t);\n\n // Find the distance from the closest separator (region between two colors)\n float dist;\n if (st.s < base)\n {\n float d1 = abs(st.t - (0.5 - halfWidth));\n float d2 = abs(st.t - (0.5 + halfWidth));\n dist = min(d1, d2);\n }\n else\n {\n float d1 = czm_infinity;\n if (st.t < 0.5 - halfWidth && st.t > 0.5 + halfWidth)\n {\n d1 = abs(st.s - base);\n }\n float d2 = abs(st.t - ptOnUpperLine);\n float d3 = abs(st.t - ptOnLowerLine);\n dist = min(min(d1, d2), d3);\n }\n\n vec4 outsideColor = vec4(0.0);\n vec4 currentColor = mix(outsideColor, color, clamp(s + t, 0.0, 1.0));\n vec4 outColor = czm_antialias(outsideColor, color, currentColor, dist);\n\n outColor = czm_gammaCorrect(outColor);\n material.diffuse = outColor.rgb;\n material.alpha = outColor.a;\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/PolylineDashMaterial.js
var import_InlineWorkers330 = __toESM(require_InlineWorkers(), 1);
var PolylineDashMaterial_default = "uniform vec4 color;\nuniform vec4 gapColor;\nuniform float dashLength;\nuniform float dashPattern;\nin float v_polylineAngle;\n\nconst float maskLength = 16.0;\n\nmat2 rotate(float rad) {\n float c = cos(rad);\n float s = sin(rad);\n return mat2(\n c, s,\n -s, c\n );\n}\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n vec2 pos = rotate(v_polylineAngle) * gl_FragCoord.xy;\n\n // Get the relative position within the dash from 0 to 1\n float dashPosition = fract(pos.x / (dashLength * czm_pixelRatio));\n // Figure out the mask index.\n float maskIndex = floor(dashPosition * maskLength);\n // Test the bit mask.\n float maskTest = floor(dashPattern / pow(2.0, maskIndex));\n vec4 fragColor = (mod(maskTest, 2.0) < 1.0) ? gapColor : color;\n if (fragColor.a < 0.005) { // matches 0/255 and 1/255\n discard;\n }\n\n fragColor = czm_gammaCorrect(fragColor);\n material.emission = fragColor.rgb;\n material.alpha = fragColor.a;\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/PolylineGlowMaterial.js
var import_InlineWorkers331 = __toESM(require_InlineWorkers(), 1);
var PolylineGlowMaterial_default = "uniform vec4 color;\nuniform float glowPower;\nuniform float taperPower;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n vec2 st = materialInput.st;\n float glow = glowPower / abs(st.t - 0.5) - (glowPower / 0.5);\n\n if (taperPower <= 0.99999) {\n glow *= min(1.0, taperPower / (0.5 - st.s * 0.5) - (taperPower / 0.5));\n }\n\n vec4 fragColor;\n fragColor.rgb = max(vec3(glow - 1.0 + color.rgb), color.rgb);\n fragColor.a = clamp(0.0, 1.0, glow) * color.a;\n fragColor = czm_gammaCorrect(fragColor);\n\n material.emission = fragColor.rgb;\n material.alpha = fragColor.a;\n\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/PolylineOutlineMaterial.js
var import_InlineWorkers332 = __toESM(require_InlineWorkers(), 1);
var PolylineOutlineMaterial_default = "uniform vec4 color;\nuniform vec4 outlineColor;\nuniform float outlineWidth;\n\nin float v_width;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n vec2 st = materialInput.st;\n float halfInteriorWidth = 0.5 * (v_width - outlineWidth) / v_width;\n float b = step(0.5 - halfInteriorWidth, st.t);\n b *= 1.0 - step(0.5 + halfInteriorWidth, st.t);\n\n // Find the distance from the closest separator (region between two colors)\n float d1 = abs(st.t - (0.5 - halfInteriorWidth));\n float d2 = abs(st.t - (0.5 + halfInteriorWidth));\n float dist = min(d1, d2);\n\n vec4 currentColor = mix(outlineColor, color, b);\n vec4 outColor = czm_antialias(outlineColor, color, currentColor, dist);\n outColor = czm_gammaCorrect(outColor);\n\n material.diffuse = outColor.rgb;\n material.alpha = outColor.a;\n\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/RimLightingMaterial.js
var import_InlineWorkers333 = __toESM(require_InlineWorkers(), 1);
var RimLightingMaterial_default = "uniform vec4 color;\nuniform vec4 rimColor;\nuniform float width;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n // See http://www.fundza.com/rman_shaders/surface/fake_rim/fake_rim1.html\n float d = 1.0 - dot(materialInput.normalEC, normalize(materialInput.positionToEyeEC));\n float s = smoothstep(1.0 - width, 1.0, d);\n\n vec4 outColor = czm_gammaCorrect(color);\n vec4 outRimColor = czm_gammaCorrect(rimColor);\n\n material.diffuse = outColor.rgb;\n material.emission = outRimColor.rgb * s;\n material.alpha = mix(outColor.a, outRimColor.a, s);\n\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/SlopeRampMaterial.js
var import_InlineWorkers334 = __toESM(require_InlineWorkers(), 1);
var SlopeRampMaterial_default = "uniform sampler2D image;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n vec4 rampColor = texture(image, vec2(materialInput.slope / (czm_pi / 2.0), 0.5));\n rampColor = czm_gammaCorrect(rampColor);\n material.diffuse = rampColor.rgb;\n material.alpha = rampColor.a;\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/StripeMaterial.js
var import_InlineWorkers335 = __toESM(require_InlineWorkers(), 1);
var StripeMaterial_default = "uniform vec4 evenColor;\nuniform vec4 oddColor;\nuniform float offset;\nuniform float repeat;\nuniform bool horizontal;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n // Based on the Stripes Fragment Shader in the Orange Book (11.1.2)\n float coord = mix(materialInput.st.s, materialInput.st.t, float(horizontal));\n float value = fract((coord - offset) * (repeat * 0.5));\n float dist = min(value, min(abs(value - 0.5), 1.0 - value));\n\n vec4 currentColor = mix(evenColor, oddColor, step(0.5, value));\n vec4 color = czm_antialias(evenColor, oddColor, currentColor, dist);\n color = czm_gammaCorrect(color);\n\n material.diffuse = color.rgb;\n material.alpha = color.a;\n\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/WaterMaskMaterial.js
var import_InlineWorkers336 = __toESM(require_InlineWorkers(), 1);
var WaterMaskMaterial_default = "uniform vec4 waterColor;\nuniform vec4 landColor;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n vec4 outColor = mix(landColor, waterColor, materialInput.waterMask);\n outColor = czm_gammaCorrect(outColor);\n\n material.diffuse = outColor.rgb;\n material.alpha = outColor.a;\n\n return material;\n}\n";
// packages/engine/Source/Shaders/Materials/Water.js
var import_InlineWorkers337 = __toESM(require_InlineWorkers(), 1);
var Water_default = "// Thanks for the contribution Jonas\n// http://29a.ch/2012/7/19/webgl-terrain-rendering-water-fog\n\nuniform sampler2D specularMap;\nuniform sampler2D normalMap;\nuniform vec4 baseWaterColor;\nuniform vec4 blendColor;\nuniform float frequency;\nuniform float animationSpeed;\nuniform float amplitude;\nuniform float specularIntensity;\nuniform float fadeFactor;\n\nczm_material czm_getMaterial(czm_materialInput materialInput)\n{\n czm_material material = czm_getDefaultMaterial(materialInput);\n\n float time = czm_frameNumber * animationSpeed;\n\n // fade is a function of the distance from the fragment and the frequency of the waves\n float fade = max(1.0, (length(materialInput.positionToEyeEC) / 10000000000.0) * frequency * fadeFactor);\n\n float specularMapValue = texture(specularMap, materialInput.st).r;\n\n // note: not using directional motion at this time, just set the angle to 0.0;\n vec4 noise = czm_getWaterNoise(normalMap, materialInput.st * frequency, time, 0.0);\n vec3 normalTangentSpace = noise.xyz * vec3(1.0, 1.0, (1.0 / amplitude));\n\n // fade out the normal perturbation as we move further from the water surface\n normalTangentSpace.xy /= fade;\n\n // attempt to fade out the normal perturbation as we approach non water areas (low specular map value)\n normalTangentSpace = mix(vec3(0.0, 0.0, 50.0), normalTangentSpace, specularMapValue);\n\n normalTangentSpace = normalize(normalTangentSpace);\n\n // get ratios for alignment of the new normal vector with a vector perpendicular to the tangent plane\n float tsPerturbationRatio = clamp(dot(normalTangentSpace, vec3(0.0, 0.0, 1.0)), 0.0, 1.0);\n\n // fade out water effect as specular map value decreases\n material.alpha = mix(blendColor.a, baseWaterColor.a, specularMapValue) * specularMapValue;\n\n // base color is a blend of the water and non-water color based on the value from the specular map\n // may need a uniform blend factor to better control this\n material.diffuse = mix(blendColor.rgb, baseWaterColor.rgb, specularMapValue);\n\n // diffuse highlights are based on how perturbed the normal is\n material.diffuse += (0.1 * tsPerturbationRatio);\n\n material.diffuse = material.diffuse;\n\n material.normal = normalize(materialInput.tangentToEyeMatrix * normalTangentSpace);\n\n material.specular = specularIntensity;\n material.shininess = 10.0;\n\n return material;\n}\n";
// packages/engine/Source/Scene/Material.js
function Material(options) {
this.type = void 0;
this.shaderSource = void 0;
this.materials = void 0;
this.uniforms = void 0;
this._uniforms = void 0;
this.translucent = void 0;
this._minificationFilter = options.minificationFilter ?? TextureMinificationFilter_default.LINEAR;
this._magnificationFilter = options.magnificationFilter ?? TextureMagnificationFilter_default.LINEAR;
this._strict = void 0;
this._template = void 0;
this._count = void 0;
this._texturePaths = {};
this._loadedImages = [];
this._loadedCubeMaps = [];
this._textures = {};
this._updateFunctions = [];
this._defaultTexture = void 0;
initializeMaterial(options, this);
Object.defineProperties(this, {
type: {
value: this.type,
writable: false
}
});
if (!defined_default(Material._uniformList[this.type])) {
Material._uniformList[this.type] = Object.keys(this._uniforms);
}
}
Material._uniformList = {};
Material.fromType = function(type, uniforms) {
if (!defined_default(Material._materialCache.getMaterial(type))) {
throw new DeveloperError_default(`material with type '${type}' does not exist.`);
}
const material = new Material({
fabric: {
type
}
});
if (defined_default(uniforms)) {
for (const name in uniforms) {
if (uniforms.hasOwnProperty(name)) {
material.uniforms[name] = uniforms[name];
}
}
}
return material;
};
Material.prototype.isTranslucent = function() {
if (defined_default(this.translucent)) {
if (typeof this.translucent === "function") {
return this.translucent();
}
return this.translucent;
}
let translucent = true;
const funcs = this._translucentFunctions;
const length2 = funcs.length;
for (let i = 0; i < length2; ++i) {
const func = funcs[i];
if (typeof func === "function") {
translucent = translucent && func();
} else {
translucent = translucent && func;
}
if (!translucent) {
break;
}
}
return translucent;
};
Material.prototype.update = function(context) {
this._defaultTexture = context.defaultTexture;
let i;
let uniformId;
const loadedImages = this._loadedImages;
let length2 = loadedImages.length;
for (i = 0; i < length2; ++i) {
const loadedImage = loadedImages[i];
uniformId = loadedImage.id;
let image = loadedImage.image;
let mipLevels;
if (Array.isArray(image)) {
mipLevels = image.slice(1, image.length).map(function(mipLevel) {
return mipLevel.bufferView;
});
image = image[0];
}
const sampler = new Sampler_default({
minificationFilter: this._minificationFilter,
magnificationFilter: this._magnificationFilter
});
let texture;
if (defined_default(image.internalFormat)) {
texture = new Texture_default({
context,
pixelFormat: image.internalFormat,
width: image.width,
height: image.height,
source: {
arrayBufferView: image.bufferView,
mipLevels
},
sampler
});
} else {
texture = new Texture_default({
context,
source: image,
sampler
});
}
const oldTexture = this._textures[uniformId];
if (defined_default(oldTexture) && oldTexture !== this._defaultTexture) {
oldTexture.destroy();
}
this._textures[uniformId] = texture;
const uniformDimensionsName = `${uniformId}Dimensions`;
if (this.uniforms.hasOwnProperty(uniformDimensionsName)) {
const uniformDimensions = this.uniforms[uniformDimensionsName];
uniformDimensions.x = texture._width;
uniformDimensions.y = texture._height;
}
}
loadedImages.length = 0;
const loadedCubeMaps = this._loadedCubeMaps;
length2 = loadedCubeMaps.length;
for (i = 0; i < length2; ++i) {
const loadedCubeMap = loadedCubeMaps[i];
uniformId = loadedCubeMap.id;
const images = loadedCubeMap.images;
const cubeMap = new CubeMap_default({
context,
source: {
positiveX: images[0],
negativeX: images[1],
positiveY: images[2],
negativeY: images[3],
positiveZ: images[4],
negativeZ: images[5]
},
sampler: new Sampler_default({
minificationFilter: this._minificationFilter,
magnificationFilter: this._magnificationFilter
})
});
this._textures[uniformId] = cubeMap;
}
loadedCubeMaps.length = 0;
const updateFunctions2 = this._updateFunctions;
length2 = updateFunctions2.length;
for (i = 0; i < length2; ++i) {
updateFunctions2[i](this, context);
}
const subMaterials = this.materials;
for (const name in subMaterials) {
if (subMaterials.hasOwnProperty(name)) {
subMaterials[name].update(context);
}
}
};
Material.prototype.isDestroyed = function() {
return false;
};
Material.prototype.destroy = function() {
const textures = this._textures;
for (const texture in textures) {
if (textures.hasOwnProperty(texture)) {
const instance = textures[texture];
if (instance !== this._defaultTexture) {
instance.destroy();
}
}
}
const materials = this.materials;
for (const material in materials) {
if (materials.hasOwnProperty(material)) {
materials[material].destroy();
}
}
return destroyObject_default(this);
};
function initializeMaterial(options, result) {
options = options ?? Frozen_default.EMPTY_OBJECT;
result._strict = options.strict ?? false;
result._count = options.count ?? 0;
result._template = clone_default(options.fabric ?? Frozen_default.EMPTY_OBJECT);
result._template.uniforms = clone_default(
result._template.uniforms ?? Frozen_default.EMPTY_OBJECT
);
result._template.materials = clone_default(
result._template.materials ?? Frozen_default.EMPTY_OBJECT
);
result.type = defined_default(result._template.type) ? result._template.type : createGuid_default();
result.shaderSource = "";
result.materials = {};
result.uniforms = {};
result._uniforms = {};
result._translucentFunctions = [];
let translucent;
const cachedMaterial = Material._materialCache.getMaterial(result.type);
if (defined_default(cachedMaterial)) {
const template = clone_default(cachedMaterial.fabric, true);
result._template = combine_default(result._template, template, true);
translucent = cachedMaterial.translucent;
}
checkForTemplateErrors(result);
if (!defined_default(cachedMaterial)) {
Material._materialCache.addMaterial(result.type, result);
}
createMethodDefinition(result);
createUniforms(result);
createSubMaterials(result);
const defaultTranslucent = result._translucentFunctions.length === 0 ? true : void 0;
translucent = translucent ?? defaultTranslucent;
translucent = options.translucent ?? translucent;
if (defined_default(translucent)) {
if (typeof translucent === "function") {
const wrappedTranslucent = function() {
return translucent(result);
};
result._translucentFunctions.push(wrappedTranslucent);
} else {
result._translucentFunctions.push(translucent);
}
}
}
function checkForValidProperties(object2, properties, result, throwNotFound) {
if (defined_default(object2)) {
for (const property in object2) {
if (object2.hasOwnProperty(property)) {
const hasProperty = properties.indexOf(property) !== -1;
if (throwNotFound && !hasProperty || !throwNotFound && hasProperty) {
result(property, properties);
}
}
}
}
}
function invalidNameError(property, properties) {
let errorString = `fabric: property name '${property}' is not valid. It should be `;
for (let i = 0; i < properties.length; i++) {
const propertyName = `'${properties[i]}'`;
errorString += i === properties.length - 1 ? `or ${propertyName}.` : `${propertyName}, `;
}
throw new DeveloperError_default(errorString);
}
function duplicateNameError(property, properties) {
const errorString = `fabric: uniforms and materials cannot share the same property '${property}'`;
throw new DeveloperError_default(errorString);
}
var templateProperties = [
"type",
"materials",
"uniforms",
"components",
"source"
];
var componentProperties = [
"diffuse",
"specular",
"shininess",
"normal",
"emission",
"alpha"
];
function checkForTemplateErrors(material) {
const template = material._template;
const uniforms = template.uniforms;
const materials = template.materials;
const components = template.components;
if (defined_default(components) && defined_default(template.source)) {
throw new DeveloperError_default(
"fabric: cannot have source and components in the same template."
);
}
checkForValidProperties(template, templateProperties, invalidNameError, true);
checkForValidProperties(
components,
componentProperties,
invalidNameError,
true
);
const materialNames = [];
for (const property in materials) {
if (materials.hasOwnProperty(property)) {
materialNames.push(property);
}
}
checkForValidProperties(uniforms, materialNames, duplicateNameError, false);
}
function isMaterialFused(shaderComponent, material) {
const materials = material._template.materials;
for (const subMaterialId in materials) {
if (materials.hasOwnProperty(subMaterialId)) {
if (shaderComponent.indexOf(subMaterialId) > -1) {
return true;
}
}
}
return false;
}
function createMethodDefinition(material) {
const components = material._template.components;
const source = material._template.source;
if (defined_default(source)) {
material.shaderSource += `${source}
`;
} else {
material.shaderSource += "czm_material czm_getMaterial(czm_materialInput materialInput)\n{\n";
material.shaderSource += "czm_material material = czm_getDefaultMaterial(materialInput);\n";
if (defined_default(components)) {
const isMultiMaterial = Object.keys(material._template.materials).length > 0;
for (const component in components) {
if (components.hasOwnProperty(component)) {
if (component === "diffuse" || component === "emission") {
const isFusion = isMultiMaterial && isMaterialFused(components[component], material);
const componentSource = isFusion ? components[component] : `czm_gammaCorrect(${components[component]})`;
material.shaderSource += `material.${component} = ${componentSource};
`;
} else if (component === "alpha") {
material.shaderSource += `material.alpha = ${components.alpha};
`;
} else {
material.shaderSource += `material.${component} = ${components[component]};
`;
}
}
}
}
material.shaderSource += "return material;\n}\n";
}
}
var matrixMap = {
mat2: Matrix2_default,
mat3: Matrix3_default,
mat4: Matrix4_default
};
var ktx2Regex = /\.ktx2$/i;
function createTexture2DUpdateFunction(uniformId) {
let oldUniformValue;
return function(material, context) {
const uniforms = material.uniforms;
const uniformValue = uniforms[uniformId];
const uniformChanged = oldUniformValue !== uniformValue;
const uniformValueIsDefaultImage = !defined_default(uniformValue) || uniformValue === Material.DefaultImageId;
oldUniformValue = uniformValue;
let texture = material._textures[uniformId];
let uniformDimensionsName;
let uniformDimensions;
if (uniformValue instanceof HTMLVideoElement) {
if (uniformValue.readyState >= 2) {
if (uniformChanged && defined_default(texture)) {
if (texture !== context.defaultTexture) {
texture.destroy();
}
texture = void 0;
}
if (!defined_default(texture) || texture === context.defaultTexture) {
const sampler = new Sampler_default({
minificationFilter: material._minificationFilter,
magnificationFilter: material._magnificationFilter
});
texture = new Texture_default({
context,
source: uniformValue,
sampler
});
material._textures[uniformId] = texture;
return;
}
texture.copyFrom({
source: uniformValue
});
} else if (!defined_default(texture)) {
material._textures[uniformId] = context.defaultTexture;
}
return;
}
if (uniformValue instanceof Texture_default && uniformValue !== texture) {
material._texturePaths[uniformId] = void 0;
const tmp2 = material._textures[uniformId];
if (defined_default(tmp2) && tmp2 !== material._defaultTexture) {
tmp2.destroy();
}
material._textures[uniformId] = uniformValue;
uniformDimensionsName = `${uniformId}Dimensions`;
if (uniforms.hasOwnProperty(uniformDimensionsName)) {
uniformDimensions = uniforms[uniformDimensionsName];
uniformDimensions.x = uniformValue._width;
uniformDimensions.y = uniformValue._height;
}
return;
}
if (uniformChanged && defined_default(texture) && uniformValueIsDefaultImage) {
if (texture !== material._defaultTexture) {
texture.destroy();
}
texture = void 0;
}
if (!defined_default(texture)) {
material._texturePaths[uniformId] = void 0;
texture = material._textures[uniformId] = material._defaultTexture;
uniformDimensionsName = `${uniformId}Dimensions`;
if (uniforms.hasOwnProperty(uniformDimensionsName)) {
uniformDimensions = uniforms[uniformDimensionsName];
uniformDimensions.x = texture._width;
uniformDimensions.y = texture._height;
}
}
if (uniformValueIsDefaultImage) {
return;
}
const isResource = uniformValue instanceof Resource_default;
if (!defined_default(material._texturePaths[uniformId]) || isResource && uniformValue.url !== material._texturePaths[uniformId].url || !isResource && uniformValue !== material._texturePaths[uniformId]) {
if (typeof uniformValue === "string" || isResource) {
const resource = isResource ? uniformValue : Resource_default.createIfNeeded(uniformValue);
let promise;
if (ktx2Regex.test(resource.url)) {
promise = loadKTX2_default(resource.url);
} else {
promise = resource.fetchImage();
}
Promise.resolve(promise).then(function(image) {
material._loadedImages.push({
id: uniformId,
image
});
}).catch(function() {
if (defined_default(texture) && texture !== material._defaultTexture) {
texture.destroy();
}
material._textures[uniformId] = material._defaultTexture;
});
} else if (uniformValue instanceof HTMLCanvasElement || uniformValue instanceof HTMLImageElement || uniformValue instanceof ImageBitmap || uniformValue instanceof OffscreenCanvas) {
material._loadedImages.push({
id: uniformId,
image: uniformValue
});
}
material._texturePaths[uniformId] = uniformValue;
}
};
}
function createCubeMapUpdateFunction(uniformId) {
return function(material, context) {
const uniformValue = material.uniforms[uniformId];
if (uniformValue instanceof CubeMap_default) {
const tmp2 = material._textures[uniformId];
if (tmp2 !== material._defaultTexture) {
tmp2.destroy();
}
material._texturePaths[uniformId] = void 0;
material._textures[uniformId] = uniformValue;
return;
}
if (!defined_default(material._textures[uniformId])) {
material._texturePaths[uniformId] = void 0;
material._textures[uniformId] = context.defaultCubeMap;
}
if (uniformValue === Material.DefaultCubeMapId) {
return;
}
const path = uniformValue.positiveX + uniformValue.negativeX + uniformValue.positiveY + uniformValue.negativeY + uniformValue.positiveZ + uniformValue.negativeZ;
if (path !== material._texturePaths[uniformId]) {
const promises = [
Resource_default.createIfNeeded(uniformValue.positiveX).fetchImage(),
Resource_default.createIfNeeded(uniformValue.negativeX).fetchImage(),
Resource_default.createIfNeeded(uniformValue.positiveY).fetchImage(),
Resource_default.createIfNeeded(uniformValue.negativeY).fetchImage(),
Resource_default.createIfNeeded(uniformValue.positiveZ).fetchImage(),
Resource_default.createIfNeeded(uniformValue.negativeZ).fetchImage()
];
Promise.all(promises).then(function(images) {
material._loadedCubeMaps.push({
id: uniformId,
images
});
});
material._texturePaths[uniformId] = path;
}
};
}
function createUniforms(material) {
const uniforms = material._template.uniforms;
for (const uniformId in uniforms) {
if (uniforms.hasOwnProperty(uniformId)) {
createUniform2(material, uniformId);
}
}
}
function createUniform2(material, uniformId) {
const strict = material._strict;
const materialUniforms = material._template.uniforms;
const uniformValue = materialUniforms[uniformId];
const uniformType = getUniformType(uniformValue);
if (!defined_default(uniformType)) {
throw new DeveloperError_default(
`fabric: uniform '${uniformId}' has invalid type.`
);
}
let replacedTokenCount;
if (uniformType === "channels") {
replacedTokenCount = replaceToken(material, uniformId, uniformValue, false);
if (replacedTokenCount === 0 && strict) {
throw new DeveloperError_default(
`strict: shader source does not use channels '${uniformId}'.`
);
}
} else {
if (uniformType === "sampler2D") {
const imageDimensionsUniformName = `${uniformId}Dimensions`;
if (getNumberOfTokens(material, imageDimensionsUniformName) > 0) {
materialUniforms[imageDimensionsUniformName] = {
type: "ivec3",
x: 1,
y: 1
};
createUniform2(material, imageDimensionsUniformName);
}
}
const uniformDeclarationRegex = new RegExp(
`uniform\\s+${uniformType}\\s+${uniformId}\\s*;`
);
if (!uniformDeclarationRegex.test(material.shaderSource)) {
const uniformDeclaration = `uniform ${uniformType} ${uniformId};`;
material.shaderSource = uniformDeclaration + material.shaderSource;
}
const newUniformId = `${uniformId}_${material._count++}`;
replacedTokenCount = replaceToken(material, uniformId, newUniformId);
if (replacedTokenCount === 1 && strict) {
throw new DeveloperError_default(
`strict: shader source does not use uniform '${uniformId}'.`
);
}
material.uniforms[uniformId] = uniformValue;
if (uniformType === "sampler2D") {
material._uniforms[newUniformId] = function() {
return material._textures[uniformId];
};
material._updateFunctions.push(createTexture2DUpdateFunction(uniformId));
} else if (uniformType === "samplerCube") {
material._uniforms[newUniformId] = function() {
return material._textures[uniformId];
};
material._updateFunctions.push(createCubeMapUpdateFunction(uniformId));
} else if (uniformType.indexOf("mat") !== -1) {
const scratchMatrix8 = new matrixMap[uniformType]();
material._uniforms[newUniformId] = function() {
return matrixMap[uniformType].fromColumnMajorArray(
material.uniforms[uniformId],
scratchMatrix8
);
};
} else {
material._uniforms[newUniformId] = function() {
return material.uniforms[uniformId];
};
}
}
}
function getUniformType(uniformValue) {
let uniformType = uniformValue.type;
if (!defined_default(uniformType)) {
const type = typeof uniformValue;
if (type === "number") {
uniformType = "float";
} else if (type === "boolean") {
uniformType = "bool";
} else if (type === "string" || uniformValue instanceof Resource_default || uniformValue instanceof HTMLCanvasElement || uniformValue instanceof HTMLImageElement || uniformValue instanceof ImageBitmap || uniformValue instanceof OffscreenCanvas) {
if (/^([rgba]){1,4}$/i.test(uniformValue)) {
uniformType = "channels";
} else if (uniformValue === Material.DefaultCubeMapId) {
uniformType = "samplerCube";
} else {
uniformType = "sampler2D";
}
} else if (type === "object") {
if (Array.isArray(uniformValue)) {
if (uniformValue.length === 4 || uniformValue.length === 9 || uniformValue.length === 16) {
uniformType = `mat${Math.sqrt(uniformValue.length)}`;
}
} else {
let numAttributes = 0;
for (const attribute in uniformValue) {
if (uniformValue.hasOwnProperty(attribute)) {
numAttributes += 1;
}
}
if (numAttributes >= 2 && numAttributes <= 4) {
uniformType = `vec${numAttributes}`;
} else if (numAttributes === 6) {
uniformType = "samplerCube";
}
}
}
}
return uniformType;
}
function createSubMaterials(material) {
const strict = material._strict;
const subMaterialTemplates = material._template.materials;
for (const subMaterialId in subMaterialTemplates) {
if (subMaterialTemplates.hasOwnProperty(subMaterialId)) {
const subMaterial = new Material({
strict,
fabric: subMaterialTemplates[subMaterialId],
count: material._count
});
material._count = subMaterial._count;
material._uniforms = combine_default(
material._uniforms,
subMaterial._uniforms,
true
);
material.materials[subMaterialId] = subMaterial;
material._translucentFunctions = material._translucentFunctions.concat(
subMaterial._translucentFunctions
);
const originalMethodName = "czm_getMaterial";
const newMethodName = `${originalMethodName}_${material._count++}`;
replaceToken(subMaterial, originalMethodName, newMethodName);
material.shaderSource = subMaterial.shaderSource + material.shaderSource;
const materialMethodCall = `${newMethodName}(materialInput)`;
const tokensReplacedCount = replaceToken(
material,
subMaterialId,
materialMethodCall
);
if (tokensReplacedCount === 0 && strict) {
throw new DeveloperError_default(
`strict: shader source does not use material '${subMaterialId}'.`
);
}
}
}
}
function replaceToken(material, token, newToken, excludePeriod) {
excludePeriod = excludePeriod ?? true;
let count = 0;
const suffixChars = "([\\w])?";
const prefixChars = `([\\w${excludePeriod ? "." : ""}])?`;
const regExp = new RegExp(prefixChars + token + suffixChars, "g");
material.shaderSource = material.shaderSource.replace(
regExp,
function($0, $1, $2) {
if ($1 || $2) {
return $0;
}
count += 1;
return newToken;
}
);
return count;
}
function getNumberOfTokens(material, token, excludePeriod) {
return replaceToken(material, token, token, excludePeriod);
}
Material._materialCache = {
_materials: {},
addMaterial: function(type, materialTemplate) {
this._materials[type] = materialTemplate;
},
getMaterial: function(type) {
return this._materials[type];
}
};
Material.DefaultImageId = "czm_defaultImage";
Material.DefaultCubeMapId = "czm_defaultCubeMap";
Material.ColorType = "Color";
Material._materialCache.addMaterial(Material.ColorType, {
fabric: {
type: Material.ColorType,
uniforms: {
color: new Color_default(1, 0, 0, 0.5)
},
components: {
diffuse: "color.rgb",
alpha: "color.a"
}
},
translucent: function(material) {
return material.uniforms.color.alpha < 1;
}
});
Material.ImageType = "Image";
Material._materialCache.addMaterial(Material.ImageType, {
fabric: {
type: Material.ImageType,
uniforms: {
image: Material.DefaultImageId,
repeat: new Cartesian2_default(1, 1),
color: new Color_default(1, 1, 1, 1)
},
components: {
diffuse: "texture(image, fract(repeat * materialInput.st)).rgb * color.rgb",
alpha: "texture(image, fract(repeat * materialInput.st)).a * color.a"
}
},
translucent: function(material) {
return material.uniforms.color.alpha < 1;
}
});
Material.DiffuseMapType = "DiffuseMap";
Material._materialCache.addMaterial(Material.DiffuseMapType, {
fabric: {
type: Material.DiffuseMapType,
uniforms: {
image: Material.DefaultImageId,
channels: "rgb",
repeat: new Cartesian2_default(1, 1)
},
components: {
diffuse: "texture(image, fract(repeat * materialInput.st)).channels"
}
},
translucent: false
});
Material.AlphaMapType = "AlphaMap";
Material._materialCache.addMaterial(Material.AlphaMapType, {
fabric: {
type: Material.AlphaMapType,
uniforms: {
image: Material.DefaultImageId,
channel: "a",
repeat: new Cartesian2_default(1, 1)
},
components: {
alpha: "texture(image, fract(repeat * materialInput.st)).channel"
}
},
translucent: true
});
Material.SpecularMapType = "SpecularMap";
Material._materialCache.addMaterial(Material.SpecularMapType, {
fabric: {
type: Material.SpecularMapType,
uniforms: {
image: Material.DefaultImageId,
channel: "r",
repeat: new Cartesian2_default(1, 1)
},
components: {
specular: "texture(image, fract(repeat * materialInput.st)).channel"
}
},
translucent: false
});
Material.EmissionMapType = "EmissionMap";
Material._materialCache.addMaterial(Material.EmissionMapType, {
fabric: {
type: Material.EmissionMapType,
uniforms: {
image: Material.DefaultImageId,
channels: "rgb",
repeat: new Cartesian2_default(1, 1)
},
components: {
emission: "texture(image, fract(repeat * materialInput.st)).channels"
}
},
translucent: false
});
Material.BumpMapType = "BumpMap";
Material._materialCache.addMaterial(Material.BumpMapType, {
fabric: {
type: Material.BumpMapType,
uniforms: {
image: Material.DefaultImageId,
channel: "r",
strength: 0.8,
repeat: new Cartesian2_default(1, 1)
},
source: BumpMapMaterial_default
},
translucent: false
});
Material.NormalMapType = "NormalMap";
Material._materialCache.addMaterial(Material.NormalMapType, {
fabric: {
type: Material.NormalMapType,
uniforms: {
image: Material.DefaultImageId,
channels: "rgb",
strength: 0.8,
repeat: new Cartesian2_default(1, 1)
},
source: NormalMapMaterial_default
},
translucent: false
});
Material.GridType = "Grid";
Material._materialCache.addMaterial(Material.GridType, {
fabric: {
type: Material.GridType,
uniforms: {
color: new Color_default(0, 1, 0, 1),
cellAlpha: 0.1,
lineCount: new Cartesian2_default(8, 8),
lineThickness: new Cartesian2_default(1, 1),
lineOffset: new Cartesian2_default(0, 0)
},
source: GridMaterial_default
},
translucent: function(material) {
const uniforms = material.uniforms;
return uniforms.color.alpha < 1 || uniforms.cellAlpha < 1;
}
});
Material.StripeType = "Stripe";
Material._materialCache.addMaterial(Material.StripeType, {
fabric: {
type: Material.StripeType,
uniforms: {
horizontal: true,
evenColor: new Color_default(1, 1, 1, 0.5),
oddColor: new Color_default(0, 0, 1, 0.5),
offset: 0,
repeat: 5
},
source: StripeMaterial_default
},
translucent: function(material) {
const uniforms = material.uniforms;
return uniforms.evenColor.alpha < 1 || uniforms.oddColor.alpha < 1;
}
});
Material.CheckerboardType = "Checkerboard";
Material._materialCache.addMaterial(Material.CheckerboardType, {
fabric: {
type: Material.CheckerboardType,
uniforms: {
lightColor: new Color_default(1, 1, 1, 0.5),
darkColor: new Color_default(0, 0, 0, 0.5),
repeat: new Cartesian2_default(5, 5)
},
source: CheckerboardMaterial_default
},
translucent: function(material) {
const uniforms = material.uniforms;
return uniforms.lightColor.alpha < 1 || uniforms.darkColor.alpha < 1;
}
});
Material.DotType = "Dot";
Material._materialCache.addMaterial(Material.DotType, {
fabric: {
type: Material.DotType,
uniforms: {
lightColor: new Color_default(1, 1, 0, 0.75),
darkColor: new Color_default(0, 1, 1, 0.75),
repeat: new Cartesian2_default(5, 5)
},
source: DotMaterial_default
},
translucent: function(material) {
const uniforms = material.uniforms;
return uniforms.lightColor.alpha < 1 || uniforms.darkColor.alpha < 1;
}
});
Material.WaterType = "Water";
Material._materialCache.addMaterial(Material.WaterType, {
fabric: {
type: Material.WaterType,
uniforms: {
baseWaterColor: new Color_default(0.2, 0.3, 0.6, 1),
blendColor: new Color_default(0, 1, 0.699, 1),
specularMap: Material.DefaultImageId,
normalMap: Material.DefaultImageId,
frequency: 10,
animationSpeed: 0.01,
amplitude: 1,
specularIntensity: 0.5,
fadeFactor: 1
},
source: Water_default
},
translucent: function(material) {
const uniforms = material.uniforms;
return uniforms.baseWaterColor.alpha < 1 || uniforms.blendColor.alpha < 1;
}
});
Material.RimLightingType = "RimLighting";
Material._materialCache.addMaterial(Material.RimLightingType, {
fabric: {
type: Material.RimLightingType,
uniforms: {
color: new Color_default(1, 0, 0, 0.7),
rimColor: new Color_default(1, 1, 1, 0.4),
width: 0.3
},
source: RimLightingMaterial_default
},
translucent: function(material) {
const uniforms = material.uniforms;
return uniforms.color.alpha < 1 || uniforms.rimColor.alpha < 1;
}
});
Material.FadeType = "Fade";
Material._materialCache.addMaterial(Material.FadeType, {
fabric: {
type: Material.FadeType,
uniforms: {
fadeInColor: new Color_default(1, 0, 0, 1),
fadeOutColor: new Color_default(0, 0, 0, 0),
maximumDistance: 0.5,
repeat: true,
fadeDirection: {
x: true,
y: true
},
time: new Cartesian2_default(0.5, 0.5)
},
source: FadeMaterial_default
},
translucent: function(material) {
const uniforms = material.uniforms;
return uniforms.fadeInColor.alpha < 1 || uniforms.fadeOutColor.alpha < 1;
}
});
Material.PolylineArrowType = "PolylineArrow";
Material._materialCache.addMaterial(Material.PolylineArrowType, {
fabric: {
type: Material.PolylineArrowType,
uniforms: {
color: new Color_default(1, 1, 1, 1)
},
source: PolylineArrowMaterial_default
},
translucent: true
});
Material.PolylineDashType = "PolylineDash";
Material._materialCache.addMaterial(Material.PolylineDashType, {
fabric: {
type: Material.PolylineDashType,
uniforms: {
color: new Color_default(1, 0, 1, 1),
gapColor: new Color_default(0, 0, 0, 0),
dashLength: 16,
dashPattern: 255
},
source: PolylineDashMaterial_default
},
translucent: true
});
Material.PolylineGlowType = "PolylineGlow";
Material._materialCache.addMaterial(Material.PolylineGlowType, {
fabric: {
type: Material.PolylineGlowType,
uniforms: {
color: new Color_default(0, 0.5, 1, 1),
glowPower: 0.25,
taperPower: 1
},
source: PolylineGlowMaterial_default
},
translucent: true
});
Material.PolylineOutlineType = "PolylineOutline";
Material._materialCache.addMaterial(Material.PolylineOutlineType, {
fabric: {
type: Material.PolylineOutlineType,
uniforms: {
color: new Color_default(1, 1, 1, 1),
outlineColor: new Color_default(1, 0, 0, 1),
outlineWidth: 1
},
source: PolylineOutlineMaterial_default
},
translucent: function(material) {
const uniforms = material.uniforms;
return uniforms.color.alpha < 1 || uniforms.outlineColor.alpha < 1;
}
});
Material.ElevationContourType = "ElevationContour";
Material._materialCache.addMaterial(Material.ElevationContourType, {
fabric: {
type: Material.ElevationContourType,
uniforms: {
spacing: 100,
color: new Color_default(1, 0, 0, 1),
width: 1
},
source: ElevationContourMaterial_default
},
translucent: false
});
Material.ElevationRampType = "ElevationRamp";
Material._materialCache.addMaterial(Material.ElevationRampType, {
fabric: {
type: Material.ElevationRampType,
uniforms: {
image: Material.DefaultImageId,
minimumHeight: 0,
maximumHeight: 1e4
},
source: ElevationRampMaterial_default
},
translucent: false
});
Material.SlopeRampMaterialType = "SlopeRamp";
Material._materialCache.addMaterial(Material.SlopeRampMaterialType, {
fabric: {
type: Material.SlopeRampMaterialType,
uniforms: {
image: Material.DefaultImageId
},
source: SlopeRampMaterial_default
},
translucent: false
});
Material.AspectRampMaterialType = "AspectRamp";
Material._materialCache.addMaterial(Material.AspectRampMaterialType, {
fabric: {
type: Material.AspectRampMaterialType,
uniforms: {
image: Material.DefaultImageId
},
source: AspectRampMaterial_default
},
translucent: false
});
Material.ElevationBandType = "ElevationBand";
Material._materialCache.addMaterial(Material.ElevationBandType, {
fabric: {
type: Material.ElevationBandType,
uniforms: {
heights: Material.DefaultImageId,
colors: Material.DefaultImageId
},
source: ElevationBandMaterial_default
},
translucent: true
});
Material.WaterMaskType = "WaterMask";
Material._materialCache.addMaterial(Material.WaterMaskType, {
fabric: {
type: Material.WaterMaskType,
source: WaterMaskMaterial_default,
uniforms: {
waterColor: new Color_default(1, 1, 1, 1),
landColor: new Color_default(0, 0, 0, 0)
}
},
translucent: false
});
var Material_default = Material;
// packages/engine/Source/Scene/MaterialAppearance.js
function MaterialAppearance(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const translucent = options.translucent ?? true;
const closed = options.closed ?? false;
const materialSupport = options.materialSupport ?? MaterialAppearance.MaterialSupport.TEXTURED;
this.material = defined_default(options.material) ? options.material : Material_default.fromType(Material_default.ColorType);
this.translucent = translucent;
this._vertexShaderSource = options.vertexShaderSource ?? materialSupport.vertexShaderSource;
this._fragmentShaderSource = options.fragmentShaderSource ?? materialSupport.fragmentShaderSource;
this._renderState = Appearance_default.getDefaultRenderState(
translucent,
closed,
options.renderState
);
this._closed = closed;
this._materialSupport = materialSupport;
this._vertexFormat = materialSupport.vertexFormat;
this._flat = options.flat ?? false;
this._faceForward = options.faceForward ?? !closed;
}
Object.defineProperties(MaterialAppearance.prototype, {
/**
* The GLSL source code for the vertex shader.
*
* @memberof MaterialAppearance.prototype
*
* @type {string}
* @readonly
*/
vertexShaderSource: {
get: function() {
return this._vertexShaderSource;
}
},
/**
* The GLSL source code for the fragment shader. The full fragment shader
* source is built procedurally taking into account {@link MaterialAppearance#material},
* {@link MaterialAppearance#flat}, and {@link MaterialAppearance#faceForward}.
* Use {@link MaterialAppearance#getFragmentShaderSource} to get the full source.
*
* @memberof MaterialAppearance.prototype
*
* @type {string}
* @readonly
*/
fragmentShaderSource: {
get: function() {
return this._fragmentShaderSource;
}
},
/**
* The WebGL fixed-function state to use when rendering the geometry.
* * The render state can be explicitly defined when constructing a {@link MaterialAppearance} * instance, or it is set implicitly via {@link MaterialAppearance#translucent} * and {@link MaterialAppearance#closed}. *
* * @memberof MaterialAppearance.prototype * * @type {object} * @readonly */ renderState: { get: function() { return this._renderState; } }, /** * Whentrue, the geometry is expected to be closed so
* {@link MaterialAppearance#renderState} has backface culling enabled.
* If the viewer enters the geometry, it will not be visible.
*
* @memberof MaterialAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
closed: {
get: function() {
return this._closed;
}
},
/**
* The type of materials supported by this instance. This impacts the required
* {@link VertexFormat} and the complexity of the vertex and fragment shaders.
*
* @memberof MaterialAppearance.prototype
*
* @type {MaterialAppearance.MaterialSupportType}
* @readonly
*
* @default {@link MaterialAppearance.MaterialSupport.TEXTURED}
*/
materialSupport: {
get: function() {
return this._materialSupport;
}
},
/**
* The {@link VertexFormat} that this appearance instance is compatible with.
* A geometry can have more vertex attributes and still be compatible - at a
* potential performance cost - but it can't have less.
*
* @memberof MaterialAppearance.prototype
*
* @type VertexFormat
* @readonly
*
* @default {@link MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat}
*/
vertexFormat: {
get: function() {
return this._vertexFormat;
}
},
/**
* When true, flat shading is used in the fragment shader,
* which means lighting is not taking into account.
*
* @memberof MaterialAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
flat: {
get: function() {
return this._flat;
}
},
/**
* When true, the fragment shader flips the surface normal
* as needed to ensure that the normal faces the viewer to avoid
* dark spots. This is useful when both sides of a geometry should be
* shaded like {@link WallGeometry}.
*
* @memberof MaterialAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
faceForward: {
get: function() {
return this._faceForward;
}
}
});
MaterialAppearance.prototype.getFragmentShaderSource = Appearance_default.prototype.getFragmentShaderSource;
MaterialAppearance.prototype.isTranslucent = Appearance_default.prototype.isTranslucent;
MaterialAppearance.prototype.getRenderState = Appearance_default.prototype.getRenderState;
MaterialAppearance.MaterialSupport = {
/**
* Only basic materials, which require just position and
* normal vertex attributes, are supported.
*
* @type {MaterialAppearance.MaterialSupportType}
* @constant
*/
BASIC: Object.freeze({
vertexFormat: VertexFormat_default.POSITION_AND_NORMAL,
vertexShaderSource: BasicMaterialAppearanceVS_default,
fragmentShaderSource: BasicMaterialAppearanceFS_default
}),
/**
* Materials with textures, which require position,
* normal, and st vertex attributes,
* are supported. The vast majority of materials fall into this category.
*
* @type {MaterialAppearance.MaterialSupportType}
* @constant
*/
TEXTURED: Object.freeze({
vertexFormat: VertexFormat_default.POSITION_NORMAL_AND_ST,
vertexShaderSource: TexturedMaterialAppearanceVS_default,
fragmentShaderSource: TexturedMaterialAppearanceFS_default
}),
/**
* All materials, including those that work in tangent space, are supported.
* This requires position, normal, st,
* tangent, and bitangent vertex attributes.
*
* @type {MaterialAppearance.MaterialSupportType}
* @constant
*/
ALL: Object.freeze({
vertexFormat: VertexFormat_default.ALL,
vertexShaderSource: AllMaterialAppearanceVS_default,
fragmentShaderSource: AllMaterialAppearanceFS_default
})
};
var MaterialAppearance_default = MaterialAppearance;
// packages/engine/Source/Scene/PerInstanceColorAppearance.js
var import_InlineWorkers344 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Appearances/PerInstanceColorAppearanceFS.js
var import_InlineWorkers340 = __toESM(require_InlineWorkers(), 1);
var PerInstanceColorAppearanceFS_default = "in vec3 v_positionEC;\nin vec3 v_normalEC;\nin vec4 v_color;\n\nvoid main()\n{\n vec3 positionToEyeEC = -v_positionEC;\n\n vec3 normalEC = normalize(v_normalEC);\n#ifdef FACE_FORWARD\n normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\n#endif\n\n vec4 color = czm_gammaCorrect(v_color);\n\n czm_materialInput materialInput;\n materialInput.normalEC = normalEC;\n materialInput.positionToEyeEC = positionToEyeEC;\n czm_material material = czm_getDefaultMaterial(materialInput);\n material.diffuse = color.rgb;\n material.alpha = color.a;\n\n out_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\n}\n";
// packages/engine/Source/Shaders/Appearances/PerInstanceColorAppearanceVS.js
var import_InlineWorkers341 = __toESM(require_InlineWorkers(), 1);
var PerInstanceColorAppearanceVS_default = "in vec3 position3DHigh;\nin vec3 position3DLow;\nin vec3 normal;\nin vec4 color;\nin float batchId;\n\nout vec3 v_positionEC;\nout vec3 v_normalEC;\nout vec4 v_color;\n\nvoid main()\n{\n vec4 p = czm_computePosition();\n\n v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates\n v_normalEC = czm_normal * normal; // normal in eye coordinates\n v_color = color;\n\n gl_Position = czm_modelViewProjectionRelativeToEye * p;\n}\n";
// packages/engine/Source/Shaders/Appearances/PerInstanceFlatColorAppearanceFS.js
var import_InlineWorkers342 = __toESM(require_InlineWorkers(), 1);
var PerInstanceFlatColorAppearanceFS_default = "in vec4 v_color;\n\nvoid main()\n{\n out_FragColor = czm_gammaCorrect(v_color);\n}\n";
// packages/engine/Source/Shaders/Appearances/PerInstanceFlatColorAppearanceVS.js
var import_InlineWorkers343 = __toESM(require_InlineWorkers(), 1);
var PerInstanceFlatColorAppearanceVS_default = "in vec3 position3DHigh;\nin vec3 position3DLow;\nin vec4 color;\nin float batchId;\n\nout vec4 v_color;\n\nvoid main()\n{\n vec4 p = czm_computePosition();\n\n v_color = color;\n\n gl_Position = czm_modelViewProjectionRelativeToEye * p;\n}\n";
// packages/engine/Source/Scene/PerInstanceColorAppearance.js
function PerInstanceColorAppearance(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const translucent = options.translucent ?? true;
const closed = options.closed ?? false;
const flat = options.flat ?? false;
const vs = flat ? PerInstanceFlatColorAppearanceVS_default : PerInstanceColorAppearanceVS_default;
const fs = flat ? PerInstanceFlatColorAppearanceFS_default : PerInstanceColorAppearanceFS_default;
const vertexFormat = flat ? PerInstanceColorAppearance.FLAT_VERTEX_FORMAT : PerInstanceColorAppearance.VERTEX_FORMAT;
this.material = void 0;
this.translucent = translucent;
this._vertexShaderSource = options.vertexShaderSource ?? vs;
this._fragmentShaderSource = options.fragmentShaderSource ?? fs;
this._renderState = Appearance_default.getDefaultRenderState(
translucent,
closed,
options.renderState
);
this._closed = closed;
this._vertexFormat = vertexFormat;
this._flat = flat;
this._faceForward = options.faceForward ?? !closed;
}
Object.defineProperties(PerInstanceColorAppearance.prototype, {
/**
* The GLSL source code for the vertex shader.
*
* @memberof PerInstanceColorAppearance.prototype
*
* @type {string}
* @readonly
*/
vertexShaderSource: {
get: function() {
return this._vertexShaderSource;
}
},
/**
* The GLSL source code for the fragment shader.
*
* @memberof PerInstanceColorAppearance.prototype
*
* @type {string}
* @readonly
*/
fragmentShaderSource: {
get: function() {
return this._fragmentShaderSource;
}
},
/**
* The WebGL fixed-function state to use when rendering the geometry.
* * The render state can be explicitly defined when constructing a {@link PerInstanceColorAppearance} * instance, or it is set implicitly via {@link PerInstanceColorAppearance#translucent} * and {@link PerInstanceColorAppearance#closed}. *
* * @memberof PerInstanceColorAppearance.prototype * * @type {object} * @readonly */ renderState: { get: function() { return this._renderState; } }, /** * Whentrue, the geometry is expected to be closed so
* {@link PerInstanceColorAppearance#renderState} has backface culling enabled.
* If the viewer enters the geometry, it will not be visible.
*
* @memberof PerInstanceColorAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
closed: {
get: function() {
return this._closed;
}
},
/**
* The {@link VertexFormat} that this appearance instance is compatible with.
* A geometry can have more vertex attributes and still be compatible - at a
* potential performance cost - but it can't have less.
*
* @memberof PerInstanceColorAppearance.prototype
*
* @type VertexFormat
* @readonly
*/
vertexFormat: {
get: function() {
return this._vertexFormat;
}
},
/**
* When true, flat shading is used in the fragment shader,
* which means lighting is not taking into account.
*
* @memberof PerInstanceColorAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
flat: {
get: function() {
return this._flat;
}
},
/**
* When true, the fragment shader flips the surface normal
* as needed to ensure that the normal faces the viewer to avoid
* dark spots. This is useful when both sides of a geometry should be
* shaded like {@link WallGeometry}.
*
* @memberof PerInstanceColorAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
faceForward: {
get: function() {
return this._faceForward;
}
}
});
PerInstanceColorAppearance.VERTEX_FORMAT = VertexFormat_default.POSITION_AND_NORMAL;
PerInstanceColorAppearance.FLAT_VERTEX_FORMAT = VertexFormat_default.POSITION_ONLY;
PerInstanceColorAppearance.prototype.getFragmentShaderSource = Appearance_default.prototype.getFragmentShaderSource;
PerInstanceColorAppearance.prototype.isTranslucent = Appearance_default.prototype.isTranslucent;
PerInstanceColorAppearance.prototype.getRenderState = Appearance_default.prototype.getRenderState;
var PerInstanceColorAppearance_default = PerInstanceColorAppearance;
// packages/engine/Source/DataSources/ColorMaterialProperty.js
var import_InlineWorkers345 = __toESM(require_InlineWorkers(), 1);
function ColorMaterialProperty(color) {
this._definitionChanged = new Event_default();
this._color = void 0;
this._colorSubscription = void 0;
this.color = color;
}
Object.defineProperties(ColorMaterialProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof ColorMaterialProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return Property_default.isConstant(this._color);
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof ColorMaterialProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the {@link Color} {@link Property}.
* @memberof ColorMaterialProperty.prototype
* @type {Property|undefined}
* @default Color.WHITE
*/
color: createPropertyDescriptor_default("color")
});
ColorMaterialProperty.prototype.getType = function(time) {
return "Color";
};
var timeScratch = new JulianDate_default();
ColorMaterialProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch);
}
if (!defined_default(result)) {
result = {};
}
result.color = Property_default.getValueOrClonedDefault(
this._color,
time,
Color_default.WHITE,
result.color
);
return result;
};
ColorMaterialProperty.prototype.equals = function(other) {
return this === other || //
other instanceof ColorMaterialProperty && //
Property_default.equals(this._color, other._color);
};
var ColorMaterialProperty_default = ColorMaterialProperty;
// packages/engine/Source/DataSources/DynamicGeometryUpdater.js
var import_InlineWorkers372 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GroundPrimitive.js
var import_InlineWorkers370 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/ApproximateTerrainHeights.js
var import_InlineWorkers347 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/GeographicTilingScheme.js
var import_InlineWorkers346 = __toESM(require_InlineWorkers(), 1);
function GeographicTilingScheme(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
this._rectangle = options.rectangle ?? Rectangle_default.MAX_VALUE;
this._projection = new GeographicProjection_default(this._ellipsoid);
this._numberOfLevelZeroTilesX = options.numberOfLevelZeroTilesX ?? 2;
this._numberOfLevelZeroTilesY = options.numberOfLevelZeroTilesY ?? 1;
}
Object.defineProperties(GeographicTilingScheme.prototype, {
/**
* Gets the ellipsoid that is tiled by this tiling scheme.
* @memberof GeographicTilingScheme.prototype
* @type {Ellipsoid}
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
},
/**
* Gets the rectangle, in radians, covered by this tiling scheme.
* @memberof GeographicTilingScheme.prototype
* @type {Rectangle}
*/
rectangle: {
get: function() {
return this._rectangle;
}
},
/**
* Gets the map projection used by this tiling scheme.
* @memberof GeographicTilingScheme.prototype
* @type {MapProjection}
*/
projection: {
get: function() {
return this._projection;
}
}
});
GeographicTilingScheme.prototype.getNumberOfXTilesAtLevel = function(level) {
return this._numberOfLevelZeroTilesX << level;
};
GeographicTilingScheme.prototype.getNumberOfYTilesAtLevel = function(level) {
return this._numberOfLevelZeroTilesY << level;
};
GeographicTilingScheme.prototype.rectangleToNativeRectangle = function(rectangle, result) {
Check_default.defined("rectangle", rectangle);
const west = Math_default.toDegrees(rectangle.west);
const south = Math_default.toDegrees(rectangle.south);
const east = Math_default.toDegrees(rectangle.east);
const north = Math_default.toDegrees(rectangle.north);
if (!defined_default(result)) {
return new Rectangle_default(west, south, east, north);
}
result.west = west;
result.south = south;
result.east = east;
result.north = north;
return result;
};
GeographicTilingScheme.prototype.tileXYToNativeRectangle = function(x, y, level, result) {
const rectangleRadians = this.tileXYToRectangle(x, y, level, result);
rectangleRadians.west = Math_default.toDegrees(rectangleRadians.west);
rectangleRadians.south = Math_default.toDegrees(rectangleRadians.south);
rectangleRadians.east = Math_default.toDegrees(rectangleRadians.east);
rectangleRadians.north = Math_default.toDegrees(rectangleRadians.north);
return rectangleRadians;
};
GeographicTilingScheme.prototype.tileXYToRectangle = function(x, y, level, result) {
const rectangle = this._rectangle;
const xTiles = this.getNumberOfXTilesAtLevel(level);
const yTiles = this.getNumberOfYTilesAtLevel(level);
const xTileWidth = rectangle.width / xTiles;
const west = x * xTileWidth + rectangle.west;
const east = (x + 1) * xTileWidth + rectangle.west;
const yTileHeight = rectangle.height / yTiles;
const north = rectangle.north - y * yTileHeight;
const south = rectangle.north - (y + 1) * yTileHeight;
if (!defined_default(result)) {
result = new Rectangle_default(west, south, east, north);
}
result.west = west;
result.south = south;
result.east = east;
result.north = north;
return result;
};
GeographicTilingScheme.prototype.positionToTileXY = function(position, level, result) {
const rectangle = this._rectangle;
if (!Rectangle_default.contains(rectangle, position)) {
return void 0;
}
const xTiles = this.getNumberOfXTilesAtLevel(level);
const yTiles = this.getNumberOfYTilesAtLevel(level);
const xTileWidth = rectangle.width / xTiles;
const yTileHeight = rectangle.height / yTiles;
let longitude = position.longitude;
if (rectangle.east < rectangle.west) {
longitude += Math_default.TWO_PI;
}
let xTileCoordinate = (longitude - rectangle.west) / xTileWidth | 0;
if (xTileCoordinate >= xTiles) {
xTileCoordinate = xTiles - 1;
}
let yTileCoordinate = (rectangle.north - position.latitude) / yTileHeight | 0;
if (yTileCoordinate >= yTiles) {
yTileCoordinate = yTiles - 1;
}
if (!defined_default(result)) {
return new Cartesian2_default(xTileCoordinate, yTileCoordinate);
}
result.x = xTileCoordinate;
result.y = yTileCoordinate;
return result;
};
var GeographicTilingScheme_default = GeographicTilingScheme;
// packages/engine/Source/Core/ApproximateTerrainHeights.js
var scratchDiagonalCartesianNE = new Cartesian3_default();
var scratchDiagonalCartesianSW = new Cartesian3_default();
var scratchDiagonalCartographic = new Cartographic_default();
var scratchCenterCartesian = new Cartesian3_default();
var scratchSurfaceCartesian = new Cartesian3_default();
var scratchBoundingSphere = new BoundingSphere_default();
var tilingScheme = new GeographicTilingScheme_default();
var scratchCorners = [
new Cartographic_default(),
new Cartographic_default(),
new Cartographic_default(),
new Cartographic_default()
];
var scratchTileXY = new Cartesian2_default();
var ApproximateTerrainHeights = {};
ApproximateTerrainHeights.initialize = function() {
let initPromise = ApproximateTerrainHeights._initPromise;
if (defined_default(initPromise)) {
return initPromise;
}
initPromise = Resource_default.fetchJson(
buildModuleUrl_default("Assets/approximateTerrainHeights.json")
).then(function(json) {
ApproximateTerrainHeights._terrainHeights = json;
});
ApproximateTerrainHeights._initPromise = initPromise;
return initPromise;
};
ApproximateTerrainHeights.getMinimumMaximumHeights = function(rectangle, ellipsoid) {
Check_default.defined("rectangle", rectangle);
if (!defined_default(ApproximateTerrainHeights._terrainHeights)) {
throw new DeveloperError_default(
"You must call ApproximateTerrainHeights.initialize and wait for the promise to resolve before using this function"
);
}
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
const xyLevel = getTileXYLevel(rectangle);
let minTerrainHeight = ApproximateTerrainHeights._defaultMinTerrainHeight;
let maxTerrainHeight = ApproximateTerrainHeights._defaultMaxTerrainHeight;
if (defined_default(xyLevel)) {
const key = `${xyLevel.level}-${xyLevel.x}-${xyLevel.y}`;
const heights = ApproximateTerrainHeights._terrainHeights[key];
if (defined_default(heights)) {
minTerrainHeight = heights[0];
maxTerrainHeight = heights[1];
}
ellipsoid.cartographicToCartesian(
Rectangle_default.northeast(rectangle, scratchDiagonalCartographic),
scratchDiagonalCartesianNE
);
ellipsoid.cartographicToCartesian(
Rectangle_default.southwest(rectangle, scratchDiagonalCartographic),
scratchDiagonalCartesianSW
);
Cartesian3_default.midpoint(
scratchDiagonalCartesianSW,
scratchDiagonalCartesianNE,
scratchCenterCartesian
);
const surfacePosition = ellipsoid.scaleToGeodeticSurface(
scratchCenterCartesian,
scratchSurfaceCartesian
);
if (defined_default(surfacePosition)) {
const distance2 = Cartesian3_default.distance(
scratchCenterCartesian,
surfacePosition
);
minTerrainHeight = Math.min(minTerrainHeight, -distance2);
} else {
minTerrainHeight = ApproximateTerrainHeights._defaultMinTerrainHeight;
}
}
minTerrainHeight = Math.max(
ApproximateTerrainHeights._defaultMinTerrainHeight,
minTerrainHeight
);
return {
minimumTerrainHeight: minTerrainHeight,
maximumTerrainHeight: maxTerrainHeight
};
};
ApproximateTerrainHeights.getBoundingSphere = function(rectangle, ellipsoid) {
Check_default.defined("rectangle", rectangle);
if (!defined_default(ApproximateTerrainHeights._terrainHeights)) {
throw new DeveloperError_default(
"You must call ApproximateTerrainHeights.initialize and wait for the promise to resolve before using this function"
);
}
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
const xyLevel = getTileXYLevel(rectangle);
let maxTerrainHeight = ApproximateTerrainHeights._defaultMaxTerrainHeight;
if (defined_default(xyLevel)) {
const key = `${xyLevel.level}-${xyLevel.x}-${xyLevel.y}`;
const heights = ApproximateTerrainHeights._terrainHeights[key];
if (defined_default(heights)) {
maxTerrainHeight = heights[1];
}
}
const result = BoundingSphere_default.fromRectangle3D(rectangle, ellipsoid, 0);
BoundingSphere_default.fromRectangle3D(
rectangle,
ellipsoid,
maxTerrainHeight,
scratchBoundingSphere
);
return BoundingSphere_default.union(result, scratchBoundingSphere, result);
};
function getTileXYLevel(rectangle) {
Cartographic_default.fromRadians(
rectangle.east,
rectangle.north,
0,
scratchCorners[0]
);
Cartographic_default.fromRadians(
rectangle.west,
rectangle.north,
0,
scratchCorners[1]
);
Cartographic_default.fromRadians(
rectangle.east,
rectangle.south,
0,
scratchCorners[2]
);
Cartographic_default.fromRadians(
rectangle.west,
rectangle.south,
0,
scratchCorners[3]
);
let lastLevelX = 0, lastLevelY = 0;
let currentX = 0, currentY = 0;
const maxLevel = ApproximateTerrainHeights._terrainHeightsMaxLevel;
let i;
for (i = 0; i <= maxLevel; ++i) {
let failed = false;
for (let j = 0; j < 4; ++j) {
const corner = scratchCorners[j];
tilingScheme.positionToTileXY(corner, i, scratchTileXY);
if (j === 0) {
currentX = scratchTileXY.x;
currentY = scratchTileXY.y;
} else if (currentX !== scratchTileXY.x || currentY !== scratchTileXY.y) {
failed = true;
break;
}
}
if (failed) {
break;
}
lastLevelX = currentX;
lastLevelY = currentY;
}
if (i === 0) {
return void 0;
}
return {
x: lastLevelX,
y: lastLevelY,
level: i > maxLevel ? maxLevel : i - 1
};
}
ApproximateTerrainHeights._terrainHeightsMaxLevel = 6;
ApproximateTerrainHeights._defaultMaxTerrainHeight = 9e3;
ApproximateTerrainHeights._defaultMinTerrainHeight = -1e5;
ApproximateTerrainHeights._terrainHeights = void 0;
ApproximateTerrainHeights._initPromise = void 0;
Object.defineProperties(ApproximateTerrainHeights, {
/**
* Determines if the terrain heights are initialized and ready to use. To initialize the terrain heights,
* call {@link ApproximateTerrainHeights#initialize} and wait for the returned promise to resolve.
* @type {boolean}
* @readonly
* @memberof ApproximateTerrainHeights
*/
initialized: {
get: function() {
return defined_default(ApproximateTerrainHeights._terrainHeights);
}
}
});
var ApproximateTerrainHeights_default = ApproximateTerrainHeights;
// packages/engine/Source/Core/OrientedBoundingBox.js
var import_InlineWorkers350 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/EllipsoidTangentPlane.js
var import_InlineWorkers349 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/AxisAlignedBoundingBox.js
var import_InlineWorkers348 = __toESM(require_InlineWorkers(), 1);
function AxisAlignedBoundingBox(minimum, maximum, center) {
this.minimum = Cartesian3_default.clone(minimum ?? Cartesian3_default.ZERO);
this.maximum = Cartesian3_default.clone(maximum ?? Cartesian3_default.ZERO);
if (!defined_default(center)) {
center = Cartesian3_default.midpoint(this.minimum, this.maximum, new Cartesian3_default());
} else {
center = Cartesian3_default.clone(center);
}
this.center = center;
}
AxisAlignedBoundingBox.fromCorners = function(minimum, maximum, result) {
Check_default.defined("minimum", minimum);
Check_default.defined("maximum", maximum);
if (!defined_default(result)) {
result = new AxisAlignedBoundingBox();
}
result.minimum = Cartesian3_default.clone(minimum, result.minimum);
result.maximum = Cartesian3_default.clone(maximum, result.maximum);
result.center = Cartesian3_default.midpoint(minimum, maximum, result.center);
return result;
};
AxisAlignedBoundingBox.fromPoints = function(positions, result) {
if (!defined_default(result)) {
result = new AxisAlignedBoundingBox();
}
if (!defined_default(positions) || positions.length === 0) {
result.minimum = Cartesian3_default.clone(Cartesian3_default.ZERO, result.minimum);
result.maximum = Cartesian3_default.clone(Cartesian3_default.ZERO, result.maximum);
result.center = Cartesian3_default.clone(Cartesian3_default.ZERO, result.center);
return result;
}
let minimumX = positions[0].x;
let minimumY = positions[0].y;
let minimumZ = positions[0].z;
let maximumX = positions[0].x;
let maximumY = positions[0].y;
let maximumZ = positions[0].z;
const length2 = positions.length;
for (let i = 1; i < length2; i++) {
const p = positions[i];
const x = p.x;
const y = p.y;
const z = p.z;
minimumX = Math.min(x, minimumX);
maximumX = Math.max(x, maximumX);
minimumY = Math.min(y, minimumY);
maximumY = Math.max(y, maximumY);
minimumZ = Math.min(z, minimumZ);
maximumZ = Math.max(z, maximumZ);
}
const minimum = result.minimum;
minimum.x = minimumX;
minimum.y = minimumY;
minimum.z = minimumZ;
const maximum = result.maximum;
maximum.x = maximumX;
maximum.y = maximumY;
maximum.z = maximumZ;
result.center = Cartesian3_default.midpoint(minimum, maximum, result.center);
return result;
};
AxisAlignedBoundingBox.clone = function(box, result) {
if (!defined_default(box)) {
return void 0;
}
if (!defined_default(result)) {
return new AxisAlignedBoundingBox(box.minimum, box.maximum, box.center);
}
result.minimum = Cartesian3_default.clone(box.minimum, result.minimum);
result.maximum = Cartesian3_default.clone(box.maximum, result.maximum);
result.center = Cartesian3_default.clone(box.center, result.center);
return result;
};
AxisAlignedBoundingBox.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && Cartesian3_default.equals(left.center, right.center) && Cartesian3_default.equals(left.minimum, right.minimum) && Cartesian3_default.equals(left.maximum, right.maximum);
};
var intersectScratch = new Cartesian3_default();
AxisAlignedBoundingBox.intersectPlane = function(box, plane) {
Check_default.defined("box", box);
Check_default.defined("plane", plane);
intersectScratch = Cartesian3_default.subtract(
box.maximum,
box.minimum,
intersectScratch
);
const h = Cartesian3_default.multiplyByScalar(
intersectScratch,
0.5,
intersectScratch
);
const normal2 = plane.normal;
const e = h.x * Math.abs(normal2.x) + h.y * Math.abs(normal2.y) + h.z * Math.abs(normal2.z);
const s = Cartesian3_default.dot(box.center, normal2) + plane.distance;
if (s - e > 0) {
return Intersect_default.INSIDE;
}
if (s + e < 0) {
return Intersect_default.OUTSIDE;
}
return Intersect_default.INTERSECTING;
};
AxisAlignedBoundingBox.prototype.clone = function(result) {
return AxisAlignedBoundingBox.clone(this, result);
};
AxisAlignedBoundingBox.prototype.intersectPlane = function(plane) {
return AxisAlignedBoundingBox.intersectPlane(this, plane);
};
AxisAlignedBoundingBox.prototype.equals = function(right) {
return AxisAlignedBoundingBox.equals(this, right);
};
var AxisAlignedBoundingBox_default = AxisAlignedBoundingBox;
// packages/engine/Source/Core/EllipsoidTangentPlane.js
var scratchCart4 = new Cartesian4_default();
function EllipsoidTangentPlane(origin, ellipsoid) {
Check_default.defined("origin", origin);
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
origin = ellipsoid.scaleToGeodeticSurface(origin);
if (!defined_default(origin)) {
throw new DeveloperError_default(
"origin must not be at the center of the ellipsoid."
);
}
const eastNorthUp = Transforms_default.eastNorthUpToFixedFrame(origin, ellipsoid);
this._ellipsoid = ellipsoid;
this._origin = origin;
this._xAxis = Cartesian3_default.fromCartesian4(
Matrix4_default.getColumn(eastNorthUp, 0, scratchCart4)
);
this._yAxis = Cartesian3_default.fromCartesian4(
Matrix4_default.getColumn(eastNorthUp, 1, scratchCart4)
);
const normal2 = Cartesian3_default.fromCartesian4(
Matrix4_default.getColumn(eastNorthUp, 2, scratchCart4)
);
this._plane = Plane_default.fromPointNormal(origin, normal2);
}
Object.defineProperties(EllipsoidTangentPlane.prototype, {
/**
* Gets the ellipsoid.
* @memberof EllipsoidTangentPlane.prototype
* @type {Ellipsoid}
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
},
/**
* Gets the origin.
* @memberof EllipsoidTangentPlane.prototype
* @type {Cartesian3}
*/
origin: {
get: function() {
return this._origin;
}
},
/**
* Gets the plane which is tangent to the ellipsoid.
* @memberof EllipsoidTangentPlane.prototype
* @readonly
* @type {Plane}
*/
plane: {
get: function() {
return this._plane;
}
},
/**
* Gets the local X-axis (east) of the tangent plane.
* @memberof EllipsoidTangentPlane.prototype
* @readonly
* @type {Cartesian3}
*/
xAxis: {
get: function() {
return this._xAxis;
}
},
/**
* Gets the local Y-axis (north) of the tangent plane.
* @memberof EllipsoidTangentPlane.prototype
* @readonly
* @type {Cartesian3}
*/
yAxis: {
get: function() {
return this._yAxis;
}
},
/**
* Gets the local Z-axis (up) of the tangent plane.
* @memberof EllipsoidTangentPlane.prototype
* @readonly
* @type {Cartesian3}
*/
zAxis: {
get: function() {
return this._plane.normal;
}
}
});
var tmp = new AxisAlignedBoundingBox_default();
EllipsoidTangentPlane.fromPoints = function(cartesians, ellipsoid) {
Check_default.defined("cartesians", cartesians);
const box = AxisAlignedBoundingBox_default.fromPoints(cartesians, tmp);
return new EllipsoidTangentPlane(box.center, ellipsoid);
};
var scratchProjectPointOntoPlaneRay = new Ray_default();
var scratchProjectPointOntoPlaneCartesian3 = new Cartesian3_default();
EllipsoidTangentPlane.prototype.projectPointOntoPlane = function(cartesian11, result) {
Check_default.defined("cartesian", cartesian11);
const ray = scratchProjectPointOntoPlaneRay;
ray.origin = cartesian11;
Cartesian3_default.normalize(cartesian11, ray.direction);
let intersectionPoint = IntersectionTests_default.rayPlane(
ray,
this._plane,
scratchProjectPointOntoPlaneCartesian3
);
if (!defined_default(intersectionPoint)) {
Cartesian3_default.negate(ray.direction, ray.direction);
intersectionPoint = IntersectionTests_default.rayPlane(
ray,
this._plane,
scratchProjectPointOntoPlaneCartesian3
);
}
if (defined_default(intersectionPoint)) {
const v3 = Cartesian3_default.subtract(
intersectionPoint,
this._origin,
intersectionPoint
);
const x = Cartesian3_default.dot(this._xAxis, v3);
const y = Cartesian3_default.dot(this._yAxis, v3);
if (!defined_default(result)) {
return new Cartesian2_default(x, y);
}
result.x = x;
result.y = y;
return result;
}
return void 0;
};
EllipsoidTangentPlane.prototype.projectPointsOntoPlane = function(cartesians, result) {
Check_default.defined("cartesians", cartesians);
if (!defined_default(result)) {
result = [];
}
let count = 0;
const length2 = cartesians.length;
for (let i = 0; i < length2; i++) {
const p = this.projectPointOntoPlane(cartesians[i], result[count]);
if (defined_default(p)) {
result[count] = p;
count++;
}
}
result.length = count;
return result;
};
EllipsoidTangentPlane.prototype.projectPointToNearestOnPlane = function(cartesian11, result) {
Check_default.defined("cartesian", cartesian11);
if (!defined_default(result)) {
result = new Cartesian2_default();
}
const ray = scratchProjectPointOntoPlaneRay;
ray.origin = cartesian11;
Cartesian3_default.clone(this._plane.normal, ray.direction);
let intersectionPoint = IntersectionTests_default.rayPlane(
ray,
this._plane,
scratchProjectPointOntoPlaneCartesian3
);
if (!defined_default(intersectionPoint)) {
Cartesian3_default.negate(ray.direction, ray.direction);
intersectionPoint = IntersectionTests_default.rayPlane(
ray,
this._plane,
scratchProjectPointOntoPlaneCartesian3
);
}
const v3 = Cartesian3_default.subtract(
intersectionPoint,
this._origin,
intersectionPoint
);
const x = Cartesian3_default.dot(this._xAxis, v3);
const y = Cartesian3_default.dot(this._yAxis, v3);
result.x = x;
result.y = y;
return result;
};
EllipsoidTangentPlane.prototype.projectPointsToNearestOnPlane = function(cartesians, result) {
Check_default.defined("cartesians", cartesians);
if (!defined_default(result)) {
result = [];
}
const length2 = cartesians.length;
result.length = length2;
for (let i = 0; i < length2; i++) {
result[i] = this.projectPointToNearestOnPlane(cartesians[i], result[i]);
}
return result;
};
var projectPointsOntoEllipsoidScratch = new Cartesian3_default();
EllipsoidTangentPlane.prototype.projectPointOntoEllipsoid = function(cartesian11, result) {
Check_default.defined("cartesian", cartesian11);
if (!defined_default(result)) {
result = new Cartesian3_default();
}
const ellipsoid = this._ellipsoid;
const origin = this._origin;
const xAxis = this._xAxis;
const yAxis = this._yAxis;
const tmp2 = projectPointsOntoEllipsoidScratch;
Cartesian3_default.multiplyByScalar(xAxis, cartesian11.x, tmp2);
result = Cartesian3_default.add(origin, tmp2, result);
Cartesian3_default.multiplyByScalar(yAxis, cartesian11.y, tmp2);
Cartesian3_default.add(result, tmp2, result);
ellipsoid.scaleToGeocentricSurface(result, result);
return result;
};
EllipsoidTangentPlane.prototype.projectPointsOntoEllipsoid = function(cartesians, result) {
Check_default.defined("cartesians", cartesians);
const length2 = cartesians.length;
if (!defined_default(result)) {
result = new Array(length2);
} else {
result.length = length2;
}
for (let i = 0; i < length2; ++i) {
result[i] = this.projectPointOntoEllipsoid(cartesians[i], result[i]);
}
return result;
};
var EllipsoidTangentPlane_default = EllipsoidTangentPlane;
// packages/engine/Source/Core/OrientedBoundingBox.js
function OrientedBoundingBox(center, halfAxes) {
this.center = Cartesian3_default.clone(center ?? Cartesian3_default.ZERO);
this.halfAxes = Matrix3_default.clone(halfAxes ?? Matrix3_default.ZERO);
}
OrientedBoundingBox.packedLength = Cartesian3_default.packedLength + Matrix3_default.packedLength;
OrientedBoundingBox.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
Cartesian3_default.pack(value.center, array, startingIndex);
Matrix3_default.pack(value.halfAxes, array, startingIndex + Cartesian3_default.packedLength);
return array;
};
OrientedBoundingBox.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new OrientedBoundingBox();
}
Cartesian3_default.unpack(array, startingIndex, result.center);
Matrix3_default.unpack(
array,
startingIndex + Cartesian3_default.packedLength,
result.halfAxes
);
return result;
};
var scratchCartesian12 = new Cartesian3_default();
var scratchCartesian23 = new Cartesian3_default();
var scratchCartesian34 = new Cartesian3_default();
var scratchCartesian4 = new Cartesian3_default();
var scratchCartesian5 = new Cartesian3_default();
var scratchCartesian6 = new Cartesian3_default();
var scratchCovarianceResult = new Matrix3_default();
var scratchEigenResult = {
unitary: new Matrix3_default(),
diagonal: new Matrix3_default()
};
OrientedBoundingBox.fromPoints = function(positions, result) {
if (!defined_default(result)) {
result = new OrientedBoundingBox();
}
if (!defined_default(positions) || positions.length === 0) {
result.halfAxes = Matrix3_default.ZERO;
result.center = Cartesian3_default.ZERO;
return result;
}
let i;
const length2 = positions.length;
const meanPoint = Cartesian3_default.clone(positions[0], scratchCartesian12);
for (i = 1; i < length2; i++) {
Cartesian3_default.add(meanPoint, positions[i], meanPoint);
}
const invLength = 1 / length2;
Cartesian3_default.multiplyByScalar(meanPoint, invLength, meanPoint);
let exx = 0;
let exy = 0;
let exz = 0;
let eyy = 0;
let eyz = 0;
let ezz = 0;
let p;
for (i = 0; i < length2; i++) {
p = Cartesian3_default.subtract(positions[i], meanPoint, scratchCartesian23);
exx += p.x * p.x;
exy += p.x * p.y;
exz += p.x * p.z;
eyy += p.y * p.y;
eyz += p.y * p.z;
ezz += p.z * p.z;
}
exx *= invLength;
exy *= invLength;
exz *= invLength;
eyy *= invLength;
eyz *= invLength;
ezz *= invLength;
const covarianceMatrix = scratchCovarianceResult;
covarianceMatrix[0] = exx;
covarianceMatrix[1] = exy;
covarianceMatrix[2] = exz;
covarianceMatrix[3] = exy;
covarianceMatrix[4] = eyy;
covarianceMatrix[5] = eyz;
covarianceMatrix[6] = exz;
covarianceMatrix[7] = eyz;
covarianceMatrix[8] = ezz;
const eigenDecomposition = Matrix3_default.computeEigenDecomposition(
covarianceMatrix,
scratchEigenResult
);
const rotation = Matrix3_default.clone(eigenDecomposition.unitary, result.halfAxes);
let v12 = Matrix3_default.getColumn(rotation, 0, scratchCartesian4);
let v22 = Matrix3_default.getColumn(rotation, 1, scratchCartesian5);
let v3 = Matrix3_default.getColumn(rotation, 2, scratchCartesian6);
let u12 = -Number.MAX_VALUE;
let u22 = -Number.MAX_VALUE;
let u3 = -Number.MAX_VALUE;
let l1 = Number.MAX_VALUE;
let l2 = Number.MAX_VALUE;
let l3 = Number.MAX_VALUE;
for (i = 0; i < length2; i++) {
p = positions[i];
u12 = Math.max(Cartesian3_default.dot(v12, p), u12);
u22 = Math.max(Cartesian3_default.dot(v22, p), u22);
u3 = Math.max(Cartesian3_default.dot(v3, p), u3);
l1 = Math.min(Cartesian3_default.dot(v12, p), l1);
l2 = Math.min(Cartesian3_default.dot(v22, p), l2);
l3 = Math.min(Cartesian3_default.dot(v3, p), l3);
}
v12 = Cartesian3_default.multiplyByScalar(v12, 0.5 * (l1 + u12), v12);
v22 = Cartesian3_default.multiplyByScalar(v22, 0.5 * (l2 + u22), v22);
v3 = Cartesian3_default.multiplyByScalar(v3, 0.5 * (l3 + u3), v3);
const center = Cartesian3_default.add(v12, v22, result.center);
Cartesian3_default.add(center, v3, center);
const scale = scratchCartesian34;
scale.x = u12 - l1;
scale.y = u22 - l2;
scale.z = u3 - l3;
Cartesian3_default.multiplyByScalar(scale, 0.5, scale);
Matrix3_default.multiplyByScale(result.halfAxes, scale, result.halfAxes);
return result;
};
var scratchOffset = new Cartesian3_default();
var scratchScale2 = new Cartesian3_default();
function fromPlaneExtents(planeOrigin, planeXAxis, planeYAxis, planeZAxis, minimumX, maximumX, minimumY, maximumY, minimumZ, maximumZ, result) {
if (!defined_default(minimumX) || !defined_default(maximumX) || !defined_default(minimumY) || !defined_default(maximumY) || !defined_default(minimumZ) || !defined_default(maximumZ)) {
throw new DeveloperError_default(
"all extents (minimum/maximum X/Y/Z) are required."
);
}
if (!defined_default(result)) {
result = new OrientedBoundingBox();
}
const halfAxes = result.halfAxes;
Matrix3_default.setColumn(halfAxes, 0, planeXAxis, halfAxes);
Matrix3_default.setColumn(halfAxes, 1, planeYAxis, halfAxes);
Matrix3_default.setColumn(halfAxes, 2, planeZAxis, halfAxes);
let centerOffset = scratchOffset;
centerOffset.x = (minimumX + maximumX) / 2;
centerOffset.y = (minimumY + maximumY) / 2;
centerOffset.z = (minimumZ + maximumZ) / 2;
const scale = scratchScale2;
scale.x = (maximumX - minimumX) / 2;
scale.y = (maximumY - minimumY) / 2;
scale.z = (maximumZ - minimumZ) / 2;
const center = result.center;
centerOffset = Matrix3_default.multiplyByVector(halfAxes, centerOffset, centerOffset);
Cartesian3_default.add(planeOrigin, centerOffset, center);
Matrix3_default.multiplyByScale(halfAxes, scale, halfAxes);
return result;
}
var scratchRectangleCenterCartographic = new Cartographic_default();
var scratchRectangleCenter = new Cartesian3_default();
var scratchPerimeterCartographicNC = new Cartographic_default();
var scratchPerimeterCartographicNW = new Cartographic_default();
var scratchPerimeterCartographicCW = new Cartographic_default();
var scratchPerimeterCartographicSW = new Cartographic_default();
var scratchPerimeterCartographicSC = new Cartographic_default();
var scratchPerimeterCartesianNC = new Cartesian3_default();
var scratchPerimeterCartesianNW = new Cartesian3_default();
var scratchPerimeterCartesianCW = new Cartesian3_default();
var scratchPerimeterCartesianSW = new Cartesian3_default();
var scratchPerimeterCartesianSC = new Cartesian3_default();
var scratchPerimeterProjectedNC = new Cartesian2_default();
var scratchPerimeterProjectedNW = new Cartesian2_default();
var scratchPerimeterProjectedCW = new Cartesian2_default();
var scratchPerimeterProjectedSW = new Cartesian2_default();
var scratchPerimeterProjectedSC = new Cartesian2_default();
var scratchPlaneOrigin = new Cartesian3_default();
var scratchPlaneNormal2 = new Cartesian3_default();
var scratchPlaneXAxis = new Cartesian3_default();
var scratchHorizonCartesian = new Cartesian3_default();
var scratchHorizonProjected = new Cartesian2_default();
var scratchMaxY = new Cartesian3_default();
var scratchMinY = new Cartesian3_default();
var scratchZ = new Cartesian3_default();
var scratchPlane2 = new Plane_default(Cartesian3_default.UNIT_X, 0);
OrientedBoundingBox.fromRectangle = function(rectangle, minimumHeight, maximumHeight, ellipsoid, result) {
if (!defined_default(rectangle)) {
throw new DeveloperError_default("rectangle is required");
}
if (rectangle.width < 0 || rectangle.width > Math_default.TWO_PI) {
throw new DeveloperError_default("Rectangle width must be between 0 and 2 * pi");
}
if (rectangle.height < 0 || rectangle.height > Math_default.PI) {
throw new DeveloperError_default("Rectangle height must be between 0 and pi");
}
if (defined_default(ellipsoid) && !Math_default.equalsEpsilon(
ellipsoid.radii.x,
ellipsoid.radii.y,
Math_default.EPSILON15
)) {
throw new DeveloperError_default(
"Ellipsoid must be an ellipsoid of revolution (radii.x == radii.y)"
);
}
minimumHeight = minimumHeight ?? 0;
maximumHeight = maximumHeight ?? 0;
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
let minX, maxX, minY, maxY, minZ, maxZ, plane;
if (rectangle.width <= Math_default.PI) {
const tangentPointCartographic = Rectangle_default.center(
rectangle,
scratchRectangleCenterCartographic
);
const tangentPoint = ellipsoid.cartographicToCartesian(
tangentPointCartographic,
scratchRectangleCenter
);
const tangentPlane = new EllipsoidTangentPlane_default(tangentPoint, ellipsoid);
plane = tangentPlane.plane;
const lonCenter = tangentPointCartographic.longitude;
const latCenter = rectangle.south < 0 && rectangle.north > 0 ? 0 : tangentPointCartographic.latitude;
const perimeterCartographicNC = Cartographic_default.fromRadians(
lonCenter,
rectangle.north,
maximumHeight,
scratchPerimeterCartographicNC
);
const perimeterCartographicNW = Cartographic_default.fromRadians(
rectangle.west,
rectangle.north,
maximumHeight,
scratchPerimeterCartographicNW
);
const perimeterCartographicCW = Cartographic_default.fromRadians(
rectangle.west,
latCenter,
maximumHeight,
scratchPerimeterCartographicCW
);
const perimeterCartographicSW = Cartographic_default.fromRadians(
rectangle.west,
rectangle.south,
maximumHeight,
scratchPerimeterCartographicSW
);
const perimeterCartographicSC = Cartographic_default.fromRadians(
lonCenter,
rectangle.south,
maximumHeight,
scratchPerimeterCartographicSC
);
const perimeterCartesianNC = ellipsoid.cartographicToCartesian(
perimeterCartographicNC,
scratchPerimeterCartesianNC
);
let perimeterCartesianNW = ellipsoid.cartographicToCartesian(
perimeterCartographicNW,
scratchPerimeterCartesianNW
);
const perimeterCartesianCW = ellipsoid.cartographicToCartesian(
perimeterCartographicCW,
scratchPerimeterCartesianCW
);
let perimeterCartesianSW = ellipsoid.cartographicToCartesian(
perimeterCartographicSW,
scratchPerimeterCartesianSW
);
const perimeterCartesianSC = ellipsoid.cartographicToCartesian(
perimeterCartographicSC,
scratchPerimeterCartesianSC
);
const perimeterProjectedNC = tangentPlane.projectPointToNearestOnPlane(
perimeterCartesianNC,
scratchPerimeterProjectedNC
);
const perimeterProjectedNW = tangentPlane.projectPointToNearestOnPlane(
perimeterCartesianNW,
scratchPerimeterProjectedNW
);
const perimeterProjectedCW = tangentPlane.projectPointToNearestOnPlane(
perimeterCartesianCW,
scratchPerimeterProjectedCW
);
const perimeterProjectedSW = tangentPlane.projectPointToNearestOnPlane(
perimeterCartesianSW,
scratchPerimeterProjectedSW
);
const perimeterProjectedSC = tangentPlane.projectPointToNearestOnPlane(
perimeterCartesianSC,
scratchPerimeterProjectedSC
);
minX = Math.min(
perimeterProjectedNW.x,
perimeterProjectedCW.x,
perimeterProjectedSW.x
);
maxX = -minX;
maxY = Math.max(perimeterProjectedNW.y, perimeterProjectedNC.y);
minY = Math.min(perimeterProjectedSW.y, perimeterProjectedSC.y);
perimeterCartographicNW.height = perimeterCartographicSW.height = minimumHeight;
perimeterCartesianNW = ellipsoid.cartographicToCartesian(
perimeterCartographicNW,
scratchPerimeterCartesianNW
);
perimeterCartesianSW = ellipsoid.cartographicToCartesian(
perimeterCartographicSW,
scratchPerimeterCartesianSW
);
minZ = Math.min(
Plane_default.getPointDistance(plane, perimeterCartesianNW),
Plane_default.getPointDistance(plane, perimeterCartesianSW)
);
maxZ = maximumHeight;
return fromPlaneExtents(
tangentPlane.origin,
tangentPlane.xAxis,
tangentPlane.yAxis,
tangentPlane.zAxis,
minX,
maxX,
minY,
maxY,
minZ,
maxZ,
result
);
}
const fullyAboveEquator = rectangle.south > 0;
const fullyBelowEquator = rectangle.north < 0;
const latitudeNearestToEquator = fullyAboveEquator ? rectangle.south : fullyBelowEquator ? rectangle.north : 0;
const centerLongitude = Rectangle_default.center(
rectangle,
scratchRectangleCenterCartographic
).longitude;
const planeOrigin = Cartesian3_default.fromRadians(
centerLongitude,
latitudeNearestToEquator,
maximumHeight,
ellipsoid,
scratchPlaneOrigin
);
planeOrigin.z = 0;
const isPole = Math.abs(planeOrigin.x) < Math_default.EPSILON10 && Math.abs(planeOrigin.y) < Math_default.EPSILON10;
const planeNormal = !isPole ? Cartesian3_default.normalize(planeOrigin, scratchPlaneNormal2) : Cartesian3_default.UNIT_X;
const planeYAxis = Cartesian3_default.UNIT_Z;
const planeXAxis = Cartesian3_default.cross(
planeNormal,
planeYAxis,
scratchPlaneXAxis
);
plane = Plane_default.fromPointNormal(planeOrigin, planeNormal, scratchPlane2);
const horizonCartesian = Cartesian3_default.fromRadians(
centerLongitude + Math_default.PI_OVER_TWO,
latitudeNearestToEquator,
maximumHeight,
ellipsoid,
scratchHorizonCartesian
);
maxX = Cartesian3_default.dot(
Plane_default.projectPointOntoPlane(
plane,
horizonCartesian,
scratchHorizonProjected
),
planeXAxis
);
minX = -maxX;
maxY = Cartesian3_default.fromRadians(
0,
rectangle.north,
fullyBelowEquator ? minimumHeight : maximumHeight,
ellipsoid,
scratchMaxY
).z;
minY = Cartesian3_default.fromRadians(
0,
rectangle.south,
fullyAboveEquator ? minimumHeight : maximumHeight,
ellipsoid,
scratchMinY
).z;
const farZ = Cartesian3_default.fromRadians(
rectangle.east,
latitudeNearestToEquator,
maximumHeight,
ellipsoid,
scratchZ
);
minZ = Plane_default.getPointDistance(plane, farZ);
maxZ = 0;
return fromPlaneExtents(
planeOrigin,
planeXAxis,
planeYAxis,
planeNormal,
minX,
maxX,
minY,
maxY,
minZ,
maxZ,
result
);
};
OrientedBoundingBox.fromTransformation = function(transformation, result) {
Check_default.typeOf.object("transformation", transformation);
if (!defined_default(result)) {
result = new OrientedBoundingBox();
}
result.center = Matrix4_default.getTranslation(transformation, result.center);
result.halfAxes = Matrix4_default.getMatrix3(transformation, result.halfAxes);
result.halfAxes = Matrix3_default.multiplyByScalar(
result.halfAxes,
0.5,
result.halfAxes
);
return result;
};
OrientedBoundingBox.clone = function(box, result) {
if (!defined_default(box)) {
return void 0;
}
if (!defined_default(result)) {
return new OrientedBoundingBox(box.center, box.halfAxes);
}
Cartesian3_default.clone(box.center, result.center);
Matrix3_default.clone(box.halfAxes, result.halfAxes);
return result;
};
OrientedBoundingBox.intersectPlane = function(box, plane) {
if (!defined_default(box)) {
throw new DeveloperError_default("box is required.");
}
if (!defined_default(plane)) {
throw new DeveloperError_default("plane is required.");
}
const center = box.center;
const normal2 = plane.normal;
const halfAxes = box.halfAxes;
const normalX = normal2.x, normalY = normal2.y, normalZ = normal2.z;
const radEffective = Math.abs(
normalX * halfAxes[Matrix3_default.COLUMN0ROW0] + normalY * halfAxes[Matrix3_default.COLUMN0ROW1] + normalZ * halfAxes[Matrix3_default.COLUMN0ROW2]
) + Math.abs(
normalX * halfAxes[Matrix3_default.COLUMN1ROW0] + normalY * halfAxes[Matrix3_default.COLUMN1ROW1] + normalZ * halfAxes[Matrix3_default.COLUMN1ROW2]
) + Math.abs(
normalX * halfAxes[Matrix3_default.COLUMN2ROW0] + normalY * halfAxes[Matrix3_default.COLUMN2ROW1] + normalZ * halfAxes[Matrix3_default.COLUMN2ROW2]
);
const distanceToPlane = Cartesian3_default.dot(normal2, center) + plane.distance;
if (distanceToPlane <= -radEffective) {
return Intersect_default.OUTSIDE;
} else if (distanceToPlane >= radEffective) {
return Intersect_default.INSIDE;
}
return Intersect_default.INTERSECTING;
};
var scratchCartesianU = new Cartesian3_default();
var scratchCartesianV = new Cartesian3_default();
var scratchCartesianW = new Cartesian3_default();
var scratchValidAxis2 = new Cartesian3_default();
var scratchValidAxis3 = new Cartesian3_default();
var scratchPPrime = new Cartesian3_default();
OrientedBoundingBox.distanceSquaredTo = function(box, cartesian11) {
if (!defined_default(box)) {
throw new DeveloperError_default("box is required.");
}
if (!defined_default(cartesian11)) {
throw new DeveloperError_default("cartesian is required.");
}
const offset = Cartesian3_default.subtract(cartesian11, box.center, scratchOffset);
const halfAxes = box.halfAxes;
let u3 = Matrix3_default.getColumn(halfAxes, 0, scratchCartesianU);
let v3 = Matrix3_default.getColumn(halfAxes, 1, scratchCartesianV);
let w = Matrix3_default.getColumn(halfAxes, 2, scratchCartesianW);
const uHalf = Cartesian3_default.magnitude(u3);
const vHalf = Cartesian3_default.magnitude(v3);
const wHalf = Cartesian3_default.magnitude(w);
let uValid = true;
let vValid = true;
let wValid = true;
if (uHalf > 0) {
Cartesian3_default.divideByScalar(u3, uHalf, u3);
} else {
uValid = false;
}
if (vHalf > 0) {
Cartesian3_default.divideByScalar(v3, vHalf, v3);
} else {
vValid = false;
}
if (wHalf > 0) {
Cartesian3_default.divideByScalar(w, wHalf, w);
} else {
wValid = false;
}
const numberOfDegenerateAxes = !uValid + !vValid + !wValid;
let validAxis1;
let validAxis2;
let validAxis3;
if (numberOfDegenerateAxes === 1) {
let degenerateAxis = u3;
validAxis1 = v3;
validAxis2 = w;
if (!vValid) {
degenerateAxis = v3;
validAxis1 = u3;
} else if (!wValid) {
degenerateAxis = w;
validAxis2 = u3;
}
validAxis3 = Cartesian3_default.cross(validAxis1, validAxis2, scratchValidAxis3);
if (degenerateAxis === u3) {
u3 = validAxis3;
} else if (degenerateAxis === v3) {
v3 = validAxis3;
} else if (degenerateAxis === w) {
w = validAxis3;
}
} else if (numberOfDegenerateAxes === 2) {
validAxis1 = u3;
if (vValid) {
validAxis1 = v3;
} else if (wValid) {
validAxis1 = w;
}
let crossVector = Cartesian3_default.UNIT_Y;
if (crossVector.equalsEpsilon(validAxis1, Math_default.EPSILON3)) {
crossVector = Cartesian3_default.UNIT_X;
}
validAxis2 = Cartesian3_default.cross(validAxis1, crossVector, scratchValidAxis2);
Cartesian3_default.normalize(validAxis2, validAxis2);
validAxis3 = Cartesian3_default.cross(validAxis1, validAxis2, scratchValidAxis3);
Cartesian3_default.normalize(validAxis3, validAxis3);
if (validAxis1 === u3) {
v3 = validAxis2;
w = validAxis3;
} else if (validAxis1 === v3) {
w = validAxis2;
u3 = validAxis3;
} else if (validAxis1 === w) {
u3 = validAxis2;
v3 = validAxis3;
}
} else if (numberOfDegenerateAxes === 3) {
u3 = Cartesian3_default.UNIT_X;
v3 = Cartesian3_default.UNIT_Y;
w = Cartesian3_default.UNIT_Z;
}
const pPrime = scratchPPrime;
pPrime.x = Cartesian3_default.dot(offset, u3);
pPrime.y = Cartesian3_default.dot(offset, v3);
pPrime.z = Cartesian3_default.dot(offset, w);
let distanceSquared = 0;
let d;
if (pPrime.x < -uHalf) {
d = pPrime.x + uHalf;
distanceSquared += d * d;
} else if (pPrime.x > uHalf) {
d = pPrime.x - uHalf;
distanceSquared += d * d;
}
if (pPrime.y < -vHalf) {
d = pPrime.y + vHalf;
distanceSquared += d * d;
} else if (pPrime.y > vHalf) {
d = pPrime.y - vHalf;
distanceSquared += d * d;
}
if (pPrime.z < -wHalf) {
d = pPrime.z + wHalf;
distanceSquared += d * d;
} else if (pPrime.z > wHalf) {
d = pPrime.z - wHalf;
distanceSquared += d * d;
}
return distanceSquared;
};
var scratchCorner = new Cartesian3_default();
var scratchToCenter = new Cartesian3_default();
OrientedBoundingBox.computePlaneDistances = function(box, position, direction2, result) {
if (!defined_default(box)) {
throw new DeveloperError_default("box is required.");
}
if (!defined_default(position)) {
throw new DeveloperError_default("position is required.");
}
if (!defined_default(direction2)) {
throw new DeveloperError_default("direction is required.");
}
if (!defined_default(result)) {
result = new Interval_default();
}
let minDist = Number.POSITIVE_INFINITY;
let maxDist = Number.NEGATIVE_INFINITY;
const center = box.center;
const halfAxes = box.halfAxes;
const u3 = Matrix3_default.getColumn(halfAxes, 0, scratchCartesianU);
const v3 = Matrix3_default.getColumn(halfAxes, 1, scratchCartesianV);
const w = Matrix3_default.getColumn(halfAxes, 2, scratchCartesianW);
const corner = Cartesian3_default.add(u3, v3, scratchCorner);
Cartesian3_default.add(corner, w, corner);
Cartesian3_default.add(corner, center, corner);
const toCenter = Cartesian3_default.subtract(corner, position, scratchToCenter);
let mag = Cartesian3_default.dot(direction2, toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
Cartesian3_default.add(center, u3, corner);
Cartesian3_default.add(corner, v3, corner);
Cartesian3_default.subtract(corner, w, corner);
Cartesian3_default.subtract(corner, position, toCenter);
mag = Cartesian3_default.dot(direction2, toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
Cartesian3_default.add(center, u3, corner);
Cartesian3_default.subtract(corner, v3, corner);
Cartesian3_default.add(corner, w, corner);
Cartesian3_default.subtract(corner, position, toCenter);
mag = Cartesian3_default.dot(direction2, toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
Cartesian3_default.add(center, u3, corner);
Cartesian3_default.subtract(corner, v3, corner);
Cartesian3_default.subtract(corner, w, corner);
Cartesian3_default.subtract(corner, position, toCenter);
mag = Cartesian3_default.dot(direction2, toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
Cartesian3_default.subtract(center, u3, corner);
Cartesian3_default.add(corner, v3, corner);
Cartesian3_default.add(corner, w, corner);
Cartesian3_default.subtract(corner, position, toCenter);
mag = Cartesian3_default.dot(direction2, toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
Cartesian3_default.subtract(center, u3, corner);
Cartesian3_default.add(corner, v3, corner);
Cartesian3_default.subtract(corner, w, corner);
Cartesian3_default.subtract(corner, position, toCenter);
mag = Cartesian3_default.dot(direction2, toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
Cartesian3_default.subtract(center, u3, corner);
Cartesian3_default.subtract(corner, v3, corner);
Cartesian3_default.add(corner, w, corner);
Cartesian3_default.subtract(corner, position, toCenter);
mag = Cartesian3_default.dot(direction2, toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
Cartesian3_default.subtract(center, u3, corner);
Cartesian3_default.subtract(corner, v3, corner);
Cartesian3_default.subtract(corner, w, corner);
Cartesian3_default.subtract(corner, position, toCenter);
mag = Cartesian3_default.dot(direction2, toCenter);
minDist = Math.min(mag, minDist);
maxDist = Math.max(mag, maxDist);
result.start = minDist;
result.stop = maxDist;
return result;
};
var scratchXAxis = new Cartesian3_default();
var scratchYAxis = new Cartesian3_default();
var scratchZAxis = new Cartesian3_default();
OrientedBoundingBox.computeCorners = function(box, result) {
Check_default.typeOf.object("box", box);
if (!defined_default(result)) {
result = [
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default()
];
}
const center = box.center;
const halfAxes = box.halfAxes;
const xAxis = Matrix3_default.getColumn(halfAxes, 0, scratchXAxis);
const yAxis = Matrix3_default.getColumn(halfAxes, 1, scratchYAxis);
const zAxis = Matrix3_default.getColumn(halfAxes, 2, scratchZAxis);
Cartesian3_default.clone(center, result[0]);
Cartesian3_default.subtract(result[0], xAxis, result[0]);
Cartesian3_default.subtract(result[0], yAxis, result[0]);
Cartesian3_default.subtract(result[0], zAxis, result[0]);
Cartesian3_default.clone(center, result[1]);
Cartesian3_default.subtract(result[1], xAxis, result[1]);
Cartesian3_default.subtract(result[1], yAxis, result[1]);
Cartesian3_default.add(result[1], zAxis, result[1]);
Cartesian3_default.clone(center, result[2]);
Cartesian3_default.subtract(result[2], xAxis, result[2]);
Cartesian3_default.add(result[2], yAxis, result[2]);
Cartesian3_default.subtract(result[2], zAxis, result[2]);
Cartesian3_default.clone(center, result[3]);
Cartesian3_default.subtract(result[3], xAxis, result[3]);
Cartesian3_default.add(result[3], yAxis, result[3]);
Cartesian3_default.add(result[3], zAxis, result[3]);
Cartesian3_default.clone(center, result[4]);
Cartesian3_default.add(result[4], xAxis, result[4]);
Cartesian3_default.subtract(result[4], yAxis, result[4]);
Cartesian3_default.subtract(result[4], zAxis, result[4]);
Cartesian3_default.clone(center, result[5]);
Cartesian3_default.add(result[5], xAxis, result[5]);
Cartesian3_default.subtract(result[5], yAxis, result[5]);
Cartesian3_default.add(result[5], zAxis, result[5]);
Cartesian3_default.clone(center, result[6]);
Cartesian3_default.add(result[6], xAxis, result[6]);
Cartesian3_default.add(result[6], yAxis, result[6]);
Cartesian3_default.subtract(result[6], zAxis, result[6]);
Cartesian3_default.clone(center, result[7]);
Cartesian3_default.add(result[7], xAxis, result[7]);
Cartesian3_default.add(result[7], yAxis, result[7]);
Cartesian3_default.add(result[7], zAxis, result[7]);
return result;
};
var scratchRotationScale = new Matrix3_default();
OrientedBoundingBox.computeTransformation = function(box, result) {
Check_default.typeOf.object("box", box);
if (!defined_default(result)) {
result = new Matrix4_default();
}
const translation3 = box.center;
const rotationScale = Matrix3_default.multiplyByUniformScale(
box.halfAxes,
2,
scratchRotationScale
);
return Matrix4_default.fromRotationTranslation(rotationScale, translation3, result);
};
var scratchBoundingSphere2 = new BoundingSphere_default();
OrientedBoundingBox.isOccluded = function(box, occluder) {
if (!defined_default(box)) {
throw new DeveloperError_default("box is required.");
}
if (!defined_default(occluder)) {
throw new DeveloperError_default("occluder is required.");
}
const sphere = BoundingSphere_default.fromOrientedBoundingBox(
box,
scratchBoundingSphere2
);
return !occluder.isBoundingSphereVisible(sphere);
};
OrientedBoundingBox.prototype.intersectPlane = function(plane) {
return OrientedBoundingBox.intersectPlane(this, plane);
};
OrientedBoundingBox.prototype.distanceSquaredTo = function(cartesian11) {
return OrientedBoundingBox.distanceSquaredTo(this, cartesian11);
};
OrientedBoundingBox.prototype.computePlaneDistances = function(position, direction2, result) {
return OrientedBoundingBox.computePlaneDistances(
this,
position,
direction2,
result
);
};
OrientedBoundingBox.prototype.computeCorners = function(result) {
return OrientedBoundingBox.computeCorners(this, result);
};
OrientedBoundingBox.prototype.computeTransformation = function(result) {
return OrientedBoundingBox.computeTransformation(this, result);
};
OrientedBoundingBox.prototype.isOccluded = function(occluder) {
return OrientedBoundingBox.isOccluded(this, occluder);
};
OrientedBoundingBox.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && Cartesian3_default.equals(left.center, right.center) && Matrix3_default.equals(left.halfAxes, right.halfAxes);
};
OrientedBoundingBox.prototype.clone = function(result) {
return OrientedBoundingBox.clone(this, result);
};
OrientedBoundingBox.prototype.equals = function(right) {
return OrientedBoundingBox.equals(this, right);
};
var OrientedBoundingBox_default = OrientedBoundingBox;
// packages/engine/Source/Core/VerticalExaggeration.js
var import_InlineWorkers351 = __toESM(require_InlineWorkers(), 1);
var VerticalExaggeration = {};
VerticalExaggeration.getHeight = function(height, scale, relativeHeight) {
if (!Number.isFinite(scale)) {
throw new DeveloperError_default("scale must be a finite number.");
}
if (!Number.isFinite(relativeHeight)) {
throw new DeveloperError_default("relativeHeight must be a finite number.");
}
return (height - relativeHeight) * scale + relativeHeight;
};
var scratchCartographic2 = new Cartographic_default();
VerticalExaggeration.getPosition = function(position, ellipsoid, verticalExaggeration, verticalExaggerationRelativeHeight, result) {
const cartographic2 = ellipsoid.cartesianToCartographic(
position,
scratchCartographic2
);
if (!defined_default(cartographic2)) {
return Cartesian3_default.clone(position, result);
}
const newHeight = VerticalExaggeration.getHeight(
cartographic2.height,
verticalExaggeration,
verticalExaggerationRelativeHeight
);
return Cartesian3_default.fromRadians(
cartographic2.longitude,
cartographic2.latitude,
newHeight,
ellipsoid,
result
);
};
var VerticalExaggeration_default = VerticalExaggeration;
// packages/engine/Source/Scene/ClassificationPrimitive.js
var import_InlineWorkers369 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/ShadowVolumeAppearanceVS.js
var import_InlineWorkers352 = __toESM(require_InlineWorkers(), 1);
var ShadowVolumeAppearanceVS_default = 'in vec3 position3DHigh;\nin vec3 position3DLow;\nin float batchId;\n\n#ifdef EXTRUDED_GEOMETRY\nin vec3 extrudeDirection;\n\nuniform float u_globeMinimumAltitude;\n#endif // EXTRUDED_GEOMETRY\n\n#ifdef PER_INSTANCE_COLOR\nout vec4 v_color;\n#endif // PER_INSTANCE_COLOR\n\n#ifdef TEXTURE_COORDINATES\n#ifdef SPHERICAL\nout vec4 v_sphericalExtents;\n#else // SPHERICAL\nout vec2 v_inversePlaneExtents;\nout vec4 v_westPlane;\nout vec4 v_southPlane;\n#endif // SPHERICAL\nout vec3 v_uvMinAndSphericalLongitudeRotation;\nout vec3 v_uMaxAndInverseDistance;\nout vec3 v_vMaxAndInverseDistance;\n#endif // TEXTURE_COORDINATES\n\nvoid main()\n{\n vec4 position = czm_computePosition();\n\n#ifdef EXTRUDED_GEOMETRY\n float delta = min(u_globeMinimumAltitude, czm_geometricToleranceOverMeter * length(position.xyz));\n delta *= czm_sceneMode == czm_sceneMode3D ? 1.0 : 0.0;\n\n //extrudeDirection is zero for the top layer\n position = position + vec4(extrudeDirection * delta, 0.0);\n#endif\n\n#ifdef TEXTURE_COORDINATES\n#ifdef SPHERICAL\n v_sphericalExtents = czm_batchTable_sphericalExtents(batchId);\n v_uvMinAndSphericalLongitudeRotation.z = czm_batchTable_longitudeRotation(batchId);\n#else // SPHERICAL\n#ifdef COLUMBUS_VIEW_2D\n vec4 planes2D_high = czm_batchTable_planes2D_HIGH(batchId);\n vec4 planes2D_low = czm_batchTable_planes2D_LOW(batchId);\n\n // If the primitive is split across the IDL (planes2D_high.x > planes2D_high.w):\n // - If this vertex is on the east side of the IDL (position3DLow.y > 0.0, comparison with position3DHigh may produce artifacts)\n // - existing "east" is on the wrong side of the world, far away (planes2D_high/low.w)\n // - so set "east" as beyond the eastmost extent of the projection (idlSplitNewPlaneHiLow)\n vec2 idlSplitNewPlaneHiLow = vec2(EAST_MOST_X_HIGH - (WEST_MOST_X_HIGH - planes2D_high.w), EAST_MOST_X_LOW - (WEST_MOST_X_LOW - planes2D_low.w));\n bool idlSplit = planes2D_high.x > planes2D_high.w && position3DLow.y > 0.0;\n planes2D_high.w = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.x, planes2D_high.w);\n planes2D_low.w = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.y, planes2D_low.w);\n\n // - else, if this vertex is on the west side of the IDL (position3DLow.y < 0.0)\n // - existing "west" is on the wrong side of the world, far away (planes2D_high/low.x)\n // - so set "west" as beyond the westmost extent of the projection (idlSplitNewPlaneHiLow)\n idlSplit = planes2D_high.x > planes2D_high.w && position3DLow.y < 0.0;\n idlSplitNewPlaneHiLow = vec2(WEST_MOST_X_HIGH - (EAST_MOST_X_HIGH - planes2D_high.x), WEST_MOST_X_LOW - (EAST_MOST_X_LOW - planes2D_low.x));\n planes2D_high.x = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.x, planes2D_high.x);\n planes2D_low.x = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.y, planes2D_low.x);\n\n vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.xy), vec3(0.0, planes2D_low.xy))).xyz;\n vec3 northWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.x, planes2D_high.z), vec3(0.0, planes2D_low.x, planes2D_low.z))).xyz;\n vec3 southEastCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.w, planes2D_high.y), vec3(0.0, planes2D_low.w, planes2D_low.y))).xyz;\n#else // COLUMBUS_VIEW_2D\n // 3D case has smaller "plane extents," so planes encoded as a 64 bit position and 2 vec3s for distances/direction\n vec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_southWest_HIGH(batchId), czm_batchTable_southWest_LOW(batchId))).xyz;\n vec3 northWestCorner = czm_normal * czm_batchTable_northward(batchId) + southWestCorner;\n vec3 southEastCorner = czm_normal * czm_batchTable_eastward(batchId) + southWestCorner;\n#endif // COLUMBUS_VIEW_2D\n\n vec3 eastWard = southEastCorner - southWestCorner;\n float eastExtent = length(eastWard);\n eastWard /= eastExtent;\n\n vec3 northWard = northWestCorner - southWestCorner;\n float northExtent = length(northWard);\n northWard /= northExtent;\n\n v_westPlane = vec4(eastWard, -dot(eastWard, southWestCorner));\n v_southPlane = vec4(northWard, -dot(northWard, southWestCorner));\n v_inversePlaneExtents = vec2(1.0 / eastExtent, 1.0 / northExtent);\n#endif // SPHERICAL\n vec4 uvMinAndExtents = czm_batchTable_uvMinAndExtents(batchId);\n vec4 uMaxVmax = czm_batchTable_uMaxVmax(batchId);\n\n v_uMaxAndInverseDistance = vec3(uMaxVmax.xy, uvMinAndExtents.z);\n v_vMaxAndInverseDistance = vec3(uMaxVmax.zw, uvMinAndExtents.w);\n v_uvMinAndSphericalLongitudeRotation.xy = uvMinAndExtents.xy;\n#endif // TEXTURE_COORDINATES\n\n#ifdef PER_INSTANCE_COLOR\n v_color = czm_batchTable_color(batchId);\n#endif\n\n gl_Position = czm_depthClamp(czm_modelViewProjectionRelativeToEye * position);\n}\n';
// packages/engine/Source/Shaders/ShadowVolumeFS.js
var import_InlineWorkers353 = __toESM(require_InlineWorkers(), 1);
var ShadowVolumeFS_default = "#ifdef VECTOR_TILE\nuniform vec4 u_highlightColor;\n#endif\n\nvoid main(void)\n{\n#ifdef VECTOR_TILE\n out_FragColor = czm_gammaCorrect(u_highlightColor);\n#else\n out_FragColor = vec4(1.0);\n#endif\n czm_writeDepthClamp();\n}\n";
// packages/engine/Source/Scene/ClassificationType.js
var import_InlineWorkers354 = __toESM(require_InlineWorkers(), 1);
var ClassificationType = {
/**
* Only terrain will be classified.
*
* @type {number}
* @constant
*/
TERRAIN: 0,
/**
* Only 3D Tiles will be classified.
*
* @type {number}
* @constant
*/
CESIUM_3D_TILE: 1,
/**
* Both terrain and 3D Tiles will be classified.
*
* @type {number}
* @constant
*/
BOTH: 2
};
ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES = 3;
var ClassificationType_default = Object.freeze(ClassificationType);
// packages/engine/Source/Scene/DepthFunction.js
var import_InlineWorkers355 = __toESM(require_InlineWorkers(), 1);
var DepthFunction = {
/**
* The depth test never passes.
*
* @type {number}
* @constant
*/
NEVER: WebGLConstants_default.NEVER,
/**
* The depth test passes if the incoming depth is less than the stored depth.
*
* @type {number}
* @constant
*/
LESS: WebGLConstants_default.LESS,
/**
* The depth test passes if the incoming depth is equal to the stored depth.
*
* @type {number}
* @constant
*/
EQUAL: WebGLConstants_default.EQUAL,
/**
* The depth test passes if the incoming depth is less than or equal to the stored depth.
*
* @type {number}
* @constant
*/
LESS_OR_EQUAL: WebGLConstants_default.LEQUAL,
/**
* The depth test passes if the incoming depth is greater than the stored depth.
*
* @type {number}
* @constant
*/
GREATER: WebGLConstants_default.GREATER,
/**
* The depth test passes if the incoming depth is not equal to the stored depth.
*
* @type {number}
* @constant
*/
NOT_EQUAL: WebGLConstants_default.NOTEQUAL,
/**
* The depth test passes if the incoming depth is greater than or equal to the stored depth.
*
* @type {number}
* @constant
*/
GREATER_OR_EQUAL: WebGLConstants_default.GEQUAL,
/**
* The depth test always passes.
*
* @type {number}
* @constant
*/
ALWAYS: WebGLConstants_default.ALWAYS
};
var DepthFunction_default = Object.freeze(DepthFunction);
// packages/engine/Source/Scene/Primitive.js
var import_InlineWorkers362 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/subdivideArray.js
var import_InlineWorkers356 = __toESM(require_InlineWorkers(), 1);
function subdivideArray(array, numberOfArrays) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required.");
}
if (!defined_default(numberOfArrays) || numberOfArrays < 1) {
throw new DeveloperError_default("numberOfArrays must be greater than 0.");
}
const result = [];
const len = array.length;
let i = 0;
while (i < len) {
const size = Math.ceil((len - i) / numberOfArrays--);
result.push(array.slice(i, i + size));
i += size;
}
return result;
}
var subdivideArray_default = subdivideArray;
// packages/engine/Source/Scene/BatchTable.js
var import_InlineWorkers357 = __toESM(require_InlineWorkers(), 1);
function BatchTable(context, attributes, numberOfInstances) {
if (!defined_default(context)) {
throw new DeveloperError_default("context is required");
}
if (!defined_default(attributes)) {
throw new DeveloperError_default("attributes is required");
}
if (!defined_default(numberOfInstances)) {
throw new DeveloperError_default("numberOfInstances is required");
}
this._attributes = attributes;
this._numberOfInstances = numberOfInstances;
if (attributes.length === 0) {
return;
}
const pixelDatatype = getDatatype(attributes);
const textureFloatSupported = context.floatingPointTexture;
const packFloats = pixelDatatype === PixelDatatype_default.FLOAT && !textureFloatSupported;
const offsets = createOffsets(attributes, packFloats);
const stride = getStride(offsets, attributes, packFloats);
const maxNumberOfInstancesPerRow = Math.floor(
ContextLimits_default.maximumTextureSize / stride
);
const instancesPerWidth = Math.min(
numberOfInstances,
maxNumberOfInstancesPerRow
);
const width = stride * instancesPerWidth;
const height = Math.ceil(numberOfInstances / instancesPerWidth);
const stepX = 1 / width;
const centerX = stepX * 0.5;
const stepY = 1 / height;
const centerY = stepY * 0.5;
this._textureDimensions = new Cartesian2_default(width, height);
this._textureStep = new Cartesian4_default(stepX, centerX, stepY, centerY);
this._pixelDatatype = !packFloats ? pixelDatatype : PixelDatatype_default.UNSIGNED_BYTE;
this._packFloats = packFloats;
this._offsets = offsets;
this._stride = stride;
this._texture = void 0;
const batchLength = 4 * width * height;
this._batchValues = pixelDatatype === PixelDatatype_default.FLOAT && !packFloats ? new Float32Array(batchLength) : new Uint8Array(batchLength);
this._batchValuesDirty = false;
}
Object.defineProperties(BatchTable.prototype, {
/**
* The attribute descriptions.
* @memberOf BatchTable.prototype
* @type {Object[]}
* @readonly
*/
attributes: {
get: function() {
return this._attributes;
}
},
/**
* The number of instances.
* @memberOf BatchTable.prototype
* @type {number}
* @readonly
*/
numberOfInstances: {
get: function() {
return this._numberOfInstances;
}
}
});
function getDatatype(attributes) {
let foundFloatDatatype = false;
const length2 = attributes.length;
for (let i = 0; i < length2; ++i) {
if (attributes[i].componentDatatype !== ComponentDatatype_default.UNSIGNED_BYTE) {
foundFloatDatatype = true;
break;
}
}
return foundFloatDatatype ? PixelDatatype_default.FLOAT : PixelDatatype_default.UNSIGNED_BYTE;
}
function getAttributeType(attributes, attributeIndex) {
const componentsPerAttribute = attributes[attributeIndex].componentsPerAttribute;
if (componentsPerAttribute === 2) {
return Cartesian2_default;
} else if (componentsPerAttribute === 3) {
return Cartesian3_default;
} else if (componentsPerAttribute === 4) {
return Cartesian4_default;
}
return Number;
}
function createOffsets(attributes, packFloats) {
const offsets = new Array(attributes.length);
let currentOffset = 0;
const attributesLength = attributes.length;
for (let i = 0; i < attributesLength; ++i) {
const attribute = attributes[i];
const componentDatatype = attribute.componentDatatype;
offsets[i] = currentOffset;
if (componentDatatype !== ComponentDatatype_default.UNSIGNED_BYTE && packFloats) {
currentOffset += 4;
} else {
++currentOffset;
}
}
return offsets;
}
function getStride(offsets, attributes, packFloats) {
const length2 = offsets.length;
const lastOffset = offsets[length2 - 1];
const lastAttribute = attributes[length2 - 1];
const componentDatatype = lastAttribute.componentDatatype;
if (componentDatatype !== ComponentDatatype_default.UNSIGNED_BYTE && packFloats) {
return lastOffset + 4;
}
return lastOffset + 1;
}
var scratchPackedFloatCartesian4 = new Cartesian4_default();
function getPackedFloat(array, index, result) {
let packed = Cartesian4_default.unpack(array, index, scratchPackedFloatCartesian4);
const x = Cartesian4_default.unpackFloat(packed);
packed = Cartesian4_default.unpack(array, index + 4, scratchPackedFloatCartesian4);
const y = Cartesian4_default.unpackFloat(packed);
packed = Cartesian4_default.unpack(array, index + 8, scratchPackedFloatCartesian4);
const z = Cartesian4_default.unpackFloat(packed);
packed = Cartesian4_default.unpack(array, index + 12, scratchPackedFloatCartesian4);
const w = Cartesian4_default.unpackFloat(packed);
return Cartesian4_default.fromElements(x, y, z, w, result);
}
function setPackedAttribute(value, array, index) {
let packed = Cartesian4_default.packFloat(value.x, scratchPackedFloatCartesian4);
Cartesian4_default.pack(packed, array, index);
packed = Cartesian4_default.packFloat(value.y, packed);
Cartesian4_default.pack(packed, array, index + 4);
packed = Cartesian4_default.packFloat(value.z, packed);
Cartesian4_default.pack(packed, array, index + 8);
packed = Cartesian4_default.packFloat(value.w, packed);
Cartesian4_default.pack(packed, array, index + 12);
}
var scratchGetAttributeCartesian4 = new Cartesian4_default();
BatchTable.prototype.getBatchedAttribute = function(instanceIndex, attributeIndex, result) {
if (instanceIndex < 0 || instanceIndex >= this._numberOfInstances) {
throw new DeveloperError_default("instanceIndex is out of range.");
}
if (attributeIndex < 0 || attributeIndex >= this._attributes.length) {
throw new DeveloperError_default("attributeIndex is out of range");
}
const attributes = this._attributes;
const offset = this._offsets[attributeIndex];
const stride = this._stride;
const index = 4 * stride * instanceIndex + 4 * offset;
let value;
if (this._packFloats && attributes[attributeIndex].componentDatatype !== PixelDatatype_default.UNSIGNED_BYTE) {
value = getPackedFloat(
this._batchValues,
index,
scratchGetAttributeCartesian4
);
} else {
value = Cartesian4_default.unpack(
this._batchValues,
index,
scratchGetAttributeCartesian4
);
}
const attributeType = getAttributeType(attributes, attributeIndex);
if (defined_default(attributeType.fromCartesian4)) {
return attributeType.fromCartesian4(value, result);
} else if (defined_default(attributeType.clone)) {
return attributeType.clone(value, result);
}
return value.x;
};
var setAttributeScratchValues = [
void 0,
void 0,
new Cartesian2_default(),
new Cartesian3_default(),
new Cartesian4_default()
];
var setAttributeScratchCartesian4 = new Cartesian4_default();
BatchTable.prototype.setBatchedAttribute = function(instanceIndex, attributeIndex, value) {
if (instanceIndex < 0 || instanceIndex >= this._numberOfInstances) {
throw new DeveloperError_default("instanceIndex is out of range.");
}
if (attributeIndex < 0 || attributeIndex >= this._attributes.length) {
throw new DeveloperError_default("attributeIndex is out of range");
}
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const attributes = this._attributes;
const result = setAttributeScratchValues[attributes[attributeIndex].componentsPerAttribute];
const currentAttribute = this.getBatchedAttribute(
instanceIndex,
attributeIndex,
result
);
const attributeType = getAttributeType(this._attributes, attributeIndex);
const entriesEqual = defined_default(attributeType.equals) ? attributeType.equals(currentAttribute, value) : currentAttribute === value;
if (entriesEqual) {
return;
}
const attributeValue = setAttributeScratchCartesian4;
attributeValue.x = defined_default(value.x) ? value.x : value;
attributeValue.y = defined_default(value.y) ? value.y : 0;
attributeValue.z = defined_default(value.z) ? value.z : 0;
attributeValue.w = defined_default(value.w) ? value.w : 0;
const offset = this._offsets[attributeIndex];
const stride = this._stride;
const index = 4 * stride * instanceIndex + 4 * offset;
if (this._packFloats && attributes[attributeIndex].componentDatatype !== PixelDatatype_default.UNSIGNED_BYTE) {
setPackedAttribute(attributeValue, this._batchValues, index);
} else {
Cartesian4_default.pack(attributeValue, this._batchValues, index);
}
this._batchValuesDirty = true;
};
function createTexture(batchTable, context) {
const dimensions = batchTable._textureDimensions;
batchTable._texture = new Texture_default({
context,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: batchTable._pixelDatatype,
width: dimensions.x,
height: dimensions.y,
sampler: Sampler_default.NEAREST,
flipY: false
});
}
function updateTexture(batchTable) {
const dimensions = batchTable._textureDimensions;
batchTable._texture.copyFrom({
source: {
width: dimensions.x,
height: dimensions.y,
arrayBufferView: batchTable._batchValues
}
});
}
BatchTable.prototype.update = function(frameState) {
if (defined_default(this._texture) && !this._batchValuesDirty || this._attributes.length === 0) {
return;
}
this._batchValuesDirty = false;
if (!defined_default(this._texture)) {
createTexture(this, frameState.context);
}
updateTexture(this);
};
BatchTable.prototype.getUniformMapCallback = function() {
const that = this;
return function(uniformMap2) {
if (that._attributes.length === 0) {
return uniformMap2;
}
const batchUniformMap = {
batchTexture: function() {
return that._texture;
},
batchTextureDimensions: function() {
return that._textureDimensions;
},
batchTextureStep: function() {
return that._textureStep;
}
};
return combine_default(uniformMap2, batchUniformMap);
};
};
function getGlslComputeSt(batchTable) {
const stride = batchTable._stride;
if (batchTable._textureDimensions.y === 1) {
return `${"uniform vec4 batchTextureStep; \nvec2 computeSt(float batchId) \n{ \n float stepX = batchTextureStep.x; \n float centerX = batchTextureStep.y; \n float numberOfAttributes = float("}${stride});
return vec2(centerX + (batchId * numberOfAttributes * stepX), 0.5);
}
`;
}
return `${"uniform vec4 batchTextureStep; \nuniform vec2 batchTextureDimensions; \nvec2 computeSt(float batchId) \n{ \n float stepX = batchTextureStep.x; \n float centerX = batchTextureStep.y; \n float stepY = batchTextureStep.z; \n float centerY = batchTextureStep.w; \n float numberOfAttributes = float("}${stride});
float xId = mod(batchId * numberOfAttributes, batchTextureDimensions.x);
float yId = floor(batchId * numberOfAttributes / batchTextureDimensions.x);
return vec2(centerX + (xId * stepX), centerY + (yId * stepY));
}
`;
}
function getComponentType(componentsPerAttribute) {
if (componentsPerAttribute === 1) {
return "float";
}
return `vec${componentsPerAttribute}`;
}
function getComponentSwizzle(componentsPerAttribute) {
if (componentsPerAttribute === 1) {
return ".x";
} else if (componentsPerAttribute === 2) {
return ".xy";
} else if (componentsPerAttribute === 3) {
return ".xyz";
}
return "";
}
function getGlslAttributeFunction(batchTable, attributeIndex) {
const attributes = batchTable._attributes;
const attribute = attributes[attributeIndex];
const componentsPerAttribute = attribute.componentsPerAttribute;
const functionName = attribute.functionName;
const functionReturnType = getComponentType(componentsPerAttribute);
const functionReturnValue = getComponentSwizzle(componentsPerAttribute);
const offset = batchTable._offsets[attributeIndex];
let glslFunction = `${functionReturnType} ${functionName}(float batchId)
{
vec2 st = computeSt(batchId);
st.x += batchTextureStep.x * float(${offset});
`;
if (batchTable._packFloats && attribute.componentDatatype !== PixelDatatype_default.UNSIGNED_BYTE) {
glslFunction += "vec4 textureValue; \ntextureValue.x = czm_unpackFloat(texture(batchTexture, st)); \ntextureValue.y = czm_unpackFloat(texture(batchTexture, st + vec2(batchTextureStep.x, 0.0))); \ntextureValue.z = czm_unpackFloat(texture(batchTexture, st + vec2(batchTextureStep.x * 2.0, 0.0))); \ntextureValue.w = czm_unpackFloat(texture(batchTexture, st + vec2(batchTextureStep.x * 3.0, 0.0))); \n";
} else {
glslFunction += " vec4 textureValue = texture(batchTexture, st); \n";
}
glslFunction += ` ${functionReturnType} value = textureValue${functionReturnValue};
`;
if (batchTable._pixelDatatype === PixelDatatype_default.UNSIGNED_BYTE && attribute.componentDatatype === ComponentDatatype_default.UNSIGNED_BYTE && !attribute.normalize) {
glslFunction += "value *= 255.0; \n";
} else if (batchTable._pixelDatatype === PixelDatatype_default.FLOAT && attribute.componentDatatype === ComponentDatatype_default.UNSIGNED_BYTE && attribute.normalize) {
glslFunction += "value /= 255.0; \n";
}
glslFunction += " return value; \n} \n";
return glslFunction;
}
BatchTable.prototype.getVertexShaderCallback = function() {
const attributes = this._attributes;
if (attributes.length === 0) {
return function(source) {
return source;
};
}
let batchTableShader = "uniform highp sampler2D batchTexture; \n";
batchTableShader += `${getGlslComputeSt(this)}
`;
const length2 = attributes.length;
for (let i = 0; i < length2; ++i) {
batchTableShader += getGlslAttributeFunction(this, i);
}
return function(source) {
const mainIndex = source.indexOf("void main");
const beforeMain = source.substring(0, mainIndex);
const afterMain = source.substring(mainIndex);
return `${beforeMain}
${batchTableShader}
${afterMain}`;
};
};
BatchTable.prototype.isDestroyed = function() {
return false;
};
BatchTable.prototype.destroy = function() {
this._texture = this._texture && this._texture.destroy();
return destroyObject_default(this);
};
var BatchTable_default = BatchTable;
// packages/engine/Source/Scene/PrimitivePipeline.js
var import_InlineWorkers359 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/WebMercatorProjection.js
var import_InlineWorkers358 = __toESM(require_InlineWorkers(), 1);
function WebMercatorProjection(ellipsoid) {
this._ellipsoid = ellipsoid ?? Ellipsoid_default.WGS84;
this._semimajorAxis = this._ellipsoid.maximumRadius;
this._oneOverSemimajorAxis = 1 / this._semimajorAxis;
}
Object.defineProperties(WebMercatorProjection.prototype, {
/**
* Gets the {@link Ellipsoid}.
*
* @memberof WebMercatorProjection.prototype
*
* @type {Ellipsoid}
* @readonly
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
}
});
WebMercatorProjection.mercatorAngleToGeodeticLatitude = function(mercatorAngle) {
return Math_default.PI_OVER_TWO - 2 * Math.atan(Math.exp(-mercatorAngle));
};
WebMercatorProjection.geodeticLatitudeToMercatorAngle = function(latitude) {
if (latitude > WebMercatorProjection.MaximumLatitude) {
latitude = WebMercatorProjection.MaximumLatitude;
} else if (latitude < -WebMercatorProjection.MaximumLatitude) {
latitude = -WebMercatorProjection.MaximumLatitude;
}
const sinLatitude = Math.sin(latitude);
return 0.5 * Math.log((1 + sinLatitude) / (1 - sinLatitude));
};
WebMercatorProjection.MaximumLatitude = WebMercatorProjection.mercatorAngleToGeodeticLatitude(Math.PI);
WebMercatorProjection.prototype.project = function(cartographic2, result) {
const semimajorAxis = this._semimajorAxis;
const x = cartographic2.longitude * semimajorAxis;
const y = WebMercatorProjection.geodeticLatitudeToMercatorAngle(
cartographic2.latitude
) * semimajorAxis;
const z = cartographic2.height;
if (!defined_default(result)) {
return new Cartesian3_default(x, y, z);
}
result.x = x;
result.y = y;
result.z = z;
return result;
};
WebMercatorProjection.prototype.unproject = function(cartesian11, result) {
if (!defined_default(cartesian11)) {
throw new DeveloperError_default("cartesian is required");
}
const oneOverEarthSemimajorAxis = this._oneOverSemimajorAxis;
const longitude = cartesian11.x * oneOverEarthSemimajorAxis;
const latitude = WebMercatorProjection.mercatorAngleToGeodeticLatitude(
cartesian11.y * oneOverEarthSemimajorAxis
);
const height = cartesian11.z;
if (!defined_default(result)) {
return new Cartographic_default(longitude, latitude, height);
}
result.longitude = longitude;
result.latitude = latitude;
result.height = height;
return result;
};
var WebMercatorProjection_default = WebMercatorProjection;
// packages/engine/Source/Scene/PrimitivePipeline.js
function transformToWorldCoordinates(instances, primitiveModelMatrix, scene3DOnly) {
let toWorld = !scene3DOnly;
const length2 = instances.length;
let i;
if (!toWorld && length2 > 1) {
const modelMatrix = instances[0].modelMatrix;
for (i = 1; i < length2; ++i) {
if (!Matrix4_default.equals(modelMatrix, instances[i].modelMatrix)) {
toWorld = true;
break;
}
}
}
if (toWorld) {
for (i = 0; i < length2; ++i) {
if (defined_default(instances[i].geometry)) {
GeometryPipeline_default.transformToWorldCoordinates(instances[i]);
}
}
} else {
Matrix4_default.multiplyTransformation(
primitiveModelMatrix,
instances[0].modelMatrix,
primitiveModelMatrix
);
}
}
function addGeometryBatchId(geometry, batchId) {
const attributes = geometry.attributes;
const positionAttr = attributes.position;
const numberOfComponents = positionAttr.values.length / positionAttr.componentsPerAttribute;
attributes.batchId = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 1,
values: new Float32Array(numberOfComponents)
});
const values = attributes.batchId.values;
for (let j = 0; j < numberOfComponents; ++j) {
values[j] = batchId;
}
}
function addBatchIds(instances) {
const length2 = instances.length;
for (let i = 0; i < length2; ++i) {
const instance = instances[i];
if (defined_default(instance.geometry)) {
addGeometryBatchId(instance.geometry, i);
} else if (defined_default(instance.westHemisphereGeometry) && defined_default(instance.eastHemisphereGeometry)) {
addGeometryBatchId(instance.westHemisphereGeometry, i);
addGeometryBatchId(instance.eastHemisphereGeometry, i);
}
}
}
function geometryPipeline(parameters) {
const instances = parameters.instances;
const projection = parameters.projection;
const uintIndexSupport = parameters.elementIndexUintSupported;
const scene3DOnly = parameters.scene3DOnly;
const vertexCacheOptimize = parameters.vertexCacheOptimize;
const compressVertices = parameters.compressVertices;
const modelMatrix = parameters.modelMatrix;
let i;
let geometry;
let primitiveType;
let length2 = instances.length;
for (i = 0; i < length2; ++i) {
if (defined_default(instances[i].geometry)) {
primitiveType = instances[i].geometry.primitiveType;
break;
}
}
for (i = 1; i < length2; ++i) {
if (defined_default(instances[i].geometry) && instances[i].geometry.primitiveType !== primitiveType) {
throw new DeveloperError_default(
"All instance geometries must have the same primitiveType."
);
}
}
transformToWorldCoordinates(instances, modelMatrix, scene3DOnly);
if (!scene3DOnly) {
for (i = 0; i < length2; ++i) {
if (defined_default(instances[i].geometry)) {
GeometryPipeline_default.splitLongitude(instances[i]);
}
}
}
addBatchIds(instances);
if (vertexCacheOptimize) {
for (i = 0; i < length2; ++i) {
const instance = instances[i];
if (defined_default(instance.geometry)) {
GeometryPipeline_default.reorderForPostVertexCache(instance.geometry);
GeometryPipeline_default.reorderForPreVertexCache(instance.geometry);
} else if (defined_default(instance.westHemisphereGeometry) && defined_default(instance.eastHemisphereGeometry)) {
GeometryPipeline_default.reorderForPostVertexCache(
instance.westHemisphereGeometry
);
GeometryPipeline_default.reorderForPreVertexCache(
instance.westHemisphereGeometry
);
GeometryPipeline_default.reorderForPostVertexCache(
instance.eastHemisphereGeometry
);
GeometryPipeline_default.reorderForPreVertexCache(
instance.eastHemisphereGeometry
);
}
}
}
let geometries = GeometryPipeline_default.combineInstances(instances);
length2 = geometries.length;
for (i = 0; i < length2; ++i) {
geometry = geometries[i];
const attributes = geometry.attributes;
if (!scene3DOnly) {
for (const name in attributes) {
if (attributes.hasOwnProperty(name) && attributes[name].componentDatatype === ComponentDatatype_default.DOUBLE) {
const name3D = `${name}3D`;
const name2D = `${name}2D`;
GeometryPipeline_default.projectTo2D(
geometry,
name,
name3D,
name2D,
projection
);
if (defined_default(geometry.boundingSphere) && name === "position") {
geometry.boundingSphereCV = BoundingSphere_default.fromVertices(
geometry.attributes.position2D.values
);
}
GeometryPipeline_default.encodeAttribute(
geometry,
name3D,
`${name3D}High`,
`${name3D}Low`
);
GeometryPipeline_default.encodeAttribute(
geometry,
name2D,
`${name2D}High`,
`${name2D}Low`
);
}
}
} else {
for (const name in attributes) {
if (attributes.hasOwnProperty(name) && attributes[name].componentDatatype === ComponentDatatype_default.DOUBLE) {
GeometryPipeline_default.encodeAttribute(
geometry,
name,
`${name}3DHigh`,
`${name}3DLow`
);
}
}
}
if (compressVertices) {
GeometryPipeline_default.compressVertices(geometry);
}
}
if (!uintIndexSupport) {
let splitGeometries = [];
length2 = geometries.length;
for (i = 0; i < length2; ++i) {
geometry = geometries[i];
splitGeometries = splitGeometries.concat(
GeometryPipeline_default.fitToUnsignedShortIndices(geometry)
);
}
geometries = splitGeometries;
}
return geometries;
}
function createPickOffsets(instances, geometryName, geometries, pickOffsets) {
let offset;
let indexCount;
let geometryIndex;
const offsetIndex = pickOffsets.length - 1;
if (offsetIndex >= 0) {
const pickOffset = pickOffsets[offsetIndex];
offset = pickOffset.offset + pickOffset.count;
geometryIndex = pickOffset.index;
indexCount = geometries[geometryIndex].indices.length;
} else {
offset = 0;
geometryIndex = 0;
indexCount = geometries[geometryIndex].indices.length;
}
const length2 = instances.length;
for (let i = 0; i < length2; ++i) {
const instance = instances[i];
const geometry = instance[geometryName];
if (!defined_default(geometry)) {
continue;
}
const count = geometry.indices.length;
if (offset + count > indexCount) {
offset = 0;
indexCount = geometries[++geometryIndex].indices.length;
}
pickOffsets.push({
index: geometryIndex,
offset,
count
});
offset += count;
}
}
function createInstancePickOffsets(instances, geometries) {
const pickOffsets = [];
createPickOffsets(instances, "geometry", geometries, pickOffsets);
createPickOffsets(
instances,
"westHemisphereGeometry",
geometries,
pickOffsets
);
createPickOffsets(
instances,
"eastHemisphereGeometry",
geometries,
pickOffsets
);
return pickOffsets;
}
var PrimitivePipeline = {};
PrimitivePipeline.combineGeometry = function(parameters) {
let geometries;
let attributeLocations8;
const instances = parameters.instances;
const length2 = instances.length;
let pickOffsets;
let offsetInstanceExtend;
let hasOffset = false;
if (length2 > 0) {
geometries = geometryPipeline(parameters);
if (geometries.length > 0) {
attributeLocations8 = GeometryPipeline_default.createAttributeLocations(
geometries[0]
);
if (parameters.createPickOffsets) {
pickOffsets = createInstancePickOffsets(instances, geometries);
}
}
if (defined_default(instances[0].attributes) && defined_default(instances[0].attributes.offset)) {
offsetInstanceExtend = new Array(length2);
hasOffset = true;
}
}
const boundingSpheres = new Array(length2);
const boundingSpheresCV = new Array(length2);
for (let i = 0; i < length2; ++i) {
const instance = instances[i];
const geometry = instance.geometry;
if (defined_default(geometry)) {
boundingSpheres[i] = geometry.boundingSphere;
boundingSpheresCV[i] = geometry.boundingSphereCV;
if (hasOffset) {
offsetInstanceExtend[i] = instance.geometry.offsetAttribute;
}
}
const eastHemisphereGeometry = instance.eastHemisphereGeometry;
const westHemisphereGeometry = instance.westHemisphereGeometry;
if (defined_default(eastHemisphereGeometry) && defined_default(westHemisphereGeometry)) {
if (defined_default(eastHemisphereGeometry.boundingSphere) && defined_default(westHemisphereGeometry.boundingSphere)) {
boundingSpheres[i] = BoundingSphere_default.union(
eastHemisphereGeometry.boundingSphere,
westHemisphereGeometry.boundingSphere
);
}
if (defined_default(eastHemisphereGeometry.boundingSphereCV) && defined_default(westHemisphereGeometry.boundingSphereCV)) {
boundingSpheresCV[i] = BoundingSphere_default.union(
eastHemisphereGeometry.boundingSphereCV,
westHemisphereGeometry.boundingSphereCV
);
}
}
}
return {
geometries,
modelMatrix: parameters.modelMatrix,
attributeLocations: attributeLocations8,
pickOffsets,
offsetInstanceExtend,
boundingSpheres,
boundingSpheresCV
};
};
function transferGeometry(geometry, transferableObjects) {
const attributes = geometry.attributes;
for (const name in attributes) {
if (attributes.hasOwnProperty(name)) {
const attribute = attributes[name];
if (defined_default(attribute) && defined_default(attribute.values)) {
transferableObjects.push(attribute.values.buffer);
}
}
}
if (defined_default(geometry.indices)) {
transferableObjects.push(geometry.indices.buffer);
}
}
function transferGeometries(geometries, transferableObjects) {
const length2 = geometries.length;
for (let i = 0; i < length2; ++i) {
transferGeometry(geometries[i], transferableObjects);
}
}
function countCreateGeometryResults(items) {
let count = 1;
const length2 = items.length;
for (let i = 0; i < length2; i++) {
const geometry = items[i];
++count;
if (!defined_default(geometry)) {
continue;
}
const attributes = geometry.attributes;
count += 7 + 2 * BoundingSphere_default.packedLength + (defined_default(geometry.indices) ? geometry.indices.length : 0);
for (const property in attributes) {
if (attributes.hasOwnProperty(property) && defined_default(attributes[property])) {
const attribute = attributes[property];
count += 5 + attribute.values.length;
}
}
}
return count;
}
PrimitivePipeline.packCreateGeometryResults = function(items, transferableObjects) {
const packedData = new Float64Array(countCreateGeometryResults(items));
const stringTable = [];
const stringHash = {};
const length2 = items.length;
let count = 0;
packedData[count++] = length2;
for (let i = 0; i < length2; i++) {
const geometry = items[i];
const validGeometry = defined_default(geometry);
packedData[count++] = validGeometry ? 1 : 0;
if (!validGeometry) {
continue;
}
packedData[count++] = geometry.primitiveType;
packedData[count++] = geometry.geometryType;
packedData[count++] = geometry.offsetAttribute ?? -1;
const validBoundingSphere = defined_default(geometry.boundingSphere) ? 1 : 0;
packedData[count++] = validBoundingSphere;
if (validBoundingSphere) {
BoundingSphere_default.pack(geometry.boundingSphere, packedData, count);
}
count += BoundingSphere_default.packedLength;
const validBoundingSphereCV = defined_default(geometry.boundingSphereCV) ? 1 : 0;
packedData[count++] = validBoundingSphereCV;
if (validBoundingSphereCV) {
BoundingSphere_default.pack(geometry.boundingSphereCV, packedData, count);
}
count += BoundingSphere_default.packedLength;
const attributes = geometry.attributes;
const attributesToWrite = [];
for (const property in attributes) {
if (attributes.hasOwnProperty(property) && defined_default(attributes[property])) {
attributesToWrite.push(property);
if (!defined_default(stringHash[property])) {
stringHash[property] = stringTable.length;
stringTable.push(property);
}
}
}
packedData[count++] = attributesToWrite.length;
for (let q = 0; q < attributesToWrite.length; q++) {
const name = attributesToWrite[q];
const attribute = attributes[name];
packedData[count++] = stringHash[name];
packedData[count++] = attribute.componentDatatype;
packedData[count++] = attribute.componentsPerAttribute;
packedData[count++] = attribute.normalize ? 1 : 0;
packedData[count++] = attribute.values.length;
packedData.set(attribute.values, count);
count += attribute.values.length;
}
const indicesLength = defined_default(geometry.indices) ? geometry.indices.length : 0;
packedData[count++] = indicesLength;
if (indicesLength > 0) {
packedData.set(geometry.indices, count);
count += indicesLength;
}
}
transferableObjects.push(packedData.buffer);
return {
stringTable,
packedData
};
};
PrimitivePipeline.unpackCreateGeometryResults = function(createGeometryResult) {
const stringTable = createGeometryResult.stringTable;
const packedGeometry = createGeometryResult.packedData;
let i;
const result = new Array(packedGeometry[0]);
let resultIndex = 0;
let packedGeometryIndex = 1;
while (packedGeometryIndex < packedGeometry.length) {
const valid = packedGeometry[packedGeometryIndex++] === 1;
if (!valid) {
result[resultIndex++] = void 0;
continue;
}
const primitiveType = packedGeometry[packedGeometryIndex++];
const geometryType = packedGeometry[packedGeometryIndex++];
let offsetAttribute = packedGeometry[packedGeometryIndex++];
if (offsetAttribute === -1) {
offsetAttribute = void 0;
}
let boundingSphere;
let boundingSphereCV;
const validBoundingSphere = packedGeometry[packedGeometryIndex++] === 1;
if (validBoundingSphere) {
boundingSphere = BoundingSphere_default.unpack(
packedGeometry,
packedGeometryIndex
);
}
packedGeometryIndex += BoundingSphere_default.packedLength;
const validBoundingSphereCV = packedGeometry[packedGeometryIndex++] === 1;
if (validBoundingSphereCV) {
boundingSphereCV = BoundingSphere_default.unpack(
packedGeometry,
packedGeometryIndex
);
}
packedGeometryIndex += BoundingSphere_default.packedLength;
let length2;
let values;
let componentsPerAttribute;
const attributes = new GeometryAttributes_default();
const numAttributes = packedGeometry[packedGeometryIndex++];
for (i = 0; i < numAttributes; i++) {
const name = stringTable[packedGeometry[packedGeometryIndex++]];
const componentDatatype = packedGeometry[packedGeometryIndex++];
componentsPerAttribute = packedGeometry[packedGeometryIndex++];
const normalize2 = packedGeometry[packedGeometryIndex++] !== 0;
length2 = packedGeometry[packedGeometryIndex++];
values = ComponentDatatype_default.createTypedArray(componentDatatype, length2);
for (let valuesIndex = 0; valuesIndex < length2; valuesIndex++) {
values[valuesIndex] = packedGeometry[packedGeometryIndex++];
}
attributes[name] = new GeometryAttribute_default({
componentDatatype,
componentsPerAttribute,
normalize: normalize2,
values
});
}
let indices;
length2 = packedGeometry[packedGeometryIndex++];
if (length2 > 0) {
const numberOfVertices = values.length / componentsPerAttribute;
indices = IndexDatatype_default.createTypedArray(numberOfVertices, length2);
for (i = 0; i < length2; i++) {
indices[i] = packedGeometry[packedGeometryIndex++];
}
}
result[resultIndex++] = new Geometry_default({
primitiveType,
geometryType,
boundingSphere,
boundingSphereCV,
indices,
attributes,
offsetAttribute
});
}
return result;
};
function packInstancesForCombine(instances, transferableObjects) {
const length2 = instances.length;
const packedData = new Float64Array(1 + length2 * 19);
let count = 0;
packedData[count++] = length2;
for (let i = 0; i < length2; i++) {
const instance = instances[i];
Matrix4_default.pack(instance.modelMatrix, packedData, count);
count += Matrix4_default.packedLength;
if (defined_default(instance.attributes) && defined_default(instance.attributes.offset)) {
const values = instance.attributes.offset.value;
packedData[count] = values[0];
packedData[count + 1] = values[1];
packedData[count + 2] = values[2];
}
count += 3;
}
transferableObjects.push(packedData.buffer);
return packedData;
}
function unpackInstancesForCombine(data) {
const packedInstances = data;
const result = new Array(packedInstances[0]);
let count = 0;
let i = 1;
while (i < packedInstances.length) {
const modelMatrix = Matrix4_default.unpack(packedInstances, i);
let attributes;
i += Matrix4_default.packedLength;
if (defined_default(packedInstances[i])) {
attributes = {
offset: new OffsetGeometryInstanceAttribute_default(
packedInstances[i],
packedInstances[i + 1],
packedInstances[i + 2]
)
};
}
i += 3;
result[count++] = {
modelMatrix,
attributes
};
}
return result;
}
PrimitivePipeline.packCombineGeometryParameters = function(parameters, transferableObjects) {
const createGeometryResults = parameters.createGeometryResults;
const length2 = createGeometryResults.length;
for (let i = 0; i < length2; i++) {
transferableObjects.push(createGeometryResults[i].packedData.buffer);
}
return {
createGeometryResults: parameters.createGeometryResults,
packedInstances: packInstancesForCombine(
parameters.instances,
transferableObjects
),
ellipsoid: parameters.ellipsoid,
isGeographic: parameters.projection instanceof GeographicProjection_default,
elementIndexUintSupported: parameters.elementIndexUintSupported,
scene3DOnly: parameters.scene3DOnly,
vertexCacheOptimize: parameters.vertexCacheOptimize,
compressVertices: parameters.compressVertices,
modelMatrix: parameters.modelMatrix,
createPickOffsets: parameters.createPickOffsets
};
};
PrimitivePipeline.unpackCombineGeometryParameters = function(packedParameters) {
const instances = unpackInstancesForCombine(packedParameters.packedInstances);
const createGeometryResults = packedParameters.createGeometryResults;
const length2 = createGeometryResults.length;
let instanceIndex = 0;
for (let resultIndex = 0; resultIndex < length2; resultIndex++) {
const geometries = PrimitivePipeline.unpackCreateGeometryResults(
createGeometryResults[resultIndex]
);
const geometriesLength = geometries.length;
for (let geometryIndex = 0; geometryIndex < geometriesLength; geometryIndex++) {
const geometry = geometries[geometryIndex];
const instance = instances[instanceIndex];
instance.geometry = geometry;
++instanceIndex;
}
}
const ellipsoid = Ellipsoid_default.clone(packedParameters.ellipsoid);
const projection = packedParameters.isGeographic ? new GeographicProjection_default(ellipsoid) : new WebMercatorProjection_default(ellipsoid);
return {
instances,
ellipsoid,
projection,
elementIndexUintSupported: packedParameters.elementIndexUintSupported,
scene3DOnly: packedParameters.scene3DOnly,
vertexCacheOptimize: packedParameters.vertexCacheOptimize,
compressVertices: packedParameters.compressVertices,
modelMatrix: Matrix4_default.clone(packedParameters.modelMatrix),
createPickOffsets: packedParameters.createPickOffsets
};
};
function packBoundingSpheres(boundingSpheres) {
const length2 = boundingSpheres.length;
const bufferLength = 1 + (BoundingSphere_default.packedLength + 1) * length2;
const buffer2 = new Float32Array(bufferLength);
let bufferIndex = 0;
buffer2[bufferIndex++] = length2;
for (let i = 0; i < length2; ++i) {
const bs = boundingSpheres[i];
if (!defined_default(bs)) {
buffer2[bufferIndex++] = 0;
} else {
buffer2[bufferIndex++] = 1;
BoundingSphere_default.pack(boundingSpheres[i], buffer2, bufferIndex);
}
bufferIndex += BoundingSphere_default.packedLength;
}
return buffer2;
}
function unpackBoundingSpheres(buffer2) {
const result = new Array(buffer2[0]);
let count = 0;
let i = 1;
while (i < buffer2.length) {
if (buffer2[i++] === 1) {
result[count] = BoundingSphere_default.unpack(buffer2, i);
}
++count;
i += BoundingSphere_default.packedLength;
}
return result;
}
PrimitivePipeline.packCombineGeometryResults = function(results, transferableObjects) {
if (defined_default(results.geometries)) {
transferGeometries(results.geometries, transferableObjects);
}
const packedBoundingSpheres = packBoundingSpheres(results.boundingSpheres);
const packedBoundingSpheresCV = packBoundingSpheres(
results.boundingSpheresCV
);
transferableObjects.push(
packedBoundingSpheres.buffer,
packedBoundingSpheresCV.buffer
);
return {
geometries: results.geometries,
attributeLocations: results.attributeLocations,
modelMatrix: results.modelMatrix,
pickOffsets: results.pickOffsets,
offsetInstanceExtend: results.offsetInstanceExtend,
boundingSpheres: packedBoundingSpheres,
boundingSpheresCV: packedBoundingSpheresCV
};
};
PrimitivePipeline.unpackCombineGeometryResults = function(packedResult) {
return {
geometries: packedResult.geometries,
attributeLocations: packedResult.attributeLocations,
modelMatrix: packedResult.modelMatrix,
pickOffsets: packedResult.pickOffsets,
offsetInstanceExtend: packedResult.offsetInstanceExtend,
boundingSpheres: unpackBoundingSpheres(packedResult.boundingSpheres),
boundingSpheresCV: unpackBoundingSpheres(packedResult.boundingSpheresCV)
};
};
var PrimitivePipeline_default = PrimitivePipeline;
// packages/engine/Source/Scene/PrimitiveState.js
var import_InlineWorkers360 = __toESM(require_InlineWorkers(), 1);
var PrimitiveState = {
READY: 0,
CREATING: 1,
CREATED: 2,
COMBINING: 3,
COMBINED: 4,
COMPLETE: 5,
FAILED: 6
};
var PrimitiveState_default = Object.freeze(PrimitiveState);
// packages/engine/Source/Scene/ShadowMode.js
var import_InlineWorkers361 = __toESM(require_InlineWorkers(), 1);
var ShadowMode = {
/**
* The object does not cast or receive shadows.
*
* @type {number}
* @constant
*/
DISABLED: 0,
/**
* The object casts and receives shadows.
*
* @type {number}
* @constant
*/
ENABLED: 1,
/**
* The object casts shadows only.
*
* @type {number}
* @constant
*/
CAST_ONLY: 2,
/**
* The object receives shadows only.
*
* @type {number}
* @constant
*/
RECEIVE_ONLY: 3
};
ShadowMode.NUMBER_OF_SHADOW_MODES = 4;
ShadowMode.castShadows = function(shadowMode) {
return shadowMode === ShadowMode.ENABLED || shadowMode === ShadowMode.CAST_ONLY;
};
ShadowMode.receiveShadows = function(shadowMode) {
return shadowMode === ShadowMode.ENABLED || shadowMode === ShadowMode.RECEIVE_ONLY;
};
ShadowMode.fromCastReceive = function(castShadows, receiveShadows) {
if (castShadows && receiveShadows) {
return ShadowMode.ENABLED;
} else if (castShadows) {
return ShadowMode.CAST_ONLY;
} else if (receiveShadows) {
return ShadowMode.RECEIVE_ONLY;
}
return ShadowMode.DISABLED;
};
var ShadowMode_default = Object.freeze(ShadowMode);
// packages/engine/Source/Scene/Primitive.js
function Primitive(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.geometryInstances = options.geometryInstances;
this.appearance = options.appearance;
this._appearance = void 0;
this._material = void 0;
this.depthFailAppearance = options.depthFailAppearance;
this._depthFailAppearance = void 0;
this._depthFailMaterial = void 0;
this.modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this._modelMatrix = new Matrix4_default();
this.show = options.show ?? true;
this._vertexCacheOptimize = options.vertexCacheOptimize ?? false;
this._interleave = options.interleave ?? false;
this._releaseGeometryInstances = options.releaseGeometryInstances ?? true;
this._allowPicking = options.allowPicking ?? true;
this._asynchronous = options.asynchronous ?? true;
this._compressVertices = options.compressVertices ?? true;
this.cull = options.cull ?? true;
this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this.rtcCenter = options.rtcCenter;
if (defined_default(this.rtcCenter) && (!defined_default(this.geometryInstances) || Array.isArray(this.geometryInstances) && this.geometryInstances.length !== 1)) {
throw new DeveloperError_default(
"Relative-to-center rendering only supports one geometry instance."
);
}
this.shadows = options.shadows ?? ShadowMode_default.DISABLED;
this._translucent = void 0;
this._state = PrimitiveState_default.READY;
this._geometries = [];
this._error = void 0;
this._numberOfInstances = 0;
this._boundingSpheres = [];
this._boundingSphereWC = [];
this._boundingSphereCV = [];
this._boundingSphere2D = [];
this._boundingSphereMorph = [];
this._perInstanceAttributeCache = /* @__PURE__ */ new Map();
this._instanceIds = [];
this._lastPerInstanceAttributeIndex = 0;
this._va = [];
this._attributeLocations = void 0;
this._primitiveType = void 0;
this._frontFaceRS = void 0;
this._backFaceRS = void 0;
this._sp = void 0;
this._depthFailAppearance = void 0;
this._spDepthFail = void 0;
this._frontFaceDepthFailRS = void 0;
this._backFaceDepthFailRS = void 0;
this._pickIds = [];
this._colorCommands = [];
this._pickCommands = [];
this._createBoundingVolumeFunction = options._createBoundingVolumeFunction;
this._createRenderStatesFunction = options._createRenderStatesFunction;
this._createShaderProgramFunction = options._createShaderProgramFunction;
this._createCommandsFunction = options._createCommandsFunction;
this._updateAndQueueCommandsFunction = options._updateAndQueueCommandsFunction;
this._createPickOffsets = options._createPickOffsets;
this._pickOffsets = void 0;
this._createGeometryResults = void 0;
this._ready = false;
this._batchTable = void 0;
this._batchTableAttributeIndices = void 0;
this._offsetInstanceExtend = void 0;
this._batchTableOffsetAttribute2DIndex = void 0;
this._batchTableOffsetsUpdated = false;
this._instanceBoundingSpheres = void 0;
this._instanceBoundingSpheresCV = void 0;
this._tempBoundingSpheres = void 0;
this._recomputeBoundingSpheres = false;
this._batchTableBoundingSpheresUpdated = false;
this._batchTableBoundingSphereAttributeIndices = void 0;
}
Object.defineProperties(Primitive.prototype, {
/**
* When true, geometry vertices are optimized for the pre and post-vertex-shader caches.
*
* @memberof Primitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
vertexCacheOptimize: {
get: function() {
return this._vertexCacheOptimize;
}
},
/**
* Determines if geometry vertex attributes are interleaved, which can slightly improve rendering performance.
*
* @memberof Primitive.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
interleave: {
get: function() {
return this._interleave;
}
},
/**
* When true, the primitive does not keep a reference to the input geometryInstances to save memory.
*
* @memberof Primitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
releaseGeometryInstances: {
get: function() {
return this._releaseGeometryInstances;
}
},
/**
* When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved. *
*
* @memberof Primitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
allowPicking: {
get: function() {
return this._allowPicking;
}
},
/**
* Determines if the geometry instances will be created and batched on a web worker.
*
* @memberof Primitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
asynchronous: {
get: function() {
return this._asynchronous;
}
},
/**
* When true, geometry vertices are compressed, which will save memory.
*
* @memberof Primitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
compressVertices: {
get: function() {
return this._compressVertices;
}
},
/**
* Determines if the primitive is complete and ready to render. If this property is
* true, the primitive will be rendered the next time that {@link Primitive#update}
* is called.
*
* @memberof Primitive.prototype
*
* @type {boolean}
* @readonly
*
* @example
* // Wait for a primitive to become ready before accessing attributes
* const removeListener = scene.postRender.addEventListener(() => {
* if (!frustumPrimitive.ready) {
* return;
* }
*
* const attributes = primitive.getGeometryInstanceAttributes('an id');
* attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.AQUA);
*
* removeListener();
* });
*/
ready: {
get: function() {
return this._ready;
}
}
});
function getCommonPerInstanceAttributeNames(instances) {
const length2 = instances.length;
const attributesInAllInstances = [];
const attributes0 = instances[0].attributes;
let name;
for (name in attributes0) {
if (attributes0.hasOwnProperty(name) && defined_default(attributes0[name])) {
const attribute = attributes0[name];
let inAllInstances = true;
for (let i = 1; i < length2; ++i) {
const otherAttribute = instances[i].attributes[name];
if (!defined_default(otherAttribute) || attribute.componentDatatype !== otherAttribute.componentDatatype || attribute.componentsPerAttribute !== otherAttribute.componentsPerAttribute || attribute.normalize !== otherAttribute.normalize) {
inAllInstances = false;
break;
}
}
if (inAllInstances) {
attributesInAllInstances.push(name);
}
}
}
return attributesInAllInstances;
}
var scratchGetAttributeCartesian2 = new Cartesian2_default();
var scratchGetAttributeCartesian3 = new Cartesian3_default();
var scratchGetAttributeCartesian42 = new Cartesian4_default();
function getAttributeValue(value) {
const componentsPerAttribute = value.length;
if (componentsPerAttribute === 1) {
return value[0];
} else if (componentsPerAttribute === 2) {
return Cartesian2_default.unpack(value, 0, scratchGetAttributeCartesian2);
} else if (componentsPerAttribute === 3) {
return Cartesian3_default.unpack(value, 0, scratchGetAttributeCartesian3);
} else if (componentsPerAttribute === 4) {
return Cartesian4_default.unpack(value, 0, scratchGetAttributeCartesian42);
}
}
function createBatchTable(primitive, context) {
const geometryInstances = primitive.geometryInstances;
const instances = Array.isArray(geometryInstances) ? geometryInstances : [geometryInstances];
const numberOfInstances = instances.length;
if (numberOfInstances === 0) {
return;
}
const names = getCommonPerInstanceAttributeNames(instances);
const length2 = names.length;
const attributes = [];
const attributeIndices = {};
const boundingSphereAttributeIndices = {};
let offset2DIndex;
const firstInstance = instances[0];
let instanceAttributes = firstInstance.attributes;
let i;
let name;
let attribute;
for (i = 0; i < length2; ++i) {
name = names[i];
attribute = instanceAttributes[name];
attributeIndices[name] = i;
attributes.push({
functionName: `czm_batchTable_${name}`,
componentDatatype: attribute.componentDatatype,
componentsPerAttribute: attribute.componentsPerAttribute,
normalize: attribute.normalize
});
}
if (names.indexOf("distanceDisplayCondition") !== -1) {
attributes.push(
{
functionName: "czm_batchTable_boundingSphereCenter3DHigh",
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3
},
{
functionName: "czm_batchTable_boundingSphereCenter3DLow",
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3
},
{
functionName: "czm_batchTable_boundingSphereCenter2DHigh",
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3
},
{
functionName: "czm_batchTable_boundingSphereCenter2DLow",
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3
},
{
functionName: "czm_batchTable_boundingSphereRadius",
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 1
}
);
boundingSphereAttributeIndices.center3DHigh = attributes.length - 5;
boundingSphereAttributeIndices.center3DLow = attributes.length - 4;
boundingSphereAttributeIndices.center2DHigh = attributes.length - 3;
boundingSphereAttributeIndices.center2DLow = attributes.length - 2;
boundingSphereAttributeIndices.radius = attributes.length - 1;
}
if (names.indexOf("offset") !== -1) {
attributes.push({
functionName: "czm_batchTable_offset2D",
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3
});
offset2DIndex = attributes.length - 1;
}
attributes.push({
functionName: "czm_batchTable_pickColor",
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 4,
normalize: true
});
const attributesLength = attributes.length;
const batchTable = new BatchTable_default(context, attributes, numberOfInstances);
for (i = 0; i < numberOfInstances; ++i) {
const instance = instances[i];
instanceAttributes = instance.attributes;
for (let j = 0; j < length2; ++j) {
name = names[j];
attribute = instanceAttributes[name];
const value = getAttributeValue(attribute.value);
const attributeIndex = attributeIndices[name];
batchTable.setBatchedAttribute(i, attributeIndex, value);
}
const pickObject = {
primitive: instance.pickPrimitive ?? primitive
};
if (defined_default(instance.id)) {
pickObject.id = instance.id;
}
const pickId = context.createPickId(pickObject);
primitive._pickIds.push(pickId);
const pickColor = pickId.color;
const color = scratchGetAttributeCartesian42;
color.x = Color_default.floatToByte(pickColor.red);
color.y = Color_default.floatToByte(pickColor.green);
color.z = Color_default.floatToByte(pickColor.blue);
color.w = Color_default.floatToByte(pickColor.alpha);
batchTable.setBatchedAttribute(i, attributesLength - 1, color);
}
primitive._batchTable = batchTable;
primitive._batchTableAttributeIndices = attributeIndices;
primitive._batchTableBoundingSphereAttributeIndices = boundingSphereAttributeIndices;
primitive._batchTableOffsetAttribute2DIndex = offset2DIndex;
}
function cloneAttribute(attribute) {
let clonedValues;
if (Array.isArray(attribute.values)) {
clonedValues = attribute.values.slice(0);
} else {
clonedValues = new attribute.values.constructor(attribute.values);
}
return new GeometryAttribute_default({
componentDatatype: attribute.componentDatatype,
componentsPerAttribute: attribute.componentsPerAttribute,
normalize: attribute.normalize,
values: clonedValues
});
}
function cloneGeometry(geometry) {
const attributes = geometry.attributes;
const newAttributes = new GeometryAttributes_default();
for (const property in attributes) {
if (attributes.hasOwnProperty(property) && defined_default(attributes[property])) {
newAttributes[property] = cloneAttribute(attributes[property]);
}
}
let indices;
if (defined_default(geometry.indices)) {
const sourceValues = geometry.indices;
if (Array.isArray(sourceValues)) {
indices = sourceValues.slice(0);
} else {
indices = new sourceValues.constructor(sourceValues);
}
}
return new Geometry_default({
attributes: newAttributes,
indices,
primitiveType: geometry.primitiveType,
boundingSphere: BoundingSphere_default.clone(geometry.boundingSphere)
});
}
function cloneInstance(instance, geometry) {
return {
geometry,
attributes: instance.attributes,
modelMatrix: Matrix4_default.clone(instance.modelMatrix),
pickPrimitive: instance.pickPrimitive,
id: instance.id
};
}
var positionRegex = /in\s+vec(?:3|4)\s+(.*)3DHigh;/g;
Primitive._modifyShaderPosition = function(primitive, vertexShaderSource, scene3DOnly) {
let match;
let forwardDecl = "";
let attributes = "";
let computeFunctions = "";
while ((match = positionRegex.exec(vertexShaderSource)) !== null) {
const name = match[1];
const functionName = `vec4 czm_compute${name[0].toUpperCase()}${name.substr(
1
)}()`;
if (functionName !== "vec4 czm_computePosition()") {
forwardDecl += `${functionName};
`;
}
if (!defined_default(primitive.rtcCenter)) {
if (!scene3DOnly) {
attributes += `in vec3 ${name}2DHigh;
in vec3 ${name}2DLow;
`;
computeFunctions += `${functionName}
{
vec4 p;
if (czm_morphTime == 1.0)
{
p = czm_translateRelativeToEye(${name}3DHigh, ${name}3DLow);
}
else if (czm_morphTime == 0.0)
{
p = czm_translateRelativeToEye(${name}2DHigh.zxy, ${name}2DLow.zxy);
}
else
{
p = czm_columbusViewMorph(
czm_translateRelativeToEye(${name}2DHigh.zxy, ${name}2DLow.zxy),
czm_translateRelativeToEye(${name}3DHigh, ${name}3DLow),
czm_morphTime);
}
return p;
}
`;
} else {
computeFunctions += `${functionName}
{
return czm_translateRelativeToEye(${name}3DHigh, ${name}3DLow);
}
`;
}
} else {
vertexShaderSource = vertexShaderSource.replace(
/in\s+vec(?:3|4)\s+position3DHigh;/g,
""
);
vertexShaderSource = vertexShaderSource.replace(
/in\s+vec(?:3|4)\s+position3DLow;/g,
""
);
forwardDecl += "uniform mat4 u_modifiedModelView;\n";
attributes += "in vec4 position;\n";
computeFunctions += `${functionName}
{
return u_modifiedModelView * position;
}
`;
vertexShaderSource = vertexShaderSource.replace(
/czm_modelViewRelativeToEye\s+\*\s+/g,
""
);
vertexShaderSource = vertexShaderSource.replace(
/czm_modelViewProjectionRelativeToEye/g,
"czm_projection"
);
}
}
return [forwardDecl, attributes, vertexShaderSource, computeFunctions].join(
"\n"
);
};
Primitive._appendShowToShader = function(primitive, vertexShaderSource) {
if (!defined_default(primitive._batchTableAttributeIndices.show)) {
return vertexShaderSource;
}
const renamedVS = ShaderSource_default.replaceMain(
vertexShaderSource,
"czm_non_show_main"
);
const showMain = "void main() \n{ \n czm_non_show_main(); \n gl_Position *= czm_batchTable_show(batchId); \n}";
return `${renamedVS}
${showMain}`;
};
Primitive._updateColorAttribute = function(primitive, vertexShaderSource, isDepthFail) {
if (!defined_default(primitive._batchTableAttributeIndices.color) && !defined_default(primitive._batchTableAttributeIndices.depthFailColor)) {
return vertexShaderSource;
}
if (vertexShaderSource.search(/in\s+vec4\s+color;/g) === -1) {
return vertexShaderSource;
}
if (isDepthFail && !defined_default(primitive._batchTableAttributeIndices.depthFailColor)) {
throw new DeveloperError_default(
"A depthFailColor per-instance attribute is required when using a depth fail appearance that uses a color attribute."
);
}
let modifiedVS = vertexShaderSource;
modifiedVS = modifiedVS.replace(/in\s+vec4\s+color;/g, "");
if (!isDepthFail) {
modifiedVS = modifiedVS.replace(
/(\b)color(\b)/g,
"$1czm_batchTable_color(batchId)$2"
);
} else {
modifiedVS = modifiedVS.replace(
/(\b)color(\b)/g,
"$1czm_batchTable_depthFailColor(batchId)$2"
);
}
return modifiedVS;
};
function appendPickToVertexShader(source) {
const renamedVS = ShaderSource_default.replaceMain(source, "czm_non_pick_main");
const pickMain = "out vec4 v_pickColor; \nvoid main() \n{ \n czm_non_pick_main(); \n v_pickColor = czm_batchTable_pickColor(batchId); \n}";
return `${renamedVS}
${pickMain}`;
}
function appendPickToFragmentShader(source) {
return `in vec4 v_pickColor;
${source}`;
}
Primitive._updatePickColorAttribute = function(source) {
let vsPick = source.replace(/in\s+vec4\s+pickColor;/g, "");
vsPick = vsPick.replace(
/(\b)pickColor(\b)/g,
"$1czm_batchTable_pickColor(batchId)$2"
);
return vsPick;
};
Primitive._appendOffsetToShader = function(primitive, vertexShaderSource) {
if (!defined_default(primitive._batchTableAttributeIndices.offset)) {
return vertexShaderSource;
}
let attr = "in float batchId;\n";
attr += "in float applyOffset;";
let modifiedShader = vertexShaderSource.replace(
/in\s+float\s+batchId;/g,
attr
);
let str = "vec4 $1 = czm_computePosition();\n";
str += " if (czm_sceneMode == czm_sceneMode3D)\n";
str += " {\n";
str += " $1 = $1 + vec4(czm_batchTable_offset(batchId) * applyOffset, 0.0);";
str += " }\n";
str += " else\n";
str += " {\n";
str += " $1 = $1 + vec4(czm_batchTable_offset2D(batchId) * applyOffset, 0.0);";
str += " }\n";
modifiedShader = modifiedShader.replace(
/vec4\s+([A-Za-z0-9_]+)\s+=\s+czm_computePosition\(\);/g,
str
);
return modifiedShader;
};
Primitive._appendDistanceDisplayConditionToShader = function(primitive, vertexShaderSource, scene3DOnly) {
if (!defined_default(primitive._batchTableAttributeIndices.distanceDisplayCondition)) {
return vertexShaderSource;
}
const renamedVS = ShaderSource_default.replaceMain(
vertexShaderSource,
"czm_non_distanceDisplayCondition_main"
);
let distanceDisplayConditionMain = "void main() \n{ \n czm_non_distanceDisplayCondition_main(); \n vec2 distanceDisplayCondition = czm_batchTable_distanceDisplayCondition(batchId);\n vec3 boundingSphereCenter3DHigh = czm_batchTable_boundingSphereCenter3DHigh(batchId);\n vec3 boundingSphereCenter3DLow = czm_batchTable_boundingSphereCenter3DLow(batchId);\n float boundingSphereRadius = czm_batchTable_boundingSphereRadius(batchId);\n";
if (!scene3DOnly) {
distanceDisplayConditionMain += " vec3 boundingSphereCenter2DHigh = czm_batchTable_boundingSphereCenter2DHigh(batchId);\n vec3 boundingSphereCenter2DLow = czm_batchTable_boundingSphereCenter2DLow(batchId);\n vec4 centerRTE;\n if (czm_morphTime == 1.0)\n {\n centerRTE = czm_translateRelativeToEye(boundingSphereCenter3DHigh, boundingSphereCenter3DLow);\n }\n else if (czm_morphTime == 0.0)\n {\n centerRTE = czm_translateRelativeToEye(boundingSphereCenter2DHigh.zxy, boundingSphereCenter2DLow.zxy);\n }\n else\n {\n centerRTE = czm_columbusViewMorph(\n czm_translateRelativeToEye(boundingSphereCenter2DHigh.zxy, boundingSphereCenter2DLow.zxy),\n czm_translateRelativeToEye(boundingSphereCenter3DHigh, boundingSphereCenter3DLow),\n czm_morphTime);\n }\n";
} else {
distanceDisplayConditionMain += " vec4 centerRTE = czm_translateRelativeToEye(boundingSphereCenter3DHigh, boundingSphereCenter3DLow);\n";
}
distanceDisplayConditionMain += " float radiusSq = boundingSphereRadius * boundingSphereRadius; \n float distanceSq; \n if (czm_sceneMode == czm_sceneMode2D) \n { \n distanceSq = czm_eyeHeight2D.y - radiusSq; \n } \n else \n { \n distanceSq = dot(centerRTE.xyz, centerRTE.xyz) - radiusSq; \n } \n distanceSq = max(distanceSq, 0.0); \n float nearSq = distanceDisplayCondition.x * distanceDisplayCondition.x; \n float farSq = distanceDisplayCondition.y * distanceDisplayCondition.y; \n float show = (distanceSq >= nearSq && distanceSq <= farSq) ? 1.0 : 0.0; \n gl_Position *= show; \n}";
return `${renamedVS}
${distanceDisplayConditionMain}`;
};
function modifyForEncodedNormals(primitive, vertexShaderSource) {
if (!primitive.compressVertices) {
return vertexShaderSource;
}
const containsNormal = vertexShaderSource.search(/in\s+vec3\s+normal;/g) !== -1;
const containsSt = vertexShaderSource.search(/in\s+vec2\s+st;/g) !== -1;
if (!containsNormal && !containsSt) {
return vertexShaderSource;
}
const containsTangent = vertexShaderSource.search(/in\s+vec3\s+tangent;/g) !== -1;
const containsBitangent = vertexShaderSource.search(/in\s+vec3\s+bitangent;/g) !== -1;
let numComponents = containsSt && containsNormal ? 2 : 1;
numComponents += containsTangent || containsBitangent ? 1 : 0;
const type = numComponents > 1 ? `vec${numComponents}` : "float";
const attributeName = "compressedAttributes";
const attributeDecl = `in ${type} ${attributeName};`;
let globalDecl = "";
let decode = "";
if (containsSt) {
globalDecl += "vec2 st;\n";
const stComponent = numComponents > 1 ? `${attributeName}.x` : attributeName;
decode += ` st = czm_decompressTextureCoordinates(${stComponent});
`;
}
if (containsNormal && containsTangent && containsBitangent) {
globalDecl += "vec3 normal;\nvec3 tangent;\nvec3 bitangent;\n";
decode += ` czm_octDecode(${attributeName}.${containsSt ? "yz" : "xy"}, normal, tangent, bitangent);
`;
} else {
if (containsNormal) {
globalDecl += "vec3 normal;\n";
decode += ` normal = czm_octDecode(${attributeName}${numComponents > 1 ? `.${containsSt ? "y" : "x"}` : ""});
`;
}
if (containsTangent) {
globalDecl += "vec3 tangent;\n";
decode += ` tangent = czm_octDecode(${attributeName}.${containsSt && containsNormal ? "z" : "y"});
`;
}
if (containsBitangent) {
globalDecl += "vec3 bitangent;\n";
decode += ` bitangent = czm_octDecode(${attributeName}.${containsSt && containsNormal ? "z" : "y"});
`;
}
}
let modifiedVS = vertexShaderSource;
modifiedVS = modifiedVS.replace(/in\s+vec3\s+normal;/g, "");
modifiedVS = modifiedVS.replace(/in\s+vec2\s+st;/g, "");
modifiedVS = modifiedVS.replace(/in\s+vec3\s+tangent;/g, "");
modifiedVS = modifiedVS.replace(/in\s+vec3\s+bitangent;/g, "");
modifiedVS = ShaderSource_default.replaceMain(modifiedVS, "czm_non_compressed_main");
const compressedMain = `${"void main() \n{ \n"}${decode} czm_non_compressed_main();
}`;
return [attributeDecl, globalDecl, modifiedVS, compressedMain].join("\n");
}
function depthClampVS(vertexShaderSource) {
let modifiedVS = ShaderSource_default.replaceMain(
vertexShaderSource,
"czm_non_depth_clamp_main"
);
modifiedVS += "void main() {\n czm_non_depth_clamp_main();\n gl_Position = czm_depthClamp(gl_Position);}\n";
return modifiedVS;
}
function depthClampFS(fragmentShaderSource) {
let modifiedFS = ShaderSource_default.replaceMain(
fragmentShaderSource,
"czm_non_depth_clamp_main"
);
modifiedFS += "void main() {\n czm_non_depth_clamp_main();\n #if defined(LOG_DEPTH)\n czm_writeLogDepth();\n #else\n czm_writeDepthClamp();\n #endif\n}\n";
return modifiedFS;
}
function validateShaderMatching(shaderProgram, attributeLocations8) {
const shaderAttributes = shaderProgram.vertexAttributes;
for (const name in shaderAttributes) {
if (shaderAttributes.hasOwnProperty(name)) {
if (!defined_default(attributeLocations8[name])) {
throw new DeveloperError_default(
`Appearance/Geometry mismatch. The appearance requires vertex shader attribute input '${name}', which was not computed as part of the Geometry. Use the appearance's vertexFormat property when constructing the geometry.`
);
}
}
}
}
function getUniformFunction(uniforms, name) {
return function() {
return uniforms[name];
};
}
var numberOfCreationWorkers = Math.max(
FeatureDetection_default.hardwareConcurrency - 1,
1
);
var createGeometryTaskProcessors;
var combineGeometryTaskProcessor = new TaskProcessor_default("combineGeometry");
function loadAsynchronous(primitive, frameState) {
let instances;
let geometry;
let i;
let j;
const instanceIds = primitive._instanceIds;
if (primitive._state === PrimitiveState_default.READY) {
instances = Array.isArray(primitive.geometryInstances) ? primitive.geometryInstances : [primitive.geometryInstances];
const length2 = primitive._numberOfInstances = instances.length;
const promises = [];
let subTasks = [];
for (i = 0; i < length2; ++i) {
geometry = instances[i].geometry;
instanceIds.push(instances[i].id);
if (defined_default(geometry._workerName) && defined_default(geometry._workerPath) || !defined_default(geometry._workerName) && !defined_default(geometry._workerPath)) {
throw new DeveloperError_default(
"Must define either _workerName or _workerPath for asynchronous geometry."
);
}
subTasks.push({
moduleName: geometry._workerName,
modulePath: geometry._workerPath,
geometry
});
}
if (!defined_default(createGeometryTaskProcessors)) {
createGeometryTaskProcessors = new Array(numberOfCreationWorkers);
for (i = 0; i < numberOfCreationWorkers; i++) {
createGeometryTaskProcessors[i] = new TaskProcessor_default("createGeometry");
}
}
let subTask;
subTasks = subdivideArray_default(subTasks, numberOfCreationWorkers);
for (i = 0; i < subTasks.length; i++) {
let packedLength = 0;
const workerSubTasks = subTasks[i];
const workerSubTasksLength = workerSubTasks.length;
for (j = 0; j < workerSubTasksLength; ++j) {
subTask = workerSubTasks[j];
geometry = subTask.geometry;
if (defined_default(geometry.constructor.pack)) {
subTask.offset = packedLength;
packedLength += geometry.constructor.packedLength ?? geometry.packedLength;
}
}
let subTaskTransferableObjects;
if (packedLength > 0) {
const array = new Float64Array(packedLength);
subTaskTransferableObjects = [array.buffer];
for (j = 0; j < workerSubTasksLength; ++j) {
subTask = workerSubTasks[j];
geometry = subTask.geometry;
if (defined_default(geometry.constructor.pack)) {
geometry.constructor.pack(geometry, array, subTask.offset);
subTask.geometry = array;
}
}
}
promises.push(
createGeometryTaskProcessors[i].scheduleTask(
{
subTasks: subTasks[i]
},
subTaskTransferableObjects
)
);
}
primitive._state = PrimitiveState_default.CREATING;
Promise.all(promises).then(function(results) {
primitive._createGeometryResults = results;
primitive._state = PrimitiveState_default.CREATED;
}).catch(function(error) {
setReady(primitive, frameState, PrimitiveState_default.FAILED, error);
});
} else if (primitive._state === PrimitiveState_default.CREATED) {
const transferableObjects = [];
instances = Array.isArray(primitive.geometryInstances) ? primitive.geometryInstances : [primitive.geometryInstances];
const scene3DOnly = frameState.scene3DOnly;
const projection = frameState.mapProjection;
const promise = combineGeometryTaskProcessor.scheduleTask(
PrimitivePipeline_default.packCombineGeometryParameters(
{
createGeometryResults: primitive._createGeometryResults,
instances,
ellipsoid: projection.ellipsoid,
projection,
elementIndexUintSupported: frameState.context.elementIndexUint,
scene3DOnly,
vertexCacheOptimize: primitive.vertexCacheOptimize,
compressVertices: primitive.compressVertices,
modelMatrix: primitive.modelMatrix,
createPickOffsets: primitive._createPickOffsets
},
transferableObjects
),
transferableObjects
);
primitive._createGeometryResults = void 0;
primitive._state = PrimitiveState_default.COMBINING;
Promise.resolve(promise).then(function(packedResult) {
const result = PrimitivePipeline_default.unpackCombineGeometryResults(packedResult);
primitive._geometries = result.geometries;
primitive._attributeLocations = result.attributeLocations;
primitive.modelMatrix = Matrix4_default.clone(
result.modelMatrix,
primitive.modelMatrix
);
primitive._pickOffsets = result.pickOffsets;
primitive._offsetInstanceExtend = result.offsetInstanceExtend;
primitive._instanceBoundingSpheres = result.boundingSpheres;
primitive._instanceBoundingSpheresCV = result.boundingSpheresCV;
if (defined_default(primitive._geometries) && primitive._geometries.length > 0) {
primitive._recomputeBoundingSpheres = true;
primitive._state = PrimitiveState_default.COMBINED;
} else {
setReady(primitive, frameState, PrimitiveState_default.FAILED, void 0);
}
}).catch(function(error) {
setReady(primitive, frameState, PrimitiveState_default.FAILED, error);
});
}
}
function loadSynchronous(primitive, frameState) {
const instances = Array.isArray(primitive.geometryInstances) ? primitive.geometryInstances : [primitive.geometryInstances];
const length2 = primitive._numberOfInstances = instances.length;
const clonedInstances = new Array(length2);
const instanceIds = primitive._instanceIds;
let instance;
let i;
let geometryIndex = 0;
for (i = 0; i < length2; i++) {
instance = instances[i];
const geometry = instance.geometry;
let createdGeometry;
if (defined_default(geometry.attributes) && defined_default(geometry.primitiveType)) {
createdGeometry = cloneGeometry(geometry);
} else {
createdGeometry = geometry.constructor.createGeometry(geometry);
}
clonedInstances[geometryIndex++] = cloneInstance(instance, createdGeometry);
instanceIds.push(instance.id);
}
clonedInstances.length = geometryIndex;
const scene3DOnly = frameState.scene3DOnly;
const projection = frameState.mapProjection;
const result = PrimitivePipeline_default.combineGeometry({
instances: clonedInstances,
ellipsoid: projection.ellipsoid,
projection,
elementIndexUintSupported: frameState.context.elementIndexUint,
scene3DOnly,
vertexCacheOptimize: primitive.vertexCacheOptimize,
compressVertices: primitive.compressVertices,
modelMatrix: primitive.modelMatrix,
createPickOffsets: primitive._createPickOffsets
});
primitive._geometries = result.geometries;
primitive._attributeLocations = result.attributeLocations;
primitive.modelMatrix = Matrix4_default.clone(
result.modelMatrix,
primitive.modelMatrix
);
primitive._pickOffsets = result.pickOffsets;
primitive._offsetInstanceExtend = result.offsetInstanceExtend;
primitive._instanceBoundingSpheres = result.boundingSpheres;
primitive._instanceBoundingSpheresCV = result.boundingSpheresCV;
if (defined_default(primitive._geometries) && primitive._geometries.length > 0) {
primitive._recomputeBoundingSpheres = true;
primitive._state = PrimitiveState_default.COMBINED;
} else {
setReady(primitive, frameState, PrimitiveState_default.FAILED, void 0);
}
}
function recomputeBoundingSpheres(primitive, frameState) {
const offsetIndex = primitive._batchTableAttributeIndices.offset;
if (!primitive._recomputeBoundingSpheres || !defined_default(offsetIndex)) {
primitive._recomputeBoundingSpheres = false;
return;
}
let i;
const offsetInstanceExtend = primitive._offsetInstanceExtend;
const boundingSpheres = primitive._instanceBoundingSpheres;
const length2 = boundingSpheres.length;
let newBoundingSpheres = primitive._tempBoundingSpheres;
if (!defined_default(newBoundingSpheres)) {
newBoundingSpheres = new Array(length2);
for (i = 0; i < length2; i++) {
newBoundingSpheres[i] = new BoundingSphere_default();
}
primitive._tempBoundingSpheres = newBoundingSpheres;
}
for (i = 0; i < length2; ++i) {
let newBS = newBoundingSpheres[i];
const offset = primitive._batchTable.getBatchedAttribute(
i,
offsetIndex,
new Cartesian3_default()
);
newBS = boundingSpheres[i].clone(newBS);
transformBoundingSphere(newBS, offset, offsetInstanceExtend[i]);
}
const combinedBS = [];
const combinedWestBS = [];
const combinedEastBS = [];
for (i = 0; i < length2; ++i) {
const bs = newBoundingSpheres[i];
const minX = bs.center.x - bs.radius;
if (minX > 0 || BoundingSphere_default.intersectPlane(bs, Plane_default.ORIGIN_ZX_PLANE) !== Intersect_default.INTERSECTING) {
combinedBS.push(bs);
} else {
combinedWestBS.push(bs);
combinedEastBS.push(bs);
}
}
let resultBS1 = combinedBS[0];
let resultBS2 = combinedEastBS[0];
let resultBS3 = combinedWestBS[0];
for (i = 1; i < combinedBS.length; i++) {
resultBS1 = BoundingSphere_default.union(resultBS1, combinedBS[i]);
}
for (i = 1; i < combinedEastBS.length; i++) {
resultBS2 = BoundingSphere_default.union(resultBS2, combinedEastBS[i]);
}
for (i = 1; i < combinedWestBS.length; i++) {
resultBS3 = BoundingSphere_default.union(resultBS3, combinedWestBS[i]);
}
const result = [];
if (defined_default(resultBS1)) {
result.push(resultBS1);
}
if (defined_default(resultBS2)) {
result.push(resultBS2);
}
if (defined_default(resultBS3)) {
result.push(resultBS3);
}
for (i = 0; i < result.length; i++) {
const boundingSphere = result[i].clone(primitive._boundingSpheres[i]);
primitive._boundingSpheres[i] = boundingSphere;
primitive._boundingSphereCV[i] = BoundingSphere_default.projectTo2D(
boundingSphere,
frameState.mapProjection,
primitive._boundingSphereCV[i]
);
}
Primitive._updateBoundingVolumes(
primitive,
frameState,
primitive.modelMatrix,
true
);
primitive._recomputeBoundingSpheres = false;
}
var scratchBoundingSphereCenterEncoded = new EncodedCartesian3_default();
var scratchBoundingSphereCartographic = new Cartographic_default();
var scratchBoundingSphereCenter2D = new Cartesian3_default();
var scratchBoundingSphere3 = new BoundingSphere_default();
function updateBatchTableBoundingSpheres(primitive, frameState) {
const hasDistanceDisplayCondition = defined_default(
primitive._batchTableAttributeIndices.distanceDisplayCondition
);
if (!hasDistanceDisplayCondition || primitive._batchTableBoundingSpheresUpdated) {
return;
}
const indices = primitive._batchTableBoundingSphereAttributeIndices;
const center3DHighIndex = indices.center3DHigh;
const center3DLowIndex = indices.center3DLow;
const center2DHighIndex = indices.center2DHigh;
const center2DLowIndex = indices.center2DLow;
const radiusIndex = indices.radius;
const projection = frameState.mapProjection;
const ellipsoid = projection.ellipsoid;
const batchTable = primitive._batchTable;
const boundingSpheres = primitive._instanceBoundingSpheres;
const length2 = boundingSpheres.length;
for (let i = 0; i < length2; ++i) {
let boundingSphere = boundingSpheres[i];
if (!defined_default(boundingSphere)) {
continue;
}
const modelMatrix = primitive.modelMatrix;
if (defined_default(modelMatrix)) {
boundingSphere = BoundingSphere_default.transform(
boundingSphere,
modelMatrix,
scratchBoundingSphere3
);
}
const center = boundingSphere.center;
const radius = boundingSphere.radius;
let encodedCenter = EncodedCartesian3_default.fromCartesian(
center,
scratchBoundingSphereCenterEncoded
);
batchTable.setBatchedAttribute(i, center3DHighIndex, encodedCenter.high);
batchTable.setBatchedAttribute(i, center3DLowIndex, encodedCenter.low);
if (!frameState.scene3DOnly) {
const cartographic2 = ellipsoid.cartesianToCartographic(
center,
scratchBoundingSphereCartographic
);
const center2D = projection.project(
cartographic2,
scratchBoundingSphereCenter2D
);
encodedCenter = EncodedCartesian3_default.fromCartesian(
center2D,
scratchBoundingSphereCenterEncoded
);
batchTable.setBatchedAttribute(i, center2DHighIndex, encodedCenter.high);
batchTable.setBatchedAttribute(i, center2DLowIndex, encodedCenter.low);
}
batchTable.setBatchedAttribute(i, radiusIndex, radius);
}
primitive._batchTableBoundingSpheresUpdated = true;
}
var offsetScratchCartesian = new Cartesian3_default();
var offsetCenterScratch = new Cartesian3_default();
function updateBatchTableOffsets(primitive, frameState) {
const hasOffset = defined_default(primitive._batchTableAttributeIndices.offset);
if (!hasOffset || primitive._batchTableOffsetsUpdated || frameState.scene3DOnly) {
return;
}
const index2D = primitive._batchTableOffsetAttribute2DIndex;
const projection = frameState.mapProjection;
const ellipsoid = projection.ellipsoid;
const batchTable = primitive._batchTable;
const boundingSpheres = primitive._instanceBoundingSpheres;
const length2 = boundingSpheres.length;
for (let i = 0; i < length2; ++i) {
let boundingSphere = boundingSpheres[i];
if (!defined_default(boundingSphere)) {
continue;
}
const offset = batchTable.getBatchedAttribute(
i,
primitive._batchTableAttributeIndices.offset
);
if (Cartesian3_default.equals(offset, Cartesian3_default.ZERO)) {
batchTable.setBatchedAttribute(i, index2D, Cartesian3_default.ZERO);
continue;
}
const modelMatrix = primitive.modelMatrix;
if (defined_default(modelMatrix)) {
boundingSphere = BoundingSphere_default.transform(
boundingSphere,
modelMatrix,
scratchBoundingSphere3
);
}
let center = boundingSphere.center;
center = ellipsoid.scaleToGeodeticSurface(center, offsetCenterScratch);
let cartographic2 = ellipsoid.cartesianToCartographic(
center,
scratchBoundingSphereCartographic
);
const center2D = projection.project(
cartographic2,
scratchBoundingSphereCenter2D
);
const newPoint = Cartesian3_default.add(offset, center, offsetScratchCartesian);
cartographic2 = ellipsoid.cartesianToCartographic(newPoint, cartographic2);
const newPointProjected = projection.project(
cartographic2,
offsetScratchCartesian
);
const newVector = Cartesian3_default.subtract(
newPointProjected,
center2D,
offsetScratchCartesian
);
const x = newVector.x;
newVector.x = newVector.z;
newVector.z = newVector.y;
newVector.y = x;
batchTable.setBatchedAttribute(i, index2D, newVector);
}
primitive._batchTableOffsetsUpdated = true;
}
function createVertexArray(primitive, frameState) {
const attributeLocations8 = primitive._attributeLocations;
const geometries = primitive._geometries;
const scene3DOnly = frameState.scene3DOnly;
const context = frameState.context;
const va = [];
const length2 = geometries.length;
for (let i = 0; i < length2; ++i) {
const geometry = geometries[i];
va.push(
VertexArray_default.fromGeometry({
context,
geometry,
attributeLocations: attributeLocations8,
bufferUsage: BufferUsage_default.STATIC_DRAW,
interleave: primitive._interleave
})
);
if (defined_default(primitive._createBoundingVolumeFunction)) {
primitive._createBoundingVolumeFunction(frameState, geometry);
} else {
primitive._boundingSpheres.push(
BoundingSphere_default.clone(geometry.boundingSphere)
);
primitive._boundingSphereWC.push(new BoundingSphere_default());
if (!scene3DOnly) {
const center = geometry.boundingSphereCV.center;
const x = center.x;
const y = center.y;
const z = center.z;
center.x = z;
center.y = x;
center.z = y;
primitive._boundingSphereCV.push(
BoundingSphere_default.clone(geometry.boundingSphereCV)
);
primitive._boundingSphere2D.push(new BoundingSphere_default());
primitive._boundingSphereMorph.push(new BoundingSphere_default());
}
}
}
primitive._va = va;
primitive._primitiveType = geometries[0].primitiveType;
if (primitive.releaseGeometryInstances) {
primitive.geometryInstances = void 0;
}
primitive._geometries = void 0;
setReady(primitive, frameState, PrimitiveState_default.COMPLETE, void 0);
}
function createRenderStates(primitive, context, appearance, twoPasses) {
let renderState = appearance.getRenderState();
let rs;
if (twoPasses) {
rs = clone_default(renderState, false);
rs.cull = {
enabled: true,
face: CullFace_default.BACK
};
primitive._frontFaceRS = RenderState_default.fromCache(rs);
rs.cull.face = CullFace_default.FRONT;
primitive._backFaceRS = RenderState_default.fromCache(rs);
} else {
primitive._frontFaceRS = RenderState_default.fromCache(renderState);
primitive._backFaceRS = primitive._frontFaceRS;
}
rs = clone_default(renderState, false);
if (defined_default(primitive._depthFailAppearance)) {
rs.depthTest.enabled = false;
}
if (defined_default(primitive._depthFailAppearance)) {
renderState = primitive._depthFailAppearance.getRenderState();
rs = clone_default(renderState, false);
rs.depthTest.func = DepthFunction_default.GREATER;
if (twoPasses) {
rs.cull = {
enabled: true,
face: CullFace_default.BACK
};
primitive._frontFaceDepthFailRS = RenderState_default.fromCache(rs);
rs.cull.face = CullFace_default.FRONT;
primitive._backFaceDepthFailRS = RenderState_default.fromCache(rs);
} else {
primitive._frontFaceDepthFailRS = RenderState_default.fromCache(rs);
primitive._backFaceDepthFailRS = primitive._frontFaceRS;
}
}
}
function createShaderProgram(primitive, frameState, appearance) {
const context = frameState.context;
const attributeLocations8 = primitive._attributeLocations;
let vs = primitive._batchTable.getVertexShaderCallback()(
appearance.vertexShaderSource
);
vs = Primitive._appendOffsetToShader(primitive, vs);
vs = Primitive._appendShowToShader(primitive, vs);
vs = Primitive._appendDistanceDisplayConditionToShader(
primitive,
vs,
frameState.scene3DOnly
);
vs = appendPickToVertexShader(vs);
vs = Primitive._updateColorAttribute(primitive, vs, false);
vs = modifyForEncodedNormals(primitive, vs);
vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly);
let fs = appearance.getFragmentShaderSource();
fs = appendPickToFragmentShader(fs);
primitive._sp = ShaderProgram_default.replaceCache({
context,
shaderProgram: primitive._sp,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations8
});
validateShaderMatching(primitive._sp, attributeLocations8);
if (defined_default(primitive._depthFailAppearance)) {
vs = primitive._batchTable.getVertexShaderCallback()(
primitive._depthFailAppearance.vertexShaderSource
);
vs = Primitive._appendShowToShader(primitive, vs);
vs = Primitive._appendDistanceDisplayConditionToShader(
primitive,
vs,
frameState.scene3DOnly
);
vs = appendPickToVertexShader(vs);
vs = Primitive._updateColorAttribute(primitive, vs, true);
vs = modifyForEncodedNormals(primitive, vs);
vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly);
vs = depthClampVS(vs);
fs = primitive._depthFailAppearance.getFragmentShaderSource();
fs = appendPickToFragmentShader(fs);
fs = depthClampFS(fs);
primitive._spDepthFail = ShaderProgram_default.replaceCache({
context,
shaderProgram: primitive._spDepthFail,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations8
});
validateShaderMatching(primitive._spDepthFail, attributeLocations8);
}
}
var modifiedModelViewScratch = new Matrix4_default();
var rtcScratch = new Cartesian3_default();
function getUniforms(primitive, appearance, material, frameState) {
const materialUniformMap = defined_default(material) ? material._uniforms : void 0;
const appearanceUniformMap = {};
const appearanceUniforms = appearance.uniforms;
if (defined_default(appearanceUniforms)) {
for (const name in appearanceUniforms) {
if (appearanceUniforms.hasOwnProperty(name)) {
if (defined_default(materialUniformMap) && defined_default(materialUniformMap[name])) {
throw new DeveloperError_default(
`Appearance and material have a uniform with the same name: ${name}`
);
}
appearanceUniformMap[name] = getUniformFunction(
appearanceUniforms,
name
);
}
}
}
let uniforms = combine_default(appearanceUniformMap, materialUniformMap);
uniforms = primitive._batchTable.getUniformMapCallback()(uniforms);
if (defined_default(primitive.rtcCenter)) {
uniforms.u_modifiedModelView = function() {
const viewMatrix = frameState.context.uniformState.view;
Matrix4_default.multiply(
viewMatrix,
primitive._modelMatrix,
modifiedModelViewScratch
);
Matrix4_default.multiplyByPoint(
modifiedModelViewScratch,
primitive.rtcCenter,
rtcScratch
);
Matrix4_default.setTranslation(
modifiedModelViewScratch,
rtcScratch,
modifiedModelViewScratch
);
return modifiedModelViewScratch;
};
}
return uniforms;
}
function createCommands(primitive, appearance, material, translucent, twoPasses, colorCommands, pickCommands, frameState) {
const uniforms = getUniforms(primitive, appearance, material, frameState);
let depthFailUniforms;
if (defined_default(primitive._depthFailAppearance)) {
depthFailUniforms = getUniforms(
primitive,
primitive._depthFailAppearance,
primitive._depthFailAppearance.material,
frameState
);
}
const pass = translucent ? Pass_default.TRANSLUCENT : Pass_default.OPAQUE;
let multiplier = twoPasses ? 2 : 1;
multiplier *= defined_default(primitive._depthFailAppearance) ? 2 : 1;
colorCommands.length = primitive._va.length * multiplier;
const length2 = colorCommands.length;
let vaIndex = 0;
for (let i = 0; i < length2; ++i) {
let colorCommand;
if (twoPasses) {
colorCommand = colorCommands[i];
if (!defined_default(colorCommand)) {
colorCommand = colorCommands[i] = new DrawCommand_default({
owner: primitive,
primitiveType: primitive._primitiveType
});
}
colorCommand.vertexArray = primitive._va[vaIndex];
colorCommand.renderState = primitive._backFaceRS;
colorCommand.shaderProgram = primitive._sp;
colorCommand.uniformMap = uniforms;
colorCommand.pass = pass;
++i;
}
colorCommand = colorCommands[i];
if (!defined_default(colorCommand)) {
colorCommand = colorCommands[i] = new DrawCommand_default({
owner: primitive,
primitiveType: primitive._primitiveType
});
}
colorCommand.vertexArray = primitive._va[vaIndex];
colorCommand.renderState = primitive._frontFaceRS;
colorCommand.shaderProgram = primitive._sp;
colorCommand.uniformMap = uniforms;
colorCommand.pass = pass;
if (defined_default(primitive._depthFailAppearance)) {
if (twoPasses) {
++i;
colorCommand = colorCommands[i];
if (!defined_default(colorCommand)) {
colorCommand = colorCommands[i] = new DrawCommand_default({
owner: primitive,
primitiveType: primitive._primitiveType
});
}
colorCommand.vertexArray = primitive._va[vaIndex];
colorCommand.renderState = primitive._backFaceDepthFailRS;
colorCommand.shaderProgram = primitive._spDepthFail;
colorCommand.uniformMap = depthFailUniforms;
colorCommand.pass = pass;
}
++i;
colorCommand = colorCommands[i];
if (!defined_default(colorCommand)) {
colorCommand = colorCommands[i] = new DrawCommand_default({
owner: primitive,
primitiveType: primitive._primitiveType
});
}
colorCommand.vertexArray = primitive._va[vaIndex];
colorCommand.renderState = primitive._frontFaceDepthFailRS;
colorCommand.shaderProgram = primitive._spDepthFail;
colorCommand.uniformMap = depthFailUniforms;
colorCommand.pass = pass;
}
++vaIndex;
}
}
Primitive._updateBoundingVolumes = function(primitive, frameState, modelMatrix, forceUpdate) {
let i;
let length2;
let boundingSphere;
if (forceUpdate || !Matrix4_default.equals(modelMatrix, primitive._modelMatrix)) {
Matrix4_default.clone(modelMatrix, primitive._modelMatrix);
length2 = primitive._boundingSpheres.length;
for (i = 0; i < length2; ++i) {
boundingSphere = primitive._boundingSpheres[i];
if (defined_default(boundingSphere)) {
primitive._boundingSphereWC[i] = BoundingSphere_default.transform(
boundingSphere,
modelMatrix,
primitive._boundingSphereWC[i]
);
if (!frameState.scene3DOnly) {
primitive._boundingSphere2D[i] = BoundingSphere_default.clone(
primitive._boundingSphereCV[i],
primitive._boundingSphere2D[i]
);
primitive._boundingSphereMorph[i] = BoundingSphere_default.union(
primitive._boundingSphereWC[i],
primitive._boundingSphereCV[i]
);
}
}
}
}
const pixelSize = primitive.appearance.pixelSize;
if (defined_default(pixelSize)) {
length2 = primitive._boundingSpheres.length;
for (i = 0; i < length2; ++i) {
boundingSphere = primitive._boundingSpheres[i];
const boundingSphereWC = primitive._boundingSphereWC[i];
const pixelSizeInMeters = frameState.camera.getPixelSize(
boundingSphere,
frameState.context.drawingBufferWidth,
frameState.context.drawingBufferHeight
);
const sizeInMeters = pixelSizeInMeters * pixelSize;
boundingSphereWC.radius = boundingSphere.radius + sizeInMeters;
}
}
};
function updateAndQueueCommands(primitive, frameState, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume2, twoPasses) {
if (frameState.mode !== SceneMode_default.SCENE3D && !Matrix4_default.equals(modelMatrix, Matrix4_default.IDENTITY)) {
throw new DeveloperError_default(
"Primitive.modelMatrix is only supported in 3D mode."
);
}
Primitive._updateBoundingVolumes(primitive, frameState, modelMatrix);
let boundingSpheres;
if (frameState.mode === SceneMode_default.SCENE3D) {
boundingSpheres = primitive._boundingSphereWC;
} else if (frameState.mode === SceneMode_default.COLUMBUS_VIEW) {
boundingSpheres = primitive._boundingSphereCV;
} else if (frameState.mode === SceneMode_default.SCENE2D && defined_default(primitive._boundingSphere2D)) {
boundingSpheres = primitive._boundingSphere2D;
} else if (defined_default(primitive._boundingSphereMorph)) {
boundingSpheres = primitive._boundingSphereMorph;
}
const commandList = frameState.commandList;
const passes = frameState.passes;
if (passes.render || passes.pick) {
const allowPicking = primitive.allowPicking;
const castShadows = ShadowMode_default.castShadows(primitive.shadows);
const receiveShadows = ShadowMode_default.receiveShadows(primitive.shadows);
const colorLength = colorCommands.length;
let factor2 = twoPasses ? 2 : 1;
factor2 *= defined_default(primitive._depthFailAppearance) ? 2 : 1;
for (let j = 0; j < colorLength; ++j) {
const sphereIndex = Math.floor(j / factor2);
const colorCommand = colorCommands[j];
colorCommand.modelMatrix = modelMatrix;
colorCommand.boundingVolume = boundingSpheres[sphereIndex];
colorCommand.cull = cull;
colorCommand.debugShowBoundingVolume = debugShowBoundingVolume2;
colorCommand.castShadows = castShadows;
colorCommand.receiveShadows = receiveShadows;
if (allowPicking) {
colorCommand.pickId = "v_pickColor";
} else {
colorCommand.pickId = void 0;
}
commandList.push(colorCommand);
}
}
}
Primitive.prototype.update = function(frameState) {
if (!defined_default(this.geometryInstances) && this._va.length === 0 || defined_default(this.geometryInstances) && Array.isArray(this.geometryInstances) && this.geometryInstances.length === 0 || !defined_default(this.appearance) || frameState.mode !== SceneMode_default.SCENE3D && frameState.scene3DOnly || !frameState.passes.render && !frameState.passes.pick) {
return;
}
if (defined_default(this._error)) {
throw this._error;
}
if (defined_default(this.rtcCenter) && !frameState.scene3DOnly) {
throw new DeveloperError_default(
"RTC rendering is only available for 3D only scenes."
);
}
if (this._state === PrimitiveState_default.FAILED) {
return;
}
const context = frameState.context;
if (!defined_default(this._batchTable)) {
createBatchTable(this, context);
}
if (this._batchTable.attributes.length > 0) {
if (ContextLimits_default.maximumVertexTextureImageUnits === 0) {
throw new RuntimeError_default(
"Vertex texture fetch support is required to render primitives with per-instance attributes. The maximum number of vertex texture image units must be greater than zero."
);
}
this._batchTable.update(frameState);
}
if (this._state !== PrimitiveState_default.COMPLETE && this._state !== PrimitiveState_default.COMBINED) {
if (this.asynchronous) {
loadAsynchronous(this, frameState);
} else {
loadSynchronous(this, frameState);
}
}
if (this._state === PrimitiveState_default.COMBINED) {
updateBatchTableBoundingSpheres(this, frameState);
updateBatchTableOffsets(this, frameState);
createVertexArray(this, frameState);
}
if (!this.show || this._state !== PrimitiveState_default.COMPLETE) {
return;
}
if (!this._batchTableOffsetsUpdated) {
updateBatchTableOffsets(this, frameState);
}
if (this._recomputeBoundingSpheres) {
recomputeBoundingSpheres(this, frameState);
}
const appearance = this.appearance;
const material = appearance.material;
let createRS = false;
let createSP = false;
if (this._appearance !== appearance) {
this._appearance = appearance;
this._material = material;
createRS = true;
createSP = true;
} else if (this._material !== material) {
this._material = material;
createSP = true;
}
const depthFailAppearance = this.depthFailAppearance;
const depthFailMaterial = defined_default(depthFailAppearance) ? depthFailAppearance.material : void 0;
if (this._depthFailAppearance !== depthFailAppearance) {
this._depthFailAppearance = depthFailAppearance;
this._depthFailMaterial = depthFailMaterial;
createRS = true;
createSP = true;
} else if (this._depthFailMaterial !== depthFailMaterial) {
this._depthFailMaterial = depthFailMaterial;
createSP = true;
}
const translucent = this._appearance.isTranslucent();
if (this._translucent !== translucent) {
this._translucent = translucent;
createRS = true;
}
if (defined_default(this._material)) {
this._material.update(context);
}
const twoPasses = appearance.closed && translucent;
if (createRS) {
const rsFunc = this._createRenderStatesFunction ?? createRenderStates;
rsFunc(this, context, appearance, twoPasses);
}
if (createSP) {
const spFunc = this._createShaderProgramFunction ?? createShaderProgram;
spFunc(this, frameState, appearance);
}
if (createRS || createSP) {
const commandFunc = this._createCommandsFunction ?? createCommands;
commandFunc(
this,
appearance,
material,
translucent,
twoPasses,
this._colorCommands,
this._pickCommands,
frameState
);
}
const updateAndQueueCommandsFunc = this._updateAndQueueCommandsFunction ?? updateAndQueueCommands;
updateAndQueueCommandsFunc(
this,
frameState,
this._colorCommands,
this._pickCommands,
this.modelMatrix,
this.cull,
this.debugShowBoundingVolume,
twoPasses
);
};
var offsetBoundingSphereScratch1 = new BoundingSphere_default();
var offsetBoundingSphereScratch2 = new BoundingSphere_default();
function transformBoundingSphere(boundingSphere, offset, offsetAttribute) {
if (offsetAttribute === GeometryOffsetAttribute_default.TOP) {
const origBS = BoundingSphere_default.clone(
boundingSphere,
offsetBoundingSphereScratch1
);
const offsetBS = BoundingSphere_default.clone(
boundingSphere,
offsetBoundingSphereScratch2
);
offsetBS.center = Cartesian3_default.add(offsetBS.center, offset, offsetBS.center);
boundingSphere = BoundingSphere_default.union(origBS, offsetBS, boundingSphere);
} else if (offsetAttribute === GeometryOffsetAttribute_default.ALL) {
boundingSphere.center = Cartesian3_default.add(
boundingSphere.center,
offset,
boundingSphere.center
);
}
return boundingSphere;
}
function createGetFunction(batchTable, instanceIndex, attributeIndex) {
return function() {
const attributeValue = batchTable.getBatchedAttribute(
instanceIndex,
attributeIndex
);
const attribute = batchTable.attributes[attributeIndex];
const componentsPerAttribute = attribute.componentsPerAttribute;
const value = ComponentDatatype_default.createTypedArray(
attribute.componentDatatype,
componentsPerAttribute
);
if (defined_default(attributeValue.constructor.pack)) {
attributeValue.constructor.pack(attributeValue, value, 0);
} else {
value[0] = attributeValue;
}
return value;
};
}
function createSetFunction(batchTable, instanceIndex, attributeIndex, primitive, name) {
return function(value) {
if (!defined_default(value) || !defined_default(value.length) || value.length < 1 || value.length > 4) {
throw new DeveloperError_default(
"value must be and array with length between 1 and 4."
);
}
const attributeValue = getAttributeValue(value);
batchTable.setBatchedAttribute(
instanceIndex,
attributeIndex,
attributeValue
);
if (name === "offset") {
primitive._recomputeBoundingSpheres = true;
primitive._batchTableOffsetsUpdated = false;
}
};
}
var offsetScratch2 = new Cartesian3_default();
function createBoundingSphereProperties(primitive, properties, index) {
properties.boundingSphere = {
get: function() {
let boundingSphere = primitive._instanceBoundingSpheres[index];
if (defined_default(boundingSphere)) {
boundingSphere = boundingSphere.clone();
const modelMatrix = primitive.modelMatrix;
const offset = properties.offset;
if (defined_default(offset)) {
transformBoundingSphere(
boundingSphere,
Cartesian3_default.fromArray(offset.get(), 0, offsetScratch2),
primitive._offsetInstanceExtend[index]
);
}
if (defined_default(modelMatrix)) {
boundingSphere = BoundingSphere_default.transform(
boundingSphere,
modelMatrix
);
}
}
return boundingSphere;
}
};
properties.boundingSphereCV = {
get: function() {
return primitive._instanceBoundingSpheresCV[index];
}
};
}
function createPickIdProperty(primitive, properties, index) {
properties.pickId = {
get: function() {
return primitive._pickIds[index];
}
};
}
Primitive.prototype.getGeometryInstanceAttributes = function(id) {
if (!defined_default(id)) {
throw new DeveloperError_default("id is required");
}
if (!defined_default(this._batchTable)) {
throw new DeveloperError_default(
"must call update before calling getGeometryInstanceAttributes"
);
}
let attributes = this._perInstanceAttributeCache.get(id);
if (defined_default(attributes)) {
return attributes;
}
let index = -1;
const lastIndex = this._lastPerInstanceAttributeIndex;
const ids = this._instanceIds;
const length2 = ids.length;
for (let i = 0; i < length2; ++i) {
const curIndex = (lastIndex + i) % length2;
if (id === ids[curIndex]) {
index = curIndex;
break;
}
}
if (index === -1) {
return void 0;
}
const batchTable = this._batchTable;
const perInstanceAttributeIndices = this._batchTableAttributeIndices;
attributes = {};
const properties = {};
for (const name in perInstanceAttributeIndices) {
if (perInstanceAttributeIndices.hasOwnProperty(name)) {
const attributeIndex = perInstanceAttributeIndices[name];
properties[name] = {
get: createGetFunction(batchTable, index, attributeIndex),
set: createSetFunction(batchTable, index, attributeIndex, this, name)
};
}
}
createBoundingSphereProperties(this, properties, index);
createPickIdProperty(this, properties, index);
Object.defineProperties(attributes, properties);
this._lastPerInstanceAttributeIndex = index;
this._perInstanceAttributeCache.set(id, attributes);
return attributes;
};
Primitive.prototype.isDestroyed = function() {
return false;
};
Primitive.prototype.destroy = function() {
let length2;
let i;
this._sp = this._sp && this._sp.destroy();
this._spDepthFail = this._spDepthFail && this._spDepthFail.destroy();
const va = this._va;
length2 = va.length;
for (i = 0; i < length2; ++i) {
va[i].destroy();
}
this._va = void 0;
const pickIds = this._pickIds;
length2 = pickIds.length;
for (i = 0; i < length2; ++i) {
pickIds[i].destroy();
}
this._pickIds = void 0;
this._batchTable = this._batchTable && this._batchTable.destroy();
this._instanceIds = void 0;
this._perInstanceAttributeCache = void 0;
this._attributeLocations = void 0;
return destroyObject_default(this);
};
function setReady(primitive, frameState, state, error) {
primitive._error = error;
primitive._state = state;
frameState.afterRender.push(function() {
primitive._ready = primitive._state === PrimitiveState_default.COMPLETE || primitive._state === PrimitiveState_default.FAILED;
});
}
var Primitive_default = Primitive;
// packages/engine/Source/Scene/ShadowVolumeAppearance.js
var import_InlineWorkers365 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/GeometryInstanceAttribute.js
var import_InlineWorkers363 = __toESM(require_InlineWorkers(), 1);
function GeometryInstanceAttribute(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
if (!defined_default(options.componentDatatype)) {
throw new DeveloperError_default("options.componentDatatype is required.");
}
if (!defined_default(options.componentsPerAttribute)) {
throw new DeveloperError_default("options.componentsPerAttribute is required.");
}
if (options.componentsPerAttribute < 1 || options.componentsPerAttribute > 4) {
throw new DeveloperError_default(
"options.componentsPerAttribute must be between 1 and 4."
);
}
if (!defined_default(options.value)) {
throw new DeveloperError_default("options.value is required.");
}
this.componentDatatype = options.componentDatatype;
this.componentsPerAttribute = options.componentsPerAttribute;
this.normalize = options.normalize ?? false;
this.value = options.value;
}
var GeometryInstanceAttribute_default = GeometryInstanceAttribute;
// packages/engine/Source/Shaders/ShadowVolumeAppearanceFS.js
var import_InlineWorkers364 = __toESM(require_InlineWorkers(), 1);
var ShadowVolumeAppearanceFS_default = "#ifdef TEXTURE_COORDINATES\n#ifdef SPHERICAL\nin vec4 v_sphericalExtents;\n#else // SPHERICAL\nin vec2 v_inversePlaneExtents;\nin vec4 v_westPlane;\nin vec4 v_southPlane;\n#endif // SPHERICAL\nin vec3 v_uvMinAndSphericalLongitudeRotation;\nin vec3 v_uMaxAndInverseDistance;\nin vec3 v_vMaxAndInverseDistance;\n#endif // TEXTURE_COORDINATES\n\n#ifdef PER_INSTANCE_COLOR\nin vec4 v_color;\n#endif\n\n#ifdef NORMAL_EC\nvec3 getEyeCoordinate3FromWindowCoordinate(vec2 fragCoord, float logDepthOrDepth) {\n vec4 eyeCoordinate = czm_windowToEyeCoordinates(fragCoord, logDepthOrDepth);\n return eyeCoordinate.xyz / eyeCoordinate.w;\n}\n\nvec3 vectorFromOffset(vec4 eyeCoordinate, vec2 positiveOffset) {\n vec2 glFragCoordXY = gl_FragCoord.xy;\n // Sample depths at both offset and negative offset\n float upOrRightLogDepth = czm_unpackDepth(texture(czm_globeDepthTexture, (glFragCoordXY + positiveOffset) / czm_viewport.zw));\n float downOrLeftLogDepth = czm_unpackDepth(texture(czm_globeDepthTexture, (glFragCoordXY - positiveOffset) / czm_viewport.zw));\n // Explicitly evaluate both paths\n // Necessary for multifrustum and for edges of the screen\n bvec2 upOrRightInBounds = lessThan(glFragCoordXY + positiveOffset, czm_viewport.zw);\n float useUpOrRight = float(upOrRightLogDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);\n float useDownOrLeft = float(useUpOrRight == 0.0);\n vec3 upOrRightEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY + positiveOffset, upOrRightLogDepth);\n vec3 downOrLeftEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY - positiveOffset, downOrLeftLogDepth);\n return (upOrRightEC - (eyeCoordinate.xyz / eyeCoordinate.w)) * useUpOrRight + ((eyeCoordinate.xyz / eyeCoordinate.w) - downOrLeftEC) * useDownOrLeft;\n}\n#endif // NORMAL_EC\n\nvoid main(void)\n{\n#ifdef REQUIRES_EC\n float logDepthOrDepth = czm_unpackDepth(texture(czm_globeDepthTexture, gl_FragCoord.xy / czm_viewport.zw));\n vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth);\n#endif\n\n#ifdef REQUIRES_WC\n vec4 worldCoordinate4 = czm_inverseView * eyeCoordinate;\n vec3 worldCoordinate = worldCoordinate4.xyz / worldCoordinate4.w;\n#endif\n\n#ifdef TEXTURE_COORDINATES\n vec2 uv;\n#ifdef SPHERICAL\n // Treat world coords as a sphere normal for spherical coordinates\n vec2 sphericalLatLong = czm_approximateSphericalCoordinates(worldCoordinate);\n sphericalLatLong.y += v_uvMinAndSphericalLongitudeRotation.z;\n sphericalLatLong.y = czm_branchFreeTernary(sphericalLatLong.y < czm_pi, sphericalLatLong.y, sphericalLatLong.y - czm_twoPi);\n uv.x = (sphericalLatLong.y - v_sphericalExtents.y) * v_sphericalExtents.w;\n uv.y = (sphericalLatLong.x - v_sphericalExtents.x) * v_sphericalExtents.z;\n#else // SPHERICAL\n // Unpack planes and transform to eye space\n uv.x = czm_planeDistance(v_westPlane, eyeCoordinate.xyz / eyeCoordinate.w) * v_inversePlaneExtents.x;\n uv.y = czm_planeDistance(v_southPlane, eyeCoordinate.xyz / eyeCoordinate.w) * v_inversePlaneExtents.y;\n#endif // SPHERICAL\n#endif // TEXTURE_COORDINATES\n\n#ifdef PICK\n#ifdef CULL_FRAGMENTS\n // When classifying translucent geometry, logDepthOrDepth == 0.0\n // indicates a region that should not be classified, possibly due to there\n // being opaque pixels there in another buffer.\n // Check for logDepthOrDepth != 0.0 to make sure this should be classified.\n if (0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0 || logDepthOrDepth != 0.0) {\n out_FragColor.a = 1.0; // 0.0 alpha leads to discard from ShaderSource.createPickFragmentShaderSource\n czm_writeDepthClamp();\n }\n#else // CULL_FRAGMENTS\n out_FragColor.a = 1.0;\n#endif // CULL_FRAGMENTS\n#else // PICK\n\n#ifdef CULL_FRAGMENTS\n // When classifying translucent geometry, logDepthOrDepth == 0.0\n // indicates a region that should not be classified, possibly due to there\n // being opaque pixels there in another buffer.\n if (uv.x <= 0.0 || 1.0 <= uv.x || uv.y <= 0.0 || 1.0 <= uv.y || logDepthOrDepth == 0.0) {\n discard;\n }\n#endif\n\n#ifdef NORMAL_EC\n // Compute normal by sampling adjacent pixels in 2x2 block in screen space\n vec3 downUp = vectorFromOffset(eyeCoordinate, vec2(0.0, 1.0));\n vec3 leftRight = vectorFromOffset(eyeCoordinate, vec2(1.0, 0.0));\n vec3 normalEC = normalize(cross(leftRight, downUp));\n#endif\n\n\n#ifdef PER_INSTANCE_COLOR\n\n vec4 color = czm_gammaCorrect(v_color);\n#ifdef FLAT\n out_FragColor = color;\n#else // FLAT\n czm_materialInput materialInput;\n materialInput.normalEC = normalEC;\n materialInput.positionToEyeEC = -eyeCoordinate.xyz;\n czm_material material = czm_getDefaultMaterial(materialInput);\n material.diffuse = color.rgb;\n material.alpha = color.a;\n\n out_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material, czm_lightDirectionEC);\n#endif // FLAT\n\n // Premultiply alpha. Required for classification primitives on translucent globe.\n out_FragColor.rgb *= out_FragColor.a;\n\n#else // PER_INSTANCE_COLOR\n\n // Material support.\n // USES_ is distinct from REQUIRES_, because some things are dependencies of each other or\n // dependencies for culling but might not actually be used by the material.\n\n czm_materialInput materialInput;\n\n#ifdef USES_NORMAL_EC\n materialInput.normalEC = normalEC;\n#endif\n\n#ifdef USES_POSITION_TO_EYE_EC\n materialInput.positionToEyeEC = -eyeCoordinate.xyz;\n#endif\n\n#ifdef USES_TANGENT_TO_EYE\n materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(worldCoordinate, normalEC);\n#endif\n\n#ifdef USES_ST\n // Remap texture coordinates from computed (approximately aligned with cartographic space) to the desired\n // texture coordinate system, which typically forms a tight oriented bounding box around the geometry.\n // Shader is provided a set of reference points for remapping.\n materialInput.st.x = czm_lineDistance(v_uvMinAndSphericalLongitudeRotation.xy, v_uMaxAndInverseDistance.xy, uv) * v_uMaxAndInverseDistance.z;\n materialInput.st.y = czm_lineDistance(v_uvMinAndSphericalLongitudeRotation.xy, v_vMaxAndInverseDistance.xy, uv) * v_vMaxAndInverseDistance.z;\n#endif\n\n czm_material material = czm_getMaterial(materialInput);\n\n#ifdef FLAT\n out_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n#else // FLAT\n out_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material, czm_lightDirectionEC);\n#endif // FLAT\n\n // Premultiply alpha. Required for classification primitives on translucent globe.\n out_FragColor.rgb *= out_FragColor.a;\n\n#endif // PER_INSTANCE_COLOR\n czm_writeDepthClamp();\n#endif // PICK\n}\n";
// packages/engine/Source/Scene/ShadowVolumeAppearance.js
function ShadowVolumeAppearance(extentsCulling, planarExtents, appearance) {
Check_default.typeOf.bool("extentsCulling", extentsCulling);
Check_default.typeOf.bool("planarExtents", planarExtents);
Check_default.typeOf.object("appearance", appearance);
this._projectionExtentDefines = {
eastMostYhighDefine: "",
eastMostYlowDefine: "",
westMostYhighDefine: "",
westMostYlowDefine: ""
};
const colorShaderDependencies = new ShaderDependencies();
colorShaderDependencies.requiresTextureCoordinates = extentsCulling;
colorShaderDependencies.requiresEC = !appearance.flat;
const pickShaderDependencies = new ShaderDependencies();
pickShaderDependencies.requiresTextureCoordinates = extentsCulling;
if (appearance instanceof PerInstanceColorAppearance_default) {
colorShaderDependencies.requiresNormalEC = !appearance.flat;
} else {
const materialShaderSource = `${appearance.material.shaderSource}
${appearance.fragmentShaderSource}`;
colorShaderDependencies.normalEC = materialShaderSource.indexOf("materialInput.normalEC") !== -1 || materialShaderSource.indexOf("czm_getDefaultMaterial") !== -1;
colorShaderDependencies.positionToEyeEC = materialShaderSource.indexOf("materialInput.positionToEyeEC") !== -1;
colorShaderDependencies.tangentToEyeMatrix = materialShaderSource.indexOf("materialInput.tangentToEyeMatrix") !== -1;
colorShaderDependencies.st = materialShaderSource.indexOf("materialInput.st") !== -1;
}
this._colorShaderDependencies = colorShaderDependencies;
this._pickShaderDependencies = pickShaderDependencies;
this._appearance = appearance;
this._extentsCulling = extentsCulling;
this._planarExtents = planarExtents;
}
ShadowVolumeAppearance.prototype.createFragmentShader = function(columbusView2D) {
Check_default.typeOf.bool("columbusView2D", columbusView2D);
const appearance = this._appearance;
const dependencies = this._colorShaderDependencies;
const defines = [];
if (!columbusView2D && !this._planarExtents) {
defines.push("SPHERICAL");
}
if (dependencies.requiresEC) {
defines.push("REQUIRES_EC");
}
if (dependencies.requiresWC) {
defines.push("REQUIRES_WC");
}
if (dependencies.requiresTextureCoordinates) {
defines.push("TEXTURE_COORDINATES");
}
if (this._extentsCulling) {
defines.push("CULL_FRAGMENTS");
}
if (dependencies.requiresNormalEC) {
defines.push("NORMAL_EC");
}
if (appearance instanceof PerInstanceColorAppearance_default) {
defines.push("PER_INSTANCE_COLOR");
}
if (dependencies.normalEC) {
defines.push("USES_NORMAL_EC");
}
if (dependencies.positionToEyeEC) {
defines.push("USES_POSITION_TO_EYE_EC");
}
if (dependencies.tangentToEyeMatrix) {
defines.push("USES_TANGENT_TO_EYE");
}
if (dependencies.st) {
defines.push("USES_ST");
}
if (appearance.flat) {
defines.push("FLAT");
}
let materialSource = "";
if (!(appearance instanceof PerInstanceColorAppearance_default)) {
materialSource = appearance.material.shaderSource;
}
return new ShaderSource_default({
defines,
sources: [materialSource, ShadowVolumeAppearanceFS_default]
});
};
ShadowVolumeAppearance.prototype.createPickFragmentShader = function(columbusView2D) {
Check_default.typeOf.bool("columbusView2D", columbusView2D);
const dependencies = this._pickShaderDependencies;
const defines = ["PICK"];
if (!columbusView2D && !this._planarExtents) {
defines.push("SPHERICAL");
}
if (dependencies.requiresEC) {
defines.push("REQUIRES_EC");
}
if (dependencies.requiresWC) {
defines.push("REQUIRES_WC");
}
if (dependencies.requiresTextureCoordinates) {
defines.push("TEXTURE_COORDINATES");
}
if (this._extentsCulling) {
defines.push("CULL_FRAGMENTS");
}
return new ShaderSource_default({
defines,
sources: [ShadowVolumeAppearanceFS_default],
pickColorQualifier: "in"
});
};
ShadowVolumeAppearance.prototype.createVertexShader = function(defines, vertexShaderSource, columbusView2D, mapProjection) {
Check_default.defined("defines", defines);
Check_default.typeOf.string("vertexShaderSource", vertexShaderSource);
Check_default.typeOf.bool("columbusView2D", columbusView2D);
Check_default.defined("mapProjection", mapProjection);
return createShadowVolumeAppearanceVS(
this._colorShaderDependencies,
this._planarExtents,
columbusView2D,
defines,
vertexShaderSource,
this._appearance,
mapProjection,
this._projectionExtentDefines
);
};
ShadowVolumeAppearance.prototype.createPickVertexShader = function(defines, vertexShaderSource, columbusView2D, mapProjection) {
Check_default.defined("defines", defines);
Check_default.typeOf.string("vertexShaderSource", vertexShaderSource);
Check_default.typeOf.bool("columbusView2D", columbusView2D);
Check_default.defined("mapProjection", mapProjection);
return createShadowVolumeAppearanceVS(
this._pickShaderDependencies,
this._planarExtents,
columbusView2D,
defines,
vertexShaderSource,
void 0,
mapProjection,
this._projectionExtentDefines
);
};
var longitudeExtentsCartesianScratch = new Cartesian3_default();
var longitudeExtentsCartographicScratch = new Cartographic_default();
var longitudeExtentsEncodeScratch = {
high: 0,
low: 0
};
function createShadowVolumeAppearanceVS(shaderDependencies, planarExtents, columbusView2D, defines, vertexShaderSource, appearance, mapProjection, projectionExtentDefines) {
const allDefines = defines.slice();
if (projectionExtentDefines.eastMostYhighDefine === "") {
const eastMostCartographic = longitudeExtentsCartographicScratch;
eastMostCartographic.longitude = Math_default.PI;
eastMostCartographic.latitude = 0;
eastMostCartographic.height = 0;
const eastMostCartesian = mapProjection.project(
eastMostCartographic,
longitudeExtentsCartesianScratch
);
let encoded = EncodedCartesian3_default.encode(
eastMostCartesian.x,
longitudeExtentsEncodeScratch
);
projectionExtentDefines.eastMostYhighDefine = `EAST_MOST_X_HIGH ${encoded.high.toFixed(
`${encoded.high}`.length + 1
)}`;
projectionExtentDefines.eastMostYlowDefine = `EAST_MOST_X_LOW ${encoded.low.toFixed(
`${encoded.low}`.length + 1
)}`;
const westMostCartographic = longitudeExtentsCartographicScratch;
westMostCartographic.longitude = -Math_default.PI;
westMostCartographic.latitude = 0;
westMostCartographic.height = 0;
const westMostCartesian = mapProjection.project(
westMostCartographic,
longitudeExtentsCartesianScratch
);
encoded = EncodedCartesian3_default.encode(
westMostCartesian.x,
longitudeExtentsEncodeScratch
);
projectionExtentDefines.westMostYhighDefine = `WEST_MOST_X_HIGH ${encoded.high.toFixed(
`${encoded.high}`.length + 1
)}`;
projectionExtentDefines.westMostYlowDefine = `WEST_MOST_X_LOW ${encoded.low.toFixed(
`${encoded.low}`.length + 1
)}`;
}
if (columbusView2D) {
allDefines.push(projectionExtentDefines.eastMostYhighDefine);
allDefines.push(projectionExtentDefines.eastMostYlowDefine);
allDefines.push(projectionExtentDefines.westMostYhighDefine);
allDefines.push(projectionExtentDefines.westMostYlowDefine);
}
if (defined_default(appearance) && appearance instanceof PerInstanceColorAppearance_default) {
allDefines.push("PER_INSTANCE_COLOR");
}
if (shaderDependencies.requiresTextureCoordinates) {
allDefines.push("TEXTURE_COORDINATES");
if (!(planarExtents || columbusView2D)) {
allDefines.push("SPHERICAL");
}
if (columbusView2D) {
allDefines.push("COLUMBUS_VIEW_2D");
}
}
return new ShaderSource_default({
defines: allDefines,
sources: [vertexShaderSource]
});
}
function ShaderDependencies() {
this._requiresEC = false;
this._requiresWC = false;
this._requiresNormalEC = false;
this._requiresTextureCoordinates = false;
this._usesNormalEC = false;
this._usesPositionToEyeEC = false;
this._usesTangentToEyeMat = false;
this._usesSt = false;
}
Object.defineProperties(ShaderDependencies.prototype, {
// Set when assessing final shading (flat vs. phong) and culling using computed texture coordinates
requiresEC: {
get: function() {
return this._requiresEC;
},
set: function(value) {
this._requiresEC = value || this._requiresEC;
}
},
requiresWC: {
get: function() {
return this._requiresWC;
},
set: function(value) {
this._requiresWC = value || this._requiresWC;
this.requiresEC = this._requiresWC;
}
},
requiresNormalEC: {
get: function() {
return this._requiresNormalEC;
},
set: function(value) {
this._requiresNormalEC = value || this._requiresNormalEC;
this.requiresEC = this._requiresNormalEC;
}
},
requiresTextureCoordinates: {
get: function() {
return this._requiresTextureCoordinates;
},
set: function(value) {
this._requiresTextureCoordinates = value || this._requiresTextureCoordinates;
this.requiresWC = this._requiresTextureCoordinates;
}
},
// Get/Set when assessing material hookups
normalEC: {
set: function(value) {
this.requiresNormalEC = value;
this._usesNormalEC = value;
},
get: function() {
return this._usesNormalEC;
}
},
tangentToEyeMatrix: {
set: function(value) {
this.requiresWC = value;
this.requiresNormalEC = value;
this._usesTangentToEyeMat = value;
},
get: function() {
return this._usesTangentToEyeMat;
}
},
positionToEyeEC: {
set: function(value) {
this.requiresEC = value;
this._usesPositionToEyeEC = value;
},
get: function() {
return this._usesPositionToEyeEC;
}
},
st: {
set: function(value) {
this.requiresTextureCoordinates = value;
this._usesSt = value;
},
get: function() {
return this._usesSt;
}
}
});
function pointLineDistance(point1, point2, point) {
return Math.abs(
(point2.y - point1.y) * point.x - (point2.x - point1.x) * point.y + point2.x * point1.y - point2.y * point1.x
) / Cartesian2_default.distance(point2, point1);
}
var points2DScratch2 = [
new Cartesian2_default(),
new Cartesian2_default(),
new Cartesian2_default(),
new Cartesian2_default()
];
function addTextureCoordinateRotationAttributes(attributes, textureCoordinateRotationPoints4) {
const points2D = points2DScratch2;
const minXYCorner = Cartesian2_default.unpack(
textureCoordinateRotationPoints4,
0,
points2D[0]
);
const maxYCorner = Cartesian2_default.unpack(
textureCoordinateRotationPoints4,
2,
points2D[1]
);
const maxXCorner = Cartesian2_default.unpack(
textureCoordinateRotationPoints4,
4,
points2D[2]
);
attributes.uMaxVmax = new GeometryInstanceAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 4,
normalize: false,
value: [maxYCorner.x, maxYCorner.y, maxXCorner.x, maxXCorner.y]
});
const inverseExtentX = 1 / pointLineDistance(minXYCorner, maxYCorner, maxXCorner);
const inverseExtentY = 1 / pointLineDistance(minXYCorner, maxXCorner, maxYCorner);
attributes.uvMinAndExtents = new GeometryInstanceAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 4,
normalize: false,
value: [minXYCorner.x, minXYCorner.y, inverseExtentX, inverseExtentY]
});
}
var cartographicScratch = new Cartographic_default();
var cornerScratch = new Cartesian3_default();
var northWestScratch = new Cartesian3_default();
var southEastScratch = new Cartesian3_default();
var highLowScratch = { high: 0, low: 0 };
function add2DTextureCoordinateAttributes(rectangle, projection, attributes) {
const carto = cartographicScratch;
carto.height = 0;
carto.longitude = rectangle.west;
carto.latitude = rectangle.south;
const southWestCorner = projection.project(carto, cornerScratch);
carto.latitude = rectangle.north;
const northWest = projection.project(carto, northWestScratch);
carto.longitude = rectangle.east;
carto.latitude = rectangle.south;
const southEast = projection.project(carto, southEastScratch);
const valuesHigh = [0, 0, 0, 0];
const valuesLow = [0, 0, 0, 0];
let encoded = EncodedCartesian3_default.encode(southWestCorner.x, highLowScratch);
valuesHigh[0] = encoded.high;
valuesLow[0] = encoded.low;
encoded = EncodedCartesian3_default.encode(southWestCorner.y, highLowScratch);
valuesHigh[1] = encoded.high;
valuesLow[1] = encoded.low;
encoded = EncodedCartesian3_default.encode(northWest.y, highLowScratch);
valuesHigh[2] = encoded.high;
valuesLow[2] = encoded.low;
encoded = EncodedCartesian3_default.encode(southEast.x, highLowScratch);
valuesHigh[3] = encoded.high;
valuesLow[3] = encoded.low;
attributes.planes2D_HIGH = new GeometryInstanceAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 4,
normalize: false,
value: valuesHigh
});
attributes.planes2D_LOW = new GeometryInstanceAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 4,
normalize: false,
value: valuesLow
});
}
var enuMatrixScratch = new Matrix4_default();
var inverseEnuScratch = new Matrix4_default();
var rectanglePointCartesianScratch = new Cartesian3_default();
var rectangleCenterScratch2 = new Cartographic_default();
var pointsCartographicScratch = [
new Cartographic_default(),
new Cartographic_default(),
new Cartographic_default(),
new Cartographic_default(),
new Cartographic_default(),
new Cartographic_default(),
new Cartographic_default(),
new Cartographic_default()
];
function computeRectangleBounds(rectangle, ellipsoid, height, southWestCornerResult, eastVectorResult, northVectorResult) {
const centerCartographic = Rectangle_default.center(
rectangle,
rectangleCenterScratch2
);
centerCartographic.height = height;
const centerCartesian2 = Cartographic_default.toCartesian(
centerCartographic,
ellipsoid,
rectanglePointCartesianScratch
);
const enuMatrix = Transforms_default.eastNorthUpToFixedFrame(
centerCartesian2,
ellipsoid,
enuMatrixScratch
);
const inverseEnu = Matrix4_default.inverse(enuMatrix, inverseEnuScratch);
const west = rectangle.west;
const east = rectangle.east;
const north = rectangle.north;
const south = rectangle.south;
const cartographics = pointsCartographicScratch;
cartographics[0].latitude = south;
cartographics[0].longitude = west;
cartographics[1].latitude = north;
cartographics[1].longitude = west;
cartographics[2].latitude = north;
cartographics[2].longitude = east;
cartographics[3].latitude = south;
cartographics[3].longitude = east;
const longitudeCenter = (west + east) * 0.5;
const latitudeCenter = (north + south) * 0.5;
cartographics[4].latitude = south;
cartographics[4].longitude = longitudeCenter;
cartographics[5].latitude = north;
cartographics[5].longitude = longitudeCenter;
cartographics[6].latitude = latitudeCenter;
cartographics[6].longitude = west;
cartographics[7].latitude = latitudeCenter;
cartographics[7].longitude = east;
let minX = Number.POSITIVE_INFINITY;
let maxX = Number.NEGATIVE_INFINITY;
let minY = Number.POSITIVE_INFINITY;
let maxY = Number.NEGATIVE_INFINITY;
for (let i = 0; i < 8; i++) {
cartographics[i].height = height;
const pointCartesian = Cartographic_default.toCartesian(
cartographics[i],
ellipsoid,
rectanglePointCartesianScratch
);
Matrix4_default.multiplyByPoint(inverseEnu, pointCartesian, pointCartesian);
pointCartesian.z = 0;
minX = Math.min(minX, pointCartesian.x);
maxX = Math.max(maxX, pointCartesian.x);
minY = Math.min(minY, pointCartesian.y);
maxY = Math.max(maxY, pointCartesian.y);
}
const southWestCorner = southWestCornerResult;
southWestCorner.x = minX;
southWestCorner.y = minY;
southWestCorner.z = 0;
Matrix4_default.multiplyByPoint(enuMatrix, southWestCorner, southWestCorner);
const southEastCorner = eastVectorResult;
southEastCorner.x = maxX;
southEastCorner.y = minY;
southEastCorner.z = 0;
Matrix4_default.multiplyByPoint(enuMatrix, southEastCorner, southEastCorner);
Cartesian3_default.subtract(southEastCorner, southWestCorner, eastVectorResult);
const northWestCorner = northVectorResult;
northWestCorner.x = minX;
northWestCorner.y = maxY;
northWestCorner.z = 0;
Matrix4_default.multiplyByPoint(enuMatrix, northWestCorner, northWestCorner);
Cartesian3_default.subtract(northWestCorner, southWestCorner, northVectorResult);
}
var eastwardScratch = new Cartesian3_default();
var northwardScratch = new Cartesian3_default();
var encodeScratch = new EncodedCartesian3_default();
ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes = function(boundingRectangle, textureCoordinateRotationPoints4, ellipsoid, projection, height) {
Check_default.typeOf.object("boundingRectangle", boundingRectangle);
Check_default.defined(
"textureCoordinateRotationPoints",
textureCoordinateRotationPoints4
);
Check_default.typeOf.object("ellipsoid", ellipsoid);
Check_default.typeOf.object("projection", projection);
const corner = cornerScratch;
const eastward = eastwardScratch;
const northward = northwardScratch;
computeRectangleBounds(
boundingRectangle,
ellipsoid,
height ?? 0,
corner,
eastward,
northward
);
const attributes = {};
addTextureCoordinateRotationAttributes(
attributes,
textureCoordinateRotationPoints4
);
const encoded = EncodedCartesian3_default.fromCartesian(corner, encodeScratch);
attributes.southWest_HIGH = new GeometryInstanceAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
normalize: false,
value: Cartesian3_default.pack(encoded.high, [0, 0, 0])
});
attributes.southWest_LOW = new GeometryInstanceAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
normalize: false,
value: Cartesian3_default.pack(encoded.low, [0, 0, 0])
});
attributes.eastward = new GeometryInstanceAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
normalize: false,
value: Cartesian3_default.pack(eastward, [0, 0, 0])
});
attributes.northward = new GeometryInstanceAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
normalize: false,
value: Cartesian3_default.pack(northward, [0, 0, 0])
});
add2DTextureCoordinateAttributes(boundingRectangle, projection, attributes);
return attributes;
};
var spherePointScratch = new Cartesian3_default();
function latLongToSpherical(latitude, longitude, ellipsoid, result) {
const cartographic2 = cartographicScratch;
cartographic2.latitude = latitude;
cartographic2.longitude = longitude;
cartographic2.height = 0;
const spherePoint = Cartographic_default.toCartesian(
cartographic2,
ellipsoid,
spherePointScratch
);
const magXY = Math.sqrt(
spherePoint.x * spherePoint.x + spherePoint.y * spherePoint.y
);
const sphereLatitude = Math_default.fastApproximateAtan2(magXY, spherePoint.z);
const sphereLongitude = Math_default.fastApproximateAtan2(
spherePoint.x,
spherePoint.y
);
result.x = sphereLatitude;
result.y = sphereLongitude;
return result;
}
var sphericalScratch = new Cartesian2_default();
ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes = function(boundingRectangle, textureCoordinateRotationPoints4, ellipsoid, projection) {
Check_default.typeOf.object("boundingRectangle", boundingRectangle);
Check_default.defined(
"textureCoordinateRotationPoints",
textureCoordinateRotationPoints4
);
Check_default.typeOf.object("ellipsoid", ellipsoid);
Check_default.typeOf.object("projection", projection);
const southWestExtents = latLongToSpherical(
boundingRectangle.south,
boundingRectangle.west,
ellipsoid,
sphericalScratch
);
let south = southWestExtents.x;
let west = southWestExtents.y;
const northEastExtents = latLongToSpherical(
boundingRectangle.north,
boundingRectangle.east,
ellipsoid,
sphericalScratch
);
let north = northEastExtents.x;
let east = northEastExtents.y;
let rotationRadians = 0;
if (west > east) {
rotationRadians = Math_default.PI - west;
west = -Math_default.PI;
east += rotationRadians;
}
south -= Math_default.EPSILON5;
west -= Math_default.EPSILON5;
north += Math_default.EPSILON5;
east += Math_default.EPSILON5;
const longitudeRangeInverse = 1 / (east - west);
const latitudeRangeInverse = 1 / (north - south);
const attributes = {
sphericalExtents: new GeometryInstanceAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 4,
normalize: false,
value: [south, west, latitudeRangeInverse, longitudeRangeInverse]
}),
longitudeRotation: new GeometryInstanceAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 1,
normalize: false,
value: [rotationRadians]
})
};
addTextureCoordinateRotationAttributes(
attributes,
textureCoordinateRotationPoints4
);
add2DTextureCoordinateAttributes(boundingRectangle, projection, attributes);
return attributes;
};
ShadowVolumeAppearance.hasAttributesForTextureCoordinatePlanes = function(attributes) {
return defined_default(attributes.southWest_HIGH) && defined_default(attributes.southWest_LOW) && defined_default(attributes.northward) && defined_default(attributes.eastward) && defined_default(attributes.planes2D_HIGH) && defined_default(attributes.planes2D_LOW) && defined_default(attributes.uMaxVmax) && defined_default(attributes.uvMinAndExtents);
};
ShadowVolumeAppearance.hasAttributesForSphericalExtents = function(attributes) {
return defined_default(attributes.sphericalExtents) && defined_default(attributes.longitudeRotation) && defined_default(attributes.planes2D_HIGH) && defined_default(attributes.planes2D_LOW) && defined_default(attributes.uMaxVmax) && defined_default(attributes.uvMinAndExtents);
};
function shouldUseSpherical(rectangle) {
return Math.max(rectangle.width, rectangle.height) > ShadowVolumeAppearance.MAX_WIDTH_FOR_PLANAR_EXTENTS;
}
ShadowVolumeAppearance.shouldUseSphericalCoordinates = function(rectangle) {
Check_default.typeOf.object("rectangle", rectangle);
return shouldUseSpherical(rectangle);
};
ShadowVolumeAppearance.MAX_WIDTH_FOR_PLANAR_EXTENTS = Math_default.toRadians(1);
var ShadowVolumeAppearance_default = ShadowVolumeAppearance;
// packages/engine/Source/Scene/StencilConstants.js
var import_InlineWorkers368 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/StencilFunction.js
var import_InlineWorkers366 = __toESM(require_InlineWorkers(), 1);
var StencilFunction = {
/**
* The stencil test never passes.
*
* @type {number}
* @constant
*/
NEVER: WebGLConstants_default.NEVER,
/**
* The stencil test passes when the masked reference value is less than the masked stencil value.
*
* @type {number}
* @constant
*/
LESS: WebGLConstants_default.LESS,
/**
* The stencil test passes when the masked reference value is equal to the masked stencil value.
*
* @type {number}
* @constant
*/
EQUAL: WebGLConstants_default.EQUAL,
/**
* The stencil test passes when the masked reference value is less than or equal to the masked stencil value.
*
* @type {number}
* @constant
*/
LESS_OR_EQUAL: WebGLConstants_default.LEQUAL,
/**
* The stencil test passes when the masked reference value is greater than the masked stencil value.
*
* @type {number}
* @constant
*/
GREATER: WebGLConstants_default.GREATER,
/**
* The stencil test passes when the masked reference value is not equal to the masked stencil value.
*
* @type {number}
* @constant
*/
NOT_EQUAL: WebGLConstants_default.NOTEQUAL,
/**
* The stencil test passes when the masked reference value is greater than or equal to the masked stencil value.
*
* @type {number}
* @constant
*/
GREATER_OR_EQUAL: WebGLConstants_default.GEQUAL,
/**
* The stencil test always passes.
*
* @type {number}
* @constant
*/
ALWAYS: WebGLConstants_default.ALWAYS
};
var StencilFunction_default = Object.freeze(StencilFunction);
// packages/engine/Source/Scene/StencilOperation.js
var import_InlineWorkers367 = __toESM(require_InlineWorkers(), 1);
var StencilOperation = {
/**
* Sets the stencil buffer value to zero.
*
* @type {number}
* @constant
*/
ZERO: WebGLConstants_default.ZERO,
/**
* Does not change the stencil buffer.
*
* @type {number}
* @constant
*/
KEEP: WebGLConstants_default.KEEP,
/**
* Replaces the stencil buffer value with the reference value.
*
* @type {number}
* @constant
*/
REPLACE: WebGLConstants_default.REPLACE,
/**
* Increments the stencil buffer value, clamping to unsigned byte.
*
* @type {number}
* @constant
*/
INCREMENT: WebGLConstants_default.INCR,
/**
* Decrements the stencil buffer value, clamping to zero.
*
* @type {number}
* @constant
*/
DECREMENT: WebGLConstants_default.DECR,
/**
* Bitwise inverts the existing stencil buffer value.
*
* @type {number}
* @constant
*/
INVERT: WebGLConstants_default.INVERT,
/**
* Increments the stencil buffer value, wrapping to zero when exceeding the unsigned byte range.
*
* @type {number}
* @constant
*/
INCREMENT_WRAP: WebGLConstants_default.INCR_WRAP,
/**
* Decrements the stencil buffer value, wrapping to the maximum unsigned byte instead of going below zero.
*
* @type {number}
* @constant
*/
DECREMENT_WRAP: WebGLConstants_default.DECR_WRAP
};
var StencilOperation_default = Object.freeze(StencilOperation);
// packages/engine/Source/Scene/StencilConstants.js
var StencilConstants = {
CESIUM_3D_TILE_MASK: 128,
SKIP_LOD_MASK: 112,
SKIP_LOD_BIT_SHIFT: 4,
CLASSIFICATION_MASK: 15
};
StencilConstants.setCesium3DTileBit = function() {
return {
enabled: true,
frontFunction: StencilFunction_default.ALWAYS,
frontOperation: {
fail: StencilOperation_default.KEEP,
zFail: StencilOperation_default.KEEP,
zPass: StencilOperation_default.REPLACE
},
backFunction: StencilFunction_default.ALWAYS,
backOperation: {
fail: StencilOperation_default.KEEP,
zFail: StencilOperation_default.KEEP,
zPass: StencilOperation_default.REPLACE
},
reference: StencilConstants.CESIUM_3D_TILE_MASK,
mask: StencilConstants.CESIUM_3D_TILE_MASK
};
};
var StencilConstants_default = Object.freeze(StencilConstants);
// packages/engine/Source/Scene/ClassificationPrimitive.js
function ClassificationPrimitive(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const geometryInstances = options.geometryInstances;
this.geometryInstances = geometryInstances;
this.show = options.show ?? true;
this.classificationType = options.classificationType ?? ClassificationType_default.BOTH;
this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this.debugShowShadowVolume = options.debugShowShadowVolume ?? false;
this._debugShowShadowVolume = false;
this._extruded = options._extruded ?? false;
this._uniformMap = options._uniformMap;
this._sp = void 0;
this._spStencil = void 0;
this._spPick = void 0;
this._spColor = void 0;
this._spPick2D = void 0;
this._spColor2D = void 0;
this._rsStencilDepthPass = void 0;
this._rsStencilDepthPass3DTiles = void 0;
this._rsColorPass = void 0;
this._rsPickPass = void 0;
this._commandsIgnoreShow = [];
this._ready = false;
this._primitive = void 0;
this._pickPrimitive = options._pickPrimitive;
this._hasSphericalExtentsAttribute = false;
this._hasPlanarExtentsAttributes = false;
this._hasPerColorAttribute = false;
this.appearance = options.appearance;
this._createBoundingVolumeFunction = options._createBoundingVolumeFunction;
this._updateAndQueueCommandsFunction = options._updateAndQueueCommandsFunction;
this._usePickOffsets = false;
this._primitiveOptions = {
geometryInstances: void 0,
appearance: void 0,
vertexCacheOptimize: options.vertexCacheOptimize ?? false,
interleave: options.interleave ?? false,
releaseGeometryInstances: options.releaseGeometryInstances ?? true,
allowPicking: options.allowPicking ?? true,
asynchronous: options.asynchronous ?? true,
compressVertices: options.compressVertices ?? true,
_createBoundingVolumeFunction: void 0,
_createRenderStatesFunction: void 0,
_createShaderProgramFunction: void 0,
_createCommandsFunction: void 0,
_updateAndQueueCommandsFunction: void 0,
_createPickOffsets: true
};
}
Object.defineProperties(ClassificationPrimitive.prototype, {
/**
* When true, geometry vertices are optimized for the pre and post-vertex-shader caches.
*
* @memberof ClassificationPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
vertexCacheOptimize: {
get: function() {
return this._primitiveOptions.vertexCacheOptimize;
}
},
/**
* Determines if geometry vertex attributes are interleaved, which can slightly improve rendering performance.
*
* @memberof ClassificationPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
interleave: {
get: function() {
return this._primitiveOptions.interleave;
}
},
/**
* When true, the primitive does not keep a reference to the input geometryInstances to save memory.
*
* @memberof ClassificationPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
releaseGeometryInstances: {
get: function() {
return this._primitiveOptions.releaseGeometryInstances;
}
},
/**
* When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved.
*
* @memberof ClassificationPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
allowPicking: {
get: function() {
return this._primitiveOptions.allowPicking;
}
},
/**
* Determines if the geometry instances will be created and batched on a web worker.
*
* @memberof ClassificationPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
asynchronous: {
get: function() {
return this._primitiveOptions.asynchronous;
}
},
/**
* When true, geometry vertices are compressed, which will save memory.
*
* @memberof ClassificationPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
compressVertices: {
get: function() {
return this._primitiveOptions.compressVertices;
}
},
/**
* Determines if the primitive is complete and ready to render. If this property is
* true, the primitive will be rendered the next time that {@link ClassificationPrimitive#update}
* is called.
*
* @memberof ClassificationPrimitive.prototype
*
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
},
/**
* Returns true if the ClassificationPrimitive needs a separate shader and commands for 2D.
* This is because texture coordinates on ClassificationPrimitives are computed differently,
* and are used for culling when multiple GeometryInstances are batched in one ClassificationPrimitive.
* @memberof ClassificationPrimitive.prototype
* @type {boolean}
* @readonly
* @private
*/
_needs2DShader: {
get: function() {
return this._hasPlanarExtentsAttributes || this._hasSphericalExtentsAttribute;
}
}
});
ClassificationPrimitive.isSupported = function(scene) {
return scene.context.stencilBuffer;
};
function getStencilDepthRenderState(enableStencil, mask3DTiles) {
const stencilFunction = mask3DTiles ? StencilFunction_default.EQUAL : StencilFunction_default.ALWAYS;
return {
colorMask: {
red: false,
green: false,
blue: false,
alpha: false
},
stencilTest: {
enabled: enableStencil,
frontFunction: stencilFunction,
frontOperation: {
fail: StencilOperation_default.KEEP,
zFail: StencilOperation_default.DECREMENT_WRAP,
zPass: StencilOperation_default.KEEP
},
backFunction: stencilFunction,
backOperation: {
fail: StencilOperation_default.KEEP,
zFail: StencilOperation_default.INCREMENT_WRAP,
zPass: StencilOperation_default.KEEP
},
reference: StencilConstants_default.CESIUM_3D_TILE_MASK,
mask: StencilConstants_default.CESIUM_3D_TILE_MASK
},
stencilMask: StencilConstants_default.CLASSIFICATION_MASK,
depthTest: {
enabled: true,
func: DepthFunction_default.LESS_OR_EQUAL
},
depthMask: false
};
}
function getColorRenderState(enableStencil) {
return {
stencilTest: {
enabled: enableStencil,
frontFunction: StencilFunction_default.NOT_EQUAL,
frontOperation: {
fail: StencilOperation_default.ZERO,
zFail: StencilOperation_default.ZERO,
zPass: StencilOperation_default.ZERO
},
backFunction: StencilFunction_default.NOT_EQUAL,
backOperation: {
fail: StencilOperation_default.ZERO,
zFail: StencilOperation_default.ZERO,
zPass: StencilOperation_default.ZERO
},
reference: 0,
mask: StencilConstants_default.CLASSIFICATION_MASK
},
stencilMask: StencilConstants_default.CLASSIFICATION_MASK,
depthTest: {
enabled: false
},
depthMask: false,
blending: BlendingState_default.PRE_MULTIPLIED_ALPHA_BLEND
};
}
var pickRenderState = {
stencilTest: {
enabled: true,
frontFunction: StencilFunction_default.NOT_EQUAL,
frontOperation: {
fail: StencilOperation_default.ZERO,
zFail: StencilOperation_default.ZERO,
zPass: StencilOperation_default.ZERO
},
backFunction: StencilFunction_default.NOT_EQUAL,
backOperation: {
fail: StencilOperation_default.ZERO,
zFail: StencilOperation_default.ZERO,
zPass: StencilOperation_default.ZERO
},
reference: 0,
mask: StencilConstants_default.CLASSIFICATION_MASK
},
stencilMask: StencilConstants_default.CLASSIFICATION_MASK,
depthTest: {
enabled: false
},
depthMask: false
};
function createRenderStates2(classificationPrimitive, context, appearance, twoPasses) {
if (defined_default(classificationPrimitive._rsStencilDepthPass)) {
return;
}
const stencilEnabled = !classificationPrimitive.debugShowShadowVolume;
classificationPrimitive._rsStencilDepthPass = RenderState_default.fromCache(
getStencilDepthRenderState(stencilEnabled, false)
);
classificationPrimitive._rsStencilDepthPass3DTiles = RenderState_default.fromCache(
getStencilDepthRenderState(stencilEnabled, true)
);
classificationPrimitive._rsColorPass = RenderState_default.fromCache(
getColorRenderState(stencilEnabled, false)
);
classificationPrimitive._rsPickPass = RenderState_default.fromCache(pickRenderState);
}
function modifyForEncodedNormals2(primitive, vertexShaderSource) {
if (!primitive.compressVertices) {
return vertexShaderSource;
}
if (vertexShaderSource.search(/in\s+vec3\s+extrudeDirection;/g) !== -1) {
const attributeName = "compressedAttributes";
const attributeDecl = `in vec2 ${attributeName};`;
const globalDecl = "vec3 extrudeDirection;\n";
const decode = ` extrudeDirection = czm_octDecode(${attributeName}, 65535.0);
`;
let modifiedVS = vertexShaderSource;
modifiedVS = modifiedVS.replace(/in\s+vec3\s+extrudeDirection;/g, "");
modifiedVS = ShaderSource_default.replaceMain(
modifiedVS,
"czm_non_compressed_main"
);
const compressedMain = `${"void main() \n{ \n"}${decode} czm_non_compressed_main();
}`;
return [attributeDecl, globalDecl, modifiedVS, compressedMain].join("\n");
}
}
function createShaderProgram2(classificationPrimitive, frameState) {
const context = frameState.context;
const primitive = classificationPrimitive._primitive;
let vs = ShadowVolumeAppearanceVS_default;
vs = classificationPrimitive._primitive._batchTable.getVertexShaderCallback()(
vs
);
vs = Primitive_default._appendDistanceDisplayConditionToShader(primitive, vs);
vs = Primitive_default._modifyShaderPosition(
classificationPrimitive,
vs,
frameState.scene3DOnly
);
vs = Primitive_default._updateColorAttribute(primitive, vs);
const planarExtents = classificationPrimitive._hasPlanarExtentsAttributes;
const cullFragmentsUsingExtents = planarExtents || classificationPrimitive._hasSphericalExtentsAttribute;
if (classificationPrimitive._extruded) {
vs = modifyForEncodedNormals2(primitive, vs);
}
const extrudedDefine = classificationPrimitive._extruded ? "EXTRUDED_GEOMETRY" : "";
let vsSource = new ShaderSource_default({
defines: [extrudedDefine],
sources: [vs]
});
const fsSource = new ShaderSource_default({
sources: [ShadowVolumeFS_default]
});
const attributeLocations8 = classificationPrimitive._primitive._attributeLocations;
const shadowVolumeAppearance = new ShadowVolumeAppearance_default(
cullFragmentsUsingExtents,
planarExtents,
classificationPrimitive.appearance
);
classificationPrimitive._spStencil = ShaderProgram_default.replaceCache({
context,
shaderProgram: classificationPrimitive._spStencil,
vertexShaderSource: vsSource,
fragmentShaderSource: fsSource,
attributeLocations: attributeLocations8
});
if (classificationPrimitive._primitive.allowPicking) {
let vsPick = ShaderSource_default.createPickVertexShaderSource(vs);
vsPick = Primitive_default._appendShowToShader(primitive, vsPick);
vsPick = Primitive_default._updatePickColorAttribute(vsPick);
const pickFS3D = shadowVolumeAppearance.createPickFragmentShader(false);
const pickVS3D = shadowVolumeAppearance.createPickVertexShader(
[extrudedDefine],
vsPick,
false,
frameState.mapProjection
);
classificationPrimitive._spPick = ShaderProgram_default.replaceCache({
context,
shaderProgram: classificationPrimitive._spPick,
vertexShaderSource: pickVS3D,
fragmentShaderSource: pickFS3D,
attributeLocations: attributeLocations8
});
if (cullFragmentsUsingExtents) {
let pickProgram2D = context.shaderCache.getDerivedShaderProgram(
classificationPrimitive._spPick,
"2dPick"
);
if (!defined_default(pickProgram2D)) {
const pickFS2D = shadowVolumeAppearance.createPickFragmentShader(true);
const pickVS2D = shadowVolumeAppearance.createPickVertexShader(
[extrudedDefine],
vsPick,
true,
frameState.mapProjection
);
pickProgram2D = context.shaderCache.createDerivedShaderProgram(
classificationPrimitive._spPick,
"2dPick",
{
vertexShaderSource: pickVS2D,
fragmentShaderSource: pickFS2D,
attributeLocations: attributeLocations8
}
);
}
classificationPrimitive._spPick2D = pickProgram2D;
}
} else {
classificationPrimitive._spPick = ShaderProgram_default.fromCache({
context,
vertexShaderSource: vsSource,
fragmentShaderSource: fsSource,
attributeLocations: attributeLocations8
});
}
vs = Primitive_default._appendShowToShader(primitive, vs);
vsSource = new ShaderSource_default({
defines: [extrudedDefine],
sources: [vs]
});
classificationPrimitive._sp = ShaderProgram_default.replaceCache({
context,
shaderProgram: classificationPrimitive._sp,
vertexShaderSource: vsSource,
fragmentShaderSource: fsSource,
attributeLocations: attributeLocations8
});
const fsColorSource = shadowVolumeAppearance.createFragmentShader(false);
const vsColorSource = shadowVolumeAppearance.createVertexShader(
[extrudedDefine],
vs,
false,
frameState.mapProjection
);
classificationPrimitive._spColor = ShaderProgram_default.replaceCache({
context,
shaderProgram: classificationPrimitive._spColor,
vertexShaderSource: vsColorSource,
fragmentShaderSource: fsColorSource,
attributeLocations: attributeLocations8
});
if (cullFragmentsUsingExtents) {
let colorProgram2D = context.shaderCache.getDerivedShaderProgram(
classificationPrimitive._spColor,
"2dColor"
);
if (!defined_default(colorProgram2D)) {
const fsColorSource2D = shadowVolumeAppearance.createFragmentShader(true);
const vsColorSource2D = shadowVolumeAppearance.createVertexShader(
[extrudedDefine],
vs,
true,
frameState.mapProjection
);
colorProgram2D = context.shaderCache.createDerivedShaderProgram(
classificationPrimitive._spColor,
"2dColor",
{
vertexShaderSource: vsColorSource2D,
fragmentShaderSource: fsColorSource2D,
attributeLocations: attributeLocations8
}
);
}
classificationPrimitive._spColor2D = colorProgram2D;
}
}
function createColorCommands(classificationPrimitive, colorCommands) {
const primitive = classificationPrimitive._primitive;
let length2 = primitive._va.length * 2;
colorCommands.length = length2;
let i;
let command;
let derivedCommand;
let vaIndex = 0;
let uniformMap2 = primitive._batchTable.getUniformMapCallback()(
classificationPrimitive._uniformMap
);
const needs2DShader = classificationPrimitive._needs2DShader;
for (i = 0; i < length2; i += 2) {
const vertexArray = primitive._va[vaIndex++];
command = colorCommands[i];
if (!defined_default(command)) {
command = colorCommands[i] = new DrawCommand_default({
owner: classificationPrimitive,
primitiveType: primitive._primitiveType
});
}
command.vertexArray = vertexArray;
command.renderState = classificationPrimitive._rsStencilDepthPass;
command.shaderProgram = classificationPrimitive._sp;
command.uniformMap = uniformMap2;
command.pass = Pass_default.TERRAIN_CLASSIFICATION;
derivedCommand = DrawCommand_default.shallowClone(
command,
command.derivedCommands.tileset
);
derivedCommand.renderState = classificationPrimitive._rsStencilDepthPass3DTiles;
derivedCommand.pass = Pass_default.CESIUM_3D_TILE_CLASSIFICATION;
command.derivedCommands.tileset = derivedCommand;
command = colorCommands[i + 1];
if (!defined_default(command)) {
command = colorCommands[i + 1] = new DrawCommand_default({
owner: classificationPrimitive,
primitiveType: primitive._primitiveType
});
}
command.vertexArray = vertexArray;
command.renderState = classificationPrimitive._rsColorPass;
command.shaderProgram = classificationPrimitive._spColor;
command.pass = Pass_default.TERRAIN_CLASSIFICATION;
const appearance = classificationPrimitive.appearance;
const material = appearance.material;
if (defined_default(material)) {
uniformMap2 = combine_default(uniformMap2, material._uniforms);
}
command.uniformMap = uniformMap2;
derivedCommand = DrawCommand_default.shallowClone(
command,
command.derivedCommands.tileset
);
derivedCommand.pass = Pass_default.CESIUM_3D_TILE_CLASSIFICATION;
command.derivedCommands.tileset = derivedCommand;
if (needs2DShader) {
let derived2DCommand = DrawCommand_default.shallowClone(
command,
command.derivedCommands.appearance2D
);
derived2DCommand.shaderProgram = classificationPrimitive._spColor2D;
command.derivedCommands.appearance2D = derived2DCommand;
derived2DCommand = DrawCommand_default.shallowClone(
derivedCommand,
derivedCommand.derivedCommands.appearance2D
);
derived2DCommand.shaderProgram = classificationPrimitive._spColor2D;
derivedCommand.derivedCommands.appearance2D = derived2DCommand;
}
}
const commandsIgnoreShow = classificationPrimitive._commandsIgnoreShow;
const spStencil = classificationPrimitive._spStencil;
let commandIndex = 0;
length2 = commandsIgnoreShow.length = length2 / 2;
for (let j = 0; j < length2; ++j) {
const commandIgnoreShow = commandsIgnoreShow[j] = DrawCommand_default.shallowClone(
colorCommands[commandIndex],
commandsIgnoreShow[j]
);
commandIgnoreShow.shaderProgram = spStencil;
commandIgnoreShow.pass = Pass_default.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW;
commandIndex += 2;
}
}
function createPickCommands(classificationPrimitive, pickCommands) {
const usePickOffsets = classificationPrimitive._usePickOffsets;
const primitive = classificationPrimitive._primitive;
let length2 = primitive._va.length * 2;
let pickOffsets;
let pickIndex = 0;
let pickOffset;
if (usePickOffsets) {
pickOffsets = primitive._pickOffsets;
length2 = pickOffsets.length * 2;
}
pickCommands.length = length2;
let j;
let command;
let derivedCommand;
let vaIndex = 0;
const uniformMap2 = primitive._batchTable.getUniformMapCallback()(
classificationPrimitive._uniformMap
);
const needs2DShader = classificationPrimitive._needs2DShader;
for (j = 0; j < length2; j += 2) {
let vertexArray = primitive._va[vaIndex++];
if (usePickOffsets) {
pickOffset = pickOffsets[pickIndex++];
vertexArray = primitive._va[pickOffset.index];
}
command = pickCommands[j];
if (!defined_default(command)) {
command = pickCommands[j] = new DrawCommand_default({
owner: classificationPrimitive,
primitiveType: primitive._primitiveType,
pickOnly: true
});
}
command.vertexArray = vertexArray;
command.renderState = classificationPrimitive._rsStencilDepthPass;
command.shaderProgram = classificationPrimitive._sp;
command.uniformMap = uniformMap2;
command.pass = Pass_default.TERRAIN_CLASSIFICATION;
if (usePickOffsets) {
command.offset = pickOffset.offset;
command.count = pickOffset.count;
}
derivedCommand = DrawCommand_default.shallowClone(
command,
command.derivedCommands.tileset
);
derivedCommand.renderState = classificationPrimitive._rsStencilDepthPass3DTiles;
derivedCommand.pass = Pass_default.CESIUM_3D_TILE_CLASSIFICATION;
command.derivedCommands.tileset = derivedCommand;
command = pickCommands[j + 1];
if (!defined_default(command)) {
command = pickCommands[j + 1] = new DrawCommand_default({
owner: classificationPrimitive,
primitiveType: primitive._primitiveType,
pickOnly: true
});
}
command.vertexArray = vertexArray;
command.renderState = classificationPrimitive._rsPickPass;
command.shaderProgram = classificationPrimitive._spPick;
command.uniformMap = uniformMap2;
command.pass = Pass_default.TERRAIN_CLASSIFICATION;
if (usePickOffsets) {
command.offset = pickOffset.offset;
command.count = pickOffset.count;
}
derivedCommand = DrawCommand_default.shallowClone(
command,
command.derivedCommands.tileset
);
derivedCommand.pass = Pass_default.CESIUM_3D_TILE_CLASSIFICATION;
command.derivedCommands.tileset = derivedCommand;
if (needs2DShader) {
let derived2DCommand = DrawCommand_default.shallowClone(
command,
command.derivedCommands.pick2D
);
derived2DCommand.shaderProgram = classificationPrimitive._spPick2D;
command.derivedCommands.pick2D = derived2DCommand;
derived2DCommand = DrawCommand_default.shallowClone(
derivedCommand,
derivedCommand.derivedCommands.pick2D
);
derived2DCommand.shaderProgram = classificationPrimitive._spPick2D;
derivedCommand.derivedCommands.pick2D = derived2DCommand;
}
}
}
function createCommands2(classificationPrimitive, appearance, material, translucent, twoPasses, colorCommands, pickCommands) {
createColorCommands(classificationPrimitive, colorCommands);
createPickCommands(classificationPrimitive, pickCommands);
}
function boundingVolumeIndex(commandIndex, length2) {
return Math.floor(commandIndex % length2 / 2);
}
function updateAndQueueRenderCommand(command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume2) {
command.modelMatrix = modelMatrix;
command.boundingVolume = boundingVolume;
command.cull = cull;
command.debugShowBoundingVolume = debugShowBoundingVolume2;
frameState.commandList.push(command);
}
function updateAndQueuePickCommand(command, frameState, modelMatrix, cull, boundingVolume) {
command.modelMatrix = modelMatrix;
command.boundingVolume = boundingVolume;
command.cull = cull;
frameState.commandList.push(command);
}
function updateAndQueueCommands2(classificationPrimitive, frameState, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume2, twoPasses) {
const primitive = classificationPrimitive._primitive;
Primitive_default._updateBoundingVolumes(primitive, frameState, modelMatrix);
let boundingVolumes;
if (frameState.mode === SceneMode_default.SCENE3D) {
boundingVolumes = primitive._boundingSphereWC;
} else if (frameState.mode === SceneMode_default.COLUMBUS_VIEW) {
boundingVolumes = primitive._boundingSphereCV;
} else if (frameState.mode === SceneMode_default.SCENE2D && defined_default(primitive._boundingSphere2D)) {
boundingVolumes = primitive._boundingSphere2D;
} else if (defined_default(primitive._boundingSphereMorph)) {
boundingVolumes = primitive._boundingSphereMorph;
}
const classificationType = classificationPrimitive.classificationType;
const queueTerrainCommands = classificationType !== ClassificationType_default.CESIUM_3D_TILE;
const queue3DTilesCommands = classificationType !== ClassificationType_default.TERRAIN;
const passes = frameState.passes;
let i;
let boundingVolume;
let command;
if (passes.render) {
const colorLength = colorCommands.length;
for (i = 0; i < colorLength; ++i) {
boundingVolume = boundingVolumes[boundingVolumeIndex(i, colorLength)];
if (queueTerrainCommands) {
command = colorCommands[i];
updateAndQueueRenderCommand(
command,
frameState,
modelMatrix,
cull,
boundingVolume,
debugShowBoundingVolume2
);
}
if (queue3DTilesCommands) {
command = colorCommands[i].derivedCommands.tileset;
updateAndQueueRenderCommand(
command,
frameState,
modelMatrix,
cull,
boundingVolume,
debugShowBoundingVolume2
);
}
}
if (frameState.invertClassification) {
const ignoreShowCommands = classificationPrimitive._commandsIgnoreShow;
const ignoreShowCommandsLength = ignoreShowCommands.length;
for (i = 0; i < ignoreShowCommandsLength; ++i) {
boundingVolume = boundingVolumes[i];
command = ignoreShowCommands[i];
updateAndQueueRenderCommand(
command,
frameState,
modelMatrix,
cull,
boundingVolume,
debugShowBoundingVolume2
);
}
}
}
if (passes.pick) {
const pickLength = pickCommands.length;
const pickOffsets = primitive._pickOffsets;
for (i = 0; i < pickLength; ++i) {
const pickOffset = pickOffsets[boundingVolumeIndex(i, pickLength)];
boundingVolume = boundingVolumes[pickOffset.index];
if (queueTerrainCommands) {
command = pickCommands[i];
updateAndQueuePickCommand(
command,
frameState,
modelMatrix,
cull,
boundingVolume
);
}
if (queue3DTilesCommands) {
command = pickCommands[i].derivedCommands.tileset;
updateAndQueuePickCommand(
command,
frameState,
modelMatrix,
cull,
boundingVolume
);
}
}
}
}
ClassificationPrimitive.prototype.update = function(frameState) {
if (!defined_default(this._primitive) && !defined_default(this.geometryInstances)) {
return;
}
let appearance = this.appearance;
if (defined_default(appearance) && defined_default(appearance.material)) {
appearance.material.update(frameState.context);
}
const that = this;
const primitiveOptions = this._primitiveOptions;
if (!defined_default(this._primitive)) {
const instances = Array.isArray(this.geometryInstances) ? this.geometryInstances : [this.geometryInstances];
const length2 = instances.length;
let i;
let instance;
let attributes;
let hasPerColorAttribute = false;
let allColorsSame = true;
let firstColor;
let hasSphericalExtentsAttribute = false;
let hasPlanarExtentsAttributes = false;
if (length2 > 0) {
attributes = instances[0].attributes;
hasSphericalExtentsAttribute = ShadowVolumeAppearance_default.hasAttributesForSphericalExtents(attributes);
hasPlanarExtentsAttributes = ShadowVolumeAppearance_default.hasAttributesForTextureCoordinatePlanes(
attributes
);
firstColor = attributes.color;
}
for (i = 0; i < length2; i++) {
instance = instances[i];
const color = instance.attributes.color;
if (defined_default(color)) {
hasPerColorAttribute = true;
} else if (hasPerColorAttribute) {
throw new DeveloperError_default(
"All GeometryInstances must have color attributes to use per-instance color."
);
}
allColorsSame = allColorsSame && defined_default(color) && ColorGeometryInstanceAttribute_default.equals(firstColor, color);
}
if (!allColorsSame && !hasSphericalExtentsAttribute && !hasPlanarExtentsAttributes) {
throw new DeveloperError_default(
"All GeometryInstances must have the same color attribute except via GroundPrimitives"
);
}
if (hasPerColorAttribute && !defined_default(appearance)) {
appearance = new PerInstanceColorAppearance_default({
flat: true
});
this.appearance = appearance;
}
if (!hasPerColorAttribute && appearance instanceof PerInstanceColorAppearance_default) {
throw new DeveloperError_default(
"PerInstanceColorAppearance requires color GeometryInstanceAttributes on all GeometryInstances"
);
}
if (defined_default(appearance.material) && !hasSphericalExtentsAttribute && !hasPlanarExtentsAttributes) {
throw new DeveloperError_default(
"Materials on ClassificationPrimitives are not supported except via GroundPrimitives"
);
}
this._usePickOffsets = !hasSphericalExtentsAttribute && !hasPlanarExtentsAttributes;
this._hasSphericalExtentsAttribute = hasSphericalExtentsAttribute;
this._hasPlanarExtentsAttributes = hasPlanarExtentsAttributes;
this._hasPerColorAttribute = hasPerColorAttribute;
const geometryInstances = new Array(length2);
for (i = 0; i < length2; ++i) {
instance = instances[i];
geometryInstances[i] = new GeometryInstance_default({
geometry: instance.geometry,
attributes: instance.attributes,
modelMatrix: instance.modelMatrix,
id: instance.id,
pickPrimitive: this._pickPrimitive ?? that
});
}
primitiveOptions.appearance = appearance;
primitiveOptions.geometryInstances = geometryInstances;
if (defined_default(this._createBoundingVolumeFunction)) {
primitiveOptions._createBoundingVolumeFunction = function(frameState2, geometry) {
that._createBoundingVolumeFunction(frameState2, geometry);
};
}
primitiveOptions._createRenderStatesFunction = function(primitive, context, appearance2, twoPasses) {
createRenderStates2(that, context);
};
primitiveOptions._createShaderProgramFunction = function(primitive, frameState2, appearance2) {
createShaderProgram2(that, frameState2);
};
primitiveOptions._createCommandsFunction = function(primitive, appearance2, material, translucent, twoPasses, colorCommands, pickCommands) {
createCommands2(
that,
void 0,
void 0,
true,
false,
colorCommands,
pickCommands
);
};
if (defined_default(this._updateAndQueueCommandsFunction)) {
primitiveOptions._updateAndQueueCommandsFunction = function(primitive, frameState2, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume2, twoPasses) {
that._updateAndQueueCommandsFunction(
primitive,
frameState2,
colorCommands,
pickCommands,
modelMatrix,
cull,
debugShowBoundingVolume2,
twoPasses
);
};
} else {
primitiveOptions._updateAndQueueCommandsFunction = function(primitive, frameState2, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume2, twoPasses) {
updateAndQueueCommands2(
that,
frameState2,
colorCommands,
pickCommands,
modelMatrix,
cull,
debugShowBoundingVolume2,
twoPasses
);
};
}
this._primitive = new Primitive_default(primitiveOptions);
}
if (this.debugShowShadowVolume && !this._debugShowShadowVolume && this._ready) {
this._debugShowShadowVolume = true;
this._rsStencilDepthPass = RenderState_default.fromCache(
getStencilDepthRenderState(false, false)
);
this._rsStencilDepthPass3DTiles = RenderState_default.fromCache(
getStencilDepthRenderState(false, true)
);
this._rsColorPass = RenderState_default.fromCache(getColorRenderState(false));
} else if (!this.debugShowShadowVolume && this._debugShowShadowVolume) {
this._debugShowShadowVolume = false;
this._rsStencilDepthPass = RenderState_default.fromCache(
getStencilDepthRenderState(true, false)
);
this._rsStencilDepthPass3DTiles = RenderState_default.fromCache(
getStencilDepthRenderState(true, true)
);
this._rsColorPass = RenderState_default.fromCache(getColorRenderState(true));
}
if (this._primitive.appearance !== appearance) {
if (!this._hasSphericalExtentsAttribute && !this._hasPlanarExtentsAttributes && defined_default(appearance.material)) {
throw new DeveloperError_default(
"Materials on ClassificationPrimitives are not supported except via GroundPrimitive"
);
}
if (!this._hasPerColorAttribute && appearance instanceof PerInstanceColorAppearance_default) {
throw new DeveloperError_default(
"PerInstanceColorAppearance requires color GeometryInstanceAttribute"
);
}
this._primitive.appearance = appearance;
}
this._primitive.show = this.show;
this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;
this._primitive.update(frameState);
frameState.afterRender.push(() => {
if (defined_default(this._primitive) && this._primitive.ready) {
this._ready = true;
if (this.releaseGeometryInstances) {
this.geometryInstances = void 0;
}
}
});
};
ClassificationPrimitive.prototype.getGeometryInstanceAttributes = function(id) {
if (!defined_default(this._primitive)) {
throw new DeveloperError_default(
"must call update before calling getGeometryInstanceAttributes"
);
}
return this._primitive.getGeometryInstanceAttributes(id);
};
ClassificationPrimitive.prototype.isDestroyed = function() {
return false;
};
ClassificationPrimitive.prototype.destroy = function() {
this._primitive = this._primitive && this._primitive.destroy();
this._sp = this._sp && this._sp.destroy();
this._spPick = this._spPick && this._spPick.destroy();
this._spColor = this._spColor && this._spColor.destroy();
this._spPick2D = void 0;
this._spColor2D = void 0;
return destroyObject_default(this);
};
var ClassificationPrimitive_default = ClassificationPrimitive;
// packages/engine/Source/Scene/GroundPrimitive.js
var GroundPrimitiveUniformMap = {
u_globeMinimumAltitude: function() {
return 55e3;
}
};
function GroundPrimitive(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
let appearance = options.appearance;
const geometryInstances = options.geometryInstances;
if (!defined_default(appearance) && defined_default(geometryInstances)) {
const geometryInstancesArray = Array.isArray(geometryInstances) ? geometryInstances : [geometryInstances];
const geometryInstanceCount = geometryInstancesArray.length;
for (let i = 0; i < geometryInstanceCount; i++) {
const attributes = geometryInstancesArray[i].attributes;
if (defined_default(attributes) && defined_default(attributes.color)) {
appearance = new PerInstanceColorAppearance_default({
flat: true
});
break;
}
}
}
this.appearance = appearance;
this.geometryInstances = options.geometryInstances;
this.show = options.show ?? true;
this.classificationType = options.classificationType ?? ClassificationType_default.BOTH;
this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this.debugShowShadowVolume = options.debugShowShadowVolume ?? false;
this._boundingVolumes = [];
this._boundingVolumes2D = [];
this._ready = false;
this._primitive = void 0;
this._maxHeight = void 0;
this._minHeight = void 0;
this._maxTerrainHeight = ApproximateTerrainHeights_default._defaultMaxTerrainHeight;
this._minTerrainHeight = ApproximateTerrainHeights_default._defaultMinTerrainHeight;
this._boundingSpheresKeys = [];
this._boundingSpheres = [];
this._useFragmentCulling = false;
this._zIndex = void 0;
const that = this;
this._classificationPrimitiveOptions = {
geometryInstances: void 0,
appearance: void 0,
vertexCacheOptimize: options.vertexCacheOptimize ?? false,
interleave: options.interleave ?? false,
releaseGeometryInstances: options.releaseGeometryInstances ?? true,
allowPicking: options.allowPicking ?? true,
asynchronous: options.asynchronous ?? true,
compressVertices: options.compressVertices ?? true,
_createBoundingVolumeFunction: void 0,
_updateAndQueueCommandsFunction: void 0,
_pickPrimitive: that,
_extruded: true,
_uniformMap: GroundPrimitiveUniformMap
};
}
Object.defineProperties(GroundPrimitive.prototype, {
/**
* When true, geometry vertices are optimized for the pre and post-vertex-shader caches.
*
* @memberof GroundPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
vertexCacheOptimize: {
get: function() {
return this._classificationPrimitiveOptions.vertexCacheOptimize;
}
},
/**
* Determines if geometry vertex attributes are interleaved, which can slightly improve rendering performance.
*
* @memberof GroundPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
interleave: {
get: function() {
return this._classificationPrimitiveOptions.interleave;
}
},
/**
* When true, the primitive does not keep a reference to the input geometryInstances to save memory.
*
* @memberof GroundPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
releaseGeometryInstances: {
get: function() {
return this._classificationPrimitiveOptions.releaseGeometryInstances;
}
},
/**
* When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved.
*
* @memberof GroundPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
allowPicking: {
get: function() {
return this._classificationPrimitiveOptions.allowPicking;
}
},
/**
* Determines if the geometry instances will be created and batched on a web worker.
*
* @memberof GroundPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
asynchronous: {
get: function() {
return this._classificationPrimitiveOptions.asynchronous;
}
},
/**
* When true, geometry vertices are compressed, which will save memory.
*
* @memberof GroundPrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
compressVertices: {
get: function() {
return this._classificationPrimitiveOptions.compressVertices;
}
},
/**
* Determines if the primitive is complete and ready to render. If this property is
* true, the primitive will be rendered the next time that {@link GroundPrimitive#update}
* is called.
*
* @memberof GroundPrimitive.prototype
*
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
}
});
GroundPrimitive.isSupported = ClassificationPrimitive_default.isSupported;
function getComputeMaximumHeightFunction(primitive) {
return function(granularity, ellipsoid) {
const r = ellipsoid.maximumRadius;
const delta = r / Math.cos(granularity * 0.5) - r;
return primitive._maxHeight + delta;
};
}
function getComputeMinimumHeightFunction(primitive) {
return function(granularity, ellipsoid) {
return primitive._minHeight;
};
}
var scratchBVCartesianHigh = new Cartesian3_default();
var scratchBVCartesianLow = new Cartesian3_default();
var scratchBVCartesian = new Cartesian3_default();
var scratchBVCartographic = new Cartographic_default();
var scratchBVRectangle = new Rectangle_default();
function getRectangle(frameState, geometry) {
const ellipsoid = frameState.mapProjection.ellipsoid;
if (!defined_default(geometry.attributes) || !defined_default(geometry.attributes.position3DHigh)) {
if (defined_default(geometry.rectangle)) {
return geometry.rectangle;
}
return void 0;
}
const highPositions = geometry.attributes.position3DHigh.values;
const lowPositions = geometry.attributes.position3DLow.values;
const length2 = highPositions.length;
let minLat = Number.POSITIVE_INFINITY;
let minLon = Number.POSITIVE_INFINITY;
let maxLat = Number.NEGATIVE_INFINITY;
let maxLon = Number.NEGATIVE_INFINITY;
for (let i = 0; i < length2; i += 3) {
const highPosition = Cartesian3_default.unpack(
highPositions,
i,
scratchBVCartesianHigh
);
const lowPosition = Cartesian3_default.unpack(
lowPositions,
i,
scratchBVCartesianLow
);
const position = Cartesian3_default.add(
highPosition,
lowPosition,
scratchBVCartesian
);
const cartographic2 = ellipsoid.cartesianToCartographic(
position,
scratchBVCartographic
);
const latitude = cartographic2.latitude;
const longitude = cartographic2.longitude;
minLat = Math.min(minLat, latitude);
minLon = Math.min(minLon, longitude);
maxLat = Math.max(maxLat, latitude);
maxLon = Math.max(maxLon, longitude);
}
const rectangle = scratchBVRectangle;
rectangle.north = maxLat;
rectangle.south = minLat;
rectangle.east = maxLon;
rectangle.west = minLon;
return rectangle;
}
function setMinMaxTerrainHeights(primitive, rectangle, ellipsoid) {
const result = ApproximateTerrainHeights_default.getMinimumMaximumHeights(
rectangle,
ellipsoid
);
primitive._minTerrainHeight = result.minimumTerrainHeight;
primitive._maxTerrainHeight = result.maximumTerrainHeight;
}
function createBoundingVolume(groundPrimitive, frameState, geometry) {
const ellipsoid = frameState.mapProjection.ellipsoid;
const rectangle = getRectangle(frameState, geometry);
const obb = OrientedBoundingBox_default.fromRectangle(
rectangle,
groundPrimitive._minHeight,
groundPrimitive._maxHeight,
ellipsoid
);
groundPrimitive._boundingVolumes.push(obb);
if (!frameState.scene3DOnly) {
const projection = frameState.mapProjection;
const boundingVolume = BoundingSphere_default.fromRectangleWithHeights2D(
rectangle,
projection,
groundPrimitive._maxHeight,
groundPrimitive._minHeight
);
Cartesian3_default.fromElements(
boundingVolume.center.z,
boundingVolume.center.x,
boundingVolume.center.y,
boundingVolume.center
);
groundPrimitive._boundingVolumes2D.push(boundingVolume);
}
}
function boundingVolumeIndex2(commandIndex, length2) {
return Math.floor(commandIndex % length2 / 2);
}
function updateAndQueueRenderCommand2(groundPrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume2) {
const classificationPrimitive = groundPrimitive._primitive;
if (frameState.mode !== SceneMode_default.SCENE3D && command.shaderProgram === classificationPrimitive._spColor && classificationPrimitive._needs2DShader) {
command = command.derivedCommands.appearance2D;
}
command.owner = groundPrimitive;
command.modelMatrix = modelMatrix;
command.boundingVolume = boundingVolume;
command.cull = cull;
command.debugShowBoundingVolume = debugShowBoundingVolume2;
frameState.commandList.push(command);
}
function updateAndQueuePickCommand2(groundPrimitive, command, frameState, modelMatrix, cull, boundingVolume) {
const classificationPrimitive = groundPrimitive._primitive;
if (frameState.mode !== SceneMode_default.SCENE3D && command.shaderProgram === classificationPrimitive._spPick && classificationPrimitive._needs2DShader) {
command = command.derivedCommands.pick2D;
}
command.owner = groundPrimitive;
command.modelMatrix = modelMatrix;
command.boundingVolume = boundingVolume;
command.cull = cull;
frameState.commandList.push(command);
}
function updateAndQueueCommands3(groundPrimitive, frameState, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume2, twoPasses) {
let boundingVolumes;
if (frameState.mode === SceneMode_default.SCENE3D) {
boundingVolumes = groundPrimitive._boundingVolumes;
} else {
boundingVolumes = groundPrimitive._boundingVolumes2D;
}
const classificationType = groundPrimitive.classificationType;
const queueTerrainCommands = classificationType !== ClassificationType_default.CESIUM_3D_TILE;
const queue3DTilesCommands = classificationType !== ClassificationType_default.TERRAIN;
const passes = frameState.passes;
const classificationPrimitive = groundPrimitive._primitive;
let i;
let boundingVolume;
let command;
if (passes.render) {
const colorLength = colorCommands.length;
for (i = 0; i < colorLength; ++i) {
boundingVolume = boundingVolumes[boundingVolumeIndex2(i, colorLength)];
if (queueTerrainCommands) {
command = colorCommands[i];
updateAndQueueRenderCommand2(
groundPrimitive,
command,
frameState,
modelMatrix,
cull,
boundingVolume,
debugShowBoundingVolume2
);
}
if (queue3DTilesCommands) {
command = colorCommands[i].derivedCommands.tileset;
updateAndQueueRenderCommand2(
groundPrimitive,
command,
frameState,
modelMatrix,
cull,
boundingVolume,
debugShowBoundingVolume2
);
}
}
if (frameState.invertClassification) {
const ignoreShowCommands = classificationPrimitive._commandsIgnoreShow;
const ignoreShowCommandsLength = ignoreShowCommands.length;
for (i = 0; i < ignoreShowCommandsLength; ++i) {
boundingVolume = boundingVolumes[i];
command = ignoreShowCommands[i];
updateAndQueueRenderCommand2(
groundPrimitive,
command,
frameState,
modelMatrix,
cull,
boundingVolume,
debugShowBoundingVolume2
);
}
}
}
if (passes.pick) {
const pickLength = pickCommands.length;
let pickOffsets;
if (!groundPrimitive._useFragmentCulling) {
pickOffsets = classificationPrimitive._primitive._pickOffsets;
}
for (i = 0; i < pickLength; ++i) {
boundingVolume = boundingVolumes[boundingVolumeIndex2(i, pickLength)];
if (!groundPrimitive._useFragmentCulling) {
const pickOffset = pickOffsets[boundingVolumeIndex2(i, pickLength)];
boundingVolume = boundingVolumes[pickOffset.index];
}
if (queueTerrainCommands) {
command = pickCommands[i];
updateAndQueuePickCommand2(
groundPrimitive,
command,
frameState,
modelMatrix,
cull,
boundingVolume
);
}
if (queue3DTilesCommands) {
command = pickCommands[i].derivedCommands.tileset;
updateAndQueuePickCommand2(
groundPrimitive,
command,
frameState,
modelMatrix,
cull,
boundingVolume
);
}
}
}
}
GroundPrimitive.initializeTerrainHeights = function() {
return ApproximateTerrainHeights_default.initialize();
};
GroundPrimitive.prototype.update = function(frameState) {
if (!defined_default(this._primitive) && !defined_default(this.geometryInstances)) {
return;
}
if (!ApproximateTerrainHeights_default.initialized) {
if (!this.asynchronous) {
throw new DeveloperError_default(
"For synchronous GroundPrimitives, you must call GroundPrimitive.initializeTerrainHeights() and wait for the returned promise to resolve."
);
}
GroundPrimitive.initializeTerrainHeights();
return;
}
const that = this;
const primitiveOptions = this._classificationPrimitiveOptions;
if (!defined_default(this._primitive)) {
const ellipsoid = frameState.mapProjection.ellipsoid;
let instance;
let geometry;
let instanceType;
const instances = Array.isArray(this.geometryInstances) ? this.geometryInstances : [this.geometryInstances];
const length2 = instances.length;
const groundInstances = new Array(length2);
let i;
let rectangle;
for (i = 0; i < length2; ++i) {
instance = instances[i];
geometry = instance.geometry;
const instanceRectangle = getRectangle(frameState, geometry);
if (!defined_default(rectangle)) {
rectangle = Rectangle_default.clone(instanceRectangle);
} else if (defined_default(instanceRectangle)) {
Rectangle_default.union(rectangle, instanceRectangle, rectangle);
}
const id = instance.id;
if (defined_default(id) && defined_default(instanceRectangle)) {
const boundingSphere = ApproximateTerrainHeights_default.getBoundingSphere(
instanceRectangle,
ellipsoid
);
this._boundingSpheresKeys.push(id);
this._boundingSpheres.push(boundingSphere);
}
instanceType = geometry.constructor;
if (!defined_default(instanceType) || !defined_default(instanceType.createShadowVolume)) {
throw new DeveloperError_default(
"Not all of the geometry instances have GroundPrimitive support."
);
}
}
setMinMaxTerrainHeights(this, rectangle, ellipsoid);
const exaggeration = frameState.verticalExaggeration;
const exaggerationRelativeHeight = frameState.verticalExaggerationRelativeHeight;
this._minHeight = VerticalExaggeration_default.getHeight(
this._minTerrainHeight,
exaggeration,
exaggerationRelativeHeight
);
this._maxHeight = VerticalExaggeration_default.getHeight(
this._maxTerrainHeight,
exaggeration,
exaggerationRelativeHeight
);
const useFragmentCulling = GroundPrimitive._supportsMaterials(
frameState.context
);
this._useFragmentCulling = useFragmentCulling;
if (useFragmentCulling) {
let attributes;
let usePlanarExtents = true;
for (i = 0; i < length2; ++i) {
instance = instances[i];
geometry = instance.geometry;
rectangle = getRectangle(frameState, geometry);
if (ShadowVolumeAppearance_default.shouldUseSphericalCoordinates(rectangle)) {
usePlanarExtents = false;
break;
}
}
for (i = 0; i < length2; ++i) {
instance = instances[i];
geometry = instance.geometry;
instanceType = geometry.constructor;
const boundingRectangle = getRectangle(frameState, geometry);
const textureCoordinateRotationPoints4 = geometry.textureCoordinateRotationPoints;
if (usePlanarExtents) {
attributes = ShadowVolumeAppearance_default.getPlanarTextureCoordinateAttributes(
boundingRectangle,
textureCoordinateRotationPoints4,
ellipsoid,
frameState.mapProjection,
this._maxHeight
);
} else {
attributes = ShadowVolumeAppearance_default.getSphericalExtentGeometryInstanceAttributes(
boundingRectangle,
textureCoordinateRotationPoints4,
ellipsoid,
frameState.mapProjection
);
}
const instanceAttributes = instance.attributes;
for (const attributeKey in instanceAttributes) {
if (instanceAttributes.hasOwnProperty(attributeKey)) {
attributes[attributeKey] = instanceAttributes[attributeKey];
}
}
groundInstances[i] = new GeometryInstance_default({
geometry: instanceType.createShadowVolume(
geometry,
getComputeMinimumHeightFunction(this),
getComputeMaximumHeightFunction(this)
),
attributes,
id: instance.id
});
}
} else {
for (i = 0; i < length2; ++i) {
instance = instances[i];
geometry = instance.geometry;
instanceType = geometry.constructor;
groundInstances[i] = new GeometryInstance_default({
geometry: instanceType.createShadowVolume(
geometry,
getComputeMinimumHeightFunction(this),
getComputeMaximumHeightFunction(this)
),
attributes: instance.attributes,
id: instance.id
});
}
}
primitiveOptions.geometryInstances = groundInstances;
primitiveOptions.appearance = this.appearance;
primitiveOptions._createBoundingVolumeFunction = function(frameState2, geometry2) {
createBoundingVolume(that, frameState2, geometry2);
};
primitiveOptions._updateAndQueueCommandsFunction = function(primitive, frameState2, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume2, twoPasses) {
updateAndQueueCommands3(
that,
frameState2,
colorCommands,
pickCommands,
modelMatrix,
cull,
debugShowBoundingVolume2,
twoPasses
);
};
this._primitive = new ClassificationPrimitive_default(primitiveOptions);
}
this._primitive.appearance = this.appearance;
this._primitive.show = this.show;
this._primitive.debugShowShadowVolume = this.debugShowShadowVolume;
this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;
this._primitive.update(frameState);
frameState.afterRender.push(() => {
if (!this._ready && defined_default(this._primitive) && this._primitive.ready) {
this._ready = true;
if (this.releaseGeometryInstances) {
this.geometryInstances = void 0;
}
}
});
};
GroundPrimitive.prototype.getBoundingSphere = function(id) {
const index = this._boundingSpheresKeys.indexOf(id);
if (index !== -1) {
return this._boundingSpheres[index];
}
return void 0;
};
GroundPrimitive.prototype.getGeometryInstanceAttributes = function(id) {
if (!defined_default(this._primitive)) {
throw new DeveloperError_default(
"must call update before calling getGeometryInstanceAttributes"
);
}
return this._primitive.getGeometryInstanceAttributes(id);
};
GroundPrimitive.prototype.isDestroyed = function() {
return false;
};
GroundPrimitive.prototype.destroy = function() {
this._primitive = this._primitive && this._primitive.destroy();
return destroyObject_default(this);
};
GroundPrimitive._supportsMaterials = function(context) {
return context.depthTexture;
};
GroundPrimitive.supportsMaterials = function(scene) {
Check_default.typeOf.object("scene", scene);
return GroundPrimitive._supportsMaterials(scene.frameState.context);
};
var GroundPrimitive_default = GroundPrimitive;
// packages/engine/Source/DataSources/MaterialProperty.js
var import_InlineWorkers371 = __toESM(require_InlineWorkers(), 1);
function MaterialProperty() {
DeveloperError_default.throwInstantiationError();
}
Object.defineProperties(MaterialProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof MaterialProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof MaterialProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: DeveloperError_default.throwInstantiationError
}
});
MaterialProperty.prototype.getType = DeveloperError_default.throwInstantiationError;
MaterialProperty.prototype.getValue = DeveloperError_default.throwInstantiationError;
MaterialProperty.prototype.equals = DeveloperError_default.throwInstantiationError;
var timeScratch2 = new JulianDate_default();
MaterialProperty.getValue = function(time, materialProperty, material) {
let type;
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch2);
}
if (defined_default(materialProperty)) {
type = materialProperty.getType(time);
if (defined_default(type)) {
if (!defined_default(material) || material.type !== type) {
material = Material_default.fromType(type);
}
materialProperty.getValue(time, material.uniforms);
return material;
}
}
if (!defined_default(material) || material.type !== Material_default.ColorType) {
material = Material_default.fromType(Material_default.ColorType);
}
Color_default.clone(Color_default.WHITE, material.uniforms.color);
return material;
};
var MaterialProperty_default = MaterialProperty;
// packages/engine/Source/DataSources/DynamicGeometryUpdater.js
function DynamicGeometryUpdater(geometryUpdater, primitives, orderedGroundPrimitives) {
Check_default.defined("geometryUpdater", geometryUpdater);
Check_default.defined("primitives", primitives);
Check_default.defined("orderedGroundPrimitives", orderedGroundPrimitives);
this._primitives = primitives;
this._orderedGroundPrimitives = orderedGroundPrimitives;
this._primitive = void 0;
this._outlinePrimitive = void 0;
this._geometryUpdater = geometryUpdater;
this._options = geometryUpdater._options;
this._entity = geometryUpdater._entity;
this._material = void 0;
}
DynamicGeometryUpdater.prototype._isHidden = function(entity, geometry, time) {
return !entity.isShowing || !entity.isAvailable(time) || !Property_default.getValueOrDefault(geometry.show, time, true);
};
DynamicGeometryUpdater.prototype._setOptions = DeveloperError_default.throwInstantiationError;
DynamicGeometryUpdater.prototype.update = function(time) {
Check_default.defined("time", time);
const geometryUpdater = this._geometryUpdater;
const onTerrain = geometryUpdater._onTerrain;
const primitives = this._primitives;
const orderedGroundPrimitives = this._orderedGroundPrimitives;
if (onTerrain) {
orderedGroundPrimitives.remove(this._primitive);
} else {
primitives.removeAndDestroy(this._primitive);
primitives.removeAndDestroy(this._outlinePrimitive);
this._outlinePrimitive = void 0;
}
this._primitive = void 0;
const entity = this._entity;
const geometry = entity[this._geometryUpdater._geometryPropertyName];
this._setOptions(entity, geometry, time);
if (this._isHidden(entity, geometry, time)) {
return;
}
const shadows = this._geometryUpdater.shadowsProperty.getValue(time);
const options = this._options;
if (!defined_default(geometry.fill) || geometry.fill.getValue(time)) {
const fillMaterialProperty = geometryUpdater.fillMaterialProperty;
const isColorAppearance = fillMaterialProperty instanceof ColorMaterialProperty_default;
let appearance;
const closed = geometryUpdater._getIsClosed(options);
if (isColorAppearance) {
appearance = new PerInstanceColorAppearance_default({
closed,
flat: onTerrain && !geometryUpdater._supportsMaterialsforEntitiesOnTerrain
});
} else {
const material = MaterialProperty_default.getValue(
time,
fillMaterialProperty,
this._material
);
this._material = material;
appearance = new MaterialAppearance_default({
material,
translucent: material.isTranslucent(),
closed
});
}
if (onTerrain) {
options.vertexFormat = PerInstanceColorAppearance_default.VERTEX_FORMAT;
this._primitive = orderedGroundPrimitives.add(
new GroundPrimitive_default({
geometryInstances: this._geometryUpdater.createFillGeometryInstance(time),
appearance,
asynchronous: false,
shadows,
classificationType: this._geometryUpdater.classificationTypeProperty.getValue(time)
}),
Property_default.getValueOrUndefined(this._geometryUpdater.zIndex, time)
);
} else {
options.vertexFormat = appearance.vertexFormat;
const fillInstance = this._geometryUpdater.createFillGeometryInstance(time);
if (isColorAppearance) {
appearance.translucent = fillInstance.attributes.color.value[3] !== 255;
}
this._primitive = primitives.add(
new Primitive_default({
geometryInstances: fillInstance,
appearance,
asynchronous: false,
shadows
})
);
}
}
if (!onTerrain && defined_default(geometry.outline) && geometry.outline.getValue(time)) {
const outlineInstance = this._geometryUpdater.createOutlineGeometryInstance(time);
const outlineWidth = Property_default.getValueOrDefault(
geometry.outlineWidth,
time,
1
);
this._outlinePrimitive = primitives.add(
new Primitive_default({
geometryInstances: outlineInstance,
appearance: new PerInstanceColorAppearance_default({
flat: true,
translucent: outlineInstance.attributes.color.value[3] !== 255,
renderState: {
lineWidth: geometryUpdater._scene.clampLineWidth(outlineWidth)
}
}),
asynchronous: false,
shadows
})
);
}
};
DynamicGeometryUpdater.prototype.getBoundingSphere = function(result) {
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
const entity = this._entity;
const primitive = this._primitive;
const outlinePrimitive = this._outlinePrimitive;
let attributes;
if (defined_default(primitive) && primitive.show && primitive.ready) {
attributes = primitive.getGeometryInstanceAttributes(entity);
if (defined_default(attributes) && defined_default(attributes.boundingSphere)) {
BoundingSphere_default.clone(attributes.boundingSphere, result);
return BoundingSphereState_default.DONE;
}
}
if (defined_default(outlinePrimitive) && outlinePrimitive.show && outlinePrimitive.ready) {
attributes = outlinePrimitive.getGeometryInstanceAttributes(entity);
if (defined_default(attributes) && defined_default(attributes.boundingSphere)) {
BoundingSphere_default.clone(attributes.boundingSphere, result);
return BoundingSphereState_default.DONE;
}
}
if (defined_default(primitive) && !primitive.ready || defined_default(outlinePrimitive) && !outlinePrimitive.ready) {
return BoundingSphereState_default.PENDING;
}
return BoundingSphereState_default.FAILED;
};
DynamicGeometryUpdater.prototype.isDestroyed = function() {
return false;
};
DynamicGeometryUpdater.prototype.destroy = function() {
const primitives = this._primitives;
const orderedGroundPrimitives = this._orderedGroundPrimitives;
if (this._geometryUpdater._onTerrain) {
orderedGroundPrimitives.remove(this._primitive);
} else {
primitives.removeAndDestroy(this._primitive);
}
primitives.removeAndDestroy(this._outlinePrimitive);
destroyObject_default(this);
};
var DynamicGeometryUpdater_default = DynamicGeometryUpdater;
// packages/engine/Source/DataSources/GeometryUpdater.js
var import_InlineWorkers418 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/oneTimeWarning.js
var import_InlineWorkers373 = __toESM(require_InlineWorkers(), 1);
var warnings = {};
function oneTimeWarning(identifier, message) {
if (!defined_default(identifier)) {
throw new DeveloperError_default("identifier is required.");
}
if (!defined_default(warnings[identifier])) {
warnings[identifier] = true;
console.warn(message ?? identifier);
}
}
oneTimeWarning.geometryOutlines = "Entity geometry outlines are unsupported on terrain. Outlines will be disabled. To enable outlines, disable geometry terrain clamping by explicitly setting height to 0.";
oneTimeWarning.geometryZIndex = "Entity geometry with zIndex are unsupported when height or extrudedHeight are defined. zIndex will be ignored";
oneTimeWarning.geometryHeightReference = "Entity corridor, ellipse, polygon or rectangle with heightReference must also have a defined height. heightReference will be ignored";
oneTimeWarning.geometryExtrudedHeightReference = "Entity corridor, ellipse, polygon or rectangle with extrudedHeightReference must also have a defined extrudedHeight. extrudedHeightReference will be ignored";
var oneTimeWarning_default = oneTimeWarning;
// packages/engine/Source/DataSources/Entity.js
var import_InlineWorkers417 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/TrackingReferenceFrame.js
var import_InlineWorkers374 = __toESM(require_InlineWorkers(), 1);
var TrackingReferenceFrame = {
/**
* Auto-detect algorithm. The reference frame used to track the Entity will
* be automatically selected based on its trajectory: near-surface slow moving
* objects will be tracked in the entity's local east-north-up reference
* frame, while faster objects like satellites will use VVLH (Vehicle Velocity,
* Local Horizontal).
*
* @type {number}
* @constant
*/
AUTODETECT: 0,
/**
* The entity's local East-North-Up reference frame.
*
* @type {number}
* @constant
*/
ENU: 1,
/**
* The entity's inertial reference frame. If entity has no defined orientation
* property, it falls back to auto-detect algorithm.
*
* @type {number}
* @constant
*/
INERTIAL: 2,
/**
* The entity's inertial reference frame with orientation fixed to its
* {@link VelocityOrientationProperty}, ignoring its own orientation.
*
* @type {number}
* @constant
*/
VELOCITY: 3
};
var TrackingReferenceFrame_default = Object.freeze(TrackingReferenceFrame);
// packages/engine/Source/Scene/GroundPolylinePrimitive.js
var import_InlineWorkers390 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/GroundPolylineGeometry.js
var import_InlineWorkers379 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/ArcType.js
var import_InlineWorkers375 = __toESM(require_InlineWorkers(), 1);
var ArcType = {
/**
* Straight line that does not conform to the surface of the ellipsoid.
*
* @type {number}
* @constant
*/
NONE: 0,
/**
* Follow geodesic path.
*
* @type {number}
* @constant
*/
GEODESIC: 1,
/**
* Follow rhumb or loxodrome path.
*
* @type {number}
* @constant
*/
RHUMB: 2
};
var ArcType_default = Object.freeze(ArcType);
// packages/engine/Source/Core/arrayRemoveDuplicates.js
var import_InlineWorkers376 = __toESM(require_InlineWorkers(), 1);
var removeDuplicatesEpsilon = Math_default.EPSILON10;
function arrayRemoveDuplicates(values, equalsEpsilon, wrapAround, removedIndices) {
Check_default.defined("equalsEpsilon", equalsEpsilon);
if (!defined_default(values)) {
return void 0;
}
wrapAround = wrapAround ?? false;
const storeRemovedIndices = defined_default(removedIndices);
const length2 = values.length;
if (length2 < 2) {
return values;
}
let i;
let v02 = values[0];
let v12;
let cleanedValues;
let lastCleanIndex = 0;
let removedIndexLCI = -1;
for (i = 1; i < length2; ++i) {
v12 = values[i];
if (equalsEpsilon(v02, v12, removeDuplicatesEpsilon)) {
if (!defined_default(cleanedValues)) {
cleanedValues = values.slice(0, i);
lastCleanIndex = i - 1;
removedIndexLCI = 0;
}
if (storeRemovedIndices) {
removedIndices.push(i);
}
} else {
if (defined_default(cleanedValues)) {
cleanedValues.push(v12);
lastCleanIndex = i;
if (storeRemovedIndices) {
removedIndexLCI = removedIndices.length;
}
}
v02 = v12;
}
}
if (wrapAround && equalsEpsilon(values[0], values[length2 - 1], removeDuplicatesEpsilon)) {
if (storeRemovedIndices) {
if (defined_default(cleanedValues)) {
removedIndices.splice(removedIndexLCI, 0, lastCleanIndex);
} else {
removedIndices.push(length2 - 1);
}
}
if (defined_default(cleanedValues)) {
cleanedValues.length -= 1;
} else {
cleanedValues = values.slice(0, -1);
}
}
return defined_default(cleanedValues) ? cleanedValues : values;
}
var arrayRemoveDuplicates_default = arrayRemoveDuplicates;
// packages/engine/Source/Core/EllipsoidGeodesic.js
var import_InlineWorkers377 = __toESM(require_InlineWorkers(), 1);
function setConstants(ellipsoidGeodesic2) {
const uSquared = ellipsoidGeodesic2._uSquared;
const a3 = ellipsoidGeodesic2._ellipsoid.maximumRadius;
const b = ellipsoidGeodesic2._ellipsoid.minimumRadius;
const f = (a3 - b) / a3;
const cosineHeading = Math.cos(ellipsoidGeodesic2._startHeading);
const sineHeading = Math.sin(ellipsoidGeodesic2._startHeading);
const tanU = (1 - f) * Math.tan(ellipsoidGeodesic2._start.latitude);
const cosineU = 1 / Math.sqrt(1 + tanU * tanU);
const sineU = cosineU * tanU;
const sigma = Math.atan2(tanU, cosineHeading);
const sineAlpha = cosineU * sineHeading;
const sineSquaredAlpha = sineAlpha * sineAlpha;
const cosineSquaredAlpha = 1 - sineSquaredAlpha;
const cosineAlpha = Math.sqrt(cosineSquaredAlpha);
const u2Over4 = uSquared / 4;
const u4Over16 = u2Over4 * u2Over4;
const u6Over64 = u4Over16 * u2Over4;
const u8Over256 = u4Over16 * u4Over16;
const a0 = 1 + u2Over4 - 3 * u4Over16 / 4 + 5 * u6Over64 / 4 - 175 * u8Over256 / 64;
const a1 = 1 - u2Over4 + 15 * u4Over16 / 8 - 35 * u6Over64 / 8;
const a22 = 1 - 3 * u2Over4 + 35 * u4Over16 / 4;
const a32 = 1 - 5 * u2Over4;
const distanceRatio = a0 * sigma - a1 * Math.sin(2 * sigma) * u2Over4 / 2 - a22 * Math.sin(4 * sigma) * u4Over16 / 16 - a32 * Math.sin(6 * sigma) * u6Over64 / 48 - Math.sin(8 * sigma) * 5 * u8Over256 / 512;
const constants = ellipsoidGeodesic2._constants;
constants.a = a3;
constants.b = b;
constants.f = f;
constants.cosineHeading = cosineHeading;
constants.sineHeading = sineHeading;
constants.tanU = tanU;
constants.cosineU = cosineU;
constants.sineU = sineU;
constants.sigma = sigma;
constants.sineAlpha = sineAlpha;
constants.sineSquaredAlpha = sineSquaredAlpha;
constants.cosineSquaredAlpha = cosineSquaredAlpha;
constants.cosineAlpha = cosineAlpha;
constants.u2Over4 = u2Over4;
constants.u4Over16 = u4Over16;
constants.u6Over64 = u6Over64;
constants.u8Over256 = u8Over256;
constants.a0 = a0;
constants.a1 = a1;
constants.a2 = a22;
constants.a3 = a32;
constants.distanceRatio = distanceRatio;
}
function computeC(f, cosineSquaredAlpha) {
return f * cosineSquaredAlpha * (4 + f * (4 - 3 * cosineSquaredAlpha)) / 16;
}
function computeDeltaLambda(f, sineAlpha, cosineSquaredAlpha, sigma, sineSigma, cosineSigma, cosineTwiceSigmaMidpoint) {
const C = computeC(f, cosineSquaredAlpha);
return (1 - C) * f * sineAlpha * (sigma + C * sineSigma * (cosineTwiceSigmaMidpoint + C * cosineSigma * (2 * cosineTwiceSigmaMidpoint * cosineTwiceSigmaMidpoint - 1)));
}
function vincentyInverseFormula(ellipsoidGeodesic2, major, minor, firstLongitude, firstLatitude, secondLongitude, secondLatitude) {
const eff = (major - minor) / major;
const l = secondLongitude - firstLongitude;
const u12 = Math.atan((1 - eff) * Math.tan(firstLatitude));
const u22 = Math.atan((1 - eff) * Math.tan(secondLatitude));
const cosineU1 = Math.cos(u12);
const sineU1 = Math.sin(u12);
const cosineU2 = Math.cos(u22);
const sineU2 = Math.sin(u22);
const cc = cosineU1 * cosineU2;
const cs = cosineU1 * sineU2;
const ss = sineU1 * sineU2;
const sc = sineU1 * cosineU2;
let lambda = l;
let lambdaDot = Math_default.TWO_PI;
let cosineLambda = Math.cos(lambda);
let sineLambda = Math.sin(lambda);
let sigma;
let cosineSigma;
let sineSigma;
let cosineSquaredAlpha;
let cosineTwiceSigmaMidpoint;
do {
cosineLambda = Math.cos(lambda);
sineLambda = Math.sin(lambda);
const temp = cs - sc * cosineLambda;
sineSigma = Math.sqrt(
cosineU2 * cosineU2 * sineLambda * sineLambda + temp * temp
);
cosineSigma = ss + cc * cosineLambda;
sigma = Math.atan2(sineSigma, cosineSigma);
let sineAlpha;
if (sineSigma === 0) {
sineAlpha = 0;
cosineSquaredAlpha = 1;
} else {
sineAlpha = cc * sineLambda / sineSigma;
cosineSquaredAlpha = 1 - sineAlpha * sineAlpha;
}
lambdaDot = lambda;
cosineTwiceSigmaMidpoint = cosineSigma - 2 * ss / cosineSquaredAlpha;
if (!isFinite(cosineTwiceSigmaMidpoint)) {
cosineTwiceSigmaMidpoint = 0;
}
lambda = l + computeDeltaLambda(
eff,
sineAlpha,
cosineSquaredAlpha,
sigma,
sineSigma,
cosineSigma,
cosineTwiceSigmaMidpoint
);
} while (Math.abs(lambda - lambdaDot) > Math_default.EPSILON12);
const uSquared = cosineSquaredAlpha * (major * major - minor * minor) / (minor * minor);
const A = 1 + uSquared * (4096 + uSquared * (uSquared * (320 - 175 * uSquared) - 768)) / 16384;
const B = uSquared * (256 + uSquared * (uSquared * (74 - 47 * uSquared) - 128)) / 1024;
const cosineSquaredTwiceSigmaMidpoint = cosineTwiceSigmaMidpoint * cosineTwiceSigmaMidpoint;
const deltaSigma = B * sineSigma * (cosineTwiceSigmaMidpoint + B * (cosineSigma * (2 * cosineSquaredTwiceSigmaMidpoint - 1) - B * cosineTwiceSigmaMidpoint * (4 * sineSigma * sineSigma - 3) * (4 * cosineSquaredTwiceSigmaMidpoint - 3) / 6) / 4);
const distance2 = minor * A * (sigma - deltaSigma);
const startHeading = Math.atan2(
cosineU2 * sineLambda,
cs - sc * cosineLambda
);
const endHeading = Math.atan2(cosineU1 * sineLambda, cs * cosineLambda - sc);
ellipsoidGeodesic2._distance = distance2;
ellipsoidGeodesic2._startHeading = startHeading;
ellipsoidGeodesic2._endHeading = endHeading;
ellipsoidGeodesic2._uSquared = uSquared;
}
var scratchCart1 = new Cartesian3_default();
var scratchCart2 = new Cartesian3_default();
function computeProperties(ellipsoidGeodesic2, start, end, ellipsoid) {
const firstCartesian = Cartesian3_default.normalize(
ellipsoid.cartographicToCartesian(start, scratchCart2),
scratchCart1
);
const lastCartesian = Cartesian3_default.normalize(
ellipsoid.cartographicToCartesian(end, scratchCart2),
scratchCart2
);
Check_default.typeOf.number.greaterThanOrEquals(
"value",
Math.abs(
Math.abs(Cartesian3_default.angleBetween(firstCartesian, lastCartesian)) - Math.PI
),
0.0125
);
vincentyInverseFormula(
ellipsoidGeodesic2,
ellipsoid.maximumRadius,
ellipsoid.minimumRadius,
start.longitude,
start.latitude,
end.longitude,
end.latitude
);
ellipsoidGeodesic2._start = Cartographic_default.clone(
start,
ellipsoidGeodesic2._start
);
ellipsoidGeodesic2._end = Cartographic_default.clone(end, ellipsoidGeodesic2._end);
ellipsoidGeodesic2._start.height = 0;
ellipsoidGeodesic2._end.height = 0;
setConstants(ellipsoidGeodesic2);
}
function EllipsoidGeodesic(start, end, ellipsoid) {
const e = ellipsoid ?? Ellipsoid_default.default;
this._ellipsoid = e;
this._start = new Cartographic_default();
this._end = new Cartographic_default();
this._constants = {};
this._startHeading = void 0;
this._endHeading = void 0;
this._distance = void 0;
this._uSquared = void 0;
if (defined_default(start) && defined_default(end)) {
computeProperties(this, start, end, e);
}
}
Object.defineProperties(EllipsoidGeodesic.prototype, {
/**
* Gets the ellipsoid.
* @memberof EllipsoidGeodesic.prototype
* @type {Ellipsoid}
* @readonly
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
},
/**
* Gets the surface distance between the start and end point
* @memberof EllipsoidGeodesic.prototype
* @type {number}
* @readonly
*/
surfaceDistance: {
get: function() {
Check_default.defined("distance", this._distance);
return this._distance;
}
},
/**
* Gets the initial planetodetic point on the path.
* @memberof EllipsoidGeodesic.prototype
* @type {Cartographic}
* @readonly
*/
start: {
get: function() {
return this._start;
}
},
/**
* Gets the final planetodetic point on the path.
* @memberof EllipsoidGeodesic.prototype
* @type {Cartographic}
* @readonly
*/
end: {
get: function() {
return this._end;
}
},
/**
* Gets the heading at the initial point.
* @memberof EllipsoidGeodesic.prototype
* @type {number}
* @readonly
*/
startHeading: {
get: function() {
Check_default.defined("distance", this._distance);
return this._startHeading;
}
},
/**
* Gets the heading at the final point.
* @memberof EllipsoidGeodesic.prototype
* @type {number}
* @readonly
*/
endHeading: {
get: function() {
Check_default.defined("distance", this._distance);
return this._endHeading;
}
}
});
EllipsoidGeodesic.prototype.setEndPoints = function(start, end) {
Check_default.defined("start", start);
Check_default.defined("end", end);
computeProperties(this, start, end, this._ellipsoid);
};
EllipsoidGeodesic.prototype.interpolateUsingFraction = function(fraction, result) {
return this.interpolateUsingSurfaceDistance(
this._distance * fraction,
result
);
};
EllipsoidGeodesic.prototype.interpolateUsingSurfaceDistance = function(distance2, result) {
Check_default.defined("distance", this._distance);
const constants = this._constants;
const s = constants.distanceRatio + distance2 / constants.b;
const cosine2S = Math.cos(2 * s);
const cosine4S = Math.cos(4 * s);
const cosine6S = Math.cos(6 * s);
const sine2S = Math.sin(2 * s);
const sine4S = Math.sin(4 * s);
const sine6S = Math.sin(6 * s);
const sine8S = Math.sin(8 * s);
const s2 = s * s;
const s3 = s * s2;
const u8Over256 = constants.u8Over256;
const u2Over4 = constants.u2Over4;
const u6Over64 = constants.u6Over64;
const u4Over16 = constants.u4Over16;
let sigma = 2 * s3 * u8Over256 * cosine2S / 3 + s * (1 - u2Over4 + 7 * u4Over16 / 4 - 15 * u6Over64 / 4 + 579 * u8Over256 / 64 - (u4Over16 - 15 * u6Over64 / 4 + 187 * u8Over256 / 16) * cosine2S - (5 * u6Over64 / 4 - 115 * u8Over256 / 16) * cosine4S - 29 * u8Over256 * cosine6S / 16) + (u2Over4 / 2 - u4Over16 + 71 * u6Over64 / 32 - 85 * u8Over256 / 16) * sine2S + (5 * u4Over16 / 16 - 5 * u6Over64 / 4 + 383 * u8Over256 / 96) * sine4S - s2 * ((u6Over64 - 11 * u8Over256 / 2) * sine2S + 5 * u8Over256 * sine4S / 2) + (29 * u6Over64 / 96 - 29 * u8Over256 / 16) * sine6S + 539 * u8Over256 * sine8S / 1536;
const theta = Math.asin(Math.sin(sigma) * constants.cosineAlpha);
const latitude = Math.atan(constants.a / constants.b * Math.tan(theta));
sigma = sigma - constants.sigma;
const cosineTwiceSigmaMidpoint = Math.cos(2 * constants.sigma + sigma);
const sineSigma = Math.sin(sigma);
const cosineSigma = Math.cos(sigma);
const cc = constants.cosineU * cosineSigma;
const ss = constants.sineU * sineSigma;
const lambda = Math.atan2(
sineSigma * constants.sineHeading,
cc - ss * constants.cosineHeading
);
const l = lambda - computeDeltaLambda(
constants.f,
constants.sineAlpha,
constants.cosineSquaredAlpha,
sigma,
sineSigma,
cosineSigma,
cosineTwiceSigmaMidpoint
);
if (defined_default(result)) {
result.longitude = this._start.longitude + l;
result.latitude = latitude;
result.height = 0;
return result;
}
return new Cartographic_default(this._start.longitude + l, latitude, 0);
};
var EllipsoidGeodesic_default = EllipsoidGeodesic;
// packages/engine/Source/Core/EllipsoidRhumbLine.js
var import_InlineWorkers378 = __toESM(require_InlineWorkers(), 1);
function calculateM(ellipticity, major, latitude) {
if (ellipticity === 0) {
return major * latitude;
}
const e2 = ellipticity * ellipticity;
const e4 = e2 * e2;
const e6 = e4 * e2;
const e8 = e6 * e2;
const e10 = e8 * e2;
const e12 = e10 * e2;
const phi = latitude;
const sin2Phi = Math.sin(2 * phi);
const sin4Phi = Math.sin(4 * phi);
const sin6Phi = Math.sin(6 * phi);
const sin8Phi = Math.sin(8 * phi);
const sin10Phi = Math.sin(10 * phi);
const sin12Phi = Math.sin(12 * phi);
return major * ((1 - e2 / 4 - 3 * e4 / 64 - 5 * e6 / 256 - 175 * e8 / 16384 - 441 * e10 / 65536 - 4851 * e12 / 1048576) * phi - (3 * e2 / 8 + 3 * e4 / 32 + 45 * e6 / 1024 + 105 * e8 / 4096 + 2205 * e10 / 131072 + 6237 * e12 / 524288) * sin2Phi + (15 * e4 / 256 + 45 * e6 / 1024 + 525 * e8 / 16384 + 1575 * e10 / 65536 + 155925 * e12 / 8388608) * sin4Phi - (35 * e6 / 3072 + 175 * e8 / 12288 + 3675 * e10 / 262144 + 13475 * e12 / 1048576) * sin6Phi + (315 * e8 / 131072 + 2205 * e10 / 524288 + 43659 * e12 / 8388608) * sin8Phi - (693 * e10 / 1310720 + 6237 * e12 / 5242880) * sin10Phi + 1001 * e12 / 8388608 * sin12Phi);
}
function calculateInverseM(M, ellipticity, major) {
const d = M / major;
if (ellipticity === 0) {
return d;
}
const d2 = d * d;
const d3 = d2 * d;
const d4 = d3 * d;
const e = ellipticity;
const e2 = e * e;
const e4 = e2 * e2;
const e6 = e4 * e2;
const e8 = e6 * e2;
const e10 = e8 * e2;
const e12 = e10 * e2;
const sin2D = Math.sin(2 * d);
const cos2D = Math.cos(2 * d);
const sin4D = Math.sin(4 * d);
const cos4D = Math.cos(4 * d);
const sin6D = Math.sin(6 * d);
const cos6D = Math.cos(6 * d);
const sin8D = Math.sin(8 * d);
const cos8D = Math.cos(8 * d);
const sin10D = Math.sin(10 * d);
const cos10D = Math.cos(10 * d);
const sin12D = Math.sin(12 * d);
return d + d * e2 / 4 + 7 * d * e4 / 64 + 15 * d * e6 / 256 + 579 * d * e8 / 16384 + 1515 * d * e10 / 65536 + 16837 * d * e12 / 1048576 + (3 * d * e4 / 16 + 45 * d * e6 / 256 - d * (32 * d2 - 561) * e8 / 4096 - d * (232 * d2 - 1677) * e10 / 16384 + d * (399985 - 90560 * d2 + 512 * d4) * e12 / 5242880) * cos2D + (21 * d * e6 / 256 + 483 * d * e8 / 4096 - d * (224 * d2 - 1969) * e10 / 16384 - d * (33152 * d2 - 112599) * e12 / 1048576) * cos4D + (151 * d * e8 / 4096 + 4681 * d * e10 / 65536 + 1479 * d * e12 / 16384 - 453 * d3 * e12 / 32768) * cos6D + (1097 * d * e10 / 65536 + 42783 * d * e12 / 1048576) * cos8D + 8011 * d * e12 / 1048576 * cos10D + (3 * e2 / 8 + 3 * e4 / 16 + 213 * e6 / 2048 - 3 * d2 * e6 / 64 + 255 * e8 / 4096 - 33 * d2 * e8 / 512 + 20861 * e10 / 524288 - 33 * d2 * e10 / 512 + d4 * e10 / 1024 + 28273 * e12 / 1048576 - 471 * d2 * e12 / 8192 + 9 * d4 * e12 / 4096) * sin2D + (21 * e4 / 256 + 21 * e6 / 256 + 533 * e8 / 8192 - 21 * d2 * e8 / 512 + 197 * e10 / 4096 - 315 * d2 * e10 / 4096 + 584039 * e12 / 16777216 - 12517 * d2 * e12 / 131072 + 7 * d4 * e12 / 2048) * sin4D + (151 * e6 / 6144 + 151 * e8 / 4096 + 5019 * e10 / 131072 - 453 * d2 * e10 / 16384 + 26965 * e12 / 786432 - 8607 * d2 * e12 / 131072) * sin6D + (1097 * e8 / 131072 + 1097 * e10 / 65536 + 225797 * e12 / 10485760 - 1097 * d2 * e12 / 65536) * sin8D + (8011 * e10 / 2621440 + 8011 * e12 / 1048576) * sin10D + 293393 * e12 / 251658240 * sin12D;
}
function calculateSigma(ellipticity, latitude) {
if (ellipticity === 0) {
return Math.log(Math.tan(0.5 * (Math_default.PI_OVER_TWO + latitude)));
}
const eSinL = ellipticity * Math.sin(latitude);
return Math.log(Math.tan(0.5 * (Math_default.PI_OVER_TWO + latitude))) - ellipticity / 2 * Math.log((1 + eSinL) / (1 - eSinL));
}
function calculateHeading(ellipsoidRhumbLine, firstLongitude, firstLatitude, secondLongitude, secondLatitude) {
const sigma1 = calculateSigma(ellipsoidRhumbLine._ellipticity, firstLatitude);
const sigma2 = calculateSigma(
ellipsoidRhumbLine._ellipticity,
secondLatitude
);
return Math.atan2(
Math_default.negativePiToPi(secondLongitude - firstLongitude),
sigma2 - sigma1
);
}
function calculateArcLength(ellipsoidRhumbLine, major, minor, firstLongitude, firstLatitude, secondLongitude, secondLatitude) {
const heading = ellipsoidRhumbLine._heading;
const deltaLongitude = secondLongitude - firstLongitude;
let distance2 = 0;
if (Math_default.equalsEpsilon(
Math.abs(heading),
Math_default.PI_OVER_TWO,
Math_default.EPSILON8
)) {
if (major === minor) {
distance2 = major * Math.cos(firstLatitude) * Math_default.negativePiToPi(deltaLongitude);
} else {
const sinPhi = Math.sin(firstLatitude);
distance2 = major * Math.cos(firstLatitude) * Math_default.negativePiToPi(deltaLongitude) / Math.sqrt(1 - ellipsoidRhumbLine._ellipticitySquared * sinPhi * sinPhi);
}
} else {
const M1 = calculateM(
ellipsoidRhumbLine._ellipticity,
major,
firstLatitude
);
const M2 = calculateM(
ellipsoidRhumbLine._ellipticity,
major,
secondLatitude
);
distance2 = (M2 - M1) / Math.cos(heading);
}
return Math.abs(distance2);
}
var scratchCart12 = new Cartesian3_default();
var scratchCart22 = new Cartesian3_default();
function computeProperties2(ellipsoidRhumbLine, start, end, ellipsoid) {
const firstCartesian = Cartesian3_default.normalize(
ellipsoid.cartographicToCartesian(start, scratchCart22),
scratchCart12
);
const lastCartesian = Cartesian3_default.normalize(
ellipsoid.cartographicToCartesian(end, scratchCart22),
scratchCart22
);
Check_default.typeOf.number.greaterThanOrEquals(
"value",
Math.abs(
Math.abs(Cartesian3_default.angleBetween(firstCartesian, lastCartesian)) - Math.PI
),
0.0125
);
const major = ellipsoid.maximumRadius;
const minor = ellipsoid.minimumRadius;
const majorSquared = major * major;
const minorSquared = minor * minor;
ellipsoidRhumbLine._ellipticitySquared = (majorSquared - minorSquared) / majorSquared;
ellipsoidRhumbLine._ellipticity = Math.sqrt(
ellipsoidRhumbLine._ellipticitySquared
);
ellipsoidRhumbLine._start = Cartographic_default.clone(
start,
ellipsoidRhumbLine._start
);
ellipsoidRhumbLine._start.height = 0;
ellipsoidRhumbLine._end = Cartographic_default.clone(end, ellipsoidRhumbLine._end);
ellipsoidRhumbLine._end.height = 0;
ellipsoidRhumbLine._heading = calculateHeading(
ellipsoidRhumbLine,
start.longitude,
start.latitude,
end.longitude,
end.latitude
);
ellipsoidRhumbLine._distance = calculateArcLength(
ellipsoidRhumbLine,
ellipsoid.maximumRadius,
ellipsoid.minimumRadius,
start.longitude,
start.latitude,
end.longitude,
end.latitude
);
}
function interpolateUsingSurfaceDistance(start, heading, distance2, major, ellipticity, result) {
if (distance2 === 0) {
return Cartographic_default.clone(start, result);
}
const ellipticitySquared = ellipticity * ellipticity;
let longitude;
let latitude;
let deltaLongitude;
if (Math.abs(Math_default.PI_OVER_TWO - Math.abs(heading)) > Math_default.EPSILON8) {
const M1 = calculateM(ellipticity, major, start.latitude);
const deltaM = distance2 * Math.cos(heading);
const M2 = M1 + deltaM;
latitude = calculateInverseM(M2, ellipticity, major);
if (Math.abs(heading) < Math_default.EPSILON10) {
longitude = Math_default.negativePiToPi(start.longitude);
} else {
const sigma1 = calculateSigma(ellipticity, start.latitude);
const sigma2 = calculateSigma(ellipticity, latitude);
deltaLongitude = Math.tan(heading) * (sigma2 - sigma1);
longitude = Math_default.negativePiToPi(start.longitude + deltaLongitude);
}
} else {
latitude = start.latitude;
let localRad;
if (ellipticity === 0) {
localRad = major * Math.cos(start.latitude);
} else {
const sinPhi = Math.sin(start.latitude);
localRad = major * Math.cos(start.latitude) / Math.sqrt(1 - ellipticitySquared * sinPhi * sinPhi);
}
deltaLongitude = distance2 / localRad;
if (heading > 0) {
longitude = Math_default.negativePiToPi(start.longitude + deltaLongitude);
} else {
longitude = Math_default.negativePiToPi(start.longitude - deltaLongitude);
}
}
if (defined_default(result)) {
result.longitude = longitude;
result.latitude = latitude;
result.height = 0;
return result;
}
return new Cartographic_default(longitude, latitude, 0);
}
function EllipsoidRhumbLine(start, end, ellipsoid) {
const e = ellipsoid ?? Ellipsoid_default.default;
this._ellipsoid = e;
this._start = new Cartographic_default();
this._end = new Cartographic_default();
this._heading = void 0;
this._distance = void 0;
this._ellipticity = void 0;
this._ellipticitySquared = void 0;
if (defined_default(start) && defined_default(end)) {
computeProperties2(this, start, end, e);
}
}
Object.defineProperties(EllipsoidRhumbLine.prototype, {
/**
* Gets the ellipsoid.
* @memberof EllipsoidRhumbLine.prototype
* @type {Ellipsoid}
* @readonly
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
},
/**
* Gets the surface distance between the start and end point
* @memberof EllipsoidRhumbLine.prototype
* @type {number}
* @readonly
*/
surfaceDistance: {
get: function() {
Check_default.defined("distance", this._distance);
return this._distance;
}
},
/**
* Gets the initial planetodetic point on the path.
* @memberof EllipsoidRhumbLine.prototype
* @type {Cartographic}
* @readonly
*/
start: {
get: function() {
return this._start;
}
},
/**
* Gets the final planetodetic point on the path.
* @memberof EllipsoidRhumbLine.prototype
* @type {Cartographic}
* @readonly
*/
end: {
get: function() {
return this._end;
}
},
/**
* Gets the heading from the start point to the end point.
* @memberof EllipsoidRhumbLine.prototype
* @type {number}
* @readonly
*/
heading: {
get: function() {
Check_default.defined("distance", this._distance);
return this._heading;
}
}
});
EllipsoidRhumbLine.fromStartHeadingDistance = function(start, heading, distance2, ellipsoid, result) {
Check_default.defined("start", start);
Check_default.defined("heading", heading);
Check_default.defined("distance", distance2);
Check_default.typeOf.number.greaterThan("distance", distance2, 0);
const e = ellipsoid ?? Ellipsoid_default.default;
const major = e.maximumRadius;
const minor = e.minimumRadius;
const majorSquared = major * major;
const minorSquared = minor * minor;
const ellipticity = Math.sqrt((majorSquared - minorSquared) / majorSquared);
heading = Math_default.negativePiToPi(heading);
const end = interpolateUsingSurfaceDistance(
start,
heading,
distance2,
e.maximumRadius,
ellipticity
);
if (!defined_default(result) || defined_default(ellipsoid) && !ellipsoid.equals(result.ellipsoid)) {
return new EllipsoidRhumbLine(start, end, e);
}
result.setEndPoints(start, end);
return result;
};
EllipsoidRhumbLine.prototype.setEndPoints = function(start, end) {
Check_default.defined("start", start);
Check_default.defined("end", end);
computeProperties2(this, start, end, this._ellipsoid);
};
EllipsoidRhumbLine.prototype.interpolateUsingFraction = function(fraction, result) {
return this.interpolateUsingSurfaceDistance(
fraction * this._distance,
result
);
};
EllipsoidRhumbLine.prototype.interpolateUsingSurfaceDistance = function(distance2, result) {
Check_default.typeOf.number("distance", distance2);
if (!defined_default(this._distance) || this._distance === 0) {
throw new DeveloperError_default(
"EllipsoidRhumbLine must have distinct start and end set."
);
}
return interpolateUsingSurfaceDistance(
this._start,
this._heading,
distance2,
this._ellipsoid.maximumRadius,
this._ellipticity,
result
);
};
EllipsoidRhumbLine.prototype.findIntersectionWithLongitude = function(intersectionLongitude, result) {
Check_default.typeOf.number("intersectionLongitude", intersectionLongitude);
if (!defined_default(this._distance) || this._distance === 0) {
throw new DeveloperError_default(
"EllipsoidRhumbLine must have distinct start and end set."
);
}
const ellipticity = this._ellipticity;
const heading = this._heading;
const absHeading = Math.abs(heading);
const start = this._start;
intersectionLongitude = Math_default.negativePiToPi(intersectionLongitude);
if (Math_default.equalsEpsilon(
Math.abs(intersectionLongitude),
Math.PI,
Math_default.EPSILON14
)) {
intersectionLongitude = Math_default.sign(start.longitude) * Math.PI;
}
if (!defined_default(result)) {
result = new Cartographic_default();
}
if (Math.abs(Math_default.PI_OVER_TWO - absHeading) <= Math_default.EPSILON8) {
result.longitude = intersectionLongitude;
result.latitude = start.latitude;
result.height = 0;
return result;
} else if (Math_default.equalsEpsilon(
Math.abs(Math_default.PI_OVER_TWO - absHeading),
Math_default.PI_OVER_TWO,
Math_default.EPSILON8
)) {
if (Math_default.equalsEpsilon(
intersectionLongitude,
start.longitude,
Math_default.EPSILON12
)) {
return void 0;
}
result.longitude = intersectionLongitude;
result.latitude = Math_default.PI_OVER_TWO * Math_default.sign(Math_default.PI_OVER_TWO - heading);
result.height = 0;
return result;
}
const phi1 = start.latitude;
const eSinPhi1 = ellipticity * Math.sin(phi1);
const leftComponent = Math.tan(0.5 * (Math_default.PI_OVER_TWO + phi1)) * Math.exp((intersectionLongitude - start.longitude) / Math.tan(heading));
const denominator = (1 + eSinPhi1) / (1 - eSinPhi1);
let newPhi = start.latitude;
let phi;
do {
phi = newPhi;
const eSinPhi = ellipticity * Math.sin(phi);
const numerator = (1 + eSinPhi) / (1 - eSinPhi);
newPhi = 2 * Math.atan(
leftComponent * Math.pow(numerator / denominator, ellipticity / 2)
) - Math_default.PI_OVER_TWO;
} while (!Math_default.equalsEpsilon(newPhi, phi, Math_default.EPSILON12));
result.longitude = intersectionLongitude;
result.latitude = newPhi;
result.height = 0;
return result;
};
EllipsoidRhumbLine.prototype.findIntersectionWithLatitude = function(intersectionLatitude, result) {
Check_default.typeOf.number("intersectionLatitude", intersectionLatitude);
if (!defined_default(this._distance) || this._distance === 0) {
throw new DeveloperError_default(
"EllipsoidRhumbLine must have distinct start and end set."
);
}
const ellipticity = this._ellipticity;
const heading = this._heading;
const start = this._start;
if (Math_default.equalsEpsilon(
Math.abs(heading),
Math_default.PI_OVER_TWO,
Math_default.EPSILON8
)) {
return;
}
const sigma1 = calculateSigma(ellipticity, start.latitude);
const sigma2 = calculateSigma(ellipticity, intersectionLatitude);
const deltaLongitude = Math.tan(heading) * (sigma2 - sigma1);
const longitude = Math_default.negativePiToPi(start.longitude + deltaLongitude);
if (defined_default(result)) {
result.longitude = longitude;
result.latitude = intersectionLatitude;
result.height = 0;
return result;
}
return new Cartographic_default(longitude, intersectionLatitude, 0);
};
var EllipsoidRhumbLine_default = EllipsoidRhumbLine;
// packages/engine/Source/Core/GroundPolylineGeometry.js
var PROJECTIONS = [GeographicProjection_default, WebMercatorProjection_default];
var PROJECTION_COUNT = PROJECTIONS.length;
var MITER_BREAK_SMALL = Math.cos(Math_default.toRadians(30));
var MITER_BREAK_LARGE = Math.cos(Math_default.toRadians(150));
var WALL_INITIAL_MIN_HEIGHT = 0;
var WALL_INITIAL_MAX_HEIGHT = 1e3;
function GroundPolylineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const positions = options.positions;
if (!defined_default(positions) || positions.length < 2) {
throw new DeveloperError_default("At least two positions are required.");
}
if (defined_default(options.arcType) && options.arcType !== ArcType_default.GEODESIC && options.arcType !== ArcType_default.RHUMB) {
throw new DeveloperError_default(
"Valid options for arcType are ArcType.GEODESIC and ArcType.RHUMB."
);
}
this.width = options.width ?? 1;
this._positions = positions;
this.granularity = options.granularity ?? 9999;
this.loop = options.loop ?? false;
this.arcType = options.arcType ?? ArcType_default.GEODESIC;
this._ellipsoid = Ellipsoid_default.default;
this._projectionIndex = 0;
this._workerName = "createGroundPolylineGeometry";
this._scene3DOnly = false;
}
Object.defineProperties(GroundPolylineGeometry.prototype, {
/**
* The number of elements used to pack the object into an array.
* @memberof GroundPolylineGeometry.prototype
* @type {number}
* @readonly
* @private
*/
packedLength: {
get: function() {
return 1 + this._positions.length * 3 + 1 + 1 + 1 + Ellipsoid_default.packedLength + 1 + 1;
}
}
});
GroundPolylineGeometry.setProjectionAndEllipsoid = function(groundPolylineGeometry, mapProjection) {
let projectionIndex = 0;
for (let i = 0; i < PROJECTION_COUNT; i++) {
if (mapProjection instanceof PROJECTIONS[i]) {
projectionIndex = i;
break;
}
}
groundPolylineGeometry._projectionIndex = projectionIndex;
groundPolylineGeometry._ellipsoid = mapProjection.ellipsoid;
};
var cart3Scratch1 = new Cartesian3_default();
var cart3Scratch2 = new Cartesian3_default();
var cart3Scratch3 = new Cartesian3_default();
function computeRightNormal(start, end, maxHeight, ellipsoid, result) {
const startBottom = getPosition(ellipsoid, start, 0, cart3Scratch1);
const startTop = getPosition(ellipsoid, start, maxHeight, cart3Scratch2);
const endBottom = getPosition(ellipsoid, end, 0, cart3Scratch3);
const up = direction(startTop, startBottom, cart3Scratch2);
const forward = direction(endBottom, startBottom, cart3Scratch3);
Cartesian3_default.cross(forward, up, result);
return Cartesian3_default.normalize(result, result);
}
var interpolatedCartographicScratch = new Cartographic_default();
var interpolatedBottomScratch = new Cartesian3_default();
var interpolatedTopScratch = new Cartesian3_default();
var interpolatedNormalScratch = new Cartesian3_default();
function interpolateSegment(start, end, minHeight, maxHeight, granularity, arcType, ellipsoid, normalsArray, bottomPositionsArray, topPositionsArray, cartographicsArray) {
if (granularity === 0) {
return;
}
let ellipsoidLine;
if (arcType === ArcType_default.GEODESIC) {
ellipsoidLine = new EllipsoidGeodesic_default(start, end, ellipsoid);
} else if (arcType === ArcType_default.RHUMB) {
ellipsoidLine = new EllipsoidRhumbLine_default(start, end, ellipsoid);
}
const surfaceDistance = ellipsoidLine.surfaceDistance;
if (surfaceDistance < granularity) {
return;
}
const interpolatedNormal = computeRightNormal(
start,
end,
maxHeight,
ellipsoid,
interpolatedNormalScratch
);
const segments = Math.ceil(surfaceDistance / granularity);
const interpointDistance = surfaceDistance / segments;
let distanceFromStart = interpointDistance;
const pointsToAdd = segments - 1;
let packIndex = normalsArray.length;
for (let i = 0; i < pointsToAdd; i++) {
const interpolatedCartographic = ellipsoidLine.interpolateUsingSurfaceDistance(
distanceFromStart,
interpolatedCartographicScratch
);
const interpolatedBottom = getPosition(
ellipsoid,
interpolatedCartographic,
minHeight,
interpolatedBottomScratch
);
const interpolatedTop = getPosition(
ellipsoid,
interpolatedCartographic,
maxHeight,
interpolatedTopScratch
);
Cartesian3_default.pack(interpolatedNormal, normalsArray, packIndex);
Cartesian3_default.pack(interpolatedBottom, bottomPositionsArray, packIndex);
Cartesian3_default.pack(interpolatedTop, topPositionsArray, packIndex);
cartographicsArray.push(interpolatedCartographic.latitude);
cartographicsArray.push(interpolatedCartographic.longitude);
packIndex += 3;
distanceFromStart += interpointDistance;
}
}
var heightlessCartographicScratch = new Cartographic_default();
function getPosition(ellipsoid, cartographic2, height, result) {
Cartographic_default.clone(cartographic2, heightlessCartographicScratch);
heightlessCartographicScratch.height = height;
return Cartographic_default.toCartesian(
heightlessCartographicScratch,
ellipsoid,
result
);
}
GroundPolylineGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
let index = startingIndex ?? 0;
const positions = value._positions;
const positionsLength = positions.length;
array[index++] = positionsLength;
for (let i = 0; i < positionsLength; ++i) {
const cartesian11 = positions[i];
Cartesian3_default.pack(cartesian11, array, index);
index += 3;
}
array[index++] = value.granularity;
array[index++] = value.loop ? 1 : 0;
array[index++] = value.arcType;
Ellipsoid_default.pack(value._ellipsoid, array, index);
index += Ellipsoid_default.packedLength;
array[index++] = value._projectionIndex;
array[index++] = value._scene3DOnly ? 1 : 0;
return array;
};
GroundPolylineGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
let index = startingIndex ?? 0;
const positionsLength = array[index++];
const positions = new Array(positionsLength);
for (let i = 0; i < positionsLength; i++) {
positions[i] = Cartesian3_default.unpack(array, index);
index += 3;
}
const granularity = array[index++];
const loop = array[index++] === 1;
const arcType = array[index++];
const ellipsoid = Ellipsoid_default.unpack(array, index);
index += Ellipsoid_default.packedLength;
const projectionIndex = array[index++];
const scene3DOnly = array[index++] === 1;
if (!defined_default(result)) {
result = new GroundPolylineGeometry({
positions
});
}
result._positions = positions;
result.granularity = granularity;
result.loop = loop;
result.arcType = arcType;
result._ellipsoid = ellipsoid;
result._projectionIndex = projectionIndex;
result._scene3DOnly = scene3DOnly;
return result;
};
function direction(target, origin, result) {
Cartesian3_default.subtract(target, origin, result);
Cartesian3_default.normalize(result, result);
return result;
}
function tangentDirection(target, origin, up, result) {
result = direction(target, origin, result);
result = Cartesian3_default.cross(result, up, result);
result = Cartesian3_default.normalize(result, result);
result = Cartesian3_default.cross(up, result, result);
return result;
}
var toPreviousScratch = new Cartesian3_default();
var toNextScratch = new Cartesian3_default();
var forwardScratch = new Cartesian3_default();
var vertexUpScratch = new Cartesian3_default();
var cosine90 = 0;
var cosine180 = -1;
function computeVertexMiterNormal(previousBottom, vertexBottom, vertexTop, nextBottom, result) {
const up = direction(vertexTop, vertexBottom, vertexUpScratch);
const toPrevious = tangentDirection(
previousBottom,
vertexBottom,
up,
toPreviousScratch
);
const toNext = tangentDirection(nextBottom, vertexBottom, up, toNextScratch);
if (Math_default.equalsEpsilon(
Cartesian3_default.dot(toPrevious, toNext),
cosine180,
Math_default.EPSILON5
)) {
result = Cartesian3_default.cross(up, toPrevious, result);
result = Cartesian3_default.normalize(result, result);
return result;
}
result = Cartesian3_default.add(toNext, toPrevious, result);
result = Cartesian3_default.normalize(result, result);
const forward = Cartesian3_default.cross(up, result, forwardScratch);
if (Cartesian3_default.dot(toNext, forward) < cosine90) {
result = Cartesian3_default.negate(result, result);
}
return result;
}
var XZ_PLANE = Plane_default.fromPointNormal(Cartesian3_default.ZERO, Cartesian3_default.UNIT_Y);
var previousBottomScratch = new Cartesian3_default();
var vertexBottomScratch = new Cartesian3_default();
var vertexTopScratch = new Cartesian3_default();
var nextBottomScratch = new Cartesian3_default();
var vertexNormalScratch = new Cartesian3_default();
var intersectionScratch = new Cartesian3_default();
var cartographicScratch0 = new Cartographic_default();
var cartographicScratch1 = new Cartographic_default();
var cartographicIntersectionScratch = new Cartographic_default();
GroundPolylineGeometry.createGeometry = function(groundPolylineGeometry) {
const compute2dAttributes = !groundPolylineGeometry._scene3DOnly;
let loop = groundPolylineGeometry.loop;
const ellipsoid = groundPolylineGeometry._ellipsoid;
const granularity = groundPolylineGeometry.granularity;
const arcType = groundPolylineGeometry.arcType;
const projection = new PROJECTIONS[groundPolylineGeometry._projectionIndex](
ellipsoid
);
const minHeight = WALL_INITIAL_MIN_HEIGHT;
const maxHeight = WALL_INITIAL_MAX_HEIGHT;
let index;
let i;
const positions = groundPolylineGeometry._positions;
const positionsLength = positions.length;
if (positionsLength === 2) {
loop = false;
}
let p0;
let p1;
let c0;
let c14;
const rhumbLine = new EllipsoidRhumbLine_default(void 0, void 0, ellipsoid);
let intersection;
let intersectionCartographic;
let intersectionLongitude;
const splitPositions = [positions[0]];
for (i = 0; i < positionsLength - 1; i++) {
p0 = positions[i];
p1 = positions[i + 1];
intersection = IntersectionTests_default.lineSegmentPlane(
p0,
p1,
XZ_PLANE,
intersectionScratch
);
if (defined_default(intersection) && !Cartesian3_default.equalsEpsilon(intersection, p0, Math_default.EPSILON7) && !Cartesian3_default.equalsEpsilon(intersection, p1, Math_default.EPSILON7)) {
if (groundPolylineGeometry.arcType === ArcType_default.GEODESIC) {
splitPositions.push(Cartesian3_default.clone(intersection));
} else if (groundPolylineGeometry.arcType === ArcType_default.RHUMB) {
intersectionLongitude = ellipsoid.cartesianToCartographic(
intersection,
cartographicScratch0
).longitude;
c0 = ellipsoid.cartesianToCartographic(p0, cartographicScratch0);
c14 = ellipsoid.cartesianToCartographic(p1, cartographicScratch1);
rhumbLine.setEndPoints(c0, c14);
intersectionCartographic = rhumbLine.findIntersectionWithLongitude(
intersectionLongitude,
cartographicIntersectionScratch
);
intersection = ellipsoid.cartographicToCartesian(
intersectionCartographic,
intersectionScratch
);
if (defined_default(intersection) && !Cartesian3_default.equalsEpsilon(intersection, p0, Math_default.EPSILON7) && !Cartesian3_default.equalsEpsilon(intersection, p1, Math_default.EPSILON7)) {
splitPositions.push(Cartesian3_default.clone(intersection));
}
}
}
splitPositions.push(p1);
}
if (loop) {
p0 = positions[positionsLength - 1];
p1 = positions[0];
intersection = IntersectionTests_default.lineSegmentPlane(
p0,
p1,
XZ_PLANE,
intersectionScratch
);
if (defined_default(intersection) && !Cartesian3_default.equalsEpsilon(intersection, p0, Math_default.EPSILON7) && !Cartesian3_default.equalsEpsilon(intersection, p1, Math_default.EPSILON7)) {
if (groundPolylineGeometry.arcType === ArcType_default.GEODESIC) {
splitPositions.push(Cartesian3_default.clone(intersection));
} else if (groundPolylineGeometry.arcType === ArcType_default.RHUMB) {
intersectionLongitude = ellipsoid.cartesianToCartographic(
intersection,
cartographicScratch0
).longitude;
c0 = ellipsoid.cartesianToCartographic(p0, cartographicScratch0);
c14 = ellipsoid.cartesianToCartographic(p1, cartographicScratch1);
rhumbLine.setEndPoints(c0, c14);
intersectionCartographic = rhumbLine.findIntersectionWithLongitude(
intersectionLongitude,
cartographicIntersectionScratch
);
intersection = ellipsoid.cartographicToCartesian(
intersectionCartographic,
intersectionScratch
);
if (defined_default(intersection) && !Cartesian3_default.equalsEpsilon(intersection, p0, Math_default.EPSILON7) && !Cartesian3_default.equalsEpsilon(intersection, p1, Math_default.EPSILON7)) {
splitPositions.push(Cartesian3_default.clone(intersection));
}
}
}
}
let cartographicsLength = splitPositions.length;
let cartographics = new Array(cartographicsLength);
for (i = 0; i < cartographicsLength; i++) {
const cartographic2 = Cartographic_default.fromCartesian(
splitPositions[i],
ellipsoid
);
cartographic2.height = 0;
cartographics[i] = cartographic2;
}
cartographics = arrayRemoveDuplicates_default(
cartographics,
Cartographic_default.equalsEpsilon
);
cartographicsLength = cartographics.length;
if (cartographicsLength < 2) {
return void 0;
}
const cartographicsArray = [];
const normalsArray = [];
const bottomPositionsArray = [];
const topPositionsArray = [];
let previousBottom = previousBottomScratch;
let vertexBottom = vertexBottomScratch;
let vertexTop = vertexTopScratch;
let nextBottom = nextBottomScratch;
let vertexNormal = vertexNormalScratch;
const startCartographic = cartographics[0];
const nextCartographic = cartographics[1];
const prestartCartographic = cartographics[cartographicsLength - 1];
previousBottom = getPosition(
ellipsoid,
prestartCartographic,
minHeight,
previousBottom
);
nextBottom = getPosition(ellipsoid, nextCartographic, minHeight, nextBottom);
vertexBottom = getPosition(
ellipsoid,
startCartographic,
minHeight,
vertexBottom
);
vertexTop = getPosition(ellipsoid, startCartographic, maxHeight, vertexTop);
if (loop) {
vertexNormal = computeVertexMiterNormal(
previousBottom,
vertexBottom,
vertexTop,
nextBottom,
vertexNormal
);
} else {
vertexNormal = computeRightNormal(
startCartographic,
nextCartographic,
maxHeight,
ellipsoid,
vertexNormal
);
}
Cartesian3_default.pack(vertexNormal, normalsArray, 0);
Cartesian3_default.pack(vertexBottom, bottomPositionsArray, 0);
Cartesian3_default.pack(vertexTop, topPositionsArray, 0);
cartographicsArray.push(startCartographic.latitude);
cartographicsArray.push(startCartographic.longitude);
interpolateSegment(
startCartographic,
nextCartographic,
minHeight,
maxHeight,
granularity,
arcType,
ellipsoid,
normalsArray,
bottomPositionsArray,
topPositionsArray,
cartographicsArray
);
for (i = 1; i < cartographicsLength - 1; ++i) {
previousBottom = Cartesian3_default.clone(vertexBottom, previousBottom);
vertexBottom = Cartesian3_default.clone(nextBottom, vertexBottom);
const vertexCartographic = cartographics[i];
getPosition(ellipsoid, vertexCartographic, maxHeight, vertexTop);
getPosition(ellipsoid, cartographics[i + 1], minHeight, nextBottom);
computeVertexMiterNormal(
previousBottom,
vertexBottom,
vertexTop,
nextBottom,
vertexNormal
);
index = normalsArray.length;
Cartesian3_default.pack(vertexNormal, normalsArray, index);
Cartesian3_default.pack(vertexBottom, bottomPositionsArray, index);
Cartesian3_default.pack(vertexTop, topPositionsArray, index);
cartographicsArray.push(vertexCartographic.latitude);
cartographicsArray.push(vertexCartographic.longitude);
interpolateSegment(
cartographics[i],
cartographics[i + 1],
minHeight,
maxHeight,
granularity,
arcType,
ellipsoid,
normalsArray,
bottomPositionsArray,
topPositionsArray,
cartographicsArray
);
}
const endCartographic = cartographics[cartographicsLength - 1];
const preEndCartographic = cartographics[cartographicsLength - 2];
vertexBottom = getPosition(
ellipsoid,
endCartographic,
minHeight,
vertexBottom
);
vertexTop = getPosition(ellipsoid, endCartographic, maxHeight, vertexTop);
if (loop) {
const postEndCartographic = cartographics[0];
previousBottom = getPosition(
ellipsoid,
preEndCartographic,
minHeight,
previousBottom
);
nextBottom = getPosition(
ellipsoid,
postEndCartographic,
minHeight,
nextBottom
);
vertexNormal = computeVertexMiterNormal(
previousBottom,
vertexBottom,
vertexTop,
nextBottom,
vertexNormal
);
} else {
vertexNormal = computeRightNormal(
preEndCartographic,
endCartographic,
maxHeight,
ellipsoid,
vertexNormal
);
}
index = normalsArray.length;
Cartesian3_default.pack(vertexNormal, normalsArray, index);
Cartesian3_default.pack(vertexBottom, bottomPositionsArray, index);
Cartesian3_default.pack(vertexTop, topPositionsArray, index);
cartographicsArray.push(endCartographic.latitude);
cartographicsArray.push(endCartographic.longitude);
if (loop) {
interpolateSegment(
endCartographic,
startCartographic,
minHeight,
maxHeight,
granularity,
arcType,
ellipsoid,
normalsArray,
bottomPositionsArray,
topPositionsArray,
cartographicsArray
);
index = normalsArray.length;
for (i = 0; i < 3; ++i) {
normalsArray[index + i] = normalsArray[i];
bottomPositionsArray[index + i] = bottomPositionsArray[i];
topPositionsArray[index + i] = topPositionsArray[i];
}
cartographicsArray.push(startCartographic.latitude);
cartographicsArray.push(startCartographic.longitude);
}
return generateGeometryAttributes(
loop,
projection,
bottomPositionsArray,
topPositionsArray,
normalsArray,
cartographicsArray,
compute2dAttributes
);
};
var lineDirectionScratch = new Cartesian3_default();
var matrix3Scratch = new Matrix3_default();
var quaternionScratch = new Quaternion_default();
function breakMiter(endGeometryNormal, startBottom, endBottom, endTop) {
const lineDirection = direction(endBottom, startBottom, lineDirectionScratch);
const dot2 = Cartesian3_default.dot(lineDirection, endGeometryNormal);
if (dot2 > MITER_BREAK_SMALL || dot2 < MITER_BREAK_LARGE) {
const vertexUp = direction(endTop, endBottom, vertexUpScratch);
const angle = dot2 < MITER_BREAK_LARGE ? Math_default.PI_OVER_TWO : -Math_default.PI_OVER_TWO;
const quaternion = Quaternion_default.fromAxisAngle(
vertexUp,
angle,
quaternionScratch
);
const rotationMatrix = Matrix3_default.fromQuaternion(quaternion, matrix3Scratch);
Matrix3_default.multiplyByVector(
rotationMatrix,
endGeometryNormal,
endGeometryNormal
);
return true;
}
return false;
}
var endPosCartographicScratch = new Cartographic_default();
var normalStartpointScratch = new Cartesian3_default();
var normalEndpointScratch = new Cartesian3_default();
function projectNormal(projection, cartographic2, normal2, projectedPosition2, result) {
const position = Cartographic_default.toCartesian(
cartographic2,
projection._ellipsoid,
normalStartpointScratch
);
let normalEndpoint = Cartesian3_default.add(position, normal2, normalEndpointScratch);
let flipNormal = false;
const ellipsoid = projection._ellipsoid;
let normalEndpointCartographic = ellipsoid.cartesianToCartographic(
normalEndpoint,
endPosCartographicScratch
);
if (Math.abs(cartographic2.longitude - normalEndpointCartographic.longitude) > Math_default.PI_OVER_TWO) {
flipNormal = true;
normalEndpoint = Cartesian3_default.subtract(
position,
normal2,
normalEndpointScratch
);
normalEndpointCartographic = ellipsoid.cartesianToCartographic(
normalEndpoint,
endPosCartographicScratch
);
}
normalEndpointCartographic.height = 0;
const normalEndpointProjected = projection.project(
normalEndpointCartographic,
result
);
result = Cartesian3_default.subtract(
normalEndpointProjected,
projectedPosition2,
result
);
result.z = 0;
result = Cartesian3_default.normalize(result, result);
if (flipNormal) {
Cartesian3_default.negate(result, result);
}
return result;
}
var adjustHeightNormalScratch = new Cartesian3_default();
var adjustHeightOffsetScratch = new Cartesian3_default();
function adjustHeights(bottom, top, minHeight, maxHeight, adjustHeightBottom, adjustHeightTop) {
const adjustHeightNormal = Cartesian3_default.subtract(
top,
bottom,
adjustHeightNormalScratch
);
Cartesian3_default.normalize(adjustHeightNormal, adjustHeightNormal);
const distanceForBottom = minHeight - WALL_INITIAL_MIN_HEIGHT;
let adjustHeightOffset = Cartesian3_default.multiplyByScalar(
adjustHeightNormal,
distanceForBottom,
adjustHeightOffsetScratch
);
Cartesian3_default.add(bottom, adjustHeightOffset, adjustHeightBottom);
const distanceForTop = maxHeight - WALL_INITIAL_MAX_HEIGHT;
adjustHeightOffset = Cartesian3_default.multiplyByScalar(
adjustHeightNormal,
distanceForTop,
adjustHeightOffsetScratch
);
Cartesian3_default.add(top, adjustHeightOffset, adjustHeightTop);
}
var nudgeDirectionScratch = new Cartesian3_default();
function nudgeXZ(start, end) {
const startToXZdistance = Plane_default.getPointDistance(XZ_PLANE, start);
const endToXZdistance = Plane_default.getPointDistance(XZ_PLANE, end);
let offset = nudgeDirectionScratch;
if (Math_default.equalsEpsilon(startToXZdistance, 0, Math_default.EPSILON2)) {
offset = direction(end, start, offset);
Cartesian3_default.multiplyByScalar(offset, Math_default.EPSILON2, offset);
Cartesian3_default.add(start, offset, start);
} else if (Math_default.equalsEpsilon(endToXZdistance, 0, Math_default.EPSILON2)) {
offset = direction(start, end, offset);
Cartesian3_default.multiplyByScalar(offset, Math_default.EPSILON2, offset);
Cartesian3_default.add(end, offset, end);
}
}
function nudgeCartographic(start, end) {
const absStartLon = Math.abs(start.longitude);
const absEndLon = Math.abs(end.longitude);
if (Math_default.equalsEpsilon(absStartLon, Math_default.PI, Math_default.EPSILON11)) {
const endSign = Math_default.sign(end.longitude);
start.longitude = endSign * (absStartLon - Math_default.EPSILON11);
return 1;
} else if (Math_default.equalsEpsilon(absEndLon, Math_default.PI, Math_default.EPSILON11)) {
const startSign = Math_default.sign(start.longitude);
end.longitude = startSign * (absEndLon - Math_default.EPSILON11);
return 2;
}
return 0;
}
var startCartographicScratch = new Cartographic_default();
var endCartographicScratch = new Cartographic_default();
var segmentStartTopScratch = new Cartesian3_default();
var segmentEndTopScratch = new Cartesian3_default();
var segmentStartBottomScratch = new Cartesian3_default();
var segmentEndBottomScratch = new Cartesian3_default();
var segmentStartNormalScratch = new Cartesian3_default();
var segmentEndNormalScratch = new Cartesian3_default();
var getHeightCartographics = [
startCartographicScratch,
endCartographicScratch
];
var getHeightRectangleScratch = new Rectangle_default();
var adjustHeightStartTopScratch = new Cartesian3_default();
var adjustHeightEndTopScratch = new Cartesian3_default();
var adjustHeightStartBottomScratch = new Cartesian3_default();
var adjustHeightEndBottomScratch = new Cartesian3_default();
var segmentStart2DScratch = new Cartesian3_default();
var segmentEnd2DScratch = new Cartesian3_default();
var segmentStartNormal2DScratch = new Cartesian3_default();
var segmentEndNormal2DScratch = new Cartesian3_default();
var offsetScratch3 = new Cartesian3_default();
var startUpScratch = new Cartesian3_default();
var endUpScratch = new Cartesian3_default();
var rightScratch2 = new Cartesian3_default();
var startPlaneNormalScratch = new Cartesian3_default();
var endPlaneNormalScratch = new Cartesian3_default();
var encodeScratch2 = new EncodedCartesian3_default();
var encodeScratch2D = new EncodedCartesian3_default();
var forwardOffset2DScratch = new Cartesian3_default();
var right2DScratch = new Cartesian3_default();
var normalNudgeScratch = new Cartesian3_default();
var scratchBoundingSpheres = [new BoundingSphere_default(), new BoundingSphere_default()];
var REFERENCE_INDICES = [
0,
2,
1,
0,
3,
2,
// right
0,
7,
3,
0,
4,
7,
// start
0,
5,
4,
0,
1,
5,
// bottom
5,
7,
4,
5,
6,
7,
// left
5,
2,
6,
5,
1,
2,
// end
3,
6,
2,
3,
7,
6
// top
];
var REFERENCE_INDICES_LENGTH = REFERENCE_INDICES.length;
function generateGeometryAttributes(loop, projection, bottomPositionsArray, topPositionsArray, normalsArray, cartographicsArray, compute2dAttributes) {
let i;
let index;
const ellipsoid = projection._ellipsoid;
const segmentCount = bottomPositionsArray.length / 3 - 1;
const vertexCount = segmentCount * 8;
const arraySizeVec4 = vertexCount * 4;
const indexCount = segmentCount * 36;
const indices = vertexCount > 65535 ? new Uint32Array(indexCount) : new Uint16Array(indexCount);
const positionsArray = new Float64Array(vertexCount * 3);
const startHiAndForwardOffsetX = new Float32Array(arraySizeVec4);
const startLoAndForwardOffsetY = new Float32Array(arraySizeVec4);
const startNormalAndForwardOffsetZ = new Float32Array(arraySizeVec4);
const endNormalAndTextureCoordinateNormalizationX = new Float32Array(
arraySizeVec4
);
const rightNormalAndTextureCoordinateNormalizationY = new Float32Array(
arraySizeVec4
);
let startHiLo2D;
let offsetAndRight2D;
let startEndNormals2D;
let texcoordNormalization2D;
if (compute2dAttributes) {
startHiLo2D = new Float32Array(arraySizeVec4);
offsetAndRight2D = new Float32Array(arraySizeVec4);
startEndNormals2D = new Float32Array(arraySizeVec4);
texcoordNormalization2D = new Float32Array(vertexCount * 2);
}
const cartographicsLength = cartographicsArray.length / 2;
let length2D = 0;
const startCartographic = startCartographicScratch;
startCartographic.height = 0;
const endCartographic = endCartographicScratch;
endCartographic.height = 0;
let segmentStartCartesian = segmentStartTopScratch;
let segmentEndCartesian = segmentEndTopScratch;
if (compute2dAttributes) {
index = 0;
for (i = 1; i < cartographicsLength; i++) {
startCartographic.latitude = cartographicsArray[index];
startCartographic.longitude = cartographicsArray[index + 1];
endCartographic.latitude = cartographicsArray[index + 2];
endCartographic.longitude = cartographicsArray[index + 3];
segmentStartCartesian = projection.project(
startCartographic,
segmentStartCartesian
);
segmentEndCartesian = projection.project(
endCartographic,
segmentEndCartesian
);
length2D += Cartesian3_default.distance(
segmentStartCartesian,
segmentEndCartesian
);
index += 2;
}
}
const positionsLength = topPositionsArray.length / 3;
segmentEndCartesian = Cartesian3_default.unpack(
topPositionsArray,
0,
segmentEndCartesian
);
let length3D = 0;
index = 3;
for (i = 1; i < positionsLength; i++) {
segmentStartCartesian = Cartesian3_default.clone(
segmentEndCartesian,
segmentStartCartesian
);
segmentEndCartesian = Cartesian3_default.unpack(
topPositionsArray,
index,
segmentEndCartesian
);
length3D += Cartesian3_default.distance(segmentStartCartesian, segmentEndCartesian);
index += 3;
}
let j;
index = 3;
let cartographicsIndex = 0;
let vec2sWriteIndex = 0;
let vec3sWriteIndex = 0;
let vec4sWriteIndex = 0;
let miterBroken = false;
let endBottom = Cartesian3_default.unpack(
bottomPositionsArray,
0,
segmentEndBottomScratch
);
let endTop = Cartesian3_default.unpack(topPositionsArray, 0, segmentEndTopScratch);
let endGeometryNormal = Cartesian3_default.unpack(
normalsArray,
0,
segmentEndNormalScratch
);
if (loop) {
const preEndBottom = Cartesian3_default.unpack(
bottomPositionsArray,
bottomPositionsArray.length - 6,
segmentStartBottomScratch
);
if (breakMiter(endGeometryNormal, preEndBottom, endBottom, endTop)) {
endGeometryNormal = Cartesian3_default.negate(
endGeometryNormal,
endGeometryNormal
);
}
}
let lengthSoFar3D = 0;
let lengthSoFar2D = 0;
let sumHeights = 0;
for (i = 0; i < segmentCount; i++) {
const startBottom = Cartesian3_default.clone(endBottom, segmentStartBottomScratch);
const startTop = Cartesian3_default.clone(endTop, segmentStartTopScratch);
let startGeometryNormal = Cartesian3_default.clone(
endGeometryNormal,
segmentStartNormalScratch
);
if (miterBroken) {
startGeometryNormal = Cartesian3_default.negate(
startGeometryNormal,
startGeometryNormal
);
}
endBottom = Cartesian3_default.unpack(
bottomPositionsArray,
index,
segmentEndBottomScratch
);
endTop = Cartesian3_default.unpack(topPositionsArray, index, segmentEndTopScratch);
endGeometryNormal = Cartesian3_default.unpack(
normalsArray,
index,
segmentEndNormalScratch
);
miterBroken = breakMiter(endGeometryNormal, startBottom, endBottom, endTop);
startCartographic.latitude = cartographicsArray[cartographicsIndex];
startCartographic.longitude = cartographicsArray[cartographicsIndex + 1];
endCartographic.latitude = cartographicsArray[cartographicsIndex + 2];
endCartographic.longitude = cartographicsArray[cartographicsIndex + 3];
let start2D;
let end2D;
let startGeometryNormal2D;
let endGeometryNormal2D;
if (compute2dAttributes) {
const nudgeResult = nudgeCartographic(startCartographic, endCartographic);
start2D = projection.project(startCartographic, segmentStart2DScratch);
end2D = projection.project(endCartographic, segmentEnd2DScratch);
const direction2D = direction(end2D, start2D, forwardOffset2DScratch);
direction2D.y = Math.abs(direction2D.y);
startGeometryNormal2D = segmentStartNormal2DScratch;
endGeometryNormal2D = segmentEndNormal2DScratch;
if (nudgeResult === 0 || Cartesian3_default.dot(direction2D, Cartesian3_default.UNIT_Y) > MITER_BREAK_SMALL) {
startGeometryNormal2D = projectNormal(
projection,
startCartographic,
startGeometryNormal,
start2D,
segmentStartNormal2DScratch
);
endGeometryNormal2D = projectNormal(
projection,
endCartographic,
endGeometryNormal,
end2D,
segmentEndNormal2DScratch
);
} else if (nudgeResult === 1) {
endGeometryNormal2D = projectNormal(
projection,
endCartographic,
endGeometryNormal,
end2D,
segmentEndNormal2DScratch
);
startGeometryNormal2D.x = 0;
startGeometryNormal2D.y = Math_default.sign(
startCartographic.longitude - Math.abs(endCartographic.longitude)
);
startGeometryNormal2D.z = 0;
} else {
startGeometryNormal2D = projectNormal(
projection,
startCartographic,
startGeometryNormal,
start2D,
segmentStartNormal2DScratch
);
endGeometryNormal2D.x = 0;
endGeometryNormal2D.y = Math_default.sign(
startCartographic.longitude - endCartographic.longitude
);
endGeometryNormal2D.z = 0;
}
}
const segmentLength3D = Cartesian3_default.distance(startTop, endTop);
const encodedStart = EncodedCartesian3_default.fromCartesian(
startBottom,
encodeScratch2
);
const forwardOffset = Cartesian3_default.subtract(
endBottom,
startBottom,
offsetScratch3
);
const forward = Cartesian3_default.normalize(forwardOffset, rightScratch2);
let startUp = Cartesian3_default.subtract(startTop, startBottom, startUpScratch);
startUp = Cartesian3_default.normalize(startUp, startUp);
let rightNormal = Cartesian3_default.cross(forward, startUp, rightScratch2);
rightNormal = Cartesian3_default.normalize(rightNormal, rightNormal);
let startPlaneNormal = Cartesian3_default.cross(
startUp,
startGeometryNormal,
startPlaneNormalScratch
);
startPlaneNormal = Cartesian3_default.normalize(startPlaneNormal, startPlaneNormal);
let endUp = Cartesian3_default.subtract(endTop, endBottom, endUpScratch);
endUp = Cartesian3_default.normalize(endUp, endUp);
let endPlaneNormal = Cartesian3_default.cross(
endGeometryNormal,
endUp,
endPlaneNormalScratch
);
endPlaneNormal = Cartesian3_default.normalize(endPlaneNormal, endPlaneNormal);
const texcoordNormalization3DX = segmentLength3D / length3D;
const texcoordNormalization3DY = lengthSoFar3D / length3D;
let segmentLength2D = 0;
let encodedStart2D;
let forwardOffset2D;
let right2D;
let texcoordNormalization2DX = 0;
let texcoordNormalization2DY = 0;
if (compute2dAttributes) {
segmentLength2D = Cartesian3_default.distance(start2D, end2D);
encodedStart2D = EncodedCartesian3_default.fromCartesian(
start2D,
encodeScratch2D
);
forwardOffset2D = Cartesian3_default.subtract(
end2D,
start2D,
forwardOffset2DScratch
);
right2D = Cartesian3_default.normalize(forwardOffset2D, right2DScratch);
const swap5 = right2D.x;
right2D.x = right2D.y;
right2D.y = -swap5;
texcoordNormalization2DX = segmentLength2D / length2D;
texcoordNormalization2DY = lengthSoFar2D / length2D;
}
for (j = 0; j < 8; j++) {
const vec4Index = vec4sWriteIndex + j * 4;
const vec2Index = vec2sWriteIndex + j * 2;
const wIndex = vec4Index + 3;
const rightPlaneSide = j < 4 ? 1 : -1;
const topBottomSide = j === 2 || j === 3 || j === 6 || j === 7 ? 1 : -1;
Cartesian3_default.pack(encodedStart.high, startHiAndForwardOffsetX, vec4Index);
startHiAndForwardOffsetX[wIndex] = forwardOffset.x;
Cartesian3_default.pack(encodedStart.low, startLoAndForwardOffsetY, vec4Index);
startLoAndForwardOffsetY[wIndex] = forwardOffset.y;
Cartesian3_default.pack(
startPlaneNormal,
startNormalAndForwardOffsetZ,
vec4Index
);
startNormalAndForwardOffsetZ[wIndex] = forwardOffset.z;
Cartesian3_default.pack(
endPlaneNormal,
endNormalAndTextureCoordinateNormalizationX,
vec4Index
);
endNormalAndTextureCoordinateNormalizationX[wIndex] = texcoordNormalization3DX * rightPlaneSide;
Cartesian3_default.pack(
rightNormal,
rightNormalAndTextureCoordinateNormalizationY,
vec4Index
);
let texcoordNormalization = texcoordNormalization3DY * topBottomSide;
if (texcoordNormalization === 0 && topBottomSide < 0) {
texcoordNormalization = 9;
}
rightNormalAndTextureCoordinateNormalizationY[wIndex] = texcoordNormalization;
if (compute2dAttributes) {
startHiLo2D[vec4Index] = encodedStart2D.high.x;
startHiLo2D[vec4Index + 1] = encodedStart2D.high.y;
startHiLo2D[vec4Index + 2] = encodedStart2D.low.x;
startHiLo2D[vec4Index + 3] = encodedStart2D.low.y;
startEndNormals2D[vec4Index] = -startGeometryNormal2D.y;
startEndNormals2D[vec4Index + 1] = startGeometryNormal2D.x;
startEndNormals2D[vec4Index + 2] = endGeometryNormal2D.y;
startEndNormals2D[vec4Index + 3] = -endGeometryNormal2D.x;
offsetAndRight2D[vec4Index] = forwardOffset2D.x;
offsetAndRight2D[vec4Index + 1] = forwardOffset2D.y;
offsetAndRight2D[vec4Index + 2] = right2D.x;
offsetAndRight2D[vec4Index + 3] = right2D.y;
texcoordNormalization2D[vec2Index] = texcoordNormalization2DX * rightPlaneSide;
texcoordNormalization = texcoordNormalization2DY * topBottomSide;
if (texcoordNormalization === 0 && topBottomSide < 0) {
texcoordNormalization = 9;
}
texcoordNormalization2D[vec2Index + 1] = texcoordNormalization;
}
}
const adjustHeightStartBottom = adjustHeightStartBottomScratch;
const adjustHeightEndBottom = adjustHeightEndBottomScratch;
const adjustHeightStartTop = adjustHeightStartTopScratch;
const adjustHeightEndTop = adjustHeightEndTopScratch;
const getHeightsRectangle = Rectangle_default.fromCartographicArray(
getHeightCartographics,
getHeightRectangleScratch
);
const minMaxHeights = ApproximateTerrainHeights_default.getMinimumMaximumHeights(
getHeightsRectangle,
ellipsoid
);
const minHeight = minMaxHeights.minimumTerrainHeight;
const maxHeight = minMaxHeights.maximumTerrainHeight;
sumHeights += Math.abs(minHeight);
sumHeights += Math.abs(maxHeight);
adjustHeights(
startBottom,
startTop,
minHeight,
maxHeight,
adjustHeightStartBottom,
adjustHeightStartTop
);
adjustHeights(
endBottom,
endTop,
minHeight,
maxHeight,
adjustHeightEndBottom,
adjustHeightEndTop
);
let normalNudge = Cartesian3_default.multiplyByScalar(
rightNormal,
Math_default.EPSILON5,
normalNudgeScratch
);
Cartesian3_default.add(
adjustHeightStartBottom,
normalNudge,
adjustHeightStartBottom
);
Cartesian3_default.add(adjustHeightEndBottom, normalNudge, adjustHeightEndBottom);
Cartesian3_default.add(adjustHeightStartTop, normalNudge, adjustHeightStartTop);
Cartesian3_default.add(adjustHeightEndTop, normalNudge, adjustHeightEndTop);
nudgeXZ(adjustHeightStartBottom, adjustHeightEndBottom);
nudgeXZ(adjustHeightStartTop, adjustHeightEndTop);
Cartesian3_default.pack(adjustHeightStartBottom, positionsArray, vec3sWriteIndex);
Cartesian3_default.pack(adjustHeightEndBottom, positionsArray, vec3sWriteIndex + 3);
Cartesian3_default.pack(adjustHeightEndTop, positionsArray, vec3sWriteIndex + 6);
Cartesian3_default.pack(adjustHeightStartTop, positionsArray, vec3sWriteIndex + 9);
normalNudge = Cartesian3_default.multiplyByScalar(
rightNormal,
-2 * Math_default.EPSILON5,
normalNudgeScratch
);
Cartesian3_default.add(
adjustHeightStartBottom,
normalNudge,
adjustHeightStartBottom
);
Cartesian3_default.add(adjustHeightEndBottom, normalNudge, adjustHeightEndBottom);
Cartesian3_default.add(adjustHeightStartTop, normalNudge, adjustHeightStartTop);
Cartesian3_default.add(adjustHeightEndTop, normalNudge, adjustHeightEndTop);
nudgeXZ(adjustHeightStartBottom, adjustHeightEndBottom);
nudgeXZ(adjustHeightStartTop, adjustHeightEndTop);
Cartesian3_default.pack(
adjustHeightStartBottom,
positionsArray,
vec3sWriteIndex + 12
);
Cartesian3_default.pack(
adjustHeightEndBottom,
positionsArray,
vec3sWriteIndex + 15
);
Cartesian3_default.pack(adjustHeightEndTop, positionsArray, vec3sWriteIndex + 18);
Cartesian3_default.pack(adjustHeightStartTop, positionsArray, vec3sWriteIndex + 21);
cartographicsIndex += 2;
index += 3;
vec2sWriteIndex += 16;
vec3sWriteIndex += 24;
vec4sWriteIndex += 32;
lengthSoFar3D += segmentLength3D;
lengthSoFar2D += segmentLength2D;
}
index = 0;
let indexOffset = 0;
for (i = 0; i < segmentCount; i++) {
for (j = 0; j < REFERENCE_INDICES_LENGTH; j++) {
indices[index + j] = REFERENCE_INDICES[j] + indexOffset;
}
indexOffset += 8;
index += REFERENCE_INDICES_LENGTH;
}
const boundingSpheres = scratchBoundingSpheres;
BoundingSphere_default.fromVertices(
bottomPositionsArray,
Cartesian3_default.ZERO,
3,
boundingSpheres[0]
);
BoundingSphere_default.fromVertices(
topPositionsArray,
Cartesian3_default.ZERO,
3,
boundingSpheres[1]
);
const boundingSphere = BoundingSphere_default.fromBoundingSpheres(boundingSpheres);
boundingSphere.radius += sumHeights / (segmentCount * 2);
const attributes = {
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
normalize: false,
values: positionsArray
}),
startHiAndForwardOffsetX: getVec4GeometryAttribute(
startHiAndForwardOffsetX
),
startLoAndForwardOffsetY: getVec4GeometryAttribute(
startLoAndForwardOffsetY
),
startNormalAndForwardOffsetZ: getVec4GeometryAttribute(
startNormalAndForwardOffsetZ
),
endNormalAndTextureCoordinateNormalizationX: getVec4GeometryAttribute(
endNormalAndTextureCoordinateNormalizationX
),
rightNormalAndTextureCoordinateNormalizationY: getVec4GeometryAttribute(
rightNormalAndTextureCoordinateNormalizationY
)
};
if (compute2dAttributes) {
attributes.startHiLo2D = getVec4GeometryAttribute(startHiLo2D);
attributes.offsetAndRight2D = getVec4GeometryAttribute(offsetAndRight2D);
attributes.startEndNormals2D = getVec4GeometryAttribute(startEndNormals2D);
attributes.texcoordNormalization2D = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
normalize: false,
values: texcoordNormalization2D
});
}
return new Geometry_default({
attributes,
indices,
boundingSphere
});
}
function getVec4GeometryAttribute(typedArray) {
return new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 4,
normalize: false,
values: typedArray
});
}
GroundPolylineGeometry._projectNormal = projectNormal;
var GroundPolylineGeometry_default = GroundPolylineGeometry;
// packages/engine/Source/Shaders/PolylineShadowVolumeFS.js
var import_InlineWorkers380 = __toESM(require_InlineWorkers(), 1);
var PolylineShadowVolumeFS_default = 'in vec4 v_startPlaneNormalEcAndHalfWidth;\nin vec4 v_endPlaneNormalEcAndBatchId;\nin vec4 v_rightPlaneEC; // Technically can compute distance for this here\nin vec4 v_endEcAndStartEcX;\nin vec4 v_texcoordNormalizationAndStartEcYZ;\n\n#ifdef PER_INSTANCE_COLOR\nin vec4 v_color;\n#endif\n\nvoid main(void)\n{\n float logDepthOrDepth = czm_branchFreeTernary(czm_sceneMode == czm_sceneMode2D, gl_FragCoord.z, czm_unpackDepth(texture(czm_globeDepthTexture, gl_FragCoord.xy / czm_viewport.zw)));\n vec3 ecStart = vec3(v_endEcAndStartEcX.w, v_texcoordNormalizationAndStartEcYZ.zw);\n\n // Discard for sky\n if (logDepthOrDepth == 0.0) {\n#ifdef DEBUG_SHOW_VOLUME\n out_FragColor = vec4(1.0, 0.0, 0.0, 0.5);\n return;\n#else // DEBUG_SHOW_VOLUME\n discard;\n#endif // DEBUG_SHOW_VOLUME\n }\n\n vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth);\n eyeCoordinate /= eyeCoordinate.w;\n\n float halfMaxWidth = v_startPlaneNormalEcAndHalfWidth.w * czm_metersPerPixel(eyeCoordinate);\n // Check distance of the eye coordinate against the right-facing plane\n float widthwiseDistance = czm_planeDistance(v_rightPlaneEC, eyeCoordinate.xyz);\n\n // Check eye coordinate against the mitering planes\n float distanceFromStart = czm_planeDistance(v_startPlaneNormalEcAndHalfWidth.xyz, -dot(ecStart, v_startPlaneNormalEcAndHalfWidth.xyz), eyeCoordinate.xyz);\n float distanceFromEnd = czm_planeDistance(v_endPlaneNormalEcAndBatchId.xyz, -dot(v_endEcAndStartEcX.xyz, v_endPlaneNormalEcAndBatchId.xyz), eyeCoordinate.xyz);\n\n if (abs(widthwiseDistance) > halfMaxWidth || distanceFromStart < 0.0 || distanceFromEnd < 0.0) {\n#ifdef DEBUG_SHOW_VOLUME\n out_FragColor = vec4(1.0, 0.0, 0.0, 0.5);\n return;\n#else // DEBUG_SHOW_VOLUME\n discard;\n#endif // DEBUG_SHOW_VOLUME\n }\n\n // Check distance of the eye coordinate against start and end planes with normals in the right plane.\n // For computing unskewed lengthwise texture coordinate.\n // Can also be used for clipping extremely pointy miters, but in practice unnecessary because of miter breaking.\n\n // aligned plane: cross the right plane normal with miter plane normal, then cross the result with right again to point it more "forward"\n vec3 alignedPlaneNormal;\n\n // start aligned plane\n alignedPlaneNormal = cross(v_rightPlaneEC.xyz, v_startPlaneNormalEcAndHalfWidth.xyz);\n alignedPlaneNormal = normalize(cross(alignedPlaneNormal, v_rightPlaneEC.xyz));\n distanceFromStart = czm_planeDistance(alignedPlaneNormal, -dot(alignedPlaneNormal, ecStart), eyeCoordinate.xyz);\n\n // end aligned plane\n alignedPlaneNormal = cross(v_rightPlaneEC.xyz, v_endPlaneNormalEcAndBatchId.xyz);\n alignedPlaneNormal = normalize(cross(alignedPlaneNormal, v_rightPlaneEC.xyz));\n distanceFromEnd = czm_planeDistance(alignedPlaneNormal, -dot(alignedPlaneNormal, v_endEcAndStartEcX.xyz), eyeCoordinate.xyz);\n\n#ifdef PER_INSTANCE_COLOR\n out_FragColor = czm_gammaCorrect(v_color);\n#else // PER_INSTANCE_COLOR\n // Clamp - distance to aligned planes may be negative due to mitering,\n // so fragment texture coordinate might be out-of-bounds.\n float s = clamp(distanceFromStart / (distanceFromStart + distanceFromEnd), 0.0, 1.0);\n s = (s * v_texcoordNormalizationAndStartEcYZ.x) + v_texcoordNormalizationAndStartEcYZ.y;\n float t = (widthwiseDistance + halfMaxWidth) / (2.0 * halfMaxWidth);\n\n czm_materialInput materialInput;\n\n materialInput.s = s;\n materialInput.st = vec2(s, t);\n materialInput.str = vec3(s, t, 0.0);\n\n czm_material material = czm_getMaterial(materialInput);\n out_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n#endif // PER_INSTANCE_COLOR\n\n // Premultiply alpha. Required for classification primitives on translucent globe.\n out_FragColor.rgb *= out_FragColor.a;\n\n czm_writeDepthClamp();\n}\n';
// packages/engine/Source/Shaders/PolylineShadowVolumeMorphFS.js
var import_InlineWorkers381 = __toESM(require_InlineWorkers(), 1);
var PolylineShadowVolumeMorphFS_default = "in vec3 v_forwardDirectionEC;\nin vec3 v_texcoordNormalizationAndHalfWidth;\nin float v_batchId;\n\n#ifdef PER_INSTANCE_COLOR\nin vec4 v_color;\n#else\nin vec2 v_alignedPlaneDistances;\nin float v_texcoordT;\n#endif\n\nfloat rayPlaneDistanceUnsafe(vec3 origin, vec3 direction, vec3 planeNormal, float planeDistance) {\n // We don't expect the ray to ever be parallel to the plane\n return (-planeDistance - dot(planeNormal, origin)) / dot(planeNormal, direction);\n}\n\nvoid main(void)\n{\n vec4 eyeCoordinate = gl_FragCoord;\n eyeCoordinate /= eyeCoordinate.w;\n\n#ifdef PER_INSTANCE_COLOR\n out_FragColor = czm_gammaCorrect(v_color);\n#else // PER_INSTANCE_COLOR\n // Use distances for planes aligned with segment to prevent skew in dashing\n float distanceFromStart = rayPlaneDistanceUnsafe(eyeCoordinate.xyz, -v_forwardDirectionEC, v_forwardDirectionEC.xyz, v_alignedPlaneDistances.x);\n float distanceFromEnd = rayPlaneDistanceUnsafe(eyeCoordinate.xyz, v_forwardDirectionEC, -v_forwardDirectionEC.xyz, v_alignedPlaneDistances.y);\n\n // Clamp - distance to aligned planes may be negative due to mitering\n distanceFromStart = max(0.0, distanceFromStart);\n distanceFromEnd = max(0.0, distanceFromEnd);\n\n float s = distanceFromStart / (distanceFromStart + distanceFromEnd);\n s = (s * v_texcoordNormalizationAndHalfWidth.x) + v_texcoordNormalizationAndHalfWidth.y;\n\n czm_materialInput materialInput;\n\n materialInput.s = s;\n materialInput.st = vec2(s, v_texcoordT);\n materialInput.str = vec3(s, v_texcoordT, 0.0);\n\n czm_material material = czm_getMaterial(materialInput);\n out_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n#endif // PER_INSTANCE_COLOR\n}\n";
// packages/engine/Source/Shaders/PolylineShadowVolumeMorphVS.js
var import_InlineWorkers382 = __toESM(require_InlineWorkers(), 1);
var PolylineShadowVolumeMorphVS_default = `in vec3 position3DHigh;
in vec3 position3DLow;
in vec4 startHiAndForwardOffsetX;
in vec4 startLoAndForwardOffsetY;
in vec4 startNormalAndForwardOffsetZ;
in vec4 endNormalAndTextureCoordinateNormalizationX;
in vec4 rightNormalAndTextureCoordinateNormalizationY;
in vec4 startHiLo2D;
in vec4 offsetAndRight2D;
in vec4 startEndNormals2D;
in vec2 texcoordNormalization2D;
in float batchId;
out vec3 v_forwardDirectionEC;
out vec3 v_texcoordNormalizationAndHalfWidth;
out float v_batchId;
// For materials
#ifdef WIDTH_VARYING
out float v_width;
#endif
#ifdef ANGLE_VARYING
out float v_polylineAngle;
#endif
#ifdef PER_INSTANCE_COLOR
out vec4 v_color;
#else
out vec2 v_alignedPlaneDistances;
out float v_texcoordT;
#endif
// Morphing planes using SLERP or NLERP doesn't seem to work, so instead draw the material directly on the shadow volume.
// Morph views are from very far away and aren't meant to be used precisely, so this should be sufficient.
void main()
{
v_batchId = batchId;
// Start position
vec4 posRelativeToEye2D = czm_translateRelativeToEye(vec3(0.0, startHiLo2D.xy), vec3(0.0, startHiLo2D.zw));
vec4 posRelativeToEye3D = czm_translateRelativeToEye(startHiAndForwardOffsetX.xyz, startLoAndForwardOffsetY.xyz);
vec4 posRelativeToEye = czm_columbusViewMorph(posRelativeToEye2D, posRelativeToEye3D, czm_morphTime);
vec3 posEc2D = (czm_modelViewRelativeToEye * posRelativeToEye2D).xyz;
vec3 posEc3D = (czm_modelViewRelativeToEye * posRelativeToEye3D).xyz;
vec3 startEC = (czm_modelViewRelativeToEye * posRelativeToEye).xyz;
// Start plane
vec4 startPlane2D;
vec4 startPlane3D;
startPlane2D.xyz = czm_normal * vec3(0.0, startEndNormals2D.xy);
startPlane3D.xyz = czm_normal * startNormalAndForwardOffsetZ.xyz;
startPlane2D.w = -dot(startPlane2D.xyz, posEc2D);
startPlane3D.w = -dot(startPlane3D.xyz, posEc3D);
// Right plane
vec4 rightPlane2D;
vec4 rightPlane3D;
rightPlane2D.xyz = czm_normal * vec3(0.0, offsetAndRight2D.zw);
rightPlane3D.xyz = czm_normal * rightNormalAndTextureCoordinateNormalizationY.xyz;
rightPlane2D.w = -dot(rightPlane2D.xyz, posEc2D);
rightPlane3D.w = -dot(rightPlane3D.xyz, posEc3D);
// End position
posRelativeToEye2D = posRelativeToEye2D + vec4(0.0, offsetAndRight2D.xy, 0.0);
posRelativeToEye3D = posRelativeToEye3D + vec4(startHiAndForwardOffsetX.w, startLoAndForwardOffsetY.w, startNormalAndForwardOffsetZ.w, 0.0);
posRelativeToEye = czm_columbusViewMorph(posRelativeToEye2D, posRelativeToEye3D, czm_morphTime);
posEc2D = (czm_modelViewRelativeToEye * posRelativeToEye2D).xyz;
posEc3D = (czm_modelViewRelativeToEye * posRelativeToEye3D).xyz;
vec3 endEC = (czm_modelViewRelativeToEye * posRelativeToEye).xyz;
vec3 forwardEc3D = czm_normal * normalize(vec3(startHiAndForwardOffsetX.w, startLoAndForwardOffsetY.w, startNormalAndForwardOffsetZ.w));
vec3 forwardEc2D = czm_normal * normalize(vec3(0.0, offsetAndRight2D.xy));
// End plane
vec4 endPlane2D;
vec4 endPlane3D;
endPlane2D.xyz = czm_normal * vec3(0.0, startEndNormals2D.zw);
endPlane3D.xyz = czm_normal * endNormalAndTextureCoordinateNormalizationX.xyz;
endPlane2D.w = -dot(endPlane2D.xyz, posEc2D);
endPlane3D.w = -dot(endPlane3D.xyz, posEc3D);
// Forward direction
v_forwardDirectionEC = normalize(endEC - startEC);
vec2 cleanTexcoordNormalization2D;
cleanTexcoordNormalization2D.x = abs(texcoordNormalization2D.x);
cleanTexcoordNormalization2D.y = czm_branchFreeTernary(texcoordNormalization2D.y > 1.0, 0.0, abs(texcoordNormalization2D.y));
vec2 cleanTexcoordNormalization3D;
cleanTexcoordNormalization3D.x = abs(endNormalAndTextureCoordinateNormalizationX.w);
cleanTexcoordNormalization3D.y = rightNormalAndTextureCoordinateNormalizationY.w;
cleanTexcoordNormalization3D.y = czm_branchFreeTernary(cleanTexcoordNormalization3D.y > 1.0, 0.0, abs(cleanTexcoordNormalization3D.y));
v_texcoordNormalizationAndHalfWidth.xy = mix(cleanTexcoordNormalization2D, cleanTexcoordNormalization3D, czm_morphTime);
#ifdef PER_INSTANCE_COLOR
v_color = czm_batchTable_color(batchId);
#else // PER_INSTANCE_COLOR
// For computing texture coordinates
v_alignedPlaneDistances.x = -dot(v_forwardDirectionEC, startEC);
v_alignedPlaneDistances.y = -dot(-v_forwardDirectionEC, endEC);
#endif // PER_INSTANCE_COLOR
#ifdef WIDTH_VARYING
float width = czm_batchTable_width(batchId);
float halfWidth = width * 0.5;
v_width = width;
v_texcoordNormalizationAndHalfWidth.z = halfWidth;
#else
float halfWidth = 0.5 * czm_batchTable_width(batchId);
v_texcoordNormalizationAndHalfWidth.z = halfWidth;
#endif
// Compute a normal along which to "push" the position out, extending the miter depending on view distance.
// Position has already been "pushed" by unit length along miter normal, and miter normals are encoded in the planes.
// Decode the normal to use at this specific vertex, push the position back, and then push to where it needs to be.
// Since this is morphing, compute both 3D and 2D positions and then blend.
// ****** 3D ******
// Check distance to the end plane and start plane, pick the plane that is closer
vec4 positionEc3D = czm_modelViewRelativeToEye * czm_translateRelativeToEye(position3DHigh, position3DLow); // w = 1.0, see czm_computePosition
float absStartPlaneDistance = abs(czm_planeDistance(startPlane3D, positionEc3D.xyz));
float absEndPlaneDistance = abs(czm_planeDistance(endPlane3D, positionEc3D.xyz));
vec3 planeDirection = czm_branchFreeTernary(absStartPlaneDistance < absEndPlaneDistance, startPlane3D.xyz, endPlane3D.xyz);
vec3 upOrDown = normalize(cross(rightPlane3D.xyz, planeDirection)); // Points "up" for start plane, "down" at end plane.
vec3 normalEC = normalize(cross(planeDirection, upOrDown)); // In practice, the opposite seems to work too.
// Nudge the top vertex upwards to prevent flickering
vec3 geodeticSurfaceNormal = normalize(cross(normalEC, forwardEc3D));
geodeticSurfaceNormal *= float(0.0 <= rightNormalAndTextureCoordinateNormalizationY.w && rightNormalAndTextureCoordinateNormalizationY.w <= 1.0);
geodeticSurfaceNormal *= MAX_TERRAIN_HEIGHT;
positionEc3D.xyz += geodeticSurfaceNormal;
// Determine if this vertex is on the "left" or "right"
normalEC *= sign(endNormalAndTextureCoordinateNormalizationX.w);
// A "perfect" implementation would push along normals according to the angle against forward.
// In practice, just pushing the normal out by halfWidth is sufficient for morph views.
positionEc3D.xyz += halfWidth * max(0.0, czm_metersPerPixel(positionEc3D)) * normalEC; // prevent artifacts when czm_metersPerPixel is negative (behind camera)
// ****** 2D ******
// Check distance to the end plane and start plane, pick the plane that is closer
vec4 positionEc2D = czm_modelViewRelativeToEye * czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy); // w = 1.0, see czm_computePosition
absStartPlaneDistance = abs(czm_planeDistance(startPlane2D, positionEc2D.xyz));
absEndPlaneDistance = abs(czm_planeDistance(endPlane2D, positionEc2D.xyz));
planeDirection = czm_branchFreeTernary(absStartPlaneDistance < absEndPlaneDistance, startPlane2D.xyz, endPlane2D.xyz);
upOrDown = normalize(cross(rightPlane2D.xyz, planeDirection)); // Points "up" for start plane, "down" at end plane.
normalEC = normalize(cross(planeDirection, upOrDown)); // In practice, the opposite seems to work too.
// Nudge the top vertex upwards to prevent flickering
geodeticSurfaceNormal = normalize(cross(normalEC, forwardEc2D));
geodeticSurfaceNormal *= float(0.0 <= texcoordNormalization2D.y && texcoordNormalization2D.y <= 1.0);
geodeticSurfaceNormal *= MAX_TERRAIN_HEIGHT;
positionEc2D.xyz += geodeticSurfaceNormal;
// Determine if this vertex is on the "left" or "right"
normalEC *= sign(texcoordNormalization2D.x);
#ifndef PER_INSTANCE_COLOR
// Use vertex's sidedness to compute its texture coordinate.
v_texcoordT = clamp(sign(texcoordNormalization2D.x), 0.0, 1.0);
#endif
// A "perfect" implementation would push along normals according to the angle against forward.
// In practice, just pushing the normal out by halfWidth is sufficient for morph views.
positionEc2D.xyz += halfWidth * max(0.0, czm_metersPerPixel(positionEc2D)) * normalEC; // prevent artifacts when czm_metersPerPixel is negative (behind camera)
// Blend for actual position
gl_Position = czm_projection * mix(positionEc2D, positionEc3D, czm_morphTime);
#ifdef ANGLE_VARYING
// Approximate relative screen space direction of the line.
vec2 approxLineDirection = normalize(vec2(v_forwardDirectionEC.x, -v_forwardDirectionEC.y));
approxLineDirection.y = czm_branchFreeTernary(approxLineDirection.x == 0.0 && approxLineDirection.y == 0.0, -1.0, approxLineDirection.y);
v_polylineAngle = czm_fastApproximateAtan(approxLineDirection.x, approxLineDirection.y);
#endif
}
`;
// packages/engine/Source/Shaders/PolylineShadowVolumeVS.js
var import_InlineWorkers383 = __toESM(require_InlineWorkers(), 1);
var PolylineShadowVolumeVS_default = 'in vec3 position3DHigh;\nin vec3 position3DLow;\n\n// In 2D and in 3D, texture coordinate normalization component signs encodes:\n// * X sign - sidedness relative to right plane\n// * Y sign - is negative OR magnitude is greater than 1.0 if vertex is on bottom of volume\n#ifndef COLUMBUS_VIEW_2D\nin vec4 startHiAndForwardOffsetX;\nin vec4 startLoAndForwardOffsetY;\nin vec4 startNormalAndForwardOffsetZ;\nin vec4 endNormalAndTextureCoordinateNormalizationX;\nin vec4 rightNormalAndTextureCoordinateNormalizationY;\n#else\nin vec4 startHiLo2D;\nin vec4 offsetAndRight2D;\nin vec4 startEndNormals2D;\nin vec2 texcoordNormalization2D;\n#endif\n\nin float batchId;\n\nout vec4 v_startPlaneNormalEcAndHalfWidth;\nout vec4 v_endPlaneNormalEcAndBatchId;\nout vec4 v_rightPlaneEC;\nout vec4 v_endEcAndStartEcX;\nout vec4 v_texcoordNormalizationAndStartEcYZ;\n\n// For materials\n#ifdef WIDTH_VARYING\nout float v_width;\n#endif\n#ifdef ANGLE_VARYING\nout float v_polylineAngle;\n#endif\n\n#ifdef PER_INSTANCE_COLOR\nout vec4 v_color;\n#endif\n\nvoid main()\n{\n#ifdef COLUMBUS_VIEW_2D\n vec3 ecStart = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, startHiLo2D.xy), vec3(0.0, startHiLo2D.zw))).xyz;\n\n vec3 forwardDirectionEC = czm_normal * vec3(0.0, offsetAndRight2D.xy);\n vec3 ecEnd = forwardDirectionEC + ecStart;\n forwardDirectionEC = normalize(forwardDirectionEC);\n\n // Right plane\n v_rightPlaneEC.xyz = czm_normal * vec3(0.0, offsetAndRight2D.zw);\n v_rightPlaneEC.w = -dot(v_rightPlaneEC.xyz, ecStart);\n\n // start plane\n vec4 startPlaneEC;\n startPlaneEC.xyz = czm_normal * vec3(0.0, startEndNormals2D.xy);\n startPlaneEC.w = -dot(startPlaneEC.xyz, ecStart);\n\n // end plane\n vec4 endPlaneEC;\n endPlaneEC.xyz = czm_normal * vec3(0.0, startEndNormals2D.zw);\n endPlaneEC.w = -dot(endPlaneEC.xyz, ecEnd);\n\n v_texcoordNormalizationAndStartEcYZ.x = abs(texcoordNormalization2D.x);\n v_texcoordNormalizationAndStartEcYZ.y = texcoordNormalization2D.y;\n\n#else // COLUMBUS_VIEW_2D\n vec3 ecStart = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(startHiAndForwardOffsetX.xyz, startLoAndForwardOffsetY.xyz)).xyz;\n vec3 offset = czm_normal * vec3(startHiAndForwardOffsetX.w, startLoAndForwardOffsetY.w, startNormalAndForwardOffsetZ.w);\n vec3 ecEnd = ecStart + offset;\n\n vec3 forwardDirectionEC = normalize(offset);\n\n // start plane\n vec4 startPlaneEC;\n startPlaneEC.xyz = czm_normal * startNormalAndForwardOffsetZ.xyz;\n startPlaneEC.w = -dot(startPlaneEC.xyz, ecStart);\n\n // end plane\n vec4 endPlaneEC;\n endPlaneEC.xyz = czm_normal * endNormalAndTextureCoordinateNormalizationX.xyz;\n endPlaneEC.w = -dot(endPlaneEC.xyz, ecEnd);\n\n // Right plane\n v_rightPlaneEC.xyz = czm_normal * rightNormalAndTextureCoordinateNormalizationY.xyz;\n v_rightPlaneEC.w = -dot(v_rightPlaneEC.xyz, ecStart);\n\n v_texcoordNormalizationAndStartEcYZ.x = abs(endNormalAndTextureCoordinateNormalizationX.w);\n v_texcoordNormalizationAndStartEcYZ.y = rightNormalAndTextureCoordinateNormalizationY.w;\n\n#endif // COLUMBUS_VIEW_2D\n\n v_endEcAndStartEcX.xyz = ecEnd;\n v_endEcAndStartEcX.w = ecStart.x;\n v_texcoordNormalizationAndStartEcYZ.zw = ecStart.yz;\n\n#ifdef PER_INSTANCE_COLOR\n v_color = czm_batchTable_color(batchId);\n#endif // PER_INSTANCE_COLOR\n\n // Compute a normal along which to "push" the position out, extending the miter depending on view distance.\n // Position has already been "pushed" by unit length along miter normal, and miter normals are encoded in the planes.\n // Decode the normal to use at this specific vertex, push the position back, and then push to where it needs to be.\n vec4 positionRelativeToEye = czm_computePosition();\n\n // Check distance to the end plane and start plane, pick the plane that is closer\n vec4 positionEC = czm_modelViewRelativeToEye * positionRelativeToEye; // w = 1.0, see czm_computePosition\n float absStartPlaneDistance = abs(czm_planeDistance(startPlaneEC, positionEC.xyz));\n float absEndPlaneDistance = abs(czm_planeDistance(endPlaneEC, positionEC.xyz));\n vec3 planeDirection = czm_branchFreeTernary(absStartPlaneDistance < absEndPlaneDistance, startPlaneEC.xyz, endPlaneEC.xyz);\n vec3 upOrDown = normalize(cross(v_rightPlaneEC.xyz, planeDirection)); // Points "up" for start plane, "down" at end plane.\n vec3 normalEC = normalize(cross(planeDirection, upOrDown)); // In practice, the opposite seems to work too.\n\n // Extrude bottom vertices downward for far view distances, like for GroundPrimitives\n upOrDown = cross(forwardDirectionEC, normalEC);\n upOrDown = float(czm_sceneMode == czm_sceneMode3D) * upOrDown;\n upOrDown = float(v_texcoordNormalizationAndStartEcYZ.y > 1.0 || v_texcoordNormalizationAndStartEcYZ.y < 0.0) * upOrDown;\n upOrDown = min(GLOBE_MINIMUM_ALTITUDE, czm_geometricToleranceOverMeter * length(positionRelativeToEye.xyz)) * upOrDown;\n positionEC.xyz += upOrDown;\n\n v_texcoordNormalizationAndStartEcYZ.y = czm_branchFreeTernary(v_texcoordNormalizationAndStartEcYZ.y > 1.0, 0.0, abs(v_texcoordNormalizationAndStartEcYZ.y));\n\n // Determine distance along normalEC to push for a volume of appropriate width.\n // Make volumes about double pixel width for a conservative fit - in practice the\n // extra cost here is minimal compared to the loose volume heights.\n //\n // N = normalEC (guaranteed "right-facing")\n // R = rightEC\n // p = angle between N and R\n // w = distance to push along R if R == N\n // d = distance to push along N\n //\n // N R\n // { p| } * cos(p) = dot(N, R) = w / d\n // d | |w * d = w / dot(N, R)\n // { | }\n // o---------- polyline segment ---->\n //\n float width = czm_batchTable_width(batchId);\n#ifdef WIDTH_VARYING\n v_width = width;\n#endif\n\n v_startPlaneNormalEcAndHalfWidth.xyz = startPlaneEC.xyz;\n v_startPlaneNormalEcAndHalfWidth.w = width * 0.5;\n\n v_endPlaneNormalEcAndBatchId.xyz = endPlaneEC.xyz;\n v_endPlaneNormalEcAndBatchId.w = batchId;\n\n width = width * max(0.0, czm_metersPerPixel(positionEC)); // width = distance to push along R\n width = width / dot(normalEC, v_rightPlaneEC.xyz); // width = distance to push along N\n\n // Determine if this vertex is on the "left" or "right"\n#ifdef COLUMBUS_VIEW_2D\n normalEC *= sign(texcoordNormalization2D.x);\n#else\n normalEC *= sign(endNormalAndTextureCoordinateNormalizationX.w);\n#endif\n\n positionEC.xyz += width * normalEC;\n gl_Position = czm_depthClamp(czm_projection * positionEC);\n\n#ifdef ANGLE_VARYING\n // Approximate relative screen space direction of the line.\n vec2 approxLineDirection = normalize(vec2(forwardDirectionEC.x, -forwardDirectionEC.y));\n approxLineDirection.y = czm_branchFreeTernary(approxLineDirection.x == 0.0 && approxLineDirection.y == 0.0, -1.0, approxLineDirection.y);\n v_polylineAngle = czm_fastApproximateAtan(approxLineDirection.x, approxLineDirection.y);\n#endif\n}\n';
// packages/engine/Source/Scene/PolylineColorAppearance.js
var import_InlineWorkers386 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Appearances/PolylineColorAppearanceVS.js
var import_InlineWorkers384 = __toESM(require_InlineWorkers(), 1);
var PolylineColorAppearanceVS_default = "in vec3 position3DHigh;\nin vec3 position3DLow;\nin vec3 prevPosition3DHigh;\nin vec3 prevPosition3DLow;\nin vec3 nextPosition3DHigh;\nin vec3 nextPosition3DLow;\nin vec2 expandAndWidth;\nin vec4 color;\nin float batchId;\n\nout vec4 v_color;\n\nvoid main()\n{\n float expandDir = expandAndWidth.x;\n float width = abs(expandAndWidth.y) + 0.5;\n bool usePrev = expandAndWidth.y < 0.0;\n\n vec4 p = czm_computePosition();\n vec4 prev = czm_computePrevPosition();\n vec4 next = czm_computeNextPosition();\n\n float angle;\n vec4 positionWC = getPolylineWindowCoordinates(p, prev, next, expandDir, width, usePrev, angle);\n gl_Position = czm_viewportOrthographic * positionWC;\n\n v_color = color;\n}\n";
// packages/engine/Source/Shaders/PolylineCommon.js
var import_InlineWorkers385 = __toESM(require_InlineWorkers(), 1);
var PolylineCommon_default = "void clipLineSegmentToNearPlane(\n vec3 p0,\n vec3 p1,\n out vec4 positionWC,\n out bool clipped,\n out bool culledByNearPlane,\n out vec4 clippedPositionEC)\n{\n culledByNearPlane = false;\n clipped = false;\n\n vec3 p0ToP1 = p1 - p0;\n float magnitude = length(p0ToP1);\n vec3 direction = normalize(p0ToP1);\n\n // Distance that p0 is behind the near plane. Negative means p0 is\n // in front of the near plane.\n float endPoint0Distance = czm_currentFrustum.x + p0.z;\n\n // Camera looks down -Z.\n // When moving a point along +Z: LESS VISIBLE\n // * Points in front of the camera move closer to the camera.\n // * Points behind the camrea move farther away from the camera.\n // When moving a point along -Z: MORE VISIBLE\n // * Points in front of the camera move farther away from the camera.\n // * Points behind the camera move closer to the camera.\n\n // Positive denominator: -Z, becoming more visible\n // Negative denominator: +Z, becoming less visible\n // Nearly zero: parallel to near plane\n float denominator = -direction.z;\n\n if (endPoint0Distance > 0.0 && abs(denominator) < czm_epsilon7)\n {\n // p0 is behind the near plane and the line to p1 is nearly parallel to\n // the near plane, so cull the segment completely.\n culledByNearPlane = true;\n }\n else if (endPoint0Distance > 0.0)\n {\n // p0 is behind the near plane, and the line to p1 is moving distinctly\n // toward or away from it.\n\n // t = (-plane distance - dot(plane normal, ray origin)) / dot(plane normal, ray direction)\n float t = endPoint0Distance / denominator;\n if (t < 0.0 || t > magnitude)\n {\n // Near plane intersection is not between the two points.\n // We already confirmed p0 is behind the naer plane, so now\n // we know the entire segment is behind it.\n culledByNearPlane = true;\n }\n else\n {\n // Segment crosses the near plane, update p0 to lie exactly on it.\n p0 = p0 + t * direction;\n\n // Numerical noise might put us a bit on the wrong side of the near plane.\n // Don't let that happen.\n p0.z = min(p0.z, -czm_currentFrustum.x);\n\n clipped = true;\n }\n }\n\n clippedPositionEC = vec4(p0, 1.0);\n positionWC = czm_eyeToWindowCoordinates(clippedPositionEC);\n}\n\nvec4 getPolylineWindowCoordinatesEC(vec4 positionEC, vec4 prevEC, vec4 nextEC, float expandDirection, float width, bool usePrevious, out float angle)\n{\n // expandDirection +1 is to the _left_ when looking from positionEC toward nextEC.\n\n#ifdef POLYLINE_DASH\n // Compute the window coordinates of the points.\n vec4 positionWindow = czm_eyeToWindowCoordinates(positionEC);\n vec4 previousWindow = czm_eyeToWindowCoordinates(prevEC);\n vec4 nextWindow = czm_eyeToWindowCoordinates(nextEC);\n\n // Determine the relative screen space direction of the line.\n vec2 lineDir;\n if (usePrevious) {\n lineDir = normalize(positionWindow.xy - previousWindow.xy);\n }\n else {\n lineDir = normalize(nextWindow.xy - positionWindow.xy);\n }\n angle = atan(lineDir.x, lineDir.y) - 1.570796327; // precomputed atan(1,0)\n\n // Quantize the angle so it doesn't change rapidly between segments.\n angle = floor(angle / czm_piOverFour + 0.5) * czm_piOverFour;\n#endif\n\n vec4 clippedPrevWC, clippedPrevEC;\n bool prevSegmentClipped, prevSegmentCulled;\n clipLineSegmentToNearPlane(prevEC.xyz, positionEC.xyz, clippedPrevWC, prevSegmentClipped, prevSegmentCulled, clippedPrevEC);\n\n vec4 clippedNextWC, clippedNextEC;\n bool nextSegmentClipped, nextSegmentCulled;\n clipLineSegmentToNearPlane(nextEC.xyz, positionEC.xyz, clippedNextWC, nextSegmentClipped, nextSegmentCulled, clippedNextEC);\n\n bool segmentClipped, segmentCulled;\n vec4 clippedPositionWC, clippedPositionEC;\n clipLineSegmentToNearPlane(positionEC.xyz, usePrevious ? prevEC.xyz : nextEC.xyz, clippedPositionWC, segmentClipped, segmentCulled, clippedPositionEC);\n\n if (segmentCulled)\n {\n return vec4(0.0, 0.0, 0.0, 1.0);\n }\n\n vec2 directionToPrevWC = normalize(clippedPrevWC.xy - clippedPositionWC.xy);\n vec2 directionToNextWC = normalize(clippedNextWC.xy - clippedPositionWC.xy);\n\n // If a segment was culled, we can't use the corresponding direction\n // computed above. We should never see both of these be true without\n // `segmentCulled` above also being true.\n if (prevSegmentCulled)\n {\n directionToPrevWC = -directionToNextWC;\n }\n else if (nextSegmentCulled)\n {\n directionToNextWC = -directionToPrevWC;\n }\n\n vec2 thisSegmentForwardWC, otherSegmentForwardWC;\n if (usePrevious)\n {\n thisSegmentForwardWC = -directionToPrevWC;\n otherSegmentForwardWC = directionToNextWC;\n }\n else\n {\n thisSegmentForwardWC = directionToNextWC;\n otherSegmentForwardWC = -directionToPrevWC;\n }\n\n vec2 thisSegmentLeftWC = vec2(-thisSegmentForwardWC.y, thisSegmentForwardWC.x);\n\n vec2 leftWC = thisSegmentLeftWC;\n float expandWidth = width * 0.5;\n\n // When lines are split at the anti-meridian, the position may be at the\n // same location as the next or previous position, and we need to handle\n // that to avoid producing NaNs.\n if (!czm_equalsEpsilon(prevEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1) && !czm_equalsEpsilon(nextEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1))\n {\n vec2 otherSegmentLeftWC = vec2(-otherSegmentForwardWC.y, otherSegmentForwardWC.x);\n\n vec2 leftSumWC = thisSegmentLeftWC + otherSegmentLeftWC;\n float leftSumLength = length(leftSumWC);\n leftWC = leftSumLength < czm_epsilon6 ? thisSegmentLeftWC : (leftSumWC / leftSumLength);\n\n // The sine of the angle between the two vectors is given by the formula\n // |a x b| = |a||b|sin(theta)\n // which is\n // float sinAngle = length(cross(vec3(leftWC, 0.0), vec3(-thisSegmentForwardWC, 0.0)));\n // Because the z components of both vectors are zero, the x and y coordinate will be zero.\n // Therefore, the sine of the angle is just the z component of the cross product.\n vec2 u = -thisSegmentForwardWC;\n vec2 v = leftWC;\n float sinAngle = abs(u.x * v.y - u.y * v.x);\n expandWidth = clamp(expandWidth / sinAngle, 0.0, width * 2.0);\n }\n\n vec2 offset = leftWC * expandDirection * expandWidth * czm_pixelRatio;\n return vec4(clippedPositionWC.xy + offset, -clippedPositionWC.z, 1.0) * (czm_projection * clippedPositionEC).w;\n}\n\nvec4 getPolylineWindowCoordinates(vec4 position, vec4 previous, vec4 next, float expandDirection, float width, bool usePrevious, out float angle)\n{\n vec4 positionEC = czm_modelViewRelativeToEye * position;\n vec4 prevEC = czm_modelViewRelativeToEye * previous;\n vec4 nextEC = czm_modelViewRelativeToEye * next;\n return getPolylineWindowCoordinatesEC(positionEC, prevEC, nextEC, expandDirection, width, usePrevious, angle);\n}\n";
// packages/engine/Source/Scene/PolylineColorAppearance.js
var defaultVertexShaderSource = `${PolylineCommon_default}
${PolylineColorAppearanceVS_default}`;
var defaultFragmentShaderSource = PerInstanceFlatColorAppearanceFS_default;
if (!FeatureDetection_default.isInternetExplorer()) {
defaultVertexShaderSource = `#define CLIP_POLYLINE
${defaultVertexShaderSource}`;
}
function PolylineColorAppearance(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const translucent = options.translucent ?? true;
const closed = false;
const vertexFormat = PolylineColorAppearance.VERTEX_FORMAT;
this.material = void 0;
this.translucent = translucent;
this._vertexShaderSource = options.vertexShaderSource ?? defaultVertexShaderSource;
this._fragmentShaderSource = options.fragmentShaderSource ?? defaultFragmentShaderSource;
this._renderState = Appearance_default.getDefaultRenderState(
translucent,
closed,
options.renderState
);
this._closed = closed;
this._vertexFormat = vertexFormat;
}
Object.defineProperties(PolylineColorAppearance.prototype, {
/**
* The GLSL source code for the vertex shader.
*
* @memberof PolylineColorAppearance.prototype
*
* @type {string}
* @readonly
*/
vertexShaderSource: {
get: function() {
return this._vertexShaderSource;
}
},
/**
* The GLSL source code for the fragment shader.
*
* @memberof PolylineColorAppearance.prototype
*
* @type {string}
* @readonly
*/
fragmentShaderSource: {
get: function() {
return this._fragmentShaderSource;
}
},
/**
* The WebGL fixed-function state to use when rendering the geometry.
* * The render state can be explicitly defined when constructing a {@link PolylineColorAppearance} * instance, or it is set implicitly via {@link PolylineColorAppearance#translucent}. *
* * @memberof PolylineColorAppearance.prototype * * @type {object} * @readonly */ renderState: { get: function() { return this._renderState; } }, /** * Whentrue, the geometry is expected to be closed so
* {@link PolylineColorAppearance#renderState} has backface culling enabled.
* This is always false for PolylineColorAppearance.
*
* @memberof PolylineColorAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
closed: {
get: function() {
return this._closed;
}
},
/**
* The {@link VertexFormat} that this appearance instance is compatible with.
* A geometry can have more vertex attributes and still be compatible - at a
* potential performance cost - but it can't have less.
*
* @memberof PolylineColorAppearance.prototype
*
* @type VertexFormat
* @readonly
*
* @default {@link PolylineColorAppearance.VERTEX_FORMAT}
*/
vertexFormat: {
get: function() {
return this._vertexFormat;
}
}
});
PolylineColorAppearance.VERTEX_FORMAT = VertexFormat_default.POSITION_ONLY;
PolylineColorAppearance.prototype.getFragmentShaderSource = Appearance_default.prototype.getFragmentShaderSource;
PolylineColorAppearance.prototype.isTranslucent = Appearance_default.prototype.isTranslucent;
PolylineColorAppearance.prototype.getRenderState = Appearance_default.prototype.getRenderState;
var PolylineColorAppearance_default = PolylineColorAppearance;
// packages/engine/Source/Scene/PolylineMaterialAppearance.js
var import_InlineWorkers389 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Appearances/PolylineMaterialAppearanceVS.js
var import_InlineWorkers387 = __toESM(require_InlineWorkers(), 1);
var PolylineMaterialAppearanceVS_default = "in vec3 position3DHigh;\nin vec3 position3DLow;\nin vec3 prevPosition3DHigh;\nin vec3 prevPosition3DLow;\nin vec3 nextPosition3DHigh;\nin vec3 nextPosition3DLow;\nin vec2 expandAndWidth;\nin vec2 st;\nin float batchId;\n\nout float v_width;\nout vec2 v_st;\nout float v_polylineAngle;\n\nvoid main()\n{\n float expandDir = expandAndWidth.x;\n float width = abs(expandAndWidth.y) + 0.5;\n bool usePrev = expandAndWidth.y < 0.0;\n\n vec4 p = czm_computePosition();\n vec4 prev = czm_computePrevPosition();\n vec4 next = czm_computeNextPosition();\n\n float angle;\n vec4 positionWC = getPolylineWindowCoordinates(p, prev, next, expandDir, width, usePrev, angle);\n gl_Position = czm_viewportOrthographic * positionWC;\n\n v_width = width;\n v_st.s = st.s;\n v_st.t = czm_writeNonPerspective(st.t, gl_Position.w);\n v_polylineAngle = angle;\n}\n";
// packages/engine/Source/Shaders/PolylineFS.js
var import_InlineWorkers388 = __toESM(require_InlineWorkers(), 1);
var PolylineFS_default = "#ifdef VECTOR_TILE\nuniform vec4 u_highlightColor;\n#endif\n\nin vec2 v_st;\n\nvoid main()\n{\n czm_materialInput materialInput;\n\n vec2 st = v_st;\n st.t = czm_readNonPerspective(st.t, gl_FragCoord.w);\n\n materialInput.s = st.s;\n materialInput.st = st;\n materialInput.str = vec3(st, 0.0);\n\n czm_material material = czm_getMaterial(materialInput);\n out_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n#ifdef VECTOR_TILE\n out_FragColor *= u_highlightColor;\n#endif\n\n czm_writeLogDepth();\n}\n";
// packages/engine/Source/Scene/PolylineMaterialAppearance.js
var defaultVertexShaderSource2 = `${PolylineCommon_default}
${PolylineMaterialAppearanceVS_default}`;
var defaultFragmentShaderSource2 = PolylineFS_default;
if (!FeatureDetection_default.isInternetExplorer()) {
defaultVertexShaderSource2 = `#define CLIP_POLYLINE
${defaultVertexShaderSource2}`;
}
function PolylineMaterialAppearance(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const translucent = options.translucent ?? true;
const closed = false;
const vertexFormat = PolylineMaterialAppearance.VERTEX_FORMAT;
this.material = defined_default(options.material) ? options.material : Material_default.fromType(Material_default.ColorType);
this.translucent = translucent;
this._vertexShaderSource = options.vertexShaderSource ?? defaultVertexShaderSource2;
this._fragmentShaderSource = options.fragmentShaderSource ?? defaultFragmentShaderSource2;
this._renderState = Appearance_default.getDefaultRenderState(
translucent,
closed,
options.renderState
);
this._closed = closed;
this._vertexFormat = vertexFormat;
}
Object.defineProperties(PolylineMaterialAppearance.prototype, {
/**
* The GLSL source code for the vertex shader.
*
* @memberof PolylineMaterialAppearance.prototype
*
* @type {string}
* @readonly
*/
vertexShaderSource: {
get: function() {
let vs = this._vertexShaderSource;
if (this.material.shaderSource.search(/in\s+float\s+v_polylineAngle;/g) !== -1) {
vs = `#define POLYLINE_DASH
${vs}`;
}
return vs;
}
},
/**
* The GLSL source code for the fragment shader.
*
* @memberof PolylineMaterialAppearance.prototype
*
* @type {string}
* @readonly
*/
fragmentShaderSource: {
get: function() {
return this._fragmentShaderSource;
}
},
/**
* The WebGL fixed-function state to use when rendering the geometry.
* * The render state can be explicitly defined when constructing a {@link PolylineMaterialAppearance} * instance, or it is set implicitly via {@link PolylineMaterialAppearance#translucent} * and {@link PolylineMaterialAppearance#closed}. *
* * @memberof PolylineMaterialAppearance.prototype * * @type {object} * @readonly */ renderState: { get: function() { return this._renderState; } }, /** * Whentrue, the geometry is expected to be closed so
* {@link PolylineMaterialAppearance#renderState} has backface culling enabled.
* This is always false for PolylineMaterialAppearance.
*
* @memberof PolylineMaterialAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
closed: {
get: function() {
return this._closed;
}
},
/**
* The {@link VertexFormat} that this appearance instance is compatible with.
* A geometry can have more vertex attributes and still be compatible - at a
* potential performance cost - but it can't have less.
*
* @memberof PolylineMaterialAppearance.prototype
*
* @type VertexFormat
* @readonly
*
* @default {@link PolylineMaterialAppearance.VERTEX_FORMAT}
*/
vertexFormat: {
get: function() {
return this._vertexFormat;
}
}
});
PolylineMaterialAppearance.VERTEX_FORMAT = VertexFormat_default.POSITION_AND_ST;
PolylineMaterialAppearance.prototype.getFragmentShaderSource = Appearance_default.prototype.getFragmentShaderSource;
PolylineMaterialAppearance.prototype.isTranslucent = Appearance_default.prototype.isTranslucent;
PolylineMaterialAppearance.prototype.getRenderState = Appearance_default.prototype.getRenderState;
var PolylineMaterialAppearance_default = PolylineMaterialAppearance;
// packages/engine/Source/Scene/GroundPolylinePrimitive.js
function GroundPolylinePrimitive(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.geometryInstances = options.geometryInstances;
this._hasPerInstanceColors = true;
let appearance = options.appearance;
if (!defined_default(appearance)) {
appearance = new PolylineMaterialAppearance_default();
}
this.appearance = appearance;
this.show = options.show ?? true;
this.classificationType = options.classificationType ?? ClassificationType_default.BOTH;
this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this._debugShowShadowVolume = options.debugShowShadowVolume ?? false;
this._primitiveOptions = {
geometryInstances: void 0,
appearance: void 0,
vertexCacheOptimize: false,
interleave: options.interleave ?? false,
releaseGeometryInstances: options.releaseGeometryInstances ?? true,
allowPicking: options.allowPicking ?? true,
asynchronous: options.asynchronous ?? true,
compressVertices: false,
_createShaderProgramFunction: void 0,
_createCommandsFunction: void 0,
_updateAndQueueCommandsFunction: void 0
};
this._zIndex = void 0;
this._ready = false;
this._primitive = void 0;
this._sp = void 0;
this._sp2D = void 0;
this._spMorph = void 0;
this._renderState = getRenderState(false);
this._renderState3DTiles = getRenderState(true);
this._renderStateMorph = RenderState_default.fromCache({
cull: {
enabled: true,
face: CullFace_default.FRONT
// Geometry is "inverted," so cull front when materials on volume instead of on terrain (morph)
},
depthTest: {
enabled: true
},
blending: BlendingState_default.PRE_MULTIPLIED_ALPHA_BLEND,
depthMask: false
});
}
Object.defineProperties(GroundPolylinePrimitive.prototype, {
/**
* Determines if geometry vertex attributes are interleaved, which can slightly improve rendering performance.
*
* @memberof GroundPolylinePrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
interleave: {
get: function() {
return this._primitiveOptions.interleave;
}
},
/**
* When true, the primitive does not keep a reference to the input geometryInstances to save memory.
*
* @memberof GroundPolylinePrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
releaseGeometryInstances: {
get: function() {
return this._primitiveOptions.releaseGeometryInstances;
}
},
/**
* When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved.
*
* @memberof GroundPolylinePrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
allowPicking: {
get: function() {
return this._primitiveOptions.allowPicking;
}
},
/**
* Determines if the geometry instances will be created and batched on a web worker.
*
* @memberof GroundPolylinePrimitive.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
asynchronous: {
get: function() {
return this._primitiveOptions.asynchronous;
}
},
/**
* Determines if the primitive is complete and ready to render. If this property is
* true, the primitive will be rendered the next time that {@link GroundPolylinePrimitive#update}
* is called.
*
* @memberof GroundPolylinePrimitive.prototype
*
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
},
/**
* This property is for debugging only; it is not for production use nor is it optimized.
* * If true, draws the shadow volume for each geometry in the primitive. *
* * @memberof GroundPolylinePrimitive.prototype * * @type {boolean} * @readonly * * @default false */ debugShowShadowVolume: { get: function() { return this._debugShowShadowVolume; } } }); GroundPolylinePrimitive.initializeTerrainHeights = function() { return ApproximateTerrainHeights_default.initialize(); }; function createShaderProgram3(groundPolylinePrimitive, frameState, appearance) { const context = frameState.context; const primitive = groundPolylinePrimitive._primitive; const attributeLocations8 = primitive._attributeLocations; let vs = primitive._batchTable.getVertexShaderCallback()( PolylineShadowVolumeVS_default ); vs = Primitive_default._appendShowToShader(primitive, vs); vs = Primitive_default._appendDistanceDisplayConditionToShader(primitive, vs); vs = Primitive_default._modifyShaderPosition( groundPolylinePrimitive, vs, frameState.scene3DOnly ); let vsMorph = primitive._batchTable.getVertexShaderCallback()( PolylineShadowVolumeMorphVS_default ); vsMorph = Primitive_default._appendShowToShader(primitive, vsMorph); vsMorph = Primitive_default._appendDistanceDisplayConditionToShader( primitive, vsMorph ); vsMorph = Primitive_default._modifyShaderPosition( groundPolylinePrimitive, vsMorph, frameState.scene3DOnly ); let fs = primitive._batchTable.getVertexShaderCallback()( PolylineShadowVolumeFS_default ); const vsDefines = [ `GLOBE_MINIMUM_ALTITUDE ${frameState.mapProjection.ellipsoid.minimumRadius.toFixed( 1 )}` ]; let colorDefine = ""; let materialShaderSource = ""; if (defined_default(appearance.material)) { materialShaderSource = defined_default(appearance.material) ? appearance.material.shaderSource : ""; if (materialShaderSource.search(/in\s+float\s+v_polylineAngle;/g) !== -1) { vsDefines.push("ANGLE_VARYING"); } if (materialShaderSource.search(/in\s+float\s+v_width;/g) !== -1) { vsDefines.push("WIDTH_VARYING"); } } else { colorDefine = "PER_INSTANCE_COLOR"; } vsDefines.push(colorDefine); const fsDefines = groundPolylinePrimitive.debugShowShadowVolume ? ["DEBUG_SHOW_VOLUME", colorDefine] : [colorDefine]; const vsColor3D = new ShaderSource_default({ defines: vsDefines, sources: [vs] }); const fsColor3D = new ShaderSource_default({ defines: fsDefines, sources: [materialShaderSource, fs] }); groundPolylinePrimitive._sp = ShaderProgram_default.replaceCache({ context, shaderProgram: primitive._sp, vertexShaderSource: vsColor3D, fragmentShaderSource: fsColor3D, attributeLocations: attributeLocations8 }); let colorProgram2D = context.shaderCache.getDerivedShaderProgram( groundPolylinePrimitive._sp, "2dColor" ); if (!defined_default(colorProgram2D)) { const vsColor2D = new ShaderSource_default({ defines: vsDefines.concat(["COLUMBUS_VIEW_2D"]), sources: [vs] }); colorProgram2D = context.shaderCache.createDerivedShaderProgram( groundPolylinePrimitive._sp, "2dColor", { context, shaderProgram: groundPolylinePrimitive._sp2D, vertexShaderSource: vsColor2D, fragmentShaderSource: fsColor3D, attributeLocations: attributeLocations8 } ); } groundPolylinePrimitive._sp2D = colorProgram2D; let colorProgramMorph = context.shaderCache.getDerivedShaderProgram( groundPolylinePrimitive._sp, "MorphColor" ); if (!defined_default(colorProgramMorph)) { const vsColorMorph = new ShaderSource_default({ defines: vsDefines.concat([ `MAX_TERRAIN_HEIGHT ${ApproximateTerrainHeights_default._defaultMaxTerrainHeight.toFixed( 1 )}` ]), sources: [vsMorph] }); fs = primitive._batchTable.getVertexShaderCallback()( PolylineShadowVolumeMorphFS_default ); const fsColorMorph = new ShaderSource_default({ defines: fsDefines, sources: [materialShaderSource, fs] }); colorProgramMorph = context.shaderCache.createDerivedShaderProgram( groundPolylinePrimitive._sp, "MorphColor", { context, shaderProgram: groundPolylinePrimitive._spMorph, vertexShaderSource: vsColorMorph, fragmentShaderSource: fsColorMorph, attributeLocations: attributeLocations8 } ); } groundPolylinePrimitive._spMorph = colorProgramMorph; } function getRenderState(mask3DTiles) { return RenderState_default.fromCache({ cull: { enabled: true // prevent double-draw. Geometry is "inverted" (reversed winding order) so we're drawing backfaces. }, blending: BlendingState_default.PRE_MULTIPLIED_ALPHA_BLEND, depthMask: false, stencilTest: { enabled: mask3DTiles, frontFunction: StencilFunction_default.EQUAL, frontOperation: { fail: StencilOperation_default.KEEP, zFail: StencilOperation_default.KEEP, zPass: StencilOperation_default.KEEP }, backFunction: StencilFunction_default.EQUAL, backOperation: { fail: StencilOperation_default.KEEP, zFail: StencilOperation_default.KEEP, zPass: StencilOperation_default.KEEP }, reference: StencilConstants_default.CESIUM_3D_TILE_MASK, mask: StencilConstants_default.CESIUM_3D_TILE_MASK } }); } function createCommands3(groundPolylinePrimitive, appearance, material, translucent, colorCommands, pickCommands) { const primitive = groundPolylinePrimitive._primitive; const length2 = primitive._va.length; colorCommands.length = length2; pickCommands.length = length2; const isPolylineColorAppearance = appearance instanceof PolylineColorAppearance_default; const materialUniforms = isPolylineColorAppearance ? {} : material._uniforms; const uniformMap2 = primitive._batchTable.getUniformMapCallback()(materialUniforms); for (let i = 0; i < length2; i++) { const vertexArray = primitive._va[i]; let command = colorCommands[i]; if (!defined_default(command)) { command = colorCommands[i] = new DrawCommand_default({ owner: groundPolylinePrimitive, primitiveType: primitive._primitiveType }); } command.vertexArray = vertexArray; command.renderState = groundPolylinePrimitive._renderState; command.shaderProgram = groundPolylinePrimitive._sp; command.uniformMap = uniformMap2; command.pass = Pass_default.TERRAIN_CLASSIFICATION; command.pickId = "czm_batchTable_pickColor(v_endPlaneNormalEcAndBatchId.w)"; const derivedTilesetCommand = DrawCommand_default.shallowClone( command, command.derivedCommands.tileset ); derivedTilesetCommand.renderState = groundPolylinePrimitive._renderState3DTiles; derivedTilesetCommand.pass = Pass_default.CESIUM_3D_TILE_CLASSIFICATION; command.derivedCommands.tileset = derivedTilesetCommand; const derived2DCommand = DrawCommand_default.shallowClone( command, command.derivedCommands.color2D ); derived2DCommand.shaderProgram = groundPolylinePrimitive._sp2D; command.derivedCommands.color2D = derived2DCommand; const derived2DTilesetCommand = DrawCommand_default.shallowClone( derivedTilesetCommand, derivedTilesetCommand.derivedCommands.color2D ); derived2DTilesetCommand.shaderProgram = groundPolylinePrimitive._sp2D; derivedTilesetCommand.derivedCommands.color2D = derived2DTilesetCommand; const derivedMorphCommand = DrawCommand_default.shallowClone( command, command.derivedCommands.colorMorph ); derivedMorphCommand.renderState = groundPolylinePrimitive._renderStateMorph; derivedMorphCommand.shaderProgram = groundPolylinePrimitive._spMorph; derivedMorphCommand.pickId = "czm_batchTable_pickColor(v_batchId)"; command.derivedCommands.colorMorph = derivedMorphCommand; } } function updateAndQueueCommand(groundPolylinePrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume2) { if (frameState.mode === SceneMode_default.MORPHING) { command = command.derivedCommands.colorMorph; } else if (frameState.mode !== SceneMode_default.SCENE3D) { command = command.derivedCommands.color2D; } command.modelMatrix = modelMatrix; command.boundingVolume = boundingVolume; command.cull = cull; command.debugShowBoundingVolume = debugShowBoundingVolume2; frameState.commandList.push(command); } function updateAndQueueCommands4(groundPolylinePrimitive, frameState, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume2) { const primitive = groundPolylinePrimitive._primitive; Primitive_default._updateBoundingVolumes(primitive, frameState, modelMatrix); let boundingSpheres; if (frameState.mode === SceneMode_default.SCENE3D) { boundingSpheres = primitive._boundingSphereWC; } else if (frameState.mode === SceneMode_default.COLUMBUS_VIEW) { boundingSpheres = primitive._boundingSphereCV; } else if (frameState.mode === SceneMode_default.SCENE2D && defined_default(primitive._boundingSphere2D)) { boundingSpheres = primitive._boundingSphere2D; } else if (defined_default(primitive._boundingSphereMorph)) { boundingSpheres = primitive._boundingSphereMorph; } const morphing = frameState.mode === SceneMode_default.MORPHING; const classificationType = groundPolylinePrimitive.classificationType; const queueTerrainCommands = classificationType !== ClassificationType_default.CESIUM_3D_TILE; const queue3DTilesCommands = classificationType !== ClassificationType_default.TERRAIN && !morphing; let command; const passes = frameState.passes; if (passes.render || passes.pick && primitive.allowPicking) { const colorLength = colorCommands.length; for (let j = 0; j < colorLength; ++j) { const boundingVolume = boundingSpheres[j]; if (queueTerrainCommands) { command = colorCommands[j]; updateAndQueueCommand( groundPolylinePrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume2 ); } if (queue3DTilesCommands) { command = colorCommands[j].derivedCommands.tileset; updateAndQueueCommand( groundPolylinePrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume2 ); } } } } GroundPolylinePrimitive.prototype.update = function(frameState) { if (!defined_default(this._primitive) && !defined_default(this.geometryInstances)) { return; } if (!ApproximateTerrainHeights_default.initialized) { if (!this.asynchronous) { throw new DeveloperError_default( "For synchronous GroundPolylinePrimitives, you must call GroundPolylinePrimitives.initializeTerrainHeights() and wait for the returned promise to resolve." ); } GroundPolylinePrimitive.initializeTerrainHeights(); return; } let i; const that = this; const primitiveOptions = this._primitiveOptions; if (!defined_default(this._primitive)) { const geometryInstances = Array.isArray(this.geometryInstances) ? this.geometryInstances : [this.geometryInstances]; const geometryInstancesLength = geometryInstances.length; const groundInstances = new Array(geometryInstancesLength); let attributes; for (i = 0; i < geometryInstancesLength; ++i) { attributes = geometryInstances[i].attributes; if (!defined_default(attributes) || !defined_default(attributes.color)) { this._hasPerInstanceColors = false; break; } } for (i = 0; i < geometryInstancesLength; ++i) { const geometryInstance = geometryInstances[i]; attributes = {}; const instanceAttributes = geometryInstance.attributes; for (const attributeKey in instanceAttributes) { if (instanceAttributes.hasOwnProperty(attributeKey)) { attributes[attributeKey] = instanceAttributes[attributeKey]; } } if (!defined_default(attributes.width)) { attributes.width = new GeometryInstanceAttribute_default({ componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE, componentsPerAttribute: 1, value: [geometryInstance.geometry.width] }); } geometryInstance.geometry._scene3DOnly = frameState.scene3DOnly; GroundPolylineGeometry_default.setProjectionAndEllipsoid( geometryInstance.geometry, frameState.mapProjection ); groundInstances[i] = new GeometryInstance_default({ geometry: geometryInstance.geometry, attributes, id: geometryInstance.id, pickPrimitive: that }); } primitiveOptions.geometryInstances = groundInstances; primitiveOptions.appearance = this.appearance; primitiveOptions._createShaderProgramFunction = function(primitive, frameState2, appearance) { createShaderProgram3(that, frameState2, appearance); }; primitiveOptions._createCommandsFunction = function(primitive, appearance, material, translucent, twoPasses, colorCommands, pickCommands) { createCommands3( that, appearance, material, translucent, colorCommands, pickCommands ); }; primitiveOptions._updateAndQueueCommandsFunction = function(primitive, frameState2, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume2, twoPasses) { updateAndQueueCommands4( that, frameState2, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume2 ); }; this._primitive = new Primitive_default(primitiveOptions); } if (this.appearance instanceof PolylineColorAppearance_default && !this._hasPerInstanceColors) { throw new DeveloperError_default( "All GeometryInstances must have color attributes to use PolylineColorAppearance with GroundPolylinePrimitive." ); } this._primitive.appearance = this.appearance; this._primitive.show = this.show; this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume; this._primitive.update(frameState); frameState.afterRender.push(() => { if (!this._ready && defined_default(this._primitive) && this._primitive.ready) { this._ready = true; if (this.releaseGeometryInstances) { this.geometryInstances = void 0; } } }); }; GroundPolylinePrimitive.prototype.getGeometryInstanceAttributes = function(id) { if (!defined_default(this._primitive)) { throw new DeveloperError_default( "must call update before calling getGeometryInstanceAttributes" ); } return this._primitive.getGeometryInstanceAttributes(id); }; GroundPolylinePrimitive.isSupported = function(scene) { return scene.frameState.context.depthTexture; }; GroundPolylinePrimitive.prototype.isDestroyed = function() { return false; }; GroundPolylinePrimitive.prototype.destroy = function() { this._primitive = this._primitive && this._primitive.destroy(); this._sp = this._sp && this._sp.destroy(); this._sp2D = void 0; this._spMorph = void 0; return destroyObject_default(this); }; var GroundPolylinePrimitive_default = GroundPolylinePrimitive; // packages/engine/Source/DataSources/BoxGraphics.js var import_InlineWorkers393 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/DataSources/createMaterialPropertyDescriptor.js var import_InlineWorkers392 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/DataSources/ImageMaterialProperty.js var import_InlineWorkers391 = __toESM(require_InlineWorkers(), 1); var defaultRepeat = new Cartesian2_default(1, 1); var defaultTransparent = false; var defaultColor2 = Color_default.WHITE; function ImageMaterialProperty(options) { options = options ?? Frozen_default.EMPTY_OBJECT; this._definitionChanged = new Event_default(); this._image = void 0; this._imageSubscription = void 0; this._repeat = void 0; this._repeatSubscription = void 0; this._color = void 0; this._colorSubscription = void 0; this._transparent = void 0; this._transparentSubscription = void 0; this.image = options.image; this.repeat = options.repeat; this.color = options.color; this.transparent = options.transparent; } Object.defineProperties(ImageMaterialProperty.prototype, { /** * Gets a value indicating if this property is constant. A property is considered * constant if getValue always returns the same result for the current definition. * @memberof ImageMaterialProperty.prototype * * @type {boolean} * @readonly */ isConstant: { get: function() { return Property_default.isConstant(this._image) && Property_default.isConstant(this._repeat); } }, /** * Gets the event that is raised whenever the definition of this property changes. * The definition is considered to have changed if a call to getValue would return * a different result for the same time. * @memberof ImageMaterialProperty.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the Property specifying Image, URL, Canvas, or Video to use. * @memberof ImageMaterialProperty.prototype * @type {Property|undefined} */ image: createPropertyDescriptor_default("image"), /** * Gets or sets the {@link Cartesian2} Property specifying the number of times the image repeats in each direction. * @memberof ImageMaterialProperty.prototype * @type {Property|undefined} * @default new Cartesian2(1, 1) */ repeat: createPropertyDescriptor_default("repeat"), /** * Gets or sets the Color Property specifying the desired color applied to the image. * @memberof ImageMaterialProperty.prototype * @type {Property|undefined} * @default 1.0 */ color: createPropertyDescriptor_default("color"), /** * Gets or sets the Boolean Property specifying whether the image has transparency * @memberof ImageMaterialProperty.prototype * @type {Property|undefined} * @default 1.0 */ transparent: createPropertyDescriptor_default("transparent") }); ImageMaterialProperty.prototype.getType = function(time) { return "Image"; }; var timeScratch3 = new JulianDate_default(); ImageMaterialProperty.prototype.getValue = function(time, result) { if (!defined_default(time)) { time = JulianDate_default.now(timeScratch3); } if (!defined_default(result)) { result = {}; } result.image = Property_default.getValueOrUndefined(this._image, time); result.repeat = Property_default.getValueOrClonedDefault( this._repeat, time, defaultRepeat, result.repeat ); result.color = Property_default.getValueOrClonedDefault( this._color, time, defaultColor2, result.color ); if (Property_default.getValueOrDefault(this._transparent, time, defaultTransparent)) { result.color.alpha = Math.min(0.99, result.color.alpha); } return result; }; ImageMaterialProperty.prototype.equals = function(other) { return this === other || other instanceof ImageMaterialProperty && Property_default.equals(this._image, other._image) && Property_default.equals(this._repeat, other._repeat) && Property_default.equals(this._color, other._color) && Property_default.equals(this._transparent, other._transparent); }; var ImageMaterialProperty_default = ImageMaterialProperty; // packages/engine/Source/DataSources/createMaterialPropertyDescriptor.js function createMaterialProperty(value) { if (value instanceof Color_default) { return new ColorMaterialProperty_default(value); } if (typeof value === "string" || value instanceof Resource_default || value instanceof HTMLCanvasElement || value instanceof HTMLVideoElement) { const result = new ImageMaterialProperty_default(); result.image = value; return result; } throw new DeveloperError_default(`Unable to infer material type: ${value}`); } function createMaterialPropertyDescriptor(name, configurable) { return createPropertyDescriptor_default(name, configurable, createMaterialProperty); } var createMaterialPropertyDescriptor_default = createMaterialPropertyDescriptor; // packages/engine/Source/DataSources/BoxGraphics.js function BoxGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._dimensions = void 0; this._dimensionsSubscription = void 0; this._heightReference = void 0; this._heightReferenceSubscription = void 0; this._fill = void 0; this._fillSubscription = void 0; this._material = void 0; this._materialSubscription = void 0; this._outline = void 0; this._outlineSubscription = void 0; this._outlineColor = void 0; this._outlineColorSubscription = void 0; this._outlineWidth = void 0; this._outlineWidthSubscription = void 0; this._shadows = void 0; this._shadowsSubscription = void 0; this._distanceDisplayCondition = void 0; this._distanceDisplayConditionSubscription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(BoxGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof BoxGraphics.prototype * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the box. * @memberof BoxGraphics.prototype * @type {Property|undefined} * @default true */ show: createPropertyDescriptor_default("show"), /** * Gets or sets {@link Cartesian3} Property property specifying the length, width, and height of the box. * @memberof BoxGraphics.prototype * @type {Property|undefined} */ dimensions: createPropertyDescriptor_default("dimensions"), /** * Gets or sets the Property specifying the {@link HeightReference}. * @memberof BoxGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ heightReference: createPropertyDescriptor_default("heightReference"), /** * Gets or sets the boolean Property specifying whether the box is filled with the provided material. * @memberof BoxGraphics.prototype * @type {Property|undefined} * @default true */ fill: createPropertyDescriptor_default("fill"), /** * Gets or sets the material used to fill the box. * @memberof BoxGraphics.prototype * @type {MaterialProperty|undefined} * @default Color.WHITE */ material: createMaterialPropertyDescriptor_default("material"), /** * Gets or sets the Property specifying whether the box is outlined. * @memberof BoxGraphics.prototype * @type {Property|undefined} * @default false */ outline: createPropertyDescriptor_default("outline"), /** * Gets or sets the Property specifying the {@link Color} of the outline. * @memberof BoxGraphics.prototype * @type {Property|undefined} * @default Color.BLACK */ outlineColor: createPropertyDescriptor_default("outlineColor"), /** * Gets or sets the numeric Property specifying the width of the outline. ** Note: This property will be ignored on all major browsers on Windows platforms. For details, see (@link https://github.com/CesiumGS/cesium/issues/40}. *
* @memberof BoxGraphics.prototype * @type {Property|undefined} * @default 1.0 */ outlineWidth: createPropertyDescriptor_default("outlineWidth"), /** * Get or sets the enum Property specifying whether the box * casts or receives shadows from light sources. * @memberof BoxGraphics.prototype * @type {Property|undefined} * @default ShadowMode.DISABLED */ shadows: createPropertyDescriptor_default("shadows"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this box will be displayed. * @memberof BoxGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ) }); BoxGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new BoxGraphics(this); } result.show = this.show; result.dimensions = this.dimensions; result.heightReference = this.heightReference; result.fill = this.fill; result.material = this.material; result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; BoxGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.dimensions = this.dimensions ?? source.dimensions; this.heightReference = this.heightReference ?? source.heightReference; this.fill = this.fill ?? source.fill; this.material = this.material ?? source.material; this.outline = this.outline ?? source.outline; this.outlineColor = this.outlineColor ?? source.outlineColor; this.outlineWidth = this.outlineWidth ?? source.outlineWidth; this.shadows = this.shadows ?? source.shadows; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; }; var BoxGraphics_default = BoxGraphics; // packages/engine/Source/DataSources/ConstantPositionProperty.js var import_InlineWorkers396 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Core/ReferenceFrame.js var import_InlineWorkers394 = __toESM(require_InlineWorkers(), 1); var ReferenceFrame = { /** * The fixed frame. * * @type {number} * @constant */ FIXED: 0, /** * The inertial frame. * * @type {number} * @constant */ INERTIAL: 1 }; var ReferenceFrame_default = Object.freeze(ReferenceFrame); // packages/engine/Source/DataSources/PositionProperty.js var import_InlineWorkers395 = __toESM(require_InlineWorkers(), 1); function PositionProperty() { DeveloperError_default.throwInstantiationError(); } Object.defineProperties(PositionProperty.prototype, { /** * Gets a value indicating if this property is constant. A property is considered * constant if getValue always returns the same result for the current definition. * @memberof PositionProperty.prototype * * @type {boolean} * @readonly */ isConstant: { get: DeveloperError_default.throwInstantiationError }, /** * Gets the event that is raised whenever the definition of this property changes. * The definition is considered to have changed if a call to getValue would return * a different result for the same time. * @memberof PositionProperty.prototype * * @type {Event} * @readonly */ definitionChanged: { get: DeveloperError_default.throwInstantiationError }, /** * Gets the reference frame that the position is defined in. * @memberof PositionProperty.prototype * @type {ReferenceFrame} */ referenceFrame: { get: DeveloperError_default.throwInstantiationError } }); PositionProperty.prototype.getValue = DeveloperError_default.throwInstantiationError; PositionProperty.prototype.getValueInReferenceFrame = DeveloperError_default.throwInstantiationError; PositionProperty.prototype.equals = DeveloperError_default.throwInstantiationError; var scratchMatrix3 = new Matrix3_default(); PositionProperty.convertToReferenceFrame = function(time, value, inputFrame, outputFrame, result) { if (!defined_default(value)) { return value; } if (!defined_default(result)) { result = new Cartesian3_default(); } if (inputFrame === outputFrame) { return Cartesian3_default.clone(value, result); } const icrfToFixed2 = Transforms_default.computeIcrfToCentralBodyFixedMatrix( time, scratchMatrix3 ); if (inputFrame === ReferenceFrame_default.INERTIAL) { return Matrix3_default.multiplyByVector(icrfToFixed2, value, result); } if (inputFrame === ReferenceFrame_default.FIXED) { return Matrix3_default.multiplyByVector( Matrix3_default.transpose(icrfToFixed2, scratchMatrix3), value, result ); } }; var PositionProperty_default = PositionProperty; // packages/engine/Source/DataSources/ConstantPositionProperty.js function ConstantPositionProperty(value, referenceFrame) { this._definitionChanged = new Event_default(); this._value = Cartesian3_default.clone(value); this._referenceFrame = referenceFrame ?? ReferenceFrame_default.FIXED; } Object.defineProperties(ConstantPositionProperty.prototype, { /** * Gets a value indicating if this property is constant. A property is considered * constant if getValue always returns the same result for the current definition. * @memberof ConstantPositionProperty.prototype * * @type {boolean} * @readonly */ isConstant: { get: function() { return !defined_default(this._value) || this._referenceFrame === ReferenceFrame_default.FIXED; } }, /** * Gets the event that is raised whenever the definition of this property changes. * The definition is considered to have changed if a call to getValue would return * a different result for the same time. * @memberof ConstantPositionProperty.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets the reference frame in which the position is defined. * @memberof ConstantPositionProperty.prototype * @type {ReferenceFrame} * @default ReferenceFrame.FIXED; */ referenceFrame: { get: function() { return this._referenceFrame; } } }); var timeScratch4 = new JulianDate_default(); ConstantPositionProperty.prototype.getValue = function(time, result) { if (!defined_default(time)) { time = JulianDate_default.now(timeScratch4); } return this.getValueInReferenceFrame(time, ReferenceFrame_default.FIXED, result); }; ConstantPositionProperty.prototype.setValue = function(value, referenceFrame) { let definitionChanged = false; if (!Cartesian3_default.equals(this._value, value)) { definitionChanged = true; this._value = Cartesian3_default.clone(value); } if (defined_default(referenceFrame) && this._referenceFrame !== referenceFrame) { definitionChanged = true; this._referenceFrame = referenceFrame; } if (definitionChanged) { this._definitionChanged.raiseEvent(this); } }; ConstantPositionProperty.prototype.getValueInReferenceFrame = function(time, referenceFrame, result) { if (!defined_default(time)) { throw new DeveloperError_default("time is required."); } if (!defined_default(referenceFrame)) { throw new DeveloperError_default("referenceFrame is required."); } return PositionProperty_default.convertToReferenceFrame( time, this._value, this._referenceFrame, referenceFrame, result ); }; ConstantPositionProperty.prototype.equals = function(other) { return this === other || other instanceof ConstantPositionProperty && Cartesian3_default.equals(this._value, other._value) && this._referenceFrame === other._referenceFrame; }; var ConstantPositionProperty_default = ConstantPositionProperty; // packages/engine/Source/DataSources/CorridorGraphics.js var import_InlineWorkers397 = __toESM(require_InlineWorkers(), 1); function CorridorGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._positions = void 0; this._positionsSubscription = void 0; this._width = void 0; this._widthSubscription = void 0; this._height = void 0; this._heightSubscription = void 0; this._heightReference = void 0; this._heightReferenceSubscription = void 0; this._extrudedHeight = void 0; this._extrudedHeightSubscription = void 0; this._extrudedHeightReference = void 0; this._extrudedHeightReferenceSubscription = void 0; this._cornerType = void 0; this._cornerTypeSubscription = void 0; this._granularity = void 0; this._granularitySubscription = void 0; this._fill = void 0; this._fillSubscription = void 0; this._material = void 0; this._materialSubscription = void 0; this._outline = void 0; this._outlineSubscription = void 0; this._outlineColor = void 0; this._outlineColorSubscription = void 0; this._outlineWidth = void 0; this._outlineWidthSubscription = void 0; this._shadows = void 0; this._shadowsSubscription = void 0; this._distanceDisplayCondition = void 0; this._distanceDisplayConditionSubscription = void 0; this._classificationType = void 0; this._classificationTypeSubscription = void 0; this._zIndex = void 0; this._zIndexSubscription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(CorridorGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof CorridorGraphics.prototype * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the corridor. * @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default true */ show: createPropertyDescriptor_default("show"), /** * Gets or sets a Property specifying the array of {@link Cartesian3} positions that define the centerline of the corridor. * @memberof CorridorGraphics.prototype * @type {Property|undefined} */ positions: createPropertyDescriptor_default("positions"), /** * Gets or sets the numeric Property specifying the width of the outline. * @memberof CorridorGraphics.prototype * @type {Property|undefined} */ width: createPropertyDescriptor_default("width"), /** * Gets or sets the numeric Property specifying the altitude of the corridor. * @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default 0.0 */ height: createPropertyDescriptor_default("height"), /** * Gets or sets the Property specifying the {@link HeightReference}. * @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ heightReference: createPropertyDescriptor_default("heightReference"), /** * Gets or sets the numeric Property specifying the altitude of the corridor extrusion. * Setting this property creates a corridor shaped volume starting at height and ending * at this altitude. * @memberof CorridorGraphics.prototype * @type {Property|undefined} */ extrudedHeight: createPropertyDescriptor_default("extrudedHeight"), /** * Gets or sets the Property specifying the extruded {@link HeightReference}. * @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ extrudedHeightReference: createPropertyDescriptor_default("extrudedHeightReference"), /** * Gets or sets the {@link CornerType} Property specifying how corners are styled. * @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default CornerType.ROUNDED */ cornerType: createPropertyDescriptor_default("cornerType"), /** * Gets or sets the numeric Property specifying the sampling distance between each latitude and longitude point. * @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default {CesiumMath.RADIANS_PER_DEGREE} */ granularity: createPropertyDescriptor_default("granularity"), /** * Gets or sets the boolean Property specifying whether the corridor is filled with the provided material. * @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default true */ fill: createPropertyDescriptor_default("fill"), /** * Gets or sets the Property specifying the material used to fill the corridor. * @memberof CorridorGraphics.prototype * @type {MaterialProperty|undefined} * @default Color.WHITE */ material: createMaterialPropertyDescriptor_default("material"), /** * Gets or sets the Property specifying whether the corridor is outlined. * @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default false */ outline: createPropertyDescriptor_default("outline"), /** * Gets or sets the Property specifying the {@link Color} of the outline. * @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default Color.BLACK */ outlineColor: createPropertyDescriptor_default("outlineColor"), /** * Gets or sets the numeric Property specifying the width of the outline. ** Note: This property will be ignored on all major browsers on Windows platforms. For details, see (@link https://github.com/CesiumGS/cesium/issues/40}. *
* @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default 1.0 */ outlineWidth: createPropertyDescriptor_default("outlineWidth"), /** * Get or sets the enum Property specifying whether the corridor * casts or receives shadows from light sources. * @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default ShadowMode.DISABLED */ shadows: createPropertyDescriptor_default("shadows"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this corridor will be displayed. * @memberof CorridorGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ), /** * Gets or sets the {@link ClassificationType} Property specifying whether this corridor will classify terrain, 3D Tiles, or both when on the ground. * @memberof CorridorGraphics.prototype * @type {Property|undefined} * @default ClassificationType.BOTH */ classificationType: createPropertyDescriptor_default("classificationType"), /** * Gets or sets the zIndex Property specifying the ordering of the corridor. Only has an effect if the coridor is static and neither height or exturdedHeight are specified. * @memberof CorridorGraphics.prototype * @type {ConstantProperty|undefined} * @default 0 */ zIndex: createPropertyDescriptor_default("zIndex") }); CorridorGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new CorridorGraphics(this); } result.show = this.show; result.positions = this.positions; result.width = this.width; result.height = this.height; result.heightReference = this.heightReference; result.extrudedHeight = this.extrudedHeight; result.extrudedHeightReference = this.extrudedHeightReference; result.cornerType = this.cornerType; result.granularity = this.granularity; result.fill = this.fill; result.material = this.material; result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; result.classificationType = this.classificationType; result.zIndex = this.zIndex; return result; }; CorridorGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.positions = this.positions ?? source.positions; this.width = this.width ?? source.width; this.height = this.height ?? source.height; this.heightReference = this.heightReference ?? source.heightReference; this.extrudedHeight = this.extrudedHeight ?? source.extrudedHeight; this.extrudedHeightReference = this.extrudedHeightReference ?? source.extrudedHeightReference; this.cornerType = this.cornerType ?? source.cornerType; this.granularity = this.granularity ?? source.granularity; this.fill = this.fill ?? source.fill; this.material = this.material ?? source.material; this.outline = this.outline ?? source.outline; this.outlineColor = this.outlineColor ?? source.outlineColor; this.outlineWidth = this.outlineWidth ?? source.outlineWidth; this.shadows = this.shadows ?? source.shadows; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; this.classificationType = this.classificationType ?? source.classificationType; this.zIndex = this.zIndex ?? source.zIndex; }; var CorridorGraphics_default = CorridorGraphics; // packages/engine/Source/DataSources/createRawPropertyDescriptor.js var import_InlineWorkers398 = __toESM(require_InlineWorkers(), 1); function createRawProperty(value) { return value; } function createRawPropertyDescriptor(name, configurable) { return createPropertyDescriptor_default(name, configurable, createRawProperty); } var createRawPropertyDescriptor_default = createRawPropertyDescriptor; // packages/engine/Source/DataSources/CylinderGraphics.js var import_InlineWorkers399 = __toESM(require_InlineWorkers(), 1); function CylinderGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._length = void 0; this._lengthSubscription = void 0; this._topRadius = void 0; this._topRadiusSubscription = void 0; this._bottomRadius = void 0; this._bottomRadiusSubscription = void 0; this._heightReference = void 0; this._heightReferenceSubscription = void 0; this._fill = void 0; this._fillSubscription = void 0; this._material = void 0; this._materialSubscription = void 0; this._outline = void 0; this._outlineSubscription = void 0; this._outlineColor = void 0; this._outlineColorSubscription = void 0; this._outlineWidth = void 0; this._outlineWidthSubscription = void 0; this._numberOfVerticalLines = void 0; this._numberOfVerticalLinesSubscription = void 0; this._slices = void 0; this._slicesSubscription = void 0; this._shadows = void 0; this._shadowsSubscription = void 0; this._distanceDisplayCondition = void 0; this._distanceDisplayConditionSubscription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(CylinderGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof CylinderGraphics.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the cylinder. * @memberof CylinderGraphics.prototype * @type {Property|undefined} * @default true */ show: createPropertyDescriptor_default("show"), /** * Gets or sets the numeric Property specifying the length of the cylinder. * @memberof CylinderGraphics.prototype * @type {Property|undefined} */ length: createPropertyDescriptor_default("length"), /** * Gets or sets the numeric Property specifying the radius of the top of the cylinder. * @memberof CylinderGraphics.prototype * @type {Property|undefined} */ topRadius: createPropertyDescriptor_default("topRadius"), /** * Gets or sets the numeric Property specifying the radius of the bottom of the cylinder. * @memberof CylinderGraphics.prototype * @type {Property|undefined} */ bottomRadius: createPropertyDescriptor_default("bottomRadius"), /** * Gets or sets the Property specifying the {@link HeightReference}. * @memberof CylinderGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ heightReference: createPropertyDescriptor_default("heightReference"), /** * Gets or sets the boolean Property specifying whether the cylinder is filled with the provided material. * @memberof CylinderGraphics.prototype * @type {Property|undefined} * @default true */ fill: createPropertyDescriptor_default("fill"), /** * Gets or sets the Property specifying the material used to fill the cylinder. * @memberof CylinderGraphics.prototype * @type {MaterialProperty|undefined} * @default Color.WHITE */ material: createMaterialPropertyDescriptor_default("material"), /** * Gets or sets the boolean Property specifying whether the cylinder is outlined. * @memberof CylinderGraphics.prototype * @type {Property|undefined} * @default false */ outline: createPropertyDescriptor_default("outline"), /** * Gets or sets the Property specifying the {@link Color} of the outline. * @memberof CylinderGraphics.prototype * @type {Property|undefined} * @default Color.BLACK */ outlineColor: createPropertyDescriptor_default("outlineColor"), /** * Gets or sets the numeric Property specifying the width of the outline. ** Note: This property will be ignored on all major browsers on Windows platforms. For details, see (@link https://github.com/CesiumGS/cesium/issues/40}. *
* @memberof CylinderGraphics.prototype * @type {Property|undefined} * @default 1.0 */ outlineWidth: createPropertyDescriptor_default("outlineWidth"), /** * Gets or sets the Property specifying the number of vertical lines to draw along the perimeter for the outline. * @memberof CylinderGraphics.prototype * @type {Property|undefined} * @default 16 */ numberOfVerticalLines: createPropertyDescriptor_default("numberOfVerticalLines"), /** * Gets or sets the Property specifying the number of edges around the perimeter of the cylinder. * @memberof CylinderGraphics.prototype * @type {Property|undefined} * @default 128 */ slices: createPropertyDescriptor_default("slices"), /** * Get or sets the enum Property specifying whether the cylinder * casts or receives shadows from light sources. * @memberof CylinderGraphics.prototype * @type {Property|undefined} * @default ShadowMode.DISABLED */ shadows: createPropertyDescriptor_default("shadows"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this cylinder will be displayed. * @memberof CylinderGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ) }); CylinderGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new CylinderGraphics(this); } result.show = this.show; result.length = this.length; result.topRadius = this.topRadius; result.bottomRadius = this.bottomRadius; result.heightReference = this.heightReference; result.fill = this.fill; result.material = this.material; result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.numberOfVerticalLines = this.numberOfVerticalLines; result.slices = this.slices; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; CylinderGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.length = this.length ?? source.length; this.topRadius = this.topRadius ?? source.topRadius; this.bottomRadius = this.bottomRadius ?? source.bottomRadius; this.heightReference = this.heightReference ?? source.heightReference; this.fill = this.fill ?? source.fill; this.material = this.material ?? source.material; this.outline = this.outline ?? source.outline; this.outlineColor = this.outlineColor ?? source.outlineColor; this.outlineWidth = this.outlineWidth ?? source.outlineWidth; this.numberOfVerticalLines = this.numberOfVerticalLines ?? source.numberOfVerticalLines; this.slices = this.slices ?? source.slices; this.shadows = this.shadows ?? source.shadows; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; }; var CylinderGraphics_default = CylinderGraphics; // packages/engine/Source/DataSources/EllipseGraphics.js var import_InlineWorkers400 = __toESM(require_InlineWorkers(), 1); function EllipseGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._semiMajorAxis = void 0; this._semiMajorAxisSubscription = void 0; this._semiMinorAxis = void 0; this._semiMinorAxisSubscription = void 0; this._height = void 0; this._heightSubscription = void 0; this._heightReference = void 0; this._heightReferenceSubscription = void 0; this._extrudedHeight = void 0; this._extrudedHeightSubscription = void 0; this._extrudedHeightReference = void 0; this._extrudedHeightReferenceSubscription = void 0; this._rotation = void 0; this._rotationSubscription = void 0; this._stRotation = void 0; this._stRotationSubscription = void 0; this._granularity = void 0; this._granularitySubscription = void 0; this._fill = void 0; this._fillSubscription = void 0; this._material = void 0; this._materialSubscription = void 0; this._outline = void 0; this._outlineSubscription = void 0; this._outlineColor = void 0; this._outlineColorSubscription = void 0; this._outlineWidth = void 0; this._outlineWidthSubscription = void 0; this._numberOfVerticalLines = void 0; this._numberOfVerticalLinesSubscription = void 0; this._shadows = void 0; this._shadowsSubscription = void 0; this._distanceDisplayCondition = void 0; this._distanceDisplayConditionSubscription = void 0; this._classificationType = void 0; this._classificationTypeSubscription = void 0; this._zIndex = void 0; this._zIndexSubscription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(EllipseGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof EllipseGraphics.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the ellipse. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default true */ show: createPropertyDescriptor_default("show"), /** * Gets or sets the numeric Property specifying the semi-major axis. * @memberof EllipseGraphics.prototype * @type {Property|undefined} */ semiMajorAxis: createPropertyDescriptor_default("semiMajorAxis"), /** * Gets or sets the numeric Property specifying the semi-minor axis. * @memberof EllipseGraphics.prototype * @type {Property|undefined} */ semiMinorAxis: createPropertyDescriptor_default("semiMinorAxis"), /** * Gets or sets the numeric Property specifying the altitude of the ellipse. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default 0.0 */ height: createPropertyDescriptor_default("height"), /** * Gets or sets the Property specifying the {@link HeightReference}. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ heightReference: createPropertyDescriptor_default("heightReference"), /** * Gets or sets the numeric Property specifying the altitude of the ellipse extrusion. * Setting this property creates volume starting at height and ending at this altitude. * @memberof EllipseGraphics.prototype * @type {Property|undefined} */ extrudedHeight: createPropertyDescriptor_default("extrudedHeight"), /** * Gets or sets the Property specifying the extruded {@link HeightReference}. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ extrudedHeightReference: createPropertyDescriptor_default("extrudedHeightReference"), /** * Gets or sets the numeric property specifying the rotation of the ellipse counter-clockwise from north. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default 0 */ rotation: createPropertyDescriptor_default("rotation"), /** * Gets or sets the numeric property specifying the rotation of the ellipse texture counter-clockwise from north. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default 0 */ stRotation: createPropertyDescriptor_default("stRotation"), /** * Gets or sets the numeric Property specifying the angular distance between points on the ellipse. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default {CesiumMath.RADIANS_PER_DEGREE} */ granularity: createPropertyDescriptor_default("granularity"), /** * Gets or sets the boolean Property specifying whether the ellipse is filled with the provided material. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default true */ fill: createPropertyDescriptor_default("fill"), /** * Gets or sets the Property specifying the material used to fill the ellipse. * @memberof EllipseGraphics.prototype * @type {MaterialProperty|undefined} * @default Color.WHITE */ material: createMaterialPropertyDescriptor_default("material"), /** * Gets or sets the Property specifying whether the ellipse is outlined. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default false */ outline: createPropertyDescriptor_default("outline"), /** * Gets or sets the Property specifying the {@link Color} of the outline. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default Color.BLACK */ outlineColor: createPropertyDescriptor_default("outlineColor"), /** * Gets or sets the numeric Property specifying the width of the outline. ** Note: This property will be ignored on all major browsers on Windows platforms. For details, see (@link https://github.com/CesiumGS/cesium/issues/40}. *
* @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default 1.0 */ outlineWidth: createPropertyDescriptor_default("outlineWidth"), /** * Gets or sets the numeric Property specifying the number of vertical lines to draw along the perimeter for the outline. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default 16 */ numberOfVerticalLines: createPropertyDescriptor_default("numberOfVerticalLines"), /** * Get or sets the enum Property specifying whether the ellipse * casts or receives shadows from light sources. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default ShadowMode.DISABLED */ shadows: createPropertyDescriptor_default("shadows"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this ellipse will be displayed. * @memberof EllipseGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ), /** * Gets or sets the {@link ClassificationType} Property specifying whether this ellipse will classify terrain, 3D Tiles, or both when on the ground. * @memberof EllipseGraphics.prototype * @type {Property|undefined} * @default ClassificationType.BOTH */ classificationType: createPropertyDescriptor_default("classificationType"), /** * Gets or sets the zIndex Property specifying the ellipse ordering. Only has an effect if the ellipse is constant and neither height or extrudedHeight are specified * @memberof EllipseGraphics.prototype * @type {ConstantProperty|undefined} * @default 0 */ zIndex: createPropertyDescriptor_default("zIndex") }); EllipseGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new EllipseGraphics(this); } result.show = this.show; result.semiMajorAxis = this.semiMajorAxis; result.semiMinorAxis = this.semiMinorAxis; result.height = this.height; result.heightReference = this.heightReference; result.extrudedHeight = this.extrudedHeight; result.extrudedHeightReference = this.extrudedHeightReference; result.rotation = this.rotation; result.stRotation = this.stRotation; result.granularity = this.granularity; result.fill = this.fill; result.material = this.material; result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.numberOfVerticalLines = this.numberOfVerticalLines; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; result.classificationType = this.classificationType; result.zIndex = this.zIndex; return result; }; EllipseGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.semiMajorAxis = this.semiMajorAxis ?? source.semiMajorAxis; this.semiMinorAxis = this.semiMinorAxis ?? source.semiMinorAxis; this.height = this.height ?? source.height; this.heightReference = this.heightReference ?? source.heightReference; this.extrudedHeight = this.extrudedHeight ?? source.extrudedHeight; this.extrudedHeightReference = this.extrudedHeightReference ?? source.extrudedHeightReference; this.rotation = this.rotation ?? source.rotation; this.stRotation = this.stRotation ?? source.stRotation; this.granularity = this.granularity ?? source.granularity; this.fill = this.fill ?? source.fill; this.material = this.material ?? source.material; this.outline = this.outline ?? source.outline; this.outlineColor = this.outlineColor ?? source.outlineColor; this.outlineWidth = this.outlineWidth ?? source.outlineWidth; this.numberOfVerticalLines = this.numberOfVerticalLines ?? source.numberOfVerticalLines; this.shadows = this.shadows ?? source.shadows; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; this.classificationType = this.classificationType ?? source.classificationType; this.zIndex = this.zIndex ?? source.zIndex; }; var EllipseGraphics_default = EllipseGraphics; // packages/engine/Source/DataSources/EllipsoidGraphics.js var import_InlineWorkers401 = __toESM(require_InlineWorkers(), 1); function EllipsoidGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._radii = void 0; this._radiiSubscription = void 0; this._innerRadii = void 0; this._innerRadiiSubscription = void 0; this._minimumClock = void 0; this._minimumClockSubscription = void 0; this._maximumClock = void 0; this._maximumClockSubscription = void 0; this._minimumCone = void 0; this._minimumConeSubscription = void 0; this._maximumCone = void 0; this._maximumConeSubscription = void 0; this._heightReference = void 0; this._heightReferenceSubscription = void 0; this._fill = void 0; this._fillSubscription = void 0; this._material = void 0; this._materialSubscription = void 0; this._outline = void 0; this._outlineSubscription = void 0; this._outlineColor = void 0; this._outlineColorSubscription = void 0; this._outlineWidth = void 0; this._outlineWidthSubscription = void 0; this._stackPartitions = void 0; this._stackPartitionsSubscription = void 0; this._slicePartitions = void 0; this._slicePartitionsSubscription = void 0; this._subdivisions = void 0; this._subdivisionsSubscription = void 0; this._shadows = void 0; this._shadowsSubscription = void 0; this._distanceDisplayCondition = void 0; this._distanceDisplayConditionSubscription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(EllipsoidGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof EllipsoidGraphics.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the ellipsoid. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default true */ show: createPropertyDescriptor_default("show"), /** * Gets or sets the {@link Cartesian3} {@link Property} specifying the radii of the ellipsoid. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} */ radii: createPropertyDescriptor_default("radii"), /** * Gets or sets the {@link Cartesian3} {@link Property} specifying the inner radii of the ellipsoid. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default radii */ innerRadii: createPropertyDescriptor_default("innerRadii"), /** * Gets or sets the Property specifying the minimum clock angle of the ellipsoid. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default 0.0 */ minimumClock: createPropertyDescriptor_default("minimumClock"), /** * Gets or sets the Property specifying the maximum clock angle of the ellipsoid. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default 2*PI */ maximumClock: createPropertyDescriptor_default("maximumClock"), /** * Gets or sets the Property specifying the minimum cone angle of the ellipsoid. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default 0.0 */ minimumCone: createPropertyDescriptor_default("minimumCone"), /** * Gets or sets the Property specifying the maximum cone angle of the ellipsoid. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default PI */ maximumCone: createPropertyDescriptor_default("maximumCone"), /** * Gets or sets the Property specifying the {@link HeightReference}. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ heightReference: createPropertyDescriptor_default("heightReference"), /** * Gets or sets the boolean Property specifying whether the ellipsoid is filled with the provided material. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default true */ fill: createPropertyDescriptor_default("fill"), /** * Gets or sets the Property specifying the material used to fill the ellipsoid. * @memberof EllipsoidGraphics.prototype * @type {MaterialProperty} * @default Color.WHITE */ material: createMaterialPropertyDescriptor_default("material"), /** * Gets or sets the Property specifying whether the ellipsoid is outlined. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default false */ outline: createPropertyDescriptor_default("outline"), /** * Gets or sets the Property specifying the {@link Color} of the outline. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default Color.BLACK */ outlineColor: createPropertyDescriptor_default("outlineColor"), /** * Gets or sets the numeric Property specifying the width of the outline. ** Note: This property will be ignored on all major browsers on Windows platforms. For details, see (@link https://github.com/CesiumGS/cesium/issues/40}. *
* @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default 1.0 */ outlineWidth: createPropertyDescriptor_default("outlineWidth"), /** * Gets or sets the Property specifying the number of stacks. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default 64 */ stackPartitions: createPropertyDescriptor_default("stackPartitions"), /** * Gets or sets the Property specifying the number of radial slices per 360 degrees. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default 64 */ slicePartitions: createPropertyDescriptor_default("slicePartitions"), /** * Gets or sets the Property specifying the number of samples per outline ring, determining the granularity of the curvature. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default 128 */ subdivisions: createPropertyDescriptor_default("subdivisions"), /** * Get or sets the enum Property specifying whether the ellipsoid * casts or receives shadows from light sources. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} * @default ShadowMode.DISABLED */ shadows: createPropertyDescriptor_default("shadows"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this ellipsoid will be displayed. * @memberof EllipsoidGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ) }); EllipsoidGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new EllipsoidGraphics(this); } result.show = this.show; result.radii = this.radii; result.innerRadii = this.innerRadii; result.minimumClock = this.minimumClock; result.maximumClock = this.maximumClock; result.minimumCone = this.minimumCone; result.maximumCone = this.maximumCone; result.heightReference = this.heightReference; result.fill = this.fill; result.material = this.material; result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.stackPartitions = this.stackPartitions; result.slicePartitions = this.slicePartitions; result.subdivisions = this.subdivisions; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; EllipsoidGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.radii = this.radii ?? source.radii; this.innerRadii = this.innerRadii ?? source.innerRadii; this.minimumClock = this.minimumClock ?? source.minimumClock; this.maximumClock = this.maximumClock ?? source.maximumClock; this.minimumCone = this.minimumCone ?? source.minimumCone; this.maximumCone = this.maximumCone ?? source.maximumCone; this.heightReference = this.heightReference ?? source.heightReference; this.fill = this.fill ?? source.fill; this.material = this.material ?? source.material; this.outline = this.outline ?? source.outline; this.outlineColor = this.outlineColor ?? source.outlineColor; this.outlineWidth = this.outlineWidth ?? source.outlineWidth; this.stackPartitions = this.stackPartitions ?? source.stackPartitions; this.slicePartitions = this.slicePartitions ?? source.slicePartitions; this.subdivisions = this.subdivisions ?? source.subdivisions; this.shadows = this.shadows ?? source.shadows; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; }; var EllipsoidGraphics_default = EllipsoidGraphics; // packages/engine/Source/DataSources/LabelGraphics.js var import_InlineWorkers402 = __toESM(require_InlineWorkers(), 1); function LabelGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._text = void 0; this._textSubscription = void 0; this._font = void 0; this._fontSubscription = void 0; this._style = void 0; this._styleSubscription = void 0; this._scale = void 0; this._scaleSubscription = void 0; this._showBackground = void 0; this._showBackgroundSubscription = void 0; this._backgroundColor = void 0; this._backgroundColorSubscription = void 0; this._backgroundPadding = void 0; this._backgroundPaddingSubscription = void 0; this._pixelOffset = void 0; this._pixelOffsetSubscription = void 0; this._eyeOffset = void 0; this._eyeOffsetSubscription = void 0; this._horizontalOrigin = void 0; this._horizontalOriginSubscription = void 0; this._verticalOrigin = void 0; this._verticalOriginSubscription = void 0; this._heightReference = void 0; this._heightReferenceSubscription = void 0; this._fillColor = void 0; this._fillColorSubscription = void 0; this._outlineColor = void 0; this._outlineColorSubscription = void 0; this._outlineWidth = void 0; this._outlineWidthSubscription = void 0; this._translucencyByDistance = void 0; this._translucencyByDistanceSubscription = void 0; this._pixelOffsetScaleByDistance = void 0; this._pixelOffsetScaleByDistanceSubscription = void 0; this._scaleByDistance = void 0; this._scaleByDistanceSubscription = void 0; this._distanceDisplayCondition = void 0; this._distanceDisplayConditionSubscription = void 0; this._disableDepthTestDistance = void 0; this._disableDepthTestDistanceSubscription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(LabelGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof LabelGraphics.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the label. * @memberof LabelGraphics.prototype * @type {Property|undefined} */ show: createPropertyDescriptor_default("show"), /** * Gets or sets the string Property specifying the text of the label. * Explicit newlines '\n' are supported. * @memberof LabelGraphics.prototype * @type {Property|undefined} */ text: createPropertyDescriptor_default("text"), /** * Gets or sets the string Property specifying the font in CSS syntax. * @memberof LabelGraphics.prototype * @type {Property|undefined} * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/font|CSS font on MDN} */ font: createPropertyDescriptor_default("font"), /** * Gets or sets the Property specifying the {@link LabelStyle}. * @memberof LabelGraphics.prototype * @type {Property|undefined} */ style: createPropertyDescriptor_default("style"), /** * Gets or sets the numeric Property specifying the uniform scale to apply to the image. * A scale greater than1.0 enlarges the label while a scale less than 1.0 shrinks it.
* *

0.5, 1.0,
* and 2.0.
* x increases from left to right, and y increases from top to bottom.
* *
default |
* l.pixeloffset = new Cartesian2(25, 75); |
*
x points towards the viewer's
* right, y points up, and z points into the screen.
* * An eye offset is commonly used to arrange multiple labels or objects at the same position, e.g., to * arrange a label above its corresponding 3D model. *
* Below, the label is positioned at the center of the Earth but an eye offset makes it always * appear on top of the Earth regardless of the viewer's or Earth's orientation. **
![]() |
* ![]() |
*
l.eyeOffset = new Cartesian3(0.0, 8000000.0, 0.0);1.0.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default true
*/
enableVerticalExaggeration: createPropertyDescriptor_default(
"enableVerticalExaggeration"
),
/**
* Gets or sets the numeric Property specifying the approximate minimum
* pixel size of the model regardless of zoom. This can be used to ensure that
* a model is visible even when the viewer zooms out. When 0.0,
* no minimum size is enforced.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default 0.0
*/
minimumPixelSize: createPropertyDescriptor_default("minimumPixelSize"),
/**
* Gets or sets the numeric Property specifying the maximum scale
* size of a model. This property is used as an upper limit for
* {@link ModelGraphics#minimumPixelSize}.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
*/
maximumScale: createPropertyDescriptor_default("maximumScale"),
/**
* Get or sets the boolean Property specifying whether textures
* may continue to stream in after the model is loaded.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
*/
incrementallyLoadTextures: createPropertyDescriptor_default(
"incrementallyLoadTextures"
),
/**
* Gets or sets the boolean Property specifying if glTF animations should be run.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default true
*/
runAnimations: createPropertyDescriptor_default("runAnimations"),
/**
* Gets or sets the boolean Property specifying if glTF animations should hold the last pose for time durations with no keyframes.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default true
*/
clampAnimations: createPropertyDescriptor_default("clampAnimations"),
/**
* Get or sets the enum Property specifying whether the model
* casts or receives shadows from light sources.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default ShadowMode.ENABLED
*/
shadows: createPropertyDescriptor_default("shadows"),
/**
* Gets or sets the Property specifying the {@link HeightReference}.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default HeightReference.NONE
*/
heightReference: createPropertyDescriptor_default("heightReference"),
/**
* Gets or sets the Property specifying the {@link Color} of the silhouette.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default Color.RED
*/
silhouetteColor: createPropertyDescriptor_default("silhouetteColor"),
/**
* Gets or sets the numeric Property specifying the size of the silhouette in pixels.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default 0.0
*/
silhouetteSize: createPropertyDescriptor_default("silhouetteSize"),
/**
* Gets or sets the Property specifying the {@link Color} that blends with the model's rendered color.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default Color.WHITE
*/
color: createPropertyDescriptor_default("color"),
/**
* Gets or sets the enum Property specifying how the color blends with the model.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default ColorBlendMode.HIGHLIGHT
*/
colorBlendMode: createPropertyDescriptor_default("colorBlendMode"),
/**
* A numeric Property specifying the color strength when the colorBlendMode is MIX.
* A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with
* any value in-between resulting in a mix of the two.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
* @default 0.5
*/
colorBlendAmount: createPropertyDescriptor_default("colorBlendAmount"),
/**
* A property specifying the {@link Cartesian2} used to scale the diffuse and specular image-based lighting contribution to the final color.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
*/
imageBasedLightingFactor: createPropertyDescriptor_default(
"imageBasedLightingFactor"
),
/**
* Gets or sets the {@link DynamicEnvironmentMapManager.ConstructorOptions} to apply to this model. This is represented as an {@link PropertyBag}.
* @memberof ModelGraphics.prototype
* @type {PropertyBag}
*/
environmentMapOptions: createPropertyDescriptor_default(
"environmentMapOptions",
void 0,
createEnvironmentMapPropertyBag
),
/**
* A property specifying the {@link Cartesian3} light color when shading the model. When undefined the scene's light color is used instead.
* @memberOf ModelGraphics.prototype
* @type {Property|undefined}
*/
lightColor: createPropertyDescriptor_default("lightColor"),
/**
* Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this model will be displayed.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
*/
distanceDisplayCondition: createPropertyDescriptor_default(
"distanceDisplayCondition"
),
/**
* Gets or sets the set of node transformations to apply to this model. This is represented as an {@link PropertyBag}, where keys are
* names of nodes, and values are {@link TranslationRotationScale} Properties describing the transformation to apply to that node.
* The transformation is applied after the node's existing transformation as specified in the glTF, and does not replace the node's existing transformation.
* @memberof ModelGraphics.prototype
* @type {PropertyBag}
*/
nodeTransformations: createPropertyDescriptor_default(
"nodeTransformations",
void 0,
createNodeTransformationPropertyBag
),
/**
* Gets or sets the set of articulation values to apply to this model. This is represented as an {@link PropertyBag}, where keys are
* composed as the name of the articulation, a single space, and the name of the stage.
* @memberof ModelGraphics.prototype
* @type {PropertyBag}
*/
articulations: createPropertyDescriptor_default(
"articulations",
void 0,
createArticulationStagePropertyBag
),
/**
* A property specifying the {@link ClippingPlaneCollection} used to selectively disable rendering the model.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
*/
clippingPlanes: createPropertyDescriptor_default("clippingPlanes"),
/**
* Gets or sets the {@link CustomShader} to apply to this model. When undefined, no custom shader code is used.
* @memberof ModelGraphics.prototype
* @type {Property|undefined}
*/
customShader: createPropertyDescriptor_default("customShader")
});
ModelGraphics.prototype.clone = function(result) {
if (!defined_default(result)) {
return new ModelGraphics(this);
}
result.show = this.show;
result.uri = this.uri;
result.scale = this.scale;
result.enableVerticalExaggeration = this.enableVerticalExaggeration;
result.minimumPixelSize = this.minimumPixelSize;
result.maximumScale = this.maximumScale;
result.incrementallyLoadTextures = this.incrementallyLoadTextures;
result.runAnimations = this.runAnimations;
result.clampAnimations = this.clampAnimations;
result.heightReference = this._heightReference;
result.silhouetteColor = this.silhouetteColor;
result.silhouetteSize = this.silhouetteSize;
result.color = this.color;
result.colorBlendMode = this.colorBlendMode;
result.colorBlendAmount = this.colorBlendAmount;
result.imageBasedLightingFactor = this.imageBasedLightingFactor;
result.environmentMapOptions = this.environmentMapOptions;
result.lightColor = this.lightColor;
result.distanceDisplayCondition = this.distanceDisplayCondition;
result.nodeTransformations = this.nodeTransformations;
result.articulations = this.articulations;
result.clippingPlanes = this.clippingPlanes;
result.customShader = this.customShader;
return result;
};
ModelGraphics.prototype.merge = function(source) {
if (!defined_default(source)) {
throw new DeveloperError_default("source is required.");
}
this.show = this.show ?? source.show;
this.uri = this.uri ?? source.uri;
this.scale = this.scale ?? source.scale;
this.enableVerticalExaggeration = this.enableVerticalExaggeration ?? source.enableVerticalExaggeration;
this.minimumPixelSize = this.minimumPixelSize ?? source.minimumPixelSize;
this.maximumScale = this.maximumScale ?? source.maximumScale;
this.incrementallyLoadTextures = this.incrementallyLoadTextures ?? source.incrementallyLoadTextures;
this.runAnimations = this.runAnimations ?? source.runAnimations;
this.clampAnimations = this.clampAnimations ?? source.clampAnimations;
this.shadows = this.shadows ?? source.shadows;
this.heightReference = this.heightReference ?? source.heightReference;
this.silhouetteColor = this.silhouetteColor ?? source.silhouetteColor;
this.silhouetteSize = this.silhouetteSize ?? source.silhouetteSize;
this.color = this.color ?? source.color;
this.colorBlendMode = this.colorBlendMode ?? source.colorBlendMode;
this.colorBlendAmount = this.colorBlendAmount ?? source.colorBlendAmount;
this.imageBasedLightingFactor = this.imageBasedLightingFactor ?? source.imageBasedLightingFactor;
this.environmentMapOptions = this.environmentMapOptions ?? source.environmentMapOptions;
this.lightColor = this.lightColor ?? source.lightColor;
this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition;
this.clippingPlanes = this.clippingPlanes ?? source.clippingPlanes;
this.customShader = this.customShader ?? source.customShader;
const sourceNodeTransformations = source.nodeTransformations;
if (defined_default(sourceNodeTransformations)) {
const targetNodeTransformations = this.nodeTransformations;
if (defined_default(targetNodeTransformations)) {
targetNodeTransformations.merge(sourceNodeTransformations);
} else {
this.nodeTransformations = new PropertyBag_default(
sourceNodeTransformations,
createNodeTransformationProperty
);
}
}
const sourceArticulations = source.articulations;
if (defined_default(sourceArticulations)) {
const targetArticulations = this.articulations;
if (defined_default(targetArticulations)) {
targetArticulations.merge(sourceArticulations);
} else {
this.articulations = new PropertyBag_default(sourceArticulations);
}
}
};
var ModelGraphics_default = ModelGraphics;
// packages/engine/Source/DataSources/Cesium3DTilesetGraphics.js
var import_InlineWorkers407 = __toESM(require_InlineWorkers(), 1);
function Cesium3DTilesetGraphics(options) {
this._definitionChanged = new Event_default();
this._show = void 0;
this._showSubscription = void 0;
this._uri = void 0;
this._uriSubscription = void 0;
this._maximumScreenSpaceError = void 0;
this._maximumScreenSpaceErrorSubscription = void 0;
this.merge(options ?? Frozen_default.EMPTY_OBJECT);
}
Object.defineProperties(Cesium3DTilesetGraphics.prototype, {
/**
* Gets the event that is raised whenever a property or sub-property is changed or modified.
* @memberof Cesium3DTilesetGraphics.prototype
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the boolean Property specifying the visibility of the model.
* @memberof Cesium3DTilesetGraphics.prototype
* @type {Property|undefined}
* @default true
*/
show: createPropertyDescriptor_default("show"),
/**
* Gets or sets the string Property specifying the URI of the glTF asset.
* @memberof Cesium3DTilesetGraphics.prototype
* @type {Property|undefined}
*/
uri: createPropertyDescriptor_default("uri"),
/**
* Gets or sets the maximum screen space error used to drive level of detail refinement.
* @memberof Cesium3DTilesetGraphics.prototype
* @type {Property|undefined}
*/
maximumScreenSpaceError: createPropertyDescriptor_default("maximumScreenSpaceError")
});
Cesium3DTilesetGraphics.prototype.clone = function(result) {
if (!defined_default(result)) {
return new Cesium3DTilesetGraphics(this);
}
result.show = this.show;
result.uri = this.uri;
result.maximumScreenSpaceError = this.maximumScreenSpaceError;
return result;
};
Cesium3DTilesetGraphics.prototype.merge = function(source) {
if (!defined_default(source)) {
throw new DeveloperError_default("source is required.");
}
this.show = this.show ?? source.show;
this.uri = this.uri ?? source.uri;
this.maximumScreenSpaceError = this.maximumScreenSpaceError ?? source.maximumScreenSpaceError;
};
var Cesium3DTilesetGraphics_default = Cesium3DTilesetGraphics;
// packages/engine/Source/DataSources/PathGraphics.js
var import_InlineWorkers408 = __toESM(require_InlineWorkers(), 1);
function PathGraphics(options) {
this._definitionChanged = new Event_default();
this._show = void 0;
this._showSubscription = void 0;
this._leadTime = void 0;
this._leadTimeSubscription = void 0;
this._trailTime = void 0;
this._trailTimeSubscription = void 0;
this._width = void 0;
this._widthSubscription = void 0;
this._resolution = void 0;
this._resolutionSubscription = void 0;
this._material = void 0;
this._materialSubscription = void 0;
this._distanceDisplayCondition = void 0;
this._distanceDisplayConditionSubscription = void 0;
this.merge(options ?? Frozen_default.EMPTY_OBJECT);
}
Object.defineProperties(PathGraphics.prototype, {
/**
* Gets the event that is raised whenever a property or sub-property is changed or modified.
* @memberof PathGraphics.prototype
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the boolean Property specifying the visibility of the path.
* @memberof PathGraphics.prototype
* @type {Property|undefined}
* @default true
*/
show: createPropertyDescriptor_default("show"),
/**
* Gets or sets the Property specifying the number of seconds in front of the object to show.
* @memberof PathGraphics.prototype
* @type {Property|undefined}
*/
leadTime: createPropertyDescriptor_default("leadTime"),
/**
* Gets or sets the Property specifying the number of seconds behind the object to show.
* @memberof PathGraphics.prototype
* @type {Property|undefined}
*/
trailTime: createPropertyDescriptor_default("trailTime"),
/**
* Gets or sets the numeric Property specifying the width in pixels.
* @memberof PathGraphics.prototype
* @type {Property|undefined}
* @default 1.0
*/
width: createPropertyDescriptor_default("width"),
/**
* Gets or sets the Property specifying the maximum number of seconds to step when sampling the position.
* @memberof PathGraphics.prototype
* @type {Property|undefined}
* @default 60
*/
resolution: createPropertyDescriptor_default("resolution"),
/**
* Gets or sets the Property specifying the material used to draw the path.
* @memberof PathGraphics.prototype
* @type {MaterialProperty}
* @default Color.WHITE
*/
material: createMaterialPropertyDescriptor_default("material"),
/**
* Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this path will be displayed.
* @memberof PathGraphics.prototype
* @type {Property|undefined}
*/
distanceDisplayCondition: createPropertyDescriptor_default(
"distanceDisplayCondition"
)
});
PathGraphics.prototype.clone = function(result) {
if (!defined_default(result)) {
return new PathGraphics(this);
}
result.show = this.show;
result.leadTime = this.leadTime;
result.trailTime = this.trailTime;
result.width = this.width;
result.resolution = this.resolution;
result.material = this.material;
result.distanceDisplayCondition = this.distanceDisplayCondition;
return result;
};
PathGraphics.prototype.merge = function(source) {
if (!defined_default(source)) {
throw new DeveloperError_default("source is required.");
}
this.show = this.show ?? source.show;
this.leadTime = this.leadTime ?? source.leadTime;
this.trailTime = this.trailTime ?? source.trailTime;
this.width = this.width ?? source.width;
this.resolution = this.resolution ?? source.resolution;
this.material = this.material ?? source.material;
this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition;
};
var PathGraphics_default = PathGraphics;
// packages/engine/Source/DataSources/PlaneGraphics.js
var import_InlineWorkers409 = __toESM(require_InlineWorkers(), 1);
function PlaneGraphics(options) {
this._definitionChanged = new Event_default();
this._show = void 0;
this._showSubscription = void 0;
this._plane = void 0;
this._planeSubscription = void 0;
this._dimensions = void 0;
this._dimensionsSubscription = void 0;
this._fill = void 0;
this._fillSubscription = void 0;
this._material = void 0;
this._materialSubscription = void 0;
this._outline = void 0;
this._outlineSubscription = void 0;
this._outlineColor = void 0;
this._outlineColorSubscription = void 0;
this._outlineWidth = void 0;
this._outlineWidthSubscription = void 0;
this._shadows = void 0;
this._shadowsSubscription = void 0;
this._distanceDisplayCondition = void 0;
this._distanceDisplayConditionSubscription = void 0;
this.merge(options ?? Frozen_default.EMPTY_OBJECT);
}
Object.defineProperties(PlaneGraphics.prototype, {
/**
* Gets the event that is raised whenever a property or sub-property is changed or modified.
* @memberof PlaneGraphics.prototype
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the boolean Property specifying the visibility of the plane.
* @memberof PlaneGraphics.prototype
* @type {Property|undefined}
* @default true
*/
show: createPropertyDescriptor_default("show"),
/**
* Gets or sets the {@link Plane} Property specifying the normal and distance of the plane.
*
* @memberof PlaneGraphics.prototype
* @type {Property|undefined}
*/
plane: createPropertyDescriptor_default("plane"),
/**
* Gets or sets the {@link Cartesian2} Property specifying the width and height of the plane.
*
* @memberof PlaneGraphics.prototype
* @type {Property|undefined}
*/
dimensions: createPropertyDescriptor_default("dimensions"),
/**
* Gets or sets the boolean Property specifying whether the plane is filled with the provided material.
* @memberof PlaneGraphics.prototype
* @type {Property|undefined}
* @default true
*/
fill: createPropertyDescriptor_default("fill"),
/**
* Gets or sets the material used to fill the plane.
* @memberof PlaneGraphics.prototype
* @type {MaterialProperty}
* @default Color.WHITE
*/
material: createMaterialPropertyDescriptor_default("material"),
/**
* Gets or sets the Property specifying whether the plane is outlined.
* @memberof PlaneGraphics.prototype
* @type {Property|undefined}
* @default false
*/
outline: createPropertyDescriptor_default("outline"),
/**
* Gets or sets the Property specifying the {@link Color} of the outline.
* @memberof PlaneGraphics.prototype
* @type {Property|undefined}
* @default Color.BLACK
*/
outlineColor: createPropertyDescriptor_default("outlineColor"),
/**
* Gets or sets the numeric Property specifying the width of the outline.
* * Note: This property will be ignored on all major browsers on Windows platforms. For details, see (@link https://github.com/CesiumGS/cesium/issues/40}. *
* @memberof PlaneGraphics.prototype * @type {Property|undefined} * @default 1.0 */ outlineWidth: createPropertyDescriptor_default("outlineWidth"), /** * Get or sets the enum Property specifying whether the plane * casts or receives shadows from light sources. * @memberof PlaneGraphics.prototype * @type {Property|undefined} * @default ShadowMode.DISABLED */ shadows: createPropertyDescriptor_default("shadows"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this plane will be displayed. * @memberof PlaneGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ) }); PlaneGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new PlaneGraphics(this); } result.show = this.show; result.plane = this.plane; result.dimensions = this.dimensions; result.fill = this.fill; result.material = this.material; result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; PlaneGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.plane = this.plane ?? source.plane; this.dimensions = this.dimensions ?? source.dimensions; this.fill = this.fill ?? source.fill; this.material = this.material ?? source.material; this.outline = this.outline ?? source.outline; this.outlineColor = this.outlineColor ?? source.outlineColor; this.outlineWidth = this.outlineWidth ?? source.outlineWidth; this.shadows = this.shadows ?? source.shadows; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; }; var PlaneGraphics_default = PlaneGraphics; // packages/engine/Source/DataSources/PointGraphics.js var import_InlineWorkers410 = __toESM(require_InlineWorkers(), 1); function PointGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._pixelSize = void 0; this._pixelSizeSubscription = void 0; this._heightReference = void 0; this._heightReferenceSubscription = void 0; this._color = void 0; this._colorSubscription = void 0; this._outlineColor = void 0; this._outlineColorSubscription = void 0; this._outlineWidth = void 0; this._outlineWidthSubscription = void 0; this._scaleByDistance = void 0; this._scaleByDistanceSubscription = void 0; this._translucencyByDistance = void 0; this._translucencyByDistanceSubscription = void 0; this._distanceDisplayCondition = void 0; this._distanceDisplayConditionSubscription = void 0; this._disableDepthTestDistance = void 0; this._disableDepthTestDistanceSubscription = void 0; this._splitDirection = void 0; this._splitDirectionSubscription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(PointGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof PointGraphics.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the point. * @memberof PointGraphics.prototype * @type {Property|undefined} * @default true */ show: createPropertyDescriptor_default("show"), /** * Gets or sets the numeric Property specifying the size in pixels. * @memberof PointGraphics.prototype * @type {Property|undefined} * @default 1 */ pixelSize: createPropertyDescriptor_default("pixelSize"), /** * Gets or sets the Property specifying the {@link HeightReference}. * @memberof PointGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ heightReference: createPropertyDescriptor_default("heightReference"), /** * Gets or sets the Property specifying the {@link Color} of the point. * @memberof PointGraphics.prototype * @type {Property|undefined} * @default Color.WHITE */ color: createPropertyDescriptor_default("color"), /** * Gets or sets the Property specifying the {@link Color} of the outline. * @memberof PointGraphics.prototype * @type {Property|undefined} * @default Color.BLACK */ outlineColor: createPropertyDescriptor_default("outlineColor"), /** * Gets or sets the numeric Property specifying the the outline width in pixels. * @memberof PointGraphics.prototype * @type {Property|undefined} * @default 0 */ outlineWidth: createPropertyDescriptor_default("outlineWidth"), /** * Gets or sets the {@link NearFarScalar} Property used to scale the point based on distance. * If undefined, a constant size is used. * @memberof PointGraphics.prototype * @type {Property|undefined} */ scaleByDistance: createPropertyDescriptor_default("scaleByDistance"), /** * Gets or sets {@link NearFarScalar} Property specifying the translucency of the point based on the distance from the camera. * A point's translucency will interpolate between the {@link NearFarScalar#nearValue} and * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}. * Outside of these ranges the points's translucency remains clamped to the nearest bound. * @memberof PointGraphics.prototype * @type {Property|undefined} */ translucencyByDistance: createPropertyDescriptor_default("translucencyByDistance"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this point will be displayed. * @memberof PointGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ), /** * Gets or sets the distance from the camera at which to disable the depth test to, for example, prevent clipping against terrain. * When set to zero, the depth test is always applied. When set to Number.POSITIVE_INFINITY, the depth test is never applied. * @memberof PointGraphics.prototype * @type {Property|undefined} */ disableDepthTestDistance: createPropertyDescriptor_default( "disableDepthTestDistance" ), /** * Gets or sets the Property specifying the {@link SplitDirection} of this point. * @memberof PointGraphics.prototype * @type {Property|undefined} * @default SplitDirection.NONE */ splitDirection: createPropertyDescriptor_default("splitDirection") }); PointGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new PointGraphics(this); } result.show = this.show; result.pixelSize = this.pixelSize; result.heightReference = this.heightReference; result.color = this.color; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.scaleByDistance = this.scaleByDistance; result.translucencyByDistance = this._translucencyByDistance; result.distanceDisplayCondition = this.distanceDisplayCondition; result.disableDepthTestDistance = this.disableDepthTestDistance; result.splitDirection = this.splitDirection; return result; }; PointGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.pixelSize = this.pixelSize ?? source.pixelSize; this.heightReference = this.heightReference ?? source.heightReference; this.color = this.color ?? source.color; this.outlineColor = this.outlineColor ?? source.outlineColor; this.outlineWidth = this.outlineWidth ?? source.outlineWidth; this.scaleByDistance = this.scaleByDistance ?? source.scaleByDistance; this.translucencyByDistance = this._translucencyByDistance ?? source.translucencyByDistance; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; this.disableDepthTestDistance = this.disableDepthTestDistance ?? source.disableDepthTestDistance; this.splitDirection = this.splitDirection ?? source.splitDirection; }; var PointGraphics_default = PointGraphics; // packages/engine/Source/DataSources/PolygonGraphics.js var import_InlineWorkers412 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Core/PolygonHierarchy.js var import_InlineWorkers411 = __toESM(require_InlineWorkers(), 1); function PolygonHierarchy(positions, holes) { this.positions = defined_default(positions) ? positions : []; this.holes = defined_default(holes) ? holes : []; } var PolygonHierarchy_default = PolygonHierarchy; // packages/engine/Source/DataSources/PolygonGraphics.js function createPolygonHierarchyProperty(value) { if (Array.isArray(value)) { value = new PolygonHierarchy_default(value); } return new ConstantProperty_default(value); } function PolygonGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._hierarchy = void 0; this._hierarchySubscription = void 0; this._height = void 0; this._heightSubscription = void 0; this._heightReference = void 0; this._heightReferenceSubscription = void 0; this._extrudedHeight = void 0; this._extrudedHeightSubscription = void 0; this._extrudedHeightReference = void 0; this._extrudedHeightReferenceSubscription = void 0; this._stRotation = void 0; this._stRotationSubscription = void 0; this._granularity = void 0; this._granularitySubscription = void 0; this._fill = void 0; this._fillSubscription = void 0; this._material = void 0; this._materialSubscription = void 0; this._outline = void 0; this._outlineSubscription = void 0; this._outlineColor = void 0; this._outlineColorSubscription = void 0; this._outlineWidth = void 0; this._outlineWidthSubscription = void 0; this._perPositionHeight = void 0; this._perPositionHeightSubscription = void 0; this._closeTop = void 0; this._closeTopSubscription = void 0; this._closeBottom = void 0; this._closeBottomSubscription = void 0; this._arcType = void 0; this._arcTypeSubscription = void 0; this._shadows = void 0; this._shadowsSubscription = void 0; this._distanceDisplayCondition = void 0; this._distanceDisplayConditionSubscription = void 0; this._classificationType = void 0; this._classificationTypeSubscription = void 0; this._zIndex = void 0; this._zIndexSubscription = void 0; this._textureCoordinates = void 0; this._textureCoordinatesSubscription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(PolygonGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof PolygonGraphics.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the polygon. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default true */ show: createPropertyDescriptor_default("show"), /** * Gets or sets the Property specifying the {@link PolygonHierarchy}. * @memberof PolygonGraphics.prototype * @type {Property|undefined} */ hierarchy: createPropertyDescriptor_default( "hierarchy", void 0, createPolygonHierarchyProperty ), /** * Gets or sets the numeric Property specifying the constant altitude of the polygon. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default 0.0 */ height: createPropertyDescriptor_default("height"), /** * Gets or sets the Property specifying the {@link HeightReference}. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ heightReference: createPropertyDescriptor_default("heightReference"), /** * Gets or sets the numeric Property specifying the altitude of the polygon extrusion. * If {@link PolygonGraphics#perPositionHeight} is false, the volume starts at {@link PolygonGraphics#height} and ends at this altitude. * If {@link PolygonGraphics#perPositionHeight} is true, the volume starts at the height of each {@link PolygonGraphics#hierarchy} position and ends at this altitude. * @memberof PolygonGraphics.prototype * @type {Property|undefined} */ extrudedHeight: createPropertyDescriptor_default("extrudedHeight"), /** * Gets or sets the Property specifying the extruded {@link HeightReference}. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ extrudedHeightReference: createPropertyDescriptor_default("extrudedHeightReference"), /** * Gets or sets the numeric property specifying the rotation of the polygon texture counter-clockwise from north. Only has an effect if textureCoordinates is not defined. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default 0 */ stRotation: createPropertyDescriptor_default("stRotation"), /** * Gets or sets the numeric Property specifying the angular distance between points on the polygon. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default {CesiumMath.RADIANS_PER_DEGREE} */ granularity: createPropertyDescriptor_default("granularity"), /** * Gets or sets the boolean Property specifying whether the polygon is filled with the provided material. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default true */ fill: createPropertyDescriptor_default("fill"), /** * Gets or sets the Property specifying the material used to fill the polygon. * @memberof PolygonGraphics.prototype * @type {MaterialProperty} * @default Color.WHITE */ material: createMaterialPropertyDescriptor_default("material"), /** * Gets or sets the Property specifying whether the polygon is outlined. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default false */ outline: createPropertyDescriptor_default("outline"), /** * Gets or sets the Property specifying the {@link Color} of the outline. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default Color.BLACK */ outlineColor: createPropertyDescriptor_default("outlineColor"), /** * Gets or sets the numeric Property specifying the width of the outline. ** Note: This property will be ignored on all major browsers on Windows platforms. For details, see (@link https://github.com/CesiumGS/cesium/issues/40}. *
* @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default 1.0 */ outlineWidth: createPropertyDescriptor_default("outlineWidth"), /** * Gets or sets the boolean specifying whether or not the the height of each position is used. * If true, the shape will have non-uniform altitude defined by the height of each {@link PolygonGraphics#hierarchy} position. * If false, the shape will have a constant altitude as specified by {@link PolygonGraphics#height}. * @memberof PolygonGraphics.prototype * @type {Property|undefined} */ perPositionHeight: createPropertyDescriptor_default("perPositionHeight"), /** * Gets or sets a boolean specifying whether or not the top of an extruded polygon is included. * @memberof PolygonGraphics.prototype * @type {Property|undefined} */ closeTop: createPropertyDescriptor_default("closeTop"), /** * Gets or sets a boolean specifying whether or not the bottom of an extruded polygon is included. * @memberof PolygonGraphics.prototype * @type {Property|undefined} */ closeBottom: createPropertyDescriptor_default("closeBottom"), /** * Gets or sets the {@link ArcType} Property specifying the type of lines the polygon edges use. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default ArcType.GEODESIC */ arcType: createPropertyDescriptor_default("arcType"), /** * Get or sets the enum Property specifying whether the polygon * casts or receives shadows from light sources. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default ShadowMode.DISABLED */ shadows: createPropertyDescriptor_default("shadows"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this polygon will be displayed. * @memberof PolygonGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ), /** * Gets or sets the {@link ClassificationType} Property specifying whether this polygon will classify terrain, 3D Tiles, or both when on the ground. * @memberof PolygonGraphics.prototype * @type {Property|undefined} * @default ClassificationType.BOTH */ classificationType: createPropertyDescriptor_default("classificationType"), /** * Gets or sets the zIndex Prperty specifying the ordering of ground geometry. Only has an effect if the polygon is constant and neither height or extrudedHeight are specified. * @memberof PolygonGraphics.prototype * @type {ConstantProperty|undefined} * @default 0 */ zIndex: createPropertyDescriptor_default("zIndex"), /** * A Property specifying texture coordinates as a {@link PolygonHierarchy} of {@link Cartesian2} points. Has no effect for ground primitives. * @memberof PolygonGraphics.prototype * @type {Property|undefined} */ textureCoordinates: createPropertyDescriptor_default("textureCoordinates") }); PolygonGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new PolygonGraphics(this); } result.show = this.show; result.hierarchy = this.hierarchy; result.height = this.height; result.heightReference = this.heightReference; result.extrudedHeight = this.extrudedHeight; result.extrudedHeightReference = this.extrudedHeightReference; result.stRotation = this.stRotation; result.granularity = this.granularity; result.fill = this.fill; result.material = this.material; result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.perPositionHeight = this.perPositionHeight; result.closeTop = this.closeTop; result.closeBottom = this.closeBottom; result.arcType = this.arcType; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; result.classificationType = this.classificationType; result.zIndex = this.zIndex; result.textureCoordinates = this.textureCoordinates; return result; }; PolygonGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.hierarchy = this.hierarchy ?? source.hierarchy; this.height = this.height ?? source.height; this.heightReference = this.heightReference ?? source.heightReference; this.extrudedHeight = this.extrudedHeight ?? source.extrudedHeight; this.extrudedHeightReference = this.extrudedHeightReference ?? source.extrudedHeightReference; this.stRotation = this.stRotation ?? source.stRotation; this.granularity = this.granularity ?? source.granularity; this.fill = this.fill ?? source.fill; this.material = this.material ?? source.material; this.outline = this.outline ?? source.outline; this.outlineColor = this.outlineColor ?? source.outlineColor; this.outlineWidth = this.outlineWidth ?? source.outlineWidth; this.perPositionHeight = this.perPositionHeight ?? source.perPositionHeight; this.closeTop = this.closeTop ?? source.closeTop; this.closeBottom = this.closeBottom ?? source.closeBottom; this.arcType = this.arcType ?? source.arcType; this.shadows = this.shadows ?? source.shadows; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; this.classificationType = this.classificationType ?? source.classificationType; this.zIndex = this.zIndex ?? source.zIndex; this.textureCoordinates = this.textureCoordinates ?? source.textureCoordinates; }; var PolygonGraphics_default = PolygonGraphics; // packages/engine/Source/DataSources/PolylineGraphics.js var import_InlineWorkers413 = __toESM(require_InlineWorkers(), 1); function PolylineGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._positions = void 0; this._positionsSubscription = void 0; this._width = void 0; this._widthSubscription = void 0; this._granularity = void 0; this._granularitySubscription = void 0; this._material = void 0; this._materialSubscription = void 0; this._depthFailMaterial = void 0; this._depthFailMaterialSubscription = void 0; this._arcType = void 0; this._arcTypeSubscription = void 0; this._clampToGround = void 0; this._clampToGroundSubscription = void 0; this._shadows = void 0; this._shadowsSubscription = void 0; this._distanceDisplayCondition = void 0; this._distanceDisplayConditionSubscription = void 0; this._classificationType = void 0; this._classificationTypeSubscription = void 0; this._zIndex = void 0; this._zIndexSubscription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(PolylineGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof PolylineGraphics.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the polyline. * @memberof PolylineGraphics.prototype * @type {Property|undefined} * @default true */ show: createPropertyDescriptor_default("show"), /** * Gets or sets the Property specifying the array of {@link Cartesian3} * positions that define the line strip. * @memberof PolylineGraphics.prototype * @type {Property|undefined} */ positions: createPropertyDescriptor_default("positions"), /** * Gets or sets the numeric Property specifying the width in pixels. * @memberof PolylineGraphics.prototype * @type {Property|undefined} * @default 1.0 */ width: createPropertyDescriptor_default("width"), /** * Gets or sets the numeric Property specifying the angular distance between each latitude and longitude if arcType is not ArcType.NONE and clampToGround is false. * @memberof PolylineGraphics.prototype * @type {Property|undefined} * @default Cesium.Math.RADIANS_PER_DEGREE */ granularity: createPropertyDescriptor_default("granularity"), /** * Gets or sets the Property specifying the material used to draw the polyline. * @memberof PolylineGraphics.prototype * @type {MaterialProperty} * @default Color.WHITE */ material: createMaterialPropertyDescriptor_default("material"), /** * Gets or sets the Property specifying the material used to draw the polyline when it fails the depth test. ** Requires the EXT_frag_depth WebGL extension to render properly. If the extension is not supported, * there may be artifacts. *
* @memberof PolylineGraphics.prototype * @type {MaterialProperty} * @default undefined */ depthFailMaterial: createMaterialPropertyDescriptor_default("depthFailMaterial"), /** * Gets or sets the {@link ArcType} Property specifying whether the line segments should be great arcs, rhumb lines or linearly connected. * @memberof PolylineGraphics.prototype * @type {Property|undefined} * @default ArcType.GEODESIC */ arcType: createPropertyDescriptor_default("arcType"), /** * Gets or sets the boolean Property specifying whether the polyline * should be clamped to the ground. * @memberof PolylineGraphics.prototype * @type {Property|undefined} * @default false */ clampToGround: createPropertyDescriptor_default("clampToGround"), /** * Get or sets the enum Property specifying whether the polyline * casts or receives shadows from light sources. * @memberof PolylineGraphics.prototype * @type {Property|undefined} * @default ShadowMode.DISABLED */ shadows: createPropertyDescriptor_default("shadows"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this polyline will be displayed. * @memberof PolylineGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ), /** * Gets or sets the {@link ClassificationType} Property specifying whether this polyline will classify terrain, 3D Tiles, or both when on the ground. * @memberof PolylineGraphics.prototype * @type {Property|undefined} * @default ClassificationType.BOTH */ classificationType: createPropertyDescriptor_default("classificationType"), /** * Gets or sets the zIndex Property specifying the ordering of the polyline. Only has an effect if `clampToGround` is true and polylines on terrain is supported. * @memberof PolylineGraphics.prototype * @type {ConstantProperty|undefined} * @default 0 */ zIndex: createPropertyDescriptor_default("zIndex") }); PolylineGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new PolylineGraphics(this); } result.show = this.show; result.positions = this.positions; result.width = this.width; result.granularity = this.granularity; result.material = this.material; result.depthFailMaterial = this.depthFailMaterial; result.arcType = this.arcType; result.clampToGround = this.clampToGround; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; result.classificationType = this.classificationType; result.zIndex = this.zIndex; return result; }; PolylineGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.positions = this.positions ?? source.positions; this.width = this.width ?? source.width; this.granularity = this.granularity ?? source.granularity; this.material = this.material ?? source.material; this.depthFailMaterial = this.depthFailMaterial ?? source.depthFailMaterial; this.arcType = this.arcType ?? source.arcType; this.clampToGround = this.clampToGround ?? source.clampToGround; this.shadows = this.shadows ?? source.shadows; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; this.classificationType = this.classificationType ?? source.classificationType; this.zIndex = this.zIndex ?? source.zIndex; }; var PolylineGraphics_default = PolylineGraphics; // packages/engine/Source/DataSources/PolylineVolumeGraphics.js var import_InlineWorkers414 = __toESM(require_InlineWorkers(), 1); function PolylineVolumeGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._positions = void 0; this._positionsSubscription = void 0; this._shape = void 0; this._shapeSubscription = void 0; this._cornerType = void 0; this._cornerTypeSubscription = void 0; this._granularity = void 0; this._granularitySubscription = void 0; this._fill = void 0; this._fillSubscription = void 0; this._material = void 0; this._materialSubscription = void 0; this._outline = void 0; this._outlineSubscription = void 0; this._outlineColor = void 0; this._outlineColorSubscription = void 0; this._outlineWidth = void 0; this._outlineWidthSubscription = void 0; this._shadows = void 0; this._shadowsSubscription = void 0; this._distanceDisplayCondition = void 0; this._distanceDisplayConditionSubsription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(PolylineVolumeGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof PolylineVolumeGraphics.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the volume. * @memberof PolylineVolumeGraphics.prototype * @type {Property|undefined} * @default true */ show: createPropertyDescriptor_default("show"), /** * Gets or sets the Property specifying the array of {@link Cartesian3} positions which define the line strip. * @memberof PolylineVolumeGraphics.prototype * @type {Property|undefined} */ positions: createPropertyDescriptor_default("positions"), /** * Gets or sets the Property specifying the array of {@link Cartesian2} positions which define the shape to be extruded. * @memberof PolylineVolumeGraphics.prototype * @type {Property|undefined} */ shape: createPropertyDescriptor_default("shape"), /** * Gets or sets the {@link CornerType} Property specifying the style of the corners. * @memberof PolylineVolumeGraphics.prototype * @type {Property|undefined} * @default CornerType.ROUNDED */ cornerType: createPropertyDescriptor_default("cornerType"), /** * Gets or sets the numeric Property specifying the angular distance between points on the volume. * @memberof PolylineVolumeGraphics.prototype * @type {Property|undefined} * @default {CesiumMath.RADIANS_PER_DEGREE} */ granularity: createPropertyDescriptor_default("granularity"), /** * Gets or sets the boolean Property specifying whether the volume is filled with the provided material. * @memberof PolylineVolumeGraphics.prototype * @type {Property|undefined} * @default true */ fill: createPropertyDescriptor_default("fill"), /** * Gets or sets the Property specifying the material used to fill the volume. * @memberof PolylineVolumeGraphics.prototype * @type {MaterialProperty} * @default Color.WHITE */ material: createMaterialPropertyDescriptor_default("material"), /** * Gets or sets the Property specifying whether the volume is outlined. * @memberof PolylineVolumeGraphics.prototype * @type {Property|undefined} * @default false */ outline: createPropertyDescriptor_default("outline"), /** * Gets or sets the Property specifying the {@link Color} of the outline. * @memberof PolylineVolumeGraphics.prototype * @type {Property|undefined} * @default Color.BLACK */ outlineColor: createPropertyDescriptor_default("outlineColor"), /** * Gets or sets the numeric Property specifying the width of the outline. ** Note: This property will be ignored on all major browsers on Windows platforms. For details, see (@link https://github.com/CesiumGS/cesium/issues/40}. *
* @memberof PolylineVolumeGraphics.prototype * @type {Property|undefined} * @default 1.0 */ outlineWidth: createPropertyDescriptor_default("outlineWidth"), /** * Get or sets the enum Property specifying whether the volume * casts or receives shadows from light sources. * @memberof PolylineVolumeGraphics.prototype * @type {Property|undefined} * @default ShadowMode.DISABLED */ shadows: createPropertyDescriptor_default("shadows"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this volume will be displayed. * @memberof PolylineVolumeGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ) }); PolylineVolumeGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new PolylineVolumeGraphics(this); } result.show = this.show; result.positions = this.positions; result.shape = this.shape; result.cornerType = this.cornerType; result.granularity = this.granularity; result.fill = this.fill; result.material = this.material; result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; PolylineVolumeGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.positions = this.positions ?? source.positions; this.shape = this.shape ?? source.shape; this.cornerType = this.cornerType ?? source.cornerType; this.granularity = this.granularity ?? source.granularity; this.fill = this.fill ?? source.fill; this.material = this.material ?? source.material; this.outline = this.outline ?? source.outline; this.outlineColor = this.outlineColor ?? source.outlineColor; this.outlineWidth = this.outlineWidth ?? source.outlineWidth; this.shadows = this.shadows ?? source.shadows; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; }; var PolylineVolumeGraphics_default = PolylineVolumeGraphics; // packages/engine/Source/DataSources/RectangleGraphics.js var import_InlineWorkers415 = __toESM(require_InlineWorkers(), 1); function RectangleGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._coordinates = void 0; this._coordinatesSubscription = void 0; this._height = void 0; this._heightSubscription = void 0; this._heightReference = void 0; this._heightReferenceSubscription = void 0; this._extrudedHeight = void 0; this._extrudedHeightSubscription = void 0; this._extrudedHeightReference = void 0; this._extrudedHeightReferenceSubscription = void 0; this._rotation = void 0; this._rotationSubscription = void 0; this._stRotation = void 0; this._stRotationSubscription = void 0; this._granularity = void 0; this._granularitySubscription = void 0; this._fill = void 0; this._fillSubscription = void 0; this._material = void 0; this._materialSubscription = void 0; this._outline = void 0; this._outlineSubscription = void 0; this._outlineColor = void 0; this._outlineColorSubscription = void 0; this._outlineWidth = void 0; this._outlineWidthSubscription = void 0; this._shadows = void 0; this._shadowsSubscription = void 0; this._distanceDisplayCondition = void 0; this._distancedisplayConditionSubscription = void 0; this._classificationType = void 0; this._classificationTypeSubscription = void 0; this._zIndex = void 0; this._zIndexSubscription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(RectangleGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof RectangleGraphics.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the rectangle. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default true */ show: createPropertyDescriptor_default("show"), /** * Gets or sets the Property specifying the {@link Rectangle}. * @memberof RectangleGraphics.prototype * @type {Property|undefined} */ coordinates: createPropertyDescriptor_default("coordinates"), /** * Gets or sets the numeric Property specifying the altitude of the rectangle. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default 0.0 */ height: createPropertyDescriptor_default("height"), /** * Gets or sets the Property specifying the {@link HeightReference}. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ heightReference: createPropertyDescriptor_default("heightReference"), /** * Gets or sets the numeric Property specifying the altitude of the rectangle extrusion. * Setting this property creates volume starting at height and ending at this altitude. * @memberof RectangleGraphics.prototype * @type {Property|undefined} */ extrudedHeight: createPropertyDescriptor_default("extrudedHeight"), /** * Gets or sets the Property specifying the extruded {@link HeightReference}. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default HeightReference.NONE */ extrudedHeightReference: createPropertyDescriptor_default("extrudedHeightReference"), /** * Gets or sets the numeric property specifying the rotation of the rectangle clockwise from north. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default 0 */ rotation: createPropertyDescriptor_default("rotation"), /** * Gets or sets the numeric property specifying the rotation of the rectangle texture counter-clockwise from north. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default 0 */ stRotation: createPropertyDescriptor_default("stRotation"), /** * Gets or sets the numeric Property specifying the angular distance between points on the rectangle. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default {CesiumMath.RADIANS_PER_DEGREE} */ granularity: createPropertyDescriptor_default("granularity"), /** * Gets or sets the boolean Property specifying whether the rectangle is filled with the provided material. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default true */ fill: createPropertyDescriptor_default("fill"), /** * Gets or sets the Property specifying the material used to fill the rectangle. * @memberof RectangleGraphics.prototype * @type {MaterialProperty} * @default Color.WHITE */ material: createMaterialPropertyDescriptor_default("material"), /** * Gets or sets the Property specifying whether the rectangle is outlined. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default false */ outline: createPropertyDescriptor_default("outline"), /** * Gets or sets the Property specifying the {@link Color} of the outline. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default Color.BLACK */ outlineColor: createPropertyDescriptor_default("outlineColor"), /** * Gets or sets the numeric Property specifying the width of the outline. ** Note: This property will be ignored on all major browsers on Windows platforms. For details, see (@link https://github.com/CesiumGS/cesium/issues/40}. *
* @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default 1.0 */ outlineWidth: createPropertyDescriptor_default("outlineWidth"), /** * Get or sets the enum Property specifying whether the rectangle * casts or receives shadows from light sources. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default ShadowMode.DISABLED */ shadows: createPropertyDescriptor_default("shadows"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this rectangle will be displayed. * @memberof RectangleGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ), /** * Gets or sets the {@link ClassificationType} Property specifying whether this rectangle will classify terrain, 3D Tiles, or both when on the ground. * @memberof RectangleGraphics.prototype * @type {Property|undefined} * @default ClassificationType.BOTH */ classificationType: createPropertyDescriptor_default("classificationType"), /** * Gets or sets the zIndex Property specifying the ordering of the rectangle. Only has an effect if the rectangle is constant and neither height or extrudedHeight are specified. * @memberof RectangleGraphics.prototype * @type {ConstantProperty|undefined} * @default 0 */ zIndex: createPropertyDescriptor_default("zIndex") }); RectangleGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new RectangleGraphics(this); } result.show = this.show; result.coordinates = this.coordinates; result.height = this.height; result.heightReference = this.heightReference; result.extrudedHeight = this.extrudedHeight; result.extrudedHeightReference = this.extrudedHeightReference; result.rotation = this.rotation; result.stRotation = this.stRotation; result.granularity = this.granularity; result.fill = this.fill; result.material = this.material; result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; result.classificationType = this.classificationType; result.zIndex = this.zIndex; return result; }; RectangleGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.coordinates = this.coordinates ?? source.coordinates; this.height = this.height ?? source.height; this.heightReference = this.heightReference ?? source.heightReference; this.extrudedHeight = this.extrudedHeight ?? source.extrudedHeight; this.extrudedHeightReference = this.extrudedHeightReference ?? source.extrudedHeightReference; this.rotation = this.rotation ?? source.rotation; this.stRotation = this.stRotation ?? source.stRotation; this.granularity = this.granularity ?? source.granularity; this.fill = this.fill ?? source.fill; this.material = this.material ?? source.material; this.outline = this.outline ?? source.outline; this.outlineColor = this.outlineColor ?? source.outlineColor; this.outlineWidth = this.outlineWidth ?? source.outlineWidth; this.shadows = this.shadows ?? source.shadows; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; this.classificationType = this.classificationType ?? source.classificationType; this.zIndex = this.zIndex ?? source.zIndex; }; var RectangleGraphics_default = RectangleGraphics; // packages/engine/Source/DataSources/WallGraphics.js var import_InlineWorkers416 = __toESM(require_InlineWorkers(), 1); function WallGraphics(options) { this._definitionChanged = new Event_default(); this._show = void 0; this._showSubscription = void 0; this._positions = void 0; this._positionsSubscription = void 0; this._minimumHeights = void 0; this._minimumHeightsSubscription = void 0; this._maximumHeights = void 0; this._maximumHeightsSubscription = void 0; this._granularity = void 0; this._granularitySubscription = void 0; this._fill = void 0; this._fillSubscription = void 0; this._material = void 0; this._materialSubscription = void 0; this._outline = void 0; this._outlineSubscription = void 0; this._outlineColor = void 0; this._outlineColorSubscription = void 0; this._outlineWidth = void 0; this._outlineWidthSubscription = void 0; this._shadows = void 0; this._shadowsSubscription = void 0; this._distanceDisplayCondition = void 0; this._distanceDisplayConditionSubscription = void 0; this.merge(options ?? Frozen_default.EMPTY_OBJECT); } Object.defineProperties(WallGraphics.prototype, { /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof WallGraphics.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the boolean Property specifying the visibility of the wall. * @memberof WallGraphics.prototype * @type {Property|undefined} * @default true */ show: createPropertyDescriptor_default("show"), /** * Gets or sets the Property specifying the array of {@link Cartesian3} positions which define the top of the wall. * @memberof WallGraphics.prototype * @type {Property|undefined} */ positions: createPropertyDescriptor_default("positions"), /** * Gets or sets the Property specifying an array of heights to be used for the bottom of the wall instead of the surface of the globe. * If defined, the array must be the same length as {@link Wall#positions}. * @memberof WallGraphics.prototype * @type {Property|undefined} */ minimumHeights: createPropertyDescriptor_default("minimumHeights"), /** * Gets or sets the Property specifying an array of heights to be used for the top of the wall instead of the height of each position. * If defined, the array must be the same length as {@link Wall#positions}. * @memberof WallGraphics.prototype * @type {Property|undefined} */ maximumHeights: createPropertyDescriptor_default("maximumHeights"), /** * Gets or sets the numeric Property specifying the angular distance between points on the wall. * @memberof WallGraphics.prototype * @type {Property|undefined} * @default {CesiumMath.RADIANS_PER_DEGREE} */ granularity: createPropertyDescriptor_default("granularity"), /** * Gets or sets the boolean Property specifying whether the wall is filled with the provided material. * @memberof WallGraphics.prototype * @type {Property|undefined} * @default true */ fill: createPropertyDescriptor_default("fill"), /** * Gets or sets the Property specifying the material used to fill the wall. * @memberof WallGraphics.prototype * @type {MaterialProperty} * @default Color.WHITE */ material: createMaterialPropertyDescriptor_default("material"), /** * Gets or sets the Property specifying whether the wall is outlined. * @memberof WallGraphics.prototype * @type {Property|undefined} * @default false */ outline: createPropertyDescriptor_default("outline"), /** * Gets or sets the Property specifying the {@link Color} of the outline. * @memberof WallGraphics.prototype * @type {Property|undefined} * @default Color.BLACK */ outlineColor: createPropertyDescriptor_default("outlineColor"), /** * Gets or sets the numeric Property specifying the width of the outline. ** Note: This property will be ignored on all major browsers on Windows platforms. For details, see (@link https://github.com/CesiumGS/cesium/issues/40}. *
* @memberof WallGraphics.prototype * @type {Property|undefined} * @default 1.0 */ outlineWidth: createPropertyDescriptor_default("outlineWidth"), /** * Get or sets the enum Property specifying whether the wall * casts or receives shadows from light sources. * @memberof WallGraphics.prototype * @type {Property|undefined} * @default ShadowMode.DISABLED */ shadows: createPropertyDescriptor_default("shadows"), /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this wall will be displayed. * @memberof WallGraphics.prototype * @type {Property|undefined} */ distanceDisplayCondition: createPropertyDescriptor_default( "distanceDisplayCondition" ) }); WallGraphics.prototype.clone = function(result) { if (!defined_default(result)) { return new WallGraphics(this); } result.show = this.show; result.positions = this.positions; result.minimumHeights = this.minimumHeights; result.maximumHeights = this.maximumHeights; result.granularity = this.granularity; result.fill = this.fill; result.material = this.material; result.outline = this.outline; result.outlineColor = this.outlineColor; result.outlineWidth = this.outlineWidth; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; WallGraphics.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.show = this.show ?? source.show; this.positions = this.positions ?? source.positions; this.minimumHeights = this.minimumHeights ?? source.minimumHeights; this.maximumHeights = this.maximumHeights ?? source.maximumHeights; this.granularity = this.granularity ?? source.granularity; this.fill = this.fill ?? source.fill; this.material = this.material ?? source.material; this.outline = this.outline ?? source.outline; this.outlineColor = this.outlineColor ?? source.outlineColor; this.outlineWidth = this.outlineWidth ?? source.outlineWidth; this.shadows = this.shadows ?? source.shadows; this.distanceDisplayCondition = this.distanceDisplayCondition ?? source.distanceDisplayCondition; }; var WallGraphics_default = WallGraphics; // packages/engine/Source/DataSources/Entity.js var cartoScratch = new Cartographic_default(); var ExtraPropertyNames = []; function createConstantPositionProperty(value) { return new ConstantPositionProperty_default(value); } function createPositionPropertyDescriptor(name) { return createPropertyDescriptor_default( name, void 0, createConstantPositionProperty ); } function createPropertyTypeDescriptor(name, Type) { return createPropertyDescriptor_default(name, void 0, function(value) { if (value instanceof Type) { return value; } return new Type(value); }); } function Entity(options) { options = options ?? Frozen_default.EMPTY_OBJECT; let id = options.id; if (!defined_default(id)) { id = createGuid_default(); } this._availability = void 0; this._id = id; this._definitionChanged = new Event_default(); this._name = options.name; this._show = options.show ?? true; this._trackingReferenceFrame = options.trackingReferenceFrame ?? TrackingReferenceFrame_default.AUTODETECT; this._parent = void 0; this._propertyNames = [ "billboard", "box", "corridor", "cylinder", "description", "ellipse", "ellipsoid", "label", "model", "tileset", "orientation", "path", "plane", "point", "polygon", "polyline", "polylineVolume", "position", "properties", "rectangle", "viewFrom", "wall", ...ExtraPropertyNames ]; this._billboard = void 0; this._billboardSubscription = void 0; this._box = void 0; this._boxSubscription = void 0; this._corridor = void 0; this._corridorSubscription = void 0; this._cylinder = void 0; this._cylinderSubscription = void 0; this._description = void 0; this._descriptionSubscription = void 0; this._ellipse = void 0; this._ellipseSubscription = void 0; this._ellipsoid = void 0; this._ellipsoidSubscription = void 0; this._label = void 0; this._labelSubscription = void 0; this._model = void 0; this._modelSubscription = void 0; this._tileset = void 0; this._tilesetSubscription = void 0; this._orientation = void 0; this._orientationSubscription = void 0; this._path = void 0; this._pathSubscription = void 0; this._plane = void 0; this._planeSubscription = void 0; this._point = void 0; this._pointSubscription = void 0; this._polygon = void 0; this._polygonSubscription = void 0; this._polyline = void 0; this._polylineSubscription = void 0; this._polylineVolume = void 0; this._polylineVolumeSubscription = void 0; this._position = void 0; this._positionSubscription = void 0; this._properties = void 0; this._propertiesSubscription = void 0; this._rectangle = void 0; this._rectangleSubscription = void 0; this._viewFrom = void 0; this._viewFromSubscription = void 0; this._wall = void 0; this._wallSubscription = void 0; this._children = []; this.entityCollection = void 0; this.parent = options.parent; this.merge(options); } function updateShow(entity, children, isShowing) { const length2 = children.length; for (let i = 0; i < length2; i++) { const child = children[i]; const childShow = child._show; const oldValue2 = !isShowing && childShow; const newValue = isShowing && childShow; if (oldValue2 !== newValue) { updateShow(child, child._children, isShowing); } } entity._definitionChanged.raiseEvent( entity, "isShowing", isShowing, !isShowing ); } Object.defineProperties(Entity.prototype, { /** * The availability, if any, associated with this object. * If availability is undefined, it is assumed that this object's * other properties will return valid data for any provided time. * If availability exists, the objects other properties will only * provide valid data if queried within the given interval. * @memberof Entity.prototype * @type {TimeIntervalCollection|undefined} */ availability: createRawPropertyDescriptor_default("availability"), /** * Gets the unique ID associated with this object. * @memberof Entity.prototype * @type {string} */ id: { get: function() { return this._id; } }, /** * Gets the event that is raised whenever a property or sub-property is changed or modified. * @memberof Entity.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets or sets the name of the object. The name is intended for end-user * consumption and does not need to be unique. * @memberof Entity.prototype * @type {string|undefined} */ name: createRawPropertyDescriptor_default("name"), /** * Gets or sets whether this entity should be displayed. When set to true, * the entity is only displayed if the parent entity's show property is also true. * @memberof Entity.prototype * @type {boolean} */ show: { get: function() { return this._show; }, set: function(value) { if (!defined_default(value)) { throw new DeveloperError_default("value is required."); } if (value === this._show) { return; } const wasShowing = this.isShowing; this._show = value; const isShowing = this.isShowing; if (wasShowing !== isShowing) { updateShow(this, this._children, isShowing); } this._definitionChanged.raiseEvent(this, "show", value, !value); } }, /** * Gets or sets the entity's tracking reference frame. * @demo {@link https://sandcastle.cesium.com/index.html?src=Entity tracking.html|Cesium Sandcastle Entity tracking Demo} * * @memberof Entity.prototype * @type {TrackingReferenceFrame} */ trackingReferenceFrame: createRawPropertyDescriptor_default("trackingReferenceFrame"), /** * Gets whether this entity is being displayed, taking into account * the visibility of any ancestor entities. * @memberof Entity.prototype * @type {boolean} */ isShowing: { get: function() { return this._show && (!defined_default(this.entityCollection) || this.entityCollection.show) && (!defined_default(this._parent) || this._parent.isShowing); } }, /** * Gets or sets the parent object. * @memberof Entity.prototype * @type {Entity|undefined} */ parent: { get: function() { return this._parent; }, set: function(value) { const oldValue2 = this._parent; if (oldValue2 === value) { return; } const wasShowing = this.isShowing; if (defined_default(oldValue2)) { const index = oldValue2._children.indexOf(this); oldValue2._children.splice(index, 1); } this._parent = value; if (defined_default(value)) { value._children.push(this); } const isShowing = this.isShowing; if (wasShowing !== isShowing) { updateShow(this, this._children, isShowing); } this._definitionChanged.raiseEvent(this, "parent", value, oldValue2); } }, /** * Gets the names of all properties registered on this instance. * @memberof Entity.prototype * @type {string[]} */ propertyNames: { get: function() { return this._propertyNames; } }, /** * Gets or sets the billboard. * @memberof Entity.prototype * @type {BillboardGraphics|undefined} */ billboard: createPropertyTypeDescriptor("billboard", BillboardGraphics_default), /** * Gets or sets the box. * @memberof Entity.prototype * @type {BoxGraphics|undefined} */ box: createPropertyTypeDescriptor("box", BoxGraphics_default), /** * Gets or sets the corridor. * @memberof Entity.prototype * @type {CorridorGraphics|undefined} */ corridor: createPropertyTypeDescriptor("corridor", CorridorGraphics_default), /** * Gets or sets the cylinder. * @memberof Entity.prototype * @type {CylinderGraphics|undefined} */ cylinder: createPropertyTypeDescriptor("cylinder", CylinderGraphics_default), /** * Gets or sets the description. * @memberof Entity.prototype * @type {Property|undefined} */ description: createPropertyDescriptor_default("description"), /** * Gets or sets the ellipse. * @memberof Entity.prototype * @type {EllipseGraphics|undefined} */ ellipse: createPropertyTypeDescriptor("ellipse", EllipseGraphics_default), /** * Gets or sets the ellipsoid. * @memberof Entity.prototype * @type {EllipsoidGraphics|undefined} */ ellipsoid: createPropertyTypeDescriptor("ellipsoid", EllipsoidGraphics_default), /** * Gets or sets the label. * @memberof Entity.prototype * @type {LabelGraphics|undefined} */ label: createPropertyTypeDescriptor("label", LabelGraphics_default), /** * Gets or sets the model. * @memberof Entity.prototype * @type {ModelGraphics|undefined} */ model: createPropertyTypeDescriptor("model", ModelGraphics_default), /** * Gets or sets the tileset. * @memberof Entity.prototype * @type {Cesium3DTilesetGraphics|undefined} */ tileset: createPropertyTypeDescriptor("tileset", Cesium3DTilesetGraphics_default), /** * Gets or sets the orientation in respect to Earth-fixed-Earth-centered (ECEF). * Defaults to east-north-up at entity position. * @memberof Entity.prototype * @type {Property|undefined} */ orientation: createPropertyDescriptor_default("orientation"), /** * Gets or sets the path. * @memberof Entity.prototype * @type {PathGraphics|undefined} */ path: createPropertyTypeDescriptor("path", PathGraphics_default), /** * Gets or sets the plane. * @memberof Entity.prototype * @type {PlaneGraphics|undefined} */ plane: createPropertyTypeDescriptor("plane", PlaneGraphics_default), /** * Gets or sets the point graphic. * @memberof Entity.prototype * @type {PointGraphics|undefined} */ point: createPropertyTypeDescriptor("point", PointGraphics_default), /** * Gets or sets the polygon. * @memberof Entity.prototype * @type {PolygonGraphics|undefined} */ polygon: createPropertyTypeDescriptor("polygon", PolygonGraphics_default), /** * Gets or sets the polyline. * @memberof Entity.prototype * @type {PolylineGraphics|undefined} */ polyline: createPropertyTypeDescriptor("polyline", PolylineGraphics_default), /** * Gets or sets the polyline volume. * @memberof Entity.prototype * @type {PolylineVolumeGraphics|undefined} */ polylineVolume: createPropertyTypeDescriptor( "polylineVolume", PolylineVolumeGraphics_default ), /** * Gets or sets the bag of arbitrary properties associated with this entity. * @memberof Entity.prototype * @type {PropertyBag|undefined} */ properties: createPropertyTypeDescriptor("properties", PropertyBag_default), /** * Gets or sets the position. * @memberof Entity.prototype * @type {PositionProperty|undefined} */ position: createPositionPropertyDescriptor("position"), /** * Gets or sets the rectangle. * @memberof Entity.prototype * @type {RectangleGraphics|undefined} */ rectangle: createPropertyTypeDescriptor("rectangle", RectangleGraphics_default), /** * Gets or sets the suggested initial offset when tracking this object. * The offset is typically defined in the east-north-up reference frame, * but may be another frame depending on the object's velocity. * @memberof Entity.prototype * @type {Property|undefined} */ viewFrom: createPropertyDescriptor_default("viewFrom"), /** * Gets or sets the wall. * @memberof Entity.prototype * @type {WallGraphics|undefined} */ wall: createPropertyTypeDescriptor("wall", WallGraphics_default) }); Entity.registerEntityType = function(propertyName, Type) { Object.defineProperties(Entity.prototype, { [propertyName]: createPropertyTypeDescriptor(propertyName, Type) }); if (!ExtraPropertyNames.includes(propertyName)) { ExtraPropertyNames.push(propertyName); } }; Entity.prototype.isAvailable = function(time) { if (!defined_default(time)) { throw new DeveloperError_default("time is required."); } const availability = this._availability; return !defined_default(availability) || availability.contains(time); }; Entity.prototype.addProperty = function(propertyName) { const propertyNames = this._propertyNames; if (!defined_default(propertyName)) { throw new DeveloperError_default("propertyName is required."); } if (propertyNames.indexOf(propertyName) !== -1) { throw new DeveloperError_default( `${propertyName} is already a registered property.` ); } if (propertyName in this) { throw new DeveloperError_default(`${propertyName} is a reserved property name.`); } propertyNames.push(propertyName); Object.defineProperty( this, propertyName, createRawPropertyDescriptor_default(propertyName, true) ); }; Entity.prototype.removeProperty = function(propertyName) { const propertyNames = this._propertyNames; const index = propertyNames.indexOf(propertyName); if (!defined_default(propertyName)) { throw new DeveloperError_default("propertyName is required."); } if (index === -1) { throw new DeveloperError_default(`${propertyName} is not a registered property.`); } this._propertyNames.splice(index, 1); delete this[propertyName]; }; Entity.prototype.merge = function(source) { if (!defined_default(source)) { throw new DeveloperError_default("source is required."); } this.name = this.name ?? source.name; this.availability = this.availability ?? source.availability; const propertyNames = this._propertyNames; const sourcePropertyNames = defined_default(source._propertyNames) ? source._propertyNames : Object.keys(source); const propertyNamesLength = sourcePropertyNames.length; for (let i = 0; i < propertyNamesLength; i++) { const name = sourcePropertyNames[i]; if (name === "parent" || name === "name" || name === "availability" || name === "children") { continue; } const targetProperty = this[name]; const sourceProperty = source[name]; if (!defined_default(targetProperty) && propertyNames.indexOf(name) === -1) { this.addProperty(name); } if (defined_default(sourceProperty)) { if (defined_default(targetProperty)) { if (defined_default(targetProperty.merge)) { targetProperty.merge(sourceProperty); } } else if (defined_default(sourceProperty.merge) && defined_default(sourceProperty.clone)) { this[name] = sourceProperty.clone(); } else { this[name] = sourceProperty; } } } }; var matrix3Scratch2 = new Matrix3_default(); var positionScratch2 = new Cartesian3_default(); var orientationScratch = new Quaternion_default(); Entity.prototype.computeModelMatrix = function(time, result) { Check_default.typeOf.object("time", time); const position = Property_default.getValueOrUndefined( this._position, time, positionScratch2 ); if (!defined_default(position)) { return void 0; } const orientation = Property_default.getValueOrUndefined( this._orientation, time, orientationScratch ); if (!defined_default(orientation)) { result = Transforms_default.eastNorthUpToFixedFrame(position, void 0, result); } else { result = Matrix4_default.fromRotationTranslation( Matrix3_default.fromQuaternion(orientation, matrix3Scratch2), position, result ); } return result; }; Entity.prototype.computeModelMatrixForHeightReference = function(time, heightReferenceProperty, heightOffset, ellipsoid, result) { Check_default.typeOf.object("time", time); const heightReference = Property_default.getValueOrDefault( heightReferenceProperty, time, HeightReference_default.NONE ); let position = Property_default.getValueOrUndefined( this._position, time, positionScratch2 ); if (heightReference === HeightReference_default.NONE || !defined_default(position) || Cartesian3_default.equalsEpsilon(position, Cartesian3_default.ZERO, Math_default.EPSILON8)) { return this.computeModelMatrix(time, result); } const carto = ellipsoid.cartesianToCartographic(position, cartoScratch); if (isHeightReferenceClamp(heightReference)) { carto.height = heightOffset; } else { carto.height += heightOffset; } position = ellipsoid.cartographicToCartesian(carto, position); const orientation = Property_default.getValueOrUndefined( this._orientation, time, orientationScratch ); if (!defined_default(orientation)) { result = Transforms_default.eastNorthUpToFixedFrame(position, void 0, result); } else { result = Matrix4_default.fromRotationTranslation( Matrix3_default.fromQuaternion(orientation, matrix3Scratch2), position, result ); } return result; }; Entity.supportsMaterialsforEntitiesOnTerrain = function(scene) { return GroundPrimitive_default.supportsMaterials(scene); }; Entity.supportsPolylinesOnTerrain = function(scene) { return GroundPolylinePrimitive_default.isSupported(scene); }; var Entity_default = Entity; // packages/engine/Source/DataSources/GeometryUpdater.js var defaultMaterial = new ColorMaterialProperty_default(Color_default.WHITE); var defaultShow = new ConstantProperty_default(true); var defaultFill = new ConstantProperty_default(true); var defaultOutline = new ConstantProperty_default(false); var defaultOutlineColor = new ConstantProperty_default(Color_default.BLACK); var defaultShadows = new ConstantProperty_default(ShadowMode_default.DISABLED); var defaultDistanceDisplayCondition = new ConstantProperty_default( new DistanceDisplayCondition_default() ); var defaultClassificationType = new ConstantProperty_default(ClassificationType_default.BOTH); function GeometryUpdater(options) { Check_default.defined("options.entity", options.entity); Check_default.defined("options.scene", options.scene); Check_default.defined("options.geometryOptions", options.geometryOptions); Check_default.defined("options.geometryPropertyName", options.geometryPropertyName); Check_default.defined("options.observedPropertyNames", options.observedPropertyNames); const entity = options.entity; const geometryPropertyName = options.geometryPropertyName; this._entity = entity; this._scene = options.scene; this._fillEnabled = false; this._isClosed = false; this._onTerrain = false; this._dynamic = false; this._outlineEnabled = false; this._geometryChanged = new Event_default(); this._showProperty = void 0; this._materialProperty = void 0; this._showOutlineProperty = void 0; this._outlineColorProperty = void 0; this._outlineWidth = 1; this._shadowsProperty = void 0; this._distanceDisplayConditionProperty = void 0; this._classificationTypeProperty = void 0; this._options = options.geometryOptions; this._geometryPropertyName = geometryPropertyName; this._id = `${geometryPropertyName}-${entity.id}`; this._observedPropertyNames = options.observedPropertyNames; this._supportsMaterialsforEntitiesOnTerrain = Entity_default.supportsMaterialsforEntitiesOnTerrain(options.scene); } Object.defineProperties(GeometryUpdater.prototype, { /** * Gets the unique ID associated with this updater * @memberof GeometryUpdater.prototype * @type {string} * @readonly */ id: { get: function() { return this._id; } }, /** * Gets the entity associated with this geometry. * @memberof GeometryUpdater.prototype * * @type {Entity} * @readonly */ entity: { get: function() { return this._entity; } }, /** * Gets a value indicating if the geometry has a fill component. * @memberof GeometryUpdater.prototype * * @type {boolean} * @readonly */ fillEnabled: { get: function() { return this._fillEnabled; } }, /** * Gets a value indicating if fill visibility varies with simulation time. * @memberof GeometryUpdater.prototype * * @type {boolean} * @readonly */ hasConstantFill: { get: function() { return !this._fillEnabled || !defined_default(this._entity.availability) && Property_default.isConstant(this._showProperty) && Property_default.isConstant(this._fillProperty); } }, /** * Gets the material property used to fill the geometry. * @memberof GeometryUpdater.prototype * * @type {MaterialProperty} * @readonly */ fillMaterialProperty: { get: function() { return this._materialProperty; } }, /** * Gets a value indicating if the geometry has an outline component. * @memberof GeometryUpdater.prototype * * @type {boolean} * @readonly */ outlineEnabled: { get: function() { return this._outlineEnabled; } }, /** * Gets a value indicating if the geometry has an outline component. * @memberof GeometryUpdater.prototype * * @type {boolean} * @readonly */ hasConstantOutline: { get: function() { return !this._outlineEnabled || !defined_default(this._entity.availability) && Property_default.isConstant(this._showProperty) && Property_default.isConstant(this._showOutlineProperty); } }, /** * Gets the {@link Color} property for the geometry outline. * @memberof GeometryUpdater.prototype * * @type {Property} * @readonly */ outlineColorProperty: { get: function() { return this._outlineColorProperty; } }, /** * Gets the constant with of the geometry outline, in pixels. * This value is only valid if isDynamic is false. * @memberof GeometryUpdater.prototype * * @type {number} * @readonly */ outlineWidth: { get: function() { return this._outlineWidth; } }, /** * Gets the property specifying whether the geometry * casts or receives shadows from light sources. * @memberof GeometryUpdater.prototype * * @type {Property} * @readonly */ shadowsProperty: { get: function() { return this._shadowsProperty; } }, /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this geometry will be displayed. * @memberof GeometryUpdater.prototype * * @type {Property} * @readonly */ distanceDisplayConditionProperty: { get: function() { return this._distanceDisplayConditionProperty; } }, /** * Gets or sets the {@link ClassificationType} Property specifying if this geometry will classify terrain, 3D Tiles, or both when on the ground. * @memberof GeometryUpdater.prototype * * @type {Property} * @readonly */ classificationTypeProperty: { get: function() { return this._classificationTypeProperty; } }, /** * Gets a value indicating if the geometry is time-varying. * * @memberof GeometryUpdater.prototype * * @type {boolean} * @readonly */ isDynamic: { get: function() { return this._dynamic; } }, /** * Gets a value indicating if the geometry is closed. * This property is only valid for static geometry. * @memberof GeometryUpdater.prototype * * @type {boolean} * @readonly */ isClosed: { get: function() { return this._isClosed; } }, /** * Gets a value indicating if the geometry should be drawn on terrain. * @memberof EllipseGeometryUpdater.prototype * * @type {boolean} * @readonly */ onTerrain: { get: function() { return this._onTerrain; } }, /** * Gets an event that is raised whenever the public properties * of this updater change. * @memberof GeometryUpdater.prototype * * @type {boolean} * @readonly */ geometryChanged: { get: function() { return this._geometryChanged; } } }); GeometryUpdater.prototype.isOutlineVisible = function(time) { const entity = this._entity; const visible = this._outlineEnabled && entity.isAvailable(time) && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time); return visible ?? false; }; GeometryUpdater.prototype.isFilled = function(time) { const entity = this._entity; const visible = this._fillEnabled && entity.isAvailable(time) && this._showProperty.getValue(time) && this._fillProperty.getValue(time); return visible ?? false; }; GeometryUpdater.prototype.createFillGeometryInstance = DeveloperError_default.throwInstantiationError; GeometryUpdater.prototype.createOutlineGeometryInstance = DeveloperError_default.throwInstantiationError; GeometryUpdater.prototype.isDestroyed = function() { return false; }; GeometryUpdater.prototype.destroy = function() { destroyObject_default(this); }; GeometryUpdater.prototype._isHidden = function(entity, geometry) { const show = geometry.show; return defined_default(show) && show.isConstant && !show.getValue(Iso8601_default.MINIMUM_VALUE); }; GeometryUpdater.prototype._isOnTerrain = function(entity, geometry) { return false; }; GeometryUpdater.prototype._getIsClosed = function(options) { return true; }; GeometryUpdater.prototype._isDynamic = DeveloperError_default.throwInstantiationError; GeometryUpdater.prototype._setStaticOptions = DeveloperError_default.throwInstantiationError; GeometryUpdater.prototype._onEntityPropertyChanged = function(entity, propertyName, newValue, oldValue2) { if (this._observedPropertyNames.indexOf(propertyName) === -1) { return; } const geometry = this._entity[this._geometryPropertyName]; if (!defined_default(geometry)) { if (this._fillEnabled || this._outlineEnabled) { this._fillEnabled = false; this._outlineEnabled = false; this._geometryChanged.raiseEvent(this); } return; } const fillProperty = geometry.fill; const fillEnabled = defined_default(fillProperty) && fillProperty.isConstant ? fillProperty.getValue(Iso8601_default.MINIMUM_VALUE) : true; const outlineProperty = geometry.outline; let outlineEnabled = defined_default(outlineProperty); if (outlineEnabled && outlineProperty.isConstant) { outlineEnabled = outlineProperty.getValue(Iso8601_default.MINIMUM_VALUE); } if (!fillEnabled && !outlineEnabled) { if (this._fillEnabled || this._outlineEnabled) { this._fillEnabled = false; this._outlineEnabled = false; this._geometryChanged.raiseEvent(this); } return; } const show = geometry.show; if (this._isHidden(entity, geometry)) { if (this._fillEnabled || this._outlineEnabled) { this._fillEnabled = false; this._outlineEnabled = false; this._geometryChanged.raiseEvent(this); } return; } this._materialProperty = geometry.material ?? defaultMaterial; this._fillProperty = fillProperty ?? defaultFill; this._showProperty = show ?? defaultShow; this._showOutlineProperty = geometry.outline ?? defaultOutline; this._outlineColorProperty = outlineEnabled ? geometry.outlineColor ?? defaultOutlineColor : void 0; this._shadowsProperty = geometry.shadows ?? defaultShadows; this._distanceDisplayConditionProperty = geometry.distanceDisplayCondition ?? defaultDistanceDisplayCondition; this._classificationTypeProperty = geometry.classificationType ?? defaultClassificationType; this._fillEnabled = fillEnabled; const onTerrain = this._isOnTerrain(entity, geometry) && (this._supportsMaterialsforEntitiesOnTerrain || this._materialProperty instanceof ColorMaterialProperty_default); if (outlineEnabled && onTerrain) { oneTimeWarning_default(oneTimeWarning_default.geometryOutlines); outlineEnabled = false; } this._onTerrain = onTerrain; this._outlineEnabled = outlineEnabled; if (this._isDynamic(entity, geometry)) { if (!this._dynamic) { this._dynamic = true; this._geometryChanged.raiseEvent(this); } } else { this._setStaticOptions(entity, geometry); this._isClosed = this._getIsClosed(this._options); const outlineWidth = geometry.outlineWidth; this._outlineWidth = defined_default(outlineWidth) ? outlineWidth.getValue(Iso8601_default.MINIMUM_VALUE) : 1; this._dynamic = false; this._geometryChanged.raiseEvent(this); } }; GeometryUpdater.prototype.createDynamicUpdater = function(primitives, groundPrimitives) { Check_default.defined("primitives", primitives); Check_default.defined("groundPrimitives", groundPrimitives); if (!this._dynamic) { throw new DeveloperError_default( "This instance does not represent dynamic geometry." ); } return new this.constructor.DynamicGeometryUpdater( this, primitives, groundPrimitives ); }; var GeometryUpdater_default = GeometryUpdater; // packages/engine/Source/DataSources/heightReferenceOnEntityPropertyChanged.js var import_InlineWorkers421 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/DataSources/CallbackProperty.js var import_InlineWorkers419 = __toESM(require_InlineWorkers(), 1); function CallbackProperty(callback, isConstant) { this._callback = void 0; this._isConstant = void 0; this._definitionChanged = new Event_default(); this.setCallback(callback, isConstant); } Object.defineProperties(CallbackProperty.prototype, { /** * Gets a value indicating if this property is constant. * @memberof CallbackProperty.prototype * * @type {boolean} * @readonly */ isConstant: { get: function() { return this._isConstant; } }, /** * Gets the event that is raised whenever the definition of this property changes. * The definition is changed whenever setCallback is called. * @memberof CallbackProperty.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } } }); var timeScratch7 = new JulianDate_default(); CallbackProperty.prototype.getValue = function(time, result) { if (!defined_default(time)) { time = JulianDate_default.now(timeScratch7); } return this._callback(time, result); }; CallbackProperty.prototype.setCallback = function(callback, isConstant) { if (!defined_default(callback)) { throw new DeveloperError_default("callback is required."); } if (!defined_default(isConstant)) { throw new DeveloperError_default("isConstant is required."); } const changed = this._callback !== callback || this._isConstant !== isConstant; this._callback = callback; this._isConstant = isConstant; if (changed) { this._definitionChanged.raiseEvent(this); } }; CallbackProperty.prototype.equals = function(other) { return this === other || other instanceof CallbackProperty && this._callback === other._callback && this._isConstant === other._isConstant; }; var CallbackProperty_default = CallbackProperty; // packages/engine/Source/DataSources/TerrainOffsetProperty.js var import_InlineWorkers420 = __toESM(require_InlineWorkers(), 1); var scratchPosition = new Cartesian3_default(); function TerrainOffsetProperty(scene, positionProperty, heightReferenceProperty, extrudedHeightReferenceProperty) { Check_default.defined("scene", scene); Check_default.defined("positionProperty", positionProperty); this._scene = scene; this._heightReference = heightReferenceProperty; this._extrudedHeightReference = extrudedHeightReferenceProperty; this._positionProperty = positionProperty; this._position = new Cartesian3_default(); this._cartographicPosition = new Cartographic_default(); this._normal = new Cartesian3_default(); this._definitionChanged = new Event_default(); this._terrainHeight = 0; this._removeCallbackFunc = void 0; this._removeEventListener = void 0; this._removeModeListener = void 0; const that = this; if (defined_default(scene.globe)) { this._removeEventListener = scene.terrainProviderChanged.addEventListener( function() { that._updateClamping(); } ); this._removeModeListener = scene.morphComplete.addEventListener( function() { that._updateClamping(); } ); } if (positionProperty.isConstant) { const position = positionProperty.getValue( Iso8601_default.MINIMUM_VALUE, scratchPosition ); if (!defined_default(position) || Cartesian3_default.equals(position, Cartesian3_default.ZERO) || !defined_default(scene.globe)) { return; } this._position = Cartesian3_default.clone(position, this._position); this._updateClamping(); this._normal = scene.ellipsoid.geodeticSurfaceNormal( position, this._normal ); } } Object.defineProperties(TerrainOffsetProperty.prototype, { /** * Gets a value indicating if this property is constant. * @memberof TerrainOffsetProperty.prototype * * @type {boolean} * @readonly */ isConstant: { get: function() { return false; } }, /** * Gets the event that is raised whenever the definition of this property changes. * @memberof TerrainOffsetProperty.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } } }); TerrainOffsetProperty.prototype._updateClamping = function() { if (defined_default(this._removeCallbackFunc)) { this._removeCallbackFunc(); } const scene = this._scene; const position = this._position; if (Cartesian3_default.equals(position, Cartesian3_default.ZERO)) { this._terrainHeight = 0; return; } const ellipsoid = scene.ellipsoid; const cartographicPosition = ellipsoid.cartesianToCartographic( position, this._cartographicPosition ); const height = scene.getHeight(cartographicPosition, this._heightReference); if (defined_default(height)) { this._terrainHeight = height; } else { this._terrainHeight = 0; } const updateFunction = (clampedPosition) => { this._terrainHeight = clampedPosition.height; this.definitionChanged.raiseEvent(); }; this._removeCallbackFunc = scene.updateHeight( cartographicPosition, updateFunction, this._heightReference ); }; var timeScratch8 = new JulianDate_default(); TerrainOffsetProperty.prototype.getValue = function(time, result) { if (!defined_default(time)) { time = JulianDate_default.now(timeScratch8); } const heightReference = Property_default.getValueOrDefault( this._heightReference, time, HeightReference_default.NONE ); const extrudedHeightReference = Property_default.getValueOrDefault( this._extrudedHeightReference, time, HeightReference_default.NONE ); if (heightReference === HeightReference_default.NONE && !isHeightReferenceRelative(extrudedHeightReference)) { this._position = Cartesian3_default.clone(Cartesian3_default.ZERO, this._position); return Cartesian3_default.clone(Cartesian3_default.ZERO, result); } if (this._positionProperty.isConstant) { return Cartesian3_default.multiplyByScalar( this._normal, this._terrainHeight, result ); } const scene = this._scene; const position = this._positionProperty.getValue(time, scratchPosition); if (!defined_default(position) || Cartesian3_default.equals(position, Cartesian3_default.ZERO) || !defined_default(scene.globe)) { return Cartesian3_default.clone(Cartesian3_default.ZERO, result); } if (Cartesian3_default.equalsEpsilon(this._position, position, Math_default.EPSILON10)) { return Cartesian3_default.multiplyByScalar( this._normal, this._terrainHeight, result ); } this._position = Cartesian3_default.clone(position, this._position); this._updateClamping(); const normal2 = scene.ellipsoid.geodeticSurfaceNormal(position, this._normal); return Cartesian3_default.multiplyByScalar(normal2, this._terrainHeight, result); }; TerrainOffsetProperty.prototype.isDestroyed = function() { return false; }; TerrainOffsetProperty.prototype.destroy = function() { if (defined_default(this._removeEventListener)) { this._removeEventListener(); } if (defined_default(this._removeModeListener)) { this._removeModeListener(); } if (defined_default(this._removeCallbackFunc)) { this._removeCallbackFunc(); } return destroyObject_default(this); }; var TerrainOffsetProperty_default = TerrainOffsetProperty; // packages/engine/Source/DataSources/heightReferenceOnEntityPropertyChanged.js function heightReferenceOnEntityPropertyChanged(entity, propertyName, newValue, oldValue2) { GeometryUpdater_default.prototype._onEntityPropertyChanged.call( this, entity, propertyName, newValue, oldValue2 ); if (this._observedPropertyNames.indexOf(propertyName) === -1) { return; } const geometry = this._entity[this._geometryPropertyName]; if (!defined_default(geometry)) { return; } if (defined_default(this._terrainOffsetProperty)) { this._terrainOffsetProperty.destroy(); this._terrainOffsetProperty = void 0; } const heightReferenceProperty = geometry.heightReference; if (defined_default(heightReferenceProperty)) { const centerPosition = new CallbackProperty_default( this._computeCenter.bind(this), !this._dynamic ); this._terrainOffsetProperty = new TerrainOffsetProperty_default( this._scene, centerPosition, heightReferenceProperty ); } } var heightReferenceOnEntityPropertyChanged_default = heightReferenceOnEntityPropertyChanged; // packages/engine/Source/DataSources/BoxGeometryUpdater.js var defaultOffset = Cartesian3_default.ZERO; var offsetScratch4 = new Cartesian3_default(); var positionScratch3 = new Cartesian3_default(); var scratchColor = new Color_default(); function BoxGeometryOptions(entity) { this.id = entity; this.vertexFormat = void 0; this.dimensions = void 0; this.offsetAttribute = void 0; } function BoxGeometryUpdater(entity, scene) { GeometryUpdater_default.call(this, { entity, scene, geometryOptions: new BoxGeometryOptions(entity), geometryPropertyName: "box", observedPropertyNames: ["availability", "position", "orientation", "box"] }); this._onEntityPropertyChanged(entity, "box", entity.box, void 0); } if (defined_default(Object.create)) { BoxGeometryUpdater.prototype = Object.create(GeometryUpdater_default.prototype); BoxGeometryUpdater.prototype.constructor = BoxGeometryUpdater; } Object.defineProperties(BoxGeometryUpdater.prototype, { /** * Gets the terrain offset property * @type {TerrainOffsetProperty} * @memberof BoxGeometryUpdater.prototype * @readonly * @private */ terrainOffsetProperty: { get: function() { return this._terrainOffsetProperty; } } }); BoxGeometryUpdater.prototype.createFillGeometryInstance = function(time) { Check_default.defined("time", time); if (!this._fillEnabled) { throw new DeveloperError_default( "This instance does not represent a filled geometry." ); } const entity = this._entity; const isAvailable = entity.isAvailable(time); const show = new ShowGeometryInstanceAttribute_default( isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time) ); const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); const distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition( distanceDisplayCondition ); const attributes = { show, distanceDisplayCondition: distanceDisplayConditionAttribute, color: void 0, offset: void 0 }; if (this._materialProperty instanceof ColorMaterialProperty_default) { let currentColor; if (defined_default(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) { currentColor = this._materialProperty.color.getValue(time, scratchColor); } if (!defined_default(currentColor)) { currentColor = Color_default.WHITE; } attributes.color = ColorGeometryInstanceAttribute_default.fromColor(currentColor); } if (defined_default(this._options.offsetAttribute)) { attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3( Property_default.getValueOrDefault( this._terrainOffsetProperty, time, defaultOffset, offsetScratch4 ) ); } return new GeometryInstance_default({ id: entity, geometry: BoxGeometry_default.fromDimensions(this._options), modelMatrix: entity.computeModelMatrixForHeightReference( time, entity.box.heightReference, this._options.dimensions.z * 0.5, this._scene.ellipsoid ), attributes }); }; BoxGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) { Check_default.defined("time", time); if (!this._outlineEnabled) { throw new DeveloperError_default( "This instance does not represent an outlined geometry." ); } const entity = this._entity; const isAvailable = entity.isAvailable(time); const outlineColor = Property_default.getValueOrDefault( this._outlineColorProperty, time, Color_default.BLACK, scratchColor ); const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time); const attributes = { show: new ShowGeometryInstanceAttribute_default( isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time) ), color: ColorGeometryInstanceAttribute_default.fromColor(outlineColor), distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition( distanceDisplayCondition ), offset: void 0 }; if (defined_default(this._options.offsetAttribute)) { attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3( Property_default.getValueOrDefault( this._terrainOffsetProperty, time, defaultOffset, offsetScratch4 ) ); } return new GeometryInstance_default({ id: entity, geometry: BoxOutlineGeometry_default.fromDimensions(this._options), modelMatrix: entity.computeModelMatrixForHeightReference( time, entity.box.heightReference, this._options.dimensions.z * 0.5, this._scene.ellipsoid ), attributes }); }; BoxGeometryUpdater.prototype._computeCenter = function(time, result) { return Property_default.getValueOrUndefined(this._entity.position, time, result); }; BoxGeometryUpdater.prototype._isHidden = function(entity, box) { return !defined_default(box.dimensions) || !defined_default(entity.position) || GeometryUpdater_default.prototype._isHidden.call(this, entity, box); }; BoxGeometryUpdater.prototype._isDynamic = function(entity, box) { return !entity.position.isConstant || !Property_default.isConstant(entity.orientation) || !box.dimensions.isConstant || !Property_default.isConstant(box.outlineWidth); }; BoxGeometryUpdater.prototype._setStaticOptions = function(entity, box) { const heightReference = Property_default.getValueOrDefault( box.heightReference, Iso8601_default.MINIMUM_VALUE, HeightReference_default.NONE ); const options = this._options; options.vertexFormat = this._materialProperty instanceof ColorMaterialProperty_default ? PerInstanceColorAppearance_default.VERTEX_FORMAT : MaterialAppearance_default.MaterialSupport.TEXTURED.vertexFormat; options.dimensions = box.dimensions.getValue( Iso8601_default.MINIMUM_VALUE, options.dimensions ); options.offsetAttribute = heightReference !== HeightReference_default.NONE ? GeometryOffsetAttribute_default.ALL : void 0; }; BoxGeometryUpdater.prototype._onEntityPropertyChanged = heightReferenceOnEntityPropertyChanged_default; BoxGeometryUpdater.DynamicGeometryUpdater = DynamicBoxGeometryUpdater; function DynamicBoxGeometryUpdater(geometryUpdater, primitives, groundPrimitives) { DynamicGeometryUpdater_default.call( this, geometryUpdater, primitives, groundPrimitives ); } if (defined_default(Object.create)) { DynamicBoxGeometryUpdater.prototype = Object.create( DynamicGeometryUpdater_default.prototype ); DynamicBoxGeometryUpdater.prototype.constructor = DynamicBoxGeometryUpdater; } DynamicBoxGeometryUpdater.prototype._isHidden = function(entity, box, time) { const position = Property_default.getValueOrUndefined( entity.position, time, positionScratch3 ); const dimensions = this._options.dimensions; return !defined_default(position) || !defined_default(dimensions) || DynamicGeometryUpdater_default.prototype._isHidden.call(this, entity, box, time); }; DynamicBoxGeometryUpdater.prototype._setOptions = function(entity, box, time) { const heightReference = Property_default.getValueOrDefault( box.heightReference, time, HeightReference_default.NONE ); const options = this._options; options.dimensions = Property_default.getValueOrUndefined( box.dimensions, time, options.dimensions ); options.offsetAttribute = heightReference !== HeightReference_default.NONE ? GeometryOffsetAttribute_default.ALL : void 0; }; var BoxGeometryUpdater_default = BoxGeometryUpdater; // packages/engine/Source/DataSources/CallbackPositionProperty.js var import_InlineWorkers423 = __toESM(require_InlineWorkers(), 1); function CallbackPositionProperty(callback, isConstant, referenceFrame) { this._callback = void 0; this._isConstant = void 0; this._referenceFrame = referenceFrame ?? ReferenceFrame_default.FIXED; this._definitionChanged = new Event_default(); this.setCallback(callback, isConstant); } Object.defineProperties(CallbackPositionProperty.prototype, { /** * Gets a value indicating if this property is constant. * @memberof CallbackPositionProperty.prototype * * @type {boolean} * @readonly */ isConstant: { get: function() { return this._isConstant; } }, /** * Gets the event that is raised whenever the definition of this property changes. * The definition is considered to have changed if a call to getValue would return * a different result for the same time. * @memberof CallbackPositionProperty.prototype * * @type {Event} * @readonly */ definitionChanged: { get: function() { return this._definitionChanged; } }, /** * Gets the reference frame in which the position is defined. * @memberof CallbackPositionProperty.prototype * @type {ReferenceFrame} * @default ReferenceFrame.FIXED; */ referenceFrame: { get: function() { return this._referenceFrame; } } }); var timeScratch9 = new JulianDate_default(); CallbackPositionProperty.prototype.getValue = function(time, result) { if (!defined_default(time)) { time = JulianDate_default.now(timeScratch9); } return this.getValueInReferenceFrame(time, ReferenceFrame_default.FIXED, result); }; CallbackPositionProperty.prototype.setCallback = function(callback, isConstant) { if (!defined_default(callback)) { throw new DeveloperError_default("callback is required."); } if (!defined_default(isConstant)) { throw new DeveloperError_default("isConstant is required."); } const changed = this._callback !== callback || this._isConstant !== isConstant; this._callback = callback; this._isConstant = isConstant; if (changed) { this._definitionChanged.raiseEvent(this); } }; CallbackPositionProperty.prototype.getValueInReferenceFrame = function(time, referenceFrame, result) { if (!defined_default(time)) { throw new DeveloperError_default("time is required."); } if (!defined_default(referenceFrame)) { throw new DeveloperError_default("referenceFrame is required."); } const value = this._callback(time, result); return PositionProperty_default.convertToReferenceFrame( time, value, this._referenceFrame, referenceFrame, result ); }; CallbackPositionProperty.prototype.equals = function(other) { return this === other || other instanceof CallbackPositionProperty && this._callback === other._callback && this._isConstant === other._isConstant && this._referenceFrame === other._referenceFrame; }; var CallbackPositionProperty_default = CallbackPositionProperty; // packages/engine/Source/DataSources/Cesium3DTilesetVisualizer.js var import_InlineWorkers815 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/Cesium3DTileset.js var import_InlineWorkers814 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Core/Credit.js var import_InlineWorkers425 = __toESM(require_InlineWorkers(), 1); // node_modules/dompurify/dist/purify.es.mjs var import_InlineWorkers424 = __toESM(require_InlineWorkers(), 1); /*! @license DOMPurify 3.2.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.6/LICENSE */ var { entries, setPrototypeOf, isFrozen, getPrototypeOf, getOwnPropertyDescriptor } = Object; var { freeze, seal, create } = Object; var { apply, construct } = typeof Reflect !== "undefined" && Reflect; if (!freeze) { freeze = function freeze2(x) { return x; }; } if (!seal) { seal = function seal2(x) { return x; }; } if (!apply) { apply = function apply2(fun, thisValue, args) { return fun.apply(thisValue, args); }; } if (!construct) { construct = function construct2(Func, args) { return new Func(...args); }; } var arrayForEach = unapply(Array.prototype.forEach); var arrayLastIndexOf = unapply(Array.prototype.lastIndexOf); var arrayPop = unapply(Array.prototype.pop); var arrayPush = unapply(Array.prototype.push); var arraySplice = unapply(Array.prototype.splice); var stringToLowerCase = unapply(String.prototype.toLowerCase); var stringToString = unapply(String.prototype.toString); var stringMatch = unapply(String.prototype.match); var stringReplace = unapply(String.prototype.replace); var stringIndexOf = unapply(String.prototype.indexOf); var stringTrim = unapply(String.prototype.trim); var objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty); var regExpTest = unapply(RegExp.prototype.test); var typeErrorCreate = unconstruct(TypeError); function unapply(func) { return function(thisArg) { if (thisArg instanceof RegExp) { thisArg.lastIndex = 0; } for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } return apply(func, thisArg, args); }; } function unconstruct(func) { return function() { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return construct(func, args); }; } function addToSet(set2, array) { let transformCaseFunc = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : stringToLowerCase; if (setPrototypeOf) { setPrototypeOf(set2, null); } let l = array.length; while (l--) { let element = array[l]; if (typeof element === "string") { const lcElement = transformCaseFunc(element); if (lcElement !== element) { if (!isFrozen(array)) { array[l] = lcElement; } element = lcElement; } } set2[element] = true; } return set2; } function cleanArray(array) { for (let index = 0; index < array.length; index++) { const isPropertyExist = objectHasOwnProperty(array, index); if (!isPropertyExist) { array[index] = null; } } return array; } function clone2(object2) { const newObject = create(null); for (const [property, value] of entries(object2)) { const isPropertyExist = objectHasOwnProperty(object2, property); if (isPropertyExist) { if (Array.isArray(value)) { newObject[property] = cleanArray(value); } else if (value && typeof value === "object" && value.constructor === Object) { newObject[property] = clone2(value); } else { newObject[property] = value; } } } return newObject; } function lookupGetter(object2, prop) { while (object2 !== null) { const desc = getOwnPropertyDescriptor(object2, prop); if (desc) { if (desc.get) { return unapply(desc.get); } if (typeof desc.value === "function") { return unapply(desc.value); } } object2 = getPrototypeOf(object2); } function fallbackValue() { return null; } return fallbackValue; } var html$1 = freeze(["a", "abbr", "acronym", "address", "area", "article", "aside", "audio", "b", "bdi", "bdo", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "decorator", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "fieldset", "figcaption", "figure", "font", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "img", "input", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "marquee", "menu", "menuitem", "meter", "nav", "nobr", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "section", "select", "shadow", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]); var svg$1 = freeze(["svg", "a", "altglyph", "altglyphdef", "altglyphitem", "animatecolor", "animatemotion", "animatetransform", "circle", "clippath", "defs", "desc", "ellipse", "filter", "font", "g", "glyph", "glyphref", "hkern", "image", "line", "lineargradient", "marker", "mask", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialgradient", "rect", "stop", "style", "switch", "symbol", "text", "textpath", "title", "tref", "tspan", "view", "vkern"]); var svgFilters = freeze(["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence"]); var svgDisallowed = freeze(["animate", "color-profile", "cursor", "discard", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignobject", "hatch", "hatchpath", "mesh", "meshgradient", "meshpatch", "meshrow", "missing-glyph", "script", "set", "solidcolor", "unknown", "use"]); var mathMl$1 = freeze(["math", "menclose", "merror", "mfenced", "mfrac", "mglyph", "mi", "mlabeledtr", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mphantom", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msup", "msubsup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover", "mprescripts"]); var mathMlDisallowed = freeze(["maction", "maligngroup", "malignmark", "mlongdiv", "mscarries", "mscarry", "msgroup", "mstack", "msline", "msrow", "semantics", "annotation", "annotation-xml", "mprescripts", "none"]); var text = freeze(["#text"]); var html = freeze(["accept", "action", "align", "alt", "autocapitalize", "autocomplete", "autopictureinpicture", "autoplay", "background", "bgcolor", "border", "capture", "cellpadding", "cellspacing", "checked", "cite", "class", "clear", "color", "cols", "colspan", "controls", "controlslist", "coords", "crossorigin", "datetime", "decoding", "default", "dir", "disabled", "disablepictureinpicture", "disableremoteplayback", "download", "draggable", "enctype", "enterkeyhint", "face", "for", "headers", "height", "hidden", "high", "href", "hreflang", "id", "inputmode", "integrity", "ismap", "kind", "label", "lang", "list", "loading", "loop", "low", "max", "maxlength", "media", "method", "min", "minlength", "multiple", "muted", "name", "nonce", "noshade", "novalidate", "nowrap", "open", "optimum", "pattern", "placeholder", "playsinline", "popover", "popovertarget", "popovertargetaction", "poster", "preload", "pubdate", "radiogroup", "readonly", "rel", "required", "rev", "reversed", "role", "rows", "rowspan", "spellcheck", "scope", "selected", "shape", "size", "sizes", "span", "srclang", "start", "src", "srcset", "step", "style", "summary", "tabindex", "title", "translate", "type", "usemap", "valign", "value", "width", "wrap", "xmlns", "slot"]); var svg = freeze(["accent-height", "accumulate", "additive", "alignment-baseline", "amplitude", "ascent", "attributename", "attributetype", "azimuth", "basefrequency", "baseline-shift", "begin", "bias", "by", "class", "clip", "clippathunits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "cx", "cy", "d", "dx", "dy", "diffuseconstant", "direction", "display", "divisor", "dur", "edgemode", "elevation", "end", "exponent", "fill", "fill-opacity", "fill-rule", "filter", "filterunits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "fx", "fy", "g1", "g2", "glyph-name", "glyphref", "gradientunits", "gradienttransform", "height", "href", "id", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kerning", "keypoints", "keysplines", "keytimes", "lang", "lengthadjust", "letter-spacing", "kernelmatrix", "kernelunitlength", "lighting-color", "local", "marker-end", "marker-mid", "marker-start", "markerheight", "markerunits", "markerwidth", "maskcontentunits", "maskunits", "max", "mask", "media", "method", "mode", "min", "name", "numoctaves", "offset", "operator", "opacity", "order", "orient", "orientation", "origin", "overflow", "paint-order", "path", "pathlength", "patterncontentunits", "patterntransform", "patternunits", "points", "preservealpha", "preserveaspectratio", "primitiveunits", "r", "rx", "ry", "radius", "refx", "refy", "repeatcount", "repeatdur", "restart", "result", "rotate", "scale", "seed", "shape-rendering", "slope", "specularconstant", "specularexponent", "spreadmethod", "startoffset", "stddeviation", "stitchtiles", "stop-color", "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke", "stroke-width", "style", "surfacescale", "systemlanguage", "tabindex", "tablevalues", "targetx", "targety", "transform", "transform-origin", "text-anchor", "text-decoration", "text-rendering", "textlength", "type", "u1", "u2", "unicode", "values", "viewbox", "visibility", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "width", "word-spacing", "wrap", "writing-mode", "xchannelselector", "ychannelselector", "x", "x1", "x2", "xmlns", "y", "y1", "y2", "z", "zoomandpan"]); var mathMl = freeze(["accent", "accentunder", "align", "bevelled", "close", "columnsalign", "columnlines", "columnspan", "denomalign", "depth", "dir", "display", "displaystyle", "encoding", "fence", "frame", "height", "href", "id", "largeop", "length", "linethickness", "lspace", "lquote", "mathbackground", "mathcolor", "mathsize", "mathvariant", "maxsize", "minsize", "movablelimits", "notation", "numalign", "open", "rowalign", "rowlines", "rowspacing", "rowspan", "rspace", "rquote", "scriptlevel", "scriptminsize", "scriptsizemultiplier", "selection", "separator", "separators", "stretchy", "subscriptshift", "supscriptshift", "symmetric", "voffset", "width", "xmlns"]); var xml = freeze(["xlink:href", "xml:id", "xlink:title", "xml:space", "xmlns:xlink"]); var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm); var TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); var ARIA_ATTR = seal(/^aria-[\-\w]+$/); var IS_ALLOWED_URI = seal( /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape ); var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i); var ATTR_WHITESPACE = seal( /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex ); var DOCTYPE_NAME = seal(/^html$/i); var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i); var EXPRESSIONS = /* @__PURE__ */ Object.freeze({ __proto__: null, ARIA_ATTR, ATTR_WHITESPACE, CUSTOM_ELEMENT, DATA_ATTR, DOCTYPE_NAME, ERB_EXPR, IS_ALLOWED_URI, IS_SCRIPT_OR_DATA, MUSTACHE_EXPR, TMPLIT_EXPR }); var NODE_TYPE = { element: 1, attribute: 2, text: 3, cdataSection: 4, entityReference: 5, // Deprecated entityNode: 6, // Deprecated progressingInstruction: 7, comment: 8, document: 9, documentType: 10, documentFragment: 11, notation: 12 // Deprecated }; var getGlobal = function getGlobal2() { return typeof window === "undefined" ? null : window; }; var _createTrustedTypesPolicy = function _createTrustedTypesPolicy2(trustedTypes, purifyHostElement) { if (typeof trustedTypes !== "object" || typeof trustedTypes.createPolicy !== "function") { return null; } let suffix = null; const ATTR_NAME = "data-tt-policy-suffix"; if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) { suffix = purifyHostElement.getAttribute(ATTR_NAME); } const policyName = "dompurify" + (suffix ? "#" + suffix : ""); try { return trustedTypes.createPolicy(policyName, { createHTML(html2) { return html2; }, createScriptURL(scriptUrl) { return scriptUrl; } }); } catch (_) { console.warn("TrustedTypes policy " + policyName + " could not be created."); return null; } }; var _createHooksMap = function _createHooksMap2() { return { afterSanitizeAttributes: [], afterSanitizeElements: [], afterSanitizeShadowDOM: [], beforeSanitizeAttributes: [], beforeSanitizeElements: [], beforeSanitizeShadowDOM: [], uponSanitizeAttribute: [], uponSanitizeElement: [], uponSanitizeShadowNode: [] }; }; function createDOMPurify() { let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal(); const DOMPurify = (root) => createDOMPurify(root); DOMPurify.version = "3.2.6"; DOMPurify.removed = []; if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) { DOMPurify.isSupported = false; return DOMPurify; } let { document: document2 } = window2; const originalDocument = document2; const currentScript = originalDocument.currentScript; const { DocumentFragment: DocumentFragment2, HTMLTemplateElement, Node: Node6, Element: Element2, NodeFilter, NamedNodeMap = window2.NamedNodeMap || window2.MozNamedAttrMap, HTMLFormElement, DOMParser: DOMParser2, trustedTypes } = window2; const ElementPrototype = Element2.prototype; const cloneNode = lookupGetter(ElementPrototype, "cloneNode"); const remove4 = lookupGetter(ElementPrototype, "remove"); const getNextSibling = lookupGetter(ElementPrototype, "nextSibling"); const getChildNodes = lookupGetter(ElementPrototype, "childNodes"); const getParentNode = lookupGetter(ElementPrototype, "parentNode"); if (typeof HTMLTemplateElement === "function") { const template = document2.createElement("template"); if (template.content && template.content.ownerDocument) { document2 = template.content.ownerDocument; } } let trustedTypesPolicy; let emptyHTML = ""; const { implementation: implementation2, createNodeIterator, createDocumentFragment, getElementsByTagName } = document2; const { importNode } = originalDocument; let hooks2 = _createHooksMap(); DOMPurify.isSupported = typeof entries === "function" && typeof getParentNode === "function" && implementation2 && implementation2.createHTMLDocument !== void 0; const { MUSTACHE_EXPR: MUSTACHE_EXPR2, ERB_EXPR: ERB_EXPR2, TMPLIT_EXPR: TMPLIT_EXPR2, DATA_ATTR: DATA_ATTR2, ARIA_ATTR: ARIA_ATTR2, IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA2, ATTR_WHITESPACE: ATTR_WHITESPACE2, CUSTOM_ELEMENT: CUSTOM_ELEMENT2 } = EXPRESSIONS; let { IS_ALLOWED_URI: IS_ALLOWED_URI$1 } = EXPRESSIONS; let ALLOWED_TAGS = null; const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]); let ALLOWED_ATTR = null; const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]); let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, { tagNameCheck: { writable: true, configurable: false, enumerable: true, value: null }, attributeNameCheck: { writable: true, configurable: false, enumerable: true, value: null }, allowCustomizedBuiltInElements: { writable: true, configurable: false, enumerable: true, value: false } })); let FORBID_TAGS = null; let FORBID_ATTR = null; let ALLOW_ARIA_ATTR = true; let ALLOW_DATA_ATTR = true; let ALLOW_UNKNOWN_PROTOCOLS = false; let ALLOW_SELF_CLOSE_IN_ATTR = true; let SAFE_FOR_TEMPLATES = false; let SAFE_FOR_XML = true; let WHOLE_DOCUMENT = false; let SET_CONFIG = false; let FORCE_BODY = false; let RETURN_DOM = false; let RETURN_DOM_FRAGMENT = false; let RETURN_TRUSTED_TYPE = false; let SANITIZE_DOM = true; let SANITIZE_NAMED_PROPS = false; const SANITIZE_NAMED_PROPS_PREFIX = "user-content-"; let KEEP_CONTENT = true; let IN_PLACE = false; let USE_PROFILES = {}; let FORBID_CONTENTS = null; const DEFAULT_FORBID_CONTENTS = addToSet({}, ["annotation-xml", "audio", "colgroup", "desc", "foreignobject", "head", "iframe", "math", "mi", "mn", "mo", "ms", "mtext", "noembed", "noframes", "noscript", "plaintext", "script", "style", "svg", "template", "thead", "title", "video", "xmp"]); let DATA_URI_TAGS = null; const DEFAULT_DATA_URI_TAGS = addToSet({}, ["audio", "video", "img", "source", "image", "track"]); let URI_SAFE_ATTRIBUTES = null; const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ["alt", "class", "for", "id", "label", "name", "pattern", "placeholder", "role", "summary", "title", "value", "style", "xmlns"]); const MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML"; const SVG_NAMESPACE = "http://www.w3.org/2000/svg"; const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml"; let NAMESPACE = HTML_NAMESPACE; let IS_EMPTY_INPUT = false; let ALLOWED_NAMESPACES = null; const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString); let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ["mi", "mo", "mn", "ms", "mtext"]); let HTML_INTEGRATION_POINTS = addToSet({}, ["annotation-xml"]); const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ["title", "style", "font", "a", "script"]); let PARSER_MEDIA_TYPE = null; const SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"]; const DEFAULT_PARSER_MEDIA_TYPE = "text/html"; let transformCaseFunc = null; let CONFIG = null; const formElement = document2.createElement("form"); const isRegexOrFunction = function isRegexOrFunction2(testValue) { return testValue instanceof RegExp || testValue instanceof Function; }; const _parseConfig = function _parseConfig2() { let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; if (CONFIG && CONFIG === cfg) { return; } if (!cfg || typeof cfg !== "object") { cfg = {}; } cfg = clone2(cfg); PARSER_MEDIA_TYPE = // eslint-disable-next-line unicorn/prefer-includes SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE; transformCaseFunc = PARSER_MEDIA_TYPE === "application/xhtml+xml" ? stringToString : stringToLowerCase; ALLOWED_TAGS = objectHasOwnProperty(cfg, "ALLOWED_TAGS") ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS; ALLOWED_ATTR = objectHasOwnProperty(cfg, "ALLOWED_ATTR") ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR; ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, "ALLOWED_NAMESPACES") ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES; URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") ? addToSet(clone2(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES; DATA_URI_TAGS = objectHasOwnProperty(cfg, "ADD_DATA_URI_TAGS") ? addToSet(clone2(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS; FORBID_CONTENTS = objectHasOwnProperty(cfg, "FORBID_CONTENTS") ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS; FORBID_TAGS = objectHasOwnProperty(cfg, "FORBID_TAGS") ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone2({}); FORBID_ATTR = objectHasOwnProperty(cfg, "FORBID_ATTR") ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone2({}); USE_PROFILES = objectHasOwnProperty(cfg, "USE_PROFILES") ? cfg.USE_PROFILES : false; ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; RETURN_DOM = cfg.RETURN_DOM || false; RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; FORCE_BODY = cfg.FORCE_BODY || false; SANITIZE_DOM = cfg.SANITIZE_DOM !== false; SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; KEEP_CONTENT = cfg.KEEP_CONTENT !== false; IN_PLACE = cfg.IN_PLACE || false; IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI; NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE; MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS; HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS; CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {}; if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) { CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck; } if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) { CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck; } if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === "boolean") { CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements; } if (SAFE_FOR_TEMPLATES) { ALLOW_DATA_ATTR = false; } if (RETURN_DOM_FRAGMENT) { RETURN_DOM = true; } if (USE_PROFILES) { ALLOWED_TAGS = addToSet({}, text); ALLOWED_ATTR = []; if (USE_PROFILES.html === true) { addToSet(ALLOWED_TAGS, html$1); addToSet(ALLOWED_ATTR, html); } if (USE_PROFILES.svg === true) { addToSet(ALLOWED_TAGS, svg$1); addToSet(ALLOWED_ATTR, svg); addToSet(ALLOWED_ATTR, xml); } if (USE_PROFILES.svgFilters === true) { addToSet(ALLOWED_TAGS, svgFilters); addToSet(ALLOWED_ATTR, svg); addToSet(ALLOWED_ATTR, xml); } if (USE_PROFILES.mathMl === true) { addToSet(ALLOWED_TAGS, mathMl$1); addToSet(ALLOWED_ATTR, mathMl); addToSet(ALLOWED_ATTR, xml); } } if (cfg.ADD_TAGS) { if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) { ALLOWED_TAGS = clone2(ALLOWED_TAGS); } addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc); } if (cfg.ADD_ATTR) { if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) { ALLOWED_ATTR = clone2(ALLOWED_ATTR); } addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc); } if (cfg.ADD_URI_SAFE_ATTR) { addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc); } if (cfg.FORBID_CONTENTS) { if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) { FORBID_CONTENTS = clone2(FORBID_CONTENTS); } addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc); } if (KEEP_CONTENT) { ALLOWED_TAGS["#text"] = true; } if (WHOLE_DOCUMENT) { addToSet(ALLOWED_TAGS, ["html", "head", "body"]); } if (ALLOWED_TAGS.table) { addToSet(ALLOWED_TAGS, ["tbody"]); delete FORBID_TAGS.tbody; } if (cfg.TRUSTED_TYPES_POLICY) { if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== "function") { throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.'); } if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") { throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.'); } trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY; emptyHTML = trustedTypesPolicy.createHTML(""); } else { if (trustedTypesPolicy === void 0) { trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript); } if (trustedTypesPolicy !== null && typeof emptyHTML === "string") { emptyHTML = trustedTypesPolicy.createHTML(""); } } if (freeze) { freeze(cfg); } CONFIG = cfg; }; const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]); const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]); const _checkValidNamespace = function _checkValidNamespace2(element) { let parent = getParentNode(element); if (!parent || !parent.tagName) { parent = { namespaceURI: NAMESPACE, tagName: "template" }; } const tagName = stringToLowerCase(element.tagName); const parentTagName = stringToLowerCase(parent.tagName); if (!ALLOWED_NAMESPACES[element.namespaceURI]) { return false; } if (element.namespaceURI === SVG_NAMESPACE) { if (parent.namespaceURI === HTML_NAMESPACE) { return tagName === "svg"; } if (parent.namespaceURI === MATHML_NAMESPACE) { return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]); } return Boolean(ALL_SVG_TAGS[tagName]); } if (element.namespaceURI === MATHML_NAMESPACE) { if (parent.namespaceURI === HTML_NAMESPACE) { return tagName === "math"; } if (parent.namespaceURI === SVG_NAMESPACE) { return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName]; } return Boolean(ALL_MATHML_TAGS[tagName]); } if (element.namespaceURI === HTML_NAMESPACE) { if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) { return false; } if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) { return false; } return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]); } if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) { return true; } return false; }; const _forceRemove = function _forceRemove2(node) { arrayPush(DOMPurify.removed, { element: node }); try { getParentNode(node).removeChild(node); } catch (_) { remove4(node); } }; const _removeAttribute = function _removeAttribute2(name, element) { try { arrayPush(DOMPurify.removed, { attribute: element.getAttributeNode(name), from: element }); } catch (_) { arrayPush(DOMPurify.removed, { attribute: null, from: element }); } element.removeAttribute(name); if (name === "is") { if (RETURN_DOM || RETURN_DOM_FRAGMENT) { try { _forceRemove(element); } catch (_) { } } else { try { element.setAttribute(name, ""); } catch (_) { } } } }; const _initDocument = function _initDocument2(dirty) { let doc = null; let leadingWhitespace = null; if (FORCE_BODY) { dirty = "maximumMipmapLevel is suitable for
* PBR rendering of a material with maximum roughness (1.0).
* @memberOf SpecularEnvironmentCubeMap.prototype
* @type {number}
* @readonly
*/
maximumMipmapLevel: {
get: function() {
return this._maximumMipmapLevel;
}
},
/**
* Determines if the cube map is complete and ready to use.
* @memberof SpecularEnvironmentCubeMap.prototype
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
}
});
SpecularEnvironmentCubeMap.isSupported = function(context) {
const supportsFloatBuffersAndTextures = context.colorBufferHalfFloat && context.halfFloatingPointTexture || context.floatingPointTexture && context.colorBufferFloat;
return supportsFloatBuffersAndTextures && context.supportsTextureLod;
};
function cleanupResources(map) {
map._cubeMapBuffers = void 0;
}
SpecularEnvironmentCubeMap.prototype.update = function(frameState) {
const { context } = frameState;
if (!SpecularEnvironmentCubeMap.isSupported(context)) {
return;
}
if (defined_default(this._texture)) {
cleanupResources(this);
return;
}
if (!defined_default(this._texture) && !this._loading) {
const cachedTexture = context.textureCache.getTexture(this._url);
if (defined_default(cachedTexture)) {
cleanupResources(this);
this._texture = cachedTexture;
this._maximumMipmapLevel = this._texture.maximumMipmapLevel;
this._ready = true;
}
}
const cubeMapBuffers = this._cubeMapBuffers;
if (!defined_default(cubeMapBuffers) && !this._loading) {
const that = this;
loadKTX2_default(this._url).then(function(buffers) {
that._cubeMapBuffers = buffers;
that._loading = false;
}).catch(function(error) {
if (that.isDestroyed()) {
return;
}
that._errorEvent.raiseEvent(error);
});
this._loading = true;
}
if (!defined_default(this._cubeMapBuffers)) {
return;
}
let { pixelDatatype } = cubeMapBuffers[0].positiveX;
if (!defined_default(pixelDatatype)) {
pixelDatatype = context.halfFloatingPointTexture ? PixelDatatype_default.HALF_FLOAT : PixelDatatype_default.FLOAT;
}
const pixelFormat = PixelFormat_default.RGBA;
const mipLevels = cubeMapBuffers.length;
this._maximumMipmapLevel = mipLevels - 1;
const faceSize = cubeMapBuffers[0].positiveX.width;
const expectedMipLevels = Math.log2(faceSize) + 1;
if (mipLevels !== expectedMipLevels) {
const dummyMipLevel = {};
Object.values(CubeMap_default.FaceName).forEach((faceName) => {
dummyMipLevel[faceName] = void 0;
});
for (let mipLevel = mipLevels; mipLevel < expectedMipLevels; mipLevel++) {
cubeMapBuffers.push(dummyMipLevel);
}
}
const sampler = new Sampler_default({
minificationFilter: TextureMinificationFilter_default.LINEAR_MIPMAP_LINEAR
});
const cubeMap = new CubeMap_default({
context,
source: cubeMapBuffers[0],
flipY: false,
pixelDatatype,
pixelFormat,
sampler
});
cubeMap.loadMipmaps(cubeMapBuffers.slice(1));
this._texture = cubeMap;
this._texture.maximumMipmapLevel = this._maximumMipmapLevel;
context.textureCache.addTexture(this._url, this._texture);
this._ready = true;
};
SpecularEnvironmentCubeMap.prototype.isDestroyed = function() {
return false;
};
SpecularEnvironmentCubeMap.prototype.destroy = function() {
cleanupResources(this);
this._texture = this._texture && this._texture.destroy();
return destroyObject_default(this);
};
var SpecularEnvironmentCubeMap_default = SpecularEnvironmentCubeMap;
// packages/engine/Source/Scene/ImageBasedLighting.js
function ImageBasedLighting(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const imageBasedLightingFactor = defined_default(options.imageBasedLightingFactor) ? Cartesian2_default.clone(options.imageBasedLightingFactor) : new Cartesian2_default(1, 1);
Check_default.typeOf.object(
"options.imageBasedLightingFactor",
imageBasedLightingFactor
);
Check_default.typeOf.number.greaterThanOrEquals(
"options.imageBasedLightingFactor.x",
imageBasedLightingFactor.x,
0
);
Check_default.typeOf.number.lessThanOrEquals(
"options.imageBasedLightingFactor.x",
imageBasedLightingFactor.x,
1
);
Check_default.typeOf.number.greaterThanOrEquals(
"options.imageBasedLightingFactor.y",
imageBasedLightingFactor.y,
0
);
Check_default.typeOf.number.lessThanOrEquals(
"options.imageBasedLightingFactor.y",
imageBasedLightingFactor.y,
1
);
this._imageBasedLightingFactor = imageBasedLightingFactor;
const sphericalHarmonicCoefficients = options.sphericalHarmonicCoefficients;
if (defined_default(sphericalHarmonicCoefficients) && (!Array.isArray(sphericalHarmonicCoefficients) || sphericalHarmonicCoefficients.length !== 9)) {
throw new DeveloperError_default(
"options.sphericalHarmonicCoefficients must be an array of 9 Cartesian3 values."
);
}
this._sphericalHarmonicCoefficients = sphericalHarmonicCoefficients;
this._specularEnvironmentMaps = options.specularEnvironmentMaps;
this._specularEnvironmentCubeMap = void 0;
this._specularEnvironmentCubeMapDirty = true;
this._specularEnvironmentMapLoaded = false;
this._previousSpecularEnvironmentMapLoaded = false;
this._useDefaultSpecularMaps = false;
this._useDefaultSphericalHarmonics = false;
this._shouldRegenerateShaders = false;
this._previousFrameNumber = void 0;
this._previousFrameContext = void 0;
this._previousImageBasedLightingFactor = Cartesian2_default.clone(
imageBasedLightingFactor
);
this._previousSphericalHarmonicCoefficients = sphericalHarmonicCoefficients;
this._removeErrorListener = void 0;
}
Object.defineProperties(ImageBasedLighting.prototype, {
/**
* Cesium adds lighting from the earth, sky, atmosphere, and star skybox.
* This cartesian is used to scale the final diffuse and specular lighting
* contribution from those sources to the final color. A value of 0.0 will
* disable those light sources.
*
* @memberof ImageBasedLighting.prototype
*
* @type {Cartesian2}
* @default Cartesian2(1.0, 1.0)
*/
imageBasedLightingFactor: {
get: function() {
return this._imageBasedLightingFactor;
},
set: function(value) {
Check_default.typeOf.object("imageBasedLightingFactor", value);
Check_default.typeOf.number.greaterThanOrEquals(
"imageBasedLightingFactor.x",
value.x,
0
);
Check_default.typeOf.number.lessThanOrEquals(
"imageBasedLightingFactor.x",
value.x,
1
);
Check_default.typeOf.number.greaterThanOrEquals(
"imageBasedLightingFactor.y",
value.y,
0
);
Check_default.typeOf.number.lessThanOrEquals(
"imageBasedLightingFactor.y",
value.y,
1
);
this._previousImageBasedLightingFactor = Cartesian2_default.clone(
this._imageBasedLightingFactor,
this._previousImageBasedLightingFactor
);
this._imageBasedLightingFactor = Cartesian2_default.clone(
value,
this._imageBasedLightingFactor
);
}
},
/**
* The third order spherical harmonic coefficients used for the diffuse color of image-based lighting. When undefined, a diffuse irradiance
* computed from the atmosphere color is used.
*
* There are nine Cartesian3 coefficients.
* The order of the coefficients is: L0,0, L1,-1, L1,0, L1,1, L2,-2, L2,-1, L2,0, L2,1, L2,2
*
cmgen tool of
* {@link https://github.com/google/filament/releases|Google's Filament project}.
* Be sure to use the --no-mirror option in cmgen.
*
* @memberof ImageBasedLighting.prototype
*
* @type {Cartesian3[]}
* @demo {@link https://sandcastle.cesium.com/index.html?src=Image-Based Lighting.html|Sandcastle Image Based Lighting Demo}
* @see {@link https://graphics.stanford.edu/papers/envmap/envmap.pdf|An Efficient Representation for Irradiance Environment Maps}
*/
sphericalHarmonicCoefficients: {
get: function() {
return this._sphericalHarmonicCoefficients;
},
set: function(value) {
if (defined_default(value) && (!Array.isArray(value) || value.length !== 9)) {
throw new DeveloperError_default(
"sphericalHarmonicCoefficients must be an array of 9 Cartesian3 values."
);
}
this._previousSphericalHarmonicCoefficients = this._sphericalHarmonicCoefficients;
this._sphericalHarmonicCoefficients = value;
}
},
/**
* A URL to a KTX2 file that contains a cube map of the specular lighting and the convoluted specular mipmaps.
*
* @memberof ImageBasedLighting.prototype
* @demo {@link https://sandcastle.cesium.com/index.html?src=Image-Based Lighting.html|Sandcastle Image Based Lighting Demo}
* @type {string}
* @see ImageBasedLighting#sphericalHarmonicCoefficients
*/
specularEnvironmentMaps: {
get: function() {
return this._specularEnvironmentMaps;
},
set: function(value) {
if (value !== this._specularEnvironmentMaps) {
this._specularEnvironmentCubeMapDirty = this._specularEnvironmentCubeMapDirty || value !== this._specularEnvironmentMaps;
this._specularEnvironmentMapLoaded = false;
}
this._specularEnvironmentMaps = value;
}
},
/**
* Whether or not image-based lighting is enabled.
*
* @memberof ImageBasedLighting.prototype
* @type {boolean}
*
* @private
*/
enabled: {
get: function() {
return this._imageBasedLightingFactor.x > 0 || this._imageBasedLightingFactor.y > 0;
}
},
/**
* Whether or not the models that use this lighting should regenerate their shaders,
* based on the properties and resources have changed.
*
* @memberof ImageBasedLighting.prototype
* @type {boolean}
*
* @private
*/
shouldRegenerateShaders: {
get: function() {
return this._shouldRegenerateShaders;
}
},
/**
* The texture atlas for the specular environment maps.
*
* @memberof ImageBasedLighting.prototype
* @type {SpecularEnvironmentCubeMap}
*
* @private
*/
specularEnvironmentCubeMap: {
get: function() {
return this._specularEnvironmentCubeMap;
}
},
/**
* Whether or not to use the default spherical harmonics coefficients.
*
* @memberof ImageBasedLighting.prototype
* @type {boolean}
*
* @private
*/
useDefaultSphericalHarmonics: {
get: function() {
return this._useDefaultSphericalHarmonics;
}
},
/**
* Whether or not to use the default specular environment maps.
*
* @memberof ImageBasedLighting.prototype
* @type {boolean}
*
* @private
*/
useDefaultSpecularMaps: {
get: function() {
return this._useDefaultSpecularMaps;
}
},
/**
* Whether or not the image-based lighting settings use specular environment maps.
*
* @memberof ImageBasedLighting.prototype
* @type {boolean}
*
* @private
*/
useSpecularEnvironmentMaps: {
get: function() {
return defined_default(this._specularEnvironmentCubeMap) && this._specularEnvironmentCubeMap.ready || this._useDefaultSpecularMaps;
}
}
});
function createSpecularEnvironmentCubeMap(imageBasedLighting, context) {
if (!SpecularEnvironmentCubeMap_default.isSupported(context)) {
return;
}
imageBasedLighting._specularEnvironmentCubeMap = imageBasedLighting._specularEnvironmentCubeMap && imageBasedLighting._specularEnvironmentCubeMap.destroy();
if (defined_default(imageBasedLighting._specularEnvironmentMaps)) {
const cubeMap = new SpecularEnvironmentCubeMap_default(
imageBasedLighting._specularEnvironmentMaps
);
imageBasedLighting._specularEnvironmentCubeMap = cubeMap;
imageBasedLighting._removeErrorListener = cubeMap.errorEvent.addEventListener((error) => {
console.error(`Error loading specularEnvironmentMaps: ${error}`);
});
}
imageBasedLighting._shouldRegenerateShaders = true;
}
ImageBasedLighting.prototype.update = function(frameState) {
if (frameState.frameNumber === this._previousFrameNumber && frameState.context === this._previousFrameContext) {
return;
}
this._previousFrameNumber = frameState.frameNumber;
const context = this._previousFrameContext = frameState.context;
frameState.brdfLutGenerator.update(frameState);
this._shouldRegenerateShaders = false;
const iblFactor = this._imageBasedLightingFactor;
const previousIBLFactor = this._previousImageBasedLightingFactor;
if (!Cartesian2_default.equals(iblFactor, previousIBLFactor)) {
this._shouldRegenerateShaders = iblFactor.x > 0 && previousIBLFactor.x === 0 || iblFactor.x === 0 && previousIBLFactor.x > 0;
this._shouldRegenerateShaders = this._shouldRegenerateShaders || iblFactor.y > 0 && previousIBLFactor.y === 0 || iblFactor.y === 0 && previousIBLFactor.y > 0;
this._previousImageBasedLightingFactor = Cartesian2_default.clone(
this._imageBasedLightingFactor,
this._previousImageBasedLightingFactor
);
}
if (this._previousSphericalHarmonicCoefficients !== this._sphericalHarmonicCoefficients) {
this._shouldRegenerateShaders = this._shouldRegenerateShaders || defined_default(this._previousSphericalHarmonicCoefficients) !== defined_default(this._sphericalHarmonicCoefficients);
this._previousSphericalHarmonicCoefficients = this._sphericalHarmonicCoefficients;
}
this._shouldRegenerateShaders = this._shouldRegenerateShaders || this._previousSpecularEnvironmentMapLoaded !== this._specularEnvironmentMapLoaded;
this._previousSpecularEnvironmentMapLoaded = this._specularEnvironmentMapLoaded;
if (this._specularEnvironmentCubeMapDirty) {
createSpecularEnvironmentCubeMap(this, context);
this._specularEnvironmentCubeMapDirty = false;
}
if (defined_default(this._specularEnvironmentCubeMap)) {
this._specularEnvironmentCubeMap.update(frameState);
if (this._specularEnvironmentCubeMap.ready) {
this._specularEnvironmentMapLoaded = true;
}
}
const recompileWithDefaultCubeMap = !defined_default(this._specularEnvironmentCubeMap) && defined_default(frameState.specularEnvironmentMaps) && !this._useDefaultSpecularMaps;
const recompileWithoutDefaultCubeMap = !defined_default(frameState.specularEnvironmentMaps) && this._useDefaultSpecularMaps;
const recompileWithDefaultSHCoeffs = !defined_default(this._sphericalHarmonicCoefficients) && defined_default(frameState.sphericalHarmonicCoefficients) && !this._useDefaultSphericalHarmonics;
const recompileWithoutDefaultSHCoeffs = !defined_default(frameState.sphericalHarmonicCoefficients) && this._useDefaultSphericalHarmonics;
this._shouldRegenerateShaders = this._shouldRegenerateShaders || recompileWithDefaultCubeMap || recompileWithoutDefaultCubeMap || recompileWithDefaultSHCoeffs || recompileWithoutDefaultSHCoeffs;
this._useDefaultSpecularMaps = !defined_default(this._specularEnvironmentCubeMap) && defined_default(frameState.specularEnvironmentMaps);
this._useDefaultSphericalHarmonics = !defined_default(this._sphericalHarmonicCoefficients) && defined_default(frameState.sphericalHarmonicCoefficients);
};
ImageBasedLighting.prototype.isDestroyed = function() {
return false;
};
ImageBasedLighting.prototype.destroy = function() {
this._specularEnvironmentCubeMap = this._specularEnvironmentCubeMap && this._specularEnvironmentCubeMap.destroy();
this._removeErrorListener = this._removeErrorListener && this._removeErrorListener();
return destroyObject_default(this);
};
var ImageBasedLighting_default = ImageBasedLighting;
// packages/engine/Source/Core/IonResource.js
var import_InlineWorkers430 = __toESM(require_InlineWorkers(), 1);
var import_urijs8 = __toESM(require_URI(), 1);
// packages/engine/Source/Core/Ion.js
var import_InlineWorkers429 = __toESM(require_InlineWorkers(), 1);
var defaultTokenCredit;
var defaultAccessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NTEwZTU2Yi0wOGEyLTQyZjgtOTJjNi04Mzc2NGRlNzA4NTkiLCJpZCI6MjU5LCJpYXQiOjE3NTY4NDExOTJ9._Y3MIsYgGKTVTpkEpKPNT0cQSa_hUocY0DdH7h0U-xM";
var Ion = {};
Ion.defaultAccessToken = defaultAccessToken;
Ion.defaultServer = new Resource_default({ url: "https://api.cesium.com/" });
Ion.getDefaultTokenCredit = function(providedKey) {
if (providedKey !== defaultAccessToken) {
return void 0;
}
if (!defined_default(defaultTokenCredit)) {
const defaultTokenMessage = ` This application is using Cesium's default ion access token. Please assign Cesium.Ion.defaultAccessToken with an access token from your ion account before making any Cesium API calls. You can sign up for a free ion account at https://cesium.com.`;
defaultTokenCredit = new Credit_default(defaultTokenMessage, true);
}
return defaultTokenCredit;
};
var Ion_default = Ion;
// packages/engine/Source/Core/IonResource.js
function IonResource(endpoint, endpointResource) {
Check_default.defined("endpoint", endpoint);
Check_default.defined("endpointResource", endpointResource);
let options;
const externalType = endpoint.externalType;
const isExternal = defined_default(externalType);
if (!isExternal) {
options = {
url: endpoint.url,
retryAttempts: 1,
retryCallback
};
} else if (externalType === "3DTILES" || externalType === "STK_TERRAIN_SERVER") {
options = { url: endpoint.options.url };
} else {
throw new RuntimeError_default(
"Ion.createResource does not support external imagery assets; use IonImageryProvider instead."
);
}
Resource_default.call(this, options);
this._ionEndpoint = endpoint;
this._ionEndpointDomain = isExternal ? void 0 : new import_urijs8.default(endpoint.url).authority();
this._ionEndpointResource = endpointResource;
this._ionRoot = void 0;
this._pendingPromise = void 0;
this._credits = void 0;
this._isExternal = isExternal;
}
if (defined_default(Object.create)) {
IonResource.prototype = Object.create(Resource_default.prototype);
IonResource.prototype.constructor = IonResource;
}
IonResource.fromAssetId = function(assetId, options) {
const endpointResource = IonResource._createEndpointResource(
assetId,
options
);
return endpointResource.fetchJson().then(function(endpoint) {
return new IonResource(endpoint, endpointResource);
});
};
Object.defineProperties(IonResource.prototype, {
/**
* Gets the credits required for attribution of the asset.
*
* @memberof IonResource.prototype
* @type {Credit[]}
* @readonly
*/
credits: {
get: function() {
if (defined_default(this._ionRoot)) {
return this._ionRoot.credits;
}
if (defined_default(this._credits)) {
return this._credits;
}
this._credits = IonResource.getCreditsFromEndpoint(
this._ionEndpoint,
this._ionEndpointResource
);
return this._credits;
}
}
});
IonResource.getCreditsFromEndpoint = function(endpoint, endpointResource) {
const credits = endpoint.attributions.map(Credit_default.getIonCredit);
const defaultTokenCredit3 = Ion_default.getDefaultTokenCredit(
endpointResource.queryParameters.access_token
);
if (defined_default(defaultTokenCredit3)) {
credits.push(Credit_default.clone(defaultTokenCredit3));
}
return credits;
};
IonResource.prototype.clone = function(result) {
const ionRoot = this._ionRoot ?? this;
if (!defined_default(result)) {
result = new IonResource(
ionRoot._ionEndpoint,
ionRoot._ionEndpointResource
);
}
result = Resource_default.prototype.clone.call(this, result);
result._ionRoot = ionRoot;
result._isExternal = this._isExternal;
return result;
};
IonResource.prototype.fetchImage = function(options) {
if (!this._isExternal) {
const userOptions = options;
options = {
preferBlob: true
};
if (defined_default(userOptions)) {
options.flipY = userOptions.flipY;
options.preferImageBitmap = userOptions.preferImageBitmap;
}
}
return Resource_default.prototype.fetchImage.call(this, options);
};
IonResource.prototype._makeRequest = function(options) {
if (this._isExternal || new import_urijs8.default(this.url).authority() !== this._ionEndpointDomain) {
return Resource_default.prototype._makeRequest.call(this, options);
}
addClientHeaders(options);
options.headers.Authorization = `Bearer ${this._ionEndpoint.accessToken}`;
return Resource_default.prototype._makeRequest.call(this, options);
};
IonResource._createEndpointResource = function(assetId, options) {
Check_default.defined("assetId", assetId);
options = options ?? Frozen_default.EMPTY_OBJECT;
let server = options.server ?? Ion_default.defaultServer;
const accessToken = options.accessToken ?? Ion_default.defaultAccessToken;
server = Resource_default.createIfNeeded(server);
const resourceOptions = {
url: `v1/assets/${assetId}/endpoint`
};
if (defined_default(accessToken)) {
resourceOptions.queryParameters = { access_token: accessToken };
}
addClientHeaders(resourceOptions);
return server.getDerivedResource(resourceOptions);
};
function addClientHeaders(options) {
if (!defined_default(options.headers)) {
options.headers = {};
}
options.headers["X-Cesium-Client"] = "CesiumJS";
if (typeof CESIUM_VERSION !== "undefined") {
options.headers["X-Cesium-Client-Version"] = CESIUM_VERSION;
}
}
function retryCallback(that, error) {
const ionRoot = that._ionRoot ?? that;
const endpointResource = ionRoot._ionEndpointResource;
const imageDefined = typeof Image !== "undefined";
if (!defined_default(error) || error.statusCode !== 401 && !(imageDefined && error.target instanceof Image)) {
return Promise.resolve(false);
}
if (!defined_default(ionRoot._pendingPromise)) {
ionRoot._pendingPromise = endpointResource.fetchJson().then(function(newEndpoint) {
ionRoot._ionEndpoint = newEndpoint;
return newEndpoint;
}).finally(function(newEndpoint) {
ionRoot._pendingPromise = void 0;
return newEndpoint;
});
}
return ionRoot._pendingPromise.then(function(newEndpoint) {
that._ionEndpoint = newEndpoint;
return true;
});
}
var IonResource_default = IonResource;
// packages/engine/Source/Core/ManagedArray.js
var import_InlineWorkers431 = __toESM(require_InlineWorkers(), 1);
function ManagedArray(length2) {
length2 = length2 ?? 0;
this._array = new Array(length2);
this._length = length2;
}
Object.defineProperties(ManagedArray.prototype, {
/**
* Gets or sets the length of the array.
* If the set length is greater than the length of the internal array, the internal array is resized.
*
* @memberof ManagedArray.prototype
* @type {number}
*/
length: {
get: function() {
return this._length;
},
set: function(length2) {
Check_default.typeOf.number.greaterThanOrEquals("length", length2, 0);
const array = this._array;
const originalLength = this._length;
if (length2 < originalLength) {
for (let i = length2; i < originalLength; ++i) {
array[i] = void 0;
}
} else if (length2 > array.length) {
array.length = length2;
}
this._length = length2;
}
},
/**
* Gets the internal array.
*
* @memberof ManagedArray.prototype
* @type {Array}
* @readonly
*/
values: {
get: function() {
return this._array;
}
}
});
ManagedArray.prototype.get = function(index) {
Check_default.typeOf.number.lessThan("index", index, this._array.length);
return this._array[index];
};
ManagedArray.prototype.set = function(index, element) {
Check_default.typeOf.number("index", index);
if (index >= this._length) {
this.length = index + 1;
}
this._array[index] = element;
};
ManagedArray.prototype.peek = function() {
return this._array[this._length - 1];
};
ManagedArray.prototype.push = function(element) {
const index = this.length++;
this._array[index] = element;
};
ManagedArray.prototype.pop = function() {
if (this._length === 0) {
return void 0;
}
const element = this._array[this._length - 1];
--this.length;
return element;
};
ManagedArray.prototype.reserve = function(length2) {
Check_default.typeOf.number.greaterThanOrEquals("length", length2, 0);
if (length2 > this._array.length) {
this._array.length = length2;
}
};
ManagedArray.prototype.resize = function(length2) {
Check_default.typeOf.number.greaterThanOrEquals("length", length2, 0);
this.length = length2;
};
ManagedArray.prototype.trim = function(length2) {
length2 = length2 ?? this._length;
this._array.length = length2;
};
var ManagedArray_default = ManagedArray;
// packages/engine/Source/Scene/Axis.js
var import_InlineWorkers432 = __toESM(require_InlineWorkers(), 1);
var Axis = {
/**
* Denotes the x-axis.
*
* @type {number}
* @constant
*/
X: 0,
/**
* Denotes the y-axis.
*
* @type {number}
* @constant
*/
Y: 1,
/**
* Denotes the z-axis.
*
* @type {number}
* @constant
*/
Z: 2
};
Axis.Y_UP_TO_Z_UP = Matrix4_default.fromRotationTranslation(
// Rotation about PI/2 around the X-axis
Matrix3_default.fromArray([1, 0, 0, 0, 0, 1, 0, -1, 0])
);
Axis.Z_UP_TO_Y_UP = Matrix4_default.fromRotationTranslation(
// Rotation about -PI/2 around the X-axis
Matrix3_default.fromArray([1, 0, 0, 0, 0, -1, 0, 1, 0])
);
Axis.X_UP_TO_Z_UP = Matrix4_default.fromRotationTranslation(
// Rotation about -PI/2 around the Y-axis
Matrix3_default.fromArray([0, 0, 1, 0, 1, 0, -1, 0, 0])
);
Axis.Z_UP_TO_X_UP = Matrix4_default.fromRotationTranslation(
// Rotation about PI/2 around the Y-axis
Matrix3_default.fromArray([0, 0, -1, 0, 1, 0, 1, 0, 0])
);
Axis.X_UP_TO_Y_UP = Matrix4_default.fromRotationTranslation(
// Rotation about PI/2 around the Z-axis
Matrix3_default.fromArray([0, 1, 0, -1, 0, 0, 0, 0, 1])
);
Axis.Y_UP_TO_X_UP = Matrix4_default.fromRotationTranslation(
// Rotation about -PI/2 around the Z-axis
Matrix3_default.fromArray([0, -1, 0, 1, 0, 0, 0, 0, 1])
);
Axis.fromName = function(name) {
Check_default.typeOf.string("name", name);
return Axis[name];
};
var Axis_default = Object.freeze(Axis);
// packages/engine/Source/Scene/Cesium3DTile.js
var import_InlineWorkers796 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Cesium3DContentGroup.js
var import_InlineWorkers433 = __toESM(require_InlineWorkers(), 1);
function Cesium3DContentGroup(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("options.metadata", options.metadata);
this._metadata = options.metadata;
}
Object.defineProperties(Cesium3DContentGroup.prototype, {
/**
* Get the metadata for this group
*
* @memberof Cesium3DContentGroup.prototype
*
* @type {GroupMetadata}
*
* @readonly
*/
metadata: {
get: function() {
return this._metadata;
}
}
});
var Cesium3DContentGroup_default = Cesium3DContentGroup;
// packages/engine/Source/Scene/Cesium3DTileContentFactory.js
var import_InlineWorkers773 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Composite3DTileContent.js
var import_InlineWorkers436 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/getMagic.js
var import_InlineWorkers435 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/getStringFromTypedArray.js
var import_InlineWorkers434 = __toESM(require_InlineWorkers(), 1);
function getStringFromTypedArray(uint8Array, byteOffset, byteLength) {
if (!defined_default(uint8Array)) {
throw new DeveloperError_default("uint8Array is required.");
}
if (byteOffset < 0) {
throw new DeveloperError_default("byteOffset cannot be negative.");
}
if (byteLength < 0) {
throw new DeveloperError_default("byteLength cannot be negative.");
}
if (byteOffset + byteLength > uint8Array.byteLength) {
throw new DeveloperError_default("sub-region exceeds array bounds.");
}
byteOffset = byteOffset ?? 0;
byteLength = byteLength ?? uint8Array.byteLength - byteOffset;
uint8Array = uint8Array.subarray(byteOffset, byteOffset + byteLength);
return getStringFromTypedArray.decode(uint8Array);
}
getStringFromTypedArray.decodeWithTextDecoder = function(view) {
const decoder = new TextDecoder("utf-8");
return decoder.decode(view);
};
getStringFromTypedArray.decodeWithFromCharCode = function(view) {
let result = "";
const codePoints = utf8Handler(view);
const length2 = codePoints.length;
for (let i = 0; i < length2; ++i) {
let cp = codePoints[i];
if (cp <= 65535) {
result += String.fromCharCode(cp);
} else {
cp -= 65536;
result += String.fromCharCode((cp >> 10) + 55296, (cp & 1023) + 56320);
}
}
return result;
};
function inRange(a3, min3, max3) {
return min3 <= a3 && a3 <= max3;
}
function utf8Handler(utfBytes) {
let codePoint = 0;
let bytesSeen = 0;
let bytesNeeded = 0;
let lowerBoundary = 128;
let upperBoundary = 191;
const codePoints = [];
const length2 = utfBytes.length;
for (let i = 0; i < length2; ++i) {
const currentByte = utfBytes[i];
if (bytesNeeded === 0) {
if (inRange(currentByte, 0, 127)) {
codePoints.push(currentByte);
continue;
}
if (inRange(currentByte, 194, 223)) {
bytesNeeded = 1;
codePoint = currentByte & 31;
continue;
}
if (inRange(currentByte, 224, 239)) {
if (currentByte === 224) {
lowerBoundary = 160;
}
if (currentByte === 237) {
upperBoundary = 159;
}
bytesNeeded = 2;
codePoint = currentByte & 15;
continue;
}
if (inRange(currentByte, 240, 244)) {
if (currentByte === 240) {
lowerBoundary = 144;
}
if (currentByte === 244) {
upperBoundary = 143;
}
bytesNeeded = 3;
codePoint = currentByte & 7;
continue;
}
throw new RuntimeError_default("String decoding failed.");
}
if (!inRange(currentByte, lowerBoundary, upperBoundary)) {
codePoint = bytesNeeded = bytesSeen = 0;
lowerBoundary = 128;
upperBoundary = 191;
--i;
continue;
}
lowerBoundary = 128;
upperBoundary = 191;
codePoint = codePoint << 6 | currentByte & 63;
++bytesSeen;
if (bytesSeen === bytesNeeded) {
codePoints.push(codePoint);
codePoint = bytesNeeded = bytesSeen = 0;
}
}
return codePoints;
}
if (typeof TextDecoder !== "undefined") {
getStringFromTypedArray.decode = getStringFromTypedArray.decodeWithTextDecoder;
} else {
getStringFromTypedArray.decode = getStringFromTypedArray.decodeWithFromCharCode;
}
var getStringFromTypedArray_default = getStringFromTypedArray;
// packages/engine/Source/Core/getMagic.js
function getMagic(uint8Array, byteOffset) {
byteOffset = byteOffset ?? 0;
return getStringFromTypedArray_default(
uint8Array,
byteOffset,
Math.min(4, uint8Array.length)
);
}
var getMagic_default = getMagic;
// packages/engine/Source/Scene/Composite3DTileContent.js
function Composite3DTileContent(tileset, tile, resource, contents) {
this._tileset = tileset;
this._tile = tile;
this._resource = resource;
if (!defined_default(contents)) {
contents = [];
}
this._contents = contents;
this._metadata = void 0;
this._group = void 0;
this._ready = false;
}
Object.defineProperties(Composite3DTileContent.prototype, {
featurePropertiesDirty: {
get: function() {
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
if (contents[i].featurePropertiesDirty) {
return true;
}
}
return false;
},
set: function(value) {
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
contents[i].featurePropertiesDirty = value;
}
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent
* always returns 0. Instead call featuresLength for a tile in the composite.
* @memberof Composite3DTileContent.prototype
*/
featuresLength: {
get: function() {
return 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent
* always returns 0. Instead call pointsLength for a tile in the composite.
* @memberof Composite3DTileContent.prototype
*/
pointsLength: {
get: function() {
return 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent
* always returns 0. Instead call trianglesLength for a tile in the composite.
* @memberof Composite3DTileContent.prototype
*/
trianglesLength: {
get: function() {
return 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent
* always returns 0. Instead call geometryByteLength for a tile in the composite.
* @memberof Composite3DTileContent.prototype
*/
geometryByteLength: {
get: function() {
return 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent
* always returns 0. Instead call texturesByteLength for a tile in the composite.
* @memberof Composite3DTileContent.prototype
*/
texturesByteLength: {
get: function() {
return 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent
* always returns 0. Instead call batchTableByteLength for a tile in the composite.
* @memberof Composite3DTileContent.prototype
*/
batchTableByteLength: {
get: function() {
return 0;
}
},
innerContents: {
get: function() {
return this._contents;
}
},
/**
* Returns true when the tile's content is ready to render; otherwise false
*
* @memberof Composite3DTileContent.prototype
*
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
return this._ready;
}
},
tileset: {
get: function() {
return this._tileset;
}
},
tile: {
get: function() {
return this._tile;
}
},
url: {
get: function() {
return this._resource.getUrlComponent(true);
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent
* both stores the content metadata and propagates the content metadata to all of its children.
* @memberof Composite3DTileContent.prototype
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
metadata: {
get: function() {
return this._metadata;
},
set: function(value) {
this._metadata = value;
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
contents[i].metadata = value;
}
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent
* always returns undefined. Instead call batchTable for a tile in the composite.
* @memberof Composite3DTileContent.prototype
*/
batchTable: {
get: function() {
return void 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent
* both stores the group metadata and propagates the group metadata to all of its children.
* @memberof Composite3DTileContent.prototype
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
group: {
get: function() {
return this._group;
},
set: function(value) {
this._group = value;
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
contents[i].group = value;
}
}
}
});
var sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;
Composite3DTileContent.fromTileType = async function(tileset, tile, resource, arrayBuffer, byteOffset, factory) {
byteOffset = byteOffset ?? 0;
const uint8Array = new Uint8Array(arrayBuffer);
const view = new DataView(arrayBuffer);
byteOffset += sizeOfUint32;
const version2 = view.getUint32(byteOffset, true);
if (version2 !== 1) {
throw new RuntimeError_default(
`Only Composite Tile version 1 is supported. Version ${version2} is not.`
);
}
byteOffset += sizeOfUint32;
byteOffset += sizeOfUint32;
const tilesLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint32;
let prefix = resource.queryParameters.compositeIndex;
if (defined_default(prefix)) {
prefix = `${prefix}_`;
} else {
prefix = "";
}
const promises = [];
promises.length = tilesLength;
for (let i = 0; i < tilesLength; ++i) {
const tileType = getMagic_default(uint8Array, byteOffset);
const tileByteLength = view.getUint32(byteOffset + sizeOfUint32 * 2, true);
const contentFactory = factory[tileType];
const compositeIndex = `${prefix}${i}`;
const childResource = resource.getDerivedResource({
queryParameters: {
compositeIndex
}
});
if (defined_default(contentFactory)) {
promises[i] = Promise.resolve(
contentFactory(tileset, tile, childResource, arrayBuffer, byteOffset)
);
} else {
throw new RuntimeError_default(
`Unknown tile content type, ${tileType}, inside Composite tile`
);
}
byteOffset += tileByteLength;
}
const innerContents = await Promise.all(promises);
const content = new Composite3DTileContent(
tileset,
tile,
resource,
innerContents
);
return content;
};
Composite3DTileContent.prototype.hasProperty = function(batchId, name) {
return false;
};
Composite3DTileContent.prototype.getFeature = function(batchId) {
return void 0;
};
Composite3DTileContent.prototype.applyDebugSettings = function(enabled, color) {
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
contents[i].applyDebugSettings(enabled, color);
}
};
Composite3DTileContent.prototype.applyStyle = function(style) {
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
contents[i].applyStyle(style);
}
};
Composite3DTileContent.prototype.update = function(tileset, frameState) {
const contents = this._contents;
const length2 = contents.length;
let ready = true;
for (let i = 0; i < length2; ++i) {
contents[i].update(tileset, frameState);
ready = ready && contents[i].ready;
}
if (!this._ready && ready) {
this._ready = true;
}
};
Composite3DTileContent.prototype.pick = function(ray, frameState, result) {
if (!this._ready) {
return void 0;
}
let intersection;
let minDistance = Number.POSITIVE_INFINITY;
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
const candidate = contents[i].pick(ray, frameState, result);
if (!defined_default(candidate)) {
continue;
}
const distance2 = Cartesian3_default.distance(ray.origin, candidate);
if (distance2 < minDistance) {
intersection = candidate;
minDistance = distance2;
}
}
if (!defined_default(intersection)) {
return void 0;
}
return result;
};
Composite3DTileContent.prototype.isDestroyed = function() {
return false;
};
Composite3DTileContent.prototype.destroy = function() {
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
contents[i].destroy();
}
return destroyObject_default(this);
};
var Composite3DTileContent_default = Composite3DTileContent;
// packages/engine/Source/Scene/Geometry3DTileContent.js
var import_InlineWorkers451 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/getJsonFromTypedArray.js
var import_InlineWorkers437 = __toESM(require_InlineWorkers(), 1);
function getJsonFromTypedArray(uint8Array, byteOffset, byteLength) {
return JSON.parse(
getStringFromTypedArray_default(uint8Array, byteOffset, byteLength)
);
}
var getJsonFromTypedArray_default = getJsonFromTypedArray;
// packages/engine/Source/Scene/Cesium3DTileBatchTable.js
var import_InlineWorkers442 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/BatchTexture.js
var import_InlineWorkers438 = __toESM(require_InlineWorkers(), 1);
function BatchTexture(options) {
Check_default.typeOf.number("options.featuresLength", options.featuresLength);
Check_default.typeOf.object("options.owner", options.owner);
this._id = createGuid_default();
const featuresLength = options.featuresLength;
this._showAlphaProperties = void 0;
this._batchValues = void 0;
this._batchValuesDirty = false;
this._batchTexture = void 0;
this._defaultTexture = void 0;
this._pickTexture = void 0;
this._pickIds = [];
let textureDimensions;
let textureStep;
if (featuresLength > 0) {
const width = Math.min(featuresLength, ContextLimits_default.maximumTextureSize);
const height = Math.ceil(featuresLength / ContextLimits_default.maximumTextureSize);
const stepX = 1 / width;
const centerX = stepX * 0.5;
const stepY = 1 / height;
const centerY = stepY * 0.5;
textureDimensions = new Cartesian2_default(width, height);
textureStep = new Cartesian4_default(stepX, centerX, stepY, centerY);
}
this._translucentFeaturesLength = 0;
this._featuresLength = featuresLength;
this._textureDimensions = textureDimensions;
this._textureStep = textureStep;
this._owner = options.owner;
this._statistics = options.statistics;
this._colorChangedCallback = options.colorChangedCallback;
}
Object.defineProperties(BatchTexture.prototype, {
/**
* Number of features that are translucent
*
* @memberof BatchTexture.prototype
* @type {number}
* @readonly
* @private
*/
translucentFeaturesLength: {
get: function() {
return this._translucentFeaturesLength;
}
},
/**
* Total size of all GPU resources used by this batch texture.
*
* @memberof BatchTexture.prototype
* @type {number}
* @readonly
* @private
*/
byteLength: {
get: function() {
let memory = 0;
if (defined_default(this._pickTexture)) {
memory += this._pickTexture.sizeInBytes;
}
if (defined_default(this._batchTexture)) {
memory += this._batchTexture.sizeInBytes;
}
return memory;
}
},
/**
* Dimensions of the underlying batch texture.
*
* @memberof BatchTexture.prototype
* @type {Cartesian2}
* @readonly
* @private
*/
textureDimensions: {
get: function() {
return this._textureDimensions;
}
},
/**
* Size of each texture and distance from side to center of a texel in
* each direction. Stored as (stepX, centerX, stepY, centerY)
*
* @memberof BatchTexture.prototype
* @type {Cartesian4}
* @readonly
* @private
*/
textureStep: {
get: function() {
return this._textureStep;
}
},
/**
* The underlying texture used for styling. The texels are accessed
* by batch ID, and the value is the color of this feature after accounting
* for show/hide settings.
*
* @memberof BatchTexture.prototype
* @type {Texture}
* @readonly
* @private
*/
batchTexture: {
get: function() {
return this._batchTexture;
}
},
/**
* The default texture to use when there are no batch values
*
* @memberof BatchTexture.prototype
* @type {Texture}
* @readonly
* @private
*/
defaultTexture: {
get: function() {
return this._defaultTexture;
}
},
/**
* The underlying texture used for picking. The texels are accessed by
* batch ID, and the value is the pick color.
*
* @memberof BatchTexture.prototype
* @type {Texture}
* @readonly
* @private
*/
pickTexture: {
get: function() {
return this._pickTexture;
}
}
});
BatchTexture.DEFAULT_COLOR_VALUE = Color_default.WHITE;
BatchTexture.DEFAULT_SHOW_VALUE = true;
function getByteLength(batchTexture) {
const dimensions = batchTexture._textureDimensions;
return dimensions.x * dimensions.y * 4;
}
function getBatchValues(batchTexture) {
if (!defined_default(batchTexture._batchValues)) {
const byteLength = getByteLength(batchTexture);
const bytes = new Uint8Array(byteLength).fill(255);
batchTexture._batchValues = bytes;
}
return batchTexture._batchValues;
}
function getShowAlphaProperties(batchTexture) {
if (!defined_default(batchTexture._showAlphaProperties)) {
const byteLength = 2 * batchTexture._featuresLength;
const bytes = new Uint8Array(byteLength).fill(255);
batchTexture._showAlphaProperties = bytes;
}
return batchTexture._showAlphaProperties;
}
function checkBatchId(batchId, featuresLength) {
if (!defined_default(batchId) || batchId < 0 || batchId >= featuresLength) {
throw new DeveloperError_default(
`batchId is required and between zero and featuresLength - 1 (${featuresLength}` - +")."
);
}
}
BatchTexture.prototype.setShow = function(batchId, show) {
checkBatchId(batchId, this._featuresLength);
Check_default.typeOf.bool("show", show);
if (show && !defined_default(this._showAlphaProperties)) {
return;
}
const showAlphaProperties = getShowAlphaProperties(this);
const propertyOffset = batchId * 2;
const newShow = show ? 255 : 0;
if (showAlphaProperties[propertyOffset] !== newShow) {
showAlphaProperties[propertyOffset] = newShow;
const batchValues = getBatchValues(this);
const offset = batchId * 4 + 3;
batchValues[offset] = show ? showAlphaProperties[propertyOffset + 1] : 0;
this._batchValuesDirty = true;
}
};
BatchTexture.prototype.setAllShow = function(show) {
Check_default.typeOf.bool("show", show);
const featuresLength = this._featuresLength;
for (let i = 0; i < featuresLength; ++i) {
this.setShow(i, show);
}
};
BatchTexture.prototype.getShow = function(batchId) {
checkBatchId(batchId, this._featuresLength);
if (!defined_default(this._showAlphaProperties)) {
return true;
}
const offset = batchId * 2;
return this._showAlphaProperties[offset] === 255;
};
var scratchColorBytes = new Array(4);
BatchTexture.prototype.setColor = function(batchId, color) {
checkBatchId(batchId, this._featuresLength);
Check_default.typeOf.object("color", color);
if (Color_default.equals(color, BatchTexture.DEFAULT_COLOR_VALUE) && !defined_default(this._batchValues)) {
return;
}
const newColor = color.toBytes(scratchColorBytes);
const newAlpha = newColor[3];
const batchValues = getBatchValues(this);
const offset = batchId * 4;
const showAlphaProperties = getShowAlphaProperties(this);
const propertyOffset = batchId * 2;
if (batchValues[offset] !== newColor[0] || batchValues[offset + 1] !== newColor[1] || batchValues[offset + 2] !== newColor[2] || showAlphaProperties[propertyOffset + 1] !== newAlpha) {
batchValues[offset] = newColor[0];
batchValues[offset + 1] = newColor[1];
batchValues[offset + 2] = newColor[2];
const wasTranslucent = showAlphaProperties[propertyOffset + 1] !== 255;
const show = showAlphaProperties[propertyOffset] !== 0;
batchValues[offset + 3] = show ? newAlpha : 0;
showAlphaProperties[propertyOffset + 1] = newAlpha;
const isTranslucent = newAlpha !== 255;
if (isTranslucent && !wasTranslucent) {
++this._translucentFeaturesLength;
} else if (!isTranslucent && wasTranslucent) {
--this._translucentFeaturesLength;
}
this._batchValuesDirty = true;
if (defined_default(this._colorChangedCallback)) {
this._colorChangedCallback(batchId, color);
}
}
};
BatchTexture.prototype.setAllColor = function(color) {
Check_default.typeOf.object("color", color);
const featuresLength = this._featuresLength;
for (let i = 0; i < featuresLength; ++i) {
this.setColor(i, color);
}
};
BatchTexture.prototype.getColor = function(batchId, result) {
checkBatchId(batchId, this._featuresLength);
Check_default.typeOf.object("result", result);
if (!defined_default(this._batchValues)) {
return Color_default.clone(BatchTexture.DEFAULT_COLOR_VALUE, result);
}
const batchValues = this._batchValues;
const offset = batchId * 4;
const showAlphaProperties = this._showAlphaProperties;
const propertyOffset = batchId * 2;
return Color_default.fromBytes(
batchValues[offset],
batchValues[offset + 1],
batchValues[offset + 2],
showAlphaProperties[propertyOffset + 1],
result
);
};
BatchTexture.prototype.getPickColor = function(batchId) {
checkBatchId(batchId, this._featuresLength);
return this._pickIds[batchId];
};
function createTexture2(batchTexture, context, bytes) {
const dimensions = batchTexture._textureDimensions;
return new Texture_default({
context,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
source: {
width: dimensions.x,
height: dimensions.y,
arrayBufferView: bytes
},
flipY: false,
sampler: Sampler_default.NEAREST
});
}
function createPickTexture(batchTexture, context) {
const featuresLength = batchTexture._featuresLength;
if (!defined_default(batchTexture._pickTexture) && featuresLength > 0) {
const pickIds = batchTexture._pickIds;
const byteLength = getByteLength(batchTexture);
const bytes = new Uint8Array(byteLength);
const owner = batchTexture._owner;
const statistics2 = batchTexture._statistics;
for (let i = 0; i < featuresLength; ++i) {
const pickId = context.createPickId(owner.getFeature(i));
pickIds.push(pickId);
const pickColor = pickId.color;
const offset = i * 4;
bytes[offset] = Color_default.floatToByte(pickColor.red);
bytes[offset + 1] = Color_default.floatToByte(pickColor.green);
bytes[offset + 2] = Color_default.floatToByte(pickColor.blue);
bytes[offset + 3] = Color_default.floatToByte(pickColor.alpha);
}
batchTexture._pickTexture = createTexture2(batchTexture, context, bytes);
if (defined_default(statistics2)) {
statistics2.batchTableByteLength += batchTexture._pickTexture.sizeInBytes;
}
}
}
function updateBatchTexture(batchTexture) {
const dimensions = batchTexture._textureDimensions;
batchTexture._batchTexture.copyFrom({
source: {
width: dimensions.x,
height: dimensions.y,
arrayBufferView: batchTexture._batchValues
}
});
}
BatchTexture.prototype.update = function(tileset, frameState) {
const context = frameState.context;
this._defaultTexture = context.defaultTexture;
const passes = frameState.passes;
if (passes.pick || passes.postProcess) {
createPickTexture(this, context);
}
if (this._batchValuesDirty) {
this._batchValuesDirty = false;
if (!defined_default(this._batchTexture)) {
this._batchTexture = createTexture2(this, context, this._batchValues);
if (defined_default(this._statistics)) {
this._statistics.batchTableByteLength += this._batchTexture.sizeInBytes;
}
}
updateBatchTexture(this);
}
};
BatchTexture.prototype.isDestroyed = function() {
return false;
};
BatchTexture.prototype.destroy = function() {
this._batchTexture = this._batchTexture && this._batchTexture.destroy();
this._pickTexture = this._pickTexture && this._pickTexture.destroy();
const pickIds = this._pickIds;
const length2 = pickIds.length;
for (let i = 0; i < length2; ++i) {
pickIds[i].destroy();
}
return destroyObject_default(this);
};
var BatchTexture_default = BatchTexture;
// packages/engine/Source/Scene/BatchTableHierarchy.js
var import_InlineWorkers440 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/getBinaryAccessor.js
var import_InlineWorkers439 = __toESM(require_InlineWorkers(), 1);
var ComponentsPerAttribute = {
SCALAR: 1,
VEC2: 2,
VEC3: 3,
VEC4: 4,
MAT2: 4,
MAT3: 9,
MAT4: 16
};
var ClassPerType = {
SCALAR: void 0,
VEC2: Cartesian2_default,
VEC3: Cartesian3_default,
VEC4: Cartesian4_default,
MAT2: Matrix2_default,
MAT3: Matrix3_default,
MAT4: Matrix4_default
};
function getBinaryAccessor(accessor) {
const componentType = accessor.componentType;
let componentDatatype;
if (typeof componentType === "string") {
componentDatatype = ComponentDatatype_default.fromName(componentType);
} else {
componentDatatype = componentType;
}
const componentsPerAttribute = ComponentsPerAttribute[accessor.type];
const classType = ClassPerType[accessor.type];
return {
componentsPerAttribute,
classType,
createArrayBufferView: function(buffer2, byteOffset, length2) {
return ComponentDatatype_default.createArrayBufferView(
componentDatatype,
buffer2,
byteOffset,
componentsPerAttribute * length2
);
}
};
}
var getBinaryAccessor_default = getBinaryAccessor;
// packages/engine/Source/Scene/BatchTableHierarchy.js
function BatchTableHierarchy(options) {
this._classes = void 0;
this._classIds = void 0;
this._classIndexes = void 0;
this._parentCounts = void 0;
this._parentIndexes = void 0;
this._parentIds = void 0;
this._byteLength = 0;
Check_default.typeOf.object("options.extension", options.extension);
initialize3(this, options.extension, options.binaryBody);
validateHierarchy(this);
}
Object.defineProperties(BatchTableHierarchy.prototype, {
byteLength: {
get: function() {
return this._byteLength;
}
}
});
function initialize3(hierarchy, hierarchyJson, binaryBody) {
let i;
let classId;
let binaryAccessor;
const instancesLength = hierarchyJson.instancesLength;
const classes = hierarchyJson.classes;
let classIds = hierarchyJson.classIds;
let parentCounts = hierarchyJson.parentCounts;
let parentIds = hierarchyJson.parentIds;
let parentIdsLength = instancesLength;
let byteLength = 0;
if (defined_default(classIds.byteOffset)) {
classIds.componentType = classIds.componentType ?? ComponentDatatype_default.UNSIGNED_SHORT;
classIds.type = AttributeType_default.SCALAR;
binaryAccessor = getBinaryAccessor_default(classIds);
classIds = binaryAccessor.createArrayBufferView(
binaryBody.buffer,
binaryBody.byteOffset + classIds.byteOffset,
instancesLength
);
byteLength += classIds.byteLength;
}
let parentIndexes;
if (defined_default(parentCounts)) {
if (defined_default(parentCounts.byteOffset)) {
parentCounts.componentType = parentCounts.componentType ?? ComponentDatatype_default.UNSIGNED_SHORT;
parentCounts.type = AttributeType_default.SCALAR;
binaryAccessor = getBinaryAccessor_default(parentCounts);
parentCounts = binaryAccessor.createArrayBufferView(
binaryBody.buffer,
binaryBody.byteOffset + parentCounts.byteOffset,
instancesLength
);
byteLength += parentCounts.byteLength;
}
parentIndexes = new Uint16Array(instancesLength);
parentIdsLength = 0;
for (i = 0; i < instancesLength; ++i) {
parentIndexes[i] = parentIdsLength;
parentIdsLength += parentCounts[i];
}
byteLength += parentIndexes.byteLength;
}
if (defined_default(parentIds) && defined_default(parentIds.byteOffset)) {
parentIds.componentType = parentIds.componentType ?? ComponentDatatype_default.UNSIGNED_SHORT;
parentIds.type = AttributeType_default.SCALAR;
binaryAccessor = getBinaryAccessor_default(parentIds);
parentIds = binaryAccessor.createArrayBufferView(
binaryBody.buffer,
binaryBody.byteOffset + parentIds.byteOffset,
parentIdsLength
);
byteLength += parentIds.byteLength;
}
const classesLength = classes.length;
for (i = 0; i < classesLength; ++i) {
const classInstancesLength = classes[i].length;
const properties = classes[i].instances;
const binaryProperties = getBinaryProperties(
classInstancesLength,
properties,
binaryBody
);
byteLength += countBinaryPropertyMemory(binaryProperties);
classes[i].instances = combine_default(binaryProperties, properties);
}
const classCounts = new Array(classesLength).fill(0);
const classIndexes = new Uint16Array(instancesLength);
for (i = 0; i < instancesLength; ++i) {
classId = classIds[i];
classIndexes[i] = classCounts[classId];
++classCounts[classId];
}
byteLength += classIndexes.byteLength;
hierarchy._classes = classes;
hierarchy._classIds = classIds;
hierarchy._classIndexes = classIndexes;
hierarchy._parentCounts = parentCounts;
hierarchy._parentIndexes = parentIndexes;
hierarchy._parentIds = parentIds;
hierarchy._byteLength = byteLength;
}
function getBinaryProperties(featuresLength, properties, binaryBody) {
let binaryProperties;
for (const name in properties) {
if (properties.hasOwnProperty(name)) {
const property = properties[name];
const byteOffset = property.byteOffset;
if (defined_default(byteOffset)) {
const componentType = property.componentType;
const type = property.type;
if (!defined_default(componentType)) {
throw new RuntimeError_default("componentType is required.");
}
if (!defined_default(type)) {
throw new RuntimeError_default("type is required.");
}
if (!defined_default(binaryBody)) {
throw new RuntimeError_default(
`Property ${name} requires a batch table binary.`
);
}
const binaryAccessor = getBinaryAccessor_default(property);
const componentCount = binaryAccessor.componentsPerAttribute;
const classType = binaryAccessor.classType;
const typedArray = binaryAccessor.createArrayBufferView(
binaryBody.buffer,
binaryBody.byteOffset + byteOffset,
featuresLength
);
if (!defined_default(binaryProperties)) {
binaryProperties = {};
}
binaryProperties[name] = {
typedArray,
componentCount,
type: classType
};
}
}
}
return binaryProperties;
}
function countBinaryPropertyMemory(binaryProperties) {
let byteLength = 0;
for (const name in binaryProperties) {
if (binaryProperties.hasOwnProperty(name)) {
byteLength += binaryProperties[name].typedArray.byteLength;
}
}
return byteLength;
}
var scratchValidateStack = [];
function validateHierarchy(hierarchy) {
const stack = scratchValidateStack;
stack.length = 0;
const classIds = hierarchy._classIds;
const instancesLength = classIds.length;
for (let i = 0; i < instancesLength; ++i) {
validateInstance(hierarchy, i, stack);
}
}
function validateInstance(hierarchy, instanceIndex, stack) {
const parentCounts = hierarchy._parentCounts;
const parentIds = hierarchy._parentIds;
const parentIndexes = hierarchy._parentIndexes;
const classIds = hierarchy._classIds;
const instancesLength = classIds.length;
if (!defined_default(parentIds)) {
return;
}
if (instanceIndex >= instancesLength) {
throw new DeveloperError_default(
`Parent index ${instanceIndex} exceeds the total number of instances: ${instancesLength}`
);
}
if (stack.indexOf(instanceIndex) > -1) {
throw new DeveloperError_default(
"Circular dependency detected in the batch table hierarchy."
);
}
stack.push(instanceIndex);
const parentCount = defined_default(parentCounts) ? parentCounts[instanceIndex] : 1;
const parentIndex = defined_default(parentCounts) ? parentIndexes[instanceIndex] : instanceIndex;
for (let i = 0; i < parentCount; ++i) {
const parentId = parentIds[parentIndex + i];
if (parentId !== instanceIndex) {
validateInstance(hierarchy, parentId, stack);
}
}
stack.pop(instanceIndex);
}
var scratchVisited = [];
var scratchStack = [];
var marker = 0;
function traverseHierarchyMultipleParents(hierarchy, instanceIndex, endConditionCallback) {
const classIds = hierarchy._classIds;
const parentCounts = hierarchy._parentCounts;
const parentIds = hierarchy._parentIds;
const parentIndexes = hierarchy._parentIndexes;
const instancesLength = classIds.length;
const visited = scratchVisited;
visited.length = Math.max(visited.length, instancesLength);
const visitedMarker = ++marker;
const stack = scratchStack;
stack.length = 0;
stack.push(instanceIndex);
while (stack.length > 0) {
instanceIndex = stack.pop();
if (visited[instanceIndex] === visitedMarker) {
continue;
}
visited[instanceIndex] = visitedMarker;
const result = endConditionCallback(hierarchy, instanceIndex);
if (defined_default(result)) {
return result;
}
const parentCount = parentCounts[instanceIndex];
const parentIndex = parentIndexes[instanceIndex];
for (let i = 0; i < parentCount; ++i) {
const parentId = parentIds[parentIndex + i];
if (parentId !== instanceIndex) {
stack.push(parentId);
}
}
}
}
function traverseHierarchySingleParent(hierarchy, instanceIndex, endConditionCallback) {
let hasParent = true;
while (hasParent) {
const result = endConditionCallback(hierarchy, instanceIndex);
if (defined_default(result)) {
return result;
}
const parentId = hierarchy._parentIds[instanceIndex];
hasParent = parentId !== instanceIndex;
instanceIndex = parentId;
}
}
function traverseHierarchy(hierarchy, instanceIndex, endConditionCallback) {
const parentCounts = hierarchy._parentCounts;
const parentIds = hierarchy._parentIds;
if (!defined_default(parentIds)) {
return endConditionCallback(hierarchy, instanceIndex);
} else if (defined_default(parentCounts)) {
return traverseHierarchyMultipleParents(
hierarchy,
instanceIndex,
endConditionCallback
);
}
return traverseHierarchySingleParent(
hierarchy,
instanceIndex,
endConditionCallback
);
}
BatchTableHierarchy.prototype.hasProperty = function(batchId, propertyId) {
const result = traverseHierarchy(
this,
batchId,
function(hierarchy, instanceIndex) {
const classId = hierarchy._classIds[instanceIndex];
const instances = hierarchy._classes[classId].instances;
if (defined_default(instances[propertyId])) {
return true;
}
}
);
return defined_default(result);
};
BatchTableHierarchy.prototype.propertyExists = function(propertyId) {
const classes = this._classes;
const classesLength = classes.length;
for (let i = 0; i < classesLength; ++i) {
const instances = classes[i].instances;
if (defined_default(instances[propertyId])) {
return true;
}
}
return false;
};
BatchTableHierarchy.prototype.getPropertyIds = function(batchId, results) {
results = defined_default(results) ? results : [];
results.length = 0;
traverseHierarchy(this, batchId, function(hierarchy, instanceIndex) {
const classId = hierarchy._classIds[instanceIndex];
const instances = hierarchy._classes[classId].instances;
for (const name in instances) {
if (instances.hasOwnProperty(name)) {
if (results.indexOf(name) === -1) {
results.push(name);
}
}
}
});
return results;
};
BatchTableHierarchy.prototype.getProperty = function(batchId, propertyId) {
return traverseHierarchy(this, batchId, function(hierarchy, instanceIndex) {
const classId = hierarchy._classIds[instanceIndex];
const instanceClass = hierarchy._classes[classId];
const indexInClass = hierarchy._classIndexes[instanceIndex];
const propertyValues = instanceClass.instances[propertyId];
if (defined_default(propertyValues)) {
if (defined_default(propertyValues.typedArray)) {
return getBinaryProperty(propertyValues, indexInClass);
}
return clone_default(propertyValues[indexInClass], true);
}
});
};
function getBinaryProperty(binaryProperty, index) {
const typedArray = binaryProperty.typedArray;
const componentCount = binaryProperty.componentCount;
if (componentCount === 1) {
return typedArray[index];
}
return binaryProperty.type.unpack(typedArray, index * componentCount);
}
BatchTableHierarchy.prototype.setProperty = function(batchId, propertyId, value) {
const result = traverseHierarchy(
this,
batchId,
function(hierarchy, instanceIndex) {
const classId = hierarchy._classIds[instanceIndex];
const instanceClass = hierarchy._classes[classId];
const indexInClass = hierarchy._classIndexes[instanceIndex];
const propertyValues = instanceClass.instances[propertyId];
if (defined_default(propertyValues)) {
if (instanceIndex !== batchId) {
throw new DeveloperError_default(
`Inherited property "${propertyId}" is read-only.`
);
}
if (defined_default(propertyValues.typedArray)) {
setBinaryProperty(propertyValues, indexInClass, value);
} else {
propertyValues[indexInClass] = clone_default(value, true);
}
return true;
}
}
);
return defined_default(result);
};
function setBinaryProperty(binaryProperty, index, value) {
const typedArray = binaryProperty.typedArray;
const componentCount = binaryProperty.componentCount;
if (componentCount === 1) {
typedArray[index] = value;
} else {
binaryProperty.type.pack(value, typedArray, index * componentCount);
}
}
BatchTableHierarchy.prototype.isClass = function(batchId, className) {
const result = traverseHierarchy(
this,
batchId,
function(hierarchy, instanceIndex) {
const classId = hierarchy._classIds[instanceIndex];
const instanceClass = hierarchy._classes[classId];
if (instanceClass.name === className) {
return true;
}
}
);
return defined_default(result);
};
BatchTableHierarchy.prototype.getClassName = function(batchId) {
const classId = this._classIds[batchId];
const instanceClass = this._classes[classId];
return instanceClass.name;
};
var BatchTableHierarchy_default = BatchTableHierarchy;
// packages/engine/Source/Scene/Cesium3DTileColorBlendMode.js
var import_InlineWorkers441 = __toESM(require_InlineWorkers(), 1);
var Cesium3DTileColorBlendMode = {
/**
* Multiplies the source color by the feature color.
*
* @type {number}
* @constant
*/
HIGHLIGHT: 0,
/**
* Replaces the source color with the feature color.
*
* @type {number}
* @constant
*/
REPLACE: 1,
/**
* Blends the source color and feature color together.
*
* @type {number}
* @constant
*/
MIX: 2
};
var Cesium3DTileColorBlendMode_default = Object.freeze(Cesium3DTileColorBlendMode);
// packages/engine/Source/Scene/Cesium3DTileBatchTable.js
var DEFAULT_COLOR_VALUE = BatchTexture_default.DEFAULT_COLOR_VALUE;
var DEFAULT_SHOW_VALUE = BatchTexture_default.DEFAULT_SHOW_VALUE;
function Cesium3DTileBatchTable(content, featuresLength, batchTableJson, batchTableBinary, colorChangedCallback) {
this.featuresLength = featuresLength;
let extensions;
if (defined_default(batchTableJson)) {
extensions = batchTableJson.extensions;
}
this._extensions = extensions ?? {};
const properties = initializeProperties(batchTableJson);
this._properties = properties;
this._batchTableHierarchy = initializeHierarchy(
this,
batchTableJson,
batchTableBinary
);
const binaryProperties = getBinaryProperties2(
featuresLength,
properties,
batchTableBinary
);
this._binaryPropertiesByteLength = countBinaryPropertyMemory2(binaryProperties);
this._batchTableBinaryProperties = binaryProperties;
this._content = content;
this._batchTexture = new BatchTexture_default({
featuresLength,
colorChangedCallback,
owner: content,
statistics: content.tileset.statistics
});
}
Cesium3DTileBatchTable._deprecationWarning = deprecationWarning_default;
Object.defineProperties(Cesium3DTileBatchTable.prototype, {
/**
* Size of the batch table, including the batch table hierarchy's binary
* buffers and any binary properties. JSON data is not counted.
*
* @memberof Cesium3DTileBatchTable.prototype
* @type {number}
* @readonly
* @private
*/
batchTableByteLength: {
get: function() {
let totalByteLength = this._binaryPropertiesByteLength;
if (defined_default(this._batchTableHierarchy)) {
totalByteLength += this._batchTableHierarchy.byteLength;
}
totalByteLength += this._batchTexture.byteLength;
return totalByteLength;
}
}
});
function initializeProperties(jsonHeader) {
const properties = {};
if (!defined_default(jsonHeader)) {
return properties;
}
for (const propertyName in jsonHeader) {
if (jsonHeader.hasOwnProperty(propertyName) && propertyName !== "HIERARCHY" && // Deprecated HIERARCHY property
propertyName !== "extensions" && propertyName !== "extras") {
properties[propertyName] = clone_default(jsonHeader[propertyName], true);
}
}
return properties;
}
function initializeHierarchy(batchTable, jsonHeader, binaryBody) {
if (!defined_default(jsonHeader)) {
return;
}
let hierarchy = batchTable._extensions["3DTILES_batch_table_hierarchy"];
const legacyHierarchy = jsonHeader.HIERARCHY;
if (defined_default(legacyHierarchy)) {
Cesium3DTileBatchTable._deprecationWarning(
"batchTableHierarchyExtension",
"The batch table HIERARCHY property has been moved to an extension. Use extensions.3DTILES_batch_table_hierarchy instead."
);
batchTable._extensions["3DTILES_batch_table_hierarchy"] = legacyHierarchy;
hierarchy = legacyHierarchy;
}
if (!defined_default(hierarchy)) {
return;
}
return new BatchTableHierarchy_default({
extension: hierarchy,
binaryBody
});
}
function getBinaryProperties2(featuresLength, properties, binaryBody) {
let binaryProperties;
for (const name in properties) {
if (properties.hasOwnProperty(name)) {
const property = properties[name];
const byteOffset = property.byteOffset;
if (defined_default(byteOffset)) {
const componentType = property.componentType;
const type = property.type;
if (!defined_default(componentType)) {
throw new RuntimeError_default("componentType is required.");
}
if (!defined_default(type)) {
throw new RuntimeError_default("type is required.");
}
if (!defined_default(binaryBody)) {
throw new RuntimeError_default(
`Property ${name} requires a batch table binary.`
);
}
const binaryAccessor = getBinaryAccessor_default(property);
const componentCount = binaryAccessor.componentsPerAttribute;
const classType = binaryAccessor.classType;
const typedArray = binaryAccessor.createArrayBufferView(
binaryBody.buffer,
binaryBody.byteOffset + byteOffset,
featuresLength
);
if (!defined_default(binaryProperties)) {
binaryProperties = {};
}
binaryProperties[name] = {
typedArray,
componentCount,
type: classType
};
}
}
}
return binaryProperties;
}
function countBinaryPropertyMemory2(binaryProperties) {
if (!defined_default(binaryProperties)) {
return 0;
}
let byteLength = 0;
for (const name in binaryProperties) {
if (binaryProperties.hasOwnProperty(name)) {
byteLength += binaryProperties[name].typedArray.byteLength;
}
}
return byteLength;
}
Cesium3DTileBatchTable.getBinaryProperties = function(featuresLength, batchTableJson, batchTableBinary) {
return getBinaryProperties2(featuresLength, batchTableJson, batchTableBinary);
};
Cesium3DTileBatchTable.prototype.setShow = function(batchId, show) {
this._batchTexture.setShow(batchId, show);
};
Cesium3DTileBatchTable.prototype.setAllShow = function(show) {
this._batchTexture.setAllShow(show);
};
Cesium3DTileBatchTable.prototype.getShow = function(batchId) {
return this._batchTexture.getShow(batchId);
};
Cesium3DTileBatchTable.prototype.setColor = function(batchId, color) {
this._batchTexture.setColor(batchId, color);
};
Cesium3DTileBatchTable.prototype.setAllColor = function(color) {
this._batchTexture.setAllColor(color);
};
Cesium3DTileBatchTable.prototype.getColor = function(batchId, result) {
return this._batchTexture.getColor(batchId, result);
};
Cesium3DTileBatchTable.prototype.getPickColor = function(batchId) {
return this._batchTexture.getPickColor(batchId);
};
var scratchColor2 = new Color_default();
Cesium3DTileBatchTable.prototype.applyStyle = function(style) {
if (!defined_default(style)) {
this.setAllColor(DEFAULT_COLOR_VALUE);
this.setAllShow(DEFAULT_SHOW_VALUE);
return;
}
const content = this._content;
const length2 = this.featuresLength;
for (let i = 0; i < length2; ++i) {
const feature2 = content.getFeature(i);
const color = defined_default(style.color) ? style.color.evaluateColor(feature2, scratchColor2) ?? DEFAULT_COLOR_VALUE : DEFAULT_COLOR_VALUE;
const show = defined_default(style.show) ? style.show.evaluate(feature2) ?? DEFAULT_SHOW_VALUE : DEFAULT_SHOW_VALUE;
this.setColor(i, color);
this.setShow(i, show);
}
};
function getBinaryProperty2(binaryProperty, index) {
const typedArray = binaryProperty.typedArray;
const componentCount = binaryProperty.componentCount;
if (componentCount === 1) {
return typedArray[index];
}
return binaryProperty.type.unpack(typedArray, index * componentCount);
}
function setBinaryProperty2(binaryProperty, index, value) {
const typedArray = binaryProperty.typedArray;
const componentCount = binaryProperty.componentCount;
if (componentCount === 1) {
typedArray[index] = value;
} else {
binaryProperty.type.pack(value, typedArray, index * componentCount);
}
}
function checkBatchId2(batchId, featuresLength) {
if (!defined_default(batchId) || batchId < 0 || batchId >= featuresLength) {
throw new DeveloperError_default(
`batchId is required and must be between zero and featuresLength - 1 (${featuresLength}` - +")."
);
}
}
Cesium3DTileBatchTable.prototype.isClass = function(batchId, className) {
checkBatchId2(batchId, this.featuresLength);
Check_default.typeOf.string("className", className);
const hierarchy = this._batchTableHierarchy;
if (!defined_default(hierarchy)) {
return false;
}
return hierarchy.isClass(batchId, className);
};
Cesium3DTileBatchTable.prototype.isExactClass = function(batchId, className) {
Check_default.typeOf.string("className", className);
return this.getExactClassName(batchId) === className;
};
Cesium3DTileBatchTable.prototype.getExactClassName = function(batchId) {
checkBatchId2(batchId, this.featuresLength);
const hierarchy = this._batchTableHierarchy;
if (!defined_default(hierarchy)) {
return void 0;
}
return hierarchy.getClassName(batchId);
};
Cesium3DTileBatchTable.prototype.hasProperty = function(batchId, name) {
checkBatchId2(batchId, this.featuresLength);
Check_default.typeOf.string("name", name);
return defined_default(this._properties[name]) || defined_default(this._batchTableHierarchy) && this._batchTableHierarchy.hasProperty(batchId, name);
};
Cesium3DTileBatchTable.prototype.hasPropertyBySemantic = function() {
return false;
};
Cesium3DTileBatchTable.prototype.getPropertyIds = function(batchId, results) {
checkBatchId2(batchId, this.featuresLength);
results = defined_default(results) ? results : [];
results.length = 0;
const scratchPropertyIds = Object.keys(this._properties);
addAllToArray_default(results, scratchPropertyIds);
if (defined_default(this._batchTableHierarchy)) {
const propertyIds = this._batchTableHierarchy.getPropertyIds(
batchId,
scratchPropertyIds
);
addAllToArray_default(results, propertyIds);
}
return results;
};
Cesium3DTileBatchTable.prototype.getPropertyBySemantic = function(batchId, name) {
return void 0;
};
Cesium3DTileBatchTable.prototype.getProperty = function(batchId, name) {
checkBatchId2(batchId, this.featuresLength);
Check_default.typeOf.string("name", name);
if (defined_default(this._batchTableBinaryProperties)) {
const binaryProperty = this._batchTableBinaryProperties[name];
if (defined_default(binaryProperty)) {
return getBinaryProperty2(binaryProperty, batchId);
}
}
const propertyValues = this._properties[name];
if (defined_default(propertyValues)) {
return clone_default(propertyValues[batchId], true);
}
if (defined_default(this._batchTableHierarchy)) {
const hierarchyProperty = this._batchTableHierarchy.getProperty(
batchId,
name
);
if (defined_default(hierarchyProperty)) {
return hierarchyProperty;
}
}
return void 0;
};
Cesium3DTileBatchTable.prototype.setProperty = function(batchId, name, value) {
const featuresLength = this.featuresLength;
checkBatchId2(batchId, featuresLength);
Check_default.typeOf.string("name", name);
if (defined_default(this._batchTableBinaryProperties)) {
const binaryProperty = this._batchTableBinaryProperties[name];
if (defined_default(binaryProperty)) {
setBinaryProperty2(binaryProperty, batchId, value);
return;
}
}
if (defined_default(this._batchTableHierarchy)) {
if (this._batchTableHierarchy.setProperty(batchId, name, value)) {
return;
}
}
let propertyValues = this._properties[name];
if (!defined_default(propertyValues)) {
this._properties[name] = new Array(featuresLength);
propertyValues = this._properties[name];
}
propertyValues[batchId] = clone_default(value, true);
};
function getGlslComputeSt2(batchTable) {
if (batchTable._batchTexture.textureDimensions.y === 1) {
return "uniform vec4 tile_textureStep; \nvec2 computeSt(float batchId) \n{ \n float stepX = tile_textureStep.x; \n float centerX = tile_textureStep.y; \n return vec2(centerX + (batchId * stepX), 0.5); \n} \n";
}
return "uniform vec4 tile_textureStep; \nuniform vec2 tile_textureDimensions; \nvec2 computeSt(float batchId) \n{ \n float stepX = tile_textureStep.x; \n float centerX = tile_textureStep.y; \n float stepY = tile_textureStep.z; \n float centerY = tile_textureStep.w; \n float xId = mod(batchId, tile_textureDimensions.x); \n float yId = floor(batchId / tile_textureDimensions.x); \n return vec2(centerX + (xId * stepX), centerY + (yId * stepY)); \n} \n";
}
Cesium3DTileBatchTable.prototype.getVertexShaderCallback = function(handleTranslucent, batchIdAttributeName, diffuseAttributeOrUniformName) {
if (this.featuresLength === 0) {
return;
}
const that = this;
return function(source) {
const renamedSource = modifyDiffuse(
source,
diffuseAttributeOrUniformName,
false
);
let newMain;
if (ContextLimits_default.maximumVertexTextureImageUnits > 0) {
newMain = "";
if (handleTranslucent) {
newMain += "uniform bool tile_translucentCommand; \n";
}
newMain += `${"uniform sampler2D tile_batchTexture; \nout vec4 tile_featureColor; \nout vec2 tile_featureSt; \nvoid main() \n{ \n vec2 st = computeSt("}${batchIdAttributeName});
vec4 featureProperties = texture(tile_batchTexture, st);
tile_color(featureProperties);
float show = ceil(featureProperties.a);
gl_Position *= show;
`;
if (handleTranslucent) {
newMain += " bool isStyleTranslucent = (featureProperties.a != 1.0); \n if (czm_pass == czm_passTranslucent) \n { \n if (!isStyleTranslucent && !tile_translucentCommand) \n { \n gl_Position *= 0.0; \n } \n } \n else \n { \n if (isStyleTranslucent) \n { \n gl_Position *= 0.0; \n } \n } \n";
}
newMain += " tile_featureColor = featureProperties; \n tile_featureSt = st; \n}";
} else {
newMain = `${"out vec2 tile_featureSt; \nvoid main() \n{ \n tile_color(vec4(1.0)); \n tile_featureSt = computeSt("}${batchIdAttributeName});
}`;
}
return `${renamedSource}
${getGlslComputeSt2(that)}${newMain}`;
};
};
function getDefaultShader(source, applyHighlight) {
source = ShaderSource_default.replaceMain(source, "tile_main");
if (!applyHighlight) {
return `${source}void tile_color(vec4 tile_featureColor)
{
tile_main();
}
`;
}
return `${source}uniform float tile_colorBlend;
void tile_color(vec4 tile_featureColor)
{
tile_main();
tile_featureColor = czm_gammaCorrect(tile_featureColor);
out_FragColor.a *= tile_featureColor.a;
float highlight = ceil(tile_colorBlend);
out_FragColor.rgb *= mix(tile_featureColor.rgb, vec3(1.0), highlight);
}
`;
}
function replaceDiffuseTextureCalls(source, diffuseAttributeOrUniformName) {
const functionCall = `texture(${diffuseAttributeOrUniformName}`;
let fromIndex = 0;
let startIndex = source.indexOf(functionCall, fromIndex);
let endIndex;
while (startIndex > -1) {
let nestedLevel = 0;
for (let i = startIndex; i < source.length; ++i) {
const character = source.charAt(i);
if (character === "(") {
++nestedLevel;
} else if (character === ")") {
--nestedLevel;
if (nestedLevel === 0) {
endIndex = i + 1;
break;
}
}
}
const extractedFunction = source.slice(startIndex, endIndex);
const replacedFunction = `tile_diffuse_final(${extractedFunction}, tile_diffuse)`;
source = source.slice(0, startIndex) + replacedFunction + source.slice(endIndex);
fromIndex = startIndex + replacedFunction.length;
startIndex = source.indexOf(functionCall, fromIndex);
}
return source;
}
function modifyDiffuse(source, diffuseAttributeOrUniformName, applyHighlight) {
if (!defined_default(diffuseAttributeOrUniformName)) {
return getDefaultShader(source, applyHighlight);
}
let regex = new RegExp(
`(uniform|attribute|in)\\s+(vec[34]|sampler2D)\\s+${diffuseAttributeOrUniformName};`
);
const uniformMatch = source.match(regex);
if (!defined_default(uniformMatch)) {
return getDefaultShader(source, applyHighlight);
}
const declaration = uniformMatch[0];
const type = uniformMatch[2];
source = ShaderSource_default.replaceMain(source, "tile_main");
source = source.replace(declaration, "");
const finalDiffuseFunction = "bool isWhite(vec3 color) \n{ \n return all(greaterThan(color, vec3(1.0 - czm_epsilon3))); \n} \nvec4 tile_diffuse_final(vec4 sourceDiffuse, vec4 tileDiffuse) \n{ \n vec4 blendDiffuse = mix(sourceDiffuse, tileDiffuse, tile_colorBlend); \n vec4 diffuse = isWhite(tileDiffuse.rgb) ? sourceDiffuse : blendDiffuse; \n return vec4(diffuse.rgb, sourceDiffuse.a); \n} \n";
const highlight = " tile_featureColor = czm_gammaCorrect(tile_featureColor); \n out_FragColor.a *= tile_featureColor.a; \n float highlight = ceil(tile_colorBlend); \n out_FragColor.rgb *= mix(tile_featureColor.rgb, vec3(1.0), highlight); \n";
let setColor;
if (type === "vec3" || type === "vec4") {
const sourceDiffuse = type === "vec3" ? `vec4(${diffuseAttributeOrUniformName}, 1.0)` : diffuseAttributeOrUniformName;
const replaceDiffuse = type === "vec3" ? "tile_diffuse.xyz" : "tile_diffuse";
regex = new RegExp(diffuseAttributeOrUniformName, "g");
source = source.replace(regex, replaceDiffuse);
setColor = ` vec4 source = ${sourceDiffuse};
tile_diffuse = tile_diffuse_final(source, tile_featureColor);
tile_main();
`;
} else if (type === "sampler2D") {
source = replaceDiffuseTextureCalls(source, diffuseAttributeOrUniformName);
setColor = " tile_diffuse = tile_featureColor; \n tile_main(); \n";
}
source = `${"uniform float tile_colorBlend; \nvec4 tile_diffuse = vec4(1.0); \n"}${finalDiffuseFunction}${declaration}
${source}
void tile_color(vec4 tile_featureColor)
{
${setColor}`;
if (applyHighlight) {
source += highlight;
}
source += "} \n";
return source;
}
Cesium3DTileBatchTable.prototype.getFragmentShaderCallback = function(handleTranslucent, diffuseAttributeOrUniformName, hasPremultipliedAlpha) {
if (this.featuresLength === 0) {
return;
}
return function(source) {
source = modifyDiffuse(source, diffuseAttributeOrUniformName, true);
if (ContextLimits_default.maximumVertexTextureImageUnits > 0) {
source += "uniform sampler2D tile_pickTexture; \nin vec2 tile_featureSt; \nin vec4 tile_featureColor; \nvoid main() \n{ \n tile_color(tile_featureColor); \n";
if (hasPremultipliedAlpha) {
source += " out_FragColor.rgb *= out_FragColor.a; \n";
}
source += "}";
} else {
if (handleTranslucent) {
source += "uniform bool tile_translucentCommand; \n";
}
source += "uniform sampler2D tile_pickTexture; \nuniform sampler2D tile_batchTexture; \nin vec2 tile_featureSt; \nvoid main() \n{ \n vec4 featureProperties = texture(tile_batchTexture, tile_featureSt); \n if (featureProperties.a == 0.0) { \n discard; \n } \n";
if (handleTranslucent) {
source += " bool isStyleTranslucent = (featureProperties.a != 1.0); \n if (czm_pass == czm_passTranslucent) \n { \n if (!isStyleTranslucent && !tile_translucentCommand) \n { \n discard; \n } \n } \n else \n { \n if (isStyleTranslucent) \n { \n discard; \n } \n } \n";
}
source += " tile_color(featureProperties); \n";
if (hasPremultipliedAlpha) {
source += " out_FragColor.rgb *= out_FragColor.a; \n";
}
source += "} \n";
}
return source;
};
};
function getColorBlend(batchTable) {
const tileset = batchTable._content.tileset;
const colorBlendMode = tileset.colorBlendMode;
const colorBlendAmount = tileset.colorBlendAmount;
if (colorBlendMode === Cesium3DTileColorBlendMode_default.HIGHLIGHT) {
return 0;
}
if (colorBlendMode === Cesium3DTileColorBlendMode_default.REPLACE) {
return 1;
}
if (colorBlendMode === Cesium3DTileColorBlendMode_default.MIX) {
return Math_default.clamp(colorBlendAmount, Math_default.EPSILON4, 1);
}
throw new DeveloperError_default(`Invalid color blend mode "${colorBlendMode}".`);
}
Cesium3DTileBatchTable.prototype.getUniformMapCallback = function() {
if (this.featuresLength === 0) {
return;
}
const that = this;
return function(uniformMap2) {
const batchUniformMap = {
tile_batchTexture: function() {
return that._batchTexture.batchTexture ?? that._batchTexture.defaultTexture;
},
tile_textureDimensions: function() {
return that._batchTexture.textureDimensions;
},
tile_textureStep: function() {
return that._batchTexture.textureStep;
},
tile_colorBlend: function() {
return getColorBlend(that);
},
tile_pickTexture: function() {
return that._batchTexture.pickTexture;
}
};
return combine_default(uniformMap2, batchUniformMap);
};
};
Cesium3DTileBatchTable.prototype.getPickId = function() {
return "texture(tile_pickTexture, tile_featureSt)";
};
var StyleCommandsNeeded = {
ALL_OPAQUE: 0,
ALL_TRANSLUCENT: 1,
OPAQUE_AND_TRANSLUCENT: 2
};
Cesium3DTileBatchTable.prototype.addDerivedCommands = function(frameState, commandStart) {
const commandList = frameState.commandList;
const commandEnd = commandList.length;
const tile = this._content._tile;
const finalResolution = tile._finalResolution;
const tileset = tile.tileset;
const bivariateVisibilityTest = tileset.isSkippingLevelOfDetail && tileset.hasMixedContent && frameState.context.stencilBuffer;
const styleCommandsNeeded = getStyleCommandsNeeded(this);
for (let i = commandStart; i < commandEnd; ++i) {
const command = commandList[i];
if (command.pass === Pass_default.COMPUTE) {
continue;
}
let derivedCommands = command.derivedCommands.tileset;
if (!defined_default(derivedCommands) || command.dirty) {
derivedCommands = {};
command.derivedCommands.tileset = derivedCommands;
derivedCommands.originalCommand = deriveCommand(command);
command.dirty = false;
}
const originalCommand = derivedCommands.originalCommand;
if (styleCommandsNeeded !== StyleCommandsNeeded.ALL_OPAQUE && command.pass !== Pass_default.TRANSLUCENT) {
if (!defined_default(derivedCommands.translucent)) {
derivedCommands.translucent = deriveTranslucentCommand(originalCommand);
}
}
if (styleCommandsNeeded !== StyleCommandsNeeded.ALL_TRANSLUCENT && command.pass !== Pass_default.TRANSLUCENT) {
if (!defined_default(derivedCommands.opaque)) {
derivedCommands.opaque = deriveOpaqueCommand(originalCommand);
}
if (bivariateVisibilityTest) {
if (!finalResolution) {
if (!defined_default(derivedCommands.zback)) {
derivedCommands.zback = deriveZBackfaceCommand(
frameState.context,
originalCommand
);
}
tileset._backfaceCommands.push(derivedCommands.zback);
}
if (!defined_default(derivedCommands.stencil) || tile._selectionDepth !== getLastSelectionDepth(derivedCommands.stencil)) {
if (command.renderState.depthMask) {
derivedCommands.stencil = deriveStencilCommand(
originalCommand,
tile._selectionDepth
);
} else {
derivedCommands.stencil = derivedCommands.opaque;
}
}
}
}
const opaqueCommand = bivariateVisibilityTest ? derivedCommands.stencil : derivedCommands.opaque;
const translucentCommand = derivedCommands.translucent;
if (command.pass !== Pass_default.TRANSLUCENT) {
if (styleCommandsNeeded === StyleCommandsNeeded.ALL_OPAQUE) {
commandList[i] = opaqueCommand;
}
if (styleCommandsNeeded === StyleCommandsNeeded.ALL_TRANSLUCENT) {
commandList[i] = translucentCommand;
}
if (styleCommandsNeeded === StyleCommandsNeeded.OPAQUE_AND_TRANSLUCENT) {
commandList[i] = opaqueCommand;
commandList.push(translucentCommand);
}
} else {
commandList[i] = originalCommand;
}
}
};
function getStyleCommandsNeeded(batchTable) {
const translucentFeaturesLength = batchTable._batchTexture.translucentFeaturesLength;
if (translucentFeaturesLength === 0) {
return StyleCommandsNeeded.ALL_OPAQUE;
} else if (translucentFeaturesLength === batchTable.featuresLength) {
return StyleCommandsNeeded.ALL_TRANSLUCENT;
}
return StyleCommandsNeeded.OPAQUE_AND_TRANSLUCENT;
}
function deriveCommand(command) {
const derivedCommand = DrawCommand_default.shallowClone(command);
const translucentCommand = derivedCommand.pass === Pass_default.TRANSLUCENT;
derivedCommand.uniformMap = defined_default(derivedCommand.uniformMap) ? derivedCommand.uniformMap : {};
derivedCommand.uniformMap.tile_translucentCommand = function() {
return translucentCommand;
};
return derivedCommand;
}
function deriveTranslucentCommand(command) {
const derivedCommand = DrawCommand_default.shallowClone(command);
derivedCommand.pass = Pass_default.TRANSLUCENT;
derivedCommand.renderState = getTranslucentRenderState(command.renderState);
return derivedCommand;
}
function deriveOpaqueCommand(command) {
const derivedCommand = DrawCommand_default.shallowClone(command);
derivedCommand.renderState = getOpaqueRenderState(command.renderState);
return derivedCommand;
}
function getLogDepthPolygonOffsetFragmentShaderProgram(context, shaderProgram) {
let shader = context.shaderCache.getDerivedShaderProgram(
shaderProgram,
"zBackfaceLogDepth"
);
if (!defined_default(shader)) {
const fs = shaderProgram.fragmentShaderSource.clone();
fs.defines = defined_default(fs.defines) ? fs.defines.slice(0) : [];
fs.defines.push("POLYGON_OFFSET");
shader = context.shaderCache.createDerivedShaderProgram(
shaderProgram,
"zBackfaceLogDepth",
{
vertexShaderSource: shaderProgram.vertexShaderSource,
fragmentShaderSource: fs,
attributeLocations: shaderProgram._attributeLocations
}
);
}
return shader;
}
function deriveZBackfaceCommand(context, command) {
const derivedCommand = DrawCommand_default.shallowClone(command);
const rs = clone_default(derivedCommand.renderState, true);
rs.cull.enabled = true;
rs.cull.face = CullFace_default.FRONT;
rs.colorMask = {
red: false,
green: false,
blue: false,
alpha: false
};
rs.polygonOffset = {
enabled: true,
factor: 5,
units: 5
};
rs.stencilTest = StencilConstants_default.setCesium3DTileBit();
rs.stencilMask = StencilConstants_default.CESIUM_3D_TILE_MASK;
derivedCommand.renderState = RenderState_default.fromCache(rs);
derivedCommand.castShadows = false;
derivedCommand.receiveShadows = false;
derivedCommand.uniformMap = clone_default(command.uniformMap);
const polygonOffset = new Cartesian2_default(5, 5);
derivedCommand.uniformMap.u_polygonOffset = function() {
return polygonOffset;
};
derivedCommand.shaderProgram = getLogDepthPolygonOffsetFragmentShaderProgram(
context,
command.shaderProgram
);
return derivedCommand;
}
function deriveStencilCommand(command, reference) {
const derivedCommand = DrawCommand_default.shallowClone(command);
const rs = clone_default(derivedCommand.renderState, true);
rs.stencilTest.enabled = true;
rs.stencilTest.mask = StencilConstants_default.SKIP_LOD_MASK;
rs.stencilTest.reference = StencilConstants_default.CESIUM_3D_TILE_MASK | reference << StencilConstants_default.SKIP_LOD_BIT_SHIFT;
rs.stencilTest.frontFunction = StencilFunction_default.GREATER_OR_EQUAL;
rs.stencilTest.frontOperation.zPass = StencilOperation_default.REPLACE;
rs.stencilTest.backFunction = StencilFunction_default.GREATER_OR_EQUAL;
rs.stencilTest.backOperation.zPass = StencilOperation_default.REPLACE;
rs.stencilMask = StencilConstants_default.CESIUM_3D_TILE_MASK | StencilConstants_default.SKIP_LOD_MASK;
derivedCommand.renderState = RenderState_default.fromCache(rs);
return derivedCommand;
}
function getLastSelectionDepth(stencilCommand) {
const reference = stencilCommand.renderState.stencilTest.reference;
return (reference & StencilConstants_default.SKIP_LOD_MASK) >>> StencilConstants_default.SKIP_LOD_BIT_SHIFT;
}
function getTranslucentRenderState(renderState) {
const rs = clone_default(renderState, true);
rs.cull.enabled = false;
rs.depthTest.enabled = true;
rs.depthMask = false;
rs.blending = BlendingState_default.ALPHA_BLEND;
rs.stencilTest = StencilConstants_default.setCesium3DTileBit();
rs.stencilMask = StencilConstants_default.CESIUM_3D_TILE_MASK;
return RenderState_default.fromCache(rs);
}
function getOpaqueRenderState(renderState) {
const rs = clone_default(renderState, true);
rs.stencilTest = StencilConstants_default.setCesium3DTileBit();
rs.stencilMask = StencilConstants_default.CESIUM_3D_TILE_MASK;
return RenderState_default.fromCache(rs);
}
Cesium3DTileBatchTable.prototype.update = function(tileset, frameState) {
this._batchTexture.update(tileset, frameState);
};
Cesium3DTileBatchTable.prototype.isDestroyed = function() {
return false;
};
Cesium3DTileBatchTable.prototype.destroy = function() {
this._batchTexture = this._batchTexture && this._batchTexture.destroy();
return destroyObject_default(this);
};
var Cesium3DTileBatchTable_default = Cesium3DTileBatchTable;
// packages/engine/Source/Scene/Vector3DTileGeometry.js
var import_InlineWorkers450 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Vector3DTileBatch.js
var import_InlineWorkers443 = __toESM(require_InlineWorkers(), 1);
function Vector3DTileBatch(options) {
this.offset = options.offset;
this.count = options.count;
this.color = options.color;
this.batchIds = options.batchIds;
}
var Vector3DTileBatch_default = Vector3DTileBatch;
// packages/engine/Source/Scene/Vector3DTilePrimitive.js
var import_InlineWorkers449 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/VectorTileVS.js
var import_InlineWorkers444 = __toESM(require_InlineWorkers(), 1);
var VectorTileVS_default = "in vec3 position;\nin float a_batchId;\n\nuniform mat4 u_modifiedModelViewProjection;\n\nvoid main()\n{\n gl_Position = czm_depthClamp(u_modifiedModelViewProjection * vec4(position, 1.0));\n}\n";
// packages/engine/Source/Scene/Cesium3DTileFeature.js
var import_InlineWorkers445 = __toESM(require_InlineWorkers(), 1);
function Cesium3DTileFeature(content, batchId) {
this._content = content;
this._batchId = batchId;
this._color = void 0;
}
Object.defineProperties(Cesium3DTileFeature.prototype, {
/**
* Gets or sets if the feature will be shown. This is set for all features
* when a style's show is evaluated.
*
* @memberof Cesium3DTileFeature.prototype
*
* @type {boolean}
*
* @default true
*/
show: {
get: function() {
return this._content.batchTable.getShow(this._batchId);
},
set: function(value) {
this._content.batchTable.setShow(this._batchId, value);
}
},
/**
* Gets or sets the highlight color multiplied with the feature's color. When
* this is white, the feature's color is not changed. This is set for all features
* when a style's color is evaluated.
*
* @memberof Cesium3DTileFeature.prototype
*
* @type {Color}
*
* @default {@link Color.WHITE}
*/
color: {
get: function() {
if (!defined_default(this._color)) {
this._color = new Color_default();
}
return this._content.batchTable.getColor(this._batchId, this._color);
},
set: function(value) {
this._content.batchTable.setColor(this._batchId, value);
}
},
/**
* Gets a typed array containing the ECEF positions of the polyline.
* Returns undefined if {@link Cesium3DTileset#vectorKeepDecodedPositions} is false
* or the feature is not a polyline in a vector tile.
*
* @memberof Cesium3DTileFeature.prototype
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @type {Float64Array}
*/
polylinePositions: {
get: function() {
if (!defined_default(this._content.getPolylinePositions)) {
return void 0;
}
return this._content.getPolylinePositions(this._batchId);
}
},
/**
* Gets the content of the tile containing the feature.
*
* @memberof Cesium3DTileFeature.prototype
*
* @type {Cesium3DTileContent}
*
* @readonly
* @private
*/
content: {
get: function() {
return this._content;
}
},
/**
* Gets the tileset containing the feature.
*
* @memberof Cesium3DTileFeature.prototype
*
* @type {Cesium3DTileset}
*
* @readonly
*/
tileset: {
get: function() {
return this._content.tileset;
}
},
/**
* All objects returned by {@link Scene#pick} have a primitive property. This returns
* the tileset containing the feature.
*
* @memberof Cesium3DTileFeature.prototype
*
* @type {Cesium3DTileset}
*
* @readonly
*/
primitive: {
get: function() {
return this._content.tileset;
}
},
/**
* Get the feature ID associated with this feature. For 3D Tiles 1.0, the
* batch ID is returned. For EXT_mesh_features, this is the feature ID from
* the selected feature ID set.
*
* @memberof Cesium3DTileFeature.prototype
*
* @type {number}
*
* @readonly
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
featureId: {
get: function() {
return this._batchId;
}
},
/**
* @private
*/
pickId: {
get: function() {
return this._content.batchTable.getPickColor(this._batchId);
}
}
});
Cesium3DTileFeature.prototype.hasProperty = function(name) {
return this._content.batchTable.hasProperty(this._batchId, name);
};
Cesium3DTileFeature.prototype.getPropertyIds = function(results) {
return this._content.batchTable.getPropertyIds(this._batchId, results);
};
Cesium3DTileFeature.prototype.getProperty = function(name) {
return this._content.batchTable.getProperty(this._batchId, name);
};
Cesium3DTileFeature.getPropertyInherited = function(content, batchId, name) {
const batchTable = content.batchTable;
if (defined_default(batchTable)) {
if (batchTable.hasPropertyBySemantic(batchId, name)) {
return batchTable.getPropertyBySemantic(batchId, name);
}
if (batchTable.hasProperty(batchId, name)) {
return batchTable.getProperty(batchId, name);
}
}
const contentMetadata = content.metadata;
if (defined_default(contentMetadata)) {
if (contentMetadata.hasPropertyBySemantic(name)) {
return contentMetadata.getPropertyBySemantic(name);
}
if (contentMetadata.hasProperty(name)) {
return contentMetadata.getProperty(name);
}
}
const tile = content.tile;
const tileMetadata = tile.metadata;
if (defined_default(tileMetadata)) {
if (tileMetadata.hasPropertyBySemantic(name)) {
return tileMetadata.getPropertyBySemantic(name);
}
if (tileMetadata.hasProperty(name)) {
return tileMetadata.getProperty(name);
}
}
let subtreeMetadata;
if (defined_default(tile.implicitSubtree)) {
subtreeMetadata = tile.implicitSubtree.metadata;
}
if (defined_default(subtreeMetadata)) {
if (subtreeMetadata.hasPropertyBySemantic(name)) {
return subtreeMetadata.getPropertyBySemantic(name);
}
if (subtreeMetadata.hasProperty(name)) {
return subtreeMetadata.getProperty(name);
}
}
const groupMetadata = defined_default(content.group) ? content.group.metadata : void 0;
if (defined_default(groupMetadata)) {
if (groupMetadata.hasPropertyBySemantic(name)) {
return groupMetadata.getPropertyBySemantic(name);
}
if (groupMetadata.hasProperty(name)) {
return groupMetadata.getProperty(name);
}
}
const tilesetMetadata = content.tileset.metadata;
if (defined_default(tilesetMetadata)) {
if (tilesetMetadata.hasPropertyBySemantic(name)) {
return tilesetMetadata.getPropertyBySemantic(name);
}
if (tilesetMetadata.hasProperty(name)) {
return tilesetMetadata.getProperty(name);
}
}
return void 0;
};
Cesium3DTileFeature.prototype.getPropertyInherited = function(name) {
return Cesium3DTileFeature.getPropertyInherited(
this._content,
this._batchId,
name
);
};
Cesium3DTileFeature.prototype.setProperty = function(name, value) {
this._content.batchTable.setProperty(this._batchId, name, value);
this._content.featurePropertiesDirty = true;
};
Cesium3DTileFeature.prototype.isExactClass = function(className) {
return this._content.batchTable.isExactClass(this._batchId, className);
};
Cesium3DTileFeature.prototype.isClass = function(className) {
return this._content.batchTable.isClass(this._batchId, className);
};
Cesium3DTileFeature.prototype.getExactClassName = function() {
return this._content.batchTable.getExactClassName(this._batchId);
};
var Cesium3DTileFeature_default = Cesium3DTileFeature;
// packages/engine/Source/Scene/Expression.js
var import_InlineWorkers448 = __toESM(require_InlineWorkers(), 1);
// node_modules/jsep/dist/jsep.js
var import_InlineWorkers446 = __toESM(require_InlineWorkers(), 1);
var Hooks = class {
/**
* @callback HookCallback
* @this {*|Jsep} this
* @param {Jsep} env
* @returns: void
*/
/**
* Adds the given callback to the list of callbacks for the given hook.
*
* The callback will be invoked when the hook it is registered for is run.
*
* One callback function can be registered to multiple hooks and the same hook multiple times.
*
* @param {string|object} name The name of the hook, or an object of callbacks keyed by name
* @param {HookCallback|boolean} callback The callback function which is given environment variables.
* @param {?boolean} [first=false] Will add the hook to the top of the list (defaults to the bottom)
* @public
*/
add(name, callback, first) {
if (typeof arguments[0] != "string") {
for (let name2 in arguments[0]) {
this.add(name2, arguments[0][name2], arguments[1]);
}
} else {
(Array.isArray(name) ? name : [name]).forEach(function(name2) {
this[name2] = this[name2] || [];
if (callback) {
this[name2][first ? "unshift" : "push"](callback);
}
}, this);
}
}
/**
* Runs a hook invoking all registered callbacks with the given environment variables.
*
* Callbacks will be invoked synchronously and in the order in which they were registered.
*
* @param {string} name The name of the hook.
* @param {Object1.
*
* @memberof ImplicitAvailabilityBitstream.prototype
*
* @type {number}
* @readonly
* @private
*/
availableCount: {
get: function() {
return this._availableCount;
}
}
});
ImplicitAvailabilityBitstream.prototype.getBit = function(index) {
if (index < 0 || index >= this._lengthBits) {
throw new DeveloperError_default("Bit index out of bounds.");
}
if (defined_default(this._constant)) {
return this._constant;
}
const byteIndex = index >> 3;
const bitIndex = index % 8;
return (this._bitstream[byteIndex] >> bitIndex & 1) === 1;
};
var ImplicitAvailabilityBitstream_default = ImplicitAvailabilityBitstream;
// packages/engine/Source/Scene/ImplicitMetadataView.js
var import_InlineWorkers456 = __toESM(require_InlineWorkers(), 1);
function ImplicitMetadataView(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const metadataTable = options.metadataTable;
const metadataClass = options.class;
const entityId = options.entityId;
const propertyTableJson = options.propertyTableJson;
Check_default.typeOf.object("options.metadataTable", metadataTable);
Check_default.typeOf.object("options.class", metadataClass);
Check_default.typeOf.number("options.entityId", entityId);
Check_default.typeOf.object("options.propertyTableJson", propertyTableJson);
this._class = metadataClass;
this._metadataTable = metadataTable;
this._entityId = entityId;
this._extensions = propertyTableJson.extensions;
this._extras = propertyTableJson.extras;
}
Object.defineProperties(ImplicitMetadataView.prototype, {
/**
* The class that properties conform to.
*
* @memberof ImplicitMetadataView.prototype
* @type {MetadataClass}
* @readonly
*/
class: {
get: function() {
return this._class;
}
},
/**
* Extra user-defined properties.
*
* @memberof ImplicitMetadataView.prototype
* @type {object}
* @readonly
*/
extras: {
get: function() {
return this._extras;
}
},
/**
* An object containing extensions.
*
* @memberof ImplicitMetadataView.prototype
* @type {object}
* @readonly
*/
extensions: {
get: function() {
return this._extensions;
}
}
});
ImplicitMetadataView.prototype.hasProperty = function(propertyId) {
return this._metadataTable.hasProperty(propertyId);
};
ImplicitMetadataView.prototype.hasPropertyBySemantic = function(semantic) {
return this._metadataTable.hasPropertyBySemantic(semantic);
};
ImplicitMetadataView.prototype.getPropertyIds = function(results) {
return this._metadataTable.getPropertyIds(results);
};
ImplicitMetadataView.prototype.getProperty = function(propertyId) {
return this._metadataTable.getProperty(this._entityId, propertyId);
};
ImplicitMetadataView.prototype.setProperty = function(propertyId, value) {
return this._metadataTable.setProperty(this._entityId, propertyId, value);
};
ImplicitMetadataView.prototype.getPropertyBySemantic = function(semantic) {
return this._metadataTable.getPropertyBySemantic(this._entityId, semantic);
};
ImplicitMetadataView.prototype.setPropertyBySemantic = function(semantic, value) {
return this._metadataTable.setPropertyBySemantic(
this._entityId,
semantic,
value
);
};
var ImplicitMetadataView_default = ImplicitMetadataView;
// packages/engine/Source/Scene/ImplicitSubdivisionScheme.js
var import_InlineWorkers457 = __toESM(require_InlineWorkers(), 1);
var ImplicitSubdivisionScheme = {
/**
* A quadtree divides a parent tile into four children, split at the midpoint
* of the x and y dimensions of the bounding box
* @type {string}
* @constant
* @private
*/
QUADTREE: "QUADTREE",
/**
* An octree divides a parent tile into eight children, split at the midpoint
* of the x, y, and z dimensions of the bounding box.
* @type {string}
* @constant
* @private
*/
OCTREE: "OCTREE"
};
ImplicitSubdivisionScheme.getBranchingFactor = function(subdivisionScheme) {
switch (subdivisionScheme) {
case ImplicitSubdivisionScheme.OCTREE:
return 8;
case ImplicitSubdivisionScheme.QUADTREE:
return 4;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("subdivisionScheme is not a valid value.");
}
};
var ImplicitSubdivisionScheme_default = Object.freeze(ImplicitSubdivisionScheme);
// packages/engine/Source/Scene/ImplicitSubtreeMetadata.js
var import_InlineWorkers459 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/MetadataEntity.js
var import_InlineWorkers458 = __toESM(require_InlineWorkers(), 1);
function MetadataEntity() {
}
Object.defineProperties(MetadataEntity.prototype, {
/**
* The class that properties conform to.
*
* @memberof MetadataEntity.prototype
* @type {MetadataClass}
* @readonly
* @private
*/
class: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
}
});
MetadataEntity.prototype.hasProperty = function(propertyId) {
DeveloperError_default.throwInstantiationError();
};
MetadataEntity.prototype.hasPropertyBySemantic = function(semantic) {
DeveloperError_default.throwInstantiationError();
};
MetadataEntity.prototype.getPropertyIds = function(results) {
DeveloperError_default.throwInstantiationError();
};
MetadataEntity.prototype.getProperty = function(propertyId) {
DeveloperError_default.throwInstantiationError();
};
MetadataEntity.prototype.setProperty = function(propertyId, value) {
DeveloperError_default.throwInstantiationError();
};
MetadataEntity.prototype.getPropertyBySemantic = function(semantic) {
DeveloperError_default.throwInstantiationError();
};
MetadataEntity.prototype.setPropertyBySemantic = function(semantic, value) {
DeveloperError_default.throwInstantiationError();
};
MetadataEntity.hasProperty = function(propertyId, properties, classDefinition) {
Check_default.typeOf.string("propertyId", propertyId);
Check_default.typeOf.object("properties", properties);
Check_default.typeOf.object("classDefinition", classDefinition);
if (defined_default(properties[propertyId])) {
return true;
}
const classProperties = classDefinition.properties;
if (!defined_default(classProperties)) {
return false;
}
const classProperty = classProperties[propertyId];
if (defined_default(classProperty) && defined_default(classProperty.default)) {
return true;
}
return false;
};
MetadataEntity.hasPropertyBySemantic = function(semantic, properties, classDefinition) {
Check_default.typeOf.string("semantic", semantic);
Check_default.typeOf.object("properties", properties);
Check_default.typeOf.object("classDefinition", classDefinition);
const propertiesBySemantic = classDefinition.propertiesBySemantic;
if (!defined_default(propertiesBySemantic)) {
return false;
}
const property = propertiesBySemantic[semantic];
return defined_default(property);
};
MetadataEntity.getPropertyIds = function(properties, classDefinition, results) {
Check_default.typeOf.object("properties", properties);
Check_default.typeOf.object("classDefinition", classDefinition);
results = defined_default(results) ? results : [];
results.length = 0;
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId) && defined_default(properties[propertyId])) {
results.push(propertyId);
}
}
const classProperties = classDefinition.properties;
if (defined_default(classProperties)) {
for (const classPropertyId in classProperties) {
if (classProperties.hasOwnProperty(classPropertyId) && !defined_default(properties[classPropertyId]) && defined_default(classProperties[classPropertyId].default)) {
results.push(classPropertyId);
}
}
}
return results;
};
MetadataEntity.getProperty = function(propertyId, properties, classDefinition) {
Check_default.typeOf.string("propertyId", propertyId);
Check_default.typeOf.object("properties", properties);
Check_default.typeOf.object("classDefinition", classDefinition);
if (!defined_default(classDefinition.properties[propertyId])) {
throw new DeveloperError_default(`Class definition missing property ${propertyId}`);
}
const classProperty = classDefinition.properties[propertyId];
let value = properties[propertyId];
if (Array.isArray(value)) {
value = value.slice();
}
const enableNestedArrays = true;
value = classProperty.handleNoData(value);
if (!defined_default(value) && defined_default(classProperty.default)) {
value = clone_default(classProperty.default, true);
return classProperty.unpackVectorAndMatrixTypes(value, enableNestedArrays);
}
if (!defined_default(value)) {
return void 0;
}
value = classProperty.normalize(value);
value = classProperty.applyValueTransform(value);
return classProperty.unpackVectorAndMatrixTypes(value, enableNestedArrays);
};
MetadataEntity.setProperty = function(propertyId, value, properties, classDefinition) {
Check_default.typeOf.string("propertyId", propertyId);
Check_default.defined("value", value);
Check_default.typeOf.object("properties", properties);
Check_default.typeOf.object("classDefinition", classDefinition);
if (!defined_default(properties[propertyId])) {
return false;
}
if (Array.isArray(value)) {
value = value.slice();
}
let classProperty;
const classProperties = classDefinition.properties;
if (defined_default(classProperties)) {
classProperty = classProperties[propertyId];
}
const enableNestedArrays = true;
if (defined_default(classProperty)) {
value = classProperty.packVectorAndMatrixTypes(value, enableNestedArrays);
value = classProperty.unapplyValueTransform(value);
value = classProperty.unnormalize(value);
}
properties[propertyId] = value;
return true;
};
MetadataEntity.getPropertyBySemantic = function(semantic, properties, classDefinition) {
Check_default.typeOf.string("semantic", semantic);
Check_default.typeOf.object("properties", properties);
Check_default.typeOf.object("classDefinition", classDefinition);
const propertiesBySemantic = classDefinition.propertiesBySemantic;
if (!defined_default(propertiesBySemantic)) {
return void 0;
}
const property = propertiesBySemantic[semantic];
if (defined_default(property)) {
return MetadataEntity.getProperty(property.id, properties, classDefinition);
}
return void 0;
};
MetadataEntity.setPropertyBySemantic = function(semantic, value, properties, classDefinition) {
Check_default.typeOf.string("semantic", semantic);
Check_default.defined("value", value);
Check_default.typeOf.object("properties", properties);
Check_default.typeOf.object("classDefinition", classDefinition);
const propertiesBySemantic = classDefinition.propertiesBySemantic;
if (!defined_default(propertiesBySemantic)) {
return false;
}
const property = classDefinition.propertiesBySemantic[semantic];
if (defined_default(property)) {
return MetadataEntity.setProperty(
property.id,
value,
properties,
classDefinition
);
}
return false;
};
var MetadataEntity_default = MetadataEntity;
// packages/engine/Source/Scene/ImplicitSubtreeMetadata.js
function ImplicitSubtreeMetadata(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const subtreeMetadata = options.subtreeMetadata;
const metadataClass = options.class;
Check_default.typeOf.object("options.subtreeMetadata", subtreeMetadata);
Check_default.typeOf.object("options.class", metadataClass);
const properties = defined_default(subtreeMetadata.properties) ? subtreeMetadata.properties : {};
this._class = metadataClass;
this._properties = properties;
this._extras = subtreeMetadata.extras;
this._extensions = subtreeMetadata.extensions;
}
Object.defineProperties(ImplicitSubtreeMetadata.prototype, {
/**
* The class that properties conform to.
*
* @memberof ImplicitSubtreeMetadata.prototype
* @type {MetadataClass}
* @readonly
* @private
*/
class: {
get: function() {
return this._class;
}
},
/**
* Extra user-defined properties.
*
* @memberof ImplicitSubtreeMetadata.prototype
* @type {object}
* @readonly
* @private
*/
extras: {
get: function() {
return this._extras;
}
},
/**
* An object containing extensions.
*
* @memberof ImplicitSubtreeMetadata.prototype
* @type {object}
* @readonly
* @private
*/
extensions: {
get: function() {
return this._extensions;
}
}
});
ImplicitSubtreeMetadata.prototype.hasProperty = function(propertyId) {
return MetadataEntity_default.hasProperty(propertyId, this._properties, this._class);
};
ImplicitSubtreeMetadata.prototype.hasPropertyBySemantic = function(semantic) {
return MetadataEntity_default.hasPropertyBySemantic(
semantic,
this._properties,
this._class
);
};
ImplicitSubtreeMetadata.prototype.getPropertyIds = function(results) {
return MetadataEntity_default.getPropertyIds(this._properties, this._class, results);
};
ImplicitSubtreeMetadata.prototype.getProperty = function(propertyId) {
return MetadataEntity_default.getProperty(propertyId, this._properties, this._class);
};
ImplicitSubtreeMetadata.prototype.setProperty = function(propertyId, value) {
return MetadataEntity_default.setProperty(
propertyId,
value,
this._properties,
this._class
);
};
ImplicitSubtreeMetadata.prototype.getPropertyBySemantic = function(semantic) {
return MetadataEntity_default.getPropertyBySemantic(
semantic,
this._properties,
this._class
);
};
ImplicitSubtreeMetadata.prototype.setPropertyBySemantic = function(semantic, value) {
return MetadataEntity_default.setPropertyBySemantic(
semantic,
value,
this._properties,
this._class
);
};
var ImplicitSubtreeMetadata_default = ImplicitSubtreeMetadata;
// packages/engine/Source/Scene/MetadataTable.js
var import_InlineWorkers464 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/MetadataTableProperty.js
var import_InlineWorkers463 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/MetadataComponentType.js
var import_InlineWorkers460 = __toESM(require_InlineWorkers(), 1);
var MetadataComponentType = {
/**
* An 8-bit signed integer
*
* @type {string}
* @constant
*/
INT8: "INT8",
/**
* An 8-bit unsigned integer
*
* @type {string}
* @constant
*/
UINT8: "UINT8",
/**
* A 16-bit signed integer
*
* @type {string}
* @constant
*/
INT16: "INT16",
/**
* A 16-bit unsigned integer
*
* @type {string}
* @constant
*/
UINT16: "UINT16",
/**
* A 32-bit signed integer
*
* @type {string}
* @constant
*/
INT32: "INT32",
/**
* A 32-bit unsigned integer
*
* @type {string}
* @constant
*/
UINT32: "UINT32",
/**
* A 64-bit signed integer. This type requires BigInt support.
*
* @see FeatureDetection.supportsBigInt
*
* @type {string}
* @constant
*/
INT64: "INT64",
/**
* A 64-bit signed integer. This type requires BigInt support
*
* @see FeatureDetection.supportsBigInt
*
* @type {string}
* @constant
*/
UINT64: "UINT64",
/**
* A 32-bit (single precision) floating point number
*
* @type {string}
* @constant
*/
FLOAT32: "FLOAT32",
/**
* A 64-bit (double precision) floating point number
*
* @type {string}
* @constant
*/
FLOAT64: "FLOAT64"
};
MetadataComponentType.getMinimum = function(type) {
Check_default.typeOf.string("type", type);
switch (type) {
case MetadataComponentType.INT8:
return -128;
case MetadataComponentType.UINT8:
return 0;
case MetadataComponentType.INT16:
return -32768;
case MetadataComponentType.UINT16:
return 0;
case MetadataComponentType.INT32:
return -2147483648;
case MetadataComponentType.UINT32:
return 0;
case MetadataComponentType.INT64:
if (FeatureDetection_default.supportsBigInt()) {
return BigInt("-9223372036854775808");
}
return -Math.pow(2, 63);
case MetadataComponentType.UINT64:
if (FeatureDetection_default.supportsBigInt()) {
return BigInt(0);
}
return 0;
case MetadataComponentType.FLOAT32:
return -34028234663852886e22;
case MetadataComponentType.FLOAT64:
return -Number.MAX_VALUE;
}
};
MetadataComponentType.getMaximum = function(type) {
Check_default.typeOf.string("type", type);
switch (type) {
case MetadataComponentType.INT8:
return 127;
case MetadataComponentType.UINT8:
return 255;
case MetadataComponentType.INT16:
return 32767;
case MetadataComponentType.UINT16:
return 65535;
case MetadataComponentType.INT32:
return 2147483647;
case MetadataComponentType.UINT32:
return 4294967295;
case MetadataComponentType.INT64:
if (FeatureDetection_default.supportsBigInt()) {
return BigInt("9223372036854775807");
}
return Math.pow(2, 63) - 1;
case MetadataComponentType.UINT64:
if (FeatureDetection_default.supportsBigInt()) {
return BigInt("18446744073709551615");
}
return Math.pow(2, 64) - 1;
case MetadataComponentType.FLOAT32:
return 34028234663852886e22;
case MetadataComponentType.FLOAT64:
return Number.MAX_VALUE;
}
};
MetadataComponentType.isIntegerType = function(type) {
Check_default.typeOf.string("type", type);
switch (type) {
case MetadataComponentType.INT8:
case MetadataComponentType.UINT8:
case MetadataComponentType.INT16:
case MetadataComponentType.UINT16:
case MetadataComponentType.INT32:
case MetadataComponentType.UINT32:
case MetadataComponentType.INT64:
case MetadataComponentType.UINT64:
return true;
default:
return false;
}
};
MetadataComponentType.isUnsignedIntegerType = function(type) {
Check_default.typeOf.string("type", type);
switch (type) {
case MetadataComponentType.UINT8:
case MetadataComponentType.UINT16:
case MetadataComponentType.UINT32:
case MetadataComponentType.UINT64:
return true;
default:
return false;
}
};
MetadataComponentType.isVectorCompatible = function(type) {
Check_default.typeOf.string("type", type);
switch (type) {
case MetadataComponentType.INT8:
case MetadataComponentType.UINT8:
case MetadataComponentType.INT16:
case MetadataComponentType.UINT16:
case MetadataComponentType.INT32:
case MetadataComponentType.UINT32:
case MetadataComponentType.FLOAT32:
case MetadataComponentType.FLOAT64:
return true;
default:
return false;
}
};
MetadataComponentType.normalize = function(value, type) {
if (typeof value !== "number" && typeof value !== "bigint") {
throw new DeveloperError_default("value must be a number or a BigInt");
}
if (!MetadataComponentType.isIntegerType(type)) {
throw new DeveloperError_default("type must be an integer type");
}
return Math.max(
Number(value) / Number(MetadataComponentType.getMaximum(type)),
-1
);
};
MetadataComponentType.unnormalize = function(value, type) {
Check_default.typeOf.number("value", value);
if (!MetadataComponentType.isIntegerType(type)) {
throw new DeveloperError_default("type must be an integer type");
}
const max3 = MetadataComponentType.getMaximum(type);
const min3 = MetadataComponentType.isUnsignedIntegerType(type) ? 0 : -max3;
value = Math_default.sign(value) * Math.round(Math.abs(value) * Number(max3));
if ((type === MetadataComponentType.INT64 || type === MetadataComponentType.UINT64) && FeatureDetection_default.supportsBigInt()) {
value = BigInt(value);
}
if (value > max3) {
return max3;
}
if (value < min3) {
return min3;
}
return value;
};
MetadataComponentType.applyValueTransform = function(value, offset, scale) {
return scale * value + offset;
};
MetadataComponentType.unapplyValueTransform = function(value, offset, scale) {
if (scale === 0) {
return 0;
}
return (value - offset) / scale;
};
MetadataComponentType.getSizeInBytes = function(type) {
Check_default.typeOf.string("type", type);
switch (type) {
case MetadataComponentType.INT8:
case MetadataComponentType.UINT8:
return 1;
case MetadataComponentType.INT16:
case MetadataComponentType.UINT16:
return 2;
case MetadataComponentType.INT32:
case MetadataComponentType.UINT32:
return 4;
case MetadataComponentType.INT64:
case MetadataComponentType.UINT64:
return 8;
case MetadataComponentType.FLOAT32:
return 4;
case MetadataComponentType.FLOAT64:
return 8;
}
};
MetadataComponentType.fromComponentDatatype = function(componentDatatype) {
Check_default.typeOf.number("componentDatatype", componentDatatype);
switch (componentDatatype) {
case ComponentDatatype_default.BYTE:
return MetadataComponentType.INT8;
case ComponentDatatype_default.UNSIGNED_BYTE:
return MetadataComponentType.UINT8;
case ComponentDatatype_default.SHORT:
return MetadataComponentType.INT16;
case ComponentDatatype_default.UNSIGNED_SHORT:
return MetadataComponentType.UINT16;
case ComponentDatatype_default.INT:
return MetadataComponentType.INT32;
case ComponentDatatype_default.UNSIGNED_INT:
return MetadataComponentType.UINT32;
case ComponentDatatype_default.FLOAT:
return MetadataComponentType.FLOAT32;
case ComponentDatatype_default.DOUBLE:
return MetadataComponentType.FLOAT64;
}
};
MetadataComponentType.toComponentDatatype = function(type) {
Check_default.typeOf.string("type", type);
switch (type) {
case MetadataComponentType.INT8:
return ComponentDatatype_default.BYTE;
case MetadataComponentType.UINT8:
return ComponentDatatype_default.UNSIGNED_BYTE;
case MetadataComponentType.INT16:
return ComponentDatatype_default.SHORT;
case MetadataComponentType.UINT16:
return ComponentDatatype_default.UNSIGNED_SHORT;
case MetadataComponentType.INT32:
return ComponentDatatype_default.INT;
case MetadataComponentType.UINT32:
return ComponentDatatype_default.UNSIGNED_INT;
case MetadataComponentType.FLOAT32:
return ComponentDatatype_default.FLOAT;
case MetadataComponentType.FLOAT64:
return ComponentDatatype_default.DOUBLE;
}
};
var MetadataComponentType_default = Object.freeze(MetadataComponentType);
// packages/engine/Source/Scene/MetadataClassProperty.js
var import_InlineWorkers462 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/MetadataType.js
var import_InlineWorkers461 = __toESM(require_InlineWorkers(), 1);
var MetadataType = {
/**
* A single component
*
* @type {string}
* @constant
*/
SCALAR: "SCALAR",
/**
* A vector with two components
*
* @type {string}
* @constant
*/
VEC2: "VEC2",
/**
* A vector with three components
*
* @type {string}
* @constant
*/
VEC3: "VEC3",
/**
* A vector with four components
*
* @type {string}
* @constant
*/
VEC4: "VEC4",
/**
* A 2x2 matrix, stored in column-major format.
*
* @type {string}
* @constant
*/
MAT2: "MAT2",
/**
* A 3x3 matrix, stored in column-major format.
*
* @type {string}
* @constant
*/
MAT3: "MAT3",
/**
* A 4x4 matrix, stored in column-major format.
*
* @type {string}
* @constant
*/
MAT4: "MAT4",
/**
* A boolean (true/false) value
*
* @type {string}
* @constant
*/
BOOLEAN: "BOOLEAN",
/**
* A UTF-8 encoded string value
*
* @type {string}
* @constant
*/
STRING: "STRING",
/**
* An enumerated value. This type is used in conjunction with a {@link MetadataEnum} to describe the valid values.
*
* @see MetadataEnum
*
* @type {string}
* @constant
*/
ENUM: "ENUM"
};
MetadataType.isVectorType = function(type) {
Check_default.typeOf.string("type", type);
switch (type) {
case MetadataType.VEC2:
case MetadataType.VEC3:
case MetadataType.VEC4:
return true;
default:
return false;
}
};
MetadataType.isMatrixType = function(type) {
Check_default.typeOf.string("type", type);
switch (type) {
case MetadataType.MAT2:
case MetadataType.MAT3:
case MetadataType.MAT4:
return true;
default:
return false;
}
};
MetadataType.getComponentCount = function(type) {
Check_default.typeOf.string("type", type);
switch (type) {
case MetadataType.SCALAR:
case MetadataType.STRING:
case MetadataType.ENUM:
case MetadataType.BOOLEAN:
return 1;
case MetadataType.VEC2:
return 2;
case MetadataType.VEC3:
return 3;
case MetadataType.VEC4:
return 4;
case MetadataType.MAT2:
return 4;
case MetadataType.MAT3:
return 9;
case MetadataType.MAT4:
return 16;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default(`Invalid metadata type ${type}`);
}
};
MetadataType.getMathType = function(type) {
switch (type) {
case MetadataType.VEC2:
return Cartesian2_default;
case MetadataType.VEC3:
return Cartesian3_default;
case MetadataType.VEC4:
return Cartesian4_default;
case MetadataType.MAT2:
return Matrix2_default;
case MetadataType.MAT3:
return Matrix3_default;
case MetadataType.MAT4:
return Matrix4_default;
default:
return void 0;
}
};
var MetadataType_default = Object.freeze(MetadataType);
// packages/engine/Source/Scene/MetadataClassProperty.js
function MetadataClassProperty(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const id = options.id;
const type = options.type;
Check_default.typeOf.string("options.id", id);
Check_default.typeOf.string("options.type", type);
const componentType = options.componentType;
const enumType = options.enumType;
const normalized = defined_default(componentType) && MetadataComponentType_default.isIntegerType(componentType) && (options.normalized ?? false);
this._id = id;
this._name = options.name;
this._description = options.description;
this._semantic = options.semantic;
this._isLegacyExtension = options.isLegacyExtension;
this._type = type;
this._componentType = componentType;
this._enumType = enumType;
this._valueType = defined_default(enumType) ? enumType.valueType : componentType;
this._isArray = options.isArray ?? false;
this._isVariableLengthArray = options.isVariableLengthArray ?? false;
this._arrayLength = options.arrayLength;
this._min = clone_default(options.min, true);
this._max = clone_default(options.max, true);
this._normalized = normalized;
let offset = clone_default(options.offset, true);
let scale = clone_default(options.scale, true);
const hasValueTransform = defined_default(offset) || defined_default(scale);
const enableNestedArrays = true;
if (!defined_default(offset)) {
offset = this.expandConstant(0, enableNestedArrays);
}
if (!defined_default(scale)) {
scale = this.expandConstant(1, enableNestedArrays);
}
this._offset = offset;
this._scale = scale;
this._hasValueTransform = hasValueTransform;
this._noData = clone_default(options.noData, true);
this._default = clone_default(options.default, true);
this._required = options.required ?? true;
this._extras = clone_default(options.extras, true);
this._extensions = clone_default(options.extensions, true);
}
MetadataClassProperty.fromJson = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const id = options.id;
const property = options.property;
Check_default.typeOf.string("options.id", id);
Check_default.typeOf.object("options.property", property);
Check_default.typeOf.string("options.property.type", property.type);
const isLegacyExtension = isLegacy(property);
const parsedType = parseType(property, options.enums);
let required;
if (!defined_default(isLegacyExtension)) {
required = false;
} else if (isLegacyExtension) {
required = defined_default(property.optional) ? !property.optional : true;
} else {
required = property.required ?? false;
}
return new MetadataClassProperty({
id,
type: parsedType.type,
componentType: parsedType.componentType,
enumType: parsedType.enumType,
isArray: parsedType.isArray,
isVariableLengthArray: parsedType.isVariableLengthArray,
arrayLength: parsedType.arrayLength,
normalized: property.normalized,
min: property.min,
max: property.max,
offset: property.offset,
scale: property.scale,
noData: property.noData,
default: property.default,
required,
name: property.name,
description: property.description,
semantic: property.semantic,
extras: property.extras,
extensions: property.extensions,
isLegacyExtension
});
};
Object.defineProperties(MetadataClassProperty.prototype, {
/**
* The ID of the property.
*
* @memberof MetadataClassProperty.prototype
* @type {string}
* @readonly
*/
id: {
get: function() {
return this._id;
}
},
/**
* The name of the property.
*
* @memberof MetadataClassProperty.prototype
* @type {string}
* @readonly
*/
name: {
get: function() {
return this._name;
}
},
/**
* The description of the property.
*
* @memberof MetadataClassProperty.prototype
* @type {string}
* @readonly
*/
description: {
get: function() {
return this._description;
}
},
/**
* The type of the property such as SCALAR, VEC2, VEC3
*
* @memberof MetadataClassProperty.prototype
* @type {MetadataType}
* @readonly
*/
type: {
get: function() {
return this._type;
}
},
/**
* The enum type of the property. Only defined when type is ENUM.
*
* @memberof MetadataClassProperty.prototype
* @type {MetadataEnum}
* @readonly
*/
enumType: {
get: function() {
return this._enumType;
}
},
/**
* The component type of the property. This includes integer
* (e.g. INT8 or UINT16), and floating point (FLOAT32 and FLOAT64) values
*
* @memberof MetadataClassProperty.prototype
* @type {MetadataComponentType}
* @readonly
*/
componentType: {
get: function() {
return this._componentType;
}
},
/**
* The datatype used for storing each component of the property. This
* is usually the same as componentType except for ENUM, where this
* returns an integer type
*
* @memberof MetadataClassProperty.prototype
* @type {MetadataComponentType}
* @readonly
* @private
*/
valueType: {
get: function() {
return this._valueType;
}
},
/**
* True if a property is an array (either fixed length or variable length),
* false otherwise.
*
* @memberof MetadataClassProperty.prototype
* @type {boolean}
* @readonly
*/
isArray: {
get: function() {
return this._isArray;
}
},
/**
* True if a property is a variable length array, false otherwise.
*
* @memberof MetadataClassProperty.prototype
* @type {boolean}
* @readonly
*/
isVariableLengthArray: {
get: function() {
return this._isVariableLengthArray;
}
},
/**
* The number of array elements. Only defined for fixed-size
* arrays.
*
* @memberof MetadataClassProperty.prototype
* @type {number}
* @readonly
*/
arrayLength: {
get: function() {
return this._arrayLength;
}
},
/**
* Whether the property is normalized.
*
* @memberof MetadataClassProperty.prototype
* @type {boolean}
* @readonly
*/
normalized: {
get: function() {
return this._normalized;
}
},
/**
* A number or an array of numbers storing the maximum allowable value of this property. Only defined when type is a numeric type.
*
* @memberof MetadataClassProperty.prototype
* @type {number|number[]|number[][]}
* @readonly
*/
max: {
get: function() {
return this._max;
}
},
/**
* A number or an array of numbers storing the minimum allowable value of this property. Only defined when type is a numeric type.
*
* @memberof MetadataClassProperty.prototype
* @type {number|number[]|number[][]}
* @readonly
*/
min: {
get: function() {
return this._min;
}
},
/**
* The no-data sentinel value that represents null values
*
* @memberof MetadataClassProperty.prototype
* @type {boolean|number|string|Array}
* @readonly
*/
noData: {
get: function() {
return this._noData;
}
},
/**
* A default value to use when an entity's property value is not defined.
*
* @memberof MetadataClassProperty.prototype
* @type {boolean|number|string|Array}
* @readonly
*/
default: {
get: function() {
return this._default;
}
},
/**
* Whether the property is required.
*
* @memberof MetadataClassProperty.prototype
* @type {boolean}
* @readonly
*/
required: {
get: function() {
return this._required;
}
},
/**
* An identifier that describes how this property should be interpreted.
*
* @memberof MetadataClassProperty.prototype
* @type {string}
* @readonly
*/
semantic: {
get: function() {
return this._semantic;
}
},
/**
* True if offset/scale should be applied. If both offset/scale were
* undefined, they default to identity so this property is set false
*
* @memberof MetadataClassProperty.prototype
* @type {boolean}
* @readonly
* @private
*/
hasValueTransform: {
get: function() {
return this._hasValueTransform;
}
},
/**
* The offset to be added to property values as part of the value transform.
*
* This is always defined, even when `hasValueTransform` is `false`. If
* the class property JSON itself did not define it, then it will be
* initialized to the default value.
*
* @memberof MetadataClassProperty.prototype
* @type {number|number[]|number[][]}
* @readonly
*/
offset: {
get: function() {
return this._offset;
}
},
/**
* The scale to be multiplied to property values as part of the value transform.
*
* This is always defined, even when `hasValueTransform` is `false`. If
* the class property JSON itself did not define it, then it will be
* initialized to the default value.
*
* @memberof MetadataClassProperty.prototype
* @type {number|number[]|number[][]}
* @readonly
*/
scale: {
get: function() {
return this._scale;
}
},
/**
* Extra user-defined properties.
*
* @memberof MetadataClassProperty.prototype
* @type {*}
* @readonly
*/
extras: {
get: function() {
return this._extras;
}
},
/**
* An object containing extensions.
*
* @memberof MetadataClassProperty.prototype
* @type {object}
* @readonly
*/
extensions: {
get: function() {
return this._extensions;
}
}
});
function isLegacy(property) {
if (property.type === "ARRAY") {
return true;
}
const type = property.type;
if (type === MetadataType_default.SCALAR || MetadataType_default.isMatrixType(type) || MetadataType_default.isVectorType(type)) {
return false;
}
if (defined_default(MetadataComponentType_default[type])) {
return true;
}
if (defined_default(property.noData) || defined_default(property.scale) || defined_default(property.offset) || defined_default(property.required) || defined_default(property.count) || defined_default(property.array)) {
return false;
}
if (defined_default(property.optional)) {
return false;
}
return void 0;
}
function parseType(property, enums) {
const type = property.type;
const componentType = property.componentType;
const isLegacyArray = type === "ARRAY";
let isArray;
let arrayLength;
let isVariableLengthArray;
if (isLegacyArray) {
isArray = true;
arrayLength = property.componentCount;
isVariableLengthArray = !defined_default(arrayLength);
} else if (property.array) {
isArray = true;
arrayLength = property.count;
isVariableLengthArray = !defined_default(property.count);
} else {
isArray = false;
arrayLength = void 0;
isVariableLengthArray = false;
}
let enumType;
if (defined_default(property.enumType)) {
enumType = enums[property.enumType];
}
if (type === MetadataType_default.ENUM) {
return {
type,
componentType: void 0,
enumType,
valueType: enumType.valueType,
isArray,
isVariableLengthArray,
arrayLength
};
}
if (isLegacyArray && componentType === MetadataType_default.ENUM) {
return {
type: componentType,
componentType: void 0,
enumType,
valueType: enumType.valueType,
isArray,
isVariableLengthArray,
arrayLength
};
}
if (type === MetadataType_default.SCALAR || MetadataType_default.isMatrixType(type) || MetadataType_default.isVectorType(type)) {
return {
type,
componentType,
enumType: void 0,
valueType: componentType,
isArray,
isVariableLengthArray,
arrayLength
};
}
if (type === MetadataType_default.BOOLEAN || type === MetadataType_default.STRING) {
return {
type,
componentType: void 0,
enumType: void 0,
valueType: void 0,
isArray,
isVariableLengthArray,
arrayLength
};
}
if (isLegacyArray && (componentType === MetadataType_default.BOOLEAN || componentType === MetadataType_default.STRING)) {
return {
type: componentType,
componentType: void 0,
enumType: void 0,
valueType: void 0,
isArray,
isVariableLengthArray,
arrayLength
};
}
if (defined_default(componentType) && defined_default(MetadataComponentType_default[componentType])) {
return {
type: MetadataType_default.SCALAR,
componentType,
enumType: void 0,
valueType: componentType,
isArray,
isVariableLengthArray,
arrayLength
};
}
if (defined_default(MetadataComponentType_default[type])) {
return {
type: MetadataType_default.SCALAR,
componentType: type,
enumType: void 0,
valueType: type,
isArray,
isVariableLengthArray,
arrayLength
};
}
throw new DeveloperError_default(
`unknown metadata type {type: ${type}, componentType: ${componentType})`
);
}
MetadataClassProperty.prototype.normalize = function(value) {
if (!this._normalized) {
return value;
}
return normalizeInPlace(
value,
this._valueType,
MetadataComponentType_default.normalize
);
};
MetadataClassProperty.prototype.unnormalize = function(value) {
if (!this._normalized) {
return value;
}
return normalizeInPlace(
value,
this._valueType,
MetadataComponentType_default.unnormalize
);
};
MetadataClassProperty.prototype.applyValueTransform = function(value) {
if (!this._hasValueTransform || this._isVariableLengthArray) {
return value;
}
return MetadataClassProperty.valueTransformInPlace(
value,
this._offset,
this._scale,
MetadataComponentType_default.applyValueTransform
);
};
MetadataClassProperty.prototype.unapplyValueTransform = function(value) {
if (!this._hasValueTransform || this._isVariableLengthArray) {
return value;
}
return MetadataClassProperty.valueTransformInPlace(
value,
this._offset,
this._scale,
MetadataComponentType_default.unapplyValueTransform
);
};
MetadataClassProperty.prototype.expandConstant = function(constant, enableNestedArrays) {
enableNestedArrays = enableNestedArrays ?? false;
const isArray = this._isArray;
const arrayLength = this._arrayLength;
const componentCount = MetadataType_default.getComponentCount(this._type);
const isNested = isArray && componentCount > 1;
if (!isArray && componentCount === 1) {
return constant;
}
if (!isArray) {
return new Array(componentCount).fill(constant);
}
if (!isNested) {
return new Array(arrayLength).fill(constant);
}
if (!enableNestedArrays) {
return new Array(this._arrayLength * componentCount).fill(constant);
}
const innerConstant = new Array(componentCount).fill(constant);
return new Array(this._arrayLength).fill(innerConstant);
};
MetadataClassProperty.prototype.handleNoData = function(value) {
const sentinel = this._noData;
if (!defined_default(sentinel)) {
return value;
}
if (arrayEquals(value, sentinel)) {
return void 0;
}
return value;
};
function arrayEquals(left, right) {
if (!Array.isArray(left)) {
return left === right;
}
if (!Array.isArray(right)) {
return false;
}
if (left.length !== right.length) {
return false;
}
for (let i = 0; i < left.length; i++) {
if (!arrayEquals(left[i], right[i])) {
return false;
}
}
return true;
}
MetadataClassProperty.prototype.unpackVectorAndMatrixTypes = function(value, enableNestedArrays) {
enableNestedArrays = enableNestedArrays ?? false;
const MathType = MetadataType_default.getMathType(this._type);
const isArray = this._isArray;
const componentCount = MetadataType_default.getComponentCount(this._type);
const isNested = isArray && componentCount > 1;
if (!defined_default(MathType)) {
return value;
}
if (enableNestedArrays && isNested) {
return value.map(function(x) {
return MathType.unpack(x);
});
}
if (isArray) {
return MathType.unpackArray(value);
}
return MathType.unpack(value);
};
MetadataClassProperty.prototype.packVectorAndMatrixTypes = function(value, enableNestedArrays) {
enableNestedArrays = enableNestedArrays ?? false;
const MathType = MetadataType_default.getMathType(this._type);
const isArray = this._isArray;
const componentCount = MetadataType_default.getComponentCount(this._type);
const isNested = isArray && componentCount > 1;
if (!defined_default(MathType)) {
return value;
}
if (enableNestedArrays && isNested) {
return value.map(function(x) {
return MathType.pack(x, []);
});
}
if (isArray) {
return MathType.packArray(value, []);
}
return MathType.pack(value, []);
};
MetadataClassProperty.prototype.validate = function(value) {
if (!defined_default(value) && defined_default(this._default)) {
return void 0;
}
if (this._required && !defined_default(value)) {
return `required property must have a value`;
}
if (this._isArray) {
return validateArray(this, value);
}
return validateSingleValue(this, value);
};
function validateArray(classProperty, value) {
if (!Array.isArray(value)) {
return `value ${value} must be an array`;
}
const length2 = value.length;
if (!classProperty._isVariableLengthArray && length2 !== classProperty._arrayLength) {
return "Array length does not match property.arrayLength";
}
for (let i = 0; i < length2; i++) {
const message = validateSingleValue(classProperty, value[i]);
if (defined_default(message)) {
return message;
}
}
}
function validateSingleValue(classProperty, value) {
const type = classProperty._type;
const componentType = classProperty._componentType;
const enumType = classProperty._enumType;
const normalized = classProperty._normalized;
if (MetadataType_default.isVectorType(type)) {
return validateVector(value, type, componentType);
} else if (MetadataType_default.isMatrixType(type)) {
return validateMatrix(value, type, componentType);
} else if (type === MetadataType_default.STRING) {
return validateString(value);
} else if (type === MetadataType_default.BOOLEAN) {
return validateBoolean(value);
} else if (type === MetadataType_default.ENUM) {
return validateEnum(value, enumType);
}
return validateScalar(value, componentType, normalized);
}
function validateVector(value, type, componentType) {
if (!MetadataComponentType_default.isVectorCompatible(componentType)) {
return `componentType ${componentType} is incompatible with vector type ${type}`;
}
if (type === MetadataType_default.VEC2 && !(value instanceof Cartesian2_default)) {
return `vector value ${value} must be a Cartesian2`;
}
if (type === MetadataType_default.VEC3 && !(value instanceof Cartesian3_default)) {
return `vector value ${value} must be a Cartesian3`;
}
if (type === MetadataType_default.VEC4 && !(value instanceof Cartesian4_default)) {
return `vector value ${value} must be a Cartesian4`;
}
}
function validateMatrix(value, type, componentType) {
if (!MetadataComponentType_default.isVectorCompatible(componentType)) {
return `componentType ${componentType} is incompatible with matrix type ${type}`;
}
if (type === MetadataType_default.MAT2 && !(value instanceof Matrix2_default)) {
return `matrix value ${value} must be a Matrix2`;
}
if (type === MetadataType_default.MAT3 && !(value instanceof Matrix3_default)) {
return `matrix value ${value} must be a Matrix3`;
}
if (type === MetadataType_default.MAT4 && !(value instanceof Matrix4_default)) {
return `matrix value ${value} must be a Matrix4`;
}
}
function validateString(value) {
if (typeof value !== "string") {
return getTypeErrorMessage(value, MetadataType_default.STRING);
}
}
function validateBoolean(value) {
if (typeof value !== "boolean") {
return getTypeErrorMessage(value, MetadataType_default.BOOLEAN);
}
}
function validateEnum(value, enumType) {
const javascriptType = typeof value;
if (defined_default(enumType)) {
if (javascriptType !== "string" || !defined_default(enumType.valuesByName[value])) {
return `value ${value} is not a valid enum name for ${enumType.id}`;
}
return;
}
}
function validateScalar(value, componentType, normalized) {
const javascriptType = typeof value;
switch (componentType) {
case MetadataComponentType_default.INT8:
case MetadataComponentType_default.UINT8:
case MetadataComponentType_default.INT16:
case MetadataComponentType_default.UINT16:
case MetadataComponentType_default.INT32:
case MetadataComponentType_default.UINT32:
case MetadataComponentType_default.FLOAT32:
case MetadataComponentType_default.FLOAT64:
if (javascriptType !== "number") {
return getTypeErrorMessage(value, componentType);
}
if (!isFinite(value)) {
return getNonFiniteErrorMessage(value, componentType);
}
return checkInRange(value, componentType, normalized);
case MetadataComponentType_default.INT64:
case MetadataComponentType_default.UINT64:
if (javascriptType !== "number" && javascriptType !== "bigint") {
return getTypeErrorMessage(value, componentType);
}
if (javascriptType === "number" && !isFinite(value)) {
return getNonFiniteErrorMessage(value, componentType);
}
return checkInRange(value, componentType, normalized);
}
}
function getTypeErrorMessage(value, type) {
return `value ${value} does not match type ${type}`;
}
function getOutOfRangeErrorMessage(value, type, normalized) {
let errorMessage = `value ${value} is out of range for type ${type}`;
if (normalized) {
errorMessage += " (normalized)";
}
return errorMessage;
}
function checkInRange(value, componentType, normalized) {
if (normalized) {
const min3 = MetadataComponentType_default.isUnsignedIntegerType(componentType) ? 0 : -1;
const max3 = 1;
if (value < min3 || value > max3) {
return getOutOfRangeErrorMessage(value, componentType, normalized);
}
return;
}
if (value < MetadataComponentType_default.getMinimum(componentType) || value > MetadataComponentType_default.getMaximum(componentType)) {
return getOutOfRangeErrorMessage(value, componentType, normalized);
}
}
function getNonFiniteErrorMessage(value, type) {
return `value ${value} of type ${type} must be finite`;
}
function normalizeInPlace(values, valueType, normalizeFunction) {
if (!Array.isArray(values)) {
return normalizeFunction(values, valueType);
}
for (let i = 0; i < values.length; i++) {
values[i] = normalizeInPlace(values[i], valueType, normalizeFunction);
}
return values;
}
MetadataClassProperty.valueTransformInPlace = function(values, offsets, scales, transformationFunction) {
if (!Array.isArray(values)) {
return transformationFunction(values, offsets, scales);
}
for (let i = 0; i < values.length; i++) {
values[i] = MetadataClassProperty.valueTransformInPlace(
values[i],
offsets[i],
scales[i],
transformationFunction
);
}
return values;
};
var MetadataClassProperty_default = MetadataClassProperty;
// packages/engine/Source/Scene/MetadataTableProperty.js
function MetadataTableProperty(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const count = options.count;
const property = options.property;
const classProperty = options.classProperty;
const bufferViews = options.bufferViews;
Check_default.typeOf.number.greaterThan("options.count", count, 0);
Check_default.typeOf.object("options.property", property);
Check_default.typeOf.object("options.classProperty", classProperty);
Check_default.typeOf.object("options.bufferViews", bufferViews);
const type = classProperty.type;
const isArray = classProperty.isArray;
const isVariableLengthArray = classProperty.isVariableLengthArray;
let valueType = classProperty.valueType;
const enumType = classProperty.enumType;
const hasStrings = type === MetadataType_default.STRING;
const hasBooleans = type === MetadataType_default.BOOLEAN;
let byteLength = 0;
let arrayOffsets;
if (isVariableLengthArray) {
let arrayOffsetType = property.arrayOffsetType ?? property.offsetType;
arrayOffsetType = MetadataComponentType_default[arrayOffsetType] ?? MetadataComponentType_default.UINT32;
const arrayOffsetBufferView = property.arrayOffsets ?? property.arrayOffsetBufferView;
arrayOffsets = new BufferView(
bufferViews[arrayOffsetBufferView],
arrayOffsetType,
count + 1
);
byteLength += arrayOffsets.typedArray.byteLength;
}
const vectorComponentCount = MetadataType_default.getComponentCount(type);
let arrayComponentCount;
if (isVariableLengthArray) {
arrayComponentCount = arrayOffsets.get(count) - arrayOffsets.get(0);
} else if (isArray) {
arrayComponentCount = count * classProperty.arrayLength;
} else {
arrayComponentCount = count;
}
const componentCount = vectorComponentCount * arrayComponentCount;
let stringOffsets;
if (hasStrings) {
let stringOffsetType = property.stringOffsetType ?? property.offsetType;
stringOffsetType = MetadataComponentType_default[stringOffsetType] ?? MetadataComponentType_default.UINT32;
const stringOffsetBufferView = property.stringOffsets ?? property.stringOffsetBufferView;
stringOffsets = new BufferView(
bufferViews[stringOffsetBufferView],
stringOffsetType,
componentCount + 1
);
byteLength += stringOffsets.typedArray.byteLength;
}
if (hasStrings || hasBooleans) {
valueType = MetadataComponentType_default.UINT8;
}
let valueCount;
if (hasStrings) {
valueCount = stringOffsets.get(componentCount) - stringOffsets.get(0);
} else if (hasBooleans) {
valueCount = Math.ceil(componentCount / 8);
} else {
valueCount = componentCount;
}
const valuesBufferView = property.values ?? property.bufferView;
const values = new BufferView(
bufferViews[valuesBufferView],
valueType,
valueCount
);
byteLength += values.typedArray.byteLength;
let offset = property.offset;
let scale = property.scale;
const hasValueTransform = classProperty.hasValueTransform || defined_default(offset) || defined_default(scale);
offset = offset ?? classProperty.offset;
scale = scale ?? classProperty.scale;
offset = flatten(offset);
scale = flatten(scale);
let getValueFunction;
let setValueFunction;
const that = this;
if (hasStrings) {
getValueFunction = function(index) {
return getString(index, that._values, that._stringOffsets);
};
} else if (hasBooleans) {
getValueFunction = function(index) {
return getBoolean(index, that._values);
};
setValueFunction = function(index, value) {
setBoolean(index, that._values, value);
};
} else if (defined_default(enumType)) {
getValueFunction = function(index) {
const integer = that._values.get(index);
return enumType.namesByValue[integer];
};
setValueFunction = function(index, value) {
const integer = enumType.valuesByName[value];
that._values.set(index, integer);
};
} else {
getValueFunction = function(index) {
return that._values.get(index);
};
setValueFunction = function(index, value) {
that._values.set(index, value);
};
}
this._arrayOffsets = arrayOffsets;
this._stringOffsets = stringOffsets;
this._values = values;
this._classProperty = classProperty;
this._count = count;
this._vectorComponentCount = vectorComponentCount;
this._min = property.min;
this._max = property.max;
this._offset = offset;
this._scale = scale;
this._hasValueTransform = hasValueTransform;
this._getValue = getValueFunction;
this._setValue = setValueFunction;
this._unpackedValues = void 0;
this._extras = property.extras;
this._extensions = property.extensions;
this._byteLength = byteLength;
}
Object.defineProperties(MetadataTableProperty.prototype, {
/**
* True if offset/scale should be applied. If both offset/scale were
* undefined, they default to identity so this property is set false
*
* @memberof MetadataClassProperty.prototype
* @type {boolean}
* @readonly
* @private
*/
hasValueTransform: {
get: function() {
return this._hasValueTransform;
}
},
/**
* The offset to be added to property values as part of the value transform.
*
* @memberof MetadataClassProperty.prototype
* @type {number|number[]|number[][]}
* @readonly
* @private
*/
offset: {
get: function() {
return this._offset;
}
},
/**
* The scale to be multiplied to property values as part of the value transform.
*
* @memberof MetadataClassProperty.prototype
* @type {number|number[]|number[][]}
* @readonly
* @private
*/
scale: {
get: function() {
return this._scale;
}
},
/**
* Extra user-defined properties.
*
* @memberof MetadataTableProperty.prototype
* @type {*}
* @readonly
* @private
*/
extras: {
get: function() {
return this._extras;
}
},
/**
* An object containing extensions.
*
* @memberof MetadataTableProperty.prototype
* @type {*}
* @readonly
* @private
*/
extensions: {
get: function() {
return this._extensions;
}
},
/**
* Size of all typed arrays used by this table property
*
* @memberof MetadataTableProperty.prototype
* @type {Normal}
* @readonly
* @private
*/
byteLength: {
get: function() {
return this._byteLength;
}
}
});
MetadataTableProperty.prototype.get = function(index) {
checkIndex(this, index);
let value = get(this, index);
value = this._classProperty.handleNoData(value);
if (!defined_default(value)) {
value = this._classProperty.default;
return this._classProperty.unpackVectorAndMatrixTypes(value);
}
value = this._classProperty.normalize(value);
value = applyValueTransform(this, value);
return this._classProperty.unpackVectorAndMatrixTypes(value);
};
MetadataTableProperty.prototype.set = function(index, value) {
const classProperty = this._classProperty;
Check_default.defined("value", value);
checkIndex(this, index);
const errorMessage = classProperty.validate(value);
if (defined_default(errorMessage)) {
throw new DeveloperError_default(errorMessage);
}
value = classProperty.packVectorAndMatrixTypes(value);
value = unapplyValueTransform(this, value);
value = classProperty.unnormalize(value);
set(this, index, value);
};
MetadataTableProperty.prototype.getTypedArray = function() {
if (defined_default(this._values)) {
return this._values.typedArray;
}
return void 0;
};
function flatten(values) {
if (!Array.isArray(values)) {
return values;
}
const result = [];
for (let i = 0; i < values.length; i++) {
const value = values[i];
if (Array.isArray(value)) {
addAllToArray_default(result, value);
} else {
result.push(value);
}
}
return result;
}
function checkIndex(table2, index) {
const count = table2._count;
if (!defined_default(index) || index < 0 || index >= count) {
const maximumIndex = count - 1;
throw new DeveloperError_default(
`index is required and between zero and count - 1. Actual value: ${maximumIndex}`
);
}
}
function get(property, index) {
if (requiresUnpackForGet(property)) {
unpackProperty(property);
}
const classProperty = property._classProperty;
const isArray = classProperty.isArray;
const type = classProperty.type;
const componentCount = MetadataType_default.getComponentCount(type);
if (defined_default(property._unpackedValues)) {
const value = property._unpackedValues[index];
if (isArray) {
return clone_default(value, true);
}
return value;
}
if (!isArray && componentCount === 1) {
return property._getValue(index);
}
return getArrayValues(property, classProperty, index);
}
function getArrayValues(property, classProperty, index) {
let offset;
let length2;
if (classProperty.isVariableLengthArray) {
offset = property._arrayOffsets.get(index);
length2 = property._arrayOffsets.get(index + 1) - offset;
const componentCount = MetadataType_default.getComponentCount(classProperty.type);
offset *= componentCount;
length2 *= componentCount;
} else {
const arrayLength = classProperty.arrayLength ?? 1;
const componentCount = arrayLength * property._vectorComponentCount;
offset = index * componentCount;
length2 = componentCount;
}
const values = new Array(length2);
for (let i = 0; i < length2; i++) {
values[i] = property._getValue(offset + i);
}
return values;
}
function set(property, index, value) {
if (requiresUnpackForSet(property, index, value)) {
unpackProperty(property);
}
const classProperty = property._classProperty;
const isArray = classProperty.isArray;
const type = classProperty.type;
const componentCount = MetadataType_default.getComponentCount(type);
if (defined_default(property._unpackedValues)) {
if (classProperty.isArray) {
value = clone_default(value, true);
}
property._unpackedValues[index] = value;
return;
}
if (!isArray && componentCount === 1) {
property._setValue(index, value);
return;
}
let offset;
let length2;
if (classProperty.isVariableLengthArray) {
offset = property._arrayOffsets.get(index);
length2 = property._arrayOffsets.get(index + 1) - offset;
} else {
const arrayLength = classProperty.arrayLength ?? 1;
const componentCount2 = arrayLength * property._vectorComponentCount;
offset = index * componentCount2;
length2 = componentCount2;
}
for (let i = 0; i < length2; ++i) {
property._setValue(offset + i, value[i]);
}
}
function getString(index, values, stringOffsets) {
const stringByteOffset = stringOffsets.get(index);
const stringByteLength = stringOffsets.get(index + 1) - stringByteOffset;
return getStringFromTypedArray_default(
values.typedArray,
stringByteOffset,
stringByteLength
);
}
function getBoolean(index, values) {
const byteIndex = index >> 3;
const bitIndex = index % 8;
return (values.typedArray[byteIndex] >> bitIndex & 1) === 1;
}
function setBoolean(index, values, value) {
const byteIndex = index >> 3;
const bitIndex = index % 8;
if (value) {
values.typedArray[byteIndex] |= 1 << bitIndex;
} else {
values.typedArray[byteIndex] &= ~(1 << bitIndex);
}
}
function getInt64NumberFallback(index, values) {
const dataView = values.dataView;
const byteOffset = index * 8;
let value = 0;
const isNegative = (dataView.getUint8(byteOffset + 7) & 128) > 0;
let carrying = true;
for (let i = 0; i < 8; ++i) {
let byte = dataView.getUint8(byteOffset + i);
if (isNegative) {
if (carrying) {
if (byte !== 0) {
byte = ~(byte - 1) & 255;
carrying = false;
}
} else {
byte = ~byte & 255;
}
}
value += byte * Math.pow(256, i);
}
if (isNegative) {
value = -value;
}
return value;
}
function getInt64BigIntFallback(index, values) {
const dataView = values.dataView;
const byteOffset = index * 8;
let value = BigInt(0);
const isNegative = (dataView.getUint8(byteOffset + 7) & 128) > 0;
let carrying = true;
for (let i = 0; i < 8; ++i) {
let byte = dataView.getUint8(byteOffset + i);
if (isNegative) {
if (carrying) {
if (byte !== 0) {
byte = ~(byte - 1) & 255;
carrying = false;
}
} else {
byte = ~byte & 255;
}
}
value += BigInt(byte) * (BigInt(1) << BigInt(i * 8));
}
if (isNegative) {
value = -value;
}
return value;
}
function getUint64NumberFallback(index, values) {
const dataView = values.dataView;
const byteOffset = index * 8;
const left = dataView.getUint32(byteOffset, true);
const right = dataView.getUint32(byteOffset + 4, true);
const value = left + 4294967296 * right;
return value;
}
function getUint64BigIntFallback(index, values) {
const dataView = values.dataView;
const byteOffset = index * 8;
const left = BigInt(dataView.getUint32(byteOffset, true));
const right = BigInt(dataView.getUint32(byteOffset + 4, true));
const value = left + BigInt(4294967296) * right;
return value;
}
function getComponentDatatype(componentType) {
switch (componentType) {
case MetadataComponentType_default.INT8:
return ComponentDatatype_default.BYTE;
case MetadataComponentType_default.UINT8:
return ComponentDatatype_default.UNSIGNED_BYTE;
case MetadataComponentType_default.INT16:
return ComponentDatatype_default.SHORT;
case MetadataComponentType_default.UINT16:
return ComponentDatatype_default.UNSIGNED_SHORT;
case MetadataComponentType_default.INT32:
return ComponentDatatype_default.INT;
case MetadataComponentType_default.UINT32:
return ComponentDatatype_default.UNSIGNED_INT;
case MetadataComponentType_default.FLOAT32:
return ComponentDatatype_default.FLOAT;
case MetadataComponentType_default.FLOAT64:
return ComponentDatatype_default.DOUBLE;
}
}
function requiresUnpackForGet(property) {
if (defined_default(property._unpackedValues)) {
return false;
}
const classProperty = property._classProperty;
const type = classProperty.type;
const valueType = classProperty.valueType;
if (type === MetadataType_default.STRING) {
return true;
}
if (valueType === MetadataComponentType_default.INT64 && !FeatureDetection_default.supportsBigInt64Array()) {
return true;
}
if (valueType === MetadataComponentType_default.UINT64 && !FeatureDetection_default.supportsBigUint64Array()) {
return true;
}
return false;
}
function requiresUnpackForSet(property, index, value) {
if (requiresUnpackForGet(property)) {
return true;
}
const arrayOffsets = property._arrayOffsets;
if (defined_default(arrayOffsets)) {
const oldLength = arrayOffsets.get(index + 1) - arrayOffsets.get(index);
const newLength = value.length;
if (oldLength !== newLength) {
return true;
}
}
return false;
}
function unpackProperty(property) {
property._unpackedValues = unpackValues(property);
property._arrayOffsets = void 0;
property._stringOffsets = void 0;
property._values = void 0;
}
function unpackValues(property) {
const count = property._count;
const unpackedValues = new Array(count);
const classProperty = property._classProperty;
const isArray = classProperty.isArray;
const type = classProperty.type;
const componentCount = MetadataType_default.getComponentCount(type);
if (!isArray && componentCount === 1) {
for (let i = 0; i < count; ++i) {
unpackedValues[i] = property._getValue(i);
}
return unpackedValues;
}
for (let i = 0; i < count; i++) {
unpackedValues[i] = getArrayValues(property, classProperty, i);
}
return unpackedValues;
}
function applyValueTransform(property, value) {
const classProperty = property._classProperty;
const isVariableLengthArray = classProperty.isVariableLengthArray;
if (!property._hasValueTransform || isVariableLengthArray) {
return value;
}
return MetadataClassProperty_default.valueTransformInPlace(
value,
property._offset,
property._scale,
MetadataComponentType_default.applyValueTransform
);
}
function unapplyValueTransform(property, value) {
const classProperty = property._classProperty;
const isVariableLengthArray = classProperty.isVariableLengthArray;
if (!property._hasValueTransform || isVariableLengthArray) {
return value;
}
return MetadataClassProperty_default.valueTransformInPlace(
value,
property._offset,
property._scale,
MetadataComponentType_default.unapplyValueTransform
);
}
function BufferView(bufferView, componentType, length2) {
const that = this;
let typedArray;
let getFunction;
let setFunction;
if (componentType === MetadataComponentType_default.INT64) {
if (!FeatureDetection_default.supportsBigInt()) {
oneTimeWarning_default(
"INT64 type is not fully supported on this platform. Values greater than 2^53 - 1 or less than -(2^53 - 1) may lose precision when read."
);
typedArray = new Uint8Array(
bufferView.buffer,
bufferView.byteOffset,
length2 * 8
);
getFunction = function(index) {
return getInt64NumberFallback(index, that);
};
} else if (!FeatureDetection_default.supportsBigInt64Array()) {
typedArray = new Uint8Array(
bufferView.buffer,
bufferView.byteOffset,
length2 * 8
);
getFunction = function(index) {
return getInt64BigIntFallback(index, that);
};
} else {
typedArray = new BigInt64Array(
bufferView.buffer,
bufferView.byteOffset,
length2
);
setFunction = function(index, value) {
that.typedArray[index] = BigInt(value);
};
}
} else if (componentType === MetadataComponentType_default.UINT64) {
if (!FeatureDetection_default.supportsBigInt()) {
oneTimeWarning_default(
"UINT64 type is not fully supported on this platform. Values greater than 2^53 - 1 may lose precision when read."
);
typedArray = new Uint8Array(
bufferView.buffer,
bufferView.byteOffset,
length2 * 8
);
getFunction = function(index) {
return getUint64NumberFallback(index, that);
};
} else if (!FeatureDetection_default.supportsBigUint64Array()) {
typedArray = new Uint8Array(
bufferView.buffer,
bufferView.byteOffset,
length2 * 8
);
getFunction = function(index) {
return getUint64BigIntFallback(index, that);
};
} else {
typedArray = new BigUint64Array(
bufferView.buffer,
bufferView.byteOffset,
length2
);
setFunction = function(index, value) {
that.typedArray[index] = BigInt(value);
};
}
} else {
const componentDatatype = getComponentDatatype(componentType);
typedArray = ComponentDatatype_default.createArrayBufferView(
componentDatatype,
bufferView.buffer,
bufferView.byteOffset,
length2
);
setFunction = function(index, value) {
that.typedArray[index] = value;
};
}
if (!defined_default(getFunction)) {
getFunction = function(index) {
return that.typedArray[index];
};
}
this.typedArray = typedArray;
this.dataView = new DataView(typedArray.buffer, typedArray.byteOffset);
this.get = getFunction;
this.set = setFunction;
this._componentType = componentType;
}
var MetadataTableProperty_default = MetadataTableProperty;
// packages/engine/Source/Scene/MetadataTable.js
function MetadataTable(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const count = options.count;
const metadataClass = options.class;
Check_default.typeOf.number.greaterThan("options.count", count, 0);
Check_default.typeOf.object("options.class", metadataClass);
let byteLength = 0;
const properties = {};
if (defined_default(options.properties)) {
for (const propertyId in options.properties) {
if (options.properties.hasOwnProperty(propertyId)) {
const property = new MetadataTableProperty_default({
count,
property: options.properties[propertyId],
classProperty: metadataClass.properties[propertyId],
bufferViews: options.bufferViews
});
properties[propertyId] = property;
byteLength += property.byteLength;
}
}
}
this._count = count;
this._class = metadataClass;
this._properties = properties;
this._byteLength = byteLength;
}
Object.defineProperties(MetadataTable.prototype, {
/**
* The number of entities in the table.
*
* @memberof MetadataTable.prototype
* @type {number}
* @readonly
* @private
*/
count: {
get: function() {
return this._count;
}
},
/**
* The class that properties conform to.
*
* @memberof MetadataTable.prototype
* @type {MetadataClass}
* @readonly
* @private
*/
class: {
get: function() {
return this._class;
}
},
/**
* The size of all typed arrays used in this table.
*
* @memberof MetadataTable.prototype
* @type {number}
* @readonly
* @private
*/
byteLength: {
get: function() {
return this._byteLength;
}
}
});
MetadataTable.prototype.hasProperty = function(propertyId) {
return MetadataEntity_default.hasProperty(propertyId, this._properties, this._class);
};
MetadataTable.prototype.hasPropertyBySemantic = function(semantic) {
return MetadataEntity_default.hasPropertyBySemantic(
semantic,
this._properties,
this._class
);
};
MetadataTable.prototype.getPropertyIds = function(results) {
return MetadataEntity_default.getPropertyIds(this._properties, this._class, results);
};
MetadataTable.prototype.getProperty = function(index, propertyId) {
Check_default.typeOf.string("propertyId", propertyId);
const property = this._properties[propertyId];
let value;
if (defined_default(property)) {
value = property.get(index);
} else {
value = getDefault(this._class, propertyId);
}
return value;
};
MetadataTable.prototype.setProperty = function(index, propertyId, value) {
Check_default.typeOf.string("propertyId", propertyId);
const property = this._properties[propertyId];
if (defined_default(property)) {
property.set(index, value);
return true;
}
return false;
};
MetadataTable.prototype.getPropertyBySemantic = function(index, semantic) {
Check_default.typeOf.string("semantic", semantic);
let property;
const propertiesBySemantic = this._class.propertiesBySemantic;
if (defined_default(propertiesBySemantic)) {
property = propertiesBySemantic[semantic];
}
if (defined_default(property)) {
return this.getProperty(index, property.id);
}
return void 0;
};
MetadataTable.prototype.setPropertyBySemantic = function(index, semantic, value) {
Check_default.typeOf.string("semantic", semantic);
let property;
const propertiesBySemantic = this._class.propertiesBySemantic;
if (defined_default(propertiesBySemantic)) {
property = propertiesBySemantic[semantic];
}
if (defined_default(property)) {
return this.setProperty(index, property.id, value);
}
return false;
};
MetadataTable.prototype.getPropertyTypedArray = function(propertyId) {
Check_default.typeOf.string("propertyId", propertyId);
const property = this._properties[propertyId];
if (defined_default(property)) {
return property.getTypedArray();
}
return void 0;
};
MetadataTable.prototype.getPropertyTypedArrayBySemantic = function(semantic) {
Check_default.typeOf.string("semantic", semantic);
let property;
const propertiesBySemantic = this._class.propertiesBySemantic;
if (defined_default(propertiesBySemantic)) {
property = propertiesBySemantic[semantic];
}
if (defined_default(property)) {
return this.getPropertyTypedArray(property.id);
}
return void 0;
};
function getDefault(classDefinition, propertyId) {
const classProperties = classDefinition.properties;
if (!defined_default(classProperties)) {
return void 0;
}
const classProperty = classProperties[propertyId];
if (defined_default(classProperty) && defined_default(classProperty.default)) {
let value = classProperty.default;
if (classProperty.isArray) {
value = clone_default(value, true);
}
value = classProperty.normalize(value);
return classProperty.unpackVectorAndMatrixTypes(value);
}
}
var MetadataTable_default = MetadataTable;
// packages/engine/Source/Scene/ResourceCache.js
var import_InlineWorkers522 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/BufferLoader.js
var import_InlineWorkers467 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/ResourceLoader.js
var import_InlineWorkers465 = __toESM(require_InlineWorkers(), 1);
function ResourceLoader() {
}
Object.defineProperties(ResourceLoader.prototype, {
/**
* The cache key of the resource.
*
* @memberof ResourceLoader.prototype
*
* @type {string}
* @readonly
* @private
*/
cacheKey: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
}
});
ResourceLoader.prototype.load = function() {
DeveloperError_default.throwInstantiationError();
};
ResourceLoader.prototype.unload = function() {
};
ResourceLoader.prototype.process = function(frameState) {
return false;
};
ResourceLoader.prototype.getError = function(errorMessage, error) {
Check_default.typeOf.string("errorMessage", errorMessage);
if (defined_default(error) && defined_default(error.message)) {
errorMessage += `
${error.message}`;
}
const runtimeError = new RuntimeError_default(errorMessage);
if (defined_default(error)) {
runtimeError.stack = `Original stack:
${error.stack}
Handler stack:
${runtimeError.stack}`;
}
return runtimeError;
};
ResourceLoader.prototype.isDestroyed = function() {
return false;
};
ResourceLoader.prototype.destroy = function() {
this.unload();
return destroyObject_default(this);
};
var ResourceLoader_default = ResourceLoader;
// packages/engine/Source/Scene/ResourceLoaderState.js
var import_InlineWorkers466 = __toESM(require_InlineWorkers(), 1);
var ResourceLoaderState = {
/**
* The resource has not yet been loaded.
*
* @type {number}
* @constant
* @private
*/
UNLOADED: 0,
/**
* The resource is loading. In this state, external resources are fetched as needed.
*
* @type {number}
* @constant
* @private
*/
LOADING: 1,
/**
* The resource has finished loading, but requires further processing.
*
* @type {number}
* @constant
* @private
*/
LOADED: 2,
/**
* The resource is processing. GPU resources are allocated in this state as needed.
*
* @type {Number}
* @constant
* @private
*/
PROCESSING: 3,
/**
* The resource has finished loading and processing; the results are ready to be used.
*
* @type {number}
* @constant
* @private
*/
READY: 4,
/**
* The resource loading or processing has failed due to an error.
*
* @type {number}
* @constant
* @private
*/
FAILED: 5
};
var ResourceLoaderState_default = Object.freeze(ResourceLoaderState);
// packages/engine/Source/Scene/BufferLoader.js
function BufferLoader(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const typedArray = options.typedArray;
const resource = options.resource;
const cacheKey = options.cacheKey;
if (defined_default(typedArray) === defined_default(resource)) {
throw new DeveloperError_default(
"One of options.typedArray and options.resource must be defined."
);
}
this._typedArray = typedArray;
this._resource = resource;
this._cacheKey = cacheKey;
this._state = ResourceLoaderState_default.UNLOADED;
this._promise = void 0;
}
if (defined_default(Object.create)) {
BufferLoader.prototype = Object.create(ResourceLoader_default.prototype);
BufferLoader.prototype.constructor = BufferLoader;
}
Object.defineProperties(BufferLoader.prototype, {
/**
* The cache key of the resource.
*
* @memberof BufferLoader.prototype
*
* @type {string}
* @readonly
* @private
*/
cacheKey: {
get: function() {
return this._cacheKey;
}
},
/**
* The typed array containing the embedded buffer contents.
*
* @memberof BufferLoader.prototype
*
* @type {Uint8Array}
* @readonly
* @private
*/
typedArray: {
get: function() {
return this._typedArray;
}
}
});
BufferLoader.prototype.load = async function() {
if (defined_default(this._promise)) {
return this._promise;
}
if (defined_default(this._typedArray)) {
this._promise = Promise.resolve(this);
return this._promise;
}
this._promise = loadExternalBuffer(this);
return this._promise;
};
async function loadExternalBuffer(bufferLoader) {
const resource = bufferLoader._resource;
bufferLoader._state = ResourceLoaderState_default.LOADING;
try {
const arrayBuffer = await BufferLoader._fetchArrayBuffer(resource);
if (bufferLoader.isDestroyed()) {
return;
}
bufferLoader._typedArray = new Uint8Array(arrayBuffer);
bufferLoader._state = ResourceLoaderState_default.READY;
return bufferLoader;
} catch (error) {
if (bufferLoader.isDestroyed()) {
return;
}
bufferLoader._state = ResourceLoaderState_default.FAILED;
const errorMessage = `Failed to load external buffer: ${resource.url}`;
throw bufferLoader.getError(errorMessage, error);
}
}
BufferLoader._fetchArrayBuffer = function(resource) {
return resource.fetchArrayBuffer();
};
BufferLoader.prototype.unload = function() {
this._typedArray = void 0;
};
var BufferLoader_default = BufferLoader;
// packages/engine/Source/Scene/GltfBufferViewLoader.js
var import_InlineWorkers473 = __toESM(require_InlineWorkers(), 1);
// node_modules/meshoptimizer/index.module.js
var import_InlineWorkers472 = __toESM(require_InlineWorkers());
// node_modules/meshoptimizer/meshopt_encoder.module.js
var import_InlineWorkers468 = __toESM(require_InlineWorkers());
var MeshoptEncoder = (function() {
var wasm = "b9H79Tebbbe9ok9Geueu9Geub9Gbb9Gruuuuuuueu9Gvuuuuueu9Gduueu9Gluuuueu9Gvuuuuub9Gouuuuuub9Gluuuub9GiuuueuiE8AdilveoveovrrwrrrDDoDrbqqbelve9Weiiviebeoweuec;G:Qdkr:PlCo9TW9T9VV95dbH9F9F939H79T9F9J9H229F9Jt9VV7bb8F9TW79O9V9Wt9FW9U9J9V9KW9wWVtW949c919M9MWV9mW4W2be8A9TW79O9V9Wt9FW9U9J9V9KW9wWVtW949c919M9MWVbd8F9TW79O9V9Wt9FW9U9J9V9KW9wWVtW949c919M9MWV9c9V919U9KbiE9TW79O9V9Wt9FW9U9J9V9KW9wWVtW949wWV79P9V9UblY9TW79O9V9Wt9FW9U9J9V9KW69U9KW949c919M9MWVbv8E9TW79O9V9Wt9FW9U9J9V9KW69U9KW949c919M9MWV9c9V919U9Kbo8A9TW79O9V9Wt9FW9U9J9V9KW69U9KW949wWV79P9V9UbrE9TW79O9V9Wt9FW9U9J9V9KW69U9KW949tWG91W9U9JWbwa9TW79O9V9Wt9FW9U9J9V9KW69U9KW949tWG91W9U9JW9c9V919U9KbDL9TW79O9V9Wt9FW9U9J9V9KWS9P2tWV9p9JtbqK9TW79O9V9Wt9FW9U9J9V9KWS9P2tWV9r919HtbkL9TW79O9V9Wt9FW9U9J9V9KWS9P2tWVT949WbxY9TW79O9V9Wt9FW9U9J9V9KWS9P2tWVJ9V29VVbmE9TW79O9V9Wt9F9V9Wt9P9T9P96W9wWVtW94J9H9J9OWbza9TW79O9V9Wt9F9V9Wt9P9T9P96W9wWVtW94J9H9J9OW9ttV9P9WbHa9TW79O9V9Wt9F9V9Wt9P9T9P96W9wWVtW94SWt9J9O9sW9T9H9WbOK9TW79O9V9Wt9F79W9Ht9P9H29t9VVt9sW9T9H9WbAl79IV9RbXDwebcekdKYq;i28Adbk:Bhdhud9:8Jjjjjbc;qw9Rgr8KjjjjbcbhwdnaeTmbabcbyd;C:kjjbaoaocb9iEgDc:GeV86bbarc;adfcbcjdz:xjjjb8AdnaiTmbarc;adfadalz:wjjjb8Akarc;abfalfcbcbcjdal9RalcFe0Ez:xjjjb8Aarc;abfarc;adfalz:wjjjb8AarcUf9cb83ibarc8Wf9cb83ibarcyf9cb83ibarcaf9cb83ibarcKf9cb83ibarczf9cb83ibar9cb83iwar9cb83ibcj;abal9Uc;WFbGcjdalca0Ehqdnaicd6mbavcd9imbaDTmbadcefhkaqci2gxal2hmarc;alfclfhParc;qlfceVhsarc;qofclVhzarc;qofcKfhHarc;qofczfhOcbhAincdhCcbhodnavci6mbaH9cb83ibaO9cb83ibar9cb83i;yoar9cb83i;qoadaAfgoybbhXcbhQincbhwcbhLdninaoalfhKaoybbgYaX7aLVhLawcP0meaKhoaYhXawcefgwaQfai6mbkkcbhXarc;qofhwincwh8AcwhEdnaLaX93gocFeGg3cs0mbclhEa3ci0mba3cb9hcethEkdnaocw4cFeGg3cs0mbclh8Aa3ci0mba3cb9hceth8Aka8AaEfh3awydbh5cwh8AcwhEdnaocz4cFeGg8Ecs0mbclhEa8Eci0mba8Ecb9hcethEka3a5fh3dnaocFFFFb0mbclh8AaocFFF8F0mbaocFFFr0ceth8Akawa3aEfa8AfBdbawclfhwaXcefgXcw9hmbkaKhoaYhXaQczfgQai6mbkcbhocehwazhLinawaoaLydbarc;qofaocdtfydb6EhoaLclfhLawcefgwcw9hmbkcihCkcbh3arc;qlfcbcjdz:xjjjb8Aarc;alfcwfcbBdbar9cb83i;alaoclth8Fadhaaqhhakh5inarc;qlfadcba3cufgoaoa30Eal2falz:wjjjb8Aaiahaiah6Ehgdnaqaia39Ra3aqfai6EgYcsfc9WGgoaY9nmbarc;qofaYfcbaoaY9Rz:xjjjb8Akada3al2fh8Jcbh8Kina8Ka8FVcl4hQarc;alfa8Kcdtfh8LaAh8Mcbh8Nina8NaAfhwdndndndndndna8KPldebidkasa8Mc98GgLfhoa5aLfh8Aarc;qlfawc98GgLfRbbhXcwhwinaoRbbawtaXVhXaocefhoawcwfgwca9hmbkaYTmla8Ncith8Ea8JaLfhEcbhKinaERbbhLcwhoa8AhwinawRbbaotaLVhLawcefhwaocwfgoca9hmbkarc;qofaKfaLaX7aQ93a8E486bba8Aalfh8AaEalfhEaLhXaKcefgKaY9hmbxlkkaYTmia8Mc9:Ghoa8NcitcwGhEarc;qlfawceVfRbbcwtarc;qlfawc9:GfRbbVhLarc;qofhwaghXinawa5aofRbbcwtaaaofRbbVg8AaL9RgLcetaLcztcz91cs47cFFiGaE486bbaoalfhoawcefhwa8AhLa3aXcufgX9hmbxikkaYTmda8Jawfhoarc;qlfawfRbbhLarc;qofhwaghXinawaoRbbg8AaL9RgLcetaLcKtcK91cr4786bbawcefhwaoalfhoa8AhLa3aXcufgX9hmbxdkkaYTmeka8LydbhEcbhKarc;qofhoincdhLcbhwinaLaoawfRbbcb9hfhLawcefgwcz9hmbkclhXcbhwinaXaoawfRbbcd0fhXawcefgwcz9hmbkcwh8Acbhwina8AaoawfRbbcP0fh8Aawcefgwcz9hmbkaLaXaLaX6Egwa8Aawa8A6Egwczawcz6EaEfhEaoczfhoaKczfgKaY6mbka8LaEBdbka8Mcefh8Ma8Ncefg8Ncl9hmbka8Kcefg8KaC9hmbkaaamfhaahaxfhha5amfh5a3axfg3ai6mbkcbhocehwaPhLinawaoaLydbarc;alfaocdtfydb6EhoaLclfhLawcefgXhwaCaX9hmbkaraAcd4fa8FcdVaoaocdSE86bbaAclfgAal6mbkkabaefh8Kabcefhoalcd4gecbaDEhkadcefhOarc;abfceVhHcbhmdndninaiam9nmearc;qofcbcjdz:xjjjb8Aa8Kao9Rak6mdadamal2gwfhxcbh8JaOawfhzaocbakz:xjjjbghakfh5aqaiam9Ramaqfai6Egscsfgocl4cifcd4hCaoc9WGg8LThPindndndndndndndndndndnaDTmbara8Jcd4fRbbgLciGPlbedlbkasTmdaxa8Jfhoarc;abfa8JfRbbhLarc;qofhwashXinawaoRbbg8AaL9RgLcetaLcKtcK91cr4786bbawcefhwaoalfhoa8AhLaXcufgXmbxikkasTmia8JcitcwGhEarc;abfa8JceVfRbbcwtarc;abfa8Jc9:GgofRbbVhLaxaofhoarc;qofhwashXinawao8Vbbg8AaL9RgLcetaLcztcz91cs47cFFiGaE486bbawcefhwaoalfhoa8AhLaXcufgXmbxdkkaHa8Jc98GgEfhoazaEfh8Aarc;abfaEfRbbhXcwhwinaoRbbawtaXVhXaocefhoawcwfgwca9hmbkasTmbaLcl4hYa8JcitcKGh3axaEfhEcbhKinaERbbhLcwhoa8AhwinawRbbaotaLVhLawcefhwaocwfgoca9hmbkarc;qofaKfaLaX7aY93a3486bba8Aalfh8AaEalfhEaLhXaKcefgKas9hmbkkaDmbcbhoxlka8LTmbcbhodninarc;qofaofgwcwf8Pibaw8Pib:e9qTmeaoczfgoa8L9pmdxbkkdnavmbcehoxikcbhEaChKaChYinarc;qofaEfgocwf8Pibhyao8Pibh8PcdhLcbhwinaLaoawfRbbcb9hfhLawcefgwcz9hmbkclhXcbhwinaXaoawfRbbcd0fhXawcefgwcz9hmbkcwh8Acbhwina8AaoawfRbbcP0fh8Aawcefgwcz9hmbkaLaXaLaX6Egoa8Aaoa8A6Egoczaocz6EaYfhYaocucbaya8P:e9cb9sEgwaoaw6EaKfhKaEczfgEa8L9pmdxbkkaha8Jcd4fgoaoRbbcda8JcetcoGtV86bbxikdnaKas6mbaYas6mbaha8Jcd4fgoaoRbbcia8JcetcoGtV86bba8Ka59Ras6mra5arc;qofasz:wjjjbasfh5xikaKaY9phokaha8Jcd4fgwawRbbaoa8JcetcoGtV86bbka8Ka59RaC6mla5cbaCz:xjjjbgAaCfhYdndna8LmbaPhoxekdna8KaY9RcK9pmbaPhoxekaocdtc:q1jjbfcj1jjbaDEg5ydxggcetc;:FFFeGh8Fcuh3cuagtcu7cFeGhacbh8Marc;qofhLinarc;qofa8MfhQczhEdndndnagPDbeeeeeeedekcucbaQcwf8PibaQ8Pib:e9cb9sEhExekcbhoa8FhEinaEaaaLaofRbb9nfhEaocefgocz9hmbkkcih8Ecbh8Ainczhwdndndna5a8AcdtfydbgKPDbeeeeeeedekcucbaQcwf8PibaQ8Pib:e9cb9sEhwxekaKcetc;:FFFeGhwcuaKtcu7cFeGhXcbhoinawaXaLaofRbb9nfhwaocefgocz9hmbkkdndnawaE6mbaKa39hmeawaE9hmea5a8EcdtfydbcwSmeka8Ah8EawhEka8Acefg8Aci9hmbkaAa8Mco4fgoaoRbba8Ea8Mci4coGtV86bbdndndna5a8Ecdtfydbg3PDdbbbbbbbebkdncwa39Tg8ETmbcua3tcu7hwdndna3ceSmbcbh8NaLhQinaQhoa8Eh8AcbhXinaoRbbgEawcFeGgKaEaK6EaXa3tVhXaocefhoa8Acufg8AmbkaYaX86bbaQa8EfhQaYcefhYa8Na8Efg8Ncz6mbxdkkcbh8NaLhQinaQhoa8Eh8AcbhXinaoRbbgEawcFeGgKaEaK6EaXcetVhXaocefhoa8Acufg8AmbkaYaX:T9cFe:d9c:c:qj:bw9:9c:q;c1:I1e:d9c:b:c:e1z9:9ca188bbaQa8EfhQaYcefhYa8Na8Efg8Ncz6mbkkcbhoinaYaLaofRbbgX86bbaYaXawcFeG9pfhYaocefgocz9hmbxikkdna3ceSmbinaYcb86bbaYcefhYxbkkinaYcb86bbaYcefhYxbkkaYaQ8Pbb83bbaYcwfaQcwf8Pbb83bbaYczfhYka8Mczfg8Ma8L9pgomeaLczfhLa8KaY9RcK9pmbkkaoTmlaYh5aYTmlka8Jcefg8Jal9hmbkarc;abfaxascufal2falz:wjjjb8Aasamfhma5hoa5mbkcbhwxdkdna8Kao9RakalfgwcKcaaDEgLawaL0EgX9pmbcbhwxdkdnawaL9pmbaocbaXaw9Rgwz:xjjjbawfhokaoarc;adfalz:wjjjbalfhodnaDTmbaoaraez:wjjjbaefhokaoab9Rhwxekcbhwkarc;qwf8Kjjjjbawk5babaeadaialcdcbyd;C:kjjbz:bjjjbk9reduaecd4gdaefgicaaica0Eabcj;abae9Uc;WFbGcjdaeca0Egifcufai9Uae2aiadfaicl4cifcd4f2fcefkmbcbabBd;C:kjjbk:Ese5u8Jjjjjbc;ae9Rgl8Kjjjjbcbhvdnaici9UgocHfae0mbabcbyd;m:kjjbgrc;GeV86bbalc;abfcFecjez:xjjjb8AalcUfgw9cu83ibalc8WfgD9cu83ibalcyfgq9cu83ibalcafgk9cu83ibalcKfgx9cu83ibalczfgm9cu83ibal9cu83iwal9cu83ibabaefc9WfhPabcefgsaofhednaiTmbcmcsarcb9kgzEhHcbhOcbhAcbhCcbhXcbhQindnaeaP9nmbcbhvxikaQcufhvadaCcdtfgLydbhKaLcwfydbhYaLclfydbh8AcbhEdndndninalc;abfavcsGcitfgoydlh3dndndnaoydbgoaK9hmba3a8ASmekdnaoa8A9hmba3aY9hmbaEcefhExekaoaY9hmea3aK9hmeaEcdfhEkaEc870mdaXcufhvaLaEciGcx2goc;i1jjbfydbcdtfydbh3aLaoc;e1jjbfydbcdtfydbh8AaLaoc;a1jjbfydbcdtfydbhKcbhodnindnalavcsGcdtfydba39hmbaohYxdkcuhYavcufhvaocefgocz9hmbkkaOa3aOSgvaYce9iaYaH9oVgoGfhOdndndncbcsavEaYaoEgvcs9hmbarce9imba3a3aAa3cefaASgvEgAcefSmecmcsavEhvkasavaEcdtc;WeGV86bbavcs9hmea3aA9Rgvcetavc8F917hvinaeavcFb0crtavcFbGV86bbaecefheavcje6hoavcr4hvaoTmbka3hAxvkcPhvasaEcdtcPV86bba3hAkavTmiavaH9omicdhocehEaQhYxlkavcufhvaEclfgEc;ab9hmbkkdnaLceaYaOSceta8AaOSEcx2gvc;a1jjbfydbcdtfydbgKTaLavc;e1jjbfydbcdtfydbg8AceSGaLavc;i1jjbfydbcdtfydbg3cdSGaOcb9hGazGg5ce9hmbaw9cu83ibaD9cu83ibaq9cu83ibak9cu83ibax9cu83ibam9cu83ibal9cu83iwal9cu83ibcbhOkcbhEaXcufgvhodnindnalaocsGcdtfydba8A9hmbaEhYxdkcuhYaocufhoaEcefgEcz9hmbkkcbhodnindnalavcsGcdtfydba39hmbaohExdkcuhEavcufhvaocefgocz9hmbkkaOaKaOSg8EfhLdndnaYcm0mbaYcefhYxekcbcsa8AaLSgvEhYaLavfhLkdndnaEcm0mbaEcefhExekcbcsa3aLSgvEhEaLavfhLkc9:cua8EEh8FcbhvaEaYcltVgacFeGhodndndninavc:W1jjbfRbbaoSmeavcefgvcz9hmbxdkka5aKaO9havcm0VVmbasavc;WeV86bbxekasa8F86bbaeaa86bbaecefhekdna8EmbaKaA9Rgvcetavc8F917hvinaeavcFb0gocrtavcFbGV86bbavcr4hvaecefheaombkaKhAkdnaYcs9hmba8AaA9Rgvcetavc8F917hvinaeavcFb0gocrtavcFbGV86bbavcr4hvaecefheaombka8AhAkdnaEcs9hmba3aA9Rgvcetavc8F917hvinaeavcFb0gocrtavcFbGV86bbavcr4hvaecefheaombka3hAkalaXcdtfaKBdbaXcefcsGhvdndnaYPzbeeeeeeeeeeeeeebekalavcdtfa8ABdbaXcdfcsGhvkdndnaEPzbeeeeeeeeeeeeeebekalavcdtfa3BdbavcefcsGhvkcihoalc;abfaQcitfgEaKBdlaEa8ABdbaQcefcsGhYcdhEavhXaLhOxekcdhoalaXcdtfa3BdbcehEaXcefcsGhXaQhYkalc;abfaYcitfgva8ABdlava3Bdbalc;abfaQaEfcsGcitfgva3BdlavaKBdbascefhsaQaofcsGhQaCcifgCai6mbkkdnaeaP9nmbcbhvxekcbhvinaeavfavc:W1jjbfRbb86bbavcefgvcz9hmbkaeab9Ravfhvkalc;aef8KjjjjbavkZeeucbhddninadcefgdc8F0meceadtae6mbkkadcrfcFeGcr9Uci2cdfabci9U2cHfkmbcbabBd;m:kjjbk:Adewu8Jjjjjbcz9Rhlcbhvdnaicvfae0mbcbhvabcbRb;m:kjjbc;qeV86bbal9cb83iwabcefhoabaefc98fhrdnaiTmbcbhwcbhDindnaoar6mbcbskadaDcdtfydbgqalcwfawaqav9Rgvavc8F91gv7av9Rc507gwcdtfgkydb9Rgvc8E91c9:Gavcdt7awVhvinaoavcFb0gecrtavcFbGV86bbavcr4hvaocefhoaembkakaqBdbaqhvaDcefgDai9hmbkkdnaoar9nmbcbskaocbBbbaoab9RclfhvkavkBeeucbhddninadcefgdc8F0meceadtae6mbkkadcwfcFeGcr9Uab2cvfk:bvli99dui99ludnaeTmbcuadcetcuftcu7:Zhvdndncuaicuftcu7:ZgoJbbbZMgr:lJbbb9p9DTmbar:Ohwxekcjjjj94hwkcbhicbhDinalclfIdbgrJbbbbJbbjZalIdbgq:lar:lMalcwfIdbgk:lMgr:varJbbbb9BEgrNhxaqarNhrdndnakJbbbb9GTmbaxhqxekJbbjZar:l:tgqaq:maxJbbbb9GEhqJbbjZax:l:tgxax:marJbbbb9GEhrkdndnalcxfIdbgxJbbj:;axJbbj:;9GEgkJbbjZakJbbjZ9FEavNJbbbZJbbb:;axJbbbb9GEMgx:lJbbb9p9DTmbax:Ohmxekcjjjj94hmkdndnaqJbbj:;aqJbbj:;9GEgxJbbjZaxJbbjZ9FEaoNJbbbZJbbb:;aqJbbbb9GEMgq:lJbbb9p9DTmbaq:OhPxekcjjjj94hPkdndnarJbbj:;arJbbj:;9GEgqJbbjZaqJbbjZ9FEaoNJbbbZJbbb:;arJbbbb9GEMgr:lJbbb9p9DTmbar:Ohsxekcjjjj94hskdndnadcl9hmbabaifgzas86bbazcifam86bbazcdfaw86bbazcefaP86bbxekabaDfgzas87ebazcofam87ebazclfaw87ebazcdfaP87ebkalczfhlaiclfhiaDcwfhDaecufgembkkk;hlld99eud99eudnaeTmbdndncuaicuftcu7:ZgvJbbbZMgo:lJbbb9p9DTmbao:Ohixekcjjjj94hikaic;8FiGhrinabcofcicdalclfIdb:lalIdb:l9EgialcwfIdb:lalaicdtfIdb:l9EEgialcxfIdb:lalaicdtfIdb:l9EEgiarV87ebdndnJbbj:;JbbjZalaicdtfIdbJbbbb9DEgoalaicd7cdtfIdbJ;Zl:1ZNNgwJbbj:;awJbbj:;9GEgDJbbjZaDJbbjZ9FEavNJbbbZJbbb:;awJbbbb9GEMgw:lJbbb9p9DTmbaw:Ohqxekcjjjj94hqkabcdfaq87ebdndnalaicefciGcdtfIdbJ;Zl:1ZNaoNgwJbbj:;awJbbj:;9GEgDJbbjZaDJbbjZ9FEavNJbbbZJbbb:;awJbbbb9GEMgw:lJbbb9p9DTmbaw:Ohqxekcjjjj94hqkabaq87ebdndnaoalaicufciGcdtfIdbJ;Zl:1ZNNgoJbbj:;aoJbbj:;9GEgwJbbjZawJbbjZ9FEavNJbbbZJbbb:;aoJbbbb9GEMgo:lJbbb9p9DTmbao:Ohixekcjjjj94hikabclfai87ebabcwfhbalczfhlaecufgembkkk;3viDue99eu8Jjjjjbcjd9Rgo8Kjjjjbadcd4hrdndndndnavcd9hmbadcl6meaohwarhDinawc:CuBdbawclfhwaDcufgDmbkaeTmiadcl6mdarcdthqalhkcbhxinaohwakhDarhminawawydbgPcbaDIdbgs:8cL4cFeGc:cufasJbbbb9BEgzaPaz9kEBdbaDclfhDawclfhwamcufgmmbkakaqfhkaxcefgxaeSmixbkkaeTmdxekaeTmekarcdthkavce9hhqadcl6hdcbhxindndndnaqmbadmdc:CuhDalhwarhminaDcbawIdbgs:8cL4cFeGc:cufasJbbbb9BEgPaDaP9kEhDawclfhwamcufgmmbxdkkc:CuhDdndnavPleddbdkadmdaohwalhmarhPinawcbamIdbgs:8cL4cFeGgzc;:bazc;:b0Ec:cufasJbbbb9BEBdbamclfhmawclfhwaPcufgPmbxdkkadmecbhwarhminaoawfcbalawfIdbgs:8cL4cFeGgPc8AaPc8A0Ec:cufasJbbbb9BEBdbawclfhwamcufgmmbkkadmbcbhwarhPinaDhmdnavceSmbaoawfydbhmkdndnalawfIdbgscjjj;8iamai9RcefgmcLt9R::NJbbbZJbbb:;asJbbbb9GEMgs:lJbbb9p9DTmbas:Ohzxekcjjjj94hzkabawfazcFFFrGamcKtVBdbawclfhwaPcufgPmbkkabakfhbalakfhlaxcefgxae9hmbkkaocjdf8Kjjjjbk:Ylvdud99due99iudnaeTmbceaicufgvthocuaitcu7:Zhrcuavtcu7:Zhwcbhvadcl9hhDcbhqindndnalcwfIdbgkJbbbbakJbbbb9GEgkJbbjZakJbbjZ9FEarNJbbbZMgk:lJbbb9p9DTmbak:Ohixekcjjjj94hikdndnalIdbgkJbbbbakJbbbb9GEgkJbbjZakJbbjZ9FEarNJbbbZMgk:lJbbb9p9DTmbak:Ohdxekcjjjj94hdkadai9Rcd9TgxaifhidndnalclfIdbgkJbbbbakJbbbb9GEgkJbbjZakJbbjZ9FEarNJbbbZMgk:lJbbb9p9DTmbak:Ohdxekcjjjj94hdkadai9Rcd9ThddndnalcxfIdbgkJbbbbakJbbbb9GEgkJbbjZakJbbjZ9FEawNJbbbZMgk:lJbbb9p9DTmbak:Ohmxekcjjjj94hmkadaifhiaoamVhmdndnaDmbabavfgPai86bbaPcifam86bbaPcdfad86bbaPcefax86bbxekabaqfgPai87ebaPcofam87ebaPclfad87ebaPcdfax87ebkalczfhlavclfhvaqcwfhqaecufgembkkk;YqdXui998Jjjjjbc:qd9Rgv8Kjjjjbavc:Sefcbc;Kbz:xjjjb8AcbhodnadTmbcbhoaiTmbdndnabaeSmbaehrxekavcuadcdtgwadcFFFFi0Ecbyd;q:kjjbHjjjjbbgrBd:SeavceBd:mdaraeawz:wjjjb8Akavc:GefcwfcbBdbav9cb83i:Geavc:Gefaradaiavc:Sefz:pjjjbavyd:GehDadci9Ugqcbyd;q:kjjbHjjjjbbheavc:Sefavyd:mdgkcdtfaeBdbavakcefgwBd:mdaecbaqz:xjjjbhxavc:SefawcdtfcuaicdtaicFFFFi0Ecbyd;q:kjjbHjjjjbbgmBdbavakcdfgPBd:mdalc;ebfhsaDheamhwinawalIdbasaeydbgzcwazcw6EcdtfIdbMUdbaeclfheawclfhwaicufgimbkavc:SefaPcdtfcuaqcdtadcFFFF970Ecbyd;q:kjjbHjjjjbbgPBdbdnadci6mbarheaPhwaqhiinawamaeydbcdtfIdbamaeclfydbcdtfIdbMamaecwfydbcdtfIdbMUdbaecxfheawclfhwaicufgimbkkakcifhoalc;ebfhHavc;qbfhOavheavyd:KehAavyd:OehCcbhzcbhwcbhXcehQinaehLcihkarawci2gKcdtfgeydbhsaeclfydbhdabaXcx2fgicwfaecwfydbgYBdbaiclfadBdbaiasBdbaxawfce86bbaOaYBdwaOadBdlaOasBdbaPawcdtfcbBdbdnazTmbcihkaLhiinaOakcdtfaiydbgeBdbakaeaY9haeas9haead9hGGfhkaiclfhiazcufgzmbkkaXcefhXcbhzinaCaAarazaKfcdtfydbcdtgifydbcdtfgYheaDaifgdydbgshidnasTmbdninaeydbawSmeaeclfheaicufgiTmdxbkkaeaYascdtfc98fydbBdbadadydbcufBdbkazcefgzci9hmbkdndnakTmbcuhwJbbbbh8Acbhdavyd:KehYavyd:OehKindndnaDaOadcdtfydbcdtgzfydbgembadcefhdxekadcs0hiamazfgsIdbhEasalcbadcefgdaiEcdtfIdbaHaecwaecw6EcdtfIdbMg3Udba3aE:th3aecdthiaKaYazfydbcdtfheinaPaeydbgzcdtfgsa3asIdbMgEUdbaEa8Aa8AaE9DgsEh8AazawasEhwaeclfheaic98fgimbkkadak9hmbkawcu9hmekaQaq9pmdindnaxaQfRbbmbaQhwxdkaqaQcefgQ9hmbxikkakczakcz6EhzaOheaLhOawcu9hmbkkaocdtavc:Seffc98fhedninaoTmeaeydbcbyd;u:kjjbH:bjjjbbaec98fheaocufhoxbkkavc:qdf8Kjjjjbk;IlevucuaicdtgvaicFFFFi0Egocbyd;q:kjjbHjjjjbbhralalyd9GgwcdtfarBdbalawcefBd9GabarBdbaocbyd;q:kjjbHjjjjbbhralalyd9GgocdtfarBdbalaocefBd9GabarBdlcuadcdtadcFFFFi0Ecbyd;q:kjjbHjjjjbbhralalyd9GgocdtfarBdbalaocefBd9GabarBdwabydbcbavz:xjjjb8Aadci9UhDdnadTmbabydbhoaehladhrinaoalydbcdtfgvavydbcefBdbalclfhlarcufgrmbkkdnaiTmbabydbhlabydlhrcbhvaihoinaravBdbarclfhralydbavfhvalclfhlaocufgombkkdnadci6mbabydlhrabydwhvcbhlinaecwfydbhoaeclfydbhdaraeydbcdtfgwawydbgwcefBdbavawcdtfalBdbaradcdtfgdadydbgdcefBdbavadcdtfalBdbaraocdtfgoaoydbgocefBdbavaocdtfalBdbaecxfheaDalcefgl9hmbkkdnaiTmbabydlheabydbhlinaeaeydbalydb9RBdbalclfhlaeclfheaicufgimbkkkQbabaeadaic;K1jjbz:ojjjbkQbabaeadaic;m:jjjbz:ojjjbk9DeeuabcFeaicdtz:xjjjbhlcbhbdnadTmbindnalaeydbcdtfgiydbcu9hmbaiabBdbabcefhbkaeclfheadcufgdmbkkabk:Vvioud9:du8Jjjjjbc;Wa9Rgl8Kjjjjbcbhvalcxfcbc;Kbz:xjjjb8AalcuadcitgoadcFFFFe0Ecbyd;q:kjjbHjjjjbbgrBdxalceBd2araeadaicezNjjjbalcuaoadcjjjjoGEcbyd;q:kjjbHjjjjbbgwBdzadcdthednadTmbabhiinaiavBdbaiclfhiadavcefgv9hmbkkawaefhDalabBdwalawBdl9cbhqindnadTmbaq9cq9:hkarhvaDhiadheinaiav8Pibak1:NcFrG87ebavcwfhvaicdfhiaecufgembkkalclfaq:NceGcdtfydbhxalclfaq9ce98gq:NceGcdtfydbhmalc;Wbfcbcjaz:xjjjb8AaDhvadhidnadTmbinalc;Wbfav8VebcdtfgeaeydbcefBdbavcdfhvaicufgimbkkcbhvcbhiinalc;WbfavfgeydbhoaeaiBdbaoaifhiavclfgvcja9hmbkadhvdndnadTmbinalc;WbfaDamydbgicetf8VebcdtfgeaeydbgecefBdbaxaecdtfaiBdbamclfhmavcufgvmbkaq9cv9smdcbhvinabawydbcdtfavBdbawclfhwadavcefgv9hmbxdkkaq9cv9smekkclhvdninavc98Smealcxfavfydbcbyd;u:kjjbH:bjjjbbavc98fhvxbkkalc;Waf8Kjjjjbk:Jwliuo99iud9:cbhv8Jjjjjbca9Rgoczfcwfcbyd:8:kjjbBdbaocb8Pd:0:kjjb83izaocwfcbyd;i:kjjbBdbaocb8Pd;a:kjjb83ibaicd4hrdndnadmbJFFuFhwJFFuuhDJFFuuhqJFFuFhkJFFuuhxJFFuFhmxekarcdthPaehsincbhiinaoczfaifgzasaifIdbgwazIdbgDaDaw9EEUdbaoaifgzawazIdbgDaDaw9DEUdbaiclfgicx9hmbkasaPfhsavcefgvad9hmbkaoIdKhDaoIdwhwaoIdChqaoIdlhkaoIdzhxaoIdbhmkdnadTmbJbbbbJbFu9hJbbbbamax:tgmamJbbbb9DEgmakaq:tgkakam9DEgkawaD:tgwawak9DEgw:vawJbbbb9BEhwdnalmbarcdthoindndnaeclfIdbaq:tawNJbbbZMgk:lJbbb9p9DTmbak:Ohixekcjjjj94hikai:S9cC:ghHdndnaeIdbax:tawNJbbbZMgk:lJbbb9p9DTmbak:Ohixekcjjjj94hikaHai:S:ehHdndnaecwfIdbaD:tawNJbbbZMgk:lJbbb9p9DTmbak:Ohixekcjjjj94hikabaHai:T9cy:g:e83ibaeaofheabcwfhbadcufgdmbxdkkarcdthoindndnaeIdbax:tawNJbbbZMgk:lJbbb9p9DTmbak:Ohixekcjjjj94hikai:SgH9ca:gaH9cz:g9cjjj;4s:d:eaH9cFe:d:e9cF:bj;4:pj;ar:d9c:bd9:9c:p;G:d;4j:E;ar:d9cH9:9c;d;H:W:y:m:g;d;Hb:d9cv9:9c;j:KM;j:KM;j:Kd:dhOdndnaeclfIdbaq:tawNJbbbZMgk:lJbbb9p9DTmbak:Ohixekcjjjj94hikai:SgH9ca:gaH9cz:g9cjjj;4s:d:eaH9cFe:d:e9cF:bj;4:pj;ar:d9c:bd9:9c:p;G:d;4j:E;ar:d9cH9:9c;d;H:W:y:m:g;d;Hb:d9cq9:9cM;j:KM;j:KM;jl:daO:ehOdndnaecwfIdbaD:tawNJbbbZMgk:lJbbb9p9DTmbak:Ohixekcjjjj94hikabaOai:SgH9ca:gaH9cz:g9cjjj;4s:d:eaH9cFe:d:e9cF:bj;4:pj;ar:d9c:bd9:9c:p;G:d;4j:E;ar:d9cH9:9c;d;H:W:y:m:g;d;Hb:d9cC9:9c:KM;j:KM;j:KMD:d:e83ibaeaofheabcwfhbadcufgdmbkkk9teiucbcbyd;y:kjjbgeabcifc98GfgbBd;y:kjjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaik;teeeudndnaeabVciGTmbabhixekdndnadcz9pmbabhixekabhiinaiaeydbBdbaiaeydlBdlaiaeydwBdwaiaeydxBdxaeczfheaiczfhiadc9Wfgdcs0mbkkadcl6mbinaiaeydbBdbaeclfheaiclfhiadc98fgdci0mbkkdnadTmbinaiaeRbb86bbaicefhiaecefheadcufgdmbkkabk:3eedudndnabciGTmbabhixekaecFeGc:b:c:ew2hldndnadcz9pmbabhixekabhiinaialBdxaialBdwaialBdlaialBdbaiczfhiadc9Wfgdcs0mbkkadcl6mbinaialBdbaiclfhiadc98fgdci0mbkkdnadTmbinaiae86bbaicefhiadcufgdmbkkabk9teiucbcbyd;y:kjjbgeabcrfc94GfgbBd;y:kjjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaik9:eiuZbhedndncbyd;y:kjjbgdaecztgi9nmbcuheadai9RcFFifcz4nbcuSmekadhekcbabae9Rcifc98Gcbyd;y:kjjbfgdBd;y:kjjbdnadZbcztge9nmbadae9RcFFifcz4nb8Akkk;Qddbcjwk;mdbbbbdbbblbbbwbbbbbbbebbbdbbblbbbwbbbbbbbbbbbbbbbb4:h9w9N94:P:gW:j9O:ye9Pbbbbbbebbbdbbbebbbdbbbbbbbdbbbbbbbebbbbbbb:l29hZ;69:9kZ;N;76Z;rg97Z;z;o9xZ8J;B85Z;:;u9yZ;b;k9HZ:2;Z9DZ9e:l9mZ59A8KZ:r;T3Z:A:zYZ79OHZ;j4::8::Y:D9V8:bbbb9s:49:Z8R:hBZ9M9M;M8:L;z;o8:;8:PG89q;x:J878R:hQ8::M:B;e87bbbbbbjZbbjZbbjZ:E;V;N8::Y:DsZ9i;H;68:xd;R8:;h0838:;W:NoZbbbb:WV9O8:uf888:9i;H;68:9c9G;L89;n;m9m89;D8Ko8:bbbbf:8tZ9m836ZS:2AZL;zPZZ818EZ9e:lxZ;U98F8:819E;68:FFuuFFuuFFuuFFuFFFuFFFuFbc;mqkzebbbebbbdbbb9G:vbb";
var wasmpack = new Uint8Array([
32,
0,
65,
2,
1,
106,
34,
33,
3,
128,
11,
4,
13,
64,
6,
253,
10,
7,
15,
116,
127,
5,
8,
12,
40,
16,
19,
54,
20,
9,
27,
255,
113,
17,
42,
67,
24,
23,
146,
148,
18,
14,
22,
45,
70,
69,
56,
114,
101,
21,
25,
63,
75,
136,
108,
28,
118,
29,
73,
115
]);
if (typeof WebAssembly !== "object") {
return {
supported: false
};
}
var instance;
var ready = WebAssembly.instantiate(unpack(wasm), {}).then(function(result) {
instance = result.instance;
instance.exports.__wasm_call_ctors();
instance.exports.meshopt_encodeVertexVersion(0);
instance.exports.meshopt_encodeIndexVersion(1);
});
function unpack(data) {
var result = new Uint8Array(data.length);
for (var i = 0; i < data.length; ++i) {
var ch = data.charCodeAt(i);
result[i] = ch > 96 ? ch - 97 : ch > 64 ? ch - 39 : ch + 4;
}
var write = 0;
for (var i = 0; i < data.length; ++i) {
result[write++] = result[i] < 60 ? wasmpack[result[i]] : (result[i] - 60) * 64 + result[++i];
}
return result.buffer.slice(0, write);
}
function assert(cond) {
if (!cond) {
throw new Error("Assertion failed");
}
}
function bytes(view) {
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
}
function reorder(fun, indices, vertices, optf) {
var sbrk = instance.exports.sbrk;
var ip = sbrk(indices.length * 4);
var rp = sbrk(vertices * 4);
var heap = new Uint8Array(instance.exports.memory.buffer);
var indices8 = bytes(indices);
heap.set(indices8, ip);
if (optf) {
optf(ip, ip, indices.length, vertices);
}
var unique = fun(rp, ip, indices.length, vertices);
heap = new Uint8Array(instance.exports.memory.buffer);
var remap = new Uint32Array(vertices);
new Uint8Array(remap.buffer).set(heap.subarray(rp, rp + vertices * 4));
indices8.set(heap.subarray(ip, ip + indices.length * 4));
sbrk(ip - sbrk(0));
for (var i = 0; i < indices.length; ++i) indices[i] = remap[indices[i]];
return [remap, unique];
}
function spatialsort(fun, positions, count, stride) {
var sbrk = instance.exports.sbrk;
var ip = sbrk(count * 4);
var sp = sbrk(count * stride);
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(positions), sp);
fun(ip, sp, count, stride);
heap = new Uint8Array(instance.exports.memory.buffer);
var remap = new Uint32Array(count);
new Uint8Array(remap.buffer).set(heap.subarray(ip, ip + count * 4));
sbrk(ip - sbrk(0));
return remap;
}
function encode(fun, bound, source, count, size, level, version2) {
var sbrk = instance.exports.sbrk;
var tp = sbrk(bound);
var sp = sbrk(count * size);
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(source), sp);
var res = fun(tp, bound, sp, count, size, level, version2);
var target = new Uint8Array(res);
target.set(heap.subarray(tp, tp + res));
sbrk(tp - sbrk(0));
return target;
}
function maxindex(source) {
var result = 0;
for (var i = 0; i < source.length; ++i) {
var index = source[i];
result = result < index ? index : result;
}
return result;
}
function index32(source, size) {
assert(size == 2 || size == 4);
if (size == 4) {
return new Uint32Array(source.buffer, source.byteOffset, source.byteLength / 4);
} else {
var view = new Uint16Array(source.buffer, source.byteOffset, source.byteLength / 2);
return new Uint32Array(view);
}
}
function filter(fun, source, count, stride, bits, insize, mode2) {
var sbrk = instance.exports.sbrk;
var tp = sbrk(count * stride);
var sp = sbrk(count * insize);
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(source), sp);
fun(tp, count, stride, bits, sp, mode2);
var target = new Uint8Array(count * stride);
target.set(heap.subarray(tp, tp + count * stride));
sbrk(tp - sbrk(0));
return target;
}
return {
ready,
supported: true,
reorderMesh: function(indices, triangles, optsize) {
var optf = triangles ? optsize ? instance.exports.meshopt_optimizeVertexCacheStrip : instance.exports.meshopt_optimizeVertexCache : void 0;
return reorder(instance.exports.meshopt_optimizeVertexFetchRemap, indices, maxindex(indices) + 1, optf);
},
reorderPoints: function(positions, positions_stride) {
assert(positions instanceof Float32Array);
assert(positions.length % positions_stride == 0);
assert(positions_stride >= 3);
return spatialsort(instance.exports.meshopt_spatialSortRemap, positions, positions.length / positions_stride, positions_stride * 4);
},
encodeVertexBuffer: function(source, count, size) {
assert(size > 0 && size <= 256);
assert(size % 4 == 0);
var bound = instance.exports.meshopt_encodeVertexBufferBound(count, size);
return encode(instance.exports.meshopt_encodeVertexBuffer, bound, source, count, size);
},
encodeVertexBufferLevel: function(source, count, size, level, version2) {
assert(size > 0 && size <= 256);
assert(size % 4 == 0);
assert(level >= 0 && level <= 3);
assert(version2 === void 0 || version2 == 0 || version2 == 1);
var bound = instance.exports.meshopt_encodeVertexBufferBound(count, size);
return encode(instance.exports.meshopt_encodeVertexBufferLevel, bound, source, count, size, level, version2 || 0);
},
encodeIndexBuffer: function(source, count, size) {
assert(size == 2 || size == 4);
assert(count % 3 == 0);
var indices = index32(source, size);
var bound = instance.exports.meshopt_encodeIndexBufferBound(count, maxindex(indices) + 1);
return encode(instance.exports.meshopt_encodeIndexBuffer, bound, indices, count, 4);
},
encodeIndexSequence: function(source, count, size) {
assert(size == 2 || size == 4);
var indices = index32(source, size);
var bound = instance.exports.meshopt_encodeIndexSequenceBound(count, maxindex(indices) + 1);
return encode(instance.exports.meshopt_encodeIndexSequence, bound, indices, count, 4);
},
encodeGltfBuffer: function(source, count, size, mode2) {
var table2 = {
ATTRIBUTES: this.encodeVertexBuffer,
TRIANGLES: this.encodeIndexBuffer,
INDICES: this.encodeIndexSequence
};
assert(table2[mode2]);
return table2[mode2](source, count, size);
},
encodeFilterOct: function(source, count, stride, bits) {
assert(stride == 4 || stride == 8);
assert(bits >= 1 && bits <= 16);
return filter(instance.exports.meshopt_encodeFilterOct, source, count, stride, bits, 16);
},
encodeFilterQuat: function(source, count, stride, bits) {
assert(stride == 8);
assert(bits >= 4 && bits <= 16);
return filter(instance.exports.meshopt_encodeFilterQuat, source, count, stride, bits, 16);
},
encodeFilterExp: function(source, count, stride, bits, mode2) {
assert(stride > 0 && stride % 4 == 0);
assert(bits >= 1 && bits <= 24);
var table2 = {
Separate: 0,
SharedVector: 1,
SharedComponent: 2,
Clamped: 3
};
return filter(instance.exports.meshopt_encodeFilterExp, source, count, stride, bits, stride, mode2 ? table2[mode2] : 1);
},
encodeFilterColor: function(source, count, stride, bits) {
assert(stride == 4 || stride == 8);
assert(bits >= 2 && bits <= 16);
return filter(instance.exports.meshopt_encodeFilterColor, source, count, stride, bits, 16);
}
};
})();
// node_modules/meshoptimizer/meshopt_decoder.module.js
var import_InlineWorkers469 = __toESM(require_InlineWorkers());
var MeshoptDecoder = (function() {
var wasm_base = "b9H79Tebbbe8Fv9Gbb9Gvuuuuueu9Giuuub9Geueu9Giuuueuixkbeeeddddillviebeoweuec:W:Odkr;Neqo9TW9T9VV95dbH9F9F939H79T9F9J9H229F9Jt9VV7bb8A9TW79O9V9Wt9F9KW9J9V9KW9wWVtW949c919M9MWVbeY9TW79O9V9Wt9F9KW9J9V9KW69U9KW949c919M9MWVbdE9TW79O9V9Wt9F9KW9J9V9KW69U9KW949tWG91W9U9JWbiL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9p9JtblK9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9r919HtbvL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWVT949WboY9TW79O9V9Wt9F9KW9J9V9KWS9P2tWVJ9V29VVbrl79IV9Rbwq;BZkdbk;jYi5ud9:du8Jjjjjbcj;kb9Rgv8Kjjjjbc9:hodnalTmbcuhoaiRbbgrc;WeGc:Ge9hmbarcsGgwce0mbc9:hoalcufadcd4cbawEgDadfgrcKcaawEgqaraq0Egk6mbaicefhxcj;abad9Uc;WFbGcjdadca0EhmaialfgPar9Rgoadfhsavaoadz:jjjjbgzceVhHcbhOdndninaeaO9nmeaPax9RaD6mdamaeaO9RaOamfgoae6EgAcsfglc9WGhCabaOad2fhXaAcethQaxaDfhiaOaeaoaeao6E9RhLalcl4cifcd4hKazcj;cbfaAfhYcbh8AazcjdfhEaHh3incbhodnawTmbaxa8Acd4fRbbhokaocFeGh5cbh8Eazcj;cbfhqinaih8Fdndndndna5a8Ecet4ciGgoc9:fPdebdkaPa8F9RaA6mrazcj;cbfa8EaA2fa8FaAz:jjjjb8Aa8FaAfhixdkazcj;cbfa8EaA2fcbaAz:kjjjb8Aa8FhixekaPa8F9RaK6mva8FaKfhidnaCTmbaPai9RcK6mbaocdtc:q1jjbfcj1jjbawEhaczhrcbhlinargoc9Wfghaqfhrdndndndndndnaaa8Fahco4fRbbalcoG4ciGcdtfydbPDbedvivvvlvkar9cb83bbarcwf9cb83bbxlkarcbaiRbdai8Xbb9c:c:qj:bw9:9c:q;c1:I1e:d9c:b:c:e1z9:gg9cjjjjjz:dg8J9qE86bbaqaofgrcGfag9c8F1:NghcKtc8F91aicdfa8J9c8N1:Nfg8KRbbG86bbarcVfcba8KahcjeGcr4fghRbbag9cjjjjjl:dg8J9qE86bbarc7fcbaha8J9c8L1:NfghRbbag9cjjjjjd:dg8J9qE86bbarctfcbaha8J9c8K1:NfghRbbag9cjjjjje:dg8J9qE86bbarc91fcbaha8J9c8J1:NfghRbbag9cjjjj;ab:dg8J9qE86bbarc4fcbaha8J9cg1:NfghRbbag9cjjjja:dg8J9qE86bbarc93fcbaha8J9ch1:NfghRbbag9cjjjjz:dgg9qE86bbarc94fcbahag9ca1:NfghRbbai8Xbe9c:c:qj:bw9:9c:q;c1:I1e:d9c:b:c:e1z9:gg9cjjjjjz:dg8J9qE86bbarc95fag9c8F1:NgicKtc8F91aha8J9c8N1:NfghRbbG86bbarc96fcbahaicjeGcr4fgiRbbag9cjjjjjl:dg8J9qE86bbarc97fcbaia8J9c8L1:NfgiRbbag9cjjjjjd:dg8J9qE86bbarc98fcbaia8J9c8K1:NfgiRbbag9cjjjjje:dg8J9qE86bbarc99fcbaia8J9c8J1:NfgiRbbag9cjjjj;ab:dg8J9qE86bbarc9:fcbaia8J9cg1:NfgiRbbag9cjjjja:dg8J9qE86bbarcufcbaia8J9ch1:NfgiRbbag9cjjjjz:dgg9qE86bbaiag9ca1:NfhixikaraiRblaiRbbghco4g8Ka8KciSg8KE86bbaqaofgrcGfaiclfa8Kfg8KRbbahcl4ciGg8La8LciSg8LE86bbarcVfa8Ka8Lfg8KRbbahcd4ciGg8La8LciSg8LE86bbarc7fa8Ka8Lfg8KRbbahciGghahciSghE86bbarctfa8Kahfg8KRbbaiRbeghco4g8La8LciSg8LE86bbarc91fa8Ka8Lfg8KRbbahcl4ciGg8La8LciSg8LE86bbarc4fa8Ka8Lfg8KRbbahcd4ciGg8La8LciSg8LE86bbarc93fa8Ka8Lfg8KRbbahciGghahciSghE86bbarc94fa8Kahfg8KRbbaiRbdghco4g8La8LciSg8LE86bbarc95fa8Ka8Lfg8KRbbahcl4ciGg8La8LciSg8LE86bbarc96fa8Ka8Lfg8KRbbahcd4ciGg8La8LciSg8LE86bbarc97fa8Ka8Lfg8KRbbahciGghahciSghE86bbarc98fa8KahfghRbbaiRbigico4g8Ka8KciSg8KE86bbarc99faha8KfghRbbaicl4ciGg8Ka8KciSg8KE86bbarc9:faha8KfghRbbaicd4ciGg8Ka8KciSg8KE86bbarcufaha8KfgrRbbaiciGgiaiciSgiE86bbaraifhixdkaraiRbwaiRbbghcl4g8Ka8KcsSg8KE86bbaqaofgrcGfaicwfa8Kfg8KRbbahcsGghahcsSghE86bbarcVfa8KahfghRbbaiRbeg8Kcl4g8La8LcsSg8LE86bbarc7faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarctfaha8KfghRbbaiRbdg8Kcl4g8La8LcsSg8LE86bbarc91faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarc4faha8KfghRbbaiRbig8Kcl4g8La8LcsSg8LE86bbarc93faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarc94faha8KfghRbbaiRblg8Kcl4g8La8LcsSg8LE86bbarc95faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarc96faha8KfghRbbaiRbvg8Kcl4g8La8LcsSg8LE86bbarc97faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarc98faha8KfghRbbaiRbog8Kcl4g8La8LcsSg8LE86bbarc99faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarc9:faha8KfghRbbaiRbrgicl4g8Ka8KcsSg8KE86bbarcufaha8KfgrRbbaicsGgiaicsSgiE86bbaraifhixekarai8Pbb83bbarcwfaicwf8Pbb83bbaiczfhikdnaoaC9pmbalcdfhlaoczfhraPai9RcL0mekkaoaC6moaimexokaCmva8FTmvkaqaAfhqa8Ecefg8Ecl9hmbkdndndndnawTmbasa8Acd4fRbbgociGPlbedrbkaATmdaza8Afh8Fazcj;cbfhhcbh8EaEhaina8FRbbhraahocbhlinaoahalfRbbgqce4cbaqceG9R7arfgr86bbaoadfhoaAalcefgl9hmbkaacefhaa8Fcefh8FahaAfhha8Ecefg8Ecl9hmbxikkaATmeaza8Afhaazcj;cbfhhcbhoceh8EaYh8FinaEaofhlaa8Vbbhrcbhoinala8FaofRbbcwtahaofRbbgqVc;:FiGce4cbaqceG9R7arfgr87bbaladfhlaLaocefgofmbka8FaQfh8FcdhoaacdfhaahaQfhha8EceGhlcbh8EalmbxdkkaATmbcbaocl49Rh8Eaza8AfRbbhqcwhoa3hlinalRbbaotaqVhqalcefhlaocwfgoca9hmbkcbhhaEh8FaYhainazcj;cbfahfRbbhrcwhoaahlinalRbbaotarVhralaAfhlaocwfgoca9hmbkara8E93aq7hqcbhoa8Fhlinalaqao486bbalcefhlaocwfgoca9hmbka8Fadfh8FaacefhaahcefghaA9hmbkkaEclfhEa3clfh3a8Aclfg8Aad6mbkaXazcjdfaAad2z:jjjjb8AazazcjdfaAcufad2fadz:jjjjb8AaAaOfhOaihxaimbkc9:hoxdkcbc99aPax9RakSEhoxekc9:hokavcj;kbf8Kjjjjbaok:XseHu8Jjjjjbc;ae9Rgv8Kjjjjbc9:hodnaeci9UgrcHfal0mbcuhoaiRbbgwc;WeGc;Ge9hmbawcsGgDce0mbavc;abfcFecjez:kjjjb8AavcUf9cu83ibavc8Wf9cu83ibavcyf9cu83ibavcaf9cu83ibavcKf9cu83ibavczf9cu83ibav9cu83iwav9cu83ibaialfc9WfhqaicefgwarfhldnaeTmbcmcsaDceSEhkcbhxcbhmcbhrcbhicbhoindnalaq9nmbc9:hoxikdndnawRbbgDc;Ve0mbavc;abfaoaDcu7gPcl4fcsGcitfgsydlhzasydbhHdndnaDcsGgsak9pmbavaiaPfcsGcdtfydbaxasEhDaxasTgOfhxxekdndnascsSmbcehOasc987asamffcefhDxekalcefhDal8SbbgscFeGhPdndnascu9mmbaDhlxekalcvfhlaPcFbGhPcrhsdninaD8SbbgOcFbGastaPVhPaOcu9kmeaDcefhDascrfgsc8J9hmbxdkkaDcefhlkcehOaPce4cbaPceG9R7amfhDkaDhmkavc;abfaocitfgsaDBdbasazBdlavaicdtfaDBdbavc;abfaocefcsGcitfgsaHBdbasaDBdlaocdfhoaOaifhidnadcd9hmbabarcetfgsaH87ebasclfaD87ebascdfaz87ebxdkabarcdtfgsaHBdbascwfaDBdbasclfazBdbxekdnaDcpe0mbaxcefgOavaiaqaDcsGfRbbgscl49RcsGcdtfydbascz6gPEhDavaias9RcsGcdtfydbaOaPfgzascsGgOEhsaOThOdndnadcd9hmbabarcetfgHax87ebaHclfas87ebaHcdfaD87ebxekabarcdtfgHaxBdbaHcwfasBdbaHclfaDBdbkavaicdtfaxBdbavc;abfaocitfgHaDBdbaHaxBdlavaicefgicsGcdtfaDBdbavc;abfaocefcsGcitfgHasBdbaHaDBdlavaiaPfgicsGcdtfasBdbavc;abfaocdfcsGcitfgDaxBdbaDasBdlaocifhoaiaOfhiazaOfhxxekaxcbalRbbgHEgAaDc;:eSgDfhzaHcsGhCaHcl4hXdndnaHcs0mbazcefhOxekazhOavaiaX9RcsGcdtfydbhzkdndnaCmbaOcefhxxekaOhxavaiaH9RcsGcdtfydbhOkdndnaDTmbalcefhDxekalcdfhDal8SbegPcFeGhsdnaPcu9kmbalcofhAascFbGhscrhldninaD8SbbgPcFbGaltasVhsaPcu9kmeaDcefhDalcrfglc8J9hmbkaAhDxekaDcefhDkasce4cbasceG9R7amfgmhAkdndnaXcsSmbaDhsxekaDcefhsaD8SbbglcFeGhPdnalcu9kmbaDcvfhzaPcFbGhPcrhldninas8SbbgDcFbGaltaPVhPaDcu9kmeascefhsalcrfglc8J9hmbkazhsxekascefhskaPce4cbaPceG9R7amfgmhzkdndnaCcsSmbashlxekascefhlas8SbbgDcFeGhPdnaDcu9kmbascvfhOaPcFbGhPcrhDdninal8SbbgscFbGaDtaPVhPascu9kmealcefhlaDcrfgDc8J9hmbkaOhlxekalcefhlkaPce4cbaPceG9R7amfgmhOkdndnadcd9hmbabarcetfgDaA87ebaDclfaO87ebaDcdfaz87ebxekabarcdtfgDaABdbaDcwfaOBdbaDclfazBdbkavc;abfaocitfgDazBdbaDaABdlavaicdtfaABdbavc;abfaocefcsGcitfgDaOBdbaDazBdlavaicefgicsGcdtfazBdbavc;abfaocdfcsGcitfgDaABdbaDaOBdlavaiaHcz6aXcsSVfgicsGcdtfaOBdbaiaCTaCcsSVfhiaocifhokawcefhwaocsGhoaicsGhiarcifgrae6mbkkcbc99alaqSEhokavc;aef8Kjjjjbaok:clevu8Jjjjjbcz9Rhvdnaecvfal9nmbc9:skdnaiRbbc;:eGc;qeSmbcuskav9cb83iwaicefhoaialfc98fhrdnaeTmbdnadcdSmbcbhwindnaoar6mbc9:skaocefhlao8SbbgicFeGhddndnaicu9mmbalhoxekaocvfhoadcFbGhdcrhidninal8SbbgDcFbGaitadVhdaDcu9kmealcefhlaicrfgic8J9hmbxdkkalcefhokabawcdtfadc8Etc8F91adcd47avcwfadceGcdtVglydbfgiBdbalaiBdbawcefgwae9hmbxdkkcbhwindnaoar6mbc9:skaocefhlao8SbbgicFeGhddndnaicu9mmbalhoxekaocvfhoadcFbGhdcrhidninal8SbbgDcFbGaitadVhdaDcu9kmealcefhlaicrfgic8J9hmbxdkkalcefhokabawcetfadc8Etc8F91adcd47avcwfadceGcdtVglydbfgi87ebalaiBdbawcefgwae9hmbkkcbc99aoarSEk:Lvoeue99dud99eud99dndnadcl9hmbaeTmeindndnabcdfgd8Sbb:Yab8Sbbgi:Ygl:l:tabcefgv8Sbbgo:Ygr:l:tgwJbb;:9cawawNJbbbbawawJbbbb9GgDEgq:mgkaqaicb9iEalMgwawNakaqaocb9iEarMgqaqNMM:r:vglNJbbbZJbbb:;aDEMgr:lJbbb9p9DTmbar:Ohixekcjjjj94hikadai86bbdndnaqalNJbbbZJbbb:;aqJbbbb9GEMgq:lJbbb9p9DTmbaq:Ohdxekcjjjj94hdkavad86bbdndnawalNJbbbZJbbb:;awJbbbb9GEMgw:lJbbb9p9DTmbaw:Ohdxekcjjjj94hdkabad86bbabclfhbaecufgembxdkkaeTmbindndnabclfgd8Ueb:Yab8Uebgi:Ygl:l:tabcdfgv8Uebgo:Ygr:l:tgwJb;:FSawawNJbbbbawawJbbbb9GgDEgq:mgkaqaicb9iEalMgwawNakaqaocb9iEarMgqaqNMM:r:vglNJbbbZJbbb:;aDEMgr:lJbbb9p9DTmbar:Ohixekcjjjj94hikadai87ebdndnaqalNJbbbZJbbb:;aqJbbbb9GEMgq:lJbbb9p9DTmbaq:Ohdxekcjjjj94hdkavad87ebdndnawalNJbbbZJbbb:;awJbbbb9GEMgw:lJbbb9p9DTmbaw:Ohdxekcjjjj94hdkabad87ebabcwfhbaecufgembkkk;oiliui99iue99dnaeTmbcbhiabhlindndnJ;Zl81Zalcof8UebgvciV:Y:vgoal8Ueb:YNgrJb;:FSNJbbbZJbbb:;arJbbbb9GEMgw:lJbbb9p9DTmbaw:OhDxekcjjjj94hDkalclf8Uebhqalcdf8UebhkabaiavcefciGfcetfaD87ebdndnaoak:YNgwJb;:FSNJbbbZJbbb:;awJbbbb9GEMgx:lJbbb9p9DTmbax:OhDxekcjjjj94hDkabaiavciGfgkcd7cetfaD87ebdndnaoaq:YNgoJb;:FSNJbbbZJbbb:;aoJbbbb9GEMgx:lJbbb9p9DTmbax:OhDxekcjjjj94hDkabaiavcufciGfcetfaD87ebdndnJbbjZararN:tawawN:taoaoN:tgrJbbbbarJbbbb9GE:rJb;:FSNJbbbZMgr:lJbbb9p9DTmbar:Ohvxekcjjjj94hvkabakcetfav87ebalcwfhlaiclfhiaecufgembkkk9mbdnadcd4ae2gdTmbinababydbgecwtcw91:Yaece91cjjj98Gcjjj;8if::NUdbabclfhbadcufgdmbkkk:Tvirud99eudndnadcl9hmbaeTmeindndnabRbbgiabcefgl8Sbbgvabcdfgo8Sbbgrf9R:YJbbuJabcifgwRbbgdce4adVgDcd4aDVgDcl4aDVgD:Z:vgqNJbbbZMgk:lJbbb9p9DTmbak:Ohxxekcjjjj94hxkaoax86bbdndnaraif:YaqNJbbbZMgk:lJbbb9p9DTmbak:Ohoxekcjjjj94hokalao86bbdndnavaifar9R:YaqNJbbbZMgk:lJbbb9p9DTmbak:Ohixekcjjjj94hikabai86bbdndnaDadcetGadceGV:ZaqNJbbbZMgq:lJbbb9p9DTmbaq:Ohdxekcjjjj94hdkawad86bbabclfhbaecufgembxdkkaeTmbindndnab8Vebgiabcdfgl8Uebgvabclfgo8Uebgrf9R:YJbFu9habcofgw8Vebgdce4adVgDcd4aDVgDcl4aDVgDcw4aDVgD:Z:vgqNJbbbZMgk:lJbbb9p9DTmbak:Ohxxekcjjjj94hxkaoax87ebdndnaraif:YaqNJbbbZMgk:lJbbb9p9DTmbak:Ohoxekcjjjj94hokalao87ebdndnavaifar9R:YaqNJbbbZMgk:lJbbb9p9DTmbak:Ohixekcjjjj94hikabai87ebdndnaDadcetGadceGV:ZaqNJbbbZMgq:lJbbb9p9DTmbaq:Ohdxekcjjjj94hdkawad87ebabcwfhbaecufgembkkk9teiucbcbyd:K1jjbgeabcifc98GfgbBd:K1jjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaik;teeeudndnaeabVciGTmbabhixekdndnadcz9pmbabhixekabhiinaiaeydbBdbaiaeydlBdlaiaeydwBdwaiaeydxBdxaeczfheaiczfhiadc9Wfgdcs0mbkkadcl6mbinaiaeydbBdbaeclfheaiclfhiadc98fgdci0mbkkdnadTmbinaiaeRbb86bbaicefhiaecefheadcufgdmbkkabk:3eedudndnabciGTmbabhixekaecFeGc:b:c:ew2hldndnadcz9pmbabhixekabhiinaialBdxaialBdwaialBdlaialBdbaiczfhiadc9Wfgdcs0mbkkadcl6mbinaialBdbaiclfhiadc98fgdci0mbkkdnadTmbinaiae86bbaicefhiadcufgdmbkkabkk81dbcjwk8Kbbbbdbbblbbbwbbbbbbbebbbdbbblbbbwbbbbc:Kwkl8WNbb";
var wasm_simd = "b9H79TebbbeKl9Gbb9Gvuuuuueu9Giuuub9Geueuixkbbebeeddddilve9Weeeviebeoweuec:q:6dkr;Neqo9TW9T9VV95dbH9F9F939H79T9F9J9H229F9Jt9VV7bb8A9TW79O9V9Wt9F9KW9J9V9KW9wWVtW949c919M9MWVbdY9TW79O9V9Wt9F9KW9J9V9KW69U9KW949c919M9MWVblE9TW79O9V9Wt9F9KW9J9V9KW69U9KW949tWG91W9U9JWbvL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9p9JtboK9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9r919HtbrL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWVT949WbwY9TW79O9V9Wt9F9KW9J9V9KWS9P2tWVJ9V29VVbDl79IV9Rbqq;Ctklbzik9:evu8Jjjjjbcz9Rhbcbheincbhdcbhiinabcwfadfaicjuaead4ceGglE86bbaialfhiadcefgdcw9hmbkaec:q:yjjbfai86bbaecitc:q1jjbfab8Piw83ibaecefgecjd9hmbkk:183lYud97dur978Jjjjjbcj;kb9Rgv8Kjjjjbc9:hodnalTmbcuhoaiRbbgrc;WeGc:Ge9hmbarcsGgwce0mbc9:hoalcufadcd4cbawEgDadfgrcKcaawEgqaraq0Egk6mbaicefhxavaialfgmar9Rgoad;8qbbcj;abad9Uc;WFbGcjdadca0EhPdndndnadTmbaoadfhscbhzinaeaz9nmdamax9RaD6miabazad2fhHaxaDfhOaPaeaz9RazaPfae6EgAcsfgocl4cifcd4hCavcj;cbfaoc9WGgXcetfhQavcj;cbfaXci2fhLavcj;cbfaXfhKcbhYaoc;ab6h8AincbhodnawTmbaxaYcd4fRbbhokaocFeGhEcbh3avcj;cbfh5indndndndnaEa3cet4ciGgoc9:fPdebdkamaO9RaX6mwavcj;cbfa3aX2faOaX;8qbbaOaAfhOxdkavcj;cbfa3aX2fcbaX;8kbxekamaO9RaC6moaoclVcbawEhraOaCfhocbhidna8Ambamao9Rc;Gb6mbcbhlina5alfhidndndndndndnaOalco4fRbbgqciGarfPDbedibledibkaipxbbbbbbbbbbbbbbbbpklbxlkaiaopbblaopbbbg8Eclp:mea8EpmbzeHdOiAlCvXoQrLg8Ecdp:mea8EpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9og8Fpxiiiiiiiiiiiiiiiip8Jg8Ep5b9cjF;8;4;W;G;ab9:9cU1:Ngacitc:q1jjbfpbibaac:q:yjjbfRbbgapsa8Ep5e9cjF;8;4;W;G;ab9:9cU1:Nghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPa8Fa8Ep9spklbaaaoclffahc:q:yjjbfRbbfhoxikaiaopbbwaopbbbg8Eclp:mea8EpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9og8Fpxssssssssssssssssp8Jg8Ep5b9cjF;8;4;W;G;ab9:9cU1:Ngacitc:q1jjbfpbibaac:q:yjjbfRbbgapsa8Ep5e9cjF;8;4;W;G;ab9:9cU1:Nghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPa8Fa8Ep9spklbaaaocwffahc:q:yjjbfRbbfhoxdkaiaopbbbpklbaoczfhoxekaiaopbbdaoRbbgacitc:q1jjbfpbibaac:q:yjjbfRbbgapsaoRbeghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPpklbaaaocdffahc:q:yjjbfRbbfhokdndndndndndnaqcd4ciGarfPDbedibledibkaiczfpxbbbbbbbbbbbbbbbbpklbxlkaiczfaopbblaopbbbg8Eclp:mea8EpmbzeHdOiAlCvXoQrLg8Ecdp:mea8EpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9og8Fpxiiiiiiiiiiiiiiiip8Jg8Ep5b9cjF;8;4;W;G;ab9:9cU1:Ngacitc:q1jjbfpbibaac:q:yjjbfRbbgapsa8Ep5e9cjF;8;4;W;G;ab9:9cU1:Nghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPa8Fa8Ep9spklbaaaoclffahc:q:yjjbfRbbfhoxikaiczfaopbbwaopbbbg8Eclp:mea8EpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9og8Fpxssssssssssssssssp8Jg8Ep5b9cjF;8;4;W;G;ab9:9cU1:Ngacitc:q1jjbfpbibaac:q:yjjbfRbbgapsa8Ep5e9cjF;8;4;W;G;ab9:9cU1:Nghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPa8Fa8Ep9spklbaaaocwffahc:q:yjjbfRbbfhoxdkaiczfaopbbbpklbaoczfhoxekaiczfaopbbdaoRbbgacitc:q1jjbfpbibaac:q:yjjbfRbbgapsaoRbeghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPpklbaaaocdffahc:q:yjjbfRbbfhokdndndndndndnaqcl4ciGarfPDbedibledibkaicafpxbbbbbbbbbbbbbbbbpklbxlkaicafaopbblaopbbbg8Eclp:mea8EpmbzeHdOiAlCvXoQrLg8Ecdp:mea8EpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9og8Fpxiiiiiiiiiiiiiiiip8Jg8Ep5b9cjF;8;4;W;G;ab9:9cU1:Ngacitc:q1jjbfpbibaac:q:yjjbfRbbgapsa8Ep5e9cjF;8;4;W;G;ab9:9cU1:Nghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPa8Fa8Ep9spklbaaaoclffahc:q:yjjbfRbbfhoxikaicafaopbbwaopbbbg8Eclp:mea8EpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9og8Fpxssssssssssssssssp8Jg8Ep5b9cjF;8;4;W;G;ab9:9cU1:Ngacitc:q1jjbfpbibaac:q:yjjbfRbbgapsa8Ep5e9cjF;8;4;W;G;ab9:9cU1:Nghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPa8Fa8Ep9spklbaaaocwffahc:q:yjjbfRbbfhoxdkaicafaopbbbpklbaoczfhoxekaicafaopbbdaoRbbgacitc:q1jjbfpbibaac:q:yjjbfRbbgapsaoRbeghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPpklbaaaocdffahc:q:yjjbfRbbfhokdndndndndndnaqco4arfPDbedibledibkaic8Wfpxbbbbbbbbbbbbbbbbpklbxlkaic8Wfaopbblaopbbbg8Eclp:mea8EpmbzeHdOiAlCvXoQrLg8Ecdp:mea8EpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9og8Fpxiiiiiiiiiiiiiiiip8Jg8Ep5b9cjF;8;4;W;G;ab9:9cU1:Ngicitc:q1jjbfpbibaic:q:yjjbfRbbgipsa8Ep5e9cjF;8;4;W;G;ab9:9cU1:Ngqcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPa8Fa8Ep9spklbaiaoclffaqc:q:yjjbfRbbfhoxikaic8Wfaopbbwaopbbbg8Eclp:mea8EpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9og8Fpxssssssssssssssssp8Jg8Ep5b9cjF;8;4;W;G;ab9:9cU1:Ngicitc:q1jjbfpbibaic:q:yjjbfRbbgipsa8Ep5e9cjF;8;4;W;G;ab9:9cU1:Ngqcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPa8Fa8Ep9spklbaiaocwffaqc:q:yjjbfRbbfhoxdkaic8Wfaopbbbpklbaoczfhoxekaic8WfaopbbdaoRbbgicitc:q1jjbfpbibaic:q:yjjbfRbbgipsaoRbegqcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPpklbaiaocdffaqc:q:yjjbfRbbfhokalc;abfhialcjefaX0meaihlamao9Rc;Fb0mbkkdnaiaX9pmbaici4hlinamao9RcK6mwa5aifhqdndndndndndnaOaico4fRbbalcoG4ciGarfPDbedibledibkaqpxbbbbbbbbbbbbbbbbpkbbxlkaqaopbblaopbbbg8Eclp:mea8EpmbzeHdOiAlCvXoQrLg8Ecdp:mea8EpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9og8Fpxiiiiiiiiiiiiiiiip8Jg8Ep5b9cjF;8;4;W;G;ab9:9cU1:Ngacitc:q1jjbfpbibaac:q:yjjbfRbbgapsa8Ep5e9cjF;8;4;W;G;ab9:9cU1:Nghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPa8Fa8Ep9spkbbaaaoclffahc:q:yjjbfRbbfhoxikaqaopbbwaopbbbg8Eclp:mea8EpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9og8Fpxssssssssssssssssp8Jg8Ep5b9cjF;8;4;W;G;ab9:9cU1:Ngacitc:q1jjbfpbibaac:q:yjjbfRbbgapsa8Ep5e9cjF;8;4;W;G;ab9:9cU1:Nghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPa8Fa8Ep9spkbbaaaocwffahc:q:yjjbfRbbfhoxdkaqaopbbbpkbbaoczfhoxekaqaopbbdaoRbbgacitc:q1jjbfpbibaac:q:yjjbfRbbgapsaoRbeghcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPpkbbaaaocdffahc:q:yjjbfRbbfhokalcdfhlaiczfgiaX6mbkkaohOaoTmoka5aXfh5a3cefg3cl9hmbkdndndndnawTmbasaYcd4fRbbglciGPlbedwbkaXTmdavcjdfaYfhlavaYfpbdbhgcbhoinalavcj;cbfaofpblbg8JaKaofpblbg8KpmbzeHdOiAlCvXoQrLg8LaQaofpblbg8MaLaofpblbg8NpmbzeHdOiAlCvXoQrLgypmbezHdiOAlvCXorQLg8Ecep9Ta8Epxeeeeeeeeeeeeeeeeg8Fp9op9Hp9rg8Eagp9Uggp9Abbbaladfglaga8Ea8Epmlvorlvorlvorlvorp9Uggp9Abbbaladfglaga8Ea8EpmwDqkwDqkwDqkwDqkp9Uggp9Abbbaladfglaga8Ea8EpmxmPsxmPsxmPsxmPsp9Uggp9Abbbaladfglaga8LaypmwDKYqk8AExm35Ps8E8Fg8Ecep9Ta8Ea8Fp9op9Hp9rg8Ep9Uggp9Abbbaladfglaga8Ea8Epmlvorlvorlvorlvorp9Uggp9Abbbaladfglaga8Ea8EpmwDqkwDqkwDqkwDqkp9Uggp9Abbbaladfglaga8Ea8EpmxmPsxmPsxmPsxmPsp9Uggp9Abbbaladfglaga8Ja8KpmwKDYq8AkEx3m5P8Es8Fg8Ja8Ma8NpmwKDYq8AkEx3m5P8Es8Fg8KpmbezHdiOAlvCXorQLg8Ecep9Ta8Ea8Fp9op9Hp9rg8Ep9Uggp9Abbbaladfglaga8Ea8Epmlvorlvorlvorlvorp9Uggp9Abbbaladfglaga8Ea8EpmwDqkwDqkwDqkwDqkp9Uggp9Abbbaladfglaga8Ea8EpmxmPsxmPsxmPsxmPsp9Uggp9Abbbaladfglaga8Ja8KpmwDKYqk8AExm35Ps8E8Fg8Ecep9Ta8Ea8Fp9op9Hp9rg8Ep9Ug8Fp9Abbbaladfgla8Fa8Ea8Epmlvorlvorlvorlvorp9Ug8Fp9Abbbaladfgla8Fa8Ea8EpmwDqkwDqkwDqkwDqkp9Ug8Fp9Abbbaladfgla8Fa8Ea8EpmxmPsxmPsxmPsxmPsp9Uggp9AbbbaladfhlaoczfgoaX6mbxikkaXTmeavcjdfaYfhlavaYfpbdbhgcbhoinalavcj;cbfaofpblbg8JaKaofpblbg8KpmbzeHdOiAlCvXoQrLg8LaQaofpblbg8MaLaofpblbg8NpmbzeHdOiAlCvXoQrLgypmbezHdiOAlvCXorQLg8Ecep:nea8Epxebebebebebebebebg8Fp9op:bep9rg8Eagp:oeggp9Abbbaladfglaga8Ea8Epmlvorlvorlvorlvorp:oeggp9Abbbaladfglaga8Ea8EpmwDqkwDqkwDqkwDqkp:oeggp9Abbbaladfglaga8Ea8EpmxmPsxmPsxmPsxmPsp:oeggp9Abbbaladfglaga8LaypmwDKYqk8AExm35Ps8E8Fg8Ecep:nea8Ea8Fp9op:bep9rg8Ep:oeggp9Abbbaladfglaga8Ea8Epmlvorlvorlvorlvorp:oeggp9Abbbaladfglaga8Ea8EpmwDqkwDqkwDqkwDqkp:oeggp9Abbbaladfglaga8Ea8EpmxmPsxmPsxmPsxmPsp:oeggp9Abbbaladfglaga8Ja8KpmwKDYq8AkEx3m5P8Es8Fg8Ja8Ma8NpmwKDYq8AkEx3m5P8Es8Fg8KpmbezHdiOAlvCXorQLg8Ecep:nea8Ea8Fp9op:bep9rg8Ep:oeggp9Abbbaladfglaga8Ea8Epmlvorlvorlvorlvorp:oeggp9Abbbaladfglaga8Ea8EpmwDqkwDqkwDqkwDqkp:oeggp9Abbbaladfglaga8Ea8EpmxmPsxmPsxmPsxmPsp:oeggp9Abbbaladfglaga8Ja8KpmwDKYqk8AExm35Ps8E8Fg8Ecep:nea8Ea8Fp9op:bep9rg8Ep:oeg8Fp9Abbbaladfgla8Fa8Ea8Epmlvorlvorlvorlvorp:oeg8Fp9Abbbaladfgla8Fa8Ea8EpmwDqkwDqkwDqkwDqkp:oeg8Fp9Abbbaladfgla8Fa8Ea8EpmxmPsxmPsxmPsxmPsp:oeggp9AbbbaladfhlaoczfgoaX6mbxdkkaXTmbcbhocbalcl4gl9Rc8FGhiavcjdfaYfhravaYfpbdbh8Finaravcj;cbfaofpblbggaKaofpblbg8JpmbzeHdOiAlCvXoQrLg8KaQaofpblbg8LaLaofpblbg8MpmbzeHdOiAlCvXoQrLg8NpmbezHdiOAlvCXorQLg8Eaip:Rea8Ealp:Sep9qg8Ea8Fp9rg8Fp9Abbbaradfgra8Fa8Ea8Epmlvorlvorlvorlvorp9rg8Fp9Abbbaradfgra8Fa8Ea8EpmwDqkwDqkwDqkwDqkp9rg8Fp9Abbbaradfgra8Fa8Ea8EpmxmPsxmPsxmPsxmPsp9rg8Fp9Abbbaradfgra8Fa8Ka8NpmwDKYqk8AExm35Ps8E8Fg8Eaip:Rea8Ealp:Sep9qg8Ep9rg8Fp9Abbbaradfgra8Fa8Ea8Epmlvorlvorlvorlvorp9rg8Fp9Abbbaradfgra8Fa8Ea8EpmwDqkwDqkwDqkwDqkp9rg8Fp9Abbbaradfgra8Fa8Ea8EpmxmPsxmPsxmPsxmPsp9rg8Fp9Abbbaradfgra8Faga8JpmwKDYq8AkEx3m5P8Es8Fgga8La8MpmwKDYq8AkEx3m5P8Es8Fg8JpmbezHdiOAlvCXorQLg8Eaip:Rea8Ealp:Sep9qg8Ep9rg8Fp9Abbbaradfgra8Fa8Ea8Epmlvorlvorlvorlvorp9rg8Fp9Abbbaradfgra8Fa8Ea8EpmwDqkwDqkwDqkwDqkp9rg8Fp9Abbbaradfgra8Fa8Ea8EpmxmPsxmPsxmPsxmPsp9rg8Fp9Abbbaradfgra8Faga8JpmwDKYqk8AExm35Ps8E8Fg8Eaip:Rea8Ealp:Sep9qg8Ep9rg8Fp9Abbbaradfgra8Fa8Ea8Epmlvorlvorlvorlvorp9rg8Fp9Abbbaradfgra8Fa8Ea8EpmwDqkwDqkwDqkwDqkp9rg8Fp9Abbbaradfgra8Fa8Ea8EpmxmPsxmPsxmPsxmPsp9rg8Fp9AbbbaradfhraoczfgoaX6mbkkaYclfgYad6mbkaHavcjdfaAad2;8qbbavavcjdfaAcufad2fad;8qbbaAazfhzc9:hoaOhxaOmbxlkkaeTmbaDalfhrcbhocuhlinaralaD9RglfaD6mdaPaeao9RaoaPfae6Eaofgoae6mbkaial9Rhxkcbc99amax9RakSEhoxekc9:hokavcj;kbf8Kjjjjbaokwbz:bjjjbk:TseHu8Jjjjjbc;ae9Rgv8Kjjjjbc9:hodnaeci9UgrcHfal0mbcuhoaiRbbgwc;WeGc;Ge9hmbawcsGgDce0mbavc;abfcFecje;8kbavcUf9cu83ibavc8Wf9cu83ibavcyf9cu83ibavcaf9cu83ibavcKf9cu83ibavczf9cu83ibav9cu83iwav9cu83ibaialfc9WfhqaicefgwarfhldnaeTmbcmcsaDceSEhkcbhxcbhmcbhrcbhicbhoindnalaq9nmbc9:hoxikdndnawRbbgDc;Ve0mbavc;abfaoaDcu7gPcl4fcsGcitfgsydlhzasydbhHdndnaDcsGgsak9pmbavaiaPfcsGcdtfydbaxasEhDaxasTgOfhxxekdndnascsSmbcehOasc987asamffcefhDxekalcefhDal8SbbgscFeGhPdndnascu9mmbaDhlxekalcvfhlaPcFbGhPcrhsdninaD8SbbgOcFbGastaPVhPaOcu9kmeaDcefhDascrfgsc8J9hmbxdkkaDcefhlkcehOaPce4cbaPceG9R7amfhDkaDhmkavc;abfaocitfgsaDBdbasazBdlavaicdtfaDBdbavc;abfaocefcsGcitfgsaHBdbasaDBdlaocdfhoaOaifhidnadcd9hmbabarcetfgsaH87ebasclfaD87ebascdfaz87ebxdkabarcdtfgsaHBdbascwfaDBdbasclfazBdbxekdnaDcpe0mbaxcefgOavaiaqaDcsGfRbbgscl49RcsGcdtfydbascz6gPEhDavaias9RcsGcdtfydbaOaPfgzascsGgOEhsaOThOdndnadcd9hmbabarcetfgHax87ebaHclfas87ebaHcdfaD87ebxekabarcdtfgHaxBdbaHcwfasBdbaHclfaDBdbkavaicdtfaxBdbavc;abfaocitfgHaDBdbaHaxBdlavaicefgicsGcdtfaDBdbavc;abfaocefcsGcitfgHasBdbaHaDBdlavaiaPfgicsGcdtfasBdbavc;abfaocdfcsGcitfgDaxBdbaDasBdlaocifhoaiaOfhiazaOfhxxekaxcbalRbbgHEgAaDc;:eSgDfhzaHcsGhCaHcl4hXdndnaHcs0mbazcefhOxekazhOavaiaX9RcsGcdtfydbhzkdndnaCmbaOcefhxxekaOhxavaiaH9RcsGcdtfydbhOkdndnaDTmbalcefhDxekalcdfhDal8SbegPcFeGhsdnaPcu9kmbalcofhAascFbGhscrhldninaD8SbbgPcFbGaltasVhsaPcu9kmeaDcefhDalcrfglc8J9hmbkaAhDxekaDcefhDkasce4cbasceG9R7amfgmhAkdndnaXcsSmbaDhsxekaDcefhsaD8SbbglcFeGhPdnalcu9kmbaDcvfhzaPcFbGhPcrhldninas8SbbgDcFbGaltaPVhPaDcu9kmeascefhsalcrfglc8J9hmbkazhsxekascefhskaPce4cbaPceG9R7amfgmhzkdndnaCcsSmbashlxekascefhlas8SbbgDcFeGhPdnaDcu9kmbascvfhOaPcFbGhPcrhDdninal8SbbgscFbGaDtaPVhPascu9kmealcefhlaDcrfgDc8J9hmbkaOhlxekalcefhlkaPce4cbaPceG9R7amfgmhOkdndnadcd9hmbabarcetfgDaA87ebaDclfaO87ebaDcdfaz87ebxekabarcdtfgDaABdbaDcwfaOBdbaDclfazBdbkavc;abfaocitfgDazBdbaDaABdlavaicdtfaABdbavc;abfaocefcsGcitfgDaOBdbaDazBdlavaicefgicsGcdtfazBdbavc;abfaocdfcsGcitfgDaABdbaDaOBdlavaiaHcz6aXcsSVfgicsGcdtfaOBdbaiaCTaCcsSVfhiaocifhokawcefhwaocsGhoaicsGhiarcifgrae6mbkkcbc99alaqSEhokavc;aef8Kjjjjbaok:clevu8Jjjjjbcz9Rhvdnaecvfal9nmbc9:skdnaiRbbc;:eGc;qeSmbcuskav9cb83iwaicefhoaialfc98fhrdnaeTmbdnadcdSmbcbhwindnaoar6mbc9:skaocefhlao8SbbgicFeGhddndnaicu9mmbalhoxekaocvfhoadcFbGhdcrhidninal8SbbgDcFbGaitadVhdaDcu9kmealcefhlaicrfgic8J9hmbxdkkalcefhokabawcdtfadc8Etc8F91adcd47avcwfadceGcdtVglydbfgiBdbalaiBdbawcefgwae9hmbxdkkcbhwindnaoar6mbc9:skaocefhlao8SbbgicFeGhddndnaicu9mmbalhoxekaocvfhoadcFbGhdcrhidninal8SbbgDcFbGaitadVhdaDcu9kmealcefhlaicrfgic8J9hmbxdkkalcefhokabawcetfadc8Etc8F91adcd47avcwfadceGcdtVglydbfgi87ebalaiBdbawcefgwae9hmbkkcbc99aoarSEk:2Pliur97eue978Jjjjjbc8W9Rhiaec98Ghldndnadcl9hmbdnalTmbcbhvabhdinadadpbbbgocKp:RecKp:Sep;6egraocwp:RecKp:Sep;6earp;Geaoczp:RecKp:Sep;6egwp;Gep;Kep;LegDpxbbbbbbbbbbbbbbbbp:2egqarpxbbbjbbbjbbbjbbbjgkp9op9rp;Kegrpxbb;:9cbb;:9cbb;:9cbb;:9cararp;MeaDaDp;Meawaqawakp9op9rp;Kegrarp;Mep;Kep;Kep;Jep;Negwp;Mepxbbn0bbn0bbn0bbn0gqp;KepxFbbbFbbbFbbbFbbbp9oaopxbbbFbbbFbbbFbbbFp9op9qarawp;Meaqp;Kecwp:RepxbFbbbFbbbFbbbFbbp9op9qaDawp;Meaqp;Keczp:RepxbbFbbbFbbbFbbbFbp9op9qpkbbadczfhdavclfgval6mbkkalaeSmeaipxbbbbbbbbbbbbbbbbgqpklbaiabalcdtfgdaeciGglcdtgv;8qbbdnalTmbaiaipblbgocKp:RecKp:Sep;6egraocwp:RecKp:Sep;6earp;Geaoczp:RecKp:Sep;6egwp;Gep;Kep;LegDaqp:2egqarpxbbbjbbbjbbbjbbbjgkp9op9rp;Kegrpxbb;:9cbb;:9cbb;:9cbb;:9cararp;MeaDaDp;Meawaqawakp9op9rp;Kegrarp;Mep;Kep;Kep;Jep;Negwp;Mepxbbn0bbn0bbn0bbn0gqp;KepxFbbbFbbbFbbbFbbbp9oaopxbbbFbbbFbbbFbbbFp9op9qarawp;Meaqp;Kecwp:RepxbFbbbFbbbFbbbFbbp9op9qaDawp;Meaqp;Keczp:RepxbbFbbbFbbbFbbbFbp9op9qpklbkadaiav;8qbbskaipxFubbFubbFubbFubbgxpklbdnalTmbcbhvabhdinadczfgmampbbbgopxbbbbbbFFbbbbbbFFgkp9oadpbbbgDaopmbediwDqkzHOAKY8AEgwczp:Reczp:Sep;6egraipblbaDaopmlvorxmPsCXQL358E8Fp9op;6eawczp:Sep;6egwp;Gearp;Gep;Kep;Legopxbbbbbbbbbbbbbbbbp:2egqarpxbbbjbbbjbbbjbbbjgPp9op9rp;Kegrpxb;:FSb;:FSb;:FSb;:FSararp;Meaoaop;MeawaqawaPp9op9rp;Kegrarp;Mep;Kep;Kep;Jep;Negwp;Mepxbbn0bbn0bbn0bbn0gqp;KepxFFbbFFbbFFbbFFbbp9oaoawp;Meaqp;Keczp:Rep9qgoarawp;Meaqp;KepxFFbbFFbbFFbbFFbbp9ogrpmwDKYqk8AExm35Ps8E8Fp9qpkbbadaDakp9oaoarpmbezHdiOAlvCXorQLp9qpkbbadcafhdavclfgval6mbkkalaeSmbaiczfpxbbbbbbbbbbbbbbbbgopklbaiaopklbaiabalcitfgdaeciGglcitgv;8qbbaiaxpkladnalTmbaiaipblzgopxbbbbbbFFbbbbbbFFgkp9oaipblbgDaopmbediwDqkzHOAKY8AEgwczp:Reczp:Sep;6egraipblaaDaopmlvorxmPsCXQL358E8Fp9op;6eawczp:Sep;6egwp;Gearp;Gep;Kep;Legopxbbbbbbbbbbbbbbbbp:2egqarpxbbbjbbbjbbbjbbbjgPp9op9rp;Kegrpxb;:FSb;:FSb;:FSb;:FSararp;Meaoaop;MeawaqawaPp9op9rp;Kegrarp;Mep;Kep;Kep;Jep;Negwp;Mepxbbn0bbn0bbn0bbn0gqp;KepxFFbbFFbbFFbbFFbbp9oaoawp;Meaqp;Keczp:Rep9qgoarawp;Meaqp;KepxFFbbFFbbFFbbFFbbp9ogrpmwDKYqk8AExm35Ps8E8Fp9qpklzaiaDakp9oaoarpmbezHdiOAlvCXorQLp9qpklbkadaiav;8qbbkk;Iwllue97euo978Jjjjjbca9Rhidnaec98GglTmbcbhvabhoinaocKfpxbbjZbbjZbbjZbbjZpx;Zl81Z;Zl81Z;Zl81Z;Zl81ZaopbbbgraoczfgwpbbbgDpmlvorxmPsCXQL358E8Fgqczp:Segkpxibbbibbbibbbibbbp9qp;6ep;NegxaraDpmbediwDqkzHOAKY8AEgrczp:Reczp:Sep;6ep;MegDaDp;Meaxarczp:Sep;6ep;Megmamp;Meaxaqczp:Reczp:Sep;6ep;Megqaqp;Mep;Kep;Kep;Lepxbbbbbbbbbbbbbbbbp:4ep;Jepxb;:FSb;:FSb;:FSb;:FSgxp;Mepxbbn0bbn0bbn0bbn0grp;KepxFFbbFFbbFFbbFFbbgPp9oamaxp;Mearp;Keczp:Rep9qgmaDaxp;Mearp;KeaPp9oaqaxp;Mearp;Keczp:Rep9qgrpmwDKYqk8AExm35Ps8E8FgDp5eakclp:RegxpEi:T:j83ibawaDp5baxpEd:T:j83ibaocwfamarpmbezHdiOAlvCXorQLgrp5eaxpEe:T:j83ibaoarp5baxpEb:T:j83ibaocafhoavclfgval6mbkkdnalaeSmbaiczfpxbbbbbbbbbbbbbbbbgxpklbaiaxpklbaiabalcitfgoaeciGgvcitgw;8qbbdnavTmbaipxbbjZbbjZbbjZbbjZpx;Zl81Z;Zl81Z;Zl81Z;Zl81ZaipblbgraipblzgDpmlvorxmPsCXQL358E8Fgqczp:Segkpxibbbibbbibbbibbbp9qp;6ep;NegxaraDpmbediwDqkzHOAKY8AEgrczp:Reczp:Sep;6ep;MegDaDp;Meaxarczp:Sep;6ep;Megmamp;Meaxaqczp:Reczp:Sep;6ep;Megqaqp;Mep;Kep;Kep;Lepxbbbbbbbbbbbbbbbbp:4ep;Jepxb;:FSb;:FSb;:FSb;:FSgxp;Mepxbbn0bbn0bbn0bbn0grp;KepxFFbbFFbbFFbbFFbbgPp9oamaxp;Mearp;Keczp:Rep9qgmaDaxp;Mearp;KeaPp9oaqaxp;Mearp;Keczp:Rep9qgrpmwDKYqk8AExm35Ps8E8FgDp5eakclp:RegxpEi:T:j83iKaiaDp5baxpEd:T:j83izaiamarpmbezHdiOAlvCXorQLgrp5eaxpEe:T:j83iwaiarp5baxpEb:T:j83ibkaoaiaw;8qbbkk;uddiue978Jjjjjbc;ab9Rhidnadcd4ae2glc98GgvTmbcbheabhdinadadpbbbgocwp:Recwp:Sep;6eaocep:SepxbbjFbbjFbbjFbbjFp9opxbbjZbbjZbbjZbbjZp:Uep;Mepkbbadczfhdaeclfgeav6mbkkdnavalSmbaic8WfpxbbbbbbbbbbbbbbbbgopklbaicafaopklbaiczfaopklbaiaopklbaiabavcdtfgdalciGgecdtgv;8qbbdnaeTmbaiaipblbgocwp:Recwp:Sep;6eaocep:SepxbbjFbbjFbbjFbbjFp9opxbbjZbbjZbbjZbbjZp:Uep;Mepklbkadaiav;8qbbkk:CPvdue97euw97eu8Jjjjjbc8W9Rhiaec98Ghldndnadcl9hmbaipxbbbbbbbbbbbbbbbbgvpklbdnalTmbcbhoabhdinadpbbbhradpxbbuJbbuJbbuJbbuJaipblbarcKp:Tep9qgwcep:Seawp9qgDcdp:SeaDp9qgDclp:SeaDp9qgqp;6ep;NegDarcwp:RecKp:SegkarpxFbbbFbbbFbbbFbbbgxp9ogmp:Uep;6ep;Mepxbbn0bbn0bbn0bbn0gPp;Kecwp:RepxbFbbbFbbbFbbbFbbp9oaDamakp:Xearczp:RecKp:Segrp:Uep;6ep;MeaPp;Keaxp9op9qaDamakarp:Uep:Xep;6ep;MeaPp;Keczp:RepxbbFbbbFbbbFbbbFbp9op9qaDaqawcep:Rep9oawpxebbbebbbebbbebbbp9op9qp;6ep;MeaPp;KecKp:Rep9qpkbbadczfhdaoclfgoal6mbkkalaeSmeaiavpklaaicafabalcdtfgdaeciGglcdtgo;8qbbaiavpklbdnalTmbaipblahraipxbbuJbbuJbbuJbbuJaipblbarcKp:Tep9qgwcep:Seawp9qgDcdp:SeaDp9qgDclp:SeaDp9qgqp;6ep;NegDarcwp:RecKp:SegkarpxFbbbFbbbFbbbFbbbgxp9ogmp:Uep;6ep;Mepxbbn0bbn0bbn0bbn0gPp;Kecwp:RepxbFbbbFbbbFbbbFbbp9oaDamakp:Xearczp:RecKp:Segrp:Uep;6ep;MeaPp;Keaxp9op9qaDamakarp:Uep:Xep;6ep;MeaPp;Keczp:RepxbbFbbbFbbbFbbbFbp9op9qaDaqawcep:Rep9oawpxebbbebbbebbbebbbp9op9qp;6ep;MeaPp;KecKp:Rep9qpklakadaicafao;8qbbskaipxbbbbbbbbbbbbbbbbgvpklbdnalTmbcbhoabhdinadczfgspxbFu9hbFu9hbFu9hbFu9hadpbbbgDaspbbbgPpmlvorxmPsCXQL358E8Fgmczp:Teaipblbp9qgrcep:Searp9qgwcdp:Seawp9qgwclp:Seawp9qgwcwp:Seawp9qgqp;6ep;NegwaDaPpmbediwDqkzHOAKY8AEgDpxFFbbFFbbFFbbFFbbgPp9ogkaDczp:Segxp:Ueamczp:Reczp:Segmp:Xep;6ep;Mepxbbn0bbn0bbn0bbn0gDp;KeaPp9oawakaxamp:Uep:Xep;6ep;MeaDp;Keczp:Rep9qgxawaqarcep:Rep9oarpxebbbebbbebbbebbbp9op9qp;6ep;MeaDp;Keczp:Reawamakp:Uep;6ep;MeaDp;KeaPp9op9qgrpmwDKYqk8AExm35Ps8E8FpkbbadaxarpmbezHdiOAlvCXorQLpkbbadcafhdaoclfgoal6mbkkalaeSmbaiczfpxbbbbbbbbbbbbbbbbgrpklbaiarpklbaiabalcitfgdaeciGglcitgo;8qbbaiavpkladnalTmbaipxbFu9hbFu9hbFu9hbFu9haipblbgDaipblzgPpmlvorxmPsCXQL358E8Fgmczp:Teaipblap9qgrcep:Searp9qgwcdp:Seawp9qgwclp:Seawp9qgwcwp:Seawp9qgqp;6ep;NegwaDaPpmbediwDqkzHOAKY8AEgDpxFFbbFFbbFFbbFFbbgPp9ogkaDczp:Segxp:Ueamczp:Reczp:Segmp:Xep;6ep;Mepxbbn0bbn0bbn0bbn0gDp;KeaPp9oawakaxamp:Uep:Xep;6ep;MeaDp;Keczp:Rep9qgxawaqarcep:Rep9oarpxebbbebbbebbbebbbp9op9qp;6ep;MeaDp;Keczp:Reawamakp:Uep;6ep;MeaDp;KeaPp9op9qgrpmwDKYqk8AExm35Ps8E8FpklzaiaxarpmbezHdiOAlvCXorQLpklbkadaiao;8qbbkk9teiucbcbydj1jjbgeabcifc98GfgbBdj1jjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaikkkebcjwklz:Dbb";
var detector = new Uint8Array([
0,
97,
115,
109,
1,
0,
0,
0,
1,
4,
1,
96,
0,
0,
3,
3,
2,
0,
0,
5,
3,
1,
0,
1,
12,
1,
0,
10,
22,
2,
12,
0,
65,
0,
65,
0,
65,
0,
252,
10,
0,
0,
11,
7,
0,
65,
0,
253,
15,
26,
11
]);
var wasmpack = new Uint8Array([
32,
0,
65,
2,
1,
106,
34,
33,
3,
128,
11,
4,
13,
64,
6,
253,
10,
7,
15,
116,
127,
5,
8,
12,
40,
16,
19,
54,
20,
9,
27,
255,
113,
17,
42,
67,
24,
23,
146,
148,
18,
14,
22,
45,
70,
69,
56,
114,
101,
21,
25,
63,
75,
136,
108,
28,
118,
29,
73,
115
]);
if (typeof WebAssembly !== "object") {
return {
supported: false
};
}
var wasm = WebAssembly.validate(detector) ? unpack(wasm_simd) : unpack(wasm_base);
var instance;
var ready = WebAssembly.instantiate(wasm, {}).then(function(result) {
instance = result.instance;
instance.exports.__wasm_call_ctors();
});
function unpack(data) {
var result = new Uint8Array(data.length);
for (var i = 0; i < data.length; ++i) {
var ch = data.charCodeAt(i);
result[i] = ch > 96 ? ch - 97 : ch > 64 ? ch - 39 : ch + 4;
}
var write = 0;
for (var i = 0; i < data.length; ++i) {
result[write++] = result[i] < 60 ? wasmpack[result[i]] : (result[i] - 60) * 64 + result[++i];
}
return result.buffer.slice(0, write);
}
function decode(instance2, fun, target, count, size, source, filter) {
var sbrk = instance2.exports.sbrk;
var count4 = count + 3 & ~3;
var tp = sbrk(count4 * size);
var sp = sbrk(source.length);
var heap = new Uint8Array(instance2.exports.memory.buffer);
heap.set(source, sp);
var res = fun(tp, count, size, sp, source.length);
if (res == 0 && filter) {
filter(tp, count4, size);
}
target.set(heap.subarray(tp, tp + count * size));
sbrk(tp - sbrk(0));
if (res != 0) {
throw new Error("Malformed buffer data: " + res);
}
}
var filters = {
NONE: "",
OCTAHEDRAL: "meshopt_decodeFilterOct",
QUATERNION: "meshopt_decodeFilterQuat",
EXPONENTIAL: "meshopt_decodeFilterExp",
COLOR: "meshopt_decodeFilterColor"
};
var decoders = {
ATTRIBUTES: "meshopt_decodeVertexBuffer",
TRIANGLES: "meshopt_decodeIndexBuffer",
INDICES: "meshopt_decodeIndexSequence"
};
var workers2 = [];
var requestId = 0;
function createWorker2(url2) {
var worker = {
object: new Worker(url2),
pending: 0,
requests: {}
};
worker.object.onmessage = function(event) {
var data = event.data;
worker.pending -= data.count;
worker.requests[data.id][data.action](data.value);
delete worker.requests[data.id];
};
return worker;
}
function initWorkers(count) {
var source = "self.ready = WebAssembly.instantiate(new Uint8Array([" + new Uint8Array(wasm) + "]), {}).then(function(result) { result.instance.exports.__wasm_call_ctors(); return result.instance; });self.onmessage = " + workerProcess.name + ";" + decode.toString() + workerProcess.toString();
var blob = new Blob([source], { type: "text/javascript" });
var url2 = URL.createObjectURL(blob);
for (var i = workers2.length; i < count; ++i) {
workers2[i] = createWorker2(url2);
}
for (var i = count; i < workers2.length; ++i) {
workers2[i].object.postMessage({});
}
workers2.length = count;
URL.revokeObjectURL(url2);
}
function decodeWorker(count, size, source, mode2, filter) {
var worker = workers2[0];
for (var i = 1; i < workers2.length; ++i) {
if (workers2[i].pending < worker.pending) {
worker = workers2[i];
}
}
return new Promise(function(resolve2, reject) {
var data = new Uint8Array(source);
var id = ++requestId;
worker.pending += count;
worker.requests[id] = { resolve: resolve2, reject };
worker.object.postMessage({ id, count, size, source: data, mode: mode2, filter }, [data.buffer]);
});
}
function workerProcess(event) {
var data = event.data;
if (!data.id) {
return self.close();
}
self.ready.then(function(instance2) {
try {
var target = new Uint8Array(data.count * data.size);
decode(instance2, instance2.exports[data.mode], target, data.count, data.size, data.source, instance2.exports[data.filter]);
self.postMessage({ id: data.id, count: data.count, action: "resolve", value: target }, [target.buffer]);
} catch (error) {
self.postMessage({ id: data.id, count: data.count, action: "reject", value: error });
}
});
}
return {
ready,
supported: true,
useWorkers: function(count) {
initWorkers(count);
},
decodeVertexBuffer: function(target, count, size, source, filter) {
decode(instance, instance.exports.meshopt_decodeVertexBuffer, target, count, size, source, instance.exports[filters[filter]]);
},
decodeIndexBuffer: function(target, count, size, source) {
decode(instance, instance.exports.meshopt_decodeIndexBuffer, target, count, size, source);
},
decodeIndexSequence: function(target, count, size, source) {
decode(instance, instance.exports.meshopt_decodeIndexSequence, target, count, size, source);
},
decodeGltfBuffer: function(target, count, size, source, mode2, filter) {
decode(instance, instance.exports[decoders[mode2]], target, count, size, source, instance.exports[filters[filter]]);
},
decodeGltfBufferAsync: function(count, size, source, mode2, filter) {
if (workers2.length > 0) {
return decodeWorker(count, size, source, decoders[mode2], filters[filter]);
}
return ready.then(function() {
var target = new Uint8Array(count * size);
decode(instance, instance.exports[decoders[mode2]], target, count, size, source, instance.exports[filters[filter]]);
return target;
});
}
};
})();
// node_modules/meshoptimizer/meshopt_simplifier.module.js
var import_InlineWorkers470 = __toESM(require_InlineWorkers());
var MeshoptSimplifier = (function() {
var wasm = "b9H79Tebbbe:Gez9Geueu9Geub9Gbb9Gsuuuuuuuuuuuu99uueu9Gvuuuuub9Gruuuuuuub9Gouuuuuue999Gvuuuuueu9Gquuuuuuu99uueu9GPuuuuuuuuuuu99uueu9Gquuuuuuuu99ueu9Gruuuuuu99eu9Gwuuuuuu99ueu9Giuuue999Gluuuueu9GiuuueuiXCdilvorlwiDqkxmPbssbelve9Weiiviebeoweuec:G:Pdkr;7eko9TW9T9VV95dbH9F9F939H79T9F9J9H229F9Jt9VV7bbz9TW79O9V9Wt9F79P9T9W29P9M95br8E9TW79O9V9Wt9F79P9T9W29P9M959x9Pt9OcttV9P9I91tW7bw8A9TW79O9V9Wt9F79P9T9W29P9M959x9Pt9O9v9W9K9HtWbDQ9TW79O9V9Wt9F79P9T9W29P9M959t29V9W9W95bqX9TW79O9V9Wt9F79P9T9W29P9M959qV919UWbkQ9TW79O9V9Wt9F79P9T9W29P9M959q9V9P9Ut7bxX9TW79O9V9Wt9F79P9T9W29P9M959t9J9H2Wbma9TW79O9V9Wt9F9V9Wt9P9T9P96W9wWVtW94SWt9J9O9sW9T9H9WbPl79IV9RbsDwebcekdOAq:d;OeCdbk:J1eo3ue99euE99Cue9:8Jjjjjbcj;sb9Rgs8Kjjjjbcbhzasc:Cefcbc;Kbz:rjjjb8AdnabaeSmbabaeadcdtz:qjjjb8AkdnamcdGTmbalcrfci4gHcbyd1:jjjbHjjjjbbheasc:Cefasyd;8egOcdtfaeBdbasaOcefBd;8eaecbaHz:rjjjbhAcbhlcbhednadTmbcbhlabheadhHinaAaeydbgOci4fgCaCRbbgCceaOcrGgOtV86bbaCcu7aO4ceGalfhlaeclfheaHcufgHmbkcualcdtalcFFFFi0Ehekaecbyd1:jjjbHjjjjbbhzasc:Cefasyd;8egecdtfazBdbasaecefBd;8ealcd4alfhOcehHinaHgecethHaeaO6mbkcbhXcuaecdtgOaecFFFFi0Ecbyd1:jjjbHjjjjbbhHasc:Cefasyd;8egCcdtfaHBdbasaCcefBd;8eaHcFeaOz:rjjjbhQdnadTmbaecufhLcbhKindndnaQabaXcdtfgYydbgCc:v;t;h;Ev2aLGgOcdtfgAydbgHcuSmbceheinazaHcdtfydbaCSmdaOaefhHaecefheaQaHaLGgOcdtfgAydbgHcu9hmbkkazaKcdtfaCBdbaAaKBdbaKhHaKcefhKkaYaHBdbaXcefgXad9hmbkkaQcbyd:m:jjjbH:bjjjbbasasyd;8ecufBd;8ekcbh8AcualcefgecdtaecFFFFi0Ecbyd1:jjjbHjjjjbbhKasc:Cefasyd;8egecdtfaKBdbasaKBdNeasaecefBd;8ecuadcitadcFFFFe0Ecbyd1:jjjbHjjjjbbhEasc:Cefasyd;8egecdtfaEBdbasaEBd:yeasaecefBd;8eascNefabadalcbz:cjjjbcualcdtgealcFFFFi0Eg3cbyd1:jjjbHjjjjbbhCasc:Cefasyd;8egHcdtfaCBdbasaHcefBd;8ea3cbyd1:jjjbHjjjjbbhYasc:Cefasyd;8egHcdtfaYBdbasaHcefBd;8eaCaYaialavazasc:Cefz:djjjbalcbyd1:jjjbHjjjjbbh5asc:Cefasyd;8egHcdtfa5BdbasaHcefBd;8ea3cbyd1:jjjbHjjjjbbhHasc:Cefasyd;8egOcdtfaHBdbasaOcefBd;8ea3cbyd1:jjjbHjjjjbbhOasc:Cefasyd;8egAcdtfaOBdbasaAcefBd;8eaHcFeaez:rjjjbh8EaOcFeaez:rjjjbh8FdnalTmbaEcwfhaindnaKa8AgOcefg8AcdtfydbgAaKaOcdtgefydbgHSmbaAaH9RhhaEaHcitfhga8Faefh8Ja8Eaefh8KcbhQindndnagaQcitfydbgLaO9hmba8KaOBdba8JaOBdbxekdnaKaLcdtg8LfgeclfydbgHaeydbgeSmbaEaecitgAfydbaOSmeaHae9Rh8Maecu7aHfhXaaaAfhHcbheinaXaeSmeaecefheaHydbhAaHcwfhHaAaO9hmbkaea8M6meka8Fa8LfgeaOaLaeydbcuSEBdba8KaLaOa8KydbcuSEBdbkaQcefgQah9hmbkka8Aal9hmbkaChHaYhOa8FhAa8EhQcbheindndnaeaHydbgL9hmbdnaeaOydbgL9hmbaQydbhLdnaAydbgXcu9hmbaLcu9hmba5aefcb86bbxikdnaXcuSmbaLcuSmbaeaXSmbaCaXcdtfydbaCaLcdtfydb9hmba5aefcd86bbxika5aefh8KdnaeaXSmbaeaLSmba8Kce86bbxika8Kcl86bbxdkdnaeaYaLcdtgXfydb9hmbdnaAydbg8KcuSmbaea8KSmbaQydbghcuSmbaeahSmba8FaXfydbggcuSmbagaLSmba8EaXfydbgXcuSmbaXaLSmbdnaCa8KcdtfydbgLaCaXcdtfydb9hmbaLaCahcdtfydbgXSmbaXaCagcdtfydb9hmba5aefcd86bbxlka5aefcl86bbxika5aefcl86bbxdka5aefcl86bbxeka5aefa5aLfRbb86bbkaHclfhHaOclfhOaAclfhAaQclfhQalaecefge9hmbkdnamcaGTmbaEcwfh8Jcbh8Nindndna5a8NfgyRbbg8Pc9:fPibebekdndndnaCa8Ncdtfydbgea8N9hmbdnaqmbcbhgxdkdnazTmbcbhga8NheinagaqazaecdtgefydbfRbbcdGce4VhgaYaefydbgea8N9hmbxikkcbhga8NheinagaqaefRbbcdGce4VhgaYaecdtfydbgea8N9hmbxdkka5aefRbbhexeka8NheindnaKaecdtgafgeclfydbgHaeydbgeSmbaHae9Rh8AaEaecitfh8MaCaafh8Lcbh8Kina8Ma8KcitfydbgXhednindnaKaecdtgLfgeclfydbgHaeydbgeSmbdnaCaEaecitgOfydbcdtfydba8LydbgQ9hmbcehexikaHae9Rhhaecu7aHfhAa8JaOfhHcbheinaAaeSmeaecefheaHydbhOaHcwfhHaCaOcdtfydbaQ9hmbkaeah6hexdkaYaLfydbgeaX9hmbkcbhekagaece7Vhga8Kcefg8Ka8A9hmbkkaYaafydbgea8N9hmbka8PciagceGEhekayae86bbka8Ncefg8Nal9hmbkkdnaqTmbdndnazTmbazheaChHalhOindnaqaeydbfRbbceGTmba5aHydbfcl86bbkaeclfheaHclfhHaOcufgOmbxdkkaChealhHindnaqRbbceGTmba5aeydbfcl86bbkaqcefhqaeclfheaHcufgHmbkkaChealhOa5hHindna5aeydbfRbbcl9hmbaHcl86bbkaeclfheaHcefhHaOcufgOmbkkamceGTmba5healhHindnaeRbbce9hmbaecl86bbkaecefheaHcufgHmbkkcbhIcualcx2alc;v:Q;v:Qe0Ecbyd1:jjjbHjjjjbbhaasc:Cefasyd;8egecdtfaaBdbasaecefBd;8easc:qefcbBdbas9cb83i1eaaaialavazasc1efz:ejjjbh8RdndnaDmbcbh8Scbh8Lxekcbh8LawhecbhHindnaeIdbJbbbb9ETmbasa8LcdtfaHBdba8Lcefh8LkaeclfheaDaHcefgH9hmbkcua8Lal2gecdtaecFFFFi0Ecbyd1:jjjbHjjjjbbh8Sasc:Cefasyd;8egecdtfa8SBdbasaecefBd;8ealTmbdna8Lmbcbh8Lxekarcd4hXdnazTmba8Lcdth8KcbhLa8ShKinaoazaLcdtfydbaX2cdtfhQasheaKhHa8LhOinaHaQaeydbcdtgAfIdbawaAfIdbNUdbaeclfheaHclfhHaOcufgOmbkaKa8KfhKaLcefgLal9hmbxdkka8Lcdth8KcbhLa8ShKinaoaLaX2cdtfhQasheaKhHa8LhOinaHaQaeydbcdtgAfIdbawaAfIdbNUdbaeclfheaHclfhHaOcufgOmbkaKa8KfhKaLcefgLal9hmbkkcualc8S2gHalc;D;O;f8U0EgAcbyd1:jjjbHjjjjbbheasc:Cefasyd;8egOcdtfaeBdbasaOcefBd;8eaecbaHz:rjjjbhycbhqcbh8Ndna8LTmbcbhIaAcbyd1:jjjbHjjjjbbh8Nasc:Cefasyd;8egecdtfa8NBdbasaecefBd;8ea8NcbaHz:rjjjb8Acua8Lal2gecltgHaecFFFFb0Ecbyd1:jjjbHjjjjbbhqasc:Cefasyd;8egecdtfaqBdbasaecefBd;8eaqcbaHz:rjjjb8AamcjjjjdGTmbcualcltgealcFFFFb0Ecbyd1:jjjbHjjjjbbhIasc:Cefasyd;8egHcdtfaIBdbasaHcefBd;8eaIcbaez:rjjjb8AkdnadTmbcbhQabhHinaaaHclfydbgLcx2fgeIdbaaaHydbgKcx2fgOIdbgR:tg8UaaaHcwfydbgXcx2fgAIdlaOIdlg8V:tg8WNaAIdbaR:tg8XaeIdla8V:tg8YN:tg8Zh80aeIdwaOIdwg81:tgBa8XNaAIdwa81:tg83a8UN:tgUh8Xa8Ya83Na8WaBN:tg8Yh8Udna8Za8ZNa8Ya8YNaUaUNMM:rgBJbbbb9EgOTmba8ZaB:vh80aUaB:vh8Xa8YaB:vh8UkayaCaKcdtfydbgAc8S2fgea8UaB:rg8Wa8UNNg85aeIdbMUdbaea8Xa8Wa8XNg86Ng87aeIdlMUdlaea80a8Wa80Ng83Ng88aeIdwMUdwaea86a8UNg86aeIdxMUdxaea83a8UNg89aeIdzMUdzaea83a8XNg8:aeIdCMUdCaea8Ua8Wa80a81Na8UaRNa8Va8XNMM:mgZNg83Ng8UaeIdKMUdKaea8Xa83Ng8XaeId3MUd3aea80a83Ng80aeIdaMUdaaea83aZNg83aeId8KMUd8Kaea8WaeIdyMUdyayaCaLcdtfydbgLc8S2fgea85aeIdbMUdbaea87aeIdlMUdlaea88aeIdwMUdwaea86aeIdxMUdxaea89aeIdzMUdzaea8:aeIdCMUdCaea8UaeIdKMUdKaea8XaeId3MUd3aea80aeIdaMUdaaea83aeId8KMUd8Kaea8WaeIdyMUdyayaCaXcdtfydbgKc8S2fgea85aeIdbMUdbaea87aeIdlMUdlaea88aeIdwMUdwaea86aeIdxMUdxaea89aeIdzMUdzaea8:aeIdCMUdCaea8UaeIdKMUdKaea8XaeId3MUd3aea80aeIdaMUdaaea83aeId8KMUd8Kaea8WaeIdyMUdydnaITmbdnaOTmba8ZaB:vh8ZaUaB:vhUa8YaB:vh8YkaIaAcltfgeaBJbbbZNg8UaUNg8WaeIdlMUdlaea8Ua8ZNg8XaeIdwMUdwaea8Ua8YNg80aeIdbMUdbaea8UaR:ma8YNaUa8VN:ta81a8ZN:tNg8UaeIdxMUdxaIaLcltfgea8WaeIdlMUdlaea8XaeIdwMUdwaea80aeIdbMUdbaea8UaeIdxMUdxaIaKcltfgea8WaeIdlMUdlaea8XaeIdwMUdwaea80aeIdbMUdbaea8UaeIdxMUdxkaHcxfhHaQcifgQad6mbkkdnalTmbJ;n;m;m89J:v:;;w8ZamczGEh8YcbhOaChAaahHayheindnaOaAydb9hmbaecxfgQaQIdbJbbbbMUdbaeczfgQaQIdbJbbbbMUdbaecCfgQaQIdbJbbbbMUdbaea8YaecyfgQIdbg8ZNg8UaeIdbMUdbaeclfgLa8UaLIdbMUdbaecwfgLa8UaLIdbMUdbaecKfgLaLIdbaHIdbg8Xa8UN:tUdbaHcwfIdbh8Waec3fgLaLIdba8UaHclfIdbg80N:tUdbaecafgLaLIdba8Ua8WN:tUdbaec8KfgLIdbhUaQa8Za8UMUdbaLaUa8Ua8Wa8WNa8Xa8XNa80a80NMMNMUdbkaAclfhAaHcxfhHaec8SfhealaOcefgO9hmbkkdnadTmbcbhXabhKinabaXcdtfhLcbhHina5aLaHc:G1jjbfydbcdtfydbgOfRbbhedndna5aKaHfydbgAfRbbgQc99fcFeGcpe0mbaec99fcFeGc;:e6mekdnaQcufcFeGce0mba8EaAcdtfydbaO9hmekdnaecufcFeGce0mba8FaOcdtfydbaA9hmekJbbacJbbacJbbbZaecFeGceSEaQcFeGceSEh88aaaOcx2fgeIdwaaaAcx2fgQIdwgB:tg80:mh86aeIdlaQIdlg83:tg8Z:mh89aeIdbaQIdbgR:tgU:mh8:dnaaaLaHc:K1jjbfydbcdtfydbcx2fgeIdwaB:tg8Va80a80NaUaUNa8Za8ZNMMg8YNa8Va80NaeIdbaR:tg81aUNa8ZaeIdla83:tg85NMMg8Wa80N:tg8Xa8XNa81a8YNa8WaUN:tg8Ua8UNa85a8YNa8Wa8ZN:tg8Wa8WNMM:rg87Jbbbb9ETmba8Xa87:vh8Xa8Wa87:vh8Wa8Ua87:vh8Uka88a8Y:rNg8Ya8XaBNa8UaRNa83a8WNMM:mgZNg87aZNhZa8Xa87Nhna8Wa87Nhca8Ua87Nh9ca8Ya8XNg87a8WNhJa87a8UNh9ea8Ya8WNgTa8UNhSa8Xa87Nh87a8WaTNhTa8Ua8Ya8UNNh9hdnaUa85Na81a89NMg8Xa8XNa8Za8VNa85a86NMg8Ua8UNa80a81Na8Va8:NMg8Wa8WNMM:rg80Jbbbb9ETmba8Xa80:vh8Xa8Wa80:vh8Wa8Ua80:vh8UkayaCaAcdtfydbc8S2fgeaeIdba9ha8Ua88a80:rNg80a8UNNMgUMUdbaeaTa8Wa80a8WNg8VNMg81aeIdlMUdlaea87a8Xa80a8XNg8ZNMg85aeIdwMUdwaeaSa8Va8UNMg8VaeIdxMUdxaea9ea8Za8UNMg87aeIdzMUdzaeaJa8Za8WNMg8ZaeIdCMUdCaea9ca8Ua80a8XaBNa8UaRNa83a8WNMMgB:mNg80NMg8UaeIdKMUdKaeaca8Wa80NMg8WaeId3MUd3aeana8Xa80NMg8XaeIdaMUdaaeaZaBa80N:tg80aeId8KMUd8Kaea8YJbbbbMg8YaeIdyMUdyayaCaOcdtfydbc8S2fgeaUaeIdbMUdbaea81aeIdlMUdlaea85aeIdwMUdwaea8VaeIdxMUdxaea87aeIdzMUdzaea8ZaeIdCMUdCaea8UaeIdKMUdKaea8WaeId3MUd3aea8XaeIdaMUdaaea80aeId8KMUd8Kaea8YaeIdyMUdykaHclfgHcx9hmbkaKcxfhKaXcifgXad6mbka8LTmbcbhKinJbbbbh8YaaabaKcdtfgeclfydbgXcx2fgHIdwaaaeydbg8Kcx2fgOIdwg81:tg8Wa8WNaHIdbaOIdbg85:tg8Xa8XNaHIdlaOIdlg87:tg80a80NMMgRaaaecwfydbghcx2fgeIdwa81:tg8ZNa8Wa8Wa8ZNa8XaeIdba85:tgUNa80aeIdla87:tgBNMMg8UN:tJbbbbJbbjZaRa8Za8ZNaUaUNaBaBNMMg8VNa8Ua8UN:tg83:va83Jbbbb9BEg83Nh89a8Va8WNa8Za8UN:ta83Nh8:aRaBNa80a8UN:ta83NhZa8Va80NaBa8UN:ta83NhnaRaUNa8Xa8UN:ta83Nhca8Va8XNaUa8UN:ta83Nh9ca8XaBNaUa80N:tg8Ua8UNa80a8ZNaBa8WN:tg8Ua8UNa8WaUNa8Za8XN:tg8Ua8UNMM:rJbbbZNh8Ua8Sa8Ka8L2ggcdtfhHa8Saha8L2gEcdtfhOa8SaXa8L2g8JcdtfhAa81:mhJa87:mh9ea85:mhTcbhQa8LhLJbbbbhBJbbbbh83JbbbbhRJbbbbh8VJbbbbh81Jbbbbh85Jbbbbh87Jbbbbh88Jbbbbh86inascjdfaQfgecwfa8Ua8:aAIdbaHIdbg8Z:tg80Na89aOIdba8Z:tgUNMg8WNUdbaeclfa8Uana80NaZaUNMg8XNUdbaea8Ua9ca80NacaUNMg80NUdbaecxfa8UaJa8WNa9ea8XNa8ZaTa80NMMMg8ZNUdba8Ua8Wa8XNNa8VMh8Va8Ua8Wa80NNa81Mh81a8Ua8Xa80NNa85Mh85a8Ua8Za8ZNNa8YMh8Ya8Ua8Wa8ZNNaBMhBa8Ua8Xa8ZNNa83Mh83a8Ua80a8ZNNaRMhRa8Ua8Wa8WNNa87Mh87a8Ua8Xa8XNNa88Mh88a8Ua80a80NNa86Mh86aHclfhHaAclfhAaOclfhOaQczfhQaLcufgLmbka8Na8Kc8S2fgea86aeIdbMUdbaea88aeIdlMUdlaea87aeIdwMUdwaea85aeIdxMUdxaea81aeIdzMUdzaea8VaeIdCMUdCaeaRaeIdKMUdKaea83aeId3MUd3aeaBaeIdaMUdaaea8YaeId8KMUd8Kaea8UaeIdyMUdya8NaXc8S2fgea86aeIdbMUdbaea88aeIdlMUdlaea87aeIdwMUdwaea85aeIdxMUdxaea81aeIdzMUdzaea8VaeIdCMUdCaeaRaeIdKMUdKaea83aeId3MUd3aeaBaeIdaMUdaaea8YaeId8KMUd8Kaea8UaeIdyMUdya8Nahc8S2fgea86aeIdbMUdbaea88aeIdlMUdlaea87aeIdwMUdwaea85aeIdxMUdxaea81aeIdzMUdzaea8VaeIdCMUdCaeaRaeIdKMUdKaea83aeId3MUd3aeaBaeIdaMUdaaea8YaeId8KMUd8Kaea8UaeIdyMUdyaqagcltfhLcbhHa8LhAinaLaHfgeascjdfaHfgOIdbaeIdbMUdbaeclfgQaOclfIdbaQIdbMUdbaecwfgQaOcwfIdbaQIdbMUdbaecxfgeaOcxfIdbaeIdbMUdbaHczfhHaAcufgAmbkaqa8JcltfhLcbhHa8LhAinaLaHfgeascjdfaHfgOIdbaeIdbMUdbaeclfgQaOclfIdbaQIdbMUdbaecwfgQaOcwfIdbaQIdbMUdbaecxfgeaOcxfIdbaeIdbMUdbaHczfhHaAcufgAmbkaqaEcltfhLcbhHa8LhAinaLaHfgeascjdfaHfgOIdbaeIdbMUdbaeclfgQaOclfIdbaQIdbMUdbaecwfgQaOcwfIdbaQIdbMUdbaecxfgeaOcxfIdbaeIdbMUdbaHczfhHaAcufgAmbkaKcifgKad6mbkkcbhOdndnamcwGg9imbJbbbbh85cbh6cbh9kcbh0xekcbh6a3cbyd1:jjjbHjjjjbbh0asc:Cefasyd;8egecdtfa0BdbasaecefBd;8ecua0alabadaCz:fjjjbgAcltaAcjjjjiGEcbyd1:jjjbHjjjjbbh9kasc:Cefasyd;8egecdtfa9kBdbasaecefBd;8ea9kaAa0aaalz:gjjjbJFFuuh85aATmba9kheaAhHinaeIdbg8Ua85a85a8U9EEh85aeclfheaHcufgHmbkaAh6kasydNeh9mdnalTmba9mclfhea9mydbhAa5hHalhQcbhOincbaeydbgLaA9RaHRbbcpeGEaOfhOaHcefhHaeclfheaLhAaQcufgQmbkaOce4hOkcuadaO9Rcifg9ncx2a9nc;v:Q;v:Qe0Ecbyd1:jjjbHjjjjbbh8Pasc:Cefasyd;8egecdtfa8PBdbasaecefBd;8ecua9ncdta9ncFFFFi0Ecbyd1:jjjbHjjjjbbh9oasc:Cefasyd;8egecdtfa9oBdbasaecefBd;8ea3cbyd1:jjjbHjjjjbbhDasc:Cefasyd;8egecdtfaDBdbasaecefBd;8ealcbyd1:jjjbHjjjjbbh9pasc:Cefasyd;8egecdtfa9pBdbasaecefBd;8eaxaxNa8RJbbjZamclGEgnanN:vh88Jbbbbh86dnadak9nmbdna9nci6mbasyd:yeh9qa8Lclth9ra8Pcwfh9sJbbbbh87Jbbbbh86inascNefabadalaCz:cjjjbabh8Kcbh8Mcbh3inaba3cdtfhgcbheindnaCa8KaefydbgOcdtgXfydbgAaCagaec:W1jjbfydbcdtfydbgHcdtghfydbgQSmba5aHfRbbgKcv2a5aOfRbbgLfc;a1jjbfRbbg8JaLcv2aKfgEc;a1jjbfRbbg8AVcFeGTmbdnaQaA9nmbaEc;G1jjbfRbbcFeGmekdnaLcufcFeGce0mbaKTmba8EaXfydbaH9hmekdnaLTmbaKcufcFeGce0mba8FahfydbaO9hmeka8Pa8Mcx2fgAaHaOa8AcFeGgQEBdlaAaOaHaQEBdbaAaQa8JGcb9hBdwa8Mcefh8Mkaeclfgecx9hmbkdna3cifg3ad9pmba8Kcxfh8Ka8Mcifa9n9nmekka8MTmdcbhhinayaCa8Pahcx2fgKydbgQcdtgAfydbc8S2fgeIdwaaaKydlgLcx2fgHIdwg8XNaeIdzaHIdbg80NaeIdaMg8Ua8UMMa8XNaeIdlaHIdlg8ZNaeIdCa8XNaeId3Mg8Ua8UMMa8ZNaeIdba80NaeIdxa8ZNaeIdKMg8Ua8UMMa80NaeId8KMMM:lh8UJbbbbJbbjZaeIdyg8W:va8WJbbbb9BEh8WdndnaKydwg8KmbJFFuuh81xekJbbbbJbbjZayaCaLcdtfydbc8S2fgeIdygU:vaUJbbbb9BEaeIdwaaaQcx2fgHIdwgUNaeIdzaHIdbg8YNaeIdaMgBaBMMaUNaeIdlaHIdlgBNaeIdCaUNaeId3MgUaUMMaBNaeIdba8YNaeIdxaBNaeIdKMgUaUMMa8YNaeId8KMMM:lNh81ka8Wa8UNh8Vdna8LTmba8NaQc8S2fgHIdwa8XNaHIdza80NaHIdaMg8Ua8UMMa8XNaHIdla8ZNaHIdCa8XNaHId3Mg8Ua8UMMa8ZNaHIdba80NaHIdxa8ZNaHIdKMg8Ua8UMMa80NaHId8KMMMh8UaqaQa8L2ggcltfheaHIdyhUa8SaLa8L2gEcdtfgXhHa8LhOinaHIdbg8Wa8WaUNaecxfIdba8XaecwfIdbNa80aeIdbNa8ZaeclfIdbNMMMg8Wa8WM:tNa8UMh8UaHclfhHaeczfheaOcufgOmbkdndna8KmbJbbbbh8Wxeka8NaLc8S2fgOIdwaaaQcx2fgeIdwg8YNaOIdzaeIdbgBNaOIdaMg8Wa8WMMa8YNaOIdlaeIdlg83NaOIdCa8YNaOId3Mg8Wa8WMMa83NaOIdbaBNaOIdxa83NaOIdKMg8Wa8WMMaBNaOId8KMMMh8Wa8SagcdtfhHaqaEcltfheaOIdyhRa8LhOinaHIdbgUaUaRNaecxfIdba8YaecwfIdbNaBaeIdbNa83aeclfIdbNMMMgUaUM:tNa8WMh8WaHclfhHaeczfheaOcufgOmbka8W:lh8Wka8Va8U:lMh8Va81a8WMh81dndndna5aQfRbbc9:fPdbedkdna8Fa8Ea8EaAfydbaLSEaYaAfydbgXcdtfydbgAcu9hmbaYaLcdtfydbhAka8NaXc8S2fgOIdwaaaAcx2fgeIdwg8XNaOIdzaeIdbg80NaOIdaMg8Ua8UMMa8XNaOIdlaeIdlg8ZNaOIdCa8XNaOId3Mg8Ua8UMMa8ZNaOIdba80NaOIdxa8ZNaOIdKMg8Ua8UMMa80NaOId8KMMMh8Ua8SaAa8L2ggcdtfhHaqaXa8L2gEcltfheaOIdyhUa8LhOinaHIdbg8Wa8WaUNaecxfIdba8XaecwfIdbNa80aeIdbNa8ZaeclfIdbNMMMg8Wa8WM:tNa8UMh8UaHclfhHaeczfheaOcufgOmbkdndna8KmbJbbbbh8Wxeka8NaAc8S2fgOIdwaaaXcx2fgeIdwg80NaOIdzaeIdbg8ZNaOIdaMg8Wa8WMMa80NaOIdlaeIdlgUNaOIdCa80NaOId3Mg8Wa8WMMaUNaOIdba8ZNaOIdxaUNaOIdKMg8Wa8WMMa8ZNaOId8KMMMh8Wa8SaEcdtfhHaqagcltfheaOIdyh8Ya8LhOinaHIdbg8Xa8Xa8YNaecxfIdba80aecwfIdbNa8ZaeIdbNaUaeclfIdbNMMMg8Xa8XM:tNa8WMh8WaHclfhHaeczfheaOcufgOmbka8W:lh8Wka8Va8U:lMh8Va81a8WMh81xdkaYaAfydbgAaQSmbina8NaAc8S2fgHIdwa8XNaHIdza80NaHIdaMg8Ua8UMMa8XNaHIdla8ZNaHIdCa8XNaHId3Mg8Ua8UMMa8ZNaHIdba80NaHIdxa8ZNaHIdKMg8Ua8UMMa80NaHId8KMMMh8UaqaAa8L2cltfheaHIdyhUaXhHa8LhOinaHIdbg8Wa8WaUNaecxfIdba8XaecwfIdbNa80aeIdbNa8ZaeclfIdbNMMMg8Wa8WM:tNa8UMh8UaHclfhHaeczfheaOcufgOmbka8Va8U:lMh8VaYaAcdtfydbgAaQ9hmbkka5aLfRbbci9hmba8KTmbaYaLcdtfydbgAaLSmba8SagcdtfhXaaaQcx2fgeIdbh8XaeIdwh80aeIdlh8Zina8NaAc8S2fgHIdwa80NaHIdza8XNaHIdaMg8Ua8UMMa80NaHIdla8ZNaHIdCa80NaHId3Mg8Ua8UMMa8ZNaHIdba8XNaHIdxa8ZNaHIdKMg8Ua8UMMa8XNaHId8KMMMh8UaqaAa8L2cltfheaHIdyhUaXhHa8LhOinaHIdbg8Wa8WaUNaecxfIdba80aecwfIdbNa8XaeIdbNa8ZaeclfIdbNMMMg8Wa8WM:tNa8UMh8UaHclfhHaeczfheaOcufgOmbka81a8U:lMh81aYaAcdtfydbgAaL9hmbkkaKa81a8Va81a8V9DgeEUdwaKaQaLaea8Kcb9hGgeEBdlaKaLaQaeEBdbahcefgha8M9hmbkascjdfcbcj;qbz:rjjjb8Aa9shea8MhHinascjdfaeydbcA4cF8FGgOcFAaOcFA6EcdtfgOaOydbcefBdbaecxfheaHcufgHmbkcbhecbhHinascjdfaefgOydbhAaOaHBdbaAaHfhHaeclfgecj;qb9hmbkcbhea9shHinascjdfaHydbcA4cF8FGgOcFAaOcFA6EcdtfgOaOydbgOcefBdba9oaOcdtfaeBdbaHcxfhHa8Maecefge9hmbkadak9RgOci9Uh9tdnalTmbcbheaDhHinaHaeBdbaHclfhHalaecefge9hmbkkcbh9ua9pcbalz:rjjjbh3aOcO9Uh9va9tce4h9wcbh8Acbh8Jdnina8Pa9oa8Jcdtfydbcx2fgEIdwg8Ua889Emea8Aa9t9pmeJFFuuh8Wdna9wa8M9pmba8Pa9oa9wcdtfydbcx2fIdwJbb;aZNh8Wkdna8Ua8W9ETmba8Ua869ETmba8Aa9v0mdkdna3aCaEydlghcdtg9xfydbgAfg9yRbba3aCaEydbg8Kcdtg9zfydbgefg9ARbbVmba5a8KfRbbh9Bdna9maecdtfgHclfydbgOaHydbgHSmbaOaH9RhQaaaAcx2fhKaaaecx2fhXa9qaHcitfhecbhHcehgdnindnaDaeydbcdtfydbgOaASmbaDaeclfydbcdtfydbgLaASmbaOaLSmbaaaLcx2fgLIdbaaaOcx2fgOIdbg8X:tg8UaXIdlaOIdlg80:tg8YNaXIdba8X:tgBaLIdla80:tg8WN:tg8Za8UaKIdla80:tg83NaKIdba8X:tgRa8WN:tg80Na8WaXIdwaOIdwgU:tg8VNa8YaLIdwaU:tg8XN:tg8Ya8WaKIdwaU:tg81Na83a8XN:tg8WNa8XaBNa8Va8UN:tgUa8XaRNa81a8UN:tg8UNMMa8Za8ZNa8Ya8YNaUaUNMMa80a80Na8Wa8WNa8Ua8UNMMN:rJbbj8:N9FmdkaecwfheaHcefgHaQ6hgaQaH9hmbkkagceGTmba9wcefh9wxekdndndndna9Bc9:fPdebdka8KheinaDaecdtgefahBdbaYaefydbgea8K9hmbxikkdna8Fa8Ea8Ea9zfydbahSEaYa9zfydbg8Kcdtfydbgecu9hmbaYa9xfydbhekaDa9zfahBdbaehhkaDa8KcdtfahBdbka9Ace86bba9yce86bbaEIdwg8Ua86a86a8U9DEh86a9ucefh9ucecda9BceSEa8Afh8Aka8Jcefg8Ja8M9hmbkka9uTmddnalTmbcbhLcbhXindnaDaXcdtgefydbgOaXSmbaCaOcdtfydbh8KdnaXaCaefydb9hghmbaya8Kc8S2fgeayaXc8S2fgHIdbaeIdbMUdbaeaHIdlaeIdlMUdlaeaHIdwaeIdwMUdwaeaHIdxaeIdxMUdxaeaHIdzaeIdzMUdzaeaHIdCaeIdCMUdCaeaHIdKaeIdKMUdKaeaHId3aeId3MUd3aeaHIdaaeIdaMUdaaeaHId8KaeId8KMUd8KaeaHIdyaeIdyMUdyaITmbaIa8KcltfgeaIaXcltfgHIdbaeIdbMUdbaeaHIdlaeIdlMUdlaeaHIdwaeIdwMUdwaeaHIdxaeIdxMUdxka8LTmba8NaOc8S2fgea8NaXc8S2ggfgHIdbaeIdbMUdbaeaHIdlaeIdlMUdlaeaHIdwaeIdwMUdwaeaHIdxaeIdxMUdxaeaHIdzaeIdzMUdzaeaHIdCaeIdCMUdCaeaHIdKaeIdKMUdKaeaHId3aeId3MUd3aeaHIdaaeIdaMUdaaeaHId8KaeId8KMUd8KaeaHIdyaeIdyMUdya9raO2hKaqhHa8LhAinaHaKfgeaHaLfgOIdbaeIdbMUdbaeclfgQaOclfIdbaQIdbMUdbaecwfgQaOcwfIdbaQIdbMUdbaecxfgeaOcxfIdbaeIdbMUdbaHczfhHaAcufgAmbkahmbJbbbbJbbjZayagfgeIdyg8U:va8UJbbbb9BEaeIdwaaa8Kcx2fgHIdwg8UNaeIdzaHIdbg8WNaeIdaMg8Xa8XMMa8UNaeIdlaHIdlg8XNaeIdCa8UNaeId3Mg8Ua8UMMa8XNaeIdba8WNaeIdxa8XNaeIdKMg8Ua8UMMa8WNaeId8KMMM:lNg8Ua87a87a8U9DEh87kaLa9rfhLaXcefgXal9hmbkcbhHa8EheindnaeydbgOcuSmbdnaHaDaOcdtgAfydbgO9hmbcuhOa8EaAfydbgAcuSmbaDaAcdtfydbhOkaeaOBdbkaeclfhealaHcefgH9hmbkcbhHa8FheindnaeydbgOcuSmbdnaHaDaOcdtgAfydbgO9hmbcuhOa8FaAfydbgAcuSmbaDaAcdtfydbhOkaeaOBdbkaeclfhealaHcefgH9hmbkka87a86a8LEh87cbhHabhecbhOindnaCaDaeydbcdtfydbgLcdtfydbgAaCaDaeclfydbcdtfydbgKcdtfydbgQSmbaAaCaDaecwfydbcdtfydbg8KcdtfydbgXSmbaQaXSmbabaHcdtfgAaLBdbaAcwfa8KBdbaAclfaKBdbaHcifhHkaecxfheaOcifgOad6mbkdndna9imbaHhdxekdnaHak0mbaHhdxekdna85a879FmbaHhdxekJFFuuh85cbhdabhecbhOindna9ka0aeydbgAcdtfydbcdtfIdbg8Ua879ETmbaeclf8Pdbh9CabadcdtfgQaABdbaQclfa9C83dba8Ua85a85a8U9EEh85adcifhdkaecxfheaOcifgOaH6mbkkadak0mbxdkkascNefabadalaCz:cjjjbkdndnadak0mbadhOxekdna9imbadhOxekdna85a889FmbadhOxekcehLina85Jbb;aZNg8Ua88a8Ua889DEh8XJbbbbh8Udna6Tmba9khea6hHinaeIdbg8Wa8Ua8Wa8X9FEa8Ua8Wa8U9EEh8UaeclfheaHcufgHmbkkJFFuuh85cbhOabhecbhHindna9ka0aeydbgAcdtfydbcdtfIdbg8Wa8X9ETmbaeclf8Pdbh9CabaOcdtfgQaABdbaQclfa9C83dba8Wa85a85a8W9EEh85aOcifhOkaecxfheaHcifgHad6mbkdnaLaOad9hVceGmbadhOxdka8Ua86a86a8U9DEh86aOak9nmecbhLaOhda85a889FmbkkdnamcjjjjdGTmba9pcbalz:rjjjbhLdnaOTmbabheaOhHinaLaeydbgAfa5aAfRbbcl9h86bbaeclfheaHcufgHmbkkascNefabaOalaCz:cjjjbalTmbcbhQasyd:yehgindnaLaQfRbbTmbdna5aQfRbbgecl0mbceaetcQGmekdnaCaQcdtgKfydbgeaQSmbaaaQcx2fgHaaaecx2fge8Pdb83dbaHcwfaecwfydbBdbxekayaQc8S2fgeIdyg8Ua8UJL:3;rUNg8UMh88aeIdwa8UMhRaeIdla8UMh8VaeIdba8UMhUaeIdaa8UaaaQcx2fg8KIdwg89N:th81aeId3a8Ua8KIdlg8:N:th85aeIdKa8KIdbgZa8UN:th8YJbbbbhcaeIdCJbbbbMh87aeIdzJbbbbMhBaeIdxJbbbbMh83dndna8LTmbaQhAinJbbbba88a8NaAc8S2fgHIdyg8U:va8UJbbbb9BEh8UaqaAa8L2cltfheaHIdaa88Na81Mh81aHId3a88Na85Mh85aHIdKa88Na8YMh8YaHIdCa88Na87Mh87aHIdza88NaBMhBaHIdxa88Na83Mh83aHIdwa88NaRMhRaHIdla88Na8VMh8VaHIdba88NaUMhUa8LhHina81aecxfIdbg8ZaecwfIdbg8WNa8UN:th81a85a8ZaeclfIdbg8XNa8UN:th85a87a8Wa8XNa8UN:th87aUaeIdbg80a80Na8UN:thUa8Ya8Za80Na8UN:th8YaBa8Wa80Na8UN:thBa83a8Xa80Na8UN:th83aRa8Wa8WNa8UN:thRa8Va8Xa8XNa8UN:th8VaeczfheaHcufgHmbkaYaAcdtfydbgAaQ9hmbkaITmbaIaQcltfgeIdxhTaeIdwh9caeIdlhJaeIdbh8UxekJbbbbhTJbbbbh9cJbbbbhJJbbbbh8UkaBaU:vg8Xa8YNa81:ta87aBa83aU:vg8WN:tg81a8Va83a8WN:tg8Z:vg80a8Wa8YNa85:tg8VN:th85a9ca8Ua8XN:taJa8Ua8WN:tg83a80N:tg87aRaBa8XN:ta81a80N:tgB:vgR:mh81a83a8Z:vg9c:mhJdnJbbbba8Ua8UaU:vg9eN:ta83a9cN:ta87aRN:tg83:la88J:983:g81Ng8U9ETmba81a85NaJa8VNa9ea8YNaT:tMMa83:vhckaU:la8U9ETmba8Z:la8U9ETmbaB:la8U9ETmba9e:macNa8X:ma81acNa85aB:vMg85Na8W:maJacNa80:ma85Na8Va8Z:vMMg87Na8Y:maU:vMMMh88a9maKfgeclfydbgHaeydbge9RhXagaecitfhKJbbbbh8UdnaHaeSghmbJbbbbh8UaKheaXhAinaaaeclfydbcx2fgHIdwa89:tg8Wa8WNaHIdbaZ:tg8Wa8WNaHIdla8::tg8Wa8WNMMg8Waaaeydbcx2fgHIdwa89:tg8Xa8XNaHIdbaZ:tg8Xa8XNaHIdla8::tg8Xa8XNMMg8Xa8Ua8Ua8X9DEg8Ua8Ua8W9DEh8UaecwfheaAcufgAmbkka85a89:tg8Wa8WNa88aZ:tg8Wa8WNa87a8::tg8Wa8WNMMa8U:rg8Ua8UN9EmbdnahmbcbhAcehhdninaaaKclfydbcx2fgeIdbaaaKydbcx2fgHIdbg8X:tg8Ua8:aHIdlg80:tg8YNaZa8X:tgBaeIdla80:tg8WN:tg8Za8Ua87a80:tg83Na88a8X:tgRa8WN:tg80Na8Wa89aHIdwgU:tg8VNa8YaeIdwaU:tg8XN:tg8Ya8Wa85aU:tg81Na83a8XN:tg8WNa8XaBNa8Va8UN:tgUa8XaRNa81a8UN:tg8UNMMa8Za8ZNa8Ya8YNaUaUNMMa80a80Na8Wa8WNa8Ua8UNMMN:rJbbj8:N9FmeaKcwfhKaAcefgAaX6hhaXaA9hmbkkahceGmeka8Ka85Udwa8Ka87Udla8Ka88UdbkaQcefgQal9hmbkdndna8LTmba8LclthYa8Lcdth8KcbhKa8ShXindnaLaKfRbbTmba5aKfRbbclSmbJbbbbJbbjZa8NaKc8S2fIdyg8U:va8UJbbbb9BEh8UaaaCaKcdtfydbcx2fhHaqheaXhAa8LhQinaAa8UaecwfIdbaHIdwNaeIdbaHIdbNaeclfIdbaHIdlNMMaecxfIdbMNUdbaeczfheaAclfhAaQcufgQmbkkaqaYfhqaXa8KfhXaKcefgKal9hmbkarcd4hXavcd4hYasId:qeh8UasId:meh8WasId1eh8XazTmea8Lcdth8KcbhKindnaLaKfRbbTmbaiazaKcdtfydbgCaY2cdtfgeaaaKcx2fgHIdba8RNa8XMUdbaeaHIdla8RNa8WMUdlaeaHIdwa8RNa8UMUdwaoaCaX2cdtfhQashea8ShHa8LhCinaQaeydbcdtgAfaHIdbawaAfIdb:vUdbaeclfheaHclfhHaCcufgCmbkka8Sa8Kfh8SaKcefgKal9hmbxikkavcd4hCasId:qeh8UasId:meh8WasId1eh8XdnazTmbazheindna9pRbbTmbaiaeydbaC2cdtfgHaaIdba8RNa8XMUdbaHaaclfIdba8RNa8WMUdlaHaacwfIdba8RNa8UMUdwka9pcefh9paeclfheaacxfhaalcufglmbxikkaCcdtheindna9pRbbTmbaiaaIdba8RNa8XMUdbaiclfaaclfIdba8RNa8WMUdbaicwfaacwfIdba8RNa8UMUdbka9pcefh9paacxfhaaiaefhialcufglmbxdkka8Lcdth8KcbhKindnaLaKfRbbTmbaiaKaY2cdtfgeaaaKcx2fgHIdba8RNa8XMUdbaeaHIdla8RNa8WMUdlaeaHIdwa8RNa8UMUdwaoaKaX2cdtfhQashea8ShHa8LhCinaQaeydbcdtgAfaHIdbawaAfIdb:vUdbaeclfheaHclfhHaCcufgCmbkka8Sa8Kfh8SaKcefgKal9hmbkkdnamcjjjjlGTmbazmbaOTmbcbhLabheina5aeydbgAfRbbc3thKaecwfgXydbhHdndna8EaAcdtg8KfydbaeclfgYydbgCSmbcbhQa8FaCcdtfydbaA9hmekcjjjj94hQkaeaKaQVaAVBdba5aCfRbbc3thKdndna8EaCcdtfydbaHSmbcbhQa8FaHcdtfydbaC9hmekcjjjj94hQkaYaKaQVaCVBdba5aHfRbbc3thQdndna8EaHcdtfydbaASmbcbhCa8Fa8KfydbaH9hmekcjjjj94hCkaXaQaCVaHVBdbaecxfheaLcifgLaO6mbkkdnazTmbaOTmbaOheinabazabydbcdtfydbBdbabclfhbaecufgembkkdnaPTmbaPana86:rNUdbkasyd;8egecdtasc:Ceffc98fhHdninaeTmeaHydbcbyd:m:jjjbH:bjjjbbaHc98fhHaecufhexbkkascj;sbf8KjjjjbaOk;Yieouabydlhvabydbclfcbaicdtz:rjjjbhoadci9UhrdnadTmbdnalTmbaehwadhDinaoalawydbcdtfydbcdtfgqaqydbcefBdbawclfhwaDcufgDmbxdkkaehwadhDinaoawydbcdtfgqaqydbcefBdbawclfhwaDcufgDmbkkdnaiTmbcbhDaohwinawydbhqawaDBdbawclfhwaqaDfhDaicufgimbkkdnadci6mbinaecwfydbhwaeclfydbhDaeydbhidnalTmbalawcdtfydbhwalaDcdtfydbhDalaicdtfydbhikavaoaicdtfgqydbcitfaDBdbavaqydbcitfawBdlaqaqydbcefBdbavaoaDcdtfgqydbcitfawBdbavaqydbcitfaiBdlaqaqydbcefBdbavaoawcdtfgwydbcitfaiBdbavawydbcitfaDBdlawawydbcefBdbaecxfhearcufgrmbkkabydbcbBdbk:todDue99aicd4aifhrcehwinawgDcethwaDar6mbkcuaDcdtgraDcFFFFi0Ecbyd1:jjjbHjjjjbbhwaoaoyd9GgqcefBd9GaoaqcdtfawBdbawcFearz:rjjjbhkdnaiTmbalcd4hlaDcufhxcbhminamhDdnavTmbavamcdtfydbhDkcbadaDal2cdtfgDydlgwawcjjjj94SEgwcH4aw7c:F:b:DD2cbaDydbgwawcjjjj94SEgwcH4aw7c;D;O:B8J27cbaDydwgDaDcjjjj94SEgDcH4aD7c:3F;N8N27axGhwamcdthPdndndnavTmbakawcdtfgrydbgDcuSmeadavaPfydbal2cdtfgsIdbhzcehqinaqhrdnadavaDcdtfydbal2cdtfgqIdbaz9CmbaqIdlasIdl9CmbaqIdwasIdw9BmlkarcefhqakawarfaxGgwcdtfgrydbgDcu9hmbxdkkakawcdtfgrydbgDcuSmbadamal2cdtfgsIdbhzcehqinaqhrdnadaDal2cdtfgqIdbaz9CmbaqIdlasIdl9CmbaqIdwasIdw9BmikarcefhqakawarfaxGgwcdtfgrydbgDcu9hmbkkaramBdbamhDkabaPfaDBdbamcefgmai9hmbkkakcbyd:m:jjjbH:bjjjbbaoaoyd9GcufBd9GdnaeTmbaiTmbcbhDaehwinawaDBdbawclfhwaiaDcefgD9hmbkcbhDaehwindnaDabydbgrSmbawaearcdtfgrydbBdbaraDBdbkawclfhwabclfhbaiaDcefgD9hmbkkk:hrdvuv998Jjjjjbca9Rgoczfcwfcbyd11jjbBdbaocb8Pdj1jjb83izaocwfcbydN1jjbBdbaocb8Pd:m1jjb83ibdnadTmbaicd4hrdnabmbdnalTmbcbhwinaealawcdtfydbar2cdtfhDcbhiinaoczfaifgqaDaifIdbgkaqIdbgxaxak9EEUdbaoaifgqakaqIdbgxaxak9DEUdbaiclfgicx9hmbkawcefgwad9hmbxikkarcdthwcbhDincbhiinaoczfaifgqaeaifIdbgkaqIdbgxaxak9EEUdbaoaifgqakaqIdbgxaxak9DEUdbaiclfgicx9hmbkaeawfheaDcefgDad9hmbxdkkdnalTmbcbhwinabawcx2fgiaealawcdtfydbar2cdtfgDIdbUdbaiaDIdlUdlaiaDIdwUdwcbhiinaoczfaifgqaDaifIdbgkaqIdbgxaxak9EEUdbaoaifgqakaqIdbgxaxak9DEUdbaiclfgicx9hmbkawcefgwad9hmbxdkkarcdthlcbhwaehDinabawcx2fgiaeawar2cdtfgqIdbUdbaiaqIdlUdlaiaqIdwUdwcbhiinaoczfaifgqaDaifIdbgkaqIdbgxaxak9EEUdbaoaifgqakaqIdbgxaxak9DEUdbaiclfgicx9hmbkaDalfhDawcefgwad9hmbkkJbbbbaoIdbaoIdzgx:tgkakJbbbb9DEgkaoIdlaoIdCgm:tgPaPak9DEgkaoIdwaoIdKgP:tgsasak9DEhsdnabTmbadTmbJbbbbJbbjZas:vasJbbbb9BEhkinabakabIdbax:tNUdbabclfgoakaoIdbam:tNUdbabcwfgoakaoIdbaP:tNUdbabcxfhbadcufgdmbkkdnavTmbavaPUdwavamUdlavaxUdbkask:ZlewudnaeTmbcbhvabhoinaoavBdbaoclfhoaeavcefgv9hmbkkdnaiTmbcbhrinadarcdtfhwcbhDinalawaDcdtgvc:G1jjbfydbcdtfydbcdtfydbhodnabalawavfydbcdtfydbgqcdtfgkydbgvaqSmbinakabavgqcdtfgxydbgvBdbaxhkaqav9hmbkkdnabaocdtfgkydbgvaoSmbinakabavgocdtfgxydbgvBdbaxhkaoav9hmbkkdnaqaoSmbabaqaoaqao0Ecdtfaqaoaqao6EBdbkaDcefgDci9hmbkarcifgrai6mbkkdnaembcbskcbhxindnalaxcdtgvfydbax9hmbaxhodnabavfgDydbgvaxSmbaDhqinaqabavgocdtfgkydbgvBdbakhqaoav9hmbkkaDaoBdbkaxcefgxae9hmbkcbhvabhocbhkindndnavalydbgq9hmbdnavaoydbgq9hmbaoakBdbakcefhkxdkaoabaqcdtfydbBdbxekaoabaqcdtfydbBdbkaoclfhoalclfhlaeavcefgv9hmbkakk;Jiilud99duabcbaecltz:rjjjbhvdnalTmbadhoaihralhwinarcwfIdbhDarclfIdbhqavaoydbcltfgkarIdbakIdbMUdbakclfgxaqaxIdbMUdbakcwfgxaDaxIdbMUdbakcxfgkakIdbJbbjZMUdbaoclfhoarcxfhrawcufgwmbkkdnaeTmbavhraehkinarcxfgoIdbhDaocbBdbararIdbJbbbbJbbjZaD:vaDJbbbb9BEgDNUdbarclfgoaDaoIdbNUdbarcwfgoaDaoIdbNUdbarczfhrakcufgkmbkkdnalTmbinavadydbcltfgrcxfgkaicwfIdbarcwfIdb:tgDaDNaiIdbarIdb:tgDaDNaiclfIdbarclfIdb:tgDaDNMMgDakIdbgqaqaD9DEUdbadclfhdaicxfhialcufglmbkkdnaeTmbavcxfhrinabarIdbUdbarczfhrabclfhbaecufgembkkk8MbabaeadaialavcbcbcbcbcbaoarawaDz:bjjjbk8MbabaeadaialavaoarawaDaqakaxamaPz:bjjjbkRbababaeadaialavaoarawaDaqakaxcjjjjdVamz:bjjjbk:p8Koque99due99iuq998Jjjjjbc;Wb9Rgq8Kjjjjbcbhkaqcxfcbc;Kbz:rjjjb8Aaqcualcx2alc;v:Q;v:Qe0Ecbyd1:jjjbHjjjjbbgxBdxaqceBd2axaialavcbcbz:ejjjb8AaqcualcdtalcFFFFi0Egmcbyd1:jjjbHjjjjbbgiBdzaqcdBd2dndnJFF959eJbbjZawJbbjZawJbbjZ9DE:vawJ9VO:d869DEgw:lJbbb9p9DTmbaw:OhPxekcjjjj94hPkadci9Uhsarco9UhzdndnaombaPcd9imekdnalTmbaPcuf:YhwdnaoTmbcbhvaihHaxhOindndnaoavfRbbceGTmbavcjjjjlVhAxekdndnaOclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhAxekcjjjj94hAkaAcqthAdndnaOcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaAaXVhAdndnaOIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaAaXcCtVhAkaHaABdbaHclfhHaOcxfhOalavcefgv9hmbxdkkaxhvaihOalhHindndnavIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhAxekcjjjj94hAkaAcCthAdndnavclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaXcqtaAVhAdndnavcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaOaAaXVBdbavcxfhvaOclfhOaHcufgHmbkkadTmbcbhkaehvcbhOinakaiavclfydbcdtfydbgHaiavcwfydbcdtfydbgA9haiavydbcdtfydbgXaH9haXaA9hGGfhkavcxfhvaOcifgOad6mbkkarci9UhQdndnaz:Z:rJbbbZMgw:lJbbb9p9DTmbaw:Ohvxekcjjjj94hvkaQ:ZhLcbhKc:bwhHdndninashYaHhXaPhrakg8AaQ9pmeaXar9Rcd9imeavaXcufavaX9iEarcefavar9kEhzdnalTmbazcuf:YhwdnaoTmbcbhOaihPaxhvindndnaoaOfRbbceGTmbaOcjjjjlVhHxekdndnavclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhHxekcjjjj94hHkaHcqthHdndnavcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:Ohsxekcjjjj94hskaHasVhHdndnavIdbawNJbbbZMgC:lJbbb9p9DTmbaC:Ohsxekcjjjj94hskaHascCtVhHkaPaHBdbaPclfhPavcxfhvalaOcefgO9hmbxdkkaxhvaihOalhPindndnavIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhHxekcjjjj94hHkaHcCthHdndnavclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:Ohsxekcjjjj94hskascqtaHVhHdndnavcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:Ohsxekcjjjj94hskaOaHasVBdbavcxfhvaOclfhOaPcufgPmbkkcbhOdnadTmbaehvcbhPinaOaiavclfydbcdtfydbgHaiavcwfydbcdtfydbgs9haiavydbcdtfydbgAaH9haAas9hGGfhOavcxfhvaPcifgPad6mbkkaYhsaOhkaXhHazhPdnaOaQ9nmbaOhsa8AhkazhHarhPkdndnaKcl0mbdnaY:Zgwa8A:ZgC:taz:YgEar:Y:tg3aEaX:Y:tg5aO:Zg8EaL:tNNNawaL:ta5NaCa8E:tNaCaL:ta3Na8Eaw:tNM:vaEMJbbbZMgw:lJbbb9p9DTmbaw:Ohvxdkcjjjj94hvxekaPaHfcd9ThvkaKcefgKcs9hmbxdkka8AhkarhPkdndndnakmbJbbjZhwcbhicdhvaDmexdkalcd4alfhHcehOinaOgvcethOavaH6mbkcbhOaqcuavcdtgravcFFFFi0Ecbyd1:jjjbHjjjjbbgzBdCaqciBd2aqamcbyd1:jjjbHjjjjbbgXBdKaqclBd2dndndndnalTmbaPcuf:YhwaoTmecbhOaihHaxhPindndnaoaOfRbbceGTmbaOcjjjjlVhsxekdndnaPclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:Ohsxekcjjjj94hskascqthsdndnaPcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhAxekcjjjj94hAkasaAVhsdndnaPIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhAxekcjjjj94hAkasaAcCtVhskaHasBdbaHclfhHaPcxfhPalaOcefgO9hmbxikkazcFearz:rjjjb8AcbhrcbhvxdkaxhOaihPalhHindndnaOIdbawNJbbbZMgC:lJbbb9p9DTmbaC:Ohsxekcjjjj94hskascCthsdndnaOclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhAxekcjjjj94hAkaAcqtasVhsdndnaOcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhAxekcjjjj94hAkaPasaAVBdbaOcxfhOaPclfhPaHcufgHmbkkazcFearz:rjjjbhAavcufhocbhrcbhzindndndnaAaiazcdtgKfydbgHcm4aH7c:v;t;h;Ev2gvcs4av7aoGgPcdtfgsydbgOcuSmbcehvinaiaOcdtgOfydbaHSmdaPavfhOavcefhvaAaOaoGgPcdtfgsydbgOcu9hmbkkasazBdbarhvarcefhrxekaXaOfydbhvkaXaKfavBdbazcefgzal9hmbkcuarc8S2gOarc;D;O;f8U0EhvkcbhAaqavcbyd1:jjjbHjjjjbbgvBd3aqcvBd2avcbaOz:rjjjbhOdnadTmbaehiinJbbnnJbbjZaXaiydbgHcdtfydbgvaXaiclfydbgPcdtfydbgzSavaXaicwfydbgscdtfydbgKSGgoEh8FdnaxaPcx2fgPIdbaxaHcx2fgHIdbg8E:tgCaxascx2fgsIdlaHIdlg3:tgwNasIdba8E:tgEaPIdla3:tgaN:tgLaLNaaasIdwaHIdwg5:tghNawaPIdwa5:tgaN:tgwawNaaaENahaCN:tgCaCNMM:rgEJbbbb9ETmbaLaE:vhLaCaE:vhCawaE:vhwkaOavc8S2fgvavIdbawa8FaE:rNgEawNNgaMUdbavaCaEaCNghNggavIdlMUdlavaLaEaLNg8FNg8JavIdwMUdwavahawNghavIdxMUdxava8FawNg8KavIdzMUdzava8FaCNg8FavIdCMUdCavawaEaLa5Nawa8ENa3aCNMM:mg3Ng8ENgwavIdKMUdKavaCa8ENgCavId3MUd3avaLa8ENgLavIdaMUdaava8Ea3Ng8EavId8KMUd8KavaEavIdyMUdydnaombaOazc8S2fgvaaavIdbMUdbavagavIdlMUdlava8JavIdwMUdwavahavIdxMUdxava8KavIdzMUdzava8FavIdCMUdCavawavIdKMUdKavaCavId3MUd3avaLavIdaMUdaava8EavId8KMUd8KavaEavIdyMUdyaOaKc8S2fgvaaavIdbMUdbavagavIdlMUdlava8JavIdwMUdwavahavIdxMUdxava8KavIdzMUdzava8FavIdCMUdCavawavIdKMUdKavaCavId3MUd3avaLavIdaMUdaava8EavId8KMUd8KavaEavIdyMUdykaicxfhiaAcifgAad6mbkkcbhHaqcuarcdtgvarcFFFFi0Egicbyd1:jjjbHjjjjbbgPBdaaqcoBd2aqaicbyd1:jjjbHjjjjbbgiBd8KaqcrBd2aPcFeavz:rjjjbhzdnalTmbaXhPinJbbbbJbbjZaOaPydbgsc8S2fgvIdygw:vawJbbbb9BEavIdwaxcwfIdbgwNavIdzaxIdbgCNavIdaMgLaLMMawNavIdlaxclfIdbgLNavIdCawNavId3MgwawMMaLNavIdbaCNavIdxaLNavIdKMgwawMMaCNavId8KMMM:lNhwdndnazascdtgvfgsydbcuSmbaiavfIdbaw9ETmekasaHBdbaiavfawUdbkaPclfhPaxcxfhxalaHcefgH9hmbkkJbbbbhwdnarTmbinaiIdbgCawawaC9DEhwaiclfhiarcufgrmbkkakcd4akfhOcehiinaigvcethiavaO6mbkcbhiaqcuavcdtgOavcFFFFi0Ecbyd1:jjjbHjjjjbbgPBdyaPcFeaOz:rjjjbhsdnadTmbavcufhAcbhrcbhxindnaXaeaxcdtfgvydbcdtfydbgiaXavclfydbcdtfydbgOSmbaiaXavcwfydbcdtfydbgvSmbaOavSmbazavcdtfydbhHdndnazaOcdtfydbgvazaicdtfydbgi9pmbavaH9pmbaHhlaihoavhHxekdnaHai9pmbaHav9pmbaihlavhoxekavhlaHhoaihHkabarcx2fgvaHBdbavcwfaoBdbavclfalBdbdnasaoc:3F;N8N2alc:F:b:DD27aHc;D;O:B8J27aAGgOcdtfgvydbgicuSmbcehPinaPhvdnabaicx2fgiydbaH9hmbaiydlal9hmbaiydwaoSmikavcefhPasaOavfaAGgOcdtfgvydbgicu9hmbkkavarBdbarcefhrkaxcifgxad6mbkarci2hikdnaDmbcwhvxdkaw:rhwcwhvkaDawUdbkavcdthvdninavTmeavc98fgvaqcxffydbcbyd:m:jjjbH:bjjjbbxbkkaqc;Wbf8Kjjjjbaik:2ldwue9:8Jjjjjbc;Wb9Rgr8Kjjjjbcbhwarcxfcbc;Kbz:rjjjb8AdnabaeSmbabaeadcdtz:qjjjb8AkarcualcdtalcFFFFi0EgDcbyd1:jjjbHjjjjbbgqBdxarceBd2aqcbaialavcbarcxfz:djjjbcualcx2alc;v:Q;v:Qe0Ecbyd1:jjjbHjjjjbbhkarcxfaryd2gxcdtgmfakBdbaraxcefgPBd2akaialavcbcbz:ejjjb8AarcxfaPcdtfaDcbyd1:jjjbHjjjjbbgvBdbaraxcdfgiBd2arcxfaicdtfcuavalaeadaqz:fjjjbgecltaecjjjjiGEcbyd1:jjjbHjjjjbbgiBdbaiaeavakalz:gjjjbdnadTmbaoaoNhocbhwabhlcbhkindnaiavalydbgecdtfydbcdtfIdbao9ETmbalclf8PdbhsabawcdtfgqaeBdbaqclfas83dbawcifhwkalcxfhlakcifgkad6mbkkaxcifhlamarcxffcwfhkdninalTmeakydbcbyd:m:jjjbH:bjjjbbakc98fhkalcufhlxbkkarc;Wbf8Kjjjjbawk:FCoDud99rue99iul998Jjjjjbc;Wb9Rgw8KjjjjbdndnarmbcbhDxekawcxfcbc;Kbz:rjjjb8Aawcuadcx2adc;v:Q;v:Qe0Ecbyd1:jjjbHjjjjbbgqBdxawceBd2aqaeadaicbcbz:ejjjb8AawcuadcdtadcFFFFi0Egkcbyd1:jjjbHjjjjbbgxBdzawcdBd2adcd4adfhmceheinaegicetheaiam6mbkcbhPawcuaicdtgsaicFFFFi0Ecbyd1:jjjbHjjjjbbgzBdCawciBd2dndnar:ZgH:rJbbbZMgO:lJbbb9p9DTmbaO:Ohexekcjjjj94hekaicufhAc:bwhmcbhCadhXcbhQinaChLaeamgKcufaeaK9iEaPgDcefaeaD9kEhYdndnadTmbaYcuf:YhOaqhiaxheadhmindndnaiIdbaONJbbbZMg8A:lJbbb9p9DTmba8A:OhCxekcjjjj94hCkaCcCthCdndnaiclfIdbaONJbbbZMg8A:lJbbb9p9DTmba8A:OhExekcjjjj94hEkaEcqtaCVhCdndnaicwfIdbaONJbbbZMg8A:lJbbb9p9DTmba8A:OhExekcjjjj94hEkaeaCaEVBdbaicxfhiaeclfheamcufgmmbkazcFeasz:rjjjbh3cbh5cbhPindna3axaPcdtfydbgCcm4aC7c:v;t;h;Ev2gics4ai7aAGgmcdtfgEydbgecuSmbaeaCSmbcehiina3amaifaAGgmcdtfgEydbgecuSmeaicefhiaeaC9hmbkkaEaCBdba5aecuSfh5aPcefgPad9hmbxdkkazcFeasz:rjjjb8Acbh5kaDaYa5ar0giEhPaLa5aiEhCdna5arSmbaYaKaiEgmaP9Rcd9imbdndnaQcl0mbdnaX:ZgOaL:Zg8A:taY:Yg8EaD:Y:tg8Fa8EaK:Y:tgaa5:ZghaH:tNNNaOaH:taaNa8Aah:tNa8AaH:ta8FNahaO:tNM:va8EMJbbbZMgO:lJbbb9p9DTmbaO:Ohexdkcjjjj94hexekaPamfcd9Theka5aXaiEhXaQcefgQcs9hmekkdndnaCmbcihicbhDxekcbhiawakcbyd1:jjjbHjjjjbbg5BdKawclBd2aPcuf:Yh8AdndnadTmbaqhiaxheadhmindndnaiIdba8ANJbbbZMgO:lJbbb9p9DTmbaO:OhCxekcjjjj94hCkaCcCthCdndnaiclfIdba8ANJbbbZMgO:lJbbb9p9DTmbaO:OhExekcjjjj94hEkaEcqtaCVhCdndnaicwfIdba8ANJbbbZMgO:lJbbb9p9DTmbaO:OhExekcjjjj94hEkaeaCaEVBdbaicxfhiaeclfheamcufgmmbkazcFeasz:rjjjbh3cbhDcbhYindndndna3axaYcdtgKfydbgCcm4aC7c:v;t;h;Ev2gics4ai7aAGgmcdtfgEydbgecuSmbcehiinaxaecdtgefydbaCSmdamaifheaicefhia3aeaAGgmcdtfgEydbgecu9hmbkkaEaYBdbaDhiaDcefhDxeka5aefydbhika5aKfaiBdbaYcefgYad9hmbkcuaDc32giaDc;j:KM;jb0EhexekazcFeasz:rjjjb8AcbhDcbhekawaecbyd1:jjjbHjjjjbbgeBd3awcvBd2aecbaiz:rjjjbhEavcd4hKdnadTmbdnalTmbaKcdth3a5hCaqhealhmadhAinaEaCydbc32fgiaeIdbaiIdbMUdbaiaeclfIdbaiIdlMUdlaiaecwfIdbaiIdwMUdwaiamIdbaiIdxMUdxaiamclfIdbaiIdzMUdzaiamcwfIdbaiIdCMUdCaiaiIdKJbbjZMUdKaCclfhCaecxfheama3fhmaAcufgAmbxdkka5hmaqheadhCinaEamydbc32fgiaeIdbaiIdbMUdbaiaeclfIdbaiIdlMUdlaiaecwfIdbaiIdwMUdwaiaiIdxJbbbbMUdxaiaiIdzJbbbbMUdzaiaiIdCJbbbbMUdCaiaiIdKJbbjZMUdKamclfhmaecxfheaCcufgCmbkkdnaDTmbaEhiaDheinaiaiIdbJbbbbJbbjZaicKfIdbgO:vaOJbbbb9BEgONUdbaiclfgmaOamIdbNUdbaicwfgmaOamIdbNUdbaicxfgmaOamIdbNUdbaiczfgmaOamIdbNUdbaicCfgmaOamIdbNUdbaic3fhiaecufgembkkcbhCawcuaDcdtgYaDcFFFFi0Egicbyd1:jjjbHjjjjbbgeBdaawcoBd2awaicbyd1:jjjbHjjjjbbg3Bd8KaecFeaYz:rjjjbhxdnadTmbJbbjZJbbjZa8A:vaPceSEaoNgOaONh8AaKcdthPalheina8Aaec;81jjbalEgmIdwaEa5ydbgAc32fgiIdC:tgOaONamIdbaiIdx:tgOaONamIdlaiIdz:tgOaONMMNaqcwfIdbaiIdw:tgOaONaqIdbaiIdb:tgOaONaqclfIdbaiIdl:tgOaONMMMhOdndnaxaAcdtgifgmydbcuSmba3aifIdbaO9ETmekamaCBdba3aifaOUdbka5clfh5aqcxfhqaeaPfheadaCcefgC9hmbkkabaxaYz:qjjjb8AcrhikaicdthiinaiTmeaic98fgiawcxffydbcbyd:m:jjjbH:bjjjbbxbkkawc;Wbf8KjjjjbaDk:Ydidui99ducbhi8Jjjjjbca9Rglczfcwfcbyd11jjbBdbalcb8Pdj1jjb83izalcwfcbydN1jjbBdbalcb8Pd:m1jjb83ibdndnaembJbbjFhvJbbjFhoJbbjFhrxekadcd4cdthwincbhdinalczfadfgDabadfIdbgvaDIdbgoaoav9EEUdbaladfgDavaDIdbgoaoav9DEUdbadclfgdcx9hmbkabawfhbaicefgiae9hmbkalIdwalIdK:thralIdlalIdC:thoalIdbalIdz:thvkJbbbbavavJbbbb9DEgvaoaoav9DEgvararav9DEk9DeeuabcFeaicdtz:rjjjbhlcbhbdnadTmbindnalaeydbcdtfgiydbcu9hmbaiabBdbabcefhbkaeclfheadcufgdmbkkabk9teiucbcbyd:q:jjjbgeabcifc98GfgbBd:q:jjjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaik;teeeudndnaeabVciGTmbabhixekdndnadcz9pmbabhixekabhiinaiaeydbBdbaiaeydlBdlaiaeydwBdwaiaeydxBdxaeczfheaiczfhiadc9Wfgdcs0mbkkadcl6mbinaiaeydbBdbaeclfheaiclfhiadc98fgdci0mbkkdnadTmbinaiaeRbb86bbaicefhiaecefheadcufgdmbkkabk:3eedudndnabciGTmbabhixekaecFeGc:b:c:ew2hldndnadcz9pmbabhixekabhiinaialBdxaialBdwaialBdlaialBdbaiczfhiadc9Wfgdcs0mbkkadcl6mbinaialBdbaiclfhiadc98fgdci0mbkkdnadTmbinaiae86bbaicefhiadcufgdmbkkabk9teiucbcbyd:q:jjjbgeabcrfc94GfgbBd:q:jjjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaik9:eiuZbhedndncbyd:q:jjjbgdaecztgi9nmbcuheadai9RcFFifcz4nbcuSmekadhekcbabae9Rcifc98Gcbyd:q:jjjbfgdBd:q:jjjbdnadZbcztge9nmbadae9RcFFifcz4nb8Akkk:Iedbcjwk1eFFuuFFuuFFuuFFuFFFuFFFuFbbbbbbbbebbbdbbbbbbbebbbebbbdbbbbbbbbbbbeeeeebebbebbebebbbeebbbbbbbbbbbbeeeeeebebbeeebeebbbbebebbbbbbbbbbbbbbbbbbc1Dkxebbbdbbb:GNbb";
var wasmpack = new Uint8Array([
32,
0,
65,
2,
1,
106,
34,
33,
3,
128,
11,
4,
13,
64,
6,
253,
10,
7,
15,
116,
127,
5,
8,
12,
40,
16,
19,
54,
20,
9,
27,
255,
113,
17,
42,
67,
24,
23,
146,
148,
18,
14,
22,
45,
70,
69,
56,
114,
101,
21,
25,
63,
75,
136,
108,
28,
118,
29,
73,
115
]);
if (typeof WebAssembly !== "object") {
return {
supported: false
};
}
var instance;
var ready = WebAssembly.instantiate(unpack(wasm), {}).then(function(result) {
instance = result.instance;
instance.exports.__wasm_call_ctors();
});
function unpack(data) {
var result = new Uint8Array(data.length);
for (var i = 0; i < data.length; ++i) {
var ch = data.charCodeAt(i);
result[i] = ch > 96 ? ch - 97 : ch > 64 ? ch - 39 : ch + 4;
}
var write = 0;
for (var i = 0; i < data.length; ++i) {
result[write++] = result[i] < 60 ? wasmpack[result[i]] : (result[i] - 60) * 64 + result[++i];
}
return result.buffer.slice(0, write);
}
function assert(cond) {
if (!cond) {
throw new Error("Assertion failed");
}
}
function bytes(view) {
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
}
function reorder(fun, indices, vertices) {
var sbrk = instance.exports.sbrk;
var ip = sbrk(indices.length * 4);
var rp = sbrk(vertices * 4);
var heap = new Uint8Array(instance.exports.memory.buffer);
var indices8 = bytes(indices);
heap.set(indices8, ip);
var unique = fun(rp, ip, indices.length, vertices);
heap = new Uint8Array(instance.exports.memory.buffer);
var remap = new Uint32Array(vertices);
new Uint8Array(remap.buffer).set(heap.subarray(rp, rp + vertices * 4));
indices8.set(heap.subarray(ip, ip + indices.length * 4));
sbrk(ip - sbrk(0));
for (var i = 0; i < indices.length; ++i) indices[i] = remap[indices[i]];
return [remap, unique];
}
function maxindex(source) {
var result = 0;
for (var i = 0; i < source.length; ++i) {
var index = source[i];
result = result < index ? index : result;
}
return result;
}
function simplify(fun, indices, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count, target_error, options) {
var sbrk = instance.exports.sbrk;
var te = sbrk(4);
var ti = sbrk(index_count * 4);
var sp = sbrk(vertex_count * vertex_positions_stride);
var si = sbrk(index_count * 4);
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(vertex_positions), sp);
heap.set(bytes(indices), si);
var result = fun(ti, si, index_count, sp, vertex_count, vertex_positions_stride, target_index_count, target_error, options, te);
heap = new Uint8Array(instance.exports.memory.buffer);
var target = new Uint32Array(result);
bytes(target).set(heap.subarray(ti, ti + result * 4));
var error = new Float32Array(1);
bytes(error).set(heap.subarray(te, te + 4));
sbrk(te - sbrk(0));
return [target, error[0]];
}
function simplifyAttr(fun, indices, index_count, vertex_positions, vertex_count, vertex_positions_stride, vertex_attributes, vertex_attributes_stride, attribute_weights, vertex_lock, target_index_count, target_error, options) {
var sbrk = instance.exports.sbrk;
var te = sbrk(4);
var ti = sbrk(index_count * 4);
var sp = sbrk(vertex_count * vertex_positions_stride);
var sa = sbrk(vertex_count * vertex_attributes_stride);
var sw = sbrk(attribute_weights.length * 4);
var si = sbrk(index_count * 4);
var vl = vertex_lock ? sbrk(vertex_count) : 0;
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(vertex_positions), sp);
heap.set(bytes(vertex_attributes), sa);
heap.set(bytes(attribute_weights), sw);
heap.set(bytes(indices), si);
if (vertex_lock) {
heap.set(bytes(vertex_lock), vl);
}
var result = fun(
ti,
si,
index_count,
sp,
vertex_count,
vertex_positions_stride,
sa,
vertex_attributes_stride,
sw,
attribute_weights.length,
vl,
target_index_count,
target_error,
options,
te
);
heap = new Uint8Array(instance.exports.memory.buffer);
var target = new Uint32Array(result);
bytes(target).set(heap.subarray(ti, ti + result * 4));
var error = new Float32Array(1);
bytes(error).set(heap.subarray(te, te + 4));
sbrk(te - sbrk(0));
return [target, error[0]];
}
function simplifyUpdate(fun, indices, index_count, vertex_positions, vertex_count, vertex_positions_stride, vertex_attributes, vertex_attributes_stride, attribute_weights, vertex_lock, target_index_count, target_error, options) {
var sbrk = instance.exports.sbrk;
var te = sbrk(4);
var sp = sbrk(vertex_count * vertex_positions_stride);
var sa = sbrk(vertex_count * vertex_attributes_stride);
var sw = sbrk(attribute_weights.length * 4);
var si = sbrk(index_count * 4);
var vl = vertex_lock ? sbrk(vertex_count) : 0;
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(vertex_positions), sp);
heap.set(bytes(vertex_attributes), sa);
heap.set(bytes(attribute_weights), sw);
heap.set(bytes(indices), si);
if (vertex_lock) {
heap.set(bytes(vertex_lock), vl);
}
var result = fun(
si,
index_count,
sp,
vertex_count,
vertex_positions_stride,
sa,
vertex_attributes_stride,
sw,
attribute_weights.length,
vl,
target_index_count,
target_error,
options,
te
);
heap = new Uint8Array(instance.exports.memory.buffer);
bytes(indices).set(heap.subarray(si, si + result * 4));
bytes(vertex_positions).set(heap.subarray(sp, sp + vertex_count * vertex_positions_stride));
bytes(vertex_attributes).set(heap.subarray(sa, sa + vertex_count * vertex_attributes_stride));
var error = new Float32Array(1);
bytes(error).set(heap.subarray(te, te + 4));
sbrk(te - sbrk(0));
return [result, error[0]];
}
function simplifyScale(fun, vertex_positions, vertex_count, vertex_positions_stride) {
var sbrk = instance.exports.sbrk;
var sp = sbrk(vertex_count * vertex_positions_stride);
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(vertex_positions), sp);
var result = fun(sp, vertex_count, vertex_positions_stride);
sbrk(sp - sbrk(0));
return result;
}
function simplifyPoints(fun, vertex_positions, vertex_count, vertex_positions_stride, vertex_colors, vertex_colors_stride, color_weight, target_vertex_count) {
var sbrk = instance.exports.sbrk;
var ti = sbrk(target_vertex_count * 4);
var sp = sbrk(vertex_count * vertex_positions_stride);
var sc = sbrk(vertex_count * vertex_colors_stride);
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(vertex_positions), sp);
if (vertex_colors) {
heap.set(bytes(vertex_colors), sc);
}
var result = fun(ti, sp, vertex_count, vertex_positions_stride, sc, vertex_colors_stride, color_weight, target_vertex_count);
heap = new Uint8Array(instance.exports.memory.buffer);
var target = new Uint32Array(result);
bytes(target).set(heap.subarray(ti, ti + result * 4));
sbrk(ti - sbrk(0));
return target;
}
function simplifySloppy(fun, indices, index_count, vertex_positions, vertex_count, vertex_positions_stride, vertex_lock, target_index_count, target_error) {
var sbrk = instance.exports.sbrk;
var te = sbrk(4);
var ti = sbrk(index_count * 4);
var sp = sbrk(vertex_count * vertex_positions_stride);
var si = sbrk(index_count * 4);
var vl = vertex_lock ? sbrk(vertex_count) : 0;
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(vertex_positions), sp);
heap.set(bytes(indices), si);
if (vertex_lock) {
heap.set(bytes(vertex_lock), vl);
}
var result = fun(ti, si, index_count, sp, vertex_count, vertex_positions_stride, vl, target_index_count, target_error, te);
heap = new Uint8Array(instance.exports.memory.buffer);
var target = new Uint32Array(result);
bytes(target).set(heap.subarray(ti, ti + result * 4));
var error = new Float32Array(1);
bytes(error).set(heap.subarray(te, te + 4));
sbrk(te - sbrk(0));
return [target, error[0]];
}
function simplifyPrune(fun, indices, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_error) {
var sbrk = instance.exports.sbrk;
var ti = sbrk(index_count * 4);
var sp = sbrk(vertex_count * vertex_positions_stride);
var si = sbrk(index_count * 4);
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(vertex_positions), sp);
heap.set(bytes(indices), si);
var result = fun(ti, si, index_count, sp, vertex_count, vertex_positions_stride, target_error);
heap = new Uint8Array(instance.exports.memory.buffer);
var target = new Uint32Array(result);
bytes(target).set(heap.subarray(ti, ti + result * 4));
sbrk(ti - sbrk(0));
return target;
}
var simplifyOptions = {
LockBorder: 1,
Sparse: 2,
ErrorAbsolute: 4,
Prune: 8,
Regularize: 16,
Permissive: 32,
_InternalDebug: 1 << 30
// internal, don't use!
};
return {
ready,
supported: true,
compactMesh: function(indices) {
assert(
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
);
assert(indices.length % 3 == 0);
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
return reorder(instance.exports.meshopt_optimizeVertexFetchRemap, indices32, maxindex(indices) + 1);
},
simplify: function(indices, vertex_positions, vertex_positions_stride, target_index_count, target_error, flags) {
assert(
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
);
assert(indices.length % 3 == 0);
assert(vertex_positions instanceof Float32Array);
assert(vertex_positions.length % vertex_positions_stride == 0);
assert(vertex_positions_stride >= 3);
assert(target_index_count >= 0 && target_index_count <= indices.length);
assert(target_index_count % 3 == 0);
assert(target_error >= 0);
var options = 0;
for (var i = 0; i < (flags ? flags.length : 0); ++i) {
assert(flags[i] in simplifyOptions);
options |= simplifyOptions[flags[i]];
}
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
var result = simplify(
instance.exports.meshopt_simplify,
indices32,
indices.length,
vertex_positions,
vertex_positions.length / vertex_positions_stride,
vertex_positions_stride * 4,
target_index_count,
target_error,
options
);
result[0] = indices instanceof Uint32Array ? result[0] : new indices.constructor(result[0]);
return result;
},
simplifyWithAttributes: function(indices, vertex_positions, vertex_positions_stride, vertex_attributes, vertex_attributes_stride, attribute_weights, vertex_lock, target_index_count, target_error, flags) {
assert(
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
);
assert(indices.length % 3 == 0);
assert(vertex_positions instanceof Float32Array);
assert(vertex_positions.length % vertex_positions_stride == 0);
assert(vertex_positions_stride >= 3);
assert(vertex_attributes instanceof Float32Array);
assert(vertex_attributes.length == vertex_attributes_stride * (vertex_positions.length / vertex_positions_stride));
assert(vertex_attributes_stride >= 0);
assert(vertex_lock == null || vertex_lock instanceof Uint8Array);
assert(vertex_lock == null || vertex_lock.length == vertex_positions.length / vertex_positions_stride);
assert(target_index_count >= 0 && target_index_count <= indices.length);
assert(target_index_count % 3 == 0);
assert(target_error >= 0);
assert(Array.isArray(attribute_weights));
assert(vertex_attributes_stride >= attribute_weights.length);
assert(attribute_weights.length <= 32);
for (var i = 0; i < attribute_weights.length; ++i) {
assert(attribute_weights[i] >= 0);
}
var options = 0;
for (var i = 0; i < (flags ? flags.length : 0); ++i) {
assert(flags[i] in simplifyOptions);
options |= simplifyOptions[flags[i]];
}
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
var result = simplifyAttr(
instance.exports.meshopt_simplifyWithAttributes,
indices32,
indices.length,
vertex_positions,
vertex_positions.length / vertex_positions_stride,
vertex_positions_stride * 4,
vertex_attributes,
vertex_attributes_stride * 4,
new Float32Array(attribute_weights),
vertex_lock,
target_index_count,
target_error,
options
);
result[0] = indices instanceof Uint32Array ? result[0] : new indices.constructor(result[0]);
return result;
},
simplifyWithUpdate: function(indices, vertex_positions, vertex_positions_stride, vertex_attributes, vertex_attributes_stride, attribute_weights, vertex_lock, target_index_count, target_error, flags) {
assert(
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
);
assert(indices.length % 3 == 0);
assert(vertex_positions instanceof Float32Array);
assert(vertex_positions.length % vertex_positions_stride == 0);
assert(vertex_positions_stride >= 3);
assert(vertex_attributes instanceof Float32Array);
assert(vertex_attributes.length == vertex_attributes_stride * (vertex_positions.length / vertex_positions_stride));
assert(vertex_attributes_stride >= 0);
assert(vertex_lock == null || vertex_lock instanceof Uint8Array);
assert(vertex_lock == null || vertex_lock.length == vertex_positions.length / vertex_positions_stride);
assert(target_index_count >= 0 && target_index_count <= indices.length);
assert(target_index_count % 3 == 0);
assert(target_error >= 0);
assert(Array.isArray(attribute_weights));
assert(vertex_attributes_stride >= attribute_weights.length);
assert(attribute_weights.length <= 32);
for (var i = 0; i < attribute_weights.length; ++i) {
assert(attribute_weights[i] >= 0);
}
var options = 0;
for (var i = 0; i < (flags ? flags.length : 0); ++i) {
assert(flags[i] in simplifyOptions);
options |= simplifyOptions[flags[i]];
}
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
var result = simplifyUpdate(
instance.exports.meshopt_simplifyWithUpdate,
indices32,
indices.length,
vertex_positions,
vertex_positions.length / vertex_positions_stride,
vertex_positions_stride * 4,
vertex_attributes,
vertex_attributes_stride * 4,
new Float32Array(attribute_weights),
vertex_lock,
target_index_count,
target_error,
options
);
if (indices !== indices32) {
for (var i = 0; i < result[0]; ++i) {
indices[i] = indices32[i];
}
}
return result;
},
getScale: function(vertex_positions, vertex_positions_stride) {
assert(vertex_positions instanceof Float32Array);
assert(vertex_positions.length % vertex_positions_stride == 0);
assert(vertex_positions_stride >= 3);
return simplifyScale(
instance.exports.meshopt_simplifyScale,
vertex_positions,
vertex_positions.length / vertex_positions_stride,
vertex_positions_stride * 4
);
},
simplifyPoints: function(vertex_positions, vertex_positions_stride, target_vertex_count, vertex_colors, vertex_colors_stride, color_weight) {
assert(vertex_positions instanceof Float32Array);
assert(vertex_positions.length % vertex_positions_stride == 0);
assert(vertex_positions_stride >= 3);
assert(target_vertex_count >= 0 && target_vertex_count <= vertex_positions.length / vertex_positions_stride);
if (vertex_colors) {
assert(vertex_colors instanceof Float32Array);
assert(vertex_colors.length % vertex_colors_stride == 0);
assert(vertex_colors_stride >= 3);
assert(vertex_positions.length / vertex_positions_stride == vertex_colors.length / vertex_colors_stride);
return simplifyPoints(
instance.exports.meshopt_simplifyPoints,
vertex_positions,
vertex_positions.length / vertex_positions_stride,
vertex_positions_stride * 4,
vertex_colors,
vertex_colors_stride * 4,
color_weight,
target_vertex_count
);
} else {
return simplifyPoints(
instance.exports.meshopt_simplifyPoints,
vertex_positions,
vertex_positions.length / vertex_positions_stride,
vertex_positions_stride * 4,
void 0,
0,
0,
target_vertex_count
);
}
},
simplifySloppy: function(indices, vertex_positions, vertex_positions_stride, vertex_lock, target_index_count, target_error) {
assert(
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
);
assert(indices.length % 3 == 0);
assert(vertex_positions instanceof Float32Array);
assert(vertex_positions.length % vertex_positions_stride == 0);
assert(vertex_positions_stride >= 3);
assert(vertex_lock == null || vertex_lock instanceof Uint8Array);
assert(vertex_lock == null || vertex_lock.length == vertex_positions.length / vertex_positions_stride);
assert(target_index_count >= 0 && target_index_count <= indices.length);
assert(target_index_count % 3 == 0);
assert(target_error >= 0);
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
var result = simplifySloppy(
instance.exports.meshopt_simplifySloppy,
indices32,
indices.length,
vertex_positions,
vertex_positions.length / vertex_positions_stride,
vertex_positions_stride * 4,
vertex_lock,
target_index_count,
target_error
);
result[0] = indices instanceof Uint32Array ? result[0] : new indices.constructor(result[0]);
return result;
},
simplifyPrune: function(indices, vertex_positions, vertex_positions_stride, target_error) {
assert(
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
);
assert(indices.length % 3 == 0);
assert(vertex_positions instanceof Float32Array);
assert(vertex_positions.length % vertex_positions_stride == 0);
assert(vertex_positions_stride >= 3);
assert(target_error >= 0);
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
var result = simplifyPrune(
instance.exports.meshopt_simplifyPrune,
indices32,
indices.length,
vertex_positions,
vertex_positions.length / vertex_positions_stride,
vertex_positions_stride * 4,
target_error
);
result = indices instanceof Uint32Array ? result : new indices.constructor(result);
return result;
}
};
})();
// node_modules/meshoptimizer/meshopt_clusterizer.module.js
var import_InlineWorkers471 = __toESM(require_InlineWorkers());
var MeshoptClusterizer = (function() {
var wasm = "b9H79TebbbeVx9Geueu9Geub9Gbb9Giuuueu9Gmuuuuuuuuuuu9999eu9Gvuuuuueu9Gwuuuuuuuub9Gxuuuuuuuuuuuueu9Gkuuuuuuuuuu99eu9Gouuuuuub9Gruuuuuuub9GluuuubiAOdilvorwDqqDkbiibeilve9Weiiviebeoweuec;G:Odkr;qeDo9TW9T9VV95dbH9F9F939H79T9F9J9H229F9Jt9VV7bb8A9TW79O9V9Wt9F9I919P29K9nW79O2Wt79c9V919U9KbeX9TW79O9V9Wt9F9I919P29K9nW79O2Wt7bo39TW79O9V9Wt9F9J9V9T9W91tWJ2917tWV9c9V919U9K7br39TW79O9V9Wt9F9J9V9T9W91tW9nW79O2Wt9c9V919U9K7bDE9TW79O9V9Wt9F9J9V9T9W91tW9t9W9OWVW9c9V919U9K7bqL9TW79O9V9Wt9F9V9Wt9P9T9P96W9nW79O2Wtbkl79IV9RbxDwebcekdszq:x9DOdbkIbabaec9:fgefcufae9Ugeabci9Uadfcufad9Ugbaeab0Ek:w8KDPue99eux99dui99euo99iu8Jjjjjbc:WD9Rgm8KjjjjbdndnalmbcbhPxekamc:Cwfcbc;Kbz:ojjjb8Adndnalcb9imbaoal9nmbamcuaocdtaocFFFFi0Egscbyd;u1jjbHjjjjbbgzBd:CwamceBd;8wamascbyd;u1jjbHjjjjbbgHBd:GwamcdBd;8wamcualcdtalcFFFFi0Ecbyd;u1jjbHjjjjbbgOBd:KwamciBd;8waihsalhAinazasydbcdtfcbBdbasclfhsaAcufgAmbkaihsalhAinazasydbcdtfgCaCydbcefBdbasclfhsaAcufgAmbkaihsalhCcbhXindnazasydbcdtgQfgAydbcb9imbaHaQfaXBdbaAaAydbgQcjjjj94VBdbaQaXfhXkasclfhsaCcufgCmbkalci9UhLdnalci6mbcbhsaihAinaAcwfydbhCaAclfydbhXaHaAydbcdtfgQaQydbgQcefBdbaOaQcdtfasBdbaHaXcdtfgXaXydbgXcefBdbaOaXcdtfasBdbaHaCcdtfgCaCydbgCcefBdbaOaCcdtfasBdbaAcxfhAaLascefgs9hmbkkaihsalhAindnazasydbcdtgCfgXydbgQcu9kmbaXaQcFFFFrGgQBdbaHaCfgCaCydbaQ9RBdbkasclfhsaAcufgAmbxdkkamcuaocdtgsaocFFFFi0EgAcbyd;u1jjbHjjjjbbgzBd:CwamceBd;8wamaAcbyd;u1jjbHjjjjbbgHBd:GwamcdBd;8wamcualcdtalcFFFFi0Ecbyd;u1jjbHjjjjbbgOBd:KwamciBd;8wazcbasz:ojjjbhXalci9UhLaihsalhAinaXasydbcdtfgCaCydbcefBdbasclfhsaAcufgAmbkdnaoTmbcbhsaHhAaXhCaohQinaAasBdbaAclfhAaCydbasfhsaCclfhCaQcufgQmbkkdnalci6mbcbhsaihAinaAcwfydbhCaAclfydbhQaHaAydbcdtfgKaKydbgKcefBdbaOaKcdtfasBdbaHaQcdtfgQaQydbgQcefBdbaOaQcdtfasBdbaHaCcdtfgCaCydbgCcefBdbaOaCcdtfasBdbaAcxfhAaLascefgs9hmbkkaoTmbcbhsaohAinaHasfgCaCydbaXasfydb9RBdbasclfhsaAcufgAmbkkamaLcbyd;u1jjbHjjjjbbgsBd:OwamclBd;8wascbaLz:ojjjbhYamcuaLcK2alcjjjjd0Ecbyd;u1jjbHjjjjbbg8ABd:SwamcvBd;8wJbbbbhEdnalci6g3mbarcd4hKaihAa8AhsaLhrJbbbbh5inavaAclfydbaK2cdtfgCIdlh8EavaAydbaK2cdtfgXIdlhEavaAcwfydbaK2cdtfgQIdlh8FaCIdwhaaXIdwhhaQIdwhgasaCIdbg8JaXIdbg8KMaQIdbg8LMJbbnn:vUdbasclfaXIdlaCIdlMaQIdlMJbbnn:vUdbaQIdwh8MaCIdwh8NaXIdwhyascxfa8EaE:tg8Eagah:tggNa8FaE:tg8Faaah:tgaN:tgEJbbbbJbbjZa8Ja8K:tg8Ja8FNa8La8K:tg8Ka8EN:tghahNaEaENaaa8KNaga8JN:tgEaENMM:rg8K:va8KJbbbb9BEg8ENUdbasczfaEa8ENUdbascCfaha8ENUdbascwfa8Maya8NMMJbbnn:vUdba5a8KMh5aAcxfhAascKfhsarcufgrmbka5aL:Z:vJbbbZNhEkamcuaLcdtalcFFFF970Ecbyd;u1jjbHjjjjbbgCBd:WwamcoBd;8waEaq:ZNhEdna3mbcbhsaChAinaAasBdbaAclfhAaLascefgs9hmbkkaE:rhhcuh8PamcuaLcltalcFFFFd0Ecbyd;u1jjbHjjjjbbgIBd:0wamcrBd;8wcbaIa8AaCaLz:djjjb8AJFFuuhyJFFuuh8RJFFuuh8Sdnalci6gXmbJFFuuh8Sa8AhsaLhAJFFuuh8RJFFuuhyinascwfIdbgEayayaE9EEhyasclfIdbgEa8Ra8RaE9EEh8RasIdbgEa8Sa8SaE9EEh8SascKfhsaAcufgAmbkkahJbbbZNhgamaocetgscuaocu9kEcbyd;u1jjbHjjjjbbgABd:4waAcFeasz:ojjjbhCdnaXmbcbhAJFFuuhEa8Ahscuh8PinascwfIdbay:tghahNasIdba8S:tghahNasclfIdba8R:tghahNMM:rghaEa8PcuSahaE9DVgXEhEaAa8PaXEh8PascKfhsaLaAcefgA9hmbkkamczfcbcjwz:ojjjb8Aamcwf9cb83ibam9cb83ibagaxNhRJbbjZak:th8Ncbh8UJbbbbh8VJbbbbh8WJbbbbh8XJbbbbh8YJbbbbh8ZJbbbbh80cbh81cbhPinJbbbbhEdna8UTmbJbbjZa8U:Z:vhEkJbbbbhhdna80a80Na8Ya8YNa8Za8ZNMMg8KJbbbb9BmbJbbjZa8K:r:vhhka8XaENh5a8WaENh8Fa8VaENhaa8PhQdndndndndna8UaPVTmbamydwgBTmea80ahNh8Ja8ZahNh8La8YahNh8Maeamydbcdtfh83cbh3JFFuuhEcvhXcuhQindnaza83a3cdtfydbcdtgsfydbgvTmbaOaHasfydbcdtfhAindndnaCaiaAydbgKcx2fgsclfydbgrcetf8Vebcs4aCasydbgLcetf8Vebcs4faCascwfydbglcetf8Vebcs4fgombcbhsxekcehsazaLcdtfydbgLceSmbcehsazarcdtfydbgrceSmbcehsazalcdtfydbglceSmbdnarcdSaLcdSfalcdSfcd6mbaocefhsxekaocdfhskdnasaX9kmba8AaKcK2fgLIdwa5:thhaLIdla8F:th8KaLIdbaa:th8EdndnakJbbbb9DTmba8E:lg8Ea8K:lg8Ka8Ea8K9EEg8Kah:lgha8Kah9EEag:vJbbjZMhhxekahahNa8Ea8ENa8Ka8KNMM:rag:va8NNJbbjZMJ9VO:d86JbbjZaLIdCa8JNaLIdxa8MNa8LaLIdzNMMakN:tghahJ9VO:d869DENhhkaKaQasaX6ahaE9DVgLEhQasaXaLEhXahaEaLEhEkaAclfhAavcufgvmbkka3cefg3aB9hmbkkaQcu9hmekama5Ud:ODama8FUd:KDamaaUd:GDamcuBd:qDamcFFF;7rBdjDaIcba8AaYamc:GDfakJbbbb9Damc:qDfamcjDfz:ejjjbamyd:qDhQdndnaxJbbbb9ETmba8UaD6mbaQcuSmeceh3amIdjDaR9EmixdkaQcu9hmekdna8UTmbdnamydlgza8Uci2fgsciGTmbadasfcba8Uazcu7fciGcefz:ojjjb8AkabaPcltfgzam8Pib83dbazcwfamcwf8Pib83dbaPcefhPkc3hzinazc98Smvamc:Cwfazfydbcbyd;y1jjbH:bjjjbbazc98fhzxbkkcbh3a8Uaq9pmbamydwaCaiaQcx2fgsydbcetf8Vebcs4aCascwfydbcetf8Vebcs4faCasclfydbcetf8Vebcs4ffaw9nmekcbhscbhAdna81TmbcbhAamczfhXinamczfaAcdtfaXydbgLBdbaXclfhXaAaYaLfRbbTfhAa81cufg81mbkkamydwhlamydbhXam9cu83i:GDam9cu83i:ODam9cu83i:qDam9cu83i:yDaAc;8eaAclfc:bd6Eh81inamcjDfasfcFFF;7rBdbasclfgscz9hmbka81cdthBdnalTmbaeaXcdtfhocbhrindnazaoarcdtfydbcdtgsfydbgvTmbaOaHasfydbcdtfhAcuhLcuhsinazaiaAydbgKcx2fgXclfydbcdtfydbazaXydbcdtfydbfazaXcwfydbcdtfydbfgXasaXas6gXEhsaKaLaXEhLaAclfhAavcufgvmbkaLcuSmba8AaLcK2fgAIdway:tgEaENaAIdba8S:tgEaENaAIdla8R:tgEaENMM:rhEcbhAindndnasamc:qDfaAfgvydbgX6mbasaX9hmeaEamcjDfaAfIdb9FTmekavasBdbamc:GDfaAfaLBdbamcjDfaAfaEUdbxdkaAclfgAcz9hmbkkarcefgral9hmbkkamczfaBfhLcbhscbhAindnamc:GDfasfydbgXcuSmbaLaAcdtfaXBdbaAcefhAkasclfgscz9hmbkaAa81fg81TmbJFFuuhhcuhKamczfhsa81hvcuhLina8AasydbgXcK2fgAIdway:tgEaENaAIdba8S:tgEaENaAIdla8R:tgEaENMM:rhEdndnazaiaXcx2fgAclfydbcdtfydbazaAydbcdtfydbfazaAcwfydbcdtfydbfgAaL6mbaAaL9hmeaEah9DTmekaEhhaAhLaXhKkasclfhsavcufgvmbkaKcuSmbaKhQkdnamaiaQcx2fgrydbarclfydbarcwfydbaCabaeadaPawaqa3z:fjjjbTmbaPcefhPJbbbbh8VJbbbbh8WJbbbbh8XJbbbbh8YJbbbbh8ZJbbbbh80kcbhXinaOaHaraXcdtfydbcdtgAfydbcdtfgKhsazaAfgvydbgLhAdnaLTmbdninasydbaQSmeasclfhsaAcufgATmdxbkkasaKaLcdtfc98fydbBdbavavydbcufBdbkaXcefgXci9hmbka8AaQcK2fgsIdbhEasIdlhhasIdwh8KasIdxh8EasIdzh5asIdCh8FaYaQfce86bba80a8FMh80a8Za5Mh8Za8Ya8EMh8Ya8Xa8KMh8Xa8WahMh8Wa8VaEMh8Vamydxh8Uxbkkamc:WDf8KjjjjbaPk;Vvivuv99lu8Jjjjjbca9Rgv8Kjjjjbdndnalcw0mbaiydbhoaeabcitfgralcdtcufBdlaraoBdbdnalcd6mbaiclfhoalcufhwarcxfhrinaoydbhDarcuBdbarc98faDBdbarcwfhraoclfhoawcufgwmbkkalabfhrxekcbhDavczfcwfcbBdbav9cb83izavcwfcbBdbav9cb83ibJbbjZhqJbbjZhkinadaiaDcdtfydbcK2fhwcbhrinavczfarfgoawarfIdbgxaoIdbgm:tgPakNamMgmUdbavarfgoaPaxam:tNaoIdbMUdbarclfgrcx9hmbkJbbjZaqJbbjZMgq:vhkaDcefgDal9hmbkcbhoadcbcecdavIdlgxavIdwgm9GEgravIdbgPam9GEaraPax9GEgscdtgrfhzavczfarfIdbhxaihralhwinaiaocdtfgDydbhHaDarydbgOBdbaraHBdbarclfhraoazaOcK2fIdbax9Dfhoawcufgwmbkaeabcitfhrdndnaocv6mbaoalc98f6mekaraiydbBdbaralcdtcufBdlaiclfhoalcufhwarcxfhrinaoydbhDarcuBdbarc98faDBdbarcwfhraoclfhoawcufgwmbkalabfhrxekaraxUdbararydlc98GasVBdlabcefaeadaiaoz:djjjbhwararydlciGawabcu7fcdtVBdlawaeadaiaocdtfalao9Rz:djjjbhrkavcaf8Kjjjjbark:;idiud99dndnabaecitfgwydlgDciGgqciSmbinabcbaDcd4gDalaqcdtfIdbawIdb:tgkJbbbb9FEgwaecefgefadaialavaoarz:ejjjbak:larIdb9FTmdabawaD7aefgecitfgwydlgDciGgqci9hmbkkabaecitfgeclfhbdnavmbcuhwindnaiaeydbgDfRbbmbadaDcK2fgqIdwalIdw:tgkakNaqIdbalIdb:tgkakNaqIdlalIdl:tgkakNMM:rgkarIdb9DTmbarakUdbaoaDBdbkaecwfheawcefgwabydbcd46mbxdkkcuhwindnaiaeydbgDfRbbmbadaDcK2fgqIdbalIdb:t:lgkaqIdlalIdl:t:lgxakax9EEgkaqIdwalIdw:t:lgxakax9EEgkarIdb9DTmbarakUdbaoaDBdbkaecwfheawcefgwabydbcd46mbkkk;llevudnabydwgxaladcetfgm8Vebcs4alaecetfgP8Vebgscs4falaicetfgz8Vebcs4ffaD0abydxaq9pVakVgDce9hmbavawcltfgxab8Pdb83dbaxcwfabcwfgx8Pdb83dbdnaxydbgqTmbaoabydbcdtfhxaqhsinalaxydbcetfcFFi87ebaxclfhxascufgsmbkkdnabydxglci2gsabydlgxfgkciGTmbarakfcbalaxcu7fciGcefz:ojjjb8Aabydxci2hsabydlhxabydwhqkab9cb83dwababydbaqfBdbabascifc98GaxfBdlaP8Vebhscbhxkdnascztcz91cu9kmbabaxcefBdwaPax87ebaoabydbcdtfaxcdtfaeBdbkdnam8Uebcu9kmbababydwgxcefBdwamax87ebaoabydbcdtfaxcdtfadBdbkdnaz8Uebcu9kmbababydwgxcefBdwazax87ebaoabydbcdtfaxcdtfaiBdbkarabydlfabydxci2faPRbb86bbarabydlfabydxci2fcefamRbb86bbarabydlfabydxci2fcdfazRbb86bbababydxcefBdxaDk8LbabaeadaialavaoarawaDaDaqJbbbbz:cjjjbk;Nkovud99euv99eul998Jjjjjbc:W;ae9Rgo8KjjjjbdndnadTmbavcd4hrcbhwcbhDindnaiaeclfydbar2cdtfgvIdbaiaeydbar2cdtfgqIdbgk:tgxaiaecwfydbar2cdtfgmIdlaqIdlgP:tgsNamIdbak:tgzavIdlaP:tgPN:tgkakNaPamIdwaqIdwgH:tgONasavIdwaH:tgHN:tgPaPNaHazNaOaxN:tgxaxNMM:rgsJbbbb9Bmbaoc:W:qefawcx2fgAakas:vUdwaAaxas:vUdlaAaPas:vUdbaoc8Wfawc8K2fgAaq8Pdb83dbaAav8Pdb83dxaAam8Pdb83dKaAcwfaqcwfydbBdbaAcCfavcwfydbBdbaAcafamcwfydbBdbawcefhwkaecxfheaDcifgDad6mbkab9cb83dbabcyf9cb83dbabcaf9cb83dbabcKf9cb83dbabczf9cb83dbabcwf9cb83dbawTmeaocbBd8Sao9cb83iKao9cb83izaoczfaoc8Wfawci2cxaoc8Sfcbcrz1jjjbaoIdKhCaoIdChXaoIdzhQao9cb83iwao9cb83ibaoaoc:W:qefawcxaoc8Sfcbciz1jjjbJbbjZhkaoIdwgPJbbbbJbbjZaPaPNaoIdbgPaPNaoIdlgsasNMM:rgx:vaxJbbbb9BEgzNhxasazNhsaPazNhzaoc:W:qefheawhvinaecwfIdbaxNaeIdbazNasaeclfIdbNMMgPakaPak9DEhkaecxfheavcufgvmbkabaCUdwabaXUdlabaQUdbabaoId3UdxdndnakJ;n;m;m899FmbJbbbbhPaoc:W:qefheaoc8WfhvinaCavcwfIdb:taecwfIdbgHNaQavIdb:taeIdbgONaXavclfIdb:taeclfIdbgLNMMaxaHNazaONasaLNMM:vgHaPaHaP9EEhPavc8KfhvaecxfheawcufgwmbkabaxUd8KabasUdaabazUd3abaCaxaPN:tUdKabaXasaPN:tUdCabaQazaPN:tUdzabJbbjZakakN:t:rgkUdydndnaxJbbj:;axJbbj:;9GEgPJbbjZaPJbbjZ9FEJbb;:9cNJbbbZJbbb:;axJbbbb9GEMgP:lJbbb9p9DTmbaP:Ohexekcjjjj94hekabae86b8UdndnasJbbj:;asJbbj:;9GEgPJbbjZaPJbbjZ9FEJbb;:9cNJbbbZJbbb:;asJbbbb9GEMgP:lJbbb9p9DTmbaP:Ohvxekcjjjj94hvkabav86bRdndnazJbbj:;azJbbj:;9GEgPJbbjZaPJbbjZ9FEJbb;:9cNJbbbZJbbb:;azJbbbb9GEMgP:lJbbb9p9DTmbaP:Ohqxekcjjjj94hqkabaq86b8SdndnaecKtcK91:YJbb;:9c:vax:t:lavcKtcK91:YJbb;:9c:vas:t:laqcKtcK91:YJbb;:9c:vaz:t:lakMMMJbb;:9cNJbbjZMgk:lJbbb9p9DTmbak:Ohexekcjjjj94hekaecFbaecFb9iEhexekabcjjj;8iBdycFbhekabae86b8Vxekab9cb83dbabcyf9cb83dbabcaf9cb83dbabcKf9cb83dbabczf9cb83dbabcwf9cb83dbkaoc:W;aef8Kjjjjbk;Iwwvul99iud99eue99eul998Jjjjjbcje9Rgr8Kjjjjbavcd4hwaicd4hDdndnaoTmbarc;abfcbaocdtgvz:ojjjb8Aarc;Gbfcbavz:ojjjb8AarhvarcafhiaohqinavcFFF97BdbaicFFF;7rBdbaiclfhiavclfhvaqcufgqmbkdnadTmbcbhkinaeakaD2cdtfgvIdwhxavIdlhmavIdbhPalakaw2cdtfIdbhsarc;abfhzarhiarc;GbfhHarcafhqcj1jjbhvaohOinasavcwfIdbaxNavIdbaPNavclfIdbamNMMgAMhCakhXdnaAas:tgAaqIdbgQ9DgLmbaHydbhXkaHaXBdbakhXdnaCaiIdbgK9EmbazydbhXaKhCkazaXBdbaiaCUdbaqaAaQaLEUdbavcxfhvaqclfhqaHclfhHaiclfhiazclfhzaOcufgOmbkakcefgkad9hmbkkadThkJbbbbhCcbhXarc;abfhvarc;Gbfhicbhqinalavydbgzaw2cdtfIdbalaiydbgHaw2cdtfIdbaeazaD2cdtfgzIdwaeaHaD2cdtfgHIdw:tgsasNazIdbaHIdb:tgsasNazIdlaHIdl:tgsasNMM:rMMgsaCasaC9EgzEhCaqaXazEhXaiclfhiavclfhvaoaqcefgq9hmbkaCJbbbZNhKxekadThkcbhXJbbbbhKkJbbbbhCdnaearc;abfaXcdtgifydbgqaD2cdtfgvIdwaearc;GbfaifydbgzaD2cdtfgiIdwgm:tgsasNavIdbaiIdbgY:tgAaANavIdlaiIdlgP:tgQaQNMM:rgxJbbbb9ETmbaxalaqaw2cdtfIdbMalazaw2cdtfIdb:taxaxM:vhCkasaCNamMhmaQaCNaPMhPaAaCNaYMhYdnakmbaDcdthvawcdthiindnalIdbg8AaecwfIdbam:tgCaCNaeIdbaY:tgsasNaeclfIdbaP:tgAaANMM:rgQMgEaK9ETmbJbbbbhxdnaQJbbbb9ETmbaEaK:taQaQM:vhxkaxaCNamMhmaxaANaPMhPaxasNaYMhYa8AaKaQMMJbbbZNhKkaeavfhealaifhladcufgdmbkkabaKUdxabamUdwabaPUdlabaYUdbarcjef8Kjjjjbkjeeiu8Jjjjjbcj8W9Rgr8Kjjjjbaici2hwdnaiTmbawceawce0EhDarhiinaiaeadRbbcdtfydbBdbadcefhdaiclfhiaDcufgDmbkkabarawaladaoz:hjjjbarcj8Wf8Kjjjjbk:Reeeu8Jjjjjbca9Rgo8Kjjjjbab9cb83dbabcyf9cb83dbabcaf9cb83dbabcKf9cb83dbabczf9cb83dbabcwf9cb83dbdnadTmbaocbBd3ao9cb83iwao9cb83ibaoaeadaialaoc3falEavcbalEcrz1jjjbabao8Pib83dbabao8Piw83dwkaocaf8Kjjjjbk:3lequ8JjjjjbcjP9Rgl8Kjjjjbcbhvalcjxfcbaiz:ojjjb8AdndnadTmbcjehoaehrincuhwarhDcuhqavhkdninawakaoalcjxfaDcefRbbfRbb9RcFeGci6aoalcjxfaDRbbfRbb9RcFeGci6faoalcjxfaDcdfRbbfRbb9RcFeGci6fgxaq9mgmEhwdnammbaxce0mdkaxaqaxaq9kEhqaDcifhDadakcefgk9hmbkkaeawci2fgDcdfRbbhqaDcefRbbhxaDRbbhkaeavci2fgDcifaDawav9Rci2z:rjjjb8Aakalcjxffaocefgo86bbaxalcjxffao86bbaDcdfaq86bbaDcefax86bbaDak86bbaqalcjxffao86bbarcifhravcefgvad9hmbkalcFeaicetz:ojjjbhoadci2gDceaDce0EhqcbhxindnaoaeRbbgkcetfgw8UebgDcu9kmbawax87ebaocjlfaxcdtfabakcdtfydbBdbaxhDaxcefhxkaeaD86bbaecefheaqcufgqmbkaxcdthDxekcbhDkabalcjlfaDz:njjjb8AalcjPf8Kjjjjbk9teiucbcbyd;C1jjbgeabcifc98GfgbBd;C1jjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaik;teeeudndnaeabVciGTmbabhixekdndnadcz9pmbabhixekabhiinaiaeydbBdbaiaeydlBdlaiaeydwBdwaiaeydxBdxaeczfheaiczfhiadc9Wfgdcs0mbkkadcl6mbinaiaeydbBdbaeclfheaiclfhiadc98fgdci0mbkkdnadTmbinaiaeRbb86bbaicefhiaecefheadcufgdmbkkabk:3eedudndnabciGTmbabhixekaecFeGc:b:c:ew2hldndnadcz9pmbabhixekabhiinaialBdxaialBdwaialBdlaialBdbaiczfhiadc9Wfgdcs0mbkkadcl6mbinaialBdbaiclfhiadc98fgdci0mbkkdnadTmbinaiae86bbaicefhiadcufgdmbkkabk9teiucbcbyd;C1jjbgeabcrfc94GfgbBd;C1jjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaik9:eiuZbhedndncbyd;C1jjbgdaecztgi9nmbcuheadai9RcFFifcz4nbcuSmekadhekcbabae9Rcifc98Gcbyd;C1jjbfgdBd;C1jjbdnadZbcztge9nmbadae9RcFFifcz4nb8Akk:;Deludndndnadch9pmbabaeSmdaeabadfgi9Rcbadcet9R0mekabaead;8qbbxekaeab7ciGhldndndnabae9pmbdnalTmbadhvabhixikdnabciGmbadhvabhixdkadTmiabaeRbb86bbadcufhvdnabcefgiciGmbaecefhexdkavTmiabaeRbe86beadc9:fhvdnabcdfgiciGmbaecdfhexdkavTmiabaeRbd86bdadc99fhvdnabcifgiciGmbaecifhexdkavTmiabaeRbi86biabclfhiaeclfheadc98fhvxekdnalmbdnaiciGTmbadTmlabadcufgifglaeaifRbb86bbdnalciGmbaihdxekaiTmlabadc9:fgifglaeaifRbb86bbdnalciGmbaihdxekaiTmlabadc99fgifglaeaifRbb86bbdnalciGmbaihdxekaiTmlabadc98fgdfaeadfRbb86bbkadcl6mbdnadc98fgocd4cefciGgiTmbaec98fhlabc98fhvinavadfaladfydbBdbadc98fhdaicufgimbkkaocx6mbaec9Wfhvabc9WfhoinaoadfgicxfavadfglcxfydbBdbaicwfalcwfydbBdbaiclfalclfydbBdbaialydbBdbadc9Wfgdci0mbkkadTmdadhidnadciGglTmbaecufhvabcufhoadhiinaoaifavaifRbb86bbaicufhialcufglmbkkadcl6mdaec98fhlabc98fhvinavaifgecifalaifgdcifRbb86bbaecdfadcdfRbb86bbaecefadcefRbb86bbaeadRbb86bbaic98fgimbxikkavcl6mbdnavc98fglcd4cefcrGgdTmbavadcdt9RhvinaiaeydbBdbaeclfheaiclfhiadcufgdmbkkalc36mbinaiaeydbBdbaiaeydlBdlaiaeydwBdwaiaeydxBdxaiaeydzBdzaiaeydCBdCaiaeydKBdKaiaeyd3Bd3aecafheaicafhiavc9Gfgvci0mbkkavTmbdndnavcrGgdmbavhlxekavc94GhlinaiaeRbb86bbaicefhiaecefheadcufgdmbkkavcw6mbinaiaeRbb86bbaiaeRbe86beaiaeRbd86bdaiaeRbi86biaiaeRbl86blaiaeRbv86bvaiaeRbo86boaiaeRbr86braicwfhiaecwfhealc94fglmbkkabkk9Tdbcjwk9ubbjZbbbbbbbbbbbbbbjZbbbbbbbbbbbbbbjZ86;nAZ86;nAZ86;nAZ86;nA:;86;nAZ86;nAZ86;nAZ86;nA:;86;nAZ86;nAZ86;nAZ86;nA:;bc;uwkxebbbdbbb9GNbb";
var wasmpack = new Uint8Array([
32,
0,
65,
2,
1,
106,
34,
33,
3,
128,
11,
4,
13,
64,
6,
253,
10,
7,
15,
116,
127,
5,
8,
12,
40,
16,
19,
54,
20,
9,
27,
255,
113,
17,
42,
67,
24,
23,
146,
148,
18,
14,
22,
45,
70,
69,
56,
114,
101,
21,
25,
63,
75,
136,
108,
28,
118,
29,
73,
115
]);
if (typeof WebAssembly !== "object") {
return {
supported: false
};
}
var instance;
var ready = WebAssembly.instantiate(unpack(wasm), {}).then(function(result) {
instance = result.instance;
instance.exports.__wasm_call_ctors();
});
function unpack(data) {
var result = new Uint8Array(data.length);
for (var i = 0; i < data.length; ++i) {
var ch = data.charCodeAt(i);
result[i] = ch > 96 ? ch - 97 : ch > 64 ? ch - 39 : ch + 4;
}
var write = 0;
for (var i = 0; i < data.length; ++i) {
result[write++] = result[i] < 60 ? wasmpack[result[i]] : (result[i] - 60) * 64 + result[++i];
}
return result.buffer.slice(0, write);
}
function assert(cond) {
if (!cond) {
throw new Error("Assertion failed");
}
}
function bytes(view) {
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
}
var BOUNDS_SIZE = 48;
var MESHLET_SIZE = 16;
function extractMeshlet(buffers, index) {
var vertex_offset = buffers.meshlets[index * 4 + 0];
var triangle_offset = buffers.meshlets[index * 4 + 1];
var vertex_count = buffers.meshlets[index * 4 + 2];
var triangle_count = buffers.meshlets[index * 4 + 3];
return {
vertices: buffers.vertices.subarray(vertex_offset, vertex_offset + vertex_count),
triangles: buffers.triangles.subarray(triangle_offset, triangle_offset + triangle_count * 3)
};
}
function buildMeshlets(indices, vertex_positions, vertex_count, vertex_positions_stride, max_vertices, max_triangles, cone_weight) {
var sbrk = instance.exports.sbrk;
var max_meshlets = instance.exports.meshopt_buildMeshletsBound(indices.length, max_vertices, max_triangles);
var meshletsp = sbrk(max_meshlets * MESHLET_SIZE);
var meshlet_verticesp = sbrk(max_meshlets * max_vertices * 4);
var meshlet_trianglesp = sbrk(max_meshlets * max_triangles * 3);
var indicesp = sbrk(indices.byteLength);
var verticesp = sbrk(vertex_positions.byteLength);
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(indices), indicesp);
heap.set(bytes(vertex_positions), verticesp);
var count = instance.exports.meshopt_buildMeshlets(
meshletsp,
meshlet_verticesp,
meshlet_trianglesp,
indicesp,
indices.length,
verticesp,
vertex_count,
vertex_positions_stride,
max_vertices,
max_triangles,
cone_weight
);
heap = new Uint8Array(instance.exports.memory.buffer);
var meshletBytes = heap.subarray(meshletsp, meshletsp + count * MESHLET_SIZE);
var meshlets = new Uint32Array(meshletBytes.buffer, meshletBytes.byteOffset, meshletBytes.byteLength / 4).slice();
for (var i = 0; i < count; ++i) {
var vertex_offset = meshlets[i * 4 + 0];
var triangle_offset = meshlets[i * 4 + 1];
var vertex_count = meshlets[i * 4 + 2];
var triangle_count = meshlets[i * 4 + 3];
instance.exports.meshopt_optimizeMeshlet(
meshlet_verticesp + vertex_offset * 4,
meshlet_trianglesp + triangle_offset,
triangle_count,
vertex_count
);
}
var last_vertex_offset = meshlets[(count - 1) * 4 + 0];
var last_triangle_offset = meshlets[(count - 1) * 4 + 1];
var last_vertex_count = meshlets[(count - 1) * 4 + 2];
var last_triangle_count = meshlets[(count - 1) * 4 + 3];
var used_vertices = last_vertex_offset + last_vertex_count;
var used_triangles = last_triangle_offset + (last_triangle_count * 3 + 3 & ~3);
var result = {
meshlets,
vertices: new Uint32Array(heap.buffer, meshlet_verticesp, used_vertices).slice(),
triangles: new Uint8Array(heap.buffer, meshlet_trianglesp, used_triangles * 3).slice(),
meshletCount: count
};
sbrk(meshletsp - sbrk(0));
return result;
}
function extractBounds(boundsp) {
var bounds_floats = new Float32Array(instance.exports.memory.buffer, boundsp, BOUNDS_SIZE / 4);
return {
centerX: bounds_floats[0],
centerY: bounds_floats[1],
centerZ: bounds_floats[2],
radius: bounds_floats[3],
coneApexX: bounds_floats[4],
coneApexY: bounds_floats[5],
coneApexZ: bounds_floats[6],
coneAxisX: bounds_floats[7],
coneAxisY: bounds_floats[8],
coneAxisZ: bounds_floats[9],
coneCutoff: bounds_floats[10]
};
}
function computeMeshletBounds(buffers, vertex_positions, vertex_count, vertex_positions_stride) {
var sbrk = instance.exports.sbrk;
var results = [];
var verticesp = sbrk(vertex_positions.byteLength);
var meshlet_verticesp = sbrk(buffers.vertices.byteLength);
var meshlet_trianglesp = sbrk(buffers.triangles.byteLength);
var resultp = sbrk(BOUNDS_SIZE);
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(vertex_positions), verticesp);
heap.set(bytes(buffers.vertices), meshlet_verticesp);
heap.set(bytes(buffers.triangles), meshlet_trianglesp);
for (var i = 0; i < buffers.meshletCount; ++i) {
var vertex_offset = buffers.meshlets[i * 4 + 0];
var triangle_offset = buffers.meshlets[i * 4 + 0 + 1];
var triangle_count = buffers.meshlets[i * 4 + 0 + 3];
instance.exports.meshopt_computeMeshletBounds(
resultp,
meshlet_verticesp + vertex_offset * 4,
meshlet_trianglesp + triangle_offset,
triangle_count,
verticesp,
vertex_count,
vertex_positions_stride
);
results.push(extractBounds(resultp));
}
sbrk(verticesp - sbrk(0));
return results;
}
function computeClusterBounds(indices, vertex_positions, vertex_count, vertex_positions_stride) {
var sbrk = instance.exports.sbrk;
var resultp = sbrk(BOUNDS_SIZE);
var indicesp = sbrk(indices.byteLength);
var verticesp = sbrk(vertex_positions.byteLength);
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(indices), indicesp);
heap.set(bytes(vertex_positions), verticesp);
instance.exports.meshopt_computeClusterBounds(resultp, indicesp, indices.length, verticesp, vertex_count, vertex_positions_stride);
var result = extractBounds(resultp);
sbrk(resultp - sbrk(0));
return result;
}
function computeSphereBounds(positions, count, positions_stride, radii, radii_stride) {
var sbrk = instance.exports.sbrk;
var resultp = sbrk(BOUNDS_SIZE);
var positionsp = sbrk(positions.byteLength);
var radiip = radii ? sbrk(radii.byteLength) : 0;
var heap = new Uint8Array(instance.exports.memory.buffer);
heap.set(bytes(positions), positionsp);
if (radii) {
heap.set(bytes(radii), radiip);
}
instance.exports.meshopt_computeSphereBounds(resultp, positionsp, count, positions_stride, radiip, radii ? radii_stride : 0);
var result = extractBounds(resultp);
sbrk(resultp - sbrk(0));
return result;
}
return {
ready,
supported: true,
buildMeshlets: function(indices, vertex_positions, vertex_positions_stride, max_vertices, max_triangles, cone_weight) {
assert(indices.length % 3 == 0);
assert(vertex_positions instanceof Float32Array);
assert(vertex_positions.length % vertex_positions_stride == 0);
assert(vertex_positions_stride >= 3);
assert(max_vertices <= 256 || max_vertices > 0);
assert(max_triangles <= 512);
assert(max_triangles % 4 == 0);
cone_weight = cone_weight || 0;
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
return buildMeshlets(
indices32,
vertex_positions,
vertex_positions.length / vertex_positions_stride,
vertex_positions_stride * 4,
max_vertices,
max_triangles,
cone_weight
);
},
extractMeshlet: function(buffers, index) {
assert(index >= 0 && index < buffers.meshletCount);
return extractMeshlet(buffers, index);
},
computeClusterBounds: function(indices, vertex_positions, vertex_positions_stride) {
assert(indices.length % 3 == 0);
assert(indices.length / 3 <= 512);
assert(vertex_positions instanceof Float32Array);
assert(vertex_positions.length % vertex_positions_stride == 0);
assert(vertex_positions_stride >= 3);
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
return computeClusterBounds(indices32, vertex_positions, vertex_positions.length / vertex_positions_stride, vertex_positions_stride * 4);
},
computeMeshletBounds: function(buffers, vertex_positions, vertex_positions_stride) {
assert(buffers.meshletCount != 0);
assert(vertex_positions instanceof Float32Array);
assert(vertex_positions.length % vertex_positions_stride == 0);
assert(vertex_positions_stride >= 3);
return computeMeshletBounds(buffers, vertex_positions, vertex_positions.length / vertex_positions_stride, vertex_positions_stride * 4);
},
computeSphereBounds: function(positions, positions_stride, radii, radii_stride) {
assert(positions instanceof Float32Array);
assert(positions.length % positions_stride == 0);
assert(positions_stride >= 3);
assert(!radii || radii instanceof Float32Array);
assert(!radii || radii.length % radii_stride == 0);
assert(!radii || radii_stride >= 1);
assert(!radii || positions.length / positions_stride == radii.length / radii_stride);
radii_stride = radii_stride || 0;
return computeSphereBounds(positions, positions.length / positions_stride, positions_stride * 4, radii, radii_stride * 4);
}
};
})();
// packages/engine/Source/Scene/GltfBufferViewLoader.js
function GltfBufferViewLoader(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const resourceCache = options.resourceCache;
const gltf = options.gltf;
const bufferViewId = options.bufferViewId;
const gltfResource = options.gltfResource;
const baseResource2 = options.baseResource;
const cacheKey = options.cacheKey;
Check_default.typeOf.func("options.resourceCache", resourceCache);
Check_default.typeOf.object("options.gltf", gltf);
Check_default.typeOf.number("options.bufferViewId", bufferViewId);
Check_default.typeOf.object("options.gltfResource", gltfResource);
Check_default.typeOf.object("options.baseResource", baseResource2);
const bufferView = gltf.bufferViews[bufferViewId];
let bufferId = bufferView.buffer;
let byteOffset = bufferView.byteOffset;
let byteLength = bufferView.byteLength;
let hasMeshopt = false;
let meshoptByteStride;
let meshoptCount;
let meshoptMode;
let meshoptFilter;
if (hasExtension_default(bufferView, "EXT_meshopt_compression")) {
const meshopt = bufferView.extensions.EXT_meshopt_compression;
bufferId = meshopt.buffer;
byteOffset = meshopt.byteOffset ?? 0;
byteLength = meshopt.byteLength;
hasMeshopt = true;
meshoptByteStride = meshopt.byteStride;
meshoptCount = meshopt.count;
meshoptMode = meshopt.mode;
meshoptFilter = meshopt.filter ?? "NONE";
}
const buffer2 = gltf.buffers[bufferId];
this._hasMeshopt = hasMeshopt;
this._meshoptByteStride = meshoptByteStride;
this._meshoptCount = meshoptCount;
this._meshoptMode = meshoptMode;
this._meshoptFilter = meshoptFilter;
this._resourceCache = resourceCache;
this._gltfResource = gltfResource;
this._baseResource = baseResource2;
this._buffer = buffer2;
this._bufferId = bufferId;
this._byteOffset = byteOffset;
this._byteLength = byteLength;
this._cacheKey = cacheKey;
this._bufferLoader = void 0;
this._typedArray = void 0;
this._state = ResourceLoaderState_default.UNLOADED;
this._promise = void 0;
}
if (defined_default(Object.create)) {
GltfBufferViewLoader.prototype = Object.create(ResourceLoader_default.prototype);
GltfBufferViewLoader.prototype.constructor = GltfBufferViewLoader;
}
Object.defineProperties(GltfBufferViewLoader.prototype, {
/**
* The cache key of the resource.
*
* @memberof GltfBufferViewLoader.prototype
*
* @type {string}
* @readonly
* @private
*/
cacheKey: {
get: function() {
return this._cacheKey;
}
},
/**
* The typed array containing buffer view data.
*
* @memberof GltfBufferViewLoader.prototype
*
* @type {Uint8Array}
* @readonly
* @private
*/
typedArray: {
get: function() {
return this._typedArray;
}
}
});
async function loadResources(loader) {
try {
const bufferLoader = getBufferLoader(loader);
loader._bufferLoader = bufferLoader;
await bufferLoader.load();
if (loader.isDestroyed()) {
return;
}
const bufferTypedArray = bufferLoader.typedArray;
const bufferViewTypedArray = new Uint8Array(
bufferTypedArray.buffer,
bufferTypedArray.byteOffset + loader._byteOffset,
loader._byteLength
);
loader.unload();
loader._typedArray = bufferViewTypedArray;
if (loader._hasMeshopt) {
const count = loader._meshoptCount;
const byteStride = loader._meshoptByteStride;
const result = new Uint8Array(count * byteStride);
MeshoptDecoder.decodeGltfBuffer(
result,
count,
byteStride,
loader._typedArray,
loader._meshoptMode,
loader._meshoptFilter
);
loader._typedArray = result;
}
loader._state = ResourceLoaderState_default.READY;
return loader;
} catch (error) {
if (loader.isDestroyed()) {
return;
}
loader.unload();
loader._state = ResourceLoaderState_default.FAILED;
const errorMessage = "Failed to load buffer view";
throw loader.getError(errorMessage, error);
}
}
GltfBufferViewLoader.prototype.load = async function() {
if (defined_default(this._promise)) {
return this._promise;
}
this._state = ResourceLoaderState_default.LOADING;
this._promise = loadResources(this);
return this._promise;
};
function getBufferLoader(bufferViewLoader) {
const resourceCache = bufferViewLoader._resourceCache;
const buffer2 = bufferViewLoader._buffer;
if (defined_default(buffer2.uri)) {
const baseResource2 = bufferViewLoader._baseResource;
const resource = baseResource2.getDerivedResource({
url: buffer2.uri
});
return resourceCache.getExternalBufferLoader({
resource
});
}
return resourceCache.getEmbeddedBufferLoader({
parentResource: bufferViewLoader._gltfResource,
bufferId: bufferViewLoader._bufferId
});
}
GltfBufferViewLoader.prototype.unload = function() {
if (defined_default(this._bufferLoader) && !this._bufferLoader.isDestroyed()) {
this._resourceCache.unload(this._bufferLoader);
}
this._bufferLoader = void 0;
this._typedArray = void 0;
};
var GltfBufferViewLoader_default = GltfBufferViewLoader;
// packages/engine/Source/Scene/GltfDracoLoader.js
var import_InlineWorkers476 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/DracoLoader.js
var import_InlineWorkers474 = __toESM(require_InlineWorkers(), 1);
function DracoLoader() {
}
DracoLoader._maxDecodingConcurrency = Math.max(
FeatureDetection_default.hardwareConcurrency - 1,
1
);
DracoLoader._decoderTaskProcessor = void 0;
DracoLoader._taskProcessorReady = false;
DracoLoader._error = void 0;
DracoLoader._getDecoderTaskProcessor = function() {
if (!defined_default(DracoLoader._decoderTaskProcessor)) {
const processor = new TaskProcessor_default(
"decodeDraco",
DracoLoader._maxDecodingConcurrency
);
processor.initWebAssemblyModule({
wasmBinaryFile: "ThirdParty/draco_decoder.wasm"
}).then(function(result) {
if (result) {
DracoLoader._taskProcessorReady = true;
} else {
DracoLoader._error = new RuntimeError_default(
"Draco decoder could not be initialized."
);
}
}).catch((error) => {
DracoLoader._error = error;
});
DracoLoader._decoderTaskProcessor = processor;
}
return DracoLoader._decoderTaskProcessor;
};
DracoLoader.decodePointCloud = function(parameters) {
const decoderTaskProcessor = DracoLoader._getDecoderTaskProcessor();
if (defined_default(DracoLoader._error)) {
throw DracoLoader._error;
}
if (!DracoLoader._taskProcessorReady) {
return;
}
return decoderTaskProcessor.scheduleTask(parameters, [
parameters.buffer.buffer
]);
};
DracoLoader.decodeBufferView = function(options) {
const decoderTaskProcessor = DracoLoader._getDecoderTaskProcessor();
if (defined_default(DracoLoader._error)) {
throw DracoLoader._error;
}
if (!DracoLoader._taskProcessorReady) {
return;
}
return decoderTaskProcessor.scheduleTask(options, [options.array.buffer]);
};
var DracoLoader_default = DracoLoader;
// packages/engine/Source/Scene/VertexAttributeSemantic.js
var import_InlineWorkers475 = __toESM(require_InlineWorkers(), 1);
var VertexAttributeSemantic = {
/**
* Per-vertex position.
*
* @type {string}
* @constant
*/
POSITION: "POSITION",
/**
* Per-vertex normal.
*
* @type {string}
* @constant
*/
NORMAL: "NORMAL",
/**
* Per-vertex tangent.
*
* @type {string}
* @constant
*/
TANGENT: "TANGENT",
/**
* Per-vertex texture coordinates.
*
* @type {string}
* @constant
*/
TEXCOORD: "TEXCOORD",
/**
* Per-vertex color.
*
* @type {string}
* @constant
*/
COLOR: "COLOR",
/**
* Per-vertex joint IDs for skinning.
*
* @type {string}
* @constant
*/
JOINTS: "JOINTS",
/**
* Per-vertex joint weights for skinning.
*
* @type {string}
* @constant
*/
WEIGHTS: "WEIGHTS",
/**
* Per-vertex feature ID.
*
* @type {string}
* @constant
*/
FEATURE_ID: "_FEATURE_ID",
/**
* Gaussian Splat Scale
*
* @type {string}
* @constant
*/
SCALE: "KHR_gaussian_splatting:SCALE",
/**
* Gaussian Splat Rotation
*
* @type {string}
* @constant
*/
ROTATION: "KHR_gaussian_splatting:ROTATION"
};
function semanticToVariableName(semantic) {
switch (semantic) {
case VertexAttributeSemantic.POSITION:
return "positionMC";
case VertexAttributeSemantic.NORMAL:
return "normalMC";
case VertexAttributeSemantic.TANGENT:
return "tangentMC";
case VertexAttributeSemantic.TEXCOORD:
return "texCoord";
case VertexAttributeSemantic.COLOR:
return "color";
case VertexAttributeSemantic.JOINTS:
return "joints";
case VertexAttributeSemantic.WEIGHTS:
return "weights";
case VertexAttributeSemantic.FEATURE_ID:
return "featureId";
case VertexAttributeSemantic.SCALE:
return "scale";
case VertexAttributeSemantic.ROTATION:
return "rotation";
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("semantic is not a valid value.");
}
}
VertexAttributeSemantic.hasSetIndex = function(semantic) {
Check_default.typeOf.string("semantic", semantic);
switch (semantic) {
case VertexAttributeSemantic.POSITION:
case VertexAttributeSemantic.NORMAL:
case VertexAttributeSemantic.TANGENT:
return false;
case VertexAttributeSemantic.TEXCOORD:
case VertexAttributeSemantic.COLOR:
case VertexAttributeSemantic.JOINTS:
case VertexAttributeSemantic.WEIGHTS:
case VertexAttributeSemantic.FEATURE_ID:
case VertexAttributeSemantic.SCALE:
case VertexAttributeSemantic.ROTATION:
return true;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("semantic is not a valid value.");
}
};
VertexAttributeSemantic.fromGltfSemantic = function(gltfSemantic) {
Check_default.typeOf.string("gltfSemantic", gltfSemantic);
let semantic = gltfSemantic;
const setIndexRegex = /^(\w+)_\d+$/;
const setIndexMatch = setIndexRegex.exec(gltfSemantic);
if (setIndexMatch !== null) {
semantic = setIndexMatch[1];
}
switch (semantic) {
case "POSITION":
return VertexAttributeSemantic.POSITION;
case "NORMAL":
return VertexAttributeSemantic.NORMAL;
case "TANGENT":
return VertexAttributeSemantic.TANGENT;
case "TEXCOORD":
return VertexAttributeSemantic.TEXCOORD;
case "COLOR":
return VertexAttributeSemantic.COLOR;
case "JOINTS":
return VertexAttributeSemantic.JOINTS;
case "WEIGHTS":
return VertexAttributeSemantic.WEIGHTS;
case "_FEATURE_ID":
return VertexAttributeSemantic.FEATURE_ID;
case "KHR_gaussian_splatting:SCALE":
case "_SCALE":
return VertexAttributeSemantic.SCALE;
case "KHR_gaussian_splatting:ROTATION":
case "_ROTATION":
return VertexAttributeSemantic.ROTATION;
}
return void 0;
};
VertexAttributeSemantic.fromPntsSemantic = function(pntsSemantic) {
Check_default.typeOf.string("pntsSemantic", pntsSemantic);
switch (pntsSemantic) {
case "POSITION":
case "POSITION_QUANTIZED":
return VertexAttributeSemantic.POSITION;
case "RGBA":
case "RGB":
case "RGB565":
return VertexAttributeSemantic.COLOR;
case "NORMAL":
case "NORMAL_OCT16P":
return VertexAttributeSemantic.NORMAL;
case "BATCH_ID":
return VertexAttributeSemantic.FEATURE_ID;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("pntsSemantic is not a valid value.");
}
};
VertexAttributeSemantic.getGlslType = function(semantic) {
Check_default.typeOf.string("semantic", semantic);
switch (semantic) {
case VertexAttributeSemantic.POSITION:
case VertexAttributeSemantic.NORMAL:
case VertexAttributeSemantic.TANGENT:
return "vec3";
case VertexAttributeSemantic.TEXCOORD:
return "vec2";
case VertexAttributeSemantic.COLOR:
return "vec4";
case VertexAttributeSemantic.JOINTS:
return "ivec4";
case VertexAttributeSemantic.WEIGHTS:
return "vec4";
case VertexAttributeSemantic.FEATURE_ID:
return "int";
case VertexAttributeSemantic.SCALE:
return "vec3";
case VertexAttributeSemantic.ROTATION:
return "vec4";
case VertexAttributeSemantic.OPACITY:
return "float";
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("semantic is not a valid value.");
}
};
VertexAttributeSemantic.getVariableName = function(semantic, setIndex) {
Check_default.typeOf.string("semantic", semantic);
let variableName = semanticToVariableName(semantic);
if (defined_default(setIndex)) {
variableName += `_${setIndex}`;
}
return variableName;
};
var VertexAttributeSemantic_default = Object.freeze(VertexAttributeSemantic);
// packages/engine/Source/Scene/GltfDracoLoader.js
function GltfDracoLoader(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const resourceCache = options.resourceCache;
const gltf = options.gltf;
const primitive = options.primitive;
const draco = options.draco;
const gltfResource = options.gltfResource;
const baseResource2 = options.baseResource;
const cacheKey = options.cacheKey;
Check_default.typeOf.func("options.resourceCache", resourceCache);
Check_default.typeOf.object("options.gltf", gltf);
Check_default.typeOf.object("options.primitive", primitive);
Check_default.typeOf.object("options.draco", draco);
Check_default.typeOf.object("options.gltfResource", gltfResource);
Check_default.typeOf.object("options.baseResource", baseResource2);
this._resourceCache = resourceCache;
this._gltfResource = gltfResource;
this._baseResource = baseResource2;
this._gltf = gltf;
this._primitive = primitive;
this._draco = draco;
this._cacheKey = cacheKey;
this._bufferViewLoader = void 0;
this._bufferViewTypedArray = void 0;
this._decodePromise = void 0;
this._decodedData = void 0;
this._state = ResourceLoaderState_default.UNLOADED;
this._promise = void 0;
this._dracoError = void 0;
}
if (defined_default(Object.create)) {
GltfDracoLoader.prototype = Object.create(ResourceLoader_default.prototype);
GltfDracoLoader.prototype.constructor = GltfDracoLoader;
}
Object.defineProperties(GltfDracoLoader.prototype, {
/**
* The cache key of the resource.
*
* @memberof GltfDracoLoader.prototype
*
* @type {string}
* @readonly
* @private
*/
cacheKey: {
get: function() {
return this._cacheKey;
}
},
/**
* The decoded data.
*
* @memberof GltfDracoLoader.prototype
*
* @type {object}
* @readonly
* @private
*/
decodedData: {
get: function() {
return this._decodedData;
}
}
});
async function loadResources2(loader) {
const resourceCache = loader._resourceCache;
try {
const bufferViewLoader = resourceCache.getBufferViewLoader({
gltf: loader._gltf,
bufferViewId: loader._draco.bufferView,
gltfResource: loader._gltfResource,
baseResource: loader._baseResource
});
loader._bufferViewLoader = bufferViewLoader;
await bufferViewLoader.load();
if (loader.isDestroyed()) {
return;
}
loader._bufferViewTypedArray = bufferViewLoader.typedArray;
loader._state = ResourceLoaderState_default.PROCESSING;
return loader;
} catch (error) {
if (loader.isDestroyed()) {
return;
}
handleError(loader, error);
}
}
GltfDracoLoader.prototype.load = async function() {
if (defined_default(this._promise)) {
return this._promise;
}
this._state = ResourceLoaderState_default.LOADING;
this._promise = loadResources2(this);
return this._promise;
};
function handleError(dracoLoader, error) {
dracoLoader.unload();
dracoLoader._state = ResourceLoaderState_default.FAILED;
const errorMessage = "Failed to load Draco";
throw dracoLoader.getError(errorMessage, error);
}
async function processDecode(loader, decodePromise) {
try {
const results = await decodePromise;
if (loader.isDestroyed()) {
return;
}
loader.unload();
loader._decodedData = {
indices: results.indexArray,
vertexAttributes: results.attributeData
};
loader._state = ResourceLoaderState_default.READY;
return loader._baseResource;
} catch (error) {
if (loader.isDestroyed()) {
return;
}
loader._dracoError = error;
}
}
var SemanticToDracoAttributeType = {};
SemanticToDracoAttributeType[VertexAttributeSemantic_default.POSITION] = "POSITION";
SemanticToDracoAttributeType[VertexAttributeSemantic_default.NORMAL] = "NORMAL";
SemanticToDracoAttributeType[VertexAttributeSemantic_default.COLOR] = "COLOR";
SemanticToDracoAttributeType[VertexAttributeSemantic_default.TEXCOORD] = "TEX_COORD";
function getDracoAttributeType(attribute) {
for (const semantic in SemanticToDracoAttributeType) {
if (SemanticToDracoAttributeType.hasOwnProperty(semantic)) {
if (attribute.startsWith(semantic)) {
return SemanticToDracoAttributeType[semantic];
}
}
}
return void 0;
}
GltfDracoLoader.prototype.process = function(frameState) {
Check_default.typeOf.object("frameState", frameState);
if (this._state === ResourceLoaderState_default.READY) {
return true;
}
if (this._state !== ResourceLoaderState_default.PROCESSING) {
return false;
}
if (defined_default(this._dracoError)) {
handleError(this, this._dracoError);
}
if (!defined_default(this._bufferViewTypedArray)) {
return false;
}
if (defined_default(this._decodePromise)) {
return false;
}
const draco = this._draco;
const primitive = this._primitive;
const gltf = this._gltf;
const bufferViews = gltf.bufferViews;
const bufferViewId = draco.bufferView;
const bufferView = bufferViews[bufferViewId];
const compressedAttributes = draco.attributes;
const attributesToSkipTransform = [];
for (const attribute in primitive.attributes) {
if (primitive.attributes.hasOwnProperty(attribute)) {
const dracoAttributeType = getDracoAttributeType(attribute);
if (defined_default(dracoAttributeType)) {
const accessor = gltf.accessors[primitive.attributes[attribute]];
if (accessor.componentType === ComponentDatatype_default.FLOAT) {
if (!attributesToSkipTransform.includes(dracoAttributeType)) {
attributesToSkipTransform.push(dracoAttributeType);
}
}
}
}
}
const decodeOptions = {
// Need to make a copy of the typed array otherwise the underlying
// ArrayBuffer may be accessed on both the worker and the main thread. This
// leads to errors such as "ArrayBuffer at index 0 is already detached".
// PERFORMANCE_IDEA: Look into SharedArrayBuffer to get around this.
array: new Uint8Array(this._bufferViewTypedArray),
bufferView,
compressedAttributes,
dequantizeInShader: true,
attributesToSkipTransform
};
const decodePromise = DracoLoader_default.decodeBufferView(decodeOptions);
if (!defined_default(decodePromise)) {
return false;
}
this._decodePromise = processDecode(this, decodePromise);
};
GltfDracoLoader.prototype.unload = function() {
if (defined_default(this._bufferViewLoader)) {
this._resourceCache.unload(this._bufferViewLoader);
}
this._bufferViewLoader = void 0;
this._bufferViewTypedArray = void 0;
this._decodedData = void 0;
this._gltf = void 0;
this._primitive = void 0;
};
var GltfDracoLoader_default = GltfDracoLoader;
// packages/engine/Source/Scene/GltfImageLoader.js
var import_InlineWorkers478 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/loadImageFromTypedArray.js
var import_InlineWorkers477 = __toESM(require_InlineWorkers(), 1);
function loadImageFromTypedArray(options) {
const uint8Array = options.uint8Array;
const format = options.format;
const request = options.request;
const flipY = options.flipY ?? false;
const skipColorSpaceConversion = options.skipColorSpaceConversion ?? false;
Check_default.typeOf.object("uint8Array", uint8Array);
Check_default.typeOf.string("format", format);
const blob = new Blob([uint8Array], {
type: format
});
let blobUrl;
return Resource_default.supportsImageBitmapOptions().then(function(result) {
if (result) {
return Promise.resolve(
Resource_default.createImageBitmapFromBlob(blob, {
flipY,
premultiplyAlpha: false,
skipColorSpaceConversion
})
);
}
blobUrl = window.URL.createObjectURL(blob);
const resource = new Resource_default({
url: blobUrl,
request
});
return resource.fetchImage({
flipY,
skipColorSpaceConversion
});
}).then(function(result) {
if (defined_default(blobUrl)) {
window.URL.revokeObjectURL(blobUrl);
}
return result;
}).catch(function(error) {
if (defined_default(blobUrl)) {
window.URL.revokeObjectURL(blobUrl);
}
return Promise.reject(error);
});
}
var loadImageFromTypedArray_default = loadImageFromTypedArray;
// packages/engine/Source/Scene/GltfImageLoader.js
function GltfImageLoader(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const resourceCache = options.resourceCache;
const gltf = options.gltf;
const imageId = options.imageId;
const gltfResource = options.gltfResource;
const baseResource2 = options.baseResource;
const cacheKey = options.cacheKey;
Check_default.typeOf.func("options.resourceCache", resourceCache);
Check_default.typeOf.object("options.gltf", gltf);
Check_default.typeOf.number("options.imageId", imageId);
Check_default.typeOf.object("options.gltfResource", gltfResource);
Check_default.typeOf.object("options.baseResource", baseResource2);
const image = gltf.images[imageId];
const bufferViewId = image.bufferView;
const uri = image.uri;
this._resourceCache = resourceCache;
this._gltfResource = gltfResource;
this._baseResource = baseResource2;
this._gltf = gltf;
this._bufferViewId = bufferViewId;
this._uri = uri;
this._cacheKey = cacheKey;
this._bufferViewLoader = void 0;
this._image = void 0;
this._mipLevels = void 0;
this._state = ResourceLoaderState_default.UNLOADED;
this._promise = void 0;
}
if (defined_default(Object.create)) {
GltfImageLoader.prototype = Object.create(ResourceLoader_default.prototype);
GltfImageLoader.prototype.constructor = GltfImageLoader;
}
Object.defineProperties(GltfImageLoader.prototype, {
/**
* The cache key of the resource.
*
* @memberof GltfImageLoader.prototype
*
* @type {string}
* @readonly
* @private
*/
cacheKey: {
get: function() {
return this._cacheKey;
}
},
/**
* The image.
*
* @memberof GltfImageLoader.prototype
*
* @type {Image|ImageBitmap|CompressedTextureBuffer}
* @readonly
* @private
*/
image: {
get: function() {
return this._image;
}
},
/**
* The mip levels. Only defined for KTX2 files containing mip levels.
*
* @memberof GltfImageLoader.prototype
*
* @type {Uint8Array[]}
* @readonly
* @private
*/
mipLevels: {
get: function() {
return this._mipLevels;
}
}
});
GltfImageLoader.prototype.load = function() {
if (defined_default(this._promise)) {
return this._promise;
}
if (defined_default(this._bufferViewId)) {
this._promise = loadFromBufferView(this);
return this._promise;
}
this._promise = loadFromUri(this);
return this._promise;
};
function getImageAndMipLevels(image) {
let mipLevels;
if (Array.isArray(image)) {
mipLevels = image.slice(1, image.length).map(function(mipLevel) {
return mipLevel.bufferView;
});
image = image[0];
}
return {
image,
mipLevels
};
}
async function loadFromBufferView(imageLoader) {
imageLoader._state = ResourceLoaderState_default.LOADING;
const resourceCache = imageLoader._resourceCache;
try {
const bufferViewLoader = resourceCache.getBufferViewLoader({
gltf: imageLoader._gltf,
bufferViewId: imageLoader._bufferViewId,
gltfResource: imageLoader._gltfResource,
baseResource: imageLoader._baseResource
});
imageLoader._bufferViewLoader = bufferViewLoader;
await bufferViewLoader.load();
if (imageLoader.isDestroyed()) {
return;
}
const typedArray = bufferViewLoader.typedArray;
const image = await loadImageFromBufferTypedArray(typedArray);
if (imageLoader.isDestroyed()) {
return;
}
const imageAndMipLevels = getImageAndMipLevels(image);
imageLoader.unload();
imageLoader._image = imageAndMipLevels.image;
imageLoader._mipLevels = imageAndMipLevels.mipLevels;
imageLoader._state = ResourceLoaderState_default.READY;
return imageLoader;
} catch (error) {
if (imageLoader.isDestroyed()) {
return;
}
return handleError2(imageLoader, error, "Failed to load embedded image");
}
}
async function loadFromUri(imageLoader) {
imageLoader._state = ResourceLoaderState_default.LOADING;
const baseResource2 = imageLoader._baseResource;
const uri = imageLoader._uri;
const resource = baseResource2.getDerivedResource({
url: uri
});
try {
const image = await loadImageFromUri(resource);
if (imageLoader.isDestroyed()) {
return;
}
const imageAndMipLevels = getImageAndMipLevels(image);
imageLoader.unload();
imageLoader._image = imageAndMipLevels.image;
imageLoader._mipLevels = imageAndMipLevels.mipLevels;
imageLoader._state = ResourceLoaderState_default.READY;
return imageLoader;
} catch (error) {
if (imageLoader.isDestroyed()) {
return;
}
return handleError2(imageLoader, error, `Failed to load image: ${uri}`);
}
}
function handleError2(imageLoader, error, errorMessage) {
imageLoader.unload();
imageLoader._state = ResourceLoaderState_default.FAILED;
return Promise.reject(imageLoader.getError(errorMessage, error));
}
function getMimeTypeFromTypedArray(typedArray) {
const header = typedArray.subarray(0, 2);
const webpHeaderRIFFChars = typedArray.subarray(0, 4);
const webpHeaderWEBPChars = typedArray.subarray(8, 12);
if (header[0] === 255 && header[1] === 216) {
return "image/jpeg";
} else if (header[0] === 137 && header[1] === 80) {
return "image/png";
} else if (header[0] === 171 && header[1] === 75) {
return "image/ktx2";
} else if (
// See https://developers.google.com/speed/webp/docs/riff_container#webp_file_header
webpHeaderRIFFChars[0] === 82 && webpHeaderRIFFChars[1] === 73 && webpHeaderRIFFChars[2] === 70 && webpHeaderRIFFChars[3] === 70 && webpHeaderWEBPChars[0] === 87 && webpHeaderWEBPChars[1] === 69 && webpHeaderWEBPChars[2] === 66 && webpHeaderWEBPChars[3] === 80
) {
return "image/webp";
}
throw new RuntimeError_default("Image format is not recognized");
}
async function loadImageFromBufferTypedArray(typedArray) {
const mimeType = getMimeTypeFromTypedArray(typedArray);
if (mimeType === "image/ktx2") {
const ktxBuffer = new Uint8Array(typedArray);
return loadKTX2_default(ktxBuffer);
}
return GltfImageLoader._loadImageFromTypedArray({
uint8Array: typedArray,
format: mimeType,
flipY: false,
skipColorSpaceConversion: true
});
}
var ktx2Regex2 = /(^data:image\/ktx2)|(\.ktx2$)/i;
function loadImageFromUri(resource) {
const uri = resource.getUrlComponent(false, true);
if (ktx2Regex2.test(uri)) {
return loadKTX2_default(resource);
}
return resource.fetchImage({
skipColorSpaceConversion: true,
preferImageBitmap: true
});
}
GltfImageLoader.prototype.unload = function() {
if (defined_default(this._bufferViewLoader) && !this._bufferViewLoader.isDestroyed()) {
this._resourceCache.unload(this._bufferViewLoader);
}
this._bufferViewLoader = void 0;
this._uri = void 0;
this._image = void 0;
this._mipLevels = void 0;
this._gltf = void 0;
};
GltfImageLoader._loadImageFromTypedArray = loadImageFromTypedArray_default;
var GltfImageLoader_default = GltfImageLoader;
// packages/engine/Source/Scene/GltfIndexBufferLoader.js
var import_InlineWorkers480 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/JobType.js
var import_InlineWorkers479 = __toESM(require_InlineWorkers(), 1);
var JobType = {
TEXTURE: 0,
PROGRAM: 1,
BUFFER: 2,
NUMBER_OF_JOB_TYPES: 3
};
var JobType_default = Object.freeze(JobType);
// packages/engine/Source/Scene/GltfIndexBufferLoader.js
function GltfIndexBufferLoader(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const resourceCache = options.resourceCache;
const gltf = options.gltf;
const accessorId = options.accessorId;
const gltfResource = options.gltfResource;
const baseResource2 = options.baseResource;
const primitive = options.primitive;
const draco = options.draco;
const cacheKey = options.cacheKey;
const asynchronous = options.asynchronous ?? true;
const loadBuffer = options.loadBuffer ?? false;
const loadTypedArray = options.loadTypedArray ?? false;
Check_default.typeOf.func("options.resourceCache", resourceCache);
Check_default.typeOf.object("options.gltf", gltf);
Check_default.typeOf.number("options.accessorId", accessorId);
Check_default.typeOf.object("options.gltfResource", gltfResource);
Check_default.typeOf.object("options.baseResource", baseResource2);
if (!loadBuffer && !loadTypedArray) {
throw new DeveloperError_default(
"At least one of loadBuffer and loadTypedArray must be true."
);
}
const indexDatatype = gltf.accessors[accessorId].componentType;
this._resourceCache = resourceCache;
this._gltfResource = gltfResource;
this._baseResource = baseResource2;
this._gltf = gltf;
this._accessorId = accessorId;
this._indexDatatype = indexDatatype;
this._primitive = primitive;
this._draco = draco;
this._cacheKey = cacheKey;
this._asynchronous = asynchronous;
this._loadBuffer = loadBuffer;
this._loadTypedArray = loadTypedArray;
this._bufferViewLoader = void 0;
this._dracoLoader = void 0;
this._typedArray = void 0;
this._buffer = void 0;
this._state = ResourceLoaderState_default.UNLOADED;
this._promise = void 0;
}
if (defined_default(Object.create)) {
GltfIndexBufferLoader.prototype = Object.create(ResourceLoader_default.prototype);
GltfIndexBufferLoader.prototype.constructor = GltfIndexBufferLoader;
}
Object.defineProperties(GltfIndexBufferLoader.prototype, {
/**
* The cache key of the resource.
*
* @memberof GltfIndexBufferLoader.prototype
*
* @type {string}
* @readonly
* @private
*/
cacheKey: {
get: function() {
return this._cacheKey;
}
},
/**
* The index buffer. This is only defined when loadBuffer is true.
*
* @memberof GltfIndexBufferLoader.prototype
*
* @type {Buffer}
* @readonly
* @private
*/
buffer: {
get: function() {
return this._buffer;
}
},
/**
* The typed array containing indices. This is only defined when loadTypedArray is true.
*
* @memberof GltfIndexBufferLoader.prototype
*
* @type {Uint8Array|Uint16Array|Uint32Array}
* @readonly
* @private
*/
typedArray: {
get: function() {
return this._typedArray;
}
},
/**
* The index datatype after decode.
*
* @memberof GltfIndexBufferLoader.prototype
*
* @type {IndexDatatype}
* @readonly
* @private
*/
indexDatatype: {
get: function() {
return this._indexDatatype;
}
}
});
var scratchIndexBufferJob = new CreateIndexBufferJob();
GltfIndexBufferLoader.prototype.load = async function() {
if (defined_default(this._promise)) {
return this._promise;
}
if (defined_default(this._draco)) {
this._promise = loadFromDraco(this);
return this._promise;
}
this._promise = loadFromBufferView2(this);
return this._promise;
};
async function loadFromDraco(indexBufferLoader) {
indexBufferLoader._state = ResourceLoaderState_default.LOADING;
const resourceCache = indexBufferLoader._resourceCache;
try {
const dracoLoader = resourceCache.getDracoLoader({
gltf: indexBufferLoader._gltf,
primitive: indexBufferLoader._primitive,
draco: indexBufferLoader._draco,
gltfResource: indexBufferLoader._gltfResource,
baseResource: indexBufferLoader._baseResource
});
indexBufferLoader._dracoLoader = dracoLoader;
await dracoLoader.load();
if (indexBufferLoader.isDestroyed()) {
return;
}
indexBufferLoader._state = ResourceLoaderState_default.LOADED;
return indexBufferLoader;
} catch (error) {
if (indexBufferLoader.isDestroyed()) {
return;
}
handleError3(indexBufferLoader, error);
}
}
async function loadFromBufferView2(indexBufferLoader) {
const gltf = indexBufferLoader._gltf;
const accessorId = indexBufferLoader._accessorId;
const accessor = gltf.accessors[accessorId];
const bufferViewId = accessor.bufferView;
indexBufferLoader._state = ResourceLoaderState_default.LOADING;
const resourceCache = indexBufferLoader._resourceCache;
try {
const bufferViewLoader = resourceCache.getBufferViewLoader({
gltf,
bufferViewId,
gltfResource: indexBufferLoader._gltfResource,
baseResource: indexBufferLoader._baseResource
});
indexBufferLoader._bufferViewLoader = bufferViewLoader;
await bufferViewLoader.load();
if (indexBufferLoader.isDestroyed()) {
return;
}
const bufferViewTypedArray = bufferViewLoader.typedArray;
indexBufferLoader._typedArray = createIndicesTypedArray(
indexBufferLoader,
bufferViewTypedArray
);
indexBufferLoader._state = ResourceLoaderState_default.PROCESSING;
return indexBufferLoader;
} catch (error) {
if (indexBufferLoader.isDestroyed()) {
return;
}
handleError3(indexBufferLoader, error);
}
}
function createIndicesTypedArray(indexBufferLoader, bufferViewTypedArray) {
const gltf = indexBufferLoader._gltf;
const accessorId = indexBufferLoader._accessorId;
const accessor = gltf.accessors[accessorId];
const count = accessor.count;
const indexDatatype = accessor.componentType;
const indexSize = IndexDatatype_default.getSizeInBytes(indexDatatype);
let arrayBuffer = bufferViewTypedArray.buffer;
let byteOffset = bufferViewTypedArray.byteOffset + accessor.byteOffset;
if (byteOffset % indexSize !== 0) {
const byteLength = count * indexSize;
const view = new Uint8Array(arrayBuffer, byteOffset, byteLength);
const copy = new Uint8Array(view);
arrayBuffer = copy.buffer;
byteOffset = 0;
deprecationWarning_default(
"index-buffer-unaligned",
`The index array is not aligned to a ${indexSize}-byte boundary.`
);
}
let typedArray;
if (indexDatatype === IndexDatatype_default.UNSIGNED_BYTE) {
typedArray = new Uint8Array(arrayBuffer, byteOffset, count);
} else if (indexDatatype === IndexDatatype_default.UNSIGNED_SHORT) {
typedArray = new Uint16Array(arrayBuffer, byteOffset, count);
} else if (indexDatatype === IndexDatatype_default.UNSIGNED_INT) {
typedArray = new Uint32Array(arrayBuffer, byteOffset, count);
}
return typedArray;
}
function handleError3(indexBufferLoader, error) {
indexBufferLoader.unload();
indexBufferLoader._state = ResourceLoaderState_default.FAILED;
const errorMessage = "Failed to load index buffer";
throw indexBufferLoader.getError(errorMessage, error);
}
function CreateIndexBufferJob() {
this.typedArray = void 0;
this.indexDatatype = void 0;
this.context = void 0;
this.buffer = void 0;
}
CreateIndexBufferJob.prototype.set = function(typedArray, indexDatatype, context) {
this.typedArray = typedArray;
this.indexDatatype = indexDatatype;
this.context = context;
};
CreateIndexBufferJob.prototype.execute = function() {
this.buffer = createIndexBuffer(
this.typedArray,
this.indexDatatype,
this.context
);
};
function createIndexBuffer(typedArray, indexDatatype, context) {
const buffer2 = Buffer_default.createIndexBuffer({
typedArray,
context,
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype
});
buffer2.vertexArrayDestroyable = false;
return buffer2;
}
GltfIndexBufferLoader.prototype.process = function(frameState) {
Check_default.typeOf.object("frameState", frameState);
if (this._state === ResourceLoaderState_default.READY) {
return true;
}
if (this._state !== ResourceLoaderState_default.LOADED && this._state !== ResourceLoaderState_default.PROCESSING) {
return false;
}
let typedArray = this._typedArray;
let indexDatatype = this._indexDatatype;
if (defined_default(this._dracoLoader)) {
try {
const ready = this._dracoLoader.process(frameState);
if (ready) {
const dracoLoader = this._dracoLoader;
typedArray = dracoLoader.decodedData.indices.typedArray;
this._typedArray = typedArray;
indexDatatype = ComponentDatatype_default.fromTypedArray(typedArray);
this._indexDatatype = indexDatatype;
}
} catch (error) {
handleError3(this, error);
}
}
if (!defined_default(typedArray)) {
return false;
}
let buffer2;
if (this._loadBuffer && this._asynchronous) {
const indexBufferJob = scratchIndexBufferJob;
indexBufferJob.set(typedArray, indexDatatype, frameState.context);
const jobScheduler = frameState.jobScheduler;
if (!jobScheduler.execute(indexBufferJob, JobType_default.BUFFER)) {
return false;
}
buffer2 = indexBufferJob.buffer;
} else if (this._loadBuffer) {
buffer2 = createIndexBuffer(typedArray, indexDatatype, frameState.context);
}
this.unload();
this._buffer = buffer2;
this._typedArray = this._loadTypedArray ? typedArray : void 0;
this._state = ResourceLoaderState_default.READY;
this._resourceCache.statistics.addGeometryLoader(this);
return true;
};
GltfIndexBufferLoader.prototype.unload = function() {
if (defined_default(this._buffer)) {
this._buffer.destroy();
}
const resourceCache = this._resourceCache;
if (defined_default(this._bufferViewLoader) && !this._bufferViewLoader.isDestroyed()) {
resourceCache.unload(this._bufferViewLoader);
}
if (defined_default(this._dracoLoader)) {
resourceCache.unload(this._dracoLoader);
}
this._bufferViewLoader = void 0;
this._dracoLoader = void 0;
this._typedArray = void 0;
this._buffer = void 0;
this._gltf = void 0;
this._primitive = void 0;
};
var GltfIndexBufferLoader_default = GltfIndexBufferLoader;
// packages/engine/Source/Scene/GltfJsonLoader.js
var import_InlineWorkers506 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfPipeline/addDefaults.js
var import_InlineWorkers486 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfPipeline/addToArray.js
var import_InlineWorkers481 = __toESM(require_InlineWorkers(), 1);
function addToArray(array, element, checkDuplicates) {
checkDuplicates = checkDuplicates ?? false;
if (checkDuplicates) {
const index = array.indexOf(element);
if (index > -1) {
return index;
}
}
array.push(element);
return array.length - 1;
}
var addToArray_default = addToArray;
// packages/engine/Source/Scene/GltfPipeline/ForEach.js
var import_InlineWorkers483 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfPipeline/usesExtension.js
var import_InlineWorkers482 = __toESM(require_InlineWorkers(), 1);
function usesExtension(gltf, extension) {
return defined_default(gltf.extensionsUsed) && gltf.extensionsUsed.indexOf(extension) >= 0;
}
var usesExtension_default = usesExtension;
// packages/engine/Source/Scene/GltfPipeline/ForEach.js
function ForEach() {
}
ForEach.objectLegacy = function(objects, handler) {
if (defined_default(objects)) {
for (const objectId in objects) {
if (Object.prototype.hasOwnProperty.call(objects, objectId)) {
const object2 = objects[objectId];
const value = handler(object2, objectId);
if (defined_default(value)) {
return value;
}
}
}
}
};
ForEach.object = function(arrayOfObjects, handler) {
if (defined_default(arrayOfObjects)) {
const length2 = arrayOfObjects.length;
for (let i = 0; i < length2; i++) {
const object2 = arrayOfObjects[i];
const value = handler(object2, i);
if (defined_default(value)) {
return value;
}
}
}
};
ForEach.topLevel = function(gltf, name, handler) {
const gltfProperty = gltf[name];
if (defined_default(gltfProperty) && !Array.isArray(gltfProperty)) {
return ForEach.objectLegacy(gltfProperty, handler);
}
return ForEach.object(gltfProperty, handler);
};
ForEach.accessor = function(gltf, handler) {
return ForEach.topLevel(gltf, "accessors", handler);
};
ForEach.accessorWithSemantic = function(gltf, semantic, handler) {
const visited = {};
return ForEach.mesh(gltf, function(mesh) {
return ForEach.meshPrimitive(mesh, function(primitive) {
const valueForEach = ForEach.meshPrimitiveAttribute(
primitive,
function(accessorId, attributeSemantic) {
if (attributeSemantic.indexOf(semantic) === 0 && !defined_default(visited[accessorId])) {
visited[accessorId] = true;
const value = handler(accessorId);
if (defined_default(value)) {
return value;
}
}
}
);
if (defined_default(valueForEach)) {
return valueForEach;
}
return ForEach.meshPrimitiveTarget(primitive, function(target) {
return ForEach.meshPrimitiveTargetAttribute(
target,
function(accessorId, attributeSemantic) {
if (attributeSemantic.indexOf(semantic) === 0 && !defined_default(visited[accessorId])) {
visited[accessorId] = true;
const value = handler(accessorId);
if (defined_default(value)) {
return value;
}
}
}
);
});
});
});
};
ForEach.accessorContainingVertexAttributeData = function(gltf, handler) {
const visited = {};
return ForEach.mesh(gltf, function(mesh) {
return ForEach.meshPrimitive(mesh, function(primitive) {
const valueForEach = ForEach.meshPrimitiveAttribute(
primitive,
function(accessorId) {
if (!defined_default(visited[accessorId])) {
visited[accessorId] = true;
const value = handler(accessorId);
if (defined_default(value)) {
return value;
}
}
}
);
if (defined_default(valueForEach)) {
return valueForEach;
}
return ForEach.meshPrimitiveTarget(primitive, function(target) {
return ForEach.meshPrimitiveTargetAttribute(
target,
function(accessorId) {
if (!defined_default(visited[accessorId])) {
visited[accessorId] = true;
const value = handler(accessorId);
if (defined_default(value)) {
return value;
}
}
}
);
});
});
});
};
ForEach.accessorContainingIndexData = function(gltf, handler) {
const visited = {};
return ForEach.mesh(gltf, function(mesh) {
return ForEach.meshPrimitive(mesh, function(primitive) {
const indices = primitive.indices;
if (defined_default(indices) && !defined_default(visited[indices])) {
visited[indices] = true;
const value = handler(indices);
if (defined_default(value)) {
return value;
}
}
});
});
};
ForEach.animation = function(gltf, handler) {
return ForEach.topLevel(gltf, "animations", handler);
};
ForEach.animationChannel = function(animation, handler) {
const channels = animation.channels;
return ForEach.object(channels, handler);
};
ForEach.animationSampler = function(animation, handler) {
const samplers = animation.samplers;
return ForEach.object(samplers, handler);
};
ForEach.buffer = function(gltf, handler) {
return ForEach.topLevel(gltf, "buffers", handler);
};
ForEach.bufferView = function(gltf, handler) {
return ForEach.topLevel(gltf, "bufferViews", handler);
};
ForEach.camera = function(gltf, handler) {
return ForEach.topLevel(gltf, "cameras", handler);
};
ForEach.image = function(gltf, handler) {
return ForEach.topLevel(gltf, "images", handler);
};
ForEach.material = function(gltf, handler) {
return ForEach.topLevel(gltf, "materials", handler);
};
ForEach.materialValue = function(material, handler) {
let values = material.values;
if (defined_default(material.extensions) && defined_default(material.extensions.KHR_techniques_webgl)) {
values = material.extensions.KHR_techniques_webgl.values;
}
for (const name in values) {
if (Object.prototype.hasOwnProperty.call(values, name)) {
const value = handler(values[name], name);
if (defined_default(value)) {
return value;
}
}
}
};
ForEach.mesh = function(gltf, handler) {
return ForEach.topLevel(gltf, "meshes", handler);
};
ForEach.meshPrimitive = function(mesh, handler) {
const primitives = mesh.primitives;
if (defined_default(primitives)) {
const primitivesLength = primitives.length;
for (let i = 0; i < primitivesLength; i++) {
const primitive = primitives[i];
const value = handler(primitive, i);
if (defined_default(value)) {
return value;
}
}
}
};
ForEach.meshPrimitiveAttribute = function(primitive, handler) {
const attributes = primitive.attributes;
for (const semantic in attributes) {
if (Object.prototype.hasOwnProperty.call(attributes, semantic)) {
const value = handler(attributes[semantic], semantic);
if (defined_default(value)) {
return value;
}
}
}
};
ForEach.meshPrimitiveTarget = function(primitive, handler) {
const targets = primitive.targets;
if (defined_default(targets)) {
const length2 = targets.length;
for (let i = 0; i < length2; ++i) {
const value = handler(targets[i], i);
if (defined_default(value)) {
return value;
}
}
}
};
ForEach.meshPrimitiveTargetAttribute = function(target, handler) {
for (const semantic in target) {
if (Object.prototype.hasOwnProperty.call(target, semantic)) {
const accessorId = target[semantic];
const value = handler(accessorId, semantic);
if (defined_default(value)) {
return value;
}
}
}
};
ForEach.node = function(gltf, handler) {
return ForEach.topLevel(gltf, "nodes", handler);
};
ForEach.nodeInTree = function(gltf, nodeIds, handler) {
const nodes = gltf.nodes;
if (defined_default(nodes)) {
const length2 = nodeIds.length;
for (let i = 0; i < length2; i++) {
const nodeId = nodeIds[i];
const node = nodes[nodeId];
if (defined_default(node)) {
let value = handler(node, nodeId);
if (defined_default(value)) {
return value;
}
const children = node.children;
if (defined_default(children)) {
value = ForEach.nodeInTree(gltf, children, handler);
if (defined_default(value)) {
return value;
}
}
}
}
}
};
ForEach.nodeInScene = function(gltf, scene, handler) {
const sceneNodeIds = scene.nodes;
if (defined_default(sceneNodeIds)) {
return ForEach.nodeInTree(gltf, sceneNodeIds, handler);
}
};
ForEach.program = function(gltf, handler) {
if (usesExtension_default(gltf, "KHR_techniques_webgl")) {
return ForEach.object(
gltf.extensions.KHR_techniques_webgl.programs,
handler
);
}
return ForEach.topLevel(gltf, "programs", handler);
};
ForEach.sampler = function(gltf, handler) {
return ForEach.topLevel(gltf, "samplers", handler);
};
ForEach.scene = function(gltf, handler) {
return ForEach.topLevel(gltf, "scenes", handler);
};
ForEach.shader = function(gltf, handler) {
if (usesExtension_default(gltf, "KHR_techniques_webgl")) {
return ForEach.object(
gltf.extensions.KHR_techniques_webgl.shaders,
handler
);
}
return ForEach.topLevel(gltf, "shaders", handler);
};
ForEach.skin = function(gltf, handler) {
return ForEach.topLevel(gltf, "skins", handler);
};
ForEach.skinJoint = function(skin, handler) {
const joints = skin.joints;
if (defined_default(joints)) {
const jointsLength = joints.length;
for (let i = 0; i < jointsLength; i++) {
const joint = joints[i];
const value = handler(joint);
if (defined_default(value)) {
return value;
}
}
}
};
ForEach.techniqueAttribute = function(technique, handler) {
const attributes = technique.attributes;
for (const attributeName in attributes) {
if (Object.prototype.hasOwnProperty.call(attributes, attributeName)) {
const value = handler(attributes[attributeName], attributeName);
if (defined_default(value)) {
return value;
}
}
}
};
ForEach.techniqueUniform = function(technique, handler) {
const uniforms = technique.uniforms;
for (const uniformName in uniforms) {
if (Object.prototype.hasOwnProperty.call(uniforms, uniformName)) {
const value = handler(uniforms[uniformName], uniformName);
if (defined_default(value)) {
return value;
}
}
}
};
ForEach.techniqueParameter = function(technique, handler) {
const parameters = technique.parameters;
for (const parameterName in parameters) {
if (Object.prototype.hasOwnProperty.call(parameters, parameterName)) {
const value = handler(parameters[parameterName], parameterName);
if (defined_default(value)) {
return value;
}
}
}
};
ForEach.technique = function(gltf, handler) {
if (usesExtension_default(gltf, "KHR_techniques_webgl")) {
return ForEach.object(
gltf.extensions.KHR_techniques_webgl.techniques,
handler
);
}
return ForEach.topLevel(gltf, "techniques", handler);
};
ForEach.texture = function(gltf, handler) {
return ForEach.topLevel(gltf, "textures", handler);
};
var ForEach_default = ForEach;
// packages/engine/Source/Scene/GltfPipeline/getAccessorByteStride.js
var import_InlineWorkers485 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfPipeline/numberOfComponentsForType.js
var import_InlineWorkers484 = __toESM(require_InlineWorkers(), 1);
function numberOfComponentsForType(type) {
switch (type) {
case "SCALAR":
return 1;
case "VEC2":
return 2;
case "VEC3":
return 3;
case "VEC4":
case "MAT2":
return 4;
case "MAT3":
return 9;
case "MAT4":
return 16;
}
}
var numberOfComponentsForType_default = numberOfComponentsForType;
// packages/engine/Source/Scene/GltfPipeline/getAccessorByteStride.js
function getAccessorByteStride(gltf, accessor) {
const bufferViewId = accessor.bufferView;
if (defined_default(bufferViewId)) {
const bufferView = gltf.bufferViews[bufferViewId];
if (defined_default(bufferView.byteStride) && bufferView.byteStride > 0) {
return bufferView.byteStride;
}
}
return ComponentDatatype_default.getSizeInBytes(accessor.componentType) * numberOfComponentsForType_default(accessor.type);
}
var getAccessorByteStride_default = getAccessorByteStride;
// packages/engine/Source/Scene/GltfPipeline/addDefaults.js
function addDefaults(gltf) {
ForEach_default.accessor(gltf, function(accessor) {
if (defined_default(accessor.bufferView)) {
accessor.byteOffset = accessor.byteOffset ?? 0;
}
});
ForEach_default.bufferView(gltf, function(bufferView) {
if (defined_default(bufferView.buffer)) {
bufferView.byteOffset = bufferView.byteOffset ?? 0;
}
});
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
primitive.mode = primitive.mode ?? WebGLConstants_default.TRIANGLES;
if (!defined_default(primitive.material)) {
if (!defined_default(gltf.materials)) {
gltf.materials = [];
}
const defaultMaterial4 = {
name: "default"
};
primitive.material = addToArray_default(gltf.materials, defaultMaterial4);
}
});
});
ForEach_default.accessorContainingVertexAttributeData(gltf, function(accessorId) {
const accessor = gltf.accessors[accessorId];
const bufferViewId = accessor.bufferView;
accessor.normalized = accessor.normalized ?? false;
if (defined_default(bufferViewId)) {
const bufferView = gltf.bufferViews[bufferViewId];
bufferView.byteStride = getAccessorByteStride_default(gltf, accessor);
bufferView.target = WebGLConstants_default.ARRAY_BUFFER;
}
});
ForEach_default.accessorContainingIndexData(gltf, function(accessorId) {
const accessor = gltf.accessors[accessorId];
const bufferViewId = accessor.bufferView;
if (defined_default(bufferViewId)) {
const bufferView = gltf.bufferViews[bufferViewId];
bufferView.target = WebGLConstants_default.ELEMENT_ARRAY_BUFFER;
}
});
ForEach_default.material(gltf, function(material) {
const extensions = material.extensions ?? {};
const materialsCommon = extensions.KHR_materials_common;
if (defined_default(materialsCommon)) {
const technique = materialsCommon.technique;
const values = defined_default(materialsCommon.values) ? materialsCommon.values : {};
materialsCommon.values = values;
values.ambient = defined_default(values.ambient) ? values.ambient : [0, 0, 0, 1];
values.emission = defined_default(values.emission) ? values.emission : [0, 0, 0, 1];
values.transparency = values.transparency ?? 1;
if (technique !== "CONSTANT") {
values.diffuse = defined_default(values.diffuse) ? values.diffuse : [0, 0, 0, 1];
if (technique !== "LAMBERT") {
values.specular = defined_default(values.specular) ? values.specular : [0, 0, 0, 1];
values.shininess = values.shininess ?? 0;
}
}
materialsCommon.transparent = materialsCommon.transparent ?? false;
materialsCommon.doubleSided = materialsCommon.doubleSided ?? false;
return;
}
material.emissiveFactor = material.emissiveFactor ?? [0, 0, 0];
material.alphaMode = material.alphaMode ?? "OPAQUE";
material.doubleSided = material.doubleSided ?? false;
if (material.alphaMode === "MASK") {
material.alphaCutoff = material.alphaCutoff ?? 0.5;
}
const techniquesExtension = extensions.KHR_techniques_webgl;
if (defined_default(techniquesExtension)) {
ForEach_default.materialValue(material, function(materialValue) {
if (defined_default(materialValue.index)) {
addTextureDefaults(materialValue);
}
});
}
addTextureDefaults(material.emissiveTexture);
addTextureDefaults(material.normalTexture);
addTextureDefaults(material.occlusionTexture);
const pbrMetallicRoughness = material.pbrMetallicRoughness;
if (defined_default(pbrMetallicRoughness)) {
pbrMetallicRoughness.baseColorFactor = pbrMetallicRoughness.baseColorFactor ?? [1, 1, 1, 1];
pbrMetallicRoughness.metallicFactor = pbrMetallicRoughness.metallicFactor ?? 1;
pbrMetallicRoughness.roughnessFactor = pbrMetallicRoughness.roughnessFactor ?? 1;
addTextureDefaults(pbrMetallicRoughness.baseColorTexture);
addTextureDefaults(pbrMetallicRoughness.metallicRoughnessTexture);
}
const pbrSpecularGlossiness = extensions.KHR_materials_pbrSpecularGlossiness;
if (defined_default(pbrSpecularGlossiness)) {
pbrSpecularGlossiness.diffuseFactor = pbrSpecularGlossiness.diffuseFactor ?? [1, 1, 1, 1];
pbrSpecularGlossiness.specularFactor = pbrSpecularGlossiness.specularFactor ?? [1, 1, 1];
pbrSpecularGlossiness.glossinessFactor = pbrSpecularGlossiness.glossinessFactor ?? 1;
addTextureDefaults(pbrSpecularGlossiness.specularGlossinessTexture);
}
});
ForEach_default.animation(gltf, function(animation) {
ForEach_default.animationSampler(animation, function(sampler) {
sampler.interpolation = sampler.interpolation ?? "LINEAR";
});
});
const animatedNodes = getAnimatedNodes(gltf);
ForEach_default.node(gltf, function(node, id) {
const animated = defined_default(animatedNodes[id]);
if (animated || defined_default(node.translation) || defined_default(node.rotation) || defined_default(node.scale)) {
node.translation = node.translation ?? [0, 0, 0];
node.rotation = node.rotation ?? [0, 0, 0, 1];
node.scale = node.scale ?? [1, 1, 1];
} else {
node.matrix = node.matrix ?? [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
];
}
});
ForEach_default.sampler(gltf, function(sampler) {
sampler.wrapS = sampler.wrapS ?? WebGLConstants_default.REPEAT;
sampler.wrapT = sampler.wrapT ?? WebGLConstants_default.REPEAT;
});
if (defined_default(gltf.scenes) && !defined_default(gltf.scene)) {
gltf.scene = 0;
}
return gltf;
}
function getAnimatedNodes(gltf) {
const nodes = {};
ForEach_default.animation(gltf, function(animation) {
ForEach_default.animationChannel(animation, function(channel) {
const target = channel.target;
const nodeId = target.node;
const path = target.path;
if (path === "translation" || path === "rotation" || path === "scale") {
nodes[nodeId] = true;
}
});
});
return nodes;
}
function addTextureDefaults(texture) {
if (defined_default(texture)) {
texture.texCoord = texture.texCoord ?? 0;
}
}
var addDefaults_default = addDefaults;
// packages/engine/Source/Scene/GltfPipeline/addPipelineExtras.js
var import_InlineWorkers487 = __toESM(require_InlineWorkers(), 1);
function addPipelineExtras(gltf) {
ForEach_default.shader(gltf, function(shader) {
addExtras(shader);
});
ForEach_default.buffer(gltf, function(buffer2) {
addExtras(buffer2);
});
ForEach_default.image(gltf, function(image) {
addExtras(image);
});
addExtras(gltf);
return gltf;
}
function addExtras(object2) {
object2.extras = defined_default(object2.extras) ? object2.extras : {};
object2.extras._pipeline = defined_default(object2.extras._pipeline) ? object2.extras._pipeline : {};
}
var addPipelineExtras_default = addPipelineExtras;
// packages/engine/Source/Scene/GltfPipeline/parseGlb.js
var import_InlineWorkers490 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfPipeline/removeExtensionsUsed.js
var import_InlineWorkers489 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfPipeline/removeExtensionsRequired.js
var import_InlineWorkers488 = __toESM(require_InlineWorkers(), 1);
function removeExtensionsRequired(gltf, extension) {
const extensionsRequired = gltf.extensionsRequired;
if (defined_default(extensionsRequired)) {
const index = extensionsRequired.indexOf(extension);
if (index >= 0) {
extensionsRequired.splice(index, 1);
}
if (extensionsRequired.length === 0) {
delete gltf.extensionsRequired;
}
}
}
var removeExtensionsRequired_default = removeExtensionsRequired;
// packages/engine/Source/Scene/GltfPipeline/removeExtensionsUsed.js
function removeExtensionsUsed(gltf, extension) {
const extensionsUsed = gltf.extensionsUsed;
if (defined_default(extensionsUsed)) {
const index = extensionsUsed.indexOf(extension);
if (index >= 0) {
extensionsUsed.splice(index, 1);
}
removeExtensionsRequired_default(gltf, extension);
if (extensionsUsed.length === 0) {
delete gltf.extensionsUsed;
}
}
}
var removeExtensionsUsed_default = removeExtensionsUsed;
// packages/engine/Source/Scene/GltfPipeline/parseGlb.js
var sizeOfUint323 = 4;
function parseGlb(glb) {
const magic = getMagic_default(glb);
if (magic !== "glTF") {
throw new RuntimeError_default("File is not valid binary glTF");
}
const header = readHeader(glb, 0, 5);
const version2 = header[1];
if (version2 !== 1 && version2 !== 2) {
throw new RuntimeError_default("Binary glTF version is not 1 or 2");
}
if (version2 === 1) {
return parseGlbVersion1(glb, header);
}
return parseGlbVersion2(glb, header);
}
function readHeader(glb, byteOffset, count) {
const dataView = new DataView(glb.buffer);
const header = new Array(count);
for (let i = 0; i < count; ++i) {
header[i] = dataView.getUint32(
glb.byteOffset + byteOffset + i * sizeOfUint323,
true
);
}
return header;
}
function parseGlbVersion1(glb, header) {
const length2 = header[2];
const contentLength = header[3];
const contentFormat = header[4];
if (contentFormat !== 0) {
throw new RuntimeError_default("Binary glTF scene format is not JSON");
}
const jsonStart = 20;
const binaryStart = jsonStart + contentLength;
const contentString = getStringFromTypedArray_default(glb, jsonStart, contentLength);
const gltf = JSON.parse(contentString);
addPipelineExtras_default(gltf);
const binaryBuffer = glb.subarray(binaryStart, length2);
const buffers = gltf.buffers;
if (defined_default(buffers) && Object.keys(buffers).length > 0) {
const binaryGltfBuffer = buffers.binary_glTF ?? buffers.KHR_binary_glTF;
if (defined_default(binaryGltfBuffer)) {
binaryGltfBuffer.extras._pipeline.source = binaryBuffer;
delete binaryGltfBuffer.uri;
}
}
removeExtensionsUsed_default(gltf, "KHR_binary_glTF");
return gltf;
}
function parseGlbVersion2(glb, header) {
const length2 = header[2];
let byteOffset = 12;
let gltf;
let binaryBuffer;
while (byteOffset < length2) {
const chunkHeader = readHeader(glb, byteOffset, 2);
const chunkLength = chunkHeader[0];
const chunkType = chunkHeader[1];
byteOffset += 8;
const chunkBuffer = glb.subarray(byteOffset, byteOffset + chunkLength);
byteOffset += chunkLength;
if (chunkType === 1313821514) {
const jsonString = getStringFromTypedArray_default(chunkBuffer);
gltf = JSON.parse(jsonString);
addPipelineExtras_default(gltf);
} else if (chunkType === 5130562) {
binaryBuffer = chunkBuffer;
}
}
if (defined_default(gltf) && defined_default(binaryBuffer)) {
const buffers = gltf.buffers;
if (defined_default(buffers) && buffers.length > 0) {
const buffer2 = buffers[0];
buffer2.extras._pipeline.source = binaryBuffer;
}
}
return gltf;
}
var parseGlb_default = parseGlb;
// packages/engine/Source/Scene/GltfPipeline/removePipelineExtras.js
var import_InlineWorkers491 = __toESM(require_InlineWorkers(), 1);
function removePipelineExtras(gltf) {
ForEach_default.shader(gltf, function(shader) {
removeExtras(shader);
});
ForEach_default.buffer(gltf, function(buffer2) {
removeExtras(buffer2);
});
ForEach_default.image(gltf, function(image) {
removeExtras(image);
});
removeExtras(gltf);
return gltf;
}
function removeExtras(object2) {
if (!defined_default(object2.extras)) {
return;
}
if (defined_default(object2.extras._pipeline)) {
delete object2.extras._pipeline;
}
if (Object.keys(object2.extras).length === 0) {
delete object2.extras;
}
}
var removePipelineExtras_default = removePipelineExtras;
// packages/engine/Source/Scene/GltfPipeline/updateVersion.js
var import_InlineWorkers504 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfPipeline/addExtensionsUsed.js
var import_InlineWorkers492 = __toESM(require_InlineWorkers(), 1);
function addExtensionsUsed(gltf, extension) {
let extensionsUsed = gltf.extensionsUsed;
if (!defined_default(extensionsUsed)) {
extensionsUsed = [];
gltf.extensionsUsed = extensionsUsed;
}
addToArray_default(extensionsUsed, extension, true);
}
var addExtensionsUsed_default = addExtensionsUsed;
// packages/engine/Source/Scene/GltfPipeline/findAccessorMinMax.js
var import_InlineWorkers494 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfPipeline/getComponentReader.js
var import_InlineWorkers493 = __toESM(require_InlineWorkers(), 1);
function getComponentReader(componentType) {
switch (componentType) {
case ComponentDatatype_default.BYTE:
return function(dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
for (let i = 0; i < numberOfComponents; ++i) {
result[i] = dataView.getInt8(
byteOffset + i * componentTypeByteLength
);
}
};
case ComponentDatatype_default.UNSIGNED_BYTE:
return function(dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
for (let i = 0; i < numberOfComponents; ++i) {
result[i] = dataView.getUint8(
byteOffset + i * componentTypeByteLength
);
}
};
case ComponentDatatype_default.SHORT:
return function(dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
for (let i = 0; i < numberOfComponents; ++i) {
result[i] = dataView.getInt16(
byteOffset + i * componentTypeByteLength,
true
);
}
};
case ComponentDatatype_default.UNSIGNED_SHORT:
return function(dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
for (let i = 0; i < numberOfComponents; ++i) {
result[i] = dataView.getUint16(
byteOffset + i * componentTypeByteLength,
true
);
}
};
case ComponentDatatype_default.INT:
return function(dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
for (let i = 0; i < numberOfComponents; ++i) {
result[i] = dataView.getInt32(
byteOffset + i * componentTypeByteLength,
true
);
}
};
case ComponentDatatype_default.UNSIGNED_INT:
return function(dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
for (let i = 0; i < numberOfComponents; ++i) {
result[i] = dataView.getUint32(
byteOffset + i * componentTypeByteLength,
true
);
}
};
case ComponentDatatype_default.FLOAT:
return function(dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
for (let i = 0; i < numberOfComponents; ++i) {
result[i] = dataView.getFloat32(
byteOffset + i * componentTypeByteLength,
true
);
}
};
case ComponentDatatype_default.DOUBLE:
return function(dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
for (let i = 0; i < numberOfComponents; ++i) {
result[i] = dataView.getFloat64(
byteOffset + i * componentTypeByteLength,
true
);
}
};
}
}
var getComponentReader_default = getComponentReader;
// packages/engine/Source/Scene/GltfPipeline/findAccessorMinMax.js
function findAccessorMinMax(gltf, accessor) {
const bufferViews = gltf.bufferViews;
const buffers = gltf.buffers;
const bufferViewId = accessor.bufferView;
const numberOfComponents = numberOfComponentsForType_default(accessor.type);
if (!defined_default(accessor.bufferView)) {
return {
min: new Array(numberOfComponents).fill(0),
max: new Array(numberOfComponents).fill(0)
};
}
const min3 = new Array(numberOfComponents).fill(Number.POSITIVE_INFINITY);
const max3 = new Array(numberOfComponents).fill(Number.NEGATIVE_INFINITY);
const bufferView = bufferViews[bufferViewId];
const bufferId = bufferView.buffer;
const buffer2 = buffers[bufferId];
const source = buffer2.extras._pipeline.source;
const count = accessor.count;
const byteStride = getAccessorByteStride_default(gltf, accessor);
let byteOffset = accessor.byteOffset + bufferView.byteOffset + source.byteOffset;
const componentType = accessor.componentType;
const componentTypeByteLength = ComponentDatatype_default.getSizeInBytes(componentType);
const dataView = new DataView(source.buffer);
const components = new Array(numberOfComponents);
const componentReader = getComponentReader_default(componentType);
for (let i = 0; i < count; i++) {
componentReader(
dataView,
byteOffset,
numberOfComponents,
componentTypeByteLength,
components
);
for (let j = 0; j < numberOfComponents; j++) {
const value = components[j];
min3[j] = Math.min(min3[j], value);
max3[j] = Math.max(max3[j], value);
}
byteOffset += byteStride;
}
return {
min: min3,
max: max3
};
}
var findAccessorMinMax_default = findAccessorMinMax;
// packages/engine/Source/Scene/GltfPipeline/moveTechniqueRenderStates.js
var import_InlineWorkers495 = __toESM(require_InlineWorkers(), 1);
var defaultBlendEquation = [WebGLConstants_default.FUNC_ADD, WebGLConstants_default.FUNC_ADD];
var defaultBlendFactors = [
WebGLConstants_default.ONE,
WebGLConstants_default.ZERO,
WebGLConstants_default.ONE,
WebGLConstants_default.ZERO
];
function isStateEnabled(renderStates, state) {
const enabled = renderStates.enable;
if (!defined_default(enabled)) {
return false;
}
return enabled.indexOf(state) > -1;
}
var supportedBlendFactors = [
WebGLConstants_default.ZERO,
WebGLConstants_default.ONE,
WebGLConstants_default.SRC_COLOR,
WebGLConstants_default.ONE_MINUS_SRC_COLOR,
WebGLConstants_default.SRC_ALPHA,
WebGLConstants_default.ONE_MINUS_SRC_ALPHA,
WebGLConstants_default.DST_ALPHA,
WebGLConstants_default.ONE_MINUS_DST_ALPHA,
WebGLConstants_default.DST_COLOR,
WebGLConstants_default.ONE_MINUS_DST_COLOR
];
function getSupportedBlendFactors(value, defaultValue2) {
if (!defined_default(value)) {
return defaultValue2;
}
for (let i = 0; i < 4; i++) {
if (supportedBlendFactors.indexOf(value[i]) === -1) {
return defaultValue2;
}
}
return value;
}
function moveTechniqueRenderStates(gltf) {
const blendingForTechnique = {};
const materialPropertiesForTechnique = {};
const techniquesLegacy = gltf.techniques;
if (!defined_default(techniquesLegacy)) {
return gltf;
}
ForEach_default.technique(gltf, function(techniqueLegacy, techniqueIndex) {
const renderStates = techniqueLegacy.states;
if (defined_default(renderStates)) {
const materialProperties = materialPropertiesForTechnique[techniqueIndex] = {};
if (isStateEnabled(renderStates, WebGLConstants_default.BLEND)) {
materialProperties.alphaMode = "BLEND";
const blendFunctions = renderStates.functions;
if (defined_default(blendFunctions) && (defined_default(blendFunctions.blendEquationSeparate) || defined_default(blendFunctions.blendFuncSeparate))) {
blendingForTechnique[techniqueIndex] = {
blendEquation: blendFunctions.blendEquationSeparate ?? defaultBlendEquation,
blendFactors: getSupportedBlendFactors(
blendFunctions.blendFuncSeparate,
defaultBlendFactors
)
};
}
}
if (!isStateEnabled(renderStates, WebGLConstants_default.CULL_FACE)) {
materialProperties.doubleSided = true;
}
delete techniqueLegacy.states;
}
});
if (Object.keys(blendingForTechnique).length > 0) {
if (!defined_default(gltf.extensions)) {
gltf.extensions = {};
}
addExtensionsUsed_default(gltf, "KHR_blend");
}
ForEach_default.material(gltf, function(material) {
if (defined_default(material.technique)) {
const materialProperties = materialPropertiesForTechnique[material.technique];
ForEach_default.objectLegacy(materialProperties, function(value, property) {
material[property] = value;
});
const blending = blendingForTechnique[material.technique];
if (defined_default(blending)) {
if (!defined_default(material.extensions)) {
material.extensions = {};
}
material.extensions.KHR_blend = blending;
}
}
});
return gltf;
}
var moveTechniqueRenderStates_default = moveTechniqueRenderStates;
// packages/engine/Source/Scene/GltfPipeline/moveTechniquesToExtension.js
var import_InlineWorkers497 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfPipeline/addExtensionsRequired.js
var import_InlineWorkers496 = __toESM(require_InlineWorkers(), 1);
function addExtensionsRequired(gltf, extension) {
let extensionsRequired = gltf.extensionsRequired;
if (!defined_default(extensionsRequired)) {
extensionsRequired = [];
gltf.extensionsRequired = extensionsRequired;
}
addToArray_default(extensionsRequired, extension, true);
addExtensionsUsed_default(gltf, extension);
}
var addExtensionsRequired_default = addExtensionsRequired;
// packages/engine/Source/Scene/GltfPipeline/moveTechniquesToExtension.js
function moveTechniquesToExtension(gltf) {
const techniquesLegacy = gltf.techniques;
const mappedUniforms = {};
const updatedTechniqueIndices = {};
const seenPrograms = {};
if (defined_default(techniquesLegacy)) {
const extension = {
programs: [],
shaders: [],
techniques: []
};
const glExtensions = gltf.glExtensionsUsed;
delete gltf.glExtensionsUsed;
ForEach_default.technique(gltf, function(techniqueLegacy, techniqueId) {
const technique = {
name: techniqueLegacy.name,
program: void 0,
attributes: {},
uniforms: {}
};
let parameterLegacy;
ForEach_default.techniqueAttribute(
techniqueLegacy,
function(parameterName, attributeName) {
parameterLegacy = techniqueLegacy.parameters[parameterName];
technique.attributes[attributeName] = {
semantic: parameterLegacy.semantic
};
}
);
ForEach_default.techniqueUniform(
techniqueLegacy,
function(parameterName, uniformName) {
parameterLegacy = techniqueLegacy.parameters[parameterName];
technique.uniforms[uniformName] = {
count: parameterLegacy.count,
node: parameterLegacy.node,
type: parameterLegacy.type,
semantic: parameterLegacy.semantic,
value: parameterLegacy.value
};
if (!defined_default(mappedUniforms[techniqueId])) {
mappedUniforms[techniqueId] = {};
}
mappedUniforms[techniqueId][parameterName] = uniformName;
}
);
if (!defined_default(seenPrograms[techniqueLegacy.program])) {
const programLegacy = gltf.programs[techniqueLegacy.program];
const program = {
name: programLegacy.name,
fragmentShader: void 0,
vertexShader: void 0,
glExtensions
};
const fs = gltf.shaders[programLegacy.fragmentShader];
program.fragmentShader = addToArray_default(extension.shaders, fs, true);
const vs = gltf.shaders[programLegacy.vertexShader];
program.vertexShader = addToArray_default(extension.shaders, vs, true);
technique.program = addToArray_default(extension.programs, program);
seenPrograms[techniqueLegacy.program] = technique.program;
} else {
technique.program = seenPrograms[techniqueLegacy.program];
}
updatedTechniqueIndices[techniqueId] = addToArray_default(
extension.techniques,
technique
);
});
if (extension.techniques.length > 0) {
if (!defined_default(gltf.extensions)) {
gltf.extensions = {};
}
gltf.extensions.KHR_techniques_webgl = extension;
addExtensionsUsed_default(gltf, "KHR_techniques_webgl");
addExtensionsRequired_default(gltf, "KHR_techniques_webgl");
}
}
ForEach_default.material(gltf, function(material) {
if (defined_default(material.technique)) {
const materialExtension = {
technique: updatedTechniqueIndices[material.technique]
};
ForEach_default.objectLegacy(material.values, function(value, parameterName) {
if (!defined_default(materialExtension.values)) {
materialExtension.values = {};
}
const uniformName = mappedUniforms[material.technique][parameterName];
if (defined_default(uniformName)) {
materialExtension.values[uniformName] = value;
}
});
if (!defined_default(material.extensions)) {
material.extensions = {};
}
material.extensions.KHR_techniques_webgl = materialExtension;
}
delete material.technique;
delete material.values;
});
delete gltf.techniques;
delete gltf.programs;
delete gltf.shaders;
return gltf;
}
var moveTechniquesToExtension_default = moveTechniquesToExtension;
// packages/engine/Source/Scene/GltfPipeline/removeUnusedElements.js
var import_InlineWorkers499 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfPipeline/forEachTextureInMaterial.js
var import_InlineWorkers498 = __toESM(require_InlineWorkers(), 1);
function forEachTextureInMaterial(material, handler) {
Check_default.typeOf.object("material", material);
Check_default.defined("handler", handler);
const pbrMetallicRoughness = material.pbrMetallicRoughness;
if (defined_default(pbrMetallicRoughness)) {
if (defined_default(pbrMetallicRoughness.baseColorTexture)) {
const textureInfo = pbrMetallicRoughness.baseColorTexture;
const value2 = handler(textureInfo.index, textureInfo);
if (defined_default(value2)) {
return value2;
}
}
if (defined_default(pbrMetallicRoughness.metallicRoughnessTexture)) {
const textureInfo = pbrMetallicRoughness.metallicRoughnessTexture;
const value2 = handler(textureInfo.index, textureInfo);
if (defined_default(value2)) {
return value2;
}
}
}
const { extensions } = material;
if (defined_default(extensions)) {
const pbrSpecularGlossiness = extensions.KHR_materials_pbrSpecularGlossiness;
if (defined_default(pbrSpecularGlossiness)) {
if (defined_default(pbrSpecularGlossiness.diffuseTexture)) {
const textureInfo = pbrSpecularGlossiness.diffuseTexture;
const value2 = handler(textureInfo.index, textureInfo);
if (defined_default(value2)) {
return value2;
}
}
if (defined_default(pbrSpecularGlossiness.specularGlossinessTexture)) {
const textureInfo = pbrSpecularGlossiness.specularGlossinessTexture;
const value2 = handler(textureInfo.index, textureInfo);
if (defined_default(value2)) {
return value2;
}
}
}
const specular = extensions.KHR_materials_specular;
if (defined_default(specular)) {
const { specularTexture, specularColorTexture } = specular;
if (defined_default(specularTexture)) {
const value2 = handler(specularTexture.index, specularTexture);
if (defined_default(value2)) {
return value2;
}
}
if (defined_default(specularColorTexture)) {
const value2 = handler(specularColorTexture.index, specularColorTexture);
if (defined_default(value2)) {
return value2;
}
}
}
const materialsCommon = extensions.KHR_materials_common;
if (defined_default(materialsCommon) && defined_default(materialsCommon.values)) {
const { diffuse, ambient, emission, specular: specular2 } = materialsCommon.values;
if (defined_default(diffuse) && defined_default(diffuse.index)) {
const value2 = handler(diffuse.index, diffuse);
if (defined_default(value2)) {
return value2;
}
}
if (defined_default(ambient) && defined_default(ambient.index)) {
const value2 = handler(ambient.index, ambient);
if (defined_default(value2)) {
return value2;
}
}
if (defined_default(emission) && defined_default(emission.index)) {
const value2 = handler(emission.index, emission);
if (defined_default(value2)) {
return value2;
}
}
if (defined_default(specular2) && defined_default(specular2.index)) {
const value2 = handler(specular2.index, specular2);
if (defined_default(value2)) {
return value2;
}
}
}
}
const value = ForEach_default.materialValue(material, function(materialValue) {
if (defined_default(materialValue.index)) {
const value2 = handler(materialValue.index, materialValue);
if (defined_default(value2)) {
return value2;
}
}
});
if (defined_default(value)) {
return value;
}
if (defined_default(material.emissiveTexture)) {
const textureInfo = material.emissiveTexture;
const value2 = handler(textureInfo.index, textureInfo);
if (defined_default(value2)) {
return value2;
}
}
if (defined_default(material.normalTexture)) {
const textureInfo = material.normalTexture;
const value2 = handler(textureInfo.index, textureInfo);
if (defined_default(value2)) {
return value2;
}
}
if (defined_default(material.occlusionTexture)) {
const textureInfo = material.occlusionTexture;
const value2 = handler(textureInfo.index, textureInfo);
if (defined_default(value2)) {
return value2;
}
}
}
var forEachTextureInMaterial_default = forEachTextureInMaterial;
// packages/engine/Source/Scene/GltfPipeline/removeUnusedElements.js
var allElementTypes = [
"mesh",
"node",
"material",
"accessor",
"bufferView",
"buffer",
"texture",
"sampler",
"image"
];
function removeUnusedElements(gltf, elementTypes) {
elementTypes = elementTypes ?? allElementTypes;
allElementTypes.forEach(function(type) {
if (elementTypes.indexOf(type) > -1) {
removeUnusedElementsByType(gltf, type);
}
});
return gltf;
}
var TypeToGltfElementName = {
accessor: "accessors",
buffer: "buffers",
bufferView: "bufferViews",
image: "images",
node: "nodes",
material: "materials",
mesh: "meshes",
sampler: "samplers",
texture: "textures"
};
function removeUnusedElementsByType(gltf, type) {
const name = TypeToGltfElementName[type];
const arrayOfObjects = gltf[name];
if (defined_default(arrayOfObjects)) {
let removed = 0;
const usedIds = getListOfElementsIdsInUse[type](gltf);
const length2 = arrayOfObjects.length;
for (let i = 0; i < length2; ++i) {
if (!usedIds[i]) {
Remove[type](gltf, i - removed);
removed++;
}
}
}
}
function Remove() {
}
Remove.accessor = function(gltf, accessorId) {
const accessors = gltf.accessors;
accessors.splice(accessorId, 1);
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
ForEach_default.meshPrimitiveAttribute(
primitive,
function(attributeAccessorId, semantic) {
if (attributeAccessorId > accessorId) {
primitive.attributes[semantic]--;
}
}
);
ForEach_default.meshPrimitiveTarget(primitive, function(target) {
ForEach_default.meshPrimitiveTargetAttribute(
target,
function(attributeAccessorId, semantic) {
if (attributeAccessorId > accessorId) {
target[semantic]--;
}
}
);
});
const indices = primitive.indices;
if (defined_default(indices) && indices > accessorId) {
primitive.indices--;
}
const ext = primitive.extensions;
if (defined_default(ext) && defined_default(ext.CESIUM_primitive_outline) && ext.CESIUM_primitive_outline.indices > accessorId) {
--ext.CESIUM_primitive_outline.indices;
}
});
});
ForEach_default.skin(gltf, function(skin) {
if (defined_default(skin.inverseBindMatrices) && skin.inverseBindMatrices > accessorId) {
skin.inverseBindMatrices--;
}
});
ForEach_default.animation(gltf, function(animation) {
ForEach_default.animationSampler(animation, function(sampler) {
if (defined_default(sampler.input) && sampler.input > accessorId) {
sampler.input--;
}
if (defined_default(sampler.output) && sampler.output > accessorId) {
sampler.output--;
}
});
});
};
Remove.buffer = function(gltf, bufferId) {
const buffers = gltf.buffers;
buffers.splice(bufferId, 1);
ForEach_default.bufferView(gltf, function(bufferView) {
if (defined_default(bufferView.buffer) && bufferView.buffer > bufferId) {
bufferView.buffer--;
}
if (defined_default(bufferView.extensions) && defined_default(bufferView.extensions.EXT_meshopt_compression)) {
bufferView.extensions.EXT_meshopt_compression.buffer--;
}
});
};
Remove.bufferView = function(gltf, bufferViewId) {
const bufferViews = gltf.bufferViews;
bufferViews.splice(bufferViewId, 1);
ForEach_default.accessor(gltf, function(accessor) {
if (defined_default(accessor.bufferView) && accessor.bufferView > bufferViewId) {
accessor.bufferView--;
}
});
ForEach_default.shader(gltf, function(shader) {
if (defined_default(shader.bufferView) && shader.bufferView > bufferViewId) {
shader.bufferView--;
}
});
ForEach_default.image(gltf, function(image) {
if (defined_default(image.bufferView) && image.bufferView > bufferViewId) {
image.bufferView--;
}
});
if (usesExtension_default(gltf, "KHR_draco_mesh_compression")) {
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
if (defined_default(primitive.extensions) && defined_default(primitive.extensions.KHR_draco_mesh_compression)) {
if (primitive.extensions.KHR_draco_mesh_compression.bufferView > bufferViewId) {
primitive.extensions.KHR_draco_mesh_compression.bufferView--;
}
}
});
});
}
if (usesExtension_default(gltf, "EXT_feature_metadata")) {
const extension = gltf.extensions.EXT_feature_metadata;
const featureTables = extension.featureTables;
for (const featureTableId in featureTables) {
if (featureTables.hasOwnProperty(featureTableId)) {
const featureTable = featureTables[featureTableId];
const properties = featureTable.properties;
if (defined_default(properties)) {
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId)) {
const property = properties[propertyId];
if (defined_default(property.bufferView) && property.bufferView > bufferViewId) {
property.bufferView--;
}
if (defined_default(property.arrayOffsetBufferView) && property.arrayOffsetBufferView > bufferViewId) {
property.arrayOffsetBufferView--;
}
if (defined_default(property.stringOffsetBufferView) && property.stringOffsetBufferView > bufferViewId) {
property.stringOffsetBufferView--;
}
}
}
}
}
}
}
if (usesExtension_default(gltf, "EXT_structural_metadata")) {
const extension = gltf.extensions.EXT_structural_metadata;
const propertyTables = extension.propertyTables;
if (defined_default(propertyTables)) {
const propertyTablesLength = propertyTables.length;
for (let i = 0; i < propertyTablesLength; ++i) {
const propertyTable = propertyTables[i];
const properties = propertyTable.properties;
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId)) {
const property = properties[propertyId];
if (defined_default(property.values) && property.values > bufferViewId) {
property.values--;
}
if (defined_default(property.arrayOffsets) && property.arrayOffsets > bufferViewId) {
property.arrayOffsets--;
}
if (defined_default(property.stringOffsets) && property.stringOffsets > bufferViewId) {
property.stringOffsets--;
}
}
}
}
}
}
};
Remove.image = function(gltf, imageId) {
const images = gltf.images;
images.splice(imageId, 1);
ForEach_default.texture(gltf, function(texture) {
if (defined_default(texture.source)) {
if (texture.source > imageId) {
--texture.source;
}
}
const ext = texture.extensions;
if (defined_default(ext) && defined_default(ext.EXT_texture_webp) && ext.EXT_texture_webp.source > imageId) {
--texture.extensions.EXT_texture_webp.source;
} else if (defined_default(ext) && defined_default(ext.KHR_texture_basisu) && ext.KHR_texture_basisu.source > imageId) {
--texture.extensions.KHR_texture_basisu.source;
}
});
};
Remove.mesh = function(gltf, meshId) {
const meshes = gltf.meshes;
meshes.splice(meshId, 1);
ForEach_default.node(gltf, function(node) {
if (defined_default(node.mesh)) {
if (node.mesh > meshId) {
node.mesh--;
} else if (node.mesh === meshId) {
delete node.mesh;
}
}
});
};
Remove.node = function(gltf, nodeId) {
const nodes = gltf.nodes;
nodes.splice(nodeId, 1);
ForEach_default.skin(gltf, function(skin) {
if (defined_default(skin.skeleton) && skin.skeleton > nodeId) {
skin.skeleton--;
}
skin.joints = skin.joints.map(function(x) {
return x > nodeId ? x - 1 : x;
});
});
ForEach_default.animation(gltf, function(animation) {
ForEach_default.animationChannel(animation, function(channel) {
if (defined_default(channel.target) && defined_default(channel.target.node) && channel.target.node > nodeId) {
channel.target.node--;
}
});
});
ForEach_default.technique(gltf, function(technique) {
ForEach_default.techniqueUniform(technique, function(uniform) {
if (defined_default(uniform.node) && uniform.node > nodeId) {
uniform.node--;
}
});
});
ForEach_default.node(gltf, function(node) {
if (!defined_default(node.children)) {
return;
}
node.children = node.children.filter(function(x) {
return x !== nodeId;
}).map(function(x) {
return x > nodeId ? x - 1 : x;
});
});
ForEach_default.scene(gltf, function(scene) {
scene.nodes = scene.nodes.filter(function(x) {
return x !== nodeId;
}).map(function(x) {
return x > nodeId ? x - 1 : x;
});
});
};
Remove.material = function(gltf, materialId) {
const materials = gltf.materials;
materials.splice(materialId, 1);
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
if (defined_default(primitive.material) && primitive.material > materialId) {
primitive.material--;
}
});
});
};
Remove.sampler = function(gltf, samplerId) {
const samplers = gltf.samplers;
samplers.splice(samplerId, 1);
ForEach_default.texture(gltf, function(texture) {
if (defined_default(texture.sampler)) {
if (texture.sampler > samplerId) {
--texture.sampler;
}
}
});
};
Remove.texture = function(gltf, textureId) {
const textures = gltf.textures;
textures.splice(textureId, 1);
ForEach_default.material(gltf, function(material) {
forEachTextureInMaterial_default(material, function(textureIndex, textureInfo) {
if (textureInfo.index > textureId) {
--textureInfo.index;
}
});
});
if (usesExtension_default(gltf, "EXT_feature_metadata")) {
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
const extensions = primitive.extensions;
if (defined_default(extensions) && defined_default(extensions.EXT_feature_metadata)) {
const extension2 = extensions.EXT_feature_metadata;
const featureIdTextures = extension2.featureIdTextures;
if (defined_default(featureIdTextures)) {
const featureIdTexturesLength = featureIdTextures.length;
for (let i = 0; i < featureIdTexturesLength; ++i) {
const featureIdTexture = featureIdTextures[i];
const textureInfo = featureIdTexture.featureIds.texture;
if (textureInfo.index > textureId) {
--textureInfo.index;
}
}
}
}
});
});
const extension = gltf.extensions.EXT_feature_metadata;
const featureTextures = extension.featureTextures;
for (const featureTextureId in featureTextures) {
if (featureTextures.hasOwnProperty(featureTextureId)) {
const featureTexture = featureTextures[featureTextureId];
const properties = featureTexture.properties;
if (defined_default(properties)) {
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId)) {
const property = properties[propertyId];
const textureInfo = property.texture;
if (textureInfo.index > textureId) {
--textureInfo.index;
}
}
}
}
}
}
}
if (usesExtension_default(gltf, "EXT_mesh_features")) {
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
const extensions = primitive.extensions;
if (defined_default(extensions) && defined_default(extensions.EXT_mesh_features)) {
const extension = extensions.EXT_mesh_features;
const featureIds = extension.featureIds;
if (defined_default(featureIds)) {
const featureIdsLength = featureIds.length;
for (let i = 0; i < featureIdsLength; ++i) {
const featureId = featureIds[i];
if (defined_default(featureId.texture)) {
if (featureId.texture.index > textureId) {
--featureId.texture.index;
}
}
}
}
}
});
});
}
if (usesExtension_default(gltf, "EXT_structural_metadata")) {
const extension = gltf.extensions.EXT_structural_metadata;
const propertyTextures = extension.propertyTextures;
if (defined_default(propertyTextures)) {
const propertyTexturesLength = propertyTextures.length;
for (let i = 0; i < propertyTexturesLength; ++i) {
const propertyTexture = propertyTextures[i];
const properties = propertyTexture.properties;
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId)) {
const property = properties[propertyId];
if (property.index > textureId) {
--property.index;
}
}
}
}
}
}
};
function getListOfElementsIdsInUse() {
}
getListOfElementsIdsInUse.accessor = function(gltf) {
const usedAccessorIds = {};
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
ForEach_default.meshPrimitiveAttribute(primitive, function(accessorId) {
usedAccessorIds[accessorId] = true;
});
ForEach_default.meshPrimitiveTarget(primitive, function(target) {
ForEach_default.meshPrimitiveTargetAttribute(target, function(accessorId) {
usedAccessorIds[accessorId] = true;
});
});
const indices = primitive.indices;
if (defined_default(indices)) {
usedAccessorIds[indices] = true;
}
});
});
ForEach_default.skin(gltf, function(skin) {
if (defined_default(skin.inverseBindMatrices)) {
usedAccessorIds[skin.inverseBindMatrices] = true;
}
});
ForEach_default.animation(gltf, function(animation) {
ForEach_default.animationSampler(animation, function(sampler) {
if (defined_default(sampler.input)) {
usedAccessorIds[sampler.input] = true;
}
if (defined_default(sampler.output)) {
usedAccessorIds[sampler.output] = true;
}
});
});
if (usesExtension_default(gltf, "EXT_mesh_gpu_instancing")) {
ForEach_default.node(gltf, function(node) {
if (defined_default(node.extensions) && defined_default(node.extensions.EXT_mesh_gpu_instancing)) {
Object.keys(node.extensions.EXT_mesh_gpu_instancing.attributes).forEach(
function(key) {
const attributeAccessorId = node.extensions.EXT_mesh_gpu_instancing.attributes[key];
usedAccessorIds[attributeAccessorId] = true;
}
);
}
});
}
if (usesExtension_default(gltf, "CESIUM_primitive_outline")) {
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
const extensions = primitive.extensions;
if (defined_default(extensions) && defined_default(extensions.CESIUM_primitive_outline)) {
const extension = extensions.CESIUM_primitive_outline;
const indicesAccessorId = extension.indices;
if (defined_default(indicesAccessorId)) {
usedAccessorIds[indicesAccessorId] = true;
}
}
});
});
}
return usedAccessorIds;
};
getListOfElementsIdsInUse.buffer = function(gltf) {
const usedBufferIds = {};
ForEach_default.bufferView(gltf, function(bufferView) {
if (defined_default(bufferView.buffer)) {
usedBufferIds[bufferView.buffer] = true;
}
if (defined_default(bufferView.extensions) && defined_default(bufferView.extensions.EXT_meshopt_compression)) {
usedBufferIds[bufferView.extensions.EXT_meshopt_compression.buffer] = true;
}
});
return usedBufferIds;
};
getListOfElementsIdsInUse.bufferView = function(gltf) {
const usedBufferViewIds = {};
ForEach_default.accessor(gltf, function(accessor) {
if (defined_default(accessor.bufferView)) {
usedBufferViewIds[accessor.bufferView] = true;
}
});
ForEach_default.shader(gltf, function(shader) {
if (defined_default(shader.bufferView)) {
usedBufferViewIds[shader.bufferView] = true;
}
});
ForEach_default.image(gltf, function(image) {
if (defined_default(image.bufferView)) {
usedBufferViewIds[image.bufferView] = true;
}
});
if (usesExtension_default(gltf, "KHR_draco_mesh_compression")) {
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
if (defined_default(primitive.extensions) && defined_default(primitive.extensions.KHR_draco_mesh_compression)) {
usedBufferViewIds[primitive.extensions.KHR_draco_mesh_compression.bufferView] = true;
}
});
});
}
if (usesExtension_default(gltf, "EXT_feature_metadata")) {
const extension = gltf.extensions.EXT_feature_metadata;
const featureTables = extension.featureTables;
for (const featureTableId in featureTables) {
if (featureTables.hasOwnProperty(featureTableId)) {
const featureTable = featureTables[featureTableId];
const properties = featureTable.properties;
if (defined_default(properties)) {
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId)) {
const property = properties[propertyId];
if (defined_default(property.bufferView)) {
usedBufferViewIds[property.bufferView] = true;
}
if (defined_default(property.arrayOffsetBufferView)) {
usedBufferViewIds[property.arrayOffsetBufferView] = true;
}
if (defined_default(property.stringOffsetBufferView)) {
usedBufferViewIds[property.stringOffsetBufferView] = true;
}
}
}
}
}
}
}
if (usesExtension_default(gltf, "EXT_structural_metadata")) {
const extension = gltf.extensions.EXT_structural_metadata;
const propertyTables = extension.propertyTables;
if (defined_default(propertyTables)) {
const propertyTablesLength = propertyTables.length;
for (let i = 0; i < propertyTablesLength; ++i) {
const propertyTable = propertyTables[i];
const properties = propertyTable.properties;
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId)) {
const property = properties[propertyId];
if (defined_default(property.values)) {
usedBufferViewIds[property.values] = true;
}
if (defined_default(property.arrayOffsets)) {
usedBufferViewIds[property.arrayOffsets] = true;
}
if (defined_default(property.stringOffsets)) {
usedBufferViewIds[property.stringOffsets] = true;
}
}
}
}
}
}
return usedBufferViewIds;
};
getListOfElementsIdsInUse.image = function(gltf) {
const usedImageIds = {};
ForEach_default.texture(gltf, function(texture) {
if (defined_default(texture.source)) {
usedImageIds[texture.source] = true;
}
if (defined_default(texture.extensions) && defined_default(texture.extensions.EXT_texture_webp)) {
usedImageIds[texture.extensions.EXT_texture_webp.source] = true;
} else if (defined_default(texture.extensions) && defined_default(texture.extensions.KHR_texture_basisu)) {
usedImageIds[texture.extensions.KHR_texture_basisu.source] = true;
}
});
return usedImageIds;
};
getListOfElementsIdsInUse.mesh = function(gltf) {
const usedMeshIds = {};
ForEach_default.node(gltf, function(node) {
if (defined_default(node.mesh && defined_default(gltf.meshes))) {
const mesh = gltf.meshes[node.mesh];
if (defined_default(mesh) && defined_default(mesh.primitives) && mesh.primitives.length > 0) {
usedMeshIds[node.mesh] = true;
}
}
});
return usedMeshIds;
};
function nodeIsEmpty(gltf, nodeId, usedNodeIds) {
const node = gltf.nodes[nodeId];
if (defined_default(node.mesh) || defined_default(node.camera) || defined_default(node.skin) || defined_default(node.weights) || defined_default(node.extras) || defined_default(node.extensions) && Object.keys(node.extensions).length !== 0 || defined_default(usedNodeIds[nodeId])) {
return false;
}
return !defined_default(node.children) || node.children.filter(function(n) {
return !nodeIsEmpty(gltf, n, usedNodeIds);
}).length === 0;
}
getListOfElementsIdsInUse.node = function(gltf) {
const usedNodeIds = {};
ForEach_default.skin(gltf, function(skin) {
if (defined_default(skin.skeleton)) {
usedNodeIds[skin.skeleton] = true;
}
ForEach_default.skinJoint(skin, function(joint) {
usedNodeIds[joint] = true;
});
});
ForEach_default.animation(gltf, function(animation) {
ForEach_default.animationChannel(animation, function(channel) {
if (defined_default(channel.target) && defined_default(channel.target.node)) {
usedNodeIds[channel.target.node] = true;
}
});
});
ForEach_default.technique(gltf, function(technique) {
ForEach_default.techniqueUniform(technique, function(uniform) {
if (defined_default(uniform.node)) {
usedNodeIds[uniform.node] = true;
}
});
});
ForEach_default.node(gltf, function(node, nodeId) {
if (!nodeIsEmpty(gltf, nodeId, usedNodeIds)) {
usedNodeIds[nodeId] = true;
}
});
return usedNodeIds;
};
getListOfElementsIdsInUse.material = function(gltf) {
const usedMaterialIds = {};
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
if (defined_default(primitive.material)) {
usedMaterialIds[primitive.material] = true;
}
});
});
return usedMaterialIds;
};
getListOfElementsIdsInUse.texture = function(gltf) {
const usedTextureIds = {};
ForEach_default.material(gltf, function(material) {
forEachTextureInMaterial_default(material, function(textureId) {
usedTextureIds[textureId] = true;
});
});
if (usesExtension_default(gltf, "EXT_feature_metadata")) {
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
const extensions = primitive.extensions;
if (defined_default(extensions) && defined_default(extensions.EXT_feature_metadata)) {
const extension2 = extensions.EXT_feature_metadata;
const featureIdTextures = extension2.featureIdTextures;
if (defined_default(featureIdTextures)) {
const featureIdTexturesLength = featureIdTextures.length;
for (let i = 0; i < featureIdTexturesLength; ++i) {
const featureIdTexture = featureIdTextures[i];
const textureInfo = featureIdTexture.featureIds.texture;
usedTextureIds[textureInfo.index] = true;
}
}
}
});
});
const extension = gltf.extensions.EXT_feature_metadata;
const featureTextures = extension.featureTextures;
for (const featureTextureId in featureTextures) {
if (featureTextures.hasOwnProperty(featureTextureId)) {
const featureTexture = featureTextures[featureTextureId];
const properties = featureTexture.properties;
if (defined_default(properties)) {
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId)) {
const property = properties[propertyId];
const textureInfo = property.texture;
usedTextureIds[textureInfo.index] = true;
}
}
}
}
}
}
if (usesExtension_default(gltf, "EXT_mesh_features")) {
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
const extensions = primitive.extensions;
if (defined_default(extensions) && defined_default(extensions.EXT_mesh_features)) {
const extension = extensions.EXT_mesh_features;
const featureIds = extension.featureIds;
if (defined_default(featureIds)) {
const featureIdsLength = featureIds.length;
for (let i = 0; i < featureIdsLength; ++i) {
const featureId = featureIds[i];
if (defined_default(featureId.texture)) {
usedTextureIds[featureId.texture.index] = true;
}
}
}
}
});
});
}
if (usesExtension_default(gltf, "EXT_structural_metadata")) {
const extension = gltf.extensions.EXT_structural_metadata;
const propertyTextures = extension.propertyTextures;
if (defined_default(propertyTextures)) {
const propertyTexturesLength = propertyTextures.length;
for (let i = 0; i < propertyTexturesLength; ++i) {
const propertyTexture = propertyTextures[i];
const properties = propertyTexture.properties;
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId)) {
const property = properties[propertyId];
usedTextureIds[property.index] = true;
}
}
}
}
}
return usedTextureIds;
};
getListOfElementsIdsInUse.sampler = function(gltf) {
const usedSamplerIds = {};
ForEach_default.texture(gltf, function(texture) {
if (defined_default(texture.sampler)) {
usedSamplerIds[texture.sampler] = true;
}
});
return usedSamplerIds;
};
var removeUnusedElements_default = removeUnusedElements;
// packages/engine/Source/Scene/GltfPipeline/updateAccessorComponentTypes.js
var import_InlineWorkers502 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfPipeline/addBuffer.js
var import_InlineWorkers500 = __toESM(require_InlineWorkers(), 1);
function addBuffer(gltf, buffer2) {
const newBuffer = {
byteLength: buffer2.length,
extras: {
_pipeline: {
source: buffer2
}
}
};
const bufferId = addToArray_default(gltf.buffers, newBuffer);
const bufferView = {
buffer: bufferId,
byteOffset: 0,
byteLength: buffer2.length
};
return addToArray_default(gltf.bufferViews, bufferView);
}
var addBuffer_default = addBuffer;
// packages/engine/Source/Scene/GltfPipeline/readAccessorPacked.js
var import_InlineWorkers501 = __toESM(require_InlineWorkers(), 1);
function readAccessorPacked(gltf, accessor) {
const byteStride = getAccessorByteStride_default(gltf, accessor);
const componentTypeByteLength = ComponentDatatype_default.getSizeInBytes(
accessor.componentType
);
const numberOfComponents = numberOfComponentsForType_default(accessor.type);
const count = accessor.count;
const values = new Array(numberOfComponents * count);
if (!defined_default(accessor.bufferView)) {
return values.fill(0);
}
const bufferView = gltf.bufferViews[accessor.bufferView];
const source = gltf.buffers[bufferView.buffer].extras._pipeline.source;
let byteOffset = accessor.byteOffset + bufferView.byteOffset + source.byteOffset;
const dataView = new DataView(source.buffer);
const components = new Array(numberOfComponents);
const componentReader = getComponentReader_default(accessor.componentType);
for (let i = 0; i < count; ++i) {
componentReader(
dataView,
byteOffset,
numberOfComponents,
componentTypeByteLength,
components
);
for (let j = 0; j < numberOfComponents; ++j) {
values[i * numberOfComponents + j] = components[j];
}
byteOffset += byteStride;
}
return values;
}
var readAccessorPacked_default = readAccessorPacked;
// packages/engine/Source/Scene/GltfPipeline/updateAccessorComponentTypes.js
function updateAccessorComponentTypes(gltf) {
let componentType;
ForEach_default.accessorWithSemantic(gltf, "JOINTS_0", function(accessorId) {
const accessor = gltf.accessors[accessorId];
componentType = accessor.componentType;
if (componentType === WebGLConstants_default.BYTE) {
convertType(gltf, accessor, ComponentDatatype_default.UNSIGNED_BYTE);
} else if (componentType !== WebGLConstants_default.UNSIGNED_BYTE && componentType !== WebGLConstants_default.UNSIGNED_SHORT) {
convertType(gltf, accessor, ComponentDatatype_default.UNSIGNED_SHORT);
}
});
ForEach_default.accessorWithSemantic(gltf, "WEIGHTS_0", function(accessorId) {
const accessor = gltf.accessors[accessorId];
componentType = accessor.componentType;
if (componentType === WebGLConstants_default.BYTE) {
convertType(gltf, accessor, ComponentDatatype_default.UNSIGNED_BYTE);
} else if (componentType === WebGLConstants_default.SHORT) {
convertType(gltf, accessor, ComponentDatatype_default.UNSIGNED_SHORT);
}
});
return gltf;
}
function convertType(gltf, accessor, updatedComponentType) {
const typedArray = ComponentDatatype_default.createTypedArray(
updatedComponentType,
readAccessorPacked_default(gltf, accessor)
);
const newBuffer = new Uint8Array(typedArray.buffer);
accessor.bufferView = addBuffer_default(gltf, newBuffer);
accessor.componentType = updatedComponentType;
accessor.byteOffset = 0;
}
var updateAccessorComponentTypes_default = updateAccessorComponentTypes;
// packages/engine/Source/Scene/GltfPipeline/removeExtension.js
var import_InlineWorkers503 = __toESM(require_InlineWorkers(), 1);
function removeExtension(gltf, extension) {
removeExtensionsUsed_default(gltf, extension);
if (extension === "CESIUM_RTC") {
removeCesiumRTC(gltf);
}
return removeExtensionAndTraverse(gltf, extension);
}
function removeCesiumRTC(gltf) {
ForEach_default.technique(gltf, function(technique) {
ForEach_default.techniqueUniform(technique, function(uniform) {
if (uniform.semantic === "CESIUM_RTC_MODELVIEW") {
uniform.semantic = "MODELVIEW";
}
});
});
}
function removeExtensionAndTraverse(object2, extension) {
if (Array.isArray(object2)) {
const length2 = object2.length;
for (let i = 0; i < length2; ++i) {
removeExtensionAndTraverse(object2[i], extension);
}
} else if (object2 !== null && typeof object2 === "object" && object2.constructor === Object) {
const extensions = object2.extensions;
let extensionData;
if (defined_default(extensions)) {
extensionData = extensions[extension];
if (defined_default(extensionData)) {
delete extensions[extension];
if (Object.keys(extensions).length === 0) {
delete object2.extensions;
}
}
}
for (const key in object2) {
if (Object.prototype.hasOwnProperty.call(object2, key)) {
removeExtensionAndTraverse(object2[key], extension);
}
}
return extensionData;
}
}
var removeExtension_default = removeExtension;
// packages/engine/Source/Scene/GltfPipeline/updateVersion.js
var updateFunctions = {
0.8: glTF08to10,
"1.0": glTF10to20,
"2.0": void 0
};
function updateVersion(gltf, options) {
options = options ?? {};
const targetVersion = options.targetVersion;
let version2 = gltf.version;
gltf.asset = gltf.asset ?? {
version: "1.0"
};
gltf.asset.version = gltf.asset.version ?? "1.0";
version2 = (version2 ?? gltf.asset.version).toString();
if (!Object.prototype.hasOwnProperty.call(updateFunctions, version2)) {
if (defined_default(version2)) {
version2 = version2.substring(0, 3);
}
if (!Object.prototype.hasOwnProperty.call(updateFunctions, version2)) {
version2 = "1.0";
}
}
let updateFunction = updateFunctions[version2];
while (defined_default(updateFunction)) {
if (version2 === targetVersion) {
break;
}
updateFunction(gltf, options);
version2 = gltf.asset.version;
updateFunction = updateFunctions[version2];
}
if (!options.keepLegacyExtensions) {
convertTechniquesToPbr(gltf, options);
convertMaterialsCommonToPbr(gltf);
}
return gltf;
}
function updateInstanceTechniques(gltf) {
const materials = gltf.materials;
for (const materialId in materials) {
if (Object.prototype.hasOwnProperty.call(materials, materialId)) {
const material = materials[materialId];
const instanceTechnique = material.instanceTechnique;
if (defined_default(instanceTechnique)) {
material.technique = instanceTechnique.technique;
material.values = instanceTechnique.values;
delete material.instanceTechnique;
}
}
}
}
function setPrimitiveModes(gltf) {
const meshes = gltf.meshes;
for (const meshId in meshes) {
if (Object.prototype.hasOwnProperty.call(meshes, meshId)) {
const mesh = meshes[meshId];
const primitives = mesh.primitives;
if (defined_default(primitives)) {
const primitivesLength = primitives.length;
for (let i = 0; i < primitivesLength; ++i) {
const primitive = primitives[i];
const defaultMode = primitive.primitive ?? WebGLConstants_default.TRIANGLES;
primitive.mode = primitive.mode ?? defaultMode;
delete primitive.primitive;
}
}
}
}
}
function updateNodes(gltf) {
const nodes = gltf.nodes;
const axis = new Cartesian3_default();
const quat = new Quaternion_default();
for (const nodeId in nodes) {
if (Object.prototype.hasOwnProperty.call(nodes, nodeId)) {
const node = nodes[nodeId];
if (defined_default(node.rotation)) {
const rotation = node.rotation;
Cartesian3_default.fromArray(rotation, 0, axis);
Quaternion_default.fromAxisAngle(axis, rotation[3], quat);
node.rotation = [quat.x, quat.y, quat.z, quat.w];
}
const instanceSkin = node.instanceSkin;
if (defined_default(instanceSkin)) {
node.skeletons = instanceSkin.skeletons;
node.skin = instanceSkin.skin;
node.meshes = instanceSkin.meshes;
delete node.instanceSkin;
}
}
}
}
function updateAnimations(gltf) {
const animations = gltf.animations;
const accessors = gltf.accessors;
const bufferViews = gltf.bufferViews;
const buffers = gltf.buffers;
const updatedAccessors = {};
const axis = new Cartesian3_default();
const quat = new Quaternion_default();
for (const animationId in animations) {
if (Object.prototype.hasOwnProperty.call(animations, animationId)) {
const animation = animations[animationId];
const channels = animation.channels;
const parameters = animation.parameters;
const samplers = animation.samplers;
if (defined_default(channels)) {
const channelsLength = channels.length;
for (let i = 0; i < channelsLength; ++i) {
const channel = channels[i];
if (channel.target.path === "rotation") {
const accessorId = parameters[samplers[channel.sampler].output];
if (defined_default(updatedAccessors[accessorId])) {
continue;
}
updatedAccessors[accessorId] = true;
const accessor = accessors[accessorId];
const bufferView = bufferViews[accessor.bufferView];
const buffer2 = buffers[bufferView.buffer];
const source = buffer2.extras._pipeline.source;
const byteOffset = source.byteOffset + bufferView.byteOffset + accessor.byteOffset;
const componentType = accessor.componentType;
const count = accessor.count;
const componentsLength = numberOfComponentsForType_default(accessor.type);
const length2 = accessor.count * componentsLength;
const typedArray = ComponentDatatype_default.createArrayBufferView(
componentType,
source.buffer,
byteOffset,
length2
);
for (let j = 0; j < count; j++) {
const offset = j * componentsLength;
Cartesian3_default.unpack(typedArray, offset, axis);
const angle = typedArray[offset + 3];
Quaternion_default.fromAxisAngle(axis, angle, quat);
Quaternion_default.pack(quat, typedArray, offset);
}
}
}
}
}
}
}
function removeTechniquePasses(gltf) {
const techniques = gltf.techniques;
for (const techniqueId in techniques) {
if (Object.prototype.hasOwnProperty.call(techniques, techniqueId)) {
const technique = techniques[techniqueId];
const passes = technique.passes;
if (defined_default(passes)) {
const passName = technique.pass ?? "defaultPass";
if (Object.prototype.hasOwnProperty.call(passes, passName)) {
const pass = passes[passName];
const instanceProgram = pass.instanceProgram;
technique.attributes = technique.attributes ?? instanceProgram.attributes;
technique.program = technique.program ?? instanceProgram.program;
technique.uniforms = technique.uniforms ?? instanceProgram.uniforms;
technique.states = technique.states ?? pass.states;
}
delete technique.passes;
delete technique.pass;
}
}
}
}
function glTF08to10(gltf) {
if (!defined_default(gltf.asset)) {
gltf.asset = {};
}
const asset = gltf.asset;
asset.version = "1.0";
if (typeof asset.profile === "string") {
const split = asset.profile.split(" ");
asset.profile = {
api: split[0],
version: split[1]
};
} else {
asset.profile = {};
}
if (defined_default(gltf.version)) {
delete gltf.version;
}
updateInstanceTechniques(gltf);
setPrimitiveModes(gltf);
updateNodes(gltf);
updateAnimations(gltf);
removeTechniquePasses(gltf);
if (defined_default(gltf.allExtensions)) {
gltf.extensionsUsed = gltf.allExtensions;
delete gltf.allExtensions;
}
if (defined_default(gltf.lights)) {
const extensions = gltf.extensions ?? {};
gltf.extensions = extensions;
const materialsCommon = extensions.KHR_materials_common ?? {};
extensions.KHR_materials_common = materialsCommon;
materialsCommon.lights = gltf.lights;
delete gltf.lights;
addExtensionsUsed_default(gltf, "KHR_materials_common");
}
}
function removeAnimationSamplersIndirection(gltf) {
const animations = gltf.animations;
for (const animationId in animations) {
if (Object.prototype.hasOwnProperty.call(animations, animationId)) {
const animation = animations[animationId];
const parameters = animation.parameters;
if (defined_default(parameters)) {
const samplers = animation.samplers;
for (const samplerId in samplers) {
if (Object.prototype.hasOwnProperty.call(samplers, samplerId)) {
const sampler = samplers[samplerId];
sampler.input = parameters[sampler.input];
sampler.output = parameters[sampler.output];
}
}
delete animation.parameters;
}
}
}
}
function objectToArray(object2, mapping) {
const array = [];
for (const id in object2) {
if (Object.prototype.hasOwnProperty.call(object2, id)) {
const value = object2[id];
mapping[id] = array.length;
array.push(value);
if (!defined_default(value.name)) {
value.name = id;
}
}
}
return array;
}
function objectsToArrays(gltf) {
let i;
const globalMapping = {
accessors: {},
animations: {},
buffers: {},
bufferViews: {},
cameras: {},
images: {},
materials: {},
meshes: {},
nodes: {},
programs: {},
samplers: {},
scenes: {},
shaders: {},
skins: {},
textures: {},
techniques: {}
};
let jointName;
const jointNameToId = {};
const nodes = gltf.nodes;
for (const id in nodes) {
if (Object.prototype.hasOwnProperty.call(nodes, id)) {
jointName = nodes[id].jointName;
if (defined_default(jointName)) {
jointNameToId[jointName] = id;
}
}
}
for (const topLevelId in gltf) {
if (Object.prototype.hasOwnProperty.call(gltf, topLevelId) && defined_default(globalMapping[topLevelId])) {
const objectMapping = {};
const object2 = gltf[topLevelId];
gltf[topLevelId] = objectToArray(object2, objectMapping);
globalMapping[topLevelId] = objectMapping;
}
}
for (jointName in jointNameToId) {
if (Object.prototype.hasOwnProperty.call(jointNameToId, jointName)) {
jointNameToId[jointName] = globalMapping.nodes[jointNameToId[jointName]];
}
}
if (defined_default(gltf.scene)) {
gltf.scene = globalMapping.scenes[gltf.scene];
}
ForEach_default.bufferView(gltf, function(bufferView) {
if (defined_default(bufferView.buffer)) {
bufferView.buffer = globalMapping.buffers[bufferView.buffer];
}
});
ForEach_default.accessor(gltf, function(accessor) {
if (defined_default(accessor.bufferView)) {
accessor.bufferView = globalMapping.bufferViews[accessor.bufferView];
}
});
ForEach_default.shader(gltf, function(shader) {
const extensions = shader.extensions;
if (defined_default(extensions)) {
const binaryGltf = extensions.KHR_binary_glTF;
if (defined_default(binaryGltf)) {
shader.bufferView = globalMapping.bufferViews[binaryGltf.bufferView];
delete extensions.KHR_binary_glTF;
}
if (Object.keys(extensions).length === 0) {
delete shader.extensions;
}
}
});
ForEach_default.program(gltf, function(program) {
if (defined_default(program.vertexShader)) {
program.vertexShader = globalMapping.shaders[program.vertexShader];
}
if (defined_default(program.fragmentShader)) {
program.fragmentShader = globalMapping.shaders[program.fragmentShader];
}
});
ForEach_default.technique(gltf, function(technique) {
if (defined_default(technique.program)) {
technique.program = globalMapping.programs[technique.program];
}
ForEach_default.techniqueParameter(technique, function(parameter) {
if (defined_default(parameter.node)) {
parameter.node = globalMapping.nodes[parameter.node];
}
const value = parameter.value;
if (typeof value === "string") {
parameter.value = {
index: globalMapping.textures[value]
};
}
});
});
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
if (defined_default(primitive.indices)) {
primitive.indices = globalMapping.accessors[primitive.indices];
}
ForEach_default.meshPrimitiveAttribute(
primitive,
function(accessorId, semantic) {
primitive.attributes[semantic] = globalMapping.accessors[accessorId];
}
);
if (defined_default(primitive.material)) {
primitive.material = globalMapping.materials[primitive.material];
}
});
});
ForEach_default.node(gltf, function(node) {
let children = node.children;
if (defined_default(children)) {
const childrenLength = children.length;
for (i = 0; i < childrenLength; ++i) {
children[i] = globalMapping.nodes[children[i]];
}
}
if (defined_default(node.meshes)) {
const meshes = node.meshes;
const meshesLength = meshes.length;
if (meshesLength > 0) {
node.mesh = globalMapping.meshes[meshes[0]];
for (i = 1; i < meshesLength; ++i) {
const meshNode = {
mesh: globalMapping.meshes[meshes[i]]
};
const meshNodeId = addToArray_default(gltf.nodes, meshNode);
if (!defined_default(children)) {
children = [];
node.children = children;
}
children.push(meshNodeId);
}
}
delete node.meshes;
}
if (defined_default(node.camera)) {
node.camera = globalMapping.cameras[node.camera];
}
if (defined_default(node.skin)) {
node.skin = globalMapping.skins[node.skin];
}
if (defined_default(node.skeletons)) {
const skeletons = node.skeletons;
const skeletonsLength = skeletons.length;
if (skeletonsLength > 0 && defined_default(node.skin)) {
const skin = gltf.skins[node.skin];
skin.skeleton = globalMapping.nodes[skeletons[0]];
}
delete node.skeletons;
}
if (defined_default(node.jointName)) {
delete node.jointName;
}
});
ForEach_default.skin(gltf, function(skin) {
if (defined_default(skin.inverseBindMatrices)) {
skin.inverseBindMatrices = globalMapping.accessors[skin.inverseBindMatrices];
}
const jointNames = skin.jointNames;
if (defined_default(jointNames)) {
const joints = [];
const jointNamesLength = jointNames.length;
for (i = 0; i < jointNamesLength; ++i) {
joints[i] = jointNameToId[jointNames[i]];
}
skin.joints = joints;
delete skin.jointNames;
}
});
ForEach_default.scene(gltf, function(scene) {
const sceneNodes = scene.nodes;
if (defined_default(sceneNodes)) {
const sceneNodesLength = sceneNodes.length;
for (i = 0; i < sceneNodesLength; ++i) {
sceneNodes[i] = globalMapping.nodes[sceneNodes[i]];
}
}
});
ForEach_default.animation(gltf, function(animation) {
const samplerMapping = {};
animation.samplers = objectToArray(animation.samplers, samplerMapping);
ForEach_default.animationSampler(animation, function(sampler) {
sampler.input = globalMapping.accessors[sampler.input];
sampler.output = globalMapping.accessors[sampler.output];
});
ForEach_default.animationChannel(animation, function(channel) {
channel.sampler = samplerMapping[channel.sampler];
const target = channel.target;
if (defined_default(target)) {
target.node = globalMapping.nodes[target.id];
delete target.id;
}
});
});
ForEach_default.material(gltf, function(material) {
if (defined_default(material.technique)) {
material.technique = globalMapping.techniques[material.technique];
}
ForEach_default.materialValue(material, function(value, name) {
if (typeof value === "string") {
material.values[name] = {
index: globalMapping.textures[value]
};
}
});
const extensions = material.extensions;
if (defined_default(extensions)) {
const materialsCommon = extensions.KHR_materials_common;
if (defined_default(materialsCommon) && defined_default(materialsCommon.values)) {
ForEach_default.materialValue(materialsCommon, function(value, name) {
if (typeof value === "string") {
materialsCommon.values[name] = {
index: globalMapping.textures[value]
};
}
});
}
}
});
ForEach_default.image(gltf, function(image) {
const extensions = image.extensions;
if (defined_default(extensions)) {
const binaryGltf = extensions.KHR_binary_glTF;
if (defined_default(binaryGltf)) {
image.bufferView = globalMapping.bufferViews[binaryGltf.bufferView];
image.mimeType = binaryGltf.mimeType;
delete extensions.KHR_binary_glTF;
}
if (Object.keys(extensions).length === 0) {
delete image.extensions;
}
}
});
ForEach_default.texture(gltf, function(texture) {
if (defined_default(texture.sampler)) {
texture.sampler = globalMapping.samplers[texture.sampler];
}
if (defined_default(texture.source)) {
texture.source = globalMapping.images[texture.source];
}
});
}
function removeAnimationSamplerNames(gltf) {
ForEach_default.animation(gltf, function(animation) {
ForEach_default.animationSampler(animation, function(sampler) {
delete sampler.name;
});
});
}
function removeEmptyArrays(gltf) {
for (const topLevelId in gltf) {
if (Object.prototype.hasOwnProperty.call(gltf, topLevelId)) {
const array = gltf[topLevelId];
if (Array.isArray(array) && array.length === 0) {
delete gltf[topLevelId];
}
}
}
ForEach_default.node(gltf, function(node) {
if (defined_default(node.children) && node.children.length === 0) {
delete node.children;
}
});
}
function stripAsset(gltf) {
const asset = gltf.asset;
delete asset.profile;
delete asset.premultipliedAlpha;
}
var knownExtensions = {
CESIUM_RTC: true,
KHR_materials_common: true,
WEB3D_quantized_attributes: true
};
function requireKnownExtensions(gltf) {
const extensionsUsed = gltf.extensionsUsed;
gltf.extensionsRequired = gltf.extensionsRequired ?? [];
if (defined_default(extensionsUsed)) {
const extensionsUsedLength = extensionsUsed.length;
for (let i = 0; i < extensionsUsedLength; ++i) {
const extension = extensionsUsed[i];
if (defined_default(knownExtensions[extension])) {
gltf.extensionsRequired.push(extension);
}
}
}
}
function removeBufferType(gltf) {
ForEach_default.buffer(gltf, function(buffer2) {
delete buffer2.type;
});
}
function removeTextureProperties(gltf) {
ForEach_default.texture(gltf, function(texture) {
delete texture.format;
delete texture.internalFormat;
delete texture.target;
delete texture.type;
});
}
function requireAttributeSetIndex(gltf) {
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
ForEach_default.meshPrimitiveAttribute(
primitive,
function(accessorId, semantic) {
if (semantic === "TEXCOORD") {
primitive.attributes.TEXCOORD_0 = accessorId;
} else if (semantic === "COLOR") {
primitive.attributes.COLOR_0 = accessorId;
}
}
);
delete primitive.attributes.TEXCOORD;
delete primitive.attributes.COLOR;
});
});
ForEach_default.technique(gltf, function(technique) {
ForEach_default.techniqueParameter(technique, function(parameter) {
const semantic = parameter.semantic;
if (defined_default(semantic)) {
if (semantic === "TEXCOORD") {
parameter.semantic = "TEXCOORD_0";
} else if (semantic === "COLOR") {
parameter.semantic = "COLOR_0";
}
}
});
});
}
var knownSemantics = {
POSITION: true,
NORMAL: true,
TANGENT: true
};
var indexedSemantics = {
COLOR: "COLOR",
JOINT: "JOINTS",
JOINTS: "JOINTS",
TEXCOORD: "TEXCOORD",
WEIGHT: "WEIGHTS",
WEIGHTS: "WEIGHTS"
};
function underscoreApplicationSpecificSemantics(gltf) {
const mappedSemantics = {};
ForEach_default.mesh(gltf, function(mesh) {
ForEach_default.meshPrimitive(mesh, function(primitive) {
ForEach_default.meshPrimitiveAttribute(
primitive,
function(accessorId, semantic) {
if (semantic.charAt(0) !== "_") {
const setIndex = semantic.search(/_[0-9]+/g);
let strippedSemantic = semantic;
let suffix = "_0";
if (setIndex >= 0) {
strippedSemantic = semantic.substring(0, setIndex);
suffix = semantic.substring(setIndex);
}
let newSemantic;
const indexedSemantic = indexedSemantics[strippedSemantic];
if (defined_default(indexedSemantic)) {
newSemantic = indexedSemantic + suffix;
mappedSemantics[semantic] = newSemantic;
} else if (!defined_default(knownSemantics[strippedSemantic])) {
newSemantic = `_${semantic}`;
mappedSemantics[semantic] = newSemantic;
}
}
}
);
for (const semantic in mappedSemantics) {
if (Object.prototype.hasOwnProperty.call(mappedSemantics, semantic)) {
const mappedSemantic = mappedSemantics[semantic];
const accessorId = primitive.attributes[semantic];
if (defined_default(accessorId)) {
delete primitive.attributes[semantic];
primitive.attributes[mappedSemantic] = accessorId;
}
}
}
});
});
ForEach_default.technique(gltf, function(technique) {
ForEach_default.techniqueParameter(technique, function(parameter) {
const mappedSemantic = mappedSemantics[parameter.semantic];
if (defined_default(mappedSemantic)) {
parameter.semantic = mappedSemantic;
}
});
});
}
function clampCameraParameters(gltf) {
ForEach_default.camera(gltf, function(camera) {
const perspective = camera.perspective;
if (defined_default(perspective)) {
const aspectRatio = perspective.aspectRatio;
if (defined_default(aspectRatio) && aspectRatio === 0) {
delete perspective.aspectRatio;
}
const yfov = perspective.yfov;
if (defined_default(yfov) && yfov === 0) {
perspective.yfov = 1;
}
}
});
}
function computeAccessorByteStride(gltf, accessor) {
return defined_default(accessor.byteStride) && accessor.byteStride !== 0 ? accessor.byteStride : getAccessorByteStride_default(gltf, accessor);
}
function requireByteLength(gltf) {
ForEach_default.buffer(gltf, function(buffer2) {
if (!defined_default(buffer2.byteLength)) {
buffer2.byteLength = buffer2.extras._pipeline.source.length;
}
});
ForEach_default.accessor(gltf, function(accessor) {
const bufferViewId = accessor.bufferView;
if (defined_default(bufferViewId)) {
const bufferView = gltf.bufferViews[bufferViewId];
const accessorByteStride = computeAccessorByteStride(gltf, accessor);
const accessorByteEnd = accessor.byteOffset + accessor.count * accessorByteStride;
bufferView.byteLength = Math.max(
bufferView.byteLength ?? 0,
accessorByteEnd
);
}
});
}
function moveByteStrideToBufferView(gltf) {
let i;
let j;
let bufferView;
const bufferViews = gltf.bufferViews;
const bufferViewHasVertexAttributes = {};
ForEach_default.accessorContainingVertexAttributeData(gltf, function(accessorId) {
const accessor = gltf.accessors[accessorId];
if (defined_default(accessor.bufferView)) {
bufferViewHasVertexAttributes[accessor.bufferView] = true;
}
});
const bufferViewMap = {};
ForEach_default.accessor(gltf, function(accessor) {
if (defined_default(accessor.bufferView)) {
bufferViewMap[accessor.bufferView] = bufferViewMap[accessor.bufferView] ?? [];
bufferViewMap[accessor.bufferView].push(accessor);
}
});
for (const bufferViewId in bufferViewMap) {
if (Object.prototype.hasOwnProperty.call(bufferViewMap, bufferViewId)) {
bufferView = bufferViews[bufferViewId];
const accessors = bufferViewMap[bufferViewId];
accessors.sort(function(a3, b) {
return a3.byteOffset - b.byteOffset;
});
let currentByteOffset = 0;
let currentIndex = 0;
const accessorsLength = accessors.length;
for (i = 0; i < accessorsLength; ++i) {
let accessor = accessors[i];
const accessorByteStride = computeAccessorByteStride(gltf, accessor);
const accessorByteOffset = accessor.byteOffset;
const accessorByteLength = accessor.count * accessorByteStride;
delete accessor.byteStride;
const hasNextAccessor = i < accessorsLength - 1;
const nextAccessorByteStride = hasNextAccessor ? computeAccessorByteStride(gltf, accessors[i + 1]) : void 0;
if (accessorByteStride !== nextAccessorByteStride) {
const newBufferView = clone_default(bufferView, true);
if (bufferViewHasVertexAttributes[bufferViewId]) {
newBufferView.byteStride = accessorByteStride;
}
newBufferView.byteOffset += currentByteOffset;
newBufferView.byteLength = accessorByteOffset + accessorByteLength - currentByteOffset;
const newBufferViewId = addToArray_default(bufferViews, newBufferView);
for (j = currentIndex; j <= i; ++j) {
accessor = accessors[j];
accessor.bufferView = newBufferViewId;
accessor.byteOffset = accessor.byteOffset - currentByteOffset;
}
currentByteOffset = hasNextAccessor ? accessors[i + 1].byteOffset : void 0;
currentIndex = i + 1;
}
}
}
}
removeUnusedElements_default(gltf, ["accessor", "bufferView", "buffer"]);
}
function requirePositionAccessorMinMax(gltf) {
ForEach_default.accessorWithSemantic(gltf, "POSITION", function(accessorId) {
const accessor = gltf.accessors[accessorId];
if (!defined_default(accessor.min) || !defined_default(accessor.max)) {
const minMax = findAccessorMinMax_default(gltf, accessor);
accessor.min = minMax.min;
accessor.max = minMax.max;
}
});
}
function isNodeEmpty(node) {
return (!defined_default(node.children) || node.children.length === 0) && (!defined_default(node.meshes) || node.meshes.length === 0) && !defined_default(node.camera) && !defined_default(node.skin) && !defined_default(node.skeletons) && !defined_default(node.jointName) && (!defined_default(node.translation) || Cartesian3_default.fromArray(node.translation).equals(Cartesian3_default.ZERO)) && (!defined_default(node.scale) || Cartesian3_default.fromArray(node.scale).equals(new Cartesian3_default(1, 1, 1))) && (!defined_default(node.rotation) || Cartesian4_default.fromArray(node.rotation).equals(
new Cartesian4_default(0, 0, 0, 1)
)) && (!defined_default(node.matrix) || Matrix4_default.fromColumnMajorArray(node.matrix).equals(Matrix4_default.IDENTITY)) && !defined_default(node.extensions) && !defined_default(node.extras);
}
function deleteNode(gltf, nodeId) {
ForEach_default.scene(gltf, function(scene) {
const sceneNodes = scene.nodes;
if (defined_default(sceneNodes)) {
const sceneNodesLength = sceneNodes.length;
for (let i = sceneNodesLength; i >= 0; --i) {
if (sceneNodes[i] === nodeId) {
sceneNodes.splice(i, 1);
return;
}
}
}
});
ForEach_default.node(gltf, function(parentNode, parentNodeId) {
if (defined_default(parentNode.children)) {
const index = parentNode.children.indexOf(nodeId);
if (index > -1) {
parentNode.children.splice(index, 1);
if (isNodeEmpty(parentNode)) {
deleteNode(gltf, parentNodeId);
}
}
}
});
delete gltf.nodes[nodeId];
}
function removeEmptyNodes(gltf) {
ForEach_default.node(gltf, function(node, nodeId) {
if (isNodeEmpty(node)) {
deleteNode(gltf, nodeId);
}
});
return gltf;
}
function requireAnimationAccessorMinMax(gltf) {
ForEach_default.animation(gltf, function(animation) {
ForEach_default.animationSampler(animation, function(sampler) {
const accessor = gltf.accessors[sampler.input];
if (!defined_default(accessor.min) || !defined_default(accessor.max)) {
const minMax = findAccessorMinMax_default(gltf, accessor);
accessor.min = minMax.min;
accessor.max = minMax.max;
}
});
});
}
function validatePresentAccessorMinMax(gltf) {
ForEach_default.accessor(gltf, function(accessor) {
if (defined_default(accessor.min) || defined_default(accessor.max)) {
const minMax = findAccessorMinMax_default(gltf, accessor);
if (defined_default(accessor.min)) {
accessor.min = minMax.min;
}
if (defined_default(accessor.max)) {
accessor.max = minMax.max;
}
}
});
}
function glTF10to20(gltf) {
gltf.asset = gltf.asset ?? {};
gltf.asset.version = "2.0";
updateInstanceTechniques(gltf);
removeAnimationSamplersIndirection(gltf);
removeEmptyNodes(gltf);
objectsToArrays(gltf);
removeAnimationSamplerNames(gltf);
stripAsset(gltf);
requireKnownExtensions(gltf);
requireByteLength(gltf);
moveByteStrideToBufferView(gltf);
requirePositionAccessorMinMax(gltf);
requireAnimationAccessorMinMax(gltf);
validatePresentAccessorMinMax(gltf);
removeBufferType(gltf);
removeTextureProperties(gltf);
requireAttributeSetIndex(gltf);
underscoreApplicationSpecificSemantics(gltf);
updateAccessorComponentTypes_default(gltf);
clampCameraParameters(gltf);
moveTechniqueRenderStates_default(gltf);
moveTechniquesToExtension_default(gltf);
removeEmptyArrays(gltf);
}
var defaultBaseColorTextureNames = [
"u_tex",
"u_diffuse",
"u_emission",
"u_diffuse_tex"
];
var defaultBaseColorFactorNames = ["u_diffuse", "u_diffuse_mat"];
function initializePbrMaterial(material) {
material.pbrMetallicRoughness = defined_default(material.pbrMetallicRoughness) ? material.pbrMetallicRoughness : {};
material.pbrMetallicRoughness.roughnessFactor = 1;
material.pbrMetallicRoughness.metallicFactor = 0;
}
function isTexture(value) {
return defined_default(value.index);
}
function isVec4(value) {
return Array.isArray(value) && value.length === 4;
}
function srgbToLinear(srgb) {
const linear = new Array(4);
linear[3] = srgb[3];
for (let i = 0; i < 3; i++) {
const c = srgb[i];
if (c <= 0.04045) {
linear[i] = srgb[i] * 0.07739938080495357;
} else {
linear[i] = Math.pow(
// eslint-disable-next-line no-loss-of-precision
(c + 0.055) * 0.9478672985781991,
2.4
);
}
}
return linear;
}
function convertTechniquesToPbr(gltf, options) {
options = options ?? {};
const baseColorTextureNames = options.baseColorTextureNames ?? defaultBaseColorTextureNames;
const baseColorFactorNames = options.baseColorFactorNames ?? defaultBaseColorFactorNames;
ForEach_default.material(gltf, function(material) {
ForEach_default.materialValue(material, function(value, name) {
if (baseColorTextureNames.indexOf(name) !== -1 && isTexture(value)) {
initializePbrMaterial(material);
material.pbrMetallicRoughness.baseColorTexture = value;
} else if (baseColorFactorNames.indexOf(name) !== -1 && isVec4(value)) {
initializePbrMaterial(material);
material.pbrMetallicRoughness.baseColorFactor = srgbToLinear(value);
}
});
});
removeExtension_default(gltf, "KHR_techniques_webgl");
removeExtension_default(gltf, "KHR_blend");
}
function assignAsBaseColor(material, baseColor) {
if (defined_default(baseColor)) {
if (isVec4(baseColor)) {
material.pbrMetallicRoughness.baseColorFactor = srgbToLinear(baseColor);
} else if (isTexture(baseColor)) {
material.pbrMetallicRoughness.baseColorTexture = baseColor;
}
}
}
function assignAsEmissive(material, emissive) {
if (defined_default(emissive)) {
if (isVec4(emissive)) {
material.emissiveFactor = emissive.slice(0, 3);
} else if (isTexture(emissive)) {
material.emissiveTexture = emissive;
}
}
}
function convertMaterialsCommonToPbr(gltf) {
ForEach_default.material(gltf, function(material) {
const materialsCommon = (material.extensions ?? {}).KHR_materials_common;
if (!defined_default(materialsCommon)) {
return;
}
const values = materialsCommon.values ?? {};
const ambient = values.ambient;
const diffuse = values.diffuse;
const emission = values.emission;
const transparency = values.transparency;
const doubleSided = materialsCommon.doubleSided;
const transparent = materialsCommon.transparent;
initializePbrMaterial(material);
const technique = materialsCommon.technique;
if (technique === "CONSTANT") {
addExtensionsUsed_default(gltf, "KHR_materials_unlit");
material.extensions = defined_default(material.extensions) ? material.extensions : {};
material.extensions["KHR_materials_unlit"] = {};
assignAsBaseColor(material, emission);
assignAsBaseColor(material, ambient);
} else {
assignAsBaseColor(material, diffuse);
assignAsEmissive(material, ambient);
assignAsEmissive(material, emission);
}
if (defined_default(doubleSided)) {
material.doubleSided = doubleSided;
}
if (defined_default(transparency)) {
if (defined_default(material.pbrMetallicRoughness.baseColorFactor)) {
material.pbrMetallicRoughness.baseColorFactor[3] *= transparency;
} else {
material.pbrMetallicRoughness.baseColorFactor = [1, 1, 1, transparency];
}
}
if (defined_default(transparent)) {
material.alphaMode = transparent ? "BLEND" : "OPAQUE";
}
});
removeExtension_default(gltf, "KHR_materials_common");
}
var updateVersion_default = updateVersion;
// packages/engine/Source/Scene/Model/ModelUtility.js
var import_InlineWorkers505 = __toESM(require_InlineWorkers(), 1);
function ModelUtility() {
}
ModelUtility.getError = function(type, path, error) {
let message = `Failed to load ${type}: ${path}`;
if (defined_default(error) && defined_default(error.message)) {
message += `
${error.message}`;
}
const runtimeError = new RuntimeError_default(message);
if (defined_default(error)) {
runtimeError.stack = `Original stack:
${error.stack}
Handler stack:
${runtimeError.stack}`;
}
return runtimeError;
};
ModelUtility.getNodeTransform = function(node) {
if (defined_default(node.matrix)) {
return node.matrix;
}
return Matrix4_default.fromTranslationQuaternionRotationScale(
defined_default(node.translation) ? node.translation : Cartesian3_default.ZERO,
defined_default(node.rotation) ? node.rotation : Quaternion_default.IDENTITY,
defined_default(node.scale) ? node.scale : Cartesian3_default.ONE
);
};
ModelUtility.getAttributeBySemantic = function(object2, semantic, setIndex) {
const attributes = object2.attributes;
const attributesLength = attributes.length;
for (let i = 0; i < attributesLength; ++i) {
const attribute = attributes[i];
const matchesSetIndex = defined_default(setIndex) ? attribute.setIndex === setIndex : true;
if (attribute.semantic === semantic && matchesSetIndex) {
return attribute;
}
}
return void 0;
};
ModelUtility.getAttributeByName = function(object2, name) {
const attributes = object2.attributes;
const attributesLength = attributes.length;
for (let i = 0; i < attributesLength; ++i) {
const attribute = attributes[i];
if (attribute.name === name) {
return attribute;
}
}
return void 0;
};
ModelUtility.getFeatureIdsByLabel = function(featureIds, label) {
for (let i = 0; i < featureIds.length; i++) {
const featureIdSet = featureIds[i];
if (featureIdSet.positionalLabel === label || featureIdSet.label === label) {
return featureIdSet;
}
}
return void 0;
};
ModelUtility.hasQuantizedAttributes = function(attributes) {
if (!defined_default(attributes)) {
return false;
}
for (let i = 0; i < attributes.length; i++) {
const attribute = attributes[i];
if (defined_default(attribute.quantization)) {
return true;
}
}
return false;
};
ModelUtility.getAttributeInfo = function(attribute) {
const semantic = attribute.semantic;
const setIndex = attribute.setIndex;
let variableName;
let hasSemantic = false;
if (defined_default(semantic)) {
variableName = VertexAttributeSemantic_default.getVariableName(semantic, setIndex);
hasSemantic = true;
} else {
variableName = attribute.name;
variableName = variableName.replace(/^_/, "");
variableName = variableName.toLowerCase();
}
const isVertexColor = /^color_\d+$/.test(variableName);
const attributeType = attribute.type;
let glslType = AttributeType_default.getGlslType(attributeType);
if (isVertexColor) {
glslType = "vec4";
}
const isQuantized = defined_default(attribute.quantization);
let quantizedGlslType;
if (isQuantized) {
quantizedGlslType = isVertexColor ? "vec4" : AttributeType_default.getGlslType(attribute.quantization.type);
}
return {
attribute,
isQuantized,
variableName,
hasSemantic,
glslType,
quantizedGlslType
};
};
var cartesianMaxScratch = new Cartesian3_default();
var cartesianMinScratch = new Cartesian3_default();
ModelUtility.getPositionMinMax = function(primitive, instancingTranslationMin, instancingTranslationMax) {
const positionGltfAttribute = ModelUtility.getAttributeBySemantic(
primitive,
"POSITION"
);
let positionMax = positionGltfAttribute.max;
let positionMin = positionGltfAttribute.min;
if (defined_default(instancingTranslationMax) && defined_default(instancingTranslationMin)) {
positionMin = Cartesian3_default.add(
positionMin,
instancingTranslationMin,
cartesianMinScratch
);
positionMax = Cartesian3_default.add(
positionMax,
instancingTranslationMax,
cartesianMaxScratch
);
}
return {
min: positionMin,
max: positionMax
};
};
ModelUtility.getAxisCorrectionMatrix = function(upAxis, forwardAxis, result) {
result = Matrix4_default.clone(Matrix4_default.IDENTITY, result);
if (upAxis === Axis_default.Y) {
result = Matrix4_default.clone(Axis_default.Y_UP_TO_Z_UP, result);
} else if (upAxis === Axis_default.X) {
result = Matrix4_default.clone(Axis_default.X_UP_TO_Z_UP, result);
}
if (forwardAxis === Axis_default.Z) {
result = Matrix4_default.multiplyTransformation(result, Axis_default.Z_UP_TO_X_UP, result);
}
return result;
};
var scratchMatrix32 = new Matrix3_default();
ModelUtility.getCullFace = function(modelMatrix, primitiveType) {
if (!PrimitiveType_default.isTriangles(primitiveType)) {
return CullFace_default.BACK;
}
const matrix3 = Matrix4_default.getMatrix3(modelMatrix, scratchMatrix32);
return Matrix3_default.determinant(matrix3) < 0 ? CullFace_default.FRONT : CullFace_default.BACK;
};
ModelUtility.sanitizeGlslIdentifier = function(identifier) {
let sanitizedIdentifier = identifier.replaceAll(/[^A-Za-z0-9]+/g, "_");
sanitizedIdentifier = sanitizedIdentifier.replace(/^gl_/, "");
if (/^\d/.test(sanitizedIdentifier)) {
sanitizedIdentifier = `_${sanitizedIdentifier}`;
}
return sanitizedIdentifier;
};
ModelUtility.supportedExtensions = {
AGI_articulations: true,
CESIUM_primitive_outline: true,
CESIUM_RTC: true,
EXT_feature_metadata: true,
EXT_implicit_cylinder_region: true,
EXT_implicit_ellipsoid_region: true,
EXT_instance_features: true,
EXT_mesh_features: true,
EXT_mesh_gpu_instancing: true,
EXT_meshopt_compression: true,
EXT_primitive_voxels: true,
EXT_structural_metadata: true,
EXT_texture_webp: true,
KHR_blend: true,
KHR_draco_mesh_compression: true,
KHR_implicit_shapes: true,
KHR_materials_common: true,
KHR_materials_pbrSpecularGlossiness: true,
KHR_materials_specular: true,
KHR_materials_anisotropy: true,
KHR_materials_clearcoat: true,
KHR_materials_unlit: true,
KHR_mesh_quantization: true,
KHR_techniques_webgl: true,
KHR_texture_basisu: true,
KHR_texture_transform: true,
KHR_gaussian_splatting: true,
KHR_gaussian_splatting_compression_spz_2: true,
KHR_spz_gaussian_splats_compression: true,
WEB3D_quantized_attributes: true
};
ModelUtility.checkSupportedExtensions = function(extensionsRequired) {
const length2 = extensionsRequired.length;
for (let i = 0; i < length2; i++) {
const extension = extensionsRequired[i];
if (!ModelUtility.supportedExtensions[extension]) {
throw new RuntimeError_default(`Unsupported glTF Extension: ${extension}`);
}
}
};
var ModelUtility_default = ModelUtility;
// packages/engine/Source/Scene/GltfJsonLoader.js
function GltfJsonLoader(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const resourceCache = options.resourceCache;
const gltfResource = options.gltfResource;
const baseResource2 = options.baseResource;
const typedArray = options.typedArray;
const gltfJson = options.gltfJson;
const cacheKey = options.cacheKey;
Check_default.typeOf.func("options.resourceCache", resourceCache);
Check_default.typeOf.object("options.gltfResource", gltfResource);
Check_default.typeOf.object("options.baseResource", baseResource2);
this._resourceCache = resourceCache;
this._gltfResource = gltfResource;
this._baseResource = baseResource2;
this._typedArray = typedArray;
this._gltfJson = gltfJson;
this._cacheKey = cacheKey;
this._gltf = void 0;
this._bufferLoaders = [];
this._state = ResourceLoaderState_default.UNLOADED;
this._promise = void 0;
}
if (defined_default(Object.create)) {
GltfJsonLoader.prototype = Object.create(ResourceLoader_default.prototype);
GltfJsonLoader.prototype.constructor = GltfJsonLoader;
}
Object.defineProperties(GltfJsonLoader.prototype, {
/**
* The cache key of the resource.
*
* @memberof GltfJsonLoader.prototype
*
* @type {string}
* @readonly
* @private
*/
cacheKey: {
get: function() {
return this._cacheKey;
}
},
/**
* The glTF JSON.
*
* @memberof GltfJsonLoader.prototype
*
* @type {object}
* @readonly
* @private
*/
gltf: {
get: function() {
return this._gltf;
}
}
});
GltfJsonLoader.prototype.load = async function() {
if (defined_default(this._promise)) {
return this._promise;
}
this._state = ResourceLoaderState_default.LOADING;
if (defined_default(this._gltfJson)) {
this._promise = processGltfJson(this, this._gltfJson);
return this._promise;
}
if (defined_default(this._typedArray)) {
this._promise = processGltfTypedArray(this, this._typedArray);
return this._promise;
}
this._promise = loadFromUri2(this);
return this._promise;
};
async function loadFromUri2(gltfJsonLoader) {
let typedArray;
try {
const arrayBuffer = await gltfJsonLoader._fetchGltf();
if (gltfJsonLoader.isDestroyed()) {
return;
}
typedArray = new Uint8Array(arrayBuffer);
} catch (error) {
if (gltfJsonLoader.isDestroyed()) {
return;
}
handleError4(gltfJsonLoader, error);
}
return processGltfTypedArray(gltfJsonLoader, typedArray);
}
function handleError4(gltfJsonLoader, error) {
gltfJsonLoader.unload();
gltfJsonLoader._state = ResourceLoaderState_default.FAILED;
const errorMessage = `Failed to load glTF: ${gltfJsonLoader._gltfResource.url}`;
throw gltfJsonLoader.getError(errorMessage, error);
}
async function upgradeVersion(gltfJsonLoader, gltf) {
if (defined_default(gltf.asset) && gltf.asset.version === "2.0" && !usesExtension_default(gltf, "KHR_techniques_webgl") && !usesExtension_default(gltf, "KHR_materials_common")) {
return Promise.resolve();
}
const promises = [];
ForEach_default.buffer(gltf, function(buffer2) {
if (!defined_default(buffer2.extras._pipeline.source) && // Ignore uri if this buffer uses the glTF 1.0 KHR_binary_glTF extension
defined_default(buffer2.uri)) {
const resource = gltfJsonLoader._baseResource.getDerivedResource({
url: buffer2.uri
});
const resourceCache = gltfJsonLoader._resourceCache;
const bufferLoader = resourceCache.getExternalBufferLoader({
resource
});
gltfJsonLoader._bufferLoaders.push(bufferLoader);
promises.push(
bufferLoader.load().then(function() {
if (bufferLoader.isDestroyed()) {
return;
}
buffer2.extras._pipeline.source = bufferLoader.typedArray;
})
);
}
});
await Promise.all(promises);
updateVersion_default(gltf);
}
function decodeDataUris(gltf) {
const promises = [];
ForEach_default.buffer(gltf, function(buffer2) {
const bufferUri = buffer2.uri;
if (!defined_default(buffer2.extras._pipeline.source) && // Ignore uri if this buffer uses the glTF 1.0 KHR_binary_glTF extension
defined_default(bufferUri) && isDataUri_default(bufferUri)) {
delete buffer2.uri;
promises.push(
Resource_default.fetchArrayBuffer(bufferUri).then(function(arrayBuffer) {
buffer2.extras._pipeline.source = new Uint8Array(arrayBuffer);
})
);
}
});
return Promise.all(promises);
}
function loadEmbeddedBuffers(gltfJsonLoader, gltf) {
const promises = [];
ForEach_default.buffer(gltf, function(buffer2, bufferId) {
const source = buffer2.extras._pipeline.source;
if (defined_default(source) && !defined_default(buffer2.uri)) {
const resourceCache = gltfJsonLoader._resourceCache;
const bufferLoader = resourceCache.getEmbeddedBufferLoader({
parentResource: gltfJsonLoader._gltfResource,
bufferId,
typedArray: source
});
gltfJsonLoader._bufferLoaders.push(bufferLoader);
promises.push(bufferLoader.load());
}
});
return Promise.all(promises);
}
async function processGltfJson(gltfJsonLoader, gltf) {
try {
addPipelineExtras_default(gltf);
await decodeDataUris(gltf);
await upgradeVersion(gltfJsonLoader, gltf);
addDefaults_default(gltf);
await loadEmbeddedBuffers(gltfJsonLoader, gltf);
removePipelineExtras_default(gltf);
const version2 = gltf.asset.version;
if (version2 !== "1.0" && version2 !== "2.0") {
throw new RuntimeError_default(`Unsupported glTF version: ${version2}`);
}
const extensionsRequired = gltf.extensionsRequired;
if (defined_default(extensionsRequired)) {
ModelUtility_default.checkSupportedExtensions(extensionsRequired);
}
gltfJsonLoader._gltf = gltf;
gltfJsonLoader._state = ResourceLoaderState_default.READY;
return gltfJsonLoader;
} catch (error) {
if (gltfJsonLoader.isDestroyed()) {
return;
}
handleError4(gltfJsonLoader, error);
}
}
async function processGltfTypedArray(gltfJsonLoader, typedArray) {
let gltf;
try {
if (getMagic_default(typedArray) === "glTF") {
gltf = parseGlb_default(typedArray);
} else {
gltf = getJsonFromTypedArray_default(typedArray);
}
} catch (error) {
if (gltfJsonLoader.isDestroyed()) {
return;
}
handleError4(gltfJsonLoader, error);
}
return processGltfJson(gltfJsonLoader, gltf);
}
GltfJsonLoader.prototype.unload = function() {
const bufferLoaders = this._bufferLoaders;
const bufferLoadersLength = bufferLoaders.length;
for (let i = 0; i < bufferLoadersLength; ++i) {
bufferLoaders[i] = !bufferLoaders[i].isDestroyed() && this._resourceCache.unload(bufferLoaders[i]);
}
this._bufferLoaders.length = 0;
this._gltf = void 0;
};
GltfJsonLoader.prototype._fetchGltf = function() {
return this._gltfResource.fetchArrayBuffer();
};
var GltfJsonLoader_default = GltfJsonLoader;
// packages/engine/Source/Scene/GltfTextureLoader.js
var import_InlineWorkers511 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GltfLoaderUtil.js
var import_InlineWorkers509 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/ModelComponents.js
var import_InlineWorkers508 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/AlphaMode.js
var import_InlineWorkers507 = __toESM(require_InlineWorkers(), 1);
var AlphaMode = {
/**
* The alpha value is ignored and the rendered output is fully opaque.
*
* @type {string}
* @constant
*/
OPAQUE: "OPAQUE",
/**
* The rendered output is either fully opaque or fully transparent depending on the alpha value and the specified alpha cutoff value.
*
* @type {string}
* @constant
*/
MASK: "MASK",
/**
* The rendered output is composited onto the destination with alpha blending.
*
* @type {string}
* @constant
*/
BLEND: "BLEND"
};
var AlphaMode_default = Object.freeze(AlphaMode);
// packages/engine/Source/Scene/ModelComponents.js
var ModelComponents = {};
function Quantization() {
this.octEncoded = false;
this.octEncodedZXY = false;
this.normalizationRange = void 0;
this.quantizedVolumeOffset = void 0;
this.quantizedVolumeDimensions = void 0;
this.quantizedVolumeStepSize = void 0;
this.componentDatatype = void 0;
this.type = void 0;
}
function Attribute() {
this.name = void 0;
this.semantic = void 0;
this.setIndex = void 0;
this.componentDatatype = void 0;
this.type = void 0;
this.normalized = false;
this.count = void 0;
this.min = void 0;
this.max = void 0;
this.constant = void 0;
this.quantization = void 0;
this.typedArray = void 0;
this.buffer = void 0;
this.byteOffset = 0;
this.byteStride = void 0;
}
function Indices() {
this.indexDatatype = void 0;
this.count = void 0;
this.buffer = void 0;
this.typedArray = void 0;
}
function FeatureIdAttribute() {
this.featureCount = void 0;
this.nullFeatureId = void 0;
this.propertyTableId = void 0;
this.setIndex = void 0;
this.label = void 0;
this.positionalLabel = void 0;
}
function FeatureIdImplicitRange() {
this.featureCount = void 0;
this.nullFeatureId = void 0;
this.propertyTableId = void 0;
this.offset = 0;
this.repeat = void 0;
this.label = void 0;
this.positionalLabel = void 0;
}
function FeatureIdTexture() {
this.featureCount = void 0;
this.nullFeatureId = void 0;
this.propertyTableId = void 0;
this.textureReader = void 0;
this.label = void 0;
this.positionalLabel = void 0;
}
function MorphTarget() {
this.attributes = [];
}
function Primitive2() {
this.attributes = [];
this.morphTargets = [];
this.indices = void 0;
this.material = void 0;
this.primitiveType = void 0;
this.featureIds = [];
this.propertyTextureIds = [];
this.propertyAttributeIds = [];
this.outlineCoordinates = void 0;
this.modelPrimitiveImagery = void 0;
}
function Instances() {
this.attributes = [];
this.featureIds = [];
this.transformInWorldSpace = false;
}
function Skin() {
this.index = void 0;
this.joints = [];
this.inverseBindMatrices = [];
}
function Node3() {
this.name = void 0;
this.index = void 0;
this.children = [];
this.primitives = [];
this.instances = void 0;
this.skin = void 0;
this.matrix = void 0;
this.translation = void 0;
this.rotation = void 0;
this.scale = void 0;
this.morphWeights = [];
this.articulationName = void 0;
}
function Scene() {
this.nodes = [];
}
var AnimatedPropertyType = {
TRANSLATION: "translation",
ROTATION: "rotation",
SCALE: "scale",
WEIGHTS: "weights"
};
function AnimationSampler() {
this.input = [];
this.interpolation = void 0;
this.output = [];
}
function AnimationTarget() {
this.node = void 0;
this.path = void 0;
}
function AnimationChannel() {
this.sampler = void 0;
this.target = void 0;
}
function Animation() {
this.name = void 0;
this.samplers = [];
this.channels = [];
}
function ArticulationStage() {
this.name = void 0;
this.type = void 0;
this.minimumValue = void 0;
this.maximumValue = void 0;
this.initialValue = void 0;
}
function Articulation() {
this.name = void 0;
this.stages = [];
}
function Asset() {
this.credits = [];
}
function Components() {
this.asset = new Asset();
this.scene = void 0;
this.nodes = [];
this.skins = [];
this.animations = [];
this.articulations = [];
this.structuralMetadata = void 0;
this.upAxis = void 0;
this.forwardAxis = void 0;
this.transform = Matrix4_default.clone(Matrix4_default.IDENTITY);
this.extensions = {};
}
function TextureReader() {
this.texture = void 0;
this.index = void 0;
this.texCoord = 0;
this.transform = Matrix3_default.clone(Matrix3_default.IDENTITY);
this.scale = 1;
this.channels = void 0;
}
function MetallicRoughness() {
this.baseColorTexture = void 0;
this.metallicRoughnessTexture = void 0;
this.baseColorFactor = Cartesian4_default.clone(
MetallicRoughness.DEFAULT_BASE_COLOR_FACTOR
);
this.metallicFactor = MetallicRoughness.DEFAULT_METALLIC_FACTOR;
this.roughnessFactor = MetallicRoughness.DEFAULT_ROUGHNESS_FACTOR;
}
MetallicRoughness.DEFAULT_BASE_COLOR_FACTOR = Cartesian4_default.ONE;
MetallicRoughness.DEFAULT_METALLIC_FACTOR = 1;
MetallicRoughness.DEFAULT_ROUGHNESS_FACTOR = 1;
function SpecularGlossiness() {
this.diffuseTexture = void 0;
this.specularGlossinessTexture = void 0;
this.diffuseFactor = Cartesian4_default.clone(
SpecularGlossiness.DEFAULT_DIFFUSE_FACTOR
);
this.specularFactor = Cartesian3_default.clone(
SpecularGlossiness.DEFAULT_SPECULAR_FACTOR
);
this.glossinessFactor = SpecularGlossiness.DEFAULT_GLOSSINESS_FACTOR;
}
SpecularGlossiness.DEFAULT_DIFFUSE_FACTOR = Cartesian4_default.ONE;
SpecularGlossiness.DEFAULT_SPECULAR_FACTOR = Cartesian3_default.ONE;
SpecularGlossiness.DEFAULT_GLOSSINESS_FACTOR = 1;
function Specular() {
this.specularFactor = Specular.DEFAULT_SPECULAR_FACTOR;
this.specularTexture = void 0;
this.specularColorFactor = Cartesian3_default.clone(
Specular.DEFAULT_SPECULAR_COLOR_FACTOR
);
this.specularColorTexture = void 0;
}
Specular.DEFAULT_SPECULAR_FACTOR = 1;
Specular.DEFAULT_SPECULAR_COLOR_FACTOR = Cartesian3_default.ONE;
function Anisotropy() {
this.anisotropyStrength = Anisotropy.DEFAULT_ANISOTROPY_STRENGTH;
this.anisotropyRotation = Anisotropy.DEFAULT_ANISOTROPY_ROTATION;
this.anisotropyTexture = void 0;
}
Anisotropy.DEFAULT_ANISOTROPY_STRENGTH = 0;
Anisotropy.DEFAULT_ANISOTROPY_ROTATION = 0;
function Clearcoat() {
this.clearcoatFactor = Clearcoat.DEFAULT_CLEARCOAT_FACTOR;
this.clearcoatTexture = void 0;
this.clearcoatRoughnessFactor = Clearcoat.DEFAULT_CLEARCOAT_ROUGHNESS_FACTOR;
this.clearcoatRoughnessTexture = void 0;
this.clearcoatNormalTexture = void 0;
}
Clearcoat.DEFAULT_CLEARCOAT_FACTOR = 0;
Clearcoat.DEFAULT_CLEARCOAT_ROUGHNESS_FACTOR = 0;
function Material2() {
this.metallicRoughness = new MetallicRoughness();
this.specularGlossiness = void 0;
this.specular = void 0;
this.anisotropy = void 0;
this.clearcoat = void 0;
this.emissiveTexture = void 0;
this.normalTexture = void 0;
this.occlusionTexture = void 0;
this.emissiveFactor = Cartesian3_default.clone(Material2.DEFAULT_EMISSIVE_FACTOR);
this.alphaMode = AlphaMode_default.OPAQUE;
this.alphaCutoff = 0.5;
this.doubleSided = false;
this.unlit = false;
}
Material2.DEFAULT_EMISSIVE_FACTOR = Cartesian3_default.ZERO;
ModelComponents.Quantization = Quantization;
ModelComponents.Attribute = Attribute;
ModelComponents.Indices = Indices;
ModelComponents.FeatureIdAttribute = FeatureIdAttribute;
ModelComponents.FeatureIdTexture = FeatureIdTexture;
ModelComponents.FeatureIdImplicitRange = FeatureIdImplicitRange;
ModelComponents.MorphTarget = MorphTarget;
ModelComponents.Primitive = Primitive2;
ModelComponents.Instances = Instances;
ModelComponents.Skin = Skin;
ModelComponents.Node = Node3;
ModelComponents.Scene = Scene;
ModelComponents.AnimatedPropertyType = Object.freeze(AnimatedPropertyType);
ModelComponents.AnimationSampler = AnimationSampler;
ModelComponents.AnimationTarget = AnimationTarget;
ModelComponents.AnimationChannel = AnimationChannel;
ModelComponents.Animation = Animation;
ModelComponents.ArticulationStage = ArticulationStage;
ModelComponents.Articulation = Articulation;
ModelComponents.Asset = Asset;
ModelComponents.Components = Components;
ModelComponents.TextureReader = TextureReader;
ModelComponents.MetallicRoughness = MetallicRoughness;
ModelComponents.SpecularGlossiness = SpecularGlossiness;
ModelComponents.Specular = Specular;
ModelComponents.Anisotropy = Anisotropy;
ModelComponents.Clearcoat = Clearcoat;
ModelComponents.Material = Material2;
var ModelComponents_default = ModelComponents;
// packages/engine/Source/Scene/GltfLoaderUtil.js
var GltfLoaderUtil = {};
GltfLoaderUtil.getImageIdFromTexture = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const { gltf, textureId, supportedImageFormats } = options;
Check_default.typeOf.object("options.gltf", gltf);
Check_default.typeOf.number("options.textureId", textureId);
Check_default.typeOf.object("options.supportedImageFormats", supportedImageFormats);
const texture = gltf.textures[textureId];
const extensions = texture.extensions;
if (defined_default(extensions)) {
if (supportedImageFormats.webp && defined_default(extensions.EXT_texture_webp)) {
return extensions.EXT_texture_webp.source;
} else if (supportedImageFormats.basis && defined_default(extensions.KHR_texture_basisu)) {
return extensions.KHR_texture_basisu.source;
}
}
return texture.source;
};
GltfLoaderUtil.createSampler = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const { gltf, textureInfo, compressedTextureNoMipmap = false } = options;
Check_default.typeOf.object("options.gltf", gltf);
Check_default.typeOf.object("options.textureInfo", textureInfo);
let wrapS = TextureWrap_default.REPEAT;
let wrapT = TextureWrap_default.REPEAT;
let minFilter = TextureMinificationFilter_default.LINEAR;
let magFilter = TextureMagnificationFilter_default.LINEAR;
const textureId = textureInfo.index;
const texture = gltf.textures[textureId];
const samplerId = texture.sampler;
if (defined_default(samplerId)) {
const sampler = gltf.samplers[samplerId];
wrapS = sampler.wrapS ?? wrapS;
wrapT = sampler.wrapT ?? wrapT;
minFilter = sampler.minFilter ?? minFilter;
magFilter = sampler.magFilter ?? magFilter;
}
if (compressedTextureNoMipmap && minFilter !== TextureMinificationFilter_default.LINEAR && minFilter !== TextureMinificationFilter_default.NEAREST) {
if (minFilter === TextureMinificationFilter_default.NEAREST_MIPMAP_NEAREST || minFilter === TextureMinificationFilter_default.NEAREST_MIPMAP_LINEAR) {
minFilter = TextureMinificationFilter_default.NEAREST;
} else {
minFilter = TextureMinificationFilter_default.LINEAR;
}
}
return new Sampler_default({
wrapS,
wrapT,
minificationFilter: minFilter,
magnificationFilter: magFilter
});
};
var defaultScale3 = new Cartesian2_default(1, 1);
GltfLoaderUtil.createModelTextureReader = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const { textureInfo, channels, texture } = options;
Check_default.typeOf.object("options.textureInfo", textureInfo);
let texCoord = textureInfo.texCoord ?? 0;
let transform3;
const textureTransform = textureInfo.extensions?.KHR_texture_transform;
if (defined_default(textureTransform)) {
texCoord = textureTransform.texCoord ?? texCoord;
const offset = defined_default(textureTransform.offset) ? Cartesian2_default.unpack(textureTransform.offset) : Cartesian2_default.ZERO;
let rotation = textureTransform.rotation ?? 0;
const scale = defined_default(textureTransform.scale) ? Cartesian2_default.unpack(textureTransform.scale) : defaultScale3;
rotation = -rotation;
transform3 = new Matrix3_default(
Math.cos(rotation) * scale.x,
-Math.sin(rotation) * scale.y,
offset.x,
Math.sin(rotation) * scale.x,
Math.cos(rotation) * scale.y,
offset.y,
0,
0,
1
);
}
const modelTextureReader = new ModelComponents_default.TextureReader();
modelTextureReader.index = textureInfo.index;
modelTextureReader.texture = texture;
modelTextureReader.texCoord = texCoord;
modelTextureReader.scale = textureInfo.scale;
modelTextureReader.transform = transform3;
modelTextureReader.channels = channels;
return modelTextureReader;
};
var GltfLoaderUtil_default = GltfLoaderUtil;
// packages/engine/Source/Core/resizeImageToNextPowerOfTwo.js
var import_InlineWorkers510 = __toESM(require_InlineWorkers(), 1);
function resizeImageToNextPowerOfTwo(image) {
const canvas = document.createElement("canvas");
canvas.width = Math_default.nextPowerOfTwo(image.width);
canvas.height = Math_default.nextPowerOfTwo(image.height);
const canvasContext = canvas.getContext("2d");
canvasContext.drawImage(
image,
0,
0,
image.width,
image.height,
0,
0,
canvas.width,
canvas.height
);
return canvas;
}
var resizeImageToNextPowerOfTwo_default = resizeImageToNextPowerOfTwo;
// packages/engine/Source/Scene/GltfTextureLoader.js
function GltfTextureLoader(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const resourceCache = options.resourceCache;
const gltf = options.gltf;
const textureInfo = options.textureInfo;
const gltfResource = options.gltfResource;
const baseResource2 = options.baseResource;
const supportedImageFormats = options.supportedImageFormats;
const cacheKey = options.cacheKey;
const asynchronous = options.asynchronous ?? true;
Check_default.typeOf.func("options.resourceCache", resourceCache);
Check_default.typeOf.object("options.gltf", gltf);
Check_default.typeOf.object("options.textureInfo", textureInfo);
Check_default.typeOf.object("options.gltfResource", gltfResource);
Check_default.typeOf.object("options.baseResource", baseResource2);
Check_default.typeOf.object("options.supportedImageFormats", supportedImageFormats);
const textureId = textureInfo.index;
const imageId = GltfLoaderUtil_default.getImageIdFromTexture({
gltf,
textureId,
supportedImageFormats
});
this._resourceCache = resourceCache;
this._gltf = gltf;
this._textureInfo = textureInfo;
this._imageId = imageId;
this._gltfResource = gltfResource;
this._baseResource = baseResource2;
this._cacheKey = cacheKey;
this._asynchronous = asynchronous;
this._imageLoader = void 0;
this._image = void 0;
this._mipLevels = void 0;
this._texture = void 0;
this._state = ResourceLoaderState_default.UNLOADED;
this._promise = void 0;
}
if (defined_default(Object.create)) {
GltfTextureLoader.prototype = Object.create(ResourceLoader_default.prototype);
GltfTextureLoader.prototype.constructor = GltfTextureLoader;
}
Object.defineProperties(GltfTextureLoader.prototype, {
/**
* The cache key of the resource.
*
* @memberof GltfTextureLoader.prototype
*
* @type {string}
* @readonly
* @private
*/
cacheKey: {
get: function() {
return this._cacheKey;
}
},
/**
* The texture.
*
* @memberof GltfTextureLoader.prototype
*
* @type {Texture}
* @readonly
* @private
*/
texture: {
get: function() {
return this._texture;
}
}
});
var scratchTextureJob = new CreateTextureJob();
async function loadResources3(loader) {
const resourceCache = loader._resourceCache;
try {
const imageLoader = resourceCache.getImageLoader({
gltf: loader._gltf,
imageId: loader._imageId,
gltfResource: loader._gltfResource,
baseResource: loader._baseResource
});
loader._imageLoader = imageLoader;
await imageLoader.load();
if (loader.isDestroyed()) {
return;
}
loader._image = imageLoader.image;
loader._mipLevels = imageLoader.mipLevels;
loader._state = ResourceLoaderState_default.LOADED;
return loader;
} catch (error) {
if (loader.isDestroyed()) {
return;
}
loader.unload();
loader._state = ResourceLoaderState_default.FAILED;
const errorMessage = "Failed to load texture";
throw loader.getError(errorMessage, error);
}
}
GltfTextureLoader.prototype.load = async function() {
if (defined_default(this._promise)) {
return this._promise;
}
this._state = ResourceLoaderState_default.LOADING;
this._promise = loadResources3(this);
return this._promise;
};
function CreateTextureJob() {
this.gltf = void 0;
this.textureInfo = void 0;
this.textureId = void 0;
this.image = void 0;
this.context = void 0;
this.texture = void 0;
}
CreateTextureJob.prototype.set = function(gltf, textureInfo, textureId, image, mipLevels, context) {
this.gltf = gltf;
this.textureInfo = textureInfo;
this.textureId = textureId;
this.image = image;
this.mipLevels = mipLevels;
this.context = context;
};
CreateTextureJob.prototype.execute = function() {
this.texture = createTexture3(
this.gltf,
this.textureInfo,
this.textureId,
this.image,
this.mipLevels,
this.context
);
};
function createTexture3(gltf, textureInfo, textureId, image, mipLevels, context) {
const internalFormat = image.internalFormat;
let compressedTextureNoMipmap = false;
if (PixelFormat_default.isCompressedFormat(internalFormat) && !defined_default(mipLevels)) {
compressedTextureNoMipmap = true;
}
const sampler = GltfLoaderUtil_default.createSampler({
gltf,
textureInfo,
compressedTextureNoMipmap
});
const minFilter = sampler.minificationFilter;
const wrapS = sampler.wrapS;
const wrapT = sampler.wrapT;
const samplerRequiresMipmap2 = minFilter === TextureMinificationFilter_default.NEAREST_MIPMAP_NEAREST || minFilter === TextureMinificationFilter_default.NEAREST_MIPMAP_LINEAR || minFilter === TextureMinificationFilter_default.LINEAR_MIPMAP_NEAREST || minFilter === TextureMinificationFilter_default.LINEAR_MIPMAP_LINEAR;
const generateMipmap = !defined_default(internalFormat) && samplerRequiresMipmap2;
const requiresPowerOfTwo = generateMipmap || wrapS === TextureWrap_default.REPEAT || wrapS === TextureWrap_default.MIRRORED_REPEAT || wrapT === TextureWrap_default.REPEAT || wrapT === TextureWrap_default.MIRRORED_REPEAT;
const nonPowerOfTwo = !Math_default.isPowerOfTwo(image.width) || !Math_default.isPowerOfTwo(image.height);
const requiresResize = requiresPowerOfTwo && nonPowerOfTwo;
let texture;
if (defined_default(internalFormat)) {
if (!context.webgl2 && PixelFormat_default.isCompressedFormat(internalFormat) && nonPowerOfTwo && requiresPowerOfTwo) {
console.warn(
"Compressed texture uses REPEAT or MIRRORED_REPEAT texture wrap mode and dimensions are not powers of two. The texture may be rendered incorrectly."
);
}
texture = Texture_default.create({
id: textureId,
context,
source: {
arrayBufferView: image.bufferView,
// Only defined for CompressedTextureBuffer
mipLevels
},
width: image.width,
height: image.height,
pixelFormat: image.internalFormat,
// Only defined for CompressedTextureBuffer
sampler
});
} else {
if (requiresResize) {
image = resizeImageToNextPowerOfTwo_default(image);
}
texture = Texture_default.create({
id: textureId,
context,
source: image,
sampler,
flipY: false,
skipColorSpaceConversion: true
});
}
if (generateMipmap) {
texture.generateMipmap();
}
return texture;
}
GltfTextureLoader.prototype.process = function(frameState) {
Check_default.typeOf.object("frameState", frameState);
if (this._state === ResourceLoaderState_default.READY) {
return true;
}
if (this._state !== ResourceLoaderState_default.LOADED && this._state !== ResourceLoaderState_default.PROCESSING) {
return false;
}
if (defined_default(this._texture)) {
return false;
}
if (!defined_default(this._image)) {
return false;
}
this._state = ResourceLoaderState_default.PROCESSING;
let texture;
if (this._asynchronous) {
const textureJob = scratchTextureJob;
textureJob.set(
this._gltf,
this._textureInfo,
this._cacheKey,
this._image,
this._mipLevels,
frameState.context
);
const jobScheduler = frameState.jobScheduler;
if (!jobScheduler.execute(textureJob, JobType_default.TEXTURE)) {
return;
}
texture = textureJob.texture;
} else {
texture = createTexture3(
this._gltf,
this._textureInfo,
this._cacheKey,
this._image,
this._mipLevels,
frameState.context
);
}
this.unload();
this._texture = texture;
this._state = ResourceLoaderState_default.READY;
this._resourceCache.statistics.addTextureLoader(this);
return true;
};
GltfTextureLoader.prototype.unload = function() {
if (defined_default(this._texture)) {
this._texture.destroy();
}
if (defined_default(this._imageLoader) && !this._imageLoader.isDestroyed()) {
this._resourceCache.unload(this._imageLoader);
}
this._imageLoader = void 0;
this._image = void 0;
this._mipLevels = void 0;
this._texture = void 0;
this._gltf = void 0;
};
var GltfTextureLoader_default = GltfTextureLoader;
// packages/engine/Source/Scene/GltfVertexBufferLoader.js
var import_InlineWorkers512 = __toESM(require_InlineWorkers(), 1);
function GltfVertexBufferLoader(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const resourceCache = options.resourceCache;
const gltf = options.gltf;
const gltfResource = options.gltfResource;
const baseResource2 = options.baseResource;
const bufferViewId = options.bufferViewId;
const primitive = options.primitive;
const draco = options.draco;
const attributeSemantic = options.attributeSemantic;
const accessorId = options.accessorId;
const cacheKey = options.cacheKey;
const spz = options.spz;
const asynchronous = options.asynchronous ?? true;
const loadBuffer = options.loadBuffer ?? false;
const loadTypedArray = options.loadTypedArray ?? false;
Check_default.typeOf.func("options.resourceCache", resourceCache);
Check_default.typeOf.object("options.gltf", gltf);
Check_default.typeOf.object("options.gltfResource", gltfResource);
Check_default.typeOf.object("options.baseResource", baseResource2);
if (!loadBuffer && !loadTypedArray) {
throw new DeveloperError_default(
"At least one of loadBuffer and loadTypedArray must be true."
);
}
const hasBufferViewId = defined_default(bufferViewId);
const hasPrimitive = defined_default(primitive);
const hasDraco = hasDracoCompression(draco, attributeSemantic);
const hasAttributeSemantic = defined_default(attributeSemantic);
const hasAccessorId = defined_default(accessorId);
const hasSpz = defined_default(spz);
if (hasBufferViewId === (hasDraco !== hasSpz)) {
throw new DeveloperError_default(
"One of options.bufferViewId, options.draco, or options.spz must be defined."
);
}
if (hasDraco && !hasAttributeSemantic) {
throw new DeveloperError_default(
"When options.draco is defined options.attributeSemantic must also be defined."
);
}
if (hasDraco && !hasAccessorId) {
throw new DeveloperError_default(
"When options.draco is defined options.accessorId must also be defined."
);
}
if (hasDraco && !hasPrimitive) {
throw new DeveloperError_default(
"When options.draco is defined options.primitive must also be defined."
);
}
if (hasDraco) {
Check_default.typeOf.object("options.primitive", primitive);
Check_default.typeOf.object("options.draco", draco);
Check_default.typeOf.string("options.attributeSemantic", attributeSemantic);
Check_default.typeOf.number("options.accessorId", accessorId);
}
this._resourceCache = resourceCache;
this._gltfResource = gltfResource;
this._baseResource = baseResource2;
this._gltf = gltf;
this._bufferViewId = bufferViewId;
this._primitive = primitive;
this._draco = draco;
this._spz = spz;
this._attributeSemantic = attributeSemantic;
this._accessorId = accessorId;
this._cacheKey = cacheKey;
this._asynchronous = asynchronous;
this._loadBuffer = loadBuffer;
this._loadTypedArray = loadTypedArray;
this._bufferViewLoader = void 0;
this._dracoLoader = void 0;
this._quantization = void 0;
this._typedArray = void 0;
this._buffer = void 0;
this._state = ResourceLoaderState_default.UNLOADED;
this._promise = void 0;
}
if (defined_default(Object.create)) {
GltfVertexBufferLoader.prototype = Object.create(ResourceLoader_default.prototype);
GltfVertexBufferLoader.prototype.constructor = GltfVertexBufferLoader;
}
Object.defineProperties(GltfVertexBufferLoader.prototype, {
/**
* The cache key of the resource.
*
* @memberof GltfVertexBufferLoader.prototype
*
* @type {string}
* @readonly
* @private
*/
cacheKey: {
get: function() {
return this._cacheKey;
}
},
/**
* The vertex buffer. This is only defined when loadAsTypedArray is false.
*
* @memberof GltfVertexBufferLoader.prototype
*
* @type {Buffer}
* @readonly
* @private
*/
buffer: {
get: function() {
return this._buffer;
}
},
/**
* The typed array containing vertex buffer data. This is only defined when loadAsTypedArray is true.
*
* @memberof GltfVertexBufferLoader.prototype
*
* @type {Uint8Array}
* @readonly
* @private
*/
typedArray: {
get: function() {
return this._typedArray;
}
},
/**
* Information about the quantized vertex attribute after Draco decode.
*
* @memberof GltfVertexBufferLoader.prototype
*
* @type {ModelComponents.Quantization}
* @readonly
* @private
*/
quantization: {
get: function() {
return this._quantization;
}
}
});
function hasDracoCompression(draco, semantic) {
return defined_default(draco) && defined_default(draco.attributes) && defined_default(draco.attributes[semantic]);
}
GltfVertexBufferLoader.prototype.load = async function() {
if (defined_default(this._promise)) {
return this._promise;
}
if (defined_default(this._spz)) {
this._promise = loadFromSpz(this);
return this._promise;
}
if (hasDracoCompression(this._draco, this._attributeSemantic)) {
this._promise = loadFromDraco2(this);
return this._promise;
}
this._promise = loadFromBufferView3(this);
return this._promise;
};
function getQuantizationInformation(dracoQuantization, componentDatatype, componentCount, type) {
const quantizationBits = dracoQuantization.quantizationBits;
const normalizationRange = (1 << quantizationBits) - 1;
const normalizationDivisor = 1 / normalizationRange;
const quantization = new ModelComponents_default.Quantization();
quantization.componentDatatype = componentDatatype;
quantization.octEncoded = dracoQuantization.octEncoded;
quantization.octEncodedZXY = true;
quantization.type = type;
if (quantization.octEncoded) {
quantization.type = AttributeType_default.VEC2;
quantization.normalizationRange = normalizationRange;
} else {
const MathType = AttributeType_default.getMathType(type);
if (MathType === Number) {
const dimensions = dracoQuantization.range;
quantization.quantizedVolumeOffset = dracoQuantization.minValues[0];
quantization.quantizedVolumeDimensions = dimensions;
quantization.normalizationRange = normalizationRange;
quantization.quantizedVolumeStepSize = dimensions * normalizationDivisor;
} else {
quantization.quantizedVolumeOffset = MathType.unpack(
dracoQuantization.minValues
);
quantization.normalizationRange = MathType.unpack(
new Array(componentCount).fill(normalizationRange)
);
const packedDimensions = new Array(componentCount).fill(
dracoQuantization.range
);
quantization.quantizedVolumeDimensions = MathType.unpack(packedDimensions);
const packedSteps = packedDimensions.map(function(dimension) {
return dimension * normalizationDivisor;
});
quantization.quantizedVolumeStepSize = MathType.unpack(packedSteps);
}
}
return quantization;
}
async function loadFromSpz(vertexBufferLoader) {
vertexBufferLoader._state = ResourceLoaderState_default.LOADING;
const resourceCache = vertexBufferLoader._resourceCache;
try {
const spzLoader = resourceCache.getSpzLoader({
gltf: vertexBufferLoader._gltf,
primitive: vertexBufferLoader._primitive,
spz: vertexBufferLoader._spz,
gltfResource: vertexBufferLoader._gltfResource,
baseResource: vertexBufferLoader._baseResource
});
vertexBufferLoader._spzLoader = spzLoader;
await spzLoader.load();
if (vertexBufferLoader.isDestroyed()) {
return;
}
vertexBufferLoader._state = ResourceLoaderState_default.LOADED;
return vertexBufferLoader;
} catch {
if (vertexBufferLoader.isDestroyed()) {
return;
}
}
}
function getShAttributePrefix(attribute) {
const prefix = attribute.startsWith("KHR_gaussian_splatting:") ? "KHR_gaussian_splatting:" : "_";
return `${prefix}SH_DEGREE_`;
}
function extractSHDegreeAndCoef(attribute) {
const prefix = getShAttributePrefix(attribute);
const separator = "_COEF_";
const lStart = prefix.length;
const coefIndex = attribute.indexOf(separator, lStart);
const l = parseInt(attribute.slice(lStart, coefIndex), 10);
const n = parseInt(attribute.slice(coefIndex + separator.length), 10);
return { l, n };
}
function processSpz(vertexBufferLoader) {
vertexBufferLoader._state = ResourceLoaderState_default.PROCESSING;
const spzLoader = vertexBufferLoader._spzLoader;
const gcloudData = spzLoader.decodedData.gcloud;
if (vertexBufferLoader._attributeSemantic === "POSITION") {
vertexBufferLoader._typedArray = gcloudData.positions;
} else if (vertexBufferLoader._attributeSemantic === "KHR_gaussian_splatting:SCALE" || vertexBufferLoader._attributeSemantic === "_SCALE") {
vertexBufferLoader._typedArray = gcloudData.scales;
} else if (vertexBufferLoader._attributeSemantic === "KHR_gaussian_splatting:ROTATION" || vertexBufferLoader._attributeSemantic === "_ROTATION") {
vertexBufferLoader._typedArray = gcloudData.rotations;
} else if (vertexBufferLoader._attributeSemantic === "COLOR_0") {
const colors = gcloudData.colors;
const alphas = gcloudData.alphas;
vertexBufferLoader._typedArray = new Uint8Array(colors.length / 3 * 4);
for (let i = 0; i < colors.length / 3; i++) {
vertexBufferLoader._typedArray[i * 4] = Math_default.clamp(
colors[i * 3] * 255,
0,
255
);
vertexBufferLoader._typedArray[i * 4 + 1] = Math_default.clamp(
colors[i * 3 + 1] * 255,
0,
255
);
vertexBufferLoader._typedArray[i * 4 + 2] = Math_default.clamp(
colors[i * 3 + 2] * 255,
0,
255
);
vertexBufferLoader._typedArray[i * 4 + 3] = Math_default.clamp(
alphas[i] * 255,
0,
255
);
}
} else if (vertexBufferLoader._attributeSemantic.includes("SH_DEGREE_")) {
const { l, n } = extractSHDegreeAndCoef(
vertexBufferLoader._attributeSemantic
);
const sphericalHarmonicDegree = gcloudData.shDegree;
let stride = 0;
const base = [0, 9, 24];
switch (sphericalHarmonicDegree) {
case 1:
stride = 9;
break;
case 2:
stride = 24;
break;
case 3:
stride = 45;
break;
}
const count = gcloudData.numPoints;
const sh = gcloudData.sh;
vertexBufferLoader._typedArray = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
const idx = i * stride + base[l - 1] + n * 3;
vertexBufferLoader._typedArray[i * 3] = sh[idx];
vertexBufferLoader._typedArray[i * 3 + 1] = sh[idx + 1];
vertexBufferLoader._typedArray[i * 3 + 2] = sh[idx + 2];
}
}
}
async function loadFromDraco2(vertexBufferLoader) {
vertexBufferLoader._state = ResourceLoaderState_default.LOADING;
const resourceCache = vertexBufferLoader._resourceCache;
try {
const dracoLoader = resourceCache.getDracoLoader({
gltf: vertexBufferLoader._gltf,
primitive: vertexBufferLoader._primitive,
draco: vertexBufferLoader._draco,
gltfResource: vertexBufferLoader._gltfResource,
baseResource: vertexBufferLoader._baseResource
});
vertexBufferLoader._dracoLoader = dracoLoader;
await dracoLoader.load();
if (vertexBufferLoader.isDestroyed()) {
return;
}
vertexBufferLoader._state = ResourceLoaderState_default.LOADED;
return vertexBufferLoader;
} catch {
if (vertexBufferLoader.isDestroyed()) {
return;
}
handleError5(vertexBufferLoader);
}
}
function processDraco(vertexBufferLoader) {
vertexBufferLoader._state = ResourceLoaderState_default.PROCESSING;
const dracoLoader = vertexBufferLoader._dracoLoader;
const decodedVertexAttributes = dracoLoader.decodedData.vertexAttributes;
const attributeSemantic = vertexBufferLoader._attributeSemantic;
const dracoAttribute = decodedVertexAttributes[attributeSemantic];
const accessorId = vertexBufferLoader._accessorId;
const accessor = vertexBufferLoader._gltf.accessors[accessorId];
const type = accessor.type;
const typedArray = dracoAttribute.array;
const dracoQuantization = dracoAttribute.data.quantization;
if (defined_default(dracoQuantization)) {
vertexBufferLoader._quantization = getQuantizationInformation(
dracoQuantization,
dracoAttribute.data.componentDatatype,
dracoAttribute.data.componentsPerAttribute,
type
);
}
vertexBufferLoader._typedArray = new Uint8Array(
typedArray.buffer,
typedArray.byteOffset,
typedArray.byteLength
);
}
async function loadFromBufferView3(vertexBufferLoader) {
vertexBufferLoader._state = ResourceLoaderState_default.LOADING;
const resourceCache = vertexBufferLoader._resourceCache;
try {
const bufferViewLoader = resourceCache.getBufferViewLoader({
gltf: vertexBufferLoader._gltf,
bufferViewId: vertexBufferLoader._bufferViewId,
gltfResource: vertexBufferLoader._gltfResource,
baseResource: vertexBufferLoader._baseResource
});
vertexBufferLoader._bufferViewLoader = bufferViewLoader;
await bufferViewLoader.load();
if (vertexBufferLoader.isDestroyed()) {
return;
}
vertexBufferLoader._typedArray = bufferViewLoader.typedArray;
vertexBufferLoader._state = ResourceLoaderState_default.PROCESSING;
return vertexBufferLoader;
} catch (error) {
if (vertexBufferLoader.isDestroyed()) {
return;
}
handleError5(vertexBufferLoader, error);
}
}
function handleError5(vertexBufferLoader, error) {
vertexBufferLoader.unload();
vertexBufferLoader._state = ResourceLoaderState_default.FAILED;
const errorMessage = "Failed to load vertex buffer";
throw vertexBufferLoader.getError(errorMessage, error);
}
function CreateVertexBufferJob() {
this.typedArray = void 0;
this.context = void 0;
this.buffer = void 0;
}
CreateVertexBufferJob.prototype.set = function(typedArray, context) {
this.typedArray = typedArray;
this.context = context;
};
CreateVertexBufferJob.prototype.execute = function() {
this.buffer = createVertexBuffer(this.typedArray, this.context);
};
function createVertexBuffer(typedArray, context) {
const buffer2 = Buffer_default.createVertexBuffer({
typedArray,
context,
usage: BufferUsage_default.STATIC_DRAW
});
buffer2.vertexArrayDestroyable = false;
return buffer2;
}
var scratchVertexBufferJob = new CreateVertexBufferJob();
GltfVertexBufferLoader.prototype.process = function(frameState) {
Check_default.typeOf.object("frameState", frameState);
if (this._state === ResourceLoaderState_default.READY) {
return true;
}
if (this._state !== ResourceLoaderState_default.LOADED && this._state !== ResourceLoaderState_default.PROCESSING) {
return false;
}
if (defined_default(this._dracoLoader)) {
try {
const ready = this._dracoLoader.process(frameState);
if (!ready) {
return false;
}
} catch (error) {
handleError5(this, error);
}
processDraco(this);
}
if (defined_default(this._spzLoader)) {
try {
const ready = this._spzLoader.process(frameState);
if (!ready) {
return false;
}
} catch (error) {
handleError5(this, error);
}
processSpz(this);
}
let buffer2;
const typedArray = this._typedArray;
if (this._loadBuffer && this._asynchronous) {
const vertexBufferJob = scratchVertexBufferJob;
vertexBufferJob.set(typedArray, frameState.context);
const jobScheduler = frameState.jobScheduler;
if (!jobScheduler.execute(vertexBufferJob, JobType_default.BUFFER)) {
return false;
}
buffer2 = vertexBufferJob.buffer;
} else if (this._loadBuffer) {
buffer2 = createVertexBuffer(typedArray, frameState.context);
}
this.unload();
this._buffer = buffer2;
this._typedArray = this._loadTypedArray ? typedArray : void 0;
this._state = ResourceLoaderState_default.READY;
this._resourceCache.statistics.addGeometryLoader(this);
return true;
};
GltfVertexBufferLoader.prototype.unload = function() {
if (defined_default(this._buffer)) {
this._buffer.destroy();
}
const resourceCache = this._resourceCache;
if (defined_default(this._bufferViewLoader) && !this._bufferViewLoader.isDestroyed()) {
resourceCache.unload(this._bufferViewLoader);
}
if (defined_default(this._dracoLoader)) {
resourceCache.unload(this._dracoLoader);
}
if (defined_default(this._spzLoader)) {
resourceCache.unload(this._spzLoader);
}
this._bufferViewLoader = void 0;
this._dracoLoader = void 0;
this._spzLoader = void 0;
this._typedArray = void 0;
this._buffer = void 0;
this._gltf = void 0;
this._primitive = void 0;
};
var GltfVertexBufferLoader_default = GltfVertexBufferLoader;
// packages/engine/Source/Scene/GltfSpzLoader.js
var import_InlineWorkers514 = __toESM(require_InlineWorkers(), 1);
// node_modules/@spz-loader/core/dist/index.js
var import_InlineWorkers513 = __toESM(require_InlineWorkers(), 1);
var import_meta2 = {};
async function TI(R = {}) {
var DI;
var s, i = R, L = typeof window == "object", k = typeof WorkerGlobalScope < "u", f = typeof process == "object" && ((DI = process.versions) == null ? void 0 : DI.node) && process.type != "renderer";
if (f) {
const { createRequire: I } = await Promise.resolve().then(() => bI);
var r = I(import_meta2.url);
}
var x = "./this.program", p = import_meta2.url, $;
if (f) {
var wI = r("fs");
p.startsWith("file:") && r("path").dirname(r("url").fileURLToPath(p)), $ = (I) => (I = oI(I) ? new URL(I) : I, wI.readFileSync(I)), 1 < process.argv.length && (x = process.argv[1].replace(/\\/g, "/")), process.argv.slice(2);
} else if (L || k) {
try {
new URL(".", p);
} catch {
}
k && ($ = (I) => {
var A = new XMLHttpRequest();
return A.open("GET", I, false), A.responseType = "arraybuffer", A.send(null), new Uint8Array(A.response);
});
}
var qA = console.log.bind(console), _ = console.error.bind(console), GA, fA = false, oI = (I) => I.startsWith("file://"), AA, IA, gA, BA, c, O, P, W, a3, eA, dA, lA, xA, WA = false;
function ZA() {
var I = gA.buffer;
BA = new Int8Array(I), O = new Int16Array(I), i.HEAPU8 = c = new Uint8Array(I), P = new Uint16Array(I), W = new Int32Array(I), a3 = new Uint32Array(I), i.HEAPF32 = eA = new Float32Array(I), dA = new Float64Array(I), lA = new BigInt64Array(I), xA = new BigUint64Array(I);
}
var e = 0, u3 = null;
function jA(I) {
var A;
throw (A = i.onAbort) == null || A.call(i, I), I = "Aborted(" + I + ")", _(I), fA = true, I = new WebAssembly.RuntimeError(I + ". Build with -sASSERTIONS for more info."), IA == null || IA(I), I;
}
var RA;
async function FI(I) {
if (!ArrayBuffer.isView(I)) if (I == RA && GA) I = new Uint8Array(GA);
else if ($) I = $(I);
else throw "both async and sync fetching of the wasm failed";
return I;
}
async function GI(I) {
var A = RA;
try {
var g = await FI(A);
return await WebAssembly.instantiate(g, I);
} catch (B) {
_(`failed to asynchronously prepare wasm: ${B}`), jA(B);
}
}
async function RI(I) {
return GI(I);
}
var VA = (I) => {
for (; 0 < I.length; ) I.shift()(i);
}, XA = [], TA = [], sI = () => {
var I = i.preRun.shift();
TA.push(I);
}, yI = (I) => {
if (f) return I = Buffer.from(I, "base64"), new Uint8Array(I.buffer, I.byteOffset, I.length);
for (var A, g, B = 0, Q = 0, E = I.length, C = new Uint8Array((3 * E >> 2) - (I[E - 2] == "=") - (I[E - 1] == "=")); B < E; B += 4, Q += 3) A = t[I.charCodeAt(B + 1)], g = t[I.charCodeAt(B + 2)], C[Q] = t[I.charCodeAt(B)] << 2 | A >> 4, C[Q + 1] = A << 4 | g >> 2, C[Q + 2] = g << 6 | t[I.charCodeAt(B + 3)];
return C;
}, QA = {}, sA = (I) => {
for (; I.length; ) {
var A = I.pop();
I.pop()(A);
}
};
function m(I) {
return this.N(a3[I >> 2]);
}
var Z = {}, d = {}, CA = {}, EA = class extends Error {
constructor(I) {
super(I), this.name = "InternalError";
}
}, l = (I, A, g) => {
function B(D) {
if (D = g(D), D.length !== I.length) throw new EA("Mismatched type converter count");
for (var o = 0; o < I.length; ++o) J(I[o], D[o]);
}
I.forEach((D) => CA[D] = A);
var Q = Array(A.length), E = [], C = 0;
A.forEach((D, o) => {
d.hasOwnProperty(D) ? Q[o] = d[D] : (E.push(D), Z.hasOwnProperty(D) || (Z[D] = []), Z[D].push(() => {
Q[o] = d[D], ++C, C === E.length && B(Q);
}));
}), E.length === 0 && B(Q);
}, h = (I) => {
for (var A = ""; ; ) {
var g = c[I++];
if (!g) return A;
A += String.fromCharCode(g);
}
}, G = class extends Error {
constructor(I) {
super(I), this.name = "BindingError";
}
}, aI = (I) => {
throw new G(I);
};
function hI(I, A, g = {}) {
var B = A.name;
if (!I) throw new G(`type "${B}" must have a positive integer typeid pointer`);
if (d.hasOwnProperty(I)) {
if (g.wa) return;
throw new G(`Cannot register type '${B}' twice`);
}
d[I] = A, delete CA[I], Z.hasOwnProperty(I) && (A = Z[I], delete Z[I], A.forEach((Q) => Q()));
}
function J(I, A, g = {}) {
return hI(I, A, g);
}
var pA = (I, A, g) => {
switch (A) {
case 1:
return g ? (B) => BA[B] : (B) => c[B];
case 2:
return g ? (B) => O[B >> 1] : (B) => P[B >> 1];
case 4:
return g ? (B) => W[B >> 2] : (B) => a3[B >> 2];
case 8:
return g ? (B) => lA[B >> 3] : (B) => xA[B >> 3];
default:
throw new TypeError(`invalid integer width (${A}): ${I}`);
}
}, yA = (I) => {
throw new G(I.L.P.M.name + " instance already deleted");
}, aA = false, OA = () => {
}, b = (I) => typeof FinalizationRegistry > "u" ? (b = (A) => A, I) : (aA = new FinalizationRegistry((A) => {
A = A.L, --A.count.value, A.count.value === 0 && (A.S ? A.W.Y(A.S) : A.P.M.Y(A.O));
}), b = (A) => {
var g = A.L;
return g.S && aA.register(A, { L: g }, A), A;
}, OA = (A) => {
aA.unregister(A);
}, b(I));
function DA() {
}
var iA = (I, A) => Object.defineProperty(A, "name", { value: I }), PA = {}, uA = (I, A, g) => {
if (I[A].R === void 0) {
var B = I[A];
I[A] = function(...Q) {
if (!I[A].R.hasOwnProperty(Q.length)) throw new G(`Function '${g}' called with an invalid number of arguments (${Q.length}) - expects one of (${I[A].R})!`);
return I[A].R[Q.length].apply(this, Q);
}, I[A].R = [], I[A].R[B.aa] = B;
}
}, hA = (I, A, g) => {
if (i.hasOwnProperty(I)) {
if (g === void 0 || i[I].R !== void 0 && i[I].R[g] !== void 0) throw new G(`Cannot register public name '${I}' twice`);
if (uA(i, I, I), i[I].R.hasOwnProperty(g)) throw new G(`Cannot register multiple overloads of a function with the same number of arguments (${g})!`);
i[I].R[g] = A;
} else i[I] = A, i[I].aa = g;
}, MI = (I) => {
I = I.replace(/[^a-zA-Z0-9_]/g, "$");
var A = I.charCodeAt(0);
return 48 <= A && 57 >= A ? `_${I}` : I;
};
function NI(I, A, g, B, Q, E, C, D) {
this.name = I, this.constructor = A, this.$ = g, this.Y = B, this.U = Q, this.ra = E, this.ea = C, this.pa = D, this.ya = [];
}
var MA = (I, A, g) => {
for (; A !== g; ) {
if (!A.ea) throw new G(`Expected null or instance of ${g.name}, got an instance of ${A.name}`);
I = A.ea(I), A = A.U;
}
return I;
}, NA = (I) => {
if (I === null) return "null";
var A = typeof I;
return A === "object" || A === "array" || A === "function" ? I.toString() : "" + I;
};
function UI(I, A) {
if (A === null) {
if (this.ha) throw new G(`null is not a valid ${this.name}`);
return 0;
}
if (!A.L) throw new G(`Cannot pass "${NA(A)}" as a ${this.name}`);
if (!A.L.O) throw new G(`Cannot pass deleted object as a pointer of type ${this.name}`);
return MA(A.L.O, A.L.P.M, this.M);
}
function SI(I, A) {
if (A === null) {
if (this.ha) throw new G(`null is not a valid ${this.name}`);
if (this.ga) {
var g = this.ia();
return I !== null && I.push(this.Y, g), g;
}
return 0;
}
if (!A || !A.L) throw new G(`Cannot pass "${NA(A)}" as a ${this.name}`);
if (!A.L.O) throw new G(`Cannot pass deleted object as a pointer of type ${this.name}`);
if (!this.fa && A.L.P.fa) throw new G(`Cannot convert argument of type ${A.L.W ? A.L.W.name : A.L.P.name} to parameter type ${this.name}`);
if (g = MA(A.L.O, A.L.P.M, this.M), this.ga) {
if (A.L.S === void 0) throw new G("Passing raw pointer to smart pointer is illegal");
switch (this.Da) {
case 0:
if (A.L.W === this) g = A.L.S;
else throw new G(`Cannot convert argument of type ${A.L.W ? A.L.W.name : A.L.P.name} to parameter type ${this.name}`);
break;
case 1:
g = A.L.S;
break;
case 2:
if (A.L.W === this) g = A.L.S;
else {
var B = A.clone();
g = this.za(g, LA(() => B.delete())), I !== null && I.push(this.Y, g);
}
break;
default:
throw new G("Unsupporting sharing policy");
}
}
return g;
}
function JI(I, A) {
if (A === null) {
if (this.ha) throw new G(`null is not a valid ${this.name}`);
return 0;
}
if (!A.L) throw new G(`Cannot pass "${NA(A)}" as a ${this.name}`);
if (!A.L.O) throw new G(`Cannot pass deleted object as a pointer of type ${this.name}`);
if (A.L.P.fa) throw new G(`Cannot convert argument of type ${A.L.P.name} to parameter type ${this.name}`);
return MA(A.L.O, A.L.P.M, this.M);
}
var mA = (I, A, g) => A === g ? I : g.U === void 0 ? null : (I = mA(I, A, g.U), I === null ? null : g.pa(I)), YI = {}, LI = (I, A) => {
if (A === void 0) throw new G("ptr should not be undefined");
for (; I.U; ) A = I.ea(A), I = I.U;
return YI[A];
}, wA = (I, A) => {
if (!A.P || !A.O) throw new EA("makeClassHandle requires ptr and ptrType");
if (!!A.W != !!A.S) throw new EA("Both smartPtrType and smartPtr must be specified");
return A.count = { value: 1 }, b(Object.create(I, { L: { value: A, writable: true } }));
};
function oA(I, A, g, B, Q, E, C, D, o, F, w) {
this.name = I, this.M = A, this.ha = g, this.fa = B, this.ga = Q, this.xa = E, this.Da = C, this.na = D, this.ia = o, this.za = F, this.Y = w, Q || A.U !== void 0 ? this.T = SI : (this.T = B ? UI : JI, this.V = null);
}
var bA = (I, A, g) => {
if (!i.hasOwnProperty(I)) throw new EA("Replacing nonexistent public symbol");
i[I].R !== void 0 && g !== void 0 ? i[I].R[g] = A : (i[I] = A, i[I].aa = g);
}, zA, H = (I, A) => {
I = h(I);
var g = zA.get(A);
if (typeof g != "function") throw new G(`unknown function pointer with signature ${I}: ${A}`);
return g;
};
class kI extends Error {
}
var vA = (I) => {
I = EI(I);
var A = h(I);
return q(I), A;
}, FA = (I, A) => {
function g(E) {
Q[E] || d[E] || (CA[E] ? CA[E].forEach(g) : (B.push(E), Q[E] = true));
}
var B = [], Q = {};
throw A.forEach(g), new kI(`${I}: ` + B.map(vA).join([", "]));
}, UA = (I, A) => {
for (var g = [], B = 0; B < I; B++) g.push(a3[A + 4 * B >> 2]);
return g;
};
function $A(I) {
for (var A = 1; A < I.length; ++A) if (I[A] !== null && I[A].V === void 0) return true;
return false;
}
function SA(I, A, g, B, Q, E) {
var C = A.length;
if (2 > C) throw new G("argTypes array size mismatch! Must at least get return value and 'this' types!");
var D = A[1] !== null && g !== null, o = $A(A);
g = !A[0].ma;
var F = A[0], w = A[1];
for (B = [I, aI, B, Q, sA, F.N.bind(F), w == null ? void 0 : w.T.bind(w)], Q = 2; Q < C; ++Q) F = A[Q], B.push(F.T.bind(F));
if (!o) for (Q = D ? 1 : 2; Q < A.length; ++Q) A[Q].V !== null && B.push(A[Q].V);
for (o = $A(A), Q = A.length - 2, w = [], F = ["fn"], D && F.push("thisWired"), C = 0; C < Q; ++C) w.push(`arg${C}`), F.push(`arg${C}Wired`);
w = w.join(","), F = F.join(","), w = `return function (${w}) {
`, o && (w += `var destructors = [];
`);
var y = o ? "destructors" : "null", U = "humanName throwBindingError invoker fn runDestructors fromRetWire toClassParamWire".split(" ");
for (D && (w += `var thisWired = toClassParamWire(${y}, this);
`), C = 0; C < Q; ++C) {
var M = `toArg${C}Wire`;
w += `var arg${C}Wired = ${M}(${y}, arg${C});
`, U.push(M);
}
if (w += (g || E ? "var rv = " : "") + `invoker(${F});
`, o) w += `runDestructors(destructors);
`;
else for (C = D ? 1 : 2; C < A.length; ++C) E = C === 1 ? "thisWired" : "arg" + (C - 2) + "Wired", A[C].V !== null && (w += `${E}_dtor(${E});
`, U.push(`${E}_dtor`));
return g && (w += `var ret = fromRetWire(rv);
return ret;
`), A = new Function(U, w + `}
`)(...B), iA(I, A);
}
for (var _A = (I) => {
I = I.trim();
const A = I.indexOf("(");
return A === -1 ? I : I.slice(0, A);
}, AI = [], j = [0, 1, , 1, null, 1, true, 1, false, 1], JA = (I) => {
9 < I && --j[I + 1] === 0 && (j[I] = void 0, AI.push(I));
}, YA = (I) => {
if (!I) throw new G(`Cannot use deleted val. handle = ${I}`);
return j[I];
}, LA = (I) => {
switch (I) {
case void 0:
return 2;
case null:
return 4;
case true:
return 6;
case false:
return 8;
default:
const A = AI.pop() || j.length;
return j[A] = I, j[A + 1] = 1, A;
}
}, II = { name: "emscripten::val", N: (I) => {
var A = YA(I);
return JA(I), A;
}, T: (I, A) => LA(A), X: m, V: null }, cI = (I, A, g) => {
switch (A) {
case 1:
return g ? function(B) {
return this.N(BA[B]);
} : function(B) {
return this.N(c[B]);
};
case 2:
return g ? function(B) {
return this.N(O[B >> 1]);
} : function(B) {
return this.N(P[B >> 1]);
};
case 4:
return g ? function(B) {
return this.N(W[B >> 2]);
} : function(B) {
return this.N(a3[B >> 2]);
};
default:
throw new TypeError(`invalid integer width (${A}): ${I}`);
}
}, gI = (I, A) => {
var g = d[I];
if (g === void 0) throw I = `${A} has unknown type ${vA(I)}`, new G(I);
return g;
}, HI = (I, A) => {
switch (A) {
case 4:
return function(g) {
return this.N(eA[g >> 2]);
};
case 8:
return function(g) {
return this.N(dA[g >> 3]);
};
default:
throw new TypeError(`invalid float width (${A}): ${I}`);
}
}, tI = Object.assign({ optional: true }, II), V = (I, A, g) => {
var B = c;
if (!(0 < g)) return 0;
var Q = A;
g = A + g - 1;
for (var E = 0; E < I.length; ++E) {
var C = I.codePointAt(E);
if (127 >= C) {
if (A >= g) break;
B[A++] = C;
} else if (2047 >= C) {
if (A + 1 >= g) break;
B[A++] = 192 | C >> 6, B[A++] = 128 | C & 63;
} else if (65535 >= C) {
if (A + 2 >= g) break;
B[A++] = 224 | C >> 12, B[A++] = 128 | C >> 6 & 63, B[A++] = 128 | C & 63;
} else {
if (A + 3 >= g) break;
B[A++] = 240 | C >> 18, B[A++] = 128 | C >> 12 & 63, B[A++] = 128 | C >> 6 & 63, B[A++] = 128 | C & 63, E++;
}
}
return B[A] = 0, A - Q;
}, BI = (I) => {
for (var A = 0, g = 0; g < I.length; ++g) {
var B = I.charCodeAt(g);
127 >= B ? A++ : 2047 >= B ? A += 2 : 55296 <= B && 57343 >= B ? (A += 4, ++g) : A += 3;
}
return A;
}, QI = new TextDecoder(), kA = (I, A, g, B) => {
if (g = A + g, B) return g;
for (; I[A] && !(A >= g); ) ++A;
return A;
}, KI = new TextDecoder("utf-16le"), rI = (I, A, g) => (I >>= 1, KI.decode(P.subarray(I, kA(P, I, A / 2, g)))), nI = (I, A, g) => {
if (g ?? (g = 2147483647), 2 > g) return 0;
g -= 2;
var B = A;
g = g < 2 * I.length ? g / 2 : I.length;
for (var Q = 0; Q < g; ++Q) O[A >> 1] = I.charCodeAt(Q), A += 2;
return O[A >> 1] = 0, A - B;
}, qI = (I) => 2 * I.length, fI = (I, A, g) => {
var B = "";
I >>= 2;
for (var Q = 0; !(Q >= A / 4); Q++) {
var E = a3[I + Q];
if (!E && !g) break;
B += String.fromCodePoint(E);
}
return B;
}, eI = (I, A, g) => {
if (g ?? (g = 2147483647), 4 > g) return 0;
var B = A;
g = B + g - 4;
for (var Q = 0; Q < I.length; ++Q) {
var E = I.codePointAt(Q);
if (65535 < E && Q++, W[A >> 2] = E, A += 4, A + 4 > g) break;
}
return W[A >> 2] = 0, A - B;
}, dI = (I) => {
for (var A = 0, g = 0; g < I.length; ++g) 65535 < I.codePointAt(g) && g++, A += 4;
return A;
}, cA = [], lI = (I) => {
var A = cA.length;
return cA.push(I), A;
}, xI = (I, A) => {
for (var g = Array(I), B = 0; B < I; ++B) g[B] = gI(a3[A + 4 * B >> 2], `parameter ${B}`);
return g;
}, WI = (I, A, g) => {
var B = [];
return I = I(B, g), B.length && (a3[A >> 2] = LA(B)), I;
}, ZI = {}, jI = (I) => {
var A = ZI[I];
return A === void 0 ? h(I) : A;
}, HA = {}, CI = () => {
if (!tA) {
var I = { USER: "web_user", LOGNAME: "web_user", PATH: "/", PWD: "/", HOME: "/home/web_user", LANG: (typeof navigator == "object" && navigator.language || "C").replace("-", "_") + ".UTF-8", _: x || "./this.program" }, A;
for (A in HA) HA[A] === void 0 ? delete I[A] : I[A] = HA[A];
var g = [];
for (A in I) g.push(`${A}=${I[A]}`);
tA = g;
}
return tA;
}, tA, VI = [null, [], []], t = new Uint8Array(123), n = 25; 0 <= n; --n) t[48 + n] = 52 + n, t[65 + n] = n, t[97 + n] = 26 + n;
t[43] = 62, t[47] = 63, (() => {
let I = DA.prototype;
Object.assign(I, { isAliasOf: function(g) {
if (!(this instanceof DA && g instanceof DA)) return false;
var B = this.L.P.M, Q = this.L.O;
g.L = g.L;
var E = g.L.P.M;
for (g = g.L.O; B.U; ) Q = B.ea(Q), B = B.U;
for (; E.U; ) g = E.ea(g), E = E.U;
return B === E && Q === g;
}, clone: function() {
if (this.L.O || yA(this), this.L.da) return this.L.count.value += 1, this;
var g = b, B = Object, Q = B.create, E = Object.getPrototypeOf(this), C = this.L;
return g = g(Q.call(B, E, { L: { value: { count: C.count, ba: C.ba, da: C.da, O: C.O, P: C.P, S: C.S, W: C.W } } })), g.L.count.value += 1, g.L.ba = false, g;
}, delete() {
if (this.L.O || yA(this), this.L.ba && !this.L.da) throw new G("Object already scheduled for deletion");
OA(this);
var g = this.L;
--g.count.value, g.count.value === 0 && (g.S ? g.W.Y(g.S) : g.P.M.Y(g.O)), this.L.da || (this.L.S = void 0, this.L.O = void 0);
}, isDeleted: function() {
return !this.L.O;
}, deleteLater: function() {
if (this.L.O || yA(this), this.L.ba && !this.L.da) throw new G("Object already scheduled for deletion");
return this.L.ba = true, this;
} });
const A = Symbol.dispose;
A && (I[A] = I.delete);
})(), Object.assign(oA.prototype, { sa(I) {
return this.na && (I = this.na(I)), I;
}, ka(I) {
var A;
(A = this.Y) == null || A.call(this, I);
}, X: m, N: function(I) {
function A() {
return this.ga ? wA(this.M.$, { P: this.xa, O: g, W: this, S: I }) : wA(this.M.$, { P: this, O: I });
}
var g = this.sa(I);
if (!g) return this.ka(I), null;
var B = LI(this.M, g);
if (B !== void 0)
return B.L.count.value === 0 ? (B.L.O = g, B.L.S = I, B.clone()) : (B = B.clone(), this.ka(I), B);
if (B = this.M.ra(g), B = PA[B], !B) return A.call(this);
B = this.fa ? B.oa : B.pointerType;
var Q = mA(g, this.M, B.M);
return Q === null ? A.call(this) : this.ga ? wA(B.M.$, { P: B, O: Q, W: this, S: I }) : wA(B.M.$, { P: B, O: Q });
} }), i.print && (qA = i.print), i.printErr && (_ = i.printErr), i.wasmBinary && (GA = i.wasmBinary), i.thisProgram && (x = i.thisProgram);
var EI, KA, q, XI = { x: () => jA(""), q: (I) => {
var A = QA[I];
delete QA[I];
var g = A.ia, B = A.Y, Q = A.la, E = Q.map((C) => C.va).concat(Q.map((C) => C.Ba));
l([I], E, (C) => {
var D = {};
return Q.forEach((o, F) => {
var w = C[F], y = o.ta, U = o.ua, M = C[F + Q.length], N = o.Aa, Y = o.Ca;
D[o.qa] = { read: (K) => w.N(y(U, K)), write: (K, z) => {
var S = [];
N(Y, K, M.T(S, z)), sA(S);
}, optional: C[F].optional };
}), [{ name: A.name, N: (o) => {
var F = {}, w;
for (w in D) F[w] = D[w].read(o);
return B(o), F;
}, T: (o, F) => {
for (var w in D) if (!(w in F || D[w].optional)) throw new TypeError(`Missing field: "${w}"`);
var y = g();
for (w in D) D[w].write(y, F[w]);
return o !== null && o.push(B, y), y;
}, X: m, V: B }];
});
}, n: (I, A, g, B, Q) => {
A = h(A), B = B === 0n;
let E = (C) => C;
if (B) {
const C = 8 * g;
E = (D) => BigInt.asUintN(C, D), Q = E(Q);
}
J(I, { name: A, N: E, T: (C, D) => (typeof D == "number" && (D = BigInt(D)), D), X: pA(A, g, !B), V: null });
}, B: (I, A, g, B) => {
A = h(A), J(I, { name: A, N: function(Q) {
return !!Q;
}, T: function(Q, E) {
return E ? g : B;
}, X: function(Q) {
return this.N(c[Q]);
}, V: null });
}, j: (I, A, g, B, Q, E, C, D, o, F, w, y, U) => {
w = h(w), E = H(Q, E), D && (D = H(C, D)), F && (F = H(o, F)), U = H(y, U);
var M = MI(w);
hA(M, function() {
FA(
`Cannot construct ${w} due to unbound types`,
[B]
);
}), l([I, A, g], B ? [B] : [], (N) => {
if (N = N[0], B)
var Y = N.M, K = Y.$;
else K = DA.prototype;
N = iA(w, function(...nA) {
if (Object.getPrototypeOf(this) !== z) throw new G(`Use 'new' to construct ${w}`);
if (S.Z === void 0) throw new G(`${w} has no accessible constructor`);
var iI = S.Z[nA.length];
if (iI === void 0) throw new G(`Tried to invoke ctor of ${w} with invalid number of parameters (${nA.length}) - expected (${Object.keys(S.Z).toString()}) parameters instead!`);
return iI.apply(this, nA);
});
var z = Object.create(K, { constructor: { value: N } });
N.prototype = z;
var S = new NI(w, N, z, U, Y, E, D, F);
if (S.U) {
var v3;
(v3 = S.U).ja ?? (v3.ja = []), S.U.ja.push(S);
}
return Y = new oA(w, S, true, false, false), v3 = new oA(w + "*", S, false, false, false), K = new oA(w + " const*", S, false, true, false), PA[I] = { pointerType: v3, oa: K }, bA(M, N), [Y, v3, K];
});
}, g: (I, A, g, B, Q, E) => {
var C = UA(A, g);
Q = H(B, Q), l([], [I], (D) => {
D = D[0];
var o = `constructor ${D.name}`;
if (D.M.Z === void 0 && (D.M.Z = []), D.M.Z[A - 1] !== void 0) throw new G(`Cannot register multiple constructors with identical number of parameters (${A - 1}) for class '${D.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`);
return D.M.Z[A - 1] = () => {
FA(`Cannot construct ${D.name} due to unbound types`, C);
}, l([], C, (F) => (F.splice(1, 0, null), D.M.Z[A - 1] = SA(o, F, null, Q, E), [])), [];
});
}, b: (I, A, g, B, Q, E, C, D, o) => {
var F = UA(g, B);
A = h(A), A = _A(A), E = H(Q, E), l([], [I], (w) => {
function y() {
FA(`Cannot call ${U} due to unbound types`, F);
}
w = w[0];
var U = `${w.name}.${A}`;
A.startsWith("@@") && (A = Symbol[A.substring(2)]), D && w.M.ya.push(A);
var M = w.M.$, N = M[A];
return N === void 0 || N.R === void 0 && N.className !== w.name && N.aa === g - 2 ? (y.aa = g - 2, y.className = w.name, M[A] = y) : (uA(
M,
A,
U
), M[A].R[g - 2] = y), l([], F, (Y) => (Y = SA(U, Y, w, E, C, o), M[A].R === void 0 ? (Y.aa = g - 2, M[A] = Y) : M[A].R[g - 2] = Y, [])), [];
});
}, z: (I) => J(I, II), r: (I, A, g, B) => {
function Q() {
}
A = h(A), Q.values = {}, J(I, { name: A, constructor: Q, N: function(E) {
return this.constructor.values[E];
}, T: (E, C) => C.value, X: cI(A, g, B), V: null }), hA(A, Q);
}, d: (I, A, g) => {
var B = gI(I, "enum");
A = h(A), I = B.constructor, B = Object.create(B.constructor.prototype, { value: { value: g }, constructor: { value: iA(`${B.name}_${A}`, function() {
}) } }), I.values[g] = B, I[A] = B;
}, m: (I, A, g) => {
A = h(A), J(I, { name: A, N: (B) => B, T: (B, Q) => Q, X: HI(A, g), V: null });
}, l: (I, A, g, B, Q, E, C) => {
var D = UA(A, g);
I = h(I), I = _A(I), Q = H(B, Q), hA(I, function() {
FA(`Cannot call ${I} due to unbound types`, D);
}, A - 1), l([], D, (o) => (o = [o[0], null].concat(o.slice(1)), bA(I, SA(I, o, null, Q, E, C), A - 1), []));
}, c: (I, A, g, B, Q) => {
A = h(A);
let E = (D) => D;
if (B === 0) {
var C = 32 - 8 * g;
E = (D) => D << C >>> C, Q = E(Q);
}
J(I, { name: A, N: E, T: (D, o) => o, X: pA(A, g, B !== 0), V: null });
}, a: (I, A, g) => {
function B(E) {
return new Q(BA.buffer, a3[E + 4 >> 2], a3[E >> 2]);
}
var Q = [
Int8Array,
Uint8Array,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array,
BigInt64Array,
BigUint64Array
][A];
g = h(g), J(I, { name: g, N: B, X: B }, { wa: true });
}, h: (I) => {
J(I, tI);
}, A: (I, A) => {
A = h(A), J(I, { name: A, N(g) {
var B = (B = g + 4) ? QI.decode(c.subarray(B, kA(c, B, a3[g >> 2], true))) : "";
return q(g), B;
}, T(g, B) {
B instanceof ArrayBuffer && (B = new Uint8Array(B));
var Q = typeof B == "string";
if (!(Q || ArrayBuffer.isView(B) && B.BYTES_PER_ELEMENT == 1)) throw new G("Cannot pass non-string to std::string");
var E = Q ? BI(B) : B.length, C = KA(4 + E + 1), D = C + 4;
return a3[C >> 2] = E, Q ? V(B, D, E + 1) : c.set(B, D), g !== null && g.push(q, C), C;
}, X: m, V(g) {
q(g);
} });
}, f: (I, A, g) => {
if (g = h(g), A === 2)
var B = rI, Q = nI, E = qI;
else B = fI, Q = eI, E = dI;
J(I, { name: g, N: (C) => {
var D = B(C + 4, a3[C >> 2] * A, true);
return q(C), D;
}, T: (C, D) => {
if (typeof D != "string") throw new G(`Cannot pass non-string to C++ string type ${g}`);
var o = E(D), F = KA(4 + o + A);
return a3[F >> 2] = o / A, Q(D, F + 4, o + A), C !== null && C.push(q, F), F;
}, X: m, V(C) {
q(C);
} });
}, i: (I, A, g, B, Q, E) => {
QA[I] = { name: h(A), ia: H(g, B), Y: H(Q, E), la: [] };
}, e: (I, A, g, B, Q, E, C, D, o, F) => {
QA[I].la.push({
qa: h(A),
va: g,
ta: H(B, Q),
ua: E,
Ba: C,
Aa: H(D, o),
Ca: F
});
}, C: (I, A) => {
A = h(A), J(I, { ma: true, name: A, N: () => {
}, T: () => {
} });
}, p: (I, A, g) => {
var [B, ...Q] = xI(I, A);
A = B.T.bind(B);
var E = Q.map((o) => o.X.bind(o));
I--;
var C = { toValue: YA };
switch (I = E.map((o, F) => {
var w = `argFromPtr${F}`;
return C[w] = o, `${w}(args${F ? "+" + 8 * F : ""})`;
}), g) {
case 0:
var D = "toValue(handle)";
break;
case 2:
D = "new (toValue(handle))";
break;
case 3:
D = "";
break;
case 1:
C.getStringOrSymbol = jI, D = "toValue(handle)[getStringOrSymbol(methodName)]";
}
return D += `(${I})`, B.ma || (C.toReturnWire = A, C.emval_returnValue = WI, D = `return emval_returnValue(toReturnWire, destructorsRef, ${D})`), D = `return function (handle, methodName, destructorsRef, args) {
${D}
}`, g = new Function(Object.keys(C), D)(...Object.values(C)), D = `methodCaller<(${Q.map((o) => o.name)}) => ${B.name}>`, lI(iA(D, g));
}, E: JA, o: (I, A, g, B, Q) => cA[I](A, g, B, Q), D: (I) => {
var A = YA(I);
sA(A), JA(I);
}, s: (I, A, g, B) => {
var Q = (/* @__PURE__ */ new Date()).getFullYear(), E = new Date(Q, 0, 1).getTimezoneOffset();
Q = new Date(Q, 6, 1).getTimezoneOffset(), a3[I >> 2] = 60 * Math.max(E, Q), W[A >> 2] = +(E != Q), A = (C) => {
var D = Math.abs(C);
return `UTC${0 <= C ? "-" : "+"}${String(Math.floor(D / 60)).padStart(2, "0")}${String(D % 60).padStart(2, "0")}`;
}, I = A(E), A = A(Q), Q < E ? (V(I, g, 17), V(A, B, 17)) : (V(I, B, 17), V(A, g, 17));
}, y: (I) => {
var A = c.length;
if (I >>>= 0, 2147483648 < I) return false;
for (var g = 1; 4 >= g; g *= 2) {
var B = A * (1 + 0.2 / g);
B = Math.min(B, I + 100663296);
A: {
B = (Math.min(2147483648, 65536 * Math.ceil(Math.max(I, B) / 65536)) - gA.buffer.byteLength + 65535) / 65536 | 0;
try {
gA.grow(B), ZA();
var Q = 1;
break A;
} catch {
}
Q = void 0;
}
if (Q) return true;
}
return false;
}, t: (I, A) => {
var g = 0, B = 0, Q;
for (Q of CI()) {
var E = A + g;
a3[I + B >> 2] = E, g += V(Q, E, 1 / 0) + 1, B += 4;
}
return 0;
}, u: (I, A) => {
var g = CI();
a3[I >> 2] = g.length, I = 0;
for (var B of g) I += BI(B) + 1;
return a3[A >> 2] = I, 0;
}, v: () => 52, w: function() {
return 70;
}, k: (I, A, g, B) => {
for (var Q = 0, E = 0; E < g; E++) {
var C = a3[A >> 2], D = a3[A + 4 >> 2];
A += 8;
for (var o = 0; o < D; o++) {
var F = I, w = c[C + o], y = VI[F];
w === 0 || w === 10 ? (F = F === 1 ? qA : _, w = kA(y, 0), w = QI.decode(y.buffer ? y.subarray(0, w) : new Uint8Array(y.slice(0, w))), F(w), y.length = 0) : y.push(w);
}
Q += D;
}
return a3[B >> 2] = Q, 0;
} }, X = await (async function() {
var g;
function I(B) {
var Q;
return X = B.exports, gA = X.F, ZA(), zA = X.H, B = X, EI = B.I, i._malloc = KA = B.J, i._free = q = B.K, e--, (Q = i.monitorRunDependencies) == null || Q.call(i, e), e == 0 && u3 && (B = u3, u3 = null, B()), X;
}
e++, (g = i.monitorRunDependencies) == null || g.call(i, e);
var A = { a: XI };
return i.instantiateWasm ? new Promise((B) => {
i.instantiateWasm(A, (Q, E) => {
B(I(Q));
});
}) : (RA ?? (RA = yI("AGFzbQEAAAAB2QM5YAF/AX9gAn9/AGABfwBgA39/fwF/YAJ/fwF/YAN/f38AYAZ/f39/f38Bf2AFf39/f38Bf2AEf39/fwBgBH9/f38Bf2AGf39/f39/AGAFf39/f38AYAAAYAh/f39/f39/fwF/YAd/f39/f39/AX9gAAF/YAV/fn5+fgBgCn9/f39/f39/f38AYAd/f39/f39/AGAFf39/f34Bf2AIf39/f39/f38AYAR/fn5/AGADf35/AX5gBX9/fn9/AGACf34AYAp/f39/f39/f39/AX9gDH9/f39/f39/f39/fwF/YAN/f38BfmAGf39/f35/AX9gD39/f39/f39/f39/f39/fwBgC39/f39/f39/f39/AX9gBH9/f38BfmAGf3x/f39/AX9gB39/f39/fn4Bf2AGf39/f35+AX9gBX9/f398AX9gDX9/f39/f39/f39/f38AYAV/f39+fgBgBX9/f39/AXxgBH9+f38Bf2ACf3wAYAR+fn5+AX9gAn5/AX9gBH9/f34BfmACfn4BfGABfwF8YAN/f38BfGADf39/AX1gA39/fgBgAn5+AX1gAn9/AX5gBH9+fn4AYAN+fn4Bf2ACfH8BfGAEf39/fQF/YAR/f399AGADf399AAK7AR8BYQFhAAUBYQFiABEBYQFjAAsBYQFkAAUBYQFlABEBYQFmAAUBYQFnAAoBYQFoAAEBYQFpAAoBYQFqACQBYQFrAAkBYQFsABQBYQFtAAUBYQFuACUBYQFvACYBYQFwAAMBYQFxAAIBYQFyAAgBYQFzAAgBYQF0AAQBYQF1AAQBYQF2AAABYQF3ACcBYQF4AAwBYQF5AAABYQF6AAIBYQFBAAEBYQFCAAgBYQFDAAEBYQFEAAIBYQFFAAIDjQWLBQAAAQQAAAIAAQABAQQEAg8QAgAEBQACAwAAAAIDAQwAABAEBQgVCwAAAAAQBAAFAAEBAwQAAAQBAQEAAAwBAQADAwACBBgFBQcHAwAAKA0NCAEDAQABAAQAAAgEAQEAAAwGBAQBAQYDKQUAFQMMAAQBAAEBBQQEBwMZABkAAQABAAQBBAABACoBAAEHAQAFBAUBAAgDBAIECwEUAgIBAAACCQABBAAACQEJAwcIBA4EDgQJCQQAAQABAAACAQQAAgADAgAGAQoFCAQFAQwAAAMBBAAABAsEAgACAxoLAAMaCwgCGwArAQAJEAAEAgIDAgAABBgBACwEAQUtAQIMAAgCBBwGHAYACQkBBAwIAwECFAUFBQAEBAIABQACBQ8FAwUFAAIAAAcNDQcNDQUABw0EAAQCAgIBAAIBAQIAAwMdEQMBHREAAAADCwEeAQAABQEeAQEBCgsKCgsKCg8AAxICEgcJBxIJBwkHCRIDBgMILgwvHwkGCR8JAQUbCQAABwQCAAQEAzAxMggQEBUzNAEAAAAAAAMEAAEFAQUBAAACAQgCBAAAAgICBAAMAgQDCAAOBzUAAQMAAAkDCAU2Azc4CgoKCwsLAwgICAMCDwIAAgACAAIAAgUAAgACAAIAAgACBAACAAIAAgACAAUBAQEBAQEAAAIEAgAHAAcNDQIHBwMJAwQDBAIHAwkDBAMEAgkJCQMCAg8DCgoGIQUGIQUODgEADg4DDg4NBQYGBgYGBQ0GBgYGBgciIxMHEwcHAAciBCMTBxMJBwcGBgYGBgYGBgYGBgYGBgAGBgYIAQYDCAcDCAcDAwICAAIACAIXBAQAAAACAgAAAgACAAMAAAMIFwMCABYBIBYDDAQHAXABgAOAAwUHAQGCAoCAAgYIAX8BQfD+BQsHGwYBRgIAAUcAqQUBSAEAAUkA1gMBSgA0AUsALQm/BQEAQQEL/wKQA/sE9wTmBOEE3gT/AvsC/ATPBGvJBMUEwgT/AvsCwQS+BNcDuwS2BLUErgTPAssClQSLBIEE9gPsAzDPAssCpQLfA94DoALdA9wDpQLbA9oDoALZA9gDnALVA9QDRqgFpwWmBaUFlAKiBZMCoQWgBZ8FRkaeBZ0FnAXIA5sFyAOQAsYDmgWZBY8CwQOYBZcF2AGOApYFlAWVBZMF/AGMBY0FiwWQBY8FjgWxAYwCigWJBYgFhwWJAoYFhQWEBS3hAdICiQSHBIUEgwSABP4D/AP6A/gD9QPzA/ED7wPtA9YCtASzBNACpgSlBKQEowSiBNECoQSgBJ8E2wKdBJwEmwSaBJkERpgElwTEApYEkwSSBJEEjwSNBMMClASSBZEFkASOBIwEiQEwMLIEsQSwBK8ErQSsBKsEqgTRAqkEqASnBDDOAs4CqgHiAeIBngTiATDKAskCqgFGRsgCvgEwygLJAqoBRkbIAr4BMMcCxgKqAUZGxQK+ATDHAsYCqgFGRsUCvgGJATCDBYIFgQWJATCABf8E/gQw/QT6BPkE+ASUA5QD9gT1BPQE8wTyBDDxBPAE7wTuBIwDjAPtBOwE6wTqBOkEMOgE5wTlBOQE4wTiBOAE3wQw3QTcBNsE2gTZBNgE1wTWBIkBMPwC1QTUBNME0gTRBNAEigSGBIIE9APwA/0D+QOJATD8As4EzQTMBMsEygTIBIgEhAT/A/ID7gP7A/cD7QHCAscE7QHCAsYEMMUBxQFXV1fyAkZ0dDDFAcUBV1dX8gJGdHQwxAHEAVdXV/ECRnR0MMQBxAFXV1fxAkZ0dDDEBMMEMMAEvwQwvQS8BDC6BLkEMNwCuASTAjDcArcEkwKJAesD6wGjBaQFiQEw4QHhAawCMKwCMOoD4APjA+kDMOED5APoAzDiA+UD5wMw5gMMASoKwLAIiwUTACAAEEcEQCAAKAIEDwsgABBeCxoBAX8gABBHBEAgACgCACAAEH4aEIsCCyAAC4sBAQN/IAAQHyICIAFJBEAjAEEQayIEJAAgASACayICBEAgAiAAECgiAyAAEB8iAWtLBEAgACADIAIgA2sgAWogASABEPQBCyABIAAQIyIDaiACQQAQsgIgACABIAJqIgAQgwEgBEEAOgAPIAAgA2ogBEEPahBdCyAEQRBqJAAPCyAAIAAQIyABEMACCwkAIAAQIyABagsRACAAEEcEQCAAKAIADwsgAAsSACAAQgA3AgAgAEEANgIIIAALFgAgACgCACIAQaDxAUcEQCAAEL8BCwuLAgIDfwJ+AkAgACkDcCIEUEUgBCAAKQN4IAAoAgQiASAAKAIsIgJrrHwiBVdxRQRAIwBBEGsiAiQAQX8hAQJAIAAQyQMNACAAIAJBD2pBASAAKAIgEQMAQQFHDQAgAi0ADyEBCyACQRBqJAAgASIDQQBODQEgACgCBCEBIAAoAiwhAgsgAEJ/NwNwIAAgATYCaCAAIAUgAiABa6x8NwN4QX8PCyAFQgF8IQUgACgCBCEBIAAoAgghAgJAIAApA3AiBFANACAEIAV9IgQgAiABa6xZDQAgASAEp2ohAgsgACACNgJoIAAgBSAAKAIsIgAgAWusfDcDeCAAIAFPBEAgAUEBayADOgAACyADCwwAIAAgAUEcahDVAgsZAQF/QQohASAAEEcEfyAAEH5BAWsFQQoLC3kBA38CQCABELcCIQIgABDxASEDIAAQHyEEIAIgA00EQCAAECMiAyABIAIQZSMAQRBrIgEkACAAEB8aIAAgAhCDASABQQA2AgwgAyACQQJ0aiABQQxqEFYgAUEQaiQADAELIAAgAyACIANrIARBACAEIAIgARCvAgsLDgAgACABIAEQqAEQsQILEAAgABCyAyABELIDc0EBcwsQACAAELMDIAEQswNzQQFzC4EMAQh/AkAgAEUNACAAQQhrIgMgAEEEaygCACICQXhxIgBqIQUCQCACQQFxDQAgAkECcUUNASADIAMoAgAiBGsiA0Gc6gEoAgBJDQEgACAEaiEAAkACQAJAQaDqASgCACADRwRAIAMoAgwhASAEQf8BTQRAIAEgAygCCCICRw0CQYzqAUGM6gEoAgBBfiAEQQN2d3E2AgAMBQsgAygCGCEHIAEgA0cEQCADKAIIIgIgATYCDCABIAI2AggMBAsgAygCFCICBH8gA0EUagUgAygCECICRQ0DIANBEGoLIQQDQCAEIQYgAiIBQRRqIQQgASgCFCICDQAgAUEQaiEEIAEoAhAiAg0ACyAGQQA2AgAMAwsgBSgCBCICQQNxQQNHDQNBlOoBIAA2AgAgBSACQX5xNgIEIAMgAEEBcjYCBCAFIAA2AgAPCyACIAE2AgwgASACNgIIDAILQQAhAQsgB0UNAAJAIAMoAhwiBEECdCICKAK87AEgA0YEQCACQbzsAWogATYCACABDQFBkOoBQZDqASgCAEF+IAR3cTYCAAwCCwJAIAMgBygCEEYEQCAHIAE2AhAMAQsgByABNgIUCyABRQ0BCyABIAc2AhggAygCECICBEAgASACNgIQIAIgATYCGAsgAygCFCICRQ0AIAEgAjYCFCACIAE2AhgLIAMgBU8NACAFKAIEIgRBAXFFDQACQAJAAkACQCAEQQJxRQRAQaTqASgCACAFRgRAQaTqASADNgIAQZjqAUGY6gEoAgAgAGoiADYCACADIABBAXI2AgQgA0Gg6gEoAgBHDQZBlOoBQQA2AgBBoOoBQQA2AgAPC0Gg6gEoAgAiByAFRgRAQaDqASADNgIAQZTqAUGU6gEoAgAgAGoiADYCACADIABBAXI2AgQgACADaiAANgIADwsgBEF4cSAAaiEAIAUoAgwhASAEQf8BTQRAIAUoAggiAiABRgRAQYzqAUGM6gEoAgBBfiAEQQN2d3E2AgAMBQsgAiABNgIMIAEgAjYCCAwECyAFKAIYIQggASAFRwRAIAUoAggiAiABNgIMIAEgAjYCCAwDCyAFKAIUIgIEfyAFQRRqBSAFKAIQIgJFDQIgBUEQagshBANAIAQhBiACIgFBFGohBCABKAIUIgINACABQRBqIQQgASgCECICDQALIAZBADYCAAwCCyAFIARBfnE2AgQgAyAAQQFyNgIEIAAgA2ogADYCAAwDC0EAIQELIAhFDQACQCAFKAIcIgRBAnQiAigCvOwBIAVGBEAgAkG87AFqIAE2AgAgAQ0BQZDqAUGQ6gEoAgBBfiAEd3E2AgAMAgsCQCAFIAgoAhBGBEAgCCABNgIQDAELIAggATYCFAsgAUUNAQsgASAINgIYIAUoAhAiAgRAIAEgAjYCECACIAE2AhgLIAUoAhQiAkUNACABIAI2AhQgAiABNgIYCyADIABBAXI2AgQgACADaiAANgIAIAMgB0cNAEGU6gEgADYCAA8LIABB/wFNBEAgAEF4cUG06gFqIQICf0GM6gEoAgAiBEEBIABBA3Z0IgBxRQRAQYzqASAAIARyNgIAIAIMAQsgAigCCAshACACIAM2AgggACADNgIMIAMgAjYCDCADIAA2AggPC0EfIQEgAEH///8HTQRAIABBJiAAQQh2ZyICa3ZBAXEgAkEBdGtBPmohAQsgAyABNgIcIANCADcCECABQQJ0QbzsAWohBAJ/AkACf0GQ6gEoAgAiBkEBIAF0IgJxRQRAQZDqASACIAZyNgIAIAQgAzYCAEEYIQFBCAwBCyAAQRkgAUEBdmtBACABQR9HG3QhASAEKAIAIQQDQCAEIgIoAgRBeHEgAEYNAiABQR12IQQgAUEBdCEBIAIgBEEEcWoiBigCECIEDQALIAYgAzYCEEEYIQEgAiEEQQgLIQAgAyICDAELIAIoAggiBCADNgIMIAIgAzYCCEEYIQBBCCEBQQALIQYgASADaiAENgIAIAMgAjYCDCAAIANqIAY2AgBBrOoBQazqASgCAEEBayIAQX8gABs2AgALC+kCAQZ/QZzxAS0AAARAQZjxASgCAA8LIwBBIGsiAiQAAkACQANAIAJBCGoiBCAAQQJ0IgNqAn9BASAAdEH/////B3EiBUEBckUEQCADKAIADAELIABBjBZBxh8gBRsQogMLIgM2AgAgA0F/Rg0BIABBAWoiAEEGRw0AC0EAEKEDRQRAQZiDASEBIARBmIMBQRgQiwFFDQJBsIMBIQEgBEGwgwFBGBCLAUUNAkEAIQBBvO4BLQAARQRAA0AgAEECdCAAQcYfEKIDNgKM7gEgAEEBaiIAQQZHDQALQbzuAUEBOgAAQaTuAUGM7gEoAgA2AgALQYzuASEBIAJBCGoiAEGM7gFBGBCLAUUNAkGk7gEhASAAQaTuAUEYEIsBRQ0CQRgQNCIBRQ0BCyABIAIpAgg3AgAgASACKQIYNwIQIAEgAikCEDcCCAwBC0EAIQELIAJBIGokAEGc8QFBAToAAEGY8QEgATYCACABC80KAgV/CX4jAEHgAGsiBSQAIARC////////P4MhCiACIASFQoCAgICAgICAgH+DIQsgAkL///////8/gyIMQiCIIQ8gBEIwiKdB//8BcSEHAkACQCACQjCIp0H//wFxIglB//8Ba0GCgH5PBEAgB0H//wFrQYGAfksNAQsgAVAgAkL///////////8AgyINQoCAgICAgMD//wBUIA1CgICAgICAwP//AFEbRQRAIAJCgICAgICAIIQhCwwCCyADUCAEQv///////////wCDIgJCgICAgICAwP//AFQgAkKAgICAgIDA//8AURtFBEAgBEKAgICAgIAghCELIAMhAQwCCyABIA1CgICAgICAwP//AIWEUARAIAIgA4RQBEBCgICAgICA4P//ACELQgAhAQwDCyALQoCAgICAgMD//wCEIQtCACEBDAILIAMgAkKAgICAgIDA//8AhYRQBEAgASANhEIAIQFQBEBCgICAgICA4P//ACELDAMLIAtCgICAgICAwP//AIQhCwwCCyABIA2EUARAQgAhAQwCCyACIAOEUARAQgAhAQwCCyANQv///////z9YBEAgBUHQAGogASAMIAEgDCAMUCIGG3lCwABCACAGG3ynIgZBD2sQREEQIAZrIQYgBSkDWCIMQiCIIQ8gBSkDUCEBCyACQv///////z9WDQAgBUFAayADIAogAyAKIApQIggbeULAAEIAIAgbfKciCEEPaxBEIAYgCGtBEGohBiAFKQNIIQogBSkDQCEDCyAHIAlqIAZqQf//AGshBgJAIApCD4YiDkIgiEKAgICACIQiAiABQiCIIgR+IhAgA0IPhiIRQiCIIgogD0KAgASEIg1+fCIPIBBUrSAPIANCMYggDoRC/////w+DIgMgDEL/////D4MiDH58Ig4gD1StfCACIA1+fCAOIA4gEUKAgP7/D4MiDyAMfiIRIAQgCn58IhAgEVStIBAgECADIAFC/////w+DIgF+fCIQVq18fCIOVq18IAMgDX4iEiACIAx+fCIRIBJUrUIghiARQiCIhHwgDiAOIBFCIIZ8Ig5WrXwgDiANIA9+Ig0gCiAMfnwiDCABIAJ+fCICIAMgBH58IgNCIIggAiADVq0gDCANVK0gAiAMVK18fEIghoR8IgIgDlStfCACIBAgBCAPfiIMIAEgCn58IgRCIIggBCAMVK1CIIaEfCIKIBBUrSAKIANCIIZ8IgMgClStfHwiCiACVK18IAogAyAEQiCGIgIgASAPfnwiASACVK18IgIgA1StfCIEIApUrXwiA0KAgICAgIDAAINQRQRAIAZBAWohBgwBCyABQj+IIANCAYYgBEI/iIQhAyAEQgGGIAJCP4iEIQQgAUIBhiEBIAJCAYaEIQILIAZB//8BTgRAIAtCgICAgICAwP//AIQhC0IAIQEMAQsCfiAGQQBMBEBBASAGayIHQf8ATQRAIAVBMGogASACIAZB/wBqIgYQRCAFQSBqIAQgAyAGEEQgBUEQaiABIAIgBxCKASAFIAQgAyAHEIoBIAUpAzAgBSkDOIRCAFKtIAUpAyAgBSkDEISEIQEgBSkDKCAFKQMYhCECIAUpAwAhBCAFKQMIDAILQgAhAQwCCyADQv///////z+DIAatQjCGhAsgC4QhCyABUCACQgBZIAJCgICAgICAgICAf1EbRQRAIAsgBEIBfCIBUK18IQsMAQsgASACQoCAgICAgICAgH+FhFBFBEAgBCEBDAELIAsgBCAEQgGDfCIBIARUrXwhCwsgACABNwMAIAAgCzcDCCAFQeAAaiQACwYAIAAQLQt8AQN/IwBBEGsiASQAIAEgADYCDCMAQRBrIgIkACAAKAIAQX9HBEAgAkEIaiACQQxqIAFBDGoQVRBVIQMDQCAAKAIAQQFGDQALIAAoAgBFBEAgAEEBNgIAIAMQ0gIgAEF/NgIACwsgAkEQaiQAIAAoAgQgAUEQaiQAQQFrCyAAIAAgAUEBazYCBCAAQeDVATYCACAAQZCtATYCACAAC/cFAQl/IwBBEGsiCSQAIAEQ1wIgCUEMaiABEFUhCCAAQQhqIgMQayACTQRAAkAgAkEBaiIAIAMQayIBSwRAIwBBIGsiCiQAAkAgACABayIHIAMoAgggAygCBGtBAnVNBEAgAyAHENkCDAELIApBDGohAQJ/IAMQayAHaiEFIwBBEGsiACQAIAAgBTYCDCAFELwCIgRNBEAgAxC5AiIFIARBAXZJBEAgACAFQQF0NgIIIABBCGogAEEMahCgASgCACEECyAAQRBqJAAgBAwBCxCMAQALIQQgAxBrIQUjAEEQayIAJAAgASADQQxqIgs2AhAgAUEANgIMIAQEfyAAQQhqIAsgBBC7AiAAKAIIIQYgACgCDAVBAAshBCABIAY2AgAgASAGIAVBAnRqIgU2AgggASAGIARBAnRqNgIMIAEgBTYCBCAAQRBqJAAjAEEQayIGJAAgASgCCCEEIAZBBGoiACABQQhqNgIIIAAgBDYCACAAIAQgB0ECdGo2AgQgACgCACEEA0AgACgCBCAERwRAIAEoAhAaIAQQugIgACAAKAIAQQRqIgQ2AgAMAQsLIAAoAgggACgCADYCACAGQRBqJAAgASgCBCADKAIAIgAgAygCBGtqIQQgAygCBCAAayIHBEAgBCAAIAf8CgAACyABIAQ2AgQgAyADKAIANgIEIAMgAUEEahDXASADQQRqIAFBCGoQ1wEgA0EIaiABQQxqENcBIAEgASgCBDYCACADEGsaIAEoAgQhAANAIAEoAggiBCAARwRAIAEgBEEEazYCCCABKAIQGgwBCwsgASgCACIABEAgASgCECAAIAEoAgwgASgCAGtBAnUQuAILCyAKQSBqJAAMAQsgACABSQRAIAMoAgAgAEECdGohACADEGsaIAMgABDYAgsLCyADIAIQggEoAgAEQCADIAIQggEoAgAQvwELIAgQrAEhACADIAIQggEgADYCACAIKAIAIQAgCEEANgIAIAAEQCAAEL8BCyAJQRBqJAALySgBC38jAEEQayIKJAACQAJAAkACQAJAAkACQAJAAkACQCAAQfQBTQRAQYzqASgCACIEQRAgAEELakH4A3EgAEELSRsiBkEDdiIAdiIBQQNxBEACQCABQX9zQQFxIABqIgJBA3QiAUG06gFqIgAgASgCvOoBIgEoAggiBUYEQEGM6gEgBEF+IAJ3cTYCAAwBCyAFIAA2AgwgACAFNgIICyABQQhqIQAgASACQQN0IgJBA3I2AgQgASACaiIBIAEoAgRBAXI2AgQMCwsgBkGU6gEoAgAiCE0NASABBEACQEECIAB0IgJBACACa3IgASAAdHFoIgFBA3QiAEG06gFqIgIgACgCvOoBIgAoAggiBUYEQEGM6gEgBEF+IAF3cSIENgIADAELIAUgAjYCDCACIAU2AggLIAAgBkEDcjYCBCAAIAZqIgcgAUEDdCIBIAZrIgVBAXI2AgQgACABaiAFNgIAIAgEQCAIQXhxQbTqAWohAUGg6gEoAgAhAgJ/IARBASAIQQN2dCIDcUUEQEGM6gEgAyAEcjYCACABDAELIAEoAggLIQMgASACNgIIIAMgAjYCDCACIAE2AgwgAiADNgIICyAAQQhqIQBBoOoBIAc2AgBBlOoBIAU2AgAMCwtBkOoBKAIAIgtFDQEgC2hBAnQoArzsASICKAIEQXhxIAZrIQMgAiEBA0ACQCABKAIQIgBFBEAgASgCFCIARQ0BCyAAKAIEQXhxIAZrIgEgAyABIANJIgEbIQMgACACIAEbIQIgACEBDAELCyACKAIYIQkgAiACKAIMIgBHBEAgAigCCCIBIAA2AgwgACABNgIIDAoLIAIoAhQiAQR/IAJBFGoFIAIoAhAiAUUNAyACQRBqCyEFA0AgBSEHIAEiAEEUaiEFIAAoAhQiAQ0AIABBEGohBSAAKAIQIgENAAsgB0EANgIADAkLQX8hBiAAQb9/Sw0AIABBC2oiAUF4cSEGQZDqASgCACIHRQ0AQR8hCEEAIAZrIQMgAEH0//8HTQRAIAZBJiABQQh2ZyIAa3ZBAXEgAEEBdGtBPmohCAsCQAJAAkAgCEECdCgCvOwBIgFFBEBBACEADAELQQAhACAGQRkgCEEBdmtBACAIQR9HG3QhAgNAAkAgASgCBEF4cSAGayIEIANPDQAgASEFIAQiAw0AQQAhAyABIQAMAwsgACABKAIUIgQgBCABIAJBHXZBBHFqKAIQIgFGGyAAIAQbIQAgAkEBdCECIAENAAsLIAAgBXJFBEBBACEFQQIgCHQiAEEAIABrciAHcSIARQ0DIABoQQJ0KAK87AEhAAsgAEUNAQsDQCAAKAIEQXhxIAZrIgIgA0khASACIAMgARshAyAAIAUgARshBSAAKAIQIgEEfyABBSAAKAIUCyIADQALCyAFRQ0AIANBlOoBKAIAIAZrTw0AIAUoAhghCCAFIAUoAgwiAEcEQCAFKAIIIgEgADYCDCAAIAE2AggMCAsgBSgCFCIBBH8gBUEUagUgBSgCECIBRQ0DIAVBEGoLIQIDQCACIQQgASIAQRRqIQIgACgCFCIBDQAgAEEQaiECIAAoAhAiAQ0ACyAEQQA2AgAMBwsgBkGU6gEoAgAiBU0EQEGg6gEoAgAhAAJAIAUgBmsiAUEQTwRAIAAgBmoiAiABQQFyNgIEIAAgBWogATYCACAAIAZBA3I2AgQMAQsgACAFQQNyNgIEIAAgBWoiASABKAIEQQFyNgIEQQAhAkEAIQELQZTqASABNgIAQaDqASACNgIAIABBCGohAAwJCyAGQZjqASgCACICSQRAQZjqASACIAZrIgE2AgBBpOoBQaTqASgCACIAIAZqIgI2AgAgAiABQQFyNgIEIAAgBkEDcjYCBCAAQQhqIQAMCQtBACEAIAZBL2oiAwJ/QeTtASgCAARAQeztASgCAAwBC0Hw7QFCfzcCAEHo7QFCgKCAgICABDcCAEHk7QEgCkEMakFwcUHYqtWqBXM2AgBB+O0BQQA2AgBByO0BQQA2AgBBgCALIgFqIgRBACABayIHcSIBIAZNDQhBxO0BKAIAIgUEQEG87QEoAgAiCCABaiIJIAhNIAUgCUlyDQkLAkBByO0BLQAAQQRxRQRAAkACQAJAAkBBpOoBKAIAIgUEQEHM7QEhAANAIAAoAgAiCCAFTQRAIAUgCCAAKAIEakkNAwsgACgCCCIADQALC0EAEKUBIgJBf0YNAyABIQRB6O0BKAIAIgBBAWsiBSACcQRAIAEgAmsgAiAFakEAIABrcWohBAsgBCAGTQ0DQcTtASgCACIABEBBvO0BKAIAIgUgBGoiByAFTSAAIAdJcg0ECyAEEKUBIgAgAkcNAQwFCyAEIAJrIAdxIgQQpQEiAiAAKAIAIAAoAgRqRg0BIAIhAAsgAEF/Rg0BIAZBMGogBE0EQCAAIQIMBAtB7O0BKAIAIgIgAyAEa2pBACACa3EiAhClAUF/Rg0BIAIgBGohBCAAIQIMAwsgAkF/Rw0CC0HI7QFByO0BKAIAQQRyNgIACyABEKUBIgJBf0ZBABClASIAQX9GciAAIAJNcg0FIAAgAmsiBCAGQShqTQ0FC0G87QFBvO0BKAIAIARqIgA2AgBBwO0BKAIAIABJBEBBwO0BIAA2AgALAkBBpOoBKAIAIgMEQEHM7QEhAANAIAIgACgCACIBIAAoAgQiBWpGDQIgACgCCCIADQALDAQLQZzqASgCACIAQQAgACACTRtFBEBBnOoBIAI2AgALQQAhAEHQ7QEgBDYCAEHM7QEgAjYCAEGs6gFBfzYCAEGw6gFB5O0BKAIANgIAQdjtAUEANgIAA0AgAEEDdCIBIAFBtOoBaiIFNgK86gEgASAFNgLA6gEgAEEBaiIAQSBHDQALQZjqASAEQShrIgBBeCACa0EHcSIBayIFNgIAQaTqASABIAJqIgE2AgAgASAFQQFyNgIEIAAgAmpBKDYCBEGo6gFB9O0BKAIANgIADAQLIAIgA00gASADS3INAiAAKAIMQQhxDQIgACAEIAVqNgIEQaTqASADQXggA2tBB3EiAGoiATYCAEGY6gFBmOoBKAIAIARqIgIgAGsiADYCACABIABBAXI2AgQgAiADakEoNgIEQajqAUH07QEoAgA2AgAMAwtBACEADAYLQQAhAAwEC0Gc6gEoAgAgAksEQEGc6gEgAjYCAAsgAiAEaiEFQcztASEAAkADQCAFIAAoAgAiAUcEQCAAKAIIIgANAQwCCwsgAC0ADEEIcUUNAwtBzO0BIQADQAJAIAAoAgAiASADTQRAIAMgASAAKAIEaiIFSQ0BCyAAKAIIIQAMAQsLQZjqASAEQShrIgBBeCACa0EHcSIBayIHNgIAQaTqASABIAJqIgE2AgAgASAHQQFyNgIEIAAgAmpBKDYCBEGo6gFB9O0BKAIANgIAIAMgBUEnIAVrQQdxakEvayIAIAAgA0EQakkbIgFBGzYCBCABQdTtASkCADcCECABQcztASkCADcCCEHU7QEgAUEIajYCAEHQ7QEgBDYCAEHM7QEgAjYCAEHY7QFBADYCACABQRhqIQADQCAAQQc2AgQgAEEIaiAAQQRqIQAgBUkNAAsgASADRg0AIAEgASgCBEF+cTYCBCADIAEgA2siAkEBcjYCBCABIAI2AgACfyACQf8BTQRAIAJBeHFBtOoBaiEAAn9BjOoBKAIAIgFBASACQQN2dCICcUUEQEGM6gEgASACcjYCACAADAELIAAoAggLIQEgACADNgIIIAEgAzYCDEEMIQJBCAwBC0EfIQAgAkH///8HTQRAIAJBJiACQQh2ZyIAa3ZBAXEgAEEBdGtBPmohAAsgAyAANgIcIANCADcCECAAQQJ0QbzsAWohAQJAAkBBkOoBKAIAIgVBASAAdCIEcUUEQEGQ6gEgBCAFcjYCACABIAM2AgAMAQsgAkEZIABBAXZrQQAgAEEfRxt0IQAgASgCACEFA0AgBSIBKAIEQXhxIAJGDQIgAEEddiEFIABBAXQhACABIAVBBHFqIgQoAhAiBQ0ACyAEIAM2AhALIAMgATYCGEEIIQIgAyIBIQBBDAwBCyABKAIIIgAgAzYCDCABIAM2AgggAyAANgIIQQAhAEEYIQJBDAsgA2ogATYCACACIANqIAA2AgALQZjqASgCACIAIAZNDQBBmOoBIAAgBmsiATYCAEGk6gFBpOoBKAIAIgAgBmoiAjYCACACIAFBAXI2AgQgACAGQQNyNgIEIABBCGohAAwEC0GI6gFBMDYCAEEAIQAMAwsgACACNgIAIAAgACgCBCAEajYCBCACQXggAmtBB3FqIgggBkEDcjYCBCABQXggAWtBB3FqIgQgBiAIaiIDayEHAkBBpOoBKAIAIARGBEBBpOoBIAM2AgBBmOoBQZjqASgCACAHaiIANgIAIAMgAEEBcjYCBAwBC0Gg6gEoAgAgBEYEQEGg6gEgAzYCAEGU6gFBlOoBKAIAIAdqIgA2AgAgAyAAQQFyNgIEIAAgA2ogADYCAAwBCyAEKAIEIgBBA3FBAUYEQCAAQXhxIQkgBCgCDCECAkAgAEH/AU0EQCAEKAIIIgEgAkYEQEGM6gFBjOoBKAIAQX4gAEEDdndxNgIADAILIAEgAjYCDCACIAE2AggMAQsgBCgCGCEGAkAgAiAERwRAIAQoAggiACACNgIMIAIgADYCCAwBCwJAIAQoAhQiAAR/IARBFGoFIAQoAhAiAEUNASAEQRBqCyEBA0AgASEFIAAiAkEUaiEBIAAoAhQiAA0AIAJBEGohASACKAIQIgANAAsgBUEANgIADAELQQAhAgsgBkUNAAJAIAQoAhwiAEECdCIBKAK87AEgBEYEQCABQbzsAWogAjYCACACDQFBkOoBQZDqASgCAEF+IAB3cTYCAAwCCwJAIAQgBigCEEYEQCAGIAI2AhAMAQsgBiACNgIUCyACRQ0BCyACIAY2AhggBCgCECIABEAgAiAANgIQIAAgAjYCGAsgBCgCFCIARQ0AIAIgADYCFCAAIAI2AhgLIAcgCWohByAEIAlqIgQoAgQhAAsgBCAAQX5xNgIEIAMgB0EBcjYCBCADIAdqIAc2AgAgB0H/AU0EQCAHQXhxQbTqAWohAAJ/QYzqASgCACIBQQEgB0EDdnQiAnFFBEBBjOoBIAEgAnI2AgAgAAwBCyAAKAIICyEBIAAgAzYCCCABIAM2AgwgAyAANgIMIAMgATYCCAwBC0EfIQIgB0H///8HTQRAIAdBJiAHQQh2ZyIAa3ZBAXEgAEEBdGtBPmohAgsgAyACNgIcIANCADcCECACQQJ0QbzsAWohAAJAAkBBkOoBKAIAIgFBASACdCIFcUUEQEGQ6gEgASAFcjYCACAAIAM2AgAMAQsgB0EZIAJBAXZrQQAgAkEfRxt0IQIgACgCACEBA0AgASIAKAIEQXhxIAdGDQIgAkEddiEBIAJBAXQhAiAAIAFBBHFqIgUoAhAiAQ0ACyAFIAM2AhALIAMgADYCGCADIAM2AgwgAyADNgIIDAELIAAoAggiASADNgIMIAAgAzYCCCADQQA2AhggAyAANgIMIAMgATYCCAsgCEEIaiEADAILAkAgCEUNAAJAIAUoAhwiAUECdCICKAK87AEgBUYEQCACQbzsAWogADYCACAADQFBkOoBIAdBfiABd3EiBzYCAAwCCwJAIAUgCCgCEEYEQCAIIAA2AhAMAQsgCCAANgIUCyAARQ0BCyAAIAg2AhggBSgCECIBBEAgACABNgIQIAEgADYCGAsgBSgCFCIBRQ0AIAAgATYCFCABIAA2AhgLAkAgA0EPTQRAIAUgAyAGaiIAQQNyNgIEIAAgBWoiACAAKAIEQQFyNgIEDAELIAUgBkEDcjYCBCAFIAZqIgQgA0EBcjYCBCADIARqIAM2AgAgA0H/AU0EQCADQXhxQbTqAWohAAJ/QYzqASgCACIBQQEgA0EDdnQiAnFFBEBBjOoBIAEgAnI2AgAgAAwBCyAAKAIICyEBIAAgBDYCCCABIAQ2AgwgBCAANgIMIAQgATYCCAwBC0EfIQAgA0H///8HTQRAIANBJiADQQh2ZyIAa3ZBAXEgAEEBdGtBPmohAAsgBCAANgIcIARCADcCECAAQQJ0QbzsAWohAQJAAkAgB0EBIAB0IgJxRQRAQZDqASACIAdyNgIAIAEgBDYCACAEIAE2AhgMAQsgA0EZIABBAXZrQQAgAEEfRxt0IQAgASgCACEBA0AgASICKAIEQXhxIANGDQIgAEEddiEBIABBAXQhACACIAFBBHFqIgcoAhAiAQ0ACyAHIAQ2AhAgBCACNgIYCyAEIAQ2AgwgBCAENgIIDAELIAIoAggiACAENgIMIAIgBDYCCCAEQQA2AhggBCACNgIMIAQgADYCCAsgBUEIaiEADAELAkAgCUUNAAJAIAIoAhwiAUECdCIFKAK87AEgAkYEQCAFQbzsAWogADYCACAADQFBkOoBIAtBfiABd3E2AgAMAgsCQCACIAkoAhBGBEAgCSAANgIQDAELIAkgADYCFAsgAEUNAQsgACAJNgIYIAIoAhAiAQRAIAAgATYCECABIAA2AhgLIAIoAhQiAUUNACAAIAE2AhQgASAANgIYCwJAIANBD00EQCACIAMgBmoiAEEDcjYCBCAAIAJqIgAgACgCBEEBcjYCBAwBCyACIAZBA3I2AgQgAiAGaiIFIANBAXI2AgQgAyAFaiADNgIAIAgEQCAIQXhxQbTqAWohAEGg6gEoAgAhAQJ/QQEgCEEDdnQiByAEcUUEQEGM6gEgBCAHcjYCACAADAELIAAoAggLIQQgACABNgIIIAQgATYCDCABIAA2AgwgASAENgIIC0Gg6gEgBTYCAEGU6gEgAzYCAAsgAkEIaiEACyAKQRBqJAAgAAsIACAAQQAQPAsVACAAIAE2AgAgACACKAIANgIEIAALCgAgACgCABC9AwsLACAAKAIAEMMDwAsXACAAEEcEQCAAKAIAIAAQfhCpAQsgAAs7AQJ/IwBBEGsiASQAIAEgADYCDCABKAIMIgAoAgAiAgRAIAAgAjYCBCAAKAIIGiACEC0LIAFBEGokAAstACACRQRAIAAoAgQgASgCBEYPCyAAIAFGBEBBAQ8LIAAoAgQgASgCBBDQAUULIQEBfyAAKAIAIQIgACABNgIAIAIEQCACIAAoAgQRAgALCwYAEMoDAAsNACAAKAIAELwDGiAACw0AIAAoAgAQnQIaIAALdQEBfiAAIAEgBH4gAiADfnwgA0IgiCICIAFCIIgiBH58IANC/////w+DIgMgAUL/////D4MiAX4iBUIgiCADIAR+fCIDQiCIfCABIAJ+IANC/////w+DfCIBQiCIfDcDCCAAIAVC/////w+DIAFCIIaENwMACxEAIAAgASAAKAIAKAIcEQQAC8EBAQN/IAAtAABBIHFFBEACQCAAKAIQIgMEfyADBSAAEN8BDQEgACgCEAsgACgCFCIEayACSQRAIAAgASACIAAoAiQRAwAaDAELAkACQCACRSAAKAJQQQBIcg0AIAIhAwNAIAEgA2oiBUEBay0AAEEKRwRAIANBAWsiAw0BDAILCyAAIAEgAyAAKAIkEQMAIANJDQIgAiADayECIAAoAhQhBAwBCyABIQULIAQgBSACEHEaIAAgACgCFCACajYCFAsLC6EBAQJ/AkAgABAfRSACIAFrQQVIcg0AIAEgAhDHASACQQRrIQQgABAjIgIgABAfaiEFAkADQAJAIAIsAAAhACABIARPDQAgAEEATCAAQf8ATnJFBEAgASgCACACLAAARw0DCyABQQRqIQEgAiAFIAJrQQFKaiECDAELCyAAQQBMIABB/wBOcg0BIAIsAAAgBCgCAEEBa0sNAQsgA0EENgIACwtQAQF+AkAgA0HAAHEEQCABIANBQGqthiECQgAhAQwBCyADRQ0AIAIgA60iBIYgAUHAACADa62IhCECIAEgBIYhAQsgACABNwMAIAAgAjcDCAtpAQF/IwBBgAJrIgUkACAEQYDABHEgAiADTHJFBEAgBSABIAIgA2siA0GAAiADQYACSSIBGxCYAiABRQRAA0AgACAFQYACEEIgA0GAAmsiA0H/AUsNAAsLIAAgBSADEEILIAVBgAJqJAALBABBAAsKACAALQALQQd2CwoAIABB0PIBEHoLCgAgAEHY8gEQegvPCQIEfwR+IwBB8ABrIgYkACAEQv///////////wCDIQkCQAJAIAFQIgUgAkL///////////8AgyIKQoCAgICAgMD//wB9QoCAgICAgMCAgH9UIApQG0UEQCADQgBSIAlCgICAgICAwP//AH0iC0KAgICAgIDAgIB/ViALQoCAgICAgMCAgH9RGw0BCyAFIApCgICAgICAwP//AFQgCkKAgICAgIDA//8AURtFBEAgAkKAgICAgIAghCEEIAEhAwwCCyADUCAJQoCAgICAgMD//wBUIAlCgICAgICAwP//AFEbRQRAIARCgICAgICAIIQhBAwCCyABIApCgICAgICAwP//AIWEUARAQoCAgICAgOD//wAgAiABIAOFIAIgBIVCgICAgICAgICAf4WEUCIFGyEEQgAgASAFGyEDDAILIAMgCUKAgICAgIDA//8AhYRQDQEgASAKhFAEQCADIAmEQgBSDQIgASADgyEDIAIgBIMhBAwCCyADIAmEUEUNACABIQMgAiEEDAELIAMgASABIANUIAkgClYgCSAKURsiCBshCiAEIAIgCBsiDEL///////8/gyEJIAIgBCAIGyILQjCIp0H//wFxIQcgDEIwiKdB//8BcSIFRQRAIAZB4ABqIAogCSAKIAkgCVAiBRt5QsAAQgAgBRt8pyIFQQ9rEEQgBikDaCEJIAYpA2AhCkEQIAVrIQULIAEgAyAIGyEDIAtC////////P4MhASAHBH4gAQUgBkHQAGogAyABIAMgASABUCIHG3lCwABCACAHG3ynIgdBD2sQREEQIAdrIQcgBikDUCEDIAYpA1gLQgOGIANCPYiEQoCAgICAgIAEhCEBIAlCA4YgCkI9iIQgAiAEhSEEAn4gA0IDhiICIAUgB0YNABogBSAHayIHQf8ASwRAQgAhAUIBDAELIAZBQGsgAiABQYABIAdrEEQgBkEwaiACIAEgBxCKASAGKQM4IQEgBikDMCAGKQNAIAYpA0iEQgBSrYQLIQlCgICAgICAgASEIQsgCkIDhiEKAkAgBEIAUwRAQgAhA0IAIQQgCSAKhSABIAuFhFANAiAKIAl9IQIgCyABfSAJIApWrX0iBEL/////////A1YNASAGQSBqIAIgBCACIAQgBFAiBxt5QsAAQgAgBxt8p0EMayIHEEQgBSAHayEFIAYpAyghBCAGKQMgIQIMAQsgCSAKfCICIAlUrSABIAt8fCIEQoCAgICAgIAIg1ANACAJQgGDIARCP4YgAkIBiISEIQIgBUEBaiEFIARCAYghBAsgDEKAgICAgICAgIB/gyEDIAVB//8BTgRAIANCgICAgICAwP//AIQhBEIAIQMMAQtBACEHAkAgBUEASgRAIAUhBwwBCyAGQRBqIAIgBCAFQf8AahBEIAYgAiAEQQEgBWsQigEgBikDACAGKQMQIAYpAxiEQgBSrYQhAiAGKQMIIQQLIARCPYYgAkIDiIQhASAEQgOIQv///////z+DIAetQjCGhCADhCEEAkACQCACp0EHcSIFQQRHBEAgBCABIAEgBUEES618IgNWrXwhBAwBCyAEIAEgASABQgGDfCIDVq18IQQMAQsgBUUNAQsLIAAgAzcDACAAIAQ3AwggBkHwAGokAAsRACAAIAEgACgCACgCLBEEAAsIACAAQYABSQsRACACBEAgACABIAL8CgAACwsJACAAECMQ9wELhAECAn8BfiMAQRBrIgMkACAAAn4gAUUEQEIADAELIAMgASABQR91IgJzIAJrIgKtQgAgAmciAkHRAGoQRCADKQMIQoCAgICAgMAAhUGegAEgAmutQjCGfEKAgICAgICAgIB/QgAgAUEASBuEIQQgAykDAAs3AwAgACAENwMIIANBEGokAAsNACAAIAFB/wBxOgALC6oMAQh/An9BACABRQ0AGiAAQX9zIQMgAkEXTwRAAkAgAUEDcUUNACABLQAAIANzQf8BcUECdCgC0DMgA0EIdnMhAyACQQFrIgBFIAFBAWoiBEEDcUVyRQRAIAEtAAEgA3NB/wFxQQJ0KALQMyADQQh2cyEDIAJBAmsiAEUgAUECaiIEQQNxRXJFBEAgAS0AAiADc0H/AXFBAnQoAtAzIANBCHZzIQMgAkEDayIARSABQQNqIgRBA3FFckUEQCABLQADIANzQf8BcUECdCgC0DMgA0EIdnMhAyABQQRqIQEgAkEEayECDAMLIAAhAiAEIQEMAgsgACECIAQhAQwBCyAAIQIgBCEBCyACQRRuIghBbGwhCgJAIAhBAWsiCUUEQEEAIQQMAQsgASEAQQAhBANAIAAoAhAgB3MiB0EWdkH8B3EoAtBTIAdBDnZB/AdxKALQSyAHQQZ2QfwHcSgC0EMgB0H/AXFBAnQoAtA7c3NzIQcgACgCDCAGcyIGQRZ2QfwHcSgC0FMgBkEOdkH8B3EoAtBLIAZBBnZB/AdxKALQQyAGQf8BcUECdCgC0Dtzc3MhBiAAKAIIIARzIgRBFnZB/AdxKALQUyAEQQ52QfwHcSgC0EsgBEEGdkH8B3EoAtBDIARB/wFxQQJ0KALQO3NzcyEEIAAoAgQgBXMiBUEWdkH8B3EoAtBTIAVBDnZB/AdxKALQSyAFQQZ2QfwHcSgC0EMgBUH/AXFBAnQoAtA7c3NzIQUgACgCACADcyIDQRZ2QfwHcSgC0FMgA0EOdkH8B3EoAtBLIANBBnZB/AdxKALQQyADQf8BcUECdCgC0Dtzc3MhAyAAQRRqIQAgCUEBayIJDQALIAEgCEEUbGpBFGshAQsgAiAKaiECIAEoAhAgASgCDCABKAIIIAEoAgQgASgCACADcyIAQQh2IABB/wFxQQJ0KALQM3MiAEEIdiAAQf8BcUECdCgC0DNzIgBBCHYgAEH/AXFBAnQoAtAzcyIAQf8BcUECdCgC0DMgBXNzIABBCHZzIgBBCHYgAEH/AXFBAnQoAtAzcyIAQQh2IABB/wFxQQJ0KALQM3MiAEEIdiAAQf8BcUECdCgC0DNzIgBB/wFxQQJ0KALQMyAEc3MgAEEIdnMiAEEIdiAAQf8BcUECdCgC0DNzIgBBCHYgAEH/AXFBAnQoAtAzcyIAQQh2IABB/wFxQQJ0KALQM3MiAEH/AXFBAnQoAtAzIAZzcyAAQQh2cyIAQQh2IABB/wFxQQJ0KALQM3MiAEEIdiAAQf8BcUECdCgC0DNzIgBBCHYgAEH/AXFBAnQoAtAzcyIAQf8BcUECdCgC0DMgB3NzIABBCHZzIgBBCHYgAEH/AXFBAnQoAtAzcyIAQQh2IABB/wFxQQJ0KALQM3MiAEEIdiAAQf8BcUECdCgC0DNzIgBBCHYgAEH/AXFBAnQoAtAzcyEDIAFBFGohAQsgAkEHSwRAA0AgAS0AACADc0H/AXFBAnQoAtAzIANBCHZzIgBBCHYgAS0AASAAc0H/AXFBAnQoAtAzcyIAQQh2IAEtAAIgAHNB/wFxQQJ0KALQM3MiAEEIdiABLQADIABzQf8BcUECdCgC0DNzIgBBCHYgAS0ABCAAc0H/AXFBAnQoAtAzcyIAQQh2IAEtAAUgAHNB/wFxQQJ0KALQM3MiAEEIdiABLQAGIABzQf8BcUECdCgC0DNzIgBBCHYgAS0AByAAc0H/AXFBAnQoAtAzcyEDIAFBCGohASACQQhrIgJBB0sNAAsLAkAgAkUNACABLQAAIANzQf8BcUECdCgC0DMgA0EIdnMhAyACQQFGDQAgAS0AASADc0H/AXFBAnQoAtAzIANBCHZzIQMgAkECRg0AIAEtAAIgA3NB/wFxQQJ0KALQMyADQQh2cyEDIAJBA0YNACABLQADIANzQf8BcUECdCgC0DMgA0EIdnMhAyACQQRGDQAgAS0ABCADc0H/AXFBAnQoAtAzIANBCHZzIQMgAkEFRg0AIAEtAAUgA3NB/wFxQQJ0KALQMyADQQh2cyEDIAJBBkYNACABLQAGIANzQf8BcUECdCgC0DMgA0EIdnMhAwsgA0F/cwsL5QMBBX8jAEEQayIDJAAgAyAAKAIAIgRBCGsoAgAiAjYCDCADIAAgAmo2AgQgAyAEQQRrKAIANgIIIAMoAggiBCABQQAQOyECIAMoAgQhBQJAIAIEQCADKAIMIQAjAEFAaiIBJAAgAUFAayQAQQAgBSAAGyECDAELIwBBQGoiAiQAIAAgBU4EQCACQgA3AhwgAkIANwIkIAJCADcCLCACQgA3AhQgAkEANgIQIAIgATYCDCACIAQ2AgQgAkEANgI8IAJCgYCAgICAgIABNwI0IAIgADYCCCAEIAJBBGogBSAFQQFBACAEKAIAKAIUEQoAIABBACACKAIcGyEGCyACQUBrJAAgBiICDQAjAEFAaiICJAAgAkEANgIQIAJBlNYBNgIMIAIgADYCCCACIAE2AgRBACEAIAJBFGpBAEEn/AsAIAJBADYCPCACQQE6ADsgBCACQQRqIAVBAUEAIAQoAgAoAhgRCwACQAJAAkAgAigCKA4CAAECCyACKAIYQQAgAigCJEEBRhtBACACKAIgQQFGG0EAIAIoAixBAUYbIQAMAQsgAigCHEEBRwRAIAIoAiwNASACKAIgQQFHDQEgAigCJEEBRw0BCyACKAIUIQALIAJBQGskACAAIQILIANBEGokACACCzwBAn9BASAAIABBAU0bIQEDQAJAIAEQNCIADQBB5P4BKAIAIgJFDQAgAhEMAAwBCwsgAEUEQBDrAQsgAAsUAQF/QQQQUyIBIAAoAgA2AgAgAQsLACAAIAE2AgAgAAsMACAAIAEoAgA2AgALBwAgABAkGgsRACAAIAEgASgCACgCFBEBAAsPACAAIAAoAgAoAhARAAALBwAgABAfRQsJAEGFEBCuAgALEAAgACABQYCAgIB4cjYCCAsMACAAIAEtAAA6AAALCwAgAC0AC0H/AHELEwAgACABIAIgACgCACgCDBEDAAsiAQF/IAIQTAR/IAAoAgggAkECdGooAgAgAXFBAEcFQQALC+wBAQN/IABFBEBB0N4BKAIABEBB0N4BKAIAEGEhAQtBgOABKAIABEBBgOABKAIAEGEgAXIhAQtBwOABKAIAIgAEQANAIAAoAkwaIAAoAhQgACgCHEcEQCAAEGEgAXIhAQsgACgCOCIADQALCyABDwsgACgCTEEASCECAkACQCAAKAIUIAAoAhxGDQAgAEEAQQAgACgCJBEDABogACgCFA0AQX8hAQwBCyAAKAIEIgEgACgCCCIDRwRAIAAgASADa6xBASAAKAIoERYAGgtBACEBIABBADYCHCAAQgA3AxAgAEIANwIEIAINAAsgAQsSACAAKAIAIgAEQCAAEJwDGgsLEQAgACABKAIAEJwDNgIAIAALQQEBfyAAIAE3A3AgACAAKAIsIAAoAgQiAmusNwN4IAAgAVAgASAAKAIIIgAgAmusWXIEfyAABSACIAGnags2AmgLHgACQCACRQ0AIAJBAnQiAkUNACAAIAEgAvwKAAALCxYAIAAgASgCADYCACAAIAIoAgA2AgQLtQEBAn8jAEEQayIFJAAgBSABNgIMQQAhAQJAIAICf0EGIAAgBUEMahArDQAaQQQgA0HAACAAEDciBhBfRQ0AGiADIAYQlAEhAQNAAkAgABA+GiABQTBrIQEgACAFQQxqECsgBEECSHINACADQcAAIAAQNyIGEF9FDQMgBEEBayEEIAMgBhCUASABQQpsaiEBDAELCyAAIAVBDGoQK0UNAUECCyACKAIAcjYCAAsgBUEQaiQAIAELtQEBAn8jAEEQayIFJAAgBSABNgIMQQAhAQJAIAICf0EGIAAgBUEMahAsDQAaQQQgA0HAACAAEDgiBhBgRQ0AGiADIAYQlQEhAQNAAkAgABA/GiABQTBrIQEgACAFQQxqECwgBEECSHINACADQcAAIAAQOCIGEGBFDQMgBEEBayEEIAMgBhCVASABQQpsaiEBDAELCyAAIAVBDGoQLEUNAUECCyACKAIAcjYCAAsgBUEQaiQAIAELYwAgAigCBEGwAXEiAkEgRgRAIAEPCwJAIAJBEEcNAAJAAkAgAC0AACICQStrDgMAAQABCyAAQQFqDwsgAkEwRyABIABrQQJIcg0AIAAtAAFBIHJB+ABHDQAgAEECaiEACyAACy4AAkAgACgCBEHKAHEiAARAIABBwABGBEBBCA8LIABBCEcNAUEQDwtBAA8LQQoLEAAgACgCBCAAKAIAa0ECdQvOAQIEfgJ/IwBBEGsiBiQAIAG9IgVC/////////weDIQIgAAJ+IAVCNIhC/w+DIgNQRQRAIANC/w9SBEAgAkIEiCEEIANCgPgAfCEDIAJCPIYMAgsgAkIEiCEEQv//ASEDIAJCPIYMAQsgAlAEQEIAIQNCAAwBCyAGIAJCACACeaciB0ExahBEIAYpAwhCgICAgICAwACFIQRBjPgAIAdrrSEDIAYpAwALNwMAIAAgBUKAgICAgICAgIB/gyADQjCGhCAEhDcDCCAGQRBqJAALsgMBA38jAEEQayIIJAAgCCACNgIIIAggATYCDCAIQQRqIgEgAxAnIAEQSCEJIAEQJSAEQQA2AgBBACEBAkADQCAGIAdGIAFyDQECQCAIQQxqIAhBCGoQKw0AAkAgCSAGKAIAEJQBQSVGBEAgBkEEaiAHRg0CQQAhAgJ/AkAgCSAGKAIEEJQBIgFBxQBGDQBBBCEKIAFB/wFxQTBGDQAgAQwBCyAGQQhqIAdGDQNBCCEKIAEhAiAJIAYoAggQlAELIQEgCCAAIAgoAgwgCCgCCCADIAQgBSABIAIgACgCACgCJBENADYCDCAGIApqQQRqIQYMAQsgCUEBIAYoAgAQXwRAA0AgByAGQQRqIgZHBEAgCUEBIAYoAgAQXw0BCwsDQCAIQQxqIgEgCEEIahArDQIgCUEBIAEQNxBfRQ0CIAEQPhoMAAsACyAJIAhBDGoiARA3EEEgCSAGKAIAEEFGBEAgBkEEaiEGIAEQPhoMAQsgBEEENgIACyAEKAIAIQEMAQsLIARBBDYCAAsgCEEMaiAIQQhqECsEQCAEIAQoAgBBAnI2AgALIAgoAgwgCEEQaiQAC7QDAQN/IwBBEGsiCCQAIAggAjYCCCAIIAE2AgwgCEEEaiIBIAMQJyABEEkhCSABECUgBEEANgIAQQAhAQJAA0AgBiAHRiABcg0BAkAgCEEMaiAIQQhqECwNAAJAIAkgBiwAABCVAUElRgRAIAZBAWogB0YNAkEAIQICfwJAIAkgBiwAARCVASIBQcUARg0AQQEhCiABQf8BcUEwRg0AIAEMAQsgBkECaiAHRg0DQQIhCiABIQIgCSAGLAACEJUBCyEBIAggACAIKAIMIAgoAgggAyAEIAUgASACIAAoAgAoAiQRDQA2AgwgBiAKakEBaiEGDAELIAlBASAGLAAAEGAEQANAIAcgBkEBaiIGRwRAIAlBASAGLAAAEGANAQsLA0AgCEEMaiIBIAhBCGoQLA0CIAlBASABEDgQYEUNAiABED8aDAALAAsgCSAIQQxqIgEQOBDOASAJIAYsAAAQzgFGBEAgBkEBaiEGIAEQPxoMAQsgBEEENgIACyAEKAIAIQEMAQsLIARBBDYCAAsgCEEMaiAIQQhqECwEQCAEIAQoAgBBAnI2AgALIAgoAgwgCEEQaiQACxYAIAAgASACIAMgACgCACgCMBEJABoLPAAgACwAC0EASARAIAAoAggaIAAoAgAQLQsgACABKQIANwIAIAAgASgCCDYCCCABQQA6AAsgAUEAOgAACxMAIAIEQCAAIAEgAvwKAAALIAALKwEBfyMAQRBrIgIkACACIAE2AgxBwN0BIAAgAUEAQQAQ0QMaIAJBEGokAAsjAQF/IwBBEGsiASQAIAEgADYCDCABQQxqEOwBIAFBEGokAAsMACAAQYKGgCA2AAALEQAgABAjIAAQH0ECdGoQ9wELDQAgACgCACABKAIARgsOACAAECMgABAfahD3AQsPACAAIAAoAgAoAgwRAAALFgAgACABIAIgAyAAKAIAKAIgEQkAGgtEAQF/IAAoAgAhAiABEDEhACACQQhqIgEQayAASwR/IAEgABCCASgCAEEARwVBAAtFBEAQPQALIAJBCGogABCCASgCAAsRACAAIAEgASgCACgCHBEBAAsRACAAIAEgASgCACgCGBEBAAsQACAAQSBGIABBCWtBBUlyCw4AIAAoAghB/////wdxC9cBAQF/AkBBjN4BKAIAIgBBAE4EQCAARQ0BQZThASgCACAAQf////8DcUcNAQsCQEGQ3gEoAgBBCkYNAEHU3QEoAgAiAEHQ3QEoAgBGDQBB1N0BIABBAWo2AgAgAEEKOgAADwtBwN0BEN4BDwtBjN4BQYzeASgCACIAQf////8DIAAbNgIAAkACQEGQ3gEoAgBBCkYNAEHU3QEoAgAiAEHQ3QEoAgBGDQBB1N0BIABBAWo2AgAgAEEKOgAADAELQcDdARDeAQtBjN4BKAIAGkGM3gFBADYCAAvDAQEEfyMAQRBrIgckAAJAIABFDQAgBCgCDCEJIAIgAWsiBkEASgRAIAAgASAGIAAoAgAoAjARAwAgBkcNAQsgAyABayIBIAlIBEAgB0EEaiIGIAkgAWsiASAFELACIAAgBygCBCAGIAcsAA9BAEgbIAEgACgCACgCMBEDACEFIAYQIBogASAFRw0BCyADIAJrIgFBAEoEQCAAIAIgASAAKAIAKAIwEQMAIAFHDQELIARBADYCDCAAIQgLIAdBEGokACAIC14BA38gAEEANgIIIABCADcCACABKAIAIQMgASgCBCIBIANrIgRBAnUiAgRAIAAgAhCuAyAAKAIEIQIgBEUgASADRnJFBEAgAiADIAT8CgAACyAAIAIgBGo2AgQLIAALDQAgACgCACABQQJ0agsXACAAEEcEQCAAIAE2AgQPCyAAIAEQUAthAQF/IwBBEGsiAiQAIAIgADYCDAJAIAAgAUYNAANAIAIgAUEBayIBNgIIIAAgAU8NASACKAIMIAIoAggQ8wIgAiACKAIMQQFqIgA2AgwgAigCCCEBDAALAAsgAkEQaiQAC6wBAQR/IwBBEGsiByQAAkAgAEUNACAEKAIMIQYgAiABa0ECdSIIQQBKBEAgACABIAgQjQIgCEcNAQsgAyABa0ECdSIBIAZIBEAgACAHQQRqIAYgAWsiASAFEP0CIgUQIyABEI0CIQYgBRA5GiABIAZHDQELIAMgAmtBAnUiAUEASgRAIAAgAiABEI0CIAFHDQELIAQoAgwaIARBADYCDCAAIQkLIAdBEGokACAJCycBAX8jAEEQayIDJAAgAyACNgIMIABB5AAgASACENEBIANBEGokAAvbAQIBfwJ+QQEhBAJAIABCAFIgAUL///////////8AgyIFQoCAgICAgMD//wBWIAVCgICAgICAwP//AFEbDQAgAkIAUiADQv///////////wCDIgZCgICAgICAwP//AFYgBkKAgICAgIDA//8AURsNACAAIAKEIAUgBoSEUARAQQAPCyABIAODQgBZBEAgACACVCABIANTIAEgA1EbBEBBfw8LIAAgAoUgASADhYRCAFIPCyAAIAJWIAEgA1UgASADURsEQEF/DwsgACAChSABIAOFhEIAUiEECyAEC+wBAQR/IwBBEGsiBCQAIABBADYCBCMAQRBrIgUkACAEQQA6AA8gACAAKAIAQQxrKAIAahDZASEGIAAgACgCAEEMaygCAGohAwJAIAYEQCADKAJIBEAgACAAKAIAQQxrKAIAaigCSBDFAwsgBCAAIAAoAgBBDGsoAgBqENkBOgAPDAELIANBBBDVAQsgBUEQaiQAQQQhAyAELQAPBEAgACAAIAAoAgBBDGsoAgBqKAIYIgMgASACIAMoAgAoAiARAwAiATYCBEEGQQAgASACRxshAwsgACAAKAIAQQxrKAIAaiADENUBIARBEGokAAsEACAAC1ABAX4CQCADQcAAcQRAIAIgA0FAaq2IIQFCACECDAELIANFDQAgAkHAACADa62GIAEgA60iBIiEIQEgAiAEiCECCyAAIAE3AwAgACACNwMIC0MBA38CQCACRQ0AA0AgAC0AACIEIAEtAAAiBUYEQCABQQFqIQEgAEEBaiEAIAJBAWsiAg0BDAILCyAEIAVrIQMLIAMLCQBB+gsQrgIACxQBAX9BCBBTIgEgACkCADcDACABCwoAIAAgASAAa2oLGQEBfyABEMECIQIgACABNgIEIAAgAjYCAAskACAAQQJPBH8gAEECakF+cSIAIABBAWsiACAAQQJGGwVBAQsLlgEBA38CQCABELcCIQIjAEEQayIDJAAgAkH3////A00EQAJAIAIQvQEEQCAAIAIQUCAAIQQMAQsgA0EIaiACEJABQQFqEI8BIAMoAgwaIAAgAygCCCIENgIAIAAgAygCDBBcIAAgAjYCBAsgBCABIAIQZSADQQA2AgQgBCACQQJ0aiADQQRqEFYgA0EQaiQADAELEFsACwsRACAAIAEgASgCACgCLBEBAAvHAQEGfyMAQRBrIgQkACAAEPIBKAIAIQUCfyACKAIAIAAoAgBrIgNB/////wdJBEAgA0EBdAwBC0F/CyIDQQQgAxshAyABKAIAIQYgACgCACEHIAVB5ABGBH9BAAUgACgCAAsgAxDcASIIBEAgBUHkAEcEQCAAEKwBGgsgBEHjADYCBCAAIARBCGogCCAEQQRqEDYiBRDrAiAFEDUgASAAKAIAIAYgB2tqNgIAIAIgACgCACADQXxxajYCACAEQRBqJAAPCxA9AAsTACAAIAFBACAAKAIAKAI0EQMACxMAIAAgAUEAIAAoAgAoAiQRAwALQgEBfyMAQRBrIgUkACAFIAI2AgwgBSAENgIIIAVBBGogBUEMahBjIAAgASADIAUoAggQ0QEhABBiIAVBEGokACAAC0EBAX8jAEEQayIDJAAgAyACNgIMQaAgIAFB7CBBzSxBHCADQQxqIgEQVEHsIEHRLEEdIAEQVBAEIANBEGokACAAC+oCAQJ/IwBBEGsiCiQAIAogADYCDAJAAkACQCADKAIAIgsgAkcNACAJKAJgIABGBH9BKwUgACAJKAJkRw0BQS0LIQAgAyALQQFqNgIAIAsgADoAAAwBCyAGEB9FIAAgBUdyRQRAQQAhACAIKAIAIgEgB2tBnwFKDQIgBCgCACEAIAggAUEEajYCACABIAA2AgAMAQtBfyEAIAkgCUHoAGogCkEMahD5ASAJa0ECdSIFQRdKDQECQAJAAkAgAUEIaw4DAAIAAQsgASAFSg0BDAMLIAFBEEcgBUEWSHINACADKAIAIgEgAkYgASACa0ECSnINAiABQQFrLQAAQTBHDQJBACEAIARBADYCACADIAFBAWo2AgAgASAFLQDQnwE6AAAMAgsgAyADKAIAIgBBAWo2AgAgACAFQdCfAWotAAA6AAAgBCAEKAIAQQFqNgIAQQAhAAwBC0EAIQAgBEEANgIACyAKQRBqJAAgAAsKACAAQZjzARB6C+wCAQN/IwBBEGsiCiQAIAogADoADwJAAkACQCADKAIAIgsgAkcNACAAQf8BcSIMIAktABhGBH9BKwUgDCAJLQAZRw0BQS0LIQAgAyALQQFqNgIAIAsgADoAAAwBCyAGEB9FIAAgBUdyRQRAQQAhACAIKAIAIgEgB2tBnwFKDQIgBCgCACEAIAggAUEEajYCACABIAA2AgAMAQtBfyEAIAkgCUEaaiAKQQ9qEP0BIAlrIgVBF0oNAQJAAkACQCABQQhrDgMAAgABCyABIAVKDQEMAwsgAUEQRyAFQRZIcg0AIAMoAgAiASACRiABIAJrQQJKcg0CIAFBAWstAABBMEcNAkEAIQAgBEEANgIAIAMgAUEBajYCACABIAUtANCfAToAAAwCCyADIAMoAgAiAEEBajYCACAAIAVB0J8Bai0AADoAACAEIAQoAgBBAWo2AgBBACEADAELQQAhACAEQQA2AgALIApBEGokACAACwoAIABBkPMBEHoLZgIBfwF+IwBBEGsiAiQAIAACfiABRQRAQgAMAQsgAiABrUIAQfAAIAFnIgFBH3NrEEQgAikDCEKAgICAgIDAAIVBnoABIAFrrUIwhnwhAyACKQMACzcDACAAIAM3AwggAkEQaiQACxQAIABB3wBxIAAgAEHhAGtBGkkbCywBAX8Cf0EBENYBBEAgAUEBELQCDAELIAEQUwshAiAAIAE2AgQgACACNgIACyQAIABBC08EfyAAQQhqQXhxIgAgAEEBayIAIABBC0YbBUEKCwskAQJ/IwBBEGsiAiQAIAAgARDTASEDIAJBEGokACABIAAgAxsLPAAgAEEANgIIIABCADcCACAAIAEoAgA2AgAgACABKAIENgIEIAAgASgCCDYCCCABQQA2AgggAUIANwIACywBAX8gAEEANgIIIABCADcCACAAIAEoAgAiAiABKAIEIgEgASACaxDAAyAACwgAIABB/wFxC/wBAQN/IAAoAgQgACgCACIDa0ECdSICIAFJBEAjAEEgayIDJAACQCABIAJrIgIgACgCCCAAKAIEIgFrQQJ1TQRAIAAoAgQiASACQQJ0aiECA0AgASACRgRAIAAgAjYCBAUgAUEANgIAIAFBBGohAQwBCwsMAQsgA0EMaiAAIAEgACgCAGtBAnUgAmoQtgEgACgCBCAAKAIAa0ECdSAAEIcCIgQoAggiASACQQJ0aiECA0AgASACRwRAIAFBADYCACABQQRqIQEMAQsLIAQgAjYCCCAAIAQQhQIgBBCBAgsgA0EgaiQADwsgASACSQRAIAAgAyABQQJ0ajYCBAsLUgECf0HU3gEoAgAiASAAQQdqQXhxIgJqIQACQCACQQAgACABTRtFBEAgAD8AQRB0TQ0BIAAQGA0BC0GI6gFBMDYCAEF/DwtB1N4BIAA2AgAgAQt/AgF+A38CQCAAQoCAgIAQVARAIAAhAgwBCwNAIAFBAWsiASAAIABCCoAiAkIKfn2nQTByOgAAIABC/////58BViACIQANAAsLIAJQRQRAIAKnIQMDQCABQQFrIgEgAyADQQpuIgRBCmxrQTByOgAAIANBCUsgBCEDDQALCyABC78BAQN/IAAoAgQgACgCACIDayICIAFJBEAjAEEgayIDJAACQCABIAJrIgIgACgCCCAAKAIEIgFrTQRAIAAgAhCYAwwBCyACIANBDGogACABIAJqIAAoAgBrELQBIAAoAgQgACgCAGsgABDGASIEKAIIIgFqIQIDQCABIAJHBEAgAUEAOgAAIAFBAWohAQwBCwsgBCACNgIIIAAgBBDvASAEELoBCyADQSBqJAAPCyABIAJJBEAgACABIANqNgIECwt9AQN/AkACQCAAIgFBA3FFDQAgAS0AAEUEQEEADwsDQCABQQFqIgFBA3FFDQEgAS0AAA0ACwwBCwNAIAEiAkEEaiEBQYCChAggAigCACIDayADckGAgYKEeHFBgIGChHhGDQALA0AgAiIBQQFqIQIgAS0AAA0ACwsgASAAawsTAEEEENYBBEAgABAtDwsgABAtCwsAIAQgAjYCAEEDC3wBAn8jAEEQayICJAAgABBHBEAgACgCACAAEH4QqQELIAEQHxogARBHIQMgACABKAIINgIIIAAgASkCADcCACABQQAQUCACQQA2AgwgASACQQxqEFYCQCADIAAgAUYiAXJFDQALIAAQRyABckUEQCAAEF4aCyACQRBqJAALEAEBfyAAKAIAIABBADYCAAs3AQJ/IwBBEGsiAyQAIANBDGoiBCABECcgAiAEEJkBIgEQWTYCACAAIAEQWCAEECUgA0EQaiQACzUBAn8jAEEQayICJAAgAkEMaiIDIAAQJyADEEhB0J8BQeqfASABEG8gAxAlIAJBEGokACABCzcBAn8jAEEQayIDJAAgA0EMaiIEIAEQJyACIAQQmwEiARBZOgAAIAAgARBYIAQQJSADQRBqJAALkwEBA38CQCABEKgBIQIjAEEQayIDJAAgAkH3////B00EQAJAIAIQ1AEEQCAAIAIQUCAAIQQMAQsgA0EIaiACEJ8BQQFqEJ4BIAMoAgwaIAAgAygCCCIENgIAIAAgAygCDBBcIAAgAjYCBAsgBCABIAIQTSADQQA6AAcgAiAEaiADQQdqEF0gA0EQaiQADAELEFsACwtGAQF/IABB+PsAKAIAIgE2AgAgACABQQxrKAIAakGY/AAoAgA2AgAgAEGc/AAoAgA2AgggAEEMahD8ARogAEFAaxDaASAACxcAIAAgAzYCECAAIAI2AgwgACABNgIIC7kHAQV/An8gAEH//wNxIQMgAEEQdiEEIAJBAUYEQCADIAEtAABqIgBB8f8DayAAIABB8P8DSxsiACAEaiIBQRB0IgJBgIA8aiACIAFB8P8DSxsgAHIMAQsgAQR/AkACQAJAAkAgAkEQTwRAAkAgAkGvK0sEQANAQdsCIQUgASEAA0AgAyAALQAAaiIDIARqIAMgAC0AAWoiA2ogAyAALQACaiIDaiADIAAtAANqIgNqIAMgAC0ABGoiA2ogAyAALQAFaiIDaiADIAAtAAZqIgNqIAMgAC0AB2oiA2ogAyAALQAIaiIDaiADIAAtAAlqIgNqIAMgAC0ACmoiA2ogAyAALQALaiIDaiADIAAtAAxqIgNqIAMgAC0ADWoiA2ogAyAALQAOaiIDaiADIAAtAA9qIgNqIQQgAEEQaiEAIAVBAWsiBQ0ACyAEQfH/A3AhBCADQfH/A3AhAyABQbAraiEBIAJBsCtrIgJBrytLDQALIAJFDQYgAkEQSQ0BCwNAIAMgAS0AAGoiACAEaiAAIAEtAAFqIgBqIAAgAS0AAmoiAGogACABLQADaiIAaiAAIAEtAARqIgBqIAAgAS0ABWoiAGogACABLQAGaiIAaiAAIAEtAAdqIgBqIAAgAS0ACGoiAGogACABLQAJaiIAaiAAIAEtAApqIgBqIAAgAS0AC2oiAGogACABLQAMaiIAaiAAIAEtAA1qIgBqIAAgAS0ADmoiAGogACABLQAPaiIDaiEEIAFBEGohASACQRBrIgJBD0sNAAsgAkUNBAsgAkEDcSIHDQEgAiEADAILAkAgAkUNAAJAIAJBA3EiB0UEQCACIQAMAQsgAiEAIAEhBQNAIABBAWshACADIAUtAABqIgMgBGohBCAFQQFqIgEhBSAGQQFqIgYgB0cNAAsLIAJBBEkNAANAIAMgAS0AAGoiAiABLQABaiIFIAEtAAJqIgYgAS0AA2oiAyAGIAUgAiAEampqaiEEIAFBBGohASAAQQRrIgANAAsLIARB8f8DcEEQdCADQfH/A2sgAyADQfD/A0sbcgwFCyACIQAgASEFA0AgAEEBayEAIAMgBS0AAGoiAyAEaiEEIAVBAWoiASEFIAZBAWoiBiAHRw0ACwsgAkEESQ0AA0AgAyABLQAAaiICIAEtAAFqIgUgAS0AAmoiBiABLQADaiIDIAYgBSACIARqampqIQQgAUEEaiEBIABBBGsiAA0ACwsgBEHx/wNwIQQgA0Hx/wNwIQMLIARBEHQgA3IFQQELCws6AQF/IAFBAEgEQBCMAQALQf////8HIAAoAgggACgCAGsiAEEBdCICIAEgASACSRsgAEH/////A08bCxwBAX8gACgCBCIBQQlPBEAgARAeIABBADYCBAsLPgEBfyABQYCAgIAETwRAEIwBAAtB/////wMgACgCCCAAKAIAayIAQQF1IgIgASABIAJJGyAAQfz///8HTxsLSQECfyAAKAIEIgZBCHUhBSAGQQFxBEAgAigCACAFEOgBIQULIAAoAgAiACABIAIgBWogA0ECIAZBAnEbIAQgACgCACgCGBELAAuqAQEDfyMAQRBrIgIkACACIAE6AA8CQAJAAn8gABBHIgRFBEBBCiEBIAAQXgwBCyAAEH5BAWshASAAKAIECyIDIAFGBEAgACABQQEgASABEPQBIAAQIxoMAQsgABAjGiAEDQAgACIBIANBAWoQUAwBCyAAKAIAIQEgACADQQFqNgIECyABIANqIgAgAkEPahBdIAJBADoADiAAQQFqIAJBDmoQXSACQRBqJAALoQIBA38jAEEgayIIJABB9////wciCSABQX9zaiACTwRAIAAQIyEKIAFB8////wNJBEAgCCABQQF0NgIcIAggASACajYCECAIQRBqIAhBHGoQoAEoAgAQnwFBAWohCQsgCEEcaiAIQRhqIAAQVSgCABC8ASAIQRBqIAkQngEgCCgCECECIAgoAhQaIAQEQCACIAogBBBNCyAGBEAgAiAEaiAHIAYQTQsgAyAEIAVqIglrIQcgAyAJRwRAIAIgBGogBmogBCAKaiAFaiAHEE0LIAFBCkcEQCAKEIsCCyAAIAI2AgAgACAIKAIUEFwgACAEIAZqIAdqIgA2AgQgCEEAOgAPIAAgAmogCEEPahBdIAhBHGoQuwEgCEEgaiQADwsQWwALCQAgAEEBEKgCCwoAIAAoAgAQHxoLCQAgACABEFUaCwcAIABBAkkLBABBBAsoAQF/IAAgACgCBEEBayIBNgIEIAFBf0YEQCAAIAAoAgAoAggRAgALC5UBAQN/IwBBEGsiBCQAIAQgATYCDCAEIAM2AgggBEEEaiAEQQxqEGMgBCgCCCEDIwBBEGsiASQAIAEgAzYCDCABIAM2AghBfyEFAkBBAEEAIAIgAxDRASIDQQBIDQAgACADQQFqIgMQNCIANgIAIABFDQAgACADIAIgASgCDBDRASEFCyABQRBqJAAQYiAEQRBqJAAgBQsPACAAIAAoAgAoAiQRAAALEQAgACABIAEoAgAoAiARAQALDgAgACABKAIANgIAIAALCABB/////wcLBQBB/wALOwAgACADNgIQIAAgAQR/IAEQUwVBAAsiAzYCACAAIAIgA2oiAjYCCCAAIAEgA2o2AgwgACACNgIEIAALYQEBfyMAQRBrIgIkACACIAA2AgwCQCAAIAFGDQADQCACIAFBBGsiATYCCCAAIAFPDQEgAigCDCACKAIIENcBIAIgAigCDEEEaiIANgIMIAIoAgghAQwACwALIAJBEGokAAs5AgF/AX4jAEEQayIEJAAgAykDACEFIAQgAykDCDcDCCAEIAU3AwAgACABIAIgBBDAASAEQRBqJAAL0AEBAn8gAkGAEHEEQCAAQSs6AAAgAEEBaiEACyACQYAIcQRAIABBIzoAACAAQQFqIQALIAJBhAJxIgNBhAJHBEAgAEGu1AA7AAAgAEECaiEACyACQYCAAXEhAgNAIAEtAAAiBARAIAAgBDoAACAAQQFqIQAgAUEBaiEBDAELCyAAAn8CQCADQYACRwRAIANBBEcNAUHGAEHmACACGwwCC0HFAEHlACACGwwBC0HBAEHhACACGyADQYQCRg0AGkHHAEHnACACGws6AAAgA0GEAkcLKwEBfyMAQRBrIgUkACAFIAQoAgA2AgAgACABIAIgAyAFEJYBIAVBEGokAAuqAQEBfwJAIANBgBBxRSACRXINACADQcoAcSIEQQhGIARBwABGcg0AIABBKzoAACAAQQFqIQALIANBgARxBEAgAEEjOgAAIABBAWohAAsDQCABLQAAIgQEQCAAIAQ6AAAgAEEBaiEAIAFBAWohAQwBCwsgAAJ/Qe8AIANBygBxIgFBwABGDQAaQdgAQfgAIANBgIABcRsgAUEIRg0AGkHkAEH1ACACGws6AAALDAAgABAjIAFBAnRqC5IEAQt/IwBBgAFrIgokACAKIAE2AnwgAiADELUCIQggCkHjADYCECAKQQhqQQAgCkEQaiIJEDYhDwJAAkACQCAIQeUATwRAIAgQNCIJRQ0BIA8gCRA8CyAJIQcgAiEBA0AgASADRgRAA0AgACAKQfwAaiIBECtBASAIGwRAIAAgARArBEAgBSAFKAIAQQJyNgIACwNAIAIgA0YNBiAJLQAAQQJGDQcgCUEBaiEJIAJBDGohAgwACwALIAAQNyEOIAZFBEAgBCAOEEEhDgsgDUEBaiEMQQAhECAJIQcgAiEBA0AgASADRgRAIAwhDSAQRQ0CIAAQPhogCSEHIAIhASAIIAtqQQJJDQIDQCABIANGBEAMBAUCQCAHLQAAQQJHDQAgARAfIA1GDQAgB0EAOgAAIAtBAWshCwsgB0EBaiEHIAFBDGohAQwBCwALAAUCQCAHLQAAQQFHDQAgASANEMwBKAIAIRECQCAGBH8gEQUgBCAREEELIA5GBEBBASEQIAEQHyAMRw0CIAdBAjoAACALQQFqIQsMAQsgB0EAOgAACyAIQQFrIQgLIAdBAWohByABQQxqIQEMAQsACwALAAUgB0ECQQEgARBaIgwbOgAAIAdBAWohByABQQxqIQEgCyAMaiELIAggDGshCAwBCwALAAsQPQALIAUgBSgCAEEEcjYCAAsgDxA1IApBgAFqJAAgAgsRACAAIAEgACgCACgCDBEEAAuTBAELfyMAQYABayIKJAAgCiABNgJ8IAIgAxC1AiEIIApB4wA2AhAgCkEIakEAIApBEGoiCRA2IQ8CQAJAAkAgCEHlAE8EQCAIEDQiCUUNASAPIAkQPAsgCSEHIAIhAQNAIAEgA0YEQANAIAAgCkH8AGoiARAsQQEgCBsEQCAAIAEQLARAIAUgBSgCAEECcjYCAAsDQCACIANGDQYgCS0AAEECRg0HIAlBAWohCSACQQxqIQIMAAsACyAAEDghDiAGRQRAIAQgDhDOASEOCyANQQFqIQxBACEQIAkhByACIQEDQCABIANGBEAgDCENIBBFDQIgABA/GiAJIQcgAiEBIAggC2pBAkkNAgNAIAEgA0YEQAwEBQJAIActAABBAkcNACABEB8gDUYNACAHQQA6AAAgC0EBayELCyAHQQFqIQcgAUEMaiEBDAELAAsABQJAIActAABBAUcNACABIA0QIiwAACERAkAgBgR/IBEFIAQgERDOAQsgDkYEQEEBIRAgARAfIAxHDQIgB0ECOgAAIAtBAWohCwwBCyAHQQA6AAALIAhBAWshCAsgB0EBaiEHIAFBDGohAQwBCwALAAsABSAHQQJBASABEFoiDBs6AAAgB0EBaiEHIAFBDGohASALIAxqIQsgCCAMayEIDAELAAsACxA9AAsgBSAFKAIAQQRyNgIACyAPEDUgCkGAAWokACACC0oBAn8CQCAALQAAIgJFIAIgAS0AACIDR3INAANAIAEtAAEhAyAALQABIgJFDQEgAUEBaiEBIABBAWohACACIANGDQALCyACIANrC4QBAQJ/IwBBoAFrIgQkACAEIAAgBEGeAWogARsiADYClAEgBCABQQFrIgVBACABIAVPGzYCmAEgBEEAQZAB/AsAIARBfzYCTCAEQeIANgIkIARBfzYCUCAEIARBnwFqNgIsIAQgBEGUAWo2AlQgAEEAOgAAIAQgAiADEM0DIARBoAFqJAALuwIBBH8gA0H87QEgAxsiBSgCACEDAkACfwJAIAFFBEAgAw0BQQAPC0F+IAJFDQEaAkAgAwRAIAIhBAwBCyABLQAAIgPAIgRBAE4EQCAABEAgACADNgIACyAEQQBHDwtB3OEBKAIAKAIARQRAQQEgAEUNAxogACAEQf+/A3E2AgBBAQ8LIANBwgFrIgNBMksNASADQQJ0KAKQgQEhAyACQQFrIgRFDQMgAUEBaiEBCyABLQAAIgZBA3YiB0EQayADQRp1IAdqckEHSw0AA0AgBEEBayEEIAZB/wFxQYABayADQQZ0ciIDQQBOBEAgBUEANgIAIAAEQCAAIAM2AgALIAIgBGsPCyAERQ0DIAFBAWoiASwAACIGQUBIDQALCyAFQQA2AgBBiOoBQRk2AgBBfwsPCyAFIAM2AgBBfgsNACAAKAIAIAEoAgBJCwcAIABBC0kLJgAgACAAKAIYRSAAKAIQIAFyciIBNgIQIAAoAhQgAXEEQBA9AAsLBwAgAEEISwscAQF/IAAoAgAhAiAAIAEoAgA2AgAgASACNgIACwwAIABBDGoQ2gEgAAsIACAAKAIQRQsIACAAEIkCGgusCwEHfyAAIAFqIQUCQAJAIAAoAgQiAkEBcQ0AIAJBAnFFDQEgACgCACICIAFqIQECQAJAAkAgACACayIAQaDqASgCAEcEQCAAKAIMIQMgAkH/AU0EQCADIAAoAggiBEcNAkGM6gFBjOoBKAIAQX4gAkEDdndxNgIADAULIAAoAhghBiAAIANHBEAgACgCCCICIAM2AgwgAyACNgIIDAQLIAAoAhQiBAR/IABBFGoFIAAoAhAiBEUNAyAAQRBqCyECA0AgAiEHIAQiA0EUaiECIAMoAhQiBA0AIANBEGohAiADKAIQIgQNAAsgB0EANgIADAMLIAUoAgQiAkEDcUEDRw0DQZTqASABNgIAIAUgAkF+cTYCBCAAIAFBAXI2AgQgBSABNgIADwsgBCADNgIMIAMgBDYCCAwCC0EAIQMLIAZFDQACQCAAKAIcIgJBAnQiBCgCvOwBIABGBEAgBEG87AFqIAM2AgAgAw0BQZDqAUGQ6gEoAgBBfiACd3E2AgAMAgsCQCAAIAYoAhBGBEAgBiADNgIQDAELIAYgAzYCFAsgA0UNAQsgAyAGNgIYIAAoAhAiAgRAIAMgAjYCECACIAM2AhgLIAAoAhQiAkUNACADIAI2AhQgAiADNgIYCwJAAkACQAJAIAUoAgQiAkECcUUEQEGk6gEoAgAgBUYEQEGk6gEgADYCAEGY6gFBmOoBKAIAIAFqIgE2AgAgACABQQFyNgIEIABBoOoBKAIARw0GQZTqAUEANgIAQaDqAUEANgIADwtBoOoBKAIAIgggBUYEQEGg6gEgADYCAEGU6gFBlOoBKAIAIAFqIgE2AgAgACABQQFyNgIEIAAgAWogATYCAA8LIAJBeHEgAWohASAFKAIMIQMgAkH/AU0EQCAFKAIIIgQgA0YEQEGM6gFBjOoBKAIAQX4gAkEDdndxNgIADAULIAQgAzYCDCADIAQ2AggMBAsgBSgCGCEGIAMgBUcEQCAFKAIIIgIgAzYCDCADIAI2AggMAwsgBSgCFCIEBH8gBUEUagUgBSgCECIERQ0CIAVBEGoLIQIDQCACIQcgBCIDQRRqIQIgAygCFCIEDQAgA0EQaiECIAMoAhAiBA0ACyAHQQA2AgAMAgsgBSACQX5xNgIEIAAgAUEBcjYCBCAAIAFqIAE2AgAMAwtBACEDCyAGRQ0AAkAgBSgCHCICQQJ0IgQoArzsASAFRgRAIARBvOwBaiADNgIAIAMNAUGQ6gFBkOoBKAIAQX4gAndxNgIADAILAkAgBSAGKAIQRgRAIAYgAzYCEAwBCyAGIAM2AhQLIANFDQELIAMgBjYCGCAFKAIQIgIEQCADIAI2AhAgAiADNgIYCyAFKAIUIgJFDQAgAyACNgIUIAIgAzYCGAsgACABQQFyNgIEIAAgAWogATYCACAAIAhHDQBBlOoBIAE2AgAPCyABQf8BTQRAIAFBeHFBtOoBaiECAn9BjOoBKAIAIgNBASABQQN2dCIBcUUEQEGM6gEgASADcjYCACACDAELIAIoAggLIQEgAiAANgIIIAEgADYCDCAAIAI2AgwgACABNgIIDwtBHyEDIAFB////B00EQCABQSYgAUEIdmciAmt2QQFxIAJBAXRrQT5qIQMLIAAgAzYCHCAAQgA3AhAgA0ECdEG87AFqIQICQAJAQZDqASgCACIEQQEgA3QiB3FFBEBBkOoBIAQgB3I2AgAgAiAANgIAIAAgAjYCGAwBCyABQRkgA0EBdmtBACADQR9HG3QhAyACKAIAIQIDQCACIgQoAgRBeHEgAUYNAiADQR12IQIgA0EBdCEDIAQgAkEEcWoiBygCECICDQALIAcgADYCECAAIAQ2AhgLIAAgADYCDCAAIAA2AggPCyAEKAIIIgEgADYCDCAEIAA2AgggAEEANgIYIAAgBDYCDCAAIAE2AggLC40IAQt/IABFBEAgARA0DwsgAUFATwRAQYjqAUEwNgIAQQAPCwJ/QRAgAUELakF4cSABQQtJGyEGIABBCGsiBCgCBCIJQXhxIQgCQCAJQQNxRQRAIAZBgAJJDQEgBkEEaiAITQRAIAQhAiAIIAZrQeztASgCAEEBdE0NAgtBAAwCCyAEIAhqIQcCQCAGIAhNBEAgCCAGayIDQRBJDQEgBCAGIAlBAXFyQQJyNgIEIAQgBmoiAiADQQNyNgIEIAcgBygCBEEBcjYCBCACIAMQ2wEMAQtBpOoBKAIAIAdGBEBBmOoBKAIAIAhqIgggBk0NAiAEIAYgCUEBcXJBAnI2AgQgBCAGaiIDIAggBmsiAkEBcjYCBEGY6gEgAjYCAEGk6gEgAzYCAAwBC0Gg6gEoAgAgB0YEQEGU6gEoAgAgCGoiAyAGSQ0CAkAgAyAGayICQRBPBEAgBCAGIAlBAXFyQQJyNgIEIAQgBmoiCCACQQFyNgIEIAMgBGoiAyACNgIAIAMgAygCBEF+cTYCBAwBCyAEIAlBAXEgA3JBAnI2AgQgAyAEaiICIAIoAgRBAXI2AgRBACECQQAhCAtBoOoBIAg2AgBBlOoBIAI2AgAMAQsgBygCBCIDQQJxDQEgA0F4cSAIaiILIAZJDQEgCyAGayEMIAcoAgwhBQJAIANB/wFNBEAgBygCCCICIAVGBEBBjOoBQYzqASgCAEF+IANBA3Z3cTYCAAwCCyACIAU2AgwgBSACNgIIDAELIAcoAhghCgJAIAUgB0cEQCAHKAIIIgIgBTYCDCAFIAI2AggMAQsCQCAHKAIUIgIEfyAHQRRqBSAHKAIQIgJFDQEgB0EQagshCANAIAghAyACIgVBFGohCCACKAIUIgINACAFQRBqIQggBSgCECICDQALIANBADYCAAwBC0EAIQULIApFDQACQCAHKAIcIgNBAnQiAigCvOwBIAdGBEAgAkG87AFqIAU2AgAgBQ0BQZDqAUGQ6gEoAgBBfiADd3E2AgAMAgsCQCAHIAooAhBGBEAgCiAFNgIQDAELIAogBTYCFAsgBUUNAQsgBSAKNgIYIAcoAhAiAgRAIAUgAjYCECACIAU2AhgLIAcoAhQiAkUNACAFIAI2AhQgAiAFNgIYCyAMQQ9NBEAgBCAJQQFxIAtyQQJyNgIEIAQgC2oiAiACKAIEQQFyNgIEDAELIAQgBiAJQQFxckECcjYCBCAEIAZqIgMgDEEDcjYCBCAEIAtqIgIgAigCBEEBcjYCBCADIAwQ2wELIAQhAgsgAgsiAgRAIAJBCGoPCyABEDQiBEUEQEEADwsgBCAAQXxBeCAAQQRrKAIAIgJBA3EbIAJBeHFqIgIgASABIAJLGxBxGiAAEC0gBAsWACAARQRAQQAPC0GI6gEgADYCAEF/C30BAn8jAEEQayIBJAAgAUEKOgAPAkACQCAAKAIQIgIEfyACBSAAEN8BDQIgACgCEAsgACgCFCICRg0AIAAoAlBBCkYNACAAIAJBAWo2AhQgAkEKOgAADAELIAAgAUEPakEBIAAoAiQRAwBBAUcNACABLQAPGgsgAUEQaiQAC1kBAX8gACAAKAJIIgFBAWsgAXI2AkggACgCACIBQQhxBEAgACABQSByNgIAQX8PCyAAQgA3AgQgACAAKAIsIgE2AhwgACABNgIUIAAgASAAKAIwajYCEEEAC+IBAQJ/IAJBAEchAwJAAkACQCAAQQNxRSACRXINACABQf8BcSEEA0AgAC0AACAERg0CIAJBAWsiAkEARyEDIABBAWoiAEEDcUUNASACDQALCyADRQ0BIAFB/wFxIgMgAC0AAEYgAkEESXJFBEAgA0GBgoQIbCEDA0BBgIKECCAAKAIAIANzIgRrIARyQYCBgoR4cUGAgYKEeEcNAiAAQQRqIQAgAkEEayICQQNLDQALCyACRQ0BCyABQf8BcSEBA0AgASAALQAARgRAIAAPCyAAQQFqIQAgAkEBayICDQALC0EACwIACwQAQQELoBABFn8jAEFAaiIGQgA3AzAgBkIANwM4IAZCADcDICAGQgA3AygCQAJAAn8CQAJ/IAIEQCACQQRPBEAgAUEGaiEIIAFBBGohDSABQQJqIQsgAkF8cSEMA0AgBkEgaiIPIAEgCkEBdCIJai8BAEEBdGoiESARLwEAQQFqOwEAIAkgC2ovAQBBAXQgD2oiESARLwEAQQFqOwEAIAkgDWovAQBBAXQgD2oiESARLwEAQQFqOwEAIAggCWovAQBBAXQgD2oiCSAJLwEAQQFqOwEAIApBBGohCiAOQQRqIg4gDEcNAAsLIAJBA3EiCQRAA0AgBkEgaiABIApBAXRqLwEAQQF0aiIIIAgvAQBBAWo7AQAgCkEBaiEKIAdBAWoiByAJRw0ACwsgBCgCACIKIAYvAT4iEEUNARpBDyELDAILIAQoAgALIQpBACEQIAYvATwEQEEOIQsMAQsgBi8BOgRAQQ0hCwwBCyAGLwE4BEBBDCELDAELIAYvATYEQEELIQsMAQsgBi8BNARAQQohCwwBCyAGLwEyBEBBCSELDAELIAYvATAEQEEIIQsMAQsgBi8BLgRAQQchCwwBCyAGLwEsBEBBBiELDAELIAYvASoEQEEFIQsMAQsgBi8BKARAQQQhCwwBCyAGLwEmBEBBAyELDAELIAYvASQEQEECIQsMAQsgBi8BIkUEQCADIAMoAgAiAEEEajYCACAAQcACNgEAIAMgAygCACIAQQRqNgIAIABBwAI2AQBBASEMDAMLIApBAEchCUEBIQtBASEKQQAMAQsgCiALIAogC0kbIQlBASEKAkADQCAGQSBqIApBAXRqLwEADQEgCkEBaiIKIAtHDQALIAshCgtBAQshD0F/IQcgBi8BIiIIQQJLDQFBBCAIQQF0a0H+/wNxIAYvASQiDWsiDkEASA0BIA5BAXQgBi8BJiIOayIMQQBIDQEgDEEBdCAGLwEoIgxrIhFBAEgNASARQQF0IAYvASoiEWsiGEEASA0BIBhBAXQgBi8BLCIYayISQQBIDQEgEkEBdCAGLwEuIhJrIhNBAEgNASATQQF0IAYvATAiE2siFEEASA0BIBRBAXQgBi8BMiIUayIVQQBIDQEgFUEBdCAGLwE0IhVrIhdBAEgNASAXQQF0IAYvATYiF2siFkEASA0BIBZBAXQgBi8BOCIWayIZQQBIDQEgGUEBdCAGLwE6IhlrIhpBAEgNASAaQQF0IAYvATwiGmsiG0EASA0BIBtBAXQiGyAQSSAQIBtHQQAgAEUgD3Ibcg0BIAkgCkshEEEAIQcgBkEAOwECIAYgCDsBBCAGIAggDWoiCDsBBiAGIAggDmoiCDsBCCAGIAggDGoiCDsBCiAGIAggEWoiCDsBDCAGIAggGGoiCDsBDiAGIAggEmoiCDsBECAGIAggE2oiCDsBEiAGIAggFGoiCDsBFCAGIAggFWoiCDsBFiAGIAggF2oiCDsBGCAGIAggFmoiCDsBGiAGIAggGWoiCDsBHCAGIAggGmo7AR4CQCACRQ0AIAJBAUcEQCACQX5xIQhBACEOA0AgASAHQQF0ai8BACINBEAgBiANQQF0aiINIA0vAQAiDUEBajsBACAFIA1BAXRqIAc7AQALIAEgB0EBciINQQF0ai8BACIMBEAgBiAMQQF0aiIMIAwvAQAiDEEBajsBACAFIAxBAXRqIA07AQALIAdBAmohByAOQQJqIg4gCEcNAAsLIAJBAXFFDQAgASAHQQF0ai8BACICRQ0AIAYgAkEBdGoiAiACLwEAIgJBAWo7AQAgBSACQQF0aiAHOwEACyAJIAogEBshDEEUIRJBACEXIAUiCCERQQAhEwJAAkACQCAADgICAAELQQEhByAMQQlLDQNBgQIhEkHA7QAhEUGA7QAhCEEBIRMMAQsgAEECRiEXQQAhEkHA7gAhEUGA7gAhCCAAQQJHBEAMAQtBASEHIAxBCUsNAgtBASAMdCIUQQFrIRkgAygCACEVQQAhAiAMIQlBACEAQQAhEEF/IQ0DQEEBIAl0IRgCQANAAn9BACASIAUgAkEBdGovAQAiCUEBaksNABogCSASSQRAQQAhCUHgAAwBCyAIIAkgEmtBAXQiB2ovAQAhCSAHIBFqLQAACyEOQX8gCiAAayIPdCEaIBUgECAAdkECdGohGyAYIQcDQCAbIAcgGmoiB0ECdGoiFiAJOwECIBYgDzoAASAWIA46AAAgBw0AC0EBIApBAWt0IQ4DQCAOIgdBAXYhDiAHIBBxDQALIAZBIGogCkEBdGoiCSAJLwEAQQFrIgk7AQAgB0EBayAQcSAHakEAIAcbIRAgAkEBaiECIAlB//8DcUUEQCAKIAtGDQIgASAFIAJBAXRqLwEAQQF0ai8BACEKCyAKIAxNDQAgECAZcSIOIA1GDQALQQEgCiAAIAwgABsiAGsiCXQhDyAKIAtJBEAgAEEBaiEWIAsgAGshDSAKIQcCQANAIA8gBkEgaiAHQQF0ai8BAGsiB0EATA0BIAdBAXQhDyAJIBZqIQcgCUEBaiEJIAcgC0kNAAsgDSEJC0EBIAl0IQ8LQQEhByATIA8gFGoiFEHUBktxIBcgFEHQBEtxcg0DIAMoAgAiDSAOQQJ0aiIHIAw6AAEgByAJOgAAIAcgFSAYQQJ0aiIVIA1rQQJ2OwECIA4hDQwBCwsgEARAIBUgEEECdGoiAEEAOwECIAAgDzoAASAAQcAAOgAACyADIAMoAgAgFEECdGo2AgALIAQgDDYCAEEAIQcLIAcLqgEBA38gASwAC0EATgRAIAAgASkCADcCACAAIAEoAgg2AggPCyABKAIAIQQgASgCBCECIwBBEGsiAyQAAkACQAJAIAIQ1AEEQCAAIgEgAhBQDAELIAJB9////wdLDQEgA0EIaiACEJ8BQQFqEJ4BIAMoAgwaIAAgAygCCCIBNgIAIAAgAygCDBBcIAAgAjYCBAsgASAEIAJBAWoQTSADQRBqJAAMAQsQWwALC0sBAn8gACgCBCIHQQh1IQYgB0EBcQRAIAMoAgAgBhDoASEGCyAAKAIAIgAgASACIAMgBmogBEECIAdBAnEbIAUgACgCACgCFBEKAAsgAAJAIAEgACgCBEcNACAAKAIcQQFGDQAgACACNgIcCwuaAQAgAEEBOgA1AkAgAiAAKAIERw0AIABBAToANAJAIAAoAhAiAkUEQCAAQQE2AiQgACADNgIYIAAgATYCECADQQFHDQIgACgCMEEBRg0BDAILIAEgAkYEQCAAKAIYIgJBAkYEQCAAIAM2AhggAyECCyAAKAIwQQFHDQIgAkEBRg0BDAILIAAgACgCJEEBajYCJAsgAEEBOgA2CwsKACAAIAFqKAIAC3YBAX8gACgCJCIDRQRAIAAgAjYCGCAAIAE2AhAgAEEBNgIkIAAgACgCODYCFA8LAkACQCAAKAIUIAAoAjhHDQAgACgCECABRw0AIAAoAhhBAkcNASAAIAI2AhgPCyAAQQE6ADYgAEECNgIYIAAgA0EBajYCJAsLrQEBA38jAEEQayICJAAgAiABNgIMAkACQAJ/IAAQRyIERQRAQQEhASAAEF4MAQsgABB+QQFrIQEgACgCBAsiAyABRgRAIAAgAUEBIAEgARDoAiAAECMaDAELIAAQIxogBA0AIAAiASADQQFqEFAMAQsgACgCACEBIAAgA0EBajYCBAsgASADQQJ0aiIAIAJBDGoQViACQQA2AgggAEEEaiACQQhqEFYgAkEQaiQACwUAED0ACycBAX8gACgCACEBIwBBEGsiACQAIAAgATYCDCAAKAIMIABBEGokAAsXACAAKAIIEC5HBEAgACgCCBCgAwsgAAs0AQF/IwBBEGsiAyQAIAMgAjYCDCADQQhqIANBDGoQYyAAIAEQlgIhABBiIANBEGokACAAC40BAQN/IAEoAgQgACgCACICIAAoAgQiA2tqIQQgAyACayIDBEAgBCACIAP8CgAACyABIAQ2AgQgACAAKAIAIgI2AgQgACABKAIENgIAIAEgAjYCBCAAKAIEIQIgACABKAIINgIEIAEgAjYCCCAAKAIIIQIgACABKAIMNgIIIAEgAjYCDCABIAEoAgQ2AgALMwEBfyMAQRBrIgIkACACIAAoAgA2AgwgAiACKAIMIAFBAnRqNgIMIAIoAgwgAkEQaiQACxkBAX9BASEBIAAQRwR/IAAQfkEBawVBAQsLBwAgAEEEagswAQF/IwBBEGsiAiQAIAIgACgCADYCDCACIAIoAgwgAWo2AgwgAigCDCACQRBqJAAL9wEBBX8jAEEQayIGJAAgBkEMaiIIIAZBCGogABBVKAIAELwBIwBBEGsiBSQAAkBB9////wcgAWsgAk8EQCAAECMhByAFQQRqIgkgAUHz////A0kEfyAFIAFBAXQ2AgwgBSABIAJqNgIEIAkgBUEMahCgASgCABCfAUEBagVB9////wcLEJ4BIAUoAgQhAiAFKAIIGiAEBEAgAiAHIAQQTQsgAyAERwRAIAIgBGogBCAHaiADIARrEE0LIAFBCkcEQCAHEIsCCyAAIAI2AgAgACAFKAIIEFwgBUEQaiQADAELEFsACyAAIAM2AgQgCBC7ASAGQRBqJAALCgAgASAAa0ECdQsPACAAIAAoAgBBBGo2AgALIAEBfyMAQRBrIgEkACABQQxqIAAQVSgCACABQRBqJAALDwAgACAAKAIAQQFqNgIAC1kBAn8jAEEQayIDJAAgAigCACEEIAACfyABIABrQQJ1IgIEQANAIAAgBCAAKAIARg0CGiAAQQRqIQAgAkEBayICDQALC0EACyIAIAEgABsQjgEgA0EQaiQAC/gDAQF/IwBBEGsiDCQAIAwgADYCDAJAAkAgACAFRgRAIAEtAABBAUcNAUEAIQAgAUEAOgAAIAQgBCgCACIBQQFqNgIAIAFBLjoAACAHEB9FDQIgCSgCACIBIAhrQZ8BSg0CIAooAgAhAiAJIAFBBGo2AgAgASACNgIADAILAkACQCAAIAZHDQAgBxAfRQ0AIAEtAABBAUcNAiAJKAIAIgAgCGtBnwFKDQEgCigCACEBIAkgAEEEajYCACAAIAE2AgBBACEAIApBADYCAAwDCyALIAtB8ABqIAxBDGoQ+QEgC2siAEECdSIGQRtKDQEgBkHQnwFqLAAAIQUCQAJAIABBe3EiAEHYAEcEQCAAQeAARw0BIAMgBCgCACIBRwRAQX8hACABQQFrLAAAEJ0BIAIsAAAQnQFHDQYLIAQgAUEBajYCACABIAU6AAAMAwsgAkHQADoAAAwBCyAFEJ0BIgAgAiwAAEcNACACIAAQsQM6AAAgAS0AAEEBRw0AIAFBADoAACAHEB9FDQAgCSgCACIAIAhrQZ8BSg0AIAooAgAhASAJIABBBGo2AgAgACABNgIACyAEIAQoAgAiAEEBajYCACAAIAU6AABBACEAIAZBFUoNAiAKIAooAgBBAWo2AgAMAgtBACEADAELQX8hAAsgDEEQaiQAIAALUAECfyMAQRBrIgYkACAGQQxqIgUgARAnIAUQSEHQnwFB7J8BIAIQbyADIAUQmQEiARB4NgIAIAQgARBZNgIAIAAgARBYIAUQJSAGQRBqJAALGAAgAEGQ9wA2AgAgAEEgahAgGiAAEJQCCy8BAX8jAEEQayIDJAAgACAAIAIsAAAgASAAaxDgASIAIAEgABsQjgEgA0EQaiQAC/ADAQF/IwBBEGsiDCQAIAwgADoADwJAAkAgACAFRgRAIAEtAABBAUcNAUEAIQAgAUEAOgAAIAQgBCgCACIBQQFqNgIAIAFBLjoAACAHEB9FDQIgCSgCACIBIAhrQZ8BSg0CIAooAgAhAiAJIAFBBGo2AgAgASACNgIADAILAkACQCAAIAZHDQAgBxAfRQ0AIAEtAABBAUcNAiAJKAIAIgAgCGtBnwFKDQEgCigCACEBIAkgAEEEajYCACAAIAE2AgBBACEAIApBADYCAAwDCyALIAtBHGogDEEPahD9ASALayIFQRtKDQEgBUHQnwFqLAAAIQYCQAJAAkACQCAFQX5xQRZrDgMBAgACCyADIAQoAgAiAUcEQEF/IQAgAUEBaywAABCdASACLAAAEJ0BRw0GCyAEIAFBAWo2AgAgASAGOgAADAMLIAJB0AA6AAAMAQsgBhCdASIAIAIsAABHDQAgAiAAELEDOgAAIAEtAABBAUcNACABQQA6AAAgBxAfRQ0AIAkoAgAiACAIa0GfAUoNACAKKAIAIQEgCSAAQQRqNgIAIAAgATYCAAsgBCAEKAIAIgBBAWo2AgAgACAGOgAAQQAhACAFQRVKDQIgCiAKKAIAQQFqNgIADAILQQAhAAwBC0F/IQALIAxBEGokACAAC1ABAn8jAEEQayIGJAAgBkEMaiIFIAEQJyAFEElB0J8BQeyfASACEHkgAyAFEJsBIgEQeDoAACAEIAEQWToAACAAIAEQWCAFECUgBkEQaiQAC34CAn8CfiMAQaABayIEJAAgBCABNgI8IAQgATYCFCAEQX82AhggBEEQaiIFQgAQZCAEIAUgA0EBEKgDIAQpAwghBiAEKQMAIQcgAgRAIAIgBCgCiAEgASAEKAIUIAQoAjxramo2AgALIAAgBjcDCCAAIAc3AwAgBEGgAWokAAsJACAAQQQQqAILDQAgACABIAJCfxCEAgucAQEDf0E1IQECQCAAKAIcIgIgACgCGCIDQQZqQQdwa0EHakEHbiADIAJrIgJB8QJqQQdwQQNJaiIDQTVHBEAgAyIBDQFBNCEBAkACQCACQQZqQQdwQQRrDgIBAAMLIAAoAhRBkANvQQFrEJ0DRQ0CC0E1DwsCQAJAIAJB8wJqQQdwQQNrDgIAAgELIAAoAhQQnQMNAQtBASEBCyABC5sEAgd/BH4jAEEQayIIJAACQAJAAkAgAkEkTARAIAAtAAAiBQ0BIAAhBAwCC0GI6gFBHDYCAEIAIQMMAgsgACEEAkADQCAFwBB9RQ0BIAQtAAEhBSAEQQFqIQQgBQ0ACwwBCwJAIAVB/wFxIgZBK2sOAwABAAELQX9BACAGQS1GGyEHIARBAWohBAsCfwJAIAJBEHJBEEcNACAELQAAQTBHDQBBASEJIAQtAAFB3wFxQdgARgRAIARBAmohBEEQDAILIARBAWohBCACQQggAhsMAQsgAkEKIAIbCyIKrSEMQQAhAgNAAkACQCAELQAAIgZBMGsiBUH/AXFBCkkNACAGQeEAa0H/AXFBGU0EQCAGQdcAayEFDAELIAZBwQBrQf8BcUEZSw0BIAZBN2shBQsgCiAFQf8BcUwNACAIIAxCACALQgAQQEEBIQYCQCAIKQMIQgBSDQAgCyAMfiINIAWtQv8BgyIOQn+FVg0AIA0gDnwhC0EBIQkgAiEGCyAEQQFqIQQgBiECDAELCyABBEAgASAEIAAgCRs2AgALAkACQCACBEBBiOoBQcQANgIAIAdBACADQgGDIgxQGyEHIAMhCwwBCyADIAtWDQEgA0IBgyEMCyAMpyAHckUEQEGI6gFBxAA2AgAgA0IBfSEDDAILIAMgC1oNAEGI6gFBxAA2AgAMAQsgCyAHrCIDhSADfSEDCyAIQRBqJAAgAwuIAQEDfyABKAIEIAAoAgQgACgCACIEayICayEDIAIEQCADIAQgAvwKAAALIAEgAzYCBCAAIAAoAgAiAjYCBCAAIAEoAgQ2AgAgASACNgIEIAAoAgQhAiAAIAEoAgg2AgQgASACNgIIIAAoAgghAiAAIAEoAgw2AgggASACNgIMIAEgASgCBDYCAAuaAwEIfwJAIAAiAUEDcQRAA0AgAS0AACICRSACQT1Gcg0CIAFBAWoiAUEDcQ0ACwsCQAJAQYCChAggASgCACIDayADckGAgYKEeHFBgIGChHhHDQADQEGAgoQIIANBvfr06QNzIgJrIAJyQYCBgoR4cUGAgYKEeEcNASABKAIEIQMgAUEEaiICIQEgA0GAgoQIIANrckGAgYKEeHFBgIGChHhGDQALDAELIAEhAgsDQCACIgEtAAAiA0UNASABQQFqIQIgA0E9Rw0ACwsgACABRgRAQQAPCwJAIAAgASAAayIDai0AAA0AQYDuASgCACIERQ0AIAQoAgAiAUUNAANAAkACfyAAIQJBACADIgZFDQAaIAAtAAAiBQR/AkADQCAFIAEtAAAiB0cgB0VyDQEgBkEBayIGRQ0BIAFBAWohASACLQABIQUgAkEBaiECIAUNAAtBACEFCyAFBUEACyABLQAAawtFBEAgBCgCACADaiIBLQAAQT1GDQELIAQoAgQhASAEQQRqIQQgAQ0BDAILCyABQQFqIQgLIAgLSgEBfyAAIAM2AhAgAEEANgIMIAEEQCABELMCIQQLIAAgBDYCACAAIAQgAkECdGoiAjYCCCAAIAQgAUECdGo2AgwgACACNgIEIAALRAEBfyMAQRBrIgUkACAFIAEgAiADIARCgICAgICAgICAf4UQSiAFKQMAIQEgACAFKQMINwMIIAAgATcDACAFQRBqJAALcgECfyAAQYj+ADYCACAAKAIcBEAgACgCKCEBA0AgAQRAQQAgACABQQFrIgFBAnQiAiAAKAIkaigCACAAKAIgIAJqKAIAEQUADAELCyAAQRxqECUgACgCIBAtIAAoAiQQLSAAKAIwEC0gACgCPBAtCyAACwcAIAEgAGsLDABBARDWARogABAtCwkAIAAQsQEQLQsTACAAIAEgAiAAKAIAKAIwEQMACwkAIAAQ2AEQLQsMACAAQQRqENoBIAALDAAgAEEIahDaASAACygBAn8jAEEQayICJAAgASgCACAAKAIASCEDIAJBEGokACABIAAgAxsLEAAgACABNwMIIABCADcDAAsCAAsUACAAQZj1ADYCACAAQQRqECUgAAvyAwICfgV/IwBBIGsiBSQAIAFC////////P4MhAgJ+IAFCMIhC//8BgyIDpyIEQYH4AGtB/Q9NBEAgAkIEhiAAQjyIhCECIARBgPgAa60hAwJAIABC//////////8PgyIAQoGAgICAgICACFoEQCACQgF8IQIMAQsgAEKAgICAgICAgAhSDQAgAkIBgyACfCECC0IAIAIgAkL/////////B1YiBBshACAErSADfAwBCyAAIAKEUCADQv//AVJyRQRAIAJCBIYgAEI8iIRCgICAgICAgASEIQBC/w8MAQsgBEH+hwFLBEBCACEAQv8PDAELQYD4AEGB+AAgA1AiBxsiCCAEayIGQfAASgRAQgAhAEIADAELIAVBEGogACACIAJCgICAgICAwACEIAcbIgJBgAEgBmsQRCAFIAAgAiAGEIoBIAUpAwhCBIYgBSkDACICQjyIhCEAAkAgBCAIRyAFKQMQIAUpAxiEQgBSca0gAkL//////////w+DhCICQoGAgICAgICACFoEQCAAQgF8IQAMAQsgAkKAgICAgICAgAhSDQAgAEIBgyAAfCEACyAAQoCAgICAgIAIhSAAIABC/////////wdWIgQbIQAgBK0LIQIgBUEgaiQAIAFCgICAgICAgICAf4MgAkI0hoQgAIS/C4kCAAJAIAAEfyABQf8ATQ0BAkBB3OEBKAIAKAIARQRAIAFBgH9xQYC/A0YNAwwBCyABQf8PTQRAIAAgAUE/cUGAAXI6AAEgACABQQZ2QcABcjoAAEECDwsgAUGAQHFBgMADRyABQYCwA09xRQRAIAAgAUE/cUGAAXI6AAIgACABQQx2QeABcjoAACAAIAFBBnZBP3FBgAFyOgABQQMPCyABQYCABGtB//8/TQRAIAAgAUE/cUGAAXI6AAMgACABQRJ2QfABcjoAACAAIAFBBnZBP3FBgAFyOgACIAAgAUEMdkE/cUGAAXI6AAFBBA8LC0GI6gFBGTYCAEF/BUEBCw8LIAAgAToAAEEBCzABAX8jAEEQayICJAAgAiABKAIANgIAIAAgAhByEH9BoPEAKAIAEGEaIAJBEGokAAsRACACBEAgACABwCAC/AsACwupAQEBfEQAAAAAAADwPyEBAkAgAEGACE4EQEQAAAAAAADgfyEBIABB/w9JBEAgAEH/B2shAAwCC0QAAAAAAADwfyEBQf0XIAAgAEH9F08bQf4PayEADAELIABBgXhKDQBEAAAAAAAAYAMhASAAQbhwSwRAIABByQdqIQAMAQtEAAAAAAAAAAAhAUHwaCAAIABB8GhNG0GSD2ohAAsgASAAQf8Haq1CNIa/ogtEAQF/IwBBEGsiAiQAIAAoAgAhACACIAE2AgggAiAANgIEIAJB/BQ2AgBByAsgAhByEH9BoPEAKAIAEGEaIAJBEGokAAt4AQN/AkAgAEUNACAAKAIgRQ0AIAAoAiQiAkUNACAAKAIcIgFFDQAgASgCACAARw0AIAEoAgRBtP4Aa0EfSw0AIAEoAjgiAwRAIAAoAiggAyACEQEAIAAoAiQhAiAAKAIcIQELIAAoAiggASACEQEAIABBADYCHAsL6QMAQZTZAUGFExAcQazZAUGUDkEBQQAQG0G42QFB8QxBAUGAf0H/ABACQdDZAUHqDEEBQYB/Qf8AEAJBxNkBQegMQQFBAEH/ARACQdzZAUGjCUECQYCAfkH//wEQAkHo2QFBmglBAkEAQf//AxACQfTZAUGyCUEEQYCAgIB4Qf////8HEAJBgNoBQakJQQRBAEF/EAJBjNoBQfMPQQRBgICAgHhB/////wcQAkGY2gFB6g9BBEEAQX8QAkGk2gFB4A9BCEKAgICAgICAgIB/Qv///////////wAQDUGw2gFB1w9BCEIAQn8QDUG82gFBogpBBBAMQcjaAUGMEUEIEAxBmC1BkhAQGkHgLUEEQfgPEAVBqC5BAkGeEBAFQfQuQQRBrRAQBUHMJhAZQcAvQQBB9RkQAEHoL0EAQboaEABBkDBBAUGTGhAAQbgwQQJBwhYQAEHgMEEDQeEWEABBiDFBBEGJFxAAQbAxQQVBphcQAEHYMUEEQd8aEABBgDJBBUH9GhAAQegvQQBBjBgQAEGQMEEBQesXEABBuDBBAkHOGBAAQeAwQQNBrBgQAEGIMUEEQdQZEABBsDFBBUGyGRAAQagyQQhBkRkQAEHQMkEJQe8YEABB+DJBBkHMFxAAQaAzQQdBpBsQAAsxAQF/IAAoAgwiASAAKAIQRgRAIAAgACgCACgCKBEAAA8LIAAgAUEBajYCDCABLQAAC2ABBH8gASAAKAIEIgYgA2siB2ohBCAGIQUDQCACIARNBEAgACAFNgIEIAdFIAMgBkZyRQRAIAYgB2sgASAH/AoAAAsFIAUgBC0AADoAACAFQQFqIQUgBEEBaiEEDAELCwsQACAAKAIAIgAEQCAAEB0LCzUBAX8gASAAKAIEIgJBAXVqIQEgACgCACEAIAEgAkEBcQR/IAEoAgAgAGooAgAFIAALEQAAC6ABAQR/IwBBgAJrIgAkACAAIAQ3A/gBIABCJTcD8AEgAEHwAWoiB0EBckGZDiAFIAIoAgQQywEgAEHQAWoiBiAGEC4gByAAQfgBahCJAyAGaiIIIAIQaSEJIABBBGoiByACECcgBiAJIAggAEEQaiIGIABBDGogAEEIaiAHEIADIAcQJSABIAYgACgCDCAAKAIIIAIgAxCFASAAQYACaiQAC6IBAQN/IwBBkAFrIgAkACAAIAQ2AowBIABCJTcDgAEgAEGAAWoiBkEBckGgDiAFIAIoAgQQywEgAEHzAGoiBCAEQQ0QLiAGIABBjAFqEMoBIARqIgcgAhBpIQggAEEEaiIGIAIQJyAEIAggByAAQRBqIgQgAEEMaiAAQQhqIAYQgAMgBhAlIAEgBCAAKAIMIAAoAgggAiADEIUBIABBkAFqJAALnQEBBH8jAEHwAGsiACQAIAAgBDcDaCAAQiU3A2AgAEHgAGoiB0EBckGZDiAFIAIoAgQQywEgAEFAayIGIAYQLiAHIABB6ABqEIkDIAZqIgggAhBpIQkgAEEEaiIHIAIQJyAGIAkgCCAAQRBqIgYgAEEMaiAAQQhqIAcQigMgBxAlIAEgBiAAKAIMIAAoAgggAiADEIABIABB8ABqJAALngEBA38jAEHQAGsiACQAIAAgBDYCTCAAQiU3A0AgAEFAayIGQQFyQaAOIAUgAigCBBDLASAAQTNqIgQgBEENEC4gBiAAQcwAahDKASAEaiIHIAIQaSEIIABBBGoiBiACECcgBCAIIAcgAEEQaiIEIABBDGogAEEIaiAGEIoDIAYQJSABIAQgACgCDCAAKAIIIAIgAxCAASAAQdAAaiQACwcAIAARDwALQgADQCABIAJHBEAgAQJ/IAEsAAAQTARAIAMoAgAgASwAAEECdGooAgAMAQsgAS0AAAs6AAAgAUEBaiEBDAELCyABCz0AA0AgASACRwRAIAEiACAAKAIAEEwEfyADKAIAIAAoAgBBAnRqBSAACygCADYCACAAQQRqIQEMAQsLIAELPwECfyAAKAIEIQMgACgCCCECA0AgAiADRwRAIAAgAiABayICNgIIDAELCyAAKAIAIgIEQCAAKAIMGiACEC0LC0wBAX8CQCABRQ0AIAFBiNgBEFIiAUUNACABKAIIIAAoAghBf3NxDQAgACgCDCABKAIMQQAQO0UNACAAKAIQIAEoAhBBABA7IQILIAILCwBBnBFBABCtAgALgQEBA38gACgCBCIEQQFxIQUCfyABLQA3QQFGBEAgBEEIdSIGIAVFDQEaIAIoAgAgBhDoAQwBCyAEQQh1IAVFDQAaIAEgACgCACgCBDYCOCAAKAIEIQRBACECQQALIQUgACgCACIAIAEgAiAFaiADQQIgBEECcRsgACgCACgCHBEIAAsKACAAIAFBABA7C/gBAQF/IwBBEGsiAiQAIAIgATYCDEGQ1gEoAgAiAiAAIAEQzQMaIAAQqAEgAGpBAWstAABBCkcEQAJAAkAgAigCTCIAQQBOBEAgAEUNAUGU4QEoAgAgAEH/////A3FHDQELAkAgAigCUEEKRg0AIAIoAhQiACACKAIQRg0AIAIgAEEBajYCFCAAQQo6AAAMAgsgAhDeAQwBCyACQcwAaiIBIgAgACgCACIAQf////8DIAAbNgIAAkACQCACKAJQQQpGDQAgAigCFCIAIAIoAhBGDQAgAiAAQQFqNgIUIABBCjoAAAwBCyACEN4BCyABEKwBGgsLEMoDAAsdAQF/IwBBEGsiASQAIAEgADYCAEG9HiABEK0CAAu5AgEDfyMAQSBrIggkAEH3////AyIJIAFBf3NqIAJPBEAgABAjIQogAUHz////AUkEQCAIIAFBAXQ2AhwgCCABIAJqNgIQIAhBEGogCEEcahCgASgCABCQAUEBaiEJCyAIQRxqIAhBGGogABBVKAIAELwBIAhBEGogCRCPASAIKAIQIQIgCCgCFBogBARAIAIgCiAEEGULIAYEQCAEQQJ0IAJqIAcgBhBlCyADIAQgBWoiCWshByADIAlHBEAgBEECdCIDIAJqIAZBAnRqIAMgCmogBUECdGogBxBlCyABQQFqIgFBAkcEQCAKIAEQqQELIAAgAjYCACAAIAgoAhQQXCAAIAQgBmogB2oiADYCBCAIQQA2AgwgAiAAQQJ0aiAIQQxqEFYgCEEcahC7ASAIQSBqJAAPCxBbAAuJAQECfyMAQRBrIgMkACABQff///8HTQRAAkAgARDUAQRAIAAgARBQIAAhBAwBCyADQQhqIAEQnwFBAWoQngEgAygCDBogACADKAIIIgQ2AgAgACADKAIMEFwgACABNgIECyAEIAEgAhCyAiADQQA6AAcgASAEaiADQQdqEF0gA0EQaiQADwsQWwALRAECfyAAECghAyAAEB8hBCACIANNBEAgABAjIgMgASACEE0gACADIAIQwAIPCyAAIAMgAiADayAEQQAgBCACIAEQuQELPQEBfyMAQRBrIgMkACADIAI6AA8DQCABBEAgACADLQAPOgAAIAFBAWshASAAQQFqIQAMAQsLIANBEGokAAsZACAAQYCAgIAETwRAEKoCAAsgAEECdBBTC5IFAQh/QQQgASABQQRNGyEDQQEgACAAQQFNGyEHA0ACQCAHIAMgB2pBAWtBACADa3EiACAAIAdJGyEEQQAhASMAQRBrIggkAAJAIANBA3ENACAEIANwDQACfwJAQTACfyADQQhGBEAgBBA0DAELQRwhASADQQNxIANBBElyDQEgA0ECdiIAIABBAWtxDQFBMEFAIANrIARJDQIaAn9BECEBAkBBEEEQIAMgA0EQTRsiACAAQRBNGyICIAJBAWtxRQRAIAIhAAwBCwNAIAEiAEEBdCEBIAAgAkkNAAsLQUAgAGsgBE0EQEGI6gFBMDYCAEEADAELQQBBECAEQQtqQXhxIARBC0kbIgUgAGpBDGoQNCICRQ0AGiACQQhrIQECQCAAQQFrIAJxRQRAIAEhAAwBCyACQQRrIgkoAgAiBEF4cSAAIAJqQQFrQQAgAGtxQQhrIgIgAEEAIAIgAWtBD00baiIAIAFrIgZrIQIgBEEDcUUEQCABKAIAIQEgACACNgIEIAAgASAGajYCAAwBCyAAIAIgACgCBEEBcXJBAnI2AgQgACACaiICIAIoAgRBAXI2AgQgCSAGIAkoAgBBAXFyQQJyNgIAIAEgBmoiAiACKAIEQQFyNgIEIAEgBhDbAQsCQCAAKAIEIgJBA3FFDQAgAkF4cSIBIAVBEGpNDQAgACAFIAJBAXFyQQJyNgIEIAAgBWoiBCABIAVrIgJBA3I2AgQgACABaiIBIAEoAgRBAXI2AgQgBCACENsBCyAAQQhqCwsiAEUNARogCCAANgIMQQAhAQsgAQshAEEAIAgoAgwgABshAQsgCEEQaiQAIAENAEHk/gEoAgAiAEUNACAAEQwADAELCyABRQRAEOsBCyABCwoAIAEgAGtBDG0LCQAgABAuNgIACyMBAn8gACEBA0AgASICQQRqIQEgAigCAA0ACyACIABrQQJ1Cy8BAX8jAEEQayIDJAACQCAAIAFGBEAgAEEAOgB4DAELIAEgAhCpAQsgA0EQaiQACxAAIAAoAgggACgCAGtBAnULCQAgAEEANgIAC0kBAX8jAEEQayIDJAACQAJAIAJBHksNACABLQB4QQFxDQAgAUEBOgB4DAELIAIQwQIhAQsgA0EQaiQAIAAgAjYCBCAAIAE2AgALOgECfyMAQRBrIgAkACAAQf////8DNgIMIABB/////wc2AgggAEEMaiAAQQhqELUDKAIAIABBEGokAAs0AQF/IwBBEGsiAyQAIAMgARBzNgIMIAMgAhBzNgIIIAAgA0EMaiADQQhqEGYgA0EQaiQAC04BAX8jAEEQayIDJAAgAyABNgIIIAMgADYCDCADIAI2AgRBACEBIANBBGoiACADQQxqENMBRQRAIAAgA0EIahDTASEBCyADQRBqJAAgAQswAQF/IwBBEGsiAyQAIAMgATYCDCADIAI2AgggACADQQxqIANBCGoQZiADQRBqJAALMwEBfyMAQRBrIgMkACAAEB8aIAAgAhCDASADQQA6AA8gASACaiADQQ9qEF0gA0EQaiQACzEAIABB/////wNLBEAQqgIACwJ/IABBAnQhAEEEENYBBEAgAEEEELQCDAELIAAQUwsLCQAgABDtARAtCxUAIABB8KoBNgIAIABBEGoQIBogAAsVACAAQciqATYCACAAQQxqECAaIAALgAMBBH8gAiEAA0ACQCAEIAdNIAAgA09yDQAgACwAACIBQf8BcSEFAn9BASABQQBODQAaIAFBQkkNASABQV9NBEAgAyAAa0ECSA0CIAAtAAFBwAFxQYABRw0CQQIMAQsgAUFvTQRAIAMgAGtBA0gNAiAALQACIAAsAAEhAQJAAkAgBUHtAUcEQCAFQeABRw0BIAFBYHFBoH9GDQIMBQsgAUGgf04NBAwBCyABQb9/Sg0DC0HAAXFBgAFHDQJBAwwBCyADIABrQQRIIAFBdEtyDQEgAC0AAyEGIAAtAAIhCCAALAABIQECQAJAAkACQCAFQfABaw4FAAICAgECCyABQfAAakH/AXFBME8NBAwCCyABQZB/Tg0DDAELIAFBv39KDQILIAhBwAFxQYABRyAGQcABcUGAAUdyIAZBP3EgCEEGdEHAH3EgBUESdEGAgPAAcSABQT9xQQx0cnJyQf//wwBLcg0BQQQLIQEgB0EBaiEHIAAgAWohAAwBCwsgACACawu4BAEEfyMAQRBrIgAkAAJ/IAAgAjYCDCAAIAU2AggCQAJAA0AgAiADTyAFIAZPckUEQCACLAAAIghB/wFxIQECfyAIQQBOBEAgAUH//8MASw0FQQEMAQsgCEFCSQ0EIAhBX00EQEEBIAMgAmtBAkgNBhpBAiEIIAItAAEiCUHAAXFBgAFHDQQgCUE/cSABQQZ0QcAPcXIhAUECDAELIAhBb00EQEEBIQggAyACayIKQQJIDQQgAiwAASEJAkACQCABQe0BRwRAIAFB4AFHDQEgCUFgcUGgf0YNAgwICyAJQaB/SA0BDAcLIAlBv39KDQYLIApBAkYNBCACLQACIghBwAFxQYABRw0FIAhBP3EgAUEMdEGA4ANxIAlBP3FBBnRyciEBQQMMAQsgCEF0Sw0EQQEhCCADIAJrIgpBAkgNAyACLAABIQkCQAJAAkACQCABQfABaw4FAAICAgECCyAJQfAAakH/AXFBME8NBwwCCyAJQZB/Tg0GDAELIAlBv39KDQULIApBAkYNAyACLQACIgtBwAFxQYABRw0EIApBA0YNAyACLQADIgpBwAFxQYABRw0EQQIhCCAKQT9xIAtBBnRBwB9xIAFBEnRBgIDwAHEgCUE/cUEMdHJyciIBQf//wwBLDQNBBAshCCAFIAE2AgAgACACIAhqIgI2AgwgACAFQQRqIgU2AggMAQsLIAIgA0khCAsgCAwBC0ECCyAEIAAoAgw2AgAgByAAKAIINgIAIABBEGokAAv1AwAjAEEQayIAJAACfyAAIAI2AgwgACAFNgIIAkADQAJAIAIgA08EQEEAIQUMAQtBAiEFIAIoAgAiAUH//8MASyABQYBwcUGAsANGcg0AAkAgAUH/AE0EQEEBIQUgBiAAKAIIIgJrQQBMDQIgACACQQFqNgIIIAIgAToAAAwBCyABQf8PTQRAIAYgACgCCCICa0ECSA0EIAAgAkEBajYCCCACIAFBBnZBwAFyOgAAIAAgACgCCCICQQFqNgIIIAIgAUE/cUGAAXI6AAAMAQsgBiAAKAIIIgJrIQUgAUH//wNNBEAgBUEDSA0EIAAgAkEBajYCCCACIAFBDHZB4AFyOgAAIAAgACgCCCICQQFqNgIIIAIgAUEGdkE/cUGAAXI6AAAgACAAKAIIIgJBAWo2AgggAiABQT9xQYABcjoAAAwBCyAFQQRIDQMgACACQQFqNgIIIAIgAUESdkHwAXI6AAAgACAAKAIIIgJBAWo2AgggAiABQQx2QT9xQYABcjoAACAAIAAoAggiAkEBajYCCCACIAFBBnZBP3FBgAFyOgAAIAAgACgCCCICQQFqNgIIIAIgAUE/cUGAAXI6AAALIAAgACgCDEEEaiICNgIMDAELCyAFDAELQQELIAQgACgCDDYCACAHIAAoAgg2AgAgAEEQaiQAC5IDAQR/IAIhAANAAkAgBCAGTSAAIANPcg0AAn8gAEEBaiAALQAAIgHAQQBODQAaIAFBwgFJDQEgAUHfAU0EQCADIABrQQJIDQIgAC0AAUHAAXFBgAFHDQIgAEECagwBCyABQe8BTQRAIAMgAGtBA0gNAiAALQACIAAsAAEhBQJAAkAgAUHtAUcEQCABQeABRw0BIAVBYHFBoH9GDQIMBQsgBUGgf04NBAwBCyAFQb9/Sg0DC0HAAXFBgAFHDQIgAEEDagwBCyADIABrQQRIIAFB9AFLciAEIAZrQQJJcg0BIAAtAAMhByAALQACIQggACwAASEFAkACQAJAAkAgAUHwAWsOBQACAgIBAgsgBUHwAGpB/wFxQTBPDQQMAgsgBUGQf04NAwwBCyAFQb9/Sg0CCyAIQcABcUGAAUcgB0HAAXFBgAFHciAHQT9xIAhBBnRBwB9xIAFBEnRBgIDwAHEgBUE/cUEMdHJyckH//8MAS3INASAGQQFqIQYgAEEEagshACAGQQFqIQYMAQsLIAAgAmsLgQUBBX8jAEEQayIAJAACfyAAIAI2AgwgACAFNgIIAkACQANAIAIgA08gBSAGT3JFBEBBAiEJIAACfyACLQAAIgHAQQBOBEAgBSABOwEAQQEMAQsgAUHCAUkNBCABQd8BTQRAQQEgAyACa0ECSA0GGiACLQABIghBwAFxQYABRw0EIAUgCEE/cSABQQZ0QcAPcXI7AQBBAgwBCyABQe8BTQRAQQEhCSADIAJrIgpBAkgNBCACLAABIQgCQAJAIAFB7QFHBEAgAUHgAUcNASAIQWBxQaB/Rw0IDAILIAhBoH9ODQcMAQsgCEG/f0oNBgsgCkECRg0EIAItAAIiCUHAAXFBgAFHDQUgBSAJQT9xIAhBP3FBBnQgAUEMdHJyOwEAQQMMAQsgAUH0AUsNBEEBIQkgAyACayIKQQJIDQMgAi0AASILwCEIAkACQAJAAkAgAUHwAWsOBQACAgIBAgsgCEHwAGpB/wFxQTBPDQcMAgsgCEGQf04NBgwBCyAIQb9/Sg0FCyAKQQJGDQMgAi0AAiIIQcABcUGAAUcNBCAKQQNGDQMgAi0AAyIKQcABcUGAAUcNBCAGIAVrQQNIDQNBAiEJIApBP3EiCiAIQQZ0IgxBwB9xIAtBDHRBgOAPcSABQQdxIgFBEnRycnJB///DAEsNAyAFIAogDEHAB3FyQYC4A3I7AQIgBSAIQQR2QQNxIAtBAnQiCUHAAXEgAUEIdHIgCUE8cXJyQcD/AGpBgLADcjsBACAFQQJqIQVBBAsgAmoiAjYCDCAAIAVBAmoiBTYCCAwBCwsgAiADSSEJCyAJDAELQQILIAQgACgCDDYCACAHIAAoAgg2AgAgAEEQaiQAC8sFAQJ/IwBBEGsiACQAAn8gACACNgIMIAAgBTYCCAJAAkADQCACIANPBEBBACEFDAILQQIhBQJAAkAgAi8BACIBQf8ATQRAQQEhBSAGIAAoAggiAmtBAEwNBCAAIAJBAWo2AgggAiABOgAADAELIAFB/w9NBEAgBiAAKAIIIgJrQQJIDQUgACACQQFqNgIIIAIgAUEGdkHAAXI6AAAgACAAKAIIIgJBAWo2AgggAiABQT9xQYABcjoAAAwBCyABQf+vA00EQCAGIAAoAggiAmtBA0gNBSAAIAJBAWo2AgggAiABQQx2QeABcjoAACAAIAAoAggiAkEBajYCCCACIAFBBnZBP3FBgAFyOgAAIAAgACgCCCICQQFqNgIIIAIgAUE/cUGAAXI6AAAMAQsgAUH/twNNBEBBASEFIAMgAmtBA0gNBCACLwECIghBgPgDcUGAuANHDQIgBiAAKAIIIglrQQRIDQQgCEH/B3EgAUEKdEGA+ANxIAFBwAdxIgVBCnRyckH//z9LDQIgACACQQJqNgIMIAAgCUEBajYCCCAJIAVBBnZBAWoiAkECdkHwAXI6AAAgACAAKAIIIgVBAWo2AgggBSACQQR0QTBxIAFBAnZBD3FyQYABcjoAACAAIAAoAggiAkEBajYCCCACIAhBBnZBD3EgAUEEdEEwcXJBgAFyOgAAIAAgACgCCCIBQQFqNgIIIAEgCEE/cUGAAXI6AAAMAQsgAUGAwANJDQMgBiAAKAIIIgJrQQNIDQQgACACQQFqNgIIIAIgAUEMdkHgAXI6AAAgACAAKAIIIgJBAWo2AgggAiABQQZ2Qb8BcToAACAAIAAoAggiAkEBajYCCCACIAFBP3FBgAFyOgAACyAAIAAoAgxBAmoiAjYCDAwBCwtBAgwCCyAFDAELQQELIAQgACgCDDYCACAHIAAoAgg2AgAgAEEQaiQACw8AIAEgACgCAGogAjYCAAs8AQJ/IwBBEGsiASQAIAEgADYCDCABQQhqIAFBDGoQY0EEQQFB3OEBKAIAKAIAGyECEGIgAUEQaiQAIAILOAEBfyMAQRBrIgUkACAFIAQ2AgwgBUEIaiAFQQxqEGMgACABIAIgAxDSASEAEGIgBUEQaiQAIAALEgAgBCACNgIAIAcgBTYCAEEDCw0AIAEgACgCAGooAgALKwEBfyAAQdyhATYCAAJAIAAoAggiAUUNACAALQAMQQFxRQ0AIAEQLQsgAAsEACABCycBAX8gACgCACgCACgCAEHM8gFBzPIBKAIAQQFqIgA2AgAgADYCBAu0CgEHf0HI8gEtAABFBEAjAEEQayIFJABBwPIBLQAARQRAIwBBEGsiBiQAIAZBATYCDEGg8QEgBigCDBAyIgFByKEBNgIAIwBBEGsiAyQAIAFBCGoiAkEANgIIIAJCADcCACACQQA6AIQBIANBCGogAhBVKAIAGiADQQA6AA8jAEEQayIEJAAQvAJBHkkEQBCMAQALIARBCGogAkEMakEeELsCIAIgBCgCCCIHNgIEIAIgBzYCACACIAcgBCgCDEECdGo2AgggBEEQaiQAIAJBHhDZAiADQQE6AA8gA0EQaiQAIAFBkAFqQYwWELABIAIQ2gJBrPwBQQEQMkHotQE2AgAgAUGs/AFB+O8BEDEQM0G0/AFBARAyQYi2ATYCACABQbT8AUGA8AEQMRAzQbz8AUEBEDIiAkEAOgAMIAJBADYCCCACQdyhATYCACACQZCiATYCCCABQbz8AUHY8gEQMRAzQcz8AUEBEDJByK0BNgIAIAFBzPwBQdDyARAxEDNB1PwBQQEQMkHgrgE2AgAgAUHU/AFB4PIBEDEQM0Hc/AFBARAyIgJBmKoBNgIAIAIQLjYCCCABQdz8AUHo8gEQMRAzQej8AUEBEDJB9K8BNgIAIAFB6PwBQfDyARAxEDNB8PwBQQEQMkHcsQE2AgAgAUHw/AFBgPMBEDEQM0H4/AFBARAyQeiwATYCACABQfj8AUH48gEQMRAzQYD9AUEBEDJB0LIBNgIAIAFBgP0BQYjzARAxEDNBiP0BQQEQMiICQa7YADsBCCACQciqATYCACACQQxqECQaIAFBiP0BQZDzARAxEDNBoP0BQQEQMiICQq6AgIDABTcCCCACQfCqATYCACACQRBqECQaIAFBoP0BQZjzARAxEDNBvP0BQQEQMkGotgE2AgAgAUG8/QFBiPABEDEQM0HE/QFBARAyQaC4ATYCACABQcT9AUGQ8AEQMRAzQcz9AUEBEDJB9LkBNgIAIAFBzP0BQZjwARAxEDNB1P0BQQEQMkHguwE2AgAgAUHU/QFBoPABEDEQM0Hc/QFBARAyQcTDATYCACABQdz9AUHI8AEQMRAzQeT9AUEBEDJB2MQBNgIAIAFB5P0BQdDwARAxEDNB7P0BQQEQMkHMxQE2AgAgAUHs/QFB2PABEDEQM0H0/QFBARAyQcDGATYCACABQfT9AUHg8AEQMRAzQfz9AUEBEDJBtMcBNgIAIAFB/P0BQejwARAxEDNBhP4BQQEQMkHcyAE2AgAgAUGE/gFB8PABEDEQM0GM/gFBARAyQYTKATYCACABQYz+AUH48AEQMRAzQZT+AUEBEDJBrMsBNgIAIAFBlP4BQYDxARAxEDNBnP4BQQEQMiICQZjVATYCCCACQai9ATYCACACQdi9ATYCCCABQZz+AUGo8AEQMRAzQaj+AUEBEDIiAkG81QE2AgggAkG0vwE2AgAgAkHkvwE2AgggAUGo/gFBsPABEDEQM0G0/gFBARAyIgJBCGoQtgIgAkGkwQE2AgAgAUG0/gFBuPABEDEQM0HA/gFBARAyIgJBCGoQtgIgAkHEwgE2AgAgAUHA/gFBwPABEDEQM0HM/gFBARAyQdTMATYCACABQcz+AUGI8QEQMRAzQdT+AUEBEDJBzM0BNgIAIAFB1P4BQZDxARAxEDMgBkEQaiQAIAVBoPEBNgIIQbzyASAFKAIIEFUaQcDyAUEBOgAACyAFQRBqJABBxPIBQbzyARDVAkHI8gFBAToAAAsgAEHE8gEoAgAiADYCACAAENQCCxEAIABBoPEBRwRAIAAQ1wILCxMAIAAgASgCACIANgIAIAAQ1AILlwEBA38gAEHIoQE2AgAgAEEIaiEBA0AgARBrIAJLBEAgASACEIIBKAIABEAgASACEIIBKAIAEL8BCyACQQFqIQIMAQsLIABBkAFqECAaIwBBEGsiAiQAIAJBDGogARBVIgEoAgAiAygCAARAIAMQ2gIgASgCABogASgCACIBQQxqIAEoAgAgARC5AhC4AgsgAkEQaiQAIAALDwAgACAAKAIEQQFqNgIECyYBAX8gACgCBCECA0AgASACRwRAIAJBBGshAgwBCwsgACABNgIEC3UBAn8jAEEQayIDJAAgA0EEaiICIAA2AgAgAiAAKAIEIgA2AgQgAiAAIAFBAnRqNgIIIAIiASgCBCEAIAIoAgghAgNAIAAgAkYEQCABKAIAIAEoAgQ2AgQgA0EQaiQABSAAELoCIAEgAEEEaiIANgIEDAELCwsRACAAEGsaIAAgACgCABDYAgsgACAAQZiqATYCACAAKAIIEC5HBEAgACgCCBCgAwsgAAsEAEF/C+EBAQR/IwBBEGsiBSQAIwBBIGsiAyQAIANBGGogACABEL0CIAMoAhghBCADKAIcIQYjAEEQayIBJAAgASAGNgIMIAIgBCAGIARrIgRBAnUQZSABIAIgBGo2AgggA0EQaiABQQxqIAFBCGoQZiABQRBqJAAgAygCECEEIwBBEGsiASQAIAEgADYCDCABQQxqIgAgBCAAEOwBa0ECdRDwASEAIAFBEGokACADIAA2AgwgAyACIAMoAhQQjgE2AgggBUEIaiADQQxqIANBCGoQZiADQSBqJAAgBSgCDCAFQRBqJAAL9gUBCn8jAEEQayITJAAgAiAANgIAQQRBACAHGyEVIANBgARxIRYDQCAUQQRGBEAgDRAfQQFLBEAgEyANEE42AgwgAiATQQxqQQEQ8AEgDRB1IAIoAgAQ3QI2AgALIANBsAFxIgNBEEcEQCABIANBIEYEfyACKAIABSAACzYCAAsgE0EQaiQABQJAAkACQAJAAkACQCAIIBRqLQAADgUAAQMCBAULIAEgAigCADYCAAwECyABIAIoAgA2AgAgBkEgEEshByACIAIoAgAiD0EEajYCACAPIAc2AgAMAwsgDRBaDQIgDUEAEMwBKAIAIQcgAiACKAIAIg9BBGo2AgAgDyAHNgIADAILIAwQWiAWRXINASACIAwQTiAMEHUgAigCABDdAjYCAAwBCyACKAIAIAQgFWoiBCEHA0ACQCAFIAdNDQAgBkHAACAHKAIAEF9FDQAgB0EEaiEHDAELCyAOQQBKBEAgAigCACEPIA4hEANAIBBFIAQgB09yRQRAIBBBAWshECAHQQRrIgcoAgAhESACIA9BBGoiEjYCACAPIBE2AgAgEiEPDAELCyAQBH8gBkEwEEsFQQALIREgAigCACEPA0AgEEEASgRAIAIgD0EEaiISNgIAIA8gETYCACAQQQFrIRAgEiEPDAELCyACIAIoAgAiD0EEajYCACAPIAk2AgALAkAgBCAHRgRAIAZBMBBLIQcgAiACKAIAIg9BBGo2AgAgDyAHNgIADAELIAsQWgR/QX8FIAtBABAiLAAACyESQQAhEEEAIREDQCAEIAdGDQECQCAQIBJHBEAgECEPDAELIAIgAigCACIPQQRqNgIAIA8gCjYCAEEAIQ8gCxAfIBFBAWoiEU0EQCAQIRIMAQsgCyARECItAABB/wBGBEBBfyESDAELIAsgERAiLAAAIRILIAdBBGsiBygCACEQIAIgAigCACIYQQRqNgIAIBggEDYCACAPQQFqIRAMAAsACyACKAIAEMcBCyAUQQFqIRQMAQsLC70BAQF/IwBBEGsiCiQAAn8gAARAIAIQ5gIMAQsgAhDlAgshAAJAIAEEQCAKQQRqIgEgABCSASADIAooAgQ2AAAgASAAEMIBDAELIApBBGoiASAAEOECIAMgCigCBDYAACABIAAQewsgCCABEKsBIAEQORogBCAAEHg2AgAgBSAAEFk2AgAgCkEEaiIBIAAQWCAGIAEQcCABECAaIAEgABB8IAcgARCrASABEDkaIAkgABDBATYCACAKQRBqJAAL2wEBBH8jAEEQayIFJAAjAEEgayIDJAAgA0EYaiAAIAEQvQIgAygCGCEEIAMoAhwhBiMAQRBrIgEkACABIAY2AgwgAiAEIAYgBGsiBBBNIAEgAiAEajYCCCADQRBqIAFBDGogAUEIahBmIAFBEGokACADKAIQIQQjAEEQayIBJAAgASAANgIMIAFBDGoiACAEIAAQ7AFrEPMBIQAgAUEQaiQAIAMgADYCDCADIAIgAygCFBCOATYCCCAFQQhqIANBDGogA0EIahBmIANBIGokACAFKAIMIAVBEGokAAsRACAAIAEgASgCACgCKBEBAAvLBQEKfyMAQRBrIhQkACACIAA2AgAgA0GABHEhFgNAIBVBBEYEQCANEB9BAUsEQCAUIA0QTjYCDCACIBRBDGpBARDzASANEHcgAigCABDgAjYCAAsgA0GwAXEiA0EQRwRAIAEgA0EgRgR/IAIoAgAFIAALNgIACyAUQRBqJAAFAkACQAJAAkACQAJAIAggFWotAAAOBQABAwIEBQsgASACKAIANgIADAQLIAEgAigCADYCACAGQSAQQSEPIAIgAigCACIQQQFqNgIAIBAgDzoAAAwDCyANEFoNAiANQQAQIi0AACEPIAIgAigCACIQQQFqNgIAIBAgDzoAAAwCCyAMEFogFkVyDQEgAiAMEE4gDBB3IAIoAgAQ4AI2AgAMAQsgAigCACAEIAdqIgQhEQNAAkAgBSARTQ0AIAZBwAAgESwAABBgRQ0AIBFBAWohEQwBCwsgDiIPQQBKBEADQCAPRSAEIBFPckUEQCAPQQFrIQ8gEUEBayIRLQAAIRAgAiACKAIAIhJBAWo2AgAgEiAQOgAADAELCyAPBH8gBkEwEEEFQQALIRIDQCACIAIoAgAiEEEBajYCACAPQQBKBEAgECASOgAAIA9BAWshDwwBCwsgECAJOgAACwJAIAQgEUYEQCAGQTAQQSEPIAIgAigCACIQQQFqNgIAIBAgDzoAAAwBCyALEFoEf0F/BSALQQAQIiwAAAshEEEAIQ9BACETA0AgBCARRg0BAkAgDyAQRwRAIA8hEgwBCyACIAIoAgAiEEEBajYCACAQIAo6AABBACESIAsQHyATQQFqIhNNBEAgDyEQDAELIAsgExAiLQAAQf8ARgRAQX8hEAwBCyALIBMQIiwAACEQCyARQQFrIhEtAAAhDyACIAIoAgAiGEEBajYCACAYIA86AAAgEkEBaiEPDAALAAsgAigCABCEAQsgFUEBaiEVDAELCwu7AQEBfyMAQRBrIgokAAJ/IAAEQCACEO0CDAELIAIQ7AILIQACQCABBEAgCkEEaiIBIAAQkgEgAyAKKAIENgAAIAEgABDCAQwBCyAKQQRqIgEgABDhAiADIAooAgQ2AAAgASAAEHsLIAggARBwIAEQIBogBCAAEHg6AAAgBSAAEFk6AAAgCkEEaiIBIAAQWCAGIAEQcCABECAaIAEgABB8IAcgARBwIAEQIBogCSAAEMEBNgIAIApBEGokAAsIACAAKAIARQsKACAAQdjwARB6CwoAIABB4PABEHoLFwAgAiAAIAEgAGsiAEECdRBlIAAgAmoLgwIBBX8jAEEQayIGJAAgBkEMaiIJIAZBCGogABBVKAIAELwBIwBBEGsiBSQAAkBB9////wMgAWsgAk8EQCAAECMhByAFQQRqIgggAUHz////AUkEfyAFIAFBAXQ2AgwgBSABIAJqNgIEIAggBUEMahCgASgCABCQAUEBagVB9////wMLEI8BIAUoAgQhAiAFKAIIGiAEBEAgAiAHIAQQZQsgAyAERwRAIARBAnQiCCACaiAHIAhqIAMgBGsQZQsgAUEBaiIBQQJHBEAgByABEKkBCyAAIAI2AgAgACAFKAIIEFwgBUEQaiQADAELEFsACyAAIAM2AgQgCRC7ASAGQRBqJAALHwEBfyABKAIAELwDIQIgACABKAIANgIEIAAgAjYCAAuyDgEKfyMAQZAEayILJAAgCyAKNgKIBCALIAE2AowEAkAgACALQYwEahArBEAgBSAFKAIAQQRyNgIAQQAhAAwBCyALQeQANgJIIAsgC0HoAGogC0HwAGogC0HIAGoiARA2Ig8oAgAiCjYCZCALIApBkANqNgJgIAEQJCERIAtBPGoQJCEMIAtBMGoQJCEOIAtBJGoQJCENIAtBGGoQJCEQIwBBEGsiASQAAkAgAgRAIAFBBGoiCiADEOYCIgIQkgEMAQsgAUEEaiIKIAMQ5QIiAhCSAQsgCyABKAIENgBcIAogAhDCASANIAoQqwEgChA5GiAKIAIQeyAOIAoQqwEgChA5GiALIAIQeDYCWCALIAIQWTYCVCAKIAIQWCARIAoQcCAKECAaIAogAhB8IAwgChCrASAKEDkaIAsgAhDBATYCFCABQRBqJAAgCSAIKAIANgIAIARBgARxIRJBACEDQQAhAQNAIAEhAgJAAkACQAJAIANBBEYNACAAIAtBjARqECsNAEEAIQoCQAJAAkACQAJAAkAgC0HcAGogA2otAAAOBQEABAMFCQsgA0EDRg0HIAdBASAAEDcQXwRAIAtBDGogABDpAiAQIAsoAgwQ6gEMAgsgBSAFKAIAQQRyNgIAQQAhAAwGCyADQQNGDQYLA0AgACALQYwEahArDQYgB0EBIAAQNxBfRQ0GIAtBDGogABDpAiAQIAsoAgwQ6gEMAAsACwJAIA4QH0UNACAAEDcgDhAjKAIARw0AIAAQPhogBkEAOgAAIA4gAiAOEB9BAUsbIQEMBgsCQCANEB9FDQAgABA3IA0QIygCAEcNACAAED4aIAZBAToAACANIAIgDRAfQQFLGyEBDAYLAkAgDhAfRQ0AIA0QH0UNACAFIAUoAgBBBHI2AgBBACEADAQLIA4QH0UEQCANEB9FDQULIAYgDRAfRToAAAwECyASIAIgA0ECSXJyRQRAQQAhASADQQJGIAstAF9BAEdxRQ0FCyALIAwQTjYCCCALQQxqIAtBCGoQwwEhAQJAIANFDQAgAyALai0AW0EBSw0AA0ACQCALIAwQdTYCCCABIAtBCGoQdg0AIAdBASABKAIAKAIAEF9FDQAgARD2AQwBCwsgCyAMEE42AgggASgCACALQQhqIgQoAgBrQQJ1IgogEBAfTQRAIAsgEBB1NgIIIARBACAKaxDwASAQEHUhCiAMEE4hEyMAQRBrIhQkABBzIQQgChBzIQogBCATEHMgCiAEa0F8cRCLAUUgFEEQaiQADQELIAsgDBBONgIEIAEgC0EIaiALQQRqEMMBKAIANgIACyALIAEoAgA2AggDQAJAIAsgDBB1NgIEIAtBCGoiASALQQRqEHYNACAAIAtBjARqECsNACAAEDcgASgCACgCAEcNACAAED4aIAEQ9gEMAQsLIBJFDQMgCyAMEHU2AgQgC0EIaiALQQRqEHYNAyAFIAUoAgBBBHI2AgBBACEADAILA0ACQCAAIAtBjARqECsNAAJ/IAdBwAAgABA3IgEQXwRAIAkoAgAiBCALKAKIBEYEQCAIIAkgC0GIBGoQkwEgCSgCACEECyAJIARBBGo2AgAgBCABNgIAIApBAWoMAQsgERAfRSAKRXINASABIAsoAlRHDQEgCygCZCIBIAsoAmBGBEAgDyALQeQAaiALQeAAahCTASALKAJkIQELIAsgAUEEajYCZCABIAo2AgBBAAshCiAAED4aDAELCyAKRSALKAJkIgEgDygCAEZyRQRAIAsoAmAgAUYEQCAPIAtB5ABqIAtB4ABqEJMBIAsoAmQhAQsgCyABQQRqNgJkIAEgCjYCAAsCQCALKAIUQQBMDQACQCAAIAtBjARqECtFBEAgABA3IAsoAlhGDQELIAUgBSgCAEEEcjYCAEEAIQAMAwsDQCAAED4aIAsoAhRBAEwNAQJAIAAgC0GMBGoQK0UEQCAHQcAAIAAQNxBfDQELIAUgBSgCAEEEcjYCAEEAIQAMBAsgCSgCACALKAKIBEYEQCAIIAkgC0GIBGoQkwELIAAQNyEBIAkgCSgCACIEQQRqNgIAIAQgATYCACALIAsoAhRBAWs2AhQMAAsACyACIQEgCCgCACAJKAIARw0DIAUgBSgCAEEEcjYCAEEAIQAMAQsCQCACRQ0AQQEhCgNAIAIQHyAKTQ0BAkAgACALQYwEahArRQRAIAAQNyACIAoQzAEoAgBGDQELIAUgBSgCAEEEcjYCAEEAIQAMAwsgABA+GiAKQQFqIQoMAAsAC0EBIQAgDygCACALKAJkRg0AQQAhACALQQA2AgwgESAPKAIAIAsoAmQgC0EMahBDIAsoAgwEQCAFIAUoAgBBBHI2AgAMAQtBASEACyAQEDkaIA0QORogDhA5GiAMEDkaIBEQIBogDxA1DAMLIAIhAQsgA0EBaiEDDAALAAsgC0GQBGokACAACxgAIAAgARCsARA8IAAgARDyASgCADYCBAsKACAAQcjwARB6CwoAIABB0PABEHoLxwEBBn8jAEEQayIEJAAgABDyASgCACEFQQECfyACKAIAIAAoAgBrIgNB/////wdJBEAgA0EBdAwBC0F/CyIDIANBAU0bIQMgASgCACEGIAAoAgAhByAFQeQARgR/QQAFIAAoAgALIAMQ3AEiCARAIAVB5ABHBEAgABCsARoLIARB4wA2AgQgACAEQQhqIAggBEEEahA2IgUQ6wIgBRA1IAEgACgCACAGIAdrajYCACACIAMgACgCAGo2AgAgBEEQaiQADwsQPQALIAEBfyABKAIAEJ0CwCECIAAgASgCADYCBCAAIAI6AAALxA4BCn8jAEGQBGsiCyQAIAsgCjYCiAQgCyABNgKMBAJAIAAgC0GMBGoQLARAIAUgBSgCAEEEcjYCAEEAIQAMAQsgC0HkADYCTCALIAtB6ABqIAtB8ABqIAtBzABqIgEQNiIPKAIAIgo2AmQgCyAKQZADajYCYCABECQhESALQUBrECQhDCALQTRqECQhDiALQShqECQhDSALQRxqECQhECMAQRBrIgEkAAJAIAIEQCABQQRqIgogAxDtAiICEJIBDAELIAFBBGoiCiADEOwCIgIQkgELIAsgASgCBDYAXCAKIAIQwgEgDSAKEHAgChAgGiAKIAIQeyAOIAoQcCAKECAaIAsgAhB4OgBbIAsgAhBZOgBaIAogAhBYIBEgChBwIAoQIBogCiACEHwgDCAKEHAgChAgGiALIAIQwQE2AhggAUEQaiQAIAkgCCgCADYCACAEQYAEcSESQQAhA0EAIQEDQCABIQICQAJAAkACQCADQQRGDQAgACALQYwEahAsDQBBACEKAkACQAJAAkACQAJAIAtB3ABqIANqLQAADgUBAAQDBQkLIANBA0YNByAHQQEgABA4EGAEQCALQRBqIAAQ7wIgECALLAAQELgBDAILIAUgBSgCAEEEcjYCAEEAIQAMBgsgA0EDRg0GCwNAIAAgC0GMBGoQLA0GIAdBASAAEDgQYEUNBiALQRBqIAAQ7wIgECALLAAQELgBDAALAAsCQCAOEB9FDQAgABA4Qf8BcSAOQQAQIi0AAEcNACAAED8aIAZBADoAACAOIAIgDhAfQQFLGyEBDAYLAkAgDRAfRQ0AIAAQOEH/AXEgDUEAECItAABHDQAgABA/GiAGQQE6AAAgDSACIA0QH0EBSxshAQwGCwJAIA4QH0UNACANEB9FDQAgBSAFKAIAQQRyNgIAQQAhAAwECyAOEB9FBEAgDRAfRQ0FCyAGIA0QH0U6AAAMBAsgEiACIANBAklyckUEQEEAIQEgA0ECRiALLQBfQQBHcUUNBQsgCyAMEE42AgwgC0EQaiALQQxqEMMBIQECQCADRQ0AIAMgC2otAFtBAUsNAANAAkAgCyAMEHc2AgwgASALQQxqEHYNACAHQQEgASgCACwAABBgRQ0AIAEQ+AEMAQsLIAsgDBBONgIMIAEoAgAgC0EMaiIEKAIAayIKIBAQH00EQCALIBAQdzYCDCAEQQAgCmsQ8wEgEBB3IQogDBBOIRMjAEEQayIUJAAQcyEEIAoQcyEKIAQgExBzIAogBGsQiwFFIBRBEGokAA0BCyALIAwQTjYCCCABIAtBDGogC0EIahDDASgCADYCAAsgCyABKAIANgIMA0ACQCALIAwQdzYCCCALQQxqIgEgC0EIahB2DQAgACALQYwEahAsDQAgABA4Qf8BcSABKAIALQAARw0AIAAQPxogARD4AQwBCwsgEkUNAyALIAwQdzYCCCALQQxqIAtBCGoQdg0DIAUgBSgCAEEEcjYCAEEAIQAMAgsDQAJAIAAgC0GMBGoQLA0AAn8gB0HAACAAEDgiARBgBEAgCSgCACIEIAsoAogERgRAIAggCSALQYgEahDuAiAJKAIAIQQLIAkgBEEBajYCACAEIAE6AAAgCkEBagwBCyAREB9FIApFcg0BIAstAFogAUH/AXFHDQEgCygCZCIBIAsoAmBGBEAgDyALQeQAaiALQeAAahCTASALKAJkIQELIAsgAUEEajYCZCABIAo2AgBBAAshCiAAED8aDAELCyAKRSALKAJkIgEgDygCAEZyRQRAIAsoAmAgAUYEQCAPIAtB5ABqIAtB4ABqEJMBIAsoAmQhAQsgCyABQQRqNgJkIAEgCjYCAAsCQCALKAIYQQBMDQACQCAAIAtBjARqECxFBEAgABA4Qf8BcSALLQBbRg0BCyAFIAUoAgBBBHI2AgBBACEADAMLA0AgABA/GiALKAIYQQBMDQECQCAAIAtBjARqECxFBEAgB0HAACAAEDgQYA0BCyAFIAUoAgBBBHI2AgBBACEADAQLIAkoAgAgCygCiARGBEAgCCAJIAtBiARqEO4CCyAAEDghASAJIAkoAgAiBEEBajYCACAEIAE6AAAgCyALKAIYQQFrNgIYDAALAAsgAiEBIAgoAgAgCSgCAEcNAyAFIAUoAgBBBHI2AgBBACEADAELAkAgAkUNAEEBIQoDQCACEB8gCk0NAQJAIAAgC0GMBGoQLEUEQCAAEDhB/wFxIAIgChAiLQAARg0BCyAFIAUoAgBBBHI2AgBBACEADAMLIAAQPxogCkEBaiEKDAALAAtBASEAIA8oAgAgCygCZEYNAEEAIQAgC0EANgIQIBEgDygCACALKAJkIAtBEGoQQyALKAIQBEAgBSAFKAIAQQRyNgIADAELQQEhAAsgEBAgGiANECAaIA4QIBogDBAgGiARECAaIA8QNQwDCyACIQELIANBAWohAwwACwALIAtBkARqJAAgAAsMACAAQQFBLRD9AhoLCwAgAEEBQS0QsAILHAEBfyAALQAAIQIgACABLQAAOgAAIAEgAjoAAAtlAQF/IwBBEGsiBiQAIAZBADoADyAGIAU6AA4gBiAEOgANIAZBJToADCAFBEAgBkENaiAGQQ5qEPMCCyACIAEgASACKAIAEIoCIAZBDGogAyAAKAIAEJ4DIAFqNgIAIAZBEGokAAtBACABIAIgAyAEQQQQZyEBIAMtAABBBHFFBEAgACABQdAPaiABQewOaiABIAFB5ABJGyABQcUASBtB7A5rNgIACwtAACACIAMgAEEIaiAAKAIIKAIEEQAAIgAgAEGgAmogBSAEQQAQzQEgAGsiAEGfAkwEQCABIABBDG1BDG82AgALC0AAIAIgAyAAQQhqIAAoAggoAgARAAAiACAAQagBaiAFIARBABDNASAAayIAQacBTARAIAEgAEEMbUEHbzYCAAsLQQAgASACIAMgBEEEEGghASADLQAAQQRxRQRAIAAgAUHQD2ogAUHsDmogASABQeQASRsgAUHFAEgbQewOazYCAAsLQAAgAiADIABBCGogACgCCCgCBBEAACIAIABBoAJqIAUgBEEAEM8BIABrIgBBnwJMBEAgASAAQQxtQQxvNgIACwtAACACIAMgAEEIaiAAKAIIKAIAEQAAIgAgAEGoAWogBSAEQQAQzwEgAGsiAEGnAUwEQCABIABBDG1BB282AgALCxgBAX9BDBBTIgBBADYCCCAAQgA3AgAgAAsEAEECC8oBAQR/IwBBEGsiAyQAAkAgAUH3////A00EQAJAIAEQvQEEQCAAIAEQUCAAIQQMAQsgA0EIaiABEJABQQFqEI8BIAMoAgwaIAAgAygCCCIENgIAIAAgAygCDBBcIAAgATYCBAsjAEEQayIFJAAgBSACNgIMIAQhBiABIQIDQCACBEAgBiAFKAIMNgIAIAJBAWshAiAGQQRqIQYMAQsLIAVBEGokACADQQA2AgQgBCABQQJ0aiADQQRqEFYgA0EQaiQADAELEFsACyAAC7IFAQp/IwBBEGsiCyQAIAYQSCEKIAtBBGogBhCZASIOEFggBSADNgIAAkACQCAAIggtAAAiBkEraw4DAAEAAQsgCiAGwBBLIQYgBSAFKAIAIgdBBGo2AgAgByAGNgIAIABBAWohCAsCQAJAIAIgCCIGa0EBTA0AIAYtAABBMEcNACAGLQABQSByQfgARw0AIApBMBBLIQcgBSAFKAIAIghBBGo2AgAgCCAHNgIAIAogBiwAARBLIQcgBSAFKAIAIghBBGo2AgAgCCAHNgIAIAZBAmoiCCEGA0AgAiAGTQ0CIAYsAAAQLhoQsANFDQIgBkEBaiEGDAALAAsDQCACIAZNDQEgBiwAABAuGhCvA0UNASAGQQFqIQYMAAsACwJAIAtBBGoQWgRAIAogCCAGIAUoAgAQbyAFIAUoAgAgBiAIa0ECdGo2AgAMAQsgCCAGEIQBIA4QWSEPIAghBwNAIAYgB00EQCADIAggAGtBAnRqIAUoAgAQxwEFAkAgC0EEaiIMIA0QIiwAAEEATA0AIAkgDCANECIsAABHDQAgBSAFKAIAIglBBGo2AgAgCSAPNgIAIA0gDSAMEB9BAWtJaiENQQAhCQsgCiAHLAAAEEshDCAFIAUoAgAiEEEEajYCACAQIAw2AgAgB0EBaiEHIAlBAWohCQwBCwsLAkACQANAIAIgBk0NASAGQQFqIQcgBiwAACIGQS5HBEAgCiAGEEshBiAFIAUoAgAiCEEEajYCACAIIAY2AgAgByEGDAELCyAOEHghBiAFIAUoAgAiCEEEaiIJNgIAIAggBjYCAAwBCyAFKAIAIQkgBiEHCyAKIAcgAiAJEG8gBSAFKAIAIAIgB2tBAnRqIgU2AgAgBCAFIAMgASAAa0ECdGogASACRhs2AgAgC0EEahAgGiALQRBqJAALDwAgAARAIAAQOgsgABAtC90DAQh/IwBBEGsiCyQAIAYQSCEKIAtBBGoiByAGEJkBIgYQWAJAIAcQWgRAIAogACACIAMQbyAFIAMgAiAAa0ECdGoiBjYCAAwBCyAFIAM2AgACQAJAIAAiBy0AACIIQStrDgMAAQABCyAKIAjAEEshByAFIAUoAgAiCEEEajYCACAIIAc2AgAgAEEBaiEHCwJAIAIgB2tBAkgNACAHLQAAQTBHDQAgBy0AAUEgckH4AEcNACAKQTAQSyEIIAUgBSgCACIJQQRqNgIAIAkgCDYCACAKIAcsAAEQSyEIIAUgBSgCACIJQQRqNgIAIAkgCDYCACAHQQJqIQcLIAcgAhCEAUEAIQkgBhBZIQ1BACEIIAchBgN/IAIgBk0EfyADIAcgAGtBAnRqIAUoAgAQxwEgBSgCAAUCQCALQQRqIgwgCBAiLQAARQ0AIAkgDCAIECIsAABHDQAgBSAFKAIAIglBBGo2AgAgCSANNgIAIAggCCAMEB9BAWtJaiEIQQAhCQsgCiAGLAAAEEshDCAFIAUoAgAiDkEEajYCACAOIAw2AgAgBkEBaiEGIAlBAWohCQwBCwshBgsgBCAGIAMgASAAa0ECdGogASACRhs2AgAgC0EEahAgGiALQRBqJAALRwIBfwF+IwBBIGsiBSQAIAMoAgAhAyAEKQMAIQYgBSAEKQMINwMQIAUgBjcDCCAFIAM2AgAgACABIAIgBRDAASAFQSBqJAALOwIBfwF+IwBBEGsiBCQAIAMpAwAhBSAEIAMpAwg3AwggBCAFNwMAIABBHiABIAIgBBCWASAEQRBqJAALSQIBfwF+IwBBIGsiBSQAIAMoAgAhAyAEKQMAIQYgBSAEKQMINwMQIAUgBjcDCCAFIAM2AgAgAEEeIAEgAiAFEJYBIAVBIGokAAuiBQEKfyMAQRBrIgokACAGEEkhCSAKQQRqIAYQmwEiDhBYIAUgAzYCAAJAAkAgACIILQAAIgZBK2sOAwABAAELIAkgBsAQQSEGIAUgBSgCACIHQQFqNgIAIAcgBjoAACAAQQFqIQgLAkACQCACIAgiBmtBAUwNACAGLQAAQTBHDQAgBi0AAUEgckH4AEcNACAJQTAQQSEHIAUgBSgCACIIQQFqNgIAIAggBzoAACAJIAYsAAEQQSEHIAUgBSgCACIIQQFqNgIAIAggBzoAACAGQQJqIgghBgNAIAIgBk0NAiAGLAAAEC4aELADRQ0CIAZBAWohBgwACwALA0AgAiAGTQ0BIAYsAAAQLhoQrwNFDQEgBkEBaiEGDAALAAsCQCAKQQRqEFoEQCAJIAggBiAFKAIAEHkgBSAFKAIAIAYgCGtqNgIADAELIAggBhCEASAOEFkhDyAIIQcDQCAGIAdNBEAgAyAIIABraiAFKAIAEIQBBQJAIApBBGoiDCANECIsAABBAEwNACALIAwgDRAiLAAARw0AIAUgBSgCACILQQFqNgIAIAsgDzoAACANIA0gDBAfQQFrSWohDUEAIQsLIAkgBywAABBBIQwgBSAFKAIAIhBBAWo2AgAgECAMOgAAIAdBAWohByALQQFqIQsMAQsLCwNAAkACQCACIAZNBEAgBiEHDAELIAZBAWohByAGLAAAIgZBLkcNASAOEHghBiAFIAUoAgAiCEEBajYCACAIIAY6AAALIAkgByACIAUoAgAQeSAFIAUoAgAgAiAHa2oiBTYCACAEIAUgAyABIABraiABIAJGGzYCACAKQQRqECAaIApBEGokAA8LIAkgBhBBIQYgBSAFKAIAIghBAWo2AgAgCCAGOgAAIAchBgwACwALKQEBfyMAQRBrIgQkACAEIAMrAwA5AwAgACABIAIgBBDAASAEQRBqJAALNwEBfyMAQRBrIgUkACADKAIAIQMgBSAEKwMAOQMIIAUgAzYCACAAIAEgAiAFEMABIAVBEGokAAsrAQF/IwBBEGsiBCQAIAQgAysDADkDACAAQR4gASACIAQQlgEgBEEQaiQACzkBAX8jAEEQayIFJAAgAygCACEDIAUgBCsDADkDCCAFIAM2AgAgAEEeIAEgAiAFEJYBIAVBEGokAAsrAQF/IwBBEGsiBCQAIAQgAykDADcDACAAQRggASACIAQQlgEgBEEQaiQAC9QDAQh/IwBBEGsiCyQAIAYQSSEKIAtBBGoiByAGEJsBIgYQWAJAIAcQWgRAIAogACACIAMQeSAFIAMgAiAAa2oiBjYCAAwBCyAFIAM2AgACQAJAIAAiBy0AACIIQStrDgMAAQABCyAKIAjAEEEhByAFIAUoAgAiCEEBajYCACAIIAc6AAAgAEEBaiEHCwJAIAIgB2tBAkgNACAHLQAAQTBHDQAgBy0AAUEgckH4AEcNACAKQTAQQSEIIAUgBSgCACIJQQFqNgIAIAkgCDoAACAKIAcsAAEQQSEIIAUgBSgCACIJQQFqNgIAIAkgCDoAACAHQQJqIQcLIAcgAhCEAUEAIQkgBhBZIQ1BACEIIAchBgN/IAIgBk0EfyADIAcgAGtqIAUoAgAQhAEgBSgCAAUCQCALQQRqIgwgCBAiLQAARQ0AIAkgDCAIECIsAABHDQAgBSAFKAIAIglBAWo2AgAgCSANOgAAIAggCCAMEB9BAWtJaiEIQQAhCQsgCiAGLAAAEEEhDCAFIAUoAgAiDkEBajYCACAOIAw6AAAgBkEBaiEGIAlBAWohCQwBCwshBgsgBCAGIAMgASAAa2ogASACRhs2AgAgC0EEahAgGiALQRBqJAALQwEBfyMAQRBrIgMkACADIAI2AgxBoCAgAUH02QFBuyxBGCADQQxqIgEQVEH02QFBvyxBGSABEFQQBCADQRBqJAAgAAuWAwECfyMAQdACayIAJAAgACACNgLIAiAAIAE2AswCIAMQaiEGIAMgAEHQAWoQrgEhByAAQcQBaiADIABBxAJqEK0BIABBuAFqECQiASABECgQISAAIAFBABAiIgI2ArQBIAAgAEEQajYCDCAAQQA2AggDQAJAIABBzAJqIABByAJqECsNACAAKAK0ASABEB8gAmpGBEAgARAfIQMgASABEB9BAXQQISABIAEQKBAhIAAgAyABQQAQIiICajYCtAELIABBzAJqIgMQNyAGIAIgAEG0AWogAEEIaiAAKALEAiAAQcQBaiAAQRBqIABBDGogBxCYAQ0AIAMQPhoMAQsLAkAgAEHEAWoQH0UNACAAKAIMIgMgAEEQamtBnwFKDQAgACADQQRqNgIMIAMgACgCCDYCAAsgBSACIAAoArQBIAQgBhCTAzYCACAAQcQBaiAAQRBqIAAoAgwgBBBDIABBzAJqIABByAJqECsEQCAEIAQoAgBBAnI2AgALIAAoAswCIAEQIBogAEHEAWoQIBogAEHQAmokAAtbAQF/IwBBEGsiAyQAIAMgAigCADYCACMAQRBrIgIkACACIAE2AgwgAiADNgIIIAJBBGogAkEMahBjIABB1w0gAigCCBCkAyEAEGIgAkEQaiQAIANBEGokACAAC9kCAgR+Bn8jAEEgayIIJAACQAJAAkAgASACRwRAQYjqASgCACENQYjqAUEANgIAIwBBEGsiCSQAEC4aIwBBEGsiCiQAIwBBEGsiCyQAIwBBEGsiDCQAIAwgASAIQRxqQQIQgAIgDCkDACEEIAsgDCkDCDcDCCALIAQ3AwAgDEEQaiQAIAspAwAhBCAKIAspAwg3AwggCiAENwMAIAtBEGokACAKKQMAIQQgCSAKKQMINwMIIAkgBDcDACAKQRBqJAAgCSkDACEEIAggCSkDCDcDECAIIAQ3AwggCUEQaiQAIAgpAxAhBCAIKQMIIQVBiOoBKAIAIgFFDQEgCCgCHCACRw0CIAUhBiAEIQcgAUHEAEcNAwwCCyADQQQ2AgAMAgtBiOoBIA02AgAgCCgCHCACRg0BCyADQQQ2AgAgBiEFIAchBAsgACAFNwMAIAAgBDcDCCAIQSBqJAALwAECA38BfCMAQRBrIgMkAAJAAkACQCAAIAFHBEBBiOoBKAIAIQVBiOoBQQA2AgAQLhojAEEQayIEJAAgBCAAIANBDGpBARCAAiAEKQMAIAQpAwgQlQIhBiAEQRBqJAACQEGI6gEoAgAiAARAIAMoAgwgAUYNAQwDC0GI6gEgBTYCACADKAIMIAFHDQIMBAsgAEHEAEcNAwwCCyACQQQ2AgAMAgtEAAAAAAAAAAAhBgsgAkEENgIACyADQRBqJAAgBgubCgEEfyMAQRBrIgIkAEGACEEEQZAgQd4gQQRBAkEAQQAQC0HtC0ECQeQgQZghQQVBA0EAQQAQCyMAQSBrIgEkAEGY4AEtAABFBEBBmOABQQE6AABBnCFBvNoBEAcLQewgQYwlQcQlQQBB+iVBBkH9JUEAQf0lQQBB1xtB/yVBBxAJQewgQQFBhCZBiCZBIkEIEAYgAUEANgIcIAFBCTYCGCABIAEpAhg3AxAjAEEQayIAJAAgACABKQIQNwIIQewgQYoPQQNBjCZBmCZBIyAAQQhqEI0BQQBBAEEAEAEgAEEQaiQAIAFBADYCHCABQQo2AhggASABKQIYNwMIIwBBEGsiACQAIAAgASkCCDcCCEHsIEHKEEEEQaAmQbAmQSQgAEEIahCNAUEAQQBBABABIABBEGokACABQQA2AhwgAUELNgIYIAEgASkCGDcDACMAQRBrIgAkACAAIAEpAgA3AghB7CBB4BBBAkG4JkHAJkElIABBCGoQjQFBAEEAQQAQASAAQRBqJAAjAEEQayIAJAAgAEEMNgIMQewgQZoKQQNB6CZB9CZBJiAAQQxqEFRBAEEAQQAQASAAQRBqJAAjAEEQayIAJAAgAEENNgIMQewgQZYKQQRBgCdBkCdBJyAAQQxqEFRBAEEAQQAQASAAQRBqJAAgAUEgaiQAIwBBIGsiASQAQaTgAS0AAEUEQEGk4AFBAToAAEGYJ0HE2QEQBwtBpCpB0CpBiCtBAEG+K0EOQf0lQQBB/SVBAEG0FUHBK0EPEAlBpCpBAUHEK0HIK0EoQRAQBiABQQA2AhwgAUERNgIYIAEgASkCGDcDECMAQRBrIgAkACAAIAEpAhA3AghBpCpBig9BA0HMK0HYK0EpIABBCGoQjQFBAEEAQQAQASAAQRBqJAAgAUEANgIcIAFBEjYCGCABIAEpAhg3AwgjAEEQayIAJAAgACABKQIINwIIQaQqQcoQQQRB4CtB8CtBKiAAQQhqEI0BQQBBAEEAEAEgAEEQaiQAIAFBADYCHCABQRM2AhggASABKQIYNwMAIwBBEGsiACQAIAAgASkCADcCCEGkKkHgEEECQfgrQYAsQSsgAEEIahCNAUEAQQBBABABIABBEGokACMAQRBrIgAkACAAQRQ2AgxBpCpBmgpBA0GMLEGYLEEsIABBDGoQVEEAQQBBABABIABBEGokACMAQRBrIgAkACAAQRU2AgxBpCpBlgpBBEGgLEGwLEEtIABBDGoQVEEAQQBBABABIABBEGokACABQSBqJABBoCBBhhJBtixBFkG4LEEXEAggAkEPakHGCkEAEIsDQZMRQQQQiwMjAEEQayIBJAAgAUEINgIMQaAgQZ8TQazZAUHELEEaIAFBDGoiAxBUQazZAUHILEEbIAMQVBAEIAFBEGokAEHlCkEMEJcBQboLQRgQlwFB7wpBJBCXAUHBC0EwEJcBQdAKQTwQlwFBtg9ByAAQlwEaQaAgEBBB2CxB/w1BBEEBEBFB2CxBgBZBABADQdgsQZoWQQEQA0HYLEGWFkECEANB2CxBkhZBAxADQdgsQY4WQQQQA0HYLEH8FUEFEANB2CxB+BVBBhADQdgsQfAVQQcQA0HYLEHsFUEIEANBwCBB1wpB+SxBHkH7LEEfEAgjAEEQayIBJAAgAUEANgIMQcAgQe4NQdgsQf4sQSAgAUEMaiIAEFRB2CxBgi1BISAAEFQQBCABQRBqJABBwCAQECACQRBqJAALvAECA38BfSMAQRBrIgMkAAJAAkACQCAAIAFHBEBBiOoBKAIAIQVBiOoBQQA2AgAQLhojAEEQayIEJAAgBCAAIANBDGpBABCAAiAEKQMAIAQpAwgQpgMhBiAEQRBqJAACQEGI6gEoAgAiAARAIAMoAgwgAUYNAQwDC0GI6gEgBTYCACADKAIMIAFHDQIMBAsgAEHEAEcNAwwCCyACQQQ2AgAMAgtDAAAAACEGCyACQQQ2AgALIANBEGokACAGC8MBAgN/AX4jAEEQayIEJAACfgJAAkAgACABRwRAAkACQCAALQAAIgVBLUcNACAAQQFqIgAgAUcNAAwBC0GI6gEoAgAhBkGI6gFBADYCABAuGiAAIARBDGogAxCCAiEHAkBBiOoBKAIAIgAEQCAEKAIMIAFHDQEgAEHEAEYNBAwFC0GI6gEgBjYCACAEKAIMIAFGDQQLCwsgAkEENgIAQgAMAgsgAkEENgIAQn8MAQtCACAHfSAHIAVBLUYbCyAEQRBqJAAL1AECA38BfiMAQRBrIgQkAAJ/AkACQAJAIAAgAUcEQAJAAkAgAC0AACIFQS1HDQAgAEEBaiIAIAFHDQAMAQtBiOoBKAIAIQZBiOoBQQA2AgAQLhogACAEQQxqIAMQggIhBwJAQYjqASgCACIABEAgBCgCDCABRw0BIABBxABGDQUMBAtBiOoBIAY2AgAgBCgCDCABRg0DCwsLIAJBBDYCAEEADAMLIAdC/////w9YDQELIAJBBDYCAEF/DAELQQAgB6ciAGsgACAFQS1GGwsgBEEQaiQAC4sDAQF/IwBBgAJrIgAkACAAIAI2AvgBIAAgATYC/AEgAxBqIQYgAEHEAWogAyAAQfcBahCvASAAQbgBahAkIgEgARAoECEgACABQQAQIiICNgK0ASAAIABBEGo2AgwgAEEANgIIA0ACQCAAQfwBaiAAQfgBahAsDQAgACgCtAEgARAfIAJqRgRAIAEQHyEDIAEgARAfQQF0ECEgASABECgQISAAIAMgAUEAECIiAmo2ArQBCyAAQfwBaiIDEDggBiACIABBtAFqIABBCGogACwA9wEgAEHEAWogAEEQaiAAQQxqQdCfARCaAQ0AIAMQPxoMAQsLAkAgAEHEAWoQH0UNACAAKAIMIgMgAEEQamtBnwFKDQAgACADQQRqNgIMIAMgACgCCDYCAAsgBSACIAAoArQBIAQgBhCTAzYCACAAQcQBaiAAQRBqIAAoAgwgBBBDIABB/AFqIABB+AFqECwEQCAEIAQoAgBBAnI2AgALIAAoAvwBIAEQIBogAEHEAWoQIBogAEGAAmokAAvZAQIDfwF+IwBBEGsiBCQAAn8CQAJAAkAgACABRwRAAkACQCAALQAAIgVBLUcNACAAQQFqIgAgAUcNAAwBC0GI6gEoAgAhBkGI6gFBADYCABAuGiAAIARBDGogAxCCAiEHAkBBiOoBKAIAIgAEQCAEKAIMIAFHDQEgAEHEAEYNBQwEC0GI6gEgBjYCACAEKAIMIAFGDQMLCwsgAkEENgIAQQAMAwsgB0L//wNYDQELIAJBBDYCAEH//wMMAQtBACAHpyIAayAAIAVBLUYbCyAEQRBqJABB//8DcQu3AQIBfgJ/IwBBEGsiBSQAAkACQCAAIAFHBEBBiOoBKAIAIQZBiOoBQQA2AgAQLhogACAFQQxqIAMQmgMhBAJAQYjqASgCACIABEAgBSgCDCABRw0BIABBxABGDQMMBAtBiOoBIAY2AgAgBSgCDCABRg0DCwsgAkEENgIAQgAhBAwBCyACQQQ2AgAgBEIAVQRAQv///////////wAhBAwBC0KAgICAgICAgIB/IQQLIAVBEGokACAEC8ABAgJ/AX4jAEEQayIEJAACfwJAAkAgACABRwRAQYjqASgCACEFQYjqAUEANgIAEC4aIAAgBEEMaiADEJoDIQYCQEGI6gEoAgAiAARAIAQoAgwgAUcNASAAQcQARg0EDAMLQYjqASAFNgIAIAQoAgwgAUYNAgsLIAJBBDYCAEEADAILIAZCgICAgHhTIAZC/////wdVcg0AIAanDAELIAJBBDYCAEH/////ByAGQgBVDQAaQYCAgIB4CyAEQRBqJAALMwEBfyABIAAoAgQiAWohAgNAIAEgAkYEQCAAIAI2AgQFIAFBADoAACABQQFqIQEMAQsLC5EBAQN/AkAgASACEPUBIQQjAEEQayIDJAAgBEH3////A00EQAJAIAQQvQEEQCAAIAQQUCAAIQUMAQsgA0EIaiAEEJABQQFqEI8BIAMoAgwaIAAgAygCCCIFNgIAIAAgAygCDBBcIAAgBDYCBAsgASACIAUQ5wIgA0EANgIEIANBBGoQViADQRBqJAAMAQsQWwALCxYAIAAgASACQoCAgICAgICAgH8QhAILhwgBBX8gASgCACEEAkACQAJAAkACQAJAAkACfwJAAkACQAJAIANFDQAgAygCACIFRQ0AIABFBEAgAiEDDAMLIANBADYCACACIQMMAQsCQEHc4QEoAgAoAgBFBEAgAEUNASACRQ0MIAIhBQNAIAQsAAAiAwRAIAAgA0H/vwNxNgIAIABBBGohACAEQQFqIQQgBUEBayIFDQEMDgsLIABBADYCACABQQA2AgAgAiAFaw8LIAIhAyAARQ0DDAULIAQQqAEPC0EBIQYMAwtBAAwBC0EBCyEGA0AgBkUEQCAELQAAQQN2IgZBEGsgBUEadSAGanJBB0sNAwJ/IARBAWoiBiAFQYCAgBBxRQ0AGiAGLAAAQUBOBEAgBEEBayEEDAcLIARBAmoiBiAFQYCAIHFFDQAaIAYsAABBQE4EQCAEQQFrIQQMBwsgBEEDagshBCADQQFrIQNBASEGDAELA0ACQCAEQQNxIAQsAAAiBUEATHINACAEKAIAIgVBgYKECGsgBXJBgIGChHhxDQADQCADQQRrIQMgBCgCBCEFIARBBGohBCAFIAVBgYKECGtyQYCBgoR4cUUNAAsLIAXAQQBKBEAgA0EBayEDIARBAWohBAwBCwsgBUH/AXFBwgFrIgZBMksNAyAEQQFqIQQgBkECdCgCkIEBIQVBACEGDAALAAsDQCAGRQRAIANFDQcDQAJAIAQtAAAiBsAiBUEATA0AIARBA3EgA0EFSXJFBEACQANAIAQoAgAiBUGBgoQIayAFckGAgYKEeHENASAAIAVB/wFxNgIAIAAgBC0AATYCBCAAIAQtAAI2AgggACAELQADNgIMIABBEGohACAEQQRqIQQgA0EEayIDQQRLDQALIAQtAAAhBQsgBUH/AXEhBiAFwEEATA0BCyAAIAY2AgAgAEEEaiEAIARBAWohBCADQQFrIgMNAQwJCwsgBkHCAWsiBkEySw0DIARBAWohBCAGQQJ0KAKQgQEhBUEBIQYMAQsgBC0AACIGQQN2IgdBEGsgByAFQRp1anJBB0sNAQJAAkACfyAEQQFqIgcgBkGAAWsgBUEGdHIiBkEATg0AGiAHLQAAQYABayIHQT9LDQEgByAGQQZ0IghyIQYgBEECaiIHIAhBAE4NABogBy0AAEGAAWsiB0E/Sw0BIAcgBkEGdHIhBiAEQQNqCyEEIAAgBjYCACADQQFrIQMgAEEEaiEADAELQYjqAUEZNgIAIARBAWshBAwFC0EAIQYMAAsACyAEQQFrIQQgBQ0BIAQtAAAhBQsgBUH/AXENACAABEAgAEEANgIAIAFBADYCAAsgAiADaw8LQYjqAUEZNgIAIABFDQELIAEgBDYCAAtBfw8LIAEgBDYCACACCzEBAX9B3OEBKAIAIQEgAARAQdzhAUHk4AEgACAAQX9GGzYCAAtBfyABIAFB5OABRhsLOAAgAEHQD2sgACAAQZPx//8HShsiAEEDcQRAQQAPCyAAQewOaiIAQeQAbwRAQQEPCyAAQZADb0ULlxMCD38EfiMAQYABayIIJAAgAQRAAn8DQAJAAn8CQAJAAkAgAi0AACIGQSVHBEAgBg0BIAoMBwtBACEFQQEhCQJAIAItAAEiB0Etaw4EAgMDAgALIAdB3wBGDQEgBw0CCyAAIApqIAY6AAAgCkEBagwCCyAHIQUgAi0AAiEHQQIhCQtBACEOAkACfyACIAlqIAciEkErRmoiCSwAAEEwa0EJTQRAIAkgCEEMakEKQv////8PEIQCpyECIAgoAgwMAQsgCCAJNgIMQQAhAiAJCyIHLQAAIgZBwwBrIgtBFktBASALdEGZgIACcUVyDQAgAiIODQAgByAJRyEOCyAGQc8ARiAGQcUARnIEfyAHLQABIQYgB0EBagUgBwshAiAIQRBqIQcgBSEJQQAhBSMAQdAAayILJABB5QghDUEwIRBBqIAIIQwCQCAIAn8CQAJAAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkACQAJAAn4CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAbAIgZBJWsOViEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0BAwQnLQcICQotLS0NLS0tLRASFBYYFxweIC0tLS0tLQACJgYFLQgCLQstLQwOLQ8tJRETFS0ZGx0fLQsgAygCGCIFQQZNDSIMKgsgAygCGCIFQQZLDSkgBUGHgAhqDCILIAMoAhAiBUELSw0oIAVBjoAIagwhCyADKAIQIgVBC0sNJyAFQZqACGoMIAsgAzQCFELsDnxC5AB/IRQMIwtB3wAhEAsgAzQCDCEUDCELQa8TIQ0MHwsgAzQCFCIVQuwOfCEUAkAgAygCHCIFQQJMBEAgFCAVQusOfCADEIMCQQFGGyEUDAELIAVB6QJJDQAgFULtDnwgFCADEIMCQQFGGyEUCyAGQecARg0ZDCALIAM0AgghFAweC0ECIQUgAygCCCIGRQRAQgwhFAwgCyAGrCIUQgx9IBQgBkEMShshFAwfCyADKAIcQQFqrCEUQQMhBQweCyADKAIQQQFqrCEUDBsLIAM0AgQhFAwaCyAIQQE2AnxBwx8hBQweC0GngAhBpoAIIAMoAghBC0obDBQLQdQVIQ0MFgtBACEMQQAhESMAQRBrIg8kACADNAIUIRQCfiADKAIQIg1BDE8EQCANIA1BDG0iBkEMbGsiBUEMaiAFIAVBAEgbIQ0gBiAFQR91aqwgFHwhFAsgD0EMaiEGIBRCAn1CiAFYBEAgFKciDEHEAGtBAnUhBQJAIAYCfyAMQQNxRQRAIAVBAWshBSAGRQ0CQQEMAQsgBkUNAUEACzYCAAsgDEGA54QPbCAFQYCjBWxqQYDWr+MHaqwMAQsgFELkAH0iFCAUQpADfyIWQpADfn0iFUI/h6cgFqdqIRMCQAJAAkAgFaciBUGQA2ogBSAVQgBTGyIFBH8CfyAFQcgBTgRAIAVBrAJPBEBBAyEMIAVBrAJrDAILQQIhDCAFQcgBawwBCyAFQeQAayAFIAVB4wBKIgwbCyIFDQFBAAVBAQshBSAGDQEMAgsgBUECdiERIAVBA3FFIQUgBkUNAQsgBiAFNgIACyAUQoDnhA9+IBEgDEEYbCATQeEAbGpqIAVrrEKAowV+fEKAqrrDA3wLIRQgDUECdEGwnAFqKAIAIgVBgKMFaiAFIA8oAgwbIAUgDUEBShshBSADKAIMIQYgAzQCCCEVIAM0AgQhFiADNAIAIA9BEGokACAUIAWsfCAGQQFrrEKAowV+fCAVQpAcfnwgFkI8fnx8IAM0AiR9DAgLIAM0AgAhFAwVCyAIQQE2AnxBxR8hBQwZC0HBFSENDBILIAMoAhgiBUEHIAUbrAwECyADKAIcIAMoAhhrQQdqQQdurSEUDBELIAMoAhwgAygCGEEGakEHcGtBB2pBB26tIRQMEAsgAxCDAq0hFAwPCyADNAIYCyEUQQEhBQwPC0GpgAghDAwKC0GqgAghDAwJCyADNAIUQuwOfELkAIEiFCAUQj+HIhSFIBR9IRQMCgsgAzQCFCIVQuwOfCEUIBVCpD9TDQogCyAUNwMwIAggB0H4EiALQTBqEIYBNgJ8IAchBQwOCyADKAIgQQBIBEAgCEEANgJ8QcYfIQUMDgsgCyADKAIkIgVBkBxtIgZB5ABsIAUgBkGQHGxrwUE8bcFqNgJAIAggB0H+EiALQUBrEIYBNgJ8IAchBQwNCyADKAIgQQBIBEAgCEEANgJ8QcYfIQUMDQsgAygCKEG07wEtAABBAXFFBEBBiO8BQYzvAUHA7wFB4O8BEBJBlO8BQeDvATYCAEGQ7wFBwO8BNgIAQbTvAUEBOgAACwwLCyAIQQE2AnxBux4hBQwLCyAUQuQAgSEUDAULIAVBgIAIcgsgBBCfAwwHC0GrgAghDAsgDCAEEJ8DIQ0LIAggB0HkACANIAMgBBCeAyIFNgJ8IAdBACAFGyEFDAULQQIhBQwBC0EEIQULAkAgCSAQIAkbIgZB3wBHBEAgBkEtRw0BIAsgFDcDECAIIAdB+RIgC0EQahCGATYCfCAHIQUMBAsgCyAUNwMoIAsgBTYCICAIIAdB8hIgC0EgahCGATYCfCAHIQUMAwsgCyAUNwMIIAsgBTYCACAIIAdB6xIgCxCGATYCfCAHIQUMAgtB7RsLIgUQqAE2AnwLIAtB0ABqJAAgBUUNAQJAIA5FBEAgCCgCfCEJDAELAn8CQAJAIAUtAAAiBkEraw4DAQABAAsgCCgCfAwBCyAFLQABIQYgBUEBaiEFIAgoAnxBAWsLIQkCQCAGQf8BcUEwRw0AA0AgBSwAASIHQTBrQQlLDQEgBUEBaiEFIAlBAWshCSAHQTBGDQALCyAIIAk2AnxBACEGA0AgBiIHQQFqIQYgBSAHaiwAAEEwa0EKSQ0ACyAOIAkgCSAOSRshBgJAIAAgCmogAygCFEGUcUgEf0EtBSASQStHDQEgBiAJayAHakEDQQUgCCgCDC0AAEHDAEYbSQ0BQSsLOgAAIAZBAWshBiAKQQFqIQoLIAYgCU0gASAKTXINAANAIAAgCmpBMDoAACAKQQFqIQogBkEBayIGIAlNDQEgASAKSw0ACwsgCCAJIAEgCmsiByAHIAlLGyIHNgJ8IAAgCmogBSAHEHEaIAgoAnwgCmoLIQogAkEBaiECIAEgCksNAQsLIAFBAWsgCiABIApGGyEKQQALIQYgACAKakEAOgAACyAIQYABaiQAIAYLugEBAn8gAEEORgRAQdEbQeEVIAEoAgAbDwsgAEH//wNxIgJB//8DRyAAQRB1IgNBBUpyRQRAIAEgA0ECdGooAgAiAEEIakGMFiAAGw8LQcYfIQACQAJ/AkACQAJAIANBAWsOBQABBAQCBAsgAkEBSw0DQeCcAQwCCyACQTFLDQJB8JwBDAELIAJBA0sNAUGwnwELIQAgAkUEQCAADwsDQCAALQAAIABBAWohAA0AIAJBAWsiAg0ACwsgAAsOACAAEKEDBEAgABAtCwsnACAAQQBHIABBmIMBR3EgAEGwgwFHcSAAQYzuAUdxIABBpO4BR3EL5AIBA38CQCABLQAADQBB2hUQhgIiAQRAIAEtAAANAQsgAEEMbEHQgwFqEIYCIgEEQCABLQAADQELQecVEIYCIgEEQCABLQAADQELQc8bIQELAkADQCABIAJqLQAAIgRFIARBL0ZyRQRAQRchBCACQQFqIgJBF0cNAQwCCwsgAiEEC0HPGyEDAkACQAJAAkACQCABLQAAIgJBLkYNACABIARqLQAADQAgASEDIAJBwwBHDQELIAMtAAFFDQELIANBzxsQ0AFFDQAgA0GuFRDQAQ0BCyAARQRAQfSCASECIAMtAAFBLkYNAgtBAA8LQYjuASgCACICBEADQCADIAJBCGoQ0AFFDQIgAigCICICDQALC0EkEDQiAgRAIAJB9IIBKQIANwIAIAJBCGoiASADIAQQcRogASAEakEAOgAAIAJBiO4BKAIANgIgQYjuASACNgIACyACQfSCASAAIAJyGyECCyACCyUBAX8jAEEQayICJAAgAiABNgIMIABBxhAgARCkAyACQRBqJAALwR4CD38FfiMAQZABayIDJAAgA0EAQZAB/AsAIANBfzYCTCADIAA2AiwgA0HhADYCICADIAA2AlQgASEEIAIhDyMAQbACayIFJAAgAygCTBoCQAJAIAMoAgRFBEAgAxDJAxogAygCBEUNAQsgBC0AACIBRQ0BAkACQANAAkACQCABQf8BcSIAEH0EQANAIAQiAUEBaiEEIAEtAAEQfQ0ACyADQgAQZANAAn8gAygCBCIAIAMoAmhHBEAgAyAAQQFqNgIEIAAtAAAMAQsgAxAmCxB9DQALIAMoAgQhBCADKQNwQgBZBEAgAyAEQQFrIgQ2AgQLIAQgAygCLGusIAMpA3ggFHx8IRQMAQsCfwJAAkAgAEElRgRAIAQtAAEiAEEqRg0BIABBJUcNAgsgA0IAEGQCQCAELQAAQSVGBEADQAJ/IAMoAgQiACADKAJoRwRAIAMgAEEBajYCBCAALQAADAELIAMQJgsiARB9DQALIARBAWohBAwBCyADKAIEIgAgAygCaEcEQCADIABBAWo2AgQgAC0AACEBDAELIAMQJiEBCyAELQAAIAFHBEAgAykDcEIAWQRAIAMgAygCBEEBazYCBAsgAUEATiANcg0KDAkLIAMoAgQgAygCLGusIAMpA3ggFHx8IRQgBCEBDAMLQQAhByAEQQJqDAELAkAgAEEwayIAQQlLDQAgBC0AAkEkRw0AIwBBEGsiASAPNgIMIAEgDyAAQQJ0akEEayAPIABBAUsbIgBBBGo2AgggACgCACEHIARBA2oMAQsgDygCACEHIA9BBGohDyAEQQFqCyEBQQAhC0EAIQIgAS0AACIEQTBrQf8BcUEJTQRAA0AgAkEKbCAEQf8BcWpBMGshAiABLQABIQQgAUEBaiEBIARBMGtB/wFxQQpJDQALCyAEQf8BcUHtAEcEfyABBUEAIQkgB0EARyELIAEtAAEhBEEAIQogAUEBagsiBkEBaiEBQQMhAAJAAkACQAJAAkACQCAEQf8BcUHBAGsOOgQJBAkEBAQJCQkJAwkJCQkJCQQJCQkJBAkJBAkJCQkJBAkEBAQEBAAEBQkBCQQEBAkJBAIECQkECQIJCyAGQQJqIAEgBi0AAUHoAEYiABshAUF+QX8gABshAAwECyAGQQJqIAEgBi0AAUHsAEYiABshAUEDQQEgABshAAwDC0EBIQAMAgtBAiEADAELQQAhACAGIQELQQEgACABLQAAIgBBL3FBA0YiBBshEAJAIABBIHIgACAEGyIMQdsARg0AAkAgDEHuAEcEQCAMQeMARw0BQQEgAiACQQFMGyECDAILIAcgECAUEKUDDAILIANCABBkA0ACfyADKAIEIgAgAygCaEcEQCADIABBAWo2AgQgAC0AAAwBCyADECYLEH0NAAsgAygCBCEEIAMpA3BCAFkEQCADIARBAWsiBDYCBAsgBCADKAIsa6wgAykDeCAUfHwhFAsgAyACrCISEGQCQCADKAIEIgAgAygCaEcEQCADIABBAWo2AgQMAQsgAxAmQQBIDQQLIAMpA3BCAFkEQCADIAMoAgRBAWs2AgQLQRAhBAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAMQdgAaw4hBgsLAgsLCwsLAQsCBAEBAQsFCwsLCwsDBgsLAgsECwsGAAsgDEHBAGsiAEEGS0EBIAB0QfEAcUVyDQoLIAVBCGogAyAQQQAQqAMgAykDeEIAIAMoAgQgAygCLGusfVENDiAHRQ0JIAUpAxAhEiAFKQMIIRMgEA4DBQYHCQsgDEEQckHzAEYEQCAFQSBqQX9BgQIQmAIgBUEAOgAgIAxB8wBHDQggBUEAOgBBIAVBADoALiAFQQA2ASoMCAsgBUEgaiABLQABIgBB3gBGIgRBgQIQmAIgBUEAOgAgIAFBAmogAUEBaiAEGyEGAn8CQAJAIAFBAkEBIAQbai0AACIBQS1HBEAgAUHdAEYNASAAQd4ARyEIIAYMAwsgBSAAQd4ARyIIOgBODAELIAUgAEHeAEciCDoAfgsgBkEBagshAQNAAkAgAS0AACIAQS1HBEAgAEUNDyAAQd0ARg0KDAELQS0hACABLQABIgZFIAZB3QBGcg0AIAFBAWohDgJAIAYgAUEBay0AACIETQRAIAYhAAwBCwNAIARBAWoiBCAFQSBqaiAIOgAAIAQgDi0AACIASQ0ACwsgDiEBCyAAIAVBIGpqIAg6AAEgAUEBaiEBDAALAAtBCCEEDAILQQohBAwBC0EAIQQLQgAhEkEAIQJBACEGQQAhDiMAQRBrIggkAAJAIARBAUcgBEEkTXFFBEBBiOoBQRw2AgAMAQsDQAJ/IAMoAgQiACADKAJoRwRAIAMgAEEBajYCBCAALQAADAELIAMQJgsiABB9DQALAkACQCAAQStrDgMAAQABC0F/QQAgAEEtRhshDiADKAIEIgAgAygCaEcEQCADIABBAWo2AgQgAC0AACEADAELIAMQJiEACwJAAkACQAJAIARBAEcgBEEQR3EgAEEwR3JFBEACfyADKAIEIgAgAygCaEcEQCADIABBAWo2AgQgAC0AAAwBCyADECYLIgBBX3FB2ABGBEBBECEEAn8gAygCBCIAIAMoAmhHBEAgAyAAQQFqNgIEIAAtAAAMAQsgAxAmCyIAQYH/AGotAABBEEkNAyADKQNwQgBZBEAgAyADKAIEQQFrNgIECyADQgAQZAwGCyAEDQFBCCEEDAILIARBCiAEGyIEIABBgf8Aai0AAEsNACADKQNwQgBZBEAgAyADKAIEQQFrNgIECyADQgAQZEGI6gFBHDYCAAwECyAEQQpHDQAgAEEwayICQQlNBEBBACEAA0AgAEEKbCACaiIAQZmz5swBSQJ/IAMoAgQiAiADKAJoRwRAIAMgAkEBajYCBCACLQAADAELIAMQJgtBMGsiAkEJTXENAAsgAK0hEgsgAkEJSw0CIBJCCn4hEyACrSEVA0ACQAJ/IAMoAgQiACADKAJoRwRAIAMgAEEBajYCBCAALQAADAELIAMQJgsiAEEwayICQQlNIBMgFXwiEkKas+bMmbPmzBlUcUUEQCACQQlNDQEMBQsgEkIKfiITIAKtIhVCf4VYDQELC0EKIQQMAQsgBCAEQQFrcQRAIABBgf8Aai0AACIGIARJBEADQCAGIAIgBGxqIgJBx+PxOEkCfyADKAIEIgAgAygCaEcEQCADIABBAWo2AgQgAC0AAAwBCyADECYLIgBBgf8Aai0AACIGIARJcQ0ACyACrSESCyAEIAZNDQEgBK0hEwNAIBIgE34iFSAGrUL/AYMiFkJ/hVYNAiAVIBZ8IRIgBAJ/IAMoAgQiACADKAJoRwRAIAMgAEEBajYCBCAALQAADAELIAMQJgsiAEGB/wBqLQAAIgZNDQIgCCATQgAgEkIAEEAgCCkDCFANAAsMAQsgBEEXbEEFdkEHcSwAgYEBIREgAEGB/wBqLQAAIgIgBEkEQANAIAIgBiARdCIAciEGIABBgICAwABJAn8gAygCBCIAIAMoAmhHBEAgAyAAQQFqNgIEIAAtAAAMAQsgAxAmCyIAQYH/AGotAAAiAiAESXENAAsgBq0hEgsgAiAETw0AQn8gEa0iE4giFSASVA0AA0AgAq1C/wGDIBIgE4aEIRIgBAJ/IAMoAgQiACADKAJoRwRAIAMgAEEBajYCBCAALQAADAELIAMQJgsiAEGB/wBqLQAAIgJNDQEgEiAVWA0ACwsgBCAAQYH/AGotAABNDQADQCAEAn8gAygCBCIAIAMoAmhHBEAgAyAAQQFqNgIEIAAtAAAMAQsgAxAmC0GB/wBqLQAASw0AC0GI6gFBxAA2AgBBACEOQn8hEgsgAykDcEIAWQRAIAMgAygCBEEBazYCBAsgDkEBckUgEkJ/UXEEQEGI6gFBxAA2AgBCfiESDAELIBIgDqwiE4UgE30hEgsgCEEQaiQAIAMpA3hCACADKAIEIAMoAixrrH1RDQkgB0UgDEHwAEdyRQRAIAcgEj4CAAwFCyAHIBAgEhClAwwECyAHIBMgEhCmAzgCAAwDCyAHIBMgEhCVAjkDAAwCCyAHIBM3AwAgByASNwMIDAELQR8gAkEBaiAMQeMARyIGGyEIAn8gEEEBRgRAIAchAiALBEAgCEECdBA0IgJFDQULIAVCADcCqAJBACEEAkACQANAIAIhAANAAn8gAygCBCICIAMoAmhHBEAgAyACQQFqNgIEIAItAAAMAQsgAxAmCyICIAVqLQAhRQ0CIAUgAjoAGyAFQRxqIAVBG2pBASAFQagCahDSASICQX5GDQAgAkF/RgRAQQAhCQwECyAABEAgACAEQQJ0aiAFKAIcNgIAIARBAWohBAsgC0UgBCAIR3INAAsgACAIQQF0QQFyIghBAnQQ3AEiAg0AC0EAIQkgACEKQQEhCwwIC0EAIQkgACAFQagCagR/IAUoAqgCBUEAC0UNAhoLIAAhCgwGCyALBEBBACEEIAgQNCICRQ0EA0AgAiEAA0ACfyADKAIEIgIgAygCaEcEQCADIAJBAWo2AgQgAi0AAAwBCyADECYLIgIgBWotACFFBEAgACEJQQAMBAsgACAEaiACOgAAIARBAWoiBCAIRw0ACyAAIAhBAXRBAXIiCBDcASICDQALQQAhCiAAIQlBASELDAYLQQAhBCAHBEADQAJ/IAMoAgQiACADKAJoRwRAIAMgAEEBajYCBCAALQAADAELIAMQJgsiACAFai0AIQRAIAQgB2ogADoAACAEQQFqIQQMAQUgByIAIQlBAAwDCwALAAsDQAJ/IAMoAgQiACADKAJoRwRAIAMgAEEBajYCBCAALQAADAELIAMQJgsgBWotACENAAtBACEAQQAhCUEACyEKIAMoAgQhAiADKQNwQgBZBEAgAyACQQFrIgI2AgQLIAMpA3ggAiADKAIsa6x8IhNQIAYgEiATUXJFcg0FIAsEQCAHIAA2AgALIAxB4wBGDQAgCgRAIAogBEECdGpBADYCAAsgCUUEQEEAIQkMAQsgBCAJakEAOgAACyADKAIEIAMoAixrrCADKQN4IBR8fCEUIA0gB0EAR2ohDQsgAUEBaiEEIAEtAAEiAQ0BDAULC0EBIQtBACEJQQAhCgsgDUF/IA0bIQ0LIAtFDQEgCRAtIAoQLQwBC0F/IQ0LIAVBsAJqJAAgA0GQAWokACANC0MAAkAgAEUNAAJAAkACQAJAIAFBAmoOBgABAgIEAwQLIAAgAjwAAA8LIAAgAj0BAA8LIAAgAj4CAA8LIAAgAjcDAAsL2QMCBX8CfiMAQSBrIgQkACABQv///////z+DIQcCQCABQjCIQv//AYMiCKciA0GB/wBrQf0BTQRAIAdCGYinIQICQCAAUCABQv///w+DIgdCgICACFQgB0KAgIAIURtFBEAgAkEBaiECDAELIAAgB0KAgIAIhYRCAFINACACQQFxIAJqIQILQQAgAiACQf///wNLIgUbIQJBgYF/QYCBfyAFGyADaiEDDAELIAAgB4RQIAhC//8BUnJFBEAgB0IZiKdBgICAAnIhAkH/ASEDDAELIANB/oABSwRAQf8BIQMMAQtBgP8AQYH/ACAIUCIFGyIGIANrIgJB8ABKBEBBACECQQAhAwwBCyAEQRBqIAAgByAHQoCAgICAgMAAhCAFGyIHQYABIAJrEEQgBCAAIAcgAhCKASAEKQMIIgBCGYinIQICQCAEKQMAIAMgBkcgBCkDECAEKQMYhEIAUnGthCIHUCAAQv///w+DIgBCgICACFQgAEKAgIAIURtFBEAgAkEBaiECDAELIAcgAEKAgIAIhYRCAFINACACQQFxIAJqIQILIAJBgICABHMgAiACQf///wNLIgMbIQILIARBIGokACABQiCIp0GAgICAeHEgA0EXdHIgAnK+C4kEAgN/AX4CQAJAAn8CQAJAAn8gACgCBCICIAAoAmhHBEAgACACQQFqNgIEIAItAAAMAQsgABAmCyICQStrDgMAAQABCyACQS1GIAFFAn8gACgCBCIDIAAoAmhHBEAgACADQQFqNgIEIAMtAAAMAQsgABAmCyIDQTprIgFBdUtyDQEaIAApA3BCAFMNAiAAIAAoAgRBAWs2AgQMAgsgAkE6ayEBIAIhA0EACyEEIAFBdkkNAAJAIANBMGtBCk8NAEEAIQIDQCADIAJBCmxqAn8gACgCBCICIAAoAmhHBEAgACACQQFqNgIEIAItAAAMAQsgABAmCyEDQTBrIQIgAkHMmbPmAEggA0EwayIBQQlNcQ0ACyACrCEFIAFBCk8NAANAIAOtIAVCCn58IQUCfyAAKAIEIgEgACgCaEcEQCAAIAFBAWo2AgQgAS0AAAwBCyAAECYLIgNBMGsiAUEJTSAFQjB9IgVCro+F18fC66MBU3ENAAsgAUEKTw0AA0ACfyAAKAIEIgEgACgCaEcEQCAAIAFBAWo2AgQgAS0AAAwBCyAAECYLQTBrQQpJDQALCyAAKQNwQgBZBEAgACAAKAIEQQFrNgIEC0IAIAV9IAUgBBshBQwBC0KAgICAgICAgIB/IQUgACkDcEIAUw0AIAAgACgCBEEBazYCBEKAgICAgICAgIB/DwsgBQuJMgMRfwd+AXwjAEEwayIMJAACQAJAIAJBAksNACACQQJ0IgIoAux+IREgAigC4H4hEANAAn8gASgCBCICIAEoAmhHBEAgASACQQFqNgIEIAItAAAMAQsgARAmCyICEH0NAAtBASEIAkACQCACQStrDgMAAQABC0F/QQEgAkEtRhshCCABKAIEIgIgASgCaEcEQCABIAJBAWo2AgQgAi0AACECDAELIAEQJiECCwJAAkAgAkFfcUHJAEYEQANAIAZBB0YNAgJ/IAEoAgQiAiABKAJoRwRAIAEgAkEBajYCBCACLQAADAELIAEQJgshAiAGLACKCCAGQQFqIQYgAkEgckYNAAsLIAZBA0cEQCAGQQhGIgcNASADRSAGQQRJcg0CIAcNAQsgASkDcCIVQgBZBEAgASABKAIEQQFrNgIECyADRSAGQQRJcg0AIBVCAFMhAgNAIAJFBEAgASABKAIEQQFrNgIECyAGQQFrIgZBA0sNAAsLQgAhFSMAQRBrIgckACAIskMAAIB/lLwiA0H///8DcSEIAn8gA0EXdiICQf8BcSIBBEAgAUH/AUcEQCAIrUIZhiEVIAJB/wFxQYD/AGoMAgsgCK1CGYYhFUH//wEMAQtBACAIRQ0AGiAHIAitQgAgCGciAUHRAGoQRCAHKQMIQoCAgICAgMAAhSEVIAcpAwAhFkGJ/wAgAWsLIQEgDCAWNwMAIAwgAa1CMIYgA0Efdq1CP4aEIBWENwMIIAdBEGokACAMKQMIIRUgDCkDACEWDAILAkACQAJAAkACQAJAIAYNAEEAIQYgAkFfcUHOAEcNAANAIAZBAkYNAgJ/IAEoAgQiAiABKAJoRwRAIAEgAkEBajYCBCACLQAADAELIAEQJgshAiAGLADnDSAGQQFqIQYgAkEgckYNAAsLIAYOBAMBAQABCwJAAn8gASgCBCICIAEoAmhHBEAgASACQQFqNgIEIAItAAAMAQsgARAmC0EoRgRAQQEhBgwBC0KAgICAgIDg//8AIRUgASkDcEIAUw0GIAEgASgCBEEBazYCBAwGCwNAAn8gASgCBCICIAEoAmhHBEAgASACQQFqNgIEIAItAAAMAQsgARAmCyICQTBrQQpJIAJBwQBrQRpJciACQd8ARnJFIAJB4QBrQRpPcUUEQCAGQQFqIQYMAQsLQoCAgICAgOD//wAhFSACQSlGDQUgASkDcCIWQgBZBEAgASABKAIEQQFrNgIECwJAIAMEQCAGDQEMBQtBiOoBQRw2AgBCACEWDAILA0AgFkIAWQRAIAEgASgCBEEBazYCBAsgBkEBayIGDQALDAMLIAEpA3BCAFkEQCABIAEoAgRBAWs2AgQLQYjqAUEcNgIACyABQgAQZAwCCwJAIAJBMEcNAAJ/IAEoAgQiByABKAJoRwRAIAEgB0EBajYCBCAHLQAADAELIAEQJgtBX3FB2ABGBEAjAEGwA2siBSQAAn8gASgCBCICIAEoAmhHBEAgASACQQFqNgIEIAItAAAMAQsgARAmCyECAkACfwNAIAJBMEcEQAJAIAJBLkcNBCABKAIEIgIgASgCaEYNACABIAJBAWo2AgQgAi0AAAwDCwUgASgCBCICIAEoAmhHBH9BASEPIAEgAkEBajYCBCACLQAABUEBIQ8gARAmCyECDAELCyABECYLIgJBMEcEQEEBIQsMAQsDQCAYQgF9IRgCfyABKAIEIgIgASgCaEcEQCABIAJBAWo2AgQgAi0AAAwBCyABECYLIgJBMEYNAAtBASELQQEhDwtCgICAgICAwP8/IRYDQAJAIAIhBgJAAkAgAkEwayINQQpJDQAgAkEuRyIHIAJBIHIiBkHhAGtBBUtxDQIgBw0AIAsNAkEBIQsgFSEYDAELIAZB1wBrIA0gAkE5ShshAgJAIBVCB1cEQCACIAlBBHRqIQkMAQsgFUIcWARAIAVBMGogAhBPIAVBIGogGiAWQgBCgICAgICAwP0/EC8gBUEQaiAFKQMwIAUpAzggBSkDICIaIAUpAygiFhAvIAUgBSkDECAFKQMYIBcgGRBKIAUpAwghGSAFKQMAIRcMAQsgAkUgCnINACAFQdAAaiAaIBZCAEKAgICAgICA/z8QLyAFQUBrIAUpA1AgBSkDWCAXIBkQSkEBIQogBSkDSCEZIAUpA0AhFwsgFUIBfCEVQQEhDwsgASgCBCICIAEoAmhHBH8gASACQQFqNgIEIAItAAAFIAEQJgshAgwBCwsCfiAPRQRAAkACQCABKQNwQgBZBEAgASABKAIEIgJBAWs2AgQgA0UNASABIAJBAms2AgQgC0UNAiABIAJBA2s2AgQMAgsgAw0BCyABQgAQZAsgBUHgAGpEAAAAAAAAAAAgCLemEGwgBSkDYCEXIAUpA2gMAQsgFUIHVwRAIBUhFgNAIAlBBHQhCSAWQgF8IhZCCFINAAsLAkACQAJAIAJBX3FB0ABGBEAgASADEKcDIhZCgICAgICAgICAf1INAyADBEAgASkDcEIAWQ0CDAMLQgAhFyABQgAQZEIADAQLQgAhFiABKQNwQgBTDQILIAEgASgCBEEBazYCBAtCACEWCyAJRQRAIAVB8ABqRAAAAAAAAAAAIAi3phBsIAUpA3AhFyAFKQN4DAELIBggFSALG0IChiAWfEIgfSIVQQAgEWutVQRAQYjqAUHEADYCACAFQaABaiAIEE8gBUGQAWogBSkDoAEgBSkDqAFCf0L///////+///8AEC8gBUGAAWogBSkDkAEgBSkDmAFCf0L///////+///8AEC8gBSkDgAEhFyAFKQOIAQwBCyARQeIBa6wgFVcEQCAJQQBOBEADQCAFQaADaiAXIBlCAEKAgICAgIDA/79/EEogFyAZQoCAgICAgID/PxCtAyEBIAVBkANqIBcgGSAFKQOgAyAXIAFBAE4iAhsgBSkDqAMgGSACGxBKIAIgCUEBdCIBciEJIBVCAX0hFSAFKQOYAyEZIAUpA5ADIRcgAUEATg0ACwsCfiAVQSAgEWutfCIWpyIBQQAgAUEAShsgECAWIBCtUxsiAUHxAE8EQCAFQYADaiAIEE8gBSkDiAMhFiAFKQOAAyEaQgAMAQsgBUHgAmpBkAEgAWsQmQIQbCAFQdACaiAIEE8gBSkD0AIhGiAFQfACaiAFKQPgAiAFKQPoAiAFKQPYAiIWEKwDIAUpA/gCIRsgBSkD8AILIRggBUHAAmogCSAJQQFxRSAXIBlCAEIAEIcBQQBHIAFBIElxcSIBchCcASAFQbACaiAaIBYgBSkDwAIgBSkDyAIQLyAFQZACaiAFKQOwAiAFKQO4AiAYIBsQSiAFQaACaiAaIBZCACAXIAEbQgAgGSABGxAvIAVBgAJqIAUpA6ACIAUpA6gCIAUpA5ACIAUpA5gCEEogBUHwAWogBSkDgAIgBSkDiAIgGCAbEIgCIAUpA/ABIhggBSkD+AEiFkIAQgAQhwFFBEBBiOoBQcQANgIACyAFQeABaiAYIBYgFacQqwMgBSkD4AEhFyAFKQPoAQwBC0GI6gFBxAA2AgAgBUHQAWogCBBPIAVBwAFqIAUpA9ABIAUpA9gBQgBCgICAgICAwAAQLyAFQbABaiAFKQPAASAFKQPIAUIAQoCAgICAgMAAEC8gBSkDsAEhFyAFKQO4AQshFSAMIBc3AxAgDCAVNwMYIAVBsANqJAAgDCkDGCEVIAwpAxAhFgwECyABKQNwQgBTDQAgASABKAIEQQFrNgIECyABIQYgAiEHIAghDSADIQhBACEDIwBBkMYAayIEJABBACARayIPIBBrIRQCQAJ/A0ACQCAHQTBHBEAgB0EuRw0EIAYoAgQiASAGKAJoRg0BIAYgAUEBajYCBCABLQAADAMLIAYoAgQiASAGKAJoRwRAIAYgAUEBajYCBCABLQAAIQcFIAYQJiEHC0EBIQMMAQsLIAYQJgsiB0EwRgRAA0AgFUIBfSEVAn8gBigCBCIBIAYoAmhHBEAgBiABQQFqNgIEIAEtAAAMAQsgBhAmCyIHQTBGDQALQQEhAwtBASELCyAEQQA2ApAGAn4CQAJAAkACQCAHQS5GIgEgB0EwayICQQlNcgRAA0ACQCABQQFxBEAgC0UEQCAWIRVBASELDAILIANFIQEMBAsgFkIBfCEWIAlB/A9MBEAgDiAWpyAHQTBGGyEOIARBkAZqIAlBAnRqIgEgCgR/IAcgASgCAEEKbGpBMGsFIAILNgIAQQEhA0EAIApBAWoiASABQQlGIgEbIQogASAJaiEJDAELIAdBMEYNACAEIAQoAoBGQQFyNgKARkHcjwEhDgsCfyAGKAIEIgEgBigCaEcEQCAGIAFBAWo2AgQgAS0AAAwBCyAGECYLIgdBLkYiASAHQTBrIgJBCklyDQALCyAVIBYgCxshFSADRSAHQV9xQcUAR3JFBEACQCAGIAgQpwMiF0KAgICAgICAgIB/Ug0AIAhFDQRCACEXIAYpA3BCAFMNACAGIAYoAgRBAWs2AgQLIBUgF3whFQwECyADRSEBIAdBAEgNAQsgBikDcEIAUw0AIAYgBigCBEEBazYCBAsgAUUNAUGI6gFBHDYCAAsgBkIAEGRCACEVQgAMAQsgBCgCkAYiAUUEQCAERAAAAAAAAAAAIA23phBsIAQpAwghFSAEKQMADAELIBUgFlIgFkIJVXIgEEEeTUEAIAEgEHYbckUEQCAEQTBqIA0QTyAEQSBqIAEQnAEgBEEQaiAEKQMwIAQpAzggBCkDICAEKQMoEC8gBCkDGCEVIAQpAxAMAQsgD0EBdq0gFVMEQEGI6gFBxAA2AgAgBEHgAGogDRBPIARB0ABqIAQpA2AgBCkDaEJ/Qv///////7///wAQLyAEQUBrIAQpA1AgBCkDWEJ/Qv///////7///wAQLyAEKQNIIRUgBCkDQAwBCyARQeIBa6wgFVUEQEGI6gFBxAA2AgAgBEGQAWogDRBPIARBgAFqIAQpA5ABIAQpA5gBQgBCgICAgICAwAAQLyAEQfAAaiAEKQOAASAEKQOIAUIAQoCAgICAgMAAEC8gBCkDeCEVIAQpA3AMAQsgCgRAIApBCEwEQCAEQZAGaiAJQQJ0aiIBKAIAIQYDQCAGQQpsIQYgCkEBaiIKQQlHDQALIAEgBjYCAAsgCUEBaiEJCwJAIA5BCU4gFUIRVXIgFaciCiAOSHINACAVQglRBEAgBEHAAWogDRBPIARBsAFqIAQoApAGEJwBIARBoAFqIAQpA8ABIAQpA8gBIAQpA7ABIAQpA7gBEC8gBCkDqAEhFSAEKQOgAQwCCyAVQghXBEAgBEGQAmogDRBPIARBgAJqIAQoApAGEJwBIARB8AFqIAQpA5ACIAQpA5gCIAQpA4ACIAQpA4gCEC8gBEHgAWpBCCAKa0ECdCgCwH4QTyAEQdABaiAEKQPwASAEKQP4ASAEKQPgASAEKQPoARCqAyAEKQPYASEVIAQpA9ABDAILIBAgCkF9bGpBG2oiAkEeTEEAIAQoApAGIgEgAnYbDQAgBEHgAmogDRBPIARB0AJqIAEQnAEgBEHAAmogBCkD4AIgBCkD6AIgBCkD0AIgBCkD2AIQLyAEQbACaiAKQQJ0QZj+AGooAgAQTyAEQaACaiAEKQPAAiAEKQPIAiAEKQOwAiAEKQO4AhAvIAQpA6gCIRUgBCkDoAIMAQsDQCAEQZAGaiAJIgFBAWsiCUECdGooAgBFDQALQQAhDgJAIApBCW8iAkUEQEEAIQIMAQsgAkEJaiACIBVCAFMbIRICQCABRQRAQQAhAkEAIQEMAQtBgJTr3ANBACASa0ECdEHg/gBqKAIAIgVtIQtBACEHQQAhBkEAIQIDQCAEQZAGaiIPIAZBAnRqIgMgByADKAIAIgkgBW4iCGoiAzYCACACQQFqQf8PcSACIANFIAIgBkZxIgMbIQIgCkEJayAKIAMbIQogCyAJIAUgCGxrbCEHIAZBAWoiBiABRw0ACyAHRQ0AIAFBAnQgD2ogBzYCACABQQFqIQELIAogEmtBCWohCgsDQCAEQZAGaiACQQJ0aiEPIApBJEghBgJAA0AgBkUEQCAKQSRHDQIgDygCAEHR6fkETw0CCyABQf8PaiEJQQAhAwNAIAEhCCADrSAEQZAGaiAJQf8PcSILQQJ0aiIBNQIAQh2GfCIVQoGU69wDVAR/QQAFIBUgFUKAlOvcA4AiFkKAlOvcA359IRUgFqcLIQMgASAVPgIAIAggCCALIAggFVAbIAIgC0YbIAsgCEEBa0H/D3EiB0cbIQEgC0EBayEJIAIgC0cNAAsgDkEdayEOIAghASADRQ0ACyACQQFrQf8PcSICIAFGBEAgBEGQBmoiCCABQf4PakH/D3FBAnRqIgEgASgCACAHQQJ0IAhqKAIAcjYCACAHIQELIApBCWohCiAEQZAGaiACQQJ0aiADNgIADAELCwJAA0AgAUEBakH/D3EhCCAEQZAGaiABQQFrQf8PcUECdGohEgNAQQlBASAKQS1KGyETAkADQCACIQNBACEGAkADQAJAIAMgBmpB/w9xIgIgAUYNACAEQZAGaiACQQJ0aigCACIHIAZBAnQoArB+IgJJDQAgAiAHSQ0CIAZBAWoiBkEERw0BCwsgCkEkRw0AQgAhFUEAIQZCACEWA0AgASADIAZqQf8PcSICRgRAIAFBAWpB/w9xIgFBAnQgBGpBADYCjAYLIARBgAZqIARBkAZqIAJBAnRqKAIAEJwBIARB8AVqIBUgFkIAQoCAgIDlmreOwAAQLyAEQeAFaiAEKQPwBSAEKQP4BSAEKQOABiAEKQOIBhBKIAQpA+gFIRYgBCkD4AUhFSAGQQFqIgZBBEcNAAsgBEHQBWogDRBPIARBwAVqIBUgFiAEKQPQBSAEKQPYBRAvQgAhFSAEKQPIBSEWIAQpA8AFIRcgDkHxAGoiByARayIJQQAgCUEAShsgECAJIBBIIggbIgZB8ABNDQIMBQsgDiATaiEOIAEhAiABIANGDQALQYCU69wDIBN2IQVBfyATdEF/cyELQQAhBiADIQIDQCAEQZAGaiIPIANBAnRqIgcgBiAHKAIAIgkgE3ZqIgc2AgAgAkEBakH/D3EgAiAHRSACIANGcSIHGyECIApBCWsgCiAHGyEKIAkgC3EgBWwhBiADQQFqQf8PcSIDIAFHDQALIAZFDQEgAiAIRwRAIAFBAnQgD2ogBjYCACAIIQEMAwsgEiASKAIAQQFyNgIADAELCwsgBEGQBWpB4QEgBmsQmQIQbCAEQbAFaiAEKQOQBSAEKQOYBSAWEKwDIAQpA7gFIRogBCkDsAUhGSAEQYAFakHxACAGaxCZAhBsIARBoAVqIBcgFiAEKQOABSAEKQOIBRCpAyAEQfAEaiAXIBYgBCkDoAUiFSAEKQOoBSIYEIgCIARB4ARqIBkgGiAEKQPwBCAEKQP4BBBKIAQpA+gEIRYgBCkD4AQhFwsCQCADQQRqQf8PcSICIAFGDQACQCAEQZAGaiACQQJ0aigCACICQf/Jte4BTQRAIAJFIANBBWpB/w9xIAFGcQ0BIARB8ANqIA23RAAAAAAAANA/ohBsIARB4ANqIBUgGCAEKQPwAyAEKQP4AxBKIAQpA+gDIRggBCkD4AMhFQwBCyACQYDKte4BRwRAIARB0ARqIA23RAAAAAAAAOg/ohBsIARBwARqIBUgGCAEKQPQBCAEKQPYBBBKIAQpA8gEIRggBCkDwAQhFQwBCyANtyEcIAEgA0EFakH/D3FGBEAgBEGQBGogHEQAAAAAAADgP6IQbCAEQYAEaiAVIBggBCkDkAQgBCkDmAQQSiAEKQOIBCEYIAQpA4AEIRUMAQsgBEGwBGogHEQAAAAAAADoP6IQbCAEQaAEaiAVIBggBCkDsAQgBCkDuAQQSiAEKQOoBCEYIAQpA6AEIRULIAZB7wBLDQAgBEHQA2ogFSAYQgBCgICAgICAwP8/EKkDIAQpA9ADIAQpA9gDQgBCABCHAQ0AIARBwANqIBUgGEIAQoCAgICAgMD/PxBKIAQpA8gDIRggBCkDwAMhFQsgBEGwA2ogFyAWIBUgGBBKIARBoANqIAQpA7ADIAQpA7gDIBkgGhCIAiAEKQOoAyEWIAQpA6ADIRcCQCAUQQJrIAdB/////wdxTg0AIAQgFkL///////////8AgzcDmAMgBCAXNwOQAyAEQYADaiAXIBZCAEKAgICAgICA/z8QLyAEKQOQAyAEKQOYA0KAgICAgICAuMAAEK0DIQIgBCkDiAMgFiACQQBOIgEbIRYgBCkDgAMgFyABGyEXIAggBiAJRyACQQBIcnEgFSAYQgBCABCHAUEAR3FFIBQgASAOaiIOQe4Aak5xDQBBiOoBQcQANgIACyAEQfACaiAXIBYgDhCrAyAEKQP4AiEVIAQpA/ACCyEWIAwgFTcDKCAMIBY3AyAgBEGQxgBqJAAgDCkDKCEVIAwpAyAhFgwCC0IAIRYMAQtCACEVCyAAIBY3AwAgACAVNwMIIAxBMGokAAvDBgIEfwN+IwBBgAFrIgUkAAJAAkACQCADIARCAEIAEIcBRQ0AAn8gBEL///////8/gyEKAn8gBEIwiKdB//8BcSIHQf//AUcEQEEEIAcNARpBAkEDIAMgCoRQGwwCCyADIAqEUAsLRQ0AIAJCMIinIghB//8BcSIGQf//AUcNAQsgBUEQaiABIAIgAyAEEC8gBSAFKQMQIgIgBSkDGCIBIAIgARCqAyAFKQMIIQIgBSkDACEEDAELIAEgAkL///////////8AgyIKIAMgBEL///////////8AgyIJEIcBQQBMBEAgASAKIAMgCRCHAQRAIAEhBAwCCyAFQfAAaiABIAJCAEIAEC8gBSkDeCECIAUpA3AhBAwBCyAEQjCIp0H//wFxIQcgBgR+IAEFIAVB4ABqIAEgCkIAQoCAgICAgMC7wAAQLyAFKQNoIgpCMIinQfgAayEGIAUpA2ALIQQgB0UEQCAFQdAAaiADIAlCAEKAgICAgIDAu8AAEC8gBSkDWCIJQjCIp0H4AGshByAFKQNQIQMLIAlC////////P4NCgICAgICAwACEIQsgCkL///////8/g0KAgICAgIDAAIQhCiAGIAdKBEADQAJ+IAogC30gAyAEVq19IglCAFkEQCAJIAQgA30iBIRQBEAgBUEgaiABIAJCAEIAEC8gBSkDKCECIAUpAyAhBAwFCyAJQgGGIARCP4iEDAELIApCAYYgBEI/iIQLIQogBEIBhiEEIAZBAWsiBiAHSg0ACyAHIQYLAkAgCiALfSADIARWrX0iCUIAUwRAIAohCQwBCyAJIAQgA30iBIRCAFINACAFQTBqIAEgAkIAQgAQLyAFKQM4IQIgBSkDMCEEDAELIAlC////////P1gEQANAIARCP4ggBkEBayEGIARCAYYhBCAJQgGGhCIJQoCAgICAgMAAVA0ACwsgCEGAgAJxIQcgBkEATARAIAVBQGsgBCAJQv///////z+DIAZB+ABqIAdyrUIwhoRCAEKAgICAgIDAwz8QLyAFKQNIIQIgBSkDQCEEDAELIAlC////////P4MgBiAHcq1CMIaEIQILIAAgBDcDACAAIAI3AwggBUGAAWokAAuIEAIFfw9+IwBB0AJrIgUkACAEQv///////z+DIQsgAkL///////8/gyEKIAIgBIVCgICAgICAgICAf4MhDCAEQjCIp0H//wFxIQcCQAJAIAJCMIinQf//AXEiCEH//wFrQYKAfk8EQCAHQf//AWtBgYB+Sw0BCyABUCACQv///////////wCDIg5CgICAgICAwP//AFQgDkKAgICAgIDA//8AURtFBEAgAkKAgICAgIAghCEMDAILIANQIARC////////////AIMiAkKAgICAgIDA//8AVCACQoCAgICAgMD//wBRG0UEQCAEQoCAgICAgCCEIQwgAyEBDAILIAEgDkKAgICAgIDA//8AhYRQBEAgAyACQoCAgICAgMD//wCFhFAEQEIAIQFCgICAgICA4P//ACEMDAMLIAxCgICAgICAwP//AIQhDEIAIQEMAgsgAyACQoCAgICAgMD//wCFhFAEQEIAIQEMAgsgASAOhFAEQEKAgICAgIDg//8AIAwgAiADhFAbIQxCACEBDAILIAIgA4RQBEAgDEKAgICAgIDA//8AhCEMQgAhAQwCCyAOQv///////z9YBEAgBUHAAmogASAKIAEgCiAKUCIGG3lCwABCACAGG3ynIgZBD2sQREEQIAZrIQYgBSkDyAIhCiAFKQPAAiEBCyACQv///////z9WDQAgBUGwAmogAyALIAMgCyALUCIJG3lCwABCACAJG3ynIglBD2sQRCAGIAlqQRBrIQYgBSkDuAIhCyAFKQOwAiEDCyAFQaACaiALQoCAgICAgMAAhCISQg+GIANCMYiEIgJCAEKAgICAsOa8gvUAIAJ9IgRCABBAIAVBkAJqQgAgBSkDqAJ9QgAgBEIAEEAgBUGAAmogBSkDmAJCAYYgBSkDkAJCP4iEIgRCACACQgAQQCAFQfABaiAEQgBCACAFKQOIAn1CABBAIAVB4AFqIAUpA/gBQgGGIAUpA/ABQj+IhCIEQgAgAkIAEEAgBUHQAWogBEIAQgAgBSkD6AF9QgAQQCAFQcABaiAFKQPYAUIBhiAFKQPQAUI/iIQiBEIAIAJCABBAIAVBsAFqIARCAEIAIAUpA8gBfUIAEEAgBUGgAWogAkIAIAUpA7gBQgGGIAUpA7ABQj+IhEIBfSICQgAQQCAFQZABaiADQg+GQgAgAkIAEEAgBUHwAGogAkIAQgAgBSkDqAEgBSkDoAEiDiAFKQOYAXwiBCAOVK18IARCAVatfH1CABBAIAVBgAFqQgEgBH1CACACQgAQQCAGIAggB2tqIghB//8AaiEGAn4gBSkDcCITQgGGIg0gBSkDiAEiD0IBhiAFKQOAAUI/iIR8IhBC5+wAfSIUQiCIIgIgCkKAgICAgIDAAIQiFUIBhiIWQiCIIgR+IhEgAUIBhiIOQiCIIgsgECAUVq0gDSAQVq0gBSkDeEIBhiATQj+IhCAPQj+IfHx8QgF9IhNCIIgiEH58Ig0gEVStIA0gDSATQv////8PgyITIAFCP4giFyAKQgGGhEL/////D4MiCn58Ig1WrXwgBCAQfnwgBCATfiIRIAogEH58Ig8gEVStQiCGIA9CIIiEfCANIA9CIIZ8Ig8gDVStfCAPIA8gFEL/////D4MiFCAKfiINIAIgC358IhEgDVStIBEgESATIA5C/v///w+DIg1+fCIRVq18fCIPVq18IA8gBCAUfiIYIA0gEH58IgQgAiAKfnwiCiALIBN+fCIQQiCIIAogEFatIAQgGFStIAQgClatfHxCIIaEfCIEIA9UrXwgBCAEIBEgAiANfiIKIAsgFH58IgJCIIggAiAKVK1CIIaEfCIKIBFUrSAKIAogEEIghnwiClatfHwiBFatfCAEIAQgCiACQiCGIgIgDSAUfnwgAlStQn+FIgJWIAIgClJxrXwiBFatfCICQv////////8AWARAIBYgF4QhFSAFQdAAaiAEIAJCgICAgICAwABUIgetIguGIgogAiALhiAEQgGIIAdBP3OtiIQiBCADIBIQQCAIQf7/AGogBiAHG0EBayEGIAFCMYYgBSkDWH0gBSkDUCIBQgBSrX0hC0IAIAF9DAELIAVB4ABqIAJCP4YgBEIBiIQiCiACQgGIIgQgAyASEEAgAUIwhiAFKQNofSAFKQNgIgJCAFKtfSELIAEhDkIAIAJ9CyECIAZB//8BTgRAIAxCgICAgICAwP//AIQhDEIAIQEMAQsCfiAGQQBKBEAgC0IBhiACQj+IhCEBIARC////////P4MgBq1CMIaEIQsgAkIBhgwBCyAGQY9/TARAQgAhAQwCCyAFQUBrIAogBEEBIAZrEIoBIAVBMGogDiAVIAZB8ABqEEQgBUEgaiADIBIgBSkDQCIKIAUpA0giCxBAIAUpAzggBSkDKEIBhiAFKQMgIgFCP4iEfSAFKQMwIgIgAUIBhiIEVK19IQEgAiAEfQshAiAFQRBqIAMgEkIDQgAQQCAFIAMgEkIFQgAQQCALIAogAyAKQgGDIgMgAnwiAlQgASACIANUrXwiASASViABIBJRG618IgMgClStfCIEIAMgAyAEQoCAgICAgMD//wBUIAIgBSkDEFYgASAFKQMYIgRWIAEgBFEbca18IgNWrXwiBCADIARCgICAgICAwP//AFQgAiAFKQMAViABIAUpAwgiAlYgASACURtxrXwiASADVK18IAyEIQwLIAAgATcDACAAIAw3AwggBUHQAmokAAu/AgEBfyMAQdAAayIEJAACQCADQYCAAU4EQCAEQSBqIAEgAkIAQoCAgICAgID//wAQLyAEKQMoIQIgBCkDICEBIANB//8BSQRAIANB//8AayEDDAILIARBEGogASACQgBCgICAgICAgP//ABAvQf3/AiADIANB/f8CTxtB/v8BayEDIAQpAxghAiAEKQMQIQEMAQsgA0GBgH9KDQAgBEFAayABIAJCAEKAgICAgICAORAvIAQpA0ghAiAEKQNAIQEgA0H0gH5LBEAgA0GN/wBqIQMMAQsgBEEwaiABIAJCAEKAgICAgICAORAvQeiBfSADIANB6IF9TRtBmv4BaiEDIAQpAzghAiAEKQMwIQELIAQgASACQgAgA0H//wBqrUIwhhAvIAAgBCkDCDcDCCAAIAQpAwA3AwAgBEHQAGokAAs8ACAAIAE3AwAgACACQv///////z+DIAJCgICAgICAwP//AINCMIinIANCMIinQYCAAnFyrUIwhoQ3AwgLwAECAX8CfkF/IQMCQCAAQgBSIAFC////////////AIMiBEKAgICAgIDA//8AViAEQoCAgICAgMD//wBRGw0AIAJC////////////AIMiBUKAgICAgIDA//8AViAFQoCAgICAgMD//wBScQ0AIAAgBCAFhIRQBEBBAA8LIAEgAoNCAFkEQCABIAJSIAEgAlNxDQEgACABIAKFhEIAUg8LIABCAFIgASACVSABIAJRGw0AIAAgASAChYRCAFIhAwsgAws0AQF/IAFBgICAgARPBEAQjAEACyAAIAEQswIiAjYCBCAAIAI2AgAgACACIAFBAnRqNgIICwoAIABBMGtBCkkLFwAgAEEwa0EKSSAAQSByQeEAa0EGSXILEwAgAEEgciAAIABBwQBrQRpJGwspAQF/IAAoAgAiAQRAIAEQvQNBf0cEQCAAKAIARQ8LIABBADYCAAtBAQspAQF/IAAoAgAiAQRAIAEQwwNBf0cEQCAAKAIARQ8LIABBADYCAAtBAQsUACACIAAgASAAayIAEE0gACACagskAQJ/IwBBEGsiAiQAIAEgABDTASEDIAJBEGokACABIAAgAxsLDAAgAEEAIABBf0cbCywBAX8gAUEASARAEIwBAAsgACABEFMiAjYCBCAAIAI2AgAgACABIAJqNgIIC5EBAQN/AkAgASACEIoCIQQjAEEQayIDJAAgBEH3////B00EQAJAIAQQ1AEEQCAAIAQQUCAAIQUMAQsgA0EIaiAEEJ8BQQFqEJ4BIAMoAgwaIAAgAygCCCIFNgIAIAAgAygCDBBcIAAgBDYCBAsgASACIAUQtAMgA0EAOgAHIANBB2oQXSADQRBqJAAMAQsQWwALCw8AIAAgACgCGCABajYCGAsXACAAIAI2AhwgACABNgIUIAAgATYCGAtUAQJ/AkAgACgCACICRQ0AAn8gAigCGCIDIAIoAhxGBEAgAiABIAIoAgAoAjQRBAAMAQsgAiADQQRqNgIYIAMgATYCACABC0F/Rw0AIABBADYCAAsLMQEBfyAAKAIMIgEgACgCEEYEQCAAIAAoAgAoAigRAAAPCyAAIAFBBGo2AgwgASgCAAsnAQF/IAAoAgwiASAAKAIQRgRAIAAgACgCACgCJBEAAA8LIAEoAgALLgEBfyMAQRBrIgEkACABIAA2AgBB6gsgARByEH9BoPEAKAIAEGEaIAFBEGokAAskAQF/AkAgACgCACICRQ0AIAIgARDCA0F/Rw0AIABBADYCAAsLPQEBfyADBEAgACADELcDIAAoAgQhAyACIAFrIgRFIAEgAkZyRQRAIAMgASAE/AoAAAsgACADIARqNgIECwsJACAAEI8CEC0LPQEBfyAAKAIYIgIgACgCHEYEQCAAIAEQowEgACgCACgCNBEEAA8LIAAgAkEBajYCGCACIAE6AAAgARCjAQsqAQF/IAAoAgwiASAAKAIQRgRAIAAgACgCACgCJBEAAA8LIAEsAAAQowELDwAgACAAKAIAKAIYEQAAC6wCAQJ/IwBBEGsiASQAIAAgACgCAEEMaygCAGooAhgEQCABIAA2AgwgAUEAOgAIIAAgACgCAEEMaygCAGoQ2QEEQCAAIAAoAgBBDGsoAgBqKAJIIgIEQCACEMUDCyABQQE6AAgLAkAgAS0ACEUNACAAIAAoAgBBDGsoAgBqKAIYEMQDQX9HDQAgACAAKAIAQQxrKAIAakEBENUBCwJAIAEoAgwiACAAKAIAQQxrKAIAaigCGEUNACABKAIMIgAgACgCAEEMaygCAGoQ2QFFDQAgASgCDCIAIAAoAgBBDGsoAgBqKAIEQYDAAHFFDQAgASgCDCIAIAAoAgBBDGsoAgBqKAIYEMQDQX9HDQAgASgCDCIAIAAoAgBBDGsoAgBqQQEQ1QELCyABQRBqJAALCQAgABCQAhAtCy0AIABByABqEDogAEE8ahA6IABBMGoQOiAAQSRqEDogAEEYahA6IABBDGoQOgsEAEF/C3wBAn8gACAAKAJIIgFBAWsgAXI2AkggACgCFCAAKAIcRwRAIABBAEEAIAAoAiQRAwAaCyAAQQA2AhwgAEIANwMQIAAoAgAiAUEEcQRAIAAgAUEgcjYCAEF/DwsgACAAKAIsIAAoAjBqIgI2AgggACACNgIEIAFBG3RBH3ULBQAQFwALLQAgAEHMAGoQOiAAQUBrEDogAEE0ahA6IABBKGoQOiAAQRxqEDogAEEQahA6CxIAIABFBEBBAA8LIAAgARCWAgsPACAAIAEgAkE0QTUQ0QMLvAIAAkACQAJAAkACQAJAAkACQAJAAkACQCABQQlrDhIACAkKCAkBAgMECgkKCggJBQYHCyACIAIoAgAiAUEEajYCACAAIAEoAgA2AgAPCyACIAIoAgAiAUEEajYCACAAIAEyAQA3AwAPCyACIAIoAgAiAUEEajYCACAAIAEzAQA3AwAPCyACIAIoAgAiAUEEajYCACAAIAEwAAA3AwAPCyACIAIoAgAiAUEEajYCACAAIAExAAA3AwAPCyACIAIoAgBBB2pBeHEiAUEIajYCACAAIAErAwA5AwAPCyAAIAIgAxEBAAsPCyACIAIoAgAiAUEEajYCACAAIAE0AgA3AwAPCyACIAIoAgAiAUEEajYCACAAIAE1AgA3AwAPCyACIAIoAgBBB2pBeHEiAUEIajYCACAAIAEpAwA3AwALbwEFfyAAKAIAIgMsAABBMGsiAUEJSwRAQQAPCwNAQX8hBCACQcyZs+YATQRAQX8gASACQQpsIgVqIAEgBUH/////B3NLGyEECyAAIANBAWoiBTYCACADLAABIAQhAiAFIQNBMGsiAUEKSQ0ACyACC/oSAhN/An4jAEFAaiIIJAAgCCABNgI8IAhBKWohFyAIQSdqIRggCEEoaiERAkACQAJAAkADQEEAIQcDQCABIQ0gByAOQf////8Hc0oNAiAHIA5qIQ4CQAJAAkACQCABIgctAAAiCwRAA0ACQAJAIAtB/wFxIgFFBEAgByEBDAELIAFBJUcNASAHIQsDQCALLQABQSVHBEAgCyEBDAILIAdBAWohByALLQACIAtBAmoiASELQSVGDQALCyAHIA1rIgcgDkH/////B3MiGUoNCSAABEAgACANIAcQQgsgBw0HIAggATYCPCABQQFqIQdBfyEQAkAgASwAAUEwayIKQQlLDQAgAS0AAkEkRw0AIAFBA2ohB0EBIRIgCiEQCyAIIAc2AjxBACEMAkAgBywAACILQSBrIgFBH0sEQCAHIQoMAQsgByEKQQEgAXQiAUGJ0QRxRQ0AA0AgCCAHQQFqIgo2AjwgASAMciEMIAcsAAEiC0EgayIBQSBPDQEgCiEHQQEgAXQiAUGJ0QRxDQALCwJAIAtBKkYEQAJ/AkAgCiwAAUEwayIBQQlLDQAgCi0AAkEkRw0AAn8gAEUEQCAEIAFBAnRqQQo2AgBBAAwBCyADIAFBA3RqKAIACyEPIApBA2ohAUEBDAELIBINBiAKQQFqIQEgAEUEQCAIIAE2AjxBACESQQAhDwwDCyACIAIoAgAiB0EEajYCACAHKAIAIQ9BAAshEiAIIAE2AjwgD0EATg0BQQAgD2shDyAMQYDAAHIhDAwBCyAIQTxqEM8DIg9BAEgNCiAIKAI8IQELQQAhB0F/IQkCf0EAIAEtAABBLkcNABogAS0AAUEqRgRAAn8CQCABLAACQTBrIgpBCUsNACABLQADQSRHDQAgAUEEaiEBAn8gAEUEQCAEIApBAnRqQQo2AgBBAAwBCyADIApBA3RqKAIACwwBCyASDQYgAUECaiEBQQAgAEUNABogAiACKAIAIgpBBGo2AgAgCigCAAshCSAIIAE2AjwgCUEATgwBCyAIIAFBAWo2AjwgCEE8ahDPAyEJIAgoAjwhAUEBCyEUA0AgByEVQRwhCiABIhMsAAAiB0H7AGtBRkkNCyABQQFqIQEgByAVQTpsakHv8ABqLQAAIgdBAWtB/wFxQQhJDQALIAggATYCPAJAIAdBG0cEQCAHRQ0MIBBBAE4EQCAARQRAIAQgEEECdGogBzYCAAwMCyAIIAMgEEEDdGopAwA3AzAMAgsgAEUNCCAIQTBqIAcgAiAGEM4DDAELIBBBAE4NC0EAIQcgAEUNCAsgAC0AAEEgcQ0LIAxB//97cSILIAwgDEGAwABxGyEMQQAhEEHuCCEWIBEhCgJAAkACfwJAAkACQAJAAkACQAJ/AkACQAJAAkACQAJAAkAgEy0AACIHwCITQVNxIBMgB0EPcUEDRhsgEyAVGyIHQdgAaw4hBBYWFhYWFhYWEBYJBhAQEBYGFhYWFgIFAxYWChYBFhYEAAsCQCAHQcEAaw4HEBYLFhAQEAALIAdB0wBGDQsMFQsgCCkDMCEbQe4IDAULQQAhBwJAAkACQAJAAkACQAJAIBUOCAABAgMEHAUGHAsgCCgCMCAONgIADBsLIAgoAjAgDjYCAAwaCyAIKAIwIA6sNwMADBkLIAgoAjAgDjsBAAwYCyAIKAIwIA46AAAMFwsgCCgCMCAONgIADBYLIAgoAjAgDqw3AwAMFQtBCCAJIAlBCE0bIQkgDEEIciEMQfgAIQcLIBEhASAHQSBxIQsgCCkDMCIbIhpQRQRAA0AgAUEBayIBIBqnQQ9xLQCAdSALcjoAACAaQg9WIBpCBIghGg0ACwsgASENIAxBCHFFIBtQcg0DIAdBBHZB7ghqIRZBAiEQDAMLIBEhASAIKQMwIhsiGlBFBEADQCABQQFrIgEgGqdBB3FBMHI6AAAgGkIHViAaQgOIIRoNAAsLIAEhDSAMQQhxRQ0CIAkgFyABayIBIAEgCUgbIQkMAgsgCCkDMCIbQgBTBEAgCEIAIBt9Ihs3AzBBASEQQe4IDAELIAxBgBBxBEBBASEQQe8IDAELQfAIQe4IIAxBAXEiEBsLIRYgGyAREKYBIQ0LIBQgCUEASHENESAMQf//e3EgDCAUGyEMIBtCAFIgCXJFBEAgESENQQAhCQwOCyAJIBtQIBEgDWtqIgEgASAJSBshCQwNCyAILQAwIQcMCwsgCCgCMCIBQZUcIAEbIg1BAEH/////ByAJIAlB/////wdPGyIHEOABIgEgDWsgByABGyIBIA1qIQogCUEATgRAIAshDCABIQkMDAsgCyEMIAEhCSAKLQAADQ8MCwsgCCkDMCIaUEUNAUEAIQcMCQsgCQRAIAgoAjAMAgtBACEHIABBICAPQQAgDBBFDAILIAhBADYCDCAIIBo+AgggCCAIQQhqIgc2AjBBfyEJIAcLIQtBACEHA0ACQCALKAIAIg1FDQAgCEEEaiANEMwDIg1BAEgNDyANIAkgB2tLDQAgC0EEaiELIAcgDWoiByAJSQ0BCwtBPSEKIAdBAEgNDCAAQSAgDyAHIAwQRSAHRQRAQQAhBwwBC0EAIQogCCgCMCELA0AgCygCACINRQ0BIAhBBGoiCSANEMwDIg0gCmoiCiAHSw0BIAAgCSANEEIgC0EEaiELIAcgCksNAAsLIABBICAPIAcgDEGAwABzEEUgDyAHIAcgD0gbIQcMCAsgFCAJQQBIcQ0JQT0hCiAAIAgrAzAgDyAJIAwgByAFESAAIgdBAE4NBwwKCyAHLQABIQsgB0EBaiEHDAALAAsgAA0JIBJFDQNBASEHA0AgBCAHQQJ0aigCACIABEAgAyAHQQN0aiAAIAIgBhDOA0EBIQ4gB0EBaiIHQQpHDQEMCwsLIAdBCk8EQEEBIQ4MCgsDQCAEIAdBAnRqKAIADQFBASEOIAdBAWoiB0EKRw0ACwwJC0EcIQoMBgsgCCAHOgAnQQEhCSAYIQ0gCyEMCyAJIAogDWsiCyAJIAtKGyIBIBBB/////wdzSg0DQT0hCiAPIAEgEGoiCSAJIA9IGyIHIBlLDQQgAEEgIAcgCSAMEEUgACAWIBAQQiAAQTAgByAJIAxBgIAEcxBFIABBMCABIAtBABBFIAAgDSALEEIgAEEgIAcgCSAMQYDAAHMQRSAIKAI8IQEMAQsLC0EAIQ4MAwtBPSEKC0GI6gEgCjYCAAtBfyEOCyAIQUBrJAAgDgvCAgEEfyMAQdABayIFJAAgBSACNgLMASAFQaABaiICQQBBKPwLACAFIAUoAswBNgLIAQJAQQAgASAFQcgBaiAFQdAAaiACIAMgBBDQA0EASARAQX8hBAwBCyAAKAJMQQBIIAAgACgCACIIQV9xNgIAAn8CQAJAIAAoAjBFBEAgAEHQADYCMCAAQQA2AhwgAEIANwMQIAAoAiwhBiAAIAU2AiwMAQsgACgCEA0BC0F/IAAQ3wENARoLIAAgASAFQcgBaiAFQdAAaiAFQaABaiADIAQQ0AMLIQIgBgRAIABBAEEAIAAoAiQRAwAaIABBADYCMCAAIAY2AiwgAEEANgIcIAAoAhQhASAAQgA3AxAgAkF/IAEbIQILIAAgACgCACIAIAhBIHFyNgIAQX8gAiAAQSBxGyEEDQALIAVB0AFqJAAgBAt/AgF/AX4gAL0iA0I0iKdB/w9xIgJB/w9HBHwgAkUEQCABIABEAAAAAAAAAABhBH9BAAUgAEQAAAAAAADwQ6IgARDSAyEAIAEoAgBBQGoLNgIAIAAPCyABIAJB/gdrNgIAIANC/////////4eAf4NCgICAgICAgPA/hL8FIAALCz4BAX8jAEEQayIBJAAgASAANgIMAn8gAEEETwRAQZ0fIAFBDGoQlwJBAAwBCyAAQQJ0KAKILQsgAUEQaiQACwYAIAEQLQsJACABIAJsEDQLJQECfyAAKAIEIgAQqAFBAWoiARA0IgIEfyACIAAgARBxBUEACwsNACAAKAIEIAAoAgBrCzABAX8jAEEQayIEJAAgACgCACEAIAQgAzoADyABIAIgBEEPaiAAEQMAIARBEGokAAuNAgIBfwF8IwBBEGsiAyQAIANBDmogASACIAAoAgARBQAgAyADLwAOOwEMIwBBEGsiASQAAkAgAy0ADUEBRgRAIwBBEGsiAiQAQazgAS0AAEEBcUUEQEECQYQsQQMQDyEAQazgAUEBOgAAQajgASAANgIACyACIAMtAAw2AgggAkEANgIEQajgASgCAEEAQQAgAkEEaiACQQhqEA4hBCACIAIoAgQ2AgAgAUEIaiIAIAT8AzYCBCAAQfzgATYCACACEJ8CIAJBEGokACAAKAIEIQIgAEEANgIEIAAQtQEMAQsgAUEANgIMIAFB/OABNgIIIAFBCGoQtQFBAiECCyABQRBqJAAgA0EQaiQAIAILVAECfyMAQRBrIgQkACABIAAoAgQiBUEBdWohASAAKAIAIQAgBUEBcQRAIAEoAgAgAGooAgAhAAsgBCADOgAPIAEgAiAEQQ9qIAARBQAgBEEQaiQAC1IBAn8jAEEQayIDJAAgASAAKAIEIgRBAXVqIQEgACgCACEAIARBAXEEQCABKAIAIABqKAIAIQALIAMgAjoADyABIANBD2ogABEBACADQRBqJAALMAEBfyMAQRBrIgQkACAAKAIAIQAgBCADOAIMIAEgAiAEQQxqIAARAwAgBEEQaiQAC40CAgF/AXwjAEEQayIDJAAgA0EIaiABIAIgACgCABEFACADIAMpAgg3AwAjAEEQayIBJAACQCADLQAEQQFGBEAjAEEQayICJABBoOABLQAAQQFxRQRAQQJBxCZBAxAPIQBBoOABQQE6AABBnOABIAA2AgALIAIgAyoCADgCCCACQQA2AgRBnOABKAIAQQBBACACQQRqIAJBCGoQDiEEIAIgAigCBDYCACABQQhqIgAgBPwDNgIEIABB/OABNgIAIAIQnwIgAkEQaiQAIAAoAgQhAiAAQQA2AgQgABC1AQwBCyABQQA2AgwgAUH84AE2AgggAUEIahC1AUECIQILIAFBEGokACADQRBqJAAgAgtUAQJ/IwBBEGsiBCQAIAEgACgCBCIFQQF1aiEBIAAoAgAhACAFQQFxBEAgASgCACAAaigCACEACyAEIAM4AgwgASACIARBDGogABEFACAEQRBqJAALUgECfyMAQRBrIgMkACABIAAoAgQiBEEBdWohASAAKAIAIQAgBEEBcQRAIAEoAgAgAGooAgAhAAsgAyACOAIMIAEgA0EMaiAAEQEAIANBEGokAAsbACAAIAEoAgggBRA7BEAgASACIAMgBBDnAQsLOAAgACABKAIIIAUQOwRAIAEgAiADIAQQ5wEPCyAAKAIIIgAgASACIAMgBCAFIAAoAgAoAhQRCgALkgIBBn8gACABKAIIIAUQOwRAIAEgAiADIAQQ5wEPCyABLQA1IAAoAgwhBiABQQA6ADUgAS0ANCABQQA6ADQgAEEQaiIJIAEgAiADIAQgBRDlASABLQA0IgpyIQggAS0ANSILciEHAkAgBkECSQ0AIAkgBkEDdGohCSAAQRhqIQYDQCABLQA2DQECQCAKQQFxBEAgASgCGEEBRg0DIAAtAAhBAnENAQwDCyALQQFxRQ0AIAAtAAhBAXFFDQILIAFBADsBNCAGIAEgAiADIAQgBRDlASABLQA1IgsgB3JBAXEhByABLQA0IgogCHJBAXEhCCAGQQhqIgYgCUkNAAsLIAEgB0EBcToANSABIAhBAXE6ADQLkgEAIAAgASgCCCAEEDsEQCABIAIgAxDmAQ8LAkAgACABKAIAIAQQO0UNAAJAIAEoAhAgAkcEQCACIAEoAhRHDQELIANBAUcNASABQQE2AiAPCyABIAI2AhQgASADNgIgIAEgASgCKEEBajYCKAJAIAEoAiRBAUcNACABKAIYQQJHDQAgAUEBOgA2CyABQQQ2AiwLC/YBACAAIAEoAgggBBA7BEAgASACIAMQ5gEPCwJAIAAgASgCACAEEDsEQAJAIAEoAhAgAkcEQCACIAEoAhRHDQELIANBAUcNAiABQQE2AiAPCyABIAM2AiACQCABKAIsQQRGDQAgAUEAOwE0IAAoAggiACABIAIgAkEBIAQgACgCACgCFBEKACABLQA1QQFGBEAgAUEDNgIsIAEtADRFDQEMAwsgAUEENgIsCyABIAI2AhQgASABKAIoQQFqNgIoIAEoAiRBAUcNASABKAIYQQJHDQEgAUEBOgA2DwsgACgCCCIAIAEgAiADIAQgACgCACgCGBELAAsLrwQBA38gACABKAIIIAQQOwRAIAEgAiADEOYBDwsCQAJAIAAgASgCACAEEDsEQAJAIAEoAhAgAkcEQCACIAEoAhRHDQELIANBAUcNAyABQQE2AiAPCyABIAM2AiAgASgCLEEERg0BIABBEGoiBSAAKAIMQQN0aiEHQQAhAwNAAkACQCABAn8CQCAFIAdPDQAgAUEAOwE0IAUgASACIAJBASAEEOUBIAEtADYNACABLQA1QQFHDQMgAS0ANEEBRgRAIAEoAhhBAUYNA0EBIQNBASEGIAAtAAhBAnFFDQMMBAtBASEDIAAtAAhBAXENA0EDDAELQQNBBCADGws2AiwgBg0FDAQLIAFBAzYCLAwECyAFQQhqIQUMAAsACyAAKAIMIQUgAEEQaiIGIAEgAiADIAQQtwEgBUECSQ0BIAYgBUEDdGohBiAAQRhqIQUCQCAAKAIIIgBBAnFFBEAgASgCJEEBRw0BCwNAIAEtADYNAyAFIAEgAiADIAQQtwEgBUEIaiIFIAZJDQALDAILIABBAXFFBEADQCABLQA2DQMgASgCJEEBRg0DIAUgASACIAMgBBC3ASAFQQhqIgUgBkkNAAwDCwALA0AgAS0ANg0CIAEoAiRBAUYEQCABKAIYQQFGDQMLIAUgASACIAMgBBC3ASAFQQhqIgUgBkkNAAsMAQsgASACNgIUIAEgASgCKEEBajYCKCABKAIkQQFHDQAgASgCGEECRw0AIAFBAToANgsLjgUBBH8jAEFAaiIEJAACQCABQaDZAUEAEDsEQCACQQA2AgBBASEFDAELAkAgACABIAAtAAhBGHEEf0EBBSABRQ0BIAFB9NYBEFIiA0UNASADLQAIQRhxQQBHCxA7IQYLIAYEQEEBIQUgAigCACIARQ0BIAIgACgCADYCAAwBCwJAIAFFDQAgAUGk1wEQUiIGRQ0BIAIoAgAiAQRAIAIgASgCADYCAAsgBigCCCIDIAAoAggiAUF/c3FBB3EgA0F/cyABcUHgAHFyDQFBASEFIAAoAgwgBigCDEEAEDsNASAAKAIMQZTZAUEAEDsEQCAGKAIMIgBFDQIgAEHU1wEQUkUhBQwCCyAAKAIMIgNFDQBBACEFIANBpNcBEFIiAQRAIAAtAAhBAXFFDQICfyAGKAIMIQBBACECAkADQEEAIABFDQIaIABBpNcBEFIiA0UNASADKAIIIAEoAghBf3NxDQFBASABKAIMIAMoAgxBABA7DQIaIAEtAAhBAXFFDQEgASgCDCIARQ0BIABBpNcBEFIiAQRAIAMoAgwhAAwBCwsgAEGI2AEQUiIARQ0AIAAgAygCDBCpAiECCyACCyEFDAILIANBiNgBEFIiAQRAIAAtAAhBAXFFDQIgASAGKAIMEKkCIQUMAgsgA0HE1gEQUiIBRQ0BIAYoAgwiAEUNASAAQcTWARBSIgBFDQEgAigCACEDIARBCGpBAEE4/AsAIAQgA0EARzoAOyAEQX82AhAgBCABNgIMIAQgADYCBCAEQQE2AjQgACAEQQRqIANBASAAKAIAKAIcEQgAIAQoAhwiAEEBRgRAIAIgBCgCFEEAIAMbNgIACyAAQQFGIQUMAQtBACEFCyAEQUBrJAAgBQtvAQJ/IAAgASgCCEEAEDsEQCABIAIgAxDpAQ8LIAAoAgwhBCAAQRBqIgUgASACIAMQqwICQCAEQQJJDQAgBSAEQQN0aiEEIABBGGohAANAIAAgASACIAMQqwIgAS0ANg0BIABBCGoiACAESQ0ACwsLMgAgACABKAIIQQAQOwRAIAEgAiADEOkBDwsgACgCCCIAIAEgAiADIAAoAgAoAhwRCAALGQAgACABKAIIQQAQOwRAIAEgAiADEOkBCwvIAQECfyMAQdAAayIDJAACQAJ/QQEgACABQQAQOw0AGkEAIAFFDQAaQQAgAUHE1gEQUiIBRQ0AGiACKAIAIgRFDQEgA0EYakEAQTj8CwAgA0EBOgBLIANBfzYCICADIAA2AhwgAyABNgIUIANBATYCRCABIANBFGogBEEBIAEoAgAoAhwRCAAgAygCLCIAQQFGBEAgAiADKAIkNgIACyAAQQFGCyADQdAAaiQADwsgA0GeFjYCCCADQecDNgIEIANBig02AgAQPQALAwAACxEBAX9BBBBTIgBBADYCACAACwkAQaD0ARA5GgslAEGs9AEtAABFBEBBoPQBQdisARCRAUGs9AFBAToAAAtBoPQBCwkAQZD0ARAgGgskAEGc9AEtAABFBEBBkPQBQc4NELABQZz0AUEBOgAAC0GQ9AELCQBBgPQBEDkaCyUAQYz0AS0AAEUEQEGA9AFBhKwBEJEBQYz0AUEBOgAAC0GA9AELCQBB8PMBECAaCyQAQfzzAS0AAEUEQEHw8wFBmRUQsAFB/PMBQQE6AAALQfDzAQsJAEHg8wEQORoLqQIBBH8gAiABIAAoAgBqIgBHBEACQCACKAIEIgQgAigCACIBa0ECdSIGIAAoAgggACgCACICa0ECdU0EQCAGIAAoAgQiAyACayIFQQJ1SwRAIAIgA0cEQCAFBEAgAiABIAX8CgAACyAAKAIEIQMLIAQgASAFaiIBayICRSABIARGckUEQCADIAEgAvwKAAALIAAgAiADajYCBAwCCyAEIAFrIgNFIAEgBEZyRQRAIAIgASAD/AoAAAsgACACIANqNgIEDAELIAAoAgAiAgRAIAAgAjYCBCAAKAIIGiACEC0gAEEANgIIIABCADcCAAsgACAAIAYQtgEQrgMgACgCBCECIAQgAWsiA0UgASAERnJFBEAgAiABIAP8CgAACyAAIAIgA2o2AgQLCwslAEHs8wEtAABFBEBB4PMBQeCrARCRAUHs8wFBAToAAAtB4PMBCwkAQeTeARAgGgsaAEHd8wEtAABFBEBB3fMBQQE6AAALQeTeAQsJAEHQ8wEQORoLJQBB3PMBLQAARQRAQdDzAUG8qwEQkQFB3PMBQQE6AAALQdDzAQsJAEHY3gEQIBoLGgBBzfMBLQAARQRAQc3zAUEBOgAAC0HY3gELGwBBqPwBIQADQCAAQQxrEDkiAEGQ/AFHDQALC1QAQczzAS0AAARAQcjzASgCAA8LQaj8AS0AAEUEQEGo/AFBAToAAAtBkPwBQfjUARApQZz8AUGE1QEQKUHM8wFBAToAAEHI8wFBkPwBNgIAQZD8AQsbAEGI/AEhAANAIABBDGsQICIAQfD7AUcNAAsLFQAgASAAKAIAaiEAQQwQUyAAEIEBC1IAQcTzAS0AAARAQcDzASgCAA8LQYj8AS0AAEUEQEGI/AFBAToAAAtB8PsBQdEVECpB/PsBQc4VECpBxPMBQQE6AABBwPMBQfD7ATYCAEHw+wELGwBB4PsBIQADQCAAQQxrEDkiAEHA+QFHDQALC7ACAEG88wEtAAAEQEG48wEoAgAPC0Hg+wEtAABFBEBB4PsBQQE6AAALQcD5AUHw0AEQKUHM+QFBkNEBEClB2PkBQbTRARApQeT5AUHM0QEQKUHw+QFB5NEBEClB/PkBQfTRARApQYj6AUGI0gEQKUGU+gFBnNIBEClBoPoBQbjSARApQaz6AUHg0gEQKUG4+gFBgNMBEClBxPoBQaTTARApQdD6AUHI0wEQKUHc+gFB2NMBEClB6PoBQejTARApQfT6AUH40wEQKUGA+wFB5NEBEClBjPsBQYjUARApQZj7AUGY1AEQKUGk+wFBqNQBEClBsPsBQbjUARApQbz7AUHI1AEQKUHI+wFB2NQBEClB1PsBQejUARApQbzzAUEBOgAAQbjzAUHA+QE2AgBBwPkBCxsAQbD5ASEAA0AgAEEMaxAgIgBBkPcBRw0ACwuYAgBBtPMBLQAABEBBsPMBKAIADwtBsPkBLQAARQRAQbD5AUEBOgAAC0GQ9wFBmwgQKkGc9wFBkggQKkGo9wFBzQ8QKkG09wFBnA4QKkHA9wFB4QgQKkHM9wFBhxEQKkHY9wFBowgQKkHk9wFBkwkQKkHw9wFB1QwQKkH89wFBxAwQKkGI+AFBzAwQKkGU+AFB3wwQKkGg+AFB6g0QKkGs+AFBlRUQKkG4+AFBhg0QKkHE+AFB9gsQKkHQ+AFB4QgQKkHc+AFB3g0QKkHo+AFBkA4QKkH0+AFB0w8QKkGA+QFByg0QKkGM+QFBngoQKkGY+QFBiwkQKkGk+QFB+BQQKkG08wFBAToAAEGw8wFBkPcBNgIAQZD3AQsbAEGI9wEhAANAIABBDGsQOSIAQeD1AUcNAAsLzAEAQazzAS0AAARAQajzASgCAA8LQYj3AS0AAEUEQEGI9wFBAToAAAtB4PUBQZzOARApQez1AUG4zgEQKUH49QFB1M4BEClBhPYBQfTOARApQZD2AUGczwEQKUGc9gFBwM8BEClBqPYBQdzPARApQbT2AUGA0AEQKUHA9gFBkNABEClBzPYBQaDQARApQdj2AUGw0AEQKUHk9gFBwNABEClB8PYBQdDQARApQfz2AUHg0AEQKUGs8wFBAToAAEGo8wFB4PUBNgIAQeD1AQsbAEHY9QEhAANAIABBDGsQICIAQbD0AUcNAAsLvgEAQaTzAS0AAARAQaDzASgCAA8LQdj1AS0AAEUEQEHY9QFBAToAAAtBsPQBQcwIECpBvPQBQdMIECpByPQBQbEIECpB1PQBQbkIECpB4PQBQagIECpB7PQBQdoIECpB+PQBQcMIECpBhPUBQdoNECpBkPUBQeINECpBnPUBQeoQECpBqPUBQasTECpBtPUBQY8JECpBwPUBQbIPECpBzPUBQcIKECpBpPMBQQE6AABBoPMBQbD0ATYCAEGw9AELDwAgASAAKAIAaiACOgAACwsAIABBpKsBEJEBCwoAIABB7hAQsAELCwAgAEGQqwEQkQELCgAgAEHlEBCwAQsMACAAIAFBEGoQ5AELDAAgACABQQxqEOQBCwcAIAAsAAkLBwAgACwACAsJACAAEMMCEC0LDQAgASAAKAIAai0AAAsJACAAEMQCEC0LFQAgACgCCCIARQRAQQEPCyAAEMwCC44BAQZ/A0ACQCACIANGIAQgCE1yDQBBASEGIAAoAgghByMAQRBrIgUkACAFIAc2AgwgBUEIaiAFQQxqEGNBACACIAMgAmsgAUH07wEgARsQ0gEhChBiIAVBEGokAAJAAkAgCiIFQQJqDgMCAgEACyAFIQYLIAhBAWohCCAGIAlqIQkgAiAGaiECDAELCyAJC0YBAn8gACgCCCECIwBBEGsiASQAIAEgAjYCDCABQQhqIAFBDGoQYxBiIAFBEGokACAAKAIIIgBFBEBBAQ8LIAAQzAJBAUYLiQEBAn8jAEEQayIGJAAgBCACNgIAAn9BAiAGQQxqIgVBACAAKAIIEO4BIgBBAWpBAkkNABpBASAAQQFrIgIgAyAEKAIAa0sNABoDfyACBH8gBS0AACEAIAQgBCgCACIBQQFqNgIAIAEgADoAACACQQFrIQIgBUEBaiEFDAEFQQALCwsgBkEQaiQAC7kGAQ1/IwBBEGsiESQAIAIhCANAAkAgAyAIRgRAIAMhCAwBCyAILQAARQ0AIAhBAWohCAwBCwsgByAFNgIAIAQgAjYCAANAAkACfwJAIAIgA0YgBSAGRnINACARIAEpAgA3AwggACgCCCEJIwBBEGsiECQAIBAgCTYCDCAQQQhqIBBBDGoQYyAIIAJrIQ5BACELIwBBkAhrIgwkACAMIAQoAgAiCTYCDCAFIAxBEGogBRshDwJAAkACQCAJRSAGIAVrQQJ1QYACIAUbIg1FckUEQANAIA5BgwFLIA5BAnYiCiANT3JFBEAgCSEKDAQLIA8gDEEMaiAKIA0gCiANSRsgARCbAyESIAwoAgwhCiASQX9GBEBBACENQX8hCwwDCyANIBJBACAPIAxBEGpHGyIUayENIA8gFEECdGohDyAJIA5qIAprQQAgChshDiALIBJqIQsgCkUNAiAKIQkgDQ0ADAILAAsgCSEKCyAKRQ0BCyANRSAORXINACALIQkDQAJAAkAgDyAKIA4gARDSASILQQJqQQJNBEACQAJAIAtBAWoOAgYAAQsgDEEANgIMDAILIAFBADYCAAwBCyAMIAwoAgwgC2oiCjYCDCAJQQFqIQkgDUEBayINDQELIAkhCwwCCyAPQQRqIQ8gDiALayEOIAkhCyAODQALCyAFBEAgBCAMKAIMNgIACyAMQZAIaiQAEGIgEEEQaiQAAkACQAJAAkAgCyIJQX9GBEADQCAHIAU2AgAgAiAEKAIARg0GQQEhBgJAAkACQCAFIAIgCCACayARQQhqIAAoAggQzQIiAUECag4DBwACAQsgBCACNgIADAQLIAEhBgsgAiAGaiECIAcoAgBBBGohBQwACwALIAcgBygCACAJQQJ0aiIFNgIAIAUgBkYNAyAEKAIAIQIgAyAIRg0GIAUgAkEBIAEgACgCCBDNAkUNAQtBAgwECyAHIAcoAgBBBGoiBTYCACAEIAQoAgBBAWoiAjYCACACIQgDQCADIAhGDQUgCC0AAEUNBiAIQQFqIQgMAAsACyAEIAI2AgBBAQwCCyAEKAIAIQILIAIgA0cLIBFBEGokAA8LIAMhCAwACwALpgUBDH8jAEEQayIPJAAgAiEIA0ACQCADIAhGBEAgAyEIDAELIAgoAgBFDQAgCEEEaiEIDAELCyAHIAU2AgAgBCACNgIAAkADQAJAAkAgAiADRiAFIAZGcgR/IAIFIA8gASkCADcDCEEBIRAgBSEJIAYgBWshCyAAKAIIIQpBACENIwBBEGsiDiQAIA4gCjYCDCAOQQhqIA5BDGoQYyMAQRBrIhEkAAJAIAQoAgAiCkUgCCACa0ECdSISRXINACALQQAgBRshCwNAIBFBDGogCSALQQRJGyAKKAIAEJYCIgxBf0YEQEF/IQ0MAgsgCQR/IAtBA00EQCALIAxJDQMgCSARQQxqIAwQcRoLIAsgDGshCyAJIAxqBUEACyEJIAooAgBFBEBBACEKDAILIAwgDWohDSAKQQRqIQogEkEBayISDQALCyAJBEAgBCAKNgIACyARQRBqJAAQYiAOQRBqJAACQAJAAkACQCANIglBAWoOAgAIAQsgByAFNgIAA0AgAiAEKAIARg0CIAUgAigCACAAKAIIEO4BIgFBf0YNAiAHIAcoAgAgAWoiBTYCACACQQRqIQIMAAsACyAHIAcoAgAgCWoiBTYCACAFIAZGDQEgAyAIRgRAIAQoAgAhAiADIQgMBgsgD0EEaiICQQAgACgCCBDuASIIQX9GDQQgBiAHKAIAayAISQ0GA0AgCARAIAItAAAhBSAHIAcoAgAiCUEBajYCACAJIAU6AAAgCEEBayEIIAJBAWohAgwBCwsgBCAEKAIAQQRqIgI2AgAgAiEIA0AgAyAIRgRAIAMhCAwFCyAIKAIARQ0EIAhBBGohCAwACwALIAQgAjYCAAwDCyAEKAIACyADRyEQDAMLIAcoAgAhBQwBCwtBAiEQCyAPQRBqJAAgEAsJACAAENsCEC0LMwAjAEEQayIAJAAgACAENgIMIAAgAyACazYCCCAAQQxqIABBCGoQtQMoAgAgAEEQaiQACzsAA0AgASACRkUEQCADIQAgBCABLAAAEEwEfyABLQAABSAACzoAACAEQQFqIQQgAUEBaiEBDAELCyABCwsAIAEgAiABEEwbCyoAA0AgASACRkUEQCADIAEtAAA6AAAgA0EBaiEDIAFBAWohAQwBCwsgAQsPACAAIAEgAkGgkAEQpgILHQAgARBMBH9BoJABKAIAIAFBAnRqKAIABSABC8ALDwAgACABIAJBmIQBEKYCCyEAIAEQTAR/QZiEASgCACABQf8BcUECdGooAgAFIAELwAsJACAAENACEC0LOwADQCABIAJGRQRAIAMhACAEIAEoAgAQTAR/IAEoAgAFIAALOgAAIARBAWohBCABQQRqIQEMAQsLIAELDAAgASACIAEQTBvACyoAA0AgASACRkUEQCADIAEsAAA2AgAgA0EEaiEDIAFBAWohAQwBCwsgAQsPACAAIAEgAkGgkAEQpwILHAAgARBMBH9BoJABKAIAIAFBAnRqKAIABSABCwsPACAAIAEgAkGYhAEQpwILHAAgARBMBH9BmIQBKAIAIAFBAnRqKAIABSABCwsQACAABEAgABDHAwsgABAtCzoAA0ACQCACIANGDQAgAigCABBMRQ0AIAIoAgBBAnRBkKIBaigCACABcUUNACACQQRqIQIMAQsLIAILOQADQAJAIAIgA0YNACACKAIAEEwEQCACKAIAQQJ0QZCiAWooAgAgAXENAQsgAkEEaiECDAELCyACC0YAA0AgASACRkUEQEEAIQAgAyABKAIAEEwEfyABKAIAQQJ0QZCiAWooAgAFQQALNgIAIANBBGohAyABQQRqIQEMAQsLIAELIwBBACEAIAIQTAR/IAJBAnRBkKIBaigCACABcUEARwVBAAsLDwAgACAAKAIAKAIEEQIACwkAIAAQ1gIQLQsVAQF/QdQAEFMiAEEAQdQA/AsAIAALFAAgACgCACABaiACLQAAOgAAQQELrgEAAkAgBRBHRQRAIAAgBSkCADcCACAAIAUoAgg2AgggABBeGgwBCyAFKAIAIQQgBSgCBCECIwBBEGsiAyQAAkACQAJAIAIQvQEEQCAAIgEgAhBQDAELIAJB9////wNLDQEgA0EIaiACEJABQQFqEI8BIAMoAgwaIAAgAygCCCIBNgIAIAAgAygCDBBcIAAgAjYCBAsgASAEIAJBAWoQZSADQRBqJAAMAQsQWwALCwsJACAAIAUQ5AELhAMBCH8jAEHgA2siACQAIABB3ANqIgYgAxAnIAYQSCEKIAUQHwRAIAVBABDMASgCACAKQS0QS0YhCwsgAiALIABB3ANqIABB2ANqIABB1ANqIABB0ANqIABBxANqECQiDCAAQbgDahAkIgYgAEGsA2oQJCIHIABBqANqEN8CIABB4wA2AhAgAEEIakEAIABBEGoiAhA2IQgCQAJ/IAUQHyAAKAKoA0oEQCAFEB8hCSAAKAKoAyENIAcQHyAJIA1rQQF0aiAGEB9qIAAoAqgDakEBagwBCyAHEB8gBhAfaiAAKAKoA2pBAmoLIglB5QBJDQAgCCAJQQJ0EDQQPCAIKAIAIgINABA9AAsgAiAAQQRqIAAgAygCBCAFECMgBRAjIAUQH0ECdGogCiALIABB2ANqIAAoAtQDIAAoAtADIAwgBiAHIAAoAqgDEN4CIAEgAiAAKAIEIAAoAgAgAyAEEIUBIAgQNSAHEDkaIAYQORogDBAgGiAAQdwDahAlIABB4ANqJAALvgQBC38jAEGgCGsiACQAIAAgBjcDmAggACAFNwOQCCAAIAU3AwAgACAGNwMIIAAgAEGgB2oiBzYCnAcgB0HAECAAEIYBIQcgAEHjADYCgAQgAEH4A2pBACAAQYAEaiIJEDYhDiAAQeMANgKABCAAQfADakEAIAkQNiEKAkAgB0HkAE8EQCAAQZwHahAuQcAQIABBkAhqEMgBIgdBf0YNASAOIAAoApwHEDwgCiAHQQJ0EDQQPCAKEOQCDQEgCigCACEJCyAAQewDaiIIIAMQJyAIEEgiESAAKAKcByIIIAcgCGogCRBvIAdBAEoEQCAAKAKcBy0AAEEtRiEPCyACIA8gAEHsA2ogAEHoA2ogAEHkA2ogAEHgA2ogAEHUA2oQJCIQIABByANqECQiCCAAQbwDahAkIgsgAEG4A2oQ3wIgAEHjADYCICAAQRhqQQAgAEEgaiICEDYhDAJ/IAAoArgDIg0gB0gEQCALEB8gByANa0EBdGogCBAfaiAAKAK4A2pBAWoMAQsgCxAfIAgQH2ogACgCuANqQQJqCyINQeUATwRAIAwgDUECdBA0EDwgDCgCACICRQ0BCyACIABBFGogAEEQaiADKAIEIAkgCSAHQQJ0aiARIA8gAEHoA2ogACgC5AMgACgC4AMgECAIIAsgACgCuAMQ3gIgASACIAAoAhQgACgCECADIAQQhQEgDBA1IAsQORogCBA5GiAQECAaIABB7ANqECUgChA1IA4QNSAAQaAIaiQADwsQPQALMwECfyABKAIEIAEoAgAiAWsgAksEQEEBIQQgASACai0AACEDCyAAIAQ6AAEgACADOgAAC/wCAQh/IwBBsAFrIgAkACAAQawBaiIGIAMQJyAGEEkhCiAFEB8EQCAFQQAQIi0AACAKQS0QQUH/AXFGIQsLIAIgCyAAQawBaiAAQagBaiAAQacBaiAAQaYBaiAAQZgBahAkIgwgAEGMAWoQJCIGIABBgAFqECQiByAAQfwAahDjAiAAQeMANgIQIABBCGpBACAAQRBqIgIQNiEIAkACfyAFEB8gACgCfEoEQCAFEB8hCSAAKAJ8IQ0gBxAfIAkgDWtBAXRqIAYQH2ogACgCfGpBAWoMAQsgBxAfIAYQH2ogACgCfGpBAmoLIglB5QBJDQAgCCAJEDQQPCAIKAIAIgINABA9AAsgAiAAQQRqIAAgAygCBCAFECMgBRAjIAUQH2ogCiALIABBqAFqIAAsAKcBIAAsAKYBIAwgBiAHIAAoAnwQ4gIgASACIAAoAgQgACgCACADIAQQgAEgCBA1IAcQIBogBhAgGiAMECAaIABBrAFqECUgAEGwAWokAAu1BAELfyMAQcADayIAJAAgACAGNwO4AyAAIAU3A7ADIAAgBTcDACAAIAY3AwggACAAQcACaiIHNgK8AiAHQcAQIAAQhgEhByAAQeMANgLQASAAQcgBakEAIABB0AFqIgkQNiEOIABB4wA2AtABIABBwAFqQQAgCRA2IQoCQCAHQeQATwRAIABBvAJqEC5BwBAgAEGwA2oQyAEiB0F/Rg0BIA4gACgCvAIQPCAKIAcQNBA8IAoQ5AINASAKKAIAIQkLIABBvAFqIgggAxAnIAgQSSIRIAAoArwCIgggByAIaiAJEHkgB0EASgRAIAAoArwCLQAAQS1GIQ8LIAIgDyAAQbwBaiAAQbgBaiAAQbcBaiAAQbYBaiAAQagBahAkIhAgAEGcAWoQJCIIIABBkAFqECQiCyAAQYwBahDjAiAAQeMANgIgIABBGGpBACAAQSBqIgIQNiEMAn8gACgCjAEiDSAHSARAIAsQHyAHIA1rQQF0aiAIEB9qIAAoAowBakEBagwBCyALEB8gCBAfaiAAKAKMAWpBAmoLIg1B5QBPBEAgDCANEDQQPCAMKAIAIgJFDQELIAIgAEEUaiAAQRBqIAMoAgQgCSAHIAlqIBEgDyAAQbgBaiAALAC3ASAALAC2ASAQIAggCyAAKAKMARDiAiABIAIgACgCFCAAKAIQIAMgBBCAASAMEDUgCxAgGiAIECAaIBAQIBogAEG8AWoQJSAKEDUgDhA1IABBwANqJAAPCxA9AAvtAQEDfyAAKAIEIAAoAgAiBGsiAyABSQRAIwBBIGsiBCQAAkAgASADayIDIAAoAgggACgCBCIBa00EQCADIAAoAgQiAWohAwNAIAEgA0YEQCAAIAM2AgQFIAEgAi0AADoAACABQQFqIQEMAQsLDAELIAMgBEEMaiAAIAEgA2ogACgCAGsQtAEgACgCBCAAKAIAayAAEMYBIgUoAggiAWohAwNAIAEgA0cEQCABIAItAAA6AAAgAUEBaiEBDAELCyAFIAM2AgggACAFEO8BIAUQugELIARBIGokAA8LIAEgA0kEQCAAIAEgBGo2AgQLC4EFAQR/IwBBwANrIgAkACAAIAI2ArgDIAAgATYCvAMgAEHkADYCFCAAQRhqIABBIGogAEEUaiIIEDYhCiAAQRBqIgEgBBAnIAEQSCEHIABBADoADyAAQbwDaiACIAMgASAEKAIEIAUgAEEPaiAHIAogCCAAQbADahDqAgRAIwBBEGsiASQAIAYQHxoCQCAGEEcEQCAGKAIAIAFBADYCDCABQQxqEFYgBkEANgIEDAELIAFBADYCCCAGIAFBCGoQViAGQQAQUAsgAUEQaiQAIAAtAA9BAUYEQCAGIAdBLRBLEOoBCyAHQTAQSyEBIAooAgAhAiAAKAIUIgNBBGshBANAAkAgAiAETw0AIAIoAgAgAUcNACACQQRqIQIMAQsLIwBBEGsiBCQAIAYQHyEBIAYQ8QEhBwJAIAIgAxD1ASIIRQ0AIAYQIyAGECMgBhAfQQJ0akEEaiACEL4CRQRAIAggByABa0sEQCAGIAcgASAHayAIaiABIAEQ6AILIAIgAyAGECMgAUECdGoQ5wIgBEEANgIEIARBBGoQViAGIAEgCGoQgwEMAQsgBEEEaiIBIAIgAxCZAyABECMhCCABEB8hAiMAQRBrIgckAAJAIAIgBhDxASIJIAYQHyIDa00EQCACRQ0BIAYQIyIJIANBAnRqIAggAhBlIAYgAiADaiICEIMBIAdBADYCDCAJIAJBAnRqIAdBDGoQVgwBCyAGIAkgAiAJayADaiADIANBACACIAgQrwILIAdBEGokACABEDkaCyAEQRBqJAALIABBvANqIABBuANqECsEQCAFIAUoAgBBAnI2AgALIAAoArwDIABBEGoQJSAKEDUgAEHAA2okAAvRAwEDfyMAQfAEayIAJAAgACACNgLoBCAAIAE2AuwEIABB5AA2AhAgAEHIAWogAEHQAWogAEEQaiIBEDYhByAAQcABaiIIIAQQJyAIEEghCSAAQQA6AL8BAkAgAEHsBGogAiADIAggBCgCBCAFIABBvwFqIAkgByAAQcQBaiAAQeAEahDqAkUNACAAQcsbKAAANgC3ASAAQcQbKQAANwOwASAJIABBsAFqIABBugFqIABBgAFqEG8gAEHjADYCECAAQQhqQQAgARA2IQMgASEEAkAgACgCxAEgBygCAGsiAUGJA04EQCADIAFBAnVBAmoQNBA8IAMoAgBFDQEgAygCACEECyAALQC/AUEBRgRAIARBLToAACAEQQFqIQQLIAcoAgAhAgNAIAAoAsQBIAJNBEACQCAEQQA6AAAgACAGNgIAIABBEGogABCjA0EBRw0AIAMQNQwECwUgBCAAQbABaiAAQYABaiIBIAFBKGogAhD5ASABa0ECdWotAAA6AAAgBEEBaiEEIAJBBGohAgwBCwsQPQALED0ACyAAQewEaiAAQegEahArBEAgBSAFKAIAQQJyNgIACyAAKALsBCAAQcABahAlIAcQNSAAQfAEaiQAC5ABAQJ/IAACfyAAKAIEIgIgACgCCEkEQCACIAEtAAA6AAAgAkEBagwBCyMAQSBrIgMkACADQQxqIAAgACgCBCAAKAIAa0EBahC0ASAAKAIEIAAoAgBrIAAQxgEiAigCCCABLQAAOgAAIAIgAigCCEEBajYCCCAAIAIQ7wEgACgCBCACELoBIANBIGokAAs2AgQLBQBBpCoL0AQBA38jAEGQAWsiACQAIAAgAjYCiAEgACABNgKMASAAQeQANgIUIABBGGogAEEgaiAAQRRqIgcQNiEJIABBEGoiCCAEECcgCBBJIQEgAEEAOgAPIABBjAFqIAIgAyAIIAQoAgQgBSAAQQ9qIAEgCSAHIABBhAFqEPACBEACQCAGLAALQQBIBEAgBigCAEEAOgAAIAZBADYCBAwBCyAGQQA6AAsgBkEAOgAACyAALQAPQQFGBEAgBiABQS0QQRC4AQsgAUEwEEEgCSgCACECIAAoAhQiBEEBayEDQf8BcSEBA0ACQCACIANPDQAgAi0AACABRw0AIAJBAWohAgwBCwsjAEEQayIBJAAgBhAfIQMgBhAoIQgCQCACIAQQigIiB0UNACAGECMgBhAjIAYQH2pBAWogAhC+AkUEQCAHIAggA2tLBEAgBiAIIAMgCGsgB2ogAyADEPQBCyACIAQgBhAjIANqELQDIAFBADoADyABQQ9qEF0gBiADIAdqEIMBDAELIAEgAiAEELgDIAEQIyEIIAEQHyECIwBBEGsiBCQAAkAgAiAGECgiByAGEB8iA2tNBEAgAkUNASAGECMiByADaiAIIAIQTSAGIAIgA2oiAhCDASAEQQA6AA8gAiAHaiAEQQ9qEF0MAQsgBiAHIAIgB2sgA2ogAyADQQAgAiAIELkBCyAEQRBqJAAgARAgGgsgAUEQaiQACyAAQYwBaiAAQYgBahAsBEAgBSAFKAIAQQJyNgIACyAAKAKMASAAQRBqECUgCRA1IABBkAFqJAALxwMBA38jAEGQAmsiACQAIAAgAjYCiAIgACABNgKMAiAAQeQANgIQIABBmAFqIABBoAFqIABBEGoiARA2IQcgAEGQAWoiCCAEECcgCBBJIQkgAEEAOgCPAQJAIABBjAJqIAIgAyAIIAQoAgQgBSAAQY8BaiAJIAcgAEGUAWogAEGEAmoQ8AJFDQAgAEHLGygAADYAhwEgAEHEGykAADcDgAEgCSAAQYABaiAAQYoBaiAAQfYAahB5IABB4wA2AhAgAEEIakEAIAEQNiEDIAEhBAJAIAAoApQBIAcoAgBrIgFB4wBOBEAgAyABQQJqEDQQPCADKAIARQ0BIAMoAgAhBAsgAC0AjwFBAUYEQCAEQS06AAAgBEEBaiEECyAHKAIAIQIDQCAAKAKUASACTQRAAkAgBEEAOgAAIAAgBjYCACAAQRBqIAAQowNBAUcNACADEDUMBAsFIAQgAEH2AGoiASABQQpqIAIQ/QEgAGsgAGotAAo6AAAgBEEBaiEEIAJBAWohAgwBCwsQPQALED0ACyAAQYwCaiAAQYgCahAsBEAgBSAFKAIAQQJyNgIACyAAKAKMAiAAQZABahAlIAcQNSAAQZACaiQACxcAIAAoAgAgAUECdGogAioCADgCAEEBC5EDAQJ/IwBBoANrIgckACAHIAdBoANqIgM2AgwjAEGQAWsiAiQAIAIgAkGEAWo2AhwgAEEIaiACQSBqIgggAkEcaiAEIAUgBhD0AiACQgA3AxAgAiAINgIMIAdBEGoiBSAHKAIMEPUBIQQgACgCCCEGIwBBEGsiACQAIAAgBjYCDCAAQQhqIABBDGoQYyAFIAJBDGogBCACQRBqEJsDIQQQYiAAQRBqJAAgBEF/RgRAED0ACyAHIAUgBEECdGo2AgwgAkGQAWokACAHKAIMIQIjAEEQayIGJAAjAEEgayIAJAAgAEEYaiAFIAIQvwIgAEEQaiAAKAIYIQIgACgCHCEIIwBBEGsiBCQAIAQgAjYCCCAEIAE2AgwDQCACIAhHBEAgBEEMaiACKAIAELsDIAQgAkEEaiICNgIIDAELCyAEQQhqIARBDGoQZiAEQRBqJAAgACAFIAAoAhAQjgE2AgwgACAAKAIUNgIIIAZBCGogAEEMaiAAQQhqEGYgAEEgaiQAIAYoAgwgBkEQaiQAIAMkAAuAAgECfyMAQYABayICJAAgAiACQfQAajYCDCAAQQhqIAJBEGoiAyACQQxqIAQgBSAGEPQCIAIoAgwhBCMAQRBrIgYkACMAQSBrIgAkACAAQRhqIAMgBBC/AiAAQRBqIAAoAhghBCAAKAIcIQgjAEEQayIFJAAgBSAENgIIIAUgATYCDANAIAQgCEcEQCAFQQxqIAQsAAAQvwMgBSAEQQFqIgQ2AggMAQsLIAVBCGogBUEMahBmIAVBEGokACAAIAMgACgCEBCOATYCDCAAIAAoAhQ2AgggBkEIaiAAQQxqIABBCGoQZiAAQSBqJAAgBigCDCAGQRBqJAAgAkGAAWokAAvdDAEBfyMAQTBrIgckACAHIAE2AiwgBEEANgIAIAcgAxAnIAcQSCEIIAcQJQJ/AkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAGQcEAaw45AAEXBBcFFwYHFxcXChcXFxcODxAXFxcTFRcXFxcXFxcAAQIDAxcXARcIFxcJCxcMFw0XCxcXERIUFgsgACAFQRhqIAdBLGogAiAEIAgQ9wIMGAsgACAFQRBqIAdBLGogAiAEIAgQ9gIMFwsgAEEIaiAAKAIIKAIMEQAAIQEgByAAIAcoAiwgAiADIAQgBSABECMgARAjIAEQH0ECdGoQbTYCLAwWCyAHQSxqIAIgBCAIQQIQZyEAAkAgBCgCACIBQQRxIABBAWtBHktyRQRAIAUgADYCDAwBCyAEIAFBBHI2AgALDBULIAdBqKABKQMANwMYIAdBoKABKQMANwMQIAdBmKABKQMANwMIIAdBkKABKQMANwMAIAcgACABIAIgAyAEIAUgByAHQSBqEG02AiwMFAsgB0HIoAEpAwA3AxggB0HAoAEpAwA3AxAgB0G4oAEpAwA3AwggB0GwoAEpAwA3AwAgByAAIAEgAiADIAQgBSAHIAdBIGoQbTYCLAwTCyAHQSxqIAIgBCAIQQIQZyEAAkAgBCgCACIBQQRxIABBF0pyRQRAIAUgADYCCAwBCyAEIAFBBHI2AgALDBILIAdBLGogAiAEIAhBAhBnIQACQCAEKAIAIgFBBHEgAEEBa0ELS3JFBEAgBSAANgIIDAELIAQgAUEEcjYCAAsMEQsgB0EsaiACIAQgCEEDEGchAAJAIAQoAgAiAUEEcSAAQe0CSnJFBEAgBSAANgIcDAELIAQgAUEEcjYCAAsMEAsgB0EsaiACIAQgCEECEGchAAJAIAQoAgAiAUEEcSAAQQFrIgBBC0tyRQRAIAUgADYCEAwBCyAEIAFBBHI2AgALDA8LIAdBLGogAiAEIAhBAhBnIQACQCAEKAIAIgFBBHEgAEE7SnJFBEAgBSAANgIEDAELIAQgAUEEcjYCAAsMDgsgB0EsaiEAIwBBEGsiASQAIAEgAjYCDANAAkAgACABQQxqECsNACAIQQEgABA3EF9FDQAgABA+GgwBCwsgACABQQxqECsEQCAEIAQoAgBBAnI2AgALIAFBEGokAAwNCyAHQSxqIQECQCAAQQhqIAAoAggoAggRAAAiABAfQQAgAEEMahAfa0YEQCAEIAQoAgBBBHI2AgAMAQsgASACIAAgAEEYaiAIIARBABDNASICIABHIAUoAggiAUEMR3JFBEAgBUEANgIIDAELIAIgAGtBDEcgAUELSnJFBEAgBSABQQxqNgIICwsMDAsgB0HQoAFBLPwKAAAgByAAIAEgAiADIAQgBSAHIAdBLGoQbTYCLAwLCyAHQZChASgCADYCECAHQYihASkDADcDCCAHQYChASkDADcDACAHIAAgASACIAMgBCAFIAcgB0EUahBtNgIsDAoLIAdBLGogAiAEIAhBAhBnIQACQCAEKAIAIgFBBHEgAEE8SnJFBEAgBSAANgIADAELIAQgAUEEcjYCAAsMCQsgB0G4oQEpAwA3AxggB0GwoQEpAwA3AxAgB0GooQEpAwA3AwggB0GgoQEpAwA3AwAgByAAIAEgAiADIAQgBSAHIAdBIGoQbTYCLAwICyAHQSxqIAIgBCAIQQEQZyEAAkAgBCgCACIBQQRxIABBBkpyRQRAIAUgADYCGAwBCyAEIAFBBHI2AgALDAcLIAAgASACIAMgBCAFIAAoAgAoAhQRBgAMBwsgAEEIaiAAKAIIKAIYEQAAIQEgByAAIAcoAiwgAiADIAQgBSABECMgARAjIAEQH0ECdGoQbTYCLAwFCyAFQRRqIAdBLGogAiAEIAgQ9QIMBAsgB0EsaiACIAQgCEEEEGchACAELQAAQQRxRQRAIAUgAEHsDms2AhQLDAMLIAZBJUYNAQsgBCAEKAIAQQRyNgIADAELIwBBEGsiACQAIAAgAjYCDAJAIAQCf0EGIAdBLGoiASAAQQxqIgIQKw0AGkEEIAggARA3EJQBQSVHDQAaIAEQPiACECtFDQFBAgsgBCgCAHI2AgALIABBEGokAAsgBygCLAsgB0EwaiQACz0AIAACfyABKAIEIAEoAgAiAWtBAnUgAksEQCAAIAEgAkECdGoqAgA4AgBBAQwBCyAAQQA6AABBAAs6AAQLSAECfyMAQRBrIgYkACAGIAE2AgwgBkEIaiIHIAMQJyAHEEghASAHECUgBUEUaiAGQQxqIAIgBCABEPUCIAYoAgwgBkEQaiQAC0oBAn8jAEEQayIGJAAgBiABNgIMIAZBCGoiByADECcgBxBIIQEgBxAlIAAgBUEQaiAGQQxqIAIgBCABEPYCIAYoAgwgBkEQaiQAC0oBAn8jAEEQayIGJAAgBiABNgIMIAZBCGoiByADECcgBxBIIQEgBxAlIAAgBUEYaiAGQQxqIAIgBCABEPcCIAYoAgwgBkEQaiQACzAAIAAgASACIAMgBCAFIABBCGogACgCCCgCFBEAACIAECMgABAjIAAQH0ECdGoQbQtYAQF/IwBBIGsiBiQAIAZBuKEBKQMANwMYIAZBsKEBKQMANwMQIAZBqKEBKQMANwMIIAZBoKEBKQMANwMAIAAgASACIAMgBCAFIAYgBkEgaiIBEG0gASQAC4ICAQN/IAAoAgQgACgCACIEa0ECdSIDIAFJBEAjAEEgayIEJAACQCABIANrIgMgACgCCCAAKAIEIgFrQQJ1TQRAIAAoAgQiASADQQJ0aiEDA0AgASADRgRAIAAgAzYCBAUgASACKgIAOAIAIAFBBGohAQwBCwsMAQsgBEEMaiAAIAEgACgCAGtBAnUgA2oQtgEgACgCBCAAKAIAa0ECdSAAEIcCIgUoAggiASADQQJ0aiEDA0AgASADRwRAIAEgAioCADgCACABQQRqIQEMAQsLIAUgAzYCCCAAIAUQhQIgBRCBAgsgBEEgaiQADwsgASADSQRAIAAgBCABQQJ0ajYCBAsL9wsBAX8jAEEQayIHJAAgByABNgIMIARBADYCACAHIAMQJyAHEEkhCCAHECUCfwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgBkHBAGsOOQABFwQXBRcGBxcXFwoXFxcXDg8QFxcXExUXFxcXFxcXAAECAwMXFwEXCBcXCQsXDBcNFwsXFxESFBYLIAAgBUEYaiAHQQxqIAIgBCAIEPoCDBgLIAAgBUEQaiAHQQxqIAIgBCAIEPkCDBcLIABBCGogACgCCCgCDBEAACEBIAcgACAHKAIMIAIgAyAEIAUgARAjIAEQIyABEB9qEG42AgwMFgsgB0EMaiACIAQgCEECEGghAAJAIAQoAgAiAUEEcSAAQQFrQR5LckUEQCAFIAA2AgwMAQsgBCABQQRyNgIACwwVCyAHQqXavanC7MuS+QA3AwAgByAAIAEgAiADIAQgBSAHIAdBCGoQbjYCDAwUCyAHQqWytanSrcuS5AA3AwAgByAAIAEgAiADIAQgBSAHIAdBCGoQbjYCDAwTCyAHQQxqIAIgBCAIQQIQaCEAAkAgBCgCACIBQQRxIABBF0pyRQRAIAUgADYCCAwBCyAEIAFBBHI2AgALDBILIAdBDGogAiAEIAhBAhBoIQACQCAEKAIAIgFBBHEgAEEBa0ELS3JFBEAgBSAANgIIDAELIAQgAUEEcjYCAAsMEQsgB0EMaiACIAQgCEEDEGghAAJAIAQoAgAiAUEEcSAAQe0CSnJFBEAgBSAANgIcDAELIAQgAUEEcjYCAAsMEAsgB0EMaiACIAQgCEECEGghAAJAIAQoAgAiAUEEcSAAQQFrIgBBC0tyRQRAIAUgADYCEAwBCyAEIAFBBHI2AgALDA8LIAdBDGogAiAEIAhBAhBoIQACQCAEKAIAIgFBBHEgAEE7SnJFBEAgBSAANgIEDAELIAQgAUEEcjYCAAsMDgsgB0EMaiEAIwBBEGsiASQAIAEgAjYCDANAAkAgACABQQxqECwNACAIQQEgABA4EGBFDQAgABA/GgwBCwsgACABQQxqECwEQCAEIAQoAgBBAnI2AgALIAFBEGokAAwNCyAHQQxqIQECQCAAQQhqIAAoAggoAggRAAAiABAfQQAgAEEMahAfa0YEQCAEIAQoAgBBBHI2AgAMAQsgASACIAAgAEEYaiAIIARBABDPASICIABHIAUoAggiAUEMR3JFBEAgBUEANgIIDAELIAIgAGtBDEcgAUELSnJFBEAgBSABQQxqNgIICwsMDAsgB0H4nwEoAAA2AAcgB0HxnwEpAAA3AwAgByAAIAEgAiADIAQgBSAHIAdBC2oQbjYCDAwLCyAHQYCgAS0AADoABCAHQfyfASgAADYCACAHIAAgASACIAMgBCAFIAcgB0EFahBuNgIMDAoLIAdBDGogAiAEIAhBAhBoIQACQCAEKAIAIgFBBHEgAEE8SnJFBEAgBSAANgIADAELIAQgAUEEcjYCAAsMCQsgB0KlkOmp0snOktMANwMAIAcgACABIAIgAyAEIAUgByAHQQhqEG42AgwMCAsgB0EMaiACIAQgCEEBEGghAAJAIAQoAgAiAUEEcSAAQQZKckUEQCAFIAA2AhgMAQsgBCABQQRyNgIACwwHCyAAIAEgAiADIAQgBSAAKAIAKAIUEQYADAcLIABBCGogACgCCCgCGBEAACEBIAcgACAHKAIMIAIgAyAEIAUgARAjIAEQIyABEB9qEG42AgwMBQsgBUEUaiAHQQxqIAIgBCAIEPgCDAQLIAdBDGogAiAEIAhBBBBoIQAgBC0AAEEEcUUEQCAFIABB7A5rNgIUCwwDCyAGQSVGDQELIAQgBCgCAEEEcjYCAAwBCyMAQRBrIgAkACAAIAI2AgwCQCAEAn9BBiAHQQxqIgEgAEEMaiICECwNABpBBCAIIAEQOBCVAUElRw0AGiABED8gAhAsRQ0BQQILIAQoAgByNgIACyAAQRBqJAALIAcoAgwLIAdBEGokAAtIAQJ/IwBBEGsiBiQAIAYgATYCDCAGQQhqIgcgAxAnIAcQSSEBIAcQJSAFQRRqIAZBDGogAiAEIAEQ+AIgBigCDCAGQRBqJAALSgECfyMAQRBrIgYkACAGIAE2AgwgBkEIaiIHIAMQJyAHEEkhASAHECUgACAFQRBqIAZBDGogAiAEIAEQ+QIgBigCDCAGQRBqJAALSgECfyMAQRBrIgYkACAGIAE2AgwgBkEIaiIHIAMQJyAHEEkhASAHECUgACAFQRhqIAZBDGogAiAEIAEQ+gIgBigCDCAGQRBqJAALLQAgACABIAIgAyAEIAUgAEEIaiAAKAIIKAIUEQAAIgAQIyAAECMgABAfahBuCzsBAX8jAEEQayIGJAAgBkKlkOmp0snOktMANwMIIAAgASACIAMgBCAFIAZBCGogBkEQaiIBEG4gASQAC4MBAQR/IwBBwAFrIgAkACAAIAQ2ArwBIABBoAFqIgUgBSAFQRQQLkHXDSAAQbwBahDKASIHaiIEIAIQaSEGIAAgAhAnIAAQSCAAECUgBSAEIAAQbyABIAAgACAHQQJ0aiIBIAAgBiAFa0ECdGogBCAGRhsgASACIAMQhQEgAEHAAWokAAvRAwEHfwJ/IwBB0AJrIgYkACAGIAU3A8gCIAYgBDcDwAIgBkIlNwO4AiAGQbgCaiIHQQFyQd8VIAIoAgQQyQEhCCAGIAZBkAJqIgk2AowCEC4hAAJ/IAgEQCAGIAIoAgg2AiAgCSAAIAcgBkEgaiAGQcACahCDAwwBCyAGQZACaiAAIAZBuAJqIAZBwAJqEIIDCyEAIAZB4wA2AiAgBkGEAmpBACAGQSBqIgoQNiEJIAZBkAJqIQcCQCAAQR5OBEAQLiEAAn8gCARAIAYgAigCCDYCICAGQYwCaiAAIAZBuAJqIAogBkHAAmoQgQMMAQsgBkGMAmogACAGQbgCaiAGQcACahDIAQsiAEF/Rg0BIAkgBigCjAIQPCAGKAKMAiEHCyAHIAAgB2oiCyACEGkhDCAGQeMANgIgIAZBGGpBACAGQSBqIgcQNiEIAkAgBigCjAIiCiAGQZACakYEQCAHIQAMAQsgAEEDdBA0IgBFDQEgCCAAEDwgBigCjAIhCgsgBkEMaiIHIAIQJyAKIAwgCyAAIAZBFGogBkEQaiAHEP4CIAcQJSABIAAgBigCFCAGKAIQIAIgAxCFASAIEDUgCRA1IAZB0AJqJAAMAQsQPQALC8kDAQd/An8jAEHAAmsiBSQAIAUgBDkDuAIgBUIlNwOwAiAFQbACaiIGQQFyQcYfIAIoAgQQyQEhByAFIAVBkAJqIgg2AowCEC4hAAJ/IAcEQCAFIAIoAgg2AiAgCCAAIAYgBUEgaiAFQbgCahCIAwwBCyAFQZACaiAAIAVBsAJqIAVBuAJqEIcDCyEAIAVB4wA2AiAgBUGEAmpBACAFQSBqIgkQNiEIIAVBkAJqIQYCQCAAQR5OBEAQLiEAAn8gBwRAIAUgAigCCDYCICAFQYwCaiAAIAVBsAJqIAkgBUG4AmoQhgMMAQsgBUGMAmogACAFQbACaiAFQbgCahCFAwsiAEF/Rg0BIAggBSgCjAIQPCAFKAKMAiEGCyAGIAAgBmoiCiACEGkhCyAFQeMANgIgIAVBGGpBACAFQSBqIgYQNiEHAkAgBSgCjAIiCSAFQZACakYEQCAGIQAMAQsgAEEDdBA0IgBFDQEgByAAEDwgBSgCjAIhCQsgBUEMaiIGIAIQJyAJIAsgCiAAIAVBFGogBUEQaiAGEP4CIAYQJSABIAAgBSgCFCAFKAIQIAIgAxCFASAHEDUgCBA1IAVBwAJqJAAMAQsQPQALCxEAIAAgASACIAMgBEEAEKECCxEAIAAgASACIAMgBEEAEKICCxEAIAAgASACIAMgBEEBEKECCxEAIAAgASACIAMgBEEBEKICC8kBAQF/IwBBIGsiBSQAIAUgATYCHAJAIAIoAgRBAXFFBEAgACABIAIgAyAEIAAoAgAoAhgRBwAhAgwBCyAFQRBqIgAgAhAnIAAQmQEhASAAECUCQCAEBEAgACABEHwMAQsgBUEQaiABEHsLIAUgBUEQahBONgIMA0AgBSAFQRBqIgAQdTYCCCAFQQxqIAVBCGoQdgRAIAUoAhwhAiAAEDkaBSAFQRxqIAVBDGoiACgCACgCABC7AyAAEPYBDAELCwsgBUEgaiQAIAILBQBB7CALewEEfyMAQdAAayIAJAAgACAENgJMIABBMGoiBSAFIAVBFBAuQdcNIABBzABqEMoBIgdqIgQgAhBpIQYgACACECcgABBJIAAQJSAFIAQgABB5IAEgACAAIAdqIgEgACAGIAVraiAEIAZGGyABIAIgAxCAASAAQdAAaiQAC8wDAQd/An8jAEGwAWsiBiQAIAYgBTcDqAEgBiAENwOgASAGQiU3A5gBIAZBmAFqIgdBAXJB3xUgAigCBBDJASEIIAYgBkHwAGoiCTYCbBAuIQACfyAIBEAgBiACKAIINgIgIAkgACAHIAZBIGogBkGgAWoQgwMMAQsgBkHwAGogACAGQZgBaiAGQaABahCCAwshACAGQeMANgIgIAZB5ABqQQAgBkEgaiIKEDYhCSAGQfAAaiEHAkAgAEEeTgRAEC4hAAJ/IAgEQCAGIAIoAgg2AiAgBkHsAGogACAGQZgBaiAKIAZBoAFqEIEDDAELIAZB7ABqIAAgBkGYAWogBkGgAWoQyAELIgBBf0YNASAJIAYoAmwQPCAGKAJsIQcLIAcgACAHaiILIAIQaSEMIAZB4wA2AiAgBkEYakEAIAZBIGoiBxA2IQgCQCAGKAJsIgogBkHwAGpGBEAgByEADAELIABBAXQQNCIARQ0BIAggABA8IAYoAmwhCgsgBkEMaiIHIAIQJyAKIAwgCyAAIAZBFGogBkEQaiAHEIQDIAcQJSABIAAgBigCFCAGKAIQIAIgAxCAASAIEDUgCRA1IAZBsAFqJAAMAQsQPQALCwkAIAEgABEAAAvEAwEHfwJ/IwBBoAFrIgUkACAFIAQ5A5gBIAVCJTcDkAEgBUGQAWoiBkEBckHGHyACKAIEEMkBIQcgBSAFQfAAaiIINgJsEC4hAAJ/IAcEQCAFIAIoAgg2AiAgCCAAIAYgBUEgaiAFQZgBahCIAwwBCyAFQfAAaiAAIAVBkAFqIAVBmAFqEIcDCyEAIAVB4wA2AiAgBUHkAGpBACAFQSBqIgkQNiEIIAVB8ABqIQYCQCAAQR5OBEAQLiEAAn8gBwRAIAUgAigCCDYCICAFQewAaiAAIAVBkAFqIAkgBUGYAWoQhgMMAQsgBUHsAGogACAFQZABaiAFQZgBahCFAwsiAEF/Rg0BIAggBSgCbBA8IAUoAmwhBgsgBiAAIAZqIgogAhBpIQsgBUHjADYCICAFQRhqQQAgBUEgaiIGEDYhBwJAIAUoAmwiCSAFQfAAakYEQCAGIQAMAQsgAEEBdBA0IgBFDQEgByAAEDwgBSgCbCEJCyAFQQxqIgYgAhAnIAkgCyAKIAAgBUEUaiAFQRBqIAYQhAMgBhAlIAEgACAFKAIUIAUoAhAgAiADEIABIAcQNSAIEDUgBUGgAWokAAwBCxA9AAsLEQAgACABIAIgAyAEQQAQowILEQAgACABIAIgAyAEQQAQpAILEQAgACABIAIgAyAEQQEQowILoQEBAn8jAEHgAGsiBSQAIAVBDGoiBCABIAIgAygCACAAEQgAQdQAEFMiACAEKQIANwIAIAAgBC0ACDoACCAAQQxqIARBDGoQgQEaIABBGGogBEEYahCBARogAEEkaiAEQSRqEIEBGiAAQTBqIARBMGoQgQEaIABBPGogBEE8ahCBARogAEHIAGogBEHIAGoQgQEaIAQQxwMgBUHgAGokACAACxEAIAAgASACIAMgBEEBEKQCC8kBAQF/IwBBIGsiBSQAIAUgATYCHAJAIAIoAgRBAXFFBEAgACABIAIgAyAEIAAoAgAoAhgRBwAhAgwBCyAFQRBqIgAgAhAnIAAQmwEhASAAECUCQCAEBEAgACABEHwMAQsgBUEQaiABEHsLIAUgBUEQahBONgIMA0AgBSAFQRBqIgAQdzYCCCAFQQxqIAVBCGoQdgRAIAUoAhwhAiAAECAaBSAFQRxqIAVBDGoiACgCACwAABC/AyAAEPgBDAELCwsgBUEgaiQAIAIL5gIBAX8jAEHAAmsiACQAIAAgAjYCuAIgACABNgK8AiAAQcQBahAkIQYgAEEQaiICIAMQJyACEEhB0J8BQeqfASAAQdABahBvIAIQJSAAQbgBahAkIgMgAxAoECEgACADQQAQIiIBNgK0ASAAIAI2AgwgAEEANgIIA0ACQCAAQbwCaiAAQbgCahArDQAgACgCtAEgAxAfIAFqRgRAIAMQHyECIAMgAxAfQQF0ECEgAyADECgQISAAIAIgA0EAECIiAWo2ArQBCyAAQbwCaiICEDdBECABIABBtAFqIABBCGpBACAGIABBEGogAEEMaiAAQdABahCYAQ0AIAIQPhoMAQsLIAMgACgCtAEgAWsQISADECMQLiAAIAU2AgQgAEEEahCNA0EBRwRAIARBBDYCAAsgAEG8AmogAEG4AmoQKwRAIAQgBCgCAEECcjYCAAsgACgCvAIgAxAgGiAGECAaIABBwAJqJAAL4QQCA38BfgJ/IwBB8AJrIgAkACAAIAI2AugCIAAgATYC7AIgAEHcAWogAyAAQfABaiAAQewBaiAAQegBahD7ASAAQdABahAkIgEgARAoECEgACABQQAQIiICNgLMASAAIABBIGo2AhwgAEEANgIYIABBAToAFyAAQcUAOgAWQQAhAwNAAkACQAJAIABB7AJqIABB6AJqECsNACAAKALMASABEB8gAmpGBEAgARAfIQYgASABEB9BAXQQISABIAEQKBAhIAAgBiABQQAQIiICajYCzAELIABB7AJqEDcgAEEXaiAAQRZqIAIgAEHMAWogACgC7AEgACgC6AEgAEHcAWogAEEgaiAAQRxqIABBGGogAEHwAWoQ+gENACADDQFBACEDIAAoAswBIAJrIgdBAEwNAgJAAkAgAi0AACIGQStrIggOAwEAAQALIAZBLkYNAkEBIQMgBkEwa0H/AXFBCkkNAwwBCyAHQQFGDQICQCAIDgMAAwADCyACLQABIgZBLkYNAUEBIQMgBkEwa0H/AXFBCU0NAgsCQCAAQdwBahAfRQ0AIAAtABdBAXFFDQAgACgCHCIDIABBIGprQZ8BSg0AIAAgA0EEajYCHCADIAAoAhg2AgALIAAgAiAAKALMASAEEI4DIAApAwAhCSAFIAApAwg3AwggBSAJNwMAIABB3AFqIABBIGogACgCHCAEEEMgAEHsAmogAEHoAmoQKwRAIAQgBCgCAEECcjYCAAsgACgC7AIgARAgGiAAQdwBahAgGiAAQfACaiQADAMLQQEhAwsgAEHsAmoQPhoMAAsACwvKBAEDfwJ/IwBB4AJrIgAkACAAIAI2AtgCIAAgATYC3AIgAEHMAWogAyAAQeABaiAAQdwBaiAAQdgBahD7ASAAQcABahAkIgEgARAoECEgACABQQAQIiICNgK8ASAAIABBEGo2AgwgAEEANgIIIABBAToAByAAQcUAOgAGQQAhAwNAAkACQAJAIABB3AJqIABB2AJqECsNACAAKAK8ASABEB8gAmpGBEAgARAfIQYgASABEB9BAXQQISABIAEQKBAhIAAgBiABQQAQIiICajYCvAELIABB3AJqEDcgAEEHaiAAQQZqIAIgAEG8AWogACgC3AEgACgC2AEgAEHMAWogAEEQaiAAQQxqIABBCGogAEHgAWoQ+gENACADDQFBACEDIAAoArwBIAJrIgdBAEwNAgJAAkAgAi0AACIGQStrIggOAwEAAQALIAZBLkYNAkEBIQMgBkEwa0H/AXFBCkkNAwwBCyAHQQFGDQICQCAIDgMAAwADCyACLQABIgZBLkYNAUEBIQMgBkEwa0H/AXFBCU0NAgsCQCAAQcwBahAfRQ0AIAAtAAdBAXFFDQAgACgCDCIDIABBEGprQZ8BSg0AIAAgA0EEajYCDCADIAAoAgg2AgALIAUgAiAAKAK8ASAEEI8DOQMAIABBzAFqIABBEGogACgCDCAEEEMgAEHcAmogAEHYAmoQKwRAIAQgBCgCAEECcjYCAAsgACgC3AIgARAgGiAAQcwBahAgGiAAQeACaiQADAMLQQEhAwsgAEHcAmoQPhoMAAsACwvKBAEDfwJ/IwBB4AJrIgAkACAAIAI2AtgCIAAgATYC3AIgAEHMAWogAyAAQeABaiAAQdwBaiAAQdgBahD7ASAAQcABahAkIgEgARAoECEgACABQQAQIiICNgK8ASAAIABBEGo2AgwgAEEANgIIIABBAToAByAAQcUAOgAGQQAhAwNAAkACQAJAIABB3AJqIABB2AJqECsNACAAKAK8ASABEB8gAmpGBEAgARAfIQYgASABEB9BAXQQISABIAEQKBAhIAAgBiABQQAQIiICajYCvAELIABB3AJqEDcgAEEHaiAAQQZqIAIgAEG8AWogACgC3AEgACgC2AEgAEHMAWogAEEQaiAAQQxqIABBCGogAEHgAWoQ+gENACADDQFBACEDIAAoArwBIAJrIgdBAEwNAgJAAkAgAi0AACIGQStrIggOAwEAAQALIAZBLkYNAkEBIQMgBkEwa0H/AXFBCkkNAwwBCyAHQQFGDQICQCAIDgMAAwADCyACLQABIgZBLkYNAUEBIQMgBkEwa0H/AXFBCU0NAgsCQCAAQcwBahAfRQ0AIAAtAAdBAXFFDQAgACgCDCIDIABBEGprQZ8BSg0AIAAgA0EEajYCDCADIAAoAgg2AgALIAUgAiAAKAK8ASAEEJEDOAIAIABBzAFqIABBEGogACgCDCAEEEMgAEHcAmogAEHYAmoQKwRAIAQgBCgCAEECcjYCAAsgACgC3AIgARAgGiAAQcwBahAgGiAAQeACaiQADAMLQQEhAwsgAEHcAmoQPhoMAAsACwuWAwECfyMAQdACayIAJAAgACACNgLIAiAAIAE2AswCIAMQaiEGIAMgAEHQAWoQrgEhByAAQcQBaiADIABBxAJqEK0BIABBuAFqECQiASABECgQISAAIAFBABAiIgI2ArQBIAAgAEEQajYCDCAAQQA2AggDQAJAIABBzAJqIABByAJqECsNACAAKAK0ASABEB8gAmpGBEAgARAfIQMgASABEB9BAXQQISABIAEQKBAhIAAgAyABQQAQIiICajYCtAELIABBzAJqIgMQNyAGIAIgAEG0AWogAEEIaiAAKALEAiAAQcQBaiAAQRBqIABBDGogBxCYAQ0AIAMQPhoMAQsLAkAgAEHEAWoQH0UNACAAKAIMIgMgAEEQamtBnwFKDQAgACADQQRqNgIMIAMgACgCCDYCAAsgBSACIAAoArQBIAQgBhCSAzcDACAAQcQBaiAAQRBqIAAoAgwgBBBDIABBzAJqIABByAJqECsEQCAEIAQoAgBBAnI2AgALIAAoAswCIAEQIBogAEHEAWoQIBogAEHQAmokAAuWAwECfyMAQdACayIAJAAgACACNgLIAiAAIAE2AswCIAMQaiEGIAMgAEHQAWoQrgEhByAAQcQBaiADIABBxAJqEK0BIABBuAFqECQiASABECgQISAAIAFBABAiIgI2ArQBIAAgAEEQajYCDCAAQQA2AggDQAJAIABBzAJqIABByAJqECsNACAAKAK0ASABEB8gAmpGBEAgARAfIQMgASABEB9BAXQQISABIAEQKBAhIAAgAyABQQAQIiICajYCtAELIABBzAJqIgMQNyAGIAIgAEG0AWogAEEIaiAAKALEAiAAQcQBaiAAQRBqIABBDGogBxCYAQ0AIAMQPhoMAQsLAkAgAEHEAWoQH0UNACAAKAIMIgMgAEEQamtBnwFKDQAgACADQQRqNgIMIAMgACgCCDYCAAsgBSACIAAoArQBIAQgBhCVAzsBACAAQcQBaiAAQRBqIAAoAgwgBBBDIABBzAJqIABByAJqECsEQCAEIAQoAgBBAnI2AgALIAAoAswCIAEQIBogAEHEAWoQIBogAEHQAmokAAuWAwECfyMAQdACayIAJAAgACACNgLIAiAAIAE2AswCIAMQaiEGIAMgAEHQAWoQrgEhByAAQcQBaiADIABBxAJqEK0BIABBuAFqECQiASABECgQISAAIAFBABAiIgI2ArQBIAAgAEEQajYCDCAAQQA2AggDQAJAIABBzAJqIABByAJqECsNACAAKAK0ASABEB8gAmpGBEAgARAfIQMgASABEB9BAXQQISABIAEQKBAhIAAgAyABQQAQIiICajYCtAELIABBzAJqIgMQNyAGIAIgAEG0AWogAEEIaiAAKALEAiAAQcQBaiAAQRBqIABBDGogBxCYAQ0AIAMQPhoMAQsLAkAgAEHEAWoQH0UNACAAKAIMIgMgAEEQamtBnwFKDQAgACADQQRqNgIMIAMgACgCCDYCAAsgBSACIAAoArQBIAQgBhCWAzcDACAAQcQBaiAAQRBqIAAoAgwgBBBDIABBzAJqIABByAJqECsEQCAEIAQoAgBBAnI2AgALIAAoAswCIAEQIBogAEHEAWoQIBogAEHQAmokAAuWAwECfyMAQdACayIAJAAgACACNgLIAiAAIAE2AswCIAMQaiEGIAMgAEHQAWoQrgEhByAAQcQBaiADIABBxAJqEK0BIABBuAFqECQiASABECgQISAAIAFBABAiIgI2ArQBIAAgAEEQajYCDCAAQQA2AggDQAJAIABBzAJqIABByAJqECsNACAAKAK0ASABEB8gAmpGBEAgARAfIQMgASABEB9BAXQQISABIAEQKBAhIAAgAyABQQAQIiICajYCtAELIABBzAJqIgMQNyAGIAIgAEG0AWogAEEIaiAAKALEAiAAQcQBaiAAQRBqIABBDGogBxCYAQ0AIAMQPhoMAQsLAkAgAEHEAWoQH0UNACAAKAIMIgMgAEEQamtBnwFKDQAgACADQQRqNgIMIAMgACgCCDYCAAsgBSACIAAoArQBIAQgBhCXAzYCACAAQcQBaiAAQRBqIAAoAgwgBBBDIABBzAJqIABByAJqECsEQCAEIAQoAgBBAnI2AgALIAAoAswCIAEQIBogAEHEAWoQIBogAEHQAmokAAvqAQEBfyMAQSBrIgYkACAGIAE2AhwCQCADKAIEQQFxRQRAIAZBfzYCACAAIAEgAiADIAQgBiAAKAIAKAIQEQYAIQECQAJAAkAgBigCAA4CAAECCyAFQQA6AAAMAwsgBUEBOgAADAILIAVBAToAACAEQQQ2AgAMAQsgBiADECcgBhBIIQEgBhAlIAYgAxAnIAYQmQEhACAGECUgBiAAEHwgBkEMciAAEHsgBSAGQRxqIAIgBiAGQRhqIgMgASAEQQEQzQEgBkY6AAAgBigCHCEBA0AgA0EMaxA5IgMgBkcNAAsLIAZBIGokACABC+YCAQF/IwBBgAJrIgAkACAAIAI2AvgBIAAgATYC/AEgAEHEAWoQJCEGIABBEGoiAiADECcgAhBJQdCfAUHqnwEgAEHQAWoQeSACECUgAEG4AWoQJCIDIAMQKBAhIAAgA0EAECIiATYCtAEgACACNgIMIABBADYCCANAAkAgAEH8AWogAEH4AWoQLA0AIAAoArQBIAMQHyABakYEQCADEB8hAiADIAMQH0EBdBAhIAMgAxAoECEgACACIANBABAiIgFqNgK0AQsgAEH8AWoiAhA4QRAgASAAQbQBaiAAQQhqQQAgBiAAQRBqIABBDGogAEHQAWoQmgENACACED8aDAELCyADIAAoArQBIAFrECEgAxAjEC4gACAFNgIEIABBBGoQjQNBAUcEQCAEQQQ2AgALIABB/AFqIABB+AFqECwEQCAEIAQoAgBBAnI2AgALIAAoAvwBIAMQIBogBhAgGiAAQYACaiQAC+EEAgN/AX4CfyMAQZACayIAJAAgACACNgKIAiAAIAE2AowCIABB0AFqIAMgAEHgAWogAEHfAWogAEHeAWoQ/wEgAEHEAWoQJCIBIAEQKBAhIAAgAUEAECIiAjYCwAEgACAAQSBqNgIcIABBADYCGCAAQQE6ABcgAEHFADoAFkEAIQMDQAJAAkACQCAAQYwCaiAAQYgCahAsDQAgACgCwAEgARAfIAJqRgRAIAEQHyEGIAEgARAfQQF0ECEgASABECgQISAAIAYgAUEAECIiAmo2AsABCyAAQYwCahA4IABBF2ogAEEWaiACIABBwAFqIAAsAN8BIAAsAN4BIABB0AFqIABBIGogAEEcaiAAQRhqIABB4AFqEP4BDQAgAw0BQQAhAyAAKALAASACayIHQQBMDQICQAJAIAItAAAiBkErayIIDgMBAAEACyAGQS5GDQJBASEDIAZBMGtB/wFxQQpJDQMMAQsgB0EBRg0CAkAgCA4DAAMAAwsgAi0AASIGQS5GDQFBASEDIAZBMGtB/wFxQQlNDQILAkAgAEHQAWoQH0UNACAALQAXQQFxRQ0AIAAoAhwiAyAAQSBqa0GfAUoNACAAIANBBGo2AhwgAyAAKAIYNgIACyAAIAIgACgCwAEgBBCOAyAAKQMAIQkgBSAAKQMINwMIIAUgCTcDACAAQdABaiAAQSBqIAAoAhwgBBBDIABBjAJqIABBiAJqECwEQCAEIAQoAgBBAnI2AgALIAAoAowCIAEQIBogAEHQAWoQIBogAEGQAmokAAwDC0EBIQMLIABBjAJqED8aDAALAAsLygQBA38CfyMAQYACayIAJAAgACACNgL4ASAAIAE2AvwBIABBwAFqIAMgAEHQAWogAEHPAWogAEHOAWoQ/wEgAEG0AWoQJCIBIAEQKBAhIAAgAUEAECIiAjYCsAEgACAAQRBqNgIMIABBADYCCCAAQQE6AAcgAEHFADoABkEAIQMDQAJAAkACQCAAQfwBaiAAQfgBahAsDQAgACgCsAEgARAfIAJqRgRAIAEQHyEGIAEgARAfQQF0ECEgASABECgQISAAIAYgAUEAECIiAmo2ArABCyAAQfwBahA4IABBB2ogAEEGaiACIABBsAFqIAAsAM8BIAAsAM4BIABBwAFqIABBEGogAEEMaiAAQQhqIABB0AFqEP4BDQAgAw0BQQAhAyAAKAKwASACayIHQQBMDQICQAJAIAItAAAiBkErayIIDgMBAAEACyAGQS5GDQJBASEDIAZBMGtB/wFxQQpJDQMMAQsgB0EBRg0CAkAgCA4DAAMAAwsgAi0AASIGQS5GDQFBASEDIAZBMGtB/wFxQQlNDQILAkAgAEHAAWoQH0UNACAALQAHQQFxRQ0AIAAoAgwiAyAAQRBqa0GfAUoNACAAIANBBGo2AgwgAyAAKAIINgIACyAFIAIgACgCsAEgBBCPAzkDACAAQcABaiAAQRBqIAAoAgwgBBBDIABB/AFqIABB+AFqECwEQCAEIAQoAgBBAnI2AgALIAAoAvwBIAEQIBogAEHAAWoQIBogAEGAAmokAAwDC0EBIQMLIABB/AFqED8aDAALAAsLygQBA38CfyMAQYACayIAJAAgACACNgL4ASAAIAE2AvwBIABBwAFqIAMgAEHQAWogAEHPAWogAEHOAWoQ/wEgAEG0AWoQJCIBIAEQKBAhIAAgAUEAECIiAjYCsAEgACAAQRBqNgIMIABBADYCCCAAQQE6AAcgAEHFADoABkEAIQMDQAJAAkACQCAAQfwBaiAAQfgBahAsDQAgACgCsAEgARAfIAJqRgRAIAEQHyEGIAEgARAfQQF0ECEgASABECgQISAAIAYgAUEAECIiAmo2ArABCyAAQfwBahA4IABBB2ogAEEGaiACIABBsAFqIAAsAM8BIAAsAM4BIABBwAFqIABBEGogAEEMaiAAQQhqIABB0AFqEP4BDQAgAw0BQQAhAyAAKAKwASACayIHQQBMDQICQAJAIAItAAAiBkErayIIDgMBAAEACyAGQS5GDQJBASEDIAZBMGtB/wFxQQpJDQMMAQsgB0EBRg0CAkAgCA4DAAMAAwsgAi0AASIGQS5GDQFBASEDIAZBMGtB/wFxQQlNDQILAkAgAEHAAWoQH0UNACAALQAHQQFxRQ0AIAAoAgwiAyAAQRBqa0GfAUoNACAAIANBBGo2AgwgAyAAKAIINgIACyAFIAIgACgCsAEgBBCRAzgCACAAQcABaiAAQRBqIAAoAgwgBBBDIABB/AFqIABB+AFqECwEQCAEIAQoAgBBAnI2AgALIAAoAvwBIAEQIBogAEHAAWoQIBogAEGAAmokAAwDC0EBIQMLIABB/AFqED8aDAALAAsLiwMBAX8jAEGAAmsiACQAIAAgAjYC+AEgACABNgL8ASADEGohBiAAQcQBaiADIABB9wFqEK8BIABBuAFqECQiASABECgQISAAIAFBABAiIgI2ArQBIAAgAEEQajYCDCAAQQA2AggDQAJAIABB/AFqIABB+AFqECwNACAAKAK0ASABEB8gAmpGBEAgARAfIQMgASABEB9BAXQQISABIAEQKBAhIAAgAyABQQAQIiICajYCtAELIABB/AFqIgMQOCAGIAIgAEG0AWogAEEIaiAALAD3ASAAQcQBaiAAQRBqIABBDGpB0J8BEJoBDQAgAxA/GgwBCwsCQCAAQcQBahAfRQ0AIAAoAgwiAyAAQRBqa0GfAUoNACAAIANBBGo2AgwgAyAAKAIINgIACyAFIAIgACgCtAEgBCAGEJIDNwMAIABBxAFqIABBEGogACgCDCAEEEMgAEH8AWogAEH4AWoQLARAIAQgBCgCAEECcjYCAAsgACgC/AEgARAgGiAAQcQBahAgGiAAQYACaiQACwcAIAAoAgALiwMBAX8jAEGAAmsiACQAIAAgAjYC+AEgACABNgL8ASADEGohBiAAQcQBaiADIABB9wFqEK8BIABBuAFqECQiASABECgQISAAIAFBABAiIgI2ArQBIAAgAEEQajYCDCAAQQA2AggDQAJAIABB/AFqIABB+AFqECwNACAAKAK0ASABEB8gAmpGBEAgARAfIQMgASABEB9BAXQQISABIAEQKBAhIAAgAyABQQAQIiICajYCtAELIABB/AFqIgMQOCAGIAIgAEG0AWogAEEIaiAALAD3ASAAQcQBaiAAQRBqIABBDGpB0J8BEJoBDQAgAxA/GgwBCwsCQCAAQcQBahAfRQ0AIAAoAgwiAyAAQRBqa0GfAUoNACAAIANBBGo2AgwgAyAAKAIINgIACyAFIAIgACgCtAEgBCAGEJUDOwEAIABBxAFqIABBEGogACgCDCAEEEMgAEH8AWogAEH4AWoQLARAIAQgBCgCAEECcjYCAAsgACgC/AEgARAgGiAAQcQBahAgGiAAQYACaiQAC4sDAQF/IwBBgAJrIgAkACAAIAI2AvgBIAAgATYC/AEgAxBqIQYgAEHEAWogAyAAQfcBahCvASAAQbgBahAkIgEgARAoECEgACABQQAQIiICNgK0ASAAIABBEGo2AgwgAEEANgIIA0ACQCAAQfwBaiAAQfgBahAsDQAgACgCtAEgARAfIAJqRgRAIAEQHyEDIAEgARAfQQF0ECEgASABECgQISAAIAMgAUEAECIiAmo2ArQBCyAAQfwBaiIDEDggBiACIABBtAFqIABBCGogACwA9wEgAEHEAWogAEEQaiAAQQxqQdCfARCaAQ0AIAMQPxoMAQsLAkAgAEHEAWoQH0UNACAAKAIMIgMgAEEQamtBnwFKDQAgACADQQRqNgIMIAMgACgCCDYCAAsgBSACIAAoArQBIAQgBhCWAzcDACAAQcQBaiAAQRBqIAAoAgwgBBBDIABB/AFqIABB+AFqECwEQCAEIAQoAgBBAnI2AgALIAAoAvwBIAEQIBogAEHEAWoQIBogAEGAAmokAAuLAwEBfyMAQYACayIAJAAgACACNgL4ASAAIAE2AvwBIAMQaiEGIABBxAFqIAMgAEH3AWoQrwEgAEG4AWoQJCIBIAEQKBAhIAAgAUEAECIiAjYCtAEgACAAQRBqNgIMIABBADYCCANAAkAgAEH8AWogAEH4AWoQLA0AIAAoArQBIAEQHyACakYEQCABEB8hAyABIAEQH0EBdBAhIAEgARAoECEgACADIAFBABAiIgJqNgK0AQsgAEH8AWoiAxA4IAYgAiAAQbQBaiAAQQhqIAAsAPcBIABBxAFqIABBEGogAEEMakHQnwEQmgENACADED8aDAELCwJAIABBxAFqEB9FDQAgACgCDCIDIABBEGprQZ8BSg0AIAAgA0EEajYCDCADIAAoAgg2AgALIAUgAiAAKAK0ASAEIAYQlwM2AgAgAEHEAWogAEEQaiAAKAIMIAQQQyAAQfwBaiAAQfgBahAsBEAgBCAEKAIAQQJyNgIACyAAKAL8ASABECAaIABBxAFqECAaIABBgAJqJAALmIwBAy5/BX0CfCMAQRBrIhkkACAZIAM2AgwgGUEANgIIIBlCADcCACAZIAEgASACaiICIAIgAWsQwAMjAEHgAGsiIiQAICJBCGohDSAZKAIEIBkoAgAiAWshAiMAQcABayITJAAgE0EANgKgASATQgA3A5gBIBNBADYCsAEgE0IANwKoASATQbQBaiIaQQA2AgggGkIANwIAIBpBgMAAELcDIBpBgMAAEJgDIBNBDGpBAEEw/AsAIBMgAjYCCCATIAE2AgQCQAJ/IBNBBGohAgJ/QXpB5RstAABBMUcNABpBfiACRQ0BGiACQQA2AhggAigCICIBRQRAIAJBADYCKCACQS82AiBBLyEBCyACKAIkRQRAIAJBMDYCJAtBfCACKAIoQQFB0DcgAREDACIDRQ0BGiACIAM2AhwgA0EANgI4IAMgAjYCACADQbT+ADYCBEF+IQQCQCACRQ0AIAIoAiBFDQAgAigCJCIFRQ0AIAIoAhwiAUUNACABKAIAIAJHDQAgASgCBEG0/gBrQR9LDQACQAJAIAEoAjgiDARAIAEoAihBD0cNAQsgAUEPNgIoIAFBBjYCDAwBCyACKAIoIAwgBREBACABQQA2AjggAigCICABQQ82AiggAUEGNgIMRQ0BCyACKAIkRQ0AIAIoAhwiAUUNACABKAIAIAJHDQAgASgCBEG0/gBrQR9LDQBBACEEIAFBADYCNCABQgA3AiwgAUEANgIgIAJBADYCCCACQgA3AhQgASgCDCIFBEAgAiAFQQFxNgIwCyABQgA3AjwgAUEANgIkIAFBgIACNgIYIAFCgICAgHA3AhAgAUK0/gA3AgQgAUKBgICAcDcCxDcgASABQbQKaiIFNgJwIAEgBTYCVCABIAU2AlALQQAgBEUNABogAigCKCADIAIoAiQRAQAgAkEANgIcIAQLC0UEQCATQQA2AqwBAkADQCATIBooAgAiATYCECATIBooAgQgAWs2AhRBACEMIwBBEGsiFyQAQX4hHAJAIBNBBGoiCkUNACAKKAIgRQ0AIAooAiRFDQAgCigCHCIGRQ0AIAYoAgAgCkcNACAGKAIEIgVBtP4Aa0EfSw0AIAooAgwiEEUNACAKKAIAIgFFBEAgCigCBA0BCyAFQb/+AEYEQCAGQcD+ADYCBEHA/gAhBQsgBkHcAGohKiAGQfQFaiEgIAZB2ABqISMgBkHwAGohISAGQbQKaiEfIAZB9ABqIRYgBigCQCEDIAYoAjwhByAKKAIEIiQhBCAKKAIQIg8hFQJAAkACQAJAAkADQEF9IQICQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAVBtP4Aaw4fBwYKDRA5Ojs8BRUWFhcYGQQcAiUmASgAKh0eA0BCQ0QLIAYoAkwhCAwoCyAGKAJMIQgMJQsgBigCbCEIDCELIAYoAgwhBQw5CyADQQ5PDRYgBEUNPCADQQhqIQIgAUEBaiEFIARBAWshCCABLQAAIAN0IAdqIQcgA0EFTQ0VIAUhASAIIQQgAiEDDBYLIANBIE8NDiAERQ07IAFBAWohAiAEQQFrIQUgAS0AACADdCAHaiEHIANBF00NDSACIQEgBSEEDA4LIANBEE8NAiAERQ06IANBCGohAiABQQFqIQUgBEEBayEIIAEtAAAgA3QgB2ohByADQQdNDQEgBSEBIAghBCACIQMMAgsgBigCDCIJRQ0XAkAgA0EQTw0AIARFDTogA0EIaiECIAFBAWohBSAEQQFrIQggAS0AACADdCAHaiEHIANBB0sEQCAFIQEgCCEEIAIhAwwBCyAIRQRAIAUhAUEAIQQgAiEDIAwhAgw8CyADQRByIQMgBEECayEEIAEtAAEgAnQgB2ohByABQQJqIQELIAlBAnFFIAdBn5YCR3JFBEAgBigCKEUEQCAGQQ82AigLQQAhByAGQQBBAEEAEFEiAjYCHCAXQZ+WAjsADCACIBdBDGpBAhBRIQIgBkG1/gA2AgQgBiACNgIcQQAhAyAGKAIEIQUMNwsgBigCJCICBEAgAkF/NgIwCyAHQQh0QYD+A3EgB0EIdmpBH3BFIAlBAXFxRQRAIApBxw42AhggBkHR/gA2AgQgBigCBCEFDDcLIAdBD3FBCEcEQCAKQZcSNgIYIAZB0f4ANgIEIAYoAgQhBQw3CyAHQQR2IgJBD3EiCEEIaiEFIAhBB00gBigCKCIJBH8gCQUgBiAFNgIoIAULIAVPcUUEQCADQQRrIQMgCkHREDYCGCAGQdH+ADYCBCACIQcgBigCBCEFDDcLQQAhAyAGQQA2AhQgBkGAAiAIdDYCGCAGQQBBAEEAELMBIgI2AhwgCiACNgIwIAZBvf4AQb/+ACAHQYDAAHEbNgIEQQAhByAGKAIEIQUMNgsgCEUEQCAFIQFBACEEIAIhAyAMIQIMOgsgA0EQciEDIARBAmshBCABLQABIAJ0IAdqIQcgAUECaiEBCyAGIAc2AhQgB0H/AXFBCEcEQCAKQZcSNgIYIAZB0f4ANgIEIAYoAgQhBQw1CyAHQYDAA3EEQCAKQesJNgIYIAZB0f4ANgIEIAYoAgQhBQw1CyAGKAIkIgIEQCACIAdBCHZBAXE2AgALAkAgB0GABHFFDQAgBi0ADEEEcUUNACAXQQg6AAwgFyAHQQh2OgANIAYgBigCHCAXQQxqQQIQUTYCHAsgBkG2/gA2AgRBACEDQQAhBwwBCyADQR9LDQELIARFDTUgAUEBaiECIARBAWshBSABLQAAIAN0IAdqIQcgA0EXSwRAIAIhASAFIQQMAQsgA0EIaiEIIAVFBEAgAiEBQQAhBCAIIQMgDCECDDcLIAFBAmohAiAEQQJrIQUgAS0AASAIdCAHaiEHIANBD0sEQCACIQEgBSEEDAELIANBEGohCCAFRQRAIAIhAUEAIQQgCCEDIAwhAgw3CyABQQNqIQIgBEEDayEFIAEtAAIgCHQgB2ohByADQQdLBEAgAiEBIAUhBAwBCyADQRhqIQMgBUUEQCACIQEMNgsgBEEEayEEIAEtAAMgA3QgB2ohByABQQRqIQELIAYoAiQiAgRAIAIgBzYCBAsCQCAGLQAVQQJxRQ0AIAYtAAxBBHFFDQAgFyAHNgAMIAYgBigCHCAXQQxqQQQQUTYCHAsgBkG3/gA2AgRBACEDQQAhBwwBCyADQQ9LDQELIARFDTIgAUEBaiECIARBAWshBSABLQAAIAN0IAdqIQcgA0EHSwRAIAIhASAFIQQMAQsgA0EIaiEDIAVFBEAgAiEBDDMLIARBAmshBCABLQABIAN0IAdqIQcgAUECaiEBCyAGKAIkIgIEQCACIAdBCHY2AgwgAiAHQf8BcTYCCAsCQCAGLQAVQQJxRQ0AIAYtAAxBBHFFDQAgFyAHOwAMIAYgBigCHCAXQQxqQQIQUTYCHAsgBkG4/gA2AgRBACEFQQAhA0EAIQcgBigCFCICQYAIcQ0BDCcLIAYoAhQiAkGACHFFBEAgAyEFDCcLIAchBSADQQ9LDQELIARFBEBBACEEIAUhByAMIQIMMQsgAUEBaiEIIARBAWshCSABLQAAIAN0IAVqIQcgA0EHSwRAIAghASAJIQQMAQsgA0EIaiEDIAlFBEAgCCEBDDALIARBAmshBCABLQABIAN0IAdqIQcgAUECaiEBCyAGIAc2AkQgBigCJCIDBEAgAyAHNgIUC0EAIQMCQCACQYAEcUUNACAGLQAMQQRxRQ0AIBcgBzsADCAGIAYoAhwgF0EMakECEFE2AhwLQQAhBwwlCyADQQhqIQggBUUEQCACIQFBACEEIAghAyAMIQIMLwsgAUECaiECIARBAmshBSABLQABIAh0IAdqIQcgA0EPSwRAIAIhASAFIQQMAQsgA0EQaiEIIAVFBEAgAiEBQQAhBCAIIQMgDCECDC8LIAFBA2ohAiAEQQNrIQUgAS0AAiAIdCAHaiEHIANBB0sEQCACIQEgBSEEDAELIANBGGohAyAFRQRAIAIhAQwuCyAEQQRrIQQgAS0AAyADdCAHaiEHIAFBBGohAQsgBiAHQRh0IAdBgP4DcUEIdHIgB0EIdkGA/gNxIAdBGHZyciICNgIcIAogAjYCMCAGQb7+ADYCBEEAIQdBACEDCyAGKAIQRQRAIAogDzYCECAKIBA2AgwgCiAENgIEIAogATYCACAGIAM2AkAgBiAHNgI8QQIhHAwvCyAGQQBBAEEAELMBIgI2AhwgCiACNgIwIAZBv/4ANgIECwJ/AkAgBigCCEUEQCADIANBAksNAhogBA0BDC0LIAZBzv4ANgIEIAcgA0EHcXYhByADQXhxIQMgBigCBCEFDCkLIARBAWshBCABLQAAIAN0IAdqIQcgAUEBaiEBIANBCHILIAYgB0EBcTYCCEHB/gAhBQJAAkACQAJAAkAgB0EBdkEDcUEBaw4DAAECAwsgBkGA3AA2AlAgBkKJgICA0AA3AlggBkGA7AA2AlQgBkHH/gA2AgQMAwtBxP4AIQUMAQsgCkH0EDYCGEHR/gAhBQsgBiAFNgIEC0EDayEDIAdBA3YhByAGKAIEIQUMJwsgByADQQdxdiEHAn8gA0F4cSIFIANBH0sNABogBEUEQEEAIQQgBSEDIAwhAgwsCyAFQQhqIQggAUEBaiECIARBAWshCSABLQAAIAV0IAdqIQcgA0EXSwRAIAIhASAJIQQgCAwBCyAJRQRAIAIhAUEAIQQgCCEDIAwhAgwsCyAFQRBqIQkgAUECaiECIARBAmshCyABLQABIAh0IAdqIQcgA0EPSwRAIAIhASALIQQgCQwBCyALRQRAIAIhAUEAIQQgCSEDIAwhAgwsCyAFQRhqIQUgAUEDaiECIARBA2shCCABLQACIAl0IAdqIQcgA0EHSwRAIAIhASAIIQQgBQwBCyAIRQRAIAIhAUEAIQQgBSEDIAwhAgwsCyAEQQRrIQQgAS0AAyAFdCAHaiEHIAFBBGohAUEgCyEDIAdB//8DcSICIAdBf3NBEHZHBEAgCkGdCzYCGCAGQdH+ADYCBCAGKAIEIQUMJwsgBkHC/gA2AgQgBiACNgJEQQAhB0EAIQMLIAZBw/4ANgIECyAGKAJEIgIEQCACIAQgAiAESRsiAiAPIAIgD0kbIgJFBEAgDCECDCoLIAIEQCAQIAEgAvwKAAALIAYgBigCRCACazYCRCACIBBqIRAgDyACayEPIAEgAmohASAEIAJrIQQgBigCBCEFDCULIAZBv/4ANgIEIAYoAgQhBQwkCyAIRQRAIAUhAUEAIQQgAiEDIAwhAgwoCyADQRByIQMgBEECayEEIAEtAAEgAnQgB2ohByABQQJqIQELIAYgB0EfcSICQYECajYCZCAGIAdBBXZBH3EiBUEBajYCaCAGIAdBCnZBD3FBBGoiCTYCYCADQQ5rIQMgB0EOdiEHIAVBHkkgAkEdTXFFBEAgCkH5CjYCGCAGQdH+ADYCBCAGKAIEIQUMIwsgBkHF/gA2AgRBACEFIAZBADYCbAwGCyAGKAJsIgUgBigCYCIJSQ0FDAYLIA9FDQ0gECAGKAJEOgAAIAZByP4ANgIEIA9BAWshDyAQQQFqIRAgBigCBCEFDCALIAYoAgwiBUUEQEEAIQUMAwsCQCADQR9LBEAgASEIDAELIARFDSMgA0EIaiECIAFBAWohCCAEQQFrIQkgAS0AACADdCAHaiEHIANBF0sEQCAJIQQgAiEDDAELIAlFBEAgCCEBQQAhBCACIQMgDCECDCULIANBEGohCSABQQJqIQggBEECayELIAEtAAEgAnQgB2ohByADQQ9LBEAgCyEEIAkhAwwBCyALRQRAIAghAUEAIQQgCSEDIAwhAgwlCyADQRhqIQIgAUEDaiEIIARBA2shCyABLQACIAl0IAdqIQcgA0EHSwRAIAshBCACIQMMAQsgC0UEQCAIIQFBACEEIAIhAyAMIQIMJQsgA0EgciEDIAFBBGohCCAEQQRrIQQgAS0AAyACdCAHaiEHCyAKIBUgD2siASAKKAIUajYCFCAGIAYoAiAgAWo2AiAgBUEEcSICRSAPIBVGcgR/IAIFIBAgAWshAiAGKAIcIQUgBgJ/IAYoAhQEQCAFIAIgARBRDAELIAUgAiABELMBCyIBNgIcIAogATYCMCAGKAIMIgVBBHELRQ0BIAYoAhwgByAHQRh0IAdBgP4DcUEIdHIgB0EIdkGA/gNxIAdBGHZyciAGKAIUG0YNASAKQfUONgIYIAZB0f4ANgIEIAghASAPIRUgBigCBCEFDB8LIAZBwP4ANgIEDBULIAghAUEAIQdBACEDIA8hFQsgBkHP/gA2AgQMGwsDQCADQQJNBEAgBEUNICAEQQFrIQQgAS0AACADdCAHaiEHIANBCHIhAyABQQFqIQELIAYgBUEBaiICNgJsIBYgBUEBdC8B0FtBAXRqIAdBB3E7AQAgA0EDayEDIAdBA3YhByACIgUgCUcNAAsgCSEFCyAFQRJNBEBBACEIIAUiAkEDcSIMQQNHBEADQCAWIAJBAXQvAdBbQQF0akEAOwEAIAJBAWohAiAMIAhBAWoiCHNBA0cNAAsLIAVBD00EQANAIBYgAkEBdCIFLwHQW0EBdGpBADsBACAWIAVB0tsAai8BAEEBdGpBADsBACAWIAVB1NsAai8BAEEBdGpBADsBACAWIAVB1tsAai8BAEEBdGpBADsBACACQQRqIgJBE0cNAAsLIAZBEzYCbAsgBkEHNgJYIAYgHzYCUCAGIB82AnBBACEIQQAgFkETICEgIyAgEOMBIgwEQCAKQdIJNgIYIAZB0f4ANgIEIAYoAgQhBQwbCyAGQcb+ADYCBCAGQQA2AmxBACEMCyAGKAJkIh0gBigCaGoiGCAISwRAQX8gBigCWHRBf3MhGyAGKAJQIRQDQCADIQ4gBCEFIAEhAgJAAkACQAJAAkACQCAUIAcgG3EiEkECdGotAAEiCyADTQRAIAMhCQwBCwNAIAVFDQIgAi0AACAOdCELIAJBAWohAiAFQQFrIQUgDkEIaiIJIQ4gCSAUIAcgC2oiByAbcSISQQJ0ai0AASILSQ0ACwsgFCASQQJ0ai8BAiIDQQ9NBEAgBiAIQQFqIgE2AmwgFiAIQQF0aiADOwEAIAkgC2shAyAHIAt2IQcgASEIDAULAn8CfwJAAkACQCADQRBrDgIAAQILIAtBAmoiASAJSwRAA0AgBUUNHiAFQQFrIQUgAi0AACAJdCAHaiEHIAJBAWohAiAJQQhqIgkgAUkNAAsLIAkgC2shAyAHIAt2IQkgCEUEQCAKQagKNgIYIAZB0f4ANgIEIAIhASAFIQQgCSEHIAYoAgQhBQwlCyADQQJrIQMgCUECdiEHIAlBA3FBA2ohCyAIQQF0IBZqQQJrLwEADAMLIAtBA2oiASAJSwRAA0AgBUUNHSAFQQFrIQUgAi0AACAJdCAHaiEHIAJBAWohAiAJQQhqIgkgAUkNAAsLIAkgC2tBA2shAyAHIAt2IgFBA3YhByABQQdxQQNqDAELIAtBB2oiASAJSwRAA0AgBUUNHCAFQQFrIQUgAi0AACAJdCAHaiEHIAJBAWohAiAJQQhqIgkgAUkNAAsLIAkgC2tBB2shAyAHIAt2IgFBB3YhByABQf8AcUELagshC0EACyEEIAggC2ogGEsNAkEAIQkgC0EDcSIORQ0BIAshAQNAIBYgCEEBdGogBDsBACAIQQFqIQggAUEBayEBIAlBAWoiCSAORw0ACwwDCyABIARqIQEgAyAEQQN0aiEDDCILIAshAQwBCyAKQagKNgIYIAZB0f4ANgIEIAIhASAFIQQgBigCBCEFDB0LIAtBBE8EQANAIBYgCEEBdGoiCSAEOwEAIAkgBDsBAiAJIAQ7AQQgCSAEOwEGIAhBBGohCCABQQRrIgENAAsLIAYgCDYCbAsgAiEBIAUhBCAIIBhJDQALCyAGLwH0BEUEQCAKQaIONgIYIAZB0f4ANgIEIAYoAgQhBQwaCyAGQQk2AlggBiAfNgJQIAYgHzYCcEEBIBYgHSAhICMgIBDjASIMBEAgCkG2CTYCGCAGQdH+ADYCBCAGKAIEIQUMGgsgBkEGNgJcIAYgBigCcDYCVEECIBYgBigCZEEBdGogBigCaCAhICogIBDjASIMBEAgCkGECjYCGCAGQdH+ADYCBCAGKAIEIQUMGgsgBkHH/gA2AgRBACEMCyAGQcj+ADYCBAsgBEEGSSAPQYICSXJFBEAgCiAPNgIQIAogEDYCDCAKIAQ2AgQgCiABNgIAIAYgAzYCQCAGIAc2AjwgCigCHCIQKAI0IgtBB3EhJSALIBVqISsgCyAQKAIsIixqIS0gCigCDCIBIAooAhAiAmoiHUGBAmshJiABIAIgFWtqIS4gCigCACIIIAooAgRqQQVrISdBfyAQKAJcdEF/cyEvQX8gECgCWHRBf3MhMCAQKAJUISggECgCUCEpIBAoAkAhBSAQKAI8IQ4gECgCOCEHIBAoAjAhMQNAIAVBDk0EfyAILQAAIAV0IA5qIAgtAAEgBUEIanRqIQ4gCEECaiEIIAVBEHIFIAULICkgDiAwcUECdGoiAi0AASIDayEFIA4gA3YhDgJAAkACQAJAAkAgEAJ/IAoCfwJAA0AgAi0AACIDRQRAIAEgAi0AAjoAACABQQFqIQEMCAsgA0EQcQRAIAIvAQIhDwJ/IANBD3EiAkUEQCAIIQMgDgwBCwJ/IAIgBU0EQCAFIQQgCAwBCyAFQQhqIQQgCC0AACAFdCAOaiEOIAhBAWoLIQMgBCACayEFIA5BfyACdEF/c3EgD2ohDyAOIAJ2CyEEIAVBDk0EQCADLQAAIAV0IARqIAMtAAEgBUEIanRqIQQgBUEQciEFIANBAmohAwsgBSAoIAQgL3FBAnRqIgItAAEiCGshBSAEIAh2IQ4gAi0AACIEQRBxDQIDQCAEQcAAcUUEQCAFICggAi8BAkECdGogDkF/IAR0QX9zcUECdGoiAi0AASIEayEFIA4gBHYhDiACLQAAIgRBEHFFDQEMBAsLIAMhCEHwEQwDCyADQcAAcUUEQCAFICkgAi8BAkECdGogDkF/IAN0QX9zcUECdGoiAi0AASIDayEFIA4gA3YhDgwBCwtBv/4AIANBIHENAhpB1BEMAQsgAi8BAiEUAn8gBEEPcSICIAVNBEAgBSEEIAMMAQsgAy0AACAFdCAOaiEOIANBAWogAiAFQQhqIgRNDQAaIAMtAAEgBHQgDmohDiAFQRBqIQQgA0ECagshCCAOQX8gAnRBf3NxIRggBCACayEFIA4gAnYhDiAUIBhqIhsgASAuayICTQ0DIBsgAmsiCSAxTQ0CIBAoAsQ3RQ0CQZQPCzYCGEHR/gALNgIEDAQLAkACQCALRQRAIAcgLCAJa2ohBCAJIA9PBEAgASECDAMLQQAhEiABIQIgCSIDQQdxIh4EQANAIAIgBC0AADoAACADQQFrIQMgAkEBaiECIARBAWohBCASQQFqIhIgHkcNAAsLIBUgGCAdaiAUamsgAWpBeEsNAQNAIAIgBC0AADoAACACIAQtAAE6AAEgAiAELQACOgACIAIgBC0AAzoAAyACIAQtAAQ6AAQgAiAELQAFOgAFIAIgBC0ABjoABiACIAQtAAc6AAcgAkEIaiECIARBCGohBCADQQhrIgMNAAsMAQsgCSALSwRAIAcgLSAJa2ohBCAJIAtrIgkgD08EQCABIQIMAwtBACESIAEhAiAJIgNBB3EiHgRAA0AgAiAELQAAOgAAIANBAWshAyACQQFqIQIgBEEBaiEEIBJBAWoiEiAeRw0ACwsgKyAYIB1qIBRqayABakF4TQRAA0AgAiAELQAAOgAAIAIgBC0AAToAASACIAQtAAI6AAIgAiAELQADOgADIAIgBC0ABDoABCACIAQtAAU6AAUgAiAELQAGOgAGIAIgBC0ABzoAByACQQhqIQIgBEEIaiEEIANBCGsiAw0ACwsgCyAPIAlrIg9PBEAgByEEDAMLQQAhASALIQMgByEEICUEQANAIAIgBC0AADoAACADQQFrIQMgAkEBaiECIARBAWohBCABQQFqIgEgJUcNAAsLIAtBCE8EQANAIAIgBC0AADoAACACIAQtAAE6AAEgAiAELQACOgACIAIgBC0AAzoAAyACIAQtAAQ6AAQgAiAELQAFOgAFIAIgBC0ABjoABiACIAQtAAc6AAcgAkEIaiECIARBCGohBCADQQhrIgMNAAsLIAIgG2shBCAPIAtrIQ8MAgsgByALIAlraiEEIAkgD08EQCABIQIMAgtBACESIAEhAiAJIgNBB3EiHgRAA0AgAiAELQAAOgAAIANBAWshAyACQQFqIQIgBEEBaiEEIBJBAWoiEiAeRw0ACwsgFSAYIB1qIBRqayABakF4Sw0AA0AgAiAELQAAOgAAIAIgBC0AAToAASACIAQtAAI6AAIgAiAELQADOgADIAIgBC0ABDoABCACIAQtAAU6AAUgAiAELQAGOgAGIAIgBC0ABzoAByACQQhqIQIgBEEIaiEEIANBCGsiAw0ACwsgAiAbayEEIA8gCWshDwsCQCAPQQNJDQAgD0EDayIBQQNuIgNBA3FBA0cEQCADQQFqQQNxIQlBACEDA0AgAiAELQAAOgAAIAIgBC0AAToAASACIAQtAAI6AAIgD0EDayEPIAJBA2ohAiAEQQNqIQQgA0EBaiIDIAlHDQALCyABQQlJDQADQCACIAQtAAA6AAAgAiAELQABOgABIAIgBC0AAjoAAiACIAQtAAM6AAMgAiAELQAEOgAEIAIgBC0ABToABSACIAQtAAY6AAYgAiAELQAHOgAHIAIgBC0ACDoACCACIAQtAAk6AAkgAiAELQAKOgAKIAIgBC0ACzoACyACQQxqIQIgBEEMaiEEIA9BDGsiD0ECSw0ACwsgD0UEQCACIQEMAwsgAiAELQAAOgAAIA9BAkYNASACQQFqIQEMAgsgASAbayEDA0AgASICIAMiBC0AADoAACACIAMtAAE6AAEgAiADLQACOgACIAJBA2ohASADQQNqIQMgD0EDayIPQQJLDQALIA9FDQEgAiADLQAAOgADIA9BAkcEQCACQQRqIQEMAgsgAiAELQAEOgAEIAJBBWohAQwBCyACIAQtAAE6AAEgAkECaiEBCyAIICdPDQAgASAmSQ0BCwsgCiABNgIMIAogCCAFQQN2ayICNgIAIAogJiABa0GBAmo2AhAgCiAnIAJrQQVqNgIEIBAgBUEHcSIBNgJAIBAgDkF/IAF0QX9zcTYCPCAGKAJAIQMgBigCPCEHIAooAgQhBCAKKAIAIQEgCigCECEPIAooAgwhECAGKAIEQb/+AEcNDyAGQX82Asg3IAYoAgQhBQwYCyAGQQA2Asg3IAMhCCAEIQUgASECAkAgBigCUCIUIAdBfyAGKAJYdEF/cyIScUECdGoiCy0AASIOIANNBEAgAyEJDAELA0AgBUUNDSACLQAAIAh0IQsgAkEBaiECIAVBAWshBSAIQQhqIgkhCCAJIBQgByALaiIHIBJxQQJ0aiILLQABIg5JDQALCyAOIQMgCy8BAiESAkAgCy0AACILQQFrQf8BcUEOSwRAQQAhAyACIQEgBSEEDAELIAUhBCACIQECQCAJIgggAyAUIBJBAnRqIhQgB0F/IAMgC2p0QX9zIhhxIAN2QQJ0aiISLQABIg5qTwRAIAghCwwBCwNAIARFDQ0gAS0AACAIdCEOIAFBAWohASAEQQFrIQQgCEEIaiILIQggAyAUIAcgDmoiByAYcSADdkECdGoiEi0AASIOaiALSw0ACwsgCyADayEJIAcgA3YhByASLQAAIQsgEi8BAiESCyAGIBJB//8DcTYCRCAGIAMgDmo2Asg3IAkgDmshAyAHIA52IQcgC0H/AXEiAkUEQCAGQc3+ADYCBCAGKAIEIQUMGAsgAkEgcQRAIAZBv/4ANgIEIAZBfzYCyDcgBigCBCEFDBgLIAJBwABxBEAgCkHUETYCGCAGQdH+ADYCBCAGKAIEIQUMGAsgBkHJ/gA2AgQgBiACQQ9xIgg2AkwLIAEhCyAEIQkCQCAIRQRAIAYoAkQhAgwBCyADIQUgASECIAMgCEkEQANAIARFDQsgBEEBayEEIAItAAAgBXQgB2ohByACQQFqIgEhAiAFQQhqIgUgCEkNAAsLIAYgBigCyDcgCGo2Asg3IAYgBigCRCAHQX8gCHRBf3NxaiICNgJEIAUgCGshAyAHIAh2IQcLIAZByv4ANgIEIAYgAjYCzDcLIAMhCCAEIQUgASECAkAgBigCVCIUIAdBfyAGKAJcdEF/cyIScUECdGoiCy0AASIOIANNBEAgAyEJDAELA0AgBUUNCCACLQAAIAh0IQsgAkEBaiECIAVBAWshBSAIQQhqIgkhCCAJIBQgByALaiIHIBJxQQJ0aiILLQABIg5JDQALCyALLwECIRIgBgJ/IAstAAAiCEEQTwRAIAIhASAFIQQgDiELIAYoAsg3DAELIAUhBCACIQECQCAJIgMgDiAUIBJBAnRqIhQgB0F/IAggDmp0QX9zIhhxIA52QQJ0aiISLQABIgtqTwRAIAMhCAwBCwNAIARFDQggAS0AACADdCELIAFBAWohASAEQQFrIQQgA0EIaiIIIQMgDiAUIAcgC2oiByAYcSAOdkECdGoiEi0AASILaiAISw0ACwsgCCAOayEJIAcgDnYhByASLQAAIQggEi8BAiESIAYoAsg3IA5qCyALajYCyDcgCSALayEDIAcgC3YhByAIQcAAcQRAIApB8BE2AhggBkHR/gA2AgQgBigCBCEFDBYLIAZBy/4ANgIEIAYgCEEPcSIINgJMIAYgEkH//wNxNgJICyABIQsgBCEJIAgEQCADIQUgASECIAMgCEkEQANAIARFDQYgBEEBayEEIAItAAAgBXQgB2ohByACQQFqIgEhAiAFQQhqIgUgCEkNAAsLIAYgBigCyDcgCGo2Asg3IAYgBigCSCAHQX8gCHRBf3NxajYCSCAHIAh2IQcgBSAIayEDCyAGQcz+ADYCBAsgDw0BC0EAIQ8gDCECDBYLAn8gBigCSCICIBUgD2siBUsEQAJAIAIgBWsiAiAGKAIwTQ0AIAYoAsQ3RQ0AIApBlA82AhggBkHR/gA2AgQgBigCBCEFDBQLAn8gBigCNCIFIAJJBEAgBigCOCAGKAIsIAIgBWsiAmtqDAELIAYoAjggBSACa2oLIQUgAiAGKAJEIgggAiAISRsMAQsgECACayEFIAYoAkQiCAshAiAGIAggAiAPIAIgD0kbIglrNgJEIAlBAWshC0EAIQggCUEHcSIORQ0GIAkhAgNAIBAgBS0AADoAACACQQFrIQIgEEEBaiEQIAVBAWohBSAIQQFqIgggDkcNAAsMBwsgCSALaiEBIAMgCUEDdGohAwwTCyACIAVqIQEgCSAFQQN0aiEDDBILIAEgBGohASADIARBA3RqIQMMEQsgCSALaiEBIAMgCUEDdGohAwwQCyACIAVqIQEgCSAFQQN0aiEDDA8LIAEgBGohASADIARBA3RqIQMMDgsgCSECCyALQQdPBEADQCAQIAUtAAA6AAAgECAFLQABOgABIBAgBS0AAjoAAiAQIAUtAAM6AAMgECAFLQAEOgAEIBAgBS0ABToABSAQIAUtAAY6AAYgECAFLQAHOgAHIBBBCGohECAFQQhqIQUgAkEIayICDQALCyAPIAlrIQ8gBigCRA0AIAZByP4ANgIEIAYoAgQhBQwJCyAGKAIEIQUMCAtBACEEIAIhASAJIQMgDCECDAsLIAYoAiQiAgRAIAJBADYCEAsgBSEDCyAGQbn+ADYCBAsCQCAGKAIUIghBgAhxRQ0AIAYoAkQiBSAEIAQgBUsbIgIEQAJAIAYoAiQiCUUNACAJKAIQIg5FDQAgCSgCGCILIAkoAhQgBWsiBU0NACALIAVrIAIgAiAFaiALSxsiCARAIAUgDmogASAI/AoAAAsgBigCFCEICwJAIAhBgARxRQ0AIAYtAAxBBHFFDQAgBiAGKAIcIAEgAhBRNgIcCyAGIAYoAkQgAmsiBTYCRCAEIAJrIQQgASACaiEBCyAFRQ0AIAwhAgwJCyAGQbr+ADYCBCAGQQA2AkQLAkAgBi0AFUEIcQRAQQAhBSAERQ0IA0AgASAFai0AACECAkAgBigCJCIIRQ0AIAgoAhwiC0UNACAGKAJEIgkgCCgCIE8NACAGIAlBAWo2AkQgCSALaiACOgAACyACQQAgBCAFQQFqIgVLGw0ACwJAIAYtABVBAnFFDQAgBi0ADEEEcUUNACAGIAYoAhwgASAFEFE2AhwLIAEgBWohASAEIAVrIQQgAkUNASAMIQIMCQsgBigCJCICRQ0AIAJBADYCHAsgBkG7/gA2AgQgBkEANgJECwJAIAYtABVBEHEEQEEAIQUgBEUNBwNAIAEgBWotAAAhAgJAIAYoAiQiCEUNACAIKAIkIgtFDQAgBigCRCIJIAgoAihPDQAgBiAJQQFqNgJEIAkgC2ogAjoAAAsgAkEAIAQgBUEBaiIFSxsNAAsCQCAGLQAVQQJxRQ0AIAYtAAxBBHFFDQAgBiAGKAIcIAEgBRBRNgIcCyABIAVqIQEgBCAFayEEIAJFDQEgDCECDAgLIAYoAiQiAkUNACACQQA2AiQLIAZBvP4ANgIECyAGKAIUIglBgARxBEACQCADQQ9LBEAgASEFDAELIARFDQYgA0EIaiECIAFBAWohBSAEQQFrIQggAS0AACADdCAHaiEHIANBB0sEQCAIIQQgAiEDDAELIAhFBEAgBSEBQQAhBCACIQMgDCECDAgLIANBEHIhAyABQQJqIQUgBEECayEEIAEtAAEgAnQgB2ohBwsCQCAGLQAMQQRxRQ0AIAcgBi8BHEYNACAKQbkPNgIYIAZB0f4ANgIEIAUhASAGKAIEIQUMAwtBACEHQQAhAyAFIQELIAYoAiQiAgRAIAJBATYCMCACIAlBCXZBAXE2AiwLIAZBAEEAQQAQUSICNgIcIAogAjYCMCAGQb/+ADYCBCAGKAIEIQUMAQsgBUUNASAGKAIURQ0BAkAgA0EfSwRAIAEhAgwBCyAERQ0EIANBCGohCCABQQFqIQIgBEEBayEJIAEtAAAgA3QgB2ohByADQRdLBEAgCSEEIAghAwwBCyAJRQRAIAIhAUEAIQQgCCEDIAwhAgwGCyADQRBqIQkgAUECaiECIARBAmshCyABLQABIAh0IAdqIQcgA0EPSwRAIAshBCAJIQMMAQsgC0UEQCACIQFBACEEIAkhAyAMIQIMBgsgA0EYaiEIIAFBA2ohAiAEQQNrIQsgAS0AAiAJdCAHaiEHIANBB0sEQCALIQQgCCEDDAELIAtFBEAgAiEBQQAhBCAIIQMgDCECDAYLIANBIHIhAyABQQRqIQIgBEEEayEEIAEtAAMgCHQgB2ohBwsCQCAFQQRxRQ0AIAcgBigCIEYNACAKQd4ONgIYIAZB0f4ANgIEIAIhASAGKAIEIQUMAQsLIAIhAUEAIQdBACEDCyAGQdD+ADYCBAtBASECDAELQQAhBCAMIQILIAogDzYCECAKIBA2AgwgCiAENgIEIAogATYCACAGIAM2AkAgBiAHNgI8AkACQCAGKAIsRQRAIA8gFUYNASAGKAIEQdD+AEsNAQsCfyAVIA9rIQMCQAJAIAooAhwiASgCOCIMRQRAQQEhBSABIAooAihBASABKAIodEEBIAooAiARAwAiDDYCOCAMRQ0BCyABKAIsIgRFBEAgAUIANwIwIAFBASABKAIodCIENgIsCyADIARPBEAgBARAIAwgECAEayAE/AoAAAsgAUEANgI0DAILIAQgASgCNCIIayIFIAMgAyAFSxsiBARAIAggDGogECADayAE/AoAAAsgAyAFSwRAIAMgBGsiAwRAIAEoAjggECADayAD/AoAAAsgASADNgI0DAILQQAhBSABIAEoAjQgBGoiA0EAIAMgASgCLCIMRxs2AjQgDCABKAIwIgNNDQAgASADIARqNgIwCyAFDAELIAEgASgCLDYCMEEACw0BIAooAhAhDyAKKAIEIQQLIAogCigCCCAkIARrajYCCCAKIBUgD2siASAKKAIUajYCFCAGIAYoAiAgAWo2AiAgBi0ADEEEcUUgDyAVRnJFBEAgCigCDCABayEDIAYoAhwhBSAGAn8gBigCFARAIAUgAyABEFEMAQsgBSADIAEQswELIgE2AhwgCiABNgIwCyAKIAYoAkBBwABBACAGKAIIG2pBgAFBACAGKAIEIgFBv/4ARhtqQYACQYACQQAgAUHC/gBGGyABQcf+AEYbajYCLCACQXsgAhsgAiAPIBVGGyACIAQgJEYbIRwMAgsgBkHS/gA2AgQLQXwhHAsgF0EQaiQAIBxBAUsNASATQagBaiEBIBMoAqwBIQMgGigCACEJIBooAgQgEygCFGshDCMAQSBrIggkAAJAIAwgCWsiBUEATA0AIAEoAgggASgCBCICayAFTgRAIAIgA2siBCAFSARAIAwgBCAJaiIHayILRSAHIAxGckUEQCACIAcgC/wKAAALIAEgAiALajYCBCAEQQBMDQIgASADIAIgAyAFahCeAiAERQ0CIAMgCSAE/AoAAAwCCyABIAMgAiADIAVqEJ4CIAVFDQEgAyAJIAX8CgAADAELIAUgCEEMaiABIAUgASgCAGsgAmoQtAEgAyABKAIAayABEMYBIgIoAggiBGohBQNAIAQgBUcEQCAEIAktAAA6AAAgCUEBaiEJIARBAWohBAwBCwsgAiAFNgIIIAIoAgQaIAEoAgQgA2siBARAIAIoAgggAyAE/AoAAAsgAiACKAIIIAEoAgQgA2tqNgIIIAEgAzYCBCACKAIEIAEoAgAiBCADa2ohBSADIARrIgMEQCAFIAQgA/wKAAALIAIgBTYCBCABIAEoAgAiAzYCBCABIAIoAgQ2AgAgAiADNgIEIAEoAgQhAyABIAIoAgg2AgQgAiADNgIIIAEoAgghAyABIAIoAgw2AgggAiADNgIMIAIgAigCBDYCACACELoBCyAIQSBqJAAgHEEBRw0ACyAKEJsCIBoQOiATQZgBaiIDIBMoAqgBIgIgEygCrAEgAmsQsQIgARA6IApBADYCXCAKQfD7ADYCQCAKQcj7ADYCACAKQdz7ADYCCCAKQYD8ACgCACIBNgIAIAogAUEMaygCAGpBhPwAKAIANgIAIApBADYCBCAKIAooAgBBDGsoAgBqIgJBADYCFCACIApBDGoiATYCGCACQQA2AgwgAkKCoICA4AA3AgQgAiABRTYCECACQSBqQQBBKPwLACACQRxqENMCIAJBADoAUCACQoCAgIBwNwJIIApBiPwAKAIAIgI2AgggAkEMaygCACAKQQhqakGM/AAoAgA2AgAgCkH8+wAoAgAiAjYCACAKIAJBDGsoAgBqQZD8ACgCADYCACAKQZT8ACgCADYCCCAKQcj7ADYCACAKQdz7ADYCCCAKQfD7ADYCQCABQZj1ADYCACABQQRqENMCIAFCADcCGCABQgA3AhAgAUIANwIIIAFCADcCICABQZD3ADYCACABQRg2AjAgAUIANwIoAkAgAyABQSBqIgJGDQAgAhBHRQRAIAMQR0UEQCACEF4aIAIQXiADEF5JBEAgAxBeGiACEF4aCyACIAMpAgA3AgAgAiADKAIINgIIIAIQXhoMAgsgAxAjIQUgAxAfIQMjAEEQayIEJAAgAhBeIQwCQCADQQpNBEAgAiADEFAgAiAFIAMQTSAEQQA6AA8gAiADaiAEQQ9qEF0MAQsgAkEKIANBCmsgDEEAIAwgAyAFELkBCyAEQRBqJAAMAQsgAxAjIQwgAxAfIQMjAEEQayIEJAAgAhB+IQUgAigCBCEIAkAgAyAFSQRAIAIoAgAhBSACIAM2AgQgBSAMIAMQTSAEQQA6AA8gAyAFaiAEQQ9qEF0MAQsgAiAFQQFrIAMgBWtBAWogCEEAIAggAyAMELkBCyAEQRBqJAALIAFBADYCLCABKAIgIAFBIGoiAyABLAArIgJBAEgiBBshCSABKAIkIAIgBBshCCABKAIwIgRBCHEEQCABIAk2AgwgASAJNgIIIAEgCCAJaiIFNgIQIAEgBTYCLAsCQCAEQRBxRQ0AIAEgCCAJajYCLCADQQogASgCKEH/////B3FBAWsgAkEAThsQISABIAk2AhggASAJNgIUIAEgCSABKAIkIAEsACsiAiACQQBIG2o2AhwgAS0AMEEDcUUNAANAIAhBAEgEQCABIAlB/////wdqIgk2AhggCEH/////B2shCAwBCwsgCEUNACABIAggCWo2AhgLIwBBwAFrIgEkACABQgA3ArgBIAFCzo7NgjU3ArABIAogAUGwAWpBEBCIAQJAAkAgCiAKKAIAQQxrKAIAai0AEEEFcUUEQCABKAKwAUHOjs2CBUYNAQtBshIQvgMgDUIANwAFIA1CADcCACANQQE6AA0gDUEQakEAQcgA/AsADAELIAEoArQBQQRrQXxNBEBBthQgAUG0AWoQlwIgDUIANwAFIA1CADcCACANQQE6AA0gDUEQakEAQcgA/AsADAELIAEoArgBIgJBga3iBE8EQEG4EyABQbgBahCXAiANQgA3AAUgDUIANwIAIA1BAToADSANQRBqQQBByAD8CwAMAQsgAS0AvAEiA0EETwRAIAEgAzYCAEH0EyABEHIQf0Gg8QAoAgAQYRogDUIANwAFIA1CADcCACANQQE6AA0gDUEQakEAQcgA/AsADAELIAMQ0wMhDCABKAK0ASEEIAFBAToAZSABQegAaiIFQQBByAD8CwAgASACNgJYIAEgAS0AvAE2AlwgASABLQC9ATYCYCABIAEtAL4BQQFxOgBkIAUgAkEDbCIDQQJBAyAEQQFGG2wQpwEgAUH0AGoiCCADEKcBIAEgBEECSyIEOgBlIAFBgAFqIglBBEEDIAQbIAJsEKcBIAFBjAFqIgQgAhCnASABQZgBaiIHIAMQpwEgAUGkAWoiCyADIAxsEKcBIAogASgCaCABQcwAaiAFEKIBIgIoAgQgAigCAGsQiAEgAhA6IAogASgCjAEgAUFAayAEEKIBIgIoAgQgAigCAGsQiAEgAhA6IAogASgCmAEgAUE0aiAHEKIBIgIoAgQgAigCAGsQiAEgAhA6IAogASgCdCABQShqIAgQogEiAigCBCACKAIAaxCIASACEDogCiABKAKAASABQRxqIAkQogEiAigCBCACKAIAaxCIASACEDogCiABKAKkASABQRBqIAsQogEiAigCBCACKAIAaxCIASACEDoCQCAKIAooAgBBDGsoAgBqLQAQQQVxBEBBkQwQvgMgDUIANwAFIA1CADcCACANQQE6AA0gDUEQakEAQcgA/AsADAELIA0gAUHYAGoiAikCADcCACANIAIpAQY3AQYgDUEQaiACQRBqEKEBIA1BHGogAkEcahChASANQShqIAJBKGoQoQEgDUE0aiACQTRqEKEBIA1BQGsgAkFAaxChASANQcwAaiACQcwAahChAQsgAUHYAGoQywMLIAFBwAFqJAAgChCxARoMAgsgE0EEahCbAgsgGhA6IBNBqAFqEDogDUIANwAFIA1CADcCACANQQE6AA0gDUEQakEAQcgA/AsACyATQZgBahAgGiATQcABaiQAIwBBkAFrIgIkACANKAIAIQQgDSgCBBDTAyEBAkACQAJAIA0oAhQgDSgCEGsiBSAEQQNsIgNBAkEDIAUgDSgCACIMQQZsIghGG2xHBEAgAkH2HTYCOCACQfgANgI0IAJB/BQ2AjBByAsgAkEwahByEH9BoPEAKAIAEGEaDAELIAMgDSgCICANKAIca0cEQCACQfkANgI8IAJBPGpBxhwQmgIMAQsgDSgCLCANKAIoa0EEQQMgDS0ADSIJQQFxGyAEbEcEQCACQZ4dNgIoIAJB+gA2AiQgAkH8FDYCIEHICyACQSBqEHIQf0Gg8QAoAgAQYRoMAQsgBCANKAI4IA0oAjRrRwRAIAJB7xs2AhggAkH7ADYCFCACQfwUNgIQQcgLIAJBEGoQchB/QaDxACgCABBhGgwBCyADIA0oAkQgDSgCQGtHBEAgAkH8ADYCPCACQTxqQZwcEJoCDAELIA0oAlAgDSgCTGsiByABIANsRg0BIAJB8Bw2AgggAkH9ADYCBCACQfwUNgIAQcgLIAIQchB/QaDxACgCABBhGgsgAEIANwIAIABBADoACCAAQQxqQQBByAD8CwAMAQsgAEEMaiIBQQBByAD8CwAgACAMNgIAIAAgDSgCBDYCBCAAIA0tAAw6AAggASADEKQBIABBGGogAxCkASAAQSRqIARBAnQQpAEgAEEwaiAEEKQBIABBPGogAxCkASAAQcgAaiAHEKQBAkAgBSAIRgRAIAEoAgAhDCANKAIQIQgDQCADIBFGDQIgDCARQQJ0agJ9QwAAgD9DAACAvyAIIBFBAXRqLwEAIgHBQQBOGyEzIAFB/wdxIQUCQCABQQp2QR9xIgFBH0cEQCABDQEgM0MAAIA4lCAFs5RDAACAOpQMAgtDAADAfyAzQwAAgH+UIAUbDAELQwAAgD8hMgJAIAFBD2siAUGAAU4EQEMAAAB/ITIgAUH/AUkEQCABQf8AayEBDAILQwAAgH8hMkH9AiABIAFB/QJPG0H+AWshAQwBCyABQYF/Sg0AQwAAgAwhMiABQZt+SwRAIAFB5gBqIQEMAQtDAAAAACEyQbZ9IAEgAUG2fU0bQcwBaiEBCyAFs0MAAIA6lEMAAIA/kiAzIDIgAUEXdEGAgID8A2q+lJSUCzgCACARQQFqIREMAAsACyANKAIQIgVBAmohDCAFQQFqIQhEAAAAAAAA8D9BASANKAIIdLejtiEyIAEoAgAhBwNAIAMgEUYNASAHIBFBAnRqIDIgCCARQQNsIgFqLQAAQQh0IAEgBWotAAByIAEgDGosAAAiAUH/AXFBEHRyQYCAgHhBACABQQBIG3KylDgCACARQQFqIREMAAsACyAAKAIYIQEgDSgCHCEFQQAhEQNAIAMgEUYEQCACQdQAaiEIQQAhESAJQQFxIQcDfyAEIBFGBH8gACgCMCEFIA0oAjQhDEEABQJAIAcEQCAAKAIkIA0oAighBSACQoCAgPyDgIDAPzcCTCACQoCAgPyDgIDAPzcCRCACQoCAgPyDgIDAPzcCPCAIQcgfQTz8CgAAIBFBBHRqIQwgAkE8aiELQwAAAAAhMiAFIBFBAnRqIgEvAAAgAS0AAkEQdHIgAS0AAyIBQRh0ciEFIAFBBnYhCUEDIQEDfyABQQBIBH8gDCAJQQJ0akMAAIA/IDKTkTgCACALQQxqIQVBAAUgASAJRwRAIAwgAUECdGogBUH/A3GzQ/MENT+UQwCA/0OVIjOMIDMgBUGABHEbIjM4AgAgMyAzlCAykiEyIAVBCnYhBQsgAUEBayEBDAELCyEBA0AgAUEDRwRAIAwgAUECdCIJaiILIAUgCWoqAgAgCyoCAJQ4AgAgAUEBaiEBDAELCwwBCyAAKAIkIA0oAiggAkKAgID8g4CAwD83AkwgAkKAgID8g4CAwD83AkQgAkKAgID8g4CAwD83AjwgCEHIH0E8/AoAACMAQRBrIgEkACARQQNsaiIFLQACIQkgBS0AASELIAEgBS0AALNDgYAAPJRDAACAv5IgAioCSJQ4AgQgASALs0OBgAA8lEMAAIC/kiACKgJMlDgCCCABIAmzQ4GAADyUQwAAgL+SIAIqAlCUOAIMIBFBBHRqIgUgASkCBDcCACAFIAEoAgw2AgggBUMAAIA/IAEqAgwgASoCDJQgASoCBCABKgIElCABKgIIIAEqAgiUkpKTIjJDAAAAACAyQwAAAABeG5E4AgwgAUEQaiQACyARQQFqIREMAQsLIREDQCAEIBFHBEAgBSARQQJ0agJ9QwAAAAAgDCARai0AALNDAAB/Q5UiMkMAAIA/IDKTlSIyvCIBQYCAgPwDRg0AGgJAIAFBgICA/AdrQf///4d4TQRAIAFBAXQiCEUEQCMAQRBrIgFDAACAvzgCDCABKgIMQwAAAACVDAMLIAFBgICA/AdGDQEgCEGAgIB4SSABQQBOcUUEQCAyIDKTIjIgMpUMAwsgMkMAAABLlLxBgICA3ABrIQELQYjxACsDACABIAFBgIDM+QNrIgFBgICAfHFrvrsgAUEPdkHwAXEiCCsDgG+iRAAAAAAAAPC/oCI3IDeiIjiiQZDxACsDACA3okGY8QArAwCgoCA4oiABQRd1t0GA8QArAwCiIAgrA4hvoCA3oKC2ITILIDILOAIAIBFBAWohEQwBCwsgACgCPCEBIA0oAkAhBEEAIREDQCADIBFGBEAgDSgCUCANKAJMIgFrIQQgACgCSCEFQQAhAwNAIAMgBEYEQCAZKAIMIQwjAEHgAGsiBCQAIwBBEGsiBSQAQQEhAQJ/QQEhA0EBIAxBAEwNABogDEEBa0EDcyIMQX9zQQFxIQEgDEEEcUUhAyAMQQJxRQshDCAFIAM6AA8gBSAMOgAOIAUgAToADSAFLQAOIQEgBS0ADyEDIAUtAA0hDCAEQYCAgPwDNgJAIARBgICA/AM2AjggBEMAAIA/QwAAgL8gDBsiMzgCXCAEQwAAgD9DAACAvyADGyIyOAJYIAQgMzgCVCAEIDI4AlAgBEMAAIA/QwAAgL8gARsiNDgCTCAEIDQ4AkQgBCAzOAIsIAQgMjgCKCAEIDQ4AiQgBCAyOAIUIAQgNDgCECAEIDM4AgwgBCAzIDKUIjU4AjwgBCA0IDKUIjY4AjQgBCAzIDSUIjM4AjAgBCAzOAIgIAQgNTgCHCAEIDY4AhggBCAzIDKUOAJIIAVBEGokACAAKAIMIgFBCGohDCABQQRqIQggACgCECABa0ECdSEJQQAhAwNAIAMgCU8EQCAAKAIkIgFBCGohDCABQQRqIQggACgCKCABa0ECdSEJQQAhAwNAIAMgCU8EQAJAIAAoAkgiBUEIaiEJIAVBBGohByAAKAJMIAVrQQJ1QQNuIgsgACgCAG4hDCAEQSRqIQ5BACEAQQAhAQNAQQAhAyABIAtPDQEDQCADIAxPBEAgASAMaiEBDAIFIAUgAEECdCIIaiIPIA4gA0ECdGoqAgAiMiAPKgIAlDgCACAHIAhqIg8gMiAPKgIAlDgCACAIIAlqIgggMiAIKgIAlDgCACAAQQNqIQAgA0EBaiEDDAELAAsACwALBSABIANBAnQiBWoiByAEKgIYIAcqAgCUOAIAIAUgCGoiByAEKgIcIAcqAgCUOAIAIAUgDGoiBSAEKgIgIAUqAgCUOAIAIANBBGohAwwBCwsgBEHgAGokAAUgASADQQJ0IgVqIgcgBCoCDCAHKgIAlDgCACAFIAhqIgcgBCoCECAHKgIAlDgCACAFIAxqIgUgBCoCFCAFKgIAlDgCACADQQNqIQMMAQsLBSAFIANBAnRqIAEgA2otAACzQwAAAMOSQwAAADyUOAIAIANBAWohAwwBCwsFIAEgEUECdGogBCARai0AALNDAAB/Q5VDAAAAv5JDmpkZPpU4AgAgEUEBaiERDAELCwUgASARQQJ0aiAFIBFqLQAAs0MAAIA9lEMAACDBkjgCACARQQFqIREMAQsLCyACQZABaiQAIA0QywMgIkHgAGokACAZEDogGUEQaiQAC5UBAQN/IAACfyAAKAIEIgIgACgCCEkEQCACIAEqAgA4AgAgAkEEagwBCyMAQSBrIgMkACADQQxqIAAgACgCBCAAKAIAa0ECdUEBahC2ASAAKAIEIAAoAgBrQQJ1IAAQhwIiAigCCCIEIAEqAgA4AgAgAiAEQQRqNgIIIAAgAhCFAiAAKAIEIAIQgQIgA0EgaiQACzYCBAvqAQEBfyMAQSBrIgYkACAGIAE2AhwCQCADKAIEQQFxRQRAIAZBfzYCACAAIAEgAiADIAQgBiAAKAIAKAIQEQYAIQECQAJAAkAgBigCAA4CAAECCyAFQQA6AAAMAwsgBUEBOgAADAILIAVBAToAACAEQQQ2AgAMAQsgBiADECcgBhBJIQEgBhAlIAYgAxAnIAYQmwEhACAGECUgBiAAEHwgBkEMciAAEHsgBSAGQRxqIAIgBiAGQRhqIgMgASAEQQEQzwEgBkY6AAAgBigCHCEBA0AgA0EMaxAgIgMgBkcNAAsLIAZBIGokACABC0ABAX9BACEAA38gASACRgR/IAAFIAEoAgAgAEEEdGoiAEGAgICAf3EiA0EYdiADciAAcyEAIAFBBGohAQwBCwsLCwAgACACIAMQmQMLVAECfwJAA0AgAyAERwRAQX8hACABIAJGDQIgASgCACIFIAMoAgAiBkgNAiAFIAZKBEBBAQ8FIANBBGohAyABQQRqIQEMAgsACwsgASACRyEACyAAC0ABAX9BACEAA38gASACRgR/IAAFIAEsAAAgAEEEdGoiAEGAgICAf3EiA0EYdiADciAAcyEAIAFBAWohAQwBCwsLCwAgACACIAMQuAMLXgEDfyABIAQgA2tqIQUCQANAIAMgBEcEQEF/IQAgASACRg0CIAEsAAAiBiADLAAAIgdIDQIgBiAHSgRAQQEPBSADQQFqIQMgAUEBaiEBDAILAAsLIAIgBUchAAsgAAuoAQEFfyAAKAJUIgMoAgAhBSADKAIEIgQgACgCFCAAKAIcIgdrIgYgBCAGSRsiBgRAIAUgByAGEHEaIAMgAygCACAGaiIFNgIAIAMgAygCBCAGayIENgIECyAEIAIgAiAESxsiBARAIAUgASAEEHEaIAMgAygCACAEaiIFNgIAIAMgAygCBCAEazYCBAsgBUEAOgAAIAAgACgCLCIBNgIcIAAgATYCFCACC1QBAn8gASAAKAJUIgEgAUEAIAJBgAJqIgMQ4AEiBCABayADIAQbIgMgAiACIANLGyICEHEaIAAgASADaiIDNgJUIAAgAzYCCCAAIAEgAmo2AgQgAgsJACAAEIkCEC0LEwAgACAAKAIAQQxrKAIAahCMAgsTACAAIAAoAgBBDGsoAgBqELEBCwoAIABBCGsQjAILCgAgAEEIaxCxAQsaACAAIAEgAikDCEEAIAMgASgCACgCEBEXAAsJACAAEPwBEC0LlAICAX8DfiABKAIYIAEoAixLBEAgASABKAIYNgIsC0J/IQgCQCAEQRhxIgVFIANBAUYgBUEYRnFyDQAgASgCLCIFBEAgBSABQSBqECNrrCEGCwJAAkACQCADDgMCAAEDCyAEQQhxBEAgASgCDCABKAIIa6whBwwCCyABKAIYIAEoAhRrrCEHDAELIAYhBwsgAiAHfCICQgBTIAIgBlVyDQAgBEEIcSEDAkAgAlANACADBEAgASgCDEUNAgsgBEEQcUUNACABKAIYRQ0BCyADBEAgASABKAIIIAEoAgggAqdqIAEoAiwQsgELIARBEHEEQCABIAEoAhQgASgCHBC6AyABIAKnELkDCyACIQgLIAAgCBCSAgv8AQEJfyMAQRBrIgMkAAJ/IAFBf0cEQCAAKAIMIQQgACgCCCEFIAAoAhggACgCHEYEQEF/IAAtADBBEHFFDQIaIAAoAhghBiAAKAIUIQcgACgCLCEIIAAoAhQhCSAAQSBqIgJBABC4ASACIAIQKBAhIAAgAhAjIgogAhAfIApqELoDIAAgBiAHaxC5AyAAIAAoAhQgCCAJa2o2AiwLIAMgACgCGEEBajYCDCAAIANBDGogAEEsahCgASgCADYCLCAALQAwQQhxBEAgACAAQSBqECMiAiACIAQgBWtqIAAoAiwQsgELIAAgAcAQwgMMAQsgARC2AwsgA0EQaiQAC5YBACAAKAIYIAAoAixLBEAgACAAKAIYNgIsCwJAIAAoAgggACgCDE8NACABQX9GBEAgACAAKAIIIAAoAgxBAWsgACgCLBCyASABELYDDwsgAC0AMEEQcUUEQCAAKAIMQQFrLQAAIAFB/wFxRw0BCyAAIAAoAgggACgCDEEBayAAKAIsELIBIAAoAgwgAcA6AAAgAQ8LQX8LZQAgACgCGCAAKAIsSwRAIAAgACgCGDYCLAsCQCAALQAwQQhxRQ0AIAAoAhAgACgCLEkEQCAAIAAoAgggACgCDCAAKAIsELIBCyAAKAIMIAAoAhBPDQAgACgCDCwAABCjAQ8LQX8LBwAgACgCDAsHACAAKAIICxMAIAAgACgCAEEMaygCAGoQjgILCgAgAEEIaxCOAgsTACAAIAAoAgBBDGsoAgBqENgBCwoAIABBCGsQ2AELEwAgACAAKAIAQQxrKAIAahDBAwsTACAAIAAoAgBBDGsoAgBqEI8CCxMAIAAgACgCAEEMaygCAGoQxgMLEwAgACAAKAIAQQxrKAIAahCQAguuAQEEfyMAQRBrIgUkAANAAkAgAiAETA0AIAAoAhgiAyAAKAIcIgZPBEAgACABLAAAEKMBIAAoAgAoAjQRBABBf0YNASAEQQFqIQQgAUEBaiEBBSAFIAYgA2s2AgwgBSACIARrNgIIIAVBDGogBUEIahCRAiEDIAAoAhggASADKAIAIgMQTSAAIAMgACgCGGo2AhggAyAEaiEEIAEgA2ohAQsMAQsLIAVBEGokACAECy8AIAAgACgCACgCJBEAAEF/RgRAQX8PCyAAIAAoAgwiAEEBajYCDCAALAAAEKMBCwQAQX8LvQEBBH8jAEEQayIEJAADQAJAIAIgBUwNAAJAIAAoAgwiAyAAKAIQIgZJBEAgBEH/////BzYCDCAEIAYgA2s2AgggBCACIAVrNgIEIARBDGogBEEIaiAEQQRqEJECEJECIQMgASAAKAIMIAMoAgAiAxBNIAAgACgCDCADajYCDAwBCyAAIAAoAgAoAigRAAAiA0F/Rg0BIAEgA8A6AABBASEDCyABIANqIQEgAyAFaiEFDAELCyAEQRBqJAAgBQsJACAAQn8QkgILCQAgAEJ/EJICCwQAIAALDAAgABCUAhogABAtCwwAIAAoAjwQFRDdAQs7AQF/IAAoAjwjAEEQayIAJAAgASACQf8BcSAAQQhqEBYQ3QEhAiAAKQMIIQEgAEEQaiQAQn8gASACGwspACABIAEoAgBBB2pBeHEiAUEQajYCACAAIAEpAwAgASkDCBCVAjkDAAu5FwMSfwF8A34jAEGwBGsiCyQAIAtBADYCLAJAIAG9IhlCAFMEQEEBIRBB+AghFCABmiIBvSEZDAELIARBgBBxBEBBASEQQfsIIRQMAQtB/ghB+QggBEEBcSIQGyEUIBBFIRcLAkAgGUKAgICAgICA+P8Ag0KAgICAgICA+P8AUQRAIABBICACIBBBA2oiBiAEQf//e3EQRSAAIBQgEBBCIABB5g1ByhUgBUEgcSIDG0G8EEH0FSADGyABIAFiG0EDEEIgAEEgIAIgBiAEQYDAAHMQRSACIAYgAiAGShshDQwBCyALQRBqIRECQAJAAkAgASALQSxqENIDIgEgAaAiAUQAAAAAAAAAAGIEQCALIAsoAiwiBkEBazYCLCAFQSByIhVB4QBHDQEMAwsgBUEgciIVQeEARg0CIAsoAiwhDAwBCyALIAZBHWsiDDYCLCABRAAAAAAAALBBoiEBC0EGIAMgA0EASBshCiALQTBqQaACQQAgDEEAThtqIg4hBwNAIAcgAfwDIgM2AgAgB0EEaiEHIAEgA7ihRAAAAABlzc1BoiIBRAAAAAAAAAAAYg0ACwJAIAxBAEwEQCAMIQkgByEGIA4hCAwBCyAOIQggDCEJA0BBHSAJIAlBHU8bIQMCQCAHQQRrIgYgCEkNACADrSEbQgAhGQNAIAYgBjUCACAbhiAZfCIaIBpCgJTr3AOAIhlCgJTr3AN+fT4CACAGQQRrIgYgCE8NAAsgGkKAlOvcA1QNACAIQQRrIgggGT4CAAsDQCAIIAciBkkEQCAGQQRrIgcoAgBFDQELCyALIAsoAiwgA2siCTYCLCAGIQcgCUEASg0ACwsgCUEASARAIApBGWpBCW5BAWohEiAVQeYARiETA0BBCUEAIAlrIgMgA0EJTxshDQJAIAYgCE0EQEEAQQQgCCgCABshBwwBC0GAlOvcAyANdiEWQX8gDXRBf3MhD0EAIQkgCCEHA0AgByAHKAIAIgMgDXYgCWo2AgAgAyAPcSAWbCEJIAdBBGoiByAGSQ0AC0EAQQQgCCgCABshByAJRQ0AIAYgCTYCACAGQQRqIQYLIAsgCygCLCANaiIJNgIsIA4gByAIaiIIIBMbIgMgEkECdGogBiAGIANrQQJ1IBJKGyEGIAlBAEgNAAsLQQAhCQJAIAYgCE0NACAOIAhrQQJ1QQlsIQlBCiEHIAgoAgAiA0EKSQ0AA0AgCUEBaiEJIAMgB0EKbCIHTw0ACwsgCiAJQQAgFUHmAEcbayAVQecARiAKQQBHcWsiAyAGIA5rQQJ1QQlsQQlrSARAIAtBMGpBhGBBpGIgDEEASBtqIANBgMgAaiIMQQltIgNBAnRqIQ1BCiEHIAwgA0EJbGsiA0EHTARAA0AgB0EKbCEHIANBAWoiA0EIRw0ACwsCQCANKAIAIgwgDCAHbiISIAdsayIPRSANQQRqIgMgBkZxDQACQCASQQFxRQRARAAAAAAAAEBDIQEgB0GAlOvcA0cgCCANT3INASANQQRrLQAAQQFxRQ0BC0QBAAAAAABAQyEBC0QAAAAAAADgP0QAAAAAAADwP0QAAAAAAAD4PyADIAZGG0QAAAAAAAD4PyAPIAdBAXYiA0YbIAMgD0sbIRgCQCAXDQAgFC0AAEEtRw0AIBiaIRggAZohAQsgDSAMIA9rIgM2AgAgASAYoCABYQ0AIA0gAyAHaiIDNgIAIANBgJTr3ANPBEADQCANQQA2AgAgCCANQQRrIg1LBEAgCEEEayIIQQA2AgALIA0gDSgCAEEBaiIDNgIAIANB/5Pr3ANLDQALCyAOIAhrQQJ1QQlsIQlBCiEHIAgoAgAiA0EKSQ0AA0AgCUEBaiEJIAMgB0EKbCIHTw0ACwsgDUEEaiIDIAYgAyAGSRshBgsDQCAGIgwgCE0iB0UEQCAGQQRrIgYoAgBFDQELCwJAIBVB5wBHBEAgBEEIcSETDAELIAlBf3NBfyAKQQEgChsiBiAJSiAJQXtKcSIDGyAGaiEKQX9BfiADGyAFaiEFIARBCHEiEw0AQXchBgJAIAcNACAMQQRrKAIAIg9FDQBBCiEDQQAhBiAPQQpwDQADQCAGIgdBAWohBiAPIANBCmwiA3BFDQALIAdBf3MhBgsgDCAOa0ECdUEJbCEDIAVBX3FBxgBGBEBBACETIAogAyAGakEJayIDQQAgA0EAShsiAyADIApKGyEKDAELQQAhEyAKIAMgCWogBmpBCWsiA0EAIANBAEobIgMgAyAKShshCgtBfyENIApB/f///wdB/v///wcgCiATciIPG0oNASAKIA9BAEdqQQFqIRYCQCAFQV9xIgdBxgBGBEAgCSAWQf////8Hc0oNAyAJQQAgCUEAShshBgwBCyARIAkgCUEfdSIDcyADa60gERCmASIGa0EBTARAA0AgBkEBayIGQTA6AAAgESAGa0ECSA0ACwsgBkECayISIAU6AAAgBkEBa0EtQSsgCUEASBs6AAAgESASayIGIBZB/////wdzSg0CCyAGIBZqIgMgEEH/////B3NKDQEgAEEgIAIgAyAQaiIJIAQQRSAAIBQgEBBCIABBMCACIAkgBEGAgARzEEUCQAJAAkAgB0HGAEYEQCALQRBqQQlyIQUgDiAIIAggDksbIgMhCANAIAg1AgAgBRCmASEGAkAgAyAIRwRAIAYgC0EQak0NAQNAIAZBAWsiBkEwOgAAIAYgC0EQaksNAAsMAQsgBSAGRw0AIAZBAWsiBkEwOgAACyAAIAYgBSAGaxBCIAhBBGoiCCAOTQ0ACyAPBEAgAEHrG0EBEEILIApBAEwgCCAMT3INAQNAIAg1AgAgBRCmASIGIAtBEGpLBEADQCAGQQFrIgZBMDoAACAGIAtBEGpLDQALCyAAIAZBCSAKIApBCU4bEEIgCkEJayEGIAhBBGoiCCAMTw0DIApBCUogBiEKDQALDAILAkAgCkEASA0AIAwgCEEEaiAIIAxJGyEDIAtBEGpBCXIhDCAIIQcDQCAMIAc1AgAgDBCmASIGRgRAIAZBAWsiBkEwOgAACwJAIAcgCEcEQCAGIAtBEGpNDQEDQCAGQQFrIgZBMDoAACAGIAtBEGpLDQALDAELIAAgBkEBEEIgBkEBaiEGIAogE3JFDQAgAEHrG0EBEEILIAAgBiAMIAZrIgUgCiAFIApIGxBCIAogBWshCiAHQQRqIgcgA08NASAKQQBODQALCyAAQTAgCkESakESQQAQRSAAIBIgESASaxBCDAILIAohBgsgAEEwIAZBCWpBCUEAEEULIABBICACIAkgBEGAwABzEEUgAiAJIAIgCUobIQ0MAQsgFCAFQRp0QR91QQlxaiEJAkAgA0ELSw0AQQwgA2shBkQAAAAAAAAwQCEYA0AgGEQAAAAAAAAwQKIhGCAGQQFrIgYNAAsgCS0AAEEtRgRAIBggAZogGKGgmiEBDAELIAEgGKAgGKEhAQsgESALKAIsIgcgB0EfdSIGcyAGa60gERCmASIGRgRAIAZBAWsiBkEwOgAAIAsoAiwhBwsgEEECciEKIAVBIHEhDCAGQQJrIg4gBUEPajoAACAGQQFrQS1BKyAHQQBIGzoAACAEQQhxRSADQQBMcSEIIAtBEGohBwNAIAciBSAB/AIiBkGA9QBqLQAAIAxyOgAAIAEgBrehRAAAAAAAADBAoiIBRAAAAAAAAAAAYSAIcSAHQQFqIgcgC0EQamtBAUdyRQRAIAVBLjoAASAFQQJqIQcLIAFEAAAAAAAAAABiDQALQX8hDSADQf3///8HIAogESAOayIIaiIGa0oNACAAQSAgAiAGIANBAmogByALQRBqIgVrIgcgB0ECayADSBsgByADGyIDaiIGIAQQRSAAIAkgChBCIABBMCACIAYgBEGAgARzEEUgACAFIAcQQiAAQTAgAyAHa0EAQQAQRSAAIA4gCBBCIABBICACIAYgBEGAwABzEEUgAiAGIAIgBkobIQ0LIAtBsARqJAAgDQsEAEIAC9YCAQd/IwBBIGsiAyQAIAMgACgCHCIENgIQIAAoAhQhBSADIAI2AhwgAyABNgIYIAMgBSAEayIBNgIUIAEgAmohBSADQRBqIQFBAiEHAn8CQAJAAkAgACgCPCABQQIgA0EMahAKEN0BBEAgASEEDAELA0AgBSADKAIMIgZGDQIgBkEASARAIAEhBAwECyABQQhBACAGIAEoAgQiCEsiCRtqIgQgBiAIQQAgCRtrIgggBCgCAGo2AgAgAUEMQQQgCRtqIgEgASgCACAIazYCACAFIAZrIQUgACgCPCAEIgEgByAJayIHIANBDGoQChDdAUUNAAsLIAVBf0cNAQsgACAAKAIsIgE2AhwgACABNgIUIAAgASAAKAIwajYCECACDAELIABBADYCHCAAQgA3AxAgACAAKAIAQSByNgIAQQAgB0ECRg0AGiACIAQoAgRrCyADQSBqJAALiQIBA38jAEEQayIAJAACQCAAQQxqIABBCGoQFA0AQYDuASAAKAIMQQJ0QQRqEDQiATYCACABRQ0AIAAoAggQNCIBBEBBgO4BKAIAIgIgACgCDEECdGpBADYCACACIAEQE0UNAQtBgO4BQQA2AgALIABBEGokAEGU4AFBADYCAEGQ4AFBATYCABCQA0GU4AFBsOABKAIANgIAQbDgAUGQ4AE2AgBBtOABQS42AgBBuOABQQA2AgAQnAJBuOABQbDgASgCADYCAEGw4AFBtOABNgIAQdzhAUHk4AE2AgBBtOEBQYCABDYCAEGw4QFB8P4FNgIAQZThAUEqNgIAQbjhAUG43QEoAgA2AgALC8jAASoAQYAIC4QYbG9hZF9zcHoAaW5maW5pdHkARmVicnVhcnkASmFudWFyeQBKdWx5AFRodXJzZGF5AFR1ZXNkYXkAV2VkbmVzZGF5AFNhdHVyZGF5AFN1bmRheQBNb25kYXkARnJpZGF5AE1heQAlbS8lZC8leQAtKyAgIDBYMHgALTBYKzBYIDBYLTB4KzB4IDB4AE5vdgBUaHUAQXVndXN0AHVuc2lnbmVkIHNob3J0AHVuc2lnbmVkIGludABpbnZhbGlkIGxpdGVyYWwvbGVuZ3RocyBzZXQAaW52YWxpZCBjb2RlIGxlbmd0aHMgc2V0AHVua25vd24gaGVhZGVyIGZsYWdzIHNldABpbnZhbGlkIGRpc3RhbmNlcyBzZXQAZ2V0AE9jdABmbG9hdABpbnZhbGlkIGJpdCBsZW5ndGggcmVwZWF0AFNhdABudW1Qb2ludHMAY29sb3JzAFVucGFja09wdGlvbnMAcG9zaXRpb25zAHJvdGF0aW9ucwB0b28gbWFueSBsZW5ndGggb3IgZGlzdGFuY2Ugc3ltYm9scwBpbnZhbGlkIHN0b3JlZCBibG9jayBsZW5ndGhzAHNjYWxlcwBhbHBoYXMAW1NQWjogRVJST1JdIENoZWNrIGZhaWxlZDogJXM6JWQ6ICVzAHZmMzJfcHRyAEFwcgB2ZWN0b3IAbW9uZXlfZ2V0IGVycm9yAFtTUFogRVJST1JdIGRlc2VyaWFsaXplUGFja2VkR2F1c3NpYW5zOiByZWFkIGVycm9yAE9jdG9iZXIATm92ZW1iZXIAU2VwdGVtYmVyAERlY2VtYmVyAHVuc2lnbmVkIGNoYXIAaW9zX2Jhc2U6OmNsZWFyAE1hcgAvZW1zZGsvZW1zY3JpcHRlbi9zeXN0ZW0vbGliL2xpYmN4eGFiaS9zcmMvcHJpdmF0ZV90eXBlaW5mby5jcHAAU2VwACVJOiVNOiVTICVwAFN1bgBKdW4ATW9uAG5hbgBKYW4AY29vcmRpbmF0ZVN5c3RlbQBDb29yZGluYXRlU3lzdGVtAEp1bABib29sAGxsAEFwcmlsAGludmFsaWQgY29kZSAtLSBtaXNzaW5nIGVuZC1vZi1ibG9jawBpbmNvcnJlY3QgaGVhZGVyIGNoZWNrAGluY29ycmVjdCBsZW5ndGggY2hlY2sAaW5jb3JyZWN0IGRhdGEgY2hlY2sAcHVzaF9iYWNrAGludmFsaWQgZGlzdGFuY2UgdG9vIGZhciBiYWNrAEZyaQBzaABoZWFkZXIgY3JjIG1pc21hdGNoAE1hcmNoAEF1ZwB1bnNpZ25lZCBsb25nIGxvbmcAdW5zaWduZWQgbG9uZwBzdGQ6OndzdHJpbmcAYmFzaWNfc3RyaW5nAHN0ZDo6c3RyaW5nAHN0ZDo6dTE2c3RyaW5nAHN0ZDo6dTMyc3RyaW5nAGluZgAlLjBMZgAlTGYAcmVzaXplAGludmFsaWQgd2luZG93IHNpemUAdHJ1ZQBUdWUAZmFsc2UAaW52YWxpZCBibG9jayB0eXBlAEp1bmUAZG91YmxlAHNoRGVncmVlAGJhZF9hcnJheV9uZXdfbGVuZ3RoIHdhcyB0aHJvd24gaW4gLWZuby1leGNlcHRpb25zIG1vZGUAaW52YWxpZCBsaXRlcmFsL2xlbmd0aCBjb2RlAGludmFsaWQgZGlzdGFuY2UgY29kZQBSYXdHYXVzc2lhbkNsb3VkAHVua25vd24gY29tcHJlc3Npb24gbWV0aG9kAFtTUFogRVJST1JdIGRlc2VyaWFsaXplUGFja2VkR2F1c3NpYW5zOiBoZWFkZXIgbm90IGZvdW5kACUwKmxsZAAlKmxsZAArJWxsZAAlKy40bGQAdm9pZABsb2NhbGUgbm90IHN1cHBvcnRlZABhbnRpYWxpYXNlZABXZWQAJVktJW0tJWQAW1NQWiBFUlJPUl0gZGVzZXJpYWxpemVQYWNrZWRHYXVzc2lhbnM6IFRvbyBtYW55IHBvaW50czogJWQAW1NQWiBFUlJPUl0gZGVzZXJpYWxpemVQYWNrZWRHYXVzc2lhbnM6IFVuc3VwcG9ydGVkIFNIIGRlZ3JlZTogJWQAW1NQWiBFUlJPUl0gZGVzZXJpYWxpemVQYWNrZWRHYXVzc2lhbnM6IHZlcnNpb24gbm90IHN1cHBvcnRlZDogJWQARGVjAC4vc3B6L3NyYy9jYy9sb2FkLXNwei5jYwBGZWIAJWEgJWIgJWQgJUg6JU06JVMgJVkAUE9TSVgAVmVjdG9yVUludDhUACVIOiVNOiVTAE5BTgBQTQBBTQAlSDolTQBMQ19BTEwAQVNDSUkATEFORwBSVUYATFVGAElORgBSREYATERGAFVOU1BFQ0lGSUVEAEMAUlVCAExVQgBSREIATERCAGNhdGNoaW5nIGEgY2xhc3Mgd2l0aG91dCBhbiBvYmplY3Q/AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHNob3J0PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBzaG9ydD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8aW50PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBpbnQ+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGZsb2F0PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1aW50OF90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxpbnQ4X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVpbnQxNl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxpbnQxNl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1aW50NjRfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8aW50NjRfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dWludDMyX3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludDMyX3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGNoYXI+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVuc2lnbmVkIGNoYXI+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHNpZ25lZCBjaGFyPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxsb25nPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBsb25nPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxkb3VibGU+ADAxMjM0NTY3ODkAQy5VVEYtOABWZWN0b3JGbG9hdDMyADEuMy4xAC4ALQAocGFja2VkLmFscGhhcy5zaXplKCkpID09IChudW1Qb2ludHMpAChudWxsKQAocGFja2VkLmNvbG9ycy5zaXplKCkpID09IChudW1Qb2ludHMgKiAzKQAocGFja2VkLnNjYWxlcy5zaXplKCkpID09IChudW1Qb2ludHMgKiAzKQAocGFja2VkLnNoLnNpemUoKSkgPT0gKG51bVBvaW50cyAqIHNoRGltICogMykAKHBhY2tlZC5yb3RhdGlvbnMuc2l6ZSgpKSA9PSAobnVtUG9pbnRzICogKHBhY2tlZC51c2VzUXVhdGVybmlvblNtYWxsZXN0VGhyZWUgPyA0IDogMykpAChwYWNrZWQucG9zaXRpb25zLnNpemUoKSkgPT0gKG51bVBvaW50cyAqIDMgKiAodXNlc0Zsb2F0MTYgPyAyIDogMykpACUAbGVuZ3RoX2Vycm9yIHdhcyB0aHJvd24gaW4gLWZuby1leGNlcHRpb25zIG1vZGUgd2l0aCBtZXNzYWdlICIlcyIAUHVyZSB2aXJ0dWFsIGZ1bmN0aW9uIGNhbGxlZCEAW1NQWjogRVJST1JdIFVuc3VwcG9ydGVkIFNIIGRlZ3JlZTogJWQKAAkAAAAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwBBkCALthMgEAAA9GwAAPRsAABAEAAAqG0AACgQAABOM3NwejEzR2F1c3NpYW5DbG91ZEUAAACobQAASBAAAE4zc3B6MTNVbnBhY2tPcHRpb25zRQBwcGlpcAD0bAAAbBAAAKhtAAB0EAAATlN0M19fMjZ2ZWN0b3JJZk5TXzlhbGxvY2F0b3JJZkVFRUUAaXBwACxuAADEEAAAAAAAAAMAAADcEAAAAAAAACgSAAAAAAAAWBIAAAAAAABOU3QzX18yOG9wdGlvbmFsSWZFRQAAAADQbQAA6BAAABgRAABOU3QzX18yMjdfX29wdGlvbmFsX21vdmVfYXNzaWduX2Jhc2VJZkxiMUVFRQAAAADQbQAAJBEAAFQRAABOU3QzX18yMjdfX29wdGlvbmFsX2NvcHlfYXNzaWduX2Jhc2VJZkxiMUVFRQAAAADQbQAAYBEAAIgRAABOU3QzX18yMjBfX29wdGlvbmFsX21vdmVfYmFzZUlmTGIxRUVFAAAA0G0AAJQRAAC8EQAATlN0M19fMjIwX19vcHRpb25hbF9jb3B5X2Jhc2VJZkxiMUVFRQAAANBtAADIEQAA9BEAAE5TdDNfXzIyM19fb3B0aW9uYWxfc3RvcmFnZV9iYXNlSWZMYjBFRUUAAAAAqG0AAPwRAABOU3QzX18yMjRfX29wdGlvbmFsX2Rlc3RydWN0X2Jhc2VJZkxiMUVFRQAAAKhtAAAwEgAATlN0M19fMjE4X19zZmluYWVfY3Rvcl9iYXNlSUxiMUVMYjFFRUUAAKhtAABgEgAATlN0M19fMjIwX19zZmluYWVfYXNzaWduX2Jhc2VJTGIxRUxiMUVFRQAAAACIbgAAnBIAAAAAAABsEAAAUE5TdDNfXzI2dmVjdG9ySWZOU185YWxsb2NhdG9ySWZFRUVFAAAAAIhuAADUEgAAAQAAAGwQAABQS05TdDNfXzI2dmVjdG9ySWZOU185YWxsb2NhdG9ySWZFRUVFAHBwAHYAdnAAAACMEgAAcHAAAJRsAACMEgAAPG0AAHZwcGQAAAAAlGwAAIwSAAAYbQAAPG0AAHZwcHBkAAAAGG0AAMQSAABwcHAATBMAADxtAACobQAAVBMAAE4xMGVtc2NyaXB0ZW4zdmFsRQAAnBAAAGwQAAAYbQAAcHBwcAAAAAAAAAAArGwAAGwQAAAYbQAAPG0AAGlwcHBkAAAALG4AAMATAAAAAAAAAwAAANgTAAAAAAAAKBIAAAAAAABYEgAAAAAAAE5TdDNfXzI4b3B0aW9uYWxJaEVFAAAAANBtAADkEwAAFBQAAE5TdDNfXzIyN19fb3B0aW9uYWxfbW92ZV9hc3NpZ25fYmFzZUloTGIxRUVFAAAAANBtAAAgFAAAUBQAAE5TdDNfXzIyN19fb3B0aW9uYWxfY29weV9hc3NpZ25fYmFzZUloTGIxRUVFAAAAANBtAABcFAAAhBQAAE5TdDNfXzIyMF9fb3B0aW9uYWxfbW92ZV9iYXNlSWhMYjFFRUUAAADQbQAAkBQAALgUAABOU3QzX18yMjBfX29wdGlvbmFsX2NvcHlfYmFzZUloTGIxRUVFAAAA0G0AAMQUAADwFAAATlN0M19fMjIzX19vcHRpb25hbF9zdG9yYWdlX2Jhc2VJaExiMEVFRQAAAACobQAA+BQAAE5TdDNfXzIyNF9fb3B0aW9uYWxfZGVzdHJ1Y3RfYmFzZUloTGIxRUVFAAAAqG0AACwVAABOU3QzX18yNnZlY3RvckloTlNfOWFsbG9jYXRvckloRUVFRQCIbgAAYBUAAAAAAAAkFQAAUE5TdDNfXzI2dmVjdG9ySWhOU185YWxsb2NhdG9ySWhFRUVFAAAAAIhuAACYFQAAAQAAACQVAABQS05TdDNfXzI2dmVjdG9ySWhOU185YWxsb2NhdG9ySWhFRUVFAHBwAHZwAFAVAABwcAAAlGwAAFAVAADEbAAAdnBwaQAAAACUbAAAUBUAABhtAADEbAAAdnBwcGkAAAAYbQAAiBUAAHBwcABMEwAAxGwAAJgTAAAkFQAAGG0AAHBwcHAAAAAArGwAACQVAAAYbQAAxGwAAGlwcHBpAHAAdnAAaXBwAHZwcGkAaXBwAHZwcGkAcHBwAHZwcHAAAABcbQAAYBYAAE4zc3B6MTZDb29yZGluYXRlU3lzdGVtRQBwAHZwAGlwcAB2cHBpAAAAAAAAAwAAAAgAAAAPAAAAqG0AAKAWAABOU3QzX18yMTJiYXNpY19zdHJpbmdJY05TXzExY2hhcl90cmFpdHNJY0VFTlNfOWFsbG9jYXRvckljRUVFRQAAqG0AAOgWAABOU3QzX18yMTJiYXNpY19zdHJpbmdJd05TXzExY2hhcl90cmFpdHNJd0VFTlNfOWFsbG9jYXRvckl3RUVFRQAAqG0AADAXAABOU3QzX18yMTJiYXNpY19zdHJpbmdJRHNOU18xMWNoYXJfdHJhaXRzSURzRUVOU185YWxsb2NhdG9ySURzRUVFRQAAAKhtAAB8FwAATlN0M19fMjEyYmFzaWNfc3RyaW5nSURpTlNfMTFjaGFyX3RyYWl0c0lEaUVFTlNfOWFsbG9jYXRvcklEaUVFRUUAAACobQAAyBcAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWNFRQAAqG0AAPAXAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lhRUUAAKhtAAAYGAAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJaEVFAACobQAAQBgAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SXNFRQAAqG0AAGgYAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0l0RUUAAKhtAACQGAAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJaUVFAACobQAAuBgAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWpFRQAAqG0AAOAYAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lsRUUAAKhtAAAIGQAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJbUVFAACobQAAMBkAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SXhFRQAAqG0AAFgZAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0l5RUUAAKhtAACAGQAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJZkVFAACobQAAqBkAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWRFRQBB1DMLoSiWMAd3LGEO7rpRCZkZxG0Hj/RqcDWlY+mjlWSeMojbDqS43Hke6dXgiNnSlytMtgm9fLF+By2455Edv5BkELcd8iCwakhxufPeQb6EfdTaGuvk3W1RtdT0x4XTg1aYbBPAqGtkevli/ezJZYpPXAEU2WwGY2M9D/r1DQiNyCBuO14QaUzkQWDVcnFnotHkAzxH1ARL/YUN0mu1CqX6qLU1bJiyQtbJu9tA+bys42zYMnVc30XPDdbcWT3Rq6ww2SY6AN5RgFHXyBZh0L+19LQhI8SzVpmVus8Ppb24nrgCKAiIBV+y2QzGJOkLsYd8by8RTGhYqx1hwT0tZraQQdx2BnHbAbwg0pgqENXviYWxcR+1tgal5L+fM9S46KLJB3g0+QAPjqgJlhiYDuG7DWp/LT1tCJdsZJEBXGPm9FFra2JhbBzYMGWFTgBi8u2VBmx7pQEbwfQIglfED/XG2bBlUOm3Euq4vot8iLn83x3dYkkt2hXzfNOMZUzU+1hhsk3OUbU6dAC8o+Iwu9RBpd9K15XYPW3E0aT79NbTaulpQ/zZbjRGiGet0Lhg2nMtBETlHQMzX0wKqsl8Dd08cQVQqkECJxAQC76GIAzJJbVoV7OFbyAJ1Ga5n+Rhzg753l6YydkpIpjQsLSo18cXPbNZgQ20LjtcvbetbLrAIIO47bazv5oM4rYDmtKxdDlH1eqvd9KdFSbbBIMW3HMSC2PjhDtklD5qbQ2oWmp6C88O5J3/CZMnrgAKsZ4HfUSTD/DSowiHaPIBHv7CBmldV2L3y2dlgHE2bBnnBmtudhvU/uAr04laetoQzErdZ2/fufn5776OQ763F9WOsGDoo9bWfpPRocTC2DhS8t9P8We70WdXvKbdBrU/SzaySNorDdhMGwqv9koDNmB6BEHD72DfVd9nqO+ObjF5vmlGjLNhyxqDZryg0m8lNuJoUpV3DMwDRwu7uRYCIi8mBVW+O7rFKAu9spJatCsEarNcp//XwjHP0LWLntksHa7eW7DCZJsm8mPsnKNqdQqTbQKpBgmcPzYO64VnB3ITVwAFgkq/lRR6uOKuK7F7OBu2DJuO0pINvtXlt+/cfCHf2wvU0tOGQuLU8fiz3Whug9ofzRa+gVsmufbhd7Bvd0e3GOZaCIhwag//yjsGZlwLARH/nmWPaa5i+NP/a2FFz2wWeOIKoO7SDddUgwROwrMDOWEmZ6f3FmDQTUdpSdt3bj5KatGu3FrW2WYL30DwO9g3U668qcWeu95/z7JH6f+1MBzyvb2KwrrKMJOzU6ajtCQFNtC6kwbXzSlX3lS/Z9kjLnpms7hKYcQCG2hdlCtvKje+C7ShjgzDG98FWo3vAi0AAAAARjtnZYx2zsrKTamvWevtTh/QiivVnSOEk6ZE4bLW25307bz4PqAVV3ibcjLrPTbTrQZRtmdL+BkhcJ98JavG4GOQoYWp3Qgq7+ZvT3xAK646e0zL8DblZLYNggGXfR190UZ6GBsL07ddMLTSzpbwM4itl1ZC4D75BNtZnAtQ/BpNa5t/hyYy0MEdVbVSuxFUFIB2Md7N356Y9rj7uYYnh/+9QOI18OlNc8uOKOBtysmmVq2sbBsEAyogY2Yu+zr6aMBdn6KN9DDktpNVdxDXtDErsNH7Zhl+vV1+G5wt4WfaFoYCEFsvrVZgSMjFxgwpg/1rTEmwwuMPi6WGFqD4NVCbn1Ca1jb/3O1Rmk9LFXsJcHIewz3bsYUGvNSkdiOo4k1EzSgA7WJuO4oH/Z3O5rumqYNx6wAsN9BnSTMLPtV1MFmwv33wH/lGl3pq4NObLNu0/uaWHVGgrXo0gd3lSMfmgi0NqyuCS5BM59g2CAaeDW9jVEDGzBJ7oakd8AQvW8tjSpGGyuXXva2ARBvpYQIgjgTIbSerjlZAzq8m37LpHbjXI1AReGVrdh32zTL8sPZVmXq7/DY8gJtTOFvCz35gpaq0LQwF8hZrYGGwL4Eni0jk7cbhS6v9hi6KjRlSzLZ+Nwb715hAwLD902b0HJVdk3lfEDrWGStdsyxA8Wtqe5YOoDY/oeYNWMR1qxwlM5B7QPnd0u+/5rWKnpYq9titTZMS4OQ8VNuDWcd9x7iBRqDdSwsJcg0wbhcJ6zeLT9BQ7oWd+UHDpp4kUADaxRY7vaDcdhQPmk1zars97Bb9BotzN0si3HFwRbni1gFYpO1mPW6gz5Iom6j3JxANcWErahSrZsO77V2k3n774D84wIda8o0u9bS2SZCVxtbs0/2xiRmwGCZfi39DzC07oooWXMdAW/VoBmCSDQK7y5FEgKz0js0FW8j2Yj5bUCbfHWtButcm6BWRHY9wsG0QDPZWd2k8G97GeiC5o+mG/UKvvZonZfAziCPLVO064AlefNtuO7aWx5TwraDxYwvkECUwg3XvfSraqUZNv4g20sPODbWmBEAcCUJ7e2zR3T+Nl+ZY6F2r8UcbkJYiH0vPvllwqNuTPQF01QZmEUagIvAAm0WVytbsOozti1+tnRQj66ZzRiHr2uln0L2M9Hb5bbJNngh4ADenPjtQwjGw9UR3i5IhvcY7jvv9XOtoWxgKLmB/b+Qt1sCiFrGlg2Yu2cVdSbwPEOATSSuHdtqNw5ectqTyVvsNXRDAajgUGzOkUiBUwZht/W7eVpoLTfDe6gvLuY/BhhAgh713RabN6Dng9o9cKrsm82yAQZb/JgV3uR1iEnNQy701a6zYAAAAAFiA4tfxBrR0qYZWo+INaOm6jYo+EwvcnUuLPkqFHaEJ3Z1D3nQbFX0sm/eqZxDJ4D+QKzeWFn2UzpafQwo7QhNSu6DE+z32Z6O9FLDoNir6sLbILRkwno5BsHxZjybjGtemAc1+IFduJqC1uW0ri/M1q2kknC0/h8St3VAUdoQmTPZm8eVwMFK98NKF9nvsz677DhgHfVi7X/26bJFrJS/J68f4YG2RWzjtc4xzZk3GK+avEYJg+bLa4BtlHk3GNUbNJOLvS3JBt8uQlvxArtykwEwLDUYaqFXG+H+bUGc8w9CF62pW00gy1jGfeV0P1SHd7QKIW7uh0NtZdijsCE1wbOqa2eq8OYFqXu7K4WCkkmGCczvn1NBjZzYHrfGpRPVxS5Nc9x0wBHf/50/8wa0XfCN6vvp12eZ6lw4i10peeleoidPR/iqLURz9wNoit5hawGAx3JbDaVx0FKfK61f/SgmAVsxfIw5MvfRFx4O+HUdhabTBN8rsQdUdPJqMa2QabrzNnDgflRzayN6X5IKGFwZVL5FQ9ncRsiG5hy1i4QfPtUiBmRYQAXvBW4pFiwMKp1yqjPH/8gwTKDahznhuISyvx6d6DJ8nmNvUrKaRjCxERiWqEuV9KvAys7xvces8jaZCutsFGjo50lGxB5gJMeVPoLez7Pg3UTtQ2BGaCFjzTaHepe75Xkc5stV5c+pVm6RD080HG1Mv0NXFsJONRVJEJMME53xD5jA3yNh6b0g6rcbObA6eTo7ZWuNTiQJjsV6r5ef982UFKrjuO2Dgbtm3SeiPFBFobcPf/vKAh34QVy74RvR2eKQjPfOaaWVzeL7M9S4dlHXMykSulbwcLndrtaghyO0owx+mo/1V/iMfglelSSEPJav2wbM0tZkz1mIwtYDBaDViFiO+XFx7Pr6L0rjoKIo4Cv9OldevFhU1eL+TY9vnE4EMrJi/RvQYXZFdngsyBR7p5cuIdqaTCJRxOo7C0mIOIAUphR5PcQX8mNiDqjuAA0jseDQZ1yC0+wCJMq2j0bJPdJo5cT7CuZPpaz/FSjO/J539KbjepalaCQwvDKpUr+59HyTQN0ekMuDuImRDtqKGlHIPW8Qqj7kTgwnvsNuJDWeQAjMtyILR+mEEh1k5hGWO9xL6za+SGBoGFE65XpSsbhUfkiRNn3Dz5BkmULyZxIdsQp3xNMJ/Jp1EKYXFxMtSjk/1GNbPF89/SUFsJ8mju+lfPPix394vGFmIjEDZalsLUlQRU9K2xvpU4GWi1AKyZnnf4j75PTWXf2uWz/+JQYR0twvc9FXcdXIDfy3y4ajjZH7ru+ScPBJiyp9K4ihIAWkWAlnp9NXwb6J2qO9AoQAAAADhtlLvg2vUBWLdhuoG16gL52H65IW8fA5kCi7hDK5RF+0YA/iPxYUSbnPX/Qp5+Rzrz6vziRItGWikf/YYXKMu+erxwZs3dyt6gSXEHosLJf89Wcqd4N8gfFaNzxTy8jn1RKDWl5kmPHYvdNMSJVoy85MI3ZFOjjdw+NzYMLhGXdEOFLKz05JYUmXAtzZv7lbX2by5tQQ6U1SyaLw8FhdK3aBFpb99w09ey5GgOsG/Qdt37a65qmtEWBw5qyjk5XPJUrecq48xdko5Y5kuM014z4Ufl61YmX1M7suSJEq0ZMX85ounIWBhRpcyjiKdHG/DK06AofbIakBAmoVgcI26gcbfVeMbWb8CrQtQZqclsYcRd17lzPG0BHqjW2ze3K2NaI5C77UIqA4DWkdqCXSmi78mSelioKMI1PJMeCwulJmafHv7R/qRGvGofn77hp+fTdRw/ZBSmhwmAHV0gn+DlTQtbPfpq4YWX/lpclXXiJPjhWfxPgONEIhRYlDIy+exfpkI06Mf4jIVTQ1WH2Pst6kxA9V0t+k0wuUGXGaa8L3QyB/fDU71PrscGlqxMvu7B2AU2drm/jhstBFIlGjJqSI6Jsv/vMwqSe4jTkPAwq/1ki3NKBTHLJ5GKEQ6Od6ljGsxx1Ht2ybnvzRC7ZHVo1vDOsGGRdAgMBc/geZrrmBQOUECjb+r4zvtRIcxw6Vmh5FKBFoXoOXsRU+NSDq5bP5oVg4j7rzvlbxTi5+SsmopwF0I9Ea36UIUWJm6yIB4DJpvGtEchftnTmqfbWCLftsyZBwGtI79sOZhlRSZl3Siy3gWf02S98kffZPDMZxydWNzEKjlmfEet3axXi3zUOh/HDI1+fbTg6sZt4mF+FY/1xc04lH91VQDEr3wfORcRi4LPpuo4d8t+g67J9TvWpGGADhMAOrZ+lIFqQKO3Ui03DIqaVrYy98IN6/VJtZOY3Q5LL7y080IoDylrN/KRBqNJSbHC8/HcVkgo3t3wULNJS4gEKPEwabxK+GW5hQAILT7Yv0yEYNLYP7nQU4fBvcc8GQqmhqFnMj17Ti3AwyO5exuU2MGj+Ux6evvHwgKWU3naITLDYkymeL5ykU6GHwX1XqhkT+bF8PQ/x3tMR6rv958djk0ncBr2/VkFC0U0kbCdg/AKJe5ksfzs7wmEgXuyXDYaCORbjrM0S6gSTCY8qZSRXRMs/Mmo9f5CEI2T1qtVJLcR7UkjqjdgPFePDajsV7rJVu/XXe021dZVTrhC7pYPI1QuYrfv8lyA2coxFGIShnXYquvhY3PpatsLhP5g0zOf2mteC2GxdxScCRqAJ9Gt4Z1pwHUmsML+nsivaiUQGAufqHWfJEAAAAAQ8umh8eQPNSEW5pTzycIc4zsrvQItzSnS3ySIJ5PEObdhLZhWd8sMhoUirVRaBiVEqO+Epb4JEHVM4LGfZlRFz5S95C6CW3D+cLLRLK+WWTxdf/jdS5lsDblwzfj1kHxoB3ndiRGfSVnjduiLPFJgm867wXrYXVWqKrT0foyoy65+QWpPaKf+n5pOX01Fatddt4N2vKFl4mxTjEOZH2zyCe2FU+j7Y8c4CYpm6tau7vokR08bMqHby8BIeiHq/I5xGBUvkA7zu0D8GhqSIz6SgtHXM2PHMaezNdgGRnk4t9aL0RY3nTeC52/eIzWw+qslQhMKxFT1nhSmHD/9GVGXbeu4Noz9XqJcD7cDjtCTi54ieip/NJy+r8Z1H1qKla7KeHwPK26am/ucczopQ1eyObG+E9inWIcIVbEm4n8F0rKN7HNTmwrng2njRlG2x85BRC5voFLI+3CgIVqF7MHrFR4oSvQIzt4k+id/9iUD9+bX6lYHwQzC1zPlYwOV+VzTZxD9MnH2aeKDH8gwXDtAIK7S4cG4NHURSt3U5AY9ZXT01MSV4jJQRRDb8ZfP/3mHPRbYZivwTLbZGe1c860ZDAFEuO0Xoiw95UuN7zpvBf/IhqQe3mAwziyJkTtgaSCrkoCBSoRmFZp2j7RIqas8WFtCnblNpAlpv02oujLjLqrACo9L1uwbmyQFukn7ITJZCciTuB8uB2jtx6adoScXDVPOtuxFKCI8t8GD7mjlC/6aDKofjOo+z34DnyVUt2t1pl7KlLC4XkRCUf+WnXV3hm+c1md5ekK3i5PjQsdzUtI1mvMzI3xn49GVxjEOsU4h/FjvwOq+exAYV9rEvkvlFEyiRPVaRNAlqK1x93eJ+eeFYFgGk4bM1mFvbSMtj9yz32Z9UsmA6YI7aUhQ5E3AQBakYaEAQvVx8qtUm9gfoMsq9gEqPBCV+s75NCgR3bw44zQd2fXSiQkHOyj8S9uZbLkyOI2v1KxdXT0Nj4IZhZ9w8CR+ZhawrpT/EUcrsrnX2VsYNs+9jOY9VC004nClJBCZBMUGf5AV9JYx4Lh2gHBKnyGRXHm1Qa6QFJNxtJyDg109YpW7qbJnUghYTeb8CL8PXemp6ck5WwBo64Qk4Pt2zUEaYCvVypLCdD/eIsWvLMtkTjot8J7IxFFMF+DZXOUJeL3z7+xtAQZNuacacmlV89OIQxVHWLH85opu2G6anDHPe4rXW6t4PvpeNN5LzsY36i/Q0X7/IjjfLf0cVz0P9fbcGRNiDOv6w+bBTje2M6eWVyVBAofXqKNVCIwrRfpliqTsgx50Hmq/gVKKDhGgY6/wtoU7IERsmvKbSBLiaaGzA39HJ9ONroYEAARABIAAAAIAAcACQAGAAoABQALAAQADAADAA0AAgAOAAEADwBBgNwAC6IVYAcAAAAIUAAACBAAFAhzABIHHwAACHAAAAgwAAAJwAAQBwoAAAhgAAAIIAAACaAAAAgAAAAIgAAACEAAAAngABAHBgAACFgAAAgYAAAJkAATBzsAAAh4AAAIOAAACdAAEQcRAAAIaAAACCgAAAmwAAAICAAACIgAAAhIAAAJ8AAQBwQAAAhUAAAIFAAVCOMAEwcrAAAIdAAACDQAAAnIABEHDQAACGQAAAgkAAAJqAAACAQAAAiEAAAIRAAACegAEAcIAAAIXAAACBwAAAmYABQHUwAACHwAAAg8AAAJ2AASBxcAAAhsAAAILAAACbgAAAgMAAAIjAAACEwAAAn4ABAHAwAACFIAAAgSABUIowATByMAAAhyAAAIMgAACcQAEQcLAAAIYgAACCIAAAmkAAAIAgAACIIAAAhCAAAJ5AAQBwcAAAhaAAAIGgAACZQAFAdDAAAIegAACDoAAAnUABIHEwAACGoAAAgqAAAJtAAACAoAAAiKAAAISgAACfQAEAcFAAAIVgAACBYAQAgAABMHMwAACHYAAAg2AAAJzAARBw8AAAhmAAAIJgAACawAAAgGAAAIhgAACEYAAAnsABAHCQAACF4AAAgeAAAJnAAUB2MAAAh+AAAIPgAACdwAEgcbAAAIbgAACC4AAAm8AAAIDgAACI4AAAhOAAAJ/ABgBwAAAAhRAAAIEQAVCIMAEgcfAAAIcQAACDEAAAnCABAHCgAACGEAAAghAAAJogAACAEAAAiBAAAIQQAACeIAEAcGAAAIWQAACBkAAAmSABMHOwAACHkAAAg5AAAJ0gARBxEAAAhpAAAIKQAACbIAAAgJAAAIiQAACEkAAAnyABAHBAAACFUAAAgVABAIAgETBysAAAh1AAAINQAACcoAEQcNAAAIZQAACCUAAAmqAAAIBQAACIUAAAhFAAAJ6gAQBwgAAAhdAAAIHQAACZoAFAdTAAAIfQAACD0AAAnaABIHFwAACG0AAAgtAAAJugAACA0AAAiNAAAITQAACfoAEAcDAAAIUwAACBMAFQjDABMHIwAACHMAAAgzAAAJxgARBwsAAAhjAAAIIwAACaYAAAgDAAAIgwAACEMAAAnmABAHBwAACFsAAAgbAAAJlgAUB0MAAAh7AAAIOwAACdYAEgcTAAAIawAACCsAAAm2AAAICwAACIsAAAhLAAAJ9gAQBwUAAAhXAAAIFwBACAAAEwczAAAIdwAACDcAAAnOABEHDwAACGcAAAgnAAAJrgAACAcAAAiHAAAIRwAACe4AEAcJAAAIXwAACB8AAAmeABQHYwAACH8AAAg/AAAJ3gASBxsAAAhvAAAILwAACb4AAAgPAAAIjwAACE8AAAn+AGAHAAAACFAAAAgQABQIcwASBx8AAAhwAAAIMAAACcEAEAcKAAAIYAAACCAAAAmhAAAIAAAACIAAAAhAAAAJ4QAQBwYAAAhYAAAIGAAACZEAEwc7AAAIeAAACDgAAAnRABEHEQAACGgAAAgoAAAJsQAACAgAAAiIAAAISAAACfEAEAcEAAAIVAAACBQAFQjjABMHKwAACHQAAAg0AAAJyQARBw0AAAhkAAAIJAAACakAAAgEAAAIhAAACEQAAAnpABAHCAAACFwAAAgcAAAJmQAUB1MAAAh8AAAIPAAACdkAEgcXAAAIbAAACCwAAAm5AAAIDAAACIwAAAhMAAAJ+QAQBwMAAAhSAAAIEgAVCKMAEwcjAAAIcgAACDIAAAnFABEHCwAACGIAAAgiAAAJpQAACAIAAAiCAAAIQgAACeUAEAcHAAAIWgAACBoAAAmVABQHQwAACHoAAAg6AAAJ1QASBxMAAAhqAAAIKgAACbUAAAgKAAAIigAACEoAAAn1ABAHBQAACFYAAAgWAEAIAAATBzMAAAh2AAAINgAACc0AEQcPAAAIZgAACCYAAAmtAAAIBgAACIYAAAhGAAAJ7QAQBwkAAAheAAAIHgAACZ0AFAdjAAAIfgAACD4AAAndABIHGwAACG4AAAguAAAJvQAACA4AAAiOAAAITgAACf0AYAcAAAAIUQAACBEAFQiDABIHHwAACHEAAAgxAAAJwwAQBwoAAAhhAAAIIQAACaMAAAgBAAAIgQAACEEAAAnjABAHBgAACFkAAAgZAAAJkwATBzsAAAh5AAAIOQAACdMAEQcRAAAIaQAACCkAAAmzAAAICQAACIkAAAhJAAAJ8wAQBwQAAAhVAAAIFQAQCAIBEwcrAAAIdQAACDUAAAnLABEHDQAACGUAAAglAAAJqwAACAUAAAiFAAAIRQAACesAEAcIAAAIXQAACB0AAAmbABQHUwAACH0AAAg9AAAJ2wASBxcAAAhtAAAILQAACbsAAAgNAAAIjQAACE0AAAn7ABAHAwAACFMAAAgTABUIwwATByMAAAhzAAAIMwAACccAEQcLAAAIYwAACCMAAAmnAAAIAwAACIMAAAhDAAAJ5wAQBwcAAAhbAAAIGwAACZcAFAdDAAAIewAACDsAAAnXABIHEwAACGsAAAgrAAAJtwAACAsAAAiLAAAISwAACfcAEAcFAAAIVwAACBcAQAgAABMHMwAACHcAAAg3AAAJzwARBw8AAAhnAAAIJwAACa8AAAgHAAAIhwAACEcAAAnvABAHCQAACF8AAAgfAAAJnwAUB2MAAAh/AAAIPwAACd8AEgcbAAAIbwAACC8AAAm/AAAIDwAACI8AAAhPAAAJ/wAQBQEAFwUBARMFEQAbBQEQEQUFABkFAQQVBUEAHQUBQBAFAwAYBQECFAUhABwFASASBQkAGgUBCBYFgQBABQAAEAUCABcFgQETBRkAGwUBGBEFBwAZBQEGFQVhAB0FAWAQBQQAGAUBAxQFMQAcBQEwEgUNABoFAQwWBcEAQAUAAAMABAAFAAYABwAIAAkACgALAA0ADwARABMAFwAbAB8AIwArADMAOwBDAFMAYwBzAIMAowDDAOMAAgEAAAAAAAAQABAAEAAQABAAEAAQABAAEQARABEAEQASABIAEgASABMAEwATABMAFAAUABQAFAAVABUAFQAVABAAywBNAAAAAQACAAMABAAFAAcACQANABEAGQAhADEAQQBhAIEAwQABAYEBAQIBAwEEAQYBCAEMARABGAEgATABQAFgAAAAABAAEAAQABAAEQARABIAEgATABMAFAAUABUAFQAWABYAFwAXABgAGAAZABkAGgAaABsAGwAcABwAHQAdAEAAQAC+8/h57GH2P96qjID3e9W/PYivSu1x9T/bbcCn8L7Sv7AQ8PA5lfQ/ZzpRf64e0L+FA7iwlcnzP+kkgqbYMcu/pWSIDBkN8z9Yd8AKT1fGv6COC3siXvI/AIGcxyuqwb8/NBpKSrvxP14OjM52Trq/uuWK8Fgj8T/MHGFaPJexv6cAmUE/lfA/HgzhOPRSor8AAAAAAADwPwAAAAAAAAAArEea/Yxg7j+EWfJdqqWqP6BqAh+zpOw/tC42qlNevD/m/GpXNiDrPwjbIHflJsU/LaqhY9HC6T9wRyINhsLLP+1BeAPmhug/4X6gyIsF0T9iSFP13GfnPwnutlcwBNQ/7zn6/kIu5j80g7hIow7Qv2oL4AtbV9U/I0EK8v7/37/AbgBBsPEAC0EZAAsAGRkZAAAAAAUAAAAAAAAJAAAAAAsAAAAAAAAAABkACgoZGRkDCgcAAQAJCxgAAAkGCwAACwAGGQAAABkZGQBBgfIACyEOAAAAAAAAAAAZAAsNGRkZAA0AAAIACQ4AAAAJAA4AAA4AQbvyAAsBDABBx/IACxUTAAAAABMAAAAACQwAAAAAAAwAAAwAQfXyAAsBEABBgfMACxUPAAAABA8AAAAACRAAAAAAABAAABAAQa/zAAsBEgBBu/MACx4RAAAAABEAAAAACRIAAAAAABIAABIAABoAAAAaGhoAQfLzAAsOGgAAABoaGgAAAAAAAAkAQaP0AAsBFABBr/QACxUXAAAAABcAAAAACRQAAAAAABQAABQAQd30AAsBFgBB6fQAC5oOFQAAAAAVAAAAAAkWAAAAAAAWAAAWAAAwMTIzNDU2Nzg5QUJDREVGAAAAAAA8AAA2AAAANwAAADgAAAA5AAAAOgAAADsAAAA8AAAAPQAAAD4AAAA/AAAAQAAAAEEAAABCAAAAQwAAAAgAAAAAAAAAPDwAAEQAAABFAAAA+P////j///88PAAARgAAAEcAAADcOgAA8DoAAAQAAAAAAAAAhDwAAEgAAABJAAAA/P////z///+EPAAASgAAAEsAAAAMOwAAIDsAAAwAAAAAAAAAHD0AAEwAAABNAAAABAAAAPj///8cPQAATgAAAE8AAAD0////9P///xw9AABQAAAAUQAAADw7AADYPAAA7DwAAAA9AAAUPQAAZDsAAFA7AAAAAAAAbD0AAFIAAABTAAAAOAAAADkAAABUAAAAVQAAADwAAAA9AAAAPgAAAFYAAABAAAAAVwAAAEIAAABYAAAA0G0AANQ7AAAQPwAATlN0M19fMjliYXNpY19pb3NJY05TXzExY2hhcl90cmFpdHNJY0VFRUUAAACobQAACDwAAE5TdDNfXzIxNWJhc2ljX3N0cmVhbWJ1ZkljTlNfMTFjaGFyX3RyYWl0c0ljRUVFRQAAAAAsbgAAVDwAAAAAAAABAAAAyDsAAAP0//9OU3QzX18yMTNiYXNpY19pc3RyZWFtSWNOU18xMWNoYXJfdHJhaXRzSWNFRUVFAAAsbgAAnDwAAAAAAAABAAAAyDsAAAP0//9OU3QzX18yMTNiYXNpY19vc3RyZWFtSWNOU18xMWNoYXJfdHJhaXRzSWNFRUVFAAAMAAAAAAAAADw8AABEAAAARQAAAPT////0////PDwAAEYAAABHAAAABAAAAAAAAACEPAAASAAAAEkAAAD8/////P///4Q8AABKAAAASwAAACxuAAA8PQAAAwAAAAIAAAA8PAAAAgAAAIQ8AAACCAAATlN0M19fMjE0YmFzaWNfaW9zdHJlYW1JY05TXzExY2hhcl90cmFpdHNJY0VFRUUA0G0AAHg9AAAAPAAATlN0M19fMjE1YmFzaWNfc3RyaW5nYnVmSWNOU18xMWNoYXJfdHJhaXRzSWNFRU5TXzlhbGxvY2F0b3JJY0VFRUUAAABAAAAAAAAAAKw+AABZAAAAWgAAADgAAAD4////rD4AAFsAAABcAAAAwP///8D///+sPgAAXQAAAF4AAADIPQAALD4AAGg+AAB8PgAAkD4AAKQ+AABUPgAAQD4AAPA9AADcPQAAQAAAAAAAAAAcPQAATAAAAE0AAAA4AAAA+P///xw9AABOAAAATwAAAMD////A////HD0AAFAAAABRAAAAQAAAAAAAAAA8PAAARAAAAEUAAADA////wP///zw8AABGAAAARwAAADgAAAAAAAAAhDwAAEgAAABJAAAAyP///8j///+EPAAASgAAAEsAAADQbQAAuD4AABw9AABOU3QzX18yMThiYXNpY19zdHJpbmdzdHJlYW1JY05TXzExY2hhcl90cmFpdHNJY0VFTlNfOWFsbG9jYXRvckljRUVFRQAAAAAAAAAAED8AAF8AAABgAAAAqG0AABg/AABOU3QzX18yOGlvc19iYXNlRQAAAAAAAADRdJ4AV529KoBwUg///z4nCgAAAGQAAADoAwAAECcAAKCGAQBAQg8AgJaYAADh9QUYAAAANQAAAHEAAABr////zvv//5K///8AAAAAAAAAAP////////////////////////////////////////////////////////////////8AAQIDBAUGBwgJ/////////woLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj////////CgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAECBAcDBgUAAAAAAAAAAgAAwAMAAMAEAADABQAAwAYAAMAHAADACAAAwAkAAMAKAADACwAAwAwAAMANAADADgAAwA8AAMAQAADAEQAAwBIAAMATAADAFAAAwBUAAMAWAADAFwAAwBgAAMAZAADAGgAAwBsAAMAcAADAHQAAwB4AAMAfAADAAAAAswEAAMMCAADDAwAAwwQAAMMFAADDBgAAwwcAAMMIAADDCQAAwwoAAMMLAADDDAAAww0AANMOAADDDwAAwwAADLsBAAzDAgAMwwMADMMEAAzbAAAAAN4SBJUAAAAA////////////////YEEAABQAAABDLlVURi04AEGwgwELAnRBAEHQgwELSkxDX0NUWVBFAAAAAExDX05VTUVSSUMAAExDX1RJTUUAAAAAAExDX0NPTExBVEUAAExDX01PTkVUQVJZAExDX01FU1NBR0VTACBEAEGkiAEL+QMBAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAACwAAAAwAAAANAAAADgAAAA8AAAAQAAAAEQAAABIAAAATAAAAFAAAABUAAAAWAAAAFwAAABgAAAAZAAAAGgAAABsAAAAcAAAAHQAAAB4AAAAfAAAAIAAAACEAAAAiAAAAIwAAACQAAAAlAAAAJgAAACcAAAAoAAAAKQAAACoAAAArAAAALAAAAC0AAAAuAAAALwAAADAAAAAxAAAAMgAAADMAAAA0AAAANQAAADYAAAA3AAAAOAAAADkAAAA6AAAAOwAAADwAAAA9AAAAPgAAAD8AAABAAAAAQQAAAEIAAABDAAAARAAAAEUAAABGAAAARwAAAEgAAABJAAAASgAAAEsAAABMAAAATQAAAE4AAABPAAAAUAAAAFEAAABSAAAAUwAAAFQAAABVAAAAVgAAAFcAAABYAAAAWQAAAFoAAABbAAAAXAAAAF0AAABeAAAAXwAAAGAAAABBAAAAQgAAAEMAAABEAAAARQAAAEYAAABHAAAASAAAAEkAAABKAAAASwAAAEwAAABNAAAATgAAAE8AAABQAAAAUQAAAFIAAABTAAAAVAAAAFUAAABWAAAAVwAAAFgAAABZAAAAWgAAAHsAAAB8AAAAfQAAAH4AAAB/AEGgkAELAjBKAEG0lAEL+QMBAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAACwAAAAwAAAANAAAADgAAAA8AAAAQAAAAEQAAABIAAAATAAAAFAAAABUAAAAWAAAAFwAAABgAAAAZAAAAGgAAABsAAAAcAAAAHQAAAB4AAAAfAAAAIAAAACEAAAAiAAAAIwAAACQAAAAlAAAAJgAAACcAAAAoAAAAKQAAACoAAAArAAAALAAAAC0AAAAuAAAALwAAADAAAAAxAAAAMgAAADMAAAA0AAAANQAAADYAAAA3AAAAOAAAADkAAAA6AAAAOwAAADwAAAA9AAAAPgAAAD8AAABAAAAAYQAAAGIAAABjAAAAZAAAAGUAAABmAAAAZwAAAGgAAABpAAAAagAAAGsAAABsAAAAbQAAAG4AAABvAAAAcAAAAHEAAAByAAAAcwAAAHQAAAB1AAAAdgAAAHcAAAB4AAAAeQAAAHoAAABbAAAAXAAAAF0AAABeAAAAXwAAAGAAAABhAAAAYgAAAGMAAABkAAAAZQAAAGYAAABnAAAAaAAAAGkAAABqAAAAawAAAGwAAABtAAAAbgAAAG8AAABwAAAAcQAAAHIAAABzAAAAdAAAAHUAAAB2AAAAdwAAAHgAAAB5AAAAegAAAHsAAAB8AAAAfQAAAH4AAAB/AEG0nAELLYDeKACAyE0AAKd2AAA0ngCAEscAgJ/uAAB+FwGAXEABgOlnAQDIkAEAVbgBLgBB8JwBC9ICU3VuAE1vbgBUdWUAV2VkAFRodQBGcmkAU2F0AFN1bmRheQBNb25kYXkAVHVlc2RheQBXZWRuZXNkYXkAVGh1cnNkYXkARnJpZGF5AFNhdHVyZGF5AEphbgBGZWIATWFyAEFwcgBNYXkASnVuAEp1bABBdWcAU2VwAE9jdABOb3YARGVjAEphbnVhcnkARmVicnVhcnkATWFyY2gAQXByaWwATWF5AEp1bmUASnVseQBBdWd1c3QAU2VwdGVtYmVyAE9jdG9iZXIATm92ZW1iZXIARGVjZW1iZXIAQU0AUE0AJWEgJWIgJWUgJVQgJVkAJW0vJWQvJXkAJUg6JU06JVMAJUk6JU06JVMgJXAAAAAlbS8lZC8leQAwMTIzNDU2Nzg5ACVhICViICVlICVUICVZACVIOiVNOiVTAAAAAABeW3lZXQBeW25OXQB5ZXMAbm8AQdCfAQsxMDEyMzQ1Njc4OWFiY2RlZkFCQ0RFRnhYKy1wUGlJbk4AJUk6JU06JVMgJXAlSDolTQBBkKABC4EBJQAAAG0AAAAvAAAAJQAAAGQAAAAvAAAAJQAAAHkAAAAlAAAAWQAAAC0AAAAlAAAAbQAAAC0AAAAlAAAAZAAAACUAAABJAAAAOgAAACUAAABNAAAAOgAAACUAAABTAAAAIAAAACUAAABwAAAAAAAAACUAAABIAAAAOgAAACUAAABNAEGgoQELZSUAAABIAAAAOgAAACUAAABNAAAAOgAAACUAAABTAAAAAAAAAABaAAB0AAAAdQAAAHYAAAAAAAAAZFoAAHcAAAB4AAAAdgAAAHkAAAB6AAAAewAAAHwAAAB9AAAAfgAAAH8AAACAAEGQogEL/QMEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAFAgAABQAAAAUAAAAFAAAABQAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAMCAACCAAAAggAAAIIAAACCAAAAggAAAIIAAACCAAAAggAAAIIAAACCAAAAggAAAIIAAACCAAAAggAAAIIAAABCAQAAQgEAAEIBAABCAQAAQgEAAEIBAABCAQAAQgEAAEIBAABCAQAAggAAAIIAAACCAAAAggAAAIIAAACCAAAAggAAACoBAAAqAQAAKgEAACoBAAAqAQAAKgEAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAggAAAIIAAACCAAAAggAAAIIAAACCAAAAMgEAADIBAAAyAQAAMgEAADIBAAAyAQAAMgAAADIAAAAyAAAAMgAAADIAAAAyAAAAMgAAADIAAAAyAAAAMgAAADIAAAAyAAAAMgAAADIAAAAyAAAAMgAAADIAAAAyAAAAMgAAADIAAACCAAAAggAAAIIAAACCAAAABABBlKoBC+0CvFkAAIEAAACCAAAAdgAAAIMAAACEAAAAhQAAAIYAAACHAAAAiAAAAIkAAAAAAAAAmFoAAIoAAACLAAAAdgAAAIwAAACNAAAAjgAAAI8AAACQAAAAAAAAALxaAACRAAAAkgAAAHYAAACTAAAAlAAAAJUAAACWAAAAlwAAAHQAAAByAAAAdQAAAGUAAAAAAAAAZgAAAGEAAABsAAAAcwAAAGUAAAAAAAAAJQAAAG0AAAAvAAAAJQAAAGQAAAAvAAAAJQAAAHkAAAAAAAAAJQAAAEgAAAA6AAAAJQAAAE0AAAA6AAAAJQAAAFMAAAAAAAAAJQAAAGEAAAAgAAAAJQAAAGIAAAAgAAAAJQAAAGQAAAAgAAAAJQAAAEgAAAA6AAAAJQAAAE0AAAA6AAAAJQAAAFMAAAAgAAAAJQAAAFkAAAAAAAAAJQAAAEkAAAA6AAAAJQAAAE0AAAA6AAAAJQAAAFMAAAAgAAAAJQAAAHAAQYytAQv9J5xWAACYAAAAmQAAAHYAAADQbQAAqFYAAOxqAABOU3QzX18yNmxvY2FsZTVmYWNldEUAAAAAAAAABFcAAJgAAACaAAAAdgAAAJsAAACcAAAAnQAAAJ4AAACfAAAAoAAAAKEAAACiAAAAowAAAKQAAAClAAAApgAAACxuAAAkVwAAAAAAAAIAAACcVgAAAgAAADhXAAACAAAATlN0M19fMjVjdHlwZUl3RUUAAACobQAAQFcAAE5TdDNfXzIxMGN0eXBlX2Jhc2VFAAAAAAAAAACIVwAAmAAAAKcAAAB2AAAAqAAAAKkAAACqAAAAqwAAAKwAAACtAAAArgAAACxuAACoVwAAAAAAAAIAAACcVgAAAgAAAMxXAAACAAAATlN0M19fMjdjb2RlY3Z0SWNjMTFfX21ic3RhdGVfdEVFAAAAqG0AANRXAABOU3QzX18yMTJjb2RlY3Z0X2Jhc2VFAAAAAAAAHFgAAJgAAACvAAAAdgAAALAAAACxAAAAsgAAALMAAAC0AAAAtQAAALYAAAAsbgAAPFgAAAAAAAACAAAAnFYAAAIAAADMVwAAAgAAAE5TdDNfXzI3Y29kZWN2dElEc2MxMV9fbWJzdGF0ZV90RUUAAAAAAACQWAAAmAAAALcAAAB2AAAAuAAAALkAAAC6AAAAuwAAALwAAAC9AAAAvgAAACxuAACwWAAAAAAAAAIAAACcVgAAAgAAAMxXAAACAAAATlN0M19fMjdjb2RlY3Z0SURzRHUxMV9fbWJzdGF0ZV90RUUAAAAAAARZAACYAAAAvwAAAHYAAADAAAAAwQAAAMIAAADDAAAAxAAAAMUAAADGAAAALG4AACRZAAAAAAAAAgAAAJxWAAACAAAAzFcAAAIAAABOU3QzX18yN2NvZGVjdnRJRGljMTFfX21ic3RhdGVfdEVFAAAAAAAAeFkAAJgAAADHAAAAdgAAAMgAAADJAAAAygAAAMsAAADMAAAAzQAAAM4AAAAsbgAAmFkAAAAAAAACAAAAnFYAAAIAAADMVwAAAgAAAE5TdDNfXzI3Y29kZWN2dElEaUR1MTFfX21ic3RhdGVfdEVFACxuAADcWQAAAAAAAAIAAACcVgAAAgAAAMxXAAACAAAATlN0M19fMjdjb2RlY3Z0SXdjMTFfX21ic3RhdGVfdEVFAAAA0G0AAAxaAACcVgAATlN0M19fMjZsb2NhbGU1X19pbXBFAAAA0G0AADBaAACcVgAATlN0M19fMjdjb2xsYXRlSWNFRQDQbQAAUFoAAJxWAABOU3QzX18yN2NvbGxhdGVJd0VFACxuAACEWgAAAAAAAAIAAACcVgAAAgAAADhXAAACAAAATlN0M19fMjVjdHlwZUljRUUAAADQbQAApFoAAJxWAABOU3QzX18yOG51bXB1bmN0SWNFRQAAAADQbQAAyFoAAJxWAABOU3QzX18yOG51bXB1bmN0SXdFRQAAAAAAAAAAJFoAAM8AAADQAAAAdgAAANEAAADSAAAA0wAAAAAAAABEWgAA1AAAANUAAAB2AAAA1gAAANcAAADYAAAAAAAAAGBbAACYAAAA2QAAAHYAAADaAAAA2wAAANwAAADdAAAA3gAAAN8AAADgAAAA4QAAAOIAAADjAAAA5AAAACxuAACAWwAAAAAAAAIAAACcVgAAAgAAAMRbAAAAAAAATlN0M19fMjdudW1fZ2V0SWNOU18xOWlzdHJlYW1idWZfaXRlcmF0b3JJY05TXzExY2hhcl90cmFpdHNJY0VFRUVFRQAsbgAA3FsAAAAAAAABAAAA9FsAAAAAAABOU3QzX18yOV9fbnVtX2dldEljRUUAAACobQAA/FsAAE5TdDNfXzIxNF9fbnVtX2dldF9iYXNlRQAAAAAAAAAAWFwAAJgAAADlAAAAdgAAAOYAAADnAAAA6AAAAOkAAADqAAAA6wAAAOwAAADtAAAA7gAAAO8AAADwAAAALG4AAHhcAAAAAAAAAgAAAJxWAAACAAAAvFwAAAAAAABOU3QzX18yN251bV9nZXRJd05TXzE5aXN0cmVhbWJ1Zl9pdGVyYXRvckl3TlNfMTFjaGFyX3RyYWl0c0l3RUVFRUVFACxuAADUXAAAAAAAAAEAAAD0WwAAAAAAAE5TdDNfXzI5X19udW1fZ2V0SXdFRQAAAAAAAAAgXQAAmAAAAPEAAAB2AAAA8gAAAPMAAAD0AAAA9QAAAPYAAAD3AAAA+AAAAPkAAAAsbgAAQF0AAAAAAAACAAAAnFYAAAIAAACEXQAAAAAAAE5TdDNfXzI3bnVtX3B1dEljTlNfMTlvc3RyZWFtYnVmX2l0ZXJhdG9ySWNOU18xMWNoYXJfdHJhaXRzSWNFRUVFRUUALG4AAJxdAAAAAAAAAQAAALRdAAAAAAAATlN0M19fMjlfX251bV9wdXRJY0VFAAAAqG0AALxdAABOU3QzX18yMTRfX251bV9wdXRfYmFzZUUAAAAAAAAAAAxeAACYAAAA+gAAAHYAAAD7AAAA/AAAAP0AAAD+AAAA/wAAAAABAAABAQAAAgEAACxuAAAsXgAAAAAAAAIAAACcVgAAAgAAAHBeAAAAAAAATlN0M19fMjdudW1fcHV0SXdOU18xOW9zdHJlYW1idWZfaXRlcmF0b3JJd05TXzExY2hhcl90cmFpdHNJd0VFRUVFRQAsbgAAiF4AAAAAAAABAAAAtF0AAAAAAABOU3QzX18yOV9fbnVtX3B1dEl3RUUAAAAAAAAA9F4AAAMBAAAEAQAAdgAAAAUBAAAGAQAABwEAAAgBAAAJAQAACgEAAAsBAAD4////9F4AAAwBAAANAQAADgEAAA8BAAAQAQAAEQEAABIBAAAsbgAAHF8AAAAAAAADAAAAnFYAAAIAAABkXwAAAgAAAIBfAAAACAAATlN0M19fMjh0aW1lX2dldEljTlNfMTlpc3RyZWFtYnVmX2l0ZXJhdG9ySWNOU18xMWNoYXJfdHJhaXRzSWNFRUVFRUUAAAAAqG0AAGxfAABOU3QzX18yOXRpbWVfYmFzZUUAAKhtAACIXwAATlN0M19fMjIwX190aW1lX2dldF9jX3N0b3JhZ2VJY0VFAAAAAAAAAABgAAATAQAAFAEAAHYAAAAVAQAAFgEAABcBAAAYAQAAGQEAABoBAAAbAQAA+P///wBgAAAcAQAAHQEAAB4BAAAfAQAAIAEAACEBAAAiAQAALG4AAChgAAAAAAAAAwAAAJxWAAACAAAAZF8AAAIAAABwYAAAAAgAAE5TdDNfXzI4dGltZV9nZXRJd05TXzE5aXN0cmVhbWJ1Zl9pdGVyYXRvckl3TlNfMTFjaGFyX3RyYWl0c0l3RUVFRUVFAAAAAKhtAAB4YAAATlN0M19fMjIwX190aW1lX2dldF9jX3N0b3JhZ2VJd0VFAAAAAAAAALRgAAAjAQAAJAEAAHYAAAAlAQAALG4AANRgAAAAAAAAAgAAAJxWAAACAAAAHGEAAAAIAABOU3QzX18yOHRpbWVfcHV0SWNOU18xOW9zdHJlYW1idWZfaXRlcmF0b3JJY05TXzExY2hhcl90cmFpdHNJY0VFRUVFRQAAAACobQAAJGEAAE5TdDNfXzIxMF9fdGltZV9wdXRFAAAAAAAAAABUYQAAJgEAACcBAAB2AAAAKAEAACxuAAB0YQAAAAAAAAIAAACcVgAAAgAAABxhAAAACAAATlN0M19fMjh0aW1lX3B1dEl3TlNfMTlvc3RyZWFtYnVmX2l0ZXJhdG9ySXdOU18xMWNoYXJfdHJhaXRzSXdFRUVFRUUAAAAAAAAAAPRhAACYAAAAKQEAAHYAAAAqAQAAKwEAACwBAAAtAQAALgEAAC8BAAAwAQAAMQEAADIBAAAsbgAAFGIAAAAAAAACAAAAnFYAAAIAAAAwYgAAAgAAAE5TdDNfXzIxMG1vbmV5cHVuY3RJY0xiMEVFRQCobQAAOGIAAE5TdDNfXzIxMG1vbmV5X2Jhc2VFAAAAAAAAAACIYgAAmAAAADMBAAB2AAAANAEAADUBAAA2AQAANwEAADgBAAA5AQAAOgEAADsBAAA8AQAALG4AAKhiAAAAAAAAAgAAAJxWAAACAAAAMGIAAAIAAABOU3QzX18yMTBtb25leXB1bmN0SWNMYjFFRUUAAAAAAPxiAACYAAAAPQEAAHYAAAA+AQAAPwEAAEABAABBAQAAQgEAAEMBAABEAQAARQEAAEYBAAAsbgAAHGMAAAAAAAACAAAAnFYAAAIAAAAwYgAAAgAAAE5TdDNfXzIxMG1vbmV5cHVuY3RJd0xiMEVFRQAAAAAAcGMAAJgAAABHAQAAdgAAAEgBAABJAQAASgEAAEsBAABMAQAATQEAAE4BAABPAQAAUAEAACxuAACQYwAAAAAAAAIAAACcVgAAAgAAADBiAAACAAAATlN0M19fMjEwbW9uZXlwdW5jdEl3TGIxRUVFAAAAAADIYwAAmAAAAFEBAAB2AAAAUgEAAFMBAAAsbgAA6GMAAAAAAAACAAAAnFYAAAIAAAAwZAAAAAAAAE5TdDNfXzI5bW9uZXlfZ2V0SWNOU18xOWlzdHJlYW1idWZfaXRlcmF0b3JJY05TXzExY2hhcl90cmFpdHNJY0VFRUVFRQAAAKhtAAA4ZAAATlN0M19fMjExX19tb25leV9nZXRJY0VFAAAAAAAAAABwZAAAmAAAAFQBAAB2AAAAVQEAAFYBAAAsbgAAkGQAAAAAAAACAAAAnFYAAAIAAADYZAAAAAAAAE5TdDNfXzI5bW9uZXlfZ2V0SXdOU18xOWlzdHJlYW1idWZfaXRlcmF0b3JJd05TXzExY2hhcl90cmFpdHNJd0VFRUVFRQAAAKhtAADgZAAATlN0M19fMjExX19tb25leV9nZXRJd0VFAAAAAAAAAAAYZQAAmAAAAFcBAAB2AAAAWAEAAFkBAAAsbgAAOGUAAAAAAAACAAAAnFYAAAIAAACAZQAAAAAAAE5TdDNfXzI5bW9uZXlfcHV0SWNOU18xOW9zdHJlYW1idWZfaXRlcmF0b3JJY05TXzExY2hhcl90cmFpdHNJY0VFRUVFRQAAAKhtAACIZQAATlN0M19fMjExX19tb25leV9wdXRJY0VFAAAAAAAAAADAZQAAmAAAAFoBAAB2AAAAWwEAAFwBAAAsbgAA4GUAAAAAAAACAAAAnFYAAAIAAAAoZgAAAAAAAE5TdDNfXzI5bW9uZXlfcHV0SXdOU18xOW9zdHJlYW1idWZfaXRlcmF0b3JJd05TXzExY2hhcl90cmFpdHNJd0VFRUVFRQAAAKhtAAAwZgAATlN0M19fMjExX19tb25leV9wdXRJd0VFAAAAAAAAAABsZgAAmAAAAF0BAAB2AAAAXgEAAF8BAABgAQAALG4AAIxmAAAAAAAAAgAAAJxWAAACAAAApGYAAAIAAABOU3QzX18yOG1lc3NhZ2VzSWNFRQAAAACobQAArGYAAE5TdDNfXzIxM21lc3NhZ2VzX2Jhc2VFAAAAAADkZgAAmAAAAGEBAAB2AAAAYgEAAGMBAABkAQAALG4AAARnAAAAAAAAAgAAAJxWAAACAAAApGYAAAIAAABOU3QzX18yOG1lc3NhZ2VzSXdFRQAAAABTAAAAdQAAAG4AAABkAAAAYQAAAHkAAAAAAAAATQAAAG8AAABuAAAAZAAAAGEAAAB5AAAAAAAAAFQAAAB1AAAAZQAAAHMAAABkAAAAYQAAAHkAAAAAAAAAVwAAAGUAAABkAAAAbgAAAGUAAABzAAAAZAAAAGEAAAB5AAAAAAAAAFQAAABoAAAAdQAAAHIAAABzAAAAZAAAAGEAAAB5AAAAAAAAAEYAAAByAAAAaQAAAGQAAABhAAAAeQAAAAAAAABTAAAAYQAAAHQAAAB1AAAAcgAAAGQAAABhAAAAeQAAAAAAAABTAAAAdQAAAG4AAAAAAAAATQAAAG8AAABuAAAAAAAAAFQAAAB1AAAAZQAAAAAAAABXAAAAZQAAAGQAAAAAAAAAVAAAAGgAAAB1AAAAAAAAAEYAAAByAAAAaQAAAAAAAABTAAAAYQAAAHQAAAAAAAAASgAAAGEAAABuAAAAdQAAAGEAAAByAAAAeQAAAAAAAABGAAAAZQAAAGIAAAByAAAAdQAAAGEAAAByAAAAeQAAAAAAAABNAAAAYQAAAHIAAABjAAAAaAAAAAAAAABBAAAAcAAAAHIAAABpAAAAbAAAAAAAAABNAAAAYQAAAHkAAAAAAAAASgAAAHUAAABuAAAAZQAAAAAAAABKAAAAdQAAAGwAAAB5AAAAAAAAAEEAAAB1AAAAZwAAAHUAAABzAAAAdAAAAAAAAABTAAAAZQAAAHAAAAB0AAAAZQAAAG0AAABiAAAAZQAAAHIAAAAAAAAATwAAAGMAAAB0AAAAbwAAAGIAAABlAAAAcgAAAAAAAABOAAAAbwAAAHYAAABlAAAAbQAAAGIAAABlAAAAcgAAAAAAAABEAAAAZQAAAGMAAABlAAAAbQAAAGIAAABlAAAAcgAAAAAAAABKAAAAYQAAAG4AAAAAAAAARgAAAGUAAABiAAAAAAAAAE0AAABhAAAAcgAAAAAAAABBAAAAcAAAAHIAAAAAAAAASgAAAHUAAABuAAAAAAAAAEoAAAB1AAAAbAAAAAAAAABBAAAAdQAAAGcAAAAAAAAAUwAAAGUAAABwAAAAAAAAAE8AAABjAAAAdAAAAAAAAABOAAAAbwAAAHYAAAAAAAAARAAAAGUAAABjAAAAAAAAAEEAAABNAAAAAAAAAFAAAABNAEGU1QELnAiAXwAADAEAAA0BAAAOAQAADwEAABABAAARAQAAEgEAAAAAAABwYAAAHAEAAB0BAAAeAQAAHwEAACABAAAhAQAAIgEAAAAAAADsagAAZQEAAGYBAABnAQAAqG0AAPRqAABOU3QzX18yMTRfX3NoYXJlZF9jb3VudEUAAAAAcG8AANBtAAAgawAAnG4AAE4xMF9fY3h4YWJpdjExNl9fc2hpbV90eXBlX2luZm9FAAAAANBtAABQawAAFGsAAE4xMF9fY3h4YWJpdjExN19fY2xhc3NfdHlwZV9pbmZvRQAAANBtAACAawAAFGsAAE4xMF9fY3h4YWJpdjExN19fcGJhc2VfdHlwZV9pbmZvRQAAANBtAACwawAAdGsAAE4xMF9fY3h4YWJpdjExOV9fcG9pbnRlcl90eXBlX2luZm9FANBtAADgawAAFGsAAE4xMF9fY3h4YWJpdjEyMF9fZnVuY3Rpb25fdHlwZV9pbmZvRQAAAADQbQAAFGwAAHRrAABOMTBfX2N4eGFiaXYxMjlfX3BvaW50ZXJfdG9fbWVtYmVyX3R5cGVfaW5mb0UAAAAAAAAAYGwAAGoBAABrAQAAbAEAAG0BAABuAQAA0G0AAGxsAAAUawAATjEwX19jeHhhYml2MTIzX19mdW5kYW1lbnRhbF90eXBlX2luZm9FAExsAACcbAAAdgAAAExsAACobAAARG4AAExsAAC0bAAAYgAAAExsAADAbAAAYwAAAExsAADMbAAAaAAAAExsAADYbAAAYQAAAExsAADkbAAAcwAAAExsAADwbAAAdAAAAExsAAD8bAAAaQAAAExsAAAIbQAAagAAAExsAAAUbQAAbAAAAExsAAAgbQAAbQAAAExsAAAsbQAAeAAAAExsAAA4bQAAeQAAAExsAABEbQAAZgAAAExsAABQbQAAZAAAAAAAAABwbQAAagEAAG8BAABsAQAAbQEAAHABAADQbQAAfG0AABRrAABOMTBfX2N4eGFiaXYxMTZfX2VudW1fdHlwZV9pbmZvRQAAAAAAAAAARGsAAGoBAABxAQAAbAEAAG0BAAByAQAAcwEAAHQBAAB1AQAAAAAAAPBtAABqAQAAdgEAAGwBAABtAQAAcgEAAHcBAAB4AQAAeQEAANBtAAD8bQAARGsAAE4xMF9fY3h4YWJpdjEyMF9fc2lfY2xhc3NfdHlwZV9pbmZvRQAAAAAAAAAATG4AAGoBAAB6AQAAbAEAAG0BAAByAQAAewEAAHwBAAB9AQAA0G0AAFhuAABEawAATjEwX19jeHhhYml2MTIxX192bWlfY2xhc3NfdHlwZV9pbmZvRQAAAAAAAACkawAAagEAAH4BAABsAQAAbQEAAH8BAACobQAApG4AAFN0OXR5cGVfaW5mbwBBud0BCwggAAAAAAAABQBBzN0BCwExAEHk3QELDjIAAAAzAAAACHEAAAAEAEH83QELAQEAQYzeAQsF/////woAQdDeAQshwG4AAHB/AQAlbS8lZC8leQAAAAglSDolTTolUwAAAAgFAEH83gELAmgBAEGU3wELCjIAAABpAQAAZH8AQazfAQsBAgBBvN8BCwj//////////wBBgOABCwJwbw==")), I((await RI(A)).instance));
})();
function rA() {
function I() {
var g;
if (i.calledRun = true, !fA) {
if (WA = true, X.G(), AA == null || AA(i), (g = i.onRuntimeInitialized) == null || g.call(i), i.postRun) for (typeof i.postRun == "function" && (i.postRun = [i.postRun]); i.postRun.length; ) {
var A = i.postRun.shift();
XA.push(A);
}
VA(XA);
}
}
if (0 < e) u3 = rA;
else {
if (i.preRun) for (typeof i.preRun == "function" && (i.preRun = [i.preRun]); i.preRun.length; ) sI();
VA(TA), 0 < e ? u3 = rA : i.setStatus ? (i.setStatus("Running..."), setTimeout(() => {
setTimeout(() => i.setStatus(""), 1), I();
}, 1)) : I();
}
}
if (i.preInit) for (typeof i.preInit == "function" && (i.preInit = [i.preInit]); 0 < i.preInit.length; ) i.preInit.shift()();
return rA(), WA ? s = i : s = new Promise((I, A) => {
AA = I, IA = A;
}), s;
}
var T = (R, s, i = (L) => L) => {
const L = R.vf32_ptr(s), k = s.size();
return new Float32Array(R.HEAPF32.buffer, L, k).map(i);
};
var pI = (R) => 1 / (1 + Math.exp(-R));
var OI = (R) => (s) => s * R + 0.5;
var PI = (R, s, i) => {
const L = (i == null ? void 0 : i.colorScaleFactor) ?? 0.282;
return {
numPoints: s.numPoints,
shDegree: s.shDegree,
antialiased: s.antialiased,
positions: T(R, s.positions),
scales: T(R, s.scales, Math.exp),
rotations: T(R, s.rotations),
alphas: T(R, s.alphas, pI),
colors: T(
R,
s.colors,
OI(L)
),
// FIXME: incorrect SH logic
sh: T(R, s.sh)
};
};
var uI = (R, s) => {
R._free(R.vf32_ptr(s.positions)), R._free(R.vf32_ptr(s.scales)), R._free(R.vf32_ptr(s.rotations)), R._free(R.vf32_ptr(s.alphas)), R._free(R.vf32_ptr(s.colors)), R._free(R.vf32_ptr(s.sh));
};
var mI = async (R, s) => {
var f;
const i = await TI(), L = R instanceof Uint8Array ? R : new Uint8Array(R);
let k = null;
try {
if (k = i._malloc(
Uint8Array.BYTES_PER_ELEMENT * L.length
), k === null)
throw new Error("couldn't allocate memory");
i.HEAPU8.set(L, k / Uint8Array.BYTES_PER_ELEMENT);
const r = i.CoordinateSystem[((f = s == null ? void 0 : s.unpackOptions) == null ? void 0 : f.coordinateSystem) ?? "UNSPECIFIED"], x = i.load_spz(k, L.length, {
coordinateSystem: r
}), p = PI(
i,
x,
s
);
return uI(i, x), p;
} catch (r) {
throw r;
} finally {
k !== null && i._free(k);
}
};
var bI = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null
}, Symbol.toStringTag, { value: "Module" }));
// packages/engine/Source/Scene/GltfSpzLoader.js
function GltfSpzLoader(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const resourceCache = options.resourceCache;
const gltf = options.gltf;
const primitive = options.primitive;
const spz = options.spz;
const gltfResource = options.gltfResource;
const baseResource2 = options.baseResource;
const cacheKey = options.cacheKey;
Check_default.typeOf.func("options.resourceCache", resourceCache);
Check_default.typeOf.object("options.gltf", gltf);
Check_default.typeOf.object("options.primitive", primitive);
Check_default.typeOf.object("options.spz", spz);
Check_default.typeOf.object("options.gltfResource", gltfResource);
Check_default.typeOf.object("options.baseResource", baseResource2);
this._resourceCache = resourceCache;
this._gltfResource = gltfResource;
this._baseResource = baseResource2;
this._gltf = gltf;
this._primitive = primitive;
this._spz = spz;
this._cacheKey = cacheKey;
this._bufferViewLoader = void 0;
this._bufferViewTypedArray = void 0;
this._decodePromise = void 0;
this._decodedData = void 0;
this._state = ResourceLoaderState_default.UNLOADED;
this._promise = void 0;
this._spzError = void 0;
}
if (defined_default(Object.create)) {
GltfSpzLoader.prototype = Object.create(ResourceLoader_default.prototype);
GltfSpzLoader.prototype.constructor = GltfSpzLoader;
}
Object.defineProperties(GltfSpzLoader.prototype, {
/**
* The cache key of the resource.
* @memberof GltfSpzLoader.prototype
* @type {string}
* @readonly
* @private
*/
cacheKey: {
get: function() {
return this._cacheKey;
}
},
/**
* The decoded SPZ data.
* @memberof GltfSpzLoader.prototype
* @type {object}
* @readonly
* @private
*/
decodedData: {
get: function() {
return this._decodedData;
}
}
});
async function loadResources4(loader) {
const resourceCache = loader._resourceCache;
try {
const bufferViewLoader = resourceCache.getBufferViewLoader({
gltf: loader._gltf,
bufferViewId: 0,
gltfResource: loader._gltfResource,
baseResource: loader._baseResource
});
loader._bufferViewLoader = bufferViewLoader;
await bufferViewLoader.load();
if (loader.isDestroyed()) {
return;
}
loader._bufferViewTypedArray = bufferViewLoader.typedArray;
loader._state = ResourceLoaderState_default.PROCESSING;
return loader;
} catch (error) {
if (loader.isDestroyed()) {
return;
}
handleError6(loader, error);
}
}
GltfSpzLoader.prototype.load = async function() {
if (defined_default(this._promise)) {
return this._promise;
}
this._state = ResourceLoaderState_default.LOADING;
this._promise = loadResources4(this);
return this._promise;
};
function handleError6(spzLoader, error) {
spzLoader.unload();
spzLoader._state = ResourceLoaderState_default.FAILED;
const errorMessage = "Failed to load SPZ";
throw spzLoader.getError(errorMessage, error);
}
async function processDecode2(loader, decodePromise) {
try {
const gcloud = await decodePromise;
if (loader.isDestroyed()) {
return;
}
loader.unload();
loader._decodedData = {
gcloud
};
loader._state = ResourceLoaderState_default.READY;
return loader._baseResource;
} catch (error) {
if (loader.isDestroyed()) {
return;
}
loader._spzError = error;
}
}
GltfSpzLoader.prototype.process = function(frameState) {
Check_default.typeOf.object("frameState", frameState);
if (this._state === ResourceLoaderState_default.READY) {
return true;
}
if (this._state !== ResourceLoaderState_default.PROCESSING) {
return false;
}
if (defined_default(this._spzError)) {
handleError6(this, this._spzError);
}
if (!defined_default(this._bufferViewTypedArray)) {
return false;
}
if (defined_default(this._decodePromise)) {
return false;
}
const decodePromise = mI(this._bufferViewTypedArray, {
unpackOptions: { coordinateSystem: "UNSPECIFIED" }
});
if (!defined_default(decodePromise)) {
return false;
}
this._decodePromise = processDecode2(this, decodePromise);
};
GltfSpzLoader.prototype.unload = function() {
if (defined_default(this._bufferViewLoader)) {
this._resourceCache.unload(this._bufferViewLoader);
}
this._bufferViewLoader = void 0;
this._bufferViewTypedArray = void 0;
this._decodedData = void 0;
this._gltf = void 0;
this._primitive = void 0;
};
var GltfSpzLoader_default = GltfSpzLoader;
// packages/engine/Source/Scene/MetadataSchemaLoader.js
var import_InlineWorkers519 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/MetadataSchema.js
var import_InlineWorkers518 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/MetadataClass.js
var import_InlineWorkers515 = __toESM(require_InlineWorkers(), 1);
function MetadataClass(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const id = options.id;
Check_default.typeOf.string("options.id", id);
const properties = options.properties ?? {};
const propertiesBySemantic = {};
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId)) {
const property = properties[propertyId];
if (defined_default(property.semantic)) {
propertiesBySemantic[property.semantic] = property;
}
}
}
this._id = id;
this._name = options.name;
this._description = options.description;
this._properties = properties;
this._propertiesBySemantic = propertiesBySemantic;
this._extras = clone_default(options.extras, true);
this._extensions = clone_default(options.extensions, true);
}
MetadataClass.fromJson = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const id = options.id;
const classDefinition = options.class;
Check_default.typeOf.string("options.id", id);
Check_default.typeOf.object("options.class", classDefinition);
const properties = {};
for (const propertyId in classDefinition.properties) {
if (classDefinition.properties.hasOwnProperty(propertyId)) {
const property = MetadataClassProperty_default.fromJson({
id: propertyId,
property: classDefinition.properties[propertyId],
enums: options.enums
});
properties[propertyId] = property;
}
}
return new MetadataClass({
id,
name: classDefinition.name,
description: classDefinition.description,
properties,
extras: classDefinition.extras,
extensions: classDefinition.extensions
});
};
Object.defineProperties(MetadataClass.prototype, {
/**
* The class properties.
*
* @memberof MetadataClass.prototype
* @type {Object3DTILES_metadata extension is used,
* this property stores a {@link MetadataTable} instance for the tiles in the subtree.
*
* @type {MetadataTable}
* @readonly
* @private
*/
tileMetadataTable: {
get: function() {
return this._tileMetadataTable;
}
},
/**
* When tile metadata is present (3D Tiles 1.1) or the 3DTILES_metadata extension is used,
* this property stores the JSON from the extension. This is used by {@link TileMetadata}
* to get the extras and extensions for the tiles in the subtree.
*
* @type {object}
* @readonly
* @private
*/
tilePropertyTableJson: {
get: function() {
return this._tilePropertyTableJson;
}
},
/**
* When content metadata is present (3D Tiles 1.1), this property stores
* an array of {@link MetadataTable} instances for the contents in the subtree.
*
* @type {Array}
* @readonly
* @private
*/
contentMetadataTables: {
get: function() {
return this._contentMetadataTables;
}
},
/**
* When content metadata is present (3D Tiles 1.1), this property
* an array of the JSONs from the extension. This is used to get the extras
* and extensions for the contents in the subtree.
*
* @type {Array}
* @readonly
* @private
*/
contentPropertyTableJsons: {
get: function() {
return this._contentPropertyTableJsons;
}
},
/**
* Gets the implicit tile coordinates for the root of the subtree.
*
* @type {ImplicitTileCoordinates}
* @readonly
* @private
*/
implicitCoordinates: {
get: function() {
return this._implicitCoordinates;
}
}
});
ImplicitSubtree.prototype.tileIsAvailableAtIndex = function(index) {
return this._tileAvailability.getBit(index);
};
ImplicitSubtree.prototype.tileIsAvailableAtCoordinates = function(implicitCoordinates) {
const index = this.getTileIndex(implicitCoordinates);
return this.tileIsAvailableAtIndex(index);
};
ImplicitSubtree.prototype.contentIsAvailableAtIndex = function(index, contentIndex) {
contentIndex = contentIndex ?? 0;
if (contentIndex < 0 || contentIndex >= this._contentAvailabilityBitstreams.length) {
throw new DeveloperError_default("contentIndex out of bounds.");
}
return this._contentAvailabilityBitstreams[contentIndex].getBit(index);
};
ImplicitSubtree.prototype.contentIsAvailableAtCoordinates = function(implicitCoordinates, contentIndex) {
const index = this.getTileIndex(implicitCoordinates);
return this.contentIsAvailableAtIndex(index, contentIndex);
};
ImplicitSubtree.prototype.childSubtreeIsAvailableAtIndex = function(index) {
return this._childSubtreeAvailability.getBit(index);
};
ImplicitSubtree.prototype.childSubtreeIsAvailableAtCoordinates = function(implicitCoordinates) {
const index = this.getChildSubtreeIndex(implicitCoordinates);
return this.childSubtreeIsAvailableAtIndex(index);
};
ImplicitSubtree.prototype.getLevelOffset = function(level) {
const branchingFactor = this._branchingFactor;
return (Math.pow(branchingFactor, level) - 1) / (branchingFactor - 1);
};
ImplicitSubtree.prototype.getParentMortonIndex = function(mortonIndex) {
let bitsPerLevel = 2;
if (this._subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
bitsPerLevel = 3;
}
return mortonIndex >> bitsPerLevel;
};
ImplicitSubtree.fromSubtreeJson = async function(resource, json, subtreeView, implicitTileset, implicitCoordinates) {
Check_default.typeOf.object("resource", resource);
if (defined_default(json) === defined_default(subtreeView)) {
throw new DeveloperError_default("One of json and subtreeView must be defined.");
}
Check_default.typeOf.object("implicitTileset", implicitTileset);
Check_default.typeOf.object("implicitCoordinates", implicitCoordinates);
const subtree = new ImplicitSubtree(
resource,
implicitTileset,
implicitCoordinates
);
let chunks;
if (defined_default(json)) {
chunks = {
json,
binary: void 0
};
} else {
chunks = parseSubtreeChunks(subtreeView);
}
const subtreeJson = chunks.json;
subtree._subtreeJson = subtreeJson;
let tilePropertyTableJson;
if (hasExtension_default(subtreeJson, "3DTILES_metadata")) {
tilePropertyTableJson = subtreeJson.extensions["3DTILES_metadata"];
} else if (defined_default(subtreeJson.tileMetadata)) {
const propertyTableIndex = subtreeJson.tileMetadata;
tilePropertyTableJson = subtreeJson.propertyTables[propertyTableIndex];
}
const contentPropertyTableJsons = [];
if (defined_default(subtreeJson.contentMetadata)) {
const length2 = subtreeJson.contentMetadata.length;
for (let i = 0; i < length2; i++) {
const propertyTableIndex = subtreeJson.contentMetadata[i];
contentPropertyTableJsons.push(
subtreeJson.propertyTables[propertyTableIndex]
);
}
}
let metadata;
const schema = implicitTileset.metadataSchema;
const subtreeMetadata = subtreeJson.subtreeMetadata;
if (defined_default(subtreeMetadata)) {
const metadataClass = subtreeMetadata.class;
const subtreeMetadataClass = schema.classes[metadataClass];
metadata = new ImplicitSubtreeMetadata_default({
subtreeMetadata,
class: subtreeMetadataClass
});
}
subtree._metadata = metadata;
subtree._tilePropertyTableJson = tilePropertyTableJson;
subtree._contentPropertyTableJsons = contentPropertyTableJsons;
const defaultContentAvailability = {
constant: 0
};
subtreeJson.contentAvailabilityHeaders = [];
if (hasExtension_default(subtreeJson, "3DTILES_multiple_contents")) {
subtreeJson.contentAvailabilityHeaders = subtreeJson.extensions["3DTILES_multiple_contents"].contentAvailability;
} else if (Array.isArray(subtreeJson.contentAvailability)) {
subtreeJson.contentAvailabilityHeaders = subtreeJson.contentAvailability;
} else {
subtreeJson.contentAvailabilityHeaders.push(
subtreeJson.contentAvailability ?? defaultContentAvailability
);
}
const bufferHeaders = preprocessBuffers(subtreeJson.buffers);
const bufferViewHeaders = preprocessBufferViews(
subtreeJson.bufferViews,
bufferHeaders
);
markActiveBufferViews(subtreeJson, bufferViewHeaders);
if (defined_default(tilePropertyTableJson)) {
markActiveMetadataBufferViews(tilePropertyTableJson, bufferViewHeaders);
}
for (let i = 0; i < contentPropertyTableJsons.length; i++) {
const contentPropertyTableJson = contentPropertyTableJsons[i];
markActiveMetadataBufferViews(contentPropertyTableJson, bufferViewHeaders);
}
const buffersU8 = await requestActiveBuffers(
subtree,
bufferHeaders,
chunks.binary
);
const bufferViewsU8 = parseActiveBufferViews(bufferViewHeaders, buffersU8);
parseAvailability(subtree, subtreeJson, implicitTileset, bufferViewsU8);
if (defined_default(tilePropertyTableJson)) {
parseTileMetadataTable(subtree, implicitTileset, bufferViewsU8);
makeTileJumpBuffer(subtree);
}
parseContentMetadataTables(subtree, implicitTileset, bufferViewsU8);
makeContentJumpBuffers(subtree);
subtree._ready = true;
return subtree;
};
function parseSubtreeChunks(subtreeView) {
const littleEndian2 = true;
const subtreeReader = new DataView(
subtreeView.buffer,
subtreeView.byteOffset
);
let byteOffset = 8;
const jsonByteLength = subtreeReader.getUint32(byteOffset, littleEndian2);
byteOffset += 8;
const binaryByteLength = subtreeReader.getUint32(byteOffset, littleEndian2);
byteOffset += 8;
const subtreeJson = getJsonFromTypedArray_default(
subtreeView,
byteOffset,
jsonByteLength
);
byteOffset += jsonByteLength;
const subtreeBinary = subtreeView.subarray(
byteOffset,
byteOffset + binaryByteLength
);
return {
json: subtreeJson,
binary: subtreeBinary
};
}
function preprocessBuffers(bufferHeaders) {
bufferHeaders = defined_default(bufferHeaders) ? bufferHeaders : [];
for (let i = 0; i < bufferHeaders.length; i++) {
const bufferHeader = bufferHeaders[i];
bufferHeader.isExternal = defined_default(bufferHeader.uri);
bufferHeader.isActive = false;
}
return bufferHeaders;
}
function preprocessBufferViews(bufferViewHeaders, bufferHeaders) {
bufferViewHeaders = defined_default(bufferViewHeaders) ? bufferViewHeaders : [];
for (let i = 0; i < bufferViewHeaders.length; i++) {
const bufferViewHeader = bufferViewHeaders[i];
const bufferHeader = bufferHeaders[bufferViewHeader.buffer];
bufferViewHeader.bufferHeader = bufferHeader;
bufferViewHeader.isActive = false;
}
return bufferViewHeaders;
}
function markActiveBufferViews(subtreeJson, bufferViewHeaders) {
let header;
const tileAvailabilityHeader = subtreeJson.tileAvailability;
if (defined_default(tileAvailabilityHeader.bitstream)) {
header = bufferViewHeaders[tileAvailabilityHeader.bitstream];
} else if (defined_default(tileAvailabilityHeader.bufferView)) {
header = bufferViewHeaders[tileAvailabilityHeader.bufferView];
}
if (defined_default(header)) {
header.isActive = true;
header.bufferHeader.isActive = true;
}
const contentAvailabilityHeaders = subtreeJson.contentAvailabilityHeaders;
for (let i = 0; i < contentAvailabilityHeaders.length; i++) {
header = void 0;
if (defined_default(contentAvailabilityHeaders[i].bitstream)) {
header = bufferViewHeaders[contentAvailabilityHeaders[i].bitstream];
} else if (defined_default(contentAvailabilityHeaders[i].bufferView)) {
header = bufferViewHeaders[contentAvailabilityHeaders[i].bufferView];
}
if (defined_default(header)) {
header.isActive = true;
header.bufferHeader.isActive = true;
}
}
header = void 0;
const childSubtreeAvailabilityHeader = subtreeJson.childSubtreeAvailability;
if (defined_default(childSubtreeAvailabilityHeader.bitstream)) {
header = bufferViewHeaders[childSubtreeAvailabilityHeader.bitstream];
} else if (defined_default(childSubtreeAvailabilityHeader.bufferView)) {
header = bufferViewHeaders[childSubtreeAvailabilityHeader.bufferView];
}
if (defined_default(header)) {
header.isActive = true;
header.bufferHeader.isActive = true;
}
}
function markActiveMetadataBufferViews(propertyTableJson, bufferViewHeaders) {
const properties = propertyTableJson.properties;
let header;
for (const key in properties) {
if (properties.hasOwnProperty(key)) {
const metadataHeader = properties[key];
const valuesBufferView = metadataHeader.values ?? metadataHeader.bufferView;
header = bufferViewHeaders[valuesBufferView];
header.isActive = true;
header.bufferHeader.isActive = true;
const stringOffsetBufferView = metadataHeader.stringOffsets ?? metadataHeader.stringOffsetBufferView;
if (defined_default(stringOffsetBufferView)) {
header = bufferViewHeaders[stringOffsetBufferView];
header.isActive = true;
header.bufferHeader.isActive = true;
}
const arrayOffsetBufferView = metadataHeader.arrayOffsets ?? metadataHeader.arrayOffsetBufferView;
if (defined_default(arrayOffsetBufferView)) {
header = bufferViewHeaders[arrayOffsetBufferView];
header.isActive = true;
header.bufferHeader.isActive = true;
}
}
}
}
function requestActiveBuffers(subtree, bufferHeaders, internalBuffer) {
const promises = [];
for (let i = 0; i < bufferHeaders.length; i++) {
const bufferHeader = bufferHeaders[i];
if (!bufferHeader.isActive) {
promises.push(Promise.resolve(void 0));
} else if (bufferHeader.isExternal) {
const promise = requestExternalBuffer(subtree, bufferHeader);
promises.push(promise);
} else {
promises.push(Promise.resolve(internalBuffer));
}
}
return Promise.all(promises).then(function(bufferResults) {
const buffersU8 = {};
for (let i = 0; i < bufferResults.length; i++) {
const result = bufferResults[i];
if (defined_default(result)) {
buffersU8[i] = result;
}
}
return buffersU8;
});
}
async function requestExternalBuffer(subtree, bufferHeader) {
const baseResource2 = subtree._resource;
const bufferResource = baseResource2.getDerivedResource({
url: bufferHeader.uri
});
const bufferLoader = ResourceCache_default.getExternalBufferLoader({
resource: bufferResource
});
subtree._bufferLoader = bufferLoader;
try {
await bufferLoader.load();
} catch (error) {
if (bufferLoader.isDestroyed()) {
return;
}
throw error;
}
return bufferLoader.typedArray;
}
function parseActiveBufferViews(bufferViewHeaders, buffersU8) {
const bufferViewsU8 = {};
for (let i = 0; i < bufferViewHeaders.length; i++) {
const bufferViewHeader = bufferViewHeaders[i];
if (!bufferViewHeader.isActive) {
continue;
}
const start = bufferViewHeader.byteOffset;
const end = start + bufferViewHeader.byteLength;
const buffer2 = buffersU8[bufferViewHeader.buffer];
const bufferView = buffer2.subarray(start, end);
bufferViewsU8[i] = bufferView;
}
return bufferViewsU8;
}
function parseAvailability(subtree, subtreeJson, implicitTileset, bufferViewsU8) {
const branchingFactor = implicitTileset.branchingFactor;
const subtreeLevels = implicitTileset.subtreeLevels;
const tileAvailabilityBits = (Math.pow(branchingFactor, subtreeLevels) - 1) / (branchingFactor - 1);
const childSubtreeBits = Math.pow(branchingFactor, subtreeLevels);
const hasMetadataExtension = hasExtension_default(subtreeJson, "3DTILES_metadata");
const hasTileMetadata = defined_default(subtree._tilePropertyTableJson);
let computeAvailableCountEnabled = hasMetadataExtension || hasTileMetadata;
subtree._tileAvailability = parseAvailabilityBitstream(
subtreeJson.tileAvailability,
bufferViewsU8,
tileAvailabilityBits,
computeAvailableCountEnabled
);
const hasContentMetadata = subtree._contentPropertyTableJsons.length > 0;
computeAvailableCountEnabled = computeAvailableCountEnabled || hasContentMetadata;
for (let i = 0; i < subtreeJson.contentAvailabilityHeaders.length; i++) {
const bitstream = parseAvailabilityBitstream(
subtreeJson.contentAvailabilityHeaders[i],
bufferViewsU8,
// content availability has the same length as tile availability.
tileAvailabilityBits,
computeAvailableCountEnabled
);
subtree._contentAvailabilityBitstreams.push(bitstream);
}
subtree._childSubtreeAvailability = parseAvailabilityBitstream(
subtreeJson.childSubtreeAvailability,
bufferViewsU8,
childSubtreeBits
);
}
function parseAvailabilityBitstream(availabilityJson, bufferViewsU8, lengthBits, computeAvailableCountEnabled) {
if (defined_default(availabilityJson.constant)) {
return new ImplicitAvailabilityBitstream_default({
constant: Boolean(availabilityJson.constant),
lengthBits,
availableCount: availabilityJson.availableCount
});
}
let bufferView;
if (defined_default(availabilityJson.bitstream)) {
bufferView = bufferViewsU8[availabilityJson.bitstream];
} else if (defined_default(availabilityJson.bufferView)) {
bufferView = bufferViewsU8[availabilityJson.bufferView];
}
return new ImplicitAvailabilityBitstream_default({
bitstream: bufferView,
lengthBits,
availableCount: availabilityJson.availableCount,
computeAvailableCountEnabled
});
}
function parseTileMetadataTable(subtree, implicitTileset, bufferViewsU8) {
const tilePropertyTableJson = subtree._tilePropertyTableJson;
const tileCount = subtree._tileAvailability.availableCount;
const metadataSchema = implicitTileset.metadataSchema;
const tileMetadataClassName = tilePropertyTableJson.class;
const tileMetadataClass = metadataSchema.classes[tileMetadataClassName];
subtree._tileMetadataTable = new MetadataTable_default({
class: tileMetadataClass,
count: tileCount,
properties: tilePropertyTableJson.properties,
bufferViews: bufferViewsU8
});
}
function parseContentMetadataTables(subtree, implicitTileset, bufferViewsU8) {
const contentPropertyTableJsons = subtree._contentPropertyTableJsons;
const contentAvailabilityBitstreams = subtree._contentAvailabilityBitstreams;
const metadataSchema = implicitTileset.metadataSchema;
const contentMetadataTables = subtree._contentMetadataTables;
for (let i = 0; i < contentPropertyTableJsons.length; i++) {
const contentPropertyTableJson = contentPropertyTableJsons[i];
const contentAvailabilityBitsteam = contentAvailabilityBitstreams[i];
const contentCount = contentAvailabilityBitsteam.availableCount;
const contentMetadataClassName = contentPropertyTableJson.class;
const contentMetadataClass = metadataSchema.classes[contentMetadataClassName];
const metadataTable = new MetadataTable_default({
class: contentMetadataClass,
count: contentCount,
properties: contentPropertyTableJson.properties,
bufferViews: bufferViewsU8
});
contentMetadataTables.push(metadataTable);
}
}
function makeJumpBuffer(availability) {
let entityId = 0;
const bufferLength = availability.lengthBits;
const availableCount = availability.availableCount;
let jumpBuffer;
if (availableCount < 256) {
jumpBuffer = new Uint8Array(bufferLength);
} else if (availableCount < 65536) {
jumpBuffer = new Uint16Array(bufferLength);
} else {
jumpBuffer = new Uint32Array(bufferLength);
}
for (let i = 0; i < availability.lengthBits; i++) {
if (availability.getBit(i)) {
jumpBuffer[i] = entityId;
entityId++;
}
}
return jumpBuffer;
}
function makeTileJumpBuffer(subtree) {
const tileJumpBuffer = makeJumpBuffer(subtree._tileAvailability);
subtree._tileJumpBuffer = tileJumpBuffer;
}
function makeContentJumpBuffers(subtree) {
const contentJumpBuffers = subtree._contentJumpBuffers;
const contentAvailabilityBitstreams = subtree._contentAvailabilityBitstreams;
for (let i = 0; i < contentAvailabilityBitstreams.length; i++) {
const contentAvailability = contentAvailabilityBitstreams[i];
const contentJumpBuffer = makeJumpBuffer(contentAvailability);
contentJumpBuffers.push(contentJumpBuffer);
}
}
ImplicitSubtree.prototype.getTileIndex = function(implicitCoordinates) {
const localLevel = implicitCoordinates.level - this._implicitCoordinates.level;
if (localLevel < 0 || this._subtreeLevels <= localLevel) {
throw new RuntimeError_default("level is out of bounds for this subtree");
}
const subtreeCoordinates = implicitCoordinates.getSubtreeCoordinates();
const offsetCoordinates = subtreeCoordinates.getOffsetCoordinates(implicitCoordinates);
const index = offsetCoordinates.tileIndex;
return index;
};
ImplicitSubtree.prototype.getChildSubtreeIndex = function(implicitCoordinates) {
const localLevel = implicitCoordinates.level - this._implicitCoordinates.level;
if (localLevel !== this._implicitCoordinates.subtreeLevels) {
throw new RuntimeError_default("level is out of bounds for this subtree");
}
const parentSubtreeCoordinates = implicitCoordinates.getParentSubtreeCoordinates();
const offsetCoordinates = parentSubtreeCoordinates.getOffsetCoordinates(implicitCoordinates);
const index = offsetCoordinates.mortonIndex;
return index;
};
function getTileEntityId(subtree, implicitCoordinates) {
if (!defined_default(subtree._tileMetadataTable)) {
return void 0;
}
const tileIndex = subtree.getTileIndex(implicitCoordinates);
if (subtree._tileAvailability.getBit(tileIndex)) {
return subtree._tileJumpBuffer[tileIndex];
}
return void 0;
}
function getContentEntityId(subtree, implicitCoordinates, contentIndex) {
const metadataTables = subtree._contentMetadataTables;
if (!defined_default(metadataTables)) {
return void 0;
}
const metadataTable = metadataTables[contentIndex];
if (!defined_default(metadataTable)) {
return void 0;
}
const availability = subtree._contentAvailabilityBitstreams[contentIndex];
const tileIndex = subtree.getTileIndex(implicitCoordinates);
if (availability.getBit(tileIndex)) {
const contentJumpBuffer = subtree._contentJumpBuffers[contentIndex];
return contentJumpBuffer[tileIndex];
}
return void 0;
}
ImplicitSubtree.prototype.getTileMetadataView = function(implicitCoordinates) {
const entityId = getTileEntityId(this, implicitCoordinates);
if (!defined_default(entityId)) {
return void 0;
}
const metadataTable = this._tileMetadataTable;
return new ImplicitMetadataView_default({
class: metadataTable.class,
metadataTable,
entityId,
propertyTableJson: this._tilePropertyTableJson
});
};
ImplicitSubtree.prototype.getContentMetadataView = function(implicitCoordinates, contentIndex) {
const entityId = getContentEntityId(this, implicitCoordinates, contentIndex);
if (!defined_default(entityId)) {
return void 0;
}
const metadataTable = this._contentMetadataTables[contentIndex];
const propertyTableJson = this._contentPropertyTableJsons[contentIndex];
return new ImplicitMetadataView_default({
class: metadataTable.class,
metadataTable,
entityId,
contentIndex,
propertyTableJson
});
};
ImplicitSubtree.prototype.isDestroyed = function() {
return false;
};
ImplicitSubtree.prototype.destroy = function() {
if (defined_default(this._bufferLoader)) {
ResourceCache_default.unload(this._bufferLoader);
}
return destroyObject_default(this);
};
var ImplicitSubtree_default = ImplicitSubtree;
// packages/engine/Source/Scene/MetadataSemantic.js
var import_InlineWorkers524 = __toESM(require_InlineWorkers(), 1);
var MetadataSemantic = {
/**
* A unique identifier, stored as a STRING.
*
* @type {string}
* @constant
* @private
*/
ID: "ID",
/**
* A name, stored as a STRING. This does not have to be unique.
*
* @type {string}
* @constant
* @private
*/
NAME: "NAME",
/**
* A description, stored as a STRING.
*
* @type {string}
* @constant
* @private
*/
DESCRIPTION: "DESCRIPTION",
/**
* The number of tiles in a tileset, stored as a UINT64.
*
* @type {string}
* @constant
* @private
*/
TILESET_TILE_COUNT: "TILESET_TILE_COUNT",
/**
* A bounding box for a tile, stored as an array of 12 FLOAT32 or FLOAT64 components. The components are the same format as for boundingVolume.box in 3D Tiles 1.0. This semantic is used to provide a tighter bounding volume than the one implicitly calculated in implicit tiling.
*
* @type {string}
* @constant
* @private
*/
TILE_BOUNDING_BOX: "TILE_BOUNDING_BOX",
/**
* A bounding region for a tile, stored as an array of 6 FLOAT64 components. The components are [west, south, east, north, minimumHeight, maximumHeight]. This semantic is used to provide a tighter bounding volume than the one implicitly calculated in implicit tiling.
*
* @type {string}
* @constant
* @private
*/
TILE_BOUNDING_REGION: "TILE_BOUNDING_REGION",
/**
* A bounding sphere for a tile, stored as an array of 4 FLOAT32 or FLOAT64 components. The components are [centerX, centerY, centerZ, radius]. This semantic is used to provide a tighter bounding volume than the one implicitly calculated in implicit tiling.
*
* @type {string}
* @constant
* @private
*/
TILE_BOUNDING_SPHERE: "TILE_BOUNDING_SPHERE",
/**
* The minimum height of a tile above (or below) the ellipsoid, stored as a FLOAT32 or a FLOAT64. This semantic is used to tighten bounding regions implicitly calculated in implicit tiling.
*
* @type {string}
* @constant
* @private
*/
TILE_MINIMUM_HEIGHT: "TILE_MINIMUM_HEIGHT",
/**
* The maximum height of a tile above (or below) the ellipsoid, stored as a FLOAT32 or a FLOAT64. This semantic is used to tighten bounding regions implicitly calculated in implicit tiling.
*
* @type {string}
* @constant
* @private
*/
TILE_MAXIMUM_HEIGHT: "TILE_MAXIMUM_HEIGHT",
/**
* The horizon occlusion point for a tile, stored as an VEC3 of FLOAT32 or FLOAT64 components.
*
* @see {@link https://cesium.com/blog/2013/04/25/horizon-culling/|Horizon Culling}
*
* @type {string}
* @constant
* @private
*/
TILE_HORIZON_OCCLUSION_POINT: "TILE_HORIZON_OCCLUSION_POINT",
/**
* The geometric error for a tile, stored as a FLOAT32 or a FLOAT64. This semantic is used to override the geometric error implicitly calculated in implicit tiling.
*
* @type {string}
* @constant
* @private
*/
TILE_GEOMETRIC_ERROR: "TILE_GEOMETRIC_ERROR",
/**
* A bounding box for the content of a tile, stored as an array of 12 FLOAT32 or FLOAT64 components. The components are the same format as for boundingVolume.box in 3D Tiles 1.0. This semantic is used to provide a tighter bounding volume than the one implicitly calculated in implicit tiling.
*
* @type {string}
* @constant
* @private
*/
CONTENT_BOUNDING_BOX: "CONTENT_BOUNDING_BOX",
/**
* A bounding region for the content of a tile, stored as an array of 6 FLOAT64 components. The components are [west, south, east, north, minimumHeight, maximumHeight]. This semantic is used to provide a tighter bounding volume than the one implicitly calculated in implicit tiling.
*
* @type {string}
* @constant
* @private
*/
CONTENT_BOUNDING_REGION: "CONTENT_BOUNDING_REGION",
/**
* A bounding sphere for the content of a tile, stored as an array of 4 FLOAT32 or FLOAT64 components. The components are [centerX, centerY, centerZ, radius]. This semantic is used to provide a tighter bounding volume than the one implicitly calculated in implicit tiling.
*
* @type {string}
* @constant
* @private
*/
CONTENT_BOUNDING_SPHERE: "CONTENT_BOUNDING_SPHERE",
/**
* The minimum height of the content of a tile above (or below) the ellipsoid, stored as a FLOAT32 or a FLOAT64
*
* @type {string}
* @constant
* @private
*/
CONTENT_MINIMUM_HEIGHT: "CONTENT_MINIMUM_HEIGHT",
/**
* The maximum height of the content of a tile above (or below) the ellipsoid, stored as a FLOAT32 or a FLOAT64
*
* @type {string}
* @constant
* @private
*/
CONTENT_MAXIMUM_HEIGHT: "CONTENT_MAXIMUM_HEIGHT",
/**
* The horizon occlusion point for the content of a tile, stored as an VEC3 of FLOAT32 or FLOAT64 components.
*
* @see {@link https://cesium.com/blog/2013/04/25/horizon-culling/|Horizon Culling}
*
* @type {string}
* @constant
* @private
*/
CONTENT_HORIZON_OCCLUSION_POINT: "CONTENT_HORIZON_OCCLUSION_POINT"
};
var MetadataSemantic_default = Object.freeze(MetadataSemantic);
// packages/engine/Source/Scene/BoundingVolumeSemantics.js
var import_InlineWorkers525 = __toESM(require_InlineWorkers(), 1);
var BoundingVolumeSemantics = {};
BoundingVolumeSemantics.parseAllBoundingVolumeSemantics = function(tileMetadata) {
Check_default.typeOf.object("tileMetadata", tileMetadata);
return {
tile: {
boundingVolume: BoundingVolumeSemantics.parseBoundingVolumeSemantic(
"TILE",
tileMetadata
),
minimumHeight: BoundingVolumeSemantics._parseMinimumHeight(
"TILE",
tileMetadata
),
maximumHeight: BoundingVolumeSemantics._parseMaximumHeight(
"TILE",
tileMetadata
)
},
content: {
boundingVolume: BoundingVolumeSemantics.parseBoundingVolumeSemantic(
"CONTENT",
tileMetadata
),
minimumHeight: BoundingVolumeSemantics._parseMinimumHeight(
"CONTENT",
tileMetadata
),
maximumHeight: BoundingVolumeSemantics._parseMaximumHeight(
"CONTENT",
tileMetadata
)
}
};
};
BoundingVolumeSemantics.parseBoundingVolumeSemantic = function(prefix, tileMetadata) {
Check_default.typeOf.string("prefix", prefix);
if (prefix !== "TILE" && prefix !== "CONTENT") {
throw new DeveloperError_default("prefix must be either 'TILE' or 'CONTENT'");
}
Check_default.typeOf.object("tileMetadata", tileMetadata);
const boundingBoxSemantic = `${prefix}_BOUNDING_BOX`;
const boundingBox = tileMetadata.getPropertyBySemantic(boundingBoxSemantic);
if (defined_default(boundingBox)) {
return {
box: boundingBox
};
}
const boundingRegionSemantic = `${prefix}_BOUNDING_REGION`;
const boundingRegion = tileMetadata.getPropertyBySemantic(
boundingRegionSemantic
);
if (defined_default(boundingRegion)) {
return {
region: boundingRegion
};
}
const boundingSphereSemantic = `${prefix}_BOUNDING_SPHERE`;
const boundingSphere = tileMetadata.getPropertyBySemantic(
boundingSphereSemantic
);
if (defined_default(boundingSphere)) {
return {
sphere: boundingSphere
};
}
return void 0;
};
BoundingVolumeSemantics._parseMinimumHeight = function(prefix, tileMetadata) {
Check_default.typeOf.string("prefix", prefix);
if (prefix !== "TILE" && prefix !== "CONTENT") {
throw new DeveloperError_default("prefix must be either 'TILE' or 'CONTENT'");
}
Check_default.typeOf.object("tileMetadata", tileMetadata);
const minimumHeightSemantic = `${prefix}_MINIMUM_HEIGHT`;
return tileMetadata.getPropertyBySemantic(minimumHeightSemantic);
};
BoundingVolumeSemantics._parseMaximumHeight = function(prefix, tileMetadata) {
Check_default.typeOf.string("prefix", prefix);
if (prefix !== "TILE" && prefix !== "CONTENT") {
throw new DeveloperError_default("prefix must be either 'TILE' or 'CONTENT'");
}
Check_default.typeOf.object("tileMetadata", tileMetadata);
const maximumHeightSemantic = `${prefix}_MAXIMUM_HEIGHT`;
return tileMetadata.getPropertyBySemantic(maximumHeightSemantic);
};
var BoundingVolumeSemantics_default = BoundingVolumeSemantics;
// packages/engine/Source/Scene/Implicit3DTileContent.js
function Implicit3DTileContent(tileset, tile, resource) {
Check_default.defined("tile.implicitTileset", tile.implicitTileset);
Check_default.defined("tile.implicitCoordinates", tile.implicitCoordinates);
const implicitTileset = tile.implicitTileset;
const implicitCoordinates = tile.implicitCoordinates;
this._implicitTileset = implicitTileset;
this._implicitCoordinates = implicitCoordinates;
this._implicitSubtree = void 0;
this._tileset = tileset;
this._tile = tile;
this._resource = resource;
this._metadata = void 0;
this.featurePropertiesDirty = false;
this._group = void 0;
const templateValues = implicitCoordinates.getTemplateValues();
const subtreeResource = implicitTileset.subtreeUriTemplate.getDerivedResource(
{
templateValues
}
);
this._url = subtreeResource.getUrlComponent(true);
this._ready = false;
}
Object.defineProperties(Implicit3DTileContent.prototype, {
featuresLength: {
get: function() {
return 0;
}
},
pointsLength: {
get: function() {
return 0;
}
},
trianglesLength: {
get: function() {
return 0;
}
},
geometryByteLength: {
get: function() {
return 0;
}
},
texturesByteLength: {
get: function() {
return 0;
}
},
batchTableByteLength: {
get: function() {
return 0;
}
},
innerContents: {
get: function() {
return void 0;
}
},
/**
* Returns true when the tile's content is ready to render; otherwise false
*
* @memberof Implicit3DTileContent.prototype
*
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
return this._ready;
}
},
tileset: {
get: function() {
return this._tileset;
}
},
tile: {
get: function() {
return this._tile;
}
},
url: {
get: function() {
return this._url;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Implicit3DTileContent
* always returns undefined. Only transcoded tiles have content metadata.
* @memberof Implicit3DTileContent.prototype
* @private
*/
metadata: {
get: function() {
return void 0;
},
set: function() {
throw new DeveloperError_default("Implicit3DTileContent cannot have metadata");
}
},
batchTable: {
get: function() {
return void 0;
}
},
group: {
get: function() {
return this._group;
},
set: function(value) {
this._group = value;
}
}
});
Implicit3DTileContent.fromSubtreeJson = async function(tileset, tile, resource, json, arrayBuffer, byteOffset) {
Check_default.defined("tile.implicitTileset", tile.implicitTileset);
Check_default.defined("tile.implicitCoordinates", tile.implicitCoordinates);
if (defined_default(json) === defined_default(arrayBuffer)) {
throw new DeveloperError_default("One of json and arrayBuffer must be defined.");
}
byteOffset = byteOffset ?? 0;
let uint8Array;
if (defined_default(arrayBuffer)) {
uint8Array = new Uint8Array(arrayBuffer, byteOffset);
}
const implicitTileset = tile.implicitTileset;
const implicitCoordinates = tile.implicitCoordinates;
const subtree = await ImplicitSubtree_default.fromSubtreeJson(
resource,
json,
uint8Array,
implicitTileset,
implicitCoordinates
);
const content = new Implicit3DTileContent(tileset, tile, resource);
content._implicitSubtree = subtree;
expandSubtree(content, subtree);
content._ready = true;
return content;
};
function expandSubtree(content, subtree) {
const placeholderTile = content._tile;
const childIndex = content._implicitCoordinates.childIndex;
const results = transcodeSubtreeTiles(
content,
subtree,
placeholderTile,
childIndex
);
const statistics2 = content._tileset.statistics;
placeholderTile.children.push(results.rootTile);
statistics2.numberOfTilesTotal++;
const childSubtrees = listChildSubtrees(content, subtree, results.bottomRow);
for (let i = 0; i < childSubtrees.length; i++) {
const subtreeLocator = childSubtrees[i];
const leafTile = subtreeLocator.tile;
const implicitChildTile = makePlaceholderChildSubtree(
content,
leafTile,
subtreeLocator.childIndex
);
leafTile.children.push(implicitChildTile);
statistics2.numberOfTilesTotal++;
}
}
function listChildSubtrees(content, subtree, bottomRow) {
const results = [];
const branchingFactor = content._implicitTileset.branchingFactor;
for (let i = 0; i < bottomRow.length; i++) {
const leafTile = bottomRow[i];
if (!defined_default(leafTile)) {
continue;
}
for (let j = 0; j < branchingFactor; j++) {
const index = i * branchingFactor + j;
if (subtree.childSubtreeIsAvailableAtIndex(index)) {
results.push({
tile: leafTile,
childIndex: j
});
}
}
}
return results;
}
function transcodeSubtreeTiles(content, subtree, placeholderTile, childIndex) {
const rootBitIndex = 0;
const rootParentIsPlaceholder = true;
const rootTile = deriveChildTile(
content,
subtree,
placeholderTile,
childIndex,
rootBitIndex,
rootParentIsPlaceholder
);
const statistics2 = content._tileset.statistics;
let parentRow = [rootTile];
let currentRow = [];
const implicitTileset = content._implicitTileset;
for (let level = 1; level < implicitTileset.subtreeLevels; level++) {
const levelOffset = subtree.getLevelOffset(level);
const numberOfChildren = implicitTileset.branchingFactor * parentRow.length;
for (let childMortonIndex = 0; childMortonIndex < numberOfChildren; childMortonIndex++) {
const childBitIndex = levelOffset + childMortonIndex;
if (!subtree.tileIsAvailableAtIndex(childBitIndex)) {
currentRow.push(void 0);
continue;
}
const parentMortonIndex = subtree.getParentMortonIndex(childMortonIndex);
const parentTile = parentRow[parentMortonIndex];
const childChildIndex = childMortonIndex % implicitTileset.branchingFactor;
const childTile = deriveChildTile(
content,
subtree,
parentTile,
childChildIndex,
childBitIndex
);
parentTile.children.push(childTile);
statistics2.numberOfTilesTotal++;
currentRow.push(childTile);
}
parentRow = currentRow;
currentRow = [];
}
return {
rootTile,
// At the end of the last loop, bottomRow was moved to parentRow
bottomRow: parentRow
};
}
function getGeometricError(tileMetadata, implicitTileset, implicitCoordinates) {
const semantic = MetadataSemantic_default.TILE_GEOMETRIC_ERROR;
if (defined_default(tileMetadata) && tileMetadata.hasPropertyBySemantic(semantic)) {
return tileMetadata.getPropertyBySemantic(semantic);
}
return implicitTileset.geometricError / Math.pow(2, implicitCoordinates.level);
}
function deriveChildTile(implicitContent, subtree, parentTile, childIndex, childBitIndex, parentIsPlaceholderTile) {
const implicitTileset = implicitContent._implicitTileset;
let implicitCoordinates;
if (parentIsPlaceholderTile ?? false) {
implicitCoordinates = parentTile.implicitCoordinates;
} else {
implicitCoordinates = parentTile.implicitCoordinates.getChildCoordinates(childIndex);
}
let tileMetadata;
let tileBounds;
let contentBounds;
if (defined_default(subtree.tilePropertyTableJson)) {
tileMetadata = subtree.getTileMetadataView(implicitCoordinates);
const boundingVolumeSemantics = BoundingVolumeSemantics_default.parseAllBoundingVolumeSemantics(tileMetadata);
tileBounds = boundingVolumeSemantics.tile;
contentBounds = boundingVolumeSemantics.content;
}
const contentPropertyTableJsons = subtree.contentPropertyTableJsons;
const length2 = contentPropertyTableJsons.length;
let hasImplicitContentMetadata = false;
for (let i = 0; i < length2; i++) {
if (subtree.contentIsAvailableAtCoordinates(implicitCoordinates, i)) {
hasImplicitContentMetadata = true;
break;
}
}
const boundingVolume = getTileBoundingVolume(
implicitTileset,
implicitCoordinates,
childIndex,
parentIsPlaceholderTile,
parentTile,
tileBounds
);
const contentJsons = [];
for (let i = 0; i < implicitTileset.contentCount; i++) {
if (!subtree.contentIsAvailableAtIndex(childBitIndex, i)) {
continue;
}
const childContentTemplate = implicitTileset.contentUriTemplates[i];
const childContentUri = childContentTemplate.getDerivedResource({
templateValues: implicitCoordinates.getTemplateValues()
}).url;
const contentJson = {
uri: childContentUri
};
const contentBoundingVolume = getContentBoundingVolume(
boundingVolume,
contentBounds
);
if (defined_default(contentBoundingVolume)) {
contentJson.boundingVolume = contentBoundingVolume;
}
contentJsons.push(combine_default(contentJson, implicitTileset.contentHeaders[i]));
}
const childGeometricError = getGeometricError(
tileMetadata,
implicitTileset,
implicitCoordinates
);
const tileJson = {
boundingVolume,
geometricError: childGeometricError,
refine: implicitTileset.refine,
contents: contentJsons
};
const deep = true;
const rootHeader = clone_default(implicitTileset.tileHeader, deep);
delete rootHeader.boundingVolume;
delete rootHeader.transform;
delete rootHeader.metadata;
const combinedTileJson = combine_default(tileJson, rootHeader, deep);
const childTile = makeTile(
implicitContent,
implicitTileset.baseResource,
combinedTileJson,
parentTile
);
childTile.implicitCoordinates = implicitCoordinates;
childTile.implicitSubtree = subtree;
childTile.metadata = tileMetadata;
childTile.hasImplicitContentMetadata = hasImplicitContentMetadata;
return childTile;
}
function canUpdateHeights(boundingVolume, tileBounds) {
return defined_default(boundingVolume) && defined_default(tileBounds) && (defined_default(tileBounds.minimumHeight) || defined_default(tileBounds.maximumHeight)) && (hasExtension_default(boundingVolume, "3DTILES_bounding_volume_S2") || defined_default(boundingVolume.region));
}
function updateHeights(boundingVolume, tileBounds) {
if (!defined_default(tileBounds)) {
return;
}
if (hasExtension_default(boundingVolume, "3DTILES_bounding_volume_S2")) {
updateS2CellHeights(
boundingVolume.extensions["3DTILES_bounding_volume_S2"],
tileBounds.minimumHeight,
tileBounds.maximumHeight
);
} else if (defined_default(boundingVolume.region)) {
updateRegionHeights(
boundingVolume.region,
tileBounds.minimumHeight,
tileBounds.maximumHeight
);
}
}
function updateRegionHeights(region, minimumHeight, maximumHeight) {
if (defined_default(minimumHeight)) {
region[4] = minimumHeight;
}
if (defined_default(maximumHeight)) {
region[5] = maximumHeight;
}
}
function updateS2CellHeights(s2CellVolume, minimumHeight, maximumHeight) {
if (defined_default(minimumHeight)) {
s2CellVolume.minimumHeight = minimumHeight;
}
if (defined_default(maximumHeight)) {
s2CellVolume.maximumHeight = maximumHeight;
}
}
function getTileBoundingVolume(implicitTileset, implicitCoordinates, childIndex, parentIsPlaceholderTile, parentTile, tileBounds) {
let boundingVolume;
if (!defined_default(tileBounds) || !defined_default(tileBounds.boundingVolume) || !canUpdateHeights(tileBounds.boundingVolume, tileBounds) && canUpdateHeights(implicitTileset.boundingVolume, tileBounds)) {
boundingVolume = deriveBoundingVolume(
implicitTileset,
implicitCoordinates,
childIndex,
parentIsPlaceholderTile ?? false,
parentTile
);
} else {
boundingVolume = tileBounds.boundingVolume;
}
updateHeights(boundingVolume, tileBounds);
return boundingVolume;
}
function getContentBoundingVolume(tileBoundingVolume, contentBounds) {
let contentBoundingVolume;
if (defined_default(contentBounds)) {
contentBoundingVolume = contentBounds.boundingVolume;
}
if (canUpdateHeights(contentBoundingVolume, contentBounds)) {
updateHeights(contentBoundingVolume, contentBounds);
} else if (canUpdateHeights(tileBoundingVolume, contentBounds)) {
contentBoundingVolume = clone_default(tileBoundingVolume, true);
updateHeights(contentBoundingVolume, contentBounds);
}
return contentBoundingVolume;
}
function deriveBoundingVolume(implicitTileset, implicitCoordinates, childIndex, parentIsPlaceholderTile, parentTile) {
const rootBoundingVolume = implicitTileset.boundingVolume;
if (hasExtension_default(rootBoundingVolume, "3DTILES_bounding_volume_S2")) {
return deriveBoundingVolumeS2(
parentIsPlaceholderTile,
parentTile,
childIndex,
implicitCoordinates.level,
implicitCoordinates.x,
implicitCoordinates.y,
implicitCoordinates.z
);
}
if (defined_default(rootBoundingVolume.region)) {
const childRegion = deriveBoundingRegion(
rootBoundingVolume.region,
implicitCoordinates.level,
implicitCoordinates.x,
implicitCoordinates.y,
implicitCoordinates.z
);
return {
region: childRegion
};
}
const childBox = deriveBoundingBox(
rootBoundingVolume.box,
implicitCoordinates.level,
implicitCoordinates.x,
implicitCoordinates.y,
implicitCoordinates.z
);
return {
box: childBox
};
}
function deriveBoundingVolumeS2(parentIsPlaceholderTile, parentTile, childIndex, level, x, y, z) {
Check_default.typeOf.bool("parentIsPlaceholderTile", parentIsPlaceholderTile);
Check_default.typeOf.object("parentTile", parentTile);
Check_default.typeOf.number("childIndex", childIndex);
Check_default.typeOf.number("level", level);
Check_default.typeOf.number("x", x);
Check_default.typeOf.number("y", y);
if (defined_default(z)) {
Check_default.typeOf.number("z", z);
}
const boundingVolumeS2 = parentTile._boundingVolume;
if (parentIsPlaceholderTile) {
return {
extensions: {
"3DTILES_bounding_volume_S2": {
token: S2Cell_default.getTokenFromId(boundingVolumeS2.s2Cell._cellId),
minimumHeight: boundingVolumeS2.minimumHeight,
maximumHeight: boundingVolumeS2.maximumHeight
}
}
};
}
const face = Number(parentTile._boundingVolume.s2Cell._cellId >> BigInt(61));
const position = face % 2 === 0 ? HilbertOrder_default.encode2D(level, x, y) : HilbertOrder_default.encode2D(level, y, x);
const cell = S2Cell_default.fromFacePositionLevel(face, BigInt(position), level);
let minHeight, maxHeight;
if (defined_default(z)) {
const midpointHeight = (boundingVolumeS2.maximumHeight + boundingVolumeS2.minimumHeight) / 2;
minHeight = childIndex < 4 ? boundingVolumeS2.minimumHeight : midpointHeight;
maxHeight = childIndex < 4 ? midpointHeight : boundingVolumeS2.maximumHeight;
} else {
minHeight = boundingVolumeS2.minimumHeight;
maxHeight = boundingVolumeS2.maximumHeight;
}
return {
extensions: {
"3DTILES_bounding_volume_S2": {
token: S2Cell_default.getTokenFromId(cell._cellId),
minimumHeight: minHeight,
maximumHeight: maxHeight
}
}
};
}
var scratchScaleFactors = new Cartesian3_default();
var scratchRootCenter = new Cartesian3_default();
var scratchCenter2 = new Cartesian3_default();
var scratchHalfAxes = new Matrix3_default();
function deriveBoundingBox(rootBox, level, x, y, z) {
Check_default.typeOf.object("rootBox", rootBox);
Check_default.typeOf.number("level", level);
Check_default.typeOf.number("x", x);
Check_default.typeOf.number("y", y);
if (defined_default(z)) {
Check_default.typeOf.number("z", z);
}
if (level === 0) {
return rootBox;
}
const rootCenter = Cartesian3_default.unpack(rootBox, 0, scratchRootCenter);
const rootHalfAxes = Matrix3_default.unpack(rootBox, 3, scratchHalfAxes);
const tileScale = Math.pow(2, -level);
const modelSpaceX = -1 + (2 * x + 1) * tileScale;
const modelSpaceY = -1 + (2 * y + 1) * tileScale;
let modelSpaceZ = 0;
const scaleFactors = Cartesian3_default.fromElements(
tileScale,
tileScale,
1,
scratchScaleFactors
);
if (defined_default(z)) {
modelSpaceZ = -1 + (2 * z + 1) * tileScale;
scaleFactors.z = tileScale;
}
let center = Cartesian3_default.fromElements(
modelSpaceX,
modelSpaceY,
modelSpaceZ,
scratchCenter2
);
center = Matrix3_default.multiplyByVector(rootHalfAxes, center, scratchCenter2);
center = Cartesian3_default.add(center, rootCenter, scratchCenter2);
let halfAxes = Matrix3_default.clone(rootHalfAxes);
halfAxes = Matrix3_default.multiplyByScale(halfAxes, scaleFactors, halfAxes);
const childBox = new Array(12);
Cartesian3_default.pack(center, childBox);
Matrix3_default.pack(halfAxes, childBox, 3);
return childBox;
}
var scratchRectangle = new Rectangle_default();
function deriveBoundingRegion(rootRegion, level, x, y, z) {
Check_default.typeOf.object("rootRegion", rootRegion);
Check_default.typeOf.number("level", level);
Check_default.typeOf.number("x", x);
Check_default.typeOf.number("y", y);
if (defined_default(z)) {
Check_default.typeOf.number("z", z);
}
if (level === 0) {
return rootRegion.slice();
}
const rectangle = Rectangle_default.unpack(rootRegion, 0, scratchRectangle);
const rootMinimumHeight = rootRegion[4];
const rootMaximumHeight = rootRegion[5];
const tileScale = Math.pow(2, -level);
const childWidth = tileScale * rectangle.width;
const west = Math_default.negativePiToPi(rectangle.west + x * childWidth);
const east = Math_default.negativePiToPi(west + childWidth);
const childHeight = tileScale * rectangle.height;
const south = Math_default.negativePiToPi(rectangle.south + y * childHeight);
const north = Math_default.negativePiToPi(south + childHeight);
let minimumHeight = rootMinimumHeight;
let maximumHeight = rootMaximumHeight;
if (defined_default(z)) {
const childThickness = tileScale * (rootMaximumHeight - rootMinimumHeight);
minimumHeight += z * childThickness;
maximumHeight = minimumHeight + childThickness;
}
return [west, south, east, north, minimumHeight, maximumHeight];
}
function makePlaceholderChildSubtree(content, parentTile, childIndex) {
const implicitTileset = content._implicitTileset;
const implicitCoordinates = parentTile.implicitCoordinates.getChildCoordinates(childIndex);
const childBoundingVolume = deriveBoundingVolume(
implicitTileset,
implicitCoordinates,
childIndex,
false,
parentTile
);
const childGeometricError = getGeometricError(
void 0,
implicitTileset,
implicitCoordinates
);
const childContentUri = implicitTileset.subtreeUriTemplate.getDerivedResource(
{
templateValues: implicitCoordinates.getTemplateValues()
}
).url;
const tileJson = {
boundingVolume: childBoundingVolume,
geometricError: childGeometricError,
refine: implicitTileset.refine,
contents: [
{
uri: childContentUri
}
]
};
const tile = makeTile(
content,
implicitTileset.baseResource,
tileJson,
parentTile
);
tile.implicitTileset = implicitTileset;
tile.implicitCoordinates = implicitCoordinates;
return tile;
}
function makeTile(content, baseResource2, tileJson, parentTile) {
const Cesium3DTile2 = content._tile.constructor;
return new Cesium3DTile2(content._tileset, baseResource2, tileJson, parentTile);
}
Implicit3DTileContent.prototype.hasProperty = function(batchId, name) {
return false;
};
Implicit3DTileContent.prototype.getFeature = function(batchId) {
return void 0;
};
Implicit3DTileContent.prototype.applyDebugSettings = function(enabled, color) {
};
Implicit3DTileContent.prototype.applyStyle = function(style) {
};
Implicit3DTileContent.prototype.update = function(tileset, frameState) {
};
Implicit3DTileContent.prototype.pick = function(ray, frameState, result) {
return void 0;
};
Implicit3DTileContent.prototype.isDestroyed = function() {
return false;
};
Implicit3DTileContent.prototype.destroy = function() {
this._implicitSubtree = this._implicitSubtree && this._implicitSubtree.destroy();
return destroyObject_default(this);
};
Implicit3DTileContent._deriveBoundingBox = deriveBoundingBox;
Implicit3DTileContent._deriveBoundingRegion = deriveBoundingRegion;
Implicit3DTileContent._deriveBoundingVolumeS2 = deriveBoundingVolumeS2;
var Implicit3DTileContent_default = Implicit3DTileContent;
// packages/engine/Source/Scene/Model/Model3DTileContent.js
var import_InlineWorkers737 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/ModelAnimationLoop.js
var import_InlineWorkers527 = __toESM(require_InlineWorkers(), 1);
var ModelAnimationLoop = {
/**
* Play the animation once; do not loop it.
*
* @type {number}
* @constant
*/
NONE: 0,
/**
* Loop the animation playing it from the start immediately after it stops.
*
* @type {number}
* @constant
*/
REPEAT: 1,
/**
* Loop the animation. First, playing it forward, then in reverse, then forward, and so on.
*
* @type {number}
* @constant
*/
MIRRORED_REPEAT: 2
};
var ModelAnimationLoop_default = Object.freeze(ModelAnimationLoop);
// packages/engine/Source/Scene/Model/Model.js
var import_InlineWorkers736 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/ClippingPlaneCollection.js
var import_InlineWorkers529 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/ClippingPlane.js
var import_InlineWorkers528 = __toESM(require_InlineWorkers(), 1);
function ClippingPlane(normal2, distance2) {
Check_default.typeOf.object("normal", normal2);
Check_default.typeOf.number("distance", distance2);
this._distance = distance2;
this._normal = new UpdateChangedCartesian3(normal2, this);
this.onChangeCallback = void 0;
this.index = -1;
}
Object.defineProperties(ClippingPlane.prototype, {
/**
* The shortest distance from the origin to the plane. The sign of
* distance determines which side of the plane the origin
* is on. If distance is positive, the origin is in the half-space
* in the direction of the normal; if negative, the origin is in the half-space
* opposite to the normal; if zero, the plane passes through the origin.
*
* @type {number}
* @memberof ClippingPlane.prototype
*/
distance: {
get: function() {
return this._distance;
},
set: function(value) {
Check_default.typeOf.number("value", value);
if (defined_default(this.onChangeCallback) && value !== this._distance) {
this.onChangeCallback(this.index);
}
this._distance = value;
}
},
/**
* The plane's normal.
*
* @type {Cartesian3}
* @memberof ClippingPlane.prototype
*/
normal: {
get: function() {
return this._normal;
},
set: function(value) {
Check_default.typeOf.object("value", value);
if (defined_default(this.onChangeCallback) && !Cartesian3_default.equals(this._normal._cartesian3, value)) {
this.onChangeCallback(this.index);
}
Cartesian3_default.clone(value, this._normal._cartesian3);
}
}
});
ClippingPlane.fromPlane = function(plane, result) {
Check_default.typeOf.object("plane", plane);
if (!defined_default(result)) {
result = new ClippingPlane(plane.normal, plane.distance);
} else {
result.normal = plane.normal;
result.distance = plane.distance;
}
return result;
};
ClippingPlane.clone = function(clippingPlane, result) {
if (!defined_default(result)) {
return new ClippingPlane(clippingPlane.normal, clippingPlane.distance);
}
result.normal = clippingPlane.normal;
result.distance = clippingPlane.distance;
return result;
};
function UpdateChangedCartesian3(normal2, clippingPlane) {
this._clippingPlane = clippingPlane;
this._cartesian3 = Cartesian3_default.clone(normal2);
}
Object.defineProperties(UpdateChangedCartesian3.prototype, {
x: {
get: function() {
return this._cartesian3.x;
},
set: function(value) {
Check_default.typeOf.number("value", value);
if (defined_default(this._clippingPlane.onChangeCallback) && value !== this._cartesian3.x) {
this._clippingPlane.onChangeCallback(this._clippingPlane.index);
}
this._cartesian3.x = value;
}
},
y: {
get: function() {
return this._cartesian3.y;
},
set: function(value) {
Check_default.typeOf.number("value", value);
if (defined_default(this._clippingPlane.onChangeCallback) && value !== this._cartesian3.y) {
this._clippingPlane.onChangeCallback(this._clippingPlane.index);
}
this._cartesian3.y = value;
}
},
z: {
get: function() {
return this._cartesian3.z;
},
set: function(value) {
Check_default.typeOf.number("value", value);
if (defined_default(this._clippingPlane.onChangeCallback) && value !== this._cartesian3.z) {
this._clippingPlane.onChangeCallback(this._clippingPlane.index);
}
this._cartesian3.z = value;
}
}
});
var ClippingPlane_default = ClippingPlane;
// packages/engine/Source/Scene/ClippingPlaneCollection.js
function ClippingPlaneCollection(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._planes = [];
this._dirtyIndex = -1;
this._multipleDirtyPlanes = false;
this._enabled = options.enabled ?? true;
this.modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this.edgeColor = Color_default.clone(options.edgeColor ?? Color_default.WHITE);
this.edgeWidth = options.edgeWidth ?? 0;
this.planeAdded = new Event_default();
this.planeRemoved = new Event_default();
this._owner = void 0;
const unionClippingRegions = options.unionClippingRegions ?? false;
this._unionClippingRegions = unionClippingRegions;
this._testIntersection = unionClippingRegions ? unionIntersectFunction : defaultIntersectFunction;
this._uint8View = void 0;
this._float32View = void 0;
this._clippingPlanesTexture = void 0;
const planes = options.planes;
if (defined_default(planes)) {
const planesLength = planes.length;
for (let i = 0; i < planesLength; ++i) {
this.add(planes[i]);
}
}
}
function unionIntersectFunction(value) {
return value === Intersect_default.OUTSIDE;
}
function defaultIntersectFunction(value) {
return value === Intersect_default.INSIDE;
}
Object.defineProperties(ClippingPlaneCollection.prototype, {
/**
* Returns the number of planes in this collection. This is commonly used with
* {@link ClippingPlaneCollection#get} to iterate over all the planes
* in the collection.
*
* @memberof ClippingPlaneCollection.prototype
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._planes.length;
}
},
/**
* If true, a region will be clipped if it is on the outside of any plane in the
* collection. Otherwise, a region will only be clipped if it is on the
* outside of every plane.
*
* @memberof ClippingPlaneCollection.prototype
* @type {boolean}
* @default false
*/
unionClippingRegions: {
get: function() {
return this._unionClippingRegions;
},
set: function(value) {
if (this._unionClippingRegions === value) {
return;
}
this._unionClippingRegions = value;
this._testIntersection = value ? unionIntersectFunction : defaultIntersectFunction;
}
},
/**
* If true, clipping will be enabled.
*
* @memberof ClippingPlaneCollection.prototype
* @type {boolean}
* @default true
*/
enabled: {
get: function() {
return this._enabled;
},
set: function(value) {
if (this._enabled === value) {
return;
}
this._enabled = value;
}
},
/**
* Returns a texture containing packed, untransformed clipping planes.
*
* @memberof ClippingPlaneCollection.prototype
* @type {Texture}
* @readonly
* @private
*/
texture: {
get: function() {
return this._clippingPlanesTexture;
}
},
/**
* A reference to the ClippingPlaneCollection's owner, if any.
*
* @memberof ClippingPlaneCollection.prototype
* @readonly
* @private
*/
owner: {
get: function() {
return this._owner;
}
},
/**
* Returns a Number encapsulating the state for this ClippingPlaneCollection.
*
* Clipping mode is encoded in the sign of the number, which is just the plane count.
* If this value changes, then shader regeneration is necessary.
*
* @memberof ClippingPlaneCollection.prototype
* @returns {number} A Number that describes the ClippingPlaneCollection's state.
* @readonly
* @private
*/
clippingPlanesState: {
get: function() {
return this._unionClippingRegions ? this._planes.length : -this._planes.length;
}
}
});
function setIndexDirty(collection, index) {
collection._multipleDirtyPlanes = collection._multipleDirtyPlanes || collection._dirtyIndex !== -1 && collection._dirtyIndex !== index;
collection._dirtyIndex = index;
}
ClippingPlaneCollection.prototype.add = function(plane) {
const newPlaneIndex = this._planes.length;
const that = this;
plane.onChangeCallback = function(index) {
setIndexDirty(that, index);
};
plane.index = newPlaneIndex;
setIndexDirty(this, newPlaneIndex);
this._planes.push(plane);
this.planeAdded.raiseEvent(plane, newPlaneIndex);
};
ClippingPlaneCollection.prototype.get = function(index) {
Check_default.typeOf.number("index", index);
return this._planes[index];
};
function indexOf(planes, plane) {
const length2 = planes.length;
for (let i = 0; i < length2; ++i) {
if (Plane_default.equals(planes[i], plane)) {
return i;
}
}
return -1;
}
ClippingPlaneCollection.prototype.contains = function(clippingPlane) {
return indexOf(this._planes, clippingPlane) !== -1;
};
ClippingPlaneCollection.prototype.remove = function(clippingPlane) {
const planes = this._planes;
const index = indexOf(planes, clippingPlane);
if (index === -1) {
return false;
}
if (clippingPlane instanceof ClippingPlane_default) {
clippingPlane.onChangeCallback = void 0;
clippingPlane.index = -1;
}
const length2 = planes.length - 1;
for (let i = index; i < length2; ++i) {
const planeToKeep = planes[i + 1];
planes[i] = planeToKeep;
if (planeToKeep instanceof ClippingPlane_default) {
planeToKeep.index = i;
}
}
this._multipleDirtyPlanes = true;
planes.length = length2;
this.planeRemoved.raiseEvent(clippingPlane, index);
return true;
};
ClippingPlaneCollection.prototype.removeAll = function() {
const planes = this._planes;
const planesCount = planes.length;
for (let i = 0; i < planesCount; ++i) {
const plane = planes[i];
if (plane instanceof ClippingPlane_default) {
plane.onChangeCallback = void 0;
plane.index = -1;
}
this.planeRemoved.raiseEvent(plane, i);
}
this._multipleDirtyPlanes = true;
this._planes = [];
};
var distanceEncodeScratch = new Cartesian4_default();
var oct32EncodeScratch = new Cartesian4_default();
function packPlanesAsUint8(clippingPlaneCollection, startIndex, endIndex) {
const uint8View = clippingPlaneCollection._uint8View;
const planes = clippingPlaneCollection._planes;
let byteIndex = 0;
for (let i = startIndex; i < endIndex; ++i) {
const plane = planes[i];
const oct32Normal = AttributeCompression_default.octEncodeToCartesian4(
plane.normal,
oct32EncodeScratch
);
uint8View[byteIndex] = oct32Normal.x;
uint8View[byteIndex + 1] = oct32Normal.y;
uint8View[byteIndex + 2] = oct32Normal.z;
uint8View[byteIndex + 3] = oct32Normal.w;
const encodedDistance = Cartesian4_default.packFloat(
plane.distance,
distanceEncodeScratch
);
uint8View[byteIndex + 4] = encodedDistance.x;
uint8View[byteIndex + 5] = encodedDistance.y;
uint8View[byteIndex + 6] = encodedDistance.z;
uint8View[byteIndex + 7] = encodedDistance.w;
byteIndex += 8;
}
}
function packPlanesAsFloats(clippingPlaneCollection, startIndex, endIndex) {
const float32View = clippingPlaneCollection._float32View;
const planes = clippingPlaneCollection._planes;
let floatIndex = 0;
for (let i = startIndex; i < endIndex; ++i) {
const plane = planes[i];
const normal2 = plane.normal;
float32View[floatIndex] = normal2.x;
float32View[floatIndex + 1] = normal2.y;
float32View[floatIndex + 2] = normal2.z;
float32View[floatIndex + 3] = plane.distance;
floatIndex += 4;
}
}
function computeTextureResolution(pixelsNeeded, result) {
const maxSize = ContextLimits_default.maximumTextureSize;
result.x = Math.min(pixelsNeeded, maxSize);
result.y = Math.ceil(pixelsNeeded / result.x);
return result;
}
var textureResolutionScratch = new Cartesian2_default();
ClippingPlaneCollection.prototype.update = function(frameState) {
let clippingPlanesTexture = this._clippingPlanesTexture;
const context = frameState.context;
const useFloatTexture = ClippingPlaneCollection.useFloatTexture(context);
const pixelsNeeded = useFloatTexture ? this.length : this.length * 2;
if (defined_default(clippingPlanesTexture)) {
const currentPixelCount = clippingPlanesTexture.width * clippingPlanesTexture.height;
if (currentPixelCount < pixelsNeeded || pixelsNeeded < 0.25 * currentPixelCount) {
clippingPlanesTexture.destroy();
clippingPlanesTexture = void 0;
this._clippingPlanesTexture = void 0;
}
}
if (this.length === 0) {
return;
}
if (!defined_default(clippingPlanesTexture)) {
const requiredResolution = computeTextureResolution(
pixelsNeeded,
textureResolutionScratch
);
requiredResolution.y *= 2;
if (useFloatTexture) {
clippingPlanesTexture = new Texture_default({
context,
width: requiredResolution.x,
height: requiredResolution.y,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.FLOAT,
sampler: Sampler_default.NEAREST,
flipY: false
});
this._float32View = new Float32Array(
requiredResolution.x * requiredResolution.y * 4
);
} else {
clippingPlanesTexture = new Texture_default({
context,
width: requiredResolution.x,
height: requiredResolution.y,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
sampler: Sampler_default.NEAREST,
flipY: false
});
this._uint8View = new Uint8Array(
requiredResolution.x * requiredResolution.y * 4
);
}
this._clippingPlanesTexture = clippingPlanesTexture;
this._multipleDirtyPlanes = true;
}
const dirtyIndex = this._dirtyIndex;
if (!this._multipleDirtyPlanes && dirtyIndex === -1) {
return;
}
if (!this._multipleDirtyPlanes) {
let offsetX = 0;
let offsetY = 0;
if (useFloatTexture) {
offsetY = Math.floor(dirtyIndex / clippingPlanesTexture.width);
offsetX = Math.floor(dirtyIndex - offsetY * clippingPlanesTexture.width);
packPlanesAsFloats(this, dirtyIndex, dirtyIndex + 1);
clippingPlanesTexture.copyFrom({
source: {
width: 1,
height: 1,
arrayBufferView: this._float32View
},
xOffset: offsetX,
yOffset: offsetY
});
} else {
offsetY = Math.floor(dirtyIndex * 2 / clippingPlanesTexture.width);
offsetX = Math.floor(
dirtyIndex * 2 - offsetY * clippingPlanesTexture.width
);
packPlanesAsUint8(this, dirtyIndex, dirtyIndex + 1);
clippingPlanesTexture.copyFrom({
source: {
width: 2,
height: 1,
arrayBufferView: this._uint8View
},
xOffset: offsetX,
yOffset: offsetY
});
}
} else if (useFloatTexture) {
packPlanesAsFloats(this, 0, this._planes.length);
clippingPlanesTexture.copyFrom({
source: {
width: clippingPlanesTexture.width,
height: clippingPlanesTexture.height,
arrayBufferView: this._float32View
}
});
} else {
packPlanesAsUint8(this, 0, this._planes.length);
clippingPlanesTexture.copyFrom({
source: {
width: clippingPlanesTexture.width,
height: clippingPlanesTexture.height,
arrayBufferView: this._uint8View
}
});
}
this._multipleDirtyPlanes = false;
this._dirtyIndex = -1;
};
var scratchMatrix = new Matrix4_default();
var scratchPlane3 = new Plane_default(Cartesian3_default.UNIT_X, 0);
ClippingPlaneCollection.prototype.computeIntersectionWithBoundingVolume = function(tileBoundingVolume, transform3) {
const planes = this._planes;
const length2 = planes.length;
let modelMatrix = this.modelMatrix;
if (defined_default(transform3)) {
modelMatrix = Matrix4_default.multiply(transform3, modelMatrix, scratchMatrix);
}
let intersection = Intersect_default.INSIDE;
if (!this.unionClippingRegions && length2 > 0) {
intersection = Intersect_default.OUTSIDE;
}
for (let i = 0; i < length2; ++i) {
const plane = planes[i];
Plane_default.transform(plane, modelMatrix, scratchPlane3);
const value = tileBoundingVolume.intersectPlane(scratchPlane3);
if (value === Intersect_default.INTERSECTING) {
intersection = value;
} else if (this._testIntersection(value)) {
return value;
}
}
return intersection;
};
ClippingPlaneCollection.setOwner = function(clippingPlaneCollection, owner, key) {
if (clippingPlaneCollection === owner[key]) {
return;
}
owner[key] = owner[key] && owner[key].destroy();
if (defined_default(clippingPlaneCollection)) {
if (defined_default(clippingPlaneCollection._owner)) {
throw new DeveloperError_default(
"ClippingPlaneCollection should only be assigned to one object"
);
}
clippingPlaneCollection._owner = owner;
owner[key] = clippingPlaneCollection;
}
};
ClippingPlaneCollection.useFloatTexture = function(context) {
return context.floatingPointTexture;
};
ClippingPlaneCollection.getTextureResolution = function(clippingPlaneCollection, context, result) {
const texture = clippingPlaneCollection.texture;
if (defined_default(texture)) {
result.x = texture.width;
result.y = texture.height;
return result;
}
const pixelsNeeded = ClippingPlaneCollection.useFloatTexture(context) ? clippingPlaneCollection.length : clippingPlaneCollection.length * 2;
const requiredResolution = computeTextureResolution(pixelsNeeded, result);
requiredResolution.y *= 2;
return requiredResolution;
};
ClippingPlaneCollection.prototype.isDestroyed = function() {
return false;
};
ClippingPlaneCollection.prototype.destroy = function() {
this._clippingPlanesTexture = this._clippingPlanesTexture && this._clippingPlanesTexture.destroy();
return destroyObject_default(this);
};
var ClippingPlaneCollection_default = ClippingPlaneCollection;
// packages/engine/Source/Scene/ClippingPolygonCollection.js
var import_InlineWorkers538 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/ClippingPolygon.js
var import_InlineWorkers536 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PolygonGeometry.js
var import_InlineWorkers535 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PolygonGeometryLibrary.js
var import_InlineWorkers533 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PolygonPipeline.js
var import_InlineWorkers531 = __toESM(require_InlineWorkers(), 1);
// node_modules/earcut/src/earcut.js
var import_InlineWorkers530 = __toESM(require_InlineWorkers(), 1);
function earcut(data, holeIndices, dim = 2) {
const hasHoles = holeIndices && holeIndices.length;
const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
let outerNode = linkedList(data, 0, outerLen, dim, true);
const triangles = [];
if (!outerNode || outerNode.next === outerNode.prev) return triangles;
let minX, minY, invSize;
if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
if (data.length > 80 * dim) {
minX = data[0];
minY = data[1];
let maxX = minX;
let maxY = minY;
for (let i = dim; i < outerLen; i += dim) {
const x = data[i];
const y = data[i + 1];
if (x < minX) minX = x;
if (y < minY) minY = y;
if (x > maxX) maxX = x;
if (y > maxY) maxY = y;
}
invSize = Math.max(maxX - minX, maxY - minY);
invSize = invSize !== 0 ? 32767 / invSize : 0;
}
earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
return triangles;
}
function linkedList(data, start, end, dim, clockwise) {
let last;
if (clockwise === signedArea(data, start, end, dim) > 0) {
for (let i = start; i < end; i += dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
} else {
for (let i = end - dim; i >= start; i -= dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
}
if (last && equals(last, last.next)) {
removeNode(last);
last = last.next;
}
return last;
}
function filterPoints(start, end) {
if (!start) return start;
if (!end) end = start;
let p = start, again;
do {
again = false;
if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
removeNode(p);
p = end = p.prev;
if (p === p.next) break;
again = true;
} else {
p = p.next;
}
} while (again || p !== end);
return end;
}
function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
if (!ear) return;
if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
let stop2 = ear;
while (ear.prev !== ear.next) {
const prev = ear.prev;
const next = ear.next;
if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
triangles.push(prev.i, ear.i, next.i);
removeNode(ear);
ear = next.next;
stop2 = next.next;
continue;
}
ear = next;
if (ear === stop2) {
if (!pass) {
earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
} else if (pass === 1) {
ear = cureLocalIntersections(filterPoints(ear), triangles);
earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
} else if (pass === 2) {
splitEarcut(ear, triangles, dim, minX, minY, invSize);
}
break;
}
}
}
function isEar(ear) {
const a3 = ear.prev, b = ear, c = ear.next;
if (area(a3, b, c) >= 0) return false;
const ax = a3.x, bx = b.x, cx = c.x, ay = a3.y, by = b.y, cy = c.y;
const x0 = Math.min(ax, bx, cx), y0 = Math.min(ay, by, cy), x1 = Math.max(ax, bx, cx), y1 = Math.max(ay, by, cy);
let p = c.next;
while (p !== a3) {
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
p = p.next;
}
return true;
}
function isEarHashed(ear, minX, minY, invSize) {
const a3 = ear.prev, b = ear, c = ear.next;
if (area(a3, b, c) >= 0) return false;
const ax = a3.x, bx = b.x, cx = c.x, ay = a3.y, by = b.y, cy = c.y;
const x0 = Math.min(ax, bx, cx), y0 = Math.min(ay, by, cy), x1 = Math.max(ax, bx, cx), y1 = Math.max(ay, by, cy);
const minZ = zOrder(x0, y0, minX, minY, invSize), maxZ = zOrder(x1, y1, minX, minY, invSize);
let p = ear.prevZ, n = ear.nextZ;
while (p && p.z >= minZ && n && n.z <= maxZ) {
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a3 && p !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
p = p.prevZ;
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a3 && n !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
n = n.nextZ;
}
while (p && p.z >= minZ) {
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a3 && p !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
p = p.prevZ;
}
while (n && n.z <= maxZ) {
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a3 && n !== c && pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
n = n.nextZ;
}
return true;
}
function cureLocalIntersections(start, triangles) {
let p = start;
do {
const a3 = p.prev, b = p.next.next;
if (!equals(a3, b) && intersects(a3, p, p.next, b) && locallyInside(a3, b) && locallyInside(b, a3)) {
triangles.push(a3.i, p.i, b.i);
removeNode(p);
removeNode(p.next);
p = start = b;
}
p = p.next;
} while (p !== start);
return filterPoints(p);
}
function splitEarcut(start, triangles, dim, minX, minY, invSize) {
let a3 = start;
do {
let b = a3.next.next;
while (b !== a3.prev) {
if (a3.i !== b.i && isValidDiagonal(a3, b)) {
let c = splitPolygon(a3, b);
a3 = filterPoints(a3, a3.next);
c = filterPoints(c, c.next);
earcutLinked(a3, triangles, dim, minX, minY, invSize, 0);
earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
return;
}
b = b.next;
}
a3 = a3.next;
} while (a3 !== start);
}
function eliminateHoles(data, holeIndices, outerNode, dim) {
const queue = [];
for (let i = 0, len = holeIndices.length; i < len; i++) {
const start = holeIndices[i] * dim;
const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
const list = linkedList(data, start, end, dim, false);
if (list === list.next) list.steiner = true;
queue.push(getLeftmost(list));
}
queue.sort(compareXYSlope);
for (let i = 0; i < queue.length; i++) {
outerNode = eliminateHole(queue[i], outerNode);
}
return outerNode;
}
function compareXYSlope(a3, b) {
let result = a3.x - b.x;
if (result === 0) {
result = a3.y - b.y;
if (result === 0) {
const aSlope = (a3.next.y - a3.y) / (a3.next.x - a3.x);
const bSlope = (b.next.y - b.y) / (b.next.x - b.x);
result = aSlope - bSlope;
}
}
return result;
}
function eliminateHole(hole, outerNode) {
const bridge = findHoleBridge(hole, outerNode);
if (!bridge) {
return outerNode;
}
const bridgeReverse = splitPolygon(bridge, hole);
filterPoints(bridgeReverse, bridgeReverse.next);
return filterPoints(bridge, bridge.next);
}
function findHoleBridge(hole, outerNode) {
let p = outerNode;
const hx = hole.x;
const hy = hole.y;
let qx = -Infinity;
let m;
if (equals(hole, p)) return p;
do {
if (equals(hole, p.next)) return p.next;
else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
if (x <= hx && x > qx) {
qx = x;
m = p.x < p.next.x ? p : p.next;
if (x === hx) return m;
}
}
p = p.next;
} while (p !== outerNode);
if (!m) return null;
const stop2 = m;
const mx = m.x;
const my = m.y;
let tanMin = Infinity;
p = m;
do {
if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
const tan = Math.abs(hy - p.y) / (hx - p.x);
if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
m = p;
tanMin = tan;
}
}
p = p.next;
} while (p !== stop2);
return m;
}
function sectorContainsSector(m, p) {
return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
}
function indexCurve(start, minX, minY, invSize) {
let p = start;
do {
if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
p.prevZ = p.prev;
p.nextZ = p.next;
p = p.next;
} while (p !== start);
p.prevZ.nextZ = null;
p.prevZ = null;
sortLinked(p);
}
function sortLinked(list) {
let numMerges;
let inSize = 1;
do {
let p = list;
let e;
list = null;
let tail = null;
numMerges = 0;
while (p) {
numMerges++;
let q = p;
let pSize = 0;
for (let i = 0; i < inSize; i++) {
pSize++;
q = q.nextZ;
if (!q) break;
}
let qSize = inSize;
while (pSize > 0 || qSize > 0 && q) {
if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
e = p;
p = p.nextZ;
pSize--;
} else {
e = q;
q = q.nextZ;
qSize--;
}
if (tail) tail.nextZ = e;
else list = e;
e.prevZ = tail;
tail = e;
}
p = q;
}
tail.nextZ = null;
inSize *= 2;
} while (numMerges > 1);
return list;
}
function zOrder(x, y, minX, minY, invSize) {
x = (x - minX) * invSize | 0;
y = (y - minY) * invSize | 0;
x = (x | x << 8) & 16711935;
x = (x | x << 4) & 252645135;
x = (x | x << 2) & 858993459;
x = (x | x << 1) & 1431655765;
y = (y | y << 8) & 16711935;
y = (y | y << 4) & 252645135;
y = (y | y << 2) & 858993459;
y = (y | y << 1) & 1431655765;
return x | y << 1;
}
function getLeftmost(start) {
let p = start, leftmost = start;
do {
if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y) leftmost = p;
p = p.next;
} while (p !== start);
return leftmost;
}
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
}
function pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, px, py) {
return !(ax === px && ay === py) && pointInTriangle(ax, ay, bx, by, cx, cy, px, py);
}
function isValidDiagonal(a3, b) {
return a3.next.i !== b.i && a3.prev.i !== b.i && !intersectsPolygon(a3, b) && // doesn't intersect other edges
(locallyInside(a3, b) && locallyInside(b, a3) && middleInside(a3, b) && // locally visible
(area(a3.prev, a3, b.prev) || area(a3, b.prev, b)) || // does not create opposite-facing sectors
equals(a3, b) && area(a3.prev, a3, a3.next) > 0 && area(b.prev, b, b.next) > 0);
}
function area(p, q, r) {
return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
}
function equals(p1, p2) {
return p1.x === p2.x && p1.y === p2.y;
}
function intersects(p1, q12, p2, q22) {
const o1 = sign2(area(p1, q12, p2));
const o2 = sign2(area(p1, q12, q22));
const o3 = sign2(area(p2, q22, p1));
const o4 = sign2(area(p2, q22, q12));
if (o1 !== o2 && o3 !== o4) return true;
if (o1 === 0 && onSegment(p1, p2, q12)) return true;
if (o2 === 0 && onSegment(p1, q22, q12)) return true;
if (o3 === 0 && onSegment(p2, p1, q22)) return true;
if (o4 === 0 && onSegment(p2, q12, q22)) return true;
return false;
}
function onSegment(p, q, r) {
return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
}
function sign2(num) {
return num > 0 ? 1 : num < 0 ? -1 : 0;
}
function intersectsPolygon(a3, b) {
let p = a3;
do {
if (p.i !== a3.i && p.next.i !== a3.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a3, b)) return true;
p = p.next;
} while (p !== a3);
return false;
}
function locallyInside(a3, b) {
return area(a3.prev, a3, a3.next) < 0 ? area(a3, b, a3.next) >= 0 && area(a3, a3.prev, b) >= 0 : area(a3, b, a3.prev) < 0 || area(a3, a3.next, b) < 0;
}
function middleInside(a3, b) {
let p = a3;
let inside = false;
const px = (a3.x + b.x) / 2;
const py = (a3.y + b.y) / 2;
do {
if (p.y > py !== p.next.y > py && p.next.y !== p.y && px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)
inside = !inside;
p = p.next;
} while (p !== a3);
return inside;
}
function splitPolygon(a3, b) {
const a22 = createNode(a3.i, a3.x, a3.y), b2 = createNode(b.i, b.x, b.y), an = a3.next, bp = b.prev;
a3.next = b;
b.prev = a3;
a22.next = an;
an.prev = a22;
b2.next = a22;
a22.prev = b2;
bp.next = b2;
b2.prev = bp;
return b2;
}
function insertNode(i, x, y, last) {
const p = createNode(i, x, y);
if (!last) {
p.prev = p;
p.next = p;
} else {
p.next = last.next;
p.prev = last;
last.next.prev = p;
last.next = p;
}
return p;
}
function removeNode(p) {
p.next.prev = p.prev;
p.prev.next = p.next;
if (p.prevZ) p.prevZ.nextZ = p.nextZ;
if (p.nextZ) p.nextZ.prevZ = p.prevZ;
}
function createNode(i, x, y) {
return {
i,
// vertex index in coordinates array
x,
y,
// vertex coordinates
prev: null,
// previous and next vertex nodes in a polygon ring
next: null,
z: 0,
// z-order curve value
prevZ: null,
// previous and next nodes in z-order
nextZ: null,
steiner: false
// indicates whether this is a steiner point
};
}
function signedArea(data, start, end, dim) {
let sum = 0;
for (let i = start, j = end - dim; i < end; i += dim) {
sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
j = i;
}
return sum;
}
// packages/engine/Source/Core/PolygonPipeline.js
var scaleToGeodeticHeightN = new Cartesian3_default();
var scaleToGeodeticHeightP = new Cartesian3_default();
var PolygonPipeline = {};
PolygonPipeline.computeArea2D = function(positions) {
Check_default.defined("positions", positions);
Check_default.typeOf.number.greaterThanOrEquals(
"positions.length",
positions.length,
3
);
const length2 = positions.length;
let area2 = 0;
for (let i0 = length2 - 1, i1 = 0; i1 < length2; i0 = i1++) {
const v02 = positions[i0];
const v12 = positions[i1];
area2 += v02.x * v12.y - v12.x * v02.y;
}
return area2 * 0.5;
};
PolygonPipeline.computeWindingOrder2D = function(positions) {
const area2 = PolygonPipeline.computeArea2D(positions);
return area2 > 0 ? WindingOrder_default.COUNTER_CLOCKWISE : WindingOrder_default.CLOCKWISE;
};
PolygonPipeline.triangulate = function(positions, holes) {
Check_default.defined("positions", positions);
const flattenedPositions = Cartesian2_default.packArray(positions);
return earcut(flattenedPositions, holes, 2);
};
var subdivisionV0Scratch = new Cartesian3_default();
var subdivisionV1Scratch = new Cartesian3_default();
var subdivisionV2Scratch = new Cartesian3_default();
var subdivisionS0Scratch = new Cartesian3_default();
var subdivisionS1Scratch = new Cartesian3_default();
var subdivisionS2Scratch = new Cartesian3_default();
var subdivisionMidScratch = new Cartesian3_default();
var subdivisionT0Scratch = new Cartesian2_default();
var subdivisionT1Scratch = new Cartesian2_default();
var subdivisionT2Scratch = new Cartesian2_default();
var subdivisionTexcoordMidScratch = new Cartesian2_default();
PolygonPipeline.computeSubdivision = function(ellipsoid, positions, indices, texcoords, granularity) {
granularity = granularity ?? Math_default.RADIANS_PER_DEGREE;
const hasTexcoords = defined_default(texcoords);
Check_default.typeOf.object("ellipsoid", ellipsoid);
Check_default.defined("positions", positions);
Check_default.defined("indices", indices);
Check_default.typeOf.number.greaterThanOrEquals("indices.length", indices.length, 3);
Check_default.typeOf.number.equals("indices.length % 3", "0", indices.length % 3, 0);
Check_default.typeOf.number.greaterThan("granularity", granularity, 0);
const triangles = indices.slice(0);
let i;
const length2 = positions.length;
const subdividedPositions = new Array(length2 * 3);
const subdividedTexcoords = new Array(length2 * 2);
let q = 0;
let p = 0;
for (i = 0; i < length2; i++) {
const item = positions[i];
subdividedPositions[q++] = item.x;
subdividedPositions[q++] = item.y;
subdividedPositions[q++] = item.z;
if (hasTexcoords) {
const texcoordItem = texcoords[i];
subdividedTexcoords[p++] = texcoordItem.x;
subdividedTexcoords[p++] = texcoordItem.y;
}
}
const subdividedIndices = [];
const edges = {};
const radius = ellipsoid.maximumRadius;
const minDistance = Math_default.chordLength(granularity, radius);
const minDistanceSqrd = minDistance * minDistance;
while (triangles.length > 0) {
const i2 = triangles.pop();
const i1 = triangles.pop();
const i0 = triangles.pop();
const v02 = Cartesian3_default.fromArray(
subdividedPositions,
i0 * 3,
subdivisionV0Scratch
);
const v12 = Cartesian3_default.fromArray(
subdividedPositions,
i1 * 3,
subdivisionV1Scratch
);
const v22 = Cartesian3_default.fromArray(
subdividedPositions,
i2 * 3,
subdivisionV2Scratch
);
let t0, t1, t2;
if (hasTexcoords) {
t0 = Cartesian2_default.fromArray(
subdividedTexcoords,
i0 * 2,
subdivisionT0Scratch
);
t1 = Cartesian2_default.fromArray(
subdividedTexcoords,
i1 * 2,
subdivisionT1Scratch
);
t2 = Cartesian2_default.fromArray(
subdividedTexcoords,
i2 * 2,
subdivisionT2Scratch
);
}
const s0 = Cartesian3_default.multiplyByScalar(
Cartesian3_default.normalize(v02, subdivisionS0Scratch),
radius,
subdivisionS0Scratch
);
const s1 = Cartesian3_default.multiplyByScalar(
Cartesian3_default.normalize(v12, subdivisionS1Scratch),
radius,
subdivisionS1Scratch
);
const s2 = Cartesian3_default.multiplyByScalar(
Cartesian3_default.normalize(v22, subdivisionS2Scratch),
radius,
subdivisionS2Scratch
);
const g0 = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(s0, s1, subdivisionMidScratch)
);
const g1 = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(s1, s2, subdivisionMidScratch)
);
const g2 = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(s2, s0, subdivisionMidScratch)
);
const max3 = Math.max(g0, g1, g2);
let edge;
let mid;
let midTexcoord;
if (max3 > minDistanceSqrd) {
if (g0 === max3) {
edge = `${Math.min(i0, i1)} ${Math.max(i0, i1)}`;
i = edges[edge];
if (!defined_default(i)) {
mid = Cartesian3_default.add(v02, v12, subdivisionMidScratch);
Cartesian3_default.multiplyByScalar(mid, 0.5, mid);
subdividedPositions.push(mid.x, mid.y, mid.z);
i = subdividedPositions.length / 3 - 1;
edges[edge] = i;
if (hasTexcoords) {
midTexcoord = Cartesian2_default.add(t0, t1, subdivisionTexcoordMidScratch);
Cartesian2_default.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
}
}
triangles.push(i0, i, i2);
triangles.push(i, i1, i2);
} else if (g1 === max3) {
edge = `${Math.min(i1, i2)} ${Math.max(i1, i2)}`;
i = edges[edge];
if (!defined_default(i)) {
mid = Cartesian3_default.add(v12, v22, subdivisionMidScratch);
Cartesian3_default.multiplyByScalar(mid, 0.5, mid);
subdividedPositions.push(mid.x, mid.y, mid.z);
i = subdividedPositions.length / 3 - 1;
edges[edge] = i;
if (hasTexcoords) {
midTexcoord = Cartesian2_default.add(t1, t2, subdivisionTexcoordMidScratch);
Cartesian2_default.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
}
}
triangles.push(i1, i, i0);
triangles.push(i, i2, i0);
} else if (g2 === max3) {
edge = `${Math.min(i2, i0)} ${Math.max(i2, i0)}`;
i = edges[edge];
if (!defined_default(i)) {
mid = Cartesian3_default.add(v22, v02, subdivisionMidScratch);
Cartesian3_default.multiplyByScalar(mid, 0.5, mid);
subdividedPositions.push(mid.x, mid.y, mid.z);
i = subdividedPositions.length / 3 - 1;
edges[edge] = i;
if (hasTexcoords) {
midTexcoord = Cartesian2_default.add(t2, t0, subdivisionTexcoordMidScratch);
Cartesian2_default.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
}
}
triangles.push(i2, i, i1);
triangles.push(i, i0, i1);
}
} else {
subdividedIndices.push(i0);
subdividedIndices.push(i1);
subdividedIndices.push(i2);
}
}
const geometryOptions = {
attributes: {
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: subdividedPositions
})
},
indices: subdividedIndices,
primitiveType: PrimitiveType_default.TRIANGLES
};
if (hasTexcoords) {
geometryOptions.attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: subdividedTexcoords
});
}
return new Geometry_default(geometryOptions);
};
var subdivisionC0Scratch = new Cartographic_default();
var subdivisionC1Scratch = new Cartographic_default();
var subdivisionC2Scratch = new Cartographic_default();
var subdivisionCartographicScratch = new Cartographic_default();
PolygonPipeline.computeRhumbLineSubdivision = function(ellipsoid, positions, indices, texcoords, granularity) {
granularity = granularity ?? Math_default.RADIANS_PER_DEGREE;
const hasTexcoords = defined_default(texcoords);
Check_default.typeOf.object("ellipsoid", ellipsoid);
Check_default.defined("positions", positions);
Check_default.defined("indices", indices);
Check_default.typeOf.number.greaterThanOrEquals("indices.length", indices.length, 3);
Check_default.typeOf.number.equals("indices.length % 3", "0", indices.length % 3, 0);
Check_default.typeOf.number.greaterThan("granularity", granularity, 0);
const triangles = indices.slice(0);
let i;
const length2 = positions.length;
const subdividedPositions = new Array(length2 * 3);
const subdividedTexcoords = new Array(length2 * 2);
let q = 0;
let p = 0;
for (i = 0; i < length2; i++) {
const item = positions[i];
subdividedPositions[q++] = item.x;
subdividedPositions[q++] = item.y;
subdividedPositions[q++] = item.z;
if (hasTexcoords) {
const texcoordItem = texcoords[i];
subdividedTexcoords[p++] = texcoordItem.x;
subdividedTexcoords[p++] = texcoordItem.y;
}
}
const subdividedIndices = [];
const edges = {};
const radius = ellipsoid.maximumRadius;
const minDistance = Math_default.chordLength(granularity, radius);
const rhumb0 = new EllipsoidRhumbLine_default(void 0, void 0, ellipsoid);
const rhumb1 = new EllipsoidRhumbLine_default(void 0, void 0, ellipsoid);
const rhumb2 = new EllipsoidRhumbLine_default(void 0, void 0, ellipsoid);
while (triangles.length > 0) {
const i2 = triangles.pop();
const i1 = triangles.pop();
const i0 = triangles.pop();
const v02 = Cartesian3_default.fromArray(
subdividedPositions,
i0 * 3,
subdivisionV0Scratch
);
const v12 = Cartesian3_default.fromArray(
subdividedPositions,
i1 * 3,
subdivisionV1Scratch
);
const v22 = Cartesian3_default.fromArray(
subdividedPositions,
i2 * 3,
subdivisionV2Scratch
);
let t0, t1, t2;
if (hasTexcoords) {
t0 = Cartesian2_default.fromArray(
subdividedTexcoords,
i0 * 2,
subdivisionT0Scratch
);
t1 = Cartesian2_default.fromArray(
subdividedTexcoords,
i1 * 2,
subdivisionT1Scratch
);
t2 = Cartesian2_default.fromArray(
subdividedTexcoords,
i2 * 2,
subdivisionT2Scratch
);
}
const c0 = ellipsoid.cartesianToCartographic(v02, subdivisionC0Scratch);
const c14 = ellipsoid.cartesianToCartographic(v12, subdivisionC1Scratch);
const c22 = ellipsoid.cartesianToCartographic(v22, subdivisionC2Scratch);
rhumb0.setEndPoints(c0, c14);
const g0 = rhumb0.surfaceDistance;
rhumb1.setEndPoints(c14, c22);
const g1 = rhumb1.surfaceDistance;
rhumb2.setEndPoints(c22, c0);
const g2 = rhumb2.surfaceDistance;
const max3 = Math.max(g0, g1, g2);
let edge;
let mid;
let midHeight;
let midCartesian3;
let midTexcoord;
if (max3 > minDistance) {
if (g0 === max3) {
edge = `${Math.min(i0, i1)} ${Math.max(i0, i1)}`;
i = edges[edge];
if (!defined_default(i)) {
mid = rhumb0.interpolateUsingFraction(
0.5,
subdivisionCartographicScratch
);
midHeight = (c0.height + c14.height) * 0.5;
midCartesian3 = Cartesian3_default.fromRadians(
mid.longitude,
mid.latitude,
midHeight,
ellipsoid,
subdivisionMidScratch
);
subdividedPositions.push(
midCartesian3.x,
midCartesian3.y,
midCartesian3.z
);
i = subdividedPositions.length / 3 - 1;
edges[edge] = i;
if (hasTexcoords) {
midTexcoord = Cartesian2_default.add(t0, t1, subdivisionTexcoordMidScratch);
Cartesian2_default.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
}
}
triangles.push(i0, i, i2);
triangles.push(i, i1, i2);
} else if (g1 === max3) {
edge = `${Math.min(i1, i2)} ${Math.max(i1, i2)}`;
i = edges[edge];
if (!defined_default(i)) {
mid = rhumb1.interpolateUsingFraction(
0.5,
subdivisionCartographicScratch
);
midHeight = (c14.height + c22.height) * 0.5;
midCartesian3 = Cartesian3_default.fromRadians(
mid.longitude,
mid.latitude,
midHeight,
ellipsoid,
subdivisionMidScratch
);
subdividedPositions.push(
midCartesian3.x,
midCartesian3.y,
midCartesian3.z
);
i = subdividedPositions.length / 3 - 1;
edges[edge] = i;
if (hasTexcoords) {
midTexcoord = Cartesian2_default.add(t1, t2, subdivisionTexcoordMidScratch);
Cartesian2_default.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
}
}
triangles.push(i1, i, i0);
triangles.push(i, i2, i0);
} else if (g2 === max3) {
edge = `${Math.min(i2, i0)} ${Math.max(i2, i0)}`;
i = edges[edge];
if (!defined_default(i)) {
mid = rhumb2.interpolateUsingFraction(
0.5,
subdivisionCartographicScratch
);
midHeight = (c22.height + c0.height) * 0.5;
midCartesian3 = Cartesian3_default.fromRadians(
mid.longitude,
mid.latitude,
midHeight,
ellipsoid,
subdivisionMidScratch
);
subdividedPositions.push(
midCartesian3.x,
midCartesian3.y,
midCartesian3.z
);
i = subdividedPositions.length / 3 - 1;
edges[edge] = i;
if (hasTexcoords) {
midTexcoord = Cartesian2_default.add(t2, t0, subdivisionTexcoordMidScratch);
Cartesian2_default.multiplyByScalar(midTexcoord, 0.5, midTexcoord);
subdividedTexcoords.push(midTexcoord.x, midTexcoord.y);
}
}
triangles.push(i2, i, i1);
triangles.push(i, i0, i1);
}
} else {
subdividedIndices.push(i0);
subdividedIndices.push(i1);
subdividedIndices.push(i2);
}
}
const geometryOptions = {
attributes: {
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: subdividedPositions
})
},
indices: subdividedIndices,
primitiveType: PrimitiveType_default.TRIANGLES
};
if (hasTexcoords) {
geometryOptions.attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: subdividedTexcoords
});
}
return new Geometry_default(geometryOptions);
};
PolygonPipeline.scaleToGeodeticHeight = function(positions, height, ellipsoid, scaleToSurface4) {
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
let n = scaleToGeodeticHeightN;
let p = scaleToGeodeticHeightP;
height = height ?? 0;
scaleToSurface4 = scaleToSurface4 ?? true;
if (defined_default(positions)) {
const length2 = positions.length;
for (let i = 0; i < length2; i += 3) {
Cartesian3_default.fromArray(positions, i, p);
if (scaleToSurface4) {
p = ellipsoid.scaleToGeodeticSurface(p, p);
}
if (height !== 0) {
n = ellipsoid.geodeticSurfaceNormal(p, n);
Cartesian3_default.multiplyByScalar(n, height, n);
Cartesian3_default.add(p, n, p);
}
positions[i] = p.x;
positions[i + 1] = p.y;
positions[i + 2] = p.z;
}
}
return positions;
};
var PolygonPipeline_default = PolygonPipeline;
// packages/engine/Source/Core/Queue.js
var import_InlineWorkers532 = __toESM(require_InlineWorkers(), 1);
function Queue() {
this._array = [];
this._offset = 0;
this._length = 0;
}
Object.defineProperties(Queue.prototype, {
/**
* The length of the queue.
*
* @memberof Queue.prototype
*
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._length;
}
}
});
Queue.prototype.enqueue = function(item) {
this._array.push(item);
this._length++;
};
Queue.prototype.dequeue = function() {
if (this._length === 0) {
return void 0;
}
const array = this._array;
let offset = this._offset;
const item = array[offset];
array[offset] = void 0;
offset++;
if (offset > 10 && offset * 2 > array.length) {
this._array = array.slice(offset);
offset = 0;
}
this._offset = offset;
this._length--;
return item;
};
Queue.prototype.peek = function() {
if (this._length === 0) {
return void 0;
}
return this._array[this._offset];
};
Queue.prototype.contains = function(item) {
return this._array.indexOf(item) !== -1;
};
Queue.prototype.clear = function() {
this._array.length = this._offset = this._length = 0;
};
Queue.prototype.sort = function(compareFunction) {
if (this._offset > 0) {
this._array = this._array.slice(this._offset);
this._offset = 0;
}
this._array.sort(compareFunction);
};
var Queue_default = Queue;
// packages/engine/Source/Core/PolygonGeometryLibrary.js
var PolygonGeometryLibrary = {};
PolygonGeometryLibrary.computeHierarchyPackedLength = function(polygonHierarchy, CartesianX) {
let numComponents = 0;
const stack = [polygonHierarchy];
while (stack.length > 0) {
const hierarchy = stack.pop();
if (!defined_default(hierarchy)) {
continue;
}
numComponents += 2;
const positions = hierarchy.positions;
const holes = hierarchy.holes;
if (defined_default(positions) && positions.length > 0) {
numComponents += positions.length * CartesianX.packedLength;
}
if (defined_default(holes)) {
const length2 = holes.length;
for (let i = 0; i < length2; ++i) {
stack.push(holes[i]);
}
}
}
return numComponents;
};
PolygonGeometryLibrary.packPolygonHierarchy = function(polygonHierarchy, array, startingIndex, CartesianX) {
const stack = [polygonHierarchy];
while (stack.length > 0) {
const hierarchy = stack.pop();
if (!defined_default(hierarchy)) {
continue;
}
const positions = hierarchy.positions;
const holes = hierarchy.holes;
array[startingIndex++] = defined_default(positions) ? positions.length : 0;
array[startingIndex++] = defined_default(holes) ? holes.length : 0;
if (defined_default(positions)) {
const positionsLength = positions.length;
for (let i = 0; i < positionsLength; ++i, startingIndex += CartesianX.packedLength) {
CartesianX.pack(positions[i], array, startingIndex);
}
}
if (defined_default(holes)) {
const holesLength = holes.length;
for (let j = 0; j < holesLength; ++j) {
stack.push(holes[j]);
}
}
}
return startingIndex;
};
PolygonGeometryLibrary.unpackPolygonHierarchy = function(array, startingIndex, CartesianX) {
const positionsLength = array[startingIndex++];
const holesLength = array[startingIndex++];
const positions = new Array(positionsLength);
const holes = holesLength > 0 ? new Array(holesLength) : void 0;
for (let i = 0; i < positionsLength; ++i, startingIndex += CartesianX.packedLength) {
positions[i] = CartesianX.unpack(array, startingIndex);
}
for (let j = 0; j < holesLength; ++j) {
holes[j] = PolygonGeometryLibrary.unpackPolygonHierarchy(
array,
startingIndex,
CartesianX
);
startingIndex = holes[j].startingIndex;
delete holes[j].startingIndex;
}
return {
positions,
holes,
startingIndex
};
};
var distance2DScratch = new Cartesian2_default();
function getPointAtDistance2D(p0, p1, distance2, length2) {
Cartesian2_default.subtract(p1, p0, distance2DScratch);
Cartesian2_default.multiplyByScalar(
distance2DScratch,
distance2 / length2,
distance2DScratch
);
Cartesian2_default.add(p0, distance2DScratch, distance2DScratch);
return [distance2DScratch.x, distance2DScratch.y];
}
var distanceScratch4 = new Cartesian3_default();
function getPointAtDistance(p0, p1, distance2, length2) {
Cartesian3_default.subtract(p1, p0, distanceScratch4);
Cartesian3_default.multiplyByScalar(
distanceScratch4,
distance2 / length2,
distanceScratch4
);
Cartesian3_default.add(p0, distanceScratch4, distanceScratch4);
return [distanceScratch4.x, distanceScratch4.y, distanceScratch4.z];
}
PolygonGeometryLibrary.subdivideLineCount = function(p0, p1, minDistance) {
const distance2 = Cartesian3_default.distance(p0, p1);
const n = distance2 / minDistance;
const countDivide = Math.max(0, Math.ceil(Math_default.log2(n)));
return Math.pow(2, countDivide);
};
var scratchCartographic0 = new Cartographic_default();
var scratchCartographic1 = new Cartographic_default();
var scratchCartographic22 = new Cartographic_default();
var scratchCartesian0 = new Cartesian3_default();
var scratchRhumbLine = new EllipsoidRhumbLine_default();
PolygonGeometryLibrary.subdivideRhumbLineCount = function(ellipsoid, p0, p1, minDistance) {
const c0 = ellipsoid.cartesianToCartographic(p0, scratchCartographic0);
const c14 = ellipsoid.cartesianToCartographic(p1, scratchCartographic1);
const rhumb = new EllipsoidRhumbLine_default(c0, c14, ellipsoid);
const n = rhumb.surfaceDistance / minDistance;
const countDivide = Math.max(0, Math.ceil(Math_default.log2(n)));
return Math.pow(2, countDivide);
};
PolygonGeometryLibrary.subdivideTexcoordLine = function(t0, t1, p0, p1, minDistance, result) {
const subdivisions = PolygonGeometryLibrary.subdivideLineCount(
p0,
p1,
minDistance
);
const length2D = Cartesian2_default.distance(t0, t1);
const distanceBetweenCoords = length2D / subdivisions;
const texcoords = result;
texcoords.length = subdivisions * 2;
let index = 0;
for (let i = 0; i < subdivisions; i++) {
const t = getPointAtDistance2D(t0, t1, i * distanceBetweenCoords, length2D);
texcoords[index++] = t[0];
texcoords[index++] = t[1];
}
return texcoords;
};
PolygonGeometryLibrary.subdivideLine = function(p0, p1, minDistance, result) {
const numVertices = PolygonGeometryLibrary.subdivideLineCount(
p0,
p1,
minDistance
);
const length2 = Cartesian3_default.distance(p0, p1);
const distanceBetweenVertices = length2 / numVertices;
if (!defined_default(result)) {
result = [];
}
const positions = result;
positions.length = numVertices * 3;
let index = 0;
for (let i = 0; i < numVertices; i++) {
const p = getPointAtDistance(p0, p1, i * distanceBetweenVertices, length2);
positions[index++] = p[0];
positions[index++] = p[1];
positions[index++] = p[2];
}
return positions;
};
PolygonGeometryLibrary.subdivideTexcoordRhumbLine = function(t0, t1, ellipsoid, p0, p1, minDistance, result) {
const c0 = ellipsoid.cartesianToCartographic(p0, scratchCartographic0);
const c14 = ellipsoid.cartesianToCartographic(p1, scratchCartographic1);
scratchRhumbLine.setEndPoints(c0, c14);
const n = scratchRhumbLine.surfaceDistance / minDistance;
const countDivide = Math.max(0, Math.ceil(Math_default.log2(n)));
const subdivisions = Math.pow(2, countDivide);
const length2D = Cartesian2_default.distance(t0, t1);
const distanceBetweenCoords = length2D / subdivisions;
const texcoords = result;
texcoords.length = subdivisions * 2;
let index = 0;
for (let i = 0; i < subdivisions; i++) {
const t = getPointAtDistance2D(t0, t1, i * distanceBetweenCoords, length2D);
texcoords[index++] = t[0];
texcoords[index++] = t[1];
}
return texcoords;
};
PolygonGeometryLibrary.subdivideRhumbLine = function(ellipsoid, p0, p1, minDistance, result) {
const c0 = ellipsoid.cartesianToCartographic(p0, scratchCartographic0);
const c14 = ellipsoid.cartesianToCartographic(p1, scratchCartographic1);
const rhumb = new EllipsoidRhumbLine_default(c0, c14, ellipsoid);
if (!defined_default(result)) {
result = [];
}
if (rhumb.surfaceDistance <= minDistance) {
result.length = 3;
result[0] = p0.x;
result[1] = p0.y;
result[2] = p0.z;
return result;
}
const n = rhumb.surfaceDistance / minDistance;
const countDivide = Math.max(0, Math.ceil(Math_default.log2(n)));
const numVertices = Math.pow(2, countDivide);
const distanceBetweenVertices = rhumb.surfaceDistance / numVertices;
const positions = result;
positions.length = numVertices * 3;
let index = 0;
for (let i = 0; i < numVertices; i++) {
const c = rhumb.interpolateUsingSurfaceDistance(
i * distanceBetweenVertices,
scratchCartographic22
);
const p = ellipsoid.cartographicToCartesian(c, scratchCartesian0);
positions[index++] = p.x;
positions[index++] = p.y;
positions[index++] = p.z;
}
return positions;
};
var scaleToGeodeticHeightN1 = new Cartesian3_default();
var scaleToGeodeticHeightN2 = new Cartesian3_default();
var scaleToGeodeticHeightP1 = new Cartesian3_default();
var scaleToGeodeticHeightP2 = new Cartesian3_default();
PolygonGeometryLibrary.scaleToGeodeticHeightExtruded = function(geometry, maxHeight, minHeight, ellipsoid, perPositionHeight) {
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
const n1 = scaleToGeodeticHeightN1;
let n2 = scaleToGeodeticHeightN2;
const p = scaleToGeodeticHeightP1;
let p2 = scaleToGeodeticHeightP2;
if (defined_default(geometry) && defined_default(geometry.attributes) && defined_default(geometry.attributes.position)) {
const positions = geometry.attributes.position.values;
const length2 = positions.length / 2;
for (let i = 0; i < length2; i += 3) {
Cartesian3_default.fromArray(positions, i, p);
ellipsoid.geodeticSurfaceNormal(p, n1);
p2 = ellipsoid.scaleToGeodeticSurface(p, p2);
n2 = Cartesian3_default.multiplyByScalar(n1, minHeight, n2);
n2 = Cartesian3_default.add(p2, n2, n2);
positions[i + length2] = n2.x;
positions[i + 1 + length2] = n2.y;
positions[i + 2 + length2] = n2.z;
if (perPositionHeight) {
p2 = Cartesian3_default.clone(p, p2);
}
n2 = Cartesian3_default.multiplyByScalar(n1, maxHeight, n2);
n2 = Cartesian3_default.add(p2, n2, n2);
positions[i] = n2.x;
positions[i + 1] = n2.y;
positions[i + 2] = n2.z;
}
}
return geometry;
};
PolygonGeometryLibrary.polygonOutlinesFromHierarchy = function(polygonHierarchy, scaleToEllipsoidSurface, ellipsoid) {
const polygons = [];
const queue = new Queue_default();
queue.enqueue(polygonHierarchy);
let i;
let j;
let length2;
while (queue.length !== 0) {
const outerNode = queue.dequeue();
let outerRing = outerNode.positions;
if (scaleToEllipsoidSurface) {
length2 = outerRing.length;
for (i = 0; i < length2; i++) {
ellipsoid.scaleToGeodeticSurface(outerRing[i], outerRing[i]);
}
}
outerRing = arrayRemoveDuplicates_default(
outerRing,
Cartesian3_default.equalsEpsilon,
true
);
if (outerRing.length < 3) {
continue;
}
const numChildren = outerNode.holes ? outerNode.holes.length : 0;
for (i = 0; i < numChildren; i++) {
const hole = outerNode.holes[i];
let holePositions = hole.positions;
if (scaleToEllipsoidSurface) {
length2 = holePositions.length;
for (j = 0; j < length2; ++j) {
ellipsoid.scaleToGeodeticSurface(holePositions[j], holePositions[j]);
}
}
holePositions = arrayRemoveDuplicates_default(
holePositions,
Cartesian3_default.equalsEpsilon,
true
);
if (holePositions.length < 3) {
continue;
}
polygons.push(holePositions);
let numGrandchildren = 0;
if (defined_default(hole.holes)) {
numGrandchildren = hole.holes.length;
}
for (j = 0; j < numGrandchildren; j++) {
queue.enqueue(hole.holes[j]);
}
}
polygons.push(outerRing);
}
return polygons;
};
var scratchRhumbIntersection = new Cartographic_default();
function computeEquatorIntersectionRhumb(start, end, ellipsoid) {
const c0 = ellipsoid.cartesianToCartographic(start, scratchCartographic0);
const c14 = ellipsoid.cartesianToCartographic(end, scratchCartographic1);
if (Math.sign(c0.latitude) === Math.sign(c14.latitude)) {
return;
}
scratchRhumbLine.setEndPoints(c0, c14);
const intersection = scratchRhumbLine.findIntersectionWithLatitude(
0,
scratchRhumbIntersection
);
if (!defined_default(intersection)) {
return;
}
let minLongitude = Math.min(c0.longitude, c14.longitude);
let maxLongitude = Math.max(c0.longitude, c14.longitude);
if (Math.abs(maxLongitude - minLongitude) > Math_default.PI) {
const swap5 = minLongitude;
minLongitude = maxLongitude;
maxLongitude = swap5;
}
if (intersection.longitude < minLongitude || intersection.longitude > maxLongitude) {
return;
}
return ellipsoid.cartographicToCartesian(intersection);
}
function computeEquatorIntersection(start, end, ellipsoid, arcType) {
if (arcType === ArcType_default.RHUMB) {
return computeEquatorIntersectionRhumb(start, end, ellipsoid);
}
const intersection = IntersectionTests_default.lineSegmentPlane(
start,
end,
Plane_default.ORIGIN_XY_PLANE
);
if (!defined_default(intersection)) {
return;
}
return ellipsoid.scaleToGeodeticSurface(intersection, intersection);
}
var scratchCartographic3 = new Cartographic_default();
function computeEdgesOnPlane(positions, ellipsoid, arcType) {
const edgesOnPlane = [];
let startPoint, endPoint, type, next, intersection, i = 0;
while (i < positions.length) {
startPoint = positions[i];
endPoint = positions[(i + 1) % positions.length];
type = Math_default.sign(startPoint.z);
next = Math_default.sign(endPoint.z);
const getLongitude = (position) => {
const cartographic2 = ellipsoid.cartesianToCartographic(
position,
scratchCartographic3
);
return cartographic2.longitude;
};
if (type === 0) {
edgesOnPlane.push({
position: i,
type,
visited: false,
next,
theta: getLongitude(startPoint)
});
} else if (next !== 0) {
intersection = computeEquatorIntersection(
startPoint,
endPoint,
ellipsoid,
arcType
);
++i;
if (!defined_default(intersection)) {
continue;
}
positions.splice(i, 0, intersection);
edgesOnPlane.push({
position: i,
type,
visited: false,
next,
theta: getLongitude(intersection)
});
}
++i;
}
return edgesOnPlane;
}
function wirePolygon(polygons, polygonIndex, positions, edgesOnPlane, toDelete, startIndex, abovePlane) {
const polygon2 = [];
let i = startIndex;
const getMatchingEdge = (i2) => (edge) => edge.position === i2;
const polygonsToWire = [];
do {
const position = positions[i];
polygon2.push(position);
const edgeIndex = edgesOnPlane.findIndex(getMatchingEdge(i));
const edge = edgesOnPlane[edgeIndex];
if (!defined_default(edge)) {
++i;
continue;
}
const { visited: hasBeenVisited, type, next } = edge;
edge.visited = true;
if (type === 0) {
if (next === 0) {
const previousEdge = edgesOnPlane[edgeIndex - (abovePlane ? 1 : -1)];
if (previousEdge?.position === i + 1) {
previousEdge.visited = true;
} else {
++i;
continue;
}
}
if (!hasBeenVisited && abovePlane && next > 0 || startIndex === i && !abovePlane && next < 0) {
++i;
continue;
}
}
const followEdge = abovePlane ? type >= 0 : type <= 0;
if (!followEdge) {
++i;
continue;
}
if (!hasBeenVisited) {
polygonsToWire.push(i);
}
const nextEdgeIndex = edgeIndex + (abovePlane ? 1 : -1);
const nextEdge = edgesOnPlane[nextEdgeIndex];
if (!defined_default(nextEdge)) {
++i;
continue;
}
i = nextEdge.position;
} while (i < positions.length && i >= 0 && i !== startIndex && polygon2.length < positions.length);
polygons.splice(polygonIndex, toDelete, polygon2);
for (const index of polygonsToWire) {
polygonIndex = wirePolygon(
polygons,
++polygonIndex,
positions,
edgesOnPlane,
0,
index,
!abovePlane
);
}
return polygonIndex;
}
PolygonGeometryLibrary.splitPolygonsOnEquator = function(outerRings, ellipsoid, arcType, result) {
if (!defined_default(result)) {
result = [];
}
result.splice(0, 0, ...outerRings);
result.length = outerRings.length;
let currentPolygon = 0;
while (currentPolygon < result.length) {
const outerRing = result[currentPolygon];
const positions = outerRing.slice();
if (outerRing.length < 3) {
result[currentPolygon] = positions;
++currentPolygon;
continue;
}
const edgesOnPlane = computeEdgesOnPlane(positions, ellipsoid, arcType);
if (positions.length === outerRing.length || edgesOnPlane.length <= 1) {
result[currentPolygon] = positions;
++currentPolygon;
continue;
}
edgesOnPlane.sort((a3, b) => {
return a3.theta - b.theta;
});
const north = positions[0].z >= 0;
currentPolygon = wirePolygon(
result,
currentPolygon,
positions,
edgesOnPlane,
1,
0,
north
);
}
return result;
};
PolygonGeometryLibrary.polygonsFromHierarchy = function(polygonHierarchy, keepDuplicates, projectPointsTo2D, scaleToEllipsoidSurface, ellipsoid, splitPolygons) {
const hierarchy = [];
const polygons = [];
const queue = new Queue_default();
queue.enqueue(polygonHierarchy);
let split = defined_default(splitPolygons);
while (queue.length !== 0) {
const outerNode = queue.dequeue();
let outerRing = outerNode.positions;
const holes = outerNode.holes;
let i;
let length2;
if (scaleToEllipsoidSurface) {
length2 = outerRing.length;
for (i = 0; i < length2; i++) {
ellipsoid.scaleToGeodeticSurface(outerRing[i], outerRing[i]);
}
}
if (!keepDuplicates) {
outerRing = arrayRemoveDuplicates_default(
outerRing,
Cartesian3_default.equalsEpsilon,
true
);
}
if (outerRing.length < 3) {
continue;
}
let positions2D = projectPointsTo2D(outerRing);
if (!defined_default(positions2D)) {
continue;
}
const holeIndices = [];
let originalWindingOrder = PolygonPipeline_default.computeWindingOrder2D(positions2D);
if (originalWindingOrder === WindingOrder_default.CLOCKWISE) {
positions2D.reverse();
outerRing = outerRing.slice().reverse();
}
if (split) {
split = false;
let polygons2 = [outerRing];
polygons2 = splitPolygons(polygons2, polygons2);
if (polygons2.length > 1) {
for (const positions2 of polygons2) {
queue.enqueue(new PolygonHierarchy_default(positions2, holes));
}
continue;
}
}
let positions = outerRing.slice();
const numChildren = defined_default(holes) ? holes.length : 0;
const polygonHoles = [];
let j;
for (i = 0; i < numChildren; i++) {
const hole = holes[i];
let holePositions = hole.positions;
if (scaleToEllipsoidSurface) {
length2 = holePositions.length;
for (j = 0; j < length2; ++j) {
ellipsoid.scaleToGeodeticSurface(holePositions[j], holePositions[j]);
}
}
if (!keepDuplicates) {
holePositions = arrayRemoveDuplicates_default(
holePositions,
Cartesian3_default.equalsEpsilon,
true
);
}
if (holePositions.length < 3) {
continue;
}
const holePositions2D = projectPointsTo2D(holePositions);
if (!defined_default(holePositions2D)) {
continue;
}
originalWindingOrder = PolygonPipeline_default.computeWindingOrder2D(holePositions2D);
if (originalWindingOrder === WindingOrder_default.CLOCKWISE) {
holePositions2D.reverse();
holePositions = holePositions.slice().reverse();
}
polygonHoles.push(holePositions);
holeIndices.push(positions.length);
positions = positions.concat(holePositions);
positions2D = positions2D.concat(holePositions2D);
let numGrandchildren = 0;
if (defined_default(hole.holes)) {
numGrandchildren = hole.holes.length;
}
for (j = 0; j < numGrandchildren; j++) {
queue.enqueue(hole.holes[j]);
}
}
hierarchy.push({
outerRing,
holes: polygonHoles
});
polygons.push({
positions,
positions2D,
holes: holeIndices
});
}
return {
hierarchy,
polygons
};
};
var computeBoundingRectangleCartesian2 = new Cartesian2_default();
var computeBoundingRectangleCartesian3 = new Cartesian3_default();
var computeBoundingRectangleQuaternion = new Quaternion_default();
var computeBoundingRectangleMatrix3 = new Matrix3_default();
PolygonGeometryLibrary.computeBoundingRectangle = function(planeNormal, projectPointTo2D, positions, angle, result) {
const rotation = Quaternion_default.fromAxisAngle(
planeNormal,
angle,
computeBoundingRectangleQuaternion
);
const textureMatrix = Matrix3_default.fromQuaternion(
rotation,
computeBoundingRectangleMatrix3
);
let minX = Number.POSITIVE_INFINITY;
let maxX = Number.NEGATIVE_INFINITY;
let minY = Number.POSITIVE_INFINITY;
let maxY = Number.NEGATIVE_INFINITY;
const length2 = positions.length;
for (let i = 0; i < length2; ++i) {
const p = Cartesian3_default.clone(
positions[i],
computeBoundingRectangleCartesian3
);
Matrix3_default.multiplyByVector(textureMatrix, p, p);
const st = projectPointTo2D(p, computeBoundingRectangleCartesian2);
if (defined_default(st)) {
minX = Math.min(minX, st.x);
maxX = Math.max(maxX, st.x);
minY = Math.min(minY, st.y);
maxY = Math.max(maxY, st.y);
}
}
result.x = minX;
result.y = minY;
result.width = maxX - minX;
result.height = maxY - minY;
return result;
};
PolygonGeometryLibrary.createGeometryFromPositions = function(ellipsoid, polygon2, textureCoordinates, granularity, perPositionHeight, vertexFormat, arcType) {
let indices = PolygonPipeline_default.triangulate(polygon2.positions2D, polygon2.holes);
if (indices.length < 3) {
indices = [0, 1, 2];
}
const positions = polygon2.positions;
const hasTexcoords = defined_default(textureCoordinates);
const texcoords = hasTexcoords ? textureCoordinates.positions : void 0;
if (perPositionHeight) {
const length2 = positions.length;
const flattenedPositions = new Array(length2 * 3);
let index = 0;
for (let i = 0; i < length2; i++) {
const p = positions[i];
flattenedPositions[index++] = p.x;
flattenedPositions[index++] = p.y;
flattenedPositions[index++] = p.z;
}
const geometryOptions = {
attributes: {
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: flattenedPositions
})
},
indices,
primitiveType: PrimitiveType_default.TRIANGLES
};
if (hasTexcoords) {
geometryOptions.attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: Cartesian2_default.packArray(texcoords)
});
}
const geometry = new Geometry_default(geometryOptions);
if (vertexFormat.normal) {
return GeometryPipeline_default.computeNormal(geometry);
}
return geometry;
}
if (arcType === ArcType_default.GEODESIC) {
return PolygonPipeline_default.computeSubdivision(
ellipsoid,
positions,
indices,
texcoords,
granularity
);
} else if (arcType === ArcType_default.RHUMB) {
return PolygonPipeline_default.computeRhumbLineSubdivision(
ellipsoid,
positions,
indices,
texcoords,
granularity
);
}
};
var computeWallTexcoordsSubdivided = [];
var computeWallIndicesSubdivided = [];
var p1Scratch2 = new Cartesian3_default();
var p2Scratch2 = new Cartesian3_default();
PolygonGeometryLibrary.computeWallGeometry = function(positions, textureCoordinates, ellipsoid, granularity, perPositionHeight, arcType) {
let edgePositions;
let topEdgeLength;
let i;
let p1;
let p2;
let t1;
let t2;
let edgeTexcoords;
let topEdgeTexcoordLength;
let length2 = positions.length;
let index = 0;
let textureIndex = 0;
const hasTexcoords = defined_default(textureCoordinates);
const texcoords = hasTexcoords ? textureCoordinates.positions : void 0;
if (!perPositionHeight) {
const minDistance = Math_default.chordLength(
granularity,
ellipsoid.maximumRadius
);
let numVertices = 0;
if (arcType === ArcType_default.GEODESIC) {
for (i = 0; i < length2; i++) {
numVertices += PolygonGeometryLibrary.subdivideLineCount(
positions[i],
positions[(i + 1) % length2],
minDistance
);
}
} else if (arcType === ArcType_default.RHUMB) {
for (i = 0; i < length2; i++) {
numVertices += PolygonGeometryLibrary.subdivideRhumbLineCount(
ellipsoid,
positions[i],
positions[(i + 1) % length2],
minDistance
);
}
}
topEdgeLength = (numVertices + length2) * 3;
edgePositions = new Array(topEdgeLength * 2);
if (hasTexcoords) {
topEdgeTexcoordLength = (numVertices + length2) * 2;
edgeTexcoords = new Array(topEdgeTexcoordLength * 2);
}
for (i = 0; i < length2; i++) {
p1 = positions[i];
p2 = positions[(i + 1) % length2];
let tempPositions;
let tempTexcoords;
if (hasTexcoords) {
t1 = texcoords[i];
t2 = texcoords[(i + 1) % length2];
}
if (arcType === ArcType_default.GEODESIC) {
tempPositions = PolygonGeometryLibrary.subdivideLine(
p1,
p2,
minDistance,
computeWallIndicesSubdivided
);
if (hasTexcoords) {
tempTexcoords = PolygonGeometryLibrary.subdivideTexcoordLine(
t1,
t2,
p1,
p2,
minDistance,
computeWallTexcoordsSubdivided
);
}
} else if (arcType === ArcType_default.RHUMB) {
tempPositions = PolygonGeometryLibrary.subdivideRhumbLine(
ellipsoid,
p1,
p2,
minDistance,
computeWallIndicesSubdivided
);
if (hasTexcoords) {
tempTexcoords = PolygonGeometryLibrary.subdivideTexcoordRhumbLine(
t1,
t2,
ellipsoid,
p1,
p2,
minDistance,
computeWallTexcoordsSubdivided
);
}
}
const tempPositionsLength = tempPositions.length;
for (let j = 0; j < tempPositionsLength; ++j, ++index) {
edgePositions[index] = tempPositions[j];
edgePositions[index + topEdgeLength] = tempPositions[j];
}
edgePositions[index] = p2.x;
edgePositions[index + topEdgeLength] = p2.x;
++index;
edgePositions[index] = p2.y;
edgePositions[index + topEdgeLength] = p2.y;
++index;
edgePositions[index] = p2.z;
edgePositions[index + topEdgeLength] = p2.z;
++index;
if (hasTexcoords) {
const tempTexcoordsLength = tempTexcoords.length;
for (let k = 0; k < tempTexcoordsLength; ++k, ++textureIndex) {
edgeTexcoords[textureIndex] = tempTexcoords[k];
edgeTexcoords[textureIndex + topEdgeTexcoordLength] = tempTexcoords[k];
}
edgeTexcoords[textureIndex] = t2.x;
edgeTexcoords[textureIndex + topEdgeTexcoordLength] = t2.x;
++textureIndex;
edgeTexcoords[textureIndex] = t2.y;
edgeTexcoords[textureIndex + topEdgeTexcoordLength] = t2.y;
++textureIndex;
}
}
} else {
topEdgeLength = length2 * 3 * 2;
edgePositions = new Array(topEdgeLength * 2);
if (hasTexcoords) {
topEdgeTexcoordLength = length2 * 2 * 2;
edgeTexcoords = new Array(topEdgeTexcoordLength * 2);
}
for (i = 0; i < length2; i++) {
p1 = positions[i];
p2 = positions[(i + 1) % length2];
edgePositions[index] = edgePositions[index + topEdgeLength] = p1.x;
++index;
edgePositions[index] = edgePositions[index + topEdgeLength] = p1.y;
++index;
edgePositions[index] = edgePositions[index + topEdgeLength] = p1.z;
++index;
edgePositions[index] = edgePositions[index + topEdgeLength] = p2.x;
++index;
edgePositions[index] = edgePositions[index + topEdgeLength] = p2.y;
++index;
edgePositions[index] = edgePositions[index + topEdgeLength] = p2.z;
++index;
if (hasTexcoords) {
t1 = texcoords[i];
t2 = texcoords[(i + 1) % length2];
edgeTexcoords[textureIndex] = edgeTexcoords[textureIndex + topEdgeTexcoordLength] = t1.x;
++textureIndex;
edgeTexcoords[textureIndex] = edgeTexcoords[textureIndex + topEdgeTexcoordLength] = t1.y;
++textureIndex;
edgeTexcoords[textureIndex] = edgeTexcoords[textureIndex + topEdgeTexcoordLength] = t2.x;
++textureIndex;
edgeTexcoords[textureIndex] = edgeTexcoords[textureIndex + topEdgeTexcoordLength] = t2.y;
++textureIndex;
}
}
}
length2 = edgePositions.length;
const indices = IndexDatatype_default.createTypedArray(
length2 / 3,
length2 - positions.length * 6
);
let edgeIndex = 0;
length2 /= 6;
for (i = 0; i < length2; i++) {
const UL = i;
const UR = UL + 1;
const LL = UL + length2;
const LR = LL + 1;
p1 = Cartesian3_default.fromArray(edgePositions, UL * 3, p1Scratch2);
p2 = Cartesian3_default.fromArray(edgePositions, UR * 3, p2Scratch2);
if (Cartesian3_default.equalsEpsilon(
p1,
p2,
Math_default.EPSILON10,
Math_default.EPSILON10
)) {
continue;
}
indices[edgeIndex++] = UL;
indices[edgeIndex++] = LL;
indices[edgeIndex++] = UR;
indices[edgeIndex++] = UR;
indices[edgeIndex++] = LL;
indices[edgeIndex++] = LR;
}
const geometryOptions = {
attributes: new GeometryAttributes_default({
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: edgePositions
})
}),
indices,
primitiveType: PrimitiveType_default.TRIANGLES
};
if (hasTexcoords) {
geometryOptions.attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: edgeTexcoords
});
}
const geometry = new Geometry_default(geometryOptions);
return geometry;
};
var PolygonGeometryLibrary_default = PolygonGeometryLibrary;
// packages/engine/Source/Core/Stereographic.js
var import_InlineWorkers534 = __toESM(require_InlineWorkers(), 1);
function Stereographic(position, tangentPlane) {
this.position = position;
if (!defined_default(this.position)) {
this.position = new Cartesian2_default();
}
this.tangentPlane = tangentPlane;
if (!defined_default(this.tangentPlane)) {
this.tangentPlane = Stereographic.NORTH_POLE_TANGENT_PLANE;
}
}
Object.defineProperties(Stereographic.prototype, {
/**
* Gets the ellipsoid.
* @memberof Stereographic.prototype
* @type {Ellipsoid}
*/
ellipsoid: {
get: function() {
return this.tangentPlane.ellipsoid;
}
},
/**
* Gets the x coordinate
* @memberof Stereographic.prototype
* @type {number}
*/
x: {
get: function() {
return this.position.x;
}
},
/**
* Gets the y coordinate
* @memberof Stereographic.prototype
* @type {number}
*/
y: {
get: function() {
return this.position.y;
}
},
/**
* Computes the conformal latitude, or the ellipsoidal latitude projected onto an arbitrary sphere.
* @memberof Stereographic.prototype
* @type {number}
*/
conformalLatitude: {
get: function() {
const r = Cartesian2_default.magnitude(this.position);
const d = 2 * this.ellipsoid.maximumRadius;
const sign3 = this.tangentPlane.plane.normal.z;
return sign3 * (Math_default.PI_OVER_TWO - 2 * Math.atan2(r, d));
}
},
/**
* Computes the longitude
* @memberof Stereographic.prototype
* @type {number}
*/
longitude: {
get: function() {
let longitude = Math_default.PI_OVER_TWO + Math.atan2(this.y, this.x);
if (longitude > Math.PI) {
longitude -= Math_default.TWO_PI;
}
return longitude;
}
}
});
var scratchCartographic4 = new Cartographic_default();
var scratchCartesian7 = new Cartesian3_default();
Stereographic.prototype.getLatitude = function(ellipsoid) {
if (!defined_default(ellipsoid)) {
ellipsoid = Ellipsoid_default.default;
}
scratchCartographic4.latitude = this.conformalLatitude;
scratchCartographic4.longitude = this.longitude;
scratchCartographic4.height = 0;
const cartesian11 = this.ellipsoid.cartographicToCartesian(
scratchCartographic4,
scratchCartesian7
);
ellipsoid.cartesianToCartographic(cartesian11, scratchCartographic4);
return scratchCartographic4.latitude;
};
var scratchProjectPointOntoPlaneRay2 = new Ray_default();
var scratchProjectPointOntoPlaneRayDirection = new Cartesian3_default();
var scratchProjectPointOntoPlaneCartesian32 = new Cartesian3_default();
Stereographic.fromCartesian = function(cartesian11, result) {
Check_default.defined("cartesian", cartesian11);
const sign3 = Math_default.signNotZero(cartesian11.z);
let tangentPlane = Stereographic.NORTH_POLE_TANGENT_PLANE;
let origin = Stereographic.SOUTH_POLE;
if (sign3 < 0) {
tangentPlane = Stereographic.SOUTH_POLE_TANGENT_PLANE;
origin = Stereographic.NORTH_POLE;
}
const ray = scratchProjectPointOntoPlaneRay2;
ray.origin = tangentPlane.ellipsoid.scaleToGeocentricSurface(
cartesian11,
ray.origin
);
ray.direction = Cartesian3_default.subtract(
ray.origin,
origin,
scratchProjectPointOntoPlaneRayDirection
);
Cartesian3_default.normalize(ray.direction, ray.direction);
const intersectionPoint = IntersectionTests_default.rayPlane(
ray,
tangentPlane.plane,
scratchProjectPointOntoPlaneCartesian32
);
const v3 = Cartesian3_default.subtract(intersectionPoint, origin, intersectionPoint);
const x = Cartesian3_default.dot(tangentPlane.xAxis, v3);
const y = sign3 * Cartesian3_default.dot(tangentPlane.yAxis, v3);
if (!defined_default(result)) {
return new Stereographic(new Cartesian2_default(x, y), tangentPlane);
}
result.position = new Cartesian2_default(x, y);
result.tangentPlane = tangentPlane;
return result;
};
Stereographic.fromCartesianArray = function(cartesians, result) {
Check_default.defined("cartesians", cartesians);
const length2 = cartesians.length;
if (!defined_default(result)) {
result = new Array(length2);
} else {
result.length = length2;
}
for (let i = 0; i < length2; i++) {
result[i] = Stereographic.fromCartesian(cartesians[i], result[i]);
}
return result;
};
Stereographic.clone = function(stereographic, result) {
if (!defined_default(stereographic)) {
return void 0;
}
if (!defined_default(result)) {
return new Stereographic(
stereographic.position,
stereographic.tangentPlane
);
}
result.position = stereographic.position;
result.tangentPlane = stereographic.tangentPlane;
return result;
};
Stereographic.HALF_UNIT_SPHERE = Object.freeze(new Ellipsoid_default(0.5, 0.5, 0.5));
Stereographic.NORTH_POLE = Object.freeze(new Cartesian3_default(0, 0, 0.5));
Stereographic.SOUTH_POLE = Object.freeze(new Cartesian3_default(0, 0, -0.5));
Stereographic.NORTH_POLE_TANGENT_PLANE = Object.freeze(
new EllipsoidTangentPlane_default(
Stereographic.NORTH_POLE,
Stereographic.HALF_UNIT_SPHERE
)
);
Stereographic.SOUTH_POLE_TANGENT_PLANE = Object.freeze(
new EllipsoidTangentPlane_default(
Stereographic.SOUTH_POLE,
Stereographic.HALF_UNIT_SPHERE
)
);
var Stereographic_default = Stereographic;
// packages/engine/Source/Core/PolygonGeometry.js
var scratchCarto1 = new Cartographic_default();
var scratchCarto2 = new Cartographic_default();
function adjustPosHeightsForNormal(position, p1, p2, ellipsoid) {
const carto12 = ellipsoid.cartesianToCartographic(position, scratchCarto1);
const height = carto12.height;
const p1Carto = ellipsoid.cartesianToCartographic(p1, scratchCarto2);
p1Carto.height = height;
ellipsoid.cartographicToCartesian(p1Carto, p1);
const p2Carto = ellipsoid.cartesianToCartographic(p2, scratchCarto2);
p2Carto.height = height - 100;
ellipsoid.cartographicToCartesian(p2Carto, p2);
}
var scratchBoundingRectangle = new BoundingRectangle_default();
var scratchPosition2 = new Cartesian3_default();
var scratchNormal2 = new Cartesian3_default();
var scratchTangent = new Cartesian3_default();
var scratchBitangent = new Cartesian3_default();
var p1Scratch3 = new Cartesian3_default();
var p2Scratch3 = new Cartesian3_default();
var scratchPerPosNormal = new Cartesian3_default();
var scratchPerPosTangent = new Cartesian3_default();
var scratchPerPosBitangent = new Cartesian3_default();
var appendTextureCoordinatesOrigin = new Cartesian2_default();
var appendTextureCoordinatesCartesian2 = new Cartesian2_default();
var appendTextureCoordinatesCartesian3 = new Cartesian3_default();
var appendTextureCoordinatesQuaternion = new Quaternion_default();
var appendTextureCoordinatesMatrix3 = new Matrix3_default();
var tangentMatrixScratch = new Matrix3_default();
function computeAttributes(options) {
const vertexFormat = options.vertexFormat;
const geometry = options.geometry;
const shadowVolume = options.shadowVolume;
const flatPositions = geometry.attributes.position.values;
const flatTexcoords = defined_default(geometry.attributes.st) ? geometry.attributes.st.values : void 0;
let length2 = flatPositions.length;
const wall = options.wall;
const top = options.top || wall;
const bottom = options.bottom || wall;
if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent || shadowVolume) {
const boundingRectangle = options.boundingRectangle;
const rotationAxis = options.rotationAxis;
const projectTo2d = options.projectTo2d;
const ellipsoid = options.ellipsoid;
const stRotation = options.stRotation;
const perPositionHeight = options.perPositionHeight;
const origin = appendTextureCoordinatesOrigin;
origin.x = boundingRectangle.x;
origin.y = boundingRectangle.y;
const textureCoordinates = vertexFormat.st ? new Float32Array(2 * (length2 / 3)) : void 0;
let normals;
if (vertexFormat.normal) {
if (perPositionHeight && top && !wall) {
normals = geometry.attributes.normal.values;
} else {
normals = new Float32Array(length2);
}
}
const tangents = vertexFormat.tangent ? new Float32Array(length2) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(length2) : void 0;
const extrudeNormals = shadowVolume ? new Float32Array(length2) : void 0;
let textureCoordIndex = 0;
let attrIndex = 0;
let normal2 = scratchNormal2;
let tangent = scratchTangent;
let bitangent = scratchBitangent;
let recomputeNormal = true;
let textureMatrix = appendTextureCoordinatesMatrix3;
let tangentRotationMatrix = tangentMatrixScratch;
if (stRotation !== 0) {
let rotation = Quaternion_default.fromAxisAngle(
rotationAxis,
stRotation,
appendTextureCoordinatesQuaternion
);
textureMatrix = Matrix3_default.fromQuaternion(rotation, textureMatrix);
rotation = Quaternion_default.fromAxisAngle(
rotationAxis,
-stRotation,
appendTextureCoordinatesQuaternion
);
tangentRotationMatrix = Matrix3_default.fromQuaternion(
rotation,
tangentRotationMatrix
);
} else {
textureMatrix = Matrix3_default.clone(Matrix3_default.IDENTITY, textureMatrix);
tangentRotationMatrix = Matrix3_default.clone(
Matrix3_default.IDENTITY,
tangentRotationMatrix
);
}
let bottomOffset = 0;
let bottomOffset2 = 0;
if (top && bottom) {
bottomOffset = length2 / 2;
bottomOffset2 = length2 / 3;
length2 /= 2;
}
for (let i = 0; i < length2; i += 3) {
const position = Cartesian3_default.fromArray(
flatPositions,
i,
appendTextureCoordinatesCartesian3
);
if (vertexFormat.st) {
if (!defined_default(flatTexcoords)) {
let p = Matrix3_default.multiplyByVector(
textureMatrix,
position,
scratchPosition2
);
p = ellipsoid.scaleToGeodeticSurface(p, p);
const st = projectTo2d([p], appendTextureCoordinatesCartesian2)[0];
Cartesian2_default.subtract(st, origin, st);
const stx = Math_default.clamp(st.x / boundingRectangle.width, 0, 1);
const sty = Math_default.clamp(st.y / boundingRectangle.height, 0, 1);
if (bottom) {
textureCoordinates[textureCoordIndex + bottomOffset2] = stx;
textureCoordinates[textureCoordIndex + 1 + bottomOffset2] = sty;
}
if (top) {
textureCoordinates[textureCoordIndex] = stx;
textureCoordinates[textureCoordIndex + 1] = sty;
}
textureCoordIndex += 2;
}
}
if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent || shadowVolume) {
const attrIndex1 = attrIndex + 1;
const attrIndex2 = attrIndex + 2;
if (wall) {
if (i + 3 < length2) {
const p1 = Cartesian3_default.fromArray(flatPositions, i + 3, p1Scratch3);
if (recomputeNormal) {
const p2 = Cartesian3_default.fromArray(
flatPositions,
i + length2,
p2Scratch3
);
if (perPositionHeight) {
adjustPosHeightsForNormal(position, p1, p2, ellipsoid);
}
Cartesian3_default.subtract(p1, position, p1);
Cartesian3_default.subtract(p2, position, p2);
normal2 = Cartesian3_default.normalize(
Cartesian3_default.cross(p2, p1, normal2),
normal2
);
recomputeNormal = false;
}
if (Cartesian3_default.equalsEpsilon(p1, position, Math_default.EPSILON10)) {
recomputeNormal = true;
}
}
if (vertexFormat.tangent || vertexFormat.bitangent) {
bitangent = ellipsoid.geodeticSurfaceNormal(position, bitangent);
if (vertexFormat.tangent) {
tangent = Cartesian3_default.normalize(
Cartesian3_default.cross(bitangent, normal2, tangent),
tangent
);
}
}
} else {
normal2 = ellipsoid.geodeticSurfaceNormal(position, normal2);
if (vertexFormat.tangent || vertexFormat.bitangent) {
if (perPositionHeight) {
scratchPerPosNormal = Cartesian3_default.fromArray(
normals,
attrIndex,
scratchPerPosNormal
);
scratchPerPosTangent = Cartesian3_default.cross(
Cartesian3_default.UNIT_Z,
scratchPerPosNormal,
scratchPerPosTangent
);
scratchPerPosTangent = Cartesian3_default.normalize(
Matrix3_default.multiplyByVector(
tangentRotationMatrix,
scratchPerPosTangent,
scratchPerPosTangent
),
scratchPerPosTangent
);
if (vertexFormat.bitangent) {
scratchPerPosBitangent = Cartesian3_default.normalize(
Cartesian3_default.cross(
scratchPerPosNormal,
scratchPerPosTangent,
scratchPerPosBitangent
),
scratchPerPosBitangent
);
}
}
tangent = Cartesian3_default.cross(Cartesian3_default.UNIT_Z, normal2, tangent);
tangent = Cartesian3_default.normalize(
Matrix3_default.multiplyByVector(tangentRotationMatrix, tangent, tangent),
tangent
);
if (vertexFormat.bitangent) {
bitangent = Cartesian3_default.normalize(
Cartesian3_default.cross(normal2, tangent, bitangent),
bitangent
);
}
}
}
if (vertexFormat.normal) {
if (options.wall) {
normals[attrIndex + bottomOffset] = normal2.x;
normals[attrIndex1 + bottomOffset] = normal2.y;
normals[attrIndex2 + bottomOffset] = normal2.z;
} else if (bottom) {
normals[attrIndex + bottomOffset] = -normal2.x;
normals[attrIndex1 + bottomOffset] = -normal2.y;
normals[attrIndex2 + bottomOffset] = -normal2.z;
}
if (top && !perPositionHeight || wall) {
normals[attrIndex] = normal2.x;
normals[attrIndex1] = normal2.y;
normals[attrIndex2] = normal2.z;
}
}
if (shadowVolume) {
if (wall) {
normal2 = ellipsoid.geodeticSurfaceNormal(position, normal2);
}
extrudeNormals[attrIndex + bottomOffset] = -normal2.x;
extrudeNormals[attrIndex1 + bottomOffset] = -normal2.y;
extrudeNormals[attrIndex2 + bottomOffset] = -normal2.z;
}
if (vertexFormat.tangent) {
if (options.wall) {
tangents[attrIndex + bottomOffset] = tangent.x;
tangents[attrIndex1 + bottomOffset] = tangent.y;
tangents[attrIndex2 + bottomOffset] = tangent.z;
} else if (bottom) {
tangents[attrIndex + bottomOffset] = -tangent.x;
tangents[attrIndex1 + bottomOffset] = -tangent.y;
tangents[attrIndex2 + bottomOffset] = -tangent.z;
}
if (top) {
if (perPositionHeight) {
tangents[attrIndex] = scratchPerPosTangent.x;
tangents[attrIndex1] = scratchPerPosTangent.y;
tangents[attrIndex2] = scratchPerPosTangent.z;
} else {
tangents[attrIndex] = tangent.x;
tangents[attrIndex1] = tangent.y;
tangents[attrIndex2] = tangent.z;
}
}
}
if (vertexFormat.bitangent) {
if (bottom) {
bitangents[attrIndex + bottomOffset] = bitangent.x;
bitangents[attrIndex1 + bottomOffset] = bitangent.y;
bitangents[attrIndex2 + bottomOffset] = bitangent.z;
}
if (top) {
if (perPositionHeight) {
bitangents[attrIndex] = scratchPerPosBitangent.x;
bitangents[attrIndex1] = scratchPerPosBitangent.y;
bitangents[attrIndex2] = scratchPerPosBitangent.z;
} else {
bitangents[attrIndex] = bitangent.x;
bitangents[attrIndex1] = bitangent.y;
bitangents[attrIndex2] = bitangent.z;
}
}
}
attrIndex += 3;
}
}
if (vertexFormat.st && !defined_default(flatTexcoords)) {
geometry.attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: textureCoordinates
});
}
if (vertexFormat.normal) {
geometry.attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: normals
});
}
if (vertexFormat.tangent) {
geometry.attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: tangents
});
}
if (vertexFormat.bitangent) {
geometry.attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: bitangents
});
}
if (shadowVolume) {
geometry.attributes.extrudeDirection = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: extrudeNormals
});
}
}
if (options.extrude && defined_default(options.offsetAttribute)) {
const size = flatPositions.length / 3;
let offsetAttribute = new Uint8Array(size);
if (options.offsetAttribute === GeometryOffsetAttribute_default.TOP) {
if (top && bottom || wall) {
offsetAttribute = offsetAttribute.fill(1, 0, size / 2);
} else if (top) {
offsetAttribute = offsetAttribute.fill(1);
}
} else {
const offsetValue = options.offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
offsetAttribute = offsetAttribute.fill(offsetValue);
}
geometry.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: offsetAttribute
});
}
return geometry;
}
var createGeometryFromPositionsExtrudedPositions = [];
function createGeometryFromPositionsExtruded(ellipsoid, polygon2, textureCoordinates, granularity, hierarchy, perPositionHeight, closeTop, closeBottom, vertexFormat, arcType) {
const geos = {
walls: []
};
let i;
if (closeTop || closeBottom) {
const topGeo = PolygonGeometryLibrary_default.createGeometryFromPositions(
ellipsoid,
polygon2,
textureCoordinates,
granularity,
perPositionHeight,
vertexFormat,
arcType
);
const edgePoints = topGeo.attributes.position.values;
const indices = topGeo.indices;
let numPositions;
let newIndices;
if (closeTop && closeBottom) {
const topBottomPositions = edgePoints.concat(edgePoints);
numPositions = topBottomPositions.length / 3;
newIndices = IndexDatatype_default.createTypedArray(
numPositions,
indices.length * 2
);
newIndices.set(indices);
const ilength = indices.length;
const length2 = numPositions / 2;
for (i = 0; i < ilength; i += 3) {
const i0 = newIndices[i] + length2;
const i1 = newIndices[i + 1] + length2;
const i2 = newIndices[i + 2] + length2;
newIndices[i + ilength] = i2;
newIndices[i + 1 + ilength] = i1;
newIndices[i + 2 + ilength] = i0;
}
topGeo.attributes.position.values = topBottomPositions;
if (perPositionHeight && vertexFormat.normal) {
const normals = topGeo.attributes.normal.values;
topGeo.attributes.normal.values = new Float32Array(
topBottomPositions.length
);
topGeo.attributes.normal.values.set(normals);
}
if (vertexFormat.st && defined_default(textureCoordinates)) {
const texcoords = topGeo.attributes.st.values;
topGeo.attributes.st.values = new Float32Array(numPositions * 2);
topGeo.attributes.st.values = texcoords.concat(texcoords);
}
topGeo.indices = newIndices;
} else if (closeBottom) {
numPositions = edgePoints.length / 3;
newIndices = IndexDatatype_default.createTypedArray(numPositions, indices.length);
for (i = 0; i < indices.length; i += 3) {
newIndices[i] = indices[i + 2];
newIndices[i + 1] = indices[i + 1];
newIndices[i + 2] = indices[i];
}
topGeo.indices = newIndices;
}
geos.topAndBottom = new GeometryInstance_default({
geometry: topGeo
});
}
let outerRing = hierarchy.outerRing;
const tangentPlane = EllipsoidTangentPlane_default.fromPoints(outerRing, ellipsoid);
let positions2D = tangentPlane.projectPointsOntoPlane(
outerRing,
createGeometryFromPositionsExtrudedPositions
);
let windingOrder = PolygonPipeline_default.computeWindingOrder2D(positions2D);
if (windingOrder === WindingOrder_default.CLOCKWISE) {
outerRing = outerRing.slice().reverse();
}
let wallGeo = PolygonGeometryLibrary_default.computeWallGeometry(
outerRing,
textureCoordinates,
ellipsoid,
granularity,
perPositionHeight,
arcType
);
geos.walls.push(
new GeometryInstance_default({
geometry: wallGeo
})
);
const holes = hierarchy.holes;
for (i = 0; i < holes.length; i++) {
let hole = holes[i];
positions2D = tangentPlane.projectPointsOntoPlane(
hole,
createGeometryFromPositionsExtrudedPositions
);
windingOrder = PolygonPipeline_default.computeWindingOrder2D(positions2D);
if (windingOrder === WindingOrder_default.COUNTER_CLOCKWISE) {
hole = hole.slice().reverse();
}
wallGeo = PolygonGeometryLibrary_default.computeWallGeometry(
hole,
textureCoordinates,
ellipsoid,
granularity,
perPositionHeight,
arcType
);
geos.walls.push(
new GeometryInstance_default({
geometry: wallGeo
})
);
}
return geos;
}
function PolygonGeometry(options) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.object("options.polygonHierarchy", options.polygonHierarchy);
if (defined_default(options.perPositionHeight) && options.perPositionHeight && defined_default(options.height)) {
throw new DeveloperError_default(
"Cannot use both options.perPositionHeight and options.height"
);
}
if (defined_default(options.arcType) && options.arcType !== ArcType_default.GEODESIC && options.arcType !== ArcType_default.RHUMB) {
throw new DeveloperError_default(
"Invalid arcType. Valid options are ArcType.GEODESIC and ArcType.RHUMB."
);
}
const polygonHierarchy = options.polygonHierarchy;
const vertexFormat = options.vertexFormat ?? VertexFormat_default.DEFAULT;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
const granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
const stRotation = options.stRotation ?? 0;
const textureCoordinates = options.textureCoordinates;
const perPositionHeight = options.perPositionHeight ?? false;
const perPositionHeightExtrude = perPositionHeight && defined_default(options.extrudedHeight);
let height = options.height ?? 0;
let extrudedHeight = options.extrudedHeight ?? height;
if (!perPositionHeightExtrude) {
const h = Math.max(height, extrudedHeight);
extrudedHeight = Math.min(height, extrudedHeight);
height = h;
}
this._vertexFormat = VertexFormat_default.clone(vertexFormat);
this._ellipsoid = Ellipsoid_default.clone(ellipsoid);
this._granularity = granularity;
this._stRotation = stRotation;
this._height = height;
this._extrudedHeight = extrudedHeight;
this._closeTop = options.closeTop ?? true;
this._closeBottom = options.closeBottom ?? true;
this._polygonHierarchy = polygonHierarchy;
this._perPositionHeight = perPositionHeight;
this._perPositionHeightExtrude = perPositionHeightExtrude;
this._shadowVolume = options.shadowVolume ?? false;
this._workerName = "createPolygonGeometry";
this._offsetAttribute = options.offsetAttribute;
this._arcType = options.arcType ?? ArcType_default.GEODESIC;
this._rectangle = void 0;
this._textureCoordinateRotationPoints = void 0;
this._textureCoordinates = textureCoordinates;
this.packedLength = PolygonGeometryLibrary_default.computeHierarchyPackedLength(
polygonHierarchy,
Cartesian3_default
) + Ellipsoid_default.packedLength + VertexFormat_default.packedLength + (textureCoordinates ? PolygonGeometryLibrary_default.computeHierarchyPackedLength(
textureCoordinates,
Cartesian2_default
) : 1) + 12;
}
PolygonGeometry.fromPositions = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.defined("options.positions", options.positions);
const newOptions2 = {
polygonHierarchy: {
positions: options.positions
},
height: options.height,
extrudedHeight: options.extrudedHeight,
vertexFormat: options.vertexFormat,
stRotation: options.stRotation,
ellipsoid: options.ellipsoid,
granularity: options.granularity,
perPositionHeight: options.perPositionHeight,
closeTop: options.closeTop,
closeBottom: options.closeBottom,
offsetAttribute: options.offsetAttribute,
arcType: options.arcType,
textureCoordinates: options.textureCoordinates
};
return new PolygonGeometry(newOptions2);
};
PolygonGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
startingIndex = PolygonGeometryLibrary_default.packPolygonHierarchy(
value._polygonHierarchy,
array,
startingIndex,
Cartesian3_default
);
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
startingIndex += VertexFormat_default.packedLength;
array[startingIndex++] = value._height;
array[startingIndex++] = value._extrudedHeight;
array[startingIndex++] = value._granularity;
array[startingIndex++] = value._stRotation;
array[startingIndex++] = value._perPositionHeightExtrude ? 1 : 0;
array[startingIndex++] = value._perPositionHeight ? 1 : 0;
array[startingIndex++] = value._closeTop ? 1 : 0;
array[startingIndex++] = value._closeBottom ? 1 : 0;
array[startingIndex++] = value._shadowVolume ? 1 : 0;
array[startingIndex++] = value._offsetAttribute ?? -1;
array[startingIndex++] = value._arcType;
if (defined_default(value._textureCoordinates)) {
startingIndex = PolygonGeometryLibrary_default.packPolygonHierarchy(
value._textureCoordinates,
array,
startingIndex,
Cartesian2_default
);
} else {
array[startingIndex++] = -1;
}
array[startingIndex++] = value.packedLength;
return array;
};
var scratchEllipsoid = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var scratchVertexFormat2 = new VertexFormat_default();
var dummyOptions = {
polygonHierarchy: {}
};
PolygonGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const polygonHierarchy = PolygonGeometryLibrary_default.unpackPolygonHierarchy(
array,
startingIndex,
Cartesian3_default
);
startingIndex = polygonHierarchy.startingIndex;
delete polygonHierarchy.startingIndex;
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid);
startingIndex += Ellipsoid_default.packedLength;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat2
);
startingIndex += VertexFormat_default.packedLength;
const height = array[startingIndex++];
const extrudedHeight = array[startingIndex++];
const granularity = array[startingIndex++];
const stRotation = array[startingIndex++];
const perPositionHeightExtrude = array[startingIndex++] === 1;
const perPositionHeight = array[startingIndex++] === 1;
const closeTop = array[startingIndex++] === 1;
const closeBottom = array[startingIndex++] === 1;
const shadowVolume = array[startingIndex++] === 1;
const offsetAttribute = array[startingIndex++];
const arcType = array[startingIndex++];
const textureCoordinates = array[startingIndex] === -1 ? void 0 : PolygonGeometryLibrary_default.unpackPolygonHierarchy(
array,
startingIndex,
Cartesian2_default
);
if (defined_default(textureCoordinates)) {
startingIndex = textureCoordinates.startingIndex;
delete textureCoordinates.startingIndex;
} else {
startingIndex++;
}
const packedLength = array[startingIndex++];
if (!defined_default(result)) {
result = new PolygonGeometry(dummyOptions);
}
result._polygonHierarchy = polygonHierarchy;
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._height = height;
result._extrudedHeight = extrudedHeight;
result._granularity = granularity;
result._stRotation = stRotation;
result._perPositionHeightExtrude = perPositionHeightExtrude;
result._perPositionHeight = perPositionHeight;
result._closeTop = closeTop;
result._closeBottom = closeBottom;
result._shadowVolume = shadowVolume;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
result._arcType = arcType;
result._textureCoordinates = textureCoordinates;
result.packedLength = packedLength;
return result;
};
var scratchCartesian02 = new Cartesian2_default();
var scratchCartesian13 = new Cartesian2_default();
var scratchPolarClosest = new Stereographic_default();
function expandRectangle(polar, lastPolar, ellipsoid, arcType, polygon2, result) {
const longitude = polar.longitude;
const lonAdjusted = longitude >= 0 ? longitude : longitude + Math_default.TWO_PI;
polygon2.westOverIdl = Math.min(polygon2.westOverIdl, lonAdjusted);
polygon2.eastOverIdl = Math.max(polygon2.eastOverIdl, lonAdjusted);
result.west = Math.min(result.west, longitude);
result.east = Math.max(result.east, longitude);
const latitude = polar.getLatitude(ellipsoid);
let segmentLatitude = latitude;
result.south = Math.min(result.south, latitude);
result.north = Math.max(result.north, latitude);
if (arcType !== ArcType_default.RHUMB) {
const segment = Cartesian2_default.subtract(
lastPolar.position,
polar.position,
scratchCartesian02
);
const t = Cartesian2_default.dot(lastPolar.position, segment) / Cartesian2_default.dot(segment, segment);
if (t > 0 && t < 1) {
const projected = Cartesian2_default.add(
lastPolar.position,
Cartesian2_default.multiplyByScalar(segment, -t, segment),
scratchCartesian13
);
const closestPolar = Stereographic_default.clone(lastPolar, scratchPolarClosest);
closestPolar.position = projected;
const adjustedLatitude = closestPolar.getLatitude(ellipsoid);
result.south = Math.min(result.south, adjustedLatitude);
result.north = Math.max(result.north, adjustedLatitude);
if (Math.abs(latitude) > Math.abs(adjustedLatitude)) {
segmentLatitude = adjustedLatitude;
}
}
}
const direction2 = lastPolar.x * polar.y - polar.x * lastPolar.y;
let angle = Math.sign(direction2);
if (angle !== 0) {
angle *= Cartesian2_default.angleBetween(lastPolar.position, polar.position);
}
if (segmentLatitude >= 0) {
polygon2.northAngle += angle;
}
if (segmentLatitude <= 0) {
polygon2.southAngle += angle;
}
}
var scratchPolar = new Stereographic_default();
var scratchPolarPrevious = new Stereographic_default();
var polygon = {
northAngle: 0,
southAngle: 0,
westOverIdl: 0,
eastOverIdl: 0
};
PolygonGeometry.computeRectangleFromPositions = function(positions, ellipsoid, arcType, result) {
Check_default.defined("positions", positions);
if (!defined_default(result)) {
result = new Rectangle_default();
}
if (positions.length < 3) {
return result;
}
result.west = Number.POSITIVE_INFINITY;
result.east = Number.NEGATIVE_INFINITY;
result.south = Number.POSITIVE_INFINITY;
result.north = Number.NEGATIVE_INFINITY;
polygon.northAngle = 0;
polygon.southAngle = 0;
polygon.westOverIdl = Number.POSITIVE_INFINITY;
polygon.eastOverIdl = Number.NEGATIVE_INFINITY;
const positionsLength = positions.length;
let lastPolarPosition = Stereographic_default.fromCartesian(
positions[0],
scratchPolarPrevious
);
for (let i = 1; i < positionsLength; i++) {
const polarPosition = Stereographic_default.fromCartesian(
positions[i],
scratchPolar
);
expandRectangle(
polarPosition,
lastPolarPosition,
ellipsoid,
arcType,
polygon,
result
);
lastPolarPosition = Stereographic_default.clone(polarPosition, lastPolarPosition);
}
expandRectangle(
Stereographic_default.fromCartesian(positions[0], scratchPolar),
lastPolarPosition,
ellipsoid,
arcType,
polygon,
result
);
if (result.east - result.west > polygon.eastOverIdl - polygon.westOverIdl) {
result.west = polygon.westOverIdl;
result.east = polygon.eastOverIdl;
if (result.east > Math_default.PI) {
result.east = result.east - Math_default.TWO_PI;
}
if (result.west > Math_default.PI) {
result.west = result.west - Math_default.TWO_PI;
}
}
if (Math_default.equalsEpsilon(
Math.abs(polygon.northAngle),
Math_default.TWO_PI,
Math_default.EPSILON10
)) {
result.north = Math_default.PI_OVER_TWO;
result.east = Math_default.PI;
result.west = -Math_default.PI;
}
if (Math_default.equalsEpsilon(
Math.abs(polygon.southAngle),
Math_default.TWO_PI,
Math_default.EPSILON10
)) {
result.south = -Math_default.PI_OVER_TWO;
result.east = Math_default.PI;
result.west = -Math_default.PI;
}
return result;
};
var scratchPolarForPlane = new Stereographic_default();
function getTangentPlane(rectangle, positions, ellipsoid) {
if (rectangle.height >= Math_default.PI || rectangle.width >= Math_default.PI) {
const polar = Stereographic_default.fromCartesian(
positions[0],
scratchPolarForPlane
);
return polar.tangentPlane;
}
return EllipsoidTangentPlane_default.fromPoints(positions, ellipsoid);
}
var scratchCartographicCyllindrical = new Cartographic_default();
function createProjectTo2d(rectangle, outerPositions, ellipsoid) {
return (positions, results) => {
if (rectangle.height >= Math_default.PI || rectangle.width >= Math_default.PI) {
if (rectangle.south < 0 && rectangle.north > 0) {
if (!defined_default(results)) {
results = [];
}
for (let i = 0; i < positions.length; ++i) {
const cartographic2 = ellipsoid.cartesianToCartographic(
positions[i],
scratchCartographicCyllindrical
);
results[i] = new Cartesian2_default(
cartographic2.longitude / Math_default.PI,
cartographic2.latitude / Math_default.PI_OVER_TWO
);
}
results.length = positions.length;
return results;
}
return Stereographic_default.fromCartesianArray(positions, results);
}
const tangentPlane = EllipsoidTangentPlane_default.fromPoints(
outerPositions,
ellipsoid
);
return tangentPlane.projectPointsOntoPlane(positions, results);
};
}
function createProjectPositionTo2d(rectangle, outerRing, ellipsoid) {
if (rectangle.height >= Math_default.PI || rectangle.width >= Math_default.PI) {
return (position, result) => {
if (rectangle.south < 0 && rectangle.north > 0) {
const cartographic2 = ellipsoid.cartesianToCartographic(
position,
scratchCartographicCyllindrical
);
if (!defined_default(result)) {
result = new Cartesian2_default();
}
result.x = cartographic2.longitude / Math_default.PI;
result.y = cartographic2.latitude / Math_default.PI_OVER_TWO;
return result;
}
return Stereographic_default.fromCartesian(position, result);
};
}
const tangentPlane = EllipsoidTangentPlane_default.fromPoints(outerRing, ellipsoid);
return (position, result) => {
return tangentPlane.projectPointsOntoPlane(position, result);
};
}
function createSplitPolygons(rectangle, ellipsoid, arcType, perPositionHeight) {
return (polygons, results) => {
if (!perPositionHeight && (rectangle.height >= Math_default.PI_OVER_TWO || rectangle.width >= 2 * Math_default.PI_OVER_THREE)) {
return PolygonGeometryLibrary_default.splitPolygonsOnEquator(
polygons,
ellipsoid,
arcType,
results
);
}
return polygons;
};
}
function computeBoundingRectangle(outerRing, rectangle, ellipsoid, stRotation) {
if (rectangle.height >= Math_default.PI || rectangle.width >= Math_default.PI) {
return BoundingRectangle_default.fromRectangle(
rectangle,
void 0,
scratchBoundingRectangle
);
}
const outerPositions = outerRing;
const tangentPlane = EllipsoidTangentPlane_default.fromPoints(
outerPositions,
ellipsoid
);
return PolygonGeometryLibrary_default.computeBoundingRectangle(
tangentPlane.plane.normal,
tangentPlane.projectPointOntoPlane.bind(tangentPlane),
outerPositions,
stRotation,
scratchBoundingRectangle
);
}
PolygonGeometry.createGeometry = function(polygonGeometry) {
const vertexFormat = polygonGeometry._vertexFormat;
const ellipsoid = polygonGeometry._ellipsoid;
const granularity = polygonGeometry._granularity;
const stRotation = polygonGeometry._stRotation;
const polygonHierarchy = polygonGeometry._polygonHierarchy;
const perPositionHeight = polygonGeometry._perPositionHeight;
const closeTop = polygonGeometry._closeTop;
const closeBottom = polygonGeometry._closeBottom;
const arcType = polygonGeometry._arcType;
const textureCoordinates = polygonGeometry._textureCoordinates;
const hasTextureCoordinates = defined_default(textureCoordinates);
const outerPositions = polygonHierarchy.positions;
if (outerPositions.length < 3) {
return;
}
const rectangle = polygonGeometry.rectangle;
const results = PolygonGeometryLibrary_default.polygonsFromHierarchy(
polygonHierarchy,
hasTextureCoordinates,
createProjectTo2d(rectangle, outerPositions, ellipsoid),
!perPositionHeight,
ellipsoid,
createSplitPolygons(rectangle, ellipsoid, arcType, perPositionHeight)
);
const hierarchy = results.hierarchy;
const polygons = results.polygons;
const dummyFunction = function(identity) {
return identity;
};
const textureCoordinatePolygons = hasTextureCoordinates ? PolygonGeometryLibrary_default.polygonsFromHierarchy(
textureCoordinates,
true,
dummyFunction,
false,
ellipsoid
).polygons : void 0;
if (hierarchy.length === 0) {
return;
}
const outerRing = hierarchy[0].outerRing;
const boundingRectangle = computeBoundingRectangle(
outerRing,
rectangle,
ellipsoid,
stRotation
);
const geometries = [];
const height = polygonGeometry._height;
const extrudedHeight = polygonGeometry._extrudedHeight;
const extrude = polygonGeometry._perPositionHeightExtrude || !Math_default.equalsEpsilon(height, extrudedHeight, 0, Math_default.EPSILON2);
const options = {
perPositionHeight,
vertexFormat,
geometry: void 0,
rotationAxis: getTangentPlane(rectangle, outerRing, ellipsoid).plane.normal,
projectTo2d: createProjectPositionTo2d(rectangle, outerRing, ellipsoid),
boundingRectangle,
ellipsoid,
stRotation,
textureCoordinates: void 0,
bottom: false,
top: true,
wall: false,
extrude: false,
arcType
};
let i;
if (extrude) {
options.extrude = true;
options.top = closeTop;
options.bottom = closeBottom;
options.shadowVolume = polygonGeometry._shadowVolume;
options.offsetAttribute = polygonGeometry._offsetAttribute;
for (i = 0; i < polygons.length; i++) {
const splitGeometry = createGeometryFromPositionsExtruded(
ellipsoid,
polygons[i],
hasTextureCoordinates ? textureCoordinatePolygons[i] : void 0,
granularity,
hierarchy[i],
perPositionHeight,
closeTop,
closeBottom,
vertexFormat,
arcType
);
let topAndBottom;
if (closeTop && closeBottom) {
topAndBottom = splitGeometry.topAndBottom;
options.geometry = PolygonGeometryLibrary_default.scaleToGeodeticHeightExtruded(
topAndBottom.geometry,
height,
extrudedHeight,
ellipsoid,
perPositionHeight
);
} else if (closeTop) {
topAndBottom = splitGeometry.topAndBottom;
topAndBottom.geometry.attributes.position.values = PolygonPipeline_default.scaleToGeodeticHeight(
topAndBottom.geometry.attributes.position.values,
height,
ellipsoid,
!perPositionHeight
);
options.geometry = topAndBottom.geometry;
} else if (closeBottom) {
topAndBottom = splitGeometry.topAndBottom;
topAndBottom.geometry.attributes.position.values = PolygonPipeline_default.scaleToGeodeticHeight(
topAndBottom.geometry.attributes.position.values,
extrudedHeight,
ellipsoid,
true
);
options.geometry = topAndBottom.geometry;
}
if (closeTop || closeBottom) {
options.wall = false;
topAndBottom.geometry = computeAttributes(options);
geometries.push(topAndBottom);
}
const walls = splitGeometry.walls;
options.wall = true;
for (let k = 0; k < walls.length; k++) {
const wall = walls[k];
options.geometry = PolygonGeometryLibrary_default.scaleToGeodeticHeightExtruded(
wall.geometry,
height,
extrudedHeight,
ellipsoid,
perPositionHeight
);
wall.geometry = computeAttributes(options);
geometries.push(wall);
}
}
} else {
for (i = 0; i < polygons.length; i++) {
const geometryInstance = new GeometryInstance_default({
geometry: PolygonGeometryLibrary_default.createGeometryFromPositions(
ellipsoid,
polygons[i],
hasTextureCoordinates ? textureCoordinatePolygons[i] : void 0,
granularity,
perPositionHeight,
vertexFormat,
arcType
)
});
geometryInstance.geometry.attributes.position.values = PolygonPipeline_default.scaleToGeodeticHeight(
geometryInstance.geometry.attributes.position.values,
height,
ellipsoid,
!perPositionHeight
);
options.geometry = geometryInstance.geometry;
geometryInstance.geometry = computeAttributes(options);
if (defined_default(polygonGeometry._offsetAttribute)) {
const length2 = geometryInstance.geometry.attributes.position.values.length;
const offsetValue = polygonGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
geometries.push(geometryInstance);
}
}
const geometry = GeometryPipeline_default.combineInstances(geometries)[0];
geometry.attributes.position.values = new Float64Array(
geometry.attributes.position.values
);
geometry.indices = IndexDatatype_default.createTypedArray(
geometry.attributes.position.values.length / 3,
geometry.indices
);
const attributes = geometry.attributes;
const boundingSphere = BoundingSphere_default.fromVertices(
attributes.position.values
);
if (!vertexFormat.position) {
delete attributes.position;
}
return new Geometry_default({
attributes,
indices: geometry.indices,
primitiveType: geometry.primitiveType,
boundingSphere,
offsetAttribute: polygonGeometry._offsetAttribute
});
};
PolygonGeometry.createShadowVolume = function(polygonGeometry, minHeightFunc, maxHeightFunc) {
const granularity = polygonGeometry._granularity;
const ellipsoid = polygonGeometry._ellipsoid;
const minHeight = minHeightFunc(granularity, ellipsoid);
const maxHeight = maxHeightFunc(granularity, ellipsoid);
return new PolygonGeometry({
polygonHierarchy: polygonGeometry._polygonHierarchy,
ellipsoid,
stRotation: polygonGeometry._stRotation,
granularity,
perPositionHeight: false,
extrudedHeight: minHeight,
height: maxHeight,
vertexFormat: VertexFormat_default.POSITION_ONLY,
shadowVolume: true,
arcType: polygonGeometry._arcType
});
};
function textureCoordinateRotationPoints(polygonGeometry) {
const stRotation = -polygonGeometry._stRotation;
if (stRotation === 0) {
return [0, 0, 0, 1, 1, 0];
}
const ellipsoid = polygonGeometry._ellipsoid;
const positions = polygonGeometry._polygonHierarchy.positions;
const boundingRectangle = polygonGeometry.rectangle;
return Geometry_default._textureCoordinateRotationPoints(
positions,
stRotation,
ellipsoid,
boundingRectangle
);
}
Object.defineProperties(PolygonGeometry.prototype, {
/**
* @private
*/
rectangle: {
get: function() {
if (!defined_default(this._rectangle)) {
const positions = this._polygonHierarchy.positions;
this._rectangle = PolygonGeometry.computeRectangleFromPositions(
positions,
this._ellipsoid,
this._arcType
);
}
return this._rectangle;
}
},
/**
* For remapping texture coordinates when rendering PolygonGeometries as GroundPrimitives.
* @private
*/
textureCoordinateRotationPoints: {
get: function() {
if (!defined_default(this._textureCoordinateRotationPoints)) {
this._textureCoordinateRotationPoints = textureCoordinateRotationPoints(this);
}
return this._textureCoordinateRotationPoints;
}
}
});
var PolygonGeometry_default = PolygonGeometry;
// packages/engine/Source/Scene/ClippingPolygon.js
function ClippingPolygon(options) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.object("options.positions", options.positions);
Check_default.typeOf.number.greaterThanOrEquals(
"options.positions.length",
options.positions.length,
3
);
this._ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
this._positions = [...options.positions];
}
Object.defineProperties(ClippingPolygon.prototype, {
/**
* Returns the total number of positions in the polygon, include any holes.
*
* @memberof ClippingPolygon.prototype
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._positions.length;
}
},
/**
* Returns the outer ring of positions.
*
* @memberof ClippingPolygon.prototype
* @type {Cartesian3[]}
* @readonly
*/
positions: {
get: function() {
return this._positions;
}
},
/**
* Returns the ellipsoid used to project the polygon onto surfaces when clipping.
*
* @memberof ClippingPolygon.prototype
* @type {Ellipsoid}
* @readonly
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
}
});
ClippingPolygon.clone = function(polygon2, result) {
Check_default.typeOf.object("polygon", polygon2);
if (!defined_default(result)) {
return new ClippingPolygon({
positions: polygon2.positions,
ellipsoid: polygon2.ellipsoid
});
}
result._ellipsoid = polygon2.ellipsoid;
result._positions.length = 0;
result._positions.push(...polygon2.positions);
return result;
};
ClippingPolygon.equals = function(left, right) {
Check_default.typeOf.object("left", left);
Check_default.typeOf.object("right", right);
return left.ellipsoid.equals(right.ellipsoid) && left.positions === right.positions;
};
ClippingPolygon.prototype.computeRectangle = function(result) {
return PolygonGeometry_default.computeRectangleFromPositions(
this.positions,
this.ellipsoid,
void 0,
result
);
};
var scratchRectangle2 = new Rectangle_default();
var spherePointScratch2 = new Cartesian3_default();
ClippingPolygon.prototype.computeSphericalExtents = function(result) {
if (!defined_default(result)) {
result = new Rectangle_default();
}
const rectangle = this.computeRectangle(scratchRectangle2);
let spherePoint = Cartographic_default.toCartesian(
Rectangle_default.southwest(rectangle),
this.ellipsoid,
spherePointScratch2
);
let magXY = Math.sqrt(
spherePoint.x * spherePoint.x + spherePoint.y * spherePoint.y
);
let sphereLatitude = Math_default.fastApproximateAtan2(magXY, spherePoint.z);
let sphereLongitude = Math_default.fastApproximateAtan2(
spherePoint.x,
spherePoint.y
);
result.south = sphereLatitude;
result.west = sphereLongitude;
spherePoint = Cartographic_default.toCartesian(
Rectangle_default.northeast(rectangle),
this.ellipsoid,
spherePointScratch2
);
magXY = Math.sqrt(
spherePoint.x * spherePoint.x + spherePoint.y * spherePoint.y
);
sphereLatitude = Math_default.fastApproximateAtan2(magXY, spherePoint.z);
sphereLongitude = Math_default.fastApproximateAtan2(
spherePoint.x,
spherePoint.y
);
result.north = sphereLatitude;
result.east = sphereLongitude;
return result;
};
var ClippingPolygon_default = ClippingPolygon;
// packages/engine/Source/Shaders/PolygonSignedDistanceFS.js
var import_InlineWorkers537 = __toESM(require_InlineWorkers(), 1);
var PolygonSignedDistanceFS_default = "in vec2 v_textureCoordinates;\n\nuniform int u_polygonsLength;\nuniform int u_extentsLength;\nuniform highp sampler2D u_polygonTexture;\nuniform highp sampler2D u_extentsTexture;\n\nint getPolygonIndex(float dimension, vec2 coord) {\n vec2 uv = coord.xy * dimension;\n return int(floor(uv.y) * dimension + floor(uv.x));\n}\n\nvec2 getLookupUv(ivec2 dimensions, int i) {\n int pixY = i / dimensions.x;\n int pixX = i - (pixY * dimensions.x);\n float pixelWidth = 1.0 / float(dimensions.x);\n float pixelHeight = 1.0 / float(dimensions.y);\n float u = (float(pixX) + 0.5) * pixelWidth; // sample from center of pixel\n float v = (float(pixY) + 0.5) * pixelHeight;\n return vec2(u, v);\n}\n\nvec4 getExtents(int i) {\n return texture(u_extentsTexture, getLookupUv(textureSize(u_extentsTexture, 0), i));\n}\n\nivec2 getPositionsLengthAndExtentsIndex(int i) {\n vec2 uv = getLookupUv(textureSize(u_polygonTexture, 0), i);\n vec4 value = texture(u_polygonTexture, uv);\n return ivec2(int(value.x), int(value.y));\n}\n\nvec2 getPolygonPosition(int i) {\n vec2 uv = getLookupUv(textureSize(u_polygonTexture, 0), i);\n return texture(u_polygonTexture, uv).xy;\n}\n\nvec2 getCoordinates(vec2 textureCoordinates, vec4 extents) {\n float latitude = mix(extents.x, extents.x + 1.0 / extents.z, textureCoordinates.y);\n float longitude = mix(extents.y, extents.y + 1.0 / extents.w, textureCoordinates.x);\n return vec2(latitude, longitude);\n}\n\nvoid main() {\n int lastPolygonIndex = 0;\n out_FragColor = vec4(1.0);\n\n // Get the relevant region of the texture\n float dimension = float(u_extentsLength);\n if (u_extentsLength > 2) {\n dimension = ceil(log2(float(u_extentsLength)));\n }\n int regionIndex = getPolygonIndex(dimension, v_textureCoordinates);\n\n for (int polygonIndex = 0; polygonIndex < u_polygonsLength; polygonIndex++) {\n ivec2 positionsLengthAndExtents = getPositionsLengthAndExtentsIndex(lastPolygonIndex);\n int positionsLength = positionsLengthAndExtents.x;\n int polygonExtentsIndex = positionsLengthAndExtents.y;\n lastPolygonIndex += 1;\n\n // Only compute signed distance for the relevant part of the atlas\n if (polygonExtentsIndex == regionIndex) {\n float clipAmount = czm_infinity;\n vec4 extents = getExtents(polygonExtentsIndex);\n vec2 textureOffset = vec2(mod(float(polygonExtentsIndex), dimension), floor(float(polygonExtentsIndex) / dimension)) / dimension;\n vec2 p = getCoordinates((v_textureCoordinates - textureOffset) * dimension, extents);\n float s = 1.0;\n\n // Check each edge for absolute distance\n for (int i = 0, j = positionsLength - 1; i < positionsLength; j = i, i++) {\n vec2 a = getPolygonPosition(lastPolygonIndex + i);\n vec2 b = getPolygonPosition(lastPolygonIndex + j);\n \n vec2 ab = b - a;\n vec2 pa = p - a;\n float t = dot(pa, ab) / dot(ab, ab);\n t = clamp(t, 0.0, 1.0);\n\n vec2 pq = pa - t * ab;\n float d = length(pq);\n\n // Inside / outside computation to determine sign\n bvec3 cond = bvec3(p.y >= a.y, \n p.y < b.y, \n ab.x * pa.y > ab.y * pa.x);\n if (all(cond) || all(not(cond))) s = -s;\n if (abs(d) < abs(clipAmount)) {\n clipAmount = d;\n }\n }\n\n // Normalize the range to [0,1]\n vec4 result = (s * vec4(clipAmount * length(extents.zw))) / 2.0 + 0.5;\n // In the case where we've iterated through multiple polygons, take the minimum\n out_FragColor = min(out_FragColor, result);\n }\n\n lastPolygonIndex += positionsLength;\n }\n}";
// packages/engine/Source/Scene/ClippingPolygonCollection.js
function ClippingPolygonCollection(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._polygons = [];
this._totalPositions = 0;
this.enabled = options.enabled ?? true;
this.inverse = options.inverse ?? false;
this.polygonAdded = new Event_default();
this.polygonRemoved = new Event_default();
this._owner = void 0;
this._float32View = void 0;
this._extentsFloat32View = void 0;
this._extentsCount = 0;
this._polygonsTexture = void 0;
this._extentsTexture = void 0;
this._signedDistanceTexture = void 0;
this._signedDistanceComputeCommand = void 0;
const polygons = options.polygons;
if (defined_default(polygons)) {
const polygonsLength = polygons.length;
for (let i = 0; i < polygonsLength; ++i) {
this._polygons.push(polygons[i]);
}
}
}
Object.defineProperties(ClippingPolygonCollection.prototype, {
/**
* Returns the number of polygons in this collection. This is commonly used with
* {@link ClippingPolygonCollection#get} to iterate over all the polygons
* in the collection.
*
* @memberof ClippingPolygonCollection.prototype
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._polygons.length;
}
},
/**
* Returns the total number of positions in all polygons in the collection.
*
* @memberof ClippingPolygonCollection.prototype
* @type {number}
* @readonly
* @private
*/
totalPositions: {
get: function() {
return this._totalPositions;
}
},
/**
* Returns a texture containing the packed computed spherical extents for each polygon
*
* @memberof ClippingPolygonCollection.prototype
* @type {Texture}
* @readonly
* @private
*/
extentsTexture: {
get: function() {
return this._extentsTexture;
}
},
/**
* Returns the number of packed extents, which can be fewer than the number of polygons.
*
* @memberof ClippingPolygonCollection.prototype
* @type {number}
* @readonly
* @private
*/
extentsCount: {
get: function() {
return this._extentsCount;
}
},
/**
* Returns the number of pixels needed in the texture containing the packed computed spherical extents for each polygon.
*
* @memberof ClippingPolygonCollection.prototype
* @type {number}
* @readonly
* @private
*/
pixelsNeededForExtents: {
get: function() {
return this.length;
}
},
/**
* Returns the number of pixels needed in the texture containing the packed polygon positions.
*
* @memberof ClippingPolygonCollection.prototype
* @type {number}
* @readonly
* @private
*/
pixelsNeededForPolygonPositions: {
get: function() {
return this.totalPositions + this.length;
}
},
/**
* Returns a texture containing the computed signed distance of each polygon.
*
* @memberof ClippingPolygonCollection.prototype
* @type {Texture}
* @readonly
* @private
*/
clippingTexture: {
get: function() {
return this._signedDistanceTexture;
}
},
/**
* A reference to the ClippingPolygonCollection's owner, if any.
*
* @memberof ClippingPolygonCollection.prototype
* @readonly
* @private
*/
owner: {
get: function() {
return this._owner;
}
},
/**
* Returns a number encapsulating the state for this ClippingPolygonCollection.
*
* Clipping mode is encoded in the sign of the number, which is just the total position count.
* If this value changes, then shader regeneration is necessary.
*
* @memberof ClippingPolygonCollection.prototype
* @returns {number} A Number that describes the ClippingPolygonCollection's state.
* @readonly
* @private
*/
clippingPolygonsState: {
get: function() {
return this.inverse ? -this.extentsCount : this.extentsCount;
}
}
});
ClippingPolygonCollection.prototype.add = function(polygon2) {
Check_default.typeOf.object("polygon", polygon2);
const newPlaneIndex = this._polygons.length;
this._polygons.push(polygon2);
this.polygonAdded.raiseEvent(polygon2, newPlaneIndex);
return polygon2;
};
ClippingPolygonCollection.prototype.get = function(index) {
Check_default.typeOf.number("index", index);
return this._polygons[index];
};
ClippingPolygonCollection.prototype.contains = function(polygon2) {
Check_default.typeOf.object("polygon", polygon2);
return this._polygons.some((p) => ClippingPolygon_default.equals(p, polygon2));
};
ClippingPolygonCollection.prototype.remove = function(polygon2) {
Check_default.typeOf.object("polygon", polygon2);
const polygons = this._polygons;
const index = polygons.findIndex((p) => ClippingPolygon_default.equals(p, polygon2));
if (index === -1) {
return false;
}
polygons.splice(index, 1);
this.polygonRemoved.raiseEvent(polygon2, index);
return true;
};
var scratchRectangle3 = new Rectangle_default();
function getExtents(polygons) {
const extentsList = [];
const polygonIndicesList = [];
const length2 = polygons.length;
for (let polygonIndex = 0; polygonIndex < length2; ++polygonIndex) {
const polygon2 = polygons[polygonIndex];
const extents = polygon2.computeSphericalExtents();
let height = Math.max(extents.height * 2.5, 1e-3);
let width = Math.max(extents.width * 2.5, 1e-3);
let paddedExtents = Rectangle_default.clone(extents);
paddedExtents.south -= height;
paddedExtents.west -= width;
paddedExtents.north += height;
paddedExtents.east += width;
paddedExtents.south = Math.max(paddedExtents.south, -Math.PI);
paddedExtents.west = Math.max(paddedExtents.west, -Math.PI);
paddedExtents.north = Math.min(paddedExtents.north, Math.PI);
paddedExtents.east = Math.min(paddedExtents.east, Math.PI);
const polygonIndices = [polygonIndex];
for (let i = 0; i < extentsList.length; ++i) {
const e = extentsList[i];
if (defined_default(e) && defined_default(Rectangle_default.simpleIntersection(e, paddedExtents)) && !Rectangle_default.equals(e, paddedExtents)) {
const intersectingPolygons = polygonIndicesList[i];
polygonIndices.push(...intersectingPolygons);
intersectingPolygons.reduce(
(extents2, p) => Rectangle_default.union(
polygons[p].computeSphericalExtents(scratchRectangle3),
extents2,
extents2
),
extents
);
extentsList[i] = void 0;
polygonIndicesList[i] = void 0;
height = Math.max(extents.height * 2.5, 1e-3);
width = Math.max(extents.width * 2.5, 1e-3);
paddedExtents = Rectangle_default.clone(extents, paddedExtents);
paddedExtents.south -= height;
paddedExtents.west -= width;
paddedExtents.north += height;
paddedExtents.east += width;
paddedExtents.south = Math.max(paddedExtents.south, -Math.PI);
paddedExtents.west = Math.max(paddedExtents.west, -Math.PI);
paddedExtents.north = Math.min(paddedExtents.north, Math.PI);
paddedExtents.east = Math.min(paddedExtents.east, Math.PI);
i = -1;
}
}
extentsList.push(paddedExtents);
polygonIndicesList.push(polygonIndices);
}
const extentsIndexByPolygon = /* @__PURE__ */ new Map();
polygonIndicesList.filter(defined_default).forEach(
(polygonIndices, e) => polygonIndices.forEach((p) => extentsIndexByPolygon.set(p, e))
);
return {
extentsList: extentsList.filter(defined_default),
extentsIndexByPolygon
};
}
ClippingPolygonCollection.prototype.removeAll = function() {
const polygons = this._polygons;
const polygonsCount = polygons.length;
for (let i = 0; i < polygonsCount; ++i) {
const polygon2 = polygons[i];
this.polygonRemoved.raiseEvent(polygon2, i);
}
this._polygons = [];
};
function packPolygonsAsFloats(clippingPolygonCollection) {
const polygonsFloat32View = clippingPolygonCollection._float32View;
const extentsFloat32View = clippingPolygonCollection._extentsFloat32View;
const polygons = clippingPolygonCollection._polygons;
const { extentsList, extentsIndexByPolygon } = getExtents(polygons);
let floatIndex = 0;
for (const [polygonIndex, polygon2] of polygons.entries()) {
const length2 = polygon2.length;
polygonsFloat32View[floatIndex++] = length2;
polygonsFloat32View[floatIndex++] = extentsIndexByPolygon.get(polygonIndex);
for (let i = 0; i < length2; ++i) {
const spherePoint = polygon2.positions[i];
const magXY = Math.hypot(spherePoint.x, spherePoint.y);
const latitudeApproximation = Math_default.fastApproximateAtan2(
magXY,
spherePoint.z
);
const longitudeApproximation = Math_default.fastApproximateAtan2(
spherePoint.x,
spherePoint.y
);
polygonsFloat32View[floatIndex++] = latitudeApproximation;
polygonsFloat32View[floatIndex++] = longitudeApproximation;
}
}
let extentsFloatIndex = 0;
for (const extents of extentsList) {
const longitudeRangeInverse = 1 / (extents.east - extents.west);
const latitudeRangeInverse = 1 / (extents.north - extents.south);
extentsFloat32View[extentsFloatIndex++] = extents.south;
extentsFloat32View[extentsFloatIndex++] = extents.west;
extentsFloat32View[extentsFloatIndex++] = latitudeRangeInverse;
extentsFloat32View[extentsFloatIndex++] = longitudeRangeInverse;
}
clippingPolygonCollection._extentsCount = extentsList.length;
}
var textureResolutionScratch2 = new Cartesian2_default();
ClippingPolygonCollection.prototype.update = function(frameState) {
const context = frameState.context;
if (!ClippingPolygonCollection.isSupported(frameState)) {
throw new RuntimeError_default(
"ClippingPolygonCollections are only supported for WebGL 2."
);
}
const totalPositions = this._polygons.reduce(
(totalPositions2, polygon2) => totalPositions2 + polygon2.length,
0
);
if (totalPositions === this.totalPositions) {
return;
}
this._totalPositions = totalPositions;
if (this.length === 0) {
return;
}
if (defined_default(this._signedDistanceComputeCommand)) {
this._signedDistanceComputeCommand.canceled = true;
this._signedDistanceComputeCommand = void 0;
}
let polygonsTexture = this._polygonsTexture;
let extentsTexture = this._extentsTexture;
let signedDistanceTexture = this._signedDistanceTexture;
if (defined_default(polygonsTexture)) {
const currentPixelCount = polygonsTexture.width * polygonsTexture.height;
if (currentPixelCount < this.pixelsNeededForPolygonPositions || this.pixelsNeededForPolygonPositions < 0.25 * currentPixelCount) {
polygonsTexture.destroy();
polygonsTexture = void 0;
this._polygonsTexture = void 0;
}
}
if (!defined_default(polygonsTexture)) {
const requiredResolution = ClippingPolygonCollection.getTextureResolution(
polygonsTexture,
this.pixelsNeededForPolygonPositions,
textureResolutionScratch2
);
polygonsTexture = new Texture_default({
context,
width: requiredResolution.x,
height: requiredResolution.y,
pixelFormat: PixelFormat_default.RG,
pixelDatatype: PixelDatatype_default.FLOAT,
sampler: Sampler_default.NEAREST,
flipY: false
});
this._float32View = new Float32Array(
requiredResolution.x * requiredResolution.y * 2
);
this._polygonsTexture = polygonsTexture;
}
if (defined_default(extentsTexture)) {
const currentPixelCount = extentsTexture.width * extentsTexture.height;
if (currentPixelCount < this.pixelsNeededForExtents || this.pixelsNeededForExtents < 0.25 * currentPixelCount) {
extentsTexture.destroy();
extentsTexture = void 0;
this._extentsTexture = void 0;
}
}
if (!defined_default(extentsTexture)) {
const requiredResolution = ClippingPolygonCollection.getTextureResolution(
extentsTexture,
this.pixelsNeededForExtents,
textureResolutionScratch2
);
extentsTexture = new Texture_default({
context,
width: requiredResolution.x,
height: requiredResolution.y,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.FLOAT,
sampler: Sampler_default.NEAREST,
flipY: false
});
this._extentsFloat32View = new Float32Array(
requiredResolution.x * requiredResolution.y * 4
);
this._extentsTexture = extentsTexture;
}
packPolygonsAsFloats(this);
extentsTexture.copyFrom({
source: {
width: extentsTexture.width,
height: extentsTexture.height,
arrayBufferView: this._extentsFloat32View
}
});
polygonsTexture.copyFrom({
source: {
width: polygonsTexture.width,
height: polygonsTexture.height,
arrayBufferView: this._float32View
}
});
if (!defined_default(signedDistanceTexture)) {
const textureDimensions = ClippingPolygonCollection.getClippingDistanceTextureResolution(
this,
textureResolutionScratch2
);
signedDistanceTexture = new Texture_default({
context,
width: textureDimensions.x,
height: textureDimensions.y,
pixelFormat: context.webgl2 ? PixelFormat_default.RED : PixelFormat_default.LUMINANCE,
pixelDatatype: PixelDatatype_default.FLOAT,
sampler: new Sampler_default({
wrapS: TextureWrap_default.CLAMP_TO_EDGE,
wrapT: TextureWrap_default.CLAMP_TO_EDGE,
minificationFilter: TextureMinificationFilter_default.LINEAR,
magnificationFilter: TextureMagnificationFilter_default.LINEAR
}),
flipY: false
});
this._signedDistanceTexture = signedDistanceTexture;
}
this._signedDistanceComputeCommand = createSignedDistanceTextureCommand(this);
};
ClippingPolygonCollection.prototype.queueCommands = function(frameState) {
if (defined_default(this._signedDistanceComputeCommand)) {
frameState.commandList.push(this._signedDistanceComputeCommand);
}
};
function createSignedDistanceTextureCommand(collection) {
const polygonTexture = collection._polygonsTexture;
const extentsTexture = collection._extentsTexture;
return new ComputeCommand_default({
fragmentShaderSource: PolygonSignedDistanceFS_default,
outputTexture: collection._signedDistanceTexture,
uniformMap: {
u_polygonsLength: function() {
return collection.length;
},
u_extentsLength: function() {
return collection.extentsCount;
},
u_extentsTexture: function() {
return extentsTexture;
},
u_polygonTexture: function() {
return polygonTexture;
}
},
persists: false,
owner: collection,
postExecute: () => {
collection._signedDistanceComputeCommand = void 0;
}
});
}
var scratchRectangleTile = new Rectangle_default();
var scratchRectangleIntersection = new Rectangle_default();
ClippingPolygonCollection.prototype.computeIntersectionWithBoundingVolume = function(tileBoundingVolume, ellipsoid) {
const polygons = this._polygons;
const length2 = polygons.length;
let intersection = Intersect_default.OUTSIDE;
if (this.inverse) {
intersection = Intersect_default.INSIDE;
}
for (let i = 0; i < length2; ++i) {
const polygon2 = polygons[i];
const polygonBoundingRectangle = polygon2.computeRectangle();
let tileBoundingRectangle = tileBoundingVolume.rectangle;
if (!defined_default(tileBoundingRectangle) && defined_default(tileBoundingVolume.boundingVolume?.computeCorners)) {
const points = tileBoundingVolume.boundingVolume.computeCorners();
tileBoundingRectangle = Rectangle_default.fromCartesianArray(
points,
ellipsoid,
scratchRectangleTile
);
}
if (!defined_default(tileBoundingRectangle)) {
tileBoundingRectangle = Rectangle_default.fromBoundingSphere(
tileBoundingVolume.boundingSphere,
ellipsoid,
scratchRectangleTile
);
}
const result = Rectangle_default.simpleIntersection(
tileBoundingRectangle,
polygonBoundingRectangle,
scratchRectangleIntersection
);
if (defined_default(result)) {
intersection = Intersect_default.INTERSECTING;
}
}
return intersection;
};
ClippingPolygonCollection.setOwner = function(clippingPolygonsCollection, owner, key) {
if (clippingPolygonsCollection === owner[key]) {
return;
}
owner[key] = owner[key] && owner[key].destroy();
if (defined_default(clippingPolygonsCollection)) {
if (defined_default(clippingPolygonsCollection._owner)) {
throw new DeveloperError_default(
"ClippingPolygonCollection should only be assigned to one object"
);
}
clippingPolygonsCollection._owner = owner;
owner[key] = clippingPolygonsCollection;
}
};
ClippingPolygonCollection.isSupported = function(scene) {
return scene?.context.webgl2;
};
ClippingPolygonCollection.getTextureResolution = function(texture, pixelsNeeded, result) {
if (defined_default(texture)) {
result.x = texture.width;
result.y = texture.height;
return result;
}
const maxSize = ContextLimits_default.maximumTextureSize;
result.x = Math.min(pixelsNeeded, maxSize);
result.y = Math.ceil(pixelsNeeded / result.x);
result.y *= 2;
return result;
};
ClippingPolygonCollection.getClippingDistanceTextureResolution = function(clippingPolygonCollection, result) {
const texture = clippingPolygonCollection.signedDistanceTexture;
if (defined_default(texture)) {
result.x = texture.width;
result.y = texture.height;
return result;
}
result.x = Math.min(ContextLimits_default.maximumTextureSize, 4096);
result.y = Math.min(ContextLimits_default.maximumTextureSize, 4096);
return result;
};
ClippingPolygonCollection.getClippingExtentsTextureResolution = function(clippingPolygonCollection, result) {
const texture = clippingPolygonCollection.extentsTexture;
if (defined_default(texture)) {
result.x = texture.width;
result.y = texture.height;
return result;
}
return ClippingPolygonCollection.getTextureResolution(
texture,
clippingPolygonCollection.pixelsNeededForExtents,
result
);
};
ClippingPolygonCollection.prototype.isDestroyed = function() {
return false;
};
ClippingPolygonCollection.prototype.destroy = function() {
if (defined_default(this._signedDistanceComputeCommand)) {
this._signedDistanceComputeCommand.canceled = true;
}
this._polygonsTexture = this._polygonsTexture && this._polygonsTexture.destroy();
this._extentsTexture = this._extentsTexture && this._extentsTexture.destroy();
this._signedDistanceTexture = this._signedDistanceTexture && this._signedDistanceTexture.destroy();
return destroyObject_default(this);
};
var ClippingPolygonCollection_default = ClippingPolygonCollection;
// packages/engine/Source/Scene/DynamicEnvironmentMapManager.js
var import_InlineWorkers546 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Atmosphere.js
var import_InlineWorkers540 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/DynamicAtmosphereLightingType.js
var import_InlineWorkers539 = __toESM(require_InlineWorkers(), 1);
var DynamicAtmosphereLightingType = {
/**
* Do not use dynamic atmosphere lighting. Atmosphere lighting effects will
* be lit from directly above rather than using the scene's light source.
*
* @type {number}
* @constant
*/
NONE: 0,
/**
* Use the scene's current light source for dynamic atmosphere lighting.
*
* @type {number}
* @constant
*/
SCENE_LIGHT: 1,
/**
* Force the dynamic atmosphere lighting to always use the sunlight direction,
* even if the scene uses a different light source.
*
* @type {number}
* @constant
*/
SUNLIGHT: 2
};
DynamicAtmosphereLightingType.fromGlobeFlags = function(globe) {
const lightingOn = globe.enableLighting && globe.dynamicAtmosphereLighting;
if (!lightingOn) {
return DynamicAtmosphereLightingType.NONE;
}
if (globe.dynamicAtmosphereLightingFromSun) {
return DynamicAtmosphereLightingType.SUNLIGHT;
}
return DynamicAtmosphereLightingType.SCENE_LIGHT;
};
var DynamicAtmosphereLightingType_default = Object.freeze(DynamicAtmosphereLightingType);
// packages/engine/Source/Scene/Atmosphere.js
function Atmosphere() {
this.lightIntensity = 10;
this.rayleighCoefficient = new Cartesian3_default(55e-7, 13e-6, 284e-7);
this.mieCoefficient = new Cartesian3_default(21e-6, 21e-6, 21e-6);
this.rayleighScaleHeight = 1e4;
this.mieScaleHeight = 3200;
this.mieAnisotropy = 0.9;
this.hueShift = 0;
this.saturationShift = 0;
this.brightnessShift = 0;
this.dynamicLighting = DynamicAtmosphereLightingType_default.NONE;
}
Atmosphere.requiresColorCorrect = function(atmosphere) {
return !(Math_default.equalsEpsilon(atmosphere.hueShift, 0, Math_default.EPSILON7) && Math_default.equalsEpsilon(
atmosphere.saturationShift,
0,
Math_default.EPSILON7
) && Math_default.equalsEpsilon(
atmosphere.brightnessShift,
0,
Math_default.EPSILON7
));
};
var Atmosphere_default = Atmosphere;
// packages/engine/Source/Shaders/AtmosphereCommon.js
var import_InlineWorkers541 = __toESM(require_InlineWorkers(), 1);
var AtmosphereCommon_default = "uniform vec3 u_radiiAndDynamicAtmosphereColor;\n\nuniform float u_atmosphereLightIntensity;\nuniform float u_atmosphereRayleighScaleHeight;\nuniform float u_atmosphereMieScaleHeight;\nuniform float u_atmosphereMieAnisotropy;\nuniform vec3 u_atmosphereRayleighCoefficient;\nuniform vec3 u_atmosphereMieCoefficient;\n\nconst float ATMOSPHERE_THICKNESS = 111e3; // The thickness of the atmosphere in meters.\nconst int PRIMARY_STEPS_MAX = 16; // Maximum number of times the ray from the camera to the world position (primary ray) is sampled.\nconst int LIGHT_STEPS_MAX = 4; // Maximum number of times the light is sampled from the light source's intersection with the atmosphere to a sample position on the primary ray.\n\n/**\n * This function computes the colors contributed by Rayliegh and Mie scattering on a given ray, as well as\n * the transmittance value for the ray.\n *\n * @param {czm_ray} primaryRay The ray from the camera to the position.\n * @param {float} primaryRayLength The length of the primary ray.\n * @param {vec3} lightDirection The direction of the light to calculate the scattering from.\n * @param {vec3} rayleighColor The variable the Rayleigh scattering will be written to.\n * @param {vec3} mieColor The variable the Mie scattering will be written to.\n * @param {float} opacity The variable the transmittance will be written to.\n * @glslFunction\n */\nvoid computeScattering(\n czm_ray primaryRay,\n float primaryRayLength,\n vec3 lightDirection,\n float atmosphereInnerRadius,\n out vec3 rayleighColor,\n out vec3 mieColor,\n out float opacity\n) {\n\n // Initialize the default scattering amounts to 0.\n rayleighColor = vec3(0.0);\n mieColor = vec3(0.0);\n opacity = 0.0;\n\n float atmosphereOuterRadius = atmosphereInnerRadius + ATMOSPHERE_THICKNESS;\n\n vec3 origin = vec3(0.0);\n\n // Calculate intersection from the camera to the outer ring of the atmosphere.\n czm_raySegment primaryRayAtmosphereIntersect = czm_raySphereIntersectionInterval(primaryRay, origin, atmosphereOuterRadius);\n\n // Return empty colors if no intersection with the atmosphere geometry.\n if (primaryRayAtmosphereIntersect == czm_emptyRaySegment) {\n return;\n }\n\n // To deal with smaller values of PRIMARY_STEPS (e.g. 4)\n // we implement a split strategy: sky or horizon.\n // For performance reasons, instead of a if/else branch\n // a soft choice is implemented through a weight 0.0 <= w_stop_gt_lprl <= 1.0\n float x = 1e-7 * primaryRayAtmosphereIntersect.stop / length(primaryRayLength);\n // Value close to 0.0: close to the horizon\n // Value close to 1.0: above in the sky\n float w_stop_gt_lprl = 0.5 * (1.0 + czm_approximateTanh(x));\n\n // The ray should start from the first intersection with the outer atmopshere, or from the camera position, if it is inside the atmosphere.\n float start_0 = primaryRayAtmosphereIntersect.start;\n primaryRayAtmosphereIntersect.start = max(primaryRayAtmosphereIntersect.start, 0.0);\n // The ray should end at the exit from the atmosphere or at the distance to the vertex, whichever is smaller.\n primaryRayAtmosphereIntersect.stop = min(primaryRayAtmosphereIntersect.stop, length(primaryRayLength));\n\n // For the number of ray steps, distinguish inside or outside atmosphere (outer space)\n // (1) from outer space we have to use more ray steps to get a realistic rendering\n // (2) within atmosphere we need fewer steps for faster rendering\n float x_o_a = start_0 - ATMOSPHERE_THICKNESS; // ATMOSPHERE_THICKNESS used as an ad-hoc constant, no precise meaning here, only the order of magnitude matters\n float w_inside_atmosphere = 1.0 - 0.5 * (1.0 + czm_approximateTanh(x_o_a));\n int PRIMARY_STEPS = PRIMARY_STEPS_MAX - int(w_inside_atmosphere * 12.0); // Number of times the ray from the camera to the world position (primary ray) is sampled.\n int LIGHT_STEPS = LIGHT_STEPS_MAX - int(w_inside_atmosphere * 2.0); // Number of times the light is sampled from the light source's intersection with the atmosphere to a sample position on the primary ray.\n\n // Setup for sampling positions along the ray - starting from the intersection with the outer ring of the atmosphere.\n float rayPositionLength = primaryRayAtmosphereIntersect.start;\n // (1) Outside the atmosphere: constant rayStepLength\n // (2) Inside atmosphere: variable rayStepLength to compensate the rough rendering of the smaller number of ray steps\n float totalRayLength = primaryRayAtmosphereIntersect.stop - rayPositionLength;\n float rayStepLengthIncrease = w_inside_atmosphere * ((1.0 - w_stop_gt_lprl) * totalRayLength / (float(PRIMARY_STEPS * (PRIMARY_STEPS + 1)) / 2.0));\n float rayStepLength = max(1.0 - w_inside_atmosphere, w_stop_gt_lprl) * totalRayLength / max(7.0 * w_inside_atmosphere, float(PRIMARY_STEPS));\n\n vec3 rayleighAccumulation = vec3(0.0);\n vec3 mieAccumulation = vec3(0.0);\n vec2 opticalDepth = vec2(0.0);\n vec2 heightScale = vec2(u_atmosphereRayleighScaleHeight, u_atmosphereMieScaleHeight);\n\n // Sample positions on the primary ray.\n for (int i = 0; i < PRIMARY_STEPS_MAX; ++i) {\n\n // The loop should be: for (int i = 0; i < PRIMARY_STEPS; ++i) {...} but WebGL1 cannot\n // loop with non-constant condition, so it has to break early instead\n if (i >= PRIMARY_STEPS) {\n break;\n }\n\n // Calculate sample position along viewpoint ray.\n vec3 samplePosition = primaryRay.origin + primaryRay.direction * (rayPositionLength + rayStepLength);\n\n // Calculate height of sample position above ellipsoid.\n float sampleHeight = length(samplePosition) - atmosphereInnerRadius;\n\n // Calculate and accumulate density of particles at the sample position.\n vec2 sampleDensity = exp(-sampleHeight / heightScale) * rayStepLength;\n opticalDepth += sampleDensity;\n\n // Generate ray from the sample position segment to the light source, up to the outer ring of the atmosphere.\n czm_ray lightRay = czm_ray(samplePosition, lightDirection);\n czm_raySegment lightRayAtmosphereIntersect = czm_raySphereIntersectionInterval(lightRay, origin, atmosphereOuterRadius);\n\n float lightStepLength = lightRayAtmosphereIntersect.stop / float(LIGHT_STEPS);\n float lightPositionLength = 0.0;\n\n vec2 lightOpticalDepth = vec2(0.0);\n\n // Sample positions along the light ray, to accumulate incidence of light on the latest sample segment.\n for (int j = 0; j < LIGHT_STEPS_MAX; ++j) {\n\n // The loop should be: for (int j = 0; i < LIGHT_STEPS; ++j) {...} but WebGL1 cannot\n // loop with non-constant condition, so it has to break early instead\n if (j >= LIGHT_STEPS) {\n break;\n }\n\n // Calculate sample position along light ray.\n vec3 lightPosition = samplePosition + lightDirection * (lightPositionLength + lightStepLength * 0.5);\n\n // Calculate height of the light sample position above ellipsoid.\n float lightHeight = length(lightPosition) - atmosphereInnerRadius;\n\n // Calculate density of photons at the light sample position.\n lightOpticalDepth += exp(-lightHeight / heightScale) * lightStepLength;\n\n // Increment distance on light ray.\n lightPositionLength += lightStepLength;\n }\n\n // Compute attenuation via the primary ray and the light ray.\n vec3 attenuation = exp(-((u_atmosphereMieCoefficient * (opticalDepth.y + lightOpticalDepth.y)) + (u_atmosphereRayleighCoefficient * (opticalDepth.x + lightOpticalDepth.x))));\n\n // Accumulate the scattering.\n rayleighAccumulation += sampleDensity.x * attenuation;\n mieAccumulation += sampleDensity.y * attenuation;\n\n // Increment distance on primary ray.\n rayPositionLength += (rayStepLength += rayStepLengthIncrease);\n }\n\n // Compute the scattering amount.\n rayleighColor = u_atmosphereRayleighCoefficient * rayleighAccumulation;\n mieColor = u_atmosphereMieCoefficient * mieAccumulation;\n\n // Compute the transmittance i.e. how much light is passing through the atmosphere.\n opacity = length(exp(-((u_atmosphereMieCoefficient * opticalDepth.y) + (u_atmosphereRayleighCoefficient * opticalDepth.x))));\n}\n\nvec4 computeAtmosphereColor(\n vec3 positionWC,\n vec3 lightDirection,\n vec3 rayleighColor,\n vec3 mieColor,\n float opacity\n) {\n // Setup the primary ray: from the camera position to the vertex position.\n vec3 cameraToPositionWC = positionWC - czm_viewerPositionWC;\n vec3 cameraToPositionWCDirection = normalize(cameraToPositionWC);\n\n float cosAngle = dot(cameraToPositionWCDirection, lightDirection);\n float cosAngleSq = cosAngle * cosAngle;\n\n float G = u_atmosphereMieAnisotropy;\n float GSq = G * G;\n\n // The Rayleigh phase function.\n float rayleighPhase = 3.0 / (50.2654824574) * (1.0 + cosAngleSq);\n // The Mie phase function.\n float miePhase = 3.0 / (25.1327412287) * ((1.0 - GSq) * (cosAngleSq + 1.0)) / (pow(1.0 + GSq - 2.0 * cosAngle * G, 1.5) * (2.0 + GSq));\n\n // The final color is generated by combining the effects of the Rayleigh and Mie scattering.\n vec3 rayleigh = rayleighPhase * rayleighColor;\n vec3 mie = miePhase * mieColor;\n\n vec3 color = (rayleigh + mie) * u_atmosphereLightIntensity;\n\n return vec4(color, opacity);\n}\n";
// packages/engine/Source/Shaders/ComputeIrradianceFS.js
var import_InlineWorkers542 = __toESM(require_InlineWorkers(), 1);
var ComputeIrradianceFS_default = "uniform samplerCube u_radianceMap;\n\nin vec2 v_textureCoordinates;\n\n\nconst float twoSqrtPi = 2.0 * sqrt(czm_pi);\n\n// Coutesy of https://www.ppsloan.org/publications/StupidSH36.pdf\nfloat computeShBasis(int index, vec3 s) {\n if (index == 0) { // l = 0, m = 0\n return 1.0 / twoSqrtPi;\n }\n \n if (index == 1) { // l = 1, m = -1\n return -sqrt(3.0) * s.y / twoSqrtPi;\n }\n\n if (index == 2) { // l = 1, m = 0\n return sqrt(3.0) * s.z / twoSqrtPi;\n }\n\n if (index == 3) { // l = 1, m = 1\n return -sqrt(3.0) * s.x / twoSqrtPi;\n }\n\n if (index == 4) { // l = 2, m = -2\n return sqrt(15.0) * s.y * s.x / twoSqrtPi;\n }\n\n if (index == 5) { // l = 2, m = -1\n return -sqrt(15.0) * s.y * s.z / twoSqrtPi;\n }\n\n if (index == 6) { // l = 2, m = 0\n return sqrt(5.0) * (3.0 * s.z * s.z - 1.0) / 2.0 / twoSqrtPi;\n }\n\n if (index == 7) { // l = 2, m = 1\n return -sqrt(15.0) * s.x * s.z / twoSqrtPi;\n }\n\n if (index == 8) { // l = 2, m = 2\n return sqrt(15.0) * (s.x * s.x - s.y * s.y) / 2.0 / twoSqrtPi;\n }\n\n return 0.0;\n}\n\nfloat vdcRadicalInverse(int i)\n{\n float r;\n float base = 2.0;\n float value = 0.0;\n float invBase = 1.0 / base;\n float invBi = invBase;\n for (int x = 0; x < 100; x++)\n {\n if (i <= 0)\n {\n break;\n }\n r = mod(float(i), base);\n value += r * invBi;\n invBi *= invBase;\n i = int(float(i) * invBase);\n }\n return value;\n}\n\nvec2 hammersley2D(int i, int N)\n{\n return vec2(float(i) / float(N), vdcRadicalInverse(i));\n}\n\n// Sample count is relatively low for the sake of performance, but should still be enough to capture directionality needed for third-order harmonics\nconst int samples = 256; \nconst float solidAngle = 1.0 / float(samples);\n\nvoid main() {\n // Get the current coefficient based on the uv\n vec2 uv = v_textureCoordinates.xy * 3.0;\n int coefficientIndex = int(floor(uv.y) * 3.0 + floor(uv.x));\n\n for (int i = 0; i < samples; ++i) {\n vec2 xi = hammersley2D(i, samples);\n float phi = czm_twoPi * xi.x;\n float cosTheta = 1.0 - 2.0 * sqrt(1.0 - xi.y * xi.y);\n float sinTheta = sqrt(1.0 - cosTheta * cosTheta);\n vec3 direction = normalize(vec3(sinTheta * cos(phi), cosTheta, sinTheta * sin(phi)));\n\n // Generate the spherical harmonics basis from the direction\n float Ylm = computeShBasis(coefficientIndex, direction);\n\n vec3 lookupDirection = -direction.xyz;\n lookupDirection.z = -lookupDirection.z;\n\n vec4 color = czm_textureCube(u_radianceMap, lookupDirection, 0.0);\n\n // Use the relevant function for this coefficient\n out_FragColor += Ylm * color * solidAngle * sinTheta;\n }\n \n}\n";
// packages/engine/Source/Shaders/ComputeRadianceMapFS.js
var import_InlineWorkers543 = __toESM(require_InlineWorkers(), 1);
var ComputeRadianceMapFS_default = "precision highp float;\n\nin vec2 v_textureCoordinates;\n\nuniform vec3 u_faceDirection; // Current cubemap face\nuniform vec3 u_positionWC;\nuniform mat4 u_enuToFixedFrame;\nuniform vec4 u_brightnessSaturationGammaIntensity;\nuniform vec4 u_groundColor; // alpha component represent albedo\n\nvec4 getCubeMapDirection(vec2 uv, vec3 faceDir) {\n vec2 scaledUV = uv * 2.0 - 1.0;\n\n if (faceDir.x != 0.0) {\n return vec4(faceDir.x, scaledUV.x * faceDir.x, -scaledUV.y, 0.0);\n } else if (faceDir.y != 0.0) {\n return vec4(scaledUV.x, -scaledUV.y * faceDir.y, faceDir.y, 0.0);\n } else {\n return vec4(scaledUV.x * faceDir.z, -faceDir.z, -scaledUV.y, 0.0); \n }\n}\n\nvoid main() { \n float height = length(u_positionWC);\n float atmosphereInnerRadius = u_radiiAndDynamicAtmosphereColor.y;\n float ellipsoidHeight = max(height - atmosphereInnerRadius, 0.0);\n\n // Scale the position to ensure the sky color is present, even when underground.\n vec3 positionWC = u_positionWC / height * (ellipsoidHeight + atmosphereInnerRadius);\n\n float atmosphereOuterRadius = u_radiiAndDynamicAtmosphereColor.x;\n float atmosphereHeight = atmosphereOuterRadius - atmosphereInnerRadius;\n\n vec3 direction = (u_enuToFixedFrame * getCubeMapDirection(v_textureCoordinates, u_faceDirection)).xyz;\n vec3 normalizedDirection = normalize(direction);\n\n czm_ray ray = czm_ray(positionWC, normalizedDirection);\n czm_raySegment intersection = czm_raySphereIntersectionInterval(ray, vec3(0.0), atmosphereInnerRadius);\n if (!czm_isEmpty(intersection)) {\n intersection = czm_rayEllipsoidIntersectionInterval(ray, vec3(0.0), czm_ellipsoidInverseRadii);\n }\n\n bool onEllipsoid = intersection.start >= 0.0;\n float rayLength = czm_branchFreeTernary(onEllipsoid, intersection.start, atmosphereOuterRadius);\n\n // Compute sky color for each position on a sphere at radius centered around the provided position's origin\n vec3 skyPositionWC = positionWC + normalizedDirection * rayLength;\n\n float lightEnum = u_radiiAndDynamicAtmosphereColor.z;\n vec3 lightDirectionWC = normalize(czm_getDynamicAtmosphereLightDirection(skyPositionWC, lightEnum));\n vec3 mieColor;\n vec3 rayleighColor;\n float opacity;\n czm_computeScattering(\n ray,\n rayLength,\n lightDirectionWC,\n atmosphereInnerRadius, \n rayleighColor,\n mieColor,\n opacity\n );\n\n vec4 atmopshereColor = czm_computeAtmosphereColor(ray, lightDirectionWC, rayleighColor, mieColor, opacity);\n\n#ifdef ATMOSPHERE_COLOR_CORRECT\n const bool ignoreBlackPixels = true;\n atmopshereColor.rgb = czm_applyHSBShift(atmopshereColor.rgb, czm_atmosphereHsbShift, ignoreBlackPixels);\n#endif\n\n vec3 lookupDirection = -normalizedDirection;\n // Flipping the X vector is a cheap way to get the inverse of czm_temeToPseudoFixed, since that's a rotation about Z.\n lookupDirection.x = -lookupDirection.x;\n lookupDirection = -normalize(czm_temeToPseudoFixed * lookupDirection);\n lookupDirection.x = -lookupDirection.x;\n\n // Values outside the atmopshere are rendered as black, when they should be treated as transparent\n float skyAlpha = clamp((1.0 - ellipsoidHeight / atmosphereHeight) * atmopshereColor.a, 0.0, 1.0);\n skyAlpha = czm_branchFreeTernary(length(atmopshereColor.rgb) <= czm_epsilon7, 0.0, skyAlpha); // Treat black as transparent\n\n // Blend starmap with atmopshere scattering\n float intensity = u_brightnessSaturationGammaIntensity.w;\n vec4 sceneSkyBoxColor = czm_textureCube(czm_environmentMap, lookupDirection);\n vec3 skyBackgroundColor = mix(czm_backgroundColor.rgb, sceneSkyBoxColor.rgb, sceneSkyBoxColor.a);\n vec4 combinedSkyColor = vec4(mix(skyBackgroundColor, atmopshereColor.rgb * intensity, skyAlpha), 1.0);\n\n // Compute ground color based on amount of reflected light, then blend it with ground atmosphere based on height\n vec3 up = normalize(positionWC);\n float occlusion = max(dot(lightDirectionWC, up), 0.05);\n vec4 groundColor = vec4(u_groundColor.rgb * u_groundColor.a * (vec3(intensity * occlusion) + atmopshereColor.rgb), 1.0);\n vec4 blendedGroundColor = mix(groundColor, atmopshereColor, clamp(ellipsoidHeight / atmosphereHeight, 0.0, 1.0));\n\n vec4 color = czm_branchFreeTernary(onEllipsoid, blendedGroundColor, combinedSkyColor);\n\n float brightness = u_brightnessSaturationGammaIntensity.x;\n float saturation = u_brightnessSaturationGammaIntensity.y;\n float gamma = u_brightnessSaturationGammaIntensity.z;\n\n#ifdef ENVIRONMENT_COLOR_CORRECT\n color.rgb = mix(vec3(0.0), color.rgb, brightness);\n color.rgb = czm_saturation(color.rgb, saturation);\n#endif\n color.rgb = pow(color.rgb, vec3(gamma)); // Normally this would be in the ifdef above, but there is a precision issue with the atmopshere scattering transmittance (alpha). Having this line is a workaround for that issue, even when gamma is 1.0.\n color.rgb = czm_gammaCorrect(color.rgb);\n\n out_FragColor = color;\n}\n";
// packages/engine/Source/Shaders/ConvolveSpecularMapFS.js
var import_InlineWorkers544 = __toESM(require_InlineWorkers(), 1);
var ConvolveSpecularMapFS_default = "precision highp float;\n\nin vec3 v_textureCoordinates;\n\nuniform float u_roughness;\nuniform samplerCube u_radianceTexture;\nuniform vec3 u_faceDirection;\n\nfloat vdcRadicalInverse(int i)\n{\n float r;\n float base = 2.0;\n float value = 0.0;\n float invBase = 1.0 / base;\n float invBi = invBase;\n for (int x = 0; x < 100; x++)\n {\n if (i <= 0)\n {\n break;\n }\n r = mod(float(i), base);\n value += r * invBi;\n invBi *= invBase;\n i = int(float(i) * invBase);\n }\n return value;\n}\n\nvec2 hammersley2D(int i, int N)\n{\n return vec2(float(i) / float(N), vdcRadicalInverse(i));\n}\n\nvec3 importanceSampleGGX(vec2 xi, float alphaRoughness, vec3 N)\n{\n float alphaRoughnessSquared = alphaRoughness * alphaRoughness;\n float phi = czm_twoPi * xi.x;\n float cosTheta = sqrt((1.0 - xi.y) / (1.0 + (alphaRoughnessSquared - 1.0) * xi.y));\n float sinTheta = sqrt(1.0 - cosTheta * cosTheta);\n vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);\n vec3 upVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\n vec3 tangentX = normalize(cross(upVector, N));\n vec3 tangentY = cross(N, tangentX);\n return tangentX * H.x + tangentY * H.y + N * H.z;\n}\n\n// Sample count is relatively low for the sake of performance, but should still be enough to prevent artifacting in lower roughnesses\nconst int samples = 128;\n\nvoid main() {\n vec3 normal = u_faceDirection;\n vec3 V = normalize(v_textureCoordinates);\n float roughness = u_roughness;\n\n vec4 color = vec4(0.0);\n float weight = 0.0;\n for (int i = 0; i < samples; ++i) {\n vec2 xi = hammersley2D(i, samples);\n vec3 H = importanceSampleGGX(xi, roughness, V);\n vec3 L = 2.0 * dot(V, H) * H - V; // reflected vector\n\n float NdotL = max(dot(V, L), 0.0);\n if (NdotL > 0.0) {\n color += vec4(czm_textureCube(u_radianceTexture, L).rgb, 1.0) * NdotL;\n weight += NdotL;\n }\n }\n out_FragColor = color / weight;\n}\n";
// packages/engine/Source/Shaders/ConvolveSpecularMapVS.js
var import_InlineWorkers545 = __toESM(require_InlineWorkers(), 1);
var ConvolveSpecularMapVS_default = "in vec3 position;\nout vec3 v_textureCoordinates;\n\nuniform vec3 u_faceDirection;\n\nvec3 getCubeMapDirection(vec2 uv, vec3 faceDir) {\n vec2 scaledUV = uv;\n\n if (faceDir.x != 0.0) {\n return vec3(faceDir.x, scaledUV.y, scaledUV.x * faceDir.x);\n } else if (faceDir.y != 0.0) {\n return vec3(scaledUV.x, -faceDir.y, -scaledUV.y * faceDir.y);\n } else {\n return vec3(scaledUV.x * faceDir.z, scaledUV.y, -faceDir.z); \n }\n}\n\nvoid main() \n{\n v_textureCoordinates = getCubeMapDirection(position.xy, u_faceDirection);\n v_textureCoordinates.y = -v_textureCoordinates.y;\n v_textureCoordinates.z = -v_textureCoordinates.z;\n gl_Position = vec4(position, 1.0);\n}\n";
// packages/engine/Source/Scene/DynamicEnvironmentMapManager.js
function DynamicEnvironmentMapManager(options) {
this._position = void 0;
this._radianceMapDirty = false;
this._radianceCommandsDirty = false;
this._convolutionsCommandsDirty = false;
this._irradianceCommandDirty = false;
this._irradianceTextureDirty = false;
this._sphericalHarmonicCoefficientsDirty = false;
this._shouldRegenerateShaders = false;
this._shouldReset = false;
options = options ?? Frozen_default.EMPTY_OBJECT;
const mipmapLevels = Math.min(
options.mipmapLevels ?? 7,
Math.log2(ContextLimits_default.maximumCubeMapSize)
);
this._mipmapLevels = mipmapLevels;
this._radianceMapComputeCommands = new Array(6);
this._convolutionComputeCommands = new Array((mipmapLevels - 1) * 6);
this._irradianceComputeCommand = void 0;
this._radianceMapFS = void 0;
this._irradianceMapFS = void 0;
this._convolveSP = void 0;
this._va = void 0;
this._radianceMapTextures = new Array(6);
this._specularMapTextures = new Array((mipmapLevels - 1) * 6);
this._radianceCubeMap = void 0;
this._irradianceMapTexture = void 0;
this._sphericalHarmonicCoefficients = DynamicEnvironmentMapManager.DEFAULT_SPHERICAL_HARMONIC_COEFFICIENTS.slice();
this._lastTime = new JulianDate_default();
const width = Math.pow(2, mipmapLevels - 1);
this._textureDimensions = new Cartesian2_default(width, width);
this._radiiAndDynamicAtmosphereColor = new Cartesian3_default();
this._sceneEnvironmentMap = void 0;
this._backgroundColor = void 0;
this._owner = void 0;
this.enabled = options.enabled ?? true;
this.shouldUpdate = true;
this.maximumSecondsDifference = options.maximumSecondsDifference ?? 60 * 60;
this.maximumPositionEpsilon = options.maximumPositionEpsilon ?? 1e3;
this.atmosphereScatteringIntensity = options.atmosphereScatteringIntensity ?? 2;
this.gamma = options.gamma ?? 1;
this.brightness = options.brightness ?? 1;
this.saturation = options.saturation ?? 1;
this.groundColor = options.groundColor ?? DynamicEnvironmentMapManager.AVERAGE_EARTH_GROUND_COLOR;
this.groundAlbedo = options.groundAlbedo ?? 0.31;
}
Object.defineProperties(DynamicEnvironmentMapManager.prototype, {
/**
* A reference to the DynamicEnvironmentMapManager's owner, if any.
* @memberof DynamicEnvironmentMapManager.prototype
* @type {object|undefined}
* @readonly
* @private
*/
owner: {
get: function() {
return this._owner;
}
},
/**
* True if model shaders need to be regenerated to account for updates.
* @memberof DynamicEnvironmentMapManager.prototype
* @type {boolean}
* @readonly
* @private
*/
shouldRegenerateShaders: {
get: function() {
return this._shouldRegenerateShaders;
}
},
/**
* The position around which the environment map is generated.
* @memberof DynamicEnvironmentMapManager.prototype
* @type {Cartesian3|undefined}
*/
position: {
get: function() {
return this._position;
},
set: function(value) {
if (Cartesian3_default.equalsEpsilon(
value,
this._position,
0,
this.maximumPositionEpsilon
)) {
return;
}
this._position = Cartesian3_default.clone(value, this._position);
this._shouldReset = true;
}
},
/**
* The computed radiance map, or undefined if it has not yet been created.
* @memberof DynamicEnvironmentMapManager.prototype
* @type {CubeMap|undefined}
* @readonly
* @private
*/
radianceCubeMap: {
get: function() {
return this._radianceCubeMap;
}
},
/**
* The maximum number of mip levels available in the radiance cubemap.
* @memberof DynamicEnvironmentMapManager.prototype
* @type {number}
* @readonly
* @private
*/
maximumMipmapLevel: {
get: function() {
return this._mipmapLevels;
}
},
/**
* The third order spherical harmonic coefficients used for the diffuse color of image-based lighting.
*
* There are nine Cartesian3 coefficients.
* The order of the coefficients is: L0,0, L1,-1, L1,0, L1,1, L2,-2, L2,-1, L2,0, L2,1, L2,2
*
* See the {@link https://github.com/CesiumGS/glTF/blob/3d-tiles-next/extensions/2.0/Vendor/EXT_feature_metadata/schema/statistics.schema.json|statistics schema reference} for the full set of properties. *
* * @memberof StructuralMetadata.prototype * @type {object} * @readonly * @private */ statistics: { get: function() { return this._statistics; } }, /** * Extra user-defined properties. * * @memberof StructuralMetadata.prototype * @type {*} * @readonly * @private */ extras: { get: function() { return this._extras; } }, /** * An object containing extensions. * * @memberof StructuralMetadata.prototype * @type {object} * @readonly * @private */ extensions: { get: function() { return this._extensions; } }, /** * Number of property tables in the metadata. * * @memberof StructuralMetadata.prototype * @type {number} * @readonly * @private */ propertyTableCount: { get: function() { return this._propertyTableCount; } }, /** * The property tables in the metadata. * * @memberof StructuralMetadata.prototype * @type {PropertyTable[]} * @readonly * @private */ propertyTables: { get: function() { return this._propertyTables; } }, /** * The property textures in the metadata. * * @memberof StructuralMetadata.prototype * @type {PropertyTexture[]} * @readonly * @private */ propertyTextures: { get: function() { return this._propertyTextures; } }, /** * The property attributes from the structural metadata extension * * @memberof StructuralMetadata.prototype * @type {PropertyAttribute[]} * @readonly * @private */ propertyAttributes: { get: function() { return this._propertyAttributes; } }, /** * Total size in bytes across all property tables * * @memberof StructuralMetadata.prototype * @type {number} * @readonly * @private */ propertyTablesByteLength: { get: function() { if (!defined_default(this._propertyTables)) { return 0; } let totalByteLength = 0; const length2 = this._propertyTables.length; for (let i = 0; i < length2; i++) { totalByteLength += this._propertyTables[i].byteLength; } return totalByteLength; } } }); StructuralMetadata.prototype.getPropertyTable = function(propertyTableId) { Check_default.typeOf.number("propertyTableId", propertyTableId); return this._propertyTables[propertyTableId]; }; StructuralMetadata.prototype.getPropertyTexture = function(propertyTextureId) { Check_default.typeOf.number("propertyTextureId", propertyTextureId); return this._propertyTextures[propertyTextureId]; }; StructuralMetadata.prototype.getPropertyAttribute = function(propertyAttributeId) { Check_default.typeOf.number("propertyAttributeId", propertyAttributeId); return this._propertyAttributes[propertyAttributeId]; }; var StructuralMetadata_default = StructuralMetadata; // packages/engine/Source/Scene/parseStructuralMetadata.js function parseStructuralMetadata(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const extension = options.extension; const schema = options.schema; Check_default.typeOf.object("options.extension", extension); Check_default.typeOf.object("options.schema", schema); const propertyTables = []; if (defined_default(extension.propertyTables)) { for (let i = 0; i < extension.propertyTables.length; i++) { const propertyTable = extension.propertyTables[i]; const classDefinition = schema.classes[propertyTable.class]; const metadataTable = new MetadataTable_default({ count: propertyTable.count, properties: propertyTable.properties, class: classDefinition, bufferViews: options.bufferViews }); propertyTables.push( new PropertyTable_default({ id: i, name: propertyTable.name, count: propertyTable.count, metadataTable, extras: propertyTable.extras, extensions: propertyTable.extensions }) ); } } const propertyTextures = []; if (defined_default(extension.propertyTextures)) { for (let i = 0; i < extension.propertyTextures.length; i++) { const propertyTexture = extension.propertyTextures[i]; propertyTextures.push( new PropertyTexture_default({ id: i, name: propertyTexture.name, propertyTexture, class: schema.classes[propertyTexture.class], textures: options.textures }) ); } } const propertyAttributes = []; if (defined_default(extension.propertyAttributes)) { for (let i = 0; i < extension.propertyAttributes.length; i++) { const propertyAttribute = extension.propertyAttributes[i]; propertyAttributes.push( new PropertyAttribute_default({ id: i, name: propertyAttribute.name, class: schema.classes[propertyAttribute.class], propertyAttribute }) ); } } return new StructuralMetadata_default({ schema, propertyTables, propertyTextures, propertyAttributes, statistics: extension.statistics, extras: extension.extras, extensions: extension.extensions }); } var parseStructuralMetadata_default = parseStructuralMetadata; // packages/engine/Source/Scene/parseFeatureMetadataLegacy.js var import_InlineWorkers558 = __toESM(require_InlineWorkers(), 1); function parseFeatureMetadataLegacy(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const extension = options.extension; const schema = options.schema; Check_default.typeOf.object("options.extension", extension); Check_default.typeOf.object("options.schema", schema); let i; const propertyTables = []; let sortedIds; if (defined_default(extension.featureTables)) { sortedIds = Object.keys(extension.featureTables).sort(); for (i = 0; i < sortedIds.length; i++) { const featureTableId = sortedIds[i]; const featureTable = extension.featureTables[featureTableId]; const classDefinition = schema.classes[featureTable.class]; const metadataTable = new MetadataTable_default({ count: featureTable.count, properties: featureTable.properties, class: classDefinition, bufferViews: options.bufferViews }); propertyTables.push( new PropertyTable_default({ id: featureTableId, count: featureTable.count, metadataTable, extras: featureTable.extras, extensions: featureTable.extensions }) ); } } const propertyTextures = []; if (defined_default(extension.featureTextures)) { sortedIds = Object.keys(extension.featureTextures).sort(); for (i = 0; i < sortedIds.length; i++) { const featureTextureId = sortedIds[i]; const featureTexture = extension.featureTextures[featureTextureId]; propertyTextures.push( new PropertyTexture_default({ id: featureTextureId, propertyTexture: transcodeToPropertyTexture(featureTexture), class: schema.classes[featureTexture.class], textures: options.textures }) ); } } return new StructuralMetadata_default({ schema, propertyTables, propertyTextures, statistics: extension.statistics, extras: extension.extras, extensions: extension.extensions }); } function transcodeToPropertyTexture(featureTexture) { const propertyTexture = { class: featureTexture.class, properties: {} }; const properties = featureTexture.properties; for (const propertyId in properties) { if (properties.hasOwnProperty(propertyId)) { const oldProperty = properties[propertyId]; const property = { // EXT_structural_metadata uses numeric channel indices instead of // a string of channel letters like "rgba". channels: reformatChannels2(oldProperty.channels), extras: oldProperty.extras, extensions: oldProperty.extensions }; propertyTexture.properties[propertyId] = combine_default( oldProperty.texture, property, true ); } } return propertyTexture; } function reformatChannels2(channelsString) { const length2 = channelsString.length; const result = new Array(length2); for (let i = 0; i < length2; i++) { result[i] = "rgba".indexOf(channelsString[i]); } return result; } var parseFeatureMetadataLegacy_default = parseFeatureMetadataLegacy; // packages/engine/Source/Scene/GltfStructuralMetadataLoader.js function GltfStructuralMetadataLoader(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const { gltf, extension, extensionLegacy, gltfResource, baseResource: baseResource2, supportedImageFormats, frameState, cacheKey, asynchronous = true } = options; Check_default.typeOf.object("options.gltf", gltf); Check_default.typeOf.object("options.gltfResource", gltfResource); Check_default.typeOf.object("options.baseResource", baseResource2); Check_default.typeOf.object("options.supportedImageFormats", supportedImageFormats); Check_default.typeOf.object("options.frameState", frameState); if (!defined_default(options.extension) && !defined_default(options.extensionLegacy)) { throw new DeveloperError_default( "One of options.extension or options.extensionLegacy must be specified" ); } this._gltfResource = gltfResource; this._baseResource = baseResource2; this._gltf = gltf; this._extension = extension; this._extensionLegacy = extensionLegacy; this._supportedImageFormats = supportedImageFormats; this._frameState = frameState; this._cacheKey = cacheKey; this._asynchronous = asynchronous; this._bufferViewLoaders = []; this._bufferViewIds = []; this._textureLoaders = []; this._textureIds = []; this._schemaLoader = void 0; this._structuralMetadata = void 0; this._state = ResourceLoaderState_default.UNLOADED; this._promise = void 0; } if (defined_default(Object.create)) { GltfStructuralMetadataLoader.prototype = Object.create( ResourceLoader_default.prototype ); GltfStructuralMetadataLoader.prototype.constructor = GltfStructuralMetadataLoader; } Object.defineProperties(GltfStructuralMetadataLoader.prototype, { /** * The cache key of the resource. * * @memberof GltfStructuralMetadataLoader.prototype * * @type {string} * @readonly * @private */ cacheKey: { get: function() { return this._cacheKey; } }, /** * The parsed structural metadata * * @memberof GltfStructuralMetadataLoader.prototype * * @type {StructuralMetadata} * @readonly * @private */ structuralMetadata: { get: function() { return this._structuralMetadata; } } }); async function loadResources5(loader) { try { const bufferViewsPromise = loadBufferViews(loader); const texturesPromise = loadTextures(loader); const schemaPromise = loadSchema(loader); await Promise.all([bufferViewsPromise, texturesPromise, schemaPromise]); if (loader.isDestroyed()) { return; } loader._gltf = void 0; loader._state = ResourceLoaderState_default.LOADED; return loader; } catch (error) { if (loader.isDestroyed()) { return; } loader.unload(); loader._state = ResourceLoaderState_default.FAILED; const errorMessage = "Failed to load structural metadata"; throw loader.getError(errorMessage, error); } } GltfStructuralMetadataLoader.prototype.load = function() { if (defined_default(this._promise)) { return this._promise; } this._state = ResourceLoaderState_default.LOADING; this._promise = loadResources5(this); return this._promise; }; function gatherBufferViewIdsFromProperties(properties, bufferViewIdSet) { for (const propertyId in properties) { if (properties.hasOwnProperty(propertyId)) { const property = properties[propertyId]; const values = property.values; const arrayOffsets = property.arrayOffsets; const stringOffsets = property.stringOffsets; if (defined_default(values)) { bufferViewIdSet[values] = true; } if (defined_default(arrayOffsets)) { bufferViewIdSet[arrayOffsets] = true; } if (defined_default(stringOffsets)) { bufferViewIdSet[stringOffsets] = true; } } } } function gatherBufferViewIdsFromPropertiesLegacy(properties, bufferViewIdSet) { for (const propertyId in properties) { if (properties.hasOwnProperty(propertyId)) { const property = properties[propertyId]; const bufferView = property.bufferView; const arrayOffsetBufferView = property.arrayOffsetBufferView; const stringOffsetBufferView = property.stringOffsetBufferView; if (defined_default(bufferView)) { bufferViewIdSet[bufferView] = true; } if (defined_default(arrayOffsetBufferView)) { bufferViewIdSet[arrayOffsetBufferView] = true; } if (defined_default(stringOffsetBufferView)) { bufferViewIdSet[stringOffsetBufferView] = true; } } } } function gatherUsedBufferViewIds(extension) { const propertyTables = extension.propertyTables; const bufferViewIdSet = {}; if (defined_default(propertyTables)) { for (let i = 0; i < propertyTables.length; i++) { const propertyTable = propertyTables[i]; gatherBufferViewIdsFromProperties( propertyTable.properties, bufferViewIdSet ); } } return bufferViewIdSet; } function gatherUsedBufferViewIdsLegacy(extensionLegacy) { const featureTables = extensionLegacy.featureTables; const bufferViewIdSet = {}; if (defined_default(featureTables)) { for (const featureTableId in featureTables) { if (featureTables.hasOwnProperty(featureTableId)) { const featureTable = featureTables[featureTableId]; const properties = featureTable.properties; if (defined_default(properties)) { gatherBufferViewIdsFromPropertiesLegacy(properties, bufferViewIdSet); } } } } return bufferViewIdSet; } async function loadBufferViews(structuralMetadataLoader) { let bufferViewIds; if (defined_default(structuralMetadataLoader._extension)) { bufferViewIds = gatherUsedBufferViewIds( structuralMetadataLoader._extension ); } else { bufferViewIds = gatherUsedBufferViewIdsLegacy( structuralMetadataLoader._extensionLegacy ); } const bufferViewPromises = []; for (const bufferViewId in bufferViewIds) { if (bufferViewIds.hasOwnProperty(bufferViewId)) { const bufferViewLoader = ResourceCache_default.getBufferViewLoader({ gltf: structuralMetadataLoader._gltf, bufferViewId: parseInt(bufferViewId), gltfResource: structuralMetadataLoader._gltfResource, baseResource: structuralMetadataLoader._baseResource }); structuralMetadataLoader._bufferViewLoaders.push(bufferViewLoader); structuralMetadataLoader._bufferViewIds.push(bufferViewId); bufferViewPromises.push(bufferViewLoader.load()); } } return Promise.all(bufferViewPromises); } function gatherUsedTextureIds(structuralMetadataExtension) { const textureIds = {}; const propertyTextures = structuralMetadataExtension.propertyTextures; if (defined_default(propertyTextures)) { for (let i = 0; i < propertyTextures.length; i++) { const propertyTexture = propertyTextures[i]; const properties = propertyTexture.properties; if (defined_default(properties)) { gatherTextureIdsFromProperties(properties, textureIds); } } } return textureIds; } function gatherTextureIdsFromProperties(properties, textureIds) { for (const propertyId in properties) { if (properties.hasOwnProperty(propertyId)) { const textureInfo = properties[propertyId]; textureIds[textureInfo.index] = textureInfo; } } } function gatherUsedTextureIdsLegacy(extensionLegacy) { const textureIds = {}; const featureTextures = extensionLegacy.featureTextures; if (defined_default(featureTextures)) { for (const featureTextureId in featureTextures) { if (featureTextures.hasOwnProperty(featureTextureId)) { const featureTexture = featureTextures[featureTextureId]; const properties = featureTexture.properties; if (defined_default(properties)) { gatherTextureIdsFromPropertiesLegacy(properties, textureIds); } } } } return textureIds; } function gatherTextureIdsFromPropertiesLegacy(properties, textureIds) { for (const propertyId in properties) { if (properties.hasOwnProperty(propertyId)) { const property = properties[propertyId]; const textureInfo = property.texture; textureIds[textureInfo.index] = textureInfo; } } } function loadTextures(structuralMetadataLoader) { let textureIds; if (defined_default(structuralMetadataLoader._extension)) { textureIds = gatherUsedTextureIds(structuralMetadataLoader._extension); } else { textureIds = gatherUsedTextureIdsLegacy( structuralMetadataLoader._extensionLegacy ); } const gltf = structuralMetadataLoader._gltf; const gltfResource = structuralMetadataLoader._gltfResource; const baseResource2 = structuralMetadataLoader._baseResource; const supportedImageFormats = structuralMetadataLoader._supportedImageFormats; const frameState = structuralMetadataLoader._frameState; const asynchronous = structuralMetadataLoader._asynchronous; const texturePromises = []; for (const textureId in textureIds) { if (textureIds.hasOwnProperty(textureId)) { const textureLoader = ResourceCache_default.getTextureLoader({ gltf, textureInfo: textureIds[textureId], gltfResource, baseResource: baseResource2, supportedImageFormats, frameState, asynchronous }); structuralMetadataLoader._textureLoaders.push(textureLoader); structuralMetadataLoader._textureIds.push(textureId); texturePromises.push(textureLoader.load()); } } return Promise.all(texturePromises); } async function loadSchema(structuralMetadataLoader) { const extension = structuralMetadataLoader._extension ?? structuralMetadataLoader._extensionLegacy; let schemaLoader; if (defined_default(extension.schemaUri)) { const resource = structuralMetadataLoader._baseResource.getDerivedResource({ url: extension.schemaUri }); schemaLoader = ResourceCache_default.getSchemaLoader({ resource }); } else { schemaLoader = ResourceCache_default.getSchemaLoader({ schema: extension.schema }); } structuralMetadataLoader._schemaLoader = schemaLoader; await schemaLoader.load(); if (!schemaLoader.isDestroyed()) { return schemaLoader.schema; } } GltfStructuralMetadataLoader.prototype.process = function(frameState) { Check_default.typeOf.object("frameState", frameState); if (this._state === ResourceLoaderState_default.READY) { return true; } if (this._state !== ResourceLoaderState_default.LOADED) { return false; } const textureLoaders = this._textureLoaders; const textureLoadersLength = textureLoaders.length; let ready = true; for (let i = 0; i < textureLoadersLength; ++i) { const textureLoader = textureLoaders[i]; const textureReady = textureLoader.process(frameState); ready = ready && textureReady; } if (!ready) { return false; } const schema = this._schemaLoader.schema; const bufferViews = {}; for (let i = 0; i < this._bufferViewIds.length; ++i) { const bufferViewId = this._bufferViewIds[i]; const bufferViewLoader = this._bufferViewLoaders[i]; if (!bufferViewLoader.isDestroyed()) { const bufferViewTypedArray = new Uint8Array(bufferViewLoader.typedArray); bufferViews[bufferViewId] = bufferViewTypedArray; } } const textures = {}; for (let i = 0; i < this._textureIds.length; ++i) { const textureId = this._textureIds[i]; const textureLoader = textureLoaders[i]; if (!textureLoader.isDestroyed()) { textures[textureId] = textureLoader.texture; } } if (defined_default(this._extension)) { this._structuralMetadata = parseStructuralMetadata_default({ extension: this._extension, schema, bufferViews, textures }); } else { this._structuralMetadata = parseFeatureMetadataLegacy_default({ extension: this._extensionLegacy, schema, bufferViews, textures }); } unloadBufferViews(this); this._state = ResourceLoaderState_default.READY; return true; }; function unloadBufferViews(structuralMetadataLoader) { const bufferViewLoaders = structuralMetadataLoader._bufferViewLoaders; const bufferViewLoadersLength = bufferViewLoaders.length; for (let i = 0; i < bufferViewLoadersLength; ++i) { ResourceCache_default.unload(bufferViewLoaders[i]); } structuralMetadataLoader._bufferViewLoaders.length = 0; structuralMetadataLoader._bufferViewIds.length = 0; } function unloadTextures(structuralMetadataLoader) { const textureLoaders = structuralMetadataLoader._textureLoaders; const textureLoadersLength = textureLoaders.length; for (let i = 0; i < textureLoadersLength; ++i) { ResourceCache_default.unload(textureLoaders[i]); } structuralMetadataLoader._textureLoaders.length = 0; structuralMetadataLoader._textureIds.length = 0; } GltfStructuralMetadataLoader.prototype.unload = function() { unloadBufferViews(this); unloadTextures(this); if (defined_default(this._schemaLoader)) { ResourceCache_default.unload(this._schemaLoader); } this._schemaLoader = void 0; this._structuralMetadata = void 0; }; var GltfStructuralMetadataLoader_default = GltfStructuralMetadataLoader; // packages/engine/Source/Scene/InstanceAttributeSemantic.js var import_InlineWorkers560 = __toESM(require_InlineWorkers(), 1); var InstanceAttributeSemantic = { /** * Per-instance translation. * * @type {string} * @constant */ TRANSLATION: "TRANSLATION", /** * Per-instance rotation. * * @type {string} * @constant */ ROTATION: "ROTATION", /** * Per-instance scale. * * @type {string} * @constant */ SCALE: "SCALE", /** * Per-instance feature ID. * * @type {string} * @constant */ FEATURE_ID: "_FEATURE_ID" }; InstanceAttributeSemantic.fromGltfSemantic = function(gltfSemantic) { Check_default.typeOf.string("gltfSemantic", gltfSemantic); let semantic = gltfSemantic; const setIndexRegex = /^(\w+)_\d+$/; const setIndexMatch = setIndexRegex.exec(gltfSemantic); if (setIndexMatch !== null) { semantic = setIndexMatch[1]; } switch (semantic) { case "TRANSLATION": return InstanceAttributeSemantic.TRANSLATION; case "ROTATION": return InstanceAttributeSemantic.ROTATION; case "SCALE": return InstanceAttributeSemantic.SCALE; case "_FEATURE_ID": return InstanceAttributeSemantic.FEATURE_ID; } return void 0; }; var InstanceAttributeSemantic_default = Object.freeze(InstanceAttributeSemantic); // packages/engine/Source/Scene/PrimitiveLoadPlan.js var import_InlineWorkers562 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/Model/PrimitiveOutlineGenerator.js var import_InlineWorkers561 = __toESM(require_InlineWorkers(), 1); var MAX_GLTF_UINT16_INDEX = 65534; var MAX_GLTF_UINT8_INDEX = 255; function PrimitiveOutlineGenerator(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const triangleIndices = options.triangleIndices; const outlineIndices = options.outlineIndices; const originalVertexCount = options.originalVertexCount; Check_default.typeOf.object("options.triangleIndices", triangleIndices); Check_default.typeOf.object("options.outlineIndices", outlineIndices); Check_default.typeOf.number("options.originalVertexCount", originalVertexCount); this._triangleIndices = triangleIndices; this._originalVertexCount = originalVertexCount; this._edges = new EdgeSet(outlineIndices, originalVertexCount); this._outlineCoordinatesTypedArray = void 0; this._extraVertices = []; initialize5(this); } Object.defineProperties(PrimitiveOutlineGenerator.prototype, { /** * The updated triangle indices after generating outlines. The caller is for * responsible for updating the primitive's indices to use this array. * * @memberof PrimitiveOutlineGenerator.prototype * * @type {Uint8Array|Uint16Array|Uint32Array} * @readonly * * @private */ updatedTriangleIndices: { get: function() { return this._triangleIndices; } }, /** * The computed outline coordinates. The caller is responsible for * turning this into a vec3 attribute for rendering. * * @memberof PrimitiveOutlineGenerator.prototype * * @type {Float32Array} * @readonly * * @private */ outlineCoordinates: { get: function() { return this._outlineCoordinatesTypedArray; } } }); function initialize5(outlineGenerator) { let triangleIndices = outlineGenerator._triangleIndices; const edges = outlineGenerator._edges; const outlineCoordinates = []; const extraVertices = outlineGenerator._extraVertices; const vertexCount = outlineGenerator._originalVertexCount; const vertexCopies = {}; for (let i = 0; i < triangleIndices.length; i += 3) { let i0 = triangleIndices[i]; let i1 = triangleIndices[i + 1]; let i2 = triangleIndices[i + 2]; const all = false; const hasEdge01 = all || edges.hasEdge(i0, i1); const hasEdge12 = all || edges.hasEdge(i1, i2); const hasEdge20 = all || edges.hasEdge(i2, i0); let unmatchableVertexIndex = matchAndStoreCoordinates( outlineCoordinates, i0, i1, i2, hasEdge01, hasEdge12, hasEdge20 ); while (defined_default(unmatchableVertexIndex)) { let copy = vertexCopies[unmatchableVertexIndex]; if (!defined_default(copy)) { copy = vertexCount + extraVertices.length; let original2 = unmatchableVertexIndex; while (original2 >= vertexCount) { original2 = extraVertices[original2 - vertexCount]; } extraVertices.push(original2); vertexCopies[unmatchableVertexIndex] = copy; } if (copy > MAX_GLTF_UINT16_INDEX && (triangleIndices instanceof Uint16Array || triangleIndices instanceof Uint8Array)) { triangleIndices = new Uint32Array(triangleIndices); } else if (copy > MAX_GLTF_UINT8_INDEX && triangleIndices instanceof Uint8Array) { triangleIndices = new Uint16Array(triangleIndices); } if (unmatchableVertexIndex === i0) { i0 = copy; triangleIndices[i] = copy; } else if (unmatchableVertexIndex === i1) { i1 = copy; triangleIndices[i + 1] = copy; } else { i2 = copy; triangleIndices[i + 2] = copy; } unmatchableVertexIndex = matchAndStoreCoordinates( outlineCoordinates, i0, i1, i2, hasEdge01, hasEdge12, hasEdge20 ); } } outlineGenerator._triangleIndices = triangleIndices; outlineGenerator._outlineCoordinatesTypedArray = new Float32Array( outlineCoordinates ); } function matchAndStoreCoordinates(outlineCoordinates, i0, i1, i2, hasEdge01, hasEdge12, hasEdge20) { const a0 = hasEdge20 ? 1 : 0; const b0 = hasEdge01 ? 1 : 0; const c0 = 0; const i0Mask = computeOrderMask(outlineCoordinates, i0, a0, b0, c0); if (i0Mask === 0) { return i0; } const a1 = 0; const b1 = hasEdge01 ? 1 : 0; const c14 = hasEdge12 ? 1 : 0; const i1Mask = computeOrderMask(outlineCoordinates, i1, a1, b1, c14); if (i1Mask === 0) { return i1; } const a22 = hasEdge20 ? 1 : 0; const b2 = 0; const c22 = hasEdge12 ? 1 : 0; const i2Mask = computeOrderMask(outlineCoordinates, i2, a22, b2, c22); if (i2Mask === 0) { return i2; } const workingOrders = i0Mask & i1Mask & i2Mask; let a3, b, c; if (workingOrders & 1 << 0) { a3 = 0; b = 1; c = 2; } else if (workingOrders & 1 << 1) { a3 = 0; c = 1; b = 2; } else if (workingOrders & 1 << 2) { b = 0; a3 = 1; c = 2; } else if (workingOrders & 1 << 3) { b = 0; c = 1; a3 = 2; } else if (workingOrders & 1 << 4) { c = 0; a3 = 1; b = 2; } else if (workingOrders & 1 << 5) { c = 0; b = 1; a3 = 2; } else { const i0ValidOrderCount = popcount6Bit(i0Mask); const i1ValidOrderCount = popcount6Bit(i1Mask); const i2ValidOrderCount = popcount6Bit(i2Mask); if (i0ValidOrderCount < i1ValidOrderCount && i0ValidOrderCount < i2ValidOrderCount) { return i0; } else if (i1ValidOrderCount < i2ValidOrderCount) { return i1; } return i2; } const i0Start = i0 * 3; outlineCoordinates[i0Start + a3] = a0; outlineCoordinates[i0Start + b] = b0; outlineCoordinates[i0Start + c] = c0; const i1Start = i1 * 3; outlineCoordinates[i1Start + a3] = a1; outlineCoordinates[i1Start + b] = b1; outlineCoordinates[i1Start + c] = c14; const i2Start = i2 * 3; outlineCoordinates[i2Start + a3] = a22; outlineCoordinates[i2Start + b] = b2; outlineCoordinates[i2Start + c] = c22; return void 0; } function computeOrderMask(outlineCoordinates, vertexIndex, a3, b, c) { const startIndex = vertexIndex * 3; const first = outlineCoordinates[startIndex]; const second = outlineCoordinates[startIndex + 1]; const third = outlineCoordinates[startIndex + 2]; if (!defined_default(first)) { return 63; } return (first === a3 && second === b && third === c) << 0 | (first === a3 && second === c && third === b) << 1 | (first === b && second === a3 && third === c) << 2 | (first === b && second === c && third === a3) << 3 | (first === c && second === a3 && third === b) << 4 | (first === c && second === b && third === a3) << 5; } function popcount6Bit(value) { return (value & 1) + (value >> 1 & 1) + (value >> 2 & 1) + (value >> 3 & 1) + (value >> 4 & 1) + (value >> 5 & 1); } PrimitiveOutlineGenerator.prototype.updateAttribute = function(attributeTypedArray) { const extraVertices = this._extraVertices; const originalLength = attributeTypedArray.length; const stride = originalLength / this._originalVertexCount; const extraVerticesLength = extraVertices.length; const ArrayType = attributeTypedArray.constructor; const result = new ArrayType( attributeTypedArray.length + extraVerticesLength * stride ); result.set(attributeTypedArray); for (let i = 0; i < extraVerticesLength; i++) { const sourceIndex = extraVertices[i] * stride; const resultIndex = originalLength + i * stride; for (let j = 0; j < stride; j++) { result[resultIndex + j] = result[sourceIndex + j]; } } return result; }; PrimitiveOutlineGenerator.createTexture = function(context) { let cache = context.cache.modelOutliningCache; if (!defined_default(cache)) { cache = context.cache.modelOutliningCache = {}; } if (defined_default(cache.outlineTexture)) { return cache.outlineTexture; } const maxSize = Math.min(4096, ContextLimits_default.maximumTextureSize); let size = maxSize; const levelZero = createMipLevel(size); const mipLevels = []; while (size > 1) { size >>= 1; mipLevels.push(createMipLevel(size)); } const texture = new Texture_default({ context, source: { arrayBufferView: levelZero, mipLevels }, width: maxSize, height: 1, pixelFormat: PixelFormat_default.LUMINANCE, sampler: new Sampler_default({ wrapS: TextureWrap_default.CLAMP_TO_EDGE, wrapT: TextureWrap_default.CLAMP_TO_EDGE, minificationFilter: TextureMinificationFilter_default.LINEAR_MIPMAP_LINEAR, magnificationFilter: TextureMagnificationFilter_default.LINEAR }) }); cache.outlineTexture = texture; return texture; }; function createMipLevel(size) { const texture = new Uint8Array(size); texture[size - 1] = 192; if (size === 8) { texture[size - 1] = 96; } else if (size === 4) { texture[size - 1] = 48; } else if (size === 2) { texture[size - 1] = 24; } else if (size === 1) { texture[size - 1] = 12; } return texture; } function EdgeSet(edgeIndices, originalVertexCount) { this._originalVertexCount = originalVertexCount; this._edges = /* @__PURE__ */ new Set(); for (let i = 0; i < edgeIndices.length; i += 2) { const a3 = edgeIndices[i]; const b = edgeIndices[i + 1]; const small = Math.min(a3, b); const big = Math.max(a3, b); const hash2 = small * this._originalVertexCount + big; this._edges.add(hash2); } } EdgeSet.prototype.hasEdge = function(a3, b) { const small = Math.min(a3, b); const big = Math.max(a3, b); const hash2 = small * this._originalVertexCount + big; return this._edges.has(hash2); }; var PrimitiveOutlineGenerator_default = PrimitiveOutlineGenerator; // packages/engine/Source/Scene/PrimitiveLoadPlan.js function AttributeLoadPlan(attribute) { Check_default.typeOf.object("attribute", attribute); this.attribute = attribute; this.loadBuffer = false; this.loadTypedArray = false; } function IndicesLoadPlan(indices) { Check_default.typeOf.object("indices", indices); this.indices = indices; this.loadBuffer = false; this.loadTypedArray = false; } function PrimitiveLoadPlan(primitive) { Check_default.typeOf.object("primitive", primitive); this.primitive = primitive; this.attributePlans = []; this.indicesPlan = void 0; this.needsOutlines = false; this.outlineIndices = void 0; this.needsGaussianSplats = false; } PrimitiveLoadPlan.prototype.postProcess = function(context) { if (this.needsOutlines) { generateOutlines(this); generateBuffers(this, context); } if (this.needsGaussianSplats) { setupGaussianSplatBuffers(this, context); } }; function generateOutlines(loadPlan) { const primitive = loadPlan.primitive; const indices = primitive.indices; const vertexCount = primitive.attributes[0].count; const generator = new PrimitiveOutlineGenerator_default({ triangleIndices: indices.typedArray, outlineIndices: loadPlan.outlineIndices, originalVertexCount: vertexCount }); indices.typedArray = generator.updatedTriangleIndices; indices.indexDatatype = IndexDatatype_default.fromTypedArray(indices.typedArray); const outlineCoordinates = makeOutlineCoordinatesAttribute( generator.outlineCoordinates ); const outlineCoordinatesPlan = new AttributeLoadPlan(outlineCoordinates); outlineCoordinatesPlan.loadBuffer = true; outlineCoordinatesPlan.loadTypedArray = false; loadPlan.attributePlans.push(outlineCoordinatesPlan); primitive.outlineCoordinates = outlineCoordinatesPlan.attribute; const attributePlans = loadPlan.attributePlans; const attributesLength = loadPlan.attributePlans.length; for (let i = 0; i < attributesLength; i++) { const attribute = attributePlans[i].attribute; attribute.typedArray = generator.updateAttribute(attribute.typedArray); } } function makeOutlineCoordinatesAttribute(outlineCoordinatesTypedArray) { const attribute = new ModelComponents_default.Attribute(); attribute.name = "_OUTLINE_COORDINATES"; attribute.typedArray = outlineCoordinatesTypedArray; attribute.componentDatatype = ComponentDatatype_default.FLOAT; attribute.type = AttributeType_default.VEC3; attribute.normalized = false; attribute.count = outlineCoordinatesTypedArray.length / 3; return attribute; } function setupGaussianSplatBuffers(loadPlan, context) { const attributePlans = loadPlan.attributePlans; const attrLen = attributePlans.length; for (let i = 0; i < attrLen; i++) { const attributePlan = attributePlans[i]; attributePlan.loadBuffer = false; attributePlan.loadTypedArray = true; } } function generateBuffers(loadPlan, context) { generateAttributeBuffers(loadPlan.attributePlans, context); if (defined_default(loadPlan.indicesPlan)) { generateIndexBuffers(loadPlan.indicesPlan, context); } } function generateAttributeBuffers(attributePlans, context) { const attributesLength = attributePlans.length; for (let i = 0; i < attributesLength; i++) { const attributePlan = attributePlans[i]; const attribute = attributePlan.attribute; const typedArray = attribute.typedArray; if (attributePlan.loadBuffer) { const buffer2 = Buffer_default.createVertexBuffer({ typedArray, context, usage: BufferUsage_default.STATIC_DRAW }); buffer2.vertexArrayDestroyable = false; attribute.buffer = buffer2; } if (!attributePlan.loadTypedArray) { attribute.typedArray = void 0; } } } function generateIndexBuffers(indicesPlan, context) { const indices = indicesPlan.indices; if (indicesPlan.loadBuffer) { const buffer2 = Buffer_default.createIndexBuffer({ typedArray: indices.typedArray, context, usage: BufferUsage_default.STATIC_DRAW, indexDatatype: indices.indexDatatype }); indices.buffer = buffer2; buffer2.vertexArrayDestroyable = false; } if (!indicesPlan.loadTypedArray) { indices.typedArray = void 0; } } PrimitiveLoadPlan.AttributeLoadPlan = AttributeLoadPlan; PrimitiveLoadPlan.IndicesLoadPlan = IndicesLoadPlan; var PrimitiveLoadPlan_default = PrimitiveLoadPlan; // packages/engine/Source/Scene/SupportedImageFormats.js var import_InlineWorkers563 = __toESM(require_InlineWorkers(), 1); function SupportedImageFormats(options) { options = options ?? Frozen_default.EMPTY_OBJECT; this.webp = options.webp ?? false; this.basis = options.basis ?? false; } var SupportedImageFormats_default = SupportedImageFormats; // packages/engine/Source/Scene/Model/Extensions/Gpm/GltfGpmLoader.js var import_InlineWorkers570 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/Model/Extensions/Gpm/AnchorPointDirect.js var import_InlineWorkers564 = __toESM(require_InlineWorkers(), 1); function AnchorPointDirect(options) { Check_default.typeOf.object("options.position", options.position); Check_default.typeOf.object("options.adjustmentParams", options.adjustmentParams); this._position = options.position; this._adjustmentParams = options.adjustmentParams; } Object.defineProperties(AnchorPointDirect.prototype, { /** * Anchor point geographic coordinates in meters as X/Easting, Y/Northing, Z/HAE * * @memberof AnchorPointDirect.prototype * @type {Cartesian3} * @readonly */ position: { get: function() { return this._position; } }, /** * The delta-x delta-y delta-z adjustment values in meters per anchor * point. * * @memberof AnchorPointDirect.prototype * @type {Cartesian3} * @readonly */ adjustmentParams: { get: function() { return this._adjustmentParams; } } }); var AnchorPointDirect_default = AnchorPointDirect; // packages/engine/Source/Scene/Model/Extensions/Gpm/AnchorPointIndirect.js var import_InlineWorkers565 = __toESM(require_InlineWorkers(), 1); function AnchorPointIndirect(options) { Check_default.typeOf.object("options.position", options.position); Check_default.typeOf.object("options.adjustmentParams", options.adjustmentParams); Check_default.typeOf.object("options.covarianceMatrix", options.covarianceMatrix); this._position = options.position; this._adjustmentParams = options.adjustmentParams; this._covarianceMatrix = options.covarianceMatrix; } Object.defineProperties(AnchorPointIndirect.prototype, { /** * Anchor point geographic coordinates in meters as X/Easting, Y/Northing, Z/HAE * * @memberof AnchorPointIndirect.prototype * @type {Cartesian3} * @readonly */ position: { get: function() { return this._position; } }, /** * The delta-x delta-y delta-z adjustment values in meters per anchor * point. * * @memberof AnchorPointIndirect.prototype * @type {Cartesian3} * @readonly */ adjustmentParams: { get: function() { return this._adjustmentParams; } }, /** * The 3x3 covariance matrix. * * @memberof AnchorPointIndirect.prototype * @type {Matrix3} * @readonly */ covarianceMatrix: { get: function() { return this._covarianceMatrix; } } }); var AnchorPointIndirect_default = AnchorPointIndirect; // packages/engine/Source/Scene/Model/Extensions/Gpm/CorrelationGroup.js var import_InlineWorkers566 = __toESM(require_InlineWorkers(), 1); function CorrelationGroup(options) { Check_default.typeOf.object("options.groupFlags", options.groupFlags); Check_default.typeOf.object("options.rotationThetas", options.rotationThetas); Check_default.typeOf.object("options.params", options.params); this._groupFlags = options.groupFlags; this._rotationThetas = options.rotationThetas; this._params = options.params; } Object.defineProperties(CorrelationGroup.prototype, { /** * Array of 3 booleans indicating if parameters delta-x delta-y delta-z * used in the correlation group * * @memberof CorrelationGroup.prototype * @type {boolean[]} * @readonly */ groupFlags: { get: function() { return this._groupFlags; } }, /** * Rotations in milliradians about X, Y, Z axes, respectively * * @memberof CorrelationGroup.prototype * @type {Cartesian3} * @readonly */ rotationThetas: { get: function() { return this._rotationThetas; } }, /** * Array of 3 sets of SPDCF parameters, for the U, V, W directions, respectively * * @memberof CorrelationGroup.prototype * @type {Spdcf[]} * @readonly */ params: { get: function() { return this._params; } } }); var CorrelationGroup_default = CorrelationGroup; // packages/engine/Source/Scene/Model/Extensions/Gpm/GltfGpmLocal.js var import_InlineWorkers568 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/Model/Extensions/Gpm/StorageType.js var import_InlineWorkers567 = __toESM(require_InlineWorkers(), 1); var StorageType = { /** * Store the full error covariance of the anchor points, to include the cross-covariance terms * * @type {string} * @constant */ Direct: "Direct", /** * A full covariance matrix is stored for each of the anchor points. However, in this case the * cross-covariance terms are not directly stored, but can be computed by a set of spatial * correlation function parameters which are stored in the metadata. * * @type {string} * @constant */ Indirect: "Indirect" }; var StorageType_default = Object.freeze(StorageType); // packages/engine/Source/Scene/Model/Extensions/Gpm/GltfGpmLocal.js function GltfGpmLocal(options) { Check_default.typeOf.string("options.storageType", options.storageType); this._storageType = options.storageType; this._anchorPointsIndirect = options.anchorPointsIndirect; this._anchorPointsDirect = options.anchorPointsDirect; this._intraTileCorrelationGroups = options.intraTileCorrelationGroups; this._covarianceDirect = options.covarianceDirect; if (this.storageType === StorageType_default.Indirect) { if (!defined_default(this.anchorPointsIndirect)) { throw new RuntimeError_default( "The anchorPointsIndirect are required for 'Indirect' storage" ); } if (!defined_default(this.intraTileCorrelationGroups)) { throw new RuntimeError_default( "The intraTileCorrelationGroups are required for 'Indirect' storage" ); } if (defined_default(this.anchorPointsDirect)) { throw new RuntimeError_default( "The anchorPointsDirect must be omitted for 'Indirect' storage" ); } if (defined_default(this.covarianceDirect)) { throw new RuntimeError_default( "The covarianceDirect must be omitted for 'Indirect' storage" ); } } else { if (!defined_default(this.anchorPointsDirect)) { throw new RuntimeError_default( "The anchorPointsDirect are required for 'Direct' storage" ); } if (!defined_default(this.covarianceDirect)) { throw new RuntimeError_default( "The covarianceDirect is required for 'Direct' storage" ); } if (defined_default(this.anchorPointsIndirect)) { throw new RuntimeError_default( "The anchorPointsIndirect must be omitted for 'Direct' storage" ); } if (defined_default(this.intraTileCorrelationGroups)) { throw new RuntimeError_default( "The intraTileCorrelationGroups must be omitted for 'Direct' storage" ); } } } Object.defineProperties(GltfGpmLocal.prototype, { /** * Specifies if covariance storage is indirect or direct. * * @memberof GltfGpmLocal.prototype * @type {StorageType} * @readonly */ storageType: { get: function() { return this._storageType; } }, /** * Array of stored indirect anchor points * * @memberof GltfGpmLocal.prototype * @type {AnchorPointIndirect[]|undefined} * @readonly */ anchorPointsIndirect: { get: function() { return this._anchorPointsIndirect; } }, /** * Array of stored direct anchor points * * @memberof GltfGpmLocal.prototype * @type {AnchorPointDirect[]|undefined} * @readonly */ anchorPointsDirect: { get: function() { return this._anchorPointsDirect; } }, /** * Metadata identifying parameters using same correlation modeling and * associated correlation parameters * * @memberof GltfGpmLocal.prototype * @type {CorrelationGroup[]|undefined} * @readonly */ intraTileCorrelationGroups: { get: function() { return this._intraTileCorrelationGroups; } }, /** * The full covariance of anchor point parameters * * @memberof GltfGpmLocal.prototype * @type {Matrix3|undefined} * @readonly */ covarianceDirect: { get: function() { return this._covarianceDirect; } } }); var GltfGpmLocal_default = GltfGpmLocal; // packages/engine/Source/Scene/Model/Extensions/Gpm/Spdcf.js var import_InlineWorkers569 = __toESM(require_InlineWorkers(), 1); function Spdcf(options) { Check_default.typeOf.number.greaterThan("options.A", options.A, 0); Check_default.typeOf.number.lessThanOrEquals("options.A", options.A, 1); Check_default.typeOf.number.greaterThanOrEquals("options.alpha", options.alpha, 0); Check_default.typeOf.number.lessThan("options.alpha", options.alpha, 1); Check_default.typeOf.number.greaterThanOrEquals("options.beta", options.beta, 0); Check_default.typeOf.number.lessThanOrEquals("options.beta", options.beta, 10); Check_default.typeOf.number.greaterThan("options.T", options.T, 0); this._A = options.A; this._alpha = options.alpha; this._beta = options.beta; this._T = options.T; } Object.defineProperties(Spdcf.prototype, { /** * In (0, 1] * * @memberof Spdcf.prototype * @type {number} * @readonly */ A: { get: function() { return this._A; } }, /** * In [0, 1) * * @memberof Spdcf.prototype * @type {number} * @readonly */ alpha: { get: function() { return this._alpha; } }, /** * In [0, 10] * * @memberof Spdcf.prototype * @type {number} * @readonly */ beta: { get: function() { return this._beta; } }, /** * In (0, +inf) * * @memberof Spdcf.prototype * @type {number} * @readonly */ T: { get: function() { return this._T; } } }); var Spdcf_default = Spdcf; // packages/engine/Source/Scene/Model/Extensions/Gpm/GltfGpmLoader.js function GltfGpmLoader() { } function createCovarianceMatrixFromUpperTriangle(array) { const covarianceMatrix = new Matrix3_default( array[0], array[1], array[3], array[1], array[2], array[4], array[3], array[4], array[5] ); return covarianceMatrix; } function createAnchorPointDirect(anchorPointDirectJson) { const position = Cartesian3_default.fromArray( anchorPointDirectJson.position, 0, new Cartesian3_default() ); const adjustmentParams = Cartesian3_default.fromArray( anchorPointDirectJson.adjustmentParams, 0, new Cartesian3_default() ); const anchorPointDirect = new AnchorPointDirect_default({ position, adjustmentParams }); return anchorPointDirect; } function createAnchorPointIndirect(anchorPointIndirectJson) { const position = Cartesian3_default.fromArray( anchorPointIndirectJson.position, 0, new Cartesian3_default() ); const adjustmentParams = Cartesian3_default.fromArray( anchorPointIndirectJson.adjustmentParams, 0, new Cartesian3_default() ); const covarianceMatrix = createCovarianceMatrixFromUpperTriangle( anchorPointIndirectJson.covarianceMatrix ); const anchorPointIndirect = new AnchorPointIndirect_default({ position, adjustmentParams, covarianceMatrix }); return anchorPointIndirect; } function createCorrelationGroup(correlationGroupJson) { const groupFlags = correlationGroupJson.groupFlags; const rotationThetas = Cartesian3_default.fromArray( correlationGroupJson.rotationThetas, 0, new Cartesian3_default() ); const params = []; for (const paramJson of correlationGroupJson.params) { const param = new Spdcf_default({ A: paramJson.A, alpha: paramJson.alpha, beta: paramJson.beta, T: paramJson.T }); params.push(param); } const correlationGroup = new CorrelationGroup_default({ groupFlags, rotationThetas, params }); return correlationGroup; } GltfGpmLoader.load = function(gltfGpmLocalJson) { Check_default.typeOf.object("gltfGpmLocalJson", gltfGpmLocalJson); const storageType = gltfGpmLocalJson.storageType; if (storageType === StorageType_default.Direct) { return GltfGpmLoader.loadDirect(gltfGpmLocalJson); } if (storageType === StorageType_default.Indirect) { return GltfGpmLoader.loadIndirect(gltfGpmLocalJson); } throw new RuntimeError_default( `Invalid storage type in NGA_gpm_local - expected 'Direct' or 'Indirect', but found ${storageType}` ); }; GltfGpmLoader.loadDirect = function(gltfGpmLocalJson) { Check_default.typeOf.object("gltfGpmLocalJson", gltfGpmLocalJson); Check_default.typeOf.object( "gltfGpmLocalJson.anchorPointsDirect", gltfGpmLocalJson.anchorPointsDirect ); Check_default.typeOf.object( "gltfGpmLocalJson.covarianceDirectUpperTriangle", gltfGpmLocalJson.covarianceDirectUpperTriangle ); const anchorPointsDirect = []; const anchorPointsDirectJson = gltfGpmLocalJson.anchorPointsDirect; for (const anchorPointDirectJson of anchorPointsDirectJson) { const anchorPointDirect = createAnchorPointDirect(anchorPointDirectJson); anchorPointsDirect.push(anchorPointDirect); } const covarianceDirect = createCovarianceMatrixFromUpperTriangle( gltfGpmLocalJson.covarianceDirectUpperTriangle ); const gltfGpmLocal = new GltfGpmLocal_default({ storageType: StorageType_default.Direct, anchorPointsDirect, covarianceDirect }); return gltfGpmLocal; }; GltfGpmLoader.loadIndirect = function(gltfGpmLocalJson) { Check_default.typeOf.object("gltfGpmLocalJson", gltfGpmLocalJson); Check_default.typeOf.object( "gltfGpmLocalJson.anchorPointsIndirect", gltfGpmLocalJson.anchorPointsIndirect ); Check_default.typeOf.object( "gltfGpmLocalJson.intraTileCorrelationGroups", gltfGpmLocalJson.intraTileCorrelationGroups ); const anchorPointsIndirect = []; const anchorPointsIndirectJson = gltfGpmLocalJson.anchorPointsIndirect; for (const anchorPointIndirectJson of anchorPointsIndirectJson) { const anchorPointIndirect = createAnchorPointIndirect( anchorPointIndirectJson ); anchorPointsIndirect.push(anchorPointIndirect); } const intraTileCorrelationGroupsJson = gltfGpmLocalJson.intraTileCorrelationGroups; const intraTileCorrelationGroups = []; for (const correlationGroupJson of intraTileCorrelationGroupsJson) { const correlationGroup = createCorrelationGroup(correlationGroupJson); intraTileCorrelationGroups.push(correlationGroup); } const gltfGpmLocal = new GltfGpmLocal_default({ storageType: StorageType_default.Indirect, anchorPointsIndirect, intraTileCorrelationGroups }); return gltfGpmLocal; }; var GltfGpmLoader_default = GltfGpmLoader; // packages/engine/Source/Scene/Model/Extensions/Gpm/GltfMeshPrimitiveGpmLoader.js var import_InlineWorkers574 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/Model/Extensions/Gpm/PpeTexture.js var import_InlineWorkers571 = __toESM(require_InlineWorkers(), 1); function PpeTexture(options) { Check_default.typeOf.object("options.traits", options.traits); Check_default.typeOf.number.greaterThanOrEquals("options.index", options.index, 0); this._traits = options.traits; this._noData = options.noData; this._offset = options.offset; this._scale = options.scale; this._index = options.index; this._texCoord = options.texCoord; } Object.defineProperties(PpeTexture.prototype, { /** * The data contained here applies to this node and corresponding * texture. * * @memberof PpeTexture.prototype * @type {PpeMetadata} * @readonly */ traits: { get: function() { return this._traits; } }, /** * A value to represent missing data - also known as a sentinel value - * wherever it appears. * * @memberof PpeTexture.prototype * @type {number|undefined} * @readonly */ noData: { get: function() { return this._noData; } }, /** * An offset to apply to property values. * * @memberof PpeTexture.prototype * @type {number|undefined} * @readonly */ offset: { get: function() { return this._offset; } }, /** * An scale to apply to property values. * * @memberof PpeTexture.prototype * @type {number|undefined} * @readonly */ scale: { get: function() { return this._scale; } }, /** * The index of the texture * * @memberof PpeTexture.prototype * @type {number} * @readonly */ index: { get: function() { return this._index; } }, /** * The set index of texture's TEXCOORD attribute used for texture coordinate mapping. * * @memberof PpeTexture.prototype * @type {number|undefined} * @readonly */ texCoord: { get: function() { return this._texCoord; } } }); var PpeTexture_default = PpeTexture; // packages/engine/Source/Scene/Model/Extensions/Gpm/PpeMetadata.js var import_InlineWorkers572 = __toESM(require_InlineWorkers(), 1); function PpeMetadata(options) { Check_default.typeOf.string("options.source", options.source); this._min = options.min; this._max = options.max; this._source = options.source; } Object.defineProperties(PpeMetadata.prototype, { /** * Minimum allowed value for the property. This is the minimum of all * values after the transforms based on the offset and scale properties * have been applied. * * @memberof PpeMetadata.prototype * @type {number|undefined} * @readonly */ min: { get: function() { return this._min; } }, /** * Maximum allowed value for the property. This is the maximum of all * values after the transforms based on the offset and scale properties * have been applied. * * @memberof PpeMetadata.prototype * @type {number|undefined} * @readonly */ max: { get: function() { return this._max; } }, /** * Possible error source contents * * @memberof PpeMetadata.prototype * @type {PpeSource} * @readonly */ source: { get: function() { return this._source; } } }); var PpeMetadata_default = PpeMetadata; // packages/engine/Source/Scene/Model/Extensions/Gpm/MeshPrimitiveGpmLocal.js var import_InlineWorkers573 = __toESM(require_InlineWorkers(), 1); function MeshPrimitiveGpmLocal(ppeTextures) { this._ppeTextures = ppeTextures; } Object.defineProperties(MeshPrimitiveGpmLocal.prototype, { /** * An array of ppe textures. * * @memberof MeshPrimitiveGpmLocal.prototype * @type {PpeTexture[]|undefined} * @readonly */ ppeTextures: { get: function() { return this._ppeTextures; } } }); var MeshPrimitiveGpmLocal_default = MeshPrimitiveGpmLocal; // packages/engine/Source/Scene/Model/Extensions/Gpm/GltfMeshPrimitiveGpmLoader.js function GltfMeshPrimitiveGpmLoader(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const gltf = options.gltf; const extension = options.extension; const gltfResource = options.gltfResource; const baseResource2 = options.baseResource; const supportedImageFormats = options.supportedImageFormats; const frameState = options.frameState; const cacheKey = options.cacheKey; const asynchronous = options.asynchronous ?? true; Check_default.typeOf.object("options.gltf", gltf); Check_default.typeOf.object("options.extension", extension); Check_default.typeOf.object("options.gltfResource", gltfResource); Check_default.typeOf.object("options.baseResource", baseResource2); Check_default.typeOf.object("options.supportedImageFormats", supportedImageFormats); Check_default.typeOf.object("options.frameState", frameState); this._gltfResource = gltfResource; this._baseResource = baseResource2; this._gltf = gltf; this._extension = extension; this._supportedImageFormats = supportedImageFormats; this._frameState = frameState; this._cacheKey = cacheKey; this._asynchronous = asynchronous; this._textureLoaders = []; this._textureIds = []; this._meshPrimitiveGpmLocal = void 0; this._structuralMetadata = void 0; this._state = ResourceLoaderState_default.UNLOADED; this._promise = void 0; } if (defined_default(Object.create)) { GltfMeshPrimitiveGpmLoader.prototype = Object.create( ResourceLoader_default.prototype ); GltfMeshPrimitiveGpmLoader.prototype.constructor = GltfMeshPrimitiveGpmLoader; } Object.defineProperties(GltfMeshPrimitiveGpmLoader.prototype, { /** * The cache key of the resource. * * @memberof GltfMeshPrimitiveGpmLoader.prototype * * @type {string} * @readonly * @private */ cacheKey: { get: function() { return this._cacheKey; } }, /** * The parsed GPM extension information from the mesh primitive * * @memberof GltfMeshPrimitiveGpmLoader.prototype * * @type {MeshPrimitiveGpmLocal} * @readonly * @private */ meshPrimitiveGpmLocal: { get: function() { return this._meshPrimitiveGpmLocal; } }, /** * Returns the result of converting the parsed 'MeshPrimitiveGpmLocal' * into a 'StructuralMetadata'. * * Some details about the translation are intentionally not specified here. * * @memberof GltfMeshPrimitiveGpmLoader.prototype * * @type {StructuralMetadata} * @readonly * @private */ structuralMetadata: { get: function() { return this._structuralMetadata; } } }); GltfMeshPrimitiveGpmLoader.prototype._loadResources = async function() { try { const texturesPromise = this._loadTextures(); await texturesPromise; if (this.isDestroyed()) { return; } this._gltf = void 0; this._state = ResourceLoaderState_default.LOADED; return this; } catch (error) { if (this.isDestroyed()) { return; } this.unload(); this._state = ResourceLoaderState_default.FAILED; const errorMessage = "Failed to load GPM data"; throw this.getError(errorMessage, error); } }; GltfMeshPrimitiveGpmLoader.prototype.load = function() { if (defined_default(this._promise)) { return this._promise; } this._state = ResourceLoaderState_default.LOADING; this._promise = this._loadResources(this); return this._promise; }; function gatherUsedTextureIds2(gpmExtension) { const textureIds = {}; const ppeTextures = gpmExtension.ppeTextures; if (defined_default(ppeTextures)) { for (let i = 0; i < ppeTextures.length; i++) { const ppeTexture = ppeTextures[i]; textureIds[ppeTexture.index] = ppeTexture; } } return textureIds; } GltfMeshPrimitiveGpmLoader.prototype._loadTextures = function() { let textureIds; if (defined_default(this._extension)) { textureIds = gatherUsedTextureIds2(this._extension); } const gltf = this._gltf; const gltfResource = this._gltfResource; const baseResource2 = this._baseResource; const supportedImageFormats = this._supportedImageFormats; const frameState = this._frameState; const asynchronous = this._asynchronous; const texturePromises = []; for (const textureId in textureIds) { if (textureIds.hasOwnProperty(textureId)) { const textureLoader = ResourceCache_default.getTextureLoader({ gltf, textureInfo: textureIds[textureId], gltfResource, baseResource: baseResource2, supportedImageFormats, frameState, asynchronous }); this._textureLoaders.push(textureLoader); this._textureIds.push(textureId); texturePromises.push(textureLoader.load()); } } return Promise.all(texturePromises); }; GltfMeshPrimitiveGpmLoader.ppeTexturesMetadataSchemaCache = /* @__PURE__ */ new Map(); GltfMeshPrimitiveGpmLoader._createPpeTextureClassJson = function(ppeTexture, index) { const traits = ppeTexture.traits; const ppePropertyName = traits.source; const offset = ppeTexture.offset ?? 0; const scale = (ppeTexture.scale ?? 1) * 255; const classJson = { name: `PPE texture class ${index}`, properties: { [ppePropertyName]: { name: "PPE", type: "SCALAR", componentType: "UINT8", normalized: true, offset, scale, min: traits.min, max: traits.max } } }; return classJson; }; GltfMeshPrimitiveGpmLoader._obtainPpeTexturesMetadataSchema = function(meshPrimitiveGpmLocal) { const ppeTexturePropertyIdentifiers = GltfMeshPrimitiveGpmLoader._collectPpeTexturePropertyIdentifiers( meshPrimitiveGpmLocal ); const key = ppeTexturePropertyIdentifiers.toString(); let ppeTexturesMetadataSchema = GltfMeshPrimitiveGpmLoader.ppeTexturesMetadataSchemaCache.get(key); if (defined_default(ppeTexturesMetadataSchema)) { return ppeTexturesMetadataSchema; } const schemaId = `PPE_TEXTURE_SCHEMA_${GltfMeshPrimitiveGpmLoader.ppeTexturesMetadataSchemaCache.size}`; const ppeTexturesMetadataSchemaJson = { id: schemaId, classes: {} }; const ppeTextures = meshPrimitiveGpmLocal.ppeTextures; for (let i = 0; i < ppeTextures.length; i++) { const ppeTexture = ppeTextures[i]; const classId = `ppeTexture_${i}`; const classJson = GltfMeshPrimitiveGpmLoader._createPpeTextureClassJson( ppeTexture, i ); ppeTexturesMetadataSchemaJson.classes[classId] = classJson; } ppeTexturesMetadataSchema = MetadataSchema_default.fromJson( ppeTexturesMetadataSchemaJson ); GltfMeshPrimitiveGpmLoader.ppeTexturesMetadataSchemaCache.set( key, ppeTexturesMetadataSchema ); return ppeTexturesMetadataSchema; }; GltfMeshPrimitiveGpmLoader._collectPpeTexturePropertyIdentifiers = function(meshPrimitiveGpmLocal) { const ppeTexturePropertyIdentifiers = []; const ppeTextures = meshPrimitiveGpmLocal.ppeTextures; for (let i = 0; i < ppeTextures.length; i++) { const ppeTexture = ppeTextures[i]; const classJson = GltfMeshPrimitiveGpmLoader._createPpeTextureClassJson( ppeTexture, i ); const ppeTexturePropertyIdentifier = JSON.stringify(classJson); ppeTexturePropertyIdentifiers.push(ppeTexturePropertyIdentifier); } return ppeTexturePropertyIdentifiers; }; GltfMeshPrimitiveGpmLoader._convertToStructuralMetadata = function(meshPrimitiveGpmLocal, textures) { const propertyTextures = []; const ppeTexturesMetadataSchema = GltfMeshPrimitiveGpmLoader._obtainPpeTexturesMetadataSchema( meshPrimitiveGpmLocal ); const ppeTextures = meshPrimitiveGpmLocal.ppeTextures; for (let i = 0; i < ppeTextures.length; i++) { const ppeTexture = ppeTextures[i]; const classId = `ppeTexture_${i}`; const traits = ppeTexture.traits; const ppePropertyName = traits.source; const metadataClass = ppeTexturesMetadataSchema.classes[classId]; const ppeTextureAsPropertyTexture = { class: classId, properties: { [ppePropertyName]: { index: ppeTexture.index, texCoord: ppeTexture.texCoord } } }; propertyTextures.push( new PropertyTexture_default({ id: i, name: ppeTexture.name, propertyTexture: ppeTextureAsPropertyTexture, class: metadataClass, textures }) ); } const structuralMetadata = new StructuralMetadata_default({ schema: ppeTexturesMetadataSchema, propertyTables: [], propertyTextures, propertyAttributes: [] }); return structuralMetadata; }; GltfMeshPrimitiveGpmLoader.prototype.process = function(frameState) { Check_default.typeOf.object("frameState", frameState); if (this._state === ResourceLoaderState_default.READY) { return true; } if (this._state !== ResourceLoaderState_default.LOADED) { return false; } const textureLoaders = this._textureLoaders; const textureLoadersLength = textureLoaders.length; let ready = true; for (let i = 0; i < textureLoadersLength; ++i) { const textureLoader = textureLoaders[i]; const textureReady = textureLoader.process(frameState); ready = ready && textureReady; } if (!ready) { return false; } const textures = {}; for (let i = 0; i < this._textureIds.length; ++i) { const textureId = this._textureIds[i]; const textureLoader = textureLoaders[i]; if (!textureLoader.isDestroyed()) { textures[textureId] = textureLoader.texture; } } const ppeTextures = []; const extension = this._extension; if (defined_default(extension.ppeTextures)) { const ppeTexturesJson = extension.ppeTextures; for (const ppeTextureJson of ppeTexturesJson) { const traitsJson = ppeTextureJson.traits; const traits = new PpeMetadata_default({ min: traitsJson.min, max: traitsJson.max, source: traitsJson.source }); const ppeTexture = new PpeTexture_default({ traits, noData: ppeTextureJson.noData, offset: ppeTextureJson.offset, scale: ppeTextureJson.scale, index: ppeTextureJson.index, texCoord: ppeTextureJson.texCoord }); ppeTextures.push(ppeTexture); } } const meshPrimitiveGpmLocal = new MeshPrimitiveGpmLocal_default(ppeTextures); this._meshPrimitiveGpmLocal = meshPrimitiveGpmLocal; const structuralMetadata = GltfMeshPrimitiveGpmLoader._convertToStructuralMetadata( meshPrimitiveGpmLocal, textures ); this._structuralMetadata = structuralMetadata; this._state = ResourceLoaderState_default.READY; return true; }; GltfMeshPrimitiveGpmLoader.prototype._unloadTextures = function() { const textureLoaders = this._textureLoaders; const textureLoadersLength = textureLoaders.length; for (let i = 0; i < textureLoadersLength; ++i) { ResourceCache_default.unload(textureLoaders[i]); } this._textureLoaders.length = 0; this._textureIds.length = 0; }; GltfMeshPrimitiveGpmLoader.prototype.unload = function() { this._unloadTextures(); this._gltf = void 0; this._extension = void 0; this._structuralMetadata = void 0; }; var GltfMeshPrimitiveGpmLoader_default = GltfMeshPrimitiveGpmLoader; // packages/engine/Source/Scene/getMeshPrimitives.js var import_InlineWorkers575 = __toESM(require_InlineWorkers(), 1); function getMeshPrimitives(mesh) { const meshExtensions = mesh.extensions ?? Frozen_default.EMPTY_OBJECT; const primitiveRestartExtension = meshExtensions.EXT_mesh_primitive_restart; const meshPrimitives = mesh.primitives; if (!defined_default(primitiveRestartExtension)) { return meshPrimitives; } const primitives = []; addAllToArray_default(primitives, meshPrimitives); for (const group of primitiveRestartExtension.primitiveGroups) { const firstPrimitiveIndex = group.primitives[0]; if (!defined_default(firstPrimitiveIndex) || !meshPrimitives[firstPrimitiveIndex]) { return meshPrimitives; } const primitive = { ...meshPrimitives[firstPrimitiveIndex], indices: group.indices }; switch (primitive.mode) { case WebGLConstants_default.TRIANGLE_FAN: case WebGLConstants_default.TRIANGLE_STRIP: case WebGLConstants_default.LINE_STRIP: case WebGLConstants_default.LINE_LOOP: break; default: return meshPrimitives; } for (const primitiveIndex of group.primitives) { const thisPrimitive = primitives[primitiveIndex]; if (!defined_default(thisPrimitive?.indices) || thisPrimitive.mode !== primitive.mode) { return meshPrimitives; } primitives[primitiveIndex] = void 0; } primitives[firstPrimitiveIndex] = primitive; } return primitives.filter(defined_default); } var getMeshPrimitives_default = getMeshPrimitives; // packages/engine/Source/Scene/GltfLoader.js var { Attribute: Attribute2, Indices: Indices2, FeatureIdAttribute: FeatureIdAttribute2, FeatureIdTexture: FeatureIdTexture2, FeatureIdImplicitRange: FeatureIdImplicitRange2, MorphTarget: MorphTarget2, Primitive: Primitive3, Instances: Instances2, Skin: Skin2, Node: Node4, AnimatedPropertyType: AnimatedPropertyType2, AnimationSampler: AnimationSampler2, AnimationTarget: AnimationTarget2, AnimationChannel: AnimationChannel2, Animation: Animation2, ArticulationStage: ArticulationStage2, Articulation: Articulation2, Asset: Asset2, Scene: Scene2, Components: Components2, MetallicRoughness: MetallicRoughness2, SpecularGlossiness: SpecularGlossiness2, Specular: Specular2, Anisotropy: Anisotropy2, Clearcoat: Clearcoat2, Material: Material3 } = ModelComponents_default; var GltfLoaderState = { /** * The initial state of the glTF loader before load() is called. * * @type {number} * @constant * * @private */ NOT_LOADED: 0, /** * The state of the loader while waiting for the glTF JSON loader promise * to resolve. * * @type {number} * @constant * * @private */ LOADING: 1, /** * The state of the loader once the glTF JSON is loaded but before * process() is called. * * @type {number} * @constant * * @private */ LOADED: 2, /** * The state of the loader while parsing the glTF and creating GPU resources * as needed. * * @type {number} * @constant * * @private */ PROCESSING: 3, /** * For some features like handling CESIUM_primitive_outlines, the geometry * must be modified after it is loaded. The post-processing state handles * any geometry modification (if needed). ** This state is not used for asynchronous texture loading. *
* * @type {number} * @constant * * @private */ POST_PROCESSING: 4, /** * Once the processing/post-processing states are finished, the loader * enters the processed state (sometimes from a promise chain). The next * call to process() will advance to the ready state. * * @type {number} * @constant * * @private */ PROCESSED: 5, /** * When the loader reaches the ready state, the loaders' promise will be * resolved. * * @type {number} * @constant * * @private */ READY: 6, /** * If an error occurs at any point, the loader switches to the failed state. * * @type {number} * @constant * * @private */ FAILED: 7, /** * If unload() is called, the loader switches to the unloaded state. * * @type {number} * @constant * * @private */ UNLOADED: 8 }; function GltfLoader(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const { gltfResource, typedArray, releaseGltfJson = false, asynchronous = true, incrementallyLoadTextures = true, upAxis = Axis_default.Y, forwardAxis = Axis_default.Z, loadAttributesAsTypedArray = false, loadAttributesFor2D = false, enablePick = false, loadIndicesForWireframe = false, loadPrimitiveOutline: loadPrimitiveOutline2 = true, loadForClassification = false, renameBatchIdSemantic = false } = options; Check_default.typeOf.object("options.gltfResource", gltfResource); const { baseResource: baseResource2 = gltfResource.clone() } = options; this._gltfJson = options.gltfJson; this._gltfResource = gltfResource; this._baseResource = baseResource2; this._typedArray = typedArray; this._releaseGltfJson = releaseGltfJson; this._asynchronous = asynchronous; this._incrementallyLoadTextures = incrementallyLoadTextures; this._upAxis = upAxis; this._forwardAxis = forwardAxis; this._loadAttributesAsTypedArray = loadAttributesAsTypedArray; this._loadAttributesFor2D = loadAttributesFor2D; this._enablePick = enablePick; this._loadIndicesForWireframe = loadIndicesForWireframe; this._loadPrimitiveOutline = loadPrimitiveOutline2; this._loadForClassification = loadForClassification; this._renameBatchIdSemantic = renameBatchIdSemantic; this._sortedPropertyTableIds = void 0; this._sortedFeatureTextureIds = void 0; this._gltfJsonLoader = void 0; this._state = GltfLoaderState.NOT_LOADED; this._textureState = GltfLoaderState.NOT_LOADED; this._promise = void 0; this._processError = void 0; this._textureErrors = []; this._primitiveLoadPlans = []; this._loaderPromises = []; this._textureLoaders = []; this._texturesPromises = []; this._textureCallbacks = []; this._bufferViewLoaders = []; this._geometryLoaders = []; this._geometryCallbacks = []; this._structuralMetadataLoader = void 0; this._meshPrimitiveGpmLoader = void 0; this._loadResourcesPromise = void 0; this._resourcesLoaded = false; this._texturesLoaded = false; this._supportedImageFormats = void 0; this._postProcessBuffers = []; this._components = void 0; } if (defined_default(Object.create)) { GltfLoader.prototype = Object.create(ResourceLoader_default.prototype); GltfLoader.prototype.constructor = GltfLoader; } Object.defineProperties(GltfLoader.prototype, { /** * The cache key of the resource. * * @memberof GltfLoader.prototype * * @type {string} * @readonly * @private */ cacheKey: { get: function() { return void 0; } }, /** * The loaded components. * * @memberof GltfLoader.prototype * * @type {ModelComponents.Components} * @readonly * @private */ components: { get: function() { return this._components; } }, /** * The loaded glTF json. * * @memberof GltfLoader.prototype * * @type {object} * @readonly * @private */ gltfJson: { get: function() { if (defined_default(this._gltfJsonLoader)) { return this._gltfJsonLoader.gltf; } return this._gltfJson; } }, /** * Returns true if textures are loaded separately from the other glTF resources. * * @memberof GltfLoader.prototype * * @type {boolean} * @readonly * @private */ incrementallyLoadTextures: { get: function() { return this._incrementallyLoadTextures; } }, /** * true if textures are loaded, useful when incrementallyLoadTextures is true * * @memberof GltfLoader.prototype * * @type {boolean} * @readonly * @private */ texturesLoaded: { get: function() { return this._texturesLoaded; } } }); async function loadGltfJson(loader) { loader._state = GltfLoaderState.LOADING; loader._textureState = GltfLoaderState.LOADING; try { const gltfJsonLoader = ResourceCache_default.getGltfJsonLoader({ gltfResource: loader._gltfResource, baseResource: loader._baseResource, typedArray: loader._typedArray, gltfJson: loader._gltfJson }); loader._gltfJsonLoader = gltfJsonLoader; await gltfJsonLoader.load(); if (loader.isDestroyed() || loader.isUnloaded() || gltfJsonLoader.isDestroyed()) { return; } loader._state = GltfLoaderState.LOADED; loader._textureState = GltfLoaderState.LOADED; return loader; } catch (error) { if (loader.isDestroyed()) { return; } loader._state = GltfLoaderState.FAILED; loader._textureState = GltfLoaderState.FAILED; handleError7(loader, error); } } async function loadResources6(loader, frameState) { if (!FeatureDetection_default.supportsWebP.initialized) { await FeatureDetection_default.supportsWebP.initialize(); } loader._supportedImageFormats = new SupportedImageFormats_default({ webp: FeatureDetection_default.supportsWebP(), basis: frameState.context.supportsBasis }); const promise = parse(loader, frameState); loader._state = GltfLoaderState.PROCESSING; loader._textureState = GltfLoaderState.PROCESSING; if (defined_default(loader._gltfJsonLoader) && loader._releaseGltfJson) { ResourceCache_default.unload(loader._gltfJsonLoader); loader._gltfJsonLoader = void 0; } return promise; } GltfLoader.prototype.load = async function() { if (defined_default(this._promise)) { return this._promise; } this._promise = loadGltfJson(this); return this._promise; }; function handleError7(gltfLoader, error) { gltfLoader.unload(); const errorMessage = "Failed to load glTF"; throw gltfLoader.getError(errorMessage, error); } function processLoaders(loader, frameState) { let ready = true; const geometryLoaders = loader._geometryLoaders; for (let i = 0; i < geometryLoaders.length; ++i) { const geometryReady = geometryLoaders[i].process(frameState); if (geometryReady && defined_default(loader._geometryCallbacks[i])) { loader._geometryCallbacks[i](); loader._geometryCallbacks[i] = void 0; } ready = ready && geometryReady; } const structuralMetadataLoader = loader._structuralMetadataLoader; if (defined_default(structuralMetadataLoader)) { const metadataReady = structuralMetadataLoader.process(frameState); if (metadataReady) { loader._components.structuralMetadata = structuralMetadataLoader.structuralMetadata; } ready = ready && metadataReady; } const meshPrimitiveGpmLoader = loader._meshPrimitiveGpmLoader; if (defined_default(meshPrimitiveGpmLoader)) { const metadataReady = meshPrimitiveGpmLoader.process(frameState); if (metadataReady) { if (defined_default(loader._components.structuralMetadata)) { oneTimeWarning_default( "structural-metadata-gpm", "The model defines both the 'EXT_structural_metadata' extension and the 'NGA_gpm_local' extension. The data from the 'EXT_structural_metadata' extension will be replaced with the data from the 'NGA_gpm_local' extension, and will no longer be available for styling and picking." ); } loader._components.structuralMetadata = meshPrimitiveGpmLoader.structuralMetadata; } ready = ready && metadataReady; } if (ready) { loader._state = GltfLoaderState.POST_PROCESSING; } } function postProcessGeometry(loader, context) { const loadPlans = loader._primitiveLoadPlans; for (let i = 0; i < loadPlans.length; i++) { const loadPlan = loadPlans[i]; loadPlan.postProcess(context); if (loadPlan.needsOutlines || loadPlan.needsGaussianSplats) { gatherPostProcessBuffers(loader, loadPlan); } } } function gatherPostProcessBuffers(loader, primitiveLoadPlan) { const buffers = loader._postProcessBuffers; const primitive = primitiveLoadPlan.primitive; const outlineCoordinates = primitive.outlineCoordinates; if (defined_default(outlineCoordinates)) { buffers.push(outlineCoordinates.buffer); } const attributes = primitive.attributes; for (let i = 0; i < attributes.length; i++) { const attribute = attributes[i]; if (defined_default(attribute.buffer)) { buffers.push(attribute.buffer); } } const indices = primitive.indices; if (defined_default(indices) && defined_default(indices.buffer)) { buffers.push(indices.buffer); } } GltfLoader.prototype._process = function(frameState) { if (this._state === GltfLoaderState.READY) { return true; } if (this._state === GltfLoaderState.PROCESSING) { processLoaders(this, frameState); } if (this._resourcesLoaded && this._state === GltfLoaderState.POST_PROCESSING) { postProcessGeometry(this, frameState.context); this._state = GltfLoaderState.PROCESSED; } if (this._resourcesLoaded && this._state === GltfLoaderState.PROCESSED) { unloadBufferViewLoaders(this); this._typedArray = void 0; this._state = GltfLoaderState.READY; return true; } return false; }; GltfLoader.prototype._processTextures = function(frameState) { if (this._textureState === GltfLoaderState.READY) { return true; } if (this._textureState !== GltfLoaderState.PROCESSING) { return false; } let ready = true; const textureLoaders = this._textureLoaders; for (let i = 0; i < textureLoaders.length; ++i) { const textureReady = textureLoaders[i].process(frameState); if (textureReady && defined_default(this._textureCallbacks[i])) { this._textureCallbacks[i](); this._textureCallbacks[i] = void 0; } ready = ready && textureReady; } if (!ready) { return false; } this._textureState = GltfLoaderState.READY; this._texturesLoaded = true; return true; }; GltfLoader.prototype.process = function(frameState) { Check_default.typeOf.object("frameState", frameState); if (this._state === GltfLoaderState.LOADED && !defined_default(this._loadResourcesPromise)) { this._loadResourcesPromise = loadResources6(this, frameState).then(() => { this._resourcesLoaded = true; }).catch((error) => { this._processError = error; }); } if (defined_default(this._processError)) { this._state = GltfLoaderState.FAILED; const error = this._processError; this._processError = void 0; handleError7(this, error); } const textureError = this._textureErrors.pop(); if (defined_default(textureError)) { const error = this.getError("Failed to load glTF texture", textureError); error.name = "TextureError"; throw error; } if (this._state === GltfLoaderState.FAILED) { return false; } let ready = false; try { ready = this._process(frameState); } catch (error) { this._state = GltfLoaderState.FAILED; handleError7(this, error); } let texturesReady = false; try { texturesReady = this._processTextures(frameState); } catch (error) { this._textureState = GltfLoaderState.FAILED; handleError7(this, error); } if (this._incrementallyLoadTextures) { return ready; } return ready && texturesReady; }; function getVertexBufferLoader(loader, accessorId, semantic, primitive, draco, spzExtension, loadBuffer, loadTypedArray, frameState) { const gltf = loader.gltfJson; const accessor = gltf.accessors[accessorId]; const bufferViewId = accessor.bufferView; const vertexBufferLoader = ResourceCache_default.getVertexBufferLoader({ gltf, gltfResource: loader._gltfResource, baseResource: loader._baseResource, frameState, bufferViewId, primitive, draco, spz: spzExtension, attributeSemantic: semantic, accessorId, asynchronous: loader._asynchronous, loadBuffer, loadTypedArray }); return vertexBufferLoader; } function getIndexBufferLoader(loader, accessorId, primitive, draco, loadBuffer, loadTypedArray, frameState) { const indexBufferLoader = ResourceCache_default.getIndexBufferLoader({ gltf: loader.gltfJson, accessorId, gltfResource: loader._gltfResource, baseResource: loader._baseResource, frameState, primitive, draco, asynchronous: loader._asynchronous, loadBuffer, loadTypedArray }); return indexBufferLoader; } function getBufferViewLoader(loader, bufferViewId) { const bufferViewLoader = ResourceCache_default.getBufferViewLoader({ gltf: loader.gltfJson, bufferViewId, gltfResource: loader._gltfResource, baseResource: loader._baseResource }); loader._bufferViewLoaders.push(bufferViewLoader); return bufferViewLoader; } function getPackedTypedArray(gltf, accessor, bufferViewTypedArray) { let byteOffset = accessor.byteOffset; const byteStride = getAccessorByteStride_default(gltf, accessor); const count = accessor.count; const componentCount = numberOfComponentsForType_default(accessor.type); const componentType = accessor.componentType; const componentByteLength = ComponentDatatype_default.getSizeInBytes(componentType); const defaultByteStride = componentByteLength * componentCount; const componentsLength = count * componentCount; if (byteStride === defaultByteStride) { bufferViewTypedArray = new Uint8Array(bufferViewTypedArray); return ComponentDatatype_default.createArrayBufferView( componentType, bufferViewTypedArray.buffer, bufferViewTypedArray.byteOffset + byteOffset, componentsLength ); } const accessorTypedArray = ComponentDatatype_default.createTypedArray( componentType, componentsLength ); const dataView = new DataView(bufferViewTypedArray.buffer); const components = new Array(componentCount); const componentReader = getComponentReader_default(accessor.componentType); byteOffset = bufferViewTypedArray.byteOffset + byteOffset; for (let i = 0; i < count; ++i) { componentReader( dataView, byteOffset, componentCount, componentByteLength, components ); for (let j = 0; j < componentCount; ++j) { accessorTypedArray[i * componentCount + j] = components[j]; } byteOffset += byteStride; } return accessorTypedArray; } function loadDefaultAccessorValues(accessor, values) { const accessorType = accessor.type; if (accessorType === AttributeType_default.SCALAR) { return values.fill(0); } const MathType = AttributeType_default.getMathType(accessorType); return values.fill(MathType.clone(MathType.ZERO)); } function loadAccessorValues(accessor, typedArray, values, useQuaternion) { const accessorType = accessor.type; const accessorCount = accessor.count; if (accessorType === AttributeType_default.SCALAR) { for (let i = 0; i < accessorCount; i++) { values[i] = typedArray[i]; } } else if (accessorType === AttributeType_default.VEC4 && useQuaternion) { for (let i = 0; i < accessorCount; i++) { values[i] = Quaternion_default.unpack(typedArray, i * 4); } } else { const MathType = AttributeType_default.getMathType(accessorType); const numberOfComponents = AttributeType_default.getNumberOfComponents(accessorType); for (let i = 0; i < accessorCount; i++) { values[i] = MathType.unpack(typedArray, i * numberOfComponents); } } return values; } async function loadAccessorBufferView(loader, bufferViewLoader, accessor, useQuaternion, values) { const { gltfJson } = loader; await bufferViewLoader.load(); if (loader.isDestroyed()) { return; } const typedArray = getPackedTypedArray( gltfJson, accessor, bufferViewLoader.typedArray ); useQuaternion = useQuaternion ?? false; loadAccessorValues(accessor, typedArray, values, useQuaternion); } function loadAccessor(loader, accessor, useQuaternion) { const values = new Array(accessor.count); const bufferViewId = accessor.bufferView; if (defined_default(bufferViewId)) { const bufferViewLoader = getBufferViewLoader(loader, bufferViewId); const promise = loadAccessorBufferView( loader, bufferViewLoader, accessor, useQuaternion, values ); loader._loaderPromises.push(promise); return values; } return loadDefaultAccessorValues(accessor, values); } function fromArray(MathType, values) { if (!defined_default(values)) { return void 0; } if (MathType === Number) { return values[0]; } return MathType.unpack(values); } function getDefault2(MathType) { if (MathType === Number) { return 0; } return new MathType(); } function getQuantizationDivisor(componentDatatype) { switch (componentDatatype) { case ComponentDatatype_default.BYTE: return 127; case ComponentDatatype_default.UNSIGNED_BYTE: return 255; case ComponentDatatype_default.SHORT: return 32767; case ComponentDatatype_default.UNSIGNED_SHORT: return 65535; default: return 1; } } var minimumBoundsByType = { VEC2: new Cartesian2_default(-1, -1), VEC3: new Cartesian3_default(-1, -1, -1), VEC4: new Cartesian4_default(-1, -1, -1, -1) }; function dequantizeMinMax(attribute, VectorType) { const divisor = getQuantizationDivisor(attribute.componentDatatype); const minimumBound = minimumBoundsByType[attribute.type]; let min3 = attribute.min; if (defined_default(min3)) { min3 = VectorType.divideByScalar(min3, divisor, min3); min3 = VectorType.maximumByComponent(min3, minimumBound, min3); } let max3 = attribute.max; if (defined_default(max3)) { max3 = VectorType.divideByScalar(max3, divisor, max3); max3 = VectorType.maximumByComponent(max3, minimumBound, max3); } attribute.min = min3; attribute.max = max3; } function setQuantizationFromWeb3dQuantizedAttributes(extension, attribute, MathType) { const decodeMatrix = extension.decodeMatrix; const decodedMin = fromArray(MathType, extension.decodedMin); const decodedMax = fromArray(MathType, extension.decodedMax); if (defined_default(decodedMin) && defined_default(decodedMax)) { attribute.min = decodedMin; attribute.max = decodedMax; } const quantization = new ModelComponents_default.Quantization(); quantization.componentDatatype = attribute.componentDatatype; quantization.type = attribute.type; if (decodeMatrix.length === 4) { quantization.quantizedVolumeOffset = decodeMatrix[2]; quantization.quantizedVolumeStepSize = decodeMatrix[0]; } else if (decodeMatrix.length === 9) { quantization.quantizedVolumeOffset = new Cartesian2_default( decodeMatrix[6], decodeMatrix[7] ); quantization.quantizedVolumeStepSize = new Cartesian2_default( decodeMatrix[0], decodeMatrix[4] ); } else if (decodeMatrix.length === 16) { quantization.quantizedVolumeOffset = new Cartesian3_default( decodeMatrix[12], decodeMatrix[13], decodeMatrix[14] ); quantization.quantizedVolumeStepSize = new Cartesian3_default( decodeMatrix[0], decodeMatrix[5], decodeMatrix[10] ); } else if (decodeMatrix.length === 25) { quantization.quantizedVolumeOffset = new Cartesian4_default( decodeMatrix[20], decodeMatrix[21], decodeMatrix[22], decodeMatrix[23] ); quantization.quantizedVolumeStepSize = new Cartesian4_default( decodeMatrix[0], decodeMatrix[6], decodeMatrix[12], decodeMatrix[18] ); } attribute.quantization = quantization; } function createAttribute(gltf, accessorId, name, semantic, setIndex) { const accessor = gltf.accessors[accessorId]; const MathType = AttributeType_default.getMathType(accessor.type); const normalized = accessor.normalized ?? false; const attribute = new Attribute2(); attribute.name = name; attribute.semantic = semantic; attribute.setIndex = setIndex; attribute.constant = getDefault2(MathType); attribute.componentDatatype = accessor.componentType; attribute.normalized = normalized; attribute.count = accessor.count; attribute.type = accessor.type; attribute.min = fromArray(MathType, accessor.min); attribute.max = fromArray(MathType, accessor.max); attribute.byteOffset = accessor.byteOffset; attribute.byteStride = getAccessorByteStride_default(gltf, accessor); if (hasExtension_default(accessor, "WEB3D_quantized_attributes")) { setQuantizationFromWeb3dQuantizedAttributes( accessor.extensions.WEB3D_quantized_attributes, attribute, MathType ); } const isQuantizable = attribute.semantic === VertexAttributeSemantic_default.POSITION || attribute.semantic === VertexAttributeSemantic_default.NORMAL || attribute.semantic === VertexAttributeSemantic_default.TANGENT || attribute.semantic === VertexAttributeSemantic_default.TEXCOORD || attribute.semantic === VertexAttributeSemantic_default.FEATURE_ID || attribute.semantic === VertexAttributeSemantic_default.SCALE || attribute.semantic === VertexAttributeSemantic_default.ROTATION; const hasKhrMeshQuantization = gltf.extensionsRequired?.includes( "KHR_mesh_quantization" ); if (hasKhrMeshQuantization && normalized && isQuantizable) { dequantizeMinMax(attribute, MathType); } return attribute; } function getSetIndex(gltfSemantic) { const setIndexRegex = /^\w+_(\d+)$/; const setIndexMatch = setIndexRegex.exec(gltfSemantic); if (setIndexMatch !== null) { return parseInt(setIndexMatch[1]); } return void 0; } var scratchSemanticInfo = { gltfSemantic: void 0, renamedSemantic: void 0, modelSemantic: void 0 }; function getSemanticInfo(loader, semanticType, gltfSemantic) { let renamedSemantic = gltfSemantic; if (loader._renameBatchIdSemantic && (gltfSemantic === "_BATCHID" || gltfSemantic === "BATCHID")) { renamedSemantic = "_FEATURE_ID_0"; } const modelSemantic = semanticType.fromGltfSemantic(renamedSemantic); const semanticInfo = scratchSemanticInfo; semanticInfo.gltfSemantic = gltfSemantic; semanticInfo.renamedSemantic = renamedSemantic; semanticInfo.modelSemantic = modelSemantic; return semanticInfo; } function isClassificationAttribute(attributeSemantic) { const isPositionAttribute = attributeSemantic === VertexAttributeSemantic_default.POSITION; const isFeatureIdAttribute = attributeSemantic === VertexAttributeSemantic_default.FEATURE_ID; const isTexcoordAttribute = attributeSemantic === VertexAttributeSemantic_default.TEXCOORD; return isPositionAttribute || isFeatureIdAttribute || isTexcoordAttribute; } function finalizeDracoAttribute(attribute, vertexBufferLoader, loadBuffer, loadTypedArray) { attribute.byteOffset = 0; attribute.byteStride = void 0; attribute.quantization = vertexBufferLoader.quantization; if (loadBuffer) { attribute.buffer = vertexBufferLoader.buffer; } if (loadTypedArray) { const componentDatatype = defined_default(vertexBufferLoader.quantization) ? vertexBufferLoader.quantization.componentDatatype : attribute.componentDatatype; attribute.typedArray = ComponentDatatype_default.createArrayBufferView( componentDatatype, vertexBufferLoader.typedArray.buffer ); } } function finalizeSpzAttribute(attribute, vertexBufferLoader, loadBuffer, loadTypedArray) { attribute.byteOffset = 0; attribute.byteStride = void 0; if (loadBuffer) { attribute.buffer = vertexBufferLoader.buffer; } if (loadTypedArray && defined_default(vertexBufferLoader.typedArray)) { attribute.typedArray = ComponentDatatype_default.createArrayBufferView( attribute.componentDatatype, vertexBufferLoader.typedArray.buffer ); } if (attribute.semantic === VertexAttributeSemantic_default.POSITION) { const findMinMaxXY = (flatArray2) => { let minX = Infinity; let maxX = -Infinity; let minY = Infinity; let maxY = -Infinity; let minZ = Infinity; let maxZ = -Infinity; for (let i = 0; i < flatArray2.length; i += 3) { const x = flatArray2[i]; const y = flatArray2[i + 1]; const z = flatArray2[i + 2]; minX = Math.min(minX, x); maxX = Math.max(maxX, x); minY = Math.min(minY, y); maxY = Math.max(maxY, y); minZ = Math.min(minZ, z); maxZ = Math.max(maxZ, z); } return [ new Cartesian3_default(minX, minY, minZ), new Cartesian3_default(maxX, maxY, maxZ) ]; }; const buffer2 = attribute.typedArray; [attribute.min, attribute.max] = findMinMaxXY(buffer2); } } function finalizeAttribute(gltf, accessor, attribute, vertexBufferLoader, loadBuffer, loadTypedArray) { if (loadBuffer) { attribute.buffer = vertexBufferLoader.buffer; } if (loadTypedArray) { const bufferViewTypedArray = vertexBufferLoader.typedArray; attribute.typedArray = getPackedTypedArray( gltf, accessor, bufferViewTypedArray ); if (!loadBuffer) { attribute.byteOffset = 0; attribute.byteStride = void 0; } } } function loadAttribute(loader, accessorId, semanticInfo, primitive, draco, spz, loadBuffer, loadTypedArray, frameState) { const gltf = loader.gltfJson; const accessor = gltf.accessors[accessorId]; const bufferViewId = accessor.bufferView; const gltfSemantic = semanticInfo.gltfSemantic; const renamedSemantic = semanticInfo.renamedSemantic; const modelSemantic = semanticInfo.modelSemantic; const setIndex = defined_default(modelSemantic) ? getSetIndex(renamedSemantic) : void 0; const name = gltfSemantic; const attribute = createAttribute( gltf, accessorId, name, modelSemantic, setIndex ); if (!defined_default(draco) && !defined_default(bufferViewId) && !defined_default(spz)) { return attribute; } const vertexBufferLoader = getVertexBufferLoader( loader, accessorId, gltfSemantic, primitive, draco, spz, loadBuffer, loadTypedArray, frameState ); const index = loader._geometryLoaders.length; loader._geometryLoaders.push(vertexBufferLoader); const promise = vertexBufferLoader.load(); loader._loaderPromises.push(promise); loader._geometryCallbacks[index] = () => { if (defined_default(draco) && defined_default(draco.attributes) && defined_default(draco.attributes[gltfSemantic])) { finalizeDracoAttribute( attribute, vertexBufferLoader, loadBuffer, loadTypedArray ); } else if (defined_default(spz)) { finalizeSpzAttribute( attribute, vertexBufferLoader, loadBuffer, loadTypedArray ); } else { finalizeAttribute( gltf, accessor, attribute, vertexBufferLoader, loadBuffer, loadTypedArray ); } }; return attribute; } function loadVertexAttribute(loader, accessorId, semanticInfo, primitive, draco, spz, hasInstances, needsPostProcessing, frameState) { const modelSemantic = semanticInfo.modelSemantic; const isPositionAttribute = modelSemantic === VertexAttributeSemantic_default.POSITION; const isFeatureIdAttribute = modelSemantic === VertexAttributeSemantic_default.FEATURE_ID; const loadTypedArrayFor2D = isPositionAttribute && !hasInstances && loader._loadAttributesFor2D && !frameState.scene3DOnly; const loadTypedArrayForPicking = isPositionAttribute && loader._enablePick && !frameState.context.webgl2; const loadTypedArrayForClassification = loader._loadForClassification && isFeatureIdAttribute; const outputTypedArrayOnly = loader._loadAttributesAsTypedArray; const outputBuffer = !outputTypedArrayOnly; const outputTypedArray = outputTypedArrayOnly || loadTypedArrayFor2D || loadTypedArrayForPicking || loadTypedArrayForClassification; const loadBuffer = needsPostProcessing ? false : outputBuffer; const loadTypedArray = needsPostProcessing ? true : outputTypedArray; const attribute = loadAttribute( loader, accessorId, semanticInfo, primitive, draco, spz, loadBuffer, loadTypedArray, frameState ); const attributePlan = new PrimitiveLoadPlan_default.AttributeLoadPlan(attribute); attributePlan.loadBuffer = outputBuffer; attributePlan.loadTypedArray = outputTypedArray; return attributePlan; } function loadInstancedAttribute(loader, accessorId, attributes, gltfSemantic, frameState) { const accessors = loader.gltfJson.accessors; const hasRotation = defined_default(attributes.ROTATION); const hasTranslationMinMax = defined_default(attributes.TRANSLATION) && defined_default(accessors[attributes.TRANSLATION].min) && defined_default(accessors[attributes.TRANSLATION].max); const semanticInfo = getSemanticInfo( loader, InstanceAttributeSemantic_default, gltfSemantic ); const modelSemantic = semanticInfo.modelSemantic; const isTransformAttribute = modelSemantic === InstanceAttributeSemantic_default.TRANSLATION || modelSemantic === InstanceAttributeSemantic_default.ROTATION || modelSemantic === InstanceAttributeSemantic_default.SCALE; const isTranslationAttribute = modelSemantic === InstanceAttributeSemantic_default.TRANSLATION; const loadAsTypedArrayOnly = loader._loadAttributesAsTypedArray || hasRotation && isTransformAttribute || !frameState.context.instancedArrays; const loadTypedArrayForPicking = loader._enablePick && !frameState.context.webgl2; const loadBuffer = !loadAsTypedArrayOnly; const loadFor2D = loader._loadAttributesFor2D && !frameState.scene3DOnly; const loadTranslationAsTypedArray = isTranslationAttribute && (!hasTranslationMinMax || loadFor2D || loadTypedArrayForPicking); const loadTypedArray = loadAsTypedArrayOnly || loadTranslationAsTypedArray; return loadAttribute( loader, accessorId, semanticInfo, void 0, void 0, void 0, loadBuffer, loadTypedArray, frameState ); } function loadIndices(loader, accessorId, primitive, draco, hasFeatureIds, needsPostProcessing, frameState) { const accessor = loader.gltfJson.accessors[accessorId]; const bufferViewId = accessor.bufferView; if (!defined_default(draco) && !defined_default(bufferViewId)) { return void 0; } const indices = new Indices2(); indices.count = accessor.count; const loadAttributesAsTypedArray = loader._loadAttributesAsTypedArray; const loadForCpuOperations = (loader._loadIndicesForWireframe || loader._enablePick) && !frameState.context.webgl2; const loadForClassification = loader._loadForClassification && hasFeatureIds; const outputTypedArrayOnly = loadAttributesAsTypedArray; const outputBuffer = !outputTypedArrayOnly; const outputTypedArray = loadAttributesAsTypedArray || loadForCpuOperations || loadForClassification; const loadBuffer = needsPostProcessing ? false : outputBuffer; const loadTypedArray = needsPostProcessing ? true : outputTypedArray; const indexBufferLoader = getIndexBufferLoader( loader, accessorId, primitive, draco, loadBuffer, loadTypedArray, frameState ); const index = loader._geometryLoaders.length; loader._geometryLoaders.push(indexBufferLoader); const promise = indexBufferLoader.load(); loader._loaderPromises.push(promise); loader._geometryCallbacks[index] = () => { indices.indexDatatype = indexBufferLoader.indexDatatype; indices.buffer = indexBufferLoader.buffer; indices.typedArray = indexBufferLoader.typedArray; }; const indicesPlan = new PrimitiveLoadPlan_default.IndicesLoadPlan(indices); indicesPlan.loadBuffer = outputBuffer; indicesPlan.loadTypedArray = outputTypedArray; return indicesPlan; } function loadTexture(loader, textureInfo, frameState, samplerOverride) { const gltf = loader.gltfJson; const imageId = GltfLoaderUtil_default.getImageIdFromTexture({ gltf, textureId: textureInfo.index, supportedImageFormats: loader._supportedImageFormats }); if (!defined_default(imageId)) { return void 0; } const textureLoader = ResourceCache_default.getTextureLoader({ gltf, textureInfo, gltfResource: loader._gltfResource, baseResource: loader._baseResource, supportedImageFormats: loader._supportedImageFormats, frameState, asynchronous: loader._asynchronous }); const textureReader = GltfLoaderUtil_default.createModelTextureReader({ textureInfo }); const index = loader._textureLoaders.length; loader._textureLoaders.push(textureLoader); const promise = textureLoader.load().catch((error) => { if (loader.isDestroyed()) { return; } if (!loader._incrementallyLoadTextures) { throw error; } loader._textureState = GltfLoaderState.FAILED; loader._textureErrors.push(error); }); loader._texturesPromises.push(promise); loader._textureCallbacks[index] = () => { textureReader.texture = textureLoader.texture; if (defined_default(samplerOverride)) { textureReader.texture.sampler = samplerOverride; } }; return textureReader; } function loadSpecularGlossiness(loader, specularGlossinessInfo, frameState) { const { diffuseTexture, specularGlossinessTexture, diffuseFactor, specularFactor, glossinessFactor } = specularGlossinessInfo; const specularGlossiness = new SpecularGlossiness2(); if (defined_default(diffuseTexture)) { specularGlossiness.diffuseTexture = loadTexture( loader, diffuseTexture, frameState ); } if (defined_default(specularGlossinessTexture)) { specularGlossiness.specularGlossinessTexture = loadTexture( loader, specularGlossinessTexture, frameState ); } specularGlossiness.diffuseFactor = fromArray(Cartesian4_default, diffuseFactor); specularGlossiness.specularFactor = fromArray(Cartesian3_default, specularFactor); specularGlossiness.glossinessFactor = glossinessFactor; return specularGlossiness; } function loadMetallicRoughness(loader, metallicRoughnessInfo, frameState) { const { baseColorTexture, metallicRoughnessTexture, baseColorFactor, metallicFactor, roughnessFactor } = metallicRoughnessInfo; const metallicRoughness = new MetallicRoughness2(); if (defined_default(baseColorTexture)) { metallicRoughness.baseColorTexture = loadTexture( loader, baseColorTexture, frameState ); } if (defined_default(metallicRoughnessTexture)) { metallicRoughness.metallicRoughnessTexture = loadTexture( loader, metallicRoughnessTexture, frameState ); } metallicRoughness.baseColorFactor = fromArray(Cartesian4_default, baseColorFactor); metallicRoughness.metallicFactor = metallicFactor; metallicRoughness.roughnessFactor = roughnessFactor; return metallicRoughness; } function loadSpecular(loader, specularInfo, frameState) { const { specularFactor, specularTexture, specularColorFactor, specularColorTexture } = specularInfo; const specular = new Specular2(); if (defined_default(specularTexture)) { specular.specularTexture = loadTexture(loader, specularTexture, frameState); } if (defined_default(specularColorTexture)) { specular.specularColorTexture = loadTexture( loader, specularColorTexture, frameState ); } specular.specularFactor = specularFactor; specular.specularColorFactor = fromArray(Cartesian3_default, specularColorFactor); return specular; } function loadAnisotropy(loader, anisotropyInfo, frameState) { const { anisotropyStrength = Anisotropy2.DEFAULT_ANISOTROPY_STRENGTH, anisotropyRotation = Anisotropy2.DEFAULT_ANISOTROPY_ROTATION, anisotropyTexture } = anisotropyInfo; const anisotropy = new Anisotropy2(); if (defined_default(anisotropyTexture)) { anisotropy.anisotropyTexture = loadTexture( loader, anisotropyTexture, frameState ); } anisotropy.anisotropyStrength = anisotropyStrength; anisotropy.anisotropyRotation = anisotropyRotation; return anisotropy; } function loadClearcoat(loader, clearcoatInfo, frameState) { const { clearcoatFactor = Clearcoat2.DEFAULT_CLEARCOAT_FACTOR, clearcoatTexture, clearcoatRoughnessFactor = Clearcoat2.DEFAULT_CLEARCOAT_ROUGHNESS_FACTOR, clearcoatRoughnessTexture, clearcoatNormalTexture } = clearcoatInfo; const clearcoat = new Clearcoat2(); if (defined_default(clearcoatTexture)) { clearcoat.clearcoatTexture = loadTexture( loader, clearcoatTexture, frameState ); } if (defined_default(clearcoatRoughnessTexture)) { clearcoat.clearcoatRoughnessTexture = loadTexture( loader, clearcoatRoughnessTexture, frameState ); } if (defined_default(clearcoatNormalTexture)) { clearcoat.clearcoatNormalTexture = loadTexture( loader, clearcoatNormalTexture, frameState ); } clearcoat.clearcoatFactor = clearcoatFactor; clearcoat.clearcoatRoughnessFactor = clearcoatRoughnessFactor; return clearcoat; } function loadMaterial(loader, gltfMaterial, frameState) { const material = new Material3(); const extensions = gltfMaterial.extensions ?? Frozen_default.EMPTY_OBJECT; const pbrSpecularGlossiness = extensions.KHR_materials_pbrSpecularGlossiness; const pbrSpecular = extensions.KHR_materials_specular; const pbrAnisotropy = extensions.KHR_materials_anisotropy; const pbrClearcoat = extensions.KHR_materials_clearcoat; const pbrMetallicRoughness = gltfMaterial.pbrMetallicRoughness; material.unlit = defined_default(extensions.KHR_materials_unlit); if (defined_default(pbrSpecularGlossiness)) { material.specularGlossiness = loadSpecularGlossiness( loader, pbrSpecularGlossiness, frameState ); } else { if (defined_default(pbrMetallicRoughness)) { material.metallicRoughness = loadMetallicRoughness( loader, pbrMetallicRoughness, frameState ); } if (defined_default(pbrSpecular) && !material.unlit) { material.specular = loadSpecular(loader, pbrSpecular, frameState); } if (defined_default(pbrAnisotropy) && !material.unlit) { material.anisotropy = loadAnisotropy(loader, pbrAnisotropy, frameState); } if (defined_default(pbrClearcoat) && !material.unlit) { material.clearcoat = loadClearcoat(loader, pbrClearcoat, frameState); } } if (defined_default(gltfMaterial.emissiveTexture)) { material.emissiveTexture = loadTexture( loader, gltfMaterial.emissiveTexture, frameState ); } if (defined_default(gltfMaterial.normalTexture) && !loader._loadForClassification) { material.normalTexture = loadTexture( loader, gltfMaterial.normalTexture, frameState ); } if (defined_default(gltfMaterial.occlusionTexture)) { material.occlusionTexture = loadTexture( loader, gltfMaterial.occlusionTexture, frameState ); } material.emissiveFactor = fromArray(Cartesian3_default, gltfMaterial.emissiveFactor); material.alphaMode = gltfMaterial.alphaMode; material.alphaCutoff = gltfMaterial.alphaCutoff; material.doubleSided = gltfMaterial.doubleSided; return material; } function loadFeatureIdAttribute(featureIds, positionalLabel) { const featureIdAttribute = new FeatureIdAttribute2(); featureIdAttribute.featureCount = featureIds.featureCount; featureIdAttribute.nullFeatureId = featureIds.nullFeatureId; featureIdAttribute.propertyTableId = featureIds.propertyTable; featureIdAttribute.setIndex = featureIds.attribute; featureIdAttribute.label = featureIds.label; featureIdAttribute.positionalLabel = positionalLabel; return featureIdAttribute; } function loadFeatureIdAttributeLegacy(gltfFeatureIdAttribute, featureTableId, featureCount, positionalLabel) { const featureIdAttribute = new FeatureIdAttribute2(); const featureIds = gltfFeatureIdAttribute.featureIds; featureIdAttribute.featureCount = featureCount; featureIdAttribute.propertyTableId = featureTableId; featureIdAttribute.setIndex = getSetIndex(featureIds.attribute); featureIdAttribute.positionalLabel = positionalLabel; return featureIdAttribute; } function loadDefaultFeatureIds(featureIds, positionalLabel) { const featureIdRange = new FeatureIdImplicitRange2(); featureIdRange.propertyTableId = featureIds.propertyTable; featureIdRange.featureCount = featureIds.featureCount; featureIdRange.nullFeatureId = featureIds.nullFeatureId; featureIdRange.label = featureIds.label; featureIdRange.positionalLabel = positionalLabel; featureIdRange.offset = 0; featureIdRange.repeat = 1; return featureIdRange; } function loadFeatureIdImplicitRangeLegacy(gltfFeatureIdAttribute, featureTableId, featureCount, positionalLabel) { const featureIdRange = new FeatureIdImplicitRange2(); const featureIds = gltfFeatureIdAttribute.featureIds; featureIdRange.propertyTableId = featureTableId; featureIdRange.featureCount = featureCount; featureIdRange.offset = featureIds.constant ?? 0; const divisor = featureIds.divisor ?? 0; featureIdRange.repeat = divisor === 0 ? void 0 : divisor; featureIdRange.positionalLabel = positionalLabel; return featureIdRange; } function loadFeatureIdTexture(loader, gltfFeatureIdTexture, frameState, positionalLabel) { const featureIdTexture = new FeatureIdTexture2(); featureIdTexture.featureCount = gltfFeatureIdTexture.featureCount; featureIdTexture.nullFeatureId = gltfFeatureIdTexture.nullFeatureId; featureIdTexture.propertyTableId = gltfFeatureIdTexture.propertyTable; featureIdTexture.label = gltfFeatureIdTexture.label; featureIdTexture.positionalLabel = positionalLabel; const textureInfo = gltfFeatureIdTexture.texture; featureIdTexture.textureReader = loadTexture( loader, textureInfo, frameState, Sampler_default.NEAREST // Feature ID textures require nearest sampling ); const channels = defined_default(textureInfo.channels) ? textureInfo.channels : [0]; const channelString = channels.map(function(channelIndex) { return "rgba".charAt(channelIndex); }).join(""); featureIdTexture.textureReader.channels = channelString; return featureIdTexture; } function loadFeatureIdTextureLegacy(loader, gltfFeatureIdTexture, featureTableId, frameState, featureCount, positionalLabel) { const featureIdTexture = new FeatureIdTexture2(); const featureIds = gltfFeatureIdTexture.featureIds; const textureInfo = featureIds.texture; featureIdTexture.featureCount = featureCount; featureIdTexture.propertyTableId = featureTableId; featureIdTexture.textureReader = loadTexture( loader, textureInfo, frameState, Sampler_default.NEAREST // Feature ID textures require nearest sampling ); featureIdTexture.textureReader.channels = featureIds.channels; featureIdTexture.positionalLabel = positionalLabel; return featureIdTexture; } function loadMorphTarget(loader, target, needsPostProcessing, primitiveLoadPlan, frameState) { const morphTarget = new MorphTarget2(); const primitive = void 0; const draco = void 0; const spz = void 0; const hasInstances = false; for (const semantic in target) { if (!target.hasOwnProperty(semantic)) { continue; } const accessorId = target[semantic]; const semanticInfo = getSemanticInfo( loader, VertexAttributeSemantic_default, semantic ); const attributePlan = loadVertexAttribute( loader, accessorId, semanticInfo, primitive, draco, spz, hasInstances, needsPostProcessing, frameState ); morphTarget.attributes.push(attributePlan.attribute); primitiveLoadPlan.attributePlans.push(attributePlan); } return morphTarget; } function fetchSpzExtensionFrom(extensions) { const gaussianSplatting = extensions?.KHR_gaussian_splatting; const gsExtensions = gaussianSplatting?.extensions; const spz = gsExtensions?.KHR_gaussian_splatting_compression_spz_2; if (defined_default(spz)) { return spz; } const legacySpz = extensions?.KHR_spz_gaussian_splats_compression; if (defined_default(legacySpz)) { return legacySpz; } return void 0; } function loadPrimitive(loader, gltfPrimitive, hasInstances, frameState) { const primitive = new Primitive3(); const primitivePlan = new PrimitiveLoadPlan_default(primitive); loader._primitiveLoadPlans.push(primitivePlan); const materialId = gltfPrimitive.material; if (defined_default(materialId)) { primitive.material = loadMaterial( loader, loader.gltfJson.materials[materialId], frameState ); } const extensions = gltfPrimitive.extensions ?? Frozen_default.EMPTY_OBJECT; let needsPostProcessing = false; const outlineExtension = extensions.CESIUM_primitive_outline; if (loader._loadPrimitiveOutline && defined_default(outlineExtension)) { needsPostProcessing = true; primitivePlan.needsOutlines = true; primitivePlan.outlineIndices = loadPrimitiveOutline( loader, outlineExtension, primitivePlan ); } const spzExtension = fetchSpzExtensionFrom(extensions); if (defined_default(spzExtension)) { needsPostProcessing = true; primitivePlan.needsGaussianSplats = true; } const loadForClassification = loader._loadForClassification; const draco = extensions.KHR_draco_mesh_compression; let hasFeatureIds = false; const attributes = gltfPrimitive.attributes; if (defined_default(attributes)) { for (const semantic in attributes) { if (!attributes.hasOwnProperty(semantic)) { continue; } const accessorId = attributes[semantic]; const semanticInfo = getSemanticInfo( loader, VertexAttributeSemantic_default, semantic ); const modelSemantic = semanticInfo.modelSemantic; if (loadForClassification && !isClassificationAttribute(modelSemantic)) { continue; } if (modelSemantic === VertexAttributeSemantic_default.FEATURE_ID) { hasFeatureIds = true; } const attributePlan = loadVertexAttribute( loader, accessorId, semanticInfo, gltfPrimitive, draco, spzExtension, hasInstances, needsPostProcessing, frameState ); primitivePlan.attributePlans.push(attributePlan); primitive.attributes.push(attributePlan.attribute); } } const targets = gltfPrimitive.targets; if (defined_default(targets) && !loadForClassification) { for (let i = 0; i < targets.length; ++i) { primitive.morphTargets.push( loadMorphTarget( loader, targets[i], needsPostProcessing, primitivePlan, frameState ) ); } } const indices = gltfPrimitive.indices; if (defined_default(indices)) { const indicesPlan = loadIndices( loader, indices, gltfPrimitive, draco, hasFeatureIds, needsPostProcessing, frameState ); if (defined_default(indicesPlan)) { primitivePlan.indicesPlan = indicesPlan; primitive.indices = indicesPlan.indices; } } const structuralMetadata = extensions.EXT_structural_metadata; const meshFeatures = extensions.EXT_mesh_features; const featureMetadataLegacy = extensions.EXT_feature_metadata; const hasFeatureMetadataLegacy = defined_default(featureMetadataLegacy); if (defined_default(meshFeatures)) { loadPrimitiveFeatures(loader, primitive, meshFeatures, frameState); } else if (hasFeatureMetadataLegacy) { loadPrimitiveFeaturesLegacy( loader, primitive, featureMetadataLegacy, frameState ); } if (defined_default(structuralMetadata)) { loadPrimitiveMetadata(primitive, structuralMetadata); } else if (hasFeatureMetadataLegacy) { loadPrimitiveMetadataLegacy(loader, primitive, featureMetadataLegacy); } const primitiveType = gltfPrimitive.mode; if (loadForClassification && primitiveType !== PrimitiveType_default.TRIANGLES) { throw new RuntimeError_default( "Only triangle meshes can be used for classification." ); } primitive.primitiveType = primitiveType; return primitive; } function loadPrimitiveOutline(loader, outlineExtension) { const accessorId = outlineExtension.indices; const accessor = loader.gltfJson.accessors[accessorId]; const useQuaternion = false; return loadAccessor(loader, accessor, useQuaternion); } function loadPrimitiveFeatures(loader, primitive, meshFeaturesExtension, frameState) { let featureIdsArray; if (defined_default(meshFeaturesExtension) && defined_default(meshFeaturesExtension.featureIds)) { featureIdsArray = meshFeaturesExtension.featureIds; } else { featureIdsArray = []; } for (let i = 0; i < featureIdsArray.length; i++) { const featureIds = featureIdsArray[i]; const label = `featureId_${i}`; let featureIdComponent; if (defined_default(featureIds.texture)) { featureIdComponent = loadFeatureIdTexture( loader, featureIds, frameState, label ); } else if (defined_default(featureIds.attribute)) { featureIdComponent = loadFeatureIdAttribute(featureIds, label); } else { featureIdComponent = loadDefaultFeatureIds(featureIds, label); } primitive.featureIds.push(featureIdComponent); } } function loadPrimitiveFeaturesLegacy(loader, primitive, metadataExtension, frameState) { const { featureTables } = loader.gltfJson.extensions.EXT_feature_metadata; let nextFeatureIdIndex = 0; const featureIdAttributes = metadataExtension.featureIdAttributes; if (defined_default(featureIdAttributes)) { for (let i = 0; i < featureIdAttributes.length; ++i) { const featureIdAttribute = featureIdAttributes[i]; const featureTableId = featureIdAttribute.featureTable; const propertyTableId = loader._sortedPropertyTableIds.indexOf(featureTableId); const featureCount = featureTables[featureTableId].count; const label = `featureId_${nextFeatureIdIndex}`; nextFeatureIdIndex++; let featureIdComponent; if (defined_default(featureIdAttribute.featureIds.attribute)) { featureIdComponent = loadFeatureIdAttributeLegacy( featureIdAttribute, propertyTableId, featureCount, label ); } else { featureIdComponent = loadFeatureIdImplicitRangeLegacy( featureIdAttribute, propertyTableId, featureCount, label ); } primitive.featureIds.push(featureIdComponent); } } const featureIdTextures = metadataExtension.featureIdTextures; if (defined_default(featureIdTextures)) { for (let i = 0; i < featureIdTextures.length; ++i) { const featureIdTexture = featureIdTextures[i]; const featureTableId = featureIdTexture.featureTable; const propertyTableId = loader._sortedPropertyTableIds.indexOf(featureTableId); const featureCount = featureTables[featureTableId].count; const featureIdLabel = `featureId_${nextFeatureIdIndex}`; nextFeatureIdIndex++; const featureIdComponent = loadFeatureIdTextureLegacy( loader, featureIdTexture, propertyTableId, frameState, featureCount, featureIdLabel ); primitive.featureIds.push(featureIdComponent); } } } function loadPrimitiveMetadata(primitive, structuralMetadataExtension) { if (!defined_default(structuralMetadataExtension)) { return; } const { propertyTextures, propertyAttributes } = structuralMetadataExtension; if (defined_default(propertyTextures)) { primitive.propertyTextureIds = propertyTextures; } if (defined_default(propertyAttributes)) { primitive.propertyAttributeIds = propertyAttributes; } } function loadPrimitiveMetadataLegacy(loader, primitive, metadataExtension) { if (defined_default(metadataExtension.featureTextures)) { primitive.propertyTextureIds = metadataExtension.featureTextures.map( function(id) { return loader._sortedFeatureTextureIds.indexOf(id); } ); } } function loadInstances(loader, nodeExtensions, frameState) { const instancingExtension = nodeExtensions.EXT_mesh_gpu_instancing; const instances = new Instances2(); const attributes = instancingExtension.attributes; if (defined_default(attributes)) { for (const semantic in attributes) { if (!attributes.hasOwnProperty(semantic)) { continue; } const accessorId = attributes[semantic]; instances.attributes.push( loadInstancedAttribute( loader, accessorId, attributes, semantic, frameState ) ); } } const instancingExtExtensions = instancingExtension.extensions ?? Frozen_default.EMPTY_OBJECT; const instanceFeatures = nodeExtensions.EXT_instance_features; const featureMetadataLegacy = instancingExtExtensions.EXT_feature_metadata; if (defined_default(instanceFeatures)) { loadInstanceFeatures(instances, instanceFeatures); } else if (defined_default(featureMetadataLegacy)) { loadInstanceFeaturesLegacy( loader.gltfJson, instances, featureMetadataLegacy, loader._sortedPropertyTableIds ); } return instances; } function loadInstanceFeatures(instances, instanceFeaturesExtension) { const featureIdsArray = instanceFeaturesExtension.featureIds; for (let i = 0; i < featureIdsArray.length; i++) { const featureIds = featureIdsArray[i]; const label = `instanceFeatureId_${i}`; let featureIdComponent; if (defined_default(featureIds.attribute)) { featureIdComponent = loadFeatureIdAttribute(featureIds, label); } else { featureIdComponent = loadDefaultFeatureIds(featureIds, label); } instances.featureIds.push(featureIdComponent); } } function loadInstanceFeaturesLegacy(gltf, instances, metadataExtension, sortedPropertyTableIds) { const featureTables = gltf.extensions.EXT_feature_metadata.featureTables; const featureIdAttributes = metadataExtension.featureIdAttributes; if (defined_default(featureIdAttributes)) { for (let i = 0; i < featureIdAttributes.length; ++i) { const featureIdAttribute = featureIdAttributes[i]; const featureTableId = featureIdAttribute.featureTable; const propertyTableId = sortedPropertyTableIds.indexOf(featureTableId); const featureCount = featureTables[featureTableId].count; const label = `instanceFeatureId_${i}`; let featureIdComponent; if (defined_default(featureIdAttribute.featureIds.attribute)) { featureIdComponent = loadFeatureIdAttributeLegacy( featureIdAttribute, propertyTableId, featureCount, label ); } else { featureIdComponent = loadFeatureIdImplicitRangeLegacy( featureIdAttribute, propertyTableId, featureCount, label ); } instances.featureIds.push(featureIdComponent); } } } function loadNode(loader, gltfNode, frameState) { const node = new Node4(); node.name = gltfNode.name; node.matrix = fromArray(Matrix4_default, gltfNode.matrix); node.translation = fromArray(Cartesian3_default, gltfNode.translation); node.rotation = fromArray(Quaternion_default, gltfNode.rotation); node.scale = fromArray(Cartesian3_default, gltfNode.scale); const nodeExtensions = gltfNode.extensions ?? Frozen_default.EMPTY_OBJECT; const instancingExtension = nodeExtensions.EXT_mesh_gpu_instancing; const articulationsExtension = nodeExtensions.AGI_articulations; if (defined_default(instancingExtension)) { if (loader._loadForClassification) { throw new RuntimeError_default( "Models with the EXT_mesh_gpu_instancing extension cannot be used for classification." ); } node.instances = loadInstances(loader, nodeExtensions, frameState); } if (defined_default(articulationsExtension)) { node.articulationName = articulationsExtension.articulationName; } const meshId = gltfNode.mesh; if (defined_default(meshId)) { const mesh = loader.gltfJson.meshes[meshId]; const primitives = getMeshPrimitives_default(mesh); for (let i = 0; i < primitives.length; ++i) { node.primitives.push( loadPrimitive( loader, primitives[i], defined_default(node.instances), frameState ) ); } const morphWeights = gltfNode.weights ?? mesh.weights; const targets = node.primitives[0].morphTargets; node.morphWeights = defined_default(morphWeights) ? morphWeights.slice() : new Array(targets.length).fill(0); } return node; } function loadNodes(loader, frameState) { const nodeJsons = loader.gltfJson.nodes; if (!defined_default(nodeJsons)) { return []; } const loadedNodes = nodeJsons.map(function(nodeJson, i) { const node = loadNode(loader, nodeJson, frameState); node.index = i; return node; }); for (let i = 0; i < loadedNodes.length; ++i) { const childrenNodeIds = nodeJsons[i].children; if (defined_default(childrenNodeIds)) { for (let j = 0; j < childrenNodeIds.length; ++j) { loadedNodes[i].children.push(loadedNodes[childrenNodeIds[j]]); } } } return loadedNodes; } function loadSkin(loader, gltfSkin, nodes) { const skin = new Skin2(); const jointIds = gltfSkin.joints; skin.joints = jointIds.map((jointId) => nodes[jointId]); const inverseBindMatricesAccessorId = gltfSkin.inverseBindMatrices; if (defined_default(inverseBindMatricesAccessorId)) { const accessor = loader.gltfJson.accessors[inverseBindMatricesAccessorId]; skin.inverseBindMatrices = loadAccessor(loader, accessor); } else { skin.inverseBindMatrices = new Array(jointIds.length).fill( Matrix4_default.IDENTITY ); } return skin; } function loadSkins(loader, nodes) { const skinJsons = loader.gltfJson.skins; if (loader._loadForClassification || !defined_default(skinJsons)) { return []; } const loadedSkins = skinJsons.map(function(skinJson, i) { const skin = loadSkin(loader, skinJson, nodes); skin.index = i; return skin; }); const nodeJsons = loader.gltfJson.nodes; for (let i = 0; i < nodes.length; ++i) { const skinId = nodeJsons[i].skin; if (defined_default(skinId)) { nodes[i].skin = loadedSkins[skinId]; } } return loadedSkins; } async function loadStructuralMetadata(loader, extension, extensionLegacy, frameState) { const structuralMetadataLoader = new GltfStructuralMetadataLoader_default({ gltf: loader.gltfJson, extension, extensionLegacy, gltfResource: loader._gltfResource, baseResource: loader._baseResource, supportedImageFormats: loader._supportedImageFormats, frameState, asynchronous: loader._asynchronous }); loader._structuralMetadataLoader = structuralMetadataLoader; return structuralMetadataLoader.load(); } async function loadMeshPrimitiveGpm(loader, gltf, extension, frameState) { const meshPrimitiveGpmLoader = new GltfMeshPrimitiveGpmLoader_default({ gltf, extension, gltfResource: loader._gltfResource, baseResource: loader._baseResource, supportedImageFormats: loader._supportedImageFormats, frameState, asynchronous: loader._asynchronous }); loader._meshPrimitiveGpmLoader = meshPrimitiveGpmLoader; return meshPrimitiveGpmLoader.load(); } function loadAnimationSampler(loader, gltfSampler) { const animationSampler = new AnimationSampler2(); const accessors = loader.gltfJson.accessors; const inputAccessor = accessors[gltfSampler.input]; animationSampler.input = loadAccessor(loader, inputAccessor); const gltfInterpolation = gltfSampler.interpolation; animationSampler.interpolation = InterpolationType_default[gltfInterpolation] ?? InterpolationType_default.LINEAR; const outputAccessor = accessors[gltfSampler.output]; animationSampler.output = loadAccessor(loader, outputAccessor, true); return animationSampler; } function loadAnimationTarget(gltfTarget, nodes) { const animationTarget = new AnimationTarget2(); const nodeIndex = gltfTarget.node; if (!defined_default(nodeIndex)) { return void 0; } animationTarget.node = nodes[nodeIndex]; const path = gltfTarget.path.toUpperCase(); animationTarget.path = AnimatedPropertyType2[path]; return animationTarget; } function loadAnimationChannel(gltfChannel, samplers, nodes) { const animationChannel = new AnimationChannel2(); const samplerIndex = gltfChannel.sampler; animationChannel.sampler = samplers[samplerIndex]; animationChannel.target = loadAnimationTarget(gltfChannel.target, nodes); return animationChannel; } function loadAnimation(loader, animationJson, nodes) { const animation = new Animation2(); animation.name = animationJson.name; const samplers = animationJson.samplers.map(function(samplerJson, i) { const sampler = loadAnimationSampler(loader, samplerJson); sampler.index = i; return sampler; }); const channels = animationJson.channels.map(function(channelJson) { return loadAnimationChannel(channelJson, samplers, nodes); }); animation.samplers = samplers; animation.channels = channels; return animation; } function loadAnimations(loader, nodes) { const animationJsons = loader.gltfJson.animations; if (loader._loadForClassification || !defined_default(animationJsons)) { return []; } const animations = animationJsons.map(function(animationJson, i) { const animation = loadAnimation(loader, animationJson, nodes); animation.index = i; return animation; }); return animations; } function loadArticulationStage(gltfStage) { const stage = new ArticulationStage2(); stage.name = gltfStage.name; const type = gltfStage.type.toUpperCase(); stage.type = ArticulationStageType_default[type]; stage.minimumValue = gltfStage.minimumValue; stage.maximumValue = gltfStage.maximumValue; stage.initialValue = gltfStage.initialValue; return stage; } function loadArticulation(articulationJson) { const articulation = new Articulation2(); articulation.name = articulationJson.name; articulation.stages = articulationJson.stages.map(loadArticulationStage); return articulation; } function loadArticulations(gltf) { const extensions = gltf.extensions ?? Frozen_default.EMPTY_OBJECT; const articulationJsons = extensions.AGI_articulations?.articulations; if (!defined_default(articulationJsons)) { return []; } return articulationJsons.map(loadArticulation); } function getSceneNodeIds(gltf) { let nodesIds; if (defined_default(gltf.scenes) && defined_default(gltf.scene)) { nodesIds = gltf.scenes[gltf.scene].nodes; } nodesIds = nodesIds ?? gltf.nodes; nodesIds = defined_default(nodesIds) ? nodesIds : []; return nodesIds; } function loadScene(gltf, nodes) { const scene = new Scene2(); const sceneNodeIds = getSceneNodeIds(gltf); scene.nodes = sceneNodeIds.map(function(sceneNodeId) { return nodes[sceneNodeId]; }); return scene; } var scratchCenter3 = new Cartesian3_default(); function parse(loader, frameState) { const gltf = loader.gltfJson; const extensions = gltf.extensions ?? Frozen_default.EMPTY_OBJECT; const structuralMetadataExtension = extensions.EXT_structural_metadata; const featureMetadataExtensionLegacy = extensions.EXT_feature_metadata; const cesiumRtcExtension = extensions.CESIUM_RTC; if (defined_default(featureMetadataExtensionLegacy)) { const featureTables = featureMetadataExtensionLegacy.featureTables; const featureTextures = featureMetadataExtensionLegacy.featureTextures; const allPropertyTableIds = defined_default(featureTables) ? featureTables : []; const allFeatureTextureIds = defined_default(featureTextures) ? featureTextures : []; loader._sortedPropertyTableIds = Object.keys(allPropertyTableIds).sort(); loader._sortedFeatureTextureIds = Object.keys(allFeatureTextureIds).sort(); } const nodes = loadNodes(loader, frameState); const skins = loadSkins(loader, nodes); const animations = loadAnimations(loader, nodes); const articulations = loadArticulations(gltf); const scene = loadScene(gltf, nodes); const components = new Components2(); const asset = new Asset2(); const copyright = gltf.asset.copyright; if (defined_default(copyright)) { const credits = copyright.split(";").map(function(string) { return new Credit_default(string.trim()); }); asset.credits = credits; } components.asset = asset; components.scene = scene; components.nodes = nodes; components.skins = skins; components.animations = animations; components.articulations = articulations; components.upAxis = loader._upAxis; components.forwardAxis = loader._forwardAxis; if (defined_default(cesiumRtcExtension)) { const center = Cartesian3_default.fromArray( cesiumRtcExtension.center, 0, scratchCenter3 ); components.transform = Matrix4_default.fromTranslation( center, components.transform ); } loader._components = components; if (defined_default(structuralMetadataExtension) || defined_default(featureMetadataExtensionLegacy)) { const promise = loadStructuralMetadata( loader, structuralMetadataExtension, featureMetadataExtensionLegacy, frameState ); loader._loaderPromises.push(promise); } const gpmExtension = extensions.NGA_gpm_local; if (defined_default(gpmExtension)) { const gltfGpmLocal = GltfGpmLoader_default.load(gpmExtension); loader._components.extensions["NGA_gpm_local"] = gltfGpmLocal; } const meshes = gltf.meshes; if (defined_default(meshes)) { for (const mesh of meshes) { const primitives = mesh.primitives; if (defined_default(primitives)) { for (const primitive of primitives) { const primitiveExtensions = primitive.extensions; if (defined_default(primitiveExtensions)) { const meshPrimitiveGpmExtension = primitiveExtensions.NGA_gpm_local; if (defined_default(meshPrimitiveGpmExtension)) { const promise = loadMeshPrimitiveGpm( loader, gltf, meshPrimitiveGpmExtension, frameState ); loader._loaderPromises.push(promise); } } } } } } const readyPromises = []; addAllToArray_default(readyPromises, loader._loaderPromises); if (!loader._incrementallyLoadTextures) { addAllToArray_default(readyPromises, loader._texturesPromises); } return Promise.all(readyPromises); } function unloadTextures2(loader) { const textureLoaders = loader._textureLoaders; for (let i = 0; i < textureLoaders.length; ++i) { textureLoaders[i] = !textureLoaders[i].isDestroyed() && ResourceCache_default.unload(textureLoaders[i]); } loader._textureLoaders.length = 0; } function unloadBufferViewLoaders(loader) { const bufferViewLoaders = loader._bufferViewLoaders; for (let i = 0; i < bufferViewLoaders.length; ++i) { bufferViewLoaders[i] = !bufferViewLoaders[i].isDestroyed() && ResourceCache_default.unload(bufferViewLoaders[i]); } loader._bufferViewLoaders.length = 0; } function unloadGeometry(loader) { const geometryLoaders = loader._geometryLoaders; for (let i = 0; i < geometryLoaders.length; ++i) { geometryLoaders[i] = !geometryLoaders[i].isDestroyed() && ResourceCache_default.unload(geometryLoaders[i]); } loader._geometryLoaders.length = 0; } function unloadGeneratedAttributes(loader) { const buffers = loader._postProcessBuffers; for (let i = 0; i < buffers.length; i++) { const buffer2 = buffers[i]; if (!buffer2.isDestroyed()) { buffer2.destroy(); } } buffers.length = 0; } function unloadStructuralMetadata(loader) { if (defined_default(loader._structuralMetadataLoader) && !loader._structuralMetadataLoader.isDestroyed()) { loader._structuralMetadataLoader.destroy(); loader._structuralMetadataLoader = void 0; } } function unloadMeshPrimitiveGpm(loader) { if (defined_default(loader._meshPrimitiveGpmLoader) && !loader._meshPrimitiveGpmLoader.isDestroyed()) { loader._meshPrimitiveGpmLoader.destroy(); loader._meshPrimitiveGpmLoader = void 0; } } GltfLoader.prototype.isUnloaded = function() { return this._state === GltfLoaderState.UNLOADED; }; GltfLoader.prototype.unload = function() { if (defined_default(this._gltfJsonLoader) && !this._gltfJsonLoader.isDestroyed()) { ResourceCache_default.unload(this._gltfJsonLoader); } this._gltfJsonLoader = void 0; unloadTextures2(this); unloadBufferViewLoaders(this); unloadGeometry(this); unloadGeneratedAttributes(this); unloadStructuralMetadata(this); unloadMeshPrimitiveGpm(this); this._components = void 0; this._typedArray = void 0; this._state = GltfLoaderState.UNLOADED; }; var GltfLoader_default = GltfLoader; // packages/engine/Source/Scene/PointCloudShading.js var import_InlineWorkers579 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/PointCloudEyeDomeLighting.js var import_InlineWorkers578 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Shaders/PostProcessStages/PointCloudEyeDomeLighting.js var import_InlineWorkers577 = __toESM(require_InlineWorkers(), 1); var PointCloudEyeDomeLighting_default = "uniform sampler2D u_pointCloud_colorGBuffer;\nuniform sampler2D u_pointCloud_depthGBuffer;\nuniform vec2 u_distanceAndEdlStrength;\nin vec2 v_textureCoordinates;\n\nvec2 neighborContribution(float log2Depth, vec2 offset)\n{\n float dist = u_distanceAndEdlStrength.x;\n vec2 texCoordOrig = v_textureCoordinates + offset * dist;\n vec2 texCoord0 = v_textureCoordinates + offset * floor(dist);\n vec2 texCoord1 = v_textureCoordinates + offset * ceil(dist);\n\n float depthOrLogDepth0 = czm_unpackDepth(texture(u_pointCloud_depthGBuffer, texCoord0));\n float depthOrLogDepth1 = czm_unpackDepth(texture(u_pointCloud_depthGBuffer, texCoord1));\n\n // ignore depth values that are the clear depth\n if (depthOrLogDepth0 == 0.0 || depthOrLogDepth1 == 0.0) {\n return vec2(0.0);\n }\n\n // interpolate the two adjacent depth values\n float depthMix = mix(depthOrLogDepth0, depthOrLogDepth1, fract(dist));\n vec4 eyeCoordinate = czm_windowToEyeCoordinates(texCoordOrig, depthMix);\n return vec2(max(0.0, log2Depth - log2(-eyeCoordinate.z / eyeCoordinate.w)), 1.0);\n}\n\nvoid main()\n{\n float depthOrLogDepth = czm_unpackDepth(texture(u_pointCloud_depthGBuffer, v_textureCoordinates));\n\n vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, depthOrLogDepth);\n eyeCoordinate /= eyeCoordinate.w;\n\n float log2Depth = log2(-eyeCoordinate.z);\n\n if (depthOrLogDepth == 0.0) // 0.0 is the clear value for the gbuffer\n {\n discard;\n }\n\n vec4 color = texture(u_pointCloud_colorGBuffer, v_textureCoordinates);\n\n // sample from neighbors left, right, down, up\n vec2 texelSize = 1.0 / czm_viewport.zw;\n\n vec2 responseAndCount = vec2(0.0);\n\n responseAndCount += neighborContribution(log2Depth, vec2(-texelSize.x, 0.0));\n responseAndCount += neighborContribution(log2Depth, vec2(+texelSize.x, 0.0));\n responseAndCount += neighborContribution(log2Depth, vec2(0.0, -texelSize.y));\n responseAndCount += neighborContribution(log2Depth, vec2(0.0, +texelSize.y));\n\n float response = responseAndCount.x / responseAndCount.y;\n float strength = u_distanceAndEdlStrength.y;\n float shade = exp(-response * 300.0 * strength);\n color.rgb *= shade;\n out_FragColor = vec4(color);\n\n // Input and output depth are the same.\n gl_FragDepth = depthOrLogDepth;\n}\n"; // packages/engine/Source/Scene/PointCloudEyeDomeLighting.js function PointCloudEyeDomeLighting() { this._framebuffer = new FramebufferManager_default({ colorAttachmentsLength: 2, depth: true, supportsDepthTexture: true }); this._drawCommand = void 0; this._clearCommand = void 0; this._strength = 1; this._radius = 1; } Object.defineProperties(PointCloudEyeDomeLighting.prototype, { framebuffer: { get: function() { return this._framebuffer.framebuffer; } }, colorGBuffer: { get: function() { return this._framebuffer.getColorTexture(0); } }, depthGBuffer: { get: function() { return this._framebuffer.getColorTexture(1); } } }); function destroyFramebuffer(processor) { processor._framebuffer.destroy(); processor._drawCommand = void 0; processor._clearCommand = void 0; } var distanceAndEdlStrengthScratch = new Cartesian2_default(); function createCommands4(processor, context) { const blendFS = new ShaderSource_default({ defines: ["LOG_DEPTH_WRITE"], sources: [PointCloudEyeDomeLighting_default] }); const blendUniformMap = { u_pointCloud_colorGBuffer: function() { return processor.colorGBuffer; }, u_pointCloud_depthGBuffer: function() { return processor.depthGBuffer; }, u_distanceAndEdlStrength: function() { distanceAndEdlStrengthScratch.x = processor._radius; distanceAndEdlStrengthScratch.y = processor._strength; return distanceAndEdlStrengthScratch; } }; const blendRenderState = RenderState_default.fromCache({ blending: BlendingState_default.ALPHA_BLEND, depthMask: true, depthTest: { enabled: true }, stencilTest: StencilConstants_default.setCesium3DTileBit(), stencilMask: StencilConstants_default.CESIUM_3D_TILE_MASK }); processor._drawCommand = context.createViewportQuadCommand(blendFS, { uniformMap: blendUniformMap, renderState: blendRenderState, pass: Pass_default.CESIUM_3D_TILE, owner: processor }); processor._clearCommand = new ClearCommand_default({ framebuffer: processor.framebuffer, color: new Color_default(0, 0, 0, 0), depth: 1, renderState: RenderState_default.fromCache(), pass: Pass_default.CESIUM_3D_TILE, owner: processor }); } function createResources(processor, context) { const width = context.drawingBufferWidth; const height = context.drawingBufferHeight; processor._framebuffer.update(context, width, height); createCommands4(processor, context); } function isSupported(context) { return context.drawBuffers && context.fragmentDepth; } PointCloudEyeDomeLighting.isSupported = isSupported; function getECShaderProgram(context, shaderProgram) { let shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, "EC"); if (!defined_default(shader)) { const attributeLocations8 = shaderProgram._attributeLocations; const fs = shaderProgram.fragmentShaderSource.clone(); fs.sources.splice( 0, 0, `layout (location = 0) out vec4 out_FragData_0; layout (location = 1) out vec4 out_FragData_1;` ); fs.sources = fs.sources.map(function(source) { source = ShaderSource_default.replaceMain( source, "czm_point_cloud_post_process_main" ); source = source.replaceAll(/out_FragColor/g, "out_FragData_0"); return source; }); fs.sources.push( "void main() \n{ \n czm_point_cloud_post_process_main(); \n#ifdef LOG_DEPTH\n czm_writeLogDepth();\n out_FragData_1 = czm_packDepth(gl_FragDepth); \n#else\n out_FragData_1 = czm_packDepth(gl_FragCoord.z);\n#endif\n}" ); shader = context.shaderCache.createDerivedShaderProgram( shaderProgram, "EC", { vertexShaderSource: shaderProgram.vertexShaderSource, fragmentShaderSource: fs, attributeLocations: attributeLocations8 } ); } return shader; } PointCloudEyeDomeLighting.prototype.update = function(frameState, commandStart, pointCloudShading, boundingVolume) { if (!isSupported(frameState.context)) { return; } this._strength = pointCloudShading.eyeDomeLightingStrength; this._radius = pointCloudShading.eyeDomeLightingRadius * frameState.pixelRatio; createResources(this, frameState.context); let i; const commandList = frameState.commandList; const commandEnd = commandList.length; for (i = commandStart; i < commandEnd; ++i) { const command = commandList[i]; if (command.primitiveType !== PrimitiveType_default.POINTS || command.pass === Pass_default.TRANSLUCENT) { continue; } let derivedCommand; let originalShaderProgram; let derivedCommandObject = command.derivedCommands.pointCloudProcessor; if (defined_default(derivedCommandObject)) { derivedCommand = derivedCommandObject.command; originalShaderProgram = derivedCommandObject.originalShaderProgram; } if (!defined_default(derivedCommand) || command.dirty || originalShaderProgram !== command.shaderProgram || derivedCommand.framebuffer !== this.framebuffer) { derivedCommand = DrawCommand_default.shallowClone(command, derivedCommand); derivedCommand.framebuffer = this.framebuffer; derivedCommand.shaderProgram = getECShaderProgram( frameState.context, command.shaderProgram ); derivedCommand.castShadows = false; derivedCommand.receiveShadows = false; if (!defined_default(derivedCommandObject)) { derivedCommandObject = { command: derivedCommand, originalShaderProgram: command.shaderProgram }; command.derivedCommands.pointCloudProcessor = derivedCommandObject; } derivedCommandObject.originalShaderProgram = command.shaderProgram; } commandList[i] = derivedCommand; } const clearCommand = this._clearCommand; const blendCommand = this._drawCommand; blendCommand.boundingVolume = boundingVolume; commandList.push(blendCommand); commandList.push(clearCommand); }; PointCloudEyeDomeLighting.prototype.isDestroyed = function() { return false; }; PointCloudEyeDomeLighting.prototype.destroy = function() { destroyFramebuffer(this); return destroyObject_default(this); }; var PointCloudEyeDomeLighting_default2 = PointCloudEyeDomeLighting; // packages/engine/Source/Scene/PointCloudShading.js function PointCloudShading(options) { const pointCloudShading = options ?? {}; this.attenuation = pointCloudShading.attenuation ?? false; this.geometricErrorScale = pointCloudShading.geometricErrorScale ?? 1; this.maximumAttenuation = pointCloudShading.maximumAttenuation; this.baseResolution = pointCloudShading.baseResolution; this.eyeDomeLighting = pointCloudShading.eyeDomeLighting ?? true; this.eyeDomeLightingStrength = pointCloudShading.eyeDomeLightingStrength ?? 1; this.eyeDomeLightingRadius = pointCloudShading.eyeDomeLightingRadius ?? 1; this.backFaceCulling = pointCloudShading.backFaceCulling ?? false; this.normalShading = pointCloudShading.normalShading ?? true; } PointCloudShading.isSupported = function(scene) { return PointCloudEyeDomeLighting_default2.isSupported(scene.context); }; var PointCloudShading_default = PointCloudShading; // packages/engine/Source/Scene/SceneTransforms.js var import_InlineWorkers580 = __toESM(require_InlineWorkers(), 1); var SceneTransforms = {}; var actualPositionScratch = new Cartesian4_default(0, 0, 0, 1); var positionCC = new Cartesian4_default(); var scratchViewport2 = new BoundingRectangle_default(); var scratchWindowCoord0 = new Cartesian2_default(); var scratchWindowCoord1 = new Cartesian2_default(); SceneTransforms.worldToWindowCoordinates = function(scene, position, result) { return SceneTransforms.worldWithEyeOffsetToWindowCoordinates( scene, position, Cartesian3_default.ZERO, result ); }; var scratchCartesian42 = new Cartesian4_default(); var scratchEyeOffset = new Cartesian3_default(); function worldToClip(position, eyeOffset, camera, result) { const viewMatrix = camera.viewMatrix; const positionEC = Matrix4_default.multiplyByVector( viewMatrix, Cartesian4_default.fromElements( position.x, position.y, position.z, 1, scratchCartesian42 ), scratchCartesian42 ); const zEyeOffset = Cartesian3_default.multiplyComponents( eyeOffset, Cartesian3_default.normalize(positionEC, scratchEyeOffset), scratchEyeOffset ); positionEC.x += eyeOffset.x + zEyeOffset.x; positionEC.y += eyeOffset.y + zEyeOffset.y; positionEC.z += zEyeOffset.z; return Matrix4_default.multiplyByVector( camera.frustum.projectionMatrix, positionEC, result ); } var scratchMaxCartographic = new Cartographic_default( Math.PI, Math_default.PI_OVER_TWO ); var scratchProjectedCartesian = new Cartesian3_default(); var scratchCameraPosition = new Cartesian3_default(); SceneTransforms.worldWithEyeOffsetToWindowCoordinates = function(scene, position, eyeOffset, result) { if (!defined_default(scene)) { throw new DeveloperError_default("scene is required."); } if (!defined_default(position)) { throw new DeveloperError_default("position is required."); } const frameState = scene.frameState; const actualPosition = SceneTransforms.computeActualEllipsoidPosition( frameState, position, actualPositionScratch ); if (!defined_default(actualPosition)) { return void 0; } const canvas = scene.canvas; const viewport = scratchViewport2; viewport.x = 0; viewport.y = 0; viewport.width = canvas.clientWidth; viewport.height = canvas.clientHeight; const camera = scene.camera; let cameraCentered = false; if (frameState.mode === SceneMode_default.SCENE2D) { const projection = scene.mapProjection; const maxCartographic = scratchMaxCartographic; const maxCoord = projection.project( maxCartographic, scratchProjectedCartesian ); const cameraPosition = Cartesian3_default.clone( camera.position, scratchCameraPosition ); const frustum = camera.frustum.clone(); const viewportTransformation = Matrix4_default.computeViewportTransformation( viewport, 0, 1, new Matrix4_default() ); const projectionMatrix = camera.frustum.projectionMatrix; const x = camera.positionWC.y; const eyePoint = Cartesian3_default.fromElements( Math_default.sign(x) * maxCoord.x - x, 0, -camera.positionWC.x ); const windowCoordinates = Transforms_default.pointToGLWindowCoordinates( projectionMatrix, viewportTransformation, eyePoint ); if (x === 0 || windowCoordinates.x <= 0 || windowCoordinates.x >= canvas.clientWidth) { cameraCentered = true; } else { if (windowCoordinates.x > canvas.clientWidth * 0.5) { viewport.width = windowCoordinates.x; camera.frustum.right = maxCoord.x - x; positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC); SceneTransforms.clipToGLWindowCoordinates( viewport, positionCC, scratchWindowCoord0 ); viewport.x += windowCoordinates.x; camera.position.x = -camera.position.x; const right = camera.frustum.right; camera.frustum.right = -camera.frustum.left; camera.frustum.left = -right; positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC); SceneTransforms.clipToGLWindowCoordinates( viewport, positionCC, scratchWindowCoord1 ); } else { viewport.x += windowCoordinates.x; viewport.width -= windowCoordinates.x; camera.frustum.left = -maxCoord.x - x; positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC); SceneTransforms.clipToGLWindowCoordinates( viewport, positionCC, scratchWindowCoord0 ); viewport.x = viewport.x - viewport.width; camera.position.x = -camera.position.x; const left = camera.frustum.left; camera.frustum.left = -camera.frustum.right; camera.frustum.right = -left; positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC); SceneTransforms.clipToGLWindowCoordinates( viewport, positionCC, scratchWindowCoord1 ); } Cartesian3_default.clone(cameraPosition, camera.position); camera.frustum = frustum.clone(); result = Cartesian2_default.clone(scratchWindowCoord0, result); if (result.x < 0 || result.x > canvas.clientWidth) { result.x = scratchWindowCoord1.x; } } } if (frameState.mode !== SceneMode_default.SCENE2D || cameraCentered) { positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC); if (positionCC.z < 0 && !(camera.frustum instanceof OrthographicFrustum_default) && !(camera.frustum instanceof OrthographicOffCenterFrustum_default)) { return void 0; } result = SceneTransforms.clipToGLWindowCoordinates( viewport, positionCC, result ); } result.y = canvas.clientHeight - result.y; return result; }; SceneTransforms.worldToDrawingBufferCoordinates = function(scene, position, result) { result = SceneTransforms.worldToWindowCoordinates(scene, position, result); if (!defined_default(result)) { return void 0; } return SceneTransforms.transformWindowToDrawingBuffer(scene, result, result); }; var projectedPosition = new Cartesian3_default(); var positionInCartographic = new Cartographic_default(); SceneTransforms.computeActualEllipsoidPosition = function(frameState, position, result) { const mode2 = frameState.mode; if (mode2 === SceneMode_default.SCENE3D) { return Cartesian3_default.clone(position, result); } const projection = frameState.mapProjection; const cartographic2 = projection.ellipsoid.cartesianToCartographic( position, positionInCartographic ); if (!defined_default(cartographic2)) { return void 0; } projection.project(cartographic2, projectedPosition); if (mode2 === SceneMode_default.COLUMBUS_VIEW) { return Cartesian3_default.fromElements( projectedPosition.z, projectedPosition.x, projectedPosition.y, result ); } if (mode2 === SceneMode_default.SCENE2D) { return Cartesian3_default.fromElements( 0, projectedPosition.x, projectedPosition.y, result ); } const morphTime = frameState.morphTime; return Cartesian3_default.fromElements( Math_default.lerp(projectedPosition.z, position.x, morphTime), Math_default.lerp(projectedPosition.x, position.y, morphTime), Math_default.lerp(projectedPosition.y, position.z, morphTime), result ); }; var positionNDC = new Cartesian3_default(); var positionWC = new Cartesian3_default(); var viewportTransform = new Matrix4_default(); SceneTransforms.clipToGLWindowCoordinates = function(viewport, position, result) { Cartesian3_default.divideByScalar(position, position.w, positionNDC); Matrix4_default.computeViewportTransformation(viewport, 0, 1, viewportTransform); Matrix4_default.multiplyByPoint(viewportTransform, positionNDC, positionWC); return Cartesian2_default.fromCartesian3(positionWC, result); }; SceneTransforms.transformWindowToDrawingBuffer = function(scene, windowPosition, result) { const canvas = scene.canvas; const xScale = scene.drawingBufferWidth / canvas.clientWidth; const yScale = scene.drawingBufferHeight / canvas.clientHeight; return Cartesian2_default.fromElements( windowPosition.x * xScale, windowPosition.y * yScale, result ); }; var scratchNDC = new Cartesian4_default(); var scratchWorldCoords = new Cartesian4_default(); SceneTransforms.drawingBufferToWorldCoordinates = function(scene, drawingBufferPosition, depth, result) { const context = scene.context; const uniformState = context.uniformState; const currentFrustum = uniformState.currentFrustum; const near = currentFrustum.x; const far = currentFrustum.y; if (scene.frameState.useLogDepth) { const log2Depth = depth * uniformState.log2FarDepthFromNearPlusOne; const depthFromNear = Math.pow(2, log2Depth) - 1; depth = far * (1 - near / (depthFromNear + near)) / (far - near); } const viewport = scene.view.passState.viewport; const ndc = Cartesian4_default.clone(Cartesian4_default.UNIT_W, scratchNDC); ndc.x = (drawingBufferPosition.x - viewport.x) / viewport.width * 2 - 1; ndc.y = (drawingBufferPosition.y - viewport.y) / viewport.height * 2 - 1; ndc.z = depth * 2 - 1; ndc.w = 1; let worldCoords; let frustum = scene.camera.frustum; if (!defined_default(frustum.fovy)) { const offCenterFrustum = frustum.offCenterFrustum; if (defined_default(offCenterFrustum)) { frustum = offCenterFrustum; } worldCoords = scratchWorldCoords; worldCoords.x = (ndc.x * (frustum.right - frustum.left) + frustum.left + frustum.right) * 0.5; worldCoords.y = (ndc.y * (frustum.top - frustum.bottom) + frustum.bottom + frustum.top) * 0.5; worldCoords.z = (ndc.z * (near - far) - near - far) * 0.5; worldCoords.w = 1; worldCoords = Matrix4_default.multiplyByVector( uniformState.inverseView, worldCoords, worldCoords ); } else { worldCoords = Matrix4_default.multiplyByVector( uniformState.inverseViewProjection, ndc, scratchWorldCoords ); const w = 1 / worldCoords.w; Cartesian3_default.multiplyByScalar(worldCoords, w, worldCoords); } return Cartesian3_default.fromCartesian4(worldCoords, result); }; var SceneTransforms_default = SceneTransforms; // packages/engine/Source/Scene/Model/B3dmLoader.js var import_InlineWorkers584 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/B3dmParser.js var import_InlineWorkers581 = __toESM(require_InlineWorkers(), 1); var B3dmParser = {}; B3dmParser._deprecationWarning = deprecationWarning_default; var sizeOfUint324 = Uint32Array.BYTES_PER_ELEMENT; B3dmParser.parse = function(arrayBuffer, byteOffset) { const byteStart = byteOffset ?? 0; Check_default.defined("arrayBuffer", arrayBuffer); byteOffset = byteStart; const uint8Array = new Uint8Array(arrayBuffer); const view = new DataView(arrayBuffer); byteOffset += sizeOfUint324; const version2 = view.getUint32(byteOffset, true); if (version2 !== 1) { throw new RuntimeError_default( `Only Batched 3D Model version 1 is supported. Version ${version2} is not.` ); } byteOffset += sizeOfUint324; const byteLength = view.getUint32(byteOffset, true); byteOffset += sizeOfUint324; let featureTableJsonByteLength = view.getUint32(byteOffset, true); byteOffset += sizeOfUint324; let featureTableBinaryByteLength = view.getUint32(byteOffset, true); byteOffset += sizeOfUint324; let batchTableJsonByteLength = view.getUint32(byteOffset, true); byteOffset += sizeOfUint324; let batchTableBinaryByteLength = view.getUint32(byteOffset, true); byteOffset += sizeOfUint324; let batchLength; if (batchTableJsonByteLength >= 570425344) { byteOffset -= sizeOfUint324 * 2; batchLength = featureTableJsonByteLength; batchTableJsonByteLength = featureTableBinaryByteLength; batchTableBinaryByteLength = 0; featureTableJsonByteLength = 0; featureTableBinaryByteLength = 0; B3dmParser._deprecationWarning( "b3dm-legacy-header", "This b3dm header is using the legacy format [batchLength] [batchTableByteLength]. The new format is [featureTableJsonByteLength] [featureTableBinaryByteLength] [batchTableJsonByteLength] [batchTableBinaryByteLength] from https://github.com/CesiumGS/3d-tiles/tree/main/specification/TileFormats/Batched3DModel." ); } else if (batchTableBinaryByteLength >= 570425344) { byteOffset -= sizeOfUint324; batchLength = batchTableJsonByteLength; batchTableJsonByteLength = featureTableJsonByteLength; batchTableBinaryByteLength = featureTableBinaryByteLength; featureTableJsonByteLength = 0; featureTableBinaryByteLength = 0; B3dmParser._deprecationWarning( "b3dm-legacy-header", "This b3dm header is using the legacy format [batchTableJsonByteLength] [batchTableBinaryByteLength] [batchLength]. The new format is [featureTableJsonByteLength] [featureTableBinaryByteLength] [batchTableJsonByteLength] [batchTableBinaryByteLength] from https://github.com/CesiumGS/3d-tiles/tree/main/specification/TileFormats/Batched3DModel." ); } let featureTableJson; if (featureTableJsonByteLength === 0) { featureTableJson = { BATCH_LENGTH: batchLength ?? 0 }; } else { featureTableJson = getJsonFromTypedArray_default( uint8Array, byteOffset, featureTableJsonByteLength ); byteOffset += featureTableJsonByteLength; } const featureTableBinary = new Uint8Array( arrayBuffer, byteOffset, featureTableBinaryByteLength ); byteOffset += featureTableBinaryByteLength; let batchTableJson; let batchTableBinary; if (batchTableJsonByteLength > 0) { batchTableJson = getJsonFromTypedArray_default( uint8Array, byteOffset, batchTableJsonByteLength ); byteOffset += batchTableJsonByteLength; if (batchTableBinaryByteLength > 0) { batchTableBinary = new Uint8Array( arrayBuffer, byteOffset, batchTableBinaryByteLength ); batchTableBinary = new Uint8Array(batchTableBinary); byteOffset += batchTableBinaryByteLength; } } const gltfByteLength = byteStart + byteLength - byteOffset; if (gltfByteLength === 0) { throw new RuntimeError_default("glTF byte length must be greater than 0."); } let gltfView; if (byteOffset % 4 === 0) { gltfView = new Uint8Array(arrayBuffer, byteOffset, gltfByteLength); } else { B3dmParser._deprecationWarning( "b3dm-glb-unaligned", "The embedded glb is not aligned to a 4-byte boundary." ); gltfView = new Uint8Array( uint8Array.subarray(byteOffset, byteOffset + gltfByteLength) ); } return { batchLength, featureTableJson, featureTableBinary, batchTableJson, batchTableBinary, gltf: gltfView }; }; var B3dmParser_default = B3dmParser; // packages/engine/Source/Scene/Cesium3DTileFeatureTable.js var import_InlineWorkers582 = __toESM(require_InlineWorkers(), 1); function Cesium3DTileFeatureTable(featureTableJson, featureTableBinary) { this.json = featureTableJson; this.buffer = featureTableBinary; this._cachedTypedArrays = {}; this.featuresLength = 0; } function getTypedArrayFromBinary(featureTable, semantic, componentType, componentLength, count, byteOffset) { const cachedTypedArrays = featureTable._cachedTypedArrays; let typedArray = cachedTypedArrays[semantic]; if (!defined_default(typedArray)) { typedArray = ComponentDatatype_default.createArrayBufferView( componentType, featureTable.buffer.buffer, featureTable.buffer.byteOffset + byteOffset, count * componentLength ); cachedTypedArrays[semantic] = typedArray; } return typedArray; } function getTypedArrayFromArray(featureTable, semantic, componentType, array) { const cachedTypedArrays = featureTable._cachedTypedArrays; let typedArray = cachedTypedArrays[semantic]; if (!defined_default(typedArray)) { typedArray = ComponentDatatype_default.createTypedArray(componentType, array); cachedTypedArrays[semantic] = typedArray; } return typedArray; } Cesium3DTileFeatureTable.prototype.getGlobalProperty = function(semantic, componentType, componentLength) { const jsonValue = this.json[semantic]; if (!defined_default(jsonValue)) { return void 0; } if (defined_default(jsonValue.byteOffset)) { componentType = componentType ?? ComponentDatatype_default.UNSIGNED_INT; componentLength = componentLength ?? 1; return getTypedArrayFromBinary( this, semantic, componentType, componentLength, 1, jsonValue.byteOffset ); } return jsonValue; }; Cesium3DTileFeatureTable.prototype.hasProperty = function(semantic) { return defined_default(this.json[semantic]); }; Cesium3DTileFeatureTable.prototype.getPropertyArray = function(semantic, componentType, componentLength) { const jsonValue = this.json[semantic]; if (!defined_default(jsonValue)) { return void 0; } if (defined_default(jsonValue.byteOffset)) { if (defined_default(jsonValue.componentType)) { componentType = ComponentDatatype_default.fromName(jsonValue.componentType); } return getTypedArrayFromBinary( this, semantic, componentType, componentLength, this.featuresLength, jsonValue.byteOffset ); } return getTypedArrayFromArray(this, semantic, componentType, jsonValue); }; Cesium3DTileFeatureTable.prototype.getProperty = function(semantic, componentType, componentLength, featureId, result) { const jsonValue = this.json[semantic]; if (!defined_default(jsonValue)) { return void 0; } const typedArray = this.getPropertyArray( semantic, componentType, componentLength ); if (componentLength === 1) { return typedArray[featureId]; } for (let i = 0; i < componentLength; ++i) { result[i] = typedArray[componentLength * featureId + i]; } return result; }; var Cesium3DTileFeatureTable_default = Cesium3DTileFeatureTable; // packages/engine/Source/Scene/parseBatchTable.js var import_InlineWorkers583 = __toESM(require_InlineWorkers(), 1); function parseBatchTable(options) { Check_default.typeOf.number("options.count", options.count); Check_default.typeOf.object("options.batchTable", options.batchTable); const featureCount = options.count; const batchTable = options.batchTable; const binaryBody = options.binaryBody; const parseAsPropertyAttributes = options.parseAsPropertyAttributes ?? false; const customAttributeOutput = options.customAttributeOutput; if (parseAsPropertyAttributes && !defined_default(customAttributeOutput)) { throw new DeveloperError_default( "customAttributeOutput is required when parsing batch table as property attributes" ); } const partitionResults = partitionProperties(batchTable); let jsonMetadataTable; if (defined_default(partitionResults.jsonProperties)) { jsonMetadataTable = new JsonMetadataTable_default({ count: featureCount, properties: partitionResults.jsonProperties }); } let hierarchy; if (defined_default(partitionResults.hierarchy)) { hierarchy = new BatchTableHierarchy_default({ extension: partitionResults.hierarchy, binaryBody }); } const className = MetadataClass_default.BATCH_TABLE_CLASS_NAME; const binaryProperties = partitionResults.binaryProperties; let metadataTable; let propertyAttributes; let transcodedSchema; if (parseAsPropertyAttributes) { const attributeResults = transcodeBinaryPropertiesAsPropertyAttributes( featureCount, className, binaryProperties, binaryBody, customAttributeOutput ); transcodedSchema = attributeResults.transcodedSchema; const propertyAttribute = new PropertyAttribute_default({ propertyAttribute: attributeResults.propertyAttributeJson, class: attributeResults.transcodedClass }); propertyAttributes = [propertyAttribute]; } else { const binaryResults = transcodeBinaryProperties( featureCount, className, binaryProperties, binaryBody ); transcodedSchema = binaryResults.transcodedSchema; const featureTableJson = binaryResults.featureTableJson; metadataTable = new MetadataTable_default({ count: featureTableJson.count, properties: featureTableJson.properties, class: binaryResults.transcodedClass, bufferViews: binaryResults.bufferViewsTypedArrays }); propertyAttributes = []; } const propertyTables = []; if (defined_default(metadataTable) || defined_default(jsonMetadataTable) || defined_default(hierarchy)) { const propertyTable = new PropertyTable_default({ id: 0, name: "Batch Table", count: featureCount, metadataTable, jsonMetadataTable, batchTableHierarchy: hierarchy }); propertyTables.push(propertyTable); } const metadataOptions = { schema: transcodedSchema, propertyTables, propertyAttributes, extensions: partitionResults.extensions, extras: partitionResults.extras }; return new StructuralMetadata_default(metadataOptions); } function partitionProperties(batchTable) { const legacyHierarchy = batchTable.HIERARCHY; const extras = batchTable.extras; const extensions = batchTable.extensions; let hierarchyExtension; if (defined_default(legacyHierarchy)) { parseBatchTable._deprecationWarning( "batchTableHierarchyExtension", "The batch table HIERARCHY property has been moved to an extension. Use extensions.3DTILES_batch_table_hierarchy instead." ); hierarchyExtension = legacyHierarchy; } else if (defined_default(extensions)) { hierarchyExtension = extensions["3DTILES_batch_table_hierarchy"]; } let jsonProperties; const binaryProperties = {}; for (const propertyId in batchTable) { if (!batchTable.hasOwnProperty(propertyId) || // these cases were handled above; propertyId === "HIERARCHY" || propertyId === "extensions" || propertyId === "extras") { continue; } const property = batchTable[propertyId]; if (Array.isArray(property)) { jsonProperties = defined_default(jsonProperties) ? jsonProperties : {}; jsonProperties[propertyId] = property; } else { binaryProperties[propertyId] = property; } } return { binaryProperties, jsonProperties, hierarchy: hierarchyExtension, extras, extensions }; } function transcodeBinaryProperties(featureCount, className, binaryProperties, binaryBody) { const classProperties = {}; const featureTableProperties = {}; const bufferViewsTypedArrays = {}; let bufferViewCount = 0; for (const propertyId in binaryProperties) { if (!binaryProperties.hasOwnProperty(propertyId)) { continue; } if (!defined_default(binaryBody)) { throw new RuntimeError_default( `Property ${propertyId} requires a batch table binary.` ); } const property = binaryProperties[propertyId]; const binaryAccessor = getBinaryAccessor_default(property); featureTableProperties[propertyId] = { bufferView: bufferViewCount }; classProperties[propertyId] = transcodePropertyType(property); bufferViewsTypedArrays[bufferViewCount] = binaryAccessor.createArrayBufferView( binaryBody.buffer, binaryBody.byteOffset + property.byteOffset, featureCount ); bufferViewCount++; } const schemaJson = { classes: {} }; schemaJson.classes[className] = { properties: classProperties }; const transcodedSchema = MetadataSchema_default.fromJson(schemaJson); const featureTableJson = { class: className, count: featureCount, properties: featureTableProperties }; return { featureTableJson, bufferViewsTypedArrays, transcodedSchema, transcodedClass: transcodedSchema.classes[className] }; } function transcodeBinaryPropertiesAsPropertyAttributes(featureCount, className, binaryProperties, binaryBody, customAttributeOutput) { const classProperties = {}; const propertyAttributeProperties = {}; let nextPlaceholderId = 0; for (const propertyId in binaryProperties) { if (!binaryProperties.hasOwnProperty(propertyId)) { continue; } const property = binaryProperties[propertyId]; if (!defined_default(binaryBody) && !defined_default(property.typedArray)) { throw new RuntimeError_default( `Property ${propertyId} requires a batch table binary.` ); } let sanitizedPropertyId = ModelUtility_default.sanitizeGlslIdentifier(propertyId); if (sanitizedPropertyId === "" || classProperties.hasOwnProperty(sanitizedPropertyId)) { sanitizedPropertyId = `property_${nextPlaceholderId}`; nextPlaceholderId++; } const classProperty = transcodePropertyType(property); classProperty.name = propertyId; classProperties[sanitizedPropertyId] = classProperty; let customAttributeName = sanitizedPropertyId.toUpperCase(); if (!customAttributeName.startsWith("_")) { customAttributeName = `_${customAttributeName}`; } let attributeTypedArray = property.typedArray; if (!defined_default(attributeTypedArray)) { const binaryAccessor = getBinaryAccessor_default(property); attributeTypedArray = binaryAccessor.createArrayBufferView( binaryBody.buffer, binaryBody.byteOffset + property.byteOffset, featureCount ); } const attribute = new ModelComponents_default.Attribute(); attribute.name = customAttributeName; attribute.count = featureCount; attribute.type = property.type; const componentDatatype = ComponentDatatype_default.fromTypedArray(attributeTypedArray); if (componentDatatype === ComponentDatatype_default.INT || componentDatatype === ComponentDatatype_default.UNSIGNED_INT || componentDatatype === ComponentDatatype_default.DOUBLE) { parseBatchTable._oneTimeWarning( "Cast pnts property to floats", `Point cloud property "${customAttributeName}" will be cast to a float array because INT, UNSIGNED_INT, and DOUBLE are not valid WebGL vertex attribute types. Some precision may be lost.` ); attributeTypedArray = new Float32Array(attributeTypedArray); } attribute.componentDatatype = ComponentDatatype_default.fromTypedArray(attributeTypedArray); attribute.typedArray = attributeTypedArray; customAttributeOutput.push(attribute); propertyAttributeProperties[sanitizedPropertyId] = { attribute: customAttributeName }; } const schemaJson = { classes: {} }; schemaJson.classes[className] = { properties: classProperties }; const transcodedSchema = MetadataSchema_default.fromJson(schemaJson); const propertyAttributeJson = { properties: propertyAttributeProperties }; return { class: className, propertyAttributeJson, transcodedSchema, transcodedClass: transcodedSchema.classes[className] }; } function transcodePropertyType(property) { const componentType = transcodeComponentType(property.componentType); return { type: property.type, componentType }; } function transcodeComponentType(componentType) { switch (componentType) { case "BYTE": return "INT8"; case "UNSIGNED_BYTE": return "UINT8"; case "SHORT": return "INT16"; case "UNSIGNED_SHORT": return "UINT16"; case "INT": return "INT32"; case "UNSIGNED_INT": return "UINT32"; case "FLOAT": return "FLOAT32"; case "DOUBLE": return "FLOAT64"; } } parseBatchTable._deprecationWarning = deprecationWarning_default; parseBatchTable._oneTimeWarning = oneTimeWarning_default; var parseBatchTable_default = parseBatchTable; // packages/engine/Source/Scene/Model/B3dmLoader.js var B3dmLoaderState = { UNLOADED: 0, LOADING: 1, PROCESSING: 2, READY: 3, FAILED: 4 }; var FeatureIdAttribute3 = ModelComponents_default.FeatureIdAttribute; function B3dmLoader(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const b3dmResource = options.b3dmResource; let baseResource2 = options.baseResource; const arrayBuffer = options.arrayBuffer; const byteOffset = options.byteOffset ?? 0; const releaseGltfJson = options.releaseGltfJson ?? false; const asynchronous = options.asynchronous ?? true; const incrementallyLoadTextures = options.incrementallyLoadTextures ?? true; const upAxis = options.upAxis ?? Axis_default.Y; const forwardAxis = options.forwardAxis ?? Axis_default.X; const loadAttributesAsTypedArray = options.loadAttributesAsTypedArray ?? false; const loadAttributesFor2D = options.loadAttributesFor2D ?? false; const enablePick = options.enablePick ?? false; const loadIndicesForWireframe = options.loadIndicesForWireframe ?? false; const loadPrimitiveOutline2 = options.loadPrimitiveOutline ?? true; const loadForClassification = options.loadForClassification ?? false; Check_default.typeOf.object("options.b3dmResource", b3dmResource); Check_default.typeOf.object("options.arrayBuffer", arrayBuffer); baseResource2 = defined_default(baseResource2) ? baseResource2 : b3dmResource.clone(); this._b3dmResource = b3dmResource; this._baseResource = baseResource2; this._arrayBuffer = arrayBuffer; this._byteOffset = byteOffset; this._releaseGltfJson = releaseGltfJson; this._asynchronous = asynchronous; this._incrementallyLoadTextures = incrementallyLoadTextures; this._upAxis = upAxis; this._forwardAxis = forwardAxis; this._loadAttributesAsTypedArray = loadAttributesAsTypedArray; this._loadAttributesFor2D = loadAttributesFor2D; this._enablePick = enablePick; this._loadIndicesForWireframe = loadIndicesForWireframe; this._loadPrimitiveOutline = loadPrimitiveOutline2; this._loadForClassification = loadForClassification; this._state = B3dmLoaderState.UNLOADED; this._promise = void 0; this._gltfLoader = void 0; this._batchLength = 0; this._propertyTable = void 0; this._batchTable = void 0; this._components = void 0; this._transform = Matrix4_default.IDENTITY; } if (defined_default(Object.create)) { B3dmLoader.prototype = Object.create(ResourceLoader_default.prototype); B3dmLoader.prototype.constructor = B3dmLoader; } Object.defineProperties(B3dmLoader.prototype, { /** * true if textures are loaded, useful when incrementallyLoadTextures is true * * @memberof B3dmLoader.prototype * * @type {boolean} * @readonly * @private */ texturesLoaded: { get: function() { return this._gltfLoader?.texturesLoaded; } }, /** * The cache key of the resource * * @memberof B3dmLoader.prototype * * @type {string} * @readonly * @private */ cacheKey: { get: function() { return void 0; } }, /** * The loaded components. * * @memberof B3dmLoader.prototype * * @type {ModelComponents.Components} * @readonly * @private */ components: { get: function() { return this._components; } } }); B3dmLoader.prototype.load = function() { if (defined_default(this._promise)) { return this._promise; } const b3dm = B3dmParser_default.parse(this._arrayBuffer, this._byteOffset); let batchLength = b3dm.batchLength; const featureTableJson = b3dm.featureTableJson; const featureTableBinary = b3dm.featureTableBinary; const batchTableJson = b3dm.batchTableJson; const batchTableBinary = b3dm.batchTableBinary; const featureTable = new Cesium3DTileFeatureTable_default( featureTableJson, featureTableBinary ); batchLength = featureTable.getGlobalProperty("BATCH_LENGTH"); this._batchLength = batchLength; const rtcCenter = featureTable.getGlobalProperty( "RTC_CENTER", ComponentDatatype_default.FLOAT, 3 ); if (defined_default(rtcCenter)) { this._transform = Matrix4_default.fromTranslation(Cartesian3_default.fromArray(rtcCenter)); } this._batchTable = { json: batchTableJson, binary: batchTableBinary }; const gltfLoader = new GltfLoader_default({ typedArray: b3dm.gltf, upAxis: this._upAxis, forwardAxis: this._forwardAxis, gltfResource: this._b3dmResource, baseResource: this._baseResource, releaseGltfJson: this._releaseGltfJson, incrementallyLoadTextures: this._incrementallyLoadTextures, loadAttributesAsTypedArray: this._loadAttributesAsTypedArray, loadAttributesFor2D: this._loadAttributesFor2D, enablePick: this._enablePick, loadIndicesForWireframe: this._loadIndicesForWireframe, loadPrimitiveOutline: this._loadPrimitiveOutline, loadForClassification: this._loadForClassification, renameBatchIdSemantic: true }); this._gltfLoader = gltfLoader; this._state = B3dmLoaderState.LOADING; const that = this; this._promise = gltfLoader.load().then(function() { if (that.isDestroyed()) { return; } that._state = B3dmLoaderState.PROCESSING; return that; }).catch(function(error) { if (that.isDestroyed()) { return; } return handleError8(that, error); }); return this._promise; }; function handleError8(b3dmLoader, error) { b3dmLoader.unload(); b3dmLoader._state = B3dmLoaderState.FAILED; const errorMessage = "Failed to load b3dm"; error = b3dmLoader.getError(errorMessage, error); return Promise.reject(error); } B3dmLoader.prototype.process = function(frameState) { Check_default.typeOf.object("frameState", frameState); if (this._state === B3dmLoaderState.READY) { return true; } if (this._state !== B3dmLoaderState.PROCESSING) { return false; } const ready = this._gltfLoader.process(frameState); if (!ready) { return false; } const components = this._gltfLoader.components; components.transform = Matrix4_default.multiplyTransformation( this._transform, components.transform, components.transform ); createStructuralMetadata(this, components); this._components = components; this._arrayBuffer = void 0; this._state = B3dmLoaderState.READY; return true; }; function createStructuralMetadata(loader, components) { const batchTable = loader._batchTable; const batchLength = loader._batchLength; if (batchLength === 0) { return; } let structuralMetadata; if (defined_default(batchTable.json)) { structuralMetadata = parseBatchTable_default({ count: batchLength, batchTable: batchTable.json, binaryBody: batchTable.binary }); } else { const emptyPropertyTable = new PropertyTable_default({ name: MetadataClass_default.BATCH_TABLE_CLASS_NAME, count: batchLength }); structuralMetadata = new StructuralMetadata_default({ schema: {}, propertyTables: [emptyPropertyTable] }); } const nodes = components.scene.nodes; const length2 = nodes.length; for (let i = 0; i < length2; i++) { processNode(nodes[i]); } components.structuralMetadata = structuralMetadata; } function processNode(node) { const childrenLength = node.children.length; for (let i = 0; i < childrenLength; i++) { processNode(node.children[i]); } const primitivesLength = node.primitives.length; for (let i = 0; i < primitivesLength; i++) { const primitive = node.primitives[i]; const featureIdVertexAttribute = ModelUtility_default.getAttributeBySemantic( primitive, VertexAttributeSemantic_default.FEATURE_ID ); if (defined_default(featureIdVertexAttribute)) { featureIdVertexAttribute.setIndex = 0; const featureIdAttribute = new FeatureIdAttribute3(); featureIdAttribute.propertyTableId = 0; featureIdAttribute.setIndex = 0; featureIdAttribute.positionalLabel = "featureId_0"; primitive.featureIds.push(featureIdAttribute); } } } B3dmLoader.prototype.unload = function() { if (defined_default(this._gltfLoader) && !this._gltfLoader.isDestroyed()) { this._gltfLoader.unload(); } this._components = void 0; this._arrayBuffer = void 0; }; var B3dmLoader_default = B3dmLoader; // packages/engine/Source/Scene/Model/GeoJsonLoader.js var import_InlineWorkers585 = __toESM(require_InlineWorkers(), 1); function GeoJsonLoader(options) { options = options ?? Frozen_default.EMPTY_OBJECT; Check_default.typeOf.object("options.geoJson", options.geoJson); this._geoJson = options.geoJson; this._components = void 0; } if (defined_default(Object.create)) { GeoJsonLoader.prototype = Object.create(ResourceLoader_default.prototype); GeoJsonLoader.prototype.constructor = GeoJsonLoader; } Object.defineProperties(GeoJsonLoader.prototype, { /** * The cache key of the resource. * * @memberof GeoJsonLoader.prototype * * @type {string} * @readonly * @private */ cacheKey: { get: function() { return void 0; } }, /** * The loaded components. * * @memberof GeoJsonLoader.prototype * * @type {ModelComponents.Components} * @readonly * @private */ components: { get: function() { return this._components; } } }); GeoJsonLoader.prototype.load = function() { return Promise.resolve(this); }; GeoJsonLoader.prototype.process = function(frameState) { Check_default.typeOf.object("frameState", frameState); if (defined_default(this._components)) { return true; } this._components = parse2(this._geoJson, frameState); this._geoJson = void 0; return true; }; function ParsedFeature() { this.lines = void 0; this.points = void 0; this.properties = void 0; } function ParseResult() { this.features = []; } function parsePosition(position) { const x = position[0]; const y = position[1]; const z = position[2] ?? 0; return new Cartesian3_default(x, y, z); } function parseLineString(coordinates) { const positionsLength = coordinates.length; const line = new Array(positionsLength); for (let i = 0; i < positionsLength; i++) { line[i] = parsePosition(coordinates[i]); } const lines = [line]; return lines; } function parseMultiLineString(coordinates) { const linesLength = coordinates.length; const lines = new Array(linesLength); for (let i = 0; i < linesLength; i++) { lines[i] = parseLineString(coordinates[i])[0]; } return lines; } function parsePolygon(coordinates) { const linesLength = coordinates.length; const lines = new Array(linesLength); for (let i = 0; i < linesLength; i++) { lines[i] = parseLineString(coordinates[i])[0]; } return lines; } function parseMultiPolygon(coordinates) { const polygonsLength = coordinates.length; const lines = []; for (let i = 0; i < polygonsLength; i++) { const polygon2 = parsePolygon(coordinates[i]); addAllToArray_default(lines, polygon2); } return lines; } function parsePoint(coordinates) { return [parsePosition(coordinates)]; } function parseMultiPoint(coordinates) { const pointsLength = coordinates.length; const points = new Array(pointsLength); for (let i = 0; i < pointsLength; i++) { points[i] = parsePosition(coordinates[i]); } return points; } var geometryTypes = { LineString: parseLineString, MultiLineString: parseMultiLineString, MultiPolygon: parseMultiPolygon, Polygon: parsePolygon, MultiPoint: parseMultiPoint, Point: parsePoint }; var primitiveTypes = { LineString: PrimitiveType_default.LINES, MultiLineString: PrimitiveType_default.LINES, MultiPolygon: PrimitiveType_default.LINES, Polygon: PrimitiveType_default.LINES, MultiPoint: PrimitiveType_default.POINTS, Point: PrimitiveType_default.POINTS }; function parseFeature(feature2, result) { if (!defined_default(feature2.geometry)) { return; } const geometryType = feature2.geometry.type; const geometryFunction = geometryTypes[geometryType]; const primitiveType = primitiveTypes[geometryType]; const coordinates = feature2.geometry.coordinates; if (!defined_default(geometryFunction)) { return; } if (!defined_default(coordinates)) { return; } const parsedFeature = new ParsedFeature(); if (primitiveType === PrimitiveType_default.LINES) { parsedFeature.lines = geometryFunction(coordinates); } else if (primitiveType === PrimitiveType_default.POINTS) { parsedFeature.points = geometryFunction(coordinates); } parsedFeature.properties = feature2.properties; result.features.push(parsedFeature); } function parseFeatureCollection(featureCollection, result) { const features = featureCollection.features; const featuresLength = features.length; for (let i = 0; i < featuresLength; i++) { parseFeature(features[i], result); } } var geoJsonObjectTypes = { FeatureCollection: parseFeatureCollection, Feature: parseFeature }; var scratchCartesian9 = new Cartesian3_default(); function createLinesPrimitive(features, toLocal, frameState) { let vertexCount = 0; let indexCount = 0; const featureCount = features.length; for (let i = 0; i < featureCount; i++) { const feature2 = features[i]; if (defined_default(feature2.lines)) { const linesLength = feature2.lines.length; for (let j = 0; j < linesLength; j++) { const line = feature2.lines[j]; vertexCount += line.length; indexCount += (line.length - 1) * 2; } } } const positionsTypedArray = new Float32Array(vertexCount * 3); const featureIdsTypedArray = new Float32Array(vertexCount); const indicesTypedArray = IndexDatatype_default.createTypedArray( vertexCount, indexCount ); const indexDatatype = IndexDatatype_default.fromTypedArray(indicesTypedArray); const localMin = new Cartesian3_default( Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY ); const localMax = new Cartesian3_default( Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY ); let vertexCounter = 0; let segmentCounter = 0; for (let i = 0; i < featureCount; i++) { const feature2 = features[i]; if (!defined_default(feature2.lines)) { continue; } const linesLength = feature2.lines.length; for (let j = 0; j < linesLength; j++) { const line = feature2.lines[j]; const positionsLength = line.length; for (let k = 0; k < positionsLength; k++) { const cartographic2 = line[k]; const globalCartesian = Cartesian3_default.fromDegrees( cartographic2.x, cartographic2.y, cartographic2.z, Ellipsoid_default.WGS84, scratchCartesian9 ); const localCartesian = Matrix4_default.multiplyByPoint( toLocal, globalCartesian, scratchCartesian9 ); Cartesian3_default.minimumByComponent(localMin, localCartesian, localMin); Cartesian3_default.maximumByComponent(localMax, localCartesian, localMax); Cartesian3_default.pack(localCartesian, positionsTypedArray, vertexCounter * 3); featureIdsTypedArray[vertexCounter] = i; if (k < positionsLength - 1) { indicesTypedArray[segmentCounter * 2] = vertexCounter; indicesTypedArray[segmentCounter * 2 + 1] = vertexCounter + 1; segmentCounter++; } vertexCounter++; } } } const positionBuffer = Buffer_default.createVertexBuffer({ typedArray: positionsTypedArray, context: frameState.context, usage: BufferUsage_default.STATIC_DRAW }); positionBuffer.vertexArrayDestroyable = false; const featureIdBuffer = Buffer_default.createVertexBuffer({ typedArray: featureIdsTypedArray, context: frameState.context, usage: BufferUsage_default.STATIC_DRAW }); featureIdBuffer.vertexArrayDestroyable = false; const indexBuffer = Buffer_default.createIndexBuffer({ typedArray: indicesTypedArray, context: frameState.context, usage: BufferUsage_default.STATIC_DRAW, indexDatatype }); indexBuffer.vertexArrayDestroyable = false; const positionAttribute = new ModelComponents_default.Attribute(); positionAttribute.semantic = VertexAttributeSemantic_default.POSITION; positionAttribute.componentDatatype = ComponentDatatype_default.FLOAT; positionAttribute.type = AttributeType_default.VEC3; positionAttribute.count = vertexCount; positionAttribute.min = localMin; positionAttribute.max = localMax; positionAttribute.buffer = positionBuffer; const featureIdAttribute = new ModelComponents_default.Attribute(); featureIdAttribute.semantic = VertexAttributeSemantic_default.FEATURE_ID; featureIdAttribute.setIndex = 0; featureIdAttribute.componentDatatype = ComponentDatatype_default.FLOAT; featureIdAttribute.type = AttributeType_default.SCALAR; featureIdAttribute.count = vertexCount; featureIdAttribute.buffer = featureIdBuffer; const attributes = [positionAttribute, featureIdAttribute]; const material = new ModelComponents_default.Material(); material.unlit = true; const indices = new ModelComponents_default.Indices(); indices.indexDatatype = indexDatatype; indices.count = indicesTypedArray.length; indices.buffer = indexBuffer; const featureId = new ModelComponents_default.FeatureIdAttribute(); featureId.featureCount = featureCount; featureId.propertyTableId = 0; featureId.setIndex = 0; featureId.positionalLabel = "featureId_0"; const featureIds = [featureId]; const primitive = new ModelComponents_default.Primitive(); primitive.attributes = attributes; primitive.indices = indices; primitive.featureIds = featureIds; primitive.primitiveType = PrimitiveType_default.LINES; primitive.material = material; return primitive; } function createPointsPrimitive(features, toLocal, frameState) { let vertexCount = 0; const featureCount = features.length; for (let i = 0; i < featureCount; i++) { const feature2 = features[i]; if (defined_default(feature2.points)) { vertexCount += feature2.points.length; } } const positionsTypedArray = new Float32Array(vertexCount * 3); const featureIdsTypedArray = new Float32Array(vertexCount); const localMin = new Cartesian3_default( Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY ); const localMax = new Cartesian3_default( Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY ); let vertexCounter = 0; for (let i = 0; i < featureCount; i++) { const feature2 = features[i]; if (!defined_default(feature2.points)) { continue; } const pointsLength = feature2.points.length; for (let j = 0; j < pointsLength; j++) { const cartographic2 = feature2.points[j]; const globalCartesian = Cartesian3_default.fromDegrees( cartographic2.x, cartographic2.y, cartographic2.z, Ellipsoid_default.WGS84, scratchCartesian9 ); const localCartesian = Matrix4_default.multiplyByPoint( toLocal, globalCartesian, scratchCartesian9 ); Cartesian3_default.minimumByComponent(localMin, localCartesian, localMin); Cartesian3_default.maximumByComponent(localMax, localCartesian, localMax); Cartesian3_default.pack(localCartesian, positionsTypedArray, vertexCounter * 3); featureIdsTypedArray[vertexCounter] = i; vertexCounter++; } } const positionBuffer = Buffer_default.createVertexBuffer({ typedArray: positionsTypedArray, context: frameState.context, usage: BufferUsage_default.STATIC_DRAW }); positionBuffer.vertexArrayDestroyable = false; const featureIdBuffer = Buffer_default.createVertexBuffer({ typedArray: featureIdsTypedArray, context: frameState.context, usage: BufferUsage_default.STATIC_DRAW }); featureIdBuffer.vertexArrayDestroyable = false; const positionAttribute = new ModelComponents_default.Attribute(); positionAttribute.semantic = VertexAttributeSemantic_default.POSITION; positionAttribute.componentDatatype = ComponentDatatype_default.FLOAT; positionAttribute.type = AttributeType_default.VEC3; positionAttribute.count = vertexCount; positionAttribute.min = localMin; positionAttribute.max = localMax; positionAttribute.buffer = positionBuffer; const featureIdAttribute = new ModelComponents_default.Attribute(); featureIdAttribute.semantic = VertexAttributeSemantic_default.FEATURE_ID; featureIdAttribute.setIndex = 0; featureIdAttribute.componentDatatype = ComponentDatatype_default.FLOAT; featureIdAttribute.type = AttributeType_default.SCALAR; featureIdAttribute.count = vertexCount; featureIdAttribute.buffer = featureIdBuffer; const attributes = [positionAttribute, featureIdAttribute]; const material = new ModelComponents_default.Material(); material.unlit = true; const featureId = new ModelComponents_default.FeatureIdAttribute(); featureId.featureCount = featureCount; featureId.propertyTableId = 0; featureId.setIndex = 0; featureId.positionalLabel = "featureId_0"; const featureIds = [featureId]; const primitive = new ModelComponents_default.Primitive(); primitive.attributes = attributes; primitive.featureIds = featureIds; primitive.primitiveType = PrimitiveType_default.POINTS; primitive.material = material; return primitive; } function parse2(geoJson, frameState) { const result = new ParseResult(); const parseFunction = geoJsonObjectTypes[geoJson.type]; if (defined_default(parseFunction)) { parseFunction(geoJson, result); } const features = result.features; const featureCount = features.length; if (featureCount === 0) { throw new RuntimeError_default("GeoJSON must have at least one feature"); } const properties = {}; for (let i = 0; i < featureCount; i++) { const feature2 = features[i]; const featureProperties = feature2.properties ?? Frozen_default.EMPTY_OBJECT; for (const propertyId in featureProperties) { if (featureProperties.hasOwnProperty(propertyId)) { if (!defined_default(properties[propertyId])) { properties[propertyId] = new Array(featureCount); } } } } for (let i = 0; i < featureCount; i++) { const feature2 = features[i]; for (const propertyId in properties) { if (properties.hasOwnProperty(propertyId)) { const value = feature2.properties[propertyId] ?? ""; properties[propertyId][i] = value; } } } const jsonMetadataTable = new JsonMetadataTable_default({ count: featureCount, properties }); const propertyTable = new PropertyTable_default({ id: 0, count: featureCount, jsonMetadataTable }); const propertyTables = [propertyTable]; const schema = MetadataSchema_default.fromJson({}); const structuralMetadata = new StructuralMetadata_default({ schema, propertyTables }); const cartographicMin = new Cartesian3_default( Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY ); const cartographicMax = new Cartesian3_default( Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY ); let hasLines = false; let hasPoints = false; for (let i = 0; i < featureCount; i++) { const feature2 = features[i]; if (defined_default(feature2.lines)) { hasLines = true; const linesLength = feature2.lines.length; for (let j = 0; j < linesLength; j++) { const line = feature2.lines[j]; const positionsLength = line.length; for (let k = 0; k < positionsLength; k++) { Cartesian3_default.minimumByComponent( cartographicMin, line[k], cartographicMin ); Cartesian3_default.maximumByComponent( cartographicMax, line[k], cartographicMax ); } } } if (defined_default(feature2.points)) { hasPoints = true; const pointsLength = feature2.points.length; for (let j = 0; j < pointsLength; j++) { const point = feature2.points[j]; Cartesian3_default.minimumByComponent(cartographicMin, point, cartographicMin); Cartesian3_default.maximumByComponent(cartographicMax, point, cartographicMax); } } } const cartographicCenter = Cartesian3_default.midpoint( cartographicMin, cartographicMax, new Cartesian3_default() ); const ecefCenter = Cartesian3_default.fromDegrees( cartographicCenter.x, cartographicCenter.y, cartographicCenter.z, Ellipsoid_default.WGS84, new Cartesian3_default() ); const toGlobal = Transforms_default.eastNorthUpToFixedFrame( ecefCenter, Ellipsoid_default.WGS84, new Matrix4_default() ); const toLocal = Matrix4_default.inverseTransformation(toGlobal, new Matrix4_default()); const primitives = []; if (hasLines) { primitives.push(createLinesPrimitive(features, toLocal, frameState)); } if (hasPoints) { primitives.push(createPointsPrimitive(features, toLocal, frameState)); } const node = new ModelComponents_default.Node(); node.index = 0; node.primitives = primitives; const nodes = [node]; const scene = new ModelComponents_default.Scene(); scene.nodes = nodes; const components = new ModelComponents_default.Components(); components.scene = scene; components.nodes = nodes; components.transform = toGlobal; components.structuralMetadata = structuralMetadata; return components; } GeoJsonLoader.prototype.unload = function() { this._components = void 0; }; var GeoJsonLoader_default = GeoJsonLoader; // packages/engine/Source/Scene/Model/I3dmLoader.js var import_InlineWorkers587 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/I3dmParser.js var import_InlineWorkers586 = __toESM(require_InlineWorkers(), 1); var I3dmParser = {}; I3dmParser._deprecationWarning = deprecationWarning_default; var sizeOfUint325 = Uint32Array.BYTES_PER_ELEMENT; I3dmParser.parse = function(arrayBuffer, byteOffset) { Check_default.defined("arrayBuffer", arrayBuffer); const byteStart = byteOffset ?? 0; byteOffset = byteStart; const uint8Array = new Uint8Array(arrayBuffer); const view = new DataView(arrayBuffer); byteOffset += sizeOfUint325; const version2 = view.getUint32(byteOffset, true); if (version2 !== 1) { throw new RuntimeError_default( `Only Instanced 3D Model version 1 is supported. Version ${version2} is not.` ); } byteOffset += sizeOfUint325; const byteLength = view.getUint32(byteOffset, true); byteOffset += sizeOfUint325; const featureTableJsonByteLength = view.getUint32(byteOffset, true); if (featureTableJsonByteLength === 0) { throw new RuntimeError_default( "featureTableJsonByteLength is zero, the feature table must be defined." ); } byteOffset += sizeOfUint325; const featureTableBinaryByteLength = view.getUint32(byteOffset, true); byteOffset += sizeOfUint325; const batchTableJsonByteLength = view.getUint32(byteOffset, true); byteOffset += sizeOfUint325; const batchTableBinaryByteLength = view.getUint32(byteOffset, true); byteOffset += sizeOfUint325; const gltfFormat = view.getUint32(byteOffset, true); if (gltfFormat !== 1 && gltfFormat !== 0) { throw new RuntimeError_default( `Only glTF format 0 (uri) or 1 (embedded) are supported. Format ${gltfFormat} is not.` ); } byteOffset += sizeOfUint325; const featureTableJson = getJsonFromTypedArray_default( uint8Array, byteOffset, featureTableJsonByteLength ); byteOffset += featureTableJsonByteLength; const featureTableBinary = new Uint8Array( arrayBuffer, byteOffset, featureTableBinaryByteLength ); byteOffset += featureTableBinaryByteLength; let batchTableJson; let batchTableBinary; if (batchTableJsonByteLength > 0) { batchTableJson = getJsonFromTypedArray_default( uint8Array, byteOffset, batchTableJsonByteLength ); byteOffset += batchTableJsonByteLength; if (batchTableBinaryByteLength > 0) { batchTableBinary = new Uint8Array( arrayBuffer, byteOffset, batchTableBinaryByteLength ); batchTableBinary = new Uint8Array(batchTableBinary); byteOffset += batchTableBinaryByteLength; } } const gltfByteLength = byteStart + byteLength - byteOffset; if (gltfByteLength === 0) { throw new RuntimeError_default("glTF byte length must be greater than 0."); } let gltfView; if (byteOffset % 4 === 0) { gltfView = new Uint8Array(arrayBuffer, byteOffset, gltfByteLength); } else { I3dmParser._deprecationWarning( "i3dm-glb-unaligned", "The embedded glb is not aligned to a 4-byte boundary." ); gltfView = new Uint8Array( uint8Array.subarray(byteOffset, byteOffset + gltfByteLength) ); } return { gltfFormat, featureTableJson, featureTableBinary, batchTableJson, batchTableBinary, gltf: gltfView }; }; var I3dmParser_default = I3dmParser; // packages/engine/Source/Scene/Model/I3dmLoader.js var I3dmLoaderState = { NOT_LOADED: 0, LOADING: 1, PROCESSING: 2, POST_PROCESSING: 3, READY: 4, FAILED: 5, UNLOADED: 6 }; var Attribute3 = ModelComponents_default.Attribute; var FeatureIdAttribute4 = ModelComponents_default.FeatureIdAttribute; var Instances3 = ModelComponents_default.Instances; function I3dmLoader(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const i3dmResource = options.i3dmResource; const arrayBuffer = options.arrayBuffer; let baseResource2 = options.baseResource; const byteOffset = options.byteOffset ?? 0; const releaseGltfJson = options.releaseGltfJson ?? false; const asynchronous = options.asynchronous ?? true; const incrementallyLoadTextures = options.incrementallyLoadTextures ?? true; const upAxis = options.upAxis ?? Axis_default.Y; const forwardAxis = options.forwardAxis ?? Axis_default.X; const loadAttributesAsTypedArray = options.loadAttributesAsTypedArray ?? false; const loadIndicesForWireframe = options.loadIndicesForWireframe ?? false; const loadPrimitiveOutline2 = options.loadPrimitiveOutline ?? true; const enablePick = options.enablePick ?? false; Check_default.typeOf.object("options.i3dmResource", i3dmResource); Check_default.typeOf.object("options.arrayBuffer", arrayBuffer); baseResource2 = defined_default(baseResource2) ? baseResource2 : i3dmResource.clone(); this._i3dmResource = i3dmResource; this._baseResource = baseResource2; this._arrayBuffer = arrayBuffer; this._byteOffset = byteOffset; this._releaseGltfJson = releaseGltfJson; this._asynchronous = asynchronous; this._incrementallyLoadTextures = incrementallyLoadTextures; this._upAxis = upAxis; this._forwardAxis = forwardAxis; this._loadAttributesAsTypedArray = loadAttributesAsTypedArray; this._loadIndicesForWireframe = loadIndicesForWireframe; this._loadPrimitiveOutline = loadPrimitiveOutline2; this._enablePick = enablePick; this._state = I3dmLoaderState.NOT_LOADED; this._promise = void 0; this._gltfLoader = void 0; this._buffers = []; this._components = void 0; this._transform = Matrix4_default.IDENTITY; this._batchTable = void 0; this._featureTable = void 0; this._instancesLength = 0; } if (defined_default(Object.create)) { I3dmLoader.prototype = Object.create(ResourceLoader_default.prototype); I3dmLoader.prototype.constructor = I3dmLoader; } Object.defineProperties(I3dmLoader.prototype, { /** * true if textures are loaded, useful when incrementallyLoadTextures is true * * @memberof I3dmLoader.prototype * * @type {boolean} * @readonly * @private */ texturesLoaded: { get: function() { return this._gltfLoader?.texturesLoaded; } }, /** * The cache key of the resource * * @memberof I3dmLoader.prototype * * @type {string} * @readonly * @private */ cacheKey: { get: function() { return void 0; } }, /** * The loaded components. * * @memberof I3dmLoader.prototype * * @type {ModelComponents.Components} * @default {@link Matrix4.IDENTITY} * @readonly * @private */ components: { get: function() { return this._components; } } }); I3dmLoader.prototype.load = function() { if (defined_default(this._promise)) { return this._promise; } const i3dm = I3dmParser_default.parse(this._arrayBuffer, this._byteOffset); const featureTableJson = i3dm.featureTableJson; const featureTableBinary = i3dm.featureTableBinary; const batchTableJson = i3dm.batchTableJson; const batchTableBinary = i3dm.batchTableBinary; const gltfFormat = i3dm.gltfFormat; const featureTable = new Cesium3DTileFeatureTable_default( featureTableJson, featureTableBinary ); this._featureTable = featureTable; const instancesLength = featureTable.getGlobalProperty("INSTANCES_LENGTH"); featureTable.featuresLength = instancesLength; if (!defined_default(instancesLength)) { throw new RuntimeError_default( "Feature table global property: INSTANCES_LENGTH must be defined" ); } this._instancesLength = instancesLength; const rtcCenter = featureTable.getGlobalProperty( "RTC_CENTER", ComponentDatatype_default.FLOAT, 3 ); if (defined_default(rtcCenter)) { this._transform = Matrix4_default.fromTranslation(Cartesian3_default.fromArray(rtcCenter)); } this._batchTable = { json: batchTableJson, binary: batchTableBinary }; const loaderOptions = { upAxis: this._upAxis, forwardAxis: this._forwardAxis, releaseGltfJson: this._releaseGltfJson, incrementallyLoadTextures: this._incrementallyLoadTextures, loadAttributesAsTypedArray: this._loadAttributesAsTypedArray, enablePick: this._enablePick, loadIndicesForWireframe: this._loadIndicesForWireframe, loadPrimitiveOutline: this._loadPrimitiveOutline }; if (gltfFormat === 0) { let gltfUrl = getStringFromTypedArray_default(i3dm.gltf); gltfUrl = gltfUrl.replace(/[\s\0]+$/, ""); const gltfResource = this._baseResource.getDerivedResource({ url: gltfUrl }); loaderOptions.gltfResource = gltfResource; loaderOptions.baseResource = gltfResource; } else { loaderOptions.gltfResource = this._i3dmResource; loaderOptions.typedArray = i3dm.gltf; } const gltfLoader = new GltfLoader_default(loaderOptions); this._gltfLoader = gltfLoader; this._state = I3dmLoaderState.LOADING; this._promise = gltfLoader.load().then(() => { if (this.isDestroyed()) { return; } this._state = I3dmLoaderState.PROCESSING; return this; }).catch((error) => { if (this.isDestroyed()) { return; } throw handleError9(this, error); }); return this._promise; }; function handleError9(i3dmLoader, error) { i3dmLoader.unload(); i3dmLoader._state = I3dmLoaderState.FAILED; const errorMessage = "Failed to load i3dm"; return i3dmLoader.getError(errorMessage, error); } I3dmLoader.prototype.process = function(frameState) { Check_default.typeOf.object("frameState", frameState); if (this._state === I3dmLoaderState.READY) { return true; } const gltfLoader = this._gltfLoader; let ready = false; if (this._state === I3dmLoaderState.PROCESSING) { ready = gltfLoader.process(frameState); } if (!ready) { return false; } const components = gltfLoader.components; components.transform = Matrix4_default.multiplyTransformation( this._transform, components.transform, components.transform ); createInstances(this, components, frameState); createStructuralMetadata2(this, components); this._components = components; this._arrayBuffer = void 0; this._state = I3dmLoaderState.READY; return true; }; function createStructuralMetadata2(loader, components) { const batchTable = loader._batchTable; const instancesLength = loader._instancesLength; if (instancesLength === 0) { return; } let structuralMetadata; if (defined_default(batchTable.json)) { structuralMetadata = parseBatchTable_default({ count: instancesLength, batchTable: batchTable.json, binaryBody: batchTable.binary }); } else { const emptyPropertyTable = new PropertyTable_default({ name: MetadataClass_default.BATCH_TABLE_CLASS_NAME, count: instancesLength }); structuralMetadata = new StructuralMetadata_default({ schema: {}, propertyTables: [emptyPropertyTable] }); } components.structuralMetadata = structuralMetadata; } var positionScratch4 = new Cartesian3_default(); var propertyScratch1 = new Array(4); var transformScratch = new Matrix4_default(); function createInstances(loader, components, frameState) { let i; const featureTable = loader._featureTable; const instancesLength = loader._instancesLength; if (instancesLength === 0) { return; } const rtcCenter = featureTable.getGlobalProperty( "RTC_CENTER", ComponentDatatype_default.FLOAT, 3 ); const eastNorthUp = featureTable.getGlobalProperty("EAST_NORTH_UP"); const hasRotation = featureTable.hasProperty("NORMAL_UP") || featureTable.hasProperty("NORMAL_UP_OCT32P") || eastNorthUp; const hasScale = featureTable.hasProperty("SCALE") || featureTable.hasProperty("SCALE_NON_UNIFORM"); const translationTypedArray = getPositions(featureTable, instancesLength); let rotationTypedArray; if (hasRotation) { rotationTypedArray = new Float32Array(4 * instancesLength); } let scaleTypedArray; if (hasScale) { scaleTypedArray = new Float32Array(3 * instancesLength); } const featureIdArray = new Float32Array(instancesLength); const instancePositions = Cartesian3_default.unpackArray(translationTypedArray); let instancePosition = new Cartesian3_default(); const instanceNormalRight = new Cartesian3_default(); const instanceNormalUp = new Cartesian3_default(); const instanceNormalForward = new Cartesian3_default(); const instanceRotation = new Matrix3_default(); const instanceQuaternion = new Quaternion_default(); const instanceQuaternionArray = new Array(4); const instanceScale = new Cartesian3_default(); const instanceScaleArray = new Array(3); const instanceTransform = new Matrix4_default(); if (!defined_default(rtcCenter) || Cartesian3_default.equals(Cartesian3_default.unpack(rtcCenter), Cartesian3_default.ZERO)) { const positionBoundingSphere = BoundingSphere_default.fromPoints(instancePositions); for (i = 0; i < instancePositions.length; i++) { Cartesian3_default.subtract( instancePositions[i], positionBoundingSphere.center, positionScratch4 ); translationTypedArray[3 * i + 0] = positionScratch4.x; translationTypedArray[3 * i + 1] = positionScratch4.y; translationTypedArray[3 * i + 2] = positionScratch4.z; } const centerTransform = Matrix4_default.fromTranslation( positionBoundingSphere.center, transformScratch ); components.transform = Matrix4_default.multiplyTransformation( centerTransform, components.transform, components.transform ); } for (i = 0; i < instancesLength; i++) { instancePosition = Cartesian3_default.clone(instancePositions[i]); if (defined_default(rtcCenter)) { Cartesian3_default.add( instancePosition, Cartesian3_default.unpack(rtcCenter), instancePosition ); } if (hasRotation) { processRotation( featureTable, eastNorthUp, i, instanceQuaternion, instancePosition, instanceNormalUp, instanceNormalRight, instanceNormalForward, instanceRotation, instanceTransform ); Quaternion_default.pack(instanceQuaternion, instanceQuaternionArray, 0); rotationTypedArray[4 * i + 0] = instanceQuaternionArray[0]; rotationTypedArray[4 * i + 1] = instanceQuaternionArray[1]; rotationTypedArray[4 * i + 2] = instanceQuaternionArray[2]; rotationTypedArray[4 * i + 3] = instanceQuaternionArray[3]; } if (hasScale) { processScale(featureTable, i, instanceScale); Cartesian3_default.pack(instanceScale, instanceScaleArray, 0); scaleTypedArray[3 * i + 0] = instanceScaleArray[0]; scaleTypedArray[3 * i + 1] = instanceScaleArray[1]; scaleTypedArray[3 * i + 2] = instanceScaleArray[2]; } let batchId = featureTable.getProperty( "BATCH_ID", ComponentDatatype_default.UNSIGNED_SHORT, 1, i ); if (!defined_default(batchId)) { batchId = i; } featureIdArray[i] = batchId; } const instances = new Instances3(); instances.transformInWorldSpace = true; const buffers = loader._buffers; const translationAttribute = new Attribute3(); translationAttribute.name = "Instance Translation"; translationAttribute.semantic = InstanceAttributeSemantic_default.TRANSLATION; translationAttribute.componentDatatype = ComponentDatatype_default.FLOAT; translationAttribute.type = AttributeType_default.VEC3; translationAttribute.count = instancesLength; translationAttribute.typedArray = translationTypedArray; if (!hasRotation) { const buffer3 = Buffer_default.createVertexBuffer({ context: frameState.context, typedArray: translationTypedArray, usage: BufferUsage_default.STATIC_DRAW }); buffer3.vertexArrayDestroyable = false; buffers.push(buffer3); translationAttribute.buffer = buffer3; } instances.attributes.push(translationAttribute); if (hasRotation) { const rotationAttribute = new Attribute3(); rotationAttribute.name = "Instance Rotation"; rotationAttribute.semantic = InstanceAttributeSemantic_default.ROTATION; rotationAttribute.componentDatatype = ComponentDatatype_default.FLOAT; rotationAttribute.type = AttributeType_default.VEC4; rotationAttribute.count = instancesLength; rotationAttribute.typedArray = rotationTypedArray; instances.attributes.push(rotationAttribute); } if (hasScale) { const scaleAttribute = new Attribute3(); scaleAttribute.name = "Instance Scale"; scaleAttribute.semantic = InstanceAttributeSemantic_default.SCALE; scaleAttribute.componentDatatype = ComponentDatatype_default.FLOAT; scaleAttribute.type = AttributeType_default.VEC3; scaleAttribute.count = instancesLength; if (hasRotation) { scaleAttribute.typedArray = scaleTypedArray; } else { const buffer3 = Buffer_default.createVertexBuffer({ context: frameState.context, typedArray: scaleTypedArray, usage: BufferUsage_default.STATIC_DRAW }); buffer3.vertexArrayDestroyable = false; buffers.push(buffer3); scaleAttribute.buffer = buffer3; } instances.attributes.push(scaleAttribute); } const featureIdAttribute = new Attribute3(); featureIdAttribute.name = "Instance Feature ID"; featureIdAttribute.setIndex = 0; featureIdAttribute.semantic = InstanceAttributeSemantic_default.FEATURE_ID; featureIdAttribute.componentDatatype = ComponentDatatype_default.FLOAT; featureIdAttribute.type = AttributeType_default.SCALAR; featureIdAttribute.count = instancesLength; const buffer2 = Buffer_default.createVertexBuffer({ context: frameState.context, typedArray: featureIdArray, usage: BufferUsage_default.STATIC_DRAW }); buffer2.vertexArrayDestroyable = false; buffers.push(buffer2); featureIdAttribute.buffer = buffer2; instances.attributes.push(featureIdAttribute); const featureIdInstanceAttribute = new FeatureIdAttribute4(); featureIdInstanceAttribute.propertyTableId = 0; featureIdInstanceAttribute.setIndex = 0; featureIdInstanceAttribute.positionalLabel = "instanceFeatureId_0"; instances.featureIds.push(featureIdInstanceAttribute); const nodes = components.nodes; const nodesLength = nodes.length; let makeInstancesCopy = false; for (i = 0; i < nodesLength; i++) { const node = nodes[i]; if (node.primitives.length > 0) { node.instances = makeInstancesCopy ? createInstancesCopy(instances) : instances; makeInstancesCopy = true; } } } function createInstancesCopy(instances) { const instancesCopy = new Instances3(); instancesCopy.transformInWorldSpace = instances.transformInWorldSpace; const attributes = instances.attributes; const attributesLength = attributes.length; for (let i = 0; i < attributesLength; i++) { const attributeCopy = clone_default(attributes[i], false); instancesCopy.attributes.push(attributeCopy); } instancesCopy.featureIds = instances.featureIds; return instancesCopy; } function getPositions(featureTable, instancesLength) { if (featureTable.hasProperty("POSITION")) { return featureTable.getPropertyArray( "POSITION", ComponentDatatype_default.FLOAT, 3 ); } else if (featureTable.hasProperty("POSITION_QUANTIZED")) { const quantizedPositions = featureTable.getPropertyArray( "POSITION_QUANTIZED", ComponentDatatype_default.UNSIGNED_SHORT, 3 ); const quantizedVolumeOffset = featureTable.getGlobalProperty( "QUANTIZED_VOLUME_OFFSET", ComponentDatatype_default.FLOAT, 3 ); if (!defined_default(quantizedVolumeOffset)) { throw new RuntimeError_default( "Global property: QUANTIZED_VOLUME_OFFSET must be defined for quantized positions." ); } const quantizedVolumeScale = featureTable.getGlobalProperty( "QUANTIZED_VOLUME_SCALE", ComponentDatatype_default.FLOAT, 3 ); if (!defined_default(quantizedVolumeScale)) { throw new RuntimeError_default( "Global property: QUANTIZED_VOLUME_SCALE must be defined for quantized positions." ); } const decodedPositions = new Float32Array(quantizedPositions.length); for (let i = 0; i < quantizedPositions.length / 3; i++) { for (let j = 0; j < 3; j++) { const index = 3 * i + j; decodedPositions[index] = quantizedPositions[index] / 65535 * quantizedVolumeScale[j] + quantizedVolumeOffset[j]; } } return decodedPositions; } else { throw new RuntimeError_default( "Either POSITION or POSITION_QUANTIZED must be defined for each instance." ); } } var propertyScratch2 = new Array(4); function processRotation(featureTable, eastNorthUp, i, instanceQuaternion, instancePosition, instanceNormalUp, instanceNormalRight, instanceNormalForward, instanceRotation, instanceTransform) { const normalUp = featureTable.getProperty( "NORMAL_UP", ComponentDatatype_default.FLOAT, 3, i, propertyScratch1 ); const normalRight = featureTable.getProperty( "NORMAL_RIGHT", ComponentDatatype_default.FLOAT, 3, i, propertyScratch2 ); let hasCustomOrientation = false; if (defined_default(normalUp)) { if (!defined_default(normalRight)) { throw new RuntimeError_default( "To define a custom orientation, both NORMAL_UP and NORMAL_RIGHT must be defined." ); } Cartesian3_default.unpack(normalUp, 0, instanceNormalUp); Cartesian3_default.unpack(normalRight, 0, instanceNormalRight); hasCustomOrientation = true; } else { const octNormalUp = featureTable.getProperty( "NORMAL_UP_OCT32P", ComponentDatatype_default.UNSIGNED_SHORT, 2, i, propertyScratch1 ); const octNormalRight = featureTable.getProperty( "NORMAL_RIGHT_OCT32P", ComponentDatatype_default.UNSIGNED_SHORT, 2, i, propertyScratch2 ); if (defined_default(octNormalUp)) { if (!defined_default(octNormalRight)) { throw new RuntimeError_default( "To define a custom orientation with oct-encoded vectors, both NORMAL_UP_OCT32P and NORMAL_RIGHT_OCT32P must be defined." ); } AttributeCompression_default.octDecodeInRange( octNormalUp[0], octNormalUp[1], 65535, instanceNormalUp ); AttributeCompression_default.octDecodeInRange( octNormalRight[0], octNormalRight[1], 65535, instanceNormalRight ); hasCustomOrientation = true; } else if (eastNorthUp) { Transforms_default.eastNorthUpToFixedFrame( instancePosition, Ellipsoid_default.WGS84, instanceTransform ); Matrix4_default.getMatrix3(instanceTransform, instanceRotation); } else { Matrix3_default.clone(Matrix3_default.IDENTITY, instanceRotation); } } if (hasCustomOrientation) { Cartesian3_default.cross( instanceNormalRight, instanceNormalUp, instanceNormalForward ); Cartesian3_default.normalize(instanceNormalForward, instanceNormalForward); Matrix3_default.setColumn( instanceRotation, 0, instanceNormalRight, instanceRotation ); Matrix3_default.setColumn(instanceRotation, 1, instanceNormalUp, instanceRotation); Matrix3_default.setColumn( instanceRotation, 2, instanceNormalForward, instanceRotation ); } Quaternion_default.fromRotationMatrix(instanceRotation, instanceQuaternion); } function processScale(featureTable, i, instanceScale) { instanceScale = Cartesian3_default.fromElements(1, 1, 1, instanceScale); const scale = featureTable.getProperty( "SCALE", ComponentDatatype_default.FLOAT, 1, i ); if (defined_default(scale)) { Cartesian3_default.multiplyByScalar(instanceScale, scale, instanceScale); } const nonUniformScale = featureTable.getProperty( "SCALE_NON_UNIFORM", ComponentDatatype_default.FLOAT, 3, i, propertyScratch1 ); if (defined_default(nonUniformScale)) { instanceScale.x *= nonUniformScale[0]; instanceScale.y *= nonUniformScale[1]; instanceScale.z *= nonUniformScale[2]; } } function unloadBuffers(loader) { const buffers = loader._buffers; const length2 = buffers.length; for (let i = 0; i < length2; i++) { const buffer2 = buffers[i]; if (!buffer2.isDestroyed()) { buffer2.destroy(); } } buffers.length = 0; } I3dmLoader.prototype.isUnloaded = function() { return this._state === I3dmLoaderState.UNLOADED; }; I3dmLoader.prototype.unload = function() { if (defined_default(this._gltfLoader) && !this._gltfLoader.isDestroyed()) { this._gltfLoader.unload(); } unloadBuffers(this); this._components = void 0; this._arrayBuffer = void 0; this._state = I3dmLoaderState.UNLOADED; }; var I3dmLoader_default = I3dmLoader; // packages/engine/Source/Scene/Model/ModelAnimationCollection.js var import_InlineWorkers598 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/Model/ModelAnimation.js var import_InlineWorkers597 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/ModelAnimationState.js var import_InlineWorkers588 = __toESM(require_InlineWorkers(), 1); var ModelAnimationState = { STOPPED: 0, ANIMATING: 1 }; var ModelAnimationState_default = Object.freeze(ModelAnimationState); // packages/engine/Source/Scene/Model/ModelAnimationChannel.js var import_InlineWorkers596 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Core/ConstantSpline.js var import_InlineWorkers590 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Core/Spline.js var import_InlineWorkers589 = __toESM(require_InlineWorkers(), 1); function Spline() { this.times = void 0; this.points = void 0; DeveloperError_default.throwInstantiationError(); } Spline.getPointType = function(point) { if (typeof point === "number") { return Number; } if (point instanceof Cartesian3_default) { return Cartesian3_default; } if (point instanceof Quaternion_default) { return Quaternion_default; } throw new DeveloperError_default( "point must be a Cartesian3, Quaternion, or number." ); }; Spline.prototype.evaluate = DeveloperError_default.throwInstantiationError; Spline.prototype.findTimeInterval = function(time, startIndex) { const times = this.times; const length2 = times.length; Check_default.typeOf.number("time", time); if (time < times[0] || time > times[length2 - 1]) { throw new DeveloperError_default("time is out of range."); } startIndex = startIndex ?? 0; if (time >= times[startIndex]) { if (startIndex + 1 < length2 && time < times[startIndex + 1]) { return startIndex; } else if (startIndex + 2 < length2 && time < times[startIndex + 2]) { return startIndex + 1; } } else if (startIndex - 1 >= 0 && time >= times[startIndex - 1]) { return startIndex - 1; } let i; if (time > times[startIndex]) { for (i = startIndex; i < length2 - 1; ++i) { if (time >= times[i] && time < times[i + 1]) { break; } } } else { for (i = startIndex - 1; i >= 0; --i) { if (time >= times[i] && time < times[i + 1]) { break; } } } if (i === length2 - 1) { i = length2 - 2; } return i; }; Spline.prototype.wrapTime = function(time) { Check_default.typeOf.number("time", time); const times = this.times; const timeEnd = times[times.length - 1]; const timeStart = times[0]; const timeStretch = timeEnd - timeStart; let divs; if (time < timeStart) { divs = Math.floor((timeStart - time) / timeStretch) + 1; time += divs * timeStretch; } if (time > timeEnd) { divs = Math.floor((time - timeEnd) / timeStretch) + 1; time -= divs * timeStretch; } return time; }; Spline.prototype.clampTime = function(time) { Check_default.typeOf.number("time", time); const times = this.times; return Math_default.clamp(time, times[0], times[times.length - 1]); }; var Spline_default = Spline; // packages/engine/Source/Core/ConstantSpline.js function ConstantSpline(value) { this._value = value; this._valueType = Spline_default.getPointType(value); } Object.defineProperties(ConstantSpline.prototype, { /** * The constant value that the spline evaluates to. * * @memberof ConstantSpline.prototype * * @type {number|Cartesian3|Quaternion} * @readonly */ value: { get: function() { return this._value; } } }); ConstantSpline.prototype.findTimeInterval = function(time) { throw new DeveloperError_default( "findTimeInterval cannot be called on a ConstantSpline." ); }; ConstantSpline.prototype.wrapTime = function(time) { Check_default.typeOf.number("time", time); return 0; }; ConstantSpline.prototype.clampTime = function(time) { Check_default.typeOf.number("time", time); return 0; }; ConstantSpline.prototype.evaluate = function(time, result) { Check_default.typeOf.number("time", time); const value = this._value; const ValueType = this._valueType; if (ValueType === Number) { return value; } return ValueType.clone(value, result); }; var ConstantSpline_default = ConstantSpline; // packages/engine/Source/Core/HermiteSpline.js var import_InlineWorkers593 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Core/LinearSpline.js var import_InlineWorkers591 = __toESM(require_InlineWorkers(), 1); function LinearSpline(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const points = options.points; const times = options.times; if (!defined_default(points) || !defined_default(times)) { throw new DeveloperError_default("points and times are required."); } if (points.length < 2) { throw new DeveloperError_default( "points.length must be greater than or equal to 2." ); } if (times.length !== points.length) { throw new DeveloperError_default("times.length must be equal to points.length."); } this._times = times; this._points = points; this._pointType = Spline_default.getPointType(points[0]); this._lastTimeIndex = 0; } Object.defineProperties(LinearSpline.prototype, { /** * An array of times for the control points. * * @memberof LinearSpline.prototype * * @type {number[]} * @readonly */ times: { get: function() { return this._times; } }, /** * An array of {@link Cartesian3} control points. * * @memberof LinearSpline.prototype * * @type {number[]|Cartesian3[]} * @readonly */ points: { get: function() { return this._points; } } }); LinearSpline.prototype.findTimeInterval = Spline_default.prototype.findTimeInterval; LinearSpline.prototype.wrapTime = Spline_default.prototype.wrapTime; LinearSpline.prototype.clampTime = Spline_default.prototype.clampTime; LinearSpline.prototype.evaluate = function(time, result) { const points = this.points; const times = this.times; const i = this._lastTimeIndex = this.findTimeInterval( time, this._lastTimeIndex ); const u3 = (time - times[i]) / (times[i + 1] - times[i]); const PointType = this._pointType; if (PointType === Number) { return (1 - u3) * points[i] + u3 * points[i + 1]; } if (!defined_default(result)) { result = new Cartesian3_default(); } return Cartesian3_default.lerp(points[i], points[i + 1], u3, result); }; var LinearSpline_default = LinearSpline; // packages/engine/Source/Core/TridiagonalSystemSolver.js var import_InlineWorkers592 = __toESM(require_InlineWorkers(), 1); var TridiagonalSystemSolver = {}; TridiagonalSystemSolver.solve = function(lower, diagonal, upper, right) { if (!defined_default(lower) || !(lower instanceof Array)) { throw new DeveloperError_default("The array lower is required."); } if (!defined_default(diagonal) || !(diagonal instanceof Array)) { throw new DeveloperError_default("The array diagonal is required."); } if (!defined_default(upper) || !(upper instanceof Array)) { throw new DeveloperError_default("The array upper is required."); } if (!defined_default(right) || !(right instanceof Array)) { throw new DeveloperError_default("The array right is required."); } if (diagonal.length !== right.length) { throw new DeveloperError_default("diagonal and right must have the same lengths."); } if (lower.length !== upper.length) { throw new DeveloperError_default("lower and upper must have the same lengths."); } else if (lower.length !== diagonal.length - 1) { throw new DeveloperError_default( "lower and upper must be one less than the length of diagonal." ); } const c = new Array(upper.length); const d = new Array(right.length); const x = new Array(right.length); let i; for (i = 0; i < d.length; i++) { d[i] = new Cartesian3_default(); x[i] = new Cartesian3_default(); } c[0] = upper[0] / diagonal[0]; d[0] = Cartesian3_default.multiplyByScalar(right[0], 1 / diagonal[0], d[0]); let scalar; for (i = 1; i < c.length; ++i) { scalar = 1 / (diagonal[i] - c[i - 1] * lower[i - 1]); c[i] = upper[i] * scalar; d[i] = Cartesian3_default.subtract( right[i], Cartesian3_default.multiplyByScalar(d[i - 1], lower[i - 1], d[i]), d[i] ); d[i] = Cartesian3_default.multiplyByScalar(d[i], scalar, d[i]); } scalar = 1 / (diagonal[i] - c[i - 1] * lower[i - 1]); d[i] = Cartesian3_default.subtract( right[i], Cartesian3_default.multiplyByScalar(d[i - 1], lower[i - 1], d[i]), d[i] ); d[i] = Cartesian3_default.multiplyByScalar(d[i], scalar, d[i]); x[x.length - 1] = d[d.length - 1]; for (i = x.length - 2; i >= 0; --i) { x[i] = Cartesian3_default.subtract( d[i], Cartesian3_default.multiplyByScalar(x[i + 1], c[i], x[i]), x[i] ); } return x; }; var TridiagonalSystemSolver_default = TridiagonalSystemSolver; // packages/engine/Source/Core/HermiteSpline.js var scratchLower = []; var scratchDiagonal = []; var scratchUpper = []; var scratchRight = []; function generateClamped(points, firstTangent, lastTangent) { const l = scratchLower; const u3 = scratchUpper; const d = scratchDiagonal; const r = scratchRight; l.length = u3.length = points.length - 1; d.length = r.length = points.length; let i; l[0] = d[0] = 1; u3[0] = 0; let right = r[0]; if (!defined_default(right)) { right = r[0] = new Cartesian3_default(); } Cartesian3_default.clone(firstTangent, right); for (i = 1; i < l.length - 1; ++i) { l[i] = u3[i] = 1; d[i] = 4; right = r[i]; if (!defined_default(right)) { right = r[i] = new Cartesian3_default(); } Cartesian3_default.subtract(points[i + 1], points[i - 1], right); Cartesian3_default.multiplyByScalar(right, 3, right); } l[i] = 0; u3[i] = 1; d[i] = 4; right = r[i]; if (!defined_default(right)) { right = r[i] = new Cartesian3_default(); } Cartesian3_default.subtract(points[i + 1], points[i - 1], right); Cartesian3_default.multiplyByScalar(right, 3, right); d[i + 1] = 1; right = r[i + 1]; if (!defined_default(right)) { right = r[i + 1] = new Cartesian3_default(); } Cartesian3_default.clone(lastTangent, right); return TridiagonalSystemSolver_default.solve(l, d, u3, r); } function generateNatural(points) { const l = scratchLower; const u3 = scratchUpper; const d = scratchDiagonal; const r = scratchRight; l.length = u3.length = points.length - 1; d.length = r.length = points.length; let i; l[0] = u3[0] = 1; d[0] = 2; let right = r[0]; if (!defined_default(right)) { right = r[0] = new Cartesian3_default(); } Cartesian3_default.subtract(points[1], points[0], right); Cartesian3_default.multiplyByScalar(right, 3, right); for (i = 1; i < l.length; ++i) { l[i] = u3[i] = 1; d[i] = 4; right = r[i]; if (!defined_default(right)) { right = r[i] = new Cartesian3_default(); } Cartesian3_default.subtract(points[i + 1], points[i - 1], right); Cartesian3_default.multiplyByScalar(right, 3, right); } d[i] = 2; right = r[i]; if (!defined_default(right)) { right = r[i] = new Cartesian3_default(); } Cartesian3_default.subtract(points[i], points[i - 1], right); Cartesian3_default.multiplyByScalar(right, 3, right); return TridiagonalSystemSolver_default.solve(l, d, u3, r); } function HermiteSpline(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const points = options.points; const times = options.times; const inTangents = options.inTangents; const outTangents = options.outTangents; if (!defined_default(points) || !defined_default(times) || !defined_default(inTangents) || !defined_default(outTangents)) { throw new DeveloperError_default( "times, points, inTangents, and outTangents are required." ); } if (points.length < 2) { throw new DeveloperError_default( "points.length must be greater than or equal to 2." ); } if (times.length !== points.length) { throw new DeveloperError_default("times.length must be equal to points.length."); } if (inTangents.length !== outTangents.length || inTangents.length !== points.length - 1) { throw new DeveloperError_default( "inTangents and outTangents must have a length equal to points.length - 1." ); } this._times = times; this._points = points; this._pointType = Spline_default.getPointType(points[0]); if (this._pointType !== Spline_default.getPointType(inTangents[0]) || this._pointType !== Spline_default.getPointType(outTangents[0])) { throw new DeveloperError_default( "inTangents and outTangents must be of the same type as points." ); } this._inTangents = inTangents; this._outTangents = outTangents; this._lastTimeIndex = 0; } Object.defineProperties(HermiteSpline.prototype, { /** * An array of times for the control points. * * @memberof HermiteSpline.prototype * * @type {number[]} * @readonly */ times: { get: function() { return this._times; } }, /** * An array of control points. * * @memberof HermiteSpline.prototype * * @type {Cartesian3[]} * @readonly */ points: { get: function() { return this._points; } }, /** * An array of incoming tangents at each control point. * * @memberof HermiteSpline.prototype * * @type {Cartesian3[]} * @readonly */ inTangents: { get: function() { return this._inTangents; } }, /** * An array of outgoing tangents at each control point. * * @memberof HermiteSpline.prototype * * @type {Cartesian3[]} * @readonly */ outTangents: { get: function() { return this._outTangents; } } }); HermiteSpline.createC1 = function(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const times = options.times; const points = options.points; const tangents = options.tangents; if (!defined_default(points) || !defined_default(times) || !defined_default(tangents)) { throw new DeveloperError_default("points, times and tangents are required."); } if (points.length < 2) { throw new DeveloperError_default( "points.length must be greater than or equal to 2." ); } if (times.length !== points.length || times.length !== tangents.length) { throw new DeveloperError_default( "times, points and tangents must have the same length." ); } const outTangents = tangents.slice(0, tangents.length - 1); const inTangents = tangents.slice(1, tangents.length); return new HermiteSpline({ times, points, inTangents, outTangents }); }; HermiteSpline.createNaturalCubic = function(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const times = options.times; const points = options.points; if (!defined_default(points) || !defined_default(times)) { throw new DeveloperError_default("points and times are required."); } if (points.length < 2) { throw new DeveloperError_default( "points.length must be greater than or equal to 2." ); } if (times.length !== points.length) { throw new DeveloperError_default("times.length must be equal to points.length."); } if (points.length < 3) { return new LinearSpline_default({ points, times }); } const tangents = generateNatural(points); const outTangents = tangents.slice(0, tangents.length - 1); const inTangents = tangents.slice(1, tangents.length); return new HermiteSpline({ times, points, inTangents, outTangents }); }; HermiteSpline.createClampedCubic = function(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const times = options.times; const points = options.points; const firstTangent = options.firstTangent; const lastTangent = options.lastTangent; if (!defined_default(points) || !defined_default(times) || !defined_default(firstTangent) || !defined_default(lastTangent)) { throw new DeveloperError_default( "points, times, firstTangent and lastTangent are required." ); } if (points.length < 2) { throw new DeveloperError_default( "points.length must be greater than or equal to 2." ); } if (times.length !== points.length) { throw new DeveloperError_default("times.length must be equal to points.length."); } const PointType = Spline_default.getPointType(points[0]); if (PointType !== Spline_default.getPointType(firstTangent) || PointType !== Spline_default.getPointType(lastTangent)) { throw new DeveloperError_default( "firstTangent and lastTangent must be of the same type as points." ); } if (points.length < 3) { return new LinearSpline_default({ points, times }); } const tangents = generateClamped(points, firstTangent, lastTangent); const outTangents = tangents.slice(0, tangents.length - 1); const inTangents = tangents.slice(1, tangents.length); return new HermiteSpline({ times, points, inTangents, outTangents }); }; HermiteSpline.hermiteCoefficientMatrix = new Matrix4_default( 2, -3, 0, 1, -2, 3, 0, 0, 1, -2, 1, 0, 1, -1, 0, 0 ); HermiteSpline.prototype.findTimeInterval = Spline_default.prototype.findTimeInterval; var scratchTimeVec = new Cartesian4_default(); var scratchTemp = new Cartesian3_default(); HermiteSpline.prototype.wrapTime = Spline_default.prototype.wrapTime; HermiteSpline.prototype.clampTime = Spline_default.prototype.clampTime; HermiteSpline.prototype.evaluate = function(time, result) { const points = this.points; const times = this.times; const inTangents = this.inTangents; const outTangents = this.outTangents; this._lastTimeIndex = this.findTimeInterval(time, this._lastTimeIndex); const i = this._lastTimeIndex; const timesDelta = times[i + 1] - times[i]; const u3 = (time - times[i]) / timesDelta; const timeVec = scratchTimeVec; timeVec.z = u3; timeVec.y = u3 * u3; timeVec.x = timeVec.y * u3; timeVec.w = 1; const coefs = Matrix4_default.multiplyByVector( HermiteSpline.hermiteCoefficientMatrix, timeVec, timeVec ); coefs.z *= timesDelta; coefs.w *= timesDelta; const PointType = this._pointType; if (PointType === Number) { return points[i] * coefs.x + points[i + 1] * coefs.y + outTangents[i] * coefs.z + inTangents[i] * coefs.w; } if (!defined_default(result)) { result = new PointType(); } result = PointType.multiplyByScalar(points[i], coefs.x, result); PointType.multiplyByScalar(points[i + 1], coefs.y, scratchTemp); PointType.add(result, scratchTemp, result); PointType.multiplyByScalar(outTangents[i], coefs.z, scratchTemp); PointType.add(result, scratchTemp, result); PointType.multiplyByScalar(inTangents[i], coefs.w, scratchTemp); return PointType.add(result, scratchTemp, result); }; var HermiteSpline_default = HermiteSpline; // packages/engine/Source/Core/SteppedSpline.js var import_InlineWorkers594 = __toESM(require_InlineWorkers(), 1); function SteppedSpline(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const points = options.points; const times = options.times; if (!defined_default(points) || !defined_default(times)) { throw new DeveloperError_default("points and times are required."); } if (points.length < 2) { throw new DeveloperError_default( "points.length must be greater than or equal to 2." ); } if (times.length !== points.length) { throw new DeveloperError_default("times.length must be equal to points.length."); } this._times = times; this._points = points; this._pointType = Spline_default.getPointType(points[0]); this._lastTimeIndex = 0; } Object.defineProperties(SteppedSpline.prototype, { /** * An array of times for the control points. * * @memberof SteppedSpline.prototype * * @type {number[]} * @readonly */ times: { get: function() { return this._times; } }, /** * An array of control points. * * @memberof SteppedSpline.prototype * * @type {number[]|Cartesian3[]|Quaternion[]} * @readonly */ points: { get: function() { return this._points; } } }); SteppedSpline.prototype.findTimeInterval = Spline_default.prototype.findTimeInterval; SteppedSpline.prototype.wrapTime = Spline_default.prototype.wrapTime; SteppedSpline.prototype.clampTime = Spline_default.prototype.clampTime; SteppedSpline.prototype.evaluate = function(time, result) { const points = this.points; this._lastTimeIndex = this.findTimeInterval(time, this._lastTimeIndex); const i = this._lastTimeIndex; const PointType = this._pointType; if (PointType === Number) { return points[i]; } if (!defined_default(result)) { result = new PointType(); } return PointType.clone(points[i], result); }; var SteppedSpline_default = SteppedSpline; // packages/engine/Source/Core/QuaternionSpline.js var import_InlineWorkers595 = __toESM(require_InlineWorkers(), 1); function createEvaluateFunction(spline) { const points = spline.points; const times = spline.times; return function(time, result) { if (!defined_default(result)) { result = new Quaternion_default(); } const i = spline._lastTimeIndex = spline.findTimeInterval( time, spline._lastTimeIndex ); const u3 = (time - times[i]) / (times[i + 1] - times[i]); const q0 = points[i]; const q12 = points[i + 1]; return Quaternion_default.fastSlerp(q0, q12, u3, result); }; } function QuaternionSpline(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const points = options.points; const times = options.times; if (!defined_default(points) || !defined_default(times)) { throw new DeveloperError_default("points and times are required."); } if (points.length < 2) { throw new DeveloperError_default( "points.length must be greater than or equal to 2." ); } if (times.length !== points.length) { throw new DeveloperError_default("times.length must be equal to points.length."); } this._times = times; this._points = points; this._evaluateFunction = createEvaluateFunction(this); this._lastTimeIndex = 0; } Object.defineProperties(QuaternionSpline.prototype, { /** * An array of times for the control points. * * @memberof QuaternionSpline.prototype * * @type {number[]} * @readonly */ times: { get: function() { return this._times; } }, /** * An array of {@link Quaternion} control points. * * @memberof QuaternionSpline.prototype * * @type {Quaternion[]} * @readonly */ points: { get: function() { return this._points; } } }); QuaternionSpline.prototype.findTimeInterval = Spline_default.prototype.findTimeInterval; QuaternionSpline.prototype.wrapTime = Spline_default.prototype.wrapTime; QuaternionSpline.prototype.clampTime = Spline_default.prototype.clampTime; QuaternionSpline.prototype.evaluate = function(time, result) { return this._evaluateFunction(time, result); }; var QuaternionSpline_default = QuaternionSpline; // packages/engine/Source/Scene/Model/ModelAnimationChannel.js var AnimatedPropertyType3 = ModelComponents_default.AnimatedPropertyType; function ModelAnimationChannel(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const channel = options.channel; const runtimeAnimation = options.runtimeAnimation; const runtimeNode = options.runtimeNode; Check_default.typeOf.object("options.channel", channel); Check_default.typeOf.object("options.runtimeAnimation", runtimeAnimation); Check_default.typeOf.object("options.runtimeNode", runtimeNode); this._channel = channel; this._runtimeAnimation = runtimeAnimation; this._runtimeNode = runtimeNode; this._splines = []; this._path = void 0; initialize6(this); } Object.defineProperties(ModelAnimationChannel.prototype, { /** * The glTF animation channel. * * @memberof ModelAnimationChannel.prototype * * @type {ModelComponents.AnimationChannel} * @readonly * * @private */ channel: { get: function() { return this._channel; } }, /** * The runtime animation that owns this channel. * * @memberof ModelAnimationChannel.prototype * * @type {ModelAnimation} * @readonly * * @private */ runtimeAnimation: { get: function() { return this._runtimeAnimation; } }, /** * The runtime node that this channel animates. * * @memberof ModelAnimationChannel.prototype * * @type {ModelRuntimeNode} * @readonly * * @private */ runtimeNode: { get: function() { return this._runtimeNode; } }, /** * The splines used to evaluate this animation channel. * * @memberof ModelAnimationChannel.prototype * * @type {Spline[]} * @readonly * * @private */ splines: { get: function() { return this._splines; } } }); function createCubicSpline(times, points) { const cubicPoints = []; const inTangents = []; const outTangents = []; const length2 = points.length; for (let i = 0; i < length2; i += 3) { inTangents.push(points[i]); cubicPoints.push(points[i + 1]); outTangents.push(points[i + 2]); } inTangents.splice(0, 1); outTangents.length = outTangents.length - 1; return new HermiteSpline_default({ times, points: cubicPoints, inTangents, outTangents }); } function createSpline(times, points, interpolation, path) { if (times.length === 1 && points.length === 1) { return new ConstantSpline_default(points[0]); } switch (interpolation) { case InterpolationType_default.STEP: return new SteppedSpline_default({ times, points }); case InterpolationType_default.CUBICSPLINE: return createCubicSpline(times, points); case InterpolationType_default.LINEAR: if (path === AnimatedPropertyType3.ROTATION) { return new QuaternionSpline_default({ times, points }); } return new LinearSpline_default({ times, points }); } } function createSplines(times, points, interpolation, path, count) { const splines = []; if (path === AnimatedPropertyType3.WEIGHTS) { const pointsLength = points.length; const outputLength = pointsLength / count; let targetIndex, i; for (targetIndex = 0; targetIndex < count; targetIndex++) { const output = new Array(outputLength); let pointsIndex = targetIndex; if (interpolation === InterpolationType_default.CUBICSPLINE) { for (i = 0; i < outputLength; i += 3) { output[i] = points[pointsIndex]; output[i + 1] = points[pointsIndex + count]; output[i + 2] = points[pointsIndex + 2 * count]; pointsIndex += count * 3; } } else { for (i = 0; i < outputLength; i++) { output[i] = points[pointsIndex]; pointsIndex += count; } } splines.push(createSpline(times, output, interpolation, path)); } } else { splines.push(createSpline(times, points, interpolation, path)); } return splines; } var scratchCartesian35 = new Cartesian3_default(); var scratchQuaternion = new Quaternion_default(); function initialize6(runtimeChannel) { const channel = runtimeChannel._channel; const sampler = channel.sampler; const times = sampler.input; const points = sampler.output; const interpolation = sampler.interpolation; const target = channel.target; const path = target.path; const runtimeNode = runtimeChannel._runtimeNode; const count = defined_default(runtimeNode.morphWeights) ? runtimeNode.morphWeights.length : 1; const splines = createSplines(times, points, interpolation, path, count); runtimeChannel._splines = splines; runtimeChannel._path = path; } ModelAnimationChannel.prototype.animate = function(time) { const splines = this._splines; const path = this._path; const model = this._runtimeAnimation.model; const runtimeNode = this._runtimeNode; if (path === AnimatedPropertyType3.WEIGHTS) { const morphWeights = runtimeNode.morphWeights; const length2 = morphWeights.length; for (let i = 0; i < length2; i++) { const spline = splines[i]; const localAnimationTime = model.clampAnimations ? spline.clampTime(time) : spline.wrapTime(time); morphWeights[i] = spline.evaluate(localAnimationTime); } } else if (runtimeNode.userAnimated) { return; } else { const spline = splines[0]; const localAnimationTime = model.clampAnimations ? spline.clampTime(time) : spline.wrapTime(time); if (path === AnimatedPropertyType3.TRANSLATION || path === AnimatedPropertyType3.SCALE) { runtimeNode[path] = spline.evaluate( localAnimationTime, scratchCartesian35 ); } else if (path === AnimatedPropertyType3.ROTATION) { runtimeNode[path] = spline.evaluate( localAnimationTime, scratchQuaternion ); } } }; var ModelAnimationChannel_default = ModelAnimationChannel; // packages/engine/Source/Scene/Model/ModelAnimation.js function ModelAnimation(model, animation, options) { this._animation = animation; this._name = animation.name; this._runtimeChannels = void 0; this._startTime = JulianDate_default.clone(options.startTime); this._delay = options.delay ?? 0; this._stopTime = JulianDate_default.clone(options.stopTime); this.removeOnStop = options.removeOnStop ?? false; this._multiplier = options.multiplier ?? 1; this._reverse = options.reverse ?? false; this._loop = options.loop ?? ModelAnimationLoop_default.NONE; this._animationTime = options.animationTime; this._prevAnimationDelta = void 0; this.start = new Event_default(); this.update = new Event_default(); this.stop = new Event_default(); this._state = ModelAnimationState_default.STOPPED; this._computedStartTime = void 0; this._duration = void 0; const that = this; this._raiseStartEvent = function() { that.start.raiseEvent(model, that); }; this._updateEventTime = 0; this._raiseUpdateEvent = function() { that.update.raiseEvent(model, that, that._updateEventTime); }; this._raiseStopEvent = function() { that.stop.raiseEvent(model, that); }; this._model = model; this._localStartTime = void 0; this._localStopTime = void 0; initialize7(this); } Object.defineProperties(ModelAnimation.prototype, { /** * The glTF animation. * * @memberof ModelAnimation.prototype * * @type {ModelComponents.Animation} * @readonly * * @private */ animation: { get: function() { return this._animation; } }, /** * The name that identifies this animation in the model, if it exists. * * @memberof ModelAnimation.prototype * * @type {string} * @readonly */ name: { get: function() { return this._name; } }, /** * The runtime animation channels for this animation. * * @memberof ModelAnimation.prototype * * @type {ModelAnimationChannel[]} * @readonly * * @private */ runtimeChannels: { get: function() { return this._runtimeChannels; } }, /** * The {@link Model} that owns this animation. * * @memberof ModelAnimation.prototype * * @type {Model} * @readonly * * @private */ model: { get: function() { return this._model; } }, /** * The starting point of the animation in local animation time. This is the minimum * time value across all of the keyframes belonging to this animation. * * @memberof ModelAnimation.prototype * * @type {number} * @readonly * * @private */ localStartTime: { get: function() { return this._localStartTime; } }, /** * The stopping point of the animation in local animation time. This is the maximum * time value across all of the keyframes belonging to this animation. * * @memberof ModelAnimation.prototype * * @type {number} * @readonly * * @private */ localStopTime: { get: function() { return this._localStopTime; } }, /** * The scene time to start playing this animation. When this isundefined,
* the animation starts at the next frame.
*
* @memberof ModelAnimation.prototype
*
* @type {JulianDate}
* @readonly
*
* @default undefined
*/
startTime: {
get: function() {
return this._startTime;
}
},
/**
* The delay, in seconds, from {@link ModelAnimation#startTime} to start playing.
*
* @memberof ModelAnimation.prototype
*
* @type {number}
* @readonly
*
* @default undefined
*/
delay: {
get: function() {
return this._delay;
}
},
/**
* The scene time to stop playing this animation. When this is undefined,
* the animation is played for its full duration and perhaps repeated depending on
* {@link ModelAnimation#loop}.
*
* @memberof ModelAnimation.prototype
*
* @type {JulianDate}
* @readonly
*
* @default undefined
*/
stopTime: {
get: function() {
return this._stopTime;
}
},
/**
* Values greater than 1.0 increase the speed that the animation is played relative
* to the scene clock speed; values less than 1.0 decrease the speed. A value of
* 1.0 plays the animation at the speed in the glTF animation mapped to the scene
* clock speed. For example, if the scene is played at 2x real-time, a two-second glTF animation
* will play in one second even if multiplier is 1.0.
*
* @memberof ModelAnimation.prototype
*
* @type {number}
* @readonly
*
* @default 1.0
*/
multiplier: {
get: function() {
return this._multiplier;
}
},
/**
* When true, the animation is played in reverse.
*
* @memberof ModelAnimation.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
reverse: {
get: function() {
return this._reverse;
}
},
/**
* Determines if and how the animation is looped.
*
* @memberof ModelAnimation.prototype
*
* @type {ModelAnimationLoop}
* @readonly
*
* @default {@link ModelAnimationLoop.NONE}
*/
loop: {
get: function() {
return this._loop;
}
},
/**
* If this is defined, it will be used to compute the local animation time
* instead of the scene's time.
*
* @memberof ModelAnimation.prototype
*
* @type {ModelAnimation.AnimationTimeCallback}
* @default undefined
*/
animationTime: {
get: function() {
return this._animationTime;
}
}
});
function initialize7(runtimeAnimation) {
let localStartTime = Number.MAX_VALUE;
let localStopTime = -Number.MAX_VALUE;
const sceneGraph = runtimeAnimation._model.sceneGraph;
const animation = runtimeAnimation._animation;
const channels = animation.channels;
const length2 = channels.length;
const runtimeChannels = [];
for (let i = 0; i < length2; i++) {
const channel = channels[i];
const target = channel.target;
if (!defined_default(target)) {
continue;
}
const nodeIndex = target.node.index;
const runtimeNode = sceneGraph._runtimeNodes[nodeIndex];
const runtimeChannel = new ModelAnimationChannel_default({
channel,
runtimeAnimation,
runtimeNode
});
const times = channel.sampler.input;
localStartTime = Math.min(localStartTime, times[0]);
localStopTime = Math.max(localStopTime, times[times.length - 1]);
runtimeChannels.push(runtimeChannel);
}
runtimeAnimation._runtimeChannels = runtimeChannels;
runtimeAnimation._localStartTime = localStartTime;
runtimeAnimation._localStopTime = localStopTime;
}
ModelAnimation.prototype.animate = function(time) {
const runtimeChannels = this._runtimeChannels;
const length2 = runtimeChannels.length;
for (let i = 0; i < length2; i++) {
runtimeChannels[i].animate(time);
}
};
var ModelAnimation_default = ModelAnimation;
// packages/engine/Source/Scene/Model/ModelAnimationCollection.js
function ModelAnimationCollection(model) {
this.animationAdded = new Event_default();
this.animationRemoved = new Event_default();
this.animateWhilePaused = false;
this._model = model;
this._runtimeAnimations = [];
this._previousTime = void 0;
}
Object.defineProperties(ModelAnimationCollection.prototype, {
/**
* The number of animations in the collection.
*
* @memberof ModelAnimationCollection.prototype
*
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._runtimeAnimations.length;
}
},
/**
* The model that owns this animation collection.
*
* @memberof ModelAnimationCollection.prototype
*
* @type {Model}
* @readonly
*/
model: {
get: function() {
return this._model;
}
}
});
function addAnimation(collection, animation, options) {
const model = collection._model;
const runtimeAnimation = new ModelAnimation_default(model, animation, options);
collection._runtimeAnimations.push(runtimeAnimation);
collection.animationAdded.raiseEvent(model, runtimeAnimation);
return runtimeAnimation;
}
ModelAnimationCollection.prototype.add = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const model = this._model;
if (!model.ready) {
throw new DeveloperError_default(
"Animations are not loaded. Wait for Model.ready to be true."
);
}
const animations = model.sceneGraph.components.animations;
if (!defined_default(options.name) && !defined_default(options.index)) {
throw new DeveloperError_default(
"Either options.name or options.index must be defined."
);
}
if (defined_default(options.multiplier) && options.multiplier <= 0) {
throw new DeveloperError_default("options.multiplier must be greater than zero.");
}
if (defined_default(options.index) && (options.index >= animations.length || options.index < 0)) {
throw new DeveloperError_default("options.index must be a valid animation index.");
}
let index = options.index;
if (defined_default(index)) {
return addAnimation(this, animations[index], options);
}
const length2 = animations.length;
for (let i = 0; i < length2; ++i) {
if (animations[i].name === options.name) {
index = i;
break;
}
}
if (!defined_default(index)) {
throw new DeveloperError_default("options.name must be a valid animation name.");
}
return addAnimation(this, animations[index], options);
};
ModelAnimationCollection.prototype.addAll = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const model = this._model;
if (!model.ready) {
throw new DeveloperError_default(
"Animations are not loaded. Wait for Model.ready to be true."
);
}
if (defined_default(options.multiplier) && options.multiplier <= 0) {
throw new DeveloperError_default("options.multiplier must be greater than zero.");
}
const animations = model.sceneGraph.components.animations;
const addedAnimations = [];
const length2 = animations.length;
for (let i = 0; i < length2; ++i) {
const animation = addAnimation(this, animations[i], options);
addedAnimations.push(animation);
}
return addedAnimations;
};
ModelAnimationCollection.prototype.remove = function(runtimeAnimation) {
if (!defined_default(runtimeAnimation)) {
return false;
}
const animations = this._runtimeAnimations;
const i = animations.indexOf(runtimeAnimation);
if (i !== -1) {
animations.splice(i, 1);
this.animationRemoved.raiseEvent(this._model, runtimeAnimation);
return true;
}
return false;
};
ModelAnimationCollection.prototype.removeAll = function() {
const model = this._model;
const animations = this._runtimeAnimations;
const length2 = animations.length;
this._runtimeAnimations.length = 0;
for (let i = 0; i < length2; ++i) {
this.animationRemoved.raiseEvent(model, animations[i]);
}
};
ModelAnimationCollection.prototype.contains = function(runtimeAnimation) {
if (defined_default(runtimeAnimation)) {
return this._runtimeAnimations.indexOf(runtimeAnimation) !== -1;
}
return false;
};
ModelAnimationCollection.prototype.get = function(index) {
if (!defined_default(index)) {
throw new DeveloperError_default("index is required.");
}
if (index >= this._runtimeAnimations.length || index < 0) {
throw new DeveloperError_default(
"index must be valid within the range of the collection"
);
}
return this._runtimeAnimations[index];
};
var animationsToRemove = [];
function createAnimationRemovedFunction(modelAnimationCollection, model, animation) {
return function() {
modelAnimationCollection.animationRemoved.raiseEvent(model, animation);
};
}
ModelAnimationCollection.prototype.update = function(frameState) {
const runtimeAnimations = this._runtimeAnimations;
let length2 = runtimeAnimations.length;
if (length2 === 0) {
this._previousTime = void 0;
return false;
}
if (!this.animateWhilePaused && JulianDate_default.equals(frameState.time, this._previousTime)) {
return false;
}
this._previousTime = JulianDate_default.clone(frameState.time, this._previousTime);
let animationOccurred = false;
const sceneTime = frameState.time;
const model = this._model;
for (let i = 0; i < length2; ++i) {
const runtimeAnimation = runtimeAnimations[i];
if (!defined_default(runtimeAnimation._computedStartTime)) {
runtimeAnimation._computedStartTime = JulianDate_default.addSeconds(
runtimeAnimation.startTime ?? sceneTime,
runtimeAnimation.delay,
new JulianDate_default()
);
}
if (!defined_default(runtimeAnimation._duration)) {
runtimeAnimation._duration = runtimeAnimation.localStopTime * (1 / runtimeAnimation.multiplier);
}
const startTime = runtimeAnimation._computedStartTime;
const duration = runtimeAnimation._duration;
const stopTime = runtimeAnimation.stopTime;
const pastStartTime = JulianDate_default.lessThanOrEquals(startTime, sceneTime);
const reachedStopTime = defined_default(stopTime) && JulianDate_default.greaterThan(sceneTime, stopTime);
let delta = 0;
if (duration !== 0) {
const seconds = JulianDate_default.secondsDifference(
reachedStopTime ? stopTime : sceneTime,
startTime
);
delta = defined_default(runtimeAnimation._animationTime) ? runtimeAnimation._animationTime(duration, seconds) : seconds / duration;
}
const repeat = runtimeAnimation.loop === ModelAnimationLoop_default.REPEAT || runtimeAnimation.loop === ModelAnimationLoop_default.MIRRORED_REPEAT;
const play = (pastStartTime || repeat && !defined_default(runtimeAnimation.startTime)) && (delta <= 1 || repeat) && !reachedStopTime;
if (delta === runtimeAnimation._prevAnimationDelta) {
const animationStopped = runtimeAnimation._state === ModelAnimationState_default.STOPPED;
if (play !== animationStopped) {
continue;
}
}
runtimeAnimation._prevAnimationDelta = delta;
if (play || runtimeAnimation._state === ModelAnimationState_default.ANIMATING) {
if (play && runtimeAnimation._state === ModelAnimationState_default.STOPPED) {
runtimeAnimation._state = ModelAnimationState_default.ANIMATING;
if (runtimeAnimation.start.numberOfListeners > 0) {
frameState.afterRender.push(runtimeAnimation._raiseStartEvent);
}
}
if (runtimeAnimation.loop === ModelAnimationLoop_default.REPEAT) {
delta = delta - Math.floor(delta);
} else if (runtimeAnimation.loop === ModelAnimationLoop_default.MIRRORED_REPEAT) {
const floor = Math.floor(delta);
const fract2 = delta - floor;
delta = floor % 2 === 1 ? 1 - fract2 : fract2;
}
if (runtimeAnimation.reverse) {
delta = 1 - delta;
}
let localAnimationTime = delta * duration * runtimeAnimation.multiplier;
localAnimationTime = Math_default.clamp(
localAnimationTime,
runtimeAnimation.localStartTime,
runtimeAnimation.localStopTime
);
runtimeAnimation.animate(localAnimationTime);
if (runtimeAnimation.update.numberOfListeners > 0) {
runtimeAnimation._updateEventTime = localAnimationTime;
frameState.afterRender.push(runtimeAnimation._raiseUpdateEvent);
}
animationOccurred = true;
if (!play) {
runtimeAnimation._state = ModelAnimationState_default.STOPPED;
if (runtimeAnimation.stop.numberOfListeners > 0) {
frameState.afterRender.push(runtimeAnimation._raiseStopEvent);
}
if (runtimeAnimation.removeOnStop) {
animationsToRemove.push(runtimeAnimation);
}
}
}
}
length2 = animationsToRemove.length;
for (let j = 0; j < length2; ++j) {
const animationToRemove = animationsToRemove[j];
runtimeAnimations.splice(runtimeAnimations.indexOf(animationToRemove), 1);
frameState.afterRender.push(
createAnimationRemovedFunction(this, model, animationToRemove)
);
}
animationsToRemove.length = 0;
return animationOccurred;
};
var ModelAnimationCollection_default = ModelAnimationCollection;
// packages/engine/Source/Scene/Model/ModelFeatureTable.js
var import_InlineWorkers602 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Model/ModelFeature.js
var import_InlineWorkers599 = __toESM(require_InlineWorkers(), 1);
function ModelFeature(options) {
this._model = options.model;
this._featureTable = options.featureTable;
this._featureId = options.featureId;
this._color = void 0;
}
Object.defineProperties(ModelFeature.prototype, {
/**
* Gets or sets if the feature will be shown. This is set for all features
* when a style's show is evaluated.
*
* @memberof ModelFeature.prototype
*
* @type {boolean}
*
* @default true
*/
show: {
get: function() {
return this._featureTable.getShow(this._featureId);
},
set: function(value) {
this._featureTable.setShow(this._featureId, value);
}
},
/**
* Gets or sets the highlight color multiplied with the feature's color. When
* this is white, the feature's color is not changed. This is set for all features
* when a style's color is evaluated.
*
* @memberof ModelFeature.prototype
*
* @type {Color}
*
* @default {@link Color.WHITE}
*/
color: {
get: function() {
if (!defined_default(this._color)) {
this._color = new Color_default();
}
return this._featureTable.getColor(this._featureId, this._color);
},
set: function(value) {
this._featureTable.setColor(this._featureId, value);
}
},
/**
* All objects returned by {@link Scene#pick} have a primitive property. This returns
* the model containing the feature.
*
* @memberof ModelFeature.prototype
*
* @type {Model}
*
* @readonly
* @private
*/
primitive: {
get: function() {
return this._model;
}
},
/**
* The {@link ModelFeatureTable} that this feature belongs to.
*
* @memberof ModelFeature.prototype
*
* @type {ModelFeatureTable}
*
* @readonly
* @private
*/
featureTable: {
get: function() {
return this._featureTable;
}
},
/**
* Get the feature ID associated with this feature. For 3D Tiles 1.0, the
* batch ID is returned. For EXT_mesh_features, this is the feature ID from
* the selected feature ID set.
*
* @memberof ModelFeature.prototype
*
* @type {number}
*
* @readonly
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
featureId: {
get: function() {
return this._featureId;
}
}
});
ModelFeature.prototype.hasProperty = function(name) {
return this._featureTable.hasProperty(this._featureId, name);
};
ModelFeature.prototype.getProperty = function(name) {
return this._featureTable.getProperty(this._featureId, name);
};
ModelFeature.prototype.getPropertyInherited = function(name) {
if (this._featureTable.hasPropertyBySemantic(this._featureId, name)) {
return this._featureTable.getPropertyBySemantic(this._featureId, name);
}
return this._featureTable.getProperty(this._featureId, name);
};
ModelFeature.prototype.getPropertyIds = function(results) {
return this._featureTable.getPropertyIds(results);
};
ModelFeature.prototype.setProperty = function(name, value) {
return this._featureTable.setProperty(this._featureId, name, value);
};
var ModelFeature_default = ModelFeature;
// packages/engine/Source/Scene/Model/StyleCommandsNeeded.js
var import_InlineWorkers600 = __toESM(require_InlineWorkers(), 1);
var StyleCommandsNeeded2 = {
ALL_OPAQUE: 0,
ALL_TRANSLUCENT: 1,
OPAQUE_AND_TRANSLUCENT: 2
};
StyleCommandsNeeded2.getStyleCommandsNeeded = function(featuresLength, translucentFeaturesLength) {
if (translucentFeaturesLength === 0) {
return StyleCommandsNeeded2.ALL_OPAQUE;
} else if (translucentFeaturesLength === featuresLength) {
return StyleCommandsNeeded2.ALL_TRANSLUCENT;
}
return StyleCommandsNeeded2.OPAQUE_AND_TRANSLUCENT;
};
var StyleCommandsNeeded_default = Object.freeze(StyleCommandsNeeded2);
// packages/engine/Source/Scene/Model/ModelType.js
var import_InlineWorkers601 = __toESM(require_InlineWorkers(), 1);
var ModelType = {
/**
* An individual glTF model.
* * Not to be confused with {@link ModelType.TILE_GLTF} * which is for 3D Tiles *
* * @type {string} * @constant */ GLTF: "GLTF", /** * A glTF model used as tile content in a 3D Tileset via *3DTILES_content_gltf.
* * Not to be confused with {@link ModelType.GLTF} * which is for individual models *
* * @type {string} * @constant */ TILE_GLTF: "TILE_GLTF", /** * A 3D Tiles 1.0 Batched 3D Model * * @type {string} * @constant */ TILE_B3DM: "B3DM", /** * A 3D Tiles 1.0 Instanced 3D Model * * @type {string} * @constant */ TILE_I3DM: "I3DM", /** * A 3D Tiles 1.0 Point Cloud * * @type {string} * @constant */ TILE_PNTS: "PNTS", /** * GeoJSON content forMAXAR_content_geojson extension
*
* @type {string}
* @constant
*/
TILE_GEOJSON: "TILE_GEOJSON"
};
ModelType.is3DTiles = function(modelType) {
Check_default.typeOf.string("modelType", modelType);
switch (modelType) {
case ModelType.TILE_GLTF:
case ModelType.TILE_B3DM:
case ModelType.TILE_I3DM:
case ModelType.TILE_PNTS:
case ModelType.TILE_GEOJSON:
return true;
case ModelType.GLTF:
return false;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("modelType is not a valid value.");
}
};
var ModelType_default = Object.freeze(ModelType);
// packages/engine/Source/Scene/Model/ModelFeatureTable.js
function ModelFeatureTable(options) {
const model = options.model;
const propertyTable = options.propertyTable;
Check_default.typeOf.object("propertyTable", propertyTable);
Check_default.typeOf.object("model", model);
this._propertyTable = propertyTable;
this._model = model;
this._features = void 0;
this._featuresLength = 0;
this._batchTexture = void 0;
this._styleCommandsNeededDirty = false;
this._styleCommandsNeeded = StyleCommandsNeeded_default.ALL_OPAQUE;
initialize8(this);
}
Object.defineProperties(ModelFeatureTable.prototype, {
/**
* The batch texture created for the features in this table.
*
* @memberof ModelFeatureTable.prototype
*
* @type {BatchTexture}
* @readonly
*
* @private
*/
batchTexture: {
get: function() {
return this._batchTexture;
}
},
/**
* The number of features in this table.
*
* @memberof ModelFeatureTable.prototype
*
* @type {number}
* @readonly
*
* @private
*/
featuresLength: {
get: function() {
return this._featuresLength;
}
},
/**
* Size of the batch texture. This does not count the property table size
* as that is counted separately through StructuralMetadata.
*
* @memberof ModelFeatureTable.prototype
*
* @type {number}
* @readonly
*
* @private
*/
batchTextureByteLength: {
get: function() {
if (defined_default(this._batchTexture)) {
return this._batchTexture.byteLength;
}
return 0;
}
},
/**
* A flag to indicate whether or not the types of style commands needed by this feature table have changed.
*
* @memberof ModelFeatureTable.prototype
*
* @type {boolean}
* @readonly
*
* @private
*/
styleCommandsNeededDirty: {
get: function() {
return this._styleCommandsNeededDirty;
}
}
});
function initialize8(modelFeatureTable) {
const model = modelFeatureTable._model;
const is3DTiles = ModelType_default.is3DTiles(model.type);
const featuresLength = modelFeatureTable._propertyTable.count;
if (featuresLength === 0) {
return;
}
let i;
const features = new Array(featuresLength);
if (is3DTiles) {
const content = model.content;
for (i = 0; i < featuresLength; i++) {
features[i] = new Cesium3DTileFeature_default(content, i);
}
} else {
for (i = 0; i < featuresLength; i++) {
features[i] = new ModelFeature_default({
model,
featureId: i,
featureTable: modelFeatureTable
});
}
}
modelFeatureTable._features = features;
modelFeatureTable._featuresLength = featuresLength;
modelFeatureTable._batchTexture = new BatchTexture_default({
featuresLength,
owner: modelFeatureTable,
statistics: is3DTiles ? model.content.tileset.statistics : void 0
});
}
ModelFeatureTable.prototype.update = function(frameState) {
this._styleCommandsNeededDirty = false;
this._batchTexture.update(void 0, frameState);
const currentStyleCommandsNeeded = StyleCommandsNeeded_default.getStyleCommandsNeeded(
this._featuresLength,
this._batchTexture.translucentFeaturesLength
);
if (this._styleCommandsNeeded !== currentStyleCommandsNeeded) {
this._styleCommandsNeededDirty = true;
this._styleCommandsNeeded = currentStyleCommandsNeeded;
}
};
ModelFeatureTable.prototype.setShow = function(featureId, show) {
this._batchTexture.setShow(featureId, show);
};
ModelFeatureTable.prototype.setAllShow = function(show) {
this._batchTexture.setAllShow(show);
};
ModelFeatureTable.prototype.getShow = function(featureId) {
return this._batchTexture.getShow(featureId);
};
ModelFeatureTable.prototype.setColor = function(featureId, color) {
this._batchTexture.setColor(featureId, color);
};
ModelFeatureTable.prototype.setAllColor = function(color) {
this._batchTexture.setAllColor(color);
};
ModelFeatureTable.prototype.getColor = function(featureId, result) {
return this._batchTexture.getColor(featureId, result);
};
ModelFeatureTable.prototype.getPickColor = function(featureId) {
return this._batchTexture.getPickColor(featureId);
};
ModelFeatureTable.prototype.getFeature = function(featureId) {
return this._features[featureId];
};
ModelFeatureTable.prototype.hasProperty = function(featureId, propertyName) {
return this._propertyTable.hasProperty(featureId, propertyName);
};
ModelFeatureTable.prototype.hasPropertyBySemantic = function(featureId, propertyName) {
return this._propertyTable.hasPropertyBySemantic(featureId, propertyName);
};
ModelFeatureTable.prototype.getProperty = function(featureId, name) {
return this._propertyTable.getProperty(featureId, name);
};
ModelFeatureTable.prototype.getPropertyBySemantic = function(featureId, semantic) {
return this._propertyTable.getPropertyBySemantic(featureId, semantic);
};
ModelFeatureTable.prototype.getPropertyIds = function(results) {
return this._propertyTable.getPropertyIds(results);
};
ModelFeatureTable.prototype.setProperty = function(featureId, name, value) {
return this._propertyTable.setProperty(featureId, name, value);
};
ModelFeatureTable.prototype.isClass = function(featureId, className) {
return this._propertyTable.isClass(featureId, className);
};
ModelFeatureTable.prototype.isExactClass = function(featureId, className) {
return this._propertyTable.isExactClass(featureId, className);
};
ModelFeatureTable.prototype.getExactClassName = function(featureId) {
return this._propertyTable.getExactClassName(featureId);
};
var scratchColor7 = new Color_default();
ModelFeatureTable.prototype.applyStyle = function(style) {
if (!defined_default(style)) {
this.setAllColor(BatchTexture_default.DEFAULT_COLOR_VALUE);
this.setAllShow(BatchTexture_default.DEFAULT_SHOW_VALUE);
return;
}
for (let i = 0; i < this._featuresLength; i++) {
const feature2 = this.getFeature(i);
const color = defined_default(style.color) ? style.color.evaluateColor(feature2, scratchColor7) ?? BatchTexture_default.DEFAULT_COLOR_VALUE : BatchTexture_default.DEFAULT_COLOR_VALUE;
const show = defined_default(style.show) ? style.show.evaluate(feature2) ?? BatchTexture_default.DEFAULT_SHOW_VALUE : BatchTexture_default.DEFAULT_SHOW_VALUE;
this.setColor(i, color);
this.setShow(i, show);
}
};
ModelFeatureTable.prototype.isDestroyed = function() {
return false;
};
ModelFeatureTable.prototype.destroy = function(frameState) {
this._batchTexture = this._batchTexture && this._batchTexture.destroy();
destroyObject_default(this);
};
var ModelFeatureTable_default = ModelFeatureTable;
// packages/engine/Source/Scene/Model/ModelSceneGraph.js
var import_InlineWorkers729 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Model/TilesetPipelineStage.js
var import_InlineWorkers603 = __toESM(require_InlineWorkers(), 1);
var TilesetPipelineStage = {
name: "TilesetPipelineStage"
// Helps with debugging
};
TilesetPipelineStage.process = function(renderResources, model, frameState) {
if (model.hasSkipLevelOfDetail(frameState)) {
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addDefine(
"POLYGON_OFFSET",
void 0,
ShaderDestination_default.FRAGMENT
);
const uniformMap2 = {
u_polygonOffset: function() {
return Cartesian2_default.ZERO;
}
};
renderResources.uniformMap = combine_default(
uniformMap2,
renderResources.uniformMap
);
renderResources.hasSkipLevelOfDetail = true;
}
const renderStateOptions = renderResources.renderStateOptions;
renderStateOptions.stencilTest = StencilConstants_default.setCesium3DTileBit();
renderStateOptions.stencilMask = StencilConstants_default.CESIUM_3D_TILE_MASK;
};
var TilesetPipelineStage_default = TilesetPipelineStage;
// packages/engine/Source/Scene/Model/AtmospherePipelineStage.js
var import_InlineWorkers606 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/AtmosphereStageFS.js
var import_InlineWorkers604 = __toESM(require_InlineWorkers(), 1);
var AtmosphereStageFS_default = "// robust iterative solution without trig functions\n// https://github.com/0xfaded/ellipse_demo/issues/1\n// https://stackoverflow.com/questions/22959698/distance-from-given-point-to-given-ellipse\n//\n// This version uses only a single iteration for best performance. For fog\n// rendering, the difference is negligible.\nvec2 nearestPointOnEllipseFast(vec2 pos, vec2 radii) {\n vec2 p = abs(pos);\n vec2 inverseRadii = 1.0 / radii;\n vec2 evoluteScale = (radii.x * radii.x - radii.y * radii.y) * vec2(1.0, -1.0) * inverseRadii;\n\n // We describe the ellipse parametrically: v = radii * vec2(cos(t), sin(t))\n // but store the cos and sin of t in a vec2 for efficiency.\n // Initial guess: t = cos(pi/4)\n vec2 tTrigs = vec2(0.70710678118);\n vec2 v = radii * tTrigs;\n\n // Find the evolute of the ellipse (center of curvature) at v.\n vec2 evolute = evoluteScale * tTrigs * tTrigs * tTrigs;\n // Find the (approximate) intersection of p - evolute with the ellipsoid.\n vec2 q = normalize(p - evolute) * length(v - evolute);\n // Update the estimate of t.\n tTrigs = (q + evolute) * inverseRadii;\n tTrigs = normalize(clamp(tTrigs, 0.0, 1.0));\n v = radii * tTrigs;\n\n return v * sign(pos);\n}\n\nvec3 computeEllipsoidPositionWC(vec3 positionMC) {\n // Get the world-space position and project onto a meridian plane of\n // the ellipsoid\n vec3 positionWC = (czm_model * vec4(positionMC, 1.0)).xyz;\n\n vec2 positionEllipse = vec2(length(positionWC.xy), positionWC.z);\n vec2 nearestPoint = nearestPointOnEllipseFast(positionEllipse, czm_ellipsoidRadii.xz);\n\n // Reconstruct a 3D point in world space\n return vec3(nearestPoint.x * normalize(positionWC.xy), nearestPoint.y);\n}\n\nvoid applyFog(inout vec4 color, vec4 groundAtmosphereColor, vec3 lightDirection, float distanceToCamera) {\n\n vec3 fogColor = groundAtmosphereColor.rgb;\n\n // If there is dynamic lighting, apply that to the fog.\n const float NONE = 0.0;\n if (czm_atmosphereDynamicLighting != NONE) {\n float darken = clamp(dot(normalize(czm_viewerPositionWC), lightDirection), czm_fogMinimumBrightness, 1.0);\n fogColor *= darken;\n }\n\n // Tonemap if HDR rendering is disabled\n #ifndef HDR\n fogColor.rgb = czm_pbrNeutralTonemapping(fogColor.rgb);\n fogColor.rgb = czm_inverseGamma(fogColor.rgb);\n #endif\n\n vec3 withFog = czm_fog(distanceToCamera, color.rgb, fogColor, czm_fogVisualDensityScalar);\n color = vec4(withFog, color.a);\n}\n\nvoid atmosphereStage(inout vec4 color, in ProcessedAttributes attributes) {\n vec3 rayleighColor;\n vec3 mieColor;\n float opacity;\n\n vec3 positionWC;\n vec3 lightDirection;\n\n // When the camera is in space, compute the position per-fragment for\n // more accurate ground atmosphere. All other cases will use\n //\n // The if condition will be added in https://github.com/CesiumGS/cesium/issues/11717\n if (false) {\n positionWC = computeEllipsoidPositionWC(attributes.positionMC);\n lightDirection = czm_getDynamicAtmosphereLightDirection(positionWC, czm_atmosphereDynamicLighting);\n\n // The fog color is derived from the ground atmosphere color\n czm_computeGroundAtmosphereScattering(\n positionWC,\n lightDirection,\n rayleighColor,\n mieColor,\n opacity\n );\n } else {\n positionWC = attributes.positionWC;\n lightDirection = czm_getDynamicAtmosphereLightDirection(positionWC, czm_atmosphereDynamicLighting);\n rayleighColor = v_atmosphereRayleighColor;\n mieColor = v_atmosphereMieColor;\n opacity = v_atmosphereOpacity;\n }\n\n //color correct rayleigh and mie colors\n const bool ignoreBlackPixels = true;\n rayleighColor = czm_applyHSBShift(rayleighColor, czm_atmosphereHsbShift, ignoreBlackPixels);\n mieColor = czm_applyHSBShift(mieColor, czm_atmosphereHsbShift, ignoreBlackPixels);\n\n vec4 groundAtmosphereColor = czm_computeAtmosphereColor(positionWC, lightDirection, rayleighColor, mieColor, opacity);\n\n if (u_isInFog) {\n float distanceToCamera = length(attributes.positionEC);\n applyFog(color, groundAtmosphereColor, lightDirection, distanceToCamera);\n } else {\n // Ground atmosphere\n }\n}\n";
// packages/engine/Source/Shaders/Model/AtmosphereStageVS.js
var import_InlineWorkers605 = __toESM(require_InlineWorkers(), 1);
var AtmosphereStageVS_default = "void atmosphereStage(ProcessedAttributes attributes) {\n vec3 lightDirection = czm_getDynamicAtmosphereLightDirection(v_positionWC, czm_atmosphereDynamicLighting);\n\n czm_computeGroundAtmosphereScattering(\n // This assumes the geometry stage came before this.\n v_positionWC,\n lightDirection,\n v_atmosphereRayleighColor,\n v_atmosphereMieColor,\n v_atmosphereOpacity\n );\n}\n";
// packages/engine/Source/Scene/Model/AtmospherePipelineStage.js
var AtmospherePipelineStage = {
name: "AtmospherePipelineStage"
// Helps with debugging
};
AtmospherePipelineStage.process = function(modelRenderResources, model, frameState) {
const shaderBuilder = modelRenderResources.shaderBuilder;
shaderBuilder.addDefine("HAS_ATMOSPHERE", void 0, ShaderDestination_default.BOTH);
shaderBuilder.addDefine(
"COMPUTE_POSITION_WC_ATMOSPHERE",
void 0,
ShaderDestination_default.BOTH
);
shaderBuilder.addVarying("vec3", "v_atmosphereRayleighColor");
shaderBuilder.addVarying("vec3", "v_atmosphereMieColor");
shaderBuilder.addVarying("float", "v_atmosphereOpacity");
shaderBuilder.addVertexLines([AtmosphereStageVS_default]);
shaderBuilder.addFragmentLines([AtmosphereStageFS_default]);
shaderBuilder.addUniform("bool", "u_isInFog", ShaderDestination_default.FRAGMENT);
modelRenderResources.uniformMap.u_isInFog = function() {
const distance2 = Cartesian3_default.distance(
frameState.camera.positionWC,
model.boundingSphere.center
);
return Math_default.fog(distance2, frameState.fog.density) > Math_default.EPSILON3;
};
};
var AtmospherePipelineStage_default = AtmospherePipelineStage;
// packages/engine/Source/Scene/Model/ImageBasedLightingPipelineStage.js
var import_InlineWorkers608 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/ImageBasedLightingStageFS.js
var import_InlineWorkers607 = __toESM(require_InlineWorkers(), 1);
var ImageBasedLightingStageFS_default = "#ifdef DIFFUSE_IBL\nvec3 sampleDiffuseEnvironment(vec3 cubeDir)\n{\n #ifdef CUSTOM_SPHERICAL_HARMONICS\n return czm_sphericalHarmonics(cubeDir, model_sphericalHarmonicCoefficients); \n #else\n return czm_sphericalHarmonics(cubeDir, czm_sphericalHarmonicCoefficients); \n #endif\n}\n#endif\n\n#ifdef SPECULAR_IBL\nvec3 sampleSpecularEnvironment(vec3 cubeDir, float roughness)\n{\n #ifdef CUSTOM_SPECULAR_IBL\n float lod = roughness * model_specularEnvironmentMapsMaximumLOD;\n return czm_textureCube(model_specularEnvironmentMaps, cubeDir, lod).rgb;\n #else\n float lod = roughness * czm_specularEnvironmentMapsMaximumLOD;\n return czm_textureCube(czm_specularEnvironmentMaps, cubeDir, lod).rgb;\n #endif\n}\nvec3 computeSpecularIBL(vec3 cubeDir, float NdotV, vec3 f0, float roughness)\n{\n // see https://bruop.github.io/ibl/ at Single Scattering Results\n // Roughness dependent fresnel, from Fdez-Aguera\n vec3 f90 = max(vec3(1.0 - roughness), f0);\n vec3 F = fresnelSchlick2(f0, f90, NdotV);\n\n vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg;\n vec3 specularSample = sampleSpecularEnvironment(cubeDir, roughness);\n\n return specularSample * (F * brdfLut.x + brdfLut.y);\n}\n#endif\n\n#if defined(DIFFUSE_IBL) || defined(SPECULAR_IBL)\n/**\n * Compute the light contributions from environment maps and spherical harmonic coefficients.\n * See Fdez-Aguera, https://www.jcgt.org/published/0008/01/03/paper.pdf, for explanation\n * of the single- and multi-scattering terms.\n *\n * @param {vec3} viewDirectionEC Unit vector pointing from the fragment to the eye position.\n * @param {vec3} normalEC The surface normal in eye coordinates.\n * @param {czm_modelMaterial} The material properties.\n * @return {vec3} The computed HDR color.\n */\nvec3 textureIBL(vec3 viewDirectionEC, vec3 normalEC, czm_modelMaterial material) {\n vec3 f0 = material.specular;\n float roughness = material.roughness;\n float specularWeight = 1.0;\n #ifdef USE_SPECULAR\n specularWeight = material.specularWeight;\n #endif\n float NdotV = clamp(dot(normalEC, viewDirectionEC), 0.0, 1.0);\n\n // see https://bruop.github.io/ibl/ at Single Scattering Results\n // Roughness dependent fresnel, from Fdez-Aguera\n vec3 f90 = max(vec3(1.0 - roughness), f0);\n vec3 singleScatterFresnel = fresnelSchlick2(f0, f90, NdotV);\n\n vec2 brdfLut = texture(czm_brdfLut, vec2(NdotV, roughness)).rg;\n vec3 FssEss = specularWeight * (singleScatterFresnel * brdfLut.x + brdfLut.y);\n\n #ifdef DIFFUSE_IBL\n vec3 normalMC = normalize(model_iblReferenceFrameMatrix * normalEC);\n vec3 irradiance = sampleDiffuseEnvironment(normalMC);\n\n vec3 averageFresnel = f0 + (1.0 - f0) / 21.0;\n float Ems = specularWeight * (1.0 - brdfLut.x - brdfLut.y);\n vec3 FmsEms = FssEss * averageFresnel * Ems / (1.0 - averageFresnel * Ems);\n vec3 dielectricScattering = (1.0 - FssEss - FmsEms) * material.diffuse;\n vec3 diffuseContribution = irradiance * (FmsEms + dielectricScattering) * model_iblFactor.x;\n #else\n vec3 diffuseContribution = vec3(0.0);\n #endif\n\n #ifdef USE_ANISOTROPY\n // Bend normal to account for anisotropic distortion of specular reflection\n vec3 anisotropyDirection = material.anisotropicB;\n vec3 anisotropicTangent = cross(anisotropyDirection, viewDirectionEC);\n vec3 anisotropicNormal = cross(anisotropicTangent, anisotropyDirection);\n float bendFactor = 1.0 - material.anisotropyStrength * (1.0 - roughness);\n float bendFactorPow4 = bendFactor * bendFactor * bendFactor * bendFactor;\n vec3 bentNormal = normalize(mix(anisotropicNormal, normalEC, bendFactorPow4));\n vec3 reflectEC = reflect(-viewDirectionEC, bentNormal);\n #else\n vec3 reflectEC = reflect(-viewDirectionEC, normalEC);\n #endif\n\n #ifdef SPECULAR_IBL\n vec3 reflectMC = normalize(model_iblReferenceFrameMatrix * reflectEC);\n vec3 radiance = sampleSpecularEnvironment(reflectMC, roughness);\n vec3 specularContribution = radiance * FssEss * model_iblFactor.y;\n #else\n vec3 specularContribution = vec3(0.0);\n #endif\n\n return diffuseContribution + specularContribution;\n}\n#endif\n";
// packages/engine/Source/Scene/Model/ImageBasedLightingPipelineStage.js
var ImageBasedLightingPipelineStage = {
name: "ImageBasedLightingPipelineStage"
// Helps with debugging
};
var scratchCartesian10 = new Cartesian2_default();
ImageBasedLightingPipelineStage.process = function(renderResources, model, frameState) {
const imageBasedLighting = model.imageBasedLighting;
const environmentMapManager = model.environmentMapManager;
const shaderBuilder = renderResources.shaderBuilder;
let specularEnvironmentMapAtlas;
if (!defined_default(imageBasedLighting.specularEnvironmentMaps)) {
specularEnvironmentMapAtlas = environmentMapManager.radianceCubeMap;
}
const sphericalHarmonicCoefficients = imageBasedLighting.sphericalHarmonicCoefficients ?? environmentMapManager.sphericalHarmonicCoefficients;
shaderBuilder.addDefine(
"USE_IBL_LIGHTING",
void 0,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"vec2",
"model_iblFactor",
ShaderDestination_default.FRAGMENT
);
if (SpecularEnvironmentCubeMap_default.isSupported(frameState.context)) {
const addMatrix = imageBasedLighting.useSphericalHarmonics || imageBasedLighting.useSpecularEnvironmentMaps || imageBasedLighting.enabled;
if (addMatrix) {
shaderBuilder.addUniform(
"mat3",
"model_iblReferenceFrameMatrix",
ShaderDestination_default.FRAGMENT
);
}
if (defined_default(specularEnvironmentMapAtlas)) {
shaderBuilder.addDefine(
"COMPUTE_POSITION_WC_ATMOSPHERE",
void 0,
ShaderDestination_default.BOTH
);
}
if (defined_default(sphericalHarmonicCoefficients) && defined_default(sphericalHarmonicCoefficients[0])) {
shaderBuilder.addDefine(
"DIFFUSE_IBL",
void 0,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addDefine(
"CUSTOM_SPHERICAL_HARMONICS",
void 0,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"vec3",
"model_sphericalHarmonicCoefficients[9]",
ShaderDestination_default.FRAGMENT
);
} else if (imageBasedLighting.useDefaultSphericalHarmonics) {
shaderBuilder.addDefine(
"DIFFUSE_IBL",
void 0,
ShaderDestination_default.FRAGMENT
);
}
if (defined_default(imageBasedLighting.specularEnvironmentCubeMap) && imageBasedLighting.specularEnvironmentCubeMap.ready || defined_default(specularEnvironmentMapAtlas)) {
shaderBuilder.addDefine(
"SPECULAR_IBL",
void 0,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addDefine(
"CUSTOM_SPECULAR_IBL",
void 0,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"samplerCube",
"model_specularEnvironmentMaps",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"float",
"model_specularEnvironmentMapsMaximumLOD",
ShaderDestination_default.FRAGMENT
);
} else if (model.useDefaultSpecularMaps) {
shaderBuilder.addDefine(
"SPECULAR_IBL",
void 0,
ShaderDestination_default.FRAGMENT
);
}
}
shaderBuilder.addFragmentLines(ImageBasedLightingStageFS_default);
const uniformMap2 = {
model_iblFactor: function() {
return Cartesian2_default.multiplyByScalar(
imageBasedLighting.imageBasedLightingFactor,
environmentMapManager?.intensity || 1,
scratchCartesian10
);
},
model_iblReferenceFrameMatrix: function() {
return model._iblReferenceFrameMatrix;
},
model_sphericalHarmonicCoefficients: function() {
return sphericalHarmonicCoefficients;
},
model_specularEnvironmentMaps: function() {
return imageBasedLighting.specularEnvironmentCubeMap.texture;
},
model_specularEnvironmentMapsMaximumLOD: function() {
return imageBasedLighting.specularEnvironmentCubeMap.maximumMipmapLevel;
}
};
if (defined_default(specularEnvironmentMapAtlas)) {
uniformMap2.model_specularEnvironmentMaps = function() {
return specularEnvironmentMapAtlas;
};
uniformMap2.model_specularEnvironmentMapsMaximumLOD = function() {
return environmentMapManager.maximumMipmapLevel;
};
}
renderResources.uniformMap = combine_default(uniformMap2, renderResources.uniformMap);
};
var ImageBasedLightingPipelineStage_default = ImageBasedLightingPipelineStage;
// packages/engine/Source/Scene/Model/ModelArticulation.js
var import_InlineWorkers610 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Model/ModelArticulationStage.js
var import_InlineWorkers609 = __toESM(require_InlineWorkers(), 1);
var articulationEpsilon = Math_default.EPSILON16;
function ModelArticulationStage(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const stage = options.stage;
const runtimeArticulation = options.runtimeArticulation;
Check_default.typeOf.object("options.stage", stage);
Check_default.typeOf.object("options.runtimeArticulation", runtimeArticulation);
this._stage = stage;
this._runtimeArticulation = runtimeArticulation;
this._name = stage.name;
this._type = stage.type;
this._minimumValue = stage.minimumValue;
this._maximumValue = stage.maximumValue;
this._currentValue = stage.initialValue;
}
Object.defineProperties(ModelArticulationStage.prototype, {
/**
* The internal articulation stage that this runtime stage represents.
*
* @memberof ModelArticulationStage.prototype
* @type {ModelComponents.ArticulationStage}
* @readonly
*
* @private
*/
stage: {
get: function() {
return this._stage;
}
},
/**
* The runtime articulation that this stage belongs to.
*
* @memberof ModelArticulationStage.prototype
* @type {ModelArticulation}
* @readonly
*
* @private
*/
runtimeArticulation: {
get: function() {
return this._runtimeArticulation;
}
},
/**
* The name of this articulation stage.
*
* @memberof ModelArticulationStage.prototype
* @type {string}
* @readonly
*
* @private
*/
name: {
get: function() {
return this._name;
}
},
/**
* The type of this articulation stage. This specifies which of the
* node's properties is modified by the stage's value.
*
* @memberof ModelArticulationStage.prototype
* @type {ArticulationStageType}
* @readonly
*
* @private
*/
type: {
get: function() {
return this._type;
}
},
/**
* The minimum value of this articulation stage.
*
* @memberof ModelArticulationStage.prototype
* @type {number}
* @readonly
*
* @private
*/
minimumValue: {
get: function() {
return this._minimumValue;
}
},
/**
* The maximum value of this articulation stage.
*
* @memberof ModelArticulationStage.prototype
* @type {number}
* @readonly
*
* @private
*/
maximumValue: {
get: function() {
return this._maximumValue;
}
},
/**
* The current value of this articulation stage.
*
* @memberof ModelArticulationStage.prototype
* @type {number}
*
* @private
*/
currentValue: {
get: function() {
return this._currentValue;
},
set: function(value) {
Check_default.typeOf.number("value", value);
value = Math_default.clamp(value, this.minimumValue, this.maximumValue);
if (!Math_default.equalsEpsilon(
this._currentValue,
value,
articulationEpsilon
)) {
this._currentValue = value;
this.runtimeArticulation._dirty = true;
}
}
}
});
var scratchArticulationCartesian = new Cartesian3_default();
var scratchArticulationRotation = new Matrix3_default();
ModelArticulationStage.prototype.applyStageToMatrix = function(result) {
Check_default.typeOf.object("result", result);
const type = this.type;
const value = this.currentValue;
const cartesian11 = scratchArticulationCartesian;
let rotation;
switch (type) {
case ArticulationStageType_default.XROTATE:
rotation = Matrix3_default.fromRotationX(
Math_default.toRadians(value),
scratchArticulationRotation
);
result = Matrix4_default.multiplyByMatrix3(result, rotation, result);
break;
case ArticulationStageType_default.YROTATE:
rotation = Matrix3_default.fromRotationY(
Math_default.toRadians(value),
scratchArticulationRotation
);
result = Matrix4_default.multiplyByMatrix3(result, rotation, result);
break;
case ArticulationStageType_default.ZROTATE:
rotation = Matrix3_default.fromRotationZ(
Math_default.toRadians(value),
scratchArticulationRotation
);
result = Matrix4_default.multiplyByMatrix3(result, rotation, result);
break;
case ArticulationStageType_default.XTRANSLATE:
cartesian11.x = value;
cartesian11.y = 0;
cartesian11.z = 0;
result = Matrix4_default.multiplyByTranslation(result, cartesian11, result);
break;
case ArticulationStageType_default.YTRANSLATE:
cartesian11.x = 0;
cartesian11.y = value;
cartesian11.z = 0;
result = Matrix4_default.multiplyByTranslation(result, cartesian11, result);
break;
case ArticulationStageType_default.ZTRANSLATE:
cartesian11.x = 0;
cartesian11.y = 0;
cartesian11.z = value;
result = Matrix4_default.multiplyByTranslation(result, cartesian11, result);
break;
case ArticulationStageType_default.XSCALE:
cartesian11.x = value;
cartesian11.y = 1;
cartesian11.z = 1;
result = Matrix4_default.multiplyByScale(result, cartesian11, result);
break;
case ArticulationStageType_default.YSCALE:
cartesian11.x = 1;
cartesian11.y = value;
cartesian11.z = 1;
result = Matrix4_default.multiplyByScale(result, cartesian11, result);
break;
case ArticulationStageType_default.ZSCALE:
cartesian11.x = 1;
cartesian11.y = 1;
cartesian11.z = value;
result = Matrix4_default.multiplyByScale(result, cartesian11, result);
break;
case ArticulationStageType_default.UNIFORMSCALE:
result = Matrix4_default.multiplyByUniformScale(result, value, result);
break;
default:
break;
}
return result;
};
var ModelArticulationStage_default = ModelArticulationStage;
// packages/engine/Source/Scene/Model/ModelArticulation.js
function ModelArticulation(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const articulation = options.articulation;
const sceneGraph = options.sceneGraph;
Check_default.typeOf.object("options.articulation", articulation);
Check_default.typeOf.object("options.sceneGraph", sceneGraph);
this._articulation = articulation;
this._sceneGraph = sceneGraph;
this._name = articulation.name;
this._runtimeStages = [];
this._runtimeStagesByName = {};
this._runtimeNodes = [];
this._dirty = true;
initialize9(this);
}
Object.defineProperties(ModelArticulation.prototype, {
/**
* The internal articulation that this runtime articulation represents.
*
* @memberof ModelArticulation.prototype
* @type {ModelComponents.Articulation}
* @readonly
*
* @private
*/
articulation: {
get: function() {
return this._articulation;
}
},
/**
* The scene graph that this articulation belongs to.
*
* @memberof ModelArticulation.prototype
* @type {ModelSceneGraph}
* @readonly
*
* @private
*/
sceneGraph: {
get: function() {
return this._sceneGraph;
}
},
/**
* The name of this articulation.
*
* @memberof ModelArticulation.prototype
* @type {string}
* @readonly
*
* @private
*/
name: {
get: function() {
return this._name;
}
},
/**
* The runtime stages that belong to this articulation.
*
* @memberof ModelArticulation.prototype
* @type {ModelArticulationStage[]}
* @readonly
*
* @private
*/
runtimeStages: {
get: function() {
return this._runtimeStages;
}
},
/**
* The runtime nodes that are affected by this articulation.
*
* @memberof ModelArticulation.prototype
* @type {ModelRuntimeNode[]}
* @readonly
*
* @private
*/
runtimeNodes: {
get: function() {
return this._runtimeNodes;
}
}
});
function initialize9(runtimeArticulation) {
const articulation = runtimeArticulation.articulation;
const stages = articulation.stages;
const length2 = stages.length;
const runtimeStages = runtimeArticulation._runtimeStages;
const runtimeStagesByName = runtimeArticulation._runtimeStagesByName;
for (let i = 0; i < length2; i++) {
const stage = stages[i];
const runtimeStage = new ModelArticulationStage_default({
stage,
runtimeArticulation
});
runtimeStages.push(runtimeStage);
const stageName = stage.name;
runtimeStagesByName[stageName] = runtimeStage;
}
}
ModelArticulation.prototype.setArticulationStage = function(stageName, value) {
const stage = this._runtimeStagesByName[stageName];
if (defined_default(stage)) {
stage.currentValue = value;
}
};
var scratchArticulationMatrix = new Matrix4_default();
var scratchNodeMatrix = new Matrix4_default();
ModelArticulation.prototype.apply = function() {
if (!this._dirty) {
return;
}
this._dirty = false;
let articulationMatrix = Matrix4_default.clone(
Matrix4_default.IDENTITY,
scratchArticulationMatrix
);
let i;
const stages = this._runtimeStages;
const stagesLength = stages.length;
for (i = 0; i < stagesLength; i++) {
const stage = stages[i];
articulationMatrix = stage.applyStageToMatrix(articulationMatrix);
}
const nodes = this._runtimeNodes;
const nodesLength = nodes.length;
for (i = 0; i < nodesLength; i++) {
const node = nodes[i];
const transform3 = Matrix4_default.multiplyTransformation(
node.originalTransform,
articulationMatrix,
scratchNodeMatrix
);
node.transform = transform3;
}
};
var ModelArticulation_default = ModelArticulation;
// packages/engine/Source/Scene/Model/ModelColorPipelineStage.js
var import_InlineWorkers612 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/ModelColorStageFS.js
var import_InlineWorkers611 = __toESM(require_InlineWorkers(), 1);
var ModelColorStageFS_default = "void modelColorStage(inout czm_modelMaterial material)\n{\n material.diffuse = mix(material.diffuse, model_color.rgb, model_colorBlend);\n float highlight = ceil(model_colorBlend);\n material.diffuse *= mix(model_color.rgb, vec3(1.0), highlight);\n material.alpha *= model_color.a;\n}\n";
// packages/engine/Source/Scene/Model/ModelColorPipelineStage.js
var ModelColorPipelineStage = {
name: "ModelColorPipelineStage",
// Helps with debugging
COLOR_UNIFORM_NAME: "model_color",
COLOR_BLEND_UNIFORM_NAME: "model_colorBlend"
};
ModelColorPipelineStage.process = function(renderResources, model, frameState) {
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addDefine(
"HAS_MODEL_COLOR",
void 0,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFragmentLines(ModelColorStageFS_default);
const stageUniforms = {};
const color = model.color;
if (color.alpha === 0 && !model.hasSilhouette(frameState)) {
renderResources.renderStateOptions.colorMask = {
red: false,
green: false,
blue: false,
alpha: false
};
}
if (color.alpha < 1) {
renderResources.alphaOptions.pass = Pass_default.TRANSLUCENT;
}
shaderBuilder.addUniform(
"vec4",
ModelColorPipelineStage.COLOR_UNIFORM_NAME,
ShaderDestination_default.FRAGMENT
);
stageUniforms[ModelColorPipelineStage.COLOR_UNIFORM_NAME] = function() {
return model.color;
};
shaderBuilder.addUniform(
"float",
ModelColorPipelineStage.COLOR_BLEND_UNIFORM_NAME,
ShaderDestination_default.FRAGMENT
);
stageUniforms[ModelColorPipelineStage.COLOR_BLEND_UNIFORM_NAME] = function() {
return ColorBlendMode_default.getColorBlend(
model.colorBlendMode,
model.colorBlendAmount
);
};
renderResources.uniformMap = combine_default(
stageUniforms,
renderResources.uniformMap
);
};
var ModelColorPipelineStage_default = ModelColorPipelineStage;
// packages/engine/Source/Scene/Model/ModelClippingPlanesPipelineStage.js
var import_InlineWorkers614 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/ModelClippingPlanesStageFS.js
var import_InlineWorkers613 = __toESM(require_InlineWorkers(), 1);
var ModelClippingPlanesStageFS_default = "#ifdef USE_CLIPPING_PLANES_FLOAT_TEXTURE\nvec4 getClippingPlane(\n highp sampler2D packedClippingPlanes,\n int clippingPlaneNumber,\n mat4 transform\n) {\n int pixY = clippingPlaneNumber / CLIPPING_PLANES_TEXTURE_WIDTH;\n int pixX = clippingPlaneNumber - (pixY * CLIPPING_PLANES_TEXTURE_WIDTH);\n float pixelWidth = 1.0 / float(CLIPPING_PLANES_TEXTURE_WIDTH);\n float pixelHeight = 1.0 / float(CLIPPING_PLANES_TEXTURE_HEIGHT);\n float u = (float(pixX) + 0.5) * pixelWidth; // sample from center of pixel\n float v = (float(pixY) + 0.5) * pixelHeight;\n vec4 plane = texture(packedClippingPlanes, vec2(u, v));\n return czm_transformPlane(plane, transform);\n}\n#else\n// Handle uint8 clipping texture instead\nvec4 getClippingPlane(\n highp sampler2D packedClippingPlanes,\n int clippingPlaneNumber,\n mat4 transform\n) {\n int clippingPlaneStartIndex = clippingPlaneNumber * 2; // clipping planes are two pixels each\n int pixY = clippingPlaneStartIndex / CLIPPING_PLANES_TEXTURE_WIDTH;\n int pixX = clippingPlaneStartIndex - (pixY * CLIPPING_PLANES_TEXTURE_WIDTH);\n float pixelWidth = 1.0 / float(CLIPPING_PLANES_TEXTURE_WIDTH);\n float pixelHeight = 1.0 / float(CLIPPING_PLANES_TEXTURE_HEIGHT);\n float u = (float(pixX) + 0.5) * pixelWidth; // sample from center of pixel\n float v = (float(pixY) + 0.5) * pixelHeight;\n vec4 oct32 = texture(packedClippingPlanes, vec2(u, v)) * 255.0;\n vec2 oct = vec2(oct32.x * 256.0 + oct32.y, oct32.z * 256.0 + oct32.w);\n vec4 plane;\n plane.xyz = czm_octDecode(oct, 65535.0);\n plane.w = czm_unpackFloat(texture(packedClippingPlanes, vec2(u + pixelWidth, v)));\n return czm_transformPlane(plane, transform);\n}\n#endif\n\nfloat clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix) {\n vec4 position = czm_windowToEyeCoordinates(fragCoord);\n vec3 clipNormal = vec3(0.0);\n vec3 clipPosition = vec3(0.0);\n float pixelWidth = czm_metersPerPixel(position);\n \n #ifdef UNION_CLIPPING_REGIONS\n float clipAmount; // For union planes, we want to get the min distance. So we set the initial value to the first plane distance in the loop below.\n #else\n float clipAmount = 0.0;\n bool clipped = true;\n #endif\n\n for (int i = 0; i < CLIPPING_PLANES_LENGTH; ++i) {\n vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);\n clipNormal = clippingPlane.xyz;\n clipPosition = -clippingPlane.w * clipNormal;\n float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;\n \n #ifdef UNION_CLIPPING_REGIONS\n clipAmount = czm_branchFreeTernary(i == 0, amount, min(amount, clipAmount));\n if (amount <= 0.0) {\n discard;\n }\n #else\n clipAmount = max(amount, clipAmount);\n clipped = clipped && (amount <= 0.0);\n #endif\n }\n\n #ifndef UNION_CLIPPING_REGIONS\n if (clipped) {\n discard;\n }\n #endif\n \n return clipAmount;\n}\n\nvoid modelClippingPlanesStage(inout vec4 color)\n{\n float clipDistance = clip(gl_FragCoord, model_clippingPlanes, model_clippingPlanesMatrix);\n vec4 clippingPlanesEdgeColor = vec4(1.0);\n clippingPlanesEdgeColor.rgb = model_clippingPlanesEdgeStyle.rgb;\n float clippingPlanesEdgeWidth = model_clippingPlanesEdgeStyle.a;\n \n if (clipDistance > 0.0 && clipDistance < clippingPlanesEdgeWidth) {\n color = clippingPlanesEdgeColor;\n }\n}\n";
// packages/engine/Source/Scene/Model/ModelClippingPlanesPipelineStage.js
var ModelClippingPlanesPipelineStage = {
name: "ModelClippingPlanesPipelineStage"
// Helps with debugging
};
var textureResolutionScratch3 = new Cartesian2_default();
ModelClippingPlanesPipelineStage.process = function(renderResources, model, frameState) {
const clippingPlanes = model.clippingPlanes;
const context = frameState.context;
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addDefine(
"HAS_CLIPPING_PLANES",
void 0,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addDefine(
"CLIPPING_PLANES_LENGTH",
clippingPlanes.length,
ShaderDestination_default.FRAGMENT
);
if (clippingPlanes.unionClippingRegions) {
shaderBuilder.addDefine(
"UNION_CLIPPING_REGIONS",
void 0,
ShaderDestination_default.FRAGMENT
);
}
if (ClippingPlaneCollection_default.useFloatTexture(context)) {
shaderBuilder.addDefine(
"USE_CLIPPING_PLANES_FLOAT_TEXTURE",
void 0,
ShaderDestination_default.FRAGMENT
);
}
const textureResolution = ClippingPlaneCollection_default.getTextureResolution(
clippingPlanes,
context,
textureResolutionScratch3
);
shaderBuilder.addDefine(
"CLIPPING_PLANES_TEXTURE_WIDTH",
textureResolution.x,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addDefine(
"CLIPPING_PLANES_TEXTURE_HEIGHT",
textureResolution.y,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"sampler2D",
"model_clippingPlanes",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"vec4",
"model_clippingPlanesEdgeStyle",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"mat4",
"model_clippingPlanesMatrix",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFragmentLines(ModelClippingPlanesStageFS_default);
const uniformMap2 = {
model_clippingPlanes: function() {
return clippingPlanes.texture;
},
model_clippingPlanesEdgeStyle: function() {
const style = Color_default.clone(clippingPlanes.edgeColor);
style.alpha = clippingPlanes.edgeWidth;
return style;
},
model_clippingPlanesMatrix: function() {
return model._clippingPlanesMatrix;
}
};
renderResources.uniformMap = combine_default(uniformMap2, renderResources.uniformMap);
};
var ModelClippingPlanesPipelineStage_default = ModelClippingPlanesPipelineStage;
// packages/engine/Source/Scene/Model/ModelClippingPolygonsPipelineStage.js
var import_InlineWorkers617 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/ModelClippingPolygonsStageVS.js
var import_InlineWorkers615 = __toESM(require_InlineWorkers(), 1);
var ModelClippingPolygonsStageVS_default = "void modelClippingPolygonsStage(ProcessedAttributes attributes)\n{\n vec2 sphericalLatLong = czm_approximateSphericalCoordinates(v_positionWC);\n sphericalLatLong.y = czm_branchFreeTernary(sphericalLatLong.y < czm_pi, sphericalLatLong.y, sphericalLatLong.y - czm_twoPi);\n\n vec2 minDistance = vec2(czm_infinity);\n v_regionIndex = -1;\n v_clippingPosition = vec2(czm_infinity);\n\n for (int regionIndex = 0; regionIndex < CLIPPING_POLYGON_REGIONS_LENGTH; regionIndex++) {\n vec4 extents = czm_unpackClippingExtents(model_clippingExtents, regionIndex);\n vec2 rectUv = (sphericalLatLong.yx - extents.yx) * extents.wz;\n\n vec2 clamped = clamp(rectUv, vec2(0.0), vec2(1.0));\n vec2 distance = abs(rectUv - clamped) * extents.wz;\n \n if (minDistance.x > distance.x || minDistance.y > distance.y) {\n minDistance = distance;\n v_clippingPosition = rectUv;\n }\n\n float threshold = 0.01;\n if (rectUv.x > threshold && rectUv.y > threshold && rectUv.x < 1.0 - threshold && rectUv.y < 1.0 - threshold) {\n v_regionIndex = regionIndex;\n }\n }\n}\n";
// packages/engine/Source/Shaders/Model/ModelClippingPolygonsStageFS.js
var import_InlineWorkers616 = __toESM(require_InlineWorkers(), 1);
var ModelClippingPolygonsStageFS_default = "void modelClippingPolygonsStage()\n{\n vec2 clippingPosition = v_clippingPosition;\n int regionIndex = v_regionIndex;\n czm_clipPolygons(model_clippingDistance, CLIPPING_POLYGON_REGIONS_LENGTH, clippingPosition, regionIndex);\n}\n";
// packages/engine/Source/Scene/Model/ModelClippingPolygonsPipelineStage.js
var ModelClippingPolygonsPipelineStage = {
name: "ModelClippingPolygonsPipelineStage"
// Helps with debugging
};
ModelClippingPolygonsPipelineStage.process = function(renderResources, model, frameState) {
const clippingPolygons = model.clippingPolygons;
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addDefine(
"ENABLE_CLIPPING_POLYGONS",
void 0,
ShaderDestination_default.BOTH
);
if (clippingPolygons.inverse) {
shaderBuilder.addDefine(
"CLIPPING_INVERSE",
void 0,
ShaderDestination_default.FRAGMENT
);
}
shaderBuilder.addDefine(
"CLIPPING_POLYGON_REGIONS_LENGTH",
clippingPolygons.extentsCount,
ShaderDestination_default.BOTH
);
shaderBuilder.addUniform(
"sampler2D",
"model_clippingDistance",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"sampler2D",
"model_clippingExtents",
ShaderDestination_default.VERTEX
);
shaderBuilder.addVarying("vec2", "v_clippingPosition");
shaderBuilder.addVarying("int", "v_regionIndex", "flat");
shaderBuilder.addVertexLines(ModelClippingPolygonsStageVS_default);
shaderBuilder.addFragmentLines(ModelClippingPolygonsStageFS_default);
const uniformMap2 = {
model_clippingDistance: function() {
return (
// The later should never happen during a render pass, see https://github.com/CesiumGS/cesium/issues/12725
clippingPolygons.clippingTexture ?? frameState.context.defaultTexture
);
},
model_clippingExtents: function() {
return (
// The later should never happen during a render pass, see https://github.com/CesiumGS/cesium/issues/12725
clippingPolygons.extentsTexture ?? frameState.context.defaultTexture
);
}
};
renderResources.uniformMap = combine_default(uniformMap2, renderResources.uniformMap);
};
var ModelClippingPolygonsPipelineStage_default = ModelClippingPolygonsPipelineStage;
// packages/engine/Source/Scene/Model/ModelNode.js
var import_InlineWorkers618 = __toESM(require_InlineWorkers(), 1);
function ModelNode(model, runtimeNode) {
Check_default.typeOf.object("model", model);
Check_default.typeOf.object("runtimeNode", runtimeNode);
this._model = model;
this._runtimeNode = runtimeNode;
}
Object.defineProperties(ModelNode.prototype, {
/**
* The value of the name property of this node.
*
* @memberof ModelNode.prototype
*
* @type {string}
* @readonly
*/
name: {
get: function() {
return this._runtimeNode._name;
}
},
/**
* The index of the node in the glTF.
*
* @memberof ModelNode.prototype
*
* @type {number}
* @readonly
*/
id: {
get: function() {
return this._runtimeNode._id;
}
},
/**
* Determines if this node and its children will be shown.
*
* @memberof ModelNode.prototype
* @type {boolean}
*
* @default true
*/
show: {
get: function() {
return this._runtimeNode.show;
},
set: function(value) {
this._runtimeNode.show = value;
}
},
/**
* The node's 4x4 matrix transform from its local coordinates to
* its parent's. Setting the matrix to undefined will restore the
* node's original transform, and allow the node to be animated by
* any animations in the model again.
* * For changes to take effect, this property must be assigned to; * setting individual elements of the matrix will not work. *
* * @memberof ModelNode.prototype * @type {Matrix4} */ matrix: { get: function() { return this._runtimeNode.transform; }, set: function(value) { if (defined_default(value)) { this._runtimeNode.transform = value; this._runtimeNode.userAnimated = true; this._model._userAnimationDirty = true; } else { this._runtimeNode.transform = this.originalMatrix; this._runtimeNode.userAnimated = false; } } }, /** * Gets the node's original 4x4 matrix transform from its local * coordinates to its parent's, without any node transformations * or articulations applied. * * @memberof ModelNode.prototype * @type {Matrix4} */ originalMatrix: { get: function() { return this._runtimeNode.originalTransform; } } }); var ModelNode_default = ModelNode; // packages/engine/Source/Scene/Model/ModelRuntimeNode.js var import_InlineWorkers625 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/Model/InstancingPipelineStage.js var import_InlineWorkers622 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Shaders/Model/InstancingStageCommon.js var import_InlineWorkers619 = __toESM(require_InlineWorkers(), 1); var InstancingStageCommon_default = "mat4 getInstancingTransform()\n{\n mat4 instancingTransform;\n\n #ifdef HAS_INSTANCE_MATRICES\n instancingTransform = mat4(\n a_instancingTransformRow0.x, a_instancingTransformRow1.x, a_instancingTransformRow2.x, 0.0, // Column 1\n a_instancingTransformRow0.y, a_instancingTransformRow1.y, a_instancingTransformRow2.y, 0.0, // Column 2\n a_instancingTransformRow0.z, a_instancingTransformRow1.z, a_instancingTransformRow2.z, 0.0, // Column 3\n a_instancingTransformRow0.w, a_instancingTransformRow1.w, a_instancingTransformRow2.w, 1.0 // Column 4\n );\n #else\n vec3 translation = vec3(0.0, 0.0, 0.0);\n vec3 scale = vec3(1.0, 1.0, 1.0);\n \n #ifdef HAS_INSTANCE_TRANSLATION\n translation = a_instanceTranslation;\n #endif\n #ifdef HAS_INSTANCE_SCALE\n scale = a_instanceScale;\n #endif\n\n instancingTransform = mat4(\n scale.x, 0.0, 0.0, 0.0,\n 0.0, scale.y, 0.0, 0.0,\n 0.0, 0.0, scale.z, 0.0,\n translation.x, translation.y, translation.z, 1.0\n ); \n #endif\n\n return instancingTransform;\n}\n\n#ifdef USE_2D_INSTANCING\nmat4 getInstancingTransform2D()\n{\n mat4 instancingTransform2D;\n\n #ifdef HAS_INSTANCE_MATRICES\n instancingTransform2D = mat4(\n a_instancingTransform2DRow0.x, a_instancingTransform2DRow1.x, a_instancingTransform2DRow2.x, 0.0, // Column 1\n a_instancingTransform2DRow0.y, a_instancingTransform2DRow1.y, a_instancingTransform2DRow2.y, 0.0, // Column 2\n a_instancingTransform2DRow0.z, a_instancingTransform2DRow1.z, a_instancingTransform2DRow2.z, 0.0, // Column 3\n a_instancingTransform2DRow0.w, a_instancingTransform2DRow1.w, a_instancingTransform2DRow2.w, 1.0 // Column 4\n );\n #else\n vec3 translation2D = vec3(0.0, 0.0, 0.0);\n vec3 scale = vec3(1.0, 1.0, 1.0);\n \n #ifdef HAS_INSTANCE_TRANSLATION\n translation2D = a_instanceTranslation2D;\n #endif\n #ifdef HAS_INSTANCE_SCALE\n scale = a_instanceScale;\n #endif\n\n instancingTransform2D = mat4(\n scale.x, 0.0, 0.0, 0.0,\n 0.0, scale.y, 0.0, 0.0,\n 0.0, 0.0, scale.z, 0.0,\n translation2D.x, translation2D.y, translation2D.z, 1.0\n ); \n #endif\n\n return instancingTransform2D;\n}\n#endif\n"; // packages/engine/Source/Shaders/Model/InstancingStageVS.js var import_InlineWorkers620 = __toESM(require_InlineWorkers(), 1); var InstancingStageVS_default = "void instancingStage(inout ProcessedAttributes attributes) \n{\n vec3 positionMC = attributes.positionMC;\n \n mat4 instancingTransform = getInstancingTransform();\n \n attributes.positionMC = (instancingTransform * vec4(positionMC, 1.0)).xyz;\n\n #ifdef HAS_NORMALS\n vec3 normalMC = attributes.normalMC;\n attributes.normalMC = (instancingTransform * vec4(normalMC, 0.0)).xyz;\n #endif\n\n #ifdef USE_2D_INSTANCING\n mat4 instancingTransform2D = getInstancingTransform2D();\n attributes.position2D = (instancingTransform2D * vec4(positionMC, 1.0)).xyz;\n #endif\n}\n"; // packages/engine/Source/Shaders/Model/LegacyInstancingStageVS.js var import_InlineWorkers621 = __toESM(require_InlineWorkers(), 1); var LegacyInstancingStageVS_default = "void legacyInstancingStage(\n inout ProcessedAttributes attributes,\n out mat4 instanceModelView,\n out mat3 instanceModelViewInverseTranspose)\n{\n vec3 positionMC = attributes.positionMC;\n\n mat4 instancingTransform = getInstancingTransform();\n \n mat4 instanceModel = instancingTransform * u_instance_nodeTransform;\n instanceModelView = u_instance_modifiedModelView;\n instanceModelViewInverseTranspose = mat3(u_instance_modifiedModelView * instanceModel);\n\n attributes.positionMC = (instanceModel * vec4(positionMC, 1.0)).xyz;\n \n #ifdef USE_2D_INSTANCING\n mat4 instancingTransform2D = getInstancingTransform2D();\n attributes.position2D = (instancingTransform2D * vec4(positionMC, 1.0)).xyz;\n #endif\n}\n"; // packages/engine/Source/Scene/Model/InstancingPipelineStage.js var modelViewScratch = new Matrix4_default(); var nodeTransformScratch = new Matrix4_default(); var modelView2DScratch = new Matrix4_default(); var InstancingPipelineStage = { name: "InstancingPipelineStage", // Helps with debugging // Expose some methods for testing _getInstanceTransformsAsMatrices: getInstanceTransformsAsMatrices, _transformsToTypedArray: transformsToTypedArray }; InstancingPipelineStage.process = function(renderResources, node, frameState) { const instances = node.instances; const count = instances.attributes[0].count; const shaderBuilder = renderResources.shaderBuilder; shaderBuilder.addDefine("HAS_INSTANCING"); shaderBuilder.addVertexLines(InstancingStageCommon_default); const model = renderResources.model; const sceneGraph = model.sceneGraph; const runtimeNode = renderResources.runtimeNode; const use2D = frameState.mode !== SceneMode_default.SCENE3D && !frameState.scene3DOnly && model._projectTo2D; const keepTypedArray = model._enablePick && !frameState.context.webgl2; const instancingVertexAttributes = []; processTransformAttributes( renderResources, frameState, instances, instancingVertexAttributes, use2D, keepTypedArray ); processFeatureIdAttributes( renderResources, frameState, instances, instancingVertexAttributes ); const uniformMap2 = {}; if (instances.transformInWorldSpace) { shaderBuilder.addDefine( "USE_LEGACY_INSTANCING", void 0, ShaderDestination_default.VERTEX ); shaderBuilder.addUniform( "mat4", "u_instance_modifiedModelView", ShaderDestination_default.VERTEX ); shaderBuilder.addUniform( "mat4", "u_instance_nodeTransform", ShaderDestination_default.VERTEX ); uniformMap2.u_instance_modifiedModelView = function() { let modifiedModelMatrix = Matrix4_default.multiplyTransformation( // For 3D Tiles, model.modelMatrix is the computed tile // transform (which includes tileset.modelMatrix). This always applies // for i3dm, since such models are always part of a tileset. model.modelMatrix, // For i3dm models, components.transform contains the RTC_CENTER // translation. sceneGraph.components.transform, modelViewScratch ); if (use2D) { return Matrix4_default.multiplyTransformation( frameState.context.uniformState.view3D, modifiedModelMatrix, modelViewScratch ); } if (frameState.mode !== SceneMode_default.SCENE3D) { modifiedModelMatrix = Transforms_default.basisTo2D( frameState.mapProjection, modifiedModelMatrix, modelViewScratch ); } return Matrix4_default.multiplyTransformation( frameState.context.uniformState.view, modifiedModelMatrix, modelViewScratch ); }; uniformMap2.u_instance_nodeTransform = function() { return Matrix4_default.multiplyTransformation( // glTF y-up to 3D Tiles z-up sceneGraph.axisCorrectionMatrix, // This transforms from the node's coordinate system to the root // of the node hierarchy runtimeNode.computedTransform, nodeTransformScratch ); }; shaderBuilder.addVertexLines(LegacyInstancingStageVS_default); } else { shaderBuilder.addVertexLines(InstancingStageVS_default); } if (use2D) { shaderBuilder.addDefine( "USE_2D_INSTANCING", void 0, ShaderDestination_default.VERTEX ); shaderBuilder.addUniform("mat4", "u_modelView2D", ShaderDestination_default.VERTEX); const context = frameState.context; const modelMatrix2D = Matrix4_default.fromTranslation( runtimeNode.instancingReferencePoint2D, new Matrix4_default() ); uniformMap2.u_modelView2D = function() { return Matrix4_default.multiplyTransformation( context.uniformState.view, modelMatrix2D, modelView2DScratch ); }; } renderResources.uniformMap = combine_default(uniformMap2, renderResources.uniformMap); renderResources.instanceCount = count; addAllToArray_default(renderResources.attributes, instancingVertexAttributes); }; var projectedTransformScratch = new Matrix4_default(); var projectedPositionScratch = new Cartesian3_default(); function projectTransformTo2D(transform3, modelMatrix, nodeTransform, frameState, result) { let projectedTransform = Matrix4_default.multiplyTransformation( modelMatrix, transform3, projectedTransformScratch ); projectedTransform = Matrix4_default.multiplyTransformation( projectedTransform, nodeTransform, projectedTransformScratch ); result = Transforms_default.basisTo2D( frameState.mapProjection, projectedTransform, result ); return result; } function projectPositionTo2D(position, modelMatrix, nodeTransform, frameState, result) { const translationMatrix = Matrix4_default.fromTranslation( position, projectedTransformScratch ); let projectedTransform = Matrix4_default.multiplyTransformation( modelMatrix, translationMatrix, projectedTransformScratch ); projectedTransform = Matrix4_default.multiplyTransformation( projectedTransform, nodeTransform, projectedTransformScratch ); const finalPosition = Matrix4_default.getTranslation( projectedTransform, projectedPositionScratch ); result = SceneTransforms_default.computeActualEllipsoidPosition( frameState, finalPosition, result ); return result; } function getModelMatrixAndNodeTransform(renderResources, modelMatrix, nodeComputedTransform) { const model = renderResources.model; const sceneGraph = model.sceneGraph; const instances = renderResources.runtimeNode.node.instances; if (instances.transformInWorldSpace) { modelMatrix = Matrix4_default.multiplyTransformation( model.modelMatrix, sceneGraph.components.transform, modelMatrix ); nodeComputedTransform = Matrix4_default.multiplyTransformation( sceneGraph.axisCorrectionMatrix, renderResources.runtimeNode.computedTransform, nodeComputedTransform ); } else { modelMatrix = Matrix4_default.clone(sceneGraph.computedModelMatrix, modelMatrix); modelMatrix = Matrix4_default.multiplyTransformation( modelMatrix, renderResources.runtimeNode.computedTransform, modelMatrix ); nodeComputedTransform = Matrix4_default.clone( Matrix4_default.IDENTITY, nodeComputedTransform ); } } var modelMatrixScratch = new Matrix4_default(); var nodeComputedTransformScratch = new Matrix4_default(); var transformScratch2 = new Matrix4_default(); var positionScratch5 = new Cartesian3_default(); function projectTransformsTo2D(transforms, renderResources, frameState, result) { const modelMatrix = modelMatrixScratch; const nodeComputedTransform = nodeComputedTransformScratch; getModelMatrixAndNodeTransform( renderResources, modelMatrix, nodeComputedTransform ); const runtimeNode = renderResources.runtimeNode; const referencePoint = runtimeNode.instancingReferencePoint2D; const count = transforms.length; for (let i = 0; i < count; i++) { const transform3 = transforms[i]; const projectedTransform = projectTransformTo2D( transform3, modelMatrix, nodeComputedTransform, frameState, transformScratch2 ); const position = Matrix4_default.getTranslation( projectedTransform, positionScratch5 ); const finalTranslation = Cartesian3_default.subtract( position, referencePoint, position ); result[i] = Matrix4_default.setTranslation( projectedTransform, finalTranslation, result[i] ); } return result; } function projectTranslationsTo2D(translations, renderResources, frameState, result) { const modelMatrix = modelMatrixScratch; const nodeComputedTransform = nodeComputedTransformScratch; getModelMatrixAndNodeTransform( renderResources, modelMatrix, nodeComputedTransform ); const runtimeNode = renderResources.runtimeNode; const referencePoint = runtimeNode.instancingReferencePoint2D; const count = translations.length; for (let i = 0; i < count; i++) { const translation3 = translations[i]; const projectedPosition2 = projectPositionTo2D( translation3, modelMatrix, nodeComputedTransform, frameState, translation3 ); result[i] = Cartesian3_default.subtract( projectedPosition2, referencePoint, result[i] ); } return result; } var scratchProjectedMin = new Cartesian3_default(); var scratchProjectedMax = new Cartesian3_default(); function computeReferencePoint2D(renderResources, frameState) { const runtimeNode = renderResources.runtimeNode; const modelMatrix = renderResources.model.sceneGraph.computedModelMatrix; const transformedPositionMin = Matrix4_default.multiplyByPoint( modelMatrix, runtimeNode.instancingTranslationMin, scratchProjectedMin ); const projectedMin = SceneTransforms_default.computeActualEllipsoidPosition( frameState, transformedPositionMin, transformedPositionMin ); const transformedPositionMax = Matrix4_default.multiplyByPoint( modelMatrix, runtimeNode.instancingTranslationMax, scratchProjectedMax ); const projectedMax = SceneTransforms_default.computeActualEllipsoidPosition( frameState, transformedPositionMax, transformedPositionMax ); runtimeNode.instancingReferencePoint2D = Cartesian3_default.lerp( projectedMin, projectedMax, 0.5, new Cartesian3_default() ); } function transformsToTypedArray(transforms) { const elements = 12; const count = transforms.length; const transformsTypedArray = new Float32Array(count * elements); for (let i = 0; i < count; i++) { const transform3 = transforms[i]; const offset = elements * i; transformsTypedArray[offset + 0] = transform3[0]; transformsTypedArray[offset + 1] = transform3[4]; transformsTypedArray[offset + 2] = transform3[8]; transformsTypedArray[offset + 3] = transform3[12]; transformsTypedArray[offset + 4] = transform3[1]; transformsTypedArray[offset + 5] = transform3[5]; transformsTypedArray[offset + 6] = transform3[9]; transformsTypedArray[offset + 7] = transform3[13]; transformsTypedArray[offset + 8] = transform3[2]; transformsTypedArray[offset + 9] = transform3[6]; transformsTypedArray[offset + 10] = transform3[10]; transformsTypedArray[offset + 11] = transform3[14]; } return transformsTypedArray; } function translationsToTypedArray(translations) { const elements = 3; const count = translations.length; const transationsTypedArray = new Float32Array(count * elements); for (let i = 0; i < count; i++) { const translation3 = translations[i]; const offset = elements * i; transationsTypedArray[offset + 0] = translation3[0]; transationsTypedArray[offset + 1] = translation3[4]; transationsTypedArray[offset + 2] = translation3[8]; } return transationsTypedArray; } var translationScratch = new Cartesian3_default(); var rotationScratch = new Quaternion_default(); var scaleScratch = new Cartesian3_default(); function getInstanceTransformsAsMatrices(instances, count, renderResources) { const transforms = new Array(count); const translationAttribute = ModelUtility_default.getAttributeBySemantic( instances, InstanceAttributeSemantic_default.TRANSLATION ); const rotationAttribute = ModelUtility_default.getAttributeBySemantic( instances, InstanceAttributeSemantic_default.ROTATION ); const scaleAttribute = ModelUtility_default.getAttributeBySemantic( instances, InstanceAttributeSemantic_default.SCALE ); const instancingTranslationMax = new Cartesian3_default( -Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE ); const instancingTranslationMin = new Cartesian3_default( Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE ); const hasTranslation = defined_default(translationAttribute); const hasRotation = defined_default(rotationAttribute); const hasScale = defined_default(scaleAttribute); const translationTypedArray = hasTranslation ? translationAttribute.typedArray : new Float32Array(count * 3); let rotationTypedArray = hasRotation ? rotationAttribute.typedArray : new Float32Array(count * 4); if (hasRotation && rotationAttribute.normalized) { rotationTypedArray = AttributeCompression_default.dequantize( rotationTypedArray, rotationAttribute.componentDatatype, rotationAttribute.type, count ); } let scaleTypedArray; if (hasScale) { scaleTypedArray = scaleAttribute.typedArray; } else { scaleTypedArray = new Float32Array(count * 3); scaleTypedArray.fill(1); } for (let i = 0; i < count; i++) { const translation3 = new Cartesian3_default( translationTypedArray[i * 3], translationTypedArray[i * 3 + 1], translationTypedArray[i * 3 + 2], translationScratch ); Cartesian3_default.maximumByComponent( instancingTranslationMax, translation3, instancingTranslationMax ); Cartesian3_default.minimumByComponent( instancingTranslationMin, translation3, instancingTranslationMin ); const rotation = new Quaternion_default( rotationTypedArray[i * 4], rotationTypedArray[i * 4 + 1], rotationTypedArray[i * 4 + 2], hasRotation ? rotationTypedArray[i * 4 + 3] : 1, rotationScratch ); const scale = new Cartesian3_default( scaleTypedArray[i * 3], scaleTypedArray[i * 3 + 1], scaleTypedArray[i * 3 + 2], scaleScratch ); const transform3 = Matrix4_default.fromTranslationQuaternionRotationScale( translation3, rotation, scale, new Matrix4_default() ); transforms[i] = transform3; } const runtimeNode = renderResources.runtimeNode; runtimeNode.instancingTranslationMin = instancingTranslationMin; runtimeNode.instancingTranslationMax = instancingTranslationMax; if (hasTranslation) { translationAttribute.typedArray = void 0; } if (hasRotation) { rotationAttribute.typedArray = void 0; } if (hasScale) { scaleAttribute.typedArray = void 0; } return transforms; } function getInstanceTranslationsAsCartesian3s(translationAttribute, count, renderResources) { const instancingTranslations = new Array(count); const translationTypedArray = translationAttribute.typedArray; const instancingTranslationMin = new Cartesian3_default( Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE ); const instancingTranslationMax = new Cartesian3_default( -Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE ); for (let i = 0; i < count; i++) { const translation3 = new Cartesian3_default( translationTypedArray[i * 3], translationTypedArray[i * 3 + 1], translationTypedArray[i * 3 + 2] ); instancingTranslations[i] = translation3; Cartesian3_default.minimumByComponent( instancingTranslationMin, translation3, instancingTranslationMin ); Cartesian3_default.maximumByComponent( instancingTranslationMax, translation3, instancingTranslationMax ); } const runtimeNode = renderResources.runtimeNode; runtimeNode.instancingTranslationMin = instancingTranslationMin; runtimeNode.instancingTranslationMax = instancingTranslationMax; translationAttribute.typedArray = void 0; return instancingTranslations; } function createVertexBuffer2(typedArray, frameState) { const buffer2 = Buffer_default.createVertexBuffer({ context: frameState.context, typedArray, usage: BufferUsage_default.STATIC_DRAW }); buffer2.vertexArrayDestroyable = false; return buffer2; } function processTransformAttributes(renderResources, frameState, instances, instancingVertexAttributes, use2D, keepTypedArray) { const rotationAttribute = ModelUtility_default.getAttributeBySemantic( instances, InstanceAttributeSemantic_default.ROTATION ); if (defined_default(rotationAttribute)) { processTransformMatrixAttributes( renderResources, instances, instancingVertexAttributes, frameState, use2D, keepTypedArray ); } else { processTransformVec3Attributes( renderResources, instances, instancingVertexAttributes, frameState, use2D ); } } function processTransformMatrixAttributes(renderResources, instances, instancingVertexAttributes, frameState, use2D, keepTypedArray) { const shaderBuilder = renderResources.shaderBuilder; const count = instances.attributes[0].count; const model = renderResources.model; const runtimeNode = renderResources.runtimeNode; shaderBuilder.addDefine("HAS_INSTANCE_MATRICES"); const attributeString = "Transform"; let transforms; let buffer2 = runtimeNode.instancingTransformsBuffer; if (!defined_default(buffer2)) { transforms = getInstanceTransformsAsMatrices( instances, count, renderResources ); const transformsTypedArray = transformsToTypedArray(transforms); buffer2 = createVertexBuffer2(transformsTypedArray, frameState); model._modelResources.push(buffer2); if (keepTypedArray) { runtimeNode.transformsTypedArray = transformsTypedArray; } runtimeNode.instancingTransformsBuffer = buffer2; } processMatrixAttributes( renderResources, buffer2, instancingVertexAttributes, attributeString ); if (!use2D) { return; } const frameStateCV = clone_default(frameState); frameStateCV.mode = SceneMode_default.COLUMBUS_VIEW; computeReferencePoint2D(renderResources, frameStateCV); let buffer2D = runtimeNode.instancingTransformsBuffer2D; if (!defined_default(buffer2D)) { const projectedTransforms = projectTransformsTo2D( transforms, renderResources, frameStateCV, transforms ); const projectedTypedArray = transformsToTypedArray(projectedTransforms); buffer2D = createVertexBuffer2(projectedTypedArray, frameState); model._modelResources.push(buffer2D); runtimeNode.instancingTransformsBuffer2D = buffer2D; } const attributeString2D = "Transform2D"; processMatrixAttributes( renderResources, buffer2D, instancingVertexAttributes, attributeString2D ); } function processTransformVec3Attributes(renderResources, instances, instancingVertexAttributes, frameState, use2D, keepTypedArray) { const shaderBuilder = renderResources.shaderBuilder; const runtimeNode = renderResources.runtimeNode; const translationAttribute = ModelUtility_default.getAttributeBySemantic( instances, InstanceAttributeSemantic_default.TRANSLATION ); const scaleAttribute = ModelUtility_default.getAttributeBySemantic( instances, InstanceAttributeSemantic_default.SCALE ); if (defined_default(scaleAttribute)) { shaderBuilder.addDefine("HAS_INSTANCE_SCALE"); const attributeString2 = "Scale"; processVec3Attribute( renderResources, scaleAttribute.buffer, scaleAttribute.byteOffset, scaleAttribute.byteStride, instancingVertexAttributes, attributeString2 ); } if (!defined_default(translationAttribute)) { return; } let instancingTranslations; const typedArray = translationAttribute.typedArray; if (defined_default(typedArray)) { instancingTranslations = getInstanceTranslationsAsCartesian3s( translationAttribute, translationAttribute.count, renderResources ); } else if (!defined_default(runtimeNode.instancingTranslationMin)) { runtimeNode.instancingTranslationMin = translationAttribute.min; runtimeNode.instancingTranslationMax = translationAttribute.max; } shaderBuilder.addDefine("HAS_INSTANCE_TRANSLATION"); const attributeString = "Translation"; processVec3Attribute( renderResources, translationAttribute.buffer, translationAttribute.byteOffset, translationAttribute.byteStride, instancingVertexAttributes, attributeString ); if (!use2D && !keepTypedArray) { return; } const frameStateCV = clone_default(frameState); frameStateCV.mode = SceneMode_default.COLUMBUS_VIEW; computeReferencePoint2D(renderResources, frameStateCV); let buffer2D = runtimeNode.instancingTranslationBuffer2D; if (!defined_default(buffer2D)) { const projectedTranslations = projectTranslationsTo2D( instancingTranslations, renderResources, frameStateCV, instancingTranslations ); const projectedTypedArray = translationsToTypedArray(projectedTranslations); if (keepTypedArray) { runtimeNode.transformsTypedArray = projectedTypedArray; } buffer2D = createVertexBuffer2(projectedTypedArray, frameState); renderResources.model._modelResources.push(buffer2D); runtimeNode.instancingTranslationBuffer2D = buffer2D; } if (!use2D) { return; } const byteOffset = 0; const byteStride = void 0; const attributeString2D = "Translation2D"; processVec3Attribute( renderResources, buffer2D, byteOffset, byteStride, instancingVertexAttributes, attributeString2D ); } function processMatrixAttributes(renderResources, buffer2, instancingVertexAttributes, attributeString) { const vertexSizeInFloats = 12; const componentByteSize = ComponentDatatype_default.getSizeInBytes( ComponentDatatype_default.FLOAT ); const strideInBytes = componentByteSize * vertexSizeInFloats; const matrixAttributes = [ { index: renderResources.attributeIndex++, vertexBuffer: buffer2, componentsPerAttribute: 4, componentDatatype: ComponentDatatype_default.FLOAT, normalize: false, offsetInBytes: 0, strideInBytes, instanceDivisor: 1 }, { index: renderResources.attributeIndex++, vertexBuffer: buffer2, componentsPerAttribute: 4, componentDatatype: ComponentDatatype_default.FLOAT, normalize: false, offsetInBytes: componentByteSize * 4, strideInBytes, instanceDivisor: 1 }, { index: renderResources.attributeIndex++, vertexBuffer: buffer2, componentsPerAttribute: 4, componentDatatype: ComponentDatatype_default.FLOAT, normalize: false, offsetInBytes: componentByteSize * 8, strideInBytes, instanceDivisor: 1 } ]; const shaderBuilder = renderResources.shaderBuilder; shaderBuilder.addAttribute("vec4", `a_instancing${attributeString}Row0`); shaderBuilder.addAttribute("vec4", `a_instancing${attributeString}Row1`); shaderBuilder.addAttribute("vec4", `a_instancing${attributeString}Row2`); addAllToArray_default(instancingVertexAttributes, matrixAttributes); } function processVec3Attribute(renderResources, buffer2, byteOffset, byteStride, instancingVertexAttributes, attributeString) { instancingVertexAttributes.push({ index: renderResources.attributeIndex++, vertexBuffer: buffer2, componentsPerAttribute: 3, componentDatatype: ComponentDatatype_default.FLOAT, normalize: false, offsetInBytes: byteOffset, strideInBytes: byteStride, instanceDivisor: 1 }); const shaderBuilder = renderResources.shaderBuilder; shaderBuilder.addAttribute("vec3", `a_instance${attributeString}`); } function processFeatureIdAttributes(renderResources, frameState, instances, instancingVertexAttributes) { const attributes = instances.attributes; const shaderBuilder = renderResources.shaderBuilder; for (let i = 0; i < attributes.length; i++) { const attribute = attributes[i]; if (attribute.semantic !== InstanceAttributeSemantic_default.FEATURE_ID) { continue; } if (attribute.setIndex >= renderResources.featureIdVertexAttributeSetIndex) { renderResources.featureIdVertexAttributeSetIndex = attribute.setIndex + 1; } instancingVertexAttributes.push({ index: renderResources.attributeIndex++, vertexBuffer: attribute.buffer, componentsPerAttribute: AttributeType_default.getNumberOfComponents( attribute.type ), componentDatatype: attribute.componentDatatype, normalize: false, offsetInBytes: attribute.byteOffset, strideInBytes: attribute.byteStride, instanceDivisor: 1 }); shaderBuilder.addAttribute( "float", `a_instanceFeatureId_${attribute.setIndex}` ); } } var InstancingPipelineStage_default = InstancingPipelineStage; // packages/engine/Source/Scene/Model/ModelMatrixUpdateStage.js var import_InlineWorkers623 = __toESM(require_InlineWorkers(), 1); var ModelMatrixUpdateStage = {}; ModelMatrixUpdateStage.name = "ModelMatrixUpdateStage"; ModelMatrixUpdateStage.update = function(runtimeNode, sceneGraph, frameState) { const use2D = frameState.mode !== SceneMode_default.SCENE3D; if (use2D && sceneGraph._model._projectTo2D) { return; } if (runtimeNode._transformDirty) { const modelMatrix = use2D ? sceneGraph._computedModelMatrix2D : sceneGraph._computedModelMatrix; updateRuntimeNode( runtimeNode, sceneGraph, modelMatrix, runtimeNode.transformToRoot ); runtimeNode._transformDirty = false; } }; function updateDrawCommand(drawCommand, modelMatrix, transformToRoot) { drawCommand.modelMatrix = Matrix4_default.multiplyTransformation( modelMatrix, transformToRoot, drawCommand.modelMatrix ); drawCommand.cullFace = ModelUtility_default.getCullFace( drawCommand.modelMatrix, drawCommand.primitiveType ); } function updateRuntimeNode(runtimeNode, sceneGraph, modelMatrix, transformToRoot) { let i; transformToRoot = Matrix4_default.multiplyTransformation( transformToRoot, runtimeNode.transform, new Matrix4_default() ); runtimeNode.updateComputedTransform(); const primitivesLength = runtimeNode.runtimePrimitives.length; for (i = 0; i < primitivesLength; i++) { const runtimePrimitive = runtimeNode.runtimePrimitives[i]; updateDrawCommand( runtimePrimitive.drawCommand, modelMatrix, transformToRoot ); } const childrenLength = runtimeNode.children.length; for (i = 0; i < childrenLength; i++) { const childRuntimeNode = sceneGraph._runtimeNodes[runtimeNode.children[i]]; childRuntimeNode._transformToRoot = Matrix4_default.clone( transformToRoot, childRuntimeNode._transformToRoot ); updateRuntimeNode( childRuntimeNode, sceneGraph, modelMatrix, transformToRoot ); childRuntimeNode._transformDirty = false; } } var ModelMatrixUpdateStage_default = ModelMatrixUpdateStage; // packages/engine/Source/Scene/Model/NodeStatisticsPipelineStage.js var import_InlineWorkers624 = __toESM(require_InlineWorkers(), 1); var NodeStatisticsPipelineStage = { name: "NodeStatisticsPipelineStage", // Helps with debugging // Expose some methods for testing _countInstancingAttributes: countInstancingAttributes, _countGeneratedBuffers: countGeneratedBuffers }; NodeStatisticsPipelineStage.process = function(renderResources, node, frameState) { const statistics2 = renderResources.model.statistics; const instances = node.instances; const runtimeNode = renderResources.runtimeNode; countInstancingAttributes(statistics2, instances); countGeneratedBuffers(statistics2, runtimeNode); }; function countInstancingAttributes(statistics2, instances) { if (!defined_default(instances)) { return; } const attributes = instances.attributes; const length2 = attributes.length; for (let i = 0; i < length2; i++) { const attribute = attributes[i]; if (defined_default(attribute.buffer)) { const hasCpuCopy = false; statistics2.addBuffer(attribute.buffer, hasCpuCopy); } } } function countGeneratedBuffers(statistics2, runtimeNode) { if (defined_default(runtimeNode.instancingTransformsBuffer)) { const hasCpuCopy = false; statistics2.addBuffer(runtimeNode.instancingTransformsBuffer, hasCpuCopy); } if (defined_default(runtimeNode.instancingTransformsBuffer2D)) { const hasCpuCopy = false; statistics2.addBuffer(runtimeNode.instancingTransformsBuffer2D, hasCpuCopy); } if (defined_default(runtimeNode.instancingTranslationBuffer2D)) { const hasCpuCopy = false; statistics2.addBuffer(runtimeNode.instancingTranslationBuffer2D, hasCpuCopy); } } var NodeStatisticsPipelineStage_default = NodeStatisticsPipelineStage; // packages/engine/Source/Scene/Model/ModelRuntimeNode.js function ModelRuntimeNode(options) { options = options ?? Frozen_default.EMPTY_OBJECT; const node = options.node; const transform3 = options.transform; const transformToRoot = options.transformToRoot; const sceneGraph = options.sceneGraph; const children = options.children; Check_default.typeOf.object("options.node", node); Check_default.typeOf.object("options.transform", transform3); Check_default.typeOf.object("options.transformToRoot", transformToRoot); Check_default.typeOf.object("options.sceneGraph", sceneGraph); Check_default.typeOf.object("options.children", children); this._node = node; this._name = node.name; this._id = node.index; this._sceneGraph = sceneGraph; this._children = children; this._originalTransform = Matrix4_default.clone(transform3, this._originalTransform); this._transform = Matrix4_default.clone(transform3, this._transform); this._transformToRoot = Matrix4_default.clone(transformToRoot, this._transformToRoot); this._computedTransform = new Matrix4_default(); this._transformDirty = false; this._transformParameters = void 0; this._morphWeights = []; this._runtimeSkin = void 0; this._computedJointMatrices = []; this.show = true; this.userAnimated = false; this.pipelineStages = []; this.runtimePrimitives = []; this.updateStages = []; this.instancingTranslationMin = void 0; this.instancingTranslationMax = void 0; this.instancingTransformsBuffer = void 0; this.instancingTransformsBuffer2D = void 0; this.instancingTranslationBuffer2D = void 0; this.instancingReferencePoint2D = void 0; initialize10(this); } Object.defineProperties(ModelRuntimeNode.prototype, { /** * The internal node this runtime node represents. * * @memberof ModelRuntimeNode.prototype * @type {ModelComponents.Node} * @readonly * * @private */ node: { get: function() { return this._node; } }, /** * The scene graph this node belongs to. * * @memberof ModelRuntimeNode.prototype * @type {ModelSceneGraph} * @readonly * * @private */ sceneGraph: { get: function() { return this._sceneGraph; } }, /** * The indices of the children of this node in the scene graph. * * @memberof ModelRuntimeNode.prototype * @type {number[]} * @readonly * * @private */ children: { get: function() { return this._children; } }, /** * The node's local space transform. This can be changed externally via * the corresponding {@link ModelNode}, such that animation can be * driven by another source, not just an animation in the model's asset. * * @memberof ModelRuntimeNode.prototype * @type {Matrix4} * * @private */ transform: { get: function() { return this._transform; }, set: function(value) { this._transformDirty = true; this._transform = Matrix4_default.clone(value, this._transform); } }, /** * The transforms of all the node's ancestors, not including this node's * transform. * * @see ModelRuntimeNode#computedTransform * * @memberof ModelRuntimeNode.prototype * @type {Matrix4} * @readonly * * @private */ transformToRoot: { get: function() { return this._transformToRoot; } }, /** * A transform from the node's local space to the model's scene graph space. * This is the product of transformToRoot * transform. * * @memberof ModelRuntimeNode.prototype * @type {Matrix4} * @readonly * * @private */ computedTransform: { get: function() { return this._computedTransform; } }, /** * The node's original transform, as specified in the model. * Does not include transformations from the node's ancestors. * * @memberof ModelRuntimeNode.prototype * @type {Matrix4} * @readonly * * @private */ originalTransform: { get: function() { return this._originalTransform; } }, /** * The node's local space translation. This is used internally to allow * animations in the model's asset to affect the node's properties. * * If the node's transformation was originally described using a matrix * in the model, then this will return undefined. * * @memberof ModelRuntimeNode.prototype * @type {Cartesian3} * * @exception {DeveloperError} The translation of a node cannot be set if it was defined using a matrix in the model's asset. * * @private */ translation: { get: function() { return defined_default(this._transformParameters) ? this._transformParameters.translation : void 0; }, set: function(value) { const transformParameters = this._transformParameters; if (!defined_default(transformParameters)) { throw new DeveloperError_default( "The translation of a node cannot be set if it was defined using a matrix in the model." ); } const currentTranslation = transformParameters.translation; if (Cartesian3_default.equals(currentTranslation, value)) { return; } transformParameters.translation = Cartesian3_default.clone( value, transformParameters.translation ); updateTransformFromParameters(this, transformParameters); } }, /** * The node's local space rotation. This is used internally to allow * animations in the model's asset to affect the node's properties. * * If the node's transformation was originally described using a matrix * in the model, then this will return undefined. * * @memberof ModelRuntimeNode.prototype * @type {Quaternion} * * @exception {DeveloperError} The rotation of a node cannot be set if it was defined using a matrix in the model's asset. * * @private */ rotation: { get: function() { return defined_default(this._transformParameters) ? this._transformParameters.rotation : void 0; }, set: function(value) { const transformParameters = this._transformParameters; if (!defined_default(transformParameters)) { throw new DeveloperError_default( "The rotation of a node cannot be set if it was defined using a matrix in the model." ); } const currentRotation = transformParameters.rotation; if (Quaternion_default.equals(currentRotation, value)) { return; } transformParameters.rotation = Quaternion_default.clone( value, transformParameters.rotation ); updateTransformFromParameters(this, transformParameters); } }, /** * The node's local space scale. This is used internally to allow * animations in the model's asset to affect the node's properties. * * If the node's transformation was originally described using a matrix * in the model, then this will return undefined. * * @memberof ModelRuntimeNode.prototype * @type {Cartesian3} * * @exception {DeveloperError} The scale of a node cannot be set if it was defined using a matrix in the model's asset. * @private */ scale: { get: function() { return defined_default(this._transformParameters) ? this._transformParameters.scale : void 0; }, set: function(value) { const transformParameters = this._transformParameters; if (!defined_default(transformParameters)) { throw new DeveloperError_default( "The scale of a node cannot be set if it was defined using a matrix in the model." ); } const currentScale = transformParameters.scale; if (Cartesian3_default.equals(currentScale, value)) { return; } transformParameters.scale = Cartesian3_default.clone( value, transformParameters.scale ); updateTransformFromParameters(this, transformParameters); } }, /** * The node's morph weights. This is used internally to allow animations * in the model's asset to affect the node's properties. * * @memberof ModelRuntimeNode.prototype * @type {number[]} * * @private */ morphWeights: { get: function() { return this._morphWeights; }, set: function(value) { const valueLength = value.length; if (this._morphWeights.length !== valueLength) { throw new DeveloperError_default( "value must have the same length as the original weights array." ); } for (let i = 0; i < valueLength; i++) { this._morphWeights[i] = value[i]; } } }, /** * The skin applied to this node, if it exists. * * @memberof ModelRuntimeNode.prototype * @type {ModelSkin} * @readonly * * @private */ runtimeSkin: { get: function() { return this._runtimeSkin; } }, /** * The computed joint matrices of this node, derived from its skin. * * @memberof ModelRuntimeNode.prototype * @type {Matrix4[]} * @readonly * * @private */ computedJointMatrices: { get: function() { return this._computedJointMatrices; } } }); function initialize10(runtimeNode) { const transform3 = runtimeNode.transform; const transformToRoot = runtimeNode.transformToRoot; const computedTransform = runtimeNode._computedTransform; runtimeNode._computedTransform = Matrix4_default.multiply( transformToRoot, transform3, computedTransform ); const node = runtimeNode.node; if (!defined_default(node.matrix)) { runtimeNode._transformParameters = new TranslationRotationScale_default( node.translation, node.rotation, node.scale ); } if (defined_default(node.morphWeights)) { runtimeNode._morphWeights = node.morphWeights.slice(); } const articulationName = node.articulationName; if (defined_default(articulationName)) { const sceneGraph = runtimeNode.sceneGraph; const runtimeArticulations = sceneGraph._runtimeArticulations; const runtimeArticulation = runtimeArticulations[articulationName]; if (defined_default(runtimeArticulation)) { runtimeArticulation.runtimeNodes.push(runtimeNode); } } } function updateTransformFromParameters(runtimeNode, transformParameters) { runtimeNode._transformDirty = true; runtimeNode._transform = Matrix4_default.fromTranslationRotationScale( transformParameters, runtimeNode._transform ); } ModelRuntimeNode.prototype.getChild = function(index) { Check_default.typeOf.number("index", index); if (index < 0 || index >= this.children.length) { throw new DeveloperError_default( "index must be greater than or equal to 0 and less than the number of children." ); } return this.sceneGraph._runtimeNodes[this.children[index]]; }; ModelRuntimeNode.prototype.configurePipeline = function() { const node = this.node; const pipelineStages = this.pipelineStages; pipelineStages.length = 0; const updateStages = this.updateStages; updateStages.length = 0; if (defined_default(node.instances)) { pipelineStages.push(InstancingPipelineStage_default); } pipelineStages.push(NodeStatisticsPipelineStage_default); updateStages.push(ModelMatrixUpdateStage_default); }; ModelRuntimeNode.prototype.updateComputedTransform = function() { this._computedTransform = Matrix4_default.multiply( this._transformToRoot, this._transform, this._computedTransform ); }; ModelRuntimeNode.prototype.updateJointMatrices = function() { const runtimeSkin = this._runtimeSkin; if (!defined_default(runtimeSkin)) { return; } runtimeSkin.updateJointMatrices(); const computedJointMatrices = this._computedJointMatrices; const skinJointMatrices = runtimeSkin.jointMatrices; const length2 = skinJointMatrices.length; for (let i = 0; i < length2; i++) { if (!defined_default(computedJointMatrices[i])) { computedJointMatrices[i] = new Matrix4_default(); } const nodeWorldTransform = Matrix4_default.multiplyTransformation( this.transformToRoot, this.transform, computedJointMatrices[i] ); const inverseNodeWorldTransform = Matrix4_default.inverseTransformation( nodeWorldTransform, computedJointMatrices[i] ); computedJointMatrices[i] = Matrix4_default.multiplyTransformation( inverseNodeWorldTransform, skinJointMatrices[i], computedJointMatrices[i] ); } }; var ModelRuntimeNode_default = ModelRuntimeNode; // packages/engine/Source/Scene/Model/ModelRuntimePrimitive.js var import_InlineWorkers712 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/Model/AlphaPipelineStage.js var import_InlineWorkers626 = __toESM(require_InlineWorkers(), 1); var AlphaPipelineStage = { name: "AlphaPipelineStage" // Helps with debugging }; AlphaPipelineStage.process = function(renderResources, primitive, frameState) { const alphaOptions = renderResources.alphaOptions; const model = renderResources.model; alphaOptions.pass = alphaOptions.pass ?? model.opaquePass; const renderStateOptions = renderResources.renderStateOptions; if (alphaOptions.pass === Pass_default.TRANSLUCENT) { renderStateOptions.cull.enabled = false; renderStateOptions.depthMask = false; renderStateOptions.blending = BlendingState_default.ALPHA_BLEND; } const shaderBuilder = renderResources.shaderBuilder; const uniformMap2 = renderResources.uniformMap; if (defined_default(alphaOptions.alphaCutoff)) { shaderBuilder.addDefine( "ALPHA_MODE_MASK", void 0, ShaderDestination_default.FRAGMENT ); shaderBuilder.addUniform( "float", "u_alphaCutoff", ShaderDestination_default.FRAGMENT ); uniformMap2.u_alphaCutoff = function() { return alphaOptions.alphaCutoff; }; } }; var AlphaPipelineStage_default = AlphaPipelineStage; // packages/engine/Source/Scene/Model/BatchTexturePipelineStage.js var import_InlineWorkers627 = __toESM(require_InlineWorkers(), 1); var BatchTexturePipelineStage = { name: "BatchTexturePipelineStage" // Helps with debugging }; BatchTexturePipelineStage.process = function(renderResources, primitive, frameState) { const shaderBuilder = renderResources.shaderBuilder; const batchTextureUniforms = {}; const model = renderResources.model; const featureTable = model.featureTables[model.featureTableId]; const featuresLength = featureTable.featuresLength; shaderBuilder.addUniform("int", "model_featuresLength"); batchTextureUniforms.model_featuresLength = function() { return featuresLength; }; const batchTexture = featureTable.batchTexture; shaderBuilder.addUniform("sampler2D", "model_batchTexture"); batchTextureUniforms.model_batchTexture = function() { return batchTexture.batchTexture ?? batchTexture.defaultTexture; }; shaderBuilder.addUniform("vec4", "model_textureStep"); batchTextureUniforms.model_textureStep = function() { return batchTexture.textureStep; }; if (batchTexture.textureDimensions.y > 1) { shaderBuilder.addDefine("MULTILINE_BATCH_TEXTURE"); shaderBuilder.addUniform("vec2", "model_textureDimensions"); batchTextureUniforms.model_textureDimensions = function() { return batchTexture.textureDimensions; }; } renderResources.uniformMap = combine_default( batchTextureUniforms, renderResources.uniformMap ); }; var BatchTexturePipelineStage_default = BatchTexturePipelineStage; // packages/engine/Source/Scene/Model/ClassificationPipelineStage.js var import_InlineWorkers628 = __toESM(require_InlineWorkers(), 1); var ClassificationPipelineStage = { name: "ClassificationPipelineStage" // Helps with debugging }; ClassificationPipelineStage.process = function(renderResources, primitive, frameState) { const shaderBuilder = renderResources.shaderBuilder; shaderBuilder.addDefine( "HAS_CLASSIFICATION", void 0, ShaderDestination_default.BOTH ); const runtimePrimitive = renderResources.runtimePrimitive; if (!defined_default(runtimePrimitive.batchLengths)) { createClassificationBatches(primitive, runtimePrimitive); } }; function createClassificationBatches(primitive, runtimePrimitive) { const positionAttribute = ModelUtility_default.getAttributeBySemantic( primitive, VertexAttributeSemantic_default.POSITION ); if (!defined_default(positionAttribute)) { throw new RuntimeError_default( "Primitives must have a position attribute to be used for classification." ); } let indicesArray; const indices = primitive.indices; const hasIndices = defined_default(indices); if (hasIndices) { indicesArray = indices.typedArray; indices.typedArray = void 0; } const count = hasIndices ? indices.count : positionAttribute.count; const featureIdAttribute = ModelUtility_default.getAttributeBySemantic( primitive, VertexAttributeSemantic_default.FEATURE_ID, 0 ); if (!defined_default(featureIdAttribute)) { runtimePrimitive.batchLengths = [count]; runtimePrimitive.batchOffsets = [0]; return; } const featureIds = featureIdAttribute.typedArray; featureIdAttribute.typedArray = void 0; const batchLengths = []; const batchOffsets = [0]; const firstIndex = hasIndices ? indicesArray[0] : 0; let currentBatchId = featureIds[firstIndex]; let currentOffset = 0; for (let i = 1; i < count; i++) { const index = hasIndices ? indicesArray[i] : i; const batchId = featureIds[index]; if (batchId !== currentBatchId) { const batchLength = i - currentOffset; const newOffset = i; batchLengths.push(batchLength); batchOffsets.push(newOffset); currentOffset = newOffset; currentBatchId = batchId; } } const finalBatchLength = count - currentOffset; batchLengths.push(finalBatchLength); runtimePrimitive.batchLengths = batchLengths; runtimePrimitive.batchOffsets = batchOffsets; } var ClassificationPipelineStage_default = ClassificationPipelineStage; // packages/engine/Source/Scene/Model/CPUStylingPipelineStage.js var import_InlineWorkers631 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Shaders/Model/CPUStylingStageVS.js var import_InlineWorkers629 = __toESM(require_InlineWorkers(), 1); var CPUStylingStageVS_default = "void filterByPassType(inout vec3 positionMC, vec4 featureColor)\n{\n bool styleTranslucent = (featureColor.a != 1.0);\n // Only render translucent features in the translucent pass (if the style or the original command has translucency).\n if (czm_pass == czm_passTranslucent && !styleTranslucent && !model_commandTranslucent)\n {\n // If the model has a translucent silhouette, it needs to render during the silhouette color command,\n // (i.e. the command where model_silhouettePass = true), even if the model isn't translucent.\n #ifdef HAS_SILHOUETTE\n positionMC *= float(model_silhouettePass);\n #else\n positionMC *= 0.0;\n #endif\n }\n // If the current pass is not the translucent pass and the style is not translucent, don't render the feature.\n else if (czm_pass != czm_passTranslucent && styleTranslucent)\n {\n positionMC *= 0.0;\n }\n}\n\nvoid cpuStylingStage(inout vec3 positionMC, inout SelectedFeature feature)\n{\n float show = ceil(feature.color.a);\n positionMC *= show;\n\n #if defined(HAS_SELECTED_FEATURE_ID_ATTRIBUTE) && !defined(HAS_CLASSIFICATION)\n filterByPassType(positionMC, feature.color);\n #endif\n}\n"; // packages/engine/Source/Shaders/Model/CPUStylingStageFS.js var import_InlineWorkers630 = __toESM(require_InlineWorkers(), 1); var CPUStylingStageFS_default = "void filterByPassType(vec4 featureColor)\n{\n bool styleTranslucent = (featureColor.a != 1.0);\n // Only render translucent features in the translucent pass (if the style or the original command has translucency).\n if (czm_pass == czm_passTranslucent && !styleTranslucent && !model_commandTranslucent)\n { \n // If the model has a translucent silhouette, it needs to render during the silhouette color command,\n // (i.e. the command where model_silhouettePass = true), even if the model isn't translucent.\n #ifdef HAS_SILHOUETTE\n if(!model_silhouettePass) {\n discard;\n }\n #else\n discard;\n #endif\n }\n // If the current pass is not the translucent pass and the style is not translucent, don't render the feature.\n else if (czm_pass != czm_passTranslucent && styleTranslucent)\n {\n discard;\n }\n}\n\nvoid cpuStylingStage(inout czm_modelMaterial material, SelectedFeature feature)\n{\n vec4 featureColor = feature.color;\n if (featureColor.a == 0.0)\n {\n discard;\n }\n\n // If a feature ID vertex attribute is used, the pass type filter is applied in the vertex shader.\n // So, we only apply in in the fragment shader if the feature ID texture is used.\n #if defined(HAS_SELECTED_FEATURE_ID_TEXTURE) && !defined(HAS_CLASSIFICATION)\n filterByPassType(featureColor);\n #endif\n\n featureColor = czm_gammaCorrect(featureColor);\n\n // Classification models compute the diffuse differently.\n #ifdef HAS_CLASSIFICATION\n material.diffuse = featureColor.rgb * featureColor.a;\n #else\n float highlight = ceil(model_colorBlend);\n material.diffuse *= mix(featureColor.rgb, vec3(1.0), highlight);\n #endif\n \n material.alpha *= featureColor.a;\n}\n"; // packages/engine/Source/Scene/Model/CPUStylingPipelineStage.js var CPUStylingPipelineStage = { name: "CPUStylingPipelineStage" // Helps with debugging }; CPUStylingPipelineStage.process = function(renderResources, primitive, frameState) { const model = renderResources.model; const shaderBuilder = renderResources.shaderBuilder; shaderBuilder.addVertexLines(CPUStylingStageVS_default); shaderBuilder.addFragmentLines(CPUStylingStageFS_default); shaderBuilder.addDefine("USE_CPU_STYLING", void 0, ShaderDestination_default.BOTH); if (!defined_default(model.color)) { shaderBuilder.addUniform( "float", ModelColorPipelineStage_default.COLOR_BLEND_UNIFORM_NAME, ShaderDestination_default.FRAGMENT ); renderResources.uniformMap[ModelColorPipelineStage_default.COLOR_BLEND_UNIFORM_NAME] = function() { return ColorBlendMode_default.getColorBlend( model.colorBlendMode, model.colorBlendAmount ); }; } shaderBuilder.addUniform( "bool", "model_commandTranslucent", ShaderDestination_default.BOTH ); renderResources.uniformMap.model_commandTranslucent = function() { return renderResources.alphaOptions.pass === Pass_default.TRANSLUCENT; }; }; var CPUStylingPipelineStage_default = CPUStylingPipelineStage; // packages/engine/Source/Scene/Model/CustomShaderMode.js var import_InlineWorkers632 = __toESM(require_InlineWorkers(), 1); var CustomShaderMode = { /** * The custom shader will be used to modify the results of the material stage * before lighting is applied. * * @type {string} * @constant */ MODIFY_MATERIAL: "MODIFY_MATERIAL", /** * The custom shader will be used instead of the material stage. This is a hint * to optimize out the material processing code. * * @type {string} * @constant */ REPLACE_MATERIAL: "REPLACE_MATERIAL" }; CustomShaderMode.getDefineName = function(customShaderMode) { return `CUSTOM_SHADER_${customShaderMode}`; }; var CustomShaderMode_default = Object.freeze(CustomShaderMode); // packages/engine/Source/Scene/Model/CustomShaderPipelineStage.js var import_InlineWorkers642 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Shaders/Model/CustomShaderStageVS.js var import_InlineWorkers633 = __toESM(require_InlineWorkers(), 1); var CustomShaderStageVS_default = "void customShaderStage(\n inout czm_modelVertexOutput vsOutput, \n inout ProcessedAttributes attributes, \n FeatureIds featureIds,\n Metadata metadata,\n MetadataClass metadataClass,\n MetadataStatistics metadataStatistics\n) {\n // VertexInput and initializeInputStruct() are dynamically generated in JS, \n // see CustomShaderPipelineStage.js\n VertexInput vsInput;\n initializeInputStruct(vsInput, attributes);\n vsInput.featureIds = featureIds;\n vsInput.metadata = metadata;\n vsInput.metadataClass = metadataClass;\n vsInput.metadataStatistics = metadataStatistics;\n vertexMain(vsInput, vsOutput);\n attributes.positionMC = vsOutput.positionMC;\n}\n"; // packages/engine/Source/Shaders/Model/CustomShaderStageFS.js var import_InlineWorkers634 = __toESM(require_InlineWorkers(), 1); var CustomShaderStageFS_default = "void customShaderStage(\n inout czm_modelMaterial material,\n ProcessedAttributes attributes,\n FeatureIds featureIds,\n Metadata metadata,\n MetadataClass metadataClass,\n MetadataStatistics metadataStatistics\n) {\n // FragmentInput and initializeInputStruct() are dynamically generated in JS, \n // see CustomShaderPipelineStage.js\n FragmentInput fsInput;\n initializeInputStruct(fsInput, attributes);\n fsInput.featureIds = featureIds;\n fsInput.metadata = metadata;\n fsInput.metadataClass = metadataClass;\n fsInput.metadataStatistics = metadataStatistics;\n fragmentMain(fsInput, material);\n}\n"; // packages/engine/Source/Scene/Model/FeatureIdPipelineStage.js var import_InlineWorkers637 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Shaders/Model/FeatureIdStageFS.js var import_InlineWorkers635 = __toESM(require_InlineWorkers(), 1); var FeatureIdStageFS_default = "void featureIdStage(out FeatureIds featureIds, ProcessedAttributes attributes) {\n initializeFeatureIds(featureIds, attributes);\n initializeFeatureIdAliases(featureIds);\n}\n"; // packages/engine/Source/Shaders/Model/FeatureIdStageVS.js var import_InlineWorkers636 = __toESM(require_InlineWorkers(), 1); var FeatureIdStageVS_default = "void featureIdStage(out FeatureIds featureIds, ProcessedAttributes attributes) \n{\n initializeFeatureIds(featureIds, attributes);\n initializeFeatureIdAliases(featureIds);\n setFeatureIdVaryings();\n}\n"; // packages/engine/Source/Scene/Model/FeatureIdPipelineStage.js var FeatureIdPipelineStage = { name: "FeatureIdPipelineStage", // Helps with debugging STRUCT_ID_FEATURE_IDS_VS: "FeatureIdsVS", STRUCT_ID_FEATURE_IDS_FS: "FeatureIdsFS", STRUCT_NAME_FEATURE_IDS: "FeatureIds", FUNCTION_ID_INITIALIZE_FEATURE_IDS_VS: "initializeFeatureIdsVS", FUNCTION_ID_INITIALIZE_FEATURE_IDS_FS: "initializeFeatureIdsFS", FUNCTION_ID_INITIALIZE_FEATURE_ID_ALIASES_VS: "initializeFeatureIdAliasesVS", FUNCTION_ID_INITIALIZE_FEATURE_ID_ALIASES_FS: "initializeFeatureIdAliasesFS", FUNCTION_SIGNATURE_INITIALIZE_FEATURE_IDS: "void initializeFeatureIds(out FeatureIds featureIds, ProcessedAttributes attributes)", FUNCTION_SIGNATURE_INITIALIZE_FEATURE_ID_ALIASES: "void initializeFeatureIdAliases(inout FeatureIds featureIds)", FUNCTION_ID_SET_FEATURE_ID_VARYINGS: "setFeatureIdVaryings", FUNCTION_SIGNATURE_SET_FEATURE_ID_VARYINGS: "void setFeatureIdVaryings()" }; FeatureIdPipelineStage.process = function(renderResources, primitive, frameState) { const shaderBuilder = renderResources.shaderBuilder; declareStructsAndFunctions(shaderBuilder); const instances = renderResources.runtimeNode.node.instances; if (defined_default(instances)) { processInstanceFeatureIds(renderResources, instances, frameState); } processPrimitiveFeatureIds(renderResources, primitive, frameState); shaderBuilder.addVertexLines(FeatureIdStageVS_default); shaderBuilder.addFragmentLines(FeatureIdStageFS_default); }; function declareStructsAndFunctions(shaderBuilder) { shaderBuilder.addStruct( FeatureIdPipelineStage.STRUCT_ID_FEATURE_IDS_VS, FeatureIdPipelineStage.STRUCT_NAME_FEATURE_IDS, ShaderDestination_default.VERTEX ); shaderBuilder.addStruct( FeatureIdPipelineStage.STRUCT_ID_FEATURE_IDS_FS, FeatureIdPipelineStage.STRUCT_NAME_FEATURE_IDS, ShaderDestination_default.FRAGMENT ); shaderBuilder.addFunction( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_IDS_VS, FeatureIdPipelineStage.FUNCTION_SIGNATURE_INITIALIZE_FEATURE_IDS, ShaderDestination_default.VERTEX ); shaderBuilder.addFunction( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_IDS_FS, FeatureIdPipelineStage.FUNCTION_SIGNATURE_INITIALIZE_FEATURE_IDS, ShaderDestination_default.FRAGMENT ); shaderBuilder.addFunction( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_ID_ALIASES_VS, FeatureIdPipelineStage.FUNCTION_SIGNATURE_INITIALIZE_FEATURE_ID_ALIASES, ShaderDestination_default.VERTEX ); shaderBuilder.addFunction( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_ID_ALIASES_FS, FeatureIdPipelineStage.FUNCTION_SIGNATURE_INITIALIZE_FEATURE_ID_ALIASES, ShaderDestination_default.FRAGMENT ); shaderBuilder.addFunction( FeatureIdPipelineStage.FUNCTION_ID_SET_FEATURE_ID_VARYINGS, FeatureIdPipelineStage.FUNCTION_SIGNATURE_SET_FEATURE_ID_VARYINGS, ShaderDestination_default.VERTEX ); } function processInstanceFeatureIds(renderResources, instances, frameState) { const featureIdsArray = instances.featureIds; const count = instances.attributes[0].count; for (let i = 0; i < featureIdsArray.length; i++) { const featureIds = featureIdsArray[i]; const variableName = featureIds.positionalLabel; if (featureIds instanceof ModelComponents_default.FeatureIdAttribute) { processInstanceAttribute(renderResources, featureIds, variableName); } else { const instanceDivisor = 1; processImplicitRange( renderResources, featureIds, variableName, count, instanceDivisor, frameState ); } const label = featureIds.label; if (defined_default(label)) { addAlias(renderResources, variableName, label, ShaderDestination_default.BOTH); } } } function processPrimitiveFeatureIds(renderResources, primitive, frameState) { const featureIdsArray = primitive.featureIds; const positionAttribute = ModelUtility_default.getAttributeBySemantic( primitive, VertexAttributeSemantic_default.POSITION ); const count = positionAttribute.count; for (let i = 0; i < featureIdsArray.length; i++) { const featureIds = featureIdsArray[i]; const variableName = featureIds.positionalLabel; let aliasDestination = ShaderDestination_default.BOTH; if (featureIds instanceof ModelComponents_default.FeatureIdAttribute) { processAttribute(renderResources, featureIds, variableName); } else if (featureIds instanceof ModelComponents_default.FeatureIdImplicitRange) { processImplicitRange( renderResources, featureIds, variableName, count, void 0, frameState ); } else { processTexture(renderResources, featureIds, variableName, i, frameState); aliasDestination = ShaderDestination_default.FRAGMENT; } const label = featureIds.label; if (defined_default(label)) { addAlias(renderResources, variableName, label, aliasDestination); } } } function processInstanceAttribute(renderResources, featureIdAttribute, variableName) { const shaderBuilder = renderResources.shaderBuilder; shaderBuilder.addStructField( FeatureIdPipelineStage.STRUCT_ID_FEATURE_IDS_VS, "int", variableName ); shaderBuilder.addStructField( FeatureIdPipelineStage.STRUCT_ID_FEATURE_IDS_FS, "int", variableName ); const setIndex = featureIdAttribute.setIndex; const prefix = variableName.replace(/_\d+$/, "_"); const attributeName = `a_${prefix}${setIndex}`; const varyingName = `v_${prefix}${setIndex}`; const vertexLine = `featureIds.${variableName} = int(czm_round(${attributeName}));`; const fragmentLine = `featureIds.${variableName} = int(czm_round(${varyingName}));`; shaderBuilder.addFunctionLines( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_IDS_VS, [vertexLine] ); shaderBuilder.addFunctionLines( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_IDS_FS, [fragmentLine] ); shaderBuilder.addVarying("float", varyingName); shaderBuilder.addFunctionLines( FeatureIdPipelineStage.FUNCTION_ID_SET_FEATURE_ID_VARYINGS, [`${varyingName} = ${attributeName};`] ); } function processAttribute(renderResources, featureIdAttribute, variableName) { const shaderBuilder = renderResources.shaderBuilder; shaderBuilder.addStructField( FeatureIdPipelineStage.STRUCT_ID_FEATURE_IDS_VS, "int", variableName ); shaderBuilder.addStructField( FeatureIdPipelineStage.STRUCT_ID_FEATURE_IDS_FS, "int", variableName ); const setIndex = featureIdAttribute.setIndex; const prefix = variableName.replace(/_\d+$/, "_"); const initializationLines = [ `featureIds.${variableName} = int(czm_round(attributes.${prefix}${setIndex}));` ]; shaderBuilder.addFunctionLines( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_IDS_VS, initializationLines ); shaderBuilder.addFunctionLines( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_IDS_FS, initializationLines ); } function processImplicitRange(renderResources, implicitFeatureIds, variableName, count, instanceDivisor, frameState) { generateImplicitFeatureIdAttribute( renderResources, implicitFeatureIds, count, instanceDivisor, frameState ); const shaderBuilder = renderResources.shaderBuilder; const implicitAttributeName = `a_implicit_${variableName}`; shaderBuilder.addAttribute("float", implicitAttributeName); const implicitVaryingName = `v_implicit_${variableName}`; shaderBuilder.addVarying("float", implicitVaryingName); shaderBuilder.addStructField( FeatureIdPipelineStage.STRUCT_ID_FEATURE_IDS_VS, "int", variableName ); shaderBuilder.addStructField( FeatureIdPipelineStage.STRUCT_ID_FEATURE_IDS_FS, "int", variableName ); shaderBuilder.addFunctionLines( FeatureIdPipelineStage.FUNCTION_ID_SET_FEATURE_ID_VARYINGS, [`${implicitVaryingName} = ${implicitAttributeName};`] ); shaderBuilder.addFunctionLines( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_IDS_VS, [`featureIds.${variableName} = int(czm_round(${implicitAttributeName}));`] ); shaderBuilder.addFunctionLines( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_IDS_FS, [`featureIds.${variableName} = int(czm_round(${implicitVaryingName}));`] ); } function processTexture(renderResources, featureIdTexture, variableName, index, frameState) { const uniformName = `u_featureIdTexture_${index}`; const uniformMap2 = renderResources.uniformMap; const textureReader = featureIdTexture.textureReader; uniformMap2[uniformName] = function() { return textureReader.texture ?? frameState.context.defaultTexture; }; const channels = textureReader.channels; const shaderBuilder = renderResources.shaderBuilder; shaderBuilder.addStructField( FeatureIdPipelineStage.STRUCT_ID_FEATURE_IDS_FS, "int", variableName ); shaderBuilder.addUniform( "sampler2D", uniformName, ShaderDestination_default.FRAGMENT ); const texCoord = textureReader.texCoord; const texCoordVariable = `v_texCoord_${texCoord}`; let texCoordVariableExpression = texCoordVariable; const transform3 = textureReader.transform; if (defined_default(transform3) && !Matrix3_default.equals(transform3, Matrix3_default.IDENTITY)) { const transformUniformName = `${uniformName}Transform`; shaderBuilder.addUniform( "mat3", transformUniformName, ShaderDestination_default.FRAGMENT ); uniformMap2[transformUniformName] = function() { return transform3; }; texCoordVariableExpression = `vec2(${transformUniformName} * vec3(${texCoordVariable}, 1.0))`; } const textureRead = `texture(${uniformName}, ${texCoordVariableExpression}).${channels}`; const initializationLine = `featureIds.${variableName} = czm_unpackUint(${textureRead});`; shaderBuilder.addFunctionLines( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_IDS_FS, [initializationLine] ); } function addAlias(renderResources, variableName, alias, shaderDestination) { const shaderBuilder = renderResources.shaderBuilder; const updateVS = ShaderDestination_default.includesVertexShader(shaderDestination); if (updateVS) { shaderBuilder.addStructField( FeatureIdPipelineStage.STRUCT_ID_FEATURE_IDS_VS, "int", alias ); } shaderBuilder.addStructField( FeatureIdPipelineStage.STRUCT_ID_FEATURE_IDS_FS, "int", alias ); const initializationLines = [ `featureIds.${alias} = featureIds.${variableName};` ]; if (updateVS) { shaderBuilder.addFunctionLines( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_ID_ALIASES_VS, initializationLines ); } shaderBuilder.addFunctionLines( FeatureIdPipelineStage.FUNCTION_ID_INITIALIZE_FEATURE_ID_ALIASES_FS, initializationLines ); } function generateImplicitFeatureIdAttribute(renderResources, implicitFeatureIds, count, instanceDivisor, frameState) { const model = renderResources.model; let vertexBuffer; let value; if (defined_default(implicitFeatureIds.repeat)) { const typedArray = generateImplicitFeatureIdTypedArray( implicitFeatureIds, count ); vertexBuffer = Buffer_default.createVertexBuffer({ context: frameState.context, typedArray, usage: BufferUsage_default.STATIC_DRAW }); vertexBuffer.vertexArrayDestroyable = false; model._pipelineResources.push(vertexBuffer); const hasCpuCopy = false; model.statistics.addBuffer(vertexBuffer, hasCpuCopy); } else { value = [implicitFeatureIds.offset]; } const generatedFeatureIdAttribute = { index: renderResources.attributeIndex++, instanceDivisor, value, vertexBuffer, normalize: false, componentsPerAttribute: 1, componentDatatype: ComponentDatatype_default.FLOAT, strideInBytes: ComponentDatatype_default.getSizeInBytes(ComponentDatatype_default.FLOAT), offsetInBytes: 0 }; renderResources.attributes.push(generatedFeatureIdAttribute); } function generateImplicitFeatureIdTypedArray(implicitFeatureIds, count) { const offset = implicitFeatureIds.offset; const repeat = implicitFeatureIds.repeat; const typedArray = new Float32Array(count); for (let i = 0; i < count; i++) { typedArray[i] = offset + Math.floor(i / repeat); } return typedArray; } var FeatureIdPipelineStage_default = FeatureIdPipelineStage; // packages/engine/Source/Scene/Model/MetadataPipelineStage.js var import_InlineWorkers640 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Shaders/Model/MetadataStageFS.js var import_InlineWorkers638 = __toESM(require_InlineWorkers(), 1); var MetadataStageFS_default = "void metadataStage(\n out Metadata metadata,\n out MetadataClass metadataClass,\n out MetadataStatistics metadataStatistics,\n ProcessedAttributes attributes\n )\n{\n initializeMetadata(metadata, metadataClass, metadataStatistics, attributes);\n}\n"; // packages/engine/Source/Shaders/Model/MetadataStageVS.js var import_InlineWorkers639 = __toESM(require_InlineWorkers(), 1); var MetadataStageVS_default = "void metadataStage(\n out Metadata metadata,\n out MetadataClass metadataClass,\n out MetadataStatistics metadataStatistics,\n ProcessedAttributes attributes\n )\n{\n initializeMetadata(metadata, metadataClass, metadataStatistics, attributes);\n setMetadataVaryings();\n}\n"; // packages/engine/Source/Scene/Model/MetadataPipelineStage.js var MetadataPipelineStage = { name: "MetadataPipelineStage", STRUCT_ID_METADATA_VS: "MetadataVS", STRUCT_ID_METADATA_FS: "MetadataFS", STRUCT_NAME_METADATA: "Metadata", STRUCT_ID_METADATA_CLASS_VS: "MetadataClassVS", STRUCT_ID_METADATA_CLASS_FS: "MetadataClassFS", STRUCT_NAME_METADATA_CLASS: "MetadataClass", STRUCT_ID_METADATA_STATISTICS_VS: "MetadataStatisticsVS", STRUCT_ID_METADATA_STATISTICS_FS: "MetadataStatisticsFS", STRUCT_NAME_METADATA_STATISTICS: "MetadataStatistics", FUNCTION_ID_INITIALIZE_METADATA_VS: "initializeMetadataVS", FUNCTION_ID_INITIALIZE_METADATA_FS: "initializeMetadataFS", FUNCTION_SIGNATURE_INITIALIZE_METADATA: "void initializeMetadata(out Metadata metadata, out MetadataClass metadataClass, out MetadataStatistics metadataStatistics, ProcessedAttributes attributes)", FUNCTION_ID_SET_METADATA_VARYINGS: "setMetadataVaryings", FUNCTION_SIGNATURE_SET_METADATA_VARYINGS: "void setMetadataVaryings()", // Metadata class and statistics fields: // - some must be renamed to avoid reserved words // - some always have float/vec values, even for integer/ivec property types METADATA_CLASS_FIELDS: [ { specName: "noData", shaderName: "noData" }, { specName: "default", shaderName: "defaultValue" }, { specName: "min", shaderName: "minValue" }, { specName: "max", shaderName: "maxValue" } ], METADATA_STATISTICS_FIELDS: [ { specName: "min", shaderName: "minValue" }, { specName: "max", shaderName: "maxValue" }, { specName: "mean", shaderName: "mean", type: "float" }, { specName: "median", shaderName: "median" }, { specName: "standardDeviation", shaderName: "standardDeviation", type: "float" }, { specName: "variance", shaderName: "variance", type: "float" }, { specName: "sum", shaderName: "sum" } ] }; MetadataPipelineStage.process = function(renderResources, primitive, frameState) { const { shaderBuilder, model } = renderResources; const { structuralMetadata = {}, content } = model; const statistics2 = content?.tileset.metadataExtension?.statistics; const propertyAttributesInfo = getPropertyAttributesInfo( structuralMetadata.propertyAttributes, primitive, statistics2 ); const propertyTexturesInfo = getPropertyTexturesInfo( structuralMetadata.propertyTextures, statistics2 ); const allPropertyInfos = propertyAttributesInfo.concat(propertyTexturesInfo); declareMetadataTypeStructs(shaderBuilder, allPropertyInfos); declareStructsAndFunctions2(shaderBuilder); shaderBuilder.addVertexLines(MetadataStageVS_default); shaderBuilder.addFragmentLines(MetadataStageFS_default); for (let i = 0; i < propertyAttributesInfo.length; i++) { const info = propertyAttributesInfo[i]; processPropertyAttributeProperty(renderResources, info); } for (let i = 0; i < propertyTexturesInfo.length; i++) { const info = propertyTexturesInfo[i]; processPropertyTextureProperty(renderResources, info); } }; function getPropertyAttributesInfo(propertyAttributes, primitive, statistics2) { if (!defined_default(propertyAttributes)) { return []; } return propertyAttributes.flatMap( (propertyAttribute) => getPropertyAttributeInfo(propertyAttribute, primitive, statistics2) ); } function getPropertyAttributeInfo(propertyAttribute, primitive, statistics2) { const { getAttributeByName, getAttributeInfo: getAttributeInfo2, sanitizeGlslIdentifier } = ModelUtility_default; const classId = propertyAttribute.class.id; const classStatistics = statistics2?.classes[classId]; const propertiesArray = Object.entries(propertyAttribute.properties); const infoArray = new Array(propertiesArray.length); for (let i = 0; i < propertiesArray.length; i++) { const [propertyId, property] = propertiesArray[i]; const modelAttribute = getAttributeByName(primitive, property.attribute); const { glslType, variableName } = getAttributeInfo2(modelAttribute); infoArray[i] = { metadataVariable: sanitizeGlslIdentifier(propertyId), property, type: property.classProperty.type, glslType, variableName, propertyStatistics: classStatistics?.properties[propertyId], shaderDestination: ShaderDestination_default.BOTH }; } return infoArray; } function getPropertyTexturesInfo(propertyTextures, statistics2) { if (!defined_default(propertyTextures)) { return []; } return propertyTextures.flatMap( (propertyTexture) => getPropertyTextureInfo(propertyTexture, statistics2) ); } function getPropertyTextureInfo(propertyTexture, statistics2) { const { sanitizeGlslIdentifier } = ModelUtility_default; const classId = propertyTexture.class.id; const classStatistics = statistics2?.classes[classId]; const propertiesArray = Object.entries(propertyTexture.properties).filter( ([id, property]) => property.isGpuCompatible() ); const infoArray = new Array(propertiesArray.length); for (let i = 0; i < propertiesArray.length; i++) { const [propertyId, property] = propertiesArray[i]; infoArray[i] = { metadataVariable: sanitizeGlslIdentifier(propertyId), property, type: property.classProperty.type, glslType: property.getGlslType(), propertyStatistics: classStatistics?.properties[propertyId], shaderDestination: ShaderDestination_default.FRAGMENT }; } return infoArray; } function declareMetadataTypeStructs(shaderBuilder, propertyInfos) { const classTypes = /* @__PURE__ */ new Set(); const statisticsTypes = /* @__PURE__ */ new Set(); for (let i = 0; i < propertyInfos.length; i++) { const { type, glslType, propertyStatistics } = propertyInfos[i]; classTypes.add(glslType); if (!defined_default(propertyStatistics)) { continue; } if (type !== MetadataType_default.ENUM) { statisticsTypes.add(glslType); } } const classFields = MetadataPipelineStage.METADATA_CLASS_FIELDS; for (const metadataType of classTypes) { const classStructName = `${metadataType}MetadataClass`; declareTypeStruct(classStructName, metadataType, classFields); } const statisticsFields = MetadataPipelineStage.METADATA_STATISTICS_FIELDS; for (const metadataType of statisticsTypes) { const statisticsStructName = `${metadataType}MetadataStatistics`; declareTypeStruct(statisticsStructName, metadataType, statisticsFields); } function declareTypeStruct(structName, type, fields) { shaderBuilder.addStruct(structName, structName, ShaderDestination_default.BOTH); for (let i = 0; i < fields.length; i++) { const { shaderName } = fields[i]; const shaderType = fields[i].type === "float" ? convertToFloatComponents(type) : type; shaderBuilder.addStructField(structName, shaderType, shaderName); } } } var floatConversions = { int: "float", ivec2: "vec2", ivec3: "vec3", ivec4: "vec4" }; function convertToFloatComponents(type) { const converted = floatConversions[type]; return defined_default(converted) ? converted : type; } function declareStructsAndFunctions2(shaderBuilder) { shaderBuilder.addStruct( MetadataPipelineStage.STRUCT_ID_METADATA_VS, MetadataPipelineStage.STRUCT_NAME_METADATA, ShaderDestination_default.VERTEX ); shaderBuilder.addStruct( MetadataPipelineStage.STRUCT_ID_METADATA_FS, MetadataPipelineStage.STRUCT_NAME_METADATA, ShaderDestination_default.FRAGMENT ); shaderBuilder.addStruct( MetadataPipelineStage.STRUCT_ID_METADATA_CLASS_VS, MetadataPipelineStage.STRUCT_NAME_METADATA_CLASS, ShaderDestination_default.VERTEX ); shaderBuilder.addStruct( MetadataPipelineStage.STRUCT_ID_METADATA_CLASS_FS, MetadataPipelineStage.STRUCT_NAME_METADATA_CLASS, ShaderDestination_default.FRAGMENT ); shaderBuilder.addStruct( MetadataPipelineStage.STRUCT_ID_METADATA_STATISTICS_VS, MetadataPipelineStage.STRUCT_NAME_METADATA_STATISTICS, ShaderDestination_default.VERTEX ); shaderBuilder.addStruct( MetadataPipelineStage.STRUCT_ID_METADATA_STATISTICS_FS, MetadataPipelineStage.STRUCT_NAME_METADATA_STATISTICS, ShaderDestination_default.FRAGMENT ); shaderBuilder.addFunction( MetadataPipelineStage.FUNCTION_ID_INITIALIZE_METADATA_VS, MetadataPipelineStage.FUNCTION_SIGNATURE_INITIALIZE_METADATA, ShaderDestination_default.VERTEX ); shaderBuilder.addFunction( MetadataPipelineStage.FUNCTION_ID_INITIALIZE_METADATA_FS, MetadataPipelineStage.FUNCTION_SIGNATURE_INITIALIZE_METADATA, ShaderDestination_default.FRAGMENT ); shaderBuilder.addFunction( MetadataPipelineStage.FUNCTION_ID_SET_METADATA_VARYINGS, MetadataPipelineStage.FUNCTION_SIGNATURE_SET_METADATA_VARYINGS, ShaderDestination_default.VERTEX ); } function processPropertyAttributeProperty(renderResources, propertyInfo) { addPropertyAttributePropertyMetadata(renderResources, propertyInfo); addPropertyMetadataClass(renderResources.shaderBuilder, propertyInfo); addPropertyMetadataStatistics(renderResources.shaderBuilder, propertyInfo); } function addPropertyAttributePropertyMetadata(renderResources, propertyInfo) { const { shaderBuilder } = renderResources; const { metadataVariable, property, glslType } = propertyInfo; const valueExpression = addValueTransformUniforms({ valueExpression: `attributes.${propertyInfo.variableName}`, renderResources, glslType, metadataVariable, shaderDestination: ShaderDestination_default.BOTH, property }); shaderBuilder.addStructField( MetadataPipelineStage.STRUCT_ID_METADATA_VS, glslType, metadataVariable ); shaderBuilder.addStructField( MetadataPipelineStage.STRUCT_ID_METADATA_FS, glslType, metadataVariable ); const initializationLine = `metadata.${metadataVariable} = ${valueExpression};`; shaderBuilder.addFunctionLines( MetadataPipelineStage.FUNCTION_ID_INITIALIZE_METADATA_VS, [initializationLine] ); shaderBuilder.addFunctionLines( MetadataPipelineStage.FUNCTION_ID_INITIALIZE_METADATA_FS, [initializationLine] ); } function processPropertyTextureProperty(renderResources, propertyInfo) { addPropertyTexturePropertyMetadata(renderResources, propertyInfo); addPropertyMetadataClass(renderResources.shaderBuilder, propertyInfo); addPropertyMetadataStatistics(renderResources.shaderBuilder, propertyInfo); } function addPropertyTexturePropertyMetadata(renderResources, propertyInfo) { const { shaderBuilder, uniformMap: uniformMap2 } = renderResources; const { metadataVariable, glslType, property } = propertyInfo; const { texCoord, channels, index, texture, transform: transform3 } = property.textureReader; const textureUniformName = `u_propertyTexture_${index}`; if (!uniformMap2.hasOwnProperty(textureUniformName)) { shaderBuilder.addUniform( "sampler2D", textureUniformName, ShaderDestination_default.FRAGMENT ); uniformMap2[textureUniformName] = () => texture; } shaderBuilder.addStructField( MetadataPipelineStage.STRUCT_ID_METADATA_FS, glslType, metadataVariable ); const texCoordVariable = `attributes.texCoord_${texCoord}`; let texCoordVariableExpression = texCoordVariable; if (defined_default(transform3) && !Matrix3_default.equals(transform3, Matrix3_default.IDENTITY)) { const transformUniformName = `${textureUniformName}Transform`; shaderBuilder.addUniform( "mat3", transformUniformName, ShaderDestination_default.FRAGMENT ); uniformMap2[transformUniformName] = function() { return transform3; }; texCoordVariableExpression = `vec2(${transformUniformName} * vec3(${texCoordVariable}, 1.0))`; } const valueExpression = `texture(${textureUniformName}, ${texCoordVariableExpression}).${channels}`; const unpackedValue = property.unpackInShader(valueExpression); const transformedValue = addValueTransformUniforms({ valueExpression: unpackedValue, renderResources, glslType, metadataVariable, shaderDestination: ShaderDestination_default.FRAGMENT, property }); const initializationLine = `metadata.${metadataVariable} = ${transformedValue};`; shaderBuilder.addFunctionLines( MetadataPipelineStage.FUNCTION_ID_INITIALIZE_METADATA_FS, [initializationLine] ); } function addPropertyMetadataClass(shaderBuilder, propertyInfo) { const { classProperty } = propertyInfo.property; const { metadataVariable, glslType, shaderDestination } = propertyInfo; const assignments = getStructAssignments( MetadataPipelineStage.METADATA_CLASS_FIELDS, classProperty, `metadataClass.${metadataVariable}`, glslType ); const metadataType = `${glslType}MetadataClass`; shaderBuilder.addStructField( MetadataPipelineStage.STRUCT_ID_METADATA_CLASS_FS, metadataType, metadataVariable ); shaderBuilder.addFunctionLines( MetadataPipelineStage.FUNCTION_ID_INITIALIZE_METADATA_FS, assignments ); if (!ShaderDestination_default.includesVertexShader(shaderDestination)) { return; } shaderBuilder.addStructField( MetadataPipelineStage.STRUCT_ID_METADATA_CLASS_VS, metadataType, metadataVariable ); shaderBuilder.addFunctionLines( MetadataPipelineStage.FUNCTION_ID_INITIALIZE_METADATA_VS, assignments ); } function addPropertyMetadataStatistics(shaderBuilder, propertyInfo) { const { propertyStatistics } = propertyInfo; if (!defined_default(propertyStatistics)) { return; } const { metadataVariable, type, glslType } = propertyInfo; if (type === MetadataType_default.ENUM) { return; } const fields = MetadataPipelineStage.METADATA_STATISTICS_FIELDS; const struct = `metadataStatistics.${metadataVariable}`; const assignments = getStructAssignments( fields, propertyStatistics, struct, glslType ); const statisticsType = `${glslType}MetadataStatistics`; shaderBuilder.addStructField( MetadataPipelineStage.STRUCT_ID_METADATA_STATISTICS_FS, statisticsType, metadataVariable ); shaderBuilder.addFunctionLines( MetadataPipelineStage.FUNCTION_ID_INITIALIZE_METADATA_FS, assignments ); if (!ShaderDestination_default.includesVertexShader(propertyInfo.shaderDestination)) { return; } shaderBuilder.addStructField( MetadataPipelineStage.STRUCT_ID_METADATA_STATISTICS_VS, statisticsType, metadataVariable ); shaderBuilder.addFunctionLines( MetadataPipelineStage.FUNCTION_ID_INITIALIZE_METADATA_VS, assignments ); } function getStructAssignments(fieldNames, values, struct, type) { function constructAssignment(field) { const value = values[field.specName]; if (defined_default(value)) { return `${struct}.${field.shaderName} = ${type}(${value});`; } } return defined_default(values) ? fieldNames.map(constructAssignment).filter(defined_default) : []; } function addValueTransformUniforms(options) { const { valueExpression, property } = options; if (!property.hasValueTransform) { return valueExpression; } const metadataVariable = options.metadataVariable; const offsetUniformName = `u_${metadataVariable}_offset`; const scaleUniformName = `u_${metadataVariable}_scale`; const { shaderBuilder, uniformMap: uniformMap2 } = options.renderResources; const { glslType, shaderDestination } = options; shaderBuilder.addUniform(glslType, offsetUniformName, shaderDestination); shaderBuilder.addUniform(glslType, scaleUniformName, shaderDestination); const { offset, scale } = property; uniformMap2[offsetUniformName] = () => offset; uniformMap2[scaleUniformName] = () => scale; return `czm_valueTransform(${offsetUniformName}, ${scaleUniformName}, ${valueExpression})`; } var MetadataPipelineStage_default = MetadataPipelineStage; // packages/engine/Source/Scene/Model/CustomShaderTranslucencyMode.js var import_InlineWorkers641 = __toESM(require_InlineWorkers(), 1); var CustomShaderTranslucencyMode = { /** * Inherit translucency settings from the primitive's material. If the primitive used a * translucent material, the custom shader will also be considered translucent. If the primitive * used an opaque material, the custom shader will be considered opaque. * * @type {number} * @constant */ INHERIT: 0, /** * Force the primitive to render the primitive as opaque, ignoring any material settings. * * @type {number} * @constant */ OPAQUE: 1, /** * Force the primitive to render the primitive as translucent, ignoring any material settings. * * @type {number} * @constant */ TRANSLUCENT: 2 }; var CustomShaderTranslucencyMode_default = Object.freeze(CustomShaderTranslucencyMode); // packages/engine/Source/Scene/Model/CustomShaderPipelineStage.js var CustomShaderPipelineStage = { name: "CustomShaderPipelineStage", // Helps with debugging STRUCT_ID_ATTRIBUTES_VS: "AttributesVS", STRUCT_ID_ATTRIBUTES_FS: "AttributesFS", STRUCT_NAME_ATTRIBUTES: "Attributes", STRUCT_ID_VERTEX_INPUT: "VertexInput", STRUCT_NAME_VERTEX_INPUT: "VertexInput", STRUCT_ID_FRAGMENT_INPUT: "FragmentInput", STRUCT_NAME_FRAGMENT_INPUT: "FragmentInput", FUNCTION_ID_INITIALIZE_INPUT_STRUCT_VS: "initializeInputStructVS", FUNCTION_SIGNATURE_INITIALIZE_INPUT_STRUCT_VS: "void initializeInputStruct(out VertexInput vsInput, ProcessedAttributes attributes)", FUNCTION_ID_INITIALIZE_INPUT_STRUCT_FS: "initializeInputStructFS", FUNCTION_SIGNATURE_INITIALIZE_INPUT_STRUCT_FS: "void initializeInputStruct(out FragmentInput fsInput, ProcessedAttributes attributes)", // Expose method for testing. _oneTimeWarning: oneTimeWarning_default }; CustomShaderPipelineStage.process = function(renderResources, primitive, frameState) { const { shaderBuilder, model, alphaOptions } = renderResources; const { customShader } = model; const { lightingModel, translucencyMode } = customShader; if (defined_default(lightingModel)) { renderResources.lightingOptions.lightingModel = lightingModel; } if (translucencyMode === CustomShaderTranslucencyMode_default.TRANSLUCENT) { alphaOptions.pass = Pass_default.TRANSLUCENT; } else if (translucencyMode === CustomShaderTranslucencyMode_default.OPAQUE) { alphaOptions.pass = void 0; } const generatedCode = generateShaderLines(customShader, primitive); if (!generatedCode.customShaderEnabled) { return; } addLinesToShader(shaderBuilder, customShader, generatedCode); if (generatedCode.shouldComputePositionWC) { shaderBuilder.addDefine( "COMPUTE_POSITION_WC_CUSTOM_SHADER", void 0, ShaderDestination_default.BOTH ); } if (defined_default(customShader.vertexShaderText)) { shaderBuilder.addDefine( "HAS_CUSTOM_VERTEX_SHADER", void 0, ShaderDestination_default.VERTEX ); } if (defined_default(customShader.fragmentShaderText)) { shaderBuilder.addDefine( "HAS_CUSTOM_FRAGMENT_SHADER", void 0, ShaderDestination_default.FRAGMENT ); const shaderModeDefine = CustomShaderMode_default.getDefineName(customShader.mode); shaderBuilder.addDefine( shaderModeDefine, void 0, ShaderDestination_default.FRAGMENT ); } const uniforms = customShader.uniforms; for (const uniformName in uniforms) { if (uniforms.hasOwnProperty(uniformName)) { const uniform = uniforms[uniformName]; shaderBuilder.addUniform(uniform.type, uniformName); } } const varyings = customShader.varyings; for (const varyingName in varyings) { if (varyings.hasOwnProperty(varyingName)) { const varyingType = varyings[varyingName]; shaderBuilder.addVarying(varyingType, varyingName); } } renderResources.uniformMap = combine_default( renderResources.uniformMap, customShader.uniformMap ); }; function getAttributesByName(attributes) { const names = {}; for (let i = 0; i < attributes.length; i++) { const attributeInfo = ModelUtility_default.getAttributeInfo(attributes[i]); names[attributeInfo.variableName] = attributeInfo; } return names; } var attributeTypeLUT = { position: "vec3", normal: "vec3", tangent: "vec3", bitangent: "vec3", texCoord: "vec2", color: "vec4", joints: "ivec4", weights: "vec4" }; var attributeDefaultValueLUT = { position: "vec3(0.0)", normal: "vec3(0.0, 0.0, 1.0)", tangent: "vec3(1.0, 0.0, 0.0)", bitangent: "vec3(0.0, 1.0, 0.0)", texCoord: "vec2(0.0)", color: "vec4(1.0)", joints: "ivec4(0)", weights: "vec4(0.0)" }; function inferAttributeDefaults(attributeName) { let trimmed = attributeName.replace(/_[0-9]+$/, ""); trimmed = trimmed.replace(/(MC|EC)$/, ""); const glslType = attributeTypeLUT[trimmed]; const value = attributeDefaultValueLUT[trimmed]; if (!defined_default(glslType)) { return void 0; } return { attributeField: [glslType, attributeName], value }; } function generateVertexShaderLines(customShader, attributesByName) { if (!defined_default(customShader.vertexShaderText)) { return { enabled: false }; } const primitiveAttributes = customShader.usedVariablesVertex.attributeSet; const addToShader = getPrimitiveAttributesUsedInShader( attributesByName, primitiveAttributes, false ); const needsDefault = getAttributesNeedingDefaults( attributesByName, primitiveAttributes, false ); let vertexInitialization; const attributeFields = []; const initializationLines = []; for (const variableName in addToShader) { if (!addToShader.hasOwnProperty(variableName)) { continue; } const attributeInfo = addToShader[variableName]; const attributeField = [attributeInfo.glslType, variableName]; attributeFields.push(attributeField); vertexInitialization = `vsInput.attributes.${variableName} = attributes.${variableName};`; initializationLines.push(vertexInitialization); } for (let i = 0; i < needsDefault.length; i++) { const variableName = needsDefault[i]; const attributeDefaults = inferAttributeDefaults(variableName); if (!defined_default(attributeDefaults)) { CustomShaderPipelineStage._oneTimeWarning( "CustomShaderPipelineStage.incompatiblePrimitiveVS", `Primitive is missing attribute ${variableName}, disabling custom vertex shader` ); return { enabled: false }; } attributeFields.push(attributeDefaults.attributeField); vertexInitialization = `vsInput.attributes.${variableName} = ${attributeDefaults.value};`; initializationLines.push(vertexInitialization); } return { enabled: true, attributeFields, initializationLines }; } function generatePositionBuiltins(customShader) { const attributeFields = []; const initializationLines = []; const usedVariables = customShader.usedVariablesFragment.attributeSet; if (usedVariables.hasOwnProperty("positionWC")) { attributeFields.push(["vec3", "positionWC"]); initializationLines.push( "fsInput.attributes.positionWC = attributes.positionWC;" ); } if (usedVariables.hasOwnProperty("positionEC")) { attributeFields.push(["vec3", "positionEC"]); initializationLines.push( "fsInput.attributes.positionEC = attributes.positionEC;" ); } return { attributeFields, initializationLines }; } function generateFragmentShaderLines(customShader, attributesByName) { if (!defined_default(customShader.fragmentShaderText)) { return { enabled: false }; } const primitiveAttributes = customShader.usedVariablesFragment.attributeSet; const addToShader = getPrimitiveAttributesUsedInShader( attributesByName, primitiveAttributes, true ); const needsDefault = getAttributesNeedingDefaults( attributesByName, primitiveAttributes, true ); let fragmentInitialization; const attributeFields = []; const initializationLines = []; for (const variableName in addToShader) { if (!addToShader.hasOwnProperty(variableName)) { continue; } const attributeInfo = addToShader[variableName]; const attributeField = [attributeInfo.glslType, variableName]; attributeFields.push(attributeField); fragmentInitialization = `fsInput.attributes.${variableName} = attributes.${variableName};`; initializationLines.push(fragmentInitialization); } for (let i = 0; i < needsDefault.length; i++) { const variableName = needsDefault[i]; const attributeDefaults = inferAttributeDefaults(variableName); if (!defined_default(attributeDefaults)) { CustomShaderPipelineStage._oneTimeWarning( "CustomShaderPipelineStage.incompatiblePrimitiveFS", `Primitive is missing attribute ${variableName}, disabling custom fragment shader.` ); return { enabled: false }; } attributeFields.push(attributeDefaults.attributeField); fragmentInitialization = `fsInput.attributes.${variableName} = ${attributeDefaults.value};`; initializationLines.push(fragmentInitialization); } const positionBuiltins = generatePositionBuiltins(customShader); return { enabled: true, attributeFields: attributeFields.concat(positionBuiltins.attributeFields), initializationLines: positionBuiltins.initializationLines.concat(initializationLines) }; } var builtinAttributes = { positionWC: true, positionEC: true }; function getPrimitiveAttributesUsedInShader(primitiveAttributes, shaderAttributeSet, isFragmentShader) { const addToShader = {}; for (const attributeName in primitiveAttributes) { if (!primitiveAttributes.hasOwnProperty(attributeName)) { continue; } const attribute = primitiveAttributes[attributeName]; let renamed = attributeName; if (isFragmentShader && attributeName === "normalMC") { renamed = "normalEC"; } else if (isFragmentShader && attributeName === "tangentMC") { renamed = "tangentEC"; attribute.glslType = "vec3"; } if (shaderAttributeSet.hasOwnProperty(renamed)) { addToShader[renamed] = attribute; } } return addToShader; } function getAttributesNeedingDefaults(primitiveAttributes, shaderAttributeSet, isFragmentShader) { const needDefaults = []; for (const attributeName in shaderAttributeSet) { if (!shaderAttributeSet.hasOwnProperty(attributeName)) { continue; } if (builtinAttributes.hasOwnProperty(attributeName)) { continue; } let renamed = attributeName; if (isFragmentShader && attributeName === "normalEC") { renamed = "normalMC"; } else if (isFragmentShader && attributeName === "tangentEC") { renamed = "tangentMC"; } if (!primitiveAttributes.hasOwnProperty(renamed)) { needDefaults.push(attributeName); } } return needDefaults; } function generateShaderLines(customShader, primitive) { const attributesByName = getAttributesByName(primitive.attributes); const vertexLines = generateVertexShaderLines(customShader, attributesByName); const fragmentLines = generateFragmentShaderLines( customShader, attributesByName ); const attributeSetFS = customShader.usedVariablesFragment.attributeSet; const shouldComputePositionWC = attributeSetFS.hasOwnProperty("positionWC") && fragmentLines.enabled; return { vertexLines, fragmentLines, customShaderEnabled: vertexLines.enabled || fragmentLines.enabled, shouldComputePositionWC }; } function addVertexLinesToShader(shaderBuilder, vertexLines) { let structId = CustomShaderPipelineStage.STRUCT_ID_ATTRIBUTES_VS; shaderBuilder.addStruct( structId, CustomShaderPipelineStage.STRUCT_NAME_ATTRIBUTES, ShaderDestination_default.VERTEX ); const { attributeFields, initializationLines } = vertexLines; for (let i = 0; i < attributeFields.length; i++) { const [glslType, variableName] = attributeFields[i]; shaderBuilder.addStructField(structId, glslType, variableName); } structId = CustomShaderPipelineStage.STRUCT_ID_VERTEX_INPUT; shaderBuilder.addStruct( structId, CustomShaderPipelineStage.STRUCT_NAME_VERTEX_INPUT, ShaderDestination_default.VERTEX ); shaderBuilder.addStructField( structId, CustomShaderPipelineStage.STRUCT_NAME_ATTRIBUTES, "attributes" ); shaderBuilder.addStructField( structId, FeatureIdPipelineStage_default.STRUCT_NAME_FEATURE_IDS, "featureIds" ); shaderBuilder.addStructField( structId, MetadataPipelineStage_default.STRUCT_NAME_METADATA, "metadata" ); shaderBuilder.addStructField( structId, MetadataPipelineStage_default.STRUCT_NAME_METADATA_CLASS, "metadataClass" ); shaderBuilder.addStructField( structId, MetadataPipelineStage_default.STRUCT_NAME_METADATA_STATISTICS, "metadataStatistics" ); const functionId = CustomShaderPipelineStage.FUNCTION_ID_INITIALIZE_INPUT_STRUCT_VS; shaderBuilder.addFunction( functionId, CustomShaderPipelineStage.FUNCTION_SIGNATURE_INITIALIZE_INPUT_STRUCT_VS, ShaderDestination_default.VERTEX ); shaderBuilder.addFunctionLines(functionId, initializationLines); } function addFragmentLinesToShader(shaderBuilder, fragmentLines) { let structId = CustomShaderPipelineStage.STRUCT_ID_ATTRIBUTES_FS; shaderBuilder.addStruct( structId, CustomShaderPipelineStage.STRUCT_NAME_ATTRIBUTES, ShaderDestination_default.FRAGMENT ); const { attributeFields, initializationLines } = fragmentLines; for (let i = 0; i < attributeFields.length; i++) { const [glslType, variableName] = attributeFields[i]; shaderBuilder.addStructField(structId, glslType, variableName); } structId = CustomShaderPipelineStage.STRUCT_ID_FRAGMENT_INPUT; shaderBuilder.addStruct( structId, CustomShaderPipelineStage.STRUCT_NAME_FRAGMENT_INPUT, ShaderDestination_default.FRAGMENT ); shaderBuilder.addStructField( structId, CustomShaderPipelineStage.STRUCT_NAME_ATTRIBUTES, "attributes" ); shaderBuilder.addStructField( structId, FeatureIdPipelineStage_default.STRUCT_NAME_FEATURE_IDS, "featureIds" ); shaderBuilder.addStructField( structId, MetadataPipelineStage_default.STRUCT_NAME_METADATA, "metadata" ); shaderBuilder.addStructField( structId, MetadataPipelineStage_default.STRUCT_NAME_METADATA_CLASS, "metadataClass" ); shaderBuilder.addStructField( structId, MetadataPipelineStage_default.STRUCT_NAME_METADATA_STATISTICS, "metadataStatistics" ); const functionId = CustomShaderPipelineStage.FUNCTION_ID_INITIALIZE_INPUT_STRUCT_FS; shaderBuilder.addFunction( functionId, CustomShaderPipelineStage.FUNCTION_SIGNATURE_INITIALIZE_INPUT_STRUCT_FS, ShaderDestination_default.FRAGMENT ); shaderBuilder.addFunctionLines(functionId, initializationLines); } var scratchShaderLines = []; function addLinesToShader(shaderBuilder, customShader, generatedCode) { const { vertexLines, fragmentLines } = generatedCode; const shaderLines = scratchShaderLines; if (vertexLines.enabled) { addVertexLinesToShader(shaderBuilder, vertexLines); shaderLines.length = 0; shaderLines.push( "#line 0", customShader.vertexShaderText, CustomShaderStageVS_default ); shaderBuilder.addVertexLines(shaderLines); } if (fragmentLines.enabled) { addFragmentLinesToShader(shaderBuilder, fragmentLines); shaderLines.length = 0; shaderLines.push( "#line 0", customShader.fragmentShaderText, CustomShaderStageFS_default ); shaderBuilder.addFragmentLines(shaderLines); } } var CustomShaderPipelineStage_default = CustomShaderPipelineStage; // packages/engine/Source/Scene/Model/DequantizationPipelineStage.js var import_InlineWorkers643 = __toESM(require_InlineWorkers(), 1); var DequantizationPipelineStage = { name: "DequantizationPipelineStage", // Helps with debugging FUNCTION_ID_DEQUANTIZATION_STAGE_VS: "dequantizationStage", FUNCTION_SIGNATURE_DEQUANTIZATION_STAGE_VS: "void dequantizationStage(inout ProcessedAttributes attributes)" }; DequantizationPipelineStage.process = function(renderResources, primitive, frameState) { const shaderBuilder = renderResources.shaderBuilder; const model = renderResources.model; const hasClassification = defined_default(model.classificationType); shaderBuilder.addDefine( "USE_DEQUANTIZATION", void 0, ShaderDestination_default.VERTEX ); shaderBuilder.addFunction( DequantizationPipelineStage.FUNCTION_ID_DEQUANTIZATION_STAGE_VS, DequantizationPipelineStage.FUNCTION_SIGNATURE_DEQUANTIZATION_STAGE_VS, ShaderDestination_default.VERTEX ); const attributes = primitive.attributes; for (let i = 0; i < attributes.length; i++) { const attribute = attributes[i]; const quantization = attribute.quantization; if (!defined_default(quantization)) { continue; } const isPositionAttribute = attribute.semantic === VertexAttributeSemantic_default.POSITION; const isTexcoordAttribute = attribute.semantic === VertexAttributeSemantic_default.TEXCOORD; if (hasClassification && !isPositionAttribute && !isTexcoordAttribute) { continue; } const attributeInfo = ModelUtility_default.getAttributeInfo(attribute); updateDequantizationFunction(shaderBuilder, attributeInfo); addDequantizationUniforms(renderResources, attributeInfo); } }; function addDequantizationUniforms(renderResources, attributeInfo) { const shaderBuilder = renderResources.shaderBuilder; const uniformMap2 = renderResources.uniformMap; const variableName = attributeInfo.variableName; const quantization = attributeInfo.attribute.quantization; if (quantization.octEncoded) { const normalizationRange = `model_normalizationRange_${variableName}`; shaderBuilder.addUniform( "float", normalizationRange, ShaderDestination_default.VERTEX ); uniformMap2[normalizationRange] = function() { return quantization.normalizationRange; }; } else { const offset = `model_quantizedVolumeOffset_${variableName}`; const stepSize = `model_quantizedVolumeStepSize_${variableName}`; const glslType = attributeInfo.glslType; shaderBuilder.addUniform(glslType, offset, ShaderDestination_default.VERTEX); shaderBuilder.addUniform(glslType, stepSize, ShaderDestination_default.VERTEX); let quantizedVolumeOffset = quantization.quantizedVolumeOffset; let quantizedVolumeStepSize = quantization.quantizedVolumeStepSize; if (/^color_\d+$/.test(variableName)) { quantizedVolumeOffset = promoteToVec4(quantizedVolumeOffset, 0); quantizedVolumeStepSize = promoteToVec4(quantizedVolumeStepSize, 1); } uniformMap2[offset] = function() { return quantizedVolumeOffset; }; uniformMap2[stepSize] = function() { return quantizedVolumeStepSize; }; } } function promoteToVec4(value, defaultAlpha) { if (value instanceof Cartesian4_default) { return value; } return new Cartesian4_default(value.x, value.y, value.z, defaultAlpha); } function updateDequantizationFunction(shaderBuilder, attributeInfo) { const variableName = attributeInfo.variableName; const quantization = attributeInfo.attribute.quantization; let line; if (quantization.octEncoded) { line = generateOctDecodeLine(variableName, quantization); } else { line = generateDequantizeLine(variableName); } shaderBuilder.addFunctionLines( DequantizationPipelineStage.FUNCTION_ID_DEQUANTIZATION_STAGE_VS, [line] ); } function generateOctDecodeLine(variableName, quantization) { const structField = `attributes.${variableName}`; const quantizedAttribute = `a_quantized_${variableName}`; const normalizationRange = `model_normalizationRange_${variableName}`; const swizzle = quantization.octEncodedZXY ? ".zxy" : ".xyz"; return `${structField} = czm_octDecode(${quantizedAttribute}, ${normalizationRange})${swizzle};`; } function generateDequantizeLine(variableName) { const structField = `attributes.${variableName}`; const quantizedAttribute = `a_quantized_${variableName}`; const offset = `model_quantizedVolumeOffset_${variableName}`; const stepSize = `model_quantizedVolumeStepSize_${variableName}`; return `${structField} = ${offset} + ${quantizedAttribute} * ${stepSize};`; } var DequantizationPipelineStage_default = DequantizationPipelineStage; // packages/engine/Source/Scene/Model/GeometryPipelineStage.js var import_InlineWorkers648 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Shaders/Model/GeometryStageFS.js var import_InlineWorkers644 = __toESM(require_InlineWorkers(), 1); var GeometryStageFS_default = "void geometryStage(out ProcessedAttributes attributes)\n{\n attributes.positionMC = v_positionMC;\n attributes.positionEC = v_positionEC;\n\n #if defined(COMPUTE_POSITION_WC_CUSTOM_SHADER) || defined(COMPUTE_POSITION_WC_STYLE) || defined(COMPUTE_POSITION_WC_ATMOSPHERE)\n attributes.positionWC = v_positionWC;\n #endif\n\n #ifdef HAS_NORMALS\n // renormalize after interpolation\n attributes.normalEC = normalize(v_normalEC);\n #endif\n\n #ifdef HAS_TANGENTS\n attributes.tangentEC = normalize(v_tangentEC);\n #endif\n\n #ifdef HAS_BITANGENTS\n attributes.bitangentEC = normalize(v_bitangentEC);\n #endif\n\n // Everything else is dynamically generated in GeometryPipelineStage\n setDynamicVaryings(attributes);\n}\n"; // packages/engine/Source/Shaders/Model/GeometryStageVS.js var import_InlineWorkers645 = __toESM(require_InlineWorkers(), 1); var GeometryStageVS_default = "vec4 geometryStage(inout ProcessedAttributes attributes, mat4 modelView, mat3 normal)\n{\n vec4 computedPosition;\n\n // Compute positions in different coordinate systems\n vec3 positionMC = attributes.positionMC;\n v_positionMC = positionMC;\n v_positionEC = (modelView * vec4(positionMC, 1.0)).xyz;\n\n #if defined(USE_2D_POSITIONS) || defined(USE_2D_INSTANCING)\n vec3 position2D = attributes.position2D;\n vec3 positionEC = (u_modelView2D * vec4(position2D, 1.0)).xyz;\n computedPosition = czm_projection * vec4(positionEC, 1.0);\n #else\n computedPosition = czm_projection * vec4(v_positionEC, 1.0);\n #endif\n\n // Sometimes the custom shader and/or style needs this\n #if defined(COMPUTE_POSITION_WC_CUSTOM_SHADER) || defined(COMPUTE_POSITION_WC_STYLE) || defined(COMPUTE_POSITION_WC_ATMOSPHERE) || defined(ENABLE_CLIPPING_POLYGONS)\n // Note that this is a 32-bit position which may result in jitter on small\n // scales.\n v_positionWC = (czm_model * vec4(positionMC, 1.0)).xyz;\n #endif\n\n #ifdef HAS_NORMALS\n v_normalEC = normalize(normal * attributes.normalMC);\n #endif\n\n #ifdef HAS_TANGENTS\n v_tangentEC = normalize(normal * attributes.tangentMC);\n #endif\n\n #ifdef HAS_BITANGENTS\n v_bitangentEC = normalize(normal * attributes.bitangentMC);\n #endif\n\n // All other varyings need to be dynamically generated in\n // GeometryPipelineStage\n setDynamicVaryings(attributes);\n\n return computedPosition;\n}\n"; // packages/engine/Source/Scene/Model/SelectedFeatureIdPipelineStage.js var import_InlineWorkers647 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Shaders/Model/SelectedFeatureIdStageCommon.js var import_InlineWorkers646 = __toESM(require_InlineWorkers(), 1); var SelectedFeatureIdStageCommon_default = "vec2 computeSt(float featureId)\n{\n float stepX = model_textureStep.x;\n float centerX = model_textureStep.y;\n\n #ifdef MULTILINE_BATCH_TEXTURE\n float stepY = model_textureStep.z;\n float centerY = model_textureStep.w;\n\n float xId = mod(featureId, model_textureDimensions.x); \n float yId = floor(featureId / model_textureDimensions.x);\n \n return vec2(centerX + (xId * stepX), centerY + (yId * stepY));\n #else\n return vec2(centerX + (featureId * stepX), 0.5);\n #endif\n}\n\nvoid selectedFeatureIdStage(out SelectedFeature feature, FeatureIds featureIds)\n{ \n int featureId = featureIds.SELECTED_FEATURE_ID;\n\n\n if (featureId < model_featuresLength)\n {\n vec2 featureSt = computeSt(float(featureId));\n\n feature.id = featureId;\n feature.st = featureSt;\n feature.color = texture(model_batchTexture, featureSt);\n }\n // Floating point comparisons can be unreliable in GLSL, so we\n // increment the feature ID to make sure it's always greater\n // then the model_featuresLength - a condition we check for in the\n // pick ID, to avoid sampling the pick texture if the feature ID is\n // greater than the number of features.\n else\n {\n feature.id = model_featuresLength + 1;\n feature.st = vec2(0.0);\n feature.color = vec4(1.0);\n }\n\n #ifdef HAS_NULL_FEATURE_ID\n if (featureId == model_nullFeatureId) {\n feature.id = featureId;\n feature.st = vec2(0.0);\n feature.color = vec4(1.0);\n }\n #endif\n}\n"; // packages/engine/Source/Scene/Model/SelectedFeatureIdPipelineStage.js var SelectedFeatureIdPipelineStage = { name: "SelectedFeatureIdPipelineStage", // Helps with debugging STRUCT_ID_SELECTED_FEATURE: "SelectedFeature", STRUCT_NAME_SELECTED_FEATURE: "SelectedFeature" }; SelectedFeatureIdPipelineStage.process = function(renderResources, primitive, frameState) { const shaderBuilder = renderResources.shaderBuilder; renderResources.hasPropertyTable = true; const model = renderResources.model; const node = renderResources.runtimeNode.node; const selectedFeatureIds = getSelectedFeatureIds(model, node, primitive); const shaderDestination = selectedFeatureIds.shaderDestination; shaderBuilder.addDefine( "HAS_SELECTED_FEATURE_ID", void 0, shaderDestination ); shaderBuilder.addDefine( "SELECTED_FEATURE_ID", selectedFeatureIds.variableName, shaderDestination ); shaderBuilder.addDefine( selectedFeatureIds.featureIdDefine, void 0, shaderDestination ); updateFeatureStruct(shaderBuilder); const nullFeatureId = selectedFeatureIds.featureIds.nullFeatureId; const uniformMap2 = renderResources.uniformMap; if (defined_default(nullFeatureId)) { shaderBuilder.addDefine( "HAS_NULL_FEATURE_ID", void 0, shaderDestination ); shaderBuilder.addUniform("int", "model_nullFeatureId", shaderDestination); uniformMap2.model_nullFeatureId = function() { return nullFeatureId; }; } if (selectedFeatureIds.shaderDestination === ShaderDestination_default.BOTH) { shaderBuilder.addVertexLines(SelectedFeatureIdStageCommon_default); } shaderBuilder.addFragmentLines(SelectedFeatureIdStageCommon_default); }; function getFeatureIdDefine(featureIds) { if (featureIds instanceof ModelComponents_default.FeatureIdTexture) { return "HAS_SELECTED_FEATURE_ID_TEXTURE"; } return "HAS_SELECTED_FEATURE_ID_ATTRIBUTE"; } function getShaderDestination(featureIds) { if (featureIds instanceof ModelComponents_default.FeatureIdTexture) { return ShaderDestination_default.FRAGMENT; } return ShaderDestination_default.BOTH; } function getSelectedFeatureIds(model, node, primitive) { let variableName; let featureIds; if (defined_default(node.instances)) { featureIds = ModelUtility_default.getFeatureIdsByLabel( node.instances.featureIds, model.instanceFeatureIdLabel ); if (defined_default(featureIds)) { variableName = featureIds.label ?? featureIds.positionalLabel; return { featureIds, variableName, shaderDestination: getShaderDestination(featureIds), featureIdDefine: getFeatureIdDefine(featureIds) }; } } featureIds = ModelUtility_default.getFeatureIdsByLabel( primitive.featureIds, model.featureIdLabel ); variableName = featureIds.label ?? featureIds.positionalLabel; return { featureIds, variableName, shaderDestination: getShaderDestination(featureIds), featureIdDefine: getFeatureIdDefine(featureIds) }; } function updateFeatureStruct(shaderBuilder) { shaderBuilder.addStructField( SelectedFeatureIdPipelineStage.STRUCT_ID_SELECTED_FEATURE, "int", "id" ); shaderBuilder.addStructField( SelectedFeatureIdPipelineStage.STRUCT_ID_SELECTED_FEATURE, "vec2", "st" ); shaderBuilder.addStructField( SelectedFeatureIdPipelineStage.STRUCT_ID_SELECTED_FEATURE, "vec4", "color" ); } var SelectedFeatureIdPipelineStage_default = SelectedFeatureIdPipelineStage; // packages/engine/Source/Scene/Model/GeometryPipelineStage.js var GeometryPipelineStage = { name: "GeometryPipelineStage", // Helps with debugging STRUCT_ID_PROCESSED_ATTRIBUTES_VS: "ProcessedAttributesVS", STRUCT_ID_PROCESSED_ATTRIBUTES_FS: "ProcessedAttributesFS", STRUCT_NAME_PROCESSED_ATTRIBUTES: "ProcessedAttributes", FUNCTION_ID_INITIALIZE_ATTRIBUTES: "initializeAttributes", FUNCTION_SIGNATURE_INITIALIZE_ATTRIBUTES: "void initializeAttributes(out ProcessedAttributes attributes)", FUNCTION_ID_SET_DYNAMIC_VARYINGS_VS: "setDynamicVaryingsVS", FUNCTION_ID_SET_DYNAMIC_VARYINGS_FS: "setDynamicVaryingsFS", FUNCTION_SIGNATURE_SET_DYNAMIC_VARYINGS: "void setDynamicVaryings(inout ProcessedAttributes attributes)" }; GeometryPipelineStage.process = function(renderResources, primitive, frameState) { const { shaderBuilder, model } = renderResources; shaderBuilder.addStruct( GeometryPipelineStage.STRUCT_ID_PROCESSED_ATTRIBUTES_VS, "ProcessedAttributes", ShaderDestination_default.VERTEX ); shaderBuilder.addStruct( GeometryPipelineStage.STRUCT_ID_PROCESSED_ATTRIBUTES_FS, "ProcessedAttributes", ShaderDestination_default.FRAGMENT ); shaderBuilder.addStruct( SelectedFeatureIdPipelineStage_default.STRUCT_ID_SELECTED_FEATURE, SelectedFeatureIdPipelineStage_default.STRUCT_NAME_SELECTED_FEATURE, ShaderDestination_default.BOTH ); shaderBuilder.addFunction( GeometryPipelineStage.FUNCTION_ID_INITIALIZE_ATTRIBUTES, GeometryPipelineStage.FUNCTION_SIGNATURE_INITIALIZE_ATTRIBUTES, ShaderDestination_default.VERTEX ); shaderBuilder.addVarying("vec3", "v_positionWC"); shaderBuilder.addVarying("vec3", "v_positionEC"); shaderBuilder.addStructField( GeometryPipelineStage.STRUCT_ID_PROCESSED_ATTRIBUTES_FS, "vec3", "positionWC" ); shaderBuilder.addStructField( GeometryPipelineStage.STRUCT_ID_PROCESSED_ATTRIBUTES_FS, "vec3", "positionEC" ); shaderBuilder.addFunction( GeometryPipelineStage.FUNCTION_ID_SET_DYNAMIC_VARYINGS_VS, GeometryPipelineStage.FUNCTION_SIGNATURE_SET_DYNAMIC_VARYINGS, ShaderDestination_default.VERTEX ); shaderBuilder.addFunction( GeometryPipelineStage.FUNCTION_ID_SET_DYNAMIC_VARYINGS_FS, GeometryPipelineStage.FUNCTION_SIGNATURE_SET_DYNAMIC_VARYINGS, ShaderDestination_default.FRAGMENT ); if (model.type === ModelType_default.TILE_PNTS) { shaderBuilder.addDefine( "HAS_SRGB_COLOR", void 0, ShaderDestination_default.FRAGMENT ); } const use2D = frameState.mode !== SceneMode_default.SCENE3D && !frameState.scene3DOnly && model._projectTo2D; const instanced = defined_default(renderResources.runtimeNode.node.instances); const incrementIndexFor2D = use2D && !instanced; const length2 = primitive.attributes.length; for (let i = 0; i < length2; i++) { const attribute = primitive.attributes[i]; const attributeLocationCount = AttributeType_default.getAttributeLocationCount( attribute.type ); if (!defined_default(attribute.buffer) && !defined_default(attribute.constant)) { throw new DeveloperError_default( "Attributes must be provided as a Buffer or constant value" ); } const isPositionAttribute = attribute.semantic === VertexAttributeSemantic_default.POSITION; let index; if (attributeLocationCount > 1) { index = renderResources.attributeIndex; renderResources.attributeIndex += attributeLocationCount; } else if (isPositionAttribute && !incrementIndexFor2D) { index = 0; } else { index = renderResources.attributeIndex++; } processAttribute2( renderResources, attribute, index, attributeLocationCount, use2D, instanced ); } handleBitangents(shaderBuilder, primitive.attributes); if (primitive.primitiveType === PrimitiveType_default.POINTS) { shaderBuilder.addDefine("PRIMITIVE_TYPE_POINTS"); } shaderBuilder.addVertexLines(GeometryStageVS_default); shaderBuilder.addFragmentLines(GeometryStageFS_default); }; function processAttribute2(renderResources, attribute, attributeIndex, attributeLocationCount, use2D, instanced) { const shaderBuilder = renderResources.shaderBuilder; const attributeInfo = ModelUtility_default.getAttributeInfo(attribute); const modifyFor2D = use2D && !instanced; if (attributeLocationCount > 1) { addMatrixAttributeToRenderResources( renderResources, attribute, attributeIndex, attributeLocationCount ); } else { addAttributeToRenderResources( renderResources, attribute, attributeIndex, modifyFor2D ); } addAttributeDeclaration(shaderBuilder, attributeInfo, modifyFor2D); addVaryingDeclaration(shaderBuilder, attributeInfo); if (defined_default(attribute.semantic)) { addSemanticDefine(shaderBuilder, attribute); } updateAttributesStruct(shaderBuilder, attributeInfo, use2D); updateInitializeAttributesFunction(shaderBuilder, attributeInfo, modifyFor2D); updateSetDynamicVaryingsFunction(shaderBuilder, attributeInfo); } function addSemanticDefine(shaderBuilder, attribute) { const { semantic, setIndex } = attribute; switch (semantic) { case VertexAttributeSemantic_default.NORMAL: shaderBuilder.addDefine("HAS_NORMALS"); break; case VertexAttributeSemantic_default.TANGENT: shaderBuilder.addDefine("HAS_TANGENTS"); break; case VertexAttributeSemantic_default.FEATURE_ID: shaderBuilder.addDefine(`HAS${semantic}_${setIndex}`); break; case VertexAttributeSemantic_default.TEXCOORD: case VertexAttributeSemantic_default.COLOR: shaderBuilder.addDefine(`HAS_${semantic}_${setIndex}`); } } function addAttributeToRenderResources(renderResources, attribute, attributeIndex, modifyFor2D) { const { quantization, semantic, setIndex } = attribute; const { type, componentDatatype } = defined_default(quantization) ? quantization : attribute; if (semantic === VertexAttributeSemantic_default.FEATURE_ID && setIndex >= renderResources.featureIdVertexAttributeSetIndex) { renderResources.featureIdVertexAttributeSetIndex = setIndex + 1; } const isPositionAttribute = semantic === VertexAttributeSemantic_default.POSITION; const index = isPositionAttribute ? 0 : attributeIndex; const componentsPerAttribute = AttributeType_default.getNumberOfComponents(type); const vertexAttribute = { index, value: defined_default(attribute.buffer) ? void 0 : attribute.constant, vertexBuffer: attribute.buffer, count: attribute.count, componentsPerAttribute, componentDatatype, offsetInBytes: attribute.byteOffset, strideInBytes: attribute.byteStride, normalize: attribute.normalized }; renderResources.attributes.push(vertexAttribute); if (!isPositionAttribute || !modifyFor2D) { return; } const buffer2D = renderResources.runtimePrimitive.positionBuffer2D; const positionAttribute2D = { index: attributeIndex, vertexBuffer: buffer2D, count: attribute.count, componentsPerAttribute, componentDatatype: ComponentDatatype_default.FLOAT, // Projected positions will always be floats. offsetInBytes: 0, strideInBytes: void 0, normalize: attribute.normalized }; renderResources.attributes.push(positionAttribute2D); } function addMatrixAttributeToRenderResources(renderResources, attribute, attributeIndex, columnCount) { const { quantization, normalized } = attribute; const { type, componentDatatype } = defined_default(quantization) ? quantization : attribute; const componentCount = AttributeType_default.getNumberOfComponents(type); const componentsPerColumn = componentCount / columnCount; const componentSizeInBytes = ComponentDatatype_default.getSizeInBytes(componentDatatype); const columnLengthInBytes = componentsPerColumn * componentSizeInBytes; const strideInBytes = attribute.byteStride; for (let i = 0; i < columnCount; i++) { const offsetInBytes = attribute.byteOffset + i * columnLengthInBytes; const columnAttribute = { index: attributeIndex + i, vertexBuffer: attribute.buffer, componentsPerAttribute: componentsPerColumn, componentDatatype, offsetInBytes, strideInBytes, normalize: normalized }; renderResources.attributes.push(columnAttribute); } } function addVaryingDeclaration(shaderBuilder, attributeInfo) { const variableName = attributeInfo.variableName; let varyingName = `v_${variableName}`; let glslType; if (variableName === "normalMC") { varyingName = "v_normalEC"; glslType = attributeInfo.glslType; } else if (variableName === "tangentMC") { glslType = "vec3"; varyingName = "v_tangentEC"; } else { glslType = attributeInfo.glslType; } shaderBuilder.addVarying(glslType, varyingName); } function addAttributeDeclaration(shaderBuilder, attributeInfo, modifyFor2D) { const semantic = attributeInfo.attribute.semantic; const variableName = attributeInfo.variableName; let attributeName; let glslType; if (attributeInfo.isQuantized) { attributeName = `a_quantized_${variableName}`; glslType = attributeInfo.quantizedGlslType; } else { attributeName = `a_${variableName}`; glslType = attributeInfo.glslType; } const isPosition = semantic === VertexAttributeSemantic_default.POSITION; if (isPosition) { shaderBuilder.setPositionAttribute(glslType, attributeName); } else { shaderBuilder.addAttribute(glslType, attributeName); } if (isPosition && modifyFor2D) { shaderBuilder.addAttribute("vec3", "a_position2D"); } } function updateAttributesStruct(shaderBuilder, attributeInfo, use2D) { const vsStructId = GeometryPipelineStage.STRUCT_ID_PROCESSED_ATTRIBUTES_VS; const fsStructId = GeometryPipelineStage.STRUCT_ID_PROCESSED_ATTRIBUTES_FS; const { variableName, glslType } = attributeInfo; if (variableName === "tangentMC") { shaderBuilder.addStructField(vsStructId, "vec3", "tangentMC"); shaderBuilder.addStructField(vsStructId, "float", "tangentSignMC"); shaderBuilder.addStructField(fsStructId, "vec3", "tangentEC"); } else if (variableName === "normalMC") { shaderBuilder.addStructField(vsStructId, "vec3", "normalMC"); shaderBuilder.addStructField(fsStructId, "vec3", "normalEC"); } else { shaderBuilder.addStructField(vsStructId, glslType, variableName); shaderBuilder.addStructField(fsStructId, glslType, variableName); } if (variableName === "positionMC" && use2D) { shaderBuilder.addStructField(vsStructId, "vec3", "position2D"); } } function updateInitializeAttributesFunction(shaderBuilder, attributeInfo, use2D) { const functionId = GeometryPipelineStage.FUNCTION_ID_INITIALIZE_ATTRIBUTES; const variableName = attributeInfo.variableName; const use2DPosition = variableName === "positionMC" && use2D; if (use2DPosition) { const line = "attributes.position2D = a_position2D;"; shaderBuilder.addFunctionLines(functionId, [line]); } if (attributeInfo.isQuantized) { return; } const lines = []; if (variableName === "tangentMC") { lines.push("attributes.tangentMC = a_tangentMC.xyz;"); lines.push("attributes.tangentSignMC = a_tangentMC.w;"); } else { lines.push(`attributes.${variableName} = a_${variableName};`); } shaderBuilder.addFunctionLines(functionId, lines); } function updateSetDynamicVaryingsFunction(shaderBuilder, attributeInfo) { const { semantic, setIndex } = attributeInfo.attribute; if (defined_default(semantic) && !defined_default(setIndex)) { return; } let functionId = GeometryPipelineStage.FUNCTION_ID_SET_DYNAMIC_VARYINGS_VS; const variableName = attributeInfo.variableName; let line = `v_${variableName} = attributes.${variableName};`; shaderBuilder.addFunctionLines(functionId, [line]); functionId = GeometryPipelineStage.FUNCTION_ID_SET_DYNAMIC_VARYINGS_FS; line = `attributes.${variableName} = v_${variableName};`; shaderBuilder.addFunctionLines(functionId, [line]); } function handleBitangents(shaderBuilder, attributes) { let hasNormals = false; let hasTangents = false; for (let i = 0; i < attributes.length; i++) { const attribute = attributes[i]; if (attribute.semantic === VertexAttributeSemantic_default.NORMAL) { hasNormals = true; } else if (attribute.semantic === VertexAttributeSemantic_default.TANGENT) { hasTangents = true; } } if (!hasNormals || !hasTangents) { return; } shaderBuilder.addDefine("HAS_BITANGENTS"); shaderBuilder.addVarying("vec3", "v_bitangentEC"); shaderBuilder.addStructField( GeometryPipelineStage.STRUCT_ID_PROCESSED_ATTRIBUTES_VS, "vec3", "bitangentMC" ); shaderBuilder.addStructField( GeometryPipelineStage.STRUCT_ID_PROCESSED_ATTRIBUTES_FS, "vec3", "bitangentEC" ); } var GeometryPipelineStage_default = GeometryPipelineStage; // packages/engine/Source/Scene/Model/ImageryPipelineStage.js var import_InlineWorkers688 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/ImageryLayer.js var import_InlineWorkers679 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/createWorldImageryAsync.js var import_InlineWorkers672 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/IonImageryProvider.js var import_InlineWorkers670 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Scene/ArcGisMapServerImageryProvider.js var import_InlineWorkers655 = __toESM(require_InlineWorkers(), 1); // packages/engine/Source/Core/WebMercatorTilingScheme.js var import_InlineWorkers649 = __toESM(require_InlineWorkers(), 1); function WebMercatorTilingScheme(options) { options = options ?? Frozen_default.EMPTY_OBJECT; this._ellipsoid = options.ellipsoid ?? Ellipsoid_default.default; this._numberOfLevelZeroTilesX = options.numberOfLevelZeroTilesX ?? 1; this._numberOfLevelZeroTilesY = options.numberOfLevelZeroTilesY ?? 1; this._projection = new WebMercatorProjection_default(this._ellipsoid); if (defined_default(options.rectangleSouthwestInMeters) && defined_default(options.rectangleNortheastInMeters)) { this._rectangleSouthwestInMeters = options.rectangleSouthwestInMeters; this._rectangleNortheastInMeters = options.rectangleNortheastInMeters; } else { const semimajorAxisTimesPi = this._ellipsoid.maximumRadius * Math.PI; this._rectangleSouthwestInMeters = new Cartesian2_default( -semimajorAxisTimesPi, -semimajorAxisTimesPi ); this._rectangleNortheastInMeters = new Cartesian2_default( semimajorAxisTimesPi, semimajorAxisTimesPi ); } const southwest = this._projection.unproject( this._rectangleSouthwestInMeters ); const northeast = this._projection.unproject( this._rectangleNortheastInMeters ); this._rectangle = new Rectangle_default( southwest.longitude, southwest.latitude, northeast.longitude, northeast.latitude ); } Object.defineProperties(WebMercatorTilingScheme.prototype, { /** * Gets the ellipsoid that is tiled by this tiling scheme. * @memberof WebMercatorTilingScheme.prototype * @type {Ellipsoid} */ ellipsoid: { get: function() { return this._ellipsoid; } }, /** * Gets the rectangle, in radians, covered by this tiling scheme. * @memberof WebMercatorTilingScheme.prototype * @type {Rectangle} */ rectangle: { get: function() { return this._rectangle; } }, /** * Gets the map projection used by this tiling scheme. * @memberof WebMercatorTilingScheme.prototype * @type {MapProjection} */ projection: { get: function() { return this._projection; } } }); WebMercatorTilingScheme.prototype.getNumberOfXTilesAtLevel = function(level) { return this._numberOfLevelZeroTilesX << level; }; WebMercatorTilingScheme.prototype.getNumberOfYTilesAtLevel = function(level) { return this._numberOfLevelZeroTilesY << level; }; WebMercatorTilingScheme.prototype.rectangleToNativeRectangle = function(rectangle, result) { const projection = this._projection; const southwest = projection.project(Rectangle_default.southwest(rectangle)); const northeast = projection.project(Rectangle_default.northeast(rectangle)); if (!defined_default(result)) { return new Rectangle_default(southwest.x, southwest.y, northeast.x, northeast.y); } result.west = southwest.x; result.south = southwest.y; result.east = northeast.x; result.north = northeast.y; return result; }; WebMercatorTilingScheme.prototype.tileXYToNativeRectangle = function(x, y, level, result) { const xTiles = this.getNumberOfXTilesAtLevel(level); const yTiles = this.getNumberOfYTilesAtLevel(level); const xTileWidth = (this._rectangleNortheastInMeters.x - this._rectangleSouthwestInMeters.x) / xTiles; const west = this._rectangleSouthwestInMeters.x + x * xTileWidth; const east = this._rectangleSouthwestInMeters.x + (x + 1) * xTileWidth; const yTileHeight = (this._rectangleNortheastInMeters.y - this._rectangleSouthwestInMeters.y) / yTiles; const north = this._rectangleNortheastInMeters.y - y * yTileHeight; const south = this._rectangleNortheastInMeters.y - (y + 1) * yTileHeight; if (!defined_default(result)) { return new Rectangle_default(west, south, east, north); } result.west = west; result.south = south; result.east = east; result.north = north; return result; }; WebMercatorTilingScheme.prototype.tileXYToRectangle = function(x, y, level, result) { const nativeRectangle = this.tileXYToNativeRectangle(x, y, level, result); const projection = this._projection; const southwest = projection.unproject( new Cartesian2_default(nativeRectangle.west, nativeRectangle.south) ); const northeast = projection.unproject( new Cartesian2_default(nativeRectangle.east, nativeRectangle.north) ); nativeRectangle.west = southwest.longitude; nativeRectangle.south = southwest.latitude; nativeRectangle.east = northeast.longitude; nativeRectangle.north = northeast.latitude; return nativeRectangle; }; WebMercatorTilingScheme.prototype.positionToTileXY = function(position, level, result) { const rectangle = this._rectangle; if (!Rectangle_default.contains(rectangle, position)) { return void 0; } const xTiles = this.getNumberOfXTilesAtLevel(level); const yTiles = this.getNumberOfYTilesAtLevel(level); const overallWidth = this._rectangleNortheastInMeters.x - this._rectangleSouthwestInMeters.x; const xTileWidth = overallWidth / xTiles; const overallHeight = this._rectangleNortheastInMeters.y - this._rectangleSouthwestInMeters.y; const yTileHeight = overallHeight / yTiles; const projection = this._projection; const webMercatorPosition = projection.project(position); const distanceFromWest = webMercatorPosition.x - this._rectangleSouthwestInMeters.x; const distanceFromNorth = this._rectangleNortheastInMeters.y - webMercatorPosition.y; let xTileCoordinate = distanceFromWest / xTileWidth | 0; if (xTileCoordinate >= xTiles) { xTileCoordinate = xTiles - 1; } let yTileCoordinate = distanceFromNorth / yTileHeight | 0; if (yTileCoordinate >= yTiles) { yTileCoordinate = yTiles - 1; } if (!defined_default(result)) { return new Cartesian2_default(xTileCoordinate, yTileCoordinate); } result.x = xTileCoordinate; result.y = yTileCoordinate; return result; }; var WebMercatorTilingScheme_default = WebMercatorTilingScheme; // packages/engine/Source/Scene/ArcGisMapService.js var import_InlineWorkers650 = __toESM(require_InlineWorkers(), 1); var defaultTokenCredit2; var defaultAccessToken2 = "AAPTxy8BH1VEsoebNVZXo8HurEOF051kAEKlhkOhBEc9BmRXcPUeuOd6ZTh-Z86vRv6teqZdBYLUWIxB6HTYajPhFtAlXhMdqTg07UwlBQ59KbiReC5wCeOF4LzLTW4oaSPp-t4pEcJHnFePlnFcIPXM7R565gTy6f6fMuZAXPvUEuZSMf8dvTqHyV9-Zd9eZGWokDzKC4uEtHME7OeAk3oyZ7vzkjEo8fpuIfFw0sH8vQU.AT1_PLgWE6Lc"; var ArcGisMapService = {}; ArcGisMapService.defaultAccessToken = defaultAccessToken2; ArcGisMapService.defaultWorldImageryServer = new Resource_default({ url: "https://ibasemaps-api.arcgis.com/arcgis/rest/services/World_Imagery/MapServer" }); ArcGisMapService.defaultWorldHillshadeServer = new Resource_default({ url: "https://ibasemaps-api.arcgis.com/arcgis/rest/services/Elevation/World_Hillshade/MapServer" }); ArcGisMapService.defaultWorldOceanServer = new Resource_default({ url: "https://ibasemaps-api.arcgis.com/arcgis/rest/services/Ocean/World_Ocean_Base/MapServer" }); ArcGisMapService.getDefaultTokenCredit = function(providedKey) { if (providedKey !== defaultAccessToken2) { return void 0; } if (!defined_default(defaultTokenCredit2)) { const defaultTokenMessage = ' This application is using a default ArcGIS access token. Please assign Cesium.ArcGisMapService.defaultAccessToken with an API key from your ArcGIS Developer account before using the ArcGIS tile services. You can sign up for a free ArcGIS Developer account at https://developers.arcgis.com/.'; defaultTokenCredit2 = new Credit_default(defaultTokenMessage, true); } return defaultTokenCredit2; }; var ArcGisMapService_default = ArcGisMapService; // packages/engine/Source/Scene/DiscardMissingTileImagePolicy.js var import_InlineWorkers651 = __toESM(require_InlineWorkers(), 1); function DiscardMissingTileImagePolicy(options) { options = options ?? Frozen_default.EMPTY_OBJECT; if (!defined_default(options.missingImageUrl)) { throw new DeveloperError_default("options.missingImageUrl is required."); } if (!defined_default(options.pixelsToCheck)) { throw new DeveloperError_default("options.pixelsToCheck is required."); } this._pixelsToCheck = options.pixelsToCheck; this._missingImagePixels = void 0; this._missingImageByteLength = void 0; this._isReady = false; const resource = Resource_default.createIfNeeded(options.missingImageUrl); const that = this; function success(image) { if (defined_default(image.blob)) { that._missingImageByteLength = image.blob.size; } let pixels = getImagePixels_default(image); if (options.disableCheckIfAllPixelsAreTransparent) { let allAreTransparent = true; const width = image.width; const pixelsToCheck = options.pixelsToCheck; for (let i = 0, len = pixelsToCheck.length; allAreTransparent && i < len; ++i) { const pos = pixelsToCheck[i]; const index = pos.x * 4 + pos.y * width; const alpha = pixels[index + 3]; if (alpha > 0) { allAreTransparent = false; } } if (allAreTransparent) { pixels = void 0; } } that._missingImagePixels = pixels; that._isReady = true; } function failure2() { that._missingImagePixels = void 0; that._isReady = true; } resource.fetchImage({ preferBlob: true, preferImageBitmap: true, flipY: true }).then(success).catch(failure2); } DiscardMissingTileImagePolicy.prototype.isReady = function() { return this._isReady; }; DiscardMissingTileImagePolicy.prototype.shouldDiscardImage = function(image) { if (!this._isReady) { throw new DeveloperError_default( "shouldDiscardImage must not be called before the discard policy is ready." ); } const pixelsToCheck = this._pixelsToCheck; const missingImagePixels = this._missingImagePixels; if (!defined_default(missingImagePixels)) { return false; } if (defined_default(image.blob) && image.blob.size !== this._missingImageByteLength) { return false; } const pixels = getImagePixels_default(image); const width = image.width; for (let i = 0, len = pixelsToCheck.length; i < len; ++i) { const pos = pixelsToCheck[i]; const index = pos.x * 4 + pos.y * width; for (let offset = 0; offset < 4; ++offset) { const pixel = index + offset; if (pixels[pixel] !== missingImagePixels[pixel]) { return false; } } } return true; }; var DiscardMissingTileImagePolicy_default = DiscardMissingTileImagePolicy; // packages/engine/Source/Scene/ImageryLayerFeatureInfo.js var import_InlineWorkers652 = __toESM(require_InlineWorkers(), 1); function ImageryLayerFeatureInfo() { this.name = void 0; this.description = void 0; this.position = void 0; this.data = void 0; this.imageryLayer = void 0; } ImageryLayerFeatureInfo.prototype.configureNameFromProperties = function(properties) { let namePropertyPrecedence = 10; let nameProperty; for (const key in properties) { if (properties.hasOwnProperty(key) && properties[key]) { const lowerKey = key.toLowerCase(); if (namePropertyPrecedence > 1 && lowerKey === "name") { namePropertyPrecedence = 1; nameProperty = key; } else if (namePropertyPrecedence > 2 && lowerKey === "title") { namePropertyPrecedence = 2; nameProperty = key; } else if (namePropertyPrecedence > 3 && /name/i.test(key)) { namePropertyPrecedence = 3; nameProperty = key; } else if (namePropertyPrecedence > 4 && /title/i.test(key)) { namePropertyPrecedence = 4; nameProperty = key; } } } if (defined_default(nameProperty)) { this.name = properties[nameProperty]; } }; ImageryLayerFeatureInfo.prototype.configureDescriptionFromProperties = function(properties) { function describe(properties2) { let html2 = '| ${key} | ${describe(value)} |
| ${key} | ${value} |
{z}: The level of the tile in the tiling scheme. Level zero is the root of the quadtree pyramid.{x}: The tile X coordinate in the tiling scheme, where 0 is the Westernmost tile.{y}: The tile Y coordinate in the tiling scheme, where 0 is the Northernmost tile.{s}: One of the available subdomains, used to overcome browser limits on the number of simultaneous requests per host.{reverseX}: The tile X coordinate in the tiling scheme, where 0 is the Easternmost tile.{reverseY}: The tile Y coordinate in the tiling scheme, where 0 is the Southernmost tile.{reverseZ}: The level of the tile in the tiling scheme, where level zero is the maximum level of the quadtree pyramid. In order to use reverseZ, maximumLevel must be defined.{westDegrees}: The Western edge of the tile in geodetic degrees.{southDegrees}: The Southern edge of the tile in geodetic degrees.{eastDegrees}: The Eastern edge of the tile in geodetic degrees.{northDegrees}: The Northern edge of the tile in geodetic degrees.{westProjected}: The Western edge of the tile in projected coordinates of the tiling scheme.{southProjected}: The Southern edge of the tile in projected coordinates of the tiling scheme.{eastProjected}: The Eastern edge of the tile in projected coordinates of the tiling scheme.{northProjected}: The Northern edge of the tile in projected coordinates of the tiling scheme.{width}: The width of each tile in pixels.{height}: The height of each tile in pixels.{z}: The zero padding for the level of the tile in the tiling scheme.{x}: The zero padding for the tile X coordinate in the tiling scheme.{y}: The zero padding for the the tile Y coordinate in the tiling scheme.{reverseX}: The zero padding for the tile reverseX coordinate in the tiling scheme.{reverseY}: The zero padding for the tile reverseY coordinate in the tiling scheme.{reverseZ}: The zero padding for the reverseZ coordinate of the tile in the tiling scheme.{i}: The pixel column (horizontal coordinate) of the picked position, where the Westernmost pixel is 0.{j}: The pixel row (vertical coordinate) of the picked position, where the Northernmost pixel is 0.{reverseI}: The pixel column (horizontal coordinate) of the picked position, where the Easternmost pixel is 0.{reverseJ}: The pixel row (vertical coordinate) of the picked position, where the Southernmost pixel is 0.{longitudeDegrees}: The longitude of the picked position in degrees.{latitudeDegrees}: The latitude of the picked position in degrees.{longitudeProjected}: The longitude of the picked position in the projected coordinates of the tiling scheme.{latitudeProjected}: The latitude of the picked position in the projected coordinates of the tiling scheme.{format}: The format in which to get feature information, as specified in the {@link GetFeatureInfoFormat}.GetFeatureInfo service on the WMS server and attempt to interpret the features included in the response. If false,
* {@link WebMapServiceImageryProvider#pickFeatures} will immediately return undefined (indicating no pickable
* features) without communicating with the server. Set this property to false if you know your data
* source does not support picking features or if you don't want this provider's features to be pickable.
* @memberof WebMapServiceImageryProvider.prototype
* @type {boolean}
* @default true
*/
enablePickFeatures: {
get: function() {
return this._tileProvider.enablePickFeatures;
},
set: function(enablePickFeatures) {
this._tileProvider.enablePickFeatures = enablePickFeatures;
}
},
/**
* Gets or sets a clock that is used to get keep the time used for time dynamic parameters.
* @memberof WebMapServiceImageryProvider.prototype
* @type {Clock}
*/
clock: {
get: function() {
return this._timeDynamicImagery.clock;
},
set: function(value) {
this._timeDynamicImagery.clock = value;
}
},
/**
* Gets or sets a time interval collection that is used to get time dynamic parameters. The data of each
* TimeInterval is an object containing the keys and values of the properties that are used during
* tile requests.
* @memberof WebMapServiceImageryProvider.prototype
* @type {TimeIntervalCollection}
*/
times: {
get: function() {
return this._timeDynamicImagery.times;
},
set: function(value) {
this._timeDynamicImagery.times = value;
}
},
/**
* Gets the getFeatureInfo URL of the WMS server.
* @memberof WebMapServiceImageryProvider.prototype
* @type {Resource|string}
* @readonly
*/
getFeatureInfoUrl: {
get: function() {
return this._getFeatureInfoUrl;
}
}
});
WebMapServiceImageryProvider.prototype.getTileCredits = function(x, y, level) {
return this._tileProvider.getTileCredits(x, y, level);
};
WebMapServiceImageryProvider.prototype.requestImage = function(x, y, level, request) {
let result;
const timeDynamicImagery = this._timeDynamicImagery;
let currentInterval;
if (defined_default(timeDynamicImagery)) {
currentInterval = timeDynamicImagery.currentInterval;
result = timeDynamicImagery.getFromCache(x, y, level, request);
}
if (!defined_default(result)) {
result = requestImage(this, x, y, level, request, currentInterval);
}
if (defined_default(result) && defined_default(timeDynamicImagery)) {
timeDynamicImagery.checkApproachingInterval(x, y, level, request);
}
return result;
};
WebMapServiceImageryProvider.prototype.pickFeatures = function(x, y, level, longitude, latitude) {
const timeDynamicImagery = this._timeDynamicImagery;
const currentInterval = defined_default(timeDynamicImagery) ? timeDynamicImagery.currentInterval : void 0;
return pickFeatures(this, x, y, level, longitude, latitude, currentInterval);
};
WebMapServiceImageryProvider.DefaultParameters = Object.freeze({
service: "WMS",
version: "1.1.1",
request: "GetMap",
styles: "",
format: "image/jpeg"
});
WebMapServiceImageryProvider.GetFeatureInfoDefaultParameters = Object.freeze({
service: "WMS",
version: "1.1.1",
request: "GetFeatureInfo"
});
WebMapServiceImageryProvider.DefaultGetFeatureInfoFormats = Object.freeze([
Object.freeze(new GetFeatureInfoFormat_default("json", "application/json")),
Object.freeze(new GetFeatureInfoFormat_default("xml", "text/xml")),
Object.freeze(new GetFeatureInfoFormat_default("text", "text/html"))
]);
function objectToLowercase(obj) {
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result[key.toLowerCase()] = obj[key];
}
}
return result;
}
var WebMapServiceImageryProvider_default = WebMapServiceImageryProvider;
// packages/engine/Source/Scene/WebMapTileServiceImageryProvider.js
var import_InlineWorkers669 = __toESM(require_InlineWorkers(), 1);
var defaultParameters = Object.freeze({
service: "WMTS",
version: "1.0.0",
request: "GetTile"
});
function WebMapTileServiceImageryProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
if (!defined_default(options.url)) {
throw new DeveloperError_default("options.url is required.");
}
if (!defined_default(options.layer)) {
throw new DeveloperError_default("options.layer is required.");
}
if (!defined_default(options.style)) {
throw new DeveloperError_default("options.style is required.");
}
if (!defined_default(options.tileMatrixSetID)) {
throw new DeveloperError_default("options.tileMatrixSetID is required.");
}
if (defined_default(options.times) && !defined_default(options.clock)) {
throw new DeveloperError_default(
"options.times was specified, so options.clock is required."
);
}
this._defaultAlpha = void 0;
this._defaultNightAlpha = void 0;
this._defaultDayAlpha = void 0;
this._defaultBrightness = void 0;
this._defaultContrast = void 0;
this._defaultHue = void 0;
this._defaultSaturation = void 0;
this._defaultGamma = void 0;
this._defaultMinificationFilter = void 0;
this._defaultMagnificationFilter = void 0;
const resource = Resource_default.createIfNeeded(options.url);
const style = options.style;
const tileMatrixSetID = options.tileMatrixSetID;
const url2 = resource.url;
const bracketMatch = url2.match(/{/g);
if (!defined_default(bracketMatch) || bracketMatch.length === 1 && /{s}/.test(url2)) {
resource.setQueryParameters(defaultParameters);
this._useKvp = true;
} else {
const templateValues = {
style,
Style: style,
TileMatrixSet: tileMatrixSetID
};
resource.setTemplateValues(templateValues);
this._useKvp = false;
}
this._resource = resource;
this._layer = options.layer;
this._style = style;
this._tileMatrixSetID = tileMatrixSetID;
this._tileMatrixLabels = options.tileMatrixLabels;
this._format = options.format ?? "image/jpeg";
this._tileDiscardPolicy = options.tileDiscardPolicy;
this._tilingScheme = defined_default(options.tilingScheme) ? options.tilingScheme : new WebMercatorTilingScheme_default({ ellipsoid: options.ellipsoid });
this._tileWidth = options.tileWidth ?? 256;
this._tileHeight = options.tileHeight ?? 256;
this._minimumLevel = options.minimumLevel ?? 0;
this._maximumLevel = options.maximumLevel;
this._rectangle = options.rectangle ?? this._tilingScheme.rectangle;
this._dimensions = options.dimensions;
const that = this;
this._reload = void 0;
if (defined_default(options.times)) {
this._timeDynamicImagery = new TimeDynamicImagery_default({
clock: options.clock,
times: options.times,
requestImageFunction: function(x, y, level, request, interval) {
return requestImage2(that, x, y, level, request, interval);
},
reloadFunction: function() {
if (defined_default(that._reload)) {
that._reload();
}
}
});
}
this._errorEvent = new Event_default();
const credit = options.credit;
this._credit = typeof credit === "string" ? new Credit_default(credit) : credit;
this._subdomains = options.subdomains;
if (Array.isArray(this._subdomains)) {
this._subdomains = this._subdomains.slice();
} else if (defined_default(this._subdomains) && this._subdomains.length > 0) {
this._subdomains = this._subdomains.split("");
} else {
this._subdomains = ["a", "b", "c"];
}
}
function requestImage2(imageryProvider, col, row, level, request, interval) {
const labels = imageryProvider._tileMatrixLabels;
const tileMatrix = defined_default(labels) ? labels[level] : level.toString();
const subdomains = imageryProvider._subdomains;
const staticDimensions = imageryProvider._dimensions;
const dynamicIntervalData = defined_default(interval) ? interval.data : void 0;
let resource;
let templateValues;
if (!imageryProvider._useKvp) {
templateValues = {
TileMatrix: tileMatrix,
TileRow: row.toString(),
TileCol: col.toString(),
s: subdomains[(col + row + level) % subdomains.length]
};
resource = imageryProvider._resource.getDerivedResource({
request
});
resource.setTemplateValues(templateValues);
if (defined_default(staticDimensions)) {
resource.setTemplateValues(staticDimensions);
}
if (defined_default(dynamicIntervalData)) {
resource.setTemplateValues(dynamicIntervalData);
}
} else {
let query = {};
query.tilematrix = tileMatrix;
query.layer = imageryProvider._layer;
query.style = imageryProvider._style;
query.tilerow = row;
query.tilecol = col;
query.tilematrixset = imageryProvider._tileMatrixSetID;
query.format = imageryProvider._format;
if (defined_default(staticDimensions)) {
query = combine_default(query, staticDimensions);
}
if (defined_default(dynamicIntervalData)) {
query = combine_default(query, dynamicIntervalData);
}
templateValues = {
s: subdomains[(col + row + level) % subdomains.length]
};
resource = imageryProvider._resource.getDerivedResource({
queryParameters: query,
request
});
resource.setTemplateValues(templateValues);
}
return ImageryProvider_default.loadImage(imageryProvider, resource);
}
Object.defineProperties(WebMapTileServiceImageryProvider.prototype, {
/**
* Gets the URL of the service hosting the imagery.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {string}
* @readonly
*/
url: {
get: function() {
return this._resource.url;
}
},
/**
* Gets the proxy used by this provider.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {Proxy}
* @readonly
*/
proxy: {
get: function() {
return this._resource.proxy;
}
},
/**
* Gets the width of each tile, in pixels.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {number}
* @readonly
*/
tileWidth: {
get: function() {
return this._tileWidth;
}
},
/**
* Gets the height of each tile, in pixels.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {number}
* @readonly
*/
tileHeight: {
get: function() {
return this._tileHeight;
}
},
/**
* Gets the maximum level-of-detail that can be requested.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {number|undefined}
* @readonly
*/
maximumLevel: {
get: function() {
return this._maximumLevel;
}
},
/**
* Gets the minimum level-of-detail that can be requested.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {number}
* @readonly
*/
minimumLevel: {
get: function() {
return this._minimumLevel;
}
},
/**
* Gets the tiling scheme used by this provider.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {TilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._tilingScheme;
}
},
/**
* Gets the rectangle, in radians, of the imagery provided by this instance.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {Rectangle}
* @readonly
*/
rectangle: {
get: function() {
return this._rectangle;
}
},
/**
* Gets the tile discard policy. If not undefined, the discard policy is responsible
* for filtering out "missing" tiles via its shouldDiscardImage function. If this function
* returns undefined, no tiles are filtered.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {TileDiscardPolicy}
* @readonly
*/
tileDiscardPolicy: {
get: function() {
return this._tileDiscardPolicy;
}
},
/**
* Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets the mime type of images returned by this imagery provider.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {string}
* @readonly
*/
format: {
get: function() {
return this._format;
}
},
/**
* Gets the credit to display when this imagery provider is active. Typically this is used to credit
* the source of the imagery.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return this._credit;
}
},
/**
* Gets a value indicating whether or not the images provided by this imagery provider
* include an alpha channel. If this property is false, an alpha channel, if present, will
* be ignored. If this property is true, any images without an alpha channel will be treated
* as if their alpha is 1.0 everywhere. When this property is false, memory usage
* and texture upload time are reduced.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {boolean}
* @readonly
*/
hasAlphaChannel: {
get: function() {
return true;
}
},
/**
* Gets or sets a clock that is used to get keep the time used for time dynamic parameters.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {Clock}
*/
clock: {
get: function() {
return this._timeDynamicImagery.clock;
},
set: function(value) {
this._timeDynamicImagery.clock = value;
}
},
/**
* Gets or sets a time interval collection that is used to get time dynamic parameters. The data of each
* TimeInterval is an object containing the keys and values of the properties that are used during
* tile requests.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {TimeIntervalCollection}
*/
times: {
get: function() {
return this._timeDynamicImagery.times;
},
set: function(value) {
this._timeDynamicImagery.times = value;
}
},
/**
* Gets or sets an object that contains static dimensions and their values.
* @memberof WebMapTileServiceImageryProvider.prototype
* @type {object}
*/
dimensions: {
get: function() {
return this._dimensions;
},
set: function(value) {
if (this._dimensions !== value) {
this._dimensions = value;
if (defined_default(this._reload)) {
this._reload();
}
}
}
}
});
WebMapTileServiceImageryProvider.prototype.getTileCredits = function(x, y, level) {
return void 0;
};
WebMapTileServiceImageryProvider.prototype.requestImage = function(x, y, level, request) {
let result;
const timeDynamicImagery = this._timeDynamicImagery;
let currentInterval;
if (defined_default(timeDynamicImagery)) {
currentInterval = timeDynamicImagery.currentInterval;
result = timeDynamicImagery.getFromCache(x, y, level, request);
}
if (!defined_default(result)) {
result = requestImage2(this, x, y, level, request, currentInterval);
}
if (defined_default(result) && defined_default(timeDynamicImagery)) {
timeDynamicImagery.checkApproachingInterval(x, y, level, request);
}
return result;
};
WebMapTileServiceImageryProvider.prototype.pickFeatures = function(x, y, level, longitude, latitude) {
return void 0;
};
var WebMapTileServiceImageryProvider_default = WebMapTileServiceImageryProvider;
// packages/engine/Source/Scene/IonImageryProvider.js
var ImageryProviderAsyncMapping = {
ARCGIS_MAPSERVER: ArcGisMapServerImageryProvider_default.fromUrl,
BING: async (url2, options) => {
return BingMapsImageryProvider_default.fromUrl(url2, options);
},
GOOGLE_EARTH: async (url2, options) => {
const channel = options.channel;
delete options.channel;
return GoogleEarthEnterpriseMapsProvider_default.fromUrl(url2, channel, options);
},
MAPBOX: (url2, options) => {
return new MapboxImageryProvider_default({
url: url2,
...options
});
},
SINGLE_TILE: SingleTileImageryProvider_default.fromUrl,
TMS: TileMapServiceImageryProvider_default.fromUrl,
URL_TEMPLATE: (url2, options) => {
return new UrlTemplateImageryProvider_default({
url: url2,
...options
});
},
WMS: (url2, options) => {
return new WebMapServiceImageryProvider_default({
url: url2,
...options
});
},
WMTS: (url2, options) => {
return new WebMapTileServiceImageryProvider_default({
url: url2,
...options
});
}
};
function IonImageryProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._defaultAlpha = void 0;
this._defaultNightAlpha = void 0;
this._defaultDayAlpha = void 0;
this._defaultBrightness = void 0;
this._defaultContrast = void 0;
this._defaultHue = void 0;
this._defaultSaturation = void 0;
this._defaultGamma = void 0;
this._defaultMinificationFilter = void 0;
this._defaultMagnificationFilter = void 0;
this._tileCredits = void 0;
this._errorEvent = new Event_default();
}
Object.defineProperties(IonImageryProvider.prototype, {
/**
* Gets the rectangle, in radians, of the imagery provided by the instance.
* @memberof IonImageryProvider.prototype
* @type {Rectangle}
* @readonly
*/
rectangle: {
get: function() {
return this._imageryProvider.rectangle;
}
},
/**
* Gets the width of each tile, in pixels.
* @memberof IonImageryProvider.prototype
* @type {number}
* @readonly
*/
tileWidth: {
get: function() {
return this._imageryProvider.tileWidth;
}
},
/**
* Gets the height of each tile, in pixels.
* @memberof IonImageryProvider.prototype
* @type {number}
* @readonly
*/
tileHeight: {
get: function() {
return this._imageryProvider.tileHeight;
}
},
/**
* Gets the maximum level-of-detail that can be requested.
* @memberof IonImageryProvider.prototype
* @type {number|undefined}
* @readonly
*/
maximumLevel: {
get: function() {
return this._imageryProvider.maximumLevel;
}
},
/**
* Gets the minimum level-of-detail that can be requested. Generally,
* a minimum level should only be used when the rectangle of the imagery is small
* enough that the number of tiles at the minimum level is small. An imagery
* provider with more than a few tiles at the minimum level will lead to
* rendering problems.
* @memberof IonImageryProvider.prototype
* @type {number}
* @readonly
*/
minimumLevel: {
get: function() {
return this._imageryProvider.minimumLevel;
}
},
/**
* Gets the tiling scheme used by the provider.
* @memberof IonImageryProvider.prototype
* @type {TilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._imageryProvider.tilingScheme;
}
},
/**
* Gets the tile discard policy. If not undefined, the discard policy is responsible
* for filtering out "missing" tiles via its shouldDiscardImage function. If this function
* returns undefined, no tiles are filtered.
* @memberof IonImageryProvider.prototype
* @type {TileDiscardPolicy}
* @readonly
*/
tileDiscardPolicy: {
get: function() {
return this._imageryProvider.tileDiscardPolicy;
}
},
/**
* Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof IonImageryProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets the credit to display when this imagery provider is active. Typically this is used to credit
* the source of the imagery.
* @memberof IonImageryProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return this._imageryProvider.credit;
}
},
/**
* Gets a value indicating whether or not the images provided by this imagery provider
* include an alpha channel. If this property is false, an alpha channel, if present, will
* be ignored. If this property is true, any images without an alpha channel will be treated
* as if their alpha is 1.0 everywhere. When this property is false, memory usage
* and texture upload time are reduced.
* @memberof IonImageryProvider.prototype
* @type {boolean}
* @readonly
*/
hasAlphaChannel: {
get: function() {
return this._imageryProvider.hasAlphaChannel;
}
},
/**
* Gets the proxy used by this provider.
* @memberof IonImageryProvider.prototype
* @type {Proxy}
* @readonly
* @default undefined
*/
proxy: {
get: function() {
return void 0;
}
}
});
IonImageryProvider.fromAssetId = async function(assetId, options) {
Check_default.typeOf.number("assetId", assetId);
options = options ?? Frozen_default.EMPTY_OBJECT;
const endpointResource = IonResource_default._createEndpointResource(
assetId,
options
);
const cacheKey = assetId.toString() + options.accessToken + options.server;
let promise = IonImageryProvider._endpointCache[cacheKey];
if (!defined_default(promise)) {
promise = endpointResource.fetchJson();
IonImageryProvider._endpointCache[cacheKey] = promise;
}
const endpoint = await promise;
if (endpoint.type !== "IMAGERY") {
throw new RuntimeError_default(
`Cesium ion asset ${assetId} is not an imagery asset.`
);
}
let imageryProvider;
const externalType = endpoint.externalType;
if (!defined_default(externalType)) {
imageryProvider = await TileMapServiceImageryProvider_default.fromUrl(
new IonResource_default(endpoint, endpointResource)
);
} else {
const factory = ImageryProviderAsyncMapping[externalType];
if (!defined_default(factory)) {
throw new RuntimeError_default(
`Unrecognized Cesium ion imagery type: ${externalType}`
);
}
const options2 = { ...endpoint.options };
const url2 = options2.url;
delete options2.url;
imageryProvider = await factory(url2, options2);
}
const provider = new IonImageryProvider(options);
imageryProvider.errorEvent.addEventListener(function(tileProviderError) {
tileProviderError.provider = provider;
provider._errorEvent.raiseEvent(tileProviderError);
});
provider._tileCredits = IonResource_default.getCreditsFromEndpoint(
endpoint,
endpointResource
);
provider._imageryProvider = imageryProvider;
return provider;
};
IonImageryProvider.prototype.getTileCredits = function(x, y, level) {
const innerCredits = this._imageryProvider.getTileCredits(x, y, level);
if (!defined_default(innerCredits)) {
return this._tileCredits;
}
return this._tileCredits.concat(innerCredits);
};
IonImageryProvider.prototype.requestImage = function(x, y, level, request) {
return this._imageryProvider.requestImage(x, y, level, request);
};
IonImageryProvider.prototype.pickFeatures = function(x, y, level, longitude, latitude) {
return this._imageryProvider.pickFeatures(x, y, level, longitude, latitude);
};
IonImageryProvider._endpointCache = {};
var IonImageryProvider_default = IonImageryProvider;
// packages/engine/Source/Scene/IonWorldImageryStyle.js
var import_InlineWorkers671 = __toESM(require_InlineWorkers(), 1);
var IonWorldImageryStyle = {
/**
* Aerial imagery.
*
* @type {number}
* @constant
*/
AERIAL: 2,
/**
* Aerial imagery with a road overlay.
*
* @type {number}
* @constant
*/
AERIAL_WITH_LABELS: 3,
/**
* Roads without additional imagery.
*
* @type {number}
* @constant
*/
ROAD: 4
};
var IonWorldImageryStyle_default = Object.freeze(IonWorldImageryStyle);
// packages/engine/Source/Scene/createWorldImageryAsync.js
function createWorldImageryAsync(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const style = options.style ?? IonWorldImageryStyle_default.AERIAL;
return IonImageryProvider_default.fromAssetId(style);
}
var createWorldImageryAsync_default = createWorldImageryAsync;
// packages/engine/Source/Core/TerrainProvider.js
var import_InlineWorkers673 = __toESM(require_InlineWorkers(), 1);
function TerrainProvider() {
DeveloperError_default.throwInstantiationError();
}
Object.defineProperties(TerrainProvider.prototype, {
/**
* Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof TerrainProvider.prototype
* @type {EventCartesianRectangle that contains the
* (minU, minV, maxU, maxV) coordinate range.
*
* Clients may not modify the returned instance.
*
* @type {CartesianRectangle}
* @readonly
*/
get textureCoordinateRectangle() {
return this._textureCoordinateRectangle;
}
/**
* Returns the imagery
*
* @type {Imagery}
* @readonly
*/
get imagery() {
return this._imagery;
}
/**
* Computes the ImageryCoverage objects that describe the imagery
* tiles and the respective texture coordinates that are covered by the given
* input rectangle in the given imagery data.
*
* The given imagery level will be clamped if necessary, to be in the valid
* range for the imagery provider of the given imagery layer.
*
* @param {Rectangle} inputRectangle The input rectangle (e.g. tile bounds)
* @param {ImageryLayer} imageryLayer The imagery layer
* @param {number} inputImageryLevel The level for which the imagery coverage
* should be computed.
* @returns {ImageryCoverage[]} The objects describing the covered imagery
* and the respective texture coordinates
*/
static createImageryCoverages(inputRectangle, imageryLayer, inputImageryLevel) {
if (!imageryLayer.show) {
return [];
}
const imageryProvider = imageryLayer.imageryProvider;
const imageryLevel = _ImageryCoverage._clampImageryLevel(
imageryProvider,
inputImageryLevel
);
const imageryBounds = Rectangle_default.intersection(
imageryProvider.rectangle,
imageryLayer.rectangle,
imageryBoundsScratch2
);
const imageryTilingScheme = imageryProvider.tilingScheme;
const imageryRange = _ImageryCoverage._computeImageryRange(
inputRectangle,
imageryBounds,
imageryTilingScheme,
imageryLevel
);
const nativeInputRectangle = nativeInputRectangleScratch;
imageryTilingScheme.rectangleToNativeRectangle(
inputRectangle,
nativeInputRectangle
);
const nativeImageryBounds = nativeImageryBoundsScratch;
imageryTilingScheme.rectangleToNativeRectangle(
imageryBounds,
nativeImageryBounds
);
const computeClippedImageryRectangle = (x, y, level) => {
const localImageryRectangle = imageryTilingScheme.tileXYToRectangle(
x,
y,
level
);
const localClippedImageryRectangle = Rectangle_default.intersection(
localImageryRectangle,
imageryBounds,
clippedRectangleScratch2
);
if (!defined_default(localClippedImageryRectangle)) {
return void 0;
}
const nativeClippedImageryBounds = nativeClippedImageryBoundsScratch;
imageryTilingScheme.rectangleToNativeRectangle(
localClippedImageryRectangle,
nativeClippedImageryBounds
);
return nativeClippedImageryBounds;
};
const imageryCoverages = _ImageryCoverage._computeImageryCoverages(
imageryLayer,
imageryRange,
imageryLevel,
nativeInputRectangle,
computeClippedImageryRectangle
);
return imageryCoverages;
}
/**
* Validate the given imagery level against the constraints of the
* given imagery provider.
*
* This will clamp the given level to be in the range
* [minimumLevel, maximumLevel) that is
* defined by the given imagery provider (and cut off
* any fractional part that the input may have)
*
* @param {ImageryProvider} imageryProvider The imagery provider
* @param {number} imageryLevel The imagery level
* @returns {number} The validated level
*/
static _clampImageryLevel(imageryProvider, imageryLevel) {
const minimumLevel = imageryProvider.minimumLevel ?? 0;
const maximumLevel = imageryProvider.maximumLevel ?? Number.POSITIVE_INFINITY;
const clampedImageryLevel = Math.min(
maximumLevel - 1,
Math.max(minimumLevel, imageryLevel)
);
const validImageryLevel = Math.floor(clampedImageryLevel);
return validImageryLevel;
}
/**
* Compute the rectangle describing the range of imagery that is covered
* with the given rectangle.
*
* This will compute a rectangle with integer coordinates that describe
* the X/Y coordinates of the imagery that is overlapped by the given
* input rectangle, based on the given imagery rectangle.
*
* Extracted from _createTileImagerySkeletons.
*
* @param {Rectangle} inputRectangle The input rectangle
* @param {Rectangle} imageryBounds The imagery bounds
* @param {TilingScheme} imageryTilingScheme The tiling scheme
* @param {number} imageryLevel The imagery level
* @returns {CartesianRectangle} The rectangle
*/
static _computeImageryRange(inputRectangle, imageryBounds, imageryTilingScheme, imageryLevel) {
const overlappedRectangle = _ImageryCoverage._computeOverlappedRectangle(
inputRectangle,
imageryBounds
);
const northwestTileCoordinates = imageryTilingScheme.positionToTileXY(
Rectangle_default.northwest(overlappedRectangle),
imageryLevel
);
const southeastTileCoordinates = imageryTilingScheme.positionToTileXY(
Rectangle_default.southeast(overlappedRectangle),
imageryLevel
);
const result = new CartesianRectangle_default();
result.minX = northwestTileCoordinates.x;
result.minY = northwestTileCoordinates.y;
result.maxX = southeastTileCoordinates.x;
result.maxY = southeastTileCoordinates.y;
const veryCloseX = inputRectangle.width / 512;
const veryCloseY = inputRectangle.height / 512;
const northwestTileRectangle = imageryTilingScheme.tileXYToRectangle(
result.minX,
result.minY,
imageryLevel
);
const deltaNorth = Math.abs(
northwestTileRectangle.south - inputRectangle.north
);
if (deltaNorth < veryCloseY && result.minY < result.maxY) {
++result.minY;
}
const deltaWest = Math.abs(
northwestTileRectangle.east - inputRectangle.west
);
if (deltaWest < veryCloseX && result.minX < result.maxX) {
++result.minX;
}
const southeastTileRectangle = imageryTilingScheme.tileXYToRectangle(
result.maxX,
result.maxY,
imageryLevel
);
const deltaSouth = Math.abs(
southeastTileRectangle.north - inputRectangle.south
);
if (deltaSouth < veryCloseY && result.maxY > result.minY) {
--result.maxY;
}
const deltaEast = Math.abs(
southeastTileRectangle.west - inputRectangle.east
);
if (deltaEast < veryCloseX && result.maxX > result.minX) {
--result.maxX;
}
return result;
}
/**
* Clamp the given input rectangle to the given clamp rectangle.
*
* If the input rectangle is completely above/below or left/right
* of the clamp rectangle, then the north/south or east/east
* if the clamp rectangle will be used in the result.
*
* @param {Rectangle} input The input rectangle
* @param {Rectangle} clamp The clamping rectangle
* @param {Rectangle} [result] The result
* @returns {Rectangle} The result
*/
static _clampRectangle(input, clamp, result) {
if (!defined_default(result)) {
result = new Rectangle_default();
}
if (input.south >= clamp.north) {
result.north = result.south = clamp.north;
} else if (input.north <= clamp.south) {
result.north = result.south = clamp.south;
} else {
result.south = Math.max(input.south, clamp.south);
result.north = Math.min(input.north, clamp.north);
}
if (input.west >= clamp.east) {
result.west = result.east = clamp.east;
} else if (input.east <= clamp.west) {
result.west = result.east = clamp.west;
} else {
result.west = Math.max(input.west, clamp.west);
result.east = Math.min(input.east, clamp.east);
}
return result;
}
/**
* Compute overlap between the given input rectangle, and the given
* bounds that have been obtained from the imagery provider.
*
* @param {Rectangle} inputRectangle The input
* @param {Rectangle} imageryBounds The imagery bounds
* @returns {Rectangle} The rectangle
*/
static _computeOverlappedRectangle(inputRectangle, imageryBounds) {
const overlappedRectangle = Rectangle_default.intersection(
inputRectangle,
imageryBounds,
overlappedRectangleScratch
);
if (defined_default(overlappedRectangle)) {
return overlappedRectangle;
}
return _ImageryCoverage._clampRectangle(
inputRectangle,
imageryBounds,
overlappedRectangleScratch
);
}
/**
* Computes the ImageryCoverage objects that describe the imagery and
* the texture coordinates that are contained in the given range of
* imagery tile coordinates, referring to the given input rectangle.
*
* @param {ImageryLayer} imageryLayer The imagery layer
* @param {CartesianRectangle} imageryRange The range of imagery tile coordinates
* @param {number} imageryLevel The imagery level
* @param {Rectangle} nativeInputRectangle The input rectangle, in coordinates
* that are native for the tiling scheme
* @param {Function} computeClippedImageryRectangle A function that returns
* an imagery rectangle, based on (x, y, level), clipped to the imagery bounds
* (or undefined if there is no intersection between the imagery rectangle
* and the bounds)
* @returns {ImageryCoverage[]} The objects describing the covered imagery
* and the respective texture coordinates
*/
static _computeImageryCoverages(imageryLayer, imageryRange, imageryLevel, nativeInputRectangle, computeClippedImageryRectangle) {
const imageryCoverages = [];
for (let i = imageryRange.minX; i <= imageryRange.maxX; i++) {
const clippedImageryRectangleU = computeClippedImageryRectangle(
i,
imageryRange.maxY,
imageryLevel
);
if (!defined_default(clippedImageryRectangleU)) {
continue;
}
for (let j = imageryRange.minY; j <= imageryRange.maxY; j++) {
const clippedImageryRectangleV = computeClippedImageryRectangle(
i,
j,
imageryLevel
);
if (!defined_default(clippedImageryRectangleV)) {
continue;
}
const textureCoordinateRectangle = _ImageryCoverage._localizeToCartesianRectangle(
clippedImageryRectangleV,
nativeInputRectangle,
void 0
);
const imagery = imageryLayer.getImageryFromCache(i, j, imageryLevel);
const imageryCoverage = new _ImageryCoverage(
i,
j,
imageryLevel,
textureCoordinateRectangle,
imagery
);
imageryCoverages.push(imageryCoverage);
}
}
return imageryCoverages;
}
/**
* Compute the coordinates of the first rectangle relative to the
* second rectangle.
*
* The result will describe the bounds of the first rectangle
* in coordinates that are relative to the (south,west) and
* (width, height) of the second rectangle. This is suitable
* for describing the texture coordinates of the first
* rectangle within the second one.
*
* The result will be stored in the given result parameter, or
* in a new rectangle if the result was undefined.
*
* @param {Rectangle} rectangleA The first rectangle
* @param {Rectangle} rectangleB The second rectangle
* @param {CartesianRectangle} [result] The result
* @returns {CartesianRectangle} The result
*/
static _localizeToCartesianRectangle(rectangleA, rectangleB, result) {
if (!defined_default(result)) {
result = new CartesianRectangle_default();
}
const invX = 1 / rectangleB.width;
const invY = 1 / rectangleB.height;
result.minX = (rectangleA.west - rectangleB.west) * invX;
result.minY = (rectangleA.south - rectangleB.south) * invY;
result.maxX = (rectangleA.east - rectangleB.west) * invX;
result.maxY = (rectangleA.north - rectangleB.south) * invY;
return result;
}
};
var ImageryCoverage_default = ImageryCoverage;
// packages/engine/Source/Scene/Model/ModelImageryMapping.js
var import_InlineWorkers684 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Model/ModelReader.js
var import_InlineWorkers683 = __toESM(require_InlineWorkers(), 1);
var ModelReader = class _ModelReader {
/**
* Reads the data of the given atttribute into a typed array.
*
* This will read the data into a compact, flat array with the data
* type corresponding to the data type of the attribute.
*
* If the attribute is contained in an interleaved buffer, marked as
* 'normalized', quantized, or oct-encoded, then it will be deinterleaved,
* normalization will be applied, it will be dequantized and oct-decoded
* as necessary.
*
* The result will be THE actual attribute data.
*
* @param {ModelComponents.Attribute} attribute The attribute
* @returns {TypedArray} The attribute data
*/
static readAttributeAsTypedArray(attribute) {
Check_default.defined("attribute", attribute);
const compactTypedArray = _ModelReader.readAttributeAsRawCompactTypedArray(attribute);
const normalized = attribute.normalized;
const quantization = attribute.quantization;
if (!defined_default(quantization) && !normalized) {
return compactTypedArray;
}
const elementType = attribute.type;
const elementCount = attribute.count;
let normalizedTypedArray = compactTypedArray;
if (normalized) {
normalizedTypedArray = AttributeCompression_default.dequantize(
compactTypedArray,
attribute.componentDatatype,
elementType,
elementCount
);
}
if (!defined_default(quantization)) {
return normalizedTypedArray;
}
const dequantizedTypedArray = _ModelReader.dequantize(
normalizedTypedArray,
elementCount,
elementType,
quantization
);
return dequantizedTypedArray;
}
/**
* Read the data of the given attribute into a compact typed array.
*
* If the attribute is stored as interleaved data, then the result
* will be the deinterleaved data. If the data is quantized or
* normalized, then the resulting data will be the "raw" data,
* without applying normalization or dequantization.
*
* @param {ModelComponents.Attribute} attribute The attribute
* @returns {TypedArray} The raw attribute data
*/
static readAttributeAsRawCompactTypedArray(attribute) {
Check_default.defined("attribute", attribute);
const elementType = attribute.type;
const elementCount = attribute.count;
const componentsPerElement = AttributeType_default.getNumberOfComponents(elementType);
const totalComponentCount = elementCount * componentsPerElement;
let componentType = attribute.componentDatatype;
const quantization = attribute.quantization;
if (defined_default(quantization)) {
componentType = quantization.componentDatatype;
}
const buffer2 = attribute.buffer;
const byteOffset = attribute.byteOffset;
const byteStride = attribute.byteStride;
const bytesPerComponent = ComponentDatatype_default.getSizeInBytes(componentType);
const defaultByteStride = componentsPerElement * bytesPerComponent;
if (!defined_default(byteStride) || byteStride === defaultByteStride) {
const typedArray = ComponentDatatype_default.createTypedArray(
componentType,
totalComponentCount
);
buffer2.getBufferData(typedArray, byteOffset);
return typedArray;
}
const fullTypedArray = new Uint8Array(buffer2.sizeInBytes);
buffer2.getBufferData(fullTypedArray);
const compactTypedArray = ComponentDatatype_default.createTypedArray(
componentType,
totalComponentCount
);
const elementByteStride = byteStride ?? defaultByteStride;
const dataView = new DataView(
fullTypedArray.buffer,
fullTypedArray.byteOffset,
fullTypedArray.byteLength
);
const components = new Array(componentsPerElement);
const componentsReader = _ModelReader.createComponentsReader(componentType);
for (let i = 0; i < elementCount; ++i) {
const elementByteOffset = byteOffset + i * elementByteStride;
componentsReader(
dataView,
elementByteOffset,
componentsPerElement,
components
);
for (let j = 0; j < componentsPerElement; ++j) {
compactTypedArray[i * componentsPerElement + j] = components[j];
}
}
return compactTypedArray;
}
/**
* Dequantize the data from the given input array, based on the given
* quantization information, and return the result.
*
* This assumes that normalization has already been applied. This means that
* when the quantization.normalized flag is true,
* then the input is assumed to contain floating point values in the range
* [-1, 1].
*
* @param {TypedArray} quantizedTypedArray The quantized typed array
* @param {number} elementCount The number of elements
* @param {AttributeType} elementType The element type
* @param {ModelComponents.Quantization} quantization The quantization
* @returns {TypedArray} The result
* @throws DeveloperError When the element type is not SCALAR, VEC2,
* VEC3, or VEC4
*/
static dequantize(quantizedTypedArray, elementCount, elementType, quantization) {
Check_default.defined("quantizedTypedArray", quantizedTypedArray);
Check_default.typeOf.number.greaterThanOrEquals("elementCount", elementCount, 0);
Check_default.defined("elementType", elementType);
Check_default.defined("quantization", quantization);
if (quantization.octEncoded) {
const dequantizedTypedArray = _ModelReader.octDecode(
quantizedTypedArray,
elementCount,
quantization.normalizationRange,
void 0
);
if (quantization.octEncodedZXY) {
_ModelReader.convertZxyToXyz(
dequantizedTypedArray,
dequantizedTypedArray
);
}
return dequantizedTypedArray;
}
const stepSize = quantization.quantizedVolumeStepSize;
const offset = quantization.quantizedVolumeOffset;
if (elementType === AttributeType_default.SCALAR) {
return _ModelReader.dequantize1D(
quantizedTypedArray,
elementCount,
stepSize,
offset,
void 0
);
}
if (elementType === AttributeType_default.VEC2) {
return _ModelReader.dequantize2D(
quantizedTypedArray,
elementCount,
stepSize,
offset,
void 0
);
}
if (elementType === AttributeType_default.VEC3) {
return _ModelReader.dequantize3D(
quantizedTypedArray,
elementCount,
stepSize,
offset,
void 0
);
}
if (elementType === AttributeType_default.VEC4) {
return _ModelReader.dequantize4D(
quantizedTypedArray,
elementCount,
stepSize,
offset,
void 0
);
}
throw new DeveloperError_default(
`Element type for dequantization must be SCALAR, VEC2, VEC3, or VEC4, but is ${elementType}`
);
}
/**
* Decode oct-encoded normals from the given input, and write the
* result into the given output, allocating and returning a new
* array if the result was undefined.
*
* This will apply the AttributeCompression.octDecodeInRange
* function to each three components of the input.
*
* @param {TypedArray} quantizedTypedArray The input
* @param {number} elementCount The number of elements
* @param {number} normalizationRange The normalization range
* @param {TypedArray} [dequantizedTypedArray] The result
* @returns {TypedArray} The result
*/
static octDecode(quantizedTypedArray, elementCount, normalizationRange, dequantizedTypedArray) {
Check_default.defined("quantizedTypedArray", quantizedTypedArray);
Check_default.typeOf.number.greaterThanOrEquals("elementCount", elementCount, 0);
Check_default.typeOf.number.greaterThan(
"normalizationRange",
normalizationRange,
0
);
if (!defined_default(dequantizedTypedArray)) {
dequantizedTypedArray = new Float32Array(quantizedTypedArray.length);
}
const c = new Cartesian3_default();
for (let i = 0; i < elementCount; i++) {
Cartesian3_default.unpack(quantizedTypedArray, i * 3, c);
AttributeCompression_default.octDecodeInRange(c, normalizationRange, c);
Cartesian3_default.pack(dequantizedTypedArray, c, i * 3);
}
return dequantizedTypedArray;
}
/**
* Swizzle all three consecutive elements in the given input array
* from (z, x, y) to (x, y, z), and write the result into the
* given output array, creating a new array if the given output
* array was undefined.
*
* @param {TypedArray} input The input
* @param {number} elementCount The number of elements
* @param {TypedArray} [output] The result
* @returns {TypedArray} The result
*/
static convertZxyToXyz(input, elementCount, output) {
Check_default.defined("input", input);
Check_default.typeOf.number.greaterThanOrEquals("elementCount", elementCount, 0);
if (!defined_default(output)) {
output = new Float32Array(input.length);
}
let offset = 0;
for (let i = 0; i < elementCount; i++, offset += 3) {
const z = input[offset + 0];
const x = input[offset + 1];
const y = input[offset + 2];
output[offset + 0] = x;
output[offset + 1] = y;
output[offset + 2] = z;
}
return output;
}
/**
* Dequantize the given quantized array, based on the given quantization
* information, and write the result into the given output array, creating
* the output array if it was undefined.
*
* This will simply fill the output array with
* output[i] = input[i] * stepSize + offset
*
* @param {TypedArray} quantizedTypedArray The quantized array
* @param {number} elementCount The number of elements
* @param {number} stepSize The quantization step size
* @param {number} offset The quantization offset
* @param {TypedArray} [dequantizedTypedArray] The result
* @returns {TypedArray} The result
*/
static dequantize1D(quantizedTypedArray, elementCount, stepSize, offset, dequantizedTypedArray) {
Check_default.defined("quantizedTypedArray", quantizedTypedArray);
Check_default.typeOf.number.greaterThanOrEquals("elementCount", elementCount, 0);
Check_default.defined("stepSize", stepSize);
Check_default.defined("offset", offset);
if (!defined_default(dequantizedTypedArray)) {
dequantizedTypedArray = new Float32Array(quantizedTypedArray.length);
}
for (let i = 0; i < elementCount; i++) {
const q = quantizedTypedArray[i];
const d = q * stepSize + offset;
dequantizedTypedArray[i] = d;
}
return dequantizedTypedArray;
}
/**
* Dequantize the given quantized array, based on the given quantization
* information, and write the result into the given output array, creating
* the output array if it was undefined.
*
* This will simply fill the output array with
* output[i] = input[i] * stepSize + offset
* when interpreting the input and output as arrays of Cartesian2.
*
* @param {TypedArray} quantizedTypedArray The quantized array
* @param {number} elementCount The number of elements
* @param {Cartesian2} stepSize The quantization step size
* @param {Cartesian2} offset The quantization offset
* @param {TypedArray} [dequantizedTypedArray] The result
* @returns {TypedArray} The result
*/
static dequantize2D(quantizedTypedArray, elementCount, stepSize, offset, dequantizedTypedArray) {
Check_default.defined("quantizedTypedArray", quantizedTypedArray);
Check_default.typeOf.number.greaterThanOrEquals("elementCount", elementCount, 0);
Check_default.defined("stepSize", stepSize);
Check_default.defined("offset", offset);
if (!defined_default(dequantizedTypedArray)) {
dequantizedTypedArray = new Float32Array(quantizedTypedArray.length);
}
const c = new Cartesian2_default();
for (let i = 0; i < elementCount; i++) {
Cartesian2_default.unpack(quantizedTypedArray, i * 2, c);
Cartesian2_default.multiplyComponents(c, stepSize, c);
Cartesian2_default.add(c, offset, c);
Cartesian2_default.pack(c, dequantizedTypedArray, i * 2);
}
return dequantizedTypedArray;
}
/**
* Dequantize the given quantized array, based on the given quantization
* information, and write the result into the given output array, creating
* the output array if it was undefined.
*
* This will simply fill the output array with
* output[i] = input[i] * stepSize + offset
* when interpreting the input and output as arrays of Cartesian3.
*
* @param {TypedArray} quantizedTypedArray The quantized array
* @param {number} elementCount The number of elements
* @param {Cartesian3} stepSize The quantization step size
* @param {Cartesian3} offset The quantization offset
* @param {TypedArray} [dequantizedTypedArray] The result
* @returns {TypedArray} The result
*/
static dequantize3D(quantizedTypedArray, elementCount, stepSize, offset, dequantizedTypedArray) {
Check_default.defined("quantizedTypedArray", quantizedTypedArray);
Check_default.typeOf.number.greaterThanOrEquals("elementCount", elementCount, 0);
Check_default.defined("stepSize", stepSize);
Check_default.defined("offset", offset);
if (!defined_default(dequantizedTypedArray)) {
dequantizedTypedArray = new Float32Array(quantizedTypedArray.length);
}
const c = new Cartesian3_default();
for (let i = 0; i < elementCount; i++) {
Cartesian3_default.unpack(quantizedTypedArray, i * 3, c);
Cartesian3_default.multiplyComponents(c, stepSize, c);
Cartesian3_default.add(c, offset, c);
Cartesian3_default.pack(c, dequantizedTypedArray, i * 3);
}
return dequantizedTypedArray;
}
/**
* Dequantize the given quantized array, based on the given quantization
* information, and write the result into the given output array, creating
* the output array if it was undefined.
*
* This will simply fill the output array with
* output[i] = input[i] * stepSize + offset
* when interpreting the input and output as arrays of Cartesian4.
*
* @param {TypedArray} quantizedTypedArray The quantized array
* @param {number} elementCount The number of elements
* @param {Cartesian4} stepSize The quantization step size
* @param {Cartesian4} offset The quantization offset
* @param {TypedArray} [dequantizedTypedArray] The result
* @returns {TypedArray} The result
*/
static dequantize4D(quantizedTypedArray, elementCount, stepSize, offset, dequantizedTypedArray) {
Check_default.defined("quantizedTypedArray", quantizedTypedArray);
Check_default.typeOf.number.greaterThanOrEquals("elementCount", elementCount, 0);
Check_default.defined("stepSize", stepSize);
Check_default.defined("offset", offset);
if (!defined_default(dequantizedTypedArray)) {
dequantizedTypedArray = new Float32Array(quantizedTypedArray.length);
}
const c = new Cartesian4_default();
for (let i = 0; i < elementCount; i++) {
Cartesian4_default.unpack(quantizedTypedArray, i * 4, c);
Cartesian4_default.multiplyComponents(c, stepSize, c);
Cartesian4_default.add(c, offset, c);
Cartesian4_default.pack(c, dequantizedTypedArray, i * 4);
}
return dequantizedTypedArray;
}
/**
* Reads and returns a value with the given type
* at the given byte offset from the data view, in little-endian
* order
* @callback ComponentsReaderCallback
* @param {DataView} dataView Typed data view into a binary buffer
* @param {number} byteOffset The offset, in bytes, from the start of the view to read the data from
* @param {number} numberOfComponents The number of components to read
* @param {number[]} result The array in which to read the result
*/
/**
* Creates a function that reads the specified number of components with
* the given type from the given data view, in little-endian
* order, and writes them into a given result array.
*
* @param {ComponentDatatype} componentType The component type
* @returns {ComponentsReaderCallback} The reader
*/
static createComponentsReader(componentType) {
const componentReader = _ModelReader.createComponentReader(componentType);
const sizeInBytes = ComponentDatatype_default.getSizeInBytes(componentType);
return function(dataView, byteOffset, numberOfComponents, result) {
let offset = byteOffset;
for (let i = 0; i < numberOfComponents; ++i) {
result[i] = componentReader(dataView, offset);
offset += sizeInBytes;
}
};
}
/**
* Reads and returns a value with the given type
* at the given byte offset from the data view, in little-endian
* order
* @callback ComponentReaderCallback
* @param {DataView} dataView Typed data view into a binary buffer
* @param {number} byteOffset The offset, in bytes, from the start of the view to read the data from
* @returns {number|BigInt} The value read from the dataView
*/
/**
* Creates a function that reads and returns a value with the given type
* at the given byte offset from the data view, in little-endian
* order
* @param {ComponentDatatype} componentType The component type
* @returns {ComponentReaderCallback} The reader
*/
static createComponentReader(componentType) {
switch (componentType) {
case ComponentDatatype_default.BYTE:
return function(dataView, byteOffset) {
return dataView.getInt8(byteOffset);
};
case ComponentDatatype_default.UNSIGNED_BYTE:
return function(dataView, byteOffset) {
return dataView.getUint8(byteOffset);
};
case ComponentDatatype_default.SHORT:
return function(dataView, byteOffset) {
return dataView.getInt16(byteOffset, true);
};
case ComponentDatatype_default.UNSIGNED_SHORT:
return function(dataView, byteOffset) {
return dataView.getUint16(byteOffset, true);
};
case ComponentDatatype_default.INT:
return function(dataView, byteOffset) {
return dataView.getInt32(byteOffset, true);
};
case ComponentDatatype_default.UNSIGNED_INT:
return function(dataView, byteOffset) {
return dataView.getUint32(byteOffset, true);
};
case ComponentDatatype_default.FLOAT:
return function(dataView, byteOffset) {
return dataView.getFloat32(byteOffset, true);
};
case ComponentDatatype_default.DOUBLE:
return function(dataView, byteOffset) {
return dataView.getFloat64(byteOffset, true);
};
}
throw new DeveloperError_default(
`The componentType must be a valid ComponentDatatype, but is ${componentType}`
);
}
/**
* Transform the elements of the given array with the given 4x4 matrix,
* interpreting each 3 consecutive elements as a 3D point, and write
* the result into the given result array, creating the result array
* if it was undefined.
*
* @param {TypedArray} input The input array
* @param {Matrix4} matrix The matrix
* @param {TypedArray} [result] The result
* @returns {TypedArray} The result
*/
static transform3D(input, matrix, result) {
Check_default.defined("input", input);
Check_default.defined("matrix", matrix);
if (!defined_default(result)) {
result = new Float32Array(input.length);
}
const c = new Cartesian3_default();
const elementCount = input.length / 3;
for (let i = 0; i < elementCount; i++) {
Cartesian3_default.unpack(input, i * 3, c);
Matrix4_default.multiplyByPoint(matrix, c, c);
Cartesian3_default.pack(c, result, i * 3);
}
return result;
}
/**
* Read the indices values from the given primitive indices, and
* return them as a typed array.
*
* If the given object already has a typedArray/code> property, then it
* is assumed that this contains the proper indices, and they are returned.
*
* Otherwise, this reads the data from the buffer of the given
* primitive indices object, into a typed array with a type that matches the
* indexDataType, and returns it.
*
* Clients may not modify the returned typed array.
*
* @param {ModelComponents.Indices} primitiveIndices The primitive indices
* @returns {TypedArray} The indices values
* @throws {DeveloperError} If the indexDataType of the given
* object is neither UNSIGNED_BYTE, nor UNSIGNED_SHORT,
* nor UNSIGNED_INT
*/
static readIndicesAsTypedArray(primitiveIndices) {
const existingIndices = primitiveIndices.typedArray;
if (defined_default(existingIndices)) {
return existingIndices;
}
const indicesBuffer = primitiveIndices.buffer;
const indicesCount = primitiveIndices.count;
const indexDatatype = primitiveIndices.indexDatatype;
const indices = _ModelReader.createIndexTypedArray(
indexDatatype,
indicesCount
);
indicesBuffer.getBufferData(indices);
return indices;
}
/**
* Read the indices values from the given primitive indices object, and return
* them as a typed array of triangle vertex indices.
*
* If the given primitive type is TRIANGLES, then the indices
* values will be read from the given object, and returned.
*
* If the primitive type is TRIANGLE_STRIP or TRIANGLE_FAN,
* then the original indices values, will be read, converted into triangle indices
* (i.e. their equivalent TRIANGLES representation), and the result
* will be returned.
*
* The type of the returned array will match the indexDataType
* of the given object.
*
* Clients may not modify the returned typed array.
*
* @param {ModelComponents.Indices} primitiveIndices The primitive indices
* @returns {TypedArray} The indices, converted to triangle indices if necessary
* @throws {DeveloperError} If the indexDataType of the given
* object is neither UNSIGNED_BYTE, nor UNSIGNED_SHORT,
* nor UNSIGNED_INT, or the given primitiveType
* is neither TRIANGLES, nor TRIANGLE_STRIP,
* nor TRIANGLE_FAN
*/
static readIndicesAsTriangleIndicesTypedArray(primitiveIndices, primitiveType) {
const originalIndices = _ModelReader.readIndicesAsTypedArray(primitiveIndices);
if (primitiveType === PrimitiveType_default.TRIANGLES) {
return originalIndices;
}
if (primitiveType === PrimitiveType_default.TRIANGLE_STRIP) {
const triangleIndices = _ModelReader.convertTriangleStripToTriangleIndices(originalIndices);
return triangleIndices;
}
if (primitiveType === PrimitiveType_default.TRIANGLE_FAN) {
const triangleIndices = _ModelReader.convertTriangleFanToTriangleIndices(originalIndices);
return triangleIndices;
}
throw new DeveloperError_default(
`The primitiveType must be TRIANGLES (${PrimitiveType_default.TRIANGLES}, TRIANGLE_STRIP (${PrimitiveType_default.TRIANGLE_STRIP}, or TRIANGLE_FAN (${PrimitiveType_default.TRIANGLE_FAN}, but is ${primitiveType}`
);
}
/**
* Converts the given indices from a TRIANGLE_STRIP representation
* into a TRIANGLES representation, and returns the result.
*
* The type of the result will be the same as the type of the input array.
*
* @param {TypedArray} indices The input indices
* @returns {TypedArray} The resulting triangle indices
*/
static convertTriangleStripToTriangleIndices(indices) {
const triangleIndices = indices.constructor((indices.length - 2) * 3);
for (let i = 0; i < indices.length - 2; i++) {
if (i % 2 === 1) {
triangleIndices[i * 3 + 0] = indices[i + 0];
triangleIndices[i * 3 + 1] = indices[i + 2];
triangleIndices[i * 3 + 2] = indices[i + 1];
} else {
triangleIndices[i * 3 + 0] = indices[i + 0];
triangleIndices[i * 3 + 1] = indices[i + 1];
triangleIndices[i * 3 + 2] = indices[i + 2];
}
}
return triangleIndices;
}
/**
* Converts the given indices from a TRIANGLE_FAN representation
* into a TRIANGLES representation, and returns the result.
*
* The type of the result will be the same as the type of the input array.
*
* @param {TypedArray} indices The input indices
* @returns {TypedArray} The resulting triangle indices
*/
static convertTriangleFanToTriangleIndices(indices) {
const triangleIndices = indices.constructor((indices.length - 2) * 3);
for (let i = 0; i < indices.length - 2; i++) {
triangleIndices[i * 3 + 0] = indices[i + 0];
triangleIndices[i * 3 + 1] = indices[i + 1];
triangleIndices[i * 3 + 2] = indices[i + 2];
}
return triangleIndices;
}
/**
* Create a typed array with a type that matches the given index data type,
* and the given size.
*
* @param {number} indexDatatype The IndexDataType
* @param {number} size The size of the array that will be created
* @returns {TypedArray} The typed array
* @throws {DeveloperError} If the indexDataType is neither
* UNSIGNED_BYTE, nor UNSIGNED_SHORT,
* nor UNSIGNED_INT, or the size is negative.
*/
static createIndexTypedArray(indexDatatype, size) {
Check_default.typeOf.number.greaterThanOrEquals("size", size, 0);
switch (indexDatatype) {
case IndexDatatype_default.UNSIGNED_BYTE:
return new Uint8Array(size);
case IndexDatatype_default.UNSIGNED_SHORT:
return new Uint16Array(size);
case IndexDatatype_default.UNSIGNED_INT:
return new Uint32Array(size);
}
throw new DeveloperError_default(
`The indexDatatype must be UNSIGNED_BYTE (${IndexDatatype_default.UNSIGNED_BYTE}, UNSIGNED_SHORT (${IndexDatatype_default.UNSIGNED_SHORT}, or UNSIGNED_INT (${IndexDatatype_default.UNSIGNED_INT}, but is ${indexDatatype}`
);
}
};
var ModelReader_default = ModelReader;
// packages/engine/Source/Scene/Model/ModelImageryMapping.js
var ModelImageryMapping = class _ModelImageryMapping {
/**
* Creates a typed array that contains texture coordinates for
* the given MappedPositions, using the given
* projection.
*
* This will be a typed array that contains the texture coordinates
* that result from projecting the given positions with the given
* projection, and normalizing them to their bounding rectangle.
*
* @param {MappedPositions} mappedPositions The positions
* @param {MapProjection} projection The projection that should be used
* @returns {TypedArray} The result
*/
static createTextureCoordinatesForMappedPositions(mappedPositions, projection) {
Check_default.defined("mappedPositions", mappedPositions);
Check_default.defined("projection", projection);
const cartographicPositions = mappedPositions.cartographicPositions;
const cartographicBoundingRectangle = mappedPositions.cartographicBoundingRectangle;
const numPositions = mappedPositions.numPositions;
return _ModelImageryMapping._createTextureCoordinates(
cartographicPositions,
numPositions,
cartographicBoundingRectangle,
projection
);
}
/**
* Creates a typed array that contains texture coordinates for
* a primitive with the given positions, using the given
* projection.
*
* This will be a typed array of size numPositions*2
* that contains the texture coordinates that result from
* projecting the given positions with the given projection,
* and normalizing them to the given bounding rectangle.
*
* @param {Iterable} cartographicPositions The
* cartographic positions
* @param {number} numPositions The number of positions (vertices)
* @param {Rectangle} cartographicBoundingRectangle The bounding
* rectangle of the cartographic positions
* @param {MapProjection} projection The projection that should be used
* @returns {TypedArray} The result
* @private
*/
static _createTextureCoordinates(cartographicPositions, numPositions, cartographicBoundingRectangle, projection) {
Check_default.defined("cartographicPositions", cartographicPositions);
Check_default.typeOf.number.greaterThanOrEquals("numPositions", numPositions, 0);
Check_default.defined(
"cartographicBoundingRectangle",
cartographicBoundingRectangle
);
Check_default.defined("projection", projection);
const boundingRectangle = new BoundingRectangle_default();
BoundingRectangle_default.fromRectangle(
cartographicBoundingRectangle,
projection,
boundingRectangle
);
const projectedPositions = _ModelImageryMapping.createProjectedPositions(
cartographicPositions,
projection
);
const texCoords = _ModelImageryMapping.computeTexCoords(
projectedPositions,
boundingRectangle
);
const texCoordsTypedArray = _ModelImageryMapping.createTypedArrayFromCartesians2(
numPositions,
texCoords
);
return texCoordsTypedArray;
}
/**
* Creates the `ModelComponents.Attribute` for the texture coordinates
* for a primitive
*
* This will create an attribute with
* - semantic: VertexAttributeSemantic.TEXCOORD
* - type: AttributeType.VEC2
* - count: mappedPositions.numPositions
* that contains the texture coordinates for the given vertex positions,
* after they are projected using the given projection, normalized to
* their bounding rectangle.
*
* @param {Iterable} cartographicPositions The
* cartographic positions
* @param {number} numPositions The number of positions (vertices)
* @param {Rectangle} cartographicBoundingRectangle The bounding
* rectangle of the cartographic positions
* @param {MapProjection} projection The projection that should be used
* @returns {ModelComponents.Attribute} The new attribute
*/
static createTextureCoordinatesAttributeForMappedPositions(mappedPositions, projection) {
Check_default.defined("mappedPositions", mappedPositions);
Check_default.defined("projection", projection);
const texCoordsTypedArray = _ModelImageryMapping.createTextureCoordinatesForMappedPositions(
mappedPositions,
projection
);
const texCoordAttribute = _ModelImageryMapping.createTexCoordAttribute(texCoordsTypedArray);
return texCoordAttribute;
}
/**
* Create an iterable that provides the cartographic positions
* of the given POSITION attribute, based on the given ellipsoid
*
* @param {ModelComponents.Attribute} primitivePositionAttribute
* The "POSITION" attribute of the primitive.
* @param {Matrix4} primitivePositionTransform The full transform of the primitive
* @param {Elliposid} ellipsoid The ellipsoid that should be used
* @returns {Iterable} The iterable over `Cartographic` objects
*/
static createCartographicPositions(primitivePositionAttribute, primitivePositionTransform, ellipsoid) {
Check_default.defined("primitivePositionAttribute", primitivePositionAttribute);
Check_default.defined("primitivePositionTransform", primitivePositionTransform);
Check_default.defined("ellipsoid", ellipsoid);
const typedArray = ModelReader_default.readAttributeAsTypedArray(
primitivePositionAttribute
);
const type = primitivePositionAttribute.type;
const numComponents = AttributeType_default.getNumberOfComponents(type);
const positions = _ModelImageryMapping.createIterableCartesian3FromTypedArray(
typedArray,
numComponents
);
const transformedPositions = _ModelImageryMapping.transformCartesians3(
positions,
primitivePositionTransform
);
const cartographicPositions = _ModelImageryMapping.transformToCartographic(
transformedPositions,
ellipsoid
);
return cartographicPositions;
}
/**
* Creates an iterable over `Cartesian3` objects from the given
* typed array.
*
* The resulting iterable will always return the same `Cartesian3`
* object. Clients should not store and modify this object.
*
* @param {TypedArray} typedArray The typed array
* @param {number} stride The stride between to consecutive
* `Cartesian3` elements in the given array. Must be at least 3.
* @returns {Iterable} The iterable
*/
static createIterableCartesian3FromTypedArray(typedArray, stride) {
Check_default.defined("typedArray", typedArray);
Check_default.typeOf.number.greaterThanOrEquals("stride", stride, 3);
const cartesian11 = new Cartesian3_default();
const numElements = typedArray.length / stride;
const result = {
[Symbol.iterator]: function* () {
for (let i = 0; i < numElements; i++) {
cartesian11.x = typedArray[i * stride + 0];
cartesian11.y = typedArray[i * stride + 1];
cartesian11.z = typedArray[i * stride + 2];
yield cartesian11;
}
}
};
return result;
}
/**
* Creates a new iterable that applies the given mapper to the given iterable.
*
* @param {Iterable} iterable The input iterable
* @param {Function} mapper The mapper
* @returns {Iterable} The mapped iterable
*/
static map(iterable, mapper) {
Check_default.defined("iterable", iterable);
Check_default.defined("mapper", mapper);
const result = {
[Symbol.iterator]: function* () {
for (const element of iterable) {
yield mapper(element);
}
}
};
return result;
}
/**
* Computes the bounding rectangle of the given cartographic positions,
* stores it in the given result, and returns it.
*
* If the given result is `undefined`, a new rectangle will be created
* and returned.
*
* @param {Iterable} cartographicPositions The cartographics
* @param {Rectangle} [result] The result
* @returns {Rectangle} The result
*/
static computeCartographicBoundingRectangle(cartographicPositions, result) {
Check_default.defined("cartographicPositions", cartographicPositions);
if (!defined_default(result)) {
result = new Rectangle_default();
}
let north = Number.NEGATIVE_INFINITY;
let south = Number.POSITIVE_INFINITY;
let east = Number.NEGATIVE_INFINITY;
let west = Number.POSITIVE_INFINITY;
for (const cartographicPosition of cartographicPositions) {
north = Math.max(north, cartographicPosition.latitude);
south = Math.min(south, cartographicPosition.latitude);
east = Math.max(east, cartographicPosition.longitude);
west = Math.min(west, cartographicPosition.longitude);
}
result.north = north;
result.south = south;
result.east = east;
result.west = west;
return result;
}
/**
* Creates a new iterable that provides `Cartesian3` objects that
* are created by transforming the `Cartesian3` objects of the
* given iterable with the given matrix.
*
* The resulting iterable will always return the same `Cartesian3`
* object. Clients should not store and modify this object.
*
* @param {Iterable} positions The positions
* @param {Matrix4} matrix The matrix
* @returns {Iterable} The transformed cartesians
*/
static transformCartesians3(positions, matrix) {
Check_default.defined("positions", positions);
Check_default.defined("matrix", matrix);
const transformedPosition = new Cartesian3_default();
const transformedPositions = _ModelImageryMapping.map(positions, (p) => {
Matrix4_default.multiplyByPoint(matrix, p, transformedPosition);
return transformedPosition;
});
return transformedPositions;
}
/**
* Creates a new iterable that provides `Cartographic` objects that
* are created by converting the given `Cartesian3` objects to
* cartographics, based on the given ellipsoid.
*
* The resulting iterable will always return the same `Cartographic`
* object. Clients should not store and modify this object.
*
* @param {Iterable} positions The positions
* @param {Ellipsoid} ellipsoid The ellipsoid
* @returns {Iterable} The cartographic positions
*/
static transformToCartographic(positions, ellipsoid) {
Check_default.defined("positions", positions);
Check_default.defined("ellipsoid", ellipsoid);
const cartographicPosition = new Cartographic_default();
const cartographicPositions = _ModelImageryMapping.map(positions, (p) => {
ellipsoid.cartesianToCartographic(p, cartographicPosition);
return cartographicPosition;
});
return cartographicPositions;
}
/**
* Creates an iterable over the results of applying the given projection
* to the given cartographic positions.
*
* The resulting iterable will always return the same `Cartesian3`
* object. Clients should not store and modify this object.
*
* @param {Iterable} cartographicPositions The cartographic
* positions
* @param {MapProjection} projection The projection to use
* @returns {Iterable} The projected positions
*/
static createProjectedPositions(cartographicPositions, projection) {
Check_default.defined("cartographicPositions", cartographicPositions);
Check_default.defined("projection", projection);
const projectedPosition2 = new Cartesian3_default();
const projectedPositions = _ModelImageryMapping.map(
cartographicPositions,
(c) => {
projection.project(c, projectedPosition2);
return projectedPosition2;
}
);
return projectedPositions;
}
/**
* Computes the texture coordinates for the given positions, relative
* to the given bounding rectangle.
*
* This will make the x/y coordinates of the given cartesians relative
* to the given bounding rectangle and clamp them to [0,0]-[1,1].
*
* NOTE: This could be broken down into
* 1. mapping to 2D
* 2. relativizing for the bounding recangle
* 3. clamping to [0,0]-[1,1]
*
* @param {Iterable} positions The positions
* @param {BoundingRectangle} boundingRectangle The rectangle
* @returns {Iterable} The texture coordinates
*/
static computeTexCoords(positions, boundingRectangle) {
Check_default.defined("positions", positions);
Check_default.defined("boundingRectangle", boundingRectangle);
const texCoord = new Cartesian2_default();
const invSizeX = 1 / boundingRectangle.width;
const invSizeY = 1 / boundingRectangle.height;
const texCoords = _ModelImageryMapping.map(positions, (p) => {
const uRaw = (p.x - boundingRectangle.x) * invSizeX;
const vRaw = (p.y - boundingRectangle.y) * invSizeY;
const u3 = Math.min(Math.max(uRaw, 0), 1);
const v3 = Math.min(Math.max(vRaw, 0), 1);
texCoord.x = u3;
texCoord.y = v3;
return texCoord;
});
return texCoords;
}
/**
* Creates a new typed array from the given `Cartesian2` objects.
*
* @param {number} numElements The number of elements
* @param {Iterable} elements The elements
* @returns {TypedArray} The typed array
*/
static createTypedArrayFromCartesians2(numElements, elements) {
Check_default.typeOf.number.greaterThanOrEquals("numElements", numElements, 0);
Check_default.defined("elements", elements);
const typedArray = new Float32Array(numElements * 2);
let index = 0;
for (const element of elements) {
typedArray[index * 2 + 0] = element.x;
typedArray[index * 2 + 1] = element.y;
index++;
}
return typedArray;
}
/**
* Create a new texture coordinates attribute from the given data.
*
* This will create an attribute with
* - semantic: VertexAttributeSemantic.TEXCOORD
* - type: AttributeType.VEC2
* - count: texCoordsTypedArray.length / 2
* that contains the data from the given typed array.
*
* @param {TypedArray} texCoordsTypedArray The typed array
* @returns {ModelComponents.Attribute} The attribute
*/
static createTexCoordAttribute(texCoordsTypedArray) {
Check_default.defined("texCoordsTypedArray", texCoordsTypedArray);
const texCoordAttribute = {
name: "Imagery Texture Coordinates",
semantic: VertexAttributeSemantic_default.TEXCOORD,
setIndex: 0,
componentDatatype: ComponentDatatype_default.FLOAT,
type: AttributeType_default.VEC2,
normalized: false,
count: texCoordsTypedArray.length / 2,
min: void 0,
max: void 0,
constant: new Cartesian2_default(0, 0),
quantization: void 0,
typedArray: texCoordsTypedArray,
byteOffset: 0,
byteStride: void 0
};
return texCoordAttribute;
}
};
var ModelImageryMapping_default = ModelImageryMapping;
// packages/engine/Source/Scene/Model/MappedPositions.js
var import_InlineWorkers685 = __toESM(require_InlineWorkers(), 1);
var MappedPositions = class {
/**
* Creates a new instance
*
* @param {Iterable} cartographicPositions The positions
* @param {number} numPositions The number of positions
* @param {Rectangle} cartographicBoundingRectangle The bounding
* rectangle of the positions
* @param {Ellipsoid} ellipsoid The ellipsoid
*/
constructor(cartographicPositions, numPositions, cartographicBoundingRectangle, ellipsoid) {
Check_default.defined("cartographicPositions", cartographicPositions);
Check_default.typeOf.number.greaterThanOrEquals("numPositions", numPositions, 0);
Check_default.defined(
"cartographicBoundingRectangle",
cartographicBoundingRectangle
);
Check_default.defined("ellipsoid", ellipsoid);
this._cartographicPositions = cartographicPositions;
this._numPositions = numPositions;
this._cartographicBoundingRectangle = cartographicBoundingRectangle;
this._ellipsoid = ellipsoid;
}
/**
* Returns the cartographic positions
*
* @returns {Iterable} The positions
*/
get cartographicPositions() {
return this._cartographicPositions;
}
/**
* Returns the number of positions
*
* @returns {number} The number of positions
*/
get numPositions() {
return this._numPositions;
}
/**
* Returns the cartographic bounding rectangle
*
* @returns {Rectangle} The rectangle
*/
get cartographicBoundingRectangle() {
return this._cartographicBoundingRectangle;
}
/**
* Returns the ellipsoid for which these positions have been created
*
* @returns {Ellipsoid} The ellipsoid
*/
get ellipsoid() {
return this._ellipsoid;
}
};
var MappedPositions_default = MappedPositions;
// packages/engine/Source/Scene/Model/ModelPrimitiveImagery.js
var ModelPrimitiveImagery = class _ModelPrimitiveImagery {
/**
* Creates a new instance
*
* @param {Model} model The model
* @param {ModelRuntimeNode} runtimeNode The node that the primitive is attached to
* @param {ModelRuntimePrimitive} runtimePrimitive The primitive
* @throws {DeveloperError} If any argument is not defined
*/
constructor(model, runtimeNode, runtimePrimitive) {
Check_default.defined("model", model);
Check_default.defined("runtimeNode", runtimeNode);
Check_default.defined("runtimePrimitive", runtimePrimitive);
this._model = model;
this._runtimeNode = runtimeNode;
this._runtimePrimitive = runtimePrimitive;
this._mappedPositionsPerEllipsoid = void 0;
this._mappedPositionsModelMatrix = new Matrix4_default();
this._lastImageryLayersModificationCounter = 0;
this._imageryTexCoordAttributesPerProjection = void 0;
this._currentImageryLayers = void 0;
this._coveragesPerLayer = void 0;
this._allImageriesReady = false;
}
/**
* Returns the ImageryCoverage array that has been
* computed for the given imagery layer.
*
* This assumes that the given imagery layer is part of the
* imagery layer collection of the model, and that this
* model primitive imagery is "ready", meaning that the
* coverages have already been computed.
*
* Clients may not modify the returned array or any
* of its objects!
*
* @param {ImageryLayer} imageryLayer The imagery layer
* @returns {ImageryCoverage[]} The coverage information
*/
coveragesForImageryLayer(imageryLayer) {
const model = this._model;
const imageryLayers = model.imageryLayers;
const index = imageryLayers.indexOf(imageryLayer);
if (index === -1) {
throw new DeveloperError_default("Imagery layer is not part of the model");
}
const coveragesPerLayer = this._coveragesPerLayer;
if (!defined_default(coveragesPerLayer)) {
throw new DeveloperError_default(
`The coveragesPerLayer have not been computed yet`
);
}
return coveragesPerLayer[index];
}
/**
* Update the state of this instance.
*
* This is called as part of ModelImagery.update, which in
* turn is part of the Model.update that is called in each
* frame.
*
* This will perform the computations that are required to establish
* the mapping between the imagery and the primitive. It will...
*
* -
* Compute the
MappedPositions of the primitive,
* one instance for each ellipsoid
*
* -
* Compute the "coverages per layer", containing the information
* about which parts of the respective imagery layer are covered
* by the mapped positions
*
* -
* Compute the texture coordinate attributes for the imagery, one
* for each projection, and store them as the
*
_imageryTexCoordAttributesPerProjection
*
* -
* Update the imageries (i.e. processing their state machine by
* calling
Imagery.processStateMachine) until they
* are in the ImageryState.READY state
*
*
*
* @param {FrameState} frameState The frame state
*/
update(frameState) {
Check_default.defined("frameState", frameState);
const model = this._model;
const content = model.content;
const tileset = content.tileset;
const modificationCounter = tileset.imageryLayersModificationCounter;
if (this._lastImageryLayersModificationCounter !== modificationCounter) {
delete this._mappedPositionsPerEllipsoid;
this._lastImageryLayersModificationCounter = modificationCounter;
}
if (this._mappedPositionsNeedUpdate) {
model.resetDrawCommands();
this._mappedPositionsPerEllipsoid = this._computeMappedPositionsPerEllipsoid();
this._deleteCoveragesPerLayer();
this._destroyImageryTexCoordAttributes();
}
if (!defined_default(this._imageryTexCoordAttributesPerProjection)) {
this._imageryTexCoordAttributesPerProjection = this._computeImageryTexCoordsAttributesPerProjection();
this._uploadImageryTexCoordAttributes(frameState.context);
}
if (!defined_default(this._coveragesPerLayer)) {
this._computeCoveragesPerLayer();
this._allImageriesReady = false;
}
if (!this._allImageriesReady) {
this._updateImageries(frameState);
}
}
/**
* Delete the _coveragesPerLayer if they are defined.
*
* This will call deleteCoverages for each set of coverages,
* and eventually delete the _coveragesPerLayer.
*
* This will cause the reference counters of the imageries to be
* decreased.
*/
_deleteCoveragesPerLayer() {
const coveragesPerLayer = this._coveragesPerLayer;
if (!defined_default(coveragesPerLayer)) {
return;
}
const imageryLayers = this._currentImageryLayers;
const length2 = coveragesPerLayer.length;
for (let i = 0; i < length2; i++) {
const imageryLayer = imageryLayers[i];
const coverages = coveragesPerLayer[i];
this._deleteCoverages(imageryLayer, coverages);
}
delete this._currentImageryLayers;
delete this._coveragesPerLayer;
}
/**
* Delete the given imagery coverage objects for the given imagery
* layer, meaning that it will cause the reference counters of the
* imageries to be decreased.
*
* If the imagery layer already has been destroyed, then nothing
* will be done.
*
* @param {ImageryLayer} imageryLayer The imagery layer
* @param {ImageryCoverage[]} coverages The coverages
*/
_deleteCoverages(imageryLayer, coverages) {
if (imageryLayer.isDestroyed()) {
return;
}
const length2 = coverages.length;
for (let i = 0; i < length2; i++) {
const coverage = coverages[i];
const imagery = coverage.imagery;
imagery.releaseReference();
}
}
/**
* Create the GPU buffers for the typed arrays that are contained
* in the _imageryTexCoordAttributesPerProjection
*
* @param {Context} context The GL context
*/
_uploadImageryTexCoordAttributes(context) {
Check_default.defined("context", context);
const attributes = this._imageryTexCoordAttributesPerProjection;
if (!defined_default(attributes)) {
return;
}
const n = attributes.length;
for (let i = 0; i < n; i++) {
const attribute = attributes[i];
const imageryTexCoordBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: attribute.typedArray,
usage: BufferUsage_default.STATIC_DRAW
});
imageryTexCoordBuffer.vertexArrayDestroyable = false;
attribute.buffer = imageryTexCoordBuffer;
}
}
/**
* Destroy the _imageryTexCoordAttributesPerProjection
* array.
*
* This is called for cleaning up the allocated GPU resources, before
* they are supposed to be re-computed with
* _computeImageryTexCoordsAttributesPerProjection
*/
_destroyImageryTexCoordAttributes() {
const attributes = this._imageryTexCoordAttributesPerProjection;
if (!defined_default(attributes)) {
return;
}
const n = attributes.length;
for (let i = 0; i < n; i++) {
const attribute = attributes[i];
if (defined_default(attribute)) {
if (defined_default(attribute.buffer)) {
if (!attribute.buffer.isDestroyed()) {
attribute.buffer.destroy();
}
}
attributes[i] = void 0;
}
}
delete this._imageryTexCoordAttributesPerProjection;
}
/**
* Returns whether the MappedPositions have to be
* re-computed with _computeMappedPositionsPerEllipsoid.
*
* This is true when the positions have not yet been
* computed, or when the modelMatrix of the model
* changed since the previous call.
*
* @returns {boolean} Whether the mapped positions need an update
* @private
*/
get _mappedPositionsNeedUpdate() {
if (!defined_default(this._mappedPositionsPerEllipsoid)) {
return true;
}
const model = this._model;
const lastModelMatrix = this._mappedPositionsModelMatrix;
if (!Matrix4_default.equals(model.modelMatrix, lastModelMatrix)) {
return true;
}
return false;
}
/**
* Computes the mapped positions of the primitive, one for each ellipsoid.
*
* This computes the unique ellipsoids that appear in the imagery
* layers of the model, and creates one MappedPositions
* object for each of them.
*
* The respective MappedPositions objects will contain
* the cartographic positions that are computed from the positions
* of the primitive. These will serve as the basis for computing the
* part of the imagery that is covered by the primitive.
*
* These mapped positions depend on the current modelMatrix
* of the model. So they have to be re-computed when the model matrix
* changes.
*
* @returns {MappedPositions[]} The mapped positions
* @private
*/
_computeMappedPositionsPerEllipsoid() {
const model = this._model;
const runtimeNode = this._runtimeNode;
const runtimePrimitive = this._runtimePrimitive;
const primitivePositionAttribute = _ModelPrimitiveImagery._obtainPrimitivePositionAttribute(
runtimePrimitive.primitive
);
const numPositions = primitivePositionAttribute.count;
const primitivePositionTransform = _ModelPrimitiveImagery._computePrimitivePositionTransform(
model,
runtimeNode,
void 0
);
const mappedPositionsPerEllipsoid = [];
const ellipsoids = _ModelPrimitiveImagery._computeUniqueEllipsoids(
model.imageryLayers
);
const length2 = ellipsoids.length;
for (let i = 0; i < length2; i++) {
const ellipsoid = ellipsoids[i];
const cartographicPositions = ModelImageryMapping_default.createCartographicPositions(
primitivePositionAttribute,
primitivePositionTransform,
ellipsoid
);
const cartographicBoundingRectangle = ModelImageryMapping_default.computeCartographicBoundingRectangle(
cartographicPositions
);
const mappedPositions = new MappedPositions_default(
cartographicPositions,
numPositions,
cartographicBoundingRectangle,
ellipsoid
);
mappedPositionsPerEllipsoid.push(mappedPositions);
}
Matrix4_default.clone(model.modelMatrix, this._mappedPositionsModelMatrix);
return mappedPositionsPerEllipsoid;
}
/**
* Computes an array containing the unique ellipsoids that
* appear in the imagery layers of the given collection.
*
* @param {ImageryLayerCollection} imageryLayers
* @returns {Ellipsoid[]} The ellipsoids
* @private
*/
static _computeUniqueEllipsoids(imageryLayers) {
Check_default.defined("imageryLayers", imageryLayers);
const ellipsoidsSet = /* @__PURE__ */ new Set();
const length2 = imageryLayers.length;
for (let i = 0; i < length2; i++) {
const imageryLayer = imageryLayers.get(i);
const ellipsoid = _ModelPrimitiveImagery._getEllipsoid(imageryLayer);
ellipsoidsSet.add(ellipsoid);
}
return [...ellipsoidsSet];
}
/**
* Computes one coordinate attribute for each unique projection
* that is used in the imagery layers.
*
* This is taking the mapped positions, projecting them with
* the respective projection, and creating a texture coordinate
* attribute that describes the texture coordinates of these
* positions, relative to the cartographic bounding rectangle
* of the mapped positions.
*
* @returns {ModelComponents.Attribute[]} The attributes
*/
_computeImageryTexCoordsAttributesPerProjection() {
const model = this._model;
const imageryLayers = model.imageryLayers;
const allProjections = _ModelPrimitiveImagery._extractProjections(imageryLayers);
const uniqueProjections = [...new Set(allProjections)];
const attributes = this._createImageryTexCoordAttributes(uniqueProjections);
return attributes;
}
/**
* Computes an array containing the projections that are used in
* the given imagery layers.
*
* (Note that this array may contain duplicates)
*
* @param {ImageryLayerCollection} imageryLayers The imagery layers
* @returns {MapProjection[]} The projections
* @private
*/
static _extractProjections(imageryLayers) {
Check_default.defined("imageryLayers", imageryLayers);
const projections = [];
const length2 = imageryLayers.length;
for (let i = 0; i < length2; i++) {
const imageryLayer = imageryLayers.get(i);
const projection = _ModelPrimitiveImagery._getProjection(imageryLayer);
projections.push(projection);
}
return projections;
}
/**
* Returns the projection of the given imagery layer.
*
* This only exists to hide a train wreck
*
* @param {ImageryLayer} imageryLayer The imagery layer
* @returns {MapProjection} The projection
* @private
*/
static _getProjection(imageryLayer) {
Check_default.defined("imageryLayer", imageryLayer);
const projection = imageryLayer.imageryProvider.tilingScheme.projection;
return projection;
}
/**
* Create texture coordinates, one for each projection.
*
* This will create a texture coordinate attribute for each of the given projections,
* using ModelImageryMapping.createTextureCoordinatesAttributeForMappedPositions,
*
* (This means that the given projections should indeed be unique,
* i.e. contain no duplicates)
*
* @param {MapProjection[]} uniqueProjections The projections
* @returns {ModelComponents.Attribute[]} The attributes
*/
_createImageryTexCoordAttributes(uniqueProjections) {
Check_default.defined("uniqueProjections", uniqueProjections);
const imageryTexCoordAttributePerUniqueProjection = [];
const length2 = uniqueProjections.length;
for (let i = 0; i < length2; i++) {
const projection = uniqueProjections[i];
const ellipsoid = projection.ellipsoid;
const mappedPositions = this.mappedPositionsForEllipsoid(ellipsoid);
const imageryTexCoordAttribute = ModelImageryMapping_default.createTextureCoordinatesAttributeForMappedPositions(
mappedPositions,
projection
);
imageryTexCoordAttributePerUniqueProjection.push(
imageryTexCoordAttribute
);
}
return imageryTexCoordAttributePerUniqueProjection;
}
/**
* Compute the coverage information for the primitive, based on the
* imagery layers that are associated with the model.
*
* This updates the _coveragesPerLayer[layerIndex], which
* is an array that contains the ImageryCoverage objects that
* describe the imagery tiles that are covered by the primitive, including
* their texture coordinate rectangle.
*
* This has to be called after the mapped positions for the primitive
* have been computed with _computeMappedPositionsPerEllipsoid.
*
* @private
*/
_computeCoveragesPerLayer() {
const coveragesPerLayer = [];
const currentImageryLayers = [];
const model = this._model;
const imageryLayers = model.imageryLayers;
const length2 = imageryLayers.length;
for (let i = 0; i < length2; i++) {
const imageryLayer = imageryLayers.get(i);
const coverages = this._computeCoverage(imageryLayer);
coveragesPerLayer.push(coverages);
currentImageryLayers.push(imageryLayer);
}
this._coveragesPerLayer = coveragesPerLayer;
this._currentImageryLayers = currentImageryLayers;
}
/**
* Compute the coverage information for the primitive, based on the
* given imagery layer.
*
* This returns an array that contains the ImageryCoverage
* objects that describe the imagery tiles that are covered by the
* primitive, including their texture coordinate rectangle.
*
* This has to be called after the mapped positions for the primitive
* have been computed with _computeMappedPositionsPerEllipsoid.
*
* @param {ImageryLayer} imageryLayer The imagery layer
* @returns {ImageryCoverage[]} The coverage information
* @private
*/
_computeCoverage(imageryLayer) {
const mappedPositions = this.mappedPositionsForImageryLayer(imageryLayer);
const cartographicBoundingRectangle = mappedPositions.cartographicBoundingRectangle;
const imageryLevel = this._computeImageryLevel(
imageryLayer,
cartographicBoundingRectangle
);
const coverages = ImageryCoverage_default.createImageryCoverages(
cartographicBoundingRectangle,
imageryLayer,
imageryLevel
);
return coverages;
}
/**
* Compute a level for accessing the imagery from the given
* imagery layer that is suitable for a primitive with the given bounding
* rectangle.
*
* @param {ImageryLayer} imageryLayer The imagery layer
* @param {Rectangle} cartographicBoundingRectangle The cartographic
* bounding rectangle, as obtained from the MappedPositions for
* the given imagery layer
* @returns {number} The imagery level
*/
_computeImageryLevel(imageryLayer, cartographicBoundingRectangle) {
const imageryProvider = imageryLayer.imageryProvider;
const tilingScheme2 = imageryProvider.tilingScheme;
const rectangle = tilingScheme2.rectangle;
const desiredNumberOfTilesCovered = 1;
let boundingRectangleSize = cartographicBoundingRectangle.width;
let rectangleSize = rectangle.width;
if (cartographicBoundingRectangle.height > cartographicBoundingRectangle.width) {
boundingRectangleSize = cartographicBoundingRectangle.height;
rectangleSize = rectangle.height;
}
const desiredLevel = Math.log2(
desiredNumberOfTilesCovered * rectangleSize / boundingRectangleSize
);
const imageryLevel = ImageryCoverage_default._clampImageryLevel(
imageryProvider,
desiredLevel
);
return imageryLevel;
}
/**
* Update all Imagery objects.
*
* This is called as part of update, until all required
* imagery tiles are "ready", as indicated by their state
* being ImageryState.READY.
*
* This is called after it has been determined which imagery tiles are
* covered by the primitive (i.e. after the _coveragesPerLayer
* have been computed by calling _computeCoverages).
*
* For each covered imagery tile, this will call
* Imagery.processStateMachine until they are either
* READY, FAILED, or INVALID.
*
* Once they all are in one of these final states, it will set the
* _allImageriesReady flag to true.
*
* @param {FrameState} frameState The frame state, to be passed to
* imagery.processStateMachine
* @private
*/
_updateImageries(frameState) {
const model = this._model;
const coveragesPerLayer = this._coveragesPerLayer;
const length2 = coveragesPerLayer.length;
let allImageriesReady = true;
for (let i = 0; i < length2; i++) {
const coverages = coveragesPerLayer[i];
const n = coverages.length;
for (let j = 0; j < n; j++) {
const coverage = coverages[j];
const imagery = coverage.imagery;
const countsAsReady = imagery.state === ImageryState_default.READY || imagery.state === ImageryState_default.FAILED || imagery.state === ImageryState_default.INVALID;
if (!countsAsReady) {
allImageriesReady = false;
imagery.processStateMachine(frameState, false, false);
}
}
}
if (allImageriesReady) {
model.resetDrawCommands();
}
this._allImageriesReady = allImageriesReady;
}
/**
* Returns the MappedPositions object that contains
* information about the primitive positions that have been computed
* for the given imagery layer.
*
* This assumes that _computeMappedPositionsPerEllipsoid has
* already been called.
*
* @param {ImageryLayer} imageryLayer The imageryLayer
* @returns {MappedPositions} The mapped positions
* @throws {DeveloperError} If the mapped positions for the
* ellipsoid could not be found.
*/
mappedPositionsForImageryLayer(imageryLayer) {
const ellipsoid = _ModelPrimitiveImagery._getEllipsoid(imageryLayer);
return this.mappedPositionsForEllipsoid(ellipsoid);
}
/**
* Returns the MappedPositions object that contains
* information about the primitive positions that have been computed
* from the given ellipsoid.
*
* This assumes that _computeMappedPositions has
* already been called.
*
* @param {Ellipsoid} ellipsoid The ellipsoid
* @returns {MappedPositions} The mapped positions
* @throws {DeveloperError} If the mapped positions for the
* given ellipsoid could not be found.
*/
mappedPositionsForEllipsoid(ellipsoid) {
const mappedPositionsPerEllipsoid = this._mappedPositionsPerEllipsoid;
if (!defined_default(mappedPositionsPerEllipsoid)) {
throw new DeveloperError_default(
`The mappedPositions have not been computed yet`
);
}
const length2 = mappedPositionsPerEllipsoid.length;
for (let i = 0; i < length2; i++) {
const mappedPositions = mappedPositionsPerEllipsoid[i];
if (mappedPositions.ellipsoid === ellipsoid) {
return mappedPositions;
}
}
throw new DeveloperError_default(
`Could not find mapped positions for ellipsoid ${ellipsoid}`
);
}
/**
* Returns the texture coordinate attributes for the primitive that
* are used for draping the imagery.
*
* This will be available when this object is ready, and
* will contain one attribute for each unique projection that appears
* in the imagery layers.
*
* @returns {ModelComponents.Attribute[]} The attributes
*/
imageryTexCoordAttributesPerProjection() {
const imageryTexCoordAttributesPerProjection = this._imageryTexCoordAttributesPerProjection;
if (!defined_default(imageryTexCoordAttributesPerProjection)) {
throw new DeveloperError_default(
`The imagery texture coordinate attributes have not been computed yet`
);
}
return this._imageryTexCoordAttributesPerProjection;
}
/**
* Returns whether the draping computations are "ready".
*
* This means that the coveragesPerLayer information
* has been computed, which describes the set of imagery tiles
* that are covered by the primitive, and that all the
* covered imagery tiles are in a state that counts as "ready"
* (i.e. ImageryState.READY, FAILED,
* or INVALID).
*
* @returns {boolean} Whether the draping computations are ready
*/
get ready() {
const coveragesPerLayer = this._coveragesPerLayer;
if (!defined_default(coveragesPerLayer)) {
return false;
}
return this._allImageriesReady;
}
/**
* Returns whether this object was destroyed.
*
* If this object was destroyed, calling any function other than
* isDestroyed will result in a {@link DeveloperError}.
*
* @returns {boolean} Whether this object was destroyed
*/
isDestroyed() {
return false;
}
/**
* Destroys this object and all its resources.
*/
destroy() {
if (this.isDestroyed()) {
return;
}
this._deleteCoveragesPerLayer();
this._destroyImageryTexCoordAttributes();
return destroyObject_default(this);
}
/**
* Compute the transform that apparently has to be applied to
* the positions attribute of a primitive, to compute the
* actual, final positions in ECEF coordinates.
*
* This is based on the computation of the bounding
* sphere that is done at the end of buildDrawCommands
*
* @param {Model} model The model
* @param {ModelComponents.Node} runtimeNode The runtime node
* that the primitive is attached to
* @param {Matrix4} [result] The result
* @returns {Matrix4} The result
* @private
*/
static _computePrimitivePositionTransform(model, runtimeNode, result) {
Check_default.defined("model", model);
Check_default.defined("runtimeNode", runtimeNode);
if (!defined_default(result)) {
result = new Matrix4_default();
}
const modelSceneGraph = model.sceneGraph;
Matrix4_default.clone(Matrix4_default.IDENTITY, result);
Matrix4_default.multiply(result, model.modelMatrix, result);
Matrix4_default.multiply(result, modelSceneGraph.components.transform, result);
Matrix4_default.multiply(result, modelSceneGraph.axisCorrectionMatrix, result);
Matrix4_default.multiply(result, runtimeNode.computedTransform, result);
return result;
}
/**
* Returns the "POSITION" attribute from the given primitive.
*
* The "POSITION" attribute is required. If it is not
* defined for the given primitive, then a DeveloperError
* is thrown.
*
* @param {ModelComponents.Primitive} primitive The primitive
* @returns {ModelComponents.Attribute} The position attribute
* @throws {DeveloperError} If there is no position attribute
* @private
*/
static _obtainPrimitivePositionAttribute(primitive) {
Check_default.defined("primitive", primitive);
const primitivePositionAttribute = ModelUtility_default.getAttributeBySemantic(
primitive,
"POSITION"
);
if (!defined_default(primitivePositionAttribute)) {
throw new DeveloperError_default(
"The primitive does not have a POSITION attribute"
);
}
return primitivePositionAttribute;
}
/**
* Returns the ellipsoid of the given imagery layer.
*
* This only exists to hide a train wreck
*
* @param {ImageryLayer} imageryLayer The imagery layer
* @returns {Ellipsoid} The ellipsoid
* @private
*/
static _getEllipsoid(imageryLayer) {
const ellipsoid = imageryLayer.imageryProvider.tilingScheme.projection.ellipsoid;
return ellipsoid;
}
};
var ModelPrimitiveImagery_default = ModelPrimitiveImagery;
// packages/engine/Source/Scene/Model/ImageryInput.js
var import_InlineWorkers687 = __toESM(require_InlineWorkers(), 1);
var ImageryInput = class {
/**
* Creates a new instance
*
* @param {ImageryLayer} imageryLayer The imagery layer
* @param {Texture} texture The texture from the imagery
* @param {Cartesian4} textureTranslationAndScale The translation
* and scale that have to be applied to the texture, to properly
* be draped on the primitive. This is stored as a Cartesian4
* with (x,y) being the translation and (z,w) being the scale.
* It could be cleaner and clearer to store this as separate
* Cartesian2 objects, but using a single Cartesian4 probably
* was a design choice that was originally made in GlobeFS.glsl,
* with the goal to have fewer uniforms
* @param {Cartesian4} textureCoordinateRectangle The bounding
* rectangle (in texture coordinates). This directly corresponds
* to the ImageryCoverage.textureCoordinateRectangle,
* but converted into a Cartesian4 for the consumption in the
* shader
* @param {number} imageryTexCoordAttributeSetIndex The "set index"
* of the texture coordinate attribute that should be used. This
* will be used to access the texture coordinate attribute
* a_imagery_texCoord_${imageryTexCoordAttributeSetIndex}
* in the shader.
*/
constructor(imageryLayer, texture, textureTranslationAndScale, textureCoordinateRectangle, imageryTexCoordAttributeSetIndex) {
this.imageryLayer = imageryLayer;
this.texture = texture;
this.textureTranslationAndScale = textureTranslationAndScale;
this.textureCoordinateRectangle = textureCoordinateRectangle;
this.imageryTexCoordAttributeSetIndex = imageryTexCoordAttributeSetIndex;
}
};
var ImageryInput_default = ImageryInput;
// packages/engine/Source/Scene/Model/ImageryPipelineStage.js
var debugDrawImageryBoundaries = false;
var nativeBoundingRectangleScratch = new Rectangle_default();
var nativeImageryRectangleScratch = new Rectangle_default();
var ImageryPipelineStage = class _ImageryPipelineStage {
/**
* Process a primitive.
*
* This will update the render resources of the given primitive,
* depending on the imagery that is covered by the given primitive.
*
* This will obtain the ModelPrimitiveImagery from
* the given primitive, and use that to compute the actual
* ImageryInput objects that describe the information
* that has to be passed to the shader for draping the imagery over
* the primitive.
*
* After the ImageryInput has been computed, it will
* extend the render resources with the texture coordinate
* attribute that has to be used for the imagery, and augment
* the primitiveRenderResources.shaderBuilder with
* the information hat is required for the draping.
*
* @param {PrimitiveRenderResources} primitiveRenderResources The render resources for the primitive
* @param {ModelComponents.Primitive} primitive The primitive to be rendered
* @param {FrameState} frameState The frame state.
*/
static process(primitiveRenderResources, primitive, frameState) {
const model = primitiveRenderResources.model;
const modelPrimitiveImagery = primitive.modelPrimitiveImagery;
if (!defined_default(modelPrimitiveImagery)) {
return;
}
if (!modelPrimitiveImagery.ready) {
return;
}
const imageryLayers = model.imageryLayers;
const allProjections = ModelPrimitiveImagery_default._extractProjections(imageryLayers);
const uniqueProjections = [...new Set(allProjections)];
const imageryTexCoordAttributeSetIndices = _ImageryPipelineStage._computeIndexMapping(
allProjections,
uniqueProjections
);
const imageryInputs = _ImageryPipelineStage._createImageryInputs(
imageryLayers,
modelPrimitiveImagery,
imageryTexCoordAttributeSetIndices
);
if (imageryInputs.length === 0) {
return;
}
if (imageryInputs.length > 10) {
oneTimeWarning_default(
"imagery-texture-units",
`Warning: Draped imagery requires ${imageryInputs.length} texture units, truncating`
);
imageryInputs.length = 10;
}
_ImageryPipelineStage._addImageryTexCoordAttributesToRenderResources(
modelPrimitiveImagery,
primitiveRenderResources
);
const imageryLayersArray = [];
for (let i = 0; i < imageryLayers.length; i++) {
imageryLayersArray.push(imageryLayers.get(i));
}
_ImageryPipelineStage._processImageryInputs(
imageryLayersArray,
primitiveRenderResources,
imageryInputs,
uniqueProjections.length
);
}
/**
* Add one attribute to the render resources, for each imagery texture
* coordinate that was computed in the given model primitive imagery
* (one for each projection)
*
* @param {ModelPrimitiveImagery} modelPrimitiveImagery The model primitive imagery
* @param {PrimitiveRenderResources} primitiveRenderResources The render resources
*/
static _addImageryTexCoordAttributesToRenderResources(modelPrimitiveImagery, primitiveRenderResources) {
const imageryTexCoordAttributes = modelPrimitiveImagery.imageryTexCoordAttributesPerProjection();
for (const imageryTexCoordAttribute of imageryTexCoordAttributes) {
_ImageryPipelineStage._addImageryTexCoordAttributeToRenderResources(
imageryTexCoordAttribute,
primitiveRenderResources
);
}
}
/**
* Add the given attribute to the render resources
*
* @param {ModelComponents.Attribute} imageryTexCoordAttribute The attribute
* @param {PrimitiveRenderResources} primitiveRenderResources The render resources
*/
static _addImageryTexCoordAttributeToRenderResources(imageryTexCoordAttribute, primitiveRenderResources) {
const componentsPerAttribute = AttributeType_default.getNumberOfComponents(
imageryTexCoordAttribute.type
);
const renderResourcesAttribute = {
index: primitiveRenderResources.attributeIndex++,
value: defined_default(imageryTexCoordAttribute.buffer) ? void 0 : imageryTexCoordAttribute.constant,
vertexBuffer: imageryTexCoordAttribute.buffer,
count: imageryTexCoordAttribute.count,
componentsPerAttribute,
componentDatatype: imageryTexCoordAttribute.componentDatatype,
offsetInBytes: imageryTexCoordAttribute.byteOffset,
strideInBytes: imageryTexCoordAttribute.byteStride,
normalize: imageryTexCoordAttribute.normalized
};
primitiveRenderResources.attributes.push(renderResourcesAttribute);
}
/**
* Process the ImageryInput objects that have been
* created in process.
*
* This will build the shader, containing the attributes, uniforms,
* and "sample and blend" function that is required according to
* the given imagery inputs
*
* @param {ImageryLayer[]} imageryLayersArray The imagery layers
* @param {PrimitiveRenderResources} primitiveRenderResources The primitive render resources
* @param {ImageryInput[]} imageryInputs The imagery inputs
* @param {number} numImageryTexCoordAttributes The number of texture coordinate
* attributes that have been created for the imagery (one for each distinct
* projection that was found in the imagery layers)
*/
static _processImageryInputs(imageryLayersArray, renderResources, imageryInputs, numImageryTexCoordAttributes) {
const shaderBuilder = renderResources.shaderBuilder;
const imageryFlags = _ImageryPipelineStage._computeImageryFlags(imageryLayersArray);
const numTextures = imageryInputs.length;
shaderBuilder.addDefine(`HAS_IMAGERY`);
shaderBuilder.addDefine(`IMAGERY_TEXTURE_UNITS ${numTextures}`);
_ImageryPipelineStage._addAttributes(
shaderBuilder,
numImageryTexCoordAttributes
);
_ImageryPipelineStage._defineUniforms(shaderBuilder, imageryFlags);
_ImageryPipelineStage._buildSampleAndBlendFunction(
shaderBuilder,
imageryFlags
);
_ImageryPipelineStage._createMainImageryShader(
shaderBuilder,
imageryInputs,
imageryFlags
);
const uniformMap2 = renderResources.uniformMap;
const uniforms = _ImageryPipelineStage._createImageryUniforms(imageryInputs);
_ImageryPipelineStage._setImageryUniforms(uniformMap2, uniforms);
}
/**
* Add the attribute- and varying definitions for the imagery texture
* coordinates to the given shader.
*
* This includes the definition of the initializeImageryAttributes
* function that assigns the attribute values to varyings in the vertex shader.
*
* @param {ShaderBuilder} shaderBuilder The shader builder
* @param {number} numTexCoords The number of imagery texture coordinate sets
*/
static _addAttributes(shaderBuilder, numTexCoords) {
for (let i = 0; i < numTexCoords; i++) {
shaderBuilder.addAttribute("vec2", `a_imagery_texCoord_${i}`);
shaderBuilder.addVarying("vec2", `v_imagery_texCoord_${i}`);
}
const functionId = "initializeImageryAttributes";
const signature = `void ${functionId}()`;
shaderBuilder.addFunction(functionId, signature, ShaderDestination_default.VERTEX);
for (let i = 0; i < numTexCoords; i++) {
shaderBuilder.addFunctionLines(functionId, [
`v_imagery_texCoord_${i} = a_imagery_texCoord_${i};`
]);
}
}
/**
* Returns the `ImageryFlags` that indicate the features that are
* required for the given imagery layers.
*
* The resulting flags will indicate whether any of the given
* imagery layer objects did *not* have the default value for
* the respective property, as defined by `ImageryLayer.DEFAULT_...`
*
* @param {ImageryLayer[]} imageryLayers The imagery layers
* @returns {ImageryFlags} The imagery flags
*/
static _computeImageryFlags(imageryLayers) {
const imageryFlags = new ImageryFlags_default();
for (let i = 0; i < imageryLayers.length; i++) {
const imageryLayer = imageryLayers[i];
imageryFlags.alpha |= imageryLayer.alpha !== 1;
imageryFlags.brightness |= imageryLayer.brightness !== ImageryLayer_default.DEFAULT_BRIGHTNESS;
imageryFlags.contrast |= imageryLayer.contrast !== ImageryLayer_default.DEFAULT_CONTRAST;
imageryFlags.hue |= imageryLayer.hue !== ImageryLayer_default.DEFAULT_HUE;
imageryFlags.saturation |= imageryLayer.saturation !== ImageryLayer_default.DEFAULT_SATURATION;
imageryFlags.gamma |= imageryLayer.gamma !== ImageryLayer_default.DEFAULT_GAMMA;
const hasColorToAlpha = defined_default(imageryLayer.colorToAlpha) && imageryLayer.colorToAlphaThreshold > 0;
imageryFlags.colorToAlpha |= hasColorToAlpha;
}
return imageryFlags;
}
/**
* Adds the uniforms that are required for the imagery to the shader.
*
* This will use the given shader builder to add the uniforms to the
* shader that are always required for the imagery (e.g. the
* `sampler2D u_imageryTextures[...]`).
*
* The array size of all arrays will be `IMAGERY_TEXTURE_UNITS`,
* so this has to be added as a `define` with a positive value.
*
* Depending on the given imagery flags being `true`, it will add
* the optional uniforms, like `u_imageryTextureAlpha`.
*
* The naming pattern will be `u_imageryTexture`, except for
* `gamma`: To safe that one measly division, the thane will be
* `oneOverGamma` there.
*
* @param {ShaderBuilder} shaderBuilder The shader builder
* @param {ImageryFlags} imageryFlags The imagery flags
*/
static _defineUniforms(shaderBuilder, imageryFlags) {
shaderBuilder.addUniform(
"sampler2D",
"u_imageryTextures[IMAGERY_TEXTURE_UNITS]",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"vec4",
"u_imageryTextureCoordinateRectangle[IMAGERY_TEXTURE_UNITS]",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"vec4",
"u_imageryTextureTranslationAndScale[IMAGERY_TEXTURE_UNITS]",
ShaderDestination_default.FRAGMENT
);
if (imageryFlags.alpha) {
shaderBuilder.addUniform(
"float",
"u_imageryTextureAlpha[IMAGERY_TEXTURE_UNITS]",
ShaderDestination_default.FRAGMENT
);
}
if (imageryFlags.brightness) {
shaderBuilder.addUniform(
"float",
"u_imageryTextureBrightness[IMAGERY_TEXTURE_UNITS]",
ShaderDestination_default.FRAGMENT
);
}
if (imageryFlags.contrast) {
shaderBuilder.addUniform(
"float",
"u_imageryTextureContrast[IMAGERY_TEXTURE_UNITS]",
ShaderDestination_default.FRAGMENT
);
}
if (imageryFlags.hue) {
shaderBuilder.addUniform(
"float",
"u_imageryTextureHue[IMAGERY_TEXTURE_UNITS]",
ShaderDestination_default.FRAGMENT
);
}
if (imageryFlags.saturation) {
shaderBuilder.addUniform(
"float",
"u_imageryTextureSaturation[IMAGERY_TEXTURE_UNITS]",
ShaderDestination_default.FRAGMENT
);
}
if (imageryFlags.gamma) {
shaderBuilder.addUniform(
"float",
"u_imageryTextureOneOverGamma[IMAGERY_TEXTURE_UNITS]",
ShaderDestination_default.FRAGMENT
);
}
if (imageryFlags.colorToAlpha) {
shaderBuilder.addUniform(
"vec4",
"u_imageryTextureColorToAlpha[IMAGERY_TEXTURE_UNITS]",
ShaderDestination_default.FRAGMENT
);
}
}
/**
* Create the function signature for the `sampleAndBlend` function,
* based on the features that are required for the imagery.
*
* For details, see `buildSampleAndBlendFunction`
*
* @param {ImageryFlags} imageryFlags The imagery flags
* @returns {string} The string
*/
static _createSampleAndBlendFunctionSignature(imageryFlags) {
const functionId = "sampleAndBlend";
const parameters = [];
parameters.push(`vec4 previousColor`);
parameters.push(`sampler2D textureToSample`);
parameters.push(`vec2 textureCoordinates`);
parameters.push(`vec4 textureCoordinateRectangle`);
parameters.push(`vec4 textureCoordinateTranslationAndScale`);
if (imageryFlags.alpha) {
parameters.push(`float textureAlpha`);
}
if (imageryFlags.brightness) {
parameters.push(`float textureBrightness`);
}
if (imageryFlags.contrast) {
parameters.push(`float textureContrast`);
}
if (imageryFlags.hue) {
parameters.push(`float textureHue`);
}
if (imageryFlags.saturation) {
parameters.push(`float textureSaturation`);
}
if (imageryFlags.gamma) {
parameters.push(`float textureOneOverGamma`);
}
if (imageryFlags.colorToAlpha) {
parameters.push(`vec4 colorToAlpha`);
}
const parametersString = parameters.join(", ");
const signature = `vec4 ${functionId}(${parametersString})`;
return signature;
}
/**
* Build the `sampleAndBlend` function that will be called for each imagery,
* to combine the previous pixel color with the respective imagery input.
*
* The function that is built here resembles the function that was originally defined at
* https://github.com/CesiumGS/cesium/blob/6cc004aaff586bb59f07f199216ae511014cf5a9/packages/engine/Source/Shaders/GlobeFS.glsl#L166
*
* However, for the function that is built here, the signature will
* reflect the actual features that are required for the imagery:
* For example, the `float textureAlpha` parameter will only be
* present when `imageryFlags.alpha` is `true`.
*
* @param {ShaderBuilder} shaderBuilder The shader builder
* @param {ImageryFlags} imageryFlags The imagery flags
*/
static _buildSampleAndBlendFunction(shaderBuilder, imageryFlags) {
const functionId = "sampleAndBlend";
const signature = _ImageryPipelineStage._createSampleAndBlendFunctionSignature(imageryFlags);
shaderBuilder.addFunction(
functionId,
signature,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [`float effectiveAlpha = 1.0;`]);
if (imageryFlags.alpha) {
shaderBuilder.addFunctionLines(functionId, [
`effectiveAlpha = textureAlpha;`
]);
}
shaderBuilder.addFunctionLines(functionId, [
// This is the part that is documented as "This crazy step stuff"
// in GlobeFS.glsl. Using the if-approach here...
`if (textureCoordinates.x < textureCoordinateRectangle.x) effectiveAlpha = 0.0;`,
`if (textureCoordinates.x > textureCoordinateRectangle.z) effectiveAlpha = 0.0;`,
`if (textureCoordinates.y < textureCoordinateRectangle.y) effectiveAlpha = 0.0;`,
`if (textureCoordinates.y > textureCoordinateRectangle.w) effectiveAlpha = 0.0;`,
`vec2 translation = textureCoordinateTranslationAndScale.xy;`,
`vec2 scale = textureCoordinateTranslationAndScale.zw;`,
`vec2 effectiveTextureCoordinates = textureCoordinates * scale + translation;`,
`vec4 value = texture(textureToSample, effectiveTextureCoordinates);`,
`value = czm_srgbToLinear(value);`,
`vec3 color = value.rgb;`,
`float alpha = value.a;`
]);
if (imageryFlags.colorToAlpha) {
shaderBuilder.addFunctionLines(functionId, [
`vec3 colorDiff = abs(color.rgb - colorToAlpha.rgb);`,
`colorDiff.r = czm_maximumComponent(colorDiff);`,
`alpha = czm_branchFreeTernary(colorDiff.r < colorToAlpha.a, 0.0, alpha);`
]);
}
if (imageryFlags.gamma) {
shaderBuilder.addFunctionLines(functionId, [
`color = pow(color, vec3(textureOneOverGamma));`
]);
} else {
shaderBuilder.addFunctionLines(functionId, [
`vec4 tempColor = czm_gammaCorrect(vec4(color, alpha));`,
`color = tempColor.rgb;`,
`alpha = tempColor.a;`
]);
}
if (imageryFlags.brightness) {
shaderBuilder.addFunctionLines(functionId, [
`color = mix(vec3(0.0), color, textureBrightness);`
]);
}
if (imageryFlags.contrast) {
shaderBuilder.addFunctionLines(functionId, [
`color = mix(vec3(0.5), color, textureContrast);`
]);
}
if (imageryFlags.hue) {
shaderBuilder.addFunctionLines(functionId, [
`color = czm_hue(color, textureHue);`
]);
}
if (imageryFlags.saturation) {
shaderBuilder.addFunctionLines(functionId, [
`color = czm_saturation(color, textureSaturation);`
]);
}
shaderBuilder.addFunctionLines(functionId, [
`float sourceAlpha = alpha * effectiveAlpha;`,
`float outAlpha = mix(previousColor.a, 1.0, sourceAlpha);`,
`outAlpha += sign(outAlpha) - 1.0;`,
`vec3 outColor = mix(previousColor.rgb * previousColor.a, color, sourceAlpha) / outAlpha;`,
// See comments in https://github.com/CesiumGS/cesium/blob/6cc004aaff586bb59f07f199216ae511014cf5a9/packages/engine/Source/Shaders/GlobeFS.glsl#L166
`vec4 result = vec4(outColor, max(outAlpha, 0.0));`
]);
if (debugDrawImageryBoundaries) {
shaderBuilder.addFunctionLines(functionId, [
`if (abs(textureCoordinates.x - textureCoordinateRectangle.x) < (1.0/256.0) || `,
` abs(textureCoordinates.x - textureCoordinateRectangle.z) < (1.0/256.0) || `,
` abs(textureCoordinates.y - textureCoordinateRectangle.y) < (1.0/256.0) || `,
` abs(textureCoordinates.y - textureCoordinateRectangle.w) < (1.0/256.0))`,
`{`,
` result = vec4(1.0, 0.0, 0.0, effectiveAlpha);`,
`}`
]);
}
shaderBuilder.addFunctionLines(functionId, [`return result;`]);
}
/**
* Creates the arguments for a call to `sampleAndBlend` for the
* specified imagery.
*
* For details, see `buildSampleAndBlendFunction`
*
* @param {ImageryFlags} imageryFlags The imagery flags
* @param {number} imageryTexCoordAttributeSetIndex The index for the texture coordinate attribute
* @param {number} i The imagery index
* @returns {string} The string
*/
static _createSampleAndBlendCallArguments(imageryFlags, imageryTexCoordAttributeSetIndex, i) {
const textureCoordinates = `v_imagery_texCoord_${imageryTexCoordAttributeSetIndex}`;
const args = [];
args.push(`blendedBaseColor`);
args.push(`u_imageryTextures[${i}]`);
args.push(`${textureCoordinates}`);
args.push(`u_imageryTextureCoordinateRectangle[${i}]`);
args.push(`u_imageryTextureTranslationAndScale[${i}]`);
if (imageryFlags.alpha) {
args.push(`u_imageryTextureAlpha[${i}]`);
}
if (imageryFlags.brightness) {
args.push(`u_imageryTextureBrightness[${i}]`);
}
if (imageryFlags.contrast) {
args.push(`u_imageryTextureContrast[${i}]`);
}
if (imageryFlags.hue) {
args.push(`u_imageryTextureHue[${i}]`);
}
if (imageryFlags.saturation) {
args.push(`u_imageryTextureSaturation[${i}]`);
}
if (imageryFlags.gamma) {
args.push(`u_imageryTextureOneOverGamma[${i}]`);
}
if (imageryFlags.colorToAlpha) {
args.push(`u_imageryTextureColorToAlpha[${i}]`);
}
const argsString = args.join(", ");
return argsString;
}
/**
* Creates the main part of the imagery shader.
*
* It adds the `blendBaseColorWithImagery` function, which is to be
* called in the `MaterialStageFS.glsl` when the `HAS_IMAGERY`
* flag was set in the shader.
*
* The `blendBaseColorWithImagery` function will go through all imagery
* layers in the input, and call the `sampleAndBlend` function, to
* incorporate the imagery input in the resulting pixel.
*
* @param {ShaderBuilder} shaderBuilder The shader builder
* @param {ImageryInput[]} imageryInputs The imagery inputs
* @param {ImageryFlags} imageryFlags The imagery flags
*/
static _createMainImageryShader(shaderBuilder, imageryInputs, imageryFlags) {
const functionId = "blendBaseColorWithImagery";
shaderBuilder.addFunction(
functionId,
`vec4 blendBaseColorWithImagery(vec4 baseColorWithAlpha)`,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [
`vec4 blendedBaseColor = baseColorWithAlpha;`
]);
for (let i = 0; i < imageryInputs.length; i++) {
const imageryInput = imageryInputs[i];
const imageryTexCoordAttributeSetIndex = imageryInput.imageryTexCoordAttributeSetIndex;
const argsString = _ImageryPipelineStage._createSampleAndBlendCallArguments(
imageryFlags,
imageryTexCoordAttributeSetIndex,
i
);
shaderBuilder.addFunctionLines(functionId, [
`blendedBaseColor = sampleAndBlend(${argsString});`
]);
}
shaderBuilder.addFunctionLines(functionId, [`return blendedBaseColor;`]);
}
/**
* Creates an object that contains the uniform values the given imagery inputs.
*
* The result will be a structure that contains the uniform values
* that match the definitions that have been created by `defineUniforms`.
* (It will include the ones that still have their default values
* and may not be needed eventually)
*
* @param {ImageryInput[]} imageryInputs The imagery inputs
* @returns {object} The uniforms
*/
static _createImageryUniforms(imageryInputs) {
const length2 = imageryInputs.length;
const uniforms = {};
uniforms.imageryTextures = Array(length2);
uniforms.imageryTextureCoordinateRectangle = Array(length2);
uniforms.imageryTextureTranslationAndScale = Array(length2);
uniforms.imageryTextureAlpha = Array(length2);
uniforms.imageryTextureBrightness = Array(length2);
uniforms.imageryTextureContrast = Array(length2);
uniforms.imageryTextureHue = Array(length2);
uniforms.imageryTextureSaturation = Array(length2);
uniforms.imageryTextureOneOverGamma = Array(length2);
uniforms.imageryTextureColorToAlpha = Array(length2);
for (let i = 0; i < length2; i++) {
const imageryInput = imageryInputs[i];
const imageryLayer = imageryInput.imageryLayer;
const texture = imageryInput.texture;
const textureCoordinateRectangle = imageryInput.textureCoordinateRectangle;
const textureTranslationAndScale = imageryInput.textureTranslationAndScale;
uniforms.imageryTextures[i] = texture;
uniforms.imageryTextureTranslationAndScale[i] = textureTranslationAndScale;
uniforms.imageryTextureCoordinateRectangle[i] = textureCoordinateRectangle;
uniforms.imageryTextureAlpha[i] = imageryLayer.alpha;
uniforms.imageryTextureBrightness[i] = imageryLayer.brightness;
uniforms.imageryTextureContrast[i] = imageryLayer.contrast;
uniforms.imageryTextureHue[i] = imageryLayer.hue;
uniforms.imageryTextureSaturation[i] = imageryLayer.saturation;
uniforms.imageryTextureOneOverGamma[i] = 1 / imageryLayer.gamma;
let colorToAlpha = uniforms.imageryTextureColorToAlpha[i];
if (!defined_default(colorToAlpha)) {
colorToAlpha = new Cartesian4_default();
uniforms.imageryTextureColorToAlpha[i] = colorToAlpha;
}
const hasColorToAlpha = defined_default(imageryLayer.colorToAlpha) && imageryLayer.colorToAlphaThreshold > 0;
if (hasColorToAlpha) {
const color = imageryLayer.colorToAlpha;
colorToAlpha.x = color.red;
colorToAlpha.y = color.green;
colorToAlpha.z = color.blue;
colorToAlpha.w = imageryLayer.colorToAlphaThreshold;
} else {
colorToAlpha.w = -1;
}
}
return uniforms;
}
/**
* Fill the given uniform map with functions for all properties
* in the given uniforms object.
*
* The uniform names will be created as `u_`, and
* their value will just be a function that returns the respective
* property value.
*
* @param {UniformMap} uniformMap The uniform map
* @param {object} uniforms The uniforms
*/
static _setImageryUniforms(uniformMap2, uniforms) {
for (const key in uniforms) {
if (uniforms.hasOwnProperty(key)) {
const name = `u_${key}`;
uniformMap2[name] = function() {
return uniforms[key];
};
}
}
}
/**
* Create the ImageryInput objects that have to be fed to the imagery
* pipeline stage for draping the given imagery layers over the primitive
* that is described by the given model primitive imagery.
*
* For each imagery layer that is currently visible (as of `show==true`), this
* will obtain the ImageryCoverage objects that are provided by
* the given model primitive imagery (and that describe the imagery tiles
* that are covered by the primitive), and create one ImageryInput for
* each of them.
*
* @param {ImageryLayerCollection} imageryLayers The imagery layers
* @param {ModelPrimitiveImagery} modelPrimitiveImagery The model primitive imagery
* @param {number[]} imageryTexCoordAttributeSetIndices The array that contains,
* for each imagery layer index, the set index of the texture coordinate
* attribute that should be used for this imagery. This is the value that
* will be used to access the texture coordinate attribute
* a_imagery_texCoord_${imageryTexCoordAttributeSetIndex}
* in the shader.
* @returns {ImageryInput[]} The imagery inputs
*/
static _createImageryInputs(imageryLayers, modelPrimitiveImagery, imageryTexCoordAttributeSetIndices) {
Check_default.defined("imageryLayers", imageryLayers);
Check_default.defined("modelPrimitiveImagery", modelPrimitiveImagery);
Check_default.defined(
"imageryTexCoordAttributeSetIndices",
imageryTexCoordAttributeSetIndices
);
const imageryInputs = [];
for (let i = 0; i < imageryLayers.length; i++) {
const imageryLayer = imageryLayers.get(i);
if (!imageryLayer.show) {
continue;
}
const imageryTexCoordAttributeSetIndex = imageryTexCoordAttributeSetIndices[i];
const mappedPositions = modelPrimitiveImagery.mappedPositionsForImageryLayer(imageryLayer);
const cartographicBoundingRectangle = mappedPositions.cartographicBoundingRectangle;
const coverages = modelPrimitiveImagery.coveragesForImageryLayer(imageryLayer);
for (let j = 0; j < coverages.length; j++) {
const coverage = coverages[j];
const imageryInput = _ImageryPipelineStage._createImageryInput(
imageryLayer,
coverage,
cartographicBoundingRectangle,
imageryTexCoordAttributeSetIndex
);
if (defined_default(imageryInput)) {
imageryInputs.push(imageryInput);
}
}
}
return imageryInputs;
}
/**
* Create the `ImageryInput` that has to be passed to the imagery pipeline
* stage, for the given `ImageryCoverage`.
*
* The `ImageryCoverage` describes on imagery tile that is covered by the
* cartographic bounding rectangle of the primitive positions. This function
* obtains the actual `Imagery` object and its texture, computes the
* required texture coordinate and scale, and assembles this information
* into an `ImageryInput`.
*
* @param {ImageryLayer} imageryLayer The imagery layer
* @param {ImageryCoverage} coverage The imagery coverage
* @param {Rectangle} cartographicBoundingRectangle The bounding rectangle
* of the cartographic primitive positions
* @param {number} imageryTexCoordAttributeSetIndex The set index of the
* texture coordinate attribute that should be used for this imagery.
* This is the value that will be used to access the texture coordinate
* attribute a_imagery_texCoord_${imageryTexCoordAttributeSetIndex}
* in the shader.
* @returns {ImageryInput|undefined} The imagery input, or undefined if
* the imagery for the given coverage turned out to be in the
* ImageryState.INVALID/FAILED state, or did not have
* a valid texture.
* @private
*/
static _createImageryInput(imageryLayer, coverage, cartographicBoundingRectangle, imageryTexCoordAttributeSetIndex) {
Check_default.defined("imageryLayer", imageryLayer);
Check_default.defined("coverage", coverage);
Check_default.defined(
"cartographicBoundingRectangle",
cartographicBoundingRectangle
);
Check_default.typeOf.number.greaterThanOrEquals(
"imageryTexCoordAttributeSetIndex",
imageryTexCoordAttributeSetIndex,
0
);
const imagery = coverage.imagery;
if (imagery.state === ImageryState_default.FAILED || imagery.state === ImageryState_default.INVALID) {
return void 0;
}
let texture = imagery.textureWebMercator;
if (!defined_default(texture)) {
texture = imagery.texture;
if (!defined_default(texture)) {
if (imagery.state === ImageryState_default.READY) {
console.log(
`Imagery at ${coverage.x}, ${coverage.y} (level ${coverage.level}) does not have any texture - state ${imagery.state}`
);
}
return void 0;
}
}
const textureTranslationAndScale = _ImageryPipelineStage._computeTextureTranslationAndScale(
imageryLayer,
cartographicBoundingRectangle,
imagery.rectangle
);
const textureCoordinateCartesianRectangle = coverage.textureCoordinateRectangle;
const textureCoordinateRectangle = new Cartesian4_default(
textureCoordinateCartesianRectangle.minX,
textureCoordinateCartesianRectangle.minY,
textureCoordinateCartesianRectangle.maxX,
textureCoordinateCartesianRectangle.maxY
);
const imageryInput = new ImageryInput_default(
imageryLayer,
texture,
textureTranslationAndScale,
textureCoordinateRectangle,
imageryTexCoordAttributeSetIndex
);
return imageryInput;
}
/**
* Compute the translation and scale that has to be applied to
* the texture coordinates for mapping the given imagery to
* the geometry.
*
* The given rectangles will be converted into their "native" representation,
* using the tiling scheme of the given imagery layer, and passed
* to `_computeTextureTranslationAndScaleFromNative` (see that for details).
*
* @param {ImageryLayer} imageryLayer The imagery layer
* @param {Rectangle} nonNativeBoundingRectangle The bounding
* rectangle of the geometry
* @param {Rectangle} nonNativeImageryRectangle The bounding
* rectangle of the imagery
* @returns {Cartesian4} The translation and scale
* @private
*/
static _computeTextureTranslationAndScale(imageryLayer, nonNativeBoundingRectangle, nonNativeImageryRectangle) {
Check_default.defined("imageryLayer", imageryLayer);
Check_default.defined("nonNativeBoundingRectangle", nonNativeBoundingRectangle);
Check_default.defined("nonNativeImageryRectangle", nonNativeImageryRectangle);
const tilingScheme2 = imageryLayer.imageryProvider.tilingScheme;
const nativeBoundingRectangle = tilingScheme2.rectangleToNativeRectangle(
nonNativeBoundingRectangle,
nativeBoundingRectangleScratch
);
const nativeImageryRectangle = tilingScheme2.rectangleToNativeRectangle(
nonNativeImageryRectangle,
nativeImageryRectangleScratch
);
const translationAndScale = _ImageryPipelineStage._computeTextureTranslationAndScaleFromNative(
nativeBoundingRectangle,
nativeImageryRectangle
);
return translationAndScale;
}
/**
* Compute the translation and scale that has to be applied to
* the texture coordinates for mapping the given imagery rectangle
* to the geometry rectangle.
*
* This will compute a Cartesian4 containing the
* (offsetX, offsetY, scaleX, scaleY) that have to be applied to
* the texture coordinates that that have been computed with
* `ModelImageryMapping.createTextureCoordinatesAttributeForMappedPositions`.
* In the shader, this offset and scale will map the given imagery rectangle
* to the geometry * rectangle.
*
* @param {Imagery} imagery The imagery
* @param {Rectangle} nonNativeBoundingRectangle The bounding
* rectangle of the geometry
* @param {Rectangle} nonNativeImageryRectangle The bounding
* rectangle of the imagery
* @returns {Cartesian4} The translation and scale
* @private
*/
static _computeTextureTranslationAndScaleFromNative(nativeBoundingRectangle, nativeImageryRectangle) {
Check_default.defined("nativeBoundingRectangle", nativeBoundingRectangle);
Check_default.defined("nativeImageryRectangle", nativeImageryRectangle);
const invImageryWidth = 1 / nativeImageryRectangle.width;
const invImageryHeight = 1 / nativeImageryRectangle.height;
const deltaWest = nativeBoundingRectangle.west - nativeImageryRectangle.west;
const deltaSouth = nativeBoundingRectangle.south - nativeImageryRectangle.south;
const offsetX = deltaWest * invImageryWidth;
const offsetY = deltaSouth * invImageryHeight;
const scaleX = nativeBoundingRectangle.width * invImageryWidth;
const scaleY = nativeBoundingRectangle.height * invImageryHeight;
return new Cartesian4_default(offsetX, offsetY, scaleX, scaleY);
}
/**
* Computes the index mapping from the given source to the given target.
*
* The result will be an array that has the same length as the source,
* and contains the indices that the source elements have in the
* target array.
*
* @param {object[]} source The source array
* @param {object[]} target The target array
* @returns {number[]} The result
*/
static _computeIndexMapping(source, target) {
Check_default.defined("source", source);
Check_default.defined("target", target);
const result = [];
const length2 = source.length;
for (let i = 0; i < length2; i++) {
const element = source[i];
const index = target.indexOf(element);
result.push(index);
}
return result;
}
};
var ImageryPipelineStage_default = ImageryPipelineStage;
// packages/engine/Source/Scene/Model/LightingPipelineStage.js
var import_InlineWorkers691 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/LightingStageFS.js
var import_InlineWorkers689 = __toESM(require_InlineWorkers(), 1);
var LightingStageFS_default = "#ifdef USE_IBL_LIGHTING\nvec3 computeIBL(vec3 position, vec3 normal, vec3 lightDirection, vec3 lightColorHdr, czm_modelMaterial material)\n{\n #if defined(DIFFUSE_IBL) || defined(SPECULAR_IBL)\n // Environment maps were provided, use them for IBL\n vec3 viewDirection = -normalize(position);\n vec3 iblColor = textureIBL(viewDirection, normal, material);\n return iblColor;\n #endif\n \n return vec3(0.0);\n}\n#endif\n\n#ifdef USE_CLEARCOAT\nvec3 addClearcoatReflection(vec3 baseLayerColor, vec3 position, vec3 lightDirection, vec3 lightColorHdr, czm_modelMaterial material)\n{\n vec3 viewDirection = -normalize(position);\n vec3 halfwayDirection = normalize(viewDirection + lightDirection);\n vec3 normal = material.clearcoatNormal;\n float NdotL = clamp(dot(normal, lightDirection), 0.001, 1.0);\n\n // clearcoatF0 = vec3(pow((ior - 1.0) / (ior + 1.0), 2.0)), but without KHR_materials_ior, ior is a constant 1.5.\n vec3 f0 = vec3(0.04);\n vec3 f90 = vec3(1.0);\n // Note: clearcoat Fresnel computed with dot(n, v) instead of dot(v, h).\n // This is to make it energy conserving with a simple layering function.\n float NdotV = clamp(dot(normal, viewDirection), 0.0, 1.0);\n vec3 F = fresnelSchlick2(f0, f90, NdotV);\n\n // compute specular reflection from direct lighting\n float roughness = material.clearcoatRoughness;\n float alphaRoughness = roughness * roughness;\n float directStrength = computeDirectSpecularStrength(normal, lightDirection, viewDirection, halfwayDirection, alphaRoughness);\n vec3 directReflection = F * directStrength * NdotL;\n vec3 color = lightColorHdr * directReflection;\n\n #ifdef SPECULAR_IBL\n // Find the direction in which to sample the environment map\n vec3 reflectMC = normalize(model_iblReferenceFrameMatrix * reflect(-viewDirection, normal));\n vec3 iblColor = computeSpecularIBL(reflectMC, NdotV, f0, roughness);\n color += iblColor * material.occlusion;\n #endif\n\n float clearcoatFactor = material.clearcoatFactor;\n vec3 clearcoatColor = color * clearcoatFactor;\n\n // Dim base layer based on transmission loss through clearcoat\n return baseLayerColor * (1.0 - clearcoatFactor * F) + clearcoatColor;\n}\n#endif\n\n#if defined(LIGHTING_PBR) && defined(HAS_NORMALS)\nvec3 computePbrLighting(in czm_modelMaterial material, in vec3 position)\n{\n #ifdef USE_CUSTOM_LIGHT_COLOR\n vec3 lightColorHdr = model_lightColorHdr;\n #else\n vec3 lightColorHdr = czm_lightColorHdr;\n #endif\n\n vec3 viewDirection = -normalize(position);\n vec3 normal = material.normalEC;\n vec3 lightDirection = normalize(czm_lightDirectionEC);\n\n vec3 directLighting = czm_pbrLighting(viewDirection, normal, lightDirection, material);\n vec3 directColor = lightColorHdr * directLighting;\n\n // Accumulate colors from base layer\n vec3 color = directColor + material.emissive;\n #ifdef USE_IBL_LIGHTING\n color += computeIBL(position, normal, lightDirection, lightColorHdr, material);\n #endif\n\n #ifdef USE_CLEARCOAT\n color = addClearcoatReflection(color, position, lightDirection, lightColorHdr, material);\n #endif\n\n return color;\n}\n#endif\n\n/**\n * Compute the material color under the current lighting conditions.\n * All other material properties are passed through so further stages\n * have access to them.\n *\n * @param {czm_modelMaterial} material The material properties from {@MaterialStageFS}\n * @param {ProcessedAttributes} attributes\n */\nvoid lightingStage(inout czm_modelMaterial material, ProcessedAttributes attributes)\n{\n #ifdef LIGHTING_PBR\n #ifdef HAS_NORMALS\n vec3 color = computePbrLighting(material, attributes.positionEC);\n #else\n vec3 color = material.diffuse * material.occlusion + material.emissive;\n #endif\n // In HDR mode, the frame buffer is in linear color space. The\n // post-processing stages (see PostProcessStageCollection) will handle\n // tonemapping. However, if HDR is not enabled, we must tonemap else large\n // values may be clamped to 1.0\n #ifndef HDR\n color = czm_pbrNeutralTonemapping(color);\n #endif\n #else // unlit\n vec3 color = material.diffuse;\n #endif\n\n #ifdef HAS_POINT_CLOUD_COLOR_STYLE\n // The colors resulting from point cloud styles are adjusted differently.\n color = czm_gammaCorrect(color);\n #elif !defined(HDR)\n // If HDR is not enabled, the frame buffer stores sRGB colors rather than\n // linear colors so the linear value must be converted.\n color = czm_linearToSrgb(color);\n #endif\n\n material.diffuse = color;\n}\n";
// packages/engine/Source/Scene/Model/LightingModel.js
var import_InlineWorkers690 = __toESM(require_InlineWorkers(), 1);
var LightingModel = {
/**
* Use unlit shading, i.e. skip lighting calculations. The model's
* diffuse color (assumed to be linear RGB, not sRGB) is used directly
* when computing out_FragColor. The alpha mode is still
* applied.
*
* @type {number}
* @constant
*/
UNLIT: 0,
/**
* Use physically-based rendering lighting calculations. This includes
* both PBR metallic roughness and PBR specular glossiness. Image-based
* lighting is also applied when possible.
*
* @type {number}
* @constant
*/
PBR: 1
};
var LightingModel_default = Object.freeze(LightingModel);
// packages/engine/Source/Scene/Model/LightingPipelineStage.js
var LightingPipelineStage = {
name: "LightingPipelineStage"
// Helps with debugging
};
LightingPipelineStage.process = function(renderResources, primitive) {
const { model, lightingOptions, shaderBuilder } = renderResources;
if (defined_default(model.lightColor)) {
shaderBuilder.addDefine(
"USE_CUSTOM_LIGHT_COLOR",
void 0,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"vec3",
"model_lightColorHdr",
ShaderDestination_default.FRAGMENT
);
const uniformMap2 = renderResources.uniformMap;
uniformMap2.model_lightColorHdr = function() {
return model.lightColor;
};
}
const { lightingModel } = lightingOptions;
if (lightingModel === LightingModel_default.PBR) {
shaderBuilder.addDefine(
"LIGHTING_PBR",
void 0,
ShaderDestination_default.FRAGMENT
);
} else {
shaderBuilder.addDefine(
"LIGHTING_UNLIT",
void 0,
ShaderDestination_default.FRAGMENT
);
}
shaderBuilder.addFragmentLines(LightingStageFS_default);
};
var LightingPipelineStage_default = LightingPipelineStage;
// packages/engine/Source/Scene/Model/MaterialPipelineStage.js
var import_InlineWorkers693 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/MaterialStageFS.js
var import_InlineWorkers692 = __toESM(require_InlineWorkers(), 1);
var MaterialStageFS_default = "// If the style color is white, it implies the feature has not been styled.\nbool isDefaultStyleColor(vec3 color)\n{\n return all(greaterThan(color, vec3(1.0 - czm_epsilon3)));\n}\n\nvec3 blend(vec3 sourceColor, vec3 styleColor, float styleColorBlend)\n{\n vec3 blendColor = mix(sourceColor, styleColor, styleColorBlend);\n vec3 color = isDefaultStyleColor(styleColor.rgb) ? sourceColor : blendColor;\n return color;\n}\n\nvec2 computeTextureTransform(vec2 texCoord, mat3 textureTransform)\n{\n return vec2(textureTransform * vec3(texCoord, 1.0));\n}\n\n#ifdef HAS_NORMAL_TEXTURE\nvec2 getNormalTexCoords()\n{\n vec2 texCoord = TEXCOORD_NORMAL;\n #ifdef HAS_NORMAL_TEXTURE_TRANSFORM\n texCoord = vec2(u_normalTextureTransform * vec3(texCoord, 1.0));\n #endif\n return texCoord;\n}\n#endif\n\n#if defined(HAS_NORMAL_TEXTURE) || defined(HAS_CLEARCOAT_NORMAL_TEXTURE)\nvec3 computeTangent(in vec3 position, in vec2 normalTexCoords)\n{\n vec2 tex_dx = dFdx(normalTexCoords);\n vec2 tex_dy = dFdy(normalTexCoords);\n float determinant = tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y;\n vec3 tangent = tex_dy.t * dFdx(position) - tex_dx.t * dFdy(position);\n return tangent / determinant;\n}\n#endif\n\n#ifdef USE_ANISOTROPY\nstruct NormalInfo {\n vec3 tangent;\n vec3 bitangent;\n vec3 normal;\n vec3 geometryNormal;\n};\n\nNormalInfo getNormalInfo(ProcessedAttributes attributes)\n{\n vec3 geometryNormal = attributes.normalEC;\n #ifdef HAS_NORMAL_TEXTURE\n vec2 normalTexCoords = getNormalTexCoords();\n #endif\n\n #ifdef HAS_BITANGENTS\n vec3 tangent = attributes.tangentEC;\n vec3 bitangent = attributes.bitangentEC;\n #else // Assume HAS_NORMAL_TEXTURE\n vec3 tangent = computeTangent(attributes.positionEC, normalTexCoords);\n tangent = normalize(tangent - geometryNormal * dot(geometryNormal, tangent));\n vec3 bitangent = normalize(cross(geometryNormal, tangent));\n #endif\n\n #ifdef HAS_NORMAL_TEXTURE\n mat3 tbn = mat3(tangent, bitangent, geometryNormal);\n vec3 normalSample = texture(u_normalTexture, normalTexCoords).rgb;\n normalSample = 2.0 * normalSample - 1.0;\n #ifdef HAS_NORMAL_TEXTURE_SCALE\n normalSample.xy *= u_normalTextureScale;\n #endif\n vec3 normal = normalize(tbn * normalSample);\n #else\n vec3 normal = geometryNormal;\n #endif\n\n #ifdef HAS_DOUBLE_SIDED_MATERIAL\n if (czm_backFacing()) {\n tangent *= -1.0;\n bitangent *= -1.0;\n normal *= -1.0;\n geometryNormal *= -1.0;\n }\n #endif\n\n NormalInfo normalInfo;\n normalInfo.tangent = tangent;\n normalInfo.bitangent = bitangent;\n normalInfo.normal = normal;\n normalInfo.geometryNormal = geometryNormal;\n\n return normalInfo;\n}\n#endif\n\n#if defined(HAS_NORMAL_TEXTURE) && !defined(HAS_WIREFRAME)\nvec3 getNormalFromTexture(ProcessedAttributes attributes, vec3 geometryNormal)\n{\n vec2 normalTexCoords = getNormalTexCoords();\n\n // If HAS_BITANGENTS is set, then HAS_TANGENTS is also set\n #ifdef HAS_BITANGENTS\n vec3 t = attributes.tangentEC;\n vec3 b = attributes.bitangentEC;\n #else\n vec3 t = computeTangent(attributes.positionEC, normalTexCoords);\n t = normalize(t - geometryNormal * dot(geometryNormal, t));\n vec3 b = normalize(cross(geometryNormal, t));\n #endif\n\n mat3 tbn = mat3(t, b, geometryNormal);\n vec3 normalSample = texture(u_normalTexture, normalTexCoords).rgb;\n normalSample = 2.0 * normalSample - 1.0;\n #ifdef HAS_NORMAL_TEXTURE_SCALE\n normalSample.xy *= u_normalTextureScale;\n #endif\n return normalize(tbn * normalSample);\n}\n#endif\n\n#ifdef HAS_CLEARCOAT_NORMAL_TEXTURE\nvec3 getClearcoatNormalFromTexture(ProcessedAttributes attributes, vec3 geometryNormal)\n{\n vec2 normalTexCoords = TEXCOORD_CLEARCOAT_NORMAL;\n #ifdef HAS_CLEARCOAT_NORMAL_TEXTURE_TRANSFORM\n normalTexCoords = vec2(u_clearcoatNormalTextureTransform * vec3(normalTexCoords, 1.0));\n #endif\n\n // If HAS_BITANGENTS is set, then HAS_TANGENTS is also set\n #ifdef HAS_BITANGENTS\n vec3 t = attributes.tangentEC;\n vec3 b = attributes.bitangentEC;\n #else\n vec3 t = computeTangent(attributes.positionEC, normalTexCoords);\n t = normalize(t - geometryNormal * dot(geometryNormal, t));\n vec3 b = normalize(cross(geometryNormal, t));\n #endif\n\n mat3 tbn = mat3(t, b, geometryNormal);\n vec3 normalSample = texture(u_clearcoatNormalTexture, normalTexCoords).rgb;\n normalSample = 2.0 * normalSample - 1.0;\n #ifdef HAS_CLEARCOAT_NORMAL_TEXTURE_SCALE\n normalSample.xy *= u_clearcoatNormalTextureScale;\n #endif\n return normalize(tbn * normalSample);\n}\n#endif\n\n#ifdef HAS_NORMALS\nvec3 computeNormal(ProcessedAttributes attributes)\n{\n // Geometry normal. This is already normalized \n vec3 normal = attributes.normalEC;\n\n #if defined(HAS_NORMAL_TEXTURE) && !defined(HAS_WIREFRAME)\n normal = getNormalFromTexture(attributes, normal);\n #endif\n\n #ifdef HAS_DOUBLE_SIDED_MATERIAL\n if (czm_backFacing()) {\n normal = -normal;\n }\n #endif\n\n return normal;\n}\n#endif\n\n#ifdef HAS_BASE_COLOR_TEXTURE\nvec4 getBaseColorFromTexture()\n{\n vec2 baseColorTexCoords = TEXCOORD_BASE_COLOR;\n #ifdef HAS_BASE_COLOR_TEXTURE_TRANSFORM\n baseColorTexCoords = computeTextureTransform(baseColorTexCoords, u_baseColorTextureTransform);\n #endif\n\n vec4 baseColorWithAlpha = czm_srgbToLinear(texture(u_baseColorTexture, baseColorTexCoords));\n\n #ifdef HAS_BASE_COLOR_FACTOR\n baseColorWithAlpha *= u_baseColorFactor;\n #endif\n\n return baseColorWithAlpha;\n}\n#endif\n\n#ifdef HAS_EMISSIVE_TEXTURE\nvec3 getEmissiveFromTexture()\n{\n vec2 emissiveTexCoords = TEXCOORD_EMISSIVE;\n #ifdef HAS_EMISSIVE_TEXTURE_TRANSFORM\n emissiveTexCoords = computeTextureTransform(emissiveTexCoords, u_emissiveTextureTransform);\n #endif\n\n vec3 emissive = czm_srgbToLinear(texture(u_emissiveTexture, emissiveTexCoords).rgb);\n #ifdef HAS_EMISSIVE_FACTOR\n emissive *= u_emissiveFactor;\n #endif\n\n return emissive;\n}\n#endif\n\n#if defined(LIGHTING_PBR) && defined(USE_SPECULAR_GLOSSINESS)\nvoid setSpecularGlossiness(inout czm_modelMaterial material)\n{\n #ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE\n vec2 specularGlossinessTexCoords = TEXCOORD_SPECULAR_GLOSSINESS;\n #ifdef HAS_SPECULAR_GLOSSINESS_TEXTURE_TRANSFORM\n specularGlossinessTexCoords = computeTextureTransform(specularGlossinessTexCoords, u_specularGlossinessTextureTransform);\n #endif\n\n vec4 specularGlossiness = czm_srgbToLinear(texture(u_specularGlossinessTexture, specularGlossinessTexCoords));\n vec3 specular = specularGlossiness.rgb;\n float glossiness = specularGlossiness.a;\n #ifdef HAS_LEGACY_SPECULAR_FACTOR\n specular *= u_legacySpecularFactor;\n #endif\n\n #ifdef HAS_GLOSSINESS_FACTOR\n glossiness *= u_glossinessFactor;\n #endif\n #else\n #ifdef HAS_LEGACY_SPECULAR_FACTOR\n vec3 specular = clamp(u_legacySpecularFactor, vec3(0.0), vec3(1.0));\n #else\n vec3 specular = vec3(1.0);\n #endif\n\n #ifdef HAS_GLOSSINESS_FACTOR\n float glossiness = clamp(u_glossinessFactor, 0.0, 1.0);\n #else\n float glossiness = 1.0;\n #endif\n #endif\n\n #ifdef HAS_DIFFUSE_TEXTURE\n vec2 diffuseTexCoords = TEXCOORD_DIFFUSE;\n #ifdef HAS_DIFFUSE_TEXTURE_TRANSFORM\n diffuseTexCoords = computeTextureTransform(diffuseTexCoords, u_diffuseTextureTransform);\n #endif\n\n vec4 diffuse = czm_srgbToLinear(texture(u_diffuseTexture, diffuseTexCoords));\n #ifdef HAS_DIFFUSE_FACTOR\n diffuse *= u_diffuseFactor;\n #endif\n #elif defined(HAS_DIFFUSE_FACTOR)\n vec4 diffuse = clamp(u_diffuseFactor, vec4(0.0), vec4(1.0));\n #else\n vec4 diffuse = vec4(1.0);\n #endif\n\n material.diffuse = diffuse.rgb * (1.0 - czm_maximumComponent(specular));\n // the specular glossiness extension's alpha overrides anything set\n // by the base material.\n material.alpha = diffuse.a;\n\n material.specular = specular;\n\n // glossiness is the opposite of roughness, but easier for artists to use.\n material.roughness = 1.0 - glossiness;\n}\n#elif defined(LIGHTING_PBR)\nfloat setMetallicRoughness(inout czm_modelMaterial material)\n{\n #ifdef HAS_METALLIC_ROUGHNESS_TEXTURE\n vec2 metallicRoughnessTexCoords = TEXCOORD_METALLIC_ROUGHNESS;\n #ifdef HAS_METALLIC_ROUGHNESS_TEXTURE_TRANSFORM\n metallicRoughnessTexCoords = computeTextureTransform(metallicRoughnessTexCoords, u_metallicRoughnessTextureTransform);\n #endif\n\n vec3 metallicRoughness = texture(u_metallicRoughnessTexture, metallicRoughnessTexCoords).rgb;\n float metalness = clamp(metallicRoughness.b, 0.0, 1.0);\n float roughness = clamp(metallicRoughness.g, 0.0, 1.0);\n #ifdef HAS_METALLIC_FACTOR\n metalness = clamp(metalness * u_metallicFactor, 0.0, 1.0);\n #endif\n\n #ifdef HAS_ROUGHNESS_FACTOR\n roughness = clamp(roughness * u_roughnessFactor, 0.0, 1.0);\n #endif\n #else\n #ifdef HAS_METALLIC_FACTOR\n float metalness = clamp(u_metallicFactor, 0.0, 1.0);\n #else\n float metalness = 1.0;\n #endif\n\n #ifdef HAS_ROUGHNESS_FACTOR\n float roughness = clamp(u_roughnessFactor, 0.0, 1.0);\n #else\n float roughness = 1.0;\n #endif\n #endif\n\n // dielectrics use f0 = 0.04, metals use albedo as f0\n const vec3 REFLECTANCE_DIELECTRIC = vec3(0.04);\n vec3 f0 = mix(REFLECTANCE_DIELECTRIC, material.baseColor.rgb, metalness);\n\n material.specular = f0;\n\n // diffuse only applies to dielectrics.\n material.diffuse = mix(material.baseColor.rgb, vec3(0.0), metalness);\n\n // This is perceptual roughness. The square of this value is used for direct lighting\n material.roughness = roughness;\n\n return metalness;\n}\n#ifdef USE_SPECULAR\nvoid setSpecular(inout czm_modelMaterial material, in float metalness)\n{\n #ifdef HAS_SPECULAR_TEXTURE\n vec2 specularTexCoords = TEXCOORD_SPECULAR;\n #ifdef HAS_SPECULAR_TEXTURE_TRANSFORM\n specularTexCoords = computeTextureTransform(specularTexCoords, u_specularTextureTransform);\n #endif\n float specularWeight = texture(u_specularTexture, specularTexCoords).a;\n #ifdef HAS_SPECULAR_FACTOR\n specularWeight *= u_specularFactor;\n #endif\n #else\n #ifdef HAS_SPECULAR_FACTOR\n float specularWeight = u_specularFactor;\n #else\n float specularWeight = 1.0;\n #endif\n #endif\n\n #ifdef HAS_SPECULAR_COLOR_TEXTURE\n vec2 specularColorTexCoords = TEXCOORD_SPECULAR_COLOR;\n #ifdef HAS_SPECULAR_COLOR_TEXTURE_TRANSFORM\n specularColorTexCoords = computeTextureTransform(specularColorTexCoords, u_specularColorTextureTransform);\n #endif\n vec3 specularColorSample = texture(u_specularColorTexture, specularColorTexCoords).rgb;\n vec3 specularColorFactor = czm_srgbToLinear(specularColorSample);\n #ifdef HAS_SPECULAR_COLOR_FACTOR\n specularColorFactor *= u_specularColorFactor;\n #endif\n #else\n #ifdef HAS_SPECULAR_COLOR_FACTOR\n vec3 specularColorFactor = u_specularColorFactor;\n #else\n vec3 specularColorFactor = vec3(1.0);\n #endif\n #endif\n material.specularWeight = specularWeight;\n vec3 f0 = material.specular;\n vec3 dielectricSpecularF0 = min(f0 * specularColorFactor, vec3(1.0));\n material.specular = mix(dielectricSpecularF0, material.baseColor.rgb, metalness);\n}\n#endif\n#ifdef USE_ANISOTROPY\nvoid setAnisotropy(inout czm_modelMaterial material, in NormalInfo normalInfo)\n{\n mat2 rotation = mat2(u_anisotropy.xy, -u_anisotropy.y, u_anisotropy.x);\n float anisotropyStrength = u_anisotropy.z;\n\n vec2 direction = vec2(1.0, 0.0);\n #ifdef HAS_ANISOTROPY_TEXTURE\n vec2 anisotropyTexCoords = TEXCOORD_ANISOTROPY;\n #ifdef HAS_ANISOTROPY_TEXTURE_TRANSFORM\n anisotropyTexCoords = computeTextureTransform(anisotropyTexCoords, u_anisotropyTextureTransform);\n #endif\n vec3 anisotropySample = texture(u_anisotropyTexture, anisotropyTexCoords).rgb;\n direction = anisotropySample.rg * 2.0 - vec2(1.0);\n anisotropyStrength *= anisotropySample.b;\n #endif\n\n direction = rotation * direction;\n mat3 tbn = mat3(normalInfo.tangent, normalInfo.bitangent, normalInfo.normal);\n vec3 anisotropicT = tbn * normalize(vec3(direction, 0.0));\n vec3 anisotropicB = cross(normalInfo.geometryNormal, anisotropicT);\n\n material.anisotropicT = anisotropicT;\n material.anisotropicB = anisotropicB;\n material.anisotropyStrength = anisotropyStrength;\n}\n#endif\n#ifdef USE_CLEARCOAT\nvoid setClearcoat(inout czm_modelMaterial material, in ProcessedAttributes attributes)\n{\n #ifdef HAS_CLEARCOAT_TEXTURE\n vec2 clearcoatTexCoords = TEXCOORD_CLEARCOAT;\n #ifdef HAS_CLEARCOAT_TEXTURE_TRANSFORM\n clearcoatTexCoords = computeTextureTransform(clearcoatTexCoords, u_clearcoatTextureTransform);\n #endif\n float clearcoatFactor = texture(u_clearcoatTexture, clearcoatTexCoords).r;\n #ifdef HAS_CLEARCOAT_FACTOR\n clearcoatFactor *= u_clearcoatFactor;\n #endif\n #else\n #ifdef HAS_CLEARCOAT_FACTOR\n float clearcoatFactor = u_clearcoatFactor;\n #else\n // PERFORMANCE_IDEA: this case should turn the whole extension off\n float clearcoatFactor = 0.0;\n #endif\n #endif\n\n #ifdef HAS_CLEARCOAT_ROUGHNESS_TEXTURE\n vec2 clearcoatRoughnessTexCoords = TEXCOORD_CLEARCOAT_ROUGHNESS;\n #ifdef HAS_CLEARCOAT_ROUGHNESS_TEXTURE_TRANSFORM\n clearcoatRoughnessTexCoords = computeTextureTransform(clearcoatRoughnessTexCoords, u_clearcoatRoughnessTextureTransform);\n #endif\n float clearcoatRoughness = texture(u_clearcoatRoughnessTexture, clearcoatRoughnessTexCoords).g;\n #ifdef HAS_CLEARCOAT_ROUGHNESS_FACTOR\n clearcoatRoughness *= u_clearcoatRoughnessFactor;\n #endif\n #else\n #ifdef HAS_CLEARCOAT_ROUGHNESS_FACTOR\n float clearcoatRoughness = u_clearcoatRoughnessFactor;\n #else\n float clearcoatRoughness = 0.0;\n #endif\n #endif\n\n material.clearcoatFactor = clearcoatFactor;\n // This is perceptual roughness. The square of this value is used for direct lighting\n material.clearcoatRoughness = clearcoatRoughness;\n #ifdef HAS_CLEARCOAT_NORMAL_TEXTURE\n material.clearcoatNormal = getClearcoatNormalFromTexture(attributes, attributes.normalEC);\n #else\n material.clearcoatNormal = attributes.normalEC;\n #endif\n}\n#endif\n#endif\n\nvoid materialStage(inout czm_modelMaterial material, ProcessedAttributes attributes, SelectedFeature feature)\n{\n #ifdef USE_ANISOTROPY\n NormalInfo normalInfo = getNormalInfo(attributes);\n material.normalEC = normalInfo.normal;\n #elif defined(HAS_NORMALS)\n material.normalEC = computeNormal(attributes);\n #endif\n\n vec4 baseColorWithAlpha = vec4(1.0);\n // Regardless of whether we use PBR, set a base color\n #ifdef HAS_BASE_COLOR_TEXTURE\n baseColorWithAlpha = getBaseColorFromTexture();\n #elif defined(HAS_BASE_COLOR_FACTOR)\n baseColorWithAlpha = u_baseColorFactor;\n #endif\n\n #ifdef HAS_IMAGERY\n baseColorWithAlpha = blendBaseColorWithImagery(baseColorWithAlpha);\n #endif // HAS_IMAGERY\n\n #ifdef HAS_POINT_CLOUD_COLOR_STYLE\n baseColorWithAlpha = v_pointCloudColor;\n #elif defined(HAS_COLOR_0)\n vec4 color = attributes.color_0;\n // .pnts files store colors in the sRGB color space\n #ifdef HAS_SRGB_COLOR\n color = czm_srgbToLinear(color);\n #endif\n baseColorWithAlpha *= color;\n #endif\n\n #ifdef USE_CPU_STYLING\n baseColorWithAlpha.rgb = blend(baseColorWithAlpha.rgb, feature.color.rgb, model_colorBlend);\n #endif\n material.baseColor = baseColorWithAlpha;\n material.diffuse = baseColorWithAlpha.rgb;\n material.alpha = baseColorWithAlpha.a;\n\n #ifdef HAS_OCCLUSION_TEXTURE\n vec2 occlusionTexCoords = TEXCOORD_OCCLUSION;\n #ifdef HAS_OCCLUSION_TEXTURE_TRANSFORM\n occlusionTexCoords = computeTextureTransform(occlusionTexCoords, u_occlusionTextureTransform);\n #endif\n material.occlusion = texture(u_occlusionTexture, occlusionTexCoords).r;\n #endif\n\n #ifdef HAS_EMISSIVE_TEXTURE\n material.emissive = getEmissiveFromTexture();\n #elif defined(HAS_EMISSIVE_FACTOR)\n material.emissive = u_emissiveFactor;\n #endif\n\n #if defined(LIGHTING_PBR) && defined(USE_SPECULAR_GLOSSINESS)\n setSpecularGlossiness(material);\n #elif defined(LIGHTING_PBR)\n float metalness = setMetallicRoughness(material);\n #ifdef USE_SPECULAR\n setSpecular(material, metalness);\n #endif\n #ifdef USE_ANISOTROPY\n setAnisotropy(material, normalInfo);\n #endif\n #ifdef USE_CLEARCOAT\n setClearcoat(material, attributes);\n #endif\n #endif\n}\n";
// packages/engine/Source/Scene/Model/MaterialPipelineStage.js
var { Material: Material4, MetallicRoughness: MetallicRoughness3, SpecularGlossiness: SpecularGlossiness3, Specular: Specular3, Clearcoat: Clearcoat3 } = ModelComponents_default;
var MaterialPipelineStage = {
name: "MaterialPipelineStage",
// Helps with debugging
// Expose some methods for testing
_processTexture: processTexture2,
_processTextureTransform: processTextureTransform
};
MaterialPipelineStage.process = function(renderResources, primitive, frameState) {
const material = primitive.material;
const { model, uniformMap: uniformMap2, shaderBuilder } = renderResources;
const hasClassification = defined_default(model.classificationType);
const disableTextures = hasClassification;
const { defaultTexture, defaultNormalTexture, defaultEmissiveTexture } = frameState.context;
processMaterialUniforms(
material,
uniformMap2,
shaderBuilder,
defaultTexture,
defaultNormalTexture,
defaultEmissiveTexture,
disableTextures
);
if (defined_default(material.specularGlossiness)) {
processSpecularGlossinessUniforms(
material.specularGlossiness,
uniformMap2,
shaderBuilder,
defaultTexture,
disableTextures
);
} else {
if (defined_default(material.specular) && ModelUtility_default.supportedExtensions.KHR_materials_specular) {
processSpecularUniforms(
material.specular,
uniformMap2,
shaderBuilder,
defaultTexture,
disableTextures
);
}
if (defined_default(material.anisotropy) && ModelUtility_default.supportedExtensions.KHR_materials_anisotropy) {
processAnisotropyUniforms(
material.anisotropy,
uniformMap2,
shaderBuilder,
defaultTexture,
disableTextures
);
}
if (defined_default(material.clearcoat) && ModelUtility_default.supportedExtensions.KHR_materials_clearcoat) {
processClearcoatUniforms(
material.clearcoat,
uniformMap2,
shaderBuilder,
defaultTexture,
disableTextures
);
}
processMetallicRoughnessUniforms(
material.metallicRoughness,
uniformMap2,
shaderBuilder,
defaultTexture,
disableTextures
);
}
const hasNormals = ModelUtility_default.getAttributeBySemantic(
primitive,
VertexAttributeSemantic_default.NORMAL
);
const disablePointCloudNormals = defined_default(model.pointCloudShading) && !model.pointCloudShading.normalShading;
const lightingOptions = renderResources.lightingOptions;
if (material.unlit || !hasNormals || hasClassification || disablePointCloudNormals) {
lightingOptions.lightingModel = LightingModel_default.UNLIT;
} else {
lightingOptions.lightingModel = LightingModel_default.PBR;
}
const cull = model.backFaceCulling && !material.doubleSided;
renderResources.renderStateOptions.cull.enabled = cull;
const alphaOptions = renderResources.alphaOptions;
if (material.alphaMode === AlphaMode_default.BLEND) {
alphaOptions.pass = Pass_default.TRANSLUCENT;
} else if (material.alphaMode === AlphaMode_default.MASK) {
alphaOptions.alphaCutoff = material.alphaCutoff;
}
shaderBuilder.addFragmentLines(MaterialStageFS_default);
if (material.doubleSided) {
shaderBuilder.addDefine(
"HAS_DOUBLE_SIDED_MATERIAL",
void 0,
ShaderDestination_default.BOTH
);
}
};
function processTextureTransform(shaderBuilder, uniformMap2, textureReader, uniformName, defineName) {
const transformDefine = `HAS_${defineName}_TEXTURE_TRANSFORM`;
shaderBuilder.addDefine(
transformDefine,
void 0,
ShaderDestination_default.FRAGMENT
);
const transformUniformName = `${uniformName}Transform`;
shaderBuilder.addUniform(
"mat3",
transformUniformName,
ShaderDestination_default.FRAGMENT
);
uniformMap2[transformUniformName] = function() {
return textureReader.transform;
};
}
function processTextureScale(shaderBuilder, uniformMap2, textureReader, uniformName, defineName) {
const transformDefine = `HAS_${defineName}_TEXTURE_SCALE`;
shaderBuilder.addDefine(
transformDefine,
void 0,
ShaderDestination_default.FRAGMENT
);
const scaleUniformName = `${uniformName}Scale`;
shaderBuilder.addUniform(
"float",
scaleUniformName,
ShaderDestination_default.FRAGMENT
);
uniformMap2[scaleUniformName] = function() {
return textureReader.scale;
};
}
function processTexture2(shaderBuilder, uniformMap2, textureReader, uniformName, defineName, defaultTexture) {
shaderBuilder.addUniform(
"sampler2D",
uniformName,
ShaderDestination_default.FRAGMENT
);
uniformMap2[uniformName] = function() {
return textureReader.texture ?? defaultTexture;
};
const textureDefine = `HAS_${defineName}_TEXTURE`;
shaderBuilder.addDefine(textureDefine, void 0, ShaderDestination_default.FRAGMENT);
const texCoordIndex = textureReader.texCoord;
const texCoordVarying = `v_texCoord_${texCoordIndex}`;
const texCoordDefine = `TEXCOORD_${defineName}`;
shaderBuilder.addDefine(
texCoordDefine,
texCoordVarying,
ShaderDestination_default.FRAGMENT
);
const textureTransform = textureReader.transform;
if (defined_default(textureTransform) && !Matrix3_default.equals(textureTransform, Matrix3_default.IDENTITY)) {
processTextureTransform(
shaderBuilder,
uniformMap2,
textureReader,
uniformName,
defineName
);
}
const { scale } = textureReader;
if (defined_default(scale) && scale !== 1) {
processTextureScale(
shaderBuilder,
uniformMap2,
textureReader,
uniformName,
defineName
);
}
}
function processMaterialUniforms(material, uniformMap2, shaderBuilder, defaultTexture, defaultNormalTexture, defaultEmissiveTexture, disableTextures) {
const { emissiveFactor, emissiveTexture, normalTexture, occlusionTexture } = material;
if (defined_default(emissiveFactor) && !Cartesian3_default.equals(emissiveFactor, Material4.DEFAULT_EMISSIVE_FACTOR)) {
shaderBuilder.addUniform(
"vec3",
"u_emissiveFactor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.u_emissiveFactor = function() {
return material.emissiveFactor;
};
shaderBuilder.addDefine(
"HAS_EMISSIVE_FACTOR",
void 0,
ShaderDestination_default.FRAGMENT
);
if (defined_default(emissiveTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
emissiveTexture,
"u_emissiveTexture",
"EMISSIVE",
defaultEmissiveTexture
);
}
}
if (defined_default(normalTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
normalTexture,
"u_normalTexture",
"NORMAL",
defaultNormalTexture
);
}
if (defined_default(occlusionTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
occlusionTexture,
"u_occlusionTexture",
"OCCLUSION",
defaultTexture
);
}
}
function processSpecularGlossinessUniforms(specularGlossiness, uniformMap2, shaderBuilder, defaultTexture, disableTextures) {
const {
diffuseTexture,
diffuseFactor,
specularGlossinessTexture,
specularFactor,
glossinessFactor
} = specularGlossiness;
shaderBuilder.addDefine(
"USE_SPECULAR_GLOSSINESS",
void 0,
ShaderDestination_default.FRAGMENT
);
if (defined_default(diffuseTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
diffuseTexture,
"u_diffuseTexture",
"DIFFUSE",
defaultTexture
);
}
if (defined_default(diffuseFactor) && !Cartesian4_default.equals(diffuseFactor, SpecularGlossiness3.DEFAULT_DIFFUSE_FACTOR)) {
shaderBuilder.addUniform(
"vec4",
"u_diffuseFactor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.u_diffuseFactor = function() {
return specularGlossiness.diffuseFactor;
};
shaderBuilder.addDefine(
"HAS_DIFFUSE_FACTOR",
void 0,
ShaderDestination_default.FRAGMENT
);
}
if (defined_default(specularGlossinessTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
specularGlossinessTexture,
"u_specularGlossinessTexture",
"SPECULAR_GLOSSINESS",
defaultTexture
);
}
if (defined_default(specularFactor) && !Cartesian3_default.equals(
specularFactor,
SpecularGlossiness3.DEFAULT_SPECULAR_FACTOR
)) {
shaderBuilder.addUniform(
"vec3",
"u_legacySpecularFactor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.u_legacySpecularFactor = function() {
return specularGlossiness.specularFactor;
};
shaderBuilder.addDefine(
"HAS_LEGACY_SPECULAR_FACTOR",
void 0,
ShaderDestination_default.FRAGMENT
);
}
if (defined_default(glossinessFactor) && glossinessFactor !== SpecularGlossiness3.DEFAULT_GLOSSINESS_FACTOR) {
shaderBuilder.addUniform(
"float",
"u_glossinessFactor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.u_glossinessFactor = function() {
return specularGlossiness.glossinessFactor;
};
shaderBuilder.addDefine(
"HAS_GLOSSINESS_FACTOR",
void 0,
ShaderDestination_default.FRAGMENT
);
}
}
function processSpecularUniforms(specular, uniformMap2, shaderBuilder, defaultTexture, disableTextures) {
const {
specularTexture,
specularFactor,
specularColorTexture,
specularColorFactor
} = specular;
shaderBuilder.addDefine(
"USE_SPECULAR",
void 0,
ShaderDestination_default.FRAGMENT
);
if (defined_default(specularTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
specularTexture,
"u_specularTexture",
"SPECULAR",
defaultTexture
);
}
if (defined_default(specularFactor) && specularFactor !== Specular3.DEFAULT_SPECULAR_FACTOR) {
shaderBuilder.addUniform(
"float",
"u_specularFactor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.u_specularFactor = function() {
return specular.specularFactor;
};
shaderBuilder.addDefine(
"HAS_SPECULAR_FACTOR",
void 0,
ShaderDestination_default.FRAGMENT
);
}
if (defined_default(specularColorTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
specularColorTexture,
"u_specularColorTexture",
"SPECULAR_COLOR",
defaultTexture
);
}
if (defined_default(specularColorFactor) && !Cartesian3_default.equals(
specularColorFactor,
Specular3.DEFAULT_SPECULAR_COLOR_FACTOR
)) {
shaderBuilder.addUniform(
"vec3",
"u_specularColorFactor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.u_specularColorFactor = function() {
return specular.specularColorFactor;
};
shaderBuilder.addDefine(
"HAS_SPECULAR_COLOR_FACTOR",
void 0,
ShaderDestination_default.FRAGMENT
);
}
}
var scratchAnisotropy = new Cartesian3_default();
function processAnisotropyUniforms(anisotropy, uniformMap2, shaderBuilder, defaultTexture, disableTextures) {
const { anisotropyStrength, anisotropyRotation, anisotropyTexture } = anisotropy;
shaderBuilder.addDefine(
"USE_ANISOTROPY",
void 0,
ShaderDestination_default.FRAGMENT
);
if (defined_default(anisotropyTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
anisotropyTexture,
"u_anisotropyTexture",
"ANISOTROPY",
defaultTexture
);
}
const cosRotation = Math.cos(anisotropyRotation);
const sinRotation = Math.sin(anisotropyRotation);
shaderBuilder.addUniform("vec3", "u_anisotropy", ShaderDestination_default.FRAGMENT);
uniformMap2.u_anisotropy = function() {
return Cartesian3_default.fromElements(
cosRotation,
sinRotation,
anisotropyStrength,
scratchAnisotropy
);
};
}
function processClearcoatUniforms(clearcoat, uniformMap2, shaderBuilder, defaultTexture, disableTextures) {
const {
clearcoatFactor,
clearcoatTexture,
clearcoatRoughnessFactor,
clearcoatRoughnessTexture,
clearcoatNormalTexture
} = clearcoat;
shaderBuilder.addDefine(
"USE_CLEARCOAT",
void 0,
ShaderDestination_default.FRAGMENT
);
if (defined_default(clearcoatFactor) && clearcoatFactor !== Clearcoat3.DEFAULT_CLEARCOAT_FACTOR) {
shaderBuilder.addUniform(
"float",
"u_clearcoatFactor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.u_clearcoatFactor = function() {
return clearcoat.clearcoatFactor;
};
shaderBuilder.addDefine(
"HAS_CLEARCOAT_FACTOR",
void 0,
ShaderDestination_default.FRAGMENT
);
}
if (defined_default(clearcoatTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
clearcoatTexture,
"u_clearcoatTexture",
"CLEARCOAT",
defaultTexture
);
}
if (defined_default(clearcoatRoughnessFactor) && clearcoatFactor !== Clearcoat3.DEFAULT_CLEARCOAT_ROUGHNESS_FACTOR) {
shaderBuilder.addUniform(
"float",
"u_clearcoatRoughnessFactor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.u_clearcoatRoughnessFactor = function() {
return clearcoat.clearcoatRoughnessFactor;
};
shaderBuilder.addDefine(
"HAS_CLEARCOAT_ROUGHNESS_FACTOR",
void 0,
ShaderDestination_default.FRAGMENT
);
}
if (defined_default(clearcoatRoughnessTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
clearcoatRoughnessTexture,
"u_clearcoatRoughnessTexture",
"CLEARCOAT_ROUGHNESS",
defaultTexture
);
}
if (defined_default(clearcoatNormalTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
clearcoatNormalTexture,
"u_clearcoatNormalTexture",
"CLEARCOAT_NORMAL",
defaultTexture
);
}
}
function processMetallicRoughnessUniforms(metallicRoughness, uniformMap2, shaderBuilder, defaultTexture, disableTextures) {
shaderBuilder.addDefine(
"USE_METALLIC_ROUGHNESS",
void 0,
ShaderDestination_default.FRAGMENT
);
const baseColorTexture = metallicRoughness.baseColorTexture;
if (defined_default(baseColorTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
baseColorTexture,
"u_baseColorTexture",
"BASE_COLOR",
defaultTexture
);
}
const baseColorFactor = metallicRoughness.baseColorFactor;
if (defined_default(baseColorFactor) && !Cartesian4_default.equals(
baseColorFactor,
MetallicRoughness3.DEFAULT_BASE_COLOR_FACTOR
)) {
shaderBuilder.addUniform(
"vec4",
"u_baseColorFactor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.u_baseColorFactor = function() {
return metallicRoughness.baseColorFactor;
};
shaderBuilder.addDefine(
"HAS_BASE_COLOR_FACTOR",
void 0,
ShaderDestination_default.FRAGMENT
);
}
const metallicRoughnessTexture = metallicRoughness.metallicRoughnessTexture;
if (defined_default(metallicRoughnessTexture) && !disableTextures) {
processTexture2(
shaderBuilder,
uniformMap2,
metallicRoughnessTexture,
"u_metallicRoughnessTexture",
"METALLIC_ROUGHNESS",
defaultTexture
);
}
const metallicFactor = metallicRoughness.metallicFactor;
if (defined_default(metallicFactor) && metallicFactor !== MetallicRoughness3.DEFAULT_METALLIC_FACTOR) {
shaderBuilder.addUniform(
"float",
"u_metallicFactor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.u_metallicFactor = function() {
return metallicRoughness.metallicFactor;
};
shaderBuilder.addDefine(
"HAS_METALLIC_FACTOR",
void 0,
ShaderDestination_default.FRAGMENT
);
}
const roughnessFactor = metallicRoughness.roughnessFactor;
if (defined_default(roughnessFactor) && roughnessFactor !== MetallicRoughness3.DEFAULT_ROUGHNESS_FACTOR) {
shaderBuilder.addUniform(
"float",
"u_roughnessFactor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.u_roughnessFactor = function() {
return metallicRoughness.roughnessFactor;
};
shaderBuilder.addDefine(
"HAS_ROUGHNESS_FACTOR",
void 0,
ShaderDestination_default.FRAGMENT
);
}
}
var MaterialPipelineStage_default = MaterialPipelineStage;
// packages/engine/Source/Scene/Model/MetadataPickingPipelineStage.js
var import_InlineWorkers694 = __toESM(require_InlineWorkers(), 1);
var MetadataPickingPipelineStage = {
name: "MetadataPickingPipelineStage",
// Helps with debugging
// The identifiers for 'define' directives that are inserted into the
// shader code. The values of these defines will be be assigned
// in the `DerivedCommands` class when a derived command for metadata
// picking is created.
METADATA_PICKING_ENABLED: "METADATA_PICKING_ENABLED",
METADATA_PICKING_VALUE_TYPE: "METADATA_PICKING_VALUE_TYPE",
METADATA_PICKING_VALUE_STRING: "METADATA_PICKING_VALUE_STRING",
METADATA_PICKING_VALUE_COMPONENT_X: "METADATA_PICKING_VALUE_COMPONENT_X",
METADATA_PICKING_VALUE_COMPONENT_Y: "METADATA_PICKING_VALUE_COMPONENT_Y",
METADATA_PICKING_VALUE_COMPONENT_Z: "METADATA_PICKING_VALUE_COMPONENT_Z",
METADATA_PICKING_VALUE_COMPONENT_W: "METADATA_PICKING_VALUE_COMPONENT_W"
};
MetadataPickingPipelineStage.process = function(renderResources, primitive, frameState) {
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addDefine(
MetadataPickingPipelineStage.METADATA_PICKING_VALUE_TYPE,
"float",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addDefine(
MetadataPickingPipelineStage.METADATA_PICKING_VALUE_STRING,
"0.0",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addDefine(
MetadataPickingPipelineStage.METADATA_PICKING_VALUE_COMPONENT_X,
"0.0",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addDefine(
MetadataPickingPipelineStage.METADATA_PICKING_VALUE_COMPONENT_Y,
"0.0",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addDefine(
MetadataPickingPipelineStage.METADATA_PICKING_VALUE_COMPONENT_Z,
"0.0",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addDefine(
MetadataPickingPipelineStage.METADATA_PICKING_VALUE_COMPONENT_W,
"0.0",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFunction(
"metadataPickingStage",
"void metadataPickingStage(Metadata metadata, MetadataClass metadataClass, inout vec4 metadataValues)",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFunctionLines(
"metadataPickingStage",
[
`${MetadataPickingPipelineStage.METADATA_PICKING_VALUE_TYPE} value = ${MetadataPickingPipelineStage.METADATA_PICKING_VALUE_TYPE}(${MetadataPickingPipelineStage.METADATA_PICKING_VALUE_STRING});`,
`metadataValues.x = ${MetadataPickingPipelineStage.METADATA_PICKING_VALUE_COMPONENT_X};`,
`metadataValues.y = ${MetadataPickingPipelineStage.METADATA_PICKING_VALUE_COMPONENT_Y};`,
`metadataValues.z = ${MetadataPickingPipelineStage.METADATA_PICKING_VALUE_COMPONENT_Z};`,
`metadataValues.w = ${MetadataPickingPipelineStage.METADATA_PICKING_VALUE_COMPONENT_W};`
],
ShaderDestination_default.FRAGMENT
);
};
var MetadataPickingPipelineStage_default = MetadataPickingPipelineStage;
// packages/engine/Source/Scene/Model/MorphTargetsPipelineStage.js
var import_InlineWorkers696 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/MorphTargetsStageVS.js
var import_InlineWorkers695 = __toESM(require_InlineWorkers(), 1);
var MorphTargetsStageVS_default = "void morphTargetsStage(inout ProcessedAttributes attributes) \n{\n vec3 positionMC = attributes.positionMC;\n attributes.positionMC = getMorphedPosition(positionMC);\n\n #ifdef HAS_NORMALS\n vec3 normalMC = attributes.normalMC;\n attributes.normalMC = getMorphedNormal(normalMC);\n #endif\n\n #ifdef HAS_TANGENTS\n vec3 tangentMC = attributes.tangentMC;\n attributes.tangentMC = getMorphedTangent(tangentMC);\n #endif\n}";
// packages/engine/Source/Scene/Model/MorphTargetsPipelineStage.js
var MorphTargetsPipelineStage = {
name: "MorphTargetsPipelineStage",
// Helps with debugging
FUNCTION_ID_GET_MORPHED_POSITION: "getMorphedPosition",
FUNCTION_SIGNATURE_GET_MORPHED_POSITION: "vec3 getMorphedPosition(in vec3 position)",
FUNCTION_ID_GET_MORPHED_NORMAL: "getMorphedNormal",
FUNCTION_SIGNATURE_GET_MORPHED_NORMAL: "vec3 getMorphedNormal(in vec3 normal)",
FUNCTION_ID_GET_MORPHED_TANGENT: "getMorphedTangent",
FUNCTION_SIGNATURE_GET_MORPHED_TANGENT: "vec3 getMorphedTangent(in vec3 tangent)"
};
MorphTargetsPipelineStage.process = function(renderResources, primitive) {
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addDefine(
"HAS_MORPH_TARGETS",
void 0,
ShaderDestination_default.VERTEX
);
addGetMorphedAttributeFunctionDeclarations(shaderBuilder);
const morphTargetsLength = primitive.morphTargets.length;
for (let i = 0; i < morphTargetsLength; i++) {
const attributes = primitive.morphTargets[i].attributes;
const attributesLength = attributes.length;
for (let j = 0; j < attributesLength; j++) {
const attribute = attributes[j];
const semantic = attribute.semantic;
if (semantic !== VertexAttributeSemantic_default.POSITION && semantic !== VertexAttributeSemantic_default.NORMAL && semantic !== VertexAttributeSemantic_default.TANGENT) {
continue;
}
processMorphTargetAttribute(
renderResources,
attribute,
renderResources.attributeIndex,
i
);
renderResources.attributeIndex++;
}
}
addGetMorphedAttributeFunctionReturns(shaderBuilder);
const weights2 = renderResources.runtimeNode.morphWeights;
const weightsLength = weights2.length;
shaderBuilder.addUniform(
"float",
`u_morphWeights[${weightsLength}]`,
ShaderDestination_default.VERTEX
);
shaderBuilder.addVertexLines(MorphTargetsStageVS_default);
const uniformMap2 = {
u_morphWeights: function() {
return renderResources.runtimeNode.morphWeights;
}
};
renderResources.uniformMap = combine_default(uniformMap2, renderResources.uniformMap);
};
var scratchAttributeInfo = {
attributeString: void 0,
functionId: void 0
};
function processMorphTargetAttribute(renderResources, attribute, attributeIndex, morphTargetIndex) {
const shaderBuilder = renderResources.shaderBuilder;
addMorphTargetAttributeToRenderResources(
renderResources,
attribute,
attributeIndex
);
const attributeInfo = getMorphTargetAttributeInfo(
attribute,
scratchAttributeInfo
);
addMorphTargetAttributeDeclarationAndFunctionLine(
shaderBuilder,
attributeInfo,
morphTargetIndex
);
}
function addMorphTargetAttributeToRenderResources(renderResources, attribute, attributeIndex) {
const vertexAttribute = {
index: attributeIndex,
value: defined_default(attribute.buffer) ? void 0 : attribute.constant,
vertexBuffer: attribute.buffer,
componentsPerAttribute: AttributeType_default.getNumberOfComponents(attribute.type),
componentDatatype: attribute.componentDatatype,
offsetInBytes: attribute.byteOffset,
strideInBytes: attribute.byteStride,
normalize: attribute.normalized
};
renderResources.attributes.push(vertexAttribute);
}
function getMorphTargetAttributeInfo(attribute, result) {
const semantic = attribute.semantic;
switch (semantic) {
case VertexAttributeSemantic_default.POSITION:
result.attributeString = "Position";
result.functionId = MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_POSITION;
break;
case VertexAttributeSemantic_default.NORMAL:
result.attributeString = "Normal";
result.functionId = MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_NORMAL;
break;
case VertexAttributeSemantic_default.TANGENT:
result.attributeString = "Tangent";
result.functionId = MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_TANGENT;
break;
default:
break;
}
return result;
}
function addMorphTargetAttributeDeclarationAndFunctionLine(shaderBuilder, attributeInfo, morphTargetIndex) {
const attributeString = attributeInfo.attributeString;
const attributeName = `a_target${attributeString}_${morphTargetIndex}`;
const line = `morphed${attributeString} += u_morphWeights[${morphTargetIndex}] * a_target${attributeString}_${morphTargetIndex};`;
shaderBuilder.addAttribute("vec3", attributeName);
shaderBuilder.addFunctionLines(attributeInfo.functionId, [line]);
}
function addGetMorphedAttributeFunctionDeclarations(shaderBuilder) {
shaderBuilder.addFunction(
MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_POSITION,
MorphTargetsPipelineStage.FUNCTION_SIGNATURE_GET_MORPHED_POSITION,
ShaderDestination_default.VERTEX
);
const positionLine = "vec3 morphedPosition = position;";
shaderBuilder.addFunctionLines(
MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_POSITION,
[positionLine]
);
shaderBuilder.addFunction(
MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_NORMAL,
MorphTargetsPipelineStage.FUNCTION_SIGNATURE_GET_MORPHED_NORMAL,
ShaderDestination_default.VERTEX
);
const normalLine = "vec3 morphedNormal = normal;";
shaderBuilder.addFunctionLines(
MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_NORMAL,
[normalLine]
);
shaderBuilder.addFunction(
MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_TANGENT,
MorphTargetsPipelineStage.FUNCTION_SIGNATURE_GET_MORPHED_TANGENT,
ShaderDestination_default.VERTEX
);
const tangentLine = "vec3 morphedTangent = tangent;";
shaderBuilder.addFunctionLines(
MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_TANGENT,
[tangentLine]
);
}
function addGetMorphedAttributeFunctionReturns(shaderBuilder) {
const positionLine = "return morphedPosition;";
shaderBuilder.addFunctionLines(
MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_POSITION,
[positionLine]
);
const normalLine = "return morphedNormal;";
shaderBuilder.addFunctionLines(
MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_NORMAL,
[normalLine]
);
const tangentLine = "return morphedTangent;";
shaderBuilder.addFunctionLines(
MorphTargetsPipelineStage.FUNCTION_ID_GET_MORPHED_TANGENT,
[tangentLine]
);
}
var MorphTargetsPipelineStage_default = MorphTargetsPipelineStage;
// packages/engine/Source/Scene/Model/PickingPipelineStage.js
var import_InlineWorkers697 = __toESM(require_InlineWorkers(), 1);
var PickingPipelineStage = {
name: "PickingPipelineStage"
// Helps with debugging
};
PickingPipelineStage.process = function(renderResources, primitive, frameState) {
const context = frameState.context;
const runtimeNode = renderResources.runtimeNode;
const shaderBuilder = renderResources.shaderBuilder;
const model = renderResources.model;
const instances = runtimeNode.node.instances;
if (renderResources.hasPropertyTable) {
processPickTexture(renderResources, primitive, instances, context);
} else if (defined_default(instances)) {
processInstancedPickIds(renderResources, context);
} else {
const pickObject = buildPickObject(renderResources);
const pickId = context.createPickId(pickObject);
model._pipelineResources.push(pickId);
model._pickIds.push(pickId);
shaderBuilder.addUniform(
"vec4",
"czm_pickColor",
ShaderDestination_default.FRAGMENT
);
const uniformMap2 = renderResources.uniformMap;
uniformMap2.czm_pickColor = function() {
return pickId.color;
};
renderResources.pickId = "czm_pickColor";
}
};
function buildPickObject(renderResources, instanceId) {
const model = renderResources.model;
if (defined_default(model.pickObject)) {
return model.pickObject;
}
const detailPickObject = {
model,
node: renderResources.runtimeNode,
primitive: renderResources.runtimePrimitive
};
let pickObject;
if (ModelType_default.is3DTiles(model.type)) {
const content = model.content;
pickObject = {
content,
primitive: content.tileset,
detail: detailPickObject
};
} else {
pickObject = {
primitive: model,
detail: detailPickObject
};
}
pickObject.id = model.id;
if (defined_default(instanceId)) {
pickObject.instanceId = instanceId;
}
return pickObject;
}
function processPickTexture(renderResources, primitive, instances) {
const model = renderResources.model;
let featureTableId;
let featureIdAttribute;
const featureIdLabel = model.featureIdLabel;
const instanceFeatureIdLabel = model.instanceFeatureIdLabel;
if (defined_default(model.featureTableId)) {
featureTableId = model.featureTableId;
} else if (defined_default(instances)) {
featureIdAttribute = ModelUtility_default.getFeatureIdsByLabel(
instances.featureIds,
instanceFeatureIdLabel
);
featureTableId = featureIdAttribute.propertyTableId;
} else {
featureIdAttribute = ModelUtility_default.getFeatureIdsByLabel(
primitive.featureIds,
featureIdLabel
);
featureTableId = featureIdAttribute.propertyTableId;
}
const featureTable = model.featureTables[featureTableId];
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addUniform(
"sampler2D",
"model_pickTexture",
ShaderDestination_default.FRAGMENT
);
const batchTexture = featureTable.batchTexture;
renderResources.uniformMap.model_pickTexture = function() {
return batchTexture.pickTexture ?? batchTexture.defaultTexture;
};
renderResources.pickId = "((selectedFeature.id < int(model_featuresLength)) ? texture(model_pickTexture, selectedFeature.st) : vec4(0.0))";
}
function processInstancedPickIds(renderResources, context) {
const instanceCount = renderResources.instanceCount;
const pickIds = new Array(instanceCount);
const pickIdsTypedArray = new Uint8Array(instanceCount * 4);
const model = renderResources.model;
const pipelineResources = model._pipelineResources;
for (let i = 0; i < instanceCount; i++) {
const pickObject = buildPickObject(renderResources, i);
const pickId = context.createPickId(pickObject);
pipelineResources.push(pickId);
pickIds[i] = pickId;
const pickColor = pickId.color;
pickIdsTypedArray[i * 4 + 0] = Color_default.floatToByte(pickColor.red);
pickIdsTypedArray[i * 4 + 1] = Color_default.floatToByte(pickColor.green);
pickIdsTypedArray[i * 4 + 2] = Color_default.floatToByte(pickColor.blue);
pickIdsTypedArray[i * 4 + 3] = Color_default.floatToByte(pickColor.alpha);
}
model._pickIds = pickIds;
const pickIdsBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: pickIdsTypedArray,
usage: BufferUsage_default.STATIC_DRAW
});
pickIdsBuffer.vertexArrayDestroyable = false;
const hasCpuCopy = false;
model.statistics.addBuffer(pickIdsBuffer, hasCpuCopy);
pipelineResources.push(pickIdsBuffer);
const pickIdsVertexAttribute = {
index: renderResources.attributeIndex++,
vertexBuffer: pickIdsBuffer,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
normalize: true,
offsetInBytes: 0,
strideInBytes: 0,
instanceDivisor: 1
};
renderResources.attributes.push(pickIdsVertexAttribute);
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addDefine("USE_PICKING", void 0, ShaderDestination_default.BOTH);
shaderBuilder.addAttribute("vec4", "a_pickColor");
shaderBuilder.addVarying("vec4", "v_pickColor");
renderResources.pickId = "v_pickColor";
}
var PickingPipelineStage_default = PickingPipelineStage;
// packages/engine/Source/Scene/Model/PointCloudStylingPipelineStage.js
var import_InlineWorkers700 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Cesium3DTileRefine.js
var import_InlineWorkers698 = __toESM(require_InlineWorkers(), 1);
var Cesium3DTileRefine = {
/**
* Render this tile and, if it doesn't meet the screen space error, also refine to its children.
*
* @type {number}
* @constant
*/
ADD: 0,
/**
* Render this tile or, if it doesn't meet the screen space error, refine to its descendants instead.
*
* @type {number}
* @constant
*/
REPLACE: 1
};
var Cesium3DTileRefine_default = Object.freeze(Cesium3DTileRefine);
// packages/engine/Source/Shaders/Model/PointCloudStylingStageVS.js
var import_InlineWorkers699 = __toESM(require_InlineWorkers(), 1);
var PointCloudStylingStageVS_default = "float getPointSizeFromAttenuation(vec3 positionEC) {\n // Variables are packed into a single vector to minimize gl.uniformXXX() calls\n float pointSize = model_pointCloudParameters.x;\n float geometricError = model_pointCloudParameters.y;\n float depthMultiplier = model_pointCloudParameters.z;\n\n float depth = -positionEC.z;\n return min((geometricError / depth) * depthMultiplier, pointSize);\n}\n\n#ifdef HAS_POINT_CLOUD_SHOW_STYLE\nfloat pointCloudShowStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {\n float tiles3d_tileset_time = model_pointCloudParameters.w;\n return float(getShowFromStyle(attributes, metadata, tiles3d_tileset_time));\n}\n#endif\n\n#ifdef HAS_POINT_CLOUD_COLOR_STYLE\nvec4 pointCloudColorStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {\n float tiles3d_tileset_time = model_pointCloudParameters.w;\n return getColorFromStyle(attributes, metadata, tiles3d_tileset_time);\n}\n#endif\n\n#ifdef HAS_POINT_CLOUD_POINT_SIZE_STYLE\nfloat pointCloudPointSizeStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {\n float tiles3d_tileset_time = model_pointCloudParameters.w;\n return float(getPointSizeFromStyle(attributes, metadata, tiles3d_tileset_time));\n}\n#elif defined(HAS_POINT_CLOUD_ATTENUATION)\nfloat pointCloudPointSizeStylingStage(in ProcessedAttributes attributes, in Metadata metadata) {\n return getPointSizeFromAttenuation(v_positionEC);\n}\n#endif\n\n#ifdef HAS_POINT_CLOUD_BACK_FACE_CULLING\nfloat pointCloudBackFaceCullingStage() {\n #if defined(HAS_NORMALS) && !defined(HAS_DOUBLE_SIDED_MATERIAL)\n // This needs to be computed in eye coordinates so we can't use attributes.normalMC\n return step(-v_normalEC.z, 0.0);\n #else\n return 1.0;\n #endif\n}\n#endif\n";
// packages/engine/Source/Scene/Model/PointCloudStylingPipelineStage.js
var scratchUniform = new Cartesian4_default();
var PointCloudStylingPipelineStage = {
name: "PointCloudStylingPipelineStage"
// Helps with debugging
};
PointCloudStylingPipelineStage.process = function(renderResources, primitive, frameState) {
const shaderBuilder = renderResources.shaderBuilder;
const model = renderResources.model;
const style = model.style;
const structuralMetadata = model.structuralMetadata;
const propertyAttributes = defined_default(structuralMetadata) ? structuralMetadata.propertyAttributes : void 0;
const hasFeatureTable = defined_default(model.featureTableId) && model.featureTables[model.featureTableId].featuresLength > 0;
const hasBatchTable = !defined_default(propertyAttributes) && hasFeatureTable;
if (defined_default(style) && !hasBatchTable) {
const variableSubstitutionMap = getVariableSubstitutionMap(propertyAttributes);
const shaderFunctionInfo = getStyleShaderFunctionInfo(
style,
variableSubstitutionMap
);
addShaderFunctionsAndDefines(shaderBuilder, shaderFunctionInfo);
const propertyNames = getPropertyNames(shaderFunctionInfo);
const usesNormalSemantic = propertyNames.indexOf("normalMC") >= 0;
const hasNormals = ModelUtility_default.getAttributeBySemantic(
primitive,
VertexAttributeSemantic_default.NORMAL
);
if (usesNormalSemantic && !hasNormals) {
throw new RuntimeError_default(
"Style references the NORMAL semantic but the point cloud does not have normals"
);
}
shaderBuilder.addDefine(
"COMPUTE_POSITION_WC_STYLE",
void 0,
ShaderDestination_default.VERTEX
);
const styleTranslucent = shaderFunctionInfo.styleTranslucent;
if (styleTranslucent) {
renderResources.alphaOptions.pass = Pass_default.TRANSLUCENT;
}
}
const pointCloudShading = model.pointCloudShading;
if (pointCloudShading.attenuation) {
shaderBuilder.addDefine(
"HAS_POINT_CLOUD_ATTENUATION",
void 0,
ShaderDestination_default.VERTEX
);
}
if (pointCloudShading.backFaceCulling) {
shaderBuilder.addDefine(
"HAS_POINT_CLOUD_BACK_FACE_CULLING",
void 0,
ShaderDestination_default.VERTEX
);
}
let content;
let is3DTiles;
let usesAddRefinement;
if (ModelType_default.is3DTiles(model.type)) {
is3DTiles = true;
content = model.content;
usesAddRefinement = content.tile.refine === Cesium3DTileRefine_default.ADD;
}
shaderBuilder.addUniform(
"vec4",
"model_pointCloudParameters",
ShaderDestination_default.VERTEX
);
shaderBuilder.addVertexLines(PointCloudStylingStageVS_default);
const uniformMap2 = renderResources.uniformMap;
uniformMap2.model_pointCloudParameters = function() {
const vec4 = scratchUniform;
let defaultPointSize = 1;
if (is3DTiles) {
defaultPointSize = usesAddRefinement ? 5 : content.tileset.memoryAdjustedScreenSpaceError;
}
vec4.x = pointCloudShading.maximumAttenuation ?? defaultPointSize;
vec4.x *= frameState.pixelRatio;
const geometricError = getGeometricError2(
renderResources,
primitive,
pointCloudShading,
content
);
vec4.y = geometricError * pointCloudShading.geometricErrorScale;
const context = frameState.context;
const frustum = frameState.camera.frustum;
let depthMultiplier;
if (frameState.mode === SceneMode_default.SCENE2D || frustum instanceof OrthographicFrustum_default) {
depthMultiplier = Number.POSITIVE_INFINITY;
} else {
depthMultiplier = context.drawingBufferHeight / frameState.camera.frustum.sseDenominator;
}
vec4.z = depthMultiplier;
if (is3DTiles) {
vec4.w = content.tileset.timeSinceLoad;
}
return vec4;
};
};
var scratchDimensions = new Cartesian3_default();
function getGeometricError2(renderResources, primitive, pointCloudShading, content) {
if (defined_default(content)) {
const geometricError = content.tile.geometricError;
if (geometricError > 0) {
return geometricError;
}
}
if (defined_default(pointCloudShading.baseResolution)) {
return pointCloudShading.baseResolution;
}
const positionAttribute = ModelUtility_default.getAttributeBySemantic(
primitive,
VertexAttributeSemantic_default.POSITION
);
const pointsLength = positionAttribute.count;
const nodeTransform = renderResources.runtimeNode.transform;
let dimensions = Cartesian3_default.subtract(
positionAttribute.max,
positionAttribute.min,
scratchDimensions
);
dimensions = Matrix4_default.multiplyByPointAsVector(
nodeTransform,
dimensions,
scratchDimensions
);
const volume = dimensions.x * dimensions.y * dimensions.z;
const geometricErrorEstimate = Math_default.cbrt(volume / pointsLength);
return geometricErrorEstimate;
}
var scratchShaderFunctionInfo = {
colorStyleFunction: void 0,
showStyleFunction: void 0,
pointSizeStyleFunction: void 0,
styleTranslucent: false
};
var builtinVariableSubstitutionMap = {
POSITION: "attributes.positionMC",
POSITION_ABSOLUTE: "v_positionWC",
COLOR: "attributes.color_0",
NORMAL: "attributes.normalMC"
};
function getVariableSubstitutionMap(propertyAttributes) {
const variableSubstitutionMap = clone_default(builtinVariableSubstitutionMap);
if (!defined_default(propertyAttributes)) {
return variableSubstitutionMap;
}
for (let i = 0; i < propertyAttributes.length; i++) {
const propertyAttribute = propertyAttributes[i];
const properties = propertyAttribute.properties;
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId)) {
variableSubstitutionMap[propertyId] = `metadata.${propertyId}`;
}
}
}
return variableSubstitutionMap;
}
var parameterList = "ProcessedAttributes attributes, Metadata metadata, float tiles3d_tileset_time";
function getStyleShaderFunctionInfo(style, variableSubstitutionMap) {
const info = scratchShaderFunctionInfo;
const shaderState = {
translucent: false
};
info.colorStyleFunction = style.getColorShaderFunction(
`getColorFromStyle(${parameterList})`,
variableSubstitutionMap,
shaderState
);
info.showStyleFunction = style.getShowShaderFunction(
`getShowFromStyle(${parameterList})`,
variableSubstitutionMap,
shaderState
);
info.pointSizeStyleFunction = style.getPointSizeShaderFunction(
`getPointSizeFromStyle(${parameterList})`,
variableSubstitutionMap,
shaderState
);
info.styleTranslucent = defined_default(info.colorStyleFunction) && shaderState.translucent;
return info;
}
function addShaderFunctionsAndDefines(shaderBuilder, shaderFunctionInfo) {
const colorStyleFunction = shaderFunctionInfo.colorStyleFunction;
if (defined_default(colorStyleFunction)) {
shaderBuilder.addDefine(
"HAS_POINT_CLOUD_COLOR_STYLE",
void 0,
ShaderDestination_default.BOTH
);
shaderBuilder.addVertexLines(colorStyleFunction);
shaderBuilder.addVarying("vec4", "v_pointCloudColor");
}
const showStyleFunction = shaderFunctionInfo.showStyleFunction;
if (defined_default(showStyleFunction)) {
shaderBuilder.addDefine(
"HAS_POINT_CLOUD_SHOW_STYLE",
void 0,
ShaderDestination_default.BOTH
);
shaderBuilder.addVertexLines(showStyleFunction);
shaderBuilder.addVarying("float", "v_pointCloudShow");
}
const pointSizeStyleFunction = shaderFunctionInfo.pointSizeStyleFunction;
if (defined_default(pointSizeStyleFunction)) {
shaderBuilder.addDefine(
"HAS_POINT_CLOUD_POINT_SIZE_STYLE",
void 0,
ShaderDestination_default.VERTEX
);
shaderBuilder.addVertexLines(pointSizeStyleFunction);
}
}
function getBuiltinPropertyNames(source, propertyNames) {
const regex = /attributes\.(\w+)/g;
let matches = regex.exec(source);
while (matches !== null) {
const name = matches[1];
if (propertyNames.indexOf(name) === -1) {
propertyNames.push(name);
}
matches = regex.exec(source);
}
}
function getPropertyNames(shaderFunctionInfo) {
const colorStyleFunction = shaderFunctionInfo.colorStyleFunction;
const showStyleFunction = shaderFunctionInfo.showStyleFunction;
const pointSizeStyleFunction = shaderFunctionInfo.pointSizeStyleFunction;
const builtinPropertyNames = [];
if (defined_default(colorStyleFunction)) {
getBuiltinPropertyNames(colorStyleFunction, builtinPropertyNames);
}
if (defined_default(showStyleFunction)) {
getBuiltinPropertyNames(showStyleFunction, builtinPropertyNames);
}
if (defined_default(pointSizeStyleFunction)) {
getBuiltinPropertyNames(pointSizeStyleFunction, builtinPropertyNames);
}
return builtinPropertyNames;
}
var PointCloudStylingPipelineStage_default = PointCloudStylingPipelineStage;
// packages/engine/Source/Scene/Model/PrimitiveOutlinePipelineStage.js
var import_InlineWorkers703 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/PrimitiveOutlineStageVS.js
var import_InlineWorkers701 = __toESM(require_InlineWorkers(), 1);
var PrimitiveOutlineStageVS_default = "void primitiveOutlineStage() {\n v_outlineCoordinates = a_outlineCoordinates;\n}\n";
// packages/engine/Source/Shaders/Model/PrimitiveOutlineStageFS.js
var import_InlineWorkers702 = __toESM(require_InlineWorkers(), 1);
var PrimitiveOutlineStageFS_default = "void primitiveOutlineStage(inout czm_modelMaterial material) {\n if (!model_showOutline) {\n return;\n }\n\n float outlineX = \n texture(model_outlineTexture, vec2(v_outlineCoordinates.x, 0.5)).r;\n float outlineY = \n texture(model_outlineTexture, vec2(v_outlineCoordinates.y, 0.5)).r;\n float outlineZ = \n texture(model_outlineTexture, vec2(v_outlineCoordinates.z, 0.5)).r;\n float outlineness = max(outlineX, max(outlineY, outlineZ));\n\n material.diffuse = mix(material.diffuse, model_outlineColor.rgb, model_outlineColor.a * outlineness);\n}\n\n";
// packages/engine/Source/Scene/Model/PrimitiveOutlinePipelineStage.js
var PrimitiveOutlinePipelineStage = {
name: "PrimitiveOutlinePipelineStage"
// Helps with debugging
};
PrimitiveOutlinePipelineStage.process = function(renderResources, primitive, frameState) {
const shaderBuilder = renderResources.shaderBuilder;
const uniformMap2 = renderResources.uniformMap;
shaderBuilder.addDefine(
"HAS_PRIMITIVE_OUTLINE",
void 0,
ShaderDestination_default.BOTH
);
shaderBuilder.addAttribute("vec3", "a_outlineCoordinates");
shaderBuilder.addVarying("vec3", "v_outlineCoordinates");
const outlineCoordinates = primitive.outlineCoordinates;
const vertexAttribute = {
index: renderResources.attributeIndex++,
vertexBuffer: outlineCoordinates.buffer,
componentsPerAttribute: AttributeType_default.getNumberOfComponents(
outlineCoordinates.type
),
componentDatatype: outlineCoordinates.componentDatatype,
offsetInBytes: outlineCoordinates.byteOffset,
strideInBytes: outlineCoordinates.byteStride,
normalize: outlineCoordinates.normalized
};
renderResources.attributes.push(vertexAttribute);
shaderBuilder.addUniform(
"sampler2D",
"model_outlineTexture",
ShaderDestination_default.FRAGMENT
);
const outlineTexture = PrimitiveOutlineGenerator_default.createTexture(
frameState.context
);
uniformMap2.model_outlineTexture = function() {
return outlineTexture;
};
const model = renderResources.model;
shaderBuilder.addUniform(
"vec4",
"model_outlineColor",
ShaderDestination_default.FRAGMENT
);
uniformMap2.model_outlineColor = function() {
return model.outlineColor;
};
shaderBuilder.addUniform(
"bool",
"model_showOutline",
ShaderDestination_default.FRAGMENT
);
uniformMap2.model_showOutline = function() {
return model.showOutline;
};
shaderBuilder.addVertexLines(PrimitiveOutlineStageVS_default);
shaderBuilder.addFragmentLines(PrimitiveOutlineStageFS_default);
};
var PrimitiveOutlinePipelineStage_default = PrimitiveOutlinePipelineStage;
// packages/engine/Source/Scene/Model/PrimitiveStatisticsPipelineStage.js
var import_InlineWorkers704 = __toESM(require_InlineWorkers(), 1);
var PrimitiveStatisticsPipelineStage = {
name: "PrimitiveStatisticsPipelineStage",
// Helps with debugging
// Expose some methods for testing
_countGeometry: countGeometry,
_count2DPositions: count2DPositions,
_countMorphTargetAttributes: countMorphTargetAttributes,
_countMaterialTextures: countMaterialTextures,
_countFeatureIdTextures: countFeatureIdTextures,
_countBinaryMetadata: countBinaryMetadata
};
PrimitiveStatisticsPipelineStage.process = function(renderResources, primitive, frameState) {
const model = renderResources.model;
const statistics2 = model.statistics;
countGeometry(statistics2, primitive);
count2DPositions(statistics2, renderResources.runtimePrimitive);
countMorphTargetAttributes(statistics2, primitive);
countMaterialTextures(statistics2, primitive.material);
countFeatureIdTextures(statistics2, primitive.featureIds);
countBinaryMetadata(statistics2, model);
};
function countGeometry(statistics2, primitive) {
const indicesCount = defined_default(primitive.indices) ? primitive.indices.count : ModelUtility_default.getAttributeBySemantic(primitive, "POSITION").count;
const primitiveType = primitive.primitiveType;
if (primitiveType === PrimitiveType_default.POINTS) {
statistics2.pointsLength += indicesCount;
} else if (PrimitiveType_default.isTriangles(primitiveType)) {
statistics2.trianglesLength += countTriangles(primitiveType, indicesCount);
}
const attributes = primitive.attributes;
const length2 = attributes.length;
for (let i = 0; i < length2; i++) {
const attribute = attributes[i];
if (defined_default(attribute.buffer)) {
const hasCpuCopy = defined_default(attribute.typedArray);
statistics2.addBuffer(attribute.buffer, hasCpuCopy);
}
}
const outlineCoordinates = primitive.outlineCoordinates;
if (defined_default(outlineCoordinates) && defined_default(outlineCoordinates.buffer)) {
const hasCpuCopy = false;
statistics2.addBuffer(outlineCoordinates.buffer, hasCpuCopy);
}
const indices = primitive.indices;
if (defined_default(indices) && defined_default(indices.buffer)) {
const hasCpuCopy = defined_default(indices.typedArray);
statistics2.addBuffer(indices.buffer, hasCpuCopy);
}
}
function countTriangles(primitiveType, indicesCount) {
switch (primitiveType) {
case PrimitiveType_default.TRIANGLES:
return indicesCount / 3;
case PrimitiveType_default.TRIANGLE_STRIP:
case PrimitiveType_default.TRIANGLE_FAN:
return Math.max(indicesCount - 2, 0);
default:
return 0;
}
}
function count2DPositions(statistics2, runtimePrimitive) {
const buffer2D = runtimePrimitive.positionBuffer2D;
if (defined_default(buffer2D)) {
const hasCpuCopy = true;
statistics2.addBuffer(buffer2D, hasCpuCopy);
}
}
function countMorphTargetAttributes(statistics2, primitive) {
const morphTargets = primitive.morphTargets;
if (!defined_default(morphTargets)) {
return;
}
const hasCpuCopy = false;
const morphTargetsLength = morphTargets.length;
for (let i = 0; i < morphTargetsLength; i++) {
const attributes = morphTargets[i].attributes;
const attributesLength = attributes.length;
for (let j = 0; j < attributesLength; j++) {
const attribute = attributes[j];
if (defined_default(attribute.buffer)) {
statistics2.addBuffer(attribute.buffer, hasCpuCopy);
}
}
}
}
function countMaterialTextures(statistics2, material) {
const textureReaders = getAllTextureReaders(material);
const length2 = textureReaders.length;
for (let i = 0; i < length2; i++) {
const textureReader = textureReaders[i];
if (defined_default(textureReader) && defined_default(textureReader.texture)) {
statistics2.addTexture(textureReader.texture);
}
}
}
function getAllTextureReaders(material) {
const metallicRoughness = material.metallicRoughness;
const textureReaders = [
material.emissiveTexture,
material.normalTexture,
material.occlusionTexture,
metallicRoughness.baseColorTexture,
metallicRoughness.metallicRoughnessTexture
];
const specularGlossiness = material.specularGlossiness;
if (defined_default(specularGlossiness)) {
textureReaders.push(specularGlossiness.diffuseTexture);
textureReaders.push(specularGlossiness.specularGlossinessTexture);
}
return textureReaders;
}
function countFeatureIdTextures(statistics2, featureIdSets) {
const length2 = featureIdSets.length;
for (let i = 0; i < length2; i++) {
const featureIds = featureIdSets[i];
if (featureIds instanceof ModelComponents_default.FeatureIdTexture) {
const textureReader = featureIds.textureReader;
if (defined_default(textureReader.texture)) {
statistics2.addTexture(textureReader.texture);
}
}
}
}
function countBinaryMetadata(statistics2, model) {
const structuralMetadata = model.structuralMetadata;
if (defined_default(structuralMetadata)) {
countPropertyTextures(statistics2, structuralMetadata);
statistics2.propertyTablesByteLength += structuralMetadata.propertyTablesByteLength;
}
const featureTables = model.featureTables;
if (!defined_default(featureTables)) {
return;
}
const length2 = featureTables.length;
for (let i = 0; i < length2; i++) {
const featureTable = featureTables[i];
statistics2.addBatchTexture(featureTable.batchTexture);
}
}
function countPropertyTextures(statistics2, structuralMetadata) {
const propertyTextures = structuralMetadata.propertyTextures;
if (!defined_default(propertyTextures)) {
return;
}
const texturesLength = propertyTextures.length;
for (let i = 0; i < texturesLength; i++) {
const propertyTexture = propertyTextures[i];
const properties = propertyTexture.properties;
for (const propertyId in properties) {
if (properties.hasOwnProperty(propertyId)) {
const property = properties[propertyId];
const textureReader = property.textureReader;
if (defined_default(textureReader.texture)) {
statistics2.addTexture(textureReader.texture);
}
}
}
}
}
var PrimitiveStatisticsPipelineStage_default = PrimitiveStatisticsPipelineStage;
// packages/engine/Source/Scene/Model/SceneMode2DPipelineStage.js
var import_InlineWorkers705 = __toESM(require_InlineWorkers(), 1);
var scratchModelMatrix = new Matrix4_default();
var scratchModelView2D = new Matrix4_default();
var SceneMode2DPipelineStage = {
name: "SceneMode2DPipelineStage"
// Helps with debugging
};
SceneMode2DPipelineStage.process = function(renderResources, primitive, frameState) {
const positionAttribute = ModelUtility_default.getAttributeBySemantic(
primitive,
VertexAttributeSemantic_default.POSITION
);
const shaderBuilder = renderResources.shaderBuilder;
const model = renderResources.model;
const modelMatrix = model.sceneGraph.computedModelMatrix;
const nodeComputedTransform = renderResources.runtimeNode.computedTransform;
const computedModelMatrix = Matrix4_default.multiplyTransformation(
modelMatrix,
nodeComputedTransform,
scratchModelMatrix
);
const boundingSphere2D = computeBoundingSphere2D(
renderResources,
computedModelMatrix,
frameState
);
const runtimePrimitive = renderResources.runtimePrimitive;
runtimePrimitive.boundingSphere2D = boundingSphere2D;
const instances = renderResources.runtimeNode.node.instances;
if (defined_default(instances)) {
return;
}
if (defined_default(positionAttribute.typedArray)) {
const buffer2D = createPositionBufferFor2D(
positionAttribute,
computedModelMatrix,
boundingSphere2D,
frameState
);
runtimePrimitive.positionBuffer2D = buffer2D;
model._modelResources.push(buffer2D);
positionAttribute.typedArray = void 0;
}
shaderBuilder.addDefine(
"USE_2D_POSITIONS",
void 0,
ShaderDestination_default.VERTEX
);
shaderBuilder.addUniform("mat4", "u_modelView2D", ShaderDestination_default.VERTEX);
const modelMatrix2D = Matrix4_default.fromTranslation(
boundingSphere2D.center,
new Matrix4_default()
);
const context = frameState.context;
const uniformMap2 = {
u_modelView2D: function() {
return Matrix4_default.multiplyTransformation(
context.uniformState.view,
modelMatrix2D,
scratchModelView2D
);
}
};
renderResources.uniformMap = combine_default(uniformMap2, renderResources.uniformMap);
};
var scratchProjectedMin2 = new Cartesian3_default();
var scratchProjectedMax2 = new Cartesian3_default();
function computeBoundingSphere2D(renderResources, modelMatrix, frameState) {
const transformedPositionMin = Matrix4_default.multiplyByPoint(
modelMatrix,
renderResources.positionMin,
scratchProjectedMin2
);
const projectedMin = SceneTransforms_default.computeActualEllipsoidPosition(
frameState,
transformedPositionMin,
transformedPositionMin
);
const transformedPositionMax = Matrix4_default.multiplyByPoint(
modelMatrix,
renderResources.positionMax,
scratchProjectedMax2
);
const projectedMax = SceneTransforms_default.computeActualEllipsoidPosition(
frameState,
transformedPositionMax,
transformedPositionMax
);
return BoundingSphere_default.fromCornerPoints(
projectedMin,
projectedMax,
new BoundingSphere_default()
);
}
var scratchPosition3 = new Cartesian3_default();
function dequantizePositionsTypedArray(typedArray, quantization) {
const length2 = typedArray.length;
const dequantizedArray = new Float32Array(length2);
const quantizedVolumeOffset = quantization.quantizedVolumeOffset;
const quantizedVolumeStepSize = quantization.quantizedVolumeStepSize;
for (let i = 0; i < length2; i += 3) {
const initialPosition = Cartesian3_default.fromArray(
typedArray,
i,
scratchPosition3
);
const scaledPosition = Cartesian3_default.multiplyComponents(
initialPosition,
quantizedVolumeStepSize,
initialPosition
);
const dequantizedPosition = Cartesian3_default.add(
scaledPosition,
quantizedVolumeOffset,
scaledPosition
);
dequantizedArray[i] = dequantizedPosition.x;
dequantizedArray[i + 1] = dequantizedPosition.y;
dequantizedArray[i + 2] = dequantizedPosition.z;
}
return dequantizedArray;
}
function createPositionsTypedArrayFor2D(attribute, modelMatrix, referencePoint, frameState) {
let result;
if (defined_default(attribute.quantization)) {
result = dequantizePositionsTypedArray(
attribute.typedArray,
attribute.quantization
);
} else {
result = attribute.typedArray.slice();
}
const startIndex = attribute.byteOffset / Float32Array.BYTES_PER_ELEMENT;
const length2 = result.length;
const stride = defined_default(attribute.byteStride) ? attribute.byteStride / Float32Array.BYTES_PER_ELEMENT : 3;
for (let i = startIndex; i < length2; i += stride) {
const initialPosition = Cartesian3_default.fromArray(result, i, scratchPosition3);
if (isNaN(initialPosition.x) || isNaN(initialPosition.y) || isNaN(initialPosition.z)) {
continue;
}
const transformedPosition = Matrix4_default.multiplyByPoint(
modelMatrix,
initialPosition,
initialPosition
);
const projectedPosition2 = SceneTransforms_default.computeActualEllipsoidPosition(
frameState,
transformedPosition,
transformedPosition
);
const relativePosition = Cartesian3_default.subtract(
projectedPosition2,
referencePoint,
projectedPosition2
);
result[i] = relativePosition.x;
result[i + 1] = relativePosition.y;
result[i + 2] = relativePosition.z;
}
return result;
}
function createPositionBufferFor2D(positionAttribute, modelMatrix, boundingSphere2D, frameState) {
const frameStateCV = clone_default(frameState);
frameStateCV.mode = SceneMode_default.COLUMBUS_VIEW;
const referencePoint = boundingSphere2D.center;
const projectedPositions = createPositionsTypedArrayFor2D(
positionAttribute,
modelMatrix,
referencePoint,
frameStateCV
);
const buffer2 = Buffer_default.createVertexBuffer({
context: frameState.context,
typedArray: projectedPositions,
usage: BufferUsage_default.STATIC_DRAW
});
buffer2.vertexArrayDestroyable = false;
return buffer2;
}
var SceneMode2DPipelineStage_default = SceneMode2DPipelineStage;
// packages/engine/Source/Scene/Model/SkinningPipelineStage.js
var import_InlineWorkers707 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/SkinningStageVS.js
var import_InlineWorkers706 = __toESM(require_InlineWorkers(), 1);
var SkinningStageVS_default = "void skinningStage(inout ProcessedAttributes attributes) \n{\n mat4 skinningMatrix = getSkinningMatrix();\n mat3 skinningMatrixMat3 = mat3(skinningMatrix);\n\n vec4 positionMC = vec4(attributes.positionMC, 1.0);\n attributes.positionMC = vec3(skinningMatrix * positionMC);\n\n #ifdef HAS_NORMALS\n vec3 normalMC = attributes.normalMC;\n attributes.normalMC = skinningMatrixMat3 * normalMC;\n #endif\n\n #ifdef HAS_TANGENTS\n vec3 tangentMC = attributes.tangentMC;\n attributes.tangentMC = skinningMatrixMat3 * tangentMC;\n #endif\n}";
// packages/engine/Source/Scene/Model/SkinningPipelineStage.js
var SkinningPipelineStage = {
name: "SkinningPipelineStage",
// Helps with debugging
FUNCTION_ID_GET_SKINNING_MATRIX: "getSkinningMatrix",
FUNCTION_SIGNATURE_GET_SKINNING_MATRIX: "mat4 getSkinningMatrix()"
};
SkinningPipelineStage.process = function(renderResources, primitive) {
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addDefine("HAS_SKINNING", void 0, ShaderDestination_default.VERTEX);
addGetSkinningMatrixFunction(shaderBuilder, primitive);
const runtimeNode = renderResources.runtimeNode;
const jointMatrices = runtimeNode.computedJointMatrices;
shaderBuilder.addUniform(
"mat4",
`u_jointMatrices[${jointMatrices.length}]`,
ShaderDestination_default.VERTEX
);
shaderBuilder.addVertexLines(SkinningStageVS_default);
const uniformMap2 = {
u_jointMatrices: function() {
return runtimeNode.computedJointMatrices;
}
};
renderResources.uniformMap = combine_default(uniformMap2, renderResources.uniformMap);
};
function getMaximumAttributeSetIndex(primitive) {
let setIndex = -1;
const attributes = primitive.attributes;
const length2 = attributes.length;
for (let i = 0; i < length2; i++) {
const attribute = attributes[i];
const isJointsOrWeights = attribute.semantic === VertexAttributeSemantic_default.JOINTS || attribute.semantic === VertexAttributeSemantic_default.WEIGHTS;
if (!isJointsOrWeights) {
continue;
}
setIndex = Math.max(setIndex, attribute.setIndex);
}
return setIndex;
}
function addGetSkinningMatrixFunction(shaderBuilder, primitive) {
shaderBuilder.addFunction(
SkinningPipelineStage.FUNCTION_ID_GET_SKINNING_MATRIX,
SkinningPipelineStage.FUNCTION_SIGNATURE_GET_SKINNING_MATRIX,
ShaderDestination_default.VERTEX
);
const initialLine = "mat4 skinnedMatrix = mat4(0);";
shaderBuilder.addFunctionLines(
SkinningPipelineStage.FUNCTION_ID_GET_SKINNING_MATRIX,
[initialLine]
);
let setIndex;
let componentIndex;
const componentStrings = ["x", "y", "z", "w"];
const maximumSetIndex = getMaximumAttributeSetIndex(primitive);
for (setIndex = 0; setIndex <= maximumSetIndex; setIndex++) {
for (componentIndex = 0; componentIndex <= 3; componentIndex++) {
const component = componentStrings[componentIndex];
const line = `skinnedMatrix += a_weights_${setIndex}.${component} * u_jointMatrices[int(a_joints_${setIndex}.${component})];`;
shaderBuilder.addFunctionLines(
SkinningPipelineStage.FUNCTION_ID_GET_SKINNING_MATRIX,
[line]
);
}
}
const returnLine = "return skinnedMatrix;";
shaderBuilder.addFunctionLines(
SkinningPipelineStage.FUNCTION_ID_GET_SKINNING_MATRIX,
[returnLine]
);
}
var SkinningPipelineStage_default = SkinningPipelineStage;
// packages/engine/Source/Scene/Model/VerticalExaggerationPipelineStage.js
var import_InlineWorkers709 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/VerticalExaggerationStageVS.js
var import_InlineWorkers708 = __toESM(require_InlineWorkers(), 1);
var VerticalExaggerationStageVS_default = "void verticalExaggerationStage(\n inout ProcessedAttributes attributes\n) {\n // Compute the distance from the camera to the local center of curvature.\n vec4 vertexPositionENU = czm_modelToEnu * vec4(attributes.positionMC, 1.0);\n vec2 vertexAzimuth = normalize(vertexPositionENU.xy);\n // Curvature = 1 / radius of curvature.\n float azimuthalCurvature = dot(vertexAzimuth * vertexAzimuth, czm_eyeEllipsoidCurvature);\n float eyeToCenter = 1.0 / azimuthalCurvature + czm_eyeHeight;\n\n // Compute the approximate ellipsoid normal at the vertex position.\n // Uses a circular approximation for the Earth curvature along the geodesic.\n vec3 vertexPositionEC = (czm_modelView * vec4(attributes.positionMC, 1.0)).xyz;\n vec3 centerToVertex = eyeToCenter * czm_eyeEllipsoidNormalEC + vertexPositionEC;\n vec3 vertexNormal = normalize(centerToVertex);\n\n // Estimate the (sine of the) angle between the camera direction and the vertex normal\n float verticalDistance = dot(vertexPositionEC, czm_eyeEllipsoidNormalEC);\n float horizontalDistance = length(vertexPositionEC - verticalDistance * czm_eyeEllipsoidNormalEC);\n float sinTheta = horizontalDistance / (eyeToCenter + verticalDistance);\n bool isSmallAngle = clamp(sinTheta, 0.0, 0.05) == sinTheta;\n\n // Approximate the change in height above the ellipsoid, from camera to vertex position.\n float exactVersine = 1.0 - dot(czm_eyeEllipsoidNormalEC, vertexNormal);\n float smallAngleVersine = 0.5 * sinTheta * sinTheta;\n float versine = isSmallAngle ? smallAngleVersine : exactVersine;\n float dHeight = dot(vertexPositionEC, vertexNormal) - eyeToCenter * versine;\n float vertexHeight = czm_eyeHeight + dHeight;\n\n // Transform the approximate vertex normal to model coordinates.\n vec3 vertexNormalMC = (czm_inverseModelView * vec4(vertexNormal, 0.0)).xyz;\n vertexNormalMC = normalize(vertexNormalMC);\n\n // Compute the exaggeration and apply it along the approximate vertex normal.\n float stretch = u_verticalExaggerationAndRelativeHeight.x;\n float shift = u_verticalExaggerationAndRelativeHeight.y;\n float exaggeration = (vertexHeight - shift) * (stretch - 1.0);\n attributes.positionMC += exaggeration * vertexNormalMC;\n}\n";
// packages/engine/Source/Scene/Model/VerticalExaggerationPipelineStage.js
var VerticalExaggerationPipelineStage = {
name: "VerticalExaggerationPipelineStage"
// Helps with debugging
};
var scratchExaggerationUniform = new Cartesian2_default();
VerticalExaggerationPipelineStage.process = function(renderResources, primitive, frameState) {
const { shaderBuilder, uniformMap: uniformMap2 } = renderResources;
shaderBuilder.addVertexLines(VerticalExaggerationStageVS_default);
shaderBuilder.addDefine(
"HAS_VERTICAL_EXAGGERATION",
void 0,
ShaderDestination_default.VERTEX
);
shaderBuilder.addUniform(
"vec2",
"u_verticalExaggerationAndRelativeHeight",
ShaderDestination_default.VERTEX
);
uniformMap2.u_verticalExaggerationAndRelativeHeight = function() {
return Cartesian2_default.fromElements(
frameState.verticalExaggeration,
frameState.verticalExaggerationRelativeHeight,
scratchExaggerationUniform
);
};
};
var VerticalExaggerationPipelineStage_default = VerticalExaggerationPipelineStage;
// packages/engine/Source/Scene/Model/WireframePipelineStage.js
var import_InlineWorkers711 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/WireframeIndexGenerator.js
var import_InlineWorkers710 = __toESM(require_InlineWorkers(), 1);
var WireframeIndexGenerator = {};
function createWireframeFromTriangles(vertexCount) {
const wireframeIndices = IndexDatatype_default.createTypedArray(
vertexCount,
vertexCount * 2
);
const length2 = vertexCount;
let index = 0;
for (let i = 0; i < length2; i += 3) {
wireframeIndices[index++] = i;
wireframeIndices[index++] = i + 1;
wireframeIndices[index++] = i + 1;
wireframeIndices[index++] = i + 2;
wireframeIndices[index++] = i + 2;
wireframeIndices[index++] = i;
}
return wireframeIndices;
}
function createWireframeFromTriangleIndices(vertexCount, originalIndices) {
const originalIndicesCount = originalIndices.length;
const wireframeIndices = IndexDatatype_default.createTypedArray(
vertexCount,
originalIndicesCount * 2
);
let index = 0;
for (let i = 0; i < originalIndicesCount; i += 3) {
const point0 = originalIndices[i];
const point1 = originalIndices[i + 1];
const point2 = originalIndices[i + 2];
wireframeIndices[index++] = point0;
wireframeIndices[index++] = point1;
wireframeIndices[index++] = point1;
wireframeIndices[index++] = point2;
wireframeIndices[index++] = point2;
wireframeIndices[index++] = point0;
}
return wireframeIndices;
}
function createWireframeFromTriangleStrip(vertexCount) {
const numberOfTriangles = vertexCount - 2;
const wireframeIndicesCount = 2 + numberOfTriangles * 4;
const wireframeIndices = IndexDatatype_default.createTypedArray(
vertexCount,
wireframeIndicesCount
);
let index = 0;
wireframeIndices[index++] = 0;
wireframeIndices[index++] = 1;
for (let i = 0; i < numberOfTriangles; i++) {
wireframeIndices[index++] = i + 1;
wireframeIndices[index++] = i + 2;
wireframeIndices[index++] = i + 2;
wireframeIndices[index++] = i;
}
return wireframeIndices;
}
function createWireframeFromTriangleStripIndices(vertexCount, originalIndices) {
const originalIndicesCount = originalIndices.length;
const numberOfTriangles = originalIndicesCount - 2;
const wireframeIndicesCount = 2 + numberOfTriangles * 4;
const wireframeIndices = IndexDatatype_default.createTypedArray(
vertexCount,
wireframeIndicesCount
);
let index = 0;
wireframeIndices[index++] = originalIndices[0];
wireframeIndices[index++] = originalIndices[1];
for (let i = 0; i < numberOfTriangles; i++) {
const point0 = originalIndices[i];
const point1 = originalIndices[i + 1];
const point2 = originalIndices[i + 2];
wireframeIndices[index++] = point1;
wireframeIndices[index++] = point2;
wireframeIndices[index++] = point2;
wireframeIndices[index++] = point0;
}
return wireframeIndices;
}
function createWireframeFromTriangleFan(vertexCount) {
const numberOfTriangles = vertexCount - 2;
const wireframeIndicesCount = 2 + numberOfTriangles * 4;
const wireframeIndices = IndexDatatype_default.createTypedArray(
vertexCount,
wireframeIndicesCount
);
let index = 0;
wireframeIndices[index++] = 0;
wireframeIndices[index++] = 1;
for (let i = 0; i < numberOfTriangles; i++) {
wireframeIndices[index++] = i + 1;
wireframeIndices[index++] = i + 2;
wireframeIndices[index++] = i + 2;
wireframeIndices[index++] = 0;
}
return wireframeIndices;
}
function createWireframeFromTriangleFanIndices(vertexCount, originalIndices) {
const originalIndicesCount = originalIndices.length;
const numberOfTriangles = originalIndicesCount - 2;
const wireframeIndicesCount = 2 + numberOfTriangles * 4;
const wireframeIndices = IndexDatatype_default.createTypedArray(
vertexCount,
wireframeIndicesCount
);
let index = 0;
const firstPoint = originalIndices[0];
wireframeIndices[index++] = firstPoint;
wireframeIndices[index++] = originalIndices[1];
for (let i = 0; i < numberOfTriangles; i++) {
const point1 = originalIndices[i + 1];
const point2 = originalIndices[i + 2];
wireframeIndices[index++] = point1;
wireframeIndices[index++] = point2;
wireframeIndices[index++] = point2;
wireframeIndices[index++] = firstPoint;
}
return wireframeIndices;
}
WireframeIndexGenerator.createWireframeIndices = function(primitiveType, vertexCount, originalIndices) {
const hasOriginalIndices = defined_default(originalIndices);
if (primitiveType === PrimitiveType_default.TRIANGLES) {
return hasOriginalIndices ? createWireframeFromTriangleIndices(vertexCount, originalIndices) : createWireframeFromTriangles(vertexCount);
}
if (primitiveType === PrimitiveType_default.TRIANGLE_STRIP) {
return hasOriginalIndices ? createWireframeFromTriangleStripIndices(vertexCount, originalIndices) : createWireframeFromTriangleStrip(vertexCount);
}
if (primitiveType === PrimitiveType_default.TRIANGLE_FAN) {
return hasOriginalIndices ? createWireframeFromTriangleFanIndices(vertexCount, originalIndices) : createWireframeFromTriangleFan(vertexCount);
}
return void 0;
};
WireframeIndexGenerator.getWireframeIndicesCount = function(primitiveType, originalCount) {
if (primitiveType === PrimitiveType_default.TRIANGLES) {
return originalCount * 2;
}
if (primitiveType === PrimitiveType_default.TRIANGLE_STRIP || primitiveType === PrimitiveType_default.TRIANGLE_FAN) {
const numberOfTriangles = originalCount - 2;
return 2 + numberOfTriangles * 4;
}
return originalCount;
};
var WireframeIndexGenerator_default = WireframeIndexGenerator;
// packages/engine/Source/Scene/Model/WireframePipelineStage.js
var WireframePipelineStage = {
name: "WireframePipelineStage"
// Helps with debugging
};
WireframePipelineStage.process = function(renderResources, primitive, frameState) {
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addDefine(
"HAS_WIREFRAME",
void 0,
ShaderDestination_default.FRAGMENT
);
const model = renderResources.model;
const wireframeIndexBuffer = createWireframeIndexBuffer(
primitive,
renderResources.indices,
frameState
);
model._pipelineResources.push(wireframeIndexBuffer);
renderResources.wireframeIndexBuffer = wireframeIndexBuffer;
const hasCpuCopy = false;
model.statistics.addBuffer(wireframeIndexBuffer, hasCpuCopy);
const originalPrimitiveType = renderResources.primitiveType;
const originalCount = renderResources.count;
renderResources.primitiveType = PrimitiveType_default.LINES;
renderResources.count = WireframeIndexGenerator_default.getWireframeIndicesCount(
originalPrimitiveType,
originalCount
);
};
function createWireframeIndexBuffer(primitive, indices, frameState) {
const positionAttribute = ModelUtility_default.getAttributeBySemantic(
primitive,
VertexAttributeSemantic_default.POSITION
);
const vertexCount = positionAttribute.count;
const webgl2 = frameState.context.webgl2;
let originalIndices;
if (defined_default(indices)) {
const indicesBuffer = indices.buffer;
const indicesCount = indices.count;
if (defined_default(indicesBuffer) && webgl2) {
const useUint8Array = indicesBuffer.sizeInBytes === indicesCount;
originalIndices = useUint8Array ? new Uint8Array(indicesCount) : IndexDatatype_default.createTypedArray(vertexCount, indicesCount);
indicesBuffer.getBufferData(originalIndices);
} else {
originalIndices = indices.typedArray;
}
}
const primitiveType = primitive.primitiveType;
const wireframeIndices = WireframeIndexGenerator_default.createWireframeIndices(
primitiveType,
vertexCount,
originalIndices
);
const indexDatatype = IndexDatatype_default.fromSizeInBytes(
wireframeIndices.BYTES_PER_ELEMENT
);
return Buffer_default.createIndexBuffer({
context: frameState.context,
typedArray: wireframeIndices,
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype
});
}
var WireframePipelineStage_default = WireframePipelineStage;
// packages/engine/Source/Scene/Model/ModelRuntimePrimitive.js
function ModelRuntimePrimitive(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const primitive = options.primitive;
const node = options.node;
const model = options.model;
Check_default.typeOf.object("options.primitive", primitive);
Check_default.typeOf.object("options.node", node);
Check_default.typeOf.object("options.model", model);
this.primitive = primitive;
this.node = node;
this.model = model;
this.pipelineStages = [];
this.drawCommand = void 0;
this.boundingSphere = void 0;
this.boundingSphere2D = void 0;
this.positionBuffer2D = void 0;
this.batchLengths = void 0;
this.batchOffsets = void 0;
this.updateStages = [];
}
ModelRuntimePrimitive.prototype.configurePipeline = function(frameState) {
const pipelineStages = this.pipelineStages;
pipelineStages.length = 0;
const primitive = this.primitive;
const node = this.node;
const model = this.model;
const customShader = model.customShader;
const style = model.style;
const useWebgl2 = frameState.context.webgl2;
const mode2 = frameState.mode;
const use2D = mode2 !== SceneMode_default.SCENE3D && !frameState.scene3DOnly && model._projectTo2D;
const hasVerticalExaggeration = frameState.verticalExaggeration !== 1 && model.hasVerticalExaggeration;
const hasMorphTargets = defined_default(primitive.morphTargets) && primitive.morphTargets.length > 0;
const hasSkinning = defined_default(node.skin);
const hasImageryLayers = defined_default(model.imageryLayers);
const hasCustomShader = defined_default(customShader);
const hasCustomFragmentShader = hasCustomShader && defined_default(customShader.fragmentShaderText);
const materialsEnabled = !hasCustomFragmentShader || customShader.mode !== CustomShaderMode_default.REPLACE_MATERIAL;
const hasQuantization = ModelUtility_default.hasQuantizedAttributes(
primitive.attributes
);
const generateWireframeIndices = model.debugWireframe && PrimitiveType_default.isTriangles(primitive.primitiveType) && // Generating index buffers for wireframes is always possible in WebGL2.
// However, this will only work in WebGL1 if the model was constructed with
// enableDebugWireframe set to true.
(model._enableDebugWireframe || useWebgl2);
const pointCloudShading = model.pointCloudShading;
const hasAttenuation = defined_default(pointCloudShading) && pointCloudShading.attenuation;
const hasPointCloudBackFaceCulling = defined_default(pointCloudShading) && pointCloudShading.backFaceCulling;
const hasPointCloudStyle = primitive.primitiveType === PrimitiveType_default.POINTS && (defined_default(style) || hasAttenuation || hasPointCloudBackFaceCulling);
const hasOutlines = model._enableShowOutline && defined_default(primitive.outlineCoordinates);
const featureIdFlags = inspectFeatureIds(model, node, primitive);
const hasClassification = defined_default(model.classificationType);
if (use2D) {
pipelineStages.push(SceneMode2DPipelineStage_default);
}
pipelineStages.push(GeometryPipelineStage_default);
if (generateWireframeIndices) {
pipelineStages.push(WireframePipelineStage_default);
}
if (hasClassification) {
pipelineStages.push(ClassificationPipelineStage_default);
}
if (hasMorphTargets) {
pipelineStages.push(MorphTargetsPipelineStage_default);
}
if (hasSkinning) {
pipelineStages.push(SkinningPipelineStage_default);
}
if (hasPointCloudStyle) {
pipelineStages.push(PointCloudStylingPipelineStage_default);
}
if (hasQuantization) {
pipelineStages.push(DequantizationPipelineStage_default);
}
if (hasImageryLayers) {
if (hasOutlines) {
oneTimeWarning_default(
"outlines-and-draping",
"Primitive outlines disable imagery draping"
);
} else {
pipelineStages.push(ImageryPipelineStage_default);
}
}
if (materialsEnabled) {
pipelineStages.push(MaterialPipelineStage_default);
}
pipelineStages.push(FeatureIdPipelineStage_default);
pipelineStages.push(MetadataPipelineStage_default);
pipelineStages.push(MetadataPickingPipelineStage_default);
if (featureIdFlags.hasPropertyTable) {
pipelineStages.push(SelectedFeatureIdPipelineStage_default);
pipelineStages.push(BatchTexturePipelineStage_default);
pipelineStages.push(CPUStylingPipelineStage_default);
}
if (hasVerticalExaggeration) {
pipelineStages.push(VerticalExaggerationPipelineStage_default);
}
if (hasCustomShader) {
pipelineStages.push(CustomShaderPipelineStage_default);
}
pipelineStages.push(LightingPipelineStage_default);
if (model.allowPicking) {
pipelineStages.push(PickingPipelineStage_default);
}
if (hasOutlines) {
pipelineStages.push(PrimitiveOutlinePipelineStage_default);
}
pipelineStages.push(AlphaPipelineStage_default);
pipelineStages.push(PrimitiveStatisticsPipelineStage_default);
return;
};
function inspectFeatureIds(model, node, primitive) {
let featureIds;
if (defined_default(node.instances)) {
featureIds = ModelUtility_default.getFeatureIdsByLabel(
node.instances.featureIds,
model.instanceFeatureIdLabel
);
if (defined_default(featureIds)) {
return {
hasFeatureIds: true,
hasPropertyTable: defined_default(featureIds.propertyTableId)
};
}
}
featureIds = ModelUtility_default.getFeatureIdsByLabel(
primitive.featureIds,
model.featureIdLabel
);
if (defined_default(featureIds)) {
return {
hasFeatureIds: true,
hasPropertyTable: defined_default(featureIds.propertyTableId)
};
}
return {
hasFeatureIds: false,
hasPropertyTable: false
};
}
var ModelRuntimePrimitive_default = ModelRuntimePrimitive;
// packages/engine/Source/Scene/Model/ModelSkin.js
var import_InlineWorkers713 = __toESM(require_InlineWorkers(), 1);
function ModelSkin(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("options.skin", options.skin);
Check_default.typeOf.object("options.sceneGraph", options.sceneGraph);
this._sceneGraph = options.sceneGraph;
const skin = options.skin;
this._skin = skin;
this._inverseBindMatrices = void 0;
this._joints = [];
this._jointMatrices = [];
initialize11(this);
}
Object.defineProperties(ModelSkin.prototype, {
/**
* The internal skin this runtime skin represents.
*
* @memberof ModelSkin.prototype
* @type {ModelComponents.Skin}
* @readonly
*
* @private
*/
skin: {
get: function() {
return this._skin;
}
},
/**
* The scene graph this skin belongs to.
*
* @memberof ModelSkin.prototype
* @type {ModelSceneGraph}
* @readonly
*
* @private
*/
sceneGraph: {
get: function() {
return this._sceneGraph;
}
},
/**
* The inverse bind matrices of the skin.
*
* @memberof ModelSkin.prototype
* @type {Matrix4[]}
* @readonly
*
* @private
*/
inverseBindMatrices: {
get: function() {
return this._inverseBindMatrices;
}
},
/**
* The joints of the skin.
*
* @memberof ModelSkin.prototype
* @type {ModelRuntimeNode[]}
* @readonly
*
* @private
*/
joints: {
get: function() {
return this._joints;
}
},
/**
* The joint matrices for the skin, where each joint matrix is computed as
* jointMatrix = jointWorldTransform * inverseBindMatrix.
*
* Each node that references this skin is responsible for pre-multiplying its inverse
* world transform to the joint matrices for its own use.
*
* @memberof ModelSkin.prototype
* @type {Matrix4[]}
* @readonly
*
* @private
*/
jointMatrices: {
get: function() {
return this._jointMatrices;
}
}
});
function initialize11(runtimeSkin) {
const skin = runtimeSkin.skin;
const inverseBindMatrices = skin.inverseBindMatrices;
runtimeSkin._inverseBindMatrices = inverseBindMatrices;
const joints = skin.joints;
const length2 = joints.length;
const runtimeNodes = runtimeSkin.sceneGraph._runtimeNodes;
const runtimeJoints = runtimeSkin.joints;
const runtimeJointMatrices = runtimeSkin._jointMatrices;
for (let i = 0; i < length2; i++) {
const jointIndex = joints[i].index;
const runtimeNode = runtimeNodes[jointIndex];
runtimeJoints.push(runtimeNode);
const inverseBindMatrix = inverseBindMatrices[i];
const jointMatrix = computeJointMatrix(
runtimeNode,
inverseBindMatrix,
new Matrix4_default()
);
runtimeJointMatrices.push(jointMatrix);
}
}
function computeJointMatrix(joint, inverseBindMatrix, result) {
const jointWorldTransform = Matrix4_default.multiplyTransformation(
joint.transformToRoot,
joint.transform,
result
);
result = Matrix4_default.multiplyTransformation(
jointWorldTransform,
inverseBindMatrix,
result
);
return result;
}
ModelSkin.prototype.updateJointMatrices = function() {
const jointMatrices = this._jointMatrices;
const length2 = jointMatrices.length;
for (let i = 0; i < length2; i++) {
const joint = this.joints[i];
const inverseBindMatrix = this.inverseBindMatrices[i];
jointMatrices[i] = computeJointMatrix(
joint,
inverseBindMatrix,
jointMatrices[i]
);
}
};
var ModelSkin_default = ModelSkin;
// packages/engine/Source/Scene/Model/ModelRenderResources.js
var import_InlineWorkers715 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Model/ModelAlphaOptions.js
var import_InlineWorkers714 = __toESM(require_InlineWorkers(), 1);
function ModelAlphaOptions() {
this.pass = void 0;
this.alphaCutoff = void 0;
}
var ModelAlphaOptions_default = ModelAlphaOptions;
// packages/engine/Source/Scene/Model/ModelRenderResources.js
function ModelRenderResources(model) {
Check_default.typeOf.object("model", model);
this.shaderBuilder = new ShaderBuilder_default();
this.model = model;
this.uniformMap = {};
this.alphaOptions = new ModelAlphaOptions_default();
this.renderStateOptions = RenderState_default.getState(
RenderState_default.fromCache({
depthTest: {
enabled: true,
func: DepthFunction_default.LESS_OR_EQUAL
}
})
);
this.hasSilhouette = false;
this.hasSkipLevelOfDetail = false;
this.nodeRenderResources = [];
}
var ModelRenderResources_default = ModelRenderResources;
// packages/engine/Source/Scene/Model/ModelSilhouettePipelineStage.js
var import_InlineWorkers718 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/ModelSilhouetteStageFS.js
var import_InlineWorkers716 = __toESM(require_InlineWorkers(), 1);
var ModelSilhouetteStageFS_default = "void silhouetteStage(inout vec4 color) {\n if(model_silhouettePass) {\n color = czm_gammaCorrect(model_silhouetteColor);\n }\n}";
// packages/engine/Source/Shaders/Model/ModelSilhouetteStageVS.js
var import_InlineWorkers717 = __toESM(require_InlineWorkers(), 1);
var ModelSilhouetteStageVS_default = "void silhouetteStage(in ProcessedAttributes attributes, inout vec4 positionClip) {\n #ifdef HAS_NORMALS\n if(model_silhouettePass) {\n vec3 normal = normalize(czm_normal3D * attributes.normalMC);\n normal.x *= czm_projection[0][0];\n normal.y *= czm_projection[1][1];\n positionClip.xy += normal.xy * positionClip.w * model_silhouetteSize * czm_pixelRatio / czm_viewport.z;\n }\n #endif\n}\n";
// packages/engine/Source/Scene/Model/ModelSilhouettePipelineStage.js
var ModelSilhouettePipelineStage = {
name: "ModelSilhouettePipelineStage"
// Helps with debugging
};
ModelSilhouettePipelineStage.silhouettesLength = 0;
ModelSilhouettePipelineStage.process = function(renderResources, model, frameState) {
if (!defined_default(model._silhouetteId)) {
model._silhouetteId = ++ModelSilhouettePipelineStage.silhouettesLength;
}
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addDefine("HAS_SILHOUETTE", void 0, ShaderDestination_default.BOTH);
shaderBuilder.addVertexLines(ModelSilhouetteStageVS_default);
shaderBuilder.addFragmentLines(ModelSilhouetteStageFS_default);
shaderBuilder.addUniform(
"vec4",
"model_silhouetteColor",
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addUniform(
"float",
"model_silhouetteSize",
ShaderDestination_default.VERTEX
);
shaderBuilder.addUniform(
"bool",
"model_silhouettePass",
ShaderDestination_default.BOTH
);
const uniformMap2 = {
model_silhouetteColor: function() {
return model.silhouetteColor;
},
model_silhouetteSize: function() {
return model.silhouetteSize;
},
model_silhouettePass: function() {
return false;
}
};
renderResources.uniformMap = combine_default(uniformMap2, renderResources.uniformMap);
renderResources.hasSilhouette = true;
};
var ModelSilhouettePipelineStage_default = ModelSilhouettePipelineStage;
// packages/engine/Source/Scene/Model/ModelSplitterPipelineStage.js
var import_InlineWorkers720 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Model/ModelSplitterStageFS.js
var import_InlineWorkers719 = __toESM(require_InlineWorkers(), 1);
var ModelSplitterStageFS_default = "void modelSplitterStage()\n{\n // Don't split when rendering the shadow map, because it is rendered from\n // the perspective of a totally different camera.\n#ifndef SHADOW_MAP\n if (model_splitDirection < 0.0 && gl_FragCoord.x > czm_splitPosition) discard;\n if (model_splitDirection > 0.0 && gl_FragCoord.x < czm_splitPosition) discard;\n#endif\n}\n";
// packages/engine/Source/Scene/Model/ModelSplitterPipelineStage.js
var ModelSplitterPipelineStage = {
name: "ModelSplitterPipelineStage",
// Helps with debugging
SPLIT_DIRECTION_UNIFORM_NAME: "model_splitDirection"
};
ModelSplitterPipelineStage.process = function(renderResources, model, frameState) {
const shaderBuilder = renderResources.shaderBuilder;
shaderBuilder.addDefine(
"HAS_MODEL_SPLITTER",
void 0,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFragmentLines(ModelSplitterStageFS_default);
const stageUniforms = {};
shaderBuilder.addUniform(
"float",
ModelSplitterPipelineStage.SPLIT_DIRECTION_UNIFORM_NAME,
ShaderDestination_default.FRAGMENT
);
stageUniforms[ModelSplitterPipelineStage.SPLIT_DIRECTION_UNIFORM_NAME] = function() {
return model.splitDirection;
};
renderResources.uniformMap = combine_default(
stageUniforms,
renderResources.uniformMap
);
};
var ModelSplitterPipelineStage_default = ModelSplitterPipelineStage;
// packages/engine/Source/Scene/Model/NodeRenderResources.js
var import_InlineWorkers721 = __toESM(require_InlineWorkers(), 1);
function NodeRenderResources(modelRenderResources, runtimeNode) {
Check_default.typeOf.object("modelRenderResources", modelRenderResources);
Check_default.typeOf.object("runtimeNode", runtimeNode);
this.model = modelRenderResources.model;
this.shaderBuilder = modelRenderResources.shaderBuilder.clone();
this.uniformMap = clone_default(modelRenderResources.uniformMap);
this.alphaOptions = clone_default(modelRenderResources.alphaOptions);
this.renderStateOptions = clone_default(
modelRenderResources.renderStateOptions,
true
);
this.hasSilhouette = modelRenderResources.hasSilhouette;
this.hasSkipLevelOfDetail = modelRenderResources.hasSkipLevelOfDetail;
this.runtimeNode = runtimeNode;
this.attributes = [];
this.attributeIndex = 1;
this.featureIdVertexAttributeSetIndex = 0;
this.instanceCount = 0;
this.primitiveRenderResources = [];
}
var NodeRenderResources_default = NodeRenderResources;
// packages/engine/Source/Scene/Model/PrimitiveRenderResources.js
var import_InlineWorkers723 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Model/ModelLightingOptions.js
var import_InlineWorkers722 = __toESM(require_InlineWorkers(), 1);
function ModelLightingOptions(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.lightingModel = options.lightingModel ?? LightingModel_default.UNLIT;
}
var ModelLightingOptions_default = ModelLightingOptions;
// packages/engine/Source/Scene/Model/PrimitiveRenderResources.js
function PrimitiveRenderResources(nodeRenderResources, runtimePrimitive) {
Check_default.typeOf.object("nodeRenderResources", nodeRenderResources);
Check_default.typeOf.object("runtimePrimitive", runtimePrimitive);
this.model = nodeRenderResources.model;
this.runtimeNode = nodeRenderResources.runtimeNode;
this.attributes = nodeRenderResources.attributes.slice();
this.attributeIndex = nodeRenderResources.attributeIndex;
this.featureIdVertexAttributeSetIndex = nodeRenderResources.featureIdVertexAttributeSetIndex;
this.uniformMap = clone_default(nodeRenderResources.uniformMap);
this.alphaOptions = clone_default(nodeRenderResources.alphaOptions);
this.renderStateOptions = clone_default(nodeRenderResources.renderStateOptions, true);
this.hasSilhouette = nodeRenderResources.hasSilhouette;
this.hasSkipLevelOfDetail = nodeRenderResources.hasSkipLevelOfDetail;
this.shaderBuilder = nodeRenderResources.shaderBuilder.clone();
this.instanceCount = nodeRenderResources.instanceCount;
this.runtimePrimitive = runtimePrimitive;
const primitive = runtimePrimitive.primitive;
this.count = defined_default(primitive.indices) ? primitive.indices.count : ModelUtility_default.getAttributeBySemantic(primitive, "POSITION").count;
this.hasPropertyTable = false;
this.indices = primitive.indices;
this.wireframeIndexBuffer = void 0;
this.primitiveType = primitive.primitiveType;
const positionMinMax = ModelUtility_default.getPositionMinMax(
primitive,
this.runtimeNode.instancingTranslationMin,
this.runtimeNode.instancingTranslationMax
);
this.positionMin = Cartesian3_default.clone(positionMinMax.min, new Cartesian3_default());
this.positionMax = Cartesian3_default.clone(positionMinMax.max, new Cartesian3_default());
this.boundingSphere = BoundingSphere_default.fromCornerPoints(
this.positionMin,
this.positionMax,
new BoundingSphere_default()
);
this.lightingOptions = new ModelLightingOptions_default();
this.pickId = void 0;
}
var PrimitiveRenderResources_default = PrimitiveRenderResources;
// packages/engine/Source/Scene/Model/ModelDrawCommands.js
var import_InlineWorkers728 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Model/ClassificationModelDrawCommand.js
var import_InlineWorkers724 = __toESM(require_InlineWorkers(), 1);
function ClassificationModelDrawCommand(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const command = options.command;
const renderResources = options.primitiveRenderResources;
Check_default.typeOf.object("options.command", command);
Check_default.typeOf.object("options.primitiveRenderResources", renderResources);
const model = renderResources.model;
this._command = command;
this._model = model;
this._runtimePrimitive = renderResources.runtimePrimitive;
this._modelMatrix = command.modelMatrix;
this._boundingVolume = command.boundingVolume;
this._cullFace = command.renderState.cull.face;
const type = model.classificationType;
this._classificationType = type;
this._classifiesTerrain = type !== ClassificationType_default.CESIUM_3D_TILE;
this._classifies3DTiles = type !== ClassificationType_default.TERRAIN;
this._useDebugWireframe = model._enableDebugWireframe && model.debugWireframe;
this._pickId = renderResources.pickId;
this._commandListTerrain = [];
this._commandList3DTiles = [];
this._commandListIgnoreShow = [];
this._commandListDebugWireframe = [];
this._commandListTerrainPicking = [];
this._commandList3DTilesPicking = [];
initialize12(this);
}
function getStencilDepthRenderState3(stencilFunction) {
return {
colorMask: {
red: false,
green: false,
blue: false,
alpha: false
},
stencilTest: {
enabled: true,
frontFunction: stencilFunction,
frontOperation: {
fail: StencilOperation_default.KEEP,
zFail: StencilOperation_default.DECREMENT_WRAP,
zPass: StencilOperation_default.KEEP
},
backFunction: stencilFunction,
backOperation: {
fail: StencilOperation_default.KEEP,
zFail: StencilOperation_default.INCREMENT_WRAP,
zPass: StencilOperation_default.KEEP
},
reference: StencilConstants_default.CESIUM_3D_TILE_MASK,
mask: StencilConstants_default.CESIUM_3D_TILE_MASK
},
stencilMask: StencilConstants_default.CLASSIFICATION_MASK,
depthTest: {
enabled: true,
func: DepthFunction_default.LESS_OR_EQUAL
},
depthMask: false
};
}
var colorRenderState2 = {
stencilTest: {
enabled: true,
frontFunction: StencilFunction_default.NOT_EQUAL,
frontOperation: {
fail: StencilOperation_default.ZERO,
zFail: StencilOperation_default.ZERO,
zPass: StencilOperation_default.ZERO
},
backFunction: StencilFunction_default.NOT_EQUAL,
backOperation: {
fail: StencilOperation_default.ZERO,
zFail: StencilOperation_default.ZERO,
zPass: StencilOperation_default.ZERO
},
reference: 0,
mask: StencilConstants_default.CLASSIFICATION_MASK
},
stencilMask: StencilConstants_default.CLASSIFICATION_MASK,
depthTest: {
enabled: false
},
depthMask: false,
blending: BlendingState_default.PRE_MULTIPLIED_ALPHA_BLEND
};
var pickRenderState3 = {
stencilTest: {
enabled: true,
frontFunction: StencilFunction_default.NOT_EQUAL,
frontOperation: {
fail: StencilOperation_default.ZERO,
zFail: StencilOperation_default.ZERO,
zPass: StencilOperation_default.ZERO
},
backFunction: StencilFunction_default.NOT_EQUAL,
backOperation: {
fail: StencilOperation_default.ZERO,
zFail: StencilOperation_default.ZERO,
zPass: StencilOperation_default.ZERO
},
reference: 0,
mask: StencilConstants_default.CLASSIFICATION_MASK
},
stencilMask: StencilConstants_default.CLASSIFICATION_MASK,
depthTest: {
enabled: false
},
depthMask: false
};
var scratchDerivedCommands = [];
function initialize12(drawCommand) {
const command = drawCommand._command;
const derivedCommands = scratchDerivedCommands;
if (drawCommand._useDebugWireframe) {
command.pass = Pass_default.OPAQUE;
derivedCommands.length = 0;
derivedCommands.push(command);
drawCommand._commandListDebugWireframe = createBatchCommands(
drawCommand,
derivedCommands,
drawCommand._commandListDebugWireframe
);
const commandList = drawCommand._commandListDebugWireframe;
const length2 = commandList.length;
for (let i = 0; i < length2; i++) {
const command2 = commandList[i];
command2.count *= 2;
command2.offset *= 2;
}
return;
}
const model = drawCommand.model;
const allowPicking = model.allowPicking;
if (drawCommand._classifiesTerrain) {
const pass = Pass_default.TERRAIN_CLASSIFICATION;
const stencilDepthCommand = deriveStencilDepthCommand(command, pass);
const colorCommand = deriveColorCommand(command, pass);
derivedCommands.length = 0;
derivedCommands.push(stencilDepthCommand, colorCommand);
drawCommand._commandListTerrain = createBatchCommands(
drawCommand,
derivedCommands,
drawCommand._commandListTerrain
);
if (allowPicking) {
drawCommand._commandListTerrainPicking = createPickCommands3(
drawCommand,
derivedCommands,
drawCommand._commandListTerrainPicking
);
}
}
if (drawCommand._classifies3DTiles) {
const pass = Pass_default.CESIUM_3D_TILE_CLASSIFICATION;
const stencilDepthCommand = deriveStencilDepthCommand(command, pass);
const colorCommand = deriveColorCommand(command, pass);
derivedCommands.length = 0;
derivedCommands.push(stencilDepthCommand, colorCommand);
drawCommand._commandList3DTiles = createBatchCommands(
drawCommand,
derivedCommands,
drawCommand._commandList3DTiles
);
if (allowPicking) {
drawCommand._commandList3DTilesPicking = createPickCommands3(
drawCommand,
derivedCommands,
drawCommand._commandList3DTilesPicking
);
}
}
}
function createBatchCommands(drawCommand, derivedCommands, result) {
const runtimePrimitive = drawCommand._runtimePrimitive;
const batchLengths = runtimePrimitive.batchLengths;
const batchOffsets = runtimePrimitive.batchOffsets;
const numBatches = batchLengths.length;
const numDerivedCommands = derivedCommands.length;
for (let i = 0; i < numBatches; i++) {
const batchLength = batchLengths[i];
const batchOffset = batchOffsets[i];
for (let j = 0; j < numDerivedCommands; j++) {
const derivedCommand = derivedCommands[j];
const batchCommand = DrawCommand_default.shallowClone(derivedCommand);
batchCommand.count = batchLength;
batchCommand.offset = batchOffset;
result.push(batchCommand);
}
}
return result;
}
function deriveStencilDepthCommand(command, pass) {
const stencilDepthCommand = DrawCommand_default.shallowClone(command);
stencilDepthCommand.cull = false;
stencilDepthCommand.pass = pass;
const stencilFunction = pass === Pass_default.TERRAIN_CLASSIFICATION ? StencilFunction_default.ALWAYS : StencilFunction_default.EQUAL;
const renderState = getStencilDepthRenderState3(stencilFunction);
stencilDepthCommand.renderState = RenderState_default.fromCache(renderState);
return stencilDepthCommand;
}
function deriveColorCommand(command, pass) {
const colorCommand = DrawCommand_default.shallowClone(command);
colorCommand.cull = false;
colorCommand.pass = pass;
colorCommand.renderState = RenderState_default.fromCache(colorRenderState2);
return colorCommand;
}
var scratchPickCommands = [];
function createPickCommands3(drawCommand, derivedCommands, commandList) {
const renderState = RenderState_default.fromCache(pickRenderState3);
const stencilDepthCommand = derivedCommands[0];
const colorCommand = derivedCommands[1];
const pickStencilDepthCommand = DrawCommand_default.shallowClone(stencilDepthCommand);
pickStencilDepthCommand.cull = true;
pickStencilDepthCommand.pickOnly = true;
const pickColorCommand = DrawCommand_default.shallowClone(colorCommand);
pickColorCommand.cull = true;
pickColorCommand.pickOnly = true;
pickColorCommand.renderState = renderState;
pickColorCommand.pickId = drawCommand._pickId;
const pickCommands = scratchPickCommands;
pickCommands.length = 0;
pickCommands.push(pickStencilDepthCommand, pickColorCommand);
return createBatchCommands(drawCommand, pickCommands, commandList);
}
Object.defineProperties(ClassificationModelDrawCommand.prototype, {
/**
* The main draw command that the other commands are derived from.
*
* @memberof ClassificationModelDrawCommand.prototype
* @type {DrawCommand}
*
* @readonly
* @private
*/
command: {
get: function() {
return this._command;
}
},
/**
* The runtime primitive that the draw command belongs to.
*
* @memberof ClassificationModelDrawCommand.prototype
* @type {ModelRuntimePrimitive}
*
* @readonly
* @private
*/
runtimePrimitive: {
get: function() {
return this._runtimePrimitive;
}
},
/**
* The batch lengths used to generate multiple draw commands.
*
* @memberof ClassificationModelDrawCommand.prototype
* @type {number[]}
*
* @readonly
* @private
*/
batchLengths: {
get: function() {
return this._runtimePrimitive.batchLengths;
}
},
/**
* The batch offsets used to generate multiple draw commands.
*
* @memberof ClassificationModelDrawCommand.prototype
* @type {number[]}
*
* @readonly
* @private
*/
batchOffsets: {
get: function() {
return this._runtimePrimitive.batchOffsets;
}
},
/**
* The model that the draw command belongs to.
*
* @memberof ClassificationModelDrawCommand.prototype
* @type {Model}
*
* @readonly
* @private
*/
model: {
get: function() {
return this._model;
}
},
/**
* The classification type of the model that this draw command belongs to.
*
* @memberof ClassificationModelDrawCommand.prototype
* @type {ClassificationType}
*
* @readonly
* @private
*/
classificationType: {
get: function() {
return this._classificationType;
}
},
/**
* The current model matrix applied to the draw commands.
*
* @memberof ClassificationModelDrawCommand.prototype
* @type {Matrix4}
*
* @readonly
* @private
*/
modelMatrix: {
get: function() {
return this._modelMatrix;
},
set: function(value) {
this._modelMatrix = Matrix4_default.clone(value, this._modelMatrix);
const boundingSphere = this._runtimePrimitive.boundingSphere;
this._boundingVolume = BoundingSphere_default.transform(
boundingSphere,
this._modelMatrix,
this._boundingVolume
);
}
},
/**
* The bounding volume of the main draw command. This is equivalent
* to the primitive's bounding sphere transformed by the draw
* command's model matrix.
*
* @memberof ClassificationModelDrawCommand.prototype
* @type {BoundingSphere}
*
* @readonly
* @private
*/
boundingVolume: {
get: function() {
return this._boundingVolume;
}
},
/**
* Culling is disabled for classification models, so this has no effect on
* how the model renders. This only exists to match the interface of
* {@link ModelDrawCommand}.
*
* @memberof ClassificationModelDrawCommand.prototype
* @type {CullFace}
*
* @private
*/
cullFace: {
get: function() {
return this._cullFace;
},
set: function(value) {
this._cullFace = value;
}
}
});
ClassificationModelDrawCommand.prototype.pushCommands = function(frameState, result) {
const passes = frameState.passes;
if (passes.render) {
if (this._useDebugWireframe) {
addAllToArray_default(result, this._commandListDebugWireframe);
return;
}
if (this._classifiesTerrain) {
addAllToArray_default(result, this._commandListTerrain);
}
if (this._classifies3DTiles) {
addAllToArray_default(result, this._commandList3DTiles);
}
const useIgnoreShowCommands = frameState.invertClassification && this._classifies3DTiles;
if (useIgnoreShowCommands) {
if (this._commandListIgnoreShow.length === 0) {
const pass = Pass_default.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW;
const command = deriveStencilDepthCommand(this._command, pass);
const derivedCommands = scratchDerivedCommands;
derivedCommands.length = 0;
derivedCommands.push(command);
this._commandListIgnoreShow = createBatchCommands(
this,
derivedCommands,
this._commandListIgnoreShow
);
}
addAllToArray_default(result, this._commandListIgnoreShow);
}
}
if (passes.pick) {
if (this._classifiesTerrain) {
addAllToArray_default(result, this._commandListTerrainPicking);
}
if (this._classifies3DTiles) {
addAllToArray_default(result, this._commandList3DTilesPicking);
}
}
return result;
};
var ClassificationModelDrawCommand_default = ClassificationModelDrawCommand;
// packages/engine/Source/Scene/Model/ModelDrawCommand.js
var import_InlineWorkers725 = __toESM(require_InlineWorkers(), 1);
function ModelDrawCommand(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const command = options.command;
const renderResources = options.primitiveRenderResources;
Check_default.typeOf.object("options.command", command);
Check_default.typeOf.object("options.primitiveRenderResources", renderResources);
const model = renderResources.model;
this._model = model;
const runtimePrimitive = renderResources.runtimePrimitive;
this._runtimePrimitive = runtimePrimitive;
const isTranslucent = command.pass === Pass_default.TRANSLUCENT;
const isDoubleSided = runtimePrimitive.primitive.material.doubleSided;
const usesBackFaceCulling = !isDoubleSided && !isTranslucent;
const hasSilhouette = renderResources.hasSilhouette;
const needsTranslucentCommand = !isTranslucent && !hasSilhouette;
const needsSkipLevelOfDetailCommands = renderResources.hasSkipLevelOfDetail && !isTranslucent;
const needsSilhouetteCommands = hasSilhouette;
this._command = command;
this._modelMatrix = Matrix4_default.clone(command.modelMatrix);
this._boundingVolume = BoundingSphere_default.clone(command.boundingVolume);
this._modelMatrix2D = new Matrix4_default();
this._boundingVolume2D = new BoundingSphere_default();
this._modelMatrix2DDirty = false;
this._backFaceCulling = command.renderState.cull.enabled;
this._cullFace = command.renderState.cull.face;
this._shadows = model.shadows;
this._debugShowBoundingVolume = command.debugShowBoundingVolume;
this._usesBackFaceCulling = usesBackFaceCulling;
this._needsTranslucentCommand = needsTranslucentCommand;
this._needsSkipLevelOfDetailCommands = needsSkipLevelOfDetailCommands;
this._needsSilhouetteCommands = needsSilhouetteCommands;
this._originalCommand = void 0;
this._translucentCommand = void 0;
this._skipLodBackfaceCommand = void 0;
this._skipLodStencilCommand = void 0;
this._silhouetteModelCommand = void 0;
this._silhouetteColorCommand = void 0;
this._derivedCommands = [];
this._has2DCommands = false;
initialize13(this);
}
function ModelDerivedCommand(options) {
this.command = options.command;
this.updateShadows = options.updateShadows;
this.updateBackFaceCulling = options.updateBackFaceCulling;
this.updateCullFace = options.updateCullFace;
this.updateDebugShowBoundingVolume = options.updateDebugShowBoundingVolume;
this.is2D = options.is2D ?? false;
this.derivedCommand2D = void 0;
}
ModelDerivedCommand.clone = function(derivedCommand) {
return new ModelDerivedCommand({
command: derivedCommand.command,
updateShadows: derivedCommand.updateShadows,
updateBackFaceCulling: derivedCommand.updateBackFaceCulling,
updateCullFace: derivedCommand.updateCullFace,
updateDebugShowBoundingVolume: derivedCommand.updateDebugShowBoundingVolume,
is2D: derivedCommand.is2D,
derivedCommand2D: derivedCommand.derivedCommand2D
});
};
function initialize13(drawCommand) {
const command = drawCommand._command;
command.modelMatrix = drawCommand._modelMatrix;
command.boundingVolume = drawCommand._boundingVolume;
const model = drawCommand._model;
const usesBackFaceCulling = drawCommand._usesBackFaceCulling;
const derivedCommands = drawCommand._derivedCommands;
drawCommand._originalCommand = new ModelDerivedCommand({
command,
updateShadows: true,
updateBackFaceCulling: usesBackFaceCulling,
updateCullFace: usesBackFaceCulling,
updateDebugShowBoundingVolume: true,
is2D: false
});
derivedCommands.push(drawCommand._originalCommand);
if (drawCommand._needsTranslucentCommand) {
drawCommand._translucentCommand = new ModelDerivedCommand({
command: deriveTranslucentCommand2(command),
updateShadows: true,
updateBackFaceCulling: false,
updateCullFace: false,
updateDebugShowBoundingVolume: true
});
derivedCommands.push(drawCommand._translucentCommand);
}
if (drawCommand._needsSkipLevelOfDetailCommands) {
drawCommand._skipLodBackfaceCommand = new ModelDerivedCommand({
command: deriveSkipLodBackfaceCommand(command),
updateShadows: false,
updateBackFaceCulling: false,
updateCullFace: usesBackFaceCulling,
updateDebugShowBoundingVolume: false
});
drawCommand._skipLodStencilCommand = new ModelDerivedCommand({
command: deriveSkipLodStencilCommand(command, model),
updateShadows: true,
updateBackFaceCulling: usesBackFaceCulling,
updateCullFace: usesBackFaceCulling,
updateDebugShowBoundingVolume: true
});
derivedCommands.push(drawCommand._skipLodBackfaceCommand);
derivedCommands.push(drawCommand._skipLodStencilCommand);
}
if (drawCommand._needsSilhouetteCommands) {
drawCommand._silhouetteModelCommand = new ModelDerivedCommand({
command: deriveSilhouetteModelCommand(command, model),
updateShadows: true,
updateBackFaceCulling: usesBackFaceCulling,
updateCullFace: usesBackFaceCulling,
updateDebugShowBoundingVolume: true
});
drawCommand._silhouetteColorCommand = new ModelDerivedCommand({
command: deriveSilhouetteColorCommand(command, model),
updateShadows: false,
updateBackFaceCulling: false,
updateCullFace: false,
updateDebugShowBoundingVolume: false
});
derivedCommands.push(drawCommand._silhouetteModelCommand);
derivedCommands.push(drawCommand._silhouetteColorCommand);
}
}
Object.defineProperties(ModelDrawCommand.prototype, {
/**
* The main draw command that the other commands are derived from.
*
* @memberof ModelDrawCommand.prototype
* @type {DrawCommand}
*
* @readonly
* @private
*/
command: {
get: function() {
return this._command;
}
},
/**
* The runtime primitive that the draw command belongs to.
*
* @memberof ModelDrawCommand.prototype
* @type {ModelRuntimePrimitive}
*
* @readonly
* @private
*/
runtimePrimitive: {
get: function() {
return this._runtimePrimitive;
}
},
/**
* The model that the draw command belongs to.
*
* @memberof ModelDrawCommand.prototype
* @type {Model}
*
* @readonly
* @private
*/
model: {
get: function() {
return this._model;
}
},
/**
* The primitive type of the draw command.
*
* @memberof ModelDrawCommand.prototype
* @type {PrimitiveType}
*
* @readonly
* @private
*/
primitiveType: {
get: function() {
return this._command.primitiveType;
}
},
/**
* The current model matrix applied to the draw commands. If there are
* 2D draw commands, their model matrix will be derived from the 3D one.
*
* @memberof ModelDrawCommand.prototype
* @type {Matrix4}
*
* @readonly
* @private
*/
modelMatrix: {
get: function() {
return this._modelMatrix;
},
set: function(value) {
this._modelMatrix = Matrix4_default.clone(value, this._modelMatrix);
this._modelMatrix2DDirty = true;
this._boundingVolume = BoundingSphere_default.transform(
this.runtimePrimitive.boundingSphere,
this._modelMatrix,
this._boundingVolume
);
}
},
/**
* The bounding volume of the main draw command. This is equivalent
* to the primitive's bounding sphere transformed by the draw
* command's model matrix.
*
* @memberof ModelDrawCommand.prototype
* @type {BoundingSphere}
*
* @readonly
* @private
*/
boundingVolume: {
get: function() {
return this._boundingVolume;
}
},
/**
* Whether the geometry casts or receives shadows from light sources.
*
* @memberof ModelDrawCommand.prototype
* @type {ShadowMode}
*
* @private
*/
shadows: {
get: function() {
return this._shadows;
},
set: function(value) {
this._shadows = value;
updateShadows(this);
}
},
/**
* Whether to cull back-facing geometry. When true, back face culling is
* determined by the material's doubleSided property; when false, back face
* culling is disabled. Back faces are not culled if the command is
* translucent.
*
* @memberof ModelDrawCommand.prototype
* @type {boolean}
*
* @private
*/
backFaceCulling: {
get: function() {
return this._backFaceCulling;
},
set: function(value) {
if (this._backFaceCulling === value) {
return;
}
this._backFaceCulling = value;
updateBackFaceCulling(this);
}
},
/**
* Determines which faces to cull, if culling is enabled.
*
* @memberof ModelDrawCommand.prototype
* @type {CullFace}
*
* @private
*/
cullFace: {
get: function() {
return this._cullFace;
},
set: function(value) {
if (this._cullFace === value) {
return;
}
this._cullFace = value;
updateCullFace(this);
}
},
/**
* Whether to draw the bounding sphere associated with this draw command.
*
* @memberof ModelDrawCommand.prototype
* @type {boolean}
*
* @private
*/
debugShowBoundingVolume: {
get: function() {
return this._debugShowBoundingVolume;
},
set: function(value) {
if (this._debugShowBoundingVolume === value) {
return;
}
this._debugShowBoundingVolume = value;
updateDebugShowBoundingVolume(this);
}
}
});
function updateModelMatrix2D(drawCommand, frameState) {
const modelMatrix = drawCommand._modelMatrix;
drawCommand._modelMatrix2D = Matrix4_default.clone(
modelMatrix,
drawCommand._modelMatrix2D
);
drawCommand._modelMatrix2D[13] -= Math_default.sign(modelMatrix[13]) * 2 * Math_default.PI * frameState.mapProjection.ellipsoid.maximumRadius;
drawCommand._boundingVolume2D = BoundingSphere_default.transform(
drawCommand.runtimePrimitive.boundingSphere,
drawCommand._modelMatrix2D,
drawCommand._boundingVolume2D
);
}
function updateShadows(drawCommand) {
const shadows = drawCommand.shadows;
const castShadows = ShadowMode_default.castShadows(shadows);
const receiveShadows = ShadowMode_default.receiveShadows(shadows);
const derivedCommands = drawCommand._derivedCommands;
for (let i = 0; i < derivedCommands.length; ++i) {
const derivedCommand = derivedCommands[i];
if (derivedCommand.updateShadows) {
const command = derivedCommand.command;
command.castShadows = castShadows;
command.receiveShadows = receiveShadows;
}
}
}
function updateBackFaceCulling(drawCommand) {
const backFaceCulling = drawCommand.backFaceCulling;
const derivedCommands = drawCommand._derivedCommands;
for (let i = 0; i < derivedCommands.length; ++i) {
const derivedCommand = derivedCommands[i];
if (derivedCommand.updateBackFaceCulling) {
const command = derivedCommand.command;
const renderState = clone_default(command.renderState, true);
renderState.cull.enabled = backFaceCulling;
command.renderState = RenderState_default.fromCache(renderState);
}
}
}
function updateCullFace(drawCommand) {
const cullFace = drawCommand.cullFace;
const derivedCommands = drawCommand._derivedCommands;
for (let i = 0; i < derivedCommands.length; ++i) {
const derivedCommand = derivedCommands[i];
if (derivedCommand.updateCullFace) {
const command = derivedCommand.command;
const renderState = clone_default(command.renderState, true);
renderState.cull.face = cullFace;
command.renderState = RenderState_default.fromCache(renderState);
}
}
}
function updateDebugShowBoundingVolume(drawCommand) {
const debugShowBoundingVolume2 = drawCommand.debugShowBoundingVolume;
const derivedCommands = drawCommand._derivedCommands;
for (let i = 0; i < derivedCommands.length; ++i) {
const derivedCommand = derivedCommands[i];
if (derivedCommand.updateDebugShowBoundingVolume) {
const command = derivedCommand.command;
command.debugShowBoundingVolume = debugShowBoundingVolume2;
}
}
}
ModelDrawCommand.prototype.pushCommands = function(frameState, result) {
const use2D = shouldUse2DCommands(this, frameState);
if (use2D && !this._has2DCommands) {
derive2DCommands(this);
this._has2DCommands = true;
this._modelMatrix2DDirty = true;
}
if (this._modelMatrix2DDirty) {
updateModelMatrix2D(this, frameState);
this._modelMatrix2DDirty = false;
}
const styleCommandsNeeded = this.model.styleCommandsNeeded;
if (this._needsTranslucentCommand && defined_default(styleCommandsNeeded)) {
if (styleCommandsNeeded !== StyleCommandsNeeded_default.ALL_OPAQUE) {
pushCommand(result, this._translucentCommand, use2D);
}
if (styleCommandsNeeded === StyleCommandsNeeded_default.ALL_TRANSLUCENT) {
return;
}
}
if (this._needsSkipLevelOfDetailCommands) {
const { tileset, tile } = this._model.content;
if (tileset.hasMixedContent) {
if (!tile._finalResolution) {
pushCommand(
tileset._backfaceCommands,
this._skipLodBackfaceCommand,
use2D
);
}
updateSkipLodStencilCommand(this, tile, use2D);
pushCommand(result, this._skipLodStencilCommand, use2D);
return;
}
}
if (this._needsSilhouetteCommands) {
pushCommand(result, this._silhouetteModelCommand, use2D);
return;
}
pushCommand(result, this._originalCommand, use2D);
return result;
};
ModelDrawCommand.prototype.pushSilhouetteCommands = function(frameState, result) {
const use2D = shouldUse2DCommands(this, frameState);
pushCommand(result, this._silhouetteColorCommand, use2D);
return result;
};
function pushCommand(commandList, derivedCommand, use2D) {
commandList.push(derivedCommand.command);
if (use2D) {
commandList.push(derivedCommand.derivedCommand2D.command);
}
}
function shouldUse2DCommands(drawCommand, frameState) {
if (frameState.mode !== SceneMode_default.SCENE2D || drawCommand.model._projectTo2D) {
return false;
}
const model = drawCommand.model;
const boundingSphere = model.sceneGraph._boundingSphere2D;
const left = boundingSphere.center.y - boundingSphere.radius;
const right = boundingSphere.center.y + boundingSphere.radius;
const idl2D = frameState.mapProjection.ellipsoid.maximumRadius * Math_default.PI;
return left < idl2D && right > idl2D || left < -idl2D && right > -idl2D;
}
function derive2DCommand(drawCommand, derivedCommand) {
if (!defined_default(derivedCommand)) {
return;
}
const derivedCommand2D = ModelDerivedCommand.clone(derivedCommand);
const command2D = DrawCommand_default.shallowClone(derivedCommand.command);
command2D.modelMatrix = drawCommand._modelMatrix2D;
command2D.boundingVolume = drawCommand._boundingVolume2D;
derivedCommand2D.command = command2D;
derivedCommand2D.updateShadows = false;
derivedCommand2D.is2D = true;
derivedCommand.derivedCommand2D = derivedCommand2D;
drawCommand._derivedCommands.push(derivedCommand2D);
return derivedCommand2D;
}
function derive2DCommands(drawCommand) {
derive2DCommand(drawCommand, drawCommand._originalCommand);
derive2DCommand(drawCommand, drawCommand._translucentCommand);
derive2DCommand(drawCommand, drawCommand._skipLodBackfaceCommand);
derive2DCommand(drawCommand, drawCommand._skipLodStencilCommand);
derive2DCommand(drawCommand, drawCommand._silhouetteModelCommand);
derive2DCommand(drawCommand, drawCommand._silhouetteColorCommand);
}
function deriveTranslucentCommand2(command) {
const derivedCommand = DrawCommand_default.shallowClone(command);
derivedCommand.pass = Pass_default.TRANSLUCENT;
const rs = clone_default(command.renderState, true);
rs.cull.enabled = false;
rs.depthMask = false;
rs.blending = BlendingState_default.ALPHA_BLEND;
derivedCommand.renderState = RenderState_default.fromCache(rs);
return derivedCommand;
}
function deriveSilhouetteModelCommand(command, model) {
const stencilReference = model._silhouetteId % 255;
const silhouetteModelCommand = DrawCommand_default.shallowClone(command);
const renderState = clone_default(command.renderState, true);
renderState.stencilTest = {
enabled: true,
frontFunction: WebGLConstants_default.ALWAYS,
backFunction: WebGLConstants_default.ALWAYS,
reference: stencilReference,
mask: ~0,
frontOperation: {
fail: WebGLConstants_default.KEEP,
zFail: WebGLConstants_default.KEEP,
zPass: WebGLConstants_default.REPLACE
},
backOperation: {
fail: WebGLConstants_default.KEEP,
zFail: WebGLConstants_default.KEEP,
zPass: WebGLConstants_default.REPLACE
}
};
if (model.isInvisible()) {
renderState.colorMask = {
red: false,
green: false,
blue: false,
alpha: false
};
}
silhouetteModelCommand.renderState = RenderState_default.fromCache(renderState);
return silhouetteModelCommand;
}
function deriveSilhouetteColorCommand(command, model) {
const stencilReference = model._silhouetteId % 255;
const silhouetteColorCommand = DrawCommand_default.shallowClone(command);
const renderState = clone_default(command.renderState, true);
renderState.cull.enabled = false;
const silhouetteTranslucent = command.pass === Pass_default.TRANSLUCENT || model.silhouetteColor.alpha < 1;
if (silhouetteTranslucent) {
silhouetteColorCommand.pass = Pass_default.TRANSLUCENT;
renderState.depthMask = false;
renderState.blending = BlendingState_default.ALPHA_BLEND;
}
renderState.stencilTest = {
enabled: true,
frontFunction: WebGLConstants_default.NOTEQUAL,
backFunction: WebGLConstants_default.NOTEQUAL,
reference: stencilReference,
mask: ~0,
frontOperation: {
fail: WebGLConstants_default.KEEP,
zFail: WebGLConstants_default.KEEP,
zPass: WebGLConstants_default.KEEP
},
backOperation: {
fail: WebGLConstants_default.KEEP,
zFail: WebGLConstants_default.KEEP,
zPass: WebGLConstants_default.KEEP
}
};
const uniformMap2 = clone_default(command.uniformMap);
uniformMap2.model_silhouettePass = function() {
return true;
};
silhouetteColorCommand.renderState = RenderState_default.fromCache(renderState);
silhouetteColorCommand.uniformMap = uniformMap2;
silhouetteColorCommand.castShadows = false;
silhouetteColorCommand.receiveShadows = false;
return silhouetteColorCommand;
}
function updateSkipLodStencilCommand(drawCommand, tile, use2D) {
const stencilDerivedComand = drawCommand._skipLodStencilCommand;
const stencilCommand = stencilDerivedComand.command;
const selectionDepth = tile._selectionDepth;
const lastSelectionDepth = getLastSelectionDepth2(stencilCommand);
if (selectionDepth !== lastSelectionDepth) {
const skipLodStencilReference = getStencilReference(selectionDepth);
const renderState = clone_default(stencilCommand.renderState, true);
renderState.stencilTest.reference = skipLodStencilReference;
stencilCommand.renderState = RenderState_default.fromCache(renderState);
if (use2D) {
stencilDerivedComand.derivedCommand2D.renderState = renderState;
}
}
}
function getLastSelectionDepth2(stencilCommand) {
const reference = stencilCommand.renderState.stencilTest.reference;
return (reference & StencilConstants_default.SKIP_LOD_MASK) >>> StencilConstants_default.SKIP_LOD_BIT_SHIFT;
}
function getStencilReference(selectionDepth) {
return StencilConstants_default.CESIUM_3D_TILE_MASK | selectionDepth << StencilConstants_default.SKIP_LOD_BIT_SHIFT;
}
function deriveSkipLodBackfaceCommand(command) {
const backfaceCommand = DrawCommand_default.shallowClone(command);
const renderState = clone_default(command.renderState, true);
renderState.cull.enabled = true;
renderState.cull.face = CullFace_default.FRONT;
renderState.colorMask = {
red: false,
green: false,
blue: false,
alpha: false
};
renderState.polygonOffset = {
enabled: true,
factor: 5,
units: 5
};
const uniformMap2 = clone_default(backfaceCommand.uniformMap);
const polygonOffset = new Cartesian2_default(5, 5);
uniformMap2.u_polygonOffset = function() {
return polygonOffset;
};
backfaceCommand.renderState = RenderState_default.fromCache(renderState);
backfaceCommand.uniformMap = uniformMap2;
backfaceCommand.castShadows = false;
backfaceCommand.receiveShadows = false;
return backfaceCommand;
}
function deriveSkipLodStencilCommand(command) {
const stencilCommand = DrawCommand_default.shallowClone(command);
const renderState = clone_default(command.renderState, true);
const { stencilTest } = renderState;
stencilTest.enabled = true;
stencilTest.mask = StencilConstants_default.SKIP_LOD_MASK;
stencilTest.reference = StencilConstants_default.CESIUM_3D_TILE_MASK;
stencilTest.frontFunction = StencilFunction_default.GREATER_OR_EQUAL;
stencilTest.frontOperation.zPass = StencilOperation_default.REPLACE;
stencilTest.backFunction = StencilFunction_default.GREATER_OR_EQUAL;
stencilTest.backOperation.zPass = StencilOperation_default.REPLACE;
renderState.stencilMask = StencilConstants_default.CESIUM_3D_TILE_MASK | StencilConstants_default.SKIP_LOD_MASK;
stencilCommand.renderState = RenderState_default.fromCache(renderState);
return stencilCommand;
}
var ModelDrawCommand_default = ModelDrawCommand;
// packages/engine/Source/Shaders/Model/ModelVS.js
var import_InlineWorkers726 = __toESM(require_InlineWorkers(), 1);
var ModelVS_default = "precision highp float;\n\nczm_modelVertexOutput defaultVertexOutput(vec3 positionMC) {\n czm_modelVertexOutput vsOutput;\n vsOutput.positionMC = positionMC;\n vsOutput.pointSize = 1.0;\n return vsOutput;\n}\n\nvoid main()\n{\n // Initialize the attributes struct with all\n // attributes except quantized ones.\n ProcessedAttributes attributes;\n initializeAttributes(attributes);\n\n #ifdef HAS_IMAGERY\n initializeImageryAttributes();\n #endif\n\n // Dequantize the quantized ones and add them to the\n // attributes struct.\n #ifdef USE_DEQUANTIZATION\n dequantizationStage(attributes);\n #endif\n\n #ifdef HAS_MORPH_TARGETS\n morphTargetsStage(attributes);\n #endif\n\n #ifdef HAS_SKINNING\n skinningStage(attributes);\n #endif\n\n #ifdef HAS_PRIMITIVE_OUTLINE\n primitiveOutlineStage();\n #endif\n\n // Compute the bitangent according to the formula in the glTF spec.\n // Normal and tangents can be affected by morphing and skinning, so\n // the bitangent should not be computed until their values are finalized.\n #ifdef HAS_BITANGENTS\n attributes.bitangentMC = normalize(cross(attributes.normalMC, attributes.tangentMC) * attributes.tangentSignMC);\n #endif\n\n FeatureIds featureIds;\n featureIdStage(featureIds, attributes);\n\n #ifdef HAS_SELECTED_FEATURE_ID\n SelectedFeature feature;\n selectedFeatureIdStage(feature, featureIds);\n // Handle any show properties that come from the style.\n cpuStylingStage(attributes.positionMC, feature);\n #endif\n\n #if defined(USE_2D_POSITIONS) || defined(USE_2D_INSTANCING)\n // The scene mode 2D pipeline stage and instancing stage add a different\n // model view matrix to accurately project the model to 2D. However, the\n // output positions and normals should be transformed by the 3D matrices\n // to keep the data the same for the fragment shader.\n mat4 modelView = czm_modelView3D;\n mat3 normal = czm_normal3D;\n #else\n // These are used for individual model projection because they will\n // automatically change based on the scene mode.\n mat4 modelView = czm_modelView;\n mat3 normal = czm_normal;\n #endif\n\n // Update the position for this instance in place\n #ifdef HAS_INSTANCING\n\n // The legacy instance stage is used when rendering i3dm models that\n // encode instances transforms in world space, as opposed to glTF models\n // that use EXT_mesh_gpu_instancing, where instance transforms are encoded\n // in object space.\n #ifdef USE_LEGACY_INSTANCING\n mat4 instanceModelView;\n mat3 instanceModelViewInverseTranspose;\n\n legacyInstancingStage(attributes, instanceModelView, instanceModelViewInverseTranspose);\n\n modelView = instanceModelView;\n normal = instanceModelViewInverseTranspose;\n #else\n instancingStage(attributes);\n #endif\n\n #ifdef USE_PICKING\n v_pickColor = a_pickColor;\n #endif\n\n #endif\n\n Metadata metadata;\n MetadataClass metadataClass;\n MetadataStatistics metadataStatistics;\n metadataStage(metadata, metadataClass, metadataStatistics, attributes);\n\n #ifdef HAS_VERTICAL_EXAGGERATION\n verticalExaggerationStage(attributes);\n #endif\n\n #ifdef HAS_CUSTOM_VERTEX_SHADER\n czm_modelVertexOutput vsOutput = defaultVertexOutput(attributes.positionMC);\n customShaderStage(vsOutput, attributes, featureIds, metadata, metadataClass, metadataStatistics);\n #endif\n\n // Compute the final position in each coordinate system needed.\n // This returns the value that will be assigned to gl_Position.\n vec4 positionClip = geometryStage(attributes, modelView, normal);\n\n // This must go after the geometry stage as it needs v_positionWC\n #ifdef HAS_ATMOSPHERE\n atmosphereStage(attributes);\n #endif\n\n #ifdef ENABLE_CLIPPING_POLYGONS\n modelClippingPolygonsStage(attributes);\n #endif\n\n #ifdef HAS_SILHOUETTE\n silhouetteStage(attributes, positionClip);\n #endif\n\n #ifdef HAS_POINT_CLOUD_SHOW_STYLE\n float show = pointCloudShowStylingStage(attributes, metadata);\n #else\n float show = 1.0;\n #endif\n\n #ifdef HAS_POINT_CLOUD_BACK_FACE_CULLING\n show *= pointCloudBackFaceCullingStage();\n #endif\n\n #ifdef HAS_POINT_CLOUD_COLOR_STYLE\n v_pointCloudColor = pointCloudColorStylingStage(attributes, metadata);\n #endif\n\n #ifdef PRIMITIVE_TYPE_POINTS\n #ifdef HAS_CUSTOM_VERTEX_SHADER\n gl_PointSize = vsOutput.pointSize;\n #elif defined(HAS_POINT_CLOUD_POINT_SIZE_STYLE) || defined(HAS_POINT_CLOUD_ATTENUATION)\n gl_PointSize = pointCloudPointSizeStylingStage(attributes, metadata);\n #else\n gl_PointSize = 1.0;\n #endif\n \n gl_PointSize *= show;\n #endif\n\n // Important NOT to compute gl_Position = show * positionClip or we hit:\n // https://github.com/CesiumGS/cesium/issues/11270\n //\n // We will discard points with v_pointCloudShow == 0 in the fragment shader.\n gl_Position = positionClip;\n\n #ifdef HAS_POINT_CLOUD_SHOW_STYLE\n v_pointCloudShow = show;\n #endif\n}\n";
// packages/engine/Source/Shaders/Model/ModelFS.js
var import_InlineWorkers727 = __toESM(require_InlineWorkers(), 1);
var ModelFS_default = "\nprecision highp float;\n\nczm_modelMaterial defaultModelMaterial()\n{\n czm_modelMaterial material;\n material.diffuse = vec3(0.0);\n material.specular = vec3(1.0);\n material.roughness = 1.0;\n material.occlusion = 1.0;\n material.normalEC = vec3(0.0, 0.0, 1.0);\n material.emissive = vec3(0.0);\n material.alpha = 1.0;\n return material;\n}\n\nvec4 handleAlpha(vec3 color, float alpha)\n{\n #ifdef ALPHA_MODE_MASK\n if (alpha < u_alphaCutoff) {\n discard;\n }\n #endif\n\n return vec4(color, alpha);\n}\n\nSelectedFeature selectedFeature;\n\nvoid main()\n{\n #ifdef HAS_POINT_CLOUD_SHOW_STYLE\n if (v_pointCloudShow == 0.0)\n {\n discard;\n }\n #endif\n\n #ifdef HAS_MODEL_SPLITTER\n modelSplitterStage();\n #endif\n\n czm_modelMaterial material = defaultModelMaterial();\n\n ProcessedAttributes attributes;\n geometryStage(attributes);\n\n FeatureIds featureIds;\n featureIdStage(featureIds, attributes);\n\n Metadata metadata;\n MetadataClass metadataClass;\n MetadataStatistics metadataStatistics;\n metadataStage(metadata, metadataClass, metadataStatistics, attributes);\n\n //========================================================================\n // When not picking metadata START\n #ifndef METADATA_PICKING_ENABLED\n\n #ifdef HAS_SELECTED_FEATURE_ID\n selectedFeatureIdStage(selectedFeature, featureIds);\n #endif\n\n #ifndef CUSTOM_SHADER_REPLACE_MATERIAL\n materialStage(material, attributes, selectedFeature);\n #endif\n\n #ifdef HAS_CUSTOM_FRAGMENT_SHADER\n customShaderStage(material, attributes, featureIds, metadata, metadataClass, metadataStatistics);\n #endif\n\n lightingStage(material, attributes);\n\n #ifdef HAS_SELECTED_FEATURE_ID\n cpuStylingStage(material, selectedFeature);\n #endif\n\n #ifdef HAS_MODEL_COLOR\n modelColorStage(material);\n #endif\n\n #ifdef HAS_PRIMITIVE_OUTLINE\n primitiveOutlineStage(material);\n #endif\n\n vec4 color = handleAlpha(material.diffuse, material.alpha);\n\n // When not picking metadata END\n //========================================================================\n #else\n //========================================================================\n // When picking metadata START\n\n vec4 metadataValues = vec4(0.0, 0.0, 0.0, 0.0);\n metadataPickingStage(metadata, metadataClass, metadataValues);\n vec4 color = metadataValues;\n\n #endif\n // When picking metadata END\n //========================================================================\n\n #ifdef HAS_CLIPPING_PLANES\n modelClippingPlanesStage(color);\n #endif\n\n #ifdef ENABLE_CLIPPING_POLYGONS\n modelClippingPolygonsStage();\n #endif\n\n //========================================================================\n // When not picking metadata START\n #ifndef METADATA_PICKING_ENABLED\n\n #if defined(HAS_SILHOUETTE) && defined(HAS_NORMALS)\n silhouetteStage(color);\n #endif\n\n #ifdef HAS_ATMOSPHERE\n atmosphereStage(color, attributes);\n #endif\n\n #endif\n // When not picking metadata END\n //========================================================================\n\n out_FragColor = color;\n}\n\n";
// packages/engine/Source/Scene/Model/ModelDrawCommands.js
function ModelDrawCommands() {
}
ModelDrawCommands.buildModelDrawCommand = function(primitiveRenderResources, frameState) {
const shaderBuilder = primitiveRenderResources.shaderBuilder;
const shaderProgram = createShaderProgram4(
primitiveRenderResources,
shaderBuilder,
frameState
);
const command = buildDrawCommandForModel(
primitiveRenderResources,
shaderProgram,
frameState
);
const model = primitiveRenderResources.model;
const hasClassification = defined_default(model.classificationType);
if (hasClassification) {
return new ClassificationModelDrawCommand_default({
primitiveRenderResources,
command
});
}
return new ModelDrawCommand_default({
primitiveRenderResources,
command
});
};
function createShaderProgram4(primitiveRenderResources, shaderBuilder, frameState) {
shaderBuilder.addVertexLines(ModelVS_default);
shaderBuilder.addFragmentLines(ModelFS_default);
const model = primitiveRenderResources.model;
const shaderProgram = shaderBuilder.buildShaderProgram(frameState.context);
model._pipelineResources.push(shaderProgram);
return shaderProgram;
}
function buildDrawCommandForModel(primitiveRenderResources, shaderProgram, frameState) {
const indexBuffer = getIndexBuffer(primitiveRenderResources);
const vertexArray = new VertexArray_default({
context: frameState.context,
indexBuffer,
attributes: primitiveRenderResources.attributes
});
const model = primitiveRenderResources.model;
model._pipelineResources.push(vertexArray);
const pass = primitiveRenderResources.alphaOptions.pass;
const sceneGraph = model.sceneGraph;
const is3D = frameState.mode === SceneMode_default.SCENE3D;
let modelMatrix, boundingSphere;
if (!is3D && !frameState.scene3DOnly && model._projectTo2D) {
modelMatrix = Matrix4_default.multiplyTransformation(
sceneGraph._computedModelMatrix,
primitiveRenderResources.runtimeNode.computedTransform,
new Matrix4_default()
);
const runtimePrimitive = primitiveRenderResources.runtimePrimitive;
boundingSphere = runtimePrimitive.boundingSphere2D;
} else {
const computedModelMatrix = is3D ? sceneGraph._computedModelMatrix : sceneGraph._computedModelMatrix2D;
modelMatrix = Matrix4_default.multiplyTransformation(
computedModelMatrix,
primitiveRenderResources.runtimeNode.computedTransform,
new Matrix4_default()
);
boundingSphere = BoundingSphere_default.transform(
primitiveRenderResources.boundingSphere,
modelMatrix
);
}
let renderState = clone_default(
RenderState_default.fromCache(primitiveRenderResources.renderStateOptions),
true
);
renderState.cull.face = ModelUtility_default.getCullFace(
modelMatrix,
primitiveRenderResources.primitiveType
);
renderState = RenderState_default.fromCache(renderState);
const hasClassification = defined_default(model.classificationType);
const castShadows = hasClassification ? false : ShadowMode_default.castShadows(model.shadows);
const receiveShadows = hasClassification ? false : ShadowMode_default.receiveShadows(model.shadows);
const pickId = hasClassification ? void 0 : primitiveRenderResources.pickId;
const command = new DrawCommand_default({
boundingVolume: boundingSphere,
modelMatrix,
uniformMap: primitiveRenderResources.uniformMap,
renderState,
vertexArray,
shaderProgram,
cull: model.cull,
pass,
count: primitiveRenderResources.count,
owner: model,
pickId,
pickMetadataAllowed: true,
instanceCount: primitiveRenderResources.instanceCount,
primitiveType: primitiveRenderResources.primitiveType,
debugShowBoundingVolume: model.debugShowBoundingVolume,
castShadows,
receiveShadows
});
return command;
}
function getIndexBuffer(primitiveRenderResources) {
const wireframeIndexBuffer = primitiveRenderResources.wireframeIndexBuffer;
if (defined_default(wireframeIndexBuffer)) {
return wireframeIndexBuffer;
}
const indices = primitiveRenderResources.indices;
if (!defined_default(indices)) {
return void 0;
}
if (!defined_default(indices.buffer)) {
throw new DeveloperError_default("Indices must be provided as a Buffer");
}
return indices.buffer;
}
var ModelDrawCommands_default = ModelDrawCommands;
// packages/engine/Source/Scene/Model/ModelSceneGraph.js
function ModelSceneGraph(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const components = options.modelComponents;
Check_default.typeOf.object("options.model", options.model);
Check_default.typeOf.object("options.modelComponents", components);
this._model = options.model;
this._components = components;
this._pipelineStages = [];
this._updateStages = [];
this._runtimeNodes = [];
this._rootNodes = [];
this._skinnedNodes = [];
this._runtimeSkins = [];
this.modelPipelineStages = [];
this._boundingSphere = void 0;
this._boundingSphere2D = void 0;
this._computedModelMatrix = Matrix4_default.clone(Matrix4_default.IDENTITY);
this._computedModelMatrix2D = Matrix4_default.clone(Matrix4_default.IDENTITY);
this._axisCorrectionMatrix = ModelUtility_default.getAxisCorrectionMatrix(
components.upAxis,
components.forwardAxis,
new Matrix4_default()
);
this._runtimeArticulations = {};
initialize14(this);
}
Object.defineProperties(ModelSceneGraph.prototype, {
/**
* The model components this scene graph represents.
*
* @type {ModelComponents}
* @readonly
*
* @private
*/
components: {
get: function() {
return this._components;
}
},
/**
* The axis-corrected model matrix.
*
* @type {Matrix4}
* @readonly
*
* @private
*/
computedModelMatrix: {
get: function() {
return this._computedModelMatrix;
}
},
/**
* A matrix to correct from y-up in some model formats (e.g. glTF) to the
* z-up coordinate system Cesium uses.
*
* @type {Matrix4}
* @readonly
*
* @private
*/
axisCorrectionMatrix: {
get: function() {
return this._axisCorrectionMatrix;
}
},
/**
* The bounding sphere containing all the primitives in the scene graph
* in model space.
*
* @type {BoundingSphere}
* @readonly
*
* @private
*/
boundingSphere: {
get: function() {
return this._boundingSphere;
}
}
});
function initialize14(sceneGraph) {
const components = sceneGraph._components;
const scene = components.scene;
const model = sceneGraph._model;
const modelMatrix = model.modelMatrix;
computeModelMatrix(sceneGraph, modelMatrix);
const articulations = components.articulations;
const articulationsLength = articulations.length;
const runtimeArticulations = sceneGraph._runtimeArticulations;
for (let i = 0; i < articulationsLength; i++) {
const articulation = articulations[i];
const runtimeArticulation = new ModelArticulation_default({
articulation,
sceneGraph
});
const name = runtimeArticulation.name;
runtimeArticulations[name] = runtimeArticulation;
}
const nodes = components.nodes;
const nodesLength = nodes.length;
sceneGraph._runtimeNodes = new Array(nodesLength);
const rootNodes = scene.nodes;
const rootNodesLength = rootNodes.length;
const transformToRoot = Matrix4_default.IDENTITY;
for (let i = 0; i < rootNodesLength; i++) {
const rootNode = scene.nodes[i];
const rootNodeIndex = traverseAndCreateSceneGraph(
sceneGraph,
rootNode,
transformToRoot
);
sceneGraph._rootNodes.push(rootNodeIndex);
}
const skins = components.skins;
const runtimeSkins = sceneGraph._runtimeSkins;
const skinsLength = skins.length;
for (let i = 0; i < skinsLength; i++) {
const skin = skins[i];
runtimeSkins.push(
new ModelSkin_default({
skin,
sceneGraph
})
);
}
const skinnedNodes = sceneGraph._skinnedNodes;
const skinnedNodesLength = skinnedNodes.length;
for (let i = 0; i < skinnedNodesLength; i++) {
const skinnedNodeIndex = skinnedNodes[i];
const skinnedNode = sceneGraph._runtimeNodes[skinnedNodeIndex];
const skin = nodes[skinnedNodeIndex].skin;
const skinIndex = skin.index;
skinnedNode._runtimeSkin = runtimeSkins[skinIndex];
skinnedNode.updateJointMatrices();
}
sceneGraph.applyArticulations();
}
function computeModelMatrix(sceneGraph, modelMatrix) {
const components = sceneGraph._components;
const model = sceneGraph._model;
sceneGraph._computedModelMatrix = Matrix4_default.multiplyTransformation(
modelMatrix,
components.transform,
sceneGraph._computedModelMatrix
);
sceneGraph._computedModelMatrix = Matrix4_default.multiplyTransformation(
sceneGraph._computedModelMatrix,
sceneGraph._axisCorrectionMatrix,
sceneGraph._computedModelMatrix
);
sceneGraph._computedModelMatrix = Matrix4_default.multiplyByUniformScale(
sceneGraph._computedModelMatrix,
model.computedScale,
sceneGraph._computedModelMatrix
);
}
var scratchComputedTranslation = new Cartesian3_default();
function computeModelMatrix2D(sceneGraph, frameState) {
const computedModelMatrix = sceneGraph._computedModelMatrix;
const translation3 = Matrix4_default.getTranslation(
computedModelMatrix,
scratchComputedTranslation
);
if (!Cartesian3_default.equals(translation3, Cartesian3_default.ZERO)) {
sceneGraph._computedModelMatrix2D = Transforms_default.basisTo2D(
frameState.mapProjection,
computedModelMatrix,
sceneGraph._computedModelMatrix2D
);
} else {
const center = sceneGraph.boundingSphere.center;
const to2D = Transforms_default.ellipsoidTo2DModelMatrix(
frameState.mapProjection,
center,
sceneGraph._computedModelMatrix2D
);
sceneGraph._computedModelMatrix2D = Matrix4_default.multiply(
to2D,
computedModelMatrix,
sceneGraph._computedModelMatrix2D
);
}
sceneGraph._boundingSphere2D = BoundingSphere_default.transform(
sceneGraph._boundingSphere,
sceneGraph._computedModelMatrix2D,
sceneGraph._boundingSphere2D
);
}
function traverseAndCreateSceneGraph(sceneGraph, node, transformToRoot) {
const childrenIndices = [];
const transform3 = ModelUtility_default.getNodeTransform(node);
const childrenLength = node.children.length;
for (let i = 0; i < childrenLength; i++) {
const childNode = node.children[i];
const childNodeTransformToRoot = Matrix4_default.multiplyTransformation(
transformToRoot,
transform3,
new Matrix4_default()
);
const childIndex = traverseAndCreateSceneGraph(
sceneGraph,
childNode,
childNodeTransformToRoot
);
childrenIndices.push(childIndex);
}
const runtimeNode = new ModelRuntimeNode_default({
node,
transform: transform3,
transformToRoot,
children: childrenIndices,
sceneGraph
});
const primitivesLength = node.primitives.length;
for (let i = 0; i < primitivesLength; i++) {
runtimeNode.runtimePrimitives.push(
new ModelRuntimePrimitive_default({
primitive: node.primitives[i],
node,
model: sceneGraph._model
})
);
}
const index = node.index;
sceneGraph._runtimeNodes[index] = runtimeNode;
if (defined_default(node.skin)) {
sceneGraph._skinnedNodes.push(index);
}
const name = node.name;
if (defined_default(name)) {
const model = sceneGraph._model;
const publicNode = new ModelNode_default(model, runtimeNode);
model._nodesByName[name] = publicNode;
}
return index;
}
var scratchModelPositionMin = new Cartesian3_default();
var scratchModelPositionMax = new Cartesian3_default();
var scratchPrimitivePositionMin = new Cartesian3_default();
var scratchPrimitivePositionMax = new Cartesian3_default();
ModelSceneGraph.prototype.buildDrawCommands = function(frameState) {
const modelRenderResources = this.buildRenderResources(frameState);
this.computeBoundingVolumes(modelRenderResources);
this.createDrawCommands(modelRenderResources, frameState);
};
ModelSceneGraph.prototype.buildRenderResources = function(frameState) {
const model = this._model;
const modelRenderResources = new ModelRenderResources_default(model);
model.statistics.clear();
this.configurePipeline(frameState);
const modelPipelineStages = this.modelPipelineStages;
for (let i = 0; i < modelPipelineStages.length; i++) {
const modelPipelineStage = modelPipelineStages[i];
modelPipelineStage.process(modelRenderResources, model, frameState);
}
for (let i = 0; i < this._runtimeNodes.length; i++) {
const runtimeNode = this._runtimeNodes[i];
if (!defined_default(runtimeNode)) {
continue;
}
runtimeNode.configurePipeline();
const nodePipelineStages = runtimeNode.pipelineStages;
const nodeRenderResources = new NodeRenderResources_default(
modelRenderResources,
runtimeNode
);
modelRenderResources.nodeRenderResources[i] = nodeRenderResources;
for (let j = 0; j < nodePipelineStages.length; j++) {
const nodePipelineStage = nodePipelineStages[j];
nodePipelineStage.process(
nodeRenderResources,
runtimeNode.node,
frameState
);
}
for (let j = 0; j < runtimeNode.runtimePrimitives.length; j++) {
const runtimePrimitive = runtimeNode.runtimePrimitives[j];
runtimePrimitive.configurePipeline(frameState);
const primitivePipelineStages = runtimePrimitive.pipelineStages;
const primitiveRenderResources = new PrimitiveRenderResources_default(
nodeRenderResources,
runtimePrimitive
);
nodeRenderResources.primitiveRenderResources[j] = primitiveRenderResources;
for (let k = 0; k < primitivePipelineStages.length; k++) {
const primitivePipelineStage = primitivePipelineStages[k];
primitivePipelineStage.process(
primitiveRenderResources,
runtimePrimitive.primitive,
frameState
);
}
}
}
return modelRenderResources;
};
ModelSceneGraph.prototype.computeBoundingVolumes = function(modelRenderResources) {
const model = this._model;
const modelPositionMin = Cartesian3_default.fromElements(
Number.MAX_VALUE,
Number.MAX_VALUE,
Number.MAX_VALUE,
scratchModelPositionMin
);
const modelPositionMax = Cartesian3_default.fromElements(
-Number.MAX_VALUE,
-Number.MAX_VALUE,
-Number.MAX_VALUE,
scratchModelPositionMax
);
for (let i = 0; i < this._runtimeNodes.length; i++) {
const runtimeNode = this._runtimeNodes[i];
if (!defined_default(runtimeNode)) {
continue;
}
const nodeRenderResources = modelRenderResources.nodeRenderResources[i];
const nodeTransform = runtimeNode.computedTransform;
for (let j = 0; j < runtimeNode.runtimePrimitives.length; j++) {
const runtimePrimitive = runtimeNode.runtimePrimitives[j];
const primitiveRenderResources = nodeRenderResources.primitiveRenderResources[j];
runtimePrimitive.boundingSphere = BoundingSphere_default.clone(
primitiveRenderResources.boundingSphere,
new BoundingSphere_default()
);
const primitivePositionMin = Matrix4_default.multiplyByPoint(
nodeTransform,
primitiveRenderResources.positionMin,
scratchPrimitivePositionMin
);
const primitivePositionMax = Matrix4_default.multiplyByPoint(
nodeTransform,
primitiveRenderResources.positionMax,
scratchPrimitivePositionMax
);
Cartesian3_default.minimumByComponent(
modelPositionMin,
primitivePositionMin,
modelPositionMin
);
Cartesian3_default.maximumByComponent(
modelPositionMax,
primitivePositionMax,
modelPositionMax
);
}
}
this._boundingSphere = BoundingSphere_default.fromCornerPoints(
modelPositionMin,
modelPositionMax,
new BoundingSphere_default()
);
this._boundingSphere = BoundingSphere_default.transformWithoutScale(
this._boundingSphere,
this._axisCorrectionMatrix,
this._boundingSphere
);
this._boundingSphere = BoundingSphere_default.transform(
this._boundingSphere,
this._components.transform,
this._boundingSphere
);
model._boundingSphere = BoundingSphere_default.transform(
this._boundingSphere,
model.modelMatrix,
model._boundingSphere
);
model._initialRadius = model._boundingSphere.radius;
model._boundingSphere.radius *= model._clampedScale;
};
ModelSceneGraph.prototype.createDrawCommands = function(modelRenderResources, frameState) {
for (let i = 0; i < this._runtimeNodes.length; i++) {
const runtimeNode = this._runtimeNodes[i];
if (!defined_default(runtimeNode)) {
continue;
}
const nodeRenderResources = modelRenderResources.nodeRenderResources[i];
for (let j = 0; j < runtimeNode.runtimePrimitives.length; j++) {
const runtimePrimitive = runtimeNode.runtimePrimitives[j];
const primitiveRenderResources = nodeRenderResources.primitiveRenderResources[j];
const drawCommand = ModelDrawCommands_default.buildModelDrawCommand(
primitiveRenderResources,
frameState
);
runtimePrimitive.drawCommand = drawCommand;
}
}
};
ModelSceneGraph.prototype.configurePipeline = function(frameState) {
const modelPipelineStages = this.modelPipelineStages;
modelPipelineStages.length = 0;
const model = this._model;
const fogRenderable = frameState.fog.enabled && frameState.fog.renderable;
if (defined_default(model.color)) {
modelPipelineStages.push(ModelColorPipelineStage_default);
}
if (defined_default(model.classificationType)) {
return;
}
if (model.imageBasedLighting.enabled) {
modelPipelineStages.push(ImageBasedLightingPipelineStage_default);
}
if (model.isClippingEnabled()) {
modelPipelineStages.push(ModelClippingPlanesPipelineStage_default);
}
if (model.isClippingPolygonsEnabled()) {
modelPipelineStages.push(ModelClippingPolygonsPipelineStage_default);
}
if (model.hasSilhouette(frameState)) {
modelPipelineStages.push(ModelSilhouettePipelineStage_default);
}
if (defined_default(model.splitDirection) && model.splitDirection !== SplitDirection_default.NONE) {
modelPipelineStages.push(ModelSplitterPipelineStage_default);
}
if (ModelType_default.is3DTiles(model.type)) {
modelPipelineStages.push(TilesetPipelineStage_default);
}
if (fogRenderable) {
modelPipelineStages.push(AtmospherePipelineStage_default);
}
};
ModelSceneGraph.prototype.update = function(frameState, updateForAnimations) {
let i, j, k;
for (i = 0; i < this._runtimeNodes.length; i++) {
const runtimeNode = this._runtimeNodes[i];
if (!defined_default(runtimeNode)) {
continue;
}
for (j = 0; j < runtimeNode.updateStages.length; j++) {
const nodeUpdateStage = runtimeNode.updateStages[j];
nodeUpdateStage.update(runtimeNode, this, frameState);
}
const disableAnimations = frameState.mode !== SceneMode_default.SCENE3D && this._model._projectTo2D;
if (updateForAnimations && !disableAnimations) {
this.updateJointMatrices();
}
for (j = 0; j < runtimeNode.runtimePrimitives.length; j++) {
const runtimePrimitive = runtimeNode.runtimePrimitives[j];
for (k = 0; k < runtimePrimitive.updateStages.length; k++) {
const stage = runtimePrimitive.updateStages[k];
stage.update(runtimePrimitive, this);
}
}
}
};
ModelSceneGraph.prototype.updateModelMatrix = function(modelMatrix, frameState) {
computeModelMatrix(this, modelMatrix);
if (frameState.mode !== SceneMode_default.SCENE3D) {
computeModelMatrix2D(this, frameState);
}
const rootNodes = this._rootNodes;
for (let i = 0; i < rootNodes.length; i++) {
const node = this._runtimeNodes[rootNodes[i]];
node._transformDirty = true;
}
};
ModelSceneGraph.prototype.updateJointMatrices = function() {
const skinnedNodes = this._skinnedNodes;
const length2 = skinnedNodes.length;
for (let i = 0; i < length2; i++) {
const nodeIndex = skinnedNodes[i];
const runtimeNode = this._runtimeNodes[nodeIndex];
runtimeNode.updateJointMatrices();
}
};
function traverseSceneGraph(sceneGraph, runtimeNode, visibleNodesOnly, callback, callbackOptions) {
if (visibleNodesOnly && !runtimeNode.show) {
return;
}
const childrenLength = runtimeNode.children.length;
for (let i = 0; i < childrenLength; i++) {
const childRuntimeNode = runtimeNode.getChild(i);
traverseSceneGraph(
sceneGraph,
childRuntimeNode,
visibleNodesOnly,
callback,
callbackOptions
);
}
const runtimePrimitives = runtimeNode.runtimePrimitives;
const runtimePrimitivesLength = runtimePrimitives.length;
for (let j = 0; j < runtimePrimitivesLength; j++) {
const runtimePrimitive = runtimePrimitives[j];
callback(runtimePrimitive, callbackOptions);
}
}
function forEachRuntimePrimitive(sceneGraph, visibleNodesOnly, callback, callbackOptions) {
const rootNodes = sceneGraph._rootNodes;
const rootNodesLength = rootNodes.length;
for (let i = 0; i < rootNodesLength; i++) {
const rootNodeIndex = rootNodes[i];
const runtimeNode = sceneGraph._runtimeNodes[rootNodeIndex];
traverseSceneGraph(
sceneGraph,
runtimeNode,
visibleNodesOnly,
callback,
callbackOptions
);
}
}
var scratchBackFaceCullingOptions = {
backFaceCulling: void 0
};
ModelSceneGraph.prototype.updateBackFaceCulling = function(backFaceCulling) {
const backFaceCullingOptions = scratchBackFaceCullingOptions;
backFaceCullingOptions.backFaceCulling = backFaceCulling;
forEachRuntimePrimitive(
this,
false,
updatePrimitiveBackFaceCulling,
backFaceCullingOptions
);
};
function updatePrimitiveBackFaceCulling(runtimePrimitive, options) {
const drawCommand = runtimePrimitive.drawCommand;
drawCommand.backFaceCulling = options.backFaceCulling;
}
var scratchShadowOptions = {
shadowMode: void 0
};
ModelSceneGraph.prototype.updateShadows = function(shadowMode) {
const shadowOptions = scratchShadowOptions;
shadowOptions.shadowMode = shadowMode;
forEachRuntimePrimitive(this, false, updatePrimitiveShadows, shadowOptions);
};
function updatePrimitiveShadows(runtimePrimitive, options) {
const drawCommand = runtimePrimitive.drawCommand;
drawCommand.shadows = options.shadowMode;
}
var scratchShowBoundingVolumeOptions = {
debugShowBoundingVolume: void 0
};
ModelSceneGraph.prototype.updateShowBoundingVolume = function(debugShowBoundingVolume2) {
const showBoundingVolumeOptions = scratchShowBoundingVolumeOptions;
showBoundingVolumeOptions.debugShowBoundingVolume = debugShowBoundingVolume2;
forEachRuntimePrimitive(
this,
false,
updatePrimitiveShowBoundingVolume,
showBoundingVolumeOptions
);
};
function updatePrimitiveShowBoundingVolume(runtimePrimitive, options) {
const drawCommand = runtimePrimitive.drawCommand;
drawCommand.debugShowBoundingVolume = options.debugShowBoundingVolume;
}
var scratchSilhouetteCommands = [];
var scratchPushDrawCommandOptions = {
frameState: void 0,
hasSilhouette: void 0
};
ModelSceneGraph.prototype.pushDrawCommands = function(frameState) {
const silhouetteCommands = scratchSilhouetteCommands;
silhouetteCommands.length = 0;
const pushDrawCommandOptions = scratchPushDrawCommandOptions;
pushDrawCommandOptions.hasSilhouette = this._model.hasSilhouette(frameState);
pushDrawCommandOptions.frameState = frameState;
forEachRuntimePrimitive(
this,
true,
pushPrimitiveDrawCommands,
pushDrawCommandOptions
);
addAllToArray_default(frameState.commandList, silhouetteCommands);
};
function pushPrimitiveDrawCommands(runtimePrimitive, options) {
const frameState = options.frameState;
const hasSilhouette = options.hasSilhouette;
const passes = frameState.passes;
const silhouetteCommands = scratchSilhouetteCommands;
const primitiveDrawCommand = runtimePrimitive.drawCommand;
primitiveDrawCommand.pushCommands(frameState, frameState.commandList);
if (hasSilhouette && !passes.pick) {
primitiveDrawCommand.pushSilhouetteCommands(frameState, silhouetteCommands);
}
}
ModelSceneGraph.prototype.setArticulationStage = function(articulationStageKey, value) {
const names = articulationStageKey.split(" ");
if (names.length !== 2) {
return;
}
const articulationName = names[0];
const stageName = names[1];
const runtimeArticulation = this._runtimeArticulations[articulationName];
if (defined_default(runtimeArticulation)) {
runtimeArticulation.setArticulationStage(stageName, value);
}
};
ModelSceneGraph.prototype.applyArticulations = function() {
const runtimeArticulations = this._runtimeArticulations;
for (const articulationName in runtimeArticulations) {
if (runtimeArticulations.hasOwnProperty(articulationName)) {
const articulation = runtimeArticulations[articulationName];
articulation.apply();
}
}
};
var ModelSceneGraph_default = ModelSceneGraph;
// packages/engine/Source/Scene/Model/ModelStatistics.js
var import_InlineWorkers730 = __toESM(require_InlineWorkers(), 1);
function ModelStatistics() {
this.pointsLength = 0;
this.trianglesLength = 0;
this.geometryByteLength = 0;
this.texturesByteLength = 0;
this.propertyTablesByteLength = 0;
this._bufferIdSet = {};
this._textureIdByteLengths = {};
this._batchTextureIdMap = new AssociativeArray_default();
}
Object.defineProperties(ModelStatistics.prototype, {
/**
* Total size of the batch textures used for picking and styling.
* Batch textures are created asynchronously, so this iterates
* over the textures to ensure their memory values are accurate.
*
* @memberof ModelStatistics.prototype
*
* @type {number}
* @readonly
*
* @private
*/
batchTexturesByteLength: {
get: function() {
const length2 = this._batchTextureIdMap.length;
const values = this._batchTextureIdMap.values;
let memory = 0;
for (let i = 0; i < length2; i++) {
memory += values[i].byteLength;
}
return memory;
}
}
});
ModelStatistics.prototype.clear = function() {
this.pointsLength = 0;
this.trianglesLength = 0;
this.geometryByteLength = 0;
this.texturesByteLength = 0;
this.propertyTablesByteLength = 0;
this._bufferIdSet = {};
this._textureIdByteLengths = {};
this._batchTextureIdMap.removeAll();
};
ModelStatistics.prototype.addBuffer = function(buffer2, hasCpuCopy) {
Check_default.typeOf.object("buffer", buffer2);
Check_default.typeOf.bool("hasCpuCopy", hasCpuCopy);
if (!this._bufferIdSet.hasOwnProperty(buffer2._id)) {
const copies = hasCpuCopy ? 2 : 1;
this.geometryByteLength += buffer2.sizeInBytes * copies;
}
this._bufferIdSet[buffer2._id] = true;
};
ModelStatistics.prototype.addTexture = function(texture) {
Check_default.typeOf.object("texture", texture);
if (!this._textureIdByteLengths.hasOwnProperty(texture._id)) {
this.texturesByteLength += texture.sizeInBytes;
this._textureIdByteLengths[texture._id] = texture.sizeInBytes;
}
};
ModelStatistics.prototype.getTextureIds = function() {
return Object.keys(this._textureIdByteLengths);
};
ModelStatistics.prototype.getTextureByteLengthById = function(textureId) {
return this._textureIdByteLengths[textureId];
};
ModelStatistics.prototype.addBatchTexture = function(batchTexture) {
Check_default.typeOf.object("batchTexture", batchTexture);
if (!this._batchTextureIdMap.contains(batchTexture._id)) {
this._batchTextureIdMap.set(batchTexture._id, batchTexture);
}
};
var ModelStatistics_default = ModelStatistics;
// packages/engine/Source/Scene/Model/PntsLoader.js
var import_InlineWorkers732 = __toESM(require_InlineWorkers(), 1);
var import_mersenne_twister2 = __toESM(require_mersenne_twister(), 1);
// packages/engine/Source/Scene/PntsParser.js
var import_InlineWorkers731 = __toESM(require_InlineWorkers(), 1);
var PntsParser = {};
var sizeOfUint326 = Uint32Array.BYTES_PER_ELEMENT;
PntsParser.parse = function(arrayBuffer, byteOffset) {
byteOffset = byteOffset ?? 0;
Check_default.defined("arrayBuffer", arrayBuffer);
const uint8Array = new Uint8Array(arrayBuffer);
const view = new DataView(arrayBuffer);
byteOffset += sizeOfUint326;
const version2 = view.getUint32(byteOffset, true);
if (version2 !== 1) {
throw new RuntimeError_default(
`Only Point Cloud tile version 1 is supported. Version ${version2} is not.`
);
}
byteOffset += sizeOfUint326;
byteOffset += sizeOfUint326;
const featureTableJsonByteLength = view.getUint32(byteOffset, true);
if (featureTableJsonByteLength === 0) {
throw new RuntimeError_default(
"Feature table must have a byte length greater than zero"
);
}
byteOffset += sizeOfUint326;
const featureTableBinaryByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint326;
const batchTableJsonByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint326;
const batchTableBinaryByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint326;
const featureTableJson = getJsonFromTypedArray_default(
uint8Array,
byteOffset,
featureTableJsonByteLength
);
byteOffset += featureTableJsonByteLength;
const featureTableBinary = new Uint8Array(
arrayBuffer,
byteOffset,
featureTableBinaryByteLength
);
byteOffset += featureTableBinaryByteLength;
let batchTableJson;
let batchTableBinary;
if (batchTableJsonByteLength > 0) {
batchTableJson = getJsonFromTypedArray_default(
uint8Array,
byteOffset,
batchTableJsonByteLength
);
if (Object.keys(batchTableJson).length === 0) {
batchTableJson = void 0;
}
byteOffset += batchTableJsonByteLength;
if (batchTableBinaryByteLength > 0) {
batchTableBinary = new Uint8Array(
arrayBuffer,
byteOffset,
batchTableBinaryByteLength
);
batchTableBinary = new Uint8Array(batchTableBinary);
byteOffset += batchTableBinaryByteLength;
}
}
const featureTable = new Cesium3DTileFeatureTable_default(
featureTableJson,
featureTableBinary
);
const pointsLength = featureTable.getGlobalProperty("POINTS_LENGTH");
featureTable.featuresLength = pointsLength;
if (!defined_default(pointsLength)) {
throw new RuntimeError_default(
"Feature table global property: POINTS_LENGTH must be defined"
);
}
let rtcCenter = featureTable.getGlobalProperty(
"RTC_CENTER",
ComponentDatatype_default.FLOAT,
3
);
if (defined_default(rtcCenter)) {
rtcCenter = Cartesian3_default.unpack(rtcCenter);
}
const parsedContent = parseDracoProperties(featureTable, batchTableJson);
parsedContent.rtcCenter = rtcCenter;
parsedContent.pointsLength = pointsLength;
if (!parsedContent.hasPositions) {
const positions = parsePositions(featureTable);
parsedContent.positions = positions;
parsedContent.hasPositions = parsedContent.hasPositions || defined_default(positions);
}
if (!parsedContent.hasPositions) {
throw new RuntimeError_default(
"Either POSITION or POSITION_QUANTIZED must be defined."
);
}
if (!parsedContent.hasNormals) {
const normals = parseNormals(featureTable);
parsedContent.normals = normals;
parsedContent.hasNormals = parsedContent.hasNormals || defined_default(normals);
}
if (!parsedContent.hasColors) {
const colors = parseColors(featureTable);
parsedContent.colors = colors;
parsedContent.hasColors = parsedContent.hasColors || defined_default(colors);
parsedContent.hasConstantColor = defined_default(parsedContent.constantColor);
parsedContent.isTranslucent = defined_default(colors) && colors.isTranslucent;
}
if (!parsedContent.hasBatchIds) {
const batchIds = parseBatchIds(featureTable);
parsedContent.batchIds = batchIds;
parsedContent.hasBatchIds = parsedContent.hasBatchIds || defined_default(batchIds);
}
if (parsedContent.hasBatchIds) {
const batchLength = featureTable.getGlobalProperty("BATCH_LENGTH");
if (!defined_default(batchLength)) {
throw new RuntimeError_default(
"Global property: BATCH_LENGTH must be defined when BATCH_ID is defined."
);
}
parsedContent.batchLength = batchLength;
}
if (defined_default(batchTableJson) || defined_default(batchTableBinary)) {
parsedContent.batchTableJson = batchTableJson;
parsedContent.batchTableBinary = batchTableBinary;
}
return parsedContent;
};
function parseDracoProperties(featureTable, batchTableJson) {
const featureTableJson = featureTable.json;
let dracoBuffer;
let dracoFeatureTableProperties;
let dracoBatchTableProperties;
const featureTableDraco = defined_default(featureTableJson.extensions) ? featureTableJson.extensions["3DTILES_draco_point_compression"] : void 0;
const batchTableDraco = defined_default(batchTableJson) && defined_default(batchTableJson.extensions) ? batchTableJson.extensions["3DTILES_draco_point_compression"] : void 0;
if (defined_default(batchTableDraco)) {
dracoBatchTableProperties = batchTableDraco.properties;
}
let hasPositions;
let hasColors;
let hasNormals;
let hasBatchIds;
let isTranslucent;
if (defined_default(featureTableDraco)) {
dracoFeatureTableProperties = featureTableDraco.properties;
const dracoByteOffset = featureTableDraco.byteOffset;
const dracoByteLength = featureTableDraco.byteLength;
if (!defined_default(dracoFeatureTableProperties) || !defined_default(dracoByteOffset) || !defined_default(dracoByteLength)) {
throw new RuntimeError_default(
"Draco properties, byteOffset, and byteLength must be defined"
);
}
dracoBuffer = featureTable.buffer.slice(
dracoByteOffset,
dracoByteOffset + dracoByteLength
);
hasPositions = defined_default(dracoFeatureTableProperties.POSITION);
hasColors = defined_default(dracoFeatureTableProperties.RGB) || defined_default(dracoFeatureTableProperties.RGBA);
hasNormals = defined_default(dracoFeatureTableProperties.NORMAL);
hasBatchIds = defined_default(dracoFeatureTableProperties.BATCH_ID);
isTranslucent = defined_default(dracoFeatureTableProperties.RGBA);
}
let draco;
if (defined_default(dracoBuffer)) {
draco = {
buffer: dracoBuffer,
featureTableProperties: dracoFeatureTableProperties,
batchTableProperties: dracoBatchTableProperties,
properties: combine_default(
dracoFeatureTableProperties,
dracoBatchTableProperties
),
dequantizeInShader: true
};
}
return {
draco,
hasPositions,
hasColors,
isTranslucent,
hasNormals,
hasBatchIds
};
}
function parsePositions(featureTable) {
const featureTableJson = featureTable.json;
let positions;
if (defined_default(featureTableJson.POSITION)) {
positions = featureTable.getPropertyArray(
"POSITION",
ComponentDatatype_default.FLOAT,
3
);
return {
name: VertexAttributeSemantic_default.POSITION,
semantic: VertexAttributeSemantic_default.POSITION,
typedArray: positions,
isQuantized: false,
componentDatatype: ComponentDatatype_default.FLOAT,
type: AttributeType_default.VEC3
};
} else if (defined_default(featureTableJson.POSITION_QUANTIZED)) {
positions = featureTable.getPropertyArray(
"POSITION_QUANTIZED",
ComponentDatatype_default.UNSIGNED_SHORT,
3
);
const quantizedVolumeScale = featureTable.getGlobalProperty(
"QUANTIZED_VOLUME_SCALE",
ComponentDatatype_default.FLOAT,
3
);
if (!defined_default(quantizedVolumeScale)) {
throw new RuntimeError_default(
"Global property: QUANTIZED_VOLUME_SCALE must be defined for quantized positions."
);
}
const quantizedRange = (1 << 16) - 1;
const quantizedVolumeOffset = featureTable.getGlobalProperty(
"QUANTIZED_VOLUME_OFFSET",
ComponentDatatype_default.FLOAT,
3
);
if (!defined_default(quantizedVolumeOffset)) {
throw new RuntimeError_default(
"Global property: QUANTIZED_VOLUME_OFFSET must be defined for quantized positions."
);
}
return {
name: VertexAttributeSemantic_default.POSITION,
semantic: VertexAttributeSemantic_default.POSITION,
typedArray: positions,
isQuantized: true,
componentDatatype: ComponentDatatype_default.FLOAT,
type: AttributeType_default.VEC3,
quantizedRange,
quantizedVolumeOffset: Cartesian3_default.unpack(quantizedVolumeOffset),
quantizedVolumeScale: Cartesian3_default.unpack(quantizedVolumeScale),
quantizedComponentDatatype: ComponentDatatype_default.UNSIGNED_SHORT,
quantizedType: AttributeType_default.VEC3
};
}
}
function parseColors(featureTable) {
const featureTableJson = featureTable.json;
let colors;
if (defined_default(featureTableJson.RGBA)) {
colors = featureTable.getPropertyArray(
"RGBA",
ComponentDatatype_default.UNSIGNED_BYTE,
4
);
return {
name: VertexAttributeSemantic_default.COLOR,
semantic: VertexAttributeSemantic_default.COLOR,
setIndex: 0,
typedArray: colors,
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
type: AttributeType_default.VEC4,
normalized: true,
isRGB565: false,
isTranslucent: true
};
} else if (defined_default(featureTableJson.RGB)) {
colors = featureTable.getPropertyArray(
"RGB",
ComponentDatatype_default.UNSIGNED_BYTE,
3
);
return {
name: "COLOR",
semantic: VertexAttributeSemantic_default.COLOR,
setIndex: 0,
typedArray: colors,
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
type: AttributeType_default.VEC3,
normalized: true,
isRGB565: false,
isTranslucent: false
};
} else if (defined_default(featureTableJson.RGB565)) {
colors = featureTable.getPropertyArray(
"RGB565",
ComponentDatatype_default.UNSIGNED_SHORT,
1
);
return {
name: "COLOR",
semantic: VertexAttributeSemantic_default.COLOR,
setIndex: 0,
typedArray: colors,
// These settings are for the Model implementation
// which decodes on the CPU and uploads a VEC3 of float colors.
// PointCloud does the decoding on the GPU so uploads a
// UNSIGNED_SHORT instead.
componentDatatype: ComponentDatatype_default.FLOAT,
type: AttributeType_default.VEC3,
normalized: false,
isRGB565: true,
isTranslucent: false
};
} else if (defined_default(featureTableJson.CONSTANT_RGBA)) {
const constantRGBA = featureTable.getGlobalProperty(
"CONSTANT_RGBA",
ComponentDatatype_default.UNSIGNED_BYTE,
4
);
const alpha = constantRGBA[3];
const constantColor = Color_default.fromBytes(
constantRGBA[0],
constantRGBA[1],
constantRGBA[2],
alpha
);
const isTranslucent = alpha < 255;
return {
name: VertexAttributeSemantic_default.COLOR,
semantic: VertexAttributeSemantic_default.COLOR,
setIndex: 0,
constantColor,
componentDatatype: ComponentDatatype_default.FLOAT,
type: AttributeType_default.VEC4,
isQuantized: false,
isTranslucent
};
}
return void 0;
}
function parseNormals(featureTable) {
const featureTableJson = featureTable.json;
let normals;
if (defined_default(featureTableJson.NORMAL)) {
normals = featureTable.getPropertyArray(
"NORMAL",
ComponentDatatype_default.FLOAT,
3
);
return {
name: VertexAttributeSemantic_default.NORMAL,
semantic: VertexAttributeSemantic_default.NORMAL,
typedArray: normals,
octEncoded: false,
octEncodedZXY: false,
componentDatatype: ComponentDatatype_default.FLOAT,
type: AttributeType_default.VEC3
};
} else if (defined_default(featureTableJson.NORMAL_OCT16P)) {
normals = featureTable.getPropertyArray(
"NORMAL_OCT16P",
ComponentDatatype_default.UNSIGNED_BYTE,
2
);
const quantizationBits = 8;
return {
name: VertexAttributeSemantic_default.NORMAL,
semantic: VertexAttributeSemantic_default.NORMAL,
typedArray: normals,
octEncoded: true,
octEncodedZXY: false,
quantizedRange: (1 << quantizationBits) - 1,
quantizedType: AttributeType_default.VEC2,
quantizedComponentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentDatatype: ComponentDatatype_default.FLOAT,
type: AttributeType_default.VEC3
};
}
return void 0;
}
function parseBatchIds(featureTable) {
const featureTableJson = featureTable.json;
if (defined_default(featureTableJson.BATCH_ID)) {
const batchIds = featureTable.getPropertyArray(
"BATCH_ID",
ComponentDatatype_default.UNSIGNED_SHORT,
1
);
return {
name: VertexAttributeSemantic_default.FEATURE_ID,
semantic: VertexAttributeSemantic_default.FEATURE_ID,
setIndex: 0,
typedArray: batchIds,
componentDatatype: ComponentDatatype_default.fromTypedArray(batchIds),
type: AttributeType_default.SCALAR
};
}
return void 0;
}
var PntsParser_default = PntsParser;
// packages/engine/Source/Scene/Model/PntsLoader.js
var Components3 = ModelComponents_default.Components;
var Scene3 = ModelComponents_default.Scene;
var Node5 = ModelComponents_default.Node;
var Primitive4 = ModelComponents_default.Primitive;
var Attribute4 = ModelComponents_default.Attribute;
var Quantization2 = ModelComponents_default.Quantization;
var FeatureIdAttribute5 = ModelComponents_default.FeatureIdAttribute;
var Material5 = ModelComponents_default.Material;
var MetallicRoughness4 = ModelComponents_default.MetallicRoughness;
function PntsLoader(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const arrayBuffer = options.arrayBuffer;
const byteOffset = options.byteOffset ?? 0;
Check_default.typeOf.object("options.arrayBuffer", arrayBuffer);
this._arrayBuffer = arrayBuffer;
this._byteOffset = byteOffset;
this._loadAttributesFor2D = options.loadAttributesFor2D ?? false;
this._parsedContent = void 0;
this._decodePromise = void 0;
this._decodedAttributes = void 0;
this._promise = void 0;
this._error = void 0;
this._state = ResourceLoaderState_default.UNLOADED;
this._buffers = [];
this._components = void 0;
this._transform = Matrix4_default.IDENTITY;
}
if (defined_default(Object.create)) {
PntsLoader.prototype = Object.create(ResourceLoader_default.prototype);
PntsLoader.prototype.constructor = PntsLoader;
}
Object.defineProperties(PntsLoader.prototype, {
/**
* The cache key of the resource
*
* @memberof PntsLoader.prototype
*
* @type {string}
* @readonly
* @private
*/
cacheKey: {
get: function() {
return void 0;
}
},
/**
* The loaded components.
*
* @memberof PntsLoader.prototype
*
* @type {ModelComponents.Components}
* @readonly
* @private
*/
components: {
get: function() {
return this._components;
}
},
/**
* A world-space transform to apply to the primitives.
* See {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification/TileFormats/PointCloud#global-semantics}
*
* @memberof PntsLoader.prototype
*
* @type {Matrix4}
* @readonly
* @private
*/
transform: {
get: function() {
return this._transform;
}
}
});
PntsLoader.prototype.load = function() {
if (defined_default(this._promise)) {
return this._promise;
}
this._parsedContent = PntsParser_default.parse(this._arrayBuffer, this._byteOffset);
this._state = ResourceLoaderState_default.PROCESSING;
this._promise = Promise.resolve(this);
};
PntsLoader.prototype.process = function(frameState) {
if (defined_default(this._error)) {
const error = this._error;
this._error = void 0;
throw error;
}
if (this._state === ResourceLoaderState_default.READY) {
return true;
}
if (this._state === ResourceLoaderState_default.PROCESSING) {
if (defined_default(this._decodePromise)) {
return false;
}
this._decodePromise = decodeDraco(this, frameState.context);
}
return false;
};
function decodeDraco(loader, context) {
const parsedContent = loader._parsedContent;
const draco = parsedContent.draco;
let decodePromise;
if (!defined_default(draco)) {
decodePromise = Promise.resolve();
} else {
decodePromise = DracoLoader_default.decodePointCloud(draco, context);
}
if (!defined_default(decodePromise)) {
return;
}
loader._decodePromise = decodePromise;
return decodePromise.then(function(decodeDracoResult) {
if (loader.isDestroyed()) {
return;
}
if (defined_default(decodeDracoResult)) {
processDracoAttributes(loader, draco, decodeDracoResult);
}
makeComponents(loader, context);
loader._state = ResourceLoaderState_default.READY;
return loader;
}).catch(function(error) {
loader.unload();
loader._state = ResourceLoaderState_default.FAILED;
const errorMessage = "Failed to load Draco pnts";
loader._error = loader.getError(errorMessage, error);
});
}
function processDracoAttributes(loader, draco, result) {
loader._state = ResourceLoaderState_default.READY;
const parsedContent = loader._parsedContent;
let attribute;
if (defined_default(result.POSITION)) {
attribute = {
name: "POSITION",
semantic: VertexAttributeSemantic_default.POSITION,
typedArray: result.POSITION.array,
componentDatatype: ComponentDatatype_default.FLOAT,
type: AttributeType_default.VEC3,
isQuantized: false
};
if (defined_default(result.POSITION.data.quantization)) {
const quantization = result.POSITION.data.quantization;
const range = quantization.range;
const quantizedVolumeScale = Cartesian3_default.fromElements(range, range, range);
const quantizedVolumeOffset = Cartesian3_default.unpack(quantization.minValues);
const quantizedRange = (1 << quantization.quantizationBits) - 1;
attribute.isQuantized = true;
attribute.quantizedRange = quantizedRange;
attribute.quantizedVolumeOffset = quantizedVolumeOffset;
attribute.quantizedVolumeScale = quantizedVolumeScale;
attribute.quantizedComponentDatatype = quantizedRange <= 255 ? ComponentDatatype_default.UNSIGNED_BYTE : ComponentDatatype_default.UNSIGNED_SHORT;
attribute.quantizedType = AttributeType_default.VEC3;
}
parsedContent.positions = attribute;
}
if (defined_default(result.NORMAL)) {
attribute = {
name: "NORMAL",
semantic: VertexAttributeSemantic_default.NORMAL,
typedArray: result.NORMAL.array,
componentDatatype: ComponentDatatype_default.FLOAT,
type: AttributeType_default.VEC3,
isQuantized: false,
octEncoded: false,
octEncodedZXY: false
};
if (defined_default(result.NORMAL.data.quantization)) {
const octEncodedRange = (1 << result.NORMAL.data.quantization.quantizationBits) - 1;
attribute.quantizedRange = octEncodedRange;
attribute.octEncoded = true;
attribute.octEncodedZXY = true;
attribute.quantizedComponentDatatype = ComponentDatatype_default.UNSIGNED_BYTE;
attribute.quantizedType = AttributeType_default.VEC2;
}
parsedContent.normals = attribute;
}
if (defined_default(result.RGBA)) {
parsedContent.colors = {
name: "COLOR",
semantic: VertexAttributeSemantic_default.COLOR,
setIndex: 0,
typedArray: result.RGBA.array,
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
type: AttributeType_default.VEC4,
normalized: true,
isTranslucent: true
};
} else if (defined_default(result.RGB)) {
parsedContent.colors = {
name: "COLOR",
semantic: VertexAttributeSemantic_default.COLOR,
setIndex: 0,
typedArray: result.RGB.array,
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
type: AttributeType_default.VEC3,
normalized: true,
isTranslucent: false
};
}
if (defined_default(result.BATCH_ID)) {
const batchIds = result.BATCH_ID.array;
parsedContent.batchIds = {
name: "_FEATURE_ID",
semantic: VertexAttributeSemantic_default.FEATURE_ID,
setIndex: 0,
typedArray: batchIds,
componentDatatype: ComponentDatatype_default.fromTypedArray(batchIds),
type: AttributeType_default.SCALAR
};
}
let batchTableJson = parsedContent.batchTableJson;
const batchTableProperties = draco.batchTableProperties;
for (const name in batchTableProperties) {
if (batchTableProperties.hasOwnProperty(name)) {
const property = result[name];
if (!defined_default(batchTableJson)) {
batchTableJson = {};
}
parsedContent.hasDracoBatchTable = true;
const data = property.data;
batchTableJson[name] = {
byteOffset: data.byteOffset,
// Draco returns the results like glTF values, but here
// we want to transcode to a batch table. It's redundant
// but necessary to use parseBatchTable()
type: transcodeAttributeType(data.componentsPerAttribute),
componentType: transcodeComponentType2(data.componentDatatype),
// Each property is stored as a separate typed array, so
// store it here. parseBatchTable() will check for this
// instead of the entire binary body.
typedArray: property.array
};
}
}
parsedContent.batchTableJson = batchTableJson;
}
function transcodeAttributeType(componentsPerAttribute) {
switch (componentsPerAttribute) {
case 1:
return "SCALAR";
case 2:
return "VEC2";
case 3:
return "VEC3";
case 4:
return "VEC4";
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default(
"componentsPerAttribute must be a number from 1-4"
);
}
}
function transcodeComponentType2(value) {
switch (value) {
case WebGLConstants_default.BYTE:
return "BYTE";
case WebGLConstants_default.UNSIGNED_BYTE:
return "UNSIGNED_BYTE";
case WebGLConstants_default.SHORT:
return "SHORT";
case WebGLConstants_default.UNSIGNED_SHORT:
return "UNSIGNED_SHORT";
case WebGLConstants_default.INT:
return "INT";
case WebGLConstants_default.UNSIGNED_INT:
return "UNSIGNED_INT";
case WebGLConstants_default.DOUBLE:
return "DOUBLE";
case WebGLConstants_default.FLOAT:
return "FLOAT";
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default("value is not a valid WebGL constant");
}
}
function makeAttribute(loader, attributeInfo, context) {
let typedArray = attributeInfo.typedArray;
let quantization;
if (attributeInfo.octEncoded) {
quantization = new Quantization2();
quantization.octEncoded = attributeInfo.octEncoded;
quantization.octEncodedZXY = attributeInfo.octEncodedZXY;
quantization.normalizationRange = attributeInfo.quantizedRange;
quantization.type = attributeInfo.quantizedType;
quantization.componentDatatype = attributeInfo.quantizedComponentDatatype;
}
if (attributeInfo.isQuantized) {
quantization = new Quantization2();
const normalizationRange = attributeInfo.quantizedRange;
quantization.normalizationRange = normalizationRange;
quantization.quantizedVolumeOffset = Cartesian3_default.ZERO;
const quantizedVolumeDimensions = attributeInfo.quantizedVolumeScale;
quantization.quantizedVolumeDimensions = quantizedVolumeDimensions;
quantization.quantizedVolumeStepSize = Cartesian3_default.divideByScalar(
quantizedVolumeDimensions,
normalizationRange,
new Cartesian3_default()
);
quantization.componentDatatype = attributeInfo.quantizedComponentDatatype;
quantization.type = attributeInfo.quantizedType;
}
const attribute = new Attribute4();
attribute.name = attributeInfo.name;
attribute.semantic = attributeInfo.semantic;
attribute.setIndex = attributeInfo.setIndex;
attribute.componentDatatype = attributeInfo.componentDatatype;
attribute.type = attributeInfo.type;
attribute.normalized = attributeInfo.normalized ?? false;
attribute.min = attributeInfo.min;
attribute.max = attributeInfo.max;
attribute.quantization = quantization;
if (attributeInfo.isRGB565) {
typedArray = AttributeCompression_default.decodeRGB565(typedArray);
}
if (defined_default(attributeInfo.constantColor)) {
const packedColor = new Array(4);
attribute.constant = Color_default.pack(attributeInfo.constantColor, packedColor);
} else {
const buffer2 = Buffer_default.createVertexBuffer({
typedArray,
context,
usage: BufferUsage_default.STATIC_DRAW
});
buffer2.vertexArrayDestroyable = false;
loader._buffers.push(buffer2);
attribute.buffer = buffer2;
}
const loadAttributesFor2D = loader._loadAttributesFor2D;
if (attribute.semantic === VertexAttributeSemantic_default.POSITION && loadAttributesFor2D) {
attribute.typedArray = typedArray;
}
return attribute;
}
var randomNumberGenerator2;
var randomValues;
function getRandomValues(samplesLength) {
if (!defined_default(randomValues)) {
randomNumberGenerator2 = new import_mersenne_twister2.default(0);
randomValues = new Array(samplesLength);
for (let i = 0; i < samplesLength; ++i) {
randomValues[i] = randomNumberGenerator2.random();
}
}
return randomValues;
}
var scratchMin3 = new Cartesian3_default();
var scratchMax3 = new Cartesian3_default();
var scratchPosition4 = new Cartesian3_default();
function computeApproximateExtrema(positions) {
const positionsArray = positions.typedArray;
const maximumSamplesLength = 20;
const pointsLength = positionsArray.length / 3;
const samplesLength = Math.min(pointsLength, maximumSamplesLength);
const randomValues3 = getRandomValues(maximumSamplesLength);
const maxValue = Number.MAX_VALUE;
const minValue = -Number.MAX_VALUE;
let min3 = Cartesian3_default.fromElements(maxValue, maxValue, maxValue, scratchMin3);
let max3 = Cartesian3_default.fromElements(minValue, minValue, minValue, scratchMax3);
let i;
let index;
let position;
if (positions.isQuantized) {
min3 = Cartesian3_default.ZERO;
max3 = positions.quantizedVolumeScale;
} else {
for (i = 0; i < samplesLength; ++i) {
index = Math.floor(randomValues3[i] * pointsLength);
position = Cartesian3_default.unpack(positionsArray, index * 3, scratchPosition4);
Cartesian3_default.minimumByComponent(min3, position, min3);
Cartesian3_default.maximumByComponent(max3, position, max3);
}
}
positions.min = Cartesian3_default.clone(min3);
positions.max = Cartesian3_default.clone(max3);
}
var defaultColorAttribute = {
name: VertexAttributeSemantic_default.COLOR,
semantic: VertexAttributeSemantic_default.COLOR,
setIndex: 0,
constantColor: Color_default.DARKGRAY,
componentDatatype: ComponentDatatype_default.FLOAT,
type: AttributeType_default.VEC4,
isQuantized: false,
isTranslucent: false
};
function makeAttributes(loader, parsedContent, context) {
const attributes = [];
let attribute;
const positions = parsedContent.positions;
if (defined_default(positions)) {
computeApproximateExtrema(positions);
attribute = makeAttribute(loader, positions, context);
attribute.count = parsedContent.pointsLength;
attributes.push(attribute);
}
if (defined_default(parsedContent.normals)) {
attribute = makeAttribute(loader, parsedContent.normals, context);
attributes.push(attribute);
}
if (defined_default(parsedContent.colors)) {
attribute = makeAttribute(loader, parsedContent.colors, context);
attributes.push(attribute);
} else {
attribute = makeAttribute(loader, defaultColorAttribute, context);
attributes.push(attribute);
}
if (defined_default(parsedContent.batchIds)) {
attribute = makeAttribute(loader, parsedContent.batchIds, context);
attributes.push(attribute);
}
return attributes;
}
function makeStructuralMetadata(parsedContent, customAttributeOutput) {
const batchLength = parsedContent.batchLength;
const pointsLength = parsedContent.pointsLength;
const batchTableJson = parsedContent.batchTableJson;
const batchTableBinary = parsedContent.batchTableBinary;
const parseAsPropertyAttributes = !defined_default(parsedContent.batchIds);
if (defined_default(batchTableBinary) || defined_default(batchTableJson) || parsedContent.hasDracoBatchTable) {
const count = batchLength ?? pointsLength;
return parseBatchTable_default({
count,
batchTable: batchTableJson,
binaryBody: batchTableBinary,
parseAsPropertyAttributes,
customAttributeOutput
});
}
return new StructuralMetadata_default({
schema: {},
propertyTables: []
});
}
function makeComponents(loader, context) {
const parsedContent = loader._parsedContent;
const metallicRoughness = new MetallicRoughness4();
metallicRoughness.metallicFactor = 0;
metallicRoughness.roughnessFactor = 0.9;
const material = new Material5();
material.metallicRoughness = metallicRoughness;
const colors = parsedContent.colors;
if (defined_default(colors) && colors.isTranslucent) {
material.alphaMode = AlphaMode_default.BLEND;
}
const isUnlit = !defined_default(parsedContent.normals);
material.unlit = isUnlit;
const primitive = new Primitive4();
primitive.attributes = makeAttributes(loader, parsedContent, context);
primitive.primitiveType = PrimitiveType_default.POINTS;
primitive.material = material;
if (defined_default(parsedContent.batchIds)) {
const featureIdAttribute = new FeatureIdAttribute5();
featureIdAttribute.propertyTableId = 0;
featureIdAttribute.setIndex = 0;
featureIdAttribute.positionalLabel = "featureId_0";
primitive.featureIds.push(featureIdAttribute);
}
const node = new Node5();
node.index = 0;
node.primitives = [primitive];
const scene = new Scene3();
scene.nodes = [node];
scene.upAxis = Axis_default.Z;
scene.forwardAxis = Axis_default.X;
const components = new Components3();
components.scene = scene;
components.nodes = [node];
const customAttributeOutput = [];
components.structuralMetadata = makeStructuralMetadata(
parsedContent,
customAttributeOutput
);
if (customAttributeOutput.length > 0) {
addPropertyAttributesToPrimitive(
loader,
primitive,
customAttributeOutput,
context
);
}
if (defined_default(parsedContent.rtcCenter)) {
components.transform = Matrix4_default.multiplyByTranslation(
components.transform,
parsedContent.rtcCenter,
components.transform
);
}
const positions = parsedContent.positions;
if (defined_default(positions) && positions.isQuantized) {
components.transform = Matrix4_default.multiplyByTranslation(
components.transform,
positions.quantizedVolumeOffset,
components.transform
);
}
loader._components = components;
loader._parsedContent = void 0;
loader._arrayBuffer = void 0;
}
function addPropertyAttributesToPrimitive(loader, primitive, customAttributes, context) {
const attributes = primitive.attributes;
const length2 = customAttributes.length;
for (let i = 0; i < length2; i++) {
const customAttribute = customAttributes[i];
const buffer2 = Buffer_default.createVertexBuffer({
typedArray: customAttribute.typedArray,
context,
usage: BufferUsage_default.STATIC_DRAW
});
buffer2.vertexArrayDestroyable = false;
loader._buffers.push(buffer2);
customAttribute.buffer = buffer2;
customAttribute.typedArray = void 0;
attributes.push(customAttribute);
}
primitive.propertyAttributeIds = [0];
}
PntsLoader.prototype.unload = function() {
const buffers = this._buffers;
for (let i = 0; i < buffers.length; i++) {
buffers[i].destroy();
}
buffers.length = 0;
this._components = void 0;
this._parsedContent = void 0;
this._arrayBuffer = void 0;
};
var PntsLoader_default = PntsLoader;
// packages/engine/Source/Scene/Model/pickModel.js
var import_InlineWorkers733 = __toESM(require_InlineWorkers(), 1);
var scratchV0 = new Cartesian3_default();
var scratchV1 = new Cartesian3_default();
var scratchV2 = new Cartesian3_default();
var scratchNodeComputedTransform = new Matrix4_default();
var scratchModelMatrix2 = new Matrix4_default();
var scratchcomputedModelMatrix = new Matrix4_default();
var scratchPickCartographic = new Cartographic_default();
var scratchBoundingSphere4 = new BoundingSphere_default();
function pickModel(model, ray, frameState, verticalExaggeration, relativeHeight, ellipsoid, result) {
Check_default.typeOf.object("model", model);
Check_default.typeOf.object("ray", ray);
Check_default.typeOf.object("frameState", frameState);
if (!model._ready || frameState.mode === SceneMode_default.MORPHING) {
return;
}
let minT = Number.MAX_VALUE;
const sceneGraph = model.sceneGraph;
const nodes = sceneGraph._runtimeNodes;
for (let i = 0; i < nodes.length; i++) {
const runtimeNode = nodes[i];
const node = runtimeNode.node;
let nodeComputedTransform = Matrix4_default.clone(
runtimeNode.computedTransform,
scratchNodeComputedTransform
);
let modelMatrix = Matrix4_default.clone(
sceneGraph.computedModelMatrix,
scratchModelMatrix2
);
const instances = node.instances;
if (defined_default(instances)) {
if (instances.transformInWorldSpace) {
modelMatrix = Matrix4_default.multiplyTransformation(
model.modelMatrix,
sceneGraph.components.transform,
modelMatrix
);
nodeComputedTransform = Matrix4_default.multiplyTransformation(
sceneGraph.axisCorrectionMatrix,
runtimeNode.computedTransform,
nodeComputedTransform
);
}
}
let computedModelMatrix = Matrix4_default.multiplyTransformation(
modelMatrix,
nodeComputedTransform,
scratchcomputedModelMatrix
);
if (frameState.mode !== SceneMode_default.SCENE3D) {
computedModelMatrix = Transforms_default.basisTo2D(
frameState.mapProjection,
computedModelMatrix,
computedModelMatrix
);
}
const transforms = [];
if (defined_default(instances)) {
const transformsCount = instances.attributes[0].count;
const instanceComponentDatatype = instances.attributes[0].componentDatatype;
const transformElements = 12;
let transformsTypedArray = runtimeNode.transformsTypedArray;
if (!defined_default(transformsTypedArray)) {
const instanceTransformsBuffer = runtimeNode.instancingTransformsBuffer;
if (defined_default(instanceTransformsBuffer) && frameState.context.webgl2) {
transformsTypedArray = ComponentDatatype_default.createTypedArray(
instanceComponentDatatype,
transformsCount * transformElements
);
instanceTransformsBuffer.getBufferData(transformsTypedArray);
}
}
if (defined_default(transformsTypedArray)) {
for (let i2 = 0; i2 < transformsCount; i2++) {
const index = i2 * transformElements;
const transform3 = new Matrix4_default(
transformsTypedArray[index],
transformsTypedArray[index + 1],
transformsTypedArray[index + 2],
transformsTypedArray[index + 3],
transformsTypedArray[index + 4],
transformsTypedArray[index + 5],
transformsTypedArray[index + 6],
transformsTypedArray[index + 7],
transformsTypedArray[index + 8],
transformsTypedArray[index + 9],
transformsTypedArray[index + 10],
transformsTypedArray[index + 11],
0,
0,
0,
1
);
if (instances.transformInWorldSpace) {
Matrix4_default.multiplyTransformation(
transform3,
nodeComputedTransform,
transform3
);
Matrix4_default.multiplyTransformation(modelMatrix, transform3, transform3);
} else {
Matrix4_default.multiplyTransformation(
transform3,
computedModelMatrix,
transform3
);
}
transforms.push(transform3);
}
}
}
if (transforms.length === 0) {
transforms.push(computedModelMatrix);
}
const primitivesLength = runtimeNode.runtimePrimitives.length;
for (let j = 0; j < primitivesLength; j++) {
const runtimePrimitive = runtimeNode.runtimePrimitives[j];
const primitive = runtimePrimitive.primitive;
if (defined_default(runtimePrimitive.boundingSphere) && !defined_default(instances)) {
const boundingSphere = BoundingSphere_default.transform(
runtimePrimitive.boundingSphere,
computedModelMatrix,
scratchBoundingSphere4
);
const boundsIntersection = IntersectionTests_default.raySphere(
ray,
boundingSphere
);
if (!defined_default(boundsIntersection)) {
continue;
}
}
const positionAttribute = ModelUtility_default.getAttributeBySemantic(
primitive,
VertexAttributeSemantic_default.POSITION
);
const byteOffset = positionAttribute.byteOffset;
const byteStride = positionAttribute.byteStride;
const vertexCount = positionAttribute.count;
if (!defined_default(primitive.indices)) {
continue;
}
let indices = primitive.indices.typedArray;
if (!defined_default(indices)) {
const indicesBuffer = primitive.indices.buffer;
const indicesCount = primitive.indices.count;
const indexDatatype = primitive.indices.indexDatatype;
if (defined_default(indicesBuffer) && frameState.context.webgl2) {
if (indexDatatype === IndexDatatype_default.UNSIGNED_BYTE) {
indices = new Uint8Array(indicesCount);
} else if (indexDatatype === IndexDatatype_default.UNSIGNED_SHORT) {
indices = new Uint16Array(indicesCount);
} else if (indexDatatype === IndexDatatype_default.UNSIGNED_INT) {
indices = new Uint32Array(indicesCount);
}
indicesBuffer.getBufferData(indices);
}
}
let vertices = positionAttribute.typedArray;
let componentDatatype = positionAttribute.componentDatatype;
let attributeType = positionAttribute.type;
const quantization = positionAttribute.quantization;
if (defined_default(quantization)) {
componentDatatype = positionAttribute.quantization.componentDatatype;
attributeType = positionAttribute.quantization.type;
}
const numComponents = AttributeType_default.getNumberOfComponents(attributeType);
const bytes = ComponentDatatype_default.getSizeInBytes(componentDatatype);
const isInterleaved = !defined_default(vertices) && defined_default(byteStride) && byteStride !== numComponents * bytes;
let elementStride = numComponents;
let offset = 0;
if (isInterleaved) {
elementStride = byteStride / bytes;
offset = byteOffset / bytes;
}
const elementCount = vertexCount * elementStride;
if (!defined_default(vertices)) {
const verticesBuffer = positionAttribute.buffer;
if (defined_default(verticesBuffer) && frameState.context.webgl2) {
vertices = ComponentDatatype_default.createTypedArray(
componentDatatype,
elementCount
);
verticesBuffer.getBufferData(
vertices,
isInterleaved ? 0 : byteOffset,
0,
elementCount
);
}
if (quantization && positionAttribute.normalized) {
vertices = AttributeCompression_default.dequantize(
vertices,
componentDatatype,
attributeType,
vertexCount
);
}
}
if (!defined_default(indices) || !defined_default(vertices)) {
return;
}
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
verticalExaggeration = verticalExaggeration ?? 1;
relativeHeight = relativeHeight ?? 0;
const indicesLength = indices.length;
for (let i2 = 0; i2 < indicesLength; i2 += 3) {
const i0 = indices[i2];
const i1 = indices[i2 + 1];
const i22 = indices[i2 + 2];
for (const instanceTransform of transforms) {
const v02 = getVertexPosition(
vertices,
i0,
offset,
elementStride,
quantization,
instanceTransform,
verticalExaggeration,
relativeHeight,
ellipsoid,
scratchV0
);
const v12 = getVertexPosition(
vertices,
i1,
offset,
elementStride,
quantization,
instanceTransform,
verticalExaggeration,
relativeHeight,
ellipsoid,
scratchV1
);
const v22 = getVertexPosition(
vertices,
i22,
offset,
elementStride,
quantization,
instanceTransform,
verticalExaggeration,
relativeHeight,
ellipsoid,
scratchV2
);
const t = IntersectionTests_default.rayTriangleParametric(
ray,
v02,
v12,
v22,
model.backFaceCulling ?? true
);
if (defined_default(t)) {
if (t < minT && t >= 0) {
minT = t;
}
}
}
}
}
}
if (minT === Number.MAX_VALUE) {
return void 0;
}
result = Ray_default.getPoint(ray, minT, result);
if (frameState.mode !== SceneMode_default.SCENE3D) {
Cartesian3_default.fromElements(result.y, result.z, result.x, result);
const projection = frameState.mapProjection;
const ellipsoid2 = projection.ellipsoid;
const cartographic2 = projection.unproject(result, scratchPickCartographic);
ellipsoid2.cartographicToCartesian(cartographic2, result);
}
return result;
}
function getVertexPosition(vertices, index, offset, numElements, quantization, instanceTransform, verticalExaggeration, relativeHeight, ellipsoid, result) {
const i = offset + index * numElements;
result.x = vertices[i];
result.y = vertices[i + 1];
result.z = vertices[i + 2];
if (defined_default(quantization)) {
if (quantization.octEncoded) {
result = AttributeCompression_default.octDecodeInRange(
result,
quantization.normalizationRange,
result
);
if (quantization.octEncodedZXY) {
const x = result.x;
result.x = result.z;
result.z = result.y;
result.y = x;
}
} else {
result = Cartesian3_default.multiplyComponents(
result,
quantization.quantizedVolumeStepSize,
result
);
result = Cartesian3_default.add(
result,
quantization.quantizedVolumeOffset,
result
);
}
}
result = Matrix4_default.multiplyByPoint(instanceTransform, result, result);
if (verticalExaggeration !== 1) {
VerticalExaggeration_default.getPosition(
result,
ellipsoid,
verticalExaggeration,
relativeHeight,
result
);
}
return result;
}
// packages/engine/Source/Scene/Model/ModelImagery.js
var import_InlineWorkers735 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Model/ImageryConfiguration.js
var import_InlineWorkers734 = __toESM(require_InlineWorkers(), 1);
var ImageryConfiguration = class {
constructor(imageryLayer) {
this.show = imageryLayer.show;
this.alpha = imageryLayer.alpha;
this.brightness = imageryLayer.brightness;
this.contrast = imageryLayer.contrast;
this.hue = imageryLayer.hue;
this.saturation = imageryLayer.saturation;
this.gamma = imageryLayer.gamma;
this.colorToAlpha = imageryLayer.colorToAlpha;
}
};
var ImageryConfiguration_default = ImageryConfiguration;
// packages/engine/Source/Scene/Model/ModelImagery.js
var ModelImagery = class {
/**
* Creates a new instance
*
* @param {Model} model The model
* @throws {DeveloperError} If the model is not defined
*/
constructor(model) {
Check_default.defined("model", model);
this._model = model;
this._modelPrimitiveImageries = void 0;
this._imageryConfigurations = [];
}
/**
* The update function that is called from Model.update in
* each frame.
*
* This checks whether the imagery layer objects that are associated
* with the model are all ready. If they are not yet
* ready, then nothing is done.
*
* Otherwise, this just calls the update function of
* the _modelPrimitiveImageries (creating them if they had
* not been created yet).
*
* @param {FrameState} frameState The frame state
*/
update(frameState) {
Check_default.defined("frameState", frameState);
if (!this._hasImagery) {
return;
}
if (!this._allImageryLayersReady) {
return;
}
if (!defined_default(this._modelPrimitiveImageries)) {
this._modelPrimitiveImageries = this._createModelPrimitiveImageries();
}
this._updateModelPrimitiveImageries(frameState);
this._checkForModifiedImageryConfigurations();
}
/**
* Creates the ModelPrimitiveImagery array that contains
* one ModelPrimitiveImagery for each primitive that is
* contained in the model.
*
* @returns {ModelPrimitiveImagery[]} The model primitive imageries
* @private
*/
_createModelPrimitiveImageries() {
const model = this._model;
const runtimeNodesAndPrimitives = this._collectRuntimeNodesAndPrimitives();
const modelPrimitiveImageries = [];
const length2 = runtimeNodesAndPrimitives.length;
for (let i = 0; i < length2; i++) {
const runtimeNodeAndPrimitive = runtimeNodesAndPrimitives[i];
const runtimeNode = runtimeNodeAndPrimitive.runtimeNode;
const runtimePrimitive = runtimeNodeAndPrimitive.runtimePrimitive;
const modelPrimitiveImagery = new ModelPrimitiveImagery_default(
model,
runtimeNode,
runtimePrimitive
);
runtimePrimitive.primitive.modelPrimitiveImagery = modelPrimitiveImagery;
modelPrimitiveImageries.push(modelPrimitiveImagery);
}
return modelPrimitiveImageries;
}
/**
* Computes all runtime nodes and primitives of the model.
*
* This is just the array that contains a
* { runtimeNode, runtimePrimitive }
* for each
* model.sceneGraph._runtimeNodes[n]._runtimePrimitives[p].
*
* @returns {object[]} The runtime nodes and primitives
* @private
*/
_collectRuntimeNodesAndPrimitives() {
const model = this._model;
const sceneGraph = model.sceneGraph;
const runtimeNodes = sceneGraph._runtimeNodes;
const runtimeNodesAndPrimitives = [];
for (let i = 0; i < runtimeNodes.length; i++) {
const runtimeNode = runtimeNodes[i];
if (!defined_default(runtimeNode)) {
continue;
}
for (let j = 0; j < runtimeNode.runtimePrimitives.length; j++) {
const runtimePrimitive = runtimeNode.runtimePrimitives[j];
runtimeNodesAndPrimitives.push({
runtimeNode,
runtimePrimitive
});
}
}
return runtimeNodesAndPrimitives;
}
/**
* Just calls update on each ModelPrimitiveImagery
* as part of the update of this class.
*
* @private
*/
_updateModelPrimitiveImageries(frameState) {
Check_default.defined("frameState", frameState);
if (!defined_default(this._modelPrimitiveImageries)) {
throw new DeveloperError_default(
"The modelPrimitiveImageries have not been created"
);
}
const modelPrimitiveImageries = this._modelPrimitiveImageries;
const length2 = modelPrimitiveImageries.length;
for (let i = 0; i < length2; i++) {
const modelPrimitiveImagery = modelPrimitiveImageries[i];
modelPrimitiveImagery.update(frameState);
}
}
/**
* Destroy and delete all ModelPrimitiveImagery instances
* if they already have been created.
*/
_deleteModelPrimitiveImageries() {
const modelPrimitiveImageries = this._modelPrimitiveImageries;
if (!defined_default(modelPrimitiveImageries)) {
return;
}
const length2 = modelPrimitiveImageries.length;
for (let i = 0; i < length2; i++) {
const modelPrimitiveImagery = modelPrimitiveImageries[i];
modelPrimitiveImagery.destroy();
}
delete this._modelPrimitiveImageries;
}
/**
* Returns whether this instance is "ready".
*
* This means that all imagery layers that are associated with the model
* are ready, and all ModelPrimitiveImagery
* instances are ready.
*
* When this is true, then the mapping computations are
* complete and the structures containing the mapping information have
* been initialized. Otherwise, subsequent calls to update
* will perform the necessary computation until this getter eventually
* returns true.
*
* @returns {boolean} Whether this instance is "ready"
*/
get ready() {
if (!this._hasImagery) {
return true;
}
if (!this._allImageryLayersReady) {
return false;
}
if (!this._allModelPrimitiveImageriesReady) {
return false;
}
return true;
}
/**
* Returns whether the model has imagery layers associated with it.
*
* @private
*/
get _hasImagery() {
const model = this._model;
const imageryLayers = model.imageryLayers;
return defined_default(imageryLayers) && imageryLayers.length > 0;
}
/**
* Returns whether all imagery layers that are associated with the
* model are ready.
*
* If the model does not have imagery, then this always returns
* true. Otherwise, it returns whether each imagery
* layer is ready.
*
* @private
*/
get _allImageryLayersReady() {
if (!this._hasImagery) {
return true;
}
const imageryLayers = this._model.imageryLayers;
const length2 = imageryLayers.length;
for (let i = 0; i < length2; i++) {
const imageryLayer = imageryLayers.get(i);
if (!imageryLayer.ready) {
return false;
}
}
return true;
}
/**
* Returns whether all ModelPrimitiveImagery instances
* are are ready.
*
* @private
*/
get _allModelPrimitiveImageriesReady() {
const modelPrimitiveImageries = this._modelPrimitiveImageries;
if (!defined_default(modelPrimitiveImageries)) {
return false;
}
const length2 = modelPrimitiveImageries.length;
for (let i = 0; i < length2; i++) {
const modelPrimitiveImagery = modelPrimitiveImageries[i];
if (!modelPrimitiveImagery.ready) {
return false;
}
}
return true;
}
/**
* Check whether any of the settings of any imagery layer (like alpha
* or hue) has been changed since the last call to the update
* function.
*
* If this is the case, the draw commands of the model will be reset.
*/
_checkForModifiedImageryConfigurations() {
if (this._imageryConfigurationsModified()) {
this._updateImageryConfigurations();
const model = this._model;
model.resetDrawCommands();
}
}
/**
* Returns whether any setting of an imagery layer (like alpha or hue) has
* been changed since the last time the ImageryConfiguration
* objects have been updated.
*
* @returns {boolean} Whether there was a modification
*/
_imageryConfigurationsModified() {
const model = this._model;
const imageryLayers = model.imageryLayers;
const imageryConfigurations = this._imageryConfigurations;
if (imageryLayers.length !== imageryConfigurations.length) {
return true;
}
for (let i = 0; i < imageryLayers.length; i++) {
const imageryLayer = imageryLayers.get(i);
const imageryConfiguration = imageryConfigurations[i];
if (imageryLayer.show !== imageryConfiguration.show) {
return true;
}
if (imageryLayer.alpha !== imageryConfiguration.alpha) {
return true;
}
if (imageryLayer.brightness !== imageryConfiguration.brightness) {
return true;
}
if (imageryLayer.contrast !== imageryConfiguration.contrast) {
return true;
}
if (imageryLayer.hue !== imageryConfiguration.hue) {
return true;
}
if (imageryLayer.saturation !== imageryConfiguration.saturation) {
return true;
}
if (imageryLayer.gamma !== imageryConfiguration.gamma) {
return true;
}
if (imageryLayer.colorToAlpha !== imageryConfiguration.colorToAlpha) {
return true;
}
}
return false;
}
/**
* Create one ImageryConfiguration object for each imagery
* layer that appears in the model, and store them as the
* _imageryConfigurations.
*/
_updateImageryConfigurations() {
const model = this._model;
const imageryLayers = model.imageryLayers;
const imageryConfigurations = this._imageryConfigurations;
imageryConfigurations.length = imageryLayers.length;
for (let i = 0; i < imageryLayers.length; i++) {
const imageryLayer = imageryLayers.get(i);
imageryConfigurations[i] = new ImageryConfiguration_default(imageryLayer);
}
}
/**
* Returns whether this object was destroyed.
*
* If this object was destroyed, calling any function other than
* isDestroyed will result in a {@link DeveloperError}.
*
* @returns {boolean} Whether this object was destroyed
*/
isDestroyed() {
return false;
}
/**
* Destroys this object and all its resources.
*/
destroy() {
if (this.isDestroyed()) {
return;
}
this._deleteModelPrimitiveImageries();
return destroyObject_default(this);
}
};
var ModelImagery_default = ModelImagery;
// packages/engine/Source/Scene/Model/Model.js
function Model(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("options.loader", options.loader);
Check_default.typeOf.object("options.resource", options.resource);
this._loader = options.loader;
this._resource = options.resource;
this.type = options.type ?? ModelType_default.GLTF;
this.modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this._modelMatrix = Matrix4_default.clone(this.modelMatrix);
this._scale = options.scale ?? 1;
this._minimumPixelSize = options.minimumPixelSize ?? 0;
this._maximumScale = options.maximumScale;
this._clampedScale = defined_default(this._maximumScale) ? Math.min(this._scale, this._maximumScale) : this._scale;
this._computedScale = this._clampedScale;
this._updateModelMatrix = false;
this.referenceMatrix = void 0;
this._iblReferenceFrameMatrix = Matrix3_default.clone(Matrix3_default.IDENTITY);
this._resourcesLoaded = false;
this._drawCommandsBuilt = false;
this._ready = false;
this._customShader = options.customShader;
this._content = options.content;
this._texturesLoaded = false;
this._defaultTexture = void 0;
this._activeAnimations = new ModelAnimationCollection_default(this);
this._clampAnimations = options.clampAnimations ?? true;
this._userAnimationDirty = false;
this._id = options.id;
this._idDirty = false;
this._color = Color_default.clone(options.color);
this._colorBlendMode = options.colorBlendMode ?? ColorBlendMode_default.HIGHLIGHT;
this._colorBlendAmount = options.colorBlendAmount ?? 0.5;
const silhouetteColor = options.silhouetteColor ?? Color_default.RED;
this._silhouetteColor = Color_default.clone(silhouetteColor);
this._silhouetteSize = options.silhouetteSize ?? 0;
this._silhouetteDirty = false;
this._silhouetteId = void 0;
this._cull = options.cull ?? true;
this._opaquePass = options.opaquePass ?? Pass_default.OPAQUE;
this._allowPicking = options.allowPicking ?? true;
this._show = options.show ?? true;
this._style = void 0;
this._styleDirty = false;
this._styleCommandsNeeded = void 0;
let featureIdLabel = options.featureIdLabel ?? "featureId_0";
if (typeof featureIdLabel === "number") {
featureIdLabel = `featureId_${featureIdLabel}`;
}
this._featureIdLabel = featureIdLabel;
let instanceFeatureIdLabel = options.instanceFeatureIdLabel ?? "instanceFeatureId_0";
if (typeof instanceFeatureIdLabel === "number") {
instanceFeatureIdLabel = `instanceFeatureId_${instanceFeatureIdLabel}`;
}
this._instanceFeatureIdLabel = instanceFeatureIdLabel;
this._featureTables = [];
this._featureTableId = void 0;
this._featureTableIdDirty = true;
this._pipelineResources = [];
this._modelResources = [];
this._pickIds = [];
this._boundingSphere = new BoundingSphere_default();
this._initialRadius = void 0;
this._heightReference = options.heightReference ?? HeightReference_default.NONE;
this._heightDirty = this._heightReference !== HeightReference_default.NONE;
this._removeUpdateHeightCallback = void 0;
this._enableVerticalExaggeration = options.enableVerticalExaggeration ?? true;
this._hasVerticalExaggeration = false;
this._clampedModelMatrix = void 0;
const scene = options.scene;
if (defined_default(scene) && defined_default(scene.terrainProviderChanged)) {
this._terrainProviderChangedCallback = scene.terrainProviderChanged.addEventListener(() => {
this._heightDirty = true;
});
}
this._scene = scene;
this._distanceDisplayCondition = options.distanceDisplayCondition;
const pointCloudShading = new PointCloudShading_default(options.pointCloudShading);
this._pointCloudShading = pointCloudShading;
this._attenuation = pointCloudShading.attenuation;
this._pointCloudBackFaceCulling = pointCloudShading.backFaceCulling;
const clippingPlanes = options.clippingPlanes;
if (defined_default(clippingPlanes) && clippingPlanes.owner === void 0) {
ClippingPlaneCollection_default.setOwner(clippingPlanes, this, "_clippingPlanes");
} else {
this._clippingPlanes = clippingPlanes;
}
this._clippingPlanesState = 0;
this._clippingPlanesMatrix = Matrix4_default.clone(Matrix4_default.IDENTITY);
const clippingPolygons = options.clippingPolygons;
if (defined_default(clippingPolygons) && clippingPolygons.owner === void 0) {
ClippingPolygonCollection_default.setOwner(
clippingPolygons,
this,
"_clippingPolygons"
);
} else {
this._clippingPolygons = clippingPolygons;
}
this._clippingPolygonsState = 0;
this._modelImagery = new ModelImagery_default(this);
this._lightColor = Cartesian3_default.clone(options.lightColor);
this._imageBasedLighting = defined_default(options.imageBasedLighting) ? options.imageBasedLighting : new ImageBasedLighting_default();
this._shouldDestroyImageBasedLighting = !defined_default(options.imageBasedLighting);
this._environmentMapManager = void 0;
const environmentMapManager = new DynamicEnvironmentMapManager_default(
options.environmentMapOptions
);
DynamicEnvironmentMapManager_default.setOwner(
environmentMapManager,
this,
"_environmentMapManager"
);
this._backFaceCulling = options.backFaceCulling ?? true;
this._backFaceCullingDirty = false;
this._shadows = options.shadows ?? ShadowMode_default.ENABLED;
this._shadowsDirty = false;
this._debugShowBoundingVolumeDirty = false;
this._debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this._enableDebugWireframe = options.enableDebugWireframe ?? false;
this._enableShowOutline = options.enableShowOutline ?? true;
this._debugWireframe = options.debugWireframe ?? false;
if (this._debugWireframe === true && this._enableDebugWireframe === false && this.type === ModelType_default.GLTF) {
oneTimeWarning_default(
"model-debug-wireframe-ignored",
"enableDebugWireframe must be set to true in Model.fromGltf, otherwise debugWireframe will be ignored."
);
}
let credit = options.credit;
if (typeof credit === "string") {
credit = new Credit_default(credit);
}
this._credits = [];
this._credit = credit;
this._resourceCredits = [];
this._gltfCredits = [];
this._showCreditsOnScreen = options.showCreditsOnScreen ?? false;
this._showCreditsOnScreenDirty = true;
this._splitDirection = options.splitDirection ?? SplitDirection_default.NONE;
this._enableShowOutline = options.enableShowOutline ?? true;
this.showOutline = options.showOutline ?? true;
this.outlineColor = options.outlineColor ?? Color_default.BLACK;
this._classificationType = options.classificationType;
this._statistics = new ModelStatistics_default();
this._sceneMode = void 0;
this._projectTo2D = options.projectTo2D ?? false;
this._enablePick = options.enablePick ?? false;
this._fogRenderable = void 0;
this._skipLevelOfDetail = false;
this._ignoreCommands = options.ignoreCommands ?? false;
this._errorEvent = new Event_default();
this._readyEvent = new Event_default();
this._texturesReadyEvent = new Event_default();
this._sceneGraph = void 0;
this._nodesByName = {};
this.pickObject = options.pickObject;
}
function handleError11(model, error) {
if (model._errorEvent.numberOfListeners > 0) {
model._errorEvent.raiseEvent(error);
return;
}
console.log(error);
}
function createModelFeatureTables(model, structuralMetadata) {
const featureTables = model._featureTables;
const propertyTables = structuralMetadata.propertyTables;
const length2 = propertyTables.length;
for (let i = 0; i < length2; i++) {
const propertyTable = propertyTables[i];
const modelFeatureTable = new ModelFeatureTable_default({
model,
propertyTable
});
featureTables.push(modelFeatureTable);
}
return featureTables;
}
function selectFeatureTableId(components, model) {
const featureIdLabel = model._featureIdLabel;
const instanceFeatureIdLabel = model._instanceFeatureIdLabel;
let i, j;
let featureIdAttribute;
let node;
for (i = 0; i < components.nodes.length; i++) {
node = components.nodes[i];
if (defined_default(node.instances)) {
featureIdAttribute = ModelUtility_default.getFeatureIdsByLabel(
node.instances.featureIds,
instanceFeatureIdLabel
);
if (defined_default(featureIdAttribute) && defined_default(featureIdAttribute.propertyTableId)) {
return featureIdAttribute.propertyTableId;
}
}
}
for (i = 0; i < components.nodes.length; i++) {
node = components.nodes[i];
for (j = 0; j < node.primitives.length; j++) {
const primitive = node.primitives[j];
const featureIds = ModelUtility_default.getFeatureIdsByLabel(
primitive.featureIds,
featureIdLabel
);
if (defined_default(featureIds)) {
return featureIds.propertyTableId;
}
}
}
if (model._featureTables.length === 1) {
return 0;
}
}
function isColorAlphaDirty(currentColor, previousColor) {
if (!defined_default(currentColor) && !defined_default(previousColor)) {
return false;
}
if (defined_default(currentColor) !== defined_default(previousColor)) {
return true;
}
const currentAlpha = currentColor.alpha;
const previousAlpha = previousColor.alpha;
return Math.floor(currentAlpha) !== Math.floor(previousAlpha) || Math.ceil(currentAlpha) !== Math.ceil(previousAlpha);
}
Object.defineProperties(Model.prototype, {
/**
* When true, this model is ready to render, i.e., the external binary, image,
* and shader files were downloaded and the WebGL resources were created.
*
* @memberof Model.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
ready: {
get: function() {
return this._ready;
}
},
/**
* Gets an event that is raised when the model encounters an asynchronous rendering error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link ModelError}.
* @memberof Model.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets an event that is raised when the model is loaded and ready for rendering, i.e. when the external resources
* have been downloaded and the WebGL resources are created. Event listeners
* are passed an instance of the {@link Model}.
*
*
* If {@link Model.incrementallyLoadTextures} is true, this event will be raised before all textures are loaded and ready for rendering. Subscribe to {@link Model.texturesReadyEvent} to be notified when the textures are ready.
*
*
* @memberof Model.prototype
* @type {Event}
* @readonly
*/
readyEvent: {
get: function() {
return this._readyEvent;
}
},
/**
* Returns true if textures are loaded separately from the other glTF resources.
*
* @memberof Model.prototype
*
* @type {boolean}
* @readonly
* @private
*/
incrementallyLoadTextures: {
get: function() {
return this._loader.incrementallyLoadTextures ?? false;
}
},
/**
* Gets an event that, if {@link Model.incrementallyLoadTextures} is true, is raised when the model textures are loaded and ready for rendering, i.e. when the external resources
* have been downloaded and the WebGL resources are created. Event listeners
* are passed an instance of the {@link Model}.
*
* @memberof Model.prototype
* @type {Event}
* @readonly
*/
texturesReadyEvent: {
get: function() {
return this._texturesReadyEvent;
}
},
/**
* @private
*/
loader: {
get: function() {
return this._loader;
}
},
/**
* Get the estimated memory usage statistics for this model.
*
* @memberof Model.prototype
*
* @type {ModelStatistics}
* @readonly
*
* @private
*/
statistics: {
get: function() {
return this._statistics;
}
},
/**
* The currently playing glTF animations.
*
* @memberof Model.prototype
*
* @type {ModelAnimationCollection}
* @readonly
*/
activeAnimations: {
get: function() {
return this._activeAnimations;
}
},
/**
* Determines if the model's animations should hold a pose over frames where no keyframes are specified.
*
* @memberof Model.prototype
* @type {boolean}
*
* @default true
*/
clampAnimations: {
get: function() {
return this._clampAnimations;
},
set: function(value) {
this._clampAnimations = value;
}
},
/**
* Whether or not to cull the model using frustum/horizon culling. If the model is part of a 3D Tiles tileset, this property
* will always be false, since the 3D Tiles culling system is used.
*
* @memberof Model.prototype
*
* @type {boolean}
* @readonly
*
* @private
*/
cull: {
get: function() {
return this._cull;
}
},
/**
* The pass to use in the {@link DrawCommand} for the opaque portions of the model.
*
* @memberof Model.prototype
*
* @type {Pass}
* @readonly
*
* @private
*/
opaquePass: {
get: function() {
return this._opaquePass;
}
},
/**
* Point cloud shading settings for controlling point cloud attenuation
* and lighting. For 3D Tiles, this is inherited from the
* {@link Cesium3DTileset}.
*
* @memberof Model.prototype
*
* @type {PointCloudShading}
*/
pointCloudShading: {
get: function() {
return this._pointCloudShading;
},
set: function(value) {
Check_default.defined("pointCloudShading", value);
if (value !== this._pointCloudShading) {
this.resetDrawCommands();
}
this._pointCloudShading = value;
}
},
/**
* The model's custom shader, if it exists. Using custom shaders with a {@link Cesium3DTileStyle}
* may lead to undefined behavior.
*
* @memberof Model.prototype
*
* @type {CustomShader}
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
customShader: {
get: function() {
return this._customShader;
},
set: function(value) {
if (value !== this._customShader) {
this.resetDrawCommands();
}
this._customShader = value;
}
},
/**
* The scene graph of this model.
*
* @memberof Model.prototype
*
* @type {ModelSceneGraph}
* @private
*/
sceneGraph: {
get: function() {
return this._sceneGraph;
}
},
/**
* The tile content this model belongs to, if it is loaded as part of a {@link Cesium3DTileset}.
*
* @memberof Model.prototype
*
* @type {Cesium3DTileContent}
* @readonly
*
* @private
*/
content: {
get: function() {
return this._content;
}
},
/**
* The height reference of the model, which determines how the model is drawn
* relative to terrain.
*
* @memberof Model.prototype
*
* @type {HeightReference}
* @default {HeightReference.NONE}
*
*/
heightReference: {
get: function() {
return this._heightReference;
},
set: function(value) {
if (value !== this._heightReference) {
this._heightDirty = true;
}
this._heightReference = value;
}
},
/**
* Gets or sets the distance display condition, which specifies at what distance
* from the camera this model will be displayed.
*
* @memberof Model.prototype
*
* @type {DistanceDisplayCondition}
*
* @default undefined
*
*/
distanceDisplayCondition: {
get: function() {
return this._distanceDisplayCondition;
},
set: function(value) {
if (defined_default(value) && value.far <= value.near) {
throw new DeveloperError_default("far must be greater than near");
}
this._distanceDisplayCondition = DistanceDisplayCondition_default.clone(
value,
this._distanceDisplayCondition
);
}
},
/**
* The structural metadata from the EXT_structural_metadata extension
*
* @memberof Model.prototype
*
* @type {StructuralMetadata}
* @readonly
*
* @private
*/
structuralMetadata: {
get: function() {
return this._sceneGraph.components.structuralMetadata;
}
},
/**
* The ID for the feature table to use for picking and styling in this model.
*
* @memberof Model.prototype
*
* @type {number}
*
* @private
*/
featureTableId: {
get: function() {
return this._featureTableId;
},
set: function(value) {
this._featureTableId = value;
}
},
/**
* The feature tables for this model.
*
* @memberof Model.prototype
*
* @type {Array}
* @readonly
*
* @private
*/
featureTables: {
get: function() {
return this._featureTables;
},
set: function(value) {
this._featureTables = value;
}
},
/**
* A user-defined object that is returned when the model is picked.
*
* @memberof Model.prototype
*
* @type {object}
*
* @default undefined
*
* @see Scene#pick
*/
id: {
get: function() {
return this._id;
},
set: function(value) {
if (value !== this._id) {
this._idDirty = true;
}
this._id = value;
}
},
/**
* When true, each primitive is pickable with {@link Scene#pick}. When false, GPU memory is saved.
*
* @memberof Model.prototype
*
* @type {boolean}
* @readonly
*
* @private
*/
allowPicking: {
get: function() {
return this._allowPicking;
}
},
/**
* The style to apply to the features in the model. Cannot be applied if a {@link CustomShader} is also applied.
*
* @memberof Model.prototype
*
* @type {Cesium3DTileStyle}
*/
style: {
get: function() {
return this._style;
},
set: function(value) {
this._style = value;
this._styleDirty = true;
}
},
/**
* The color to blend with the model's rendered color.
*
* @memberof Model.prototype
*
* @type {Color}
*
* @default undefined
*/
color: {
get: function() {
return this._color;
},
set: function(value) {
if (isColorAlphaDirty(value, this._color)) {
this.resetDrawCommands();
}
this._color = Color_default.clone(value, this._color);
}
},
/**
* Defines how the color blends with the model.
*
* @memberof Model.prototype
*
* @type {Cesium3DTileColorBlendMode|ColorBlendMode}
*
* @default ColorBlendMode.HIGHLIGHT
*/
colorBlendMode: {
get: function() {
return this._colorBlendMode;
},
set: function(value) {
this._colorBlendMode = value;
}
},
/**
* Value used to determine the color strength when the colorBlendMode is MIX. A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with any value in-between resulting in a mix of the two.
*
* @memberof Model.prototype
*
* @type {number}
*
* @default 0.5
*/
colorBlendAmount: {
get: function() {
return this._colorBlendAmount;
},
set: function(value) {
this._colorBlendAmount = value;
}
},
/**
* The silhouette color.
*
* @memberof Model.prototype
*
* @type {Color}
*
* @default Color.RED
*/
silhouetteColor: {
get: function() {
return this._silhouetteColor;
},
set: function(value) {
if (!Color_default.equals(value, this._silhouetteColor)) {
const alphaDirty = isColorAlphaDirty(value, this._silhouetteColor);
this._silhouetteDirty = this._silhouetteDirty || alphaDirty;
}
this._silhouetteColor = Color_default.clone(value, this._silhouetteColor);
}
},
/**
* The size of the silhouette in pixels.
*
* @memberof Model.prototype
*
* @type {number}
*
* @default 0.0
*/
silhouetteSize: {
get: function() {
return this._silhouetteSize;
},
set: function(value) {
if (value !== this._silhouetteSize) {
const currentSize = this._silhouetteSize;
const sizeDirty = value > 0 && currentSize === 0 || value === 0 && currentSize > 0;
this._silhouetteDirty = this._silhouetteDirty || sizeDirty;
this._backFaceCullingDirty = this._backFaceCullingDirty || sizeDirty;
}
this._silhouetteSize = value;
}
},
/**
* Gets the model's bounding sphere in world space. This does not take into account
* glTF animations, skins, or morph targets. It also does not account for
* {@link Model#minimumPixelSize}.
*
* @memberof Model.prototype
*
* @type {BoundingSphere}
* @readonly
*/
boundingSphere: {
get: function() {
if (!this._ready) {
throw new DeveloperError_default(
"The model is not loaded. Use Model.readyEvent or wait for Model.ready to be true."
);
}
const modelMatrix = defined_default(this._clampedModelMatrix) ? this._clampedModelMatrix : this.modelMatrix;
updateBoundingSphere(this, modelMatrix);
return this._boundingSphere;
}
},
/**
* This property is for debugging only; it is not for production use nor is it optimized.
*
* Draws the bounding sphere for each draw command in the model.
*
*
* @memberof Model.prototype
*
* @type {boolean}
*
* @default false
*/
debugShowBoundingVolume: {
get: function() {
return this._debugShowBoundingVolume;
},
set: function(value) {
if (this._debugShowBoundingVolume !== value) {
this._debugShowBoundingVolumeDirty = true;
}
this._debugShowBoundingVolume = value;
}
},
/**
* This property is for debugging only; it is not for production use nor is it optimized.
*
* Draws the model in wireframe.
*
*
* @memberof Model.prototype
*
* @type {boolean}
*
* @default false
*/
debugWireframe: {
get: function() {
return this._debugWireframe;
},
set: function(value) {
if (this._debugWireframe !== value) {
this.resetDrawCommands();
}
this._debugWireframe = value;
if (this._debugWireframe === true && this._enableDebugWireframe === false && this.type === ModelType_default.GLTF) {
oneTimeWarning_default(
"model-debug-wireframe-ignored",
"enableDebugWireframe must be set to true in Model.fromGltfAsync, otherwise debugWireframe will be ignored."
);
}
}
},
/**
* Whether or not to render the model.
*
* @memberof Model.prototype
*
* @type {boolean}
*
* @default true
*/
show: {
get: function() {
return this._show;
},
set: function(value) {
this._show = value;
}
},
/**
* Label of the feature ID set to use for picking and styling.
*
* For EXT_mesh_features, this is the feature ID's label property, or
* "featureId_N" (where N is the index in the featureIds array) when not
* specified. EXT_feature_metadata did not have a label field, so such
* feature ID sets are always labeled "featureId_N" where N is the index in
* the list of all feature Ids, where feature ID attributes are listed before
* feature ID textures.
*
*
* If featureIdLabel is set to an integer N, it is converted to
* the string "featureId_N" automatically. If both per-primitive and
* per-instance feature IDs are present, the instance feature IDs take
* priority.
*
*
* @memberof Model.prototype
*
* @type {string}
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
featureIdLabel: {
get: function() {
return this._featureIdLabel;
},
set: function(value) {
if (typeof value === "number") {
value = `featureId_${value}`;
}
Check_default.typeOf.string("value", value);
if (value !== this._featureIdLabel) {
this._featureTableIdDirty = true;
}
this._featureIdLabel = value;
}
},
/**
* Label of the instance feature ID set used for picking and styling.
*
* If instanceFeatureIdLabel is set to an integer N, it is converted to
* the string "instanceFeatureId_N" automatically.
* If both per-primitive and per-instance feature IDs are present, the
* instance feature IDs take priority.
*
*
* @memberof Model.prototype
*
* @type {string}
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
instanceFeatureIdLabel: {
get: function() {
return this._instanceFeatureIdLabel;
},
set: function(value) {
if (typeof value === "number") {
value = `instanceFeatureId_${value}`;
}
Check_default.typeOf.string("value", value);
if (value !== this._instanceFeatureIdLabel) {
this._featureTableIdDirty = true;
}
this._instanceFeatureIdLabel = value;
}
},
/**
* The {@link ClippingPlaneCollection} used to selectively disable rendering the model.
*
* @memberof Model.prototype
*
* @type {ClippingPlaneCollection}
*/
clippingPlanes: {
get: function() {
return this._clippingPlanes;
},
set: function(value) {
if (value !== this._clippingPlanes) {
ClippingPlaneCollection_default.setOwner(value, this, "_clippingPlanes");
this.resetDrawCommands();
}
}
},
/**
* The {@link ClippingPolygonCollection} used to selectively disable rendering the model.
*
* @memberof Model.prototype
*
* @type {ClippingPolygonCollection}
*/
clippingPolygons: {
get: function() {
return this._clippingPolygons;
},
set: function(value) {
if (value !== this._clippingPolygons) {
ClippingPolygonCollection_default.setOwner(value, this, "_clippingPolygons");
this.resetDrawCommands();
}
}
},
/**
* If true, the model is exaggerated along the ellipsoid normal when {@link Scene.verticalExaggeration} is set to a value other than 1.0.
*
* @memberof Model.prototype
* @type {boolean}
* @default true
*
* @example
* // Exaggerate terrain by a factor of 2, but prevent model exaggeration
* scene.verticalExaggeration = 2.0;
* model.enableVerticalExaggeration = false;
*/
enableVerticalExaggeration: {
get: function() {
return this._enableVerticalExaggeration;
},
set: function(value) {
if (value !== this._enableVerticalExaggeration) {
this.resetDrawCommands();
}
this._enableVerticalExaggeration = value;
}
},
/**
* If true, the model is vertically exaggerated along the ellipsoid normal.
*
* @memberof Model.prototype
* @type {boolean}
* @default true
* @readonly
* @private
*/
hasVerticalExaggeration: {
get: function() {
return this._hasVerticalExaggeration;
}
},
/**
* If this model is part of a Model3DTileContent of a tileset,
* then this will return the ImageryLayerCollection
* of that tileset. Otherwise, undefined is returned.
*
* @memberof Model.prototype
* @type {ImageryLayerCollection|undefined}
* @readonly
* @private
*/
imageryLayers: {
get: function() {
if (defined_default(this._content)) {
const tileset = this._content.tileset;
if (defined_default(tileset)) {
return tileset.imageryLayers;
}
}
return void 0;
}
},
/**
* The directional light color when shading the model. When undefined the scene's light color is used instead.
*
* Disabling additional light sources by setting
* model.imageBasedLighting.imageBasedLightingFactor = new Cartesian2(0.0, 0.0)
* will make the model much darker. Here, increasing the intensity of the light source will make the model brighter.
*
* @memberof Model.prototype
*
* @type {Cartesian3}
*
* @default undefined
*/
lightColor: {
get: function() {
return this._lightColor;
},
set: function(value) {
if (defined_default(value) !== defined_default(this._lightColor)) {
this.resetDrawCommands();
}
this._lightColor = Cartesian3_default.clone(value, this._lightColor);
}
},
/**
* The properties for managing image-based lighting on this model.
*
* @memberof Model.prototype
*
* @type {ImageBasedLighting}
*/
imageBasedLighting: {
get: function() {
return this._imageBasedLighting;
},
set: function(value) {
Check_default.typeOf.object("imageBasedLighting", value);
if (value !== this._imageBasedLighting) {
if (this._shouldDestroyImageBasedLighting && !this._imageBasedLighting.isDestroyed()) {
this._imageBasedLighting.destroy();
}
this._imageBasedLighting = value;
this._shouldDestroyImageBasedLighting = false;
this.resetDrawCommands();
}
}
},
/**
* The properties for managing dynamic environment maps on this model. Affects lighting.
* @memberof Model.prototype
* @readonly
*
* @example
* // Change the ground color used for a model's environment map to a forest green
* const environmentMapManager = model.environmentMapManager;
* environmentMapManager.groundColor = Cesium.Color.fromCssColorString("#203b34");
*
* @type {DynamicEnvironmentMapManager}
*/
environmentMapManager: {
get: function() {
return this._environmentMapManager;
},
set: function(value) {
Check_default.typeOf.object("environmentMapManager", value);
if (value !== this.environmentMapManager) {
DynamicEnvironmentMapManager_default.setOwner(
value,
this,
"_environmentMapManager"
);
this.resetDrawCommands();
}
}
},
/**
* Whether to cull back-facing geometry. When true, back face culling is
* determined by the material's doubleSided property; when false, back face
* culling is disabled. Back faces are not culled if {@link Model#color}
* is translucent or {@link Model#silhouetteSize} is greater than 0.0.
*
* @memberof Model.prototype
*
* @type {boolean}
*
* @default true
*/
backFaceCulling: {
get: function() {
return this._backFaceCulling;
},
set: function(value) {
if (value !== this._backFaceCulling) {
this._backFaceCullingDirty = true;
}
this._backFaceCulling = value;
}
},
/**
* A uniform scale applied to this model before the {@link Model#modelMatrix}.
* Values greater than 1.0 increase the size of the model; values
* less than 1.0 decrease.
*
* @memberof Model.prototype
*
* @type {number}
*
* @default 1.0
*/
scale: {
get: function() {
return this._scale;
},
set: function(value) {
if (value !== this._scale) {
this._updateModelMatrix = true;
}
this._scale = value;
}
},
/**
* The true scale of the model after being affected by the model's scale,
* minimum pixel size, and maximum scale parameters.
*
* @memberof Model.prototype
*
* @type {number}
* @readonly
*
* @private
*/
computedScale: {
get: function() {
return this._computedScale;
}
},
/**
* The approximate minimum pixel size of the model regardless of zoom.
* This can be used to ensure that a model is visible even when the viewer
* zooms out. When 0.0, no minimum size is enforced.
*
* @memberof Model.prototype
*
* @type {number}
*
* @default 0.0
*/
minimumPixelSize: {
get: function() {
return this._minimumPixelSize;
},
set: function(value) {
if (value !== this._minimumPixelSize) {
this._updateModelMatrix = true;
}
this._minimumPixelSize = value;
}
},
/**
* The maximum scale size for a model. This can be used to give
* an upper limit to the {@link Model#minimumPixelSize}, ensuring that the model
* is never an unreasonable scale.
*
* @memberof Model.prototype
*
* @type {number}
*/
maximumScale: {
get: function() {
return this._maximumScale;
},
set: function(value) {
if (value !== this._maximumScale) {
this._updateModelMatrix = true;
}
this._maximumScale = value;
}
},
/**
* Determines whether the model casts or receives shadows from light sources.
* @memberof Model.prototype
*
* @type {ShadowMode}
*
* @default ShadowMode.ENABLED
*/
shadows: {
get: function() {
return this._shadows;
},
set: function(value) {
if (value !== this._shadows) {
this._shadowsDirty = true;
}
this._shadows = value;
}
},
/**
* Gets the credit that will be displayed for the model.
*
* @memberof Model.prototype
*
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return this._credit;
}
},
/**
* Gets or sets whether the credits of the model will be displayed
* on the screen.
*
* @memberof Model.prototype
*
* @type {boolean}
*
* @default false
*/
showCreditsOnScreen: {
get: function() {
return this._showCreditsOnScreen;
},
set: function(value) {
if (this._showCreditsOnScreen !== value) {
this._showCreditsOnScreenDirty = true;
}
this._showCreditsOnScreen = value;
}
},
/**
* The {@link SplitDirection} to apply to this model.
*
* @memberof Model.prototype
*
* @type {SplitDirection}
*
* @default {@link SplitDirection.NONE}
*/
splitDirection: {
get: function() {
return this._splitDirection;
},
set: function(value) {
if (this._splitDirection !== value) {
this.resetDrawCommands();
}
this._splitDirection = value;
}
},
/**
* Gets the model's classification type. This determines whether terrain,
* 3D Tiles, or both will be classified by this model.
*
* Additionally, there are a few requirements/limitations:
*
* - The glTF cannot contain morph targets, skins, or animations.
* - The glTF cannot contain the
EXT_mesh_gpu_instancing extension.
* - Only meshes with TRIANGLES can be used to classify other assets.
* - The meshes must be watertight.
* - The POSITION attribute is required.
* - If feature IDs and an index buffer are both present, all indices with the same feature id must occupy contiguous sections of the index buffer.
* - If feature IDs are present without an index buffer, all positions with the same feature id must occupy contiguous sections of the position buffer.
*
*
*
* The 3D Tiles or terrain receiving the classification must be opaque.
*
*
* @memberof Model.prototype
*
* @type {ClassificationType}
* @default undefined
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
* @readonly
*/
classificationType: {
get: function() {
return this._classificationType;
}
},
/**
* Reference to the pick IDs. This is only used internally, e.g. for
* per-feature post-processing in {@link PostProcessStage}.
*
* @memberof Model.prototype
*
* @type {PickId[]}
* @readonly
*
* @private
*/
pickIds: {
get: function() {
return this._pickIds;
}
},
/**
* The {@link StyleCommandsNeeded} for the style currently applied to
* the features in the model. This is used internally by the {@link ModelDrawCommand}
* when determining which commands to submit in an update.
*
* @memberof Model.prototype
*
* @type {StyleCommandsNeeded}
* @readonly
*
* @private
*/
styleCommandsNeeded: {
get: function() {
return this._styleCommandsNeeded;
}
}
});
Model.prototype.getNode = function(name) {
if (!this._ready) {
throw new DeveloperError_default(
"The model is not loaded. Use Model.readyEvent or wait for Model.ready to be true."
);
}
Check_default.typeOf.string("name", name);
return this._nodesByName[name];
};
Model.prototype.setArticulationStage = function(articulationStageKey, value) {
Check_default.typeOf.number("value", value);
if (!this._ready) {
throw new DeveloperError_default(
"The model is not loaded. Use Model.readyEvent or wait for Model.ready to be true."
);
}
this._sceneGraph.setArticulationStage(articulationStageKey, value);
};
Model.prototype.applyArticulations = function() {
if (!this._ready) {
throw new DeveloperError_default(
"The model is not loaded. Use Model.readyEvent or wait for Model.ready to be true."
);
}
this._sceneGraph.applyArticulations();
};
Model.prototype.getExtension = function(extensionName) {
Check_default.typeOf.string("extensionName", extensionName);
if (!this._ready) {
throw new DeveloperError_default(
"The model is not loaded. Use Model.readyEvent or wait for Model.ready to be true."
);
}
const components = this._loader.components;
return components.extensions[extensionName];
};
Model.prototype.makeStyleDirty = function() {
this._styleDirty = true;
};
Model.prototype.resetDrawCommands = function() {
this._drawCommandsBuilt = false;
};
var scratchIBLReferenceFrameMatrix4 = new Matrix4_default();
var scratchIBLReferenceFrameMatrix3 = new Matrix3_default();
var scratchClippingPlanesMatrix = new Matrix4_default();
Model.prototype.update = function(frameState) {
let finishedProcessing = false;
try {
finishedProcessing = processLoader(this, frameState);
} catch (error) {
if (!this._loader.incrementallyLoadTextures && error.name === "TextureError") {
handleError11(this, error);
} else {
const runtimeError = ModelUtility_default.getError(
"model",
this._resource,
error
);
handleError11(this, runtimeError);
}
}
updateCustomShader(this, frameState);
updateEnvironmentMap(this, frameState);
updateImageBasedLighting(this, frameState);
if (!this._resourcesLoaded && finishedProcessing) {
this._resourcesLoaded = true;
const components = this._loader.components;
if (!defined_default(components)) {
if (this._loader.isUnloaded()) {
return;
}
const error = ModelUtility_default.getError(
"model",
this._resource,
new RuntimeError_default("Failed to load model.")
);
handleError11(error);
this._rejectLoad = this._rejectLoad && this._rejectLoad(error);
}
const structuralMetadata = components.structuralMetadata;
if (defined_default(structuralMetadata) && structuralMetadata.propertyTableCount > 0) {
createModelFeatureTables(this, structuralMetadata);
}
const sceneGraph = new ModelSceneGraph_default({
model: this,
modelComponents: components
});
this._sceneGraph = sceneGraph;
this._gltfCredits = sceneGraph.components.asset.credits;
}
if (!this._resourcesLoaded || frameState.mode === SceneMode_default.MORPHING) {
return;
}
const modelImagery = this._modelImagery;
modelImagery.update(frameState);
if (!modelImagery.ready) {
const asynchronouslyLoadImagery = this._content?.tileset?._asynchronouslyLoadImagery ?? false;
if (!asynchronouslyLoadImagery) {
return;
}
}
updateFeatureTableId(this);
updateStyle(this);
updateFeatureTables(this, frameState);
updatePointCloudShading(this);
updateSilhouette(this, frameState);
updateSkipLevelOfDetail(this, frameState);
updateClippingPlanes(this, frameState);
updateClippingPolygons(this, frameState);
updateSceneMode(this, frameState);
updateFog(this, frameState);
updateVerticalExaggeration(this, frameState);
this._defaultTexture = frameState.context.defaultTexture;
buildDrawCommands(this, frameState);
updateModelMatrix(this, frameState);
updateClamping(this);
updateBoundingSphereAndScale(this, frameState);
updateReferenceMatrices(this, frameState);
if (!this._ready) {
frameState.afterRender.push(() => {
this._ready = true;
this._readyEvent.raiseEvent(this);
});
return;
}
if (this._loader.incrementallyLoadTextures && !this._texturesLoaded && this._loader.texturesLoaded) {
this.resetDrawCommands();
this._texturesLoaded = true;
this._texturesReadyEvent.raiseEvent(this);
}
updatePickIds(this);
updateSceneGraph(this, frameState);
updateShowCreditsOnScreen(this);
submitDrawCommands(this, frameState);
};
function processLoader(model, frameState) {
if (!model._resourcesLoaded || model._loader.incrementallyLoadTextures && !model._texturesLoaded) {
frameState.afterRender.push(() => true);
return model._loader.process(frameState);
}
return true;
}
function updateCustomShader(model, frameState) {
if (defined_default(model._customShader)) {
model._customShader.update(frameState);
}
}
function updateEnvironmentMap(model, frameState) {
const environmentMapManager = model._environmentMapManager;
const picking = frameState.passes.pick || frameState.passes.pickVoxel;
if (model._ready && environmentMapManager.owner === model && !picking) {
environmentMapManager.position = model._boundingSphere.center;
environmentMapManager.shouldUpdate = !defined_default(model._imageBasedLighting.sphericalHarmonicCoefficients) || !defined_default(model._imageBasedLighting.specularEnvironmentMaps);
environmentMapManager.update(frameState);
if (environmentMapManager.shouldRegenerateShaders) {
model.resetDrawCommands();
}
}
}
function updateImageBasedLighting(model, frameState) {
model._imageBasedLighting.update(frameState);
if (model._imageBasedLighting.shouldRegenerateShaders) {
model.resetDrawCommands();
}
}
function updateFeatureTableId(model) {
if (!model._featureTableIdDirty) {
return;
}
model._featureTableIdDirty = false;
const components = model._sceneGraph.components;
const structuralMetadata = components.structuralMetadata;
if (defined_default(structuralMetadata) && structuralMetadata.propertyTableCount > 0) {
model.featureTableId = selectFeatureTableId(components, model);
model._styleDirty = true;
model.resetDrawCommands();
}
}
function updateStyle(model) {
if (model._styleDirty) {
model.applyStyle(model._style);
model._styleDirty = false;
}
}
function updateFeatureTables(model, frameState) {
const featureTables = model._featureTables;
const length2 = featureTables.length;
let styleCommandsNeededDirty = false;
for (let i = 0; i < length2; i++) {
featureTables[i].update(frameState);
if (featureTables[i].styleCommandsNeededDirty) {
styleCommandsNeededDirty = true;
}
}
if (styleCommandsNeededDirty) {
updateStyleCommandsNeeded(model);
}
}
function updateStyleCommandsNeeded(model) {
const featureTable = model.featureTables[model.featureTableId];
model._styleCommandsNeeded = StyleCommandsNeeded_default.getStyleCommandsNeeded(
featureTable.featuresLength,
featureTable.batchTexture.translucentFeaturesLength
);
}
function updatePointCloudShading(model) {
const pointCloudShading = model.pointCloudShading;
if (pointCloudShading.attenuation !== model._attenuation) {
model.resetDrawCommands();
model._attenuation = pointCloudShading.attenuation;
}
if (pointCloudShading.backFaceCulling !== model._pointCloudBackFaceCulling) {
model.resetDrawCommands();
model._pointCloudBackFaceCulling = pointCloudShading.backFaceCulling;
}
}
function updateSilhouette(model, frameState) {
if (model._silhouetteDirty) {
if (supportsSilhouettes(frameState)) {
model.resetDrawCommands();
}
model._silhouetteDirty = false;
}
}
function updateSkipLevelOfDetail(model, frameState) {
const skipLevelOfDetail = model.hasSkipLevelOfDetail(frameState);
if (skipLevelOfDetail !== model._skipLevelOfDetail) {
model.resetDrawCommands();
model._skipLevelOfDetail = skipLevelOfDetail;
}
}
function updateClippingPlanes(model, frameState) {
let currentClippingPlanesState = 0;
if (model.isClippingEnabled()) {
if (model._clippingPlanes.owner === model) {
model._clippingPlanes.update(frameState);
}
currentClippingPlanesState = model._clippingPlanes.clippingPlanesState;
}
if (currentClippingPlanesState !== model._clippingPlanesState) {
model.resetDrawCommands();
model._clippingPlanesState = currentClippingPlanesState;
}
}
function updateClippingPolygons(model, frameState) {
let currentClippingPolygonsState = 0;
if (model.isClippingPolygonsEnabled()) {
if (model._clippingPolygons.owner === model) {
model._clippingPolygons.update(frameState);
model._clippingPolygons.queueCommands(frameState);
}
currentClippingPolygonsState = model._clippingPolygons.clippingPolygonsState;
}
if (currentClippingPolygonsState !== model._clippingPolygonsState) {
model.resetDrawCommands();
model._clippingPolygonsState = currentClippingPolygonsState;
}
}
function updateSceneMode(model, frameState) {
if (frameState.mode !== model._sceneMode) {
if (model._projectTo2D) {
model.resetDrawCommands();
} else {
model._updateModelMatrix = true;
}
model._sceneMode = frameState.mode;
}
}
function updateFog(model, frameState) {
const fogRenderable = frameState.fog.enabled && frameState.fog.renderable;
if (fogRenderable !== model._fogRenderable) {
model.resetDrawCommands();
model._fogRenderable = fogRenderable;
}
}
function updateVerticalExaggeration(model, frameState) {
if (model.enableVerticalExaggeration) {
const verticalExaggerationNeeded = frameState.verticalExaggeration !== 1;
if (model.hasVerticalExaggeration !== verticalExaggerationNeeded) {
model.resetDrawCommands();
model._hasVerticalExaggeration = verticalExaggerationNeeded;
}
} else if (model.hasVerticalExaggeration) {
model.resetDrawCommands();
model._hasVerticalExaggeration = false;
}
}
function buildDrawCommands(model, frameState) {
if (!model._drawCommandsBuilt) {
model.destroyPipelineResources();
model._sceneGraph.buildDrawCommands(frameState);
model._drawCommandsBuilt = true;
}
}
function updateModelMatrix(model, frameState) {
if (!Matrix4_default.equals(model.modelMatrix, model._modelMatrix)) {
if (frameState.mode !== SceneMode_default.SCENE3D && model._projectTo2D) {
throw new DeveloperError_default(
"Model.modelMatrix cannot be changed in 2D or Columbus View if projectTo2D is true."
);
}
model._updateModelMatrix = true;
model._modelMatrix = Matrix4_default.clone(model.modelMatrix, model._modelMatrix);
}
}
var scratchPosition5 = new Cartesian3_default();
var scratchCartographic5 = new Cartographic_default();
function updateClamping(model) {
if (!model._updateModelMatrix && !model._heightDirty && model._minimumPixelSize === 0) {
return;
}
if (defined_default(model._removeUpdateHeightCallback)) {
model._removeUpdateHeightCallback();
model._removeUpdateHeightCallback = void 0;
}
const scene = model._scene;
if (!defined_default(scene) || model.heightReference === HeightReference_default.NONE) {
if (model.heightReference !== HeightReference_default.NONE) {
throw new DeveloperError_default(
"Height reference is not supported without a scene."
);
}
model._clampedModelMatrix = void 0;
return;
}
const ellipsoid = scene.ellipsoid ?? Ellipsoid_default.default;
const modelMatrix = model.modelMatrix;
scratchPosition5.x = modelMatrix[12];
scratchPosition5.y = modelMatrix[13];
scratchPosition5.z = modelMatrix[14];
const cartoPosition = ellipsoid.cartesianToCartographic(scratchPosition5);
if (!defined_default(model._clampedModelMatrix)) {
model._clampedModelMatrix = Matrix4_default.clone(modelMatrix, new Matrix4_default());
}
model._removeUpdateHeightCallback = scene.updateHeight(
cartoPosition,
getUpdateHeightCallback(model, ellipsoid, cartoPosition),
model.heightReference
);
const height = scene.getHeight(cartoPosition, model.heightReference);
if (defined_default(height)) {
const callback = getUpdateHeightCallback(model, ellipsoid, cartoPosition);
Cartographic_default.clone(cartoPosition, scratchCartographic5);
scratchCartographic5.height = height;
callback(scratchCartographic5);
}
model._heightDirty = false;
model._updateModelMatrix = true;
}
function updateBoundingSphereAndScale(model, frameState) {
if (!model._updateModelMatrix && model._minimumPixelSize === 0) {
return;
}
const modelMatrix = defined_default(model._clampedModelMatrix) ? model._clampedModelMatrix : model.modelMatrix;
updateBoundingSphere(model, modelMatrix);
updateComputedScale(model, modelMatrix, frameState);
}
function updateBoundingSphere(model, modelMatrix) {
model._clampedScale = defined_default(model._maximumScale) ? Math.min(model._scale, model._maximumScale) : model._scale;
model._boundingSphere.center = Cartesian3_default.multiplyByScalar(
model._sceneGraph.boundingSphere.center,
model._clampedScale,
model._boundingSphere.center
);
model._boundingSphere.radius = model._initialRadius * model._clampedScale;
model._boundingSphere = BoundingSphere_default.transform(
model._boundingSphere,
modelMatrix,
model._boundingSphere
);
}
function updateComputedScale(model, modelMatrix, frameState) {
let scale = model.scale;
if (model.minimumPixelSize !== 0 && !model._projectTo2D) {
const context = frameState.context;
const maxPixelSize = Math.max(
context.drawingBufferWidth,
context.drawingBufferHeight
);
Matrix4_default.getTranslation(modelMatrix, scratchPosition5);
if (model._sceneMode !== SceneMode_default.SCENE3D) {
SceneTransforms_default.computeActualEllipsoidPosition(
frameState,
scratchPosition5,
scratchPosition5
);
}
const radius = model._boundingSphere.radius;
const metersPerPixel = scaleInPixels(scratchPosition5, radius, frameState);
const pixelsPerMeter = 1 / metersPerPixel;
const diameterInPixels = Math.min(
pixelsPerMeter * (2 * radius),
maxPixelSize
);
if (diameterInPixels < model.minimumPixelSize) {
scale = model.minimumPixelSize * metersPerPixel / (2 * model._initialRadius);
}
}
model._computedScale = defined_default(model.maximumScale) ? Math.min(model.maximumScale, scale) : scale;
}
function updatePickIds(model) {
if (!model._idDirty) {
return;
}
model._idDirty = false;
const id = model._id;
const pickIds = model._pickIds;
const length2 = pickIds.length;
for (let i = 0; i < length2; ++i) {
pickIds[i].object.id = id;
}
}
var yUpToZUp = new Matrix3_default(1, 0, 0, 0, 0, 1, 0, -1, 0);
function updateReferenceMatrices(model, frameState) {
const modelMatrix = defined_default(model._clampedModelMatrix) ? model._clampedModelMatrix : model.modelMatrix;
const referenceMatrix = model.referenceMatrix ?? modelMatrix;
const context = frameState.context;
let iblReferenceFrameMatrix3 = scratchIBLReferenceFrameMatrix3;
let iblReferenceFrameMatrix4 = scratchIBLReferenceFrameMatrix4;
iblReferenceFrameMatrix4 = Matrix4_default.multiply(
context.uniformState.view3D,
referenceMatrix,
iblReferenceFrameMatrix4
);
iblReferenceFrameMatrix3 = Matrix4_default.getRotation(
iblReferenceFrameMatrix4,
iblReferenceFrameMatrix3
);
iblReferenceFrameMatrix3 = Matrix3_default.transpose(
iblReferenceFrameMatrix3,
iblReferenceFrameMatrix3
);
model._iblReferenceFrameMatrix = Matrix3_default.multiply(
yUpToZUp,
iblReferenceFrameMatrix3,
model._iblReferenceFrameMatrix
);
if (model.isClippingEnabled()) {
let clippingPlanesMatrix = scratchClippingPlanesMatrix;
clippingPlanesMatrix = Matrix4_default.multiply(
context.uniformState.view3D,
referenceMatrix,
clippingPlanesMatrix
);
clippingPlanesMatrix = Matrix4_default.multiply(
clippingPlanesMatrix,
model._clippingPlanes.modelMatrix,
clippingPlanesMatrix
);
model._clippingPlanesMatrix = Matrix4_default.inverseTranspose(
clippingPlanesMatrix,
model._clippingPlanesMatrix
);
}
}
function updateSceneGraph(model, frameState) {
const sceneGraph = model._sceneGraph;
if (model._updateModelMatrix || model._minimumPixelSize !== 0) {
const modelMatrix = defined_default(model._clampedModelMatrix) ? model._clampedModelMatrix : model.modelMatrix;
sceneGraph.updateModelMatrix(modelMatrix, frameState);
model._updateModelMatrix = false;
}
if (model._backFaceCullingDirty) {
sceneGraph.updateBackFaceCulling(model._backFaceCulling);
model._backFaceCullingDirty = false;
}
if (model._shadowsDirty) {
sceneGraph.updateShadows(model._shadows);
model._shadowsDirty = false;
}
if (model._debugShowBoundingVolumeDirty) {
sceneGraph.updateShowBoundingVolume(model._debugShowBoundingVolume);
model._debugShowBoundingVolumeDirty = false;
}
let updateForAnimations = false;
if (!defined_default(model.classificationType)) {
updateForAnimations = model._userAnimationDirty || model._activeAnimations.update(frameState);
}
sceneGraph.update(frameState, updateForAnimations);
model._userAnimationDirty = false;
}
function updateShowCreditsOnScreen(model) {
if (!model._showCreditsOnScreenDirty) {
return;
}
model._showCreditsOnScreenDirty = false;
model._credits.length = 0;
const showOnScreen = model._showCreditsOnScreen;
if (defined_default(model._credit)) {
const credit = Credit_default.clone(model._credit);
credit.showOnScreen = credit.showOnScreen || showOnScreen;
model._credits.push(credit);
}
const resourceCredits = model._resourceCredits;
const resourceCreditsLength = resourceCredits.length;
for (let i = 0; i < resourceCreditsLength; i++) {
const credit = Credit_default.clone(resourceCredits[i]);
credit.showOnScreen = credit.showOnScreen || showOnScreen;
model._credits.push(credit);
}
const gltfCredits = model._gltfCredits;
const gltfCreditsLength = gltfCredits.length;
for (let i = 0; i < gltfCreditsLength; i++) {
const credit = Credit_default.clone(gltfCredits[i]);
credit.showOnScreen = credit.showOnScreen || showOnScreen;
model._credits.push(credit);
}
}
function submitDrawCommands(model, frameState) {
const displayConditionPassed = passesDistanceDisplayCondition(
model,
frameState
);
const invisible = model.isInvisible();
const silhouette = model.hasSilhouette(frameState);
const showModel = model._show && model._computedScale !== 0 && displayConditionPassed && (!invisible || silhouette);
const passes = frameState.passes;
const submitCommandsForPass = passes.render || passes.pick && model.allowPicking;
if (showModel && !model._ignoreCommands && submitCommandsForPass) {
addCreditsToCreditDisplay(model, frameState);
model._sceneGraph.pushDrawCommands(frameState);
}
}
var scratchBoundingSphere5 = new BoundingSphere_default();
function scaleInPixels(positionWC2, radius, frameState) {
scratchBoundingSphere5.center = positionWC2;
scratchBoundingSphere5.radius = radius;
return frameState.camera.getPixelSize(
scratchBoundingSphere5,
frameState.context.drawingBufferWidth,
frameState.context.drawingBufferHeight
);
}
var scratchUpdateHeightCartesian = new Cartesian3_default();
function getUpdateHeightCallback(model, ellipsoid, originalPostition) {
return function(clampedPosition) {
if (isHeightReferenceRelative(model.heightReference)) {
clampedPosition.height += originalPostition.height;
}
ellipsoid.cartographicToCartesian(
clampedPosition,
scratchUpdateHeightCartesian
);
const clampedModelMatrix = model._clampedModelMatrix;
Matrix4_default.clone(model.modelMatrix, clampedModelMatrix);
clampedModelMatrix[12] = scratchUpdateHeightCartesian.x;
clampedModelMatrix[13] = scratchUpdateHeightCartesian.y;
clampedModelMatrix[14] = scratchUpdateHeightCartesian.z;
model._heightDirty = true;
};
}
var scratchDisplayConditionCartesian = new Cartesian3_default();
function passesDistanceDisplayCondition(model, frameState) {
const condition = model.distanceDisplayCondition;
if (!defined_default(condition)) {
return true;
}
const nearSquared = condition.near * condition.near;
const farSquared = condition.far * condition.far;
let distanceSquared;
if (frameState.mode === SceneMode_default.SCENE2D) {
const frustum2DWidth = frameState.camera.frustum.right - frameState.camera.frustum.left;
const distance2 = frustum2DWidth * 0.5;
distanceSquared = distance2 * distance2;
} else {
const position = Matrix4_default.getTranslation(
model.modelMatrix,
scratchDisplayConditionCartesian
);
SceneTransforms_default.computeActualEllipsoidPosition(
frameState,
position,
position
);
distanceSquared = Cartesian3_default.distanceSquared(
position,
frameState.camera.positionWC
);
}
return distanceSquared >= nearSquared && distanceSquared <= farSquared;
}
function addCreditsToCreditDisplay(model, frameState) {
const creditDisplay = frameState.creditDisplay;
const credits = model._credits;
const creditsLength = credits.length;
for (let c = 0; c < creditsLength; c++) {
creditDisplay.addCreditToNextFrame(credits[c]);
}
}
Model.prototype.isTranslucent = function() {
const color = this.color;
return defined_default(color) && color.alpha > 0 && color.alpha < 1;
};
Model.prototype.isInvisible = function() {
const color = this.color;
return defined_default(color) && color.alpha === 0;
};
function supportsSilhouettes(frameState) {
return frameState.context.stencilBuffer;
}
Model.prototype.hasSilhouette = function(frameState) {
return supportsSilhouettes(frameState) && this._silhouetteSize > 0 && this._silhouetteColor.alpha > 0 && !defined_default(this._classificationType);
};
Model.prototype.hasSkipLevelOfDetail = function(frameState) {
if (!ModelType_default.is3DTiles(this.type)) {
return false;
}
const supportsSkipLevelOfDetail = frameState.context.stencilBuffer;
const tileset = this._content.tileset;
return supportsSkipLevelOfDetail && tileset.isSkippingLevelOfDetail;
};
Model.prototype.isClippingEnabled = function() {
const clippingPlanes = this._clippingPlanes;
return defined_default(clippingPlanes) && clippingPlanes.enabled && clippingPlanes.length !== 0;
};
Model.prototype.pick = function(ray, frameState, verticalExaggeration, relativeHeight, result) {
return pickModel(
this,
ray,
frameState,
verticalExaggeration,
relativeHeight,
result
);
};
Model.prototype.isClippingPolygonsEnabled = function() {
const clippingPolygons = this._clippingPolygons;
return defined_default(clippingPolygons) && clippingPolygons.enabled && clippingPolygons.length !== 0;
};
Model.prototype.isDestroyed = function() {
return false;
};
Model.prototype.destroy = function() {
const loader = this._loader;
if (defined_default(loader)) {
loader.destroy();
}
const featureTables = this._featureTables;
if (defined_default(featureTables)) {
const length2 = featureTables.length;
for (let i = 0; i < length2; i++) {
featureTables[i].destroy();
}
}
this.destroyPipelineResources();
this.destroyModelResources();
if (defined_default(this._removeUpdateHeightCallback)) {
this._removeUpdateHeightCallback();
this._removeUpdateHeightCallback = void 0;
}
if (defined_default(this._terrainProviderChangedCallback)) {
this._terrainProviderChangedCallback();
this._terrainProviderChangedCallback = void 0;
}
const clippingPlaneCollection = this._clippingPlanes;
if (defined_default(clippingPlaneCollection) && !clippingPlaneCollection.isDestroyed() && clippingPlaneCollection.owner === this) {
clippingPlaneCollection.destroy();
}
this._clippingPlanes = void 0;
const clippingPolygonCollection = this._clippingPolygons;
if (defined_default(clippingPolygonCollection) && !clippingPolygonCollection.isDestroyed() && clippingPolygonCollection.owner === this) {
clippingPolygonCollection.destroy();
}
this._clippingPolygons = void 0;
if (this._shouldDestroyImageBasedLighting && !this._imageBasedLighting.isDestroyed()) {
this._imageBasedLighting.destroy();
}
this._imageBasedLighting = void 0;
const environmentMapManager = this._environmentMapManager;
if (!environmentMapManager.isDestroyed() && environmentMapManager.owner === this) {
environmentMapManager.destroy();
}
this._environmentMapManager = void 0;
destroyObject_default(this);
};
Model.prototype.destroyPipelineResources = function() {
const resources = this._pipelineResources;
for (let i = 0; i < resources.length; i++) {
resources[i].destroy();
}
this._pipelineResources.length = 0;
this._pickIds.length = 0;
};
Model.prototype.destroyModelResources = function() {
const resources = this._modelResources;
for (let i = 0; i < resources.length; i++) {
resources[i].destroy();
}
this._modelResources.length = 0;
};
Model.fromGltfAsync = async function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
if (!defined_default(options.url) && !defined_default(options.gltf)) {
throw new DeveloperError_default("options.url is required.");
}
const gltf = options.url ?? options.gltf;
const loaderOptions = {
releaseGltfJson: options.releaseGltfJson,
asynchronous: options.asynchronous,
incrementallyLoadTextures: options.incrementallyLoadTextures,
upAxis: options.upAxis,
forwardAxis: options.forwardAxis,
loadAttributesFor2D: options.projectTo2D,
enablePick: options.enablePick,
loadIndicesForWireframe: options.enableDebugWireframe,
loadPrimitiveOutline: options.enableShowOutline,
loadForClassification: defined_default(options.classificationType)
};
const basePath = options.basePath ?? "";
const baseResource2 = Resource_default.createIfNeeded(basePath);
if (defined_default(gltf.asset)) {
loaderOptions.gltfJson = gltf;
loaderOptions.baseResource = baseResource2;
loaderOptions.gltfResource = baseResource2;
} else if (gltf instanceof Uint8Array) {
loaderOptions.typedArray = gltf;
loaderOptions.baseResource = baseResource2;
loaderOptions.gltfResource = baseResource2;
} else {
loaderOptions.gltfResource = Resource_default.createIfNeeded(gltf);
}
const loader = new GltfLoader_default(loaderOptions);
const is3DTiles = defined_default(options.content);
const type = is3DTiles ? ModelType_default.TILE_GLTF : ModelType_default.GLTF;
const resource = loaderOptions.gltfResource;
const modelOptions = makeModelOptions(loader, type, options);
modelOptions.resource = resource;
modelOptions.environmentMapOptions = options.environmentMapOptions;
try {
await loader.load();
} catch (error) {
loader.destroy();
throw ModelUtility_default.getError("model", resource, error);
}
const gltfCallback = options.gltfCallback;
if (defined_default(gltfCallback)) {
Check_default.typeOf.func("options.gltfCallback", gltfCallback);
gltfCallback(loader.gltfJson);
}
const model = new Model(modelOptions);
const resourceCredits = model._resource.credits;
if (defined_default(resourceCredits)) {
const length2 = resourceCredits.length;
for (let i = 0; i < length2; i++) {
model._resourceCredits.push(Credit_default.clone(resourceCredits[i]));
}
}
return model;
};
Model.fromB3dm = async function(options) {
const loaderOptions = {
b3dmResource: options.resource,
arrayBuffer: options.arrayBuffer,
byteOffset: options.byteOffset,
releaseGltfJson: options.releaseGltfJson,
asynchronous: options.asynchronous,
incrementallyLoadTextures: options.incrementallyLoadTextures,
upAxis: options.upAxis,
forwardAxis: options.forwardAxis,
loadAttributesFor2D: options.projectTo2D,
enablePick: options.enablePick,
loadIndicesForWireframe: options.enableDebugWireframe,
loadPrimitiveOutline: options.enableShowOutline,
loadForClassification: defined_default(options.classificationType)
};
const loader = new B3dmLoader_default(loaderOptions);
try {
await loader.load();
const modelOptions = makeModelOptions(loader, ModelType_default.TILE_B3DM, options);
const model = new Model(modelOptions);
return model;
} catch (error) {
loader.destroy();
throw error;
}
};
Model.fromPnts = async function(options) {
const loaderOptions = {
arrayBuffer: options.arrayBuffer,
byteOffset: options.byteOffset,
loadAttributesFor2D: options.projectTo2D
};
const loader = new PntsLoader_default(loaderOptions);
try {
await loader.load();
const modelOptions = makeModelOptions(loader, ModelType_default.TILE_PNTS, options);
const model = new Model(modelOptions);
return model;
} catch (error) {
loader.destroy();
throw error;
}
};
Model.fromI3dm = async function(options) {
const loaderOptions = {
i3dmResource: options.resource,
arrayBuffer: options.arrayBuffer,
byteOffset: options.byteOffset,
releaseGltfJson: options.releaseGltfJson,
asynchronous: options.asynchronous,
incrementallyLoadTextures: options.incrementallyLoadTextures,
upAxis: options.upAxis,
forwardAxis: options.forwardAxis,
loadAttributesFor2D: options.projectTo2D,
enablePick: options.enablePick,
loadIndicesForWireframe: options.enableDebugWireframe,
loadPrimitiveOutline: options.enableShowOutline
};
const loader = new I3dmLoader_default(loaderOptions);
try {
await loader.load();
const modelOptions = makeModelOptions(loader, ModelType_default.TILE_I3DM, options);
const model = new Model(modelOptions);
return model;
} catch (error) {
loader.destroy();
throw error;
}
};
Model.fromGeoJson = async function(options) {
const loaderOptions = {
geoJson: options.geoJson
};
const loader = new GeoJsonLoader_default(loaderOptions);
const modelOptions = makeModelOptions(
loader,
ModelType_default.TILE_GEOJSON,
options
);
const model = new Model(modelOptions);
return model;
};
var scratchColor8 = new Color_default();
Model.prototype.applyColorAndShow = function(style) {
const previousColor = Color_default.clone(this._color, scratchColor8);
const hasColorStyle = defined_default(style) && defined_default(style.color);
const hasShowStyle = defined_default(style) && defined_default(style.show);
this._color = hasColorStyle ? style.color.evaluateColor(void 0, this._color) : Color_default.clone(Color_default.WHITE, this._color);
this._show = hasShowStyle ? style.show.evaluate(void 0) : true;
if (isColorAlphaDirty(previousColor, this._color)) {
this.resetDrawCommands();
}
};
Model.prototype.applyStyle = function(style) {
const isPnts = this.type === ModelType_default.TILE_PNTS;
const hasFeatureTable = defined_default(this.featureTableId) && this.featureTables[this.featureTableId].featuresLength > 0;
const propertyAttributes = defined_default(this.structuralMetadata) ? this.structuralMetadata.propertyAttributes : void 0;
const hasPropertyAttributes = defined_default(propertyAttributes) && defined_default(propertyAttributes[0]);
if (isPnts && (!hasFeatureTable || hasPropertyAttributes)) {
this.resetDrawCommands();
return;
}
if (hasFeatureTable) {
const featureTable = this.featureTables[this.featureTableId];
featureTable.applyStyle(style);
updateStyleCommandsNeeded(this, style);
} else {
this.applyColorAndShow(style);
this._styleCommandsNeeded = void 0;
}
};
function makeModelOptions(loader, modelType, options) {
return {
loader,
type: modelType,
resource: options.resource,
show: options.show,
modelMatrix: options.modelMatrix,
scale: options.scale,
enableVerticalExaggeration: options.enableVerticalExaggeration,
minimumPixelSize: options.minimumPixelSize,
maximumScale: options.maximumScale,
id: options.id,
allowPicking: options.allowPicking,
clampAnimations: options.clampAnimations,
shadows: options.shadows,
debugShowBoundingVolume: options.debugShowBoundingVolume,
enableDebugWireframe: options.enableDebugWireframe,
debugWireframe: options.debugWireframe,
cull: options.cull,
opaquePass: options.opaquePass,
customShader: options.customShader,
content: options.content,
heightReference: options.heightReference,
scene: options.scene,
distanceDisplayCondition: options.distanceDisplayCondition,
color: options.color,
colorBlendAmount: options.colorBlendAmount,
colorBlendMode: options.colorBlendMode,
silhouetteColor: options.silhouetteColor,
silhouetteSize: options.silhouetteSize,
enableShowOutline: options.enableShowOutline,
showOutline: options.showOutline,
outlineColor: options.outlineColor,
clippingPlanes: options.clippingPlanes,
clippingPolygons: options.clippingPolygons,
lightColor: options.lightColor,
imageBasedLighting: options.imageBasedLighting,
backFaceCulling: options.backFaceCulling,
credit: options.credit,
showCreditsOnScreen: options.showCreditsOnScreen,
splitDirection: options.splitDirection,
projectTo2D: options.projectTo2D,
enablePick: options.enablePick,
featureIdLabel: options.featureIdLabel,
instanceFeatureIdLabel: options.instanceFeatureIdLabel,
pointCloudShading: options.pointCloudShading,
classificationType: options.classificationType,
pickObject: options.pickObject
};
}
var Model_default = Model;
// packages/engine/Source/Scene/Model/Model3DTileContent.js
function Model3DTileContent(tileset, tile, resource) {
this._tileset = tileset;
this._tile = tile;
this._resource = resource;
this._model = void 0;
this._metadata = void 0;
this._group = void 0;
this._ready = false;
}
Object.defineProperties(Model3DTileContent.prototype, {
featuresLength: {
get: function() {
const model = this._model;
const featureTables = model.featureTables;
const featureTableId = model.featureTableId;
if (defined_default(featureTables) && defined_default(featureTables[featureTableId])) {
return featureTables[featureTableId].featuresLength;
}
return 0;
}
},
pointsLength: {
get: function() {
return this._model.statistics.pointsLength;
}
},
trianglesLength: {
get: function() {
return this._model.statistics.trianglesLength;
}
},
geometryByteLength: {
get: function() {
return this._model.statistics.geometryByteLength;
}
},
texturesByteLength: {
get: function() {
return this._model.statistics.texturesByteLength;
}
},
batchTableByteLength: {
get: function() {
const statistics2 = this._model.statistics;
return statistics2.propertyTablesByteLength + statistics2.batchTexturesByteLength;
}
},
innerContents: {
get: function() {
return void 0;
}
},
/**
* Returns true when the tile's content is ready to render; otherwise false
*
* @memberof Model3DTileContent.prototype
*
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
return this._ready;
}
},
tileset: {
get: function() {
return this._tileset;
}
},
tile: {
get: function() {
return this._tile;
}
},
url: {
get: function() {
return this._resource.getUrlComponent(true);
}
},
batchTable: {
get: function() {
const model = this._model;
const featureTables = model.featureTables;
const featureTableId = model.featureTableId;
if (defined_default(featureTables) && defined_default(featureTables[featureTableId])) {
return featureTables[featureTableId];
}
return void 0;
}
},
metadata: {
get: function() {
return this._metadata;
},
set: function(value) {
this._metadata = value;
}
},
group: {
get: function() {
return this._group;
},
set: function(value) {
this._group = value;
}
}
});
Model3DTileContent.prototype.getTextureIds = function() {
return this._model.statistics.getTextureIds();
};
Model3DTileContent.prototype.getTextureByteLengthById = function(textureId) {
return this._model.statistics.getTextureByteLengthById(textureId);
};
Model3DTileContent.prototype.getExtension = function(extensionName) {
const model = this._model;
const extension = model.getExtension(extensionName);
return extension;
};
Model3DTileContent.prototype.getFeature = function(featureId) {
const model = this._model;
const featureTableId = model.featureTableId;
if (!defined_default(featureTableId)) {
throw new DeveloperError_default(
"No feature ID set is selected. Make sure Cesium3DTileset.featureIdLabel or Cesium3DTileset.instanceFeatureIdLabel is defined"
);
}
const featureTable = model.featureTables[featureTableId];
if (!defined_default(featureTable)) {
throw new DeveloperError_default(
"No feature table found for the selected feature ID set"
);
}
const featuresLength = featureTable.featuresLength;
if (!defined_default(featureId) || featureId < 0 || featureId >= featuresLength) {
throw new DeveloperError_default(
`featureId is required and must be between 0 and featuresLength - 1 (${featuresLength - 1}).`
);
}
return featureTable.getFeature(featureId);
};
Model3DTileContent.prototype.hasProperty = function(featureId, name) {
const model = this._model;
const featureTableId = model.featureTableId;
if (!defined_default(featureTableId)) {
return false;
}
const featureTable = model.featureTables[featureTableId];
return featureTable.hasProperty(featureId, name);
};
Model3DTileContent.prototype.applyDebugSettings = function(enabled, color) {
color = enabled ? color : Color_default.WHITE;
if (this.featuresLength === 0) {
this._model.color = color;
} else if (defined_default(this.batchTable)) {
this.batchTable.setAllColor(color);
}
};
Model3DTileContent.prototype.applyStyle = function(style) {
this._model.style = style;
};
Model3DTileContent.prototype.update = function(tileset, frameState) {
const model = this._model;
const tile = this._tile;
model.colorBlendAmount = tileset.colorBlendAmount;
model.colorBlendMode = tileset.colorBlendMode;
model.modelMatrix = tile.computedTransform;
model.customShader = tileset.customShader;
model.featureIdLabel = tileset.featureIdLabel;
model.instanceFeatureIdLabel = tileset.instanceFeatureIdLabel;
model.lightColor = tileset.lightColor;
model.imageBasedLighting = tileset.imageBasedLighting;
model.backFaceCulling = tileset.backFaceCulling;
model.shadows = tileset.shadows;
model.showCreditsOnScreen = tileset.showCreditsOnScreen;
model.splitDirection = tileset.splitDirection;
model.debugWireframe = tileset.debugWireframe;
model.showOutline = tileset.showOutline;
model.outlineColor = tileset.outlineColor;
model.pointCloudShading = tileset.pointCloudShading;
const tilesetClippingPlanes = tileset.clippingPlanes;
model.referenceMatrix = tileset.clippingPlanesOriginMatrix;
if (defined_default(tilesetClippingPlanes) && tile.clippingPlanesDirty) {
model._clippingPlanes = tilesetClippingPlanes.enabled && tile._isClipped ? tilesetClippingPlanes : void 0;
}
const tilesetEnvironmentMapManager = tileset.environmentMapManager;
if (model.environmentMapManager !== tilesetClippingPlanes) {
model._environmentMapManager = tilesetEnvironmentMapManager;
}
if (defined_default(tilesetClippingPlanes) && defined_default(model._clippingPlanes) && model._clippingPlanes !== tilesetClippingPlanes) {
model._clippingPlanes = tilesetClippingPlanes;
model._clippingPlanesState = 0;
}
const tilesetClippingPolygons = tileset.clippingPolygons;
if (defined_default(tilesetClippingPolygons) && tile.clippingPolygonsDirty) {
model._clippingPolygons = tilesetClippingPolygons.enabled && tile._isClippedByPolygon ? tilesetClippingPolygons : void 0;
}
if (defined_default(tilesetClippingPolygons) && defined_default(model._clippingPolygons) && model._clippingPolygons !== tilesetClippingPolygons) {
model._clippingPolygons = tilesetClippingPolygons;
model._clippingPolygonsState = 0;
}
model.update(frameState);
if (!this._ready && model.ready) {
model.activeAnimations.addAll({
loop: ModelAnimationLoop_default.REPEAT
});
this._ready = true;
}
};
Model3DTileContent.prototype.isDestroyed = function() {
return false;
};
Model3DTileContent.prototype.destroy = function() {
this._model = this._model && this._model.destroy();
return destroyObject_default(this);
};
Model3DTileContent.fromGltf = async function(tileset, tile, resource, gltf) {
const content = new Model3DTileContent(tileset, tile, resource);
const additionalOptions = {
gltf,
basePath: resource
};
const modelOptions = makeModelOptions2(
tileset,
tile,
content,
additionalOptions
);
const classificationType = tileset.vectorClassificationOnly ? void 0 : tileset.classificationType;
modelOptions.classificationType = classificationType;
const model = await Model_default.fromGltfAsync(modelOptions);
content._model = model;
return content;
};
Model3DTileContent.fromB3dm = async function(tileset, tile, resource, arrayBuffer, byteOffset) {
const content = new Model3DTileContent(tileset, tile, resource);
const additionalOptions = {
arrayBuffer,
byteOffset,
resource
};
const modelOptions = makeModelOptions2(
tileset,
tile,
content,
additionalOptions
);
const classificationType = tileset.vectorClassificationOnly ? void 0 : tileset.classificationType;
modelOptions.classificationType = classificationType;
const model = await Model_default.fromB3dm(modelOptions);
content._model = model;
return content;
};
Model3DTileContent.fromI3dm = async function(tileset, tile, resource, arrayBuffer, byteOffset) {
const content = new Model3DTileContent(tileset, tile, resource);
const additionalOptions = {
arrayBuffer,
byteOffset,
resource
};
const modelOptions = makeModelOptions2(
tileset,
tile,
content,
additionalOptions
);
const model = await Model_default.fromI3dm(modelOptions);
content._model = model;
return content;
};
Model3DTileContent.fromPnts = async function(tileset, tile, resource, arrayBuffer, byteOffset) {
const content = new Model3DTileContent(tileset, tile, resource);
const additionalOptions = {
arrayBuffer,
byteOffset,
resource
};
const modelOptions = makeModelOptions2(
tileset,
tile,
content,
additionalOptions
);
const model = await Model_default.fromPnts(modelOptions);
content._model = model;
return content;
};
Model3DTileContent.fromGeoJson = async function(tileset, tile, resource, geoJson) {
const content = new Model3DTileContent(tileset, tile, resource);
const additionalOptions = {
geoJson,
resource
};
const modelOptions = makeModelOptions2(
tileset,
tile,
content,
additionalOptions
);
const model = await Model_default.fromGeoJson(modelOptions);
content._model = model;
return content;
};
Model3DTileContent.prototype.pick = function(ray, frameState, result) {
if (!defined_default(this._model) || !this._ready) {
return void 0;
}
const verticalExaggeration = frameState.verticalExaggeration;
const relativeHeight = frameState.verticalExaggerationRelativeHeight;
return this._model.pick(
ray,
frameState,
verticalExaggeration,
relativeHeight,
Ellipsoid_default.WGS84,
result
);
};
function makeModelOptions2(tileset, tile, content, additionalOptions) {
const mainOptions = {
cull: false,
// The model is already culled by 3D Tiles
releaseGltfJson: true,
// Models are unique and will not benefit from caching so save memory
opaquePass: Pass_default.CESIUM_3D_TILE,
// Draw opaque portions of the model during the 3D Tiles pass
modelMatrix: tile.computedTransform,
upAxis: tileset._modelUpAxis,
forwardAxis: tileset._modelForwardAxis,
incrementallyLoadTextures: false,
customShader: tileset.customShader,
content,
colorBlendMode: tileset.colorBlendMode,
colorBlendAmount: tileset.colorBlendAmount,
lightColor: tileset.lightColor,
imageBasedLighting: tileset.imageBasedLighting,
featureIdLabel: tileset.featureIdLabel,
instanceFeatureIdLabel: tileset.instanceFeatureIdLabel,
pointCloudShading: tileset.pointCloudShading,
clippingPlanes: tileset.clippingPlanes,
backFaceCulling: tileset.backFaceCulling,
shadows: tileset.shadows,
showCreditsOnScreen: tileset.showCreditsOnScreen,
splitDirection: tileset.splitDirection,
enableDebugWireframe: tileset._enableDebugWireframe,
debugWireframe: tileset.debugWireframe,
projectTo2D: tileset._projectTo2D,
enablePick: tileset._enablePick,
enableShowOutline: tileset._enableShowOutline,
showOutline: tileset.showOutline,
outlineColor: tileset.outlineColor
};
return combine_default(additionalOptions, mainOptions);
}
var Model3DTileContent_default = Model3DTileContent;
// packages/engine/Source/Scene/Tileset3DTileContent.js
var import_InlineWorkers738 = __toESM(require_InlineWorkers(), 1);
function Tileset3DTileContent(tileset, tile, resource) {
this._tileset = tileset;
this._tile = tile;
this._resource = resource;
this.featurePropertiesDirty = false;
this._metadata = void 0;
this._group = void 0;
this._ready = false;
}
Object.defineProperties(Tileset3DTileContent.prototype, {
featuresLength: {
get: function() {
return 0;
}
},
pointsLength: {
get: function() {
return 0;
}
},
trianglesLength: {
get: function() {
return 0;
}
},
geometryByteLength: {
get: function() {
return 0;
}
},
texturesByteLength: {
get: function() {
return 0;
}
},
batchTableByteLength: {
get: function() {
return 0;
}
},
innerContents: {
get: function() {
return void 0;
}
},
/**
* Returns true when the tile's content is ready to render; otherwise false
*
* @memberof Tileset3DTileContent.prototype
*
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
return this._ready;
}
},
tileset: {
get: function() {
return this._tileset;
}
},
tile: {
get: function() {
return this._tile;
}
},
url: {
get: function() {
return this._resource.getUrlComponent(true);
}
},
batchTable: {
get: function() {
return void 0;
}
},
metadata: {
get: function() {
return this._metadata;
},
set: function(value) {
this._metadata = value;
}
},
group: {
get: function() {
return this._group;
},
set: function(value) {
this._group = value;
}
}
});
Tileset3DTileContent.fromJson = function(tileset, tile, resource, json) {
const content = new Tileset3DTileContent(tileset, tile, resource);
content._tileset.loadTileset(content._resource, json, content._tile);
content._ready = true;
return content;
};
Tileset3DTileContent.prototype.hasProperty = function(batchId, name) {
return false;
};
Tileset3DTileContent.prototype.getFeature = function(batchId) {
return void 0;
};
Tileset3DTileContent.prototype.applyDebugSettings = function(enabled, color) {
};
Tileset3DTileContent.prototype.applyStyle = function(style) {
};
Tileset3DTileContent.prototype.update = function(tileset, frameState) {
};
Tileset3DTileContent.prototype.pick = function(ray, frameState, result) {
return void 0;
};
Tileset3DTileContent.prototype.isDestroyed = function() {
return false;
};
Tileset3DTileContent.prototype.destroy = function() {
return destroyObject_default(this);
};
var Tileset3DTileContent_default = Tileset3DTileContent;
// packages/engine/Source/Scene/Vector3DTileContent.js
var import_InlineWorkers765 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Vector3DTilePoints.js
var import_InlineWorkers757 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/BillboardCollection.js
var import_InlineWorkers746 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/BillboardCollectionFS.js
var import_InlineWorkers739 = __toESM(require_InlineWorkers(), 1);
var BillboardCollectionFS_default = `uniform sampler2D u_atlas;
#ifdef VECTOR_TILE
uniform vec4 u_highlightColor;
#endif
in vec2 v_textureCoordinates;
in vec4 v_pickColor;
in vec4 v_color;
in float v_splitDirection;
#ifdef SDF
in vec4 v_outlineColor;
in float v_outlineWidth;
#endif
#ifdef FRAGMENT_DEPTH_CHECK
in vec4 v_textureCoordinateBounds; // the min and max x and y values for the texture coordinates
in vec4 v_originTextureCoordinateAndTranslate; // texture coordinate at the origin, billboard translate (used for label glyphs)
in vec4 v_compressed; // x: eyeDepth, y: applyTranslate & enableDepthCheck, z: dimensions, w: imageSize
in mat2 v_rotationMatrix;
const float SHIFT_LEFT12 = 4096.0;
const float SHIFT_LEFT1 = 2.0;
const float SHIFT_RIGHT12 = 1.0 / 4096.0;
const float SHIFT_RIGHT1 = 1.0 / 2.0;
float getGlobeDepth(vec2 adjustedST, vec2 depthLookupST, bool applyTranslate, vec2 dimensions, vec2 imageSize)
{
vec2 lookupVector = imageSize * (depthLookupST - adjustedST);
lookupVector = v_rotationMatrix * lookupVector;
vec2 labelOffset = (dimensions - imageSize) * (depthLookupST - vec2(0.0, v_originTextureCoordinateAndTranslate.y)); // aligns label glyph with bounding rectangle. Will be zero for billboards because dimensions and imageSize will be equal
vec2 translation = v_originTextureCoordinateAndTranslate.zw;
if (applyTranslate)
{
// this is only needed for labels where the horizontal origin is not LEFT
// it moves the label back to where the "origin" should be since all label glyphs are set to HorizontalOrigin.LEFT
translation += (dimensions * v_originTextureCoordinateAndTranslate.xy * vec2(1.0, 0.0));
}
vec2 st = ((lookupVector - translation + labelOffset) + gl_FragCoord.xy) / czm_viewport.zw;
float logDepthOrDepth = czm_unpackDepth(texture(czm_globeDepthTexture, st));
if (logDepthOrDepth == 0.0)
{
return 0.0; // not on the globe
}
vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth);
return eyeCoordinate.z / eyeCoordinate.w;
}
#endif
#ifdef SDF
// Get the distance from the edge of a glyph at a given position sampling an SDF texture.
float getDistance(vec2 position)
{
return texture(u_atlas, position).r;
}
// Samples the sdf texture at the given position and produces a color based on the fill color and the outline.
vec4 getSDFColor(vec2 position, float outlineWidth, vec4 outlineColor, float smoothing)
{
float distance = getDistance(position);
if (outlineWidth > 0.0)
{
// Don't get the outline edge exceed the SDF_EDGE
float outlineEdge = clamp(SDF_EDGE - outlineWidth, 0.0, SDF_EDGE);
float outlineFactor = smoothstep(SDF_EDGE - smoothing, SDF_EDGE + smoothing, distance);
vec4 sdfColor = mix(outlineColor, v_color, outlineFactor);
float alpha = smoothstep(outlineEdge - smoothing, outlineEdge + smoothing, distance);
return vec4(sdfColor.rgb, sdfColor.a * alpha);
}
else
{
float alpha = smoothstep(SDF_EDGE - smoothing, SDF_EDGE + smoothing, distance);
return vec4(v_color.rgb, v_color.a * alpha);
}
}
#endif
void main()
{
if (v_splitDirection < 0.0 && gl_FragCoord.x > czm_splitPosition) discard;
if (v_splitDirection > 0.0 && gl_FragCoord.x < czm_splitPosition) discard;
vec4 color = texture(u_atlas, v_textureCoordinates);
#ifdef SDF
float outlineWidth = v_outlineWidth;
vec4 outlineColor = v_outlineColor;
// Get the current distance
float distance = getDistance(v_textureCoordinates);
#if (__VERSION__ == 300 || defined(GL_OES_standard_derivatives))
float smoothing = fwidth(distance);
// Get an offset that is approximately half the distance to the neighbor pixels
// 0.354 is approximately half of 1/sqrt(2)
vec2 sampleOffset = 0.354 * vec2(dFdx(v_textureCoordinates) + dFdy(v_textureCoordinates));
// Sample the center point
vec4 center = getSDFColor(v_textureCoordinates, outlineWidth, outlineColor, smoothing);
// Sample the 4 neighbors
vec4 color1 = getSDFColor(v_textureCoordinates + vec2(sampleOffset.x, sampleOffset.y), outlineWidth, outlineColor, smoothing);
vec4 color2 = getSDFColor(v_textureCoordinates + vec2(-sampleOffset.x, sampleOffset.y), outlineWidth, outlineColor, smoothing);
vec4 color3 = getSDFColor(v_textureCoordinates + vec2(-sampleOffset.x, -sampleOffset.y), outlineWidth, outlineColor, smoothing);
vec4 color4 = getSDFColor(v_textureCoordinates + vec2(sampleOffset.x, -sampleOffset.y), outlineWidth, outlineColor, smoothing);
// Equally weight the center sample and the 4 neighboring samples
color = (center + color1 + color2 + color3 + color4)/5.0;
#else
// If no derivatives available (IE 10?), just do a single sample
float smoothing = 1.0/32.0;
color = getSDFColor(v_textureCoordinates, outlineWidth, outlineColor, smoothing);
#endif
color = czm_gammaCorrect(color);
#else
color = czm_gammaCorrect(color);
color *= czm_gammaCorrect(v_color);
#endif
// Fully transparent parts of the billboard are not pickable.
#if !defined(OPAQUE) && !defined(TRANSLUCENT)
if (color.a < 0.005) // matches 0/255 and 1/255
{
discard;
}
#else
// The billboard is rendered twice. The opaque pass discards translucent fragments
// and the translucent pass discards opaque fragments.
#ifdef OPAQUE
if (color.a < 0.995) // matches < 254/255
{
discard;
}
#else
if (color.a >= 0.995) // matches 254/255 and 255/255
{
discard;
}
#endif
#endif
#ifdef VECTOR_TILE
color *= u_highlightColor;
#endif
out_FragColor = color;
#ifdef LOG_DEPTH
czm_writeLogDepth();
#endif
#ifdef FRAGMENT_DEPTH_CHECK
float temp = v_compressed.y;
temp = temp * SHIFT_RIGHT1;
float temp2 = (temp - floor(temp)) * SHIFT_LEFT1;
bool enableDepthTest = temp2 != 0.0;
bool applyTranslate = floor(temp) != 0.0;
if (enableDepthTest) {
temp = v_compressed.z;
temp = temp * SHIFT_RIGHT12;
vec2 dimensions;
dimensions.y = (temp - floor(temp)) * SHIFT_LEFT12;
dimensions.x = floor(temp);
temp = v_compressed.w;
temp = temp * SHIFT_RIGHT12;
vec2 imageSize;
imageSize.y = (temp - floor(temp)) * SHIFT_LEFT12;
imageSize.x = floor(temp);
vec2 adjustedST = v_textureCoordinates - v_textureCoordinateBounds.xy;
adjustedST = adjustedST / vec2(v_textureCoordinateBounds.z - v_textureCoordinateBounds.x, v_textureCoordinateBounds.w - v_textureCoordinateBounds.y);
float epsilonEyeDepth = v_compressed.x + czm_epsilon1;
float globeDepth1 = getGlobeDepth(adjustedST, v_originTextureCoordinateAndTranslate.xy, applyTranslate, dimensions, imageSize);
// negative values go into the screen
if (globeDepth1 != 0.0 && globeDepth1 > epsilonEyeDepth)
{
float globeDepth2 = getGlobeDepth(adjustedST, vec2(0.0, 1.0), applyTranslate, dimensions, imageSize); // top left corner
if (globeDepth2 != 0.0 && globeDepth2 > epsilonEyeDepth)
{
float globeDepth3 = getGlobeDepth(adjustedST, vec2(1.0, 1.0), applyTranslate, dimensions, imageSize); // top right corner
if (globeDepth3 != 0.0 && globeDepth3 > epsilonEyeDepth)
{
discard;
}
}
}
}
#endif
}
`;
// packages/engine/Source/Shaders/BillboardCollectionVS.js
var import_InlineWorkers740 = __toESM(require_InlineWorkers(), 1);
var BillboardCollectionVS_default = `#ifdef INSTANCED
in vec2 direction;
#endif
in vec4 positionHighAndScale;
in vec4 positionLowAndRotation;
in vec4 compressedAttribute0; // pixel offset, translate, horizontal origin, vertical origin, show, direction, texture coordinates (texture offset)
in vec4 compressedAttribute1; // aligned axis, translucency by distance, image width
in vec4 compressedAttribute2; // label horizontal origin, image height, color, pick color, size in meters, valid aligned axis, 13 bits free
in vec4 eyeOffset; // eye offset in meters, 4 bytes free (texture range)
in vec4 scaleByDistance; // near, nearScale, far, farScale
in vec4 pixelOffsetScaleByDistance; // near, nearScale, far, farScale
in vec4 compressedAttribute3; // distance display condition near, far, disableDepthTestDistance, dimensions
in vec2 sdf; // sdf outline color (rgb) and width (w)
in float splitDirection; // splitDirection
#if defined(VERTEX_DEPTH_CHECK) || defined(FRAGMENT_DEPTH_CHECK)
in vec4 textureCoordinateBoundsOrLabelTranslate; // the min and max x and y values for the texture coordinates
#endif
#ifdef VECTOR_TILE
in float a_batchId;
#endif
out vec2 v_textureCoordinates;
#ifdef FRAGMENT_DEPTH_CHECK
out vec4 v_textureCoordinateBounds;
out vec4 v_originTextureCoordinateAndTranslate;
out vec4 v_compressed; // x: eyeDepth, y: applyTranslate & enableDepthCheck, z: dimensions, w: imageSize
out mat2 v_rotationMatrix;
#endif
out vec4 v_pickColor;
out vec4 v_color;
out float v_splitDirection;
#ifdef SDF
out vec4 v_outlineColor;
out float v_outlineWidth;
#endif
const float UPPER_BOUND = 32768.0;
const float SHIFT_LEFT16 = 65536.0;
const float SHIFT_LEFT12 = 4096.0;
const float SHIFT_LEFT8 = 256.0;
const float SHIFT_LEFT7 = 128.0;
const float SHIFT_LEFT5 = 32.0;
const float SHIFT_LEFT3 = 8.0;
const float SHIFT_LEFT2 = 4.0;
const float SHIFT_LEFT1 = 2.0;
const float SHIFT_RIGHT12 = 1.0 / 4096.0;
const float SHIFT_RIGHT8 = 1.0 / 256.0;
const float SHIFT_RIGHT7 = 1.0 / 128.0;
const float SHIFT_RIGHT5 = 1.0 / 32.0;
const float SHIFT_RIGHT3 = 1.0 / 8.0;
const float SHIFT_RIGHT2 = 1.0 / 4.0;
const float SHIFT_RIGHT1 = 1.0 / 2.0;
vec4 addScreenSpaceOffset(vec4 positionEC, vec2 imageSize, float scale, vec2 direction, vec2 origin, vec2 translate, vec2 pixelOffset, vec3 alignedAxis, bool validAlignedAxis, float rotation, bool sizeInMeters, out mat2 rotationMatrix, out float mpp)
{
// Note the halfSize cannot be computed in JavaScript because it is sent via
// compressed vertex attributes that coerce it to an integer.
vec2 halfSize = imageSize * scale * 0.5;
halfSize *= ((direction * 2.0) - 1.0);
vec2 originTranslate = origin * abs(halfSize);
#if defined(ROTATION) || defined(ALIGNED_AXIS)
if (validAlignedAxis || rotation != 0.0)
{
float angle = rotation;
if (validAlignedAxis)
{
vec4 projectedAlignedAxis = czm_modelView3D * vec4(alignedAxis, 0.0);
angle += sign(-projectedAlignedAxis.x) * acos(sign(projectedAlignedAxis.y) * (projectedAlignedAxis.y * projectedAlignedAxis.y) /
(projectedAlignedAxis.x * projectedAlignedAxis.x + projectedAlignedAxis.y * projectedAlignedAxis.y));
}
float cosTheta = cos(angle);
float sinTheta = sin(angle);
rotationMatrix = mat2(cosTheta, sinTheta, -sinTheta, cosTheta);
halfSize = rotationMatrix * halfSize;
}
else
{
rotationMatrix = mat2(1.0, 0.0, 0.0, 1.0);
}
#endif
mpp = czm_metersPerPixel(positionEC);
positionEC.xy += (originTranslate + halfSize) * czm_branchFreeTernary(sizeInMeters, 1.0, mpp);
positionEC.xy += (translate + pixelOffset) * mpp;
return positionEC;
}
#ifdef VERTEX_DEPTH_CHECK
float getGlobeDepth(vec4 positionEC)
{
vec4 posWC = czm_eyeToWindowCoordinates(positionEC);
float globeDepth = czm_unpackDepth(texture(czm_globeDepthTexture, posWC.xy / czm_viewport.zw));
if (globeDepth == 0.0)
{
return 0.0; // not on the globe
}
vec4 eyeCoordinate = czm_windowToEyeCoordinates(posWC.xy, globeDepth);
return eyeCoordinate.z / eyeCoordinate.w;
}
#endif
void main()
{
// Modifying this shader may also require modifications to Billboard._computeScreenSpacePosition
// unpack attributes
vec3 positionHigh = positionHighAndScale.xyz;
vec3 positionLow = positionLowAndRotation.xyz;
float scale = positionHighAndScale.w;
#if defined(ROTATION) || defined(ALIGNED_AXIS)
float rotation = positionLowAndRotation.w;
#else
float rotation = 0.0;
#endif
float compressed = compressedAttribute0.x;
vec2 pixelOffset;
pixelOffset.x = floor(compressed * SHIFT_RIGHT7);
compressed -= pixelOffset.x * SHIFT_LEFT7;
pixelOffset.x -= UPPER_BOUND;
vec2 origin;
origin.x = floor(compressed * SHIFT_RIGHT5);
compressed -= origin.x * SHIFT_LEFT5;
origin.y = floor(compressed * SHIFT_RIGHT3);
compressed -= origin.y * SHIFT_LEFT3;
#ifdef FRAGMENT_DEPTH_CHECK
vec2 depthOrigin = origin.xy;
#endif
origin -= vec2(1.0);
float show = floor(compressed * SHIFT_RIGHT2);
compressed -= show * SHIFT_LEFT2;
#ifdef INSTANCED
vec2 textureCoordinatesBottomLeft = czm_decompressTextureCoordinates(compressedAttribute0.w);
vec2 textureCoordinatesRange = czm_decompressTextureCoordinates(eyeOffset.w);
vec2 textureCoordinates = textureCoordinatesBottomLeft + direction * textureCoordinatesRange;
#else
vec2 direction;
direction.x = floor(compressed * SHIFT_RIGHT1);
direction.y = compressed - direction.x * SHIFT_LEFT1;
vec2 textureCoordinates = czm_decompressTextureCoordinates(compressedAttribute0.w);
#endif
float temp = compressedAttribute0.y * SHIFT_RIGHT8;
pixelOffset.y = -(floor(temp) - UPPER_BOUND);
vec2 translate;
translate.y = (temp - floor(temp)) * SHIFT_LEFT16;
temp = compressedAttribute0.z * SHIFT_RIGHT8;
translate.x = floor(temp) - UPPER_BOUND;
translate.y += (temp - floor(temp)) * SHIFT_LEFT8;
translate.y -= UPPER_BOUND;
temp = compressedAttribute1.x * SHIFT_RIGHT8;
float temp2 = floor(compressedAttribute2.w * SHIFT_RIGHT2);
vec2 imageSize = vec2(floor(temp), temp2);
#ifdef FRAGMENT_DEPTH_CHECK
float labelHorizontalOrigin = floor(compressedAttribute2.w - (temp2 * SHIFT_LEFT2));
float applyTranslate = 0.0;
if (labelHorizontalOrigin != 0.0) // is a billboard, so set apply translate to false
{
applyTranslate = 1.0;
labelHorizontalOrigin -= 2.0;
depthOrigin.x = labelHorizontalOrigin + 1.0;
}
depthOrigin = vec2(1.0) - (depthOrigin * 0.5);
#endif
#ifdef EYE_DISTANCE_TRANSLUCENCY
vec4 translucencyByDistance;
translucencyByDistance.x = compressedAttribute1.z;
translucencyByDistance.z = compressedAttribute1.w;
translucencyByDistance.y = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0;
temp = compressedAttribute1.y * SHIFT_RIGHT8;
translucencyByDistance.w = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0;
#endif
#if defined(VERTEX_DEPTH_CHECK) || defined(FRAGMENT_DEPTH_CHECK)
temp = compressedAttribute3.w;
temp = temp * SHIFT_RIGHT12;
vec2 dimensions;
dimensions.y = (temp - floor(temp)) * SHIFT_LEFT12;
dimensions.x = floor(temp);
#endif
#ifdef ALIGNED_AXIS
vec3 alignedAxis = czm_octDecode(floor(compressedAttribute1.y * SHIFT_RIGHT8));
temp = compressedAttribute2.z * SHIFT_RIGHT5;
bool validAlignedAxis = (temp - floor(temp)) * SHIFT_LEFT1 > 0.0;
#else
vec3 alignedAxis = vec3(0.0);
bool validAlignedAxis = false;
#endif
vec4 pickColor;
vec4 color;
temp = compressedAttribute2.y;
temp = temp * SHIFT_RIGHT8;
pickColor.b = (temp - floor(temp)) * SHIFT_LEFT8;
temp = floor(temp) * SHIFT_RIGHT8;
pickColor.g = (temp - floor(temp)) * SHIFT_LEFT8;
pickColor.r = floor(temp);
temp = compressedAttribute2.x;
temp = temp * SHIFT_RIGHT8;
color.b = (temp - floor(temp)) * SHIFT_LEFT8;
temp = floor(temp) * SHIFT_RIGHT8;
color.g = (temp - floor(temp)) * SHIFT_LEFT8;
color.r = floor(temp);
temp = compressedAttribute2.z * SHIFT_RIGHT8;
bool sizeInMeters = floor((temp - floor(temp)) * SHIFT_LEFT7) > 0.0;
temp = floor(temp) * SHIFT_RIGHT8;
pickColor.a = (temp - floor(temp)) * SHIFT_LEFT8;
pickColor /= 255.0;
color.a = floor(temp);
color /= 255.0;
///////////////////////////////////////////////////////////////////////////
vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
vec4 positionEC = czm_modelViewRelativeToEye * p;
#if defined(FRAGMENT_DEPTH_CHECK) || defined(VERTEX_DEPTH_CHECK)
float eyeDepth = positionEC.z;
#endif
positionEC = czm_eyeOffset(positionEC, eyeOffset.xyz);
positionEC.xyz *= show;
///////////////////////////////////////////////////////////////////////////
#if defined(EYE_DISTANCE_SCALING) || defined(EYE_DISTANCE_TRANSLUCENCY) || defined(EYE_DISTANCE_PIXEL_OFFSET) || defined(DISTANCE_DISPLAY_CONDITION) || defined(DISABLE_DEPTH_DISTANCE)
float lengthSq;
if (czm_sceneMode == czm_sceneMode2D)
{
// 2D camera distance is a special case
// treat all billboards as flattened to the z=0.0 plane
lengthSq = czm_eyeHeight2D.y;
}
else
{
lengthSq = dot(positionEC.xyz, positionEC.xyz);
}
#endif
#ifdef EYE_DISTANCE_SCALING
float distanceScale = czm_nearFarScalar(scaleByDistance, lengthSq);
scale *= distanceScale;
translate *= distanceScale;
// push vertex behind near plane for clipping
if (scale == 0.0)
{
positionEC.xyz = vec3(0.0);
}
#endif
float translucency = 1.0;
#ifdef EYE_DISTANCE_TRANSLUCENCY
translucency = czm_nearFarScalar(translucencyByDistance, lengthSq);
// push vertex behind near plane for clipping
if (translucency == 0.0)
{
positionEC.xyz = vec3(0.0);
}
#endif
#ifdef EYE_DISTANCE_PIXEL_OFFSET
float pixelOffsetScale = czm_nearFarScalar(pixelOffsetScaleByDistance, lengthSq);
pixelOffset *= pixelOffsetScale;
#endif
#ifdef DISTANCE_DISPLAY_CONDITION
float nearSq = compressedAttribute3.x;
float farSq = compressedAttribute3.y;
if (lengthSq < nearSq || lengthSq > farSq)
{
positionEC.xyz = vec3(0.0);
}
#endif
mat2 rotationMatrix;
float mpp;
#ifdef DISABLE_DEPTH_DISTANCE
float disableDepthTestDistance = compressedAttribute3.z;
#endif
#ifdef VERTEX_DEPTH_CHECK
if (lengthSq < disableDepthTestDistance) {
float depthsilon = 10.0;
vec2 labelTranslate = textureCoordinateBoundsOrLabelTranslate.xy;
vec4 pEC1 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(0.0), origin, labelTranslate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp);
float globeDepth1 = getGlobeDepth(pEC1);
if (globeDepth1 != 0.0 && pEC1.z + depthsilon < globeDepth1)
{
vec4 pEC2 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(0.0, 1.0), origin, labelTranslate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp);
float globeDepth2 = getGlobeDepth(pEC2);
if (globeDepth2 != 0.0 && pEC2.z + depthsilon < globeDepth2)
{
vec4 pEC3 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(1.0), origin, labelTranslate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp);
float globeDepth3 = getGlobeDepth(pEC3);
if (globeDepth3 != 0.0 && pEC3.z + depthsilon < globeDepth3)
{
positionEC.xyz = vec3(0.0);
}
}
}
}
#endif
positionEC = addScreenSpaceOffset(positionEC, imageSize, scale, direction, origin, translate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp);
gl_Position = czm_projection * positionEC;
v_textureCoordinates = textureCoordinates;
#ifdef LOG_DEPTH
czm_vertexLogDepth();
#endif
#ifdef DISABLE_DEPTH_DISTANCE
if (disableDepthTestDistance == 0.0 && czm_minimumDisableDepthTestDistance != 0.0)
{
disableDepthTestDistance = czm_minimumDisableDepthTestDistance;
}
if (disableDepthTestDistance != 0.0)
{
// Don't try to "multiply both sides" by w. Greater/less-than comparisons won't work for negative values of w.
float zclip = gl_Position.z / gl_Position.w;
bool clipped = (zclip < -1.0 || zclip > 1.0);
if (!clipped && (disableDepthTestDistance < 0.0 || (lengthSq > 0.0 && lengthSq < disableDepthTestDistance)))
{
// Position z on the near plane.
gl_Position.z = -gl_Position.w;
#ifdef LOG_DEPTH
v_depthFromNearPlusOne = 1.0;
#endif
}
}
#endif
#ifdef FRAGMENT_DEPTH_CHECK
if (sizeInMeters) {
translate /= mpp;
dimensions /= mpp;
imageSize /= mpp;
}
#if defined(ROTATION) || defined(ALIGNED_AXIS)
v_rotationMatrix = rotationMatrix;
#else
v_rotationMatrix = mat2(1.0, 0.0, 0.0, 1.0);
#endif
float enableDepthCheck = 0.0;
if (lengthSq < disableDepthTestDistance)
{
enableDepthCheck = 1.0;
}
float dw = floor(clamp(dimensions.x, 0.0, SHIFT_LEFT12));
float dh = floor(clamp(dimensions.y, 0.0, SHIFT_LEFT12));
float iw = floor(clamp(imageSize.x, 0.0, SHIFT_LEFT12));
float ih = floor(clamp(imageSize.y, 0.0, SHIFT_LEFT12));
v_compressed.x = eyeDepth;
v_compressed.y = applyTranslate * SHIFT_LEFT1 + enableDepthCheck;
v_compressed.z = dw * SHIFT_LEFT12 + dh;
v_compressed.w = iw * SHIFT_LEFT12 + ih;
v_originTextureCoordinateAndTranslate.xy = depthOrigin;
v_originTextureCoordinateAndTranslate.zw = translate;
v_textureCoordinateBounds = textureCoordinateBoundsOrLabelTranslate;
#endif
#ifdef SDF
vec4 outlineColor;
float outlineWidth;
temp = sdf.x;
temp = temp * SHIFT_RIGHT8;
outlineColor.b = (temp - floor(temp)) * SHIFT_LEFT8;
temp = floor(temp) * SHIFT_RIGHT8;
outlineColor.g = (temp - floor(temp)) * SHIFT_LEFT8;
outlineColor.r = floor(temp);
temp = sdf.y;
temp = temp * SHIFT_RIGHT8;
float temp3 = (temp - floor(temp)) * SHIFT_LEFT8;
temp = floor(temp) * SHIFT_RIGHT8;
outlineWidth = (temp - floor(temp)) * SHIFT_LEFT8;
outlineColor.a = floor(temp);
outlineColor /= 255.0;
v_outlineWidth = outlineWidth / 255.0;
v_outlineColor = outlineColor;
v_outlineColor.a *= translucency;
#endif
v_pickColor = pickColor;
v_color = color;
v_color.a *= translucency;
v_splitDirection = splitDirection;
}
`;
// packages/engine/Source/Scene/Billboard.js
var import_InlineWorkers743 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/BillboardTexture.js
var import_InlineWorkers742 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/BillboardLoadState.js
var import_InlineWorkers741 = __toESM(require_InlineWorkers(), 1);
var BillboardLoadState = Object.freeze({
/**
* There is no image data to load.
* @private
* @type {number}
* @constant
*/
NONE: 0,
/**
* Image data is in the process of downloading, or WebGL resources are being updated.
* @private
* @type {number}
* @constant
*/
LOADING: 2,
/**
* The image data has been downloaded and the WebGL resources have been created. It is ready for rendering.
* @private
* @type {number}
* @constant
*/
LOADED: 3,
/**
* There was an error while downloading an image or updating the WebGL resources.
* @private
* @type {number}
* @constant
*/
ERROR: 4,
/**
* Updating the WebGL resources failed, due to the resource being destroyed or another error.
* @private
* @type {number}
* @constant
*/
FAILED: 5
});
var BillboardLoadState_default = BillboardLoadState;
// packages/engine/Source/Scene/BillboardTexture.js
function BillboardTexture(billboardCollection) {
Check_default.defined("billboardCollection", billboardCollection);
this._billboardCollection = billboardCollection;
this._id = void 0;
this._loadState = BillboardLoadState_default.NONE;
this._loadError = void 0;
this._index = -1;
this._width = void 0;
this._height = void 0;
this._hasSubregion = false;
this.dirty = false;
}
Object.defineProperties(BillboardTexture.prototype, {
/**
* If defined, this error was encountered during the loading process.
* @memberof BillboardTexture.prototype
* @type {Error|undefined}
* @readonly
* @private
*/
loadError: {
get: function() {
return this._loadError;
}
},
/**
* The current status of the image load. When BillboardLoadState.LOADED, this billboard is ready to render, i.e., the image
* has been downloaded and the WebGL resources are created.
* @memberof BillboardTexture.prototype
* @type {BillboardLoadState}
* @readonly
* @default BillboardLoadState.NONE
* @private
*/
loadState: {
get: function() {
return this._loadState;
}
},
/**
* When true, this texture is ready to render, i.e., the image
* has been downloaded and the WebGL resources are created.
* @memberof BillboardTexture.prototype
* @type {boolean}
* @readonly
* @default false
* @private
*/
ready: {
get: function() {
return this._loadState === BillboardLoadState_default.LOADED;
}
},
/**
* Returns true if there is image data associated with this instance.
* @memberof BillboardTexture.prototype
* @type {boolean}
* @readonly
* @private
*/
hasImage: {
get: function() {
return this._loadState !== BillboardLoadState_default.NONE;
}
},
/**
* A unique identifier for the image, or undefined if no image data has been associated with this instance.
* @memberof BillboardTexture.prototype
* @type {string|undefined}
* @readonly
* @private
*/
id: {
get: function() {
return this._id;
}
},
/**
* The width of the associated image. Before the instance is ready, this will be undefined.
* @memberof BillboardTexture.prototype
* @type {number|undefined}
* @readonly
* @private
*/
width: {
get: function() {
return this._width;
}
},
/**
* The height of the associated image. Before the instance is ready, this will be undefined.
* @memberof BillboardTexture.prototype
* @type {number|undefined}
* @readonly
* @private
*/
height: {
get: function() {
return this._height;
}
}
});
BillboardTexture.prototype.unload = async function() {
if (this._loadState === BillboardLoadState_default.NONE) {
return;
}
this._id = void 0;
this._loadError = void 0;
this._loadState = BillboardLoadState_default.NONE;
this._index = -1;
this._width = void 0;
this._height = void 0;
this.dirty = true;
};
BillboardTexture.prototype.loadImage = async function(id, image) {
if (this._id === id) {
return;
}
const collection = this._billboardCollection;
const cache = collection.billboardTextureCache;
let billboardTexture = cache.get(id);
if (defined_default(billboardTexture) && image.loadState === BillboardLoadState_default.LOADING || image.loadState === BillboardLoadState_default.LOADED) {
BillboardTexture.clone(billboardTexture, this);
return;
}
if (!defined_default(billboardTexture)) {
billboardTexture = new BillboardTexture(collection);
cache.set(id, billboardTexture);
}
billboardTexture._id = this._id = id;
billboardTexture._loadState = this._loadState = BillboardLoadState_default.LOADING;
billboardTexture._loadError = this._loadError = void 0;
let index;
const atlas = this._billboardCollection.textureAtlas;
try {
index = await atlas.addImage(id, image);
} catch (error) {
billboardTexture._loadState = BillboardLoadState_default.ERROR;
billboardTexture._loadError = error;
if (this._id !== id) {
return;
}
this._loadState = BillboardLoadState_default.ERROR;
this._loadError = error;
return;
}
if (!defined_default(index) || index === -1) {
billboardTexture._loadState = BillboardLoadState_default.FAILED;
billboardTexture._index = -1;
if (this._id !== id) {
return;
}
this._loadState = BillboardLoadState_default.FAILED;
this._index = -1;
return;
}
billboardTexture._index = index;
billboardTexture._loadState = BillboardLoadState_default.LOADED;
const rectangle = atlas.rectangles[index];
billboardTexture._width = rectangle.width;
billboardTexture._height = rectangle.height;
if (this._id !== id) {
return;
}
this._index = index;
this._loadState = BillboardLoadState_default.LOADED;
this._width = rectangle.width;
this._height = rectangle.height;
this.dirty = true;
};
BillboardTexture.prototype.addImageSubRegion = async function(id, subRegion) {
this._id = id;
this._loadState = BillboardLoadState_default.LOADING;
this._loadError = void 0;
this._hasSubregion = true;
let index;
const atlas = this._billboardCollection.textureAtlas;
try {
index = await atlas.addImageSubRegion(id, subRegion);
} catch (error) {
this._loadState = BillboardLoadState_default.ERROR;
this._loadError = error;
return;
}
if (!defined_default(index) || index === -1) {
this._loadState = BillboardLoadState_default.FAILED;
this._index = -1;
this._width = void 0;
this._height = void 0;
return;
}
this._width = subRegion.width;
this._height = subRegion.height;
this._index = index;
this._loadState = BillboardLoadState_default.LOADED;
this.dirty = true;
};
BillboardTexture.prototype.computeTextureCoordinates = function(result) {
const atlas = this._billboardCollection.textureAtlas;
return atlas.computeTextureCoordinates(this._index, result);
};
BillboardTexture.clone = function(billboardTexture, target) {
target._id = billboardTexture._id;
target._loadState = billboardTexture._loadState;
target._loadError = void 0;
target._index = billboardTexture._index;
target._width = billboardTexture._width;
target._height = billboardTexture._height;
target._hasSubregion = billboardTexture._hasSubregion;
if (billboardTexture.ready) {
target.dirty = true;
return;
}
const completeLoad = async () => {
const id = billboardTexture._id;
const atlas = billboardTexture._billboardCollection.textureAtlas;
await atlas._indexPromiseById.get(id);
if (target._id !== id) {
return;
}
if (billboardTexture._hasSubregion) {
await Promise.resolve();
}
target._id = id;
target._loadState = billboardTexture._loadState;
target._loadError = billboardTexture._loadError;
target._index = billboardTexture._index;
target._width = billboardTexture._width;
target._height = billboardTexture._height;
target.dirty = true;
};
completeLoad();
return target;
};
var BillboardTexture_default = BillboardTexture;
// packages/engine/Source/Scene/Billboard.js
function Billboard(options, billboardCollection) {
options = options ?? Frozen_default.EMPTY_OBJECT;
if (defined_default(options.disableDepthTestDistance) && options.disableDepthTestDistance < 0) {
throw new DeveloperError_default(
"disableDepthTestDistance must be greater than or equal to 0.0."
);
}
let translucencyByDistance = options.translucencyByDistance;
let pixelOffsetScaleByDistance = options.pixelOffsetScaleByDistance;
let scaleByDistance = options.scaleByDistance;
let distanceDisplayCondition = options.distanceDisplayCondition;
if (defined_default(translucencyByDistance)) {
if (translucencyByDistance.far <= translucencyByDistance.near) {
throw new DeveloperError_default(
"translucencyByDistance.far must be greater than translucencyByDistance.near."
);
}
translucencyByDistance = NearFarScalar_default.clone(translucencyByDistance);
}
if (defined_default(pixelOffsetScaleByDistance)) {
if (pixelOffsetScaleByDistance.far <= pixelOffsetScaleByDistance.near) {
throw new DeveloperError_default(
"pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near."
);
}
pixelOffsetScaleByDistance = NearFarScalar_default.clone(
pixelOffsetScaleByDistance
);
}
if (defined_default(scaleByDistance)) {
if (scaleByDistance.far <= scaleByDistance.near) {
throw new DeveloperError_default(
"scaleByDistance.far must be greater than scaleByDistance.near."
);
}
scaleByDistance = NearFarScalar_default.clone(scaleByDistance);
}
if (defined_default(distanceDisplayCondition)) {
if (distanceDisplayCondition.far <= distanceDisplayCondition.near) {
throw new DeveloperError_default(
"distanceDisplayCondition.far must be greater than distanceDisplayCondition.near."
);
}
distanceDisplayCondition = DistanceDisplayCondition_default.clone(
distanceDisplayCondition
);
}
this._show = options.show ?? true;
this._position = Cartesian3_default.clone(options.position ?? Cartesian3_default.ZERO);
this._actualPosition = Cartesian3_default.clone(this._position);
this._pixelOffset = Cartesian2_default.clone(options.pixelOffset ?? Cartesian2_default.ZERO);
this._translate = new Cartesian2_default(0, 0);
this._eyeOffset = Cartesian3_default.clone(options.eyeOffset ?? Cartesian3_default.ZERO);
this._heightReference = options.heightReference ?? HeightReference_default.NONE;
this._verticalOrigin = options.verticalOrigin ?? VerticalOrigin_default.CENTER;
this._horizontalOrigin = options.horizontalOrigin ?? HorizontalOrigin_default.CENTER;
this._scale = options.scale ?? 1;
this._color = Color_default.clone(options.color ?? Color_default.WHITE);
this._rotation = options.rotation ?? 0;
this._alignedAxis = Cartesian3_default.clone(options.alignedAxis ?? Cartesian3_default.ZERO);
this._width = options.width;
this._height = options.height;
this._scaleByDistance = scaleByDistance;
this._translucencyByDistance = translucencyByDistance;
this._pixelOffsetScaleByDistance = pixelOffsetScaleByDistance;
this._sizeInMeters = options.sizeInMeters ?? false;
this._distanceDisplayCondition = distanceDisplayCondition;
this._disableDepthTestDistance = options.disableDepthTestDistance;
this._id = options.id;
this._collection = options.collection ?? billboardCollection;
this._pickId = void 0;
this._pickPrimitive = options._pickPrimitive ?? this;
this._billboardCollection = billboardCollection;
this._dirty = false;
this._index = -1;
this._batchIndex = void 0;
this._imageTexture = new BillboardTexture_default(billboardCollection);
this._imageWidth = void 0;
this._imageHeight = void 0;
this._labelDimensions = void 0;
this._labelHorizontalOrigin = void 0;
this._labelTranslate = void 0;
const image = options.image;
let imageId = options.imageId;
if (defined_default(image)) {
if (!defined_default(imageId)) {
if (typeof image === "string") {
imageId = image;
} else if (defined_default(image.src)) {
imageId = image.src;
} else {
imageId = createGuid_default();
}
}
this._imageTexture.loadImage(imageId, image);
}
if (defined_default(options.imageSubRegion)) {
this._imageTexture.addImageSubRegion(imageId, options.imageSubRegion);
}
this._actualClampedPosition = void 0;
this._removeCallbackFunc = void 0;
this._mode = SceneMode_default.SCENE3D;
this._clusterShow = true;
this._outlineColor = Color_default.clone(options.outlineColor ?? Color_default.BLACK);
this._outlineWidth = options.outlineWidth ?? 0;
this._updateClamping();
this._splitDirection = options.splitDirection ?? SplitDirection_default.NONE;
}
var SHOW_INDEX = Billboard.SHOW_INDEX = 0;
var POSITION_INDEX = Billboard.POSITION_INDEX = 1;
var PIXEL_OFFSET_INDEX = Billboard.PIXEL_OFFSET_INDEX = 2;
var EYE_OFFSET_INDEX = Billboard.EYE_OFFSET_INDEX = 3;
var HORIZONTAL_ORIGIN_INDEX = Billboard.HORIZONTAL_ORIGIN_INDEX = 4;
var VERTICAL_ORIGIN_INDEX = Billboard.VERTICAL_ORIGIN_INDEX = 5;
var SCALE_INDEX = Billboard.SCALE_INDEX = 6;
var IMAGE_INDEX_INDEX = Billboard.IMAGE_INDEX_INDEX = 7;
var COLOR_INDEX = Billboard.COLOR_INDEX = 8;
var ROTATION_INDEX = Billboard.ROTATION_INDEX = 9;
var ALIGNED_AXIS_INDEX = Billboard.ALIGNED_AXIS_INDEX = 10;
var SCALE_BY_DISTANCE_INDEX = Billboard.SCALE_BY_DISTANCE_INDEX = 11;
var TRANSLUCENCY_BY_DISTANCE_INDEX = Billboard.TRANSLUCENCY_BY_DISTANCE_INDEX = 12;
var PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = Billboard.PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = 13;
var DISTANCE_DISPLAY_CONDITION = Billboard.DISTANCE_DISPLAY_CONDITION = 14;
var DISABLE_DEPTH_DISTANCE = Billboard.DISABLE_DEPTH_DISTANCE = 15;
Billboard.TEXTURE_COORDINATE_BOUNDS = 16;
var SDF_INDEX = Billboard.SDF_INDEX = 17;
var SPLIT_DIRECTION_INDEX = Billboard.SPLIT_DIRECTION_INDEX = 18;
Billboard.NUMBER_OF_PROPERTIES = 19;
function makeDirty(billboard, propertyChanged) {
const billboardCollection = billboard._billboardCollection;
if (defined_default(billboardCollection)) {
billboardCollection._updateBillboard(billboard, propertyChanged);
billboard._dirty = true;
}
}
Object.defineProperties(Billboard.prototype, {
/**
* Determines if this billboard will be shown. Use this to hide or show a billboard, instead
* of removing it and re-adding it to the collection.
* @memberof Billboard.prototype
* @type {boolean}
* @default true
*/
show: {
get: function() {
return this._show;
},
set: function(value) {
Check_default.typeOf.bool("value", value);
if (this._show !== value) {
this._show = value;
makeDirty(this, SHOW_INDEX);
}
}
},
/**
* Gets or sets the Cartesian position of this billboard.
* @memberof Billboard.prototype
* @type {Cartesian3}
*/
position: {
get: function() {
return this._position;
},
set: function(value) {
Check_default.typeOf.object("value", value);
const position = this._position;
if (!Cartesian3_default.equals(position, value)) {
Cartesian3_default.clone(value, position);
Cartesian3_default.clone(value, this._actualPosition);
this._updateClamping();
makeDirty(this, POSITION_INDEX);
}
}
},
/**
* Gets or sets the height reference of this billboard.
* @memberof Billboard.prototype
* @type {HeightReference}
* @default HeightReference.NONE
*/
heightReference: {
get: function() {
return this._heightReference;
},
set: function(value) {
Check_default.typeOf.number("value", value);
const heightReference = this._heightReference;
if (value !== heightReference) {
this._heightReference = value;
this._updateClamping();
makeDirty(this, POSITION_INDEX);
}
}
},
/**
* Gets or sets the pixel offset in screen space from the origin of this billboard. This is commonly used
* to align multiple billboards and labels at the same position, e.g., an image and text. The
* screen space origin is the top, left corner of the canvas; x increases from
* left to right, and y increases from top to bottom.
*
*
*
* default

* b.pixeloffset = new Cartesian2(50, 25);

*
* The billboard's origin is indicated by the yellow point.
*
* @memberof Billboard.prototype
* @type {Cartesian2}
*/
pixelOffset: {
get: function() {
return this._pixelOffset;
},
set: function(value) {
Check_default.typeOf.object("value", value);
const pixelOffset = this._pixelOffset;
if (!Cartesian2_default.equals(pixelOffset, value)) {
Cartesian2_default.clone(value, pixelOffset);
makeDirty(this, PIXEL_OFFSET_INDEX);
}
}
},
/**
* Gets or sets near and far scaling properties of a Billboard based on the billboard's distance from the camera.
* A billboard's scale will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the billboard's scale remains clamped to the nearest bound. If undefined,
* scaleByDistance will be disabled.
* @memberof Billboard.prototype
* @type {NearFarScalar}
*
* @example
* // Example 1.
* // Set a billboard's scaleByDistance to scale by 1.5 when the
* // camera is 1500 meters from the billboard and disappear as
* // the camera distance approaches 8.0e6 meters.
* b.scaleByDistance = new Cesium.NearFarScalar(1.5e2, 1.5, 8.0e6, 0.0);
*
* @example
* // Example 2.
* // disable scaling by distance
* b.scaleByDistance = undefined;
*/
scaleByDistance: {
get: function() {
return this._scaleByDistance;
},
set: function(value) {
if (defined_default(value)) {
Check_default.typeOf.object("value", value);
if (value.far <= value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
}
const scaleByDistance = this._scaleByDistance;
if (!NearFarScalar_default.equals(scaleByDistance, value)) {
this._scaleByDistance = NearFarScalar_default.clone(value, scaleByDistance);
makeDirty(this, SCALE_BY_DISTANCE_INDEX);
}
}
},
/**
* Gets or sets near and far translucency properties of a Billboard based on the billboard's distance from the camera.
* A billboard's translucency will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the billboard's translucency remains clamped to the nearest bound. If undefined,
* translucencyByDistance will be disabled.
* @memberof Billboard.prototype
* @type {NearFarScalar}
*
* @example
* // Example 1.
* // Set a billboard's translucency to 1.0 when the
* // camera is 1500 meters from the billboard and disappear as
* // the camera distance approaches 8.0e6 meters.
* b.translucencyByDistance = new Cesium.NearFarScalar(1.5e2, 1.0, 8.0e6, 0.0);
*
* @example
* // Example 2.
* // disable translucency by distance
* b.translucencyByDistance = undefined;
*/
translucencyByDistance: {
get: function() {
return this._translucencyByDistance;
},
set: function(value) {
if (defined_default(value)) {
Check_default.typeOf.object("value", value);
if (value.far <= value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
}
const translucencyByDistance = this._translucencyByDistance;
if (!NearFarScalar_default.equals(translucencyByDistance, value)) {
this._translucencyByDistance = NearFarScalar_default.clone(
value,
translucencyByDistance
);
makeDirty(this, TRANSLUCENCY_BY_DISTANCE_INDEX);
}
}
},
/**
* Gets or sets near and far pixel offset scaling properties of a Billboard based on the billboard's distance from the camera.
* A billboard's pixel offset will be scaled between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the billboard's pixel offset scale remains clamped to the nearest bound. If undefined,
* pixelOffsetScaleByDistance will be disabled.
* @memberof Billboard.prototype
* @type {NearFarScalar}
*
* @example
* // Example 1.
* // Set a billboard's pixel offset scale to 0.0 when the
* // camera is 1500 meters from the billboard and scale pixel offset to 10.0 pixels
* // in the y direction the camera distance approaches 8.0e6 meters.
* b.pixelOffset = new Cesium.Cartesian2(0.0, 1.0);
* b.pixelOffsetScaleByDistance = new Cesium.NearFarScalar(1.5e2, 0.0, 8.0e6, 10.0);
*
* @example
* // Example 2.
* // disable pixel offset by distance
* b.pixelOffsetScaleByDistance = undefined;
*/
pixelOffsetScaleByDistance: {
get: function() {
return this._pixelOffsetScaleByDistance;
},
set: function(value) {
if (defined_default(value)) {
Check_default.typeOf.object("value", value);
if (value.far <= value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
}
const pixelOffsetScaleByDistance = this._pixelOffsetScaleByDistance;
if (!NearFarScalar_default.equals(pixelOffsetScaleByDistance, value)) {
this._pixelOffsetScaleByDistance = NearFarScalar_default.clone(
value,
pixelOffsetScaleByDistance
);
makeDirty(this, PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX);
}
}
},
/**
* Gets or sets the 3D Cartesian offset applied to this billboard in eye coordinates. Eye coordinates is a left-handed
* coordinate system, where x points towards the viewer's right, y points up, and
* z points into the screen. Eye coordinates use the same scale as world and model coordinates,
* which is typically meters.
*
* An eye offset is commonly used to arrange multiple billboards or objects at the same position, e.g., to
* arrange a billboard above its corresponding 3D model.
*
* Below, the billboard is positioned at the center of the Earth but an eye offset makes it always
* appear on top of the Earth regardless of the viewer's or Earth's orientation.
*
*
*
* 
* 
*
* b.eyeOffset = new Cartesian3(0.0, 8000000.0, 0.0);
*
* @memberof Billboard.prototype
* @type {Cartesian3}
*/
eyeOffset: {
get: function() {
return this._eyeOffset;
},
set: function(value) {
Check_default.typeOf.object("value", value);
const eyeOffset = this._eyeOffset;
if (!Cartesian3_default.equals(eyeOffset, value)) {
Cartesian3_default.clone(value, eyeOffset);
makeDirty(this, EYE_OFFSET_INDEX);
}
}
},
/**
* Gets or sets the horizontal origin of this billboard, which determines if the billboard is
* to the left, center, or right of its anchor position.
*
*
* 
*
* @memberof Billboard.prototype
* @type {HorizontalOrigin}
* @example
* // Use a bottom, left origin
* b.horizontalOrigin = Cesium.HorizontalOrigin.LEFT;
* b.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
*/
horizontalOrigin: {
get: function() {
return this._horizontalOrigin;
},
set: function(value) {
Check_default.typeOf.number("value", value);
if (this._horizontalOrigin !== value) {
this._horizontalOrigin = value;
makeDirty(this, HORIZONTAL_ORIGIN_INDEX);
}
}
},
/**
* Gets or sets the vertical origin of this billboard, which determines if the billboard is
* to the above, below, or at the center of its anchor position.
*
*
* 
*
* @memberof Billboard.prototype
* @type {VerticalOrigin}
* @example
* // Use a bottom, left origin
* b.horizontalOrigin = Cesium.HorizontalOrigin.LEFT;
* b.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
*/
verticalOrigin: {
get: function() {
return this._verticalOrigin;
},
set: function(value) {
Check_default.typeOf.number("value", value);
if (this._verticalOrigin !== value) {
this._verticalOrigin = value;
makeDirty(this, VERTICAL_ORIGIN_INDEX);
}
}
},
/**
* Gets or sets the uniform scale that is multiplied with the billboard's image size in pixels.
* A scale of 1.0 does not change the size of the billboard; a scale greater than
* 1.0 enlarges the billboard; a positive scale less than 1.0 shrinks
* the billboard.
*
*
* 
* From left to right in the above image, the scales are 0.5, 1.0,
* and 2.0.
*
* @memberof Billboard.prototype
* @type {number}
*/
scale: {
get: function() {
return this._scale;
},
set: function(value) {
Check_default.typeOf.number("value", value);
if (this._scale !== value) {
this._scale = value;
makeDirty(this, SCALE_INDEX);
}
}
},
/**
* Gets or sets the color that is multiplied with the billboard's texture. This has two common use cases. First,
* the same white texture may be used by many different billboards, each with a different color, to create
* colored billboards. Second, the color's alpha component can be used to make the billboard translucent as shown below.
* An alpha of 0.0 makes the billboard transparent, and 1.0 makes the billboard opaque.
*
*
*
* default

* alpha : 0.5

*
*
*
* The red, green, blue, and alpha values are indicated by value's red, green,
* blue, and alpha properties as shown in Example 1. These components range from 0.0
* (no intensity) to 1.0 (full intensity).
* @memberof Billboard.prototype
* @type {Color}
*
* @example
* // Example 1. Assign yellow.
* b.color = Cesium.Color.YELLOW;
*
* @example
* // Example 2. Make a billboard 50% translucent.
* b.color = new Cesium.Color(1.0, 1.0, 1.0, 0.5);
*/
color: {
get: function() {
return this._color;
},
set: function(value) {
Check_default.typeOf.object("value", value);
const color = this._color;
if (!Color_default.equals(color, value)) {
Color_default.clone(value, color);
makeDirty(this, COLOR_INDEX);
}
}
},
/**
* Gets or sets the rotation angle in radians.
* @memberof Billboard.prototype
* @type {number}
*/
rotation: {
get: function() {
return this._rotation;
},
set: function(value) {
Check_default.typeOf.number("value", value);
if (this._rotation !== value) {
this._rotation = value;
makeDirty(this, ROTATION_INDEX);
}
}
},
/**
* Gets or sets the aligned axis in world space. The aligned axis is the unit vector that the billboard up vector points towards.
* The default is the zero vector, which means the billboard is aligned to the screen up vector.
* @memberof Billboard.prototype
* @type {Cartesian3}
* @example
* // Example 1.
* // Have the billboard up vector point north
* billboard.alignedAxis = Cesium.Cartesian3.UNIT_Z;
*
* @example
* // Example 2.
* // Have the billboard point east.
* billboard.alignedAxis = Cesium.Cartesian3.UNIT_Z;
* billboard.rotation = -Cesium.Math.PI_OVER_TWO;
*
* @example
* // Example 3.
* // Reset the aligned axis
* billboard.alignedAxis = Cesium.Cartesian3.ZERO;
*/
alignedAxis: {
get: function() {
return this._alignedAxis;
},
set: function(value) {
Check_default.typeOf.object("value", value);
const alignedAxis = this._alignedAxis;
if (!Cartesian3_default.equals(alignedAxis, value)) {
Cartesian3_default.clone(value, alignedAxis);
makeDirty(this, ALIGNED_AXIS_INDEX);
}
}
},
/**
* Gets or sets a width for the billboard. If undefined, the image width will be used.
* @memberof Billboard.prototype
* @type {number|undefined}
*/
width: {
get: function() {
return this._width ?? this._imageTexture.width;
},
set: function(value) {
if (defined_default(value)) {
Check_default.typeOf.number("width", value);
}
if (this._width !== value) {
this._width = value;
makeDirty(this, IMAGE_INDEX_INDEX);
}
}
},
/**
* Gets or sets a height for the billboard. If undefined, the image height will be used.
* @memberof Billboard.prototype
* @type {number|undefined}
*/
height: {
get: function() {
return this._height ?? this._imageTexture.height;
},
set: function(value) {
if (defined_default(value)) {
Check_default.typeOf.number("height", value);
}
if (this._height !== value) {
this._height = value;
makeDirty(this, IMAGE_INDEX_INDEX);
}
}
},
/**
* Gets or sets if the billboard size is in meters or pixels. true to size the billboard in meters;
* otherwise, the size is in pixels.
* @memberof Billboard.prototype
* @type {boolean}
* @default false
*/
sizeInMeters: {
get: function() {
return this._sizeInMeters;
},
set: function(value) {
Check_default.typeOf.bool("value", value);
if (this._sizeInMeters !== value) {
this._sizeInMeters = value;
makeDirty(this, COLOR_INDEX);
}
}
},
/**
* Gets or sets the condition specifying at what distance from the camera that this billboard will be displayed.
* @memberof Billboard.prototype
* @type {DistanceDisplayCondition}
* @default undefined
*/
distanceDisplayCondition: {
get: function() {
return this._distanceDisplayCondition;
},
set: function(value) {
if (!DistanceDisplayCondition_default.equals(value, this._distanceDisplayCondition)) {
if (defined_default(value)) {
Check_default.typeOf.object("value", value);
if (value.far <= value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
}
this._distanceDisplayCondition = DistanceDisplayCondition_default.clone(
value,
this._distanceDisplayCondition
);
makeDirty(this, DISTANCE_DISPLAY_CONDITION);
}
}
},
/**
* Gets or sets the distance from the camera at which to disable the depth test to, for example, prevent clipping against terrain.
* When set to zero, the depth test is always applied. When set to Number.POSITIVE_INFINITY, the depth test is never applied.
* @memberof Billboard.prototype
* @type {number}
*/
disableDepthTestDistance: {
get: function() {
return this._disableDepthTestDistance;
},
set: function(value) {
if (defined_default(value)) {
Check_default.typeOf.number("value", value);
if (value < 0) {
throw new DeveloperError_default(
"disableDepthTestDistance must be greater than or equal to 0.0."
);
}
}
if (this._disableDepthTestDistance !== value) {
this._disableDepthTestDistance = value;
makeDirty(this, DISABLE_DEPTH_DISTANCE);
}
}
},
/**
* Gets or sets the user-defined object returned when the billboard is picked.
* @memberof Billboard.prototype
* @type {*}
*/
id: {
get: function() {
return this._id;
},
set: function(value) {
this._id = value;
if (defined_default(this._pickId)) {
this._pickId.object.id = value;
}
}
},
/**
* The primitive to return when picking this billboard.
* @memberof Billboard.prototype
* @private
*/
pickPrimitive: {
get: function() {
return this._pickPrimitive;
},
set: function(value) {
this._pickPrimitive = value;
if (defined_default(this._pickId)) {
this._pickId.object.primitive = value;
}
}
},
/**
* @private
*/
pickId: {
get: function() {
return this._pickId;
}
},
/**
*
* Gets or sets the image to be used for this billboard. If a texture has already been created for the
* given image, the existing texture is used.
*
*
* This property can be set to a loaded Image, a URL which will be loaded as an Image automatically,
* a canvas, or another billboard's image property (from the same billboard collection).
*
*
* @memberof Billboard.prototype
* @type {string}
* @example
* // load an image from a URL
* b.image = 'some/image/url.png';
*
* // assuming b1 and b2 are billboards in the same billboard collection,
* // use the same image for both billboards.
* b2.image = b1.image;
*/
image: {
get: function() {
return this._imageTexture.id;
},
set: function(value) {
if (!defined_default(value)) {
this._imageTexture.unload();
return;
}
let id;
if (typeof value === "string") {
id = value;
} else if (value instanceof Resource_default) {
id = value._url;
} else if (defined_default(value.src)) {
id = value.src;
} else {
id = createGuid_default();
}
this._imageTexture.loadImage(id, value);
}
},
/**
* When true, this billboard is ready to render, i.e., the image
* has been downloaded and the WebGL resources are created.
* @memberof Billboard.prototype
* @type {boolean}
* @readonly
* @default false
*/
ready: {
get: function() {
return this._imageTexture.ready;
}
},
/**
* If defined, this error was encountered during the loading process.
* @memberof Billboard.prototype
* @type {Error|undefined}
* @readonly
* @private
*/
loadError: {
get: function() {
return this._imageTexture.loadError;
}
},
/**
* Used by billboardCollection to track which billboards to update based on image load status.
* @memberof Billboard.prototype
* @type {boolean}
* @private
* @default false
*/
textureDirty: {
get: function() {
return this._imageTexture.dirty;
},
set: function(value) {
this._imageTexture.dirty = value;
}
},
/**
* Keeps track of the position of the billboard based on the height reference.
* @memberof Billboard.prototype
* @type {Cartesian3}
* @private
*/
_clampedPosition: {
get: function() {
return this._actualClampedPosition;
},
set: function(value) {
this._actualClampedPosition = Cartesian3_default.clone(
value,
this._actualClampedPosition
);
makeDirty(this, POSITION_INDEX);
}
},
/**
* Determines whether or not this billboard will be shown or hidden because it was clustered.
* @memberof Billboard.prototype
* @type {boolean}
* @private
*/
clusterShow: {
get: function() {
return this._clusterShow;
},
set: function(value) {
if (this._clusterShow !== value) {
this._clusterShow = value;
makeDirty(this, SHOW_INDEX);
}
}
},
/**
* The outline color of this Billboard. Effective only for SDF billboards like Label glyphs.
* @memberof Billboard.prototype
* @type {Color}
* @private
*/
outlineColor: {
get: function() {
return this._outlineColor;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const outlineColor = this._outlineColor;
if (!Color_default.equals(outlineColor, value)) {
Color_default.clone(value, outlineColor);
makeDirty(this, SDF_INDEX);
}
}
},
/**
* The outline width of this Billboard in pixels. Effective only for SDF billboards like Label glyphs.
* @memberof Billboard.prototype
* @type {number}
* @private
*/
outlineWidth: {
get: function() {
return this._outlineWidth;
},
set: function(value) {
if (this._outlineWidth !== value) {
this._outlineWidth = value;
makeDirty(this, SDF_INDEX);
}
}
},
/**
* Gets or sets the {@link SplitDirection} of this billboard.
* @memberof Billboard.prototype
* @type {SplitDirection}
* @default {@link SplitDirection.NONE}
*/
splitDirection: {
get: function() {
return this._splitDirection;
},
set: function(value) {
if (this._splitDirection !== value) {
this._splitDirection = value;
makeDirty(this, SPLIT_DIRECTION_INDEX);
}
}
}
});
Billboard.prototype.getPickId = function(context) {
if (!defined_default(this._pickId)) {
this._pickId = context.createPickId({
primitive: this._pickPrimitive,
collection: this._collection,
id: this._id
});
}
return this._pickId;
};
Billboard.prototype._updateClamping = function() {
Billboard._updateClamping(this._billboardCollection, this);
};
var scratchCartographic6 = new Cartographic_default();
Billboard._updateClamping = function(collection, owner) {
if (!defined_default(collection) || !defined_default(collection._scene)) {
if (owner._heightReference !== HeightReference_default.NONE) {
throw new DeveloperError_default(
"Height reference is not supported without a scene."
);
}
return;
}
const scene = collection._scene;
const ellipsoid = scene.ellipsoid ?? Ellipsoid_default.default;
const mode2 = scene.frameState.mode;
const modeChanged = mode2 !== owner._mode;
owner._mode = mode2;
if ((owner._heightReference === HeightReference_default.NONE || modeChanged) && defined_default(owner._removeCallbackFunc)) {
owner._removeCallbackFunc();
owner._removeCallbackFunc = void 0;
owner._clampedPosition = void 0;
}
if (owner._heightReference === HeightReference_default.NONE || !defined_default(owner._position)) {
return;
}
if (defined_default(owner._removeCallbackFunc)) {
owner._removeCallbackFunc();
}
const position = ellipsoid.cartesianToCartographic(owner._position);
if (!defined_default(position)) {
owner._actualClampedPosition = void 0;
return;
}
function updateFunction(clampedPosition) {
const updatedClampedPosition = ellipsoid.cartographicToCartesian(
clampedPosition,
owner._clampedPosition
);
if (isHeightReferenceRelative(owner._heightReference)) {
if (owner._mode === SceneMode_default.SCENE3D) {
clampedPosition.height += position.height;
ellipsoid.cartographicToCartesian(
clampedPosition,
updatedClampedPosition
);
} else {
updatedClampedPosition.x += position.height;
}
}
owner._clampedPosition = updatedClampedPosition;
}
owner._removeCallbackFunc = scene.updateHeight(
position,
updateFunction,
owner._heightReference
);
Cartographic_default.clone(position, scratchCartographic6);
const height = scene.getHeight(position, owner._heightReference);
if (defined_default(height)) {
scratchCartographic6.height = height;
}
updateFunction(scratchCartographic6);
};
Billboard.prototype.computeTextureCoordinates = function(result) {
return this._imageTexture.computeTextureCoordinates(result);
};
Billboard.prototype.setImage = function(id, image) {
Check_default.typeOf.string("id", id);
Check_default.defined("image", image);
this._imageTexture.loadImage(id, image);
};
Billboard.prototype.setImageTexture = function(billboardTexture) {
Check_default.defined("billboardTexture", billboardTexture);
BillboardTexture_default.clone(billboardTexture, this._imageTexture);
};
Billboard.prototype.setImageSubRegion = function(id, subRegion) {
Check_default.typeOf.string("id", id);
Check_default.defined("subRegion", subRegion);
this._imageTexture.addImageSubRegion(id, subRegion);
};
Billboard.prototype._setTranslate = function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const translate = this._translate;
if (!Cartesian2_default.equals(translate, value)) {
Cartesian2_default.clone(value, translate);
makeDirty(this, PIXEL_OFFSET_INDEX);
}
};
Billboard.prototype._getActualPosition = function() {
return defined_default(this._clampedPosition) ? this._clampedPosition : this._actualPosition;
};
Billboard.prototype._setActualPosition = function(value) {
if (!defined_default(this._clampedPosition)) {
Cartesian3_default.clone(value, this._actualPosition);
}
makeDirty(this, POSITION_INDEX);
};
var tempCartesian3 = new Cartesian4_default();
Billboard._computeActualPosition = function(billboard, position, frameState, modelMatrix) {
if (defined_default(billboard._clampedPosition)) {
if (frameState.mode !== billboard._mode) {
billboard._updateClamping();
}
return billboard._clampedPosition;
} else if (frameState.mode === SceneMode_default.SCENE3D) {
return position;
}
Matrix4_default.multiplyByPoint(modelMatrix, position, tempCartesian3);
return SceneTransforms_default.computeActualEllipsoidPosition(
frameState,
tempCartesian3
);
};
var scratchCartesian36 = new Cartesian3_default();
Billboard._computeScreenSpacePosition = function(modelMatrix, position, eyeOffset, pixelOffset, scene, result) {
const positionWorld = Matrix4_default.multiplyByPoint(
modelMatrix,
position,
scratchCartesian36
);
const positionWC2 = SceneTransforms_default.worldWithEyeOffsetToWindowCoordinates(
scene,
positionWorld,
eyeOffset,
result
);
if (!defined_default(positionWC2)) {
return void 0;
}
Cartesian2_default.add(positionWC2, pixelOffset, positionWC2);
return positionWC2;
};
var scratchPixelOffset = new Cartesian2_default(0, 0);
Billboard.prototype.computeScreenSpacePosition = function(scene, result) {
const billboardCollection = this._billboardCollection;
if (!defined_default(result)) {
result = new Cartesian2_default();
}
if (!defined_default(billboardCollection)) {
throw new DeveloperError_default(
"Billboard must be in a collection. Was it removed?"
);
}
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required.");
}
Cartesian2_default.clone(this._pixelOffset, scratchPixelOffset);
Cartesian2_default.add(scratchPixelOffset, this._translate, scratchPixelOffset);
let modelMatrix = billboardCollection.modelMatrix;
let position = this._position;
if (defined_default(this._clampedPosition)) {
position = this._clampedPosition;
if (scene.mode !== SceneMode_default.SCENE3D) {
const projection = scene.mapProjection;
const ellipsoid = projection.ellipsoid;
const cart = projection.unproject(position, scratchCartographic6);
position = ellipsoid.cartographicToCartesian(cart, scratchCartesian36);
modelMatrix = Matrix4_default.IDENTITY;
}
}
const windowCoordinates = Billboard._computeScreenSpacePosition(
modelMatrix,
position,
this._eyeOffset,
scratchPixelOffset,
scene,
result
);
return windowCoordinates;
};
Billboard.getScreenSpaceBoundingBox = function(billboard, screenSpacePosition, result) {
let width = billboard.width;
let height = billboard.height;
const scale = billboard.scale;
width *= scale;
height *= scale;
let x = screenSpacePosition.x;
if (billboard.horizontalOrigin === HorizontalOrigin_default.RIGHT) {
x -= width;
} else if (billboard.horizontalOrigin === HorizontalOrigin_default.CENTER) {
x -= width * 0.5;
}
let y = screenSpacePosition.y;
if (billboard.verticalOrigin === VerticalOrigin_default.BOTTOM || billboard.verticalOrigin === VerticalOrigin_default.BASELINE) {
y -= height;
} else if (billboard.verticalOrigin === VerticalOrigin_default.CENTER) {
y -= height * 0.5;
}
if (!defined_default(result)) {
result = new BoundingRectangle_default();
}
result.x = x;
result.y = y;
result.width = width;
result.height = height;
return result;
};
Billboard.prototype.equals = function(other) {
return this === other || defined_default(other) && this._id === other._id && Cartesian3_default.equals(this._position, other._position) && this.image === other.image && this._show === other._show && this._scale === other._scale && this._verticalOrigin === other._verticalOrigin && this._horizontalOrigin === other._horizontalOrigin && this._heightReference === other._heightReference && Color_default.equals(this._color, other._color) && Cartesian2_default.equals(this._pixelOffset, other._pixelOffset) && Cartesian2_default.equals(this._translate, other._translate) && Cartesian3_default.equals(this._eyeOffset, other._eyeOffset) && NearFarScalar_default.equals(this._scaleByDistance, other._scaleByDistance) && NearFarScalar_default.equals(
this._translucencyByDistance,
other._translucencyByDistance
) && NearFarScalar_default.equals(
this._pixelOffsetScaleByDistance,
other._pixelOffsetScaleByDistance
) && DistanceDisplayCondition_default.equals(
this._distanceDisplayCondition,
other._distanceDisplayCondition
) && this._disableDepthTestDistance === other._disableDepthTestDistance && this._splitDirection === other._splitDirection;
};
Billboard.prototype._destroy = function() {
if (defined_default(this._customData)) {
this._billboardCollection._scene.globe._surface.removeTileCustomData(
this._customData
);
this._customData = void 0;
}
if (defined_default(this._removeCallbackFunc)) {
this._removeCallbackFunc();
this._removeCallbackFunc = void 0;
}
this.image = void 0;
this._pickId = this._pickId && this._pickId.destroy();
this._billboardCollection = void 0;
};
var Billboard_default = Billboard;
// packages/engine/Source/Scene/BlendOption.js
var import_InlineWorkers744 = __toESM(require_InlineWorkers(), 1);
var BlendOption = {
/**
* The billboards, points, or labels in the collection are completely opaque.
* @type {number}
* @constant
*/
OPAQUE: 0,
/**
* The billboards, points, or labels in the collection are completely translucent.
* @type {number}
* @constant
*/
TRANSLUCENT: 1,
/**
* The billboards, points, or labels in the collection are both opaque and translucent.
* @type {number}
* @constant
*/
OPAQUE_AND_TRANSLUCENT: 2
};
var BlendOption_default = Object.freeze(BlendOption);
// packages/engine/Source/Scene/SDFSettings.js
var import_InlineWorkers745 = __toESM(require_InlineWorkers(), 1);
var SDFSettings = {
/**
* The font size in pixels
*
* @type {number}
* @constant
*/
FONT_SIZE: 48,
/**
* Whitespace padding around glyphs.
*
* @type {number}
* @constant
*/
PADDING: 10,
/**
* How many pixels around the glyph shape to use for encoding distance
*
* @type {number}
* @constant
*/
RADIUS: 8,
/**
* How much of the radius (relative) is used for the inside part the glyph.
*
* @type {number}
* @constant
*/
CUTOFF: 0.25
};
var SDFSettings_default = Object.freeze(SDFSettings);
// packages/engine/Source/Scene/BillboardCollection.js
var SHOW_INDEX2 = Billboard_default.SHOW_INDEX;
var POSITION_INDEX2 = Billboard_default.POSITION_INDEX;
var PIXEL_OFFSET_INDEX2 = Billboard_default.PIXEL_OFFSET_INDEX;
var EYE_OFFSET_INDEX2 = Billboard_default.EYE_OFFSET_INDEX;
var HORIZONTAL_ORIGIN_INDEX2 = Billboard_default.HORIZONTAL_ORIGIN_INDEX;
var VERTICAL_ORIGIN_INDEX2 = Billboard_default.VERTICAL_ORIGIN_INDEX;
var SCALE_INDEX2 = Billboard_default.SCALE_INDEX;
var IMAGE_INDEX_INDEX2 = Billboard_default.IMAGE_INDEX_INDEX;
var COLOR_INDEX2 = Billboard_default.COLOR_INDEX;
var ROTATION_INDEX2 = Billboard_default.ROTATION_INDEX;
var ALIGNED_AXIS_INDEX2 = Billboard_default.ALIGNED_AXIS_INDEX;
var SCALE_BY_DISTANCE_INDEX2 = Billboard_default.SCALE_BY_DISTANCE_INDEX;
var TRANSLUCENCY_BY_DISTANCE_INDEX2 = Billboard_default.TRANSLUCENCY_BY_DISTANCE_INDEX;
var PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX2 = Billboard_default.PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX;
var DISTANCE_DISPLAY_CONDITION_INDEX = Billboard_default.DISTANCE_DISPLAY_CONDITION;
var DISABLE_DEPTH_DISTANCE2 = Billboard_default.DISABLE_DEPTH_DISTANCE;
var TEXTURE_COORDINATE_BOUNDS = Billboard_default.TEXTURE_COORDINATE_BOUNDS;
var SDF_INDEX2 = Billboard_default.SDF_INDEX;
var SPLIT_DIRECTION_INDEX2 = Billboard_default.SPLIT_DIRECTION_INDEX;
var NUMBER_OF_PROPERTIES = Billboard_default.NUMBER_OF_PROPERTIES;
var attributeLocations;
var attributeLocationsBatched = {
positionHighAndScale: 0,
positionLowAndRotation: 1,
compressedAttribute0: 2,
// pixel offset, translate, horizontal origin, vertical origin, show, direction, texture coordinates
compressedAttribute1: 3,
// aligned axis, translucency by distance, image width
compressedAttribute2: 4,
// image height, color, pick color, size in meters, valid aligned axis, 13 bits free
eyeOffset: 5,
// 4 bytes free
scaleByDistance: 6,
pixelOffsetScaleByDistance: 7,
compressedAttribute3: 8,
textureCoordinateBoundsOrLabelTranslate: 9,
a_batchId: 10,
sdf: 11,
splitDirection: 12
};
var attributeLocationsInstanced = {
direction: 0,
positionHighAndScale: 1,
positionLowAndRotation: 2,
// texture offset in w
compressedAttribute0: 3,
compressedAttribute1: 4,
compressedAttribute2: 5,
eyeOffset: 6,
// texture range in w
scaleByDistance: 7,
pixelOffsetScaleByDistance: 8,
compressedAttribute3: 9,
textureCoordinateBoundsOrLabelTranslate: 10,
a_batchId: 11,
sdf: 12,
splitDirection: 13
};
function BillboardCollection(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._scene = options.scene;
this._batchTable = options.batchTable;
let textureAtlas = options.textureAtlas;
if (!defined_default(textureAtlas)) {
textureAtlas = new TextureAtlas_default();
}
this._textureAtlas = textureAtlas;
this._textureAtlasGUID = textureAtlas.guid;
this._destroyTextureAtlas = true;
this._billboardTextureCache = /* @__PURE__ */ new Map();
this._sp = void 0;
this._spTranslucent = void 0;
this._rsOpaque = void 0;
this._rsTranslucent = void 0;
this._vaf = void 0;
this._billboards = [];
this._billboardsToUpdate = [];
this._billboardsToUpdateIndex = 0;
this._billboardsRemoved = false;
this._createVertexArray = false;
this._shaderRotation = false;
this._compiledShaderRotation = false;
this._shaderAlignedAxis = false;
this._compiledShaderAlignedAxis = false;
this._shaderScaleByDistance = false;
this._compiledShaderScaleByDistance = false;
this._shaderTranslucencyByDistance = false;
this._compiledShaderTranslucencyByDistance = false;
this._shaderPixelOffsetScaleByDistance = false;
this._compiledShaderPixelOffsetScaleByDistance = false;
this._shaderDistanceDisplayCondition = false;
this._compiledShaderDistanceDisplayCondition = false;
this._shaderDisableDepthDistance = false;
this._compiledShaderDisableDepthDistance = false;
this._shaderClampToGround = false;
this._compiledShaderClampToGround = false;
this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES);
this._maxSize = 0;
this._maxEyeOffset = 0;
this._maxScale = 1;
this._maxPixelOffset = 0;
this._allHorizontalCenter = true;
this._allVerticalCenter = true;
this._allSizedInMeters = true;
this._baseVolume = new BoundingSphere_default();
this._baseVolumeWC = new BoundingSphere_default();
this._baseVolume2D = new BoundingSphere_default();
this._boundingVolume = new BoundingSphere_default();
this._boundingVolumeDirty = false;
this._colorCommands = [];
this._allBillboardsReady = false;
this.show = options.show ?? true;
this.modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this._modelMatrix = Matrix4_default.clone(Matrix4_default.IDENTITY);
this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this.debugShowTextureAtlas = options.debugShowTextureAtlas ?? false;
this.blendOption = options.blendOption ?? BlendOption_default.OPAQUE_AND_TRANSLUCENT;
this._blendOption = void 0;
this._mode = SceneMode_default.SCENE3D;
this._buffersUsage = [
BufferUsage_default.STATIC_DRAW,
// SHOW_INDEX
BufferUsage_default.STATIC_DRAW,
// POSITION_INDEX
BufferUsage_default.STATIC_DRAW,
// PIXEL_OFFSET_INDEX
BufferUsage_default.STATIC_DRAW,
// EYE_OFFSET_INDEX
BufferUsage_default.STATIC_DRAW,
// HORIZONTAL_ORIGIN_INDEX
BufferUsage_default.STATIC_DRAW,
// VERTICAL_ORIGIN_INDEX
BufferUsage_default.STATIC_DRAW,
// SCALE_INDEX
BufferUsage_default.STATIC_DRAW,
// IMAGE_INDEX_INDEX
BufferUsage_default.STATIC_DRAW,
// COLOR_INDEX
BufferUsage_default.STATIC_DRAW,
// ROTATION_INDEX
BufferUsage_default.STATIC_DRAW,
// ALIGNED_AXIS_INDEX
BufferUsage_default.STATIC_DRAW,
// SCALE_BY_DISTANCE_INDEX
BufferUsage_default.STATIC_DRAW,
// TRANSLUCENCY_BY_DISTANCE_INDEX
BufferUsage_default.STATIC_DRAW,
// PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX
BufferUsage_default.STATIC_DRAW,
// DISTANCE_DISPLAY_CONDITION_INDEX
BufferUsage_default.STATIC_DRAW,
// TEXTURE_COORDINATE_BOUNDS
BufferUsage_default.STATIC_DRAW
// SPLIT_DIRECTION_INDEX
];
this._highlightColor = Color_default.clone(Color_default.WHITE);
this._uniforms = {
u_atlas: () => {
return this.textureAtlas.texture;
},
u_highlightColor: () => {
return this._highlightColor;
}
};
const scene = this._scene;
if (defined_default(scene) && defined_default(scene.terrainProviderChanged)) {
this._removeCallbackFunc = scene.terrainProviderChanged.addEventListener(
function() {
const billboards = this._billboards;
const length2 = billboards.length;
for (let i = 0; i < length2; ++i) {
if (defined_default(billboards[i])) {
billboards[i]._updateClamping();
}
}
},
this
);
}
}
Object.defineProperties(BillboardCollection.prototype, {
/**
* Returns the number of billboards in this collection. This is commonly used with
* {@link BillboardCollection#get} to iterate over all the billboards
* in the collection.
* @memberof BillboardCollection.prototype
* @type {number}
* @readonly
*/
length: {
get: function() {
removeBillboards(this);
return this._billboards.length;
}
},
/**
* Gets or sets the textureAtlas.
* @memberof BillboardCollection.prototype
* @type {TextureAtlas}
* @private
*/
textureAtlas: {
get: function() {
return this._textureAtlas;
},
set: function(value) {
Check_default.defined("textureAtlas", value);
if (this._textureAtlas !== value) {
this._textureAtlas = this._destroyTextureAtlas && this._textureAtlas && this._textureAtlas.destroy();
this._textureAtlas = value;
}
}
},
/**
* Gets or sets a value which determines if the texture atlas is
* destroyed when the collection is destroyed.
*
* If the texture atlas is used by more than one collection, set this to false,
* and explicitly destroy the atlas to avoid attempting to destroy it multiple times.
*
* @memberof BillboardCollection.prototype
* @type {boolean}
* @private
*
* @example
* // Set destroyTextureAtlas
* // Destroy a billboard collection but not its texture atlas.
*
* const atlas = new TextureAtlas();
* billboards.textureAtlas = atlas;
* billboards.destroyTextureAtlas = false;
*
* billboards = billboards.destroy();
* console.log(atlas.isDestroyed()); // False
*/
destroyTextureAtlas: {
get: function() {
return this._destroyTextureAtlas;
},
set: function(value) {
this._destroyTextureAtlas = value;
}
},
/**
* Returns the size in bytes of the WebGL texture resources.
* @private
* @memberof BillboardCollection.prototype
* @type {number}
* @readonly
*/
sizeInBytes: {
get: function() {
return this._textureAtlas.sizeInBytes;
}
},
/**
* True when all billboards currently in the collection are ready for rendering.
* @private
* @memberof BillboardCollection.prototype
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._allBillboardsReady;
}
},
/**
* Cache of loaded billboard images.
* @private
* @memberof BillboardCollection.prototype
* @type {Map}
* @readonly
*/
billboardTextureCache: {
get: function() {
return this._billboardTextureCache;
}
}
});
function destroyBillboards(billboards) {
const length2 = billboards.length;
for (let i = 0; i < length2; ++i) {
if (billboards[i]) {
billboards[i]._destroy();
}
}
}
BillboardCollection.prototype.add = function(options) {
const billboard = new Billboard_default(options, this);
billboard._index = this._billboards.length;
this._billboards.push(billboard);
this._createVertexArray = true;
return billboard;
};
BillboardCollection.prototype.remove = function(billboard) {
if (this.contains(billboard)) {
this._billboards[billboard._index] = void 0;
this._billboardsRemoved = true;
this._createVertexArray = true;
billboard._destroy();
return true;
}
return false;
};
BillboardCollection.prototype.removeAll = function() {
destroyBillboards(this._billboards);
this._billboards = [];
this._billboardsToUpdate = [];
this._billboardsToUpdateIndex = 0;
this._billboardsRemoved = false;
this._createVertexArray = true;
};
function removeBillboards(billboardCollection) {
if (billboardCollection._billboardsRemoved) {
billboardCollection._billboardsRemoved = false;
const newBillboards = [];
const billboards = billboardCollection._billboards;
const length2 = billboards.length;
for (let i = 0, j = 0; i < length2; ++i) {
const billboard = billboards[i];
if (defined_default(billboard)) {
billboard._index = j++;
newBillboards.push(billboard);
}
}
billboardCollection._billboards = newBillboards;
}
}
BillboardCollection.prototype._updateBillboard = function(billboard, propertyChanged) {
if (!billboard._dirty) {
this._billboardsToUpdate[this._billboardsToUpdateIndex++] = billboard;
}
++this._propertiesChanged[propertyChanged];
};
BillboardCollection.prototype.contains = function(billboard) {
return defined_default(billboard) && billboard._billboardCollection === this;
};
BillboardCollection.prototype.get = function(index) {
Check_default.typeOf.number("index", index);
removeBillboards(this);
return this._billboards[index];
};
var getIndexBuffer2;
function getIndexBufferBatched(context) {
const sixteenK = 16 * 1024;
let indexBuffer = context.cache.billboardCollection_indexBufferBatched;
if (defined_default(indexBuffer)) {
return indexBuffer;
}
const length2 = sixteenK * 6 - 6;
const indices = new Uint16Array(length2);
for (let i = 0, j = 0; i < length2; i += 6, j += 4) {
indices[i] = j;
indices[i + 1] = j + 1;
indices[i + 2] = j + 2;
indices[i + 3] = j + 0;
indices[i + 4] = j + 2;
indices[i + 5] = j + 3;
}
indexBuffer = Buffer_default.createIndexBuffer({
context,
typedArray: indices,
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype: IndexDatatype_default.UNSIGNED_SHORT
});
indexBuffer.vertexArrayDestroyable = false;
context.cache.billboardCollection_indexBufferBatched = indexBuffer;
return indexBuffer;
}
function getIndexBufferInstanced(context) {
let indexBuffer = context.cache.billboardCollection_indexBufferInstanced;
if (defined_default(indexBuffer)) {
return indexBuffer;
}
indexBuffer = Buffer_default.createIndexBuffer({
context,
typedArray: new Uint16Array([0, 1, 2, 0, 2, 3]),
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype: IndexDatatype_default.UNSIGNED_SHORT
});
indexBuffer.vertexArrayDestroyable = false;
context.cache.billboardCollection_indexBufferInstanced = indexBuffer;
return indexBuffer;
}
function getVertexBufferInstanced(context) {
let vertexBuffer = context.cache.billboardCollection_vertexBufferInstanced;
if (defined_default(vertexBuffer)) {
return vertexBuffer;
}
vertexBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
usage: BufferUsage_default.STATIC_DRAW
});
vertexBuffer.vertexArrayDestroyable = false;
context.cache.billboardCollection_vertexBufferInstanced = vertexBuffer;
return vertexBuffer;
}
BillboardCollection.prototype.computeNewBuffersUsage = function() {
const buffersUsage = this._buffersUsage;
let usageChanged = false;
const properties = this._propertiesChanged;
for (let k = 0; k < NUMBER_OF_PROPERTIES; ++k) {
const newUsage = properties[k] === 0 ? BufferUsage_default.STATIC_DRAW : BufferUsage_default.STREAM_DRAW;
usageChanged = usageChanged || buffersUsage[k] !== newUsage;
buffersUsage[k] = newUsage;
}
return usageChanged;
};
function createVAF(context, numberOfBillboards, buffersUsage, instanced, batchTable, sdf) {
const attributes = [
{
index: attributeLocations.positionHighAndScale,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[POSITION_INDEX2]
},
{
index: attributeLocations.positionLowAndRotation,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[POSITION_INDEX2]
},
{
index: attributeLocations.compressedAttribute0,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[PIXEL_OFFSET_INDEX2]
},
{
index: attributeLocations.compressedAttribute1,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[TRANSLUCENCY_BY_DISTANCE_INDEX2]
},
{
index: attributeLocations.compressedAttribute2,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[COLOR_INDEX2]
},
{
index: attributeLocations.eyeOffset,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[EYE_OFFSET_INDEX2]
},
{
index: attributeLocations.scaleByDistance,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[SCALE_BY_DISTANCE_INDEX2]
},
{
index: attributeLocations.pixelOffsetScaleByDistance,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX2]
},
{
index: attributeLocations.compressedAttribute3,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[DISTANCE_DISPLAY_CONDITION_INDEX]
},
{
index: attributeLocations.textureCoordinateBoundsOrLabelTranslate,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[TEXTURE_COORDINATE_BOUNDS]
},
{
index: attributeLocations.splitDirection,
componentsPerAttribute: 1,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[SPLIT_DIRECTION_INDEX2]
}
];
if (instanced) {
attributes.push({
index: attributeLocations.direction,
componentsPerAttribute: 2,
componentDatatype: ComponentDatatype_default.FLOAT,
vertexBuffer: getVertexBufferInstanced(context)
});
}
if (defined_default(batchTable)) {
attributes.push({
index: attributeLocations.a_batchId,
componentsPerAttribute: 1,
componentDatatype: ComponentDatatype_default.FLOAT,
bufferUsage: BufferUsage_default.STATIC_DRAW
});
}
if (sdf) {
attributes.push({
index: attributeLocations.sdf,
componentsPerAttribute: 2,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[SDF_INDEX2]
});
}
const sizeInVertices = instanced ? numberOfBillboards : 4 * numberOfBillboards;
return new VertexArrayFacade_default(context, attributes, sizeInVertices, instanced);
}
var writePositionScratch = new EncodedCartesian3_default();
function writePositionScaleAndRotation(billboardCollection, frameState, vafWriters, billboard) {
let i;
const positionHighWriter = vafWriters[attributeLocations.positionHighAndScale];
const positionLowWriter = vafWriters[attributeLocations.positionLowAndRotation];
const position = billboard._getActualPosition();
if (billboardCollection._mode === SceneMode_default.SCENE3D) {
BoundingSphere_default.expand(
billboardCollection._baseVolume,
position,
billboardCollection._baseVolume
);
billboardCollection._boundingVolumeDirty = true;
}
EncodedCartesian3_default.fromCartesian(position, writePositionScratch);
const scale = billboard.scale;
const rotation = billboard.rotation;
if (rotation !== 0) {
billboardCollection._shaderRotation = true;
}
billboardCollection._maxScale = Math.max(
billboardCollection._maxScale,
scale
);
const high = writePositionScratch.high;
const low = writePositionScratch.low;
if (billboardCollection._instanced) {
i = billboard._index;
positionHighWriter(i, high.x, high.y, high.z, scale);
positionLowWriter(i, low.x, low.y, low.z, rotation);
} else {
i = billboard._index * 4;
positionHighWriter(i + 0, high.x, high.y, high.z, scale);
positionHighWriter(i + 1, high.x, high.y, high.z, scale);
positionHighWriter(i + 2, high.x, high.y, high.z, scale);
positionHighWriter(i + 3, high.x, high.y, high.z, scale);
positionLowWriter(i + 0, low.x, low.y, low.z, rotation);
positionLowWriter(i + 1, low.x, low.y, low.z, rotation);
positionLowWriter(i + 2, low.x, low.y, low.z, rotation);
positionLowWriter(i + 3, low.x, low.y, low.z, rotation);
}
}
var scratchCartesian24 = new Cartesian2_default();
var UPPER_BOUND = 32768;
var LEFT_SHIFT16 = 65536;
var LEFT_SHIFT12 = 4096;
var LEFT_SHIFT8 = 256;
var LEFT_SHIFT7 = 128;
var LEFT_SHIFT5 = 32;
var LEFT_SHIFT3 = 8;
var LEFT_SHIFT2 = 4;
var RIGHT_SHIFT8 = 1 / 256;
var LOWER_LEFT = 0;
var LOWER_RIGHT = 2;
var UPPER_RIGHT = 3;
var UPPER_LEFT = 1;
var scratchBoundingRectangle2 = new BoundingRectangle_default();
function writeCompressedAttrib0(billboardCollection, frameState, vafWriters, billboard) {
let i;
const writer = vafWriters[attributeLocations.compressedAttribute0];
const pixelOffset = billboard.pixelOffset;
const pixelOffsetX = pixelOffset.x;
const pixelOffsetY = pixelOffset.y;
const translate = billboard._translate;
const translateX = translate.x;
const translateY = translate.y;
billboardCollection._maxPixelOffset = Math.max(
billboardCollection._maxPixelOffset,
Math.abs(pixelOffsetX + translateX),
Math.abs(-pixelOffsetY + translateY)
);
const horizontalOrigin = billboard.horizontalOrigin;
let verticalOrigin = billboard._verticalOrigin;
let show = billboard.show && billboard.clusterShow;
if (billboard.color.alpha === 0) {
show = false;
}
if (verticalOrigin === VerticalOrigin_default.BASELINE) {
verticalOrigin = VerticalOrigin_default.BOTTOM;
}
billboardCollection._allHorizontalCenter = billboardCollection._allHorizontalCenter && horizontalOrigin === HorizontalOrigin_default.CENTER;
billboardCollection._allVerticalCenter = billboardCollection._allVerticalCenter && verticalOrigin === VerticalOrigin_default.CENTER;
let bottomLeftX = 0;
let bottomLeftY = 0;
let width = 0;
let height = 0;
if (billboard.ready) {
const imageRectangle = billboard.computeTextureCoordinates(
scratchBoundingRectangle2
);
bottomLeftX = imageRectangle.x;
bottomLeftY = imageRectangle.y;
width = imageRectangle.width;
height = imageRectangle.height;
}
const topRightX = bottomLeftX + width;
const topRightY = bottomLeftY + height;
let compressed0 = Math.floor(
Math_default.clamp(pixelOffsetX, -UPPER_BOUND, UPPER_BOUND) + UPPER_BOUND
) * LEFT_SHIFT7;
compressed0 += (horizontalOrigin + 1) * LEFT_SHIFT5;
compressed0 += (verticalOrigin + 1) * LEFT_SHIFT3;
compressed0 += (show ? 1 : 0) * LEFT_SHIFT2;
let compressed1 = Math.floor(
Math_default.clamp(pixelOffsetY, -UPPER_BOUND, UPPER_BOUND) + UPPER_BOUND
) * LEFT_SHIFT8;
let compressed2 = Math.floor(
Math_default.clamp(translateX, -UPPER_BOUND, UPPER_BOUND) + UPPER_BOUND
) * LEFT_SHIFT8;
const tempTanslateY = (Math_default.clamp(translateY, -UPPER_BOUND, UPPER_BOUND) + UPPER_BOUND) * RIGHT_SHIFT8;
const upperTranslateY = Math.floor(tempTanslateY);
const lowerTranslateY = Math.floor(
(tempTanslateY - upperTranslateY) * LEFT_SHIFT8
);
compressed1 += upperTranslateY;
compressed2 += lowerTranslateY;
scratchCartesian24.x = bottomLeftX;
scratchCartesian24.y = bottomLeftY;
const compressedTexCoordsLL = AttributeCompression_default.compressTextureCoordinates(scratchCartesian24);
scratchCartesian24.x = topRightX;
const compressedTexCoordsLR = AttributeCompression_default.compressTextureCoordinates(scratchCartesian24);
scratchCartesian24.y = topRightY;
const compressedTexCoordsUR = AttributeCompression_default.compressTextureCoordinates(scratchCartesian24);
scratchCartesian24.x = bottomLeftX;
const compressedTexCoordsUL = AttributeCompression_default.compressTextureCoordinates(scratchCartesian24);
if (billboardCollection._instanced) {
i = billboard._index;
writer(i, compressed0, compressed1, compressed2, compressedTexCoordsLL);
} else {
i = billboard._index * 4;
writer(
i + 0,
compressed0 + LOWER_LEFT,
compressed1,
compressed2,
compressedTexCoordsLL
);
writer(
i + 1,
compressed0 + LOWER_RIGHT,
compressed1,
compressed2,
compressedTexCoordsLR
);
writer(
i + 2,
compressed0 + UPPER_RIGHT,
compressed1,
compressed2,
compressedTexCoordsUR
);
writer(
i + 3,
compressed0 + UPPER_LEFT,
compressed1,
compressed2,
compressedTexCoordsUL
);
}
}
function writeCompressedAttrib1(billboardCollection, frameState, vafWriters, billboard) {
let i;
const writer = vafWriters[attributeLocations.compressedAttribute1];
const alignedAxis = billboard.alignedAxis;
if (!Cartesian3_default.equals(alignedAxis, Cartesian3_default.ZERO)) {
billboardCollection._shaderAlignedAxis = true;
}
let near = 0;
let nearValue = 1;
let far = 1;
let farValue = 1;
const translucency = billboard.translucencyByDistance;
if (defined_default(translucency)) {
near = translucency.near;
nearValue = translucency.nearValue;
far = translucency.far;
farValue = translucency.farValue;
if (nearValue !== 1 || farValue !== 1) {
billboardCollection._shaderTranslucencyByDistance = true;
}
}
const imageWidth = Math.round(billboard.width ?? 0);
billboardCollection._maxSize = Math.max(
billboardCollection._maxSize,
imageWidth
);
let compressed0 = Math_default.clamp(imageWidth, 0, LEFT_SHIFT16);
let compressed1 = 0;
if (Math.abs(Cartesian3_default.magnitudeSquared(alignedAxis) - 1) < Math_default.EPSILON6) {
compressed1 = AttributeCompression_default.octEncodeFloat(alignedAxis);
}
nearValue = Math_default.clamp(nearValue, 0, 1);
nearValue = nearValue === 1 ? 255 : nearValue * 255 | 0;
compressed0 = compressed0 * LEFT_SHIFT8 + nearValue;
farValue = Math_default.clamp(farValue, 0, 1);
farValue = farValue === 1 ? 255 : farValue * 255 | 0;
compressed1 = compressed1 * LEFT_SHIFT8 + farValue;
if (billboardCollection._instanced) {
i = billboard._index;
writer(i, compressed0, compressed1, near, far);
} else {
i = billboard._index * 4;
writer(i + 0, compressed0, compressed1, near, far);
writer(i + 1, compressed0, compressed1, near, far);
writer(i + 2, compressed0, compressed1, near, far);
writer(i + 3, compressed0, compressed1, near, far);
}
}
function writeCompressedAttrib2(billboardCollection, frameState, vafWriters, billboard) {
let i;
const writer = vafWriters[attributeLocations.compressedAttribute2];
const color = billboard.color;
const pickColor = !defined_default(billboardCollection._batchTable) ? billboard.getPickId(frameState.context).color : Color_default.WHITE;
const sizeInMeters = billboard.sizeInMeters ? 1 : 0;
const validAlignedAxis = Math.abs(Cartesian3_default.magnitudeSquared(billboard.alignedAxis) - 1) < Math_default.EPSILON6 ? 1 : 0;
billboardCollection._allSizedInMeters = billboardCollection._allSizedInMeters && sizeInMeters === 1;
const imageHeight = billboard.height ?? 0;
billboardCollection._maxSize = Math.max(
billboardCollection._maxSize,
imageHeight
);
let labelHorizontalOrigin = billboard._labelHorizontalOrigin ?? -2;
labelHorizontalOrigin += 2;
const compressed3 = imageHeight * LEFT_SHIFT2 + labelHorizontalOrigin;
let red = Color_default.floatToByte(color.red);
let green = Color_default.floatToByte(color.green);
let blue = Color_default.floatToByte(color.blue);
const compressed0 = red * LEFT_SHIFT16 + green * LEFT_SHIFT8 + blue;
red = Color_default.floatToByte(pickColor.red);
green = Color_default.floatToByte(pickColor.green);
blue = Color_default.floatToByte(pickColor.blue);
const compressed1 = red * LEFT_SHIFT16 + green * LEFT_SHIFT8 + blue;
let compressed2 = Color_default.floatToByte(color.alpha) * LEFT_SHIFT16 + Color_default.floatToByte(pickColor.alpha) * LEFT_SHIFT8;
compressed2 += sizeInMeters * 2 + validAlignedAxis;
if (billboardCollection._instanced) {
i = billboard._index;
writer(i, compressed0, compressed1, compressed2, compressed3);
} else {
i = billboard._index * 4;
writer(i + 0, compressed0, compressed1, compressed2, compressed3);
writer(i + 1, compressed0, compressed1, compressed2, compressed3);
writer(i + 2, compressed0, compressed1, compressed2, compressed3);
writer(i + 3, compressed0, compressed1, compressed2, compressed3);
}
}
function writeEyeOffset(billboardCollection, frameState, vafWriters, billboard) {
let i;
const writer = vafWriters[attributeLocations.eyeOffset];
const eyeOffset = billboard.eyeOffset;
let eyeOffsetZ = eyeOffset.z;
if (billboard._heightReference !== HeightReference_default.NONE) {
eyeOffsetZ *= 1.005;
}
billboardCollection._maxEyeOffset = Math.max(
billboardCollection._maxEyeOffset,
Math.abs(eyeOffset.x),
Math.abs(eyeOffset.y),
Math.abs(eyeOffsetZ)
);
if (billboardCollection._instanced) {
scratchCartesian24.x = 0;
scratchCartesian24.y = 0;
if (billboard.ready) {
const imageRectangle = billboard.computeTextureCoordinates(
scratchBoundingRectangle2
);
scratchCartesian24.x = imageRectangle.width;
scratchCartesian24.y = imageRectangle.height;
}
const compressedTexCoordsRange = AttributeCompression_default.compressTextureCoordinates(scratchCartesian24);
i = billboard._index;
writer(i, eyeOffset.x, eyeOffset.y, eyeOffsetZ, compressedTexCoordsRange);
} else {
i = billboard._index * 4;
writer(i + 0, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0);
writer(i + 1, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0);
writer(i + 2, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0);
writer(i + 3, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0);
}
}
function writeScaleByDistance(billboardCollection, frameState, vafWriters, billboard) {
let i;
const writer = vafWriters[attributeLocations.scaleByDistance];
let near = 0;
let nearValue = 1;
let far = 1;
let farValue = 1;
const scale = billboard.scaleByDistance;
if (defined_default(scale)) {
near = scale.near;
nearValue = scale.nearValue;
far = scale.far;
farValue = scale.farValue;
if (nearValue !== 1 || farValue !== 1) {
billboardCollection._shaderScaleByDistance = true;
}
}
if (billboardCollection._instanced) {
i = billboard._index;
writer(i, near, nearValue, far, farValue);
} else {
i = billboard._index * 4;
writer(i + 0, near, nearValue, far, farValue);
writer(i + 1, near, nearValue, far, farValue);
writer(i + 2, near, nearValue, far, farValue);
writer(i + 3, near, nearValue, far, farValue);
}
}
function writePixelOffsetScaleByDistance(billboardCollection, frameState, vafWriters, billboard) {
let i;
const writer = vafWriters[attributeLocations.pixelOffsetScaleByDistance];
let near = 0;
let nearValue = 1;
let far = 1;
let farValue = 1;
const pixelOffsetScale = billboard.pixelOffsetScaleByDistance;
if (defined_default(pixelOffsetScale)) {
near = pixelOffsetScale.near;
nearValue = pixelOffsetScale.nearValue;
far = pixelOffsetScale.far;
farValue = pixelOffsetScale.farValue;
if (nearValue !== 1 || farValue !== 1) {
billboardCollection._shaderPixelOffsetScaleByDistance = true;
}
}
if (billboardCollection._instanced) {
i = billboard._index;
writer(i, near, nearValue, far, farValue);
} else {
i = billboard._index * 4;
writer(i + 0, near, nearValue, far, farValue);
writer(i + 1, near, nearValue, far, farValue);
writer(i + 2, near, nearValue, far, farValue);
writer(i + 3, near, nearValue, far, farValue);
}
}
function writeCompressedAttribute3(billboardCollection, frameState, vafWriters, billboard) {
let i;
const writer = vafWriters[attributeLocations.compressedAttribute3];
let near = 0;
let far = Number.MAX_VALUE;
const distanceDisplayCondition = billboard.distanceDisplayCondition;
if (defined_default(distanceDisplayCondition)) {
near = distanceDisplayCondition.near;
far = distanceDisplayCondition.far;
near *= near;
far *= far;
billboardCollection._shaderDistanceDisplayCondition = true;
}
let disableDepthTestDistance = billboard.disableDepthTestDistance;
const clampToGround = isHeightReferenceClamp(billboard.heightReference) && frameState.context.depthTexture;
if (!defined_default(disableDepthTestDistance)) {
disableDepthTestDistance = clampToGround ? 5e3 : 0;
}
disableDepthTestDistance *= disableDepthTestDistance;
if (clampToGround || disableDepthTestDistance > 0) {
billboardCollection._shaderDisableDepthDistance = true;
if (disableDepthTestDistance === Number.POSITIVE_INFINITY) {
disableDepthTestDistance = -1;
}
}
let imageHeight;
let imageWidth;
if (!defined_default(billboard._labelDimensions)) {
imageWidth = billboard.width ?? 0;
imageHeight = billboard.height ?? 0;
} else {
imageWidth = billboard._labelDimensions.x;
imageHeight = billboard._labelDimensions.y;
}
const w = Math.floor(Math_default.clamp(imageWidth, 0, LEFT_SHIFT12));
const h = Math.floor(Math_default.clamp(imageHeight, 0, LEFT_SHIFT12));
const dimensions = w * LEFT_SHIFT12 + h;
if (billboardCollection._instanced) {
i = billboard._index;
writer(i, near, far, disableDepthTestDistance, dimensions);
} else {
i = billboard._index * 4;
writer(i + 0, near, far, disableDepthTestDistance, dimensions);
writer(i + 1, near, far, disableDepthTestDistance, dimensions);
writer(i + 2, near, far, disableDepthTestDistance, dimensions);
writer(i + 3, near, far, disableDepthTestDistance, dimensions);
}
}
function writeTextureCoordinateBoundsOrLabelTranslate(billboardCollection, frameState, vafWriters, billboard) {
if (isHeightReferenceClamp(billboard.heightReference)) {
const scene = billboardCollection._scene;
const context = frameState.context;
const globeTranslucent = frameState.globeTranslucencyState.translucent;
const depthTestAgainstTerrain = defined_default(scene.globe) && scene.globe.depthTestAgainstTerrain;
billboardCollection._shaderClampToGround = context.depthTexture && !globeTranslucent && depthTestAgainstTerrain;
}
let i;
const writer = vafWriters[attributeLocations.textureCoordinateBoundsOrLabelTranslate];
if (ContextLimits_default.maximumVertexTextureImageUnits > 0) {
let translateX = 0;
let translateY = 0;
if (defined_default(billboard._labelTranslate)) {
translateX = billboard._labelTranslate.x;
translateY = billboard._labelTranslate.y;
}
if (billboardCollection._instanced) {
i = billboard._index;
writer(i, translateX, translateY, 0, 0);
} else {
i = billboard._index * 4;
writer(i + 0, translateX, translateY, 0, 0);
writer(i + 1, translateX, translateY, 0, 0);
writer(i + 2, translateX, translateY, 0, 0);
writer(i + 3, translateX, translateY, 0, 0);
}
return;
}
let minX = 0;
let minY = 0;
let width = 0;
let height = 0;
if (billboard.ready) {
const imageRectangle = billboard.computeTextureCoordinates(
scratchBoundingRectangle2
);
minX = imageRectangle.x;
minY = imageRectangle.y;
width = imageRectangle.width;
height = imageRectangle.height;
}
const maxX = minX + width;
const maxY = minY + height;
if (billboardCollection._instanced) {
i = billboard._index;
writer(i, minX, minY, maxX, maxY);
} else {
i = billboard._index * 4;
writer(i + 0, minX, minY, maxX, maxY);
writer(i + 1, minX, minY, maxX, maxY);
writer(i + 2, minX, minY, maxX, maxY);
writer(i + 3, minX, minY, maxX, maxY);
}
}
function writeBatchId(billboardCollection, frameState, vafWriters, billboard) {
if (!defined_default(billboardCollection._batchTable)) {
return;
}
const writer = vafWriters[attributeLocations.a_batchId];
const id = billboard._batchIndex;
let i;
if (billboardCollection._instanced) {
i = billboard._index;
writer(i, id);
} else {
i = billboard._index * 4;
writer(i + 0, id);
writer(i + 1, id);
writer(i + 2, id);
writer(i + 3, id);
}
}
function writeSDF(billboardCollection, frameState, vafWriters, billboard) {
if (!billboardCollection._sdf) {
return;
}
let i;
const writer = vafWriters[attributeLocations.sdf];
const outlineColor = billboard.outlineColor;
const outlineWidth = billboard.outlineWidth;
const red = Color_default.floatToByte(outlineColor.red);
const green = Color_default.floatToByte(outlineColor.green);
const blue = Color_default.floatToByte(outlineColor.blue);
const compressed0 = red * LEFT_SHIFT16 + green * LEFT_SHIFT8 + blue;
const outlineDistance = outlineWidth / SDFSettings_default.RADIUS;
const compressed1 = Color_default.floatToByte(outlineColor.alpha) * LEFT_SHIFT16 + Color_default.floatToByte(outlineDistance) * LEFT_SHIFT8;
if (billboardCollection._instanced) {
i = billboard._index;
writer(i, compressed0, compressed1);
} else {
i = billboard._index * 4;
writer(i + 0, compressed0 + LOWER_LEFT, compressed1);
writer(i + 1, compressed0 + LOWER_RIGHT, compressed1);
writer(i + 2, compressed0 + UPPER_RIGHT, compressed1);
writer(i + 3, compressed0 + UPPER_LEFT, compressed1);
}
}
function writeSplitDirection(billboardCollection, frameState, vafWriters, billboard) {
const writer = vafWriters[attributeLocations.splitDirection];
let direction2 = 0;
const split = billboard.splitDirection;
if (defined_default(split)) {
direction2 = split;
}
let i;
if (billboardCollection._instanced) {
i = billboard._index;
writer(i, direction2);
} else {
i = billboard._index * 4;
writer(i + 0, direction2);
writer(i + 1, direction2);
writer(i + 2, direction2);
writer(i + 3, direction2);
}
}
function writeBillboard(billboardCollection, frameState, vafWriters, billboard) {
writePositionScaleAndRotation(
billboardCollection,
frameState,
vafWriters,
billboard
);
writeCompressedAttrib0(
billboardCollection,
frameState,
vafWriters,
billboard
);
writeCompressedAttrib1(
billboardCollection,
frameState,
vafWriters,
billboard
);
writeCompressedAttrib2(
billboardCollection,
frameState,
vafWriters,
billboard
);
writeEyeOffset(billboardCollection, frameState, vafWriters, billboard);
writeScaleByDistance(billboardCollection, frameState, vafWriters, billboard);
writePixelOffsetScaleByDistance(
billboardCollection,
frameState,
vafWriters,
billboard
);
writeCompressedAttribute3(
billboardCollection,
frameState,
vafWriters,
billboard
);
writeTextureCoordinateBoundsOrLabelTranslate(
billboardCollection,
frameState,
vafWriters,
billboard
);
writeBatchId(billboardCollection, frameState, vafWriters, billboard);
writeSDF(billboardCollection, frameState, vafWriters, billboard);
writeSplitDirection(billboardCollection, frameState, vafWriters, billboard);
}
function recomputeActualPositions(billboardCollection, billboards, length2, frameState, modelMatrix, recomputeBoundingVolume) {
let boundingVolume;
if (frameState.mode === SceneMode_default.SCENE3D) {
boundingVolume = billboardCollection._baseVolume;
billboardCollection._boundingVolumeDirty = true;
} else {
boundingVolume = billboardCollection._baseVolume2D;
}
const positions = [];
for (let i = 0; i < length2; ++i) {
const billboard = billboards[i];
const position = billboard.position;
const actualPosition = Billboard_default._computeActualPosition(
billboard,
position,
frameState,
modelMatrix
);
if (defined_default(actualPosition)) {
billboard._setActualPosition(actualPosition);
if (recomputeBoundingVolume) {
positions.push(actualPosition);
} else {
BoundingSphere_default.expand(boundingVolume, actualPosition, boundingVolume);
}
}
}
if (recomputeBoundingVolume) {
BoundingSphere_default.fromPoints(positions, boundingVolume);
}
}
function updateMode(billboardCollection, frameState) {
const mode2 = frameState.mode;
const billboards = billboardCollection._billboards;
const billboardsToUpdate = billboardCollection._billboardsToUpdate;
const modelMatrix = billboardCollection._modelMatrix;
if (billboardCollection._createVertexArray || billboardCollection._mode !== mode2 || mode2 !== SceneMode_default.SCENE3D && !Matrix4_default.equals(modelMatrix, billboardCollection.modelMatrix)) {
billboardCollection._mode = mode2;
Matrix4_default.clone(billboardCollection.modelMatrix, modelMatrix);
billboardCollection._createVertexArray = true;
if (mode2 === SceneMode_default.SCENE3D || mode2 === SceneMode_default.SCENE2D || mode2 === SceneMode_default.COLUMBUS_VIEW) {
recomputeActualPositions(
billboardCollection,
billboards,
billboards.length,
frameState,
modelMatrix,
true
);
}
} else if (mode2 === SceneMode_default.MORPHING) {
recomputeActualPositions(
billboardCollection,
billboards,
billboards.length,
frameState,
modelMatrix,
true
);
} else if (mode2 === SceneMode_default.SCENE2D || mode2 === SceneMode_default.COLUMBUS_VIEW) {
recomputeActualPositions(
billboardCollection,
billboardsToUpdate,
billboardCollection._billboardsToUpdateIndex,
frameState,
modelMatrix,
false
);
}
}
function updateBoundingVolume(collection, frameState, boundingVolume) {
let pixelScale = 1;
if (!collection._allSizedInMeters || collection._maxPixelOffset !== 0) {
pixelScale = frameState.camera.getPixelSize(
boundingVolume,
frameState.context.drawingBufferWidth,
frameState.context.drawingBufferHeight
);
}
let size = pixelScale * collection._maxScale * collection._maxSize * 2;
if (collection._allHorizontalCenter && collection._allVerticalCenter) {
size *= 0.5;
}
const offset = pixelScale * collection._maxPixelOffset + collection._maxEyeOffset;
boundingVolume.radius += size + offset;
}
function createDebugCommand(billboardCollection, context) {
const fs = "uniform sampler2D billboard_texture; \nin vec2 v_textureCoordinates; \nvoid main() \n{ \n out_FragColor = texture(billboard_texture, v_textureCoordinates); \n} \n";
const drawCommand = context.createViewportQuadCommand(fs, {
uniformMap: {
billboard_texture: function() {
return billboardCollection.textureAtlas.texture;
}
}
});
drawCommand.pass = Pass_default.OVERLAY;
return drawCommand;
}
var scratchWriterArray = [];
BillboardCollection.prototype.update = function(frameState) {
removeBillboards(this);
if (!this.show) {
return;
}
const context = frameState.context;
this._instanced = context.instancedArrays;
attributeLocations = this._instanced ? attributeLocationsInstanced : attributeLocationsBatched;
getIndexBuffer2 = this._instanced ? getIndexBufferInstanced : getIndexBufferBatched;
let billboards = this._billboards;
let billboardsLength = billboards.length;
let allBillboardsReady = true;
for (let i = 0; i < billboardsLength; ++i) {
const billboard = billboards[i];
if (defined_default(billboard.loadError)) {
console.error(
`Error loading image for billboard: ${billboard.loadError}`
);
billboard.image = void 0;
}
if (billboard.textureDirty) {
this._updateBillboard(billboard, IMAGE_INDEX_INDEX2);
}
if (billboard.show) {
allBillboardsReady = allBillboardsReady && billboard.ready;
}
}
const textureAtlas = this._textureAtlas;
frameState.afterRender.push(() => {
if (this.isDestroyed()) {
return;
}
return textureAtlas.update(frameState.context);
});
if (!defined_default(textureAtlas.texture)) {
return;
}
updateMode(this, frameState);
billboards = this._billboards;
billboardsLength = billboards.length;
const billboardsToUpdate = this._billboardsToUpdate;
const billboardsToUpdateLength = this._billboardsToUpdateIndex;
const properties = this._propertiesChanged;
const textureAtlasGUID = textureAtlas.guid;
const createVertexArray6 = this._createVertexArray || this._textureAtlasGUID !== textureAtlasGUID;
this._textureAtlasGUID = textureAtlasGUID;
let vafWriters;
const pass = frameState.passes;
const picking = pass.pick;
if (createVertexArray6 || !picking && this.computeNewBuffersUsage()) {
this._createVertexArray = false;
for (let k = 0; k < NUMBER_OF_PROPERTIES; ++k) {
properties[k] = 0;
}
this._vaf = this._vaf && this._vaf.destroy();
if (billboardsLength > 0) {
this._vaf = createVAF(
context,
billboardsLength,
this._buffersUsage,
this._instanced,
this._batchTable,
this._sdf
);
vafWriters = this._vaf.writers;
for (let i = 0; i < billboardsLength; ++i) {
const billboard = this._billboards[i];
billboard._dirty = false;
billboard.textureDirty = false;
writeBillboard(this, frameState, vafWriters, billboard);
}
this._vaf.commit(getIndexBuffer2(context));
}
this._billboardsToUpdateIndex = 0;
} else if (billboardsToUpdateLength > 0) {
const writers = scratchWriterArray;
writers.length = 0;
if (properties[POSITION_INDEX2] || properties[ROTATION_INDEX2] || properties[SCALE_INDEX2]) {
writers.push(writePositionScaleAndRotation);
}
if (properties[IMAGE_INDEX_INDEX2] || properties[PIXEL_OFFSET_INDEX2] || properties[HORIZONTAL_ORIGIN_INDEX2] || properties[VERTICAL_ORIGIN_INDEX2] || properties[SHOW_INDEX2]) {
writers.push(writeCompressedAttrib0);
if (this._instanced) {
writers.push(writeEyeOffset);
}
}
if (properties[IMAGE_INDEX_INDEX2] || properties[ALIGNED_AXIS_INDEX2] || properties[TRANSLUCENCY_BY_DISTANCE_INDEX2]) {
writers.push(writeCompressedAttrib1);
writers.push(writeCompressedAttrib2);
}
if (properties[IMAGE_INDEX_INDEX2] || properties[COLOR_INDEX2]) {
writers.push(writeCompressedAttrib2);
}
if (properties[IMAGE_INDEX_INDEX2] || properties[EYE_OFFSET_INDEX2]) {
writers.push(writeEyeOffset);
}
if (properties[SCALE_BY_DISTANCE_INDEX2]) {
writers.push(writeScaleByDistance);
}
if (properties[PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX2]) {
writers.push(writePixelOffsetScaleByDistance);
}
if (properties[DISTANCE_DISPLAY_CONDITION_INDEX] || properties[DISABLE_DEPTH_DISTANCE2] || properties[IMAGE_INDEX_INDEX2] || properties[POSITION_INDEX2]) {
writers.push(writeCompressedAttribute3);
}
if (properties[IMAGE_INDEX_INDEX2] || properties[POSITION_INDEX2]) {
writers.push(writeTextureCoordinateBoundsOrLabelTranslate);
}
if (properties[SDF_INDEX2]) {
writers.push(writeSDF);
}
if (properties[SPLIT_DIRECTION_INDEX2]) {
writers.push(writeSplitDirection);
}
const numWriters = writers.length;
vafWriters = this._vaf.writers;
if (billboardsToUpdateLength / billboardsLength > 0.1) {
for (let m = 0; m < billboardsToUpdateLength; ++m) {
const b = billboardsToUpdate[m];
b._dirty = false;
b.textureDirty = false;
for (let n = 0; n < numWriters; ++n) {
writers[n](this, frameState, vafWriters, b);
}
}
this._vaf.commit(getIndexBuffer2(context));
} else {
for (let h = 0; h < billboardsToUpdateLength; ++h) {
const bb = billboardsToUpdate[h];
bb._dirty = false;
bb.textureDirty = false;
for (let o = 0; o < numWriters; ++o) {
writers[o](this, frameState, vafWriters, bb);
}
if (this._instanced) {
this._vaf.subCommit(bb._index, 1);
} else {
this._vaf.subCommit(bb._index * 4, 4);
}
}
this._vaf.endSubCommits();
}
this._billboardsToUpdateIndex = 0;
}
if (billboardsToUpdateLength > billboardsLength * 1.5) {
billboardsToUpdate.length = billboardsLength;
}
if (!defined_default(this._vaf) || !defined_default(this._vaf.va)) {
return;
}
if (this._boundingVolumeDirty) {
this._boundingVolumeDirty = false;
BoundingSphere_default.transform(
this._baseVolume,
this.modelMatrix,
this._baseVolumeWC
);
}
let boundingVolume;
let modelMatrix = Matrix4_default.IDENTITY;
if (frameState.mode === SceneMode_default.SCENE3D) {
modelMatrix = this.modelMatrix;
boundingVolume = BoundingSphere_default.clone(
this._baseVolumeWC,
this._boundingVolume
);
} else {
boundingVolume = BoundingSphere_default.clone(
this._baseVolume2D,
this._boundingVolume
);
}
updateBoundingVolume(this, frameState, boundingVolume);
const blendOptionChanged = this._blendOption !== this.blendOption;
this._blendOption = this.blendOption;
if (blendOptionChanged) {
if (this._blendOption === BlendOption_default.OPAQUE || this._blendOption === BlendOption_default.OPAQUE_AND_TRANSLUCENT) {
this._rsOpaque = RenderState_default.fromCache({
depthTest: {
enabled: true,
func: WebGLConstants_default.LESS
},
depthMask: true
});
} else {
this._rsOpaque = void 0;
}
const useTranslucentDepthMask = this._blendOption === BlendOption_default.TRANSLUCENT;
if (this._blendOption === BlendOption_default.TRANSLUCENT || this._blendOption === BlendOption_default.OPAQUE_AND_TRANSLUCENT) {
this._rsTranslucent = RenderState_default.fromCache({
depthTest: {
enabled: true,
func: useTranslucentDepthMask ? WebGLConstants_default.LEQUAL : WebGLConstants_default.LESS
},
depthMask: useTranslucentDepthMask,
blending: BlendingState_default.ALPHA_BLEND
});
} else {
this._rsTranslucent = void 0;
}
}
this._shaderDisableDepthDistance = this._shaderDisableDepthDistance || frameState.minimumDisableDepthTestDistance !== 0;
let vsSource;
let fsSource;
let vs;
let fs;
let vertDefines;
const supportVSTextureReads = ContextLimits_default.maximumVertexTextureImageUnits > 0;
if (blendOptionChanged || this._shaderRotation !== this._compiledShaderRotation || this._shaderAlignedAxis !== this._compiledShaderAlignedAxis || this._shaderScaleByDistance !== this._compiledShaderScaleByDistance || this._shaderTranslucencyByDistance !== this._compiledShaderTranslucencyByDistance || this._shaderPixelOffsetScaleByDistance !== this._compiledShaderPixelOffsetScaleByDistance || this._shaderDistanceDisplayCondition !== this._compiledShaderDistanceDisplayCondition || this._shaderDisableDepthDistance !== this._compiledShaderDisableDepthDistance || this._shaderClampToGround !== this._compiledShaderClampToGround || this._sdf !== this._compiledSDF) {
vsSource = BillboardCollectionVS_default;
fsSource = BillboardCollectionFS_default;
vertDefines = [];
if (defined_default(this._batchTable)) {
vertDefines.push("VECTOR_TILE");
vsSource = this._batchTable.getVertexShaderCallback(
false,
"a_batchId",
void 0
)(vsSource);
fsSource = this._batchTable.getFragmentShaderCallback(
false,
void 0
)(fsSource);
}
vs = new ShaderSource_default({
defines: vertDefines,
sources: [vsSource]
});
if (this._instanced) {
vs.defines.push("INSTANCED");
}
if (this._shaderRotation) {
vs.defines.push("ROTATION");
}
if (this._shaderAlignedAxis) {
vs.defines.push("ALIGNED_AXIS");
}
if (this._shaderScaleByDistance) {
vs.defines.push("EYE_DISTANCE_SCALING");
}
if (this._shaderTranslucencyByDistance) {
vs.defines.push("EYE_DISTANCE_TRANSLUCENCY");
}
if (this._shaderPixelOffsetScaleByDistance) {
vs.defines.push("EYE_DISTANCE_PIXEL_OFFSET");
}
if (this._shaderDistanceDisplayCondition) {
vs.defines.push("DISTANCE_DISPLAY_CONDITION");
}
if (this._shaderDisableDepthDistance) {
vs.defines.push("DISABLE_DEPTH_DISTANCE");
}
if (this._shaderClampToGround) {
if (supportVSTextureReads) {
vs.defines.push("VERTEX_DEPTH_CHECK");
} else {
vs.defines.push("FRAGMENT_DEPTH_CHECK");
}
}
const sdfEdge = 1 - SDFSettings_default.CUTOFF;
if (this._sdf) {
vs.defines.push("SDF");
}
const vectorFragDefine = defined_default(this._batchTable) ? "VECTOR_TILE" : "";
if (this._blendOption === BlendOption_default.OPAQUE_AND_TRANSLUCENT) {
fs = new ShaderSource_default({
defines: ["OPAQUE", vectorFragDefine],
sources: [fsSource]
});
if (this._shaderClampToGround) {
if (supportVSTextureReads) {
fs.defines.push("VERTEX_DEPTH_CHECK");
} else {
fs.defines.push("FRAGMENT_DEPTH_CHECK");
}
}
if (this._sdf) {
fs.defines.push("SDF");
fs.defines.push(`SDF_EDGE ${sdfEdge}`);
}
this._sp = ShaderProgram_default.replaceCache({
context,
shaderProgram: this._sp,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations
});
fs = new ShaderSource_default({
defines: ["TRANSLUCENT", vectorFragDefine],
sources: [fsSource]
});
if (this._shaderClampToGround) {
if (supportVSTextureReads) {
fs.defines.push("VERTEX_DEPTH_CHECK");
} else {
fs.defines.push("FRAGMENT_DEPTH_CHECK");
}
}
if (this._sdf) {
fs.defines.push("SDF");
fs.defines.push(`SDF_EDGE ${sdfEdge}`);
}
this._spTranslucent = ShaderProgram_default.replaceCache({
context,
shaderProgram: this._spTranslucent,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations
});
}
if (this._blendOption === BlendOption_default.OPAQUE) {
fs = new ShaderSource_default({
defines: [vectorFragDefine],
sources: [fsSource]
});
if (this._shaderClampToGround) {
if (supportVSTextureReads) {
fs.defines.push("VERTEX_DEPTH_CHECK");
} else {
fs.defines.push("FRAGMENT_DEPTH_CHECK");
}
}
if (this._sdf) {
fs.defines.push("SDF");
fs.defines.push(`SDF_EDGE ${sdfEdge}`);
}
this._sp = ShaderProgram_default.replaceCache({
context,
shaderProgram: this._sp,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations
});
}
if (this._blendOption === BlendOption_default.TRANSLUCENT) {
fs = new ShaderSource_default({
defines: [vectorFragDefine],
sources: [fsSource]
});
if (this._shaderClampToGround) {
if (supportVSTextureReads) {
fs.defines.push("VERTEX_DEPTH_CHECK");
} else {
fs.defines.push("FRAGMENT_DEPTH_CHECK");
}
}
if (this._sdf) {
fs.defines.push("SDF");
fs.defines.push(`SDF_EDGE ${sdfEdge}`);
}
this._spTranslucent = ShaderProgram_default.replaceCache({
context,
shaderProgram: this._spTranslucent,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations
});
}
this._compiledShaderRotation = this._shaderRotation;
this._compiledShaderAlignedAxis = this._shaderAlignedAxis;
this._compiledShaderScaleByDistance = this._shaderScaleByDistance;
this._compiledShaderTranslucencyByDistance = this._shaderTranslucencyByDistance;
this._compiledShaderPixelOffsetScaleByDistance = this._shaderPixelOffsetScaleByDistance;
this._compiledShaderDistanceDisplayCondition = this._shaderDistanceDisplayCondition;
this._compiledShaderDisableDepthDistance = this._shaderDisableDepthDistance;
this._compiledShaderClampToGround = this._shaderClampToGround;
this._compiledSDF = this._sdf;
}
const commandList = frameState.commandList;
if (pass.render || pass.pick) {
const colorList = this._colorCommands;
const opaque = this._blendOption === BlendOption_default.OPAQUE;
const opaqueAndTranslucent = this._blendOption === BlendOption_default.OPAQUE_AND_TRANSLUCENT;
const va = this._vaf.va;
const vaLength = va.length;
let uniforms = this._uniforms;
let pickId;
if (defined_default(this._batchTable)) {
uniforms = this._batchTable.getUniformMapCallback()(uniforms);
pickId = this._batchTable.getPickId();
} else {
pickId = "v_pickColor";
}
colorList.length = vaLength;
const totalLength = opaqueAndTranslucent ? vaLength * 2 : vaLength;
for (let j = 0; j < totalLength; ++j) {
let command = colorList[j];
if (!defined_default(command)) {
command = colorList[j] = new DrawCommand_default();
}
const opaqueCommand = opaque || opaqueAndTranslucent && j % 2 === 0;
command.pass = opaqueCommand || !opaqueAndTranslucent ? Pass_default.OPAQUE : Pass_default.TRANSLUCENT;
command.owner = this;
const index = opaqueAndTranslucent ? Math.floor(j / 2) : j;
command.boundingVolume = boundingVolume;
command.modelMatrix = modelMatrix;
command.count = va[index].indicesCount;
command.shaderProgram = opaqueCommand ? this._sp : this._spTranslucent;
command.uniformMap = uniforms;
command.vertexArray = va[index].va;
command.renderState = opaqueCommand ? this._rsOpaque : this._rsTranslucent;
command.debugShowBoundingVolume = this.debugShowBoundingVolume;
command.pickId = pickId;
if (this._instanced) {
command.count = 6;
command.instanceCount = billboardsLength;
}
commandList.push(command);
}
if (this.debugShowTextureAtlas) {
if (!defined_default(this.debugCommand)) {
this.debugCommand = createDebugCommand(this, frameState.context);
}
commandList.push(this.debugCommand);
}
}
this._allBillboardsReady = allBillboardsReady;
};
BillboardCollection.prototype.isDestroyed = function() {
return false;
};
BillboardCollection.prototype.destroy = function() {
if (defined_default(this._removeCallbackFunc)) {
this._removeCallbackFunc();
this._removeCallbackFunc = void 0;
}
this._textureAtlas = this._destroyTextureAtlas && this._textureAtlas && this._textureAtlas.destroy();
this._sp = this._sp && this._sp.destroy();
this._spTranslucent = this._spTranslucent && this._spTranslucent.destroy();
this._vaf = this._vaf && this._vaf.destroy();
destroyBillboards(this._billboards);
return destroyObject_default(this);
};
var BillboardCollection_default = BillboardCollection;
// packages/engine/Source/Scene/Cesium3DTilePointFeature.js
var import_InlineWorkers748 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/createBillboardPointCallback.js
var import_InlineWorkers747 = __toESM(require_InlineWorkers(), 1);
function createBillboardPointCallback(centerAlpha, cssColor, cssOutlineColor, cssOutlineWidth, pixelSize) {
return function() {
const canvas = document.createElement("canvas");
const length2 = pixelSize + 2 * cssOutlineWidth;
canvas.height = canvas.width = length2;
const context2D = canvas.getContext("2d");
context2D.clearRect(0, 0, length2, length2);
if (cssOutlineWidth !== 0) {
context2D.beginPath();
context2D.arc(length2 / 2, length2 / 2, length2 / 2, 0, 2 * Math.PI, true);
context2D.closePath();
context2D.fillStyle = cssOutlineColor;
context2D.fill();
if (centerAlpha < 1) {
context2D.save();
context2D.globalCompositeOperation = "destination-out";
context2D.beginPath();
context2D.arc(
length2 / 2,
length2 / 2,
pixelSize / 2,
0,
2 * Math.PI,
true
);
context2D.closePath();
context2D.fillStyle = "black";
context2D.fill();
context2D.restore();
}
}
context2D.beginPath();
context2D.arc(length2 / 2, length2 / 2, pixelSize / 2, 0, 2 * Math.PI, true);
context2D.closePath();
context2D.fillStyle = cssColor;
context2D.fill();
return canvas;
};
}
var createBillboardPointCallback_default = createBillboardPointCallback;
// packages/engine/Source/Scene/Cesium3DTilePointFeature.js
function Cesium3DTilePointFeature(content, batchId, billboard, label, polyline) {
this._content = content;
this._billboard = billboard;
this._label = label;
this._polyline = polyline;
this._batchId = batchId;
this._billboardImage = void 0;
this._billboardColor = void 0;
this._billboardOutlineColor = void 0;
this._billboardOutlineWidth = void 0;
this._billboardSize = void 0;
this._pointSize = void 0;
this._color = void 0;
this._pointSize = void 0;
this._pointOutlineColor = void 0;
this._pointOutlineWidth = void 0;
this._heightOffset = void 0;
this._pickIds = new Array(3);
setBillboardImage(this);
}
var scratchCartographic7 = new Cartographic_default();
Object.defineProperties(Cesium3DTilePointFeature.prototype, {
/**
* Gets or sets if the feature will be shown. This is set for all features
* when a style's show is evaluated.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {boolean}
*
* @default true
*/
show: {
get: function() {
return this._label.show;
},
set: function(value) {
this._label.show = value;
this._billboard.show = value;
this._polyline.show = value;
}
},
/**
* Gets or sets the color of the point of this feature.
*
* Only applied when image is undefined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {Color}
*/
color: {
get: function() {
return this._color;
},
set: function(value) {
this._color = Color_default.clone(value, this._color);
setBillboardImage(this);
}
},
/**
* Gets or sets the point size of this feature.
*
* Only applied when image is undefined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {number}
*/
pointSize: {
get: function() {
return this._pointSize;
},
set: function(value) {
this._pointSize = value;
setBillboardImage(this);
}
},
/**
* Gets or sets the point outline color of this feature.
*
* Only applied when image is undefined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {Color}
*/
pointOutlineColor: {
get: function() {
return this._pointOutlineColor;
},
set: function(value) {
this._pointOutlineColor = Color_default.clone(value, this._pointOutlineColor);
setBillboardImage(this);
}
},
/**
* Gets or sets the point outline width in pixels of this feature.
*
* Only applied when image is undefined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {number}
*/
pointOutlineWidth: {
get: function() {
return this._pointOutlineWidth;
},
set: function(value) {
this._pointOutlineWidth = value;
setBillboardImage(this);
}
},
/**
* Gets or sets the label color of this feature.
*
* The color will be applied to the label if labelText is defined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {Color}
*/
labelColor: {
get: function() {
return this._label.fillColor;
},
set: function(value) {
this._label.fillColor = value;
this._polyline.show = this._label.show && value.alpha > 0;
}
},
/**
* Gets or sets the label outline color of this feature.
*
* The outline color will be applied to the label if labelText is defined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {Color}
*/
labelOutlineColor: {
get: function() {
return this._label.outlineColor;
},
set: function(value) {
this._label.outlineColor = value;
}
},
/**
* Gets or sets the outline width in pixels of this feature.
*
* The outline width will be applied to the point if labelText is defined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {number}
*/
labelOutlineWidth: {
get: function() {
return this._label.outlineWidth;
},
set: function(value) {
this._label.outlineWidth = value;
}
},
/**
* Gets or sets the font of this feature.
*
* Only applied when the labelText is defined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {string}
*/
font: {
get: function() {
return this._label.font;
},
set: function(value) {
this._label.font = value;
}
},
/**
* Gets or sets the fill and outline style of this feature.
*
* Only applied when labelText is defined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {LabelStyle}
*/
labelStyle: {
get: function() {
return this._label.style;
},
set: function(value) {
this._label.style = value;
}
},
/**
* Gets or sets the text for this feature.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {string}
*/
labelText: {
get: function() {
return this._label.text;
},
set: function(value) {
if (!defined_default(value)) {
value = "";
}
this._label.text = value;
}
},
/**
* Gets or sets the background color of the text for this feature.
*
* Only applied when labelText is defined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {Color}
*/
backgroundColor: {
get: function() {
return this._label.backgroundColor;
},
set: function(value) {
this._label.backgroundColor = value;
}
},
/**
* Gets or sets the background padding of the text for this feature.
*
* Only applied when labelText is defined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {Cartesian2}
*/
backgroundPadding: {
get: function() {
return this._label.backgroundPadding;
},
set: function(value) {
this._label.backgroundPadding = value;
}
},
/**
* Gets or sets whether to display the background of the text for this feature.
*
* Only applied when labelText is defined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {boolean}
*/
backgroundEnabled: {
get: function() {
return this._label.showBackground;
},
set: function(value) {
this._label.showBackground = value;
}
},
/**
* Gets or sets the near and far scaling properties for this feature.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {NearFarScalar}
*/
scaleByDistance: {
get: function() {
return this._label.scaleByDistance;
},
set: function(value) {
this._label.scaleByDistance = value;
this._billboard.scaleByDistance = value;
}
},
/**
* Gets or sets the near and far translucency properties for this feature.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {NearFarScalar}
*/
translucencyByDistance: {
get: function() {
return this._label.translucencyByDistance;
},
set: function(value) {
this._label.translucencyByDistance = value;
this._billboard.translucencyByDistance = value;
}
},
/**
* Gets or sets the condition specifying at what distance from the camera that this feature will be displayed.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {DistanceDisplayCondition}
*/
distanceDisplayCondition: {
get: function() {
return this._label.distanceDisplayCondition;
},
set: function(value) {
this._label.distanceDisplayCondition = value;
this._polyline.distanceDisplayCondition = value;
this._billboard.distanceDisplayCondition = value;
}
},
/**
* Gets or sets the height offset in meters of this feature.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {number}
*/
heightOffset: {
get: function() {
return this._heightOffset;
},
set: function(value) {
const offset = this._heightOffset ?? 0;
const ellipsoid = this._content.tileset.ellipsoid;
const cart = ellipsoid.cartesianToCartographic(
this._billboard.position,
scratchCartographic7
);
cart.height = cart.height - offset + value;
const newPosition = ellipsoid.cartographicToCartesian(cart);
this._billboard.position = newPosition;
this._label.position = this._billboard.position;
this._polyline.positions = [this._polyline.positions[0], newPosition];
this._heightOffset = value;
}
},
/**
* Gets or sets whether the anchor line is displayed.
*
* Only applied when heightOffset is defined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {boolean}
*/
anchorLineEnabled: {
get: function() {
return this._polyline.show;
},
set: function(value) {
this._polyline.show = value;
}
},
/**
* Gets or sets the color for the anchor line.
*
* Only applied when heightOffset is defined.
*
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {Color}
*/
anchorLineColor: {
get: function() {
return this._polyline.material.uniforms.color;
},
set: function(value) {
this._polyline.material.uniforms.color = Color_default.clone(
value,
this._polyline.material.uniforms.color
);
}
},
/**
* Gets or sets the image of this feature.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {string}
*/
image: {
get: function() {
return this._billboardImage;
},
set: function(value) {
const imageChanged = this._billboardImage !== value;
this._billboardImage = value;
if (imageChanged) {
setBillboardImage(this);
}
}
},
/**
* Gets or sets the distance where depth testing will be disabled.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {number}
*/
disableDepthTestDistance: {
get: function() {
return this._label.disableDepthTestDistance;
},
set: function(value) {
this._label.disableDepthTestDistance = value;
this._billboard.disableDepthTestDistance = value;
}
},
/**
* Gets or sets the horizontal origin of this point, which determines if the point is
* to the left, center, or right of its anchor position.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {HorizontalOrigin}
*/
horizontalOrigin: {
get: function() {
return this._billboard.horizontalOrigin;
},
set: function(value) {
this._billboard.horizontalOrigin = value;
}
},
/**
* Gets or sets the vertical origin of this point, which determines if the point is
* to the bottom, center, or top of its anchor position.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {VerticalOrigin}
*/
verticalOrigin: {
get: function() {
return this._billboard.verticalOrigin;
},
set: function(value) {
this._billboard.verticalOrigin = value;
}
},
/**
* Gets or sets the horizontal origin of this point's text, which determines if the point's text is
* to the left, center, or right of its anchor position.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {HorizontalOrigin}
*/
labelHorizontalOrigin: {
get: function() {
return this._label.horizontalOrigin;
},
set: function(value) {
this._label.horizontalOrigin = value;
}
},
/**
* Get or sets the vertical origin of this point's text, which determines if the point's text is
* to the bottom, center, top, or baseline of it's anchor point.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {VerticalOrigin}
*/
labelVerticalOrigin: {
get: function() {
return this._label.verticalOrigin;
},
set: function(value) {
this._label.verticalOrigin = value;
}
},
/**
* Gets the content of the tile containing the feature.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {Cesium3DTileContent}
*
* @readonly
* @private
*/
content: {
get: function() {
return this._content;
}
},
/**
* Gets the tileset containing the feature.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {Cesium3DTileset}
*
* @readonly
*/
tileset: {
get: function() {
return this._content.tileset;
}
},
/**
* All objects returned by {@link Scene#pick} have a primitive property. This returns
* the tileset containing the feature.
*
* @memberof Cesium3DTilePointFeature.prototype
*
* @type {Cesium3DTileset}
*
* @readonly
*/
primitive: {
get: function() {
return this._content.tileset;
}
},
/**
* @private
*/
pickIds: {
get: function() {
const ids = this._pickIds;
ids[0] = this._billboard.pickId;
ids[1] = this._label.pickId;
ids[2] = this._polyline.pickId;
return ids;
}
}
});
Cesium3DTilePointFeature.defaultColor = Color_default.WHITE;
Cesium3DTilePointFeature.defaultPointOutlineColor = Color_default.BLACK;
Cesium3DTilePointFeature.defaultPointOutlineWidth = 0;
Cesium3DTilePointFeature.defaultPointSize = 8;
function setBillboardImage(feature2) {
const b = feature2._billboard;
if (defined_default(feature2._billboardImage) && feature2._billboardImage !== b.image) {
b.image = feature2._billboardImage;
return;
}
if (defined_default(feature2._billboardImage)) {
return;
}
const newColor = feature2._color ?? Cesium3DTilePointFeature.defaultColor;
const newOutlineColor = feature2._pointOutlineColor ?? Cesium3DTilePointFeature.defaultPointOutlineColor;
const newOutlineWidth = feature2._pointOutlineWidth ?? Cesium3DTilePointFeature.defaultPointOutlineWidth;
const newPointSize = feature2._pointSize ?? Cesium3DTilePointFeature.defaultPointSize;
const currentColor = feature2._billboardColor;
const currentOutlineColor = feature2._billboardOutlineColor;
const currentOutlineWidth = feature2._billboardOutlineWidth;
const currentPointSize = feature2._billboardSize;
if (Color_default.equals(newColor, currentColor) && Color_default.equals(newOutlineColor, currentOutlineColor) && newOutlineWidth === currentOutlineWidth && newPointSize === currentPointSize) {
return;
}
feature2._billboardColor = Color_default.clone(newColor, feature2._billboardColor);
feature2._billboardOutlineColor = Color_default.clone(
newOutlineColor,
feature2._billboardOutlineColor
);
feature2._billboardOutlineWidth = newOutlineWidth;
feature2._billboardSize = newPointSize;
const centerAlpha = newColor.alpha;
const cssColor = newColor.toCssColorString();
const cssOutlineColor = newOutlineColor.toCssColorString();
const textureId = JSON.stringify([
cssColor,
newPointSize,
cssOutlineColor,
newOutlineWidth
]);
b.setImage(
textureId,
createBillboardPointCallback_default(
centerAlpha,
cssColor,
cssOutlineColor,
newOutlineWidth,
newPointSize
)
);
}
Cesium3DTilePointFeature.prototype.hasProperty = function(name) {
return this._content.batchTable.hasProperty(this._batchId, name);
};
Cesium3DTilePointFeature.prototype.getPropertyIds = function(results) {
return this._content.batchTable.getPropertyIds(this._batchId, results);
};
Cesium3DTilePointFeature.prototype.getProperty = function(name) {
return this._content.batchTable.getProperty(this._batchId, name);
};
Cesium3DTilePointFeature.prototype.getPropertyInherited = function(name) {
return Cesium3DTileFeature_default.getPropertyInherited(
this._content,
this._batchId,
name
);
};
Cesium3DTilePointFeature.prototype.setProperty = function(name, value) {
this._content.batchTable.setProperty(this._batchId, name, value);
this._content.featurePropertiesDirty = true;
};
Cesium3DTilePointFeature.prototype.isExactClass = function(className) {
return this._content.batchTable.isExactClass(this._batchId, className);
};
Cesium3DTilePointFeature.prototype.isClass = function(className) {
return this._content.batchTable.isClass(this._batchId, className);
};
Cesium3DTilePointFeature.prototype.getExactClassName = function() {
return this._content.batchTable.getExactClassName(this._batchId);
};
var Cesium3DTilePointFeature_default = Cesium3DTilePointFeature;
// packages/engine/Source/Scene/LabelCollection.js
var import_InlineWorkers752 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/writeTextToCanvas.js
var import_InlineWorkers749 = __toESM(require_InlineWorkers(), 1);
function measureText(context2D, textString, font, stroke, fill) {
const metrics = context2D.measureText(textString);
const isSpace = !/\S/.test(textString);
if (!isSpace) {
const fontSize = document.defaultView.getComputedStyle(context2D.canvas).getPropertyValue("font-size").replace("px", "");
const canvas = document.createElement("canvas");
const padding = 100;
const width = metrics.width + padding | 0;
const height = 3 * fontSize;
const baseline = height / 2;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
ctx.font = font;
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width + 1, canvas.height + 1);
if (stroke) {
ctx.strokeStyle = "black";
ctx.lineWidth = context2D.lineWidth;
ctx.strokeText(textString, padding / 2, baseline);
}
if (fill) {
ctx.fillStyle = "black";
ctx.fillText(textString, padding / 2, baseline);
}
const pixelData = ctx.getImageData(0, 0, width, height).data;
const length2 = pixelData.length;
const width4 = width * 4;
let i, j;
let ascent, descent;
for (i = 0; i < length2; ++i) {
if (pixelData[i] !== 255) {
ascent = i / width4 | 0;
break;
}
}
for (i = length2 - 1; i >= 0; --i) {
if (pixelData[i] !== 255) {
descent = i / width4 | 0;
break;
}
}
let minx = -1;
for (i = 0; i < width && minx === -1; ++i) {
for (j = 0; j < height; ++j) {
const pixelIndex = i * 4 + j * width4;
if (pixelData[pixelIndex] !== 255 || pixelData[pixelIndex + 1] !== 255 || pixelData[pixelIndex + 2] !== 255 || pixelData[pixelIndex + 3] !== 255) {
minx = i;
break;
}
}
}
return {
width: metrics.width,
height: descent - ascent,
ascent: baseline - ascent,
descent: descent - baseline,
minx: minx - padding / 2
};
}
return {
width: metrics.width,
height: 0,
ascent: 0,
descent: 0,
minx: 0
};
}
var imageSmoothingEnabledName;
function writeTextToCanvas(text2, options) {
if (!defined_default(text2)) {
throw new DeveloperError_default("text is required.");
}
if (text2 === "") {
return void 0;
}
options = options ?? Frozen_default.EMPTY_OBJECT;
const font = options.font ?? "10px sans-serif";
const stroke = options.stroke ?? false;
const fill = options.fill ?? true;
const strokeWidth = options.strokeWidth ?? 1;
const backgroundColor = options.backgroundColor ?? Color_default.TRANSPARENT;
const padding = options.padding ?? 0;
const doublePadding = padding * 2;
const canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = 1;
canvas.style.font = font;
const context2D = canvas.getContext("2d", { willReadFrequently: true });
if (!defined_default(imageSmoothingEnabledName)) {
if (defined_default(context2D.imageSmoothingEnabled)) {
imageSmoothingEnabledName = "imageSmoothingEnabled";
} else if (defined_default(context2D.mozImageSmoothingEnabled)) {
imageSmoothingEnabledName = "mozImageSmoothingEnabled";
} else if (defined_default(context2D.webkitImageSmoothingEnabled)) {
imageSmoothingEnabledName = "webkitImageSmoothingEnabled";
} else if (defined_default(context2D.msImageSmoothingEnabled)) {
imageSmoothingEnabledName = "msImageSmoothingEnabled";
}
}
context2D.font = font;
context2D.lineJoin = "round";
context2D.lineWidth = strokeWidth;
context2D[imageSmoothingEnabledName] = false;
canvas.style.visibility = "hidden";
document.body.appendChild(canvas);
const dimensions = measureText(context2D, text2, font, stroke, fill);
canvas.dimensions = dimensions;
document.body.removeChild(canvas);
canvas.style.visibility = "";
const x = -dimensions.minx;
const width = Math.ceil(dimensions.width) + x + doublePadding;
const height = dimensions.height + doublePadding;
const baseline = height - dimensions.ascent + padding;
const y = height - baseline + doublePadding;
canvas.width = width;
canvas.height = height;
context2D.font = font;
context2D.lineJoin = "round";
context2D.lineWidth = strokeWidth;
context2D[imageSmoothingEnabledName] = false;
if (backgroundColor !== Color_default.TRANSPARENT) {
context2D.fillStyle = backgroundColor.toCssColorString();
context2D.fillRect(0, 0, canvas.width, canvas.height);
}
if (stroke) {
const strokeColor = options.strokeColor ?? Color_default.BLACK;
context2D.strokeStyle = strokeColor.toCssColorString();
context2D.strokeText(text2, x + padding, y);
}
if (fill) {
const fillColor = options.fillColor ?? Color_default.WHITE;
context2D.fillStyle = fillColor.toCssColorString();
context2D.fillText(text2, x + padding, y);
}
return canvas;
}
var writeTextToCanvas_default = writeTextToCanvas;
// packages/engine/Source/Scene/LabelCollection.js
var import_bitmap_sdf = __toESM(require_bitmap_sdf(), 1);
// packages/engine/Source/Scene/Label.js
var import_InlineWorkers751 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/LabelStyle.js
var import_InlineWorkers750 = __toESM(require_InlineWorkers(), 1);
var LabelStyle = {
/**
* Fill the text of the label, but do not outline.
*
* @type {number}
* @constant
*/
FILL: 0,
/**
* Outline the text of the label, but do not fill.
*
* @type {number}
* @constant
*/
OUTLINE: 1,
/**
* Fill and outline the text of the label.
*
* @type {number}
* @constant
*/
FILL_AND_OUTLINE: 2
};
var LabelStyle_default = Object.freeze(LabelStyle);
// packages/engine/Source/Scene/Label.js
var fontInfoCache = {};
var fontInfoCacheLength = 0;
var fontInfoCacheMaxSize = 256;
var defaultBackgroundColor = new Color_default(0.165, 0.165, 0.165, 0.8);
var defaultBackgroundPadding = new Cartesian2_default(7, 5);
var textTypes = Object.freeze({
LTR: 0,
RTL: 1,
WEAK: 2,
BRACKETS: 3
});
function rebindAllGlyphs(label) {
if (!label._rebindAllGlyphs && !label._repositionAllGlyphs) {
label._labelCollection._labelsToUpdate.push(label);
}
label._rebindAllGlyphs = true;
}
function repositionAllGlyphs(label) {
if (!label._rebindAllGlyphs && !label._repositionAllGlyphs) {
label._labelCollection._labelsToUpdate.push(label);
}
label._repositionAllGlyphs = true;
}
function getCSSValue(element, property) {
return document.defaultView.getComputedStyle(element, null).getPropertyValue(property);
}
function parseFont(label) {
let fontInfo = fontInfoCache[label._font];
if (!defined_default(fontInfo)) {
const div = document.createElement("div");
div.style.position = "absolute";
div.style.opacity = 0;
div.style.font = label._font;
document.body.appendChild(div);
let lineHeight = parseFloat(getCSSValue(div, "line-height"));
if (isNaN(lineHeight)) {
lineHeight = void 0;
}
fontInfo = {
family: getCSSValue(div, "font-family"),
size: getCSSValue(div, "font-size").replace("px", ""),
style: getCSSValue(div, "font-style"),
weight: getCSSValue(div, "font-weight"),
lineHeight
};
document.body.removeChild(div);
if (fontInfoCacheLength < fontInfoCacheMaxSize) {
fontInfoCache[label._font] = fontInfo;
fontInfoCacheLength++;
}
}
label._fontFamily = fontInfo.family;
label._fontSize = fontInfo.size;
label._fontStyle = fontInfo.style;
label._fontWeight = fontInfo.weight;
label._lineHeight = fontInfo.lineHeight;
}
function Label(options, labelCollection) {
options = options ?? Frozen_default.EMPTY_OBJECT;
if (defined_default(options.disableDepthTestDistance) && options.disableDepthTestDistance < 0) {
throw new DeveloperError_default(
"disableDepthTestDistance must be greater than 0.0."
);
}
let translucencyByDistance = options.translucencyByDistance;
let pixelOffsetScaleByDistance = options.pixelOffsetScaleByDistance;
let scaleByDistance = options.scaleByDistance;
let distanceDisplayCondition = options.distanceDisplayCondition;
if (defined_default(translucencyByDistance)) {
if (translucencyByDistance.far <= translucencyByDistance.near) {
throw new DeveloperError_default(
"translucencyByDistance.far must be greater than translucencyByDistance.near."
);
}
translucencyByDistance = NearFarScalar_default.clone(translucencyByDistance);
}
if (defined_default(pixelOffsetScaleByDistance)) {
if (pixelOffsetScaleByDistance.far <= pixelOffsetScaleByDistance.near) {
throw new DeveloperError_default(
"pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near."
);
}
pixelOffsetScaleByDistance = NearFarScalar_default.clone(
pixelOffsetScaleByDistance
);
}
if (defined_default(scaleByDistance)) {
if (scaleByDistance.far <= scaleByDistance.near) {
throw new DeveloperError_default(
"scaleByDistance.far must be greater than scaleByDistance.near."
);
}
scaleByDistance = NearFarScalar_default.clone(scaleByDistance);
}
if (defined_default(distanceDisplayCondition)) {
if (distanceDisplayCondition.far <= distanceDisplayCondition.near) {
throw new DeveloperError_default(
"distanceDisplayCondition.far must be greater than distanceDisplayCondition.near."
);
}
distanceDisplayCondition = DistanceDisplayCondition_default.clone(
distanceDisplayCondition
);
}
this._renderedText = void 0;
this._text = void 0;
this._show = options.show ?? true;
this._font = options.font ?? "30px sans-serif";
this._fillColor = Color_default.clone(options.fillColor ?? Color_default.WHITE);
this._outlineColor = Color_default.clone(options.outlineColor ?? Color_default.BLACK);
this._outlineWidth = options.outlineWidth ?? 1;
this._showBackground = options.showBackground ?? false;
this._backgroundColor = Color_default.clone(
options.backgroundColor ?? defaultBackgroundColor
);
this._backgroundPadding = Cartesian2_default.clone(
options.backgroundPadding ?? defaultBackgroundPadding
);
this._style = options.style ?? LabelStyle_default.FILL;
this._verticalOrigin = options.verticalOrigin ?? VerticalOrigin_default.BASELINE;
this._horizontalOrigin = options.horizontalOrigin ?? HorizontalOrigin_default.LEFT;
this._pixelOffset = Cartesian2_default.clone(options.pixelOffset ?? Cartesian2_default.ZERO);
this._eyeOffset = Cartesian3_default.clone(options.eyeOffset ?? Cartesian3_default.ZERO);
this._position = Cartesian3_default.clone(options.position ?? Cartesian3_default.ZERO);
this._scale = options.scale ?? 1;
this._id = options.id;
this._translucencyByDistance = translucencyByDistance;
this._pixelOffsetScaleByDistance = pixelOffsetScaleByDistance;
this._scaleByDistance = scaleByDistance;
this._heightReference = options.heightReference ?? HeightReference_default.NONE;
this._distanceDisplayCondition = distanceDisplayCondition;
this._disableDepthTestDistance = options.disableDepthTestDistance;
this._labelCollection = labelCollection;
this._glyphs = [];
this._backgroundBillboard = void 0;
this._batchIndex = void 0;
this._rebindAllGlyphs = true;
this._repositionAllGlyphs = true;
this._actualClampedPosition = void 0;
this._removeCallbackFunc = void 0;
this._mode = void 0;
this._clusterShow = true;
this.text = options.text ?? "";
this._relativeSize = 1;
parseFont(this);
this._updateClamping();
}
Object.defineProperties(Label.prototype, {
/**
* Determines if this label will be shown. Use this to hide or show a label, instead
* of removing it and re-adding it to the collection.
* @memberof Label.prototype
* @type {boolean}
* @default true
*/
show: {
get: function() {
return this._show;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._show !== value) {
this._show = value;
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const billboard = glyphs[i].billboard;
if (defined_default(billboard)) {
billboard.show = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.show = value;
}
}
}
},
/**
* Gets or sets the Cartesian position of this label.
* @memberof Label.prototype
* @type {Cartesian3}
*/
position: {
get: function() {
return this._position;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const position = this._position;
if (!Cartesian3_default.equals(position, value)) {
Cartesian3_default.clone(value, position);
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const billboard = glyphs[i].billboard;
if (defined_default(billboard)) {
billboard.position = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.position = value;
}
this._updateClamping();
}
}
},
/**
* Gets or sets the height reference of this billboard.
* @memberof Label.prototype
* @type {HeightReference}
* @default HeightReference.NONE
*/
heightReference: {
get: function() {
return this._heightReference;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (value !== this._heightReference) {
this._heightReference = value;
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const billboard = glyphs[i].billboard;
if (defined_default(billboard)) {
billboard.heightReference = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.heightReference = value;
}
repositionAllGlyphs(this);
this._updateClamping();
}
}
},
/**
* Gets or sets the text of this label.
* @memberof Label.prototype
* @type {string}
*/
text: {
get: function() {
return this._text;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._text !== value) {
this._text = value;
const renderedValue = Label.filterUnsupportedCharacters(value);
this._renderedText = Label.enableRightToLeftDetection ? reverseRtl(renderedValue) : renderedValue;
rebindAllGlyphs(this);
}
}
},
/**
* Gets or sets the font used to draw this label. Fonts are specified using the same syntax as the CSS 'font' property.
* @memberof Label.prototype
* @type {string}
* @default '30px sans-serif'
* @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles|HTML canvas 2D context text styles}
*/
font: {
get: function() {
return this._font;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._font !== value) {
this._font = value;
rebindAllGlyphs(this);
parseFont(this);
}
}
},
/**
* Gets or sets the fill color of this label.
* @memberof Label.prototype
* @type {Color}
* @default Color.WHITE
* @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#fill-and-stroke-styles|HTML canvas 2D context fill and stroke styles}
*/
fillColor: {
get: function() {
return this._fillColor;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const fillColor = this._fillColor;
if (!Color_default.equals(fillColor, value)) {
Color_default.clone(value, fillColor);
rebindAllGlyphs(this);
}
}
},
/**
* Gets or sets the outline color of this label.
* @memberof Label.prototype
* @type {Color}
* @default Color.BLACK
* @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#fill-and-stroke-styles|HTML canvas 2D context fill and stroke styles}
*/
outlineColor: {
get: function() {
return this._outlineColor;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const outlineColor = this._outlineColor;
if (!Color_default.equals(outlineColor, value)) {
Color_default.clone(value, outlineColor);
rebindAllGlyphs(this);
}
}
},
/**
* Gets or sets the outline width of this label.
* @memberof Label.prototype
* @type {number}
* @default 1.0
* @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#fill-and-stroke-styles|HTML canvas 2D context fill and stroke styles}
*/
outlineWidth: {
get: function() {
return this._outlineWidth;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._outlineWidth !== value) {
this._outlineWidth = value;
rebindAllGlyphs(this);
}
}
},
/**
* Determines if a background behind this label will be shown.
* @memberof Label.prototype
* @default false
* @type {boolean}
*/
showBackground: {
get: function() {
return this._showBackground;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._showBackground !== value) {
this._showBackground = value;
rebindAllGlyphs(this);
}
}
},
/**
* Gets or sets the background color of this label.
* @memberof Label.prototype
* @type {Color}
* @default new Color(0.165, 0.165, 0.165, 0.8)
*/
backgroundColor: {
get: function() {
return this._backgroundColor;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const backgroundColor = this._backgroundColor;
if (!Color_default.equals(backgroundColor, value)) {
Color_default.clone(value, backgroundColor);
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.color = backgroundColor;
}
}
}
},
/**
* Gets or sets the background padding, in pixels, of this label. The x value
* controls horizontal padding, and the y value controls vertical padding.
* @memberof Label.prototype
* @type {Cartesian2}
* @default new Cartesian2(7, 5)
*/
backgroundPadding: {
get: function() {
return this._backgroundPadding;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const backgroundPadding = this._backgroundPadding;
if (!Cartesian2_default.equals(backgroundPadding, value)) {
Cartesian2_default.clone(value, backgroundPadding);
repositionAllGlyphs(this);
}
}
},
/**
* Gets or sets the style of this label.
* @memberof Label.prototype
* @type {LabelStyle}
* @default LabelStyle.FILL
*/
style: {
get: function() {
return this._style;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._style !== value) {
this._style = value;
rebindAllGlyphs(this);
}
}
},
/**
* Gets or sets the pixel offset in screen space from the origin of this label. This is commonly used
* to align multiple labels and billboards at the same position, e.g., an image and text. The
* screen space origin is the top, left corner of the canvas; x increases from
* left to right, and y increases from top to bottom.
*
*
*
* default

* l.pixeloffset = new Cartesian2(25, 75);

*
* The label's origin is indicated by the yellow point.
*
* @memberof Label.prototype
* @type {Cartesian2}
* @default Cartesian2.ZERO
*/
pixelOffset: {
get: function() {
return this._pixelOffset;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const pixelOffset = this._pixelOffset;
if (!Cartesian2_default.equals(pixelOffset, value)) {
Cartesian2_default.clone(value, pixelOffset);
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard.pixelOffset = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.pixelOffset = value;
}
}
}
},
/**
* Gets or sets near and far translucency properties of a Label based on the Label's distance from the camera.
* A label's translucency will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the label's translucency remains clamped to the nearest bound. If undefined,
* translucencyByDistance will be disabled.
* @memberof Label.prototype
* @type {NearFarScalar}
*
* @example
* // Example 1.
* // Set a label's translucencyByDistance to 1.0 when the
* // camera is 1500 meters from the label and disappear as
* // the camera distance approaches 8.0e6 meters.
* text.translucencyByDistance = new Cesium.NearFarScalar(1.5e2, 1.0, 8.0e6, 0.0);
*
* @example
* // Example 2.
* // disable translucency by distance
* text.translucencyByDistance = undefined;
*/
translucencyByDistance: {
get: function() {
return this._translucencyByDistance;
},
set: function(value) {
if (defined_default(value) && value.far <= value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
const translucencyByDistance = this._translucencyByDistance;
if (!NearFarScalar_default.equals(translucencyByDistance, value)) {
this._translucencyByDistance = NearFarScalar_default.clone(
value,
translucencyByDistance
);
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard.translucencyByDistance = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.translucencyByDistance = value;
}
}
}
},
/**
* Gets or sets near and far pixel offset scaling properties of a Label based on the Label's distance from the camera.
* A label's pixel offset will be scaled between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the label's pixel offset scaling remains clamped to the nearest bound. If undefined,
* pixelOffsetScaleByDistance will be disabled.
* @memberof Label.prototype
* @type {NearFarScalar}
*
* @example
* // Example 1.
* // Set a label's pixel offset scale to 0.0 when the
* // camera is 1500 meters from the label and scale pixel offset to 10.0 pixels
* // in the y direction the camera distance approaches 8.0e6 meters.
* text.pixelOffset = new Cesium.Cartesian2(0.0, 1.0);
* text.pixelOffsetScaleByDistance = new Cesium.NearFarScalar(1.5e2, 0.0, 8.0e6, 10.0);
*
* @example
* // Example 2.
* // disable pixel offset by distance
* text.pixelOffsetScaleByDistance = undefined;
*/
pixelOffsetScaleByDistance: {
get: function() {
return this._pixelOffsetScaleByDistance;
},
set: function(value) {
if (defined_default(value) && value.far <= value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
const pixelOffsetScaleByDistance = this._pixelOffsetScaleByDistance;
if (!NearFarScalar_default.equals(pixelOffsetScaleByDistance, value)) {
this._pixelOffsetScaleByDistance = NearFarScalar_default.clone(
value,
pixelOffsetScaleByDistance
);
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard.pixelOffsetScaleByDistance = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.pixelOffsetScaleByDistance = value;
}
}
}
},
/**
* Gets or sets near and far scaling properties of a Label based on the label's distance from the camera.
* A label's scale will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the label's scale remains clamped to the nearest bound. If undefined,
* scaleByDistance will be disabled.
* @memberof Label.prototype
* @type {NearFarScalar}
*
* @example
* // Example 1.
* // Set a label's scaleByDistance to scale by 1.5 when the
* // camera is 1500 meters from the label and disappear as
* // the camera distance approaches 8.0e6 meters.
* label.scaleByDistance = new Cesium.NearFarScalar(1.5e2, 1.5, 8.0e6, 0.0);
*
* @example
* // Example 2.
* // disable scaling by distance
* label.scaleByDistance = undefined;
*/
scaleByDistance: {
get: function() {
return this._scaleByDistance;
},
set: function(value) {
if (defined_default(value) && value.far <= value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
const scaleByDistance = this._scaleByDistance;
if (!NearFarScalar_default.equals(scaleByDistance, value)) {
this._scaleByDistance = NearFarScalar_default.clone(value, scaleByDistance);
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard.scaleByDistance = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.scaleByDistance = value;
}
}
}
},
/**
* Gets and sets the 3D Cartesian offset applied to this label in eye coordinates. Eye coordinates is a left-handed
* coordinate system, where x points towards the viewer's right, y points up, and
* z points into the screen. Eye coordinates use the same scale as world and model coordinates,
* which is typically meters.
*
* An eye offset is commonly used to arrange multiple label or objects at the same position, e.g., to
* arrange a label above its corresponding 3D model.
*
* Below, the label is positioned at the center of the Earth but an eye offset makes it always
* appear on top of the Earth regardless of the viewer's or Earth's orientation.
*
*
*
* 
* 
*
* l.eyeOffset = new Cartesian3(0.0, 8000000.0, 0.0);
*
* @memberof Label.prototype
* @type {Cartesian3}
* @default Cartesian3.ZERO
*/
eyeOffset: {
get: function() {
return this._eyeOffset;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const eyeOffset = this._eyeOffset;
if (!Cartesian3_default.equals(eyeOffset, value)) {
Cartesian3_default.clone(value, eyeOffset);
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard.eyeOffset = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.eyeOffset = value;
}
}
}
},
/**
* Gets or sets the horizontal origin of this label, which determines if the label is drawn
* to the left, center, or right of its anchor position.
*
*
* 
*
* @memberof Label.prototype
* @type {HorizontalOrigin}
* @default HorizontalOrigin.LEFT
* @example
* // Use a top, right origin
* l.horizontalOrigin = Cesium.HorizontalOrigin.RIGHT;
* l.verticalOrigin = Cesium.VerticalOrigin.TOP;
*/
horizontalOrigin: {
get: function() {
return this._horizontalOrigin;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._horizontalOrigin !== value) {
this._horizontalOrigin = value;
repositionAllGlyphs(this);
}
}
},
/**
* Gets or sets the vertical origin of this label, which determines if the label is
* to the above, below, or at the center of its anchor position.
*
*
* 
*
* @memberof Label.prototype
* @type {VerticalOrigin}
* @default VerticalOrigin.BASELINE
* @example
* // Use a top, right origin
* l.horizontalOrigin = Cesium.HorizontalOrigin.RIGHT;
* l.verticalOrigin = Cesium.VerticalOrigin.TOP;
*/
verticalOrigin: {
get: function() {
return this._verticalOrigin;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._verticalOrigin !== value) {
this._verticalOrigin = value;
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard.verticalOrigin = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.verticalOrigin = value;
}
repositionAllGlyphs(this);
}
}
},
/**
* Gets or sets the uniform scale that is multiplied with the label's size in pixels.
* A scale of 1.0 does not change the size of the label; a scale greater than
* 1.0 enlarges the label; a positive scale less than 1.0 shrinks
* the label.
*
* Applying a large scale value may pixelate the label. To make text larger without pixelation,
* use a larger font size when calling {@link Label#font} instead.
*
*
* 
* From left to right in the above image, the scales are 0.5, 1.0,
* and 2.0.
*
* @memberof Label.prototype
* @type {number}
* @default 1.0
*/
scale: {
get: function() {
return this._scale;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._scale !== value) {
this._scale = value;
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard.scale = value * this._relativeSize;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.scale = value * this._relativeSize;
}
repositionAllGlyphs(this);
}
}
},
/**
* Gets the total scale of the label, which is the label's scale multiplied by the computed relative size
* of the desired font compared to the generated glyph size.
* @memberof Label.prototype
* @type {number}
* @default 1.0
*/
totalScale: {
get: function() {
return this._scale * this._relativeSize;
}
},
/**
* Gets or sets the condition specifying at what distance from the camera that this label will be displayed.
* @memberof Label.prototype
* @type {DistanceDisplayCondition}
* @default undefined
*/
distanceDisplayCondition: {
get: function() {
return this._distanceDisplayCondition;
},
set: function(value) {
if (defined_default(value) && value.far <= value.near) {
throw new DeveloperError_default("far must be greater than near");
}
if (!DistanceDisplayCondition_default.equals(value, this._distanceDisplayCondition)) {
this._distanceDisplayCondition = DistanceDisplayCondition_default.clone(
value,
this._distanceDisplayCondition
);
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard.distanceDisplayCondition = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.distanceDisplayCondition = value;
}
}
}
},
/**
* Gets or sets the distance from the camera at which to disable the depth test to, for example, prevent clipping against terrain.
* When set to zero, the depth test is always applied. When set to Number.POSITIVE_INFINITY, the depth test is never applied.
* @memberof Label.prototype
* @type {number}
*/
disableDepthTestDistance: {
get: function() {
return this._disableDepthTestDistance;
},
set: function(value) {
if (this._disableDepthTestDistance !== value) {
if (defined_default(value) && value < 0) {
throw new DeveloperError_default(
"disableDepthTestDistance must be greater than 0.0."
);
}
this._disableDepthTestDistance = value;
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard.disableDepthTestDistance = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.disableDepthTestDistance = value;
}
}
}
},
/**
* Gets or sets the user-defined value returned when the label is picked.
* @memberof Label.prototype
* @type {*}
*/
id: {
get: function() {
return this._id;
},
set: function(value) {
if (this._id !== value) {
this._id = value;
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard.id = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.id = value;
}
}
}
},
/**
* @private
*/
pickId: {
get: function() {
if (this._glyphs.length === 0 || !defined_default(this._glyphs[0].billboard)) {
return void 0;
}
return this._glyphs[0].billboard.pickId;
}
},
/**
* Keeps track of the position of the label based on the height reference.
* @memberof Label.prototype
* @type {Cartesian3}
* @private
*/
_clampedPosition: {
get: function() {
return this._actualClampedPosition;
},
set: function(value) {
this._actualClampedPosition = Cartesian3_default.clone(
value,
this._actualClampedPosition
);
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard._clampedPosition = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard._clampedPosition = value;
}
}
},
/**
* Determines whether or not this label will be shown or hidden because it was clustered.
* @memberof Label.prototype
* @type {boolean}
* @default true
* @private
*/
clusterShow: {
get: function() {
return this._clusterShow;
},
set: function(value) {
if (this._clusterShow !== value) {
this._clusterShow = value;
const glyphs = this._glyphs;
for (let i = 0, len = glyphs.length; i < len; i++) {
const glyph = glyphs[i];
if (defined_default(glyph.billboard)) {
glyph.billboard.clusterShow = value;
}
}
const backgroundBillboard = this._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
backgroundBillboard.clusterShow = value;
}
}
}
}
});
Label.prototype._updateClamping = function() {
Billboard_default._updateClamping(this._labelCollection, this);
};
Label.prototype.computeScreenSpacePosition = function(scene, result) {
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required.");
}
if (!defined_default(result)) {
result = new Cartesian2_default();
}
const labelCollection = this._labelCollection;
const modelMatrix = labelCollection.modelMatrix;
const actualPosition = defined_default(this._actualClampedPosition) ? this._actualClampedPosition : this._position;
const windowCoordinates = Billboard_default._computeScreenSpacePosition(
modelMatrix,
actualPosition,
this._eyeOffset,
this._pixelOffset,
scene,
result
);
return windowCoordinates;
};
Label.getScreenSpaceBoundingBox = function(label, screenSpacePosition, result) {
let x = 0;
let y = 0;
let width = 0;
let height = 0;
const scale = label.totalScale;
const backgroundBillboard = label._backgroundBillboard;
if (defined_default(backgroundBillboard)) {
x = screenSpacePosition.x + backgroundBillboard._translate.x;
y = screenSpacePosition.y - backgroundBillboard._translate.y;
width = backgroundBillboard.width * scale;
height = backgroundBillboard.height * scale;
if (label.verticalOrigin === VerticalOrigin_default.BOTTOM || label.verticalOrigin === VerticalOrigin_default.BASELINE) {
y -= height;
} else if (label.verticalOrigin === VerticalOrigin_default.CENTER) {
y -= height * 0.5;
}
} else {
x = Number.POSITIVE_INFINITY;
y = Number.POSITIVE_INFINITY;
let maxX = 0;
let maxY = 0;
const glyphs = label._glyphs;
const length2 = glyphs.length;
for (let i = 0; i < length2; ++i) {
const glyph = glyphs[i];
const billboard = glyph.billboard;
if (!defined_default(billboard)) {
continue;
}
const glyphX = screenSpacePosition.x + billboard._translate.x;
let glyphY = screenSpacePosition.y - billboard._translate.y;
const glyphWidth = glyph.dimensions.width * scale;
const glyphHeight = glyph.dimensions.height * scale;
if (label.verticalOrigin === VerticalOrigin_default.BOTTOM || label.verticalOrigin === VerticalOrigin_default.BASELINE) {
glyphY -= glyphHeight;
} else if (label.verticalOrigin === VerticalOrigin_default.CENTER) {
glyphY -= glyphHeight * 0.5;
}
if (label._verticalOrigin === VerticalOrigin_default.TOP) {
glyphY += SDFSettings_default.PADDING * scale;
} else if (label._verticalOrigin === VerticalOrigin_default.BOTTOM || label._verticalOrigin === VerticalOrigin_default.BASELINE) {
glyphY -= SDFSettings_default.PADDING * scale;
}
x = Math.min(x, glyphX);
y = Math.min(y, glyphY);
maxX = Math.max(maxX, glyphX + glyphWidth);
maxY = Math.max(maxY, glyphY + glyphHeight);
}
width = maxX - x;
height = maxY - y;
}
if (!defined_default(result)) {
result = new BoundingRectangle_default();
}
result.x = x;
result.y = y;
result.width = width;
result.height = height;
return result;
};
Label.filterUnsupportedCharacters = function(text2) {
const problematicCharactersRegex = new RegExp(
// eslint-disable-next-line no-control-regex
/[\u0000-\u0008\u000E-\u001F\u00ad\u202a-\u206f\u200b-\u200f]/,
"g"
);
return text2.replace(problematicCharactersRegex, "");
};
Label.prototype.equals = function(other) {
return this === other || defined_default(other) && this._show === other._show && this._scale === other._scale && this._outlineWidth === other._outlineWidth && this._showBackground === other._showBackground && this._style === other._style && this._verticalOrigin === other._verticalOrigin && this._horizontalOrigin === other._horizontalOrigin && this._heightReference === other._heightReference && this._renderedText === other._renderedText && this._font === other._font && Cartesian3_default.equals(this._position, other._position) && Color_default.equals(this._fillColor, other._fillColor) && Color_default.equals(this._outlineColor, other._outlineColor) && Color_default.equals(this._backgroundColor, other._backgroundColor) && Cartesian2_default.equals(this._backgroundPadding, other._backgroundPadding) && Cartesian2_default.equals(this._pixelOffset, other._pixelOffset) && Cartesian3_default.equals(this._eyeOffset, other._eyeOffset) && NearFarScalar_default.equals(
this._translucencyByDistance,
other._translucencyByDistance
) && NearFarScalar_default.equals(
this._pixelOffsetScaleByDistance,
other._pixelOffsetScaleByDistance
) && NearFarScalar_default.equals(this._scaleByDistance, other._scaleByDistance) && DistanceDisplayCondition_default.equals(
this._distanceDisplayCondition,
other._distanceDisplayCondition
) && this._disableDepthTestDistance === other._disableDepthTestDistance && this._id === other._id;
};
Label.prototype.isDestroyed = function() {
return false;
};
Label.enableRightToLeftDetection = false;
function convertTextToTypes(text2, rtlChars2) {
const ltrChars = /[a-zA-Z0-9]/;
const bracketsChars = /[()[\]{}<>]/;
const parsedText = [];
let word = "";
let lastType = textTypes.LTR;
let currentType = "";
const textLength = text2.length;
for (let textIndex = 0; textIndex < textLength; ++textIndex) {
const character = text2.charAt(textIndex);
if (rtlChars2.test(character)) {
currentType = textTypes.RTL;
} else if (ltrChars.test(character)) {
currentType = textTypes.LTR;
} else if (bracketsChars.test(character)) {
currentType = textTypes.BRACKETS;
} else {
currentType = textTypes.WEAK;
}
if (textIndex === 0) {
lastType = currentType;
}
if (lastType === currentType && currentType !== textTypes.BRACKETS) {
word += character;
} else {
if (word !== "") {
parsedText.push({ Type: lastType, Word: word });
}
lastType = currentType;
word = character;
}
}
parsedText.push({ Type: currentType, Word: word });
return parsedText;
}
function reverseWord(word) {
return word.split("").reverse().join("");
}
function spliceWord(result, pointer, word) {
return result.slice(0, pointer) + word + result.slice(pointer);
}
function reverseBrackets(bracket) {
switch (bracket) {
case "(":
return ")";
case ")":
return "(";
case "[":
return "]";
case "]":
return "[";
case "{":
return "}";
case "}":
return "{";
case "<":
return ">";
case ">":
return "<";
}
}
var hebrew = "\u05D0-\u05EA";
var arabic = "\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF";
var rtlChars = new RegExp(`[${hebrew}${arabic}]`);
function reverseRtl(value) {
const texts = value.split("\n");
let result = "";
for (let i = 0; i < texts.length; i++) {
const text2 = texts[i];
const rtlDir = rtlChars.test(text2.charAt(0));
const parsedText = convertTextToTypes(text2, rtlChars);
let splicePointer = 0;
let line = "";
for (let wordIndex = 0; wordIndex < parsedText.length; ++wordIndex) {
const subText = parsedText[wordIndex];
const reverse = subText.Type === textTypes.BRACKETS ? reverseBrackets(subText.Word) : reverseWord(subText.Word);
if (rtlDir) {
if (subText.Type === textTypes.RTL) {
line = reverse + line;
splicePointer = 0;
} else if (subText.Type === textTypes.LTR) {
line = spliceWord(line, splicePointer, subText.Word);
splicePointer += subText.Word.length;
} else if (subText.Type === textTypes.WEAK || subText.Type === textTypes.BRACKETS) {
if (subText.Type === textTypes.WEAK && parsedText[wordIndex - 1].Type === textTypes.BRACKETS) {
line = reverse + line;
} else if (parsedText[wordIndex - 1].Type === textTypes.RTL) {
line = reverse + line;
splicePointer = 0;
} else if (parsedText.length > wordIndex + 1) {
if (parsedText[wordIndex + 1].Type === textTypes.RTL) {
line = reverse + line;
splicePointer = 0;
} else {
line = spliceWord(line, splicePointer, subText.Word);
splicePointer += subText.Word.length;
}
} else {
line = spliceWord(line, 0, reverse);
}
}
} else if (subText.Type === textTypes.RTL) {
line = spliceWord(line, splicePointer, reverse);
} else if (subText.Type === textTypes.LTR) {
line += subText.Word;
splicePointer = line.length;
} else if (subText.Type === textTypes.WEAK || subText.Type === textTypes.BRACKETS) {
if (wordIndex > 0) {
if (parsedText[wordIndex - 1].Type === textTypes.RTL) {
if (parsedText.length > wordIndex + 1) {
if (parsedText[wordIndex + 1].Type === textTypes.RTL) {
line = spliceWord(line, splicePointer, reverse);
} else {
line += subText.Word;
splicePointer = line.length;
}
} else {
line += subText.Word;
}
} else {
line += subText.Word;
splicePointer = line.length;
}
} else {
line += subText.Word;
splicePointer = line.length;
}
}
}
result += line;
if (i < texts.length - 1) {
result += "\n";
}
}
return result;
}
var Label_default = Label;
// packages/engine/Source/Scene/LabelCollection.js
var import_grapheme_splitter = __toESM(require_grapheme_splitter(), 1);
function Glyph() {
this.dimensions = void 0;
this.billboardTexture = void 0;
this.billboard = void 0;
}
var defaultLineSpacingPercent = 1.2;
var whitePixelCanvasId = "ID_WHITE_PIXEL";
var whitePixelSize = new Cartesian2_default(4, 4);
var whitePixelBoundingRegion = new BoundingRectangle_default(1, 1, 1, 1);
function getWhitePixelBillboard(billboardCollection, labelCollection) {
const billboardTexture = labelCollection._backgroundBillboardTexture;
if (!billboardTexture.hasImage) {
const canvas = document.createElement("canvas");
canvas.width = whitePixelSize.x;
canvas.height = whitePixelSize.y;
const context2D = canvas.getContext("2d");
context2D.fillStyle = "#fff";
context2D.fillRect(0, 0, canvas.width, canvas.height);
billboardTexture.loadImage(whitePixelCanvasId, canvas);
billboardTexture.addImageSubRegion(
whitePixelCanvasId,
whitePixelBoundingRegion
);
}
const billboard = billboardCollection.add({
collection: labelCollection
});
billboard.setImageTexture(billboardTexture);
return billboard;
}
var writeTextToCanvasParameters = {};
function createGlyphCanvas(character, font, fillColor, outlineColor, outlineWidth, style) {
writeTextToCanvasParameters.font = font;
writeTextToCanvasParameters.fillColor = fillColor;
writeTextToCanvasParameters.strokeColor = outlineColor;
writeTextToCanvasParameters.strokeWidth = outlineWidth;
writeTextToCanvasParameters.padding = SDFSettings_default.PADDING;
writeTextToCanvasParameters.fill = style === LabelStyle_default.FILL || style === LabelStyle_default.FILL_AND_OUTLINE;
writeTextToCanvasParameters.stroke = style === LabelStyle_default.OUTLINE || style === LabelStyle_default.FILL_AND_OUTLINE;
writeTextToCanvasParameters.backgroundColor = Color_default.BLACK;
return writeTextToCanvas_default(character, writeTextToCanvasParameters);
}
function unbindGlyphBillboard(labelCollection, glyph) {
const billboard = glyph.billboard;
if (defined_default(billboard)) {
billboard.show = false;
if (defined_default(billboard._removeCallbackFunc)) {
billboard._removeCallbackFunc();
billboard._removeCallbackFunc = void 0;
}
labelCollection._spareBillboards.push(billboard);
glyph.billboard = void 0;
}
}
var splitter = new import_grapheme_splitter.default();
var whitespaceRegex = /\s/;
function rebindAllGlyphs2(labelCollection, label) {
const text2 = label._renderedText;
const graphemes = splitter.splitGraphemes(text2);
const textLength = graphemes.length;
const glyphs = label._glyphs;
const glyphsLength = glyphs.length;
label._relativeSize = label._fontSize / SDFSettings_default.FONT_SIZE;
if (textLength < glyphsLength) {
for (let glyphIndex = textLength; glyphIndex < glyphsLength; ++glyphIndex) {
unbindGlyphBillboard(labelCollection, glyphs[glyphIndex]);
}
}
glyphs.length = textLength;
const showBackground = label.show && label._showBackground && text2.split("\n").join("").length > 0;
let backgroundBillboard = label._backgroundBillboard;
const backgroundBillboardCollection = labelCollection._backgroundBillboardCollection;
if (!showBackground) {
if (defined_default(backgroundBillboard)) {
backgroundBillboardCollection.remove(backgroundBillboard);
label._backgroundBillboard = backgroundBillboard = void 0;
}
} else {
if (!defined_default(backgroundBillboard)) {
backgroundBillboard = getWhitePixelBillboard(
backgroundBillboardCollection,
labelCollection
);
label._backgroundBillboard = backgroundBillboard;
}
backgroundBillboard.color = label._backgroundColor;
backgroundBillboard.show = label._show;
backgroundBillboard.position = label._position;
backgroundBillboard.eyeOffset = label._eyeOffset;
backgroundBillboard.pixelOffset = label._pixelOffset;
backgroundBillboard.horizontalOrigin = HorizontalOrigin_default.LEFT;
backgroundBillboard.verticalOrigin = label._verticalOrigin;
backgroundBillboard.heightReference = label._heightReference;
backgroundBillboard.scale = label.totalScale;
backgroundBillboard.pickPrimitive = label;
backgroundBillboard.id = label._id;
backgroundBillboard.translucencyByDistance = label._translucencyByDistance;
backgroundBillboard.pixelOffsetScaleByDistance = label._pixelOffsetScaleByDistance;
backgroundBillboard.scaleByDistance = label._scaleByDistance;
backgroundBillboard.distanceDisplayCondition = label._distanceDisplayCondition;
backgroundBillboard.disableDepthTestDistance = label._disableDepthTestDistance;
backgroundBillboard.clusterShow = label.clusterShow;
}
const glyphBillboardCollection = labelCollection._glyphBillboardCollection;
const glyphTextureCache = glyphBillboardCollection.billboardTextureCache;
const textDimensionsCache = labelCollection._textDimensionsCache;
for (let textIndex = 0; textIndex < textLength; ++textIndex) {
const character = graphemes[textIndex];
const verticalOrigin = label._verticalOrigin;
const id = JSON.stringify([
character,
label._fontFamily,
label._fontStyle,
label._fontWeight,
+verticalOrigin
]);
let dimensions = textDimensionsCache[id];
let glyphBillboardTexture = glyphTextureCache.get(id);
if (!defined_default(glyphBillboardTexture) || !defined_default(dimensions)) {
glyphBillboardTexture = new BillboardTexture_default(glyphBillboardCollection);
glyphTextureCache.set(id, glyphBillboardTexture);
const glyphFont = `${label._fontStyle} ${label._fontWeight} ${SDFSettings_default.FONT_SIZE}px ${label._fontFamily}`;
const canvas = createGlyphCanvas(
character,
glyphFont,
Color_default.WHITE,
Color_default.WHITE,
0,
LabelStyle_default.FILL
);
dimensions = canvas.dimensions;
textDimensionsCache[id] = dimensions;
if (canvas.width > 0 && canvas.height > 0 && !whitespaceRegex.test(character)) {
const sdfValues = (0, import_bitmap_sdf.default)(canvas, {
cutoff: SDFSettings_default.CUTOFF,
radius: SDFSettings_default.RADIUS
});
const ctx = canvas.getContext("2d");
const canvasWidth = canvas.width;
const canvasHeight = canvas.height;
const imgData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
for (let i = 0; i < canvasWidth; i++) {
for (let j = 0; j < canvasHeight; j++) {
const baseIndex = j * canvasWidth + i;
const alpha = sdfValues[baseIndex] * 255;
const imageIndex = baseIndex * 4;
imgData.data[imageIndex + 0] = alpha;
imgData.data[imageIndex + 1] = alpha;
imgData.data[imageIndex + 2] = alpha;
imgData.data[imageIndex + 3] = alpha;
}
}
ctx.putImageData(imgData, 0, 0);
glyphBillboardTexture.loadImage(id, canvas);
}
}
let glyph = glyphs[textIndex];
if (!defined_default(glyph)) {
glyph = new Glyph();
glyph.dimensions = dimensions;
glyph.billboardTexture = glyphBillboardTexture;
glyphs[textIndex] = glyph;
}
if (glyph.billboardTexture.id !== id) {
glyph.billboardTexture = glyphBillboardTexture;
glyph.dimensions = dimensions;
}
if (!glyphBillboardTexture.hasImage) {
unbindGlyphBillboard(labelCollection, glyph);
continue;
}
let billboard = glyph.billboard;
const spareBillboards = labelCollection._spareBillboards;
if (!defined_default(billboard)) {
if (spareBillboards.length > 0) {
billboard = spareBillboards.pop();
} else {
billboard = glyphBillboardCollection.add({
collection: labelCollection
});
billboard._labelDimensions = new Cartesian2_default();
billboard._labelTranslate = new Cartesian2_default();
}
glyph.billboard = billboard;
}
billboard.setImageTexture(glyphBillboardTexture);
billboard.show = label._show;
billboard.position = label._position;
billboard.eyeOffset = label._eyeOffset;
billboard.pixelOffset = label._pixelOffset;
billboard.horizontalOrigin = HorizontalOrigin_default.LEFT;
billboard.verticalOrigin = label._verticalOrigin;
billboard.heightReference = label._heightReference;
billboard.scale = label.totalScale;
billboard.pickPrimitive = label;
billboard.id = label._id;
billboard.translucencyByDistance = label._translucencyByDistance;
billboard.pixelOffsetScaleByDistance = label._pixelOffsetScaleByDistance;
billboard.scaleByDistance = label._scaleByDistance;
billboard.distanceDisplayCondition = label._distanceDisplayCondition;
billboard.disableDepthTestDistance = label._disableDepthTestDistance;
billboard._batchIndex = label._batchIndex;
billboard.outlineColor = label.outlineColor;
if (label.style === LabelStyle_default.FILL_AND_OUTLINE) {
billboard.color = label._fillColor;
billboard.outlineWidth = label.outlineWidth;
} else if (label.style === LabelStyle_default.FILL) {
billboard.color = label._fillColor;
billboard.outlineWidth = 0;
} else if (label.style === LabelStyle_default.OUTLINE) {
billboard.color = Color_default.TRANSPARENT;
billboard.outlineWidth = label.outlineWidth;
}
}
label._repositionAllGlyphs = true;
}
function calculateWidthOffset(lineWidth, horizontalOrigin, backgroundPadding) {
if (horizontalOrigin === HorizontalOrigin_default.CENTER) {
return -lineWidth / 2;
} else if (horizontalOrigin === HorizontalOrigin_default.RIGHT) {
return -(lineWidth + backgroundPadding.x);
}
return backgroundPadding.x;
}
var glyphPixelOffset = new Cartesian2_default();
var scratchBackgroundPadding = new Cartesian2_default();
function repositionAllGlyphs2(label) {
const glyphs = label._glyphs;
const text2 = label._renderedText;
let lastLineWidth = 0;
let maxLineWidth = 0;
const lineWidths = [];
let maxGlyphDescent = Number.NEGATIVE_INFINITY;
let maxGlyphY = 0;
let numberOfLines = 1;
const glyphLength = glyphs.length;
const backgroundBillboard = label._backgroundBillboard;
const backgroundPadding = Cartesian2_default.clone(
defined_default(backgroundBillboard) ? label._backgroundPadding : Cartesian2_default.ZERO,
scratchBackgroundPadding
);
backgroundPadding.x /= label._relativeSize;
backgroundPadding.y /= label._relativeSize;
for (let glyphIndex = 0; glyphIndex < glyphLength; ++glyphIndex) {
if (text2.charAt(glyphIndex) === "\n") {
lineWidths.push(lastLineWidth);
++numberOfLines;
lastLineWidth = 0;
continue;
}
const glyph = glyphs[glyphIndex];
const dimensions = glyph.dimensions;
if (defined_default(dimensions)) {
maxGlyphY = Math.max(maxGlyphY, dimensions.height - dimensions.descent);
maxGlyphDescent = Math.max(maxGlyphDescent, dimensions.descent);
lastLineWidth += dimensions.width - dimensions.minx;
if (glyphIndex < glyphLength - 1) {
lastLineWidth += glyphs[glyphIndex + 1].dimensions.minx;
}
maxLineWidth = Math.max(maxLineWidth, lastLineWidth);
}
}
lineWidths.push(lastLineWidth);
const maxLineHeight = maxGlyphY + maxGlyphDescent;
const scale = label.totalScale;
const horizontalOrigin = label._horizontalOrigin;
const verticalOrigin = label._verticalOrigin;
let lineIndex = 0;
let lineWidth = lineWidths[lineIndex];
let widthOffset = calculateWidthOffset(
lineWidth,
horizontalOrigin,
backgroundPadding
);
const lineSpacing = (defined_default(label._lineHeight) ? label._lineHeight : defaultLineSpacingPercent * label._fontSize) / label._relativeSize;
const otherLinesHeight = lineSpacing * (numberOfLines - 1);
let totalLineWidth = maxLineWidth;
let totalLineHeight = maxLineHeight + otherLinesHeight;
if (defined_default(backgroundBillboard)) {
totalLineWidth += backgroundPadding.x * 2;
totalLineHeight += backgroundPadding.y * 2;
backgroundBillboard._labelHorizontalOrigin = horizontalOrigin;
}
glyphPixelOffset.x = widthOffset * scale;
glyphPixelOffset.y = 0;
let firstCharOfLine = true;
let lineOffsetY = 0;
for (let glyphIndex = 0; glyphIndex < glyphLength; ++glyphIndex) {
if (text2.charAt(glyphIndex) === "\n") {
++lineIndex;
lineOffsetY += lineSpacing;
lineWidth = lineWidths[lineIndex];
widthOffset = calculateWidthOffset(
lineWidth,
horizontalOrigin,
backgroundPadding
);
glyphPixelOffset.x = widthOffset * scale;
firstCharOfLine = true;
continue;
}
const glyph = glyphs[glyphIndex];
const dimensions = glyph.dimensions;
if (defined_default(dimensions)) {
if (verticalOrigin === VerticalOrigin_default.TOP) {
glyphPixelOffset.y = dimensions.height - maxGlyphY - backgroundPadding.y;
glyphPixelOffset.y += SDFSettings_default.PADDING;
} else if (verticalOrigin === VerticalOrigin_default.CENTER) {
glyphPixelOffset.y = (otherLinesHeight + dimensions.height - maxGlyphY) / 2;
} else if (verticalOrigin === VerticalOrigin_default.BASELINE) {
glyphPixelOffset.y = otherLinesHeight;
glyphPixelOffset.y -= SDFSettings_default.PADDING;
} else {
glyphPixelOffset.y = otherLinesHeight + maxGlyphDescent + backgroundPadding.y;
glyphPixelOffset.y -= SDFSettings_default.PADDING;
}
glyphPixelOffset.y = (glyphPixelOffset.y - dimensions.descent - lineOffsetY) * scale;
if (firstCharOfLine) {
glyphPixelOffset.x -= SDFSettings_default.PADDING * scale;
firstCharOfLine = false;
}
if (defined_default(glyph.billboard)) {
glyph.billboard._setTranslate(glyphPixelOffset);
glyph.billboard._labelDimensions.x = totalLineWidth;
glyph.billboard._labelDimensions.y = totalLineHeight;
glyph.billboard._labelHorizontalOrigin = horizontalOrigin;
}
if (glyphIndex < glyphLength - 1) {
const nextGlyph = glyphs[glyphIndex + 1];
glyphPixelOffset.x += (dimensions.width - dimensions.minx + nextGlyph.dimensions.minx) * scale;
}
}
}
if (defined_default(backgroundBillboard) && text2.split("\n").join("").length > 0) {
if (horizontalOrigin === HorizontalOrigin_default.CENTER) {
widthOffset = -maxLineWidth / 2 - backgroundPadding.x;
} else if (horizontalOrigin === HorizontalOrigin_default.RIGHT) {
widthOffset = -(maxLineWidth + backgroundPadding.x * 2);
} else {
widthOffset = 0;
}
glyphPixelOffset.x = widthOffset * scale;
if (verticalOrigin === VerticalOrigin_default.TOP) {
glyphPixelOffset.y = maxLineHeight - maxGlyphY - maxGlyphDescent;
} else if (verticalOrigin === VerticalOrigin_default.CENTER) {
glyphPixelOffset.y = (maxLineHeight - maxGlyphY) / 2 - maxGlyphDescent;
} else if (verticalOrigin === VerticalOrigin_default.BASELINE) {
glyphPixelOffset.y = -backgroundPadding.y - maxGlyphDescent;
} else {
glyphPixelOffset.y = 0;
}
glyphPixelOffset.y = glyphPixelOffset.y * scale;
backgroundBillboard.width = totalLineWidth;
backgroundBillboard.height = totalLineHeight;
backgroundBillboard._setTranslate(glyphPixelOffset);
backgroundBillboard._labelTranslate = Cartesian2_default.clone(
glyphPixelOffset,
backgroundBillboard._labelTranslate
);
}
if (isHeightReferenceClamp(label.heightReference)) {
for (let glyphIndex = 0; glyphIndex < glyphLength; ++glyphIndex) {
const glyph = glyphs[glyphIndex];
const billboard = glyph.billboard;
if (defined_default(billboard)) {
billboard._labelTranslate = Cartesian2_default.clone(
glyphPixelOffset,
billboard._labelTranslate
);
}
}
}
}
function destroyLabel(labelCollection, label) {
const glyphs = label._glyphs;
for (let i = 0, len = glyphs.length; i < len; ++i) {
unbindGlyphBillboard(labelCollection, glyphs[i]);
}
if (defined_default(label._backgroundBillboard)) {
labelCollection._backgroundBillboardCollection.remove(
label._backgroundBillboard
);
label._backgroundBillboard = void 0;
}
label._labelCollection = void 0;
if (defined_default(label._removeCallbackFunc)) {
label._removeCallbackFunc();
}
destroyObject_default(label);
}
function LabelCollection(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._scene = options.scene;
this._batchTable = options.batchTable;
const backgroundBillboardCollection = new BillboardCollection_default({
scene: this._scene,
textureAtlas: new TextureAtlas_default({
initialSize: whitePixelSize
})
});
this._backgroundBillboardCollection = backgroundBillboardCollection;
this._backgroundBillboardTexture = new BillboardTexture_default(
backgroundBillboardCollection
);
this._glyphBillboardCollection = new BillboardCollection_default({
scene: this._scene,
batchTable: this._batchTable
});
this._glyphBillboardCollection._sdf = true;
this._spareBillboards = [];
this._textDimensionsCache = {};
this._labels = [];
this._labelsToUpdate = [];
this._totalGlyphCount = 0;
this._highlightColor = Color_default.clone(Color_default.WHITE);
this.show = options.show ?? true;
this.modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this.blendOption = options.blendOption ?? BlendOption_default.OPAQUE_AND_TRANSLUCENT;
}
Object.defineProperties(LabelCollection.prototype, {
/**
* Returns the number of labels in this collection. This is commonly used with
* {@link LabelCollection#get} to iterate over all the labels
* in the collection.
* @memberof LabelCollection.prototype
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._labels.length;
}
},
/**
* Returns the size in bytes of the WebGL texture resources.
* @private
* @memberof LabelCollection.prototype
* @type {number}
* @readonly
*/
sizeInBytes: {
get: function() {
return this._glyphBillboardCollection.sizeInBytes + this._backgroundBillboardCollection.sizeInBytes;
}
},
/**
* True when all labels currently in the collection are ready for rendering.
* @private
* @memberof LabelCollection.prototype
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
const backgroundBillboard = this._backgroundBillboardCollection.get(0);
if (defined_default(backgroundBillboard) && !backgroundBillboard.ready) {
return false;
}
return this._glyphBillboardCollection.ready;
}
}
});
LabelCollection.prototype.add = function(options) {
const label = new Label_default(options, this);
this._labels.push(label);
this._labelsToUpdate.push(label);
return label;
};
LabelCollection.prototype.remove = function(label) {
if (defined_default(label) && label._labelCollection === this) {
const index = this._labels.indexOf(label);
if (index !== -1) {
this._labels.splice(index, 1);
destroyLabel(this, label);
return true;
}
}
return false;
};
LabelCollection.prototype.removeAll = function() {
const labels = this._labels;
for (let i = 0, len = labels.length; i < len; ++i) {
destroyLabel(this, labels[i]);
}
labels.length = 0;
};
LabelCollection.prototype.contains = function(label) {
return defined_default(label) && label._labelCollection === this;
};
LabelCollection.prototype.get = function(index) {
if (!defined_default(index)) {
throw new DeveloperError_default("index is required.");
}
return this._labels[index];
};
LabelCollection.prototype.update = function(frameState) {
if (!this.show) {
return;
}
const glyphBillboardCollection = this._glyphBillboardCollection;
const backgroundBillboardCollection = this._backgroundBillboardCollection;
glyphBillboardCollection.modelMatrix = this.modelMatrix;
glyphBillboardCollection.debugShowBoundingVolume = this.debugShowBoundingVolume;
backgroundBillboardCollection.modelMatrix = this.modelMatrix;
backgroundBillboardCollection.debugShowBoundingVolume = this.debugShowBoundingVolume;
const len = this._labelsToUpdate.length;
for (let i = 0; i < len; ++i) {
const label = this._labelsToUpdate[i];
if (label.isDestroyed()) {
continue;
}
const preUpdateGlyphCount = label._glyphs.length;
if (label._rebindAllGlyphs) {
rebindAllGlyphs2(this, label);
label._rebindAllGlyphs = false;
}
if (label._repositionAllGlyphs) {
repositionAllGlyphs2(label);
label._repositionAllGlyphs = false;
}
const glyphCountDifference = label._glyphs.length - preUpdateGlyphCount;
this._totalGlyphCount += glyphCountDifference;
}
const blendOption = backgroundBillboardCollection.length > 0 ? BlendOption_default.TRANSLUCENT : this.blendOption;
glyphBillboardCollection.blendOption = blendOption;
backgroundBillboardCollection.blendOption = blendOption;
glyphBillboardCollection._highlightColor = this._highlightColor;
backgroundBillboardCollection._highlightColor = this._highlightColor;
this._labelsToUpdate.length = 0;
backgroundBillboardCollection.update(frameState);
glyphBillboardCollection.update(frameState);
};
LabelCollection.prototype.isDestroyed = function() {
return false;
};
LabelCollection.prototype.destroy = function() {
this.removeAll();
this._glyphBillboardCollection = this._glyphBillboardCollection.destroy();
this._backgroundBillboardCollection = this._backgroundBillboardCollection.destroy();
return destroyObject_default(this);
};
var LabelCollection_default = LabelCollection;
// packages/engine/Source/Scene/PolylineCollection.js
var import_InlineWorkers756 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/PolylineVS.js
var import_InlineWorkers753 = __toESM(require_InlineWorkers(), 1);
var PolylineVS_default = "in vec3 position3DHigh;\nin vec3 position3DLow;\nin vec3 position2DHigh;\nin vec3 position2DLow;\nin vec3 prevPosition3DHigh;\nin vec3 prevPosition3DLow;\nin vec3 prevPosition2DHigh;\nin vec3 prevPosition2DLow;\nin vec3 nextPosition3DHigh;\nin vec3 nextPosition3DLow;\nin vec3 nextPosition2DHigh;\nin vec3 nextPosition2DLow;\nin vec4 texCoordExpandAndBatchIndex;\n\nout vec2 v_st;\nout float v_width;\nout vec4 v_pickColor;\nout float v_polylineAngle;\n\nvoid main()\n{\n float texCoord = texCoordExpandAndBatchIndex.x;\n float expandDir = texCoordExpandAndBatchIndex.y;\n bool usePrev = texCoordExpandAndBatchIndex.z < 0.0;\n float batchTableIndex = texCoordExpandAndBatchIndex.w;\n\n vec2 widthAndShow = batchTable_getWidthAndShow(batchTableIndex);\n float width = widthAndShow.x + 0.5;\n float show = widthAndShow.y;\n\n if (width < 1.0)\n {\n show = 0.0;\n }\n\n vec4 pickColor = batchTable_getPickColor(batchTableIndex);\n\n vec4 p, prev, next;\n if (czm_morphTime == 1.0)\n {\n p = czm_translateRelativeToEye(position3DHigh.xyz, position3DLow.xyz);\n prev = czm_translateRelativeToEye(prevPosition3DHigh.xyz, prevPosition3DLow.xyz);\n next = czm_translateRelativeToEye(nextPosition3DHigh.xyz, nextPosition3DLow.xyz);\n }\n else if (czm_morphTime == 0.0)\n {\n p = czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy);\n prev = czm_translateRelativeToEye(prevPosition2DHigh.zxy, prevPosition2DLow.zxy);\n next = czm_translateRelativeToEye(nextPosition2DHigh.zxy, nextPosition2DLow.zxy);\n }\n else\n {\n p = czm_columbusViewMorph(\n czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy),\n czm_translateRelativeToEye(position3DHigh.xyz, position3DLow.xyz),\n czm_morphTime);\n prev = czm_columbusViewMorph(\n czm_translateRelativeToEye(prevPosition2DHigh.zxy, prevPosition2DLow.zxy),\n czm_translateRelativeToEye(prevPosition3DHigh.xyz, prevPosition3DLow.xyz),\n czm_morphTime);\n next = czm_columbusViewMorph(\n czm_translateRelativeToEye(nextPosition2DHigh.zxy, nextPosition2DLow.zxy),\n czm_translateRelativeToEye(nextPosition3DHigh.xyz, nextPosition3DLow.xyz),\n czm_morphTime);\n }\n\n #ifdef DISTANCE_DISPLAY_CONDITION\n vec3 centerHigh = batchTable_getCenterHigh(batchTableIndex);\n vec4 centerLowAndRadius = batchTable_getCenterLowAndRadius(batchTableIndex);\n vec3 centerLow = centerLowAndRadius.xyz;\n float radius = centerLowAndRadius.w;\n vec2 distanceDisplayCondition = batchTable_getDistanceDisplayCondition(batchTableIndex);\n\n float lengthSq;\n if (czm_sceneMode == czm_sceneMode2D)\n {\n lengthSq = czm_eyeHeight2D.y;\n }\n else\n {\n vec4 center = czm_translateRelativeToEye(centerHigh.xyz, centerLow.xyz);\n lengthSq = max(0.0, dot(center.xyz, center.xyz) - radius * radius);\n }\n\n float nearSq = distanceDisplayCondition.x * distanceDisplayCondition.x;\n float farSq = distanceDisplayCondition.y * distanceDisplayCondition.y;\n if (lengthSq < nearSq || lengthSq > farSq)\n {\n show = 0.0;\n }\n #endif\n\n float polylineAngle;\n vec4 positionWC = getPolylineWindowCoordinates(p, prev, next, expandDir, width, usePrev, polylineAngle);\n gl_Position = czm_viewportOrthographic * positionWC * show;\n\n v_st.s = texCoord;\n v_st.t = czm_writeNonPerspective(clamp(expandDir, 0.0, 1.0), gl_Position.w);\n\n v_width = width;\n v_pickColor = pickColor;\n v_polylineAngle = polylineAngle;\n}\n";
// packages/engine/Source/Scene/Polyline.js
var import_InlineWorkers755 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PolylinePipeline.js
var import_InlineWorkers754 = __toESM(require_InlineWorkers(), 1);
var PolylinePipeline = {};
PolylinePipeline.numberOfPoints = function(p0, p1, minDistance) {
const distance2 = Cartesian3_default.distance(p0, p1);
return Math.ceil(distance2 / minDistance);
};
PolylinePipeline.numberOfPointsRhumbLine = function(p0, p1, granularity) {
const radiansDistanceSquared = Math.pow(p0.longitude - p1.longitude, 2) + Math.pow(p0.latitude - p1.latitude, 2);
return Math.max(
1,
Math.ceil(Math.sqrt(radiansDistanceSquared / (granularity * granularity)))
);
};
var cartoScratch2 = new Cartographic_default();
PolylinePipeline.extractHeights = function(positions, ellipsoid) {
const length2 = positions.length;
const heights = new Array(length2);
for (let i = 0; i < length2; i++) {
const p = positions[i];
heights[i] = ellipsoid.cartesianToCartographic(p, cartoScratch2).height;
}
return heights;
};
var wrapLongitudeInversMatrix = new Matrix4_default();
var wrapLongitudeOrigin = new Cartesian3_default();
var wrapLongitudeXZNormal = new Cartesian3_default();
var wrapLongitudeXZPlane = new Plane_default(Cartesian3_default.UNIT_X, 0);
var wrapLongitudeYZNormal = new Cartesian3_default();
var wrapLongitudeYZPlane = new Plane_default(Cartesian3_default.UNIT_X, 0);
var wrapLongitudeIntersection = new Cartesian3_default();
var wrapLongitudeOffset = new Cartesian3_default();
var subdivideHeightsScratchArray = [];
function subdivideHeights(numPoints, h0, h1) {
const heights = subdivideHeightsScratchArray;
heights.length = numPoints;
let i;
if (h0 === h1) {
for (i = 0; i < numPoints; i++) {
heights[i] = h0;
}
return heights;
}
const dHeight = h1 - h0;
const heightPerVertex = dHeight / numPoints;
for (i = 0; i < numPoints; i++) {
const h = h0 + i * heightPerVertex;
heights[i] = h;
}
return heights;
}
var carto1 = new Cartographic_default();
var carto2 = new Cartographic_default();
var cartesian = new Cartesian3_default();
var scaleFirst = new Cartesian3_default();
var scaleLast = new Cartesian3_default();
var ellipsoidGeodesic = new EllipsoidGeodesic_default();
var ellipsoidRhumb = new EllipsoidRhumbLine_default();
function generateCartesianArc(p0, p1, minDistance, ellipsoid, h0, h1, array, offset) {
const first = ellipsoid.scaleToGeodeticSurface(p0, scaleFirst);
const last = ellipsoid.scaleToGeodeticSurface(p1, scaleLast);
const numPoints = PolylinePipeline.numberOfPoints(p0, p1, minDistance);
const start = ellipsoid.cartesianToCartographic(first, carto1);
const end = ellipsoid.cartesianToCartographic(last, carto2);
const heights = subdivideHeights(numPoints, h0, h1);
ellipsoidGeodesic.setEndPoints(start, end);
const surfaceDistanceBetweenPoints = ellipsoidGeodesic.surfaceDistance / numPoints;
let index = offset;
start.height = h0;
let cart = ellipsoid.cartographicToCartesian(start, cartesian);
Cartesian3_default.pack(cart, array, index);
index += 3;
for (let i = 1; i < numPoints; i++) {
const carto = ellipsoidGeodesic.interpolateUsingSurfaceDistance(
i * surfaceDistanceBetweenPoints,
carto2
);
carto.height = heights[i];
cart = ellipsoid.cartographicToCartesian(carto, cartesian);
Cartesian3_default.pack(cart, array, index);
index += 3;
}
return index;
}
function generateCartesianRhumbArc(p0, p1, granularity, ellipsoid, h0, h1, array, offset) {
const start = ellipsoid.cartesianToCartographic(p0, carto1);
const end = ellipsoid.cartesianToCartographic(p1, carto2);
const numPoints = PolylinePipeline.numberOfPointsRhumbLine(
start,
end,
granularity
);
start.height = 0;
end.height = 0;
const heights = subdivideHeights(numPoints, h0, h1);
if (!ellipsoidRhumb.ellipsoid.equals(ellipsoid)) {
ellipsoidRhumb = new EllipsoidRhumbLine_default(void 0, void 0, ellipsoid);
}
ellipsoidRhumb.setEndPoints(start, end);
const surfaceDistanceBetweenPoints = ellipsoidRhumb.surfaceDistance / numPoints;
let index = offset;
start.height = h0;
let cart = ellipsoid.cartographicToCartesian(start, cartesian);
Cartesian3_default.pack(cart, array, index);
index += 3;
for (let i = 1; i < numPoints; i++) {
const carto = ellipsoidRhumb.interpolateUsingSurfaceDistance(
i * surfaceDistanceBetweenPoints,
carto2
);
carto.height = heights[i];
cart = ellipsoid.cartographicToCartesian(carto, cartesian);
Cartesian3_default.pack(cart, array, index);
index += 3;
}
return index;
}
PolylinePipeline.wrapLongitude = function(positions, modelMatrix) {
const cartesians = [];
const segments = [];
if (defined_default(positions) && positions.length > 0) {
modelMatrix = modelMatrix ?? Matrix4_default.IDENTITY;
const inverseModelMatrix = Matrix4_default.inverseTransformation(
modelMatrix,
wrapLongitudeInversMatrix
);
const origin = Matrix4_default.multiplyByPoint(
inverseModelMatrix,
Cartesian3_default.ZERO,
wrapLongitudeOrigin
);
const xzNormal = Cartesian3_default.normalize(
Matrix4_default.multiplyByPointAsVector(
inverseModelMatrix,
Cartesian3_default.UNIT_Y,
wrapLongitudeXZNormal
),
wrapLongitudeXZNormal
);
const xzPlane2 = Plane_default.fromPointNormal(
origin,
xzNormal,
wrapLongitudeXZPlane
);
const yzNormal = Cartesian3_default.normalize(
Matrix4_default.multiplyByPointAsVector(
inverseModelMatrix,
Cartesian3_default.UNIT_X,
wrapLongitudeYZNormal
),
wrapLongitudeYZNormal
);
const yzPlane = Plane_default.fromPointNormal(
origin,
yzNormal,
wrapLongitudeYZPlane
);
let count = 1;
cartesians.push(Cartesian3_default.clone(positions[0]));
let prev = cartesians[0];
const length2 = positions.length;
for (let i = 1; i < length2; ++i) {
const cur = positions[i];
if (Plane_default.getPointDistance(yzPlane, prev) < 0 || Plane_default.getPointDistance(yzPlane, cur) < 0) {
const intersection = IntersectionTests_default.lineSegmentPlane(
prev,
cur,
xzPlane2,
wrapLongitudeIntersection
);
if (defined_default(intersection)) {
const offset = Cartesian3_default.multiplyByScalar(
xzNormal,
5e-9,
wrapLongitudeOffset
);
if (Plane_default.getPointDistance(xzPlane2, prev) < 0) {
Cartesian3_default.negate(offset, offset);
}
cartesians.push(
Cartesian3_default.add(intersection, offset, new Cartesian3_default())
);
segments.push(count + 1);
Cartesian3_default.negate(offset, offset);
cartesians.push(
Cartesian3_default.add(intersection, offset, new Cartesian3_default())
);
count = 1;
}
}
cartesians.push(Cartesian3_default.clone(positions[i]));
count++;
prev = cur;
}
segments.push(count);
}
return {
positions: cartesians,
lengths: segments
};
};
PolylinePipeline.generateArc = function(options) {
if (!defined_default(options)) {
options = {};
}
const positions = options.positions;
if (!defined_default(positions)) {
throw new DeveloperError_default("options.positions is required.");
}
const length2 = positions.length;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
let height = options.height ?? 0;
const hasHeightArray = Array.isArray(height);
if (length2 < 1) {
return [];
} else if (length2 === 1) {
const p = ellipsoid.scaleToGeodeticSurface(positions[0], scaleFirst);
height = hasHeightArray ? height[0] : height;
if (height !== 0) {
const n = ellipsoid.geodeticSurfaceNormal(p, cartesian);
Cartesian3_default.multiplyByScalar(n, height, n);
Cartesian3_default.add(p, n, p);
}
return [p.x, p.y, p.z];
}
let minDistance = options.minDistance;
if (!defined_default(minDistance)) {
const granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
minDistance = Math_default.chordLength(granularity, ellipsoid.maximumRadius);
}
let numPoints = 0;
let i;
for (i = 0; i < length2 - 1; i++) {
numPoints += PolylinePipeline.numberOfPoints(
positions[i],
positions[i + 1],
minDistance
);
}
const arrayLength = (numPoints + 1) * 3;
const newPositions = new Array(arrayLength);
let offset = 0;
for (i = 0; i < length2 - 1; i++) {
const p0 = positions[i];
const p1 = positions[i + 1];
const h0 = hasHeightArray ? height[i] : height;
const h1 = hasHeightArray ? height[i + 1] : height;
offset = generateCartesianArc(
p0,
p1,
minDistance,
ellipsoid,
h0,
h1,
newPositions,
offset
);
}
subdivideHeightsScratchArray.length = 0;
const lastPoint = positions[length2 - 1];
const carto = ellipsoid.cartesianToCartographic(lastPoint, carto1);
carto.height = hasHeightArray ? height[length2 - 1] : height;
const cart = ellipsoid.cartographicToCartesian(carto, cartesian);
Cartesian3_default.pack(cart, newPositions, arrayLength - 3);
return newPositions;
};
var scratchCartographic02 = new Cartographic_default();
var scratchCartographic12 = new Cartographic_default();
PolylinePipeline.generateRhumbArc = function(options) {
if (!defined_default(options)) {
options = {};
}
const positions = options.positions;
if (!defined_default(positions)) {
throw new DeveloperError_default("options.positions is required.");
}
const length2 = positions.length;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
let height = options.height ?? 0;
const hasHeightArray = Array.isArray(height);
if (length2 < 1) {
return [];
} else if (length2 === 1) {
const p = ellipsoid.scaleToGeodeticSurface(positions[0], scaleFirst);
height = hasHeightArray ? height[0] : height;
if (height !== 0) {
const n = ellipsoid.geodeticSurfaceNormal(p, cartesian);
Cartesian3_default.multiplyByScalar(n, height, n);
Cartesian3_default.add(p, n, p);
}
return [p.x, p.y, p.z];
}
const granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
let numPoints = 0;
let i;
let c0 = ellipsoid.cartesianToCartographic(
positions[0],
scratchCartographic02
);
let c14;
for (i = 0; i < length2 - 1; i++) {
c14 = ellipsoid.cartesianToCartographic(
positions[i + 1],
scratchCartographic12
);
numPoints += PolylinePipeline.numberOfPointsRhumbLine(c0, c14, granularity);
c0 = Cartographic_default.clone(c14, scratchCartographic02);
}
const arrayLength = (numPoints + 1) * 3;
const newPositions = new Array(arrayLength);
let offset = 0;
for (i = 0; i < length2 - 1; i++) {
const p0 = positions[i];
const p1 = positions[i + 1];
const h0 = hasHeightArray ? height[i] : height;
const h1 = hasHeightArray ? height[i + 1] : height;
offset = generateCartesianRhumbArc(
p0,
p1,
granularity,
ellipsoid,
h0,
h1,
newPositions,
offset
);
}
subdivideHeightsScratchArray.length = 0;
const lastPoint = positions[length2 - 1];
const carto = ellipsoid.cartesianToCartographic(lastPoint, carto1);
carto.height = hasHeightArray ? height[length2 - 1] : height;
const cart = ellipsoid.cartographicToCartesian(carto, cartesian);
Cartesian3_default.pack(cart, newPositions, arrayLength - 3);
return newPositions;
};
PolylinePipeline.generateCartesianArc = function(options) {
const numberArray = PolylinePipeline.generateArc(options);
const size = numberArray.length / 3;
const newPositions = new Array(size);
for (let i = 0; i < size; i++) {
newPositions[i] = Cartesian3_default.unpack(numberArray, i * 3);
}
return newPositions;
};
PolylinePipeline.generateCartesianRhumbArc = function(options) {
const numberArray = PolylinePipeline.generateRhumbArc(options);
const size = numberArray.length / 3;
const newPositions = new Array(size);
for (let i = 0; i < size; i++) {
newPositions[i] = Cartesian3_default.unpack(numberArray, i * 3);
}
return newPositions;
};
var PolylinePipeline_default = PolylinePipeline;
// packages/engine/Source/Scene/Polyline.js
function Polyline(options, polylineCollection) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._show = options.show ?? true;
this._width = options.width ?? 1;
this._loop = options.loop ?? false;
this._distanceDisplayCondition = options.distanceDisplayCondition;
this._material = options.material;
if (!defined_default(this._material)) {
this._material = Material_default.fromType(Material_default.ColorType, {
color: new Color_default(1, 1, 1, 1)
});
}
let positions = options.positions;
if (!defined_default(positions)) {
positions = [];
}
this._positions = positions;
this._actualPositions = arrayRemoveDuplicates_default(
positions,
Cartesian3_default.equalsEpsilon
);
if (this._loop && this._actualPositions.length > 2) {
if (this._actualPositions === this._positions) {
this._actualPositions = positions.slice();
}
this._actualPositions.push(Cartesian3_default.clone(this._actualPositions[0]));
}
this._length = this._actualPositions.length;
this._id = options.id;
let modelMatrix;
if (defined_default(polylineCollection)) {
modelMatrix = Matrix4_default.clone(polylineCollection.modelMatrix);
}
this._modelMatrix = modelMatrix;
this._segments = PolylinePipeline_default.wrapLongitude(
this._actualPositions,
modelMatrix
);
this._actualLength = void 0;
this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES2);
this._polylineCollection = polylineCollection;
this._dirty = false;
this._pickId = void 0;
this._boundingVolume = BoundingSphere_default.fromPoints(this._actualPositions);
this._boundingVolumeWC = BoundingSphere_default.transform(
this._boundingVolume,
this._modelMatrix
);
this._boundingVolume2D = new BoundingSphere_default();
}
var POSITION_INDEX3 = Polyline.POSITION_INDEX = 0;
var SHOW_INDEX3 = Polyline.SHOW_INDEX = 1;
var WIDTH_INDEX = Polyline.WIDTH_INDEX = 2;
var MATERIAL_INDEX = Polyline.MATERIAL_INDEX = 3;
var POSITION_SIZE_INDEX = Polyline.POSITION_SIZE_INDEX = 4;
var DISTANCE_DISPLAY_CONDITION2 = Polyline.DISTANCE_DISPLAY_CONDITION = 5;
var NUMBER_OF_PROPERTIES2 = Polyline.NUMBER_OF_PROPERTIES = 6;
function makeDirty2(polyline, propertyChanged) {
++polyline._propertiesChanged[propertyChanged];
const polylineCollection = polyline._polylineCollection;
if (defined_default(polylineCollection)) {
polylineCollection._updatePolyline(polyline, propertyChanged);
polyline._dirty = true;
}
}
Object.defineProperties(Polyline.prototype, {
/**
* Determines if this polyline will be shown. Use this to hide or show a polyline, instead
* of removing it and re-adding it to the collection.
* @memberof Polyline.prototype
* @type {boolean}
*/
show: {
get: function() {
return this._show;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (value !== this._show) {
this._show = value;
makeDirty2(this, SHOW_INDEX3);
}
}
},
/**
* Gets or sets the positions of the polyline.
* @memberof Polyline.prototype
* @type {Cartesian3[]}
* @example
* polyline.positions = Cesium.Cartesian3.fromDegreesArray([
* 0.0, 0.0,
* 10.0, 0.0,
* 0.0, 20.0
* ]);
*/
positions: {
get: function() {
return this._positions;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
let positions = arrayRemoveDuplicates_default(value, Cartesian3_default.equalsEpsilon);
if (this._loop && positions.length > 2) {
if (positions === value) {
positions = value.slice();
}
positions.push(Cartesian3_default.clone(positions[0]));
}
if (this._actualPositions.length !== positions.length || this._actualPositions.length !== this._length) {
makeDirty2(this, POSITION_SIZE_INDEX);
}
this._positions = value;
this._actualPositions = positions;
this._length = positions.length;
this._boundingVolume = BoundingSphere_default.fromPoints(
this._actualPositions,
this._boundingVolume
);
this._boundingVolumeWC = BoundingSphere_default.transform(
this._boundingVolume,
this._modelMatrix,
this._boundingVolumeWC
);
makeDirty2(this, POSITION_INDEX3);
this.update();
}
},
/**
* Gets or sets the surface appearance of the polyline. This can be one of several built-in {@link Material} objects or a custom material, scripted with
* {@link https://github.com/CesiumGS/cesium/wiki/Fabric|Fabric}.
* @memberof Polyline.prototype
* @type {Material}
*/
material: {
get: function() {
return this._material;
},
set: function(material) {
if (!defined_default(material)) {
throw new DeveloperError_default("material is required.");
}
if (this._material !== material) {
this._material = material;
makeDirty2(this, MATERIAL_INDEX);
}
}
},
/**
* Gets or sets the width of the polyline.
* @memberof Polyline.prototype
* @type {number}
*/
width: {
get: function() {
return this._width;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const width = this._width;
if (value !== width) {
this._width = value;
makeDirty2(this, WIDTH_INDEX);
}
}
},
/**
* Gets or sets whether a line segment will be added between the first and last polyline positions.
* @memberof Polyline.prototype
* @type {boolean}
*/
loop: {
get: function() {
return this._loop;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (value !== this._loop) {
let positions = this._actualPositions;
if (value) {
if (positions.length > 2 && !Cartesian3_default.equals(positions[0], positions[positions.length - 1])) {
if (positions.length === this._positions.length) {
this._actualPositions = positions = this._positions.slice();
}
positions.push(Cartesian3_default.clone(positions[0]));
}
} else if (positions.length > 2 && Cartesian3_default.equals(positions[0], positions[positions.length - 1])) {
if (positions.length - 1 === this._positions.length) {
this._actualPositions = this._positions;
} else {
positions.pop();
}
}
this._loop = value;
makeDirty2(this, POSITION_SIZE_INDEX);
}
}
},
/**
* Gets or sets the user-defined value returned when the polyline is picked.
* @memberof Polyline.prototype
* @type {*}
*/
id: {
get: function() {
return this._id;
},
set: function(value) {
this._id = value;
if (defined_default(this._pickId)) {
this._pickId.object.id = value;
}
}
},
/**
* @private
*/
pickId: {
get: function() {
return this._pickId;
}
},
/**
* Gets the destruction status of this polyline
* @memberof Polyline.prototype
* @type {boolean}
* @default false
* @private
*/
isDestroyed: {
get: function() {
return !defined_default(this._polylineCollection);
}
},
/**
* Gets or sets the condition specifying at what distance from the camera that this polyline will be displayed.
* @memberof Polyline.prototype
* @type {DistanceDisplayCondition}
* @default undefined
*/
distanceDisplayCondition: {
get: function() {
return this._distanceDisplayCondition;
},
set: function(value) {
if (defined_default(value) && value.far <= value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
if (!DistanceDisplayCondition_default.equals(value, this._distanceDisplayCondition)) {
this._distanceDisplayCondition = DistanceDisplayCondition_default.clone(
value,
this._distanceDisplayCondition
);
makeDirty2(this, DISTANCE_DISPLAY_CONDITION2);
}
}
}
});
Polyline.prototype.update = function() {
let modelMatrix = Matrix4_default.IDENTITY;
if (defined_default(this._polylineCollection)) {
modelMatrix = this._polylineCollection.modelMatrix;
}
const segmentPositionsLength = this._segments.positions.length;
const segmentLengths = this._segments.lengths;
const positionsChanged = this._propertiesChanged[POSITION_INDEX3] > 0 || this._propertiesChanged[POSITION_SIZE_INDEX] > 0;
if (!Matrix4_default.equals(modelMatrix, this._modelMatrix) || positionsChanged) {
this._segments = PolylinePipeline_default.wrapLongitude(
this._actualPositions,
modelMatrix
);
this._boundingVolumeWC = BoundingSphere_default.transform(
this._boundingVolume,
modelMatrix,
this._boundingVolumeWC
);
}
this._modelMatrix = Matrix4_default.clone(modelMatrix, this._modelMatrix);
if (this._segments.positions.length !== segmentPositionsLength) {
makeDirty2(this, POSITION_SIZE_INDEX);
} else {
const length2 = segmentLengths.length;
for (let i = 0; i < length2; ++i) {
if (segmentLengths[i] !== this._segments.lengths[i]) {
makeDirty2(this, POSITION_SIZE_INDEX);
break;
}
}
}
};
Polyline.prototype.getPickId = function(context) {
if (!defined_default(this._pickId)) {
this._pickId = context.createPickId({
primitive: this,
collection: this._polylineCollection,
id: this._id
});
}
return this._pickId;
};
Polyline.prototype._clean = function() {
this._dirty = false;
const properties = this._propertiesChanged;
for (let k = 0; k < NUMBER_OF_PROPERTIES2 - 1; ++k) {
properties[k] = 0;
}
};
Polyline.prototype._destroy = function() {
this._pickId = this._pickId && this._pickId.destroy();
this._material = this._material && this._material.destroy();
this._polylineCollection = void 0;
};
var Polyline_default = Polyline;
// packages/engine/Source/Scene/PolylineCollection.js
var SHOW_INDEX4 = Polyline_default.SHOW_INDEX;
var WIDTH_INDEX2 = Polyline_default.WIDTH_INDEX;
var POSITION_INDEX4 = Polyline_default.POSITION_INDEX;
var MATERIAL_INDEX2 = Polyline_default.MATERIAL_INDEX;
var POSITION_SIZE_INDEX2 = Polyline_default.POSITION_SIZE_INDEX;
var DISTANCE_DISPLAY_CONDITION3 = Polyline_default.DISTANCE_DISPLAY_CONDITION;
var NUMBER_OF_PROPERTIES3 = Polyline_default.NUMBER_OF_PROPERTIES;
var attributeLocations2 = {
texCoordExpandAndBatchIndex: 0,
position3DHigh: 1,
position3DLow: 2,
position2DHigh: 3,
position2DLow: 4,
prevPosition3DHigh: 5,
prevPosition3DLow: 6,
prevPosition2DHigh: 7,
prevPosition2DLow: 8,
nextPosition3DHigh: 9,
nextPosition3DLow: 10,
nextPosition2DHigh: 11,
nextPosition2DLow: 12
};
function PolylineCollection(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.show = options.show ?? true;
this.modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this._modelMatrix = Matrix4_default.clone(Matrix4_default.IDENTITY);
this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this._opaqueRS = void 0;
this._translucentRS = void 0;
this._colorCommands = [];
this._polylinesUpdated = false;
this._polylinesRemoved = false;
this._createVertexArray = false;
this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES3);
this._polylines = [];
this._polylineBuckets = {};
this._positionBufferUsage = {
bufferUsage: BufferUsage_default.STATIC_DRAW,
frameCount: 0
};
this._mode = void 0;
this._polylinesToUpdate = [];
this._vertexArrays = [];
this._positionBuffer = void 0;
this._texCoordExpandAndBatchIndexBuffer = void 0;
this._batchTable = void 0;
this._createBatchTable = false;
this._useHighlightColor = false;
this._highlightColor = Color_default.clone(Color_default.WHITE);
const that = this;
this._uniformMap = {
u_highlightColor: function() {
return that._highlightColor;
}
};
}
Object.defineProperties(PolylineCollection.prototype, {
/**
* Returns the number of polylines in this collection. This is commonly used with
* {@link PolylineCollection#get} to iterate over all the polylines
* in the collection.
* @memberof PolylineCollection.prototype
* @type {number}
*/
length: {
get: function() {
removePolylines(this);
return this._polylines.length;
}
}
});
PolylineCollection.prototype.add = function(options) {
const p = new Polyline_default(options, this);
p._index = this._polylines.length;
this._polylines.push(p);
this._createVertexArray = true;
this._createBatchTable = true;
return p;
};
PolylineCollection.prototype.remove = function(polyline) {
if (this.contains(polyline)) {
this._polylinesRemoved = true;
this._createVertexArray = true;
this._createBatchTable = true;
if (defined_default(polyline._bucket)) {
const bucket = polyline._bucket;
bucket.shaderProgram = bucket.shaderProgram && bucket.shaderProgram.destroy();
}
polyline._destroy();
return true;
}
return false;
};
PolylineCollection.prototype.removeAll = function() {
releaseShaders(this);
destroyPolylines(this);
this._polylineBuckets = {};
this._polylinesRemoved = false;
this._polylines.length = 0;
this._polylinesToUpdate.length = 0;
this._createVertexArray = true;
};
PolylineCollection.prototype.contains = function(polyline) {
return defined_default(polyline) && polyline._polylineCollection === this;
};
PolylineCollection.prototype.get = function(index) {
if (!defined_default(index)) {
throw new DeveloperError_default("index is required.");
}
removePolylines(this);
return this._polylines[index];
};
function createBatchTable2(collection, context) {
if (defined_default(collection._batchTable)) {
collection._batchTable.destroy();
}
const attributes = [
{
functionName: "batchTable_getWidthAndShow",
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 2
},
{
functionName: "batchTable_getPickColor",
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 4,
normalize: true
},
{
functionName: "batchTable_getCenterHigh",
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3
},
{
functionName: "batchTable_getCenterLowAndRadius",
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 4
},
{
functionName: "batchTable_getDistanceDisplayCondition",
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2
}
];
collection._batchTable = new BatchTable_default(
context,
attributes,
collection._polylines.length
);
}
var scratchUpdatePolylineEncodedCartesian = new EncodedCartesian3_default();
var scratchUpdatePolylineCartesian4 = new Cartesian4_default();
var scratchNearFarCartesian2 = new Cartesian2_default();
PolylineCollection.prototype.update = function(frameState) {
removePolylines(this);
if (this._polylines.length === 0 || !this.show) {
return;
}
updateMode2(this, frameState);
const context = frameState.context;
const projection = frameState.mapProjection;
let polyline;
let properties = this._propertiesChanged;
if (this._createBatchTable) {
if (ContextLimits_default.maximumVertexTextureImageUnits === 0) {
throw new RuntimeError_default(
"Vertex texture fetch support is required to render polylines. The maximum number of vertex texture image units must be greater than zero."
);
}
createBatchTable2(this, context);
this._createBatchTable = false;
}
if (this._createVertexArray || computeNewBuffersUsage(this)) {
createVertexArrays(this, context, projection);
} else if (this._polylinesUpdated) {
const polylinesToUpdate = this._polylinesToUpdate;
if (this._mode !== SceneMode_default.SCENE3D) {
const updateLength = polylinesToUpdate.length;
for (let i = 0; i < updateLength; ++i) {
polyline = polylinesToUpdate[i];
polyline.update();
}
}
if (properties[POSITION_SIZE_INDEX2] || properties[MATERIAL_INDEX2]) {
createVertexArrays(this, context, projection);
} else {
const length2 = polylinesToUpdate.length;
const polylineBuckets = this._polylineBuckets;
for (let ii = 0; ii < length2; ++ii) {
polyline = polylinesToUpdate[ii];
properties = polyline._propertiesChanged;
const bucket = polyline._bucket;
let index = 0;
for (const x in polylineBuckets) {
if (polylineBuckets.hasOwnProperty(x)) {
if (polylineBuckets[x] === bucket) {
if (properties[POSITION_INDEX4]) {
bucket.writeUpdate(
index,
polyline,
this._positionBuffer,
projection
);
}
break;
}
index += polylineBuckets[x].lengthOfPositions;
}
}
if (properties[SHOW_INDEX4] || properties[WIDTH_INDEX2]) {
this._batchTable.setBatchedAttribute(
polyline._index,
0,
new Cartesian2_default(polyline._width, polyline._show)
);
}
if (this._batchTable.attributes.length > 2) {
if (properties[POSITION_INDEX4] || properties[POSITION_SIZE_INDEX2]) {
const boundingSphere = frameState.mode === SceneMode_default.SCENE2D ? polyline._boundingVolume2D : polyline._boundingVolumeWC;
const encodedCenter = EncodedCartesian3_default.fromCartesian(
boundingSphere.center,
scratchUpdatePolylineEncodedCartesian
);
const low = Cartesian4_default.fromElements(
encodedCenter.low.x,
encodedCenter.low.y,
encodedCenter.low.z,
boundingSphere.radius,
scratchUpdatePolylineCartesian4
);
this._batchTable.setBatchedAttribute(
polyline._index,
2,
encodedCenter.high
);
this._batchTable.setBatchedAttribute(polyline._index, 3, low);
}
if (properties[DISTANCE_DISPLAY_CONDITION3]) {
const nearFarCartesian = scratchNearFarCartesian2;
nearFarCartesian.x = 0;
nearFarCartesian.y = Number.MAX_VALUE;
const distanceDisplayCondition = polyline.distanceDisplayCondition;
if (defined_default(distanceDisplayCondition)) {
nearFarCartesian.x = distanceDisplayCondition.near;
nearFarCartesian.y = distanceDisplayCondition.far;
}
this._batchTable.setBatchedAttribute(
polyline._index,
4,
nearFarCartesian
);
}
}
polyline._clean();
}
}
polylinesToUpdate.length = 0;
this._polylinesUpdated = false;
}
properties = this._propertiesChanged;
for (let k = 0; k < NUMBER_OF_PROPERTIES3; ++k) {
properties[k] = 0;
}
let modelMatrix = Matrix4_default.IDENTITY;
if (frameState.mode === SceneMode_default.SCENE3D) {
modelMatrix = this.modelMatrix;
}
const pass = frameState.passes;
const useDepthTest = frameState.morphTime !== 0;
if (!defined_default(this._opaqueRS) || this._opaqueRS.depthTest.enabled !== useDepthTest) {
this._opaqueRS = RenderState_default.fromCache({
depthMask: useDepthTest,
depthTest: {
enabled: useDepthTest
}
});
}
if (!defined_default(this._translucentRS) || this._translucentRS.depthTest.enabled !== useDepthTest) {
this._translucentRS = RenderState_default.fromCache({
blending: BlendingState_default.ALPHA_BLEND,
depthMask: !useDepthTest,
depthTest: {
enabled: useDepthTest
}
});
}
this._batchTable.update(frameState);
if (pass.render || pass.pick) {
const colorList = this._colorCommands;
createCommandLists(this, frameState, colorList, modelMatrix);
}
};
var boundingSphereScratch = new BoundingSphere_default();
var boundingSphereScratch2 = new BoundingSphere_default();
function createCommandLists(polylineCollection, frameState, commands, modelMatrix) {
const context = frameState.context;
const commandList = frameState.commandList;
const commandsLength = commands.length;
let commandIndex = 0;
let cloneBoundingSphere = true;
const vertexArrays = polylineCollection._vertexArrays;
const debugShowBoundingVolume2 = polylineCollection.debugShowBoundingVolume;
const batchTable = polylineCollection._batchTable;
const uniformCallback = batchTable.getUniformMapCallback();
const length2 = vertexArrays.length;
for (let m = 0; m < length2; ++m) {
const va = vertexArrays[m];
const buckets = va.buckets;
const bucketLength = buckets.length;
for (let n = 0; n < bucketLength; ++n) {
const bucketLocator = buckets[n];
let offset = bucketLocator.offset;
const sp = bucketLocator.bucket.shaderProgram;
const polylines = bucketLocator.bucket.polylines;
const polylineLength = polylines.length;
let currentId2;
let currentMaterial;
let count = 0;
let command;
let uniformMap2;
for (let s = 0; s < polylineLength; ++s) {
const polyline = polylines[s];
const mId = createMaterialId(polyline._material);
if (mId !== currentId2) {
if (defined_default(currentId2) && count > 0) {
const translucent = currentMaterial.isTranslucent();
if (commandIndex >= commandsLength) {
command = new DrawCommand_default({
owner: polylineCollection
});
commands.push(command);
} else {
command = commands[commandIndex];
}
++commandIndex;
uniformMap2 = combine_default(
uniformCallback(currentMaterial._uniforms),
polylineCollection._uniformMap
);
command.boundingVolume = BoundingSphere_default.clone(
boundingSphereScratch,
command.boundingVolume
);
command.modelMatrix = modelMatrix;
command.shaderProgram = sp;
command.vertexArray = va.va;
command.renderState = translucent ? polylineCollection._translucentRS : polylineCollection._opaqueRS;
command.pass = translucent ? Pass_default.TRANSLUCENT : Pass_default.OPAQUE;
command.debugShowBoundingVolume = debugShowBoundingVolume2;
command.pickId = "v_pickColor";
command.uniformMap = uniformMap2;
command.count = count;
command.offset = offset;
offset += count;
count = 0;
cloneBoundingSphere = true;
commandList.push(command);
}
currentMaterial = polyline._material;
currentMaterial.update(context);
currentId2 = mId;
}
const locators = polyline._locatorBuckets;
const locatorLength = locators.length;
for (let t = 0; t < locatorLength; ++t) {
const locator = locators[t];
if (locator.locator === bucketLocator) {
count += locator.count;
}
}
let boundingVolume;
if (frameState.mode === SceneMode_default.SCENE3D) {
boundingVolume = polyline._boundingVolumeWC;
} else if (frameState.mode === SceneMode_default.COLUMBUS_VIEW) {
boundingVolume = polyline._boundingVolume2D;
} else if (frameState.mode === SceneMode_default.SCENE2D) {
if (defined_default(polyline._boundingVolume2D)) {
boundingVolume = BoundingSphere_default.clone(
polyline._boundingVolume2D,
boundingSphereScratch2
);
boundingVolume.center.x = 0;
}
} else if (defined_default(polyline._boundingVolumeWC) && defined_default(polyline._boundingVolume2D)) {
boundingVolume = BoundingSphere_default.union(
polyline._boundingVolumeWC,
polyline._boundingVolume2D,
boundingSphereScratch2
);
}
if (cloneBoundingSphere) {
cloneBoundingSphere = false;
BoundingSphere_default.clone(boundingVolume, boundingSphereScratch);
} else {
BoundingSphere_default.union(
boundingVolume,
boundingSphereScratch,
boundingSphereScratch
);
}
}
if (defined_default(currentId2) && count > 0) {
if (commandIndex >= commandsLength) {
command = new DrawCommand_default({
owner: polylineCollection
});
commands.push(command);
} else {
command = commands[commandIndex];
}
++commandIndex;
uniformMap2 = combine_default(
uniformCallback(currentMaterial._uniforms),
polylineCollection._uniformMap
);
command.boundingVolume = BoundingSphere_default.clone(
boundingSphereScratch,
command.boundingVolume
);
command.modelMatrix = modelMatrix;
command.shaderProgram = sp;
command.vertexArray = va.va;
command.renderState = currentMaterial.isTranslucent() ? polylineCollection._translucentRS : polylineCollection._opaqueRS;
command.pass = currentMaterial.isTranslucent() ? Pass_default.TRANSLUCENT : Pass_default.OPAQUE;
command.debugShowBoundingVolume = debugShowBoundingVolume2;
command.pickId = "v_pickColor";
command.uniformMap = uniformMap2;
command.count = count;
command.offset = offset;
cloneBoundingSphere = true;
commandList.push(command);
}
currentId2 = void 0;
}
}
commands.length = commandIndex;
}
PolylineCollection.prototype.isDestroyed = function() {
return false;
};
PolylineCollection.prototype.destroy = function() {
destroyVertexArrays(this);
releaseShaders(this);
destroyPolylines(this);
this._batchTable = this._batchTable && this._batchTable.destroy();
return destroyObject_default(this);
};
function computeNewBuffersUsage(collection) {
let usageChanged = false;
const properties = collection._propertiesChanged;
const bufferUsage = collection._positionBufferUsage;
if (properties[POSITION_INDEX4]) {
if (bufferUsage.bufferUsage !== BufferUsage_default.STREAM_DRAW) {
usageChanged = true;
bufferUsage.bufferUsage = BufferUsage_default.STREAM_DRAW;
bufferUsage.frameCount = 100;
} else {
bufferUsage.frameCount = 100;
}
} else if (bufferUsage.bufferUsage !== BufferUsage_default.STATIC_DRAW) {
if (bufferUsage.frameCount === 0) {
usageChanged = true;
bufferUsage.bufferUsage = BufferUsage_default.STATIC_DRAW;
} else {
bufferUsage.frameCount--;
}
}
return usageChanged;
}
var emptyVertexBuffer = [0, 0, 0];
function createVertexArrays(collection, context, projection) {
collection._createVertexArray = false;
releaseShaders(collection);
destroyVertexArrays(collection);
sortPolylinesIntoBuckets(collection);
const totalIndices = [[]];
let indices = totalIndices[0];
const batchTable = collection._batchTable;
const useHighlightColor = collection._useHighlightColor;
const vertexBufferOffset = [0];
let offset = 0;
const vertexArrayBuckets = [[]];
let totalLength = 0;
const polylineBuckets = collection._polylineBuckets;
let x;
let bucket;
for (x in polylineBuckets) {
if (polylineBuckets.hasOwnProperty(x)) {
bucket = polylineBuckets[x];
bucket.updateShader(context, batchTable, useHighlightColor);
totalLength += bucket.lengthOfPositions;
}
}
if (totalLength > 0) {
const mode2 = collection._mode;
const positionArray = new Float32Array(6 * totalLength * 3);
const texCoordExpandAndBatchIndexArray = new Float32Array(totalLength * 4);
let position3DArray;
let positionIndex = 0;
let colorIndex = 0;
let texCoordExpandAndBatchIndexIndex = 0;
for (x in polylineBuckets) {
if (polylineBuckets.hasOwnProperty(x)) {
bucket = polylineBuckets[x];
bucket.write(
positionArray,
texCoordExpandAndBatchIndexArray,
positionIndex,
colorIndex,
texCoordExpandAndBatchIndexIndex,
batchTable,
context,
projection
);
if (mode2 === SceneMode_default.MORPHING) {
if (!defined_default(position3DArray)) {
position3DArray = new Float32Array(6 * totalLength * 3);
}
bucket.writeForMorph(position3DArray, positionIndex);
}
const bucketLength = bucket.lengthOfPositions;
positionIndex += 6 * bucketLength * 3;
colorIndex += bucketLength * 4;
texCoordExpandAndBatchIndexIndex += bucketLength * 4;
offset = bucket.updateIndices(
totalIndices,
vertexBufferOffset,
vertexArrayBuckets,
offset
);
}
}
const positionBufferUsage = collection._positionBufferUsage.bufferUsage;
const texCoordExpandAndBatchIndexBufferUsage = BufferUsage_default.STATIC_DRAW;
collection._positionBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: positionArray,
usage: positionBufferUsage
});
let position3DBuffer;
if (defined_default(position3DArray)) {
position3DBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: position3DArray,
usage: positionBufferUsage
});
}
collection._texCoordExpandAndBatchIndexBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: texCoordExpandAndBatchIndexArray,
usage: texCoordExpandAndBatchIndexBufferUsage
});
const positionSizeInBytes = 3 * Float32Array.BYTES_PER_ELEMENT;
const texCoordExpandAndBatchIndexSizeInBytes = 4 * Float32Array.BYTES_PER_ELEMENT;
let vbo = 0;
const numberOfIndicesArrays = totalIndices.length;
for (let k = 0; k < numberOfIndicesArrays; ++k) {
indices = totalIndices[k];
if (indices.length > 0) {
const indicesArray = new Uint16Array(indices);
const indexBuffer = Buffer_default.createIndexBuffer({
context,
typedArray: indicesArray,
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype: IndexDatatype_default.UNSIGNED_SHORT
});
vbo += vertexBufferOffset[k];
const positionHighOffset = 6 * (k * (positionSizeInBytes * Math_default.SIXTY_FOUR_KILOBYTES) - vbo * positionSizeInBytes);
const positionLowOffset = positionSizeInBytes + positionHighOffset;
const prevPositionHighOffset = positionSizeInBytes + positionLowOffset;
const prevPositionLowOffset = positionSizeInBytes + prevPositionHighOffset;
const nextPositionHighOffset = positionSizeInBytes + prevPositionLowOffset;
const nextPositionLowOffset = positionSizeInBytes + nextPositionHighOffset;
const vertexTexCoordExpandAndBatchIndexBufferOffset = k * (texCoordExpandAndBatchIndexSizeInBytes * Math_default.SIXTY_FOUR_KILOBYTES) - vbo * texCoordExpandAndBatchIndexSizeInBytes;
const attributes = [
{
index: attributeLocations2.position3DHigh,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: positionHighOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.position3DLow,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: positionLowOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.position2DHigh,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: positionHighOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.position2DLow,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: positionLowOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.prevPosition3DHigh,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: prevPositionHighOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.prevPosition3DLow,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: prevPositionLowOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.prevPosition2DHigh,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: prevPositionHighOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.prevPosition2DLow,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: prevPositionLowOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.nextPosition3DHigh,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: nextPositionHighOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.nextPosition3DLow,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: nextPositionLowOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.nextPosition2DHigh,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: nextPositionHighOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.nextPosition2DLow,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype_default.FLOAT,
offsetInBytes: nextPositionLowOffset,
strideInBytes: 6 * positionSizeInBytes
},
{
index: attributeLocations2.texCoordExpandAndBatchIndex,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
vertexBuffer: collection._texCoordExpandAndBatchIndexBuffer,
offsetInBytes: vertexTexCoordExpandAndBatchIndexBufferOffset
}
];
let bufferProperty3D;
let buffer3D;
let buffer2D;
let bufferProperty2D;
if (mode2 === SceneMode_default.SCENE3D) {
buffer3D = collection._positionBuffer;
bufferProperty3D = "vertexBuffer";
buffer2D = emptyVertexBuffer;
bufferProperty2D = "value";
} else if (mode2 === SceneMode_default.SCENE2D || mode2 === SceneMode_default.COLUMBUS_VIEW) {
buffer3D = emptyVertexBuffer;
bufferProperty3D = "value";
buffer2D = collection._positionBuffer;
bufferProperty2D = "vertexBuffer";
} else {
buffer3D = position3DBuffer;
bufferProperty3D = "vertexBuffer";
buffer2D = collection._positionBuffer;
bufferProperty2D = "vertexBuffer";
}
attributes[0][bufferProperty3D] = buffer3D;
attributes[1][bufferProperty3D] = buffer3D;
attributes[2][bufferProperty2D] = buffer2D;
attributes[3][bufferProperty2D] = buffer2D;
attributes[4][bufferProperty3D] = buffer3D;
attributes[5][bufferProperty3D] = buffer3D;
attributes[6][bufferProperty2D] = buffer2D;
attributes[7][bufferProperty2D] = buffer2D;
attributes[8][bufferProperty3D] = buffer3D;
attributes[9][bufferProperty3D] = buffer3D;
attributes[10][bufferProperty2D] = buffer2D;
attributes[11][bufferProperty2D] = buffer2D;
const va = new VertexArray_default({
context,
attributes,
indexBuffer
});
collection._vertexArrays.push({
va,
buckets: vertexArrayBuckets[k]
});
}
}
}
}
function replacer(key, value) {
if (value instanceof Texture_default) {
return value.id;
}
return value;
}
var scratchUniformArray2 = [];
function createMaterialId(material) {
const uniforms = Material_default._uniformList[material.type];
const length2 = uniforms.length;
scratchUniformArray2.length = 2 * length2;
let index = 0;
for (let i = 0; i < length2; ++i) {
const uniform = uniforms[i];
scratchUniformArray2[index] = uniform;
scratchUniformArray2[index + 1] = material._uniforms[uniform]();
index += 2;
}
return `${material.type}:${JSON.stringify(scratchUniformArray2, replacer)}`;
}
function sortPolylinesIntoBuckets(collection) {
const mode2 = collection._mode;
const modelMatrix = collection._modelMatrix;
const polylineBuckets = collection._polylineBuckets = {};
const polylines = collection._polylines;
const length2 = polylines.length;
for (let i = 0; i < length2; ++i) {
const p = polylines[i];
if (p._actualPositions.length > 1) {
p.update();
const material = p.material;
let value = polylineBuckets[material.type];
if (!defined_default(value)) {
value = polylineBuckets[material.type] = new PolylineBucket(
material,
mode2,
modelMatrix
);
}
value.addPolyline(p);
}
}
}
function updateMode2(collection, frameState) {
const mode2 = frameState.mode;
if (collection._mode !== mode2 || !Matrix4_default.equals(collection._modelMatrix, collection.modelMatrix)) {
collection._mode = mode2;
collection._modelMatrix = Matrix4_default.clone(collection.modelMatrix);
collection._createVertexArray = true;
}
}
function removePolylines(collection) {
if (collection._polylinesRemoved) {
collection._polylinesRemoved = false;
const definedPolylines = [];
const definedPolylinesToUpdate = [];
let polyIndex = 0;
let polyline;
const length2 = collection._polylines.length;
for (let i = 0; i < length2; ++i) {
polyline = collection._polylines[i];
if (!polyline.isDestroyed) {
polyline._index = polyIndex++;
definedPolylinesToUpdate.push(polyline);
definedPolylines.push(polyline);
}
}
collection._polylines = definedPolylines;
collection._polylinesToUpdate = definedPolylinesToUpdate;
}
}
function releaseShaders(collection) {
const polylines = collection._polylines;
const length2 = polylines.length;
for (let i = 0; i < length2; ++i) {
if (!polylines[i].isDestroyed) {
const bucket = polylines[i]._bucket;
if (defined_default(bucket)) {
bucket.shaderProgram = bucket.shaderProgram && bucket.shaderProgram.destroy();
}
}
}
}
function destroyVertexArrays(collection) {
const length2 = collection._vertexArrays.length;
for (let t = 0; t < length2; ++t) {
collection._vertexArrays[t].va.destroy();
}
collection._vertexArrays.length = 0;
}
PolylineCollection.prototype._updatePolyline = function(polyline, propertyChanged) {
this._polylinesUpdated = true;
if (!polyline._dirty) {
this._polylinesToUpdate.push(polyline);
}
++this._propertiesChanged[propertyChanged];
};
function destroyPolylines(collection) {
const polylines = collection._polylines;
const length2 = polylines.length;
for (let i = 0; i < length2; ++i) {
if (!polylines[i].isDestroyed) {
polylines[i]._destroy();
}
}
}
function VertexArrayBucketLocator(count, offset, bucket) {
this.count = count;
this.offset = offset;
this.bucket = bucket;
}
function PolylineBucket(material, mode2, modelMatrix) {
this.polylines = [];
this.lengthOfPositions = 0;
this.material = material;
this.shaderProgram = void 0;
this.mode = mode2;
this.modelMatrix = modelMatrix;
}
PolylineBucket.prototype.addPolyline = function(p) {
const polylines = this.polylines;
polylines.push(p);
p._actualLength = this.getPolylinePositionsLength(p);
this.lengthOfPositions += p._actualLength;
p._bucket = this;
};
PolylineBucket.prototype.updateShader = function(context, batchTable, useHighlightColor) {
if (defined_default(this.shaderProgram)) {
return;
}
const defines = ["DISTANCE_DISPLAY_CONDITION"];
if (useHighlightColor) {
defines.push("VECTOR_TILE");
}
if (this.material.shaderSource.search(/in\s+float\s+v_polylineAngle;/g) !== -1) {
defines.push("POLYLINE_DASH");
}
if (!FeatureDetection_default.isInternetExplorer()) {
defines.push("CLIP_POLYLINE");
}
const fs = new ShaderSource_default({
defines,
sources: ["in vec4 v_pickColor;\n", this.material.shaderSource, PolylineFS_default]
});
const vsSource = batchTable.getVertexShaderCallback()(PolylineVS_default);
const vs = new ShaderSource_default({
defines,
sources: [PolylineCommon_default, vsSource]
});
this.shaderProgram = ShaderProgram_default.fromCache({
context,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations2
});
};
function intersectsIDL(polyline) {
return Cartesian3_default.dot(Cartesian3_default.UNIT_X, polyline._boundingVolume.center) < 0 || polyline._boundingVolume.intersectPlane(Plane_default.ORIGIN_ZX_PLANE) === Intersect_default.INTERSECTING;
}
PolylineBucket.prototype.getPolylinePositionsLength = function(polyline) {
let length2;
if (this.mode === SceneMode_default.SCENE3D || !intersectsIDL(polyline)) {
length2 = polyline._actualPositions.length;
return length2 * 4 - 4;
}
let count = 0;
const segmentLengths = polyline._segments.lengths;
length2 = segmentLengths.length;
for (let i = 0; i < length2; ++i) {
count += segmentLengths[i] * 4 - 4;
}
return count;
};
var scratchWritePosition = new Cartesian3_default();
var scratchWritePrevPosition = new Cartesian3_default();
var scratchWriteNextPosition = new Cartesian3_default();
var scratchWriteVector = new Cartesian3_default();
var scratchPickColorCartesian = new Cartesian4_default();
var scratchWidthShowCartesian = new Cartesian2_default();
PolylineBucket.prototype.write = function(positionArray, texCoordExpandAndBatchIndexArray, positionIndex, colorIndex, texCoordExpandAndBatchIndexIndex, batchTable, context, projection) {
const mode2 = this.mode;
const maxLon = projection.ellipsoid.maximumRadius * Math_default.PI;
const polylines = this.polylines;
const length2 = polylines.length;
for (let i = 0; i < length2; ++i) {
const polyline = polylines[i];
const width = polyline.width;
const show = polyline.show && width > 0;
const polylineBatchIndex = polyline._index;
const segments = this.getSegments(polyline, projection);
const positions = segments.positions;
const lengths = segments.lengths;
const positionsLength = positions.length;
const pickColor = polyline.getPickId(context).color;
let segmentIndex = 0;
let count = 0;
let position;
for (let j = 0; j < positionsLength; ++j) {
if (j === 0) {
if (polyline._loop) {
position = positions[positionsLength - 2];
} else {
position = scratchWriteVector;
Cartesian3_default.subtract(positions[0], positions[1], position);
Cartesian3_default.add(positions[0], position, position);
}
} else {
position = positions[j - 1];
}
Cartesian3_default.clone(position, scratchWritePrevPosition);
Cartesian3_default.clone(positions[j], scratchWritePosition);
if (j === positionsLength - 1) {
if (polyline._loop) {
position = positions[1];
} else {
position = scratchWriteVector;
Cartesian3_default.subtract(
positions[positionsLength - 1],
positions[positionsLength - 2],
position
);
Cartesian3_default.add(positions[positionsLength - 1], position, position);
}
} else {
position = positions[j + 1];
}
Cartesian3_default.clone(position, scratchWriteNextPosition);
const segmentLength = lengths[segmentIndex];
if (j === count + segmentLength) {
count += segmentLength;
++segmentIndex;
}
const segmentStart = j - count === 0;
const segmentEnd = j === count + lengths[segmentIndex] - 1;
if (mode2 === SceneMode_default.SCENE2D) {
scratchWritePrevPosition.z = 0;
scratchWritePosition.z = 0;
scratchWriteNextPosition.z = 0;
}
if (mode2 === SceneMode_default.SCENE2D || mode2 === SceneMode_default.MORPHING) {
if ((segmentStart || segmentEnd) && maxLon - Math.abs(scratchWritePosition.x) < 1) {
if (scratchWritePosition.x < 0 && scratchWritePrevPosition.x > 0 || scratchWritePosition.x > 0 && scratchWritePrevPosition.x < 0) {
Cartesian3_default.clone(scratchWritePosition, scratchWritePrevPosition);
}
if (scratchWritePosition.x < 0 && scratchWriteNextPosition.x > 0 || scratchWritePosition.x > 0 && scratchWriteNextPosition.x < 0) {
Cartesian3_default.clone(scratchWritePosition, scratchWriteNextPosition);
}
}
}
const startK = segmentStart ? 2 : 0;
const endK = segmentEnd ? 2 : 4;
for (let k = startK; k < endK; ++k) {
EncodedCartesian3_default.writeElements(
scratchWritePosition,
positionArray,
positionIndex
);
EncodedCartesian3_default.writeElements(
scratchWritePrevPosition,
positionArray,
positionIndex + 6
);
EncodedCartesian3_default.writeElements(
scratchWriteNextPosition,
positionArray,
positionIndex + 12
);
const direction2 = k - 2 < 0 ? -1 : 1;
texCoordExpandAndBatchIndexArray[texCoordExpandAndBatchIndexIndex] = j / (positionsLength - 1);
texCoordExpandAndBatchIndexArray[texCoordExpandAndBatchIndexIndex + 1] = 2 * (k % 2) - 1;
texCoordExpandAndBatchIndexArray[texCoordExpandAndBatchIndexIndex + 2] = direction2;
texCoordExpandAndBatchIndexArray[texCoordExpandAndBatchIndexIndex + 3] = polylineBatchIndex;
positionIndex += 6 * 3;
texCoordExpandAndBatchIndexIndex += 4;
}
}
const colorCartesian = scratchPickColorCartesian;
colorCartesian.x = Color_default.floatToByte(pickColor.red);
colorCartesian.y = Color_default.floatToByte(pickColor.green);
colorCartesian.z = Color_default.floatToByte(pickColor.blue);
colorCartesian.w = Color_default.floatToByte(pickColor.alpha);
const widthShowCartesian = scratchWidthShowCartesian;
widthShowCartesian.x = width;
widthShowCartesian.y = show ? 1 : 0;
const boundingSphere = mode2 === SceneMode_default.SCENE2D ? polyline._boundingVolume2D : polyline._boundingVolumeWC;
const encodedCenter = EncodedCartesian3_default.fromCartesian(
boundingSphere.center,
scratchUpdatePolylineEncodedCartesian
);
const high = encodedCenter.high;
const low = Cartesian4_default.fromElements(
encodedCenter.low.x,
encodedCenter.low.y,
encodedCenter.low.z,
boundingSphere.radius,
scratchUpdatePolylineCartesian4
);
const nearFarCartesian = scratchNearFarCartesian2;
nearFarCartesian.x = 0;
nearFarCartesian.y = Number.MAX_VALUE;
const distanceDisplayCondition = polyline.distanceDisplayCondition;
if (defined_default(distanceDisplayCondition)) {
nearFarCartesian.x = distanceDisplayCondition.near;
nearFarCartesian.y = distanceDisplayCondition.far;
}
batchTable.setBatchedAttribute(polylineBatchIndex, 0, widthShowCartesian);
batchTable.setBatchedAttribute(polylineBatchIndex, 1, colorCartesian);
if (batchTable.attributes.length > 2) {
batchTable.setBatchedAttribute(polylineBatchIndex, 2, high);
batchTable.setBatchedAttribute(polylineBatchIndex, 3, low);
batchTable.setBatchedAttribute(polylineBatchIndex, 4, nearFarCartesian);
}
}
};
var morphPositionScratch = new Cartesian3_default();
var morphPrevPositionScratch = new Cartesian3_default();
var morphNextPositionScratch = new Cartesian3_default();
var morphVectorScratch = new Cartesian3_default();
PolylineBucket.prototype.writeForMorph = function(positionArray, positionIndex) {
const modelMatrix = this.modelMatrix;
const polylines = this.polylines;
const length2 = polylines.length;
for (let i = 0; i < length2; ++i) {
const polyline = polylines[i];
const positions = polyline._segments.positions;
const lengths = polyline._segments.lengths;
const positionsLength = positions.length;
let segmentIndex = 0;
let count = 0;
for (let j = 0; j < positionsLength; ++j) {
let prevPosition;
if (j === 0) {
if (polyline._loop) {
prevPosition = positions[positionsLength - 2];
} else {
prevPosition = morphVectorScratch;
Cartesian3_default.subtract(positions[0], positions[1], prevPosition);
Cartesian3_default.add(positions[0], prevPosition, prevPosition);
}
} else {
prevPosition = positions[j - 1];
}
prevPosition = Matrix4_default.multiplyByPoint(
modelMatrix,
prevPosition,
morphPrevPositionScratch
);
const position = Matrix4_default.multiplyByPoint(
modelMatrix,
positions[j],
morphPositionScratch
);
let nextPosition;
if (j === positionsLength - 1) {
if (polyline._loop) {
nextPosition = positions[1];
} else {
nextPosition = morphVectorScratch;
Cartesian3_default.subtract(
positions[positionsLength - 1],
positions[positionsLength - 2],
nextPosition
);
Cartesian3_default.add(
positions[positionsLength - 1],
nextPosition,
nextPosition
);
}
} else {
nextPosition = positions[j + 1];
}
nextPosition = Matrix4_default.multiplyByPoint(
modelMatrix,
nextPosition,
morphNextPositionScratch
);
const segmentLength = lengths[segmentIndex];
if (j === count + segmentLength) {
count += segmentLength;
++segmentIndex;
}
const segmentStart = j - count === 0;
const segmentEnd = j === count + lengths[segmentIndex] - 1;
const startK = segmentStart ? 2 : 0;
const endK = segmentEnd ? 2 : 4;
for (let k = startK; k < endK; ++k) {
EncodedCartesian3_default.writeElements(position, positionArray, positionIndex);
EncodedCartesian3_default.writeElements(
prevPosition,
positionArray,
positionIndex + 6
);
EncodedCartesian3_default.writeElements(
nextPosition,
positionArray,
positionIndex + 12
);
positionIndex += 6 * 3;
}
}
}
};
var scratchSegmentLengths = new Array(1);
PolylineBucket.prototype.updateIndices = function(totalIndices, vertexBufferOffset, vertexArrayBuckets, offset) {
let vaCount = vertexArrayBuckets.length - 1;
let bucketLocator = new VertexArrayBucketLocator(0, offset, this);
vertexArrayBuckets[vaCount].push(bucketLocator);
let count = 0;
let indices = totalIndices[totalIndices.length - 1];
let indicesCount = 0;
if (indices.length > 0) {
indicesCount = indices[indices.length - 1] + 1;
}
const polylines = this.polylines;
const length2 = polylines.length;
for (let i = 0; i < length2; ++i) {
const polyline = polylines[i];
polyline._locatorBuckets = [];
let segments;
if (this.mode === SceneMode_default.SCENE3D) {
segments = scratchSegmentLengths;
const positionsLength = polyline._actualPositions.length;
if (positionsLength > 0) {
segments[0] = positionsLength;
} else {
continue;
}
} else {
segments = polyline._segments.lengths;
}
const numberOfSegments = segments.length;
if (numberOfSegments > 0) {
let segmentIndexCount = 0;
for (let j = 0; j < numberOfSegments; ++j) {
const segmentLength = segments[j] - 1;
for (let k = 0; k < segmentLength; ++k) {
if (indicesCount + 4 > Math_default.SIXTY_FOUR_KILOBYTES) {
polyline._locatorBuckets.push({
locator: bucketLocator,
count: segmentIndexCount
});
segmentIndexCount = 0;
vertexBufferOffset.push(4);
indices = [];
totalIndices.push(indices);
indicesCount = 0;
bucketLocator.count = count;
count = 0;
offset = 0;
bucketLocator = new VertexArrayBucketLocator(0, 0, this);
vertexArrayBuckets[++vaCount] = [bucketLocator];
}
indices.push(indicesCount, indicesCount + 2, indicesCount + 1);
indices.push(indicesCount + 1, indicesCount + 2, indicesCount + 3);
segmentIndexCount += 6;
count += 6;
offset += 6;
indicesCount += 4;
}
}
polyline._locatorBuckets.push({
locator: bucketLocator,
count: segmentIndexCount
});
if (indicesCount + 4 > Math_default.SIXTY_FOUR_KILOBYTES) {
vertexBufferOffset.push(0);
indices = [];
totalIndices.push(indices);
indicesCount = 0;
bucketLocator.count = count;
offset = 0;
count = 0;
bucketLocator = new VertexArrayBucketLocator(0, 0, this);
vertexArrayBuckets[++vaCount] = [bucketLocator];
}
}
polyline._clean();
}
bucketLocator.count = count;
return offset;
};
PolylineBucket.prototype.getPolylineStartIndex = function(polyline) {
const polylines = this.polylines;
let positionIndex = 0;
const length2 = polylines.length;
for (let i = 0; i < length2; ++i) {
const p = polylines[i];
if (p === polyline) {
break;
}
positionIndex += p._actualLength;
}
return positionIndex;
};
var scratchSegments = {
positions: void 0,
lengths: void 0
};
var scratchLengths = new Array(1);
var pscratch = new Cartesian3_default();
var scratchCartographic8 = new Cartographic_default();
PolylineBucket.prototype.getSegments = function(polyline, projection) {
let positions = polyline._actualPositions;
if (this.mode === SceneMode_default.SCENE3D) {
scratchLengths[0] = positions.length;
scratchSegments.positions = positions;
scratchSegments.lengths = scratchLengths;
return scratchSegments;
}
if (intersectsIDL(polyline)) {
positions = polyline._segments.positions;
}
const ellipsoid = projection.ellipsoid;
const newPositions = [];
const modelMatrix = this.modelMatrix;
const length2 = positions.length;
let position;
let p = pscratch;
for (let n = 0; n < length2; ++n) {
position = positions[n];
p = Matrix4_default.multiplyByPoint(modelMatrix, position, p);
newPositions.push(
projection.project(
ellipsoid.cartesianToCartographic(p, scratchCartographic8)
)
);
}
if (newPositions.length > 0) {
polyline._boundingVolume2D = BoundingSphere_default.fromPoints(
newPositions,
polyline._boundingVolume2D
);
const center2D = polyline._boundingVolume2D.center;
polyline._boundingVolume2D.center = new Cartesian3_default(
center2D.z,
center2D.x,
center2D.y
);
}
scratchSegments.positions = newPositions;
scratchSegments.lengths = polyline._segments.lengths;
return scratchSegments;
};
var scratchPositionsArray;
PolylineBucket.prototype.writeUpdate = function(index, polyline, positionBuffer, projection) {
const mode2 = this.mode;
const maxLon = projection.ellipsoid.maximumRadius * Math_default.PI;
let positionsLength = polyline._actualLength;
if (positionsLength) {
index += this.getPolylineStartIndex(polyline);
let positionArray = scratchPositionsArray;
const positionsArrayLength = 6 * positionsLength * 3;
if (!defined_default(positionArray) || positionArray.length < positionsArrayLength) {
positionArray = scratchPositionsArray = new Float32Array(
positionsArrayLength
);
} else if (positionArray.length > positionsArrayLength) {
positionArray = new Float32Array(
positionArray.buffer,
0,
positionsArrayLength
);
}
const segments = this.getSegments(polyline, projection);
const positions = segments.positions;
const lengths = segments.lengths;
let positionIndex = 0;
let segmentIndex = 0;
let count = 0;
let position;
positionsLength = positions.length;
for (let i = 0; i < positionsLength; ++i) {
if (i === 0) {
if (polyline._loop) {
position = positions[positionsLength - 2];
} else {
position = scratchWriteVector;
Cartesian3_default.subtract(positions[0], positions[1], position);
Cartesian3_default.add(positions[0], position, position);
}
} else {
position = positions[i - 1];
}
Cartesian3_default.clone(position, scratchWritePrevPosition);
Cartesian3_default.clone(positions[i], scratchWritePosition);
if (i === positionsLength - 1) {
if (polyline._loop) {
position = positions[1];
} else {
position = scratchWriteVector;
Cartesian3_default.subtract(
positions[positionsLength - 1],
positions[positionsLength - 2],
position
);
Cartesian3_default.add(positions[positionsLength - 1], position, position);
}
} else {
position = positions[i + 1];
}
Cartesian3_default.clone(position, scratchWriteNextPosition);
const segmentLength = lengths[segmentIndex];
if (i === count + segmentLength) {
count += segmentLength;
++segmentIndex;
}
const segmentStart = i - count === 0;
const segmentEnd = i === count + lengths[segmentIndex] - 1;
if (mode2 === SceneMode_default.SCENE2D) {
scratchWritePrevPosition.z = 0;
scratchWritePosition.z = 0;
scratchWriteNextPosition.z = 0;
}
if (mode2 === SceneMode_default.SCENE2D || mode2 === SceneMode_default.MORPHING) {
if ((segmentStart || segmentEnd) && maxLon - Math.abs(scratchWritePosition.x) < 1) {
if (scratchWritePosition.x < 0 && scratchWritePrevPosition.x > 0 || scratchWritePosition.x > 0 && scratchWritePrevPosition.x < 0) {
Cartesian3_default.clone(scratchWritePosition, scratchWritePrevPosition);
}
if (scratchWritePosition.x < 0 && scratchWriteNextPosition.x > 0 || scratchWritePosition.x > 0 && scratchWriteNextPosition.x < 0) {
Cartesian3_default.clone(scratchWritePosition, scratchWriteNextPosition);
}
}
}
const startJ = segmentStart ? 2 : 0;
const endJ = segmentEnd ? 2 : 4;
for (let j = startJ; j < endJ; ++j) {
EncodedCartesian3_default.writeElements(
scratchWritePosition,
positionArray,
positionIndex
);
EncodedCartesian3_default.writeElements(
scratchWritePrevPosition,
positionArray,
positionIndex + 6
);
EncodedCartesian3_default.writeElements(
scratchWriteNextPosition,
positionArray,
positionIndex + 12
);
positionIndex += 6 * 3;
}
}
positionBuffer.copyFromArrayView(
positionArray,
6 * 3 * Float32Array.BYTES_PER_ELEMENT * index
);
}
};
var PolylineCollection_default = PolylineCollection;
// packages/engine/Source/Scene/Vector3DTilePoints.js
function Vector3DTilePoints(options) {
this._positions = options.positions;
this._batchTable = options.batchTable;
this._batchIds = options.batchIds;
this._rectangle = options.rectangle;
this._minHeight = options.minimumHeight;
this._maxHeight = options.maximumHeight;
this._heightReference = options.heightReference;
this._billboardCollection = new BillboardCollection_default({
batchTable: options.batchTable,
scene: options.scene
});
this._labelCollection = new LabelCollection_default({
batchTable: options.batchTable,
scene: options.scene
});
this._polylineCollection = new PolylineCollection_default();
this._polylineCollection._useHighlightColor = true;
this._packedBuffer = void 0;
this._ready = false;
this._promise = void 0;
this._error = void 0;
}
Object.defineProperties(Vector3DTilePoints.prototype, {
/**
* Returns true if the points are ready to render
*
* @memberof Vector3DTilePoints.prototype
*
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
return this._ready;
}
},
/**
* Gets the number of points.
*
* @memberof Vector3DTilePoints.prototype
*
* @type {number}
* @readonly
* @private
*/
pointsLength: {
get: function() {
return this._billboardCollection.length;
}
},
/**
* Gets the texture atlas memory in bytes.
*
* @memberof Vector3DTilePoints.prototype
*
* @type {number}
* @readonly
* @private
*/
texturesByteLength: {
get: function() {
const billboardSize = this._billboardCollection.sizeInBytes;
const labelSize = this._labelCollection.sizeInBytes;
return billboardSize + labelSize;
}
}
});
function packBuffer2(points, ellipsoid) {
const rectangle = points._rectangle;
const minimumHeight = points._minHeight;
const maximumHeight = points._maxHeight;
const packedLength = 2 + Rectangle_default.packedLength + Ellipsoid_default.packedLength;
const packedBuffer = new Float64Array(packedLength);
let offset = 0;
packedBuffer[offset++] = minimumHeight;
packedBuffer[offset++] = maximumHeight;
Rectangle_default.pack(rectangle, packedBuffer, offset);
offset += Rectangle_default.packedLength;
Ellipsoid_default.pack(ellipsoid, packedBuffer, offset);
return packedBuffer;
}
var createVerticesTaskProcessor2 = new TaskProcessor_default(
"createVectorTilePoints",
5
);
var scratchPosition6 = new Cartesian3_default();
function createPoints(points, ellipsoid) {
let positions = points._positions;
let packedBuffer = points._packedBuffer;
if (!defined_default(packedBuffer)) {
positions = points._positions = positions.slice();
points._batchIds = points._batchIds.slice();
packedBuffer = points._packedBuffer = packBuffer2(points, ellipsoid);
}
const transferrableObjects = [positions.buffer, packedBuffer.buffer];
const parameters = {
positions: positions.buffer,
packedBuffer: packedBuffer.buffer
};
const verticesPromise = createVerticesTaskProcessor2.scheduleTask(
parameters,
transferrableObjects
);
if (!defined_default(verticesPromise)) {
return;
}
return verticesPromise.then((result) => {
if (points.isDestroyed()) {
return;
}
points._positions = new Float64Array(result.positions);
const billboardCollection = points._billboardCollection;
const labelCollection = points._labelCollection;
const polylineCollection = points._polylineCollection;
positions = points._positions;
const batchIds = points._batchIds;
const numberOfPoints = positions.length / 3;
const heightReference = points._heightReference ?? HeightReference_default.NONE;
for (let i = 0; i < numberOfPoints; ++i) {
const id = batchIds[i];
const position = Cartesian3_default.unpack(positions, i * 3, scratchPosition6);
const b = billboardCollection.add();
b.position = position;
b._batchIndex = id;
b.heightReference = heightReference;
const l = labelCollection.add();
l.text = " ";
l.position = position;
l._batchIndex = id;
l.heightReference = heightReference;
const p = polylineCollection.add();
p.positions = [Cartesian3_default.clone(position), Cartesian3_default.clone(position)];
}
points._positions = void 0;
points._packedBuffer = void 0;
points._ready = true;
}).catch((error) => {
if (points.isDestroyed()) {
return;
}
points._error = error;
});
}
Vector3DTilePoints.prototype.createFeatures = function(content, features) {
const billboardCollection = this._billboardCollection;
const labelCollection = this._labelCollection;
const polylineCollection = this._polylineCollection;
const batchIds = this._batchIds;
const length2 = batchIds.length;
for (let i = 0; i < length2; ++i) {
const batchId = batchIds[i];
const billboard = billboardCollection.get(i);
const label = labelCollection.get(i);
const polyline = polylineCollection.get(i);
features[batchId] = new Cesium3DTilePointFeature_default(
content,
batchId,
billboard,
label,
polyline
);
}
};
Vector3DTilePoints.prototype.applyDebugSettings = function(enabled, color) {
if (enabled) {
Color_default.clone(color, this._billboardCollection._highlightColor);
Color_default.clone(color, this._labelCollection._highlightColor);
Color_default.clone(color, this._polylineCollection._highlightColor);
} else {
Color_default.clone(Color_default.WHITE, this._billboardCollection._highlightColor);
Color_default.clone(Color_default.WHITE, this._labelCollection._highlightColor);
Color_default.clone(Color_default.WHITE, this._polylineCollection._highlightColor);
}
};
function clearStyle2(polygons, features) {
const batchIds = polygons._batchIds;
const length2 = batchIds.length;
for (let i = 0; i < length2; ++i) {
const batchId = batchIds[i];
const feature2 = features[batchId];
feature2.show = true;
feature2.pointSize = Cesium3DTilePointFeature_default.defaultPointSize;
feature2.color = Cesium3DTilePointFeature_default.defaultColor;
feature2.pointOutlineColor = Cesium3DTilePointFeature_default.defaultPointOutlineColor;
feature2.pointOutlineWidth = Cesium3DTilePointFeature_default.defaultPointOutlineWidth;
feature2.labelColor = Color_default.WHITE;
feature2.labelOutlineColor = Color_default.WHITE;
feature2.labelOutlineWidth = 1;
feature2.font = "30px sans-serif";
feature2.labelStyle = LabelStyle_default.FILL;
feature2.labelText = void 0;
feature2.backgroundColor = new Color_default(0.165, 0.165, 0.165, 0.8);
feature2.backgroundPadding = new Cartesian2_default(7, 5);
feature2.backgroundEnabled = false;
feature2.scaleByDistance = void 0;
feature2.translucencyByDistance = void 0;
feature2.distanceDisplayCondition = void 0;
feature2.heightOffset = 0;
feature2.anchorLineEnabled = false;
feature2.anchorLineColor = Color_default.WHITE;
feature2.image = void 0;
feature2.disableDepthTestDistance = 0;
feature2.horizontalOrigin = HorizontalOrigin_default.CENTER;
feature2.verticalOrigin = VerticalOrigin_default.CENTER;
feature2.labelHorizontalOrigin = HorizontalOrigin_default.RIGHT;
feature2.labelVerticalOrigin = VerticalOrigin_default.BASELINE;
}
}
var scratchColor9 = new Color_default();
var scratchColor22 = new Color_default();
var scratchColor32 = new Color_default();
var scratchColor42 = new Color_default();
var scratchColor52 = new Color_default();
var scratchColor62 = new Color_default();
var scratchScaleByDistance = new NearFarScalar_default();
var scratchTranslucencyByDistance = new NearFarScalar_default();
var scratchDistanceDisplayCondition = new DistanceDisplayCondition_default();
Vector3DTilePoints.prototype.applyStyle = function(style, features) {
if (!defined_default(style)) {
clearStyle2(this, features);
return;
}
const batchIds = this._batchIds;
const length2 = batchIds.length;
for (let i = 0; i < length2; ++i) {
const batchId = batchIds[i];
const feature2 = features[batchId];
if (defined_default(style.show)) {
feature2.show = style.show.evaluate(feature2);
}
if (defined_default(style.pointSize)) {
feature2.pointSize = style.pointSize.evaluate(feature2);
}
if (defined_default(style.color)) {
feature2.color = style.color.evaluateColor(feature2, scratchColor9);
}
if (defined_default(style.pointOutlineColor)) {
feature2.pointOutlineColor = style.pointOutlineColor.evaluateColor(
feature2,
scratchColor22
);
}
if (defined_default(style.pointOutlineWidth)) {
feature2.pointOutlineWidth = style.pointOutlineWidth.evaluate(feature2);
}
if (defined_default(style.labelColor)) {
feature2.labelColor = style.labelColor.evaluateColor(
feature2,
scratchColor32
);
}
if (defined_default(style.labelOutlineColor)) {
feature2.labelOutlineColor = style.labelOutlineColor.evaluateColor(
feature2,
scratchColor42
);
}
if (defined_default(style.labelOutlineWidth)) {
feature2.labelOutlineWidth = style.labelOutlineWidth.evaluate(feature2);
}
if (defined_default(style.font)) {
feature2.font = style.font.evaluate(feature2);
}
if (defined_default(style.labelStyle)) {
feature2.labelStyle = style.labelStyle.evaluate(feature2);
}
if (defined_default(style.labelText)) {
feature2.labelText = style.labelText.evaluate(feature2);
} else {
feature2.labelText = void 0;
}
if (defined_default(style.backgroundColor)) {
feature2.backgroundColor = style.backgroundColor.evaluateColor(
feature2,
scratchColor52
);
}
if (defined_default(style.backgroundPadding)) {
feature2.backgroundPadding = style.backgroundPadding.evaluate(feature2);
}
if (defined_default(style.backgroundEnabled)) {
feature2.backgroundEnabled = style.backgroundEnabled.evaluate(feature2);
}
if (defined_default(style.scaleByDistance)) {
const scaleByDistanceCart4 = style.scaleByDistance.evaluate(feature2);
if (defined_default(scaleByDistanceCart4)) {
scratchScaleByDistance.near = scaleByDistanceCart4.x;
scratchScaleByDistance.nearValue = scaleByDistanceCart4.y;
scratchScaleByDistance.far = scaleByDistanceCart4.z;
scratchScaleByDistance.farValue = scaleByDistanceCart4.w;
feature2.scaleByDistance = scratchScaleByDistance;
} else {
feature2.scaleByDistance = void 0;
}
} else {
feature2.scaleByDistance = void 0;
}
if (defined_default(style.translucencyByDistance)) {
const translucencyByDistanceCart4 = style.translucencyByDistance.evaluate(feature2);
if (defined_default(translucencyByDistanceCart4)) {
scratchTranslucencyByDistance.near = translucencyByDistanceCart4.x;
scratchTranslucencyByDistance.nearValue = translucencyByDistanceCart4.y;
scratchTranslucencyByDistance.far = translucencyByDistanceCart4.z;
scratchTranslucencyByDistance.farValue = translucencyByDistanceCart4.w;
feature2.translucencyByDistance = scratchTranslucencyByDistance;
} else {
feature2.translucencyByDistance = void 0;
}
} else {
feature2.translucencyByDistance = void 0;
}
if (defined_default(style.distanceDisplayCondition)) {
const distanceDisplayConditionCart2 = style.distanceDisplayCondition.evaluate(feature2);
if (defined_default(distanceDisplayConditionCart2)) {
scratchDistanceDisplayCondition.near = distanceDisplayConditionCart2.x;
scratchDistanceDisplayCondition.far = distanceDisplayConditionCart2.y;
feature2.distanceDisplayCondition = scratchDistanceDisplayCondition;
} else {
feature2.distanceDisplayCondition = void 0;
}
} else {
feature2.distanceDisplayCondition = void 0;
}
if (defined_default(style.heightOffset)) {
feature2.heightOffset = style.heightOffset.evaluate(feature2);
}
if (defined_default(style.anchorLineEnabled)) {
feature2.anchorLineEnabled = style.anchorLineEnabled.evaluate(feature2);
}
if (defined_default(style.anchorLineColor)) {
feature2.anchorLineColor = style.anchorLineColor.evaluateColor(
feature2,
scratchColor62
);
}
if (defined_default(style.image)) {
feature2.image = style.image.evaluate(feature2);
} else {
feature2.image = void 0;
}
if (defined_default(style.disableDepthTestDistance)) {
feature2.disableDepthTestDistance = style.disableDepthTestDistance.evaluate(feature2);
}
if (defined_default(style.horizontalOrigin)) {
feature2.horizontalOrigin = style.horizontalOrigin.evaluate(feature2);
}
if (defined_default(style.verticalOrigin)) {
feature2.verticalOrigin = style.verticalOrigin.evaluate(feature2);
}
if (defined_default(style.labelHorizontalOrigin)) {
feature2.labelHorizontalOrigin = style.labelHorizontalOrigin.evaluate(feature2);
}
if (defined_default(style.labelVerticalOrigin)) {
feature2.labelVerticalOrigin = style.labelVerticalOrigin.evaluate(feature2);
}
}
};
Vector3DTilePoints.prototype.update = function(frameState) {
if (!this._ready) {
if (!defined_default(this._promise)) {
this._promise = createPoints(this, frameState.mapProjection.ellipsoid);
}
if (defined_default(this._error)) {
const error = this._error;
this._error = void 0;
throw error;
}
}
this._polylineCollection.update(frameState);
this._billboardCollection.update(frameState);
this._labelCollection.update(frameState);
};
Vector3DTilePoints.prototype.isDestroyed = function() {
return false;
};
Vector3DTilePoints.prototype.destroy = function() {
this._billboardCollection = this._billboardCollection && this._billboardCollection.destroy();
this._labelCollection = this._labelCollection && this._labelCollection.destroy();
this._polylineCollection = this._polylineCollection && this._polylineCollection.destroy();
return destroyObject_default(this);
};
var Vector3DTilePoints_default = Vector3DTilePoints;
// packages/engine/Source/Scene/Vector3DTilePolygons.js
var import_InlineWorkers758 = __toESM(require_InlineWorkers(), 1);
function Vector3DTilePolygons(options) {
this._batchTable = options.batchTable;
this._batchIds = options.batchIds;
this._positions = options.positions;
this._counts = options.counts;
this._indices = options.indices;
this._indexCounts = options.indexCounts;
this._indexOffsets = void 0;
this._batchTableColors = void 0;
this._packedBuffer = void 0;
this._batchedPositions = void 0;
this._transferrableBatchIds = void 0;
this._vertexBatchIds = void 0;
this._ellipsoid = options.ellipsoid ?? Ellipsoid_default.WGS84;
this._minimumHeight = options.minimumHeight;
this._maximumHeight = options.maximumHeight;
this._polygonMinimumHeights = options.polygonMinimumHeights;
this._polygonMaximumHeights = options.polygonMaximumHeights;
this._center = options.center ?? Cartesian3_default.ZERO;
this._rectangle = options.rectangle;
this._center = void 0;
this._boundingVolume = options.boundingVolume;
this._boundingVolumes = void 0;
this._batchedIndices = void 0;
this._ready = false;
this._promise = void 0;
this._error = void 0;
this._primitive = void 0;
this.debugWireframe = false;
this.forceRebatch = false;
this.classificationType = ClassificationType_default.BOTH;
}
Object.defineProperties(Vector3DTilePolygons.prototype, {
/**
* Gets the number of triangles.
*
* @memberof Vector3DTilePolygons.prototype
*
* @type {number}
* @readonly
* @private
*/
trianglesLength: {
get: function() {
if (defined_default(this._primitive)) {
return this._primitive.trianglesLength;
}
return 0;
}
},
/**
* Gets the geometry memory in bytes.
*
* @memberof Vector3DTilePolygons.prototype
*
* @type {number}
* @readonly
* @private
*/
geometryByteLength: {
get: function() {
if (defined_default(this._primitive)) {
return this._primitive.geometryByteLength;
}
return 0;
}
},
/**
* Returns true when the primitive is ready to render.
* @memberof Vector3DTilePolygons.prototype
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
return this._ready;
}
}
});
function packBuffer3(polygons) {
const packedBuffer = new Float64Array(
3 + Cartesian3_default.packedLength + Ellipsoid_default.packedLength + Rectangle_default.packedLength
);
let offset = 0;
packedBuffer[offset++] = polygons._indices.BYTES_PER_ELEMENT;
packedBuffer[offset++] = polygons._minimumHeight;
packedBuffer[offset++] = polygons._maximumHeight;
Cartesian3_default.pack(polygons._center, packedBuffer, offset);
offset += Cartesian3_default.packedLength;
Ellipsoid_default.pack(polygons._ellipsoid, packedBuffer, offset);
offset += Ellipsoid_default.packedLength;
Rectangle_default.pack(polygons._rectangle, packedBuffer, offset);
return packedBuffer;
}
function unpackBuffer2(polygons, packedBuffer) {
let offset = 1;
const numBVS = packedBuffer[offset++];
const bvs = polygons._boundingVolumes = new Array(numBVS);
for (let i = 0; i < numBVS; ++i) {
bvs[i] = OrientedBoundingBox_default.unpack(packedBuffer, offset);
offset += OrientedBoundingBox_default.packedLength;
}
const numBatchedIndices = packedBuffer[offset++];
const bis = polygons._batchedIndices = new Array(numBatchedIndices);
for (let j = 0; j < numBatchedIndices; ++j) {
const color = Color_default.unpack(packedBuffer, offset);
offset += Color_default.packedLength;
const indexOffset = packedBuffer[offset++];
const count = packedBuffer[offset++];
const length2 = packedBuffer[offset++];
const batchIds = new Array(length2);
for (let k = 0; k < length2; ++k) {
batchIds[k] = packedBuffer[offset++];
}
bis[j] = new Vector3DTileBatch_default({
color,
offset: indexOffset,
count,
batchIds
});
}
}
var createVerticesTaskProcessor3 = new TaskProcessor_default(
"createVectorTilePolygons",
5
);
var scratchColor10 = new Color_default();
function createPrimitive2(polygons) {
if (defined_default(polygons._primitive)) {
return;
}
let positions = polygons._positions;
let counts = polygons._counts;
let indexCounts = polygons._indexCounts;
let indices = polygons._indices;
let batchIds = polygons._transferrableBatchIds;
let batchTableColors = polygons._batchTableColors;
let packedBuffer = polygons._packedBuffer;
if (!defined_default(batchTableColors)) {
positions = polygons._positions = polygons._positions.slice();
counts = polygons._counts = polygons._counts.slice();
indexCounts = polygons._indexCounts = polygons._indexCounts.slice();
indices = polygons._indices = polygons._indices.slice();
polygons._center = polygons._ellipsoid.cartographicToCartesian(
Rectangle_default.center(polygons._rectangle)
);
batchIds = polygons._transferrableBatchIds = new Uint32Array(
polygons._batchIds
);
batchTableColors = polygons._batchTableColors = new Uint32Array(
batchIds.length
);
const batchTable = polygons._batchTable;
const length2 = batchTableColors.length;
for (let i = 0; i < length2; ++i) {
const color = batchTable.getColor(i, scratchColor10);
batchTableColors[i] = color.toRgba();
}
packedBuffer = polygons._packedBuffer = packBuffer3(polygons);
}
const transferrableObjects = [
positions.buffer,
counts.buffer,
indexCounts.buffer,
indices.buffer,
batchIds.buffer,
batchTableColors.buffer,
packedBuffer.buffer
];
const parameters = {
packedBuffer: packedBuffer.buffer,
positions: positions.buffer,
counts: counts.buffer,
indexCounts: indexCounts.buffer,
indices: indices.buffer,
batchIds: batchIds.buffer,
batchTableColors: batchTableColors.buffer
};
let minimumHeights = polygons._polygonMinimumHeights;
let maximumHeights = polygons._polygonMaximumHeights;
if (defined_default(minimumHeights) && defined_default(maximumHeights)) {
minimumHeights = minimumHeights.slice();
maximumHeights = maximumHeights.slice();
transferrableObjects.push(minimumHeights.buffer, maximumHeights.buffer);
parameters.minimumHeights = minimumHeights;
parameters.maximumHeights = maximumHeights;
}
const verticesPromise = createVerticesTaskProcessor3.scheduleTask(
parameters,
transferrableObjects
);
if (!defined_default(verticesPromise)) {
return;
}
return verticesPromise.then((result) => {
if (polygons.isDestroyed()) {
return;
}
polygons._positions = void 0;
polygons._counts = void 0;
polygons._polygonMinimumHeights = void 0;
polygons._polygonMaximumHeights = void 0;
const packedBuffer2 = new Float64Array(result.packedBuffer);
const indexDatatype = packedBuffer2[0];
unpackBuffer2(polygons, packedBuffer2);
polygons._indices = IndexDatatype_default.getSizeInBytes(indexDatatype) === 2 ? new Uint16Array(result.indices) : new Uint32Array(result.indices);
polygons._indexOffsets = new Uint32Array(result.indexOffsets);
polygons._indexCounts = new Uint32Array(result.indexCounts);
polygons._batchedPositions = new Float32Array(result.positions);
polygons._vertexBatchIds = new Uint16Array(result.batchIds);
finishPrimitive2(polygons);
polygons._ready = true;
}).catch((error) => {
if (polygons.isDestroyed()) {
return;
}
polygons._error = error;
});
}
function finishPrimitive2(polygons) {
if (!defined_default(polygons._primitive)) {
polygons._primitive = new Vector3DTilePrimitive_default({
batchTable: polygons._batchTable,
positions: polygons._batchedPositions,
batchIds: polygons._batchIds,
vertexBatchIds: polygons._vertexBatchIds,
indices: polygons._indices,
indexOffsets: polygons._indexOffsets,
indexCounts: polygons._indexCounts,
batchedIndices: polygons._batchedIndices,
boundingVolume: polygons._boundingVolume,
boundingVolumes: polygons._boundingVolumes,
center: polygons._center
});
polygons._batchTable = void 0;
polygons._batchIds = void 0;
polygons._positions = void 0;
polygons._counts = void 0;
polygons._indices = void 0;
polygons._indexCounts = void 0;
polygons._indexOffsets = void 0;
polygons._batchTableColors = void 0;
polygons._packedBuffer = void 0;
polygons._batchedPositions = void 0;
polygons._transferrableBatchIds = void 0;
polygons._vertexBatchIds = void 0;
polygons._ellipsoid = void 0;
polygons._minimumHeight = void 0;
polygons._maximumHeight = void 0;
polygons._polygonMinimumHeights = void 0;
polygons._polygonMaximumHeights = void 0;
polygons._center = void 0;
polygons._rectangle = void 0;
polygons._boundingVolume = void 0;
polygons._boundingVolumes = void 0;
polygons._batchedIndices = void 0;
}
}
Vector3DTilePolygons.prototype.createFeatures = function(content, features) {
this._primitive.createFeatures(content, features);
};
Vector3DTilePolygons.prototype.applyDebugSettings = function(enabled, color) {
this._primitive.applyDebugSettings(enabled, color);
};
Vector3DTilePolygons.prototype.applyStyle = function(style, features) {
this._primitive.applyStyle(style, features);
};
Vector3DTilePolygons.prototype.updateCommands = function(batchId, color) {
this._primitive.updateCommands(batchId, color);
};
Vector3DTilePolygons.prototype.update = function(frameState) {
if (!this._ready) {
if (!defined_default(this._promise)) {
this._promise = createPrimitive2(this);
}
if (defined_default(this._error)) {
const error = this._error;
this._error = void 0;
throw error;
}
return;
}
this._primitive.debugWireframe = this.debugWireframe;
this._primitive.forceRebatch = this.forceRebatch;
this._primitive.classificationType = this.classificationType;
this._primitive.update(frameState);
};
Vector3DTilePolygons.prototype.isDestroyed = function() {
return false;
};
Vector3DTilePolygons.prototype.destroy = function() {
this._primitive = this._primitive && this._primitive.destroy();
return destroyObject_default(this);
};
var Vector3DTilePolygons_default = Vector3DTilePolygons;
// packages/engine/Source/Scene/Vector3DTilePolylines.js
var import_InlineWorkers760 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Vector3DTilePolylinesVS.js
var import_InlineWorkers759 = __toESM(require_InlineWorkers(), 1);
var Vector3DTilePolylinesVS_default = "in vec4 currentPosition;\nin vec4 previousPosition;\nin vec4 nextPosition;\nin vec2 expandAndWidth;\nin float a_batchId;\n\nuniform mat4 u_modifiedModelView;\n\nvoid main()\n{\n float expandDir = expandAndWidth.x;\n float width = abs(expandAndWidth.y) + 0.5;\n bool usePrev = expandAndWidth.y < 0.0;\n\n vec4 p = u_modifiedModelView * currentPosition;\n vec4 prev = u_modifiedModelView * previousPosition;\n vec4 next = u_modifiedModelView * nextPosition;\n\n float angle;\n vec4 positionWC = getPolylineWindowCoordinatesEC(p, prev, next, expandDir, width, usePrev, angle);\n gl_Position = czm_viewportOrthographic * positionWC;\n}\n";
// packages/engine/Source/Scene/Vector3DTilePolylines.js
function Vector3DTilePolylines(options) {
this._positions = options.positions;
this._widths = options.widths;
this._counts = options.counts;
this._batchIds = options.batchIds;
this._ellipsoid = options.ellipsoid ?? Ellipsoid_default.WGS84;
this._minimumHeight = options.minimumHeight;
this._maximumHeight = options.maximumHeight;
this._center = options.center;
this._rectangle = options.rectangle;
this._boundingVolume = options.boundingVolume;
this._batchTable = options.batchTable;
this._va = void 0;
this._sp = void 0;
this._rs = void 0;
this._uniformMap = void 0;
this._command = void 0;
this._transferrableBatchIds = void 0;
this._packedBuffer = void 0;
this._keepDecodedPositions = options.keepDecodedPositions;
this._decodedPositions = void 0;
this._decodedPositionOffsets = void 0;
this._currentPositions = void 0;
this._previousPositions = void 0;
this._nextPositions = void 0;
this._expandAndWidth = void 0;
this._vertexBatchIds = void 0;
this._indices = void 0;
this._constantColor = Color_default.clone(Color_default.WHITE);
this._highlightColor = this._constantColor;
this._trianglesLength = 0;
this._geometryByteLength = 0;
this._ready = false;
this._promise = void 0;
this._error = void 0;
}
Object.defineProperties(Vector3DTilePolylines.prototype, {
/**
* Gets the number of triangles.
*
* @memberof Vector3DTilePolylines.prototype
*
* @type {number}
* @readonly
* @private
*/
trianglesLength: {
get: function() {
return this._trianglesLength;
}
},
/**
* Gets the geometry memory in bytes.
*
* @memberof Vector3DTilePolylines.prototype
*
* @type {number}
* @readonly
* @private
*/
geometryByteLength: {
get: function() {
return this._geometryByteLength;
}
},
/**
* Returns true when the primitive is ready to render.
* @memberof Vector3DTilePolylines.prototype
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
return this._ready;
}
}
});
function packBuffer4(polylines) {
const rectangle = polylines._rectangle;
const minimumHeight = polylines._minimumHeight;
const maximumHeight = polylines._maximumHeight;
const ellipsoid = polylines._ellipsoid;
const center = polylines._center;
const packedLength = 2 + Rectangle_default.packedLength + Ellipsoid_default.packedLength + Cartesian3_default.packedLength;
const packedBuffer = new Float64Array(packedLength);
let offset = 0;
packedBuffer[offset++] = minimumHeight;
packedBuffer[offset++] = maximumHeight;
Rectangle_default.pack(rectangle, packedBuffer, offset);
offset += Rectangle_default.packedLength;
Ellipsoid_default.pack(ellipsoid, packedBuffer, offset);
offset += Ellipsoid_default.packedLength;
Cartesian3_default.pack(center, packedBuffer, offset);
return packedBuffer;
}
var createVerticesTaskProcessor4 = new TaskProcessor_default(
"createVectorTilePolylines",
5
);
var attributeLocations3 = {
previousPosition: 0,
currentPosition: 1,
nextPosition: 2,
expandAndWidth: 3,
a_batchId: 4
};
function createVertexArray3(polylines, context) {
if (defined_default(polylines._va)) {
return;
}
let positions = polylines._positions;
let widths = polylines._widths;
let counts = polylines._counts;
let batchIds = polylines._transferrableBatchIds;
let packedBuffer = polylines._packedBuffer;
if (!defined_default(packedBuffer)) {
positions = polylines._positions = positions.slice();
widths = polylines._widths = widths.slice();
counts = polylines._counts = counts.slice();
batchIds = polylines._transferrableBatchIds = polylines._batchIds.slice();
packedBuffer = polylines._packedBuffer = packBuffer4(polylines);
}
const transferrableObjects = [
positions.buffer,
widths.buffer,
counts.buffer,
batchIds.buffer,
packedBuffer.buffer
];
const parameters = {
positions: positions.buffer,
widths: widths.buffer,
counts: counts.buffer,
batchIds: batchIds.buffer,
packedBuffer: packedBuffer.buffer,
keepDecodedPositions: polylines._keepDecodedPositions
};
const verticesPromise = createVerticesTaskProcessor4.scheduleTask(
parameters,
transferrableObjects
);
if (!defined_default(verticesPromise)) {
return;
}
return verticesPromise.then(function(result) {
if (polylines.isDestroyed()) {
return;
}
if (polylines._keepDecodedPositions) {
polylines._decodedPositions = new Float64Array(result.decodedPositions);
polylines._decodedPositionOffsets = new Uint32Array(
result.decodedPositionOffsets
);
}
polylines._currentPositions = new Float32Array(result.currentPositions);
polylines._previousPositions = new Float32Array(result.previousPositions);
polylines._nextPositions = new Float32Array(result.nextPositions);
polylines._expandAndWidth = new Float32Array(result.expandAndWidth);
polylines._vertexBatchIds = new Uint16Array(result.batchIds);
const indexDatatype = result.indexDatatype;
polylines._indices = indexDatatype === IndexDatatype_default.UNSIGNED_SHORT ? new Uint16Array(result.indices) : new Uint32Array(result.indices);
finishVertexArray(polylines, context);
polylines._ready = true;
}).catch((error) => {
if (polylines.isDestroyed()) {
return;
}
polylines._error = error;
});
}
function finishVertexArray(polylines, context) {
if (!defined_default(polylines._va)) {
const curPositions = polylines._currentPositions;
const prevPositions = polylines._previousPositions;
const nextPositions = polylines._nextPositions;
const expandAndWidth = polylines._expandAndWidth;
const vertexBatchIds = polylines._vertexBatchIds;
const indices = polylines._indices;
let byteLength = prevPositions.byteLength + curPositions.byteLength + nextPositions.byteLength;
byteLength += expandAndWidth.byteLength + vertexBatchIds.byteLength + indices.byteLength;
polylines._trianglesLength = indices.length / 3;
polylines._geometryByteLength = byteLength;
const prevPositionBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: prevPositions,
usage: BufferUsage_default.STATIC_DRAW
});
const curPositionBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: curPositions,
usage: BufferUsage_default.STATIC_DRAW
});
const nextPositionBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: nextPositions,
usage: BufferUsage_default.STATIC_DRAW
});
const expandAndWidthBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: expandAndWidth,
usage: BufferUsage_default.STATIC_DRAW
});
const idBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: vertexBatchIds,
usage: BufferUsage_default.STATIC_DRAW
});
const indexBuffer = Buffer_default.createIndexBuffer({
context,
typedArray: indices,
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype: indices.BYTES_PER_ELEMENT === 2 ? IndexDatatype_default.UNSIGNED_SHORT : IndexDatatype_default.UNSIGNED_INT
});
const vertexAttributes = [
{
index: attributeLocations3.previousPosition,
vertexBuffer: prevPositionBuffer,
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3
},
{
index: attributeLocations3.currentPosition,
vertexBuffer: curPositionBuffer,
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3
},
{
index: attributeLocations3.nextPosition,
vertexBuffer: nextPositionBuffer,
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3
},
{
index: attributeLocations3.expandAndWidth,
vertexBuffer: expandAndWidthBuffer,
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2
},
{
index: attributeLocations3.a_batchId,
vertexBuffer: idBuffer,
componentDatatype: ComponentDatatype_default.UNSIGNED_SHORT,
componentsPerAttribute: 1
}
];
polylines._va = new VertexArray_default({
context,
attributes: vertexAttributes,
indexBuffer
});
polylines._positions = void 0;
polylines._widths = void 0;
polylines._counts = void 0;
polylines._ellipsoid = void 0;
polylines._minimumHeight = void 0;
polylines._maximumHeight = void 0;
polylines._rectangle = void 0;
polylines._transferrableBatchIds = void 0;
polylines._packedBuffer = void 0;
polylines._currentPositions = void 0;
polylines._previousPositions = void 0;
polylines._nextPositions = void 0;
polylines._expandAndWidth = void 0;
polylines._vertexBatchIds = void 0;
polylines._indices = void 0;
}
}
var modifiedModelViewScratch3 = new Matrix4_default();
var rtcScratch3 = new Cartesian3_default();
function createUniformMap2(primitive, context) {
if (defined_default(primitive._uniformMap)) {
return;
}
primitive._uniformMap = {
u_modifiedModelView: function() {
const viewMatrix = context.uniformState.view;
Matrix4_default.clone(viewMatrix, modifiedModelViewScratch3);
Matrix4_default.multiplyByPoint(
modifiedModelViewScratch3,
primitive._center,
rtcScratch3
);
Matrix4_default.setTranslation(
modifiedModelViewScratch3,
rtcScratch3,
modifiedModelViewScratch3
);
return modifiedModelViewScratch3;
},
u_highlightColor: function() {
return primitive._highlightColor;
}
};
}
function createRenderStates4(primitive) {
if (defined_default(primitive._rs)) {
return;
}
const polygonOffset = {
enabled: true,
factor: -5,
units: -5
};
primitive._rs = RenderState_default.fromCache({
blending: BlendingState_default.ALPHA_BLEND,
depthMask: false,
depthTest: {
enabled: true
},
polygonOffset
});
}
var PolylineFS = "uniform vec4 u_highlightColor; \nvoid main()\n{\n out_FragColor = u_highlightColor;\n}\n";
function createShaders2(primitive, context) {
if (defined_default(primitive._sp)) {
return;
}
const batchTable = primitive._batchTable;
const vsSource = batchTable.getVertexShaderCallback(
false,
"a_batchId",
void 0
)(Vector3DTilePolylinesVS_default);
const fsSource = batchTable.getFragmentShaderCallback(
false,
void 0,
false
)(PolylineFS);
const vs = new ShaderSource_default({
defines: [
"VECTOR_TILE",
!FeatureDetection_default.isInternetExplorer() ? "CLIP_POLYLINE" : ""
],
sources: [PolylineCommon_default, vsSource]
});
const fs = new ShaderSource_default({
defines: ["VECTOR_TILE"],
sources: [fsSource]
});
primitive._sp = ShaderProgram_default.fromCache({
context,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations3
});
}
function queueCommands2(primitive, frameState) {
if (!defined_default(primitive._command)) {
const uniformMap2 = primitive._batchTable.getUniformMapCallback()(
primitive._uniformMap
);
primitive._command = new DrawCommand_default({
owner: primitive,
vertexArray: primitive._va,
renderState: primitive._rs,
shaderProgram: primitive._sp,
uniformMap: uniformMap2,
boundingVolume: primitive._boundingVolume,
pass: Pass_default.TRANSLUCENT,
pickId: primitive._batchTable.getPickId()
});
}
frameState.commandList.push(primitive._command);
}
Vector3DTilePolylines.getPolylinePositions = function(polylines, batchId) {
const batchIds = polylines._batchIds;
const positions = polylines._decodedPositions;
const offsets = polylines._decodedPositionOffsets;
if (!defined_default(batchIds) || !defined_default(positions)) {
return void 0;
}
let i;
let j;
const polylinesLength = batchIds.length;
let positionsLength = 0;
let resultCounter = 0;
for (i = 0; i < polylinesLength; ++i) {
if (batchIds[i] === batchId) {
positionsLength += offsets[i + 1] - offsets[i];
}
}
if (positionsLength === 0) {
return void 0;
}
const results = new Float64Array(positionsLength * 3);
for (i = 0; i < polylinesLength; ++i) {
if (batchIds[i] === batchId) {
const offset = offsets[i];
const count = offsets[i + 1] - offset;
for (j = 0; j < count; ++j) {
const decodedOffset = (offset + j) * 3;
results[resultCounter++] = positions[decodedOffset];
results[resultCounter++] = positions[decodedOffset + 1];
results[resultCounter++] = positions[decodedOffset + 2];
}
}
}
return results;
};
Vector3DTilePolylines.prototype.getPositions = function(batchId) {
return Vector3DTilePolylines.getPolylinePositions(this, batchId);
};
Vector3DTilePolylines.prototype.createFeatures = function(content, features) {
const batchIds = this._batchIds;
const length2 = batchIds.length;
for (let i = 0; i < length2; ++i) {
const batchId = batchIds[i];
features[batchId] = new Cesium3DTileFeature_default(content, batchId);
}
};
Vector3DTilePolylines.prototype.applyDebugSettings = function(enabled, color) {
this._highlightColor = enabled ? color : this._constantColor;
};
function clearStyle3(polygons, features) {
const batchIds = polygons._batchIds;
const length2 = batchIds.length;
for (let i = 0; i < length2; ++i) {
const batchId = batchIds[i];
const feature2 = features[batchId];
feature2.show = true;
feature2.color = Color_default.WHITE;
}
}
var scratchColor11 = new Color_default();
var DEFAULT_COLOR_VALUE3 = Color_default.WHITE;
var DEFAULT_SHOW_VALUE3 = true;
Vector3DTilePolylines.prototype.applyStyle = function(style, features) {
if (!defined_default(style)) {
clearStyle3(this, features);
return;
}
const batchIds = this._batchIds;
const length2 = batchIds.length;
for (let i = 0; i < length2; ++i) {
const batchId = batchIds[i];
const feature2 = features[batchId];
feature2.color = defined_default(style.color) ? style.color.evaluateColor(feature2, scratchColor11) : DEFAULT_COLOR_VALUE3;
feature2.show = defined_default(style.show) ? style.show.evaluate(feature2) : DEFAULT_SHOW_VALUE3;
}
};
Vector3DTilePolylines.prototype.update = function(frameState) {
const context = frameState.context;
if (!this._ready) {
if (!defined_default(this._promise)) {
this._promise = createVertexArray3(this, context);
}
if (defined_default(this._error)) {
const error = this._error;
this._error = void 0;
throw error;
}
return;
}
createUniformMap2(this, context);
createShaders2(this, context);
createRenderStates4(this);
const passes = frameState.passes;
if (passes.render || passes.pick) {
queueCommands2(this, frameState);
}
};
Vector3DTilePolylines.prototype.isDestroyed = function() {
return false;
};
Vector3DTilePolylines.prototype.destroy = function() {
this._va = this._va && this._va.destroy();
this._sp = this._sp && this._sp.destroy();
return destroyObject_default(this);
};
var Vector3DTilePolylines_default = Vector3DTilePolylines;
// packages/engine/Source/Scene/Vector3DTileClampedPolylines.js
var import_InlineWorkers763 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Vector3DTileClampedPolylinesVS.js
var import_InlineWorkers761 = __toESM(require_InlineWorkers(), 1);
var Vector3DTileClampedPolylinesVS_default = 'in vec3 startEllipsoidNormal;\nin vec3 endEllipsoidNormal;\nin vec4 startPositionAndHeight;\nin vec4 endPositionAndHeight;\nin vec4 startFaceNormalAndVertexCorner;\nin vec4 endFaceNormalAndHalfWidth;\nin float a_batchId;\n\nuniform mat4 u_modifiedModelView;\nuniform vec2 u_minimumMaximumVectorHeights;\n\nout vec4 v_startPlaneEC;\nout vec4 v_endPlaneEC;\nout vec4 v_rightPlaneEC;\nout float v_halfWidth;\nout vec3 v_volumeUpEC;\n\nvoid main()\n{\n // vertex corner IDs\n // 3-----------7\n // /| left /|\n // / | 1 / |\n // 2-----------6 5 end\n // | / | /\n // start |/ right |/\n // 0-----------4\n //\n float isEnd = floor(startFaceNormalAndVertexCorner.w * 0.251); // 0 for front, 1 for end\n float isTop = floor(startFaceNormalAndVertexCorner.w * mix(0.51, 0.19, isEnd)); // 0 for bottom, 1 for top\n\n vec3 forward = endPositionAndHeight.xyz - startPositionAndHeight.xyz;\n vec3 right = normalize(cross(forward, startEllipsoidNormal));\n\n vec4 position = vec4(startPositionAndHeight.xyz, 1.0);\n position.xyz += forward * isEnd;\n\n v_volumeUpEC = czm_normal * normalize(cross(right, forward));\n\n // Push for volume height\n float offset;\n vec3 ellipsoidNormal = mix(startEllipsoidNormal, endEllipsoidNormal, isEnd);\n\n // offset height to create volume\n offset = mix(startPositionAndHeight.w, endPositionAndHeight.w, isEnd);\n offset = mix(u_minimumMaximumVectorHeights.y, u_minimumMaximumVectorHeights.x, isTop) - offset;\n position.xyz += offset * ellipsoidNormal;\n\n // move from RTC to EC\n position = u_modifiedModelView * position;\n right = czm_normal * right;\n\n // Push for width in a direction that is in the start or end plane and in a plane with right\n // N = normalEC ("right-facing" direction for push)\n // R = right\n // p = angle between N and R\n // w = distance to push along R if R == N\n // d = distance to push along N\n //\n // N R\n // { p| } * cos(p) = dot(N, R) = w / d\n // d | |w * d = w / dot(N, R)\n // { | }\n // o---------- polyline segment ---->\n //\n vec3 scratchNormal = mix(-startFaceNormalAndVertexCorner.xyz, endFaceNormalAndHalfWidth.xyz, isEnd);\n scratchNormal = cross(scratchNormal, mix(startEllipsoidNormal, endEllipsoidNormal, isEnd));\n vec3 miterPushNormal = czm_normal * normalize(scratchNormal);\n\n offset = 2.0 * endFaceNormalAndHalfWidth.w * max(0.0, czm_metersPerPixel(position)); // offset = widthEC\n offset = offset / dot(miterPushNormal, right);\n position.xyz += miterPushNormal * (offset * sign(0.5 - mod(startFaceNormalAndVertexCorner.w, 2.0)));\n\n gl_Position = czm_depthClamp(czm_projection * position);\n\n position = u_modifiedModelView * vec4(startPositionAndHeight.xyz, 1.0);\n vec3 startNormalEC = czm_normal * startFaceNormalAndVertexCorner.xyz;\n v_startPlaneEC = vec4(startNormalEC, -dot(startNormalEC, position.xyz));\n v_rightPlaneEC = vec4(right, -dot(right, position.xyz));\n\n position = u_modifiedModelView * vec4(endPositionAndHeight.xyz, 1.0);\n vec3 endNormalEC = czm_normal * endFaceNormalAndHalfWidth.xyz;\n v_endPlaneEC = vec4(endNormalEC, -dot(endNormalEC, position.xyz));\n v_halfWidth = endFaceNormalAndHalfWidth.w;\n}\n';
// packages/engine/Source/Shaders/Vector3DTileClampedPolylinesFS.js
var import_InlineWorkers762 = __toESM(require_InlineWorkers(), 1);
var Vector3DTileClampedPolylinesFS_default = "in vec4 v_startPlaneEC;\nin vec4 v_endPlaneEC;\nin vec4 v_rightPlaneEC;\nin float v_halfWidth;\nin vec3 v_volumeUpEC;\n\nuniform vec4 u_highlightColor;\nvoid main()\n{\n float logDepthOrDepth = czm_branchFreeTernary(czm_sceneMode == czm_sceneMode2D, gl_FragCoord.z, czm_unpackDepth(texture(czm_globeDepthTexture, gl_FragCoord.xy / czm_viewport.zw)));\n\n // Discard for sky\n if (logDepthOrDepth == 0.0) {\n#ifdef DEBUG_SHOW_VOLUME\n out_FragColor = vec4(0.0, 0.0, 1.0, 0.5);\n return;\n#else // DEBUG_SHOW_VOLUME\n discard;\n#endif // DEBUG_SHOW_VOLUME\n }\n\n vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth);\n eyeCoordinate /= eyeCoordinate.w;\n\n float halfMaxWidth = v_halfWidth * czm_metersPerPixel(eyeCoordinate);\n\n // Expand halfMaxWidth if direction to camera is almost perpendicular with the volume's up direction\n halfMaxWidth += halfMaxWidth * (1.0 - dot(-normalize(eyeCoordinate.xyz), v_volumeUpEC));\n\n // Check distance of the eye coordinate against the right-facing plane\n float widthwiseDistance = czm_planeDistance(v_rightPlaneEC, eyeCoordinate.xyz);\n\n // Check eye coordinate against the mitering planes\n float distanceFromStart = czm_planeDistance(v_startPlaneEC, eyeCoordinate.xyz);\n float distanceFromEnd = czm_planeDistance(v_endPlaneEC, eyeCoordinate.xyz);\n\n if (abs(widthwiseDistance) > halfMaxWidth || distanceFromStart < 0.0 || distanceFromEnd < 0.0) {\n#ifdef DEBUG_SHOW_VOLUME\n out_FragColor = vec4(logDepthOrDepth, 0.0, 0.0, 0.5);\n return;\n#else // DEBUG_SHOW_VOLUME\n discard;\n#endif // DEBUG_SHOW_VOLUME\n }\n out_FragColor = u_highlightColor;\n\n czm_writeDepthClamp();\n}\n";
// packages/engine/Source/Scene/Vector3DTileClampedPolylines.js
function Vector3DTileClampedPolylines(options) {
this._positions = options.positions;
this._widths = options.widths;
this._counts = options.counts;
this._batchIds = options.batchIds;
this._ellipsoid = options.ellipsoid ?? Ellipsoid_default.WGS84;
this._minimumHeight = options.minimumHeight;
this._maximumHeight = options.maximumHeight;
this._center = options.center;
this._rectangle = options.rectangle;
this._batchTable = options.batchTable;
this._va = void 0;
this._sp = void 0;
this._rs = void 0;
this._uniformMap = void 0;
this._command = void 0;
this._transferrableBatchIds = void 0;
this._packedBuffer = void 0;
this._minimumMaximumVectorHeights = new Cartesian2_default(
ApproximateTerrainHeights_default._defaultMinTerrainHeight,
ApproximateTerrainHeights_default._defaultMaxTerrainHeight
);
this._boundingVolume = OrientedBoundingBox_default.fromRectangle(
options.rectangle,
ApproximateTerrainHeights_default._defaultMinTerrainHeight,
ApproximateTerrainHeights_default._defaultMaxTerrainHeight,
this._ellipsoid
);
this._classificationType = options.classificationType;
this._keepDecodedPositions = options.keepDecodedPositions;
this._decodedPositions = void 0;
this._decodedPositionOffsets = void 0;
this._startEllipsoidNormals = void 0;
this._endEllipsoidNormals = void 0;
this._startPositionAndHeights = void 0;
this._startFaceNormalAndVertexCornerIds = void 0;
this._endPositionAndHeights = void 0;
this._endFaceNormalAndHalfWidths = void 0;
this._vertexBatchIds = void 0;
this._indices = void 0;
this._constantColor = Color_default.clone(Color_default.WHITE);
this._highlightColor = this._constantColor;
this._trianglesLength = 0;
this._geometryByteLength = 0;
this._ready = false;
this._promise = void 0;
this._error = void 0;
}
Object.defineProperties(Vector3DTileClampedPolylines.prototype, {
/**
* Gets the number of triangles.
*
* @memberof Vector3DTileClampedPolylines.prototype
*
* @type {number}
* @readonly
*/
trianglesLength: {
get: function() {
return this._trianglesLength;
}
},
/**
* Gets the geometry memory in bytes.
*
* @memberof Vector3DTileClampedPolylines.prototype
*
* @type {number}
* @readonly
*/
geometryByteLength: {
get: function() {
return this._geometryByteLength;
}
},
/**
* Returns true when the primitive is ready to render.
* @memberof Vector3DTileClampedPolylines.prototype
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
}
});
function updateMinimumMaximumHeights(polylines, rectangle, ellipsoid) {
const result = ApproximateTerrainHeights_default.getMinimumMaximumHeights(
rectangle,
ellipsoid
);
const min3 = result.minimumTerrainHeight;
const max3 = result.maximumTerrainHeight;
const minimumMaximumVectorHeights = polylines._minimumMaximumVectorHeights;
minimumMaximumVectorHeights.x = min3;
minimumMaximumVectorHeights.y = max3;
const obb = polylines._boundingVolume;
const rect = polylines._rectangle;
OrientedBoundingBox_default.fromRectangle(rect, min3, max3, ellipsoid, obb);
}
function packBuffer5(polylines) {
const rectangle = polylines._rectangle;
const minimumHeight = polylines._minimumHeight;
const maximumHeight = polylines._maximumHeight;
const ellipsoid = polylines._ellipsoid;
const center = polylines._center;
const packedLength = 2 + Rectangle_default.packedLength + Ellipsoid_default.packedLength + Cartesian3_default.packedLength;
const packedBuffer = new Float64Array(packedLength);
let offset = 0;
packedBuffer[offset++] = minimumHeight;
packedBuffer[offset++] = maximumHeight;
Rectangle_default.pack(rectangle, packedBuffer, offset);
offset += Rectangle_default.packedLength;
Ellipsoid_default.pack(ellipsoid, packedBuffer, offset);
offset += Ellipsoid_default.packedLength;
Cartesian3_default.pack(center, packedBuffer, offset);
return packedBuffer;
}
var createVerticesTaskProcessor5 = new TaskProcessor_default(
"createVectorTileClampedPolylines"
);
var attributeLocations4 = {
startEllipsoidNormal: 0,
endEllipsoidNormal: 1,
startPositionAndHeight: 2,
endPositionAndHeight: 3,
startFaceNormalAndVertexCorner: 4,
endFaceNormalAndHalfWidth: 5,
a_batchId: 6
};
function createVertexArray4(polylines, context) {
if (defined_default(polylines._va)) {
return;
}
let positions = polylines._positions;
let widths = polylines._widths;
let counts = polylines._counts;
let batchIds = polylines._transferrableBatchIds;
let packedBuffer = polylines._packedBuffer;
if (!defined_default(packedBuffer)) {
positions = polylines._positions = positions.slice();
widths = polylines._widths = widths.slice();
counts = polylines._counts = counts.slice();
batchIds = polylines._transferrableBatchIds = polylines._batchIds.slice();
packedBuffer = polylines._packedBuffer = packBuffer5(polylines);
}
const transferrableObjects = [
positions.buffer,
widths.buffer,
counts.buffer,
batchIds.buffer,
packedBuffer.buffer
];
const parameters = {
positions: positions.buffer,
widths: widths.buffer,
counts: counts.buffer,
batchIds: batchIds.buffer,
packedBuffer: packedBuffer.buffer,
keepDecodedPositions: polylines._keepDecodedPositions
};
const verticesPromise = createVerticesTaskProcessor5.scheduleTask(
parameters,
transferrableObjects
);
if (!defined_default(verticesPromise)) {
return;
}
return verticesPromise.then(function(result) {
if (polylines.isDestroyed()) {
return;
}
if (polylines._keepDecodedPositions) {
polylines._decodedPositions = new Float64Array(result.decodedPositions);
polylines._decodedPositionOffsets = new Uint32Array(
result.decodedPositionOffsets
);
}
polylines._startEllipsoidNormals = new Float32Array(
result.startEllipsoidNormals
);
polylines._endEllipsoidNormals = new Float32Array(
result.endEllipsoidNormals
);
polylines._startPositionAndHeights = new Float32Array(
result.startPositionAndHeights
);
polylines._startFaceNormalAndVertexCornerIds = new Float32Array(
result.startFaceNormalAndVertexCornerIds
);
polylines._endPositionAndHeights = new Float32Array(
result.endPositionAndHeights
);
polylines._endFaceNormalAndHalfWidths = new Float32Array(
result.endFaceNormalAndHalfWidths
);
polylines._vertexBatchIds = new Uint16Array(result.vertexBatchIds);
const indexDatatype = result.indexDatatype;
polylines._indices = indexDatatype === IndexDatatype_default.UNSIGNED_SHORT ? new Uint16Array(result.indices) : new Uint32Array(result.indices);
finishVertexArray2(polylines, context);
polylines._ready = true;
}).catch((error) => {
if (polylines.isDestroyed()) {
return;
}
polylines._error = error;
});
}
function finishVertexArray2(polylines, context) {
if (!defined_default(polylines._va)) {
const startEllipsoidNormals = polylines._startEllipsoidNormals;
const endEllipsoidNormals = polylines._endEllipsoidNormals;
const startPositionAndHeights = polylines._startPositionAndHeights;
const endPositionAndHeights = polylines._endPositionAndHeights;
const startFaceNormalAndVertexCornerIds = polylines._startFaceNormalAndVertexCornerIds;
const endFaceNormalAndHalfWidths = polylines._endFaceNormalAndHalfWidths;
const batchIdAttribute = polylines._vertexBatchIds;
const indices = polylines._indices;
let byteLength = startEllipsoidNormals.byteLength + endEllipsoidNormals.byteLength;
byteLength += startPositionAndHeights.byteLength + endPositionAndHeights.byteLength;
byteLength += startFaceNormalAndVertexCornerIds.byteLength + endFaceNormalAndHalfWidths.byteLength;
byteLength += batchIdAttribute.byteLength + indices.byteLength;
polylines._trianglesLength = indices.length / 3;
polylines._geometryByteLength = byteLength;
const startEllipsoidNormalsBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: startEllipsoidNormals,
usage: BufferUsage_default.STATIC_DRAW
});
const endEllipsoidNormalsBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: endEllipsoidNormals,
usage: BufferUsage_default.STATIC_DRAW
});
const startPositionAndHeightsBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: startPositionAndHeights,
usage: BufferUsage_default.STATIC_DRAW
});
const endPositionAndHeightsBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: endPositionAndHeights,
usage: BufferUsage_default.STATIC_DRAW
});
const startFaceNormalAndVertexCornerIdsBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: startFaceNormalAndVertexCornerIds,
usage: BufferUsage_default.STATIC_DRAW
});
const endFaceNormalAndHalfWidthsBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: endFaceNormalAndHalfWidths,
usage: BufferUsage_default.STATIC_DRAW
});
const batchIdAttributeBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: batchIdAttribute,
usage: BufferUsage_default.STATIC_DRAW
});
const indexBuffer = Buffer_default.createIndexBuffer({
context,
typedArray: indices,
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype: indices.BYTES_PER_ELEMENT === 2 ? IndexDatatype_default.UNSIGNED_SHORT : IndexDatatype_default.UNSIGNED_INT
});
const vertexAttributes = [
{
index: attributeLocations4.startEllipsoidNormal,
vertexBuffer: startEllipsoidNormalsBuffer,
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3
},
{
index: attributeLocations4.endEllipsoidNormal,
vertexBuffer: endEllipsoidNormalsBuffer,
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3
},
{
index: attributeLocations4.startPositionAndHeight,
vertexBuffer: startPositionAndHeightsBuffer,
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 4
},
{
index: attributeLocations4.endPositionAndHeight,
vertexBuffer: endPositionAndHeightsBuffer,
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 4
},
{
index: attributeLocations4.startFaceNormalAndVertexCorner,
vertexBuffer: startFaceNormalAndVertexCornerIdsBuffer,
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 4
},
{
index: attributeLocations4.endFaceNormalAndHalfWidth,
vertexBuffer: endFaceNormalAndHalfWidthsBuffer,
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 4
},
{
index: attributeLocations4.a_batchId,
vertexBuffer: batchIdAttributeBuffer,
componentDatatype: ComponentDatatype_default.UNSIGNED_SHORT,
componentsPerAttribute: 1
}
];
polylines._va = new VertexArray_default({
context,
attributes: vertexAttributes,
indexBuffer
});
polylines._positions = void 0;
polylines._widths = void 0;
polylines._counts = void 0;
polylines._ellipsoid = void 0;
polylines._minimumHeight = void 0;
polylines._maximumHeight = void 0;
polylines._rectangle = void 0;
polylines._transferrableBatchIds = void 0;
polylines._packedBuffer = void 0;
polylines._startEllipsoidNormals = void 0;
polylines._endEllipsoidNormals = void 0;
polylines._startPositionAndHeights = void 0;
polylines._startFaceNormalAndVertexCornerIds = void 0;
polylines._endPositionAndHeights = void 0;
polylines._endFaceNormalAndHalfWidths = void 0;
polylines._vertexBatchIds = void 0;
polylines._indices = void 0;
}
}
var modifiedModelViewScratch4 = new Matrix4_default();
var rtcScratch4 = new Cartesian3_default();
function createUniformMap3(primitive, context) {
if (defined_default(primitive._uniformMap)) {
return;
}
primitive._uniformMap = {
u_modifiedModelView: function() {
const viewMatrix = context.uniformState.view;
Matrix4_default.clone(viewMatrix, modifiedModelViewScratch4);
Matrix4_default.multiplyByPoint(
modifiedModelViewScratch4,
primitive._center,
rtcScratch4
);
Matrix4_default.setTranslation(
modifiedModelViewScratch4,
rtcScratch4,
modifiedModelViewScratch4
);
return modifiedModelViewScratch4;
},
u_highlightColor: function() {
return primitive._highlightColor;
},
u_minimumMaximumVectorHeights: function() {
return primitive._minimumMaximumVectorHeights;
}
};
}
function getRenderState2(mask3DTiles) {
return RenderState_default.fromCache({
cull: {
enabled: true,
face: CullFace_default.FRONT
},
blending: BlendingState_default.PRE_MULTIPLIED_ALPHA_BLEND,
depthMask: false,
stencilTest: {
enabled: mask3DTiles,
frontFunction: StencilFunction_default.EQUAL,
frontOperation: {
fail: StencilOperation_default.KEEP,
zFail: StencilOperation_default.KEEP,
zPass: StencilOperation_default.KEEP
},
backFunction: StencilFunction_default.EQUAL,
backOperation: {
fail: StencilOperation_default.KEEP,
zFail: StencilOperation_default.KEEP,
zPass: StencilOperation_default.KEEP
},
reference: StencilConstants_default.CESIUM_3D_TILE_MASK,
mask: StencilConstants_default.CESIUM_3D_TILE_MASK
}
});
}
function createRenderStates5(primitive) {
if (defined_default(primitive._rs)) {
return;
}
primitive._rs = getRenderState2(false);
primitive._rs3DTiles = getRenderState2(true);
}
function createShaders3(primitive, context) {
if (defined_default(primitive._sp)) {
return;
}
const batchTable = primitive._batchTable;
const vsSource = batchTable.getVertexShaderCallback(
false,
"a_batchId",
void 0
)(Vector3DTileClampedPolylinesVS_default);
const fsSource = batchTable.getFragmentShaderCallback(
false,
void 0,
true
)(Vector3DTileClampedPolylinesFS_default);
const vs = new ShaderSource_default({
defines: [
"VECTOR_TILE",
!FeatureDetection_default.isInternetExplorer() ? "CLIP_POLYLINE" : ""
],
sources: [PolylineCommon_default, vsSource]
});
const fs = new ShaderSource_default({
defines: ["VECTOR_TILE"],
sources: [fsSource]
});
primitive._sp = ShaderProgram_default.fromCache({
context,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations4
});
}
function queueCommands3(primitive, frameState) {
let command = primitive._command;
if (!defined_default(primitive._command)) {
const uniformMap2 = primitive._batchTable.getUniformMapCallback()(
primitive._uniformMap
);
command = primitive._command = new DrawCommand_default({
owner: primitive,
vertexArray: primitive._va,
renderState: primitive._rs,
shaderProgram: primitive._sp,
uniformMap: uniformMap2,
boundingVolume: primitive._boundingVolume,
pass: Pass_default.TERRAIN_CLASSIFICATION,
pickId: primitive._batchTable.getPickId()
});
const derivedTilesetCommand = DrawCommand_default.shallowClone(
command,
command.derivedCommands.tileset
);
derivedTilesetCommand.renderState = primitive._rs3DTiles;
derivedTilesetCommand.pass = Pass_default.CESIUM_3D_TILE_CLASSIFICATION;
command.derivedCommands.tileset = derivedTilesetCommand;
}
const classificationType = primitive._classificationType;
if (classificationType === ClassificationType_default.TERRAIN || classificationType === ClassificationType_default.BOTH) {
frameState.commandList.push(command);
}
if (classificationType === ClassificationType_default.CESIUM_3D_TILE || classificationType === ClassificationType_default.BOTH) {
frameState.commandList.push(command.derivedCommands.tileset);
}
}
Vector3DTileClampedPolylines.prototype.getPositions = function(batchId) {
return Vector3DTilePolylines_default.getPolylinePositions(this, batchId);
};
Vector3DTileClampedPolylines.prototype.createFeatures = function(content, features) {
const batchIds = this._batchIds;
const length2 = batchIds.length;
for (let i = 0; i < length2; ++i) {
const batchId = batchIds[i];
features[batchId] = new Cesium3DTileFeature_default(content, batchId);
}
};
Vector3DTileClampedPolylines.prototype.applyDebugSettings = function(enabled, color) {
this._highlightColor = enabled ? color : this._constantColor;
};
function clearStyle4(polygons, features) {
const batchIds = polygons._batchIds;
const length2 = batchIds.length;
for (let i = 0; i < length2; ++i) {
const batchId = batchIds[i];
const feature2 = features[batchId];
feature2.show = true;
feature2.color = Color_default.WHITE;
}
}
var scratchColor12 = new Color_default();
var DEFAULT_COLOR_VALUE4 = Color_default.WHITE;
var DEFAULT_SHOW_VALUE4 = true;
Vector3DTileClampedPolylines.prototype.applyStyle = function(style, features) {
if (!defined_default(style)) {
clearStyle4(this, features);
return;
}
const batchIds = this._batchIds;
const length2 = batchIds.length;
for (let i = 0; i < length2; ++i) {
const batchId = batchIds[i];
const feature2 = features[batchId];
feature2.color = defined_default(style.color) ? style.color.evaluateColor(feature2, scratchColor12) : DEFAULT_COLOR_VALUE4;
feature2.show = defined_default(style.show) ? style.show.evaluate(feature2) : DEFAULT_SHOW_VALUE4;
}
};
function initialize15(polylines) {
return ApproximateTerrainHeights_default.initialize().then(function() {
updateMinimumMaximumHeights(
polylines,
polylines._rectangle,
polylines._ellipsoid
);
}).catch((error) => {
if (polylines.isDestroyed()) {
return;
}
polylines._error = error;
});
}
Vector3DTileClampedPolylines.prototype.update = function(frameState) {
const context = frameState.context;
if (!this._ready) {
if (!defined_default(this._promise)) {
this._promise = initialize15(this).then(createVertexArray4(this, context));
}
if (defined_default(this._error)) {
const error = this._error;
this._error = void 0;
throw error;
}
return;
}
createUniformMap3(this, context);
createShaders3(this, context);
createRenderStates5(this);
const passes = frameState.passes;
if (passes.render || passes.pick) {
queueCommands3(this, frameState);
}
};
Vector3DTileClampedPolylines.prototype.isDestroyed = function() {
return false;
};
Vector3DTileClampedPolylines.prototype.destroy = function() {
this._va = this._va && this._va.destroy();
this._sp = this._sp && this._sp.destroy();
return destroyObject_default(this);
};
var Vector3DTileClampedPolylines_default = Vector3DTileClampedPolylines;
// packages/engine/Source/Core/decodeVectorPolylinePositions.js
var import_InlineWorkers764 = __toESM(require_InlineWorkers(), 1);
var maxShort = 32767;
var scratchBVCartographic2 = new Cartographic_default();
var scratchEncodedPosition = new Cartesian3_default();
function decodeVectorPolylinePositions(positions, rectangle, minimumHeight, maximumHeight, ellipsoid) {
const positionsLength = positions.length / 3;
const uBuffer = positions.subarray(0, positionsLength);
const vBuffer = positions.subarray(positionsLength, 2 * positionsLength);
const heightBuffer = positions.subarray(
2 * positionsLength,
3 * positionsLength
);
AttributeCompression_default.zigZagDeltaDecode(uBuffer, vBuffer, heightBuffer);
const decoded = new Float64Array(positions.length);
for (let i = 0; i < positionsLength; ++i) {
const u3 = uBuffer[i];
const v3 = vBuffer[i];
const h = heightBuffer[i];
const lon = Math_default.lerp(rectangle.west, rectangle.east, u3 / maxShort);
const lat = Math_default.lerp(rectangle.south, rectangle.north, v3 / maxShort);
const alt = Math_default.lerp(minimumHeight, maximumHeight, h / maxShort);
const cartographic2 = Cartographic_default.fromRadians(
lon,
lat,
alt,
scratchBVCartographic2
);
const decodedPosition = ellipsoid.cartographicToCartesian(
cartographic2,
scratchEncodedPosition
);
Cartesian3_default.pack(decodedPosition, decoded, i * 3);
}
return decoded;
}
var decodeVectorPolylinePositions_default = decodeVectorPolylinePositions;
// packages/engine/Source/Scene/Vector3DTileContent.js
function Vector3DTileContent(tileset, tile, resource, arrayBuffer, byteOffset) {
this._tileset = tileset;
this._tile = tile;
this._resource = resource;
this._polygons = void 0;
this._polylines = void 0;
this._points = void 0;
this._metadata = void 0;
this._batchTable = void 0;
this._features = void 0;
this.featurePropertiesDirty = false;
this._group = void 0;
this._ready = false;
initialize16(this, arrayBuffer, byteOffset);
}
Object.defineProperties(Vector3DTileContent.prototype, {
featuresLength: {
get: function() {
return defined_default(this._batchTable) ? this._batchTable.featuresLength : 0;
}
},
pointsLength: {
get: function() {
if (defined_default(this._points)) {
return this._points.pointsLength;
}
return 0;
}
},
trianglesLength: {
get: function() {
let trianglesLength = 0;
if (defined_default(this._polygons)) {
trianglesLength += this._polygons.trianglesLength;
}
if (defined_default(this._polylines)) {
trianglesLength += this._polylines.trianglesLength;
}
return trianglesLength;
}
},
geometryByteLength: {
get: function() {
let geometryByteLength = 0;
if (defined_default(this._polygons)) {
geometryByteLength += this._polygons.geometryByteLength;
}
if (defined_default(this._polylines)) {
geometryByteLength += this._polylines.geometryByteLength;
}
return geometryByteLength;
}
},
texturesByteLength: {
get: function() {
if (defined_default(this._points)) {
return this._points.texturesByteLength;
}
return 0;
}
},
batchTableByteLength: {
get: function() {
return defined_default(this._batchTable) ? this._batchTable.batchTableByteLength : 0;
}
},
innerContents: {
get: function() {
return void 0;
}
},
/**
* Returns true when the tile's content is ready to render; otherwise false
*
* @memberof Vector3DTileContent.prototype
*
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
return this._ready;
}
},
tileset: {
get: function() {
return this._tileset;
}
},
tile: {
get: function() {
return this._tile;
}
},
url: {
get: function() {
return this._resource.getUrlComponent(true);
}
},
metadata: {
get: function() {
return this._metadata;
},
set: function(value) {
this._metadata = value;
}
},
batchTable: {
get: function() {
return this._batchTable;
}
},
group: {
get: function() {
return this._group;
},
set: function(value) {
this._group = value;
}
}
});
function createColorChangedCallback2(content) {
return function(batchId, color) {
if (defined_default(content._polygons)) {
content._polygons.updateCommands(batchId, color);
}
};
}
function getBatchIds2(featureTableJson, featureTableBinary) {
let polygonBatchIds;
let polylineBatchIds;
let pointBatchIds;
let i;
const numberOfPolygons = featureTableJson.POLYGONS_LENGTH ?? 0;
const numberOfPolylines = featureTableJson.POLYLINES_LENGTH ?? 0;
const numberOfPoints = featureTableJson.POINTS_LENGTH ?? 0;
if (numberOfPolygons > 0 && defined_default(featureTableJson.POLYGON_BATCH_IDS)) {
const polygonBatchIdsByteOffset = featureTableBinary.byteOffset + featureTableJson.POLYGON_BATCH_IDS.byteOffset;
polygonBatchIds = new Uint16Array(
featureTableBinary.buffer,
polygonBatchIdsByteOffset,
numberOfPolygons
);
}
if (numberOfPolylines > 0 && defined_default(featureTableJson.POLYLINE_BATCH_IDS)) {
const polylineBatchIdsByteOffset = featureTableBinary.byteOffset + featureTableJson.POLYLINE_BATCH_IDS.byteOffset;
polylineBatchIds = new Uint16Array(
featureTableBinary.buffer,
polylineBatchIdsByteOffset,
numberOfPolylines
);
}
if (numberOfPoints > 0 && defined_default(featureTableJson.POINT_BATCH_IDS)) {
const pointBatchIdsByteOffset = featureTableBinary.byteOffset + featureTableJson.POINT_BATCH_IDS.byteOffset;
pointBatchIds = new Uint16Array(
featureTableBinary.buffer,
pointBatchIdsByteOffset,
numberOfPoints
);
}
const atLeastOneDefined = defined_default(polygonBatchIds) || defined_default(polylineBatchIds) || defined_default(pointBatchIds);
const atLeastOneUndefined = numberOfPolygons > 0 && !defined_default(polygonBatchIds) || numberOfPolylines > 0 && !defined_default(polylineBatchIds) || numberOfPoints > 0 && !defined_default(pointBatchIds);
if (atLeastOneDefined && atLeastOneUndefined) {
throw new RuntimeError_default(
"If one group of batch ids is defined, then all batch ids must be defined"
);
}
const allUndefinedBatchIds = !defined_default(polygonBatchIds) && !defined_default(polylineBatchIds) && !defined_default(pointBatchIds);
if (allUndefinedBatchIds) {
let id = 0;
if (!defined_default(polygonBatchIds) && numberOfPolygons > 0) {
polygonBatchIds = new Uint16Array(numberOfPolygons);
for (i = 0; i < numberOfPolygons; ++i) {
polygonBatchIds[i] = id++;
}
}
if (!defined_default(polylineBatchIds) && numberOfPolylines > 0) {
polylineBatchIds = new Uint16Array(numberOfPolylines);
for (i = 0; i < numberOfPolylines; ++i) {
polylineBatchIds[i] = id++;
}
}
if (!defined_default(pointBatchIds) && numberOfPoints > 0) {
pointBatchIds = new Uint16Array(numberOfPoints);
for (i = 0; i < numberOfPoints; ++i) {
pointBatchIds[i] = id++;
}
}
}
return {
polygons: polygonBatchIds,
polylines: polylineBatchIds,
points: pointBatchIds
};
}
var sizeOfUint327 = Uint32Array.BYTES_PER_ELEMENT;
function createFloatingPolylines(options) {
return new Vector3DTilePolylines_default(options);
}
function createClampedPolylines(options) {
return new Vector3DTileClampedPolylines_default(options);
}
function initialize16(content, arrayBuffer, byteOffset) {
byteOffset = byteOffset ?? 0;
const uint8Array = new Uint8Array(arrayBuffer);
const view = new DataView(arrayBuffer);
byteOffset += sizeOfUint327;
const version2 = view.getUint32(byteOffset, true);
if (version2 !== 1) {
throw new RuntimeError_default(
`Only Vector tile version 1 is supported. Version ${version2} is not.`
);
}
byteOffset += sizeOfUint327;
const byteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint327;
if (byteLength === 0) {
content._ready = true;
return;
}
const featureTableJSONByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint327;
if (featureTableJSONByteLength === 0) {
throw new RuntimeError_default(
"Feature table must have a byte length greater than zero"
);
}
const featureTableBinaryByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint327;
const batchTableJSONByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint327;
const batchTableBinaryByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint327;
const indicesByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint327;
const positionByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint327;
const polylinePositionByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint327;
const pointsPositionByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint327;
const featureTableJson = getJsonFromTypedArray_default(
uint8Array,
byteOffset,
featureTableJSONByteLength
);
byteOffset += featureTableJSONByteLength;
const featureTableBinary = new Uint8Array(
arrayBuffer,
byteOffset,
featureTableBinaryByteLength
);
byteOffset += featureTableBinaryByteLength;
let batchTableJson;
let batchTableBinary;
if (batchTableJSONByteLength > 0) {
batchTableJson = getJsonFromTypedArray_default(
uint8Array,
byteOffset,
batchTableJSONByteLength
);
byteOffset += batchTableJSONByteLength;
if (batchTableBinaryByteLength > 0) {
batchTableBinary = new Uint8Array(
arrayBuffer,
byteOffset,
batchTableBinaryByteLength
);
batchTableBinary = new Uint8Array(batchTableBinary);
byteOffset += batchTableBinaryByteLength;
}
}
const numberOfPolygons = featureTableJson.POLYGONS_LENGTH ?? 0;
const numberOfPolylines = featureTableJson.POLYLINES_LENGTH ?? 0;
const numberOfPoints = featureTableJson.POINTS_LENGTH ?? 0;
const totalPrimitives = numberOfPolygons + numberOfPolylines + numberOfPoints;
const batchTable = new Cesium3DTileBatchTable_default(
content,
totalPrimitives,
batchTableJson,
batchTableBinary,
createColorChangedCallback2(content)
);
content._batchTable = batchTable;
if (totalPrimitives === 0) {
return;
}
const featureTable = new Cesium3DTileFeatureTable_default(
featureTableJson,
featureTableBinary
);
const region = featureTable.getGlobalProperty("REGION");
if (!defined_default(region)) {
throw new RuntimeError_default(
"Feature table global property: REGION must be defined"
);
}
const rectangle = Rectangle_default.unpack(region);
const minHeight = region[4];
const maxHeight = region[5];
const modelMatrix = content._tile.computedTransform;
let center = featureTable.getGlobalProperty(
"RTC_CENTER",
ComponentDatatype_default.FLOAT,
3
);
if (defined_default(center)) {
center = Cartesian3_default.unpack(center);
Matrix4_default.multiplyByPoint(modelMatrix, center, center);
} else {
center = Rectangle_default.center(rectangle);
center.height = Math_default.lerp(minHeight, maxHeight, 0.5);
center = Ellipsoid_default.WGS84.cartographicToCartesian(center);
}
const batchIds = getBatchIds2(featureTableJson, featureTableBinary);
byteOffset += (4 - byteOffset % 4) % 4;
if (numberOfPolygons > 0) {
featureTable.featuresLength = numberOfPolygons;
const polygonCounts = featureTable.getPropertyArray(
"POLYGON_COUNTS",
ComponentDatatype_default.UNSIGNED_INT,
1
) ?? featureTable.getPropertyArray(
"POLYGON_COUNT",
ComponentDatatype_default.UNSIGNED_INT,
1
);
if (!defined_default(polygonCounts)) {
throw new RuntimeError_default(
"Feature table property: POLYGON_COUNTS must be defined when POLYGONS_LENGTH is greater than 0"
);
}
const polygonIndexCounts = featureTable.getPropertyArray(
"POLYGON_INDEX_COUNTS",
ComponentDatatype_default.UNSIGNED_INT,
1
) ?? featureTable.getPropertyArray(
"POLYGON_INDEX_COUNT",
ComponentDatatype_default.UNSIGNED_INT,
1
);
if (!defined_default(polygonIndexCounts)) {
throw new RuntimeError_default(
"Feature table property: POLYGON_INDEX_COUNTS must be defined when POLYGONS_LENGTH is greater than 0"
);
}
const numPolygonPositions = polygonCounts.reduce(function(total, count) {
return total + count * 2;
}, 0);
const numPolygonIndices = polygonIndexCounts.reduce(function(total, count) {
return total + count;
}, 0);
const indices = new Uint32Array(arrayBuffer, byteOffset, numPolygonIndices);
byteOffset += indicesByteLength;
const polygonPositions = new Uint16Array(
arrayBuffer,
byteOffset,
numPolygonPositions
);
byteOffset += positionByteLength;
let polygonMinimumHeights;
let polygonMaximumHeights;
if (defined_default(featureTableJson.POLYGON_MINIMUM_HEIGHTS) && defined_default(featureTableJson.POLYGON_MAXIMUM_HEIGHTS)) {
polygonMinimumHeights = featureTable.getPropertyArray(
"POLYGON_MINIMUM_HEIGHTS",
ComponentDatatype_default.FLOAT,
1
);
polygonMaximumHeights = featureTable.getPropertyArray(
"POLYGON_MAXIMUM_HEIGHTS",
ComponentDatatype_default.FLOAT,
1
);
}
content._polygons = new Vector3DTilePolygons_default({
positions: polygonPositions,
counts: polygonCounts,
indexCounts: polygonIndexCounts,
indices,
minimumHeight: minHeight,
maximumHeight: maxHeight,
polygonMinimumHeights,
polygonMaximumHeights,
center,
rectangle,
boundingVolume: content.tile.boundingVolume.boundingVolume,
batchTable,
batchIds: batchIds.polygons,
modelMatrix
});
}
const tileset = content._tileset;
if (numberOfPolylines > 0) {
featureTable.featuresLength = numberOfPolylines;
const polylineCounts = featureTable.getPropertyArray(
"POLYLINE_COUNTS",
ComponentDatatype_default.UNSIGNED_INT,
1
) ?? featureTable.getPropertyArray(
"POLYLINE_COUNT",
ComponentDatatype_default.UNSIGNED_INT,
1
);
if (!defined_default(polylineCounts)) {
throw new RuntimeError_default(
"Feature table property: POLYLINE_COUNTS must be defined when POLYLINES_LENGTH is greater than 0"
);
}
let widths = featureTable.getPropertyArray(
"POLYLINE_WIDTHS",
ComponentDatatype_default.UNSIGNED_SHORT,
1
);
if (!defined_default(widths)) {
widths = new Uint16Array(numberOfPolylines);
for (let i = 0; i < numberOfPolylines; ++i) {
widths[i] = 2;
}
}
const numPolylinePositions = polylineCounts.reduce(function(total, count) {
return total + count * 3;
}, 0);
const polylinePositions = new Uint16Array(
arrayBuffer,
byteOffset,
numPolylinePositions
);
byteOffset += polylinePositionByteLength;
const examineVectorLinesFunction = tileset.examineVectorLinesFunction;
if (defined_default(examineVectorLinesFunction)) {
const decodedPositions = decodeVectorPolylinePositions_default(
new Uint16Array(polylinePositions),
rectangle,
minHeight,
maxHeight,
Ellipsoid_default.WGS84
);
examineVectorLines(
decodedPositions,
polylineCounts,
batchIds.polylines,
batchTable,
content.url,
examineVectorLinesFunction
);
}
let createPolylines = createFloatingPolylines;
if (defined_default(tileset.classificationType)) {
createPolylines = createClampedPolylines;
}
content._polylines = createPolylines({
positions: polylinePositions,
widths,
counts: polylineCounts,
batchIds: batchIds.polylines,
minimumHeight: minHeight,
maximumHeight: maxHeight,
center,
rectangle,
boundingVolume: content.tile.boundingVolume.boundingVolume,
batchTable,
classificationType: tileset.classificationType,
keepDecodedPositions: tileset.vectorKeepDecodedPositions
});
}
if (numberOfPoints > 0) {
const pointPositions = new Uint16Array(
arrayBuffer,
byteOffset,
numberOfPoints * 3
);
byteOffset += pointsPositionByteLength;
content._points = new Vector3DTilePoints_default({
positions: pointPositions,
batchIds: batchIds.points,
minimumHeight: minHeight,
maximumHeight: maxHeight,
rectangle,
batchTable,
heightReference: tileset.heightReference,
scene: tileset.scene
});
}
}
function createFeatures2(content) {
const featuresLength = content.featuresLength;
if (!defined_default(content._features) && featuresLength > 0) {
const features = new Array(featuresLength);
if (defined_default(content._polygons)) {
content._polygons.createFeatures(content, features);
}
if (defined_default(content._polylines)) {
content._polylines.createFeatures(content, features);
}
if (defined_default(content._points)) {
content._points.createFeatures(content, features);
}
content._features = features;
}
}
Vector3DTileContent.prototype.hasProperty = function(batchId, name) {
return this._batchTable.hasProperty(batchId, name);
};
Vector3DTileContent.prototype.getFeature = function(batchId) {
const featuresLength = this.featuresLength;
if (!defined_default(batchId) || batchId < 0 || batchId >= featuresLength) {
throw new DeveloperError_default(
`batchId is required and between zero and featuresLength - 1 (${featuresLength - 1}).`
);
}
if (!defined_default(this._features)) {
createFeatures2(this);
}
return this._features[batchId];
};
Vector3DTileContent.prototype.applyDebugSettings = function(enabled, color) {
if (defined_default(this._polygons)) {
this._polygons.applyDebugSettings(enabled, color);
}
if (defined_default(this._polylines)) {
this._polylines.applyDebugSettings(enabled, color);
}
if (defined_default(this._points)) {
this._points.applyDebugSettings(enabled, color);
}
};
Vector3DTileContent.prototype.applyStyle = function(style) {
if (!defined_default(this._features)) {
createFeatures2(this);
}
if (defined_default(this._polygons)) {
this._polygons.applyStyle(style, this._features);
}
if (defined_default(this._polylines)) {
this._polylines.applyStyle(style, this._features);
}
if (defined_default(this._points)) {
this._points.applyStyle(style, this._features);
}
};
Vector3DTileContent.prototype.update = function(tileset, frameState) {
let ready = true;
if (defined_default(this._polygons)) {
this._polygons.classificationType = this._tileset.classificationType;
this._polygons.debugWireframe = this._tileset.debugWireframe;
this._polygons.update(frameState);
ready = ready && this._polygons.ready;
}
if (defined_default(this._polylines)) {
this._polylines.update(frameState);
ready = ready && this._polylines.ready;
}
if (defined_default(this._points)) {
this._points.update(frameState);
ready = ready && this._points.ready;
}
if (defined_default(this._batchTable) && ready) {
if (!defined_default(this._features)) {
createFeatures2(this);
}
this._batchTable.update(tileset, frameState);
this._ready = true;
}
};
Vector3DTileContent.prototype.pick = function(ray, frameState, result) {
return void 0;
};
Vector3DTileContent.prototype.getPolylinePositions = function(batchId) {
const polylines = this._polylines;
if (!defined_default(polylines)) {
return void 0;
}
return polylines.getPositions(batchId);
};
Vector3DTileContent.prototype.isDestroyed = function() {
return false;
};
Vector3DTileContent.prototype.destroy = function() {
this._polygons = this._polygons && this._polygons.destroy();
this._polylines = this._polylines && this._polylines.destroy();
this._points = this._points && this._points.destroy();
this._batchTable = this._batchTable && this._batchTable.destroy();
return destroyObject_default(this);
};
function examineVectorLines(positions, counts, batchIds, batchTable, url2, callback) {
const countsLength = counts.length;
let polylineStart = 0;
for (let i = 0; i < countsLength; i++) {
const count = counts[i] * 3;
const linePositions = positions.slice(polylineStart, polylineStart + count);
polylineStart += count;
callback(linePositions, batchIds[i], url2, batchTable);
}
}
var Vector3DTileContent_default = Vector3DTileContent;
// packages/engine/Source/Scene/GaussianSplat3DTileContent.js
var import_InlineWorkers772 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GaussianSplatPrimitive.js
var import_InlineWorkers771 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GaussianSplatSorter.js
var import_InlineWorkers766 = __toESM(require_InlineWorkers(), 1);
function GaussianSplatSorter() {
}
GaussianSplatSorter._maxSortingConcurrency = Math.max(
FeatureDetection_default.hardwareConcurrency - 1,
1
);
GaussianSplatSorter._sorterTaskProcessor = void 0;
GaussianSplatSorter._taskProcessorReady = false;
GaussianSplatSorter._error = void 0;
GaussianSplatSorter._getSorterTaskProcessor = function() {
if (!defined_default(GaussianSplatSorter._sorterTaskProcessor)) {
const processor = new TaskProcessor_default(
"gaussianSplatSorter",
GaussianSplatSorter._maxSortingConcurrency
);
processor.initWebAssemblyModule({
wasmBinaryFile: "ThirdParty/wasm_splats_bg.wasm"
}).then(function(result) {
if (result) {
GaussianSplatSorter._taskProcessorReady = true;
} else {
GaussianSplatSorter._error = new RuntimeError_default(
"Gaussian splat sorter could not be initialized."
);
}
}).catch((error) => {
GaussianSplatSorter._error = error;
});
GaussianSplatSorter._sorterTaskProcessor = processor;
}
return GaussianSplatSorter._sorterTaskProcessor;
};
GaussianSplatSorter.radixSortIndexes = function(parameters) {
const sorterTaskProcessor = GaussianSplatSorter._getSorterTaskProcessor();
if (defined_default(GaussianSplatSorter._error)) {
throw GaussianSplatSorter._error;
}
if (!GaussianSplatSorter._taskProcessorReady) {
return;
}
return sorterTaskProcessor.scheduleTask(parameters, [
parameters.primitive.positions.buffer
]);
};
var GaussianSplatSorter_default = GaussianSplatSorter;
// packages/engine/Source/Scene/GaussianSplatTextureGenerator.js
var import_InlineWorkers767 = __toESM(require_InlineWorkers(), 1);
function GaussianSplatTextureGenerator() {
}
GaussianSplatTextureGenerator._maxSortingConcurrency = Math.max(
FeatureDetection_default.hardwareConcurrency - 1,
1
);
GaussianSplatTextureGenerator._textureTaskProcessor = void 0;
GaussianSplatTextureGenerator._taskProcessorReady = false;
GaussianSplatTextureGenerator._error = void 0;
GaussianSplatTextureGenerator._getTextureTaskProcessor = function() {
if (!defined_default(GaussianSplatTextureGenerator._textureTaskProcessor)) {
const processor = new TaskProcessor_default(
"gaussianSplatTextureGenerator",
GaussianSplatTextureGenerator._maxSortingConcurrency
);
processor.initWebAssemblyModule({
wasmBinaryFile: "ThirdParty/wasm_splats_bg.wasm"
}).then(function(result) {
if (result) {
GaussianSplatTextureGenerator._taskProcessorReady = true;
} else {
GaussianSplatTextureGenerator._error = new RuntimeError_default(
"Gaussian splat sorter could not be initialized."
);
}
}).catch((error) => {
GaussianSplatTextureGenerator._error = error;
});
GaussianSplatTextureGenerator._textureTaskProcessor = processor;
}
return GaussianSplatTextureGenerator._textureTaskProcessor;
};
GaussianSplatTextureGenerator.generateFromAttributes = function(parameters) {
const textureTaskProcessor = GaussianSplatTextureGenerator._getTextureTaskProcessor();
if (defined_default(GaussianSplatTextureGenerator._error)) {
throw GaussianSplatTextureGenerator._error;
}
if (!GaussianSplatTextureGenerator._taskProcessorReady) {
return;
}
const { attributes } = parameters;
return textureTaskProcessor.scheduleTask(parameters, [
attributes.positions.buffer,
attributes.scales.buffer,
attributes.rotations.buffer,
attributes.colors.buffer
]);
};
var GaussianSplatTextureGenerator_default = GaussianSplatTextureGenerator;
// packages/engine/Source/Scene/GaussianSplatRenderResources.js
var import_InlineWorkers768 = __toESM(require_InlineWorkers(), 1);
function GaussianSplatRenderResources(primitive) {
const shaderBuilder = new ShaderBuilder_default();
this.shaderBuilder = shaderBuilder;
this.uniformMap = {};
this.renderStateOptions = RenderState_default.getState(
RenderState_default.fromCache({
depthTest: {
enabled: true,
func: DepthFunction_default.LESS_OR_EQUAL
}
})
);
this.alphaOptions = new ModelAlphaOptions_default();
this.hasSkipLevelOfDetail = false;
if (primitive._useLogDepth) {
shaderBuilder.addDefine(
"LOG_DEPTH_READ_ONLY",
void 0,
ShaderDestination_default.FRAGMENT
);
}
}
var GaussianSplatRenderResources_default = GaussianSplatRenderResources;
// packages/engine/Source/Shaders/PrimitiveGaussianSplatVS.js
var import_InlineWorkers769 = __toESM(require_InlineWorkers(), 1);
var PrimitiveGaussianSplatVS_default = "//\n// Vertex shader for Gaussian splats.\n\n// The splats are rendered as quads in view space. Splat attributes are loaded from a texture with precomputed 3D covariance.\n\n// Passes local quad coordinates and color to the fragment shader for Gaussian evaluation. \n//\n// Discards splats outside the view frustum or with negligible screen size.\n//\n#if defined(HAS_SPHERICAL_HARMONICS)\nconst uint coefficientCount[3] = uint[3](3u,8u,15u);\nconst float SH_C1 = 0.48860251;\nconst float SH_C2[5] = float[5](\n 1.092548430,\n -1.09254843,\n 0.315391565,\n -1.09254843,\n 0.546274215\n);\n\nconst float SH_C3[7] = float[7](\n -0.59004358,\n 2.890611442,\n -0.45704579,\n 0.373176332,\n -0.45704579,\n 1.445305721,\n -0.59004358\n);\n\n//Retrieve SH coefficient. Currently RG32UI format\nuvec2 loadSHCoeff(uint splatID, int index) {\n ivec2 shTexSize = textureSize(u_sphericalHarmonicsTexture, 0);\n uint dims = coefficientCount[uint(u_sphericalHarmonicsDegree)-1u];\n uint splatsPerRow = uint(shTexSize.x) / dims;\n uint shIndex = (splatID%splatsPerRow) * dims + uint(index);\n ivec2 shPosCoord = ivec2(shIndex, splatID / splatsPerRow);\n return texelFetch(u_sphericalHarmonicsTexture, shPosCoord, 0).rg;\n}\n\n//Unpack RG32UI half float coefficients to vec3\nvec3 halfToVec3(uvec2 packed) {\n return vec3(unpackHalf2x16(packed.x), unpackHalf2x16(packed.y).x);\n}\n\nvec3 loadAndExpandSHCoeff(uint splatID, int index) {\n uvec2 coeff = loadSHCoeff(splatID, index);\n return halfToVec3(coeff);\n}\n\nvec3 evaluateSH(uint splatID, vec3 viewDir) {\n vec3 result = vec3(0.0);\n int coeffIndex = 0;\n float x = viewDir.x, y = viewDir.y, z = viewDir.z;\n\n if (u_sphericalHarmonicsDegree >= 1.) {\n vec3 sh1 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh2 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh3 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n result += -SH_C1 * y * sh1 + SH_C1 * z * sh2 - SH_C1 * x * sh3;\n\n if (u_sphericalHarmonicsDegree >= 2.) {\n float xx = x * x;\n float yy = y * y;\n float zz = z * z;\n float xy = x * y;\n float yz = y * z;\n float xz = x * z;\n\n vec3 sh4 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh5 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh6 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh7 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh8 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n result += SH_C2[0] * xy * sh4 +\n SH_C2[1] * yz * sh5 +\n SH_C2[2] * (2.0f * zz - xx - yy) * sh6 +\n SH_C2[3] * xz * sh7 +\n SH_C2[4] * (xx - yy) * sh8;\n\n if (u_sphericalHarmonicsDegree >= 3.) {\n vec3 sh9 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh10 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh11 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh12 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh13 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh14 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n vec3 sh15 = loadAndExpandSHCoeff(splatID, coeffIndex++);\n result += SH_C3[0] * y * (3.0f * xx - yy) * sh9 +\n SH_C3[1] * xy * z * sh10 +\n SH_C3[2] * y * (4.0f * zz - xx - yy) * sh11 +\n SH_C3[3] * z * (2.0f * zz - 3.0f * xx - 3.0f * yy) * sh12 +\n SH_C3[4] * x * (4.0f * zz - xx - yy) * sh13 +\n SH_C3[5] * z * (xx - yy) * sh14 +\n SH_C3[6] * x * (xx - 3.0f * yy) * sh15;\n }\n }\n }\n return result;\n}\n#endif\n\n// Transforms and projects splat covariance into screen space and extracts the major and minor axes of the Gaussian ellipsoid\n// which is used to calculate the vertex position in clip space.\nvec4 calcCovVectors(vec3 viewPos, mat3 Vrk) {\n vec4 t = vec4(viewPos, 1.0);\n vec2 focal = vec2(czm_projection[0][0] * czm_viewport.z, czm_projection[1][1] * czm_viewport.w);\n\n vec2 J1 = focal / t.z;\n vec2 J2 = -focal * vec2(t.x, t.y) / (t.z * t.z);\n mat3 J = mat3(\n J1.x, 0.0, J2.x,\n 0.0, J1.y, J2.y,\n 0.0, 0.0, 0.0\n );\n\n mat3 R = mat3(czm_modelView);\n\n //transform our covariance into view space\n //ensures orientation is correct\n mat3 Vrk_view = R * Vrk * transpose(R);\n mat3 cov = transpose(J) * Vrk_view * J;\n\n float diagonal1 = cov[0][0] + .3;\n float offDiagonal = cov[0][1];\n float diagonal2 = cov[1][1] + .3;\n\n float mid = 0.5 * (diagonal1 + diagonal2);\n float radius = length(vec2((diagonal1 - diagonal2) * 0.5, offDiagonal));\n float lambda1 = mid + radius;\n float lambda2 = max(mid - radius, 0.1);\n\n vec2 diagonalVector = normalize(vec2(offDiagonal, lambda1 - diagonal1));\n\n return vec4(\n min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector,\n min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x)\n );\n}\n\nhighp vec4 discardVec = vec4(0.0, 0.0, 2.0, 1.0);\n\nvoid main() {\n uint texIdx = uint(a_splatIndex);\n ivec2 posCoord = ivec2((texIdx & 0x3ffu) << 1, texIdx >> 10);\n vec4 splatPosition = vec4( uintBitsToFloat(uvec4(texelFetch(u_splatAttributeTexture, posCoord, 0))) );\n\n vec4 splatViewPos = czm_modelView * vec4(splatPosition.xyz, 1.0);\n vec4 clipPosition = czm_projection * splatViewPos;\n\n float clip = 1.2 * clipPosition.w;\n if (clipPosition.z < -clip || clipPosition.x < -clip || clipPosition.x > clip ||\n clipPosition.y < -clip || clipPosition.y > clip) {\n gl_Position = vec4(0.0, 0.0, 2.0, 1.0);\n return;\n }\n\n ivec2 covCoord = ivec2(((texIdx & 0x3ffu) << 1) | 1u, texIdx >> 10);\n uvec4 covariance = uvec4(texelFetch(u_splatAttributeTexture, covCoord, 0));\n\n gl_Position = clipPosition;\n\n vec2 u1 = unpackHalf2x16(covariance.x) ;\n vec2 u2 = unpackHalf2x16(covariance.y);\n vec2 u3 = unpackHalf2x16(covariance.z);\n mat3 Vrk = mat3(u1.x, u1.y, u2.x, u1.y, u2.y, u3.x, u2.x, u3.x, u3.y);\n\n vec4 covVectors = calcCovVectors(splatViewPos.xyz, Vrk);\n\n if (dot(covVectors.xy, covVectors.xy) < 4.0 && dot(covVectors.zw, covVectors.zw) < 4.0) {\n gl_Position = discardVec;\n return;\n }\n\n vec2 corner = vec2((gl_VertexID << 1) & 2, gl_VertexID & 2) - 1.;\n\n gl_Position += vec4((corner.x * covVectors.xy + corner.y * covVectors.zw) / czm_viewport.zw * gl_Position.w, 0, 0);\n gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w));\n\n v_vertPos = corner ;\n v_splatColor = vec4(covariance.w & 0xffu, (covariance.w >> 8) & 0xffu, (covariance.w >> 16) & 0xffu, (covariance.w >> 24) & 0xffu) / 255.0;\n#if defined(HAS_SPHERICAL_HARMONICS)\n vec4 splatWC = czm_inverseView * splatViewPos;\n vec3 viewDirModel = normalize(u_inverseModelRotation * (splatWC.xyz - u_cameraPositionWC.xyz));\n\n v_splatColor.rgb += evaluateSH(texIdx, viewDirModel).rgb;\n#endif\n v_splitDirection = u_splitDirection;\n}";
// packages/engine/Source/Shaders/PrimitiveGaussianSplatFS.js
var import_InlineWorkers770 = __toESM(require_InlineWorkers(), 1);
var PrimitiveGaussianSplatFS_default = "//\n// Fragment shader for Gaussian splats.\n// Renders a Gaussian splat within a quad, discarding fragments outside the unit circle.\n// Applies an approximate Gaussian falloff based on distance from the center and outputs\n// a color modulated by the alpha and Gaussian weight.\n//\nvoid main() {\n if (v_splitDirection < 0.0 && gl_FragCoord.x > czm_splitPosition) discard;\n if (v_splitDirection > 0.0 && gl_FragCoord.x < czm_splitPosition) discard;\n\n float A = -dot(v_vertPos, v_vertPos);\n if (A < -4.) {\n discard;\n }\n\n float B = exp(A * 4.) * v_splatColor.a ;\n out_FragColor = vec4(v_splatColor.rgb * B , B);\n}\n";
// packages/engine/Source/Scene/GaussianSplatPrimitive.js
var scratchMatrix4A = new Matrix4_default();
var scratchMatrix4B = new Matrix4_default();
var scratchMatrix4C = new Matrix4_default();
var scratchMatrix4D = new Matrix4_default();
var GaussianSplatSortingState = {
IDLE: 0,
WAITING: 1,
SORTING: 2,
SORTED: 3,
ERROR: 4
};
function createSphericalHarmonicsTexture(context, shData) {
const texture = new Texture_default({
context,
source: {
width: shData.width,
height: shData.height,
arrayBufferView: shData.data
},
preMultiplyAlpha: false,
skipColorSpaceConversion: true,
pixelFormat: PixelFormat_default.RG_INTEGER,
pixelDatatype: PixelDatatype_default.UNSIGNED_INT,
flipY: false,
sampler: Sampler_default.NEAREST
});
return texture;
}
function createGaussianSplatTexture(context, splatTextureData) {
return new Texture_default({
context,
source: {
width: splatTextureData.width,
height: splatTextureData.height,
arrayBufferView: splatTextureData.data
},
preMultiplyAlpha: false,
skipColorSpaceConversion: true,
pixelFormat: PixelFormat_default.RGBA_INTEGER,
pixelDatatype: PixelDatatype_default.UNSIGNED_INT,
flipY: false,
sampler: Sampler_default.NEAREST
});
}
function GaussianSplatPrimitive(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._positions = void 0;
this._rotations = void 0;
this._scales = void 0;
this._colors = void 0;
this._indexes = void 0;
this._numSplats = 0;
this._needsGaussianSplatTexture = true;
this._prevViewMatrix = new Matrix4_default();
this._debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this.gaussianSplatTexture = void 0;
this.sphericalHarmonicsTexture = void 0;
this._lastTextureWidth = 0;
this._lastTextureHeight = 0;
this._vertexArray = void 0;
this._vertexArrayLen = -1;
this._splitDirection = SplitDirection_default.NONE;
this._dirty = false;
this._tileset = options.tileset;
this._baseTilesetUpdate = this._tileset.update;
this._tileset.update = this._wrappedUpdate.bind(this);
this._tileset.tileLoad.addEventListener(this.onTileLoad, this);
this._tileset.tileVisible.addEventListener(this.onTileVisible, this);
this.selectedTileLength = 0;
this._ready = false;
this._hasGaussianSplatTexture = false;
this._gaussianSplatTexturePending = false;
this._drawCommand = void 0;
this._rootTransform = void 0;
this._axisCorrectionMatrix = ModelUtility_default.getAxisCorrectionMatrix(
Axis_default.Y,
Axis_default.X,
new Matrix4_default()
);
this._isDestroyed = false;
this._sorterState = GaussianSplatSortingState.IDLE;
this._sorterPromise = void 0;
this._sorterError = void 0;
}
Object.defineProperties(GaussianSplatPrimitive.prototype, {
/**
* Indicates whether the primitive is ready for use.
* @memberof GaussianSplatPrimitive.prototype
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
},
/**
* The {@link SplitDirection} to apply to this point.
* @memberof GaussianSplatPrimitive.prototype
* @type {SplitDirection}
* @default {@link SplitDirection.NONE}
*/
splitDirection: {
get: function() {
return this._splitDirection;
},
set: function(value) {
if (this._splitDirection !== value) {
this._splitDirection = value;
this._dirty = true;
}
}
}
});
GaussianSplatPrimitive.prototype._wrappedUpdate = function(frameState) {
this._baseTilesetUpdate.call(this._tileset, frameState);
this.update(frameState);
};
GaussianSplatPrimitive.prototype.destroy = function() {
this._positions = void 0;
this._rotations = void 0;
this._scales = void 0;
this._colors = void 0;
this._indexes = void 0;
if (defined_default(this.gaussianSplatTexture)) {
this.gaussianSplatTexture.destroy();
this.gaussianSplatTexture = void 0;
}
const drawCommand = this._drawCommand;
if (defined_default(drawCommand)) {
drawCommand.shaderProgram = drawCommand.shaderProgram && drawCommand.shaderProgram.destroy();
}
if (defined_default(this._vertexArray)) {
this._vertexArray.destroy();
this._vertexArray = void 0;
}
this._tileset.update = this._baseTilesetUpdate.bind(this._tileset);
return destroyObject_default(this);
};
GaussianSplatPrimitive.prototype.isDestroyed = function() {
return this._isDestroyed;
};
GaussianSplatPrimitive.prototype.onTileLoad = function(tile) {
this._dirty = true;
};
GaussianSplatPrimitive.prototype.onTileVisible = function(tile) {
};
GaussianSplatPrimitive.transformTile = function(tile) {
const computedTransform = tile.computedTransform;
const gltfPrimitive = tile.content.gltfPrimitive;
const gaussianSplatPrimitive = tile.tileset.gaussianSplatPrimitive;
const computedModelMatrix = Matrix4_default.multiplyTransformation(
computedTransform,
gaussianSplatPrimitive._axisCorrectionMatrix,
scratchMatrix4A
);
Matrix4_default.multiplyTransformation(
computedModelMatrix,
tile.content.worldTransform,
computedModelMatrix
);
const toGlobal = Matrix4_default.multiply(
tile.tileset.modelMatrix,
Matrix4_default.fromArray(tile.tileset.root.transform),
scratchMatrix4B
);
const toLocal = Matrix4_default.inverse(toGlobal, scratchMatrix4C);
const transform3 = Matrix4_default.multiplyTransformation(
toLocal,
computedModelMatrix,
scratchMatrix4A
);
const positions = tile.content._originalPositions;
const rotations = tile.content._originalRotations;
const scales = tile.content._originalScales;
const attributePositions = ModelUtility_default.getAttributeBySemantic(
gltfPrimitive,
VertexAttributeSemantic_default.POSITION
).typedArray;
const attributeRotations = ModelUtility_default.getAttributeBySemantic(
gltfPrimitive,
VertexAttributeSemantic_default.ROTATION
).typedArray;
const attributeScales = ModelUtility_default.getAttributeBySemantic(
gltfPrimitive,
VertexAttributeSemantic_default.SCALE
).typedArray;
const position = new Cartesian3_default();
const rotation = new Quaternion_default();
const scale = new Cartesian3_default();
for (let i = 0; i < positions.length / 3; ++i) {
position.x = positions[i * 3];
position.y = positions[i * 3 + 1];
position.z = positions[i * 3 + 2];
rotation.x = rotations[i * 4];
rotation.y = rotations[i * 4 + 1];
rotation.z = rotations[i * 4 + 2];
rotation.w = rotations[i * 4 + 3];
scale.x = scales[i * 3];
scale.y = scales[i * 3 + 1];
scale.z = scales[i * 3 + 2];
Matrix4_default.fromTranslationQuaternionRotationScale(
position,
rotation,
scale,
scratchMatrix4C
);
Matrix4_default.multiplyTransformation(transform3, scratchMatrix4C, scratchMatrix4C);
Matrix4_default.getTranslation(scratchMatrix4C, position);
Matrix4_default.getRotation(scratchMatrix4C, rotation);
Matrix4_default.getScale(scratchMatrix4C, scale);
attributePositions[i * 3] = position.x;
attributePositions[i * 3 + 1] = position.y;
attributePositions[i * 3 + 2] = position.z;
attributeRotations[i * 4] = rotation.x;
attributeRotations[i * 4 + 1] = rotation.y;
attributeRotations[i * 4 + 2] = rotation.z;
attributeRotations[i * 4 + 3] = rotation.w;
attributeScales[i * 3] = scale.x;
attributeScales[i * 3 + 1] = scale.y;
attributeScales[i * 3 + 2] = scale.z;
}
};
GaussianSplatPrimitive.generateSplatTexture = function(primitive, frameState) {
primitive._gaussianSplatTexturePending = true;
const promise = GaussianSplatTextureGenerator_default.generateFromAttributes({
attributes: {
positions: new Float32Array(primitive._positions),
scales: new Float32Array(primitive._scales),
rotations: new Float32Array(primitive._rotations),
colors: new Uint8Array(primitive._colors)
},
count: primitive._numSplats
});
if (!defined_default(promise)) {
primitive._gaussianSplatTexturePending = false;
return;
}
promise.then((splatTextureData) => {
if (!primitive._gaussianSplatTexture) {
primitive.gaussianSplatTexture = createGaussianSplatTexture(
frameState.context,
splatTextureData
);
} else if (primitive._lastTextureHeight !== splatTextureData.height || primitive._lastTextureWidth !== splatTextureData.width) {
const oldTex = primitive.gaussianSplatTexture;
primitive._gaussianSplatTexture = createGaussianSplatTexture(
frameState.context,
splatTextureData
);
oldTex.destroy();
} else {
primitive.gaussianSplatTexture.copyFrom({
source: {
width: splatTextureData.width,
height: splatTextureData.height,
arrayBufferView: splatTextureData.data
}
});
}
primitive._lastTextureHeight = splatTextureData.height;
primitive._lastTextureWidth = splatTextureData.width;
primitive._hasGaussianSplatTexture = true;
primitive._needsGaussianSplatTexture = false;
primitive._gaussianSplatTexturePending = false;
if (!defined_default(primitive._indexes) || primitive._indexes.length < primitive._numSplats) {
primitive._indexes = new Uint32Array(primitive._numSplats);
}
for (let i = 0; i < primitive._numSplats; ++i) {
primitive._indexes[i] = i;
}
}).catch((error) => {
console.error("Error generating Gaussian splat texture:", error);
primitive._gaussianSplatTexturePending = false;
});
};
GaussianSplatPrimitive.buildGSplatDrawCommand = function(primitive, frameState) {
const tileset = primitive._tileset;
const renderResources = new GaussianSplatRenderResources_default(primitive);
const { shaderBuilder } = renderResources;
const renderStateOptions = renderResources.renderStateOptions;
renderStateOptions.cull.enabled = false;
renderStateOptions.depthMask = false;
renderStateOptions.depthTest.enabled = true;
renderStateOptions.blending = BlendingState_default.PRE_MULTIPLIED_ALPHA_BLEND;
renderResources.alphaOptions.pass = Pass_default.GAUSSIAN_SPLATS;
shaderBuilder.addAttribute("vec2", "a_screenQuadPosition");
shaderBuilder.addAttribute("float", "a_splatIndex");
shaderBuilder.addVarying("vec4", "v_splatColor");
shaderBuilder.addVarying("vec2", "v_vertPos");
shaderBuilder.addUniform(
"float",
"u_splitDirection",
ShaderDestination_default.VERTEX
);
shaderBuilder.addVarying("float", "v_splitDirection");
shaderBuilder.addUniform(
"highp usampler2D",
"u_splatAttributeTexture",
ShaderDestination_default.VERTEX
);
shaderBuilder.addUniform(
"float",
"u_sphericalHarmonicsDegree",
ShaderDestination_default.VERTEX
);
shaderBuilder.addUniform("float", "u_splatScale", ShaderDestination_default.VERTEX);
shaderBuilder.addUniform(
"vec3",
"u_cameraPositionWC",
ShaderDestination_default.VERTEX
);
shaderBuilder.addUniform(
"mat3",
"u_inverseModelRotation",
ShaderDestination_default.VERTEX
);
const uniformMap2 = renderResources.uniformMap;
uniformMap2.u_splatAttributeTexture = function() {
return primitive.gaussianSplatTexture;
};
if (primitive._sphericalHarmonicsDegree > 0) {
shaderBuilder.addDefine(
"HAS_SPHERICAL_HARMONICS",
"1",
ShaderDestination_default.VERTEX
);
shaderBuilder.addUniform(
"highp usampler2D",
"u_sphericalHarmonicsTexture",
ShaderDestination_default.VERTEX
);
uniformMap2.u_sphericalHarmonicsTexture = function() {
return primitive.sphericalHarmonicsTexture;
};
}
uniformMap2.u_sphericalHarmonicsDegree = function() {
return primitive._sphericalHarmonicsDegree;
};
uniformMap2.u_cameraPositionWC = function() {
return Cartesian3_default.clone(frameState.camera.positionWC);
};
uniformMap2.u_inverseModelRotation = function() {
const tileset2 = primitive._tileset;
const modelMatrix2 = Matrix4_default.multiply(
tileset2.modelMatrix,
Matrix4_default.fromArray(tileset2.root.transform),
scratchMatrix4A
);
const inverseModelRotation = Matrix4_default.getRotation(
Matrix4_default.inverse(modelMatrix2, scratchMatrix4C),
scratchMatrix4D
);
return inverseModelRotation;
};
uniformMap2.u_splitDirection = function() {
return primitive.splitDirection;
};
renderResources.instanceCount = primitive._numSplats;
renderResources.count = 4;
renderResources.primitiveType = PrimitiveType_default.TRIANGLE_STRIP;
shaderBuilder.addVertexLines(PrimitiveGaussianSplatVS_default);
shaderBuilder.addFragmentLines(PrimitiveGaussianSplatFS_default);
const shaderProgram = shaderBuilder.buildShaderProgram(frameState.context);
let renderState = clone_default(
RenderState_default.fromCache(renderResources.renderStateOptions),
true
);
renderState.cull.face = ModelUtility_default.getCullFace(
tileset.modelMatrix,
PrimitiveType_default.TRIANGLE_STRIP
);
renderState = RenderState_default.fromCache(renderState);
const splatQuadAttrLocations = {
screenQuadPosition: 0,
splatIndex: 2
};
const idxAttr = new ModelComponents_default.Attribute();
idxAttr.name = "_SPLAT_INDEXES";
idxAttr.typedArray = primitive._indexes;
idxAttr.componentDatatype = ComponentDatatype_default.UNSIGNED_INT;
idxAttr.type = AttributeType_default.SCALAR;
idxAttr.normalized = false;
idxAttr.count = renderResources.instanceCount;
idxAttr.constant = 0;
idxAttr.instanceDivisor = 1;
if (!defined_default(primitive._vertexArray) || primitive._indexes.length > primitive._vertexArrayLen) {
const geometry = new Geometry_default({
attributes: {
screenQuadPosition: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: [-1, -1, 1, -1, 1, 1, -1, 1],
name: "_SCREEN_QUAD_POS",
variableName: "screenQuadPosition"
}),
splatIndex: { ...idxAttr, variableName: "splatIndex" }
},
primitiveType: PrimitiveType_default.TRIANGLE_STRIP
});
primitive._vertexArray = VertexArray_default.fromGeometry({
context: frameState.context,
geometry,
attributeLocations: splatQuadAttrLocations,
bufferUsage: BufferUsage_default.DYNAMIC_DRAW,
interleave: false
});
} else {
primitive._vertexArray.getAttribute(1).vertexBuffer.copyFromArrayView(primitive._indexes);
}
primitive._vertexArrayLen = primitive._indexes.length;
const modelMatrix = Matrix4_default.multiply(
tileset.modelMatrix,
Matrix4_default.fromArray(tileset.root.transform),
scratchMatrix4B
);
const command = new DrawCommand_default({
boundingVolume: tileset.boundingSphere,
modelMatrix,
uniformMap: uniformMap2,
renderState,
vertexArray: primitive._vertexArray,
shaderProgram,
cull: renderStateOptions.cull.enabled,
pass: Pass_default.GAUSSIAN_SPLATS,
count: renderResources.count,
owner: this,
instanceCount: renderResources.instanceCount,
primitiveType: PrimitiveType_default.TRIANGLE_STRIP,
debugShowBoundingVolume: tileset.debugShowBoundingVolume,
castShadows: false,
receiveShadows: false
});
primitive._drawCommand = command;
};
GaussianSplatPrimitive.prototype.update = function(frameState) {
const tileset = this._tileset;
if (!defined_default(this._rootTransform)) {
this._rootTransform = tileset.root.computedTransform;
}
if (!tileset.show || tileset._selectedTiles.length === 0) {
return;
}
if (this._drawCommand) {
frameState.commandList.push(this._drawCommand);
}
if (tileset._modelMatrixChanged) {
this._dirty = true;
return;
}
if (frameState.passes.pick === true) {
return;
}
if (this.splitDirection !== tileset.splitDirection) {
this.splitDirection = tileset.splitDirection;
}
if (this._sorterState === GaussianSplatSortingState.IDLE) {
if (!this._dirty && Matrix4_default.equals(frameState.camera.viewMatrix, this._prevViewMatrix)) {
return;
}
if (tileset._selectedTiles.length !== 0 && tileset._selectedTiles.length !== this.selectedTileLength) {
this._numSplats = 0;
this._positions = void 0;
this._rotations = void 0;
this._scales = void 0;
this._colors = void 0;
this._indexes = void 0;
this._shData = void 0;
this._needsGaussianSplatTexture = true;
this._gaussianSplatTexturePending = false;
const tiles = tileset._selectedTiles;
const totalElements = tiles.reduce(
(total, tile) => total + tile.content.pointsLength,
0
);
const aggregateAttributeValues = (componentDatatype, getAttributeCallback) => {
let aggregate;
let offset = 0;
for (const tile of tiles) {
const primitive = tile.content.gltfPrimitive;
const attribute = getAttributeCallback(primitive);
if (!defined_default(aggregate)) {
aggregate = ComponentDatatype_default.createTypedArray(
componentDatatype,
totalElements * AttributeType_default.getNumberOfComponents(attribute.type)
);
}
aggregate.set(attribute.typedArray, offset);
offset += attribute.typedArray.length;
}
return aggregate;
};
const aggregateShData = () => {
let offset = 0;
for (const tile of tiles) {
const shData = tile.content.packedSphericalHarmonicsData;
if (tile.content.sphericalHarmonicsDegree > 0) {
if (!defined_default(this._shData)) {
let coefs;
switch (tile.content.sphericalHarmonicsDegree) {
case 1:
coefs = 9;
break;
case 2:
coefs = 24;
break;
case 3:
coefs = 45;
}
this._shData = new Uint32Array(totalElements * (coefs * (2 / 3)));
}
this._shData.set(shData, offset);
offset += shData.length;
}
}
};
this._positions = aggregateAttributeValues(
ComponentDatatype_default.FLOAT,
(gltfPrimitive) => ModelUtility_default.getAttributeBySemantic(
gltfPrimitive,
VertexAttributeSemantic_default.POSITION
)
);
this._scales = aggregateAttributeValues(
ComponentDatatype_default.FLOAT,
(gltfPrimitive) => ModelUtility_default.getAttributeBySemantic(
gltfPrimitive,
VertexAttributeSemantic_default.SCALE
)
);
this._rotations = aggregateAttributeValues(
ComponentDatatype_default.FLOAT,
(gltfPrimitive) => ModelUtility_default.getAttributeBySemantic(
gltfPrimitive,
VertexAttributeSemantic_default.ROTATION
)
);
this._colors = aggregateAttributeValues(
ComponentDatatype_default.UNSIGNED_BYTE,
(gltfPrimitive) => ModelUtility_default.getAttributeBySemantic(
gltfPrimitive,
VertexAttributeSemantic_default.COLOR
)
);
aggregateShData();
this._sphericalHarmonicsDegree = tiles[0].content.sphericalHarmonicsDegree;
this._numSplats = totalElements;
this.selectedTileLength = tileset._selectedTiles.length;
}
if (this._numSplats === 0) {
return;
}
if (this._needsGaussianSplatTexture) {
if (!this._gaussianSplatTexturePending) {
GaussianSplatPrimitive.generateSplatTexture(this, frameState);
if (defined_default(this._shData)) {
const oldTex = this.sphericalHarmonicsTexture;
const width = ContextLimits_default.maximumTextureSize;
const dims = tileset._selectedTiles[0].content.sphericalHarmonicsCoefficientCount / 3;
const splatsPerRow = Math.floor(width / dims);
const floatsPerRow = splatsPerRow * (dims * 2);
const texBuf = new Uint32Array(
width * Math.ceil(this._numSplats / splatsPerRow) * 2
);
let dataIndex = 0;
for (let i = 0; dataIndex < this._shData.length; i += width * 2) {
texBuf.set(
this._shData.subarray(dataIndex, dataIndex + floatsPerRow),
i
);
dataIndex += floatsPerRow;
}
this.sphericalHarmonicsTexture = createSphericalHarmonicsTexture(
frameState.context,
{
data: texBuf,
width,
height: Math.ceil(this._numSplats / splatsPerRow)
}
);
if (defined_default(oldTex)) {
oldTex.destroy();
}
}
}
return;
}
Matrix4_default.clone(frameState.camera.viewMatrix, this._prevViewMatrix);
Matrix4_default.multiply(
frameState.camera.viewMatrix,
this._rootTransform,
scratchMatrix4A
);
if (!defined_default(this._sorterPromise)) {
this._sorterPromise = GaussianSplatSorter_default.radixSortIndexes({
primitive: {
positions: new Float32Array(this._positions),
modelView: Float32Array.from(scratchMatrix4A),
count: this._numSplats
},
sortType: "Index"
});
}
if (!defined_default(this._sorterPromise)) {
this._sorterState = GaussianSplatSortingState.WAITING;
return;
}
this._sorterPromise.catch((err) => {
this._sorterState = GaussianSplatSortingState.ERROR;
this._sorterError = err;
});
this._sorterPromise.then((sortedData) => {
this._indexes = sortedData;
this._sorterState = GaussianSplatSortingState.SORTED;
});
} else if (this._sorterState === GaussianSplatSortingState.WAITING) {
if (!defined_default(this._sorterPromise)) {
this._sorterPromise = GaussianSplatSorter_default.radixSortIndexes({
primitive: {
positions: new Float32Array(this._positions),
modelView: Float32Array.from(scratchMatrix4A),
count: this._numSplats
},
sortType: "Index"
});
}
if (!defined_default(this._sorterPromise)) {
this._sorterState = GaussianSplatSortingState.WAITING;
return;
}
this._sorterPromise.catch((err) => {
this._sorterState = GaussianSplatSortingState.ERROR;
this._sorterError = err;
});
this._sorterPromise.then((sortedData) => {
this._indexes = sortedData;
this._sorterState = GaussianSplatSortingState.SORTED;
});
this._sorterState = GaussianSplatSortingState.SORTING;
} else if (this._sorterState === GaussianSplatSortingState.SORTING) {
return;
} else if (this._sorterState === GaussianSplatSortingState.SORTED) {
GaussianSplatPrimitive.buildGSplatDrawCommand(this, frameState);
this._sorterState = GaussianSplatSortingState.IDLE;
this._dirty = false;
this._sorterPromise = void 0;
} else if (this._sorterState === GaussianSplatSortingState.ERROR) {
throw this._sorterError;
}
this._dirty = false;
};
var GaussianSplatPrimitive_default = GaussianSplatPrimitive;
// packages/engine/Source/Scene/GaussianSplat3DTileContent.js
function GaussianSplat3DTileContent(loader, tileset, tile, resource) {
this._tileset = tileset;
this._tile = tile;
this._resource = resource;
this._loader = loader;
if (!defined_default(this._tileset.gaussianSplatPrimitive)) {
this._tileset.gaussianSplatPrimitive = new GaussianSplatPrimitive_default({
tileset: this._tileset
});
}
this._originalPositions = void 0;
this._originalRotations = void 0;
this._originalScales = void 0;
this.gltfPrimitive = void 0;
this.worldTransform = void 0;
this.featurePropertiesDirty = false;
this._metadata = void 0;
this._group = void 0;
this._ready = false;
this._transformed = false;
this._sphericalHarmonicsDegree = 0;
this._sphericalHarmonicsCoefficientCount = 0;
this._packedSphericalHarmonicsData = void 0;
}
GaussianSplat3DTileContent.tilesetRequiresGaussianSplattingExt = function(tileset) {
let hasGaussianSplatExtension = false;
let hasLegacyGaussianSplatExtension = false;
if (tileset.isGltfExtensionRequired instanceof Function) {
hasGaussianSplatExtension = tileset.isGltfExtensionRequired("KHR_gaussian_splatting") && tileset.isGltfExtensionRequired(
"KHR_gaussian_splatting_compression_spz_2"
);
hasLegacyGaussianSplatExtension = tileset.isGltfExtensionRequired(
"KHR_spz_gaussian_splats_compression"
);
}
if (hasLegacyGaussianSplatExtension) {
deprecationWarning_default(
"KHR_spz_gaussian_splats_compression",
"Support for the original KHR_spz_gaussian_splats_compression extension has been deprecated in favor of the up to date KHR_gaussian_splatting and KHR_gaussian_splatting_compression_spz_2 extensions and will be removed in CesiumJS 1.135.\n\nPlease retile your tileset with the KHR_gaussian_splatting and KHR_gaussian_splatting_compression_spz_2 extensions."
);
}
return hasGaussianSplatExtension || hasLegacyGaussianSplatExtension;
};
Object.defineProperties(GaussianSplat3DTileContent.prototype, {
/**
* Gets the number of features in the tile. Currently this is always zero.
*
* @memberof GaussianSplat3DTileContent.prototype
*
* @type {number}
* @readonly
*/
featuresLength: {
get: function() {
return 0;
}
},
/**
* Equal to the number of Gaussian splats in the tile. Each splat is represented by a median point and a set of attributes, so we can
* treat this as the number of points in the tile.
*
* @memberof GaussianSplat3DTileContent.prototype
*
* @type {number}
* @readonly
*/
pointsLength: {
get: function() {
return this.gltfPrimitive.attributes[0].count;
}
},
/**
* Gets the number of triangles in the tile. Currently this is always zero because Gaussian splats are not represented as triangles in the tile content.
*
* @memberof GaussianSplat3DTileContent.prototype
*
* @type {number}
* @readonly
*/
trianglesLength: {
get: function() {
return 0;
}
},
/**
* The number of bytes used by the geometry attributes of this content.
*
* @memberof GaussianSplat3DTileContent.prototype
* @type {number}
* @readonly
*/
geometryByteLength: {
get: function() {
return this.gltfPrimitive.attributes.reduce((totalLength, attribute) => {
return totalLength + attribute.byteLength;
}, 0);
}
},
/**
* The number of bytes used by the textures of this content.
*
* @memberof GaussianSplat3DTileContent.prototype
* @type {number}
* @readonly
*/
texturesByteLength: {
get: function() {
const texture = this._tileset.gaussianSplatPrimitive.gaussianSplatTexture;
const selectedTileLength = this._tileset.gaussianSplatPrimitive.selectedTileLength;
if (!defined_default(texture) || selectedTileLength === 0) {
return 0;
}
return texture.sizeInBytes / selectedTileLength;
}
},
/**
* Gets the amount of memory used by the batch table textures and any binary
* metadata properties not accounted for in geometryByteLength or
* texturesByteLength
*
* @memberof GaussianSplat3DTileContent.prototype
*
* @type {number}
* @readonly
*/
batchTableByteLength: {
// eslint-disable-next-line getter-return
get: function() {
return 0;
}
},
/**
* Gets the array of {@link Cesium3DTileContent} objects for contents that contain other contents, such as composite tiles. The inner contents may in turn have inner contents, such as a composite tile that contains a composite tile.
*
* @see {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification/TileFormats/Composite|Composite specification}
*
* @memberof GaussianSplat3DTileContent.prototype
*
* @type {Array}
* @readonly
*/
innerContents: {
get: function() {
return void 0;
}
},
/**
* Returns true when the tile's content is ready to render; otherwise false
*
* @memberof GaussianSplat3DTileContent.prototype
*
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
},
/**
* Returns true when the tile's content is transformed to world coordinates; otherwise false
*
* @memberof GaussianSplat3DTileContent.prototype
* @type {boolean}
* @readonly
*/
transformed: {
get: function() {
return this._transformed;
}
},
/**
* The tileset that this content belongs to.
*
* @memberof GaussianSplat3DTileContent.prototype
* @type {Cesium3DTileset}
* @readonly
*/
tileset: {
get: function() {
return this._tileset;
}
},
/**
* The tile that this content belongs to.
*
* @memberof GaussianSplat3DTileContent.prototype
* @type {Cesium3DTile}
* @readonly
*/
tile: {
get: function() {
return this._tile;
}
},
/**
* The resource that this content was loaded from.
*
* @memberof GaussianSplat3DTileContent.prototype
* @type {Resource}
* @readonly
*/
url: {
get: function() {
return this._resource.getUrlComponent(true);
}
},
/**
* Gets the batch table for this content.
*
* This is used to implement the Cesium3DTileContent interface, but is
* not part of the public Cesium API.
*
*
* @type {Cesium3DTileBatchTable}
* @readonly
*
* @private
*/
batchTable: {
get: function() {
return void 0;
}
},
/**
* Gets the metadata for this content, whether it is available explicitly or via
* implicit tiling. If there is no metadata, this property should be undefined.
*
* This is used to implement the Cesium3DTileContent interface, but is
* not part of the public Cesium API.
*
*
* @type {ImplicitMetadataView|undefined}
*
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
metadata: {
get: function() {
return this._metadata;
},
set: function(value) {
this._metadata = value;
}
},
/**
* Gets the group for this content if the content has metadata (3D Tiles 1.1) or
* if it uses the 3DTILES_metadata extension. If neither are present,
* this property should be undefined.
*
* This is used to implement the Cesium3DTileContent interface, but is
* not part of the public Cesium API.
*
*
* @type {Cesium3DTileContentGroup|undefined}
*
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
group: {
get: function() {
return this._group;
},
set: function(value) {
this._group = value;
}
},
/**
* The number of spherical harmonic coefficients used for the Gaussian splats.
* @type {number}
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
sphericalHarmonicsCoefficientCount: {
get: function() {
return this._sphericalHarmonicsCoefficientCount;
}
},
/**
* The degree of the spherical harmonics used for the Gaussian splats.
* @type {number}
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
sphericalHarmonicsDegree: {
get: function() {
return this._sphericalHarmonicsDegree;
}
},
/**
* The packed spherical harmonic data for the Gaussian splats for use a shader or texture.
* @type {number}
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
packedSphericalHarmonicsData: {
get: function() {
return this._packedSphericalHarmonicsData;
}
}
});
function getShAttributePrefix2(attribute) {
const prefix = attribute.startsWith("KHR_gaussian_splatting:") ? "KHR_gaussian_splatting:" : "_";
return `${prefix}SH_DEGREE_`;
}
function degreeAndCoefFromAttributes(attributes) {
const shAttributes = attributes.filter(
(attr) => attr.name.includes("SH_DEGREE_")
);
switch (shAttributes.length) {
default:
case 0:
return { l: 0, n: 0 };
case 3:
return { l: 1, n: 9 };
case 8:
return { l: 2, n: 24 };
case 15:
return { l: 3, n: 45 };
}
}
var buffer = new ArrayBuffer(4);
var floatView = new Float32Array(buffer);
var intView = new Uint32Array(buffer);
function float32ToFloat16(float32) {
floatView[0] = float32;
const bits = intView[0];
const sign3 = bits >> 31 & 1;
const exponent = bits >> 23 & 255;
const mantissa = bits & 8388607;
let half;
if (exponent === 255) {
half = sign3 << 15 | 31 << 10 | (mantissa ? 512 : 0);
} else if (exponent === 0) {
half = sign3 << 15;
} else {
const newExponent = exponent - 127 + 15;
if (newExponent >= 31) {
half = sign3 << 15 | 31 << 10;
} else if (newExponent <= 0) {
half = sign3 << 15;
} else {
half = sign3 << 15 | newExponent << 10 | mantissa >>> 13;
}
}
return half;
}
function extractSHDegreeAndCoef2(attribute) {
const prefix = getShAttributePrefix2(attribute);
const separator = "_COEF_";
const lStart = prefix.length;
const coefIndex = attribute.indexOf(separator, lStart);
const l = parseInt(attribute.slice(lStart, coefIndex), 10);
const n = parseInt(attribute.slice(coefIndex + separator.length), 10);
return { l, n };
}
function packSphericalHarmonicsData(tileContent) {
const degree = tileContent.sphericalHarmonicsDegree;
const coefs = tileContent.sphericalHarmonicsCoefficientCount;
const totalLength = tileContent.pointsLength * (coefs * (2 / 3));
const packedData = new Uint32Array(totalLength);
const shAttributes = tileContent.gltfPrimitive.attributes.filter(
(attr) => attr.name.includes("SH_DEGREE_")
);
let stride = 0;
const base = [0, 9, 24];
switch (degree) {
case 1:
stride = 9;
break;
case 2:
stride = 24;
break;
case 3:
stride = 45;
break;
}
shAttributes.sort((a3, b) => {
if (a3.name < b.name) {
return -1;
}
if (a3.name > b.name) {
return 1;
}
return 0;
});
const packedStride = stride * (2 / 3);
for (let i = 0; i < shAttributes.length; i++) {
const { l, n } = extractSHDegreeAndCoef2(shAttributes[i].name);
for (let j = 0; j < tileContent.pointsLength; j++) {
const packedBase = base[l - 1] * 2 / 3;
const idx = j * packedStride + packedBase + n * 2;
const src = j * 3;
packedData[idx] = float32ToFloat16(shAttributes[i].typedArray[src]) | float32ToFloat16(shAttributes[i].typedArray[src + 1]) << 16;
packedData[idx + 1] = float32ToFloat16(
shAttributes[i].typedArray[src + 2]
);
}
}
return packedData;
}
GaussianSplat3DTileContent.fromGltf = async function(tileset, tile, resource, gltf) {
const basePath = resource;
const baseResource2 = Resource_default.createIfNeeded(basePath);
const loaderOptions = {
releaseGltfJson: false,
upAxis: Axis_default.Y,
forwardAxis: Axis_default.Z
};
if (defined_default(gltf.asset)) {
loaderOptions.gltfJson = gltf;
loaderOptions.baseResource = baseResource2;
loaderOptions.gltfResource = baseResource2;
} else if (gltf instanceof Uint8Array) {
loaderOptions.typedArray = gltf;
loaderOptions.baseResource = baseResource2;
loaderOptions.gltfResource = baseResource2;
} else {
loaderOptions.gltfResource = Resource_default.createIfNeeded(gltf);
}
const loader = new GltfLoader_default(loaderOptions);
try {
await loader.load();
} catch (error) {
loader.destroy();
throw new RuntimeError_default(`Failed to load glTF: ${error.message}`);
}
return new GaussianSplat3DTileContent(loader, tileset, tile, resource);
};
GaussianSplat3DTileContent.prototype.update = function(primitive, frameState) {
const loader = this._loader;
if (this._ready) {
if (!this._transformed && primitive.root.content.ready) {
GaussianSplatPrimitive_default.transformTile(this._tile);
this._transformed = true;
}
return;
}
frameState.afterRender.push(() => true);
if (!defined_default(loader)) {
this._ready = true;
return;
}
if (this._resourcesLoaded) {
this.gltfPrimitive = loader.components.scene.nodes[0].primitives[0];
this.worldTransform = loader.components.scene.nodes[0].matrix;
this._ready = true;
this._originalPositions = new Float32Array(
ModelUtility_default.getAttributeBySemantic(
this.gltfPrimitive,
VertexAttributeSemantic_default.POSITION
).typedArray
);
this._originalRotations = new Float32Array(
ModelUtility_default.getAttributeBySemantic(
this.gltfPrimitive,
VertexAttributeSemantic_default.ROTATION
).typedArray
);
this._originalScales = new Float32Array(
ModelUtility_default.getAttributeBySemantic(
this.gltfPrimitive,
VertexAttributeSemantic_default.SCALE
).typedArray
);
const { l, n } = degreeAndCoefFromAttributes(this.gltfPrimitive.attributes);
this._sphericalHarmonicsDegree = l;
this._sphericalHarmonicsCoefficientCount = n;
this._packedSphericalHarmonicsData = packSphericalHarmonicsData(this);
return;
}
this._resourcesLoaded = loader.process(frameState);
};
GaussianSplat3DTileContent.prototype.hasProperty = function(batchId, name) {
return false;
};
GaussianSplat3DTileContent.prototype.getFeature = function(batchId) {
return void 0;
};
GaussianSplat3DTileContent.prototype.applyDebugSettings = function(enabled, color) {
};
GaussianSplat3DTileContent.prototype.applyStyle = function(style) {
};
GaussianSplat3DTileContent.prototype.pick = function(ray, frameState, result) {
return void 0;
};
GaussianSplat3DTileContent.prototype.isDestroyed = function() {
return this.isDestroyed;
};
GaussianSplat3DTileContent.prototype.destroy = function() {
this.splatPrimitive = void 0;
if (defined_default(this._tileset.gaussianSplatPrimitive) && !this._tileset.gaussianSplatPrimitive.isDestroyed()) {
this._tileset.gaussianSplatPrimitive.destroy();
}
this._tileset.gaussianSplatPrimitive = void 0;
this._tile = void 0;
this._tileset = void 0;
this._resource = void 0;
this._ready = false;
this._group = void 0;
this._metadata = void 0;
this._resourcesLoaded = false;
if (defined_default(this._loader)) {
this._loader.destroy();
this._loader = void 0;
}
return destroyObject_default(this);
};
var GaussianSplat3DTileContent_default = GaussianSplat3DTileContent;
// packages/engine/Source/Scene/Cesium3DTileContentFactory.js
var Cesium3DTileContentFactory = {
b3dm: function(tileset, tile, resource, arrayBuffer, byteOffset) {
return Model3DTileContent_default.fromB3dm(
tileset,
tile,
resource,
arrayBuffer,
byteOffset
);
},
pnts: function(tileset, tile, resource, arrayBuffer, byteOffset) {
return Model3DTileContent_default.fromPnts(
tileset,
tile,
resource,
arrayBuffer,
byteOffset
);
},
i3dm: function(tileset, tile, resource, arrayBuffer, byteOffset) {
return Model3DTileContent_default.fromI3dm(
tileset,
tile,
resource,
arrayBuffer,
byteOffset
);
},
cmpt: function(tileset, tile, resource, arrayBuffer, byteOffset) {
return Composite3DTileContent_default.fromTileType(
tileset,
tile,
resource,
arrayBuffer,
byteOffset,
Cesium3DTileContentFactory
);
},
externalTileset: function(tileset, tile, resource, json) {
return Tileset3DTileContent_default.fromJson(tileset, tile, resource, json);
},
geom: function(tileset, tile, resource, arrayBuffer, byteOffset) {
return new Geometry3DTileContent_default(
tileset,
tile,
resource,
arrayBuffer,
byteOffset
);
},
vctr: function(tileset, tile, resource, arrayBuffer, byteOffset) {
return new Vector3DTileContent_default(
tileset,
tile,
resource,
arrayBuffer,
byteOffset
);
},
subt: function(tileset, tile, resource, arrayBuffer, byteOffset) {
return Implicit3DTileContent_default.fromSubtreeJson(
tileset,
tile,
resource,
void 0,
arrayBuffer,
byteOffset
);
},
subtreeJson: function(tileset, tile, resource, json) {
return Implicit3DTileContent_default.fromSubtreeJson(tileset, tile, resource, json);
},
glb: function(tileset, tile, resource, arrayBuffer, byteOffset) {
const arrayBufferByteLength = arrayBuffer.byteLength;
if (arrayBufferByteLength < 12) {
throw new RuntimeError_default("Invalid glb content");
}
const dataView = new DataView(arrayBuffer, byteOffset);
const byteLength = dataView.getUint32(8, true);
const glb = new Uint8Array(arrayBuffer, byteOffset, byteLength);
if (GaussianSplat3DTileContent_default.tilesetRequiresGaussianSplattingExt(tileset)) {
return GaussianSplat3DTileContent_default.fromGltf(tileset, tile, resource, glb);
}
return Model3DTileContent_default.fromGltf(tileset, tile, resource, glb);
},
gltf: function(tileset, tile, resource, json) {
if (GaussianSplat3DTileContent_default.tilesetRequiresGaussianSplattingExt(tileset)) {
return GaussianSplat3DTileContent_default.fromGltf(tileset, tile, resource, json);
}
return Model3DTileContent_default.fromGltf(tileset, tile, resource, json);
},
geoJson: function(tileset, tile, resource, json) {
return Model3DTileContent_default.fromGeoJson(tileset, tile, resource, json);
}
};
var Cesium3DTileContentFactory_default = Cesium3DTileContentFactory;
// packages/engine/Source/Scene/Cesium3DTileContentState.js
var import_InlineWorkers774 = __toESM(require_InlineWorkers(), 1);
var Cesium3DTileContentState = {
UNLOADED: 0,
// Has never been requested
LOADING: 1,
// Is waiting on a pending request
PROCESSING: 2,
// Request received. Contents are being processed for rendering. Depending on the content, it might make its own requests for external data.
READY: 3,
// Ready to render.
EXPIRED: 4,
// Is expired and will be unloaded once new content is loaded.
FAILED: 5
// Request failed.
};
var Cesium3DTileContentState_default = Object.freeze(Cesium3DTileContentState);
// packages/engine/Source/Scene/Cesium3DTileContentType.js
var import_InlineWorkers775 = __toESM(require_InlineWorkers(), 1);
var Cesium3DTileContentType = {
/**
* A Batched 3D Model. This is a binary format with
* magic number b3dm
*
* @type {string}
* @constant
* @private
*/
BATCHED_3D_MODEL: "b3dm",
/**
* An Instanced 3D Model. This is a binary format with magic number
* i3dm
*
* @type {string}
* @constant
* @private
*/
INSTANCED_3D_MODEL: "i3dm",
/**
* A Composite model. This is a binary format with magic number
* cmpt
*
* @type {string}
* @constant
* @private
*/
COMPOSITE: "cmpt",
/**
* A Point Cloud model. This is a binary format with magic number
* pnts
*
* @type {string}
* @constant
* @private
*/
POINT_CLOUD: "pnts",
/**
* Vector tiles. This is a binary format with magic number
* vctr
*
* @type {string}
* @constant
* @private
*/
VECTOR: "vctr",
/**
* Geometry tiles. This is a binary format with magic number
* geom
*
* @type {string}
* @constant
* @private
*/
GEOMETRY: "geom",
/**
* A glTF model in JSON + external BIN form. This is treated
* as a JSON format.
*
* @type {string}
* @constant
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
GLTF: "gltf",
/**
* The binary form of a glTF file. Internally, the magic number is
* changed from glTF to glb to distinguish it from
* the JSON glTF format.
*
* @type {string}
* @constant
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
GLTF_BINARY: "glb",
/**
* For implicit tiling, availability bitstreams are stored in binary subtree files.
* The magic number is subt
*
* @type {string}
* @constant
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
IMPLICIT_SUBTREE: "subt",
/**
* For implicit tiling. Subtrees can also be represented as JSON files.
*
* @type {string}
* @constant
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
IMPLICIT_SUBTREE_JSON: "subtreeJson",
/**
* Contents can reference another tileset.json to use
* as an external tileset. This is a JSON-based format.
*
* @type {string}
* @constant
* @private
*/
EXTERNAL_TILESET: "externalTileset",
/**
* Multiple contents are handled separately from the other content types
* due to differences in request scheduling.
*
* @type {string}
* @constant
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
MULTIPLE_CONTENT: "multipleContent",
/**
* GeoJSON content for MAXAR_content_geojson extension.
*
* @type {string}
* @constant
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
GEOJSON: "geoJson",
/**
* Binary voxel content for 3DTILES_content_voxels extension.
*
* @type {string}
* @constant
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
VOXEL_BINARY: "voxl",
/**
* Binary voxel content for 3DTILES_content_voxels extension.
*
* @type {string}
* @constant
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
VOXEL_JSON: "voxelJson"
};
Cesium3DTileContentType.isBinaryFormat = function(contentType) {
switch (contentType) {
case Cesium3DTileContentType.BATCHED_3D_MODEL:
case Cesium3DTileContentType.INSTANCED_3D_MODEL:
case Cesium3DTileContentType.COMPOSITE:
case Cesium3DTileContentType.POINT_CLOUD:
case Cesium3DTileContentType.VECTOR:
case Cesium3DTileContentType.GEOMETRY:
case Cesium3DTileContentType.IMPLICIT_SUBTREE:
case Cesium3DTileContentType.VOXEL_BINARY:
case Cesium3DTileContentType.GLTF_BINARY:
return true;
default:
return false;
}
};
var Cesium3DTileContentType_default = Object.freeze(Cesium3DTileContentType);
// packages/engine/Source/Scene/Cesium3DTileOptimizationHint.js
var import_InlineWorkers776 = __toESM(require_InlineWorkers(), 1);
var Cesium3DTileOptimizationHint = {
NOT_COMPUTED: -1,
USE_OPTIMIZATION: 1,
SKIP_OPTIMIZATION: 0
};
var Cesium3DTileOptimizationHint_default = Object.freeze(Cesium3DTileOptimizationHint);
// packages/engine/Source/Scene/Cesium3DTilePass.js
var import_InlineWorkers777 = __toESM(require_InlineWorkers(), 1);
var Cesium3DTilePass = {
RENDER: 0,
PICK: 1,
SHADOW: 2,
PRELOAD: 3,
PRELOAD_FLIGHT: 4,
REQUEST_RENDER_MODE_DEFER_CHECK: 5,
MOST_DETAILED_PRELOAD: 6,
MOST_DETAILED_PICK: 7,
NUMBER_OF_PASSES: 8
};
var passOptions = new Array(Cesium3DTilePass.NUMBER_OF_PASSES);
passOptions[Cesium3DTilePass.RENDER] = Object.freeze({
pass: Cesium3DTilePass.RENDER,
isRender: true,
requestTiles: true,
ignoreCommands: false
});
passOptions[Cesium3DTilePass.PICK] = Object.freeze({
pass: Cesium3DTilePass.PICK,
isRender: false,
requestTiles: false,
ignoreCommands: false
});
passOptions[Cesium3DTilePass.SHADOW] = Object.freeze({
pass: Cesium3DTilePass.SHADOW,
isRender: false,
requestTiles: true,
ignoreCommands: false
});
passOptions[Cesium3DTilePass.PRELOAD] = Object.freeze({
pass: Cesium3DTilePass.PRELOAD,
isRender: false,
requestTiles: true,
ignoreCommands: true
});
passOptions[Cesium3DTilePass.PRELOAD_FLIGHT] = Object.freeze({
pass: Cesium3DTilePass.PRELOAD_FLIGHT,
isRender: false,
requestTiles: true,
ignoreCommands: true
});
passOptions[Cesium3DTilePass.REQUEST_RENDER_MODE_DEFER_CHECK] = Object.freeze({
pass: Cesium3DTilePass.REQUEST_RENDER_MODE_DEFER_CHECK,
isRender: false,
requestTiles: true,
ignoreCommands: true
});
passOptions[Cesium3DTilePass.MOST_DETAILED_PRELOAD] = Object.freeze({
pass: Cesium3DTilePass.MOST_DETAILED_PRELOAD,
isRender: false,
requestTiles: true,
ignoreCommands: true
});
passOptions[Cesium3DTilePass.MOST_DETAILED_PICK] = Object.freeze({
pass: Cesium3DTilePass.MOST_DETAILED_PICK,
isRender: false,
requestTiles: false,
ignoreCommands: false
});
Cesium3DTilePass.getPassOptions = function(pass) {
return passOptions[pass];
};
var Cesium3DTilePass_default = Object.freeze(Cesium3DTilePass);
// packages/engine/Source/Scene/Empty3DTileContent.js
var import_InlineWorkers778 = __toESM(require_InlineWorkers(), 1);
function Empty3DTileContent(tileset, tile) {
this._tileset = tileset;
this._tile = tile;
this.featurePropertiesDirty = false;
}
Object.defineProperties(Empty3DTileContent.prototype, {
featuresLength: {
get: function() {
return 0;
}
},
pointsLength: {
get: function() {
return 0;
}
},
trianglesLength: {
get: function() {
return 0;
}
},
geometryByteLength: {
get: function() {
return 0;
}
},
texturesByteLength: {
get: function() {
return 0;
}
},
batchTableByteLength: {
get: function() {
return 0;
}
},
innerContents: {
get: function() {
return void 0;
}
},
/**
* Returns true when the tile's content is ready to render; otherwise false
*
* @memberof Empty3DTileContent.prototype
*
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
return true;
}
},
tileset: {
get: function() {
return this._tileset;
}
},
tile: {
get: function() {
return this._tile;
}
},
url: {
get: function() {
return void 0;
}
},
metadata: {
get: function() {
return void 0;
},
set: function(value) {
throw new DeveloperError_default(
"Empty3DTileContent cannot have content metadata"
);
}
},
batchTable: {
get: function() {
return void 0;
}
},
group: {
get: function() {
return void 0;
},
set: function(value) {
throw new DeveloperError_default("Empty3DTileContent cannot have group metadata");
}
}
});
Empty3DTileContent.prototype.hasProperty = function(batchId, name) {
return false;
};
Empty3DTileContent.prototype.getFeature = function(batchId) {
return void 0;
};
Empty3DTileContent.prototype.applyDebugSettings = function(enabled, color) {
};
Empty3DTileContent.prototype.applyStyle = function(style) {
};
Empty3DTileContent.prototype.update = function(tileset, frameState) {
};
Empty3DTileContent.prototype.pick = function(ray, frameState, result) {
return void 0;
};
Empty3DTileContent.prototype.isDestroyed = function() {
return false;
};
Empty3DTileContent.prototype.destroy = function() {
return destroyObject_default(this);
};
var Empty3DTileContent_default = Empty3DTileContent;
// packages/engine/Source/Scene/findContentMetadata.js
var import_InlineWorkers780 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/ContentMetadata.js
var import_InlineWorkers779 = __toESM(require_InlineWorkers(), 1);
function ContentMetadata(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const content = options.content;
const metadataClass = options.class;
Check_default.typeOf.object("options.content", content);
Check_default.typeOf.object("options.class", metadataClass);
this._class = metadataClass;
this._properties = content.properties;
this._extensions = content.extensions;
this._extras = content.extras;
}
Object.defineProperties(ContentMetadata.prototype, {
/**
* The class that properties conform to.
*
* @memberof ContentMetadata.prototype
* @type {MetadataClass}
* @readonly
* @private
*/
class: {
get: function() {
return this._class;
}
},
/**
* Extra user-defined properties.
*
* @memberof ContentMetadata.prototype
* @type {object}
* @readonly
* @private
*/
extras: {
get: function() {
return this._extras;
}
},
/**
* An object containing extensions.
*
* @memberof ContentMetadata.prototype
* @type {object}
* @readonly
* @private
*/
extensions: {
get: function() {
return this._extensions;
}
}
});
ContentMetadata.prototype.hasProperty = function(propertyId) {
return MetadataEntity_default.hasProperty(propertyId, this._properties, this._class);
};
ContentMetadata.prototype.hasPropertyBySemantic = function(semantic) {
return MetadataEntity_default.hasPropertyBySemantic(
semantic,
this._properties,
this._class
);
};
ContentMetadata.prototype.getPropertyIds = function(results) {
return MetadataEntity_default.getPropertyIds(this._properties, this._class, results);
};
ContentMetadata.prototype.getProperty = function(propertyId) {
return MetadataEntity_default.getProperty(propertyId, this._properties, this._class);
};
ContentMetadata.prototype.setProperty = function(propertyId, value) {
return MetadataEntity_default.setProperty(
propertyId,
value,
this._properties,
this._class
);
};
ContentMetadata.prototype.getPropertyBySemantic = function(semantic) {
return MetadataEntity_default.getPropertyBySemantic(
semantic,
this._properties,
this._class
);
};
ContentMetadata.prototype.setPropertyBySemantic = function(semantic, value) {
return MetadataEntity_default.setPropertyBySemantic(
semantic,
value,
this._properties,
this._class
);
};
var ContentMetadata_default = ContentMetadata;
// packages/engine/Source/Scene/findContentMetadata.js
function findContentMetadata(tileset, contentHeader) {
const metadataJson = hasExtension_default(contentHeader, "3DTILES_metadata") ? contentHeader.extensions["3DTILES_metadata"] : contentHeader.metadata;
if (!defined_default(metadataJson)) {
return void 0;
}
if (!defined_default(tileset.schema)) {
findContentMetadata._oneTimeWarning(
"findContentMetadata-missing-root-schema",
"Could not find a metadata schema for content metadata. For tilesets that contain external tilesets, make sure the schema is added to the root tileset.json."
);
return void 0;
}
const classes = tileset.schema.classes ?? Frozen_default.EMPTY_OBJECT;
if (defined_default(metadataJson.class)) {
const contentClass = classes[metadataJson.class];
return new ContentMetadata_default({
content: metadataJson,
class: contentClass
});
}
return void 0;
}
findContentMetadata._oneTimeWarning = oneTimeWarning_default;
var findContentMetadata_default = findContentMetadata;
// packages/engine/Source/Scene/findGroupMetadata.js
var import_InlineWorkers781 = __toESM(require_InlineWorkers(), 1);
function findGroupMetadata(tileset, contentHeader) {
const metadataExtension = tileset.metadataExtension;
if (!defined_default(metadataExtension)) {
return void 0;
}
const groups = metadataExtension.groups;
const group = hasExtension_default(contentHeader, "3DTILES_metadata") ? contentHeader.extensions["3DTILES_metadata"].group : contentHeader.group;
if (typeof group === "number") {
return groups[group];
}
const index = metadataExtension.groupIds.findIndex(function(id) {
return id === group;
});
return index >= 0 ? groups[index] : void 0;
}
var findGroupMetadata_default = findGroupMetadata;
// packages/engine/Source/Scene/findTileMetadata.js
var import_InlineWorkers783 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/TileMetadata.js
var import_InlineWorkers782 = __toESM(require_InlineWorkers(), 1);
function TileMetadata(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const tile = options.tile;
const metadataClass = options.class;
Check_default.typeOf.object("options.tile", tile);
Check_default.typeOf.object("options.class", metadataClass);
this._class = metadataClass;
this._properties = tile.properties;
this._extensions = tile.extensions;
this._extras = tile.extras;
}
Object.defineProperties(TileMetadata.prototype, {
/**
* The class that properties conform to.
*
* @memberof TileMetadata.prototype
* @type {MetadataClass}
* @readonly
* @private
*/
class: {
get: function() {
return this._class;
}
},
/**
* Extra user-defined properties.
*
* @memberof TileMetadata.prototype
* @type {object}
* @readonly
* @private
*/
extras: {
get: function() {
return this._extras;
}
},
/**
* An object containing extensions.
*
* @memberof TileMetadata.prototype
* @type {object}
* @readonly
* @private
*/
extensions: {
get: function() {
return this._extensions;
}
}
});
TileMetadata.prototype.hasProperty = function(propertyId) {
return MetadataEntity_default.hasProperty(propertyId, this._properties, this._class);
};
TileMetadata.prototype.hasPropertyBySemantic = function(semantic) {
return MetadataEntity_default.hasPropertyBySemantic(
semantic,
this._properties,
this._class
);
};
TileMetadata.prototype.getPropertyIds = function(results) {
return MetadataEntity_default.getPropertyIds(this._properties, this._class, results);
};
TileMetadata.prototype.getProperty = function(propertyId) {
return MetadataEntity_default.getProperty(propertyId, this._properties, this._class);
};
TileMetadata.prototype.setProperty = function(propertyId, value) {
return MetadataEntity_default.setProperty(
propertyId,
value,
this._properties,
this._class
);
};
TileMetadata.prototype.getPropertyBySemantic = function(semantic) {
return MetadataEntity_default.getPropertyBySemantic(
semantic,
this._properties,
this._class
);
};
TileMetadata.prototype.setPropertyBySemantic = function(semantic, value) {
return MetadataEntity_default.setPropertyBySemantic(
semantic,
value,
this._properties,
this._class
);
};
var TileMetadata_default = TileMetadata;
// packages/engine/Source/Scene/findTileMetadata.js
function findTileMetadata(tileset, tileHeader) {
const metadataJson = hasExtension_default(tileHeader, "3DTILES_metadata") ? tileHeader.extensions["3DTILES_metadata"] : tileHeader.metadata;
if (!defined_default(metadataJson)) {
return void 0;
}
if (!defined_default(tileset.schema)) {
findTileMetadata._oneTimeWarning(
"findTileMetadata-missing-root-schema",
"Could not find a metadata schema for tile metadata. For tilesets that contain external tilesets, make sure the schema is added to the root tileset.json."
);
return void 0;
}
const classes = tileset.schema.classes ?? Frozen_default.EMPTY_OBJECT;
if (defined_default(metadataJson.class)) {
const tileClass = classes[metadataJson.class];
return new TileMetadata_default({
tile: metadataJson,
class: tileClass
});
}
return void 0;
}
findTileMetadata._oneTimeWarning = oneTimeWarning_default;
var findTileMetadata_default = findTileMetadata;
// packages/engine/Source/Scene/Multiple3DTileContent.js
var import_InlineWorkers785 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/preprocess3DTileContent.js
var import_InlineWorkers784 = __toESM(require_InlineWorkers(), 1);
function preprocess3DTileContent(arrayBuffer) {
const uint8Array = new Uint8Array(arrayBuffer);
let contentType = getMagic_default(uint8Array);
if (contentType === "glTF") {
contentType = "glb";
}
if (Cesium3DTileContentType_default.isBinaryFormat(contentType)) {
return {
// For binary files, the enum value is the magic number
contentType,
binaryPayload: uint8Array
};
}
const json = getJsonContent(uint8Array);
if (defined_default(json.root)) {
return {
contentType: Cesium3DTileContentType_default.EXTERNAL_TILESET,
jsonPayload: json
};
}
if (defined_default(json.asset)) {
return {
contentType: Cesium3DTileContentType_default.GLTF,
jsonPayload: json
};
}
if (defined_default(json.tileAvailability)) {
return {
contentType: Cesium3DTileContentType_default.IMPLICIT_SUBTREE_JSON,
jsonPayload: json
};
}
if (defined_default(json.type)) {
return {
contentType: Cesium3DTileContentType_default.GEOJSON,
jsonPayload: json
};
}
if (defined_default(json.voxelTable)) {
return {
contentType: Cesium3DTileContentType_default.VOXEL_JSON,
jsonPayload: json
};
}
throw new RuntimeError_default("Invalid tile content.");
}
function getJsonContent(uint8Array) {
let json;
try {
json = getJsonFromTypedArray_default(uint8Array);
} catch (error) {
throw new RuntimeError_default("Invalid tile content.");
}
return json;
}
var preprocess3DTileContent_default = preprocess3DTileContent;
// packages/engine/Source/Scene/Multiple3DTileContent.js
function Multiple3DTileContent(tileset, tile, tilesetResource, contentsJson) {
this._tileset = tileset;
this._tile = tile;
this._tilesetResource = tilesetResource;
this._contents = [];
this._contentsCreated = false;
const contentHeaders = defined_default(contentsJson.contents) ? contentsJson.contents : contentsJson.content;
this._innerContentHeaders = contentHeaders;
this._requestsInFlight = 0;
this._cancelCount = 0;
this._externalTilesetCount = 0;
const contentCount = this._innerContentHeaders.length;
this._arrayFetchPromises = new Array(contentCount);
this._requests = new Array(contentCount);
this._ready = false;
this._innerContentResources = new Array(contentCount);
this._serverKeys = new Array(contentCount);
for (let i = 0; i < contentCount; i++) {
const contentResource = tilesetResource.getDerivedResource({
url: contentHeaders[i].uri
});
const serverKey = RequestScheduler_default.getServerKey(
contentResource.getUrlComponent()
);
this._innerContentResources[i] = contentResource;
this._serverKeys[i] = serverKey;
}
}
Object.defineProperties(Multiple3DTileContent.prototype, {
/**
* Part of the {@link Cesium3DTileContent} interface. Multiple3DTileContent checks if any of the inner contents have dirty featurePropertiesDirty.
* @memberof Multiple3DTileContent.prototype
*
* @type {boolean}
*
* @private
*/
featurePropertiesDirty: {
get: function() {
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
if (contents[i].featurePropertiesDirty) {
return true;
}
}
return false;
},
set: function(value) {
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
contents[i].featurePropertiesDirty = value;
}
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Multiple3DTileContent
* always returns 0. Instead call featuresLength for a specific inner content.
*
* @memberof Multiple3DTileContent.prototype
*
* @type {number}
* @readonly
*
* @private
*/
featuresLength: {
get: function() {
return 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Multiple3DTileContent
* always returns 0. Instead, call pointsLength for a specific inner content.
*
* @memberof Multiple3DTileContent.prototype
*
* @type {number}
* @readonly
*
* @private
*/
pointsLength: {
get: function() {
return 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Multiple3DTileContent
* always returns 0. Instead call trianglesLength for a specific inner content.
*
* @memberof Multiple3DTileContent.prototype
*
* @type {number}
* @readonly
*
* @private
*/
trianglesLength: {
get: function() {
return 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Multiple3DTileContent
* always returns 0. Instead call geometryByteLength for a specific inner content.
*
* @memberof Multiple3DTileContent.prototype
*
* @type {number}
* @readonly
*
* @private
*/
geometryByteLength: {
get: function() {
return 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Multiple3DTileContent
* always returns 0. Instead call texturesByteLength for a specific inner content.
*
* @memberof Multiple3DTileContent.prototype
*
* @type {number}
* @readonly
*
* @private
*/
texturesByteLength: {
get: function() {
return 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Multiple3DTileContent
* always returns 0. Instead call batchTableByteLength for a specific inner content.
*
* @memberof Multiple3DTileContent.prototype
*
* @type {number}
* @readonly
*
* @private
*/
batchTableByteLength: {
get: function() {
return 0;
}
},
innerContents: {
get: function() {
return this._contents;
}
},
/**
* Returns true when the tile's content is ready to render; otherwise false
*
* @memberof Multiple3DTileContent.prototype
*
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
if (!this._contentsCreated) {
return false;
}
return this._ready;
}
},
tileset: {
get: function() {
return this._tileset;
}
},
tile: {
get: function() {
return this._tile;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface.
* Unlike other content types, Multiple3DTileContent does not
* have a single URL, so this returns undefined.
* @memberof Multiple3DTileContent.prototype
*
* @type {string}
* @readonly
* @private
*/
url: {
get: function() {
return void 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Multiple3DTileContent
* always returns undefined. Instead call metadata for a specific inner content.
* @memberof Multiple3DTileContent.prototype
* @private
*/
metadata: {
get: function() {
return void 0;
},
set: function() {
throw new DeveloperError_default("Multiple3DTileContent cannot have metadata");
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Multiple3DTileContent
* always returns undefined. Instead call batchTable for a specific inner content.
* @memberof Multiple3DTileContent.prototype
* @private
*/
batchTable: {
get: function() {
return void 0;
}
},
/**
* Part of the {@link Cesium3DTileContent} interface. Multiple3DTileContent
* always returns undefined. Instead call group for a specific inner content.
* @memberof Multiple3DTileContent.prototype
* @private
*/
group: {
get: function() {
return void 0;
},
set: function() {
throw new DeveloperError_default(
"Multiple3DTileContent cannot have group metadata"
);
}
},
/**
* Get an array of the inner content URLs, regardless of whether they've
* been fetched or not. This is intended for use with
* {@link Cesium3DTileset#debugShowUrl}.
* @memberof Multiple3DTileContent.prototype
*
* @type {string[]}
* @readonly
* @private
*/
innerContentUrls: {
get: function() {
return this._innerContentHeaders.map(function(contentHeader) {
return contentHeader.uri;
});
}
}
});
function updatePendingRequests(multipleContents, deltaRequestCount) {
multipleContents._requestsInFlight += deltaRequestCount;
multipleContents.tileset.statistics.numberOfPendingRequests += deltaRequestCount;
}
function cancelPendingRequests(multipleContents, originalContentState) {
multipleContents._cancelCount++;
multipleContents._tile._contentState = originalContentState;
const statistics2 = multipleContents.tileset.statistics;
statistics2.numberOfPendingRequests -= multipleContents._requestsInFlight;
statistics2.numberOfAttemptedRequests += multipleContents._requestsInFlight;
multipleContents._requestsInFlight = 0;
const contentCount = multipleContents._innerContentHeaders.length;
multipleContents._arrayFetchPromises = new Array(contentCount);
}
Multiple3DTileContent.prototype.requestInnerContents = function() {
if (!canScheduleAllRequests(this._serverKeys)) {
this.tileset.statistics.numberOfAttemptedRequests += this._serverKeys.length;
return;
}
const contentHeaders = this._innerContentHeaders;
updatePendingRequests(this, contentHeaders.length);
const originalCancelCount = this._cancelCount;
for (let i = 0; i < contentHeaders.length; i++) {
this._arrayFetchPromises[i] = requestInnerContent(
this,
i,
originalCancelCount,
this._tile._contentState
);
}
return createInnerContents(this);
};
function canScheduleAllRequests(serverKeys) {
const requestCountsByServer = {};
for (let i = 0; i < serverKeys.length; i++) {
const serverKey = serverKeys[i];
if (defined_default(requestCountsByServer[serverKey])) {
requestCountsByServer[serverKey]++;
} else {
requestCountsByServer[serverKey] = 1;
}
}
for (const key in requestCountsByServer) {
if (requestCountsByServer.hasOwnProperty(key) && !RequestScheduler_default.serverHasOpenSlots(key, requestCountsByServer[key])) {
return false;
}
}
return RequestScheduler_default.heapHasOpenSlots(serverKeys.length);
}
function requestInnerContent(multipleContents, index, originalCancelCount, originalContentState) {
const contentResource = multipleContents._innerContentResources[index].clone();
const tile = multipleContents.tile;
const priorityFunction = function() {
return tile._priority;
};
const serverKey = multipleContents._serverKeys[index];
const request = new Request_default({
throttle: true,
throttleByServer: true,
type: RequestType_default.TILES3D,
priorityFunction,
serverKey
});
contentResource.request = request;
multipleContents._requests[index] = request;
const promise = contentResource.fetchArrayBuffer();
if (!defined_default(promise)) {
return;
}
return promise.then(function(arrayBuffer) {
if (originalCancelCount < multipleContents._cancelCount) {
return;
}
if (contentResource.request.cancelled || contentResource.request.state === RequestState_default.CANCELLED) {
cancelPendingRequests(multipleContents, originalContentState);
return;
}
updatePendingRequests(multipleContents, -1);
return arrayBuffer;
}).catch(function(error) {
if (originalCancelCount < multipleContents._cancelCount) {
return;
}
if (contentResource.request.cancelled || contentResource.request.state === RequestState_default.CANCELLED) {
cancelPendingRequests(multipleContents, originalContentState);
return;
}
updatePendingRequests(multipleContents, -1);
handleInnerContentFailed(multipleContents, index, error);
});
}
async function createInnerContents(multipleContents) {
const originalCancelCount = multipleContents._cancelCount;
const arrayBuffers = await Promise.all(multipleContents._arrayFetchPromises);
if (originalCancelCount < multipleContents._cancelCount) {
return;
}
const promises = arrayBuffers.map(
(arrayBuffer, i) => createInnerContent(multipleContents, arrayBuffer, i)
);
const contents = await Promise.all(promises);
multipleContents._contentsCreated = true;
multipleContents._contents = contents.filter(defined_default);
if (multipleContents._externalTilesetCount === multipleContents._contents.length) {
const tile = multipleContents._tile;
tile.hasRenderableContent = false;
}
return contents;
}
async function createInnerContent(multipleContents, arrayBuffer, index) {
if (!defined_default(arrayBuffer)) {
return;
}
try {
const preprocessed = preprocess3DTileContent_default(arrayBuffer);
const tileset = multipleContents._tileset;
const resource = multipleContents._innerContentResources[index];
const tile = multipleContents._tile;
if (preprocessed.contentType === Cesium3DTileContentType_default.EXTERNAL_TILESET) {
multipleContents._externalTilesetCount++;
tile.hasTilesetContent = true;
}
multipleContents._disableSkipLevelOfDetail = multipleContents._disableSkipLevelOfDetail || preprocessed.contentType === Cesium3DTileContentType_default.GEOMETRY || preprocessed.contentType === Cesium3DTileContentType_default.VECTOR;
let content;
const contentFactory = Cesium3DTileContentFactory_default[preprocessed.contentType];
if (defined_default(preprocessed.binaryPayload)) {
content = await Promise.resolve(
contentFactory(
tileset,
tile,
resource,
preprocessed.binaryPayload.buffer,
0
)
);
} else {
content = await Promise.resolve(
contentFactory(tileset, tile, resource, preprocessed.jsonPayload)
);
}
const contentHeader = multipleContents._innerContentHeaders[index];
if (tile.hasImplicitContentMetadata) {
const subtree = tile.implicitSubtree;
const coordinates = tile.implicitCoordinates;
content.metadata = subtree.getContentMetadataView(coordinates, index);
} else if (!tile.hasImplicitContent) {
content.metadata = findContentMetadata_default(tileset, contentHeader);
}
const groupMetadata = findGroupMetadata_default(tileset, contentHeader);
if (defined_default(groupMetadata)) {
content.group = new Cesium3DContentGroup_default({
metadata: groupMetadata
});
}
return content;
} catch (error) {
handleInnerContentFailed(multipleContents, index, error);
}
}
function handleInnerContentFailed(multipleContents, index, error) {
const tileset = multipleContents._tileset;
const url2 = multipleContents._innerContentResources[index].url;
const message = defined_default(error.message) ? error.message : error.toString();
if (tileset.tileFailed.numberOfListeners > 0) {
tileset.tileFailed.raiseEvent({
url: url2,
message
});
} else {
console.log(`A content failed to load: ${url2}`);
console.log(`Error: ${message}`);
}
}
Multiple3DTileContent.prototype.cancelRequests = function() {
for (let i = 0; i < this._requests.length; i++) {
const request = this._requests[i];
if (defined_default(request)) {
request.cancel();
}
}
};
Multiple3DTileContent.prototype.hasProperty = function(batchId, name) {
return false;
};
Multiple3DTileContent.prototype.getFeature = function(batchId) {
return void 0;
};
Multiple3DTileContent.prototype.applyDebugSettings = function(enabled, color) {
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
contents[i].applyDebugSettings(enabled, color);
}
};
Multiple3DTileContent.prototype.applyStyle = function(style) {
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
contents[i].applyStyle(style);
}
};
Multiple3DTileContent.prototype.update = function(tileset, frameState) {
const contents = this._contents;
const length2 = contents.length;
let ready = true;
for (let i = 0; i < length2; ++i) {
contents[i].update(tileset, frameState);
ready = ready && contents[i].ready;
}
if (!this._ready && ready) {
this._ready = true;
}
};
Multiple3DTileContent.prototype.pick = function(ray, frameState, result) {
if (!this._ready) {
return void 0;
}
let intersection;
let minDistance = Number.POSITIVE_INFINITY;
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
const candidate = contents[i].pick(ray, frameState, result);
if (!defined_default(candidate)) {
continue;
}
const distance2 = Cartesian3_default.distance(ray.origin, candidate);
if (distance2 < minDistance) {
intersection = candidate;
minDistance = distance2;
}
}
if (!defined_default(intersection)) {
return void 0;
}
return result;
};
Multiple3DTileContent.prototype.isDestroyed = function() {
return false;
};
Multiple3DTileContent.prototype.destroy = function() {
const contents = this._contents;
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
contents[i].destroy();
}
return destroyObject_default(this);
};
var Multiple3DTileContent_default = Multiple3DTileContent;
// packages/engine/Source/Scene/TileBoundingRegion.js
var import_InlineWorkers788 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/RectangleOutlineGeometry.js
var import_InlineWorkers787 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/RectangleGeometryLibrary.js
var import_InlineWorkers786 = __toESM(require_InlineWorkers(), 1);
var cos = Math.cos;
var sin = Math.sin;
var sqrt = Math.sqrt;
var RectangleGeometryLibrary = {};
RectangleGeometryLibrary.computePosition = function(computedOptions, ellipsoid, computeST, row, col, position, st) {
const radiiSquared = ellipsoid.radiiSquared;
const nwCorner = computedOptions.nwCorner;
const rectangle = computedOptions.boundingRectangle;
let stLatitude = nwCorner.latitude - computedOptions.granYCos * row + col * computedOptions.granXSin;
const cosLatitude = cos(stLatitude);
const nZ = sin(stLatitude);
const kZ = radiiSquared.z * nZ;
let stLongitude = nwCorner.longitude + row * computedOptions.granYSin + col * computedOptions.granXCos;
const nX = cosLatitude * cos(stLongitude);
const nY = cosLatitude * sin(stLongitude);
const kX = radiiSquared.x * nX;
const kY = radiiSquared.y * nY;
const gamma = sqrt(kX * nX + kY * nY + kZ * nZ);
position.x = kX / gamma;
position.y = kY / gamma;
position.z = kZ / gamma;
if (computeST) {
const stNwCorner = computedOptions.stNwCorner;
if (defined_default(stNwCorner)) {
stLatitude = stNwCorner.latitude - computedOptions.stGranYCos * row + col * computedOptions.stGranXSin;
stLongitude = stNwCorner.longitude + row * computedOptions.stGranYSin + col * computedOptions.stGranXCos;
st.x = (stLongitude - computedOptions.stWest) * computedOptions.lonScalar;
st.y = (stLatitude - computedOptions.stSouth) * computedOptions.latScalar;
} else {
st.x = (stLongitude - rectangle.west) * computedOptions.lonScalar;
st.y = (stLatitude - rectangle.south) * computedOptions.latScalar;
}
}
};
var rotationMatrixScratch = new Matrix2_default();
var nwCartesian = new Cartesian3_default();
var centerScratch = new Cartographic_default();
var centerCartesian = new Cartesian3_default();
var proj = new GeographicProjection_default();
function getRotationOptions(nwCorner, rotation, granularityX, granularityY, center, width, height) {
const cosRotation = Math.cos(rotation);
const granYCos = granularityY * cosRotation;
const granXCos = granularityX * cosRotation;
const sinRotation = Math.sin(rotation);
const granYSin = granularityY * sinRotation;
const granXSin = granularityX * sinRotation;
proj._ellipsoid = Ellipsoid_default.default;
nwCartesian = proj.project(nwCorner, nwCartesian);
nwCartesian = Cartesian3_default.subtract(nwCartesian, centerCartesian, nwCartesian);
const rotationMatrix = Matrix2_default.fromRotation(rotation, rotationMatrixScratch);
nwCartesian = Matrix2_default.multiplyByVector(
rotationMatrix,
nwCartesian,
nwCartesian
);
nwCartesian = Cartesian3_default.add(nwCartesian, centerCartesian, nwCartesian);
nwCorner = proj.unproject(nwCartesian, nwCorner);
width -= 1;
height -= 1;
const latitude = nwCorner.latitude;
const latitude0 = latitude + width * granXSin;
const latitude1 = latitude - granYCos * height;
const latitude2 = latitude - granYCos * height + width * granXSin;
const north = Math.max(latitude, latitude0, latitude1, latitude2);
const south = Math.min(latitude, latitude0, latitude1, latitude2);
const longitude = nwCorner.longitude;
const longitude0 = longitude + width * granXCos;
const longitude1 = longitude + height * granYSin;
const longitude2 = longitude + height * granYSin + width * granXCos;
const east = Math.max(longitude, longitude0, longitude1, longitude2);
const west = Math.min(longitude, longitude0, longitude1, longitude2);
return {
north,
south,
east,
west,
granYCos,
granYSin,
granXCos,
granXSin,
nwCorner
};
}
RectangleGeometryLibrary.computeOptions = function(rectangle, granularity, rotation, stRotation, boundingRectangleScratch2, nwCornerResult, stNwCornerResult) {
let east = rectangle.east;
let west = rectangle.west;
let north = rectangle.north;
let south = rectangle.south;
let northCap = false;
let southCap = false;
if (north === Math_default.PI_OVER_TWO) {
northCap = true;
}
if (south === -Math_default.PI_OVER_TWO) {
southCap = true;
}
let dx;
const dy = north - south;
if (west > east) {
dx = Math_default.TWO_PI - west + east;
} else {
dx = east - west;
}
const width = Math.ceil(dx / granularity) + 1;
const height = Math.ceil(dy / granularity) + 1;
const granularityX = dx / (width - 1);
const granularityY = dy / (height - 1);
const nwCorner = Rectangle_default.northwest(rectangle, nwCornerResult);
const center = Rectangle_default.center(rectangle, centerScratch);
if (rotation !== 0 || stRotation !== 0) {
if (center.longitude < nwCorner.longitude) {
center.longitude += Math_default.TWO_PI;
}
proj._ellipsoid = Ellipsoid_default.default;
centerCartesian = proj.project(center, centerCartesian);
}
const granYCos = granularityY;
const granXCos = granularityX;
const granYSin = 0;
const granXSin = 0;
const boundingRectangle = Rectangle_default.clone(
rectangle,
boundingRectangleScratch2
);
const computedOptions = {
granYCos,
granYSin,
granXCos,
granXSin,
nwCorner,
boundingRectangle,
width,
height,
northCap,
southCap
};
if (rotation !== 0) {
const rotationOptions = getRotationOptions(
nwCorner,
rotation,
granularityX,
granularityY,
center,
width,
height
);
north = rotationOptions.north;
south = rotationOptions.south;
east = rotationOptions.east;
west = rotationOptions.west;
if (north < -Math_default.PI_OVER_TWO || north > Math_default.PI_OVER_TWO || south < -Math_default.PI_OVER_TWO || south > Math_default.PI_OVER_TWO) {
throw new DeveloperError_default(
"Rotated rectangle is invalid. It crosses over either the north or south pole."
);
}
computedOptions.granYCos = rotationOptions.granYCos;
computedOptions.granYSin = rotationOptions.granYSin;
computedOptions.granXCos = rotationOptions.granXCos;
computedOptions.granXSin = rotationOptions.granXSin;
boundingRectangle.north = north;
boundingRectangle.south = south;
boundingRectangle.east = east;
boundingRectangle.west = west;
}
if (stRotation !== 0) {
rotation = rotation - stRotation;
const stNwCorner = Rectangle_default.northwest(boundingRectangle, stNwCornerResult);
const stRotationOptions = getRotationOptions(
stNwCorner,
rotation,
granularityX,
granularityY,
center,
width,
height
);
computedOptions.stGranYCos = stRotationOptions.granYCos;
computedOptions.stGranXCos = stRotationOptions.granXCos;
computedOptions.stGranYSin = stRotationOptions.granYSin;
computedOptions.stGranXSin = stRotationOptions.granXSin;
computedOptions.stNwCorner = stNwCorner;
computedOptions.stWest = stRotationOptions.west;
computedOptions.stSouth = stRotationOptions.south;
}
return computedOptions;
};
var RectangleGeometryLibrary_default = RectangleGeometryLibrary;
// packages/engine/Source/Core/RectangleOutlineGeometry.js
var bottomBoundingSphere = new BoundingSphere_default();
var topBoundingSphere = new BoundingSphere_default();
var positionScratch6 = new Cartesian3_default();
var rectangleScratch3 = new Rectangle_default();
function constructRectangle(geometry, computedOptions) {
const ellipsoid = geometry._ellipsoid;
const height = computedOptions.height;
const width = computedOptions.width;
const northCap = computedOptions.northCap;
const southCap = computedOptions.southCap;
let rowHeight = height;
let widthMultiplier = 2;
let size = 0;
let corners2 = 4;
if (northCap) {
widthMultiplier -= 1;
rowHeight -= 1;
size += 1;
corners2 -= 2;
}
if (southCap) {
widthMultiplier -= 1;
rowHeight -= 1;
size += 1;
corners2 -= 2;
}
size += widthMultiplier * width + 2 * rowHeight - corners2;
const positions = new Float64Array(size * 3);
let posIndex = 0;
let row = 0;
let col;
const position = positionScratch6;
if (northCap) {
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
false,
row,
0,
position
);
positions[posIndex++] = position.x;
positions[posIndex++] = position.y;
positions[posIndex++] = position.z;
} else {
for (col = 0; col < width; col++) {
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
false,
row,
col,
position
);
positions[posIndex++] = position.x;
positions[posIndex++] = position.y;
positions[posIndex++] = position.z;
}
}
col = width - 1;
for (row = 1; row < height; row++) {
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
false,
row,
col,
position
);
positions[posIndex++] = position.x;
positions[posIndex++] = position.y;
positions[posIndex++] = position.z;
}
row = height - 1;
if (!southCap) {
for (col = width - 2; col >= 0; col--) {
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
false,
row,
col,
position
);
positions[posIndex++] = position.x;
positions[posIndex++] = position.y;
positions[posIndex++] = position.z;
}
}
col = 0;
for (row = height - 2; row > 0; row--) {
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
false,
row,
col,
position
);
positions[posIndex++] = position.x;
positions[posIndex++] = position.y;
positions[posIndex++] = position.z;
}
const indicesSize = positions.length / 3 * 2;
const indices = IndexDatatype_default.createTypedArray(
positions.length / 3,
indicesSize
);
let index = 0;
for (let i = 0; i < positions.length / 3 - 1; i++) {
indices[index++] = i;
indices[index++] = i + 1;
}
indices[index++] = positions.length / 3 - 1;
indices[index++] = 0;
const geo = new Geometry_default({
attributes: new GeometryAttributes_default(),
primitiveType: PrimitiveType_default.LINES
});
geo.attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
});
geo.indices = indices;
return geo;
}
function constructExtrudedRectangle(rectangleGeometry, computedOptions) {
const maxHeight = rectangleGeometry._surfaceHeight;
const minHeight = rectangleGeometry._extrudedHeight;
const ellipsoid = rectangleGeometry._ellipsoid;
const geo = constructRectangle(rectangleGeometry, computedOptions);
const height = computedOptions.height;
const width = computedOptions.width;
const topPositions = PolygonPipeline_default.scaleToGeodeticHeight(
geo.attributes.position.values,
maxHeight,
ellipsoid,
false
);
let length2 = topPositions.length;
const positions = new Float64Array(length2 * 2);
positions.set(topPositions);
const bottomPositions = PolygonPipeline_default.scaleToGeodeticHeight(
geo.attributes.position.values,
minHeight,
ellipsoid
);
positions.set(bottomPositions, length2);
geo.attributes.position.values = positions;
const northCap = computedOptions.northCap;
const southCap = computedOptions.southCap;
let corners2 = 4;
if (northCap) {
corners2 -= 1;
}
if (southCap) {
corners2 -= 1;
}
const indicesSize = (positions.length / 3 + corners2) * 2;
const indices = IndexDatatype_default.createTypedArray(
positions.length / 3,
indicesSize
);
length2 = positions.length / 6;
let index = 0;
for (let i = 0; i < length2 - 1; i++) {
indices[index++] = i;
indices[index++] = i + 1;
indices[index++] = i + length2;
indices[index++] = i + length2 + 1;
}
indices[index++] = length2 - 1;
indices[index++] = 0;
indices[index++] = length2 + length2 - 1;
indices[index++] = length2;
indices[index++] = 0;
indices[index++] = length2;
let bottomCorner;
if (northCap) {
bottomCorner = height - 1;
} else {
const topRightCorner = width - 1;
indices[index++] = topRightCorner;
indices[index++] = topRightCorner + length2;
bottomCorner = width + height - 2;
}
indices[index++] = bottomCorner;
indices[index++] = bottomCorner + length2;
if (!southCap) {
const bottomLeftCorner = width + bottomCorner - 1;
indices[index++] = bottomLeftCorner;
indices[index] = bottomLeftCorner + length2;
}
geo.indices = indices;
return geo;
}
function RectangleOutlineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const rectangle = options.rectangle;
const granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
const rotation = options.rotation ?? 0;
if (!defined_default(rectangle)) {
throw new DeveloperError_default("rectangle is required.");
}
Rectangle_default._validate(rectangle);
if (rectangle.north < rectangle.south) {
throw new DeveloperError_default(
"options.rectangle.north must be greater than options.rectangle.south"
);
}
const height = options.height ?? 0;
const extrudedHeight = options.extrudedHeight ?? height;
this._rectangle = Rectangle_default.clone(rectangle);
this._granularity = granularity;
this._ellipsoid = ellipsoid;
this._surfaceHeight = Math.max(height, extrudedHeight);
this._rotation = rotation;
this._extrudedHeight = Math.min(height, extrudedHeight);
this._offsetAttribute = options.offsetAttribute;
this._workerName = "createRectangleOutlineGeometry";
}
RectangleOutlineGeometry.packedLength = Rectangle_default.packedLength + Ellipsoid_default.packedLength + 5;
RectangleOutlineGeometry.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
Rectangle_default.pack(value._rectangle, array, startingIndex);
startingIndex += Rectangle_default.packedLength;
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
array[startingIndex++] = value._granularity;
array[startingIndex++] = value._surfaceHeight;
array[startingIndex++] = value._rotation;
array[startingIndex++] = value._extrudedHeight;
array[startingIndex] = value._offsetAttribute ?? -1;
return array;
};
var scratchRectangle4 = new Rectangle_default();
var scratchEllipsoid2 = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var scratchOptions3 = {
rectangle: scratchRectangle4,
ellipsoid: scratchEllipsoid2,
granularity: void 0,
height: void 0,
rotation: void 0,
extrudedHeight: void 0,
offsetAttribute: void 0
};
RectangleOutlineGeometry.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
const rectangle = Rectangle_default.unpack(array, startingIndex, scratchRectangle4);
startingIndex += Rectangle_default.packedLength;
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid2);
startingIndex += Ellipsoid_default.packedLength;
const granularity = array[startingIndex++];
const height = array[startingIndex++];
const rotation = array[startingIndex++];
const extrudedHeight = array[startingIndex++];
const offsetAttribute = array[startingIndex];
if (!defined_default(result)) {
scratchOptions3.granularity = granularity;
scratchOptions3.height = height;
scratchOptions3.rotation = rotation;
scratchOptions3.extrudedHeight = extrudedHeight;
scratchOptions3.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new RectangleOutlineGeometry(scratchOptions3);
}
result._rectangle = Rectangle_default.clone(rectangle, result._rectangle);
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._surfaceHeight = height;
result._rotation = rotation;
result._extrudedHeight = extrudedHeight;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
var nwScratch = new Cartographic_default();
RectangleOutlineGeometry.createGeometry = function(rectangleGeometry) {
const rectangle = rectangleGeometry._rectangle;
const ellipsoid = rectangleGeometry._ellipsoid;
const computedOptions = RectangleGeometryLibrary_default.computeOptions(
rectangle,
rectangleGeometry._granularity,
rectangleGeometry._rotation,
0,
rectangleScratch3,
nwScratch
);
let geometry;
let boundingSphere;
if (Math_default.equalsEpsilon(
rectangle.north,
rectangle.south,
Math_default.EPSILON10
) || Math_default.equalsEpsilon(
rectangle.east,
rectangle.west,
Math_default.EPSILON10
)) {
return void 0;
}
const surfaceHeight = rectangleGeometry._surfaceHeight;
const extrudedHeight = rectangleGeometry._extrudedHeight;
const extrude = !Math_default.equalsEpsilon(
surfaceHeight,
extrudedHeight,
0,
Math_default.EPSILON2
);
let offsetValue;
if (extrude) {
geometry = constructExtrudedRectangle(rectangleGeometry, computedOptions);
if (defined_default(rectangleGeometry._offsetAttribute)) {
const size = geometry.attributes.position.values.length / 3;
let offsetAttribute = new Uint8Array(size);
if (rectangleGeometry._offsetAttribute === GeometryOffsetAttribute_default.TOP) {
offsetAttribute = offsetAttribute.fill(1, 0, size / 2);
} else {
offsetValue = rectangleGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
offsetAttribute = offsetAttribute.fill(offsetValue);
}
geometry.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: offsetAttribute
});
}
const topBS = BoundingSphere_default.fromRectangle3D(
rectangle,
ellipsoid,
surfaceHeight,
topBoundingSphere
);
const bottomBS = BoundingSphere_default.fromRectangle3D(
rectangle,
ellipsoid,
extrudedHeight,
bottomBoundingSphere
);
boundingSphere = BoundingSphere_default.union(topBS, bottomBS);
} else {
geometry = constructRectangle(rectangleGeometry, computedOptions);
geometry.attributes.position.values = PolygonPipeline_default.scaleToGeodeticHeight(
geometry.attributes.position.values,
surfaceHeight,
ellipsoid,
false
);
if (defined_default(rectangleGeometry._offsetAttribute)) {
const length2 = geometry.attributes.position.values.length;
offsetValue = rectangleGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
geometry.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
boundingSphere = BoundingSphere_default.fromRectangle3D(
rectangle,
ellipsoid,
surfaceHeight
);
}
return new Geometry_default({
attributes: geometry.attributes,
indices: geometry.indices,
primitiveType: PrimitiveType_default.LINES,
boundingSphere,
offsetAttribute: rectangleGeometry._offsetAttribute
});
};
var RectangleOutlineGeometry_default = RectangleOutlineGeometry;
// packages/engine/Source/Scene/TileBoundingRegion.js
function TileBoundingRegion(options) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.object("options.rectangle", options.rectangle);
this.rectangle = Rectangle_default.clone(options.rectangle);
this.minimumHeight = options.minimumHeight ?? 0;
this.maximumHeight = options.maximumHeight ?? 0;
this.southwestCornerCartesian = new Cartesian3_default();
this.northeastCornerCartesian = new Cartesian3_default();
this.westNormal = new Cartesian3_default();
this.southNormal = new Cartesian3_default();
this.eastNormal = new Cartesian3_default();
this.northNormal = new Cartesian3_default();
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.WGS84;
computeBox(this, options.rectangle, ellipsoid);
this._orientedBoundingBox = void 0;
this._boundingSphere = void 0;
if (options.computeBoundingVolumes ?? true) {
this.computeBoundingVolumes(ellipsoid);
}
}
Object.defineProperties(TileBoundingRegion.prototype, {
/**
* The underlying bounding volume
*
* @memberof TileBoundingRegion.prototype
*
* @type {object}
* @readonly
*/
boundingVolume: {
get: function() {
return this._orientedBoundingBox;
}
},
/**
* The underlying bounding sphere
*
* @memberof TileBoundingRegion.prototype
*
* @type {BoundingSphere}
* @readonly
*/
boundingSphere: {
get: function() {
return this._boundingSphere;
}
}
});
TileBoundingRegion.prototype.computeBoundingVolumes = function(ellipsoid) {
this._orientedBoundingBox = OrientedBoundingBox_default.fromRectangle(
this.rectangle,
this.minimumHeight,
this.maximumHeight,
ellipsoid
);
this._boundingSphere = BoundingSphere_default.fromOrientedBoundingBox(
this._orientedBoundingBox
);
};
var cartesian3Scratch = new Cartesian3_default();
var cartesian3Scratch22 = new Cartesian3_default();
var cartesian3Scratch32 = new Cartesian3_default();
var westNormalScratch = new Cartesian3_default();
var eastWestNormalScratch = new Cartesian3_default();
var westernMidpointScratch = new Cartesian3_default();
var easternMidpointScratch = new Cartesian3_default();
var cartographicScratch3 = new Cartographic_default();
var planeScratch = new Plane_default(Cartesian3_default.UNIT_X, 0);
var rayScratch = new Ray_default();
function computeBox(tileBB, rectangle, ellipsoid) {
ellipsoid.cartographicToCartesian(
Rectangle_default.southwest(rectangle),
tileBB.southwestCornerCartesian
);
ellipsoid.cartographicToCartesian(
Rectangle_default.northeast(rectangle),
tileBB.northeastCornerCartesian
);
cartographicScratch3.longitude = rectangle.west;
cartographicScratch3.latitude = (rectangle.south + rectangle.north) * 0.5;
cartographicScratch3.height = 0;
const westernMidpointCartesian = ellipsoid.cartographicToCartesian(
cartographicScratch3,
westernMidpointScratch
);
const westNormal = Cartesian3_default.cross(
westernMidpointCartesian,
Cartesian3_default.UNIT_Z,
westNormalScratch
);
Cartesian3_default.normalize(westNormal, tileBB.westNormal);
cartographicScratch3.longitude = rectangle.east;
const easternMidpointCartesian = ellipsoid.cartographicToCartesian(
cartographicScratch3,
easternMidpointScratch
);
const eastNormal = Cartesian3_default.cross(
Cartesian3_default.UNIT_Z,
easternMidpointCartesian,
cartesian3Scratch
);
Cartesian3_default.normalize(eastNormal, tileBB.eastNormal);
let westVector = Cartesian3_default.subtract(
westernMidpointCartesian,
easternMidpointCartesian,
cartesian3Scratch
);
if (Cartesian3_default.magnitude(westVector) === 0) {
westVector = Cartesian3_default.clone(westNormal, westVector);
}
const eastWestNormal = Cartesian3_default.normalize(
westVector,
eastWestNormalScratch
);
const south = rectangle.south;
let southSurfaceNormal;
if (south > 0) {
cartographicScratch3.longitude = (rectangle.west + rectangle.east) * 0.5;
cartographicScratch3.latitude = south;
const southCenterCartesian = ellipsoid.cartographicToCartesian(
cartographicScratch3,
rayScratch.origin
);
Cartesian3_default.clone(eastWestNormal, rayScratch.direction);
const westPlane = Plane_default.fromPointNormal(
tileBB.southwestCornerCartesian,
tileBB.westNormal,
planeScratch
);
IntersectionTests_default.rayPlane(
rayScratch,
westPlane,
tileBB.southwestCornerCartesian
);
southSurfaceNormal = ellipsoid.geodeticSurfaceNormal(
southCenterCartesian,
cartesian3Scratch22
);
} else {
southSurfaceNormal = ellipsoid.geodeticSurfaceNormalCartographic(
Rectangle_default.southeast(rectangle),
cartesian3Scratch22
);
}
const southNormal = Cartesian3_default.cross(
southSurfaceNormal,
westVector,
cartesian3Scratch32
);
Cartesian3_default.normalize(southNormal, tileBB.southNormal);
const north = rectangle.north;
let northSurfaceNormal;
if (north < 0) {
cartographicScratch3.longitude = (rectangle.west + rectangle.east) * 0.5;
cartographicScratch3.latitude = north;
const northCenterCartesian = ellipsoid.cartographicToCartesian(
cartographicScratch3,
rayScratch.origin
);
Cartesian3_default.negate(eastWestNormal, rayScratch.direction);
const eastPlane = Plane_default.fromPointNormal(
tileBB.northeastCornerCartesian,
tileBB.eastNormal,
planeScratch
);
IntersectionTests_default.rayPlane(
rayScratch,
eastPlane,
tileBB.northeastCornerCartesian
);
northSurfaceNormal = ellipsoid.geodeticSurfaceNormal(
northCenterCartesian,
cartesian3Scratch22
);
} else {
northSurfaceNormal = ellipsoid.geodeticSurfaceNormalCartographic(
Rectangle_default.northwest(rectangle),
cartesian3Scratch22
);
}
const northNormal = Cartesian3_default.cross(
westVector,
northSurfaceNormal,
cartesian3Scratch32
);
Cartesian3_default.normalize(northNormal, tileBB.northNormal);
}
var southwestCornerScratch = new Cartesian3_default();
var northeastCornerScratch = new Cartesian3_default();
var negativeUnitY = new Cartesian3_default(0, -1, 0);
var negativeUnitZ = new Cartesian3_default(0, 0, -1);
var vectorScratch = new Cartesian3_default();
function distanceToCameraRegion(tileBB, frameState) {
const camera = frameState.camera;
const cameraCartesianPosition = camera.positionWC;
const cameraCartographicPosition = camera.positionCartographic;
let result = 0;
if (!Rectangle_default.contains(tileBB.rectangle, cameraCartographicPosition)) {
let southwestCornerCartesian = tileBB.southwestCornerCartesian;
let northeastCornerCartesian = tileBB.northeastCornerCartesian;
let westNormal = tileBB.westNormal;
let southNormal = tileBB.southNormal;
let eastNormal = tileBB.eastNormal;
let northNormal = tileBB.northNormal;
if (frameState.mode !== SceneMode_default.SCENE3D) {
southwestCornerCartesian = frameState.mapProjection.project(
Rectangle_default.southwest(tileBB.rectangle),
southwestCornerScratch
);
southwestCornerCartesian.z = southwestCornerCartesian.y;
southwestCornerCartesian.y = southwestCornerCartesian.x;
southwestCornerCartesian.x = 0;
northeastCornerCartesian = frameState.mapProjection.project(
Rectangle_default.northeast(tileBB.rectangle),
northeastCornerScratch
);
northeastCornerCartesian.z = northeastCornerCartesian.y;
northeastCornerCartesian.y = northeastCornerCartesian.x;
northeastCornerCartesian.x = 0;
westNormal = negativeUnitY;
eastNormal = Cartesian3_default.UNIT_Y;
southNormal = negativeUnitZ;
northNormal = Cartesian3_default.UNIT_Z;
}
const vectorFromSouthwestCorner = Cartesian3_default.subtract(
cameraCartesianPosition,
southwestCornerCartesian,
vectorScratch
);
const distanceToWestPlane = Cartesian3_default.dot(
vectorFromSouthwestCorner,
westNormal
);
const distanceToSouthPlane = Cartesian3_default.dot(
vectorFromSouthwestCorner,
southNormal
);
const vectorFromNortheastCorner = Cartesian3_default.subtract(
cameraCartesianPosition,
northeastCornerCartesian,
vectorScratch
);
const distanceToEastPlane = Cartesian3_default.dot(
vectorFromNortheastCorner,
eastNormal
);
const distanceToNorthPlane = Cartesian3_default.dot(
vectorFromNortheastCorner,
northNormal
);
if (distanceToWestPlane > 0) {
result += distanceToWestPlane * distanceToWestPlane;
} else if (distanceToEastPlane > 0) {
result += distanceToEastPlane * distanceToEastPlane;
}
if (distanceToSouthPlane > 0) {
result += distanceToSouthPlane * distanceToSouthPlane;
} else if (distanceToNorthPlane > 0) {
result += distanceToNorthPlane * distanceToNorthPlane;
}
}
let cameraHeight;
let minimumHeight;
let maximumHeight;
if (frameState.mode === SceneMode_default.SCENE3D) {
cameraHeight = cameraCartographicPosition.height;
minimumHeight = tileBB.minimumHeight;
maximumHeight = tileBB.maximumHeight;
} else {
cameraHeight = cameraCartesianPosition.x;
minimumHeight = 0;
maximumHeight = 0;
}
if (cameraHeight > maximumHeight) {
const distanceAboveTop = cameraHeight - maximumHeight;
result += distanceAboveTop * distanceAboveTop;
} else if (cameraHeight < minimumHeight) {
const distanceBelowBottom = minimumHeight - cameraHeight;
result += distanceBelowBottom * distanceBelowBottom;
}
return Math.sqrt(result);
}
TileBoundingRegion.prototype.distanceToCamera = function(frameState) {
Check_default.defined("frameState", frameState);
const regionResult = distanceToCameraRegion(this, frameState);
if (frameState.mode === SceneMode_default.SCENE3D && defined_default(this._orientedBoundingBox)) {
const obbResult = Math.sqrt(
this._orientedBoundingBox.distanceSquaredTo(frameState.camera.positionWC)
);
return Math.max(regionResult, obbResult);
}
return regionResult;
};
TileBoundingRegion.prototype.intersectPlane = function(plane) {
Check_default.defined("plane", plane);
return this._orientedBoundingBox.intersectPlane(plane);
};
TileBoundingRegion.prototype.createDebugVolume = function(color) {
Check_default.defined("color", color);
const modelMatrix = new Matrix4_default.clone(Matrix4_default.IDENTITY);
const geometry = new RectangleOutlineGeometry_default({
rectangle: this.rectangle,
height: this.minimumHeight,
extrudedHeight: this.maximumHeight
});
const instance = new GeometryInstance_default({
geometry,
id: "outline",
modelMatrix,
attributes: {
color: ColorGeometryInstanceAttribute_default.fromColor(color)
}
});
return new Primitive_default({
geometryInstances: instance,
appearance: new PerInstanceColorAppearance_default({
translucent: false,
flat: true
}),
asynchronous: false
});
};
var TileBoundingRegion_default = TileBoundingRegion;
// packages/engine/Source/Scene/TileBoundingS2Cell.js
var import_InlineWorkers791 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/CoplanarPolygonOutlineGeometry.js
var import_InlineWorkers790 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/CoplanarPolygonGeometryLibrary.js
var import_InlineWorkers789 = __toESM(require_InlineWorkers(), 1);
var CoplanarPolygonGeometryLibrary = {};
var scratchIntersectionPoint = new Cartesian3_default();
var scratchXAxis2 = new Cartesian3_default();
var scratchYAxis2 = new Cartesian3_default();
var scratchZAxis2 = new Cartesian3_default();
var obbScratch = new OrientedBoundingBox_default();
CoplanarPolygonGeometryLibrary.validOutline = function(positions) {
Check_default.defined("positions", positions);
const orientedBoundingBox = OrientedBoundingBox_default.fromPoints(
positions,
obbScratch
);
const halfAxes = orientedBoundingBox.halfAxes;
const xAxis = Matrix3_default.getColumn(halfAxes, 0, scratchXAxis2);
const yAxis = Matrix3_default.getColumn(halfAxes, 1, scratchYAxis2);
const zAxis = Matrix3_default.getColumn(halfAxes, 2, scratchZAxis2);
const xMag = Cartesian3_default.magnitude(xAxis);
const yMag = Cartesian3_default.magnitude(yAxis);
const zMag = Cartesian3_default.magnitude(zAxis);
return !(xMag === 0 && (yMag === 0 || zMag === 0) || yMag === 0 && zMag === 0);
};
CoplanarPolygonGeometryLibrary.computeProjectTo2DArguments = function(positions, centerResult, planeAxis1Result, planeAxis2Result) {
Check_default.defined("positions", positions);
Check_default.defined("centerResult", centerResult);
Check_default.defined("planeAxis1Result", planeAxis1Result);
Check_default.defined("planeAxis2Result", planeAxis2Result);
const orientedBoundingBox = OrientedBoundingBox_default.fromPoints(
positions,
obbScratch
);
const halfAxes = orientedBoundingBox.halfAxes;
const xAxis = Matrix3_default.getColumn(halfAxes, 0, scratchXAxis2);
const yAxis = Matrix3_default.getColumn(halfAxes, 1, scratchYAxis2);
const zAxis = Matrix3_default.getColumn(halfAxes, 2, scratchZAxis2);
const xMag = Cartesian3_default.magnitude(xAxis);
const yMag = Cartesian3_default.magnitude(yAxis);
const zMag = Cartesian3_default.magnitude(zAxis);
const min3 = Math.min(xMag, yMag, zMag);
if (xMag === 0 && (yMag === 0 || zMag === 0) || yMag === 0 && zMag === 0) {
return false;
}
let planeAxis1;
let planeAxis2;
if (min3 === yMag || min3 === zMag) {
planeAxis1 = xAxis;
}
if (min3 === xMag) {
planeAxis1 = yAxis;
} else if (min3 === zMag) {
planeAxis2 = yAxis;
}
if (min3 === xMag || min3 === yMag) {
planeAxis2 = zAxis;
}
Cartesian3_default.normalize(planeAxis1, planeAxis1Result);
Cartesian3_default.normalize(planeAxis2, planeAxis2Result);
Cartesian3_default.clone(orientedBoundingBox.center, centerResult);
return true;
};
function projectTo2D(position, center, axis1, axis2, result) {
const v3 = Cartesian3_default.subtract(position, center, scratchIntersectionPoint);
const x = Cartesian3_default.dot(axis1, v3);
const y = Cartesian3_default.dot(axis2, v3);
return Cartesian2_default.fromElements(x, y, result);
}
CoplanarPolygonGeometryLibrary.createProjectPointsTo2DFunction = function(center, axis1, axis2) {
return function(positions) {
const positionResults = new Array(positions.length);
for (let i = 0; i < positions.length; i++) {
positionResults[i] = projectTo2D(positions[i], center, axis1, axis2);
}
return positionResults;
};
};
CoplanarPolygonGeometryLibrary.createProjectPointTo2DFunction = function(center, axis1, axis2) {
return function(position, result) {
return projectTo2D(position, center, axis1, axis2, result);
};
};
var CoplanarPolygonGeometryLibrary_default = CoplanarPolygonGeometryLibrary;
// packages/engine/Source/Core/CoplanarPolygonOutlineGeometry.js
function createGeometryFromPositions(positions) {
const length2 = positions.length;
const flatPositions = new Float64Array(length2 * 3);
const indices = IndexDatatype_default.createTypedArray(length2, length2 * 2);
let positionIndex = 0;
let index = 0;
for (let i = 0; i < length2; i++) {
const position = positions[i];
flatPositions[positionIndex++] = position.x;
flatPositions[positionIndex++] = position.y;
flatPositions[positionIndex++] = position.z;
indices[index++] = i;
indices[index++] = (i + 1) % length2;
}
const attributes = new GeometryAttributes_default({
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: flatPositions
})
});
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.LINES
});
}
function CoplanarPolygonOutlineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const polygonHierarchy = options.polygonHierarchy;
Check_default.defined("options.polygonHierarchy", polygonHierarchy);
this._polygonHierarchy = polygonHierarchy;
this._workerName = "createCoplanarPolygonOutlineGeometry";
this.packedLength = PolygonGeometryLibrary_default.computeHierarchyPackedLength(
polygonHierarchy,
Cartesian3_default
) + 1;
}
CoplanarPolygonOutlineGeometry.fromPositions = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.defined("options.positions", options.positions);
const newOptions2 = {
polygonHierarchy: {
positions: options.positions
}
};
return new CoplanarPolygonOutlineGeometry(newOptions2);
};
CoplanarPolygonOutlineGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
startingIndex = PolygonGeometryLibrary_default.packPolygonHierarchy(
value._polygonHierarchy,
array,
startingIndex,
Cartesian3_default
);
array[startingIndex] = value.packedLength;
return array;
};
var scratchOptions4 = {
polygonHierarchy: {}
};
CoplanarPolygonOutlineGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const polygonHierarchy = PolygonGeometryLibrary_default.unpackPolygonHierarchy(
array,
startingIndex,
Cartesian3_default
);
startingIndex = polygonHierarchy.startingIndex;
delete polygonHierarchy.startingIndex;
const packedLength = array[startingIndex];
if (!defined_default(result)) {
result = new CoplanarPolygonOutlineGeometry(scratchOptions4);
}
result._polygonHierarchy = polygonHierarchy;
result.packedLength = packedLength;
return result;
};
CoplanarPolygonOutlineGeometry.createGeometry = function(polygonGeometry) {
const polygonHierarchy = polygonGeometry._polygonHierarchy;
let outerPositions = polygonHierarchy.positions;
outerPositions = arrayRemoveDuplicates_default(
outerPositions,
Cartesian3_default.equalsEpsilon,
true
);
if (outerPositions.length < 3) {
return;
}
const isValid = CoplanarPolygonGeometryLibrary_default.validOutline(outerPositions);
if (!isValid) {
return void 0;
}
const polygons = PolygonGeometryLibrary_default.polygonOutlinesFromHierarchy(
polygonHierarchy,
false
);
if (polygons.length === 0) {
return void 0;
}
const geometries = [];
for (let i = 0; i < polygons.length; i++) {
const geometryInstance = new GeometryInstance_default({
geometry: createGeometryFromPositions(polygons[i])
});
geometries.push(geometryInstance);
}
const geometry = GeometryPipeline_default.combineInstances(geometries)[0];
const boundingSphere = BoundingSphere_default.fromPoints(polygonHierarchy.positions);
return new Geometry_default({
attributes: geometry.attributes,
indices: geometry.indices,
primitiveType: geometry.primitiveType,
boundingSphere
});
};
var CoplanarPolygonOutlineGeometry_default = CoplanarPolygonOutlineGeometry;
// packages/engine/Source/Scene/TileBoundingS2Cell.js
var centerCartographicScratch = new Cartographic_default();
function TileBoundingS2Cell(options) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.string("options.token", options.token);
const s2Cell = S2Cell_default.fromToken(options.token);
const minimumHeight = options.minimumHeight ?? 0;
const maximumHeight = options.maximumHeight ?? 0;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.WGS84;
this.s2Cell = s2Cell;
this.minimumHeight = minimumHeight;
this.maximumHeight = maximumHeight;
this.ellipsoid = ellipsoid;
const boundingPlanes = computeBoundingPlanes(
s2Cell,
minimumHeight,
maximumHeight,
ellipsoid
);
this._boundingPlanes = boundingPlanes;
const vertices = computeVertices(boundingPlanes);
this._vertices = vertices;
this._edgeNormals = new Array(6);
this._edgeNormals[0] = computeEdgeNormals(
boundingPlanes[0],
vertices.slice(0, 4)
);
let i;
for (i = 0; i < 4; i++) {
this._edgeNormals[0][i] = Cartesian3_default.negate(
this._edgeNormals[0][i],
this._edgeNormals[0][i]
);
}
this._edgeNormals[1] = computeEdgeNormals(
boundingPlanes[1],
vertices.slice(4, 8)
);
for (i = 0; i < 4; i++) {
this._edgeNormals[2 + i] = computeEdgeNormals(boundingPlanes[2 + i], [
vertices[i % 4],
vertices[(i + 1) % 4],
vertices[4 + (i + 1) % 4],
vertices[4 + i]
]);
}
this._planeVertices = [
this._vertices.slice(0, 4),
this._vertices.slice(4, 8)
];
for (i = 0; i < 4; i++) {
this._planeVertices.push([
this._vertices[i % 4],
this._vertices[(i + 1) % 4],
this._vertices[4 + (i + 1) % 4],
this._vertices[4 + i]
]);
}
const center = s2Cell.getCenter();
centerCartographicScratch = ellipsoid.cartesianToCartographic(
center,
centerCartographicScratch
);
centerCartographicScratch.height = (maximumHeight + minimumHeight) / 2;
this.center = ellipsoid.cartographicToCartesian(
centerCartographicScratch,
center
);
this._boundingSphere = BoundingSphere_default.fromPoints(vertices);
}
var centerGeodeticNormalScratch = new Cartesian3_default();
var topCartographicScratch = new Cartographic_default();
var topScratch = new Cartesian3_default();
var vertexCartographicScratch = new Cartographic_default();
var vertexScratch = new Cartesian3_default();
var vertexGeodeticNormalScratch = new Cartesian3_default();
var sideNormalScratch = new Cartesian3_default();
var sideScratch = new Cartesian3_default();
function computeBoundingPlanes(s2Cell, minimumHeight, maximumHeight, ellipsoid) {
const planes = new Array(6);
const centerPoint = s2Cell.getCenter();
const centerSurfaceNormal = ellipsoid.geodeticSurfaceNormal(
centerPoint,
centerGeodeticNormalScratch
);
const topCartographic = ellipsoid.cartesianToCartographic(
centerPoint,
topCartographicScratch
);
topCartographic.height = maximumHeight;
const top = ellipsoid.cartographicToCartesian(topCartographic, topScratch);
const topPlane = Plane_default.fromPointNormal(top, centerSurfaceNormal);
planes[0] = topPlane;
let maxDistance = 0;
let i;
const vertices = [];
let vertex, vertexCartographic;
for (i = 0; i < 4; i++) {
vertex = s2Cell.getVertex(i);
vertices[i] = vertex;
vertexCartographic = ellipsoid.cartesianToCartographic(
vertex,
vertexCartographicScratch
);
vertexCartographic.height = minimumHeight;
const distance2 = Plane_default.getPointDistance(
topPlane,
ellipsoid.cartographicToCartesian(vertexCartographic, vertexScratch)
);
if (distance2 < maxDistance) {
maxDistance = distance2;
}
}
const bottomPlane = Plane_default.clone(topPlane);
bottomPlane.normal = Cartesian3_default.negate(
bottomPlane.normal,
bottomPlane.normal
);
bottomPlane.distance = bottomPlane.distance * -1 + maxDistance;
planes[1] = bottomPlane;
for (i = 0; i < 4; i++) {
vertex = vertices[i];
const adjacentVertex = vertices[(i + 1) % 4];
const geodeticNormal = ellipsoid.geodeticSurfaceNormal(
vertex,
vertexGeodeticNormalScratch
);
const side = Cartesian3_default.subtract(adjacentVertex, vertex, sideScratch);
let sideNormal = Cartesian3_default.cross(side, geodeticNormal, sideNormalScratch);
sideNormal = Cartesian3_default.normalize(sideNormal, sideNormal);
planes[2 + i] = Plane_default.fromPointNormal(vertex, sideNormal);
}
return planes;
}
var n0Scratch = new Cartesian3_default();
var n1Scratch = new Cartesian3_default();
var n2Scratch = new Cartesian3_default();
var x0Scratch = new Cartesian3_default();
var x1Scratch = new Cartesian3_default();
var x2Scratch = new Cartesian3_default();
var t0Scratch = new Cartesian3_default();
var t1Scratch = new Cartesian3_default();
var t2Scratch = new Cartesian3_default();
var f0Scratch = new Cartesian3_default();
var f1Scratch = new Cartesian3_default();
var f2Scratch = new Cartesian3_default();
var sScratch2 = new Cartesian3_default();
var matrixScratch = new Matrix3_default();
function computeIntersection(p0, p1, p2) {
n0Scratch = p0.normal;
n1Scratch = p1.normal;
n2Scratch = p2.normal;
x0Scratch = Cartesian3_default.multiplyByScalar(p0.normal, -p0.distance, x0Scratch);
x1Scratch = Cartesian3_default.multiplyByScalar(p1.normal, -p1.distance, x1Scratch);
x2Scratch = Cartesian3_default.multiplyByScalar(p2.normal, -p2.distance, x2Scratch);
f0Scratch = Cartesian3_default.multiplyByScalar(
Cartesian3_default.cross(n1Scratch, n2Scratch, t0Scratch),
Cartesian3_default.dot(x0Scratch, n0Scratch),
f0Scratch
);
f1Scratch = Cartesian3_default.multiplyByScalar(
Cartesian3_default.cross(n2Scratch, n0Scratch, t1Scratch),
Cartesian3_default.dot(x1Scratch, n1Scratch),
f1Scratch
);
f2Scratch = Cartesian3_default.multiplyByScalar(
Cartesian3_default.cross(n0Scratch, n1Scratch, t2Scratch),
Cartesian3_default.dot(x2Scratch, n2Scratch),
f2Scratch
);
matrixScratch[0] = n0Scratch.x;
matrixScratch[1] = n1Scratch.x;
matrixScratch[2] = n2Scratch.x;
matrixScratch[3] = n0Scratch.y;
matrixScratch[4] = n1Scratch.y;
matrixScratch[5] = n2Scratch.y;
matrixScratch[6] = n0Scratch.z;
matrixScratch[7] = n1Scratch.z;
matrixScratch[8] = n2Scratch.z;
const determinant = Matrix3_default.determinant(matrixScratch);
sScratch2 = Cartesian3_default.add(f0Scratch, f1Scratch, sScratch2);
sScratch2 = Cartesian3_default.add(sScratch2, f2Scratch, sScratch2);
return new Cartesian3_default(
sScratch2.x / determinant,
sScratch2.y / determinant,
sScratch2.z / determinant
);
}
function computeVertices(boundingPlanes) {
const vertices = new Array(8);
for (let i = 0; i < 4; i++) {
vertices[i] = computeIntersection(
boundingPlanes[0],
boundingPlanes[2 + (i + 3) % 4],
boundingPlanes[2 + i % 4]
);
vertices[i + 4] = computeIntersection(
boundingPlanes[1],
boundingPlanes[2 + (i + 3) % 4],
boundingPlanes[2 + i % 4]
);
}
return vertices;
}
var edgeScratch = new Cartesian3_default();
var edgeNormalScratch = new Cartesian3_default();
function computeEdgeNormals(plane, vertices) {
const edgeNormals = [];
for (let i = 0; i < 4; i++) {
edgeScratch = Cartesian3_default.subtract(
vertices[(i + 1) % 4],
vertices[i],
edgeScratch
);
edgeNormalScratch = Cartesian3_default.cross(
plane.normal,
edgeScratch,
edgeNormalScratch
);
edgeNormalScratch = Cartesian3_default.normalize(
edgeNormalScratch,
edgeNormalScratch
);
edgeNormals[i] = Cartesian3_default.clone(edgeNormalScratch);
}
return edgeNormals;
}
Object.defineProperties(TileBoundingS2Cell.prototype, {
/**
* The underlying bounding volume.
*
* @memberof TileBoundingS2Cell.prototype
*
* @type {object}
* @readonly
*/
boundingVolume: {
get: function() {
return this;
}
},
/**
* The underlying bounding sphere.
*
* @memberof TileBoundingS2Cell.prototype
*
* @type {BoundingSphere}
* @readonly
*/
boundingSphere: {
get: function() {
return this._boundingSphere;
}
}
});
var facePointScratch = new Cartesian3_default();
TileBoundingS2Cell.prototype.distanceToCamera = function(frameState) {
Check_default.defined("frameState", frameState);
const point = frameState.camera.positionWC;
const selectedPlaneIndices = [];
const vertices = [];
let edgeNormals;
if (Plane_default.getPointDistance(this._boundingPlanes[0], point) > 0) {
selectedPlaneIndices.push(0);
vertices.push(this._planeVertices[0]);
edgeNormals = this._edgeNormals[0];
} else if (Plane_default.getPointDistance(this._boundingPlanes[1], point) > 0) {
selectedPlaneIndices.push(1);
vertices.push(this._planeVertices[1]);
edgeNormals = this._edgeNormals[1];
}
let i;
let sidePlaneIndex;
for (i = 0; i < 4; i++) {
sidePlaneIndex = 2 + i;
if (Plane_default.getPointDistance(this._boundingPlanes[sidePlaneIndex], point) > 0) {
selectedPlaneIndices.push(sidePlaneIndex);
vertices.push(this._planeVertices[sidePlaneIndex]);
edgeNormals = this._edgeNormals[sidePlaneIndex];
}
}
if (selectedPlaneIndices.length === 0) {
return 0;
}
let facePoint;
let selectedPlane;
if (selectedPlaneIndices.length === 1) {
selectedPlane = this._boundingPlanes[selectedPlaneIndices[0]];
facePoint = closestPointPolygon(
Plane_default.projectPointOntoPlane(selectedPlane, point, facePointScratch),
vertices[0],
selectedPlane,
edgeNormals
);
return Cartesian3_default.distance(facePoint, point);
} else if (selectedPlaneIndices.length === 2) {
if (selectedPlaneIndices[0] === 0) {
const edge = [
this._vertices[4 * selectedPlaneIndices[0] + (selectedPlaneIndices[1] - 2)],
this._vertices[4 * selectedPlaneIndices[0] + (selectedPlaneIndices[1] - 2 + 1) % 4]
];
facePoint = closestPointLineSegment(point, edge[0], edge[1]);
return Cartesian3_default.distance(facePoint, point);
}
let minimumDistance = Number.MAX_VALUE;
let distance2;
for (i = 0; i < 2; i++) {
selectedPlane = this._boundingPlanes[selectedPlaneIndices[i]];
facePoint = closestPointPolygon(
Plane_default.projectPointOntoPlane(selectedPlane, point, facePointScratch),
vertices[i],
selectedPlane,
this._edgeNormals[selectedPlaneIndices[i]]
);
distance2 = Cartesian3_default.distanceSquared(facePoint, point);
if (distance2 < minimumDistance) {
minimumDistance = distance2;
}
}
return Math.sqrt(minimumDistance);
} else if (selectedPlaneIndices.length > 3) {
facePoint = closestPointPolygon(
Plane_default.projectPointOntoPlane(
this._boundingPlanes[1],
point,
facePointScratch
),
this._planeVertices[1],
this._boundingPlanes[1],
this._edgeNormals[1]
);
return Cartesian3_default.distance(facePoint, point);
}
const skip = selectedPlaneIndices[1] === 2 && selectedPlaneIndices[2] === 5 ? 0 : 1;
if (selectedPlaneIndices[0] === 0) {
return Cartesian3_default.distance(
point,
this._vertices[(selectedPlaneIndices[1] - 2 + skip) % 4]
);
}
return Cartesian3_default.distance(
point,
this._vertices[4 + (selectedPlaneIndices[1] - 2 + skip) % 4]
);
};
var dScratch2 = new Cartesian3_default();
var pL0Scratch = new Cartesian3_default();
function closestPointLineSegment(p, l0, l1) {
const d = Cartesian3_default.subtract(l1, l0, dScratch2);
const pL0 = Cartesian3_default.subtract(p, l0, pL0Scratch);
let t = Cartesian3_default.dot(d, pL0);
if (t <= 0) {
return l0;
}
const dMag = Cartesian3_default.dot(d, d);
if (t >= dMag) {
return l1;
}
t = t / dMag;
return new Cartesian3_default(
(1 - t) * l0.x + t * l1.x,
(1 - t) * l0.y + t * l1.y,
(1 - t) * l0.z + t * l1.z
);
}
var edgePlaneScratch = new Plane_default(Cartesian3_default.UNIT_X, 0);
function closestPointPolygon(p, vertices, plane, edgeNormals) {
let minDistance = Number.MAX_VALUE;
let distance2;
let closestPoint;
let closestPointOnEdge;
for (let i = 0; i < vertices.length; i++) {
const edgePlane = Plane_default.fromPointNormal(
vertices[i],
edgeNormals[i],
edgePlaneScratch
);
const edgePlaneDistance = Plane_default.getPointDistance(edgePlane, p);
if (edgePlaneDistance < 0) {
continue;
}
closestPointOnEdge = closestPointLineSegment(
p,
vertices[i],
vertices[(i + 1) % 4]
);
distance2 = Cartesian3_default.distance(p, closestPointOnEdge);
if (distance2 < minDistance) {
minDistance = distance2;
closestPoint = closestPointOnEdge;
}
}
if (!defined_default(closestPoint)) {
return p;
}
return closestPoint;
}
TileBoundingS2Cell.prototype.intersectPlane = function(plane) {
Check_default.defined("plane", plane);
let plusCount = 0;
let negCount = 0;
for (let i = 0; i < this._vertices.length; i++) {
const distanceToPlane = Cartesian3_default.dot(plane.normal, this._vertices[i]) + plane.distance;
if (distanceToPlane < 0) {
negCount++;
} else {
plusCount++;
}
}
if (plusCount === this._vertices.length) {
return Intersect_default.INSIDE;
} else if (negCount === this._vertices.length) {
return Intersect_default.OUTSIDE;
}
return Intersect_default.INTERSECTING;
};
TileBoundingS2Cell.prototype.createDebugVolume = function(color) {
Check_default.defined("color", color);
const modelMatrix = new Matrix4_default.clone(Matrix4_default.IDENTITY);
const topPlanePolygon = new CoplanarPolygonOutlineGeometry_default({
polygonHierarchy: {
positions: this._planeVertices[0]
}
});
const topPlaneGeometry = CoplanarPolygonOutlineGeometry_default.createGeometry(topPlanePolygon);
const topPlaneInstance = new GeometryInstance_default({
geometry: topPlaneGeometry,
id: "outline",
modelMatrix,
attributes: {
color: ColorGeometryInstanceAttribute_default.fromColor(color)
}
});
const bottomPlanePolygon = new CoplanarPolygonOutlineGeometry_default({
polygonHierarchy: {
positions: this._planeVertices[1]
}
});
const bottomPlaneGeometry = CoplanarPolygonOutlineGeometry_default.createGeometry(bottomPlanePolygon);
const bottomPlaneInstance = new GeometryInstance_default({
geometry: bottomPlaneGeometry,
id: "outline",
modelMatrix,
attributes: {
color: ColorGeometryInstanceAttribute_default.fromColor(color)
}
});
const sideInstances = [];
for (let i = 0; i < 4; i++) {
const sidePlanePolygon = new CoplanarPolygonOutlineGeometry_default({
polygonHierarchy: {
positions: this._planeVertices[2 + i]
}
});
const sidePlaneGeometry = CoplanarPolygonOutlineGeometry_default.createGeometry(sidePlanePolygon);
sideInstances[i] = new GeometryInstance_default({
geometry: sidePlaneGeometry,
id: "outline",
modelMatrix,
attributes: {
color: ColorGeometryInstanceAttribute_default.fromColor(color)
}
});
}
return new Primitive_default({
geometryInstances: [
sideInstances[0],
sideInstances[1],
sideInstances[2],
sideInstances[3],
bottomPlaneInstance,
topPlaneInstance
],
appearance: new PerInstanceColorAppearance_default({
translucent: false,
flat: true
}),
asynchronous: false
});
};
var TileBoundingS2Cell_default = TileBoundingS2Cell;
// packages/engine/Source/Scene/TileBoundingSphere.js
var import_InlineWorkers794 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/SphereOutlineGeometry.js
var import_InlineWorkers793 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/EllipsoidOutlineGeometry.js
var import_InlineWorkers792 = __toESM(require_InlineWorkers(), 1);
var defaultRadii = new Cartesian3_default(1, 1, 1);
var cos2 = Math.cos;
var sin2 = Math.sin;
function EllipsoidOutlineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const radii = options.radii ?? defaultRadii;
const innerRadii = options.innerRadii ?? radii;
const minimumClock = options.minimumClock ?? 0;
const maximumClock = options.maximumClock ?? Math_default.TWO_PI;
const minimumCone = options.minimumCone ?? 0;
const maximumCone = options.maximumCone ?? Math_default.PI;
const stackPartitions = Math.round(options.stackPartitions ?? 10);
const slicePartitions = Math.round(options.slicePartitions ?? 8);
const subdivisions = Math.round(options.subdivisions ?? 128);
if (stackPartitions < 1) {
throw new DeveloperError_default("options.stackPartitions cannot be less than 1");
}
if (slicePartitions < 0) {
throw new DeveloperError_default("options.slicePartitions cannot be less than 0");
}
if (subdivisions < 0) {
throw new DeveloperError_default(
"options.subdivisions must be greater than or equal to zero."
);
}
if (defined_default(options.offsetAttribute) && options.offsetAttribute === GeometryOffsetAttribute_default.TOP) {
throw new DeveloperError_default(
"GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry."
);
}
this._radii = Cartesian3_default.clone(radii);
this._innerRadii = Cartesian3_default.clone(innerRadii);
this._minimumClock = minimumClock;
this._maximumClock = maximumClock;
this._minimumCone = minimumCone;
this._maximumCone = maximumCone;
this._stackPartitions = stackPartitions;
this._slicePartitions = slicePartitions;
this._subdivisions = subdivisions;
this._offsetAttribute = options.offsetAttribute;
this._workerName = "createEllipsoidOutlineGeometry";
}
EllipsoidOutlineGeometry.packedLength = 2 * Cartesian3_default.packedLength + 8;
EllipsoidOutlineGeometry.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
Cartesian3_default.pack(value._radii, array, startingIndex);
startingIndex += Cartesian3_default.packedLength;
Cartesian3_default.pack(value._innerRadii, array, startingIndex);
startingIndex += Cartesian3_default.packedLength;
array[startingIndex++] = value._minimumClock;
array[startingIndex++] = value._maximumClock;
array[startingIndex++] = value._minimumCone;
array[startingIndex++] = value._maximumCone;
array[startingIndex++] = value._stackPartitions;
array[startingIndex++] = value._slicePartitions;
array[startingIndex++] = value._subdivisions;
array[startingIndex] = value._offsetAttribute ?? -1;
return array;
};
var scratchRadii = new Cartesian3_default();
var scratchInnerRadii = new Cartesian3_default();
var scratchOptions5 = {
radii: scratchRadii,
innerRadii: scratchInnerRadii,
minimumClock: void 0,
maximumClock: void 0,
minimumCone: void 0,
maximumCone: void 0,
stackPartitions: void 0,
slicePartitions: void 0,
subdivisions: void 0,
offsetAttribute: void 0
};
EllipsoidOutlineGeometry.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
const radii = Cartesian3_default.unpack(array, startingIndex, scratchRadii);
startingIndex += Cartesian3_default.packedLength;
const innerRadii = Cartesian3_default.unpack(array, startingIndex, scratchInnerRadii);
startingIndex += Cartesian3_default.packedLength;
const minimumClock = array[startingIndex++];
const maximumClock = array[startingIndex++];
const minimumCone = array[startingIndex++];
const maximumCone = array[startingIndex++];
const stackPartitions = array[startingIndex++];
const slicePartitions = array[startingIndex++];
const subdivisions = array[startingIndex++];
const offsetAttribute = array[startingIndex];
if (!defined_default(result)) {
scratchOptions5.minimumClock = minimumClock;
scratchOptions5.maximumClock = maximumClock;
scratchOptions5.minimumCone = minimumCone;
scratchOptions5.maximumCone = maximumCone;
scratchOptions5.stackPartitions = stackPartitions;
scratchOptions5.slicePartitions = slicePartitions;
scratchOptions5.subdivisions = subdivisions;
scratchOptions5.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new EllipsoidOutlineGeometry(scratchOptions5);
}
result._radii = Cartesian3_default.clone(radii, result._radii);
result._innerRadii = Cartesian3_default.clone(innerRadii, result._innerRadii);
result._minimumClock = minimumClock;
result._maximumClock = maximumClock;
result._minimumCone = minimumCone;
result._maximumCone = maximumCone;
result._stackPartitions = stackPartitions;
result._slicePartitions = slicePartitions;
result._subdivisions = subdivisions;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
EllipsoidOutlineGeometry.createGeometry = function(ellipsoidGeometry) {
const radii = ellipsoidGeometry._radii;
if (radii.x <= 0 || radii.y <= 0 || radii.z <= 0) {
return;
}
const innerRadii = ellipsoidGeometry._innerRadii;
if (innerRadii.x <= 0 || innerRadii.y <= 0 || innerRadii.z <= 0) {
return;
}
const minimumClock = ellipsoidGeometry._minimumClock;
const maximumClock = ellipsoidGeometry._maximumClock;
const minimumCone = ellipsoidGeometry._minimumCone;
const maximumCone = ellipsoidGeometry._maximumCone;
const subdivisions = ellipsoidGeometry._subdivisions;
const ellipsoid = Ellipsoid_default.fromCartesian3(radii);
let slicePartitions = ellipsoidGeometry._slicePartitions + 1;
let stackPartitions = ellipsoidGeometry._stackPartitions + 1;
slicePartitions = Math.round(
slicePartitions * Math.abs(maximumClock - minimumClock) / Math_default.TWO_PI
);
stackPartitions = Math.round(
stackPartitions * Math.abs(maximumCone - minimumCone) / Math_default.PI
);
if (slicePartitions < 2) {
slicePartitions = 2;
}
if (stackPartitions < 2) {
stackPartitions = 2;
}
let extraIndices = 0;
let vertexMultiplier = 1;
const hasInnerSurface = innerRadii.x !== radii.x || innerRadii.y !== radii.y || innerRadii.z !== radii.z;
let isTopOpen = false;
let isBotOpen = false;
if (hasInnerSurface) {
vertexMultiplier = 2;
if (minimumCone > 0) {
isTopOpen = true;
extraIndices += slicePartitions;
}
if (maximumCone < Math.PI) {
isBotOpen = true;
extraIndices += slicePartitions;
}
}
const vertexCount = subdivisions * vertexMultiplier * (stackPartitions + slicePartitions);
const positions = new Float64Array(vertexCount * 3);
const numIndices = 2 * (vertexCount + extraIndices - (slicePartitions + stackPartitions) * vertexMultiplier);
const indices = IndexDatatype_default.createTypedArray(vertexCount, numIndices);
let i;
let j;
let theta;
let phi;
let index = 0;
const sinPhi = new Array(stackPartitions);
const cosPhi = new Array(stackPartitions);
for (i = 0; i < stackPartitions; i++) {
phi = minimumCone + i * (maximumCone - minimumCone) / (stackPartitions - 1);
sinPhi[i] = sin2(phi);
cosPhi[i] = cos2(phi);
}
const sinTheta = new Array(subdivisions);
const cosTheta = new Array(subdivisions);
for (i = 0; i < subdivisions; i++) {
theta = minimumClock + i * (maximumClock - minimumClock) / (subdivisions - 1);
sinTheta[i] = sin2(theta);
cosTheta[i] = cos2(theta);
}
for (i = 0; i < stackPartitions; i++) {
for (j = 0; j < subdivisions; j++) {
positions[index++] = radii.x * sinPhi[i] * cosTheta[j];
positions[index++] = radii.y * sinPhi[i] * sinTheta[j];
positions[index++] = radii.z * cosPhi[i];
}
}
if (hasInnerSurface) {
for (i = 0; i < stackPartitions; i++) {
for (j = 0; j < subdivisions; j++) {
positions[index++] = innerRadii.x * sinPhi[i] * cosTheta[j];
positions[index++] = innerRadii.y * sinPhi[i] * sinTheta[j];
positions[index++] = innerRadii.z * cosPhi[i];
}
}
}
sinPhi.length = subdivisions;
cosPhi.length = subdivisions;
for (i = 0; i < subdivisions; i++) {
phi = minimumCone + i * (maximumCone - minimumCone) / (subdivisions - 1);
sinPhi[i] = sin2(phi);
cosPhi[i] = cos2(phi);
}
sinTheta.length = slicePartitions;
cosTheta.length = slicePartitions;
for (i = 0; i < slicePartitions; i++) {
theta = minimumClock + i * (maximumClock - minimumClock) / (slicePartitions - 1);
sinTheta[i] = sin2(theta);
cosTheta[i] = cos2(theta);
}
for (i = 0; i < subdivisions; i++) {
for (j = 0; j < slicePartitions; j++) {
positions[index++] = radii.x * sinPhi[i] * cosTheta[j];
positions[index++] = radii.y * sinPhi[i] * sinTheta[j];
positions[index++] = radii.z * cosPhi[i];
}
}
if (hasInnerSurface) {
for (i = 0; i < subdivisions; i++) {
for (j = 0; j < slicePartitions; j++) {
positions[index++] = innerRadii.x * sinPhi[i] * cosTheta[j];
positions[index++] = innerRadii.y * sinPhi[i] * sinTheta[j];
positions[index++] = innerRadii.z * cosPhi[i];
}
}
}
index = 0;
for (i = 0; i < stackPartitions * vertexMultiplier; i++) {
const topOffset = i * subdivisions;
for (j = 0; j < subdivisions - 1; j++) {
indices[index++] = topOffset + j;
indices[index++] = topOffset + j + 1;
}
}
let offset = stackPartitions * subdivisions * vertexMultiplier;
for (i = 0; i < slicePartitions; i++) {
for (j = 0; j < subdivisions - 1; j++) {
indices[index++] = offset + i + j * slicePartitions;
indices[index++] = offset + i + (j + 1) * slicePartitions;
}
}
if (hasInnerSurface) {
offset = stackPartitions * subdivisions * vertexMultiplier + slicePartitions * subdivisions;
for (i = 0; i < slicePartitions; i++) {
for (j = 0; j < subdivisions - 1; j++) {
indices[index++] = offset + i + j * slicePartitions;
indices[index++] = offset + i + (j + 1) * slicePartitions;
}
}
}
if (hasInnerSurface) {
let outerOffset = stackPartitions * subdivisions * vertexMultiplier;
let innerOffset = outerOffset + subdivisions * slicePartitions;
if (isTopOpen) {
for (i = 0; i < slicePartitions; i++) {
indices[index++] = outerOffset + i;
indices[index++] = innerOffset + i;
}
}
if (isBotOpen) {
outerOffset += subdivisions * slicePartitions - slicePartitions;
innerOffset += subdivisions * slicePartitions - slicePartitions;
for (i = 0; i < slicePartitions; i++) {
indices[index++] = outerOffset + i;
indices[index++] = innerOffset + i;
}
}
}
const attributes = new GeometryAttributes_default({
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
})
});
if (defined_default(ellipsoidGeometry._offsetAttribute)) {
const length2 = positions.length;
const offsetValue = ellipsoidGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.LINES,
boundingSphere: BoundingSphere_default.fromEllipsoid(ellipsoid),
offsetAttribute: ellipsoidGeometry._offsetAttribute
});
};
var EllipsoidOutlineGeometry_default = EllipsoidOutlineGeometry;
// packages/engine/Source/Core/SphereOutlineGeometry.js
function SphereOutlineGeometry(options) {
const radius = options.radius ?? 1;
const radii = new Cartesian3_default(radius, radius, radius);
const ellipsoidOptions = {
radii,
stackPartitions: options.stackPartitions,
slicePartitions: options.slicePartitions,
subdivisions: options.subdivisions
};
this._ellipsoidGeometry = new EllipsoidOutlineGeometry_default(ellipsoidOptions);
this._workerName = "createSphereOutlineGeometry";
}
SphereOutlineGeometry.packedLength = EllipsoidOutlineGeometry_default.packedLength;
SphereOutlineGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
return EllipsoidOutlineGeometry_default.pack(
value._ellipsoidGeometry,
array,
startingIndex
);
};
var scratchEllipsoidGeometry = new EllipsoidOutlineGeometry_default();
var scratchOptions6 = {
radius: void 0,
radii: new Cartesian3_default(),
stackPartitions: void 0,
slicePartitions: void 0,
subdivisions: void 0
};
SphereOutlineGeometry.unpack = function(array, startingIndex, result) {
const ellipsoidGeometry = EllipsoidOutlineGeometry_default.unpack(
array,
startingIndex,
scratchEllipsoidGeometry
);
scratchOptions6.stackPartitions = ellipsoidGeometry._stackPartitions;
scratchOptions6.slicePartitions = ellipsoidGeometry._slicePartitions;
scratchOptions6.subdivisions = ellipsoidGeometry._subdivisions;
if (!defined_default(result)) {
scratchOptions6.radius = ellipsoidGeometry._radii.x;
return new SphereOutlineGeometry(scratchOptions6);
}
Cartesian3_default.clone(ellipsoidGeometry._radii, scratchOptions6.radii);
result._ellipsoidGeometry = new EllipsoidOutlineGeometry_default(scratchOptions6);
return result;
};
SphereOutlineGeometry.createGeometry = function(sphereGeometry) {
return EllipsoidOutlineGeometry_default.createGeometry(
sphereGeometry._ellipsoidGeometry
);
};
var SphereOutlineGeometry_default = SphereOutlineGeometry;
// packages/engine/Source/Scene/TileBoundingSphere.js
function TileBoundingSphere(center, radius) {
if (radius === 0) {
radius = Math_default.EPSILON7;
}
this._boundingSphere = new BoundingSphere_default(center, radius);
}
Object.defineProperties(TileBoundingSphere.prototype, {
/**
* The center of the bounding sphere
*
* @memberof TileBoundingSphere.prototype
*
* @type {Cartesian3}
* @readonly
*/
center: {
get: function() {
return this._boundingSphere.center;
}
},
/**
* The radius of the bounding sphere
*
* @memberof TileBoundingSphere.prototype
*
* @type {number}
* @readonly
*/
radius: {
get: function() {
return this._boundingSphere.radius;
}
},
/**
* The underlying bounding volume
*
* @memberof TileBoundingSphere.prototype
*
* @type {object}
* @readonly
*/
boundingVolume: {
get: function() {
return this._boundingSphere;
}
},
/**
* The underlying bounding sphere
*
* @memberof TileBoundingSphere.prototype
*
* @type {BoundingSphere}
* @readonly
*/
boundingSphere: {
get: function() {
return this._boundingSphere;
}
}
});
TileBoundingSphere.prototype.distanceToCamera = function(frameState) {
Check_default.defined("frameState", frameState);
const boundingSphere = this._boundingSphere;
return Math.max(
0,
Cartesian3_default.distance(boundingSphere.center, frameState.camera.positionWC) - boundingSphere.radius
);
};
TileBoundingSphere.prototype.intersectPlane = function(plane) {
Check_default.defined("plane", plane);
return BoundingSphere_default.intersectPlane(this._boundingSphere, plane);
};
TileBoundingSphere.prototype.update = function(center, radius) {
Cartesian3_default.clone(center, this._boundingSphere.center);
this._boundingSphere.radius = radius;
};
TileBoundingSphere.prototype.createDebugVolume = function(color) {
Check_default.defined("color", color);
const geometry = new SphereOutlineGeometry_default({
radius: this.radius
});
const modelMatrix = Matrix4_default.fromTranslation(
this.center,
new Matrix4_default.clone(Matrix4_default.IDENTITY)
);
const instance = new GeometryInstance_default({
geometry,
id: "outline",
modelMatrix,
attributes: {
color: ColorGeometryInstanceAttribute_default.fromColor(color)
}
});
return new Primitive_default({
geometryInstances: instance,
appearance: new PerInstanceColorAppearance_default({
translucent: false,
flat: true
}),
asynchronous: false
});
};
var TileBoundingSphere_default = TileBoundingSphere;
// packages/engine/Source/Scene/TileOrientedBoundingBox.js
var import_InlineWorkers795 = __toESM(require_InlineWorkers(), 1);
var scratchU = new Cartesian3_default();
var scratchV = new Cartesian3_default();
var scratchW2 = new Cartesian3_default();
var scratchCartesian11 = new Cartesian3_default();
function computeMissingVector(a3, b, result) {
result = Cartesian3_default.cross(a3, b, result);
const magnitude = Cartesian3_default.magnitude(result);
return Cartesian3_default.multiplyByScalar(
result,
Math_default.EPSILON7 / magnitude,
result
);
}
function findOrthogonalVector(a3, result) {
const temp = Cartesian3_default.normalize(a3, scratchCartesian11);
const b = Cartesian3_default.equalsEpsilon(
temp,
Cartesian3_default.UNIT_X,
Math_default.EPSILON6
) ? Cartesian3_default.UNIT_Y : Cartesian3_default.UNIT_X;
return computeMissingVector(a3, b, result);
}
function checkHalfAxes(halfAxes) {
let u3 = Matrix3_default.getColumn(halfAxes, 0, scratchU);
let v3 = Matrix3_default.getColumn(halfAxes, 1, scratchV);
let w = Matrix3_default.getColumn(halfAxes, 2, scratchW2);
const uZero = Cartesian3_default.equals(u3, Cartesian3_default.ZERO);
const vZero = Cartesian3_default.equals(v3, Cartesian3_default.ZERO);
const wZero = Cartesian3_default.equals(w, Cartesian3_default.ZERO);
if (!uZero && !vZero && !wZero) {
return halfAxes;
}
if (uZero && vZero && wZero) {
halfAxes[0] = Math_default.EPSILON7;
halfAxes[4] = Math_default.EPSILON7;
halfAxes[8] = Math_default.EPSILON7;
return halfAxes;
}
if (uZero && !vZero && !wZero) {
u3 = computeMissingVector(v3, w, u3);
} else if (!uZero && vZero && !wZero) {
v3 = computeMissingVector(u3, w, v3);
} else if (!uZero && !vZero && wZero) {
w = computeMissingVector(v3, u3, w);
} else if (!uZero) {
v3 = findOrthogonalVector(u3, v3);
w = computeMissingVector(v3, u3, w);
} else if (!vZero) {
u3 = findOrthogonalVector(v3, u3);
w = computeMissingVector(v3, u3, w);
} else if (!wZero) {
u3 = findOrthogonalVector(w, u3);
v3 = computeMissingVector(w, u3, v3);
}
Matrix3_default.setColumn(halfAxes, 0, u3, halfAxes);
Matrix3_default.setColumn(halfAxes, 1, v3, halfAxes);
Matrix3_default.setColumn(halfAxes, 2, w, halfAxes);
return halfAxes;
}
function TileOrientedBoundingBox(center, halfAxes) {
halfAxes = checkHalfAxes(halfAxes);
this._orientedBoundingBox = new OrientedBoundingBox_default(center, halfAxes);
this._boundingSphere = BoundingSphere_default.fromOrientedBoundingBox(
this._orientedBoundingBox
);
}
Object.defineProperties(TileOrientedBoundingBox.prototype, {
/**
* The underlying bounding volume.
*
* @memberof TileOrientedBoundingBox.prototype
*
* @type {OrientedBoundingBox}
* @readonly
*/
boundingVolume: {
get: function() {
return this._orientedBoundingBox;
}
},
/**
* The underlying bounding sphere.
*
* @memberof TileOrientedBoundingBox.prototype
*
* @type {BoundingSphere}
* @readonly
*/
boundingSphere: {
get: function() {
return this._boundingSphere;
}
}
});
TileOrientedBoundingBox.prototype.distanceToCamera = function(frameState) {
Check_default.defined("frameState", frameState);
return Math.sqrt(
this._orientedBoundingBox.distanceSquaredTo(frameState.camera.positionWC)
);
};
TileOrientedBoundingBox.prototype.intersectPlane = function(plane) {
Check_default.defined("plane", plane);
return this._orientedBoundingBox.intersectPlane(plane);
};
TileOrientedBoundingBox.prototype.update = function(center, halfAxes) {
Cartesian3_default.clone(center, this._orientedBoundingBox.center);
halfAxes = checkHalfAxes(halfAxes);
Matrix3_default.clone(halfAxes, this._orientedBoundingBox.halfAxes);
BoundingSphere_default.fromOrientedBoundingBox(
this._orientedBoundingBox,
this._boundingSphere
);
};
TileOrientedBoundingBox.prototype.createDebugVolume = function(color) {
Check_default.defined("color", color);
const geometry = new BoxOutlineGeometry_default({
// Make a 2x2x2 cube
minimum: new Cartesian3_default(-1, -1, -1),
maximum: new Cartesian3_default(1, 1, 1)
});
const modelMatrix = Matrix4_default.fromRotationTranslation(
this.boundingVolume.halfAxes,
this.boundingVolume.center
);
const instance = new GeometryInstance_default({
geometry,
id: "outline",
modelMatrix,
attributes: {
color: ColorGeometryInstanceAttribute_default.fromColor(color)
}
});
return new Primitive_default({
geometryInstances: instance,
appearance: new PerInstanceColorAppearance_default({
translucent: false,
flat: true
}),
asynchronous: false
});
};
var TileOrientedBoundingBox_default = TileOrientedBoundingBox;
// packages/engine/Source/Scene/Cesium3DTile.js
function Cesium3DTile(tileset, baseResource2, header, parent) {
this._tileset = tileset;
this._header = header;
const hasContentsArray = defined_default(header.contents);
const hasMultipleContents = hasContentsArray && header.contents.length > 1 || hasExtension_default(header, "3DTILES_multiple_contents");
const contentHeader = hasContentsArray && !hasMultipleContents ? header.contents[0] : header.content;
this._contentHeader = contentHeader;
this.transform = defined_default(header.transform) ? Matrix4_default.unpack(header.transform) : Matrix4_default.clone(Matrix4_default.IDENTITY);
const parentTransform = defined_default(parent) ? parent.computedTransform : tileset.modelMatrix;
const computedTransform = Matrix4_default.multiply(
parentTransform,
this.transform,
new Matrix4_default()
);
const parentInitialTransform = defined_default(parent) ? parent._initialTransform : Matrix4_default.IDENTITY;
this._initialTransform = Matrix4_default.multiply(
parentInitialTransform,
this.transform,
new Matrix4_default()
);
this.computedTransform = computedTransform;
this.metadata = findTileMetadata_default(tileset, header);
this._verticalExaggeration = 1;
this._verticalExaggerationRelativeHeight = 0;
this._boundingVolume = this.createBoundingVolume(
header.boundingVolume,
computedTransform
);
this._boundingVolume2D = void 0;
let contentBoundingVolume;
if (defined_default(contentHeader) && defined_default(contentHeader.boundingVolume)) {
contentBoundingVolume = this.createBoundingVolume(
contentHeader.boundingVolume,
computedTransform
);
}
this._contentBoundingVolume = contentBoundingVolume;
this._contentBoundingVolume2D = void 0;
let viewerRequestVolume;
if (defined_default(header.viewerRequestVolume)) {
viewerRequestVolume = this.createBoundingVolume(
header.viewerRequestVolume,
computedTransform
);
}
this._viewerRequestVolume = viewerRequestVolume;
this.geometricError = header.geometricError;
this._geometricError = header.geometricError;
if (!defined_default(this._geometricError)) {
this._geometricError = defined_default(parent) ? parent._geometricError : tileset._geometricError;
Cesium3DTile._deprecationWarning(
"geometricErrorUndefined",
"Required property geometricError is undefined for this tile. Using parent's geometric error instead."
);
}
this.updateGeometricErrorScale();
let refine;
if (defined_default(header.refine)) {
if (header.refine === "replace" || header.refine === "add") {
Cesium3DTile._deprecationWarning(
"lowercase-refine",
`This tile uses a lowercase refine "${header.refine}". Instead use "${header.refine.toUpperCase()}".`
);
}
refine = header.refine.toUpperCase() === "REPLACE" ? Cesium3DTileRefine_default.REPLACE : Cesium3DTileRefine_default.ADD;
} else if (defined_default(parent)) {
refine = parent.refine;
} else {
refine = Cesium3DTileRefine_default.REPLACE;
}
this.refine = refine;
this.children = [];
this.parent = parent;
let content;
let hasEmptyContent = false;
let contentState;
let contentResource;
let serverKey;
baseResource2 = Resource_default.createIfNeeded(baseResource2);
if (hasMultipleContents) {
contentState = Cesium3DTileContentState_default.UNLOADED;
contentResource = baseResource2.clone();
} else if (defined_default(contentHeader)) {
let contentHeaderUri = contentHeader.uri;
if (defined_default(contentHeader.url)) {
Cesium3DTile._deprecationWarning(
"contentUrl",
'This tileset JSON uses the "content.url" property which has been deprecated. Use "content.uri" instead.'
);
contentHeaderUri = contentHeader.url;
}
if (contentHeaderUri === "") {
Cesium3DTile._deprecationWarning(
"contentUriEmpty",
"content.uri property is an empty string, which creates a circular dependency, making this tileset invalid. Omit the content property instead"
);
content = new Empty3DTileContent_default(tileset, this);
hasEmptyContent = true;
contentState = Cesium3DTileContentState_default.READY;
} else {
contentState = Cesium3DTileContentState_default.UNLOADED;
contentResource = baseResource2.getDerivedResource({
url: contentHeaderUri
});
serverKey = RequestScheduler_default.getServerKey(
contentResource.getUrlComponent()
);
}
} else {
content = new Empty3DTileContent_default(tileset, this);
hasEmptyContent = true;
contentState = Cesium3DTileContentState_default.READY;
}
this._content = content;
this._contentResource = contentResource;
this._contentState = contentState;
this._expiredContent = void 0;
this._serverKey = serverKey;
this.hasEmptyContent = hasEmptyContent;
this.hasTilesetContent = false;
this.hasImplicitContent = false;
this.hasRenderableContent = !hasEmptyContent;
this.hasImplicitContentMetadata = false;
this.hasMultipleContents = hasMultipleContents;
this.cacheNode = void 0;
const expire = header.expire;
let expireDuration;
let expireDate;
if (defined_default(expire)) {
expireDuration = expire.duration;
if (defined_default(expire.date)) {
expireDate = JulianDate_default.fromIso8601(expire.date);
}
}
this.expireDuration = expireDuration;
this.expireDate = expireDate;
this.lastStyleTime = 0;
this._optimChildrenWithinParent = Cesium3DTileOptimizationHint_default.NOT_COMPUTED;
this.clippingPlanesDirty = false;
this.clippingPolygonsDirty = false;
this.priorityDeferred = false;
this.implicitTileset = void 0;
this.implicitCoordinates = void 0;
this.implicitSubtree = void 0;
this._distanceToCamera = 0;
this._centerZDepth = 0;
this._screenSpaceError = 0;
this._screenSpaceErrorProgressiveResolution = 0;
this._visibilityPlaneMask = 0;
this._visible = false;
this._inRequestVolume = false;
this._finalResolution = true;
this._depth = 0;
this._stackLength = 0;
this._selectionDepth = 0;
this._updatedVisibilityFrame = 0;
this._touchedFrame = 0;
this._visitedFrame = 0;
this._selectedFrame = 0;
this._wasSelectedLastFrame = false;
this._requestedFrame = 0;
this._ancestorWithContent = void 0;
this._ancestorWithContentAvailable = void 0;
this._refines = false;
this._shouldSelect = false;
this._isClipped = true;
this._isClippedByPolygon = false;
this._clippingPlanesState = 0;
this._clippingPolygonsState = 0;
this._debugBoundingVolume = void 0;
this._debugContentBoundingVolume = void 0;
this._debugViewerRequestVolume = void 0;
this._debugColor = Color_default.fromRandom({ alpha: 1 });
this._debugColorizeTiles = false;
this._priority = 0;
this._priorityHolder = this;
this._priorityProgressiveResolution = false;
this._priorityProgressiveResolutionScreenSpaceErrorLeaf = false;
this._priorityReverseScreenSpaceError = 0;
this._foveatedFactor = 0;
this._wasMinPriorityChild = false;
this._loadTimestamp = new JulianDate_default();
this._commandsLength = 0;
this._color = void 0;
this._colorDirty = false;
this._request = void 0;
}
Cesium3DTile._deprecationWarning = deprecationWarning_default;
Object.defineProperties(Cesium3DTile.prototype, {
/**
* The tileset containing this tile.
*
* @memberof Cesium3DTile.prototype
*
* @type {Cesium3DTileset}
* @readonly
*/
tileset: {
get: function() {
return this._tileset;
}
},
/**
* The tile's content. This represents the actual tile's payload,
* not the content's metadata in the tileset JSON file.
*
* @memberof Cesium3DTile.prototype
*
* @type {Cesium3DTileContent}
* @readonly
*/
content: {
get: function() {
return this._content;
}
},
/**
* Get the tile's bounding volume.
*
* @memberof Cesium3DTile.prototype
*
* @type {TileBoundingVolume}
* @readonly
* @private
*/
boundingVolume: {
get: function() {
return this._boundingVolume;
}
},
/**
* Get the bounding volume of the tile's contents. This defaults to the
* tile's bounding volume when the content's bounding volume is
* undefined.
*
* @memberof Cesium3DTile.prototype
*
* @type {TileBoundingVolume}
* @readonly
* @private
*/
contentBoundingVolume: {
get: function() {
return this._contentBoundingVolume ?? this._boundingVolume;
}
},
/**
* Get the bounding sphere derived from the tile's bounding volume.
*
* @memberof Cesium3DTile.prototype
*
* @type {BoundingSphere}
* @readonly
*/
boundingSphere: {
get: function() {
return this._boundingVolume.boundingSphere;
}
},
/**
* Determines if the tile is visible within the current field of view
*
* @memberof Cesium3DTile.prototype
*
* @type {boolean}
* @readonly
*
* @private
*/
isVisible: {
get: function() {
return this._visible && this._inRequestVolume;
}
},
/**
* Returns the extras property in the tileset JSON for this tile, which contains application specific metadata.
* Returns undefined if extras does not exist.
*
* @memberof Cesium3DTile.prototype
*
* @type {object}
* @readonly
* @see {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification#specifying-extensions-and-application-specific-extras|Extras in the 3D Tiles specification.}
*/
extras: {
get: function() {
return this._header.extras;
}
},
/**
* Gets or sets the tile's highlight color.
*
* @memberof Cesium3DTile.prototype
*
* @type {Color}
*
* @default {@link Color.WHITE}
*
* @private
*/
color: {
get: function() {
if (!defined_default(this._color)) {
this._color = new Color_default();
}
return Color_default.clone(this._color);
},
set: function(value) {
this._color = Color_default.clone(value, this._color);
this._colorDirty = true;
}
},
/**
* Determines if the tile has available content to render. true if the tile's
* content is ready or if it has expired content that renders while new content loads; otherwise,
* false.
*
* @memberof Cesium3DTile.prototype
*
* @type {boolean}
* @readonly
*
* @private
*/
contentAvailable: {
get: function() {
return this.contentReady && this.hasRenderableContent || defined_default(this._expiredContent) && !this.contentFailed;
}
},
/**
* Determines if the tile's content is ready. This is automatically true for
* tile's with empty content.
*
* @memberof Cesium3DTile.prototype
*
* @type {boolean}
* @readonly
*
* @private
*/
contentReady: {
get: function() {
return this._contentState === Cesium3DTileContentState_default.READY;
}
},
/**
* Determines if the tile's content has not be requested. true if tile's
* content has not be requested; otherwise, false.
*
* @memberof Cesium3DTile.prototype
*
* @type {boolean}
* @readonly
*
* @private
*/
contentUnloaded: {
get: function() {
return this._contentState === Cesium3DTileContentState_default.UNLOADED;
}
},
/**
* Determines if the tile has renderable content which is unloaded
*
* @memberof Cesium3DTile.prototype
*
* @type {boolean}
* @readonly
*
* @private
*/
hasUnloadedRenderableContent: {
get: function() {
return this.hasRenderableContent && this.contentUnloaded;
}
},
/**
* Determines if the tile's content is expired. true if tile's
* content is expired; otherwise, false.
*
* @memberof Cesium3DTile.prototype
*
* @type {boolean}
* @readonly
*
* @private
*/
contentExpired: {
get: function() {
return this._contentState === Cesium3DTileContentState_default.EXPIRED;
}
},
/**
* Determines if the tile's content failed to load. true if the tile's
* content failed to load; otherwise, false.
*
* @memberof Cesium3DTile.prototype
*
* @type {boolean}
* @readonly
*
* @private
*/
contentFailed: {
get: function() {
return this._contentState === Cesium3DTileContentState_default.FAILED;
}
},
/**
* Returns the number of draw commands used by this tile.
*
* @readonly
*
* @private
*/
commandsLength: {
get: function() {
return this._commandsLength;
}
}
});
var scratchCartesian14 = new Cartesian3_default();
function isPriorityDeferred(tile, frameState) {
const { tileset, boundingSphere } = tile;
const { radius, center } = boundingSphere;
const { camera } = frameState;
const scaledCameraDirection = Cartesian3_default.multiplyByScalar(
camera.directionWC,
tile._centerZDepth,
scratchCartesian14
);
const closestPointOnLine = Cartesian3_default.add(
camera.positionWC,
scaledCameraDirection,
scratchCartesian14
);
const toLine = Cartesian3_default.subtract(
closestPointOnLine,
center,
scratchCartesian14
);
const distanceToCenterLine = Cartesian3_default.magnitude(toLine);
const notTouchingSphere = distanceToCenterLine > radius;
if (notTouchingSphere) {
const toLineNormalized = Cartesian3_default.normalize(toLine, scratchCartesian14);
const scaledToLine = Cartesian3_default.multiplyByScalar(
toLineNormalized,
radius,
scratchCartesian14
);
const closestOnSphere = Cartesian3_default.add(
center,
scaledToLine,
scratchCartesian14
);
const toClosestOnSphere = Cartesian3_default.subtract(
closestOnSphere,
camera.positionWC,
scratchCartesian14
);
const toClosestOnSphereNormalize = Cartesian3_default.normalize(
toClosestOnSphere,
scratchCartesian14
);
tile._foveatedFactor = 1 - Math.abs(Cartesian3_default.dot(camera.directionWC, toClosestOnSphereNormalize));
} else {
tile._foveatedFactor = 0;
}
const replace = tile.refine === Cesium3DTileRefine_default.REPLACE;
const skipLevelOfDetail = tileset.isSkippingLevelOfDetail;
if (replace && !skipLevelOfDetail || !tileset.foveatedScreenSpaceError || tileset.foveatedConeSize === 1 || tile._priorityProgressiveResolution && replace && skipLevelOfDetail || tileset._pass === Cesium3DTilePass_default.PRELOAD_FLIGHT || tileset._pass === Cesium3DTilePass_default.PRELOAD) {
return false;
}
const maximumFovatedFactor = 1 - Math.cos(camera.frustum.fov * 0.5);
const foveatedConeFactor = tileset.foveatedConeSize * maximumFovatedFactor;
if (tile._foveatedFactor <= foveatedConeFactor) {
return false;
}
const range = maximumFovatedFactor - foveatedConeFactor;
const normalizedFoveatedFactor = Math_default.clamp(
(tile._foveatedFactor - foveatedConeFactor) / range,
0,
1
);
const sseRelaxation = tileset.foveatedInterpolationCallback(
tileset.foveatedMinimumScreenSpaceErrorRelaxation,
tileset.memoryAdjustedScreenSpaceError,
normalizedFoveatedFactor
);
const sse = tile._screenSpaceError === 0 && defined_default(tile.parent) ? tile.parent._screenSpaceError * 0.5 : tile._screenSpaceError;
return tileset.memoryAdjustedScreenSpaceError - sseRelaxation <= sse;
}
var scratchJulianDate = new JulianDate_default();
Cesium3DTile.prototype.getScreenSpaceError = function(frameState, useParentGeometricError, progressiveResolutionHeightFraction) {
const tileset = this._tileset;
const heightFraction = progressiveResolutionHeightFraction ?? 1;
const parentGeometricError = defined_default(this.parent) ? this.parent.geometricError : tileset._scaledGeometricError;
const geometricError = useParentGeometricError ? parentGeometricError : this.geometricError;
if (geometricError === 0) {
return 0;
}
const { camera, context } = frameState;
let frustum = camera.frustum;
const width = context.drawingBufferWidth;
const height = context.drawingBufferHeight * heightFraction;
let error;
if (frameState.mode === SceneMode_default.SCENE2D || frustum instanceof OrthographicFrustum_default) {
const offCenterFrustum = frustum.offCenterFrustum;
if (defined_default(offCenterFrustum)) {
frustum = offCenterFrustum;
}
const pixelSize = Math.max(frustum.top - frustum.bottom, frustum.right - frustum.left) / Math.max(width, height);
error = geometricError / pixelSize;
} else {
const distance2 = Math.max(this._distanceToCamera, Math_default.EPSILON7);
const sseDenominator = frustum.sseDenominator;
error = geometricError * height / (distance2 * sseDenominator);
if (tileset.dynamicScreenSpaceError) {
const density = tileset._dynamicScreenSpaceErrorComputedDensity;
const factor2 = tileset.dynamicScreenSpaceErrorFactor;
const dynamicError = Math_default.fog(distance2, density) * factor2;
error -= dynamicError;
}
}
error /= frameState.pixelRatio;
return error;
};
function isPriorityProgressiveResolution(tileset, tile) {
if (tileset.progressiveResolutionHeightFraction <= 0 || tileset.progressiveResolutionHeightFraction > 0.5) {
return false;
}
const maximumScreenSpaceError = tileset.memoryAdjustedScreenSpaceError;
let isProgressiveResolutionTile = tile._screenSpaceErrorProgressiveResolution > maximumScreenSpaceError;
tile._priorityProgressiveResolutionScreenSpaceErrorLeaf = false;
const parent = tile.parent;
const tilePasses = tile._screenSpaceErrorProgressiveResolution <= maximumScreenSpaceError;
const parentFails = defined_default(parent) && parent._screenSpaceErrorProgressiveResolution > maximumScreenSpaceError;
if (tilePasses && parentFails) {
tile._priorityProgressiveResolutionScreenSpaceErrorLeaf = true;
isProgressiveResolutionTile = true;
}
return isProgressiveResolutionTile;
}
function getPriorityReverseScreenSpaceError(tileset, tile) {
const parent = tile.parent;
const useParentScreenSpaceError = defined_default(parent) && (!tileset.isSkippingLevelOfDetail || tile._screenSpaceError === 0 || parent.hasTilesetContent || parent.hasImplicitContent);
const screenSpaceError2 = useParentScreenSpaceError ? parent._screenSpaceError : tile._screenSpaceError;
return tileset.root._screenSpaceError - screenSpaceError2;
}
Cesium3DTile.prototype.updateVisibility = function(frameState) {
const { parent, tileset } = this;
if (this._updatedVisibilityFrame === tileset._updatedVisibilityFrame) {
return;
}
const parentTransform = defined_default(parent) ? parent.computedTransform : tileset.modelMatrix;
const parentVisibilityPlaneMask = defined_default(parent) ? parent._visibilityPlaneMask : CullingVolume_default.MASK_INDETERMINATE;
this.updateTransform(parentTransform, frameState);
this._distanceToCamera = this.distanceToTile(frameState);
this._centerZDepth = this.distanceToTileCenter(frameState);
this._screenSpaceError = this.getScreenSpaceError(frameState, false);
this._screenSpaceErrorProgressiveResolution = this.getScreenSpaceError(
frameState,
false,
tileset.progressiveResolutionHeightFraction
);
this._visibilityPlaneMask = this.visibility(
frameState,
parentVisibilityPlaneMask
);
this._visible = this._visibilityPlaneMask !== CullingVolume_default.MASK_OUTSIDE;
this._inRequestVolume = this.insideViewerRequestVolume(frameState);
this._priorityReverseScreenSpaceError = getPriorityReverseScreenSpaceError(
tileset,
this
);
this._priorityProgressiveResolution = isPriorityProgressiveResolution(
tileset,
this
);
this.priorityDeferred = isPriorityDeferred(this, frameState);
this._updatedVisibilityFrame = tileset._updatedVisibilityFrame;
};
Cesium3DTile.prototype.updateExpiration = function() {
if (defined_default(this.expireDate) && this.contentReady && !this.hasEmptyContent && !this.hasMultipleContents) {
const now2 = JulianDate_default.now(scratchJulianDate);
if (JulianDate_default.lessThan(this.expireDate, now2)) {
this._contentState = Cesium3DTileContentState_default.EXPIRED;
this._expiredContent = this._content;
}
}
};
function updateExpireDate(tile) {
if (!defined_default(tile.expireDuration)) {
return;
}
const expireDurationDate = JulianDate_default.now(scratchJulianDate);
JulianDate_default.addSeconds(
expireDurationDate,
tile.expireDuration,
expireDurationDate
);
if (defined_default(tile.expireDate)) {
if (JulianDate_default.lessThan(tile.expireDate, expireDurationDate)) {
JulianDate_default.clone(expireDurationDate, tile.expireDate);
}
} else {
tile.expireDate = JulianDate_default.clone(expireDurationDate);
}
}
function createPriorityFunction(tile) {
return function() {
return tile._priority;
};
}
Cesium3DTile.prototype.requestContent = function() {
if (this.hasEmptyContent) {
return;
}
if (this.hasMultipleContents) {
return requestMultipleContents(this);
}
return requestSingleContent(this);
};
function requestMultipleContents(tile) {
let multipleContents = tile._content;
const tileset = tile._tileset;
if (!defined_default(multipleContents)) {
const contentsJson = hasExtension_default(tile._header, "3DTILES_multiple_contents") ? tile._header.extensions["3DTILES_multiple_contents"] : tile._header;
multipleContents = new Multiple3DTileContent_default(
tileset,
tile,
tile._contentResource.clone(),
contentsJson
);
tile._content = multipleContents;
}
const promise = multipleContents.requestInnerContents();
if (!defined_default(promise)) {
return;
}
tile._contentState = Cesium3DTileContentState_default.LOADING;
return promise.then((content) => {
if (tile.isDestroyed()) {
return;
}
if (!defined_default(content)) {
return;
}
tile._contentState = Cesium3DTileContentState_default.PROCESSING;
return multipleContents;
}).catch((error) => {
if (tile.isDestroyed()) {
return;
}
tile._contentState = Cesium3DTileContentState_default.FAILED;
throw error;
});
}
async function processArrayBuffer(tile, tileset, request, expired, requestPromise) {
const previousState = tile._contentState;
tile._contentState = Cesium3DTileContentState_default.LOADING;
++tileset.statistics.numberOfPendingRequests;
let arrayBuffer;
try {
arrayBuffer = await requestPromise;
} catch (error) {
--tileset.statistics.numberOfPendingRequests;
if (tile.isDestroyed()) {
return;
}
if (request.cancelled || request.state === RequestState_default.CANCELLED) {
tile._contentState = previousState;
++tileset.statistics.numberOfAttemptedRequests;
return;
}
tile._contentState = Cesium3DTileContentState_default.FAILED;
throw error;
}
if (tile.isDestroyed()) {
--tileset.statistics.numberOfPendingRequests;
return;
}
if (request.cancelled || request.state === RequestState_default.CANCELLED) {
tile._contentState = previousState;
--tileset.statistics.numberOfPendingRequests;
++tileset.statistics.numberOfAttemptedRequests;
return;
}
try {
const content = await makeContent(tile, arrayBuffer);
--tileset.statistics.numberOfPendingRequests;
if (tile.isDestroyed()) {
return;
}
if (expired) {
tile.expireDate = void 0;
}
tile._content = content;
tile._contentState = Cesium3DTileContentState_default.PROCESSING;
return content;
} catch (error) {
--tileset.statistics.numberOfPendingRequests;
if (tile.isDestroyed()) {
return;
}
tile._contentState = Cesium3DTileContentState_default.FAILED;
throw error;
}
}
function requestSingleContent(tile) {
const resource = tile._contentResource.clone();
const expired = tile.contentExpired;
if (expired) {
resource.setQueryParameters({
expired: tile.expireDate.toString()
});
}
const request = new Request_default({
throttle: true,
throttleByServer: true,
type: RequestType_default.TILES3D,
priorityFunction: createPriorityFunction(tile),
serverKey: tile._serverKey
});
tile._request = request;
resource.request = request;
const tileset = tile._tileset;
const promise = resource.fetchArrayBuffer();
if (!defined_default(promise)) {
++tileset.statistics.numberOfAttemptedRequests;
return;
}
return processArrayBuffer(tile, tileset, request, expired, promise);
}
async function makeContent(tile, arrayBuffer) {
const preprocessed = preprocess3DTileContent_default(arrayBuffer);
const tileset = tile._tileset;
tileset._disableSkipLevelOfDetail = tileset._disableSkipLevelOfDetail || preprocessed.contentType === Cesium3DTileContentType_default.GEOMETRY || preprocessed.contentType === Cesium3DTileContentType_default.VECTOR;
if (preprocessed.contentType === Cesium3DTileContentType_default.IMPLICIT_SUBTREE || preprocessed.contentType === Cesium3DTileContentType_default.IMPLICIT_SUBTREE_JSON) {
tile.hasImplicitContent = true;
tile.hasRenderableContent = false;
}
if (preprocessed.contentType === Cesium3DTileContentType_default.EXTERNAL_TILESET) {
tile.hasTilesetContent = true;
tile.hasRenderableContent = false;
}
let content;
const contentFactory = Cesium3DTileContentFactory_default[preprocessed.contentType];
if (tile.isDestroyed()) {
return;
}
if (defined_default(preprocessed.binaryPayload)) {
content = await Promise.resolve(
contentFactory(
tileset,
tile,
tile._contentResource,
preprocessed.binaryPayload.buffer,
0
)
);
} else {
content = await Promise.resolve(
contentFactory(
tileset,
tile,
tile._contentResource,
preprocessed.jsonPayload
)
);
}
const contentHeader = tile._contentHeader;
if (tile.hasImplicitContentMetadata) {
const subtree = tile.implicitSubtree;
const coordinates = tile.implicitCoordinates;
content.metadata = subtree.getContentMetadataView(coordinates, 0);
} else if (!tile.hasImplicitContent) {
content.metadata = findContentMetadata_default(tileset, contentHeader);
}
const groupMetadata = findGroupMetadata_default(tileset, contentHeader);
if (defined_default(groupMetadata)) {
content.group = new Cesium3DContentGroup_default({
metadata: groupMetadata
});
}
return content;
}
Cesium3DTile.prototype.cancelRequests = function() {
if (this.hasMultipleContents) {
this._content.cancelRequests();
} else {
this._request.cancel();
}
};
Cesium3DTile.prototype.unloadContent = function() {
if (!this.hasRenderableContent) {
return;
}
this._content = this._content && this._content.destroy();
this._contentState = Cesium3DTileContentState_default.UNLOADED;
this.lastStyleTime = 0;
this.clippingPlanesDirty = this._clippingPlanesState === 0;
this._clippingPlanesState = 0;
this.clippingPolygonsDirty = this._clippingPolygonsState === 0;
this._clippingPolygonsState = 0;
this._debugColorizeTiles = false;
this._debugBoundingVolume = this._debugBoundingVolume && this._debugBoundingVolume.destroy();
this._debugContentBoundingVolume = this._debugContentBoundingVolume && this._debugContentBoundingVolume.destroy();
this._debugViewerRequestVolume = this._debugViewerRequestVolume && this._debugViewerRequestVolume.destroy();
};
var scratchProjectedBoundingSphere = new BoundingSphere_default();
function getBoundingVolume(tile, frameState) {
if (frameState.mode !== SceneMode_default.SCENE3D && !defined_default(tile._boundingVolume2D)) {
const boundingSphere = tile._boundingVolume.boundingSphere;
const sphere = BoundingSphere_default.projectTo2D(
boundingSphere,
frameState.mapProjection,
scratchProjectedBoundingSphere
);
tile._boundingVolume2D = new TileBoundingSphere_default(
sphere.center,
sphere.radius
);
}
return frameState.mode !== SceneMode_default.SCENE3D ? tile._boundingVolume2D : tile._boundingVolume;
}
function getContentBoundingVolume2(tile, frameState) {
if (frameState.mode !== SceneMode_default.SCENE3D && !defined_default(tile._contentBoundingVolume2D)) {
const boundingSphere = tile._contentBoundingVolume.boundingSphere;
const sphere = BoundingSphere_default.projectTo2D(
boundingSphere,
frameState.mapProjection,
scratchProjectedBoundingSphere
);
tile._contentBoundingVolume2D = new TileBoundingSphere_default(
sphere.center,
sphere.radius
);
}
return frameState.mode !== SceneMode_default.SCENE3D ? tile._contentBoundingVolume2D : tile._contentBoundingVolume;
}
Cesium3DTile.prototype.visibility = function(frameState, parentVisibilityPlaneMask) {
const cullingVolume = frameState.cullingVolume;
const boundingVolume = getBoundingVolume(this, frameState);
const tileset = this._tileset;
const clippingPlanes = tileset.clippingPlanes;
if (defined_default(clippingPlanes) && clippingPlanes.enabled) {
const intersection = clippingPlanes.computeIntersectionWithBoundingVolume(
boundingVolume,
tileset.clippingPlanesOriginMatrix
);
this._isClipped = intersection !== Intersect_default.INSIDE;
if (intersection === Intersect_default.OUTSIDE) {
return CullingVolume_default.MASK_OUTSIDE;
}
}
const clippingPolygons = tileset.clippingPolygons;
if (defined_default(clippingPolygons) && clippingPolygons.enabled) {
const intersection = clippingPolygons.computeIntersectionWithBoundingVolume(boundingVolume);
this._isClippedByPolygon = intersection !== Intersect_default.OUTSIDE;
}
return cullingVolume.computeVisibilityWithPlaneMask(
boundingVolume,
parentVisibilityPlaneMask
);
};
Cesium3DTile.prototype.contentVisibility = function(frameState) {
if (!defined_default(this._contentBoundingVolume)) {
return Intersect_default.INSIDE;
}
if (this._visibilityPlaneMask === CullingVolume_default.MASK_INSIDE) {
return Intersect_default.INSIDE;
}
const cullingVolume = frameState.cullingVolume;
const boundingVolume = getContentBoundingVolume2(this, frameState);
const tileset = this._tileset;
const clippingPlanes = tileset.clippingPlanes;
if (defined_default(clippingPlanes) && clippingPlanes.enabled) {
const intersection = clippingPlanes.computeIntersectionWithBoundingVolume(
boundingVolume,
tileset.clippingPlanesOriginMatrix
);
this._isClipped = intersection !== Intersect_default.INSIDE;
if (intersection === Intersect_default.OUTSIDE) {
return Intersect_default.OUTSIDE;
}
}
const clippingPolygons = tileset.clippingPolygons;
if (defined_default(clippingPolygons) && clippingPolygons.enabled) {
const intersection = clippingPolygons.computeIntersectionWithBoundingVolume(boundingVolume);
this._isClippedByPolygon = intersection !== Intersect_default.OUTSIDE;
if (intersection === Intersect_default.INSIDE) {
return Intersect_default.OUTSIDE;
}
}
return cullingVolume.computeVisibility(boundingVolume);
};
Cesium3DTile.prototype.distanceToTile = function(frameState) {
const boundingVolume = getBoundingVolume(this, frameState);
return boundingVolume.distanceToCamera(frameState);
};
var scratchToTileCenter = new Cartesian3_default();
Cesium3DTile.prototype.distanceToTileCenter = function(frameState) {
const tileBoundingVolume = getBoundingVolume(this, frameState);
const boundingVolume = tileBoundingVolume.boundingVolume;
const toCenter = Cartesian3_default.subtract(
boundingVolume.center,
frameState.camera.positionWC,
scratchToTileCenter
);
return Cartesian3_default.dot(frameState.camera.directionWC, toCenter);
};
Cesium3DTile.prototype.insideViewerRequestVolume = function(frameState) {
const viewerRequestVolume = this._viewerRequestVolume;
return !defined_default(viewerRequestVolume) || viewerRequestVolume.distanceToCamera(frameState) === 0;
};
var scratchMatrix4 = new Matrix3_default();
var scratchScale3 = new Cartesian3_default();
var scratchHalfAxes2 = new Matrix3_default();
var scratchCenter4 = new Cartesian3_default();
var scratchRectangle5 = new Rectangle_default();
var scratchOrientedBoundingBox = new OrientedBoundingBox_default();
var scratchTransform = new Matrix4_default();
function createBox(box, transform3, result) {
let center = Cartesian3_default.fromElements(box[0], box[1], box[2], scratchCenter4);
let halfAxes = Matrix3_default.fromArray(box, 3, scratchHalfAxes2);
center = Matrix4_default.multiplyByPoint(transform3, center, center);
const rotationScale = Matrix4_default.getMatrix3(transform3, scratchMatrix4);
halfAxes = Matrix3_default.multiply(rotationScale, halfAxes, halfAxes);
if (defined_default(result)) {
result.update(center, halfAxes);
return result;
}
return new TileOrientedBoundingBox_default(center, halfAxes);
}
function createBoxFromTransformedRegion(region, transform3, initialTransform, result) {
const rectangle = Rectangle_default.unpack(region, 0, scratchRectangle5);
const minimumHeight = region[4];
const maximumHeight = region[5];
const orientedBoundingBox = OrientedBoundingBox_default.fromRectangle(
rectangle,
minimumHeight,
maximumHeight,
Ellipsoid_default.WGS84,
scratchOrientedBoundingBox
);
let center = orientedBoundingBox.center;
let halfAxes = orientedBoundingBox.halfAxes;
transform3 = Matrix4_default.multiplyTransformation(
transform3,
Matrix4_default.inverseTransformation(initialTransform, scratchTransform),
scratchTransform
);
center = Matrix4_default.multiplyByPoint(transform3, center, center);
const rotationScale = Matrix4_default.getMatrix3(transform3, scratchMatrix4);
halfAxes = Matrix3_default.multiply(rotationScale, halfAxes, halfAxes);
if (defined_default(result) && result instanceof TileOrientedBoundingBox_default) {
result.update(center, halfAxes);
return result;
}
return new TileOrientedBoundingBox_default(center, halfAxes);
}
function createRegion(region, transform3, initialTransform, result) {
if (!Matrix4_default.equalsEpsilon(transform3, initialTransform, Math_default.EPSILON8)) {
if (result instanceof TileOrientedBoundingBox_default) {
return createBoxFromTransformedRegion(
region,
transform3,
initialTransform,
result
);
}
return createBoxFromTransformedRegion(
region,
transform3,
initialTransform,
void 0
);
}
const rectangleRegion = Rectangle_default.unpack(region, 0, scratchRectangle5);
if (result instanceof TileBoundingRegion_default) {
result.rectangle = Rectangle_default.clone(rectangleRegion, result.rectangle);
result.minimumHeight = region[4];
result.maximumHeight = region[5];
result.computeBoundingVolumes(Ellipsoid_default.WGS84);
return result;
}
return new TileBoundingRegion_default({
rectangle: rectangleRegion,
minimumHeight: region[4],
maximumHeight: region[5]
});
}
function createSphere(sphere, transform3, result) {
let center = Cartesian3_default.fromElements(
sphere[0],
sphere[1],
sphere[2],
scratchCenter4
);
let radius = sphere[3];
center = Matrix4_default.multiplyByPoint(transform3, center, center);
const scale = Matrix4_default.getScale(transform3, scratchScale3);
const uniformScale = Cartesian3_default.maximumComponent(scale);
radius *= uniformScale;
if (defined_default(result)) {
result.update(center, radius);
return result;
}
return new TileBoundingSphere_default(center, radius);
}
Cesium3DTile.prototype.createBoundingVolume = function(boundingVolumeHeader, transform3, result) {
const tileMetadata = this.metadata;
let metadataBoundingVolumeHeader;
if (defined_default(tileMetadata)) {
metadataBoundingVolumeHeader = BoundingVolumeSemantics_default.parseBoundingVolumeSemantic("TILE", tileMetadata);
}
if (defined_default(metadataBoundingVolumeHeader)) {
boundingVolumeHeader = metadataBoundingVolumeHeader;
}
if (!defined_default(boundingVolumeHeader)) {
throw new RuntimeError_default("boundingVolume must be defined");
}
if (hasExtension_default(boundingVolumeHeader, "3DTILES_bounding_volume_S2")) {
return new TileBoundingS2Cell_default(
boundingVolumeHeader.extensions["3DTILES_bounding_volume_S2"]
);
}
const { box, region, sphere } = boundingVolumeHeader;
if (defined_default(box)) {
const tileOrientedBoundingBox = createBox(box, transform3, result);
if (this._verticalExaggeration !== 1) {
exaggerateBoundingBox(
tileOrientedBoundingBox,
this._verticalExaggeration,
this._verticalExaggerationRelativeHeight
);
}
return tileOrientedBoundingBox;
}
if (defined_default(region)) {
const tileBoundingVolume = createRegion(
region,
transform3,
this._initialTransform,
result
);
if (this._verticalExaggeration === 1) {
return tileBoundingVolume;
}
if (tileBoundingVolume instanceof TileOrientedBoundingBox_default) {
exaggerateBoundingBox(
tileBoundingVolume,
this._verticalExaggeration,
this._verticalExaggerationRelativeHeight
);
} else {
tileBoundingVolume.minimumHeight = VerticalExaggeration_default.getHeight(
tileBoundingVolume.minimumHeight,
this._verticalExaggeration,
this._verticalExaggerationRelativeHeight
);
tileBoundingVolume.maximumHeight = VerticalExaggeration_default.getHeight(
tileBoundingVolume.maximumHeight,
this._verticalExaggeration,
this._verticalExaggerationRelativeHeight
);
tileBoundingVolume.computeBoundingVolumes(Ellipsoid_default.WGS84);
}
return tileBoundingVolume;
}
if (defined_default(sphere)) {
const tileBoundingSphere = createSphere(sphere, transform3, result);
if (this._verticalExaggeration !== 1) {
const exaggeratedCenter = VerticalExaggeration_default.getPosition(
tileBoundingSphere.center,
Ellipsoid_default.WGS84,
this._verticalExaggeration,
this._verticalExaggerationRelativeHeight,
scratchCenter4
);
const exaggeratedRadius = tileBoundingSphere.radius * this._verticalExaggeration;
tileBoundingSphere.update(exaggeratedCenter, exaggeratedRadius);
}
return tileBoundingSphere;
}
throw new RuntimeError_default(
"boundingVolume must contain a sphere, region, or box"
);
};
var scratchExaggeratedCorners = Cartesian3_default.unpackArray(
new Array(8 * 3).fill(0)
);
function exaggerateBoundingBox(tileOrientedBoundingBox, exaggeration, exaggerationRelativeHeight) {
const exaggeratedCorners = tileOrientedBoundingBox.boundingVolume.computeCorners(scratchExaggeratedCorners).map(
(corner) => VerticalExaggeration_default.getPosition(
corner,
Ellipsoid_default.WGS84,
exaggeration,
exaggerationRelativeHeight,
corner
)
);
const exaggeratedBox = OrientedBoundingBox_default.fromPoints(
exaggeratedCorners,
scratchOrientedBoundingBox
);
tileOrientedBoundingBox.update(
exaggeratedBox.center,
exaggeratedBox.halfAxes
);
}
Cesium3DTile.prototype.updateTransform = function(parentTransform, frameState) {
parentTransform = parentTransform ?? Matrix4_default.IDENTITY;
const computedTransform = Matrix4_default.multiplyTransformation(
parentTransform,
this.transform,
scratchTransform
);
const transformChanged = !Matrix4_default.equals(
computedTransform,
this.computedTransform
);
const exaggerationChanged = defined_default(frameState) && (this._verticalExaggeration !== frameState.verticalExaggeration || this._verticalExaggerationRelativeHeight !== frameState.verticalExaggerationRelativeHeight);
if (!transformChanged && !exaggerationChanged) {
return;
}
if (transformChanged) {
Matrix4_default.clone(computedTransform, this.computedTransform);
}
if (exaggerationChanged) {
this._verticalExaggeration = frameState.verticalExaggeration;
this._verticalExaggerationRelativeHeight = frameState.verticalExaggerationRelativeHeight;
}
const header = this._header;
const contentHeader = this._contentHeader;
this._boundingVolume = this.createBoundingVolume(
header.boundingVolume,
this.computedTransform,
this._boundingVolume
);
if (defined_default(this._contentBoundingVolume)) {
this._contentBoundingVolume = this.createBoundingVolume(
contentHeader.boundingVolume,
this.computedTransform,
this._contentBoundingVolume
);
}
if (defined_default(this._viewerRequestVolume)) {
this._viewerRequestVolume = this.createBoundingVolume(
header.viewerRequestVolume,
this.computedTransform,
this._viewerRequestVolume
);
}
this.updateGeometricErrorScale();
this._debugBoundingVolume = this._debugBoundingVolume && this._debugBoundingVolume.destroy();
this._debugContentBoundingVolume = this._debugContentBoundingVolume && this._debugContentBoundingVolume.destroy();
this._debugViewerRequestVolume = this._debugViewerRequestVolume && this._debugViewerRequestVolume.destroy();
};
Cesium3DTile.prototype.updateGeometricErrorScale = function() {
const scale = Matrix4_default.getScale(this.computedTransform, scratchScale3);
const uniformScale = Cartesian3_default.maximumComponent(scale);
this.geometricError = this._geometricError * uniformScale;
if (!defined_default(this.parent)) {
const tileset = this._tileset;
tileset._scaledGeometricError = tileset._geometricError * uniformScale;
}
};
function applyDebugSettings(tile, tileset, frameState, passOptions2) {
if (!passOptions2.isRender) {
return;
}
const hasContentBoundingVolume = defined_default(tile._contentHeader) && defined_default(tile._contentHeader.boundingVolume);
const showVolume = tileset.debugShowBoundingVolume || tileset.debugShowContentBoundingVolume && !hasContentBoundingVolume;
if (showVolume) {
let color;
if (!tile._finalResolution) {
color = Color_default.YELLOW;
} else if (!tile.hasRenderableContent) {
color = Color_default.DARKGRAY;
} else {
color = Color_default.WHITE;
}
if (!defined_default(tile._debugBoundingVolume)) {
tile._debugBoundingVolume = tile._boundingVolume.createDebugVolume(color);
}
tile._debugBoundingVolume.update(frameState);
const attributes = tile._debugBoundingVolume.getGeometryInstanceAttributes("outline");
attributes.color = ColorGeometryInstanceAttribute_default.toValue(
color,
attributes.color
);
} else if (!showVolume && defined_default(tile._debugBoundingVolume)) {
tile._debugBoundingVolume = tile._debugBoundingVolume.destroy();
}
if (tileset.debugShowContentBoundingVolume && hasContentBoundingVolume) {
if (!defined_default(tile._debugContentBoundingVolume)) {
tile._debugContentBoundingVolume = tile._contentBoundingVolume.createDebugVolume(Color_default.BLUE);
}
tile._debugContentBoundingVolume.update(frameState);
} else if (!tileset.debugShowContentBoundingVolume && defined_default(tile._debugContentBoundingVolume)) {
tile._debugContentBoundingVolume = tile._debugContentBoundingVolume.destroy();
}
if (tileset.debugShowViewerRequestVolume && defined_default(tile._viewerRequestVolume)) {
if (!defined_default(tile._debugViewerRequestVolume)) {
tile._debugViewerRequestVolume = tile._viewerRequestVolume.createDebugVolume(Color_default.YELLOW);
}
tile._debugViewerRequestVolume.update(frameState);
} else if (!tileset.debugShowViewerRequestVolume && defined_default(tile._debugViewerRequestVolume)) {
tile._debugViewerRequestVolume = tile._debugViewerRequestVolume.destroy();
}
const debugColorizeTilesOn = tileset.debugColorizeTiles && !tile._debugColorizeTiles || defined_default(tileset._heatmap.tilePropertyName);
const debugColorizeTilesOff = !tileset.debugColorizeTiles && tile._debugColorizeTiles;
if (debugColorizeTilesOn) {
tileset._heatmap.colorize(tile, frameState);
tile._debugColorizeTiles = true;
tile.color = tile._debugColor;
} else if (debugColorizeTilesOff) {
tile._debugColorizeTiles = false;
tile.color = Color_default.WHITE;
}
if (tile._colorDirty) {
tile._colorDirty = false;
tile._content.applyDebugSettings(true, tile._color);
}
if (debugColorizeTilesOff) {
tileset.makeStyleDirty();
}
}
function updateContent(tile, tileset, frameState) {
const expiredContent = tile._expiredContent;
if (!tile.hasMultipleContents && defined_default(expiredContent)) {
if (!tile.contentReady) {
try {
expiredContent.update(tileset, frameState);
} catch (error) {
}
return;
}
tile._expiredContent.destroy();
tile._expiredContent = void 0;
}
if (!defined_default(tile.content)) {
return;
}
try {
tile.content.update(tileset, frameState);
} catch (error) {
tile._contentState = Cesium3DTileContentState_default.FAILED;
throw error;
}
}
function updateClippingPlanes2(tile, tileset) {
const clippingPlanes = tileset.clippingPlanes;
let currentClippingPlanesState = 0;
if (defined_default(clippingPlanes) && tile._isClipped && clippingPlanes.enabled) {
currentClippingPlanesState = clippingPlanes.clippingPlanesState;
}
if (currentClippingPlanesState !== tile._clippingPlanesState) {
tile._clippingPlanesState = currentClippingPlanesState;
tile.clippingPlanesDirty = true;
}
}
function updateClippingPolygons2(tile, tileset) {
const clippingPolygons = tileset.clippingPolygons;
let currentClippingPolygonsState = 0;
if (defined_default(clippingPolygons) && tile._isClippedByPolygon && clippingPolygons.enabled) {
currentClippingPolygonsState = clippingPolygons.clippingPolygonsState;
}
if (currentClippingPolygonsState !== tile._clippingPolygonsState) {
tile._clippingPolygonsState = currentClippingPolygonsState;
tile.clippingPolygonsDirty = true;
}
}
Cesium3DTile.prototype.update = function(tileset, frameState, passOptions2) {
const { commandList } = frameState;
const commandStart = commandList.length;
updateClippingPlanes2(this, tileset);
updateClippingPolygons2(this, tileset);
applyDebugSettings(this, tileset, frameState, passOptions2);
updateContent(this, tileset, frameState);
const commandEnd = commandList.length;
this._commandsLength = commandEnd - commandStart;
for (let i = commandStart; i < commandEnd; ++i) {
const command = commandList[i];
const translucent = command.pass === Pass_default.TRANSLUCENT;
command.depthForTranslucentClassification = translucent;
}
this.clippingPlanesDirty = false;
this.clippingPolygonsDirty = false;
};
var scratchCommandList = [];
Cesium3DTile.prototype.process = function(tileset, frameState) {
if (!this.contentExpired && !this.contentReady && this._content.ready) {
updateExpireDate(this);
this._selectedFrame = 0;
this.lastStyleTime = 0;
JulianDate_default.now(this._loadTimestamp);
this._contentState = Cesium3DTileContentState_default.READY;
if (!this.hasTilesetContent && !this.hasImplicitContent) {
tileset._statistics.incrementLoadCounts(this.content);
++tileset._statistics.numberOfTilesWithContentReady;
++tileset._statistics.numberOfLoadedTilesTotal;
tileset._cache.add(this);
}
}
const savedCommandList = frameState.commandList;
frameState.commandList = scratchCommandList;
try {
this._content.update(tileset, frameState);
} catch (error) {
this._contentState = Cesium3DTileContentState_default.FAILED;
throw error;
}
scratchCommandList.length = 0;
frameState.commandList = savedCommandList;
};
function isolateDigits(normalizedValue, numberOfDigits, leftShift) {
const scaled = normalizedValue * Math.pow(10, numberOfDigits);
const integer = parseInt(scaled);
return integer * Math.pow(10, leftShift);
}
function priorityNormalizeAndClamp(value, minimum, maximum) {
return Math.max(
Math_default.normalize(value, minimum, maximum) - Math_default.EPSILON7,
0
);
}
Cesium3DTile.prototype.updatePriority = function() {
const tileset = this.tileset;
const preferLeaves = tileset.preferLeaves;
const minimumPriority = tileset._minimumPriority;
const maximumPriority = tileset._maximumPriority;
const digitsForANumber = 4;
const digitsForABoolean = 1;
const preferredSortingLeftShift = 0;
const preferredSortingDigitsCount = digitsForANumber;
const foveatedLeftShift = preferredSortingLeftShift + preferredSortingDigitsCount;
const foveatedDigitsCount = digitsForANumber;
const preloadProgressiveResolutionLeftShift = foveatedLeftShift + foveatedDigitsCount;
const preloadProgressiveResolutionDigitsCount = digitsForABoolean;
const preloadProgressiveResolutionScale = Math.pow(
10,
preloadProgressiveResolutionLeftShift
);
const foveatedDeferLeftShift = preloadProgressiveResolutionLeftShift + preloadProgressiveResolutionDigitsCount;
const foveatedDeferDigitsCount = digitsForABoolean;
const foveatedDeferScale = Math.pow(10, foveatedDeferLeftShift);
const preloadFlightLeftShift = foveatedDeferLeftShift + foveatedDeferDigitsCount;
const preloadFlightScale = Math.pow(10, preloadFlightLeftShift);
let depthDigits = priorityNormalizeAndClamp(
this._depth,
minimumPriority.depth,
maximumPriority.depth
);
depthDigits = preferLeaves ? 1 - depthDigits : depthDigits;
const useDistance = !tileset.isSkippingLevelOfDetail && this.refine === Cesium3DTileRefine_default.REPLACE;
const normalizedPreferredSorting = useDistance ? priorityNormalizeAndClamp(
this._priorityHolder._distanceToCamera,
minimumPriority.distance,
maximumPriority.distance
) : priorityNormalizeAndClamp(
this._priorityReverseScreenSpaceError,
minimumPriority.reverseScreenSpaceError,
maximumPriority.reverseScreenSpaceError
);
const preferredSortingDigits = isolateDigits(
normalizedPreferredSorting,
preferredSortingDigitsCount,
preferredSortingLeftShift
);
const preloadProgressiveResolutionDigits = this._priorityProgressiveResolution ? 0 : preloadProgressiveResolutionScale;
const normalizedFoveatedFactor = priorityNormalizeAndClamp(
this._priorityHolder._foveatedFactor,
minimumPriority.foveatedFactor,
maximumPriority.foveatedFactor
);
const foveatedDigits = isolateDigits(
normalizedFoveatedFactor,
foveatedDigitsCount,
foveatedLeftShift
);
const foveatedDeferDigits = this.priorityDeferred ? foveatedDeferScale : 0;
const preloadFlightDigits = tileset._pass === Cesium3DTilePass_default.PRELOAD_FLIGHT ? 0 : preloadFlightScale;
this._priority = depthDigits + preferredSortingDigits + preloadProgressiveResolutionDigits + foveatedDigits + foveatedDeferDigits + preloadFlightDigits;
};
Cesium3DTile.prototype.isDestroyed = function() {
return false;
};
Cesium3DTile.prototype.destroy = function() {
this._content = this._content && this._content.destroy();
this._expiredContent = this._expiredContent && !this._expiredContent.isDestroyed() && this._expiredContent.destroy();
this._debugBoundingVolume = this._debugBoundingVolume && this._debugBoundingVolume.destroy();
this._debugContentBoundingVolume = this._debugContentBoundingVolume && this._debugContentBoundingVolume.destroy();
this._debugViewerRequestVolume = this._debugViewerRequestVolume && this._debugViewerRequestVolume.destroy();
return destroyObject_default(this);
};
var Cesium3DTile_default = Cesium3DTile;
// packages/engine/Source/Scene/Cesium3DTilesetMetadata.js
var import_InlineWorkers799 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/GroupMetadata.js
var import_InlineWorkers797 = __toESM(require_InlineWorkers(), 1);
function GroupMetadata(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const id = options.id;
const group = options.group;
const metadataClass = options.class;
Check_default.typeOf.object("options.group", group);
Check_default.typeOf.object("options.class", metadataClass);
const properties = defined_default(group.properties) ? group.properties : {};
this._class = metadataClass;
this._properties = properties;
this._id = id;
this._extras = group.extras;
this._extensions = group.extensions;
}
Object.defineProperties(GroupMetadata.prototype, {
/**
* The class that properties conform to.
*
* @memberof GroupMetadata.prototype
* @type {MetadataClass}
* @readonly
* @private
*/
class: {
get: function() {
return this._class;
}
},
/**
* The ID of the group.
*
* @memberof GroupMetadata.prototype
* @type {string}
* @readonly
* @private
*/
id: {
get: function() {
return this._id;
}
},
/**
* Extra user-defined properties.
*
* @memberof GroupMetadata.prototype
* @type {*}
* @readonly
* @private
*/
extras: {
get: function() {
return this._extras;
}
},
/**
* An object containing extensions.
*
* @memberof GroupMetadata.prototype
* @type {object}
* @readonly
* @private
*/
extensions: {
get: function() {
return this._extensions;
}
}
});
GroupMetadata.prototype.hasProperty = function(propertyId) {
return MetadataEntity_default.hasProperty(propertyId, this._properties, this._class);
};
GroupMetadata.prototype.hasPropertyBySemantic = function(semantic) {
return MetadataEntity_default.hasPropertyBySemantic(
semantic,
this._properties,
this._class
);
};
GroupMetadata.prototype.getPropertyIds = function(results) {
return MetadataEntity_default.getPropertyIds(this._properties, this._class, results);
};
GroupMetadata.prototype.getProperty = function(propertyId) {
return MetadataEntity_default.getProperty(propertyId, this._properties, this._class);
};
GroupMetadata.prototype.setProperty = function(propertyId, value) {
return MetadataEntity_default.setProperty(
propertyId,
value,
this._properties,
this._class
);
};
GroupMetadata.prototype.getPropertyBySemantic = function(semantic) {
return MetadataEntity_default.getPropertyBySemantic(
semantic,
this._properties,
this._class
);
};
GroupMetadata.prototype.setPropertyBySemantic = function(semantic, value) {
return MetadataEntity_default.setPropertyBySemantic(
semantic,
value,
this._properties,
this._class
);
};
var GroupMetadata_default = GroupMetadata;
// packages/engine/Source/Scene/TilesetMetadata.js
var import_InlineWorkers798 = __toESM(require_InlineWorkers(), 1);
function TilesetMetadata(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const tileset = options.tileset;
const metadataClass = options.class;
Check_default.typeOf.object("options.tileset", tileset);
Check_default.typeOf.object("options.class", metadataClass);
const properties = defined_default(tileset.properties) ? tileset.properties : {};
this._class = metadataClass;
this._properties = properties;
this._extras = tileset.extras;
this._extensions = tileset.extensions;
}
Object.defineProperties(TilesetMetadata.prototype, {
/**
* The class that properties conform to.
*
* @memberof TilesetMetadata.prototype
* @type {MetadataClass}
* @readonly
* @private
*/
class: {
get: function() {
return this._class;
}
},
/**
* Extra user-defined properties.
*
* @memberof TilesetMetadata.prototype
* @type {*}
* @readonly
* @private
*/
extras: {
get: function() {
return this._extras;
}
},
/**
* An object containing extensions.
*
* @memberof TilesetMetadata.prototype
* @type {object}
* @readonly
* @private
*/
extensions: {
get: function() {
return this._extensions;
}
}
});
TilesetMetadata.prototype.hasProperty = function(propertyId) {
return MetadataEntity_default.hasProperty(propertyId, this._properties, this._class);
};
TilesetMetadata.prototype.hasPropertyBySemantic = function(semantic) {
return MetadataEntity_default.hasPropertyBySemantic(
semantic,
this._properties,
this._class
);
};
TilesetMetadata.prototype.getPropertyIds = function(results) {
return MetadataEntity_default.getPropertyIds(this._properties, this._class, results);
};
TilesetMetadata.prototype.getProperty = function(propertyId) {
return MetadataEntity_default.getProperty(propertyId, this._properties, this._class);
};
TilesetMetadata.prototype.setProperty = function(propertyId, value) {
return MetadataEntity_default.setProperty(
propertyId,
value,
this._properties,
this._class
);
};
TilesetMetadata.prototype.getPropertyBySemantic = function(semantic) {
return MetadataEntity_default.getPropertyBySemantic(
semantic,
this._properties,
this._class
);
};
TilesetMetadata.prototype.setPropertyBySemantic = function(semantic, value) {
return MetadataEntity_default.setPropertyBySemantic(
semantic,
value,
this._properties,
this._class
);
};
var TilesetMetadata_default = TilesetMetadata;
// packages/engine/Source/Scene/Cesium3DTilesetMetadata.js
function Cesium3DTilesetMetadata(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const metadataJson = options.metadataJson;
const schema = options.schema;
Check_default.typeOf.object("options.metadataJson", metadataJson);
Check_default.typeOf.object("options.schema", schema);
const metadata = metadataJson.metadata ?? metadataJson.tileset;
let tileset;
if (defined_default(metadata)) {
tileset = new TilesetMetadata_default({
tileset: metadata,
class: schema.classes[metadata.class]
});
}
let groupIds = [];
const groups = [];
const groupsJson = metadataJson.groups;
if (Array.isArray(groupsJson)) {
const length2 = groupsJson.length;
for (let i = 0; i < length2; i++) {
const group = groupsJson[i];
groups.push(
new GroupMetadata_default({
group,
class: schema.classes[group.class]
})
);
}
} else if (defined_default(groupsJson)) {
groupIds = Object.keys(groupsJson).sort();
const length2 = groupIds.length;
for (let i = 0; i < length2; i++) {
const groupId = groupIds[i];
if (groupsJson.hasOwnProperty(groupId)) {
const group = groupsJson[groupId];
groups.push(
new GroupMetadata_default({
id: groupId,
group: groupsJson[groupId],
class: schema.classes[group.class]
})
);
}
}
}
this._schema = schema;
this._groups = groups;
this._groupIds = groupIds;
this._tileset = tileset;
this._statistics = metadataJson.statistics;
this._extras = metadataJson.extras;
this._extensions = metadataJson.extensions;
}
Object.defineProperties(Cesium3DTilesetMetadata.prototype, {
/**
* Schema containing classes and enums.
*
* @memberof Cesium3DTilesetMetadata.prototype
* @type {MetadataSchema}
* @readonly
* @private
*/
schema: {
get: function() {
return this._schema;
}
},
/**
* Metadata about groups of content.
*
* @memberof Cesium3DTilesetMetadata.prototype
* @type {GroupMetadata[]}
* @readonly
* @private
*/
groups: {
get: function() {
return this._groups;
}
},
/**
* The IDs of the group metadata in the corresponding groups dictionary.
* Only populated if using the legacy schema.
*
* @memberof Cesium3DTilesetMetadata.prototype
* @type {}
* @readonly
* @private
*/
groupIds: {
get: function() {
return this._groupIds;
}
},
/**
* Metadata about the tileset as a whole.
*
* @memberof Cesium3DTilesetMetadata.prototype
* @type {TilesetMetadata}
* @readonly
* @private
*/
tileset: {
get: function() {
return this._tileset;
}
},
/**
* Statistics about the metadata.
*
* See the {@link https://github.com/CesiumGS/3d-tiles/blob/main/extensions/3DTILES_metadata/schema/statistics.schema.json|statistics schema reference}
* in the 3D Tiles spec for the full set of properties.
*
*
* @memberof Cesium3DTilesetMetadata.prototype
* @type {object}
* @readonly
* @private
*/
statistics: {
get: function() {
return this._statistics;
}
},
/**
* Extra user-defined properties.
*
* @memberof Cesium3DTilesetMetadata.prototype
* @type {*}
* @readonly
* @private
*/
extras: {
get: function() {
return this._extras;
}
},
/**
* An object containing extensions.
*
* @memberof Cesium3DTilesetMetadata.prototype
* @type {object}
* @readonly
* @private
*/
extensions: {
get: function() {
return this._extensions;
}
}
});
var Cesium3DTilesetMetadata_default = Cesium3DTilesetMetadata;
// packages/engine/Source/Scene/Cesium3DTileOptimizations.js
var import_InlineWorkers800 = __toESM(require_InlineWorkers(), 1);
var Cesium3DTileOptimizations = {};
var scratchAxis = new Cartesian3_default();
Cesium3DTileOptimizations.checkChildrenWithinParent = function(tile) {
Check_default.typeOf.object("tile", tile);
const children = tile.children;
const length2 = children.length;
const boundingVolume = tile.boundingVolume;
if (boundingVolume instanceof TileOrientedBoundingBox_default || boundingVolume instanceof TileBoundingRegion_default) {
const orientedBoundingBox = boundingVolume._orientedBoundingBox;
tile._optimChildrenWithinParent = Cesium3DTileOptimizationHint_default.USE_OPTIMIZATION;
for (let i = 0; i < length2; ++i) {
const child = children[i];
const childBoundingVolume = child.boundingVolume;
if (!(childBoundingVolume instanceof TileOrientedBoundingBox_default || childBoundingVolume instanceof TileBoundingRegion_default)) {
tile._optimChildrenWithinParent = Cesium3DTileOptimizationHint_default.SKIP_OPTIMIZATION;
break;
}
const childOrientedBoundingBox = childBoundingVolume._orientedBoundingBox;
const axis = Cartesian3_default.subtract(
childOrientedBoundingBox.center,
orientedBoundingBox.center,
scratchAxis
);
const axisLength = Cartesian3_default.magnitude(axis);
Cartesian3_default.divideByScalar(axis, axisLength, axis);
const proj1 = Math.abs(orientedBoundingBox.halfAxes[0] * axis.x) + Math.abs(orientedBoundingBox.halfAxes[1] * axis.y) + Math.abs(orientedBoundingBox.halfAxes[2] * axis.z) + Math.abs(orientedBoundingBox.halfAxes[3] * axis.x) + Math.abs(orientedBoundingBox.halfAxes[4] * axis.y) + Math.abs(orientedBoundingBox.halfAxes[5] * axis.z) + Math.abs(orientedBoundingBox.halfAxes[6] * axis.x) + Math.abs(orientedBoundingBox.halfAxes[7] * axis.y) + Math.abs(orientedBoundingBox.halfAxes[8] * axis.z);
const proj2 = Math.abs(childOrientedBoundingBox.halfAxes[0] * axis.x) + Math.abs(childOrientedBoundingBox.halfAxes[1] * axis.y) + Math.abs(childOrientedBoundingBox.halfAxes[2] * axis.z) + Math.abs(childOrientedBoundingBox.halfAxes[3] * axis.x) + Math.abs(childOrientedBoundingBox.halfAxes[4] * axis.y) + Math.abs(childOrientedBoundingBox.halfAxes[5] * axis.z) + Math.abs(childOrientedBoundingBox.halfAxes[6] * axis.x) + Math.abs(childOrientedBoundingBox.halfAxes[7] * axis.y) + Math.abs(childOrientedBoundingBox.halfAxes[8] * axis.z);
if (proj1 <= proj2 + axisLength) {
tile._optimChildrenWithinParent = Cesium3DTileOptimizationHint_default.SKIP_OPTIMIZATION;
break;
}
}
}
return tile._optimChildrenWithinParent === Cesium3DTileOptimizationHint_default.USE_OPTIMIZATION;
};
var Cesium3DTileOptimizations_default = Cesium3DTileOptimizations;
// packages/engine/Source/Scene/Cesium3DTilesetCache.js
var import_InlineWorkers802 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/DoublyLinkedList.js
var import_InlineWorkers801 = __toESM(require_InlineWorkers(), 1);
function DoublyLinkedList() {
this.head = void 0;
this.tail = void 0;
this._length = 0;
}
Object.defineProperties(DoublyLinkedList.prototype, {
length: {
get: function() {
return this._length;
}
}
});
function DoublyLinkedListNode(item, previous, next) {
this.item = item;
this.previous = previous;
this.next = next;
}
DoublyLinkedList.prototype.add = function(item) {
const node = new DoublyLinkedListNode(item, this.tail, void 0);
if (defined_default(this.tail)) {
this.tail.next = node;
this.tail = node;
} else {
this.head = node;
this.tail = node;
}
++this._length;
return node;
};
function remove(list, node) {
if (defined_default(node.previous) && defined_default(node.next)) {
node.previous.next = node.next;
node.next.previous = node.previous;
} else if (defined_default(node.previous)) {
node.previous.next = void 0;
list.tail = node.previous;
} else if (defined_default(node.next)) {
node.next.previous = void 0;
list.head = node.next;
} else {
list.head = void 0;
list.tail = void 0;
}
node.next = void 0;
node.previous = void 0;
}
DoublyLinkedList.prototype.remove = function(node) {
if (!defined_default(node)) {
return;
}
remove(this, node);
--this._length;
};
DoublyLinkedList.prototype.splice = function(node, nextNode) {
if (node === nextNode) {
return;
}
remove(this, nextNode);
const oldNodeNext = node.next;
node.next = nextNode;
if (this.tail === node) {
this.tail = nextNode;
} else {
oldNodeNext.previous = nextNode;
}
nextNode.next = oldNodeNext;
nextNode.previous = node;
};
var DoublyLinkedList_default = DoublyLinkedList;
// packages/engine/Source/Scene/Cesium3DTilesetCache.js
function Cesium3DTilesetCache() {
this._list = new DoublyLinkedList_default();
this._sentinel = this._list.add();
this._trimTiles = false;
}
Cesium3DTilesetCache.prototype.reset = function() {
this._list.splice(this._list.tail, this._sentinel);
};
Cesium3DTilesetCache.prototype.touch = function(tile) {
const node = tile.cacheNode;
if (defined_default(node)) {
this._list.splice(this._sentinel, node);
}
};
Cesium3DTilesetCache.prototype.add = function(tile) {
if (!defined_default(tile.cacheNode)) {
tile.cacheNode = this._list.add(tile);
}
};
Cesium3DTilesetCache.prototype.unloadTile = function(tileset, tile, unloadCallback) {
const node = tile.cacheNode;
if (!defined_default(node)) {
return;
}
this._list.remove(node);
tile.cacheNode = void 0;
unloadCallback(tileset, tile);
};
Cesium3DTilesetCache.prototype.unloadTiles = function(tileset, unloadCallback) {
const trimTiles = this._trimTiles;
this._trimTiles = false;
const list = this._list;
const sentinel = this._sentinel;
let node = list.head;
while (node !== sentinel && (tileset.totalMemoryUsageInBytes > tileset.cacheBytes || trimTiles)) {
const tile = node.item;
node = node.next;
this.unloadTile(tileset, tile, unloadCallback);
}
};
Cesium3DTilesetCache.prototype.trim = function() {
this._trimTiles = true;
};
var Cesium3DTilesetCache_default = Cesium3DTilesetCache;
// packages/engine/Source/Scene/Cesium3DTilesetHeatmap.js
var import_InlineWorkers803 = __toESM(require_InlineWorkers(), 1);
function Cesium3DTilesetHeatmap(tilePropertyName) {
this.tilePropertyName = tilePropertyName;
this._minimum = Number.MAX_VALUE;
this._maximum = -Number.MAX_VALUE;
this._previousMinimum = Number.MAX_VALUE;
this._previousMaximum = -Number.MAX_VALUE;
this._referenceMinimum = {};
this._referenceMaximum = {};
}
function getHeatmapValue(tileValue, tilePropertyName) {
let value;
if (tilePropertyName === "_loadTimestamp") {
value = JulianDate_default.toDate(tileValue).getTime();
} else {
value = tileValue;
}
return value;
}
Cesium3DTilesetHeatmap.prototype.setReferenceMinimumMaximum = function(minimum, maximum, tilePropertyName) {
this._referenceMinimum[tilePropertyName] = getHeatmapValue(
minimum,
tilePropertyName
);
this._referenceMaximum[tilePropertyName] = getHeatmapValue(
maximum,
tilePropertyName
);
};
function getHeatmapValueAndUpdateMinimumMaximum(heatmap, tile) {
const tilePropertyName = heatmap.tilePropertyName;
if (defined_default(tilePropertyName)) {
const heatmapValue = getHeatmapValue(
tile[tilePropertyName],
tilePropertyName
);
if (!defined_default(heatmapValue)) {
heatmap.tilePropertyName = void 0;
return heatmapValue;
}
heatmap._maximum = Math.max(heatmapValue, heatmap._maximum);
heatmap._minimum = Math.min(heatmapValue, heatmap._minimum);
return heatmapValue;
}
}
var heatmapColors = [
new Color_default(0.1, 0.1, 0.1, 1),
// Dark Gray
new Color_default(0.153, 0.278, 0.878, 1),
// Blue
new Color_default(0.827, 0.231, 0.49, 1),
// Pink
new Color_default(0.827, 0.188, 0.22, 1),
// Red
new Color_default(1, 0.592, 0.259, 1),
// Orange
new Color_default(1, 0.843, 0, 1)
];
Cesium3DTilesetHeatmap.prototype.colorize = function(tile, frameState) {
const tilePropertyName = this.tilePropertyName;
if (!defined_default(tilePropertyName) || !tile.contentAvailable || tile._selectedFrame !== frameState.frameNumber) {
return;
}
const heatmapValue = getHeatmapValueAndUpdateMinimumMaximum(this, tile);
const minimum = this._previousMinimum;
const maximum = this._previousMaximum;
if (minimum === Number.MAX_VALUE || maximum === -Number.MAX_VALUE) {
return;
}
const shiftedMax = maximum - minimum + Math_default.EPSILON7;
const shiftedValue = Math_default.clamp(
heatmapValue - minimum,
0,
shiftedMax
);
const zeroToOne = shiftedValue / shiftedMax;
const lastIndex = heatmapColors.length - 1;
const colorPosition = zeroToOne * lastIndex;
const colorPositionFloor = Math.floor(colorPosition);
const colorPositionCeil = Math.ceil(colorPosition);
const t = colorPosition - colorPositionFloor;
const colorZero = heatmapColors[colorPositionFloor];
const colorOne = heatmapColors[colorPositionCeil];
const finalColor = Color_default.clone(Color_default.WHITE);
finalColor.red = Math_default.lerp(colorZero.red, colorOne.red, t);
finalColor.green = Math_default.lerp(colorZero.green, colorOne.green, t);
finalColor.blue = Math_default.lerp(colorZero.blue, colorOne.blue, t);
tile._debugColor = finalColor;
};
Cesium3DTilesetHeatmap.prototype.resetMinimumMaximum = function() {
const tilePropertyName = this.tilePropertyName;
if (defined_default(tilePropertyName)) {
const referenceMinimum = this._referenceMinimum[tilePropertyName];
const referenceMaximum = this._referenceMaximum[tilePropertyName];
const useReference = defined_default(referenceMinimum) && defined_default(referenceMaximum);
this._previousMinimum = useReference ? referenceMinimum : this._minimum;
this._previousMaximum = useReference ? referenceMaximum : this._maximum;
this._minimum = Number.MAX_VALUE;
this._maximum = -Number.MAX_VALUE;
}
};
var Cesium3DTilesetHeatmap_default = Cesium3DTilesetHeatmap;
// packages/engine/Source/Scene/Cesium3DTilesetStatistics.js
var import_InlineWorkers804 = __toESM(require_InlineWorkers(), 1);
function Cesium3DTilesetStatistics() {
this.selected = 0;
this.visited = 0;
this.numberOfCommands = 0;
this.numberOfAttemptedRequests = 0;
this.numberOfPendingRequests = 0;
this.numberOfTilesProcessing = 0;
this.numberOfTilesWithContentReady = 0;
this.numberOfTilesTotal = 0;
this.numberOfLoadedTilesTotal = 0;
this.numberOfFeaturesSelected = 0;
this.numberOfFeaturesLoaded = 0;
this.numberOfPointsSelected = 0;
this.numberOfPointsLoaded = 0;
this.numberOfTrianglesSelected = 0;
this.numberOfTilesStyled = 0;
this.numberOfFeaturesStyled = 0;
this.numberOfTilesCulledWithChildrenUnion = 0;
this.geometryByteLength = 0;
this.texturesByteLength = 0;
this.texturesReferenceCounterById = {};
this.batchTableByteLength = 0;
}
Cesium3DTilesetStatistics.prototype.clear = function() {
this.selected = 0;
this.visited = 0;
this.numberOfCommands = 0;
this.numberOfAttemptedRequests = 0;
this.numberOfFeaturesSelected = 0;
this.numberOfPointsSelected = 0;
this.numberOfTrianglesSelected = 0;
this.numberOfTilesStyled = 0;
this.numberOfFeaturesStyled = 0;
this.numberOfTilesCulledWithChildrenUnion = 0;
};
Cesium3DTilesetStatistics.prototype.incrementSelectionCounts = function(content) {
this.numberOfFeaturesSelected += content.featuresLength;
this.numberOfPointsSelected += content.pointsLength;
this.numberOfTrianglesSelected += content.trianglesLength;
const contents = content.innerContents;
if (defined_default(contents)) {
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
this.incrementSelectionCounts(contents[i]);
}
}
};
Cesium3DTilesetStatistics.prototype.incrementLoadCounts = function(content) {
this.numberOfFeaturesLoaded += content.featuresLength;
this.numberOfPointsLoaded += content.pointsLength;
this.geometryByteLength += content.geometryByteLength;
this.batchTableByteLength += content.batchTableByteLength;
if (!(content instanceof Model3DTileContent_default)) {
this.texturesByteLength += content.texturesByteLength;
} else {
const textureIds = content.getTextureIds();
for (const textureId of textureIds) {
const referenceCounter = this.texturesReferenceCounterById[textureId] ?? 0;
if (referenceCounter === 0) {
const textureByteLength = content.getTextureByteLengthById(textureId);
this.texturesByteLength += textureByteLength;
}
this.texturesReferenceCounterById[textureId] = referenceCounter + 1;
}
}
const contents = content.innerContents;
if (defined_default(contents)) {
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
this.incrementLoadCounts(contents[i]);
}
}
};
Cesium3DTilesetStatistics.prototype.decrementLoadCounts = function(content) {
this.numberOfFeaturesLoaded -= content.featuresLength;
this.numberOfPointsLoaded -= content.pointsLength;
this.geometryByteLength -= content.geometryByteLength;
this.batchTableByteLength -= content.batchTableByteLength;
if (!(content instanceof Model3DTileContent_default)) {
this.texturesByteLength -= content.texturesByteLength;
} else {
const textureIds = content.getTextureIds();
for (const textureId of textureIds) {
const referenceCounter = this.texturesReferenceCounterById[textureId];
if (referenceCounter === 1) {
delete this.texturesReferenceCounterById[textureId];
const textureByteLength = content.getTextureByteLengthById(textureId);
this.texturesByteLength -= textureByteLength;
} else {
this.texturesReferenceCounterById[textureId] = referenceCounter - 1;
}
}
}
const contents = content.innerContents;
if (defined_default(contents)) {
const length2 = contents.length;
for (let i = 0; i < length2; ++i) {
this.decrementLoadCounts(contents[i]);
}
}
};
Cesium3DTilesetStatistics.clone = function(statistics2, result) {
result.selected = statistics2.selected;
result.visited = statistics2.visited;
result.numberOfCommands = statistics2.numberOfCommands;
result.numberOfAttemptedRequests = statistics2.numberOfAttemptedRequests;
result.numberOfPendingRequests = statistics2.numberOfPendingRequests;
result.numberOfTilesProcessing = statistics2.numberOfTilesProcessing;
result.numberOfTilesWithContentReady = statistics2.numberOfTilesWithContentReady;
result.numberOfTilesTotal = statistics2.numberOfTilesTotal;
result.numberOfFeaturesSelected = statistics2.numberOfFeaturesSelected;
result.numberOfFeaturesLoaded = statistics2.numberOfFeaturesLoaded;
result.numberOfPointsSelected = statistics2.numberOfPointsSelected;
result.numberOfPointsLoaded = statistics2.numberOfPointsLoaded;
result.numberOfTrianglesSelected = statistics2.numberOfTrianglesSelected;
result.numberOfTilesStyled = statistics2.numberOfTilesStyled;
result.numberOfFeaturesStyled = statistics2.numberOfFeaturesStyled;
result.numberOfTilesCulledWithChildrenUnion = statistics2.numberOfTilesCulledWithChildrenUnion;
result.geometryByteLength = statistics2.geometryByteLength;
result.texturesByteLength = statistics2.texturesByteLength;
result.texturesReferenceCounterById = {
...statistics2.texturesReferenceCounterById
};
result.batchTableByteLength = statistics2.batchTableByteLength;
};
var Cesium3DTilesetStatistics_default = Cesium3DTilesetStatistics;
// packages/engine/Source/Scene/Cesium3DTileStyleEngine.js
var import_InlineWorkers805 = __toESM(require_InlineWorkers(), 1);
function Cesium3DTileStyleEngine() {
this._style = void 0;
this._styleDirty = false;
this._lastStyleTime = 0;
}
Object.defineProperties(Cesium3DTileStyleEngine.prototype, {
style: {
get: function() {
return this._style;
},
set: function(value) {
if (value === this._style) {
return;
}
this._style = value;
this._styleDirty = true;
}
}
});
Cesium3DTileStyleEngine.prototype.makeDirty = function() {
this._styleDirty = true;
};
Cesium3DTileStyleEngine.prototype.resetDirty = function() {
this._styleDirty = false;
};
Cesium3DTileStyleEngine.prototype.applyStyle = function(tileset) {
if (!defined_default(tileset.root)) {
return;
}
if (defined_default(this._style) && !this._style._ready) {
return;
}
const styleDirty = this._styleDirty;
if (styleDirty) {
++this._lastStyleTime;
}
const lastStyleTime = this._lastStyleTime;
const statistics2 = tileset._statistics;
const tiles = styleDirty ? tileset._selectedTiles : tileset._selectedTilesToStyle;
const length2 = tiles.length;
for (let i = 0; i < length2; ++i) {
const tile = tiles[i];
if (tile.lastStyleTime !== lastStyleTime) {
const content = tile.content;
tile.lastStyleTime = lastStyleTime;
content.applyStyle(this._style);
statistics2.numberOfFeaturesStyled += content.featuresLength;
++statistics2.numberOfTilesStyled;
}
}
};
var Cesium3DTileStyleEngine_default = Cesium3DTileStyleEngine;
// packages/engine/Source/Scene/ImplicitTileset.js
var import_InlineWorkers806 = __toESM(require_InlineWorkers(), 1);
function ImplicitTileset(baseResource2, tileJson, metadataSchema) {
const implicitTiling = hasExtension_default(tileJson, "3DTILES_implicit_tiling") ? tileJson.extensions["3DTILES_implicit_tiling"] : tileJson.implicitTiling;
Check_default.typeOf.object("implicitTiling", implicitTiling);
this.baseResource = baseResource2;
this.geometricError = tileJson.geometricError;
this.metadataSchema = metadataSchema;
const boundingVolume = tileJson.boundingVolume;
if (!defined_default(boundingVolume.box) && !defined_default(boundingVolume.region) && !hasExtension_default(boundingVolume, "3DTILES_bounding_volume_S2") && !hasExtension_default(boundingVolume, "3DTILES_bounding_volume_cylinder")) {
throw new RuntimeError_default(
"Only box, region, 3DTILES_bounding_volume_S2, and 3DTILES_bounding_volume_cylinder are supported for implicit tiling"
);
}
this.boundingVolume = boundingVolume;
this.refine = tileJson.refine;
this.subtreeUriTemplate = new Resource_default({ url: implicitTiling.subtrees.uri });
this.contentUriTemplates = [];
this.contentHeaders = [];
const contentHeaders = gatherContentHeaders(tileJson);
for (let i = 0; i < contentHeaders.length; i++) {
const contentHeader = contentHeaders[i];
this.contentHeaders.push(clone_default(contentHeader, true));
const contentResource = new Resource_default({ url: contentHeader.uri });
this.contentUriTemplates.push(contentResource);
}
this.contentCount = this.contentHeaders.length;
this.tileHeader = makeTileHeaderTemplate(tileJson);
this.subdivisionScheme = ImplicitSubdivisionScheme_default[implicitTiling.subdivisionScheme];
this.branchingFactor = ImplicitSubdivisionScheme_default.getBranchingFactor(
this.subdivisionScheme
);
this.subtreeLevels = implicitTiling.subtreeLevels;
if (defined_default(implicitTiling.availableLevels)) {
this.availableLevels = implicitTiling.availableLevels;
} else {
this.availableLevels = implicitTiling.maximumLevel + 1;
}
}
function gatherContentHeaders(tileJson) {
if (hasExtension_default(tileJson, "3DTILES_multiple_contents")) {
const extension = tileJson.extensions["3DTILES_multiple_contents"];
return defined_default(extension.contents) ? extension.contents : extension.content;
}
if (defined_default(tileJson.contents)) {
return tileJson.contents;
}
if (defined_default(tileJson.content)) {
return [tileJson.content];
}
return [];
}
function makeTileHeaderTemplate(tileJson) {
const template = clone_default(tileJson, true);
if (defined_default(template.extensions)) {
delete template.extensions["3DTILES_implicit_tiling"];
delete template.extensions["3DTILES_multiple_contents"];
if (Object.keys(template.extensions).length === 0) {
delete template.extensions;
}
}
delete template.implicitTiling;
delete template.contents;
delete template.content;
return template;
}
var ImplicitTileset_default = ImplicitTileset;
// packages/engine/Source/Scene/ImplicitTileCoordinates.js
var import_InlineWorkers808 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/MortonOrder.js
var import_InlineWorkers807 = __toESM(require_InlineWorkers(), 1);
var MortonOrder = {};
function insertOneSpacing(v3) {
v3 = (v3 ^ v3 << 8) & 16711935;
v3 = (v3 ^ v3 << 4) & 252645135;
v3 = (v3 ^ v3 << 2) & 858993459;
v3 = (v3 ^ v3 << 1) & 1431655765;
return v3;
}
function insertTwoSpacing(v3) {
v3 = (v3 ^ v3 << 16) & 50331903;
v3 = (v3 ^ v3 << 8) & 50393103;
v3 = (v3 ^ v3 << 4) & 51130563;
v3 = (v3 ^ v3 << 2) & 153391689;
return v3;
}
function removeOneSpacing(v3) {
v3 &= 1431655765;
v3 = (v3 ^ v3 >> 1) & 858993459;
v3 = (v3 ^ v3 >> 2) & 252645135;
v3 = (v3 ^ v3 >> 4) & 16711935;
v3 = (v3 ^ v3 >> 8) & 65535;
return v3;
}
function removeTwoSpacing(v3) {
v3 &= 153391689;
v3 = (v3 ^ v3 >> 2) & 51130563;
v3 = (v3 ^ v3 >> 4) & 50393103;
v3 = (v3 ^ v3 >> 8) & 4278190335;
v3 = (v3 ^ v3 >> 16) & 1023;
return v3;
}
MortonOrder.encode2D = function(x, y) {
Check_default.typeOf.number("x", x);
Check_default.typeOf.number("y", y);
if (x < 0 || x > 65535 || y < 0 || y > 65535) {
throw new DeveloperError_default("inputs must be 16-bit unsigned integers");
}
return (insertOneSpacing(x) | insertOneSpacing(y) << 1) >>> 0;
};
MortonOrder.decode2D = function(mortonIndex, result) {
Check_default.typeOf.number("mortonIndex", mortonIndex);
if (mortonIndex < 0 || mortonIndex > 4294967295) {
throw new DeveloperError_default("input must be a 32-bit unsigned integer");
}
if (!defined_default(result)) {
result = new Array(2);
}
result[0] = removeOneSpacing(mortonIndex);
result[1] = removeOneSpacing(mortonIndex >> 1);
return result;
};
MortonOrder.encode3D = function(x, y, z) {
Check_default.typeOf.number("x", x);
Check_default.typeOf.number("y", y);
Check_default.typeOf.number("z", z);
if (x < 0 || x > 1023 || y < 0 || y > 1023 || z < 0 || z > 1023) {
throw new DeveloperError_default("inputs must be 10-bit unsigned integers");
}
return insertTwoSpacing(x) | insertTwoSpacing(y) << 1 | insertTwoSpacing(z) << 2;
};
MortonOrder.decode3D = function(mortonIndex, result) {
Check_default.typeOf.number("mortonIndex", mortonIndex);
if (mortonIndex < 0 || mortonIndex > 1073741823) {
throw new DeveloperError_default("input must be a 30-bit unsigned integer");
}
if (!defined_default(result)) {
result = new Array(3);
}
result[0] = removeTwoSpacing(mortonIndex);
result[1] = removeTwoSpacing(mortonIndex >> 1);
result[2] = removeTwoSpacing(mortonIndex >> 2);
return result;
};
var MortonOrder_default = MortonOrder;
// packages/engine/Source/Scene/ImplicitTileCoordinates.js
function ImplicitTileCoordinates(options) {
Check_default.typeOf.string("options.subdivisionScheme", options.subdivisionScheme);
Check_default.typeOf.number("options.subtreeLevels", options.subtreeLevels);
Check_default.typeOf.number("options.level", options.level);
Check_default.typeOf.number("options.x", options.x);
Check_default.typeOf.number("options.y", options.y);
if (options.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
Check_default.typeOf.number("options.z", options.z);
}
if (options.level < 0) {
throw new DeveloperError_default("level must be non-negative");
}
if (options.x < 0) {
throw new DeveloperError_default("x must be non-negative");
}
if (options.y < 0) {
throw new DeveloperError_default("y must be non-negative");
}
if (options.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
if (options.z < 0) {
throw new DeveloperError_default("z must be non-negative");
}
}
const dimensionAtLevel = 1 << options.level;
if (options.x >= dimensionAtLevel) {
throw new DeveloperError_default("x is out of range");
}
if (options.y >= dimensionAtLevel) {
throw new DeveloperError_default("y is out of range");
}
if (options.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
if (options.z >= dimensionAtLevel) {
throw new DeveloperError_default("z is out of range");
}
}
this.subdivisionScheme = options.subdivisionScheme;
this.subtreeLevels = options.subtreeLevels;
this.level = options.level;
this.x = options.x;
this.y = options.y;
this.z = void 0;
if (options.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
this.z = options.z;
}
}
Object.defineProperties(ImplicitTileCoordinates.prototype, {
/**
* An index in the range of [0, branchingFactor) that indicates
* which child of the parent cell these coordinates correspond to.
* This can be viewed as a morton index within the parent tile.
*
* This is the last 3 bits of the morton index of the tile, but it can
* be computed more directly by concatenating the bits [z0] y0 x0
*
*
* @type {number}
* @readonly
* @private
*/
childIndex: {
get: function() {
let childIndex = 0;
childIndex |= this.x & 1;
childIndex |= (this.y & 1) << 1;
if (this.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
childIndex |= (this.z & 1) << 2;
}
return childIndex;
}
},
/**
* Get the Morton index for this tile within the current level by interleaving
* the bits of the x, y and z coordinates.
*
* @type {number}
* @readonly
* @private
*/
mortonIndex: {
get: function() {
if (this.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
return MortonOrder_default.encode3D(this.x, this.y, this.z);
}
return MortonOrder_default.encode2D(this.x, this.y);
}
},
/**
* Get the tile index by adding the Morton index to the level offset
*
* @type {number}
* @readonly
* @private
*/
tileIndex: {
get: function() {
const levelOffset = this.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE ? (
// (8^N - 1) / (8-1)
((1 << 3 * this.level) - 1) / 7
) : (
// (4^N - 1) / (4-1)
((1 << 2 * this.level) - 1) / 3
);
const mortonIndex = this.mortonIndex;
return levelOffset + mortonIndex;
}
}
});
function checkMatchingSubtreeShape(a3, b) {
if (a3.subdivisionScheme !== b.subdivisionScheme) {
throw new DeveloperError_default("coordinates must have same subdivisionScheme");
}
if (a3.subtreeLevels !== b.subtreeLevels) {
throw new DeveloperError_default("coordinates must have same subtreeLevels");
}
}
ImplicitTileCoordinates.prototype.getDescendantCoordinates = function(offsetCoordinates) {
Check_default.typeOf.object("offsetCoordinates", offsetCoordinates);
checkMatchingSubtreeShape(this, offsetCoordinates);
const descendantLevel = this.level + offsetCoordinates.level;
const descendantX = (this.x << offsetCoordinates.level) + offsetCoordinates.x;
const descendantY = (this.y << offsetCoordinates.level) + offsetCoordinates.y;
if (this.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
const descendantZ = (this.z << offsetCoordinates.level) + offsetCoordinates.z;
return new ImplicitTileCoordinates({
subdivisionScheme: this.subdivisionScheme,
subtreeLevels: this.subtreeLevels,
level: descendantLevel,
x: descendantX,
y: descendantY,
z: descendantZ
});
}
return new ImplicitTileCoordinates({
subdivisionScheme: this.subdivisionScheme,
subtreeLevels: this.subtreeLevels,
level: descendantLevel,
x: descendantX,
y: descendantY
});
};
ImplicitTileCoordinates.prototype.getAncestorCoordinates = function(offsetLevels) {
Check_default.typeOf.number("offsetLevels", offsetLevels);
if (offsetLevels < 0) {
throw new DeveloperError_default("offsetLevels must be non-negative");
}
if (offsetLevels > this.level) {
throw new DeveloperError_default("ancestor cannot be above the tileset root");
}
const divisor = 1 << offsetLevels;
const ancestorLevel = this.level - offsetLevels;
const ancestorX = Math.floor(this.x / divisor);
const ancestorY = Math.floor(this.y / divisor);
if (this.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
const ancestorZ = Math.floor(this.z / divisor);
return new ImplicitTileCoordinates({
subdivisionScheme: this.subdivisionScheme,
subtreeLevels: this.subtreeLevels,
level: ancestorLevel,
x: ancestorX,
y: ancestorY,
z: ancestorZ
});
}
return new ImplicitTileCoordinates({
subdivisionScheme: this.subdivisionScheme,
subtreeLevels: this.subtreeLevels,
level: ancestorLevel,
x: ancestorX,
y: ancestorY
});
};
ImplicitTileCoordinates.prototype.getOffsetCoordinates = function(descendantCoordinates) {
Check_default.typeOf.object("descendantCoordinates", descendantCoordinates);
if (!this.isEqual(descendantCoordinates) && !this.isAncestor(descendantCoordinates)) {
throw new DeveloperError_default("this is not an ancestor of descendant");
}
checkMatchingSubtreeShape(this, descendantCoordinates);
const offsetLevel = descendantCoordinates.level - this.level;
const dimensionAtOffsetLevel = 1 << offsetLevel;
const offsetX = descendantCoordinates.x % dimensionAtOffsetLevel;
const offsetY = descendantCoordinates.y % dimensionAtOffsetLevel;
if (this.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
const offsetZ = descendantCoordinates.z % dimensionAtOffsetLevel;
return new ImplicitTileCoordinates({
subdivisionScheme: this.subdivisionScheme,
subtreeLevels: this.subtreeLevels,
level: offsetLevel,
x: offsetX,
y: offsetY,
z: offsetZ
});
}
return new ImplicitTileCoordinates({
subdivisionScheme: this.subdivisionScheme,
subtreeLevels: this.subtreeLevels,
level: offsetLevel,
x: offsetX,
y: offsetY
});
};
ImplicitTileCoordinates.prototype.getChildCoordinates = function(childIndex) {
Check_default.typeOf.number("childIndex", childIndex);
const branchingFactor = ImplicitSubdivisionScheme_default.getBranchingFactor(
this.subdivisionScheme
);
if (childIndex < 0 || branchingFactor <= childIndex) {
throw new DeveloperError_default(
`childIndex must be at least 0 and less than ${branchingFactor}`
);
}
const level = this.level + 1;
const x = 2 * this.x + childIndex % 2;
const y = 2 * this.y + Math.floor(childIndex / 2) % 2;
if (this.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
const z = 2 * this.z + Math.floor(childIndex / 4) % 2;
return new ImplicitTileCoordinates({
subdivisionScheme: this.subdivisionScheme,
subtreeLevels: this.subtreeLevels,
level,
x,
y,
z
});
}
return new ImplicitTileCoordinates({
subdivisionScheme: this.subdivisionScheme,
subtreeLevels: this.subtreeLevels,
level,
x,
y
});
};
ImplicitTileCoordinates.prototype.getSubtreeCoordinates = function() {
return this.getAncestorCoordinates(this.level % this.subtreeLevels);
};
ImplicitTileCoordinates.prototype.getParentSubtreeCoordinates = function() {
return this.getAncestorCoordinates(
this.level % this.subtreeLevels + this.subtreeLevels
);
};
ImplicitTileCoordinates.prototype.isAncestor = function(descendantCoordinates) {
Check_default.typeOf.object("descendantCoordinates", descendantCoordinates);
checkMatchingSubtreeShape(this, descendantCoordinates);
const levelDifference = descendantCoordinates.level - this.level;
if (levelDifference <= 0) {
return false;
}
const ancestorX = descendantCoordinates.x >> levelDifference;
const ancestorY = descendantCoordinates.y >> levelDifference;
const isAncestorX = this.x === ancestorX;
const isAncestorY = this.y === ancestorY;
if (this.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
const ancestorZ = descendantCoordinates.z >> levelDifference;
const isAncestorZ = this.z === ancestorZ;
return isAncestorX && isAncestorY && isAncestorZ;
}
return isAncestorX && isAncestorY;
};
ImplicitTileCoordinates.prototype.isEqual = function(otherCoordinates) {
Check_default.typeOf.object("otherCoordinates", otherCoordinates);
return this.subdivisionScheme === otherCoordinates.subdivisionScheme && this.subtreeLevels === otherCoordinates.subtreeLevels && this.level === otherCoordinates.level && this.x === otherCoordinates.x && this.y === otherCoordinates.y && (this.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE ? this.z === otherCoordinates.z : true);
};
ImplicitTileCoordinates.prototype.isImplicitTilesetRoot = function() {
return this.level === 0;
};
ImplicitTileCoordinates.prototype.isSubtreeRoot = function() {
return this.level % this.subtreeLevels === 0;
};
ImplicitTileCoordinates.prototype.isBottomOfSubtree = function() {
return this.level % this.subtreeLevels === this.subtreeLevels - 1;
};
ImplicitTileCoordinates.prototype.getTemplateValues = function() {
const values = {
level: this.level,
x: this.x,
y: this.y
};
if (this.subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
values.z = this.z;
}
return values;
};
var scratchCoordinatesArray = [0, 0, 0];
ImplicitTileCoordinates.fromMortonIndex = function(subdivisionScheme, subtreeLevels, level, mortonIndex) {
let coordinatesArray;
if (subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
coordinatesArray = MortonOrder_default.decode3D(
mortonIndex,
scratchCoordinatesArray
);
return new ImplicitTileCoordinates({
subdivisionScheme,
subtreeLevels,
level,
x: coordinatesArray[0],
y: coordinatesArray[1],
z: coordinatesArray[2]
});
}
coordinatesArray = MortonOrder_default.decode2D(mortonIndex, scratchCoordinatesArray);
return new ImplicitTileCoordinates({
subdivisionScheme,
subtreeLevels,
level,
x: coordinatesArray[0],
y: coordinatesArray[1]
});
};
ImplicitTileCoordinates.fromTileIndex = function(subdivisionScheme, subtreeLevels, tileIndex) {
let level;
let levelOffset;
let mortonIndex;
if (subdivisionScheme === ImplicitSubdivisionScheme_default.OCTREE) {
level = Math.floor(Math_default.log2(7 * tileIndex + 1) / 3);
levelOffset = ((1 << 3 * level) - 1) / 7;
mortonIndex = tileIndex - levelOffset;
} else {
level = Math.floor(Math_default.log2(3 * tileIndex + 1) / 2);
levelOffset = ((1 << 2 * level) - 1) / 3;
mortonIndex = tileIndex - levelOffset;
}
return ImplicitTileCoordinates.fromMortonIndex(
subdivisionScheme,
subtreeLevels,
level,
mortonIndex
);
};
var ImplicitTileCoordinates_default = ImplicitTileCoordinates;
// packages/engine/Source/Scene/Cesium3DTilesetMostDetailedTraversal.js
var import_InlineWorkers810 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Cesium3DTilesetTraversal.js
var import_InlineWorkers809 = __toESM(require_InlineWorkers(), 1);
function Cesium3DTilesetTraversal() {
}
Cesium3DTilesetTraversal.selectTiles = function(tileset, frameState) {
DeveloperError_default.throwInstantiationError();
};
Cesium3DTilesetTraversal.sortChildrenByDistanceToCamera = function(a3, b) {
if (b._distanceToCamera === 0 && a3._distanceToCamera === 0) {
return b._centerZDepth - a3._centerZDepth;
}
return b._distanceToCamera - a3._distanceToCamera;
};
Cesium3DTilesetTraversal.canTraverse = function(tile) {
if (tile.children.length === 0) {
return false;
}
if (tile.hasTilesetContent || tile.hasImplicitContent) {
return !tile.contentExpired;
}
return tile._screenSpaceError > tile.tileset.memoryAdjustedScreenSpaceError;
};
Cesium3DTilesetTraversal.selectTile = function(tile, frameState) {
if (tile.contentVisibility(frameState) === Intersect_default.OUTSIDE) {
return;
}
tile._wasSelectedLastFrame = true;
const { content, tileset } = tile;
if (content.featurePropertiesDirty) {
content.featurePropertiesDirty = false;
tile.lastStyleTime = 0;
tileset._selectedTilesToStyle.push(tile);
} else if (tile._selectedFrame < frameState.frameNumber - 1) {
tileset._selectedTilesToStyle.push(tile);
tile._wasSelectedLastFrame = false;
}
tile._selectedFrame = frameState.frameNumber;
tileset._selectedTiles.push(tile);
};
Cesium3DTilesetTraversal.visitTile = function(tile, frameState) {
++tile.tileset._statistics.visited;
tile._visitedFrame = frameState.frameNumber;
};
Cesium3DTilesetTraversal.touchTile = function(tile, frameState) {
if (tile._touchedFrame === frameState.frameNumber) {
return;
}
tile.tileset._cache.touch(tile);
tile._touchedFrame = frameState.frameNumber;
};
Cesium3DTilesetTraversal.loadTile = function(tile, frameState) {
const { tileset } = tile;
if (tile._requestedFrame === frameState.frameNumber || !tile.hasUnloadedRenderableContent && !tile.contentExpired) {
return;
}
if (!isOnScreenLongEnough(tile, frameState)) {
return;
}
const cameraHasNotStoppedMovingLongEnough = frameState.camera.timeSinceMoved < tileset.foveatedTimeDelay;
if (tile.priorityDeferred && cameraHasNotStoppedMovingLongEnough) {
return;
}
tile._requestedFrame = frameState.frameNumber;
tileset._requestedTiles.push(tile);
};
function isOnScreenLongEnough(tile, frameState) {
const { tileset } = tile;
if (!tileset._cullRequestsWhileMoving) {
return true;
}
const { positionWCDeltaMagnitude, positionWCDeltaMagnitudeLastFrame } = frameState.camera;
const deltaMagnitude = positionWCDeltaMagnitude !== 0 ? positionWCDeltaMagnitude : positionWCDeltaMagnitudeLastFrame;
const diameter = Math.max(tile.boundingSphere.radius * 2, 1);
const movementRatio = tileset.cullRequestsWhileMovingMultiplier * deltaMagnitude / diameter;
return movementRatio < 1;
}
Cesium3DTilesetTraversal.updateTile = function(tile, frameState) {
updateTileVisibility(tile, frameState);
tile.updateExpiration();
tile._wasMinPriorityChild = false;
tile._priorityHolder = tile;
updateMinimumMaximumPriority(tile);
tile._shouldSelect = false;
tile._finalResolution = true;
};
function updateTileVisibility(tile, frameState) {
tile.updateVisibility(frameState);
if (!tile.isVisible) {
return;
}
const hasChildren = tile.children.length > 0;
if ((tile.hasTilesetContent || tile.hasImplicitContent) && hasChildren) {
const child = tile.children[0];
updateTileVisibility(child, frameState);
tile._visible = child._visible;
return;
}
if (meetsScreenSpaceErrorEarly(tile, frameState)) {
tile._visible = false;
return;
}
const replace = tile.refine === Cesium3DTileRefine_default.REPLACE;
const useOptimization = tile._optimChildrenWithinParent === Cesium3DTileOptimizationHint_default.USE_OPTIMIZATION;
if (replace && useOptimization && hasChildren) {
if (!anyChildrenVisible(tile, frameState)) {
++tile.tileset._statistics.numberOfTilesCulledWithChildrenUnion;
tile._visible = false;
return;
}
}
}
function meetsScreenSpaceErrorEarly(tile, frameState) {
const { parent, tileset } = tile;
if (!defined_default(parent) || parent.hasTilesetContent || parent.hasImplicitContent || parent.refine !== Cesium3DTileRefine_default.ADD) {
return false;
}
return tile.getScreenSpaceError(frameState, true) <= tileset.memoryAdjustedScreenSpaceError;
}
function anyChildrenVisible(tile, frameState) {
let anyVisible = false;
const children = tile.children;
for (let i = 0; i < children.length; ++i) {
const child = children[i];
child.updateVisibility(frameState);
anyVisible = anyVisible || child.isVisible;
}
return anyVisible;
}
function updateMinimumMaximumPriority(tile) {
const minimumPriority = tile.tileset._minimumPriority;
const maximumPriority = tile.tileset._maximumPriority;
const priorityHolder = tile._priorityHolder;
maximumPriority.distance = Math.max(
priorityHolder._distanceToCamera,
maximumPriority.distance
);
minimumPriority.distance = Math.min(
priorityHolder._distanceToCamera,
minimumPriority.distance
);
maximumPriority.depth = Math.max(tile._depth, maximumPriority.depth);
minimumPriority.depth = Math.min(tile._depth, minimumPriority.depth);
maximumPriority.foveatedFactor = Math.max(
priorityHolder._foveatedFactor,
maximumPriority.foveatedFactor
);
minimumPriority.foveatedFactor = Math.min(
priorityHolder._foveatedFactor,
minimumPriority.foveatedFactor
);
maximumPriority.reverseScreenSpaceError = Math.max(
tile._priorityReverseScreenSpaceError,
maximumPriority.reverseScreenSpaceError
);
minimumPriority.reverseScreenSpaceError = Math.min(
tile._priorityReverseScreenSpaceError,
minimumPriority.reverseScreenSpaceError
);
}
var Cesium3DTilesetTraversal_default = Cesium3DTilesetTraversal;
// packages/engine/Source/Scene/Cesium3DTilesetMostDetailedTraversal.js
function Cesium3DTilesetMostDetailedTraversal() {
}
var traversal = {
stack: new ManagedArray_default(),
stackMaximumLength: 0
};
Cesium3DTilesetMostDetailedTraversal.selectTiles = function(tileset, frameState) {
tileset._selectedTiles.length = 0;
tileset._requestedTiles.length = 0;
tileset.hasMixedContent = false;
let ready = true;
const root = tileset.root;
root.updateVisibility(frameState);
if (!root.isVisible) {
return ready;
}
const { touchTile, visitTile: visitTile3 } = Cesium3DTilesetTraversal_default;
const stack = traversal.stack;
stack.push(root);
while (stack.length > 0) {
traversal.stackMaximumLength = Math.max(
traversal.stackMaximumLength,
stack.length
);
const tile = stack.pop();
const add2 = tile.refine === Cesium3DTileRefine_default.ADD;
const replace = tile.refine === Cesium3DTileRefine_default.REPLACE;
const traverse = canTraverse(tile);
if (traverse) {
updateAndPushChildren(tile, stack, frameState);
}
if (add2 || replace && !traverse) {
loadTile(tileset, tile);
touchTile(tile, frameState);
selectDesiredTile(tile, frameState);
if (tile.hasRenderableContent && !tile.contentAvailable) {
ready = false;
}
}
visitTile3(tile, frameState);
}
traversal.stack.trim(traversal.stackMaximumLength);
return ready;
};
function canTraverse(tile) {
if (tile.children.length === 0) {
return false;
}
if (tile.hasTilesetContent || tile.hasImplicitContent) {
return !tile.contentExpired;
}
if (tile.hasEmptyContent) {
return true;
}
return true;
}
function updateAndPushChildren(tile, stack, frameState) {
const { children } = tile;
for (let i = 0; i < children.length; ++i) {
const child = children[i];
child.updateVisibility(frameState);
if (child.isVisible) {
stack.push(child);
}
}
}
function loadTile(tileset, tile) {
if (tile.hasUnloadedRenderableContent || tile.contentExpired) {
tile._priority = 0;
tileset._requestedTiles.push(tile);
}
}
function selectDesiredTile(tile, frameState) {
if (tile.contentAvailable && tile.contentVisibility(frameState) !== Intersect_default.OUTSIDE) {
tile.tileset._selectedTiles.push(tile);
}
}
var Cesium3DTilesetMostDetailedTraversal_default = Cesium3DTilesetMostDetailedTraversal;
// packages/engine/Source/Scene/Cesium3DTilesetBaseTraversal.js
var import_InlineWorkers811 = __toESM(require_InlineWorkers(), 1);
function Cesium3DTilesetBaseTraversal() {
}
var traversal2 = {
stack: new ManagedArray_default(),
stackMaximumLength: 0
};
var emptyTraversal = {
stack: new ManagedArray_default(),
stackMaximumLength: 0
};
Cesium3DTilesetBaseTraversal.selectTiles = function(tileset, frameState) {
tileset._requestedTiles.length = 0;
if (tileset.debugFreezeFrame) {
return;
}
tileset._selectedTiles.length = 0;
tileset._selectedTilesToStyle.length = 0;
tileset._emptyTiles.length = 0;
tileset.hasMixedContent = false;
const root = tileset.root;
Cesium3DTilesetTraversal_default.updateTile(root, frameState);
if (!root.isVisible) {
return;
}
if (root.getScreenSpaceError(frameState, true) <= tileset.memoryAdjustedScreenSpaceError) {
return;
}
executeTraversal(root, frameState);
traversal2.stack.trim(traversal2.stackMaximumLength);
emptyTraversal.stack.trim(emptyTraversal.stackMaximumLength);
const requestedTiles = tileset._requestedTiles;
for (let i = 0; i < requestedTiles.length; ++i) {
requestedTiles[i].updatePriority();
}
};
function selectDesiredTile2(tile, frameState) {
if (tile.contentAvailable) {
Cesium3DTilesetTraversal_default.selectTile(tile, frameState);
}
}
function updateAndPushChildren2(tile, stack, frameState) {
const replace = tile.refine === Cesium3DTileRefine_default.REPLACE;
const { tileset, children } = tile;
const { updateTile, loadTile: loadTile2, touchTile } = Cesium3DTilesetTraversal_default;
for (let i = 0; i < children.length; ++i) {
updateTile(children[i], frameState);
}
children.sort(Cesium3DTilesetTraversal_default.sortChildrenByDistanceToCamera);
const checkRefines = replace && tile.hasRenderableContent;
let refines = true;
let anyChildrenVisible2 = false;
let minIndex = -1;
let minimumPriority = Number.MAX_VALUE;
for (let i = 0; i < children.length; ++i) {
const child = children[i];
if (child.isVisible) {
stack.push(child);
if (child._foveatedFactor < minimumPriority) {
minIndex = i;
minimumPriority = child._foveatedFactor;
}
anyChildrenVisible2 = true;
} else if (checkRefines || tileset.loadSiblings) {
if (child._foveatedFactor < minimumPriority) {
minIndex = i;
minimumPriority = child._foveatedFactor;
}
loadTile2(child, frameState);
touchTile(child, frameState);
}
if (checkRefines) {
let childRefines;
if (!child._inRequestVolume) {
childRefines = false;
} else if (!child.hasRenderableContent) {
childRefines = executeEmptyTraversal(child, frameState);
} else {
childRefines = child.contentAvailable;
}
refines = refines && childRefines;
}
}
if (!anyChildrenVisible2) {
refines = false;
}
if (minIndex !== -1 && replace) {
const minPriorityChild = children[minIndex];
minPriorityChild._wasMinPriorityChild = true;
const priorityHolder = (tile._wasMinPriorityChild || tile === tileset.root) && minimumPriority <= tile._priorityHolder._foveatedFactor ? tile._priorityHolder : tile;
priorityHolder._foveatedFactor = Math.min(
minPriorityChild._foveatedFactor,
priorityHolder._foveatedFactor
);
priorityHolder._distanceToCamera = Math.min(
minPriorityChild._distanceToCamera,
priorityHolder._distanceToCamera
);
for (let i = 0; i < children.length; ++i) {
children[i]._priorityHolder = priorityHolder;
}
}
return refines;
}
function executeTraversal(root, frameState) {
const { tileset } = root;
const { canTraverse: canTraverse2, loadTile: loadTile2, visitTile: visitTile3, touchTile } = Cesium3DTilesetTraversal_default;
const stack = traversal2.stack;
stack.push(root);
while (stack.length > 0) {
traversal2.stackMaximumLength = Math.max(
traversal2.stackMaximumLength,
stack.length
);
const tile = stack.pop();
const parent = tile.parent;
const parentRefines = !defined_default(parent) || parent._refines;
tile._refines = canTraverse2(tile) ? updateAndPushChildren2(tile, stack, frameState) && parentRefines : false;
const stoppedRefining = !tile._refines && parentRefines;
if (!tile.hasRenderableContent) {
tileset._emptyTiles.push(tile);
loadTile2(tile, frameState);
if (stoppedRefining) {
selectDesiredTile2(tile, frameState);
}
} else if (tile.refine === Cesium3DTileRefine_default.ADD) {
selectDesiredTile2(tile, frameState);
loadTile2(tile, frameState);
} else if (tile.refine === Cesium3DTileRefine_default.REPLACE) {
loadTile2(tile, frameState);
if (stoppedRefining) {
selectDesiredTile2(tile, frameState);
}
}
visitTile3(tile, frameState);
touchTile(tile, frameState);
}
}
function executeEmptyTraversal(root, frameState) {
const { canTraverse: canTraverse2, updateTile, loadTile: loadTile2, touchTile } = Cesium3DTilesetTraversal_default;
let allDescendantsLoaded = true;
const stack = emptyTraversal.stack;
stack.push(root);
while (stack.length > 0) {
emptyTraversal.stackMaximumLength = Math.max(
emptyTraversal.stackMaximumLength,
stack.length
);
const tile = stack.pop();
const children = tile.children;
const childrenLength = children.length;
const traverse = !tile.hasRenderableContent && canTraverse2(tile);
if (!traverse && !tile.contentAvailable) {
allDescendantsLoaded = false;
}
updateTile(tile, frameState);
if (!tile.isVisible) {
loadTile2(tile, frameState);
touchTile(tile, frameState);
}
if (traverse) {
for (let i = 0; i < childrenLength; ++i) {
const child = children[i];
stack.push(child);
}
}
}
return root.hasEmptyContent || allDescendantsLoaded;
}
var Cesium3DTilesetBaseTraversal_default = Cesium3DTilesetBaseTraversal;
// packages/engine/Source/Scene/Cesium3DTilesetSkipTraversal.js
var import_InlineWorkers812 = __toESM(require_InlineWorkers(), 1);
function Cesium3DTilesetSkipTraversal() {
}
var traversal3 = {
stack: new ManagedArray_default(),
stackMaximumLength: 0
};
var descendantTraversal = {
stack: new ManagedArray_default(),
stackMaximumLength: 0
};
var selectionTraversal = {
stack: new ManagedArray_default(),
stackMaximumLength: 0,
ancestorStack: new ManagedArray_default(),
ancestorStackMaximumLength: 0
};
var descendantSelectionDepth = 2;
Cesium3DTilesetSkipTraversal.selectTiles = function(tileset, frameState) {
tileset._requestedTiles.length = 0;
if (tileset.debugFreezeFrame) {
return;
}
tileset._selectedTiles.length = 0;
tileset._selectedTilesToStyle.length = 0;
tileset._emptyTiles.length = 0;
tileset.hasMixedContent = false;
const root = tileset.root;
Cesium3DTilesetTraversal_default.updateTile(root, frameState);
if (!root.isVisible) {
return;
}
if (root.getScreenSpaceError(frameState, true) <= tileset.memoryAdjustedScreenSpaceError) {
return;
}
executeTraversal2(root, frameState);
traverseAndSelect(root, frameState);
traversal3.stack.trim(traversal3.stackMaximumLength);
descendantTraversal.stack.trim(descendantTraversal.stackMaximumLength);
selectionTraversal.stack.trim(selectionTraversal.stackMaximumLength);
selectionTraversal.ancestorStack.trim(
selectionTraversal.ancestorStackMaximumLength
);
const requestedTiles = tileset._requestedTiles;
for (let i = 0; i < requestedTiles.length; ++i) {
requestedTiles[i].updatePriority();
}
};
function selectDescendants(root, frameState) {
const { updateTile, touchTile, selectTile } = Cesium3DTilesetTraversal_default;
const stack = descendantTraversal.stack;
stack.push(root);
while (stack.length > 0) {
descendantTraversal.stackMaximumLength = Math.max(
descendantTraversal.stackMaximumLength,
stack.length
);
const tile = stack.pop();
const children = tile.children;
for (let i = 0; i < children.length; ++i) {
const child = children[i];
if (child.isVisible) {
if (child.contentAvailable) {
updateTile(child, frameState);
touchTile(child, frameState);
selectTile(child, frameState);
} else if (child._depth - root._depth < descendantSelectionDepth) {
stack.push(child);
}
}
}
}
}
function selectDesiredTile3(tile, frameState) {
const loadedTile = tile.contentAvailable ? tile : tile._ancestorWithContentAvailable;
if (defined_default(loadedTile)) {
loadedTile._shouldSelect = true;
} else {
selectDescendants(tile, frameState);
}
}
function updateTileAncestorContentLinks(tile, frameState) {
tile._ancestorWithContent = void 0;
tile._ancestorWithContentAvailable = void 0;
const { parent } = tile;
if (!defined_default(parent)) {
return;
}
const parentHasContent = !parent.hasUnloadedRenderableContent || parent._requestedFrame === frameState.frameNumber;
tile._ancestorWithContent = parentHasContent ? parent : parent._ancestorWithContent;
tile._ancestorWithContentAvailable = parent.contentAvailable ? parent : parent._ancestorWithContentAvailable;
}
function reachedSkippingThreshold(tileset, tile) {
const ancestor = tile._ancestorWithContent;
return !tileset.immediatelyLoadDesiredLevelOfDetail && (tile._priorityProgressiveResolutionScreenSpaceErrorLeaf || defined_default(ancestor) && tile._screenSpaceError < ancestor._screenSpaceError / tileset.skipScreenSpaceErrorFactor && tile._depth > ancestor._depth + tileset.skipLevels);
}
function updateAndPushChildren3(tile, stack, frameState) {
const { tileset, children } = tile;
const { updateTile, loadTile: loadTile2, touchTile } = Cesium3DTilesetTraversal_default;
for (let i = 0; i < children.length; ++i) {
updateTile(children[i], frameState);
}
children.sort(Cesium3DTilesetTraversal_default.sortChildrenByDistanceToCamera);
let anyChildrenVisible2 = false;
for (let i = 0; i < children.length; ++i) {
const child = children[i];
if (child.isVisible) {
stack.push(child);
anyChildrenVisible2 = true;
} else if (tileset.loadSiblings) {
loadTile2(child, frameState);
touchTile(child, frameState);
}
}
return anyChildrenVisible2;
}
function inBaseTraversal(tile, baseScreenSpaceError) {
const { tileset } = tile;
if (tileset.immediatelyLoadDesiredLevelOfDetail) {
return false;
}
if (!defined_default(tile._ancestorWithContent)) {
return true;
}
if (tile._screenSpaceError === 0) {
return tile.parent._screenSpaceError > baseScreenSpaceError;
}
return tile._screenSpaceError > baseScreenSpaceError;
}
function executeTraversal2(root, frameState) {
const { tileset } = root;
const baseScreenSpaceError = tileset.immediatelyLoadDesiredLevelOfDetail ? Number.MAX_VALUE : Math.max(
tileset.baseScreenSpaceError,
tileset.memoryAdjustedScreenSpaceError
);
const { canTraverse: canTraverse2, loadTile: loadTile2, visitTile: visitTile3, touchTile } = Cesium3DTilesetTraversal_default;
const stack = traversal3.stack;
stack.push(root);
while (stack.length > 0) {
traversal3.stackMaximumLength = Math.max(
traversal3.stackMaximumLength,
stack.length
);
const tile = stack.pop();
updateTileAncestorContentLinks(tile, frameState);
const parent = tile.parent;
const parentRefines = !defined_default(parent) || parent._refines;
tile._refines = canTraverse2(tile) ? updateAndPushChildren3(tile, stack, frameState) && parentRefines : false;
const stoppedRefining = !tile._refines && parentRefines;
if (!tile.hasRenderableContent) {
tileset._emptyTiles.push(tile);
loadTile2(tile, frameState);
if (stoppedRefining) {
selectDesiredTile3(tile, frameState);
}
} else if (tile.refine === Cesium3DTileRefine_default.ADD) {
selectDesiredTile3(tile, frameState);
loadTile2(tile, frameState);
} else if (tile.refine === Cesium3DTileRefine_default.REPLACE) {
if (inBaseTraversal(tile, baseScreenSpaceError)) {
loadTile2(tile, frameState);
if (stoppedRefining) {
selectDesiredTile3(tile, frameState);
}
} else if (stoppedRefining) {
selectDesiredTile3(tile, frameState);
loadTile2(tile, frameState);
} else if (reachedSkippingThreshold(tileset, tile)) {
loadTile2(tile, frameState);
}
}
visitTile3(tile, frameState);
touchTile(tile, frameState);
}
}
function traverseAndSelect(root, frameState) {
const { selectTile, canTraverse: canTraverse2 } = Cesium3DTilesetTraversal_default;
const { stack, ancestorStack } = selectionTraversal;
let lastAncestor;
stack.push(root);
while (stack.length > 0 || ancestorStack.length > 0) {
selectionTraversal.stackMaximumLength = Math.max(
selectionTraversal.stackMaximumLength,
stack.length
);
selectionTraversal.ancestorStackMaximumLength = Math.max(
selectionTraversal.ancestorStackMaximumLength,
ancestorStack.length
);
if (ancestorStack.length > 0) {
const waitingTile = ancestorStack.peek();
if (waitingTile._stackLength === stack.length) {
ancestorStack.pop();
if (waitingTile !== lastAncestor) {
waitingTile._finalResolution = false;
}
selectTile(waitingTile, frameState);
continue;
}
}
const tile = stack.pop();
if (!defined_default(tile)) {
continue;
}
const traverse = canTraverse2(tile);
if (tile._shouldSelect) {
if (tile.refine === Cesium3DTileRefine_default.ADD) {
selectTile(tile, frameState);
} else {
tile._selectionDepth = ancestorStack.length;
if (tile._selectionDepth > 0) {
tile.tileset.hasMixedContent = true;
}
lastAncestor = tile;
if (!traverse) {
selectTile(tile, frameState);
continue;
}
ancestorStack.push(tile);
tile._stackLength = stack.length;
}
}
if (traverse) {
const children = tile.children;
for (let i = 0; i < children.length; ++i) {
const child = children[i];
if (child.isVisible) {
stack.push(child);
}
}
}
}
}
var Cesium3DTilesetSkipTraversal_default = Cesium3DTilesetSkipTraversal;
// packages/engine/Source/Scene/ImageryLayerCollection.js
var import_InlineWorkers813 = __toESM(require_InlineWorkers(), 1);
function ImageryLayerCollection() {
this._layers = [];
this.layerAdded = new Event_default();
this.layerRemoved = new Event_default();
this.layerMoved = new Event_default();
this.layerShownOrHidden = new Event_default();
}
Object.defineProperties(ImageryLayerCollection.prototype, {
/**
* Gets the number of layers in this collection.
* @memberof ImageryLayerCollection.prototype
* @type {number}
*/
length: {
get: function() {
return this._layers.length;
}
}
});
ImageryLayerCollection.prototype.add = function(layer, index) {
const hasIndex = defined_default(index);
if (!defined_default(layer)) {
throw new DeveloperError_default("layer is required.");
}
if (hasIndex) {
if (index < 0) {
throw new DeveloperError_default("index must be greater than or equal to zero.");
} else if (index > this._layers.length) {
throw new DeveloperError_default(
"index must be less than or equal to the number of layers."
);
}
}
if (!hasIndex) {
index = this._layers.length;
this._layers.push(layer);
} else {
this._layers.splice(index, 0, layer);
}
this._update();
this.layerAdded.raiseEvent(layer, index);
const removeReadyEventListener = layer.readyEvent.addEventListener(() => {
this.layerShownOrHidden.raiseEvent(layer, layer._layerIndex, layer.show);
removeReadyEventListener();
});
};
ImageryLayerCollection.prototype.addImageryProvider = function(imageryProvider, index) {
if (!defined_default(imageryProvider)) {
throw new DeveloperError_default("imageryProvider is required.");
}
const layer = new ImageryLayer_default(imageryProvider);
this.add(layer, index);
return layer;
};
ImageryLayerCollection.prototype.remove = function(layer, destroy) {
destroy = destroy ?? true;
const index = this._layers.indexOf(layer);
if (index !== -1) {
this._layers.splice(index, 1);
this._update();
this.layerRemoved.raiseEvent(layer, index);
if (destroy) {
layer.destroy();
}
return true;
}
return false;
};
ImageryLayerCollection.prototype.removeAll = function(destroy) {
destroy = destroy ?? true;
const layers = this._layers;
for (let i = 0, len = layers.length; i < len; i++) {
const layer = layers[i];
this.layerRemoved.raiseEvent(layer, i);
if (destroy) {
layer.destroy();
}
}
this._layers = [];
};
ImageryLayerCollection.prototype.contains = function(layer) {
return this.indexOf(layer) !== -1;
};
ImageryLayerCollection.prototype.indexOf = function(layer) {
return this._layers.indexOf(layer);
};
ImageryLayerCollection.prototype.get = function(index) {
if (!defined_default(index)) {
throw new DeveloperError_default("index is required.", "index");
}
return this._layers[index];
};
function getLayerIndex(layers, layer) {
if (!defined_default(layer)) {
throw new DeveloperError_default("layer is required.");
}
const index = layers.indexOf(layer);
if (index === -1) {
throw new DeveloperError_default("layer is not in this collection.");
}
return index;
}
function swapLayers(collection, i, j) {
const arr = collection._layers;
i = Math_default.clamp(i, 0, arr.length - 1);
j = Math_default.clamp(j, 0, arr.length - 1);
if (i === j) {
return;
}
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
collection._update();
collection.layerMoved.raiseEvent(temp, j, i);
}
ImageryLayerCollection.prototype.raise = function(layer) {
const index = getLayerIndex(this._layers, layer);
swapLayers(this, index, index + 1);
};
ImageryLayerCollection.prototype.lower = function(layer) {
const index = getLayerIndex(this._layers, layer);
swapLayers(this, index, index - 1);
};
ImageryLayerCollection.prototype.raiseToTop = function(layer) {
const index = getLayerIndex(this._layers, layer);
if (index === this._layers.length - 1) {
return;
}
this._layers.splice(index, 1);
this._layers.push(layer);
this._update();
this.layerMoved.raiseEvent(layer, this._layers.length - 1, index);
};
ImageryLayerCollection.prototype.lowerToBottom = function(layer) {
const index = getLayerIndex(this._layers, layer);
if (index === 0) {
return;
}
this._layers.splice(index, 1);
this._layers.splice(0, 0, layer);
this._update();
this.layerMoved.raiseEvent(layer, 0, index);
};
var applicableRectangleScratch = new Rectangle_default();
function pickImageryHelper(scene, pickedLocation, pickFeatures2, callback) {
const tilesToRender = scene.globe._surface._tilesToRender;
let pickedTile;
for (let textureIndex = 0; !defined_default(pickedTile) && textureIndex < tilesToRender.length; ++textureIndex) {
const tile = tilesToRender[textureIndex];
if (Rectangle_default.contains(tile.rectangle, pickedLocation)) {
pickedTile = tile;
}
}
if (!defined_default(pickedTile)) {
return;
}
const imageryTiles = pickedTile.data.imagery;
for (let i = imageryTiles.length - 1; i >= 0; --i) {
const terrainImagery = imageryTiles[i];
const imagery = terrainImagery.readyImagery;
if (!defined_default(imagery)) {
continue;
}
if (!imagery.imageryLayer.ready) {
continue;
}
const provider = imagery.imageryLayer.imageryProvider;
if (pickFeatures2 && !defined_default(provider.pickFeatures)) {
continue;
}
if (!Rectangle_default.contains(imagery.rectangle, pickedLocation)) {
continue;
}
const applicableRectangle = applicableRectangleScratch;
const epsilon = 1 / 1024;
applicableRectangle.west = Math_default.lerp(
pickedTile.rectangle.west,
pickedTile.rectangle.east,
terrainImagery.textureCoordinateRectangle.x - epsilon
);
applicableRectangle.east = Math_default.lerp(
pickedTile.rectangle.west,
pickedTile.rectangle.east,
terrainImagery.textureCoordinateRectangle.z + epsilon
);
applicableRectangle.south = Math_default.lerp(
pickedTile.rectangle.south,
pickedTile.rectangle.north,
terrainImagery.textureCoordinateRectangle.y - epsilon
);
applicableRectangle.north = Math_default.lerp(
pickedTile.rectangle.south,
pickedTile.rectangle.north,
terrainImagery.textureCoordinateRectangle.w + epsilon
);
if (!Rectangle_default.contains(applicableRectangle, pickedLocation)) {
continue;
}
callback(imagery);
}
}
ImageryLayerCollection.prototype.pickImageryLayers = function(ray, scene) {
const pickedPosition = scene.globe.pick(ray, scene);
if (!defined_default(pickedPosition)) {
return;
}
const pickedLocation = scene.ellipsoid.cartesianToCartographic(pickedPosition);
const imageryLayers = [];
pickImageryHelper(scene, pickedLocation, false, function(imagery) {
imageryLayers.push(imagery.imageryLayer);
});
if (imageryLayers.length === 0) {
return void 0;
}
return imageryLayers;
};
ImageryLayerCollection.prototype.pickImageryLayerFeatures = function(ray, scene) {
const pickedPosition = scene.globe.pick(ray, scene);
if (!defined_default(pickedPosition)) {
return;
}
const pickedLocation = scene.ellipsoid.cartesianToCartographic(pickedPosition);
const promises = [];
const imageryLayers = [];
pickImageryHelper(scene, pickedLocation, true, function(imagery) {
if (!imagery.imageryLayer.ready) {
return void 0;
}
const provider = imagery.imageryLayer.imageryProvider;
const promise = provider.pickFeatures(
imagery.x,
imagery.y,
imagery.level,
pickedLocation.longitude,
pickedLocation.latitude
);
if (defined_default(promise)) {
promises.push(promise);
imageryLayers.push(imagery.imageryLayer);
}
});
if (promises.length === 0) {
return void 0;
}
return Promise.all(promises).then(function(results) {
const features = [];
for (let resultIndex = 0; resultIndex < results.length; ++resultIndex) {
const result = results[resultIndex];
const image = imageryLayers[resultIndex];
if (defined_default(result) && result.length > 0) {
for (let featureIndex = 0; featureIndex < result.length; ++featureIndex) {
const feature2 = result[featureIndex];
feature2.imageryLayer = image;
if (!defined_default(feature2.position)) {
feature2.position = pickedLocation;
}
features.push(feature2);
}
}
}
return features;
});
};
ImageryLayerCollection.prototype.queueReprojectionCommands = function(frameState) {
const layers = this._layers;
for (let i = 0, len = layers.length; i < len; ++i) {
layers[i].queueReprojectionCommands(frameState);
}
};
ImageryLayerCollection.prototype.cancelReprojections = function() {
const layers = this._layers;
for (let i = 0, len = layers.length; i < len; ++i) {
layers[i].cancelReprojections();
}
};
ImageryLayerCollection.prototype.isDestroyed = function() {
return false;
};
ImageryLayerCollection.prototype.destroy = function() {
this.removeAll(true);
return destroyObject_default(this);
};
ImageryLayerCollection.prototype._update = function() {
let isBaseLayer = true;
const layers = this._layers;
let layersShownOrHidden;
let layer;
let i, len;
for (i = 0, len = layers.length; i < len; ++i) {
layer = layers[i];
layer._layerIndex = i;
if (layer.show) {
layer._isBaseLayer = isBaseLayer;
isBaseLayer = false;
} else {
layer._isBaseLayer = false;
}
if (layer.show !== layer._show) {
if (defined_default(layer._show)) {
if (!defined_default(layersShownOrHidden)) {
layersShownOrHidden = [];
}
layersShownOrHidden.push(layer);
}
layer._show = layer.show;
}
}
if (defined_default(layersShownOrHidden)) {
for (i = 0, len = layersShownOrHidden.length; i < len; ++i) {
layer = layersShownOrHidden[i];
this.layerShownOrHidden.raiseEvent(layer, layer._layerIndex, layer.show);
}
}
};
var ImageryLayerCollection_default = ImageryLayerCollection;
// packages/engine/Source/Scene/Cesium3DTileset.js
function Cesium3DTileset(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._url = void 0;
this._basePath = void 0;
this._root = void 0;
this._resource = void 0;
this._asset = void 0;
this._properties = void 0;
this._geometricError = void 0;
this._scaledGeometricError = void 0;
this._extensionsUsed = void 0;
this._extensions = void 0;
this._modelUpAxis = void 0;
this._modelForwardAxis = void 0;
this._cache = new Cesium3DTilesetCache_default();
this._processingQueue = [];
this._selectedTiles = [];
this._emptyTiles = [];
this._requestedTiles = [];
this._selectedTilesToStyle = [];
this._loadTimestamp = void 0;
this._timeSinceLoad = 0;
this._updatedVisibilityFrame = 0;
this._updatedModelMatrixFrame = 0;
this._modelMatrixChanged = false;
this._previousModelMatrix = void 0;
this._extras = void 0;
this._credits = void 0;
this._showCreditsOnScreen = options.showCreditsOnScreen ?? false;
this._cullWithChildrenBounds = options.cullWithChildrenBounds ?? true;
this._allTilesAdditive = true;
this._hasMixedContent = false;
this._stencilClearCommand = void 0;
this._backfaceCommands = new ManagedArray_default();
this._maximumScreenSpaceError = options.maximumScreenSpaceError ?? 16;
this._memoryAdjustedScreenSpaceError = this._maximumScreenSpaceError;
this._cacheBytes = options.cacheBytes ?? 512 * 1024 * 1024;
Check_default.typeOf.number.greaterThanOrEquals("cacheBytes", this._cacheBytes, 0);
const maximumCacheOverflowBytes = options.maximumCacheOverflowBytes ?? 512 * 1024 * 1024;
Check_default.typeOf.number.greaterThanOrEquals(
"maximumCacheOverflowBytes",
maximumCacheOverflowBytes,
0
);
this._maximumCacheOverflowBytes = maximumCacheOverflowBytes;
this._styleEngine = new Cesium3DTileStyleEngine_default();
this._styleApplied = false;
this._modelMatrix = defined_default(options.modelMatrix) ? Matrix4_default.clone(options.modelMatrix) : Matrix4_default.clone(Matrix4_default.IDENTITY);
this._addHeightCallbacks = [];
this._statistics = new Cesium3DTilesetStatistics_default();
this._statisticsLast = new Cesium3DTilesetStatistics_default();
this._statisticsPerPass = new Array(Cesium3DTilePass_default.NUMBER_OF_PASSES);
for (let i = 0; i < Cesium3DTilePass_default.NUMBER_OF_PASSES; ++i) {
this._statisticsPerPass[i] = new Cesium3DTilesetStatistics_default();
}
this._requestedTilesInFlight = [];
this._maximumPriority = {
foveatedFactor: -Number.MAX_VALUE,
depth: -Number.MAX_VALUE,
distance: -Number.MAX_VALUE,
reverseScreenSpaceError: -Number.MAX_VALUE
};
this._minimumPriority = {
foveatedFactor: Number.MAX_VALUE,
depth: Number.MAX_VALUE,
distance: Number.MAX_VALUE,
reverseScreenSpaceError: Number.MAX_VALUE
};
this._heatmap = new Cesium3DTilesetHeatmap_default(
options.debugHeatmapTilePropertyName
);
this.cullRequestsWhileMoving = options.cullRequestsWhileMoving ?? true;
this._cullRequestsWhileMoving = false;
this.cullRequestsWhileMovingMultiplier = options.cullRequestsWhileMovingMultiplier ?? 60;
this.progressiveResolutionHeightFraction = Math_default.clamp(
options.progressiveResolutionHeightFraction ?? 0.3,
0,
0.5
);
this.preferLeaves = options.preferLeaves ?? false;
this._tilesLoaded = false;
this._initialTilesLoaded = false;
this._tileDebugLabels = void 0;
this._classificationType = options.classificationType;
this._heightReference = options.heightReference;
this._scene = options.scene;
this._ellipsoid = options.ellipsoid ?? Ellipsoid_default.WGS84;
this._initialClippingPlanesOriginMatrix = Matrix4_default.IDENTITY;
this._clippingPlanesOriginMatrix = void 0;
this._clippingPlanesOriginMatrixDirty = true;
this._vectorClassificationOnly = options.vectorClassificationOnly ?? false;
this._vectorKeepDecodedPositions = options.vectorKeepDecodedPositions ?? false;
this._imageryLayers = new ImageryLayerCollection_default(this);
this._imageryLayersModificationCounter = 0;
this._imageryLayersListener = () => {
this._imageryLayersModificationCounter++;
};
this.imageryLayers.layerAdded.addEventListener(this._imageryLayersListener);
this.imageryLayers.layerRemoved.addEventListener(this._imageryLayersListener);
this.imageryLayers.layerMoved.addEventListener(this._imageryLayersListener);
this.imageryLayers.layerShownOrHidden.addEventListener(
this._imageryLayersListener
);
this._asynchronouslyLoadImagery = options.asynchronouslyLoadImagery ?? false;
this.preloadWhenHidden = options.preloadWhenHidden ?? false;
this.preloadFlightDestinations = options.preloadFlightDestinations ?? true;
this._pass = void 0;
this.dynamicScreenSpaceError = options.dynamicScreenSpaceError ?? true;
this.foveatedScreenSpaceError = options.foveatedScreenSpaceError ?? true;
this._foveatedConeSize = options.foveatedConeSize ?? 0.1;
this._foveatedMinimumScreenSpaceErrorRelaxation = options.foveatedMinimumScreenSpaceErrorRelaxation ?? 0;
this.foveatedInterpolationCallback = options.foveatedInterpolationCallback ?? Math_default.lerp;
this.foveatedTimeDelay = options.foveatedTimeDelay ?? 0.2;
this.dynamicScreenSpaceErrorDensity = options.dynamicScreenSpaceErrorDensity ?? 2e-4;
this.dynamicScreenSpaceErrorFactor = options.dynamicScreenSpaceErrorFactor ?? 24;
this.dynamicScreenSpaceErrorHeightFalloff = options.dynamicScreenSpaceErrorHeightFalloff ?? 0.25;
this._dynamicScreenSpaceErrorComputedDensity = 0;
this.shadows = options.shadows ?? ShadowMode_default.ENABLED;
this.show = options.show ?? true;
this.colorBlendMode = Cesium3DTileColorBlendMode_default.HIGHLIGHT;
this.colorBlendAmount = 0.5;
this._pointCloudShading = new PointCloudShading_default(options.pointCloudShading);
this._pointCloudEyeDomeLighting = new PointCloudEyeDomeLighting_default2();
this.loadProgress = new Event_default();
this.allTilesLoaded = new Event_default();
this.initialTilesLoaded = new Event_default();
this.tileLoad = new Event_default();
this.tileUnload = new Event_default();
this.tileFailed = new Event_default();
this.tileVisible = new Event_default();
this.skipLevelOfDetail = options.skipLevelOfDetail ?? false;
this._disableSkipLevelOfDetail = false;
this.baseScreenSpaceError = options.baseScreenSpaceError ?? 1024;
this.skipScreenSpaceErrorFactor = options.skipScreenSpaceErrorFactor ?? 16;
this.skipLevels = options.skipLevels ?? 1;
this.immediatelyLoadDesiredLevelOfDetail = options.immediatelyLoadDesiredLevelOfDetail ?? false;
this.loadSiblings = options.loadSiblings ?? false;
this._clippingPlanes = void 0;
if (defined_default(options.clippingPlanes)) {
ClippingPlaneCollection_default.setOwner(
options.clippingPlanes,
this,
"_clippingPlanes"
);
}
this._clippingPolygons = void 0;
if (defined_default(options.clippingPolygons)) {
ClippingPolygonCollection_default.setOwner(
options.clippingPolygons,
this,
"_clippingPolygons"
);
}
if (defined_default(options.imageBasedLighting)) {
this._imageBasedLighting = options.imageBasedLighting;
this._shouldDestroyImageBasedLighting = false;
} else {
this._imageBasedLighting = new ImageBasedLighting_default();
this._shouldDestroyImageBasedLighting = true;
}
this._environmentMapManager = new DynamicEnvironmentMapManager_default(
options.environmentMapOptions
);
this.lightColor = options.lightColor;
this.backFaceCulling = options.backFaceCulling ?? true;
this._enableShowOutline = options.enableShowOutline ?? true;
this.showOutline = options.showOutline ?? true;
this.outlineColor = options.outlineColor ?? Color_default.BLACK;
this.splitDirection = options.splitDirection ?? SplitDirection_default.NONE;
this.enableCollision = options.enableCollision ?? false;
this._projectTo2D = options.projectTo2D ?? false;
this._enablePick = options.enablePick ?? false;
this.debugFreezeFrame = options.debugFreezeFrame ?? false;
this.debugColorizeTiles = options.debugColorizeTiles ?? false;
this._enableDebugWireframe = options.enableDebugWireframe ?? false;
this.debugWireframe = options.debugWireframe ?? false;
if (this.debugWireframe === true && this._enableDebugWireframe === false) {
oneTimeWarning_default(
"tileset-debug-wireframe-ignored",
"enableDebugWireframe must be set to true in the Cesium3DTileset constructor, otherwise debugWireframe will be ignored."
);
}
this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this.debugShowContentBoundingVolume = options.debugShowContentBoundingVolume ?? false;
this.debugShowViewerRequestVolume = options.debugShowViewerRequestVolume ?? false;
this._tileDebugLabels = void 0;
this.debugPickedTileLabelOnly = false;
this.debugPickedTile = void 0;
this.debugPickPosition = void 0;
this.debugShowGeometricError = options.debugShowGeometricError ?? false;
this.debugShowRenderingStatistics = options.debugShowRenderingStatistics ?? false;
this.debugShowMemoryUsage = options.debugShowMemoryUsage ?? false;
this.debugShowUrl = options.debugShowUrl ?? false;
this.examineVectorLinesFunction = void 0;
this._metadataExtension = void 0;
this._customShader = options.customShader;
let featureIdLabel = options.featureIdLabel ?? "featureId_0";
if (typeof featureIdLabel === "number") {
featureIdLabel = `featureId_${featureIdLabel}`;
}
this._featureIdLabel = featureIdLabel;
let instanceFeatureIdLabel = options.instanceFeatureIdLabel ?? "instanceFeatureId_0";
if (typeof instanceFeatureIdLabel === "number") {
instanceFeatureIdLabel = `instanceFeatureId_${instanceFeatureIdLabel}`;
}
this._instanceFeatureIdLabel = instanceFeatureIdLabel;
}
Object.defineProperties(Cesium3DTileset.prototype, {
/**
* NOTE: This getter exists so that `Picking.js` can differentiate between
* PrimitiveCollection and Cesium3DTileset objects without inflating
* the size of the module via `instanceof Cesium3DTileset`
* @private
*/
isCesium3DTileset: {
get: function() {
return true;
}
},
/**
* Gets the tileset's asset object property, which contains metadata about the tileset.
*
* See the {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification#reference-asset|asset schema reference}
* in the 3D Tiles spec for the full set of properties.
*
*
* @memberof Cesium3DTileset.prototype
*
* @type {object}
* @readonly
*/
asset: {
get: function() {
return this._asset;
}
},
/**
* Gets the tileset's extensions object property.
*
* @memberof Cesium3DTileset.prototype
*
* @type {object}
* @readonly
*/
extensions: {
get: function() {
return this._extensions;
}
},
/**
* The {@link ClippingPlaneCollection} used to selectively disable rendering the tileset.
*
* @memberof Cesium3DTileset.prototype
*
* @type {ClippingPlaneCollection}
*/
clippingPlanes: {
get: function() {
return this._clippingPlanes;
},
set: function(value) {
ClippingPlaneCollection_default.setOwner(value, this, "_clippingPlanes");
}
},
/**
* The {@link ClippingPolygonCollection} used to selectively disable rendering the tileset.
*
* @memberof Cesium3DTileset.prototype
*
* @type {ClippingPolygonCollection}
*/
clippingPolygons: {
get: function() {
return this._clippingPolygons;
},
set: function(value) {
ClippingPolygonCollection_default.setOwner(value, this, "_clippingPolygons");
}
},
/**
* The collection of ImageryLayer objects providing 2D georeferenced
* image data that will be rendered over the tileset.
*
* The imagery will be draped over glTF, B3DM, PNTS, or GeoJSON tile content.
*
* @see ImageryLayer
*
* @memberof Cesium3DTileset.prototype
* @readonly
* @type {ImageryLayerCollection}
*
* @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* // Drape Bing Maps Aerial imagery over the tileset
* const imageryProvider = await Cesium.createWorldImageryAsync({
* style: Cesium.IonWorldImageryStyle.AERIAL,
* });
* const imageryLayer = new ImageryLayer(imageryProvider);
* tileset.imageryLayers.add(imageryLayer);
*/
imageryLayers: {
get: function() {
return this._imageryLayers;
}
},
/**
* The modification counter of the imagery layers.
*
* This is incremented for each modification (layerAdded, layerMoved,
* layerRemoved, layerShownOrHidden) of the imagery layers, and can
* be used internally (by ModelPrimitiveImagery)
* to trigger updates whenever the collection of imagery layers
* changes.
*
* @memberof Cesium3DTileset.prototype
* @readonly
* @type {number}
* @private
*/
imageryLayersModificationCounter: {
get: function() {
return this._imageryLayersModificationCounter;
}
},
/**
* Whether loading imagery that is draped over the tileset should be
* done asynchronously.
*
* @memberof Cesium3DTileset.prototype
* @readonly
* @type {boolean}
* @private
*/
asynchronouslyLoadImagery: {
get: function() {
return this._asynchronouslyLoadImagery;
}
},
/**
* Gets the tileset's properties dictionary object, which contains metadata about per-feature properties.
*
* See the {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification#reference-properties|properties schema reference}
* in the 3D Tiles spec for the full set of properties.
*
*
* @memberof Cesium3DTileset.prototype
*
* @type {object}
* @readonly
*
* @example
* console.log(`Maximum building height: ${tileset.properties.height.maximum}`);
* console.log(`Minimum building height: ${tileset.properties.height.minimum}`);
*
* @see Cesium3DTileFeature#getProperty
* @see Cesium3DTileFeature#setProperty
*/
properties: {
get: function() {
return this._properties;
}
},
/**
* When true, all tiles that meet the screen space error this frame are loaded. The tileset is
* completely loaded for this view.
*
* @memberof Cesium3DTileset.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*
* @see Cesium3DTileset#allTilesLoaded
*/
tilesLoaded: {
get: function() {
return this._tilesLoaded;
}
},
/**
* The resource used to fetch the tileset JSON file
*
* @memberof Cesium3DTileset.prototype
*
* @type {Resource}
* @readonly
*/
resource: {
get: function() {
return this._resource;
}
},
/**
* The base path that non-absolute paths in tileset JSON file are relative to.
*
* @memberof Cesium3DTileset.prototype
*
* @type {string}
* @readonly
* @deprecated
*/
basePath: {
get: function() {
deprecationWarning_default(
"Cesium3DTileset.basePath",
"Cesium3DTileset.basePath has been deprecated. All tiles are relative to the url of the tileset JSON file that contains them. Use the url property instead."
);
return this._basePath;
}
},
/**
* The style, defined using the
* {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification/Styling|3D Tiles Styling language},
* applied to each feature in the tileset.
*
* Assign undefined to remove the style, which will restore the visual
* appearance of the tileset to its default when no style was applied.
*
*
* The style is applied to a tile before the {@link Cesium3DTileset#tileVisible}
* event is raised, so code in tileVisible can manually set a feature's
* properties (e.g. color and show) after the style is applied. When
* a new style is assigned any manually set properties are overwritten.
*
*
* Use an always "true" condition to specify the Color for all objects that are not
* overridden by pre-existing conditions. Otherwise, the default color Cesium.Color.White
* will be used. Similarly, use an always "true" condition to specify the show property
* for all objects that are not overridden by pre-existing conditions. Otherwise, the
* default show value true will be used.
*
*
* @memberof Cesium3DTileset.prototype
*
* @type {Cesium3DTileStyle|undefined}
*
* @default undefined
*
* @example
* tileset.style = new Cesium.Cesium3DTileStyle({
* color : {
* conditions : [
* ['${Height} >= 100', 'color("purple", 0.5)'],
* ['${Height} >= 50', 'color("red")'],
* ['true', 'color("blue")']
* ]
* },
* show : '${Height} > 0',
* meta : {
* description : '"Building id ${id} has height ${Height}."'
* }
* });
*
* @see {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification/Styling|3D Tiles Styling language}
*/
style: {
get: function() {
return this._styleEngine.style;
},
set: function(value) {
this._styleEngine.style = value;
}
},
/**
* A custom shader to apply to all tiles in the tileset. Only used for
* contents that use {@link Model}. Using custom shaders with a
* {@link Cesium3DTileStyle} may lead to undefined behavior.
*
* @memberof Cesium3DTileset.prototype
*
* @type {CustomShader|undefined}
*
* @default undefined
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
customShader: {
get: function() {
return this._customShader;
},
set: function(value) {
this._customShader = value;
}
},
/**
* Whether the tileset is rendering different levels of detail in the same view.
* Only relevant if {@link Cesium3DTileset.isSkippingLevelOfDetail} is true.
*
* @memberof Cesium3DTileset.prototype
*
* @type {boolean}
* @private
*/
hasMixedContent: {
get: function() {
return this._hasMixedContent;
},
set: function(value) {
Check_default.typeOf.bool("value", value);
this._hasMixedContent = value;
}
},
/**
* Whether this tileset is actually skipping levels of detail.
* The user option may have been disabled if all tiles are using additive refinement,
* or if some tiles have a content type for which rendering does not support skipping
*
* @memberof Cesium3DTileset.prototype
*
* @type {boolean}
* @private
* @readonly
*/
isSkippingLevelOfDetail: {
get: function() {
return this.skipLevelOfDetail && !defined_default(this._classificationType) && !this._disableSkipLevelOfDetail && !this._allTilesAdditive;
}
},
/**
* The tileset's schema, groups, tileset metadata and other details from the
* 3DTILES_metadata extension or a 3D Tiles 1.1 tileset JSON. This getter is
* for internal use by other classes.
*
* @memberof Cesium3DTileset.prototype
* @type {Cesium3DTilesetMetadata}
* @private
* @readonly
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
metadataExtension: {
get: function() {
return this._metadataExtension;
}
},
/**
* The metadata properties attached to the tileset as a whole.
*
* @memberof Cesium3DTileset.prototype
*
* @type {TilesetMetadata}
* @private
* @readonly
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
metadata: {
get: function() {
if (defined_default(this._metadataExtension)) {
return this._metadataExtension.tileset;
}
return void 0;
}
},
/**
* The metadata schema used in this tileset. Shorthand for
* tileset.metadataExtension.schema
*
* @memberof Cesium3DTileset.prototype
*
* @type {MetadataSchema}
* @private
* @readonly
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
schema: {
get: function() {
if (defined_default(this._metadataExtension)) {
return this._metadataExtension.schema;
}
return void 0;
}
},
/**
* The maximum screen space error used to drive level of detail refinement. This value helps determine when a tile
* refines to its descendants, and therefore plays a major role in balancing performance with visual quality.
*
* A tile's screen space error is roughly equivalent to the number of pixels wide that would be drawn if a sphere with a
* radius equal to the tile's geometric error were rendered at the tile's position. If this value exceeds
* maximumScreenSpaceError the tile refines to its descendants.
*
*
* Depending on the tileset, maximumScreenSpaceError may need to be tweaked to achieve the right balance.
* Higher values provide better performance but lower visual quality.
*
*
* @memberof Cesium3DTileset.prototype
*
* @type {number}
* @default 16
*
* @exception {DeveloperError} maximumScreenSpaceError must be greater than or equal to zero.
*/
maximumScreenSpaceError: {
get: function() {
return this._maximumScreenSpaceError;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals(
"maximumScreenSpaceError",
value,
0
);
this._maximumScreenSpaceError = value;
this._memoryAdjustedScreenSpaceError = value;
}
},
/**
* The amount of GPU memory (in bytes) used to cache tiles. This memory usage is estimated from
* geometry, textures, and batch table textures of loaded tiles. For point clouds, this value also
* includes per-point metadata.
*
* Tiles not in view are unloaded to enforce this.
*
*
* If decreasing this value results in unloading tiles, the tiles are unloaded the next frame.
*
*
* If tiles sized more than cacheBytes are needed to meet the
* desired screen space error, determined by {@link Cesium3DTileset#maximumScreenSpaceError},
* for the current view, then the memory usage of the tiles loaded will exceed
* cacheBytes by up to maximumCacheOverflowBytes.
* For example, if cacheBytes is 500000, but 600000 bytes
* of tiles are needed to meet the screen space error, then 600000 bytes of tiles
* may be loaded (if maximumCacheOverflowBytes is at least 100000).
* When these tiles go out of view, they will be unloaded.
*
*
* @memberof Cesium3DTileset.prototype
*
* @type {number}
* @default 536870912
*
* @exception {DeveloperError} cacheBytes must be typeof 'number' and greater than or equal to 0
* @see Cesium3DTileset#totalMemoryUsageInBytes
*/
cacheBytes: {
get: function() {
return this._cacheBytes;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._cacheBytes = value;
}
},
/**
* The maximum additional amount of GPU memory (in bytes) that will be used to cache tiles.
*
* If tiles sized more than cacheBytes plus maximumCacheOverflowBytes
* are needed to meet the desired screen space error, determined by
* {@link Cesium3DTileset#maximumScreenSpaceError} for the current view, then
* {@link Cesium3DTileset#memoryAdjustedScreenSpaceError} will be adjusted
* until the tiles required to meet the adjusted screen space error use less
* than cacheBytes plus maximumCacheOverflowBytes.
*
*
* @memberof Cesium3DTileset.prototype
*
* @type {number}
* @default 536870912
*
* @exception {DeveloperError} maximumCacheOverflowBytes must be typeof 'number' and greater than or equal to 0
* @see Cesium3DTileset#totalMemoryUsageInBytes
*/
maximumCacheOverflowBytes: {
get: function() {
return this._maximumCacheOverflowBytes;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._maximumCacheOverflowBytes = value;
}
},
/**
* If loading the level of detail required by @{link Cesium3DTileset#maximumScreenSpaceError}
* results in the memory usage exceeding @{link Cesium3DTileset#cacheBytes}
* plus @{link Cesium3DTileset#maximumCacheOverflowBytes}, level of detail refinement
* will instead use this (larger) adjusted screen space error to achieve the
* best possible visual quality within the available memory
*
* @memberof Cesium3DTileset.prototype
*
* @type {number}
* @readonly
*
* @private
*/
memoryAdjustedScreenSpaceError: {
get: function() {
return this._memoryAdjustedScreenSpaceError;
}
},
/**
* Options for controlling point size based on geometric error and eye dome lighting.
*
* @memberof Cesium3DTileset.prototype
*
* @type {PointCloudShading}
*/
pointCloudShading: {
get: function() {
return this._pointCloudShading;
},
set: function(value) {
Check_default.defined("pointCloudShading", value);
this._pointCloudShading = value;
}
},
/**
* The root tile.
*
* @memberOf Cesium3DTileset.prototype
*
* @type {Cesium3DTile}
* @readonly
*/
root: {
get: function() {
return this._root;
}
},
/**
* The tileset's bounding sphere.
*
* @memberof Cesium3DTileset.prototype
*
* @type {BoundingSphere}
* @readonly
*
* @example
* const tileset = await Cesium.Cesium3DTileset.fromUrl("http://localhost:8002/tilesets/Seattle/tileset.json");
*
* viewer.scene.primitives.add(tileset);
*
* // Set the camera to view the newly added tileset
* viewer.camera.viewBoundingSphere(tileset.boundingSphere, new Cesium.HeadingPitchRange(0, -0.5, 0));
*/
boundingSphere: {
get: function() {
this._root.updateTransform(this._modelMatrix);
return this._root.boundingSphere;
}
},
/**
* A 4x4 transformation matrix that transforms the entire tileset.
*
* @memberof Cesium3DTileset.prototype
*
* @type {Matrix4}
* @default Matrix4.IDENTITY
*
* @example
* // Adjust a tileset's height from the globe's surface.
* const heightOffset = 20.0;
* const boundingSphere = tileset.boundingSphere;
* const cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);
* const surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
* const offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);
* const translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
* tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
*/
modelMatrix: {
get: function() {
return this._modelMatrix;
},
set: function(value) {
this._modelMatrix = Matrix4_default.clone(value, this._modelMatrix);
}
},
/**
* Returns the time, in milliseconds, since the tileset was loaded and first updated.
*
* @memberof Cesium3DTileset.prototype
*
* @type {number}
* @readonly
*/
timeSinceLoad: {
get: function() {
return this._timeSinceLoad;
}
},
/**
* The total amount of GPU memory in bytes used by the tileset. This value is estimated from
* geometry, texture, batch table textures, and binary metadata of loaded tiles.
*
* @memberof Cesium3DTileset.prototype
*
* @type {number}
* @readonly
*
* @see Cesium3DTileset#cacheBytes
*/
totalMemoryUsageInBytes: {
get: function() {
const statistics2 = this._statistics;
return statistics2.texturesByteLength + statistics2.geometryByteLength + statistics2.batchTableByteLength;
}
},
/**
* @private
*/
clippingPlanesOriginMatrix: {
get: function() {
if (!defined_default(this._clippingPlanesOriginMatrix)) {
return Matrix4_default.IDENTITY;
}
if (this._clippingPlanesOriginMatrixDirty) {
Matrix4_default.multiply(
this.root.computedTransform,
this._initialClippingPlanesOriginMatrix,
this._clippingPlanesOriginMatrix
);
this._clippingPlanesOriginMatrixDirty = false;
}
return this._clippingPlanesOriginMatrix;
}
},
/**
* @private
*/
styleEngine: {
get: function() {
return this._styleEngine;
}
},
/**
* @private
*/
statistics: {
get: function() {
return this._statistics;
}
},
/**
* Determines whether terrain, 3D Tiles, or both will be classified by this tileset.
*
* This option is only applied to tilesets containing batched 3D models,
* glTF content, geometry data, or vector data. Even when undefined, vector
* and geometry data must render as classifications and will default to
* rendering on both terrain and other 3D Tiles tilesets.
*
*
* When enabled for batched 3D model and glTF tilesets, there are a few
* requirements/limitations on the glTF:
*
* - The glTF cannot contain morph targets, skins, or animations.
* - The glTF cannot contain the
EXT_mesh_gpu_instancing extension.
* - Only meshes with TRIANGLES can be used to classify other assets.
* - The meshes must be watertight.
* - The
POSITION semantic is required.
* - If
_BATCHIDs and an index buffer are both present, all indices with the same batch id must occupy contiguous sections of the index buffer.
* - If
_BATCHIDs are present with no index buffer, all positions with the same batch id must occupy contiguous sections of the position buffer.
*
*
*
* Additionally, classification is not supported for points or instanced 3D
* models.
*
*
* The 3D Tiles or terrain receiving the classification must be opaque.
*
*
* @memberof Cesium3DTileset.prototype
*
* @type {ClassificationType}
* @default undefined
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
* @readonly
*/
classificationType: {
get: function() {
return this._classificationType;
}
},
/**
* Specifies if the height is relative to terrain, 3D Tiles, or both.
*
* This option is only applied to point features in tilesets containing vector data.
* This option requires the Viewer's scene to be passed in through options.scene.
*
*
* @memberof Cesium3DTileset.prototype
*
* @type {HeightReference | undefined}
* @default undefined
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
* @readonly
*/
heightReference: {
get: function() {
return this._heightReference;
}
},
/**
* The {@link CesiumWidget#scene} that the tileset will be rendered in, required for tilesets that specify a {@link heightReference} value for clamping 3D Tiles vector data content- like points, lines, and labels- to terrain or 3D tiles.
*
* @member of Cesium3DTileset.prototype
*
* @type {Scene | undefined}
* @default undefined
* @readonly
*
*/
scene: {
get: function() {
return this._scene;
}
},
/**
* Gets an ellipsoid describing the shape of the globe.
*
* @memberof Cesium3DTileset.prototype
*
* @type {Ellipsoid}
* @readonly
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
},
/**
* Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control the cone size that determines which tiles are deferred.
* Tiles that are inside this cone are loaded immediately. Tiles outside the cone are potentially deferred based on how far outside the cone they are and {@link Cesium3DTileset#foveatedInterpolationCallback} and {@link Cesium3DTileset#foveatedMinimumScreenSpaceErrorRelaxation}.
* Setting this to 0.0 means the cone will be the line formed by the camera position and its view direction. Setting this to 1.0 means the cone encompasses the entire field of view of the camera, essentially disabling the effect.
*
* @memberof Cesium3DTileset.prototype
*
* @type {number}
* @default 0.3
*/
foveatedConeSize: {
get: function() {
return this._foveatedConeSize;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("foveatedConeSize", value, 0);
Check_default.typeOf.number.lessThanOrEquals("foveatedConeSize", value, 1);
this._foveatedConeSize = value;
}
},
/**
* Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control the starting screen space error relaxation for tiles outside the foveated cone.
* The screen space error will be raised starting with this value up to {@link Cesium3DTileset#maximumScreenSpaceError} based on the provided {@link Cesium3DTileset#foveatedInterpolationCallback}.
*
* @memberof Cesium3DTileset.prototype
*
* @type {number}
* @default 0.0
*/
foveatedMinimumScreenSpaceErrorRelaxation: {
get: function() {
return this._foveatedMinimumScreenSpaceErrorRelaxation;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals(
"foveatedMinimumScreenSpaceErrorRelaxation",
value,
0
);
Check_default.typeOf.number.lessThanOrEquals(
"foveatedMinimumScreenSpaceErrorRelaxation",
value,
this.maximumScreenSpaceError
);
this._foveatedMinimumScreenSpaceErrorRelaxation = value;
}
},
/**
* Returns the extras property at the top-level of the tileset JSON, which contains application specific metadata.
* Returns undefined if extras does not exist.
*
* @memberof Cesium3DTileset.prototype
*
* @type {*}
* @readonly
*
* @see {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification#specifying-extensions-and-application-specific-extras|Extras in the 3D Tiles specification.}
*/
extras: {
get: function() {
return this._extras;
}
},
/**
* The properties for managing image-based lighting on this tileset.
*
* @memberof Cesium3DTileset.prototype
*
* @type {ImageBasedLighting}
*/
imageBasedLighting: {
get: function() {
return this._imageBasedLighting;
},
set: function(value) {
Check_default.typeOf.object("imageBasedLighting", this._imageBasedLighting);
if (value !== this._imageBasedLighting) {
if (this._shouldDestroyImageBasedLighting && !this._imageBasedLighting.isDestroyed()) {
this._imageBasedLighting.destroy();
}
this._imageBasedLighting = value;
this._shouldDestroyImageBasedLighting = false;
}
}
},
/**
* The properties for managing dynamic environment maps on this model. Affects lighting.
*
* @memberof Cesium3DTileset.prototype
* @readonly
*
* @example
* // Change the ground color used for a tileset's environment map to a forest green
* const environmentMapManager = tileset.environmentMapManager;
* environmentMapManager.groundColor = Cesium.Color.fromCssColorString("#203b34");
*
* @type {DynamicEnvironmentMapManager}
*/
environmentMapManager: {
get: function() {
return this._environmentMapManager;
}
},
/**
* Indicates that only the tileset's vector tiles should be used for classification.
*
* @memberof Cesium3DTileset.prototype
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @type {boolean}
* @default false
*/
vectorClassificationOnly: {
get: function() {
return this._vectorClassificationOnly;
}
},
/**
* Whether vector tiles should keep decoded positions in memory.
* This is used with {@link Cesium3DTileFeature.getPolylinePositions}.
*
* @memberof Cesium3DTileset.prototype
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @type {boolean}
* @default false
*/
vectorKeepDecodedPositions: {
get: function() {
return this._vectorKeepDecodedPositions;
}
},
/**
* Determines whether the credits of the tileset will be displayed on the screen
*
* @memberof Cesium3DTileset.prototype
*
* @type {boolean}
* @default false
*/
showCreditsOnScreen: {
get: function() {
return this._showCreditsOnScreen;
},
set: function(value) {
this._showCreditsOnScreen = value;
createCredits(this);
}
},
/**
* Label of the feature ID set to use for picking and styling.
*
* For EXT_mesh_features, this is the feature ID's label property, or
* "featureId_N" (where N is the index in the featureIds array) when not
* specified. EXT_feature_metadata did not have a label field, so such
* feature ID sets are always labeled "featureId_N" where N is the index in
* the list of all feature Ids, where feature ID attributes are listed before
* feature ID textures.
*
*
* If featureIdLabel is set to an integer N, it is converted to
* the string "featureId_N" automatically. If both per-primitive and
* per-instance feature IDs are present, the instance feature IDs take
* priority.
*
*
* @memberof Cesium3DTileset.prototype
*
* @type {string}
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
featureIdLabel: {
get: function() {
return this._featureIdLabel;
},
set: function(value) {
if (typeof value === "number") {
value = `featureId_${value}`;
}
Check_default.typeOf.string("value", value);
this._featureIdLabel = value;
}
},
/**
* Label of the instance feature ID set used for picking and styling.
*
* If instanceFeatureIdLabel is set to an integer N, it is converted to
* the string "instanceFeatureId_N" automatically.
* If both per-primitive and per-instance feature IDs are present, the
* instance feature IDs take priority.
*
*
* @memberof Cesium3DTileset.prototype
*
* @type {string}
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
instanceFeatureIdLabel: {
get: function() {
return this._instanceFeatureIdLabel;
},
set: function(value) {
if (typeof value === "number") {
value = `instanceFeatureId_${value}`;
}
Check_default.typeOf.string("value", value);
this._instanceFeatureIdLabel = value;
}
}
});
Cesium3DTileset.fromIonAssetId = async function(assetId, options) {
Check_default.defined("assetId", assetId);
const resource = await IonResource_default.fromAssetId(assetId);
return Cesium3DTileset.fromUrl(resource, options);
};
Cesium3DTileset.fromUrl = async function(url2, options) {
Check_default.defined("url", url2);
options = options ?? Frozen_default.EMPTY_OBJECT;
const resource = Resource_default.createIfNeeded(url2);
let basePath;
if (resource.extension === "json") {
basePath = resource.getBaseUri(true);
} else if (resource.isDataUri) {
basePath = "";
}
const tilesetJson = await Cesium3DTileset.loadJson(resource);
const metadataExtension = await processMetadataExtension(
resource,
tilesetJson
);
const tileset = new Cesium3DTileset(options);
tileset._resource = resource;
tileset._url = resource.url;
tileset._basePath = basePath;
tileset._metadataExtension = metadataExtension;
tileset._geometricError = tilesetJson.geometricError;
tileset._scaledGeometricError = tilesetJson.geometricError;
const asset = tilesetJson.asset;
tileset._asset = asset;
tileset._extras = tilesetJson.extras;
createCredits(tileset);
const gltfUpAxis = defined_default(tilesetJson.asset.gltfUpAxis) ? Axis_default.fromName(tilesetJson.asset.gltfUpAxis) : Axis_default.Y;
const modelUpAxis = options.modelUpAxis ?? gltfUpAxis;
const modelForwardAxis = options.modelForwardAxis ?? Axis_default.X;
tileset._properties = tilesetJson.properties;
tileset._extensionsUsed = tilesetJson.extensionsUsed;
tileset._extensions = tilesetJson.extensions;
tileset._modelUpAxis = modelUpAxis;
tileset._modelForwardAxis = modelForwardAxis;
tileset._root = tileset.loadTileset(resource, tilesetJson);
const boundingVolume = tileset._root.createBoundingVolume(
tilesetJson.root.boundingVolume,
Matrix4_default.IDENTITY
);
const clippingPlanesOrigin = boundingVolume.boundingSphere.center;
const originCartographic = tileset._ellipsoid.cartesianToCartographic(clippingPlanesOrigin);
if (defined_default(originCartographic) && originCartographic.height > ApproximateTerrainHeights_default._defaultMinTerrainHeight) {
tileset._initialClippingPlanesOriginMatrix = Transforms_default.eastNorthUpToFixedFrame(clippingPlanesOrigin);
}
tileset._clippingPlanesOriginMatrix = Matrix4_default.clone(
tileset._initialClippingPlanesOriginMatrix
);
return tileset;
};
Cesium3DTileset.loadJson = function(tilesetUrl) {
const resource = Resource_default.createIfNeeded(tilesetUrl);
return resource.fetchJson();
};
Cesium3DTileset.prototype.makeStyleDirty = function() {
this._styleEngine.makeDirty();
};
Cesium3DTileset.prototype.loadTileset = function(resource, tilesetJson, parentTile) {
const asset = tilesetJson.asset;
if (!defined_default(asset)) {
throw new RuntimeError_default("Tileset must have an asset property.");
}
if (asset.version !== "0.0" && asset.version !== "1.0" && asset.version !== "1.1") {
throw new RuntimeError_default(
"The tileset must be 3D Tiles version 0.0, 1.0, or 1.1"
);
}
if (defined_default(tilesetJson.extensionsRequired)) {
Cesium3DTileset.checkSupportedExtensions(tilesetJson.extensionsRequired);
}
const statistics2 = this._statistics;
const tilesetVersion = asset.tilesetVersion;
if (defined_default(tilesetVersion)) {
this._basePath += `?v=${tilesetVersion}`;
resource = resource.clone();
resource.setQueryParameters({ v: tilesetVersion });
}
const rootTile = makeTile2(this, resource, tilesetJson.root, parentTile);
if (defined_default(parentTile)) {
parentTile.children.push(rootTile);
rootTile._depth = parentTile._depth + 1;
}
const stack = [];
stack.push(rootTile);
while (stack.length > 0) {
const tile = stack.pop();
++statistics2.numberOfTilesTotal;
this._allTilesAdditive = this._allTilesAdditive && tile.refine === Cesium3DTileRefine_default.ADD;
const children = tile._header.children;
if (defined_default(children)) {
for (let i = 0; i < children.length; ++i) {
const childHeader = children[i];
const childTile = makeTile2(this, resource, childHeader, tile);
tile.children.push(childTile);
childTile._depth = tile._depth + 1;
stack.push(childTile);
}
}
if (this._cullWithChildrenBounds) {
Cesium3DTileOptimizations_default.checkChildrenWithinParent(tile);
}
}
return rootTile;
};
function makeTile2(tileset, baseResource2, tileHeader, parentTile) {
const hasImplicitTiling = defined_default(tileHeader.implicitTiling) || hasExtension_default(tileHeader, "3DTILES_implicit_tiling");
if (!hasImplicitTiling) {
return new Cesium3DTile_default(tileset, baseResource2, tileHeader, parentTile);
}
const metadataSchema = tileset.schema;
const implicitTileset = new ImplicitTileset_default(
baseResource2,
tileHeader,
metadataSchema
);
const rootCoordinates = new ImplicitTileCoordinates_default({
subdivisionScheme: implicitTileset.subdivisionScheme,
subtreeLevels: implicitTileset.subtreeLevels,
level: 0,
x: 0,
y: 0,
// The constructor will only use this for octrees.
z: 0
});
const contentUri = implicitTileset.subtreeUriTemplate.getDerivedResource({
templateValues: rootCoordinates.getTemplateValues()
}).url;
const deepCopy = true;
const tileJson = clone_default(tileHeader, deepCopy);
tileJson.contents = [
{
uri: contentUri
}
];
delete tileJson.content;
delete tileJson.extensions;
const tile = new Cesium3DTile_default(tileset, baseResource2, tileJson, parentTile);
tile.implicitTileset = implicitTileset;
tile.implicitCoordinates = rootCoordinates;
return tile;
}
async function processMetadataExtension(resource, tilesetJson) {
const metadataJson = hasExtension_default(tilesetJson, "3DTILES_metadata") ? tilesetJson.extensions["3DTILES_metadata"] : tilesetJson;
let schemaLoader;
if (defined_default(metadataJson.schemaUri)) {
resource = resource.getDerivedResource({
url: metadataJson.schemaUri
});
schemaLoader = ResourceCache_default.getSchemaLoader({
resource
});
} else if (defined_default(metadataJson.schema)) {
schemaLoader = ResourceCache_default.getSchemaLoader({
schema: metadataJson.schema
});
} else {
return;
}
await schemaLoader.load();
const metadataExtension = new Cesium3DTilesetMetadata_default({
schema: schemaLoader.schema,
metadataJson
});
ResourceCache_default.unload(schemaLoader);
return metadataExtension;
}
var scratchPositionNormal = new Cartesian3_default();
var scratchCartographic9 = new Cartographic_default();
var scratchMatrix5 = new Matrix4_default();
var scratchCenter5 = new Cartesian3_default();
var scratchPosition7 = new Cartesian3_default();
var scratchDirection = new Cartesian3_default();
var scratchHalfHeight = new Cartesian3_default();
function updateDynamicScreenSpaceError(tileset, frameState) {
let up;
let direction2;
let height;
let minimumHeight;
let maximumHeight;
const camera = frameState.camera;
const root = tileset._root;
const tileBoundingVolume = root.contentBoundingVolume;
if (tileBoundingVolume instanceof TileBoundingRegion_default) {
up = Cartesian3_default.normalize(camera.positionWC, scratchPositionNormal);
direction2 = camera.directionWC;
height = camera.positionCartographic.height;
minimumHeight = tileBoundingVolume.minimumHeight;
maximumHeight = tileBoundingVolume.maximumHeight;
} else {
const transformLocal = Matrix4_default.inverseTransformation(
root.computedTransform,
scratchMatrix5
);
const ellipsoid = frameState.mapProjection.ellipsoid;
const boundingVolume = tileBoundingVolume.boundingVolume;
const centerLocal = Matrix4_default.multiplyByPoint(
transformLocal,
boundingVolume.center,
scratchCenter5
);
if (Cartesian3_default.magnitude(centerLocal) > ellipsoid.minimumRadius) {
const centerCartographic = Cartographic_default.fromCartesian(
centerLocal,
ellipsoid,
scratchCartographic9
);
up = Cartesian3_default.normalize(camera.positionWC, scratchPositionNormal);
direction2 = camera.directionWC;
height = camera.positionCartographic.height;
minimumHeight = 0;
maximumHeight = centerCartographic.height * 2;
} else {
const positionLocal = Matrix4_default.multiplyByPoint(
transformLocal,
camera.positionWC,
scratchPosition7
);
up = Cartesian3_default.UNIT_Z;
direction2 = Matrix4_default.multiplyByPointAsVector(
transformLocal,
camera.directionWC,
scratchDirection
);
direction2 = Cartesian3_default.normalize(direction2, direction2);
height = positionLocal.z;
if (tileBoundingVolume instanceof TileOrientedBoundingBox_default) {
const halfHeightVector = Matrix3_default.getColumn(
boundingVolume.halfAxes,
2,
scratchHalfHeight
);
const halfHeight = Cartesian3_default.magnitude(halfHeightVector);
minimumHeight = centerLocal.z - halfHeight;
maximumHeight = centerLocal.z + halfHeight;
} else if (tileBoundingVolume instanceof TileBoundingSphere_default) {
const radius = boundingVolume.radius;
minimumHeight = centerLocal.z - radius;
maximumHeight = centerLocal.z + radius;
}
}
}
const heightFalloff = tileset.dynamicScreenSpaceErrorHeightFalloff;
const heightClose = minimumHeight + (maximumHeight - minimumHeight) * heightFalloff;
const heightFar = maximumHeight;
const t = Math_default.clamp(
(height - heightClose) / (heightFar - heightClose),
0,
1
);
let horizonFactor = 1 - Math.abs(Cartesian3_default.dot(direction2, up));
horizonFactor = horizonFactor * (1 - t);
tileset._dynamicScreenSpaceErrorComputedDensity = tileset.dynamicScreenSpaceErrorDensity * horizonFactor;
}
function requestContent(tileset, tile) {
if (tile.hasEmptyContent) {
return;
}
const { statistics: statistics2 } = tileset;
const contentExpired = tile.contentExpired;
const promise = tile.requestContent();
if (!defined_default(promise)) {
return;
}
promise.then((content) => {
if (!defined_default(content) || tile.isDestroyed() || tileset.isDestroyed()) {
return;
}
tileset._processingQueue.push(tile);
++statistics2.numberOfTilesProcessing;
}).catch((error) => {
handleTileFailure(error, tileset, tile);
});
if (contentExpired) {
if (tile.hasTilesetContent || tile.hasImplicitContent) {
destroySubtree(tileset, tile);
} else {
statistics2.decrementLoadCounts(tile.content);
--statistics2.numberOfTilesWithContentReady;
}
}
tileset._requestedTilesInFlight.push(tile);
}
function sortTilesByPriority(a3, b) {
return a3._priority - b._priority;
}
Cesium3DTileset.prototype.postPassesUpdate = function(frameState) {
if (!defined_default(this._root)) {
return;
}
cancelOutOfViewRequests(this, frameState);
raiseLoadProgressEvent(this, frameState);
this._cache.unloadTiles(this, unloadTile);
if (this._styleApplied) {
this._styleEngine.resetDirty();
}
this._styleApplied = false;
};
Cesium3DTileset.prototype.prePassesUpdate = function(frameState) {
if (!defined_default(this._root)) {
return;
}
processTiles(this, frameState);
const clippingPlanes = this._clippingPlanes;
this._clippingPlanesOriginMatrixDirty = true;
if (defined_default(clippingPlanes) && clippingPlanes.enabled) {
clippingPlanes.update(frameState);
}
const clippingPolygons = this._clippingPolygons;
if (defined_default(clippingPolygons) && clippingPolygons.enabled) {
clippingPolygons.update(frameState);
}
if (!defined_default(this._loadTimestamp)) {
this._loadTimestamp = JulianDate_default.clone(frameState.time);
}
this._timeSinceLoad = Math.max(
JulianDate_default.secondsDifference(frameState.time, this._loadTimestamp) * 1e3,
0
);
if (this.dynamicScreenSpaceError) {
updateDynamicScreenSpaceError(this, frameState);
}
if (frameState.newFrame) {
this._cache.reset();
}
};
function cancelOutOfViewRequests(tileset, frameState) {
const requestedTilesInFlight = tileset._requestedTilesInFlight;
let removeCount = 0;
for (let i = 0; i < requestedTilesInFlight.length; ++i) {
const tile = requestedTilesInFlight[i];
const outOfView = frameState.frameNumber - tile._touchedFrame >= 1;
if (tile._contentState !== Cesium3DTileContentState_default.LOADING) {
++removeCount;
continue;
} else if (outOfView) {
tile.cancelRequests();
++removeCount;
continue;
}
if (removeCount > 0) {
requestedTilesInFlight[i - removeCount] = tile;
}
}
requestedTilesInFlight.length -= removeCount;
}
function requestTiles(tileset) {
const requestedTiles = tileset._requestedTiles;
requestedTiles.sort(sortTilesByPriority);
for (let i = 0; i < requestedTiles.length; ++i) {
requestContent(tileset, requestedTiles[i]);
}
}
function handleTileFailure(error, tileset, tile) {
if (tileset.isDestroyed()) {
return;
}
let url2;
if (!tile.isDestroyed()) {
url2 = tile._contentResource.url;
}
const message = defined_default(error.message) ? error.message : error.toString();
if (tileset.tileFailed.numberOfListeners > 0) {
tileset.tileFailed.raiseEvent({
url: url2,
message
});
} else {
console.log(`A 3D tile failed to load: ${url2}`);
console.log(`Error: ${message}`);
console.log(error.stack);
}
}
function filterProcessingQueue(tileset) {
const tiles = tileset._processingQueue;
let removeCount = 0;
for (let i = 0; i < tiles.length; ++i) {
const tile = tiles[i];
if (tile.isDestroyed() || tile._contentState !== Cesium3DTileContentState_default.PROCESSING) {
++removeCount;
continue;
}
if (removeCount > 0) {
tiles[i - removeCount] = tile;
}
}
tiles.length -= removeCount;
}
var scratchUpdateHeightCartographic = new Cartographic_default();
var scratchUpdateHeightCartographic2 = new Cartographic_default();
var scratchUpdateHeightCartesian2 = new Cartesian3_default();
function processUpdateHeight(tileset, tile, frameState) {
if (!tileset.enableCollision || !tileset.show) {
return;
}
const heightCallbackData = tileset._addHeightCallbacks;
const boundingSphere = tile.boundingSphere;
for (const callbackData of heightCallbackData) {
if (callbackData.invoked || tile._wasSelectedLastFrame) {
continue;
}
const ellipsoid = callbackData.ellipsoid;
const positionCartographic = Cartographic_default.clone(
callbackData.positionCartographic,
scratchUpdateHeightCartographic
);
const centerCartographic = Cartographic_default.fromCartesian(
boundingSphere.center,
ellipsoid,
scratchUpdateHeightCartographic2
);
if (defined_default(centerCartographic)) {
positionCartographic.height = centerCartographic.height;
}
const position = Cartographic_default.toCartesian(
positionCartographic,
ellipsoid,
scratchUpdateHeightCartesian2
);
if (Cartesian3_default.distance(position, boundingSphere.center) <= boundingSphere.radius) {
callbackData.invoked = true;
frameState.afterRender.push(() => {
if (defined_default(callbackData.callback)) {
callbackData.callback();
}
callbackData.invoked = false;
});
}
}
}
function processTiles(tileset, frameState) {
filterProcessingQueue(tileset);
const tiles = tileset._processingQueue;
const { cacheBytes, maximumCacheOverflowBytes, statistics: statistics2 } = tileset;
const cacheByteLimit = cacheBytes + maximumCacheOverflowBytes;
let memoryExceeded = false;
for (let i = 0; i < tiles.length; ++i) {
if (tileset.totalMemoryUsageInBytes > cacheByteLimit) {
memoryExceeded = true;
break;
}
const tile = tiles[i];
try {
tile.process(tileset, frameState);
if (tile.contentReady) {
--statistics2.numberOfTilesProcessing;
tileset.tileLoad.raiseEvent(tile);
}
} catch (error) {
--statistics2.numberOfTilesProcessing;
handleTileFailure(error, tileset, tile);
}
}
if (tileset.totalMemoryUsageInBytes < cacheBytes) {
decreaseScreenSpaceError(tileset);
} else if (memoryExceeded && tiles.length > 0) {
increaseScreenSpaceError(tileset);
}
}
function increaseScreenSpaceError(tileset) {
oneTimeWarning_default(
"increase-screenSpaceError",
`The tiles needed to meet maximumScreenSpaceError would use more memory than allocated for this tileset.
The tileset will be rendered with a larger screen space error (see memoryAdjustedScreenSpaceError).
Consider using larger values for cacheBytes and maximumCacheOverflowBytes.`
);
tileset._memoryAdjustedScreenSpaceError *= 1.02;
const tiles = tileset._processingQueue;
for (let i = 0; i < tiles.length; ++i) {
tiles[i].updatePriority();
}
tiles.sort(sortTilesByPriority);
}
function decreaseScreenSpaceError(tileset) {
tileset._memoryAdjustedScreenSpaceError = Math.max(
tileset.memoryAdjustedScreenSpaceError / 1.02,
tileset.maximumScreenSpaceError
);
}
var scratchCartesian15 = new Cartesian3_default();
var stringOptions = {
maximumFractionDigits: 3
};
function formatMemoryString(memorySizeInBytes) {
const memoryInMegabytes = memorySizeInBytes / 1048576;
if (memoryInMegabytes < 1) {
return memoryInMegabytes.toLocaleString(void 0, stringOptions);
}
return Math.round(memoryInMegabytes).toLocaleString();
}
function computeTileLabelPosition(tile) {
const { halfAxes, radius, center } = tile.boundingVolume.boundingVolume;
let position = Cartesian3_default.clone(center, scratchCartesian15);
if (defined_default(halfAxes)) {
position.x += 0.75 * (halfAxes[0] + halfAxes[3] + halfAxes[6]);
position.y += 0.75 * (halfAxes[1] + halfAxes[4] + halfAxes[7]);
position.z += 0.75 * (halfAxes[2] + halfAxes[5] + halfAxes[8]);
} else if (defined_default(radius)) {
let normal2 = Cartesian3_default.normalize(center, scratchCartesian15);
normal2 = Cartesian3_default.multiplyByScalar(
normal2,
0.75 * radius,
scratchCartesian15
);
position = Cartesian3_default.add(normal2, center, scratchCartesian15);
}
return position;
}
function addTileDebugLabel(tile, tileset, position) {
let labelString = "";
let attributes = 0;
if (tileset.debugShowGeometricError) {
labelString += `
Geometric error: ${tile.geometricError}`;
attributes++;
}
if (tileset.debugShowRenderingStatistics) {
labelString += `
Commands: ${tile.commandsLength}`;
attributes++;
const numberOfPoints = tile.content.pointsLength;
if (numberOfPoints > 0) {
labelString += `
Points: ${tile.content.pointsLength}`;
attributes++;
}
const numberOfTriangles = tile.content.trianglesLength;
if (numberOfTriangles > 0) {
labelString += `
Triangles: ${tile.content.trianglesLength}`;
attributes++;
}
labelString += `
Features: ${tile.content.featuresLength}`;
attributes++;
}
if (tileset.debugShowMemoryUsage) {
labelString += `
Texture Memory: ${formatMemoryString(
tile.content.texturesByteLength
)}`;
labelString += `
Geometry Memory: ${formatMemoryString(
tile.content.geometryByteLength
)}`;
attributes += 2;
}
if (tileset.debugShowUrl) {
if (tile.hasMultipleContents) {
labelString += "\nUrls:";
const urls = tile.content.innerContentUrls;
for (let i = 0; i < urls.length; i++) {
labelString += `
- ${urls[i]}`;
}
attributes += urls.length;
} else {
labelString += `
Url: ${tile._contentHeader.uri}`;
attributes++;
}
}
const newLabel = {
text: labelString.substring(1),
position,
font: `${19 - attributes}px sans-serif`,
showBackground: true,
disableDepthTestDistance: Number.POSITIVE_INFINITY
};
return tileset._tileDebugLabels.add(newLabel);
}
function updateTileDebugLabels(tileset, frameState) {
const selectedTiles = tileset._selectedTiles;
const selectedLength = selectedTiles.length;
const emptyTiles = tileset._emptyTiles;
const emptyLength = emptyTiles.length;
tileset._tileDebugLabels.removeAll();
if (tileset.debugPickedTileLabelOnly) {
if (defined_default(tileset.debugPickedTile)) {
const position = defined_default(tileset.debugPickPosition) ? tileset.debugPickPosition : computeTileLabelPosition(tileset.debugPickedTile);
const label = addTileDebugLabel(
tileset.debugPickedTile,
tileset,
position
);
label.pixelOffset = new Cartesian2_default(15, -15);
}
} else {
for (let i = 0; i < selectedLength; ++i) {
const tile = selectedTiles[i];
addTileDebugLabel(tile, tileset, computeTileLabelPosition(tile));
}
for (let i = 0; i < emptyLength; ++i) {
const tile = emptyTiles[i];
if (tile.hasTilesetContent || tile.hasImplicitContent) {
addTileDebugLabel(tile, tileset, computeTileLabelPosition(tile));
}
}
}
tileset._tileDebugLabels.update(frameState);
}
function updateTiles(tileset, frameState, passOptions2) {
tileset._styleEngine.applyStyle(tileset);
tileset._styleApplied = true;
const { commandList, context } = frameState;
const numberOfInitialCommands = commandList.length;
const selectedTiles = tileset._selectedTiles;
const bivariateVisibilityTest = tileset.isSkippingLevelOfDetail && tileset._hasMixedContent && context.stencilBuffer && selectedTiles.length > 0;
tileset._backfaceCommands.length = 0;
if (bivariateVisibilityTest) {
if (!defined_default(tileset._stencilClearCommand)) {
tileset._stencilClearCommand = new ClearCommand_default({
stencil: 0,
pass: Pass_default.CESIUM_3D_TILE,
renderState: RenderState_default.fromCache({
stencilMask: StencilConstants_default.SKIP_LOD_MASK
})
});
}
commandList.push(tileset._stencilClearCommand);
}
const { statistics: statistics2, tileVisible } = tileset;
const isRender = passOptions2.isRender;
const lengthBeforeUpdate = commandList.length;
for (let i = 0; i < selectedTiles.length; ++i) {
const tile = selectedTiles[i];
if (isRender) {
tileVisible.raiseEvent(tile);
}
processUpdateHeight(tileset, tile, frameState);
tile.update(tileset, frameState, passOptions2);
statistics2.incrementSelectionCounts(tile.content);
++statistics2.selected;
}
const emptyTiles = tileset._emptyTiles;
for (let i = 0; i < emptyTiles.length; ++i) {
const tile = emptyTiles[i];
tile.update(tileset, frameState, passOptions2);
}
let addedCommandsLength = commandList.length - lengthBeforeUpdate;
tileset._backfaceCommands.trim();
if (bivariateVisibilityTest) {
const backfaceCommands = tileset._backfaceCommands.values;
const backfaceCommandsLength = backfaceCommands.length;
commandList.length += backfaceCommandsLength;
for (let i = addedCommandsLength - 1; i >= 0; --i) {
commandList[lengthBeforeUpdate + backfaceCommandsLength + i] = commandList[lengthBeforeUpdate + i];
}
for (let i = 0; i < backfaceCommandsLength; ++i) {
commandList[lengthBeforeUpdate + i] = backfaceCommands[i];
}
}
addedCommandsLength = commandList.length - numberOfInitialCommands;
statistics2.numberOfCommands = addedCommandsLength;
if (!isRender) {
return;
}
if (tileset.pointCloudShading.attenuation && tileset.pointCloudShading.eyeDomeLighting && addedCommandsLength > 0) {
tileset._pointCloudEyeDomeLighting.update(
frameState,
numberOfInitialCommands,
tileset.pointCloudShading,
tileset.boundingSphere
);
}
if (tileset.debugShowGeometricError || tileset.debugShowRenderingStatistics || tileset.debugShowMemoryUsage || tileset.debugShowUrl) {
if (!defined_default(tileset._tileDebugLabels)) {
tileset._tileDebugLabels = new LabelCollection_default();
}
updateTileDebugLabels(tileset, frameState);
} else {
tileset._tileDebugLabels = tileset._tileDebugLabels && tileset._tileDebugLabels.destroy();
}
}
var scratchStack2 = [];
function destroySubtree(tileset, tile) {
const root = tile;
const stack = scratchStack2;
stack.push(tile);
while (stack.length > 0) {
tile = stack.pop();
const children = tile.children;
for (let i = 0; i < children.length; ++i) {
stack.push(children[i]);
}
if (tile !== root) {
destroyTile(tileset, tile);
--tileset._statistics.numberOfTilesTotal;
}
}
root.children = [];
}
function unloadTile(tileset, tile) {
tileset.tileUnload.raiseEvent(tile);
tileset._statistics.decrementLoadCounts(tile.content);
--tileset._statistics.numberOfTilesWithContentReady;
tile.unloadContent();
}
function destroyTile(tileset, tile) {
tileset._cache.unloadTile(tileset, tile, unloadTile);
tile.destroy();
}
Cesium3DTileset.prototype.trimLoadedTiles = function() {
this._cache.trim();
};
function raiseLoadProgressEvent(tileset, frameState) {
const statistics2 = tileset._statistics;
const statisticsLast = tileset._statisticsLast;
const numberOfPendingRequests = statistics2.numberOfPendingRequests;
const numberOfTilesProcessing = statistics2.numberOfTilesProcessing;
const lastNumberOfPendingRequest = statisticsLast.numberOfPendingRequests;
const lastNumberOfTilesProcessing = statisticsLast.numberOfTilesProcessing;
Cesium3DTilesetStatistics_default.clone(statistics2, statisticsLast);
const progressChanged = numberOfPendingRequests !== lastNumberOfPendingRequest || numberOfTilesProcessing !== lastNumberOfTilesProcessing;
if (progressChanged) {
frameState.afterRender.push(function() {
tileset.loadProgress.raiseEvent(
numberOfPendingRequests,
numberOfTilesProcessing
);
return true;
});
}
tileset._tilesLoaded = statistics2.numberOfPendingRequests === 0 && statistics2.numberOfTilesProcessing === 0 && statistics2.numberOfAttemptedRequests === 0;
if (progressChanged && tileset._tilesLoaded) {
frameState.afterRender.push(function() {
tileset.allTilesLoaded.raiseEvent();
return true;
});
if (!tileset._initialTilesLoaded) {
tileset._initialTilesLoaded = true;
frameState.afterRender.push(function() {
tileset.initialTilesLoaded.raiseEvent();
return true;
});
}
}
}
function resetMinimumMaximum(tileset) {
tileset._heatmap.resetMinimumMaximum();
tileset._minimumPriority.depth = Number.MAX_VALUE;
tileset._maximumPriority.depth = -Number.MAX_VALUE;
tileset._minimumPriority.foveatedFactor = Number.MAX_VALUE;
tileset._maximumPriority.foveatedFactor = -Number.MAX_VALUE;
tileset._minimumPriority.distance = Number.MAX_VALUE;
tileset._maximumPriority.distance = -Number.MAX_VALUE;
tileset._minimumPriority.reverseScreenSpaceError = Number.MAX_VALUE;
tileset._maximumPriority.reverseScreenSpaceError = -Number.MAX_VALUE;
}
function detectModelMatrixChanged(tileset, frameState) {
if (frameState.frameNumber === tileset._updatedModelMatrixFrame && defined_default(tileset._previousModelMatrix)) {
return;
}
tileset._updatedModelMatrixFrame = frameState.frameNumber;
tileset._modelMatrixChanged = !Matrix4_default.equals(
tileset.modelMatrix,
tileset._previousModelMatrix
);
if (tileset._modelMatrixChanged) {
tileset._previousModelMatrix = Matrix4_default.clone(
tileset.modelMatrix,
tileset._previousModelMatrix
);
}
}
function update3(tileset, frameState, passStatistics, passOptions2) {
if (frameState.mode === SceneMode_default.MORPHING) {
return false;
}
if (!defined_default(tileset._root)) {
return false;
}
const statistics2 = tileset._statistics;
statistics2.clear();
++tileset._updatedVisibilityFrame;
resetMinimumMaximum(tileset);
detectModelMatrixChanged(tileset, frameState);
tileset._cullRequestsWhileMoving = tileset.cullRequestsWhileMoving && !tileset._modelMatrixChanged;
const ready = tileset.getTraversal(passOptions2).selectTiles(tileset, frameState);
if (passOptions2.requestTiles) {
requestTiles(tileset);
}
updateTiles(tileset, frameState, passOptions2);
Cesium3DTilesetStatistics_default.clone(statistics2, passStatistics);
if (passOptions2.isRender) {
const credits = tileset._credits;
if (defined_default(credits) && statistics2.selected !== 0) {
for (let i = 0; i < credits.length; ++i) {
const credit = credits[i];
frameState.creditDisplay.addCreditToNextFrame(credit);
}
}
}
return ready;
}
function createCredits(tileset) {
let credits = tileset._credits;
if (!defined_default(credits)) {
credits = [];
}
credits.length = 0;
if (defined_default(tileset.resource.credits)) {
tileset.resource.credits.forEach((credit) => {
credits.push(Credit_default.clone(credit));
});
}
const assetExtras = tileset.asset.extras;
if (defined_default(assetExtras) && defined_default(assetExtras.cesium) && defined_default(assetExtras.cesium.credits)) {
const extraCredits = assetExtras.cesium.credits;
for (let i = 0; i < extraCredits.length; ++i) {
const credit = extraCredits[i];
credits.push(new Credit_default(credit.html));
}
}
credits.forEach(
(credit) => credit.showOnScreen = credit.showOnScreen || tileset._showCreditsOnScreen
);
tileset._credits = credits;
}
Cesium3DTileset.prototype.getTraversal = function(passOptions2) {
const { pass } = passOptions2;
if (pass === Cesium3DTilePass_default.MOST_DETAILED_PRELOAD || pass === Cesium3DTilePass_default.MOST_DETAILED_PICK) {
return Cesium3DTilesetMostDetailedTraversal_default;
}
return this.isSkippingLevelOfDetail ? Cesium3DTilesetSkipTraversal_default : Cesium3DTilesetBaseTraversal_default;
};
Cesium3DTileset.prototype.update = function(frameState) {
this.updateForPass(frameState, frameState.tilesetPassState);
};
Cesium3DTileset.prototype.updateForPass = function(frameState, tilesetPassState) {
Check_default.typeOf.object("frameState", frameState);
Check_default.typeOf.object("tilesetPassState", tilesetPassState);
this.imageryLayers._update();
const pass = tilesetPassState.pass;
if (pass === Cesium3DTilePass_default.PRELOAD && (!this.preloadWhenHidden || this.show) || pass === Cesium3DTilePass_default.PRELOAD_FLIGHT && (!this.preloadFlightDestinations || !this.show && !this.preloadWhenHidden) || pass === Cesium3DTilePass_default.REQUEST_RENDER_MODE_DEFER_CHECK && (!this._cullRequestsWhileMoving && this.foveatedTimeDelay <= 0 || !this.show)) {
return;
}
const originalCommandList = frameState.commandList;
const originalCamera = frameState.camera;
const originalCullingVolume = frameState.cullingVolume;
tilesetPassState.ready = false;
const passOptions2 = Cesium3DTilePass_default.getPassOptions(pass);
const ignoreCommands = passOptions2.ignoreCommands;
const commandList = tilesetPassState.commandList ?? originalCommandList;
const commandStart = commandList.length;
frameState.commandList = commandList;
frameState.camera = tilesetPassState.camera ?? originalCamera;
frameState.cullingVolume = tilesetPassState.cullingVolume ?? originalCullingVolume;
if (passOptions2.isRender) {
const environmentMapManager = this._environmentMapManager;
if (defined_default(this._root)) {
environmentMapManager.position = this.boundingSphere.center;
}
environmentMapManager.update(frameState);
}
const clippingPolygons = this._clippingPolygons;
if (defined_default(clippingPolygons) && clippingPolygons.enabled) {
clippingPolygons.queueCommands(frameState);
}
const passStatistics = this._statisticsPerPass[pass];
if (this.show || ignoreCommands) {
this._pass = pass;
tilesetPassState.ready = update3(
this,
frameState,
passStatistics,
passOptions2
);
}
if (ignoreCommands) {
commandList.length = commandStart;
}
frameState.commandList = originalCommandList;
frameState.camera = originalCamera;
frameState.cullingVolume = originalCullingVolume;
};
Cesium3DTileset.prototype.hasExtension = function(extensionName) {
if (!defined_default(this._extensionsUsed)) {
return false;
}
return this._extensionsUsed.indexOf(extensionName) > -1;
};
Cesium3DTileset.prototype.isDestroyed = function() {
return false;
};
Cesium3DTileset.prototype.destroy = function() {
this._tileDebugLabels = this._tileDebugLabels && this._tileDebugLabels.destroy();
this._clippingPlanes = this._clippingPlanes && this._clippingPlanes.destroy();
this._clippingPolygons = this._clippingPolygons && this._clippingPolygons.destroy();
if (defined_default(this._root)) {
const stack = scratchStack2;
stack.push(this._root);
while (stack.length > 0) {
const tile = stack.pop();
tile.destroy();
const children = tile.children;
for (let i = 0; i < children.length; ++i) {
stack.push(children[i]);
}
}
}
this._root = void 0;
if (this._shouldDestroyImageBasedLighting && !this._imageBasedLighting.isDestroyed()) {
this._imageBasedLighting.destroy();
}
this._imageBasedLighting = void 0;
if (!this._environmentMapManager.isDestroyed()) {
this._environmentMapManager.destroy();
}
this._environmentMapManager = void 0;
if (!this._imageryLayers.isDestroyed()) {
this.imageryLayers.layerAdded.removeEventListener(
this._imageryLayersListener
);
this.imageryLayers.layerRemoved.removeEventListener(
this._imageryLayersListener
);
this.imageryLayers.layerMoved.removeEventListener(
this._imageryLayersListener
);
this.imageryLayers.layerShownOrHidden.removeEventListener(
this._imageryLayersListener
);
this._imageryLayers.destroy();
}
this._imageryLayers = void 0;
return destroyObject_default(this);
};
Cesium3DTileset.supportedExtensions = {
"3DTILES_metadata": true,
"3DTILES_implicit_tiling": true,
"3DTILES_content_gltf": true,
"3DTILES_multiple_contents": true,
"3DTILES_bounding_volume_S2": true,
"3DTILES_batch_table_hierarchy": true,
"3DTILES_draco_point_compression": true,
MAXAR_content_geojson: true
};
Cesium3DTileset.checkSupportedExtensions = function(extensionsRequired) {
for (let i = 0; i < extensionsRequired.length; i++) {
if (!Cesium3DTileset.supportedExtensions[extensionsRequired[i]]) {
throw new RuntimeError_default(
`Unsupported 3D Tiles Extension: ${extensionsRequired[i]}`
);
}
}
};
var scratchGetHeightRay = new Ray_default();
var scratchIntersection = new Cartesian3_default();
var scratchGetHeightCartographic = new Cartographic_default();
Cesium3DTileset.prototype.getHeight = function(cartographic2, scene) {
Check_default.typeOf.object("cartographic", cartographic2);
Check_default.typeOf.object("scene", scene);
let ellipsoid = scene.ellipsoid;
if (!defined_default(ellipsoid)) {
ellipsoid = Ellipsoid_default.WGS84;
}
const ray = scratchGetHeightRay;
const position = ellipsoid.cartographicToCartesian(
cartographic2,
ray.direction
);
Cartesian3_default.normalize(ray.direction, ray.direction);
ray.direction = Cartesian3_default.normalize(position, ray.direction);
ray.direction = Cartesian3_default.negate(position, ray.direction);
ray.origin = Cartesian3_default.multiplyByScalar(
ray.direction,
-2 * ellipsoid.maximumRadius,
ray.origin
);
const intersection = this.pick(ray, scene.frameState, scratchIntersection);
if (!defined_default(intersection)) {
return;
}
return ellipsoid.cartesianToCartographic(
intersection,
scratchGetHeightCartographic
)?.height;
};
Cesium3DTileset.prototype.updateHeight = function(cartographic2, callback, ellipsoid) {
ellipsoid = ellipsoid ?? Ellipsoid_default.WGS84;
const object2 = {
positionCartographic: cartographic2,
ellipsoid,
callback,
invoked: false
};
const removeCallback = () => {
const addedCallbacks = this._addHeightCallbacks;
const length2 = addedCallbacks.length;
for (let i = 0; i < length2; ++i) {
if (addedCallbacks[i] === object2) {
addedCallbacks.splice(i, 1);
break;
}
}
if (object2.callback) {
object2.callback = void 0;
}
};
this._addHeightCallbacks.push(object2);
return removeCallback;
};
var scratchSphereIntersection = new Interval_default();
var scratchPickIntersection = new Cartesian3_default();
Cesium3DTileset.prototype.pick = function(ray, frameState, result) {
if (!frameState.context.webgl2 && !this._enablePick) {
return;
}
const selectedTiles = this._selectedTiles;
const selectedLength = selectedTiles.length;
const candidates = [];
for (let i = 0; i < selectedLength; ++i) {
const tile = selectedTiles[i];
const boundsIntersection = IntersectionTests_default.raySphere(
ray,
tile.contentBoundingVolume.boundingSphere,
scratchSphereIntersection
);
if (!defined_default(boundsIntersection) || !defined_default(tile.content)) {
continue;
}
candidates.push(tile);
}
const length2 = candidates.length;
candidates.sort((a3, b) => {
const aDist = BoundingSphere_default.distanceSquaredTo(
a3.contentBoundingVolume.boundingSphere,
ray.origin
);
const bDist = BoundingSphere_default.distanceSquaredTo(
b.contentBoundingVolume.boundingSphere,
ray.origin
);
return aDist - bDist;
});
let intersection;
for (let i = 0; i < length2; ++i) {
const tile = candidates[i];
const candidate = tile.content.pick(
ray,
frameState,
scratchPickIntersection
);
if (defined_default(candidate)) {
intersection = Cartesian3_default.clone(candidate, result);
return intersection;
}
}
};
Cesium3DTileset.prototype.isGltfExtensionUsed = function(gltfExtensionName) {
if (this.hasExtension("3DTILES_content_gltf")) {
if (!defined_default(this.extensions)) {
return false;
}
const extensionsUsed = this.extensions["3DTILES_content_gltf"]?.extensionsUsed;
if (!defined_default(extensionsUsed)) {
return false;
}
return extensionsUsed.indexOf(gltfExtensionName) > -1;
}
return false;
};
Cesium3DTileset.prototype.isGltfExtensionRequired = function(gltfExtensionName) {
if (this.isGltfExtensionUsed(gltfExtensionName)) {
const extensionsRequired = this.extensions["3DTILES_content_gltf"].extensionsRequired;
if (!defined_default(extensionsRequired)) {
return false;
}
return extensionsRequired.indexOf(gltfExtensionName) > -1;
}
return false;
};
var Cesium3DTileset_default = Cesium3DTileset;
// packages/engine/Source/DataSources/Cesium3DTilesetVisualizer.js
var modelMatrixScratch2 = new Matrix4_default();
function Cesium3DTilesetVisualizer(scene, entityCollection) {
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required.");
}
if (!defined_default(entityCollection)) {
throw new DeveloperError_default("entityCollection is required.");
}
entityCollection.collectionChanged.addEventListener(
Cesium3DTilesetVisualizer.prototype._onCollectionChanged,
this
);
this._scene = scene;
this._primitives = scene.primitives;
this._entityCollection = entityCollection;
this._tilesetHash = {};
this._entitiesToVisualize = new AssociativeArray_default();
this._onCollectionChanged(entityCollection, entityCollection.values, [], []);
}
Cesium3DTilesetVisualizer.prototype.update = function(time) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required.");
}
const entities = this._entitiesToVisualize.values;
const tilesetHash = this._tilesetHash;
const primitives = this._primitives;
for (let i = 0, len = entities.length; i < len; i++) {
const entity = entities[i];
const tilesetGraphics = entity._tileset;
let resource;
const tilesetData = tilesetHash[entity.id];
const show = entity.isShowing && entity.isAvailable(time) && Property_default.getValueOrDefault(tilesetGraphics._show, time, true);
let modelMatrix;
if (show) {
modelMatrix = entity.computeModelMatrix(time, modelMatrixScratch2);
resource = Resource_default.createIfNeeded(
Property_default.getValueOrUndefined(tilesetGraphics._uri, time)
);
}
const tileset = defined_default(tilesetData) ? tilesetData.tilesetPrimitive : void 0;
if (!show) {
if (defined_default(tileset)) {
tileset.show = false;
}
continue;
}
if (!defined_default(tilesetData) || resource.url !== tilesetData.url) {
if (defined_default(tileset)) {
primitives.removeAndDestroy(tileset);
}
delete tilesetHash[entity.id];
createTileset(resource, tilesetHash, entity, primitives);
}
if (!defined_default(tileset)) {
continue;
}
tileset.show = true;
if (defined_default(modelMatrix)) {
tileset.modelMatrix = modelMatrix;
}
tileset.maximumScreenSpaceError = Property_default.getValueOrDefault(
tilesetGraphics.maximumScreenSpaceError,
time,
tileset.maximumScreenSpaceError
);
}
return true;
};
Cesium3DTilesetVisualizer.prototype.isDestroyed = function() {
return false;
};
Cesium3DTilesetVisualizer.prototype.destroy = function() {
this._entityCollection.collectionChanged.removeEventListener(
Cesium3DTilesetVisualizer.prototype._onCollectionChanged,
this
);
const entities = this._entitiesToVisualize.values;
const tilesetHash = this._tilesetHash;
const primitives = this._primitives;
for (let i = entities.length - 1; i > -1; i--) {
removeTileset(this, entities[i], tilesetHash, primitives);
}
return destroyObject_default(this);
};
Cesium3DTilesetVisualizer.prototype.getBoundingSphere = function(entity, result) {
if (!defined_default(entity)) {
throw new DeveloperError_default("entity is required.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
const tilesetData = this._tilesetHash[entity.id];
if (!defined_default(tilesetData) || tilesetData.loadFail) {
return BoundingSphereState_default.FAILED;
}
const primitive = tilesetData.tilesetPrimitive;
if (!defined_default(primitive)) {
return BoundingSphereState_default.PENDING;
}
if (!primitive.show) {
return BoundingSphereState_default.FAILED;
}
BoundingSphere_default.clone(primitive.boundingSphere, result);
return BoundingSphereState_default.DONE;
};
Cesium3DTilesetVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed, changed) {
let i;
let entity;
const entities = this._entitiesToVisualize;
const tilesetHash = this._tilesetHash;
const primitives = this._primitives;
for (i = added.length - 1; i > -1; i--) {
entity = added[i];
if (defined_default(entity._tileset)) {
entities.set(entity.id, entity);
}
}
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i];
if (defined_default(entity._tileset)) {
entities.set(entity.id, entity);
} else {
removeTileset(this, entity, tilesetHash, primitives);
entities.remove(entity.id);
}
}
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i];
removeTileset(this, entity, tilesetHash, primitives);
entities.remove(entity.id);
}
};
function removeTileset(visualizer, entity, tilesetHash, primitives) {
const tilesetData = tilesetHash[entity.id];
if (defined_default(tilesetData)) {
if (defined_default(tilesetData.tilesetPrimitive)) {
primitives.removeAndDestroy(tilesetData.tilesetPrimitive);
}
delete tilesetHash[entity.id];
}
}
async function createTileset(resource, tilesetHash, entity, primitives) {
tilesetHash[entity.id] = {
url: resource.url,
loadFail: false
};
try {
const tileset = await Cesium3DTileset_default.fromUrl(resource);
tileset.id = entity;
primitives.add(tileset);
if (!defined_default(tilesetHash[entity.id])) {
return;
}
tilesetHash[entity.id].tilesetPrimitive = tileset;
} catch (error) {
console.error(error);
tilesetHash[entity.id].loadFail = true;
}
}
var Cesium3DTilesetVisualizer_default = Cesium3DTilesetVisualizer;
// packages/engine/Source/DataSources/CheckerboardMaterialProperty.js
var import_InlineWorkers816 = __toESM(require_InlineWorkers(), 1);
var defaultEvenColor = Color_default.WHITE;
var defaultOddColor = Color_default.BLACK;
var defaultRepeat2 = new Cartesian2_default(2, 2);
function CheckerboardMaterialProperty(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._definitionChanged = new Event_default();
this._evenColor = void 0;
this._evenColorSubscription = void 0;
this._oddColor = void 0;
this._oddColorSubscription = void 0;
this._repeat = void 0;
this._repeatSubscription = void 0;
this.evenColor = options.evenColor;
this.oddColor = options.oddColor;
this.repeat = options.repeat;
}
Object.defineProperties(CheckerboardMaterialProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof CheckerboardMaterialProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return Property_default.isConstant(this._evenColor) && //
Property_default.isConstant(this._oddColor) && //
Property_default.isConstant(this._repeat);
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof CheckerboardMaterialProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the Property specifying the first {@link Color}.
* @memberof CheckerboardMaterialProperty.prototype
* @type {Property|undefined}
* @default Color.WHITE
*/
evenColor: createPropertyDescriptor_default("evenColor"),
/**
* Gets or sets the Property specifying the second {@link Color}.
* @memberof CheckerboardMaterialProperty.prototype
* @type {Property|undefined}
* @default Color.BLACK
*/
oddColor: createPropertyDescriptor_default("oddColor"),
/**
* Gets or sets the {@link Cartesian2} Property specifying how many times the tiles repeat in each direction.
* @memberof CheckerboardMaterialProperty.prototype
* @type {Property|undefined}
* @default new Cartesian2(2.0, 2.0)
*/
repeat: createPropertyDescriptor_default("repeat")
});
CheckerboardMaterialProperty.prototype.getType = function(time) {
return "Checkerboard";
};
var timeScratch10 = new JulianDate_default();
CheckerboardMaterialProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch10);
}
if (!defined_default(result)) {
result = {};
}
result.lightColor = Property_default.getValueOrClonedDefault(
this._evenColor,
time,
defaultEvenColor,
result.lightColor
);
result.darkColor = Property_default.getValueOrClonedDefault(
this._oddColor,
time,
defaultOddColor,
result.darkColor
);
result.repeat = Property_default.getValueOrDefault(this._repeat, time, defaultRepeat2);
return result;
};
CheckerboardMaterialProperty.prototype.equals = function(other) {
return this === other || //
other instanceof CheckerboardMaterialProperty && //
Property_default.equals(this._evenColor, other._evenColor) && //
Property_default.equals(this._oddColor, other._oddColor) && //
Property_default.equals(this._repeat, other._repeat);
};
var CheckerboardMaterialProperty_default = CheckerboardMaterialProperty;
// packages/engine/Source/DataSources/CompositeEntityCollection.js
var import_InlineWorkers818 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/EntityCollection.js
var import_InlineWorkers817 = __toESM(require_InlineWorkers(), 1);
var entityOptionsScratch = {
id: void 0
};
function fireChangedEvent(collection) {
if (collection._firing) {
collection._refire = true;
return;
}
if (collection._suspendCount === 0) {
const added = collection._addedEntities;
const removed = collection._removedEntities;
const changed = collection._changedEntities;
if (changed.length !== 0 || added.length !== 0 || removed.length !== 0) {
collection._firing = true;
do {
collection._refire = false;
const addedArray = added.values.slice(0);
const removedArray = removed.values.slice(0);
const changedArray = changed.values.slice(0);
added.removeAll();
removed.removeAll();
changed.removeAll();
collection._collectionChanged.raiseEvent(
collection,
addedArray,
removedArray,
changedArray
);
} while (collection._refire);
collection._firing = false;
}
}
}
function EntityCollection(owner) {
this._owner = owner;
this._entities = new AssociativeArray_default();
this._addedEntities = new AssociativeArray_default();
this._removedEntities = new AssociativeArray_default();
this._changedEntities = new AssociativeArray_default();
this._suspendCount = 0;
this._collectionChanged = new Event_default();
this._id = createGuid_default();
this._show = true;
this._firing = false;
this._refire = false;
}
EntityCollection.prototype.suspendEvents = function() {
this._suspendCount++;
};
EntityCollection.prototype.resumeEvents = function() {
if (this._suspendCount === 0) {
throw new DeveloperError_default(
"resumeEvents can not be called before suspendEvents."
);
}
this._suspendCount--;
fireChangedEvent(this);
};
Object.defineProperties(EntityCollection.prototype, {
/**
* Gets the event that is fired when entities are added or removed from the collection.
* The generated event is a {@link EntityCollection.CollectionChangedEventCallback}.
* @memberof EntityCollection.prototype
* @readonly
* @type {Event}
*/
collectionChanged: {
get: function() {
return this._collectionChanged;
}
},
/**
* Gets a globally unique identifier for this collection.
* @memberof EntityCollection.prototype
* @readonly
* @type {string}
*/
id: {
get: function() {
return this._id;
}
},
/**
* Gets the array of Entity instances in the collection.
* This array should not be modified directly.
* @memberof EntityCollection.prototype
* @readonly
* @type {Entity[]}
*/
values: {
get: function() {
return this._entities.values;
}
},
/**
* Gets whether or not this entity collection should be
* displayed. When true, each entity is only displayed if
* its own show property is also true.
* @memberof EntityCollection.prototype
* @type {boolean}
*/
show: {
get: function() {
return this._show;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (value === this._show) {
return;
}
this.suspendEvents();
let i;
const oldShows = [];
const entities = this._entities.values;
const entitiesLength = entities.length;
for (i = 0; i < entitiesLength; i++) {
oldShows.push(entities[i].isShowing);
}
this._show = value;
for (i = 0; i < entitiesLength; i++) {
const oldShow = oldShows[i];
const entity = entities[i];
if (oldShow !== entity.isShowing) {
entity.definitionChanged.raiseEvent(
entity,
"isShowing",
entity.isShowing,
oldShow
);
}
}
this.resumeEvents();
}
},
/**
* Gets the owner of this entity collection, ie. the data source or composite entity collection which created it.
* @memberof EntityCollection.prototype
* @readonly
* @type {DataSource|CompositeEntityCollection}
*/
owner: {
get: function() {
return this._owner;
}
}
});
EntityCollection.prototype.computeAvailability = function() {
let startTime = Iso8601_default.MAXIMUM_VALUE;
let stopTime = Iso8601_default.MINIMUM_VALUE;
const entities = this._entities.values;
for (let i = 0, len = entities.length; i < len; i++) {
const entity = entities[i];
const availability = entity.availability;
if (defined_default(availability)) {
const start = availability.start;
const stop2 = availability.stop;
if (JulianDate_default.lessThan(start, startTime) && !start.equals(Iso8601_default.MINIMUM_VALUE)) {
startTime = start;
}
if (JulianDate_default.greaterThan(stop2, stopTime) && !stop2.equals(Iso8601_default.MAXIMUM_VALUE)) {
stopTime = stop2;
}
}
}
if (Iso8601_default.MAXIMUM_VALUE.equals(startTime)) {
startTime = Iso8601_default.MINIMUM_VALUE;
}
if (Iso8601_default.MINIMUM_VALUE.equals(stopTime)) {
stopTime = Iso8601_default.MAXIMUM_VALUE;
}
return new TimeInterval_default({
start: startTime,
stop: stopTime
});
};
EntityCollection.prototype.add = function(entity) {
if (!defined_default(entity)) {
throw new DeveloperError_default("entity is required.");
}
if (!(entity instanceof Entity_default)) {
entity = new Entity_default(entity);
}
const id = entity.id;
const entities = this._entities;
if (entities.contains(id)) {
throw new DeveloperError_default(
`An entity with id ${id} already exists in this collection.`
);
}
entity.entityCollection = this;
entities.set(id, entity);
if (!this._removedEntities.remove(id)) {
this._addedEntities.set(id, entity);
}
entity.definitionChanged.addEventListener(
EntityCollection.prototype._onEntityDefinitionChanged,
this
);
fireChangedEvent(this);
return entity;
};
EntityCollection.prototype.remove = function(entity) {
if (!defined_default(entity)) {
return false;
}
return this.removeById(entity.id);
};
EntityCollection.prototype.contains = function(entity) {
if (!defined_default(entity)) {
throw new DeveloperError_default("entity is required");
}
return this._entities.get(entity.id) === entity;
};
EntityCollection.prototype.removeById = function(id) {
if (!defined_default(id)) {
return false;
}
const entities = this._entities;
const entity = entities.get(id);
if (!this._entities.remove(id)) {
return false;
}
if (!this._addedEntities.remove(id)) {
this._removedEntities.set(id, entity);
this._changedEntities.remove(id);
}
this._entities.remove(id);
entity.definitionChanged.removeEventListener(
EntityCollection.prototype._onEntityDefinitionChanged,
this
);
fireChangedEvent(this);
return true;
};
EntityCollection.prototype.removeAll = function() {
const entities = this._entities;
const entitiesLength = entities.length;
const array = entities.values;
const addedEntities = this._addedEntities;
const removed = this._removedEntities;
for (let i = 0; i < entitiesLength; i++) {
const existingItem = array[i];
const existingItemId = existingItem.id;
const addedItem = addedEntities.get(existingItemId);
if (!defined_default(addedItem)) {
existingItem.definitionChanged.removeEventListener(
EntityCollection.prototype._onEntityDefinitionChanged,
this
);
removed.set(existingItemId, existingItem);
}
}
entities.removeAll();
addedEntities.removeAll();
this._changedEntities.removeAll();
fireChangedEvent(this);
};
EntityCollection.prototype.getById = function(id) {
if (!defined_default(id)) {
throw new DeveloperError_default("id is required.");
}
return this._entities.get(id);
};
EntityCollection.prototype.getOrCreateEntity = function(id) {
if (!defined_default(id)) {
throw new DeveloperError_default("id is required.");
}
let entity = this._entities.get(id);
if (!defined_default(entity)) {
entityOptionsScratch.id = id;
entity = new Entity_default(entityOptionsScratch);
this.add(entity);
}
return entity;
};
EntityCollection.prototype._onEntityDefinitionChanged = function(entity) {
const id = entity.id;
if (!this._addedEntities.contains(id)) {
this._changedEntities.set(id, entity);
}
fireChangedEvent(this);
};
var EntityCollection_default = EntityCollection;
// packages/engine/Source/DataSources/CompositeEntityCollection.js
var entityOptionsScratch2 = {
id: void 0
};
var entityIdScratch = new Array(2);
function clean(entity) {
const propertyNames = entity.propertyNames;
const propertyNamesLength = propertyNames.length;
for (let i = 0; i < propertyNamesLength; i++) {
entity[propertyNames[i]] = void 0;
}
entity._name = void 0;
entity._availability = void 0;
}
function subscribeToEntity(that, eventHash, collectionId, entity) {
entityIdScratch[0] = collectionId;
entityIdScratch[1] = entity.id;
eventHash[JSON.stringify(entityIdScratch)] = entity.definitionChanged.addEventListener(
CompositeEntityCollection.prototype._onDefinitionChanged,
that
);
}
function unsubscribeFromEntity(that, eventHash, collectionId, entity) {
entityIdScratch[0] = collectionId;
entityIdScratch[1] = entity.id;
const id = JSON.stringify(entityIdScratch);
eventHash[id]();
eventHash[id] = void 0;
}
function recomposite(that) {
that._shouldRecomposite = true;
if (that._suspendCount !== 0) {
return;
}
const collections = that._collections;
const collectionsLength = collections.length;
const collectionsCopy = that._collectionsCopy;
const collectionsCopyLength = collectionsCopy.length;
let i;
let entity;
let entities;
let iEntities;
let collection;
const composite = that._composite;
const newEntities = new EntityCollection_default(that);
const eventHash = that._eventHash;
let collectionId;
for (i = 0; i < collectionsCopyLength; i++) {
collection = collectionsCopy[i];
collection.collectionChanged.removeEventListener(
CompositeEntityCollection.prototype._onCollectionChanged,
that
);
entities = collection.values;
collectionId = collection.id;
for (iEntities = entities.length - 1; iEntities > -1; iEntities--) {
entity = entities[iEntities];
unsubscribeFromEntity(that, eventHash, collectionId, entity);
}
}
for (i = collectionsLength - 1; i >= 0; i--) {
collection = collections[i];
collection.collectionChanged.addEventListener(
CompositeEntityCollection.prototype._onCollectionChanged,
that
);
entities = collection.values;
collectionId = collection.id;
for (iEntities = entities.length - 1; iEntities > -1; iEntities--) {
entity = entities[iEntities];
subscribeToEntity(that, eventHash, collectionId, entity);
let compositeEntity = newEntities.getById(entity.id);
if (!defined_default(compositeEntity)) {
compositeEntity = composite.getById(entity.id);
if (!defined_default(compositeEntity)) {
entityOptionsScratch2.id = entity.id;
compositeEntity = new Entity_default(entityOptionsScratch2);
} else {
clean(compositeEntity);
}
newEntities.add(compositeEntity);
}
compositeEntity.merge(entity);
}
}
that._collectionsCopy = collections.slice(0);
composite.suspendEvents();
composite.removeAll();
const newEntitiesArray = newEntities.values;
for (i = 0; i < newEntitiesArray.length; i++) {
composite.add(newEntitiesArray[i]);
}
composite.resumeEvents();
}
function CompositeEntityCollection(collections, owner) {
this._owner = owner;
this._composite = new EntityCollection_default(this);
this._suspendCount = 0;
this._collections = defined_default(collections) ? collections.slice() : [];
this._collectionsCopy = [];
this._id = createGuid_default();
this._eventHash = {};
recomposite(this);
this._shouldRecomposite = false;
}
Object.defineProperties(CompositeEntityCollection.prototype, {
/**
* Gets the event that is fired when entities are added or removed from the collection.
* The generated event is a {@link EntityCollection.collectionChangedEventCallback}.
* @memberof CompositeEntityCollection.prototype
* @readonly
* @type {Event}
*/
collectionChanged: {
get: function() {
return this._composite._collectionChanged;
}
},
/**
* Gets a globally unique identifier for this collection.
* @memberof CompositeEntityCollection.prototype
* @readonly
* @type {string}
*/
id: {
get: function() {
return this._id;
}
},
/**
* Gets the array of Entity instances in the collection.
* This array should not be modified directly.
* @memberof CompositeEntityCollection.prototype
* @readonly
* @type {Entity[]}
*/
values: {
get: function() {
return this._composite.values;
}
},
/**
* Gets the owner of this composite entity collection, ie. the data source or composite entity collection which created it.
* @memberof CompositeEntityCollection.prototype
* @readonly
* @type {DataSource|CompositeEntityCollection}
*/
owner: {
get: function() {
return this._owner;
}
}
});
CompositeEntityCollection.prototype.addCollection = function(collection, index) {
const hasIndex = defined_default(index);
if (!defined_default(collection)) {
throw new DeveloperError_default("collection is required.");
}
if (hasIndex) {
if (index < 0) {
throw new DeveloperError_default("index must be greater than or equal to zero.");
} else if (index > this._collections.length) {
throw new DeveloperError_default(
"index must be less than or equal to the number of collections."
);
}
}
if (!hasIndex) {
index = this._collections.length;
this._collections.push(collection);
} else {
this._collections.splice(index, 0, collection);
}
recomposite(this);
};
CompositeEntityCollection.prototype.removeCollection = function(collection) {
const index = this._collections.indexOf(collection);
if (index !== -1) {
this._collections.splice(index, 1);
recomposite(this);
return true;
}
return false;
};
CompositeEntityCollection.prototype.removeAllCollections = function() {
this._collections.length = 0;
recomposite(this);
};
CompositeEntityCollection.prototype.containsCollection = function(collection) {
return this._collections.indexOf(collection) !== -1;
};
CompositeEntityCollection.prototype.contains = function(entity) {
return this._composite.contains(entity);
};
CompositeEntityCollection.prototype.indexOfCollection = function(collection) {
return this._collections.indexOf(collection);
};
CompositeEntityCollection.prototype.getCollection = function(index) {
if (!defined_default(index)) {
throw new DeveloperError_default("index is required.", "index");
}
return this._collections[index];
};
CompositeEntityCollection.prototype.getCollectionsLength = function() {
return this._collections.length;
};
function getCollectionIndex(collections, collection) {
if (!defined_default(collection)) {
throw new DeveloperError_default("collection is required.");
}
const index = collections.indexOf(collection);
if (index === -1) {
throw new DeveloperError_default("collection is not in this composite.");
}
return index;
}
function swapCollections(composite, i, j) {
const arr = composite._collections;
i = Math_default.clamp(i, 0, arr.length - 1);
j = Math_default.clamp(j, 0, arr.length - 1);
if (i === j) {
return;
}
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
recomposite(composite);
}
CompositeEntityCollection.prototype.raiseCollection = function(collection) {
const index = getCollectionIndex(this._collections, collection);
swapCollections(this, index, index + 1);
};
CompositeEntityCollection.prototype.lowerCollection = function(collection) {
const index = getCollectionIndex(this._collections, collection);
swapCollections(this, index, index - 1);
};
CompositeEntityCollection.prototype.raiseCollectionToTop = function(collection) {
const index = getCollectionIndex(this._collections, collection);
if (index === this._collections.length - 1) {
return;
}
this._collections.splice(index, 1);
this._collections.push(collection);
recomposite(this);
};
CompositeEntityCollection.prototype.lowerCollectionToBottom = function(collection) {
const index = getCollectionIndex(this._collections, collection);
if (index === 0) {
return;
}
this._collections.splice(index, 1);
this._collections.splice(0, 0, collection);
recomposite(this);
};
CompositeEntityCollection.prototype.suspendEvents = function() {
this._suspendCount++;
this._composite.suspendEvents();
};
CompositeEntityCollection.prototype.resumeEvents = function() {
if (this._suspendCount === 0) {
throw new DeveloperError_default(
"resumeEvents can not be called before suspendEvents."
);
}
this._suspendCount--;
if (this._shouldRecomposite && this._suspendCount === 0) {
recomposite(this);
this._shouldRecomposite = false;
}
this._composite.resumeEvents();
};
CompositeEntityCollection.prototype.computeAvailability = function() {
return this._composite.computeAvailability();
};
CompositeEntityCollection.prototype.getById = function(id) {
return this._composite.getById(id);
};
CompositeEntityCollection.prototype._onCollectionChanged = function(collection, added, removed) {
const collections = this._collectionsCopy;
const collectionsLength = collections.length;
const composite = this._composite;
composite.suspendEvents();
let i;
let q;
let entity;
let compositeEntity;
const removedLength = removed.length;
const eventHash = this._eventHash;
const collectionId = collection.id;
for (i = 0; i < removedLength; i++) {
const removedEntity = removed[i];
unsubscribeFromEntity(this, eventHash, collectionId, removedEntity);
const removedId = removedEntity.id;
for (q = collectionsLength - 1; q >= 0; q--) {
entity = collections[q].getById(removedId);
if (defined_default(entity)) {
if (!defined_default(compositeEntity)) {
compositeEntity = composite.getById(removedId);
clean(compositeEntity);
}
compositeEntity.merge(entity);
}
}
if (!defined_default(compositeEntity)) {
composite.removeById(removedId);
}
compositeEntity = void 0;
}
const addedLength = added.length;
for (i = 0; i < addedLength; i++) {
const addedEntity = added[i];
subscribeToEntity(this, eventHash, collectionId, addedEntity);
const addedId = addedEntity.id;
for (q = collectionsLength - 1; q >= 0; q--) {
entity = collections[q].getById(addedId);
if (defined_default(entity)) {
if (!defined_default(compositeEntity)) {
compositeEntity = composite.getById(addedId);
if (!defined_default(compositeEntity)) {
entityOptionsScratch2.id = addedId;
compositeEntity = new Entity_default(entityOptionsScratch2);
composite.add(compositeEntity);
} else {
clean(compositeEntity);
}
}
compositeEntity.merge(entity);
}
}
compositeEntity = void 0;
}
composite.resumeEvents();
};
CompositeEntityCollection.prototype._onDefinitionChanged = function(entity, propertyName, newValue, oldValue2) {
const collections = this._collections;
const composite = this._composite;
const collectionsLength = collections.length;
const id = entity.id;
const compositeEntity = composite.getById(id);
let compositeProperty = compositeEntity[propertyName];
const newProperty = !defined_default(compositeProperty);
let firstTime = true;
for (let q = collectionsLength - 1; q >= 0; q--) {
const innerEntity = collections[q].getById(entity.id);
if (defined_default(innerEntity)) {
const property = innerEntity[propertyName];
if (defined_default(property)) {
if (firstTime) {
firstTime = false;
if (defined_default(property.merge) && defined_default(property.clone)) {
compositeProperty = property.clone(compositeProperty);
} else {
compositeProperty = property;
break;
}
}
compositeProperty.merge(property);
}
}
}
if (newProperty && compositeEntity.propertyNames.indexOf(propertyName) === -1) {
compositeEntity.addProperty(propertyName);
}
compositeEntity[propertyName] = compositeProperty;
};
var CompositeEntityCollection_default = CompositeEntityCollection;
// packages/engine/Source/DataSources/CompositeMaterialProperty.js
var import_InlineWorkers822 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/CompositeProperty.js
var import_InlineWorkers821 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/EventHelper.js
var import_InlineWorkers819 = __toESM(require_InlineWorkers(), 1);
function EventHelper() {
this._removalFunctions = [];
}
EventHelper.prototype.add = function(event, listener, scope) {
if (!defined_default(event)) {
throw new DeveloperError_default("event is required");
}
const removalFunction = event.addEventListener(listener, scope);
this._removalFunctions.push(removalFunction);
const that = this;
return function() {
removalFunction();
const removalFunctions = that._removalFunctions;
removalFunctions.splice(removalFunctions.indexOf(removalFunction), 1);
};
};
EventHelper.prototype.removeAll = function() {
const removalFunctions = this._removalFunctions;
for (let i = 0, len = removalFunctions.length; i < len; ++i) {
removalFunctions[i]();
}
removalFunctions.length = 0;
};
var EventHelper_default = EventHelper;
// packages/engine/Source/Core/TimeIntervalCollection.js
var import_InlineWorkers820 = __toESM(require_InlineWorkers(), 1);
function compareIntervalStartTimes(left, right) {
return JulianDate_default.compare(left.start, right.start);
}
function TimeIntervalCollection(intervals) {
this._intervals = [];
this._changedEvent = new Event_default();
if (defined_default(intervals)) {
const length2 = intervals.length;
for (let i = 0; i < length2; i++) {
this.addInterval(intervals[i]);
}
}
}
Object.defineProperties(TimeIntervalCollection.prototype, {
/**
* Gets an event that is raised whenever the collection of intervals change.
* @memberof TimeIntervalCollection.prototype
* @type {Event}
* @readonly
*/
changedEvent: {
get: function() {
return this._changedEvent;
}
},
/**
* Gets the start time of the collection.
* @memberof TimeIntervalCollection.prototype
* @type {JulianDate}
* @readonly
*/
start: {
get: function() {
const intervals = this._intervals;
return intervals.length === 0 ? void 0 : intervals[0].start;
}
},
/**
* Gets whether or not the start time is included in the collection.
* @memberof TimeIntervalCollection.prototype
* @type {boolean}
* @readonly
*/
isStartIncluded: {
get: function() {
const intervals = this._intervals;
return intervals.length === 0 ? false : intervals[0].isStartIncluded;
}
},
/**
* Gets the stop time of the collection.
* @memberof TimeIntervalCollection.prototype
* @type {JulianDate}
* @readonly
*/
stop: {
get: function() {
const intervals = this._intervals;
const length2 = intervals.length;
return length2 === 0 ? void 0 : intervals[length2 - 1].stop;
}
},
/**
* Gets whether or not the stop time is included in the collection.
* @memberof TimeIntervalCollection.prototype
* @type {boolean}
* @readonly
*/
isStopIncluded: {
get: function() {
const intervals = this._intervals;
const length2 = intervals.length;
return length2 === 0 ? false : intervals[length2 - 1].isStopIncluded;
}
},
/**
* Gets the number of intervals in the collection.
* @memberof TimeIntervalCollection.prototype
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._intervals.length;
}
},
/**
* Gets whether or not the collection is empty.
* @memberof TimeIntervalCollection.prototype
* @type {boolean}
* @readonly
*/
isEmpty: {
get: function() {
return this._intervals.length === 0;
}
}
});
TimeIntervalCollection.prototype.equals = function(right, dataComparer) {
if (this === right) {
return true;
}
if (!(right instanceof TimeIntervalCollection)) {
return false;
}
const intervals = this._intervals;
const rightIntervals = right._intervals;
const length2 = intervals.length;
if (length2 !== rightIntervals.length) {
return false;
}
for (let i = 0; i < length2; i++) {
if (!TimeInterval_default.equals(intervals[i], rightIntervals[i], dataComparer)) {
return false;
}
}
return true;
};
TimeIntervalCollection.prototype.get = function(index) {
if (!defined_default(index)) {
throw new DeveloperError_default("index is required.");
}
return this._intervals[index];
};
TimeIntervalCollection.prototype.removeAll = function() {
if (this._intervals.length > 0) {
this._intervals.length = 0;
this._changedEvent.raiseEvent(this);
}
};
TimeIntervalCollection.prototype.findIntervalContainingDate = function(date) {
const index = this.indexOf(date);
return index >= 0 ? this._intervals[index] : void 0;
};
TimeIntervalCollection.prototype.findDataForIntervalContainingDate = function(date) {
const index = this.indexOf(date);
return index >= 0 ? this._intervals[index].data : void 0;
};
TimeIntervalCollection.prototype.contains = function(julianDate) {
return this.indexOf(julianDate) >= 0;
};
var indexOfScratch = new TimeInterval_default();
TimeIntervalCollection.prototype.indexOf = function(date) {
if (!defined_default(date)) {
throw new DeveloperError_default("date is required");
}
const intervals = this._intervals;
indexOfScratch.start = date;
indexOfScratch.stop = date;
let index = binarySearch_default(
intervals,
indexOfScratch,
compareIntervalStartTimes
);
if (index >= 0) {
if (intervals[index].isStartIncluded) {
return index;
}
if (index > 0 && intervals[index - 1].stop.equals(date) && intervals[index - 1].isStopIncluded) {
return index - 1;
}
return ~index;
}
index = ~index;
if (index > 0 && index - 1 < intervals.length && TimeInterval_default.contains(intervals[index - 1], date)) {
return index - 1;
}
return ~index;
};
TimeIntervalCollection.prototype.findInterval = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const start = options.start;
const stop2 = options.stop;
const isStartIncluded = options.isStartIncluded;
const isStopIncluded = options.isStopIncluded;
const intervals = this._intervals;
for (let i = 0, len = intervals.length; i < len; i++) {
const interval = intervals[i];
if ((!defined_default(start) || interval.start.equals(start)) && (!defined_default(stop2) || interval.stop.equals(stop2)) && (!defined_default(isStartIncluded) || interval.isStartIncluded === isStartIncluded) && (!defined_default(isStopIncluded) || interval.isStopIncluded === isStopIncluded)) {
return intervals[i];
}
}
return void 0;
};
TimeIntervalCollection.prototype.addInterval = function(interval, dataComparer) {
if (!defined_default(interval)) {
throw new DeveloperError_default("interval is required");
}
if (interval.isEmpty) {
return;
}
const intervals = this._intervals;
if (intervals.length === 0 || JulianDate_default.greaterThan(interval.start, intervals[intervals.length - 1].stop)) {
intervals.push(interval);
this._changedEvent.raiseEvent(this);
return;
}
let index = binarySearch_default(intervals, interval, compareIntervalStartTimes);
if (index < 0) {
index = ~index;
} else {
if (index > 0 && interval.isStartIncluded && intervals[index - 1].isStartIncluded && intervals[index - 1].start.equals(interval.start)) {
--index;
} else if (index < intervals.length && !interval.isStartIncluded && intervals[index].isStartIncluded && intervals[index].start.equals(interval.start)) {
++index;
}
}
let comparison;
if (index > 0) {
comparison = JulianDate_default.compare(intervals[index - 1].stop, interval.start);
if (comparison > 0 || comparison === 0 && (intervals[index - 1].isStopIncluded || interval.isStartIncluded)) {
if (defined_default(dataComparer) ? dataComparer(intervals[index - 1].data, interval.data) : intervals[index - 1].data === interval.data) {
if (JulianDate_default.greaterThan(interval.stop, intervals[index - 1].stop)) {
interval = new TimeInterval_default({
start: intervals[index - 1].start,
stop: interval.stop,
isStartIncluded: intervals[index - 1].isStartIncluded,
isStopIncluded: interval.isStopIncluded,
data: interval.data
});
} else {
interval = new TimeInterval_default({
start: intervals[index - 1].start,
stop: intervals[index - 1].stop,
isStartIncluded: intervals[index - 1].isStartIncluded,
isStopIncluded: intervals[index - 1].isStopIncluded || interval.stop.equals(intervals[index - 1].stop) && interval.isStopIncluded,
data: interval.data
});
}
intervals.splice(index - 1, 1);
--index;
} else {
comparison = JulianDate_default.compare(
intervals[index - 1].stop,
interval.stop
);
if (comparison > 0 || comparison === 0 && intervals[index - 1].isStopIncluded && !interval.isStopIncluded) {
intervals.splice(
index,
0,
new TimeInterval_default({
start: interval.stop,
stop: intervals[index - 1].stop,
isStartIncluded: !interval.isStopIncluded,
isStopIncluded: intervals[index - 1].isStopIncluded,
data: intervals[index - 1].data
})
);
}
intervals[index - 1] = new TimeInterval_default({
start: intervals[index - 1].start,
stop: interval.start,
isStartIncluded: intervals[index - 1].isStartIncluded,
isStopIncluded: !interval.isStartIncluded,
data: intervals[index - 1].data
});
}
}
}
while (index < intervals.length) {
comparison = JulianDate_default.compare(interval.stop, intervals[index].start);
if (comparison > 0 || comparison === 0 && (interval.isStopIncluded || intervals[index].isStartIncluded)) {
if (defined_default(dataComparer) ? dataComparer(intervals[index].data, interval.data) : intervals[index].data === interval.data) {
interval = new TimeInterval_default({
start: interval.start,
stop: JulianDate_default.greaterThan(intervals[index].stop, interval.stop) ? intervals[index].stop : interval.stop,
isStartIncluded: interval.isStartIncluded,
isStopIncluded: JulianDate_default.greaterThan(
intervals[index].stop,
interval.stop
) ? intervals[index].isStopIncluded : interval.isStopIncluded,
data: interval.data
});
intervals.splice(index, 1);
} else {
intervals[index] = new TimeInterval_default({
start: interval.stop,
stop: intervals[index].stop,
isStartIncluded: !interval.isStopIncluded,
isStopIncluded: intervals[index].isStopIncluded,
data: intervals[index].data
});
if (intervals[index].isEmpty) {
intervals.splice(index, 1);
} else {
break;
}
}
} else {
break;
}
}
intervals.splice(index, 0, interval);
this._changedEvent.raiseEvent(this);
};
TimeIntervalCollection.prototype.removeInterval = function(interval) {
if (!defined_default(interval)) {
throw new DeveloperError_default("interval is required");
}
if (interval.isEmpty) {
return false;
}
const intervals = this._intervals;
let index = binarySearch_default(intervals, interval, compareIntervalStartTimes);
if (index < 0) {
index = ~index;
}
let result = false;
if (index > 0 && (JulianDate_default.greaterThan(intervals[index - 1].stop, interval.start) || intervals[index - 1].stop.equals(interval.start) && intervals[index - 1].isStopIncluded && interval.isStartIncluded)) {
result = true;
if (JulianDate_default.greaterThan(intervals[index - 1].stop, interval.stop) || intervals[index - 1].isStopIncluded && !interval.isStopIncluded && intervals[index - 1].stop.equals(interval.stop)) {
intervals.splice(
index,
0,
new TimeInterval_default({
start: interval.stop,
stop: intervals[index - 1].stop,
isStartIncluded: !interval.isStopIncluded,
isStopIncluded: intervals[index - 1].isStopIncluded,
data: intervals[index - 1].data
})
);
}
intervals[index - 1] = new TimeInterval_default({
start: intervals[index - 1].start,
stop: interval.start,
isStartIncluded: intervals[index - 1].isStartIncluded,
isStopIncluded: !interval.isStartIncluded,
data: intervals[index - 1].data
});
}
if (index < intervals.length && !interval.isStartIncluded && intervals[index].isStartIncluded && interval.start.equals(intervals[index].start)) {
result = true;
intervals.splice(
index,
0,
new TimeInterval_default({
start: intervals[index].start,
stop: intervals[index].start,
isStartIncluded: true,
isStopIncluded: true,
data: intervals[index].data
})
);
++index;
}
while (index < intervals.length && JulianDate_default.greaterThan(interval.stop, intervals[index].stop)) {
result = true;
intervals.splice(index, 1);
}
if (index < intervals.length && interval.stop.equals(intervals[index].stop)) {
result = true;
if (!interval.isStopIncluded && intervals[index].isStopIncluded) {
if (index + 1 < intervals.length && intervals[index + 1].start.equals(interval.stop) && intervals[index].data === intervals[index + 1].data) {
intervals.splice(index, 1);
intervals[index] = new TimeInterval_default({
start: intervals[index].start,
stop: intervals[index].stop,
isStartIncluded: true,
isStopIncluded: intervals[index].isStopIncluded,
data: intervals[index].data
});
} else {
intervals[index] = new TimeInterval_default({
start: interval.stop,
stop: interval.stop,
isStartIncluded: true,
isStopIncluded: true,
data: intervals[index].data
});
}
} else {
intervals.splice(index, 1);
}
}
if (index < intervals.length && (JulianDate_default.greaterThan(interval.stop, intervals[index].start) || interval.stop.equals(intervals[index].start) && interval.isStopIncluded && intervals[index].isStartIncluded)) {
result = true;
intervals[index] = new TimeInterval_default({
start: interval.stop,
stop: intervals[index].stop,
isStartIncluded: !interval.isStopIncluded,
isStopIncluded: intervals[index].isStopIncluded,
data: intervals[index].data
});
}
if (result) {
this._changedEvent.raiseEvent(this);
}
return result;
};
TimeIntervalCollection.prototype.intersect = function(other, dataComparer, mergeCallback) {
if (!defined_default(other)) {
throw new DeveloperError_default("other is required.");
}
const result = new TimeIntervalCollection();
let left = 0;
let right = 0;
const intervals = this._intervals;
const otherIntervals = other._intervals;
while (left < intervals.length && right < otherIntervals.length) {
const leftInterval = intervals[left];
const rightInterval = otherIntervals[right];
if (JulianDate_default.lessThan(leftInterval.stop, rightInterval.start)) {
++left;
} else if (JulianDate_default.lessThan(rightInterval.stop, leftInterval.start)) {
++right;
} else {
if (defined_default(mergeCallback) || defined_default(dataComparer) && dataComparer(leftInterval.data, rightInterval.data) || !defined_default(dataComparer) && rightInterval.data === leftInterval.data) {
const intersection = TimeInterval_default.intersect(
leftInterval,
rightInterval,
new TimeInterval_default(),
mergeCallback
);
if (!intersection.isEmpty) {
result.addInterval(intersection, dataComparer);
}
}
if (JulianDate_default.lessThan(leftInterval.stop, rightInterval.stop) || leftInterval.stop.equals(rightInterval.stop) && !leftInterval.isStopIncluded && rightInterval.isStopIncluded) {
++left;
} else {
++right;
}
}
}
return result;
};
TimeIntervalCollection.fromJulianDateArray = function(options, result) {
if (!defined_default(options)) {
throw new DeveloperError_default("options is required.");
}
if (!defined_default(options.julianDates)) {
throw new DeveloperError_default("options.iso8601Array is required.");
}
if (!defined_default(result)) {
result = new TimeIntervalCollection();
}
const julianDates = options.julianDates;
const length2 = julianDates.length;
const dataCallback = options.dataCallback;
const isStartIncluded = options.isStartIncluded ?? true;
const isStopIncluded = options.isStopIncluded ?? true;
const leadingInterval = options.leadingInterval ?? false;
const trailingInterval = options.trailingInterval ?? false;
let interval;
let startIndex = 0;
if (leadingInterval) {
++startIndex;
interval = new TimeInterval_default({
start: Iso8601_default.MINIMUM_VALUE,
stop: julianDates[0],
isStartIncluded: true,
isStopIncluded: !isStartIncluded
});
interval.data = defined_default(dataCallback) ? dataCallback(interval, result.length) : result.length;
result.addInterval(interval);
}
for (let i = 0; i < length2 - 1; ++i) {
let startDate = julianDates[i];
const endDate = julianDates[i + 1];
interval = new TimeInterval_default({
start: startDate,
stop: endDate,
isStartIncluded: result.length === startIndex ? isStartIncluded : true,
isStopIncluded: i === length2 - 2 ? isStopIncluded : false
});
interval.data = defined_default(dataCallback) ? dataCallback(interval, result.length) : result.length;
result.addInterval(interval);
startDate = endDate;
}
if (trailingInterval) {
interval = new TimeInterval_default({
start: julianDates[length2 - 1],
stop: Iso8601_default.MAXIMUM_VALUE,
isStartIncluded: !isStopIncluded,
isStopIncluded: true
});
interval.data = defined_default(dataCallback) ? dataCallback(interval, result.length) : result.length;
result.addInterval(interval);
}
return result;
};
var scratchGregorianDate = new GregorianDate_default();
var monthLengths = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
function addToDate(julianDate, duration, result) {
if (!defined_default(result)) {
result = new JulianDate_default();
}
JulianDate_default.toGregorianDate(julianDate, scratchGregorianDate);
let millisecond = scratchGregorianDate.millisecond + duration.millisecond;
let second = scratchGregorianDate.second + duration.second;
let minute = scratchGregorianDate.minute + duration.minute;
let hour = scratchGregorianDate.hour + duration.hour;
let day = scratchGregorianDate.day + duration.day;
let month = scratchGregorianDate.month + duration.month;
let year = scratchGregorianDate.year + duration.year;
if (millisecond >= 1e3) {
second += Math.floor(millisecond / 1e3);
millisecond = millisecond % 1e3;
}
if (second >= 60) {
minute += Math.floor(second / 60);
second = second % 60;
}
if (minute >= 60) {
hour += Math.floor(minute / 60);
minute = minute % 60;
}
if (hour >= 24) {
day += Math.floor(hour / 24);
hour = hour % 24;
}
monthLengths[2] = isLeapYear_default(year) ? 29 : 28;
while (day > monthLengths[month] || month >= 13) {
if (day > monthLengths[month]) {
day -= monthLengths[month];
++month;
}
if (month >= 13) {
--month;
year += Math.floor(month / 12);
month = month % 12;
++month;
}
monthLengths[2] = isLeapYear_default(year) ? 29 : 28;
}
scratchGregorianDate.millisecond = millisecond;
scratchGregorianDate.second = second;
scratchGregorianDate.minute = minute;
scratchGregorianDate.hour = hour;
scratchGregorianDate.day = day;
scratchGregorianDate.month = month;
scratchGregorianDate.year = year;
return JulianDate_default.fromGregorianDate(scratchGregorianDate, result);
}
var scratchJulianDate2 = new JulianDate_default();
var durationRegex = /P(?:([\d.,]+)Y)?(?:([\d.,]+)M)?(?:([\d.,]+)W)?(?:([\d.,]+)D)?(?:T(?:([\d.,]+)H)?(?:([\d.,]+)M)?(?:([\d.,]+)S)?)?/;
function parseDuration(iso8601, result) {
if (!defined_default(iso8601) || iso8601.length === 0) {
return false;
}
result.year = 0;
result.month = 0;
result.day = 0;
result.hour = 0;
result.minute = 0;
result.second = 0;
result.millisecond = 0;
if (iso8601[0] === "P") {
const matches = iso8601.match(durationRegex);
if (!defined_default(matches)) {
return false;
}
if (defined_default(matches[1])) {
result.year = Number(matches[1].replace(",", "."));
}
if (defined_default(matches[2])) {
result.month = Number(matches[2].replace(",", "."));
}
if (defined_default(matches[3])) {
result.day = Number(matches[3].replace(",", ".")) * 7;
}
if (defined_default(matches[4])) {
result.day += Number(matches[4].replace(",", "."));
}
if (defined_default(matches[5])) {
result.hour = Number(matches[5].replace(",", "."));
}
if (defined_default(matches[6])) {
result.minute = Number(matches[6].replace(",", "."));
}
if (defined_default(matches[7])) {
const seconds = Number(matches[7].replace(",", "."));
result.second = Math.floor(seconds);
result.millisecond = seconds % 1 * 1e3;
}
} else {
if (iso8601[iso8601.length - 1] !== "Z") {
iso8601 += "Z";
}
JulianDate_default.toGregorianDate(
JulianDate_default.fromIso8601(iso8601, scratchJulianDate2),
result
);
}
return result.year || result.month || result.day || result.hour || result.minute || result.second || result.millisecond;
}
var scratchDuration = new GregorianDate_default();
TimeIntervalCollection.fromIso8601 = function(options, result) {
if (!defined_default(options)) {
throw new DeveloperError_default("options is required.");
}
if (!defined_default(options.iso8601)) {
throw new DeveloperError_default("options.iso8601 is required.");
}
const dates = options.iso8601.split("/");
const start = JulianDate_default.fromIso8601(dates[0]);
const stop2 = JulianDate_default.fromIso8601(dates[1]);
const julianDates = [];
if (!parseDuration(dates[2], scratchDuration)) {
julianDates.push(start, stop2);
} else {
let date = JulianDate_default.clone(start);
julianDates.push(date);
while (JulianDate_default.compare(date, stop2) < 0) {
date = addToDate(date, scratchDuration);
const afterStop = JulianDate_default.compare(stop2, date) <= 0;
if (afterStop) {
JulianDate_default.clone(stop2, date);
}
julianDates.push(date);
}
}
return TimeIntervalCollection.fromJulianDateArray(
{
julianDates,
isStartIncluded: options.isStartIncluded,
isStopIncluded: options.isStopIncluded,
leadingInterval: options.leadingInterval,
trailingInterval: options.trailingInterval,
dataCallback: options.dataCallback
},
result
);
};
TimeIntervalCollection.fromIso8601DateArray = function(options, result) {
if (!defined_default(options)) {
throw new DeveloperError_default("options is required.");
}
if (!defined_default(options.iso8601Dates)) {
throw new DeveloperError_default("options.iso8601Dates is required.");
}
return TimeIntervalCollection.fromJulianDateArray(
{
julianDates: options.iso8601Dates.map(function(date) {
return JulianDate_default.fromIso8601(date);
}),
isStartIncluded: options.isStartIncluded,
isStopIncluded: options.isStopIncluded,
leadingInterval: options.leadingInterval,
trailingInterval: options.trailingInterval,
dataCallback: options.dataCallback
},
result
);
};
TimeIntervalCollection.fromIso8601DurationArray = function(options, result) {
if (!defined_default(options)) {
throw new DeveloperError_default("options is required.");
}
if (!defined_default(options.epoch)) {
throw new DeveloperError_default("options.epoch is required.");
}
if (!defined_default(options.iso8601Durations)) {
throw new DeveloperError_default("options.iso8601Durations is required.");
}
const epoch2 = options.epoch;
const iso8601Durations = options.iso8601Durations;
const relativeToPrevious = options.relativeToPrevious ?? false;
const julianDates = [];
let date, previousDate;
const length2 = iso8601Durations.length;
for (let i = 0; i < length2; ++i) {
if (parseDuration(iso8601Durations[i], scratchDuration) || i === 0) {
if (relativeToPrevious && defined_default(previousDate)) {
date = addToDate(previousDate, scratchDuration);
} else {
date = addToDate(epoch2, scratchDuration);
}
julianDates.push(date);
previousDate = date;
}
}
return TimeIntervalCollection.fromJulianDateArray(
{
julianDates,
isStartIncluded: options.isStartIncluded,
isStopIncluded: options.isStopIncluded,
leadingInterval: options.leadingInterval,
trailingInterval: options.trailingInterval,
dataCallback: options.dataCallback
},
result
);
};
var TimeIntervalCollection_default = TimeIntervalCollection;
// packages/engine/Source/DataSources/CompositeProperty.js
function subscribeAll(property, eventHelper, definitionChanged, intervals) {
function callback() {
definitionChanged.raiseEvent(property);
}
const items = [];
eventHelper.removeAll();
const length2 = intervals.length;
for (let i = 0; i < length2; i++) {
const interval = intervals.get(i);
if (defined_default(interval.data) && items.indexOf(interval.data) === -1) {
eventHelper.add(interval.data.definitionChanged, callback);
}
}
}
function CompositeProperty() {
this._eventHelper = new EventHelper_default();
this._definitionChanged = new Event_default();
this._intervals = new TimeIntervalCollection_default();
this._intervals.changedEvent.addEventListener(
CompositeProperty.prototype._intervalsChanged,
this
);
}
Object.defineProperties(CompositeProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof CompositeProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return this._intervals.isEmpty;
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is changed whenever setValue is called with data different
* than the current value.
* @memberof CompositeProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets the interval collection.
* @memberof CompositeProperty.prototype
*
* @type {TimeIntervalCollection}
*/
intervals: {
get: function() {
return this._intervals;
}
}
});
var timeScratch11 = new JulianDate_default();
CompositeProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch11);
}
const innerProperty = this._intervals.findDataForIntervalContainingDate(time);
if (defined_default(innerProperty)) {
return innerProperty.getValue(time, result);
}
return void 0;
};
CompositeProperty.prototype.equals = function(other) {
return this === other || //
other instanceof CompositeProperty && //
this._intervals.equals(other._intervals, Property_default.equals);
};
CompositeProperty.prototype._intervalsChanged = function() {
subscribeAll(
this,
this._eventHelper,
this._definitionChanged,
this._intervals
);
this._definitionChanged.raiseEvent(this);
};
var CompositeProperty_default = CompositeProperty;
// packages/engine/Source/DataSources/CompositeMaterialProperty.js
function CompositeMaterialProperty() {
this._definitionChanged = new Event_default();
this._composite = new CompositeProperty_default();
this._composite.definitionChanged.addEventListener(
CompositeMaterialProperty.prototype._raiseDefinitionChanged,
this
);
}
Object.defineProperties(CompositeMaterialProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof CompositeMaterialProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return this._composite.isConstant;
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is changed whenever setValue is called with data different
* than the current value.
* @memberof CompositeMaterialProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets the interval collection.
* @memberof CompositeMaterialProperty.prototype
*
* @type {TimeIntervalCollection}
*/
intervals: {
get: function() {
return this._composite._intervals;
}
}
});
CompositeMaterialProperty.prototype.getType = function(time) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required");
}
const innerProperty = this._composite._intervals.findDataForIntervalContainingDate(time);
if (defined_default(innerProperty)) {
return innerProperty.getType(time);
}
return void 0;
};
var timeScratch12 = new JulianDate_default();
CompositeMaterialProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch12);
}
const innerProperty = this._composite._intervals.findDataForIntervalContainingDate(time);
if (defined_default(innerProperty)) {
return innerProperty.getValue(time, result);
}
return void 0;
};
CompositeMaterialProperty.prototype.equals = function(other) {
return this === other || //
other instanceof CompositeMaterialProperty && //
this._composite.equals(other._composite, Property_default.equals);
};
CompositeMaterialProperty.prototype._raiseDefinitionChanged = function() {
this._definitionChanged.raiseEvent(this);
};
var CompositeMaterialProperty_default = CompositeMaterialProperty;
// packages/engine/Source/DataSources/CompositePositionProperty.js
var import_InlineWorkers823 = __toESM(require_InlineWorkers(), 1);
function CompositePositionProperty(referenceFrame) {
this._referenceFrame = referenceFrame ?? ReferenceFrame_default.FIXED;
this._definitionChanged = new Event_default();
this._composite = new CompositeProperty_default();
this._composite.definitionChanged.addEventListener(
CompositePositionProperty.prototype._raiseDefinitionChanged,
this
);
}
Object.defineProperties(CompositePositionProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof CompositePositionProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return this._composite.isConstant;
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is changed whenever setValue is called with data different
* than the current value.
* @memberof CompositePositionProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets the interval collection.
* @memberof CompositePositionProperty.prototype
*
* @type {TimeIntervalCollection}
*/
intervals: {
get: function() {
return this._composite.intervals;
}
},
/**
* Gets or sets the reference frame which this position presents itself as.
* Each PositionProperty making up this object has it's own reference frame,
* so this property merely exposes a "preferred" reference frame for clients
* to use.
* @memberof CompositePositionProperty.prototype
*
* @type {ReferenceFrame}
*/
referenceFrame: {
get: function() {
return this._referenceFrame;
},
set: function(value) {
this._referenceFrame = value;
}
}
});
var timeScratch13 = new JulianDate_default();
CompositePositionProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch13);
}
return this.getValueInReferenceFrame(time, ReferenceFrame_default.FIXED, result);
};
CompositePositionProperty.prototype.getValueInReferenceFrame = function(time, referenceFrame, result) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required.");
}
if (!defined_default(referenceFrame)) {
throw new DeveloperError_default("referenceFrame is required.");
}
const innerProperty = this._composite._intervals.findDataForIntervalContainingDate(time);
if (defined_default(innerProperty)) {
return innerProperty.getValueInReferenceFrame(time, referenceFrame, result);
}
return void 0;
};
CompositePositionProperty.prototype.equals = function(other) {
return this === other || //
other instanceof CompositePositionProperty && //
this._referenceFrame === other._referenceFrame && //
this._composite.equals(other._composite, Property_default.equals);
};
CompositePositionProperty.prototype._raiseDefinitionChanged = function() {
this._definitionChanged.raiseEvent(this);
};
var CompositePositionProperty_default = CompositePositionProperty;
// packages/engine/Source/DataSources/CorridorGeometryUpdater.js
var import_InlineWorkers830 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/CorridorGeometry.js
var import_InlineWorkers827 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/CornerType.js
var import_InlineWorkers824 = __toESM(require_InlineWorkers(), 1);
var CornerType = {
/**
*
*
* Corner has a smooth edge.
* @type {number}
* @constant
*/
ROUNDED: 0,
/**
*
*
* Corner point is the intersection of adjacent edges.
* @type {number}
* @constant
*/
MITERED: 1,
/**
*
*
* Corner is clipped.
* @type {number}
* @constant
*/
BEVELED: 2
};
var CornerType_default = Object.freeze(CornerType);
// packages/engine/Source/Core/CorridorGeometryLibrary.js
var import_InlineWorkers826 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PolylineVolumeGeometryLibrary.js
var import_InlineWorkers825 = __toESM(require_InlineWorkers(), 1);
var scratch2Array = [new Cartesian3_default(), new Cartesian3_default()];
var scratchCartesian16 = new Cartesian3_default();
var scratchCartesian25 = new Cartesian3_default();
var scratchCartesian37 = new Cartesian3_default();
var scratchCartesian43 = new Cartesian3_default();
var scratchCartesian52 = new Cartesian3_default();
var scratchCartesian62 = new Cartesian3_default();
var scratchCartesian72 = new Cartesian3_default();
var scratchCartesian82 = new Cartesian3_default();
var scratchCartesian92 = new Cartesian3_default();
var scratch1 = new Cartesian3_default();
var scratch2 = new Cartesian3_default();
var PolylineVolumeGeometryLibrary = {};
var cartographic = new Cartographic_default();
function scaleToSurface(positions, ellipsoid) {
const heights = new Array(positions.length);
for (let i = 0; i < positions.length; i++) {
const pos = positions[i];
cartographic = ellipsoid.cartesianToCartographic(pos, cartographic);
heights[i] = cartographic.height;
positions[i] = ellipsoid.scaleToGeodeticSurface(pos, pos);
}
return heights;
}
function subdivideHeights2(points, h0, h1, granularity) {
const p0 = points[0];
const p1 = points[1];
const angleBetween = Cartesian3_default.angleBetween(p0, p1);
const numPoints = Math.ceil(angleBetween / granularity);
const heights = new Array(numPoints);
let i;
if (h0 === h1) {
for (i = 0; i < numPoints; i++) {
heights[i] = h0;
}
heights.push(h1);
return heights;
}
const dHeight = h1 - h0;
const heightPerVertex = dHeight / numPoints;
for (i = 1; i < numPoints; i++) {
const h = h0 + i * heightPerVertex;
heights[i] = h;
}
heights[0] = h0;
heights.push(h1);
return heights;
}
var nextScratch = new Cartesian3_default();
var prevScratch = new Cartesian3_default();
function computeRotationAngle(start, end, position, ellipsoid) {
const tangentPlane = new EllipsoidTangentPlane_default(position, ellipsoid);
const next = tangentPlane.projectPointOntoPlane(
Cartesian3_default.add(position, start, nextScratch),
nextScratch
);
const prev = tangentPlane.projectPointOntoPlane(
Cartesian3_default.add(position, end, prevScratch),
prevScratch
);
const angle = Cartesian2_default.angleBetween(next, prev);
return prev.x * next.y - prev.y * next.x >= 0 ? -angle : angle;
}
var negativeX = new Cartesian3_default(-1, 0, 0);
var transform = new Matrix4_default();
var translation2 = new Matrix4_default();
var rotationZ = new Matrix3_default();
var scaleMatrix = Matrix3_default.IDENTITY.clone();
var westScratch = new Cartesian3_default();
var finalPosScratch = new Cartesian4_default();
var heightCartesian = new Cartesian3_default();
function addPosition(center, left, shape, finalPositions, ellipsoid, height, xScalar, repeat) {
let west = westScratch;
let finalPosition = finalPosScratch;
transform = Transforms_default.eastNorthUpToFixedFrame(center, ellipsoid, transform);
west = Matrix4_default.multiplyByPointAsVector(transform, negativeX, west);
west = Cartesian3_default.normalize(west, west);
const angle = computeRotationAngle(west, left, center, ellipsoid);
rotationZ = Matrix3_default.fromRotationZ(angle, rotationZ);
heightCartesian.z = height;
transform = Matrix4_default.multiplyTransformation(
transform,
Matrix4_default.fromRotationTranslation(rotationZ, heightCartesian, translation2),
transform
);
const scale = scaleMatrix;
scale[0] = xScalar;
for (let j = 0; j < repeat; j++) {
for (let i = 0; i < shape.length; i += 3) {
finalPosition = Cartesian3_default.fromArray(shape, i, finalPosition);
finalPosition = Matrix3_default.multiplyByVector(
scale,
finalPosition,
finalPosition
);
finalPosition = Matrix4_default.multiplyByPoint(
transform,
finalPosition,
finalPosition
);
finalPositions.push(finalPosition.x, finalPosition.y, finalPosition.z);
}
}
return finalPositions;
}
var centerScratch2 = new Cartesian3_default();
function addPositions(centers, left, shape, finalPositions, ellipsoid, heights, xScalar) {
for (let i = 0; i < centers.length; i += 3) {
const center = Cartesian3_default.fromArray(centers, i, centerScratch2);
finalPositions = addPosition(
center,
left,
shape,
finalPositions,
ellipsoid,
heights[i / 3],
xScalar,
1
);
}
return finalPositions;
}
function convertShapeTo3DDuplicate(shape2D, boundingRectangle) {
const length2 = shape2D.length;
const shape = new Array(length2 * 6);
let index = 0;
const xOffset = boundingRectangle.x + boundingRectangle.width / 2;
const yOffset = boundingRectangle.y + boundingRectangle.height / 2;
let point = shape2D[0];
shape[index++] = point.x - xOffset;
shape[index++] = 0;
shape[index++] = point.y - yOffset;
for (let i = 1; i < length2; i++) {
point = shape2D[i];
const x = point.x - xOffset;
const z = point.y - yOffset;
shape[index++] = x;
shape[index++] = 0;
shape[index++] = z;
shape[index++] = x;
shape[index++] = 0;
shape[index++] = z;
}
point = shape2D[0];
shape[index++] = point.x - xOffset;
shape[index++] = 0;
shape[index++] = point.y - yOffset;
return shape;
}
function convertShapeTo3D(shape2D, boundingRectangle) {
const length2 = shape2D.length;
const shape = new Array(length2 * 3);
let index = 0;
const xOffset = boundingRectangle.x + boundingRectangle.width / 2;
const yOffset = boundingRectangle.y + boundingRectangle.height / 2;
for (let i = 0; i < length2; i++) {
shape[index++] = shape2D[i].x - xOffset;
shape[index++] = 0;
shape[index++] = shape2D[i].y - yOffset;
}
return shape;
}
var quaterion = new Quaternion_default();
var startPointScratch = new Cartesian3_default();
var rotMatrix = new Matrix3_default();
function computeRoundCorner(pivot, startPoint, endPoint, cornerType, leftIsOutside, ellipsoid, finalPositions, shape, height, duplicatePoints) {
const angle = Cartesian3_default.angleBetween(
Cartesian3_default.subtract(startPoint, pivot, scratch1),
Cartesian3_default.subtract(endPoint, pivot, scratch2)
);
const granularity = cornerType === CornerType_default.BEVELED ? 0 : Math.ceil(angle / Math_default.toRadians(5));
let m;
if (leftIsOutside) {
m = Matrix3_default.fromQuaternion(
Quaternion_default.fromAxisAngle(
Cartesian3_default.negate(pivot, scratch1),
angle / (granularity + 1),
quaterion
),
rotMatrix
);
} else {
m = Matrix3_default.fromQuaternion(
Quaternion_default.fromAxisAngle(pivot, angle / (granularity + 1), quaterion),
rotMatrix
);
}
let left;
let surfacePoint;
startPoint = Cartesian3_default.clone(startPoint, startPointScratch);
if (granularity > 0) {
const repeat = duplicatePoints ? 2 : 1;
for (let i = 0; i < granularity; i++) {
startPoint = Matrix3_default.multiplyByVector(m, startPoint, startPoint);
left = Cartesian3_default.subtract(startPoint, pivot, scratch1);
left = Cartesian3_default.normalize(left, left);
if (!leftIsOutside) {
left = Cartesian3_default.negate(left, left);
}
surfacePoint = ellipsoid.scaleToGeodeticSurface(startPoint, scratch2);
finalPositions = addPosition(
surfacePoint,
left,
shape,
finalPositions,
ellipsoid,
height,
1,
repeat
);
}
} else {
left = Cartesian3_default.subtract(startPoint, pivot, scratch1);
left = Cartesian3_default.normalize(left, left);
if (!leftIsOutside) {
left = Cartesian3_default.negate(left, left);
}
surfacePoint = ellipsoid.scaleToGeodeticSurface(startPoint, scratch2);
finalPositions = addPosition(
surfacePoint,
left,
shape,
finalPositions,
ellipsoid,
height,
1,
1
);
endPoint = Cartesian3_default.clone(endPoint, startPointScratch);
left = Cartesian3_default.subtract(endPoint, pivot, scratch1);
left = Cartesian3_default.normalize(left, left);
if (!leftIsOutside) {
left = Cartesian3_default.negate(left, left);
}
surfacePoint = ellipsoid.scaleToGeodeticSurface(endPoint, scratch2);
finalPositions = addPosition(
surfacePoint,
left,
shape,
finalPositions,
ellipsoid,
height,
1,
1
);
}
return finalPositions;
}
PolylineVolumeGeometryLibrary.removeDuplicatesFromShape = function(shapePositions) {
const length2 = shapePositions.length;
const cleanedPositions = [];
for (let i0 = length2 - 1, i1 = 0; i1 < length2; i0 = i1++) {
const v02 = shapePositions[i0];
const v12 = shapePositions[i1];
if (!Cartesian2_default.equals(v02, v12)) {
cleanedPositions.push(v12);
}
}
return cleanedPositions;
};
PolylineVolumeGeometryLibrary.angleIsGreaterThanPi = function(forward, backward, position, ellipsoid) {
const tangentPlane = new EllipsoidTangentPlane_default(position, ellipsoid);
const next = tangentPlane.projectPointOntoPlane(
Cartesian3_default.add(position, forward, nextScratch),
nextScratch
);
const prev = tangentPlane.projectPointOntoPlane(
Cartesian3_default.add(position, backward, prevScratch),
prevScratch
);
return prev.x * next.y - prev.y * next.x >= 0;
};
var scratchForwardProjection = new Cartesian3_default();
var scratchBackwardProjection = new Cartesian3_default();
PolylineVolumeGeometryLibrary.computePositions = function(positions, shape2D, boundingRectangle, geometry, duplicatePoints) {
const ellipsoid = geometry._ellipsoid;
const heights = scaleToSurface(positions, ellipsoid);
const granularity = geometry._granularity;
const cornerType = geometry._cornerType;
const shapeForSides = duplicatePoints ? convertShapeTo3DDuplicate(shape2D, boundingRectangle) : convertShapeTo3D(shape2D, boundingRectangle);
const shapeForEnds = duplicatePoints ? convertShapeTo3D(shape2D, boundingRectangle) : void 0;
const heightOffset = boundingRectangle.height / 2;
const width = boundingRectangle.width / 2;
let length2 = positions.length;
let finalPositions = [];
let ends = duplicatePoints ? [] : void 0;
let forward = scratchCartesian16;
let backward = scratchCartesian25;
let cornerDirection = scratchCartesian37;
let surfaceNormal = scratchCartesian43;
let pivot = scratchCartesian52;
let start = scratchCartesian62;
let end = scratchCartesian72;
let left = scratchCartesian82;
let previousPosition = scratchCartesian92;
let position = positions[0];
let nextPosition = positions[1];
surfaceNormal = ellipsoid.geodeticSurfaceNormal(position, surfaceNormal);
forward = Cartesian3_default.subtract(nextPosition, position, forward);
forward = Cartesian3_default.normalize(forward, forward);
left = Cartesian3_default.cross(surfaceNormal, forward, left);
left = Cartesian3_default.normalize(left, left);
let h0 = heights[0];
let h1 = heights[1];
if (duplicatePoints) {
ends = addPosition(
position,
left,
shapeForEnds,
ends,
ellipsoid,
h0 + heightOffset,
1,
1
);
}
previousPosition = Cartesian3_default.clone(position, previousPosition);
position = nextPosition;
backward = Cartesian3_default.negate(forward, backward);
let subdividedHeights;
let subdividedPositions;
for (let i = 1; i < length2 - 1; i++) {
const repeat = duplicatePoints ? 2 : 1;
nextPosition = positions[i + 1];
if (position.equals(nextPosition)) {
oneTimeWarning_default(
"Positions are too close and are considered equivalent with rounding error."
);
continue;
}
forward = Cartesian3_default.subtract(nextPosition, position, forward);
forward = Cartesian3_default.normalize(forward, forward);
surfaceNormal = ellipsoid.geodeticSurfaceNormal(position, surfaceNormal);
const forwardProjection = Cartesian3_default.multiplyByScalar(
surfaceNormal,
Cartesian3_default.dot(forward, surfaceNormal),
scratchForwardProjection
);
Cartesian3_default.subtract(forward, forwardProjection, forwardProjection);
Cartesian3_default.normalize(forwardProjection, forwardProjection);
const backwardProjection = Cartesian3_default.multiplyByScalar(
surfaceNormal,
Cartesian3_default.dot(backward, surfaceNormal),
scratchBackwardProjection
);
Cartesian3_default.subtract(backward, backwardProjection, backwardProjection);
Cartesian3_default.normalize(backwardProjection, backwardProjection);
const doCorner = !Math_default.equalsEpsilon(
Math.abs(Cartesian3_default.dot(forwardProjection, backwardProjection)),
1,
Math_default.EPSILON7
);
if (doCorner) {
cornerDirection = Cartesian3_default.add(forward, backward, cornerDirection);
cornerDirection = Cartesian3_default.normalize(cornerDirection, cornerDirection);
cornerDirection = Cartesian3_default.cross(
cornerDirection,
surfaceNormal,
cornerDirection
);
cornerDirection = Cartesian3_default.cross(
surfaceNormal,
cornerDirection,
cornerDirection
);
cornerDirection = Cartesian3_default.normalize(cornerDirection, cornerDirection);
const scalar = 1 / Math.max(
0.25,
Cartesian3_default.magnitude(
Cartesian3_default.cross(cornerDirection, backward, scratch1)
)
);
const leftIsOutside = PolylineVolumeGeometryLibrary.angleIsGreaterThanPi(
forward,
backward,
position,
ellipsoid
);
if (leftIsOutside) {
pivot = Cartesian3_default.add(
position,
Cartesian3_default.multiplyByScalar(
cornerDirection,
scalar * width,
cornerDirection
),
pivot
);
start = Cartesian3_default.add(
pivot,
Cartesian3_default.multiplyByScalar(left, width, start),
start
);
scratch2Array[0] = Cartesian3_default.clone(previousPosition, scratch2Array[0]);
scratch2Array[1] = Cartesian3_default.clone(start, scratch2Array[1]);
subdividedHeights = subdivideHeights2(
scratch2Array,
h0 + heightOffset,
h1 + heightOffset,
granularity
);
subdividedPositions = PolylinePipeline_default.generateArc({
positions: scratch2Array,
granularity,
ellipsoid
});
finalPositions = addPositions(
subdividedPositions,
left,
shapeForSides,
finalPositions,
ellipsoid,
subdividedHeights,
1
);
left = Cartesian3_default.cross(surfaceNormal, forward, left);
left = Cartesian3_default.normalize(left, left);
end = Cartesian3_default.add(
pivot,
Cartesian3_default.multiplyByScalar(left, width, end),
end
);
if (cornerType === CornerType_default.ROUNDED || cornerType === CornerType_default.BEVELED) {
computeRoundCorner(
pivot,
start,
end,
cornerType,
leftIsOutside,
ellipsoid,
finalPositions,
shapeForSides,
h1 + heightOffset,
duplicatePoints
);
} else {
cornerDirection = Cartesian3_default.negate(cornerDirection, cornerDirection);
finalPositions = addPosition(
position,
cornerDirection,
shapeForSides,
finalPositions,
ellipsoid,
h1 + heightOffset,
scalar,
repeat
);
}
previousPosition = Cartesian3_default.clone(end, previousPosition);
} else {
pivot = Cartesian3_default.add(
position,
Cartesian3_default.multiplyByScalar(
cornerDirection,
scalar * width,
cornerDirection
),
pivot
);
start = Cartesian3_default.add(
pivot,
Cartesian3_default.multiplyByScalar(left, -width, start),
start
);
scratch2Array[0] = Cartesian3_default.clone(previousPosition, scratch2Array[0]);
scratch2Array[1] = Cartesian3_default.clone(start, scratch2Array[1]);
subdividedHeights = subdivideHeights2(
scratch2Array,
h0 + heightOffset,
h1 + heightOffset,
granularity
);
subdividedPositions = PolylinePipeline_default.generateArc({
positions: scratch2Array,
granularity,
ellipsoid
});
finalPositions = addPositions(
subdividedPositions,
left,
shapeForSides,
finalPositions,
ellipsoid,
subdividedHeights,
1
);
left = Cartesian3_default.cross(surfaceNormal, forward, left);
left = Cartesian3_default.normalize(left, left);
end = Cartesian3_default.add(
pivot,
Cartesian3_default.multiplyByScalar(left, -width, end),
end
);
if (cornerType === CornerType_default.ROUNDED || cornerType === CornerType_default.BEVELED) {
computeRoundCorner(
pivot,
start,
end,
cornerType,
leftIsOutside,
ellipsoid,
finalPositions,
shapeForSides,
h1 + heightOffset,
duplicatePoints
);
} else {
finalPositions = addPosition(
position,
cornerDirection,
shapeForSides,
finalPositions,
ellipsoid,
h1 + heightOffset,
scalar,
repeat
);
}
previousPosition = Cartesian3_default.clone(end, previousPosition);
}
backward = Cartesian3_default.negate(forward, backward);
} else {
finalPositions = addPosition(
previousPosition,
left,
shapeForSides,
finalPositions,
ellipsoid,
h0 + heightOffset,
1,
1
);
previousPosition = position;
}
h0 = h1;
h1 = heights[i + 1];
position = nextPosition;
}
scratch2Array[0] = Cartesian3_default.clone(previousPosition, scratch2Array[0]);
scratch2Array[1] = Cartesian3_default.clone(position, scratch2Array[1]);
subdividedHeights = subdivideHeights2(
scratch2Array,
h0 + heightOffset,
h1 + heightOffset,
granularity
);
subdividedPositions = PolylinePipeline_default.generateArc({
positions: scratch2Array,
granularity,
ellipsoid
});
finalPositions = addPositions(
subdividedPositions,
left,
shapeForSides,
finalPositions,
ellipsoid,
subdividedHeights,
1
);
if (duplicatePoints) {
ends = addPosition(
position,
left,
shapeForEnds,
ends,
ellipsoid,
h1 + heightOffset,
1,
1
);
}
length2 = finalPositions.length;
const posLength = duplicatePoints ? length2 + ends.length : length2;
const combinedPositions = new Float64Array(posLength);
combinedPositions.set(finalPositions);
if (duplicatePoints) {
combinedPositions.set(ends, length2);
}
return combinedPositions;
};
var PolylineVolumeGeometryLibrary_default = PolylineVolumeGeometryLibrary;
// packages/engine/Source/Core/CorridorGeometryLibrary.js
var CorridorGeometryLibrary = {};
var scratch12 = new Cartesian3_default();
var scratch22 = new Cartesian3_default();
var scratch3 = new Cartesian3_default();
var scratch4 = new Cartesian3_default();
var scaleArray2 = [new Cartesian3_default(), new Cartesian3_default()];
var cartesian1 = new Cartesian3_default();
var cartesian2 = new Cartesian3_default();
var cartesian3 = new Cartesian3_default();
var cartesian4 = new Cartesian3_default();
var cartesian5 = new Cartesian3_default();
var cartesian6 = new Cartesian3_default();
var cartesian7 = new Cartesian3_default();
var cartesian8 = new Cartesian3_default();
var cartesian9 = new Cartesian3_default();
var cartesian10 = new Cartesian3_default();
var quaterion2 = new Quaternion_default();
var rotMatrix2 = new Matrix3_default();
function computeRoundCorner2(cornerPoint, startPoint, endPoint, cornerType, leftIsOutside) {
const angle = Cartesian3_default.angleBetween(
Cartesian3_default.subtract(startPoint, cornerPoint, scratch12),
Cartesian3_default.subtract(endPoint, cornerPoint, scratch22)
);
const granularity = cornerType === CornerType_default.BEVELED ? 1 : Math.ceil(angle / Math_default.toRadians(5)) + 1;
const size = granularity * 3;
const array = new Array(size);
array[size - 3] = endPoint.x;
array[size - 2] = endPoint.y;
array[size - 1] = endPoint.z;
let m;
if (leftIsOutside) {
m = Matrix3_default.fromQuaternion(
Quaternion_default.fromAxisAngle(
Cartesian3_default.negate(cornerPoint, scratch12),
angle / granularity,
quaterion2
),
rotMatrix2
);
} else {
m = Matrix3_default.fromQuaternion(
Quaternion_default.fromAxisAngle(cornerPoint, angle / granularity, quaterion2),
rotMatrix2
);
}
let index = 0;
startPoint = Cartesian3_default.clone(startPoint, scratch12);
for (let i = 0; i < granularity; i++) {
startPoint = Matrix3_default.multiplyByVector(m, startPoint, startPoint);
array[index++] = startPoint.x;
array[index++] = startPoint.y;
array[index++] = startPoint.z;
}
return array;
}
function addEndCaps(calculatedPositions) {
let cornerPoint = cartesian1;
let startPoint = cartesian2;
let endPoint = cartesian3;
let leftEdge = calculatedPositions[1];
startPoint = Cartesian3_default.fromArray(
calculatedPositions[1],
leftEdge.length - 3,
startPoint
);
endPoint = Cartesian3_default.fromArray(calculatedPositions[0], 0, endPoint);
cornerPoint = Cartesian3_default.midpoint(startPoint, endPoint, cornerPoint);
const firstEndCap = computeRoundCorner2(
cornerPoint,
startPoint,
endPoint,
CornerType_default.ROUNDED,
false
);
const length2 = calculatedPositions.length - 1;
const rightEdge = calculatedPositions[length2 - 1];
leftEdge = calculatedPositions[length2];
startPoint = Cartesian3_default.fromArray(
rightEdge,
rightEdge.length - 3,
startPoint
);
endPoint = Cartesian3_default.fromArray(leftEdge, 0, endPoint);
cornerPoint = Cartesian3_default.midpoint(startPoint, endPoint, cornerPoint);
const lastEndCap = computeRoundCorner2(
cornerPoint,
startPoint,
endPoint,
CornerType_default.ROUNDED,
false
);
return [firstEndCap, lastEndCap];
}
function computeMiteredCorner(position, leftCornerDirection, lastPoint, leftIsOutside) {
let cornerPoint = scratch12;
if (leftIsOutside) {
cornerPoint = Cartesian3_default.add(position, leftCornerDirection, cornerPoint);
} else {
leftCornerDirection = Cartesian3_default.negate(
leftCornerDirection,
leftCornerDirection
);
cornerPoint = Cartesian3_default.add(position, leftCornerDirection, cornerPoint);
}
return [
cornerPoint.x,
cornerPoint.y,
cornerPoint.z,
lastPoint.x,
lastPoint.y,
lastPoint.z
];
}
function addShiftedPositions(positions, left, scalar, calculatedPositions) {
const rightPositions = new Array(positions.length);
const leftPositions = new Array(positions.length);
const scaledLeft = Cartesian3_default.multiplyByScalar(left, scalar, scratch12);
const scaledRight = Cartesian3_default.negate(scaledLeft, scratch22);
let rightIndex = 0;
let leftIndex = positions.length - 1;
for (let i = 0; i < positions.length; i += 3) {
const pos = Cartesian3_default.fromArray(positions, i, scratch3);
const rightPos = Cartesian3_default.add(pos, scaledRight, scratch4);
rightPositions[rightIndex++] = rightPos.x;
rightPositions[rightIndex++] = rightPos.y;
rightPositions[rightIndex++] = rightPos.z;
const leftPos = Cartesian3_default.add(pos, scaledLeft, scratch4);
leftPositions[leftIndex--] = leftPos.z;
leftPositions[leftIndex--] = leftPos.y;
leftPositions[leftIndex--] = leftPos.x;
}
calculatedPositions.push(rightPositions, leftPositions);
return calculatedPositions;
}
CorridorGeometryLibrary.addAttribute = function(attribute, value, front, back) {
const x = value.x;
const y = value.y;
const z = value.z;
if (defined_default(front)) {
attribute[front] = x;
attribute[front + 1] = y;
attribute[front + 2] = z;
}
if (defined_default(back)) {
attribute[back] = z;
attribute[back - 1] = y;
attribute[back - 2] = x;
}
};
var scratchForwardProjection2 = new Cartesian3_default();
var scratchBackwardProjection2 = new Cartesian3_default();
CorridorGeometryLibrary.computePositions = function(params) {
const granularity = params.granularity;
const positions = params.positions;
const ellipsoid = params.ellipsoid;
const width = params.width / 2;
const cornerType = params.cornerType;
const saveAttributes = params.saveAttributes;
let normal2 = cartesian1;
let forward = cartesian2;
let backward = cartesian3;
let left = cartesian4;
let cornerDirection = cartesian5;
let startPoint = cartesian6;
let previousPos = cartesian7;
let rightPos = cartesian8;
let leftPos = cartesian9;
let center = cartesian10;
let calculatedPositions = [];
const calculatedLefts = saveAttributes ? [] : void 0;
const calculatedNormals = saveAttributes ? [] : void 0;
let position = positions[0];
let nextPosition = positions[1];
forward = Cartesian3_default.normalize(
Cartesian3_default.subtract(nextPosition, position, forward),
forward
);
normal2 = ellipsoid.geodeticSurfaceNormal(position, normal2);
left = Cartesian3_default.normalize(Cartesian3_default.cross(normal2, forward, left), left);
if (saveAttributes) {
calculatedLefts.push(left.x, left.y, left.z);
calculatedNormals.push(normal2.x, normal2.y, normal2.z);
}
previousPos = Cartesian3_default.clone(position, previousPos);
position = nextPosition;
backward = Cartesian3_default.negate(forward, backward);
let subdividedPositions;
const corners2 = [];
let i;
const length2 = positions.length;
for (i = 1; i < length2 - 1; i++) {
normal2 = ellipsoid.geodeticSurfaceNormal(position, normal2);
nextPosition = positions[i + 1];
forward = Cartesian3_default.normalize(
Cartesian3_default.subtract(nextPosition, position, forward),
forward
);
const forwardProjection = Cartesian3_default.multiplyByScalar(
normal2,
Cartesian3_default.dot(forward, normal2),
scratchForwardProjection2
);
Cartesian3_default.subtract(forward, forwardProjection, forwardProjection);
Cartesian3_default.normalize(forwardProjection, forwardProjection);
const backwardProjection = Cartesian3_default.multiplyByScalar(
normal2,
Cartesian3_default.dot(backward, normal2),
scratchBackwardProjection2
);
Cartesian3_default.subtract(backward, backwardProjection, backwardProjection);
Cartesian3_default.normalize(backwardProjection, backwardProjection);
const doCorner = !Math_default.equalsEpsilon(
Math.abs(Cartesian3_default.dot(forwardProjection, backwardProjection)),
1,
Math_default.EPSILON7
);
if (doCorner) {
cornerDirection = Cartesian3_default.normalize(
Cartesian3_default.add(forward, backward, cornerDirection),
cornerDirection
);
cornerDirection = Cartesian3_default.cross(
cornerDirection,
normal2,
cornerDirection
);
cornerDirection = Cartesian3_default.cross(
normal2,
cornerDirection,
cornerDirection
);
cornerDirection = Cartesian3_default.normalize(cornerDirection, cornerDirection);
const scalar = width / Math.max(
0.25,
Cartesian3_default.magnitude(
Cartesian3_default.cross(cornerDirection, backward, scratch12)
)
);
const leftIsOutside = PolylineVolumeGeometryLibrary_default.angleIsGreaterThanPi(
forward,
backward,
position,
ellipsoid
);
cornerDirection = Cartesian3_default.multiplyByScalar(
cornerDirection,
scalar,
cornerDirection
);
if (leftIsOutside) {
rightPos = Cartesian3_default.add(position, cornerDirection, rightPos);
center = Cartesian3_default.add(
rightPos,
Cartesian3_default.multiplyByScalar(left, width, center),
center
);
leftPos = Cartesian3_default.add(
rightPos,
Cartesian3_default.multiplyByScalar(left, width * 2, leftPos),
leftPos
);
scaleArray2[0] = Cartesian3_default.clone(previousPos, scaleArray2[0]);
scaleArray2[1] = Cartesian3_default.clone(center, scaleArray2[1]);
subdividedPositions = PolylinePipeline_default.generateArc({
positions: scaleArray2,
granularity,
ellipsoid
});
calculatedPositions = addShiftedPositions(
subdividedPositions,
left,
width,
calculatedPositions
);
if (saveAttributes) {
calculatedLefts.push(left.x, left.y, left.z);
calculatedNormals.push(normal2.x, normal2.y, normal2.z);
}
startPoint = Cartesian3_default.clone(leftPos, startPoint);
left = Cartesian3_default.normalize(
Cartesian3_default.cross(normal2, forward, left),
left
);
leftPos = Cartesian3_default.add(
rightPos,
Cartesian3_default.multiplyByScalar(left, width * 2, leftPos),
leftPos
);
previousPos = Cartesian3_default.add(
rightPos,
Cartesian3_default.multiplyByScalar(left, width, previousPos),
previousPos
);
if (cornerType === CornerType_default.ROUNDED || cornerType === CornerType_default.BEVELED) {
corners2.push({
leftPositions: computeRoundCorner2(
rightPos,
startPoint,
leftPos,
cornerType,
leftIsOutside
)
});
} else {
corners2.push({
leftPositions: computeMiteredCorner(
position,
Cartesian3_default.negate(cornerDirection, cornerDirection),
leftPos,
leftIsOutside
)
});
}
} else {
leftPos = Cartesian3_default.add(position, cornerDirection, leftPos);
center = Cartesian3_default.add(
leftPos,
Cartesian3_default.negate(
Cartesian3_default.multiplyByScalar(left, width, center),
center
),
center
);
rightPos = Cartesian3_default.add(
leftPos,
Cartesian3_default.negate(
Cartesian3_default.multiplyByScalar(left, width * 2, rightPos),
rightPos
),
rightPos
);
scaleArray2[0] = Cartesian3_default.clone(previousPos, scaleArray2[0]);
scaleArray2[1] = Cartesian3_default.clone(center, scaleArray2[1]);
subdividedPositions = PolylinePipeline_default.generateArc({
positions: scaleArray2,
granularity,
ellipsoid
});
calculatedPositions = addShiftedPositions(
subdividedPositions,
left,
width,
calculatedPositions
);
if (saveAttributes) {
calculatedLefts.push(left.x, left.y, left.z);
calculatedNormals.push(normal2.x, normal2.y, normal2.z);
}
startPoint = Cartesian3_default.clone(rightPos, startPoint);
left = Cartesian3_default.normalize(
Cartesian3_default.cross(normal2, forward, left),
left
);
rightPos = Cartesian3_default.add(
leftPos,
Cartesian3_default.negate(
Cartesian3_default.multiplyByScalar(left, width * 2, rightPos),
rightPos
),
rightPos
);
previousPos = Cartesian3_default.add(
leftPos,
Cartesian3_default.negate(
Cartesian3_default.multiplyByScalar(left, width, previousPos),
previousPos
),
previousPos
);
if (cornerType === CornerType_default.ROUNDED || cornerType === CornerType_default.BEVELED) {
corners2.push({
rightPositions: computeRoundCorner2(
leftPos,
startPoint,
rightPos,
cornerType,
leftIsOutside
)
});
} else {
corners2.push({
rightPositions: computeMiteredCorner(
position,
cornerDirection,
rightPos,
leftIsOutside
)
});
}
}
backward = Cartesian3_default.negate(forward, backward);
}
position = nextPosition;
}
normal2 = ellipsoid.geodeticSurfaceNormal(position, normal2);
scaleArray2[0] = Cartesian3_default.clone(previousPos, scaleArray2[0]);
scaleArray2[1] = Cartesian3_default.clone(position, scaleArray2[1]);
subdividedPositions = PolylinePipeline_default.generateArc({
positions: scaleArray2,
granularity,
ellipsoid
});
calculatedPositions = addShiftedPositions(
subdividedPositions,
left,
width,
calculatedPositions
);
if (saveAttributes) {
calculatedLefts.push(left.x, left.y, left.z);
calculatedNormals.push(normal2.x, normal2.y, normal2.z);
}
let endPositions;
if (cornerType === CornerType_default.ROUNDED) {
endPositions = addEndCaps(calculatedPositions);
}
return {
positions: calculatedPositions,
corners: corners2,
lefts: calculatedLefts,
normals: calculatedNormals,
endPositions
};
};
var CorridorGeometryLibrary_default = CorridorGeometryLibrary;
// packages/engine/Source/Core/CorridorGeometry.js
var cartesian12 = new Cartesian3_default();
var cartesian22 = new Cartesian3_default();
var cartesian32 = new Cartesian3_default();
var cartesian42 = new Cartesian3_default();
var cartesian52 = new Cartesian3_default();
var cartesian62 = new Cartesian3_default();
var scratch13 = new Cartesian3_default();
var scratch23 = new Cartesian3_default();
function scaleToSurface2(positions, ellipsoid) {
for (let i = 0; i < positions.length; i++) {
positions[i] = ellipsoid.scaleToGeodeticSurface(positions[i], positions[i]);
}
return positions;
}
function addNormals(attr, normal2, left, front, back, vertexFormat) {
const normals = attr.normals;
const tangents = attr.tangents;
const bitangents = attr.bitangents;
const forward = Cartesian3_default.normalize(
Cartesian3_default.cross(left, normal2, scratch13),
scratch13
);
if (vertexFormat.normal) {
CorridorGeometryLibrary_default.addAttribute(normals, normal2, front, back);
}
if (vertexFormat.tangent) {
CorridorGeometryLibrary_default.addAttribute(tangents, forward, front, back);
}
if (vertexFormat.bitangent) {
CorridorGeometryLibrary_default.addAttribute(bitangents, left, front, back);
}
}
function combine2(computedPositions, vertexFormat, ellipsoid) {
const positions = computedPositions.positions;
const corners2 = computedPositions.corners;
const endPositions = computedPositions.endPositions;
const computedLefts = computedPositions.lefts;
const computedNormals = computedPositions.normals;
const attributes = new GeometryAttributes_default();
let corner;
let leftCount = 0;
let rightCount = 0;
let i;
let indicesLength = 0;
let length2;
for (i = 0; i < positions.length; i += 2) {
length2 = positions[i].length - 3;
leftCount += length2;
indicesLength += length2 * 2;
rightCount += positions[i + 1].length - 3;
}
leftCount += 3;
rightCount += 3;
for (i = 0; i < corners2.length; i++) {
corner = corners2[i];
const leftSide = corners2[i].leftPositions;
if (defined_default(leftSide)) {
length2 = leftSide.length;
leftCount += length2;
indicesLength += length2;
} else {
length2 = corners2[i].rightPositions.length;
rightCount += length2;
indicesLength += length2;
}
}
const addEndPositions = defined_default(endPositions);
let endPositionLength;
if (addEndPositions) {
endPositionLength = endPositions[0].length - 3;
leftCount += endPositionLength;
rightCount += endPositionLength;
endPositionLength /= 3;
indicesLength += endPositionLength * 6;
}
const size = leftCount + rightCount;
const finalPositions = new Float64Array(size);
const normals = vertexFormat.normal ? new Float32Array(size) : void 0;
const tangents = vertexFormat.tangent ? new Float32Array(size) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(size) : void 0;
const attr = {
normals,
tangents,
bitangents
};
let front = 0;
let back = size - 1;
let UL, LL, UR, LR;
let normal2 = cartesian12;
let left = cartesian22;
let rightPos, leftPos;
const halfLength = endPositionLength / 2;
const indices = IndexDatatype_default.createTypedArray(size / 3, indicesLength);
let index = 0;
if (addEndPositions) {
leftPos = cartesian32;
rightPos = cartesian42;
const firstEndPositions = endPositions[0];
normal2 = Cartesian3_default.fromArray(computedNormals, 0, normal2);
left = Cartesian3_default.fromArray(computedLefts, 0, left);
for (i = 0; i < halfLength; i++) {
leftPos = Cartesian3_default.fromArray(
firstEndPositions,
(halfLength - 1 - i) * 3,
leftPos
);
rightPos = Cartesian3_default.fromArray(
firstEndPositions,
(halfLength + i) * 3,
rightPos
);
CorridorGeometryLibrary_default.addAttribute(finalPositions, rightPos, front);
CorridorGeometryLibrary_default.addAttribute(
finalPositions,
leftPos,
void 0,
back
);
addNormals(attr, normal2, left, front, back, vertexFormat);
LL = front / 3;
LR = LL + 1;
UL = (back - 2) / 3;
UR = UL - 1;
indices[index++] = UL;
indices[index++] = LL;
indices[index++] = UR;
indices[index++] = UR;
indices[index++] = LL;
indices[index++] = LR;
front += 3;
back -= 3;
}
}
let posIndex = 0;
let compIndex = 0;
let rightEdge = positions[posIndex++];
let leftEdge = positions[posIndex++];
finalPositions.set(rightEdge, front);
finalPositions.set(leftEdge, back - leftEdge.length + 1);
left = Cartesian3_default.fromArray(computedLefts, compIndex, left);
let rightNormal;
let leftNormal;
length2 = leftEdge.length - 3;
for (i = 0; i < length2; i += 3) {
rightNormal = ellipsoid.geodeticSurfaceNormal(
Cartesian3_default.fromArray(rightEdge, i, scratch13),
scratch13
);
leftNormal = ellipsoid.geodeticSurfaceNormal(
Cartesian3_default.fromArray(leftEdge, length2 - i, scratch23),
scratch23
);
normal2 = Cartesian3_default.normalize(
Cartesian3_default.add(rightNormal, leftNormal, normal2),
normal2
);
addNormals(attr, normal2, left, front, back, vertexFormat);
LL = front / 3;
LR = LL + 1;
UL = (back - 2) / 3;
UR = UL - 1;
indices[index++] = UL;
indices[index++] = LL;
indices[index++] = UR;
indices[index++] = UR;
indices[index++] = LL;
indices[index++] = LR;
front += 3;
back -= 3;
}
rightNormal = ellipsoid.geodeticSurfaceNormal(
Cartesian3_default.fromArray(rightEdge, length2, scratch13),
scratch13
);
leftNormal = ellipsoid.geodeticSurfaceNormal(
Cartesian3_default.fromArray(leftEdge, length2, scratch23),
scratch23
);
normal2 = Cartesian3_default.normalize(
Cartesian3_default.add(rightNormal, leftNormal, normal2),
normal2
);
compIndex += 3;
for (i = 0; i < corners2.length; i++) {
let j;
corner = corners2[i];
const l = corner.leftPositions;
const r = corner.rightPositions;
let pivot;
let start;
let outsidePoint = cartesian62;
let previousPoint = cartesian32;
let nextPoint = cartesian42;
normal2 = Cartesian3_default.fromArray(computedNormals, compIndex, normal2);
if (defined_default(l)) {
addNormals(attr, normal2, left, void 0, back, vertexFormat);
back -= 3;
pivot = LR;
start = UR;
for (j = 0; j < l.length / 3; j++) {
outsidePoint = Cartesian3_default.fromArray(l, j * 3, outsidePoint);
indices[index++] = pivot;
indices[index++] = start - j - 1;
indices[index++] = start - j;
CorridorGeometryLibrary_default.addAttribute(
finalPositions,
outsidePoint,
void 0,
back
);
previousPoint = Cartesian3_default.fromArray(
finalPositions,
(start - j - 1) * 3,
previousPoint
);
nextPoint = Cartesian3_default.fromArray(finalPositions, pivot * 3, nextPoint);
left = Cartesian3_default.normalize(
Cartesian3_default.subtract(previousPoint, nextPoint, left),
left
);
addNormals(attr, normal2, left, void 0, back, vertexFormat);
back -= 3;
}
outsidePoint = Cartesian3_default.fromArray(
finalPositions,
pivot * 3,
outsidePoint
);
previousPoint = Cartesian3_default.subtract(
Cartesian3_default.fromArray(finalPositions, start * 3, previousPoint),
outsidePoint,
previousPoint
);
nextPoint = Cartesian3_default.subtract(
Cartesian3_default.fromArray(finalPositions, (start - j) * 3, nextPoint),
outsidePoint,
nextPoint
);
left = Cartesian3_default.normalize(
Cartesian3_default.add(previousPoint, nextPoint, left),
left
);
addNormals(attr, normal2, left, front, void 0, vertexFormat);
front += 3;
} else {
addNormals(attr, normal2, left, front, void 0, vertexFormat);
front += 3;
pivot = UR;
start = LR;
for (j = 0; j < r.length / 3; j++) {
outsidePoint = Cartesian3_default.fromArray(r, j * 3, outsidePoint);
indices[index++] = pivot;
indices[index++] = start + j;
indices[index++] = start + j + 1;
CorridorGeometryLibrary_default.addAttribute(
finalPositions,
outsidePoint,
front
);
previousPoint = Cartesian3_default.fromArray(
finalPositions,
pivot * 3,
previousPoint
);
nextPoint = Cartesian3_default.fromArray(
finalPositions,
(start + j) * 3,
nextPoint
);
left = Cartesian3_default.normalize(
Cartesian3_default.subtract(previousPoint, nextPoint, left),
left
);
addNormals(attr, normal2, left, front, void 0, vertexFormat);
front += 3;
}
outsidePoint = Cartesian3_default.fromArray(
finalPositions,
pivot * 3,
outsidePoint
);
previousPoint = Cartesian3_default.subtract(
Cartesian3_default.fromArray(finalPositions, (start + j) * 3, previousPoint),
outsidePoint,
previousPoint
);
nextPoint = Cartesian3_default.subtract(
Cartesian3_default.fromArray(finalPositions, start * 3, nextPoint),
outsidePoint,
nextPoint
);
left = Cartesian3_default.normalize(
Cartesian3_default.negate(Cartesian3_default.add(nextPoint, previousPoint, left), left),
left
);
addNormals(attr, normal2, left, void 0, back, vertexFormat);
back -= 3;
}
rightEdge = positions[posIndex++];
leftEdge = positions[posIndex++];
rightEdge.splice(0, 3);
leftEdge.splice(leftEdge.length - 3, 3);
finalPositions.set(rightEdge, front);
finalPositions.set(leftEdge, back - leftEdge.length + 1);
length2 = leftEdge.length - 3;
compIndex += 3;
left = Cartesian3_default.fromArray(computedLefts, compIndex, left);
for (j = 0; j < leftEdge.length; j += 3) {
rightNormal = ellipsoid.geodeticSurfaceNormal(
Cartesian3_default.fromArray(rightEdge, j, scratch13),
scratch13
);
leftNormal = ellipsoid.geodeticSurfaceNormal(
Cartesian3_default.fromArray(leftEdge, length2 - j, scratch23),
scratch23
);
normal2 = Cartesian3_default.normalize(
Cartesian3_default.add(rightNormal, leftNormal, normal2),
normal2
);
addNormals(attr, normal2, left, front, back, vertexFormat);
LR = front / 3;
LL = LR - 1;
UR = (back - 2) / 3;
UL = UR + 1;
indices[index++] = UL;
indices[index++] = LL;
indices[index++] = UR;
indices[index++] = UR;
indices[index++] = LL;
indices[index++] = LR;
front += 3;
back -= 3;
}
front -= 3;
back += 3;
}
normal2 = Cartesian3_default.fromArray(
computedNormals,
computedNormals.length - 3,
normal2
);
addNormals(attr, normal2, left, front, back, vertexFormat);
if (addEndPositions) {
front += 3;
back -= 3;
leftPos = cartesian32;
rightPos = cartesian42;
const lastEndPositions = endPositions[1];
for (i = 0; i < halfLength; i++) {
leftPos = Cartesian3_default.fromArray(
lastEndPositions,
(endPositionLength - i - 1) * 3,
leftPos
);
rightPos = Cartesian3_default.fromArray(lastEndPositions, i * 3, rightPos);
CorridorGeometryLibrary_default.addAttribute(
finalPositions,
leftPos,
void 0,
back
);
CorridorGeometryLibrary_default.addAttribute(finalPositions, rightPos, front);
addNormals(attr, normal2, left, front, back, vertexFormat);
LR = front / 3;
LL = LR - 1;
UR = (back - 2) / 3;
UL = UR + 1;
indices[index++] = UL;
indices[index++] = LL;
indices[index++] = UR;
indices[index++] = UR;
indices[index++] = LL;
indices[index++] = LR;
front += 3;
back -= 3;
}
}
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: finalPositions
});
if (vertexFormat.st) {
const st = new Float32Array(size / 3 * 2);
let rightSt;
let leftSt;
let stIndex = 0;
if (addEndPositions) {
leftCount /= 3;
rightCount /= 3;
const theta = Math.PI / (endPositionLength + 1);
leftSt = 1 / (leftCount - endPositionLength + 1);
rightSt = 1 / (rightCount - endPositionLength + 1);
let a3;
const halfEndPos = endPositionLength / 2;
for (i = halfEndPos + 1; i < endPositionLength + 1; i++) {
a3 = Math_default.PI_OVER_TWO + theta * i;
st[stIndex++] = rightSt * (1 + Math.cos(a3));
st[stIndex++] = 0.5 * (1 + Math.sin(a3));
}
for (i = 1; i < rightCount - endPositionLength + 1; i++) {
st[stIndex++] = i * rightSt;
st[stIndex++] = 0;
}
for (i = endPositionLength; i > halfEndPos; i--) {
a3 = Math_default.PI_OVER_TWO - i * theta;
st[stIndex++] = 1 - rightSt * (1 + Math.cos(a3));
st[stIndex++] = 0.5 * (1 + Math.sin(a3));
}
for (i = halfEndPos; i > 0; i--) {
a3 = Math_default.PI_OVER_TWO - theta * i;
st[stIndex++] = 1 - leftSt * (1 + Math.cos(a3));
st[stIndex++] = 0.5 * (1 + Math.sin(a3));
}
for (i = leftCount - endPositionLength; i > 0; i--) {
st[stIndex++] = i * leftSt;
st[stIndex++] = 1;
}
for (i = 1; i < halfEndPos + 1; i++) {
a3 = Math_default.PI_OVER_TWO + theta * i;
st[stIndex++] = leftSt * (1 + Math.cos(a3));
st[stIndex++] = 0.5 * (1 + Math.sin(a3));
}
} else {
leftCount /= 3;
rightCount /= 3;
leftSt = 1 / (leftCount - 1);
rightSt = 1 / (rightCount - 1);
for (i = 0; i < rightCount; i++) {
st[stIndex++] = i * rightSt;
st[stIndex++] = 0;
}
for (i = leftCount; i > 0; i--) {
st[stIndex++] = (i - 1) * leftSt;
st[stIndex++] = 1;
}
}
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: st
});
}
if (vertexFormat.normal) {
attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: attr.normals
});
}
if (vertexFormat.tangent) {
attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: attr.tangents
});
}
if (vertexFormat.bitangent) {
attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: attr.bitangents
});
}
return {
attributes,
indices
};
}
function extrudedAttributes(attributes, vertexFormat) {
if (!vertexFormat.normal && !vertexFormat.tangent && !vertexFormat.bitangent && !vertexFormat.st) {
return attributes;
}
const positions = attributes.position.values;
let topNormals;
let topBitangents;
if (vertexFormat.normal || vertexFormat.bitangent) {
topNormals = attributes.normal.values;
topBitangents = attributes.bitangent.values;
}
const size = attributes.position.values.length / 18;
const threeSize = size * 3;
const twoSize = size * 2;
const sixSize = threeSize * 2;
let i;
if (vertexFormat.normal || vertexFormat.bitangent || vertexFormat.tangent) {
const normals = vertexFormat.normal ? new Float32Array(threeSize * 6) : void 0;
const tangents = vertexFormat.tangent ? new Float32Array(threeSize * 6) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(threeSize * 6) : void 0;
let topPosition = cartesian12;
let bottomPosition = cartesian22;
let previousPosition = cartesian32;
let normal2 = cartesian42;
let tangent = cartesian52;
let bitangent = cartesian62;
let attrIndex = sixSize;
for (i = 0; i < threeSize; i += 3) {
const attrIndexOffset = attrIndex + sixSize;
topPosition = Cartesian3_default.fromArray(positions, i, topPosition);
bottomPosition = Cartesian3_default.fromArray(
positions,
i + threeSize,
bottomPosition
);
previousPosition = Cartesian3_default.fromArray(
positions,
(i + 3) % threeSize,
previousPosition
);
bottomPosition = Cartesian3_default.subtract(
bottomPosition,
topPosition,
bottomPosition
);
previousPosition = Cartesian3_default.subtract(
previousPosition,
topPosition,
previousPosition
);
normal2 = Cartesian3_default.normalize(
Cartesian3_default.cross(bottomPosition, previousPosition, normal2),
normal2
);
if (vertexFormat.normal) {
CorridorGeometryLibrary_default.addAttribute(normals, normal2, attrIndexOffset);
CorridorGeometryLibrary_default.addAttribute(
normals,
normal2,
attrIndexOffset + 3
);
CorridorGeometryLibrary_default.addAttribute(normals, normal2, attrIndex);
CorridorGeometryLibrary_default.addAttribute(normals, normal2, attrIndex + 3);
}
if (vertexFormat.tangent || vertexFormat.bitangent) {
bitangent = Cartesian3_default.fromArray(topNormals, i, bitangent);
if (vertexFormat.bitangent) {
CorridorGeometryLibrary_default.addAttribute(
bitangents,
bitangent,
attrIndexOffset
);
CorridorGeometryLibrary_default.addAttribute(
bitangents,
bitangent,
attrIndexOffset + 3
);
CorridorGeometryLibrary_default.addAttribute(
bitangents,
bitangent,
attrIndex
);
CorridorGeometryLibrary_default.addAttribute(
bitangents,
bitangent,
attrIndex + 3
);
}
if (vertexFormat.tangent) {
tangent = Cartesian3_default.normalize(
Cartesian3_default.cross(bitangent, normal2, tangent),
tangent
);
CorridorGeometryLibrary_default.addAttribute(
tangents,
tangent,
attrIndexOffset
);
CorridorGeometryLibrary_default.addAttribute(
tangents,
tangent,
attrIndexOffset + 3
);
CorridorGeometryLibrary_default.addAttribute(tangents, tangent, attrIndex);
CorridorGeometryLibrary_default.addAttribute(
tangents,
tangent,
attrIndex + 3
);
}
}
attrIndex += 6;
}
if (vertexFormat.normal) {
normals.set(topNormals);
for (i = 0; i < threeSize; i += 3) {
normals[i + threeSize] = -topNormals[i];
normals[i + threeSize + 1] = -topNormals[i + 1];
normals[i + threeSize + 2] = -topNormals[i + 2];
}
attributes.normal.values = normals;
} else {
attributes.normal = void 0;
}
if (vertexFormat.bitangent) {
bitangents.set(topBitangents);
bitangents.set(topBitangents, threeSize);
attributes.bitangent.values = bitangents;
} else {
attributes.bitangent = void 0;
}
if (vertexFormat.tangent) {
const topTangents = attributes.tangent.values;
tangents.set(topTangents);
tangents.set(topTangents, threeSize);
attributes.tangent.values = tangents;
}
}
if (vertexFormat.st) {
const topSt = attributes.st.values;
const st = new Float32Array(twoSize * 6);
st.set(topSt);
st.set(topSt, twoSize);
let index = twoSize * 2;
for (let j = 0; j < 2; j++) {
st[index++] = topSt[0];
st[index++] = topSt[1];
for (i = 2; i < twoSize; i += 2) {
const s = topSt[i];
const t = topSt[i + 1];
st[index++] = s;
st[index++] = t;
st[index++] = s;
st[index++] = t;
}
st[index++] = topSt[0];
st[index++] = topSt[1];
}
attributes.st.values = st;
}
return attributes;
}
function addWallPositions(positions, index, wallPositions) {
wallPositions[index++] = positions[0];
wallPositions[index++] = positions[1];
wallPositions[index++] = positions[2];
for (let i = 3; i < positions.length; i += 3) {
const x = positions[i];
const y = positions[i + 1];
const z = positions[i + 2];
wallPositions[index++] = x;
wallPositions[index++] = y;
wallPositions[index++] = z;
wallPositions[index++] = x;
wallPositions[index++] = y;
wallPositions[index++] = z;
}
wallPositions[index++] = positions[0];
wallPositions[index++] = positions[1];
wallPositions[index++] = positions[2];
return wallPositions;
}
function computePositionsExtruded(params, vertexFormat) {
const topVertexFormat = new VertexFormat_default({
position: vertexFormat.position,
normal: vertexFormat.normal || vertexFormat.bitangent || params.shadowVolume,
tangent: vertexFormat.tangent,
bitangent: vertexFormat.normal || vertexFormat.bitangent,
st: vertexFormat.st
});
const ellipsoid = params.ellipsoid;
const computedPositions = CorridorGeometryLibrary_default.computePositions(params);
const attr = combine2(computedPositions, topVertexFormat, ellipsoid);
const height = params.height;
const extrudedHeight = params.extrudedHeight;
let attributes = attr.attributes;
const indices = attr.indices;
let positions = attributes.position.values;
let length2 = positions.length;
const newPositions = new Float64Array(length2 * 6);
let extrudedPositions = new Float64Array(length2);
extrudedPositions.set(positions);
let wallPositions = new Float64Array(length2 * 4);
positions = PolygonPipeline_default.scaleToGeodeticHeight(
positions,
height,
ellipsoid
);
wallPositions = addWallPositions(positions, 0, wallPositions);
extrudedPositions = PolygonPipeline_default.scaleToGeodeticHeight(
extrudedPositions,
extrudedHeight,
ellipsoid
);
wallPositions = addWallPositions(
extrudedPositions,
length2 * 2,
wallPositions
);
newPositions.set(positions);
newPositions.set(extrudedPositions, length2);
newPositions.set(wallPositions, length2 * 2);
attributes.position.values = newPositions;
attributes = extrudedAttributes(attributes, vertexFormat);
let i;
const size = length2 / 3;
if (params.shadowVolume) {
const topNormals = attributes.normal.values;
length2 = topNormals.length;
let extrudeNormals = new Float32Array(length2 * 6);
for (i = 0; i < length2; i++) {
topNormals[i] = -topNormals[i];
}
extrudeNormals.set(topNormals, length2);
extrudeNormals = addWallPositions(topNormals, length2 * 4, extrudeNormals);
attributes.extrudeDirection = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: extrudeNormals
});
if (!vertexFormat.normal) {
attributes.normal = void 0;
}
}
if (defined_default(params.offsetAttribute)) {
let applyOffset = new Uint8Array(size * 6);
if (params.offsetAttribute === GeometryOffsetAttribute_default.TOP) {
applyOffset = applyOffset.fill(1, 0, size).fill(1, size * 2, size * 4);
} else {
const applyOffsetValue = params.offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
applyOffset = applyOffset.fill(applyOffsetValue);
}
attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
const iLength = indices.length;
const twoSize = size + size;
const newIndices = IndexDatatype_default.createTypedArray(
newPositions.length / 3,
iLength * 2 + twoSize * 3
);
newIndices.set(indices);
let index = iLength;
for (i = 0; i < iLength; i += 3) {
const v02 = indices[i];
const v12 = indices[i + 1];
const v22 = indices[i + 2];
newIndices[index++] = v22 + size;
newIndices[index++] = v12 + size;
newIndices[index++] = v02 + size;
}
let UL, LL, UR, LR;
for (i = 0; i < twoSize; i += 2) {
UL = i + twoSize;
LL = UL + twoSize;
UR = UL + 1;
LR = LL + 1;
newIndices[index++] = UL;
newIndices[index++] = LL;
newIndices[index++] = UR;
newIndices[index++] = UR;
newIndices[index++] = LL;
newIndices[index++] = LR;
}
return {
attributes,
indices: newIndices
};
}
var scratchCartesian17 = new Cartesian3_default();
var scratchCartesian26 = new Cartesian3_default();
var scratchCartographic10 = new Cartographic_default();
function computeOffsetPoints(position1, position2, ellipsoid, halfWidth, min3, max3) {
const direction2 = Cartesian3_default.subtract(
position2,
position1,
scratchCartesian17
);
Cartesian3_default.normalize(direction2, direction2);
const normal2 = ellipsoid.geodeticSurfaceNormal(position1, scratchCartesian26);
const offsetDirection = Cartesian3_default.cross(
direction2,
normal2,
scratchCartesian17
);
Cartesian3_default.multiplyByScalar(offsetDirection, halfWidth, offsetDirection);
let minLat = min3.latitude;
let minLon = min3.longitude;
let maxLat = max3.latitude;
let maxLon = max3.longitude;
Cartesian3_default.add(position1, offsetDirection, scratchCartesian26);
ellipsoid.cartesianToCartographic(scratchCartesian26, scratchCartographic10);
let lat = scratchCartographic10.latitude;
let lon = scratchCartographic10.longitude;
minLat = Math.min(minLat, lat);
minLon = Math.min(minLon, lon);
maxLat = Math.max(maxLat, lat);
maxLon = Math.max(maxLon, lon);
Cartesian3_default.subtract(position1, offsetDirection, scratchCartesian26);
ellipsoid.cartesianToCartographic(scratchCartesian26, scratchCartographic10);
lat = scratchCartographic10.latitude;
lon = scratchCartographic10.longitude;
minLat = Math.min(minLat, lat);
minLon = Math.min(minLon, lon);
maxLat = Math.max(maxLat, lat);
maxLon = Math.max(maxLon, lon);
min3.latitude = minLat;
min3.longitude = minLon;
max3.latitude = maxLat;
max3.longitude = maxLon;
}
var scratchCartesianOffset = new Cartesian3_default();
var scratchCartesianEnds = new Cartesian3_default();
var scratchCartographicMin = new Cartographic_default();
var scratchCartographicMax = new Cartographic_default();
function computeRectangle(positions, ellipsoid, width, cornerType, result) {
positions = scaleToSurface2(positions, ellipsoid);
const cleanPositions = arrayRemoveDuplicates_default(
positions,
Cartesian3_default.equalsEpsilon
);
const length2 = cleanPositions.length;
if (length2 < 2 || width <= 0) {
return new Rectangle_default();
}
const halfWidth = width * 0.5;
scratchCartographicMin.latitude = Number.POSITIVE_INFINITY;
scratchCartographicMin.longitude = Number.POSITIVE_INFINITY;
scratchCartographicMax.latitude = Number.NEGATIVE_INFINITY;
scratchCartographicMax.longitude = Number.NEGATIVE_INFINITY;
let lat, lon;
if (cornerType === CornerType_default.ROUNDED) {
const first = cleanPositions[0];
Cartesian3_default.subtract(first, cleanPositions[1], scratchCartesianOffset);
Cartesian3_default.normalize(scratchCartesianOffset, scratchCartesianOffset);
Cartesian3_default.multiplyByScalar(
scratchCartesianOffset,
halfWidth,
scratchCartesianOffset
);
Cartesian3_default.add(first, scratchCartesianOffset, scratchCartesianEnds);
ellipsoid.cartesianToCartographic(
scratchCartesianEnds,
scratchCartographic10
);
lat = scratchCartographic10.latitude;
lon = scratchCartographic10.longitude;
scratchCartographicMin.latitude = Math.min(
scratchCartographicMin.latitude,
lat
);
scratchCartographicMin.longitude = Math.min(
scratchCartographicMin.longitude,
lon
);
scratchCartographicMax.latitude = Math.max(
scratchCartographicMax.latitude,
lat
);
scratchCartographicMax.longitude = Math.max(
scratchCartographicMax.longitude,
lon
);
}
for (let i = 0; i < length2 - 1; ++i) {
computeOffsetPoints(
cleanPositions[i],
cleanPositions[i + 1],
ellipsoid,
halfWidth,
scratchCartographicMin,
scratchCartographicMax
);
}
const last = cleanPositions[length2 - 1];
Cartesian3_default.subtract(last, cleanPositions[length2 - 2], scratchCartesianOffset);
Cartesian3_default.normalize(scratchCartesianOffset, scratchCartesianOffset);
Cartesian3_default.multiplyByScalar(
scratchCartesianOffset,
halfWidth,
scratchCartesianOffset
);
Cartesian3_default.add(last, scratchCartesianOffset, scratchCartesianEnds);
computeOffsetPoints(
last,
scratchCartesianEnds,
ellipsoid,
halfWidth,
scratchCartographicMin,
scratchCartographicMax
);
if (cornerType === CornerType_default.ROUNDED) {
ellipsoid.cartesianToCartographic(
scratchCartesianEnds,
scratchCartographic10
);
lat = scratchCartographic10.latitude;
lon = scratchCartographic10.longitude;
scratchCartographicMin.latitude = Math.min(
scratchCartographicMin.latitude,
lat
);
scratchCartographicMin.longitude = Math.min(
scratchCartographicMin.longitude,
lon
);
scratchCartographicMax.latitude = Math.max(
scratchCartographicMax.latitude,
lat
);
scratchCartographicMax.longitude = Math.max(
scratchCartographicMax.longitude,
lon
);
}
const rectangle = defined_default(result) ? result : new Rectangle_default();
rectangle.north = scratchCartographicMax.latitude;
rectangle.south = scratchCartographicMin.latitude;
rectangle.east = scratchCartographicMax.longitude;
rectangle.west = scratchCartographicMin.longitude;
return rectangle;
}
function CorridorGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const positions = options.positions;
const width = options.width;
Check_default.defined("options.positions", positions);
Check_default.defined("options.width", width);
const height = options.height ?? 0;
const extrudedHeight = options.extrudedHeight ?? height;
this._positions = positions;
this._ellipsoid = Ellipsoid_default.clone(options.ellipsoid ?? Ellipsoid_default.default);
this._vertexFormat = VertexFormat_default.clone(
options.vertexFormat ?? VertexFormat_default.DEFAULT
);
this._width = width;
this._height = Math.max(height, extrudedHeight);
this._extrudedHeight = Math.min(height, extrudedHeight);
this._cornerType = options.cornerType ?? CornerType_default.ROUNDED;
this._granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
this._shadowVolume = options.shadowVolume ?? false;
this._workerName = "createCorridorGeometry";
this._offsetAttribute = options.offsetAttribute;
this._rectangle = void 0;
this.packedLength = 1 + positions.length * Cartesian3_default.packedLength + Ellipsoid_default.packedLength + VertexFormat_default.packedLength + 7;
}
CorridorGeometry.pack = function(value, array, startingIndex) {
Check_default.defined("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const positions = value._positions;
const length2 = positions.length;
array[startingIndex++] = length2;
for (let i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
Cartesian3_default.pack(positions[i], array, startingIndex);
}
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
startingIndex += VertexFormat_default.packedLength;
array[startingIndex++] = value._width;
array[startingIndex++] = value._height;
array[startingIndex++] = value._extrudedHeight;
array[startingIndex++] = value._cornerType;
array[startingIndex++] = value._granularity;
array[startingIndex++] = value._shadowVolume ? 1 : 0;
array[startingIndex] = value._offsetAttribute ?? -1;
return array;
};
var scratchEllipsoid3 = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var scratchVertexFormat3 = new VertexFormat_default();
var scratchOptions7 = {
positions: void 0,
ellipsoid: scratchEllipsoid3,
vertexFormat: scratchVertexFormat3,
width: void 0,
height: void 0,
extrudedHeight: void 0,
cornerType: void 0,
granularity: void 0,
shadowVolume: void 0,
offsetAttribute: void 0
};
CorridorGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const length2 = array[startingIndex++];
const positions = new Array(length2);
for (let i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
positions[i] = Cartesian3_default.unpack(array, startingIndex);
}
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid3);
startingIndex += Ellipsoid_default.packedLength;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat3
);
startingIndex += VertexFormat_default.packedLength;
const width = array[startingIndex++];
const height = array[startingIndex++];
const extrudedHeight = array[startingIndex++];
const cornerType = array[startingIndex++];
const granularity = array[startingIndex++];
const shadowVolume = array[startingIndex++] === 1;
const offsetAttribute = array[startingIndex];
if (!defined_default(result)) {
scratchOptions7.positions = positions;
scratchOptions7.width = width;
scratchOptions7.height = height;
scratchOptions7.extrudedHeight = extrudedHeight;
scratchOptions7.cornerType = cornerType;
scratchOptions7.granularity = granularity;
scratchOptions7.shadowVolume = shadowVolume;
scratchOptions7.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new CorridorGeometry(scratchOptions7);
}
result._positions = positions;
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._width = width;
result._height = height;
result._extrudedHeight = extrudedHeight;
result._cornerType = cornerType;
result._granularity = granularity;
result._shadowVolume = shadowVolume;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
CorridorGeometry.computeRectangle = function(options, result) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const positions = options.positions;
const width = options.width;
Check_default.defined("options.positions", positions);
Check_default.defined("options.width", width);
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
const cornerType = options.cornerType ?? CornerType_default.ROUNDED;
return computeRectangle(positions, ellipsoid, width, cornerType, result);
};
CorridorGeometry.createGeometry = function(corridorGeometry) {
let positions = corridorGeometry._positions;
const width = corridorGeometry._width;
const ellipsoid = corridorGeometry._ellipsoid;
positions = scaleToSurface2(positions, ellipsoid);
const cleanPositions = arrayRemoveDuplicates_default(
positions,
Cartesian3_default.equalsEpsilon
);
if (cleanPositions.length < 2 || width <= 0) {
return;
}
const height = corridorGeometry._height;
const extrudedHeight = corridorGeometry._extrudedHeight;
const extrude = !Math_default.equalsEpsilon(
height,
extrudedHeight,
0,
Math_default.EPSILON2
);
const vertexFormat = corridorGeometry._vertexFormat;
const params = {
ellipsoid,
positions: cleanPositions,
width,
cornerType: corridorGeometry._cornerType,
granularity: corridorGeometry._granularity,
saveAttributes: true
};
let attr;
if (extrude) {
params.height = height;
params.extrudedHeight = extrudedHeight;
params.shadowVolume = corridorGeometry._shadowVolume;
params.offsetAttribute = corridorGeometry._offsetAttribute;
attr = computePositionsExtruded(params, vertexFormat);
} else {
const computedPositions = CorridorGeometryLibrary_default.computePositions(params);
attr = combine2(computedPositions, vertexFormat, ellipsoid);
attr.attributes.position.values = PolygonPipeline_default.scaleToGeodeticHeight(
attr.attributes.position.values,
height,
ellipsoid
);
if (defined_default(corridorGeometry._offsetAttribute)) {
const applyOffsetValue = corridorGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const length2 = attr.attributes.position.values.length;
const applyOffset = new Uint8Array(length2 / 3).fill(applyOffsetValue);
attr.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
}
const attributes = attr.attributes;
const boundingSphere = BoundingSphere_default.fromVertices(
attributes.position.values,
void 0,
3
);
if (!vertexFormat.position) {
attr.attributes.position.values = void 0;
}
return new Geometry_default({
attributes,
indices: attr.indices,
primitiveType: PrimitiveType_default.TRIANGLES,
boundingSphere,
offsetAttribute: corridorGeometry._offsetAttribute
});
};
CorridorGeometry.createShadowVolume = function(corridorGeometry, minHeightFunc, maxHeightFunc) {
const granularity = corridorGeometry._granularity;
const ellipsoid = corridorGeometry._ellipsoid;
const minHeight = minHeightFunc(granularity, ellipsoid);
const maxHeight = maxHeightFunc(granularity, ellipsoid);
return new CorridorGeometry({
positions: corridorGeometry._positions,
width: corridorGeometry._width,
cornerType: corridorGeometry._cornerType,
ellipsoid,
granularity,
extrudedHeight: minHeight,
height: maxHeight,
vertexFormat: VertexFormat_default.POSITION_ONLY,
shadowVolume: true
});
};
Object.defineProperties(CorridorGeometry.prototype, {
/**
* @private
*/
rectangle: {
get: function() {
if (!defined_default(this._rectangle)) {
this._rectangle = computeRectangle(
this._positions,
this._ellipsoid,
this._width,
this._cornerType
);
}
return this._rectangle;
}
},
/**
* For remapping texture coordinates when rendering CorridorGeometries as GroundPrimitives.
*
* Corridors don't support stRotation,
* so just return the corners of the original system.
* @private
*/
textureCoordinateRotationPoints: {
get: function() {
return [0, 0, 0, 1, 1, 0];
}
}
});
var CorridorGeometry_default = CorridorGeometry;
// packages/engine/Source/Core/CorridorOutlineGeometry.js
var import_InlineWorkers828 = __toESM(require_InlineWorkers(), 1);
var cartesian13 = new Cartesian3_default();
var cartesian23 = new Cartesian3_default();
var cartesian33 = new Cartesian3_default();
function scaleToSurface3(positions, ellipsoid) {
for (let i = 0; i < positions.length; i++) {
positions[i] = ellipsoid.scaleToGeodeticSurface(positions[i], positions[i]);
}
return positions;
}
function combine3(computedPositions, cornerType) {
const wallIndices = [];
const positions = computedPositions.positions;
const corners2 = computedPositions.corners;
const endPositions = computedPositions.endPositions;
const attributes = new GeometryAttributes_default();
let corner;
let leftCount = 0;
let rightCount = 0;
let i;
let indicesLength = 0;
let length2;
for (i = 0; i < positions.length; i += 2) {
length2 = positions[i].length - 3;
leftCount += length2;
indicesLength += length2 / 3 * 4;
rightCount += positions[i + 1].length - 3;
}
leftCount += 3;
rightCount += 3;
for (i = 0; i < corners2.length; i++) {
corner = corners2[i];
const leftSide = corners2[i].leftPositions;
if (defined_default(leftSide)) {
length2 = leftSide.length;
leftCount += length2;
indicesLength += length2 / 3 * 2;
} else {
length2 = corners2[i].rightPositions.length;
rightCount += length2;
indicesLength += length2 / 3 * 2;
}
}
const addEndPositions = defined_default(endPositions);
let endPositionLength;
if (addEndPositions) {
endPositionLength = endPositions[0].length - 3;
leftCount += endPositionLength;
rightCount += endPositionLength;
endPositionLength /= 3;
indicesLength += endPositionLength * 4;
}
const size = leftCount + rightCount;
const finalPositions = new Float64Array(size);
let front = 0;
let back = size - 1;
let UL, LL, UR, LR;
let rightPos, leftPos;
const halfLength = endPositionLength / 2;
const indices = IndexDatatype_default.createTypedArray(size / 3, indicesLength + 4);
let index = 0;
indices[index++] = front / 3;
indices[index++] = (back - 2) / 3;
if (addEndPositions) {
wallIndices.push(front / 3);
leftPos = cartesian13;
rightPos = cartesian23;
const firstEndPositions = endPositions[0];
for (i = 0; i < halfLength; i++) {
leftPos = Cartesian3_default.fromArray(
firstEndPositions,
(halfLength - 1 - i) * 3,
leftPos
);
rightPos = Cartesian3_default.fromArray(
firstEndPositions,
(halfLength + i) * 3,
rightPos
);
CorridorGeometryLibrary_default.addAttribute(finalPositions, rightPos, front);
CorridorGeometryLibrary_default.addAttribute(
finalPositions,
leftPos,
void 0,
back
);
LL = front / 3;
LR = LL + 1;
UL = (back - 2) / 3;
UR = UL - 1;
indices[index++] = UL;
indices[index++] = UR;
indices[index++] = LL;
indices[index++] = LR;
front += 3;
back -= 3;
}
}
let posIndex = 0;
let rightEdge = positions[posIndex++];
let leftEdge = positions[posIndex++];
finalPositions.set(rightEdge, front);
finalPositions.set(leftEdge, back - leftEdge.length + 1);
length2 = leftEdge.length - 3;
wallIndices.push(front / 3, (back - 2) / 3);
for (i = 0; i < length2; i += 3) {
LL = front / 3;
LR = LL + 1;
UL = (back - 2) / 3;
UR = UL - 1;
indices[index++] = UL;
indices[index++] = UR;
indices[index++] = LL;
indices[index++] = LR;
front += 3;
back -= 3;
}
for (i = 0; i < corners2.length; i++) {
let j;
corner = corners2[i];
const l = corner.leftPositions;
const r = corner.rightPositions;
let start;
let outsidePoint = cartesian33;
if (defined_default(l)) {
back -= 3;
start = UR;
wallIndices.push(LR);
for (j = 0; j < l.length / 3; j++) {
outsidePoint = Cartesian3_default.fromArray(l, j * 3, outsidePoint);
indices[index++] = start - j - 1;
indices[index++] = start - j;
CorridorGeometryLibrary_default.addAttribute(
finalPositions,
outsidePoint,
void 0,
back
);
back -= 3;
}
wallIndices.push(start - Math.floor(l.length / 6));
if (cornerType === CornerType_default.BEVELED) {
wallIndices.push((back - 2) / 3 + 1);
}
front += 3;
} else {
front += 3;
start = LR;
wallIndices.push(UR);
for (j = 0; j < r.length / 3; j++) {
outsidePoint = Cartesian3_default.fromArray(r, j * 3, outsidePoint);
indices[index++] = start + j;
indices[index++] = start + j + 1;
CorridorGeometryLibrary_default.addAttribute(
finalPositions,
outsidePoint,
front
);
front += 3;
}
wallIndices.push(start + Math.floor(r.length / 6));
if (cornerType === CornerType_default.BEVELED) {
wallIndices.push(front / 3 - 1);
}
back -= 3;
}
rightEdge = positions[posIndex++];
leftEdge = positions[posIndex++];
rightEdge.splice(0, 3);
leftEdge.splice(leftEdge.length - 3, 3);
finalPositions.set(rightEdge, front);
finalPositions.set(leftEdge, back - leftEdge.length + 1);
length2 = leftEdge.length - 3;
for (j = 0; j < leftEdge.length; j += 3) {
LR = front / 3;
LL = LR - 1;
UR = (back - 2) / 3;
UL = UR + 1;
indices[index++] = UL;
indices[index++] = UR;
indices[index++] = LL;
indices[index++] = LR;
front += 3;
back -= 3;
}
front -= 3;
back += 3;
wallIndices.push(front / 3, (back - 2) / 3);
}
if (addEndPositions) {
front += 3;
back -= 3;
leftPos = cartesian13;
rightPos = cartesian23;
const lastEndPositions = endPositions[1];
for (i = 0; i < halfLength; i++) {
leftPos = Cartesian3_default.fromArray(
lastEndPositions,
(endPositionLength - i - 1) * 3,
leftPos
);
rightPos = Cartesian3_default.fromArray(lastEndPositions, i * 3, rightPos);
CorridorGeometryLibrary_default.addAttribute(
finalPositions,
leftPos,
void 0,
back
);
CorridorGeometryLibrary_default.addAttribute(finalPositions, rightPos, front);
LR = front / 3;
LL = LR - 1;
UR = (back - 2) / 3;
UL = UR + 1;
indices[index++] = UL;
indices[index++] = UR;
indices[index++] = LL;
indices[index++] = LR;
front += 3;
back -= 3;
}
wallIndices.push(front / 3);
} else {
wallIndices.push(front / 3, (back - 2) / 3);
}
indices[index++] = front / 3;
indices[index++] = (back - 2) / 3;
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: finalPositions
});
return {
attributes,
indices,
wallIndices
};
}
function computePositionsExtruded2(params) {
const ellipsoid = params.ellipsoid;
const computedPositions = CorridorGeometryLibrary_default.computePositions(params);
const attr = combine3(computedPositions, params.cornerType);
const wallIndices = attr.wallIndices;
const height = params.height;
const extrudedHeight = params.extrudedHeight;
const attributes = attr.attributes;
const indices = attr.indices;
let positions = attributes.position.values;
let length2 = positions.length;
let extrudedPositions = new Float64Array(length2);
extrudedPositions.set(positions);
const newPositions = new Float64Array(length2 * 2);
positions = PolygonPipeline_default.scaleToGeodeticHeight(
positions,
height,
ellipsoid
);
extrudedPositions = PolygonPipeline_default.scaleToGeodeticHeight(
extrudedPositions,
extrudedHeight,
ellipsoid
);
newPositions.set(positions);
newPositions.set(extrudedPositions, length2);
attributes.position.values = newPositions;
length2 /= 3;
if (defined_default(params.offsetAttribute)) {
let applyOffset = new Uint8Array(length2 * 2);
if (params.offsetAttribute === GeometryOffsetAttribute_default.TOP) {
applyOffset = applyOffset.fill(1, 0, length2);
} else {
const applyOffsetValue = params.offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
applyOffset = applyOffset.fill(applyOffsetValue);
}
attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
let i;
const iLength = indices.length;
const newIndices = IndexDatatype_default.createTypedArray(
newPositions.length / 3,
(iLength + wallIndices.length) * 2
);
newIndices.set(indices);
let index = iLength;
for (i = 0; i < iLength; i += 2) {
const v02 = indices[i];
const v12 = indices[i + 1];
newIndices[index++] = v02 + length2;
newIndices[index++] = v12 + length2;
}
let UL, LL;
for (i = 0; i < wallIndices.length; i++) {
UL = wallIndices[i];
LL = UL + length2;
newIndices[index++] = UL;
newIndices[index++] = LL;
}
return {
attributes,
indices: newIndices
};
}
function CorridorOutlineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const positions = options.positions;
const width = options.width;
Check_default.typeOf.object("options.positions", positions);
Check_default.typeOf.number("options.width", width);
const height = options.height ?? 0;
const extrudedHeight = options.extrudedHeight ?? height;
this._positions = positions;
this._ellipsoid = Ellipsoid_default.clone(options.ellipsoid ?? Ellipsoid_default.default);
this._width = width;
this._height = Math.max(height, extrudedHeight);
this._extrudedHeight = Math.min(height, extrudedHeight);
this._cornerType = options.cornerType ?? CornerType_default.ROUNDED;
this._granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
this._offsetAttribute = options.offsetAttribute;
this._workerName = "createCorridorOutlineGeometry";
this.packedLength = 1 + positions.length * Cartesian3_default.packedLength + Ellipsoid_default.packedLength + 6;
}
CorridorOutlineGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.typeOf.object("array", array);
startingIndex = startingIndex ?? 0;
const positions = value._positions;
const length2 = positions.length;
array[startingIndex++] = length2;
for (let i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
Cartesian3_default.pack(positions[i], array, startingIndex);
}
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
array[startingIndex++] = value._width;
array[startingIndex++] = value._height;
array[startingIndex++] = value._extrudedHeight;
array[startingIndex++] = value._cornerType;
array[startingIndex++] = value._granularity;
array[startingIndex] = value._offsetAttribute ?? -1;
return array;
};
var scratchEllipsoid4 = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var scratchOptions8 = {
positions: void 0,
ellipsoid: scratchEllipsoid4,
width: void 0,
height: void 0,
extrudedHeight: void 0,
cornerType: void 0,
granularity: void 0,
offsetAttribute: void 0
};
CorridorOutlineGeometry.unpack = function(array, startingIndex, result) {
Check_default.typeOf.object("array", array);
startingIndex = startingIndex ?? 0;
const length2 = array[startingIndex++];
const positions = new Array(length2);
for (let i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
positions[i] = Cartesian3_default.unpack(array, startingIndex);
}
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid4);
startingIndex += Ellipsoid_default.packedLength;
const width = array[startingIndex++];
const height = array[startingIndex++];
const extrudedHeight = array[startingIndex++];
const cornerType = array[startingIndex++];
const granularity = array[startingIndex++];
const offsetAttribute = array[startingIndex];
if (!defined_default(result)) {
scratchOptions8.positions = positions;
scratchOptions8.width = width;
scratchOptions8.height = height;
scratchOptions8.extrudedHeight = extrudedHeight;
scratchOptions8.cornerType = cornerType;
scratchOptions8.granularity = granularity;
scratchOptions8.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new CorridorOutlineGeometry(scratchOptions8);
}
result._positions = positions;
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._width = width;
result._height = height;
result._extrudedHeight = extrudedHeight;
result._cornerType = cornerType;
result._granularity = granularity;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
CorridorOutlineGeometry.createGeometry = function(corridorOutlineGeometry) {
let positions = corridorOutlineGeometry._positions;
const width = corridorOutlineGeometry._width;
const ellipsoid = corridorOutlineGeometry._ellipsoid;
positions = scaleToSurface3(positions, ellipsoid);
const cleanPositions = arrayRemoveDuplicates_default(
positions,
Cartesian3_default.equalsEpsilon
);
if (cleanPositions.length < 2 || width <= 0) {
return;
}
const height = corridorOutlineGeometry._height;
const extrudedHeight = corridorOutlineGeometry._extrudedHeight;
const extrude = !Math_default.equalsEpsilon(
height,
extrudedHeight,
0,
Math_default.EPSILON2
);
const params = {
ellipsoid,
positions: cleanPositions,
width,
cornerType: corridorOutlineGeometry._cornerType,
granularity: corridorOutlineGeometry._granularity,
saveAttributes: false
};
let attr;
if (extrude) {
params.height = height;
params.extrudedHeight = extrudedHeight;
params.offsetAttribute = corridorOutlineGeometry._offsetAttribute;
attr = computePositionsExtruded2(params);
} else {
const computedPositions = CorridorGeometryLibrary_default.computePositions(params);
attr = combine3(computedPositions, params.cornerType);
attr.attributes.position.values = PolygonPipeline_default.scaleToGeodeticHeight(
attr.attributes.position.values,
height,
ellipsoid
);
if (defined_default(corridorOutlineGeometry._offsetAttribute)) {
const length2 = attr.attributes.position.values.length;
const offsetValue = corridorOutlineGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
attr.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
}
const attributes = attr.attributes;
const boundingSphere = BoundingSphere_default.fromVertices(
attributes.position.values,
void 0,
3
);
return new Geometry_default({
attributes,
indices: attr.indices,
primitiveType: PrimitiveType_default.LINES,
boundingSphere,
offsetAttribute: corridorOutlineGeometry._offsetAttribute
});
};
var CorridorOutlineGeometry_default = CorridorOutlineGeometry;
// packages/engine/Source/DataSources/GroundGeometryUpdater.js
var import_InlineWorkers829 = __toESM(require_InlineWorkers(), 1);
var defaultZIndex = new ConstantProperty_default(0);
function GroundGeometryUpdater(options) {
GeometryUpdater_default.call(this, options);
this._zIndex = 0;
this._terrainOffsetProperty = void 0;
}
if (defined_default(Object.create)) {
GroundGeometryUpdater.prototype = Object.create(GeometryUpdater_default.prototype);
GroundGeometryUpdater.prototype.constructor = GroundGeometryUpdater;
}
Object.defineProperties(GroundGeometryUpdater.prototype, {
/**
* Gets the zindex
* @type {number}
* @memberof GroundGeometryUpdater.prototype
* @readonly
*/
zIndex: {
get: function() {
return this._zIndex;
}
},
/**
* Gets the terrain offset property
* @type {TerrainOffsetProperty}
* @memberof GroundGeometryUpdater.prototype
* @readonly
* @private
*/
terrainOffsetProperty: {
get: function() {
return this._terrainOffsetProperty;
}
}
});
GroundGeometryUpdater.prototype._isOnTerrain = function(entity, geometry) {
return this._fillEnabled && !defined_default(geometry.height) && !defined_default(geometry.extrudedHeight) && GroundPrimitive_default.isSupported(this._scene);
};
GroundGeometryUpdater.prototype._getIsClosed = function(options) {
const height = options.height;
const extrudedHeight = options.extrudedHeight;
return height === 0 || defined_default(extrudedHeight) && extrudedHeight !== height;
};
GroundGeometryUpdater.prototype._computeCenter = DeveloperError_default.throwInstantiationError;
GroundGeometryUpdater.prototype._onEntityPropertyChanged = function(entity, propertyName, newValue, oldValue2) {
GeometryUpdater_default.prototype._onEntityPropertyChanged.call(
this,
entity,
propertyName,
newValue,
oldValue2
);
if (this._observedPropertyNames.indexOf(propertyName) === -1) {
return;
}
const geometry = this._entity[this._geometryPropertyName];
if (!defined_default(geometry)) {
return;
}
if (defined_default(geometry.zIndex) && (defined_default(geometry.height) || defined_default(geometry.extrudedHeight))) {
oneTimeWarning_default(oneTimeWarning_default.geometryZIndex);
}
this._zIndex = geometry.zIndex ?? defaultZIndex;
if (defined_default(this._terrainOffsetProperty)) {
this._terrainOffsetProperty.destroy();
this._terrainOffsetProperty = void 0;
}
const heightReferenceProperty = geometry.heightReference;
const extrudedHeightReferenceProperty = geometry.extrudedHeightReference;
if (defined_default(heightReferenceProperty) || defined_default(extrudedHeightReferenceProperty)) {
const centerPosition = new CallbackProperty_default(
this._computeCenter.bind(this),
!this._dynamic
);
this._terrainOffsetProperty = new TerrainOffsetProperty_default(
this._scene,
centerPosition,
heightReferenceProperty,
extrudedHeightReferenceProperty
);
}
};
GroundGeometryUpdater.prototype.destroy = function() {
if (defined_default(this._terrainOffsetProperty)) {
this._terrainOffsetProperty.destroy();
this._terrainOffsetProperty = void 0;
}
GeometryUpdater_default.prototype.destroy.call(this);
};
GroundGeometryUpdater.getGeometryHeight = function(height, heightReference) {
Check_default.defined("heightReference", heightReference);
if (!defined_default(height)) {
if (heightReference !== HeightReference_default.NONE) {
oneTimeWarning_default(oneTimeWarning_default.geometryHeightReference);
}
return;
}
if (!isHeightReferenceClamp(heightReference)) {
return height;
}
return 0;
};
GroundGeometryUpdater.getGeometryExtrudedHeight = function(extrudedHeight, extrudedHeightReference) {
Check_default.defined("extrudedHeightReference", extrudedHeightReference);
if (!defined_default(extrudedHeight)) {
if (extrudedHeightReference !== HeightReference_default.NONE) {
oneTimeWarning_default(oneTimeWarning_default.geometryExtrudedHeightReference);
}
return;
}
if (!isHeightReferenceClamp(extrudedHeightReference)) {
return extrudedHeight;
}
return GroundGeometryUpdater.CLAMP_TO_GROUND;
};
GroundGeometryUpdater.CLAMP_TO_GROUND = "clamp";
GroundGeometryUpdater.computeGeometryOffsetAttribute = function(height, heightReference, extrudedHeight, extrudedHeightReference) {
if (!defined_default(height) || !defined_default(heightReference)) {
heightReference = HeightReference_default.NONE;
}
if (!defined_default(extrudedHeight) || !defined_default(extrudedHeightReference)) {
extrudedHeightReference = HeightReference_default.NONE;
}
let n = 0;
if (heightReference !== HeightReference_default.NONE) {
n++;
}
if (extrudedHeightReference === HeightReference_default.RELATIVE_TO_GROUND) {
n++;
}
if (n === 2) {
return GeometryOffsetAttribute_default.ALL;
}
if (n === 1) {
return GeometryOffsetAttribute_default.TOP;
}
return void 0;
};
var GroundGeometryUpdater_default = GroundGeometryUpdater;
// packages/engine/Source/DataSources/CorridorGeometryUpdater.js
var scratchColor13 = new Color_default();
var defaultOffset2 = Cartesian3_default.ZERO;
var offsetScratch5 = new Cartesian3_default();
var scratchRectangle6 = new Rectangle_default();
function CorridorGeometryOptions(entity) {
this.id = entity;
this.vertexFormat = void 0;
this.positions = void 0;
this.width = void 0;
this.cornerType = void 0;
this.height = void 0;
this.extrudedHeight = void 0;
this.granularity = void 0;
this.offsetAttribute = void 0;
}
function CorridorGeometryUpdater(entity, scene) {
GroundGeometryUpdater_default.call(this, {
entity,
scene,
geometryOptions: new CorridorGeometryOptions(entity),
geometryPropertyName: "corridor",
observedPropertyNames: ["availability", "corridor"]
});
this._onEntityPropertyChanged(entity, "corridor", entity.corridor, void 0);
}
if (defined_default(Object.create)) {
CorridorGeometryUpdater.prototype = Object.create(
GroundGeometryUpdater_default.prototype
);
CorridorGeometryUpdater.prototype.constructor = CorridorGeometryUpdater;
}
CorridorGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._fillEnabled) {
throw new DeveloperError_default(
"This instance does not represent a filled geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const attributes = {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)
),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
this._distanceDisplayConditionProperty.getValue(time)
),
offset: void 0,
color: void 0
};
if (this._materialProperty instanceof ColorMaterialProperty_default) {
let currentColor;
if (defined_default(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
currentColor = this._materialProperty.color.getValue(time, scratchColor13);
}
if (!defined_default(currentColor)) {
currentColor = Color_default.WHITE;
}
attributes.color = ColorGeometryInstanceAttribute_default.fromColor(currentColor);
}
if (defined_default(this._options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset2,
offsetScratch5
)
);
}
return new GeometryInstance_default({
id: entity,
geometry: new CorridorGeometry_default(this._options),
attributes
});
};
CorridorGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._outlineEnabled) {
throw new DeveloperError_default(
"This instance does not represent an outlined geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const outlineColor = Property_default.getValueOrDefault(
this._outlineColorProperty,
time,
Color_default.BLACK,
scratchColor13
);
const attributes = {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)
),
color: ColorGeometryInstanceAttribute_default.fromColor(outlineColor),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
this._distanceDisplayConditionProperty.getValue(time)
),
offset: void 0
};
if (defined_default(this._options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset2,
offsetScratch5
)
);
}
return new GeometryInstance_default({
id: entity,
geometry: new CorridorOutlineGeometry_default(this._options),
attributes
});
};
CorridorGeometryUpdater.prototype._computeCenter = function(time, result) {
const positions = Property_default.getValueOrUndefined(
this._entity.corridor.positions,
time
);
if (!defined_default(positions) || positions.length === 0) {
return;
}
return Cartesian3_default.clone(
positions[Math.floor(positions.length / 2)],
result
);
};
CorridorGeometryUpdater.prototype._isHidden = function(entity, corridor) {
return !defined_default(corridor.positions) || !defined_default(corridor.width) || GeometryUpdater_default.prototype._isHidden.call(this, entity, corridor);
};
CorridorGeometryUpdater.prototype._isDynamic = function(entity, corridor) {
return !corridor.positions.isConstant || //
!Property_default.isConstant(corridor.height) || //
!Property_default.isConstant(corridor.extrudedHeight) || //
!Property_default.isConstant(corridor.granularity) || //
!Property_default.isConstant(corridor.width) || //
!Property_default.isConstant(corridor.outlineWidth) || //
!Property_default.isConstant(corridor.cornerType) || //
!Property_default.isConstant(corridor.zIndex) || //
this._onTerrain && !Property_default.isConstant(this._materialProperty) && !(this._materialProperty instanceof ColorMaterialProperty_default);
};
CorridorGeometryUpdater.prototype._setStaticOptions = function(entity, corridor) {
let heightValue = Property_default.getValueOrUndefined(
corridor.height,
Iso8601_default.MINIMUM_VALUE
);
const heightReferenceValue = Property_default.getValueOrDefault(
corridor.heightReference,
Iso8601_default.MINIMUM_VALUE,
HeightReference_default.NONE
);
let extrudedHeightValue = Property_default.getValueOrUndefined(
corridor.extrudedHeight,
Iso8601_default.MINIMUM_VALUE
);
const extrudedHeightReferenceValue = Property_default.getValueOrDefault(
corridor.extrudedHeightReference,
Iso8601_default.MINIMUM_VALUE,
HeightReference_default.NONE
);
if (defined_default(extrudedHeightValue) && !defined_default(heightValue)) {
heightValue = 0;
}
const options = this._options;
options.vertexFormat = this._materialProperty instanceof ColorMaterialProperty_default ? PerInstanceColorAppearance_default.VERTEX_FORMAT : MaterialAppearance_default.MaterialSupport.TEXTURED.vertexFormat;
options.positions = corridor.positions.getValue(
Iso8601_default.MINIMUM_VALUE,
options.positions
);
options.width = corridor.width.getValue(Iso8601_default.MINIMUM_VALUE);
options.granularity = Property_default.getValueOrUndefined(
corridor.granularity,
Iso8601_default.MINIMUM_VALUE
);
options.cornerType = Property_default.getValueOrUndefined(
corridor.cornerType,
Iso8601_default.MINIMUM_VALUE
);
options.offsetAttribute = GroundGeometryUpdater_default.computeGeometryOffsetAttribute(
heightValue,
heightReferenceValue,
extrudedHeightValue,
extrudedHeightReferenceValue
);
options.height = GroundGeometryUpdater_default.getGeometryHeight(
heightValue,
heightReferenceValue
);
extrudedHeightValue = GroundGeometryUpdater_default.getGeometryExtrudedHeight(
extrudedHeightValue,
extrudedHeightReferenceValue
);
if (extrudedHeightValue === GroundGeometryUpdater_default.CLAMP_TO_GROUND) {
extrudedHeightValue = ApproximateTerrainHeights_default.getMinimumMaximumHeights(
CorridorGeometry_default.computeRectangle(options, scratchRectangle6)
).minimumTerrainHeight;
}
options.extrudedHeight = extrudedHeightValue;
};
CorridorGeometryUpdater.DynamicGeometryUpdater = DynamicCorridorGeometryUpdater;
function DynamicCorridorGeometryUpdater(geometryUpdater, primitives, groundPrimitives) {
DynamicGeometryUpdater_default.call(
this,
geometryUpdater,
primitives,
groundPrimitives
);
}
if (defined_default(Object.create)) {
DynamicCorridorGeometryUpdater.prototype = Object.create(
DynamicGeometryUpdater_default.prototype
);
DynamicCorridorGeometryUpdater.prototype.constructor = DynamicCorridorGeometryUpdater;
}
DynamicCorridorGeometryUpdater.prototype._isHidden = function(entity, corridor, time) {
const options = this._options;
return !defined_default(options.positions) || !defined_default(options.width) || DynamicGeometryUpdater_default.prototype._isHidden.call(
this,
entity,
corridor,
time
);
};
DynamicCorridorGeometryUpdater.prototype._setOptions = function(entity, corridor, time) {
const options = this._options;
let heightValue = Property_default.getValueOrUndefined(corridor.height, time);
const heightReferenceValue = Property_default.getValueOrDefault(
corridor.heightReference,
time,
HeightReference_default.NONE
);
let extrudedHeightValue = Property_default.getValueOrUndefined(
corridor.extrudedHeight,
time
);
const extrudedHeightReferenceValue = Property_default.getValueOrDefault(
corridor.extrudedHeightReference,
time,
HeightReference_default.NONE
);
if (defined_default(extrudedHeightValue) && !defined_default(heightValue)) {
heightValue = 0;
}
options.positions = Property_default.getValueOrUndefined(corridor.positions, time);
options.width = Property_default.getValueOrUndefined(corridor.width, time);
options.granularity = Property_default.getValueOrUndefined(
corridor.granularity,
time
);
options.cornerType = Property_default.getValueOrUndefined(corridor.cornerType, time);
options.offsetAttribute = GroundGeometryUpdater_default.computeGeometryOffsetAttribute(
heightValue,
heightReferenceValue,
extrudedHeightValue,
extrudedHeightReferenceValue
);
options.height = GroundGeometryUpdater_default.getGeometryHeight(
heightValue,
heightReferenceValue
);
extrudedHeightValue = GroundGeometryUpdater_default.getGeometryExtrudedHeight(
extrudedHeightValue,
extrudedHeightReferenceValue
);
if (extrudedHeightValue === GroundGeometryUpdater_default.CLAMP_TO_GROUND) {
extrudedHeightValue = ApproximateTerrainHeights_default.getMinimumMaximumHeights(
CorridorGeometry_default.computeRectangle(options, scratchRectangle6)
).minimumTerrainHeight;
}
options.extrudedHeight = extrudedHeightValue;
};
var CorridorGeometryUpdater_default = CorridorGeometryUpdater;
// packages/engine/Source/DataSources/CustomDataSource.js
var import_InlineWorkers839 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/DataSource.js
var import_InlineWorkers831 = __toESM(require_InlineWorkers(), 1);
function DataSource() {
DeveloperError_default.throwInstantiationError();
}
Object.defineProperties(DataSource.prototype, {
/**
* Gets a human-readable name for this instance.
* @memberof DataSource.prototype
* @type {string}
*/
name: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the preferred clock settings for this data source.
* @memberof DataSource.prototype
* @type {DataSourceClock}
*/
clock: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the collection of {@link Entity} instances.
* @memberof DataSource.prototype
* @type {EntityCollection}
*/
entities: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets a value indicating if the data source is currently loading data.
* @memberof DataSource.prototype
* @type {boolean}
*/
isLoading: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets an event that will be raised when the underlying data changes.
* @memberof DataSource.prototype
* @type {Event}
*/
changedEvent: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets an event that will be raised if an error is encountered during processing.
* @memberof DataSource.prototype
* @type {Event}
*/
errorEvent: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets an event that will be raised when the value of isLoading changes.
* @memberof DataSource.prototype
* @type {Event}
*/
loadingEvent: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets whether or not this data source should be displayed.
* @memberof DataSource.prototype
* @type {boolean}
*/
show: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets or sets the clustering options for this data source. This object can be shared between multiple data sources.
*
* @memberof DataSource.prototype
* @type {EntityCluster}
*/
clustering: {
get: DeveloperError_default.throwInstantiationError
}
});
DataSource.prototype.update = function(time) {
DeveloperError_default.throwInstantiationError();
};
DataSource.setLoading = function(dataSource, isLoading) {
if (dataSource._isLoading !== isLoading) {
if (isLoading) {
dataSource._entityCollection.suspendEvents();
} else {
dataSource._entityCollection.resumeEvents();
}
dataSource._isLoading = isLoading;
dataSource._loading.raiseEvent(dataSource, isLoading);
}
};
var DataSource_default = DataSource;
// packages/engine/Source/DataSources/EntityCluster.js
var import_InlineWorkers838 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/EllipsoidalOccluder.js
var import_InlineWorkers832 = __toESM(require_InlineWorkers(), 1);
function EllipsoidalOccluder(ellipsoid, cameraPosition) {
Check_default.typeOf.object("ellipsoid", ellipsoid);
this._ellipsoid = ellipsoid;
this._cameraPosition = new Cartesian3_default();
this._cameraPositionInScaledSpace = new Cartesian3_default();
this._distanceToLimbInScaledSpaceSquared = 0;
if (defined_default(cameraPosition)) {
this.cameraPosition = cameraPosition;
}
}
Object.defineProperties(EllipsoidalOccluder.prototype, {
/**
* Gets the occluding ellipsoid.
* @memberof EllipsoidalOccluder.prototype
* @type {Ellipsoid}
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
},
/**
* Gets or sets the position of the camera.
* @memberof EllipsoidalOccluder.prototype
* @type {Cartesian3}
*/
cameraPosition: {
get: function() {
return this._cameraPosition;
},
set: function(cameraPosition) {
const ellipsoid = this._ellipsoid;
const cv = ellipsoid.transformPositionToScaledSpace(
cameraPosition,
this._cameraPositionInScaledSpace
);
const vhMagnitudeSquared = Cartesian3_default.magnitudeSquared(cv) - 1;
Cartesian3_default.clone(cameraPosition, this._cameraPosition);
this._cameraPositionInScaledSpace = cv;
this._distanceToLimbInScaledSpaceSquared = vhMagnitudeSquared;
}
}
});
var scratchCartesian18 = new Cartesian3_default();
EllipsoidalOccluder.prototype.isPointVisible = function(occludee) {
const ellipsoid = this._ellipsoid;
const occludeeScaledSpacePosition = ellipsoid.transformPositionToScaledSpace(
occludee,
scratchCartesian18
);
return isScaledSpacePointVisible(
occludeeScaledSpacePosition,
this._cameraPositionInScaledSpace,
this._distanceToLimbInScaledSpaceSquared
);
};
EllipsoidalOccluder.prototype.isScaledSpacePointVisible = function(occludeeScaledSpacePosition) {
return isScaledSpacePointVisible(
occludeeScaledSpacePosition,
this._cameraPositionInScaledSpace,
this._distanceToLimbInScaledSpaceSquared
);
};
var scratchCameraPositionInScaledSpaceShrunk = new Cartesian3_default();
EllipsoidalOccluder.prototype.isScaledSpacePointVisiblePossiblyUnderEllipsoid = function(occludeeScaledSpacePosition, minimumHeight) {
const ellipsoid = this._ellipsoid;
let vhMagnitudeSquared;
let cv;
if (defined_default(minimumHeight) && minimumHeight < 0 && ellipsoid.minimumRadius > -minimumHeight) {
cv = scratchCameraPositionInScaledSpaceShrunk;
cv.x = this._cameraPosition.x / (ellipsoid.radii.x + minimumHeight);
cv.y = this._cameraPosition.y / (ellipsoid.radii.y + minimumHeight);
cv.z = this._cameraPosition.z / (ellipsoid.radii.z + minimumHeight);
vhMagnitudeSquared = cv.x * cv.x + cv.y * cv.y + cv.z * cv.z - 1;
} else {
cv = this._cameraPositionInScaledSpace;
vhMagnitudeSquared = this._distanceToLimbInScaledSpaceSquared;
}
return isScaledSpacePointVisible(
occludeeScaledSpacePosition,
cv,
vhMagnitudeSquared
);
};
EllipsoidalOccluder.prototype.computeHorizonCullingPoint = function(directionToPoint, positions, result) {
return computeHorizonCullingPointFromPositions(
this._ellipsoid,
directionToPoint,
positions,
result
);
};
var scratchEllipsoidShrunk = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
EllipsoidalOccluder.prototype.computeHorizonCullingPointPossiblyUnderEllipsoid = function(directionToPoint, positions, minimumHeight, result) {
const possiblyShrunkEllipsoid = getPossiblyShrunkEllipsoid(
this._ellipsoid,
minimumHeight,
scratchEllipsoidShrunk
);
return computeHorizonCullingPointFromPositions(
possiblyShrunkEllipsoid,
directionToPoint,
positions,
result
);
};
EllipsoidalOccluder.prototype.computeHorizonCullingPointFromVertices = function(directionToPoint, vertices, stride, center, result) {
return computeHorizonCullingPointFromVertices(
this._ellipsoid,
directionToPoint,
vertices,
stride,
center,
result
);
};
EllipsoidalOccluder.prototype.computeHorizonCullingPointFromVerticesPossiblyUnderEllipsoid = function(directionToPoint, vertices, stride, center, minimumHeight, result) {
const possiblyShrunkEllipsoid = getPossiblyShrunkEllipsoid(
this._ellipsoid,
minimumHeight,
scratchEllipsoidShrunk
);
return computeHorizonCullingPointFromVertices(
possiblyShrunkEllipsoid,
directionToPoint,
vertices,
stride,
center,
result
);
};
var subsampleScratch = [];
EllipsoidalOccluder.prototype.computeHorizonCullingPointFromRectangle = function(rectangle, ellipsoid, result) {
Check_default.typeOf.object("rectangle", rectangle);
const positions = Rectangle_default.subsample(
rectangle,
ellipsoid,
0,
subsampleScratch
);
const bs = BoundingSphere_default.fromPoints(positions);
if (Cartesian3_default.magnitude(bs.center) < 0.1 * ellipsoid.minimumRadius) {
return void 0;
}
return this.computeHorizonCullingPoint(bs.center, positions, result);
};
var scratchEllipsoidShrunkRadii = new Cartesian3_default();
function getPossiblyShrunkEllipsoid(ellipsoid, minimumHeight, result) {
if (defined_default(minimumHeight) && minimumHeight < 0 && ellipsoid.minimumRadius > -minimumHeight) {
const ellipsoidShrunkRadii = Cartesian3_default.fromElements(
ellipsoid.radii.x + minimumHeight,
ellipsoid.radii.y + minimumHeight,
ellipsoid.radii.z + minimumHeight,
scratchEllipsoidShrunkRadii
);
ellipsoid = Ellipsoid_default.fromCartesian3(ellipsoidShrunkRadii, result);
}
return ellipsoid;
}
function computeHorizonCullingPointFromPositions(ellipsoid, directionToPoint, positions, result) {
Check_default.typeOf.object("directionToPoint", directionToPoint);
Check_default.defined("positions", positions);
if (!defined_default(result)) {
result = new Cartesian3_default();
}
const scaledSpaceDirectionToPoint = computeScaledSpaceDirectionToPoint(
ellipsoid,
directionToPoint
);
let resultMagnitude = 0;
for (let i = 0, len = positions.length; i < len; ++i) {
const position = positions[i];
const candidateMagnitude = computeMagnitude(
ellipsoid,
position,
scaledSpaceDirectionToPoint
);
if (candidateMagnitude < 0) {
return void 0;
}
resultMagnitude = Math.max(resultMagnitude, candidateMagnitude);
}
return magnitudeToPoint(scaledSpaceDirectionToPoint, resultMagnitude, result);
}
var positionScratch7 = new Cartesian3_default();
function computeHorizonCullingPointFromVertices(ellipsoid, directionToPoint, vertices, stride, center, result) {
Check_default.typeOf.object("directionToPoint", directionToPoint);
Check_default.defined("vertices", vertices);
Check_default.typeOf.number("stride", stride);
if (!defined_default(result)) {
result = new Cartesian3_default();
}
stride = stride ?? 3;
center = center ?? Cartesian3_default.ZERO;
const scaledSpaceDirectionToPoint = computeScaledSpaceDirectionToPoint(
ellipsoid,
directionToPoint
);
let resultMagnitude = 0;
for (let i = 0, len = vertices.length; i < len; i += stride) {
positionScratch7.x = vertices[i] + center.x;
positionScratch7.y = vertices[i + 1] + center.y;
positionScratch7.z = vertices[i + 2] + center.z;
const candidateMagnitude = computeMagnitude(
ellipsoid,
positionScratch7,
scaledSpaceDirectionToPoint
);
if (candidateMagnitude < 0) {
return void 0;
}
resultMagnitude = Math.max(resultMagnitude, candidateMagnitude);
}
return magnitudeToPoint(scaledSpaceDirectionToPoint, resultMagnitude, result);
}
function isScaledSpacePointVisible(occludeeScaledSpacePosition, cameraPositionInScaledSpace, distanceToLimbInScaledSpaceSquared) {
const cv = cameraPositionInScaledSpace;
const vhMagnitudeSquared = distanceToLimbInScaledSpaceSquared;
const vt = Cartesian3_default.subtract(
occludeeScaledSpacePosition,
cv,
scratchCartesian18
);
const vtDotVc = -Cartesian3_default.dot(vt, cv);
const isOccluded = vhMagnitudeSquared < 0 ? vtDotVc > 0 : vtDotVc > vhMagnitudeSquared && vtDotVc * vtDotVc / Cartesian3_default.magnitudeSquared(vt) > vhMagnitudeSquared;
return !isOccluded;
}
var scaledSpaceScratch = new Cartesian3_default();
var directionScratch = new Cartesian3_default();
function computeMagnitude(ellipsoid, position, scaledSpaceDirectionToPoint) {
const scaledSpacePosition = ellipsoid.transformPositionToScaledSpace(
position,
scaledSpaceScratch
);
let magnitudeSquared = Cartesian3_default.magnitudeSquared(scaledSpacePosition);
let magnitude = Math.sqrt(magnitudeSquared);
const direction2 = Cartesian3_default.divideByScalar(
scaledSpacePosition,
magnitude,
directionScratch
);
magnitudeSquared = Math.max(1, magnitudeSquared);
magnitude = Math.max(1, magnitude);
const cosAlpha = Cartesian3_default.dot(direction2, scaledSpaceDirectionToPoint);
const sinAlpha = Cartesian3_default.magnitude(
Cartesian3_default.cross(direction2, scaledSpaceDirectionToPoint, direction2)
);
const cosBeta = 1 / magnitude;
const sinBeta = Math.sqrt(magnitudeSquared - 1) * cosBeta;
return 1 / (cosAlpha * cosBeta - sinAlpha * sinBeta);
}
function magnitudeToPoint(scaledSpaceDirectionToPoint, resultMagnitude, result) {
if (resultMagnitude <= 0 || resultMagnitude === 1 / 0 || resultMagnitude !== resultMagnitude) {
return void 0;
}
return Cartesian3_default.multiplyByScalar(
scaledSpaceDirectionToPoint,
resultMagnitude,
result
);
}
var directionToPointScratch = new Cartesian3_default();
function computeScaledSpaceDirectionToPoint(ellipsoid, directionToPoint) {
if (Cartesian3_default.equals(directionToPoint, Cartesian3_default.ZERO)) {
return directionToPoint;
}
ellipsoid.transformPositionToScaledSpace(
directionToPoint,
directionToPointScratch
);
return Cartesian3_default.normalize(directionToPointScratch, directionToPointScratch);
}
var EllipsoidalOccluder_default = EllipsoidalOccluder;
// packages/engine/Source/Scene/PointPrimitive.js
var import_InlineWorkers833 = __toESM(require_InlineWorkers(), 1);
function PointPrimitive(options, pointPrimitiveCollection) {
options = options ?? Frozen_default.EMPTY_OBJECT;
if (defined_default(options.disableDepthTestDistance) && options.disableDepthTestDistance < 0) {
throw new DeveloperError_default(
"disableDepthTestDistance must be greater than or equal to 0.0."
);
}
let translucencyByDistance = options.translucencyByDistance;
let scaleByDistance = options.scaleByDistance;
let distanceDisplayCondition = options.distanceDisplayCondition;
if (defined_default(translucencyByDistance)) {
if (translucencyByDistance.far <= translucencyByDistance.near) {
throw new DeveloperError_default(
"translucencyByDistance.far must be greater than translucencyByDistance.near."
);
}
translucencyByDistance = NearFarScalar_default.clone(translucencyByDistance);
}
if (defined_default(scaleByDistance)) {
if (scaleByDistance.far <= scaleByDistance.near) {
throw new DeveloperError_default(
"scaleByDistance.far must be greater than scaleByDistance.near."
);
}
scaleByDistance = NearFarScalar_default.clone(scaleByDistance);
}
if (defined_default(distanceDisplayCondition)) {
if (distanceDisplayCondition.far <= distanceDisplayCondition.near) {
throw new DeveloperError_default(
"distanceDisplayCondition.far must be greater than distanceDisplayCondition.near."
);
}
distanceDisplayCondition = DistanceDisplayCondition_default.clone(
distanceDisplayCondition
);
}
this._show = options.show ?? true;
this._position = Cartesian3_default.clone(options.position ?? Cartesian3_default.ZERO);
this._actualPosition = Cartesian3_default.clone(this._position);
this._color = Color_default.clone(options.color ?? Color_default.WHITE);
this._outlineColor = Color_default.clone(options.outlineColor ?? Color_default.TRANSPARENT);
this._outlineWidth = options.outlineWidth ?? 0;
this._pixelSize = options.pixelSize ?? 10;
this._scaleByDistance = scaleByDistance;
this._translucencyByDistance = translucencyByDistance;
this._distanceDisplayCondition = distanceDisplayCondition;
this._disableDepthTestDistance = options.disableDepthTestDistance ?? 0;
this._id = options.id;
this._collection = options.collection ?? pointPrimitiveCollection;
this._clusterShow = true;
this._pickId = void 0;
this._pointPrimitiveCollection = pointPrimitiveCollection;
this._dirty = false;
this._index = -1;
this._splitDirection = options.splitDirection ?? SplitDirection_default.NONE;
}
var SHOW_INDEX5 = PointPrimitive.SHOW_INDEX = 0;
var POSITION_INDEX5 = PointPrimitive.POSITION_INDEX = 1;
var COLOR_INDEX3 = PointPrimitive.COLOR_INDEX = 2;
var OUTLINE_COLOR_INDEX = PointPrimitive.OUTLINE_COLOR_INDEX = 3;
var OUTLINE_WIDTH_INDEX = PointPrimitive.OUTLINE_WIDTH_INDEX = 4;
var PIXEL_SIZE_INDEX = PointPrimitive.PIXEL_SIZE_INDEX = 5;
var SCALE_BY_DISTANCE_INDEX3 = PointPrimitive.SCALE_BY_DISTANCE_INDEX = 6;
var TRANSLUCENCY_BY_DISTANCE_INDEX3 = PointPrimitive.TRANSLUCENCY_BY_DISTANCE_INDEX = 7;
var DISTANCE_DISPLAY_CONDITION_INDEX2 = PointPrimitive.DISTANCE_DISPLAY_CONDITION_INDEX = 8;
var DISABLE_DEPTH_DISTANCE_INDEX = PointPrimitive.DISABLE_DEPTH_DISTANCE_INDEX = 9;
var SPLIT_DIRECTION_INDEX3 = PointPrimitive.SPLIT_DIRECTION_INDEX = 10;
PointPrimitive.NUMBER_OF_PROPERTIES = 11;
function makeDirty3(pointPrimitive, propertyChanged) {
const pointPrimitiveCollection = pointPrimitive._pointPrimitiveCollection;
if (defined_default(pointPrimitiveCollection)) {
pointPrimitiveCollection._updatePointPrimitive(
pointPrimitive,
propertyChanged
);
pointPrimitive._dirty = true;
}
}
Object.defineProperties(PointPrimitive.prototype, {
/**
* Determines if this point will be shown. Use this to hide or show a point, instead
* of removing it and re-adding it to the collection.
* @memberof PointPrimitive.prototype
* @type {boolean}
*/
show: {
get: function() {
return this._show;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._show !== value) {
this._show = value;
makeDirty3(this, SHOW_INDEX5);
}
}
},
/**
* Gets or sets the Cartesian position of this point.
* @memberof PointPrimitive.prototype
* @type {Cartesian3}
*/
position: {
get: function() {
return this._position;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const position = this._position;
if (!Cartesian3_default.equals(position, value)) {
Cartesian3_default.clone(value, position);
Cartesian3_default.clone(value, this._actualPosition);
makeDirty3(this, POSITION_INDEX5);
}
}
},
/**
* Gets or sets near and far scaling properties of a point based on the point's distance from the camera.
* A point's scale will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the point's scale remains clamped to the nearest bound. This scale
* multiplies the pixelSize and outlineWidth to affect the total size of the point. If undefined,
* scaleByDistance will be disabled.
* @memberof PointPrimitive.prototype
* @type {NearFarScalar}
*
* @example
* // Example 1.
* // Set a pointPrimitive's scaleByDistance to scale to 15 when the
* // camera is 1500 meters from the pointPrimitive and disappear as
* // the camera distance approaches 8.0e6 meters.
* p.scaleByDistance = new Cesium.NearFarScalar(1.5e2, 15, 8.0e6, 0.0);
*
* @example
* // Example 2.
* // disable scaling by distance
* p.scaleByDistance = undefined;
*/
scaleByDistance: {
get: function() {
return this._scaleByDistance;
},
set: function(value) {
if (defined_default(value) && value.far <= value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
const scaleByDistance = this._scaleByDistance;
if (!NearFarScalar_default.equals(scaleByDistance, value)) {
this._scaleByDistance = NearFarScalar_default.clone(value, scaleByDistance);
makeDirty3(this, SCALE_BY_DISTANCE_INDEX3);
}
}
},
/**
* Gets or sets near and far translucency properties of a point based on the point's distance from the camera.
* A point's translucency will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the point's translucency remains clamped to the nearest bound. If undefined,
* translucencyByDistance will be disabled.
* @memberof PointPrimitive.prototype
* @type {NearFarScalar}
*
* @example
* // Example 1.
* // Set a point's translucency to 1.0 when the
* // camera is 1500 meters from the point and disappear as
* // the camera distance approaches 8.0e6 meters.
* p.translucencyByDistance = new Cesium.NearFarScalar(1.5e2, 1.0, 8.0e6, 0.0);
*
* @example
* // Example 2.
* // disable translucency by distance
* p.translucencyByDistance = undefined;
*/
translucencyByDistance: {
get: function() {
return this._translucencyByDistance;
},
set: function(value) {
if (defined_default(value) && value.far <= value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
const translucencyByDistance = this._translucencyByDistance;
if (!NearFarScalar_default.equals(translucencyByDistance, value)) {
this._translucencyByDistance = NearFarScalar_default.clone(
value,
translucencyByDistance
);
makeDirty3(this, TRANSLUCENCY_BY_DISTANCE_INDEX3);
}
}
},
/**
* Gets or sets the inner size of the point in pixels.
* @memberof PointPrimitive.prototype
* @type {number}
*/
pixelSize: {
get: function() {
return this._pixelSize;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._pixelSize !== value) {
this._pixelSize = value;
makeDirty3(this, PIXEL_SIZE_INDEX);
}
}
},
/**
* Gets or sets the inner color of the point.
* The red, green, blue, and alpha values are indicated by value's red, green,
* blue, and alpha properties as shown in Example 1. These components range from 0.0
* (no intensity) to 1.0 (full intensity).
* @memberof PointPrimitive.prototype
* @type {Color}
*
* @example
* // Example 1. Assign yellow.
* p.color = Cesium.Color.YELLOW;
*
* @example
* // Example 2. Make a pointPrimitive 50% translucent.
* p.color = new Cesium.Color(1.0, 1.0, 1.0, 0.5);
*/
color: {
get: function() {
return this._color;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const color = this._color;
if (!Color_default.equals(color, value)) {
Color_default.clone(value, color);
makeDirty3(this, COLOR_INDEX3);
}
}
},
/**
* Gets or sets the outline color of the point.
* @memberof PointPrimitive.prototype
* @type {Color}
*/
outlineColor: {
get: function() {
return this._outlineColor;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
const outlineColor = this._outlineColor;
if (!Color_default.equals(outlineColor, value)) {
Color_default.clone(value, outlineColor);
makeDirty3(this, OUTLINE_COLOR_INDEX);
}
}
},
/**
* Gets or sets the outline width in pixels. This width adds to pixelSize,
* increasing the total size of the point.
* @memberof PointPrimitive.prototype
* @type {number}
*/
outlineWidth: {
get: function() {
return this._outlineWidth;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
if (this._outlineWidth !== value) {
this._outlineWidth = value;
makeDirty3(this, OUTLINE_WIDTH_INDEX);
}
}
},
/**
* Gets or sets the condition specifying at what distance from the camera that this point will be displayed.
* @memberof PointPrimitive.prototype
* @type {DistanceDisplayCondition}
* @default undefined
*/
distanceDisplayCondition: {
get: function() {
return this._distanceDisplayCondition;
},
set: function(value) {
if (defined_default(value) && value.far <= value.near) {
throw new DeveloperError_default("far must be greater than near");
}
if (!DistanceDisplayCondition_default.equals(this._distanceDisplayCondition, value)) {
this._distanceDisplayCondition = DistanceDisplayCondition_default.clone(
value,
this._distanceDisplayCondition
);
makeDirty3(this, DISTANCE_DISPLAY_CONDITION_INDEX2);
}
}
},
/**
* Gets or sets the distance from the camera at which to disable the depth test to, for example, prevent clipping against terrain.
* When set to zero, the depth test is always applied. When set to Number.POSITIVE_INFINITY, the depth test is never applied.
* @memberof PointPrimitive.prototype
* @type {number}
* @default 0.0
*/
disableDepthTestDistance: {
get: function() {
return this._disableDepthTestDistance;
},
set: function(value) {
if (this._disableDepthTestDistance !== value) {
if (!defined_default(value) || value < 0) {
throw new DeveloperError_default(
"disableDepthTestDistance must be greater than or equal to 0.0."
);
}
this._disableDepthTestDistance = value;
makeDirty3(this, DISABLE_DEPTH_DISTANCE_INDEX);
}
}
},
/**
* Gets or sets the user-defined value returned when the point is picked.
* @memberof PointPrimitive.prototype
* @type {*}
*/
id: {
get: function() {
return this._id;
},
set: function(value) {
this._id = value;
if (defined_default(this._pickId)) {
this._pickId.object.id = value;
}
}
},
/**
* @private
*/
pickId: {
get: function() {
return this._pickId;
}
},
/**
* Determines whether or not this point will be shown or hidden because it was clustered.
* @memberof PointPrimitive.prototype
* @type {boolean}
* @private
*/
clusterShow: {
get: function() {
return this._clusterShow;
},
set: function(value) {
if (this._clusterShow !== value) {
this._clusterShow = value;
makeDirty3(this, SHOW_INDEX5);
}
}
},
/**
* The {@link SplitDirection} to apply to this point.
* @memberof PointPrimitive.prototype
* @type {SplitDirection}
* @default {@link SplitDirection.NONE}
*/
splitDirection: {
get: function() {
return this._splitDirection;
},
set: function(value) {
if (this._splitDirection !== value) {
this._splitDirection = value;
makeDirty3(this, SPLIT_DIRECTION_INDEX3);
}
}
}
});
PointPrimitive.prototype.getPickId = function(context) {
if (!defined_default(this._pickId)) {
this._pickId = context.createPickId({
primitive: this,
collection: this._collection,
id: this._id
});
}
return this._pickId;
};
PointPrimitive.prototype._getActualPosition = function() {
return this._actualPosition;
};
PointPrimitive.prototype._setActualPosition = function(value) {
Cartesian3_default.clone(value, this._actualPosition);
makeDirty3(this, POSITION_INDEX5);
};
var tempCartesian32 = new Cartesian4_default();
PointPrimitive._computeActualPosition = function(position, frameState, modelMatrix) {
if (frameState.mode === SceneMode_default.SCENE3D) {
return position;
}
Matrix4_default.multiplyByPoint(modelMatrix, position, tempCartesian32);
return SceneTransforms_default.computeActualEllipsoidPosition(
frameState,
tempCartesian32
);
};
var scratchCartesian44 = new Cartesian4_default();
PointPrimitive._computeScreenSpacePosition = function(modelMatrix, position, scene, result) {
const positionWorld = Matrix4_default.multiplyByVector(
modelMatrix,
Cartesian4_default.fromElements(
position.x,
position.y,
position.z,
1,
scratchCartesian44
),
scratchCartesian44
);
const positionWC2 = SceneTransforms_default.worldToWindowCoordinates(
scene,
positionWorld,
result
);
return positionWC2;
};
PointPrimitive.prototype.computeScreenSpacePosition = function(scene, result) {
const pointPrimitiveCollection = this._pointPrimitiveCollection;
if (!defined_default(result)) {
result = new Cartesian2_default();
}
if (!defined_default(pointPrimitiveCollection)) {
throw new DeveloperError_default("PointPrimitive must be in a collection.");
}
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required.");
}
const modelMatrix = pointPrimitiveCollection.modelMatrix;
const windowCoordinates = PointPrimitive._computeScreenSpacePosition(
modelMatrix,
this._actualPosition,
scene,
result
);
if (!defined_default(windowCoordinates)) {
return void 0;
}
windowCoordinates.y = scene.canvas.clientHeight - windowCoordinates.y;
return windowCoordinates;
};
PointPrimitive.getScreenSpaceBoundingBox = function(point, screenSpacePosition, result) {
const size = point.pixelSize;
const halfSize = size * 0.5;
const x = screenSpacePosition.x - halfSize;
const y = screenSpacePosition.y - halfSize;
const width = size;
const height = size;
if (!defined_default(result)) {
result = new BoundingRectangle_default();
}
result.x = x;
result.y = y;
result.width = width;
result.height = height;
return result;
};
PointPrimitive.prototype.equals = function(other) {
return this === other || defined_default(other) && this._id === other._id && Cartesian3_default.equals(this._position, other._position) && Color_default.equals(this._color, other._color) && this._pixelSize === other._pixelSize && this._outlineWidth === other._outlineWidth && this._show === other._show && Color_default.equals(this._outlineColor, other._outlineColor) && NearFarScalar_default.equals(this._scaleByDistance, other._scaleByDistance) && NearFarScalar_default.equals(
this._translucencyByDistance,
other._translucencyByDistance
) && DistanceDisplayCondition_default.equals(
this._distanceDisplayCondition,
other._distanceDisplayCondition
) && this._disableDepthTestDistance === other._disableDepthTestDistance && this._splitDirection === other._splitDirection;
};
PointPrimitive.prototype._destroy = function() {
this._pickId = this._pickId && this._pickId.destroy();
this._pointPrimitiveCollection = void 0;
};
var PointPrimitive_default = PointPrimitive;
// packages/engine/Source/Scene/PointPrimitiveCollection.js
var import_InlineWorkers836 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/PointPrimitiveCollectionFS.js
var import_InlineWorkers834 = __toESM(require_InlineWorkers(), 1);
var PointPrimitiveCollectionFS_default = "in vec4 v_color;\nin vec4 v_outlineColor;\nin float v_innerPercent;\nin float v_pixelDistance;\nin vec4 v_pickColor;\nin float v_splitDirection;\n\nvoid main()\n{\n if (v_splitDirection < 0.0 && gl_FragCoord.x > czm_splitPosition) discard;\n if (v_splitDirection > 0.0 && gl_FragCoord.x < czm_splitPosition) discard;\n\n // The distance in UV space from this fragment to the center of the point, at most 0.5.\n float distanceToCenter = length(gl_PointCoord - vec2(0.5));\n // The max distance stops one pixel shy of the edge to leave space for anti-aliasing.\n float maxDistance = max(0.0, 0.5 - v_pixelDistance);\n float wholeAlpha = 1.0 - smoothstep(maxDistance, 0.5, distanceToCenter);\n float innerAlpha = 1.0 - smoothstep(maxDistance * v_innerPercent, 0.5 * v_innerPercent, distanceToCenter);\n\n vec4 color = mix(v_outlineColor, v_color, innerAlpha);\n color.a *= wholeAlpha;\n\n// Fully transparent parts of the billboard are not pickable.\n#if !defined(OPAQUE) && !defined(TRANSLUCENT)\n if (color.a < 0.005) // matches 0/255 and 1/255\n {\n discard;\n }\n#else\n// The billboard is rendered twice. The opaque pass discards translucent fragments\n// and the translucent pass discards opaque fragments.\n#ifdef OPAQUE\n if (color.a < 0.995) // matches < 254/255\n {\n discard;\n }\n#else\n if (color.a >= 0.995) // matches 254/255 and 255/255\n {\n discard;\n }\n#endif\n#endif\n\n out_FragColor = czm_gammaCorrect(color);\n czm_writeLogDepth();\n}\n";
// packages/engine/Source/Shaders/PointPrimitiveCollectionVS.js
var import_InlineWorkers835 = __toESM(require_InlineWorkers(), 1);
var PointPrimitiveCollectionVS_default = `uniform float u_maxTotalPointSize;
in vec4 positionHighAndSize;
in vec4 positionLowAndOutline;
in vec4 compressedAttribute0; // color, outlineColor, pick color
in vec4 compressedAttribute1; // show, translucency by distance, some free space
in vec4 scaleByDistance; // near, nearScale, far, farScale
in vec4 distanceDisplayConditionAndDisableDepthAndSplitDirection; // near, far, disableDepthTestDistance, splitDirection
out vec4 v_color;
out vec4 v_outlineColor;
out float v_innerPercent;
out float v_pixelDistance;
out vec4 v_pickColor;
out float v_splitDirection;
const float SHIFT_LEFT8 = 256.0;
const float SHIFT_RIGHT8 = 1.0 / 256.0;
void main()
{
// Modifying this shader may also require modifications to PointPrimitive._computeScreenSpacePosition
// unpack attributes
vec3 positionHigh = positionHighAndSize.xyz;
vec3 positionLow = positionLowAndOutline.xyz;
float outlineWidthBothSides = 2.0 * positionLowAndOutline.w;
float totalSize = positionHighAndSize.w + outlineWidthBothSides;
float outlinePercent = outlineWidthBothSides / totalSize;
// Scale in response to browser-zoom.
totalSize *= czm_pixelRatio;
float temp = compressedAttribute1.x * SHIFT_RIGHT8;
float show = floor(temp);
#ifdef EYE_DISTANCE_TRANSLUCENCY
vec4 translucencyByDistance;
translucencyByDistance.x = compressedAttribute1.z;
translucencyByDistance.z = compressedAttribute1.w;
translucencyByDistance.y = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0;
temp = compressedAttribute1.y * SHIFT_RIGHT8;
translucencyByDistance.w = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0;
#endif
///////////////////////////////////////////////////////////////////////////
vec4 color;
vec4 outlineColor;
vec4 pickColor;
// compressedAttribute0.z => pickColor.rgb
temp = compressedAttribute0.z * SHIFT_RIGHT8;
pickColor.b = (temp - floor(temp)) * SHIFT_LEFT8;
temp = floor(temp) * SHIFT_RIGHT8;
pickColor.g = (temp - floor(temp)) * SHIFT_LEFT8;
pickColor.r = floor(temp);
// compressedAttribute0.x => color.rgb
temp = compressedAttribute0.x * SHIFT_RIGHT8;
color.b = (temp - floor(temp)) * SHIFT_LEFT8;
temp = floor(temp) * SHIFT_RIGHT8;
color.g = (temp - floor(temp)) * SHIFT_LEFT8;
color.r = floor(temp);
// compressedAttribute0.y => outlineColor.rgb
temp = compressedAttribute0.y * SHIFT_RIGHT8;
outlineColor.b = (temp - floor(temp)) * SHIFT_LEFT8;
temp = floor(temp) * SHIFT_RIGHT8;
outlineColor.g = (temp - floor(temp)) * SHIFT_LEFT8;
outlineColor.r = floor(temp);
// compressedAttribute0.w => color.a, outlineColor.a, pickColor.a
temp = compressedAttribute0.w * SHIFT_RIGHT8;
pickColor.a = (temp - floor(temp)) * SHIFT_LEFT8;
pickColor = pickColor / 255.0;
temp = floor(temp) * SHIFT_RIGHT8;
outlineColor.a = (temp - floor(temp)) * SHIFT_LEFT8;
outlineColor /= 255.0;
color.a = floor(temp);
color /= 255.0;
///////////////////////////////////////////////////////////////////////////
vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
vec4 positionEC = czm_modelViewRelativeToEye * p;
///////////////////////////////////////////////////////////////////////////
#if defined(EYE_DISTANCE_SCALING) || defined(EYE_DISTANCE_TRANSLUCENCY) || defined(DISTANCE_DISPLAY_CONDITION) || defined(DISABLE_DEPTH_DISTANCE)
float lengthSq;
if (czm_sceneMode == czm_sceneMode2D)
{
// 2D camera distance is a special case
// treat all billboards as flattened to the z=0.0 plane
lengthSq = czm_eyeHeight2D.y;
}
else
{
lengthSq = dot(positionEC.xyz, positionEC.xyz);
}
#endif
#ifdef EYE_DISTANCE_SCALING
totalSize *= czm_nearFarScalar(scaleByDistance, lengthSq);
#endif
if (totalSize > 0.0) {
// Add padding for anti-aliasing on both sides.
totalSize += 3.0;
}
// Clamp to max point size.
totalSize = min(totalSize, u_maxTotalPointSize);
// If size is too small, push vertex behind near plane for clipping.
// Note that context.minimumAliasedPointSize "will be at most 1.0".
if (totalSize < 1.0)
{
positionEC.xyz = vec3(0.0);
totalSize = 1.0;
}
float translucency = 1.0;
#ifdef EYE_DISTANCE_TRANSLUCENCY
translucency = czm_nearFarScalar(translucencyByDistance, lengthSq);
// push vertex behind near plane for clipping
if (translucency < 0.004)
{
positionEC.xyz = vec3(0.0);
}
#endif
#ifdef DISTANCE_DISPLAY_CONDITION
float nearSq = distanceDisplayConditionAndDisableDepthAndSplitDirection.x;
float farSq = distanceDisplayConditionAndDisableDepthAndSplitDirection.y;
if (lengthSq < nearSq || lengthSq > farSq) {
// push vertex behind camera to force it to be clipped
positionEC.xyz = vec3(0.0, 0.0, 1.0);
}
#endif
gl_Position = czm_projection * positionEC;
czm_vertexLogDepth();
#ifdef DISABLE_DEPTH_DISTANCE
float disableDepthTestDistance = distanceDisplayConditionAndDisableDepthAndSplitDirection.z;
if (disableDepthTestDistance == 0.0 && czm_minimumDisableDepthTestDistance != 0.0)
{
disableDepthTestDistance = czm_minimumDisableDepthTestDistance;
}
if (disableDepthTestDistance != 0.0)
{
// Don't try to "multiply both sides" by w. Greater/less-than comparisons won't work for negative values of w.
float zclip = gl_Position.z / gl_Position.w;
bool clipped = (zclip < -1.0 || zclip > 1.0);
if (!clipped && (disableDepthTestDistance < 0.0 || (lengthSq > 0.0 && lengthSq < disableDepthTestDistance)))
{
// Position z on the near plane.
gl_Position.z = -gl_Position.w;
#ifdef LOG_DEPTH
czm_vertexLogDepth(vec4(czm_currentFrustum.x));
#endif
}
}
#endif
v_color = color;
v_color.a *= translucency * show;
v_outlineColor = outlineColor;
v_outlineColor.a *= translucency * show;
v_innerPercent = 1.0 - outlinePercent;
v_pixelDistance = 2.0 / totalSize;
gl_PointSize = totalSize * show;
gl_Position *= show;
v_pickColor = pickColor;
v_splitDirection = distanceDisplayConditionAndDisableDepthAndSplitDirection.w;
}
`;
// packages/engine/Source/Scene/PointPrimitiveCollection.js
var SHOW_INDEX6 = PointPrimitive_default.SHOW_INDEX;
var POSITION_INDEX6 = PointPrimitive_default.POSITION_INDEX;
var COLOR_INDEX4 = PointPrimitive_default.COLOR_INDEX;
var OUTLINE_COLOR_INDEX2 = PointPrimitive_default.OUTLINE_COLOR_INDEX;
var OUTLINE_WIDTH_INDEX2 = PointPrimitive_default.OUTLINE_WIDTH_INDEX;
var PIXEL_SIZE_INDEX2 = PointPrimitive_default.PIXEL_SIZE_INDEX;
var SCALE_BY_DISTANCE_INDEX4 = PointPrimitive_default.SCALE_BY_DISTANCE_INDEX;
var TRANSLUCENCY_BY_DISTANCE_INDEX4 = PointPrimitive_default.TRANSLUCENCY_BY_DISTANCE_INDEX;
var DISTANCE_DISPLAY_CONDITION_INDEX3 = PointPrimitive_default.DISTANCE_DISPLAY_CONDITION_INDEX;
var DISABLE_DEPTH_DISTANCE_INDEX2 = PointPrimitive_default.DISABLE_DEPTH_DISTANCE_INDEX;
var SPLIT_DIRECTION_INDEX4 = PointPrimitive_default.SPLIT_DIRECTION_INDEX;
var NUMBER_OF_PROPERTIES4 = PointPrimitive_default.NUMBER_OF_PROPERTIES;
var attributeLocations5 = {
positionHighAndSize: 0,
positionLowAndOutline: 1,
compressedAttribute0: 2,
// color, outlineColor, pick color
compressedAttribute1: 3,
// show, translucency by distance, some free space
scaleByDistance: 4,
distanceDisplayConditionAndDisableDepthAndSplitDirection: 5
};
function PointPrimitiveCollection(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._sp = void 0;
this._spTranslucent = void 0;
this._rsOpaque = void 0;
this._rsTranslucent = void 0;
this._vaf = void 0;
this._pointPrimitives = [];
this._pointPrimitivesToUpdate = [];
this._pointPrimitivesToUpdateIndex = 0;
this._pointPrimitivesRemoved = false;
this._createVertexArray = false;
this._shaderScaleByDistance = false;
this._compiledShaderScaleByDistance = false;
this._shaderTranslucencyByDistance = false;
this._compiledShaderTranslucencyByDistance = false;
this._shaderDistanceDisplayCondition = false;
this._compiledShaderDistanceDisplayCondition = false;
this._shaderDisableDepthDistance = false;
this._compiledShaderDisableDepthDistance = false;
this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES4);
this._maxPixelSize = 1;
this._baseVolume = new BoundingSphere_default();
this._baseVolumeWC = new BoundingSphere_default();
this._baseVolume2D = new BoundingSphere_default();
this._boundingVolume = new BoundingSphere_default();
this._boundingVolumeDirty = false;
this._colorCommands = [];
this.show = options.show ?? true;
this.modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this._modelMatrix = Matrix4_default.clone(Matrix4_default.IDENTITY);
this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this.blendOption = options.blendOption ?? BlendOption_default.OPAQUE_AND_TRANSLUCENT;
this._blendOption = void 0;
this._mode = SceneMode_default.SCENE3D;
this._maxTotalPointSize = 1;
this._buffersUsage = [
BufferUsage_default.STATIC_DRAW,
// SHOW_INDEX
BufferUsage_default.STATIC_DRAW,
// POSITION_INDEX
BufferUsage_default.STATIC_DRAW,
// COLOR_INDEX
BufferUsage_default.STATIC_DRAW,
// OUTLINE_COLOR_INDEX
BufferUsage_default.STATIC_DRAW,
// OUTLINE_WIDTH_INDEX
BufferUsage_default.STATIC_DRAW,
// PIXEL_SIZE_INDEX
BufferUsage_default.STATIC_DRAW,
// SCALE_BY_DISTANCE_INDEX
BufferUsage_default.STATIC_DRAW,
// TRANSLUCENCY_BY_DISTANCE_INDEX
BufferUsage_default.STATIC_DRAW
// DISTANCE_DISPLAY_CONDITION_INDEX
];
const that = this;
this._uniforms = {
u_maxTotalPointSize: function() {
return that._maxTotalPointSize;
}
};
}
Object.defineProperties(PointPrimitiveCollection.prototype, {
/**
* Returns the number of points in this collection. This is commonly used with
* {@link PointPrimitiveCollection#get} to iterate over all the points
* in the collection.
* @memberof PointPrimitiveCollection.prototype
* @type {number}
*/
length: {
get: function() {
removePointPrimitives(this);
return this._pointPrimitives.length;
}
}
});
function destroyPointPrimitives(pointPrimitives) {
const length2 = pointPrimitives.length;
for (let i = 0; i < length2; ++i) {
if (pointPrimitives[i]) {
pointPrimitives[i]._destroy();
}
}
}
PointPrimitiveCollection.prototype.add = function(options) {
const p = new PointPrimitive_default(options, this);
p._index = this._pointPrimitives.length;
this._pointPrimitives.push(p);
this._createVertexArray = true;
return p;
};
PointPrimitiveCollection.prototype.remove = function(pointPrimitive) {
if (this.contains(pointPrimitive)) {
this._pointPrimitives[pointPrimitive._index] = null;
this._pointPrimitivesRemoved = true;
this._createVertexArray = true;
pointPrimitive._destroy();
return true;
}
return false;
};
PointPrimitiveCollection.prototype.removeAll = function() {
destroyPointPrimitives(this._pointPrimitives);
this._pointPrimitives = [];
this._pointPrimitivesToUpdate = [];
this._pointPrimitivesToUpdateIndex = 0;
this._pointPrimitivesRemoved = false;
this._createVertexArray = true;
};
function removePointPrimitives(pointPrimitiveCollection) {
if (pointPrimitiveCollection._pointPrimitivesRemoved) {
pointPrimitiveCollection._pointPrimitivesRemoved = false;
const newPointPrimitives = [];
const pointPrimitives = pointPrimitiveCollection._pointPrimitives;
const length2 = pointPrimitives.length;
for (let i = 0, j = 0; i < length2; ++i) {
const pointPrimitive = pointPrimitives[i];
if (pointPrimitive) {
pointPrimitive._index = j++;
newPointPrimitives.push(pointPrimitive);
}
}
pointPrimitiveCollection._pointPrimitives = newPointPrimitives;
}
}
PointPrimitiveCollection.prototype._updatePointPrimitive = function(pointPrimitive, propertyChanged) {
if (!pointPrimitive._dirty) {
this._pointPrimitivesToUpdate[this._pointPrimitivesToUpdateIndex++] = pointPrimitive;
}
++this._propertiesChanged[propertyChanged];
};
PointPrimitiveCollection.prototype.contains = function(pointPrimitive) {
return defined_default(pointPrimitive) && pointPrimitive._pointPrimitiveCollection === this;
};
PointPrimitiveCollection.prototype.get = function(index) {
if (!defined_default(index)) {
throw new DeveloperError_default("index is required.");
}
removePointPrimitives(this);
return this._pointPrimitives[index];
};
PointPrimitiveCollection.prototype.computeNewBuffersUsage = function() {
const buffersUsage = this._buffersUsage;
let usageChanged = false;
const properties = this._propertiesChanged;
for (let k = 0; k < NUMBER_OF_PROPERTIES4; ++k) {
const newUsage = properties[k] === 0 ? BufferUsage_default.STATIC_DRAW : BufferUsage_default.STREAM_DRAW;
usageChanged = usageChanged || buffersUsage[k] !== newUsage;
buffersUsage[k] = newUsage;
}
return usageChanged;
};
function createVAF2(context, numberOfPointPrimitives, buffersUsage) {
return new VertexArrayFacade_default(
context,
[
{
index: attributeLocations5.positionHighAndSize,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[POSITION_INDEX6]
},
{
index: attributeLocations5.positionLowAndShow,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[POSITION_INDEX6]
},
{
index: attributeLocations5.compressedAttribute0,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[COLOR_INDEX4]
},
{
index: attributeLocations5.compressedAttribute1,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[TRANSLUCENCY_BY_DISTANCE_INDEX4]
},
{
index: attributeLocations5.scaleByDistance,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[SCALE_BY_DISTANCE_INDEX4]
},
{
index: attributeLocations5.distanceDisplayConditionAndDisableDepthAndSplitDirection,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: buffersUsage[DISTANCE_DISPLAY_CONDITION_INDEX3]
}
],
numberOfPointPrimitives
);
}
var writePositionScratch2 = new EncodedCartesian3_default();
function writePositionSizeAndOutline(pointPrimitiveCollection, context, vafWriters, pointPrimitive) {
const i = pointPrimitive._index;
const position = pointPrimitive._getActualPosition();
if (pointPrimitiveCollection._mode === SceneMode_default.SCENE3D) {
BoundingSphere_default.expand(
pointPrimitiveCollection._baseVolume,
position,
pointPrimitiveCollection._baseVolume
);
pointPrimitiveCollection._boundingVolumeDirty = true;
}
EncodedCartesian3_default.fromCartesian(position, writePositionScratch2);
const pixelSize = pointPrimitive.pixelSize;
const outlineWidth = pointPrimitive.outlineWidth;
pointPrimitiveCollection._maxPixelSize = Math.max(
pointPrimitiveCollection._maxPixelSize,
pixelSize + outlineWidth
);
const positionHighWriter = vafWriters[attributeLocations5.positionHighAndSize];
const high = writePositionScratch2.high;
positionHighWriter(i, high.x, high.y, high.z, pixelSize);
const positionLowWriter = vafWriters[attributeLocations5.positionLowAndOutline];
const low = writePositionScratch2.low;
positionLowWriter(i, low.x, low.y, low.z, outlineWidth);
}
var LEFT_SHIFT162 = 65536;
var LEFT_SHIFT82 = 256;
function writeCompressedAttrib02(pointPrimitiveCollection, context, vafWriters, pointPrimitive) {
const i = pointPrimitive._index;
const color = pointPrimitive.color;
const pickColor = pointPrimitive.getPickId(context).color;
const outlineColor = pointPrimitive.outlineColor;
let red = Color_default.floatToByte(color.red);
let green = Color_default.floatToByte(color.green);
let blue = Color_default.floatToByte(color.blue);
const compressed0 = red * LEFT_SHIFT162 + green * LEFT_SHIFT82 + blue;
red = Color_default.floatToByte(outlineColor.red);
green = Color_default.floatToByte(outlineColor.green);
blue = Color_default.floatToByte(outlineColor.blue);
const compressed1 = red * LEFT_SHIFT162 + green * LEFT_SHIFT82 + blue;
red = Color_default.floatToByte(pickColor.red);
green = Color_default.floatToByte(pickColor.green);
blue = Color_default.floatToByte(pickColor.blue);
const compressed2 = red * LEFT_SHIFT162 + green * LEFT_SHIFT82 + blue;
const compressed3 = Color_default.floatToByte(color.alpha) * LEFT_SHIFT162 + Color_default.floatToByte(outlineColor.alpha) * LEFT_SHIFT82 + Color_default.floatToByte(pickColor.alpha);
const writer = vafWriters[attributeLocations5.compressedAttribute0];
writer(i, compressed0, compressed1, compressed2, compressed3);
}
function writeCompressedAttrib12(pointPrimitiveCollection, context, vafWriters, pointPrimitive) {
const i = pointPrimitive._index;
let near = 0;
let nearValue = 1;
let far = 1;
let farValue = 1;
const translucency = pointPrimitive.translucencyByDistance;
if (defined_default(translucency)) {
near = translucency.near;
nearValue = translucency.nearValue;
far = translucency.far;
farValue = translucency.farValue;
if (nearValue !== 1 || farValue !== 1) {
pointPrimitiveCollection._shaderTranslucencyByDistance = true;
}
}
let show = pointPrimitive.show && pointPrimitive.clusterShow;
if (pointPrimitive.color.alpha === 0 && pointPrimitive.outlineColor.alpha === 0) {
show = false;
}
nearValue = Math_default.clamp(nearValue, 0, 1);
nearValue = nearValue === 1 ? 255 : nearValue * 255 | 0;
const compressed0 = (show ? 1 : 0) * LEFT_SHIFT82 + nearValue;
farValue = Math_default.clamp(farValue, 0, 1);
farValue = farValue === 1 ? 255 : farValue * 255 | 0;
const compressed1 = farValue;
const writer = vafWriters[attributeLocations5.compressedAttribute1];
writer(i, compressed0, compressed1, near, far);
}
function writeScaleByDistance2(pointPrimitiveCollection, context, vafWriters, pointPrimitive) {
const i = pointPrimitive._index;
const writer = vafWriters[attributeLocations5.scaleByDistance];
let near = 0;
let nearValue = 1;
let far = 1;
let farValue = 1;
const scale = pointPrimitive.scaleByDistance;
if (defined_default(scale)) {
near = scale.near;
nearValue = scale.nearValue;
far = scale.far;
farValue = scale.farValue;
if (nearValue !== 1 || farValue !== 1) {
pointPrimitiveCollection._shaderScaleByDistance = true;
}
}
writer(i, near, nearValue, far, farValue);
}
function writeDistanceDisplayConditionAndDepthDisableAndSplitDirection(pointPrimitiveCollection, context, vafWriters, pointPrimitive) {
const i = pointPrimitive._index;
const writer = vafWriters[attributeLocations5.distanceDisplayConditionAndDisableDepthAndSplitDirection];
let near = 0;
let far = Number.MAX_VALUE;
const distanceDisplayCondition = pointPrimitive.distanceDisplayCondition;
if (defined_default(distanceDisplayCondition)) {
near = distanceDisplayCondition.near;
far = distanceDisplayCondition.far;
near *= near;
far *= far;
pointPrimitiveCollection._shaderDistanceDisplayCondition = true;
}
let disableDepthTestDistance = pointPrimitive.disableDepthTestDistance;
disableDepthTestDistance *= disableDepthTestDistance;
if (disableDepthTestDistance > 0) {
pointPrimitiveCollection._shaderDisableDepthDistance = true;
if (disableDepthTestDistance === Number.POSITIVE_INFINITY) {
disableDepthTestDistance = -1;
}
}
let direction2 = 0;
const split = pointPrimitive.splitDirection;
if (defined_default(split)) {
direction2 = split;
}
writer(i, near, far, disableDepthTestDistance, direction2);
}
function writePointPrimitive(pointPrimitiveCollection, context, vafWriters, pointPrimitive) {
writePositionSizeAndOutline(
pointPrimitiveCollection,
context,
vafWriters,
pointPrimitive
);
writeCompressedAttrib02(
pointPrimitiveCollection,
context,
vafWriters,
pointPrimitive
);
writeCompressedAttrib12(
pointPrimitiveCollection,
context,
vafWriters,
pointPrimitive
);
writeScaleByDistance2(
pointPrimitiveCollection,
context,
vafWriters,
pointPrimitive
);
writeDistanceDisplayConditionAndDepthDisableAndSplitDirection(
pointPrimitiveCollection,
context,
vafWriters,
pointPrimitive
);
}
function recomputeActualPositions2(pointPrimitiveCollection, pointPrimitives, length2, frameState, modelMatrix, recomputeBoundingVolume) {
let boundingVolume;
if (frameState.mode === SceneMode_default.SCENE3D) {
boundingVolume = pointPrimitiveCollection._baseVolume;
pointPrimitiveCollection._boundingVolumeDirty = true;
} else {
boundingVolume = pointPrimitiveCollection._baseVolume2D;
}
const positions = [];
for (let i = 0; i < length2; ++i) {
const pointPrimitive = pointPrimitives[i];
const position = pointPrimitive.position;
const actualPosition = PointPrimitive_default._computeActualPosition(
position,
frameState,
modelMatrix
);
if (defined_default(actualPosition)) {
pointPrimitive._setActualPosition(actualPosition);
if (recomputeBoundingVolume) {
positions.push(actualPosition);
} else {
BoundingSphere_default.expand(boundingVolume, actualPosition, boundingVolume);
}
}
}
if (recomputeBoundingVolume) {
BoundingSphere_default.fromPoints(positions, boundingVolume);
}
}
function updateMode3(pointPrimitiveCollection, frameState) {
const mode2 = frameState.mode;
const pointPrimitives = pointPrimitiveCollection._pointPrimitives;
const pointPrimitivesToUpdate = pointPrimitiveCollection._pointPrimitivesToUpdate;
const modelMatrix = pointPrimitiveCollection._modelMatrix;
if (pointPrimitiveCollection._createVertexArray || pointPrimitiveCollection._mode !== mode2 || mode2 !== SceneMode_default.SCENE3D && !Matrix4_default.equals(modelMatrix, pointPrimitiveCollection.modelMatrix)) {
pointPrimitiveCollection._mode = mode2;
Matrix4_default.clone(pointPrimitiveCollection.modelMatrix, modelMatrix);
pointPrimitiveCollection._createVertexArray = true;
if (mode2 === SceneMode_default.SCENE3D || mode2 === SceneMode_default.SCENE2D || mode2 === SceneMode_default.COLUMBUS_VIEW) {
recomputeActualPositions2(
pointPrimitiveCollection,
pointPrimitives,
pointPrimitives.length,
frameState,
modelMatrix,
true
);
}
} else if (mode2 === SceneMode_default.MORPHING) {
recomputeActualPositions2(
pointPrimitiveCollection,
pointPrimitives,
pointPrimitives.length,
frameState,
modelMatrix,
true
);
} else if (mode2 === SceneMode_default.SCENE2D || mode2 === SceneMode_default.COLUMBUS_VIEW) {
recomputeActualPositions2(
pointPrimitiveCollection,
pointPrimitivesToUpdate,
pointPrimitiveCollection._pointPrimitivesToUpdateIndex,
frameState,
modelMatrix,
false
);
}
}
function updateBoundingVolume2(collection, frameState, boundingVolume) {
const pixelSize = frameState.camera.getPixelSize(
boundingVolume,
frameState.context.drawingBufferWidth,
frameState.context.drawingBufferHeight
);
const size = pixelSize * collection._maxPixelSize;
boundingVolume.radius += size;
}
var scratchWriterArray2 = [];
PointPrimitiveCollection.prototype.update = function(frameState) {
removePointPrimitives(this);
if (!this.show) {
return;
}
this._maxTotalPointSize = ContextLimits_default.maximumAliasedPointSize;
updateMode3(this, frameState);
const pointPrimitives = this._pointPrimitives;
const pointPrimitivesLength = pointPrimitives.length;
const pointPrimitivesToUpdate = this._pointPrimitivesToUpdate;
const pointPrimitivesToUpdateLength = this._pointPrimitivesToUpdateIndex;
const properties = this._propertiesChanged;
const createVertexArray6 = this._createVertexArray;
let vafWriters;
const context = frameState.context;
const pass = frameState.passes;
const picking = pass.pick;
if (createVertexArray6 || !picking && this.computeNewBuffersUsage()) {
this._createVertexArray = false;
for (let k = 0; k < NUMBER_OF_PROPERTIES4; ++k) {
properties[k] = 0;
}
this._vaf = this._vaf && this._vaf.destroy();
if (pointPrimitivesLength > 0) {
this._vaf = createVAF2(context, pointPrimitivesLength, this._buffersUsage);
vafWriters = this._vaf.writers;
for (let i = 0; i < pointPrimitivesLength; ++i) {
const pointPrimitive = this._pointPrimitives[i];
pointPrimitive._dirty = false;
writePointPrimitive(this, context, vafWriters, pointPrimitive);
}
this._vaf.commit();
}
this._pointPrimitivesToUpdateIndex = 0;
} else if (pointPrimitivesToUpdateLength > 0) {
const writers = scratchWriterArray2;
writers.length = 0;
if (properties[POSITION_INDEX6] || properties[OUTLINE_WIDTH_INDEX2] || properties[PIXEL_SIZE_INDEX2]) {
writers.push(writePositionSizeAndOutline);
}
if (properties[COLOR_INDEX4] || properties[OUTLINE_COLOR_INDEX2]) {
writers.push(writeCompressedAttrib02);
}
if (properties[SHOW_INDEX6] || properties[TRANSLUCENCY_BY_DISTANCE_INDEX4]) {
writers.push(writeCompressedAttrib12);
}
if (properties[SCALE_BY_DISTANCE_INDEX4]) {
writers.push(writeScaleByDistance2);
}
if (properties[DISTANCE_DISPLAY_CONDITION_INDEX3] || properties[DISABLE_DEPTH_DISTANCE_INDEX2] || properties[SPLIT_DIRECTION_INDEX4]) {
writers.push(
writeDistanceDisplayConditionAndDepthDisableAndSplitDirection
);
}
const numWriters = writers.length;
vafWriters = this._vaf.writers;
if (pointPrimitivesToUpdateLength / pointPrimitivesLength > 0.1) {
for (let m = 0; m < pointPrimitivesToUpdateLength; ++m) {
const b = pointPrimitivesToUpdate[m];
b._dirty = false;
for (let n = 0; n < numWriters; ++n) {
writers[n](this, context, vafWriters, b);
}
}
this._vaf.commit();
} else {
for (let h = 0; h < pointPrimitivesToUpdateLength; ++h) {
const bb = pointPrimitivesToUpdate[h];
bb._dirty = false;
for (let o = 0; o < numWriters; ++o) {
writers[o](this, context, vafWriters, bb);
}
this._vaf.subCommit(bb._index, 1);
}
this._vaf.endSubCommits();
}
this._pointPrimitivesToUpdateIndex = 0;
}
if (pointPrimitivesToUpdateLength > pointPrimitivesLength * 1.5) {
pointPrimitivesToUpdate.length = pointPrimitivesLength;
}
if (!defined_default(this._vaf) || !defined_default(this._vaf.va)) {
return;
}
if (this._boundingVolumeDirty) {
this._boundingVolumeDirty = false;
BoundingSphere_default.transform(
this._baseVolume,
this.modelMatrix,
this._baseVolumeWC
);
}
let boundingVolume;
let modelMatrix = Matrix4_default.IDENTITY;
if (frameState.mode === SceneMode_default.SCENE3D) {
modelMatrix = this.modelMatrix;
boundingVolume = BoundingSphere_default.clone(
this._baseVolumeWC,
this._boundingVolume
);
} else {
boundingVolume = BoundingSphere_default.clone(
this._baseVolume2D,
this._boundingVolume
);
}
updateBoundingVolume2(this, frameState, boundingVolume);
const blendOptionChanged = this._blendOption !== this.blendOption;
this._blendOption = this.blendOption;
if (blendOptionChanged) {
if (this._blendOption === BlendOption_default.OPAQUE || this._blendOption === BlendOption_default.OPAQUE_AND_TRANSLUCENT) {
this._rsOpaque = RenderState_default.fromCache({
depthTest: {
enabled: true,
func: WebGLConstants_default.LEQUAL
},
depthMask: true
});
} else {
this._rsOpaque = void 0;
}
if (this._blendOption === BlendOption_default.TRANSLUCENT || this._blendOption === BlendOption_default.OPAQUE_AND_TRANSLUCENT) {
this._rsTranslucent = RenderState_default.fromCache({
depthTest: {
enabled: true,
func: WebGLConstants_default.LEQUAL
},
depthMask: false,
blending: BlendingState_default.ALPHA_BLEND
});
} else {
this._rsTranslucent = void 0;
}
}
this._shaderDisableDepthDistance = this._shaderDisableDepthDistance || frameState.minimumDisableDepthTestDistance !== 0;
let vs;
let fs;
if (blendOptionChanged || this._shaderScaleByDistance && !this._compiledShaderScaleByDistance || this._shaderTranslucencyByDistance && !this._compiledShaderTranslucencyByDistance || this._shaderDistanceDisplayCondition && !this._compiledShaderDistanceDisplayCondition || this._shaderDisableDepthDistance !== this._compiledShaderDisableDepthDistance) {
vs = new ShaderSource_default({
sources: [PointPrimitiveCollectionVS_default]
});
if (this._shaderScaleByDistance) {
vs.defines.push("EYE_DISTANCE_SCALING");
}
if (this._shaderTranslucencyByDistance) {
vs.defines.push("EYE_DISTANCE_TRANSLUCENCY");
}
if (this._shaderDistanceDisplayCondition) {
vs.defines.push("DISTANCE_DISPLAY_CONDITION");
}
if (this._shaderDisableDepthDistance) {
vs.defines.push("DISABLE_DEPTH_DISTANCE");
}
if (this._blendOption === BlendOption_default.OPAQUE_AND_TRANSLUCENT) {
fs = new ShaderSource_default({
defines: ["OPAQUE"],
sources: [PointPrimitiveCollectionFS_default]
});
this._sp = ShaderProgram_default.replaceCache({
context,
shaderProgram: this._sp,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations5
});
fs = new ShaderSource_default({
defines: ["TRANSLUCENT"],
sources: [PointPrimitiveCollectionFS_default]
});
this._spTranslucent = ShaderProgram_default.replaceCache({
context,
shaderProgram: this._spTranslucent,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations5
});
}
if (this._blendOption === BlendOption_default.OPAQUE) {
fs = new ShaderSource_default({
sources: [PointPrimitiveCollectionFS_default]
});
this._sp = ShaderProgram_default.replaceCache({
context,
shaderProgram: this._sp,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations5
});
}
if (this._blendOption === BlendOption_default.TRANSLUCENT) {
fs = new ShaderSource_default({
sources: [PointPrimitiveCollectionFS_default]
});
this._spTranslucent = ShaderProgram_default.replaceCache({
context,
shaderProgram: this._spTranslucent,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations5
});
}
this._compiledShaderScaleByDistance = this._shaderScaleByDistance;
this._compiledShaderTranslucencyByDistance = this._shaderTranslucencyByDistance;
this._compiledShaderDistanceDisplayCondition = this._shaderDistanceDisplayCondition;
this._compiledShaderDisableDepthDistance = this._shaderDisableDepthDistance;
}
let va;
let vaLength;
let command;
let j;
const commandList = frameState.commandList;
if (pass.render || picking) {
const colorList = this._colorCommands;
const opaque = this._blendOption === BlendOption_default.OPAQUE;
const opaqueAndTranslucent = this._blendOption === BlendOption_default.OPAQUE_AND_TRANSLUCENT;
va = this._vaf.va;
vaLength = va.length;
colorList.length = vaLength;
const totalLength = opaqueAndTranslucent ? vaLength * 2 : vaLength;
for (j = 0; j < totalLength; ++j) {
const opaqueCommand = opaque || opaqueAndTranslucent && j % 2 === 0;
command = colorList[j];
if (!defined_default(command)) {
command = colorList[j] = new DrawCommand_default();
}
command.primitiveType = PrimitiveType_default.POINTS;
command.pass = opaqueCommand || !opaqueAndTranslucent ? Pass_default.OPAQUE : Pass_default.TRANSLUCENT;
command.owner = this;
const index = opaqueAndTranslucent ? Math.floor(j / 2) : j;
command.boundingVolume = boundingVolume;
command.modelMatrix = modelMatrix;
command.shaderProgram = opaqueCommand ? this._sp : this._spTranslucent;
command.uniformMap = this._uniforms;
command.vertexArray = va[index].va;
command.renderState = opaqueCommand ? this._rsOpaque : this._rsTranslucent;
command.debugShowBoundingVolume = this.debugShowBoundingVolume;
command.pickId = "v_pickColor";
commandList.push(command);
}
}
};
PointPrimitiveCollection.prototype.isDestroyed = function() {
return false;
};
PointPrimitiveCollection.prototype.destroy = function() {
this._sp = this._sp && this._sp.destroy();
this._spTranslucent = this._spTranslucent && this._spTranslucent.destroy();
this._spPick = this._spPick && this._spPick.destroy();
this._vaf = this._vaf && this._vaf.destroy();
destroyPointPrimitives(this._pointPrimitives);
return destroyObject_default(this);
};
var PointPrimitiveCollection_default = PointPrimitiveCollection;
// node_modules/kdbush/index.js
var import_InlineWorkers837 = __toESM(require_InlineWorkers(), 1);
var ARRAY_TYPES = [
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array
];
var VERSION = 1;
var HEADER_SIZE = 8;
var KDBush = class _KDBush {
/**
* Creates an index from raw `ArrayBuffer` data.
* @param {ArrayBuffer} data
*/
static from(data) {
if (!(data instanceof ArrayBuffer)) {
throw new Error("Data must be an instance of ArrayBuffer.");
}
const [magic, versionAndType] = new Uint8Array(data, 0, 2);
if (magic !== 219) {
throw new Error("Data does not appear to be in a KDBush format.");
}
const version2 = versionAndType >> 4;
if (version2 !== VERSION) {
throw new Error(`Got v${version2} data when expected v${VERSION}.`);
}
const ArrayType = ARRAY_TYPES[versionAndType & 15];
if (!ArrayType) {
throw new Error("Unrecognized array type.");
}
const [nodeSize] = new Uint16Array(data, 2, 1);
const [numItems] = new Uint32Array(data, 4, 1);
return new _KDBush(numItems, nodeSize, ArrayType, data);
}
/**
* Creates an index that will hold a given number of items.
* @param {number} numItems
* @param {number} [nodeSize=64] Size of the KD-tree node (64 by default).
* @param {TypedArrayConstructor} [ArrayType=Float64Array] The array type used for coordinates storage (`Float64Array` by default).
* @param {ArrayBuffer} [data] (For internal use only)
*/
constructor(numItems, nodeSize = 64, ArrayType = Float64Array, data) {
if (isNaN(numItems) || numItems < 0) throw new Error(`Unpexpected numItems value: ${numItems}.`);
this.numItems = +numItems;
this.nodeSize = Math.min(Math.max(+nodeSize, 2), 65535);
this.ArrayType = ArrayType;
this.IndexArrayType = numItems < 65536 ? Uint16Array : Uint32Array;
const arrayTypeIndex = ARRAY_TYPES.indexOf(this.ArrayType);
const coordsByteSize = numItems * 2 * this.ArrayType.BYTES_PER_ELEMENT;
const idsByteSize = numItems * this.IndexArrayType.BYTES_PER_ELEMENT;
const padCoords = (8 - idsByteSize % 8) % 8;
if (arrayTypeIndex < 0) {
throw new Error(`Unexpected typed array class: ${ArrayType}.`);
}
if (data && data instanceof ArrayBuffer) {
this.data = data;
this.ids = new this.IndexArrayType(this.data, HEADER_SIZE, numItems);
this.coords = new this.ArrayType(this.data, HEADER_SIZE + idsByteSize + padCoords, numItems * 2);
this._pos = numItems * 2;
this._finished = true;
} else {
this.data = new ArrayBuffer(HEADER_SIZE + coordsByteSize + idsByteSize + padCoords);
this.ids = new this.IndexArrayType(this.data, HEADER_SIZE, numItems);
this.coords = new this.ArrayType(this.data, HEADER_SIZE + idsByteSize + padCoords, numItems * 2);
this._pos = 0;
this._finished = false;
new Uint8Array(this.data, 0, 2).set([219, (VERSION << 4) + arrayTypeIndex]);
new Uint16Array(this.data, 2, 1)[0] = nodeSize;
new Uint32Array(this.data, 4, 1)[0] = numItems;
}
}
/**
* Add a point to the index.
* @param {number} x
* @param {number} y
* @returns {number} An incremental index associated with the added item (starting from `0`).
*/
add(x, y) {
const index = this._pos >> 1;
this.ids[index] = index;
this.coords[this._pos++] = x;
this.coords[this._pos++] = y;
return index;
}
/**
* Perform indexing of the added points.
*/
finish() {
const numAdded = this._pos >> 1;
if (numAdded !== this.numItems) {
throw new Error(`Added ${numAdded} items when expected ${this.numItems}.`);
}
sort(this.ids, this.coords, this.nodeSize, 0, this.numItems - 1, 0);
this._finished = true;
return this;
}
/**
* Search the index for items within a given bounding box.
* @param {number} minX
* @param {number} minY
* @param {number} maxX
* @param {number} maxY
* @returns {number[]} An array of indices correponding to the found items.
*/
range(minX, minY, maxX, maxY) {
if (!this._finished) throw new Error("Data not yet indexed - call index.finish().");
const { ids, coords, nodeSize } = this;
const stack = [0, ids.length - 1, 0];
const result = [];
while (stack.length) {
const axis = stack.pop() || 0;
const right = stack.pop() || 0;
const left = stack.pop() || 0;
if (right - left <= nodeSize) {
for (let i = left; i <= right; i++) {
const x2 = coords[2 * i];
const y2 = coords[2 * i + 1];
if (x2 >= minX && x2 <= maxX && y2 >= minY && y2 <= maxY) result.push(ids[i]);
}
continue;
}
const m = left + right >> 1;
const x = coords[2 * m];
const y = coords[2 * m + 1];
if (x >= minX && x <= maxX && y >= minY && y <= maxY) result.push(ids[m]);
if (axis === 0 ? minX <= x : minY <= y) {
stack.push(left);
stack.push(m - 1);
stack.push(1 - axis);
}
if (axis === 0 ? maxX >= x : maxY >= y) {
stack.push(m + 1);
stack.push(right);
stack.push(1 - axis);
}
}
return result;
}
/**
* Search the index for items within a given radius.
* @param {number} qx
* @param {number} qy
* @param {number} r Query radius.
* @returns {number[]} An array of indices correponding to the found items.
*/
within(qx, qy, r) {
if (!this._finished) throw new Error("Data not yet indexed - call index.finish().");
const { ids, coords, nodeSize } = this;
const stack = [0, ids.length - 1, 0];
const result = [];
const r2 = r * r;
while (stack.length) {
const axis = stack.pop() || 0;
const right = stack.pop() || 0;
const left = stack.pop() || 0;
if (right - left <= nodeSize) {
for (let i = left; i <= right; i++) {
if (sqDist(coords[2 * i], coords[2 * i + 1], qx, qy) <= r2) result.push(ids[i]);
}
continue;
}
const m = left + right >> 1;
const x = coords[2 * m];
const y = coords[2 * m + 1];
if (sqDist(x, y, qx, qy) <= r2) result.push(ids[m]);
if (axis === 0 ? qx - r <= x : qy - r <= y) {
stack.push(left);
stack.push(m - 1);
stack.push(1 - axis);
}
if (axis === 0 ? qx + r >= x : qy + r >= y) {
stack.push(m + 1);
stack.push(right);
stack.push(1 - axis);
}
}
return result;
}
};
function sort(ids, coords, nodeSize, left, right, axis) {
if (right - left <= nodeSize) return;
const m = left + right >> 1;
select(ids, coords, m, left, right, axis);
sort(ids, coords, nodeSize, left, m - 1, 1 - axis);
sort(ids, coords, nodeSize, m + 1, right, 1 - axis);
}
function select(ids, coords, k, left, right, axis) {
while (right > left) {
if (right - left > 600) {
const n = right - left + 1;
const m = k - left + 1;
const z = Math.log(n);
const s = 0.5 * Math.exp(2 * z / 3);
const sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
const newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
const newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
select(ids, coords, k, newLeft, newRight, axis);
}
const t = coords[2 * k + axis];
let i = left;
let j = right;
swapItem(ids, coords, left, k);
if (coords[2 * right + axis] > t) swapItem(ids, coords, left, right);
while (i < j) {
swapItem(ids, coords, i, j);
i++;
j--;
while (coords[2 * i + axis] < t) i++;
while (coords[2 * j + axis] > t) j--;
}
if (coords[2 * left + axis] === t) swapItem(ids, coords, left, j);
else {
j++;
swapItem(ids, coords, j, right);
}
if (j <= k) left = j + 1;
if (k <= j) right = j - 1;
}
}
function swapItem(ids, coords, i, j) {
swap2(ids, i, j);
swap2(coords, 2 * i, 2 * j);
swap2(coords, 2 * i + 1, 2 * j + 1);
}
function swap2(arr, i, j) {
const tmp2 = arr[i];
arr[i] = arr[j];
arr[j] = tmp2;
}
function sqDist(ax, ay, bx, by) {
const dx = ax - bx;
const dy = ay - by;
return dx * dx + dy * dy;
}
// packages/engine/Source/DataSources/EntityCluster.js
function EntityCluster(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._enabled = options.enabled ?? false;
this._pixelRange = options.pixelRange ?? 80;
this._minimumClusterSize = options.minimumClusterSize ?? 2;
this._clusterBillboards = options.clusterBillboards ?? true;
this._clusterLabels = options.clusterLabels ?? true;
this._clusterPoints = options.clusterPoints ?? true;
this._labelCollection = void 0;
this._billboardCollection = void 0;
this._pointCollection = void 0;
this._clusterBillboardCollection = void 0;
this._clusterLabelCollection = void 0;
this._clusterPointCollection = void 0;
this._collectionIndicesByEntity = {};
this._unusedLabelIndices = [];
this._unusedBillboardIndices = [];
this._unusedPointIndices = [];
this._previousClusters = [];
this._previousHeight = void 0;
this._enabledDirty = false;
this._clusterDirty = false;
this._cluster = void 0;
this._removeEventListener = void 0;
this._clusterEvent = new Event_default();
this.show = options.show ?? true;
}
function expandBoundingBox(bbox, pixelRange) {
bbox.x -= pixelRange;
bbox.y -= pixelRange;
bbox.width += pixelRange * 2;
bbox.height += pixelRange * 2;
}
var labelBoundingBoxScratch = new BoundingRectangle_default();
function getBoundingBox(item, coord, pixelRange, entityCluster, result) {
if (defined_default(item._labelCollection) && entityCluster._clusterLabels) {
result = Label_default.getScreenSpaceBoundingBox(item, coord, result);
} else if (defined_default(item._billboardCollection) && entityCluster._clusterBillboards) {
result = Billboard_default.getScreenSpaceBoundingBox(item, coord, result);
} else if (defined_default(item._pointPrimitiveCollection) && entityCluster._clusterPoints) {
result = PointPrimitive_default.getScreenSpaceBoundingBox(item, coord, result);
}
expandBoundingBox(result, pixelRange);
if (entityCluster._clusterLabels && !defined_default(item._labelCollection) && defined_default(item.id) && hasLabelIndex(entityCluster, item.id.id) && defined_default(item.id._label)) {
const labelIndex = entityCluster._collectionIndicesByEntity[item.id.id].labelIndex;
const label = entityCluster._labelCollection.get(labelIndex);
const labelBBox = Label_default.getScreenSpaceBoundingBox(
label,
coord,
labelBoundingBoxScratch
);
expandBoundingBox(labelBBox, pixelRange);
result = BoundingRectangle_default.union(result, labelBBox, result);
}
return result;
}
function addNonClusteredItem(item, entityCluster) {
item.clusterShow = true;
if (!defined_default(item._labelCollection) && defined_default(item.id) && hasLabelIndex(entityCluster, item.id.id) && defined_default(item.id._label)) {
const labelIndex = entityCluster._collectionIndicesByEntity[item.id.id].labelIndex;
const label = entityCluster._labelCollection.get(labelIndex);
label.clusterShow = true;
}
}
function addCluster(position, numPoints, ids, entityCluster) {
const cluster = {
billboard: entityCluster._clusterBillboardCollection.add(),
label: entityCluster._clusterLabelCollection.add(),
point: entityCluster._clusterPointCollection.add()
};
cluster.billboard.show = false;
cluster.point.show = false;
cluster.label.show = true;
cluster.label.text = numPoints.toLocaleString();
cluster.label.id = ids;
cluster.billboard.position = cluster.label.position = cluster.point.position = position;
entityCluster._clusterEvent.raiseEvent(ids, cluster);
}
function hasLabelIndex(entityCluster, entityId) {
return defined_default(entityCluster) && defined_default(entityCluster._collectionIndicesByEntity[entityId]) && defined_default(entityCluster._collectionIndicesByEntity[entityId].labelIndex);
}
function getScreenSpacePositions(collection, points, scene, occluder, entityCluster) {
if (!defined_default(collection)) {
return;
}
const length2 = collection.length;
for (let i = 0; i < length2; ++i) {
const item = collection.get(i);
item.clusterShow = false;
if (!item.show || entityCluster._scene.mode === SceneMode_default.SCENE3D && !occluder.isPointVisible(item.position)) {
continue;
}
const canClusterLabels = entityCluster._clusterLabels && defined_default(item._labelCollection);
const canClusterBillboards = entityCluster._clusterBillboards && defined_default(item.id._billboard);
const canClusterPoints = entityCluster._clusterPoints && defined_default(item.id._point);
if (canClusterLabels && (canClusterPoints || canClusterBillboards)) {
continue;
}
const coord = item.computeScreenSpacePosition(scene);
if (!defined_default(coord)) {
continue;
}
points.push({
index: i,
collection,
clustered: false,
coord
});
}
}
var pointBoundinRectangleScratch = new BoundingRectangle_default();
var totalBoundingRectangleScratch = new BoundingRectangle_default();
var neighborBoundingRectangleScratch = new BoundingRectangle_default();
function createDeclutterCallback(entityCluster) {
return function(amount) {
if (defined_default(amount) && amount < 0.05 || !entityCluster.enabled) {
return;
}
const scene = entityCluster._scene;
const labelCollection = entityCluster._labelCollection;
const billboardCollection = entityCluster._billboardCollection;
const pointCollection = entityCluster._pointCollection;
if (!defined_default(labelCollection) && !defined_default(billboardCollection) && !defined_default(pointCollection) || !entityCluster._clusterBillboards && !entityCluster._clusterLabels && !entityCluster._clusterPoints) {
return;
}
let clusteredLabelCollection = entityCluster._clusterLabelCollection;
let clusteredBillboardCollection = entityCluster._clusterBillboardCollection;
let clusteredPointCollection = entityCluster._clusterPointCollection;
if (defined_default(clusteredLabelCollection)) {
clusteredLabelCollection.removeAll();
} else {
clusteredLabelCollection = entityCluster._clusterLabelCollection = new LabelCollection_default({
scene
});
}
if (defined_default(clusteredBillboardCollection)) {
clusteredBillboardCollection.removeAll();
} else {
clusteredBillboardCollection = entityCluster._clusterBillboardCollection = new BillboardCollection_default({
scene
});
}
if (defined_default(clusteredPointCollection)) {
clusteredPointCollection.removeAll();
} else {
clusteredPointCollection = entityCluster._clusterPointCollection = new PointPrimitiveCollection_default();
}
const pixelRange = entityCluster._pixelRange;
const minimumClusterSize = entityCluster._minimumClusterSize;
const clusters = entityCluster._previousClusters;
const newClusters = [];
const previousHeight = entityCluster._previousHeight;
const currentHeight = scene.camera.positionCartographic.height;
const ellipsoid = scene.ellipsoid;
const cameraPosition = scene.camera.positionWC;
const occluder = new EllipsoidalOccluder_default(ellipsoid, cameraPosition);
const points = [];
if (entityCluster._clusterLabels) {
getScreenSpacePositions(
labelCollection,
points,
scene,
occluder,
entityCluster
);
}
if (entityCluster._clusterBillboards) {
getScreenSpacePositions(
billboardCollection,
points,
scene,
occluder,
entityCluster
);
}
if (entityCluster._clusterPoints) {
getScreenSpacePositions(
pointCollection,
points,
scene,
occluder,
entityCluster
);
}
let i;
let j;
let length2;
let bbox;
let neighbors;
let neighborLength;
let neighborIndex;
let neighborPoint;
let ids;
let numPoints;
let collection;
let collectionIndex;
if (points.length > 0) {
const index = new KDBush(points.length, 64, Uint32Array);
for (let p = 0; p < points.length; ++p) {
index.add(points[p].coord.x, points[p].coord.y);
}
index.finish();
if (currentHeight < previousHeight) {
length2 = clusters.length;
for (i = 0; i < length2; ++i) {
const cluster = clusters[i];
if (!occluder.isPointVisible(cluster.position)) {
continue;
}
const coord = Billboard_default._computeScreenSpacePosition(
Matrix4_default.IDENTITY,
cluster.position,
Cartesian3_default.ZERO,
Cartesian2_default.ZERO,
scene
);
if (!defined_default(coord)) {
continue;
}
const factor2 = 1 - currentHeight / previousHeight;
let width = cluster.width = cluster.width * factor2;
let height = cluster.height = cluster.height * factor2;
width = Math.max(width, cluster.minimumWidth);
height = Math.max(height, cluster.minimumHeight);
const minX = coord.x - width * 0.5;
const minY = coord.y - height * 0.5;
const maxX = coord.x + width;
const maxY = coord.y + height;
neighbors = index.range(minX, minY, maxX, maxY);
neighborLength = neighbors.length;
numPoints = 0;
ids = [];
for (j = 0; j < neighborLength; ++j) {
neighborIndex = neighbors[j];
neighborPoint = points[neighborIndex];
if (!neighborPoint.clustered) {
++numPoints;
collection = neighborPoint.collection;
collectionIndex = neighborPoint.index;
ids.push(collection.get(collectionIndex).id);
}
}
if (numPoints >= minimumClusterSize) {
addCluster(cluster.position, numPoints, ids, entityCluster);
newClusters.push(cluster);
for (j = 0; j < neighborLength; ++j) {
points[neighbors[j]].clustered = true;
}
}
}
}
length2 = points.length;
for (i = 0; i < length2; ++i) {
const point = points[i];
if (point.clustered) {
continue;
}
point.clustered = true;
collection = point.collection;
collectionIndex = point.index;
const item = collection.get(collectionIndex);
bbox = getBoundingBox(
item,
point.coord,
pixelRange,
entityCluster,
pointBoundinRectangleScratch
);
const totalBBox = BoundingRectangle_default.clone(
bbox,
totalBoundingRectangleScratch
);
neighbors = index.range(
bbox.x,
bbox.y,
bbox.x + bbox.width,
bbox.y + bbox.height
);
neighborLength = neighbors.length;
const clusterPosition = Cartesian3_default.clone(item.position);
numPoints = 1;
ids = [item.id];
for (j = 0; j < neighborLength; ++j) {
neighborIndex = neighbors[j];
neighborPoint = points[neighborIndex];
if (!neighborPoint.clustered) {
const neighborItem = neighborPoint.collection.get(
neighborPoint.index
);
const neighborBBox = getBoundingBox(
neighborItem,
neighborPoint.coord,
pixelRange,
entityCluster,
neighborBoundingRectangleScratch
);
Cartesian3_default.add(
neighborItem.position,
clusterPosition,
clusterPosition
);
BoundingRectangle_default.union(totalBBox, neighborBBox, totalBBox);
++numPoints;
ids.push(neighborItem.id);
}
}
if (numPoints >= minimumClusterSize) {
const position = Cartesian3_default.multiplyByScalar(
clusterPosition,
1 / numPoints,
clusterPosition
);
addCluster(position, numPoints, ids, entityCluster);
newClusters.push({
position,
width: totalBBox.width,
height: totalBBox.height,
minimumWidth: bbox.width,
minimumHeight: bbox.height
});
for (j = 0; j < neighborLength; ++j) {
points[neighbors[j]].clustered = true;
}
} else {
addNonClusteredItem(item, entityCluster);
}
}
}
if (clusteredLabelCollection.length === 0) {
clusteredLabelCollection.destroy();
entityCluster._clusterLabelCollection = void 0;
}
if (clusteredBillboardCollection.length === 0) {
clusteredBillboardCollection.destroy();
entityCluster._clusterBillboardCollection = void 0;
}
if (clusteredPointCollection.length === 0) {
clusteredPointCollection.destroy();
entityCluster._clusterPointCollection = void 0;
}
entityCluster._previousClusters = newClusters;
entityCluster._previousHeight = currentHeight;
};
}
EntityCluster.prototype._initialize = function(scene) {
this._scene = scene;
const cluster = createDeclutterCallback(this);
this._cluster = cluster;
this._removeEventListener = scene.camera.changed.addEventListener(cluster);
};
Object.defineProperties(EntityCluster.prototype, {
/**
* Gets or sets whether clustering is enabled.
* @memberof EntityCluster.prototype
* @type {boolean}
*/
enabled: {
get: function() {
return this._enabled;
},
set: function(value) {
this._enabledDirty = value !== this._enabled;
this._enabled = value;
}
},
/**
* Gets or sets the pixel range to extend the screen space bounding box.
* @memberof EntityCluster.prototype
* @type {number}
*/
pixelRange: {
get: function() {
return this._pixelRange;
},
set: function(value) {
this._clusterDirty = this._clusterDirty || value !== this._pixelRange;
this._pixelRange = value;
}
},
/**
* Gets or sets the minimum number of screen space objects that can be clustered.
* @memberof EntityCluster.prototype
* @type {number}
*/
minimumClusterSize: {
get: function() {
return this._minimumClusterSize;
},
set: function(value) {
this._clusterDirty = this._clusterDirty || value !== this._minimumClusterSize;
this._minimumClusterSize = value;
}
},
/**
* Gets the event that will be raised when a new cluster will be displayed. The signature of the event listener is {@link EntityCluster.newClusterCallback}.
* @memberof EntityCluster.prototype
* @type {Event}
*/
clusterEvent: {
get: function() {
return this._clusterEvent;
}
},
/**
* Gets or sets whether clustering billboard entities is enabled.
* @memberof EntityCluster.prototype
* @type {boolean}
*/
clusterBillboards: {
get: function() {
return this._clusterBillboards;
},
set: function(value) {
this._clusterDirty = this._clusterDirty || value !== this._clusterBillboards;
this._clusterBillboards = value;
}
},
/**
* Gets or sets whether clustering labels entities is enabled.
* @memberof EntityCluster.prototype
* @type {boolean}
*/
clusterLabels: {
get: function() {
return this._clusterLabels;
},
set: function(value) {
this._clusterDirty = this._clusterDirty || value !== this._clusterLabels;
this._clusterLabels = value;
}
},
/**
* Gets or sets whether clustering point entities is enabled.
* @memberof EntityCluster.prototype
* @type {boolean}
*/
clusterPoints: {
get: function() {
return this._clusterPoints;
},
set: function(value) {
this._clusterDirty = this._clusterDirty || value !== this._clusterPoints;
this._clusterPoints = value;
}
},
/**
* Returns true when all clustered data has been rendered.
* @memberof EntityCluster.prototype
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
return !this._enabledDirty && !this._clusterDirty && (!defined_default(this._billboardCollection) || this._billboardCollection.ready) && (!defined_default(this._labelCollection) || this._labelCollection.ready);
}
}
});
function createGetEntity(collectionProperty, CollectionConstructor, unusedIndicesProperty, entityIndexProperty) {
return function(entity) {
let collection = this[collectionProperty];
if (!defined_default(this._collectionIndicesByEntity)) {
this._collectionIndicesByEntity = {};
}
let entityIndices = this._collectionIndicesByEntity[entity.id];
if (!defined_default(entityIndices)) {
entityIndices = this._collectionIndicesByEntity[entity.id] = {
billboardIndex: void 0,
labelIndex: void 0,
pointIndex: void 0
};
}
if (defined_default(collection) && defined_default(entityIndices[entityIndexProperty])) {
return collection.get(entityIndices[entityIndexProperty]);
}
if (!defined_default(collection)) {
collection = this[collectionProperty] = new CollectionConstructor({
scene: this._scene
});
}
let index;
let entityItem;
const unusedIndices = this[unusedIndicesProperty];
if (unusedIndices.length > 0) {
index = unusedIndices.shift();
entityItem = collection.get(index);
} else {
entityItem = collection.add();
index = collection.length - 1;
}
entityIndices[entityIndexProperty] = index;
const that = this;
Promise.resolve().then(function() {
that._clusterDirty = true;
});
return entityItem;
};
}
function removeEntityIndicesIfUnused(entityCluster, entityId) {
const indices = entityCluster._collectionIndicesByEntity[entityId];
if (!defined_default(indices.billboardIndex) && !defined_default(indices.labelIndex) && !defined_default(indices.pointIndex)) {
delete entityCluster._collectionIndicesByEntity[entityId];
}
}
EntityCluster.prototype.getLabel = createGetEntity(
"_labelCollection",
LabelCollection_default,
"_unusedLabelIndices",
"labelIndex"
);
EntityCluster.prototype.removeLabel = function(entity) {
const entityIndices = this._collectionIndicesByEntity && this._collectionIndicesByEntity[entity.id];
if (!defined_default(this._labelCollection) || !defined_default(entityIndices) || !defined_default(entityIndices.labelIndex)) {
return;
}
const index = entityIndices.labelIndex;
entityIndices.labelIndex = void 0;
removeEntityIndicesIfUnused(this, entity.id);
const label = this._labelCollection.get(index);
label.show = false;
label.text = "";
label.id = void 0;
this._unusedLabelIndices.push(index);
this._clusterDirty = true;
};
EntityCluster.prototype.getBillboard = createGetEntity(
"_billboardCollection",
BillboardCollection_default,
"_unusedBillboardIndices",
"billboardIndex"
);
EntityCluster.prototype.removeBillboard = function(entity) {
const entityIndices = this._collectionIndicesByEntity && this._collectionIndicesByEntity[entity.id];
if (!defined_default(this._billboardCollection) || !defined_default(entityIndices) || !defined_default(entityIndices.billboardIndex)) {
return;
}
const index = entityIndices.billboardIndex;
entityIndices.billboardIndex = void 0;
removeEntityIndicesIfUnused(this, entity.id);
const billboard = this._billboardCollection.get(index);
billboard.id = void 0;
billboard.show = false;
billboard.image = void 0;
this._unusedBillboardIndices.push(index);
this._clusterDirty = true;
};
EntityCluster.prototype.getPoint = createGetEntity(
"_pointCollection",
PointPrimitiveCollection_default,
"_unusedPointIndices",
"pointIndex"
);
EntityCluster.prototype.removePoint = function(entity) {
const entityIndices = this._collectionIndicesByEntity && this._collectionIndicesByEntity[entity.id];
if (!defined_default(this._pointCollection) || !defined_default(entityIndices) || !defined_default(entityIndices.pointIndex)) {
return;
}
const index = entityIndices.pointIndex;
entityIndices.pointIndex = void 0;
removeEntityIndicesIfUnused(this, entity.id);
const point = this._pointCollection.get(index);
point.show = false;
point.id = void 0;
this._unusedPointIndices.push(index);
this._clusterDirty = true;
};
function disableCollectionClustering(collection) {
if (!defined_default(collection)) {
return;
}
const length2 = collection.length;
for (let i = 0; i < length2; ++i) {
collection.get(i).clusterShow = true;
}
}
function updateEnable(entityCluster) {
if (entityCluster.enabled) {
return;
}
if (defined_default(entityCluster._clusterLabelCollection)) {
entityCluster._clusterLabelCollection.destroy();
}
if (defined_default(entityCluster._clusterBillboardCollection)) {
entityCluster._clusterBillboardCollection.destroy();
}
if (defined_default(entityCluster._clusterPointCollection)) {
entityCluster._clusterPointCollection.destroy();
}
entityCluster._clusterLabelCollection = void 0;
entityCluster._clusterBillboardCollection = void 0;
entityCluster._clusterPointCollection = void 0;
disableCollectionClustering(entityCluster._labelCollection);
disableCollectionClustering(entityCluster._billboardCollection);
disableCollectionClustering(entityCluster._pointCollection);
}
EntityCluster.prototype.update = function(frameState) {
if (!this.show) {
return;
}
let commandList;
const labelCollection = this._labelCollection;
if (defined_default(labelCollection) && labelCollection.length > 0 && !labelCollection.ready) {
commandList = frameState.commandList;
frameState.commandList = [];
labelCollection.update(frameState);
frameState.commandList = commandList;
}
const billboardCollection = this._billboardCollection;
if (defined_default(billboardCollection) && billboardCollection.length > 0 && !billboardCollection.ready) {
commandList = frameState.commandList;
frameState.commandList = [];
billboardCollection.update(frameState);
frameState.commandList = commandList;
}
if (this._enabledDirty) {
this._enabledDirty = false;
updateEnable(this);
this._clusterDirty = true;
}
if (this._clusterDirty) {
this._cluster();
this._clusterDirty = defined_default(labelCollection) && !labelCollection.ready || defined_default(billboardCollection) && !billboardCollection.ready;
}
if (defined_default(this._clusterLabelCollection)) {
this._clusterLabelCollection.update(frameState);
}
if (defined_default(this._clusterBillboardCollection)) {
this._clusterBillboardCollection.update(frameState);
}
if (defined_default(this._clusterPointCollection)) {
this._clusterPointCollection.update(frameState);
}
if (defined_default(labelCollection)) {
labelCollection.update(frameState);
}
if (defined_default(billboardCollection)) {
billboardCollection.update(frameState);
}
if (defined_default(this._pointCollection)) {
this._pointCollection.update(frameState);
}
};
EntityCluster.prototype.destroy = function() {
if (defined_default(this._removeEventListener)) {
this._removeEventListener();
this._removeEventListener = void 0;
}
this._labelCollection = this._labelCollection && this._labelCollection.destroy();
this._billboardCollection = this._billboardCollection && this._billboardCollection.destroy();
this._pointCollection = this._pointCollection && this._pointCollection.destroy();
this._clusterLabelCollection = this._clusterLabelCollection && this._clusterLabelCollection.destroy();
this._clusterBillboardCollection = this._clusterBillboardCollection && this._clusterBillboardCollection.destroy();
this._clusterPointCollection = this._clusterPointCollection && this._clusterPointCollection.destroy();
this._labelCollection = void 0;
this._billboardCollection = void 0;
this._pointCollection = void 0;
this._clusterBillboardCollection = void 0;
this._clusterLabelCollection = void 0;
this._clusterPointCollection = void 0;
this._collectionIndicesByEntity = void 0;
this._unusedLabelIndices = [];
this._unusedBillboardIndices = [];
this._unusedPointIndices = [];
this._previousClusters = [];
this._previousHeight = void 0;
this._enabledDirty = false;
this._pixelRangeDirty = false;
this._minimumClusterSizeDirty = false;
return void 0;
};
var EntityCluster_default = EntityCluster;
// packages/engine/Source/DataSources/CustomDataSource.js
function CustomDataSource(name) {
this._name = name;
this._clock = void 0;
this._changed = new Event_default();
this._error = new Event_default();
this._isLoading = false;
this._loading = new Event_default();
this._entityCollection = new EntityCollection_default(this);
this._entityCluster = new EntityCluster_default();
}
Object.defineProperties(CustomDataSource.prototype, {
/**
* Gets or sets a human-readable name for this instance.
* @memberof CustomDataSource.prototype
* @type {string}
*/
name: {
get: function() {
return this._name;
},
set: function(value) {
if (this._name !== value) {
this._name = value;
this._changed.raiseEvent(this);
}
}
},
/**
* Gets or sets the clock for this instance.
* @memberof CustomDataSource.prototype
* @type {DataSourceClock}
*/
clock: {
get: function() {
return this._clock;
},
set: function(value) {
if (this._clock !== value) {
this._clock = value;
this._changed.raiseEvent(this);
}
}
},
/**
* Gets the collection of {@link Entity} instances.
* @memberof CustomDataSource.prototype
* @type {EntityCollection}
*/
entities: {
get: function() {
return this._entityCollection;
}
},
/**
* Gets or sets whether the data source is currently loading data.
* @memberof CustomDataSource.prototype
* @type {boolean}
*/
isLoading: {
get: function() {
return this._isLoading;
},
set: function(value) {
DataSource_default.setLoading(this, value);
}
},
/**
* Gets an event that will be raised when the underlying data changes.
* @memberof CustomDataSource.prototype
* @type {Event}
*/
changedEvent: {
get: function() {
return this._changed;
}
},
/**
* Gets an event that will be raised if an error is encountered during processing.
* @memberof CustomDataSource.prototype
* @type {Event}
*/
errorEvent: {
get: function() {
return this._error;
}
},
/**
* Gets an event that will be raised when the data source either starts or stops loading.
* @memberof CustomDataSource.prototype
* @type {Event}
*/
loadingEvent: {
get: function() {
return this._loading;
}
},
/**
* Gets whether or not this data source should be displayed.
* @memberof CustomDataSource.prototype
* @type {boolean}
*/
show: {
get: function() {
return this._entityCollection.show;
},
set: function(value) {
this._entityCollection.show = value;
}
},
/**
* Gets or sets the clustering options for this data source. This object can be shared between multiple data sources.
*
* @memberof CustomDataSource.prototype
* @type {EntityCluster}
*/
clustering: {
get: function() {
return this._entityCluster;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value must be defined.");
}
this._entityCluster = value;
}
}
});
CustomDataSource.prototype.update = function(time) {
return true;
};
var CustomDataSource_default = CustomDataSource;
// packages/engine/Source/DataSources/CylinderGeometryUpdater.js
var import_InlineWorkers843 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/CylinderGeometry.js
var import_InlineWorkers841 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/CylinderGeometryLibrary.js
var import_InlineWorkers840 = __toESM(require_InlineWorkers(), 1);
var CylinderGeometryLibrary = {};
CylinderGeometryLibrary.computePositions = function(length2, topRadius, bottomRadius, slices, fill) {
const topZ = length2 * 0.5;
const bottomZ = -topZ;
const twoSlice = slices + slices;
const size = fill ? 2 * twoSlice : twoSlice;
const positions = new Float64Array(size * 3);
let i;
let index = 0;
let tbIndex = 0;
const bottomOffset = fill ? twoSlice * 3 : 0;
const topOffset = fill ? (twoSlice + slices) * 3 : slices * 3;
for (i = 0; i < slices; i++) {
const angle = i / slices * Math_default.TWO_PI;
const x = Math.cos(angle);
const y = Math.sin(angle);
const bottomX = x * bottomRadius;
const bottomY = y * bottomRadius;
const topX = x * topRadius;
const topY = y * topRadius;
positions[tbIndex + bottomOffset] = bottomX;
positions[tbIndex + bottomOffset + 1] = bottomY;
positions[tbIndex + bottomOffset + 2] = bottomZ;
positions[tbIndex + topOffset] = topX;
positions[tbIndex + topOffset + 1] = topY;
positions[tbIndex + topOffset + 2] = topZ;
tbIndex += 3;
if (fill) {
positions[index++] = bottomX;
positions[index++] = bottomY;
positions[index++] = bottomZ;
positions[index++] = topX;
positions[index++] = topY;
positions[index++] = topZ;
}
}
return positions;
};
var CylinderGeometryLibrary_default = CylinderGeometryLibrary;
// packages/engine/Source/Core/CylinderGeometry.js
var radiusScratch = new Cartesian2_default();
var normalScratch3 = new Cartesian3_default();
var bitangentScratch = new Cartesian3_default();
var tangentScratch = new Cartesian3_default();
var positionScratch8 = new Cartesian3_default();
function CylinderGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const length2 = options.length;
const topRadius = options.topRadius;
const bottomRadius = options.bottomRadius;
const vertexFormat = options.vertexFormat ?? VertexFormat_default.DEFAULT;
const slices = options.slices ?? 128;
if (!defined_default(length2)) {
throw new DeveloperError_default("options.length must be defined.");
}
if (!defined_default(topRadius)) {
throw new DeveloperError_default("options.topRadius must be defined.");
}
if (!defined_default(bottomRadius)) {
throw new DeveloperError_default("options.bottomRadius must be defined.");
}
if (slices < 3) {
throw new DeveloperError_default(
"options.slices must be greater than or equal to 3."
);
}
if (defined_default(options.offsetAttribute) && options.offsetAttribute === GeometryOffsetAttribute_default.TOP) {
throw new DeveloperError_default(
"GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry."
);
}
this._length = length2;
this._topRadius = topRadius;
this._bottomRadius = bottomRadius;
this._vertexFormat = VertexFormat_default.clone(vertexFormat);
this._slices = slices;
this._offsetAttribute = options.offsetAttribute;
this._workerName = "createCylinderGeometry";
}
CylinderGeometry.packedLength = VertexFormat_default.packedLength + 5;
CylinderGeometry.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
startingIndex += VertexFormat_default.packedLength;
array[startingIndex++] = value._length;
array[startingIndex++] = value._topRadius;
array[startingIndex++] = value._bottomRadius;
array[startingIndex++] = value._slices;
array[startingIndex] = value._offsetAttribute ?? -1;
return array;
};
var scratchVertexFormat4 = new VertexFormat_default();
var scratchOptions9 = {
vertexFormat: scratchVertexFormat4,
length: void 0,
topRadius: void 0,
bottomRadius: void 0,
slices: void 0,
offsetAttribute: void 0
};
CylinderGeometry.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat4
);
startingIndex += VertexFormat_default.packedLength;
const length2 = array[startingIndex++];
const topRadius = array[startingIndex++];
const bottomRadius = array[startingIndex++];
const slices = array[startingIndex++];
const offsetAttribute = array[startingIndex];
if (!defined_default(result)) {
scratchOptions9.length = length2;
scratchOptions9.topRadius = topRadius;
scratchOptions9.bottomRadius = bottomRadius;
scratchOptions9.slices = slices;
scratchOptions9.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new CylinderGeometry(scratchOptions9);
}
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._length = length2;
result._topRadius = topRadius;
result._bottomRadius = bottomRadius;
result._slices = slices;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
CylinderGeometry.createGeometry = function(cylinderGeometry) {
let length2 = cylinderGeometry._length;
const topRadius = cylinderGeometry._topRadius;
const bottomRadius = cylinderGeometry._bottomRadius;
const vertexFormat = cylinderGeometry._vertexFormat;
const slices = cylinderGeometry._slices;
if (length2 <= 0 || topRadius < 0 || bottomRadius < 0 || topRadius === 0 && bottomRadius === 0) {
return;
}
const twoSlices = slices + slices;
const threeSlices = slices + twoSlices;
const numVertices = twoSlices + twoSlices;
const positions = CylinderGeometryLibrary_default.computePositions(
length2,
topRadius,
bottomRadius,
slices,
true
);
const st = vertexFormat.st ? new Float32Array(numVertices * 2) : void 0;
const normals = vertexFormat.normal ? new Float32Array(numVertices * 3) : void 0;
const tangents = vertexFormat.tangent ? new Float32Array(numVertices * 3) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(numVertices * 3) : void 0;
let i;
const computeNormal = vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent;
if (computeNormal) {
const computeTangent = vertexFormat.tangent || vertexFormat.bitangent;
let normalIndex = 0;
let tangentIndex = 0;
let bitangentIndex = 0;
const theta = Math.atan2(bottomRadius - topRadius, length2);
const normal2 = normalScratch3;
normal2.z = Math.sin(theta);
const normalScale2 = Math.cos(theta);
let tangent = tangentScratch;
let bitangent = bitangentScratch;
for (i = 0; i < slices; i++) {
const angle = i / slices * Math_default.TWO_PI;
const x = normalScale2 * Math.cos(angle);
const y = normalScale2 * Math.sin(angle);
if (computeNormal) {
normal2.x = x;
normal2.y = y;
if (computeTangent) {
tangent = Cartesian3_default.normalize(
Cartesian3_default.cross(Cartesian3_default.UNIT_Z, normal2, tangent),
tangent
);
}
if (vertexFormat.normal) {
normals[normalIndex++] = normal2.x;
normals[normalIndex++] = normal2.y;
normals[normalIndex++] = normal2.z;
normals[normalIndex++] = normal2.x;
normals[normalIndex++] = normal2.y;
normals[normalIndex++] = normal2.z;
}
if (vertexFormat.tangent) {
tangents[tangentIndex++] = tangent.x;
tangents[tangentIndex++] = tangent.y;
tangents[tangentIndex++] = tangent.z;
tangents[tangentIndex++] = tangent.x;
tangents[tangentIndex++] = tangent.y;
tangents[tangentIndex++] = tangent.z;
}
if (vertexFormat.bitangent) {
bitangent = Cartesian3_default.normalize(
Cartesian3_default.cross(normal2, tangent, bitangent),
bitangent
);
bitangents[bitangentIndex++] = bitangent.x;
bitangents[bitangentIndex++] = bitangent.y;
bitangents[bitangentIndex++] = bitangent.z;
bitangents[bitangentIndex++] = bitangent.x;
bitangents[bitangentIndex++] = bitangent.y;
bitangents[bitangentIndex++] = bitangent.z;
}
}
}
for (i = 0; i < slices; i++) {
if (vertexFormat.normal) {
normals[normalIndex++] = 0;
normals[normalIndex++] = 0;
normals[normalIndex++] = -1;
}
if (vertexFormat.tangent) {
tangents[tangentIndex++] = 1;
tangents[tangentIndex++] = 0;
tangents[tangentIndex++] = 0;
}
if (vertexFormat.bitangent) {
bitangents[bitangentIndex++] = 0;
bitangents[bitangentIndex++] = -1;
bitangents[bitangentIndex++] = 0;
}
}
for (i = 0; i < slices; i++) {
if (vertexFormat.normal) {
normals[normalIndex++] = 0;
normals[normalIndex++] = 0;
normals[normalIndex++] = 1;
}
if (vertexFormat.tangent) {
tangents[tangentIndex++] = 1;
tangents[tangentIndex++] = 0;
tangents[tangentIndex++] = 0;
}
if (vertexFormat.bitangent) {
bitangents[bitangentIndex++] = 0;
bitangents[bitangentIndex++] = 1;
bitangents[bitangentIndex++] = 0;
}
}
}
const numIndices = 12 * slices - 12;
const indices = IndexDatatype_default.createTypedArray(numVertices, numIndices);
let index = 0;
let j = 0;
for (i = 0; i < slices - 1; i++) {
indices[index++] = j;
indices[index++] = j + 2;
indices[index++] = j + 3;
indices[index++] = j;
indices[index++] = j + 3;
indices[index++] = j + 1;
j += 2;
}
indices[index++] = twoSlices - 2;
indices[index++] = 0;
indices[index++] = 1;
indices[index++] = twoSlices - 2;
indices[index++] = 1;
indices[index++] = twoSlices - 1;
for (i = 1; i < slices - 1; i++) {
indices[index++] = twoSlices + i + 1;
indices[index++] = twoSlices + i;
indices[index++] = twoSlices;
}
for (i = 1; i < slices - 1; i++) {
indices[index++] = threeSlices;
indices[index++] = threeSlices + i;
indices[index++] = threeSlices + i + 1;
}
let textureCoordIndex = 0;
if (vertexFormat.st) {
const rad = Math.max(topRadius, bottomRadius);
for (i = 0; i < numVertices; i++) {
const position = Cartesian3_default.fromArray(positions, i * 3, positionScratch8);
st[textureCoordIndex++] = (position.x + rad) / (2 * rad);
st[textureCoordIndex++] = (position.y + rad) / (2 * rad);
}
}
const attributes = new GeometryAttributes_default();
if (vertexFormat.position) {
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
});
}
if (vertexFormat.normal) {
attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: normals
});
}
if (vertexFormat.tangent) {
attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: tangents
});
}
if (vertexFormat.bitangent) {
attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: bitangents
});
}
if (vertexFormat.st) {
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: st
});
}
radiusScratch.x = length2 * 0.5;
radiusScratch.y = Math.max(bottomRadius, topRadius);
const boundingSphere = new BoundingSphere_default(
Cartesian3_default.ZERO,
Cartesian2_default.magnitude(radiusScratch)
);
if (defined_default(cylinderGeometry._offsetAttribute)) {
length2 = positions.length;
const offsetValue = cylinderGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.TRIANGLES,
boundingSphere,
offsetAttribute: cylinderGeometry._offsetAttribute
});
};
var unitCylinderGeometry;
CylinderGeometry.getUnitCylinder = function() {
if (!defined_default(unitCylinderGeometry)) {
unitCylinderGeometry = CylinderGeometry.createGeometry(
new CylinderGeometry({
topRadius: 1,
bottomRadius: 1,
length: 1,
vertexFormat: VertexFormat_default.POSITION_ONLY
})
);
}
return unitCylinderGeometry;
};
var CylinderGeometry_default = CylinderGeometry;
// packages/engine/Source/Core/CylinderOutlineGeometry.js
var import_InlineWorkers842 = __toESM(require_InlineWorkers(), 1);
var radiusScratch2 = new Cartesian2_default();
function CylinderOutlineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const length2 = options.length;
const topRadius = options.topRadius;
const bottomRadius = options.bottomRadius;
const slices = options.slices ?? 128;
const numberOfVerticalLines = Math.max(
options.numberOfVerticalLines ?? 16,
0
);
Check_default.typeOf.number("options.positions", length2);
Check_default.typeOf.number("options.topRadius", topRadius);
Check_default.typeOf.number("options.bottomRadius", bottomRadius);
Check_default.typeOf.number.greaterThanOrEquals("options.slices", slices, 3);
if (defined_default(options.offsetAttribute) && options.offsetAttribute === GeometryOffsetAttribute_default.TOP) {
throw new DeveloperError_default(
"GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry."
);
}
this._length = length2;
this._topRadius = topRadius;
this._bottomRadius = bottomRadius;
this._slices = slices;
this._numberOfVerticalLines = numberOfVerticalLines;
this._offsetAttribute = options.offsetAttribute;
this._workerName = "createCylinderOutlineGeometry";
}
CylinderOutlineGeometry.packedLength = 6;
CylinderOutlineGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
array[startingIndex++] = value._length;
array[startingIndex++] = value._topRadius;
array[startingIndex++] = value._bottomRadius;
array[startingIndex++] = value._slices;
array[startingIndex++] = value._numberOfVerticalLines;
array[startingIndex] = value._offsetAttribute ?? -1;
return array;
};
var scratchOptions10 = {
length: void 0,
topRadius: void 0,
bottomRadius: void 0,
slices: void 0,
numberOfVerticalLines: void 0,
offsetAttribute: void 0
};
CylinderOutlineGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const length2 = array[startingIndex++];
const topRadius = array[startingIndex++];
const bottomRadius = array[startingIndex++];
const slices = array[startingIndex++];
const numberOfVerticalLines = array[startingIndex++];
const offsetAttribute = array[startingIndex];
if (!defined_default(result)) {
scratchOptions10.length = length2;
scratchOptions10.topRadius = topRadius;
scratchOptions10.bottomRadius = bottomRadius;
scratchOptions10.slices = slices;
scratchOptions10.numberOfVerticalLines = numberOfVerticalLines;
scratchOptions10.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new CylinderOutlineGeometry(scratchOptions10);
}
result._length = length2;
result._topRadius = topRadius;
result._bottomRadius = bottomRadius;
result._slices = slices;
result._numberOfVerticalLines = numberOfVerticalLines;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
CylinderOutlineGeometry.createGeometry = function(cylinderGeometry) {
let length2 = cylinderGeometry._length;
const topRadius = cylinderGeometry._topRadius;
const bottomRadius = cylinderGeometry._bottomRadius;
const slices = cylinderGeometry._slices;
const numberOfVerticalLines = cylinderGeometry._numberOfVerticalLines;
if (length2 <= 0 || topRadius < 0 || bottomRadius < 0 || topRadius === 0 && bottomRadius === 0) {
return;
}
const numVertices = slices * 2;
const positions = CylinderGeometryLibrary_default.computePositions(
length2,
topRadius,
bottomRadius,
slices,
false
);
let numIndices = slices * 2;
let numSide;
if (numberOfVerticalLines > 0) {
const numSideLines = Math.min(numberOfVerticalLines, slices);
numSide = Math.round(slices / numSideLines);
numIndices += numSideLines;
}
const indices = IndexDatatype_default.createTypedArray(numVertices, numIndices * 2);
let index = 0;
let i;
for (i = 0; i < slices - 1; i++) {
indices[index++] = i;
indices[index++] = i + 1;
indices[index++] = i + slices;
indices[index++] = i + 1 + slices;
}
indices[index++] = slices - 1;
indices[index++] = 0;
indices[index++] = slices + slices - 1;
indices[index++] = slices;
if (numberOfVerticalLines > 0) {
for (i = 0; i < slices; i += numSide) {
indices[index++] = i;
indices[index++] = i + slices;
}
}
const attributes = new GeometryAttributes_default();
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
});
radiusScratch2.x = length2 * 0.5;
radiusScratch2.y = Math.max(bottomRadius, topRadius);
const boundingSphere = new BoundingSphere_default(
Cartesian3_default.ZERO,
Cartesian2_default.magnitude(radiusScratch2)
);
if (defined_default(cylinderGeometry._offsetAttribute)) {
length2 = positions.length;
const offsetValue = cylinderGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.LINES,
boundingSphere,
offsetAttribute: cylinderGeometry._offsetAttribute
});
};
var CylinderOutlineGeometry_default = CylinderOutlineGeometry;
// packages/engine/Source/DataSources/CylinderGeometryUpdater.js
var defaultOffset3 = Cartesian3_default.ZERO;
var offsetScratch6 = new Cartesian3_default();
var positionScratch9 = new Cartesian3_default();
var scratchColor14 = new Color_default();
function CylinderGeometryOptions(entity) {
this.id = entity;
this.vertexFormat = void 0;
this.length = void 0;
this.topRadius = void 0;
this.bottomRadius = void 0;
this.slices = void 0;
this.numberOfVerticalLines = void 0;
this.offsetAttribute = void 0;
}
function CylinderGeometryUpdater(entity, scene) {
GeometryUpdater_default.call(this, {
entity,
scene,
geometryOptions: new CylinderGeometryOptions(entity),
geometryPropertyName: "cylinder",
observedPropertyNames: [
"availability",
"position",
"orientation",
"cylinder"
]
});
this._onEntityPropertyChanged(entity, "cylinder", entity.cylinder, void 0);
}
if (defined_default(Object.create)) {
CylinderGeometryUpdater.prototype = Object.create(GeometryUpdater_default.prototype);
CylinderGeometryUpdater.prototype.constructor = CylinderGeometryUpdater;
}
Object.defineProperties(CylinderGeometryUpdater.prototype, {
/**
* Gets the terrain offset property
* @type {TerrainOffsetProperty}
* @memberof CylinderGeometryUpdater.prototype
* @readonly
* @private
*/
terrainOffsetProperty: {
get: function() {
return this._terrainOffsetProperty;
}
}
});
CylinderGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._fillEnabled) {
throw new DeveloperError_default(
"This instance does not represent a filled geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const show = new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
);
const attributes = {
show,
distanceDisplayCondition: distanceDisplayConditionAttribute,
color: void 0,
offset: void 0
};
if (this._materialProperty instanceof ColorMaterialProperty_default) {
let currentColor;
if (defined_default(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
currentColor = this._materialProperty.color.getValue(time, scratchColor14);
}
if (!defined_default(currentColor)) {
currentColor = Color_default.WHITE;
}
attributes.color = ColorGeometryInstanceAttribute_default.fromColor(currentColor);
}
if (defined_default(this._options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset3,
offsetScratch6
)
);
}
return new GeometryInstance_default({
id: entity,
geometry: new CylinderGeometry_default(this._options),
modelMatrix: entity.computeModelMatrixForHeightReference(
time,
entity.cylinder.heightReference,
this._options.length * 0.5,
this._scene.ellipsoid
),
attributes
});
};
CylinderGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._outlineEnabled) {
throw new DeveloperError_default(
"This instance does not represent an outlined geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const outlineColor = Property_default.getValueOrDefault(
this._outlineColorProperty,
time,
Color_default.BLACK,
scratchColor14
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const attributes = {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)
),
color: ColorGeometryInstanceAttribute_default.fromColor(outlineColor),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
),
offset: void 0
};
if (defined_default(this._options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset3,
offsetScratch6
)
);
}
return new GeometryInstance_default({
id: entity,
geometry: new CylinderOutlineGeometry_default(this._options),
modelMatrix: entity.computeModelMatrixForHeightReference(
time,
entity.cylinder.heightReference,
this._options.length * 0.5,
this._scene.ellipsoid
),
attributes
});
};
CylinderGeometryUpdater.prototype._computeCenter = function(time, result) {
return Property_default.getValueOrUndefined(this._entity.position, time, result);
};
CylinderGeometryUpdater.prototype._isHidden = function(entity, cylinder) {
return !defined_default(entity.position) || !defined_default(cylinder.length) || !defined_default(cylinder.topRadius) || !defined_default(cylinder.bottomRadius) || GeometryUpdater_default.prototype._isHidden.call(this, entity, cylinder);
};
CylinderGeometryUpdater.prototype._isDynamic = function(entity, cylinder) {
return !entity.position.isConstant || //
!Property_default.isConstant(entity.orientation) || //
!cylinder.length.isConstant || //
!cylinder.topRadius.isConstant || //
!cylinder.bottomRadius.isConstant || //
!Property_default.isConstant(cylinder.slices) || //
!Property_default.isConstant(cylinder.outlineWidth) || //
!Property_default.isConstant(cylinder.numberOfVerticalLines);
};
CylinderGeometryUpdater.prototype._setStaticOptions = function(entity, cylinder) {
const heightReference = Property_default.getValueOrDefault(
cylinder.heightReference,
Iso8601_default.MINIMUM_VALUE,
HeightReference_default.NONE
);
const options = this._options;
options.vertexFormat = this._materialProperty instanceof ColorMaterialProperty_default ? PerInstanceColorAppearance_default.VERTEX_FORMAT : MaterialAppearance_default.MaterialSupport.TEXTURED.vertexFormat;
options.length = cylinder.length.getValue(Iso8601_default.MINIMUM_VALUE);
options.topRadius = cylinder.topRadius.getValue(Iso8601_default.MINIMUM_VALUE);
options.bottomRadius = cylinder.bottomRadius.getValue(Iso8601_default.MINIMUM_VALUE);
options.slices = Property_default.getValueOrUndefined(
cylinder.slices,
Iso8601_default.MINIMUM_VALUE
);
options.numberOfVerticalLines = Property_default.getValueOrUndefined(
cylinder.numberOfVerticalLines,
Iso8601_default.MINIMUM_VALUE
);
options.offsetAttribute = heightReference !== HeightReference_default.NONE ? GeometryOffsetAttribute_default.ALL : void 0;
};
CylinderGeometryUpdater.prototype._onEntityPropertyChanged = heightReferenceOnEntityPropertyChanged_default;
CylinderGeometryUpdater.DynamicGeometryUpdater = DynamicCylinderGeometryUpdater;
function DynamicCylinderGeometryUpdater(geometryUpdater, primitives, groundPrimitives) {
DynamicGeometryUpdater_default.call(
this,
geometryUpdater,
primitives,
groundPrimitives
);
}
if (defined_default(Object.create)) {
DynamicCylinderGeometryUpdater.prototype = Object.create(
DynamicGeometryUpdater_default.prototype
);
DynamicCylinderGeometryUpdater.prototype.constructor = DynamicCylinderGeometryUpdater;
}
DynamicCylinderGeometryUpdater.prototype._isHidden = function(entity, cylinder, time) {
const options = this._options;
const position = Property_default.getValueOrUndefined(
entity.position,
time,
positionScratch9
);
return !defined_default(position) || !defined_default(options.length) || !defined_default(options.topRadius) || //
!defined_default(options.bottomRadius) || DynamicGeometryUpdater_default.prototype._isHidden.call(
this,
entity,
cylinder,
time
);
};
DynamicCylinderGeometryUpdater.prototype._setOptions = function(entity, cylinder, time) {
const heightReference = Property_default.getValueOrDefault(
cylinder.heightReference,
time,
HeightReference_default.NONE
);
const options = this._options;
options.length = Property_default.getValueOrUndefined(cylinder.length, time);
options.topRadius = Property_default.getValueOrUndefined(cylinder.topRadius, time);
options.bottomRadius = Property_default.getValueOrUndefined(
cylinder.bottomRadius,
time
);
options.slices = Property_default.getValueOrUndefined(cylinder.slices, time);
options.numberOfVerticalLines = Property_default.getValueOrUndefined(
cylinder.numberOfVerticalLines,
time
);
options.offsetAttribute = heightReference !== HeightReference_default.NONE ? GeometryOffsetAttribute_default.ALL : void 0;
};
var CylinderGeometryUpdater_default = CylinderGeometryUpdater;
// packages/engine/Source/DataSources/CzmlDataSource.js
var import_InlineWorkers873 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/ClockRange.js
var import_InlineWorkers844 = __toESM(require_InlineWorkers(), 1);
var ClockRange = {
/**
* {@link Clock#tick} will always advances the clock in its current direction.
*
* @type {number}
* @constant
*/
UNBOUNDED: 0,
/**
* When {@link Clock#startTime} or {@link Clock#stopTime} is reached,
* {@link Clock#tick} will not advance {@link Clock#currentTime} any further.
*
* @type {number}
* @constant
*/
CLAMPED: 1,
/**
* When {@link Clock#stopTime} is reached, {@link Clock#tick} will advance
* {@link Clock#currentTime} to the opposite end of the interval. When
* time is moving backwards, {@link Clock#tick} will not advance past
* {@link Clock#startTime}
*
* @type {number}
* @constant
*/
LOOP_STOP: 2
};
var ClockRange_default = Object.freeze(ClockRange);
// packages/engine/Source/Core/ClockStep.js
var import_InlineWorkers845 = __toESM(require_InlineWorkers(), 1);
var ClockStep = {
/**
* {@link Clock#tick} advances the current time by a fixed step,
* which is the number of seconds specified by {@link Clock#multiplier}.
*
* @type {number}
* @constant
*/
TICK_DEPENDENT: 0,
/**
* {@link Clock#tick} advances the current time by the amount of system
* time elapsed since the previous call multiplied by {@link Clock#multiplier}.
*
* @type {number}
* @constant
*/
SYSTEM_CLOCK_MULTIPLIER: 1,
/**
* {@link Clock#tick} sets the clock to the current system time;
* ignoring all other settings.
*
* @type {number}
* @constant
*/
SYSTEM_CLOCK: 2
};
var ClockStep_default = Object.freeze(ClockStep);
// packages/engine/Source/Core/ExtrapolationType.js
var import_InlineWorkers846 = __toESM(require_InlineWorkers(), 1);
var ExtrapolationType = {
/**
* No extrapolation occurs.
*
* @type {number}
* @constant
*/
NONE: 0,
/**
* The first or last value is used when outside the range of sample data.
*
* @type {number}
* @constant
*/
HOLD: 1,
/**
* The value is extrapolated.
*
* @type {number}
* @constant
*/
EXTRAPOLATE: 2
};
var ExtrapolationType_default = Object.freeze(ExtrapolationType);
// packages/engine/Source/Core/getFilenameFromUri.js
var import_InlineWorkers847 = __toESM(require_InlineWorkers(), 1);
var import_urijs9 = __toESM(require_URI(), 1);
function getFilenameFromUri(uri) {
if (!defined_default(uri)) {
throw new DeveloperError_default("uri is required.");
}
const uriObject = new import_urijs9.default(uri);
uriObject.normalize();
let path = uriObject.path();
const index = path.lastIndexOf("/");
if (index !== -1) {
path = path.substr(index + 1);
}
return path;
}
var getFilenameFromUri_default = getFilenameFromUri;
// packages/engine/Source/Core/HermitePolynomialApproximation.js
var import_InlineWorkers848 = __toESM(require_InlineWorkers(), 1);
var factorial = Math_default.factorial;
function calculateCoefficientTerm(x, zIndices, xTable, derivOrder, termOrder, reservedIndices) {
let result = 0;
let reserved;
let i;
let j;
if (derivOrder > 0) {
for (i = 0; i < termOrder; i++) {
reserved = false;
for (j = 0; j < reservedIndices.length && !reserved; j++) {
if (i === reservedIndices[j]) {
reserved = true;
}
}
if (!reserved) {
reservedIndices.push(i);
result += calculateCoefficientTerm(
x,
zIndices,
xTable,
derivOrder - 1,
termOrder,
reservedIndices
);
reservedIndices.splice(reservedIndices.length - 1, 1);
}
}
return result;
}
result = 1;
for (i = 0; i < termOrder; i++) {
reserved = false;
for (j = 0; j < reservedIndices.length && !reserved; j++) {
if (i === reservedIndices[j]) {
reserved = true;
}
}
if (!reserved) {
result *= x - xTable[zIndices[i]];
}
}
return result;
}
var HermitePolynomialApproximation = {
type: "Hermite"
};
HermitePolynomialApproximation.getRequiredDataPoints = function(degree, inputOrder) {
inputOrder = inputOrder ?? 0;
if (!defined_default(degree)) {
throw new DeveloperError_default("degree is required.");
}
if (degree < 0) {
throw new DeveloperError_default("degree must be 0 or greater.");
}
if (inputOrder < 0) {
throw new DeveloperError_default("inputOrder must be 0 or greater.");
}
return Math.max(Math.floor((degree + 1) / (inputOrder + 1)), 2);
};
HermitePolynomialApproximation.interpolateOrderZero = function(x, xTable, yTable, yStride, result) {
if (!defined_default(result)) {
result = new Array(yStride);
}
let i;
let j;
let d;
let s;
let len;
let index;
const length2 = xTable.length;
const coefficients = new Array(yStride);
for (i = 0; i < yStride; i++) {
result[i] = 0;
const l = new Array(length2);
coefficients[i] = l;
for (j = 0; j < length2; j++) {
l[j] = [];
}
}
const zIndicesLength = length2, zIndices = new Array(zIndicesLength);
for (i = 0; i < zIndicesLength; i++) {
zIndices[i] = i;
}
let highestNonZeroCoef = length2 - 1;
for (s = 0; s < yStride; s++) {
for (j = 0; j < zIndicesLength; j++) {
index = zIndices[j] * yStride + s;
coefficients[s][0].push(yTable[index]);
}
for (i = 1; i < zIndicesLength; i++) {
let nonZeroCoefficients = false;
for (j = 0; j < zIndicesLength - i; j++) {
const zj = xTable[zIndices[j]];
const zn = xTable[zIndices[j + i]];
let numerator;
if (zn - zj <= 0) {
index = zIndices[j] * yStride + yStride * i + s;
numerator = yTable[index];
coefficients[s][i].push(numerator / factorial(i));
} else {
numerator = coefficients[s][i - 1][j + 1] - coefficients[s][i - 1][j];
coefficients[s][i].push(numerator / (zn - zj));
}
nonZeroCoefficients = nonZeroCoefficients || numerator !== 0;
}
if (!nonZeroCoefficients) {
highestNonZeroCoef = i - 1;
}
}
}
for (d = 0, len = 0; d <= len; d++) {
for (i = d; i <= highestNonZeroCoef; i++) {
const tempTerm = calculateCoefficientTerm(x, zIndices, xTable, d, i, []);
for (s = 0; s < yStride; s++) {
const coeff = coefficients[s][i][0];
result[s + d * yStride] += coeff * tempTerm;
}
}
}
return result;
};
var arrayScratch = [];
HermitePolynomialApproximation.interpolate = function(x, xTable, yTable, yStride, inputOrder, outputOrder, result) {
const resultLength = yStride * (outputOrder + 1);
if (!defined_default(result)) {
result = new Array(resultLength);
}
for (let r = 0; r < resultLength; r++) {
result[r] = 0;
}
const length2 = xTable.length;
const zIndices = new Array(length2 * (inputOrder + 1));
let i;
for (i = 0; i < length2; i++) {
for (let j = 0; j < inputOrder + 1; j++) {
zIndices[i * (inputOrder + 1) + j] = i;
}
}
const zIndiceslength = zIndices.length;
const coefficients = arrayScratch;
const highestNonZeroCoef = fillCoefficientList(
coefficients,
zIndices,
xTable,
yTable,
yStride,
inputOrder
);
const reservedIndices = [];
const tmp2 = zIndiceslength * (zIndiceslength + 1) / 2;
const loopStop = Math.min(highestNonZeroCoef, outputOrder);
for (let d = 0; d <= loopStop; d++) {
for (i = d; i <= highestNonZeroCoef; i++) {
reservedIndices.length = 0;
const tempTerm = calculateCoefficientTerm(
x,
zIndices,
xTable,
d,
i,
reservedIndices
);
const dimTwo = Math.floor(i * (1 - i) / 2) + zIndiceslength * i;
for (let s = 0; s < yStride; s++) {
const dimOne = Math.floor(s * tmp2);
const coef = coefficients[dimOne + dimTwo];
result[s + d * yStride] += coef * tempTerm;
}
}
}
return result;
};
function fillCoefficientList(coefficients, zIndices, xTable, yTable, yStride, inputOrder) {
let j;
let index;
let highestNonZero = -1;
const zIndiceslength = zIndices.length;
const tmp2 = zIndiceslength * (zIndiceslength + 1) / 2;
for (let s = 0; s < yStride; s++) {
const dimOne = Math.floor(s * tmp2);
for (j = 0; j < zIndiceslength; j++) {
index = zIndices[j] * yStride * (inputOrder + 1) + s;
coefficients[dimOne + j] = yTable[index];
}
for (let i = 1; i < zIndiceslength; i++) {
let coefIndex = 0;
const dimTwo = Math.floor(i * (1 - i) / 2) + zIndiceslength * i;
let nonZeroCoefficients = false;
for (j = 0; j < zIndiceslength - i; j++) {
const zj = xTable[zIndices[j]];
const zn = xTable[zIndices[j + i]];
let numerator;
let coefficient;
if (zn - zj <= 0) {
index = zIndices[j] * yStride * (inputOrder + 1) + yStride * i + s;
numerator = yTable[index];
coefficient = numerator / Math_default.factorial(i);
coefficients[dimOne + dimTwo + coefIndex] = coefficient;
coefIndex++;
} else {
const dimTwoMinusOne = Math.floor((i - 1) * (2 - i) / 2) + zIndiceslength * (i - 1);
numerator = coefficients[dimOne + dimTwoMinusOne + j + 1] - coefficients[dimOne + dimTwoMinusOne + j];
coefficient = numerator / (zn - zj);
coefficients[dimOne + dimTwo + coefIndex] = coefficient;
coefIndex++;
}
nonZeroCoefficients = nonZeroCoefficients || numerator !== 0;
}
if (nonZeroCoefficients) {
highestNonZero = Math.max(highestNonZero, i);
}
}
}
return highestNonZero;
}
var HermitePolynomialApproximation_default = HermitePolynomialApproximation;
// packages/engine/Source/Core/LagrangePolynomialApproximation.js
var import_InlineWorkers849 = __toESM(require_InlineWorkers(), 1);
var LagrangePolynomialApproximation = {
type: "Lagrange"
};
LagrangePolynomialApproximation.getRequiredDataPoints = function(degree) {
return Math.max(degree + 1, 2);
};
LagrangePolynomialApproximation.interpolateOrderZero = function(x, xTable, yTable, yStride, result) {
if (!defined_default(result)) {
result = new Array(yStride);
}
let i;
let j;
const length2 = xTable.length;
for (i = 0; i < yStride; i++) {
result[i] = 0;
}
for (i = 0; i < length2; i++) {
let coefficient = 1;
for (j = 0; j < length2; j++) {
if (j !== i) {
const diffX = xTable[i] - xTable[j];
coefficient *= (x - xTable[j]) / diffX;
}
}
for (j = 0; j < yStride; j++) {
result[j] += coefficient * yTable[i * yStride + j];
}
}
return result;
};
var LagrangePolynomialApproximation_default = LagrangePolynomialApproximation;
// packages/engine/Source/Core/LinearApproximation.js
var import_InlineWorkers850 = __toESM(require_InlineWorkers(), 1);
var LinearApproximation = {
type: "Linear"
};
LinearApproximation.getRequiredDataPoints = function(degree) {
return 2;
};
LinearApproximation.interpolateOrderZero = function(x, xTable, yTable, yStride, result) {
if (xTable.length !== 2) {
throw new DeveloperError_default(
"The xTable provided to the linear interpolator must have exactly two elements."
);
} else if (yStride <= 0) {
throw new DeveloperError_default(
"There must be at least 1 dependent variable for each independent variable."
);
}
if (!defined_default(result)) {
result = new Array(yStride);
}
let i;
let y0;
let y1;
const x0 = xTable[0];
const x1 = xTable[1];
if (x0 === x1) {
throw new DeveloperError_default(
"Divide by zero error: xTable[0] and xTable[1] are equal"
);
}
for (i = 0; i < yStride; i++) {
y0 = yTable[i];
y1 = yTable[i + yStride];
result[i] = ((y1 - y0) * x + x1 * y0 - x0 * y1) / (x1 - x0);
}
return result;
};
var LinearApproximation_default = LinearApproximation;
// packages/engine/Source/Core/Spherical.js
var import_InlineWorkers851 = __toESM(require_InlineWorkers(), 1);
function Spherical(clock, cone, magnitude) {
this.clock = clock ?? 0;
this.cone = cone ?? 0;
this.magnitude = magnitude ?? 1;
}
Spherical.fromCartesian3 = function(cartesian34, result) {
Check_default.typeOf.object("cartesian3", cartesian34);
const x = cartesian34.x;
const y = cartesian34.y;
const z = cartesian34.z;
const radialSquared = x * x + y * y;
if (!defined_default(result)) {
result = new Spherical();
}
result.clock = Math.atan2(y, x);
result.cone = Math.atan2(Math.sqrt(radialSquared), z);
result.magnitude = Math.sqrt(radialSquared + z * z);
return result;
};
Spherical.clone = function(spherical, result) {
if (!defined_default(spherical)) {
return void 0;
}
if (!defined_default(result)) {
return new Spherical(spherical.clock, spherical.cone, spherical.magnitude);
}
result.clock = spherical.clock;
result.cone = spherical.cone;
result.magnitude = spherical.magnitude;
return result;
};
Spherical.normalize = function(spherical, result) {
Check_default.typeOf.object("spherical", spherical);
if (!defined_default(result)) {
return new Spherical(spherical.clock, spherical.cone, 1);
}
result.clock = spherical.clock;
result.cone = spherical.cone;
result.magnitude = 1;
return result;
};
Spherical.equals = function(left, right) {
return left === right || defined_default(left) && defined_default(right) && left.clock === right.clock && left.cone === right.cone && left.magnitude === right.magnitude;
};
Spherical.equalsEpsilon = function(left, right, epsilon) {
epsilon = epsilon ?? 0;
return left === right || defined_default(left) && defined_default(right) && Math.abs(left.clock - right.clock) <= epsilon && Math.abs(left.cone - right.cone) <= epsilon && Math.abs(left.magnitude - right.magnitude) <= epsilon;
};
Spherical.prototype.equals = function(other) {
return Spherical.equals(this, other);
};
Spherical.prototype.clone = function(result) {
return Spherical.clone(this, result);
};
Spherical.prototype.equalsEpsilon = function(other, epsilon) {
return Spherical.equalsEpsilon(this, other, epsilon);
};
Spherical.prototype.toString = function() {
return `(${this.clock}, ${this.cone}, ${this.magnitude})`;
};
var Spherical_default = Spherical;
// packages/engine/Source/DataSources/CzmlDataSource.js
var import_urijs10 = __toESM(require_URI(), 1);
// packages/engine/Source/DataSources/DataSourceClock.js
var import_InlineWorkers854 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/Clock.js
var import_InlineWorkers853 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/getTimestamp.js
var import_InlineWorkers852 = __toESM(require_InlineWorkers(), 1);
var getTimestamp;
if (typeof performance !== "undefined" && typeof performance.now === "function" && isFinite(performance.now())) {
getTimestamp = function() {
return performance.now();
};
} else {
getTimestamp = function() {
return Date.now();
};
}
var getTimestamp_default = getTimestamp;
// packages/engine/Source/Core/Clock.js
function Clock(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
let currentTime = options.currentTime;
let startTime = options.startTime;
let stopTime = options.stopTime;
if (!defined_default(currentTime)) {
if (defined_default(startTime)) {
currentTime = JulianDate_default.clone(startTime);
} else if (defined_default(stopTime)) {
currentTime = JulianDate_default.addDays(stopTime, -1, new JulianDate_default());
} else {
currentTime = JulianDate_default.now();
}
} else {
currentTime = JulianDate_default.clone(currentTime);
}
if (!defined_default(startTime)) {
startTime = JulianDate_default.clone(currentTime);
} else {
startTime = JulianDate_default.clone(startTime);
}
if (!defined_default(stopTime)) {
stopTime = JulianDate_default.addDays(startTime, 1, new JulianDate_default());
} else {
stopTime = JulianDate_default.clone(stopTime);
}
if (JulianDate_default.greaterThan(startTime, stopTime)) {
throw new DeveloperError_default("startTime must come before stopTime.");
}
this.startTime = startTime;
this.stopTime = stopTime;
this.clockRange = options.clockRange ?? ClockRange_default.UNBOUNDED;
this.canAnimate = options.canAnimate ?? true;
this.onTick = new Event_default();
this.onStop = new Event_default();
this._currentTime = void 0;
this._multiplier = void 0;
this._clockStep = void 0;
this._shouldAnimate = void 0;
this._lastSystemTime = getTimestamp_default();
this.currentTime = currentTime;
this.multiplier = options.multiplier ?? 1;
this.shouldAnimate = options.shouldAnimate ?? false;
this.clockStep = options.clockStep ?? ClockStep_default.SYSTEM_CLOCK_MULTIPLIER;
}
Object.defineProperties(Clock.prototype, {
/**
* The current time.
* Changing this property will change
* {@link Clock#clockStep} from {@link ClockStep.SYSTEM_CLOCK} to
* {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}.
* @memberof Clock.prototype
* @type {JulianDate}
*/
currentTime: {
get: function() {
return this._currentTime;
},
set: function(value) {
if (JulianDate_default.equals(this._currentTime, value)) {
return;
}
if (this._clockStep === ClockStep_default.SYSTEM_CLOCK) {
this._clockStep = ClockStep_default.SYSTEM_CLOCK_MULTIPLIER;
}
this._currentTime = value;
}
},
/**
* Gets or sets how much time advances when {@link Clock#tick} is called. Negative values allow for advancing backwards.
* If {@link Clock#clockStep} is set to {@link ClockStep.TICK_DEPENDENT}, this is the number of seconds to advance.
* If {@link Clock#clockStep} is set to {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}, this value is multiplied by the
* elapsed system time since the last call to {@link Clock#tick}.
* Changing this property will change
* {@link Clock#clockStep} from {@link ClockStep.SYSTEM_CLOCK} to
* {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}.
* @memberof Clock.prototype
* @type {number}
* @default 1.0
*/
multiplier: {
get: function() {
return this._multiplier;
},
set: function(value) {
if (this._multiplier === value) {
return;
}
if (this._clockStep === ClockStep_default.SYSTEM_CLOCK) {
this._clockStep = ClockStep_default.SYSTEM_CLOCK_MULTIPLIER;
}
this._multiplier = value;
}
},
/**
* Determines if calls to {@link Clock#tick} are frame dependent or system clock dependent.
* Changing this property to {@link ClockStep.SYSTEM_CLOCK} will set
* {@link Clock#multiplier} to 1.0, {@link Clock#shouldAnimate} to true, and
* {@link Clock#currentTime} to the current system clock time.
* @memberof Clock.prototype
* @type ClockStep
* @default {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}
*/
clockStep: {
get: function() {
return this._clockStep;
},
set: function(value) {
if (value === ClockStep_default.SYSTEM_CLOCK) {
this._multiplier = 1;
this._shouldAnimate = true;
this._currentTime = JulianDate_default.now();
}
this._clockStep = value;
}
},
/**
* Indicates whether {@link Clock#tick} should attempt to advance time.
* The clock will only advance time when both
* {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true.
* Changing this property will change
* {@link Clock#clockStep} from {@link ClockStep.SYSTEM_CLOCK} to
* {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}.
* @memberof Clock.prototype
* @type {boolean}
* @default false
*/
shouldAnimate: {
get: function() {
return this._shouldAnimate;
},
set: function(value) {
if (this._shouldAnimate === value) {
return;
}
if (this._clockStep === ClockStep_default.SYSTEM_CLOCK) {
this._clockStep = ClockStep_default.SYSTEM_CLOCK_MULTIPLIER;
}
this._shouldAnimate = value;
}
}
});
Clock.prototype.tick = function() {
const currentSystemTime = getTimestamp_default();
let currentTime = JulianDate_default.clone(this._currentTime);
if (this.canAnimate && this._shouldAnimate) {
const clockStep = this._clockStep;
if (clockStep === ClockStep_default.SYSTEM_CLOCK) {
currentTime = JulianDate_default.now(currentTime);
} else {
const multiplier = this._multiplier;
if (clockStep === ClockStep_default.TICK_DEPENDENT) {
currentTime = JulianDate_default.addSeconds(
currentTime,
multiplier,
currentTime
);
} else {
const milliseconds = currentSystemTime - this._lastSystemTime;
currentTime = JulianDate_default.addSeconds(
currentTime,
multiplier * (milliseconds / 1e3),
currentTime
);
}
const clockRange = this.clockRange;
const startTime = this.startTime;
const stopTime = this.stopTime;
if (clockRange === ClockRange_default.CLAMPED) {
if (JulianDate_default.lessThan(currentTime, startTime)) {
currentTime = JulianDate_default.clone(startTime, currentTime);
} else if (JulianDate_default.greaterThan(currentTime, stopTime)) {
currentTime = JulianDate_default.clone(stopTime, currentTime);
this.onStop.raiseEvent(this);
}
} else if (clockRange === ClockRange_default.LOOP_STOP) {
if (JulianDate_default.lessThan(currentTime, startTime)) {
currentTime = JulianDate_default.clone(startTime, currentTime);
}
while (JulianDate_default.greaterThan(currentTime, stopTime)) {
currentTime = JulianDate_default.addSeconds(
startTime,
JulianDate_default.secondsDifference(currentTime, stopTime),
currentTime
);
this.onStop.raiseEvent(this);
}
}
}
}
this._currentTime = currentTime;
this._lastSystemTime = currentSystemTime;
this.onTick.raiseEvent(this);
return currentTime;
};
var Clock_default = Clock;
// packages/engine/Source/DataSources/DataSourceClock.js
function DataSourceClock() {
this._definitionChanged = new Event_default();
this._startTime = void 0;
this._stopTime = void 0;
this._currentTime = void 0;
this._clockRange = void 0;
this._clockStep = void 0;
this._multiplier = void 0;
}
Object.defineProperties(DataSourceClock.prototype, {
/**
* Gets the event that is raised whenever a new property is assigned.
* @memberof DataSourceClock.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the desired start time of the clock.
* See {@link Clock#startTime}.
* @memberof DataSourceClock.prototype
* @type {JulianDate}
*/
startTime: createRawPropertyDescriptor_default("startTime"),
/**
* Gets or sets the desired stop time of the clock.
* See {@link Clock#stopTime}.
* @memberof DataSourceClock.prototype
* @type {JulianDate}
*/
stopTime: createRawPropertyDescriptor_default("stopTime"),
/**
* Gets or sets the desired current time when this data source is loaded.
* See {@link Clock#currentTime}.
* @memberof DataSourceClock.prototype
* @type {JulianDate}
*/
currentTime: createRawPropertyDescriptor_default("currentTime"),
/**
* Gets or sets the desired clock range setting.
* See {@link Clock#clockRange}.
* @memberof DataSourceClock.prototype
* @type {ClockRange}
*/
clockRange: createRawPropertyDescriptor_default("clockRange"),
/**
* Gets or sets the desired clock step setting.
* See {@link Clock#clockStep}.
* @memberof DataSourceClock.prototype
* @type {ClockStep}
*/
clockStep: createRawPropertyDescriptor_default("clockStep"),
/**
* Gets or sets the desired clock multiplier.
* See {@link Clock#multiplier}.
* @memberof DataSourceClock.prototype
* @type {number}
*/
multiplier: createRawPropertyDescriptor_default("multiplier")
});
DataSourceClock.prototype.clone = function(result) {
if (!defined_default(result)) {
result = new DataSourceClock();
}
result.startTime = this.startTime;
result.stopTime = this.stopTime;
result.currentTime = this.currentTime;
result.clockRange = this.clockRange;
result.clockStep = this.clockStep;
result.multiplier = this.multiplier;
return result;
};
DataSourceClock.prototype.equals = function(other) {
return this === other || defined_default(other) && JulianDate_default.equals(this.startTime, other.startTime) && JulianDate_default.equals(this.stopTime, other.stopTime) && JulianDate_default.equals(this.currentTime, other.currentTime) && this.clockRange === other.clockRange && this.clockStep === other.clockStep && this.multiplier === other.multiplier;
};
DataSourceClock.prototype.merge = function(source) {
if (!defined_default(source)) {
throw new DeveloperError_default("source is required.");
}
this.startTime = this.startTime ?? source.startTime;
this.stopTime = this.stopTime ?? source.stopTime;
this.currentTime = this.currentTime ?? source.currentTime;
this.clockRange = this.clockRange ?? source.clockRange;
this.clockStep = this.clockStep ?? source.clockStep;
this.multiplier = this.multiplier ?? source.multiplier;
};
DataSourceClock.prototype.getValue = function(result) {
if (!defined_default(result)) {
result = new Clock_default();
}
result.startTime = this.startTime ?? result.startTime;
result.stopTime = this.stopTime ?? result.stopTime;
result.currentTime = this.currentTime ?? result.currentTime;
result.clockRange = this.clockRange ?? result.clockRange;
result.multiplier = this.multiplier ?? result.multiplier;
result.clockStep = this.clockStep ?? result.clockStep;
return result;
};
var DataSourceClock_default = DataSourceClock;
// packages/engine/Source/DataSources/GridMaterialProperty.js
var import_InlineWorkers855 = __toESM(require_InlineWorkers(), 1);
var defaultColor3 = Color_default.WHITE;
var defaultCellAlpha = 0.1;
var defaultLineCount = new Cartesian2_default(8, 8);
var defaultLineOffset = new Cartesian2_default(0, 0);
var defaultLineThickness = new Cartesian2_default(1, 1);
function GridMaterialProperty(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._definitionChanged = new Event_default();
this._color = void 0;
this._colorSubscription = void 0;
this._cellAlpha = void 0;
this._cellAlphaSubscription = void 0;
this._lineCount = void 0;
this._lineCountSubscription = void 0;
this._lineThickness = void 0;
this._lineThicknessSubscription = void 0;
this._lineOffset = void 0;
this._lineOffsetSubscription = void 0;
this.color = options.color;
this.cellAlpha = options.cellAlpha;
this.lineCount = options.lineCount;
this.lineThickness = options.lineThickness;
this.lineOffset = options.lineOffset;
}
Object.defineProperties(GridMaterialProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof GridMaterialProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return Property_default.isConstant(this._color) && Property_default.isConstant(this._cellAlpha) && Property_default.isConstant(this._lineCount) && Property_default.isConstant(this._lineThickness) && Property_default.isConstant(this._lineOffset);
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof GridMaterialProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the Property specifying the grid {@link Color}.
* @memberof GridMaterialProperty.prototype
* @type {Property|undefined}
* @default Color.WHITE
*/
color: createPropertyDescriptor_default("color"),
/**
* Gets or sets the numeric Property specifying cell alpha values.
* @memberof GridMaterialProperty.prototype
* @type {Property|undefined}
* @default 0.1
*/
cellAlpha: createPropertyDescriptor_default("cellAlpha"),
/**
* Gets or sets the {@link Cartesian2} Property specifying the number of grid lines along each axis.
* @memberof GridMaterialProperty.prototype
* @type {Property|undefined}
* @default new Cartesian2(8.0, 8.0)
*/
lineCount: createPropertyDescriptor_default("lineCount"),
/**
* Gets or sets the {@link Cartesian2} Property specifying the thickness of grid lines along each axis.
* @memberof GridMaterialProperty.prototype
* @type {Property|undefined}
* @default new Cartesian2(1.0, 1.0)
*/
lineThickness: createPropertyDescriptor_default("lineThickness"),
/**
* Gets or sets the {@link Cartesian2} Property specifying the starting offset of grid lines along each axis.
* @memberof GridMaterialProperty.prototype
* @type {Property|undefined}
* @default new Cartesian2(0.0, 0.0)
*/
lineOffset: createPropertyDescriptor_default("lineOffset")
});
GridMaterialProperty.prototype.getType = function(time) {
return "Grid";
};
var timeScratch14 = new JulianDate_default();
GridMaterialProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch14);
}
if (!defined_default(result)) {
result = {};
}
result.color = Property_default.getValueOrClonedDefault(
this._color,
time,
defaultColor3,
result.color
);
result.cellAlpha = Property_default.getValueOrDefault(
this._cellAlpha,
time,
defaultCellAlpha
);
result.lineCount = Property_default.getValueOrClonedDefault(
this._lineCount,
time,
defaultLineCount,
result.lineCount
);
result.lineThickness = Property_default.getValueOrClonedDefault(
this._lineThickness,
time,
defaultLineThickness,
result.lineThickness
);
result.lineOffset = Property_default.getValueOrClonedDefault(
this._lineOffset,
time,
defaultLineOffset,
result.lineOffset
);
return result;
};
GridMaterialProperty.prototype.equals = function(other) {
return this === other || //
other instanceof GridMaterialProperty && //
Property_default.equals(this._color, other._color) && //
Property_default.equals(this._cellAlpha, other._cellAlpha) && //
Property_default.equals(this._lineCount, other._lineCount) && //
Property_default.equals(this._lineThickness, other._lineThickness) && //
Property_default.equals(this._lineOffset, other._lineOffset);
};
var GridMaterialProperty_default = GridMaterialProperty;
// packages/engine/Source/DataSources/PolylineArrowMaterialProperty.js
var import_InlineWorkers856 = __toESM(require_InlineWorkers(), 1);
function PolylineArrowMaterialProperty(color) {
this._definitionChanged = new Event_default();
this._color = void 0;
this._colorSubscription = void 0;
this.color = color;
}
Object.defineProperties(PolylineArrowMaterialProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof PolylineArrowMaterialProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return Property_default.isConstant(this._color);
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof PolylineArrowMaterialProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the {@link Color} {@link Property}.
* @memberof PolylineArrowMaterialProperty.prototype
* @type {Property|undefined}
* @default Color.WHITE
*/
color: createPropertyDescriptor_default("color")
});
PolylineArrowMaterialProperty.prototype.getType = function(time) {
return "PolylineArrow";
};
var timeScratch15 = new JulianDate_default();
PolylineArrowMaterialProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch15);
}
if (!defined_default(result)) {
result = {};
}
result.color = Property_default.getValueOrClonedDefault(
this._color,
time,
Color_default.WHITE,
result.color
);
return result;
};
PolylineArrowMaterialProperty.prototype.equals = function(other) {
return this === other || //
other instanceof PolylineArrowMaterialProperty && //
Property_default.equals(this._color, other._color);
};
var PolylineArrowMaterialProperty_default = PolylineArrowMaterialProperty;
// packages/engine/Source/DataSources/PolylineDashMaterialProperty.js
var import_InlineWorkers857 = __toESM(require_InlineWorkers(), 1);
var defaultColor4 = Color_default.WHITE;
var defaultGapColor = Color_default.TRANSPARENT;
var defaultDashLength = 16;
var defaultDashPattern = 255;
function PolylineDashMaterialProperty(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._definitionChanged = new Event_default();
this._color = void 0;
this._colorSubscription = void 0;
this._gapColor = void 0;
this._gapColorSubscription = void 0;
this._dashLength = void 0;
this._dashLengthSubscription = void 0;
this._dashPattern = void 0;
this._dashPatternSubscription = void 0;
this.color = options.color;
this.gapColor = options.gapColor;
this.dashLength = options.dashLength;
this.dashPattern = options.dashPattern;
}
Object.defineProperties(PolylineDashMaterialProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof PolylineDashMaterialProperty.prototype
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return Property_default.isConstant(this._color) && Property_default.isConstant(this._gapColor) && Property_default.isConstant(this._dashLength) && Property_default.isConstant(this._dashPattern);
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof PolylineDashMaterialProperty.prototype
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the Property specifying the {@link Color} of the line.
* @memberof PolylineDashMaterialProperty.prototype
* @type {Property|undefined}
*/
color: createPropertyDescriptor_default("color"),
/**
* Gets or sets the Property specifying the {@link Color} of the gaps in the line.
* @memberof PolylineDashMaterialProperty.prototype
* @type {Property|undefined}
*/
gapColor: createPropertyDescriptor_default("gapColor"),
/**
* Gets or sets the numeric Property specifying the length of a dash cycle
* @memberof PolylineDashMaterialProperty.prototype
* @type {Property|undefined}
*/
dashLength: createPropertyDescriptor_default("dashLength"),
/**
* Gets or sets the numeric Property specifying a dash pattern
* @memberof PolylineDashMaterialProperty.prototype
* @type {Property|undefined}
*/
dashPattern: createPropertyDescriptor_default("dashPattern")
});
PolylineDashMaterialProperty.prototype.getType = function(time) {
return "PolylineDash";
};
var timeScratch16 = new JulianDate_default();
PolylineDashMaterialProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch16);
}
if (!defined_default(result)) {
result = {};
}
result.color = Property_default.getValueOrClonedDefault(
this._color,
time,
defaultColor4,
result.color
);
result.gapColor = Property_default.getValueOrClonedDefault(
this._gapColor,
time,
defaultGapColor,
result.gapColor
);
result.dashLength = Property_default.getValueOrDefault(
this._dashLength,
time,
defaultDashLength,
result.dashLength
);
result.dashPattern = Property_default.getValueOrDefault(
this._dashPattern,
time,
defaultDashPattern,
result.dashPattern
);
return result;
};
PolylineDashMaterialProperty.prototype.equals = function(other) {
return this === other || //
other instanceof PolylineDashMaterialProperty && Property_default.equals(this._color, other._color) && Property_default.equals(this._gapColor, other._gapColor) && Property_default.equals(this._dashLength, other._dashLength) && Property_default.equals(this._dashPattern, other._dashPattern);
};
var PolylineDashMaterialProperty_default = PolylineDashMaterialProperty;
// packages/engine/Source/DataSources/PolylineGlowMaterialProperty.js
var import_InlineWorkers858 = __toESM(require_InlineWorkers(), 1);
var defaultColor5 = Color_default.WHITE;
var defaultGlowPower = 0.25;
var defaultTaperPower = 1;
function PolylineGlowMaterialProperty(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._definitionChanged = new Event_default();
this._color = void 0;
this._colorSubscription = void 0;
this._glowPower = void 0;
this._glowPowerSubscription = void 0;
this._taperPower = void 0;
this._taperPowerSubscription = void 0;
this.color = options.color;
this.glowPower = options.glowPower;
this.taperPower = options.taperPower;
}
Object.defineProperties(PolylineGlowMaterialProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof PolylineGlowMaterialProperty.prototype
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return Property_default.isConstant(this._color) && Property_default.isConstant(this._glow);
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof PolylineGlowMaterialProperty.prototype
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the Property specifying the {@link Color} of the line.
* @memberof PolylineGlowMaterialProperty.prototype
* @type {Property|undefined}
*/
color: createPropertyDescriptor_default("color"),
/**
* Gets or sets the numeric Property specifying the strength of the glow, as a percentage of the total line width (less than 1.0).
* @memberof PolylineGlowMaterialProperty.prototype
* @type {Property|undefined}
*/
glowPower: createPropertyDescriptor_default("glowPower"),
/**
* Gets or sets the numeric Property specifying the strength of the tapering effect, as a percentage of the total line length. If 1.0 or higher, no taper effect is used.
* @memberof PolylineGlowMaterialProperty.prototype
* @type {Property|undefined}
*/
taperPower: createPropertyDescriptor_default("taperPower")
});
PolylineGlowMaterialProperty.prototype.getType = function(time) {
return "PolylineGlow";
};
var timeScratch17 = new JulianDate_default();
PolylineGlowMaterialProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch17);
}
if (!defined_default(result)) {
result = {};
}
result.color = Property_default.getValueOrClonedDefault(
this._color,
time,
defaultColor5,
result.color
);
result.glowPower = Property_default.getValueOrDefault(
this._glowPower,
time,
defaultGlowPower,
result.glowPower
);
result.taperPower = Property_default.getValueOrDefault(
this._taperPower,
time,
defaultTaperPower,
result.taperPower
);
return result;
};
PolylineGlowMaterialProperty.prototype.equals = function(other) {
return this === other || other instanceof PolylineGlowMaterialProperty && Property_default.equals(this._color, other._color) && Property_default.equals(this._glowPower, other._glowPower) && Property_default.equals(this._taperPower, other._taperPower);
};
var PolylineGlowMaterialProperty_default = PolylineGlowMaterialProperty;
// packages/engine/Source/DataSources/PolylineOutlineMaterialProperty.js
var import_InlineWorkers859 = __toESM(require_InlineWorkers(), 1);
var defaultColor6 = Color_default.WHITE;
var defaultOutlineColor2 = Color_default.BLACK;
var defaultOutlineWidth = 1;
function PolylineOutlineMaterialProperty(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._definitionChanged = new Event_default();
this._color = void 0;
this._colorSubscription = void 0;
this._outlineColor = void 0;
this._outlineColorSubscription = void 0;
this._outlineWidth = void 0;
this._outlineWidthSubscription = void 0;
this.color = options.color;
this.outlineColor = options.outlineColor;
this.outlineWidth = options.outlineWidth;
}
Object.defineProperties(PolylineOutlineMaterialProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof PolylineOutlineMaterialProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return Property_default.isConstant(this._color) && Property_default.isConstant(this._outlineColor) && Property_default.isConstant(this._outlineWidth);
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof PolylineOutlineMaterialProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the Property specifying the {@link Color} of the line.
* @memberof PolylineOutlineMaterialProperty.prototype
* @type {Property|undefined}
* @default Color.WHITE
*/
color: createPropertyDescriptor_default("color"),
/**
* Gets or sets the Property specifying the {@link Color} of the outline.
* @memberof PolylineOutlineMaterialProperty.prototype
* @type {Property|undefined}
* @default Color.BLACK
*/
outlineColor: createPropertyDescriptor_default("outlineColor"),
/**
* Gets or sets the numeric Property specifying the width of the outline.
* @memberof PolylineOutlineMaterialProperty.prototype
* @type {Property|undefined}
* @default 1.0
*/
outlineWidth: createPropertyDescriptor_default("outlineWidth")
});
PolylineOutlineMaterialProperty.prototype.getType = function(time) {
return "PolylineOutline";
};
var timeScratch18 = new JulianDate_default();
PolylineOutlineMaterialProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch18);
}
if (!defined_default(result)) {
result = {};
}
result.color = Property_default.getValueOrClonedDefault(
this._color,
time,
defaultColor6,
result.color
);
result.outlineColor = Property_default.getValueOrClonedDefault(
this._outlineColor,
time,
defaultOutlineColor2,
result.outlineColor
);
result.outlineWidth = Property_default.getValueOrDefault(
this._outlineWidth,
time,
defaultOutlineWidth
);
return result;
};
PolylineOutlineMaterialProperty.prototype.equals = function(other) {
return this === other || //
other instanceof PolylineOutlineMaterialProperty && //
Property_default.equals(this._color, other._color) && //
Property_default.equals(this._outlineColor, other._outlineColor) && //
Property_default.equals(this._outlineWidth, other._outlineWidth);
};
var PolylineOutlineMaterialProperty_default = PolylineOutlineMaterialProperty;
// packages/engine/Source/DataSources/PositionPropertyArray.js
var import_InlineWorkers860 = __toESM(require_InlineWorkers(), 1);
function PositionPropertyArray(value, referenceFrame) {
this._value = void 0;
this._definitionChanged = new Event_default();
this._eventHelper = new EventHelper_default();
this._referenceFrame = referenceFrame ?? ReferenceFrame_default.FIXED;
this.setValue(value);
}
Object.defineProperties(PositionPropertyArray.prototype, {
/**
* Gets a value indicating if this property is constant. This property
* is considered constant if all property items in the array are constant.
* @memberof PositionPropertyArray.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
const value = this._value;
if (!defined_default(value)) {
return true;
}
const length2 = value.length;
for (let i = 0; i < length2; i++) {
if (!Property_default.isConstant(value[i])) {
return false;
}
}
return true;
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is changed whenever setValue is called with data different
* than the current value or one of the properties in the array also changes.
* @memberof PositionPropertyArray.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets the reference frame in which the position is defined.
* @memberof PositionPropertyArray.prototype
* @type {ReferenceFrame}
* @default ReferenceFrame.FIXED;
*/
referenceFrame: {
get: function() {
return this._referenceFrame;
}
}
});
var timeScratch19 = new JulianDate_default();
PositionPropertyArray.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch19);
}
return this.getValueInReferenceFrame(time, ReferenceFrame_default.FIXED, result);
};
PositionPropertyArray.prototype.getValueInReferenceFrame = function(time, referenceFrame, result) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required.");
}
if (!defined_default(referenceFrame)) {
throw new DeveloperError_default("referenceFrame is required.");
}
const value = this._value;
if (!defined_default(value)) {
return void 0;
}
const length2 = value.length;
if (!defined_default(result)) {
result = new Array(length2);
}
let i = 0;
let x = 0;
while (i < length2) {
const property = value[i];
const itemValue = property.getValueInReferenceFrame(
time,
referenceFrame,
result[i]
);
if (defined_default(itemValue)) {
result[x] = itemValue;
x++;
}
i++;
}
result.length = x;
return result;
};
PositionPropertyArray.prototype.setValue = function(value) {
const eventHelper = this._eventHelper;
eventHelper.removeAll();
if (defined_default(value)) {
this._value = value.slice();
const length2 = value.length;
for (let i = 0; i < length2; i++) {
const property = value[i];
if (defined_default(property)) {
eventHelper.add(
property.definitionChanged,
PositionPropertyArray.prototype._raiseDefinitionChanged,
this
);
}
}
} else {
this._value = void 0;
}
this._definitionChanged.raiseEvent(this);
};
PositionPropertyArray.prototype.equals = function(other) {
return this === other || //
other instanceof PositionPropertyArray && //
this._referenceFrame === other._referenceFrame && //
Property_default.arrayEquals(this._value, other._value);
};
PositionPropertyArray.prototype._raiseDefinitionChanged = function() {
this._definitionChanged.raiseEvent(this);
};
var PositionPropertyArray_default = PositionPropertyArray;
// packages/engine/Source/DataSources/PropertyArray.js
var import_InlineWorkers861 = __toESM(require_InlineWorkers(), 1);
function PropertyArray(value) {
this._value = void 0;
this._definitionChanged = new Event_default();
this._eventHelper = new EventHelper_default();
this.setValue(value);
}
Object.defineProperties(PropertyArray.prototype, {
/**
* Gets a value indicating if this property is constant. This property
* is considered constant if all property items in the array are constant.
* @memberof PropertyArray.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
const value = this._value;
if (!defined_default(value)) {
return true;
}
const length2 = value.length;
for (let i = 0; i < length2; i++) {
if (!Property_default.isConstant(value[i])) {
return false;
}
}
return true;
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is changed whenever setValue is called with data different
* than the current value or one of the properties in the array also changes.
* @memberof PropertyArray.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
}
});
var timeScratch20 = new JulianDate_default();
PropertyArray.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch20);
}
const value = this._value;
if (!defined_default(value)) {
return void 0;
}
const length2 = value.length;
if (!defined_default(result)) {
result = new Array(length2);
}
let i = 0;
let x = 0;
while (i < length2) {
const property = this._value[i];
const itemValue = property.getValue(time, result[i]);
if (defined_default(itemValue)) {
result[x] = itemValue;
x++;
}
i++;
}
result.length = x;
return result;
};
PropertyArray.prototype.setValue = function(value) {
const eventHelper = this._eventHelper;
eventHelper.removeAll();
if (defined_default(value)) {
this._value = value.slice();
const length2 = value.length;
for (let i = 0; i < length2; i++) {
const property = value[i];
if (defined_default(property)) {
eventHelper.add(
property.definitionChanged,
PropertyArray.prototype._raiseDefinitionChanged,
this
);
}
}
} else {
this._value = void 0;
}
this._definitionChanged.raiseEvent(this);
};
PropertyArray.prototype.equals = function(other) {
return this === other || //
other instanceof PropertyArray && //
Property_default.arrayEquals(this._value, other._value);
};
PropertyArray.prototype._raiseDefinitionChanged = function() {
this._definitionChanged.raiseEvent(this);
};
var PropertyArray_default = PropertyArray;
// packages/engine/Source/DataSources/ReferenceProperty.js
var import_InlineWorkers862 = __toESM(require_InlineWorkers(), 1);
function resolve(that) {
let targetProperty = that._targetProperty;
if (!defined_default(targetProperty)) {
let targetEntity = that._targetEntity;
if (!defined_default(targetEntity)) {
targetEntity = that._targetCollection.getById(that._targetId);
if (!defined_default(targetEntity)) {
that._targetEntity = that._targetProperty = void 0;
return;
}
targetEntity.definitionChanged.addEventListener(
ReferenceProperty.prototype._onTargetEntityDefinitionChanged,
that
);
that._targetEntity = targetEntity;
}
const targetPropertyNames = that._targetPropertyNames;
targetProperty = that._targetEntity;
for (let i = 0, len = targetPropertyNames.length; i < len && defined_default(targetProperty); ++i) {
targetProperty = targetProperty[targetPropertyNames[i]];
}
that._targetProperty = targetProperty;
}
return targetProperty;
}
function ReferenceProperty(targetCollection, targetId, targetPropertyNames) {
if (!defined_default(targetCollection)) {
throw new DeveloperError_default("targetCollection is required.");
}
if (!defined_default(targetId) || targetId === "") {
throw new DeveloperError_default("targetId is required.");
}
if (!defined_default(targetPropertyNames) || targetPropertyNames.length === 0) {
throw new DeveloperError_default("targetPropertyNames is required.");
}
for (let i = 0; i < targetPropertyNames.length; i++) {
const item = targetPropertyNames[i];
if (!defined_default(item) || item === "") {
throw new DeveloperError_default("reference contains invalid properties.");
}
}
this._targetCollection = targetCollection;
this._targetId = targetId;
this._targetPropertyNames = targetPropertyNames;
this._targetProperty = void 0;
this._targetEntity = void 0;
this._definitionChanged = new Event_default();
targetCollection.collectionChanged.addEventListener(
ReferenceProperty.prototype._onCollectionChanged,
this
);
}
Object.defineProperties(ReferenceProperty.prototype, {
/**
* Gets a value indicating if this property is constant.
* @memberof ReferenceProperty.prototype
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return Property_default.isConstant(resolve(this));
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is changed whenever the referenced property's definition is changed.
* @memberof ReferenceProperty.prototype
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets the reference frame that the position is defined in.
* This property is only valid if the referenced property is a {@link PositionProperty}.
* @memberof ReferenceProperty.prototype
* @type {ReferenceFrame}
* @readonly
*/
referenceFrame: {
get: function() {
const target = resolve(this);
return defined_default(target) ? target.referenceFrame : void 0;
}
},
/**
* Gets the id of the entity being referenced.
* @memberof ReferenceProperty.prototype
* @type {string}
* @readonly
*/
targetId: {
get: function() {
return this._targetId;
}
},
/**
* Gets the collection containing the entity being referenced.
* @memberof ReferenceProperty.prototype
* @type {EntityCollection}
* @readonly
*/
targetCollection: {
get: function() {
return this._targetCollection;
}
},
/**
* Gets the array of property names used to retrieve the referenced property.
* @memberof ReferenceProperty.prototype
* @type {}
* @readonly
*/
targetPropertyNames: {
get: function() {
return this._targetPropertyNames;
}
},
/**
* Gets the resolved instance of the underlying referenced property.
* @memberof ReferenceProperty.prototype
* @type {Property|undefined}
* @readonly
*/
resolvedProperty: {
get: function() {
return resolve(this);
}
}
});
ReferenceProperty.fromString = function(targetCollection, referenceString) {
if (!defined_default(targetCollection)) {
throw new DeveloperError_default("targetCollection is required.");
}
if (!defined_default(referenceString)) {
throw new DeveloperError_default("referenceString is required.");
}
let identifier;
const values = [];
let inIdentifier = true;
let isEscaped = false;
let token = "";
for (let i = 0; i < referenceString.length; ++i) {
const c = referenceString.charAt(i);
if (isEscaped) {
token += c;
isEscaped = false;
} else if (c === "\\") {
isEscaped = true;
} else if (inIdentifier && c === "#") {
identifier = token;
inIdentifier = false;
token = "";
} else if (!inIdentifier && c === ".") {
values.push(token);
token = "";
} else {
token += c;
}
}
values.push(token);
return new ReferenceProperty(targetCollection, identifier, values);
};
var timeScratch21 = new JulianDate_default();
ReferenceProperty.prototype.getValue = function(time, result) {
const target = resolve(this);
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch21);
}
return defined_default(target) ? target.getValue(time, result) : void 0;
};
ReferenceProperty.prototype.getValueInReferenceFrame = function(time, referenceFrame, result) {
const target = resolve(this);
return defined_default(target) ? target.getValueInReferenceFrame(time, referenceFrame, result) : void 0;
};
ReferenceProperty.prototype.getType = function(time) {
const target = resolve(this);
return defined_default(target) ? target.getType(time) : void 0;
};
ReferenceProperty.prototype.equals = function(other) {
if (this === other) {
return true;
}
const names = this._targetPropertyNames;
const otherNames = other._targetPropertyNames;
if (this._targetCollection !== other._targetCollection || //
this._targetId !== other._targetId || //
names.length !== otherNames.length) {
return false;
}
const length2 = this._targetPropertyNames.length;
for (let i = 0; i < length2; i++) {
if (names[i] !== otherNames[i]) {
return false;
}
}
return true;
};
ReferenceProperty.prototype._onTargetEntityDefinitionChanged = function(targetEntity, name, value, oldValue2) {
if (defined_default(this._targetProperty) && this._targetPropertyNames[0] === name) {
this._targetProperty = void 0;
this._definitionChanged.raiseEvent(this);
}
};
ReferenceProperty.prototype._onCollectionChanged = function(collection, added, removed) {
let targetEntity = this._targetEntity;
if (defined_default(targetEntity) && removed.indexOf(targetEntity) !== -1) {
targetEntity.definitionChanged.removeEventListener(
ReferenceProperty.prototype._onTargetEntityDefinitionChanged,
this
);
this._targetEntity = this._targetProperty = void 0;
} else if (!defined_default(targetEntity)) {
targetEntity = resolve(this);
if (defined_default(targetEntity)) {
this._definitionChanged.raiseEvent(this);
}
}
};
var ReferenceProperty_default = ReferenceProperty;
// packages/engine/Source/DataSources/Rotation.js
var import_InlineWorkers863 = __toESM(require_InlineWorkers(), 1);
var Rotation = {
/**
* The number of elements used to pack the object into an array.
* @type {number}
*/
packedLength: 1,
/**
* Stores the provided instance into the provided array.
*
* @param {Rotation} value The value to pack.
* @param {number[]} array The array to pack into.
* @param {number} [startingIndex=0] The index into the array at which to start packing the elements.
*
* @returns {number[]} The array that was packed into
*/
pack: function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
array[startingIndex] = value;
return array;
},
/**
* Retrieves an instance from a packed array.
*
* @param {number[]} array The packed array.
* @param {number} [startingIndex=0] The starting index of the element to be unpacked.
* @param {Rotation} [result] The object into which to store the result.
* @returns {Rotation} The modified result parameter or a new Rotation instance if one was not provided.
*/
unpack: function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
return array[startingIndex];
},
/**
* Converts a packed array into a form suitable for interpolation.
*
* @param {number[]} packedArray The packed array.
* @param {number} [startingIndex=0] The index of the first element to be converted.
* @param {number} [lastIndex=packedArray.length] The index of the last element to be converted.
* @param {number[]} [result] The object into which to store the result.
*/
convertPackedArrayForInterpolation: function(packedArray, startingIndex, lastIndex, result) {
if (!defined_default(packedArray)) {
throw new DeveloperError_default("packedArray is required");
}
if (!defined_default(result)) {
result = [];
}
startingIndex = startingIndex ?? 0;
lastIndex = lastIndex ?? packedArray.length;
let previousValue;
for (let i = 0, len = lastIndex - startingIndex + 1; i < len; i++) {
const value = packedArray[startingIndex + i];
if (i === 0 || Math.abs(previousValue - value) < Math.PI) {
result[i] = value;
} else {
result[i] = value - Math_default.TWO_PI;
}
previousValue = value;
}
},
/**
* Retrieves an instance from a packed array converted with {@link Rotation.convertPackedArrayForInterpolation}.
*
* @param {number[]} array The array previously packed for interpolation.
* @param {number[]} sourceArray The original packed array.
* @param {number} [firstIndex=0] The firstIndex used to convert the array.
* @param {number} [lastIndex=packedArray.length] The lastIndex used to convert the array.
* @param {Rotation} [result] The object into which to store the result.
* @returns {Rotation} The modified result parameter or a new Rotation instance if one was not provided.
*/
unpackInterpolationResult: function(array, sourceArray, firstIndex, lastIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
if (!defined_default(sourceArray)) {
throw new DeveloperError_default("sourceArray is required");
}
result = array[0];
if (result < 0) {
return result + Math_default.TWO_PI;
}
return result;
}
};
var Rotation_default = Rotation;
// packages/engine/Source/DataSources/SampledPositionProperty.js
var import_InlineWorkers865 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/SampledProperty.js
var import_InlineWorkers864 = __toESM(require_InlineWorkers(), 1);
var PackableNumber = {
packedLength: 1,
pack: function(value, array, startingIndex) {
startingIndex = startingIndex ?? 0;
array[startingIndex] = value;
},
unpack: function(array, startingIndex, result) {
startingIndex = startingIndex ?? 0;
return array[startingIndex];
}
};
function arrayInsert(array, startIndex, items) {
let i;
const arrayLength = array.length;
const itemsLength = items.length;
const newLength = arrayLength + itemsLength;
array.length = newLength;
if (arrayLength !== startIndex) {
let q = arrayLength - 1;
for (i = newLength - 1; i >= startIndex; i--) {
array[i] = array[q--];
}
}
for (i = 0; i < itemsLength; i++) {
array[startIndex++] = items[i];
}
}
function convertDate(date, epoch2) {
if (date instanceof JulianDate_default) {
return date;
}
if (typeof date === "string") {
return JulianDate_default.fromIso8601(date);
}
return JulianDate_default.addSeconds(epoch2, date, new JulianDate_default());
}
var timesSpliceArgs = [];
var valuesSpliceArgs = [];
function mergeNewSamples(epoch2, times, values, newData, packedLength) {
let newDataIndex = 0;
let i;
let prevItem;
let timesInsertionPoint;
let valuesInsertionPoint;
let currentTime;
let nextTime;
while (newDataIndex < newData.length) {
currentTime = convertDate(newData[newDataIndex], epoch2);
timesInsertionPoint = binarySearch_default(times, currentTime, JulianDate_default.compare);
let timesSpliceArgsCount = 0;
let valuesSpliceArgsCount = 0;
if (timesInsertionPoint < 0) {
timesInsertionPoint = ~timesInsertionPoint;
valuesInsertionPoint = timesInsertionPoint * packedLength;
prevItem = void 0;
nextTime = times[timesInsertionPoint];
while (newDataIndex < newData.length) {
currentTime = convertDate(newData[newDataIndex], epoch2);
if (defined_default(prevItem) && JulianDate_default.compare(prevItem, currentTime) >= 0 || defined_default(nextTime) && JulianDate_default.compare(currentTime, nextTime) >= 0) {
break;
}
timesSpliceArgs[timesSpliceArgsCount++] = currentTime;
newDataIndex = newDataIndex + 1;
for (i = 0; i < packedLength; i++) {
valuesSpliceArgs[valuesSpliceArgsCount++] = newData[newDataIndex];
newDataIndex = newDataIndex + 1;
}
prevItem = currentTime;
}
if (timesSpliceArgsCount > 0) {
valuesSpliceArgs.length = valuesSpliceArgsCount;
arrayInsert(values, valuesInsertionPoint, valuesSpliceArgs);
timesSpliceArgs.length = timesSpliceArgsCount;
arrayInsert(times, timesInsertionPoint, timesSpliceArgs);
}
} else {
for (i = 0; i < packedLength; i++) {
newDataIndex++;
values[timesInsertionPoint * packedLength + i] = newData[newDataIndex];
}
newDataIndex++;
}
}
}
function SampledProperty(type, derivativeTypes) {
Check_default.defined("type", type);
let innerType = type;
if (innerType === Number) {
innerType = PackableNumber;
}
let packedLength = innerType.packedLength;
let packedInterpolationLength = innerType.packedInterpolationLength ?? packedLength;
let inputOrder = 0;
let innerDerivativeTypes;
if (defined_default(derivativeTypes)) {
const length2 = derivativeTypes.length;
innerDerivativeTypes = new Array(length2);
for (let i = 0; i < length2; i++) {
let derivativeType = derivativeTypes[i];
if (derivativeType === Number) {
derivativeType = PackableNumber;
}
const derivativePackedLength = derivativeType.packedLength;
packedLength += derivativePackedLength;
packedInterpolationLength += derivativeType.packedInterpolationLength ?? derivativePackedLength;
innerDerivativeTypes[i] = derivativeType;
}
inputOrder = length2;
}
this._type = type;
this._innerType = innerType;
this._interpolationDegree = 1;
this._interpolationAlgorithm = LinearApproximation_default;
this._numberOfPoints = 0;
this._times = [];
this._values = [];
this._xTable = [];
this._yTable = [];
this._packedLength = packedLength;
this._packedInterpolationLength = packedInterpolationLength;
this._updateTableLength = true;
this._interpolationResult = new Array(packedInterpolationLength);
this._definitionChanged = new Event_default();
this._derivativeTypes = derivativeTypes;
this._innerDerivativeTypes = innerDerivativeTypes;
this._inputOrder = inputOrder;
this._forwardExtrapolationType = ExtrapolationType_default.NONE;
this._forwardExtrapolationDuration = 0;
this._backwardExtrapolationType = ExtrapolationType_default.NONE;
this._backwardExtrapolationDuration = 0;
}
Object.defineProperties(SampledProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof SampledProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return this._values.length === 0;
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof SampledProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets the type of property.
* @memberof SampledProperty.prototype
* @type {*}
*/
type: {
get: function() {
return this._type;
}
},
/**
* Gets the derivative types used by this property.
* @memberof SampledProperty.prototype
* @type {Packable[]}
*/
derivativeTypes: {
get: function() {
return this._derivativeTypes;
}
},
/**
* Gets the degree of interpolation to perform when retrieving a value.
* @memberof SampledProperty.prototype
* @type {number}
* @default 1
*/
interpolationDegree: {
get: function() {
return this._interpolationDegree;
}
},
/**
* Gets the interpolation algorithm to use when retrieving a value.
* @memberof SampledProperty.prototype
* @type {InterpolationAlgorithm}
* @default LinearApproximation
*/
interpolationAlgorithm: {
get: function() {
return this._interpolationAlgorithm;
}
},
/**
* Gets or sets the type of extrapolation to perform when a value
* is requested at a time after any available samples.
* @memberof SampledProperty.prototype
* @type {ExtrapolationType}
* @default ExtrapolationType.NONE
*/
forwardExtrapolationType: {
get: function() {
return this._forwardExtrapolationType;
},
set: function(value) {
if (this._forwardExtrapolationType !== value) {
this._forwardExtrapolationType = value;
this._definitionChanged.raiseEvent(this);
}
}
},
/**
* Gets or sets the amount of time to extrapolate forward before
* the property becomes undefined. A value of 0 will extrapolate forever.
* @memberof SampledProperty.prototype
* @type {number}
* @default 0
*/
forwardExtrapolationDuration: {
get: function() {
return this._forwardExtrapolationDuration;
},
set: function(value) {
if (this._forwardExtrapolationDuration !== value) {
this._forwardExtrapolationDuration = value;
this._definitionChanged.raiseEvent(this);
}
}
},
/**
* Gets or sets the type of extrapolation to perform when a value
* is requested at a time before any available samples.
* @memberof SampledProperty.prototype
* @type {ExtrapolationType}
* @default ExtrapolationType.NONE
*/
backwardExtrapolationType: {
get: function() {
return this._backwardExtrapolationType;
},
set: function(value) {
if (this._backwardExtrapolationType !== value) {
this._backwardExtrapolationType = value;
this._definitionChanged.raiseEvent(this);
}
}
},
/**
* Gets or sets the amount of time to extrapolate backward
* before the property becomes undefined. A value of 0 will extrapolate forever.
* @memberof SampledProperty.prototype
* @type {number}
* @default 0
*/
backwardExtrapolationDuration: {
get: function() {
return this._backwardExtrapolationDuration;
},
set: function(value) {
if (this._backwardExtrapolationDuration !== value) {
this._backwardExtrapolationDuration = value;
this._definitionChanged.raiseEvent(this);
}
}
}
});
var timeScratch22 = new JulianDate_default();
SampledProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch22);
}
const times = this._times;
const timesLength = times.length;
if (timesLength === 0) {
return void 0;
}
let timeout;
const innerType = this._innerType;
const values = this._values;
let index = binarySearch_default(times, time, JulianDate_default.compare);
if (index < 0) {
index = ~index;
if (index === 0) {
const startTime = times[index];
timeout = this._backwardExtrapolationDuration;
if (this._backwardExtrapolationType === ExtrapolationType_default.NONE || timeout !== 0 && JulianDate_default.secondsDifference(startTime, time) > timeout) {
return void 0;
}
if (this._backwardExtrapolationType === ExtrapolationType_default.HOLD) {
return innerType.unpack(values, 0, result);
}
}
if (index >= timesLength) {
index = timesLength - 1;
const endTime = times[index];
timeout = this._forwardExtrapolationDuration;
if (this._forwardExtrapolationType === ExtrapolationType_default.NONE || timeout !== 0 && JulianDate_default.secondsDifference(time, endTime) > timeout) {
return void 0;
}
if (this._forwardExtrapolationType === ExtrapolationType_default.HOLD) {
index = timesLength - 1;
return innerType.unpack(values, index * innerType.packedLength, result);
}
}
const xTable = this._xTable;
const yTable = this._yTable;
const interpolationAlgorithm = this._interpolationAlgorithm;
const packedInterpolationLength = this._packedInterpolationLength;
const inputOrder = this._inputOrder;
if (this._updateTableLength) {
this._updateTableLength = false;
const numberOfPoints = Math.min(
interpolationAlgorithm.getRequiredDataPoints(
this._interpolationDegree,
inputOrder
),
timesLength
);
if (numberOfPoints !== this._numberOfPoints) {
this._numberOfPoints = numberOfPoints;
xTable.length = numberOfPoints;
yTable.length = numberOfPoints * packedInterpolationLength;
}
}
const degree = this._numberOfPoints - 1;
if (degree < 1) {
return void 0;
}
let firstIndex = 0;
let lastIndex = timesLength - 1;
const pointsInCollection = lastIndex - firstIndex + 1;
if (pointsInCollection >= degree + 1) {
let computedFirstIndex = index - (degree / 2 | 0) - 1;
if (computedFirstIndex < firstIndex) {
computedFirstIndex = firstIndex;
}
let computedLastIndex = computedFirstIndex + degree;
if (computedLastIndex > lastIndex) {
computedLastIndex = lastIndex;
computedFirstIndex = computedLastIndex - degree;
if (computedFirstIndex < firstIndex) {
computedFirstIndex = firstIndex;
}
}
firstIndex = computedFirstIndex;
lastIndex = computedLastIndex;
}
const length2 = lastIndex - firstIndex + 1;
for (let i = 0; i < length2; ++i) {
xTable[i] = JulianDate_default.secondsDifference(
times[firstIndex + i],
times[lastIndex]
);
}
if (!defined_default(innerType.convertPackedArrayForInterpolation)) {
let destinationIndex = 0;
const packedLength = this._packedLength;
let sourceIndex = firstIndex * packedLength;
const stop2 = (lastIndex + 1) * packedLength;
while (sourceIndex < stop2) {
yTable[destinationIndex] = values[sourceIndex];
sourceIndex++;
destinationIndex++;
}
} else {
innerType.convertPackedArrayForInterpolation(
values,
firstIndex,
lastIndex,
yTable
);
}
const x = JulianDate_default.secondsDifference(time, times[lastIndex]);
let interpolationResult;
if (inputOrder === 0 || !defined_default(interpolationAlgorithm.interpolate)) {
interpolationResult = interpolationAlgorithm.interpolateOrderZero(
x,
xTable,
yTable,
packedInterpolationLength,
this._interpolationResult
);
} else {
const yStride = Math.floor(packedInterpolationLength / (inputOrder + 1));
interpolationResult = interpolationAlgorithm.interpolate(
x,
xTable,
yTable,
yStride,
inputOrder,
inputOrder,
this._interpolationResult
);
}
if (!defined_default(innerType.unpackInterpolationResult)) {
return innerType.unpack(interpolationResult, 0, result);
}
return innerType.unpackInterpolationResult(
interpolationResult,
values,
firstIndex,
lastIndex,
result
);
}
return innerType.unpack(values, index * this._packedLength, result);
};
SampledProperty.prototype.setInterpolationOptions = function(options) {
if (!defined_default(options)) {
return;
}
let valuesChanged = false;
const interpolationAlgorithm = options.interpolationAlgorithm;
const interpolationDegree = options.interpolationDegree;
if (defined_default(interpolationAlgorithm) && this._interpolationAlgorithm !== interpolationAlgorithm) {
this._interpolationAlgorithm = interpolationAlgorithm;
valuesChanged = true;
}
if (defined_default(interpolationDegree) && this._interpolationDegree !== interpolationDegree) {
this._interpolationDegree = interpolationDegree;
valuesChanged = true;
}
if (valuesChanged) {
this._updateTableLength = true;
this._definitionChanged.raiseEvent(this);
}
};
SampledProperty.prototype.addSample = function(time, value, derivatives) {
const innerDerivativeTypes = this._innerDerivativeTypes;
const hasDerivatives = defined_default(innerDerivativeTypes);
Check_default.defined("time", time);
Check_default.defined("value", value);
if (hasDerivatives) {
Check_default.defined("derivatives", derivatives);
}
const innerType = this._innerType;
const data = [];
data.push(time);
innerType.pack(value, data, data.length);
if (hasDerivatives) {
const derivativesLength = innerDerivativeTypes.length;
for (let x = 0; x < derivativesLength; x++) {
innerDerivativeTypes[x].pack(derivatives[x], data, data.length);
}
}
mergeNewSamples(
void 0,
this._times,
this._values,
data,
this._packedLength
);
this._updateTableLength = true;
this._definitionChanged.raiseEvent(this);
};
SampledProperty.prototype.addSamples = function(times, values, derivativeValues) {
const innerDerivativeTypes = this._innerDerivativeTypes;
const hasDerivatives = defined_default(innerDerivativeTypes);
Check_default.defined("times", times);
Check_default.defined("values", values);
if (times.length !== values.length) {
throw new DeveloperError_default("times and values must be the same length.");
}
if (hasDerivatives && (!defined_default(derivativeValues) || derivativeValues.length !== times.length)) {
throw new DeveloperError_default(
"times and derivativeValues must be the same length."
);
}
const innerType = this._innerType;
const length2 = times.length;
const data = [];
for (let i = 0; i < length2; i++) {
data.push(times[i]);
innerType.pack(values[i], data, data.length);
if (hasDerivatives) {
const derivatives = derivativeValues[i];
const derivativesLength = innerDerivativeTypes.length;
for (let x = 0; x < derivativesLength; x++) {
innerDerivativeTypes[x].pack(derivatives[x], data, data.length);
}
}
}
mergeNewSamples(
void 0,
this._times,
this._values,
data,
this._packedLength
);
this._updateTableLength = true;
this._definitionChanged.raiseEvent(this);
};
SampledProperty.prototype.getSample = function(index) {
Check_default.typeOf.number("index", index);
const times = this._times;
const len = times.length;
if (!defined_default(len)) {
return void 0;
}
if (index < 0) {
index += len;
}
return times[index];
};
SampledProperty.prototype.addSamplesPackedArray = function(packedSamples, epoch2) {
Check_default.defined("packedSamples", packedSamples);
mergeNewSamples(
epoch2,
this._times,
this._values,
packedSamples,
this._packedLength
);
this._updateTableLength = true;
this._definitionChanged.raiseEvent(this);
};
SampledProperty.prototype.removeSample = function(time) {
Check_default.defined("time", time);
const index = binarySearch_default(this._times, time, JulianDate_default.compare);
if (index < 0) {
return false;
}
removeSamples(this, index, 1);
return true;
};
function removeSamples(property, startIndex, numberToRemove) {
const packedLength = property._packedLength;
property._times.splice(startIndex, numberToRemove);
property._values.splice(
startIndex * packedLength,
numberToRemove * packedLength
);
property._updateTableLength = true;
property._definitionChanged.raiseEvent(property);
}
SampledProperty.prototype.removeSamples = function(timeInterval) {
Check_default.defined("timeInterval", timeInterval);
const times = this._times;
let startIndex = binarySearch_default(times, timeInterval.start, JulianDate_default.compare);
if (startIndex < 0) {
startIndex = ~startIndex;
} else if (!timeInterval.isStartIncluded) {
++startIndex;
}
let stopIndex = binarySearch_default(times, timeInterval.stop, JulianDate_default.compare);
if (stopIndex < 0) {
stopIndex = ~stopIndex;
} else if (timeInterval.isStopIncluded) {
++stopIndex;
}
removeSamples(this, startIndex, stopIndex - startIndex);
};
SampledProperty.prototype.equals = function(other) {
if (this === other) {
return true;
}
if (!defined_default(other)) {
return false;
}
if (this._type !== other._type || //
this._interpolationDegree !== other._interpolationDegree || //
this._interpolationAlgorithm !== other._interpolationAlgorithm) {
return false;
}
const derivativeTypes = this._derivativeTypes;
const hasDerivatives = defined_default(derivativeTypes);
const otherDerivativeTypes = other._derivativeTypes;
const otherHasDerivatives = defined_default(otherDerivativeTypes);
if (hasDerivatives !== otherHasDerivatives) {
return false;
}
let i;
let length2;
if (hasDerivatives) {
length2 = derivativeTypes.length;
if (length2 !== otherDerivativeTypes.length) {
return false;
}
for (i = 0; i < length2; i++) {
if (derivativeTypes[i] !== otherDerivativeTypes[i]) {
return false;
}
}
}
const times = this._times;
const otherTimes = other._times;
length2 = times.length;
if (length2 !== otherTimes.length) {
return false;
}
for (i = 0; i < length2; i++) {
if (!JulianDate_default.equals(times[i], otherTimes[i])) {
return false;
}
}
const values = this._values;
const otherValues = other._values;
length2 = values.length;
for (i = 0; i < length2; i++) {
if (values[i] !== otherValues[i]) {
return false;
}
}
return true;
};
SampledProperty._mergeNewSamples = mergeNewSamples;
var SampledProperty_default = SampledProperty;
// packages/engine/Source/DataSources/SampledPositionProperty.js
function SampledPositionProperty(referenceFrame, numberOfDerivatives) {
numberOfDerivatives = numberOfDerivatives ?? 0;
let derivativeTypes;
if (numberOfDerivatives > 0) {
derivativeTypes = new Array(numberOfDerivatives);
for (let i = 0; i < numberOfDerivatives; i++) {
derivativeTypes[i] = Cartesian3_default;
}
}
this._numberOfDerivatives = numberOfDerivatives;
this._property = new SampledProperty_default(Cartesian3_default, derivativeTypes);
this._definitionChanged = new Event_default();
this._referenceFrame = referenceFrame ?? ReferenceFrame_default.FIXED;
this._property._definitionChanged.addEventListener(function() {
this._definitionChanged.raiseEvent(this);
}, this);
}
Object.defineProperties(SampledPositionProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof SampledPositionProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return this._property.isConstant;
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof SampledPositionProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets the reference frame in which the position is defined.
* @memberof SampledPositionProperty.prototype
* @type {ReferenceFrame}
* @default ReferenceFrame.FIXED;
*/
referenceFrame: {
get: function() {
return this._referenceFrame;
}
},
/**
* Gets the degree of interpolation to perform when retrieving a value. Call setInterpolationOptions to set this.
* @memberof SampledPositionProperty.prototype
*
* @type {number}
* @default 1
* @readonly
*/
interpolationDegree: {
get: function() {
return this._property.interpolationDegree;
}
},
/**
* Gets the interpolation algorithm to use when retrieving a value. Call setInterpolationOptions to set this.
* @memberof SampledPositionProperty.prototype
*
* @type {InterpolationAlgorithm}
* @default LinearApproximation
* @readonly
*/
interpolationAlgorithm: {
get: function() {
return this._property.interpolationAlgorithm;
}
},
/**
* The number of derivatives contained by this property; i.e. 0 for just position, 1 for velocity, etc.
* @memberof SampledPositionProperty.prototype
*
* @type {number}
* @default 0
*/
numberOfDerivatives: {
get: function() {
return this._numberOfDerivatives;
}
},
/**
* Gets or sets the type of extrapolation to perform when a value
* is requested at a time after any available samples.
* @memberof SampledPositionProperty.prototype
* @type {ExtrapolationType}
* @default ExtrapolationType.NONE
*/
forwardExtrapolationType: {
get: function() {
return this._property.forwardExtrapolationType;
},
set: function(value) {
this._property.forwardExtrapolationType = value;
}
},
/**
* Gets or sets the amount of time to extrapolate forward before
* the property becomes undefined. A value of 0 will extrapolate forever.
* @memberof SampledPositionProperty.prototype
* @type {number}
* @default 0
*/
forwardExtrapolationDuration: {
get: function() {
return this._property.forwardExtrapolationDuration;
},
set: function(value) {
this._property.forwardExtrapolationDuration = value;
}
},
/**
* Gets or sets the type of extrapolation to perform when a value
* is requested at a time before any available samples.
* @memberof SampledPositionProperty.prototype
* @type {ExtrapolationType}
* @default ExtrapolationType.NONE
*/
backwardExtrapolationType: {
get: function() {
return this._property.backwardExtrapolationType;
},
set: function(value) {
this._property.backwardExtrapolationType = value;
}
},
/**
* Gets or sets the amount of time to extrapolate backward
* before the property becomes undefined. A value of 0 will extrapolate forever.
* @memberof SampledPositionProperty.prototype
* @type {number}
* @default 0
*/
backwardExtrapolationDuration: {
get: function() {
return this._property.backwardExtrapolationDuration;
},
set: function(value) {
this._property.backwardExtrapolationDuration = value;
}
}
});
var timeScratch23 = new JulianDate_default();
SampledPositionProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch23);
}
return this.getValueInReferenceFrame(time, ReferenceFrame_default.FIXED, result);
};
SampledPositionProperty.prototype.getValueInReferenceFrame = function(time, referenceFrame, result) {
Check_default.defined("time", time);
Check_default.defined("referenceFrame", referenceFrame);
result = this._property.getValue(time, result);
if (defined_default(result)) {
return PositionProperty_default.convertToReferenceFrame(
time,
result,
this._referenceFrame,
referenceFrame,
result
);
}
return void 0;
};
SampledPositionProperty.prototype.setInterpolationOptions = function(options) {
this._property.setInterpolationOptions(options);
};
SampledPositionProperty.prototype.addSample = function(time, position, derivatives) {
const numberOfDerivatives = this._numberOfDerivatives;
if (numberOfDerivatives > 0 && (!defined_default(derivatives) || derivatives.length !== numberOfDerivatives)) {
throw new DeveloperError_default(
"derivatives length must be equal to the number of derivatives."
);
}
this._property.addSample(time, position, derivatives);
};
SampledPositionProperty.prototype.addSamples = function(times, positions, derivatives) {
this._property.addSamples(times, positions, derivatives);
};
SampledPositionProperty.prototype.addSamplesPackedArray = function(packedSamples, epoch2) {
this._property.addSamplesPackedArray(packedSamples, epoch2);
};
SampledPositionProperty.prototype.removeSample = function(time) {
return this._property.removeSample(time);
};
SampledPositionProperty.prototype.removeSamples = function(timeInterval) {
this._property.removeSamples(timeInterval);
};
SampledPositionProperty.prototype.equals = function(other) {
return this === other || //
other instanceof SampledPositionProperty && Property_default.equals(this._property, other._property) && //
this._referenceFrame === other._referenceFrame;
};
var SampledPositionProperty_default = SampledPositionProperty;
// packages/engine/Source/DataSources/StripeMaterialProperty.js
var import_InlineWorkers867 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/StripeOrientation.js
var import_InlineWorkers866 = __toESM(require_InlineWorkers(), 1);
var StripeOrientation = {
/**
* Horizontal orientation.
* @type {number}
*/
HORIZONTAL: 0,
/**
* Vertical orientation.
* @type {number}
*/
VERTICAL: 1
};
var StripeOrientation_default = Object.freeze(StripeOrientation);
// packages/engine/Source/DataSources/StripeMaterialProperty.js
var defaultOrientation = StripeOrientation_default.HORIZONTAL;
var defaultEvenColor2 = Color_default.WHITE;
var defaultOddColor2 = Color_default.BLACK;
var defaultOffset4 = 0;
var defaultRepeat3 = 1;
function StripeMaterialProperty(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._definitionChanged = new Event_default();
this._orientation = void 0;
this._orientationSubscription = void 0;
this._evenColor = void 0;
this._evenColorSubscription = void 0;
this._oddColor = void 0;
this._oddColorSubscription = void 0;
this._offset = void 0;
this._offsetSubscription = void 0;
this._repeat = void 0;
this._repeatSubscription = void 0;
this.orientation = options.orientation;
this.evenColor = options.evenColor;
this.oddColor = options.oddColor;
this.offset = options.offset;
this.repeat = options.repeat;
}
Object.defineProperties(StripeMaterialProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof StripeMaterialProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return Property_default.isConstant(this._orientation) && //
Property_default.isConstant(this._evenColor) && //
Property_default.isConstant(this._oddColor) && //
Property_default.isConstant(this._offset) && //
Property_default.isConstant(this._repeat);
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof StripeMaterialProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the Property specifying the {@link StripeOrientation}/
* @memberof StripeMaterialProperty.prototype
* @type {Property|undefined}
* @default StripeOrientation.HORIZONTAL
*/
orientation: createPropertyDescriptor_default("orientation"),
/**
* Gets or sets the Property specifying the first {@link Color}.
* @memberof StripeMaterialProperty.prototype
* @type {Property|undefined}
* @default Color.WHITE
*/
evenColor: createPropertyDescriptor_default("evenColor"),
/**
* Gets or sets the Property specifying the second {@link Color}.
* @memberof StripeMaterialProperty.prototype
* @type {Property|undefined}
* @default Color.BLACK
*/
oddColor: createPropertyDescriptor_default("oddColor"),
/**
* Gets or sets the numeric Property specifying the point into the pattern
* to begin drawing; with 0.0 being the beginning of the even color, 1.0 the beginning
* of the odd color, 2.0 being the even color again, and any multiple or fractional values
* being in between.
* @memberof StripeMaterialProperty.prototype
* @type {Property|undefined}
* @default 0.0
*/
offset: createPropertyDescriptor_default("offset"),
/**
* Gets or sets the numeric Property specifying how many times the stripes repeat.
* @memberof StripeMaterialProperty.prototype
* @type {Property|undefined}
* @default 1.0
*/
repeat: createPropertyDescriptor_default("repeat")
});
StripeMaterialProperty.prototype.getType = function(time) {
return "Stripe";
};
var timeScratch24 = new JulianDate_default();
StripeMaterialProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch24);
}
if (!defined_default(result)) {
result = {};
}
result.horizontal = Property_default.getValueOrDefault(this._orientation, time, defaultOrientation) === StripeOrientation_default.HORIZONTAL;
result.evenColor = Property_default.getValueOrClonedDefault(
this._evenColor,
time,
defaultEvenColor2,
result.evenColor
);
result.oddColor = Property_default.getValueOrClonedDefault(
this._oddColor,
time,
defaultOddColor2,
result.oddColor
);
result.offset = Property_default.getValueOrDefault(this._offset, time, defaultOffset4);
result.repeat = Property_default.getValueOrDefault(this._repeat, time, defaultRepeat3);
return result;
};
StripeMaterialProperty.prototype.equals = function(other) {
return this === other || //
other instanceof StripeMaterialProperty && //
Property_default.equals(this._orientation, other._orientation) && //
Property_default.equals(this._evenColor, other._evenColor) && //
Property_default.equals(this._oddColor, other._oddColor) && //
Property_default.equals(this._offset, other._offset) && //
Property_default.equals(this._repeat, other._repeat);
};
var StripeMaterialProperty_default = StripeMaterialProperty;
// packages/engine/Source/DataSources/TimeIntervalCollectionPositionProperty.js
var import_InlineWorkers868 = __toESM(require_InlineWorkers(), 1);
function TimeIntervalCollectionPositionProperty(referenceFrame) {
this._definitionChanged = new Event_default();
this._intervals = new TimeIntervalCollection_default();
this._intervals.changedEvent.addEventListener(
TimeIntervalCollectionPositionProperty.prototype._intervalsChanged,
this
);
this._referenceFrame = referenceFrame ?? ReferenceFrame_default.FIXED;
}
Object.defineProperties(TimeIntervalCollectionPositionProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof TimeIntervalCollectionPositionProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return this._intervals.isEmpty;
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is considered to have changed if a call to getValue would return
* a different result for the same time.
* @memberof TimeIntervalCollectionPositionProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets the interval collection.
* @memberof TimeIntervalCollectionPositionProperty.prototype
* @type {TimeIntervalCollection}
* @readonly
*/
intervals: {
get: function() {
return this._intervals;
}
},
/**
* Gets the reference frame in which the position is defined.
* @memberof TimeIntervalCollectionPositionProperty.prototype
* @type {ReferenceFrame}
* @readonly
* @default ReferenceFrame.FIXED;
*/
referenceFrame: {
get: function() {
return this._referenceFrame;
}
}
});
var timeScratch25 = new JulianDate_default();
TimeIntervalCollectionPositionProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch25);
}
return this.getValueInReferenceFrame(time, ReferenceFrame_default.FIXED, result);
};
TimeIntervalCollectionPositionProperty.prototype.getValueInReferenceFrame = function(time, referenceFrame, result) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required.");
}
if (!defined_default(referenceFrame)) {
throw new DeveloperError_default("referenceFrame is required.");
}
const position = this._intervals.findDataForIntervalContainingDate(time);
if (defined_default(position)) {
return PositionProperty_default.convertToReferenceFrame(
time,
position,
this._referenceFrame,
referenceFrame,
result
);
}
return void 0;
};
TimeIntervalCollectionPositionProperty.prototype.equals = function(other) {
return this === other || //
other instanceof TimeIntervalCollectionPositionProperty && //
this._intervals.equals(other._intervals, Property_default.equals) && //
this._referenceFrame === other._referenceFrame;
};
TimeIntervalCollectionPositionProperty.prototype._intervalsChanged = function() {
this._definitionChanged.raiseEvent(this);
};
var TimeIntervalCollectionPositionProperty_default = TimeIntervalCollectionPositionProperty;
// packages/engine/Source/DataSources/TimeIntervalCollectionProperty.js
var import_InlineWorkers869 = __toESM(require_InlineWorkers(), 1);
function TimeIntervalCollectionProperty() {
this._definitionChanged = new Event_default();
this._intervals = new TimeIntervalCollection_default();
this._intervals.changedEvent.addEventListener(
TimeIntervalCollectionProperty.prototype._intervalsChanged,
this
);
}
Object.defineProperties(TimeIntervalCollectionProperty.prototype, {
/**
* Gets a value indicating if this property is constant. A property is considered
* constant if getValue always returns the same result for the current definition.
* @memberof TimeIntervalCollectionProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return this._intervals.isEmpty;
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* The definition is changed whenever setValue is called with data different
* than the current value.
* @memberof TimeIntervalCollectionProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets the interval collection.
* @memberof TimeIntervalCollectionProperty.prototype
*
* @type {TimeIntervalCollection}
* @readonly
*/
intervals: {
get: function() {
return this._intervals;
}
}
});
var timeScratch26 = new JulianDate_default();
TimeIntervalCollectionProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch26);
}
const value = this._intervals.findDataForIntervalContainingDate(time);
if (defined_default(value) && typeof value.clone === "function") {
return value.clone(result);
}
return value;
};
TimeIntervalCollectionProperty.prototype.equals = function(other) {
return this === other || //
other instanceof TimeIntervalCollectionProperty && //
this._intervals.equals(other._intervals, Property_default.equals);
};
TimeIntervalCollectionProperty.prototype._intervalsChanged = function() {
this._definitionChanged.raiseEvent(this);
};
var TimeIntervalCollectionProperty_default = TimeIntervalCollectionProperty;
// packages/engine/Source/DataSources/VelocityOrientationProperty.js
var import_InlineWorkers871 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/VelocityVectorProperty.js
var import_InlineWorkers870 = __toESM(require_InlineWorkers(), 1);
function VelocityVectorProperty(position, normalize2) {
this._position = void 0;
this._subscription = void 0;
this._definitionChanged = new Event_default();
this._normalize = normalize2 ?? true;
this.position = position;
}
Object.defineProperties(VelocityVectorProperty.prototype, {
/**
* Gets a value indicating if this property is constant.
* @memberof VelocityVectorProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return Property_default.isConstant(this._position);
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* @memberof VelocityVectorProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the position property used to compute the velocity vector.
* @memberof VelocityVectorProperty.prototype
*
* @type {Property|undefined}
*/
position: {
get: function() {
return this._position;
},
set: function(value) {
const oldValue2 = this._position;
if (oldValue2 !== value) {
if (defined_default(oldValue2)) {
this._subscription();
}
this._position = value;
if (defined_default(value)) {
this._subscription = value._definitionChanged.addEventListener(
function() {
this._definitionChanged.raiseEvent(this);
},
this
);
}
this._definitionChanged.raiseEvent(this);
}
}
},
/**
* Gets or sets whether the vector produced by this property
* will be normalized or not.
* @memberof VelocityVectorProperty.prototype
*
* @type {boolean}
*/
normalize: {
get: function() {
return this._normalize;
},
set: function(value) {
if (this._normalize === value) {
return;
}
this._normalize = value;
this._definitionChanged.raiseEvent(this);
}
}
});
var position1Scratch = new Cartesian3_default();
var position2Scratch = new Cartesian3_default();
var timeScratch27 = new JulianDate_default();
var timeNowScratch = new JulianDate_default();
var step = 1 / 60;
VelocityVectorProperty.prototype.getValue = function(time, result) {
return this._getValue(time, result);
};
VelocityVectorProperty.prototype._getValue = function(time, velocityResult, positionResult) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeNowScratch);
}
if (!defined_default(velocityResult)) {
velocityResult = new Cartesian3_default();
}
const property = this._position;
if (Property_default.isConstant(property)) {
return this._normalize ? void 0 : Cartesian3_default.clone(Cartesian3_default.ZERO, velocityResult);
}
let position1 = property.getValue(time, position1Scratch);
let position2 = property.getValue(
JulianDate_default.addSeconds(time, step, timeScratch27),
position2Scratch
);
if (!defined_default(position1)) {
return void 0;
}
if (!defined_default(position2)) {
position2 = position1;
position1 = property.getValue(
JulianDate_default.addSeconds(time, -step, timeScratch27),
position2Scratch
);
if (!defined_default(position1)) {
return void 0;
}
}
if (Cartesian3_default.equals(position1, position2)) {
return this._normalize ? void 0 : Cartesian3_default.clone(Cartesian3_default.ZERO, velocityResult);
}
if (defined_default(positionResult)) {
position1.clone(positionResult);
}
const velocity = Cartesian3_default.subtract(position2, position1, velocityResult);
if (this._normalize) {
return Cartesian3_default.normalize(velocity, velocityResult);
}
return Cartesian3_default.divideByScalar(velocity, step, velocityResult);
};
VelocityVectorProperty.prototype.equals = function(other) {
return this === other || //
other instanceof VelocityVectorProperty && Property_default.equals(this._position, other._position);
};
var VelocityVectorProperty_default = VelocityVectorProperty;
// packages/engine/Source/DataSources/VelocityOrientationProperty.js
function VelocityOrientationProperty(position, ellipsoid) {
this._velocityVectorProperty = new VelocityVectorProperty_default(position, true);
this._subscription = void 0;
this._ellipsoid = void 0;
this._definitionChanged = new Event_default();
this.ellipsoid = ellipsoid ?? Ellipsoid_default.default;
const that = this;
this._velocityVectorProperty.definitionChanged.addEventListener(function() {
that._definitionChanged.raiseEvent(that);
});
}
Object.defineProperties(VelocityOrientationProperty.prototype, {
/**
* Gets a value indicating if this property is constant.
* @memberof VelocityOrientationProperty.prototype
*
* @type {boolean}
* @readonly
*/
isConstant: {
get: function() {
return Property_default.isConstant(this._velocityVectorProperty);
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* @memberof VelocityOrientationProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
/**
* Gets or sets the position property used to compute orientation.
* @memberof VelocityOrientationProperty.prototype
*
* @type {Property|undefined}
*/
position: {
get: function() {
return this._velocityVectorProperty.position;
},
set: function(value) {
this._velocityVectorProperty.position = value;
}
},
/**
* Gets or sets the ellipsoid used to determine which way is up.
* @memberof VelocityOrientationProperty.prototype
*
* @type {Property|undefined}
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
},
set: function(value) {
const oldValue2 = this._ellipsoid;
if (oldValue2 !== value) {
this._ellipsoid = value;
this._definitionChanged.raiseEvent(this);
}
}
}
});
var positionScratch10 = new Cartesian3_default();
var velocityScratch = new Cartesian3_default();
var rotationScratch2 = new Matrix3_default();
var timeScratch28 = new JulianDate_default();
VelocityOrientationProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch28);
}
const velocity = this._velocityVectorProperty._getValue(
time,
velocityScratch,
positionScratch10
);
if (!defined_default(velocity)) {
return void 0;
}
Transforms_default.rotationMatrixFromPositionVelocity(
positionScratch10,
velocity,
this._ellipsoid,
rotationScratch2
);
return Quaternion_default.fromRotationMatrix(rotationScratch2, result);
};
VelocityOrientationProperty.prototype.equals = function(other) {
return this === other || //
other instanceof VelocityOrientationProperty && Property_default.equals(
this._velocityVectorProperty,
other._velocityVectorProperty
) && (this._ellipsoid === other._ellipsoid || this._ellipsoid.equals(other._ellipsoid));
};
var VelocityOrientationProperty_default = VelocityOrientationProperty;
// packages/engine/Source/Scene/SensorVolumePortionToDisplay.js
var import_InlineWorkers872 = __toESM(require_InlineWorkers(), 1);
var SensorVolumePortionToDisplay = {
/**
* 0x0000. Display the complete sensor volume.
*
* @type {Number}
* @constant
*/
COMPLETE: 0,
/**
* 0x0001. Display the portion of the sensor volume that lies below the true horizon of the ellipsoid.
*
* @type {Number}
* @constant
*/
BELOW_ELLIPSOID_HORIZON: 1,
/**
* 0x0002. Display the portion of the sensor volume that lies above the true horizon of the ellipsoid.
*
* @type {Number}
* @constant
*/
ABOVE_ELLIPSOID_HORIZON: 2
};
SensorVolumePortionToDisplay.validate = function(portionToDisplay) {
return portionToDisplay === SensorVolumePortionToDisplay.COMPLETE || portionToDisplay === SensorVolumePortionToDisplay.BELOW_ELLIPSOID_HORIZON || portionToDisplay === SensorVolumePortionToDisplay.ABOVE_ELLIPSOID_HORIZON;
};
SensorVolumePortionToDisplay.toString = function(portionToDisplay) {
switch (portionToDisplay) {
case SensorVolumePortionToDisplay.COMPLETE:
return "COMPLETE";
case SensorVolumePortionToDisplay.BELOW_ELLIPSOID_HORIZON:
return "BELOW_ELLIPSOID_HORIZON";
case SensorVolumePortionToDisplay.ABOVE_ELLIPSOID_HORIZON:
return "ABOVE_ELLIPSOID_HORIZON";
default:
throw new DeveloperError_default(
"SensorVolumePortionToDisplay value is not valid and cannot be converted to a String."
);
}
};
var SensorVolumePortionToDisplay_default = SensorVolumePortionToDisplay;
// packages/engine/Source/DataSources/CzmlDataSource.js
function UnitCartesian3() {
}
UnitCartesian3.packedLength = Cartesian3_default.packedLength;
UnitCartesian3.unpack = Cartesian3_default.unpack;
UnitCartesian3.pack = Cartesian3_default.pack;
var currentId;
function createReferenceProperty(entityCollection, referenceString) {
if (referenceString[0] === "#") {
referenceString = currentId + referenceString;
}
return ReferenceProperty_default.fromString(entityCollection, referenceString);
}
function createSpecializedProperty(type, entityCollection, packetData) {
if (defined_default(packetData.reference)) {
return createReferenceProperty(entityCollection, packetData.reference);
}
if (defined_default(packetData.velocityReference)) {
const referenceProperty = createReferenceProperty(
entityCollection,
packetData.velocityReference
);
switch (type) {
case Cartesian3_default:
case UnitCartesian3:
return new VelocityVectorProperty_default(
referenceProperty,
type === UnitCartesian3
);
case Quaternion_default:
return new VelocityOrientationProperty_default(referenceProperty);
}
}
throw new RuntimeError_default(`${JSON.stringify(packetData)} is not valid CZML.`);
}
function createAdapterProperty(property, adapterFunction) {
return new CallbackProperty_default(function(time, result) {
return adapterFunction(property.getValue(time, result));
}, property.isConstant);
}
var scratchCartesian19 = new Cartesian3_default();
var scratchSpherical = new Spherical_default();
var scratchCartographic11 = new Cartographic_default();
var scratchTimeInterval = new TimeInterval_default();
var scratchQuaternion2 = new Quaternion_default();
function unwrapColorInterval(czmlInterval) {
let rgbaf = czmlInterval.rgbaf;
if (defined_default(rgbaf)) {
return rgbaf;
}
const rgba = czmlInterval.rgba;
if (!defined_default(rgba)) {
return void 0;
}
const length2 = rgba.length;
if (length2 === Color_default.packedLength) {
return [
Color_default.byteToFloat(rgba[0]),
Color_default.byteToFloat(rgba[1]),
Color_default.byteToFloat(rgba[2]),
Color_default.byteToFloat(rgba[3])
];
}
rgbaf = new Array(length2);
for (let i = 0; i < length2; i += 5) {
rgbaf[i] = rgba[i];
rgbaf[i + 1] = Color_default.byteToFloat(rgba[i + 1]);
rgbaf[i + 2] = Color_default.byteToFloat(rgba[i + 2]);
rgbaf[i + 3] = Color_default.byteToFloat(rgba[i + 3]);
rgbaf[i + 4] = Color_default.byteToFloat(rgba[i + 4]);
}
return rgbaf;
}
function unwrapUriInterval(czmlInterval, sourceUri) {
const uri = czmlInterval.uri ?? czmlInterval;
if (defined_default(sourceUri)) {
return sourceUri.getDerivedResource({
url: uri
});
}
return Resource_default.createIfNeeded(uri);
}
function unwrapRectangleInterval(czmlInterval) {
let wsen = czmlInterval.wsen;
if (defined_default(wsen)) {
return wsen;
}
const wsenDegrees = czmlInterval.wsenDegrees;
if (!defined_default(wsenDegrees)) {
return void 0;
}
const length2 = wsenDegrees.length;
if (length2 === Rectangle_default.packedLength) {
return [
Math_default.toRadians(wsenDegrees[0]),
Math_default.toRadians(wsenDegrees[1]),
Math_default.toRadians(wsenDegrees[2]),
Math_default.toRadians(wsenDegrees[3])
];
}
wsen = new Array(length2);
for (let i = 0; i < length2; i += 5) {
wsen[i] = wsenDegrees[i];
wsen[i + 1] = Math_default.toRadians(wsenDegrees[i + 1]);
wsen[i + 2] = Math_default.toRadians(wsenDegrees[i + 2]);
wsen[i + 3] = Math_default.toRadians(wsenDegrees[i + 3]);
wsen[i + 4] = Math_default.toRadians(wsenDegrees[i + 4]);
}
return wsen;
}
function convertUnitSphericalToCartesian(unitSpherical) {
const length2 = unitSpherical.length;
scratchSpherical.magnitude = 1;
if (length2 === 2) {
scratchSpherical.clock = unitSpherical[0];
scratchSpherical.cone = unitSpherical[1];
Cartesian3_default.fromSpherical(scratchSpherical, scratchCartesian19);
return [scratchCartesian19.x, scratchCartesian19.y, scratchCartesian19.z];
}
const result = new Array(length2 / 3 * 4);
for (let i = 0, j = 0; i < length2; i += 3, j += 4) {
result[j] = unitSpherical[i];
scratchSpherical.clock = unitSpherical[i + 1];
scratchSpherical.cone = unitSpherical[i + 2];
Cartesian3_default.fromSpherical(scratchSpherical, scratchCartesian19);
result[j + 1] = scratchCartesian19.x;
result[j + 2] = scratchCartesian19.y;
result[j + 3] = scratchCartesian19.z;
}
return result;
}
function convertSphericalToCartesian(spherical) {
const length2 = spherical.length;
if (length2 === 3) {
scratchSpherical.clock = spherical[0];
scratchSpherical.cone = spherical[1];
scratchSpherical.magnitude = spherical[2];
Cartesian3_default.fromSpherical(scratchSpherical, scratchCartesian19);
return [scratchCartesian19.x, scratchCartesian19.y, scratchCartesian19.z];
}
const result = new Array(length2);
for (let i = 0; i < length2; i += 4) {
result[i] = spherical[i];
scratchSpherical.clock = spherical[i + 1];
scratchSpherical.cone = spherical[i + 2];
scratchSpherical.magnitude = spherical[i + 3];
Cartesian3_default.fromSpherical(scratchSpherical, scratchCartesian19);
result[i + 1] = scratchCartesian19.x;
result[i + 2] = scratchCartesian19.y;
result[i + 3] = scratchCartesian19.z;
}
return result;
}
function convertCartographicRadiansToCartesian(cartographicRadians) {
const length2 = cartographicRadians.length;
if (length2 === 3) {
scratchCartographic11.longitude = cartographicRadians[0];
scratchCartographic11.latitude = cartographicRadians[1];
scratchCartographic11.height = cartographicRadians[2];
Ellipsoid_default.default.cartographicToCartesian(
scratchCartographic11,
scratchCartesian19
);
return [scratchCartesian19.x, scratchCartesian19.y, scratchCartesian19.z];
}
const result = new Array(length2);
for (let i = 0; i < length2; i += 4) {
result[i] = cartographicRadians[i];
scratchCartographic11.longitude = cartographicRadians[i + 1];
scratchCartographic11.latitude = cartographicRadians[i + 2];
scratchCartographic11.height = cartographicRadians[i + 3];
Ellipsoid_default.default.cartographicToCartesian(
scratchCartographic11,
scratchCartesian19
);
result[i + 1] = scratchCartesian19.x;
result[i + 2] = scratchCartesian19.y;
result[i + 3] = scratchCartesian19.z;
}
return result;
}
function convertCartographicDegreesToCartesian(cartographicDegrees) {
const length2 = cartographicDegrees.length;
if (length2 === 3) {
scratchCartographic11.longitude = Math_default.toRadians(
cartographicDegrees[0]
);
scratchCartographic11.latitude = Math_default.toRadians(cartographicDegrees[1]);
scratchCartographic11.height = cartographicDegrees[2];
Ellipsoid_default.default.cartographicToCartesian(
scratchCartographic11,
scratchCartesian19
);
return [scratchCartesian19.x, scratchCartesian19.y, scratchCartesian19.z];
}
const result = new Array(length2);
for (let i = 0; i < length2; i += 4) {
result[i] = cartographicDegrees[i];
scratchCartographic11.longitude = Math_default.toRadians(
cartographicDegrees[i + 1]
);
scratchCartographic11.latitude = Math_default.toRadians(
cartographicDegrees[i + 2]
);
scratchCartographic11.height = cartographicDegrees[i + 3];
Ellipsoid_default.default.cartographicToCartesian(
scratchCartographic11,
scratchCartesian19
);
result[i + 1] = scratchCartesian19.x;
result[i + 2] = scratchCartesian19.y;
result[i + 3] = scratchCartesian19.z;
}
return result;
}
function unwrapCartesianInterval(czmlInterval) {
const cartesian11 = czmlInterval.cartesian;
if (defined_default(cartesian11)) {
return cartesian11;
}
const cartesianVelocity = czmlInterval.cartesianVelocity;
if (defined_default(cartesianVelocity)) {
return cartesianVelocity;
}
const unitCartesian = czmlInterval.unitCartesian;
if (defined_default(unitCartesian)) {
return unitCartesian;
}
const unitSpherical = czmlInterval.unitSpherical;
if (defined_default(unitSpherical)) {
return convertUnitSphericalToCartesian(unitSpherical);
}
const spherical = czmlInterval.spherical;
if (defined_default(spherical)) {
return convertSphericalToCartesian(spherical);
}
const cartographicRadians = czmlInterval.cartographicRadians;
if (defined_default(cartographicRadians)) {
return convertCartographicRadiansToCartesian(cartographicRadians);
}
const cartographicDegrees = czmlInterval.cartographicDegrees;
if (defined_default(cartographicDegrees)) {
return convertCartographicDegreesToCartesian(cartographicDegrees);
}
throw new RuntimeError_default(
`${JSON.stringify(czmlInterval)} is not a valid CZML interval.`
);
}
function normalizePackedCartesianArray(array, startingIndex) {
Cartesian3_default.unpack(array, startingIndex, scratchCartesian19);
Cartesian3_default.normalize(scratchCartesian19, scratchCartesian19);
Cartesian3_default.pack(scratchCartesian19, array, startingIndex);
}
function unwrapUnitCartesianInterval(czmlInterval) {
const cartesian11 = unwrapCartesianInterval(czmlInterval);
if (cartesian11.length === 3) {
normalizePackedCartesianArray(cartesian11, 0);
return cartesian11;
}
for (let i = 1; i < cartesian11.length; i += 4) {
normalizePackedCartesianArray(cartesian11, i);
}
return cartesian11;
}
function normalizePackedQuaternionArray(array, startingIndex) {
Quaternion_default.unpack(array, startingIndex, scratchQuaternion2);
Quaternion_default.normalize(scratchQuaternion2, scratchQuaternion2);
Quaternion_default.pack(scratchQuaternion2, array, startingIndex);
}
function unwrapQuaternionInterval(czmlInterval) {
const unitQuaternion = czmlInterval.unitQuaternion;
if (defined_default(unitQuaternion)) {
if (unitQuaternion.length === 4) {
normalizePackedQuaternionArray(unitQuaternion, 0);
return unitQuaternion;
}
for (let i = 1; i < unitQuaternion.length; i += 5) {
normalizePackedQuaternionArray(unitQuaternion, i);
}
}
return unitQuaternion;
}
function getPropertyType(czmlInterval) {
if (typeof czmlInterval === "boolean") {
return Boolean;
} else if (typeof czmlInterval === "number") {
return Number;
} else if (typeof czmlInterval === "string") {
return String;
} else if (czmlInterval.hasOwnProperty("array")) {
return Array;
} else if (czmlInterval.hasOwnProperty("boolean")) {
return Boolean;
} else if (czmlInterval.hasOwnProperty("boundingRectangle")) {
return BoundingRectangle_default;
} else if (czmlInterval.hasOwnProperty("cartesian2")) {
return Cartesian2_default;
} else if (czmlInterval.hasOwnProperty("cartesian") || czmlInterval.hasOwnProperty("spherical") || czmlInterval.hasOwnProperty("cartographicRadians") || czmlInterval.hasOwnProperty("cartographicDegrees")) {
return Cartesian3_default;
} else if (czmlInterval.hasOwnProperty("unitCartesian") || czmlInterval.hasOwnProperty("unitSpherical")) {
return UnitCartesian3;
} else if (czmlInterval.hasOwnProperty("rgba") || czmlInterval.hasOwnProperty("rgbaf")) {
return Color_default;
} else if (czmlInterval.hasOwnProperty("arcType")) {
return ArcType_default;
} else if (czmlInterval.hasOwnProperty("classificationType")) {
return ClassificationType_default;
} else if (czmlInterval.hasOwnProperty("colorBlendMode")) {
return ColorBlendMode_default;
} else if (czmlInterval.hasOwnProperty("cornerType")) {
return CornerType_default;
} else if (czmlInterval.hasOwnProperty("heightReference")) {
return HeightReference_default;
} else if (czmlInterval.hasOwnProperty("horizontalOrigin")) {
return HorizontalOrigin_default;
} else if (czmlInterval.hasOwnProperty("date")) {
return JulianDate_default;
} else if (czmlInterval.hasOwnProperty("labelStyle")) {
return LabelStyle_default;
} else if (czmlInterval.hasOwnProperty("number")) {
return Number;
} else if (czmlInterval.hasOwnProperty("nearFarScalar")) {
return NearFarScalar_default;
} else if (czmlInterval.hasOwnProperty("distanceDisplayCondition")) {
return DistanceDisplayCondition_default;
} else if (czmlInterval.hasOwnProperty("object") || czmlInterval.hasOwnProperty("value")) {
return Object;
} else if (czmlInterval.hasOwnProperty("unitQuaternion")) {
return Quaternion_default;
} else if (czmlInterval.hasOwnProperty("shadowMode")) {
return ShadowMode_default;
} else if (czmlInterval.hasOwnProperty("string")) {
return String;
} else if (czmlInterval.hasOwnProperty("stripeOrientation")) {
return StripeOrientation_default;
} else if (czmlInterval.hasOwnProperty("wsen") || czmlInterval.hasOwnProperty("wsenDegrees")) {
return Rectangle_default;
} else if (czmlInterval.hasOwnProperty("uri")) {
return import_urijs10.default;
} else if (czmlInterval.hasOwnProperty("verticalOrigin")) {
return VerticalOrigin_default;
}
return Object;
}
function unwrapInterval(type, czmlInterval, sourceUri) {
switch (type) {
case ArcType_default:
return ArcType_default[czmlInterval.arcType ?? czmlInterval];
case Array:
return czmlInterval.array;
case Boolean:
return czmlInterval["boolean"] ?? czmlInterval;
case BoundingRectangle_default:
return czmlInterval.boundingRectangle;
case Cartesian2_default:
return czmlInterval.cartesian2;
case Cartesian3_default:
return unwrapCartesianInterval(czmlInterval);
case UnitCartesian3:
return unwrapUnitCartesianInterval(czmlInterval);
case Color_default:
return unwrapColorInterval(czmlInterval);
case ClassificationType_default:
return ClassificationType_default[czmlInterval.classificationType ?? czmlInterval];
case ColorBlendMode_default:
return ColorBlendMode_default[czmlInterval.colorBlendMode ?? czmlInterval];
case CornerType_default:
return CornerType_default[czmlInterval.cornerType ?? czmlInterval];
case HeightReference_default:
return HeightReference_default[czmlInterval.heightReference ?? czmlInterval];
case HorizontalOrigin_default:
return HorizontalOrigin_default[czmlInterval.horizontalOrigin ?? czmlInterval];
case Image:
return unwrapUriInterval(czmlInterval, sourceUri);
case JulianDate_default:
return JulianDate_default.fromIso8601(czmlInterval.date ?? czmlInterval);
case LabelStyle_default:
return LabelStyle_default[czmlInterval.labelStyle ?? czmlInterval];
case Number:
return czmlInterval.number ?? czmlInterval;
case NearFarScalar_default:
return czmlInterval.nearFarScalar;
case DistanceDisplayCondition_default:
return czmlInterval.distanceDisplayCondition;
case Object:
return czmlInterval.object ?? czmlInterval.value ?? czmlInterval;
case Quaternion_default:
return unwrapQuaternionInterval(czmlInterval);
case Rotation_default:
return czmlInterval.number ?? czmlInterval;
case SensorVolumePortionToDisplay_default:
return SensorVolumePortionToDisplay_default[czmlInterval.portionToDisplay ?? czmlInterval];
case ShadowMode_default:
return ShadowMode_default[czmlInterval.shadowMode ?? czmlInterval.shadows ?? czmlInterval];
case String:
return czmlInterval.string ?? czmlInterval;
case StripeOrientation_default:
return StripeOrientation_default[czmlInterval.stripeOrientation ?? czmlInterval];
case Rectangle_default:
return unwrapRectangleInterval(czmlInterval);
case import_urijs10.default:
return unwrapUriInterval(czmlInterval, sourceUri);
case VerticalOrigin_default:
return VerticalOrigin_default[czmlInterval.verticalOrigin ?? czmlInterval];
default:
throw new RuntimeError_default(`Unknown CzmlDataSource interval type: ${type}`);
}
}
var interpolators = {
HERMITE: HermitePolynomialApproximation_default,
LAGRANGE: LagrangePolynomialApproximation_default,
LINEAR: LinearApproximation_default
};
function updateInterpolationSettings(packetData, property) {
const interpolationAlgorithm = packetData.interpolationAlgorithm;
const interpolationDegree = packetData.interpolationDegree;
if (defined_default(interpolationAlgorithm) || defined_default(interpolationDegree)) {
property.setInterpolationOptions({
interpolationAlgorithm: interpolators[interpolationAlgorithm],
interpolationDegree
});
}
const forwardExtrapolationType = packetData.forwardExtrapolationType;
if (defined_default(forwardExtrapolationType)) {
property.forwardExtrapolationType = ExtrapolationType_default[forwardExtrapolationType];
}
const forwardExtrapolationDuration = packetData.forwardExtrapolationDuration;
if (defined_default(forwardExtrapolationDuration)) {
property.forwardExtrapolationDuration = forwardExtrapolationDuration;
}
const backwardExtrapolationType = packetData.backwardExtrapolationType;
if (defined_default(backwardExtrapolationType)) {
property.backwardExtrapolationType = ExtrapolationType_default[backwardExtrapolationType];
}
const backwardExtrapolationDuration = packetData.backwardExtrapolationDuration;
if (defined_default(backwardExtrapolationDuration)) {
property.backwardExtrapolationDuration = backwardExtrapolationDuration;
}
}
var iso8601Scratch = {
iso8601: void 0
};
function intervalFromString(intervalString) {
if (!defined_default(intervalString)) {
return void 0;
}
iso8601Scratch.iso8601 = intervalString;
return TimeInterval_default.fromIso8601(iso8601Scratch);
}
function wrapPropertyInInfiniteInterval(property) {
const interval = Iso8601_default.MAXIMUM_INTERVAL.clone();
interval.data = property;
return interval;
}
function convertPropertyToComposite(property) {
const composite = new CompositeProperty_default();
composite.intervals.addInterval(wrapPropertyInInfiniteInterval(property));
return composite;
}
function convertPositionPropertyToComposite(property) {
const composite = new CompositePositionProperty_default(property.referenceFrame);
composite.intervals.addInterval(wrapPropertyInInfiniteInterval(property));
return composite;
}
function processProperty(type, object2, propertyName, packetData, constrainedInterval, sourceUri, entityCollection) {
let combinedInterval = intervalFromString(packetData.interval);
if (defined_default(constrainedInterval)) {
if (defined_default(combinedInterval)) {
combinedInterval = TimeInterval_default.intersect(
combinedInterval,
constrainedInterval,
scratchTimeInterval
);
} else {
combinedInterval = constrainedInterval;
}
}
let packedLength;
let unwrappedInterval;
let unwrappedIntervalLength;
const isValue = !defined_default(packetData.reference) && !defined_default(packetData.velocityReference);
const hasInterval = defined_default(combinedInterval) && !combinedInterval.equals(Iso8601_default.MAXIMUM_INTERVAL);
if (packetData.delete === true) {
if (!hasInterval) {
object2[propertyName] = void 0;
return;
}
return removePropertyData(object2[propertyName], combinedInterval);
}
let isSampled = false;
if (isValue) {
unwrappedInterval = unwrapInterval(type, packetData, sourceUri);
if (!defined_default(unwrappedInterval)) {
return;
}
packedLength = type.packedLength ?? 1;
unwrappedIntervalLength = unwrappedInterval.length ?? 1;
isSampled = !defined_default(packetData.array) && typeof unwrappedInterval !== "string" && unwrappedIntervalLength > packedLength && type !== Object;
}
const needsUnpacking = typeof type.unpack === "function" && type !== Rotation_default;
if (!isSampled && !hasInterval) {
if (isValue) {
object2[propertyName] = new ConstantProperty_default(
needsUnpacking ? type.unpack(unwrappedInterval, 0) : unwrappedInterval
);
} else {
object2[propertyName] = createSpecializedProperty(
type,
entityCollection,
packetData
);
}
return;
}
let property = object2[propertyName];
let epoch2;
const packetEpoch = packetData.epoch;
if (defined_default(packetEpoch)) {
epoch2 = JulianDate_default.fromIso8601(packetEpoch);
}
if (isSampled && !hasInterval) {
if (!(property instanceof SampledProperty_default)) {
object2[propertyName] = property = new SampledProperty_default(type);
}
property.addSamplesPackedArray(unwrappedInterval, epoch2);
updateInterpolationSettings(packetData, property);
return;
}
let interval;
if (!isSampled && hasInterval) {
combinedInterval = combinedInterval.clone();
if (isValue) {
combinedInterval.data = needsUnpacking ? type.unpack(unwrappedInterval, 0) : unwrappedInterval;
} else {
combinedInterval.data = createSpecializedProperty(
type,
entityCollection,
packetData
);
}
if (!defined_default(property)) {
object2[propertyName] = property = isValue ? new TimeIntervalCollectionProperty_default() : new CompositeProperty_default();
}
if (isValue && property instanceof TimeIntervalCollectionProperty_default) {
property.intervals.addInterval(combinedInterval);
} else if (property instanceof CompositeProperty_default) {
if (isValue) {
combinedInterval.data = new ConstantProperty_default(combinedInterval.data);
}
property.intervals.addInterval(combinedInterval);
} else {
object2[propertyName] = property = convertPropertyToComposite(property);
if (isValue) {
combinedInterval.data = new ConstantProperty_default(combinedInterval.data);
}
property.intervals.addInterval(combinedInterval);
}
return;
}
if (!defined_default(property)) {
object2[propertyName] = property = new CompositeProperty_default();
}
if (!(property instanceof CompositeProperty_default)) {
object2[propertyName] = property = convertPropertyToComposite(property);
}
const intervals = property.intervals;
interval = intervals.findInterval(combinedInterval);
if (!defined_default(interval) || !(interval.data instanceof SampledProperty_default)) {
interval = combinedInterval.clone();
interval.data = new SampledProperty_default(type);
intervals.addInterval(interval);
}
interval.data.addSamplesPackedArray(unwrappedInterval, epoch2);
updateInterpolationSettings(packetData, interval.data);
}
function removePropertyData(property, interval) {
if (property instanceof SampledProperty_default) {
property.removeSamples(interval);
return;
} else if (property instanceof TimeIntervalCollectionProperty_default) {
property.intervals.removeInterval(interval);
return;
} else if (property instanceof CompositeProperty_default) {
const intervals = property.intervals;
for (let i = 0; i < intervals.length; ++i) {
const intersection = TimeInterval_default.intersect(
intervals.get(i),
interval,
scratchTimeInterval
);
if (!intersection.isEmpty) {
removePropertyData(intersection.data, interval);
}
}
intervals.removeInterval(interval);
return;
}
}
function processPacketData(type, object2, propertyName, packetData, interval, sourceUri, entityCollection) {
if (!defined_default(packetData)) {
return;
}
if (Array.isArray(packetData)) {
for (let i = 0, len = packetData.length; i < len; ++i) {
processProperty(
type,
object2,
propertyName,
packetData[i],
interval,
sourceUri,
entityCollection
);
}
} else {
processProperty(
type,
object2,
propertyName,
packetData,
interval,
sourceUri,
entityCollection
);
}
}
function processPositionProperty(object2, propertyName, packetData, constrainedInterval, sourceUri, entityCollection) {
let combinedInterval = intervalFromString(packetData.interval);
if (defined_default(constrainedInterval)) {
if (defined_default(combinedInterval)) {
combinedInterval = TimeInterval_default.intersect(
combinedInterval,
constrainedInterval,
scratchTimeInterval
);
} else {
combinedInterval = constrainedInterval;
}
}
const numberOfDerivatives = defined_default(packetData.cartesianVelocity) ? 1 : 0;
const packedLength = Cartesian3_default.packedLength * (numberOfDerivatives + 1);
let unwrappedInterval;
let unwrappedIntervalLength;
const isValue = !defined_default(packetData.reference);
const hasInterval = defined_default(combinedInterval) && !combinedInterval.equals(Iso8601_default.MAXIMUM_INTERVAL);
if (packetData.delete === true) {
if (!hasInterval) {
object2[propertyName] = void 0;
return;
}
return removePositionPropertyData(object2[propertyName], combinedInterval);
}
let referenceFrame;
let isSampled = false;
if (isValue) {
if (defined_default(packetData.referenceFrame)) {
referenceFrame = ReferenceFrame_default[packetData.referenceFrame];
}
referenceFrame = referenceFrame ?? ReferenceFrame_default.FIXED;
unwrappedInterval = unwrapCartesianInterval(packetData);
unwrappedIntervalLength = unwrappedInterval.length ?? 1;
isSampled = unwrappedIntervalLength > packedLength;
}
if (!isSampled && !hasInterval) {
if (isValue) {
object2[propertyName] = new ConstantPositionProperty_default(
Cartesian3_default.unpack(unwrappedInterval),
referenceFrame
);
} else {
object2[propertyName] = createReferenceProperty(
entityCollection,
packetData.reference
);
}
return;
}
let property = object2[propertyName];
let epoch2;
const packetEpoch = packetData.epoch;
if (defined_default(packetEpoch)) {
epoch2 = JulianDate_default.fromIso8601(packetEpoch);
}
if (isSampled && !hasInterval) {
if (!(property instanceof SampledPositionProperty_default) || defined_default(referenceFrame) && property.referenceFrame !== referenceFrame) {
object2[propertyName] = property = new SampledPositionProperty_default(
referenceFrame,
numberOfDerivatives
);
}
property.addSamplesPackedArray(unwrappedInterval, epoch2);
updateInterpolationSettings(packetData, property);
return;
}
let interval;
if (!isSampled && hasInterval) {
combinedInterval = combinedInterval.clone();
if (isValue) {
combinedInterval.data = Cartesian3_default.unpack(unwrappedInterval);
} else {
combinedInterval.data = createReferenceProperty(
entityCollection,
packetData.reference
);
}
if (!defined_default(property)) {
if (isValue) {
property = new TimeIntervalCollectionPositionProperty_default(referenceFrame);
} else {
property = new CompositePositionProperty_default(referenceFrame);
}
object2[propertyName] = property;
}
if (isValue && property instanceof TimeIntervalCollectionPositionProperty_default && defined_default(referenceFrame) && property.referenceFrame === referenceFrame) {
property.intervals.addInterval(combinedInterval);
} else if (property instanceof CompositePositionProperty_default) {
if (isValue) {
combinedInterval.data = new ConstantPositionProperty_default(
combinedInterval.data,
referenceFrame
);
}
property.intervals.addInterval(combinedInterval);
} else {
object2[propertyName] = property = convertPositionPropertyToComposite(property);
if (isValue) {
combinedInterval.data = new ConstantPositionProperty_default(
combinedInterval.data,
referenceFrame
);
}
property.intervals.addInterval(combinedInterval);
}
return;
}
if (!defined_default(property)) {
object2[propertyName] = property = new CompositePositionProperty_default(
referenceFrame
);
} else if (!(property instanceof CompositePositionProperty_default)) {
object2[propertyName] = property = convertPositionPropertyToComposite(property);
}
const intervals = property.intervals;
interval = intervals.findInterval(combinedInterval);
if (!defined_default(interval) || !(interval.data instanceof SampledPositionProperty_default) || defined_default(referenceFrame) && interval.data.referenceFrame !== referenceFrame) {
interval = combinedInterval.clone();
interval.data = new SampledPositionProperty_default(
referenceFrame,
numberOfDerivatives
);
intervals.addInterval(interval);
}
interval.data.addSamplesPackedArray(unwrappedInterval, epoch2);
updateInterpolationSettings(packetData, interval.data);
}
function removePositionPropertyData(property, interval) {
if (property instanceof SampledPositionProperty_default) {
property.removeSamples(interval);
return;
} else if (property instanceof TimeIntervalCollectionPositionProperty_default) {
property.intervals.removeInterval(interval);
return;
} else if (property instanceof CompositePositionProperty_default) {
const intervals = property.intervals;
for (let i = 0; i < intervals.length; ++i) {
const intersection = TimeInterval_default.intersect(
intervals.get(i),
interval,
scratchTimeInterval
);
if (!intersection.isEmpty) {
removePositionPropertyData(intersection.data, interval);
}
}
intervals.removeInterval(interval);
return;
}
}
function processPositionPacketData(object2, propertyName, packetData, interval, sourceUri, entityCollection) {
if (!defined_default(packetData)) {
return;
}
if (Array.isArray(packetData)) {
for (let i = 0, len = packetData.length; i < len; ++i) {
processPositionProperty(
object2,
propertyName,
packetData[i],
interval,
sourceUri,
entityCollection
);
}
} else {
processPositionProperty(
object2,
propertyName,
packetData,
interval,
sourceUri,
entityCollection
);
}
}
function processShapePacketData(object2, propertyName, packetData, entityCollection) {
if (defined_default(packetData.references)) {
processReferencesArrayPacketData(
object2,
propertyName,
packetData.references,
packetData.interval,
entityCollection,
PropertyArray_default,
CompositeProperty_default
);
} else {
if (defined_default(packetData.cartesian2)) {
packetData.array = Cartesian2_default.unpackArray(packetData.cartesian2);
} else if (defined_default(packetData.cartesian)) {
packetData.array = Cartesian2_default.unpackArray(packetData.cartesian);
}
if (defined_default(packetData.array)) {
processPacketData(
Array,
object2,
propertyName,
packetData,
void 0,
void 0,
entityCollection
);
}
}
}
function processMaterialProperty(object2, propertyName, packetData, constrainedInterval, sourceUri, entityCollection) {
let combinedInterval = intervalFromString(packetData.interval);
if (defined_default(constrainedInterval)) {
if (defined_default(combinedInterval)) {
combinedInterval = TimeInterval_default.intersect(
combinedInterval,
constrainedInterval,
scratchTimeInterval
);
} else {
combinedInterval = constrainedInterval;
}
}
let property = object2[propertyName];
let existingMaterial;
let existingInterval;
if (defined_default(combinedInterval)) {
if (!(property instanceof CompositeMaterialProperty_default)) {
property = new CompositeMaterialProperty_default();
object2[propertyName] = property;
}
const thisIntervals = property.intervals;
existingInterval = thisIntervals.findInterval({
start: combinedInterval.start,
stop: combinedInterval.stop
});
if (defined_default(existingInterval)) {
existingMaterial = existingInterval.data;
} else {
existingInterval = combinedInterval.clone();
thisIntervals.addInterval(existingInterval);
}
} else {
existingMaterial = property;
}
let materialData;
if (defined_default(packetData.solidColor)) {
if (!(existingMaterial instanceof ColorMaterialProperty_default)) {
existingMaterial = new ColorMaterialProperty_default();
}
materialData = packetData.solidColor;
processPacketData(
Color_default,
existingMaterial,
"color",
materialData.color,
void 0,
void 0,
entityCollection
);
} else if (defined_default(packetData.grid)) {
if (!(existingMaterial instanceof GridMaterialProperty_default)) {
existingMaterial = new GridMaterialProperty_default();
}
materialData = packetData.grid;
processPacketData(
Color_default,
existingMaterial,
"color",
materialData.color,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Number,
existingMaterial,
"cellAlpha",
materialData.cellAlpha,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Cartesian2_default,
existingMaterial,
"lineCount",
materialData.lineCount,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Cartesian2_default,
existingMaterial,
"lineThickness",
materialData.lineThickness,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Cartesian2_default,
existingMaterial,
"lineOffset",
materialData.lineOffset,
void 0,
sourceUri,
entityCollection
);
} else if (defined_default(packetData.image)) {
if (!(existingMaterial instanceof ImageMaterialProperty_default)) {
existingMaterial = new ImageMaterialProperty_default();
}
materialData = packetData.image;
processPacketData(
Image,
existingMaterial,
"image",
materialData.image,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Cartesian2_default,
existingMaterial,
"repeat",
materialData.repeat,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
existingMaterial,
"color",
materialData.color,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
existingMaterial,
"transparent",
materialData.transparent,
void 0,
sourceUri,
entityCollection
);
} else if (defined_default(packetData.stripe)) {
if (!(existingMaterial instanceof StripeMaterialProperty_default)) {
existingMaterial = new StripeMaterialProperty_default();
}
materialData = packetData.stripe;
processPacketData(
StripeOrientation_default,
existingMaterial,
"orientation",
materialData.orientation,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
existingMaterial,
"evenColor",
materialData.evenColor,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
existingMaterial,
"oddColor",
materialData.oddColor,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Number,
existingMaterial,
"offset",
materialData.offset,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Number,
existingMaterial,
"repeat",
materialData.repeat,
void 0,
sourceUri,
entityCollection
);
} else if (defined_default(packetData.polylineOutline)) {
if (!(existingMaterial instanceof PolylineOutlineMaterialProperty_default)) {
existingMaterial = new PolylineOutlineMaterialProperty_default();
}
materialData = packetData.polylineOutline;
processPacketData(
Color_default,
existingMaterial,
"color",
materialData.color,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
existingMaterial,
"outlineColor",
materialData.outlineColor,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Number,
existingMaterial,
"outlineWidth",
materialData.outlineWidth,
void 0,
sourceUri,
entityCollection
);
} else if (defined_default(packetData.polylineGlow)) {
if (!(existingMaterial instanceof PolylineGlowMaterialProperty_default)) {
existingMaterial = new PolylineGlowMaterialProperty_default();
}
materialData = packetData.polylineGlow;
processPacketData(
Color_default,
existingMaterial,
"color",
materialData.color,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Number,
existingMaterial,
"glowPower",
materialData.glowPower,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Number,
existingMaterial,
"taperPower",
materialData.taperPower,
void 0,
sourceUri,
entityCollection
);
} else if (defined_default(packetData.polylineArrow)) {
if (!(existingMaterial instanceof PolylineArrowMaterialProperty_default)) {
existingMaterial = new PolylineArrowMaterialProperty_default();
}
materialData = packetData.polylineArrow;
processPacketData(
Color_default,
existingMaterial,
"color",
materialData.color,
void 0,
void 0,
entityCollection
);
} else if (defined_default(packetData.polylineDash)) {
if (!(existingMaterial instanceof PolylineDashMaterialProperty_default)) {
existingMaterial = new PolylineDashMaterialProperty_default();
}
materialData = packetData.polylineDash;
processPacketData(
Color_default,
existingMaterial,
"color",
materialData.color,
void 0,
void 0,
entityCollection
);
processPacketData(
Color_default,
existingMaterial,
"gapColor",
materialData.gapColor,
void 0,
void 0,
entityCollection
);
processPacketData(
Number,
existingMaterial,
"dashLength",
materialData.dashLength,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Number,
existingMaterial,
"dashPattern",
materialData.dashPattern,
void 0,
sourceUri,
entityCollection
);
} else if (defined_default(packetData.checkerboard)) {
if (!(existingMaterial instanceof CheckerboardMaterialProperty_default)) {
existingMaterial = new CheckerboardMaterialProperty_default();
}
materialData = packetData.checkerboard;
processPacketData(
Color_default,
existingMaterial,
"evenColor",
materialData.evenColor,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
existingMaterial,
"oddColor",
materialData.oddColor,
void 0,
sourceUri,
entityCollection
);
processPacketData(
Cartesian2_default,
existingMaterial,
"repeat",
materialData.repeat,
void 0,
sourceUri,
entityCollection
);
}
if (defined_default(existingInterval)) {
existingInterval.data = existingMaterial;
} else {
object2[propertyName] = existingMaterial;
}
}
function processMaterialPacketData(object2, propertyName, packetData, interval, sourceUri, entityCollection) {
if (!defined_default(packetData)) {
return;
}
if (Array.isArray(packetData)) {
for (let i = 0, len = packetData.length; i < len; ++i) {
processMaterialProperty(
object2,
propertyName,
packetData[i],
interval,
sourceUri,
entityCollection
);
}
} else {
processMaterialProperty(
object2,
propertyName,
packetData,
interval,
sourceUri,
entityCollection
);
}
}
function processName(entity, packet, entityCollection, sourceUri) {
const nameData = packet.name;
if (defined_default(nameData)) {
entity.name = packet.name;
}
}
function processDescription(entity, packet, entityCollection, sourceUri) {
const descriptionData = packet.description;
if (defined_default(descriptionData)) {
processPacketData(
String,
entity,
"description",
descriptionData,
void 0,
sourceUri,
entityCollection
);
}
}
function processPosition(entity, packet, entityCollection, sourceUri) {
const positionData = packet.position;
if (defined_default(positionData)) {
processPositionPacketData(
entity,
"position",
positionData,
void 0,
sourceUri,
entityCollection
);
}
}
function processViewFrom(entity, packet, entityCollection, sourceUri) {
const viewFromData = packet.viewFrom;
if (defined_default(viewFromData)) {
processPacketData(
Cartesian3_default,
entity,
"viewFrom",
viewFromData,
void 0,
sourceUri,
entityCollection
);
}
}
function processOrientation(entity, packet, entityCollection, sourceUri) {
const orientationData = packet.orientation;
if (defined_default(orientationData)) {
processPacketData(
Quaternion_default,
entity,
"orientation",
orientationData,
void 0,
sourceUri,
entityCollection
);
}
}
function processProperties(entity, packet, entityCollection, sourceUri) {
const propertiesData = packet.properties;
if (defined_default(propertiesData)) {
if (!defined_default(entity.properties)) {
entity.properties = new PropertyBag_default();
}
for (const key in propertiesData) {
if (propertiesData.hasOwnProperty(key)) {
if (!entity.properties.hasProperty(key)) {
entity.properties.addProperty(key);
}
const propertyData = propertiesData[key];
if (Array.isArray(propertyData)) {
for (let i = 0, len = propertyData.length; i < len; ++i) {
processProperty(
getPropertyType(propertyData[i]),
entity.properties,
key,
propertyData[i],
void 0,
sourceUri,
entityCollection
);
}
} else {
processProperty(
getPropertyType(propertyData),
entity.properties,
key,
propertyData,
void 0,
sourceUri,
entityCollection
);
}
}
}
}
}
function processReferencesArrayPacketData(object2, propertyName, references, interval, entityCollection, PropertyArrayType, CompositePropertyArrayType) {
const properties = references.map(function(reference) {
return createReferenceProperty(entityCollection, reference);
});
if (defined_default(interval)) {
interval = intervalFromString(interval);
let property = object2[propertyName];
if (!(property instanceof CompositePropertyArrayType)) {
const composite = new CompositePropertyArrayType();
composite.intervals.addInterval(wrapPropertyInInfiniteInterval(property));
object2[propertyName] = property = composite;
}
interval.data = new PropertyArrayType(properties);
property.intervals.addInterval(interval);
} else {
object2[propertyName] = new PropertyArrayType(properties);
}
}
function processArrayPacketData(object2, propertyName, packetData, entityCollection) {
const references = packetData.references;
if (defined_default(references)) {
processReferencesArrayPacketData(
object2,
propertyName,
references,
packetData.interval,
entityCollection,
PropertyArray_default,
CompositeProperty_default
);
} else {
processPacketData(
Array,
object2,
propertyName,
packetData,
void 0,
void 0,
entityCollection
);
}
}
function processArray(object2, propertyName, packetData, entityCollection) {
if (!defined_default(packetData)) {
return;
}
if (Array.isArray(packetData)) {
for (let i = 0, length2 = packetData.length; i < length2; ++i) {
processArrayPacketData(
object2,
propertyName,
packetData[i],
entityCollection
);
}
} else {
processArrayPacketData(object2, propertyName, packetData, entityCollection);
}
}
function processPositionArrayPacketData(object2, propertyName, packetData, entityCollection) {
const references = packetData.references;
if (defined_default(references)) {
processReferencesArrayPacketData(
object2,
propertyName,
references,
packetData.interval,
entityCollection,
PositionPropertyArray_default,
CompositePositionProperty_default
);
} else {
if (defined_default(packetData.cartesian)) {
packetData.array = Cartesian3_default.unpackArray(packetData.cartesian);
} else if (defined_default(packetData.cartographicRadians)) {
packetData.array = Cartesian3_default.fromRadiansArrayHeights(
packetData.cartographicRadians,
Ellipsoid_default.default
);
} else if (defined_default(packetData.cartographicDegrees)) {
packetData.array = Cartesian3_default.fromDegreesArrayHeights(
packetData.cartographicDegrees,
Ellipsoid_default.default
);
}
if (defined_default(packetData.array)) {
processPacketData(
Array,
object2,
propertyName,
packetData,
void 0,
void 0,
entityCollection
);
}
}
}
function processPositionArray(object2, propertyName, packetData, entityCollection) {
if (!defined_default(packetData)) {
return;
}
if (Array.isArray(packetData)) {
for (let i = 0, length2 = packetData.length; i < length2; ++i) {
processPositionArrayPacketData(
object2,
propertyName,
packetData[i],
entityCollection
);
}
} else {
processPositionArrayPacketData(
object2,
propertyName,
packetData,
entityCollection
);
}
}
function unpackCartesianArray(array) {
return Cartesian3_default.unpackArray(array);
}
function unpackCartographicRadiansArray(array) {
return Cartesian3_default.fromRadiansArrayHeights(array, Ellipsoid_default.default);
}
function unpackCartographicDegreesArray(array) {
return Cartesian3_default.fromDegreesArrayHeights(array, Ellipsoid_default.default);
}
function processPositionArrayOfArraysPacketData(object2, propertyName, packetData, entityCollection) {
const references = packetData.references;
if (defined_default(references)) {
const properties = references.map(function(referenceArray) {
const tempObj = {};
processReferencesArrayPacketData(
tempObj,
"positions",
referenceArray,
packetData.interval,
entityCollection,
PositionPropertyArray_default,
CompositePositionProperty_default
);
return tempObj.positions;
});
object2[propertyName] = new PositionPropertyArray_default(properties);
} else {
if (defined_default(packetData.cartesian)) {
packetData.array = packetData.cartesian.map(unpackCartesianArray);
} else if (defined_default(packetData.cartographicRadians)) {
packetData.array = packetData.cartographicRadians.map(
unpackCartographicRadiansArray
);
} else if (defined_default(packetData.cartographicDegrees)) {
packetData.array = packetData.cartographicDegrees.map(
unpackCartographicDegreesArray
);
}
if (defined_default(packetData.array)) {
processPacketData(
Array,
object2,
propertyName,
packetData,
void 0,
void 0,
entityCollection
);
}
}
}
function processPositionArrayOfArrays(object2, propertyName, packetData, entityCollection) {
if (!defined_default(packetData)) {
return;
}
if (Array.isArray(packetData)) {
for (let i = 0, length2 = packetData.length; i < length2; ++i) {
processPositionArrayOfArraysPacketData(
object2,
propertyName,
packetData[i],
entityCollection
);
}
} else {
processPositionArrayOfArraysPacketData(
object2,
propertyName,
packetData,
entityCollection
);
}
}
function processShape(object2, propertyName, packetData, entityCollection) {
if (!defined_default(packetData)) {
return;
}
if (Array.isArray(packetData)) {
for (let i = 0, length2 = packetData.length; i < length2; i++) {
processShapePacketData(
object2,
propertyName,
packetData[i],
entityCollection
);
}
} else {
processShapePacketData(object2, propertyName, packetData, entityCollection);
}
}
function processAvailability(entity, packet, entityCollection, sourceUri) {
const packetData = packet.availability;
if (!defined_default(packetData)) {
return;
}
let intervals;
if (Array.isArray(packetData)) {
for (let i = 0, len = packetData.length; i < len; ++i) {
if (!defined_default(intervals)) {
intervals = new TimeIntervalCollection_default();
}
intervals.addInterval(intervalFromString(packetData[i]));
}
} else {
intervals = new TimeIntervalCollection_default();
intervals.addInterval(intervalFromString(packetData));
}
entity.availability = intervals;
}
function processAlignedAxis(billboard, packetData, interval, sourceUri, entityCollection) {
if (!defined_default(packetData)) {
return;
}
processPacketData(
UnitCartesian3,
billboard,
"alignedAxis",
packetData,
interval,
sourceUri,
entityCollection
);
}
function processBillboard(entity, packet, entityCollection, sourceUri) {
const billboardData = packet.billboard;
if (!defined_default(billboardData)) {
return;
}
const interval = intervalFromString(billboardData.interval);
let billboard = entity.billboard;
if (!defined_default(billboard)) {
entity.billboard = billboard = new BillboardGraphics_default();
}
processPacketData(
Boolean,
billboard,
"show",
billboardData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
Image,
billboard,
"image",
billboardData.image,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
billboard,
"scale",
billboardData.scale,
interval,
sourceUri,
entityCollection
);
processPacketData(
Cartesian2_default,
billboard,
"pixelOffset",
billboardData.pixelOffset,
interval,
sourceUri,
entityCollection
);
processPacketData(
Cartesian3_default,
billboard,
"eyeOffset",
billboardData.eyeOffset,
interval,
sourceUri,
entityCollection
);
processPacketData(
HorizontalOrigin_default,
billboard,
"horizontalOrigin",
billboardData.horizontalOrigin,
interval,
sourceUri,
entityCollection
);
processPacketData(
VerticalOrigin_default,
billboard,
"verticalOrigin",
billboardData.verticalOrigin,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
billboard,
"heightReference",
billboardData.heightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
billboard,
"color",
billboardData.color,
interval,
sourceUri,
entityCollection
);
processPacketData(
Rotation_default,
billboard,
"rotation",
billboardData.rotation,
interval,
sourceUri,
entityCollection
);
processAlignedAxis(
billboard,
billboardData.alignedAxis,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
billboard,
"sizeInMeters",
billboardData.sizeInMeters,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
billboard,
"width",
billboardData.width,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
billboard,
"height",
billboardData.height,
interval,
sourceUri,
entityCollection
);
processPacketData(
NearFarScalar_default,
billboard,
"scaleByDistance",
billboardData.scaleByDistance,
interval,
sourceUri,
entityCollection
);
processPacketData(
NearFarScalar_default,
billboard,
"translucencyByDistance",
billboardData.translucencyByDistance,
interval,
sourceUri,
entityCollection
);
processPacketData(
NearFarScalar_default,
billboard,
"pixelOffsetScaleByDistance",
billboardData.pixelOffsetScaleByDistance,
interval,
sourceUri,
entityCollection
);
processPacketData(
BoundingRectangle_default,
billboard,
"imageSubRegion",
billboardData.imageSubRegion,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
billboard,
"distanceDisplayCondition",
billboardData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
billboard,
"disableDepthTestDistance",
billboardData.disableDepthTestDistance,
interval,
sourceUri,
entityCollection
);
}
function processBox(entity, packet, entityCollection, sourceUri) {
const boxData = packet.box;
if (!defined_default(boxData)) {
return;
}
const interval = intervalFromString(boxData.interval);
let box = entity.box;
if (!defined_default(box)) {
entity.box = box = new BoxGraphics_default();
}
processPacketData(
Boolean,
box,
"show",
boxData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
Cartesian3_default,
box,
"dimensions",
boxData.dimensions,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
box,
"heightReference",
boxData.heightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
box,
"fill",
boxData.fill,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
box,
"material",
boxData.material,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
box,
"outline",
boxData.outline,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
box,
"outlineColor",
boxData.outlineColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
box,
"outlineWidth",
boxData.outlineWidth,
interval,
sourceUri,
entityCollection
);
processPacketData(
ShadowMode_default,
box,
"shadows",
boxData.shadows,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
box,
"distanceDisplayCondition",
boxData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
}
function processCorridor(entity, packet, entityCollection, sourceUri) {
const corridorData = packet.corridor;
if (!defined_default(corridorData)) {
return;
}
const interval = intervalFromString(corridorData.interval);
let corridor = entity.corridor;
if (!defined_default(corridor)) {
entity.corridor = corridor = new CorridorGraphics_default();
}
processPacketData(
Boolean,
corridor,
"show",
corridorData.show,
interval,
sourceUri,
entityCollection
);
processPositionArray(
corridor,
"positions",
corridorData.positions,
entityCollection
);
processPacketData(
Number,
corridor,
"width",
corridorData.width,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
corridor,
"height",
corridorData.height,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
corridor,
"heightReference",
corridorData.heightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
corridor,
"extrudedHeight",
corridorData.extrudedHeight,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
corridor,
"extrudedHeightReference",
corridorData.extrudedHeightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
CornerType_default,
corridor,
"cornerType",
corridorData.cornerType,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
corridor,
"granularity",
corridorData.granularity,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
corridor,
"fill",
corridorData.fill,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
corridor,
"material",
corridorData.material,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
corridor,
"outline",
corridorData.outline,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
corridor,
"outlineColor",
corridorData.outlineColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
corridor,
"outlineWidth",
corridorData.outlineWidth,
interval,
sourceUri,
entityCollection
);
processPacketData(
ShadowMode_default,
corridor,
"shadows",
corridorData.shadows,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
corridor,
"distanceDisplayCondition",
corridorData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
processPacketData(
ClassificationType_default,
corridor,
"classificationType",
corridorData.classificationType,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
corridor,
"zIndex",
corridorData.zIndex,
interval,
sourceUri,
entityCollection
);
}
function processCylinder(entity, packet, entityCollection, sourceUri) {
const cylinderData = packet.cylinder;
if (!defined_default(cylinderData)) {
return;
}
const interval = intervalFromString(cylinderData.interval);
let cylinder = entity.cylinder;
if (!defined_default(cylinder)) {
entity.cylinder = cylinder = new CylinderGraphics_default();
}
processPacketData(
Boolean,
cylinder,
"show",
cylinderData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
cylinder,
"length",
cylinderData.length,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
cylinder,
"topRadius",
cylinderData.topRadius,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
cylinder,
"bottomRadius",
cylinderData.bottomRadius,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
cylinder,
"heightReference",
cylinderData.heightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
cylinder,
"fill",
cylinderData.fill,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
cylinder,
"material",
cylinderData.material,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
cylinder,
"outline",
cylinderData.outline,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
cylinder,
"outlineColor",
cylinderData.outlineColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
cylinder,
"outlineWidth",
cylinderData.outlineWidth,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
cylinder,
"numberOfVerticalLines",
cylinderData.numberOfVerticalLines,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
cylinder,
"slices",
cylinderData.slices,
interval,
sourceUri,
entityCollection
);
processPacketData(
ShadowMode_default,
cylinder,
"shadows",
cylinderData.shadows,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
cylinder,
"distanceDisplayCondition",
cylinderData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
}
function processDocument(packet, dataSource) {
const version2 = packet.version;
if (defined_default(version2)) {
if (typeof version2 === "string") {
const tokens = version2.split(".");
if (tokens.length === 2) {
if (tokens[0] !== "1") {
throw new RuntimeError_default("Cesium only supports CZML version 1.");
}
dataSource._version = version2;
}
}
}
if (!defined_default(dataSource._version)) {
throw new RuntimeError_default(
"CZML version information invalid. It is expected to be a property on the document object in the . version format."
);
}
const documentPacket = dataSource._documentPacket;
if (defined_default(packet.name)) {
documentPacket.name = packet.name;
}
const clockPacket = packet.clock;
if (defined_default(clockPacket)) {
const clock = documentPacket.clock;
if (!defined_default(clock)) {
documentPacket.clock = {
interval: clockPacket.interval,
currentTime: clockPacket.currentTime,
range: clockPacket.range,
step: clockPacket.step,
multiplier: clockPacket.multiplier
};
} else {
clock.interval = clockPacket.interval ?? clock.interval;
clock.currentTime = clockPacket.currentTime ?? clock.currentTime;
clock.range = clockPacket.range ?? clock.range;
clock.step = clockPacket.step ?? clock.step;
clock.multiplier = clockPacket.multiplier ?? clock.multiplier;
}
}
}
function processEllipse(entity, packet, entityCollection, sourceUri) {
const ellipseData = packet.ellipse;
if (!defined_default(ellipseData)) {
return;
}
const interval = intervalFromString(ellipseData.interval);
let ellipse = entity.ellipse;
if (!defined_default(ellipse)) {
entity.ellipse = ellipse = new EllipseGraphics_default();
}
processPacketData(
Boolean,
ellipse,
"show",
ellipseData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipse,
"semiMajorAxis",
ellipseData.semiMajorAxis,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipse,
"semiMinorAxis",
ellipseData.semiMinorAxis,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipse,
"height",
ellipseData.height,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
ellipse,
"heightReference",
ellipseData.heightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipse,
"extrudedHeight",
ellipseData.extrudedHeight,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
ellipse,
"extrudedHeightReference",
ellipseData.extrudedHeightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Rotation_default,
ellipse,
"rotation",
ellipseData.rotation,
interval,
sourceUri,
entityCollection
);
processPacketData(
Rotation_default,
ellipse,
"stRotation",
ellipseData.stRotation,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipse,
"granularity",
ellipseData.granularity,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
ellipse,
"fill",
ellipseData.fill,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
ellipse,
"material",
ellipseData.material,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
ellipse,
"outline",
ellipseData.outline,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
ellipse,
"outlineColor",
ellipseData.outlineColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipse,
"outlineWidth",
ellipseData.outlineWidth,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipse,
"numberOfVerticalLines",
ellipseData.numberOfVerticalLines,
interval,
sourceUri,
entityCollection
);
processPacketData(
ShadowMode_default,
ellipse,
"shadows",
ellipseData.shadows,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
ellipse,
"distanceDisplayCondition",
ellipseData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
processPacketData(
ClassificationType_default,
ellipse,
"classificationType",
ellipseData.classificationType,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipse,
"zIndex",
ellipseData.zIndex,
interval,
sourceUri,
entityCollection
);
}
function processEllipsoid(entity, packet, entityCollection, sourceUri) {
const ellipsoidData = packet.ellipsoid;
if (!defined_default(ellipsoidData)) {
return;
}
const interval = intervalFromString(ellipsoidData.interval);
let ellipsoid = entity.ellipsoid;
if (!defined_default(ellipsoid)) {
entity.ellipsoid = ellipsoid = new EllipsoidGraphics_default();
}
processPacketData(
Boolean,
ellipsoid,
"show",
ellipsoidData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
Cartesian3_default,
ellipsoid,
"radii",
ellipsoidData.radii,
interval,
sourceUri,
entityCollection
);
processPacketData(
Cartesian3_default,
ellipsoid,
"innerRadii",
ellipsoidData.innerRadii,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipsoid,
"minimumClock",
ellipsoidData.minimumClock,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipsoid,
"maximumClock",
ellipsoidData.maximumClock,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipsoid,
"minimumCone",
ellipsoidData.minimumCone,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipsoid,
"maximumCone",
ellipsoidData.maximumCone,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
ellipsoid,
"heightReference",
ellipsoidData.heightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
ellipsoid,
"fill",
ellipsoidData.fill,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
ellipsoid,
"material",
ellipsoidData.material,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
ellipsoid,
"outline",
ellipsoidData.outline,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
ellipsoid,
"outlineColor",
ellipsoidData.outlineColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipsoid,
"outlineWidth",
ellipsoidData.outlineWidth,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipsoid,
"stackPartitions",
ellipsoidData.stackPartitions,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipsoid,
"slicePartitions",
ellipsoidData.slicePartitions,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
ellipsoid,
"subdivisions",
ellipsoidData.subdivisions,
interval,
sourceUri,
entityCollection
);
processPacketData(
ShadowMode_default,
ellipsoid,
"shadows",
ellipsoidData.shadows,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
ellipsoid,
"distanceDisplayCondition",
ellipsoidData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
}
function processLabel(entity, packet, entityCollection, sourceUri) {
const labelData = packet.label;
if (!defined_default(labelData)) {
return;
}
const interval = intervalFromString(labelData.interval);
let label = entity.label;
if (!defined_default(label)) {
entity.label = label = new LabelGraphics_default();
}
processPacketData(
Boolean,
label,
"show",
labelData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
String,
label,
"text",
labelData.text,
interval,
sourceUri,
entityCollection
);
processPacketData(
String,
label,
"font",
labelData.font,
interval,
sourceUri,
entityCollection
);
processPacketData(
LabelStyle_default,
label,
"style",
labelData.style,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
label,
"scale",
labelData.scale,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
label,
"showBackground",
labelData.showBackground,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
label,
"backgroundColor",
labelData.backgroundColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Cartesian2_default,
label,
"backgroundPadding",
labelData.backgroundPadding,
interval,
sourceUri,
entityCollection
);
processPacketData(
Cartesian2_default,
label,
"pixelOffset",
labelData.pixelOffset,
interval,
sourceUri,
entityCollection
);
processPacketData(
Cartesian3_default,
label,
"eyeOffset",
labelData.eyeOffset,
interval,
sourceUri,
entityCollection
);
processPacketData(
HorizontalOrigin_default,
label,
"horizontalOrigin",
labelData.horizontalOrigin,
interval,
sourceUri,
entityCollection
);
processPacketData(
VerticalOrigin_default,
label,
"verticalOrigin",
labelData.verticalOrigin,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
label,
"heightReference",
labelData.heightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
label,
"fillColor",
labelData.fillColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
label,
"outlineColor",
labelData.outlineColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
label,
"outlineWidth",
labelData.outlineWidth,
interval,
sourceUri,
entityCollection
);
processPacketData(
NearFarScalar_default,
label,
"translucencyByDistance",
labelData.translucencyByDistance,
interval,
sourceUri,
entityCollection
);
processPacketData(
NearFarScalar_default,
label,
"pixelOffsetScaleByDistance",
labelData.pixelOffsetScaleByDistance,
interval,
sourceUri,
entityCollection
);
processPacketData(
NearFarScalar_default,
label,
"scaleByDistance",
labelData.scaleByDistance,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
label,
"distanceDisplayCondition",
labelData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
label,
"disableDepthTestDistance",
labelData.disableDepthTestDistance,
interval,
sourceUri,
entityCollection
);
}
function processModel(entity, packet, entityCollection, sourceUri) {
const modelData = packet.model;
if (!defined_default(modelData)) {
return;
}
const interval = intervalFromString(modelData.interval);
let model = entity.model;
if (!defined_default(model)) {
entity.model = model = new ModelGraphics_default();
}
processPacketData(
Boolean,
model,
"show",
modelData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
import_urijs10.default,
model,
"uri",
modelData.gltf,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
model,
"scale",
modelData.scale,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
model,
"minimumPixelSize",
modelData.minimumPixelSize,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
model,
"maximumScale",
modelData.maximumScale,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
model,
"incrementallyLoadTextures",
modelData.incrementallyLoadTextures,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
model,
"runAnimations",
modelData.runAnimations,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
model,
"clampAnimations",
modelData.clampAnimations,
interval,
sourceUri,
entityCollection
);
processPacketData(
ShadowMode_default,
model,
"shadows",
modelData.shadows,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
model,
"heightReference",
modelData.heightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
model,
"silhouetteColor",
modelData.silhouetteColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
model,
"silhouetteSize",
modelData.silhouetteSize,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
model,
"color",
modelData.color,
interval,
sourceUri,
entityCollection
);
processPacketData(
ColorBlendMode_default,
model,
"colorBlendMode",
modelData.colorBlendMode,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
model,
"colorBlendAmount",
modelData.colorBlendAmount,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
model,
"distanceDisplayCondition",
modelData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
let i, len;
const nodeTransformationsData = modelData.nodeTransformations;
if (defined_default(nodeTransformationsData)) {
if (Array.isArray(nodeTransformationsData)) {
for (i = 0, len = nodeTransformationsData.length; i < len; ++i) {
processNodeTransformations(
model,
nodeTransformationsData[i],
interval,
sourceUri,
entityCollection
);
}
} else {
processNodeTransformations(
model,
nodeTransformationsData,
interval,
sourceUri,
entityCollection
);
}
}
const articulationsData = modelData.articulations;
if (defined_default(articulationsData)) {
if (Array.isArray(articulationsData)) {
for (i = 0, len = articulationsData.length; i < len; ++i) {
processArticulations(
model,
articulationsData[i],
interval,
sourceUri,
entityCollection
);
}
} else {
processArticulations(
model,
articulationsData,
interval,
sourceUri,
entityCollection
);
}
}
}
function processNodeTransformations(model, nodeTransformationsData, constrainedInterval, sourceUri, entityCollection) {
let combinedInterval = intervalFromString(nodeTransformationsData.interval);
if (defined_default(constrainedInterval)) {
if (defined_default(combinedInterval)) {
combinedInterval = TimeInterval_default.intersect(
combinedInterval,
constrainedInterval,
scratchTimeInterval
);
} else {
combinedInterval = constrainedInterval;
}
}
let nodeTransformations = model.nodeTransformations;
const nodeNames = Object.keys(nodeTransformationsData);
for (let i = 0, len = nodeNames.length; i < len; ++i) {
const nodeName = nodeNames[i];
if (nodeName === "interval") {
continue;
}
const nodeTransformationData = nodeTransformationsData[nodeName];
if (!defined_default(nodeTransformationData)) {
continue;
}
if (!defined_default(nodeTransformations)) {
model.nodeTransformations = nodeTransformations = new PropertyBag_default();
}
if (!nodeTransformations.hasProperty(nodeName)) {
nodeTransformations.addProperty(nodeName);
}
let nodeTransformation = nodeTransformations[nodeName];
if (!defined_default(nodeTransformation)) {
nodeTransformations[nodeName] = nodeTransformation = new NodeTransformationProperty_default();
}
processPacketData(
Cartesian3_default,
nodeTransformation,
"translation",
nodeTransformationData.translation,
combinedInterval,
sourceUri,
entityCollection
);
processPacketData(
Quaternion_default,
nodeTransformation,
"rotation",
nodeTransformationData.rotation,
combinedInterval,
sourceUri,
entityCollection
);
processPacketData(
Cartesian3_default,
nodeTransformation,
"scale",
nodeTransformationData.scale,
combinedInterval,
sourceUri,
entityCollection
);
}
}
function processArticulations(model, articulationsData, constrainedInterval, sourceUri, entityCollection) {
let combinedInterval = intervalFromString(articulationsData.interval);
if (defined_default(constrainedInterval)) {
if (defined_default(combinedInterval)) {
combinedInterval = TimeInterval_default.intersect(
combinedInterval,
constrainedInterval,
scratchTimeInterval
);
} else {
combinedInterval = constrainedInterval;
}
}
let articulations = model.articulations;
const keys = Object.keys(articulationsData);
for (let i = 0, len = keys.length; i < len; ++i) {
const key = keys[i];
if (key === "interval") {
continue;
}
const articulationStageData = articulationsData[key];
if (!defined_default(articulationStageData)) {
continue;
}
if (!defined_default(articulations)) {
model.articulations = articulations = new PropertyBag_default();
}
if (!articulations.hasProperty(key)) {
articulations.addProperty(key);
}
processPacketData(
Number,
articulations,
key,
articulationStageData,
combinedInterval,
sourceUri,
entityCollection
);
}
}
function processPath(entity, packet, entityCollection, sourceUri) {
const pathData = packet.path;
if (!defined_default(pathData)) {
return;
}
const interval = intervalFromString(pathData.interval);
let path = entity.path;
if (!defined_default(path)) {
entity.path = path = new PathGraphics_default();
}
processPacketData(
Boolean,
path,
"show",
pathData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
path,
"leadTime",
pathData.leadTime,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
path,
"trailTime",
pathData.trailTime,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
path,
"width",
pathData.width,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
path,
"resolution",
pathData.resolution,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
path,
"material",
pathData.material,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
path,
"distanceDisplayCondition",
pathData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
}
function processPoint(entity, packet, entityCollection, sourceUri) {
const pointData = packet.point;
if (!defined_default(pointData)) {
return;
}
const interval = intervalFromString(pointData.interval);
let point = entity.point;
if (!defined_default(point)) {
entity.point = point = new PointGraphics_default();
}
processPacketData(
Boolean,
point,
"show",
pointData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
point,
"pixelSize",
pointData.pixelSize,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
point,
"heightReference",
pointData.heightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
point,
"color",
pointData.color,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
point,
"outlineColor",
pointData.outlineColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
point,
"outlineWidth",
pointData.outlineWidth,
interval,
sourceUri,
entityCollection
);
processPacketData(
NearFarScalar_default,
point,
"scaleByDistance",
pointData.scaleByDistance,
interval,
sourceUri,
entityCollection
);
processPacketData(
NearFarScalar_default,
point,
"translucencyByDistance",
pointData.translucencyByDistance,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
point,
"distanceDisplayCondition",
pointData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
point,
"disableDepthTestDistance",
pointData.disableDepthTestDistance,
interval,
sourceUri,
entityCollection
);
}
function PolygonHierarchyProperty(polygon2) {
this.polygon = polygon2;
this._definitionChanged = new Event_default();
}
Object.defineProperties(PolygonHierarchyProperty.prototype, {
isConstant: {
get: function() {
const positions = this.polygon._positions;
const holes = this.polygon._holes;
return (!defined_default(positions) || positions.isConstant) && (!defined_default(holes) || holes.isConstant);
}
},
definitionChanged: {
get: function() {
return this._definitionChanged;
}
}
});
PolygonHierarchyProperty.prototype.getValue = function(time, result) {
let positions;
if (defined_default(this.polygon._positions)) {
positions = this.polygon._positions.getValue(time);
}
let holes;
if (defined_default(this.polygon._holes)) {
holes = this.polygon._holes.getValue(time);
if (defined_default(holes)) {
holes = holes.map(function(holePositions) {
return new PolygonHierarchy_default(holePositions);
});
}
}
if (!defined_default(result)) {
return new PolygonHierarchy_default(positions, holes);
}
result.positions = positions;
result.holes = holes;
return result;
};
PolygonHierarchyProperty.prototype.equals = function(other) {
return this === other || other instanceof PolygonHierarchyProperty && Property_default.equals(this.polygon._positions, other.polygon._positions) && Property_default.equals(this.polygon._holes, other.polygon._holes);
};
function processPolygon(entity, packet, entityCollection, sourceUri) {
const polygonData = packet.polygon;
if (!defined_default(polygonData)) {
return;
}
const interval = intervalFromString(polygonData.interval);
let polygon2 = entity.polygon;
if (!defined_default(polygon2)) {
entity.polygon = polygon2 = new PolygonGraphics_default();
}
processPacketData(
Boolean,
polygon2,
"show",
polygonData.show,
interval,
sourceUri,
entityCollection
);
processPositionArray(
polygon2,
"_positions",
polygonData.positions,
entityCollection
);
processPositionArrayOfArrays(
polygon2,
"_holes",
polygonData.holes,
entityCollection
);
if (defined_default(polygon2._positions) || defined_default(polygon2._holes)) {
polygon2.hierarchy = new PolygonHierarchyProperty(polygon2);
}
processPacketData(
Number,
polygon2,
"height",
polygonData.height,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
polygon2,
"heightReference",
polygonData.heightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
polygon2,
"extrudedHeight",
polygonData.extrudedHeight,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
polygon2,
"extrudedHeightReference",
polygonData.extrudedHeightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Rotation_default,
polygon2,
"stRotation",
polygonData.stRotation,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
polygon2,
"granularity",
polygonData.granularity,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
polygon2,
"fill",
polygonData.fill,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
polygon2,
"material",
polygonData.material,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
polygon2,
"outline",
polygonData.outline,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
polygon2,
"outlineColor",
polygonData.outlineColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
polygon2,
"outlineWidth",
polygonData.outlineWidth,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
polygon2,
"perPositionHeight",
polygonData.perPositionHeight,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
polygon2,
"closeTop",
polygonData.closeTop,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
polygon2,
"closeBottom",
polygonData.closeBottom,
interval,
sourceUri,
entityCollection
);
processPacketData(
ArcType_default,
polygon2,
"arcType",
polygonData.arcType,
interval,
sourceUri,
entityCollection
);
processPacketData(
ShadowMode_default,
polygon2,
"shadows",
polygonData.shadows,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
polygon2,
"distanceDisplayCondition",
polygonData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
processPacketData(
ClassificationType_default,
polygon2,
"classificationType",
polygonData.classificationType,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
polygon2,
"zIndex",
polygonData.zIndex,
interval,
sourceUri,
entityCollection
);
}
function adaptFollowSurfaceToArcType(followSurface) {
return followSurface ? ArcType_default.GEODESIC : ArcType_default.NONE;
}
function processPolyline(entity, packet, entityCollection, sourceUri) {
const polylineData = packet.polyline;
if (!defined_default(polylineData)) {
return;
}
const interval = intervalFromString(polylineData.interval);
let polyline = entity.polyline;
if (!defined_default(polyline)) {
entity.polyline = polyline = new PolylineGraphics_default();
}
processPacketData(
Boolean,
polyline,
"show",
polylineData.show,
interval,
sourceUri,
entityCollection
);
processPositionArray(
polyline,
"positions",
polylineData.positions,
entityCollection
);
processPacketData(
Number,
polyline,
"width",
polylineData.width,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
polyline,
"granularity",
polylineData.granularity,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
polyline,
"material",
polylineData.material,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
polyline,
"depthFailMaterial",
polylineData.depthFailMaterial,
interval,
sourceUri,
entityCollection
);
processPacketData(
ArcType_default,
polyline,
"arcType",
polylineData.arcType,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
polyline,
"clampToGround",
polylineData.clampToGround,
interval,
sourceUri,
entityCollection
);
processPacketData(
ShadowMode_default,
polyline,
"shadows",
polylineData.shadows,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
polyline,
"distanceDisplayCondition",
polylineData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
processPacketData(
ClassificationType_default,
polyline,
"classificationType",
polylineData.classificationType,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
polyline,
"zIndex",
polylineData.zIndex,
interval,
sourceUri,
entityCollection
);
if (defined_default(polylineData.followSurface) && !defined_default(polylineData.arcType)) {
const tempObj = {};
processPacketData(
Boolean,
tempObj,
"followSurface",
polylineData.followSurface,
interval,
sourceUri,
entityCollection
);
polyline.arcType = createAdapterProperty(
tempObj.followSurface,
adaptFollowSurfaceToArcType
);
}
}
function processPolylineVolume(entity, packet, entityCollection, sourceUri) {
const polylineVolumeData = packet.polylineVolume;
if (!defined_default(polylineVolumeData)) {
return;
}
const interval = intervalFromString(polylineVolumeData.interval);
let polylineVolume = entity.polylineVolume;
if (!defined_default(polylineVolume)) {
entity.polylineVolume = polylineVolume = new PolylineVolumeGraphics_default();
}
processPositionArray(
polylineVolume,
"positions",
polylineVolumeData.positions,
entityCollection
);
processShape(
polylineVolume,
"shape",
polylineVolumeData.shape,
entityCollection
);
processPacketData(
Boolean,
polylineVolume,
"show",
polylineVolumeData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
CornerType_default,
polylineVolume,
"cornerType",
polylineVolumeData.cornerType,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
polylineVolume,
"fill",
polylineVolumeData.fill,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
polylineVolume,
"material",
polylineVolumeData.material,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
polylineVolume,
"outline",
polylineVolumeData.outline,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
polylineVolume,
"outlineColor",
polylineVolumeData.outlineColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
polylineVolume,
"outlineWidth",
polylineVolumeData.outlineWidth,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
polylineVolume,
"granularity",
polylineVolumeData.granularity,
interval,
sourceUri,
entityCollection
);
processPacketData(
ShadowMode_default,
polylineVolume,
"shadows",
polylineVolumeData.shadows,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
polylineVolume,
"distanceDisplayCondition",
polylineVolumeData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
}
function processRectangle(entity, packet, entityCollection, sourceUri) {
const rectangleData = packet.rectangle;
if (!defined_default(rectangleData)) {
return;
}
const interval = intervalFromString(rectangleData.interval);
let rectangle = entity.rectangle;
if (!defined_default(rectangle)) {
entity.rectangle = rectangle = new RectangleGraphics_default();
}
processPacketData(
Boolean,
rectangle,
"show",
rectangleData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
Rectangle_default,
rectangle,
"coordinates",
rectangleData.coordinates,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
rectangle,
"height",
rectangleData.height,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
rectangle,
"heightReference",
rectangleData.heightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
rectangle,
"extrudedHeight",
rectangleData.extrudedHeight,
interval,
sourceUri,
entityCollection
);
processPacketData(
HeightReference_default,
rectangle,
"extrudedHeightReference",
rectangleData.extrudedHeightReference,
interval,
sourceUri,
entityCollection
);
processPacketData(
Rotation_default,
rectangle,
"rotation",
rectangleData.rotation,
interval,
sourceUri,
entityCollection
);
processPacketData(
Rotation_default,
rectangle,
"stRotation",
rectangleData.stRotation,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
rectangle,
"granularity",
rectangleData.granularity,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
rectangle,
"fill",
rectangleData.fill,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
rectangle,
"material",
rectangleData.material,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
rectangle,
"outline",
rectangleData.outline,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
rectangle,
"outlineColor",
rectangleData.outlineColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
rectangle,
"outlineWidth",
rectangleData.outlineWidth,
interval,
sourceUri,
entityCollection
);
processPacketData(
ShadowMode_default,
rectangle,
"shadows",
rectangleData.shadows,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
rectangle,
"distanceDisplayCondition",
rectangleData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
processPacketData(
ClassificationType_default,
rectangle,
"classificationType",
rectangleData.classificationType,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
rectangle,
"zIndex",
rectangleData.zIndex,
interval,
sourceUri,
entityCollection
);
}
function processTileset(entity, packet, entityCollection, sourceUri) {
const tilesetData = packet.tileset;
if (!defined_default(tilesetData)) {
return;
}
const interval = intervalFromString(tilesetData.interval);
let tileset = entity.tileset;
if (!defined_default(tileset)) {
entity.tileset = tileset = new Cesium3DTilesetGraphics_default();
}
processPacketData(
Boolean,
tileset,
"show",
tilesetData.show,
interval,
sourceUri,
entityCollection
);
processPacketData(
import_urijs10.default,
tileset,
"uri",
tilesetData.uri,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
tileset,
"maximumScreenSpaceError",
tilesetData.maximumScreenSpaceError,
interval,
sourceUri,
entityCollection
);
}
function processWall(entity, packet, entityCollection, sourceUri) {
const wallData = packet.wall;
if (!defined_default(wallData)) {
return;
}
const interval = intervalFromString(wallData.interval);
let wall = entity.wall;
if (!defined_default(wall)) {
entity.wall = wall = new WallGraphics_default();
}
processPacketData(
Boolean,
wall,
"show",
wallData.show,
interval,
sourceUri,
entityCollection
);
processPositionArray(wall, "positions", wallData.positions, entityCollection);
processArray(
wall,
"minimumHeights",
wallData.minimumHeights,
entityCollection
);
processArray(
wall,
"maximumHeights",
wallData.maximumHeights,
entityCollection
);
processPacketData(
Number,
wall,
"granularity",
wallData.granularity,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
wall,
"fill",
wallData.fill,
interval,
sourceUri,
entityCollection
);
processMaterialPacketData(
wall,
"material",
wallData.material,
interval,
sourceUri,
entityCollection
);
processPacketData(
Boolean,
wall,
"outline",
wallData.outline,
interval,
sourceUri,
entityCollection
);
processPacketData(
Color_default,
wall,
"outlineColor",
wallData.outlineColor,
interval,
sourceUri,
entityCollection
);
processPacketData(
Number,
wall,
"outlineWidth",
wallData.outlineWidth,
interval,
sourceUri,
entityCollection
);
processPacketData(
ShadowMode_default,
wall,
"shadows",
wallData.shadows,
interval,
sourceUri,
entityCollection
);
processPacketData(
DistanceDisplayCondition_default,
wall,
"distanceDisplayCondition",
wallData.distanceDisplayCondition,
interval,
sourceUri,
entityCollection
);
}
function processCzmlPacket(packet, entityCollection, updaterFunctions, sourceUri, dataSource) {
let objectId = packet.id;
if (!defined_default(objectId)) {
objectId = createGuid_default();
}
currentId = objectId;
if (!defined_default(dataSource._version) && objectId !== "document") {
throw new RuntimeError_default(
"The first CZML packet is required to be the document object."
);
}
if (packet["delete"] === true) {
entityCollection.removeById(objectId);
} else if (objectId === "document") {
processDocument(packet, dataSource);
} else {
const entity = entityCollection.getOrCreateEntity(objectId);
const parentId = packet.parent;
if (defined_default(parentId)) {
entity.parent = entityCollection.getOrCreateEntity(parentId);
}
for (let i = updaterFunctions.length - 1; i > -1; i--) {
updaterFunctions[i](entity, packet, entityCollection, sourceUri);
}
}
currentId = void 0;
}
function updateClock(dataSource) {
let clock;
const clockPacket = dataSource._documentPacket.clock;
if (!defined_default(clockPacket)) {
if (!defined_default(dataSource._clock)) {
const availability = dataSource._entityCollection.computeAvailability();
if (!availability.start.equals(Iso8601_default.MINIMUM_VALUE)) {
const startTime = availability.start;
const stopTime = availability.stop;
const totalSeconds = JulianDate_default.secondsDifference(stopTime, startTime);
const multiplier = Math.round(totalSeconds / 120);
clock = new DataSourceClock_default();
clock.startTime = JulianDate_default.clone(startTime);
clock.stopTime = JulianDate_default.clone(stopTime);
clock.clockRange = ClockRange_default.LOOP_STOP;
clock.multiplier = multiplier;
clock.currentTime = JulianDate_default.clone(startTime);
clock.clockStep = ClockStep_default.SYSTEM_CLOCK_MULTIPLIER;
dataSource._clock = clock;
return true;
}
}
return false;
}
if (defined_default(dataSource._clock)) {
clock = dataSource._clock.clone();
} else {
clock = new DataSourceClock_default();
clock.startTime = Iso8601_default.MINIMUM_VALUE.clone();
clock.stopTime = Iso8601_default.MAXIMUM_VALUE.clone();
clock.currentTime = Iso8601_default.MINIMUM_VALUE.clone();
clock.clockRange = ClockRange_default.LOOP_STOP;
clock.clockStep = ClockStep_default.SYSTEM_CLOCK_MULTIPLIER;
clock.multiplier = 1;
}
const interval = intervalFromString(clockPacket.interval);
if (defined_default(interval)) {
clock.startTime = interval.start;
clock.stopTime = interval.stop;
}
if (defined_default(clockPacket.currentTime)) {
clock.currentTime = JulianDate_default.fromIso8601(clockPacket.currentTime);
}
if (defined_default(clockPacket.range)) {
clock.clockRange = ClockRange_default[clockPacket.range] ?? ClockRange_default.LOOP_STOP;
}
if (defined_default(clockPacket.step)) {
clock.clockStep = ClockStep_default[clockPacket.step] ?? ClockStep_default.SYSTEM_CLOCK_MULTIPLIER;
}
if (defined_default(clockPacket.multiplier)) {
clock.multiplier = clockPacket.multiplier;
}
if (!clock.equals(dataSource._clock)) {
dataSource._clock = clock.clone(dataSource._clock);
return true;
}
return false;
}
function load(dataSource, czml, options, clear2) {
if (!defined_default(czml)) {
throw new DeveloperError_default("czml is required.");
}
options = options ?? Frozen_default.EMPTY_OBJECT;
let promise = czml;
let sourceUri = options.sourceUri;
let credit = options.credit;
if (typeof credit === "string") {
credit = new Credit_default(credit);
}
dataSource._credit = credit;
if (typeof czml === "string" || czml instanceof Resource_default) {
czml = Resource_default.createIfNeeded(czml);
promise = czml.fetchJson();
sourceUri = sourceUri ?? czml.clone();
const resourceCredits = dataSource._resourceCredits;
const credits = czml.credits;
if (defined_default(credits)) {
const length2 = credits.length;
for (let i = 0; i < length2; i++) {
resourceCredits.push(credits[i]);
}
}
}
sourceUri = Resource_default.createIfNeeded(sourceUri);
DataSource_default.setLoading(dataSource, true);
return Promise.resolve(promise).then(function(czml2) {
return loadCzml(dataSource, czml2, sourceUri, clear2);
}).catch(function(error) {
DataSource_default.setLoading(dataSource, false);
dataSource._error.raiseEvent(dataSource, error);
console.log(error);
return Promise.reject(error);
});
}
function loadCzml(dataSource, czml, sourceUri, clear2) {
DataSource_default.setLoading(dataSource, true);
const entityCollection = dataSource._entityCollection;
if (clear2) {
dataSource._version = void 0;
dataSource._documentPacket = new DocumentPacket();
entityCollection.removeAll();
}
CzmlDataSource._processCzml(
czml,
entityCollection,
sourceUri,
void 0,
dataSource
);
let raiseChangedEvent = updateClock(dataSource);
const documentPacket = dataSource._documentPacket;
if (defined_default(documentPacket.name) && dataSource._name !== documentPacket.name) {
dataSource._name = documentPacket.name;
raiseChangedEvent = true;
} else if (!defined_default(dataSource._name) && defined_default(sourceUri)) {
dataSource._name = getFilenameFromUri_default(sourceUri.getUrlComponent());
raiseChangedEvent = true;
}
DataSource_default.setLoading(dataSource, false);
if (raiseChangedEvent) {
dataSource._changed.raiseEvent(dataSource);
}
return dataSource;
}
function DocumentPacket() {
this.name = void 0;
this.clock = void 0;
}
function CzmlDataSource(name) {
this._name = name;
this._changed = new Event_default();
this._error = new Event_default();
this._isLoading = false;
this._loading = new Event_default();
this._clock = void 0;
this._documentPacket = new DocumentPacket();
this._version = void 0;
this._entityCollection = new EntityCollection_default(this);
this._entityCluster = new EntityCluster_default();
this._credit = void 0;
this._resourceCredits = [];
}
CzmlDataSource.load = function(czml, options) {
return new CzmlDataSource().load(czml, options);
};
Object.defineProperties(CzmlDataSource.prototype, {
/**
* Gets a human-readable name for this instance.
* @memberof CzmlDataSource.prototype
* @type {string}
*/
name: {
get: function() {
return this._name;
}
},
/**
* Gets the clock settings defined by the loaded CZML. If no clock is explicitly
* defined in the CZML, the combined availability of all objects is returned. If
* only static data exists, this value is undefined.
* @memberof CzmlDataSource.prototype
* @type {DataSourceClock}
*/
clock: {
get: function() {
return this._clock;
}
},
/**
* Gets the collection of {@link Entity} instances.
* @memberof CzmlDataSource.prototype
* @type {EntityCollection}
*/
entities: {
get: function() {
return this._entityCollection;
}
},
/**
* Gets a value indicating if the data source is currently loading data.
* @memberof CzmlDataSource.prototype
* @type {boolean}
*/
isLoading: {
get: function() {
return this._isLoading;
}
},
/**
* Gets an event that will be raised when the underlying data changes.
* @memberof CzmlDataSource.prototype
* @type {Event}
*/
changedEvent: {
get: function() {
return this._changed;
}
},
/**
* Gets an event that will be raised if an error is encountered during processing.
* @memberof CzmlDataSource.prototype
* @type {Event}
*/
errorEvent: {
get: function() {
return this._error;
}
},
/**
* Gets an event that will be raised when the data source either starts or stops loading.
* @memberof CzmlDataSource.prototype
* @type {Event}
*/
loadingEvent: {
get: function() {
return this._loading;
}
},
/**
* Gets whether or not this data source should be displayed.
* @memberof CzmlDataSource.prototype
* @type {boolean}
*/
show: {
get: function() {
return this._entityCollection.show;
},
set: function(value) {
this._entityCollection.show = value;
}
},
/**
* Gets or sets the clustering options for this data source. This object can be shared between multiple data sources.
*
* @memberof CzmlDataSource.prototype
* @type {EntityCluster}
*/
clustering: {
get: function() {
return this._entityCluster;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value must be defined.");
}
this._entityCluster = value;
}
},
/**
* Gets the credit that will be displayed for the data source
* @memberof CzmlDataSource.prototype
* @type {Credit}
*/
credit: {
get: function() {
return this._credit;
}
}
});
CzmlDataSource.updaters = [
processBillboard,
processBox,
processCorridor,
processCylinder,
processEllipse,
processEllipsoid,
processLabel,
processModel,
processName,
processDescription,
processPath,
processPoint,
processPolygon,
processPolyline,
processPolylineVolume,
processProperties,
processRectangle,
processPosition,
processTileset,
processViewFrom,
processWall,
processOrientation,
processAvailability
];
CzmlDataSource.registerUpdater = function(updater) {
if (!CzmlDataSource.updaters.includes(updater)) {
CzmlDataSource.updaters.push(updater);
}
};
CzmlDataSource.unregisterUpdater = function(updater) {
if (CzmlDataSource.updaters.includes(updater)) {
const index = CzmlDataSource.updaters.indexOf(updater);
CzmlDataSource.updaters.splice(index, 1);
}
};
CzmlDataSource.prototype.process = function(czml, options) {
return load(this, czml, options, false);
};
CzmlDataSource.prototype.load = function(czml, options) {
return load(this, czml, options, true);
};
CzmlDataSource.prototype.update = function(time) {
return true;
};
CzmlDataSource.processPacketData = processPacketData;
CzmlDataSource.processPositionPacketData = processPositionPacketData;
CzmlDataSource.processMaterialPacketData = processMaterialPacketData;
CzmlDataSource._processCzml = function(czml, entityCollection, sourceUri, updaterFunctions, dataSource) {
updaterFunctions = updaterFunctions ?? CzmlDataSource.updaters;
if (Array.isArray(czml)) {
for (let i = 0, len = czml.length; i < len; ++i) {
processCzmlPacket(
czml[i],
entityCollection,
updaterFunctions,
sourceUri,
dataSource
);
}
} else {
processCzmlPacket(
czml,
entityCollection,
updaterFunctions,
sourceUri,
dataSource
);
}
};
var CzmlDataSource_default = CzmlDataSource;
// packages/engine/Source/DataSources/DataSourceCollection.js
var import_InlineWorkers874 = __toESM(require_InlineWorkers(), 1);
function DataSourceCollection() {
this._dataSources = [];
this._dataSourceAdded = new Event_default();
this._dataSourceRemoved = new Event_default();
this._dataSourceMoved = new Event_default();
}
Object.defineProperties(DataSourceCollection.prototype, {
/**
* Gets the number of data sources in this collection.
* @memberof DataSourceCollection.prototype
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._dataSources.length;
}
},
/**
* An event that is raised when a data source is added to the collection.
* Event handlers are passed the data source that was added.
* @memberof DataSourceCollection.prototype
* @type {Event}
* @readonly
*/
dataSourceAdded: {
get: function() {
return this._dataSourceAdded;
}
},
/**
* An event that is raised when a data source is removed from the collection.
* Event handlers are passed the data source that was removed.
* @memberof DataSourceCollection.prototype
* @type {Event}
* @readonly
*/
dataSourceRemoved: {
get: function() {
return this._dataSourceRemoved;
}
},
/**
* An event that is raised when a data source changes position in the collection. Event handlers are passed the data source
* that was moved, its new index after the move, and its old index prior to the move.
* @memberof DataSourceCollection.prototype
* @type {Event}
* @readonly
*/
dataSourceMoved: {
get: function() {
return this._dataSourceMoved;
}
}
});
DataSourceCollection.prototype.add = function(dataSource) {
if (!defined_default(dataSource)) {
throw new DeveloperError_default("dataSource is required.");
}
const that = this;
const dataSources = this._dataSources;
return Promise.resolve(dataSource).then(function(value) {
if (dataSources === that._dataSources) {
that._dataSources.push(value);
that._dataSourceAdded.raiseEvent(that, value);
}
return value;
});
};
DataSourceCollection.prototype.remove = function(dataSource, destroy) {
destroy = destroy ?? false;
const index = this._dataSources.indexOf(dataSource);
if (index !== -1) {
this._dataSources.splice(index, 1);
this._dataSourceRemoved.raiseEvent(this, dataSource);
if (destroy && typeof dataSource.destroy === "function") {
dataSource.destroy();
}
return true;
}
return false;
};
DataSourceCollection.prototype.removeAll = function(destroy) {
destroy = destroy ?? false;
const dataSources = this._dataSources;
for (let i = 0, len = dataSources.length; i < len; ++i) {
const dataSource = dataSources[i];
this._dataSourceRemoved.raiseEvent(this, dataSource);
if (destroy && typeof dataSource.destroy === "function") {
dataSource.destroy();
}
}
this._dataSources = [];
};
DataSourceCollection.prototype.contains = function(dataSource) {
return this.indexOf(dataSource) !== -1;
};
DataSourceCollection.prototype.indexOf = function(dataSource) {
return this._dataSources.indexOf(dataSource);
};
DataSourceCollection.prototype.get = function(index) {
if (!defined_default(index)) {
throw new DeveloperError_default("index is required.");
}
return this._dataSources[index];
};
DataSourceCollection.prototype.getByName = function(name) {
if (!defined_default(name)) {
throw new DeveloperError_default("name is required.");
}
return this._dataSources.filter(function(dataSource) {
return dataSource.name === name;
});
};
function getIndex(dataSources, dataSource) {
if (!defined_default(dataSource)) {
throw new DeveloperError_default("dataSource is required.");
}
const index = dataSources.indexOf(dataSource);
if (index === -1) {
throw new DeveloperError_default("dataSource is not in this collection.");
}
return index;
}
function swapDataSources(collection, i, j) {
const arr = collection._dataSources;
const length2 = arr.length - 1;
i = Math_default.clamp(i, 0, length2);
j = Math_default.clamp(j, 0, length2);
if (i === j) {
return;
}
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
collection.dataSourceMoved.raiseEvent(temp, j, i);
}
DataSourceCollection.prototype.raise = function(dataSource) {
const index = getIndex(this._dataSources, dataSource);
swapDataSources(this, index, index + 1);
};
DataSourceCollection.prototype.lower = function(dataSource) {
const index = getIndex(this._dataSources, dataSource);
swapDataSources(this, index, index - 1);
};
DataSourceCollection.prototype.raiseToTop = function(dataSource) {
const index = getIndex(this._dataSources, dataSource);
if (index === this._dataSources.length - 1) {
return;
}
this._dataSources.splice(index, 1);
this._dataSources.push(dataSource);
this.dataSourceMoved.raiseEvent(
dataSource,
this._dataSources.length - 1,
index
);
};
DataSourceCollection.prototype.lowerToBottom = function(dataSource) {
const index = getIndex(this._dataSources, dataSource);
if (index === 0) {
return;
}
this._dataSources.splice(index, 1);
this._dataSources.splice(0, 0, dataSource);
this.dataSourceMoved.raiseEvent(dataSource, 0, index);
};
DataSourceCollection.prototype.isDestroyed = function() {
return false;
};
DataSourceCollection.prototype.destroy = function() {
this.removeAll(true);
return destroyObject_default(this);
};
var DataSourceCollection_default = DataSourceCollection;
// packages/engine/Source/DataSources/DataSourceDisplay.js
var import_InlineWorkers918 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/OrderedGroundPrimitiveCollection.js
var import_InlineWorkers876 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/PrimitiveCollection.js
var import_InlineWorkers875 = __toESM(require_InlineWorkers(), 1);
function PrimitiveCollection(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._primitives = [];
this._guid = createGuid_default();
this._primitiveAdded = new Event_default();
this._primitiveRemoved = new Event_default();
this._zIndex = void 0;
this.show = options.show ?? true;
this.destroyPrimitives = options.destroyPrimitives ?? true;
this._countReferences = options.countReferences ?? false;
}
Object.defineProperties(PrimitiveCollection.prototype, {
/**
* Gets the number of primitives in the collection.
*
* @memberof PrimitiveCollection.prototype
*
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._primitives.length;
}
},
/**
* An event that is raised when a primitive is added to the collection.
* Event handlers are passed the primitive that was added.
* @memberof PrimitiveCollection.prototype
* @type {Event}
* @readonly
*/
primitiveAdded: {
get: function() {
return this._primitiveAdded;
}
},
/**
* An event that is raised when a primitive is removed from the collection.
* Event handlers are passed the primitive that was removed.
*
* Note: Depending on the destroyPrimitives constructor option, the primitive may already be destroyed.
*
* @memberof PrimitiveCollection.prototype
* @type {Event}
* @readonly
*/
primitiveRemoved: {
get: function() {
return this._primitiveRemoved;
}
}
});
PrimitiveCollection.prototype.add = function(primitive, index) {
const hasIndex = defined_default(index);
if (!defined_default(primitive)) {
throw new DeveloperError_default("primitive is required.");
}
if (hasIndex) {
if (index < 0) {
throw new DeveloperError_default("index must be greater than or equal to zero.");
} else if (index > this._primitives.length) {
throw new DeveloperError_default(
"index must be less than or equal to the number of primitives."
);
}
}
const external = primitive._external = primitive._external || {};
const composites = external._composites = external._composites || {};
composites[this._guid] = {
collection: this
};
if (!hasIndex) {
this._primitives.push(primitive);
} else {
this._primitives.splice(index, 0, primitive);
}
if (this._countReferences) {
if (!defined_default(external._referenceCount)) {
external._referenceCount = 1;
} else {
++external._referenceCount;
}
}
this._primitiveAdded.raiseEvent(primitive);
return primitive;
};
PrimitiveCollection.prototype.remove = function(primitive) {
if (this.contains(primitive)) {
const index = this._primitives.indexOf(primitive);
if (index !== -1) {
this._primitives.splice(index, 1);
delete primitive._external._composites[this._guid];
if (this._countReferences) {
primitive._external._referenceCount--;
}
if (this.destroyPrimitives && (!this._countReferences || primitive._external._referenceCount <= 0)) {
primitive.destroy();
}
this._primitiveRemoved.raiseEvent(primitive);
return true;
}
}
return false;
};
PrimitiveCollection.prototype.removeAndDestroy = function(primitive) {
const removed = this.remove(primitive);
if (removed && !this.destroyPrimitives) {
primitive.destroy();
}
return removed;
};
PrimitiveCollection.prototype.removeAll = function() {
const primitives = this._primitives;
const length2 = primitives.length;
for (let i = 0; i < length2; ++i) {
const primitive = primitives[i];
delete primitive._external._composites[this._guid];
if (this._countReferences) {
primitive._external._referenceCount--;
}
if (this.destroyPrimitives && (!this._countReferences || primitive._external._referenceCount <= 0)) {
primitive.destroy();
}
this._primitiveRemoved.raiseEvent(primitive);
}
this._primitives = [];
};
PrimitiveCollection.prototype.contains = function(primitive) {
return !!(defined_default(primitive) && primitive._external && primitive._external._composites && primitive._external._composites[this._guid]);
};
function getPrimitiveIndex(compositePrimitive, primitive) {
if (!compositePrimitive.contains(primitive)) {
throw new DeveloperError_default("primitive is not in this collection.");
}
return compositePrimitive._primitives.indexOf(primitive);
}
PrimitiveCollection.prototype.raise = function(primitive) {
if (defined_default(primitive)) {
const index = getPrimitiveIndex(this, primitive);
const primitives = this._primitives;
if (index !== primitives.length - 1) {
const p = primitives[index];
primitives[index] = primitives[index + 1];
primitives[index + 1] = p;
}
}
};
PrimitiveCollection.prototype.raiseToTop = function(primitive) {
if (defined_default(primitive)) {
const index = getPrimitiveIndex(this, primitive);
const primitives = this._primitives;
if (index !== primitives.length - 1) {
primitives.splice(index, 1);
primitives.push(primitive);
}
}
};
PrimitiveCollection.prototype.lower = function(primitive) {
if (defined_default(primitive)) {
const index = getPrimitiveIndex(this, primitive);
const primitives = this._primitives;
if (index !== 0) {
const p = primitives[index];
primitives[index] = primitives[index - 1];
primitives[index - 1] = p;
}
}
};
PrimitiveCollection.prototype.lowerToBottom = function(primitive) {
if (defined_default(primitive)) {
const index = getPrimitiveIndex(this, primitive);
const primitives = this._primitives;
if (index !== 0) {
primitives.splice(index, 1);
primitives.unshift(primitive);
}
}
};
PrimitiveCollection.prototype.get = function(index) {
if (!defined_default(index)) {
throw new DeveloperError_default("index is required.");
}
return this._primitives[index];
};
PrimitiveCollection.prototype.update = function(frameState) {
if (!this.show) {
return;
}
const primitives = this._primitives;
for (let i = 0; i < primitives.length; ++i) {
primitives[i].update(frameState);
}
};
PrimitiveCollection.prototype.prePassesUpdate = function(frameState) {
const primitives = this._primitives;
for (let i = 0; i < primitives.length; ++i) {
const primitive = primitives[i];
if (defined_default(primitive.prePassesUpdate)) {
primitive.prePassesUpdate(frameState);
}
}
};
PrimitiveCollection.prototype.updateForPass = function(frameState, passState) {
const primitives = this._primitives;
for (let i = 0; i < primitives.length; ++i) {
const primitive = primitives[i];
if (defined_default(primitive.updateForPass)) {
primitive.updateForPass(frameState, passState);
}
}
};
PrimitiveCollection.prototype.postPassesUpdate = function(frameState) {
const primitives = this._primitives;
for (let i = 0; i < primitives.length; ++i) {
const primitive = primitives[i];
if (defined_default(primitive.postPassesUpdate)) {
primitive.postPassesUpdate(frameState);
}
}
};
PrimitiveCollection.prototype.isDestroyed = function() {
return false;
};
PrimitiveCollection.prototype.destroy = function() {
this.removeAll();
return destroyObject_default(this);
};
var PrimitiveCollection_default = PrimitiveCollection;
// packages/engine/Source/Scene/OrderedGroundPrimitiveCollection.js
function OrderedGroundPrimitiveCollection() {
this._length = 0;
this._collections = {};
this._collectionsArray = [];
this.show = true;
}
Object.defineProperties(OrderedGroundPrimitiveCollection.prototype, {
/**
* Gets the number of primitives in the collection.
*
* @memberof OrderedGroundPrimitiveCollection.prototype
*
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._length;
}
}
});
OrderedGroundPrimitiveCollection.prototype.add = function(primitive, zIndex) {
Check_default.defined("primitive", primitive);
if (defined_default(zIndex)) {
Check_default.typeOf.number("zIndex", zIndex);
}
zIndex = zIndex ?? 0;
let collection = this._collections[zIndex];
if (!defined_default(collection)) {
collection = new PrimitiveCollection_default({ destroyPrimitives: false });
collection._zIndex = zIndex;
this._collections[zIndex] = collection;
const array = this._collectionsArray;
let i = 0;
while (i < array.length && array[i]._zIndex < zIndex) {
i++;
}
array.splice(i, 0, collection);
}
collection.add(primitive);
this._length++;
primitive._zIndex = zIndex;
return primitive;
};
OrderedGroundPrimitiveCollection.prototype.set = function(primitive, zIndex) {
Check_default.defined("primitive", primitive);
Check_default.typeOf.number("zIndex", zIndex);
if (zIndex === primitive._zIndex) {
return primitive;
}
this.remove(primitive, true);
this.add(primitive, zIndex);
return primitive;
};
OrderedGroundPrimitiveCollection.prototype.remove = function(primitive, doNotDestroy) {
if (this.contains(primitive)) {
const index = primitive._zIndex;
const collection = this._collections[index];
let result;
if (doNotDestroy) {
result = collection.remove(primitive);
} else {
result = collection.removeAndDestroy(primitive);
}
if (result) {
this._length--;
}
if (collection.length === 0) {
this._collectionsArray.splice(
this._collectionsArray.indexOf(collection),
1
);
this._collections[index] = void 0;
collection.destroy();
}
return result;
}
return false;
};
OrderedGroundPrimitiveCollection.prototype.removeAll = function() {
const collections = this._collectionsArray;
for (let i = 0; i < collections.length; i++) {
const collection = collections[i];
collection.destroyPrimitives = true;
collection.destroy();
}
this._collections = {};
this._collectionsArray = [];
this._length = 0;
};
OrderedGroundPrimitiveCollection.prototype.contains = function(primitive) {
if (!defined_default(primitive)) {
return false;
}
const collection = this._collections[primitive._zIndex];
return defined_default(collection) && collection.contains(primitive);
};
OrderedGroundPrimitiveCollection.prototype.update = function(frameState) {
if (!this.show) {
return;
}
const collections = this._collectionsArray;
for (let i = 0; i < collections.length; i++) {
collections[i].update(frameState);
}
};
OrderedGroundPrimitiveCollection.prototype.isDestroyed = function() {
return false;
};
OrderedGroundPrimitiveCollection.prototype.destroy = function() {
this.removeAll();
return destroyObject_default(this);
};
var OrderedGroundPrimitiveCollection_default = OrderedGroundPrimitiveCollection;
// packages/engine/Source/DataSources/GeometryVisualizer.js
var import_InlineWorkers908 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/DynamicGeometryBatch.js
var import_InlineWorkers877 = __toESM(require_InlineWorkers(), 1);
function DynamicGeometryBatch(primitives, orderedGroundPrimitives) {
this._primitives = primitives;
this._orderedGroundPrimitives = orderedGroundPrimitives;
this._dynamicUpdaters = new AssociativeArray_default();
}
DynamicGeometryBatch.prototype.add = function(time, updater) {
this._dynamicUpdaters.set(
updater.id,
updater.createDynamicUpdater(
this._primitives,
this._orderedGroundPrimitives
)
);
};
DynamicGeometryBatch.prototype.remove = function(updater) {
const id = updater.id;
const dynamicUpdater = this._dynamicUpdaters.get(id);
if (defined_default(dynamicUpdater)) {
this._dynamicUpdaters.remove(id);
dynamicUpdater.destroy();
}
};
DynamicGeometryBatch.prototype.update = function(time) {
const geometries = this._dynamicUpdaters.values;
for (let i = 0, len = geometries.length; i < len; i++) {
geometries[i].update(time);
}
return true;
};
DynamicGeometryBatch.prototype.removeAllPrimitives = function() {
const geometries = this._dynamicUpdaters.values;
for (let i = 0, len = geometries.length; i < len; i++) {
geometries[i].destroy();
}
this._dynamicUpdaters.removeAll();
};
DynamicGeometryBatch.prototype.getBoundingSphere = function(updater, result) {
updater = this._dynamicUpdaters.get(updater.id);
if (defined_default(updater) && defined_default(updater.getBoundingSphere)) {
return updater.getBoundingSphere(result);
}
return BoundingSphereState_default.FAILED;
};
var DynamicGeometryBatch_default = DynamicGeometryBatch;
// packages/engine/Source/DataSources/GeometryUpdaterSet.js
var import_InlineWorkers899 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/EllipseGeometryUpdater.js
var import_InlineWorkers881 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/EllipseGeometry.js
var import_InlineWorkers879 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/EllipseGeometryLibrary.js
var import_InlineWorkers878 = __toESM(require_InlineWorkers(), 1);
var EllipseGeometryLibrary = {};
var rotAxis = new Cartesian3_default();
var tempVec = new Cartesian3_default();
var unitQuat = new Quaternion_default();
var rotMtx = new Matrix3_default();
function pointOnEllipsoid(theta, rotation, northVec, eastVec, aSqr, ab, bSqr, mag, unitPos, result) {
const azimuth = theta + rotation;
Cartesian3_default.multiplyByScalar(eastVec, Math.cos(azimuth), rotAxis);
Cartesian3_default.multiplyByScalar(northVec, Math.sin(azimuth), tempVec);
Cartesian3_default.add(rotAxis, tempVec, rotAxis);
let cosThetaSquared = Math.cos(theta);
cosThetaSquared = cosThetaSquared * cosThetaSquared;
let sinThetaSquared = Math.sin(theta);
sinThetaSquared = sinThetaSquared * sinThetaSquared;
const radius = ab / Math.sqrt(bSqr * cosThetaSquared + aSqr * sinThetaSquared);
const angle = radius / mag;
Quaternion_default.fromAxisAngle(rotAxis, angle, unitQuat);
Matrix3_default.fromQuaternion(unitQuat, rotMtx);
Matrix3_default.multiplyByVector(rotMtx, unitPos, result);
Cartesian3_default.normalize(result, result);
Cartesian3_default.multiplyByScalar(result, mag, result);
return result;
}
var scratchCartesian110 = new Cartesian3_default();
var scratchCartesian27 = new Cartesian3_default();
var scratchCartesian38 = new Cartesian3_default();
var scratchNormal3 = new Cartesian3_default();
EllipseGeometryLibrary.raisePositionsToHeight = function(positions, options, extrude) {
const ellipsoid = options.ellipsoid;
const height = options.height;
const extrudedHeight = options.extrudedHeight;
const size = extrude ? positions.length / 3 * 2 : positions.length / 3;
const finalPositions = new Float64Array(size * 3);
const length2 = positions.length;
const bottomOffset = extrude ? length2 : 0;
for (let i = 0; i < length2; i += 3) {
const i1 = i + 1;
const i2 = i + 2;
const position = Cartesian3_default.fromArray(positions, i, scratchCartesian110);
ellipsoid.scaleToGeodeticSurface(position, position);
const extrudedPosition = Cartesian3_default.clone(position, scratchCartesian27);
const normal2 = ellipsoid.geodeticSurfaceNormal(position, scratchNormal3);
const scaledNormal = Cartesian3_default.multiplyByScalar(
normal2,
height,
scratchCartesian38
);
Cartesian3_default.add(position, scaledNormal, position);
if (extrude) {
Cartesian3_default.multiplyByScalar(normal2, extrudedHeight, scaledNormal);
Cartesian3_default.add(extrudedPosition, scaledNormal, extrudedPosition);
finalPositions[i + bottomOffset] = extrudedPosition.x;
finalPositions[i1 + bottomOffset] = extrudedPosition.y;
finalPositions[i2 + bottomOffset] = extrudedPosition.z;
}
finalPositions[i] = position.x;
finalPositions[i1] = position.y;
finalPositions[i2] = position.z;
}
return finalPositions;
};
var unitPosScratch = new Cartesian3_default();
var eastVecScratch = new Cartesian3_default();
var northVecScratch = new Cartesian3_default();
EllipseGeometryLibrary.computeEllipsePositions = function(options, addFillPositions, addEdgePositions) {
const semiMinorAxis = options.semiMinorAxis;
const semiMajorAxis = options.semiMajorAxis;
const rotation = options.rotation;
const center = options.center;
const granularity = options.granularity * 8;
const aSqr = semiMinorAxis * semiMinorAxis;
const bSqr = semiMajorAxis * semiMajorAxis;
const ab = semiMajorAxis * semiMinorAxis;
const mag = Cartesian3_default.magnitude(center);
const unitPos = Cartesian3_default.normalize(center, unitPosScratch);
let eastVec = Cartesian3_default.cross(Cartesian3_default.UNIT_Z, center, eastVecScratch);
eastVec = Cartesian3_default.normalize(eastVec, eastVec);
const northVec = Cartesian3_default.cross(unitPos, eastVec, northVecScratch);
let numPts = 1 + Math.ceil(Math_default.PI_OVER_TWO / granularity);
const deltaTheta = Math_default.PI_OVER_TWO / (numPts - 1);
let theta = Math_default.PI_OVER_TWO - numPts * deltaTheta;
if (theta < 0) {
numPts -= Math.ceil(Math.abs(theta) / deltaTheta);
}
const size = 2 * (numPts * (numPts + 2));
const positions = addFillPositions ? new Array(size * 3) : void 0;
let positionIndex = 0;
let position = scratchCartesian110;
let reflectedPosition = scratchCartesian27;
const outerPositionsLength = numPts * 4 * 3;
let outerRightIndex = outerPositionsLength - 1;
let outerLeftIndex = 0;
const outerPositions = addEdgePositions ? new Array(outerPositionsLength) : void 0;
let i;
let j;
let numInterior;
let t;
let interiorPosition;
theta = Math_default.PI_OVER_TWO;
position = pointOnEllipsoid(
theta,
rotation,
northVec,
eastVec,
aSqr,
ab,
bSqr,
mag,
unitPos,
position
);
if (addFillPositions) {
positions[positionIndex++] = position.x;
positions[positionIndex++] = position.y;
positions[positionIndex++] = position.z;
}
if (addEdgePositions) {
outerPositions[outerRightIndex--] = position.z;
outerPositions[outerRightIndex--] = position.y;
outerPositions[outerRightIndex--] = position.x;
}
theta = Math_default.PI_OVER_TWO - deltaTheta;
for (i = 1; i < numPts + 1; ++i) {
position = pointOnEllipsoid(
theta,
rotation,
northVec,
eastVec,
aSqr,
ab,
bSqr,
mag,
unitPos,
position
);
reflectedPosition = pointOnEllipsoid(
Math.PI - theta,
rotation,
northVec,
eastVec,
aSqr,
ab,
bSqr,
mag,
unitPos,
reflectedPosition
);
if (addFillPositions) {
positions[positionIndex++] = position.x;
positions[positionIndex++] = position.y;
positions[positionIndex++] = position.z;
numInterior = 2 * i + 2;
for (j = 1; j < numInterior - 1; ++j) {
t = j / (numInterior - 1);
interiorPosition = Cartesian3_default.lerp(
position,
reflectedPosition,
t,
scratchCartesian38
);
positions[positionIndex++] = interiorPosition.x;
positions[positionIndex++] = interiorPosition.y;
positions[positionIndex++] = interiorPosition.z;
}
positions[positionIndex++] = reflectedPosition.x;
positions[positionIndex++] = reflectedPosition.y;
positions[positionIndex++] = reflectedPosition.z;
}
if (addEdgePositions) {
outerPositions[outerRightIndex--] = position.z;
outerPositions[outerRightIndex--] = position.y;
outerPositions[outerRightIndex--] = position.x;
outerPositions[outerLeftIndex++] = reflectedPosition.x;
outerPositions[outerLeftIndex++] = reflectedPosition.y;
outerPositions[outerLeftIndex++] = reflectedPosition.z;
}
theta = Math_default.PI_OVER_TWO - (i + 1) * deltaTheta;
}
for (i = numPts; i > 1; --i) {
theta = Math_default.PI_OVER_TWO - (i - 1) * deltaTheta;
position = pointOnEllipsoid(
-theta,
rotation,
northVec,
eastVec,
aSqr,
ab,
bSqr,
mag,
unitPos,
position
);
reflectedPosition = pointOnEllipsoid(
theta + Math.PI,
rotation,
northVec,
eastVec,
aSqr,
ab,
bSqr,
mag,
unitPos,
reflectedPosition
);
if (addFillPositions) {
positions[positionIndex++] = position.x;
positions[positionIndex++] = position.y;
positions[positionIndex++] = position.z;
numInterior = 2 * (i - 1) + 2;
for (j = 1; j < numInterior - 1; ++j) {
t = j / (numInterior - 1);
interiorPosition = Cartesian3_default.lerp(
position,
reflectedPosition,
t,
scratchCartesian38
);
positions[positionIndex++] = interiorPosition.x;
positions[positionIndex++] = interiorPosition.y;
positions[positionIndex++] = interiorPosition.z;
}
positions[positionIndex++] = reflectedPosition.x;
positions[positionIndex++] = reflectedPosition.y;
positions[positionIndex++] = reflectedPosition.z;
}
if (addEdgePositions) {
outerPositions[outerRightIndex--] = position.z;
outerPositions[outerRightIndex--] = position.y;
outerPositions[outerRightIndex--] = position.x;
outerPositions[outerLeftIndex++] = reflectedPosition.x;
outerPositions[outerLeftIndex++] = reflectedPosition.y;
outerPositions[outerLeftIndex++] = reflectedPosition.z;
}
}
theta = Math_default.PI_OVER_TWO;
position = pointOnEllipsoid(
-theta,
rotation,
northVec,
eastVec,
aSqr,
ab,
bSqr,
mag,
unitPos,
position
);
const r = {};
if (addFillPositions) {
positions[positionIndex++] = position.x;
positions[positionIndex++] = position.y;
positions[positionIndex++] = position.z;
r.positions = positions;
r.numPts = numPts;
}
if (addEdgePositions) {
outerPositions[outerRightIndex--] = position.z;
outerPositions[outerRightIndex--] = position.y;
outerPositions[outerRightIndex--] = position.x;
r.outerPositions = outerPositions;
}
return r;
};
var EllipseGeometryLibrary_default = EllipseGeometryLibrary;
// packages/engine/Source/Core/EllipseGeometry.js
var scratchCartesian111 = new Cartesian3_default();
var scratchCartesian28 = new Cartesian3_default();
var scratchCartesian39 = new Cartesian3_default();
var scratchCartesian45 = new Cartesian3_default();
var texCoordScratch = new Cartesian2_default();
var textureMatrixScratch = new Matrix3_default();
var tangentMatrixScratch2 = new Matrix3_default();
var quaternionScratch2 = new Quaternion_default();
var scratchNormal4 = new Cartesian3_default();
var scratchTangent2 = new Cartesian3_default();
var scratchBitangent2 = new Cartesian3_default();
var scratchCartographic13 = new Cartographic_default();
var projectedCenterScratch = new Cartesian3_default();
var scratchMinTexCoord = new Cartesian2_default();
var scratchMaxTexCoord = new Cartesian2_default();
function computeTopBottomAttributes(positions, options, extrude) {
const vertexFormat = options.vertexFormat;
const center = options.center;
const semiMajorAxis = options.semiMajorAxis;
const semiMinorAxis = options.semiMinorAxis;
const ellipsoid = options.ellipsoid;
const stRotation = options.stRotation;
const size = extrude ? positions.length / 3 * 2 : positions.length / 3;
const shadowVolume = options.shadowVolume;
const textureCoordinates = vertexFormat.st ? new Float32Array(size * 2) : void 0;
const normals = vertexFormat.normal ? new Float32Array(size * 3) : void 0;
const tangents = vertexFormat.tangent ? new Float32Array(size * 3) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(size * 3) : void 0;
const extrudeNormals = shadowVolume ? new Float32Array(size * 3) : void 0;
let textureCoordIndex = 0;
let normal2 = scratchNormal4;
let tangent = scratchTangent2;
let bitangent = scratchBitangent2;
const projection = new GeographicProjection_default(ellipsoid);
const projectedCenter = projection.project(
ellipsoid.cartesianToCartographic(center, scratchCartographic13),
projectedCenterScratch
);
const geodeticNormal = ellipsoid.scaleToGeodeticSurface(
center,
scratchCartesian111
);
ellipsoid.geodeticSurfaceNormal(geodeticNormal, geodeticNormal);
let textureMatrix = textureMatrixScratch;
let tangentMatrix = tangentMatrixScratch2;
if (stRotation !== 0) {
let rotation = Quaternion_default.fromAxisAngle(
geodeticNormal,
stRotation,
quaternionScratch2
);
textureMatrix = Matrix3_default.fromQuaternion(rotation, textureMatrix);
rotation = Quaternion_default.fromAxisAngle(
geodeticNormal,
-stRotation,
quaternionScratch2
);
tangentMatrix = Matrix3_default.fromQuaternion(rotation, tangentMatrix);
} else {
textureMatrix = Matrix3_default.clone(Matrix3_default.IDENTITY, textureMatrix);
tangentMatrix = Matrix3_default.clone(Matrix3_default.IDENTITY, tangentMatrix);
}
const minTexCoord = Cartesian2_default.fromElements(
Number.POSITIVE_INFINITY,
Number.POSITIVE_INFINITY,
scratchMinTexCoord
);
const maxTexCoord = Cartesian2_default.fromElements(
Number.NEGATIVE_INFINITY,
Number.NEGATIVE_INFINITY,
scratchMaxTexCoord
);
let length2 = positions.length;
const bottomOffset = extrude ? length2 : 0;
const stOffset = bottomOffset / 3 * 2;
for (let i = 0; i < length2; i += 3) {
const i1 = i + 1;
const i2 = i + 2;
const position = Cartesian3_default.fromArray(positions, i, scratchCartesian111);
if (vertexFormat.st) {
const rotatedPoint = Matrix3_default.multiplyByVector(
textureMatrix,
position,
scratchCartesian28
);
const projectedPoint = projection.project(
ellipsoid.cartesianToCartographic(rotatedPoint, scratchCartographic13),
scratchCartesian39
);
Cartesian3_default.subtract(projectedPoint, projectedCenter, projectedPoint);
texCoordScratch.x = (projectedPoint.x + semiMajorAxis) / (2 * semiMajorAxis);
texCoordScratch.y = (projectedPoint.y + semiMinorAxis) / (2 * semiMinorAxis);
minTexCoord.x = Math.min(texCoordScratch.x, minTexCoord.x);
minTexCoord.y = Math.min(texCoordScratch.y, minTexCoord.y);
maxTexCoord.x = Math.max(texCoordScratch.x, maxTexCoord.x);
maxTexCoord.y = Math.max(texCoordScratch.y, maxTexCoord.y);
if (extrude) {
textureCoordinates[textureCoordIndex + stOffset] = texCoordScratch.x;
textureCoordinates[textureCoordIndex + 1 + stOffset] = texCoordScratch.y;
}
textureCoordinates[textureCoordIndex++] = texCoordScratch.x;
textureCoordinates[textureCoordIndex++] = texCoordScratch.y;
}
if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent || shadowVolume) {
normal2 = ellipsoid.geodeticSurfaceNormal(position, normal2);
if (shadowVolume) {
extrudeNormals[i + bottomOffset] = -normal2.x;
extrudeNormals[i1 + bottomOffset] = -normal2.y;
extrudeNormals[i2 + bottomOffset] = -normal2.z;
}
if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {
if (vertexFormat.tangent || vertexFormat.bitangent) {
tangent = Cartesian3_default.normalize(
Cartesian3_default.cross(Cartesian3_default.UNIT_Z, normal2, tangent),
tangent
);
Matrix3_default.multiplyByVector(tangentMatrix, tangent, tangent);
}
if (vertexFormat.normal) {
normals[i] = normal2.x;
normals[i1] = normal2.y;
normals[i2] = normal2.z;
if (extrude) {
normals[i + bottomOffset] = -normal2.x;
normals[i1 + bottomOffset] = -normal2.y;
normals[i2 + bottomOffset] = -normal2.z;
}
}
if (vertexFormat.tangent) {
tangents[i] = tangent.x;
tangents[i1] = tangent.y;
tangents[i2] = tangent.z;
if (extrude) {
tangents[i + bottomOffset] = -tangent.x;
tangents[i1 + bottomOffset] = -tangent.y;
tangents[i2 + bottomOffset] = -tangent.z;
}
}
if (vertexFormat.bitangent) {
bitangent = Cartesian3_default.normalize(
Cartesian3_default.cross(normal2, tangent, bitangent),
bitangent
);
bitangents[i] = bitangent.x;
bitangents[i1] = bitangent.y;
bitangents[i2] = bitangent.z;
if (extrude) {
bitangents[i + bottomOffset] = bitangent.x;
bitangents[i1 + bottomOffset] = bitangent.y;
bitangents[i2 + bottomOffset] = bitangent.z;
}
}
}
}
}
if (vertexFormat.st) {
length2 = textureCoordinates.length;
for (let k = 0; k < length2; k += 2) {
textureCoordinates[k] = (textureCoordinates[k] - minTexCoord.x) / (maxTexCoord.x - minTexCoord.x);
textureCoordinates[k + 1] = (textureCoordinates[k + 1] - minTexCoord.y) / (maxTexCoord.y - minTexCoord.y);
}
}
const attributes = new GeometryAttributes_default();
if (vertexFormat.position) {
const finalPositions = EllipseGeometryLibrary_default.raisePositionsToHeight(
positions,
options,
extrude
);
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: finalPositions
});
}
if (vertexFormat.st) {
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: textureCoordinates
});
}
if (vertexFormat.normal) {
attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: normals
});
}
if (vertexFormat.tangent) {
attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: tangents
});
}
if (vertexFormat.bitangent) {
attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: bitangents
});
}
if (shadowVolume) {
attributes.extrudeDirection = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: extrudeNormals
});
}
if (extrude && defined_default(options.offsetAttribute)) {
let offsetAttribute = new Uint8Array(size);
if (options.offsetAttribute === GeometryOffsetAttribute_default.TOP) {
offsetAttribute = offsetAttribute.fill(1, 0, size / 2);
} else {
const offsetValue = options.offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
offsetAttribute = offsetAttribute.fill(offsetValue);
}
attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: offsetAttribute
});
}
return attributes;
}
function topIndices(numPts) {
const indices = new Array(12 * (numPts * (numPts + 1)) - 6);
let indicesIndex = 0;
let prevIndex;
let numInterior;
let positionIndex;
let i;
let j;
prevIndex = 0;
positionIndex = 1;
for (i = 0; i < 3; i++) {
indices[indicesIndex++] = positionIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex;
}
for (i = 2; i < numPts + 1; ++i) {
positionIndex = i * (i + 1) - 1;
prevIndex = (i - 1) * i - 1;
indices[indicesIndex++] = positionIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex;
numInterior = 2 * i;
for (j = 0; j < numInterior - 1; ++j) {
indices[indicesIndex++] = positionIndex;
indices[indicesIndex++] = prevIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex;
}
indices[indicesIndex++] = positionIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex;
}
numInterior = numPts * 2;
++positionIndex;
++prevIndex;
for (i = 0; i < numInterior - 1; ++i) {
indices[indicesIndex++] = positionIndex;
indices[indicesIndex++] = prevIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex;
}
indices[indicesIndex++] = positionIndex;
indices[indicesIndex++] = prevIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex++;
indices[indicesIndex++] = prevIndex++;
indices[indicesIndex++] = prevIndex;
++prevIndex;
for (i = numPts - 1; i > 1; --i) {
indices[indicesIndex++] = prevIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex;
numInterior = 2 * i;
for (j = 0; j < numInterior - 1; ++j) {
indices[indicesIndex++] = positionIndex;
indices[indicesIndex++] = prevIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex;
}
indices[indicesIndex++] = prevIndex++;
indices[indicesIndex++] = prevIndex++;
indices[indicesIndex++] = positionIndex++;
}
for (i = 0; i < 3; i++) {
indices[indicesIndex++] = prevIndex++;
indices[indicesIndex++] = prevIndex;
indices[indicesIndex++] = positionIndex;
}
return indices;
}
var boundingSphereCenter = new Cartesian3_default();
function computeEllipse(options) {
const center = options.center;
boundingSphereCenter = Cartesian3_default.multiplyByScalar(
options.ellipsoid.geodeticSurfaceNormal(center, boundingSphereCenter),
options.height,
boundingSphereCenter
);
boundingSphereCenter = Cartesian3_default.add(
center,
boundingSphereCenter,
boundingSphereCenter
);
const boundingSphere = new BoundingSphere_default(
boundingSphereCenter,
options.semiMajorAxis
);
const cep = EllipseGeometryLibrary_default.computeEllipsePositions(
options,
true,
false
);
const positions = cep.positions;
const numPts = cep.numPts;
const attributes = computeTopBottomAttributes(positions, options, false);
let indices = topIndices(numPts);
indices = IndexDatatype_default.createTypedArray(positions.length / 3, indices);
return {
boundingSphere,
attributes,
indices
};
}
function computeWallAttributes(positions, options) {
const vertexFormat = options.vertexFormat;
const center = options.center;
const semiMajorAxis = options.semiMajorAxis;
const semiMinorAxis = options.semiMinorAxis;
const ellipsoid = options.ellipsoid;
const height = options.height;
const extrudedHeight = options.extrudedHeight;
const stRotation = options.stRotation;
const size = positions.length / 3 * 2;
const finalPositions = new Float64Array(size * 3);
const textureCoordinates = vertexFormat.st ? new Float32Array(size * 2) : void 0;
const normals = vertexFormat.normal ? new Float32Array(size * 3) : void 0;
const tangents = vertexFormat.tangent ? new Float32Array(size * 3) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(size * 3) : void 0;
const shadowVolume = options.shadowVolume;
const extrudeNormals = shadowVolume ? new Float32Array(size * 3) : void 0;
let textureCoordIndex = 0;
let normal2 = scratchNormal4;
let tangent = scratchTangent2;
let bitangent = scratchBitangent2;
const projection = new GeographicProjection_default(ellipsoid);
const projectedCenter = projection.project(
ellipsoid.cartesianToCartographic(center, scratchCartographic13),
projectedCenterScratch
);
const geodeticNormal = ellipsoid.scaleToGeodeticSurface(
center,
scratchCartesian111
);
ellipsoid.geodeticSurfaceNormal(geodeticNormal, geodeticNormal);
const rotation = Quaternion_default.fromAxisAngle(
geodeticNormal,
stRotation,
quaternionScratch2
);
const textureMatrix = Matrix3_default.fromQuaternion(rotation, textureMatrixScratch);
const minTexCoord = Cartesian2_default.fromElements(
Number.POSITIVE_INFINITY,
Number.POSITIVE_INFINITY,
scratchMinTexCoord
);
const maxTexCoord = Cartesian2_default.fromElements(
Number.NEGATIVE_INFINITY,
Number.NEGATIVE_INFINITY,
scratchMaxTexCoord
);
let length2 = positions.length;
const stOffset = length2 / 3 * 2;
for (let i = 0; i < length2; i += 3) {
const i1 = i + 1;
const i2 = i + 2;
let position = Cartesian3_default.fromArray(positions, i, scratchCartesian111);
let extrudedPosition;
if (vertexFormat.st) {
const rotatedPoint = Matrix3_default.multiplyByVector(
textureMatrix,
position,
scratchCartesian28
);
const projectedPoint = projection.project(
ellipsoid.cartesianToCartographic(rotatedPoint, scratchCartographic13),
scratchCartesian39
);
Cartesian3_default.subtract(projectedPoint, projectedCenter, projectedPoint);
texCoordScratch.x = (projectedPoint.x + semiMajorAxis) / (2 * semiMajorAxis);
texCoordScratch.y = (projectedPoint.y + semiMinorAxis) / (2 * semiMinorAxis);
minTexCoord.x = Math.min(texCoordScratch.x, minTexCoord.x);
minTexCoord.y = Math.min(texCoordScratch.y, minTexCoord.y);
maxTexCoord.x = Math.max(texCoordScratch.x, maxTexCoord.x);
maxTexCoord.y = Math.max(texCoordScratch.y, maxTexCoord.y);
textureCoordinates[textureCoordIndex + stOffset] = texCoordScratch.x;
textureCoordinates[textureCoordIndex + 1 + stOffset] = texCoordScratch.y;
textureCoordinates[textureCoordIndex++] = texCoordScratch.x;
textureCoordinates[textureCoordIndex++] = texCoordScratch.y;
}
position = ellipsoid.scaleToGeodeticSurface(position, position);
extrudedPosition = Cartesian3_default.clone(position, scratchCartesian28);
normal2 = ellipsoid.geodeticSurfaceNormal(position, normal2);
if (shadowVolume) {
extrudeNormals[i + length2] = -normal2.x;
extrudeNormals[i1 + length2] = -normal2.y;
extrudeNormals[i2 + length2] = -normal2.z;
}
let scaledNormal = Cartesian3_default.multiplyByScalar(
normal2,
height,
scratchCartesian45
);
position = Cartesian3_default.add(position, scaledNormal, position);
scaledNormal = Cartesian3_default.multiplyByScalar(
normal2,
extrudedHeight,
scaledNormal
);
extrudedPosition = Cartesian3_default.add(
extrudedPosition,
scaledNormal,
extrudedPosition
);
if (vertexFormat.position) {
finalPositions[i + length2] = extrudedPosition.x;
finalPositions[i1 + length2] = extrudedPosition.y;
finalPositions[i2 + length2] = extrudedPosition.z;
finalPositions[i] = position.x;
finalPositions[i1] = position.y;
finalPositions[i2] = position.z;
}
if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {
bitangent = Cartesian3_default.clone(normal2, bitangent);
const next = Cartesian3_default.fromArray(
positions,
(i + 3) % length2,
scratchCartesian45
);
Cartesian3_default.subtract(next, position, next);
const bottom = Cartesian3_default.subtract(
extrudedPosition,
position,
scratchCartesian39
);
normal2 = Cartesian3_default.normalize(
Cartesian3_default.cross(bottom, next, normal2),
normal2
);
if (vertexFormat.normal) {
normals[i] = normal2.x;
normals[i1] = normal2.y;
normals[i2] = normal2.z;
normals[i + length2] = normal2.x;
normals[i1 + length2] = normal2.y;
normals[i2 + length2] = normal2.z;
}
if (vertexFormat.tangent) {
tangent = Cartesian3_default.normalize(
Cartesian3_default.cross(bitangent, normal2, tangent),
tangent
);
tangents[i] = tangent.x;
tangents[i1] = tangent.y;
tangents[i2] = tangent.z;
tangents[i + length2] = tangent.x;
tangents[i + 1 + length2] = tangent.y;
tangents[i + 2 + length2] = tangent.z;
}
if (vertexFormat.bitangent) {
bitangents[i] = bitangent.x;
bitangents[i1] = bitangent.y;
bitangents[i2] = bitangent.z;
bitangents[i + length2] = bitangent.x;
bitangents[i1 + length2] = bitangent.y;
bitangents[i2 + length2] = bitangent.z;
}
}
}
if (vertexFormat.st) {
length2 = textureCoordinates.length;
for (let k = 0; k < length2; k += 2) {
textureCoordinates[k] = (textureCoordinates[k] - minTexCoord.x) / (maxTexCoord.x - minTexCoord.x);
textureCoordinates[k + 1] = (textureCoordinates[k + 1] - minTexCoord.y) / (maxTexCoord.y - minTexCoord.y);
}
}
const attributes = new GeometryAttributes_default();
if (vertexFormat.position) {
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: finalPositions
});
}
if (vertexFormat.st) {
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: textureCoordinates
});
}
if (vertexFormat.normal) {
attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: normals
});
}
if (vertexFormat.tangent) {
attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: tangents
});
}
if (vertexFormat.bitangent) {
attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: bitangents
});
}
if (shadowVolume) {
attributes.extrudeDirection = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: extrudeNormals
});
}
if (defined_default(options.offsetAttribute)) {
let offsetAttribute = new Uint8Array(size);
if (options.offsetAttribute === GeometryOffsetAttribute_default.TOP) {
offsetAttribute = offsetAttribute.fill(1, 0, size / 2);
} else {
const offsetValue = options.offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
offsetAttribute = offsetAttribute.fill(offsetValue);
}
attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: offsetAttribute
});
}
return attributes;
}
function computeWallIndices(positions) {
const length2 = positions.length / 3;
const indices = IndexDatatype_default.createTypedArray(length2, length2 * 6);
let index = 0;
for (let i = 0; i < length2; i++) {
const UL = i;
const LL = i + length2;
const UR = (UL + 1) % length2;
const LR = UR + length2;
indices[index++] = UL;
indices[index++] = LL;
indices[index++] = UR;
indices[index++] = UR;
indices[index++] = LL;
indices[index++] = LR;
}
return indices;
}
var topBoundingSphere2 = new BoundingSphere_default();
var bottomBoundingSphere2 = new BoundingSphere_default();
function computeExtrudedEllipse(options) {
const center = options.center;
const ellipsoid = options.ellipsoid;
const semiMajorAxis = options.semiMajorAxis;
let scaledNormal = Cartesian3_default.multiplyByScalar(
ellipsoid.geodeticSurfaceNormal(center, scratchCartesian111),
options.height,
scratchCartesian111
);
topBoundingSphere2.center = Cartesian3_default.add(
center,
scaledNormal,
topBoundingSphere2.center
);
topBoundingSphere2.radius = semiMajorAxis;
scaledNormal = Cartesian3_default.multiplyByScalar(
ellipsoid.geodeticSurfaceNormal(center, scaledNormal),
options.extrudedHeight,
scaledNormal
);
bottomBoundingSphere2.center = Cartesian3_default.add(
center,
scaledNormal,
bottomBoundingSphere2.center
);
bottomBoundingSphere2.radius = semiMajorAxis;
const cep = EllipseGeometryLibrary_default.computeEllipsePositions(
options,
true,
true
);
const positions = cep.positions;
const numPts = cep.numPts;
const outerPositions = cep.outerPositions;
const boundingSphere = BoundingSphere_default.union(
topBoundingSphere2,
bottomBoundingSphere2
);
const topBottomAttributes = computeTopBottomAttributes(
positions,
options,
true
);
let indices = topIndices(numPts);
const length2 = indices.length;
indices.length = length2 * 2;
const posLength = positions.length / 3;
for (let i = 0; i < length2; i += 3) {
indices[i + length2] = indices[i + 2] + posLength;
indices[i + 1 + length2] = indices[i + 1] + posLength;
indices[i + 2 + length2] = indices[i] + posLength;
}
const topBottomIndices = IndexDatatype_default.createTypedArray(
posLength * 2 / 3,
indices
);
const topBottomGeo = new Geometry_default({
attributes: topBottomAttributes,
indices: topBottomIndices,
primitiveType: PrimitiveType_default.TRIANGLES
});
const wallAttributes = computeWallAttributes(outerPositions, options);
indices = computeWallIndices(outerPositions);
const wallIndices = IndexDatatype_default.createTypedArray(
outerPositions.length * 2 / 3,
indices
);
const wallGeo = new Geometry_default({
attributes: wallAttributes,
indices: wallIndices,
primitiveType: PrimitiveType_default.TRIANGLES
});
const geo = GeometryPipeline_default.combineInstances([
new GeometryInstance_default({
geometry: topBottomGeo
}),
new GeometryInstance_default({
geometry: wallGeo
})
]);
return {
boundingSphere,
attributes: geo[0].attributes,
indices: geo[0].indices
};
}
function computeRectangle2(center, semiMajorAxis, semiMinorAxis, rotation, granularity, ellipsoid, result) {
const cep = EllipseGeometryLibrary_default.computeEllipsePositions(
{
center,
semiMajorAxis,
semiMinorAxis,
rotation,
granularity
},
false,
true
);
const positionsFlat = cep.outerPositions;
const positionsCount = positionsFlat.length / 3;
const positions = new Array(positionsCount);
for (let i = 0; i < positionsCount; ++i) {
positions[i] = Cartesian3_default.fromArray(positionsFlat, i * 3);
}
const rectangle = Rectangle_default.fromCartesianArray(positions, ellipsoid, result);
if (rectangle.width > Math_default.PI) {
rectangle.north = rectangle.north > 0 ? Math_default.PI_OVER_TWO - Math_default.EPSILON7 : rectangle.north;
rectangle.south = rectangle.south < 0 ? Math_default.EPSILON7 - Math_default.PI_OVER_TWO : rectangle.south;
rectangle.east = Math_default.PI;
rectangle.west = -Math_default.PI;
}
return rectangle;
}
function EllipseGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const center = options.center;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
const semiMajorAxis = options.semiMajorAxis;
const semiMinorAxis = options.semiMinorAxis;
const granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
const vertexFormat = options.vertexFormat ?? VertexFormat_default.DEFAULT;
Check_default.defined("options.center", center);
Check_default.typeOf.number("options.semiMajorAxis", semiMajorAxis);
Check_default.typeOf.number("options.semiMinorAxis", semiMinorAxis);
if (semiMajorAxis < semiMinorAxis) {
throw new DeveloperError_default(
"semiMajorAxis must be greater than or equal to the semiMinorAxis."
);
}
if (granularity <= 0) {
throw new DeveloperError_default("granularity must be greater than zero.");
}
const height = options.height ?? 0;
const extrudedHeight = options.extrudedHeight ?? height;
this._center = Cartesian3_default.clone(center);
this._semiMajorAxis = semiMajorAxis;
this._semiMinorAxis = semiMinorAxis;
this._ellipsoid = Ellipsoid_default.clone(ellipsoid);
this._rotation = options.rotation ?? 0;
this._stRotation = options.stRotation ?? 0;
this._height = Math.max(extrudedHeight, height);
this._granularity = granularity;
this._vertexFormat = VertexFormat_default.clone(vertexFormat);
this._extrudedHeight = Math.min(extrudedHeight, height);
this._shadowVolume = options.shadowVolume ?? false;
this._workerName = "createEllipseGeometry";
this._offsetAttribute = options.offsetAttribute;
this._rectangle = void 0;
this._textureCoordinateRotationPoints = void 0;
}
EllipseGeometry.packedLength = Cartesian3_default.packedLength + Ellipsoid_default.packedLength + VertexFormat_default.packedLength + 9;
EllipseGeometry.pack = function(value, array, startingIndex) {
Check_default.defined("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
Cartesian3_default.pack(value._center, array, startingIndex);
startingIndex += Cartesian3_default.packedLength;
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
startingIndex += VertexFormat_default.packedLength;
array[startingIndex++] = value._semiMajorAxis;
array[startingIndex++] = value._semiMinorAxis;
array[startingIndex++] = value._rotation;
array[startingIndex++] = value._stRotation;
array[startingIndex++] = value._height;
array[startingIndex++] = value._granularity;
array[startingIndex++] = value._extrudedHeight;
array[startingIndex++] = value._shadowVolume ? 1 : 0;
array[startingIndex] = value._offsetAttribute ?? -1;
return array;
};
var scratchCenter6 = new Cartesian3_default();
var scratchEllipsoid5 = new Ellipsoid_default();
var scratchVertexFormat5 = new VertexFormat_default();
var scratchOptions11 = {
center: scratchCenter6,
ellipsoid: scratchEllipsoid5,
vertexFormat: scratchVertexFormat5,
semiMajorAxis: void 0,
semiMinorAxis: void 0,
rotation: void 0,
stRotation: void 0,
height: void 0,
granularity: void 0,
extrudedHeight: void 0,
shadowVolume: void 0,
offsetAttribute: void 0
};
EllipseGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const center = Cartesian3_default.unpack(array, startingIndex, scratchCenter6);
startingIndex += Cartesian3_default.packedLength;
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid5);
startingIndex += Ellipsoid_default.packedLength;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat5
);
startingIndex += VertexFormat_default.packedLength;
const semiMajorAxis = array[startingIndex++];
const semiMinorAxis = array[startingIndex++];
const rotation = array[startingIndex++];
const stRotation = array[startingIndex++];
const height = array[startingIndex++];
const granularity = array[startingIndex++];
const extrudedHeight = array[startingIndex++];
const shadowVolume = array[startingIndex++] === 1;
const offsetAttribute = array[startingIndex];
if (!defined_default(result)) {
scratchOptions11.height = height;
scratchOptions11.extrudedHeight = extrudedHeight;
scratchOptions11.granularity = granularity;
scratchOptions11.stRotation = stRotation;
scratchOptions11.rotation = rotation;
scratchOptions11.semiMajorAxis = semiMajorAxis;
scratchOptions11.semiMinorAxis = semiMinorAxis;
scratchOptions11.shadowVolume = shadowVolume;
scratchOptions11.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new EllipseGeometry(scratchOptions11);
}
result._center = Cartesian3_default.clone(center, result._center);
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._semiMajorAxis = semiMajorAxis;
result._semiMinorAxis = semiMinorAxis;
result._rotation = rotation;
result._stRotation = stRotation;
result._height = height;
result._granularity = granularity;
result._extrudedHeight = extrudedHeight;
result._shadowVolume = shadowVolume;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
EllipseGeometry.computeRectangle = function(options, result) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const center = options.center;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
const semiMajorAxis = options.semiMajorAxis;
const semiMinorAxis = options.semiMinorAxis;
const granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
const rotation = options.rotation ?? 0;
Check_default.defined("options.center", center);
Check_default.typeOf.number("options.semiMajorAxis", semiMajorAxis);
Check_default.typeOf.number("options.semiMinorAxis", semiMinorAxis);
if (semiMajorAxis < semiMinorAxis) {
throw new DeveloperError_default(
"semiMajorAxis must be greater than or equal to the semiMinorAxis."
);
}
if (granularity <= 0) {
throw new DeveloperError_default("granularity must be greater than zero.");
}
return computeRectangle2(
center,
semiMajorAxis,
semiMinorAxis,
rotation,
granularity,
ellipsoid,
result
);
};
EllipseGeometry.createGeometry = function(ellipseGeometry) {
if (ellipseGeometry._semiMajorAxis <= 0 || ellipseGeometry._semiMinorAxis <= 0) {
return;
}
const height = ellipseGeometry._height;
const extrudedHeight = ellipseGeometry._extrudedHeight;
const extrude = !Math_default.equalsEpsilon(
height,
extrudedHeight,
0,
Math_default.EPSILON2
);
ellipseGeometry._center = ellipseGeometry._ellipsoid.scaleToGeodeticSurface(
ellipseGeometry._center,
ellipseGeometry._center
);
const options = {
center: ellipseGeometry._center,
semiMajorAxis: ellipseGeometry._semiMajorAxis,
semiMinorAxis: ellipseGeometry._semiMinorAxis,
ellipsoid: ellipseGeometry._ellipsoid,
rotation: ellipseGeometry._rotation,
height,
granularity: ellipseGeometry._granularity,
vertexFormat: ellipseGeometry._vertexFormat,
stRotation: ellipseGeometry._stRotation
};
let geometry;
if (extrude) {
options.extrudedHeight = extrudedHeight;
options.shadowVolume = ellipseGeometry._shadowVolume;
options.offsetAttribute = ellipseGeometry._offsetAttribute;
geometry = computeExtrudedEllipse(options);
} else {
geometry = computeEllipse(options);
if (defined_default(ellipseGeometry._offsetAttribute)) {
const length2 = geometry.attributes.position.values.length;
const offsetValue = ellipseGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
geometry.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
}
return new Geometry_default({
attributes: geometry.attributes,
indices: geometry.indices,
primitiveType: PrimitiveType_default.TRIANGLES,
boundingSphere: geometry.boundingSphere,
offsetAttribute: ellipseGeometry._offsetAttribute
});
};
EllipseGeometry.createShadowVolume = function(ellipseGeometry, minHeightFunc, maxHeightFunc) {
const granularity = ellipseGeometry._granularity;
const ellipsoid = ellipseGeometry._ellipsoid;
const minHeight = minHeightFunc(granularity, ellipsoid);
const maxHeight = maxHeightFunc(granularity, ellipsoid);
return new EllipseGeometry({
center: ellipseGeometry._center,
semiMajorAxis: ellipseGeometry._semiMajorAxis,
semiMinorAxis: ellipseGeometry._semiMinorAxis,
ellipsoid,
rotation: ellipseGeometry._rotation,
stRotation: ellipseGeometry._stRotation,
granularity,
extrudedHeight: minHeight,
height: maxHeight,
vertexFormat: VertexFormat_default.POSITION_ONLY,
shadowVolume: true
});
};
function textureCoordinateRotationPoints2(ellipseGeometry) {
const stRotation = -ellipseGeometry._stRotation;
if (stRotation === 0) {
return [0, 0, 0, 1, 1, 0];
}
const cep = EllipseGeometryLibrary_default.computeEllipsePositions(
{
center: ellipseGeometry._center,
semiMajorAxis: ellipseGeometry._semiMajorAxis,
semiMinorAxis: ellipseGeometry._semiMinorAxis,
rotation: ellipseGeometry._rotation,
granularity: ellipseGeometry._granularity
},
false,
true
);
const positionsFlat = cep.outerPositions;
const positionsCount = positionsFlat.length / 3;
const positions = new Array(positionsCount);
for (let i = 0; i < positionsCount; ++i) {
positions[i] = Cartesian3_default.fromArray(positionsFlat, i * 3);
}
const ellipsoid = ellipseGeometry._ellipsoid;
const boundingRectangle = ellipseGeometry.rectangle;
return Geometry_default._textureCoordinateRotationPoints(
positions,
stRotation,
ellipsoid,
boundingRectangle
);
}
Object.defineProperties(EllipseGeometry.prototype, {
/**
* @private
*/
rectangle: {
get: function() {
if (!defined_default(this._rectangle)) {
this._rectangle = computeRectangle2(
this._center,
this._semiMajorAxis,
this._semiMinorAxis,
this._rotation,
this._granularity,
this._ellipsoid
);
}
return this._rectangle;
}
},
/**
* For remapping texture coordinates when rendering EllipseGeometries as GroundPrimitives.
* @private
*/
textureCoordinateRotationPoints: {
get: function() {
if (!defined_default(this._textureCoordinateRotationPoints)) {
this._textureCoordinateRotationPoints = textureCoordinateRotationPoints2(this);
}
return this._textureCoordinateRotationPoints;
}
}
});
var EllipseGeometry_default = EllipseGeometry;
// packages/engine/Source/Core/EllipseOutlineGeometry.js
var import_InlineWorkers880 = __toESM(require_InlineWorkers(), 1);
var scratchCartesian112 = new Cartesian3_default();
var boundingSphereCenter2 = new Cartesian3_default();
function computeEllipse2(options) {
const center = options.center;
boundingSphereCenter2 = Cartesian3_default.multiplyByScalar(
options.ellipsoid.geodeticSurfaceNormal(center, boundingSphereCenter2),
options.height,
boundingSphereCenter2
);
boundingSphereCenter2 = Cartesian3_default.add(
center,
boundingSphereCenter2,
boundingSphereCenter2
);
const boundingSphere = new BoundingSphere_default(
boundingSphereCenter2,
options.semiMajorAxis
);
const positions = EllipseGeometryLibrary_default.computeEllipsePositions(
options,
false,
true
).outerPositions;
const attributes = new GeometryAttributes_default({
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: EllipseGeometryLibrary_default.raisePositionsToHeight(
positions,
options,
false
)
})
});
const length2 = positions.length / 3;
const indices = IndexDatatype_default.createTypedArray(length2, length2 * 2);
let index = 0;
for (let i = 0; i < length2; ++i) {
indices[index++] = i;
indices[index++] = (i + 1) % length2;
}
return {
boundingSphere,
attributes,
indices
};
}
var topBoundingSphere3 = new BoundingSphere_default();
var bottomBoundingSphere3 = new BoundingSphere_default();
function computeExtrudedEllipse2(options) {
const center = options.center;
const ellipsoid = options.ellipsoid;
const semiMajorAxis = options.semiMajorAxis;
let scaledNormal = Cartesian3_default.multiplyByScalar(
ellipsoid.geodeticSurfaceNormal(center, scratchCartesian112),
options.height,
scratchCartesian112
);
topBoundingSphere3.center = Cartesian3_default.add(
center,
scaledNormal,
topBoundingSphere3.center
);
topBoundingSphere3.radius = semiMajorAxis;
scaledNormal = Cartesian3_default.multiplyByScalar(
ellipsoid.geodeticSurfaceNormal(center, scaledNormal),
options.extrudedHeight,
scaledNormal
);
bottomBoundingSphere3.center = Cartesian3_default.add(
center,
scaledNormal,
bottomBoundingSphere3.center
);
bottomBoundingSphere3.radius = semiMajorAxis;
let positions = EllipseGeometryLibrary_default.computeEllipsePositions(
options,
false,
true
).outerPositions;
const attributes = new GeometryAttributes_default({
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: EllipseGeometryLibrary_default.raisePositionsToHeight(
positions,
options,
true
)
})
});
positions = attributes.position.values;
const boundingSphere = BoundingSphere_default.union(
topBoundingSphere3,
bottomBoundingSphere3
);
let length2 = positions.length / 3;
if (defined_default(options.offsetAttribute)) {
let applyOffset = new Uint8Array(length2);
if (options.offsetAttribute === GeometryOffsetAttribute_default.TOP) {
applyOffset = applyOffset.fill(1, 0, length2 / 2);
} else {
const offsetValue = options.offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
applyOffset = applyOffset.fill(offsetValue);
}
attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
let numberOfVerticalLines = options.numberOfVerticalLines ?? 16;
numberOfVerticalLines = Math_default.clamp(
numberOfVerticalLines,
0,
length2 / 2
);
const indices = IndexDatatype_default.createTypedArray(
length2,
length2 * 2 + numberOfVerticalLines * 2
);
length2 /= 2;
let index = 0;
let i;
for (i = 0; i < length2; ++i) {
indices[index++] = i;
indices[index++] = (i + 1) % length2;
indices[index++] = i + length2;
indices[index++] = (i + 1) % length2 + length2;
}
let numSide;
if (numberOfVerticalLines > 0) {
const numSideLines = Math.min(numberOfVerticalLines, length2);
numSide = Math.round(length2 / numSideLines);
const maxI = Math.min(numSide * numberOfVerticalLines, length2);
for (i = 0; i < maxI; i += numSide) {
indices[index++] = i;
indices[index++] = i + length2;
}
}
return {
boundingSphere,
attributes,
indices
};
}
function EllipseOutlineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const center = options.center;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
const semiMajorAxis = options.semiMajorAxis;
const semiMinorAxis = options.semiMinorAxis;
const granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
if (!defined_default(center)) {
throw new DeveloperError_default("center is required.");
}
if (!defined_default(semiMajorAxis)) {
throw new DeveloperError_default("semiMajorAxis is required.");
}
if (!defined_default(semiMinorAxis)) {
throw new DeveloperError_default("semiMinorAxis is required.");
}
if (semiMajorAxis < semiMinorAxis) {
throw new DeveloperError_default(
"semiMajorAxis must be greater than or equal to the semiMinorAxis."
);
}
if (granularity <= 0) {
throw new DeveloperError_default("granularity must be greater than zero.");
}
const height = options.height ?? 0;
const extrudedHeight = options.extrudedHeight ?? height;
this._center = Cartesian3_default.clone(center);
this._semiMajorAxis = semiMajorAxis;
this._semiMinorAxis = semiMinorAxis;
this._ellipsoid = Ellipsoid_default.clone(ellipsoid);
this._rotation = options.rotation ?? 0;
this._height = Math.max(extrudedHeight, height);
this._granularity = granularity;
this._extrudedHeight = Math.min(extrudedHeight, height);
this._numberOfVerticalLines = Math.max(
options.numberOfVerticalLines ?? 16,
0
);
this._offsetAttribute = options.offsetAttribute;
this._workerName = "createEllipseOutlineGeometry";
}
EllipseOutlineGeometry.packedLength = Cartesian3_default.packedLength + Ellipsoid_default.packedLength + 8;
EllipseOutlineGeometry.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
Cartesian3_default.pack(value._center, array, startingIndex);
startingIndex += Cartesian3_default.packedLength;
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
array[startingIndex++] = value._semiMajorAxis;
array[startingIndex++] = value._semiMinorAxis;
array[startingIndex++] = value._rotation;
array[startingIndex++] = value._height;
array[startingIndex++] = value._granularity;
array[startingIndex++] = value._extrudedHeight;
array[startingIndex++] = value._numberOfVerticalLines;
array[startingIndex] = value._offsetAttribute ?? -1;
return array;
};
var scratchCenter7 = new Cartesian3_default();
var scratchEllipsoid6 = new Ellipsoid_default();
var scratchOptions12 = {
center: scratchCenter7,
ellipsoid: scratchEllipsoid6,
semiMajorAxis: void 0,
semiMinorAxis: void 0,
rotation: void 0,
height: void 0,
granularity: void 0,
extrudedHeight: void 0,
numberOfVerticalLines: void 0,
offsetAttribute: void 0
};
EllipseOutlineGeometry.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
const center = Cartesian3_default.unpack(array, startingIndex, scratchCenter7);
startingIndex += Cartesian3_default.packedLength;
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid6);
startingIndex += Ellipsoid_default.packedLength;
const semiMajorAxis = array[startingIndex++];
const semiMinorAxis = array[startingIndex++];
const rotation = array[startingIndex++];
const height = array[startingIndex++];
const granularity = array[startingIndex++];
const extrudedHeight = array[startingIndex++];
const numberOfVerticalLines = array[startingIndex++];
const offsetAttribute = array[startingIndex];
if (!defined_default(result)) {
scratchOptions12.height = height;
scratchOptions12.extrudedHeight = extrudedHeight;
scratchOptions12.granularity = granularity;
scratchOptions12.rotation = rotation;
scratchOptions12.semiMajorAxis = semiMajorAxis;
scratchOptions12.semiMinorAxis = semiMinorAxis;
scratchOptions12.numberOfVerticalLines = numberOfVerticalLines;
scratchOptions12.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new EllipseOutlineGeometry(scratchOptions12);
}
result._center = Cartesian3_default.clone(center, result._center);
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._semiMajorAxis = semiMajorAxis;
result._semiMinorAxis = semiMinorAxis;
result._rotation = rotation;
result._height = height;
result._granularity = granularity;
result._extrudedHeight = extrudedHeight;
result._numberOfVerticalLines = numberOfVerticalLines;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
EllipseOutlineGeometry.createGeometry = function(ellipseGeometry) {
if (ellipseGeometry._semiMajorAxis <= 0 || ellipseGeometry._semiMinorAxis <= 0) {
return;
}
const height = ellipseGeometry._height;
const extrudedHeight = ellipseGeometry._extrudedHeight;
const extrude = !Math_default.equalsEpsilon(
height,
extrudedHeight,
0,
Math_default.EPSILON2
);
ellipseGeometry._center = ellipseGeometry._ellipsoid.scaleToGeodeticSurface(
ellipseGeometry._center,
ellipseGeometry._center
);
const options = {
center: ellipseGeometry._center,
semiMajorAxis: ellipseGeometry._semiMajorAxis,
semiMinorAxis: ellipseGeometry._semiMinorAxis,
ellipsoid: ellipseGeometry._ellipsoid,
rotation: ellipseGeometry._rotation,
height,
granularity: ellipseGeometry._granularity,
numberOfVerticalLines: ellipseGeometry._numberOfVerticalLines
};
let geometry;
if (extrude) {
options.extrudedHeight = extrudedHeight;
options.offsetAttribute = ellipseGeometry._offsetAttribute;
geometry = computeExtrudedEllipse2(options);
} else {
geometry = computeEllipse2(options);
if (defined_default(ellipseGeometry._offsetAttribute)) {
const length2 = geometry.attributes.position.values.length;
const offsetValue = ellipseGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
geometry.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
}
return new Geometry_default({
attributes: geometry.attributes,
indices: geometry.indices,
primitiveType: PrimitiveType_default.LINES,
boundingSphere: geometry.boundingSphere,
offsetAttribute: ellipseGeometry._offsetAttribute
});
};
var EllipseOutlineGeometry_default = EllipseOutlineGeometry;
// packages/engine/Source/DataSources/EllipseGeometryUpdater.js
var scratchColor15 = new Color_default();
var defaultOffset5 = Cartesian3_default.ZERO;
var offsetScratch7 = new Cartesian3_default();
var scratchRectangle7 = new Rectangle_default();
function EllipseGeometryOptions(entity) {
this.id = entity;
this.vertexFormat = void 0;
this.center = void 0;
this.semiMajorAxis = void 0;
this.semiMinorAxis = void 0;
this.rotation = void 0;
this.height = void 0;
this.extrudedHeight = void 0;
this.granularity = void 0;
this.stRotation = void 0;
this.numberOfVerticalLines = void 0;
this.offsetAttribute = void 0;
}
function EllipseGeometryUpdater(entity, scene) {
GroundGeometryUpdater_default.call(this, {
entity,
scene,
geometryOptions: new EllipseGeometryOptions(entity),
geometryPropertyName: "ellipse",
observedPropertyNames: ["availability", "position", "ellipse"]
});
this._onEntityPropertyChanged(entity, "ellipse", entity.ellipse, void 0);
}
if (defined_default(Object.create)) {
EllipseGeometryUpdater.prototype = Object.create(
GroundGeometryUpdater_default.prototype
);
EllipseGeometryUpdater.prototype.constructor = EllipseGeometryUpdater;
}
EllipseGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._fillEnabled) {
throw new DeveloperError_default(
"This instance does not represent a filled geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const attributes = {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)
),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
this._distanceDisplayConditionProperty.getValue(time)
),
offset: void 0,
color: void 0
};
if (this._materialProperty instanceof ColorMaterialProperty_default) {
let currentColor;
if (defined_default(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
currentColor = this._materialProperty.color.getValue(time, scratchColor15);
}
if (!defined_default(currentColor)) {
currentColor = Color_default.WHITE;
}
attributes.color = ColorGeometryInstanceAttribute_default.fromColor(currentColor);
}
if (defined_default(this._options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset5,
offsetScratch7
)
);
}
return new GeometryInstance_default({
id: entity,
geometry: new EllipseGeometry_default(this._options),
attributes
});
};
EllipseGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._outlineEnabled) {
throw new DeveloperError_default(
"This instance does not represent an outlined geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const outlineColor = Property_default.getValueOrDefault(
this._outlineColorProperty,
time,
Color_default.BLACK,
scratchColor15
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const attributes = {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)
),
color: ColorGeometryInstanceAttribute_default.fromColor(outlineColor),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
),
offset: void 0
};
if (defined_default(this._options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset5,
offsetScratch7
)
);
}
return new GeometryInstance_default({
id: entity,
geometry: new EllipseOutlineGeometry_default(this._options),
attributes
});
};
EllipseGeometryUpdater.prototype._computeCenter = function(time, result) {
return Property_default.getValueOrUndefined(this._entity.position, time, result);
};
EllipseGeometryUpdater.prototype._isHidden = function(entity, ellipse) {
const position = entity.position;
return !defined_default(position) || !defined_default(ellipse.semiMajorAxis) || !defined_default(ellipse.semiMinorAxis) || GeometryUpdater_default.prototype._isHidden.call(this, entity, ellipse);
};
EllipseGeometryUpdater.prototype._isDynamic = function(entity, ellipse) {
return !entity.position.isConstant || //
!ellipse.semiMajorAxis.isConstant || //
!ellipse.semiMinorAxis.isConstant || //
!Property_default.isConstant(ellipse.rotation) || //
!Property_default.isConstant(ellipse.height) || //
!Property_default.isConstant(ellipse.extrudedHeight) || //
!Property_default.isConstant(ellipse.granularity) || //
!Property_default.isConstant(ellipse.stRotation) || //
!Property_default.isConstant(ellipse.outlineWidth) || //
!Property_default.isConstant(ellipse.numberOfVerticalLines) || //
!Property_default.isConstant(ellipse.zIndex) || //
this._onTerrain && !Property_default.isConstant(this._materialProperty) && !(this._materialProperty instanceof ColorMaterialProperty_default);
};
EllipseGeometryUpdater.prototype._setStaticOptions = function(entity, ellipse) {
let heightValue = Property_default.getValueOrUndefined(
ellipse.height,
Iso8601_default.MINIMUM_VALUE
);
const heightReferenceValue = Property_default.getValueOrDefault(
ellipse.heightReference,
Iso8601_default.MINIMUM_VALUE,
HeightReference_default.NONE
);
let extrudedHeightValue = Property_default.getValueOrUndefined(
ellipse.extrudedHeight,
Iso8601_default.MINIMUM_VALUE
);
const extrudedHeightReferenceValue = Property_default.getValueOrDefault(
ellipse.extrudedHeightReference,
Iso8601_default.MINIMUM_VALUE,
HeightReference_default.NONE
);
if (defined_default(extrudedHeightValue) && !defined_default(heightValue)) {
heightValue = 0;
}
const options = this._options;
options.vertexFormat = this._materialProperty instanceof ColorMaterialProperty_default ? PerInstanceColorAppearance_default.VERTEX_FORMAT : MaterialAppearance_default.MaterialSupport.TEXTURED.vertexFormat;
options.center = entity.position.getValue(
Iso8601_default.MINIMUM_VALUE,
options.center
);
options.semiMajorAxis = ellipse.semiMajorAxis.getValue(
Iso8601_default.MINIMUM_VALUE,
options.semiMajorAxis
);
options.semiMinorAxis = ellipse.semiMinorAxis.getValue(
Iso8601_default.MINIMUM_VALUE,
options.semiMinorAxis
);
options.rotation = Property_default.getValueOrUndefined(
ellipse.rotation,
Iso8601_default.MINIMUM_VALUE
);
options.granularity = Property_default.getValueOrUndefined(
ellipse.granularity,
Iso8601_default.MINIMUM_VALUE
);
options.stRotation = Property_default.getValueOrUndefined(
ellipse.stRotation,
Iso8601_default.MINIMUM_VALUE
);
options.numberOfVerticalLines = Property_default.getValueOrUndefined(
ellipse.numberOfVerticalLines,
Iso8601_default.MINIMUM_VALUE
);
options.offsetAttribute = GroundGeometryUpdater_default.computeGeometryOffsetAttribute(
heightValue,
heightReferenceValue,
extrudedHeightValue,
extrudedHeightReferenceValue
);
options.height = GroundGeometryUpdater_default.getGeometryHeight(
heightValue,
heightReferenceValue
);
extrudedHeightValue = GroundGeometryUpdater_default.getGeometryExtrudedHeight(
extrudedHeightValue,
extrudedHeightReferenceValue
);
if (extrudedHeightValue === GroundGeometryUpdater_default.CLAMP_TO_GROUND) {
extrudedHeightValue = ApproximateTerrainHeights_default.getMinimumMaximumHeights(
EllipseGeometry_default.computeRectangle(options, scratchRectangle7)
).minimumTerrainHeight;
}
options.extrudedHeight = extrudedHeightValue;
};
EllipseGeometryUpdater.DynamicGeometryUpdater = DynamicEllipseGeometryUpdater;
function DynamicEllipseGeometryUpdater(geometryUpdater, primitives, groundPrimitives) {
DynamicGeometryUpdater_default.call(
this,
geometryUpdater,
primitives,
groundPrimitives
);
}
if (defined_default(Object.create)) {
DynamicEllipseGeometryUpdater.prototype = Object.create(
DynamicGeometryUpdater_default.prototype
);
DynamicEllipseGeometryUpdater.prototype.constructor = DynamicEllipseGeometryUpdater;
}
DynamicEllipseGeometryUpdater.prototype._isHidden = function(entity, ellipse, time) {
const options = this._options;
return !defined_default(options.center) || !defined_default(options.semiMajorAxis) || !defined_default(options.semiMinorAxis) || DynamicGeometryUpdater_default.prototype._isHidden.call(this, entity, ellipse, time);
};
DynamicEllipseGeometryUpdater.prototype._setOptions = function(entity, ellipse, time) {
const options = this._options;
let heightValue = Property_default.getValueOrUndefined(ellipse.height, time);
const heightReferenceValue = Property_default.getValueOrDefault(
ellipse.heightReference,
time,
HeightReference_default.NONE
);
let extrudedHeightValue = Property_default.getValueOrUndefined(
ellipse.extrudedHeight,
time
);
const extrudedHeightReferenceValue = Property_default.getValueOrDefault(
ellipse.extrudedHeightReference,
time,
HeightReference_default.NONE
);
if (defined_default(extrudedHeightValue) && !defined_default(heightValue)) {
heightValue = 0;
}
options.center = Property_default.getValueOrUndefined(
entity.position,
time,
options.center
);
options.semiMajorAxis = Property_default.getValueOrUndefined(
ellipse.semiMajorAxis,
time
);
options.semiMinorAxis = Property_default.getValueOrUndefined(
ellipse.semiMinorAxis,
time
);
options.rotation = Property_default.getValueOrUndefined(ellipse.rotation, time);
options.granularity = Property_default.getValueOrUndefined(ellipse.granularity, time);
options.stRotation = Property_default.getValueOrUndefined(ellipse.stRotation, time);
options.numberOfVerticalLines = Property_default.getValueOrUndefined(
ellipse.numberOfVerticalLines,
time
);
options.offsetAttribute = GroundGeometryUpdater_default.computeGeometryOffsetAttribute(
heightValue,
heightReferenceValue,
extrudedHeightValue,
extrudedHeightReferenceValue
);
options.height = GroundGeometryUpdater_default.getGeometryHeight(
heightValue,
heightReferenceValue
);
extrudedHeightValue = GroundGeometryUpdater_default.getGeometryExtrudedHeight(
extrudedHeightValue,
extrudedHeightReferenceValue
);
if (extrudedHeightValue === GroundGeometryUpdater_default.CLAMP_TO_GROUND) {
extrudedHeightValue = ApproximateTerrainHeights_default.getMinimumMaximumHeights(
EllipseGeometry_default.computeRectangle(options, scratchRectangle7)
).minimumTerrainHeight;
}
options.extrudedHeight = extrudedHeightValue;
};
var EllipseGeometryUpdater_default = EllipseGeometryUpdater;
// packages/engine/Source/DataSources/EllipsoidGeometryUpdater.js
var import_InlineWorkers883 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/EllipsoidGeometry.js
var import_InlineWorkers882 = __toESM(require_InlineWorkers(), 1);
var scratchPosition8 = new Cartesian3_default();
var scratchNormal5 = new Cartesian3_default();
var scratchTangent3 = new Cartesian3_default();
var scratchBitangent3 = new Cartesian3_default();
var scratchNormalST = new Cartesian3_default();
var defaultRadii2 = new Cartesian3_default(1, 1, 1);
var cos3 = Math.cos;
var sin3 = Math.sin;
function EllipsoidGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const radii = options.radii ?? defaultRadii2;
const innerRadii = options.innerRadii ?? radii;
const minimumClock = options.minimumClock ?? 0;
const maximumClock = options.maximumClock ?? Math_default.TWO_PI;
const minimumCone = options.minimumCone ?? 0;
const maximumCone = options.maximumCone ?? Math_default.PI;
const stackPartitions = Math.round(options.stackPartitions ?? 64);
const slicePartitions = Math.round(options.slicePartitions ?? 64);
const vertexFormat = options.vertexFormat ?? VertexFormat_default.DEFAULT;
if (slicePartitions < 3) {
throw new DeveloperError_default(
"options.slicePartitions cannot be less than three."
);
}
if (stackPartitions < 3) {
throw new DeveloperError_default(
"options.stackPartitions cannot be less than three."
);
}
this._radii = Cartesian3_default.clone(radii);
this._innerRadii = Cartesian3_default.clone(innerRadii);
this._minimumClock = minimumClock;
this._maximumClock = maximumClock;
this._minimumCone = minimumCone;
this._maximumCone = maximumCone;
this._stackPartitions = stackPartitions;
this._slicePartitions = slicePartitions;
this._vertexFormat = VertexFormat_default.clone(vertexFormat);
this._offsetAttribute = options.offsetAttribute;
this._workerName = "createEllipsoidGeometry";
}
EllipsoidGeometry.packedLength = 2 * Cartesian3_default.packedLength + VertexFormat_default.packedLength + 7;
EllipsoidGeometry.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
Cartesian3_default.pack(value._radii, array, startingIndex);
startingIndex += Cartesian3_default.packedLength;
Cartesian3_default.pack(value._innerRadii, array, startingIndex);
startingIndex += Cartesian3_default.packedLength;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
startingIndex += VertexFormat_default.packedLength;
array[startingIndex++] = value._minimumClock;
array[startingIndex++] = value._maximumClock;
array[startingIndex++] = value._minimumCone;
array[startingIndex++] = value._maximumCone;
array[startingIndex++] = value._stackPartitions;
array[startingIndex++] = value._slicePartitions;
array[startingIndex] = value._offsetAttribute ?? -1;
return array;
};
var scratchRadii2 = new Cartesian3_default();
var scratchInnerRadii2 = new Cartesian3_default();
var scratchVertexFormat6 = new VertexFormat_default();
var scratchOptions13 = {
radii: scratchRadii2,
innerRadii: scratchInnerRadii2,
vertexFormat: scratchVertexFormat6,
minimumClock: void 0,
maximumClock: void 0,
minimumCone: void 0,
maximumCone: void 0,
stackPartitions: void 0,
slicePartitions: void 0,
offsetAttribute: void 0
};
EllipsoidGeometry.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
const radii = Cartesian3_default.unpack(array, startingIndex, scratchRadii2);
startingIndex += Cartesian3_default.packedLength;
const innerRadii = Cartesian3_default.unpack(array, startingIndex, scratchInnerRadii2);
startingIndex += Cartesian3_default.packedLength;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat6
);
startingIndex += VertexFormat_default.packedLength;
const minimumClock = array[startingIndex++];
const maximumClock = array[startingIndex++];
const minimumCone = array[startingIndex++];
const maximumCone = array[startingIndex++];
const stackPartitions = array[startingIndex++];
const slicePartitions = array[startingIndex++];
const offsetAttribute = array[startingIndex];
if (!defined_default(result)) {
scratchOptions13.minimumClock = minimumClock;
scratchOptions13.maximumClock = maximumClock;
scratchOptions13.minimumCone = minimumCone;
scratchOptions13.maximumCone = maximumCone;
scratchOptions13.stackPartitions = stackPartitions;
scratchOptions13.slicePartitions = slicePartitions;
scratchOptions13.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new EllipsoidGeometry(scratchOptions13);
}
result._radii = Cartesian3_default.clone(radii, result._radii);
result._innerRadii = Cartesian3_default.clone(innerRadii, result._innerRadii);
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._minimumClock = minimumClock;
result._maximumClock = maximumClock;
result._minimumCone = minimumCone;
result._maximumCone = maximumCone;
result._stackPartitions = stackPartitions;
result._slicePartitions = slicePartitions;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
EllipsoidGeometry.createGeometry = function(ellipsoidGeometry) {
const radii = ellipsoidGeometry._radii;
if (radii.x <= 0 || radii.y <= 0 || radii.z <= 0) {
return;
}
const innerRadii = ellipsoidGeometry._innerRadii;
if (innerRadii.x <= 0 || innerRadii.y <= 0 || innerRadii.z <= 0) {
return;
}
const minimumClock = ellipsoidGeometry._minimumClock;
const maximumClock = ellipsoidGeometry._maximumClock;
const minimumCone = ellipsoidGeometry._minimumCone;
const maximumCone = ellipsoidGeometry._maximumCone;
const vertexFormat = ellipsoidGeometry._vertexFormat;
let slicePartitions = ellipsoidGeometry._slicePartitions + 1;
let stackPartitions = ellipsoidGeometry._stackPartitions + 1;
slicePartitions = Math.round(
slicePartitions * Math.abs(maximumClock - minimumClock) / Math_default.TWO_PI
);
stackPartitions = Math.round(
stackPartitions * Math.abs(maximumCone - minimumCone) / Math_default.PI
);
if (slicePartitions < 2) {
slicePartitions = 2;
}
if (stackPartitions < 2) {
stackPartitions = 2;
}
let i;
let j;
let index = 0;
const phis = [minimumCone];
const thetas = [minimumClock];
for (i = 0; i < stackPartitions; i++) {
phis.push(
minimumCone + i * (maximumCone - minimumCone) / (stackPartitions - 1)
);
}
phis.push(maximumCone);
for (j = 0; j < slicePartitions; j++) {
thetas.push(
minimumClock + j * (maximumClock - minimumClock) / (slicePartitions - 1)
);
}
thetas.push(maximumClock);
const numPhis = phis.length;
const numThetas = thetas.length;
let extraIndices = 0;
let vertexMultiplier = 1;
const hasInnerSurface = innerRadii.x !== radii.x || innerRadii.y !== radii.y || innerRadii.z !== radii.z;
let isTopOpen = false;
let isBotOpen = false;
let isClockOpen = false;
if (hasInnerSurface) {
vertexMultiplier = 2;
if (minimumCone > 0) {
isTopOpen = true;
extraIndices += slicePartitions - 1;
}
if (maximumCone < Math.PI) {
isBotOpen = true;
extraIndices += slicePartitions - 1;
}
if ((maximumClock - minimumClock) % Math_default.TWO_PI) {
isClockOpen = true;
extraIndices += (stackPartitions - 1) * 2 + 1;
} else {
extraIndices += 1;
}
}
const vertexCount = numThetas * numPhis * vertexMultiplier;
const positions = new Float64Array(vertexCount * 3);
const isInner = new Array(vertexCount).fill(false);
const negateNormal = new Array(vertexCount).fill(false);
const indexCount = slicePartitions * stackPartitions * vertexMultiplier;
const numIndices = 6 * (indexCount + extraIndices + 1 - (slicePartitions + stackPartitions) * vertexMultiplier);
const indices = IndexDatatype_default.createTypedArray(indexCount, numIndices);
const normals = vertexFormat.normal ? new Float32Array(vertexCount * 3) : void 0;
const tangents = vertexFormat.tangent ? new Float32Array(vertexCount * 3) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(vertexCount * 3) : void 0;
const st = vertexFormat.st ? new Float32Array(vertexCount * 2) : void 0;
const sinPhi = new Array(numPhis);
const cosPhi = new Array(numPhis);
for (i = 0; i < numPhis; i++) {
sinPhi[i] = sin3(phis[i]);
cosPhi[i] = cos3(phis[i]);
}
const sinTheta = new Array(numThetas);
const cosTheta = new Array(numThetas);
for (j = 0; j < numThetas; j++) {
cosTheta[j] = cos3(thetas[j]);
sinTheta[j] = sin3(thetas[j]);
}
for (i = 0; i < numPhis; i++) {
for (j = 0; j < numThetas; j++) {
positions[index++] = radii.x * sinPhi[i] * cosTheta[j];
positions[index++] = radii.y * sinPhi[i] * sinTheta[j];
positions[index++] = radii.z * cosPhi[i];
}
}
let vertexIndex = vertexCount / 2;
if (hasInnerSurface) {
for (i = 0; i < numPhis; i++) {
for (j = 0; j < numThetas; j++) {
positions[index++] = innerRadii.x * sinPhi[i] * cosTheta[j];
positions[index++] = innerRadii.y * sinPhi[i] * sinTheta[j];
positions[index++] = innerRadii.z * cosPhi[i];
isInner[vertexIndex] = true;
if (i > 0 && i !== numPhis - 1 && j !== 0 && j !== numThetas - 1) {
negateNormal[vertexIndex] = true;
}
vertexIndex++;
}
}
}
index = 0;
let topOffset;
let bottomOffset;
for (i = 1; i < numPhis - 2; i++) {
topOffset = i * numThetas;
bottomOffset = (i + 1) * numThetas;
for (j = 1; j < numThetas - 2; j++) {
indices[index++] = bottomOffset + j;
indices[index++] = bottomOffset + j + 1;
indices[index++] = topOffset + j + 1;
indices[index++] = bottomOffset + j;
indices[index++] = topOffset + j + 1;
indices[index++] = topOffset + j;
}
}
if (hasInnerSurface) {
const offset = numPhis * numThetas;
for (i = 1; i < numPhis - 2; i++) {
topOffset = offset + i * numThetas;
bottomOffset = offset + (i + 1) * numThetas;
for (j = 1; j < numThetas - 2; j++) {
indices[index++] = bottomOffset + j;
indices[index++] = topOffset + j;
indices[index++] = topOffset + j + 1;
indices[index++] = bottomOffset + j;
indices[index++] = topOffset + j + 1;
indices[index++] = bottomOffset + j + 1;
}
}
}
let outerOffset;
let innerOffset;
if (hasInnerSurface) {
if (isTopOpen) {
innerOffset = numPhis * numThetas;
for (i = 1; i < numThetas - 2; i++) {
indices[index++] = i;
indices[index++] = i + 1;
indices[index++] = innerOffset + i + 1;
indices[index++] = i;
indices[index++] = innerOffset + i + 1;
indices[index++] = innerOffset + i;
}
}
if (isBotOpen) {
outerOffset = numPhis * numThetas - numThetas;
innerOffset = numPhis * numThetas * vertexMultiplier - numThetas;
for (i = 1; i < numThetas - 2; i++) {
indices[index++] = outerOffset + i + 1;
indices[index++] = outerOffset + i;
indices[index++] = innerOffset + i;
indices[index++] = outerOffset + i + 1;
indices[index++] = innerOffset + i;
indices[index++] = innerOffset + i + 1;
}
}
}
if (isClockOpen) {
for (i = 1; i < numPhis - 2; i++) {
innerOffset = numThetas * numPhis + numThetas * i;
outerOffset = numThetas * i;
indices[index++] = innerOffset;
indices[index++] = outerOffset + numThetas;
indices[index++] = outerOffset;
indices[index++] = innerOffset;
indices[index++] = innerOffset + numThetas;
indices[index++] = outerOffset + numThetas;
}
for (i = 1; i < numPhis - 2; i++) {
innerOffset = numThetas * numPhis + numThetas * (i + 1) - 1;
outerOffset = numThetas * (i + 1) - 1;
indices[index++] = outerOffset + numThetas;
indices[index++] = innerOffset;
indices[index++] = outerOffset;
indices[index++] = outerOffset + numThetas;
indices[index++] = innerOffset + numThetas;
indices[index++] = innerOffset;
}
}
const attributes = new GeometryAttributes_default();
if (vertexFormat.position) {
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
});
}
let stIndex = 0;
let normalIndex = 0;
let tangentIndex = 0;
let bitangentIndex = 0;
const vertexCountHalf = vertexCount / 2;
let ellipsoid;
const ellipsoidOuter = Ellipsoid_default.fromCartesian3(radii);
const ellipsoidInner = Ellipsoid_default.fromCartesian3(innerRadii);
if (vertexFormat.st || vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {
for (i = 0; i < vertexCount; i++) {
ellipsoid = isInner[i] ? ellipsoidInner : ellipsoidOuter;
const position = Cartesian3_default.fromArray(positions, i * 3, scratchPosition8);
const normal2 = ellipsoid.geodeticSurfaceNormal(position, scratchNormal5);
if (negateNormal[i]) {
Cartesian3_default.negate(normal2, normal2);
}
if (vertexFormat.st) {
const normalST = Cartesian2_default.negate(normal2, scratchNormalST);
st[stIndex++] = Math.atan2(normalST.y, normalST.x) / Math_default.TWO_PI + 0.5;
st[stIndex++] = Math.asin(normal2.z) / Math.PI + 0.5;
}
if (vertexFormat.normal) {
normals[normalIndex++] = normal2.x;
normals[normalIndex++] = normal2.y;
normals[normalIndex++] = normal2.z;
}
if (vertexFormat.tangent || vertexFormat.bitangent) {
const tangent = scratchTangent3;
let tangetOffset = 0;
let unit;
if (isInner[i]) {
tangetOffset = vertexCountHalf;
}
if (!isTopOpen && i >= tangetOffset && i < tangetOffset + numThetas * 2) {
unit = Cartesian3_default.UNIT_X;
} else {
unit = Cartesian3_default.UNIT_Z;
}
Cartesian3_default.cross(unit, normal2, tangent);
Cartesian3_default.normalize(tangent, tangent);
if (vertexFormat.tangent) {
tangents[tangentIndex++] = tangent.x;
tangents[tangentIndex++] = tangent.y;
tangents[tangentIndex++] = tangent.z;
}
if (vertexFormat.bitangent) {
const bitangent = Cartesian3_default.cross(normal2, tangent, scratchBitangent3);
Cartesian3_default.normalize(bitangent, bitangent);
bitangents[bitangentIndex++] = bitangent.x;
bitangents[bitangentIndex++] = bitangent.y;
bitangents[bitangentIndex++] = bitangent.z;
}
}
}
if (vertexFormat.st) {
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: st
});
}
if (vertexFormat.normal) {
attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: normals
});
}
if (vertexFormat.tangent) {
attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: tangents
});
}
if (vertexFormat.bitangent) {
attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: bitangents
});
}
}
if (defined_default(ellipsoidGeometry._offsetAttribute)) {
const length2 = positions.length;
const offsetValue = ellipsoidGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.TRIANGLES,
boundingSphere: BoundingSphere_default.fromEllipsoid(ellipsoidOuter),
offsetAttribute: ellipsoidGeometry._offsetAttribute
});
};
var unitEllipsoidGeometry;
EllipsoidGeometry.getUnitEllipsoid = function() {
if (!defined_default(unitEllipsoidGeometry)) {
unitEllipsoidGeometry = EllipsoidGeometry.createGeometry(
new EllipsoidGeometry({
radii: new Cartesian3_default(1, 1, 1),
vertexFormat: VertexFormat_default.POSITION_ONLY
})
);
}
return unitEllipsoidGeometry;
};
var EllipsoidGeometry_default = EllipsoidGeometry;
// packages/engine/Source/DataSources/EllipsoidGeometryUpdater.js
var defaultMaterial2 = new ColorMaterialProperty_default(Color_default.WHITE);
var defaultOffset6 = Cartesian3_default.ZERO;
var offsetScratch8 = new Cartesian3_default();
var radiiScratch = new Cartesian3_default();
var innerRadiiScratch = new Cartesian3_default();
var scratchColor16 = new Color_default();
var unitSphere = new Cartesian3_default(1, 1, 1);
function EllipsoidGeometryOptions(entity) {
this.id = entity;
this.vertexFormat = void 0;
this.radii = void 0;
this.innerRadii = void 0;
this.minimumClock = void 0;
this.maximumClock = void 0;
this.minimumCone = void 0;
this.maximumCone = void 0;
this.stackPartitions = void 0;
this.slicePartitions = void 0;
this.subdivisions = void 0;
this.offsetAttribute = void 0;
}
function EllipsoidGeometryUpdater(entity, scene) {
GeometryUpdater_default.call(this, {
entity,
scene,
geometryOptions: new EllipsoidGeometryOptions(entity),
geometryPropertyName: "ellipsoid",
observedPropertyNames: [
"availability",
"position",
"orientation",
"ellipsoid"
]
});
this._onEntityPropertyChanged(
entity,
"ellipsoid",
entity.ellipsoid,
void 0
);
}
if (defined_default(Object.create)) {
EllipsoidGeometryUpdater.prototype = Object.create(GeometryUpdater_default.prototype);
EllipsoidGeometryUpdater.prototype.constructor = EllipsoidGeometryUpdater;
}
Object.defineProperties(EllipsoidGeometryUpdater.prototype, {
/**
* Gets the terrain offset property
* @type {TerrainOffsetProperty}
* @memberof EllipsoidGeometryUpdater.prototype
* @readonly
* @private
*/
terrainOffsetProperty: {
get: function() {
return this._terrainOffsetProperty;
}
}
});
EllipsoidGeometryUpdater.prototype.createFillGeometryInstance = function(time, skipModelMatrix, modelMatrixResult) {
Check_default.defined("time", time);
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
let color;
const show = new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
);
const attributes = {
show,
distanceDisplayCondition: distanceDisplayConditionAttribute,
color: void 0,
offset: void 0
};
if (this._materialProperty instanceof ColorMaterialProperty_default) {
let currentColor;
if (defined_default(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
currentColor = this._materialProperty.color.getValue(time, scratchColor16);
}
if (!defined_default(currentColor)) {
currentColor = Color_default.WHITE;
}
color = ColorGeometryInstanceAttribute_default.fromColor(currentColor);
attributes.color = color;
}
if (defined_default(this._options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset6,
offsetScratch8
)
);
}
return new GeometryInstance_default({
id: entity,
geometry: new EllipsoidGeometry_default(this._options),
modelMatrix: skipModelMatrix ? void 0 : entity.computeModelMatrixForHeightReference(
time,
entity.ellipsoid.heightReference,
this._options.radii.z * 0.5,
this._scene.ellipsoid,
modelMatrixResult
),
attributes
});
};
EllipsoidGeometryUpdater.prototype.createOutlineGeometryInstance = function(time, skipModelMatrix, modelMatrixResult) {
Check_default.defined("time", time);
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const outlineColor = Property_default.getValueOrDefault(
this._outlineColorProperty,
time,
Color_default.BLACK,
scratchColor16
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const attributes = {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)
),
color: ColorGeometryInstanceAttribute_default.fromColor(outlineColor),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
),
offset: void 0
};
if (defined_default(this._options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset6,
offsetScratch8
)
);
}
return new GeometryInstance_default({
id: entity,
geometry: new EllipsoidOutlineGeometry_default(this._options),
modelMatrix: skipModelMatrix ? void 0 : entity.computeModelMatrixForHeightReference(
time,
entity.ellipsoid.heightReference,
this._options.radii.z * 0.5,
this._scene.ellipsoid,
modelMatrixResult
),
attributes
});
};
EllipsoidGeometryUpdater.prototype._computeCenter = function(time, result) {
return Property_default.getValueOrUndefined(this._entity.position, time, result);
};
EllipsoidGeometryUpdater.prototype._isHidden = function(entity, ellipsoid) {
return !defined_default(entity.position) || !defined_default(ellipsoid.radii) || GeometryUpdater_default.prototype._isHidden.call(this, entity, ellipsoid);
};
EllipsoidGeometryUpdater.prototype._isDynamic = function(entity, ellipsoid) {
return !entity.position.isConstant || //
!Property_default.isConstant(entity.orientation) || //
!ellipsoid.radii.isConstant || //
!Property_default.isConstant(ellipsoid.innerRadii) || //
!Property_default.isConstant(ellipsoid.stackPartitions) || //
!Property_default.isConstant(ellipsoid.slicePartitions) || //
!Property_default.isConstant(ellipsoid.outlineWidth) || //
!Property_default.isConstant(ellipsoid.minimumClock) || //
!Property_default.isConstant(ellipsoid.maximumClock) || //
!Property_default.isConstant(ellipsoid.minimumCone) || //
!Property_default.isConstant(ellipsoid.maximumCone) || //
!Property_default.isConstant(ellipsoid.subdivisions);
};
EllipsoidGeometryUpdater.prototype._setStaticOptions = function(entity, ellipsoid) {
const heightReference = Property_default.getValueOrDefault(
ellipsoid.heightReference,
Iso8601_default.MINIMUM_VALUE,
HeightReference_default.NONE
);
const options = this._options;
options.vertexFormat = this._materialProperty instanceof ColorMaterialProperty_default ? PerInstanceColorAppearance_default.VERTEX_FORMAT : MaterialAppearance_default.MaterialSupport.TEXTURED.vertexFormat;
options.radii = ellipsoid.radii.getValue(
Iso8601_default.MINIMUM_VALUE,
options.radii
);
options.innerRadii = Property_default.getValueOrUndefined(
ellipsoid.innerRadii,
options.radii
);
options.minimumClock = Property_default.getValueOrUndefined(
ellipsoid.minimumClock,
Iso8601_default.MINIMUM_VALUE
);
options.maximumClock = Property_default.getValueOrUndefined(
ellipsoid.maximumClock,
Iso8601_default.MINIMUM_VALUE
);
options.minimumCone = Property_default.getValueOrUndefined(
ellipsoid.minimumCone,
Iso8601_default.MINIMUM_VALUE
);
options.maximumCone = Property_default.getValueOrUndefined(
ellipsoid.maximumCone,
Iso8601_default.MINIMUM_VALUE
);
options.stackPartitions = Property_default.getValueOrUndefined(
ellipsoid.stackPartitions,
Iso8601_default.MINIMUM_VALUE
);
options.slicePartitions = Property_default.getValueOrUndefined(
ellipsoid.slicePartitions,
Iso8601_default.MINIMUM_VALUE
);
options.subdivisions = Property_default.getValueOrUndefined(
ellipsoid.subdivisions,
Iso8601_default.MINIMUM_VALUE
);
options.offsetAttribute = heightReference !== HeightReference_default.NONE ? GeometryOffsetAttribute_default.ALL : void 0;
};
EllipsoidGeometryUpdater.prototype._onEntityPropertyChanged = heightReferenceOnEntityPropertyChanged_default;
EllipsoidGeometryUpdater.DynamicGeometryUpdater = DynamicEllipsoidGeometryUpdater;
function DynamicEllipsoidGeometryUpdater(geometryUpdater, primitives, groundPrimitives) {
DynamicGeometryUpdater_default.call(
this,
geometryUpdater,
primitives,
groundPrimitives
);
this._scene = geometryUpdater._scene;
this._modelMatrix = new Matrix4_default();
this._attributes = void 0;
this._outlineAttributes = void 0;
this._lastSceneMode = void 0;
this._lastShow = void 0;
this._lastOutlineShow = void 0;
this._lastOutlineWidth = void 0;
this._lastOutlineColor = void 0;
this._lastOffset = new Cartesian3_default();
this._material = {};
}
if (defined_default(Object.create)) {
DynamicEllipsoidGeometryUpdater.prototype = Object.create(
DynamicGeometryUpdater_default.prototype
);
DynamicEllipsoidGeometryUpdater.prototype.constructor = DynamicEllipsoidGeometryUpdater;
}
DynamicEllipsoidGeometryUpdater.prototype.update = function(time) {
Check_default.defined("time", time);
const entity = this._entity;
const ellipsoid = entity.ellipsoid;
if (!entity.isShowing || !entity.isAvailable(time) || !Property_default.getValueOrDefault(ellipsoid.show, time, true)) {
if (defined_default(this._primitive)) {
this._primitive.show = false;
}
if (defined_default(this._outlinePrimitive)) {
this._outlinePrimitive.show = false;
}
return;
}
const radii = Property_default.getValueOrUndefined(
ellipsoid.radii,
time,
radiiScratch
);
let modelMatrix = defined_default(radii) ? entity.computeModelMatrixForHeightReference(
time,
ellipsoid.heightReference,
radii.z * 0.5,
this._scene.ellipsoid,
this._modelMatrix
) : void 0;
if (!defined_default(modelMatrix) || !defined_default(radii)) {
if (defined_default(this._primitive)) {
this._primitive.show = false;
}
if (defined_default(this._outlinePrimitive)) {
this._outlinePrimitive.show = false;
}
return;
}
const showFill = Property_default.getValueOrDefault(ellipsoid.fill, time, true);
const showOutline = Property_default.getValueOrDefault(
ellipsoid.outline,
time,
false
);
const outlineColor = Property_default.getValueOrClonedDefault(
ellipsoid.outlineColor,
time,
Color_default.BLACK,
scratchColor16
);
const material = MaterialProperty_default.getValue(
time,
ellipsoid.material ?? defaultMaterial2,
this._material
);
const innerRadii = Property_default.getValueOrUndefined(
ellipsoid.innerRadii,
time,
innerRadiiScratch
);
const minimumClock = Property_default.getValueOrUndefined(
ellipsoid.minimumClock,
time
);
const maximumClock = Property_default.getValueOrUndefined(
ellipsoid.maximumClock,
time
);
const minimumCone = Property_default.getValueOrUndefined(ellipsoid.minimumCone, time);
const maximumCone = Property_default.getValueOrUndefined(ellipsoid.maximumCone, time);
const stackPartitions = Property_default.getValueOrUndefined(
ellipsoid.stackPartitions,
time
);
const slicePartitions = Property_default.getValueOrUndefined(
ellipsoid.slicePartitions,
time
);
const subdivisions = Property_default.getValueOrUndefined(
ellipsoid.subdivisions,
time
);
const outlineWidth = Property_default.getValueOrDefault(
ellipsoid.outlineWidth,
time,
1
);
const heightReference = Property_default.getValueOrDefault(
ellipsoid.heightReference,
time,
HeightReference_default.NONE
);
const offsetAttribute = heightReference !== HeightReference_default.NONE ? GeometryOffsetAttribute_default.ALL : void 0;
const sceneMode = this._scene.mode;
const in3D = sceneMode === SceneMode_default.SCENE3D && heightReference === HeightReference_default.NONE;
const options = this._options;
const shadows = this._geometryUpdater.shadowsProperty.getValue(time);
const distanceDisplayConditionProperty = this._geometryUpdater.distanceDisplayConditionProperty;
const distanceDisplayCondition = distanceDisplayConditionProperty.getValue(time);
const offset = Property_default.getValueOrDefault(
this._geometryUpdater.terrainOffsetProperty,
time,
defaultOffset6,
offsetScratch8
);
const rebuildPrimitives = !in3D || this._lastSceneMode !== sceneMode || !defined_default(this._primitive) || //
options.stackPartitions !== stackPartitions || options.slicePartitions !== slicePartitions || //
defined_default(innerRadii) && !Cartesian3_default.equals(options.innerRadii !== innerRadii) || options.minimumClock !== minimumClock || //
options.maximumClock !== maximumClock || options.minimumCone !== minimumCone || //
options.maximumCone !== maximumCone || options.subdivisions !== subdivisions || //
this._lastOutlineWidth !== outlineWidth || options.offsetAttribute !== offsetAttribute;
if (rebuildPrimitives) {
const primitives = this._primitives;
primitives.removeAndDestroy(this._primitive);
primitives.removeAndDestroy(this._outlinePrimitive);
this._primitive = void 0;
this._outlinePrimitive = void 0;
this._lastSceneMode = sceneMode;
this._lastOutlineWidth = outlineWidth;
options.stackPartitions = stackPartitions;
options.slicePartitions = slicePartitions;
options.subdivisions = subdivisions;
options.offsetAttribute = offsetAttribute;
options.radii = Cartesian3_default.clone(in3D ? unitSphere : radii, options.radii);
if (defined_default(innerRadii)) {
if (in3D) {
options.innerRadii = Cartesian3_default.fromElements(
innerRadii.x / radii.x,
innerRadii.y / radii.y,
innerRadii.z / radii.z,
options.innerRadii
);
} else {
options.innerRadii = Cartesian3_default.clone(innerRadii, options.innerRadii);
}
} else {
options.innerRadii = void 0;
}
options.minimumClock = minimumClock;
options.maximumClock = maximumClock;
options.minimumCone = minimumCone;
options.maximumCone = maximumCone;
const appearance = new MaterialAppearance_default({
material,
translucent: material.isTranslucent(),
closed: true
});
options.vertexFormat = appearance.vertexFormat;
const fillInstance = this._geometryUpdater.createFillGeometryInstance(
time,
in3D,
this._modelMatrix
);
this._primitive = primitives.add(
new Primitive_default({
geometryInstances: fillInstance,
appearance,
asynchronous: false,
shadows
})
);
const outlineInstance = this._geometryUpdater.createOutlineGeometryInstance(
time,
in3D,
this._modelMatrix
);
this._outlinePrimitive = primitives.add(
new Primitive_default({
geometryInstances: outlineInstance,
appearance: new PerInstanceColorAppearance_default({
flat: true,
translucent: outlineInstance.attributes.color.value[3] !== 255,
renderState: {
lineWidth: this._geometryUpdater._scene.clampLineWidth(outlineWidth)
}
}),
asynchronous: false,
shadows
})
);
this._lastShow = showFill;
this._lastOutlineShow = showOutline;
this._lastOutlineColor = Color_default.clone(outlineColor, this._lastOutlineColor);
this._lastDistanceDisplayCondition = distanceDisplayCondition;
this._lastOffset = Cartesian3_default.clone(offset, this._lastOffset);
} else if (this._primitive.ready) {
const primitive = this._primitive;
const outlinePrimitive = this._outlinePrimitive;
primitive.show = true;
outlinePrimitive.show = true;
primitive.appearance.material = material;
let attributes = this._attributes;
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(entity);
this._attributes = attributes;
}
if (showFill !== this._lastShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
showFill,
attributes.show
);
this._lastShow = showFill;
}
let outlineAttributes = this._outlineAttributes;
if (!defined_default(outlineAttributes)) {
outlineAttributes = outlinePrimitive.getGeometryInstanceAttributes(entity);
this._outlineAttributes = outlineAttributes;
}
if (showOutline !== this._lastOutlineShow) {
outlineAttributes.show = ShowGeometryInstanceAttribute_default.toValue(
showOutline,
outlineAttributes.show
);
this._lastOutlineShow = showOutline;
}
if (!Color_default.equals(outlineColor, this._lastOutlineColor)) {
outlineAttributes.color = ColorGeometryInstanceAttribute_default.toValue(
outlineColor,
outlineAttributes.color
);
Color_default.clone(outlineColor, this._lastOutlineColor);
}
if (!DistanceDisplayCondition_default.equals(
distanceDisplayCondition,
this._lastDistanceDisplayCondition
)) {
attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute_default.toValue(
distanceDisplayCondition,
attributes.distanceDisplayCondition
);
outlineAttributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute_default.toValue(
distanceDisplayCondition,
outlineAttributes.distanceDisplayCondition
);
DistanceDisplayCondition_default.clone(
distanceDisplayCondition,
this._lastDistanceDisplayCondition
);
}
if (!Cartesian3_default.equals(offset, this._lastOffset)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.toValue(
offset,
attributes.offset
);
outlineAttributes.offset = OffsetGeometryInstanceAttribute_default.toValue(
offset,
attributes.offset
);
Cartesian3_default.clone(offset, this._lastOffset);
}
}
if (in3D) {
radii.x = Math.max(radii.x, 1e-3);
radii.y = Math.max(radii.y, 1e-3);
radii.z = Math.max(radii.z, 1e-3);
modelMatrix = Matrix4_default.multiplyByScale(modelMatrix, radii, modelMatrix);
this._primitive.modelMatrix = modelMatrix;
this._outlinePrimitive.modelMatrix = modelMatrix;
}
};
var EllipsoidGeometryUpdater_default = EllipsoidGeometryUpdater;
// packages/engine/Source/DataSources/PlaneGeometryUpdater.js
var import_InlineWorkers886 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PlaneGeometry.js
var import_InlineWorkers884 = __toESM(require_InlineWorkers(), 1);
function PlaneGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const vertexFormat = options.vertexFormat ?? VertexFormat_default.DEFAULT;
this._vertexFormat = vertexFormat;
this._workerName = "createPlaneGeometry";
}
PlaneGeometry.packedLength = VertexFormat_default.packedLength;
PlaneGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
return array;
};
var scratchVertexFormat7 = new VertexFormat_default();
var scratchOptions14 = {
vertexFormat: scratchVertexFormat7
};
PlaneGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat7
);
if (!defined_default(result)) {
return new PlaneGeometry(scratchOptions14);
}
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
return result;
};
var min = new Cartesian3_default(-0.5, -0.5, 0);
var max = new Cartesian3_default(0.5, 0.5, 0);
PlaneGeometry.createGeometry = function(planeGeometry) {
const vertexFormat = planeGeometry._vertexFormat;
const attributes = new GeometryAttributes_default();
let indices;
let positions;
if (vertexFormat.position) {
positions = new Float64Array(4 * 3);
positions[0] = min.x;
positions[1] = min.y;
positions[2] = 0;
positions[3] = max.x;
positions[4] = min.y;
positions[5] = 0;
positions[6] = max.x;
positions[7] = max.y;
positions[8] = 0;
positions[9] = min.x;
positions[10] = max.y;
positions[11] = 0;
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
});
if (vertexFormat.normal) {
const normals = new Float32Array(4 * 3);
normals[0] = 0;
normals[1] = 0;
normals[2] = 1;
normals[3] = 0;
normals[4] = 0;
normals[5] = 1;
normals[6] = 0;
normals[7] = 0;
normals[8] = 1;
normals[9] = 0;
normals[10] = 0;
normals[11] = 1;
attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: normals
});
}
if (vertexFormat.st) {
const texCoords = new Float32Array(4 * 2);
texCoords[0] = 0;
texCoords[1] = 0;
texCoords[2] = 1;
texCoords[3] = 0;
texCoords[4] = 1;
texCoords[5] = 1;
texCoords[6] = 0;
texCoords[7] = 1;
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: texCoords
});
}
if (vertexFormat.tangent) {
const tangents = new Float32Array(4 * 3);
tangents[0] = 1;
tangents[1] = 0;
tangents[2] = 0;
tangents[3] = 1;
tangents[4] = 0;
tangents[5] = 0;
tangents[6] = 1;
tangents[7] = 0;
tangents[8] = 0;
tangents[9] = 1;
tangents[10] = 0;
tangents[11] = 0;
attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: tangents
});
}
if (vertexFormat.bitangent) {
const bitangents = new Float32Array(4 * 3);
bitangents[0] = 0;
bitangents[1] = 1;
bitangents[2] = 0;
bitangents[3] = 0;
bitangents[4] = 1;
bitangents[5] = 0;
bitangents[6] = 0;
bitangents[7] = 1;
bitangents[8] = 0;
bitangents[9] = 0;
bitangents[10] = 1;
bitangents[11] = 0;
attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: bitangents
});
}
indices = new Uint16Array(2 * 3);
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 0;
indices[4] = 2;
indices[5] = 3;
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.TRIANGLES,
boundingSphere: new BoundingSphere_default(Cartesian3_default.ZERO, Math.sqrt(2))
});
};
var PlaneGeometry_default = PlaneGeometry;
// packages/engine/Source/Core/PlaneOutlineGeometry.js
var import_InlineWorkers885 = __toESM(require_InlineWorkers(), 1);
function PlaneOutlineGeometry() {
this._workerName = "createPlaneOutlineGeometry";
}
PlaneOutlineGeometry.packedLength = 0;
PlaneOutlineGeometry.pack = function(value, array) {
Check_default.defined("value", value);
Check_default.defined("array", array);
return array;
};
PlaneOutlineGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
if (!defined_default(result)) {
return new PlaneOutlineGeometry();
}
return result;
};
var min2 = new Cartesian3_default(-0.5, -0.5, 0);
var max2 = new Cartesian3_default(0.5, 0.5, 0);
PlaneOutlineGeometry.createGeometry = function() {
const attributes = new GeometryAttributes_default();
const indices = new Uint16Array(4 * 2);
const positions = new Float64Array(4 * 3);
positions[0] = min2.x;
positions[1] = min2.y;
positions[2] = min2.z;
positions[3] = max2.x;
positions[4] = min2.y;
positions[5] = min2.z;
positions[6] = max2.x;
positions[7] = max2.y;
positions[8] = min2.z;
positions[9] = min2.x;
positions[10] = max2.y;
positions[11] = min2.z;
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
});
indices[0] = 0;
indices[1] = 1;
indices[2] = 1;
indices[3] = 2;
indices[4] = 2;
indices[5] = 3;
indices[6] = 3;
indices[7] = 0;
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.LINES,
boundingSphere: new BoundingSphere_default(Cartesian3_default.ZERO, Math.sqrt(2))
});
};
var PlaneOutlineGeometry_default = PlaneOutlineGeometry;
// packages/engine/Source/DataSources/PlaneGeometryUpdater.js
var positionScratch11 = new Cartesian3_default();
var scratchColor17 = new Color_default();
function PlaneGeometryOptions(entity) {
this.id = entity;
this.vertexFormat = void 0;
this.plane = void 0;
this.dimensions = void 0;
}
function PlaneGeometryUpdater(entity, scene) {
GeometryUpdater_default.call(this, {
entity,
scene,
geometryOptions: new PlaneGeometryOptions(entity),
geometryPropertyName: "plane",
observedPropertyNames: ["availability", "position", "orientation", "plane"]
});
this._onEntityPropertyChanged(entity, "plane", entity.plane, void 0);
}
if (defined_default(Object.create)) {
PlaneGeometryUpdater.prototype = Object.create(GeometryUpdater_default.prototype);
PlaneGeometryUpdater.prototype.constructor = PlaneGeometryUpdater;
}
PlaneGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._fillEnabled) {
throw new DeveloperError_default(
"This instance does not represent a filled geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
let attributes;
let color;
const show = new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
);
if (this._materialProperty instanceof ColorMaterialProperty_default) {
let currentColor;
if (defined_default(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
currentColor = this._materialProperty.color.getValue(time, scratchColor17);
}
if (!defined_default(currentColor)) {
currentColor = Color_default.WHITE;
}
color = ColorGeometryInstanceAttribute_default.fromColor(currentColor);
attributes = {
show,
distanceDisplayCondition: distanceDisplayConditionAttribute,
color
};
} else {
attributes = {
show,
distanceDisplayCondition: distanceDisplayConditionAttribute
};
}
const planeGraphics = entity.plane;
const options = this._options;
let modelMatrix = entity.computeModelMatrix(time);
const plane = Property_default.getValueOrDefault(
planeGraphics.plane,
time,
options.plane
);
const dimensions = Property_default.getValueOrUndefined(
planeGraphics.dimensions,
time,
options.dimensions
);
options.plane = plane;
options.dimensions = dimensions;
modelMatrix = createPrimitiveMatrix(
plane,
dimensions,
modelMatrix,
modelMatrix
);
return new GeometryInstance_default({
id: entity,
geometry: new PlaneGeometry_default(this._options),
modelMatrix,
attributes
});
};
PlaneGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._outlineEnabled) {
throw new DeveloperError_default(
"This instance does not represent an outlined geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const outlineColor = Property_default.getValueOrDefault(
this._outlineColorProperty,
time,
Color_default.BLACK,
scratchColor17
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const planeGraphics = entity.plane;
const options = this._options;
let modelMatrix = entity.computeModelMatrix(time);
const plane = Property_default.getValueOrDefault(
planeGraphics.plane,
time,
options.plane
);
const dimensions = Property_default.getValueOrUndefined(
planeGraphics.dimensions,
time,
options.dimensions
);
options.plane = plane;
options.dimensions = dimensions;
modelMatrix = createPrimitiveMatrix(
plane,
dimensions,
modelMatrix,
modelMatrix
);
return new GeometryInstance_default({
id: entity,
geometry: new PlaneOutlineGeometry_default(),
modelMatrix,
attributes: {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)
),
color: ColorGeometryInstanceAttribute_default.fromColor(outlineColor),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
)
}
});
};
PlaneGeometryUpdater.prototype._isHidden = function(entity, plane) {
return !defined_default(plane.plane) || !defined_default(plane.dimensions) || !defined_default(entity.position) || GeometryUpdater_default.prototype._isHidden.call(this, entity, plane);
};
PlaneGeometryUpdater.prototype._getIsClosed = function(options) {
return false;
};
PlaneGeometryUpdater.prototype._isDynamic = function(entity, plane) {
return !entity.position.isConstant || //
!Property_default.isConstant(entity.orientation) || //
!plane.plane.isConstant || //
!plane.dimensions.isConstant || //
!Property_default.isConstant(plane.outlineWidth);
};
PlaneGeometryUpdater.prototype._setStaticOptions = function(entity, plane) {
const isColorMaterial = this._materialProperty instanceof ColorMaterialProperty_default;
const options = this._options;
options.vertexFormat = isColorMaterial ? PerInstanceColorAppearance_default.VERTEX_FORMAT : MaterialAppearance_default.MaterialSupport.TEXTURED.vertexFormat;
options.plane = plane.plane.getValue(Iso8601_default.MINIMUM_VALUE, options.plane);
options.dimensions = plane.dimensions.getValue(
Iso8601_default.MINIMUM_VALUE,
options.dimensions
);
};
PlaneGeometryUpdater.DynamicGeometryUpdater = DynamicPlaneGeometryUpdater;
function DynamicPlaneGeometryUpdater(geometryUpdater, primitives, groundPrimitives) {
DynamicGeometryUpdater_default.call(
this,
geometryUpdater,
primitives,
groundPrimitives
);
}
if (defined_default(Object.create)) {
DynamicPlaneGeometryUpdater.prototype = Object.create(
DynamicGeometryUpdater_default.prototype
);
DynamicPlaneGeometryUpdater.prototype.constructor = DynamicPlaneGeometryUpdater;
}
DynamicPlaneGeometryUpdater.prototype._isHidden = function(entity, plane, time) {
const options = this._options;
const position = Property_default.getValueOrUndefined(
entity.position,
time,
positionScratch11
);
return !defined_default(position) || !defined_default(options.plane) || !defined_default(options.dimensions) || DynamicGeometryUpdater_default.prototype._isHidden.call(this, entity, plane, time);
};
DynamicPlaneGeometryUpdater.prototype._setOptions = function(entity, plane, time) {
const options = this._options;
options.plane = Property_default.getValueOrDefault(plane.plane, time, options.plane);
options.dimensions = Property_default.getValueOrUndefined(
plane.dimensions,
time,
options.dimensions
);
};
var scratchAxis2 = new Cartesian3_default();
var scratchUp = new Cartesian3_default();
var scratchTranslation = new Cartesian3_default();
var scratchScale4 = new Cartesian3_default();
var scratchRotation2 = new Matrix3_default();
var scratchRotationScale2 = new Matrix3_default();
var scratchLocalTransform = new Matrix4_default();
function createPrimitiveMatrix(plane, dimensions, transform3, result) {
const normal2 = plane.normal;
const distance2 = plane.distance;
const translation3 = Cartesian3_default.multiplyByScalar(
normal2,
-distance2,
scratchTranslation
);
let up = Cartesian3_default.clone(Cartesian3_default.UNIT_Z, scratchUp);
if (Math_default.equalsEpsilon(
Math.abs(Cartesian3_default.dot(up, normal2)),
1,
Math_default.EPSILON8
)) {
up = Cartesian3_default.clone(Cartesian3_default.UNIT_Y, up);
}
const left = Cartesian3_default.cross(up, normal2, scratchAxis2);
up = Cartesian3_default.cross(normal2, left, up);
Cartesian3_default.normalize(left, left);
Cartesian3_default.normalize(up, up);
const rotationMatrix = scratchRotation2;
Matrix3_default.setColumn(rotationMatrix, 0, left, rotationMatrix);
Matrix3_default.setColumn(rotationMatrix, 1, up, rotationMatrix);
Matrix3_default.setColumn(rotationMatrix, 2, normal2, rotationMatrix);
const scale = Cartesian3_default.fromElements(
dimensions.x,
dimensions.y,
1,
scratchScale4
);
const rotationScaleMatrix = Matrix3_default.multiplyByScale(
rotationMatrix,
scale,
scratchRotationScale2
);
const localTransform = Matrix4_default.fromRotationTranslation(
rotationScaleMatrix,
translation3,
scratchLocalTransform
);
return Matrix4_default.multiplyTransformation(transform3, localTransform, result);
}
PlaneGeometryUpdater.createPrimitiveMatrix = createPrimitiveMatrix;
var PlaneGeometryUpdater_default = PlaneGeometryUpdater;
// packages/engine/Source/DataSources/PolygonGeometryUpdater.js
var import_InlineWorkers889 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/CoplanarPolygonGeometry.js
var import_InlineWorkers887 = __toESM(require_InlineWorkers(), 1);
var scratchPosition9 = new Cartesian3_default();
var scratchBR = new BoundingRectangle_default();
var stScratch = new Cartesian2_default();
var textureCoordinatesOrigin = new Cartesian2_default();
var scratchNormal6 = new Cartesian3_default();
var scratchTangent4 = new Cartesian3_default();
var scratchBitangent4 = new Cartesian3_default();
var centerScratch3 = new Cartesian3_default();
var axis1Scratch = new Cartesian3_default();
var axis2Scratch = new Cartesian3_default();
var quaternionScratch3 = new Quaternion_default();
var textureMatrixScratch2 = new Matrix3_default();
var tangentRotationScratch = new Matrix3_default();
var surfaceNormalScratch = new Cartesian3_default();
function createGeometryFromPolygon(polygon2, vertexFormat, boundingRectangle, stRotation, hardcodedTextureCoordinates, projectPointTo2D, normal2, tangent, bitangent) {
const positions = polygon2.positions;
let indices = PolygonPipeline_default.triangulate(polygon2.positions2D, polygon2.holes);
if (indices.length < 3) {
indices = [0, 1, 2];
}
const newIndices = IndexDatatype_default.createTypedArray(
positions.length,
indices.length
);
newIndices.set(indices);
let textureMatrix = textureMatrixScratch2;
if (stRotation !== 0) {
let rotation = Quaternion_default.fromAxisAngle(
normal2,
stRotation,
quaternionScratch3
);
textureMatrix = Matrix3_default.fromQuaternion(rotation, textureMatrix);
if (vertexFormat.tangent || vertexFormat.bitangent) {
rotation = Quaternion_default.fromAxisAngle(
normal2,
-stRotation,
quaternionScratch3
);
const tangentRotation = Matrix3_default.fromQuaternion(
rotation,
tangentRotationScratch
);
tangent = Cartesian3_default.normalize(
Matrix3_default.multiplyByVector(tangentRotation, tangent, tangent),
tangent
);
if (vertexFormat.bitangent) {
bitangent = Cartesian3_default.normalize(
Cartesian3_default.cross(normal2, tangent, bitangent),
bitangent
);
}
}
} else {
textureMatrix = Matrix3_default.clone(Matrix3_default.IDENTITY, textureMatrix);
}
const stOrigin = textureCoordinatesOrigin;
if (vertexFormat.st) {
stOrigin.x = boundingRectangle.x;
stOrigin.y = boundingRectangle.y;
}
const length2 = positions.length;
const size = length2 * 3;
const flatPositions = new Float64Array(size);
const normals = vertexFormat.normal ? new Float32Array(size) : void 0;
const tangents = vertexFormat.tangent ? new Float32Array(size) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(size) : void 0;
const textureCoordinates = vertexFormat.st ? new Float32Array(length2 * 2) : void 0;
let positionIndex = 0;
let normalIndex = 0;
let bitangentIndex = 0;
let tangentIndex = 0;
let stIndex = 0;
for (let i = 0; i < length2; i++) {
const position = positions[i];
flatPositions[positionIndex++] = position.x;
flatPositions[positionIndex++] = position.y;
flatPositions[positionIndex++] = position.z;
if (vertexFormat.st) {
if (defined_default(hardcodedTextureCoordinates) && hardcodedTextureCoordinates.positions.length === length2) {
textureCoordinates[stIndex++] = hardcodedTextureCoordinates.positions[i].x;
textureCoordinates[stIndex++] = hardcodedTextureCoordinates.positions[i].y;
} else {
const p = Matrix3_default.multiplyByVector(
textureMatrix,
position,
scratchPosition9
);
const st = projectPointTo2D(p, stScratch);
Cartesian2_default.subtract(st, stOrigin, st);
const stx = Math_default.clamp(st.x / boundingRectangle.width, 0, 1);
const sty = Math_default.clamp(st.y / boundingRectangle.height, 0, 1);
textureCoordinates[stIndex++] = stx;
textureCoordinates[stIndex++] = sty;
}
}
if (vertexFormat.normal) {
normals[normalIndex++] = normal2.x;
normals[normalIndex++] = normal2.y;
normals[normalIndex++] = normal2.z;
}
if (vertexFormat.tangent) {
tangents[tangentIndex++] = tangent.x;
tangents[tangentIndex++] = tangent.y;
tangents[tangentIndex++] = tangent.z;
}
if (vertexFormat.bitangent) {
bitangents[bitangentIndex++] = bitangent.x;
bitangents[bitangentIndex++] = bitangent.y;
bitangents[bitangentIndex++] = bitangent.z;
}
}
const attributes = new GeometryAttributes_default();
if (vertexFormat.position) {
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: flatPositions
});
}
if (vertexFormat.normal) {
attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: normals
});
}
if (vertexFormat.tangent) {
attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: tangents
});
}
if (vertexFormat.bitangent) {
attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: bitangents
});
}
if (vertexFormat.st) {
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: textureCoordinates
});
}
return new Geometry_default({
attributes,
indices: newIndices,
primitiveType: PrimitiveType_default.TRIANGLES
});
}
function CoplanarPolygonGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const polygonHierarchy = options.polygonHierarchy;
const textureCoordinates = options.textureCoordinates;
Check_default.defined("options.polygonHierarchy", polygonHierarchy);
const vertexFormat = options.vertexFormat ?? VertexFormat_default.DEFAULT;
this._vertexFormat = VertexFormat_default.clone(vertexFormat);
this._polygonHierarchy = polygonHierarchy;
this._stRotation = options.stRotation ?? 0;
this._ellipsoid = Ellipsoid_default.clone(options.ellipsoid ?? Ellipsoid_default.default);
this._workerName = "createCoplanarPolygonGeometry";
this._textureCoordinates = textureCoordinates;
this.packedLength = PolygonGeometryLibrary_default.computeHierarchyPackedLength(
polygonHierarchy,
Cartesian3_default
) + VertexFormat_default.packedLength + Ellipsoid_default.packedLength + (defined_default(textureCoordinates) ? PolygonGeometryLibrary_default.computeHierarchyPackedLength(
textureCoordinates,
Cartesian2_default
) : 1) + 2;
}
CoplanarPolygonGeometry.fromPositions = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.defined("options.positions", options.positions);
const newOptions2 = {
polygonHierarchy: {
positions: options.positions
},
vertexFormat: options.vertexFormat,
stRotation: options.stRotation,
ellipsoid: options.ellipsoid,
textureCoordinates: options.textureCoordinates
};
return new CoplanarPolygonGeometry(newOptions2);
};
CoplanarPolygonGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
startingIndex = PolygonGeometryLibrary_default.packPolygonHierarchy(
value._polygonHierarchy,
array,
startingIndex,
Cartesian3_default
);
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
startingIndex += VertexFormat_default.packedLength;
array[startingIndex++] = value._stRotation;
if (defined_default(value._textureCoordinates)) {
startingIndex = PolygonGeometryLibrary_default.packPolygonHierarchy(
value._textureCoordinates,
array,
startingIndex,
Cartesian2_default
);
} else {
array[startingIndex++] = -1;
}
array[startingIndex++] = value.packedLength;
return array;
};
var scratchEllipsoid7 = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var scratchVertexFormat8 = new VertexFormat_default();
var scratchOptions15 = {
polygonHierarchy: {}
};
CoplanarPolygonGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const polygonHierarchy = PolygonGeometryLibrary_default.unpackPolygonHierarchy(
array,
startingIndex,
Cartesian3_default
);
startingIndex = polygonHierarchy.startingIndex;
delete polygonHierarchy.startingIndex;
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid7);
startingIndex += Ellipsoid_default.packedLength;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat8
);
startingIndex += VertexFormat_default.packedLength;
const stRotation = array[startingIndex++];
const textureCoordinates = array[startingIndex] === -1 ? void 0 : PolygonGeometryLibrary_default.unpackPolygonHierarchy(
array,
startingIndex,
Cartesian2_default
);
if (defined_default(textureCoordinates)) {
startingIndex = textureCoordinates.startingIndex;
delete textureCoordinates.startingIndex;
} else {
startingIndex++;
}
const packedLength = array[startingIndex++];
if (!defined_default(result)) {
result = new CoplanarPolygonGeometry(scratchOptions15);
}
result._polygonHierarchy = polygonHierarchy;
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._stRotation = stRotation;
result._textureCoordinates = textureCoordinates;
result.packedLength = packedLength;
return result;
};
CoplanarPolygonGeometry.createGeometry = function(polygonGeometry) {
const vertexFormat = polygonGeometry._vertexFormat;
const polygonHierarchy = polygonGeometry._polygonHierarchy;
const stRotation = polygonGeometry._stRotation;
const textureCoordinates = polygonGeometry._textureCoordinates;
const hasTextureCoordinates = defined_default(textureCoordinates);
let outerPositions = polygonHierarchy.positions;
outerPositions = arrayRemoveDuplicates_default(
outerPositions,
Cartesian3_default.equalsEpsilon,
true
);
if (outerPositions.length < 3) {
return;
}
let normal2 = scratchNormal6;
let tangent = scratchTangent4;
let bitangent = scratchBitangent4;
let axis1 = axis1Scratch;
const axis2 = axis2Scratch;
const validGeometry = CoplanarPolygonGeometryLibrary_default.computeProjectTo2DArguments(
outerPositions,
centerScratch3,
axis1,
axis2
);
if (!validGeometry) {
return void 0;
}
normal2 = Cartesian3_default.cross(axis1, axis2, normal2);
normal2 = Cartesian3_default.normalize(normal2, normal2);
if (!Cartesian3_default.equalsEpsilon(
centerScratch3,
Cartesian3_default.ZERO,
Math_default.EPSILON6
)) {
const surfaceNormal = polygonGeometry._ellipsoid.geodeticSurfaceNormal(
centerScratch3,
surfaceNormalScratch
);
if (Cartesian3_default.dot(normal2, surfaceNormal) < 0) {
normal2 = Cartesian3_default.negate(normal2, normal2);
axis1 = Cartesian3_default.negate(axis1, axis1);
}
}
const projectPoints = CoplanarPolygonGeometryLibrary_default.createProjectPointsTo2DFunction(
centerScratch3,
axis1,
axis2
);
const projectPoint = CoplanarPolygonGeometryLibrary_default.createProjectPointTo2DFunction(
centerScratch3,
axis1,
axis2
);
if (vertexFormat.tangent) {
tangent = Cartesian3_default.clone(axis1, tangent);
}
if (vertexFormat.bitangent) {
bitangent = Cartesian3_default.clone(axis2, bitangent);
}
const results = PolygonGeometryLibrary_default.polygonsFromHierarchy(
polygonHierarchy,
hasTextureCoordinates,
projectPoints,
false
);
const hierarchy = results.hierarchy;
const polygons = results.polygons;
const dummyFunction = function(identity) {
return identity;
};
const textureCoordinatePolygons = hasTextureCoordinates ? PolygonGeometryLibrary_default.polygonsFromHierarchy(
textureCoordinates,
true,
dummyFunction,
false
).polygons : void 0;
if (hierarchy.length === 0) {
return;
}
outerPositions = hierarchy[0].outerRing;
const boundingSphere = BoundingSphere_default.fromPoints(outerPositions);
const boundingRectangle = PolygonGeometryLibrary_default.computeBoundingRectangle(
normal2,
projectPoint,
outerPositions,
stRotation,
scratchBR
);
const geometries = [];
for (let i = 0; i < polygons.length; i++) {
const geometryInstance = new GeometryInstance_default({
geometry: createGeometryFromPolygon(
polygons[i],
vertexFormat,
boundingRectangle,
stRotation,
hasTextureCoordinates ? textureCoordinatePolygons[i] : void 0,
projectPoint,
normal2,
tangent,
bitangent
)
});
geometries.push(geometryInstance);
}
const geometry = GeometryPipeline_default.combineInstances(geometries)[0];
geometry.attributes.position.values = new Float64Array(
geometry.attributes.position.values
);
geometry.indices = IndexDatatype_default.createTypedArray(
geometry.attributes.position.values.length / 3,
geometry.indices
);
const attributes = geometry.attributes;
if (!vertexFormat.position) {
delete attributes.position;
}
return new Geometry_default({
attributes,
indices: geometry.indices,
primitiveType: geometry.primitiveType,
boundingSphere
});
};
var CoplanarPolygonGeometry_default = CoplanarPolygonGeometry;
// packages/engine/Source/Core/PolygonOutlineGeometry.js
var import_InlineWorkers888 = __toESM(require_InlineWorkers(), 1);
var createGeometryFromPositionsPositions = [];
var createGeometryFromPositionsSubdivided = [];
function createGeometryFromPositions2(ellipsoid, positions, minDistance, perPositionHeight, arcType) {
const tangentPlane = EllipsoidTangentPlane_default.fromPoints(positions, ellipsoid);
const positions2D = tangentPlane.projectPointsOntoPlane(
positions,
createGeometryFromPositionsPositions
);
const originalWindingOrder = PolygonPipeline_default.computeWindingOrder2D(positions2D);
if (originalWindingOrder === WindingOrder_default.CLOCKWISE) {
positions2D.reverse();
positions = positions.slice().reverse();
}
let subdividedPositions;
let i;
let length2 = positions.length;
let index = 0;
if (!perPositionHeight) {
let numVertices = 0;
if (arcType === ArcType_default.GEODESIC) {
for (i = 0; i < length2; i++) {
numVertices += PolygonGeometryLibrary_default.subdivideLineCount(
positions[i],
positions[(i + 1) % length2],
minDistance
);
}
} else if (arcType === ArcType_default.RHUMB) {
for (i = 0; i < length2; i++) {
numVertices += PolygonGeometryLibrary_default.subdivideRhumbLineCount(
ellipsoid,
positions[i],
positions[(i + 1) % length2],
minDistance
);
}
}
subdividedPositions = new Float64Array(numVertices * 3);
for (i = 0; i < length2; i++) {
let tempPositions;
if (arcType === ArcType_default.GEODESIC) {
tempPositions = PolygonGeometryLibrary_default.subdivideLine(
positions[i],
positions[(i + 1) % length2],
minDistance,
createGeometryFromPositionsSubdivided
);
} else if (arcType === ArcType_default.RHUMB) {
tempPositions = PolygonGeometryLibrary_default.subdivideRhumbLine(
ellipsoid,
positions[i],
positions[(i + 1) % length2],
minDistance,
createGeometryFromPositionsSubdivided
);
}
const tempPositionsLength = tempPositions.length;
for (let j = 0; j < tempPositionsLength; ++j) {
subdividedPositions[index++] = tempPositions[j];
}
}
} else {
subdividedPositions = new Float64Array(length2 * 2 * 3);
for (i = 0; i < length2; i++) {
const p0 = positions[i];
const p1 = positions[(i + 1) % length2];
subdividedPositions[index++] = p0.x;
subdividedPositions[index++] = p0.y;
subdividedPositions[index++] = p0.z;
subdividedPositions[index++] = p1.x;
subdividedPositions[index++] = p1.y;
subdividedPositions[index++] = p1.z;
}
}
length2 = subdividedPositions.length / 3;
const indicesSize = length2 * 2;
const indices = IndexDatatype_default.createTypedArray(length2, indicesSize);
index = 0;
for (i = 0; i < length2 - 1; i++) {
indices[index++] = i;
indices[index++] = i + 1;
}
indices[index++] = length2 - 1;
indices[index++] = 0;
return new GeometryInstance_default({
geometry: new Geometry_default({
attributes: new GeometryAttributes_default({
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: subdividedPositions
})
}),
indices,
primitiveType: PrimitiveType_default.LINES
})
});
}
function createGeometryFromPositionsExtruded2(ellipsoid, positions, minDistance, perPositionHeight, arcType) {
const tangentPlane = EllipsoidTangentPlane_default.fromPoints(positions, ellipsoid);
const positions2D = tangentPlane.projectPointsOntoPlane(
positions,
createGeometryFromPositionsPositions
);
const originalWindingOrder = PolygonPipeline_default.computeWindingOrder2D(positions2D);
if (originalWindingOrder === WindingOrder_default.CLOCKWISE) {
positions2D.reverse();
positions = positions.slice().reverse();
}
let subdividedPositions;
let i;
let length2 = positions.length;
const corners2 = new Array(length2);
let index = 0;
if (!perPositionHeight) {
let numVertices = 0;
if (arcType === ArcType_default.GEODESIC) {
for (i = 0; i < length2; i++) {
numVertices += PolygonGeometryLibrary_default.subdivideLineCount(
positions[i],
positions[(i + 1) % length2],
minDistance
);
}
} else if (arcType === ArcType_default.RHUMB) {
for (i = 0; i < length2; i++) {
numVertices += PolygonGeometryLibrary_default.subdivideRhumbLineCount(
ellipsoid,
positions[i],
positions[(i + 1) % length2],
minDistance
);
}
}
subdividedPositions = new Float64Array(numVertices * 3 * 2);
for (i = 0; i < length2; ++i) {
corners2[i] = index / 3;
let tempPositions;
if (arcType === ArcType_default.GEODESIC) {
tempPositions = PolygonGeometryLibrary_default.subdivideLine(
positions[i],
positions[(i + 1) % length2],
minDistance,
createGeometryFromPositionsSubdivided
);
} else if (arcType === ArcType_default.RHUMB) {
tempPositions = PolygonGeometryLibrary_default.subdivideRhumbLine(
ellipsoid,
positions[i],
positions[(i + 1) % length2],
minDistance,
createGeometryFromPositionsSubdivided
);
}
const tempPositionsLength = tempPositions.length;
for (let j = 0; j < tempPositionsLength; ++j) {
subdividedPositions[index++] = tempPositions[j];
}
}
} else {
subdividedPositions = new Float64Array(length2 * 2 * 3 * 2);
for (i = 0; i < length2; ++i) {
corners2[i] = index / 3;
const p0 = positions[i];
const p1 = positions[(i + 1) % length2];
subdividedPositions[index++] = p0.x;
subdividedPositions[index++] = p0.y;
subdividedPositions[index++] = p0.z;
subdividedPositions[index++] = p1.x;
subdividedPositions[index++] = p1.y;
subdividedPositions[index++] = p1.z;
}
}
length2 = subdividedPositions.length / (3 * 2);
const cornersLength = corners2.length;
const indicesSize = (length2 * 2 + cornersLength) * 2;
const indices = IndexDatatype_default.createTypedArray(
length2 + cornersLength,
indicesSize
);
index = 0;
for (i = 0; i < length2; ++i) {
indices[index++] = i;
indices[index++] = (i + 1) % length2;
indices[index++] = i + length2;
indices[index++] = (i + 1) % length2 + length2;
}
for (i = 0; i < cornersLength; i++) {
const corner = corners2[i];
indices[index++] = corner;
indices[index++] = corner + length2;
}
return new GeometryInstance_default({
geometry: new Geometry_default({
attributes: new GeometryAttributes_default({
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: subdividedPositions
})
}),
indices,
primitiveType: PrimitiveType_default.LINES
})
});
}
function PolygonOutlineGeometry(options) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.object("options.polygonHierarchy", options.polygonHierarchy);
if (options.perPositionHeight && defined_default(options.height)) {
throw new DeveloperError_default(
"Cannot use both options.perPositionHeight and options.height"
);
}
if (defined_default(options.arcType) && options.arcType !== ArcType_default.GEODESIC && options.arcType !== ArcType_default.RHUMB) {
throw new DeveloperError_default(
"Invalid arcType. Valid options are ArcType.GEODESIC and ArcType.RHUMB."
);
}
const polygonHierarchy = options.polygonHierarchy;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
const granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
const perPositionHeight = options.perPositionHeight ?? false;
const perPositionHeightExtrude = perPositionHeight && defined_default(options.extrudedHeight);
const arcType = options.arcType ?? ArcType_default.GEODESIC;
let height = options.height ?? 0;
let extrudedHeight = options.extrudedHeight ?? height;
if (!perPositionHeightExtrude) {
const h = Math.max(height, extrudedHeight);
extrudedHeight = Math.min(height, extrudedHeight);
height = h;
}
this._ellipsoid = Ellipsoid_default.clone(ellipsoid);
this._granularity = granularity;
this._height = height;
this._extrudedHeight = extrudedHeight;
this._arcType = arcType;
this._polygonHierarchy = polygonHierarchy;
this._perPositionHeight = perPositionHeight;
this._perPositionHeightExtrude = perPositionHeightExtrude;
this._offsetAttribute = options.offsetAttribute;
this._workerName = "createPolygonOutlineGeometry";
this.packedLength = PolygonGeometryLibrary_default.computeHierarchyPackedLength(
polygonHierarchy,
Cartesian3_default
) + Ellipsoid_default.packedLength + 8;
}
PolygonOutlineGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
startingIndex = PolygonGeometryLibrary_default.packPolygonHierarchy(
value._polygonHierarchy,
array,
startingIndex,
Cartesian3_default
);
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
array[startingIndex++] = value._height;
array[startingIndex++] = value._extrudedHeight;
array[startingIndex++] = value._granularity;
array[startingIndex++] = value._perPositionHeightExtrude ? 1 : 0;
array[startingIndex++] = value._perPositionHeight ? 1 : 0;
array[startingIndex++] = value._arcType;
array[startingIndex++] = value._offsetAttribute ?? -1;
array[startingIndex] = value.packedLength;
return array;
};
var scratchEllipsoid8 = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var dummyOptions2 = {
polygonHierarchy: {}
};
PolygonOutlineGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const polygonHierarchy = PolygonGeometryLibrary_default.unpackPolygonHierarchy(
array,
startingIndex,
Cartesian3_default
);
startingIndex = polygonHierarchy.startingIndex;
delete polygonHierarchy.startingIndex;
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid8);
startingIndex += Ellipsoid_default.packedLength;
const height = array[startingIndex++];
const extrudedHeight = array[startingIndex++];
const granularity = array[startingIndex++];
const perPositionHeightExtrude = array[startingIndex++] === 1;
const perPositionHeight = array[startingIndex++] === 1;
const arcType = array[startingIndex++];
const offsetAttribute = array[startingIndex++];
const packedLength = array[startingIndex];
if (!defined_default(result)) {
result = new PolygonOutlineGeometry(dummyOptions2);
}
result._polygonHierarchy = polygonHierarchy;
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._height = height;
result._extrudedHeight = extrudedHeight;
result._granularity = granularity;
result._perPositionHeight = perPositionHeight;
result._perPositionHeightExtrude = perPositionHeightExtrude;
result._arcType = arcType;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
result.packedLength = packedLength;
return result;
};
PolygonOutlineGeometry.fromPositions = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.defined("options.positions", options.positions);
const newOptions2 = {
polygonHierarchy: {
positions: options.positions
},
height: options.height,
extrudedHeight: options.extrudedHeight,
ellipsoid: options.ellipsoid,
granularity: options.granularity,
perPositionHeight: options.perPositionHeight,
arcType: options.arcType,
offsetAttribute: options.offsetAttribute
};
return new PolygonOutlineGeometry(newOptions2);
};
PolygonOutlineGeometry.createGeometry = function(polygonGeometry) {
const ellipsoid = polygonGeometry._ellipsoid;
const granularity = polygonGeometry._granularity;
const polygonHierarchy = polygonGeometry._polygonHierarchy;
const perPositionHeight = polygonGeometry._perPositionHeight;
const arcType = polygonGeometry._arcType;
const polygons = PolygonGeometryLibrary_default.polygonOutlinesFromHierarchy(
polygonHierarchy,
!perPositionHeight,
ellipsoid
);
if (polygons.length === 0) {
return void 0;
}
let geometryInstance;
const geometries = [];
const minDistance = Math_default.chordLength(
granularity,
ellipsoid.maximumRadius
);
const height = polygonGeometry._height;
const extrudedHeight = polygonGeometry._extrudedHeight;
const extrude = polygonGeometry._perPositionHeightExtrude || !Math_default.equalsEpsilon(height, extrudedHeight, 0, Math_default.EPSILON2);
let offsetValue;
let i;
if (extrude) {
for (i = 0; i < polygons.length; i++) {
geometryInstance = createGeometryFromPositionsExtruded2(
ellipsoid,
polygons[i],
minDistance,
perPositionHeight,
arcType
);
geometryInstance.geometry = PolygonGeometryLibrary_default.scaleToGeodeticHeightExtruded(
geometryInstance.geometry,
height,
extrudedHeight,
ellipsoid,
perPositionHeight
);
if (defined_default(polygonGeometry._offsetAttribute)) {
const size = geometryInstance.geometry.attributes.position.values.length / 3;
let offsetAttribute = new Uint8Array(size);
if (polygonGeometry._offsetAttribute === GeometryOffsetAttribute_default.TOP) {
offsetAttribute = offsetAttribute.fill(1, 0, size / 2);
} else {
offsetValue = polygonGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
offsetAttribute = offsetAttribute.fill(offsetValue);
}
geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: offsetAttribute
});
}
geometries.push(geometryInstance);
}
} else {
for (i = 0; i < polygons.length; i++) {
geometryInstance = createGeometryFromPositions2(
ellipsoid,
polygons[i],
minDistance,
perPositionHeight,
arcType
);
geometryInstance.geometry.attributes.position.values = PolygonPipeline_default.scaleToGeodeticHeight(
geometryInstance.geometry.attributes.position.values,
height,
ellipsoid,
!perPositionHeight
);
if (defined_default(polygonGeometry._offsetAttribute)) {
const length2 = geometryInstance.geometry.attributes.position.values.length;
offsetValue = polygonGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
geometries.push(geometryInstance);
}
}
const geometry = GeometryPipeline_default.combineInstances(geometries)[0];
const boundingSphere = BoundingSphere_default.fromVertices(
geometry.attributes.position.values
);
return new Geometry_default({
attributes: geometry.attributes,
indices: geometry.indices,
primitiveType: geometry.primitiveType,
boundingSphere,
offsetAttribute: polygonGeometry._offsetAttribute
});
};
var PolygonOutlineGeometry_default = PolygonOutlineGeometry;
// packages/engine/Source/DataSources/PolygonGeometryUpdater.js
var heightAndPerPositionHeightWarning = "Entity polygons cannot have both height and perPositionHeight. height will be ignored";
var heightReferenceAndPerPositionHeightWarning = "heightReference is not supported for entity polygons with perPositionHeight. heightReference will be ignored";
var scratchColor18 = new Color_default();
var defaultOffset7 = Cartesian3_default.ZERO;
var offsetScratch9 = new Cartesian3_default();
var scratchRectangle8 = new Rectangle_default();
var scratch2DPositions = [];
var cart2Scratch = new Cartesian2_default();
function PolygonGeometryOptions(entity) {
this.id = entity;
this.vertexFormat = void 0;
this.polygonHierarchy = void 0;
this.perPositionHeight = void 0;
this.closeTop = void 0;
this.closeBottom = void 0;
this.height = void 0;
this.extrudedHeight = void 0;
this.granularity = void 0;
this.stRotation = void 0;
this.offsetAttribute = void 0;
this.arcType = void 0;
this.textureCoordinates = void 0;
}
function PolygonGeometryUpdater(entity, scene) {
GroundGeometryUpdater_default.call(this, {
entity,
scene,
geometryOptions: new PolygonGeometryOptions(entity),
geometryPropertyName: "polygon",
observedPropertyNames: ["availability", "polygon"]
});
this._onEntityPropertyChanged(entity, "polygon", entity.polygon, void 0);
}
if (defined_default(Object.create)) {
PolygonGeometryUpdater.prototype = Object.create(
GroundGeometryUpdater_default.prototype
);
PolygonGeometryUpdater.prototype.constructor = PolygonGeometryUpdater;
}
PolygonGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._fillEnabled) {
throw new DeveloperError_default(
"This instance does not represent a filled geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const options = this._options;
const attributes = {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)
),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
this._distanceDisplayConditionProperty.getValue(time)
),
offset: void 0,
color: void 0
};
if (this._materialProperty instanceof ColorMaterialProperty_default) {
let currentColor;
if (defined_default(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
currentColor = this._materialProperty.color.getValue(time, scratchColor18);
}
if (!defined_default(currentColor)) {
currentColor = Color_default.WHITE;
}
attributes.color = ColorGeometryInstanceAttribute_default.fromColor(currentColor);
}
if (defined_default(options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset7,
offsetScratch9
)
);
}
let geometry;
if (options.perPositionHeight && !defined_default(options.extrudedHeight)) {
geometry = new CoplanarPolygonGeometry_default(options);
} else {
geometry = new PolygonGeometry_default(options);
}
return new GeometryInstance_default({
id: entity,
geometry,
attributes
});
};
PolygonGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._outlineEnabled) {
throw new DeveloperError_default(
"This instance does not represent an outlined geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const options = this._options;
const outlineColor = Property_default.getValueOrDefault(
this._outlineColorProperty,
time,
Color_default.BLACK,
scratchColor18
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const attributes = {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)
),
color: ColorGeometryInstanceAttribute_default.fromColor(outlineColor),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
),
offset: void 0
};
if (defined_default(options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset7,
offsetScratch9
)
);
}
let geometry;
if (options.perPositionHeight && !defined_default(options.extrudedHeight)) {
geometry = new CoplanarPolygonOutlineGeometry_default(options);
} else {
geometry = new PolygonOutlineGeometry_default(options);
}
return new GeometryInstance_default({
id: entity,
geometry,
attributes
});
};
PolygonGeometryUpdater.prototype._computeCenter = function(time, result) {
const hierarchy = Property_default.getValueOrUndefined(
this._entity.polygon.hierarchy,
time
);
if (!defined_default(hierarchy)) {
return;
}
const positions = hierarchy.positions;
if (positions.length === 0) {
return;
}
const ellipsoid = this._scene.ellipsoid;
const tangentPlane = EllipsoidTangentPlane_default.fromPoints(positions, ellipsoid);
const positions2D = tangentPlane.projectPointsOntoPlane(
positions,
scratch2DPositions
);
const length2 = positions2D.length;
let area2 = 0;
let j = length2 - 1;
let centroid2D = new Cartesian2_default();
for (let i = 0; i < length2; j = i++) {
const p1 = positions2D[i];
const p2 = positions2D[j];
const f = p1.x * p2.y - p2.x * p1.y;
let sum = Cartesian2_default.add(p1, p2, cart2Scratch);
sum = Cartesian2_default.multiplyByScalar(sum, f, sum);
centroid2D = Cartesian2_default.add(centroid2D, sum, centroid2D);
area2 += f;
}
const a3 = 1 / (area2 * 3);
centroid2D = Cartesian2_default.multiplyByScalar(centroid2D, a3, centroid2D);
return tangentPlane.projectPointOntoEllipsoid(centroid2D, result);
};
PolygonGeometryUpdater.prototype._isHidden = function(entity, polygon2) {
return !defined_default(polygon2.hierarchy) || GeometryUpdater_default.prototype._isHidden.call(this, entity, polygon2);
};
PolygonGeometryUpdater.prototype._isOnTerrain = function(entity, polygon2) {
const onTerrain = GroundGeometryUpdater_default.prototype._isOnTerrain.call(
this,
entity,
polygon2
);
const perPositionHeightProperty = polygon2.perPositionHeight;
const perPositionHeightEnabled = defined_default(perPositionHeightProperty) && (perPositionHeightProperty.isConstant ? perPositionHeightProperty.getValue(Iso8601_default.MINIMUM_VALUE) : true);
return onTerrain && !perPositionHeightEnabled;
};
PolygonGeometryUpdater.prototype._isDynamic = function(entity, polygon2) {
return !polygon2.hierarchy.isConstant || //
!Property_default.isConstant(polygon2.height) || //
!Property_default.isConstant(polygon2.extrudedHeight) || //
!Property_default.isConstant(polygon2.granularity) || //
!Property_default.isConstant(polygon2.stRotation) || //
!Property_default.isConstant(polygon2.textureCoordinates) || //
!Property_default.isConstant(polygon2.outlineWidth) || //
!Property_default.isConstant(polygon2.perPositionHeight) || //
!Property_default.isConstant(polygon2.closeTop) || //
!Property_default.isConstant(polygon2.closeBottom) || //
!Property_default.isConstant(polygon2.zIndex) || //
!Property_default.isConstant(polygon2.arcType) || //
this._onTerrain && !Property_default.isConstant(this._materialProperty) && !(this._materialProperty instanceof ColorMaterialProperty_default);
};
PolygonGeometryUpdater.prototype._setStaticOptions = function(entity, polygon2) {
const isColorMaterial = this._materialProperty instanceof ColorMaterialProperty_default;
const options = this._options;
options.vertexFormat = isColorMaterial ? PerInstanceColorAppearance_default.VERTEX_FORMAT : MaterialAppearance_default.MaterialSupport.TEXTURED.vertexFormat;
const hierarchyValue = polygon2.hierarchy.getValue(Iso8601_default.MINIMUM_VALUE);
let heightValue = Property_default.getValueOrUndefined(
polygon2.height,
Iso8601_default.MINIMUM_VALUE
);
const heightReferenceValue = Property_default.getValueOrDefault(
polygon2.heightReference,
Iso8601_default.MINIMUM_VALUE,
HeightReference_default.NONE
);
let extrudedHeightValue = Property_default.getValueOrUndefined(
polygon2.extrudedHeight,
Iso8601_default.MINIMUM_VALUE
);
const extrudedHeightReferenceValue = Property_default.getValueOrDefault(
polygon2.extrudedHeightReference,
Iso8601_default.MINIMUM_VALUE,
HeightReference_default.NONE
);
const perPositionHeightValue = Property_default.getValueOrDefault(
polygon2.perPositionHeight,
Iso8601_default.MINIMUM_VALUE,
false
);
heightValue = GroundGeometryUpdater_default.getGeometryHeight(
heightValue,
heightReferenceValue
);
let offsetAttribute;
if (perPositionHeightValue) {
if (defined_default(heightValue)) {
heightValue = void 0;
oneTimeWarning_default(heightAndPerPositionHeightWarning);
}
if (heightReferenceValue !== HeightReference_default.NONE && perPositionHeightValue) {
heightValue = void 0;
oneTimeWarning_default(heightReferenceAndPerPositionHeightWarning);
}
} else {
if (defined_default(extrudedHeightValue) && !defined_default(heightValue)) {
heightValue = 0;
}
offsetAttribute = GroundGeometryUpdater_default.computeGeometryOffsetAttribute(
heightValue,
heightReferenceValue,
extrudedHeightValue,
extrudedHeightReferenceValue
);
}
options.polygonHierarchy = hierarchyValue;
options.granularity = Property_default.getValueOrUndefined(
polygon2.granularity,
Iso8601_default.MINIMUM_VALUE
);
options.stRotation = Property_default.getValueOrUndefined(
polygon2.stRotation,
Iso8601_default.MINIMUM_VALUE
);
options.perPositionHeight = perPositionHeightValue;
options.closeTop = Property_default.getValueOrDefault(
polygon2.closeTop,
Iso8601_default.MINIMUM_VALUE,
true
);
options.closeBottom = Property_default.getValueOrDefault(
polygon2.closeBottom,
Iso8601_default.MINIMUM_VALUE,
true
);
options.offsetAttribute = offsetAttribute;
options.height = heightValue;
options.arcType = Property_default.getValueOrDefault(
polygon2.arcType,
Iso8601_default.MINIMUM_VALUE,
ArcType_default.GEODESIC
);
options.textureCoordinates = Property_default.getValueOrUndefined(
polygon2.textureCoordinates,
Iso8601_default.MINIMUM_VALUE
);
extrudedHeightValue = GroundGeometryUpdater_default.getGeometryExtrudedHeight(
extrudedHeightValue,
extrudedHeightReferenceValue
);
if (extrudedHeightValue === GroundGeometryUpdater_default.CLAMP_TO_GROUND) {
const rectangle = PolygonGeometry_default.computeRectangleFromPositions(
options.polygonHierarchy.positions,
options.ellipsoid,
options.arcType,
scratchRectangle8
);
extrudedHeightValue = ApproximateTerrainHeights_default.getMinimumMaximumHeights(
rectangle
).minimumTerrainHeight;
}
options.extrudedHeight = extrudedHeightValue;
};
PolygonGeometryUpdater.prototype._getIsClosed = function(options) {
const height = options.height;
const extrudedHeight = options.extrudedHeight;
const isExtruded = defined_default(extrudedHeight) && extrudedHeight !== height;
return !options.perPositionHeight && (!isExtruded && height === 0 || isExtruded && options.closeTop && options.closeBottom);
};
PolygonGeometryUpdater.DynamicGeometryUpdater = DyanmicPolygonGeometryUpdater;
function DyanmicPolygonGeometryUpdater(geometryUpdater, primitives, groundPrimitives) {
DynamicGeometryUpdater_default.call(
this,
geometryUpdater,
primitives,
groundPrimitives
);
}
if (defined_default(Object.create)) {
DyanmicPolygonGeometryUpdater.prototype = Object.create(
DynamicGeometryUpdater_default.prototype
);
DyanmicPolygonGeometryUpdater.prototype.constructor = DyanmicPolygonGeometryUpdater;
}
DyanmicPolygonGeometryUpdater.prototype._isHidden = function(entity, polygon2, time) {
return !defined_default(this._options.polygonHierarchy) || DynamicGeometryUpdater_default.prototype._isHidden.call(this, entity, polygon2, time);
};
DyanmicPolygonGeometryUpdater.prototype._setOptions = function(entity, polygon2, time) {
const options = this._options;
options.polygonHierarchy = Property_default.getValueOrUndefined(
polygon2.hierarchy,
time
);
let heightValue = Property_default.getValueOrUndefined(polygon2.height, time);
const heightReferenceValue = Property_default.getValueOrDefault(
polygon2.heightReference,
time,
HeightReference_default.NONE
);
const extrudedHeightReferenceValue = Property_default.getValueOrDefault(
polygon2.extrudedHeightReference,
time,
HeightReference_default.NONE
);
let extrudedHeightValue = Property_default.getValueOrUndefined(
polygon2.extrudedHeight,
time
);
const perPositionHeightValue = Property_default.getValueOrUndefined(
polygon2.perPositionHeight,
time
);
heightValue = GroundGeometryUpdater_default.getGeometryHeight(
heightValue,
extrudedHeightReferenceValue
);
let offsetAttribute;
if (perPositionHeightValue) {
if (defined_default(heightValue)) {
heightValue = void 0;
oneTimeWarning_default(heightAndPerPositionHeightWarning);
}
if (heightReferenceValue !== HeightReference_default.NONE && perPositionHeightValue) {
heightValue = void 0;
oneTimeWarning_default(heightReferenceAndPerPositionHeightWarning);
}
} else {
if (defined_default(extrudedHeightValue) && !defined_default(heightValue)) {
heightValue = 0;
}
offsetAttribute = GroundGeometryUpdater_default.computeGeometryOffsetAttribute(
heightValue,
heightReferenceValue,
extrudedHeightValue,
extrudedHeightReferenceValue
);
}
options.granularity = Property_default.getValueOrUndefined(polygon2.granularity, time);
options.stRotation = Property_default.getValueOrUndefined(polygon2.stRotation, time);
options.textureCoordinates = Property_default.getValueOrUndefined(
polygon2.textureCoordinates,
time
);
options.perPositionHeight = Property_default.getValueOrUndefined(
polygon2.perPositionHeight,
time
);
options.closeTop = Property_default.getValueOrDefault(polygon2.closeTop, time, true);
options.closeBottom = Property_default.getValueOrDefault(
polygon2.closeBottom,
time,
true
);
options.offsetAttribute = offsetAttribute;
options.height = heightValue;
options.arcType = Property_default.getValueOrDefault(
polygon2.arcType,
time,
ArcType_default.GEODESIC
);
extrudedHeightValue = GroundGeometryUpdater_default.getGeometryExtrudedHeight(
extrudedHeightValue,
extrudedHeightReferenceValue
);
if (extrudedHeightValue === GroundGeometryUpdater_default.CLAMP_TO_GROUND) {
const rectangle = PolygonGeometry_default.computeRectangleFromPositions(
options.polygonHierarchy.positions,
options.ellipsoid,
options.arcType,
scratchRectangle8
);
extrudedHeightValue = ApproximateTerrainHeights_default.getMinimumMaximumHeights(
rectangle
).minimumTerrainHeight;
}
options.extrudedHeight = extrudedHeightValue;
};
var PolygonGeometryUpdater_default = PolygonGeometryUpdater;
// packages/engine/Source/DataSources/PolylineVolumeGeometryUpdater.js
var import_InlineWorkers892 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PolylineVolumeGeometry.js
var import_InlineWorkers890 = __toESM(require_InlineWorkers(), 1);
function computeAttributes2(combinedPositions, shape, boundingRectangle, vertexFormat) {
const attributes = new GeometryAttributes_default();
if (vertexFormat.position) {
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: combinedPositions
});
}
const shapeLength = shape.length;
const vertexCount = combinedPositions.length / 3;
const length2 = (vertexCount - shapeLength * 2) / (shapeLength * 2);
const firstEndIndices = PolygonPipeline_default.triangulate(shape);
const indicesCount = (length2 - 1) * shapeLength * 6 + firstEndIndices.length * 2;
const indices = IndexDatatype_default.createTypedArray(vertexCount, indicesCount);
let i, j;
let ll, ul, ur, lr;
const offset = shapeLength * 2;
let index = 0;
for (i = 0; i < length2 - 1; i++) {
for (j = 0; j < shapeLength - 1; j++) {
ll = j * 2 + i * shapeLength * 2;
lr = ll + offset;
ul = ll + 1;
ur = ul + offset;
indices[index++] = ul;
indices[index++] = ll;
indices[index++] = ur;
indices[index++] = ur;
indices[index++] = ll;
indices[index++] = lr;
}
ll = shapeLength * 2 - 2 + i * shapeLength * 2;
ul = ll + 1;
ur = ul + offset;
lr = ll + offset;
indices[index++] = ul;
indices[index++] = ll;
indices[index++] = ur;
indices[index++] = ur;
indices[index++] = ll;
indices[index++] = lr;
}
if (vertexFormat.st || vertexFormat.tangent || vertexFormat.bitangent) {
const st = new Float32Array(vertexCount * 2);
const lengthSt = 1 / (length2 - 1);
const heightSt = 1 / boundingRectangle.height;
const heightOffset = boundingRectangle.height / 2;
let s, t;
let stindex = 0;
for (i = 0; i < length2; i++) {
s = i * lengthSt;
t = heightSt * (shape[0].y + heightOffset);
st[stindex++] = s;
st[stindex++] = t;
for (j = 1; j < shapeLength; j++) {
t = heightSt * (shape[j].y + heightOffset);
st[stindex++] = s;
st[stindex++] = t;
st[stindex++] = s;
st[stindex++] = t;
}
t = heightSt * (shape[0].y + heightOffset);
st[stindex++] = s;
st[stindex++] = t;
}
for (j = 0; j < shapeLength; j++) {
s = 0;
t = heightSt * (shape[j].y + heightOffset);
st[stindex++] = s;
st[stindex++] = t;
}
for (j = 0; j < shapeLength; j++) {
s = (length2 - 1) * lengthSt;
t = heightSt * (shape[j].y + heightOffset);
st[stindex++] = s;
st[stindex++] = t;
}
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: new Float32Array(st)
});
}
const endOffset = vertexCount - shapeLength * 2;
for (i = 0; i < firstEndIndices.length; i += 3) {
const v02 = firstEndIndices[i] + endOffset;
const v12 = firstEndIndices[i + 1] + endOffset;
const v22 = firstEndIndices[i + 2] + endOffset;
indices[index++] = v02;
indices[index++] = v12;
indices[index++] = v22;
indices[index++] = v22 + shapeLength;
indices[index++] = v12 + shapeLength;
indices[index++] = v02 + shapeLength;
}
let geometry = new Geometry_default({
attributes,
indices,
boundingSphere: BoundingSphere_default.fromVertices(combinedPositions),
primitiveType: PrimitiveType_default.TRIANGLES
});
if (vertexFormat.normal) {
geometry = GeometryPipeline_default.computeNormal(geometry);
}
if (vertexFormat.tangent || vertexFormat.bitangent) {
try {
geometry = GeometryPipeline_default.computeTangentAndBitangent(geometry);
} catch (e) {
oneTimeWarning_default(
"polyline-volume-tangent-bitangent",
"Unable to compute tangents and bitangents for polyline volume geometry"
);
}
if (!vertexFormat.tangent) {
geometry.attributes.tangent = void 0;
}
if (!vertexFormat.bitangent) {
geometry.attributes.bitangent = void 0;
}
if (!vertexFormat.st) {
geometry.attributes.st = void 0;
}
}
return geometry;
}
function PolylineVolumeGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const positions = options.polylinePositions;
const shape = options.shapePositions;
if (!defined_default(positions)) {
throw new DeveloperError_default("options.polylinePositions is required.");
}
if (!defined_default(shape)) {
throw new DeveloperError_default("options.shapePositions is required.");
}
this._positions = positions;
this._shape = shape;
this._ellipsoid = Ellipsoid_default.clone(options.ellipsoid ?? Ellipsoid_default.default);
this._cornerType = options.cornerType ?? CornerType_default.ROUNDED;
this._vertexFormat = VertexFormat_default.clone(
options.vertexFormat ?? VertexFormat_default.DEFAULT
);
this._granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
this._workerName = "createPolylineVolumeGeometry";
let numComponents = 1 + positions.length * Cartesian3_default.packedLength;
numComponents += 1 + shape.length * Cartesian2_default.packedLength;
this.packedLength = numComponents + Ellipsoid_default.packedLength + VertexFormat_default.packedLength + 2;
}
PolylineVolumeGeometry.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
const positions = value._positions;
let length2 = positions.length;
array[startingIndex++] = length2;
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
Cartesian3_default.pack(positions[i], array, startingIndex);
}
const shape = value._shape;
length2 = shape.length;
array[startingIndex++] = length2;
for (i = 0; i < length2; ++i, startingIndex += Cartesian2_default.packedLength) {
Cartesian2_default.pack(shape[i], array, startingIndex);
}
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
startingIndex += VertexFormat_default.packedLength;
array[startingIndex++] = value._cornerType;
array[startingIndex] = value._granularity;
return array;
};
var scratchEllipsoid9 = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var scratchVertexFormat9 = new VertexFormat_default();
var scratchOptions16 = {
polylinePositions: void 0,
shapePositions: void 0,
ellipsoid: scratchEllipsoid9,
vertexFormat: scratchVertexFormat9,
cornerType: void 0,
granularity: void 0
};
PolylineVolumeGeometry.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
let length2 = array[startingIndex++];
const positions = new Array(length2);
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
positions[i] = Cartesian3_default.unpack(array, startingIndex);
}
length2 = array[startingIndex++];
const shape = new Array(length2);
for (i = 0; i < length2; ++i, startingIndex += Cartesian2_default.packedLength) {
shape[i] = Cartesian2_default.unpack(array, startingIndex);
}
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid9);
startingIndex += Ellipsoid_default.packedLength;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat9
);
startingIndex += VertexFormat_default.packedLength;
const cornerType = array[startingIndex++];
const granularity = array[startingIndex];
if (!defined_default(result)) {
scratchOptions16.polylinePositions = positions;
scratchOptions16.shapePositions = shape;
scratchOptions16.cornerType = cornerType;
scratchOptions16.granularity = granularity;
return new PolylineVolumeGeometry(scratchOptions16);
}
result._positions = positions;
result._shape = shape;
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._cornerType = cornerType;
result._granularity = granularity;
return result;
};
var brScratch = new BoundingRectangle_default();
PolylineVolumeGeometry.createGeometry = function(polylineVolumeGeometry) {
const positions = polylineVolumeGeometry._positions;
const cleanPositions = arrayRemoveDuplicates_default(
positions,
Cartesian3_default.equalsEpsilon
);
let shape2D = polylineVolumeGeometry._shape;
shape2D = PolylineVolumeGeometryLibrary_default.removeDuplicatesFromShape(shape2D);
if (cleanPositions.length < 2 || shape2D.length < 3) {
return void 0;
}
if (PolygonPipeline_default.computeWindingOrder2D(shape2D) === WindingOrder_default.CLOCKWISE) {
shape2D.reverse();
}
const boundingRectangle = BoundingRectangle_default.fromPoints(shape2D, brScratch);
const computedPositions = PolylineVolumeGeometryLibrary_default.computePositions(
cleanPositions,
shape2D,
boundingRectangle,
polylineVolumeGeometry,
true
);
return computeAttributes2(
computedPositions,
shape2D,
boundingRectangle,
polylineVolumeGeometry._vertexFormat
);
};
var PolylineVolumeGeometry_default = PolylineVolumeGeometry;
// packages/engine/Source/Core/PolylineVolumeOutlineGeometry.js
var import_InlineWorkers891 = __toESM(require_InlineWorkers(), 1);
function computeAttributes3(positions, shape) {
const attributes = new GeometryAttributes_default();
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
});
const shapeLength = shape.length;
const vertexCount = attributes.position.values.length / 3;
const positionLength = positions.length / 3;
const shapeCount = positionLength / shapeLength;
const indices = IndexDatatype_default.createTypedArray(
vertexCount,
2 * shapeLength * (shapeCount + 1)
);
let i, j;
let index = 0;
i = 0;
let offset = i * shapeLength;
for (j = 0; j < shapeLength - 1; j++) {
indices[index++] = j + offset;
indices[index++] = j + offset + 1;
}
indices[index++] = shapeLength - 1 + offset;
indices[index++] = offset;
i = shapeCount - 1;
offset = i * shapeLength;
for (j = 0; j < shapeLength - 1; j++) {
indices[index++] = j + offset;
indices[index++] = j + offset + 1;
}
indices[index++] = shapeLength - 1 + offset;
indices[index++] = offset;
for (i = 0; i < shapeCount - 1; i++) {
const firstOffset = shapeLength * i;
const secondOffset = firstOffset + shapeLength;
for (j = 0; j < shapeLength; j++) {
indices[index++] = j + firstOffset;
indices[index++] = j + secondOffset;
}
}
const geometry = new Geometry_default({
attributes,
indices: IndexDatatype_default.createTypedArray(vertexCount, indices),
boundingSphere: BoundingSphere_default.fromVertices(positions),
primitiveType: PrimitiveType_default.LINES
});
return geometry;
}
function PolylineVolumeOutlineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const positions = options.polylinePositions;
const shape = options.shapePositions;
if (!defined_default(positions)) {
throw new DeveloperError_default("options.polylinePositions is required.");
}
if (!defined_default(shape)) {
throw new DeveloperError_default("options.shapePositions is required.");
}
this._positions = positions;
this._shape = shape;
this._ellipsoid = Ellipsoid_default.clone(options.ellipsoid ?? Ellipsoid_default.default);
this._cornerType = options.cornerType ?? CornerType_default.ROUNDED;
this._granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
this._workerName = "createPolylineVolumeOutlineGeometry";
let numComponents = 1 + positions.length * Cartesian3_default.packedLength;
numComponents += 1 + shape.length * Cartesian2_default.packedLength;
this.packedLength = numComponents + Ellipsoid_default.packedLength + 2;
}
PolylineVolumeOutlineGeometry.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
const positions = value._positions;
let length2 = positions.length;
array[startingIndex++] = length2;
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
Cartesian3_default.pack(positions[i], array, startingIndex);
}
const shape = value._shape;
length2 = shape.length;
array[startingIndex++] = length2;
for (i = 0; i < length2; ++i, startingIndex += Cartesian2_default.packedLength) {
Cartesian2_default.pack(shape[i], array, startingIndex);
}
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
array[startingIndex++] = value._cornerType;
array[startingIndex] = value._granularity;
return array;
};
var scratchEllipsoid10 = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var scratchOptions17 = {
polylinePositions: void 0,
shapePositions: void 0,
ellipsoid: scratchEllipsoid10,
height: void 0,
cornerType: void 0,
granularity: void 0
};
PolylineVolumeOutlineGeometry.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
let length2 = array[startingIndex++];
const positions = new Array(length2);
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
positions[i] = Cartesian3_default.unpack(array, startingIndex);
}
length2 = array[startingIndex++];
const shape = new Array(length2);
for (i = 0; i < length2; ++i, startingIndex += Cartesian2_default.packedLength) {
shape[i] = Cartesian2_default.unpack(array, startingIndex);
}
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid10);
startingIndex += Ellipsoid_default.packedLength;
const cornerType = array[startingIndex++];
const granularity = array[startingIndex];
if (!defined_default(result)) {
scratchOptions17.polylinePositions = positions;
scratchOptions17.shapePositions = shape;
scratchOptions17.cornerType = cornerType;
scratchOptions17.granularity = granularity;
return new PolylineVolumeOutlineGeometry(scratchOptions17);
}
result._positions = positions;
result._shape = shape;
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._cornerType = cornerType;
result._granularity = granularity;
return result;
};
var brScratch2 = new BoundingRectangle_default();
PolylineVolumeOutlineGeometry.createGeometry = function(polylineVolumeOutlineGeometry) {
const positions = polylineVolumeOutlineGeometry._positions;
const cleanPositions = arrayRemoveDuplicates_default(
positions,
Cartesian3_default.equalsEpsilon
);
let shape2D = polylineVolumeOutlineGeometry._shape;
shape2D = PolylineVolumeGeometryLibrary_default.removeDuplicatesFromShape(shape2D);
if (cleanPositions.length < 2 || shape2D.length < 3) {
return void 0;
}
if (PolygonPipeline_default.computeWindingOrder2D(shape2D) === WindingOrder_default.CLOCKWISE) {
shape2D.reverse();
}
const boundingRectangle = BoundingRectangle_default.fromPoints(shape2D, brScratch2);
const computedPositions = PolylineVolumeGeometryLibrary_default.computePositions(
cleanPositions,
shape2D,
boundingRectangle,
polylineVolumeOutlineGeometry,
false
);
return computeAttributes3(computedPositions, shape2D);
};
var PolylineVolumeOutlineGeometry_default = PolylineVolumeOutlineGeometry;
// packages/engine/Source/DataSources/PolylineVolumeGeometryUpdater.js
var scratchColor19 = new Color_default();
function PolylineVolumeGeometryOptions(entity) {
this.id = entity;
this.vertexFormat = void 0;
this.polylinePositions = void 0;
this.shapePositions = void 0;
this.cornerType = void 0;
this.granularity = void 0;
}
function PolylineVolumeGeometryUpdater(entity, scene) {
GeometryUpdater_default.call(this, {
entity,
scene,
geometryOptions: new PolylineVolumeGeometryOptions(entity),
geometryPropertyName: "polylineVolume",
observedPropertyNames: ["availability", "polylineVolume"]
});
this._onEntityPropertyChanged(
entity,
"polylineVolume",
entity.polylineVolume,
void 0
);
}
if (defined_default(Object.create)) {
PolylineVolumeGeometryUpdater.prototype = Object.create(
GeometryUpdater_default.prototype
);
PolylineVolumeGeometryUpdater.prototype.constructor = PolylineVolumeGeometryUpdater;
}
PolylineVolumeGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._fillEnabled) {
throw new DeveloperError_default(
"This instance does not represent a filled geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
let attributes;
let color;
const show = new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
);
if (this._materialProperty instanceof ColorMaterialProperty_default) {
let currentColor;
if (defined_default(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
currentColor = this._materialProperty.color.getValue(time, scratchColor19);
}
if (!defined_default(currentColor)) {
currentColor = Color_default.WHITE;
}
color = ColorGeometryInstanceAttribute_default.fromColor(currentColor);
attributes = {
show,
distanceDisplayCondition: distanceDisplayConditionAttribute,
color
};
} else {
attributes = {
show,
distanceDisplayCondition: distanceDisplayConditionAttribute
};
}
return new GeometryInstance_default({
id: entity,
geometry: new PolylineVolumeGeometry_default(this._options),
attributes
});
};
PolylineVolumeGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._outlineEnabled) {
throw new DeveloperError_default(
"This instance does not represent an outlined geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const outlineColor = Property_default.getValueOrDefault(
this._outlineColorProperty,
time,
Color_default.BLACK,
scratchColor19
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
return new GeometryInstance_default({
id: entity,
geometry: new PolylineVolumeOutlineGeometry_default(this._options),
attributes: {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)
),
color: ColorGeometryInstanceAttribute_default.fromColor(outlineColor),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
)
}
});
};
PolylineVolumeGeometryUpdater.prototype._isHidden = function(entity, polylineVolume) {
return !defined_default(polylineVolume.positions) || !defined_default(polylineVolume.shape) || GeometryUpdater_default.prototype._isHidden.call(this, entity, polylineVolume);
};
PolylineVolumeGeometryUpdater.prototype._isDynamic = function(entity, polylineVolume) {
return !polylineVolume.positions.isConstant || //
!polylineVolume.shape.isConstant || //
!Property_default.isConstant(polylineVolume.granularity) || //
!Property_default.isConstant(polylineVolume.outlineWidth) || //
!Property_default.isConstant(polylineVolume.cornerType);
};
PolylineVolumeGeometryUpdater.prototype._setStaticOptions = function(entity, polylineVolume) {
const granularity = polylineVolume.granularity;
const cornerType = polylineVolume.cornerType;
const options = this._options;
const isColorMaterial = this._materialProperty instanceof ColorMaterialProperty_default;
options.vertexFormat = isColorMaterial ? PerInstanceColorAppearance_default.VERTEX_FORMAT : MaterialAppearance_default.MaterialSupport.TEXTURED.vertexFormat;
options.polylinePositions = polylineVolume.positions.getValue(
Iso8601_default.MINIMUM_VALUE,
options.polylinePositions
);
options.shapePositions = polylineVolume.shape.getValue(
Iso8601_default.MINIMUM_VALUE,
options.shape
);
options.granularity = defined_default(granularity) ? granularity.getValue(Iso8601_default.MINIMUM_VALUE) : void 0;
options.cornerType = defined_default(cornerType) ? cornerType.getValue(Iso8601_default.MINIMUM_VALUE) : void 0;
};
PolylineVolumeGeometryUpdater.DynamicGeometryUpdater = DynamicPolylineVolumeGeometryUpdater;
function DynamicPolylineVolumeGeometryUpdater(geometryUpdater, primitives, groundPrimitives) {
DynamicGeometryUpdater_default.call(
this,
geometryUpdater,
primitives,
groundPrimitives
);
}
if (defined_default(Object.create)) {
DynamicPolylineVolumeGeometryUpdater.prototype = Object.create(
DynamicGeometryUpdater_default.prototype
);
DynamicPolylineVolumeGeometryUpdater.prototype.constructor = DynamicPolylineVolumeGeometryUpdater;
}
DynamicPolylineVolumeGeometryUpdater.prototype._isHidden = function(entity, polylineVolume, time) {
const options = this._options;
return !defined_default(options.polylinePositions) || !defined_default(options.shapePositions) || DynamicGeometryUpdater_default.prototype._isHidden.call(
this,
entity,
polylineVolume,
time
);
};
DynamicPolylineVolumeGeometryUpdater.prototype._setOptions = function(entity, polylineVolume, time) {
const options = this._options;
options.polylinePositions = Property_default.getValueOrUndefined(
polylineVolume.positions,
time,
options.polylinePositions
);
options.shapePositions = Property_default.getValueOrUndefined(
polylineVolume.shape,
time
);
options.granularity = Property_default.getValueOrUndefined(
polylineVolume.granularity,
time
);
options.cornerType = Property_default.getValueOrUndefined(
polylineVolume.cornerType,
time
);
};
var PolylineVolumeGeometryUpdater_default = PolylineVolumeGeometryUpdater;
// packages/engine/Source/DataSources/RectangleGeometryUpdater.js
var import_InlineWorkers894 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/RectangleGeometry.js
var import_InlineWorkers893 = __toESM(require_InlineWorkers(), 1);
var positionScratch12 = new Cartesian3_default();
var normalScratch4 = new Cartesian3_default();
var tangentScratch2 = new Cartesian3_default();
var bitangentScratch2 = new Cartesian3_default();
var rectangleScratch4 = new Rectangle_default();
var stScratch2 = new Cartesian2_default();
var bottomBoundingSphere4 = new BoundingSphere_default();
var topBoundingSphere4 = new BoundingSphere_default();
function createAttributes(vertexFormat, attributes) {
const geo = new Geometry_default({
attributes: new GeometryAttributes_default(),
primitiveType: PrimitiveType_default.TRIANGLES
});
geo.attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: attributes.positions
});
if (vertexFormat.normal) {
geo.attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: attributes.normals
});
}
if (vertexFormat.tangent) {
geo.attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: attributes.tangents
});
}
if (vertexFormat.bitangent) {
geo.attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: attributes.bitangents
});
}
return geo;
}
function calculateAttributes(positions, vertexFormat, ellipsoid, tangentRotationMatrix) {
const length2 = positions.length;
const normals = vertexFormat.normal ? new Float32Array(length2) : void 0;
const tangents = vertexFormat.tangent ? new Float32Array(length2) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(length2) : void 0;
let attrIndex = 0;
const bitangent = bitangentScratch2;
const tangent = tangentScratch2;
let normal2 = normalScratch4;
if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {
for (let i = 0; i < length2; i += 3) {
const p = Cartesian3_default.fromArray(positions, i, positionScratch12);
const attrIndex1 = attrIndex + 1;
const attrIndex2 = attrIndex + 2;
normal2 = ellipsoid.geodeticSurfaceNormal(p, normal2);
if (vertexFormat.tangent || vertexFormat.bitangent) {
Cartesian3_default.cross(Cartesian3_default.UNIT_Z, normal2, tangent);
Matrix3_default.multiplyByVector(tangentRotationMatrix, tangent, tangent);
Cartesian3_default.normalize(tangent, tangent);
if (vertexFormat.bitangent) {
Cartesian3_default.normalize(
Cartesian3_default.cross(normal2, tangent, bitangent),
bitangent
);
}
}
if (vertexFormat.normal) {
normals[attrIndex] = normal2.x;
normals[attrIndex1] = normal2.y;
normals[attrIndex2] = normal2.z;
}
if (vertexFormat.tangent) {
tangents[attrIndex] = tangent.x;
tangents[attrIndex1] = tangent.y;
tangents[attrIndex2] = tangent.z;
}
if (vertexFormat.bitangent) {
bitangents[attrIndex] = bitangent.x;
bitangents[attrIndex1] = bitangent.y;
bitangents[attrIndex2] = bitangent.z;
}
attrIndex += 3;
}
}
return createAttributes(vertexFormat, {
positions,
normals,
tangents,
bitangents
});
}
var v1Scratch = new Cartesian3_default();
var v2Scratch = new Cartesian3_default();
function calculateAttributesWall(positions, vertexFormat, ellipsoid) {
const length2 = positions.length;
const normals = vertexFormat.normal ? new Float32Array(length2) : void 0;
const tangents = vertexFormat.tangent ? new Float32Array(length2) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(length2) : void 0;
let normalIndex = 0;
let tangentIndex = 0;
let bitangentIndex = 0;
let recomputeNormal = true;
let bitangent = bitangentScratch2;
let tangent = tangentScratch2;
let normal2 = normalScratch4;
if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {
for (let i = 0; i < length2; i += 6) {
const p = Cartesian3_default.fromArray(positions, i, positionScratch12);
const p1 = Cartesian3_default.fromArray(positions, (i + 6) % length2, v1Scratch);
if (recomputeNormal) {
const p2 = Cartesian3_default.fromArray(positions, (i + 3) % length2, v2Scratch);
Cartesian3_default.subtract(p1, p, p1);
Cartesian3_default.subtract(p2, p, p2);
normal2 = Cartesian3_default.normalize(Cartesian3_default.cross(p2, p1, normal2), normal2);
recomputeNormal = false;
}
if (Cartesian3_default.equalsEpsilon(p1, p, Math_default.EPSILON10)) {
recomputeNormal = true;
}
if (vertexFormat.tangent || vertexFormat.bitangent) {
bitangent = ellipsoid.geodeticSurfaceNormal(p, bitangent);
if (vertexFormat.tangent) {
tangent = Cartesian3_default.normalize(
Cartesian3_default.cross(bitangent, normal2, tangent),
tangent
);
}
}
if (vertexFormat.normal) {
normals[normalIndex++] = normal2.x;
normals[normalIndex++] = normal2.y;
normals[normalIndex++] = normal2.z;
normals[normalIndex++] = normal2.x;
normals[normalIndex++] = normal2.y;
normals[normalIndex++] = normal2.z;
}
if (vertexFormat.tangent) {
tangents[tangentIndex++] = tangent.x;
tangents[tangentIndex++] = tangent.y;
tangents[tangentIndex++] = tangent.z;
tangents[tangentIndex++] = tangent.x;
tangents[tangentIndex++] = tangent.y;
tangents[tangentIndex++] = tangent.z;
}
if (vertexFormat.bitangent) {
bitangents[bitangentIndex++] = bitangent.x;
bitangents[bitangentIndex++] = bitangent.y;
bitangents[bitangentIndex++] = bitangent.z;
bitangents[bitangentIndex++] = bitangent.x;
bitangents[bitangentIndex++] = bitangent.y;
bitangents[bitangentIndex++] = bitangent.z;
}
}
}
return createAttributes(vertexFormat, {
positions,
normals,
tangents,
bitangents
});
}
function constructRectangle2(rectangleGeometry, computedOptions) {
const vertexFormat = rectangleGeometry._vertexFormat;
const ellipsoid = rectangleGeometry._ellipsoid;
const height = computedOptions.height;
const width = computedOptions.width;
const northCap = computedOptions.northCap;
const southCap = computedOptions.southCap;
let rowStart = 0;
let rowEnd = height;
let rowHeight = height;
let size = 0;
if (northCap) {
rowStart = 1;
rowHeight -= 1;
size += 1;
}
if (southCap) {
rowEnd -= 1;
rowHeight -= 1;
size += 1;
}
size += width * rowHeight;
const positions = vertexFormat.position ? new Float64Array(size * 3) : void 0;
const textureCoordinates = vertexFormat.st ? new Float32Array(size * 2) : void 0;
let posIndex = 0;
let stIndex = 0;
const position = positionScratch12;
const st = stScratch2;
let minX = Number.MAX_VALUE;
let minY = Number.MAX_VALUE;
let maxX = -Number.MAX_VALUE;
let maxY = -Number.MAX_VALUE;
for (let row = rowStart; row < rowEnd; ++row) {
for (let col = 0; col < width; ++col) {
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
vertexFormat.st,
row,
col,
position,
st
);
positions[posIndex++] = position.x;
positions[posIndex++] = position.y;
positions[posIndex++] = position.z;
if (vertexFormat.st) {
textureCoordinates[stIndex++] = st.x;
textureCoordinates[stIndex++] = st.y;
minX = Math.min(minX, st.x);
minY = Math.min(minY, st.y);
maxX = Math.max(maxX, st.x);
maxY = Math.max(maxY, st.y);
}
}
}
if (northCap) {
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
vertexFormat.st,
0,
0,
position,
st
);
positions[posIndex++] = position.x;
positions[posIndex++] = position.y;
positions[posIndex++] = position.z;
if (vertexFormat.st) {
textureCoordinates[stIndex++] = st.x;
textureCoordinates[stIndex++] = st.y;
minX = st.x;
minY = st.y;
maxX = st.x;
maxY = st.y;
}
}
if (southCap) {
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
vertexFormat.st,
height - 1,
0,
position,
st
);
positions[posIndex++] = position.x;
positions[posIndex++] = position.y;
positions[posIndex] = position.z;
if (vertexFormat.st) {
textureCoordinates[stIndex++] = st.x;
textureCoordinates[stIndex] = st.y;
minX = Math.min(minX, st.x);
minY = Math.min(minY, st.y);
maxX = Math.max(maxX, st.x);
maxY = Math.max(maxY, st.y);
}
}
if (vertexFormat.st && (minX < 0 || minY < 0 || maxX > 1 || maxY > 1)) {
for (let k = 0; k < textureCoordinates.length; k += 2) {
textureCoordinates[k] = (textureCoordinates[k] - minX) / (maxX - minX);
textureCoordinates[k + 1] = (textureCoordinates[k + 1] - minY) / (maxY - minY);
}
}
const geo = calculateAttributes(
positions,
vertexFormat,
ellipsoid,
computedOptions.tangentRotationMatrix
);
let indicesSize = 6 * (width - 1) * (rowHeight - 1);
if (northCap) {
indicesSize += 3 * (width - 1);
}
if (southCap) {
indicesSize += 3 * (width - 1);
}
const indices = IndexDatatype_default.createTypedArray(size, indicesSize);
let index = 0;
let indicesIndex = 0;
let i;
for (i = 0; i < rowHeight - 1; ++i) {
for (let j = 0; j < width - 1; ++j) {
const upperLeft = index;
const lowerLeft = upperLeft + width;
const lowerRight = lowerLeft + 1;
const upperRight = upperLeft + 1;
indices[indicesIndex++] = upperLeft;
indices[indicesIndex++] = lowerLeft;
indices[indicesIndex++] = upperRight;
indices[indicesIndex++] = upperRight;
indices[indicesIndex++] = lowerLeft;
indices[indicesIndex++] = lowerRight;
++index;
}
++index;
}
if (northCap || southCap) {
let northIndex = size - 1;
const southIndex = size - 1;
if (northCap && southCap) {
northIndex = size - 2;
}
let p1;
let p2;
index = 0;
if (northCap) {
for (i = 0; i < width - 1; i++) {
p1 = index;
p2 = p1 + 1;
indices[indicesIndex++] = northIndex;
indices[indicesIndex++] = p1;
indices[indicesIndex++] = p2;
++index;
}
}
if (southCap) {
index = (rowHeight - 1) * width;
for (i = 0; i < width - 1; i++) {
p1 = index;
p2 = p1 + 1;
indices[indicesIndex++] = p1;
indices[indicesIndex++] = southIndex;
indices[indicesIndex++] = p2;
++index;
}
}
}
geo.indices = indices;
if (vertexFormat.st) {
geo.attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: textureCoordinates
});
}
return geo;
}
function addWallPositions2(wallPositions, posIndex, i, topPositions, bottomPositions) {
wallPositions[posIndex++] = topPositions[i];
wallPositions[posIndex++] = topPositions[i + 1];
wallPositions[posIndex++] = topPositions[i + 2];
wallPositions[posIndex++] = bottomPositions[i];
wallPositions[posIndex++] = bottomPositions[i + 1];
wallPositions[posIndex] = bottomPositions[i + 2];
return wallPositions;
}
function addWallTextureCoordinates(wallTextures, stIndex, i, st) {
wallTextures[stIndex++] = st[i];
wallTextures[stIndex++] = st[i + 1];
wallTextures[stIndex++] = st[i];
wallTextures[stIndex] = st[i + 1];
return wallTextures;
}
var scratchVertexFormat10 = new VertexFormat_default();
function constructExtrudedRectangle2(rectangleGeometry, computedOptions) {
const shadowVolume = rectangleGeometry._shadowVolume;
const offsetAttributeValue = rectangleGeometry._offsetAttribute;
const vertexFormat = rectangleGeometry._vertexFormat;
const minHeight = rectangleGeometry._extrudedHeight;
const maxHeight = rectangleGeometry._surfaceHeight;
const ellipsoid = rectangleGeometry._ellipsoid;
const height = computedOptions.height;
const width = computedOptions.width;
let i;
if (shadowVolume) {
const newVertexFormat = VertexFormat_default.clone(
vertexFormat,
scratchVertexFormat10
);
newVertexFormat.normal = true;
rectangleGeometry._vertexFormat = newVertexFormat;
}
const topBottomGeo = constructRectangle2(rectangleGeometry, computedOptions);
if (shadowVolume) {
rectangleGeometry._vertexFormat = vertexFormat;
}
let topPositions = PolygonPipeline_default.scaleToGeodeticHeight(
topBottomGeo.attributes.position.values,
maxHeight,
ellipsoid,
false
);
topPositions = new Float64Array(topPositions);
let length2 = topPositions.length;
const newLength = length2 * 2;
const positions = new Float64Array(newLength);
positions.set(topPositions);
const bottomPositions = PolygonPipeline_default.scaleToGeodeticHeight(
topBottomGeo.attributes.position.values,
minHeight,
ellipsoid
);
positions.set(bottomPositions, length2);
topBottomGeo.attributes.position.values = positions;
const normals = vertexFormat.normal ? new Float32Array(newLength) : void 0;
const tangents = vertexFormat.tangent ? new Float32Array(newLength) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(newLength) : void 0;
const textures = vertexFormat.st ? new Float32Array(newLength / 3 * 2) : void 0;
let topSt;
let topNormals;
if (vertexFormat.normal) {
topNormals = topBottomGeo.attributes.normal.values;
normals.set(topNormals);
for (i = 0; i < length2; i++) {
topNormals[i] = -topNormals[i];
}
normals.set(topNormals, length2);
topBottomGeo.attributes.normal.values = normals;
}
if (shadowVolume) {
topNormals = topBottomGeo.attributes.normal.values;
if (!vertexFormat.normal) {
topBottomGeo.attributes.normal = void 0;
}
const extrudeNormals = new Float32Array(newLength);
for (i = 0; i < length2; i++) {
topNormals[i] = -topNormals[i];
}
extrudeNormals.set(topNormals, length2);
topBottomGeo.attributes.extrudeDirection = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: extrudeNormals
});
}
let offsetValue;
const hasOffsets = defined_default(offsetAttributeValue);
if (hasOffsets) {
const size = length2 / 3 * 2;
let offsetAttribute = new Uint8Array(size);
if (offsetAttributeValue === GeometryOffsetAttribute_default.TOP) {
offsetAttribute = offsetAttribute.fill(1, 0, size / 2);
} else {
offsetValue = offsetAttributeValue === GeometryOffsetAttribute_default.NONE ? 0 : 1;
offsetAttribute = offsetAttribute.fill(offsetValue);
}
topBottomGeo.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: offsetAttribute
});
}
if (vertexFormat.tangent) {
const topTangents = topBottomGeo.attributes.tangent.values;
tangents.set(topTangents);
for (i = 0; i < length2; i++) {
topTangents[i] = -topTangents[i];
}
tangents.set(topTangents, length2);
topBottomGeo.attributes.tangent.values = tangents;
}
if (vertexFormat.bitangent) {
const topBitangents = topBottomGeo.attributes.bitangent.values;
bitangents.set(topBitangents);
bitangents.set(topBitangents, length2);
topBottomGeo.attributes.bitangent.values = bitangents;
}
if (vertexFormat.st) {
topSt = topBottomGeo.attributes.st.values;
textures.set(topSt);
textures.set(topSt, length2 / 3 * 2);
topBottomGeo.attributes.st.values = textures;
}
const indices = topBottomGeo.indices;
const indicesLength = indices.length;
const posLength = length2 / 3;
const newIndices = IndexDatatype_default.createTypedArray(
newLength / 3,
indicesLength * 2
);
newIndices.set(indices);
for (i = 0; i < indicesLength; i += 3) {
newIndices[i + indicesLength] = indices[i + 2] + posLength;
newIndices[i + 1 + indicesLength] = indices[i + 1] + posLength;
newIndices[i + 2 + indicesLength] = indices[i] + posLength;
}
topBottomGeo.indices = newIndices;
const northCap = computedOptions.northCap;
const southCap = computedOptions.southCap;
let rowHeight = height;
let widthMultiplier = 2;
let perimeterPositions = 0;
let corners2 = 4;
let dupliateCorners = 4;
if (northCap) {
widthMultiplier -= 1;
rowHeight -= 1;
perimeterPositions += 1;
corners2 -= 2;
dupliateCorners -= 1;
}
if (southCap) {
widthMultiplier -= 1;
rowHeight -= 1;
perimeterPositions += 1;
corners2 -= 2;
dupliateCorners -= 1;
}
perimeterPositions += widthMultiplier * width + 2 * rowHeight - corners2;
const wallCount = (perimeterPositions + dupliateCorners) * 2;
let wallPositions = new Float64Array(wallCount * 3);
const wallExtrudeNormals = shadowVolume ? new Float32Array(wallCount * 3) : void 0;
let wallOffsetAttribute = hasOffsets ? new Uint8Array(wallCount) : void 0;
let wallTextures = vertexFormat.st ? new Float32Array(wallCount * 2) : void 0;
const computeTopOffsets = offsetAttributeValue === GeometryOffsetAttribute_default.TOP;
if (hasOffsets && !computeTopOffsets) {
offsetValue = offsetAttributeValue === GeometryOffsetAttribute_default.ALL ? 1 : 0;
wallOffsetAttribute = wallOffsetAttribute.fill(offsetValue);
}
let posIndex = 0;
let stIndex = 0;
let extrudeNormalIndex = 0;
let wallOffsetIndex = 0;
const area2 = width * rowHeight;
let threeI;
for (i = 0; i < area2; i += width) {
threeI = i * 3;
wallPositions = addWallPositions2(
wallPositions,
posIndex,
threeI,
topPositions,
bottomPositions
);
posIndex += 6;
if (vertexFormat.st) {
wallTextures = addWallTextureCoordinates(
wallTextures,
stIndex,
i * 2,
topSt
);
stIndex += 4;
}
if (shadowVolume) {
extrudeNormalIndex += 3;
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];
}
if (computeTopOffsets) {
wallOffsetAttribute[wallOffsetIndex++] = 1;
wallOffsetIndex += 1;
}
}
if (!southCap) {
for (i = area2 - width; i < area2; i++) {
threeI = i * 3;
wallPositions = addWallPositions2(
wallPositions,
posIndex,
threeI,
topPositions,
bottomPositions
);
posIndex += 6;
if (vertexFormat.st) {
wallTextures = addWallTextureCoordinates(
wallTextures,
stIndex,
i * 2,
topSt
);
stIndex += 4;
}
if (shadowVolume) {
extrudeNormalIndex += 3;
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];
}
if (computeTopOffsets) {
wallOffsetAttribute[wallOffsetIndex++] = 1;
wallOffsetIndex += 1;
}
}
} else {
const southIndex = northCap ? area2 + 1 : area2;
threeI = southIndex * 3;
for (i = 0; i < 2; i++) {
wallPositions = addWallPositions2(
wallPositions,
posIndex,
threeI,
topPositions,
bottomPositions
);
posIndex += 6;
if (vertexFormat.st) {
wallTextures = addWallTextureCoordinates(
wallTextures,
stIndex,
southIndex * 2,
topSt
);
stIndex += 4;
}
if (shadowVolume) {
extrudeNormalIndex += 3;
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];
}
if (computeTopOffsets) {
wallOffsetAttribute[wallOffsetIndex++] = 1;
wallOffsetIndex += 1;
}
}
}
for (i = area2 - 1; i > 0; i -= width) {
threeI = i * 3;
wallPositions = addWallPositions2(
wallPositions,
posIndex,
threeI,
topPositions,
bottomPositions
);
posIndex += 6;
if (vertexFormat.st) {
wallTextures = addWallTextureCoordinates(
wallTextures,
stIndex,
i * 2,
topSt
);
stIndex += 4;
}
if (shadowVolume) {
extrudeNormalIndex += 3;
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];
}
if (computeTopOffsets) {
wallOffsetAttribute[wallOffsetIndex++] = 1;
wallOffsetIndex += 1;
}
}
if (!northCap) {
for (i = width - 1; i >= 0; i--) {
threeI = i * 3;
wallPositions = addWallPositions2(
wallPositions,
posIndex,
threeI,
topPositions,
bottomPositions
);
posIndex += 6;
if (vertexFormat.st) {
wallTextures = addWallTextureCoordinates(
wallTextures,
stIndex,
i * 2,
topSt
);
stIndex += 4;
}
if (shadowVolume) {
extrudeNormalIndex += 3;
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];
}
if (computeTopOffsets) {
wallOffsetAttribute[wallOffsetIndex++] = 1;
wallOffsetIndex += 1;
}
}
} else {
const northIndex = area2;
threeI = northIndex * 3;
for (i = 0; i < 2; i++) {
wallPositions = addWallPositions2(
wallPositions,
posIndex,
threeI,
topPositions,
bottomPositions
);
posIndex += 6;
if (vertexFormat.st) {
wallTextures = addWallTextureCoordinates(
wallTextures,
stIndex,
northIndex * 2,
topSt
);
stIndex += 4;
}
if (shadowVolume) {
extrudeNormalIndex += 3;
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];
wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];
}
if (computeTopOffsets) {
wallOffsetAttribute[wallOffsetIndex++] = 1;
wallOffsetIndex += 1;
}
}
}
let geo = calculateAttributesWall(wallPositions, vertexFormat, ellipsoid);
if (vertexFormat.st) {
geo.attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: wallTextures
});
}
if (shadowVolume) {
geo.attributes.extrudeDirection = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: wallExtrudeNormals
});
}
if (hasOffsets) {
geo.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: wallOffsetAttribute
});
}
const wallIndices = IndexDatatype_default.createTypedArray(
wallCount,
perimeterPositions * 6
);
let upperLeft;
let lowerLeft;
let lowerRight;
let upperRight;
length2 = wallPositions.length / 3;
let index = 0;
for (i = 0; i < length2 - 1; i += 2) {
upperLeft = i;
upperRight = (upperLeft + 2) % length2;
const p1 = Cartesian3_default.fromArray(wallPositions, upperLeft * 3, v1Scratch);
const p2 = Cartesian3_default.fromArray(wallPositions, upperRight * 3, v2Scratch);
if (Cartesian3_default.equalsEpsilon(p1, p2, Math_default.EPSILON10)) {
continue;
}
lowerLeft = (upperLeft + 1) % length2;
lowerRight = (lowerLeft + 2) % length2;
wallIndices[index++] = upperLeft;
wallIndices[index++] = lowerLeft;
wallIndices[index++] = upperRight;
wallIndices[index++] = upperRight;
wallIndices[index++] = lowerLeft;
wallIndices[index++] = lowerRight;
}
geo.indices = wallIndices;
geo = GeometryPipeline_default.combineInstances([
new GeometryInstance_default({
geometry: topBottomGeo
}),
new GeometryInstance_default({
geometry: geo
})
]);
return geo[0];
}
var scratchRectanglePoints = [
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default()
];
var nwScratch2 = new Cartographic_default();
var stNwScratch = new Cartographic_default();
function computeRectangle3(rectangle, granularity, rotation, ellipsoid, result) {
if (rotation === 0) {
return Rectangle_default.clone(rectangle, result);
}
const computedOptions = RectangleGeometryLibrary_default.computeOptions(
rectangle,
granularity,
rotation,
0,
rectangleScratch4,
nwScratch2
);
const height = computedOptions.height;
const width = computedOptions.width;
const positions = scratchRectanglePoints;
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
false,
0,
0,
positions[0]
);
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
false,
0,
width - 1,
positions[1]
);
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
false,
height - 1,
0,
positions[2]
);
RectangleGeometryLibrary_default.computePosition(
computedOptions,
ellipsoid,
false,
height - 1,
width - 1,
positions[3]
);
return Rectangle_default.fromCartesianArray(positions, ellipsoid, result);
}
function RectangleGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const rectangle = options.rectangle;
Check_default.typeOf.object("rectangle", rectangle);
Rectangle_default._validate(rectangle);
if (rectangle.north < rectangle.south) {
throw new DeveloperError_default(
"options.rectangle.north must be greater than or equal to options.rectangle.south"
);
}
const height = options.height ?? 0;
const extrudedHeight = options.extrudedHeight ?? height;
this._rectangle = Rectangle_default.clone(rectangle);
this._granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
this._ellipsoid = Ellipsoid_default.clone(options.ellipsoid ?? Ellipsoid_default.default);
this._surfaceHeight = Math.max(height, extrudedHeight);
this._rotation = options.rotation ?? 0;
this._stRotation = options.stRotation ?? 0;
this._vertexFormat = VertexFormat_default.clone(
options.vertexFormat ?? VertexFormat_default.DEFAULT
);
this._extrudedHeight = Math.min(height, extrudedHeight);
this._shadowVolume = options.shadowVolume ?? false;
this._workerName = "createRectangleGeometry";
this._offsetAttribute = options.offsetAttribute;
this._rotatedRectangle = void 0;
this._textureCoordinateRotationPoints = void 0;
}
RectangleGeometry.packedLength = Rectangle_default.packedLength + Ellipsoid_default.packedLength + VertexFormat_default.packedLength + 7;
RectangleGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
Rectangle_default.pack(value._rectangle, array, startingIndex);
startingIndex += Rectangle_default.packedLength;
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
startingIndex += VertexFormat_default.packedLength;
array[startingIndex++] = value._granularity;
array[startingIndex++] = value._surfaceHeight;
array[startingIndex++] = value._rotation;
array[startingIndex++] = value._stRotation;
array[startingIndex++] = value._extrudedHeight;
array[startingIndex++] = value._shadowVolume ? 1 : 0;
array[startingIndex] = value._offsetAttribute ?? -1;
return array;
};
var scratchRectangle9 = new Rectangle_default();
var scratchEllipsoid11 = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var scratchOptions18 = {
rectangle: scratchRectangle9,
ellipsoid: scratchEllipsoid11,
vertexFormat: scratchVertexFormat10,
granularity: void 0,
height: void 0,
rotation: void 0,
stRotation: void 0,
extrudedHeight: void 0,
shadowVolume: void 0,
offsetAttribute: void 0
};
RectangleGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const rectangle = Rectangle_default.unpack(array, startingIndex, scratchRectangle9);
startingIndex += Rectangle_default.packedLength;
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid11);
startingIndex += Ellipsoid_default.packedLength;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat10
);
startingIndex += VertexFormat_default.packedLength;
const granularity = array[startingIndex++];
const surfaceHeight = array[startingIndex++];
const rotation = array[startingIndex++];
const stRotation = array[startingIndex++];
const extrudedHeight = array[startingIndex++];
const shadowVolume = array[startingIndex++] === 1;
const offsetAttribute = array[startingIndex];
if (!defined_default(result)) {
scratchOptions18.granularity = granularity;
scratchOptions18.height = surfaceHeight;
scratchOptions18.rotation = rotation;
scratchOptions18.stRotation = stRotation;
scratchOptions18.extrudedHeight = extrudedHeight;
scratchOptions18.shadowVolume = shadowVolume;
scratchOptions18.offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return new RectangleGeometry(scratchOptions18);
}
result._rectangle = Rectangle_default.clone(rectangle, result._rectangle);
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._granularity = granularity;
result._surfaceHeight = surfaceHeight;
result._rotation = rotation;
result._stRotation = stRotation;
result._extrudedHeight = extrudedHeight;
result._shadowVolume = shadowVolume;
result._offsetAttribute = offsetAttribute === -1 ? void 0 : offsetAttribute;
return result;
};
RectangleGeometry.computeRectangle = function(options, result) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const rectangle = options.rectangle;
Check_default.typeOf.object("rectangle", rectangle);
Rectangle_default._validate(rectangle);
if (rectangle.north < rectangle.south) {
throw new DeveloperError_default(
"options.rectangle.north must be greater than or equal to options.rectangle.south"
);
}
const granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
const rotation = options.rotation ?? 0;
return computeRectangle3(rectangle, granularity, rotation, ellipsoid, result);
};
var tangentRotationMatrixScratch = new Matrix3_default();
var quaternionScratch4 = new Quaternion_default();
var centerScratch4 = new Cartographic_default();
RectangleGeometry.createGeometry = function(rectangleGeometry) {
if (Math_default.equalsEpsilon(
rectangleGeometry._rectangle.north,
rectangleGeometry._rectangle.south,
Math_default.EPSILON10
) || Math_default.equalsEpsilon(
rectangleGeometry._rectangle.east,
rectangleGeometry._rectangle.west,
Math_default.EPSILON10
)) {
return void 0;
}
let rectangle = rectangleGeometry._rectangle;
const ellipsoid = rectangleGeometry._ellipsoid;
const rotation = rectangleGeometry._rotation;
const stRotation = rectangleGeometry._stRotation;
const vertexFormat = rectangleGeometry._vertexFormat;
const computedOptions = RectangleGeometryLibrary_default.computeOptions(
rectangle,
rectangleGeometry._granularity,
rotation,
stRotation,
rectangleScratch4,
nwScratch2,
stNwScratch
);
const tangentRotationMatrix = tangentRotationMatrixScratch;
if (stRotation !== 0 || rotation !== 0) {
const center = Rectangle_default.center(rectangle, centerScratch4);
const axis = ellipsoid.geodeticSurfaceNormalCartographic(center, v1Scratch);
Quaternion_default.fromAxisAngle(axis, -stRotation, quaternionScratch4);
Matrix3_default.fromQuaternion(quaternionScratch4, tangentRotationMatrix);
} else {
Matrix3_default.clone(Matrix3_default.IDENTITY, tangentRotationMatrix);
}
const surfaceHeight = rectangleGeometry._surfaceHeight;
const extrudedHeight = rectangleGeometry._extrudedHeight;
const extrude = !Math_default.equalsEpsilon(
surfaceHeight,
extrudedHeight,
0,
Math_default.EPSILON2
);
computedOptions.lonScalar = 1 / rectangleGeometry._rectangle.width;
computedOptions.latScalar = 1 / rectangleGeometry._rectangle.height;
computedOptions.tangentRotationMatrix = tangentRotationMatrix;
let geometry;
let boundingSphere;
rectangle = rectangleGeometry._rectangle;
if (extrude) {
geometry = constructExtrudedRectangle2(rectangleGeometry, computedOptions);
const topBS = BoundingSphere_default.fromRectangle3D(
rectangle,
ellipsoid,
surfaceHeight,
topBoundingSphere4
);
const bottomBS = BoundingSphere_default.fromRectangle3D(
rectangle,
ellipsoid,
extrudedHeight,
bottomBoundingSphere4
);
boundingSphere = BoundingSphere_default.union(topBS, bottomBS);
} else {
geometry = constructRectangle2(rectangleGeometry, computedOptions);
geometry.attributes.position.values = PolygonPipeline_default.scaleToGeodeticHeight(
geometry.attributes.position.values,
surfaceHeight,
ellipsoid,
false
);
if (defined_default(rectangleGeometry._offsetAttribute)) {
const length2 = geometry.attributes.position.values.length;
const offsetValue = rectangleGeometry._offsetAttribute === GeometryOffsetAttribute_default.NONE ? 0 : 1;
const applyOffset = new Uint8Array(length2 / 3).fill(offsetValue);
geometry.attributes.applyOffset = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 1,
values: applyOffset
});
}
boundingSphere = BoundingSphere_default.fromRectangle3D(
rectangle,
ellipsoid,
surfaceHeight
);
}
if (!vertexFormat.position) {
delete geometry.attributes.position;
}
return new Geometry_default({
attributes: geometry.attributes,
indices: geometry.indices,
primitiveType: geometry.primitiveType,
boundingSphere,
offsetAttribute: rectangleGeometry._offsetAttribute
});
};
RectangleGeometry.createShadowVolume = function(rectangleGeometry, minHeightFunc, maxHeightFunc) {
const granularity = rectangleGeometry._granularity;
const ellipsoid = rectangleGeometry._ellipsoid;
const minHeight = minHeightFunc(granularity, ellipsoid);
const maxHeight = maxHeightFunc(granularity, ellipsoid);
return new RectangleGeometry({
rectangle: rectangleGeometry._rectangle,
rotation: rectangleGeometry._rotation,
ellipsoid,
stRotation: rectangleGeometry._stRotation,
granularity,
extrudedHeight: maxHeight,
height: minHeight,
vertexFormat: VertexFormat_default.POSITION_ONLY,
shadowVolume: true
});
};
var unrotatedTextureRectangleScratch = new Rectangle_default();
var points2DScratch3 = [new Cartesian2_default(), new Cartesian2_default(), new Cartesian2_default()];
var rotation2DScratch2 = new Matrix2_default();
var rectangleCenterScratch3 = new Cartographic_default();
function textureCoordinateRotationPoints3(rectangleGeometry) {
if (rectangleGeometry._stRotation === 0) {
return [0, 0, 0, 1, 1, 0];
}
const rectangle = Rectangle_default.clone(
rectangleGeometry._rectangle,
unrotatedTextureRectangleScratch
);
const granularity = rectangleGeometry._granularity;
const ellipsoid = rectangleGeometry._ellipsoid;
const rotation = rectangleGeometry._rotation - rectangleGeometry._stRotation;
const unrotatedTextureRectangle = computeRectangle3(
rectangle,
granularity,
rotation,
ellipsoid,
unrotatedTextureRectangleScratch
);
const points2D = points2DScratch3;
points2D[0].x = unrotatedTextureRectangle.west;
points2D[0].y = unrotatedTextureRectangle.south;
points2D[1].x = unrotatedTextureRectangle.west;
points2D[1].y = unrotatedTextureRectangle.north;
points2D[2].x = unrotatedTextureRectangle.east;
points2D[2].y = unrotatedTextureRectangle.south;
const boundingRectangle = rectangleGeometry.rectangle;
const toDesiredInComputed = Matrix2_default.fromRotation(
rectangleGeometry._stRotation,
rotation2DScratch2
);
const boundingRectangleCenter = Rectangle_default.center(
boundingRectangle,
rectangleCenterScratch3
);
for (let i = 0; i < 3; ++i) {
const point2D = points2D[i];
point2D.x -= boundingRectangleCenter.longitude;
point2D.y -= boundingRectangleCenter.latitude;
Matrix2_default.multiplyByVector(toDesiredInComputed, point2D, point2D);
point2D.x += boundingRectangleCenter.longitude;
point2D.y += boundingRectangleCenter.latitude;
point2D.x = (point2D.x - boundingRectangle.west) / boundingRectangle.width;
point2D.y = (point2D.y - boundingRectangle.south) / boundingRectangle.height;
}
const minXYCorner = points2D[0];
const maxYCorner = points2D[1];
const maxXCorner = points2D[2];
const result = new Array(6);
Cartesian2_default.pack(minXYCorner, result);
Cartesian2_default.pack(maxYCorner, result, 2);
Cartesian2_default.pack(maxXCorner, result, 4);
return result;
}
Object.defineProperties(RectangleGeometry.prototype, {
/**
* @private
*/
rectangle: {
get: function() {
if (!defined_default(this._rotatedRectangle)) {
this._rotatedRectangle = computeRectangle3(
this._rectangle,
this._granularity,
this._rotation,
this._ellipsoid
);
}
return this._rotatedRectangle;
}
},
/**
* For remapping texture coordinates when rendering RectangleGeometries as GroundPrimitives.
* This version permits skew in textures by computing offsets directly in cartographic space and
* more accurately approximates rendering RectangleGeometries with height as standard Primitives.
* @see Geometry#_textureCoordinateRotationPoints
* @private
*/
textureCoordinateRotationPoints: {
get: function() {
if (!defined_default(this._textureCoordinateRotationPoints)) {
this._textureCoordinateRotationPoints = textureCoordinateRotationPoints3(this);
}
return this._textureCoordinateRotationPoints;
}
}
});
var RectangleGeometry_default = RectangleGeometry;
// packages/engine/Source/DataSources/RectangleGeometryUpdater.js
var scratchColor20 = new Color_default();
var defaultOffset8 = Cartesian3_default.ZERO;
var offsetScratch10 = new Cartesian3_default();
var scratchRectangle10 = new Rectangle_default();
var scratchCenterRect = new Rectangle_default();
var scratchCarto = new Cartographic_default();
function RectangleGeometryOptions(entity) {
this.id = entity;
this.vertexFormat = void 0;
this.rectangle = void 0;
this.height = void 0;
this.extrudedHeight = void 0;
this.granularity = void 0;
this.stRotation = void 0;
this.rotation = void 0;
this.offsetAttribute = void 0;
}
function RectangleGeometryUpdater(entity, scene) {
GroundGeometryUpdater_default.call(this, {
entity,
scene,
geometryOptions: new RectangleGeometryOptions(entity),
geometryPropertyName: "rectangle",
observedPropertyNames: ["availability", "rectangle"]
});
this._onEntityPropertyChanged(
entity,
"rectangle",
entity.rectangle,
void 0
);
}
if (defined_default(Object.create)) {
RectangleGeometryUpdater.prototype = Object.create(
GroundGeometryUpdater_default.prototype
);
RectangleGeometryUpdater.prototype.constructor = RectangleGeometryUpdater;
}
RectangleGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._fillEnabled) {
throw new DeveloperError_default(
"This instance does not represent a filled geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const attributes = {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)
),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
this._distanceDisplayConditionProperty.getValue(time)
),
offset: void 0,
color: void 0
};
if (this._materialProperty instanceof ColorMaterialProperty_default) {
let currentColor;
if (defined_default(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
currentColor = this._materialProperty.color.getValue(time, scratchColor20);
}
if (!defined_default(currentColor)) {
currentColor = Color_default.WHITE;
}
attributes.color = ColorGeometryInstanceAttribute_default.fromColor(currentColor);
}
if (defined_default(this._options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset8,
offsetScratch10
)
);
}
return new GeometryInstance_default({
id: entity,
geometry: new RectangleGeometry_default(this._options),
attributes
});
};
RectangleGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._outlineEnabled) {
throw new DeveloperError_default(
"This instance does not represent an outlined geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const outlineColor = Property_default.getValueOrDefault(
this._outlineColorProperty,
time,
Color_default.BLACK,
scratchColor20
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const attributes = {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)
),
color: ColorGeometryInstanceAttribute_default.fromColor(outlineColor),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
),
offset: void 0
};
if (defined_default(this._options.offsetAttribute)) {
attributes.offset = OffsetGeometryInstanceAttribute_default.fromCartesian3(
Property_default.getValueOrDefault(
this._terrainOffsetProperty,
time,
defaultOffset8,
offsetScratch10
)
);
}
return new GeometryInstance_default({
id: entity,
geometry: new RectangleOutlineGeometry_default(this._options),
attributes
});
};
RectangleGeometryUpdater.prototype._computeCenter = function(time, result) {
const rect = Property_default.getValueOrUndefined(
this._entity.rectangle.coordinates,
time,
scratchCenterRect
);
if (!defined_default(rect)) {
return;
}
const center = Rectangle_default.center(rect, scratchCarto);
return Cartographic_default.toCartesian(center, Ellipsoid_default.default, result);
};
RectangleGeometryUpdater.prototype._isHidden = function(entity, rectangle) {
return !defined_default(rectangle.coordinates) || GeometryUpdater_default.prototype._isHidden.call(this, entity, rectangle);
};
RectangleGeometryUpdater.prototype._isDynamic = function(entity, rectangle) {
return !rectangle.coordinates.isConstant || //
!Property_default.isConstant(rectangle.height) || //
!Property_default.isConstant(rectangle.extrudedHeight) || //
!Property_default.isConstant(rectangle.granularity) || //
!Property_default.isConstant(rectangle.stRotation) || //
!Property_default.isConstant(rectangle.rotation) || //
!Property_default.isConstant(rectangle.outlineWidth) || //
!Property_default.isConstant(rectangle.zIndex) || //
this._onTerrain && !Property_default.isConstant(this._materialProperty) && !(this._materialProperty instanceof ColorMaterialProperty_default);
};
RectangleGeometryUpdater.prototype._setStaticOptions = function(entity, rectangle) {
const isColorMaterial = this._materialProperty instanceof ColorMaterialProperty_default;
let heightValue = Property_default.getValueOrUndefined(
rectangle.height,
Iso8601_default.MINIMUM_VALUE
);
const heightReferenceValue = Property_default.getValueOrDefault(
rectangle.heightReference,
Iso8601_default.MINIMUM_VALUE,
HeightReference_default.NONE
);
let extrudedHeightValue = Property_default.getValueOrUndefined(
rectangle.extrudedHeight,
Iso8601_default.MINIMUM_VALUE
);
const extrudedHeightReferenceValue = Property_default.getValueOrDefault(
rectangle.extrudedHeightReference,
Iso8601_default.MINIMUM_VALUE,
HeightReference_default.NONE
);
if (defined_default(extrudedHeightValue) && !defined_default(heightValue)) {
heightValue = 0;
}
const options = this._options;
options.vertexFormat = isColorMaterial ? PerInstanceColorAppearance_default.VERTEX_FORMAT : MaterialAppearance_default.MaterialSupport.TEXTURED.vertexFormat;
options.rectangle = rectangle.coordinates.getValue(
Iso8601_default.MINIMUM_VALUE,
options.rectangle
);
options.granularity = Property_default.getValueOrUndefined(
rectangle.granularity,
Iso8601_default.MINIMUM_VALUE
);
options.stRotation = Property_default.getValueOrUndefined(
rectangle.stRotation,
Iso8601_default.MINIMUM_VALUE
);
options.rotation = Property_default.getValueOrUndefined(
rectangle.rotation,
Iso8601_default.MINIMUM_VALUE
);
options.offsetAttribute = GroundGeometryUpdater_default.computeGeometryOffsetAttribute(
heightValue,
heightReferenceValue,
extrudedHeightValue,
extrudedHeightReferenceValue
);
options.height = GroundGeometryUpdater_default.getGeometryHeight(
heightValue,
heightReferenceValue
);
extrudedHeightValue = GroundGeometryUpdater_default.getGeometryExtrudedHeight(
extrudedHeightValue,
extrudedHeightReferenceValue
);
if (extrudedHeightValue === GroundGeometryUpdater_default.CLAMP_TO_GROUND) {
extrudedHeightValue = ApproximateTerrainHeights_default.getMinimumMaximumHeights(
RectangleGeometry_default.computeRectangle(options, scratchRectangle10)
).minimumTerrainHeight;
}
options.extrudedHeight = extrudedHeightValue;
};
RectangleGeometryUpdater.DynamicGeometryUpdater = DynamicRectangleGeometryUpdater;
function DynamicRectangleGeometryUpdater(geometryUpdater, primitives, groundPrimitives) {
DynamicGeometryUpdater_default.call(
this,
geometryUpdater,
primitives,
groundPrimitives
);
}
if (defined_default(Object.create)) {
DynamicRectangleGeometryUpdater.prototype = Object.create(
DynamicGeometryUpdater_default.prototype
);
DynamicRectangleGeometryUpdater.prototype.constructor = DynamicRectangleGeometryUpdater;
}
DynamicRectangleGeometryUpdater.prototype._isHidden = function(entity, rectangle, time) {
return !defined_default(this._options.rectangle) || DynamicGeometryUpdater_default.prototype._isHidden.call(
this,
entity,
rectangle,
time
);
};
DynamicRectangleGeometryUpdater.prototype._setOptions = function(entity, rectangle, time) {
const options = this._options;
let heightValue = Property_default.getValueOrUndefined(rectangle.height, time);
const heightReferenceValue = Property_default.getValueOrDefault(
rectangle.heightReference,
time,
HeightReference_default.NONE
);
let extrudedHeightValue = Property_default.getValueOrUndefined(
rectangle.extrudedHeight,
time
);
const extrudedHeightReferenceValue = Property_default.getValueOrDefault(
rectangle.extrudedHeightReference,
time,
HeightReference_default.NONE
);
if (defined_default(extrudedHeightValue) && !defined_default(heightValue)) {
heightValue = 0;
}
options.rectangle = Property_default.getValueOrUndefined(
rectangle.coordinates,
time,
options.rectangle
);
options.granularity = Property_default.getValueOrUndefined(
rectangle.granularity,
time
);
options.stRotation = Property_default.getValueOrUndefined(rectangle.stRotation, time);
options.rotation = Property_default.getValueOrUndefined(rectangle.rotation, time);
options.offsetAttribute = GroundGeometryUpdater_default.computeGeometryOffsetAttribute(
heightValue,
heightReferenceValue,
extrudedHeightValue,
extrudedHeightReferenceValue
);
options.height = GroundGeometryUpdater_default.getGeometryHeight(
heightValue,
heightReferenceValue
);
extrudedHeightValue = GroundGeometryUpdater_default.getGeometryExtrudedHeight(
extrudedHeightValue,
extrudedHeightReferenceValue
);
if (extrudedHeightValue === GroundGeometryUpdater_default.CLAMP_TO_GROUND) {
extrudedHeightValue = ApproximateTerrainHeights_default.getMinimumMaximumHeights(
RectangleGeometry_default.computeRectangle(options, scratchRectangle10)
).minimumTerrainHeight;
}
options.extrudedHeight = extrudedHeightValue;
};
var RectangleGeometryUpdater_default = RectangleGeometryUpdater;
// packages/engine/Source/DataSources/WallGeometryUpdater.js
var import_InlineWorkers898 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/WallGeometry.js
var import_InlineWorkers896 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/WallGeometryLibrary.js
var import_InlineWorkers895 = __toESM(require_InlineWorkers(), 1);
var WallGeometryLibrary = {};
function latLonEquals(c0, c14) {
return Math_default.equalsEpsilon(c0.latitude, c14.latitude, Math_default.EPSILON10) && Math_default.equalsEpsilon(c0.longitude, c14.longitude, Math_default.EPSILON10);
}
var scratchCartographic14 = new Cartographic_default();
var scratchCartographic23 = new Cartographic_default();
function removeDuplicates(ellipsoid, positions, topHeights, bottomHeights) {
positions = arrayRemoveDuplicates_default(positions, Cartesian3_default.equalsEpsilon);
const length2 = positions.length;
if (length2 < 2) {
return;
}
const hasBottomHeights = defined_default(bottomHeights);
const hasTopHeights = defined_default(topHeights);
const cleanedPositions = new Array(length2);
const cleanedTopHeights = new Array(length2);
const cleanedBottomHeights = new Array(length2);
const v02 = positions[0];
cleanedPositions[0] = v02;
const c0 = ellipsoid.cartesianToCartographic(v02, scratchCartographic14);
if (hasTopHeights) {
c0.height = topHeights[0];
}
cleanedTopHeights[0] = c0.height;
if (hasBottomHeights) {
cleanedBottomHeights[0] = bottomHeights[0];
} else {
cleanedBottomHeights[0] = 0;
}
const startTopHeight = cleanedTopHeights[0];
const startBottomHeight = cleanedBottomHeights[0];
let hasAllSameHeights = startTopHeight === startBottomHeight;
let index = 1;
for (let i = 1; i < length2; ++i) {
const v12 = positions[i];
const c14 = ellipsoid.cartesianToCartographic(v12, scratchCartographic23);
if (hasTopHeights) {
c14.height = topHeights[i];
}
hasAllSameHeights = hasAllSameHeights && c14.height === 0;
if (!latLonEquals(c0, c14)) {
cleanedPositions[index] = v12;
cleanedTopHeights[index] = c14.height;
if (hasBottomHeights) {
cleanedBottomHeights[index] = bottomHeights[i];
} else {
cleanedBottomHeights[index] = 0;
}
hasAllSameHeights = hasAllSameHeights && cleanedTopHeights[index] === cleanedBottomHeights[index];
Cartographic_default.clone(c14, c0);
++index;
} else if (c0.height < c14.height) {
cleanedTopHeights[index - 1] = c14.height;
}
}
if (hasAllSameHeights || index < 2) {
return;
}
cleanedPositions.length = index;
cleanedTopHeights.length = index;
cleanedBottomHeights.length = index;
return {
positions: cleanedPositions,
topHeights: cleanedTopHeights,
bottomHeights: cleanedBottomHeights
};
}
var positionsArrayScratch = new Array(2);
var heightsArrayScratch = new Array(2);
var generateArcOptionsScratch = {
positions: void 0,
height: void 0,
granularity: void 0,
ellipsoid: void 0
};
WallGeometryLibrary.computePositions = function(ellipsoid, wallPositions, maximumHeights, minimumHeights, granularity, duplicateCorners) {
const o = removeDuplicates(
ellipsoid,
wallPositions,
maximumHeights,
minimumHeights
);
if (!defined_default(o)) {
return;
}
wallPositions = o.positions;
maximumHeights = o.topHeights;
minimumHeights = o.bottomHeights;
const length2 = wallPositions.length;
const numCorners = length2 - 2;
let topPositions;
let bottomPositions;
const minDistance = Math_default.chordLength(
granularity,
ellipsoid.maximumRadius
);
const generateArcOptions = generateArcOptionsScratch;
generateArcOptions.minDistance = minDistance;
generateArcOptions.ellipsoid = ellipsoid;
if (duplicateCorners) {
let count = 0;
let i;
for (i = 0; i < length2 - 1; i++) {
count += PolylinePipeline_default.numberOfPoints(
wallPositions[i],
wallPositions[i + 1],
minDistance
) + 1;
}
topPositions = new Float64Array(count * 3);
bottomPositions = new Float64Array(count * 3);
const generateArcPositions = positionsArrayScratch;
const generateArcHeights = heightsArrayScratch;
generateArcOptions.positions = generateArcPositions;
generateArcOptions.height = generateArcHeights;
let offset = 0;
for (i = 0; i < length2 - 1; i++) {
generateArcPositions[0] = wallPositions[i];
generateArcPositions[1] = wallPositions[i + 1];
generateArcHeights[0] = maximumHeights[i];
generateArcHeights[1] = maximumHeights[i + 1];
const pos = PolylinePipeline_default.generateArc(generateArcOptions);
topPositions.set(pos, offset);
generateArcHeights[0] = minimumHeights[i];
generateArcHeights[1] = minimumHeights[i + 1];
bottomPositions.set(
PolylinePipeline_default.generateArc(generateArcOptions),
offset
);
offset += pos.length;
}
} else {
generateArcOptions.positions = wallPositions;
generateArcOptions.height = maximumHeights;
topPositions = new Float64Array(
PolylinePipeline_default.generateArc(generateArcOptions)
);
generateArcOptions.height = minimumHeights;
bottomPositions = new Float64Array(
PolylinePipeline_default.generateArc(generateArcOptions)
);
}
return {
bottomPositions,
topPositions,
numCorners
};
};
var WallGeometryLibrary_default = WallGeometryLibrary;
// packages/engine/Source/Core/WallGeometry.js
var scratchCartesian3Position1 = new Cartesian3_default();
var scratchCartesian3Position2 = new Cartesian3_default();
var scratchCartesian3Position4 = new Cartesian3_default();
var scratchCartesian3Position5 = new Cartesian3_default();
var scratchBitangent5 = new Cartesian3_default();
var scratchTangent5 = new Cartesian3_default();
var scratchNormal7 = new Cartesian3_default();
function WallGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const wallPositions = options.positions;
const maximumHeights = options.maximumHeights;
const minimumHeights = options.minimumHeights;
if (!defined_default(wallPositions)) {
throw new DeveloperError_default("options.positions is required.");
}
if (defined_default(maximumHeights) && maximumHeights.length !== wallPositions.length) {
throw new DeveloperError_default(
"options.positions and options.maximumHeights must have the same length."
);
}
if (defined_default(minimumHeights) && minimumHeights.length !== wallPositions.length) {
throw new DeveloperError_default(
"options.positions and options.minimumHeights must have the same length."
);
}
const vertexFormat = options.vertexFormat ?? VertexFormat_default.DEFAULT;
const granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
this._positions = wallPositions;
this._minimumHeights = minimumHeights;
this._maximumHeights = maximumHeights;
this._vertexFormat = VertexFormat_default.clone(vertexFormat);
this._granularity = granularity;
this._ellipsoid = Ellipsoid_default.clone(ellipsoid);
this._workerName = "createWallGeometry";
let numComponents = 1 + wallPositions.length * Cartesian3_default.packedLength + 2;
if (defined_default(minimumHeights)) {
numComponents += minimumHeights.length;
}
if (defined_default(maximumHeights)) {
numComponents += maximumHeights.length;
}
this.packedLength = numComponents + Ellipsoid_default.packedLength + VertexFormat_default.packedLength + 1;
}
WallGeometry.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
const positions = value._positions;
let length2 = positions.length;
array[startingIndex++] = length2;
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
Cartesian3_default.pack(positions[i], array, startingIndex);
}
const minimumHeights = value._minimumHeights;
length2 = defined_default(minimumHeights) ? minimumHeights.length : 0;
array[startingIndex++] = length2;
if (defined_default(minimumHeights)) {
for (i = 0; i < length2; ++i) {
array[startingIndex++] = minimumHeights[i];
}
}
const maximumHeights = value._maximumHeights;
length2 = defined_default(maximumHeights) ? maximumHeights.length : 0;
array[startingIndex++] = length2;
if (defined_default(maximumHeights)) {
for (i = 0; i < length2; ++i) {
array[startingIndex++] = maximumHeights[i];
}
}
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
startingIndex += VertexFormat_default.packedLength;
array[startingIndex] = value._granularity;
return array;
};
var scratchEllipsoid12 = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var scratchVertexFormat11 = new VertexFormat_default();
var scratchOptions19 = {
positions: void 0,
minimumHeights: void 0,
maximumHeights: void 0,
ellipsoid: scratchEllipsoid12,
vertexFormat: scratchVertexFormat11,
granularity: void 0
};
WallGeometry.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
let length2 = array[startingIndex++];
const positions = new Array(length2);
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
positions[i] = Cartesian3_default.unpack(array, startingIndex);
}
length2 = array[startingIndex++];
let minimumHeights;
if (length2 > 0) {
minimumHeights = new Array(length2);
for (i = 0; i < length2; ++i) {
minimumHeights[i] = array[startingIndex++];
}
}
length2 = array[startingIndex++];
let maximumHeights;
if (length2 > 0) {
maximumHeights = new Array(length2);
for (i = 0; i < length2; ++i) {
maximumHeights[i] = array[startingIndex++];
}
}
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid12);
startingIndex += Ellipsoid_default.packedLength;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat11
);
startingIndex += VertexFormat_default.packedLength;
const granularity = array[startingIndex];
if (!defined_default(result)) {
scratchOptions19.positions = positions;
scratchOptions19.minimumHeights = minimumHeights;
scratchOptions19.maximumHeights = maximumHeights;
scratchOptions19.granularity = granularity;
return new WallGeometry(scratchOptions19);
}
result._positions = positions;
result._minimumHeights = minimumHeights;
result._maximumHeights = maximumHeights;
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._granularity = granularity;
return result;
};
WallGeometry.fromConstantHeights = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const positions = options.positions;
if (!defined_default(positions)) {
throw new DeveloperError_default("options.positions is required.");
}
let minHeights;
let maxHeights;
const min3 = options.minimumHeight;
const max3 = options.maximumHeight;
const doMin = defined_default(min3);
const doMax = defined_default(max3);
if (doMin || doMax) {
const length2 = positions.length;
minHeights = doMin ? new Array(length2) : void 0;
maxHeights = doMax ? new Array(length2) : void 0;
for (let i = 0; i < length2; ++i) {
if (doMin) {
minHeights[i] = min3;
}
if (doMax) {
maxHeights[i] = max3;
}
}
}
const newOptions2 = {
positions,
maximumHeights: maxHeights,
minimumHeights: minHeights,
ellipsoid: options.ellipsoid,
vertexFormat: options.vertexFormat
};
return new WallGeometry(newOptions2);
};
WallGeometry.createGeometry = function(wallGeometry) {
const wallPositions = wallGeometry._positions;
const minimumHeights = wallGeometry._minimumHeights;
const maximumHeights = wallGeometry._maximumHeights;
const vertexFormat = wallGeometry._vertexFormat;
const granularity = wallGeometry._granularity;
const ellipsoid = wallGeometry._ellipsoid;
const pos = WallGeometryLibrary_default.computePositions(
ellipsoid,
wallPositions,
maximumHeights,
minimumHeights,
granularity,
true
);
if (!defined_default(pos)) {
return;
}
const bottomPositions = pos.bottomPositions;
const topPositions = pos.topPositions;
const numCorners = pos.numCorners;
let length2 = topPositions.length;
let size = length2 * 2;
const positions = vertexFormat.position ? new Float64Array(size) : void 0;
const normals = vertexFormat.normal ? new Float32Array(size) : void 0;
const tangents = vertexFormat.tangent ? new Float32Array(size) : void 0;
const bitangents = vertexFormat.bitangent ? new Float32Array(size) : void 0;
const textureCoordinates = vertexFormat.st ? new Float32Array(size / 3 * 2) : void 0;
let positionIndex = 0;
let normalIndex = 0;
let bitangentIndex = 0;
let tangentIndex = 0;
let stIndex = 0;
let normal2 = scratchNormal7;
let tangent = scratchTangent5;
let bitangent = scratchBitangent5;
let recomputeNormal = true;
length2 /= 3;
let i;
let s = 0;
const ds = 1 / (length2 - numCorners - 1);
for (i = 0; i < length2; ++i) {
const i3 = i * 3;
const topPosition = Cartesian3_default.fromArray(
topPositions,
i3,
scratchCartesian3Position1
);
const bottomPosition = Cartesian3_default.fromArray(
bottomPositions,
i3,
scratchCartesian3Position2
);
if (vertexFormat.position) {
positions[positionIndex++] = bottomPosition.x;
positions[positionIndex++] = bottomPosition.y;
positions[positionIndex++] = bottomPosition.z;
positions[positionIndex++] = topPosition.x;
positions[positionIndex++] = topPosition.y;
positions[positionIndex++] = topPosition.z;
}
if (vertexFormat.st) {
textureCoordinates[stIndex++] = s;
textureCoordinates[stIndex++] = 0;
textureCoordinates[stIndex++] = s;
textureCoordinates[stIndex++] = 1;
}
if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {
let nextTop = Cartesian3_default.clone(
Cartesian3_default.ZERO,
scratchCartesian3Position5
);
const groundPosition = Cartesian3_default.subtract(
topPosition,
ellipsoid.geodeticSurfaceNormal(
topPosition,
scratchCartesian3Position2
),
scratchCartesian3Position2
);
if (i + 1 < length2) {
nextTop = Cartesian3_default.fromArray(
topPositions,
i3 + 3,
scratchCartesian3Position5
);
}
if (recomputeNormal) {
const scalednextPosition = Cartesian3_default.subtract(
nextTop,
topPosition,
scratchCartesian3Position4
);
const scaledGroundPosition = Cartesian3_default.subtract(
groundPosition,
topPosition,
scratchCartesian3Position1
);
normal2 = Cartesian3_default.normalize(
Cartesian3_default.cross(scaledGroundPosition, scalednextPosition, normal2),
normal2
);
recomputeNormal = false;
}
if (Cartesian3_default.equalsEpsilon(topPosition, nextTop, Math_default.EPSILON10)) {
recomputeNormal = true;
} else {
s += ds;
if (vertexFormat.tangent) {
tangent = Cartesian3_default.normalize(
Cartesian3_default.subtract(nextTop, topPosition, tangent),
tangent
);
}
if (vertexFormat.bitangent) {
bitangent = Cartesian3_default.normalize(
Cartesian3_default.cross(normal2, tangent, bitangent),
bitangent
);
}
}
if (vertexFormat.normal) {
normals[normalIndex++] = normal2.x;
normals[normalIndex++] = normal2.y;
normals[normalIndex++] = normal2.z;
normals[normalIndex++] = normal2.x;
normals[normalIndex++] = normal2.y;
normals[normalIndex++] = normal2.z;
}
if (vertexFormat.tangent) {
tangents[tangentIndex++] = tangent.x;
tangents[tangentIndex++] = tangent.y;
tangents[tangentIndex++] = tangent.z;
tangents[tangentIndex++] = tangent.x;
tangents[tangentIndex++] = tangent.y;
tangents[tangentIndex++] = tangent.z;
}
if (vertexFormat.bitangent) {
bitangents[bitangentIndex++] = bitangent.x;
bitangents[bitangentIndex++] = bitangent.y;
bitangents[bitangentIndex++] = bitangent.z;
bitangents[bitangentIndex++] = bitangent.x;
bitangents[bitangentIndex++] = bitangent.y;
bitangents[bitangentIndex++] = bitangent.z;
}
}
}
const attributes = new GeometryAttributes_default();
if (vertexFormat.position) {
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
});
}
if (vertexFormat.normal) {
attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: normals
});
}
if (vertexFormat.tangent) {
attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: tangents
});
}
if (vertexFormat.bitangent) {
attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: bitangents
});
}
if (vertexFormat.st) {
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: textureCoordinates
});
}
const numVertices = size / 3;
size -= 6 * (numCorners + 1);
const indices = IndexDatatype_default.createTypedArray(numVertices, size);
let edgeIndex = 0;
for (i = 0; i < numVertices - 2; i += 2) {
const LL = i;
const LR = i + 2;
const pl = Cartesian3_default.fromArray(
positions,
LL * 3,
scratchCartesian3Position1
);
const pr = Cartesian3_default.fromArray(
positions,
LR * 3,
scratchCartesian3Position2
);
if (Cartesian3_default.equalsEpsilon(pl, pr, Math_default.EPSILON10)) {
continue;
}
const UL = i + 1;
const UR = i + 3;
indices[edgeIndex++] = UL;
indices[edgeIndex++] = LL;
indices[edgeIndex++] = UR;
indices[edgeIndex++] = UR;
indices[edgeIndex++] = LL;
indices[edgeIndex++] = LR;
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.TRIANGLES,
boundingSphere: new BoundingSphere_default.fromVertices(positions)
});
};
var WallGeometry_default = WallGeometry;
// packages/engine/Source/Core/WallOutlineGeometry.js
var import_InlineWorkers897 = __toESM(require_InlineWorkers(), 1);
var scratchCartesian3Position12 = new Cartesian3_default();
var scratchCartesian3Position22 = new Cartesian3_default();
function WallOutlineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const wallPositions = options.positions;
const maximumHeights = options.maximumHeights;
const minimumHeights = options.minimumHeights;
if (!defined_default(wallPositions)) {
throw new DeveloperError_default("options.positions is required.");
}
if (defined_default(maximumHeights) && maximumHeights.length !== wallPositions.length) {
throw new DeveloperError_default(
"options.positions and options.maximumHeights must have the same length."
);
}
if (defined_default(minimumHeights) && minimumHeights.length !== wallPositions.length) {
throw new DeveloperError_default(
"options.positions and options.minimumHeights must have the same length."
);
}
const granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
this._positions = wallPositions;
this._minimumHeights = minimumHeights;
this._maximumHeights = maximumHeights;
this._granularity = granularity;
this._ellipsoid = Ellipsoid_default.clone(ellipsoid);
this._workerName = "createWallOutlineGeometry";
let numComponents = 1 + wallPositions.length * Cartesian3_default.packedLength + 2;
if (defined_default(minimumHeights)) {
numComponents += minimumHeights.length;
}
if (defined_default(maximumHeights)) {
numComponents += maximumHeights.length;
}
this.packedLength = numComponents + Ellipsoid_default.packedLength + 1;
}
WallOutlineGeometry.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
const positions = value._positions;
let length2 = positions.length;
array[startingIndex++] = length2;
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
Cartesian3_default.pack(positions[i], array, startingIndex);
}
const minimumHeights = value._minimumHeights;
length2 = defined_default(minimumHeights) ? minimumHeights.length : 0;
array[startingIndex++] = length2;
if (defined_default(minimumHeights)) {
for (i = 0; i < length2; ++i) {
array[startingIndex++] = minimumHeights[i];
}
}
const maximumHeights = value._maximumHeights;
length2 = defined_default(maximumHeights) ? maximumHeights.length : 0;
array[startingIndex++] = length2;
if (defined_default(maximumHeights)) {
for (i = 0; i < length2; ++i) {
array[startingIndex++] = maximumHeights[i];
}
}
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
array[startingIndex] = value._granularity;
return array;
};
var scratchEllipsoid13 = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var scratchOptions20 = {
positions: void 0,
minimumHeights: void 0,
maximumHeights: void 0,
ellipsoid: scratchEllipsoid13,
granularity: void 0
};
WallOutlineGeometry.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
let length2 = array[startingIndex++];
const positions = new Array(length2);
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
positions[i] = Cartesian3_default.unpack(array, startingIndex);
}
length2 = array[startingIndex++];
let minimumHeights;
if (length2 > 0) {
minimumHeights = new Array(length2);
for (i = 0; i < length2; ++i) {
minimumHeights[i] = array[startingIndex++];
}
}
length2 = array[startingIndex++];
let maximumHeights;
if (length2 > 0) {
maximumHeights = new Array(length2);
for (i = 0; i < length2; ++i) {
maximumHeights[i] = array[startingIndex++];
}
}
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid13);
startingIndex += Ellipsoid_default.packedLength;
const granularity = array[startingIndex];
if (!defined_default(result)) {
scratchOptions20.positions = positions;
scratchOptions20.minimumHeights = minimumHeights;
scratchOptions20.maximumHeights = maximumHeights;
scratchOptions20.granularity = granularity;
return new WallOutlineGeometry(scratchOptions20);
}
result._positions = positions;
result._minimumHeights = minimumHeights;
result._maximumHeights = maximumHeights;
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._granularity = granularity;
return result;
};
WallOutlineGeometry.fromConstantHeights = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const positions = options.positions;
if (!defined_default(positions)) {
throw new DeveloperError_default("options.positions is required.");
}
let minHeights;
let maxHeights;
const min3 = options.minimumHeight;
const max3 = options.maximumHeight;
const doMin = defined_default(min3);
const doMax = defined_default(max3);
if (doMin || doMax) {
const length2 = positions.length;
minHeights = doMin ? new Array(length2) : void 0;
maxHeights = doMax ? new Array(length2) : void 0;
for (let i = 0; i < length2; ++i) {
if (doMin) {
minHeights[i] = min3;
}
if (doMax) {
maxHeights[i] = max3;
}
}
}
const newOptions2 = {
positions,
maximumHeights: maxHeights,
minimumHeights: minHeights,
ellipsoid: options.ellipsoid
};
return new WallOutlineGeometry(newOptions2);
};
WallOutlineGeometry.createGeometry = function(wallGeometry) {
const wallPositions = wallGeometry._positions;
const minimumHeights = wallGeometry._minimumHeights;
const maximumHeights = wallGeometry._maximumHeights;
const granularity = wallGeometry._granularity;
const ellipsoid = wallGeometry._ellipsoid;
const pos = WallGeometryLibrary_default.computePositions(
ellipsoid,
wallPositions,
maximumHeights,
minimumHeights,
granularity,
false
);
if (!defined_default(pos)) {
return;
}
const bottomPositions = pos.bottomPositions;
const topPositions = pos.topPositions;
let length2 = topPositions.length;
let size = length2 * 2;
const positions = new Float64Array(size);
let positionIndex = 0;
length2 /= 3;
let i;
for (i = 0; i < length2; ++i) {
const i3 = i * 3;
const topPosition = Cartesian3_default.fromArray(
topPositions,
i3,
scratchCartesian3Position12
);
const bottomPosition = Cartesian3_default.fromArray(
bottomPositions,
i3,
scratchCartesian3Position22
);
positions[positionIndex++] = bottomPosition.x;
positions[positionIndex++] = bottomPosition.y;
positions[positionIndex++] = bottomPosition.z;
positions[positionIndex++] = topPosition.x;
positions[positionIndex++] = topPosition.y;
positions[positionIndex++] = topPosition.z;
}
const attributes = new GeometryAttributes_default({
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
})
});
const numVertices = size / 3;
size = 2 * numVertices - 4 + numVertices;
const indices = IndexDatatype_default.createTypedArray(numVertices, size);
let edgeIndex = 0;
for (i = 0; i < numVertices - 2; i += 2) {
const LL = i;
const LR = i + 2;
const pl = Cartesian3_default.fromArray(
positions,
LL * 3,
scratchCartesian3Position12
);
const pr = Cartesian3_default.fromArray(
positions,
LR * 3,
scratchCartesian3Position22
);
if (Cartesian3_default.equalsEpsilon(pl, pr, Math_default.EPSILON10)) {
continue;
}
const UL = i + 1;
const UR = i + 3;
indices[edgeIndex++] = UL;
indices[edgeIndex++] = LL;
indices[edgeIndex++] = UL;
indices[edgeIndex++] = UR;
indices[edgeIndex++] = LL;
indices[edgeIndex++] = LR;
}
indices[edgeIndex++] = numVertices - 2;
indices[edgeIndex++] = numVertices - 1;
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.LINES,
boundingSphere: new BoundingSphere_default.fromVertices(positions)
});
};
var WallOutlineGeometry_default = WallOutlineGeometry;
// packages/engine/Source/DataSources/WallGeometryUpdater.js
var scratchColor21 = new Color_default();
function WallGeometryOptions(entity) {
this.id = entity;
this.vertexFormat = void 0;
this.positions = void 0;
this.minimumHeights = void 0;
this.maximumHeights = void 0;
this.granularity = void 0;
}
function WallGeometryUpdater(entity, scene) {
GeometryUpdater_default.call(this, {
entity,
scene,
geometryOptions: new WallGeometryOptions(entity),
geometryPropertyName: "wall",
observedPropertyNames: ["availability", "wall"]
});
this._onEntityPropertyChanged(entity, "wall", entity.wall, void 0);
}
if (defined_default(Object.create)) {
WallGeometryUpdater.prototype = Object.create(GeometryUpdater_default.prototype);
WallGeometryUpdater.prototype.constructor = WallGeometryUpdater;
}
WallGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._fillEnabled) {
throw new DeveloperError_default(
"This instance does not represent a filled geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
let attributes;
let color;
const show = new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time)
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
);
if (this._materialProperty instanceof ColorMaterialProperty_default) {
let currentColor;
if (defined_default(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
currentColor = this._materialProperty.color.getValue(time, scratchColor21);
}
if (!defined_default(currentColor)) {
currentColor = Color_default.WHITE;
}
color = ColorGeometryInstanceAttribute_default.fromColor(currentColor);
attributes = {
show,
distanceDisplayCondition: distanceDisplayConditionAttribute,
color
};
} else {
attributes = {
show,
distanceDisplayCondition: distanceDisplayConditionAttribute
};
}
return new GeometryInstance_default({
id: entity,
geometry: new WallGeometry_default(this._options),
attributes
});
};
WallGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
Check_default.defined("time", time);
if (!this._outlineEnabled) {
throw new DeveloperError_default(
"This instance does not represent an outlined geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const outlineColor = Property_default.getValueOrDefault(
this._outlineColorProperty,
time,
Color_default.BLACK,
scratchColor21
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
return new GeometryInstance_default({
id: entity,
geometry: new WallOutlineGeometry_default(this._options),
attributes: {
show: new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)
),
color: ColorGeometryInstanceAttribute_default.fromColor(outlineColor),
distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
)
}
});
};
WallGeometryUpdater.prototype._isHidden = function(entity, wall) {
return !defined_default(wall.positions) || GeometryUpdater_default.prototype._isHidden.call(this, entity, wall);
};
WallGeometryUpdater.prototype._getIsClosed = function(options) {
return false;
};
WallGeometryUpdater.prototype._isDynamic = function(entity, wall) {
return !wall.positions.isConstant || //
!Property_default.isConstant(wall.minimumHeights) || //
!Property_default.isConstant(wall.maximumHeights) || //
!Property_default.isConstant(wall.outlineWidth) || //
!Property_default.isConstant(wall.granularity);
};
WallGeometryUpdater.prototype._setStaticOptions = function(entity, wall) {
const minimumHeights = wall.minimumHeights;
const maximumHeights = wall.maximumHeights;
const granularity = wall.granularity;
const isColorMaterial = this._materialProperty instanceof ColorMaterialProperty_default;
const options = this._options;
options.vertexFormat = isColorMaterial ? PerInstanceColorAppearance_default.VERTEX_FORMAT : MaterialAppearance_default.MaterialSupport.TEXTURED.vertexFormat;
options.positions = wall.positions.getValue(
Iso8601_default.MINIMUM_VALUE,
options.positions
);
options.minimumHeights = defined_default(minimumHeights) ? minimumHeights.getValue(Iso8601_default.MINIMUM_VALUE, options.minimumHeights) : void 0;
options.maximumHeights = defined_default(maximumHeights) ? maximumHeights.getValue(Iso8601_default.MINIMUM_VALUE, options.maximumHeights) : void 0;
options.granularity = defined_default(granularity) ? granularity.getValue(Iso8601_default.MINIMUM_VALUE) : void 0;
};
WallGeometryUpdater.DynamicGeometryUpdater = DynamicWallGeometryUpdater;
function DynamicWallGeometryUpdater(geometryUpdater, primitives, groundPrimitives) {
DynamicGeometryUpdater_default.call(
this,
geometryUpdater,
primitives,
groundPrimitives
);
}
if (defined_default(Object.create)) {
DynamicWallGeometryUpdater.prototype = Object.create(
DynamicGeometryUpdater_default.prototype
);
DynamicWallGeometryUpdater.prototype.constructor = DynamicWallGeometryUpdater;
}
DynamicWallGeometryUpdater.prototype._isHidden = function(entity, wall, time) {
return !defined_default(this._options.positions) || DynamicGeometryUpdater_default.prototype._isHidden.call(this, entity, wall, time);
};
DynamicWallGeometryUpdater.prototype._setOptions = function(entity, wall, time) {
const options = this._options;
options.positions = Property_default.getValueOrUndefined(
wall.positions,
time,
options.positions
);
options.minimumHeights = Property_default.getValueOrUndefined(
wall.minimumHeights,
time,
options.minimumHeights
);
options.maximumHeights = Property_default.getValueOrUndefined(
wall.maximumHeights,
time,
options.maximumHeights
);
options.granularity = Property_default.getValueOrUndefined(wall.granularity, time);
};
var WallGeometryUpdater_default = WallGeometryUpdater;
// packages/engine/Source/DataSources/GeometryUpdaterSet.js
var geometryUpdaters = [
BoxGeometryUpdater_default,
CylinderGeometryUpdater_default,
CorridorGeometryUpdater_default,
EllipseGeometryUpdater_default,
EllipsoidGeometryUpdater_default,
PlaneGeometryUpdater_default,
PolygonGeometryUpdater_default,
PolylineVolumeGeometryUpdater_default,
RectangleGeometryUpdater_default,
WallGeometryUpdater_default
];
function GeometryUpdaterSet(entity, scene) {
this.entity = entity;
this.scene = scene;
const updaters = new Array(geometryUpdaters.length);
const geometryChanged = new Event_default();
const eventHelper = new EventHelper_default();
for (let i = 0; i < updaters.length; i++) {
const updater = new geometryUpdaters[i](entity, scene);
eventHelper.add(updater.geometryChanged, (geometry) => {
geometryChanged.raiseEvent(geometry);
});
updaters[i] = updater;
}
this.updaters = updaters;
this.geometryChanged = geometryChanged;
this.eventHelper = eventHelper;
this._removeEntitySubscription = entity.definitionChanged.addEventListener(
GeometryUpdaterSet.prototype._onEntityPropertyChanged,
this
);
}
GeometryUpdaterSet.prototype._onEntityPropertyChanged = function(entity, propertyName, newValue, oldValue2) {
const updaters = this.updaters;
for (let i = 0; i < updaters.length; i++) {
updaters[i]._onEntityPropertyChanged(
entity,
propertyName,
newValue,
oldValue2
);
}
};
GeometryUpdaterSet.prototype.forEach = function(callback) {
const updaters = this.updaters;
for (let i = 0; i < updaters.length; i++) {
callback(updaters[i]);
}
};
GeometryUpdaterSet.prototype.destroy = function() {
this.eventHelper.removeAll();
const updaters = this.updaters;
for (let i = 0; i < updaters.length; i++) {
updaters[i].destroy();
}
this._removeEntitySubscription();
destroyObject_default(this);
};
GeometryUpdaterSet.registerUpdater = function(updater) {
if (!geometryUpdaters.includes(updater)) {
geometryUpdaters.push(updater);
}
};
GeometryUpdaterSet.unregisterUpdater = function(updater) {
if (geometryUpdaters.includes(updater)) {
const index = geometryUpdaters.indexOf(updater);
geometryUpdaters.splice(index, 1);
}
};
var GeometryUpdaterSet_default = GeometryUpdaterSet;
// packages/engine/Source/DataSources/StaticGeometryColorBatch.js
var import_InlineWorkers900 = __toESM(require_InlineWorkers(), 1);
var colorScratch2 = new Color_default();
var distanceDisplayConditionScratch2 = new DistanceDisplayCondition_default();
var defaultDistanceDisplayCondition2 = new DistanceDisplayCondition_default();
var defaultOffset9 = Cartesian3_default.ZERO;
var offsetScratch11 = new Cartesian3_default();
function Batch(primitives, translucent, appearanceType, depthFailAppearanceType, depthFailMaterialProperty, closed, shadows) {
this.translucent = translucent;
this.appearanceType = appearanceType;
this.depthFailAppearanceType = depthFailAppearanceType;
this.depthFailMaterialProperty = depthFailMaterialProperty;
this.depthFailMaterial = void 0;
this.closed = closed;
this.shadows = shadows;
this.primitives = primitives;
this.createPrimitive = false;
this.waitingOnCreate = false;
this.primitive = void 0;
this.oldPrimitive = void 0;
this.geometry = new AssociativeArray_default();
this.updaters = new AssociativeArray_default();
this.updatersWithAttributes = new AssociativeArray_default();
this.attributes = new AssociativeArray_default();
this.subscriptions = new AssociativeArray_default();
this.showsUpdated = new AssociativeArray_default();
this.itemsToRemove = [];
this.invalidated = false;
let removeMaterialSubscription;
if (defined_default(depthFailMaterialProperty)) {
removeMaterialSubscription = depthFailMaterialProperty.definitionChanged.addEventListener(
Batch.prototype.onMaterialChanged,
this
);
}
this.removeMaterialSubscription = removeMaterialSubscription;
}
Batch.prototype.onMaterialChanged = function() {
this.invalidated = true;
};
Batch.prototype.isMaterial = function(updater) {
const material = this.depthFailMaterialProperty;
const updaterMaterial = updater.depthFailMaterialProperty;
if (updaterMaterial === material) {
return true;
}
if (defined_default(material)) {
return material.equals(updaterMaterial);
}
return false;
};
Batch.prototype.add = function(updater, instance) {
const id = updater.id;
this.createPrimitive = true;
this.geometry.set(id, instance);
this.updaters.set(id, updater);
if (!updater.hasConstantFill || !updater.fillMaterialProperty.isConstant || !Property_default.isConstant(updater.distanceDisplayConditionProperty) || !Property_default.isConstant(updater.terrainOffsetProperty)) {
this.updatersWithAttributes.set(id, updater);
} else {
const that = this;
this.subscriptions.set(
id,
updater.entity.definitionChanged.addEventListener(
function(entity, propertyName, newValue, oldValue2) {
if (propertyName === "isShowing") {
that.showsUpdated.set(updater.id, updater);
}
}
)
);
}
};
Batch.prototype.remove = function(updater) {
const id = updater.id;
this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;
if (this.updaters.remove(id)) {
this.updatersWithAttributes.remove(id);
const unsubscribe2 = this.subscriptions.get(id);
if (defined_default(unsubscribe2)) {
unsubscribe2();
this.subscriptions.remove(id);
this.showsUpdated.remove(id);
}
return true;
}
return false;
};
Batch.prototype.update = function(time) {
let isUpdated = true;
let removedCount = 0;
let primitive = this.primitive;
const primitives = this.primitives;
let i;
if (this.createPrimitive) {
const geometries = this.geometry.values;
const geometriesLength = geometries.length;
if (geometriesLength > 0) {
if (defined_default(primitive)) {
if (!defined_default(this.oldPrimitive)) {
this.oldPrimitive = primitive;
} else {
primitives.remove(primitive);
}
}
let depthFailAppearance;
if (defined_default(this.depthFailAppearanceType)) {
if (defined_default(this.depthFailMaterialProperty)) {
this.depthFailMaterial = MaterialProperty_default.getValue(
time,
this.depthFailMaterialProperty,
this.depthFailMaterial
);
}
depthFailAppearance = new this.depthFailAppearanceType({
material: this.depthFailMaterial,
translucent: this.translucent,
closed: this.closed
});
}
primitive = new Primitive_default({
show: false,
asynchronous: true,
geometryInstances: geometries.slice(),
appearance: new this.appearanceType({
translucent: this.translucent,
closed: this.closed
}),
depthFailAppearance,
shadows: this.shadows
});
primitives.add(primitive);
isUpdated = false;
} else {
if (defined_default(primitive)) {
primitives.remove(primitive);
primitive = void 0;
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
primitives.remove(oldPrimitive);
this.oldPrimitive = void 0;
}
}
this.attributes.removeAll();
this.primitive = primitive;
this.createPrimitive = false;
this.waitingOnCreate = true;
} else if (defined_default(primitive) && primitive.ready) {
primitive.show = true;
if (defined_default(this.oldPrimitive)) {
primitives.remove(this.oldPrimitive);
this.oldPrimitive = void 0;
}
if (defined_default(this.depthFailAppearanceType) && !(this.depthFailMaterialProperty instanceof ColorMaterialProperty_default)) {
this.depthFailMaterial = MaterialProperty_default.getValue(
time,
this.depthFailMaterialProperty,
this.depthFailMaterial
);
this.primitive.depthFailAppearance.material = this.depthFailMaterial;
}
const updatersWithAttributes = this.updatersWithAttributes.values;
const length2 = updatersWithAttributes.length;
const waitingOnCreate = this.waitingOnCreate;
for (i = 0; i < length2; i++) {
const updater = updatersWithAttributes[i];
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
if (!updater.fillMaterialProperty.isConstant || waitingOnCreate) {
const colorProperty = updater.fillMaterialProperty.color;
const resultColor = Property_default.getValueOrDefault(
colorProperty,
time,
Color_default.WHITE,
colorScratch2
);
if (!Color_default.equals(attributes._lastColor, resultColor)) {
attributes._lastColor = Color_default.clone(
resultColor,
attributes._lastColor
);
attributes.color = ColorGeometryInstanceAttribute_default.toValue(
resultColor,
attributes.color
);
if (this.translucent && attributes.color[3] === 255 || !this.translucent && attributes.color[3] !== 255) {
this.itemsToRemove[removedCount++] = updater;
}
}
}
if (defined_default(this.depthFailAppearanceType) && updater.depthFailMaterialProperty instanceof ColorMaterialProperty_default && (!updater.depthFailMaterialProperty.isConstant || waitingOnCreate)) {
const depthFailColorProperty = updater.depthFailMaterialProperty.color;
const depthColor = Property_default.getValueOrDefault(
depthFailColorProperty,
time,
Color_default.WHITE,
colorScratch2
);
if (!Color_default.equals(attributes._lastDepthFailColor, depthColor)) {
attributes._lastDepthFailColor = Color_default.clone(
depthColor,
attributes._lastDepthFailColor
);
attributes.depthFailColor = ColorGeometryInstanceAttribute_default.toValue(
depthColor,
attributes.depthFailColor
);
}
}
const show = updater.entity.isShowing && (updater.hasConstantFill || updater.isFilled(time));
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
}
const distanceDisplayConditionProperty = updater.distanceDisplayConditionProperty;
if (!Property_default.isConstant(distanceDisplayConditionProperty)) {
const distanceDisplayCondition = Property_default.getValueOrDefault(
distanceDisplayConditionProperty,
time,
defaultDistanceDisplayCondition2,
distanceDisplayConditionScratch2
);
if (!DistanceDisplayCondition_default.equals(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
)) {
attributes._lastDistanceDisplayCondition = DistanceDisplayCondition_default.clone(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
);
attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute_default.toValue(
distanceDisplayCondition,
attributes.distanceDisplayCondition
);
}
}
const offsetProperty = updater.terrainOffsetProperty;
if (!Property_default.isConstant(offsetProperty)) {
const offset = Property_default.getValueOrDefault(
offsetProperty,
time,
defaultOffset9,
offsetScratch11
);
if (!Cartesian3_default.equals(offset, attributes._lastOffset)) {
attributes._lastOffset = Cartesian3_default.clone(
offset,
attributes._lastOffset
);
attributes.offset = OffsetGeometryInstanceAttribute_default.toValue(
offset,
attributes.offset
);
}
}
}
this.updateShows(primitive);
this.waitingOnCreate = false;
} else if (defined_default(primitive) && !primitive.ready) {
isUpdated = false;
}
this.itemsToRemove.length = removedCount;
return isUpdated;
};
Batch.prototype.updateShows = function(primitive) {
const showsUpdated = this.showsUpdated.values;
const length2 = showsUpdated.length;
for (let i = 0; i < length2; i++) {
const updater = showsUpdated[i];
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
const show = updater.entity.isShowing;
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
instance.attributes.show.value[0] = attributes.show[0];
}
}
this.showsUpdated.removeAll();
};
Batch.prototype.contains = function(updater) {
return this.updaters.contains(updater.id);
};
Batch.prototype.getBoundingSphere = function(updater, result) {
const primitive = this.primitive;
if (!primitive.ready) {
return BoundingSphereState_default.PENDING;
}
const attributes = primitive.getGeometryInstanceAttributes(updater.entity);
if (!defined_default(attributes) || !defined_default(attributes.boundingSphere) || //
defined_default(attributes.show) && attributes.show[0] === 0) {
return BoundingSphereState_default.FAILED;
}
attributes.boundingSphere.clone(result);
return BoundingSphereState_default.DONE;
};
Batch.prototype.destroy = function() {
const primitive = this.primitive;
const primitives = this.primitives;
if (defined_default(primitive)) {
primitives.remove(primitive);
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
primitives.remove(oldPrimitive);
}
if (defined_default(this.removeMaterialSubscription)) {
this.removeMaterialSubscription();
}
};
function StaticGeometryColorBatch(primitives, appearanceType, depthFailAppearanceType, closed, shadows) {
this._solidItems = [];
this._translucentItems = [];
this._primitives = primitives;
this._appearanceType = appearanceType;
this._depthFailAppearanceType = depthFailAppearanceType;
this._closed = closed;
this._shadows = shadows;
}
StaticGeometryColorBatch.prototype.add = function(time, updater) {
let items;
let translucent;
const instance = updater.createFillGeometryInstance(time);
if (instance.attributes.color.value[3] === 255) {
items = this._solidItems;
translucent = false;
} else {
items = this._translucentItems;
translucent = true;
}
const length2 = items.length;
for (let i = 0; i < length2; i++) {
const item = items[i];
if (item.isMaterial(updater)) {
item.add(updater, instance);
return;
}
}
const batch = new Batch(
this._primitives,
translucent,
this._appearanceType,
this._depthFailAppearanceType,
updater.depthFailMaterialProperty,
this._closed,
this._shadows
);
batch.add(updater, instance);
items.push(batch);
};
function removeItem(items, updater) {
const length2 = items.length;
for (let i = length2 - 1; i >= 0; i--) {
const item = items[i];
if (item.remove(updater)) {
if (item.updaters.length === 0) {
items.splice(i, 1);
item.destroy();
}
return true;
}
}
return false;
}
StaticGeometryColorBatch.prototype.remove = function(updater) {
if (!removeItem(this._solidItems, updater)) {
removeItem(this._translucentItems, updater);
}
};
function moveItems(batch, items, time) {
let itemsMoved = false;
const length2 = items.length;
for (let i = 0; i < length2; ++i) {
const item = items[i];
const itemsToRemove = item.itemsToRemove;
const itemsToMoveLength = itemsToRemove.length;
if (itemsToMoveLength > 0) {
for (i = 0; i < itemsToMoveLength; i++) {
const updater = itemsToRemove[i];
item.remove(updater);
batch.add(time, updater);
itemsMoved = true;
}
}
}
return itemsMoved;
}
function updateItems(batch, items, time, isUpdated) {
let length2 = items.length;
let i;
for (i = length2 - 1; i >= 0; i--) {
const item = items[i];
if (item.invalidated) {
items.splice(i, 1);
const updaters = item.updaters.values;
const updatersLength = updaters.length;
for (let h = 0; h < updatersLength; h++) {
batch.add(time, updaters[h]);
}
item.destroy();
}
}
length2 = items.length;
for (i = 0; i < length2; ++i) {
isUpdated = items[i].update(time) && isUpdated;
}
return isUpdated;
}
StaticGeometryColorBatch.prototype.update = function(time) {
let isUpdated = updateItems(this, this._solidItems, time, true);
isUpdated = updateItems(this, this._translucentItems, time, isUpdated) && isUpdated;
const solidsMoved = moveItems(this, this._solidItems, time);
const translucentsMoved = moveItems(this, this._translucentItems, time);
if (solidsMoved || translucentsMoved) {
isUpdated = updateItems(this, this._solidItems, time, isUpdated) && isUpdated;
isUpdated = updateItems(this, this._translucentItems, time, isUpdated) && isUpdated;
}
return isUpdated;
};
function getBoundingSphere(items, updater, result) {
const length2 = items.length;
for (let i = 0; i < length2; i++) {
const item = items[i];
if (item.contains(updater)) {
return item.getBoundingSphere(updater, result);
}
}
return BoundingSphereState_default.FAILED;
}
StaticGeometryColorBatch.prototype.getBoundingSphere = function(updater, result) {
const boundingSphere = getBoundingSphere(this._solidItems, updater, result);
if (boundingSphere === BoundingSphereState_default.FAILED) {
return getBoundingSphere(this._translucentItems, updater, result);
}
return boundingSphere;
};
function removeAllPrimitives(items) {
const length2 = items.length;
for (let i = 0; i < length2; i++) {
items[i].destroy();
}
items.length = 0;
}
StaticGeometryColorBatch.prototype.removeAllPrimitives = function() {
removeAllPrimitives(this._solidItems);
removeAllPrimitives(this._translucentItems);
};
var StaticGeometryColorBatch_default = StaticGeometryColorBatch;
// packages/engine/Source/DataSources/StaticGeometryPerMaterialBatch.js
var import_InlineWorkers901 = __toESM(require_InlineWorkers(), 1);
var distanceDisplayConditionScratch3 = new DistanceDisplayCondition_default();
var defaultDistanceDisplayCondition3 = new DistanceDisplayCondition_default();
var defaultOffset10 = Cartesian3_default.ZERO;
var offsetScratch12 = new Cartesian3_default();
function Batch2(primitives, appearanceType, materialProperty, depthFailAppearanceType, depthFailMaterialProperty, closed, shadows) {
this.primitives = primitives;
this.appearanceType = appearanceType;
this.materialProperty = materialProperty;
this.depthFailAppearanceType = depthFailAppearanceType;
this.depthFailMaterialProperty = depthFailMaterialProperty;
this.closed = closed;
this.shadows = shadows;
this.updaters = new AssociativeArray_default();
this.createPrimitive = true;
this.primitive = void 0;
this.oldPrimitive = void 0;
this.geometry = new AssociativeArray_default();
this.material = void 0;
this.depthFailMaterial = void 0;
this.updatersWithAttributes = new AssociativeArray_default();
this.attributes = new AssociativeArray_default();
this.invalidated = false;
this.removeMaterialSubscription = materialProperty.definitionChanged.addEventListener(
Batch2.prototype.onMaterialChanged,
this
);
this.subscriptions = new AssociativeArray_default();
this.showsUpdated = new AssociativeArray_default();
}
Batch2.prototype.onMaterialChanged = function() {
this.invalidated = true;
};
Batch2.prototype.isMaterial = function(updater) {
const material = this.materialProperty;
const updaterMaterial = updater.fillMaterialProperty;
const depthFailMaterial = this.depthFailMaterialProperty;
const updaterDepthFailMaterial = updater.depthFailMaterialProperty;
if (updaterMaterial === material && updaterDepthFailMaterial === depthFailMaterial) {
return true;
}
let equals2 = defined_default(material) && material.equals(updaterMaterial);
equals2 = (!defined_default(depthFailMaterial) && !defined_default(updaterDepthFailMaterial) || defined_default(depthFailMaterial) && depthFailMaterial.equals(updaterDepthFailMaterial)) && equals2;
return equals2;
};
Batch2.prototype.add = function(time, updater) {
const id = updater.id;
this.updaters.set(id, updater);
this.geometry.set(id, updater.createFillGeometryInstance(time));
if (!updater.hasConstantFill || !updater.fillMaterialProperty.isConstant || !Property_default.isConstant(updater.distanceDisplayConditionProperty) || !Property_default.isConstant(updater.terrainOffsetProperty)) {
this.updatersWithAttributes.set(id, updater);
} else {
const that = this;
this.subscriptions.set(
id,
updater.entity.definitionChanged.addEventListener(
function(entity, propertyName, newValue, oldValue2) {
if (propertyName === "isShowing") {
that.showsUpdated.set(updater.id, updater);
}
}
)
);
}
this.createPrimitive = true;
};
Batch2.prototype.remove = function(updater) {
const id = updater.id;
this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;
if (this.updaters.remove(id)) {
this.updatersWithAttributes.remove(id);
const unsubscribe2 = this.subscriptions.get(id);
if (defined_default(unsubscribe2)) {
unsubscribe2();
this.subscriptions.remove(id);
this.showsUpdated.remove(id);
}
return true;
}
return false;
};
var colorScratch3 = new Color_default();
Batch2.prototype.update = function(time) {
let isUpdated = true;
let primitive = this.primitive;
const primitives = this.primitives;
const geometries = this.geometry.values;
let i;
if (this.createPrimitive) {
const geometriesLength = geometries.length;
if (geometriesLength > 0) {
if (defined_default(primitive)) {
if (!defined_default(this.oldPrimitive)) {
this.oldPrimitive = primitive;
} else {
primitives.remove(primitive);
}
}
this.material = MaterialProperty_default.getValue(
time,
this.materialProperty,
this.material
);
let depthFailAppearance;
if (defined_default(this.depthFailMaterialProperty)) {
this.depthFailMaterial = MaterialProperty_default.getValue(
time,
this.depthFailMaterialProperty,
this.depthFailMaterial
);
depthFailAppearance = new this.depthFailAppearanceType({
material: this.depthFailMaterial,
translucent: this.depthFailMaterial.isTranslucent(),
closed: this.closed
});
}
primitive = new Primitive_default({
show: false,
asynchronous: true,
geometryInstances: geometries.slice(),
appearance: new this.appearanceType({
material: this.material,
translucent: this.material.isTranslucent(),
closed: this.closed
}),
depthFailAppearance,
shadows: this.shadows
});
primitives.add(primitive);
isUpdated = false;
} else {
if (defined_default(primitive)) {
primitives.remove(primitive);
primitive = void 0;
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
primitives.remove(oldPrimitive);
this.oldPrimitive = void 0;
}
}
this.attributes.removeAll();
this.primitive = primitive;
this.createPrimitive = false;
} else if (defined_default(primitive) && primitive.ready) {
primitive.show = true;
if (defined_default(this.oldPrimitive)) {
primitives.remove(this.oldPrimitive);
this.oldPrimitive = void 0;
}
this.material = MaterialProperty_default.getValue(
time,
this.materialProperty,
this.material
);
this.primitive.appearance.material = this.material;
if (defined_default(this.depthFailAppearanceType) && !(this.depthFailMaterialProperty instanceof ColorMaterialProperty_default)) {
this.depthFailMaterial = MaterialProperty_default.getValue(
time,
this.depthFailMaterialProperty,
this.depthFailMaterial
);
this.primitive.depthFailAppearance.material = this.depthFailMaterial;
}
const updatersWithAttributes = this.updatersWithAttributes.values;
const length2 = updatersWithAttributes.length;
for (i = 0; i < length2; i++) {
const updater = updatersWithAttributes[i];
const entity = updater.entity;
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
if (defined_default(this.depthFailAppearanceType) && this.depthFailMaterialProperty instanceof ColorMaterialProperty_default && !updater.depthFailMaterialProperty.isConstant) {
const depthFailColorProperty = updater.depthFailMaterialProperty.color;
const depthFailColor = Property_default.getValueOrDefault(
depthFailColorProperty,
time,
Color_default.WHITE,
colorScratch3
);
if (!Color_default.equals(attributes._lastDepthFailColor, depthFailColor)) {
attributes._lastDepthFailColor = Color_default.clone(
depthFailColor,
attributes._lastDepthFailColor
);
attributes.depthFailColor = ColorGeometryInstanceAttribute_default.toValue(
depthFailColor,
attributes.depthFailColor
);
}
}
const show = entity.isShowing && (updater.hasConstantFill || updater.isFilled(time));
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
}
const distanceDisplayConditionProperty = updater.distanceDisplayConditionProperty;
if (!Property_default.isConstant(distanceDisplayConditionProperty)) {
const distanceDisplayCondition = Property_default.getValueOrDefault(
distanceDisplayConditionProperty,
time,
defaultDistanceDisplayCondition3,
distanceDisplayConditionScratch3
);
if (!DistanceDisplayCondition_default.equals(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
)) {
attributes._lastDistanceDisplayCondition = DistanceDisplayCondition_default.clone(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
);
attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute_default.toValue(
distanceDisplayCondition,
attributes.distanceDisplayCondition
);
}
}
const offsetProperty = updater.terrainOffsetProperty;
if (!Property_default.isConstant(offsetProperty)) {
const offset = Property_default.getValueOrDefault(
offsetProperty,
time,
defaultOffset10,
offsetScratch12
);
if (!Cartesian3_default.equals(offset, attributes._lastOffset)) {
attributes._lastOffset = Cartesian3_default.clone(
offset,
attributes._lastOffset
);
attributes.offset = OffsetGeometryInstanceAttribute_default.toValue(
offset,
attributes.offset
);
}
}
}
this.updateShows(primitive);
} else if (defined_default(primitive) && !primitive.ready) {
isUpdated = false;
}
return isUpdated;
};
Batch2.prototype.updateShows = function(primitive) {
const showsUpdated = this.showsUpdated.values;
const length2 = showsUpdated.length;
for (let i = 0; i < length2; i++) {
const updater = showsUpdated[i];
const entity = updater.entity;
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
const show = entity.isShowing;
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
instance.attributes.show.value[0] = attributes.show[0];
}
}
this.showsUpdated.removeAll();
};
Batch2.prototype.contains = function(updater) {
return this.updaters.contains(updater.id);
};
Batch2.prototype.getBoundingSphere = function(updater, result) {
const primitive = this.primitive;
if (!primitive.ready) {
return BoundingSphereState_default.PENDING;
}
const attributes = primitive.getGeometryInstanceAttributes(updater.entity);
if (!defined_default(attributes) || !defined_default(attributes.boundingSphere) || defined_default(attributes.show) && attributes.show[0] === 0) {
return BoundingSphereState_default.FAILED;
}
attributes.boundingSphere.clone(result);
return BoundingSphereState_default.DONE;
};
Batch2.prototype.destroy = function() {
const primitive = this.primitive;
const primitives = this.primitives;
if (defined_default(primitive)) {
primitives.remove(primitive);
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
primitives.remove(oldPrimitive);
}
this.removeMaterialSubscription();
};
function StaticGeometryPerMaterialBatch(primitives, appearanceType, depthFailAppearanceType, closed, shadows) {
this._items = [];
this._primitives = primitives;
this._appearanceType = appearanceType;
this._depthFailAppearanceType = depthFailAppearanceType;
this._closed = closed;
this._shadows = shadows;
}
StaticGeometryPerMaterialBatch.prototype.add = function(time, updater) {
const items = this._items;
const length2 = items.length;
for (let i = 0; i < length2; i++) {
const item = items[i];
if (item.isMaterial(updater)) {
item.add(time, updater);
return;
}
}
const batch = new Batch2(
this._primitives,
this._appearanceType,
updater.fillMaterialProperty,
this._depthFailAppearanceType,
updater.depthFailMaterialProperty,
this._closed,
this._shadows
);
batch.add(time, updater);
items.push(batch);
};
StaticGeometryPerMaterialBatch.prototype.remove = function(updater) {
const items = this._items;
const length2 = items.length;
for (let i = length2 - 1; i >= 0; i--) {
const item = items[i];
if (item.remove(updater)) {
if (item.updaters.length === 0) {
items.splice(i, 1);
item.destroy();
}
break;
}
}
};
StaticGeometryPerMaterialBatch.prototype.update = function(time) {
let i;
const items = this._items;
const length2 = items.length;
for (i = length2 - 1; i >= 0; i--) {
const item = items[i];
if (item.invalidated) {
items.splice(i, 1);
const updaters = item.updaters.values;
const updatersLength = updaters.length;
for (let h = 0; h < updatersLength; h++) {
this.add(time, updaters[h]);
}
item.destroy();
}
}
let isUpdated = true;
for (i = 0; i < items.length; i++) {
isUpdated = items[i].update(time) && isUpdated;
}
return isUpdated;
};
StaticGeometryPerMaterialBatch.prototype.getBoundingSphere = function(updater, result) {
const items = this._items;
const length2 = items.length;
for (let i = 0; i < length2; i++) {
const item = items[i];
if (item.contains(updater)) {
return item.getBoundingSphere(updater, result);
}
}
return BoundingSphereState_default.FAILED;
};
StaticGeometryPerMaterialBatch.prototype.removeAllPrimitives = function() {
const items = this._items;
const length2 = items.length;
for (let i = 0; i < length2; i++) {
items[i].destroy();
}
this._items.length = 0;
};
var StaticGeometryPerMaterialBatch_default = StaticGeometryPerMaterialBatch;
// packages/engine/Source/DataSources/StaticGroundGeometryColorBatch.js
var import_InlineWorkers905 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/RectangleCollisionChecker.js
var import_InlineWorkers904 = __toESM(require_InlineWorkers(), 1);
// node_modules/rbush/index.js
var import_InlineWorkers903 = __toESM(require_InlineWorkers(), 1);
// node_modules/quickselect/index.js
var import_InlineWorkers902 = __toESM(require_InlineWorkers(), 1);
function quickselect(arr, k, left = 0, right = arr.length - 1, compare = defaultCompare) {
while (right > left) {
if (right - left > 600) {
const n = right - left + 1;
const m = k - left + 1;
const z = Math.log(n);
const s = 0.5 * Math.exp(2 * z / 3);
const sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
const newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
const newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
quickselect(arr, k, newLeft, newRight, compare);
}
const t = arr[k];
let i = left;
let j = right;
swap3(arr, left, k);
if (compare(arr[right], t) > 0) swap3(arr, left, right);
while (i < j) {
swap3(arr, i, j);
i++;
j--;
while (compare(arr[i], t) < 0) i++;
while (compare(arr[j], t) > 0) j--;
}
if (compare(arr[left], t) === 0) swap3(arr, left, j);
else {
j++;
swap3(arr, j, right);
}
if (j <= k) left = j + 1;
if (k <= j) right = j - 1;
}
}
function swap3(arr, i, j) {
const tmp2 = arr[i];
arr[i] = arr[j];
arr[j] = tmp2;
}
function defaultCompare(a3, b) {
return a3 < b ? -1 : a3 > b ? 1 : 0;
}
// node_modules/rbush/index.js
var RBush = class {
constructor(maxEntries = 9) {
this._maxEntries = Math.max(4, maxEntries);
this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
this.clear();
}
all() {
return this._all(this.data, []);
}
search(bbox) {
let node = this.data;
const result = [];
if (!intersects2(bbox, node)) return result;
const toBBox = this.toBBox;
const nodesToSearch = [];
while (node) {
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
const childBBox = node.leaf ? toBBox(child) : child;
if (intersects2(bbox, childBBox)) {
if (node.leaf) result.push(child);
else if (contains(bbox, childBBox)) this._all(child, result);
else nodesToSearch.push(child);
}
}
node = nodesToSearch.pop();
}
return result;
}
collides(bbox) {
let node = this.data;
if (!intersects2(bbox, node)) return false;
const nodesToSearch = [];
while (node) {
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
const childBBox = node.leaf ? this.toBBox(child) : child;
if (intersects2(bbox, childBBox)) {
if (node.leaf || contains(bbox, childBBox)) return true;
nodesToSearch.push(child);
}
}
node = nodesToSearch.pop();
}
return false;
}
load(data) {
if (!(data && data.length)) return this;
if (data.length < this._minEntries) {
for (let i = 0; i < data.length; i++) {
this.insert(data[i]);
}
return this;
}
let node = this._build(data.slice(), 0, data.length - 1, 0);
if (!this.data.children.length) {
this.data = node;
} else if (this.data.height === node.height) {
this._splitRoot(this.data, node);
} else {
if (this.data.height < node.height) {
const tmpNode = this.data;
this.data = node;
node = tmpNode;
}
this._insert(node, this.data.height - node.height - 1, true);
}
return this;
}
insert(item) {
if (item) this._insert(item, this.data.height - 1);
return this;
}
clear() {
this.data = createNode2([]);
return this;
}
remove(item, equalsFn) {
if (!item) return this;
let node = this.data;
const bbox = this.toBBox(item);
const path = [];
const indexes = [];
let i, parent, goingUp;
while (node || path.length) {
if (!node) {
node = path.pop();
parent = path[path.length - 1];
i = indexes.pop();
goingUp = true;
}
if (node.leaf) {
const index = findItem(item, node.children, equalsFn);
if (index !== -1) {
node.children.splice(index, 1);
path.push(node);
this._condense(path);
return this;
}
}
if (!goingUp && !node.leaf && contains(node, bbox)) {
path.push(node);
indexes.push(i);
i = 0;
parent = node;
node = node.children[0];
} else if (parent) {
i++;
node = parent.children[i];
goingUp = false;
} else node = null;
}
return this;
}
toBBox(item) {
return item;
}
compareMinX(a3, b) {
return a3.minX - b.minX;
}
compareMinY(a3, b) {
return a3.minY - b.minY;
}
toJSON() {
return this.data;
}
fromJSON(data) {
this.data = data;
return this;
}
_all(node, result) {
const nodesToSearch = [];
while (node) {
if (node.leaf) result.push(...node.children);
else nodesToSearch.push(...node.children);
node = nodesToSearch.pop();
}
return result;
}
_build(items, left, right, height) {
const N = right - left + 1;
let M = this._maxEntries;
let node;
if (N <= M) {
node = createNode2(items.slice(left, right + 1));
calcBBox(node, this.toBBox);
return node;
}
if (!height) {
height = Math.ceil(Math.log(N) / Math.log(M));
M = Math.ceil(N / Math.pow(M, height - 1));
}
node = createNode2([]);
node.leaf = false;
node.height = height;
const N2 = Math.ceil(N / M);
const N1 = N2 * Math.ceil(Math.sqrt(M));
multiSelect(items, left, right, N1, this.compareMinX);
for (let i = left; i <= right; i += N1) {
const right2 = Math.min(i + N1 - 1, right);
multiSelect(items, i, right2, N2, this.compareMinY);
for (let j = i; j <= right2; j += N2) {
const right3 = Math.min(j + N2 - 1, right2);
node.children.push(this._build(items, j, right3, height - 1));
}
}
calcBBox(node, this.toBBox);
return node;
}
_chooseSubtree(bbox, node, level, path) {
while (true) {
path.push(node);
if (node.leaf || path.length - 1 === level) break;
let minArea = Infinity;
let minEnlargement = Infinity;
let targetNode;
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
const area2 = bboxArea(child);
const enlargement = enlargedArea(bbox, child) - area2;
if (enlargement < minEnlargement) {
minEnlargement = enlargement;
minArea = area2 < minArea ? area2 : minArea;
targetNode = child;
} else if (enlargement === minEnlargement) {
if (area2 < minArea) {
minArea = area2;
targetNode = child;
}
}
}
node = targetNode || node.children[0];
}
return node;
}
_insert(item, level, isNode) {
const bbox = isNode ? item : this.toBBox(item);
const insertPath = [];
const node = this._chooseSubtree(bbox, this.data, level, insertPath);
node.children.push(item);
extend(node, bbox);
while (level >= 0) {
if (insertPath[level].children.length > this._maxEntries) {
this._split(insertPath, level);
level--;
} else break;
}
this._adjustParentBBoxes(bbox, insertPath, level);
}
// split overflowed node into two
_split(insertPath, level) {
const node = insertPath[level];
const M = node.children.length;
const m = this._minEntries;
this._chooseSplitAxis(node, m, M);
const splitIndex = this._chooseSplitIndex(node, m, M);
const newNode = createNode2(node.children.splice(splitIndex, node.children.length - splitIndex));
newNode.height = node.height;
newNode.leaf = node.leaf;
calcBBox(node, this.toBBox);
calcBBox(newNode, this.toBBox);
if (level) insertPath[level - 1].children.push(newNode);
else this._splitRoot(node, newNode);
}
_splitRoot(node, newNode) {
this.data = createNode2([node, newNode]);
this.data.height = node.height + 1;
this.data.leaf = false;
calcBBox(this.data, this.toBBox);
}
_chooseSplitIndex(node, m, M) {
let index;
let minOverlap = Infinity;
let minArea = Infinity;
for (let i = m; i <= M - m; i++) {
const bbox1 = distBBox(node, 0, i, this.toBBox);
const bbox2 = distBBox(node, i, M, this.toBBox);
const overlap = intersectionArea(bbox1, bbox2);
const area2 = bboxArea(bbox1) + bboxArea(bbox2);
if (overlap < minOverlap) {
minOverlap = overlap;
index = i;
minArea = area2 < minArea ? area2 : minArea;
} else if (overlap === minOverlap) {
if (area2 < minArea) {
minArea = area2;
index = i;
}
}
}
return index || M - m;
}
// sorts node children by the best axis for split
_chooseSplitAxis(node, m, M) {
const compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;
const compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;
const xMargin = this._allDistMargin(node, m, M, compareMinX);
const yMargin = this._allDistMargin(node, m, M, compareMinY);
if (xMargin < yMargin) node.children.sort(compareMinX);
}
// total margin of all possible split distributions where each node is at least m full
_allDistMargin(node, m, M, compare) {
node.children.sort(compare);
const toBBox = this.toBBox;
const leftBBox = distBBox(node, 0, m, toBBox);
const rightBBox = distBBox(node, M - m, M, toBBox);
let margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);
for (let i = m; i < M - m; i++) {
const child = node.children[i];
extend(leftBBox, node.leaf ? toBBox(child) : child);
margin += bboxMargin(leftBBox);
}
for (let i = M - m - 1; i >= m; i--) {
const child = node.children[i];
extend(rightBBox, node.leaf ? toBBox(child) : child);
margin += bboxMargin(rightBBox);
}
return margin;
}
_adjustParentBBoxes(bbox, path, level) {
for (let i = level; i >= 0; i--) {
extend(path[i], bbox);
}
}
_condense(path) {
for (let i = path.length - 1, siblings; i >= 0; i--) {
if (path[i].children.length === 0) {
if (i > 0) {
siblings = path[i - 1].children;
siblings.splice(siblings.indexOf(path[i]), 1);
} else this.clear();
} else calcBBox(path[i], this.toBBox);
}
}
};
function findItem(item, items, equalsFn) {
if (!equalsFn) return items.indexOf(item);
for (let i = 0; i < items.length; i++) {
if (equalsFn(item, items[i])) return i;
}
return -1;
}
function calcBBox(node, toBBox) {
distBBox(node, 0, node.children.length, toBBox, node);
}
function distBBox(node, k, p, toBBox, destNode) {
if (!destNode) destNode = createNode2(null);
destNode.minX = Infinity;
destNode.minY = Infinity;
destNode.maxX = -Infinity;
destNode.maxY = -Infinity;
for (let i = k; i < p; i++) {
const child = node.children[i];
extend(destNode, node.leaf ? toBBox(child) : child);
}
return destNode;
}
function extend(a3, b) {
a3.minX = Math.min(a3.minX, b.minX);
a3.minY = Math.min(a3.minY, b.minY);
a3.maxX = Math.max(a3.maxX, b.maxX);
a3.maxY = Math.max(a3.maxY, b.maxY);
return a3;
}
function compareNodeMinX(a3, b) {
return a3.minX - b.minX;
}
function compareNodeMinY(a3, b) {
return a3.minY - b.minY;
}
function bboxArea(a3) {
return (a3.maxX - a3.minX) * (a3.maxY - a3.minY);
}
function bboxMargin(a3) {
return a3.maxX - a3.minX + (a3.maxY - a3.minY);
}
function enlargedArea(a3, b) {
return (Math.max(b.maxX, a3.maxX) - Math.min(b.minX, a3.minX)) * (Math.max(b.maxY, a3.maxY) - Math.min(b.minY, a3.minY));
}
function intersectionArea(a3, b) {
const minX = Math.max(a3.minX, b.minX);
const minY = Math.max(a3.minY, b.minY);
const maxX = Math.min(a3.maxX, b.maxX);
const maxY = Math.min(a3.maxY, b.maxY);
return Math.max(0, maxX - minX) * Math.max(0, maxY - minY);
}
function contains(a3, b) {
return a3.minX <= b.minX && a3.minY <= b.minY && b.maxX <= a3.maxX && b.maxY <= a3.maxY;
}
function intersects2(a3, b) {
return b.minX <= a3.maxX && b.minY <= a3.maxY && b.maxX >= a3.minX && b.maxY >= a3.minY;
}
function createNode2(children) {
return {
children,
height: 1,
leaf: true,
minX: Infinity,
minY: Infinity,
maxX: -Infinity,
maxY: -Infinity
};
}
function multiSelect(arr, left, right, n, compare) {
const stack = [left, right];
while (stack.length) {
right = stack.pop();
left = stack.pop();
if (right - left <= n) continue;
const mid = left + Math.ceil((right - left) / n / 2) * n;
quickselect(arr, mid, left, right, compare);
stack.push(left, mid, mid, right);
}
}
// packages/engine/Source/Core/RectangleCollisionChecker.js
function RectangleCollisionChecker() {
this._tree = new RBush();
}
function RectangleWithId() {
this.minX = 0;
this.minY = 0;
this.maxX = 0;
this.maxY = 0;
this.id = "";
}
RectangleWithId.fromRectangleAndId = function(id, rectangle, result) {
result.minX = rectangle.west;
result.minY = rectangle.south;
result.maxX = rectangle.east;
result.maxY = rectangle.north;
result.id = id;
return result;
};
RectangleCollisionChecker.prototype.insert = function(id, rectangle) {
Check_default.typeOf.string("id", id);
Check_default.typeOf.object("rectangle", rectangle);
const withId = RectangleWithId.fromRectangleAndId(
id,
rectangle,
new RectangleWithId()
);
this._tree.insert(withId);
};
function idCompare(a3, b) {
return a3.id === b.id;
}
var removalScratch = new RectangleWithId();
RectangleCollisionChecker.prototype.remove = function(id, rectangle) {
Check_default.typeOf.string("id", id);
Check_default.typeOf.object("rectangle", rectangle);
const withId = RectangleWithId.fromRectangleAndId(
id,
rectangle,
removalScratch
);
this._tree.remove(withId, idCompare);
};
var collisionScratch = new RectangleWithId();
RectangleCollisionChecker.prototype.collides = function(rectangle) {
Check_default.typeOf.object("rectangle", rectangle);
const withId = RectangleWithId.fromRectangleAndId(
"",
rectangle,
collisionScratch
);
return this._tree.collides(withId);
};
var RectangleCollisionChecker_default = RectangleCollisionChecker;
// packages/engine/Source/DataSources/StaticGroundGeometryColorBatch.js
var colorScratch4 = new Color_default();
var distanceDisplayConditionScratch4 = new DistanceDisplayCondition_default();
var defaultDistanceDisplayCondition4 = new DistanceDisplayCondition_default();
function Batch3(primitives, classificationType, color, zIndex) {
this.primitives = primitives;
this.zIndex = zIndex;
this.classificationType = classificationType;
this.color = color;
this.createPrimitive = false;
this.waitingOnCreate = false;
this.primitive = void 0;
this.oldPrimitive = void 0;
this.geometry = new AssociativeArray_default();
this.updaters = new AssociativeArray_default();
this.updatersWithAttributes = new AssociativeArray_default();
this.attributes = new AssociativeArray_default();
this.subscriptions = new AssociativeArray_default();
this.showsUpdated = new AssociativeArray_default();
this.itemsToRemove = [];
this.isDirty = false;
this.rectangleCollisionCheck = new RectangleCollisionChecker_default();
}
Batch3.prototype.overlapping = function(rectangle) {
return this.rectangleCollisionCheck.collides(rectangle);
};
Batch3.prototype.add = function(updater, instance) {
const id = updater.id;
this.createPrimitive = true;
this.geometry.set(id, instance);
this.updaters.set(id, updater);
this.rectangleCollisionCheck.insert(id, instance.geometry.rectangle);
if (!updater.hasConstantFill || !updater.fillMaterialProperty.isConstant || !Property_default.isConstant(updater.distanceDisplayConditionProperty)) {
this.updatersWithAttributes.set(id, updater);
} else {
const that = this;
this.subscriptions.set(
id,
updater.entity.definitionChanged.addEventListener(
function(entity, propertyName, newValue, oldValue2) {
if (propertyName === "isShowing") {
that.showsUpdated.set(updater.id, updater);
}
}
)
);
}
};
Batch3.prototype.remove = function(updater) {
const id = updater.id;
const geometryInstance = this.geometry.get(id);
this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;
if (this.updaters.remove(id)) {
this.rectangleCollisionCheck.remove(
id,
geometryInstance.geometry.rectangle
);
this.updatersWithAttributes.remove(id);
const unsubscribe2 = this.subscriptions.get(id);
if (defined_default(unsubscribe2)) {
unsubscribe2();
this.subscriptions.remove(id);
this.showsUpdated.remove(id);
}
return true;
}
return false;
};
Batch3.prototype.update = function(time) {
let isUpdated = true;
const removedCount = 0;
let primitive = this.primitive;
const primitives = this.primitives;
let i;
if (this.createPrimitive) {
const geometries = this.geometry.values;
const geometriesLength = geometries.length;
if (geometriesLength > 0) {
if (defined_default(primitive)) {
if (!defined_default(this.oldPrimitive)) {
this.oldPrimitive = primitive;
} else {
primitives.remove(primitive);
}
}
primitive = new GroundPrimitive_default({
show: false,
asynchronous: true,
geometryInstances: geometries.slice(),
classificationType: this.classificationType
});
primitives.add(primitive, this.zIndex);
isUpdated = false;
} else {
if (defined_default(primitive)) {
primitives.remove(primitive);
primitive = void 0;
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
primitives.remove(oldPrimitive);
this.oldPrimitive = void 0;
}
}
this.attributes.removeAll();
this.primitive = primitive;
this.createPrimitive = false;
this.waitingOnCreate = true;
} else if (defined_default(primitive) && primitive.ready) {
primitive.show = true;
if (defined_default(this.oldPrimitive)) {
primitives.remove(this.oldPrimitive);
this.oldPrimitive = void 0;
}
const updatersWithAttributes = this.updatersWithAttributes.values;
const length2 = updatersWithAttributes.length;
const waitingOnCreate = this.waitingOnCreate;
for (i = 0; i < length2; i++) {
const updater = updatersWithAttributes[i];
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
if (!updater.fillMaterialProperty.isConstant || waitingOnCreate) {
const colorProperty = updater.fillMaterialProperty.color;
const fillColor = Property_default.getValueOrDefault(
colorProperty,
time,
Color_default.WHITE,
colorScratch4
);
if (!Color_default.equals(attributes._lastColor, fillColor)) {
attributes._lastColor = Color_default.clone(fillColor, attributes._lastColor);
attributes.color = ColorGeometryInstanceAttribute_default.toValue(
fillColor,
attributes.color
);
}
}
const show = updater.entity.isShowing && (updater.hasConstantFill || updater.isFilled(time));
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
}
const distanceDisplayConditionProperty = updater.distanceDisplayConditionProperty;
if (!Property_default.isConstant(distanceDisplayConditionProperty)) {
const distanceDisplayCondition = Property_default.getValueOrDefault(
distanceDisplayConditionProperty,
time,
defaultDistanceDisplayCondition4,
distanceDisplayConditionScratch4
);
if (!DistanceDisplayCondition_default.equals(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
)) {
attributes._lastDistanceDisplayCondition = DistanceDisplayCondition_default.clone(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
);
attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute_default.toValue(
distanceDisplayCondition,
attributes.distanceDisplayCondition
);
}
}
}
this.updateShows(primitive);
this.waitingOnCreate = false;
} else if (defined_default(primitive) && !primitive.ready) {
isUpdated = false;
}
this.itemsToRemove.length = removedCount;
return isUpdated;
};
Batch3.prototype.updateShows = function(primitive) {
const showsUpdated = this.showsUpdated.values;
const length2 = showsUpdated.length;
for (let i = 0; i < length2; i++) {
const updater = showsUpdated[i];
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
const show = updater.entity.isShowing;
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
instance.attributes.show.value[0] = attributes.show[0];
}
}
this.showsUpdated.removeAll();
};
Batch3.prototype.contains = function(updater) {
return this.updaters.contains(updater.id);
};
Batch3.prototype.getBoundingSphere = function(updater, result) {
const primitive = this.primitive;
if (!primitive.ready) {
return BoundingSphereState_default.PENDING;
}
const bs = primitive.getBoundingSphere(updater.entity);
if (!defined_default(bs)) {
return BoundingSphereState_default.FAILED;
}
bs.clone(result);
return BoundingSphereState_default.DONE;
};
Batch3.prototype.removeAllPrimitives = function() {
const primitives = this.primitives;
const primitive = this.primitive;
if (defined_default(primitive)) {
primitives.remove(primitive);
this.primitive = void 0;
this.geometry.removeAll();
this.updaters.removeAll();
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
primitives.remove(oldPrimitive);
this.oldPrimitive = void 0;
}
};
function StaticGroundGeometryColorBatch(primitives, classificationType) {
this._batches = [];
this._primitives = primitives;
this._classificationType = classificationType;
}
StaticGroundGeometryColorBatch.prototype.add = function(time, updater) {
const instance = updater.createFillGeometryInstance(time);
const batches = this._batches;
const zIndex = Property_default.getValueOrDefault(updater.zIndex, 0);
let batch;
const length2 = batches.length;
for (let i = 0; i < length2; ++i) {
const item = batches[i];
if (item.zIndex === zIndex && !item.overlapping(instance.geometry.rectangle)) {
batch = item;
break;
}
}
if (!defined_default(batch)) {
batch = new Batch3(
this._primitives,
this._classificationType,
instance.attributes.color.value,
zIndex
);
batches.push(batch);
}
batch.add(updater, instance);
return batch;
};
StaticGroundGeometryColorBatch.prototype.remove = function(updater) {
const batches = this._batches;
const count = batches.length;
for (let i = 0; i < count; ++i) {
if (batches[i].remove(updater)) {
return;
}
}
};
StaticGroundGeometryColorBatch.prototype.update = function(time) {
let i;
let updater;
let isUpdated = true;
const batches = this._batches;
const batchCount = batches.length;
for (i = 0; i < batchCount; ++i) {
isUpdated = batches[i].update(time) && isUpdated;
}
for (i = 0; i < batchCount; ++i) {
const oldBatch = batches[i];
const itemsToRemove = oldBatch.itemsToRemove;
const itemsToMoveLength = itemsToRemove.length;
for (let j = 0; j < itemsToMoveLength; j++) {
updater = itemsToRemove[j];
oldBatch.remove(updater);
const newBatch = this.add(time, updater);
oldBatch.isDirty = true;
newBatch.isDirty = true;
}
}
for (i = batchCount - 1; i >= 0; --i) {
const batch = batches[i];
if (batch.isDirty) {
isUpdated = batches[i].update(time) && isUpdated;
batch.isDirty = false;
}
if (batch.geometry.length === 0) {
batches.splice(i, 1);
}
}
return isUpdated;
};
StaticGroundGeometryColorBatch.prototype.getBoundingSphere = function(updater, result) {
const batches = this._batches;
const batchCount = batches.length;
for (let i = 0; i < batchCount; ++i) {
const batch = batches[i];
if (batch.contains(updater)) {
return batch.getBoundingSphere(updater, result);
}
}
return BoundingSphereState_default.FAILED;
};
StaticGroundGeometryColorBatch.prototype.removeAllPrimitives = function() {
const batches = this._batches;
const batchCount = batches.length;
for (let i = 0; i < batchCount; ++i) {
batches[i].removeAllPrimitives();
}
};
var StaticGroundGeometryColorBatch_default = StaticGroundGeometryColorBatch;
// packages/engine/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js
var import_InlineWorkers906 = __toESM(require_InlineWorkers(), 1);
var distanceDisplayConditionScratch5 = new DistanceDisplayCondition_default();
var defaultDistanceDisplayCondition5 = new DistanceDisplayCondition_default();
function Batch4(primitives, classificationType, appearanceType, materialProperty, usingSphericalTextureCoordinates, zIndex) {
this.primitives = primitives;
this.classificationType = classificationType;
this.appearanceType = appearanceType;
this.materialProperty = materialProperty;
this.updaters = new AssociativeArray_default();
this.createPrimitive = true;
this.primitive = void 0;
this.oldPrimitive = void 0;
this.geometry = new AssociativeArray_default();
this.material = void 0;
this.updatersWithAttributes = new AssociativeArray_default();
this.attributes = new AssociativeArray_default();
this.subscriptions = new AssociativeArray_default();
this.showsUpdated = new AssociativeArray_default();
this.usingSphericalTextureCoordinates = usingSphericalTextureCoordinates;
this.zIndex = zIndex;
this.rectangleCollisionCheck = new RectangleCollisionChecker_default();
}
Batch4.prototype.overlapping = function(rectangle) {
return this.rectangleCollisionCheck.collides(rectangle);
};
Batch4.prototype.isMaterial = function(updater) {
const material = this.materialProperty;
const updaterMaterial = updater.fillMaterialProperty;
if (updaterMaterial === material || updaterMaterial instanceof ColorMaterialProperty_default && material instanceof ColorMaterialProperty_default) {
return true;
}
return defined_default(material) && material.equals(updaterMaterial);
};
Batch4.prototype.add = function(time, updater, geometryInstance) {
const id = updater.id;
this.updaters.set(id, updater);
this.geometry.set(id, geometryInstance);
this.rectangleCollisionCheck.insert(id, geometryInstance.geometry.rectangle);
if (!updater.hasConstantFill || !updater.fillMaterialProperty.isConstant || !Property_default.isConstant(updater.distanceDisplayConditionProperty)) {
this.updatersWithAttributes.set(id, updater);
} else {
const that = this;
this.subscriptions.set(
id,
updater.entity.definitionChanged.addEventListener(
function(entity, propertyName, newValue, oldValue2) {
if (propertyName === "isShowing") {
that.showsUpdated.set(updater.id, updater);
}
}
)
);
}
this.createPrimitive = true;
};
Batch4.prototype.remove = function(updater) {
const id = updater.id;
const geometryInstance = this.geometry.get(id);
this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;
if (this.updaters.remove(id)) {
this.rectangleCollisionCheck.remove(
id,
geometryInstance.geometry.rectangle
);
this.updatersWithAttributes.remove(id);
const unsubscribe2 = this.subscriptions.get(id);
if (defined_default(unsubscribe2)) {
unsubscribe2();
this.subscriptions.remove(id);
}
return true;
}
return false;
};
Batch4.prototype.update = function(time) {
let isUpdated = true;
let primitive = this.primitive;
const primitives = this.primitives;
const geometries = this.geometry.values;
let i;
if (this.createPrimitive) {
const geometriesLength = geometries.length;
if (geometriesLength > 0) {
if (defined_default(primitive)) {
if (!defined_default(this.oldPrimitive)) {
this.oldPrimitive = primitive;
} else {
primitives.remove(primitive);
}
}
this.material = MaterialProperty_default.getValue(
time,
this.materialProperty,
this.material
);
primitive = new GroundPrimitive_default({
show: false,
asynchronous: true,
geometryInstances: geometries.slice(),
appearance: new this.appearanceType({
material: this.material
// translucent and closed properties overridden
}),
classificationType: this.classificationType
});
primitives.add(primitive, this.zIndex);
isUpdated = false;
} else {
if (defined_default(primitive)) {
primitives.remove(primitive);
primitive = void 0;
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
primitives.remove(oldPrimitive);
this.oldPrimitive = void 0;
}
}
this.attributes.removeAll();
this.primitive = primitive;
this.createPrimitive = false;
} else if (defined_default(primitive) && primitive.ready) {
primitive.show = true;
if (defined_default(this.oldPrimitive)) {
primitives.remove(this.oldPrimitive);
this.oldPrimitive = void 0;
}
this.material = MaterialProperty_default.getValue(
time,
this.materialProperty,
this.material
);
this.primitive.appearance.material = this.material;
const updatersWithAttributes = this.updatersWithAttributes.values;
const length2 = updatersWithAttributes.length;
for (i = 0; i < length2; i++) {
const updater = updatersWithAttributes[i];
const entity = updater.entity;
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
const show = entity.isShowing && (updater.hasConstantFill || updater.isFilled(time));
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
}
const distanceDisplayConditionProperty = updater.distanceDisplayConditionProperty;
if (!Property_default.isConstant(distanceDisplayConditionProperty)) {
const distanceDisplayCondition = Property_default.getValueOrDefault(
distanceDisplayConditionProperty,
time,
defaultDistanceDisplayCondition5,
distanceDisplayConditionScratch5
);
if (!DistanceDisplayCondition_default.equals(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
)) {
attributes._lastDistanceDisplayCondition = DistanceDisplayCondition_default.clone(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
);
attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute_default.toValue(
distanceDisplayCondition,
attributes.distanceDisplayCondition
);
}
}
}
this.updateShows(primitive);
} else if (defined_default(primitive) && !primitive.ready) {
isUpdated = false;
}
return isUpdated;
};
Batch4.prototype.updateShows = function(primitive) {
const showsUpdated = this.showsUpdated.values;
const length2 = showsUpdated.length;
for (let i = 0; i < length2; i++) {
const updater = showsUpdated[i];
const entity = updater.entity;
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
const show = entity.isShowing;
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
instance.attributes.show.value[0] = attributes.show[0];
}
}
this.showsUpdated.removeAll();
};
Batch4.prototype.contains = function(updater) {
return this.updaters.contains(updater.id);
};
Batch4.prototype.getBoundingSphere = function(updater, result) {
const primitive = this.primitive;
if (!primitive.ready) {
return BoundingSphereState_default.PENDING;
}
const attributes = primitive.getGeometryInstanceAttributes(updater.entity);
if (!defined_default(attributes) || !defined_default(attributes.boundingSphere) || defined_default(attributes.show) && attributes.show[0] === 0) {
return BoundingSphereState_default.FAILED;
}
attributes.boundingSphere.clone(result);
return BoundingSphereState_default.DONE;
};
Batch4.prototype.destroy = function() {
const primitive = this.primitive;
const primitives = this.primitives;
if (defined_default(primitive)) {
primitives.remove(primitive);
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
primitives.remove(oldPrimitive);
}
};
function StaticGroundGeometryPerMaterialBatch(primitives, classificationType, appearanceType) {
this._items = [];
this._primitives = primitives;
this._classificationType = classificationType;
this._appearanceType = appearanceType;
}
StaticGroundGeometryPerMaterialBatch.prototype.add = function(time, updater) {
const items = this._items;
const length2 = items.length;
const geometryInstance = updater.createFillGeometryInstance(time);
const usingSphericalTextureCoordinates = ShadowVolumeAppearance_default.shouldUseSphericalCoordinates(
geometryInstance.geometry.rectangle
);
const zIndex = Property_default.getValueOrDefault(updater.zIndex, 0);
for (let i = 0; i < length2; ++i) {
const item = items[i];
if (item.isMaterial(updater) && item.usingSphericalTextureCoordinates === usingSphericalTextureCoordinates && item.zIndex === zIndex && !item.overlapping(geometryInstance.geometry.rectangle)) {
item.add(time, updater, geometryInstance);
return;
}
}
const batch = new Batch4(
this._primitives,
this._classificationType,
this._appearanceType,
updater.fillMaterialProperty,
usingSphericalTextureCoordinates,
zIndex
);
batch.add(time, updater, geometryInstance);
items.push(batch);
};
StaticGroundGeometryPerMaterialBatch.prototype.remove = function(updater) {
const items = this._items;
const length2 = items.length;
for (let i = length2 - 1; i >= 0; i--) {
const item = items[i];
if (item.remove(updater)) {
break;
}
}
};
StaticGroundGeometryPerMaterialBatch.prototype.update = function(time) {
let i;
const items = this._items;
const length2 = items.length;
for (i = length2 - 1; i >= 0; i--) {
const item = items[i];
if (item.updaters.length === 0) {
items.splice(i, 1);
item.destroy();
}
}
let isUpdated = true;
for (i = 0; i < items.length; i++) {
isUpdated = items[i].update(time) && isUpdated;
}
return isUpdated;
};
StaticGroundGeometryPerMaterialBatch.prototype.getBoundingSphere = function(updater, result) {
const items = this._items;
const length2 = items.length;
for (let i = 0; i < length2; i++) {
const item = items[i];
if (item.contains(updater)) {
return item.getBoundingSphere(updater, result);
}
}
return BoundingSphereState_default.FAILED;
};
StaticGroundGeometryPerMaterialBatch.prototype.removeAllPrimitives = function() {
const items = this._items;
const length2 = items.length;
for (let i = 0; i < length2; i++) {
items[i].destroy();
}
this._items.length = 0;
};
var StaticGroundGeometryPerMaterialBatch_default = StaticGroundGeometryPerMaterialBatch;
// packages/engine/Source/DataSources/StaticOutlineGeometryBatch.js
var import_InlineWorkers907 = __toESM(require_InlineWorkers(), 1);
var colorScratch5 = new Color_default();
var distanceDisplayConditionScratch6 = new DistanceDisplayCondition_default();
var defaultDistanceDisplayCondition6 = new DistanceDisplayCondition_default();
var defaultOffset11 = Cartesian3_default.ZERO;
var offsetScratch13 = new Cartesian3_default();
function Batch5(primitives, translucent, width, shadows) {
this.translucent = translucent;
this.width = width;
this.shadows = shadows;
this.primitives = primitives;
this.createPrimitive = false;
this.waitingOnCreate = false;
this.primitive = void 0;
this.oldPrimitive = void 0;
this.geometry = new AssociativeArray_default();
this.updaters = new AssociativeArray_default();
this.updatersWithAttributes = new AssociativeArray_default();
this.attributes = new AssociativeArray_default();
this.itemsToRemove = [];
this.subscriptions = new AssociativeArray_default();
this.showsUpdated = new AssociativeArray_default();
}
Batch5.prototype.add = function(updater, instance) {
const id = updater.id;
this.createPrimitive = true;
this.geometry.set(id, instance);
this.updaters.set(id, updater);
if (!updater.hasConstantOutline || !updater.outlineColorProperty.isConstant || !Property_default.isConstant(updater.distanceDisplayConditionProperty) || !Property_default.isConstant(updater.terrainOffsetProperty)) {
this.updatersWithAttributes.set(id, updater);
} else {
const that = this;
this.subscriptions.set(
id,
updater.entity.definitionChanged.addEventListener(
function(entity, propertyName, newValue, oldValue2) {
if (propertyName === "isShowing") {
that.showsUpdated.set(updater.id, updater);
}
}
)
);
}
};
Batch5.prototype.remove = function(updater) {
const id = updater.id;
this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;
if (this.updaters.remove(id)) {
this.updatersWithAttributes.remove(id);
const unsubscribe2 = this.subscriptions.get(id);
if (defined_default(unsubscribe2)) {
unsubscribe2();
this.subscriptions.remove(id);
this.showsUpdated.remove(id);
}
return true;
}
return false;
};
Batch5.prototype.update = function(time) {
let isUpdated = true;
let removedCount = 0;
let primitive = this.primitive;
const primitives = this.primitives;
let i;
if (this.createPrimitive) {
const geometries = this.geometry.values;
const geometriesLength = geometries.length;
if (geometriesLength > 0) {
if (defined_default(primitive)) {
if (!defined_default(this.oldPrimitive)) {
this.oldPrimitive = primitive;
} else {
primitives.remove(primitive);
}
}
primitive = new Primitive_default({
show: false,
asynchronous: true,
geometryInstances: geometries.slice(),
appearance: new PerInstanceColorAppearance_default({
flat: true,
translucent: this.translucent,
renderState: {
lineWidth: this.width
}
}),
shadows: this.shadows
});
primitives.add(primitive);
isUpdated = false;
} else {
if (defined_default(primitive)) {
primitives.remove(primitive);
primitive = void 0;
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
primitives.remove(oldPrimitive);
this.oldPrimitive = void 0;
}
}
this.attributes.removeAll();
this.primitive = primitive;
this.createPrimitive = false;
this.waitingOnCreate = true;
} else if (defined_default(primitive) && primitive.ready) {
primitive.show = true;
if (defined_default(this.oldPrimitive)) {
primitives.remove(this.oldPrimitive);
this.oldPrimitive = void 0;
}
const updatersWithAttributes = this.updatersWithAttributes.values;
const length2 = updatersWithAttributes.length;
const waitingOnCreate = this.waitingOnCreate;
for (i = 0; i < length2; i++) {
const updater = updatersWithAttributes[i];
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
if (!updater.outlineColorProperty.isConstant || waitingOnCreate) {
const outlineColorProperty = updater.outlineColorProperty;
const outlineColor = Property_default.getValueOrDefault(
outlineColorProperty,
time,
Color_default.WHITE,
colorScratch5
);
if (!Color_default.equals(attributes._lastColor, outlineColor)) {
attributes._lastColor = Color_default.clone(
outlineColor,
attributes._lastColor
);
attributes.color = ColorGeometryInstanceAttribute_default.toValue(
outlineColor,
attributes.color
);
if (this.translucent && attributes.color[3] === 255 || !this.translucent && attributes.color[3] !== 255) {
this.itemsToRemove[removedCount++] = updater;
}
}
}
const show = updater.entity.isShowing && (updater.hasConstantOutline || updater.isOutlineVisible(time));
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
}
const distanceDisplayConditionProperty = updater.distanceDisplayConditionProperty;
if (!Property_default.isConstant(distanceDisplayConditionProperty)) {
const distanceDisplayCondition = Property_default.getValueOrDefault(
distanceDisplayConditionProperty,
time,
defaultDistanceDisplayCondition6,
distanceDisplayConditionScratch6
);
if (!DistanceDisplayCondition_default.equals(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
)) {
attributes._lastDistanceDisplayCondition = DistanceDisplayCondition_default.clone(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
);
attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute_default.toValue(
distanceDisplayCondition,
attributes.distanceDisplayCondition
);
}
}
const offsetProperty = updater.terrainOffsetProperty;
if (!Property_default.isConstant(offsetProperty)) {
const offset = Property_default.getValueOrDefault(
offsetProperty,
time,
defaultOffset11,
offsetScratch13
);
if (!Cartesian3_default.equals(offset, attributes._lastOffset)) {
attributes._lastOffset = Cartesian3_default.clone(
offset,
attributes._lastOffset
);
attributes.offset = OffsetGeometryInstanceAttribute_default.toValue(
offset,
attributes.offset
);
}
}
}
this.updateShows(primitive);
this.waitingOnCreate = false;
} else if (defined_default(primitive) && !primitive.ready) {
isUpdated = false;
}
this.itemsToRemove.length = removedCount;
return isUpdated;
};
Batch5.prototype.updateShows = function(primitive) {
const showsUpdated = this.showsUpdated.values;
const length2 = showsUpdated.length;
for (let i = 0; i < length2; i++) {
const updater = showsUpdated[i];
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
const show = updater.entity.isShowing;
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
instance.attributes.show.value[0] = attributes.show[0];
}
}
this.showsUpdated.removeAll();
};
Batch5.prototype.contains = function(updater) {
return this.updaters.contains(updater.id);
};
Batch5.prototype.getBoundingSphere = function(updater, result) {
const primitive = this.primitive;
if (!primitive.ready) {
return BoundingSphereState_default.PENDING;
}
const attributes = primitive.getGeometryInstanceAttributes(updater.entity);
if (!defined_default(attributes) || !defined_default(attributes.boundingSphere) || //
defined_default(attributes.show) && attributes.show[0] === 0) {
return BoundingSphereState_default.FAILED;
}
attributes.boundingSphere.clone(result);
return BoundingSphereState_default.DONE;
};
Batch5.prototype.removeAllPrimitives = function() {
const primitives = this.primitives;
const primitive = this.primitive;
if (defined_default(primitive)) {
primitives.remove(primitive);
this.primitive = void 0;
this.geometry.removeAll();
this.updaters.removeAll();
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
primitives.remove(oldPrimitive);
this.oldPrimitive = void 0;
}
};
function StaticOutlineGeometryBatch(primitives, scene, shadows) {
this._primitives = primitives;
this._scene = scene;
this._shadows = shadows;
this._solidBatches = new AssociativeArray_default();
this._translucentBatches = new AssociativeArray_default();
}
StaticOutlineGeometryBatch.prototype.add = function(time, updater) {
const instance = updater.createOutlineGeometryInstance(time);
const width = this._scene.clampLineWidth(updater.outlineWidth);
let batches;
let batch;
if (instance.attributes.color.value[3] === 255) {
batches = this._solidBatches;
batch = batches.get(width);
if (!defined_default(batch)) {
batch = new Batch5(this._primitives, false, width, this._shadows);
batches.set(width, batch);
}
batch.add(updater, instance);
} else {
batches = this._translucentBatches;
batch = batches.get(width);
if (!defined_default(batch)) {
batch = new Batch5(this._primitives, true, width, this._shadows);
batches.set(width, batch);
}
batch.add(updater, instance);
}
};
StaticOutlineGeometryBatch.prototype.remove = function(updater) {
let i;
const solidBatches = this._solidBatches.values;
const solidBatchesLength = solidBatches.length;
for (i = 0; i < solidBatchesLength; i++) {
if (solidBatches[i].remove(updater)) {
return;
}
}
const translucentBatches = this._translucentBatches.values;
const translucentBatchesLength = translucentBatches.length;
for (i = 0; i < translucentBatchesLength; i++) {
if (translucentBatches[i].remove(updater)) {
return;
}
}
};
StaticOutlineGeometryBatch.prototype.update = function(time) {
let i;
let x;
let updater;
let batch;
const solidBatches = this._solidBatches.values;
const solidBatchesLength = solidBatches.length;
const translucentBatches = this._translucentBatches.values;
const translucentBatchesLength = translucentBatches.length;
let itemsToRemove;
let isUpdated = true;
let needUpdate = false;
do {
needUpdate = false;
for (x = 0; x < solidBatchesLength; x++) {
batch = solidBatches[x];
isUpdated = batch.update(time);
itemsToRemove = batch.itemsToRemove;
const solidsToMoveLength = itemsToRemove.length;
if (solidsToMoveLength > 0) {
needUpdate = true;
for (i = 0; i < solidsToMoveLength; i++) {
updater = itemsToRemove[i];
batch.remove(updater);
this.add(time, updater);
}
}
}
for (x = 0; x < translucentBatchesLength; x++) {
batch = translucentBatches[x];
isUpdated = batch.update(time);
itemsToRemove = batch.itemsToRemove;
const translucentToMoveLength = itemsToRemove.length;
if (translucentToMoveLength > 0) {
needUpdate = true;
for (i = 0; i < translucentToMoveLength; i++) {
updater = itemsToRemove[i];
batch.remove(updater);
this.add(time, updater);
}
}
}
} while (needUpdate);
return isUpdated;
};
StaticOutlineGeometryBatch.prototype.getBoundingSphere = function(updater, result) {
let i;
const solidBatches = this._solidBatches.values;
const solidBatchesLength = solidBatches.length;
for (i = 0; i < solidBatchesLength; i++) {
const solidBatch = solidBatches[i];
if (solidBatch.contains(updater)) {
return solidBatch.getBoundingSphere(updater, result);
}
}
const translucentBatches = this._translucentBatches.values;
const translucentBatchesLength = translucentBatches.length;
for (i = 0; i < translucentBatchesLength; i++) {
const translucentBatch = translucentBatches[i];
if (translucentBatch.contains(updater)) {
return translucentBatch.getBoundingSphere(updater, result);
}
}
return BoundingSphereState_default.FAILED;
};
StaticOutlineGeometryBatch.prototype.removeAllPrimitives = function() {
let i;
const solidBatches = this._solidBatches.values;
const solidBatchesLength = solidBatches.length;
for (i = 0; i < solidBatchesLength; i++) {
solidBatches[i].removeAllPrimitives();
}
const translucentBatches = this._translucentBatches.values;
const translucentBatchesLength = translucentBatches.length;
for (i = 0; i < translucentBatchesLength; i++) {
translucentBatches[i].removeAllPrimitives();
}
};
var StaticOutlineGeometryBatch_default = StaticOutlineGeometryBatch;
// packages/engine/Source/DataSources/GeometryVisualizer.js
var emptyArray = [];
function GeometryVisualizer(scene, entityCollection, primitives, groundPrimitives) {
Check_default.defined("scene", scene);
Check_default.defined("entityCollection", entityCollection);
primitives = primitives ?? scene.primitives;
groundPrimitives = groundPrimitives ?? scene.groundPrimitives;
this._scene = scene;
this._primitives = primitives;
this._groundPrimitives = groundPrimitives;
this._entityCollection = void 0;
this._addedObjects = new AssociativeArray_default();
this._removedObjects = new AssociativeArray_default();
this._changedObjects = new AssociativeArray_default();
const numberOfShadowModes = ShadowMode_default.NUMBER_OF_SHADOW_MODES;
this._outlineBatches = new Array(numberOfShadowModes * 2);
this._closedColorBatches = new Array(numberOfShadowModes * 2);
this._closedMaterialBatches = new Array(numberOfShadowModes * 2);
this._openColorBatches = new Array(numberOfShadowModes * 2);
this._openMaterialBatches = new Array(numberOfShadowModes * 2);
const supportsMaterialsforEntitiesOnTerrain = Entity_default.supportsMaterialsforEntitiesOnTerrain(scene);
this._supportsMaterialsforEntitiesOnTerrain = supportsMaterialsforEntitiesOnTerrain;
let i;
for (i = 0; i < numberOfShadowModes; ++i) {
this._outlineBatches[i] = new StaticOutlineGeometryBatch_default(
primitives,
scene,
i,
false
);
this._outlineBatches[numberOfShadowModes + i] = new StaticOutlineGeometryBatch_default(primitives, scene, i, true);
this._closedColorBatches[i] = new StaticGeometryColorBatch_default(
primitives,
PerInstanceColorAppearance_default,
void 0,
true,
i,
true
);
this._closedColorBatches[numberOfShadowModes + i] = new StaticGeometryColorBatch_default(
primitives,
PerInstanceColorAppearance_default,
void 0,
true,
i,
false
);
this._closedMaterialBatches[i] = new StaticGeometryPerMaterialBatch_default(
primitives,
MaterialAppearance_default,
void 0,
true,
i,
true
);
this._closedMaterialBatches[numberOfShadowModes + i] = new StaticGeometryPerMaterialBatch_default(
primitives,
MaterialAppearance_default,
void 0,
true,
i,
false
);
this._openColorBatches[i] = new StaticGeometryColorBatch_default(
primitives,
PerInstanceColorAppearance_default,
void 0,
false,
i,
true
);
this._openColorBatches[numberOfShadowModes + i] = new StaticGeometryColorBatch_default(
primitives,
PerInstanceColorAppearance_default,
void 0,
false,
i,
false
);
this._openMaterialBatches[i] = new StaticGeometryPerMaterialBatch_default(
primitives,
MaterialAppearance_default,
void 0,
false,
i,
true
);
this._openMaterialBatches[numberOfShadowModes + i] = new StaticGeometryPerMaterialBatch_default(
primitives,
MaterialAppearance_default,
void 0,
false,
i,
false
);
}
const numberOfClassificationTypes = ClassificationType_default.NUMBER_OF_CLASSIFICATION_TYPES;
const groundColorBatches = new Array(numberOfClassificationTypes);
const groundMaterialBatches = [];
if (supportsMaterialsforEntitiesOnTerrain) {
for (i = 0; i < numberOfClassificationTypes; ++i) {
groundMaterialBatches.push(
new StaticGroundGeometryPerMaterialBatch_default(
groundPrimitives,
i,
MaterialAppearance_default
)
);
groundColorBatches[i] = new StaticGroundGeometryColorBatch_default(
groundPrimitives,
i
);
}
} else {
for (i = 0; i < numberOfClassificationTypes; ++i) {
groundColorBatches[i] = new StaticGroundGeometryColorBatch_default(
groundPrimitives,
i
);
}
}
this._groundColorBatches = groundColorBatches;
this._groundMaterialBatches = groundMaterialBatches;
this._dynamicBatch = new DynamicGeometryBatch_default(primitives, groundPrimitives);
this._batches = this._outlineBatches.concat(
this._closedColorBatches,
this._closedMaterialBatches,
this._openColorBatches,
this._openMaterialBatches,
this._groundColorBatches,
this._groundMaterialBatches,
this._dynamicBatch
);
this._subscriptions = new AssociativeArray_default();
this._updaterSets = new AssociativeArray_default();
this._entityCollection = entityCollection;
entityCollection.collectionChanged.addEventListener(
GeometryVisualizer.prototype._onCollectionChanged,
this
);
this._onCollectionChanged(
entityCollection,
entityCollection.values,
emptyArray
);
}
GeometryVisualizer.registerUpdater = function(updater) {
GeometryUpdaterSet_default.registerUpdater(updater);
};
GeometryVisualizer.unregisterUpdater = function(updater) {
GeometryUpdaterSet_default.unregisterUpdater(updater);
};
GeometryVisualizer.prototype.update = function(time) {
Check_default.defined("time", time);
const addedObjects = this._addedObjects;
const added = addedObjects.values;
const removedObjects = this._removedObjects;
const removed = removedObjects.values;
const changedObjects = this._changedObjects;
const changed = changedObjects.values;
let i;
let entity;
let id;
let updaterSet;
const that = this;
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i];
id = entity.id;
updaterSet = this._updaterSets.get(id);
if (updaterSet.entity === entity) {
updaterSet.forEach(function(updater) {
that._removeUpdater(updater);
that._insertUpdaterIntoBatch(time, updater);
});
} else {
removed.push(entity);
added.push(entity);
}
}
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i];
id = entity.id;
updaterSet = this._updaterSets.get(id);
updaterSet.forEach(this._removeUpdater.bind(this));
updaterSet.destroy();
this._updaterSets.remove(id);
this._subscriptions.get(id)();
this._subscriptions.remove(id);
}
for (i = added.length - 1; i > -1; i--) {
entity = added[i];
id = entity.id;
updaterSet = new GeometryUpdaterSet_default(entity, this._scene);
this._updaterSets.set(id, updaterSet);
updaterSet.forEach(function(updater) {
that._insertUpdaterIntoBatch(time, updater);
});
this._subscriptions.set(
id,
updaterSet.geometryChanged.addEventListener(
GeometryVisualizer._onGeometryChanged,
this
)
);
}
addedObjects.removeAll();
removedObjects.removeAll();
changedObjects.removeAll();
let isUpdated = true;
const batches = this._batches;
const length2 = batches.length;
for (i = 0; i < length2; i++) {
isUpdated = batches[i].update(time) && isUpdated;
}
return isUpdated;
};
var getBoundingSphereArrayScratch = [];
var getBoundingSphereBoundingSphereScratch = new BoundingSphere_default();
GeometryVisualizer.prototype.getBoundingSphere = function(entity, result) {
Check_default.defined("entity", entity);
Check_default.defined("result", result);
const boundingSpheres = getBoundingSphereArrayScratch;
const tmp2 = getBoundingSphereBoundingSphereScratch;
let count = 0;
let state = BoundingSphereState_default.DONE;
const batches = this._batches;
const batchesLength = batches.length;
const id = entity.id;
const updaters = this._updaterSets.get(id).updaters;
for (let j = 0; j < updaters.length; j++) {
const updater = updaters[j];
for (let i = 0; i < batchesLength; i++) {
state = batches[i].getBoundingSphere(updater, tmp2);
if (state === BoundingSphereState_default.PENDING) {
return BoundingSphereState_default.PENDING;
} else if (state === BoundingSphereState_default.DONE) {
boundingSpheres[count] = BoundingSphere_default.clone(
tmp2,
boundingSpheres[count]
);
count++;
}
}
}
if (count === 0) {
return BoundingSphereState_default.FAILED;
}
boundingSpheres.length = count;
BoundingSphere_default.fromBoundingSpheres(boundingSpheres, result);
return BoundingSphereState_default.DONE;
};
GeometryVisualizer.prototype.isDestroyed = function() {
return false;
};
GeometryVisualizer.prototype.destroy = function() {
this._entityCollection.collectionChanged.removeEventListener(
GeometryVisualizer.prototype._onCollectionChanged,
this
);
this._addedObjects.removeAll();
this._removedObjects.removeAll();
let i;
const batches = this._batches;
let length2 = batches.length;
for (i = 0; i < length2; i++) {
batches[i].removeAllPrimitives();
}
const subscriptions = this._subscriptions.values;
length2 = subscriptions.length;
for (i = 0; i < length2; i++) {
subscriptions[i]();
}
this._subscriptions.removeAll();
const updaterSets = this._updaterSets.values;
length2 = updaterSets.length;
for (i = 0; i < length2; i++) {
updaterSets[i].destroy();
}
this._updaterSets.removeAll();
return destroyObject_default(this);
};
GeometryVisualizer.prototype._removeUpdater = function(updater) {
const batches = this._batches;
const length2 = batches.length;
for (let i = 0; i < length2; i++) {
batches[i].remove(updater);
}
};
GeometryVisualizer.prototype._insertUpdaterIntoBatch = function(time, updater) {
if (updater.isDynamic) {
this._dynamicBatch.add(time, updater);
return;
}
let shadows;
if (updater.outlineEnabled || updater.fillEnabled) {
shadows = updater.shadowsProperty.getValue(time);
}
const numberOfShadowModes = ShadowMode_default.NUMBER_OF_SHADOW_MODES;
if (updater.outlineEnabled) {
if (defined_default(updater.terrainOffsetProperty)) {
this._outlineBatches[numberOfShadowModes + shadows].add(time, updater);
} else {
this._outlineBatches[shadows].add(time, updater);
}
}
if (updater.fillEnabled) {
if (updater.onTerrain) {
const classificationType = updater.classificationTypeProperty.getValue(time);
if (updater.fillMaterialProperty instanceof ColorMaterialProperty_default) {
this._groundColorBatches[classificationType].add(time, updater);
} else {
this._groundMaterialBatches[classificationType].add(time, updater);
}
} else if (updater.isClosed) {
if (updater.fillMaterialProperty instanceof ColorMaterialProperty_default) {
if (defined_default(updater.terrainOffsetProperty)) {
this._closedColorBatches[numberOfShadowModes + shadows].add(
time,
updater
);
} else {
this._closedColorBatches[shadows].add(time, updater);
}
} else if (defined_default(updater.terrainOffsetProperty)) {
this._closedMaterialBatches[numberOfShadowModes + shadows].add(
time,
updater
);
} else {
this._closedMaterialBatches[shadows].add(time, updater);
}
} else if (updater.fillMaterialProperty instanceof ColorMaterialProperty_default) {
if (defined_default(updater.terrainOffsetProperty)) {
this._openColorBatches[numberOfShadowModes + shadows].add(
time,
updater
);
} else {
this._openColorBatches[shadows].add(time, updater);
}
} else if (defined_default(updater.terrainOffsetProperty)) {
this._openMaterialBatches[numberOfShadowModes + shadows].add(
time,
updater
);
} else {
this._openMaterialBatches[shadows].add(time, updater);
}
}
};
GeometryVisualizer._onGeometryChanged = function(updater) {
const removedObjects = this._removedObjects;
const changedObjects = this._changedObjects;
const entity = updater.entity;
const id = entity.id;
if (!defined_default(removedObjects.get(id)) && !defined_default(changedObjects.get(id))) {
changedObjects.set(id, entity);
}
};
GeometryVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed) {
const addedObjects = this._addedObjects;
const removedObjects = this._removedObjects;
const changedObjects = this._changedObjects;
let i;
let id;
let entity;
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i];
id = entity.id;
if (!addedObjects.remove(id)) {
removedObjects.set(id, entity);
changedObjects.remove(id);
}
}
for (i = added.length - 1; i > -1; i--) {
entity = added[i];
id = entity.id;
if (removedObjects.remove(id)) {
changedObjects.set(id, entity);
} else {
addedObjects.set(id, entity);
}
}
};
var GeometryVisualizer_default = GeometryVisualizer;
// packages/engine/Source/DataSources/LabelVisualizer.js
var import_InlineWorkers909 = __toESM(require_InlineWorkers(), 1);
var defaultScale4 = 1;
var defaultFont = "30px sans-serif";
var defaultStyle = LabelStyle_default.FILL;
var defaultFillColor = Color_default.WHITE;
var defaultOutlineColor3 = Color_default.BLACK;
var defaultOutlineWidth2 = 1;
var defaultShowBackground = false;
var defaultBackgroundColor2 = new Color_default(0.165, 0.165, 0.165, 0.8);
var defaultBackgroundPadding2 = new Cartesian2_default(7, 5);
var defaultPixelOffset2 = Cartesian2_default.ZERO;
var defaultEyeOffset2 = Cartesian3_default.ZERO;
var defaultHeightReference2 = HeightReference_default.NONE;
var defaultHorizontalOrigin2 = HorizontalOrigin_default.CENTER;
var defaultVerticalOrigin2 = VerticalOrigin_default.CENTER;
var positionScratch13 = new Cartesian3_default();
var fillColorScratch = new Color_default();
var outlineColorScratch = new Color_default();
var backgroundColorScratch = new Color_default();
var backgroundPaddingScratch = new Cartesian2_default();
var eyeOffsetScratch2 = new Cartesian3_default();
var pixelOffsetScratch2 = new Cartesian2_default();
var translucencyByDistanceScratch2 = new NearFarScalar_default();
var pixelOffsetScaleByDistanceScratch2 = new NearFarScalar_default();
var scaleByDistanceScratch2 = new NearFarScalar_default();
var distanceDisplayConditionScratch7 = new DistanceDisplayCondition_default();
function EntityData2(entity) {
this.entity = entity;
this.label = void 0;
this.index = void 0;
}
function LabelVisualizer(entityCluster, entityCollection) {
if (!defined_default(entityCluster)) {
throw new DeveloperError_default("entityCluster is required.");
}
if (!defined_default(entityCollection)) {
throw new DeveloperError_default("entityCollection is required.");
}
entityCollection.collectionChanged.addEventListener(
LabelVisualizer.prototype._onCollectionChanged,
this
);
this._cluster = entityCluster;
this._entityCollection = entityCollection;
this._items = new AssociativeArray_default();
this._onCollectionChanged(entityCollection, entityCollection.values, [], []);
}
LabelVisualizer.prototype.update = function(time) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required.");
}
const items = this._items.values;
const cluster = this._cluster;
for (let i = 0, len = items.length; i < len; i++) {
const item = items[i];
const entity = item.entity;
const labelGraphics = entity._label;
let text2;
let label = item.label;
let show = entity.isShowing && entity.isAvailable(time) && Property_default.getValueOrDefault(labelGraphics._show, time, true);
let position;
if (show) {
position = Property_default.getValueOrUndefined(
entity._position,
time,
positionScratch13
);
text2 = Property_default.getValueOrUndefined(labelGraphics._text, time);
show = defined_default(position) && defined_default(text2);
}
if (!show) {
returnPrimitive2(item, entity, cluster);
continue;
}
if (!Property_default.isConstant(entity._position)) {
cluster._clusterDirty = true;
}
let updateClamping2 = false;
const heightReference = Property_default.getValueOrDefault(
labelGraphics._heightReference,
time,
defaultHeightReference2
);
if (!defined_default(label)) {
label = cluster.getLabel(entity);
label.id = entity;
item.label = label;
updateClamping2 = Cartesian3_default.equals(label.position, position) && label.heightReference === heightReference;
}
label.show = true;
label.position = position;
label.text = text2;
label.scale = Property_default.getValueOrDefault(
labelGraphics._scale,
time,
defaultScale4
);
label.font = Property_default.getValueOrDefault(
labelGraphics._font,
time,
defaultFont
);
label.style = Property_default.getValueOrDefault(
labelGraphics._style,
time,
defaultStyle
);
label.fillColor = Property_default.getValueOrDefault(
labelGraphics._fillColor,
time,
defaultFillColor,
fillColorScratch
);
label.outlineColor = Property_default.getValueOrDefault(
labelGraphics._outlineColor,
time,
defaultOutlineColor3,
outlineColorScratch
);
label.outlineWidth = Property_default.getValueOrDefault(
labelGraphics._outlineWidth,
time,
defaultOutlineWidth2
);
label.showBackground = Property_default.getValueOrDefault(
labelGraphics._showBackground,
time,
defaultShowBackground
);
label.backgroundColor = Property_default.getValueOrDefault(
labelGraphics._backgroundColor,
time,
defaultBackgroundColor2,
backgroundColorScratch
);
label.backgroundPadding = Property_default.getValueOrDefault(
labelGraphics._backgroundPadding,
time,
defaultBackgroundPadding2,
backgroundPaddingScratch
);
label.pixelOffset = Property_default.getValueOrDefault(
labelGraphics._pixelOffset,
time,
defaultPixelOffset2,
pixelOffsetScratch2
);
label.eyeOffset = Property_default.getValueOrDefault(
labelGraphics._eyeOffset,
time,
defaultEyeOffset2,
eyeOffsetScratch2
);
label.heightReference = heightReference;
label.horizontalOrigin = Property_default.getValueOrDefault(
labelGraphics._horizontalOrigin,
time,
defaultHorizontalOrigin2
);
label.verticalOrigin = Property_default.getValueOrDefault(
labelGraphics._verticalOrigin,
time,
defaultVerticalOrigin2
);
label.translucencyByDistance = Property_default.getValueOrUndefined(
labelGraphics._translucencyByDistance,
time,
translucencyByDistanceScratch2
);
label.pixelOffsetScaleByDistance = Property_default.getValueOrUndefined(
labelGraphics._pixelOffsetScaleByDistance,
time,
pixelOffsetScaleByDistanceScratch2
);
label.scaleByDistance = Property_default.getValueOrUndefined(
labelGraphics._scaleByDistance,
time,
scaleByDistanceScratch2
);
label.distanceDisplayCondition = Property_default.getValueOrUndefined(
labelGraphics._distanceDisplayCondition,
time,
distanceDisplayConditionScratch7
);
label.disableDepthTestDistance = Property_default.getValueOrUndefined(
labelGraphics._disableDepthTestDistance,
time
);
if (updateClamping2) {
label._updateClamping();
}
}
return true;
};
LabelVisualizer.prototype.getBoundingSphere = function(entity, result) {
if (!defined_default(entity)) {
throw new DeveloperError_default("entity is required.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
const item = this._items.get(entity.id);
if (!defined_default(item) || !defined_default(item.label)) {
return BoundingSphereState_default.FAILED;
}
const label = item.label;
result.center = Cartesian3_default.clone(
label._clampedPosition ?? label.position,
result.center
);
result.radius = 0;
return BoundingSphereState_default.DONE;
};
LabelVisualizer.prototype.isDestroyed = function() {
return false;
};
LabelVisualizer.prototype.destroy = function() {
this._entityCollection.collectionChanged.removeEventListener(
LabelVisualizer.prototype._onCollectionChanged,
this
);
const entities = this._entityCollection.values;
for (let i = 0; i < entities.length; i++) {
this._cluster.removeLabel(entities[i]);
}
return destroyObject_default(this);
};
LabelVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed, changed) {
let i;
let entity;
const items = this._items;
const cluster = this._cluster;
for (i = added.length - 1; i > -1; i--) {
entity = added[i];
if (defined_default(entity._label) && defined_default(entity._position)) {
items.set(entity.id, new EntityData2(entity));
}
}
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i];
if (defined_default(entity._label) && defined_default(entity._position)) {
if (!items.contains(entity.id)) {
items.set(entity.id, new EntityData2(entity));
}
} else {
returnPrimitive2(items.get(entity.id), entity, cluster);
items.remove(entity.id);
}
}
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i];
returnPrimitive2(items.get(entity.id), entity, cluster);
items.remove(entity.id);
}
};
function returnPrimitive2(item, entity, cluster) {
if (defined_default(item)) {
item.label = void 0;
cluster.removeLabel(entity);
}
}
var LabelVisualizer_default = LabelVisualizer;
// packages/engine/Source/DataSources/ModelVisualizer.js
var import_InlineWorkers910 = __toESM(require_InlineWorkers(), 1);
var defaultScale5 = 1;
var defaultEnableVerticalExaggeration = true;
var defaultMinimumPixelSize = 0;
var defaultIncrementallyLoadTextures = true;
var defaultClampAnimations = true;
var defaultShadows2 = ShadowMode_default.ENABLED;
var defaultHeightReference3 = HeightReference_default.NONE;
var defaultSilhouetteColor = Color_default.RED;
var defaultSilhouetteSize = 0;
var defaultColor7 = Color_default.WHITE;
var defaultColorBlendMode = ColorBlendMode_default.HIGHLIGHT;
var defaultColorBlendAmount = 0.5;
var defaultImageBasedLightingFactor = new Cartesian2_default(1, 1);
var defaultEnvironmentMapOptions = {
maximumPositionEpsilon: Number.POSITIVE_INFINITY
};
var modelMatrixScratch3 = new Matrix4_default();
var nodeMatrixScratch = new Matrix4_default();
var scratchColor23 = new Color_default();
var scratchArray = new Array(4);
var scratchCartesian20 = new Cartesian3_default();
function ModelVisualizer(scene, entityCollection) {
Check_default.typeOf.object("scene", scene);
Check_default.typeOf.object("entityCollection", entityCollection);
entityCollection.collectionChanged.addEventListener(
ModelVisualizer.prototype._onCollectionChanged,
this
);
this._scene = scene;
this._primitives = scene.primitives;
this._entityCollection = entityCollection;
this._modelHash = {};
this._entitiesToVisualize = new AssociativeArray_default();
this._onCollectionChanged(entityCollection, entityCollection.values, [], []);
}
async function createModelPrimitive(visualizer, entity, resource, incrementallyLoadTextures, environmentMapOptions) {
const primitives = visualizer._primitives;
const modelHash = visualizer._modelHash;
try {
const model = await Model_default.fromGltfAsync({
url: resource,
incrementallyLoadTextures,
scene: visualizer._scene,
environmentMapOptions
});
if (visualizer.isDestroyed() || !defined_default(modelHash[entity.id])) {
return;
}
model.id = entity;
primitives.add(model);
modelHash[entity.id].modelPrimitive = model;
model.errorEvent.addEventListener((error) => {
if (!defined_default(modelHash[entity.id])) {
return;
}
console.log(error);
if (error.name !== "TextureError" && model.incrementallyLoadTextures) {
modelHash[entity.id].loadFailed = true;
}
});
} catch (error) {
if (visualizer.isDestroyed() || !defined_default(modelHash[entity.id])) {
return;
}
console.log(error);
modelHash[entity.id].loadFailed = true;
}
}
ModelVisualizer.prototype.update = function(time) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required.");
}
const entities = this._entitiesToVisualize.values;
const modelHash = this._modelHash;
const primitives = this._primitives;
for (let i = 0, len = entities.length; i < len; i++) {
const entity = entities[i];
const modelGraphics = entity._model;
let resource;
let modelData = modelHash[entity.id];
let show = entity.isShowing && entity.isAvailable(time) && Property_default.getValueOrDefault(modelGraphics._show, time, true);
let modelMatrix;
if (show) {
modelMatrix = entity.computeModelMatrix(time, modelMatrixScratch3);
resource = Resource_default.createIfNeeded(
Property_default.getValueOrUndefined(modelGraphics._uri, time)
);
show = defined_default(modelMatrix) && defined_default(resource);
}
if (!show) {
if (defined_default(modelData) && modelData.modelPrimitive) {
modelData.modelPrimitive.show = false;
}
continue;
}
if (!defined_default(modelData) || resource.url !== modelData.url) {
if (defined_default(modelData?.modelPrimitive)) {
primitives.removeAndDestroy(modelData.modelPrimitive);
delete modelHash[entity.id];
}
modelData = {
modelPrimitive: void 0,
url: resource.url,
animationsRunning: false,
nodeTransformationsScratch: {},
articulationsScratch: {},
loadFailed: false,
modelUpdated: false,
environmentMapOptionsScratch: {
...defaultEnvironmentMapOptions
}
};
modelHash[entity.id] = modelData;
const incrementallyLoadTextures = Property_default.getValueOrDefault(
modelGraphics._incrementallyLoadTextures,
time,
defaultIncrementallyLoadTextures
);
const environmentMapOptions = Property_default.getValueOrDefault(
modelGraphics._environmentMapOptions,
time,
defaultEnvironmentMapOptions,
modelData.environmentMapOptionsScratch
);
createModelPrimitive(
this,
entity,
resource,
incrementallyLoadTextures,
environmentMapOptions
);
}
const model = modelData.modelPrimitive;
if (!defined_default(model)) {
continue;
}
model.show = true;
model.scale = Property_default.getValueOrDefault(
modelGraphics._scale,
time,
defaultScale5
);
model.enableVerticalExaggeration = Property_default.getValueOrDefault(
modelGraphics._enableVerticalExaggeration,
time,
defaultEnableVerticalExaggeration
);
model.minimumPixelSize = Property_default.getValueOrDefault(
modelGraphics._minimumPixelSize,
time,
defaultMinimumPixelSize
);
model.maximumScale = Property_default.getValueOrUndefined(
modelGraphics._maximumScale,
time
);
model.modelMatrix = Matrix4_default.clone(modelMatrix, model.modelMatrix);
model.shadows = Property_default.getValueOrDefault(
modelGraphics._shadows,
time,
defaultShadows2
);
model.heightReference = Property_default.getValueOrDefault(
modelGraphics._heightReference,
time,
defaultHeightReference3
);
model.distanceDisplayCondition = Property_default.getValueOrUndefined(
modelGraphics._distanceDisplayCondition,
time
);
model.silhouetteColor = Property_default.getValueOrDefault(
modelGraphics._silhouetteColor,
time,
defaultSilhouetteColor,
scratchColor23
);
model.silhouetteSize = Property_default.getValueOrDefault(
modelGraphics._silhouetteSize,
time,
defaultSilhouetteSize
);
model.color = Property_default.getValueOrDefault(
modelGraphics._color,
time,
defaultColor7,
scratchColor23
);
model.colorBlendMode = Property_default.getValueOrDefault(
modelGraphics._colorBlendMode,
time,
defaultColorBlendMode
);
model.colorBlendAmount = Property_default.getValueOrDefault(
modelGraphics._colorBlendAmount,
time,
defaultColorBlendAmount
);
model.clippingPlanes = Property_default.getValueOrUndefined(
modelGraphics._clippingPlanes,
time
);
model.clampAnimations = Property_default.getValueOrDefault(
modelGraphics._clampAnimations,
time,
defaultClampAnimations
);
model.imageBasedLighting.imageBasedLightingFactor = Property_default.getValueOrDefault(
modelGraphics._imageBasedLightingFactor,
time,
defaultImageBasedLightingFactor
);
let lightColor = Property_default.getValueOrUndefined(
modelGraphics._lightColor,
time
);
if (defined_default(lightColor)) {
Color_default.pack(lightColor, scratchArray, 0);
lightColor = Cartesian3_default.unpack(scratchArray, 0, scratchCartesian20);
}
model.lightColor = lightColor;
model.customShader = Property_default.getValueOrUndefined(
modelGraphics._customShader,
time
);
modelHash[entity.id].modelUpdated = true;
if (model.ready) {
const runAnimations = Property_default.getValueOrDefault(
modelGraphics._runAnimations,
time,
true
);
if (modelData.animationsRunning !== runAnimations) {
if (runAnimations) {
model.activeAnimations.addAll({
loop: ModelAnimationLoop_default.REPEAT
});
} else {
model.activeAnimations.removeAll();
}
modelData.animationsRunning = runAnimations;
}
const nodeTransformations = Property_default.getValueOrUndefined(
modelGraphics._nodeTransformations,
time,
modelData.nodeTransformationsScratch
);
if (defined_default(nodeTransformations)) {
const nodeNames = Object.keys(nodeTransformations);
for (let nodeIndex = 0, nodeLength = nodeNames.length; nodeIndex < nodeLength; ++nodeIndex) {
const nodeName = nodeNames[nodeIndex];
const nodeTransformation = nodeTransformations[nodeName];
if (!defined_default(nodeTransformation)) {
continue;
}
const modelNode = model.getNode(nodeName);
if (!defined_default(modelNode)) {
continue;
}
const transformationMatrix = Matrix4_default.fromTranslationRotationScale(
nodeTransformation,
nodeMatrixScratch
);
modelNode.matrix = Matrix4_default.multiply(
modelNode.originalMatrix,
transformationMatrix,
transformationMatrix
);
}
}
let anyArticulationUpdated = false;
const articulations = Property_default.getValueOrUndefined(
modelGraphics._articulations,
time,
modelData.articulationsScratch
);
if (defined_default(articulations)) {
const articulationStageKeys = Object.keys(articulations);
for (let s = 0, numKeys = articulationStageKeys.length; s < numKeys; ++s) {
const key = articulationStageKeys[s];
const articulationStageValue = articulations[key];
if (!defined_default(articulationStageValue)) {
continue;
}
anyArticulationUpdated = true;
model.setArticulationStage(key, articulationStageValue);
}
}
if (anyArticulationUpdated) {
model.applyArticulations();
}
}
}
return true;
};
ModelVisualizer.prototype.isDestroyed = function() {
return false;
};
ModelVisualizer.prototype.destroy = function() {
this._entityCollection.collectionChanged.removeEventListener(
ModelVisualizer.prototype._onCollectionChanged,
this
);
const entities = this._entitiesToVisualize.values;
const modelHash = this._modelHash;
const primitives = this._primitives;
for (let i = entities.length - 1; i > -1; i--) {
removeModel(this, entities[i], modelHash, primitives);
}
return destroyObject_default(this);
};
var scratchPosition10 = new Cartesian3_default();
var scratchCartographic15 = new Cartographic_default();
ModelVisualizer.prototype.getBoundingSphere = function(entity, result) {
if (!defined_default(entity)) {
throw new DeveloperError_default("entity is required.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
const modelData = this._modelHash[entity.id];
if (!defined_default(modelData)) {
return BoundingSphereState_default.FAILED;
}
if (modelData.loadFailed) {
return BoundingSphereState_default.FAILED;
}
const model = modelData.modelPrimitive;
if (!defined_default(model) || !model.show) {
return BoundingSphereState_default.PENDING;
}
if (!model.ready || !modelData.modelUpdated) {
return BoundingSphereState_default.PENDING;
}
const scene = this._scene;
const ellipsoid = scene.ellipsoid ?? Ellipsoid_default.default;
const hasHeightReference = model.heightReference !== HeightReference_default.NONE;
if (hasHeightReference) {
const modelMatrix = model.modelMatrix;
scratchPosition10.x = modelMatrix[12];
scratchPosition10.y = modelMatrix[13];
scratchPosition10.z = modelMatrix[14];
const cartoPosition = ellipsoid.cartesianToCartographic(
scratchPosition10,
scratchCartographic15
);
const height = scene.getHeight(cartoPosition, model.heightReference);
if (defined_default(height)) {
if (isHeightReferenceClamp(model.heightReference)) {
cartoPosition.height = height;
} else {
cartoPosition.height += height;
}
}
BoundingSphere_default.clone(model.boundingSphere, result);
result.center = ellipsoid.cartographicToCartesian(cartoPosition);
return BoundingSphereState_default.DONE;
}
BoundingSphere_default.clone(model.boundingSphere, result);
return BoundingSphereState_default.DONE;
};
ModelVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed, changed) {
let i;
let entity;
const entities = this._entitiesToVisualize;
const modelHash = this._modelHash;
const primitives = this._primitives;
for (i = added.length - 1; i > -1; i--) {
entity = added[i];
if (defined_default(entity._model) && defined_default(entity._position)) {
entities.set(entity.id, entity);
}
}
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i];
if (defined_default(entity._model) && defined_default(entity._position)) {
clearNodeTransformationsArticulationsScratch(entity, modelHash);
entities.set(entity.id, entity);
} else {
removeModel(this, entity, modelHash, primitives);
entities.remove(entity.id);
}
}
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i];
removeModel(this, entity, modelHash, primitives);
entities.remove(entity.id);
}
};
function removeModel(visualizer, entity, modelHash, primitives) {
const modelData = modelHash[entity.id];
if (defined_default(modelData)) {
primitives.removeAndDestroy(modelData.modelPrimitive);
delete modelHash[entity.id];
}
}
function clearNodeTransformationsArticulationsScratch(entity, modelHash) {
const modelData = modelHash[entity.id];
if (defined_default(modelData)) {
modelData.nodeTransformationsScratch = {};
modelData.articulationsScratch = {};
}
}
var ModelVisualizer_default = ModelVisualizer;
// packages/engine/Source/DataSources/PathVisualizer.js
var import_InlineWorkers912 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/ScaledPositionProperty.js
var import_InlineWorkers911 = __toESM(require_InlineWorkers(), 1);
function ScaledPositionProperty(value) {
this._definitionChanged = new Event_default();
this._value = void 0;
this._removeSubscription = void 0;
this.setValue(value);
}
Object.defineProperties(ScaledPositionProperty.prototype, {
isConstant: {
get: function() {
return Property_default.isConstant(this._value);
}
},
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
referenceFrame: {
get: function() {
return defined_default(this._value) ? this._value.referenceFrame : ReferenceFrame_default.FIXED;
}
}
});
var timeScratch29 = new JulianDate_default();
ScaledPositionProperty.prototype.getValue = function(time, result) {
if (!defined_default(time)) {
time = JulianDate_default.now(timeScratch29);
}
return this.getValueInReferenceFrame(time, ReferenceFrame_default.FIXED, result);
};
ScaledPositionProperty.prototype.setValue = function(value) {
if (this._value !== value) {
this._value = value;
if (defined_default(this._removeSubscription)) {
this._removeSubscription();
this._removeSubscription = void 0;
}
if (defined_default(value)) {
this._removeSubscription = value.definitionChanged.addEventListener(
this._raiseDefinitionChanged,
this
);
}
this._definitionChanged.raiseEvent(this);
}
};
ScaledPositionProperty.prototype.getValueInReferenceFrame = function(time, referenceFrame, result) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required.");
}
if (!defined_default(referenceFrame)) {
throw new DeveloperError_default("referenceFrame is required.");
}
if (!defined_default(this._value)) {
return void 0;
}
result = this._value.getValueInReferenceFrame(time, referenceFrame, result);
return defined_default(result) ? Ellipsoid_default.default.scaleToGeodeticSurface(result, result) : void 0;
};
ScaledPositionProperty.prototype.equals = function(other) {
return this === other || other instanceof ScaledPositionProperty && this._value === other._value;
};
ScaledPositionProperty.prototype._raiseDefinitionChanged = function() {
this._definitionChanged.raiseEvent(this);
};
var ScaledPositionProperty_default = ScaledPositionProperty;
// packages/engine/Source/DataSources/PathVisualizer.js
var defaultResolution = 60;
var defaultWidth = 1;
var scratchTimeInterval2 = new TimeInterval_default();
var subSampleCompositePropertyScratch = new TimeInterval_default();
var subSampleIntervalPropertyScratch = new TimeInterval_default();
function EntityData3(entity) {
this.entity = entity;
this.polyline = void 0;
this.index = void 0;
this.updater = void 0;
}
function subSampleSampledProperty(property, start, stop2, times, updateTime, referenceFrame, maximumStep, startingIndex, result) {
let r = startingIndex;
let tmp2;
tmp2 = property.getValueInReferenceFrame(start, referenceFrame, result[r]);
if (defined_default(tmp2)) {
result[r++] = tmp2;
}
let steppedOnNow = !defined_default(updateTime) || JulianDate_default.lessThanOrEquals(updateTime, start) || JulianDate_default.greaterThanOrEquals(updateTime, stop2);
let t = 0;
const len = times.length;
let current = times[t];
const loopStop = stop2;
let sampling = false;
let sampleStepsToTake;
let sampleStepsTaken;
let sampleStepSize;
while (t < len) {
if (!steppedOnNow && JulianDate_default.greaterThanOrEquals(current, updateTime)) {
tmp2 = property.getValueInReferenceFrame(
updateTime,
referenceFrame,
result[r]
);
if (defined_default(tmp2)) {
result[r++] = tmp2;
}
steppedOnNow = true;
}
if (JulianDate_default.greaterThan(current, start) && JulianDate_default.lessThan(current, loopStop) && !current.equals(updateTime)) {
tmp2 = property.getValueInReferenceFrame(
current,
referenceFrame,
result[r]
);
if (defined_default(tmp2)) {
result[r++] = tmp2;
}
}
if (t < len - 1) {
if (maximumStep > 0 && !sampling) {
const next = times[t + 1];
const secondsUntilNext = JulianDate_default.secondsDifference(next, current);
sampling = secondsUntilNext > maximumStep;
if (sampling) {
sampleStepsToTake = Math.ceil(secondsUntilNext / maximumStep);
sampleStepsTaken = 0;
sampleStepSize = secondsUntilNext / Math.max(sampleStepsToTake, 2);
sampleStepsToTake = Math.max(sampleStepsToTake - 1, 1);
}
}
if (sampling && sampleStepsTaken < sampleStepsToTake) {
current = JulianDate_default.addSeconds(
current,
sampleStepSize,
new JulianDate_default()
);
sampleStepsTaken++;
continue;
}
}
sampling = false;
t++;
current = times[t];
}
tmp2 = property.getValueInReferenceFrame(stop2, referenceFrame, result[r]);
if (defined_default(tmp2)) {
result[r++] = tmp2;
}
return r;
}
function subSampleCallbackPositionProperty(property, start, stop2, updateTime, referenceFrame, maximumStep, startingIndex, result) {
let tmp2;
let i = 0;
let index = startingIndex;
let time = start;
let steppedOnNow = !defined_default(updateTime) || JulianDate_default.lessThanOrEquals(updateTime, start) || JulianDate_default.greaterThanOrEquals(updateTime, stop2);
while (JulianDate_default.lessThan(time, stop2)) {
if (!steppedOnNow && JulianDate_default.greaterThanOrEquals(time, updateTime)) {
steppedOnNow = true;
tmp2 = property.getValueInReferenceFrame(
updateTime,
referenceFrame,
result[index]
);
if (defined_default(tmp2)) {
result[index] = tmp2;
index++;
}
}
tmp2 = property.getValueInReferenceFrame(
time,
referenceFrame,
result[index]
);
if (defined_default(tmp2)) {
result[index] = tmp2;
index++;
}
i++;
time = JulianDate_default.addSeconds(start, maximumStep * i, new JulianDate_default());
}
tmp2 = property.getValueInReferenceFrame(stop2, referenceFrame, result[index]);
if (defined_default(tmp2)) {
result[index] = tmp2;
index++;
}
return index;
}
function subSampleGenericProperty(property, start, stop2, updateTime, referenceFrame, maximumStep, startingIndex, result) {
let tmp2;
let i = 0;
let index = startingIndex;
let time = start;
const stepSize = Math.max(maximumStep, 60);
let steppedOnNow = !defined_default(updateTime) || JulianDate_default.lessThanOrEquals(updateTime, start) || JulianDate_default.greaterThanOrEquals(updateTime, stop2);
while (JulianDate_default.lessThan(time, stop2)) {
if (!steppedOnNow && JulianDate_default.greaterThanOrEquals(time, updateTime)) {
steppedOnNow = true;
tmp2 = property.getValueInReferenceFrame(
updateTime,
referenceFrame,
result[index]
);
if (defined_default(tmp2)) {
result[index] = tmp2;
index++;
}
}
tmp2 = property.getValueInReferenceFrame(
time,
referenceFrame,
result[index]
);
if (defined_default(tmp2)) {
result[index] = tmp2;
index++;
}
i++;
time = JulianDate_default.addSeconds(start, stepSize * i, new JulianDate_default());
}
tmp2 = property.getValueInReferenceFrame(stop2, referenceFrame, result[index]);
if (defined_default(tmp2)) {
result[index] = tmp2;
index++;
}
return index;
}
function subSampleIntervalProperty(property, start, stop2, updateTime, referenceFrame, maximumStep, startingIndex, result) {
subSampleIntervalPropertyScratch.start = start;
subSampleIntervalPropertyScratch.stop = stop2;
let index = startingIndex;
const intervals = property.intervals;
for (let i = 0; i < intervals.length; i++) {
const interval = intervals.get(i);
if (!TimeInterval_default.intersect(
interval,
subSampleIntervalPropertyScratch,
scratchTimeInterval2
).isEmpty) {
let time = interval.start;
if (!interval.isStartIncluded) {
if (interval.isStopIncluded) {
time = interval.stop;
} else {
time = JulianDate_default.addSeconds(
interval.start,
JulianDate_default.secondsDifference(interval.stop, interval.start) / 2,
new JulianDate_default()
);
}
}
const tmp2 = property.getValueInReferenceFrame(
time,
referenceFrame,
result[index]
);
if (defined_default(tmp2)) {
result[index] = tmp2;
index++;
}
}
}
return index;
}
function subSampleConstantProperty(property, start, stop2, updateTime, referenceFrame, maximumStep, startingIndex, result) {
const tmp2 = property.getValueInReferenceFrame(
start,
referenceFrame,
result[startingIndex]
);
if (defined_default(tmp2)) {
result[startingIndex++] = tmp2;
}
return startingIndex;
}
function subSampleCompositeProperty(property, start, stop2, updateTime, referenceFrame, maximumStep, startingIndex, result) {
subSampleCompositePropertyScratch.start = start;
subSampleCompositePropertyScratch.stop = stop2;
let index = startingIndex;
const intervals = property.intervals;
for (let i = 0; i < intervals.length; i++) {
const interval = intervals.get(i);
if (!TimeInterval_default.intersect(
interval,
subSampleCompositePropertyScratch,
scratchTimeInterval2
).isEmpty) {
const intervalStart = interval.start;
const intervalStop = interval.stop;
let sampleStart = start;
if (JulianDate_default.greaterThan(intervalStart, sampleStart)) {
sampleStart = intervalStart;
}
let sampleStop = stop2;
if (JulianDate_default.lessThan(intervalStop, sampleStop)) {
sampleStop = intervalStop;
}
index = reallySubSample(
interval.data,
sampleStart,
sampleStop,
updateTime,
referenceFrame,
maximumStep,
index,
result
);
}
}
return index;
}
function reallySubSample(property, start, stop2, updateTime, referenceFrame, maximumStep, index, result) {
while (property instanceof ReferenceProperty_default) {
property = property.resolvedProperty;
}
if (property instanceof SampledPositionProperty_default) {
const times = property._property._times;
index = subSampleSampledProperty(
property,
start,
stop2,
times,
updateTime,
referenceFrame,
maximumStep,
index,
result
);
} else if (property instanceof CallbackPositionProperty_default) {
index = subSampleCallbackPositionProperty(
property,
start,
stop2,
updateTime,
referenceFrame,
maximumStep,
index,
result
);
} else if (property instanceof CompositePositionProperty_default) {
index = subSampleCompositeProperty(
property,
start,
stop2,
updateTime,
referenceFrame,
maximumStep,
index,
result
);
} else if (property instanceof TimeIntervalCollectionPositionProperty_default) {
index = subSampleIntervalProperty(
property,
start,
stop2,
updateTime,
referenceFrame,
maximumStep,
index,
result
);
} else if (property instanceof ConstantPositionProperty_default || property instanceof ScaledPositionProperty_default && Property_default.isConstant(property)) {
index = subSampleConstantProperty(
property,
start,
stop2,
updateTime,
referenceFrame,
maximumStep,
index,
result
);
} else {
index = subSampleGenericProperty(
property,
start,
stop2,
updateTime,
referenceFrame,
maximumStep,
index,
result
);
}
return index;
}
function subSample(property, start, stop2, updateTime, referenceFrame, maximumStep, result) {
if (!defined_default(result)) {
result = [];
}
const length2 = reallySubSample(
property,
start,
stop2,
updateTime,
referenceFrame,
maximumStep,
0,
result
);
result.length = length2;
return result;
}
var toFixedScratch = new Matrix3_default();
function PolylineUpdater(scene, referenceFrame) {
this._unusedIndexes = [];
this._polylineCollection = new PolylineCollection_default();
this._scene = scene;
this._referenceFrame = referenceFrame;
scene.primitives.add(this._polylineCollection);
}
PolylineUpdater.prototype.update = function(time) {
if (this._referenceFrame === ReferenceFrame_default.INERTIAL) {
const toFixed = Transforms_default.computeIcrfToCentralBodyFixedMatrix(
time,
toFixedScratch
);
Matrix4_default.fromRotationTranslation(
toFixed,
Cartesian3_default.ZERO,
this._polylineCollection.modelMatrix
);
}
};
PolylineUpdater.prototype.updateObject = function(time, item) {
const entity = item.entity;
const pathGraphics = entity._path;
const positionProperty = entity._position;
let sampleStart;
let sampleStop;
const showProperty = pathGraphics._show;
let polyline = item.polyline;
let show = entity.isShowing && entity.isAvailable(time) && (!defined_default(showProperty) || showProperty.getValue(time));
if (show) {
const leadTime = Property_default.getValueOrUndefined(pathGraphics._leadTime, time);
const trailTime = Property_default.getValueOrUndefined(
pathGraphics._trailTime,
time
);
const availability = entity._availability;
const hasAvailability = defined_default(availability);
const hasLeadTime = defined_default(leadTime);
const hasTrailTime = defined_default(trailTime);
show = hasAvailability || hasLeadTime && hasTrailTime;
if (show) {
if (hasTrailTime) {
sampleStart = JulianDate_default.addSeconds(time, -trailTime, new JulianDate_default());
}
if (hasLeadTime) {
sampleStop = JulianDate_default.addSeconds(time, leadTime, new JulianDate_default());
}
if (hasAvailability) {
const start = availability.start;
const stop2 = availability.stop;
if (!hasTrailTime || JulianDate_default.greaterThan(start, sampleStart)) {
sampleStart = start;
}
if (!hasLeadTime || JulianDate_default.lessThan(stop2, sampleStop)) {
sampleStop = stop2;
}
}
show = JulianDate_default.lessThan(sampleStart, sampleStop);
}
}
if (!show) {
if (defined_default(polyline)) {
this._unusedIndexes.push(item.index);
item.polyline = void 0;
polyline.show = false;
item.index = void 0;
}
return;
}
if (!defined_default(polyline)) {
const unusedIndexes = this._unusedIndexes;
const length2 = unusedIndexes.length;
if (length2 > 0) {
const index = unusedIndexes.pop();
polyline = this._polylineCollection.get(index);
item.index = index;
} else {
item.index = this._polylineCollection.length;
polyline = this._polylineCollection.add();
}
polyline.id = entity;
item.polyline = polyline;
}
const resolution = Property_default.getValueOrDefault(
pathGraphics._resolution,
time,
defaultResolution
);
polyline.show = true;
polyline.positions = subSample(
positionProperty,
sampleStart,
sampleStop,
time,
this._referenceFrame,
resolution,
polyline.positions.slice()
);
polyline.material = MaterialProperty_default.getValue(
time,
pathGraphics._material,
polyline.material
);
polyline.width = Property_default.getValueOrDefault(
pathGraphics._width,
time,
defaultWidth
);
polyline.distanceDisplayCondition = Property_default.getValueOrUndefined(
pathGraphics._distanceDisplayCondition,
time,
polyline.distanceDisplayCondition
);
};
PolylineUpdater.prototype.removeObject = function(item) {
const polyline = item.polyline;
if (defined_default(polyline)) {
this._unusedIndexes.push(item.index);
item.polyline = void 0;
polyline.show = false;
polyline.id = void 0;
item.index = void 0;
}
};
PolylineUpdater.prototype.destroy = function() {
this._scene.primitives.remove(this._polylineCollection);
return destroyObject_default(this);
};
function PathVisualizer(scene, entityCollection) {
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required.");
}
if (!defined_default(entityCollection)) {
throw new DeveloperError_default("entityCollection is required.");
}
entityCollection.collectionChanged.addEventListener(
PathVisualizer.prototype._onCollectionChanged,
this
);
this._scene = scene;
this._updaters = {};
this._entityCollection = entityCollection;
this._items = new AssociativeArray_default();
this._onCollectionChanged(entityCollection, entityCollection.values, [], []);
}
PathVisualizer.prototype.update = function(time) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required.");
}
const updaters = this._updaters;
for (const key in updaters) {
if (updaters.hasOwnProperty(key)) {
updaters[key].update(time);
}
}
const items = this._items.values;
if (items.length === 0 && defined_default(this._updaters) && Object.keys(this._updaters).length > 0) {
for (const u3 in updaters) {
if (updaters.hasOwnProperty(u3)) {
updaters[u3].destroy();
}
}
this._updaters = {};
}
for (let i = 0, len = items.length; i < len; i++) {
const item = items[i];
const entity = item.entity;
const positionProperty = entity._position;
const lastUpdater = item.updater;
let frameToVisualize = ReferenceFrame_default.FIXED;
if (this._scene.mode === SceneMode_default.SCENE3D) {
frameToVisualize = positionProperty.referenceFrame;
}
let currentUpdater = this._updaters[frameToVisualize];
if (lastUpdater === currentUpdater && defined_default(currentUpdater)) {
currentUpdater.updateObject(time, item);
continue;
}
if (defined_default(lastUpdater)) {
lastUpdater.removeObject(item);
}
if (!defined_default(currentUpdater)) {
currentUpdater = new PolylineUpdater(this._scene, frameToVisualize);
currentUpdater.update(time);
this._updaters[frameToVisualize] = currentUpdater;
}
item.updater = currentUpdater;
if (defined_default(currentUpdater)) {
currentUpdater.updateObject(time, item);
}
}
return true;
};
PathVisualizer.prototype.isDestroyed = function() {
return false;
};
PathVisualizer.prototype.destroy = function() {
this._entityCollection.collectionChanged.removeEventListener(
PathVisualizer.prototype._onCollectionChanged,
this
);
const updaters = this._updaters;
for (const key in updaters) {
if (updaters.hasOwnProperty(key)) {
updaters[key].destroy();
}
}
return destroyObject_default(this);
};
PathVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed, changed) {
let i;
let entity;
let item;
const items = this._items;
for (i = added.length - 1; i > -1; i--) {
entity = added[i];
if (defined_default(entity._path) && defined_default(entity._position)) {
items.set(entity.id, new EntityData3(entity));
}
}
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i];
if (defined_default(entity._path) && defined_default(entity._position)) {
if (!items.contains(entity.id)) {
items.set(entity.id, new EntityData3(entity));
}
} else {
item = items.get(entity.id);
if (defined_default(item)) {
if (defined_default(item.updater)) {
item.updater.removeObject(item);
}
items.remove(entity.id);
}
}
}
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i];
item = items.get(entity.id);
if (defined_default(item)) {
if (defined_default(item.updater)) {
item.updater.removeObject(item);
}
items.remove(entity.id);
}
}
};
PathVisualizer._subSample = subSample;
var PathVisualizer_default = PathVisualizer;
// packages/engine/Source/DataSources/PointVisualizer.js
var import_InlineWorkers913 = __toESM(require_InlineWorkers(), 1);
var defaultColor8 = Color_default.WHITE;
var defaultOutlineColor4 = Color_default.BLACK;
var defaultOutlineWidth3 = 0;
var defaultPixelSize = 1;
var defaultDisableDepthTestDistance = 0;
var defaultSplitDirection2 = SplitDirection_default.NONE;
var colorScratch6 = new Color_default();
var positionScratch14 = new Cartesian3_default();
var outlineColorScratch2 = new Color_default();
var scaleByDistanceScratch3 = new NearFarScalar_default();
var translucencyByDistanceScratch3 = new NearFarScalar_default();
var distanceDisplayConditionScratch8 = new DistanceDisplayCondition_default();
function EntityData4(entity) {
this.entity = entity;
this.pointPrimitive = void 0;
this.billboard = void 0;
this.color = void 0;
this.outlineColor = void 0;
this.pixelSize = void 0;
this.outlineWidth = void 0;
}
function PointVisualizer(entityCluster, entityCollection) {
if (!defined_default(entityCluster)) {
throw new DeveloperError_default("entityCluster is required.");
}
if (!defined_default(entityCollection)) {
throw new DeveloperError_default("entityCollection is required.");
}
entityCollection.collectionChanged.addEventListener(
PointVisualizer.prototype._onCollectionChanged,
this
);
this._cluster = entityCluster;
this._entityCollection = entityCollection;
this._items = new AssociativeArray_default();
this._onCollectionChanged(entityCollection, entityCollection.values, [], []);
}
PointVisualizer.prototype.update = function(time) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required.");
}
const items = this._items.values;
const cluster = this._cluster;
for (let i = 0, len = items.length; i < len; i++) {
const item = items[i];
const entity = item.entity;
const pointGraphics = entity._point;
let pointPrimitive = item.pointPrimitive;
let billboard = item.billboard;
const heightReference = Property_default.getValueOrDefault(
pointGraphics._heightReference,
time,
HeightReference_default.NONE
);
let show = entity.isShowing && entity.isAvailable(time) && Property_default.getValueOrDefault(pointGraphics._show, time, true);
let position;
if (show) {
position = Property_default.getValueOrUndefined(
entity._position,
time,
positionScratch14
);
show = defined_default(position);
}
if (!show) {
returnPrimitive3(item, entity, cluster);
continue;
}
if (!Property_default.isConstant(entity._position)) {
cluster._clusterDirty = true;
}
let needsRedraw = false;
let updateClamping2 = false;
if (heightReference !== HeightReference_default.NONE && !defined_default(billboard)) {
if (defined_default(pointPrimitive)) {
returnPrimitive3(item, entity, cluster);
pointPrimitive = void 0;
}
billboard = cluster.getBillboard(entity);
billboard.id = entity;
billboard.image = void 0;
item.billboard = billboard;
needsRedraw = true;
updateClamping2 = Cartesian3_default.equals(billboard.position, position) && billboard.heightReference === heightReference;
} else if (heightReference === HeightReference_default.NONE && !defined_default(pointPrimitive)) {
if (defined_default(billboard)) {
returnPrimitive3(item, entity, cluster);
billboard = void 0;
}
pointPrimitive = cluster.getPoint(entity);
pointPrimitive.id = entity;
item.pointPrimitive = pointPrimitive;
}
if (defined_default(pointPrimitive)) {
pointPrimitive.show = true;
pointPrimitive.position = position;
pointPrimitive.scaleByDistance = Property_default.getValueOrUndefined(
pointGraphics._scaleByDistance,
time,
scaleByDistanceScratch3
);
pointPrimitive.translucencyByDistance = Property_default.getValueOrUndefined(
pointGraphics._translucencyByDistance,
time,
translucencyByDistanceScratch3
);
pointPrimitive.color = Property_default.getValueOrDefault(
pointGraphics._color,
time,
defaultColor8,
colorScratch6
);
pointPrimitive.outlineColor = Property_default.getValueOrDefault(
pointGraphics._outlineColor,
time,
defaultOutlineColor4,
outlineColorScratch2
);
pointPrimitive.outlineWidth = Property_default.getValueOrDefault(
pointGraphics._outlineWidth,
time,
defaultOutlineWidth3
);
pointPrimitive.pixelSize = Property_default.getValueOrDefault(
pointGraphics._pixelSize,
time,
defaultPixelSize
);
pointPrimitive.distanceDisplayCondition = Property_default.getValueOrUndefined(
pointGraphics._distanceDisplayCondition,
time,
distanceDisplayConditionScratch8
);
pointPrimitive.disableDepthTestDistance = Property_default.getValueOrDefault(
pointGraphics._disableDepthTestDistance,
time,
defaultDisableDepthTestDistance
);
pointPrimitive.splitDirection = Property_default.getValueOrDefault(
pointGraphics._splitDirection,
time,
defaultSplitDirection2
);
} else if (defined_default(billboard)) {
billboard.show = true;
billboard.position = position;
billboard.scaleByDistance = Property_default.getValueOrUndefined(
pointGraphics._scaleByDistance,
time,
scaleByDistanceScratch3
);
billboard.translucencyByDistance = Property_default.getValueOrUndefined(
pointGraphics._translucencyByDistance,
time,
translucencyByDistanceScratch3
);
billboard.distanceDisplayCondition = Property_default.getValueOrUndefined(
pointGraphics._distanceDisplayCondition,
time,
distanceDisplayConditionScratch8
);
billboard.disableDepthTestDistance = Property_default.getValueOrDefault(
pointGraphics._disableDepthTestDistance,
time,
defaultDisableDepthTestDistance
);
billboard.splitDirection = Property_default.getValueOrDefault(
pointGraphics._splitDirection,
time,
defaultSplitDirection2
);
billboard.heightReference = heightReference;
const newColor = Property_default.getValueOrDefault(
pointGraphics._color,
time,
defaultColor8,
colorScratch6
);
const newOutlineColor = Property_default.getValueOrDefault(
pointGraphics._outlineColor,
time,
defaultOutlineColor4,
outlineColorScratch2
);
const newOutlineWidth = Math.round(
Property_default.getValueOrDefault(
pointGraphics._outlineWidth,
time,
defaultOutlineWidth3
)
);
let newPixelSize = Math.max(
1,
Math.round(
Property_default.getValueOrDefault(
pointGraphics._pixelSize,
time,
defaultPixelSize
)
)
);
if (newOutlineWidth > 0) {
billboard.scale = 1;
needsRedraw = needsRedraw || //
newOutlineWidth !== item.outlineWidth || //
newPixelSize !== item.pixelSize || //
!Color_default.equals(newColor, item.color) || //
!Color_default.equals(newOutlineColor, item.outlineColor);
} else {
billboard.scale = newPixelSize / 50;
newPixelSize = 50;
needsRedraw = needsRedraw || //
newOutlineWidth !== item.outlineWidth || //
!Color_default.equals(newColor, item.color) || //
!Color_default.equals(newOutlineColor, item.outlineColor);
}
if (needsRedraw) {
item.color = Color_default.clone(newColor, item.color);
item.outlineColor = Color_default.clone(newOutlineColor, item.outlineColor);
item.pixelSize = newPixelSize;
item.outlineWidth = newOutlineWidth;
const centerAlpha = newColor.alpha;
const cssColor = newColor.toCssColorString();
const cssOutlineColor = newOutlineColor.toCssColorString();
const textureId = JSON.stringify([
cssColor,
newPixelSize,
cssOutlineColor,
newOutlineWidth
]);
billboard.setImage(
textureId,
createBillboardPointCallback_default(
centerAlpha,
cssColor,
cssOutlineColor,
newOutlineWidth,
newPixelSize
)
);
}
if (updateClamping2) {
billboard._updateClamping();
}
}
}
return true;
};
PointVisualizer.prototype.getBoundingSphere = function(entity, result) {
if (!defined_default(entity)) {
throw new DeveloperError_default("entity is required.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("result is required.");
}
const item = this._items.get(entity.id);
if (!defined_default(item) || !(defined_default(item.pointPrimitive) || defined_default(item.billboard))) {
return BoundingSphereState_default.FAILED;
}
if (defined_default(item.pointPrimitive)) {
result.center = Cartesian3_default.clone(
item.pointPrimitive.position,
result.center
);
} else {
const billboard = item.billboard;
if (!defined_default(billboard._clampedPosition)) {
return BoundingSphereState_default.PENDING;
}
result.center = Cartesian3_default.clone(billboard._clampedPosition, result.center);
}
result.radius = 0;
return BoundingSphereState_default.DONE;
};
PointVisualizer.prototype.isDestroyed = function() {
return false;
};
PointVisualizer.prototype.destroy = function() {
this._entityCollection.collectionChanged.removeEventListener(
PointVisualizer.prototype._onCollectionChanged,
this
);
const entities = this._entityCollection.values;
for (let i = 0; i < entities.length; i++) {
this._cluster.removePoint(entities[i]);
}
return destroyObject_default(this);
};
PointVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed, changed) {
let i;
let entity;
const items = this._items;
const cluster = this._cluster;
for (i = added.length - 1; i > -1; i--) {
entity = added[i];
if (defined_default(entity._point) && defined_default(entity._position)) {
items.set(entity.id, new EntityData4(entity));
}
}
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i];
if (defined_default(entity._point) && defined_default(entity._position)) {
if (!items.contains(entity.id)) {
items.set(entity.id, new EntityData4(entity));
}
} else {
returnPrimitive3(items.get(entity.id), entity, cluster);
items.remove(entity.id);
}
}
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i];
returnPrimitive3(items.get(entity.id), entity, cluster);
items.remove(entity.id);
}
};
function returnPrimitive3(item, entity, cluster) {
if (defined_default(item)) {
const pointPrimitive = item.pointPrimitive;
if (defined_default(pointPrimitive)) {
item.pointPrimitive = void 0;
cluster.removePoint(entity);
return;
}
const billboard = item.billboard;
if (defined_default(billboard)) {
item.billboard = void 0;
cluster.removeBillboard(entity);
}
}
}
var PointVisualizer_default = PointVisualizer;
// packages/engine/Source/DataSources/PolylineVisualizer.js
var import_InlineWorkers917 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/DataSources/PolylineGeometryUpdater.js
var import_InlineWorkers915 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PolylineGeometry.js
var import_InlineWorkers914 = __toESM(require_InlineWorkers(), 1);
var scratchInterpolateColorsArray = [];
function interpolateColors(p0, p1, color0, color1, numPoints) {
const colors = scratchInterpolateColorsArray;
colors.length = numPoints;
let i;
const r0 = color0.red;
const g0 = color0.green;
const b0 = color0.blue;
const a0 = color0.alpha;
const r1 = color1.red;
const g1 = color1.green;
const b1 = color1.blue;
const a1 = color1.alpha;
if (Color_default.equals(color0, color1)) {
for (i = 0; i < numPoints; i++) {
colors[i] = Color_default.clone(color0);
}
return colors;
}
const redPerVertex = (r1 - r0) / numPoints;
const greenPerVertex = (g1 - g0) / numPoints;
const bluePerVertex = (b1 - b0) / numPoints;
const alphaPerVertex = (a1 - a0) / numPoints;
for (i = 0; i < numPoints; i++) {
colors[i] = new Color_default(
r0 + i * redPerVertex,
g0 + i * greenPerVertex,
b0 + i * bluePerVertex,
a0 + i * alphaPerVertex
);
}
return colors;
}
function PolylineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const positions = options.positions;
const colors = options.colors;
const width = options.width ?? 1;
const colorsPerVertex = options.colorsPerVertex ?? false;
if (!defined_default(positions) || positions.length < 2) {
throw new DeveloperError_default("At least two positions are required.");
}
if (typeof width !== "number") {
throw new DeveloperError_default("width must be a number");
}
if (defined_default(colors) && (colorsPerVertex && colors.length < positions.length || !colorsPerVertex && colors.length < positions.length - 1)) {
throw new DeveloperError_default("colors has an invalid length.");
}
this._positions = positions;
this._colors = colors;
this._width = width;
this._colorsPerVertex = colorsPerVertex;
this._vertexFormat = VertexFormat_default.clone(
options.vertexFormat ?? VertexFormat_default.DEFAULT
);
this._arcType = options.arcType ?? ArcType_default.GEODESIC;
this._granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
this._ellipsoid = Ellipsoid_default.clone(options.ellipsoid ?? Ellipsoid_default.default);
this._workerName = "createPolylineGeometry";
let numComponents = 1 + positions.length * Cartesian3_default.packedLength;
numComponents += defined_default(colors) ? 1 + colors.length * Color_default.packedLength : 1;
this.packedLength = numComponents + Ellipsoid_default.packedLength + VertexFormat_default.packedLength + 4;
}
PolylineGeometry.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
const positions = value._positions;
let length2 = positions.length;
array[startingIndex++] = length2;
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
Cartesian3_default.pack(positions[i], array, startingIndex);
}
const colors = value._colors;
length2 = defined_default(colors) ? colors.length : 0;
array[startingIndex++] = length2;
for (i = 0; i < length2; ++i, startingIndex += Color_default.packedLength) {
Color_default.pack(colors[i], array, startingIndex);
}
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
startingIndex += VertexFormat_default.packedLength;
array[startingIndex++] = value._width;
array[startingIndex++] = value._colorsPerVertex ? 1 : 0;
array[startingIndex++] = value._arcType;
array[startingIndex] = value._granularity;
return array;
};
var scratchEllipsoid14 = Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE);
var scratchVertexFormat12 = new VertexFormat_default();
var scratchOptions21 = {
positions: void 0,
colors: void 0,
ellipsoid: scratchEllipsoid14,
vertexFormat: scratchVertexFormat12,
width: void 0,
colorsPerVertex: void 0,
arcType: void 0,
granularity: void 0
};
PolylineGeometry.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
let length2 = array[startingIndex++];
const positions = new Array(length2);
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
positions[i] = Cartesian3_default.unpack(array, startingIndex);
}
length2 = array[startingIndex++];
const colors = length2 > 0 ? new Array(length2) : void 0;
for (i = 0; i < length2; ++i, startingIndex += Color_default.packedLength) {
colors[i] = Color_default.unpack(array, startingIndex);
}
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex, scratchEllipsoid14);
startingIndex += Ellipsoid_default.packedLength;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat12
);
startingIndex += VertexFormat_default.packedLength;
const width = array[startingIndex++];
const colorsPerVertex = array[startingIndex++] === 1;
const arcType = array[startingIndex++];
const granularity = array[startingIndex];
if (!defined_default(result)) {
scratchOptions21.positions = positions;
scratchOptions21.colors = colors;
scratchOptions21.width = width;
scratchOptions21.colorsPerVertex = colorsPerVertex;
scratchOptions21.arcType = arcType;
scratchOptions21.granularity = granularity;
return new PolylineGeometry(scratchOptions21);
}
result._positions = positions;
result._colors = colors;
result._ellipsoid = Ellipsoid_default.clone(ellipsoid, result._ellipsoid);
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._width = width;
result._colorsPerVertex = colorsPerVertex;
result._arcType = arcType;
result._granularity = granularity;
return result;
};
var scratchCartesian310 = new Cartesian3_default();
var scratchPosition11 = new Cartesian3_default();
var scratchPrevPosition = new Cartesian3_default();
var scratchNextPosition = new Cartesian3_default();
PolylineGeometry.createGeometry = function(polylineGeometry) {
const width = polylineGeometry._width;
const vertexFormat = polylineGeometry._vertexFormat;
let colors = polylineGeometry._colors;
const colorsPerVertex = polylineGeometry._colorsPerVertex;
const arcType = polylineGeometry._arcType;
const granularity = polylineGeometry._granularity;
const ellipsoid = polylineGeometry._ellipsoid;
let i;
let j;
let k;
const removedIndices = [];
let positions = arrayRemoveDuplicates_default(
polylineGeometry._positions,
Cartesian3_default.equalsEpsilon,
false,
removedIndices
);
if (defined_default(colors) && removedIndices.length > 0) {
let removedArrayIndex = 0;
let nextRemovedIndex = removedIndices[0];
colors = colors.filter(function(color, index2) {
let remove4 = false;
if (colorsPerVertex) {
remove4 = index2 === nextRemovedIndex || index2 === 0 && nextRemovedIndex === 1;
} else {
remove4 = index2 + 1 === nextRemovedIndex;
}
if (remove4) {
removedArrayIndex++;
nextRemovedIndex = removedIndices[removedArrayIndex];
return false;
}
return true;
});
}
let positionsLength = positions.length;
if (positionsLength < 2 || width <= 0) {
return void 0;
}
if (arcType === ArcType_default.GEODESIC || arcType === ArcType_default.RHUMB) {
let subdivisionSize;
let numberOfPointsFunction;
if (arcType === ArcType_default.GEODESIC) {
subdivisionSize = Math_default.chordLength(
granularity,
ellipsoid.maximumRadius
);
numberOfPointsFunction = PolylinePipeline_default.numberOfPoints;
} else {
subdivisionSize = granularity;
numberOfPointsFunction = PolylinePipeline_default.numberOfPointsRhumbLine;
}
const heights = PolylinePipeline_default.extractHeights(positions, ellipsoid);
if (defined_default(colors)) {
let colorLength = 1;
for (i = 0; i < positionsLength - 1; ++i) {
colorLength += numberOfPointsFunction(
positions[i],
positions[i + 1],
subdivisionSize
);
}
const newColors = new Array(colorLength);
let newColorIndex = 0;
for (i = 0; i < positionsLength - 1; ++i) {
const p0 = positions[i];
const p1 = positions[i + 1];
const c0 = colors[i];
const numColors = numberOfPointsFunction(p0, p1, subdivisionSize);
if (colorsPerVertex && i < colorLength) {
const c14 = colors[i + 1];
const interpolatedColors = interpolateColors(
p0,
p1,
c0,
c14,
numColors
);
const interpolatedColorsLength = interpolatedColors.length;
for (j = 0; j < interpolatedColorsLength; ++j) {
newColors[newColorIndex++] = interpolatedColors[j];
}
} else {
for (j = 0; j < numColors; ++j) {
newColors[newColorIndex++] = Color_default.clone(c0);
}
}
}
newColors[newColorIndex] = Color_default.clone(colors[colors.length - 1]);
colors = newColors;
scratchInterpolateColorsArray.length = 0;
}
if (arcType === ArcType_default.GEODESIC) {
positions = PolylinePipeline_default.generateCartesianArc({
positions,
minDistance: subdivisionSize,
ellipsoid,
height: heights
});
} else {
positions = PolylinePipeline_default.generateCartesianRhumbArc({
positions,
granularity: subdivisionSize,
ellipsoid,
height: heights
});
}
}
positionsLength = positions.length;
const size = positionsLength * 4 - 4;
const finalPositions = new Float64Array(size * 3);
const prevPositions = new Float64Array(size * 3);
const nextPositions = new Float64Array(size * 3);
const expandAndWidth = new Float32Array(size * 2);
const st = vertexFormat.st ? new Float32Array(size * 2) : void 0;
const finalColors = defined_default(colors) ? new Uint8Array(size * 4) : void 0;
let positionIndex = 0;
let expandAndWidthIndex = 0;
let stIndex = 0;
let colorIndex = 0;
let position;
for (j = 0; j < positionsLength; ++j) {
if (j === 0) {
position = scratchCartesian310;
Cartesian3_default.subtract(positions[0], positions[1], position);
Cartesian3_default.add(positions[0], position, position);
} else {
position = positions[j - 1];
}
Cartesian3_default.clone(position, scratchPrevPosition);
Cartesian3_default.clone(positions[j], scratchPosition11);
if (j === positionsLength - 1) {
position = scratchCartesian310;
Cartesian3_default.subtract(
positions[positionsLength - 1],
positions[positionsLength - 2],
position
);
Cartesian3_default.add(positions[positionsLength - 1], position, position);
} else {
position = positions[j + 1];
}
Cartesian3_default.clone(position, scratchNextPosition);
let color0, color1;
if (defined_default(finalColors)) {
if (j !== 0 && !colorsPerVertex) {
color0 = colors[j - 1];
} else {
color0 = colors[j];
}
if (j !== positionsLength - 1) {
color1 = colors[j];
}
}
const startK = j === 0 ? 2 : 0;
const endK = j === positionsLength - 1 ? 2 : 4;
for (k = startK; k < endK; ++k) {
Cartesian3_default.pack(scratchPosition11, finalPositions, positionIndex);
Cartesian3_default.pack(scratchPrevPosition, prevPositions, positionIndex);
Cartesian3_default.pack(scratchNextPosition, nextPositions, positionIndex);
positionIndex += 3;
const direction2 = k - 2 < 0 ? -1 : 1;
expandAndWidth[expandAndWidthIndex++] = 2 * (k % 2) - 1;
expandAndWidth[expandAndWidthIndex++] = direction2 * width;
if (vertexFormat.st) {
st[stIndex++] = j / (positionsLength - 1);
st[stIndex++] = Math.max(expandAndWidth[expandAndWidthIndex - 2], 0);
}
if (defined_default(finalColors)) {
const color = k < 2 ? color0 : color1;
finalColors[colorIndex++] = Color_default.floatToByte(color.red);
finalColors[colorIndex++] = Color_default.floatToByte(color.green);
finalColors[colorIndex++] = Color_default.floatToByte(color.blue);
finalColors[colorIndex++] = Color_default.floatToByte(color.alpha);
}
}
}
const attributes = new GeometryAttributes_default();
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: finalPositions
});
attributes.prevPosition = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: prevPositions
});
attributes.nextPosition = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: nextPositions
});
attributes.expandAndWidth = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: expandAndWidth
});
if (vertexFormat.st) {
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: st
});
}
if (defined_default(finalColors)) {
attributes.color = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 4,
values: finalColors,
normalize: true
});
}
const indices = IndexDatatype_default.createTypedArray(size, positionsLength * 6 - 6);
let index = 0;
let indicesIndex = 0;
const length2 = positionsLength - 1;
for (j = 0; j < length2; ++j) {
indices[indicesIndex++] = index;
indices[indicesIndex++] = index + 2;
indices[indicesIndex++] = index + 1;
indices[indicesIndex++] = index + 1;
indices[indicesIndex++] = index + 2;
indices[indicesIndex++] = index + 3;
index += 4;
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.TRIANGLES,
boundingSphere: BoundingSphere_default.fromPoints(positions),
geometryType: GeometryType_default.POLYLINES
});
};
var PolylineGeometry_default = PolylineGeometry;
// packages/engine/Source/DataSources/PolylineGeometryUpdater.js
var defaultZIndex2 = new ConstantProperty_default(0);
var polylineCollections = {};
var scratchColor24 = new Color_default();
var defaultMaterial3 = new ColorMaterialProperty_default(Color_default.WHITE);
var defaultShow2 = new ConstantProperty_default(true);
var defaultShadows3 = new ConstantProperty_default(ShadowMode_default.DISABLED);
var defaultDistanceDisplayCondition7 = new ConstantProperty_default(
new DistanceDisplayCondition_default()
);
var defaultClassificationType2 = new ConstantProperty_default(ClassificationType_default.BOTH);
function GeometryOptions() {
this.vertexFormat = void 0;
this.positions = void 0;
this.width = void 0;
this.arcType = void 0;
this.granularity = void 0;
}
function GroundGeometryOptions() {
this.positions = void 0;
this.width = void 0;
this.arcType = void 0;
this.granularity = void 0;
}
function PolylineGeometryUpdater(entity, scene) {
if (!defined_default(entity)) {
throw new DeveloperError_default("entity is required");
}
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required");
}
this._entity = entity;
this._scene = scene;
this._entitySubscription = entity.definitionChanged.addEventListener(
PolylineGeometryUpdater.prototype._onEntityPropertyChanged,
this
);
this._fillEnabled = false;
this._dynamic = false;
this._geometryChanged = new Event_default();
this._showProperty = void 0;
this._materialProperty = void 0;
this._shadowsProperty = void 0;
this._distanceDisplayConditionProperty = void 0;
this._classificationTypeProperty = void 0;
this._depthFailMaterialProperty = void 0;
this._geometryOptions = new GeometryOptions();
this._groundGeometryOptions = new GroundGeometryOptions();
this._id = `polyline-${entity.id}`;
this._clampToGround = false;
this._supportsPolylinesOnTerrain = Entity_default.supportsPolylinesOnTerrain(scene);
this._zIndex = 0;
this._onEntityPropertyChanged(entity, "polyline", entity.polyline, void 0);
}
Object.defineProperties(PolylineGeometryUpdater.prototype, {
/**
* Gets the unique ID associated with this updater
* @memberof PolylineGeometryUpdater.prototype
* @type {string}
* @readonly
*/
id: {
get: function() {
return this._id;
}
},
/**
* Gets the entity associated with this geometry.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {Entity}
* @readonly
*/
entity: {
get: function() {
return this._entity;
}
},
/**
* Gets a value indicating if the geometry has a fill component.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {boolean}
* @readonly
*/
fillEnabled: {
get: function() {
return this._fillEnabled;
}
},
/**
* Gets a value indicating if fill visibility varies with simulation time.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {boolean}
* @readonly
*/
hasConstantFill: {
get: function() {
return !this._fillEnabled || !defined_default(this._entity.availability) && Property_default.isConstant(this._showProperty);
}
},
/**
* Gets the material property used to fill the geometry.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {MaterialProperty}
* @readonly
*/
fillMaterialProperty: {
get: function() {
return this._materialProperty;
}
},
/**
* Gets the material property used to fill the geometry when it fails the depth test.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {MaterialProperty}
* @readonly
*/
depthFailMaterialProperty: {
get: function() {
return this._depthFailMaterialProperty;
}
},
/**
* Gets a value indicating if the geometry has an outline component.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {boolean}
* @readonly
*/
outlineEnabled: {
value: false
},
/**
* Gets a value indicating if outline visibility varies with simulation time.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {boolean}
* @readonly
*/
hasConstantOutline: {
value: true
},
/**
* Gets the {@link Color} property for the geometry outline.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {Property}
* @readonly
*/
outlineColorProperty: {
value: void 0
},
/**
* Gets the property specifying whether the geometry
* casts or receives shadows from light sources.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {Property}
* @readonly
*/
shadowsProperty: {
get: function() {
return this._shadowsProperty;
}
},
/**
* Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this geometry will be displayed.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {Property}
* @readonly
*/
distanceDisplayConditionProperty: {
get: function() {
return this._distanceDisplayConditionProperty;
}
},
/**
* Gets or sets the {@link ClassificationType} Property specifying if this geometry will classify terrain, 3D Tiles, or both when on the ground.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {Property}
* @readonly
*/
classificationTypeProperty: {
get: function() {
return this._classificationTypeProperty;
}
},
/**
* Gets a value indicating if the geometry is time-varying.
*
* @memberof PolylineGeometryUpdater.prototype
*
* @type {boolean}
* @readonly
*/
isDynamic: {
get: function() {
return this._dynamic;
}
},
/**
* Gets a value indicating if the geometry is closed.
* This property is only valid for static geometry.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {boolean}
* @readonly
*/
isClosed: {
value: false
},
/**
* Gets an event that is raised whenever the public properties
* of this updater change.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {boolean}
* @readonly
*/
geometryChanged: {
get: function() {
return this._geometryChanged;
}
},
/**
* Gets a value indicating if the path of the line.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {ArcType}
* @readonly
*/
arcType: {
get: function() {
return this._arcType;
}
},
/**
* Gets a value indicating if the geometry is clamped to the ground.
* Returns false if polylines on terrain is not supported.
* @memberof PolylineGeometryUpdater.prototype
*
* @type {boolean}
* @readonly
*/
clampToGround: {
get: function() {
return this._clampToGround && this._supportsPolylinesOnTerrain;
}
},
/**
* Gets the zindex
* @type {number}
* @memberof PolylineGeometryUpdater.prototype
* @readonly
*/
zIndex: {
get: function() {
return this._zIndex;
}
}
});
PolylineGeometryUpdater.prototype.isOutlineVisible = function(time) {
return false;
};
PolylineGeometryUpdater.prototype.isFilled = function(time) {
const entity = this._entity;
const visible = this._fillEnabled && entity.isAvailable(time) && this._showProperty.getValue(time);
return visible ?? false;
};
PolylineGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
if (!defined_default(time)) {
throw new DeveloperError_default("time is required.");
}
if (!this._fillEnabled) {
throw new DeveloperError_default(
"This instance does not represent a filled geometry."
);
}
const entity = this._entity;
const isAvailable = entity.isAvailable(time);
const show = new ShowGeometryInstanceAttribute_default(
isAvailable && entity.isShowing && this._showProperty.getValue(time)
);
const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
const distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute_default.fromDistanceDisplayCondition(
distanceDisplayCondition
);
const attributes = {
show,
distanceDisplayCondition: distanceDisplayConditionAttribute
};
let currentColor;
if (this._materialProperty instanceof ColorMaterialProperty_default) {
if (defined_default(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
currentColor = this._materialProperty.color.getValue(time, scratchColor24);
}
if (!defined_default(currentColor)) {
currentColor = Color_default.WHITE;
}
attributes.color = ColorGeometryInstanceAttribute_default.fromColor(currentColor);
}
if (this.clampToGround) {
return new GeometryInstance_default({
id: entity,
geometry: new GroundPolylineGeometry_default(this._groundGeometryOptions),
attributes
});
}
if (defined_default(this._depthFailMaterialProperty) && this._depthFailMaterialProperty instanceof ColorMaterialProperty_default) {
if (defined_default(this._depthFailMaterialProperty.color) && (this._depthFailMaterialProperty.color.isConstant || isAvailable)) {
currentColor = this._depthFailMaterialProperty.color.getValue(
time,
scratchColor24
);
}
if (!defined_default(currentColor)) {
currentColor = Color_default.WHITE;
}
attributes.depthFailColor = ColorGeometryInstanceAttribute_default.fromColor(currentColor);
}
return new GeometryInstance_default({
id: entity,
geometry: new PolylineGeometry_default(this._geometryOptions),
attributes
});
};
PolylineGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
throw new DeveloperError_default(
"This instance does not represent an outlined geometry."
);
};
PolylineGeometryUpdater.prototype.isDestroyed = function() {
return false;
};
PolylineGeometryUpdater.prototype.destroy = function() {
this._entitySubscription();
destroyObject_default(this);
};
PolylineGeometryUpdater.prototype._onEntityPropertyChanged = function(entity, propertyName, newValue, oldValue2) {
if (!(propertyName === "availability" || propertyName === "polyline")) {
return;
}
const polyline = this._entity.polyline;
if (!defined_default(polyline)) {
if (this._fillEnabled) {
this._fillEnabled = false;
this._geometryChanged.raiseEvent(this);
}
return;
}
const positionsProperty = polyline.positions;
const show = polyline.show;
if (defined_default(show) && show.isConstant && !show.getValue(Iso8601_default.MINIMUM_VALUE) || //
!defined_default(positionsProperty)) {
if (this._fillEnabled) {
this._fillEnabled = false;
this._geometryChanged.raiseEvent(this);
}
return;
}
const zIndex = polyline.zIndex;
const material = polyline.material ?? defaultMaterial3;
const isColorMaterial = material instanceof ColorMaterialProperty_default;
this._materialProperty = material;
this._depthFailMaterialProperty = polyline.depthFailMaterial;
this._showProperty = show ?? defaultShow2;
this._shadowsProperty = polyline.shadows ?? defaultShadows3;
this._distanceDisplayConditionProperty = polyline.distanceDisplayCondition ?? defaultDistanceDisplayCondition7;
this._classificationTypeProperty = polyline.classificationType ?? defaultClassificationType2;
this._fillEnabled = true;
this._zIndex = zIndex ?? defaultZIndex2;
const width = polyline.width;
const arcType = polyline.arcType;
const clampToGround = polyline.clampToGround;
const granularity = polyline.granularity;
if (!positionsProperty.isConstant || !Property_default.isConstant(width) || !Property_default.isConstant(arcType) || !Property_default.isConstant(granularity) || !Property_default.isConstant(clampToGround) || !Property_default.isConstant(zIndex)) {
if (!this._dynamic) {
this._dynamic = true;
this._geometryChanged.raiseEvent(this);
}
} else {
const geometryOptions = this._geometryOptions;
const positions = positionsProperty.getValue(
Iso8601_default.MINIMUM_VALUE,
geometryOptions.positions
);
if (!defined_default(positions) || positions.length < 2) {
if (this._fillEnabled) {
this._fillEnabled = false;
this._geometryChanged.raiseEvent(this);
}
return;
}
let vertexFormat;
if (isColorMaterial && (!defined_default(this._depthFailMaterialProperty) || this._depthFailMaterialProperty instanceof ColorMaterialProperty_default)) {
vertexFormat = PolylineColorAppearance_default.VERTEX_FORMAT;
} else {
vertexFormat = PolylineMaterialAppearance_default.VERTEX_FORMAT;
}
geometryOptions.vertexFormat = vertexFormat;
geometryOptions.positions = positions;
geometryOptions.width = defined_default(width) ? width.getValue(Iso8601_default.MINIMUM_VALUE) : void 0;
geometryOptions.arcType = defined_default(arcType) ? arcType.getValue(Iso8601_default.MINIMUM_VALUE) : void 0;
geometryOptions.granularity = defined_default(granularity) ? granularity.getValue(Iso8601_default.MINIMUM_VALUE) : void 0;
const groundGeometryOptions = this._groundGeometryOptions;
groundGeometryOptions.positions = positions;
groundGeometryOptions.width = geometryOptions.width;
groundGeometryOptions.arcType = geometryOptions.arcType;
groundGeometryOptions.granularity = geometryOptions.granularity;
this._clampToGround = defined_default(clampToGround) ? clampToGround.getValue(Iso8601_default.MINIMUM_VALUE) : false;
if (!this._clampToGround && defined_default(zIndex)) {
oneTimeWarning_default(
"Entity polylines must have clampToGround: true when using zIndex. zIndex will be ignored."
);
}
this._dynamic = false;
this._geometryChanged.raiseEvent(this);
}
};
PolylineGeometryUpdater.prototype.createDynamicUpdater = function(primitives, groundPrimitives) {
Check_default.defined("primitives", primitives);
Check_default.defined("groundPrimitives", groundPrimitives);
if (!this._dynamic) {
throw new DeveloperError_default(
"This instance does not represent dynamic geometry."
);
}
return new DynamicGeometryUpdater2(primitives, groundPrimitives, this);
};
var generateCartesianArcOptions = {
positions: void 0,
granularity: void 0,
height: void 0,
ellipsoid: void 0
};
function DynamicGeometryUpdater2(primitives, groundPrimitives, geometryUpdater) {
this._line = void 0;
this._primitives = primitives;
this._groundPrimitives = groundPrimitives;
this._groundPolylinePrimitive = void 0;
this._material = void 0;
this._geometryUpdater = geometryUpdater;
this._positions = [];
}
function getLine(dynamicGeometryUpdater) {
if (defined_default(dynamicGeometryUpdater._line)) {
return dynamicGeometryUpdater._line;
}
const primitives = dynamicGeometryUpdater._primitives;
const polylineCollectionId = dynamicGeometryUpdater._geometryUpdater._scene.id + primitives._guid;
let polylineCollection = polylineCollections[polylineCollectionId];
if (!defined_default(polylineCollection) || polylineCollection.isDestroyed()) {
polylineCollection = new PolylineCollection_default();
polylineCollections[polylineCollectionId] = polylineCollection;
primitives.add(polylineCollection);
} else if (!primitives.contains(polylineCollection)) {
primitives.add(polylineCollection);
}
const line = polylineCollection.add();
line.id = dynamicGeometryUpdater._geometryUpdater._entity;
dynamicGeometryUpdater._line = line;
return line;
}
DynamicGeometryUpdater2.prototype.update = function(time) {
const geometryUpdater = this._geometryUpdater;
const entity = geometryUpdater._entity;
const polyline = entity.polyline;
const positionsProperty = polyline.positions;
let positions = Property_default.getValueOrUndefined(
positionsProperty,
time,
this._positions
);
geometryUpdater._clampToGround = Property_default.getValueOrDefault(
polyline._clampToGround,
time,
false
);
geometryUpdater._groundGeometryOptions.positions = positions;
geometryUpdater._groundGeometryOptions.width = Property_default.getValueOrDefault(
polyline._width,
time,
1
);
geometryUpdater._groundGeometryOptions.arcType = Property_default.getValueOrDefault(
polyline._arcType,
time,
ArcType_default.GEODESIC
);
geometryUpdater._groundGeometryOptions.granularity = Property_default.getValueOrDefault(polyline._granularity, time, 9999);
const groundPrimitives = this._groundPrimitives;
if (defined_default(this._groundPolylinePrimitive)) {
groundPrimitives.remove(this._groundPolylinePrimitive);
this._groundPolylinePrimitive = void 0;
}
if (geometryUpdater.clampToGround) {
if (!entity.isShowing || !entity.isAvailable(time) || !Property_default.getValueOrDefault(polyline._show, time, true)) {
return;
}
if (!defined_default(positions) || positions.length < 2) {
return;
}
const fillMaterialProperty = geometryUpdater.fillMaterialProperty;
let appearance;
if (fillMaterialProperty instanceof ColorMaterialProperty_default) {
appearance = new PolylineColorAppearance_default();
} else {
const material = MaterialProperty_default.getValue(
time,
fillMaterialProperty,
this._material
);
appearance = new PolylineMaterialAppearance_default({
material,
translucent: material.isTranslucent()
});
this._material = material;
}
this._groundPolylinePrimitive = groundPrimitives.add(
new GroundPolylinePrimitive_default({
geometryInstances: geometryUpdater.createFillGeometryInstance(time),
appearance,
classificationType: geometryUpdater.classificationTypeProperty.getValue(time),
asynchronous: false
}),
Property_default.getValueOrUndefined(geometryUpdater.zIndex, time)
);
if (defined_default(this._line)) {
this._line.show = false;
}
return;
}
const line = getLine(this);
if (!entity.isShowing || !entity.isAvailable(time) || !Property_default.getValueOrDefault(polyline._show, time, true)) {
line.show = false;
return;
}
if (!defined_default(positions) || positions.length < 2) {
line.show = false;
return;
}
let arcType = ArcType_default.GEODESIC;
arcType = Property_default.getValueOrDefault(polyline._arcType, time, arcType);
const globe = geometryUpdater._scene.globe;
const ellipsoid = geometryUpdater._scene.ellipsoid;
if (arcType !== ArcType_default.NONE && defined_default(globe)) {
generateCartesianArcOptions.ellipsoid = ellipsoid;
generateCartesianArcOptions.positions = positions;
generateCartesianArcOptions.granularity = Property_default.getValueOrUndefined(
polyline._granularity,
time
);
generateCartesianArcOptions.height = PolylinePipeline_default.extractHeights(
positions,
ellipsoid
);
if (arcType === ArcType_default.GEODESIC) {
positions = PolylinePipeline_default.generateCartesianArc(
generateCartesianArcOptions
);
} else {
positions = PolylinePipeline_default.generateCartesianRhumbArc(
generateCartesianArcOptions
);
}
}
line.show = true;
line.positions = positions.slice();
line.material = MaterialProperty_default.getValue(
time,
geometryUpdater.fillMaterialProperty,
line.material
);
line.width = Property_default.getValueOrDefault(polyline._width, time, 1);
line.distanceDisplayCondition = Property_default.getValueOrUndefined(
polyline._distanceDisplayCondition,
time,
line.distanceDisplayCondition
);
};
DynamicGeometryUpdater2.prototype.getBoundingSphere = function(result) {
Check_default.defined("result", result);
if (!this._geometryUpdater.clampToGround) {
const line = getLine(this);
if (line.show && line.positions.length > 0) {
BoundingSphere_default.fromPoints(line.positions, result);
return BoundingSphereState_default.DONE;
}
} else {
const groundPolylinePrimitive = this._groundPolylinePrimitive;
if (defined_default(groundPolylinePrimitive) && groundPolylinePrimitive.show && groundPolylinePrimitive.ready) {
const attributes = groundPolylinePrimitive.getGeometryInstanceAttributes(
this._geometryUpdater._entity
);
if (defined_default(attributes) && defined_default(attributes.boundingSphere)) {
BoundingSphere_default.clone(attributes.boundingSphere, result);
return BoundingSphereState_default.DONE;
}
}
if (defined_default(groundPolylinePrimitive) && !groundPolylinePrimitive.ready) {
return BoundingSphereState_default.PENDING;
}
return BoundingSphereState_default.DONE;
}
return BoundingSphereState_default.FAILED;
};
DynamicGeometryUpdater2.prototype.isDestroyed = function() {
return false;
};
DynamicGeometryUpdater2.prototype.destroy = function() {
const geometryUpdater = this._geometryUpdater;
const polylineCollectionId = geometryUpdater._scene.id + this._primitives._guid;
const polylineCollection = polylineCollections[polylineCollectionId];
if (defined_default(polylineCollection)) {
polylineCollection.remove(this._line);
if (polylineCollection.length === 0) {
this._primitives.removeAndDestroy(polylineCollection);
delete polylineCollections[polylineCollectionId];
}
}
if (defined_default(this._groundPolylinePrimitive)) {
this._groundPrimitives.remove(this._groundPolylinePrimitive);
}
destroyObject_default(this);
};
var PolylineGeometryUpdater_default = PolylineGeometryUpdater;
// packages/engine/Source/DataSources/StaticGroundPolylinePerMaterialBatch.js
var import_InlineWorkers916 = __toESM(require_InlineWorkers(), 1);
var scratchColor25 = new Color_default();
var distanceDisplayConditionScratch9 = new DistanceDisplayCondition_default();
var defaultDistanceDisplayCondition8 = new DistanceDisplayCondition_default();
function Batch6(orderedGroundPrimitives, classificationType, materialProperty, zIndex, asynchronous) {
let appearanceType;
if (materialProperty instanceof ColorMaterialProperty_default) {
appearanceType = PolylineColorAppearance_default;
} else {
appearanceType = PolylineMaterialAppearance_default;
}
this.orderedGroundPrimitives = orderedGroundPrimitives;
this.classificationType = classificationType;
this.appearanceType = appearanceType;
this.materialProperty = materialProperty;
this.updaters = new AssociativeArray_default();
this.createPrimitive = true;
this.primitive = void 0;
this.oldPrimitive = void 0;
this.geometry = new AssociativeArray_default();
this.material = void 0;
this.updatersWithAttributes = new AssociativeArray_default();
this.attributes = new AssociativeArray_default();
this.invalidated = false;
this.removeMaterialSubscription = materialProperty.definitionChanged.addEventListener(
Batch6.prototype.onMaterialChanged,
this
);
this.subscriptions = new AssociativeArray_default();
this.showsUpdated = new AssociativeArray_default();
this.zIndex = zIndex;
this._asynchronous = asynchronous;
}
Batch6.prototype.onMaterialChanged = function() {
this.invalidated = true;
};
Batch6.prototype.isMaterial = function(updater) {
const material = this.materialProperty;
const updaterMaterial = updater.fillMaterialProperty;
if (updaterMaterial === material || updaterMaterial instanceof ColorMaterialProperty_default && material instanceof ColorMaterialProperty_default) {
return true;
}
return defined_default(material) && material.equals(updaterMaterial);
};
Batch6.prototype.add = function(time, updater, geometryInstance) {
const id = updater.id;
this.updaters.set(id, updater);
this.geometry.set(id, geometryInstance);
if (!updater.hasConstantFill || !updater.fillMaterialProperty.isConstant || !Property_default.isConstant(updater.distanceDisplayConditionProperty)) {
this.updatersWithAttributes.set(id, updater);
} else {
const that = this;
this.subscriptions.set(
id,
updater.entity.definitionChanged.addEventListener(
function(entity, propertyName, newValue, oldValue2) {
if (propertyName === "isShowing") {
that.showsUpdated.set(updater.id, updater);
}
}
)
);
}
this.createPrimitive = true;
};
Batch6.prototype.remove = function(updater) {
const id = updater.id;
this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;
if (this.updaters.remove(id)) {
this.updatersWithAttributes.remove(id);
const unsubscribe2 = this.subscriptions.get(id);
if (defined_default(unsubscribe2)) {
unsubscribe2();
this.subscriptions.remove(id);
}
return true;
}
return false;
};
Batch6.prototype.update = function(time) {
let isUpdated = true;
let primitive = this.primitive;
const orderedGroundPrimitives = this.orderedGroundPrimitives;
const geometries = this.geometry.values;
let i;
if (this.createPrimitive) {
const geometriesLength = geometries.length;
if (geometriesLength > 0) {
if (defined_default(primitive)) {
if (!defined_default(this.oldPrimitive)) {
this.oldPrimitive = primitive;
} else {
orderedGroundPrimitives.remove(primitive);
}
}
primitive = new GroundPolylinePrimitive_default({
show: false,
asynchronous: this._asynchronous,
geometryInstances: geometries.slice(),
appearance: new this.appearanceType(),
classificationType: this.classificationType
});
if (this.appearanceType === PolylineMaterialAppearance_default) {
this.material = MaterialProperty_default.getValue(
time,
this.materialProperty,
this.material
);
primitive.appearance.material = this.material;
}
orderedGroundPrimitives.add(primitive, this.zIndex);
isUpdated = false;
} else {
if (defined_default(primitive)) {
orderedGroundPrimitives.remove(primitive);
primitive = void 0;
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
orderedGroundPrimitives.remove(oldPrimitive);
this.oldPrimitive = void 0;
}
}
this.attributes.removeAll();
this.primitive = primitive;
this.createPrimitive = false;
} else if (defined_default(primitive) && primitive.ready) {
primitive.show = true;
if (defined_default(this.oldPrimitive)) {
orderedGroundPrimitives.remove(this.oldPrimitive);
this.oldPrimitive = void 0;
}
if (this.appearanceType === PolylineMaterialAppearance_default) {
this.material = MaterialProperty_default.getValue(
time,
this.materialProperty,
this.material
);
this.primitive.appearance.material = this.material;
}
const updatersWithAttributes = this.updatersWithAttributes.values;
const length2 = updatersWithAttributes.length;
for (i = 0; i < length2; i++) {
const updater = updatersWithAttributes[i];
const entity = updater.entity;
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
if (!updater.fillMaterialProperty.isConstant) {
const colorProperty = updater.fillMaterialProperty.color;
const resultColor = Property_default.getValueOrDefault(
colorProperty,
time,
Color_default.WHITE,
scratchColor25
);
if (!Color_default.equals(attributes._lastColor, resultColor)) {
attributes._lastColor = Color_default.clone(
resultColor,
attributes._lastColor
);
attributes.color = ColorGeometryInstanceAttribute_default.toValue(
resultColor,
attributes.color
);
}
}
const show = entity.isShowing && (updater.hasConstantFill || updater.isFilled(time));
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
}
const distanceDisplayConditionProperty = updater.distanceDisplayConditionProperty;
if (!Property_default.isConstant(distanceDisplayConditionProperty)) {
const distanceDisplayCondition = Property_default.getValueOrDefault(
distanceDisplayConditionProperty,
time,
defaultDistanceDisplayCondition8,
distanceDisplayConditionScratch9
);
if (!DistanceDisplayCondition_default.equals(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
)) {
attributes._lastDistanceDisplayCondition = DistanceDisplayCondition_default.clone(
distanceDisplayCondition,
attributes._lastDistanceDisplayCondition
);
attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute_default.toValue(
distanceDisplayCondition,
attributes.distanceDisplayCondition
);
}
}
}
this.updateShows(primitive);
} else if (defined_default(primitive) && !primitive.ready) {
isUpdated = false;
}
return isUpdated;
};
Batch6.prototype.updateShows = function(primitive) {
const showsUpdated = this.showsUpdated.values;
const length2 = showsUpdated.length;
for (let i = 0; i < length2; i++) {
const updater = showsUpdated[i];
const entity = updater.entity;
const instance = this.geometry.get(updater.id);
let attributes = this.attributes.get(instance.id.id);
if (!defined_default(attributes)) {
attributes = primitive.getGeometryInstanceAttributes(instance.id);
this.attributes.set(instance.id.id, attributes);
}
const show = entity.isShowing;
const currentShow = attributes.show[0] === 1;
if (show !== currentShow) {
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
show,
attributes.show
);
instance.attributes.show.value[0] = attributes.show[0];
}
}
this.showsUpdated.removeAll();
};
Batch6.prototype.contains = function(updater) {
return this.updaters.contains(updater.id);
};
Batch6.prototype.getBoundingSphere = function(updater, result) {
const primitive = this.primitive;
if (!primitive.ready) {
return BoundingSphereState_default.PENDING;
}
const attributes = primitive.getGeometryInstanceAttributes(updater.entity);
if (!defined_default(attributes) || !defined_default(attributes.boundingSphere) || defined_default(attributes.show) && attributes.show[0] === 0) {
return BoundingSphereState_default.FAILED;
}
attributes.boundingSphere.clone(result);
return BoundingSphereState_default.DONE;
};
Batch6.prototype.destroy = function() {
const primitive = this.primitive;
const orderedGroundPrimitives = this.orderedGroundPrimitives;
if (defined_default(primitive)) {
orderedGroundPrimitives.remove(primitive);
}
const oldPrimitive = this.oldPrimitive;
if (defined_default(oldPrimitive)) {
orderedGroundPrimitives.remove(oldPrimitive);
}
this.removeMaterialSubscription();
};
function StaticGroundPolylinePerMaterialBatch(orderedGroundPrimitives, classificationType, asynchronous) {
this._items = [];
this._orderedGroundPrimitives = orderedGroundPrimitives;
this._classificationType = classificationType;
this._asynchronous = asynchronous ?? true;
}
StaticGroundPolylinePerMaterialBatch.prototype.add = function(time, updater) {
const items = this._items;
const length2 = items.length;
const geometryInstance = updater.createFillGeometryInstance(time);
const zIndex = Property_default.getValueOrDefault(updater.zIndex, 0);
for (let i = 0; i < length2; ++i) {
const item = items[i];
if (item.isMaterial(updater) && item.zIndex === zIndex) {
item.add(time, updater, geometryInstance);
return;
}
}
const batch = new Batch6(
this._orderedGroundPrimitives,
this._classificationType,
updater.fillMaterialProperty,
zIndex,
this._asynchronous
);
batch.add(time, updater, geometryInstance);
items.push(batch);
};
StaticGroundPolylinePerMaterialBatch.prototype.remove = function(updater) {
const items = this._items;
const length2 = items.length;
for (let i = length2 - 1; i >= 0; i--) {
const item = items[i];
if (item.remove(updater)) {
if (item.updaters.length === 0) {
items.splice(i, 1);
item.destroy();
}
break;
}
}
};
StaticGroundPolylinePerMaterialBatch.prototype.update = function(time) {
let i;
const items = this._items;
const length2 = items.length;
for (i = length2 - 1; i >= 0; i--) {
const item = items[i];
if (item.invalidated) {
items.splice(i, 1);
const updaters = item.updaters.values;
const updatersLength = updaters.length;
for (let h = 0; h < updatersLength; h++) {
this.add(time, updaters[h]);
}
item.destroy();
}
}
let isUpdated = true;
for (i = 0; i < items.length; i++) {
isUpdated = items[i].update(time) && isUpdated;
}
return isUpdated;
};
StaticGroundPolylinePerMaterialBatch.prototype.getBoundingSphere = function(updater, result) {
const items = this._items;
const length2 = items.length;
for (let i = 0; i < length2; i++) {
const item = items[i];
if (item.contains(updater)) {
return item.getBoundingSphere(updater, result);
}
}
return BoundingSphereState_default.FAILED;
};
StaticGroundPolylinePerMaterialBatch.prototype.removeAllPrimitives = function() {
const items = this._items;
const length2 = items.length;
for (let i = 0; i < length2; i++) {
items[i].destroy();
}
this._items.length = 0;
};
var StaticGroundPolylinePerMaterialBatch_default = StaticGroundPolylinePerMaterialBatch;
// packages/engine/Source/DataSources/PolylineVisualizer.js
var emptyArray2 = [];
function removeUpdater(that, updater) {
const batches = that._batches;
const length2 = batches.length;
for (let i = 0; i < length2; i++) {
batches[i].remove(updater);
}
}
function insertUpdaterIntoBatch(that, time, updater) {
if (updater.isDynamic) {
that._dynamicBatch.add(time, updater);
return;
}
if (updater.clampToGround && updater.fillEnabled) {
const classificationType = updater.classificationTypeProperty.getValue(time);
that._groundBatches[classificationType].add(time, updater);
return;
}
let shadows;
if (updater.fillEnabled) {
shadows = updater.shadowsProperty.getValue(time);
}
let multiplier = 0;
if (defined_default(updater.depthFailMaterialProperty)) {
multiplier = updater.depthFailMaterialProperty instanceof ColorMaterialProperty_default ? 1 : 2;
}
let index;
if (defined_default(shadows)) {
index = shadows + multiplier * ShadowMode_default.NUMBER_OF_SHADOW_MODES;
}
if (updater.fillEnabled) {
if (updater.fillMaterialProperty instanceof ColorMaterialProperty_default) {
that._colorBatches[index].add(time, updater);
} else {
that._materialBatches[index].add(time, updater);
}
}
}
function PolylineVisualizer(scene, entityCollection, primitives, groundPrimitives) {
Check_default.defined("scene", scene);
Check_default.defined("entityCollection", entityCollection);
groundPrimitives = groundPrimitives ?? scene.groundPrimitives;
primitives = primitives ?? scene.primitives;
this._scene = scene;
this._primitives = primitives;
this._entityCollection = void 0;
this._addedObjects = new AssociativeArray_default();
this._removedObjects = new AssociativeArray_default();
this._changedObjects = new AssociativeArray_default();
let i;
const numberOfShadowModes = ShadowMode_default.NUMBER_OF_SHADOW_MODES;
this._colorBatches = new Array(numberOfShadowModes * 3);
this._materialBatches = new Array(numberOfShadowModes * 3);
for (i = 0; i < numberOfShadowModes; ++i) {
this._colorBatches[i] = new StaticGeometryColorBatch_default(
primitives,
PolylineColorAppearance_default,
void 0,
false,
i
);
this._materialBatches[i] = new StaticGeometryPerMaterialBatch_default(
primitives,
PolylineMaterialAppearance_default,
void 0,
false,
i
);
this._colorBatches[i + numberOfShadowModes] = new StaticGeometryColorBatch_default(
primitives,
PolylineColorAppearance_default,
PolylineColorAppearance_default,
false,
i
);
this._materialBatches[i + numberOfShadowModes] = new StaticGeometryPerMaterialBatch_default(
primitives,
PolylineMaterialAppearance_default,
PolylineColorAppearance_default,
false,
i
);
this._colorBatches[i + numberOfShadowModes * 2] = new StaticGeometryColorBatch_default(
primitives,
PolylineColorAppearance_default,
PolylineMaterialAppearance_default,
false,
i
);
this._materialBatches[i + numberOfShadowModes * 2] = new StaticGeometryPerMaterialBatch_default(
primitives,
PolylineMaterialAppearance_default,
PolylineMaterialAppearance_default,
false,
i
);
}
this._dynamicBatch = new DynamicGeometryBatch_default(primitives, groundPrimitives);
const numberOfClassificationTypes = ClassificationType_default.NUMBER_OF_CLASSIFICATION_TYPES;
this._groundBatches = new Array(numberOfClassificationTypes);
for (i = 0; i < numberOfClassificationTypes; ++i) {
this._groundBatches[i] = new StaticGroundPolylinePerMaterialBatch_default(
groundPrimitives,
i
);
}
this._batches = this._colorBatches.concat(
this._materialBatches,
this._dynamicBatch,
this._groundBatches
);
this._subscriptions = new AssociativeArray_default();
this._updaters = new AssociativeArray_default();
this._entityCollection = entityCollection;
entityCollection.collectionChanged.addEventListener(
PolylineVisualizer.prototype._onCollectionChanged,
this
);
this._onCollectionChanged(
entityCollection,
entityCollection.values,
emptyArray2
);
}
PolylineVisualizer.prototype.update = function(time) {
Check_default.defined("time", time);
const addedObjects = this._addedObjects;
const added = addedObjects.values;
const removedObjects = this._removedObjects;
const removed = removedObjects.values;
const changedObjects = this._changedObjects;
const changed = changedObjects.values;
let i;
let entity;
let id;
let updater;
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i];
id = entity.id;
updater = this._updaters.get(id);
if (updater.entity === entity) {
removeUpdater(this, updater);
insertUpdaterIntoBatch(this, time, updater);
} else {
removed.push(entity);
added.push(entity);
}
}
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i];
id = entity.id;
updater = this._updaters.get(id);
removeUpdater(this, updater);
updater.destroy();
this._updaters.remove(id);
this._subscriptions.get(id)();
this._subscriptions.remove(id);
}
for (i = added.length - 1; i > -1; i--) {
entity = added[i];
id = entity.id;
updater = new PolylineGeometryUpdater_default(entity, this._scene);
this._updaters.set(id, updater);
insertUpdaterIntoBatch(this, time, updater);
this._subscriptions.set(
id,
updater.geometryChanged.addEventListener(
PolylineVisualizer._onGeometryChanged,
this
)
);
}
addedObjects.removeAll();
removedObjects.removeAll();
changedObjects.removeAll();
let isUpdated = true;
const batches = this._batches;
const length2 = batches.length;
for (i = 0; i < length2; i++) {
isUpdated = batches[i].update(time) && isUpdated;
}
return isUpdated;
};
var getBoundingSphereArrayScratch2 = [];
var getBoundingSphereBoundingSphereScratch2 = new BoundingSphere_default();
PolylineVisualizer.prototype.getBoundingSphere = function(entity, result) {
Check_default.defined("entity", entity);
Check_default.defined("result", result);
const boundingSpheres = getBoundingSphereArrayScratch2;
const tmp2 = getBoundingSphereBoundingSphereScratch2;
let count = 0;
let state = BoundingSphereState_default.DONE;
const batches = this._batches;
const batchesLength = batches.length;
const updater = this._updaters.get(entity.id);
for (let i = 0; i < batchesLength; i++) {
state = batches[i].getBoundingSphere(updater, tmp2);
if (state === BoundingSphereState_default.PENDING) {
return BoundingSphereState_default.PENDING;
} else if (state === BoundingSphereState_default.DONE) {
boundingSpheres[count] = BoundingSphere_default.clone(
tmp2,
boundingSpheres[count]
);
count++;
}
}
if (count === 0) {
return BoundingSphereState_default.FAILED;
}
boundingSpheres.length = count;
BoundingSphere_default.fromBoundingSpheres(boundingSpheres, result);
return BoundingSphereState_default.DONE;
};
PolylineVisualizer.prototype.isDestroyed = function() {
return false;
};
PolylineVisualizer.prototype.destroy = function() {
this._entityCollection.collectionChanged.removeEventListener(
PolylineVisualizer.prototype._onCollectionChanged,
this
);
this._addedObjects.removeAll();
this._removedObjects.removeAll();
let i;
const batches = this._batches;
let length2 = batches.length;
for (i = 0; i < length2; i++) {
batches[i].removeAllPrimitives();
}
const subscriptions = this._subscriptions.values;
length2 = subscriptions.length;
for (i = 0; i < length2; i++) {
subscriptions[i]();
}
this._subscriptions.removeAll();
return destroyObject_default(this);
};
PolylineVisualizer._onGeometryChanged = function(updater) {
const removedObjects = this._removedObjects;
const changedObjects = this._changedObjects;
const entity = updater.entity;
const id = entity.id;
if (!defined_default(removedObjects.get(id)) && !defined_default(changedObjects.get(id))) {
changedObjects.set(id, entity);
}
};
PolylineVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed) {
const addedObjects = this._addedObjects;
const removedObjects = this._removedObjects;
const changedObjects = this._changedObjects;
let i;
let id;
let entity;
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i];
id = entity.id;
if (!addedObjects.remove(id)) {
removedObjects.set(id, entity);
changedObjects.remove(id);
}
}
for (i = added.length - 1; i > -1; i--) {
entity = added[i];
id = entity.id;
if (removedObjects.remove(id)) {
changedObjects.set(id, entity);
} else {
addedObjects.set(id, entity);
}
}
};
var PolylineVisualizer_default = PolylineVisualizer;
// packages/engine/Source/DataSources/DataSourceDisplay.js
function DataSourceDisplay(options) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.object("options.scene", options.scene);
Check_default.typeOf.object(
"options.dataSourceCollection",
options.dataSourceCollection
);
GroundPrimitive_default.initializeTerrainHeights();
GroundPolylinePrimitive_default.initializeTerrainHeights();
const scene = options.scene;
const dataSourceCollection = options.dataSourceCollection;
this._eventHelper = new EventHelper_default();
this._eventHelper.add(
dataSourceCollection.dataSourceAdded,
this._onDataSourceAdded,
this
);
this._eventHelper.add(
dataSourceCollection.dataSourceRemoved,
this._onDataSourceRemoved,
this
);
this._eventHelper.add(
dataSourceCollection.dataSourceMoved,
this._onDataSourceMoved,
this
);
this._eventHelper.add(scene.postRender, this._postRender, this);
this._dataSourceCollection = dataSourceCollection;
this._scene = scene;
this._visualizersCallback = options.visualizersCallback ?? DataSourceDisplay.defaultVisualizersCallback;
let primitivesAdded = false;
const primitives = new PrimitiveCollection_default();
const groundPrimitives = new PrimitiveCollection_default();
if (dataSourceCollection.length > 0) {
scene.primitives.add(primitives);
scene.groundPrimitives.add(groundPrimitives);
primitivesAdded = true;
}
this._primitives = primitives;
this._groundPrimitives = groundPrimitives;
for (let i = 0, len = dataSourceCollection.length; i < len; i++) {
this._onDataSourceAdded(dataSourceCollection, dataSourceCollection.get(i));
}
const defaultDataSource = new CustomDataSource_default();
this._onDataSourceAdded(void 0, defaultDataSource);
this._defaultDataSource = defaultDataSource;
let removeDefaultDataSourceListener;
let removeDataSourceCollectionListener;
if (!primitivesAdded) {
const that = this;
const addPrimitives = function() {
scene.primitives.add(primitives);
scene.groundPrimitives.add(groundPrimitives);
removeDefaultDataSourceListener();
removeDataSourceCollectionListener();
that._removeDefaultDataSourceListener = void 0;
that._removeDataSourceCollectionListener = void 0;
};
removeDefaultDataSourceListener = defaultDataSource.entities.collectionChanged.addEventListener(
addPrimitives
);
removeDataSourceCollectionListener = dataSourceCollection.dataSourceAdded.addEventListener(addPrimitives);
}
this._removeDefaultDataSourceListener = removeDefaultDataSourceListener;
this._removeDataSourceCollectionListener = removeDataSourceCollectionListener;
this._ready = false;
}
var ExtraVisualizers = [];
DataSourceDisplay.registerVisualizer = function(visualizer) {
if (!ExtraVisualizers.includes(visualizer)) {
ExtraVisualizers.push(visualizer);
}
};
DataSourceDisplay.unregisterVisualizer = function(visualizer) {
if (ExtraVisualizers.includes(visualizer)) {
const index = ExtraVisualizers.indexOf(visualizer);
ExtraVisualizers.splice(index, 1);
}
};
DataSourceDisplay.defaultVisualizersCallback = function(scene, entityCluster, dataSource) {
const entities = dataSource.entities;
return [
new BillboardVisualizer_default(entityCluster, entities),
new GeometryVisualizer_default(
scene,
entities,
dataSource._primitives,
dataSource._groundPrimitives
),
new LabelVisualizer_default(entityCluster, entities),
new ModelVisualizer_default(scene, entities),
new Cesium3DTilesetVisualizer_default(scene, entities),
new PointVisualizer_default(entityCluster, entities),
new PathVisualizer_default(scene, entities),
new PolylineVisualizer_default(
scene,
entities,
dataSource._primitives,
dataSource._groundPrimitives
),
...ExtraVisualizers.map(
(VisualizerClass) => new VisualizerClass(scene, entities)
)
];
};
Object.defineProperties(DataSourceDisplay.prototype, {
/**
* Gets the scene associated with this display.
* @memberof DataSourceDisplay.prototype
* @type {Scene}
*/
scene: {
get: function() {
return this._scene;
}
},
/**
* Gets the collection of data sources to display.
* @memberof DataSourceDisplay.prototype
* @type {DataSourceCollection}
*/
dataSources: {
get: function() {
return this._dataSourceCollection;
}
},
/**
* Gets the default data source instance which can be used to
* manually create and visualize entities not tied to
* a specific data source. This instance is always available
* and does not appear in the list dataSources collection.
* @memberof DataSourceDisplay.prototype
* @type {CustomDataSource}
*/
defaultDataSource: {
get: function() {
return this._defaultDataSource;
}
},
/**
* Gets a value indicating whether or not all entities in the data source are ready
* @memberof DataSourceDisplay.prototype
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
}
});
DataSourceDisplay.prototype.isDestroyed = function() {
return false;
};
DataSourceDisplay.prototype.destroy = function() {
this._eventHelper.removeAll();
const dataSourceCollection = this._dataSourceCollection;
for (let i = 0, length2 = dataSourceCollection.length; i < length2; ++i) {
this._onDataSourceRemoved(
this._dataSourceCollection,
dataSourceCollection.get(i)
);
}
this._onDataSourceRemoved(void 0, this._defaultDataSource);
if (defined_default(this._removeDefaultDataSourceListener)) {
this._removeDefaultDataSourceListener();
this._removeDataSourceCollectionListener();
} else {
this._scene.primitives.remove(this._primitives);
this._scene.groundPrimitives.remove(this._groundPrimitives);
}
return destroyObject_default(this);
};
DataSourceDisplay.prototype.update = function(time) {
Check_default.defined("time", time);
if (!ApproximateTerrainHeights_default.initialized) {
this._ready = false;
return false;
}
let result = true;
let i;
let x;
let visualizers;
let vLength;
const dataSources = this._dataSourceCollection;
const length2 = dataSources.length;
for (i = 0; i < length2; i++) {
const dataSource = dataSources.get(i);
if (defined_default(dataSource.update)) {
result = dataSource.update(time) && result;
}
visualizers = dataSource._visualizers;
vLength = visualizers.length;
for (x = 0; x < vLength; x++) {
result = visualizers[x].update(time) && result;
}
}
visualizers = this._defaultDataSource._visualizers;
vLength = visualizers.length;
for (x = 0; x < vLength; x++) {
result = visualizers[x].update(time) && result;
}
if (!this._ready && result) {
this._scene.requestRender();
}
this._ready = this._ready || result;
return result;
};
DataSourceDisplay.prototype._postRender = function() {
const frameState = this._scene.frameState;
const dataSources = this._dataSourceCollection;
const length2 = dataSources.length;
for (let i = 0; i < length2; i++) {
const dataSource = dataSources.get(i);
const credit = dataSource.credit;
if (defined_default(credit)) {
frameState.creditDisplay.addCreditToNextFrame(credit);
}
const credits = dataSource._resourceCredits;
if (defined_default(credits)) {
const creditCount = credits.length;
for (let c = 0; c < creditCount; c++) {
frameState.creditDisplay.addCreditToNextFrame(credits[c]);
}
}
}
};
var getBoundingSphereArrayScratch3 = [];
var getBoundingSphereBoundingSphereScratch3 = new BoundingSphere_default();
DataSourceDisplay.prototype.getBoundingSphere = function(entity, allowPartial, result) {
Check_default.defined("entity", entity);
Check_default.typeOf.bool("allowPartial", allowPartial);
Check_default.defined("result", result);
if (!this._ready) {
return BoundingSphereState_default.PENDING;
}
let i;
let length2;
let dataSource = this._defaultDataSource;
if (!dataSource.entities.contains(entity)) {
dataSource = void 0;
const dataSources = this._dataSourceCollection;
length2 = dataSources.length;
for (i = 0; i < length2; i++) {
const d = dataSources.get(i);
if (d.entities.contains(entity)) {
dataSource = d;
break;
}
}
}
if (!defined_default(dataSource)) {
return BoundingSphereState_default.FAILED;
}
const boundingSpheres = getBoundingSphereArrayScratch3;
const tmp2 = getBoundingSphereBoundingSphereScratch3;
let count = 0;
let state = BoundingSphereState_default.DONE;
const visualizers = dataSource._visualizers;
const visualizersLength = visualizers.length;
for (i = 0; i < visualizersLength; i++) {
const visualizer = visualizers[i];
if (defined_default(visualizer.getBoundingSphere)) {
state = visualizers[i].getBoundingSphere(entity, tmp2);
if (!allowPartial && state === BoundingSphereState_default.PENDING) {
return BoundingSphereState_default.PENDING;
} else if (state === BoundingSphereState_default.DONE) {
boundingSpheres[count] = BoundingSphere_default.clone(
tmp2,
boundingSpheres[count]
);
count++;
}
}
}
if (count === 0) {
return BoundingSphereState_default.FAILED;
}
boundingSpheres.length = count;
BoundingSphere_default.fromBoundingSpheres(boundingSpheres, result);
return BoundingSphereState_default.DONE;
};
DataSourceDisplay.prototype._onDataSourceAdded = function(dataSourceCollection, dataSource) {
const scene = this._scene;
const displayPrimitives = this._primitives;
const displayGroundPrimitives = this._groundPrimitives;
const primitives = displayPrimitives.add(new PrimitiveCollection_default());
const groundPrimitives = displayGroundPrimitives.add(
new OrderedGroundPrimitiveCollection_default()
);
dataSource._primitives = primitives;
dataSource._groundPrimitives = groundPrimitives;
const entityCluster = dataSource.clustering;
entityCluster._initialize(scene);
primitives.add(entityCluster);
dataSource._visualizers = this._visualizersCallback(
scene,
entityCluster,
dataSource
);
};
DataSourceDisplay.prototype._onDataSourceRemoved = function(dataSourceCollection, dataSource) {
const displayPrimitives = this._primitives;
const displayGroundPrimitives = this._groundPrimitives;
const primitives = dataSource._primitives;
const groundPrimitives = dataSource._groundPrimitives;
const entityCluster = dataSource.clustering;
primitives.remove(entityCluster);
const visualizers = dataSource._visualizers;
const length2 = visualizers.length;
for (let i = 0; i < length2; i++) {
visualizers[i].destroy();
}
displayPrimitives.remove(primitives);
displayGroundPrimitives.remove(groundPrimitives);
dataSource._visualizers = void 0;
};
DataSourceDisplay.prototype._onDataSourceMoved = function(dataSource, newIndex, oldIndex) {
const displayPrimitives = this._primitives;
const displayGroundPrimitives = this._groundPrimitives;
const primitives = dataSource._primitives;
const groundPrimitives = dataSource._groundPrimitives;
if (newIndex === oldIndex + 1) {
displayPrimitives.raise(primitives);
displayGroundPrimitives.raise(groundPrimitives);
} else if (newIndex === oldIndex - 1) {
displayPrimitives.lower(primitives);
displayGroundPrimitives.lower(groundPrimitives);
} else if (newIndex === 0) {
displayPrimitives.lowerToBottom(primitives);
displayGroundPrimitives.lowerToBottom(groundPrimitives);
displayPrimitives.raise(primitives);
displayGroundPrimitives.raise(groundPrimitives);
} else {
displayPrimitives.raiseToTop(primitives);
displayGroundPrimitives.raiseToTop(groundPrimitives);
}
};
var DataSourceDisplay_default = DataSourceDisplay;
// packages/engine/Source/DataSources/EntityView.js
var import_InlineWorkers920 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/HeadingPitchRange.js
var import_InlineWorkers919 = __toESM(require_InlineWorkers(), 1);
function HeadingPitchRange(heading, pitch, range) {
this.heading = heading ?? 0;
this.pitch = pitch ?? 0;
this.range = range ?? 0;
}
HeadingPitchRange.clone = function(hpr, result) {
if (!defined_default(hpr)) {
return void 0;
}
if (!defined_default(result)) {
result = new HeadingPitchRange();
}
result.heading = hpr.heading;
result.pitch = hpr.pitch;
result.range = hpr.range;
return result;
};
var HeadingPitchRange_default = HeadingPitchRange;
// packages/engine/Source/DataSources/EntityView.js
var updateTransformMatrix3Scratch1 = new Matrix3_default();
var updateTransformMatrix3Scratch2 = new Matrix3_default();
var updateTransformMatrix3Scratch3 = new Matrix3_default();
var updateTransformMatrix4Scratch = new Matrix4_default();
var updateTransformCartesian3Scratch1 = new Cartesian3_default();
var updateTransformCartesian3Scratch2 = new Cartesian3_default();
var updateTransformCartesian3Scratch3 = new Cartesian3_default();
var updateTransformCartesian3Scratch4 = new Cartesian3_default();
var updateTransformCartesian3Scratch5 = new Cartesian3_default();
var updateTransformCartesian3Scratch6 = new Cartesian3_default();
var updateTransformOrientationScratch = new Quaternion_default();
var velocityScratch2 = new Cartesian3_default();
var rotationScratch3 = new Matrix3_default();
var deltaTime = new JulianDate_default();
var northUpAxisFactor = 1.25;
function updateTransform(that, camera, updateLookAt, saveCamera, positionProperty, velocityProperty, orientationProperty, trackingReferenceFrame, time, ellipsoid) {
const mode2 = that.scene.mode;
let cartesian11 = positionProperty.getValue(time, that._lastCartesian);
if (defined_default(cartesian11)) {
let hasBasis = false;
let invertVelocity = false;
let xBasis;
let yBasis;
let zBasis;
if (mode2 === SceneMode_default.SCENE3D) {
JulianDate_default.addSeconds(time, 1e-3, deltaTime);
let deltaCartesian = positionProperty.getValue(
deltaTime,
updateTransformCartesian3Scratch1
);
if (!defined_default(deltaCartesian)) {
JulianDate_default.addSeconds(time, -1e-3, deltaTime);
deltaCartesian = positionProperty.getValue(
deltaTime,
updateTransformCartesian3Scratch1
);
invertVelocity = true;
}
if (defined_default(deltaCartesian)) {
let toInertial = Transforms_default.computeFixedToIcrfMatrix(
time,
updateTransformMatrix3Scratch1
);
let toInertialDelta = Transforms_default.computeFixedToIcrfMatrix(
deltaTime,
updateTransformMatrix3Scratch2
);
let toFixed;
if (!defined_default(toInertial) || !defined_default(toInertialDelta)) {
toFixed = Transforms_default.computeTemeToPseudoFixedMatrix(
time,
updateTransformMatrix3Scratch3
);
toInertial = Matrix3_default.transpose(
toFixed,
updateTransformMatrix3Scratch1
);
toInertialDelta = Transforms_default.computeTemeToPseudoFixedMatrix(
deltaTime,
updateTransformMatrix3Scratch2
);
Matrix3_default.transpose(toInertialDelta, toInertialDelta);
} else {
toFixed = Matrix3_default.transpose(
toInertial,
updateTransformMatrix3Scratch3
);
}
const inertialCartesian = Matrix3_default.multiplyByVector(
toInertial,
cartesian11,
updateTransformCartesian3Scratch5
);
const inertialDeltaCartesian = Matrix3_default.multiplyByVector(
toInertialDelta,
deltaCartesian,
updateTransformCartesian3Scratch6
);
Cartesian3_default.subtract(
inertialCartesian,
inertialDeltaCartesian,
updateTransformCartesian3Scratch4
);
const inertialVelocity = Cartesian3_default.magnitude(updateTransformCartesian3Scratch4) * 1e3;
const mu = Math_default.GRAVITATIONALPARAMETER;
const semiMajorAxis = -mu / (inertialVelocity * inertialVelocity - 2 * mu / Cartesian3_default.magnitude(inertialCartesian));
if (semiMajorAxis < 0 || semiMajorAxis > northUpAxisFactor * ellipsoid.maximumRadius) {
xBasis = updateTransformCartesian3Scratch2;
Cartesian3_default.normalize(cartesian11, xBasis);
Cartesian3_default.negate(xBasis, xBasis);
zBasis = Cartesian3_default.clone(
Cartesian3_default.UNIT_Z,
updateTransformCartesian3Scratch3
);
yBasis = Cartesian3_default.cross(
zBasis,
xBasis,
updateTransformCartesian3Scratch1
);
if (Cartesian3_default.magnitude(yBasis) > Math_default.EPSILON7) {
Cartesian3_default.normalize(xBasis, xBasis);
Cartesian3_default.normalize(yBasis, yBasis);
zBasis = Cartesian3_default.cross(
xBasis,
yBasis,
updateTransformCartesian3Scratch3
);
Cartesian3_default.normalize(zBasis, zBasis);
hasBasis = true;
}
} else if (!Cartesian3_default.equalsEpsilon(
cartesian11,
deltaCartesian,
Math_default.EPSILON7
)) {
zBasis = updateTransformCartesian3Scratch2;
Cartesian3_default.normalize(inertialCartesian, zBasis);
Cartesian3_default.normalize(inertialDeltaCartesian, inertialDeltaCartesian);
yBasis = Cartesian3_default.cross(
zBasis,
inertialDeltaCartesian,
updateTransformCartesian3Scratch3
);
if (invertVelocity) {
yBasis = Cartesian3_default.multiplyByScalar(yBasis, -1, yBasis);
}
if (!Cartesian3_default.equalsEpsilon(
yBasis,
Cartesian3_default.ZERO,
Math_default.EPSILON7
)) {
xBasis = Cartesian3_default.cross(
yBasis,
zBasis,
updateTransformCartesian3Scratch1
);
Matrix3_default.multiplyByVector(toFixed, xBasis, xBasis);
Matrix3_default.multiplyByVector(toFixed, yBasis, yBasis);
Matrix3_default.multiplyByVector(toFixed, zBasis, zBasis);
Cartesian3_default.normalize(xBasis, xBasis);
Cartesian3_default.normalize(yBasis, yBasis);
Cartesian3_default.normalize(zBasis, zBasis);
hasBasis = true;
}
}
}
}
if (defined_default(that.boundingSphere)) {
cartesian11 = that.boundingSphere.center;
}
let position;
let direction2;
let up;
if (saveCamera) {
position = Cartesian3_default.clone(
camera.position,
updateTransformCartesian3Scratch4
);
direction2 = Cartesian3_default.clone(
camera.direction,
updateTransformCartesian3Scratch5
);
up = Cartesian3_default.clone(camera.up, updateTransformCartesian3Scratch6);
}
const transform3 = updateTransformMatrix4Scratch;
let orientation;
if (defined_default(orientationProperty)) {
orientation = orientationProperty.getValue(
time,
updateTransformOrientationScratch
);
}
const velocity = velocityProperty.getValue(time, velocityScratch2);
if (trackingReferenceFrame === TrackingReferenceFrame_default.INERTIAL && defined_default(orientation)) {
Matrix4_default.fromTranslationQuaternionRotationScale(
cartesian11,
orientation,
Cartesian3_default.ONE,
transform3
);
} else if (trackingReferenceFrame === TrackingReferenceFrame_default.VELOCITY && defined_default(velocity)) {
const rotation = Transforms_default.rotationMatrixFromPositionVelocity(
cartesian11,
velocity,
ellipsoid,
rotationScratch3
);
Matrix4_default.fromRotationTranslation(rotation, cartesian11, transform3);
} else if (trackingReferenceFrame === TrackingReferenceFrame_default.ENU || !hasBasis) {
Transforms_default.eastNorthUpToFixedFrame(cartesian11, ellipsoid, transform3);
} else {
transform3[0] = xBasis.x;
transform3[1] = xBasis.y;
transform3[2] = xBasis.z;
transform3[3] = 0;
transform3[4] = yBasis.x;
transform3[5] = yBasis.y;
transform3[6] = yBasis.z;
transform3[7] = 0;
transform3[8] = zBasis.x;
transform3[9] = zBasis.y;
transform3[10] = zBasis.z;
transform3[11] = 0;
transform3[12] = cartesian11.x;
transform3[13] = cartesian11.y;
transform3[14] = cartesian11.z;
transform3[15] = 0;
}
camera._setTransform(transform3);
if (saveCamera) {
Cartesian3_default.clone(position, camera.position);
Cartesian3_default.clone(direction2, camera.direction);
Cartesian3_default.clone(up, camera.up);
Cartesian3_default.cross(direction2, up, camera.right);
}
}
if (updateLookAt) {
const offset = mode2 === SceneMode_default.SCENE2D || Cartesian3_default.equals(that._offset3D, Cartesian3_default.ZERO) ? void 0 : that._offset3D;
camera.lookAtTransform(camera.transform, offset);
}
}
function EntityView(entity, scene, ellipsoid) {
Check_default.defined("entity", entity);
Check_default.defined("scene", scene);
this.entity = entity;
this.scene = scene;
this.ellipsoid = ellipsoid ?? Ellipsoid_default.default;
this.boundingSphere = void 0;
this._lastEntity = void 0;
this._mode = void 0;
this._lastCartesian = new Cartesian3_default();
this._defaultOffset3D = void 0;
this._velocityProperty = new VelocityVectorProperty_default(entity.position, true);
this._offset3D = new Cartesian3_default();
}
Object.defineProperties(EntityView, {
/**
* Gets or sets a camera offset that will be used to
* initialize subsequent EntityViews.
* @memberof EntityView
* @type {Cartesian3}
*/
defaultOffset3D: {
get: function() {
return this._defaultOffset3D;
},
set: function(vector) {
this._defaultOffset3D = Cartesian3_default.clone(vector, new Cartesian3_default());
}
}
});
EntityView.defaultOffset3D = new Cartesian3_default(-14e3, 3500, 3500);
var scratchHeadingPitchRange = new HeadingPitchRange_default();
var scratchCartesian21 = new Cartesian3_default();
EntityView.prototype.update = function(time, boundingSphere) {
Check_default.defined("time", time);
const scene = this.scene;
const ellipsoid = this.ellipsoid;
const sceneMode = scene.mode;
if (sceneMode === SceneMode_default.MORPHING) {
return;
}
const entity = this.entity;
const trackingReferenceFrame = entity.trackingReferenceFrame;
const positionProperty = entity.position;
if (!defined_default(positionProperty)) {
return;
}
const velocityProperty = this._velocityProperty;
const orientationProperty = entity.orientation;
const objectChanged = entity !== this._lastEntity;
const sceneModeChanged = sceneMode !== this._mode;
const camera = scene.camera;
let updateLookAt = objectChanged || sceneModeChanged;
let saveCamera = true;
if (objectChanged) {
const viewFromProperty = entity.viewFrom;
const hasViewFrom = defined_default(viewFromProperty);
if (!hasViewFrom && defined_default(boundingSphere)) {
scratchHeadingPitchRange.pitch = -Math_default.PI_OVER_FOUR;
scratchHeadingPitchRange.range = 0;
const position = positionProperty.getValue(time, scratchCartesian21);
if (defined_default(position)) {
const factor2 = 2 - 1 / Math.max(
1,
Cartesian3_default.magnitude(position) / ellipsoid.maximumRadius
);
scratchHeadingPitchRange.pitch *= factor2;
}
camera.viewBoundingSphere(boundingSphere, scratchHeadingPitchRange);
this.boundingSphere = boundingSphere;
updateLookAt = false;
saveCamera = false;
} else if (!hasViewFrom || !defined_default(viewFromProperty.getValue(time, this._offset3D))) {
Cartesian3_default.clone(EntityView._defaultOffset3D, this._offset3D);
}
} else if (!sceneModeChanged && this._mode !== SceneMode_default.SCENE2D) {
Cartesian3_default.clone(camera.position, this._offset3D);
}
this._lastEntity = entity;
this._mode = sceneMode;
updateTransform(
this,
camera,
updateLookAt,
saveCamera,
positionProperty,
velocityProperty,
orientationProperty,
trackingReferenceFrame,
time,
ellipsoid
);
};
var EntityView_default = EntityView;
// packages/engine/Source/DataSources/GeoJsonDataSource.js
var import_InlineWorkers935 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PinBuilder.js
var import_InlineWorkers921 = __toESM(require_InlineWorkers(), 1);
function PinBuilder() {
this._cache = {};
}
PinBuilder.prototype.fromColor = function(color, size) {
if (!defined_default(color)) {
throw new DeveloperError_default("color is required");
}
if (!defined_default(size)) {
throw new DeveloperError_default("size is required");
}
return createPin(void 0, void 0, color, size, this._cache);
};
PinBuilder.prototype.fromUrl = function(url2, color, size) {
if (!defined_default(url2)) {
throw new DeveloperError_default("url is required");
}
if (!defined_default(color)) {
throw new DeveloperError_default("color is required");
}
if (!defined_default(size)) {
throw new DeveloperError_default("size is required");
}
return createPin(url2, void 0, color, size, this._cache);
};
PinBuilder.prototype.fromMakiIconId = function(id, color, size) {
if (!defined_default(id)) {
throw new DeveloperError_default("id is required");
}
if (!defined_default(color)) {
throw new DeveloperError_default("color is required");
}
if (!defined_default(size)) {
throw new DeveloperError_default("size is required");
}
return createPin(
buildModuleUrl_default(`Assets/Textures/maki/${encodeURIComponent(id)}.png`),
void 0,
color,
size,
this._cache
);
};
PinBuilder.prototype.fromText = function(text2, color, size) {
if (!defined_default(text2)) {
throw new DeveloperError_default("text is required");
}
if (!defined_default(color)) {
throw new DeveloperError_default("color is required");
}
if (!defined_default(size)) {
throw new DeveloperError_default("size is required");
}
return createPin(void 0, text2, color, size, this._cache);
};
var colorScratch7 = new Color_default();
function drawPin(context2D, color, size) {
context2D.save();
context2D.scale(size / 24, size / 24);
context2D.fillStyle = color.toCssColorString();
context2D.strokeStyle = color.brighten(0.6, colorScratch7).toCssColorString();
context2D.lineWidth = 0.846;
context2D.beginPath();
context2D.moveTo(6.72, 0.422);
context2D.lineTo(17.28, 0.422);
context2D.bezierCurveTo(18.553, 0.422, 19.577, 1.758, 19.577, 3.415);
context2D.lineTo(19.577, 10.973);
context2D.bezierCurveTo(19.577, 12.63, 18.553, 13.966, 17.282, 13.966);
context2D.lineTo(14.386, 14.008);
context2D.lineTo(11.826, 23.578);
context2D.lineTo(9.614, 14.008);
context2D.lineTo(6.719, 13.965);
context2D.bezierCurveTo(5.446, 13.983, 4.422, 12.629, 4.422, 10.972);
context2D.lineTo(4.422, 3.416);
context2D.bezierCurveTo(4.423, 1.76, 5.447, 0.423, 6.718, 0.423);
context2D.closePath();
context2D.fill();
context2D.stroke();
context2D.restore();
}
function drawIcon(context2D, image, size) {
const imageSize = size / 2.5;
let sizeX = imageSize;
let sizeY = imageSize;
if (image.width > image.height) {
sizeY = imageSize * (image.height / image.width);
} else if (image.width < image.height) {
sizeX = imageSize * (image.width / image.height);
}
const x = Math.round((size - sizeX) / 2);
const y = Math.round(7 / 24 * size - sizeY / 2);
context2D.globalCompositeOperation = "destination-out";
context2D.drawImage(image, x - 1, y, sizeX, sizeY);
context2D.drawImage(image, x, y - 1, sizeX, sizeY);
context2D.drawImage(image, x + 1, y, sizeX, sizeY);
context2D.drawImage(image, x, y + 1, sizeX, sizeY);
context2D.globalCompositeOperation = "destination-over";
context2D.fillStyle = Color_default.BLACK.toCssColorString();
context2D.fillRect(x - 1, y - 1, sizeX + 2, sizeY + 2);
context2D.globalCompositeOperation = "destination-out";
context2D.drawImage(image, x, y, sizeX, sizeY);
context2D.globalCompositeOperation = "destination-over";
context2D.fillStyle = Color_default.WHITE.toCssColorString();
context2D.fillRect(x - 1, y - 2, sizeX + 2, sizeY + 2);
}
var stringifyScratch = new Array(4);
function createPin(url2, label, color, size, cache) {
stringifyScratch[0] = url2;
stringifyScratch[1] = label;
stringifyScratch[2] = color;
stringifyScratch[3] = size;
const id = JSON.stringify(stringifyScratch);
const item = cache[id];
if (defined_default(item)) {
return item;
}
const canvas = document.createElement("canvas");
canvas.width = size;
canvas.height = size;
const context2D = canvas.getContext("2d");
drawPin(context2D, color, size);
if (defined_default(url2)) {
const resource = Resource_default.createIfNeeded(url2);
const promise = resource.fetchImage().then(function(image) {
drawIcon(context2D, image, size);
cache[id] = canvas;
return canvas;
});
cache[id] = promise;
return promise;
} else if (defined_default(label)) {
const image = writeTextToCanvas_default(label, {
font: `bold ${size}px sans-serif`
});
drawIcon(context2D, image, size);
}
cache[id] = canvas;
return canvas;
}
var PinBuilder_default = PinBuilder;
// node_modules/topojson-client/src/index.js
var import_InlineWorkers934 = __toESM(require_InlineWorkers());
// node_modules/topojson-client/src/bbox.js
var import_InlineWorkers924 = __toESM(require_InlineWorkers());
// node_modules/topojson-client/src/transform.js
var import_InlineWorkers923 = __toESM(require_InlineWorkers());
// node_modules/topojson-client/src/identity.js
var import_InlineWorkers922 = __toESM(require_InlineWorkers());
function identity_default(x) {
return x;
}
// node_modules/topojson-client/src/transform.js
function transform_default(transform3) {
if (transform3 == null) return identity_default;
var x0, y0, kx = transform3.scale[0], ky = transform3.scale[1], dx = transform3.translate[0], dy = transform3.translate[1];
return function(input, i) {
if (!i) x0 = y0 = 0;
var j = 2, n = input.length, output = new Array(n);
output[0] = (x0 += input[0]) * kx + dx;
output[1] = (y0 += input[1]) * ky + dy;
while (j < n) output[j] = input[j], ++j;
return output;
};
}
// node_modules/topojson-client/src/feature.js
var import_InlineWorkers926 = __toESM(require_InlineWorkers());
// node_modules/topojson-client/src/reverse.js
var import_InlineWorkers925 = __toESM(require_InlineWorkers());
function reverse_default(array, n) {
var t, j = array.length, i = j - n;
while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
}
// node_modules/topojson-client/src/feature.js
function feature_default(topology, o) {
if (typeof o === "string") o = topology.objects[o];
return o.type === "GeometryCollection" ? { type: "FeatureCollection", features: o.geometries.map(function(o2) {
return feature(topology, o2);
}) } : feature(topology, o);
}
function feature(topology, o) {
var id = o.id, bbox = o.bbox, properties = o.properties == null ? {} : o.properties, geometry = object(topology, o);
return id == null && bbox == null ? { type: "Feature", properties, geometry } : bbox == null ? { type: "Feature", id, properties, geometry } : { type: "Feature", id, bbox, properties, geometry };
}
function object(topology, o) {
var transformPoint2 = transform_default(topology.transform), arcs = topology.arcs;
function arc(i, points) {
if (points.length) points.pop();
for (var a3 = arcs[i < 0 ? ~i : i], k = 0, n = a3.length; k < n; ++k) {
points.push(transformPoint2(a3[k], k));
}
if (i < 0) reverse_default(points, n);
}
function point(p) {
return transformPoint2(p);
}
function line(arcs2) {
var points = [];
for (var i = 0, n = arcs2.length; i < n; ++i) arc(arcs2[i], points);
if (points.length < 2) points.push(points[0]);
return points;
}
function ring(arcs2) {
var points = line(arcs2);
while (points.length < 4) points.push(points[0]);
return points;
}
function polygon2(arcs2) {
return arcs2.map(ring);
}
function geometry(o2) {
var type = o2.type, coordinates;
switch (type) {
case "GeometryCollection":
return { type, geometries: o2.geometries.map(geometry) };
case "Point":
coordinates = point(o2.coordinates);
break;
case "MultiPoint":
coordinates = o2.coordinates.map(point);
break;
case "LineString":
coordinates = line(o2.arcs);
break;
case "MultiLineString":
coordinates = o2.arcs.map(line);
break;
case "Polygon":
coordinates = polygon2(o2.arcs);
break;
case "MultiPolygon":
coordinates = o2.arcs.map(polygon2);
break;
default:
return null;
}
return { type, coordinates };
}
return geometry(o);
}
// node_modules/topojson-client/src/mesh.js
var import_InlineWorkers928 = __toESM(require_InlineWorkers());
// node_modules/topojson-client/src/stitch.js
var import_InlineWorkers927 = __toESM(require_InlineWorkers());
// node_modules/topojson-client/src/merge.js
var import_InlineWorkers929 = __toESM(require_InlineWorkers());
// node_modules/topojson-client/src/neighbors.js
var import_InlineWorkers931 = __toESM(require_InlineWorkers());
// node_modules/topojson-client/src/bisect.js
var import_InlineWorkers930 = __toESM(require_InlineWorkers());
// node_modules/topojson-client/src/quantize.js
var import_InlineWorkers933 = __toESM(require_InlineWorkers());
// node_modules/topojson-client/src/untransform.js
var import_InlineWorkers932 = __toESM(require_InlineWorkers());
// packages/engine/Source/DataSources/GeoJsonDataSource.js
function defaultCrsFunction(coordinates) {
return Cartesian3_default.fromDegrees(coordinates[0], coordinates[1], coordinates[2]);
}
var crsNames = {
"urn:ogc:def:crs:OGC:1.3:CRS84": defaultCrsFunction,
"EPSG:4326": defaultCrsFunction,
"urn:ogc:def:crs:EPSG::4326": defaultCrsFunction
};
var crsLinkHrefs = {};
var crsLinkTypes = {};
var defaultMarkerSize = 48;
var defaultMarkerSymbol;
var defaultMarkerColor = Color_default.ROYALBLUE;
var defaultStroke = Color_default.YELLOW;
var defaultStrokeWidth = 2;
var defaultFill2 = Color_default.fromBytes(255, 255, 0, 100);
var defaultClampToGround = false;
var sizes = {
small: 24,
medium: 48,
large: 64
};
var simpleStyleIdentifiers = [
"title",
"description",
//
"marker-size",
"marker-symbol",
"marker-color",
"stroke",
//
"stroke-opacity",
"stroke-width",
"fill",
"fill-opacity"
];
function defaultDescribe(properties, nameProperty) {
let html2 = "";
for (const key in properties) {
if (properties.hasOwnProperty(key)) {
if (key === nameProperty || simpleStyleIdentifiers.indexOf(key) !== -1) {
continue;
}
const value = properties[key];
if (defined_default(value)) {
if (typeof value === "object") {
html2 += `${key} ${defaultDescribe(value)} `;
} else {
html2 += `${key} ${value} `;
}
}
}
}
if (html2.length > 0) {
html2 = `${html2}
`;
}
return html2;
}
function createDescriptionCallback(describe, properties, nameProperty) {
let description;
return function(time, result) {
if (!defined_default(description)) {
description = describe(properties, nameProperty);
}
return description;
};
}
function defaultDescribeProperty(properties, nameProperty) {
return new CallbackProperty_default(
createDescriptionCallback(defaultDescribe, properties, nameProperty),
true
);
}
function createObject(geoJson, entityCollection, describe) {
let id = geoJson.id;
if (!defined_default(id) || geoJson.type !== "Feature") {
id = createGuid_default();
} else {
let i = 2;
let finalId = id;
while (defined_default(entityCollection.getById(finalId))) {
finalId = `${id}_${i}`;
i++;
}
id = finalId;
}
const entity = entityCollection.getOrCreateEntity(id);
const properties = geoJson.properties;
if (defined_default(properties)) {
entity.properties = properties;
let nameProperty;
const name = properties.title;
if (defined_default(name)) {
entity.name = name;
nameProperty = "title";
} else {
let namePropertyPrecedence = Number.MAX_VALUE;
for (const key in properties) {
if (properties.hasOwnProperty(key) && properties[key]) {
const lowerKey = key.toLowerCase();
if (namePropertyPrecedence > 1 && lowerKey === "title") {
namePropertyPrecedence = 1;
nameProperty = key;
break;
} else if (namePropertyPrecedence > 2 && lowerKey === "name") {
namePropertyPrecedence = 2;
nameProperty = key;
} else if (namePropertyPrecedence > 3 && /title/i.test(key)) {
namePropertyPrecedence = 3;
nameProperty = key;
} else if (namePropertyPrecedence > 4 && /name/i.test(key)) {
namePropertyPrecedence = 4;
nameProperty = key;
}
}
}
if (defined_default(nameProperty)) {
entity.name = properties[nameProperty];
}
}
const description = properties.description;
if (description !== null) {
entity.description = !defined_default(description) ? describe(properties, nameProperty) : new ConstantProperty_default(description);
}
}
return entity;
}
function coordinatesArrayToCartesianArray(coordinates, crsFunction) {
const positions = new Array(coordinates.length);
for (let i = 0; i < coordinates.length; i++) {
positions[i] = crsFunction(coordinates[i]);
}
return positions;
}
var geoJsonObjectTypes2 = {
Feature: processFeature,
FeatureCollection: processFeatureCollection,
GeometryCollection: processGeometryCollection,
LineString: processLineString,
MultiLineString: processMultiLineString,
MultiPoint: processMultiPoint,
MultiPolygon: processMultiPolygon,
Point: processPoint2,
Polygon: processPolygon2,
Topology: processTopology
};
var geometryTypes2 = {
GeometryCollection: processGeometryCollection,
LineString: processLineString,
MultiLineString: processMultiLineString,
MultiPoint: processMultiPoint,
MultiPolygon: processMultiPolygon,
Point: processPoint2,
Polygon: processPolygon2,
Topology: processTopology
};
function processFeature(dataSource, feature2, notUsed, crsFunction, options) {
if (feature2.geometry === null) {
createObject(feature2, dataSource._entityCollection, options.describe);
return;
}
if (!defined_default(feature2.geometry)) {
throw new RuntimeError_default("feature.geometry is required.");
}
const geometryType = feature2.geometry.type;
const geometryHandler = geometryTypes2[geometryType];
if (!defined_default(geometryHandler)) {
throw new RuntimeError_default(`Unknown geometry type: ${geometryType}`);
}
geometryHandler(dataSource, feature2, feature2.geometry, crsFunction, options);
}
function processFeatureCollection(dataSource, featureCollection, notUsed, crsFunction, options) {
const features = featureCollection.features;
for (let i = 0, len = features.length; i < len; i++) {
processFeature(dataSource, features[i], void 0, crsFunction, options);
}
}
function processGeometryCollection(dataSource, geoJson, geometryCollection, crsFunction, options) {
const geometries = geometryCollection.geometries;
for (let i = 0, len = geometries.length; i < len; i++) {
const geometry = geometries[i];
const geometryType = geometry.type;
const geometryHandler = geometryTypes2[geometryType];
if (!defined_default(geometryHandler)) {
throw new RuntimeError_default(`Unknown geometry type: ${geometryType}`);
}
geometryHandler(dataSource, geoJson, geometry, crsFunction, options);
}
}
function createPoint(dataSource, geoJson, crsFunction, coordinates, options) {
let symbol = options.markerSymbol;
let color = options.markerColor;
let size = options.markerSize;
const properties = geoJson.properties;
if (defined_default(properties)) {
const cssColor = properties["marker-color"];
if (defined_default(cssColor)) {
color = Color_default.fromCssColorString(cssColor);
}
size = sizes[properties["marker-size"]] ?? size;
const markerSymbol = properties["marker-symbol"];
if (defined_default(markerSymbol)) {
symbol = markerSymbol;
}
}
let canvasOrPromise;
if (defined_default(symbol)) {
if (symbol.length === 1) {
canvasOrPromise = dataSource._pinBuilder.fromText(
symbol.toUpperCase(),
color,
size
);
} else {
canvasOrPromise = dataSource._pinBuilder.fromMakiIconId(
symbol,
color,
size
);
}
} else {
canvasOrPromise = dataSource._pinBuilder.fromColor(color, size);
}
const billboard = new BillboardGraphics_default();
billboard.verticalOrigin = new ConstantProperty_default(VerticalOrigin_default.BOTTOM);
if (coordinates.length === 2 && options.clampToGround) {
billboard.heightReference = HeightReference_default.CLAMP_TO_GROUND;
}
const entity = createObject(
geoJson,
dataSource._entityCollection,
options.describe
);
entity.billboard = billboard;
entity.position = new ConstantPositionProperty_default(crsFunction(coordinates));
const promise = Promise.resolve(canvasOrPromise).then(function(image) {
billboard.image = new ConstantProperty_default(image);
}).catch(function() {
billboard.image = new ConstantProperty_default(
dataSource._pinBuilder.fromColor(color, size)
);
});
dataSource._promises.push(promise);
}
function processPoint2(dataSource, geoJson, geometry, crsFunction, options) {
createPoint(dataSource, geoJson, crsFunction, geometry.coordinates, options);
}
function processMultiPoint(dataSource, geoJson, geometry, crsFunction, options) {
const coordinates = geometry.coordinates;
for (let i = 0; i < coordinates.length; i++) {
createPoint(dataSource, geoJson, crsFunction, coordinates[i], options);
}
}
function createLineString(dataSource, geoJson, crsFunction, coordinates, options) {
let material = options.strokeMaterialProperty;
let widthProperty = options.strokeWidthProperty;
const properties = geoJson.properties;
if (defined_default(properties)) {
const width = properties["stroke-width"];
if (defined_default(width)) {
widthProperty = new ConstantProperty_default(width);
}
let color;
const stroke = properties.stroke;
if (defined_default(stroke)) {
color = Color_default.fromCssColorString(stroke);
}
const opacity = properties["stroke-opacity"];
if (defined_default(opacity) && opacity !== 1) {
if (!defined_default(color)) {
color = material.color.getValue().clone();
}
color.alpha = opacity;
}
if (defined_default(color)) {
material = new ColorMaterialProperty_default(color);
}
}
const entity = createObject(
geoJson,
dataSource._entityCollection,
options.describe
);
const polylineGraphics = new PolylineGraphics_default();
entity.polyline = polylineGraphics;
polylineGraphics.clampToGround = options.clampToGround;
polylineGraphics.material = material;
polylineGraphics.width = widthProperty;
polylineGraphics.positions = new ConstantProperty_default(
coordinatesArrayToCartesianArray(coordinates, crsFunction)
);
polylineGraphics.arcType = ArcType_default.RHUMB;
}
function processLineString(dataSource, geoJson, geometry, crsFunction, options) {
createLineString(
dataSource,
geoJson,
crsFunction,
geometry.coordinates,
options
);
}
function processMultiLineString(dataSource, geoJson, geometry, crsFunction, options) {
const lineStrings = geometry.coordinates;
for (let i = 0; i < lineStrings.length; i++) {
createLineString(dataSource, geoJson, crsFunction, lineStrings[i], options);
}
}
function createPolygon(dataSource, geoJson, crsFunction, coordinates, options) {
if (coordinates.length === 0 || coordinates[0].length === 0) {
return;
}
let outlineColorProperty = options.strokeMaterialProperty.color;
let material = options.fillMaterialProperty;
let widthProperty = options.strokeWidthProperty;
const properties = geoJson.properties;
if (defined_default(properties)) {
const width = properties["stroke-width"];
if (defined_default(width)) {
widthProperty = new ConstantProperty_default(width);
}
let color;
const stroke = properties.stroke;
if (defined_default(stroke)) {
color = Color_default.fromCssColorString(stroke);
}
let opacity = properties["stroke-opacity"];
if (defined_default(opacity) && opacity !== 1) {
if (!defined_default(color)) {
color = outlineColorProperty.getValue().clone();
}
color.alpha = opacity;
}
if (defined_default(color)) {
outlineColorProperty = new ConstantProperty_default(color);
}
let fillColor;
const fill = properties.fill;
const materialColor = material.color.getValue();
if (defined_default(fill)) {
fillColor = Color_default.fromCssColorString(fill);
fillColor.alpha = materialColor.alpha;
}
opacity = properties["fill-opacity"];
if (defined_default(opacity) && opacity !== materialColor.alpha) {
if (!defined_default(fillColor)) {
fillColor = materialColor.clone();
}
fillColor.alpha = opacity;
}
if (defined_default(fillColor)) {
material = new ColorMaterialProperty_default(fillColor);
}
}
const polygon2 = new PolygonGraphics_default();
polygon2.outline = new ConstantProperty_default(true);
polygon2.outlineColor = outlineColorProperty;
polygon2.outlineWidth = widthProperty;
polygon2.material = material;
polygon2.arcType = ArcType_default.RHUMB;
const holes = [];
for (let i = 1, len = coordinates.length; i < len; i++) {
holes.push(
new PolygonHierarchy_default(
coordinatesArrayToCartesianArray(coordinates[i], crsFunction)
)
);
}
const positions = coordinates[0];
polygon2.hierarchy = new ConstantProperty_default(
new PolygonHierarchy_default(
coordinatesArrayToCartesianArray(positions, crsFunction),
holes
)
);
if (positions[0].length > 2) {
polygon2.perPositionHeight = new ConstantProperty_default(true);
} else if (!options.clampToGround) {
polygon2.height = 0;
}
const entity = createObject(
geoJson,
dataSource._entityCollection,
options.describe
);
entity.polygon = polygon2;
}
function processPolygon2(dataSource, geoJson, geometry, crsFunction, options) {
createPolygon(
dataSource,
geoJson,
crsFunction,
geometry.coordinates,
options
);
}
function processMultiPolygon(dataSource, geoJson, geometry, crsFunction, options) {
const polygons = geometry.coordinates;
for (let i = 0; i < polygons.length; i++) {
createPolygon(dataSource, geoJson, crsFunction, polygons[i], options);
}
}
function processTopology(dataSource, geoJson, geometry, crsFunction, options) {
for (const property in geometry.objects) {
if (geometry.objects.hasOwnProperty(property)) {
const feature2 = feature_default(geometry, geometry.objects[property]);
const typeHandler = geoJsonObjectTypes2[feature2.type];
typeHandler(dataSource, feature2, feature2, crsFunction, options);
}
}
}
function GeoJsonDataSource(name) {
this._name = name;
this._changed = new Event_default();
this._error = new Event_default();
this._isLoading = false;
this._loading = new Event_default();
this._entityCollection = new EntityCollection_default(this);
this._promises = [];
this._pinBuilder = new PinBuilder_default();
this._entityCluster = new EntityCluster_default();
this._credit = void 0;
this._resourceCredits = [];
}
GeoJsonDataSource.load = function(data, options) {
return new GeoJsonDataSource().load(data, options);
};
Object.defineProperties(GeoJsonDataSource, {
/**
* Gets or sets the default size of the map pin created for each point, in pixels.
* @memberof GeoJsonDataSource
* @type {number}
* @default 48
*/
markerSize: {
get: function() {
return defaultMarkerSize;
},
set: function(value) {
defaultMarkerSize = value;
}
},
/**
* Gets or sets the default symbol of the map pin created for each point.
* This can be any valid {@link http://mapbox.com/maki/|Maki} identifier, any single character,
* or blank if no symbol is to be used.
* @memberof GeoJsonDataSource
* @type {string}
*/
markerSymbol: {
get: function() {
return defaultMarkerSymbol;
},
set: function(value) {
defaultMarkerSymbol = value;
}
},
/**
* Gets or sets the default color of the map pin created for each point.
* @memberof GeoJsonDataSource
* @type {Color}
* @default Color.ROYALBLUE
*/
markerColor: {
get: function() {
return defaultMarkerColor;
},
set: function(value) {
defaultMarkerColor = value;
}
},
/**
* Gets or sets the default color of polylines and polygon outlines.
* @memberof GeoJsonDataSource
* @type {Color}
* @default Color.BLACK
*/
stroke: {
get: function() {
return defaultStroke;
},
set: function(value) {
defaultStroke = value;
}
},
/**
* Gets or sets the default width of polylines and polygon outlines.
* @memberof GeoJsonDataSource
* @type {number}
* @default 2.0
*/
strokeWidth: {
get: function() {
return defaultStrokeWidth;
},
set: function(value) {
defaultStrokeWidth = value;
}
},
/**
* Gets or sets default color for polygon interiors.
* @memberof GeoJsonDataSource
* @type {Color}
* @default Color.YELLOW
*/
fill: {
get: function() {
return defaultFill2;
},
set: function(value) {
defaultFill2 = value;
}
},
/**
* Gets or sets default of whether to clamp to the ground.
* @memberof GeoJsonDataSource
* @type {boolean}
* @default false
*/
clampToGround: {
get: function() {
return defaultClampToGround;
},
set: function(value) {
defaultClampToGround = value;
}
},
/**
* Gets an object that maps the name of a crs to a callback function which takes a GeoJSON coordinate
* and transforms it into a WGS84 Earth-fixed Cartesian. Older versions of GeoJSON which
* supported the EPSG type can be added to this list as well, by specifying the complete EPSG name,
* for example 'EPSG:4326'.
* @memberof GeoJsonDataSource
* @type {object}
*/
crsNames: {
get: function() {
return crsNames;
}
},
/**
* Gets an object that maps the href property of a crs link to a callback function
* which takes the crs properties object and returns a Promise that resolves
* to a function that takes a GeoJSON coordinate and transforms it into a WGS84 Earth-fixed Cartesian.
* Items in this object take precedence over those defined in crsLinkHrefs, assuming
* the link has a type specified.
* @memberof GeoJsonDataSource
* @type {object}
*/
crsLinkHrefs: {
get: function() {
return crsLinkHrefs;
}
},
/**
* Gets an object that maps the type property of a crs link to a callback function
* which takes the crs properties object and returns a Promise that resolves
* to a function that takes a GeoJSON coordinate and transforms it into a WGS84 Earth-fixed Cartesian.
* Items in crsLinkHrefs take precedence over this object.
* @memberof GeoJsonDataSource
* @type {object}
*/
crsLinkTypes: {
get: function() {
return crsLinkTypes;
}
}
});
Object.defineProperties(GeoJsonDataSource.prototype, {
/**
* Gets or sets a human-readable name for this instance.
* @memberof GeoJsonDataSource.prototype
* @type {string}
*/
name: {
get: function() {
return this._name;
},
set: function(value) {
if (this._name !== value) {
this._name = value;
this._changed.raiseEvent(this);
}
}
},
/**
* This DataSource only defines static data, therefore this property is always undefined.
* @memberof GeoJsonDataSource.prototype
* @type {DataSourceClock}
*/
clock: {
value: void 0,
writable: false
},
/**
* Gets the collection of {@link Entity} instances.
* @memberof GeoJsonDataSource.prototype
* @type {EntityCollection}
*/
entities: {
get: function() {
return this._entityCollection;
}
},
/**
* Gets a value indicating if the data source is currently loading data.
* @memberof GeoJsonDataSource.prototype
* @type {boolean}
*/
isLoading: {
get: function() {
return this._isLoading;
}
},
/**
* Gets an event that will be raised when the underlying data changes.
* @memberof GeoJsonDataSource.prototype
* @type {Event}
*/
changedEvent: {
get: function() {
return this._changed;
}
},
/**
* Gets an event that will be raised if an error is encountered during processing.
* @memberof GeoJsonDataSource.prototype
* @type {Event}
*/
errorEvent: {
get: function() {
return this._error;
}
},
/**
* Gets an event that will be raised when the data source either starts or stops loading.
* @memberof GeoJsonDataSource.prototype
* @type {Event}
*/
loadingEvent: {
get: function() {
return this._loading;
}
},
/**
* Gets whether or not this data source should be displayed.
* @memberof GeoJsonDataSource.prototype
* @type {boolean}
*/
show: {
get: function() {
return this._entityCollection.show;
},
set: function(value) {
this._entityCollection.show = value;
}
},
/**
* Gets or sets the clustering options for this data source. This object can be shared between multiple data sources.
*
* @memberof GeoJsonDataSource.prototype
* @type {EntityCluster}
*/
clustering: {
get: function() {
return this._entityCluster;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value must be defined.");
}
this._entityCluster = value;
}
},
/**
* Gets the credit that will be displayed for the data source
* @memberof GeoJsonDataSource.prototype
* @type {Credit}
*/
credit: {
get: function() {
return this._credit;
}
}
});
GeoJsonDataSource.prototype.load = function(data, options) {
return preload(this, data, options, true);
};
GeoJsonDataSource.prototype.process = function(data, options) {
return preload(this, data, options, false);
};
function preload(that, data, options, clear2) {
if (!defined_default(data)) {
throw new DeveloperError_default("data is required.");
}
DataSource_default.setLoading(that, true);
options = options ?? Frozen_default.EMPTY_OBJECT;
let credit = options.credit;
if (typeof credit === "string") {
credit = new Credit_default(credit);
}
that._credit = credit;
let promise = data;
let sourceUri = options.sourceUri;
if (typeof data === "string" || data instanceof Resource_default) {
data = Resource_default.createIfNeeded(data);
promise = data.fetchJson();
sourceUri = sourceUri ?? data.getUrlComponent();
const resourceCredits = that._resourceCredits;
const credits = data.credits;
if (defined_default(credits)) {
const length2 = credits.length;
for (let i = 0; i < length2; i++) {
resourceCredits.push(credits[i]);
}
}
}
options = {
describe: options.describe ?? defaultDescribeProperty,
markerSize: options.markerSize ?? defaultMarkerSize,
markerSymbol: options.markerSymbol ?? defaultMarkerSymbol,
markerColor: options.markerColor ?? defaultMarkerColor,
strokeWidthProperty: new ConstantProperty_default(
options.strokeWidth ?? defaultStrokeWidth
),
strokeMaterialProperty: new ColorMaterialProperty_default(
options.stroke ?? defaultStroke
),
fillMaterialProperty: new ColorMaterialProperty_default(
options.fill ?? defaultFill2
),
clampToGround: options.clampToGround ?? defaultClampToGround
};
return Promise.resolve(promise).then(function(geoJson) {
return load2(that, geoJson, options, sourceUri, clear2);
}).catch(function(error) {
DataSource_default.setLoading(that, false);
that._error.raiseEvent(that, error);
throw error;
});
}
GeoJsonDataSource.prototype.update = function(time) {
return true;
};
function load2(that, geoJson, options, sourceUri, clear2) {
let name;
if (defined_default(sourceUri)) {
name = getFilenameFromUri_default(sourceUri);
}
if (defined_default(name) && that._name !== name) {
that._name = name;
that._changed.raiseEvent(that);
}
const typeHandler = geoJsonObjectTypes2[geoJson.type];
if (!defined_default(typeHandler)) {
throw new RuntimeError_default(`Unsupported GeoJSON object type: ${geoJson.type}`);
}
const crs = geoJson.crs;
let crsFunction = crs !== null ? defaultCrsFunction : null;
if (defined_default(crs)) {
if (!defined_default(crs.properties)) {
throw new RuntimeError_default("crs.properties is undefined.");
}
const properties = crs.properties;
if (crs.type === "name") {
crsFunction = crsNames[properties.name];
if (!defined_default(crsFunction)) {
throw new RuntimeError_default(`Unknown crs name: ${properties.name}`);
}
} else if (crs.type === "link") {
let handler = crsLinkHrefs[properties.href];
if (!defined_default(handler)) {
handler = crsLinkTypes[properties.type];
}
if (!defined_default(handler)) {
throw new RuntimeError_default(
`Unable to resolve crs link: ${JSON.stringify(properties)}`
);
}
crsFunction = handler(properties);
} else if (crs.type === "EPSG") {
crsFunction = crsNames[`EPSG:${properties.code}`];
if (!defined_default(crsFunction)) {
throw new RuntimeError_default(`Unknown crs EPSG code: ${properties.code}`);
}
} else {
throw new RuntimeError_default(`Unknown crs type: ${crs.type}`);
}
}
return Promise.resolve(crsFunction).then(function(crsFunction2) {
if (clear2) {
that._entityCollection.removeAll();
}
if (crsFunction2 !== null) {
typeHandler(that, geoJson, geoJson, crsFunction2, options);
}
return Promise.all(that._promises).then(function() {
that._promises.length = 0;
DataSource_default.setLoading(that, false);
return that;
});
});
}
var GeoJsonDataSource_default = GeoJsonDataSource;
// packages/engine/Source/DataSources/GpxDataSource.js
var import_InlineWorkers964 = __toESM(require_InlineWorkers(), 1);
// node_modules/autolinker/dist/es2015/index.js
var import_InlineWorkers963 = __toESM(require_InlineWorkers());
// node_modules/autolinker/dist/es2015/autolinker.js
var import_InlineWorkers959 = __toESM(require_InlineWorkers());
// node_modules/tslib/tslib.es6.mjs
var import_InlineWorkers936 = __toESM(require_InlineWorkers(), 1);
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
d2.__proto__ = b2;
} || function(d2, b2) {
for (var p in b2) if (Object.prototype.hasOwnProperty.call(b2, p)) d2[p] = b2[p];
};
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() {
this.constructor = d;
}
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign2(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
} catch (error) {
e = { error };
} finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
} finally {
if (e) throw e.error;
}
}
return ar;
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
// node_modules/autolinker/dist/es2015/version.js
var import_InlineWorkers937 = __toESM(require_InlineWorkers());
var version = "4.1.5";
// node_modules/autolinker/dist/es2015/utils.js
var import_InlineWorkers938 = __toESM(require_InlineWorkers());
var hasOwnProperty = Object.prototype.hasOwnProperty;
function isBoolean(value) {
return typeof value === "boolean";
}
function ellipsis(str, truncateLen, ellipsisChars) {
var ellipsisLength;
if (str.length > truncateLen) {
if (ellipsisChars == null) {
ellipsisChars = "…";
ellipsisLength = 3;
} else {
ellipsisLength = ellipsisChars.length;
}
str = str.substring(0, truncateLen - ellipsisLength) + ellipsisChars;
}
return str;
}
function removeWithPredicate(arr, fn) {
for (var i = arr.length - 1; i >= 0; i--) {
if (fn(arr[i]) === true) {
arr.splice(i, 1);
}
}
}
function assertNever(theValue) {
throw new Error("Unhandled case for value: '".concat(theValue, "'"));
}
// node_modules/autolinker/dist/es2015/anchor-tag-builder.js
var import_InlineWorkers943 = __toESM(require_InlineWorkers());
// node_modules/autolinker/dist/es2015/html-tag.js
var import_InlineWorkers939 = __toESM(require_InlineWorkers());
var whitespaceRe = /\s+/;
var HtmlTag = (
/** @class */
(function() {
function HtmlTag2(cfg) {
if (cfg === void 0) {
cfg = {};
}
this.tagName = "";
this.attrs = {};
this.innerHTML = "";
this.tagName = cfg.tagName || "";
this.attrs = cfg.attrs || {};
this.innerHTML = cfg.innerHtml || cfg.innerHTML || "";
}
HtmlTag2.prototype.setTagName = function(tagName) {
this.tagName = tagName;
return this;
};
HtmlTag2.prototype.getTagName = function() {
return this.tagName;
};
HtmlTag2.prototype.setAttr = function(attrName, attrValue) {
var tagAttrs = this.getAttrs();
tagAttrs[attrName] = attrValue;
return this;
};
HtmlTag2.prototype.getAttr = function(attrName) {
return this.getAttrs()[attrName];
};
HtmlTag2.prototype.setAttrs = function(attrs) {
Object.assign(this.getAttrs(), attrs);
return this;
};
HtmlTag2.prototype.getAttrs = function() {
return this.attrs;
};
HtmlTag2.prototype.setClass = function(cssClass) {
return this.setAttr("class", cssClass);
};
HtmlTag2.prototype.addClass = function(cssClass) {
var classAttr = this.getClass();
var classes = !classAttr ? [] : classAttr.split(whitespaceRe);
var newClasses = cssClass.split(whitespaceRe);
var newClass;
while (newClass = newClasses.shift()) {
if (classes.indexOf(newClass) === -1) {
classes.push(newClass);
}
}
this.getAttrs()["class"] = classes.join(" ");
return this;
};
HtmlTag2.prototype.removeClass = function(cssClass) {
var classAttr = this.getClass();
var classes = !classAttr ? [] : classAttr.split(whitespaceRe);
var removeClasses = cssClass.split(whitespaceRe);
var removeClass;
while (classes.length && (removeClass = removeClasses.shift())) {
var idx = classes.indexOf(removeClass);
if (idx !== -1) {
classes.splice(idx, 1);
}
}
this.getAttrs()["class"] = classes.join(" ");
return this;
};
HtmlTag2.prototype.getClass = function() {
return this.getAttrs()["class"] || "";
};
HtmlTag2.prototype.hasClass = function(cssClass) {
return (" " + this.getClass() + " ").indexOf(" " + cssClass + " ") !== -1;
};
HtmlTag2.prototype.setInnerHTML = function(html2) {
this.innerHTML = html2;
return this;
};
HtmlTag2.prototype.setInnerHtml = function(html2) {
return this.setInnerHTML(html2);
};
HtmlTag2.prototype.getInnerHTML = function() {
return this.innerHTML || "";
};
HtmlTag2.prototype.getInnerHtml = function() {
return this.getInnerHTML();
};
HtmlTag2.prototype.toAnchorString = function() {
var tagName = this.getTagName();
var attrsStr = this.buildAttrsStr();
attrsStr = attrsStr ? " " + attrsStr : "";
return ["<", tagName, attrsStr, ">", this.getInnerHtml(), "", tagName, ">"].join("");
};
HtmlTag2.prototype.buildAttrsStr = function() {
var attrs = this.getAttrs(), attrsArr = [];
for (var prop in attrs) {
if (hasOwnProperty.call(attrs, prop)) {
attrsArr.push(prop + '="' + attrs[prop] + '"');
}
}
return attrsArr.join(" ");
};
return HtmlTag2;
})()
);
// node_modules/autolinker/dist/es2015/truncate/truncate-smart.js
var import_InlineWorkers940 = __toESM(require_InlineWorkers());
function truncateSmart(url2, truncateLen, ellipsisChars) {
var ellipsisLengthBeforeParsing;
var ellipsisLength;
if (ellipsisChars == null) {
ellipsisChars = "…";
ellipsisLength = 3;
ellipsisLengthBeforeParsing = 8;
} else {
ellipsisLength = ellipsisChars.length;
ellipsisLengthBeforeParsing = ellipsisChars.length;
}
if (url2.length <= truncateLen) {
return url2;
}
var availableLength = truncateLen - ellipsisLength;
var urlObj = parseUrl(url2);
if (urlObj.query) {
var matchQuery = urlObj.query.match(/^(.*?)(?=(\?|#))(.*?)$/i);
if (matchQuery) {
urlObj.query = urlObj.query.substr(0, matchQuery[1].length);
url2 = buildUrl(urlObj);
}
}
if (url2.length <= truncateLen) {
return url2;
}
if (urlObj.host) {
urlObj.host = urlObj.host.replace(/^www\./, "");
url2 = buildUrl(urlObj);
}
if (url2.length <= truncateLen) {
return url2;
}
var truncatedUrl = "";
if (urlObj.host) {
truncatedUrl += urlObj.host;
}
if (truncatedUrl.length >= availableLength) {
if (urlObj.host.length === truncateLen) {
return (urlObj.host.substr(0, truncateLen - ellipsisLength) + ellipsisChars).substr(0, availableLength + ellipsisLengthBeforeParsing);
}
return buildSegment(truncatedUrl, availableLength, ellipsisChars).substr(0, availableLength + ellipsisLengthBeforeParsing);
}
var pathAndQuery = "";
if (urlObj.path) {
pathAndQuery += "/" + urlObj.path;
}
if (urlObj.query) {
pathAndQuery += "?" + urlObj.query;
}
if (pathAndQuery) {
if ((truncatedUrl + pathAndQuery).length >= availableLength) {
if ((truncatedUrl + pathAndQuery).length == truncateLen) {
return (truncatedUrl + pathAndQuery).substr(0, truncateLen);
}
var remainingAvailableLength = availableLength - truncatedUrl.length;
return (truncatedUrl + buildSegment(pathAndQuery, remainingAvailableLength, ellipsisChars)).substr(0, availableLength + ellipsisLengthBeforeParsing);
} else {
truncatedUrl += pathAndQuery;
}
}
if (urlObj.fragment) {
var fragment = "#" + urlObj.fragment;
if ((truncatedUrl + fragment).length >= availableLength) {
if ((truncatedUrl + fragment).length == truncateLen) {
return (truncatedUrl + fragment).substr(0, truncateLen);
}
var remainingAvailableLength2 = availableLength - truncatedUrl.length;
return (truncatedUrl + buildSegment(fragment, remainingAvailableLength2, ellipsisChars)).substr(0, availableLength + ellipsisLengthBeforeParsing);
} else {
truncatedUrl += fragment;
}
}
if (urlObj.scheme && urlObj.host) {
var scheme = urlObj.scheme + "://";
if ((truncatedUrl + scheme).length < availableLength) {
return (scheme + truncatedUrl).substr(0, truncateLen);
}
}
if (truncatedUrl.length <= truncateLen) {
return truncatedUrl;
}
var end = "";
if (availableLength > 0) {
end = truncatedUrl.substr(-1 * Math.floor(availableLength / 2));
}
return (truncatedUrl.substr(0, Math.ceil(availableLength / 2)) + ellipsisChars + end).substr(0, availableLength + ellipsisLengthBeforeParsing);
}
function parseUrl(url2) {
var urlObj = {};
var urlSub = url2;
var match = urlSub.match(/^([a-z]+):\/\//i);
if (match) {
urlObj.scheme = match[1];
urlSub = urlSub.slice(match[0].length);
}
match = urlSub.match(/^(.*?)(?=(\?|#|\/|$))/i);
if (match) {
urlObj.host = match[1];
urlSub = urlSub.slice(match[0].length);
}
match = urlSub.match(/^\/(.*?)(?=(\?|#|$))/i);
if (match) {
urlObj.path = match[1];
urlSub = urlSub.slice(match[0].length);
}
match = urlSub.match(/^\?(.*?)(?=(#|$))/i);
if (match) {
urlObj.query = match[1];
urlSub = urlSub.slice(match[0].length);
}
match = urlSub.match(/^#(.*?)$/i);
if (match) {
urlObj.fragment = match[1];
}
return urlObj;
}
function buildUrl(urlObj) {
var url2 = "";
if (urlObj.scheme && urlObj.host) {
url2 += urlObj.scheme + "://";
}
if (urlObj.host) {
url2 += urlObj.host;
}
if (urlObj.path) {
url2 += "/" + urlObj.path;
}
if (urlObj.query) {
url2 += "?" + urlObj.query;
}
if (urlObj.fragment) {
url2 += "#" + urlObj.fragment;
}
return url2;
}
function buildSegment(segment, remainingAvailableLength, ellipsisChars) {
var remainingAvailableLengthHalf = remainingAvailableLength / 2;
var startOffset = Math.ceil(remainingAvailableLengthHalf);
var endOffset = -1 * Math.floor(remainingAvailableLengthHalf);
var end = "";
if (endOffset < 0) {
end = segment.substr(endOffset);
}
return segment.substr(0, startOffset) + ellipsisChars + end;
}
// node_modules/autolinker/dist/es2015/truncate/truncate-middle.js
var import_InlineWorkers941 = __toESM(require_InlineWorkers());
function truncateMiddle(url2, truncateLen, ellipsisChars) {
if (url2.length <= truncateLen) {
return url2;
}
var ellipsisLengthBeforeParsing;
var ellipsisLength;
if (ellipsisChars == null) {
ellipsisChars = "…";
ellipsisLengthBeforeParsing = 8;
ellipsisLength = 3;
} else {
ellipsisLengthBeforeParsing = ellipsisChars.length;
ellipsisLength = ellipsisChars.length;
}
var availableLength = truncateLen - ellipsisLength;
var end = "";
if (availableLength > 0) {
end = url2.substr(-1 * Math.floor(availableLength / 2));
}
return (url2.substr(0, Math.ceil(availableLength / 2)) + ellipsisChars + end).substr(0, availableLength + ellipsisLengthBeforeParsing);
}
// node_modules/autolinker/dist/es2015/truncate/truncate-end.js
var import_InlineWorkers942 = __toESM(require_InlineWorkers());
function truncateEnd(anchorText, truncateLen, ellipsisChars) {
return ellipsis(anchorText, truncateLen, ellipsisChars);
}
// node_modules/autolinker/dist/es2015/anchor-tag-builder.js
var AnchorTagBuilder = (
/** @class */
(function() {
function AnchorTagBuilder2(cfg) {
if (cfg === void 0) {
cfg = {};
}
this.newWindow = false;
this.truncate = {};
this.className = "";
this.newWindow = cfg.newWindow || false;
this.truncate = cfg.truncate || {};
this.className = cfg.className || "";
}
AnchorTagBuilder2.prototype.build = function(match) {
return new HtmlTag({
tagName: "a",
attrs: this.createAttrs(match),
innerHtml: this.processAnchorText(match.getAnchorText())
});
};
AnchorTagBuilder2.prototype.createAttrs = function(match) {
var attrs = {
href: match.getAnchorHref()
// we'll always have the `href` attribute
};
var cssClass = this.createCssClass(match);
if (cssClass) {
attrs["class"] = cssClass;
}
if (this.newWindow) {
attrs["target"] = "_blank";
attrs["rel"] = "noopener noreferrer";
}
if (this.truncate.length && this.truncate.length < match.getAnchorText().length) {
attrs["title"] = match.getAnchorHref();
}
return attrs;
};
AnchorTagBuilder2.prototype.createCssClass = function(match) {
var className = this.className;
if (!className) {
return "";
} else {
var returnClasses = [className], cssClassSuffixes = match.getCssClassSuffixes();
for (var i = 0, len = cssClassSuffixes.length; i < len; i++) {
returnClasses.push(className + "-" + cssClassSuffixes[i]);
}
return returnClasses.join(" ");
}
};
AnchorTagBuilder2.prototype.processAnchorText = function(anchorText) {
anchorText = this.doTruncate(anchorText);
return anchorText;
};
AnchorTagBuilder2.prototype.doTruncate = function(anchorText) {
var truncate = this.truncate;
if (!truncate.length)
return anchorText;
var truncateLength = truncate.length, truncateLocation = truncate.location;
if (truncateLocation === "smart") {
return truncateSmart(anchorText, truncateLength);
} else if (truncateLocation === "middle") {
return truncateMiddle(anchorText, truncateLength);
} else {
return truncateEnd(anchorText, truncateLength);
}
};
return AnchorTagBuilder2;
})()
);
// node_modules/autolinker/dist/es2015/parser/parse-matches.js
var import_InlineWorkers957 = __toESM(require_InlineWorkers());
// node_modules/autolinker/dist/es2015/match/url-match.js
var import_InlineWorkers948 = __toESM(require_InlineWorkers());
// node_modules/autolinker/dist/es2015/match/abstract-match.js
var import_InlineWorkers944 = __toESM(require_InlineWorkers());
var AbstractMatch = (
/** @class */
(function() {
function AbstractMatch2(cfg) {
this._ = null;
this.matchedText = "";
this.offset = 0;
this.tagBuilder = cfg.tagBuilder;
this.matchedText = cfg.matchedText;
this.offset = cfg.offset;
}
AbstractMatch2.prototype.getMatchedText = function() {
return this.matchedText;
};
AbstractMatch2.prototype.setOffset = function(offset) {
this.offset = offset;
};
AbstractMatch2.prototype.getOffset = function() {
return this.offset;
};
AbstractMatch2.prototype.getCssClassSuffixes = function() {
return [this.type];
};
AbstractMatch2.prototype.buildTag = function() {
return this.tagBuilder.build(this);
};
return AbstractMatch2;
})()
);
// node_modules/autolinker/dist/es2015/parser/uri-utils.js
var import_InlineWorkers947 = __toESM(require_InlineWorkers());
// node_modules/autolinker/dist/es2015/char-utils.js
var import_InlineWorkers945 = __toESM(require_InlineWorkers());
function isControlChar(c) {
return c >= 0 && c <= 31 || c == 127;
}
function isAsciiLetterChar(c) {
return c >= 65 && c <= 90 || c >= 97 && c <= 122;
}
function isDigitChar(c) {
return c >= 48 && c <= 57;
}
function isQuoteChar(c) {
return c == 34 || c == 39;
}
function isWhitespaceChar(c) {
return c < 8232 ? c < 160 ? c >= 9 && c <= 13 || c == 32 : c < 5760 ? c == 160 : c == 5760 || c >= 8192 && c <= 8202 : c < 8287 ? c >= 8232 && c <= 8233 || c == 8239 : c < 12288 ? c == 8287 : c == 12288 || c == 65279;
}
function isAlphaNumericOrMarkChar(c) {
return c < 4800 ? c < 2949 ? c < 2451 ? c < 1425 ? c < 768 ? c < 192 ? c < 169 ? c < 65 ? c >= 48 && c <= 57 : c >= 65 && c <= 90 || c >= 97 && c <= 122 : c < 181 ? c >= 169 && c <= 170 || c == 174 : c == 181 || c == 186 : c < 710 ? c < 216 ? c >= 192 && c <= 214 : c >= 216 && c <= 246 || c >= 248 && c <= 705 : c < 748 ? c >= 710 && c <= 721 || c >= 736 && c <= 740 : c == 748 || c == 750 : c < 910 ? c < 895 ? c < 886 ? c >= 768 && c <= 884 : c >= 886 && c <= 887 || c >= 890 && c <= 893 : c < 904 ? c == 895 || c == 902 : c >= 904 && c <= 906 || c == 908 : c < 1155 ? c < 931 ? c >= 910 && c <= 929 : c >= 931 && c <= 1013 || c >= 1015 && c <= 1153 : c < 1369 ? c >= 1155 && c <= 1327 || c >= 1329 && c <= 1366 : c == 1369 || c >= 1377 && c <= 1415 : c < 1808 ? c < 1552 ? c < 1476 ? c < 1471 ? c >= 1425 && c <= 1469 : c == 1471 || c >= 1473 && c <= 1474 : c < 1488 ? c >= 1476 && c <= 1477 || c == 1479 : c >= 1488 && c <= 1514 || c >= 1520 && c <= 1522 : c < 1749 ? c < 1568 ? c >= 1552 && c <= 1562 : c >= 1568 && c <= 1641 || c >= 1646 && c <= 1747 : c < 1770 ? c >= 1749 && c <= 1756 || c >= 1759 && c <= 1768 : c >= 1770 && c <= 1788 || c == 1791 : c < 2230 ? c < 2042 ? c < 1869 ? c >= 1808 && c <= 1866 : c >= 1869 && c <= 1969 || c >= 1984 && c <= 2037 : c < 2112 ? c == 2042 || c >= 2048 && c <= 2093 : c >= 2112 && c <= 2139 || c >= 2208 && c <= 2228 : c < 2406 ? c < 2260 ? c >= 2230 && c <= 2237 : c >= 2260 && c <= 2273 || c >= 2275 && c <= 2403 : c < 2437 ? c >= 2406 && c <= 2415 || c >= 2417 && c <= 2435 : c >= 2437 && c <= 2444 || c >= 2447 && c <= 2448 : c < 2693 ? c < 2579 ? c < 2519 ? c < 2486 ? c < 2474 ? c >= 2451 && c <= 2472 : c >= 2474 && c <= 2480 || c == 2482 : c < 2503 ? c >= 2486 && c <= 2489 || c >= 2492 && c <= 2500 : c >= 2503 && c <= 2504 || c >= 2507 && c <= 2510 : c < 2534 ? c < 2524 ? c == 2519 : c >= 2524 && c <= 2525 || c >= 2527 && c <= 2531 : c < 2565 ? c >= 2534 && c <= 2545 || c >= 2561 && c <= 2563 : c >= 2565 && c <= 2570 || c >= 2575 && c <= 2576 : c < 2631 ? c < 2613 ? c < 2602 ? c >= 2579 && c <= 2600 : c >= 2602 && c <= 2608 || c >= 2610 && c <= 2611 : c < 2620 ? c >= 2613 && c <= 2614 || c >= 2616 && c <= 2617 : c == 2620 || c >= 2622 && c <= 2626 : c < 2649 ? c < 2635 ? c >= 2631 && c <= 2632 : c >= 2635 && c <= 2637 || c == 2641 : c < 2662 ? c >= 2649 && c <= 2652 || c == 2654 : c >= 2662 && c <= 2677 || c >= 2689 && c <= 2691 : c < 2821 ? c < 2759 ? c < 2730 ? c < 2703 ? c >= 2693 && c <= 2701 : c >= 2703 && c <= 2705 || c >= 2707 && c <= 2728 : c < 2741 ? c >= 2730 && c <= 2736 || c >= 2738 && c <= 2739 : c >= 2741 && c <= 2745 || c >= 2748 && c <= 2757 : c < 2784 ? c < 2763 ? c >= 2759 && c <= 2761 : c >= 2763 && c <= 2765 || c == 2768 : c < 2809 ? c >= 2784 && c <= 2787 || c >= 2790 && c <= 2799 : c == 2809 || c >= 2817 && c <= 2819 : c < 2887 ? c < 2858 ? c < 2831 ? c >= 2821 && c <= 2828 : c >= 2831 && c <= 2832 || c >= 2835 && c <= 2856 : c < 2869 ? c >= 2858 && c <= 2864 || c >= 2866 && c <= 2867 : c >= 2869 && c <= 2873 || c >= 2876 && c <= 2884 : c < 2911 ? c < 2902 ? c >= 2887 && c <= 2888 || c >= 2891 && c <= 2893 : c >= 2902 && c <= 2903 || c >= 2908 && c <= 2909 : c < 2929 ? c >= 2911 && c <= 2915 || c >= 2918 && c <= 2927 : c == 2929 || c >= 2946 && c <= 2947 : c < 3517 ? c < 3205 ? c < 3046 ? c < 2984 ? c < 2969 ? c < 2958 ? c >= 2949 && c <= 2954 : c >= 2958 && c <= 2960 || c >= 2962 && c <= 2965 : c < 2974 ? c >= 2969 && c <= 2970 || c == 2972 : c >= 2974 && c <= 2975 || c >= 2979 && c <= 2980 : c < 3014 ? c < 2990 ? c >= 2984 && c <= 2986 : c >= 2990 && c <= 3001 || c >= 3006 && c <= 3010 : c < 3024 ? c >= 3014 && c <= 3016 || c >= 3018 && c <= 3021 : c == 3024 || c == 3031 : c < 3142 ? c < 3086 ? c < 3072 ? c >= 3046 && c <= 3055 : c >= 3072 && c <= 3075 || c >= 3077 && c <= 3084 : c < 3114 ? c >= 3086 && c <= 3088 || c >= 3090 && c <= 3112 : c >= 3114 && c <= 3129 || c >= 3133 && c <= 3140 : c < 3160 ? c < 3146 ? c >= 3142 && c <= 3144 : c >= 3146 && c <= 3149 || c >= 3157 && c <= 3158 : c < 3174 ? c >= 3160 && c <= 3162 || c >= 3168 && c <= 3171 : c >= 3174 && c <= 3183 || c >= 3200 && c <= 3203 : c < 3333 ? c < 3274 ? c < 3242 ? c < 3214 ? c >= 3205 && c <= 3212 : c >= 3214 && c <= 3216 || c >= 3218 && c <= 3240 : c < 3260 ? c >= 3242 && c <= 3251 || c >= 3253 && c <= 3257 : c >= 3260 && c <= 3268 || c >= 3270 && c <= 3272 : c < 3296 ? c < 3285 ? c >= 3274 && c <= 3277 : c >= 3285 && c <= 3286 || c == 3294 : c < 3313 ? c >= 3296 && c <= 3299 || c >= 3302 && c <= 3311 : c >= 3313 && c <= 3314 || c >= 3329 && c <= 3331 : c < 3423 ? c < 3389 ? c < 3342 ? c >= 3333 && c <= 3340 : c >= 3342 && c <= 3344 || c >= 3346 && c <= 3386 : c < 3402 ? c >= 3389 && c <= 3396 || c >= 3398 && c <= 3400 : c >= 3402 && c <= 3406 || c >= 3412 && c <= 3415 : c < 3458 ? c < 3430 ? c >= 3423 && c <= 3427 : c >= 3430 && c <= 3439 || c >= 3450 && c <= 3455 : c < 3482 ? c >= 3458 && c <= 3459 || c >= 3461 && c <= 3478 : c >= 3482 && c <= 3505 || c >= 3507 && c <= 3515 : c < 3804 ? c < 3722 ? c < 3570 ? c < 3535 ? c < 3520 ? c == 3517 : c >= 3520 && c <= 3526 || c == 3530 : c < 3544 ? c >= 3535 && c <= 3540 || c == 3542 : c >= 3544 && c <= 3551 || c >= 3558 && c <= 3567 : c < 3664 ? c < 3585 ? c >= 3570 && c <= 3571 : c >= 3585 && c <= 3642 || c >= 3648 && c <= 3662 : c < 3716 ? c >= 3664 && c <= 3673 || c >= 3713 && c <= 3714 : c == 3716 || c >= 3719 && c <= 3720 : c < 3754 ? c < 3737 ? c < 3725 ? c == 3722 : c == 3725 || c >= 3732 && c <= 3735 : c < 3749 ? c >= 3737 && c <= 3743 || c >= 3745 && c <= 3747 : c == 3749 || c == 3751 : c < 3776 ? c < 3757 ? c >= 3754 && c <= 3755 : c >= 3757 && c <= 3769 || c >= 3771 && c <= 3773 : c < 3784 ? c >= 3776 && c <= 3780 || c == 3782 : c >= 3784 && c <= 3789 || c >= 3792 && c <= 3801 : c < 4176 ? c < 3902 ? c < 3872 ? c < 3840 ? c >= 3804 && c <= 3807 : c == 3840 || c >= 3864 && c <= 3865 : c < 3895 ? c >= 3872 && c <= 3881 || c == 3893 : c == 3895 || c == 3897 : c < 3974 ? c < 3913 ? c >= 3902 && c <= 3911 : c >= 3913 && c <= 3948 || c >= 3953 && c <= 3972 : c < 4038 ? c >= 3974 && c <= 3991 || c >= 3993 && c <= 4028 : c == 4038 || c >= 4096 && c <= 4169 : c < 4688 ? c < 4301 ? c < 4256 ? c >= 4176 && c <= 4253 : c >= 4256 && c <= 4293 || c == 4295 : c < 4348 ? c == 4301 || c >= 4304 && c <= 4346 : c >= 4348 && c <= 4680 || c >= 4682 && c <= 4685 : c < 4746 ? c < 4698 ? c >= 4688 && c <= 4694 || c == 4696 : c >= 4698 && c <= 4701 || c >= 4704 && c <= 4744 : c < 4786 ? c >= 4746 && c <= 4749 || c >= 4752 && c <= 4784 : c >= 4786 && c <= 4789 || c >= 4792 && c <= 4798 : c < 11035 ? c < 7416 ? c < 6176 ? c < 5873 ? c < 4992 ? c < 4824 ? c < 4802 ? c == 4800 : c >= 4802 && c <= 4805 || c >= 4808 && c <= 4822 : c < 4888 ? c >= 4824 && c <= 4880 || c >= 4882 && c <= 4885 : c >= 4888 && c <= 4954 || c >= 4957 && c <= 4959 : c < 5121 ? c < 5024 ? c >= 4992 && c <= 5007 : c >= 5024 && c <= 5109 || c >= 5112 && c <= 5117 : c < 5761 ? c >= 5121 && c <= 5740 || c >= 5743 && c <= 5759 : c >= 5761 && c <= 5786 || c >= 5792 && c <= 5866 : c < 6002 ? c < 5920 ? c < 5888 ? c >= 5873 && c <= 5880 : c >= 5888 && c <= 5900 || c >= 5902 && c <= 5908 : c < 5984 ? c >= 5920 && c <= 5940 || c >= 5952 && c <= 5971 : c >= 5984 && c <= 5996 || c >= 5998 && c <= 6e3 : c < 6108 ? c < 6016 ? c >= 6002 && c <= 6003 : c >= 6016 && c <= 6099 || c == 6103 : c < 6155 ? c >= 6108 && c <= 6109 || c >= 6112 && c <= 6121 : c >= 6155 && c <= 6157 || c >= 6160 && c <= 6169 : c < 6783 ? c < 6512 ? c < 6400 ? c < 6272 ? c >= 6176 && c <= 6263 : c >= 6272 && c <= 6314 || c >= 6320 && c <= 6389 : c < 6448 ? c >= 6400 && c <= 6430 || c >= 6432 && c <= 6443 : c >= 6448 && c <= 6459 || c >= 6470 && c <= 6509 : c < 6608 ? c < 6528 ? c >= 6512 && c <= 6516 : c >= 6528 && c <= 6571 || c >= 6576 && c <= 6601 : c < 6688 ? c >= 6608 && c <= 6617 || c >= 6656 && c <= 6683 : c >= 6688 && c <= 6750 || c >= 6752 && c <= 6780 : c < 7040 ? c < 6832 ? c < 6800 ? c >= 6783 && c <= 6793 : c >= 6800 && c <= 6809 || c == 6823 : c < 6992 ? c >= 6832 && c <= 6846 || c >= 6912 && c <= 6987 : c >= 6992 && c <= 7001 || c >= 7019 && c <= 7027 : c < 7245 ? c < 7168 ? c >= 7040 && c <= 7155 : c >= 7168 && c <= 7223 || c >= 7232 && c <= 7241 : c < 7376 ? c >= 7245 && c <= 7293 || c >= 7296 && c <= 7304 : c >= 7376 && c <= 7378 || c >= 7380 && c <= 7414 : c < 8450 ? c < 8130 ? c < 8025 ? c < 7960 ? c < 7424 ? c >= 7416 && c <= 7417 : c >= 7424 && c <= 7669 || c >= 7675 && c <= 7957 : c < 8008 ? c >= 7960 && c <= 7965 || c >= 7968 && c <= 8005 : c >= 8008 && c <= 8013 || c >= 8016 && c <= 8023 : c < 8031 ? c < 8027 ? c == 8025 : c == 8027 || c == 8029 : c < 8118 ? c >= 8031 && c <= 8061 || c >= 8064 && c <= 8116 : c >= 8118 && c <= 8124 || c == 8126 : c < 8205 ? c < 8150 ? c < 8134 ? c >= 8130 && c <= 8132 : c >= 8134 && c <= 8140 || c >= 8144 && c <= 8147 : c < 8178 ? c >= 8150 && c <= 8155 || c >= 8160 && c <= 8172 : c >= 8178 && c <= 8180 || c >= 8182 && c <= 8188 : c < 8305 ? c < 8252 ? c == 8205 : c == 8252 || c == 8265 : c < 8336 ? c == 8305 || c == 8319 : c >= 8336 && c <= 8348 || c >= 8400 && c <= 8432 : c < 8579 ? c < 8486 ? c < 8469 ? c < 8455 ? c == 8450 : c == 8455 || c >= 8458 && c <= 8467 : c < 8482 ? c == 8469 || c >= 8473 && c <= 8477 : c == 8482 || c == 8484 : c < 8495 ? c < 8488 ? c == 8486 : c == 8488 || c >= 8490 && c <= 8493 : c < 8517 ? c >= 8495 && c <= 8505 || c >= 8508 && c <= 8511 : c >= 8517 && c <= 8521 || c == 8526 : c < 9410 ? c < 9e3 ? c < 8592 ? c >= 8579 && c <= 8580 : c >= 8592 && c <= 8703 || c >= 8986 && c <= 8987 : c < 9193 ? c == 9e3 || c == 9167 : c >= 9193 && c <= 9203 || c >= 9208 && c <= 9210 : c < 9723 ? c < 9654 ? c == 9410 || c >= 9642 && c <= 9643 : c == 9654 || c == 9664 : c < 10548 ? c >= 9723 && c <= 9726 || c >= 9728 && c <= 10175 : c >= 10548 && c <= 10549 || c >= 11013 && c <= 11015 : c < 43259 ? c < 12445 ? c < 11688 ? c < 11520 ? c < 11264 ? c < 11088 ? c >= 11035 && c <= 11036 : c == 11088 || c == 11093 : c < 11360 ? c >= 11264 && c <= 11310 || c >= 11312 && c <= 11358 : c >= 11360 && c <= 11492 || c >= 11499 && c <= 11507 : c < 11568 ? c < 11559 ? c >= 11520 && c <= 11557 : c == 11559 || c == 11565 : c < 11647 ? c >= 11568 && c <= 11623 || c == 11631 : c >= 11647 && c <= 11670 || c >= 11680 && c <= 11686 : c < 11744 ? c < 11712 ? c < 11696 ? c >= 11688 && c <= 11694 : c >= 11696 && c <= 11702 || c >= 11704 && c <= 11710 : c < 11728 ? c >= 11712 && c <= 11718 || c >= 11720 && c <= 11726 : c >= 11728 && c <= 11734 || c >= 11736 && c <= 11742 : c < 12330 ? c < 11823 ? c >= 11744 && c <= 11775 : c == 11823 || c >= 12293 && c <= 12294 : c < 12353 ? c >= 12330 && c <= 12341 || c >= 12347 && c <= 12349 : c >= 12353 && c <= 12438 || c >= 12441 && c <= 12442 : c < 42512 ? c < 12951 ? c < 12549 ? c < 12449 ? c >= 12445 && c <= 12447 : c >= 12449 && c <= 12538 || c >= 12540 && c <= 12543 : c < 12704 ? c >= 12549 && c <= 12589 || c >= 12593 && c <= 12686 : c >= 12704 && c <= 12730 || c >= 12784 && c <= 12799 : c < 19968 ? c < 12953 ? c == 12951 : c == 12953 || c >= 13312 && c <= 19893 : c < 42192 ? c >= 19968 && c <= 40917 || c >= 40960 && c <= 42124 : c >= 42192 && c <= 42237 || c >= 42240 && c <= 42508 : c < 42891 ? c < 42623 ? c < 42560 ? c >= 42512 && c <= 42539 : c >= 42560 && c <= 42610 || c >= 42612 && c <= 42621 : c < 42775 ? c >= 42623 && c <= 42725 || c >= 42736 && c <= 42737 : c >= 42775 && c <= 42783 || c >= 42786 && c <= 42888 : c < 43072 ? c < 42928 ? c >= 42891 && c <= 42926 : c >= 42928 && c <= 42935 || c >= 42999 && c <= 43047 : c < 43216 ? c >= 43072 && c <= 43123 || c >= 43136 && c <= 43205 : c >= 43216 && c <= 43225 || c >= 43232 && c <= 43255 : c < 55243 ? c < 43744 ? c < 43488 ? c < 43312 ? c < 43261 ? c == 43259 : c == 43261 || c >= 43264 && c <= 43309 : c < 43392 ? c >= 43312 && c <= 43347 || c >= 43360 && c <= 43388 : c >= 43392 && c <= 43456 || c >= 43471 && c <= 43481 : c < 43600 ? c < 43520 ? c >= 43488 && c <= 43518 : c >= 43520 && c <= 43574 || c >= 43584 && c <= 43597 : c < 43642 ? c >= 43600 && c <= 43609 || c >= 43616 && c <= 43638 : c >= 43642 && c <= 43714 || c >= 43739 && c <= 43741 : c < 43824 ? c < 43785 ? c < 43762 ? c >= 43744 && c <= 43759 : c >= 43762 && c <= 43766 || c >= 43777 && c <= 43782 : c < 43808 ? c >= 43785 && c <= 43790 || c >= 43793 && c <= 43798 : c >= 43808 && c <= 43814 || c >= 43816 && c <= 43822 : c < 44012 ? c < 43868 ? c >= 43824 && c <= 43866 : c >= 43868 && c <= 43877 || c >= 43888 && c <= 44010 : c < 44032 ? c >= 44012 && c <= 44013 || c >= 44016 && c <= 44025 : c >= 44032 && c <= 55203 || c >= 55216 && c <= 55238 : c < 64848 ? c < 64298 ? c < 64112 ? c < 55296 ? c >= 55243 && c <= 55291 : c >= 55296 && c <= 57343 || c >= 63744 && c <= 64109 : c < 64275 ? c >= 64112 && c <= 64217 || c >= 64256 && c <= 64262 : c >= 64275 && c <= 64279 || c >= 64285 && c <= 64296 : c < 64320 ? c < 64312 ? c >= 64298 && c <= 64310 : c >= 64312 && c <= 64316 || c == 64318 : c < 64326 ? c >= 64320 && c <= 64321 || c >= 64323 && c <= 64324 : c >= 64326 && c <= 64433 || c >= 64467 && c <= 64829 : c < 65296 ? c < 65024 ? c < 64914 ? c >= 64848 && c <= 64911 : c >= 64914 && c <= 64967 || c >= 65008 && c <= 65019 : c < 65136 ? c >= 65024 && c <= 65039 || c >= 65056 && c <= 65071 : c >= 65136 && c <= 65140 || c >= 65142 && c <= 65276 : c < 65474 ? c < 65345 ? c >= 65296 && c <= 65305 || c >= 65313 && c <= 65338 : c >= 65345 && c <= 65370 || c >= 65382 && c <= 65470 : c < 65490 ? c >= 65474 && c <= 65479 || c >= 65482 && c <= 65487 : c >= 65490 && c <= 65495 || c >= 65498 && c <= 65500;
}
function isValidEmailLocalPartSpecialChar(c) {
return c < 47 ? c < 42 ? c == 33 || c >= 35 && c <= 39 : c >= 42 && c <= 43 || c == 45 : c < 63 ? c == 47 || c == 61 : c < 94 ? c == 63 : c >= 94 && c <= 96 || c >= 123 && c <= 126;
}
function isUrlSuffixAllowedSpecialChar(c) {
return c < 91 ? c < 47 ? c >= 35 && c <= 43 || c == 45 : c < 61 ? c == 47 : c == 61 || c == 64 : c < 95 ? c == 91 || c == 93 : c < 123 ? c == 95 : c >= 123 && c <= 126 || c == 10003;
}
function isUrlSuffixNotAllowedAsFinalChar(c) {
return c < 58 ? c < 44 ? c == 33 : c == 44 || c == 46 : c < 63 ? c >= 58 && c <= 59 : c == 63 || c == 94;
}
function isOpenBraceChar(c) {
return c < 91 ? c == 40 : c == 91 || c == 123;
}
function isCloseBraceChar(c) {
return c < 93 ? c == 41 : c == 93 || c == 125;
}
// node_modules/autolinker/dist/es2015/parser/known-tlds.js
var import_InlineWorkers946 = __toESM(require_InlineWorkers());
var tldRegex = /^(?:xn--vermgensberatung-pwb|xn--vermgensberater-ctb|xn--clchc0ea0b2g2a9gcd|xn--w4r85el8fhu5dnra|travelersinsurance|vermögensberatung|xn--5su34j936bgsg|xn--bck1b9a5dre4c|xn--mgbah1a3hjkrd|xn--mgbai9azgqp6j|xn--mgberp4a5d4ar|xn--xkc2dl3a5ee0h|vermögensberater|xn--fzys8d69uvgm|xn--mgba7c0bbn0a|xn--mgbcpq6gpa1a|xn--xkc2al3hye2a|americanexpress|kerryproperties|sandvikcoromant|xn--i1b6b1a6a2e|xn--kcrx77d1x4a|xn--lgbbat1ad8j|xn--mgba3a4f16a|xn--mgbc0a9azcg|xn--nqv7fs00ema|americanfamily|weatherchannel|xn--54b7fta0cc|xn--6qq986b3xl|xn--80aqecdr1a|xn--b4w605ferd|xn--fiq228c5hs|xn--h2breg3eve|xn--jlq480n2rg|xn--mgba3a3ejt|xn--mgbaam7a8h|xn--mgbayh7gpa|xn--mgbbh1a71e|xn--mgbca7dzdo|xn--mgbi4ecexp|xn--mgbx4cd0ab|xn--rvc1e0am3e|international|lifeinsurance|wolterskluwer|xn--cckwcxetd|xn--eckvdtc9d|xn--fpcrj9c3d|xn--fzc2c9e2c|xn--h2brj9c8c|xn--tiq49xqyj|xn--yfro4i67o|xn--ygbi2ammx|construction|lplfinancial|scholarships|versicherung|xn--3e0b707e|xn--45br5cyl|xn--4dbrk0ce|xn--80adxhks|xn--80asehdb|xn--8y0a063a|xn--gckr3f0f|xn--mgb9awbf|xn--mgbab2bd|xn--mgbgu82a|xn--mgbpl2fh|xn--mgbt3dhd|xn--mk1bu44c|xn--ngbc5azd|xn--ngbe9e0a|xn--ogbpf8fl|xn--qcka1pmc|accountants|barclaycard|blackfriday|blockbuster|bridgestone|calvinklein|contractors|creditunion|engineering|enterprises|investments|kerryhotels|lamborghini|motorcycles|olayangroup|photography|playstation|productions|progressive|redumbrella|williamhill|xn--11b4c3d|xn--1ck2e1b|xn--1qqw23a|xn--2scrj9c|xn--3bst00m|xn--3ds443g|xn--3hcrj9c|xn--42c2d9a|xn--45brj9c|xn--55qw42g|xn--6frz82g|xn--80ao21a|xn--9krt00a|xn--cck2b3b|xn--czr694b|xn--d1acj3b|xn--efvy88h|xn--fct429k|xn--fjq720a|xn--flw351e|xn--g2xx48c|xn--gecrj9c|xn--gk3at1e|xn--h2brj9c|xn--hxt814e|xn--imr513n|xn--j6w193g|xn--jvr189m|xn--kprw13d|xn--kpry57d|xn--mgbbh1a|xn--mgbtx2b|xn--mix891f|xn--nyqy26a|xn--otu796d|xn--pgbs0dh|xn--q9jyb4c|xn--rhqv96g|xn--rovu88b|xn--s9brj9c|xn--ses554g|xn--t60b56a|xn--vuq861b|xn--w4rs40l|xn--xhq521b|xn--zfr164b|சிங்கப்பூர்|accountant|apartments|associates|basketball|bnpparibas|boehringer|capitalone|consulting|creditcard|cuisinella|eurovision|extraspace|foundation|healthcare|immobilien|industries|management|mitsubishi|nextdirect|properties|protection|prudential|realestate|republican|restaurant|schaeffler|tatamotors|technology|university|vlaanderen|xn--30rr7y|xn--3pxu8k|xn--45q11c|xn--4gbrim|xn--55qx5d|xn--5tzm5g|xn--80aswg|xn--90a3ac|xn--9dbq2a|xn--9et52u|xn--c2br7g|xn--cg4bki|xn--czrs0t|xn--czru2d|xn--fiq64b|xn--fiqs8s|xn--fiqz9s|xn--io0a7i|xn--kput3i|xn--mxtq1m|xn--o3cw4h|xn--pssy2u|xn--q7ce6a|xn--unup4y|xn--wgbh1c|xn--wgbl6a|xn--y9a3aq|accenture|allfinanz|amsterdam|analytics|aquarelle|barcelona|bloomberg|christmas|community|directory|education|equipment|fairwinds|financial|firestone|fresenius|furniture|goldpoint|hisamitsu|homedepot|homegoods|homesense|institute|insurance|kuokgroup|landrover|lifestyle|marketing|marshalls|melbourne|microsoft|panasonic|pramerica|richardli|shangrila|solutions|statebank|statefarm|stockholm|travelers|vacations|xn--90ais|xn--c1avg|xn--d1alf|xn--e1a4c|xn--fhbei|xn--j1aef|xn--j1amh|xn--l1acc|xn--ngbrx|xn--nqv7f|xn--p1acf|xn--qxa6a|xn--tckwe|xn--vhquv|yodobashi|موريتانيا|abudhabi|airforce|allstate|attorney|barclays|barefoot|bargains|baseball|boutique|bradesco|broadway|brussels|builders|business|capetown|catering|catholic|cipriani|cleaning|clinique|clothing|commbank|computer|delivery|deloitte|democrat|diamonds|discount|discover|download|engineer|ericsson|exchange|feedback|fidelity|firmdale|football|frontier|goodyear|grainger|graphics|hdfcbank|helsinki|holdings|hospital|infiniti|ipiranga|istanbul|jpmorgan|lighting|lundbeck|marriott|mckinsey|memorial|merckmsd|mortgage|observer|partners|pharmacy|pictures|plumbing|property|redstone|reliance|saarland|samsclub|security|services|shopping|softbank|software|stcgroup|supplies|training|vanguard|ventures|verisign|woodside|xn--90ae|xn--node|xn--p1ai|xn--qxam|yokohama|السعودية|abogado|academy|agakhan|alibaba|android|athleta|auction|audible|auspost|banamex|bauhaus|bestbuy|booking|brother|capital|caravan|careers|channel|charity|chintai|citadel|clubmed|college|cologne|company|compare|contact|cooking|corsica|country|coupons|courses|cricket|cruises|dentist|digital|domains|exposed|express|farmers|fashion|ferrari|ferrero|finance|fishing|fitness|flights|florist|flowers|forsale|frogans|fujitsu|gallery|genting|godaddy|grocery|guitars|hamburg|hangout|hitachi|holiday|hosting|hotmail|hyundai|ismaili|jewelry|juniper|kitchen|komatsu|lacaixa|lanxess|lasalle|latrobe|leclerc|limited|lincoln|markets|monster|netbank|netflix|network|neustar|okinawa|organic|origins|philips|pioneer|politie|realtor|recipes|rentals|reviews|rexroth|samsung|sandvik|schmidt|schwarz|science|shiksha|singles|staples|storage|support|surgery|systems|temasek|theater|theatre|tickets|toshiba|trading|walmart|wanggou|watches|weather|website|wedding|whoswho|windows|winners|yamaxun|youtube|zuerich|католик|البحرين|الجزائر|العليان|پاکستان|كاثوليك|இந்தியா|abbott|abbvie|africa|agency|airbus|airtel|alipay|alsace|alstom|amazon|anquan|aramco|author|bayern|beauty|berlin|bharti|bostik|boston|broker|camera|career|casino|center|chanel|chrome|church|circle|claims|clinic|coffee|comsec|condos|coupon|credit|cruise|dating|datsun|dealer|degree|dental|design|direct|doctor|dunlop|dupont|durban|emerck|energy|estate|events|expert|family|flickr|futbol|gallup|garden|george|giving|global|google|gratis|health|hermes|hiphop|hockey|hotels|hughes|imamat|insure|intuit|jaguar|joburg|juegos|kaufen|kindle|kosher|latino|lawyer|lefrak|living|locker|london|luxury|madrid|maison|makeup|market|mattel|mobile|monash|mormon|moscow|museum|nagoya|nissan|nissay|norton|nowruz|office|olayan|online|oracle|orange|otsuka|pfizer|photos|physio|pictet|quebec|racing|realty|reisen|repair|report|review|rogers|ryukyu|safety|sakura|sanofi|school|schule|search|secure|select|shouji|soccer|social|stream|studio|supply|suzuki|swatch|sydney|taipei|taobao|target|tattoo|tennis|tienda|tjmaxx|tkmaxx|toyota|travel|unicom|viajes|viking|villas|virgin|vision|voting|voyage|walter|webcam|xihuan|yachts|yandex|zappos|москва|онлайн|ابوظبي|ارامكو|الاردن|المغرب|امارات|فلسطين|مليسيا|भारतम्|இலங்கை|ファッション|actor|adult|aetna|amfam|amica|apple|archi|audio|autos|azure|baidu|beats|bible|bingo|black|boats|bosch|build|canon|cards|chase|cheap|cisco|citic|click|cloud|coach|codes|crown|cymru|dance|deals|delta|drive|dubai|earth|edeka|email|epson|faith|fedex|final|forex|forum|gallo|games|gifts|gives|glass|globo|gmail|green|gripe|group|gucci|guide|homes|honda|horse|house|hyatt|ikano|irish|jetzt|koeln|kyoto|lamer|lease|legal|lexus|lilly|loans|locus|lotte|lotto|mango|media|miami|money|movie|music|nexus|nikon|ninja|nokia|nowtv|omega|osaka|paris|parts|party|phone|photo|pizza|place|poker|praxi|press|prime|promo|quest|radio|rehab|reise|ricoh|rocks|rodeo|rugby|salon|sener|seven|sharp|shell|shoes|skype|sling|smart|smile|solar|space|sport|stada|store|study|style|sucks|swiss|tatar|tires|tirol|tmall|today|tokyo|tools|toray|total|tours|trade|trust|tunes|tushu|ubank|vegas|video|vodka|volvo|wales|watch|weber|weibo|works|world|xerox|yahoo|ישראל|ایران|بازار|بھارت|سودان|سورية|همراه|भारोत|संगठन|বাংলা|భారత్|ഭാരതം|嘉里大酒店|aarp|able|aero|akdn|ally|amex|arab|army|arpa|arte|asda|asia|audi|auto|baby|band|bank|bbva|beer|best|bike|bing|blog|blue|bofa|bond|book|buzz|cafe|call|camp|care|cars|casa|case|cash|cbre|cern|chat|citi|city|club|cool|coop|cyou|data|date|dclk|deal|dell|desi|diet|dish|docs|dvag|erni|fage|fail|fans|farm|fast|fido|film|fire|fish|flir|food|ford|free|fund|game|gbiz|gent|ggee|gift|gmbh|gold|golf|goog|guge|guru|hair|haus|hdfc|help|here|host|hsbc|icbc|ieee|imdb|immo|info|itau|java|jeep|jobs|jprs|kddi|kids|kiwi|kpmg|kred|land|lego|lgbt|lidl|life|like|limo|link|live|loan|love|ltda|luxe|maif|meet|meme|menu|mini|mint|mobi|moda|moto|name|navy|news|next|nico|nike|ollo|open|page|pars|pccw|pics|ping|pink|play|plus|pohl|porn|post|prod|prof|qpon|read|reit|rent|rest|rich|room|rsvp|ruhr|safe|sale|sarl|save|saxo|scot|seat|seek|sexy|shia|shop|show|silk|sina|site|skin|sncf|sohu|song|sony|spot|star|surf|talk|taxi|team|tech|teva|tiaa|tips|town|toys|tube|vana|visa|viva|vivo|vote|voto|wang|weir|wien|wiki|wine|work|xbox|yoga|zara|zero|zone|дети|сайт|بارت|بيتك|ڀارت|تونس|شبكة|عراق|عمان|موقع|भारत|ভারত|ভাৰত|ਭਾਰਤ|ભારત|ଭାରତ|ಭಾರತ|ලංකා|アマゾン|グーグル|クラウド|ポイント|组织机构|電訊盈科|香格里拉|aaa|abb|abc|aco|ads|aeg|afl|aig|anz|aol|app|art|aws|axa|bar|bbc|bbt|bcg|bcn|bet|bid|bio|biz|bms|bmw|bom|boo|bot|box|buy|bzh|cab|cal|cam|car|cat|cba|cbn|ceo|cfa|cfd|com|cpa|crs|dad|day|dds|dev|dhl|diy|dnp|dog|dot|dtv|dvr|eat|eco|edu|esq|eus|fan|fit|fly|foo|fox|frl|ftr|fun|fyi|gal|gap|gay|gdn|gea|gle|gmo|gmx|goo|gop|got|gov|hbo|hiv|hkt|hot|how|ibm|ice|icu|ifm|inc|ing|ink|int|ist|itv|jcb|jio|jll|jmp|jnj|jot|joy|kfh|kia|kim|kpn|krd|lat|law|lds|llc|llp|lol|lpl|ltd|man|map|mba|med|men|mil|mit|mlb|mls|mma|moe|moi|mom|mov|msd|mtn|mtr|nab|nba|nec|net|new|nfl|ngo|nhk|now|nra|nrw|ntt|nyc|obi|one|ong|onl|ooo|org|ott|ovh|pay|pet|phd|pid|pin|pnc|pro|pru|pub|pwc|red|ren|ril|rio|rip|run|rwe|sap|sas|sbi|sbs|scb|sew|sex|sfr|ski|sky|soy|spa|srl|stc|tab|tax|tci|tdk|tel|thd|tjx|top|trv|tui|tvs|ubs|uno|uol|ups|vet|vig|vin|vip|wed|win|wme|wow|wtc|wtf|xin|xxx|xyz|you|yun|zip|бел|ком|қаз|мкд|мон|орг|рус|срб|укр|հայ|קום|عرب|قطر|كوم|مصر|कॉम|नेट|คอม|ไทย|ລາວ|ストア|セール|みんな|中文网|亚马逊|天主教|我爱你|新加坡|淡马锡|飞利浦|ac|ad|ae|af|ag|ai|al|am|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw|ελ|ευ|бг|ею|рф|გე|닷넷|닷컴|삼성|한국|コム|世界|中信|中国|中國|企业|佛山|信息|健康|八卦|公司|公益|台湾|台灣|商城|商店|商标|嘉里|在线|大拿|娱乐|家電|广东|微博|慈善|手机|招聘|政务|政府|新闻|时尚|書籍|机构|游戏|澳門|点看|移动|网址|网店|网站|网络|联通|谷歌|购物|通販|集团|食品|餐厅|香港)$/;
// node_modules/autolinker/dist/es2015/parser/uri-utils.js
var httpSchemeRe = /https?:\/\//i;
var httpSchemePrefixRe = new RegExp("^" + httpSchemeRe.source, "i");
var invalidSchemeRe = /^(javascript|vbscript):/i;
var schemeUrlRe = /^[A-Za-z][-.+A-Za-z0-9]*:(\/\/)?([^:/]*)/;
var tldUrlHostRe = /^(?:\/\/)?([^/#?:]+)/;
var isSchemeStartChar = isAsciiLetterChar;
function isSchemeChar(charCode) {
return isAsciiLetterChar(charCode) || isDigitChar(charCode) || charCode === 43 || // '+'
charCode === 45 || // '-'
charCode === 46;
}
var isDomainLabelStartChar = isAlphaNumericOrMarkChar;
function isDomainLabelChar(charCode) {
return charCode === 95 || isDomainLabelStartChar(charCode);
}
function isPathChar(charCode) {
return isAlphaNumericOrMarkChar(charCode) || isUrlSuffixAllowedSpecialChar(charCode) || isUrlSuffixNotAllowedAsFinalChar(charCode);
}
function isUrlSuffixStartChar(charCode) {
return charCode === 47 || // '/'
charCode === 63 || // '?'
charCode === 35;
}
function isKnownTld(tld) {
return tldRegex.test(tld.toLowerCase());
}
function isValidSchemeUrl(url2) {
if (invalidSchemeRe.test(url2)) {
return false;
}
var schemeMatch = url2.match(schemeUrlRe);
if (!schemeMatch) {
return false;
}
var isAuthorityMatch = !!schemeMatch[1];
var host = schemeMatch[2];
if (isAuthorityMatch) {
return true;
}
if (host.indexOf(".") === -1 || !/[A-Za-z]/.test(host)) {
return false;
}
return true;
}
function isValidTldMatch(url2) {
var tldUrlHostMatch = url2.match(tldUrlHostRe);
if (!tldUrlHostMatch) {
return false;
}
var host = tldUrlHostMatch[0];
var hostLabels = host.split(".");
if (hostLabels.length < 2) {
return false;
}
var tld = hostLabels[hostLabels.length - 1];
if (!isKnownTld(tld)) {
return false;
}
return true;
}
var ipV4Re = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
var ipV4PartRe = /[:/?#]/;
function isValidIpV4Address(url2) {
var ipV4Part = url2.split(ipV4PartRe, 1)[0];
return ipV4Re.test(ipV4Part);
}
// node_modules/autolinker/dist/es2015/match/url-match.js
var wwwPrefixRegex = /^(https?:\/\/)?(?:www\.)?/i;
var protocolRelativeRegex = /^\/\//;
var UrlMatch = (
/** @class */
(function(_super) {
__extends(UrlMatch2, _super);
function UrlMatch2(cfg) {
var _this = _super.call(this, cfg) || this;
_this.type = "url";
_this.url = "";
_this.urlMatchType = "scheme";
_this.protocolRelativeMatch = false;
_this.stripPrefix = {
scheme: true,
www: true
};
_this.stripTrailingSlash = true;
_this.decodePercentEncoding = true;
_this.protocolPrepended = false;
_this.urlMatchType = cfg.urlMatchType;
_this.url = cfg.url;
_this.protocolRelativeMatch = cfg.protocolRelativeMatch;
_this.stripPrefix = cfg.stripPrefix;
_this.stripTrailingSlash = cfg.stripTrailingSlash;
_this.decodePercentEncoding = cfg.decodePercentEncoding;
return _this;
}
UrlMatch2.prototype.getType = function() {
return "url";
};
UrlMatch2.prototype.getUrlMatchType = function() {
return this.urlMatchType;
};
UrlMatch2.prototype.getUrl = function() {
var url2 = this.url;
if (!this.protocolRelativeMatch && this.urlMatchType !== "scheme" && !this.protocolPrepended) {
url2 = this.url = "http://" + url2;
this.protocolPrepended = true;
}
return url2;
};
UrlMatch2.prototype.getAnchorHref = function() {
var url2 = this.getUrl();
return url2.replace(/&/g, "&");
};
UrlMatch2.prototype.getAnchorText = function() {
var anchorText = this.getMatchedText();
if (this.protocolRelativeMatch) {
anchorText = stripProtocolRelativePrefix(anchorText);
}
if (this.stripPrefix.scheme) {
anchorText = stripSchemePrefix(anchorText);
}
if (this.stripPrefix.www) {
anchorText = stripWwwPrefix(anchorText);
}
if (this.stripTrailingSlash) {
anchorText = removeTrailingSlash(anchorText);
}
if (this.decodePercentEncoding) {
anchorText = removePercentEncoding(anchorText);
}
return anchorText;
};
return UrlMatch2;
})(AbstractMatch)
);
function stripSchemePrefix(url2) {
return url2.replace(httpSchemePrefixRe, "");
}
function stripWwwPrefix(url2) {
if (!url2.includes("www.")) {
return url2;
} else {
return url2.replace(wwwPrefixRegex, "$1");
}
}
function stripProtocolRelativePrefix(text2) {
return text2.replace(protocolRelativeRegex, "");
}
function removeTrailingSlash(anchorText) {
if (anchorText.charAt(anchorText.length - 1) === "/") {
anchorText = anchorText.slice(0, -1);
}
return anchorText;
}
function removePercentEncoding(anchorText) {
var preProcessedEntityAnchorText = anchorText.replace(/%(?:22|26|27|3C|3E)/gi, function(match) {
if (match === "%22")
return """;
if (match === "%26")
return "&";
if (match === "%27")
return "'";
if (match === "%3C" || match === "%3c")
return "<";
return ">";
});
if (preProcessedEntityAnchorText.includes("%")) {
try {
return decodeURIComponent(preProcessedEntityAnchorText);
} catch (error) {
}
}
return preProcessedEntityAnchorText;
}
// node_modules/autolinker/dist/es2015/parser/email-utils.js
var import_InlineWorkers949 = __toESM(require_InlineWorkers());
var mailtoSchemePrefixRe = /^mailto:/i;
var isEmailLocalPartStartChar = isAlphaNumericOrMarkChar;
function isEmailLocalPartChar(charCode) {
return isEmailLocalPartStartChar(charCode) || isValidEmailLocalPartSpecialChar(charCode);
}
function isValidEmail(emailAddress) {
var emailAddressTld = emailAddress.split(".").pop();
return isKnownTld(emailAddressTld);
}
// node_modules/autolinker/dist/es2015/match/email-match.js
var import_InlineWorkers950 = __toESM(require_InlineWorkers());
var EmailMatch = (
/** @class */
(function(_super) {
__extends(EmailMatch2, _super);
function EmailMatch2(cfg) {
var _this = _super.call(this, cfg) || this;
_this.type = "email";
_this.email = "";
_this.email = cfg.email;
return _this;
}
EmailMatch2.prototype.getType = function() {
return "email";
};
EmailMatch2.prototype.getEmail = function() {
return this.email;
};
EmailMatch2.prototype.getAnchorHref = function() {
return "mailto:" + this.email;
};
EmailMatch2.prototype.getAnchorText = function() {
return this.email;
};
return EmailMatch2;
})(AbstractMatch)
);
// node_modules/autolinker/dist/es2015/parser/hashtag-utils.js
var import_InlineWorkers951 = __toESM(require_InlineWorkers());
function isHashtagTextChar(charCode) {
return charCode === 95 || isAlphaNumericOrMarkChar(charCode);
}
function isValidHashtag(hashtag) {
return hashtag.length <= 140;
}
var hashtagServices = [
"twitter",
"facebook",
"instagram",
"tiktok",
"youtube"
];
// node_modules/autolinker/dist/es2015/match/hashtag-match.js
var import_InlineWorkers952 = __toESM(require_InlineWorkers());
var HashtagMatch = (
/** @class */
(function(_super) {
__extends(HashtagMatch2, _super);
function HashtagMatch2(cfg) {
var _this = _super.call(this, cfg) || this;
_this.type = "hashtag";
_this.serviceName = "twitter";
_this.hashtag = "";
_this.serviceName = cfg.serviceName;
_this.hashtag = cfg.hashtag;
return _this;
}
HashtagMatch2.prototype.getType = function() {
return "hashtag";
};
HashtagMatch2.prototype.getServiceName = function() {
return this.serviceName;
};
HashtagMatch2.prototype.getHashtag = function() {
return this.hashtag;
};
HashtagMatch2.prototype.getAnchorHref = function() {
var serviceName = this.serviceName, hashtag = this.hashtag;
switch (serviceName) {
case "twitter":
return "https://twitter.com/hashtag/" + hashtag;
case "facebook":
return "https://www.facebook.com/hashtag/" + hashtag;
case "instagram":
return "https://instagram.com/explore/tags/" + hashtag;
case "tiktok":
return "https://www.tiktok.com/tag/" + hashtag;
case "youtube":
return "https://youtube.com/hashtag/" + hashtag;
/* istanbul ignore next */
default:
assertNever(serviceName);
}
};
HashtagMatch2.prototype.getAnchorText = function() {
return "#" + this.hashtag;
};
HashtagMatch2.prototype.getCssClassSuffixes = function() {
var cssClassSuffixes = _super.prototype.getCssClassSuffixes.call(this), serviceName = this.getServiceName();
if (serviceName) {
cssClassSuffixes.push(serviceName);
}
return cssClassSuffixes;
};
return HashtagMatch2;
})(AbstractMatch)
);
// node_modules/autolinker/dist/es2015/parser/mention-utils.js
var import_InlineWorkers953 = __toESM(require_InlineWorkers());
var mentionRegexes = {
twitter: /^@\w{1,15}$/,
instagram: /^@[_\w]{1,30}$/,
soundcloud: /^@[-a-z0-9_]{3,25}$/,
// TikTok usernames are 1-24 characters containing letters, numbers, underscores
// and periods, but cannot end in a period: https://support.tiktok.com/en/getting-started/setting-up-your-profile/changing-your-username
tiktok: /^@[.\w]{1,23}[\w]$/,
// Youtube usernames are 3-30 characters containing letters, numbers, underscores,
// dashes, or latin middle dots ('·').
// https://support.google.com/youtube/answer/11585688?hl=en&co=GENIE.Platform%3DAndroid#tns
youtube: /^@[-.·\w]{3,30}$/
};
function isMentionTextChar(charCode) {
return charCode === 45 || // '-'
charCode === 46 || // '.'
charCode === 95 || // '_'
isAsciiLetterChar(charCode) || isDigitChar(charCode);
}
function isValidMention(mention, serviceName) {
var re = mentionRegexes[serviceName];
return re.test(mention);
}
var mentionServices = [
"twitter",
"instagram",
"soundcloud",
"tiktok",
"youtube"
];
// node_modules/autolinker/dist/es2015/match/mention-match.js
var import_InlineWorkers954 = __toESM(require_InlineWorkers());
var MentionMatch = (
/** @class */
(function(_super) {
__extends(MentionMatch2, _super);
function MentionMatch2(cfg) {
var _this = _super.call(this, cfg) || this;
_this.type = "mention";
_this.serviceName = "twitter";
_this.mention = "";
_this.mention = cfg.mention;
_this.serviceName = cfg.serviceName;
return _this;
}
MentionMatch2.prototype.getType = function() {
return "mention";
};
MentionMatch2.prototype.getMention = function() {
return this.mention;
};
MentionMatch2.prototype.getServiceName = function() {
return this.serviceName;
};
MentionMatch2.prototype.getAnchorHref = function() {
switch (this.serviceName) {
case "twitter":
return "https://twitter.com/" + this.mention;
case "instagram":
return "https://instagram.com/" + this.mention;
case "soundcloud":
return "https://soundcloud.com/" + this.mention;
case "tiktok":
return "https://www.tiktok.com/@" + this.mention;
case "youtube":
return "https://youtube.com/@" + this.mention;
/* istanbul ignore next */
default:
assertNever(this.serviceName);
}
};
MentionMatch2.prototype.getAnchorText = function() {
return "@" + this.mention;
};
MentionMatch2.prototype.getCssClassSuffixes = function() {
var cssClassSuffixes = _super.prototype.getCssClassSuffixes.call(this), serviceName = this.getServiceName();
if (serviceName) {
cssClassSuffixes.push(serviceName);
}
return cssClassSuffixes;
};
return MentionMatch2;
})(AbstractMatch)
);
// node_modules/autolinker/dist/es2015/parser/phone-number-utils.js
var import_InlineWorkers955 = __toESM(require_InlineWorkers());
var hasDelimCharsRe = /[-. ()]/;
var mostPhoneNumbers = /(?:(?:(?:(\+)?\d{1,3}[-. ]?)?\(?\d{3}\)?[-. ]?\d{3}[-. ]?\d{4})|(?:(\+)(?:9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)[-. ]?(?:\d[-. ]?){6,12}\d+))([,;]+[0-9]+#?)*/;
var japanesePhoneRe = /(0([1-9]-?[1-9]\d{3}|[1-9]{2}-?\d{3}|[1-9]{2}\d{1}-?\d{2}|[1-9]{2}\d{2}-?\d{1})-?\d{4}|0[789]0-?\d{4}-?\d{4}|050-?\d{4}-?\d{4})/;
var validPhoneNumberRe = new RegExp("^".concat(mostPhoneNumbers.source, "|").concat(japanesePhoneRe.source, "$"));
function isPhoneNumberSeparatorChar(charCode) {
return charCode === 45 || // '-'
charCode === 46 || // '.'
charCode === 32;
}
function isPhoneNumberControlChar(charCode) {
return charCode === 44 || // ','
charCode === 59;
}
function isValidPhoneNumber(phoneNumberText) {
var hasDelimiters = phoneNumberText.charAt(0) === "+" || hasDelimCharsRe.test(phoneNumberText);
return hasDelimiters && validPhoneNumberRe.test(phoneNumberText);
}
// node_modules/autolinker/dist/es2015/match/phone-match.js
var import_InlineWorkers956 = __toESM(require_InlineWorkers());
var PhoneMatch = (
/** @class */
(function(_super) {
__extends(PhoneMatch2, _super);
function PhoneMatch2(cfg) {
var _this = _super.call(this, cfg) || this;
_this.type = "phone";
_this.number = "";
_this.plusSign = false;
_this.number = cfg.number;
_this.plusSign = cfg.plusSign;
return _this;
}
PhoneMatch2.prototype.getType = function() {
return "phone";
};
PhoneMatch2.prototype.getPhoneNumber = function() {
return this.number;
};
PhoneMatch2.prototype.getNumber = function() {
return this.getPhoneNumber();
};
PhoneMatch2.prototype.getAnchorHref = function() {
return "tel:" + (this.plusSign ? "+" : "") + this.number;
};
PhoneMatch2.prototype.getAnchorText = function() {
return this.matchedText;
};
return PhoneMatch2;
})(AbstractMatch)
);
// node_modules/autolinker/dist/es2015/parser/parse-matches.js
var ParseMatchesContext = (
/** @class */
(function() {
function ParseMatchesContext2(text2, args) {
this.charIdx = 0;
this.matches = [];
this._stateMachines = [];
this.schemeUrlMachinesCount = 0;
this.text = text2;
this.tagBuilder = args.tagBuilder;
this.stripPrefix = args.stripPrefix;
this.stripTrailingSlash = args.stripTrailingSlash;
this.decodePercentEncoding = args.decodePercentEncoding;
this.hashtagServiceName = args.hashtagServiceName;
this.mentionServiceName = args.mentionServiceName;
}
Object.defineProperty(ParseMatchesContext2.prototype, "stateMachines", {
get: function() {
return this._stateMachines;
},
enumerable: false,
configurable: true
});
ParseMatchesContext2.prototype.addMachine = function(stateMachine) {
this._stateMachines.push(stateMachine);
if (isSchemeUrlStateMachine(stateMachine)) {
this.schemeUrlMachinesCount++;
}
};
ParseMatchesContext2.prototype.removeMachine = function(stateMachine) {
this._stateMachines = this._stateMachines.filter(function(m) {
return m !== stateMachine;
});
if (isSchemeUrlStateMachine(stateMachine)) {
this.schemeUrlMachinesCount--;
}
};
ParseMatchesContext2.prototype.hasSchemeUrlMachine = function() {
return this.schemeUrlMachinesCount > 0;
};
return ParseMatchesContext2;
})()
);
function parseMatches(text2, args) {
var context = new ParseMatchesContext(text2, args);
for (; context.charIdx < context.text.length; context.charIdx++) {
var char = text2.charAt(context.charIdx);
var charCode = text2.charCodeAt(context.charIdx);
if (context.stateMachines.length === 0) {
stateNoMatch(context, char, charCode);
} else {
for (var stateIdx = context.stateMachines.length - 1; stateIdx >= 0; stateIdx--) {
var stateMachine = context.stateMachines[stateIdx];
switch (stateMachine.state) {
// Protocol-relative URL states
case 11:
stateProtocolRelativeSlash1(context, stateMachine, charCode);
break;
case 12:
stateProtocolRelativeSlash2(context, stateMachine, charCode);
break;
case 0:
stateSchemeChar(context, stateMachine, charCode);
break;
case 1:
stateSchemeHyphen(context, stateMachine, charCode);
break;
case 2:
stateSchemeColon(context, stateMachine, charCode);
break;
case 3:
stateSchemeSlash1(context, stateMachine, charCode);
break;
case 4:
stateSchemeSlash2(context, stateMachine, char, charCode);
break;
case 5:
stateDomainLabelChar(context, stateMachine, charCode);
break;
case 6:
stateDomainHyphen(context, stateMachine, char, charCode);
break;
case 7:
stateDomainDot(context, stateMachine, char, charCode);
break;
case 13:
stateIpV4Digit(context, stateMachine, charCode);
break;
case 14:
stateIpV4Dot(context, stateMachine, charCode);
break;
case 8:
statePortColon(context, stateMachine, charCode);
break;
case 9:
statePortNumber(context, stateMachine, charCode);
break;
case 10:
statePath(context, stateMachine, charCode);
break;
// Email States
case 15:
stateEmailMailto_M(context, stateMachine, char, charCode);
break;
case 16:
stateEmailMailto_A(context, stateMachine, char, charCode);
break;
case 17:
stateEmailMailto_I(context, stateMachine, char, charCode);
break;
case 18:
stateEmailMailto_L(context, stateMachine, char, charCode);
break;
case 19:
stateEmailMailto_T(context, stateMachine, char, charCode);
break;
case 20:
stateEmailMailto_O(context, stateMachine, charCode);
break;
case 21:
stateEmailMailtoColon(context, stateMachine, charCode);
break;
case 22:
stateEmailLocalPart(context, stateMachine, charCode);
break;
case 23:
stateEmailLocalPartDot(context, stateMachine, charCode);
break;
case 24:
stateEmailAtSign(context, stateMachine, charCode);
break;
case 25:
stateEmailDomainChar(context, stateMachine, charCode);
break;
case 26:
stateEmailDomainHyphen(context, stateMachine, charCode);
break;
case 27:
stateEmailDomainDot(context, stateMachine, charCode);
break;
// Hashtag states
case 28:
stateHashtagHashChar(context, stateMachine, charCode);
break;
case 29:
stateHashtagTextChar(context, stateMachine, charCode);
break;
// Mention states
case 30:
stateMentionAtChar(context, stateMachine, charCode);
break;
case 31:
stateMentionTextChar(context, stateMachine, charCode);
break;
// Phone number states
case 32:
statePhoneNumberOpenParen(context, stateMachine, char, charCode);
break;
case 33:
statePhoneNumberAreaCodeDigit1(context, stateMachine, charCode);
break;
case 34:
statePhoneNumberAreaCodeDigit2(context, stateMachine, charCode);
break;
case 35:
statePhoneNumberAreaCodeDigit3(context, stateMachine, charCode);
break;
case 36:
statePhoneNumberCloseParen(context, stateMachine, char, charCode);
break;
case 37:
statePhoneNumberPlus(context, stateMachine, char, charCode);
break;
case 38:
statePhoneNumberDigit(context, stateMachine, char, charCode);
break;
case 39:
statePhoneNumberSeparator(context, stateMachine, char, charCode);
break;
case 40:
statePhoneNumberControlChar(context, stateMachine, charCode);
break;
case 41:
statePhoneNumberPoundChar(context, stateMachine, charCode);
break;
/* istanbul ignore next */
default:
assertNever(stateMachine.state);
}
}
if (!context.hasSchemeUrlMachine() && context.charIdx > 0 && isSchemeStartChar(charCode)) {
var prevCharCode = context.text.charCodeAt(context.charIdx - 1);
if (!isSchemeStartChar(prevCharCode)) {
context.addMachine(createSchemeUrlStateMachine(
context.charIdx,
0
/* State.SchemeChar */
));
}
}
}
}
for (var i = context.stateMachines.length - 1; i >= 0; i--) {
context.stateMachines.forEach(function(stateMachine2) {
return captureMatchIfValidAndRemove(context, stateMachine2);
});
}
return context.matches;
}
function stateNoMatch(context, char, charCode) {
var charIdx = context.charIdx;
if (charCode === 35) {
context.addMachine(createHashtagStateMachine(
charIdx,
28
/* State.HashtagHashChar */
));
} else if (charCode === 64) {
context.addMachine(createMentionStateMachine(
charIdx,
30
/* State.MentionAtChar */
));
} else if (charCode === 47) {
context.addMachine(createTldUrlStateMachine(
charIdx,
11
/* State.ProtocolRelativeSlash1 */
));
} else if (charCode === 43) {
context.addMachine(createPhoneNumberStateMachine(
charIdx,
37
/* State.PhoneNumberPlus */
));
} else if (charCode === 40) {
context.addMachine(createPhoneNumberStateMachine(
charIdx,
32
/* State.PhoneNumberOpenParen */
));
} else {
if (isDigitChar(charCode)) {
context.addMachine(createPhoneNumberStateMachine(
charIdx,
38
/* State.PhoneNumberDigit */
));
context.addMachine(createIpV4UrlStateMachine(
charIdx,
13
/* State.IpV4Digit */
));
}
if (isEmailLocalPartStartChar(charCode)) {
var startState = char.toLowerCase() === "m" ? 15 : 22;
context.addMachine(createEmailStateMachine(charIdx, startState));
}
if (isSchemeStartChar(charCode)) {
context.addMachine(createSchemeUrlStateMachine(
charIdx,
0
/* State.SchemeChar */
));
}
if (isAlphaNumericOrMarkChar(charCode)) {
context.addMachine(createTldUrlStateMachine(
charIdx,
5
/* State.DomainLabelChar */
));
}
}
}
function stateSchemeChar(context, stateMachine, charCode) {
if (charCode === 58) {
stateMachine.state = 2;
} else if (charCode === 45) {
stateMachine.state = 1;
} else if (isSchemeChar(charCode)) {
} else {
context.removeMachine(stateMachine);
}
}
function stateSchemeHyphen(context, stateMachine, charCode) {
var charIdx = context.charIdx;
if (charCode === 45) {
} else if (charCode === 47) {
context.removeMachine(stateMachine);
context.addMachine(createTldUrlStateMachine(
charIdx,
11
/* State.ProtocolRelativeSlash1 */
));
} else if (isSchemeChar(charCode)) {
stateMachine.state = 0;
} else {
context.removeMachine(stateMachine);
}
}
function stateSchemeColon(context, stateMachine, charCode) {
var charIdx = context.charIdx;
if (charCode === 47) {
stateMachine.state = 3;
} else if (charCode === 46) {
context.removeMachine(stateMachine);
} else if (isDomainLabelStartChar(charCode)) {
stateMachine.state = 5;
if (isSchemeStartChar(charCode)) {
context.addMachine(createSchemeUrlStateMachine(
charIdx,
0
/* State.SchemeChar */
));
}
} else {
context.removeMachine(stateMachine);
}
}
function stateSchemeSlash1(context, stateMachine, charCode) {
if (charCode === 47) {
stateMachine.state = 4;
} else if (isPathChar(charCode)) {
stateMachine.state = 10;
stateMachine.acceptStateReached = true;
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function stateSchemeSlash2(context, stateMachine, char, charCode) {
if (charCode === 47) {
stateMachine.state = 10;
stateMachine.acceptStateReached = true;
} else if (isDomainLabelStartChar(charCode)) {
stateMachine.state = 5;
stateMachine.acceptStateReached = true;
} else {
context.removeMachine(stateMachine);
}
}
function stateProtocolRelativeSlash1(context, stateMachine, charCode) {
if (charCode === 47) {
stateMachine.state = 12;
} else {
context.removeMachine(stateMachine);
}
}
function stateProtocolRelativeSlash2(context, stateMachine, charCode) {
if (isDomainLabelStartChar(charCode)) {
stateMachine.state = 5;
} else {
context.removeMachine(stateMachine);
}
}
function stateDomainLabelChar(context, stateMachine, charCode) {
if (charCode === 46) {
stateMachine.state = 7;
} else if (charCode === 45) {
stateMachine.state = 6;
} else if (charCode === 58) {
stateMachine.state = 8;
} else if (isUrlSuffixStartChar(charCode)) {
stateMachine.state = 10;
} else if (isDomainLabelChar(charCode)) {
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function stateDomainHyphen(context, stateMachine, char, charCode) {
if (charCode === 45) {
} else if (charCode === 46) {
captureMatchIfValidAndRemove(context, stateMachine);
} else if (isDomainLabelStartChar(charCode)) {
stateMachine.state = 5;
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function stateDomainDot(context, stateMachine, char, charCode) {
if (charCode === 46) {
captureMatchIfValidAndRemove(context, stateMachine);
} else if (isDomainLabelStartChar(charCode)) {
stateMachine.state = 5;
stateMachine.acceptStateReached = true;
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function stateIpV4Digit(context, stateMachine, charCode) {
if (charCode === 46) {
stateMachine.state = 14;
} else if (charCode === 58) {
stateMachine.state = 8;
} else if (isDigitChar(charCode)) {
} else if (isUrlSuffixStartChar(charCode)) {
stateMachine.state = 10;
} else if (isAlphaNumericOrMarkChar(charCode)) {
context.removeMachine(stateMachine);
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function stateIpV4Dot(context, stateMachine, charCode) {
if (isDigitChar(charCode)) {
stateMachine.octetsEncountered++;
if (stateMachine.octetsEncountered === 4) {
stateMachine.acceptStateReached = true;
}
stateMachine.state = 13;
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function statePortColon(context, stateMachine, charCode) {
if (isDigitChar(charCode)) {
stateMachine.state = 9;
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function statePortNumber(context, stateMachine, charCode) {
if (isDigitChar(charCode)) {
} else if (isUrlSuffixStartChar(charCode)) {
stateMachine.state = 10;
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function statePath(context, stateMachine, charCode) {
if (isPathChar(charCode)) {
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function stateEmailMailto_M(context, stateMachine, char, charCode) {
if (char.toLowerCase() === "a") {
stateMachine.state = 16;
} else {
stateEmailLocalPart(context, stateMachine, charCode);
}
}
function stateEmailMailto_A(context, stateMachine, char, charCode) {
if (char.toLowerCase() === "i") {
stateMachine.state = 17;
} else {
stateEmailLocalPart(context, stateMachine, charCode);
}
}
function stateEmailMailto_I(context, stateMachine, char, charCode) {
if (char.toLowerCase() === "l") {
stateMachine.state = 18;
} else {
stateEmailLocalPart(context, stateMachine, charCode);
}
}
function stateEmailMailto_L(context, stateMachine, char, charCode) {
if (char.toLowerCase() === "t") {
stateMachine.state = 19;
} else {
stateEmailLocalPart(context, stateMachine, charCode);
}
}
function stateEmailMailto_T(context, stateMachine, char, charCode) {
if (char.toLowerCase() === "o") {
stateMachine.state = 20;
} else {
stateEmailLocalPart(context, stateMachine, charCode);
}
}
function stateEmailMailto_O(context, stateMachine, charCode) {
if (charCode === 58) {
stateMachine.state = 21;
} else {
stateEmailLocalPart(context, stateMachine, charCode);
}
}
function stateEmailMailtoColon(context, stateMachine, charCode) {
if (isEmailLocalPartChar(charCode)) {
stateMachine.state = 22;
} else {
context.removeMachine(stateMachine);
}
}
function stateEmailLocalPart(context, stateMachine, charCode) {
if (charCode === 46) {
stateMachine.state = 23;
} else if (charCode === 64) {
stateMachine.state = 24;
} else if (isEmailLocalPartChar(charCode)) {
stateMachine.state = 22;
} else {
context.removeMachine(stateMachine);
}
}
function stateEmailLocalPartDot(context, stateMachine, charCode) {
if (charCode === 46) {
context.removeMachine(stateMachine);
} else if (charCode === 64) {
context.removeMachine(stateMachine);
} else if (isEmailLocalPartChar(charCode)) {
stateMachine.state = 22;
} else {
context.removeMachine(stateMachine);
}
}
function stateEmailAtSign(context, stateMachine, charCode) {
if (isDomainLabelStartChar(charCode)) {
stateMachine.state = 25;
} else {
context.removeMachine(stateMachine);
}
}
function stateEmailDomainChar(context, stateMachine, charCode) {
if (charCode === 46) {
stateMachine.state = 27;
} else if (charCode === 45) {
stateMachine.state = 26;
} else if (isDomainLabelChar(charCode)) {
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function stateEmailDomainHyphen(context, stateMachine, charCode) {
if (charCode === 45 || charCode === 46) {
captureMatchIfValidAndRemove(context, stateMachine);
} else if (isDomainLabelChar(charCode)) {
stateMachine.state = 25;
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function stateEmailDomainDot(context, stateMachine, charCode) {
if (charCode === 46 || charCode === 45) {
captureMatchIfValidAndRemove(context, stateMachine);
} else if (isDomainLabelStartChar(charCode)) {
stateMachine.state = 25;
stateMachine.acceptStateReached = true;
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function stateHashtagHashChar(context, stateMachine, charCode) {
if (isHashtagTextChar(charCode)) {
stateMachine.state = 29;
stateMachine.acceptStateReached = true;
} else {
context.removeMachine(stateMachine);
}
}
function stateHashtagTextChar(context, stateMachine, charCode) {
if (isHashtagTextChar(charCode)) {
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function stateMentionAtChar(context, stateMachine, charCode) {
if (isMentionTextChar(charCode)) {
stateMachine.state = 31;
stateMachine.acceptStateReached = true;
} else {
context.removeMachine(stateMachine);
}
}
function stateMentionTextChar(context, stateMachine, charCode) {
if (isMentionTextChar(charCode)) {
} else if (isAlphaNumericOrMarkChar(charCode)) {
context.removeMachine(stateMachine);
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function statePhoneNumberPlus(context, stateMachine, char, charCode) {
if (isDigitChar(charCode)) {
stateMachine.state = 38;
} else {
context.removeMachine(stateMachine);
stateNoMatch(context, char, charCode);
}
}
function statePhoneNumberOpenParen(context, stateMachine, char, charCode) {
if (isDigitChar(charCode)) {
stateMachine.state = 33;
} else {
context.removeMachine(stateMachine);
}
stateNoMatch(context, char, charCode);
}
function statePhoneNumberAreaCodeDigit1(context, stateMachine, charCode) {
if (isDigitChar(charCode)) {
stateMachine.state = 34;
} else {
context.removeMachine(stateMachine);
}
}
function statePhoneNumberAreaCodeDigit2(context, stateMachine, charCode) {
if (isDigitChar(charCode)) {
stateMachine.state = 35;
} else {
context.removeMachine(stateMachine);
}
}
function statePhoneNumberAreaCodeDigit3(context, stateMachine, charCode) {
if (charCode === 41) {
stateMachine.state = 36;
} else {
context.removeMachine(stateMachine);
}
}
function statePhoneNumberCloseParen(context, stateMachine, char, charCode) {
if (isDigitChar(charCode)) {
stateMachine.state = 38;
} else if (isPhoneNumberSeparatorChar(charCode)) {
stateMachine.state = 39;
} else {
context.removeMachine(stateMachine);
}
}
function statePhoneNumberDigit(context, stateMachine, char, charCode) {
var charIdx = context.charIdx;
stateMachine.acceptStateReached = true;
if (isPhoneNumberControlChar(charCode)) {
stateMachine.state = 40;
} else if (charCode === 35) {
stateMachine.state = 41;
} else if (isDigitChar(charCode)) {
} else if (charCode === 40) {
stateMachine.state = 32;
} else if (isPhoneNumberSeparatorChar(charCode)) {
stateMachine.state = 39;
} else {
captureMatchIfValidAndRemove(context, stateMachine);
if (isSchemeStartChar(charCode)) {
context.addMachine(createSchemeUrlStateMachine(
charIdx,
0
/* State.SchemeChar */
));
}
}
}
function statePhoneNumberSeparator(context, stateMachine, char, charCode) {
if (isDigitChar(charCode)) {
stateMachine.state = 38;
} else if (charCode === 40) {
stateMachine.state = 32;
} else {
captureMatchIfValidAndRemove(context, stateMachine);
stateNoMatch(context, char, charCode);
}
}
function statePhoneNumberControlChar(context, stateMachine, charCode) {
if (isPhoneNumberControlChar(charCode)) {
} else if (charCode === 35) {
stateMachine.state = 41;
} else if (isDigitChar(charCode)) {
stateMachine.state = 38;
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function statePhoneNumberPoundChar(context, stateMachine, charCode) {
if (isPhoneNumberControlChar(charCode)) {
stateMachine.state = 40;
} else if (isDigitChar(charCode)) {
context.removeMachine(stateMachine);
} else {
captureMatchIfValidAndRemove(context, stateMachine);
}
}
function captureMatchIfValidAndRemove(context, stateMachine) {
var matches = context.matches, text2 = context.text, charIdx = context.charIdx, tagBuilder = context.tagBuilder, stripPrefix = context.stripPrefix, stripTrailingSlash = context.stripTrailingSlash, decodePercentEncoding = context.decodePercentEncoding, hashtagServiceName = context.hashtagServiceName, mentionServiceName = context.mentionServiceName;
context.removeMachine(stateMachine);
if (!stateMachine.acceptStateReached) {
return;
}
var startIdx = stateMachine.startIdx;
var matchedText = text2.slice(stateMachine.startIdx, charIdx);
matchedText = excludeUnbalancedTrailingBracesAndPunctuation(matchedText);
switch (stateMachine.type) {
case 0: {
var charBeforeUrlMatch = text2.charCodeAt(stateMachine.startIdx - 1);
if (charBeforeUrlMatch === 64) {
return;
}
switch (stateMachine.matchType) {
case 0: {
var httpSchemeMatch = httpSchemeRe.exec(matchedText);
if (httpSchemeMatch) {
startIdx = startIdx + httpSchemeMatch.index;
matchedText = matchedText.slice(httpSchemeMatch.index);
}
if (!isValidSchemeUrl(matchedText)) {
return;
}
break;
}
case 1: {
if (!isValidTldMatch(matchedText)) {
return;
}
break;
}
case 2: {
if (!isValidIpV4Address(matchedText)) {
return;
}
break;
}
/* istanbul ignore next */
default:
assertNever(stateMachine);
}
matches.push(new UrlMatch({
tagBuilder,
matchedText,
offset: startIdx,
urlMatchType: toUrlMatchType(stateMachine.matchType),
url: matchedText,
protocolRelativeMatch: matchedText.slice(0, 2) === "//",
// TODO: Do these settings need to be passed to the match,
// or should we handle them here in UrlMatcher?
stripPrefix,
stripTrailingSlash,
decodePercentEncoding
}));
break;
}
case 1: {
if (isValidEmail(matchedText)) {
matches.push(new EmailMatch({
tagBuilder,
matchedText,
offset: startIdx,
email: matchedText.replace(mailtoSchemePrefixRe, "")
}));
}
break;
}
case 2: {
if (isValidHashtag(matchedText)) {
matches.push(new HashtagMatch({
tagBuilder,
matchedText,
offset: startIdx,
serviceName: hashtagServiceName,
hashtag: matchedText.slice(1)
}));
}
break;
}
case 3: {
if (isValidMention(matchedText, mentionServiceName)) {
matches.push(new MentionMatch({
tagBuilder,
matchedText,
offset: startIdx,
serviceName: mentionServiceName,
mention: matchedText.slice(1)
// strip off the '@' character at the beginning
}));
}
break;
}
case 4: {
matchedText = matchedText.replace(/ +$/g, "");
if (isValidPhoneNumber(matchedText)) {
var cleanNumber = matchedText.replace(/[^0-9,;#]/g, "");
matches.push(new PhoneMatch({
tagBuilder,
matchedText,
offset: startIdx,
number: cleanNumber,
plusSign: matchedText.charAt(0) === "+"
}));
}
break;
}
/* istanbul ignore next */
default:
assertNever(stateMachine);
}
}
function toUrlMatchType(stateMachineMatchType) {
switch (stateMachineMatchType) {
case 0:
return "scheme";
case 1:
return "tld";
case 2:
return "ipV4";
/* istanbul ignore next */
default:
assertNever(stateMachineMatchType);
}
}
var oppositeBrace = {
")": "(",
"}": "{",
"]": "["
};
function excludeUnbalancedTrailingBracesAndPunctuation(matchedText) {
var braceCounts = {
"(": 0,
"{": 0,
"[": 0
};
for (var i = 0; i < matchedText.length; i++) {
var char = matchedText.charAt(i);
var charCode = matchedText.charCodeAt(i);
if (isOpenBraceChar(charCode)) {
braceCounts[char]++;
} else if (isCloseBraceChar(charCode)) {
braceCounts[oppositeBrace[char]]--;
}
}
var endIdx = matchedText.length - 1;
while (endIdx >= 0) {
var char = matchedText.charAt(endIdx);
var charCode = matchedText.charCodeAt(endIdx);
if (isCloseBraceChar(charCode)) {
var oppositeBraceChar = oppositeBrace[char];
if (braceCounts[oppositeBraceChar] < 0) {
braceCounts[oppositeBraceChar]++;
endIdx--;
} else {
break;
}
} else if (isUrlSuffixNotAllowedAsFinalChar(charCode)) {
endIdx--;
} else {
break;
}
}
return matchedText.slice(0, endIdx + 1);
}
function createSchemeUrlStateMachine(startIdx, state) {
return {
type: 0,
startIdx,
state,
acceptStateReached: false,
matchType: 0
};
}
function createTldUrlStateMachine(startIdx, state) {
return {
type: 0,
startIdx,
state,
acceptStateReached: false,
matchType: 1
};
}
function createIpV4UrlStateMachine(startIdx, state) {
return {
type: 0,
startIdx,
state,
acceptStateReached: false,
matchType: 2,
octetsEncountered: 1
// starts at 1 because we create this machine when encountering the first octet
};
}
function createEmailStateMachine(startIdx, state) {
return {
type: 1,
startIdx,
state,
acceptStateReached: false
};
}
function createHashtagStateMachine(startIdx, state) {
return {
type: 2,
startIdx,
state,
acceptStateReached: false
};
}
function createMentionStateMachine(startIdx, state) {
return {
type: 3,
startIdx,
state,
acceptStateReached: false
};
}
function createPhoneNumberStateMachine(startIdx, state) {
return {
type: 4,
startIdx,
state,
acceptStateReached: false
};
}
function isSchemeUrlStateMachine(machine) {
return machine.type === 0 && machine.matchType === 0;
}
// node_modules/autolinker/dist/es2015/htmlParser/parse-html.js
var import_InlineWorkers958 = __toESM(require_InlineWorkers());
var CurrentTag = (
/** @class */
/* @__PURE__ */ (function() {
function CurrentTag2(cfg) {
if (cfg === void 0) {
cfg = {};
}
this.idx = cfg.idx !== void 0 ? cfg.idx : -1;
this.type = cfg.type || "tag";
this.name = cfg.name || "";
this.isOpening = !!cfg.isOpening;
this.isClosing = !!cfg.isClosing;
}
return CurrentTag2;
})()
);
var noCurrentTag = new CurrentTag();
var ParseHtmlContext = (
/** @class */
/* @__PURE__ */ (function() {
function ParseHtmlContext2(html2, callbacks) {
this.charIdx = 0;
this.state = 0;
this.currentDataIdx = 0;
this.currentTag = noCurrentTag;
this.html = html2;
this.callbacks = callbacks;
}
return ParseHtmlContext2;
})()
);
function parseHtml(html2, callbacks) {
var context = new ParseHtmlContext(html2, callbacks);
var len = html2.length;
while (context.charIdx < len) {
var char = html2.charAt(context.charIdx);
var charCode = html2.charCodeAt(context.charIdx);
switch (context.state) {
case 0:
stateData(context, char);
break;
case 1:
stateTagOpen(context, char, charCode);
break;
case 2:
stateEndTagOpen(context, char, charCode);
break;
case 3:
stateTagName(context, char, charCode);
break;
case 4:
stateBeforeAttributeName(context, char, charCode);
break;
case 5:
stateAttributeName(context, char, charCode);
break;
case 6:
stateAfterAttributeName(context, char, charCode);
break;
case 7:
stateBeforeAttributeValue(context, char, charCode);
break;
case 8:
stateAttributeValueDoubleQuoted(context, char);
break;
case 9:
stateAttributeValueSingleQuoted(context, char);
break;
case 10:
stateAttributeValueUnquoted(context, char, charCode);
break;
case 11:
stateAfterAttributeValueQuoted(context, char, charCode);
break;
case 12:
stateSelfClosingStartTag(context, char);
break;
case 13:
stateMarkupDeclarationOpen(context);
break;
case 14:
stateCommentStart(context, char);
break;
case 15:
stateCommentStartDash(context, char);
break;
case 16:
stateComment(context, char);
break;
case 17:
stateCommentEndDash(context, char);
break;
case 18:
stateCommentEnd(context, char);
break;
case 19:
stateCommentEndBang(context, char);
break;
case 20:
stateDoctype(context, char);
break;
/* istanbul ignore next */
default:
assertNever(context.state);
}
context.charIdx++;
}
if (context.currentDataIdx < context.charIdx) {
emitText(context);
}
}
function stateData(context, char) {
if (char === "<") {
startNewTag(context);
}
}
function stateTagOpen(context, char, charCode) {
if (char === "!") {
context.state = 13;
} else if (char === "/") {
context.state = 2;
context.currentTag = new CurrentTag(__assign(__assign({}, context.currentTag), { isClosing: true }));
} else if (char === "<") {
startNewTag(context);
} else if (isAsciiLetterChar(charCode)) {
context.state = 3;
context.currentTag = new CurrentTag(__assign(__assign({}, context.currentTag), { isOpening: true }));
} else {
context.state = 0;
context.currentTag = noCurrentTag;
}
}
function stateTagName(context, char, charCode) {
if (isWhitespaceChar(charCode)) {
context.currentTag = new CurrentTag(__assign(__assign({}, context.currentTag), { name: captureTagName(context) }));
context.state = 4;
} else if (char === "<") {
startNewTag(context);
} else if (char === "/") {
context.currentTag = new CurrentTag(__assign(__assign({}, context.currentTag), { name: captureTagName(context) }));
context.state = 12;
} else if (char === ">") {
context.currentTag = new CurrentTag(__assign(__assign({}, context.currentTag), { name: captureTagName(context) }));
emitTagAndPreviousTextNode(context);
} else if (!isAsciiLetterChar(charCode) && !isDigitChar(charCode) && char !== ":") {
resetToDataState(context);
} else {
}
}
function stateEndTagOpen(context, char, charCode) {
if (char === ">") {
resetToDataState(context);
} else if (isAsciiLetterChar(charCode)) {
context.state = 3;
} else {
resetToDataState(context);
}
}
function stateBeforeAttributeName(context, char, charCode) {
if (isWhitespaceChar(charCode)) {
} else if (char === "/") {
context.state = 12;
} else if (char === ">") {
emitTagAndPreviousTextNode(context);
} else if (char === "<") {
startNewTag(context);
} else if (char === "=" || isQuoteChar(charCode) || isControlChar(charCode)) {
resetToDataState(context);
} else {
context.state = 5;
}
}
function stateAttributeName(context, char, charCode) {
if (isWhitespaceChar(charCode)) {
context.state = 6;
} else if (char === "/") {
context.state = 12;
} else if (char === "=") {
context.state = 7;
} else if (char === ">") {
emitTagAndPreviousTextNode(context);
} else if (char === "<") {
startNewTag(context);
} else if (isQuoteChar(charCode)) {
resetToDataState(context);
} else {
}
}
function stateAfterAttributeName(context, char, charCode) {
if (isWhitespaceChar(charCode)) {
} else if (char === "/") {
context.state = 12;
} else if (char === "=") {
context.state = 7;
} else if (char === ">") {
emitTagAndPreviousTextNode(context);
} else if (char === "<") {
startNewTag(context);
} else if (isQuoteChar(charCode)) {
resetToDataState(context);
} else {
context.state = 5;
}
}
function stateBeforeAttributeValue(context, char, charCode) {
if (isWhitespaceChar(charCode)) {
} else if (char === '"') {
context.state = 8;
} else if (char === "'") {
context.state = 9;
} else if (/[>=`]/.test(char)) {
resetToDataState(context);
} else if (char === "<") {
startNewTag(context);
} else {
context.state = 10;
}
}
function stateAttributeValueDoubleQuoted(context, char) {
if (char === '"') {
context.state = 11;
} else {
}
}
function stateAttributeValueSingleQuoted(context, char) {
if (char === "'") {
context.state = 11;
} else {
}
}
function stateAttributeValueUnquoted(context, char, charCode) {
if (isWhitespaceChar(charCode)) {
context.state = 4;
} else if (char === ">") {
emitTagAndPreviousTextNode(context);
} else if (char === "<") {
startNewTag(context);
} else {
}
}
function stateAfterAttributeValueQuoted(context, char, charCode) {
if (isWhitespaceChar(charCode)) {
context.state = 4;
} else if (char === "/") {
context.state = 12;
} else if (char === ">") {
emitTagAndPreviousTextNode(context);
} else if (char === "<") {
startNewTag(context);
} else {
context.state = 4;
reconsumeCurrentChar(context);
}
}
function stateSelfClosingStartTag(context, char) {
if (char === ">") {
context.currentTag = new CurrentTag(__assign(__assign({}, context.currentTag), { isClosing: true }));
emitTagAndPreviousTextNode(context);
} else {
resetToDataState(context);
}
}
function stateMarkupDeclarationOpen(context) {
var html2 = context.html, charIdx = context.charIdx;
if (html2.slice(charIdx, charIdx + 2) === "--") {
context.charIdx++;
context.currentTag = new CurrentTag(__assign(__assign({}, context.currentTag), { type: "comment" }));
context.state = 14;
} else if (html2.slice(charIdx, charIdx + 7).toUpperCase() === "DOCTYPE") {
context.charIdx += 6;
context.currentTag = new CurrentTag(__assign(__assign({}, context.currentTag), { type: "doctype" }));
context.state = 20;
} else {
resetToDataState(context);
}
}
function stateCommentStart(context, char) {
if (char === "-") {
context.state = 15;
} else if (char === ">") {
resetToDataState(context);
} else {
context.state = 16;
}
}
function stateCommentStartDash(context, char) {
if (char === "-") {
context.state = 18;
} else if (char === ">") {
resetToDataState(context);
} else {
context.state = 16;
}
}
function stateComment(context, char) {
if (char === "-") {
context.state = 17;
} else {
}
}
function stateCommentEndDash(context, char) {
if (char === "-") {
context.state = 18;
} else {
context.state = 16;
}
}
function stateCommentEnd(context, char) {
if (char === ">") {
emitTagAndPreviousTextNode(context);
} else if (char === "!") {
context.state = 19;
} else if (char === "-") {
} else {
context.state = 16;
}
}
function stateCommentEndBang(context, char) {
if (char === "-") {
context.state = 17;
} else if (char === ">") {
emitTagAndPreviousTextNode(context);
} else {
context.state = 16;
}
}
function stateDoctype(context, char) {
if (char === ">") {
emitTagAndPreviousTextNode(context);
} else if (char === "<") {
startNewTag(context);
} else {
}
}
function resetToDataState(context) {
context.state = 0;
context.currentTag = noCurrentTag;
}
function startNewTag(context) {
context.state = 1;
context.currentTag = new CurrentTag({ idx: context.charIdx });
}
function emitTagAndPreviousTextNode(context) {
var textBeforeTag = context.html.slice(context.currentDataIdx, context.currentTag.idx);
if (textBeforeTag) {
context.callbacks.onText(textBeforeTag, context.currentDataIdx);
}
var currentTag = context.currentTag;
if (currentTag.type === "comment") {
context.callbacks.onComment(currentTag.idx);
} else if (currentTag.type === "doctype") {
context.callbacks.onDoctype(currentTag.idx);
} else {
if (currentTag.isOpening) {
context.callbacks.onOpenTag(currentTag.name, currentTag.idx);
}
if (currentTag.isClosing) {
context.callbacks.onCloseTag(currentTag.name, currentTag.idx);
}
}
resetToDataState(context);
context.currentDataIdx = context.charIdx + 1;
}
function emitText(context) {
var text2 = context.html.slice(context.currentDataIdx, context.charIdx);
context.callbacks.onText(text2, context.currentDataIdx);
context.currentDataIdx = context.charIdx + 1;
}
function captureTagName(context) {
var startIdx = context.currentTag.idx + (context.currentTag.isClosing ? 2 : 1);
return context.html.slice(startIdx, context.charIdx).toLowerCase();
}
function reconsumeCurrentChar(context) {
context.charIdx--;
}
// node_modules/autolinker/dist/es2015/autolinker.js
var Autolinker = (
/** @class */
(function() {
function Autolinker2(cfg) {
if (cfg === void 0) {
cfg = {};
}
this.version = Autolinker2.version;
this.urls = {};
this.email = true;
this.phone = true;
this.hashtag = false;
this.mention = false;
this.newWindow = true;
this.stripPrefix = {
scheme: true,
www: true
};
this.stripTrailingSlash = true;
this.decodePercentEncoding = true;
this.truncate = {
length: 0,
location: "end"
};
this.className = "";
this.replaceFn = null;
this.context = void 0;
this.sanitizeHtml = false;
this.tagBuilder = null;
this.urls = normalizeUrlsCfg(cfg.urls);
this.email = isBoolean(cfg.email) ? cfg.email : this.email;
this.phone = isBoolean(cfg.phone) ? cfg.phone : this.phone;
this.hashtag = cfg.hashtag || this.hashtag;
this.mention = cfg.mention || this.mention;
this.newWindow = isBoolean(cfg.newWindow) ? cfg.newWindow : this.newWindow;
this.stripPrefix = normalizeStripPrefixCfg(cfg.stripPrefix);
this.stripTrailingSlash = isBoolean(cfg.stripTrailingSlash) ? cfg.stripTrailingSlash : this.stripTrailingSlash;
this.decodePercentEncoding = isBoolean(cfg.decodePercentEncoding) ? cfg.decodePercentEncoding : this.decodePercentEncoding;
this.sanitizeHtml = cfg.sanitizeHtml || false;
var mention = this.mention;
if (mention !== false && mentionServices.indexOf(mention) === -1) {
throw new Error("invalid `mention` cfg '".concat(mention, "' - see docs"));
}
var hashtag = this.hashtag;
if (hashtag !== false && hashtagServices.indexOf(hashtag) === -1) {
throw new Error("invalid `hashtag` cfg '".concat(hashtag, "' - see docs"));
}
this.truncate = normalizeTruncateCfg(cfg.truncate);
this.className = cfg.className || this.className;
this.replaceFn = cfg.replaceFn || this.replaceFn;
this.context = cfg.context || this;
}
Autolinker2.link = function(textOrHtml, options) {
var autolinker3 = new Autolinker2(options);
return autolinker3.link(textOrHtml);
};
Autolinker2.parse = function(textOrHtml, options) {
var autolinker3 = new Autolinker2(options);
return autolinker3.parse(textOrHtml);
};
Autolinker2.prototype.parse = function(textOrHtml) {
var _this = this;
var skipTagNames = ["a", "style", "script"];
var skipTagsStackCount = 0;
var matches = [];
parseHtml(textOrHtml, {
onOpenTag: function(tagName) {
if (skipTagNames.indexOf(tagName) >= 0) {
skipTagsStackCount++;
}
},
onText: function(text2, offset) {
if (skipTagsStackCount === 0) {
var htmlCharacterEntitiesRegex = /( | |<|<|>|>|"|"|')/gi;
var textSplit = text2.split(htmlCharacterEntitiesRegex);
var currentOffset_1 = offset;
textSplit.forEach(function(splitText, i) {
if (i % 2 === 0) {
var textNodeMatches = _this.parseText(splitText, currentOffset_1);
matches.push.apply(matches, __spreadArray([], __read(textNodeMatches), false));
}
currentOffset_1 += splitText.length;
});
}
},
onCloseTag: function(tagName) {
if (skipTagNames.indexOf(tagName) >= 0) {
skipTagsStackCount = Math.max(skipTagsStackCount - 1, 0);
}
},
onComment: function() {
},
// no need to process comment nodes
onDoctype: function() {
}
// no need to process doctype nodes
});
matches = this.compactMatches(matches);
matches = this.removeUnwantedMatches(matches);
return matches;
};
Autolinker2.prototype.compactMatches = function(matches) {
matches.sort(byMatchOffset);
var i = 0;
while (i < matches.length - 1) {
var match = matches[i];
var offset = match.getOffset();
var matchedTextLength = match.getMatchedText().length;
if (i + 1 < matches.length) {
if (matches[i + 1].getOffset() === offset) {
var removeIdx = matches[i + 1].getMatchedText().length > matchedTextLength ? i : i + 1;
matches.splice(removeIdx, 1);
continue;
}
}
i++;
}
return matches;
};
Autolinker2.prototype.removeUnwantedMatches = function(matches) {
if (!this.hashtag)
removeWithPredicate(matches, function(match) {
return match.getType() === "hashtag";
});
if (!this.email)
removeWithPredicate(matches, function(match) {
return match.getType() === "email";
});
if (!this.phone)
removeWithPredicate(matches, function(match) {
return match.getType() === "phone";
});
if (!this.mention)
removeWithPredicate(matches, function(match) {
return match.getType() === "mention";
});
if (!this.urls.schemeMatches) {
removeWithPredicate(matches, function(m) {
return m.getType() === "url" && m.getUrlMatchType() === "scheme";
});
}
if (!this.urls.tldMatches) {
removeWithPredicate(matches, function(m) {
return m.getType() === "url" && m.getUrlMatchType() === "tld";
});
}
if (!this.urls.ipV4Matches) {
removeWithPredicate(matches, function(m) {
return m.getType() === "url" && m.getUrlMatchType() === "ipV4";
});
}
return matches;
};
Autolinker2.prototype.parseText = function(text2, offset) {
offset = offset || 0;
var matches = parseMatches(text2, {
tagBuilder: this.getTagBuilder(),
stripPrefix: this.stripPrefix,
stripTrailingSlash: this.stripTrailingSlash,
decodePercentEncoding: this.decodePercentEncoding,
hashtagServiceName: this.hashtag,
mentionServiceName: this.mention || "twitter"
});
for (var i = 0, numTextMatches = matches.length; i < numTextMatches; i++) {
matches[i].setOffset(offset + matches[i].getOffset());
}
return matches;
};
Autolinker2.prototype.link = function(textOrHtml) {
if (!textOrHtml) {
return "";
}
if (this.sanitizeHtml) {
textOrHtml = textOrHtml.replace(//g, ">");
}
var matches = this.parse(textOrHtml);
var newHtml = new Array(matches.length * 2 + 1);
var lastIndex = 0;
for (var i = 0, len = matches.length; i < len; i++) {
var match = matches[i];
newHtml.push(textOrHtml.substring(lastIndex, match.getOffset()));
newHtml.push(this.createMatchReturnVal(match));
lastIndex = match.getOffset() + match.getMatchedText().length;
}
newHtml.push(textOrHtml.substring(lastIndex));
return newHtml.join("");
};
Autolinker2.prototype.createMatchReturnVal = function(match) {
var replaceFnResult;
if (this.replaceFn) {
replaceFnResult = this.replaceFn.call(this.context, match);
}
if (typeof replaceFnResult === "string") {
return replaceFnResult;
} else if (replaceFnResult === false) {
return match.getMatchedText();
} else if (replaceFnResult instanceof HtmlTag) {
return replaceFnResult.toAnchorString();
} else {
var anchorTag = match.buildTag();
return anchorTag.toAnchorString();
}
};
Autolinker2.prototype.getTagBuilder = function() {
var tagBuilder = this.tagBuilder;
if (!tagBuilder) {
tagBuilder = this.tagBuilder = new AnchorTagBuilder({
newWindow: this.newWindow,
truncate: this.truncate,
className: this.className
});
}
return tagBuilder;
};
Autolinker2.version = version;
return Autolinker2;
})()
);
var autolinker_default = Autolinker;
function normalizeUrlsCfg(urls) {
if (urls == null)
urls = true;
if (isBoolean(urls)) {
return { schemeMatches: urls, tldMatches: urls, ipV4Matches: urls };
} else {
return {
schemeMatches: isBoolean(urls.schemeMatches) ? urls.schemeMatches : true,
tldMatches: isBoolean(urls.tldMatches) ? urls.tldMatches : true,
ipV4Matches: isBoolean(urls.ipV4Matches) ? urls.ipV4Matches : true
};
}
}
function normalizeStripPrefixCfg(stripPrefix) {
if (stripPrefix == null)
stripPrefix = true;
if (isBoolean(stripPrefix)) {
return { scheme: stripPrefix, www: stripPrefix };
} else {
return {
scheme: isBoolean(stripPrefix.scheme) ? stripPrefix.scheme : true,
www: isBoolean(stripPrefix.www) ? stripPrefix.www : true
};
}
}
function normalizeTruncateCfg(truncate) {
if (typeof truncate === "number") {
return { length: truncate, location: "end" };
} else {
return __assign({ length: Number.POSITIVE_INFINITY, location: "end" }, truncate);
}
}
function byMatchOffset(a3, b) {
return a3.getOffset() - b.getOffset();
}
// node_modules/autolinker/dist/es2015/match/index.js
var import_InlineWorkers961 = __toESM(require_InlineWorkers());
// node_modules/autolinker/dist/es2015/match/match.js
var import_InlineWorkers960 = __toESM(require_InlineWorkers());
// node_modules/autolinker/dist/es2015/parser/index.js
var import_InlineWorkers962 = __toESM(require_InlineWorkers());
// node_modules/autolinker/dist/es2015/index.js
var es2015_default = autolinker_default;
// packages/engine/Source/DataSources/GpxDataSource.js
var parser;
if (typeof DOMParser !== "undefined") {
parser = new DOMParser();
}
var autolinker = new es2015_default({
stripPrefix: false,
email: false,
replaceFn: function(linker, match) {
return match.urlMatchType === "scheme" || match.urlMatchType === "www";
}
});
var BILLBOARD_SIZE = 32;
var BILLBOARD_NEAR_DISTANCE = 2414016;
var BILLBOARD_NEAR_RATIO = 1;
var BILLBOARD_FAR_DISTANCE = 16093e3;
var BILLBOARD_FAR_RATIO = 0.1;
var gpxNamespaces = [null, void 0, "http://www.topografix.com/GPX/1/1"];
var namespaces = {
gpx: gpxNamespaces
};
function readBlobAsText(blob) {
return new Promise((resolve2, reject) => {
const reader = new FileReader();
reader.addEventListener("load", function() {
resolve2(reader.result);
});
reader.addEventListener("error", function() {
reject(reader.error);
});
reader.readAsText(blob);
});
}
function getOrCreateEntity(node, entityCollection) {
let id = queryStringAttribute(node, "id");
id = defined_default(id) ? id : createGuid_default();
const entity = entityCollection.getOrCreateEntity(id);
return entity;
}
function readCoordinateFromNode(node) {
const longitude = queryNumericAttribute(node, "lon");
const latitude = queryNumericAttribute(node, "lat");
const elevation = queryNumericValue(node, "ele", namespaces.gpx);
return Cartesian3_default.fromDegrees(longitude, latitude, elevation);
}
function queryNumericAttribute(node, attributeName) {
if (!defined_default(node)) {
return void 0;
}
const value = node.getAttribute(attributeName);
if (value !== null) {
const result = parseFloat(value);
return !isNaN(result) ? result : void 0;
}
return void 0;
}
function queryStringAttribute(node, attributeName) {
if (!defined_default(node)) {
return void 0;
}
const value = node.getAttribute(attributeName);
return value !== null ? value : void 0;
}
function queryFirstNode(node, tagName, namespace) {
if (!defined_default(node)) {
return void 0;
}
const childNodes = node.childNodes;
const length2 = childNodes.length;
for (let q = 0; q < length2; q++) {
const child = childNodes[q];
if (child.localName === tagName && namespace.indexOf(child.namespaceURI) !== -1) {
return child;
}
}
return void 0;
}
function queryNodes(node, tagName, namespace) {
if (!defined_default(node)) {
return void 0;
}
const result = [];
const childNodes = node.getElementsByTagName(tagName);
const length2 = childNodes.length;
for (let q = 0; q < length2; q++) {
const child = childNodes[q];
if (child.localName === tagName && namespace.indexOf(child.namespaceURI) !== -1) {
result.push(child);
}
}
return result;
}
function queryNumericValue(node, tagName, namespace) {
const resultNode = queryFirstNode(node, tagName, namespace);
if (defined_default(resultNode)) {
const result = parseFloat(resultNode.textContent);
return !isNaN(result) ? result : void 0;
}
return void 0;
}
function queryStringValue(node, tagName, namespace) {
const result = queryFirstNode(node, tagName, namespace);
if (defined_default(result)) {
return result.textContent.trim();
}
return void 0;
}
function createDefaultBillboard(image) {
const billboard = new BillboardGraphics_default();
billboard.width = BILLBOARD_SIZE;
billboard.height = BILLBOARD_SIZE;
billboard.scaleByDistance = new NearFarScalar_default(
BILLBOARD_NEAR_DISTANCE,
BILLBOARD_NEAR_RATIO,
BILLBOARD_FAR_DISTANCE,
BILLBOARD_FAR_RATIO
);
billboard.pixelOffsetScaleByDistance = new NearFarScalar_default(
BILLBOARD_NEAR_DISTANCE,
BILLBOARD_NEAR_RATIO,
BILLBOARD_FAR_DISTANCE,
BILLBOARD_FAR_RATIO
);
billboard.verticalOrigin = new ConstantProperty_default(VerticalOrigin_default.BOTTOM);
billboard.image = image;
return billboard;
}
function createDefaultLabel() {
const label = new LabelGraphics_default();
label.translucencyByDistance = new NearFarScalar_default(3e6, 1, 5e6, 0);
label.pixelOffset = new Cartesian2_default(17, 0);
label.horizontalOrigin = HorizontalOrigin_default.LEFT;
label.font = "16px sans-serif";
label.style = LabelStyle_default.FILL_AND_OUTLINE;
return label;
}
function createDefaultPolyline(color) {
const polyline = new PolylineGraphics_default();
polyline.width = 4;
polyline.material = new PolylineOutlineMaterialProperty_default();
polyline.material.color = defined_default(color) ? color : Color_default.RED;
polyline.material.outlineWidth = 2;
polyline.material.outlineColor = Color_default.BLACK;
return polyline;
}
var descriptiveInfoTypes = {
time: {
text: "Time",
tag: "time"
},
comment: {
text: "Comment",
tag: "cmt"
},
description: {
text: "Description",
tag: "desc"
},
source: {
text: "Source",
tag: "src"
},
number: {
text: "GPS track/route number",
tag: "number"
},
type: {
text: "Type",
tag: "type"
}
};
var scratchDiv;
if (typeof document !== "undefined") {
scratchDiv = document.createElement("div");
}
function processDescription2(node, entity) {
let i;
let text2 = "";
const infoTypeNames = Object.keys(descriptiveInfoTypes);
const length2 = infoTypeNames.length;
for (i = 0; i < length2; i++) {
const infoTypeName = infoTypeNames[i];
const infoType = descriptiveInfoTypes[infoTypeName];
infoType.value = queryStringValue(node, infoType.tag, namespaces.gpx) ?? "";
if (defined_default(infoType.value) && infoType.value !== "") {
text2 = `${text2}${infoType.text}: ${infoType.value}
`;
}
}
if (!defined_default(text2) || text2 === "") {
return;
}
text2 = autolinker.link(text2);
scratchDiv.innerHTML = text2;
const links = scratchDiv.querySelectorAll("a");
for (i = 0; i < links.length; i++) {
links[i].setAttribute("target", "_blank");
}
const background = Color_default.WHITE;
const foreground = Color_default.BLACK;
let tmp2 = '';
tmp2 += `${scratchDiv.innerHTML}`;
scratchDiv.innerHTML = "";
return tmp2;
}
function processWpt(dataSource, geometryNode, entityCollection, options) {
const position = readCoordinateFromNode(geometryNode);
const entity = getOrCreateEntity(geometryNode, entityCollection);
entity.position = position;
const image = defined_default(options.waypointImage) ? options.waypointImage : dataSource._pinBuilder.fromMakiIconId(
"marker",
Color_default.RED,
BILLBOARD_SIZE
);
entity.billboard = createDefaultBillboard(image);
const name = queryStringValue(geometryNode, "name", namespaces.gpx);
entity.name = name;
entity.label = createDefaultLabel();
entity.label.text = name;
entity.description = processDescription2(geometryNode, entity);
if (options.clampToGround) {
entity.billboard.heightReference = HeightReference_default.CLAMP_TO_GROUND;
entity.label.heightReference = HeightReference_default.CLAMP_TO_GROUND;
}
}
function processRte(dataSource, geometryNode, entityCollection, options) {
const entity = getOrCreateEntity(geometryNode, entityCollection);
entity.description = processDescription2(geometryNode, entity);
const routePoints = queryNodes(geometryNode, "rtept", namespaces.gpx);
const coordinateTuples = new Array(routePoints.length);
for (let i = 0; i < routePoints.length; i++) {
processWpt(dataSource, routePoints[i], entityCollection, options);
coordinateTuples[i] = readCoordinateFromNode(routePoints[i]);
}
entity.polyline = createDefaultPolyline(options.routeColor);
if (options.clampToGround) {
entity.polyline.clampToGround = true;
}
entity.polyline.positions = coordinateTuples;
}
function processTrk(dataSource, geometryNode, entityCollection, options) {
const entity = getOrCreateEntity(geometryNode, entityCollection);
entity.description = processDescription2(geometryNode, entity);
const trackSegs = queryNodes(geometryNode, "trkseg", namespaces.gpx);
let positions = [];
let times = [];
let trackSegInfo;
let isTimeDynamic = true;
const property = new SampledPositionProperty_default();
for (let i = 0; i < trackSegs.length; i++) {
trackSegInfo = processTrkSeg(trackSegs[i]);
positions = positions.concat(trackSegInfo.positions);
if (trackSegInfo.times.length > 0) {
times = times.concat(trackSegInfo.times);
property.addSamples(times, positions);
isTimeDynamic = isTimeDynamic && true;
} else {
isTimeDynamic = false;
}
}
if (isTimeDynamic) {
const image = defined_default(options.waypointImage) ? options.waypointImage : dataSource._pinBuilder.fromMakiIconId(
"marker",
Color_default.RED,
BILLBOARD_SIZE
);
entity.billboard = createDefaultBillboard(image);
entity.position = property;
if (options.clampToGround) {
entity.billboard.heightReference = HeightReference_default.CLAMP_TO_GROUND;
}
entity.availability = new TimeIntervalCollection_default();
entity.availability.addInterval(
new TimeInterval_default({
start: times[0],
stop: times[times.length - 1]
})
);
}
entity.polyline = createDefaultPolyline(options.trackColor);
entity.polyline.positions = positions;
if (options.clampToGround) {
entity.polyline.clampToGround = true;
}
}
function processTrkSeg(node) {
const result = {
positions: [],
times: []
};
const trackPoints = queryNodes(node, "trkpt", namespaces.gpx);
let time;
for (let i = 0; i < trackPoints.length; i++) {
const position = readCoordinateFromNode(trackPoints[i]);
result.positions.push(position);
time = queryStringValue(trackPoints[i], "time", namespaces.gpx);
if (defined_default(time)) {
result.times.push(JulianDate_default.fromIso8601(time));
}
}
return result;
}
function processMetadata(node) {
const metadataNode = queryFirstNode(node, "metadata", namespaces.gpx);
if (defined_default(metadataNode)) {
const metadata = {
name: queryStringValue(metadataNode, "name", namespaces.gpx),
desc: queryStringValue(metadataNode, "desc", namespaces.gpx),
author: getPerson(metadataNode),
copyright: getCopyright(metadataNode),
link: getLink(metadataNode),
time: queryStringValue(metadataNode, "time", namespaces.gpx),
keywords: queryStringValue(metadataNode, "keywords", namespaces.gpx),
bounds: getBounds(metadataNode)
};
if (defined_default(metadata.name) || defined_default(metadata.desc) || defined_default(metadata.author) || defined_default(metadata.copyright) || defined_default(metadata.link) || defined_default(metadata.time) || defined_default(metadata.keywords) || defined_default(metadata.bounds)) {
return metadata;
}
}
return void 0;
}
function getPerson(node) {
const personNode = queryFirstNode(node, "author", namespaces.gpx);
if (defined_default(personNode)) {
const person = {
name: queryStringValue(personNode, "name", namespaces.gpx),
email: getEmail(personNode),
link: getLink(personNode)
};
if (defined_default(person.name) || defined_default(person.email) || defined_default(person.link)) {
return person;
}
}
return void 0;
}
function getEmail(node) {
const emailNode = queryFirstNode(node, "email", namespaces.gpx);
if (defined_default(emailNode)) {
const id = queryStringValue(emailNode, "id", namespaces.gpx);
const domain = queryStringValue(emailNode, "domain", namespaces.gpx);
return `${id}@${domain}`;
}
return void 0;
}
function getLink(node) {
const linkNode = queryFirstNode(node, "link", namespaces.gpx);
if (defined_default(linkNode)) {
const link = {
href: queryStringAttribute(linkNode, "href"),
text: queryStringValue(linkNode, "text", namespaces.gpx),
mimeType: queryStringValue(linkNode, "type", namespaces.gpx)
};
if (defined_default(link.href) || defined_default(link.text) || defined_default(link.mimeType)) {
return link;
}
}
return void 0;
}
function getCopyright(node) {
const copyrightNode = queryFirstNode(node, "copyright", namespaces.gpx);
if (defined_default(copyrightNode)) {
const copyright = {
author: queryStringAttribute(copyrightNode, "author"),
year: queryStringValue(copyrightNode, "year", namespaces.gpx),
license: queryStringValue(copyrightNode, "license", namespaces.gpx)
};
if (defined_default(copyright.author) || defined_default(copyright.year) || defined_default(copyright.license)) {
return copyright;
}
}
return void 0;
}
function getBounds(node) {
const boundsNode = queryFirstNode(node, "bounds", namespaces.gpx);
if (defined_default(boundsNode)) {
const bounds = {
minLat: queryNumericValue(boundsNode, "minlat", namespaces.gpx),
maxLat: queryNumericValue(boundsNode, "maxlat", namespaces.gpx),
minLon: queryNumericValue(boundsNode, "minlon", namespaces.gpx),
maxLon: queryNumericValue(boundsNode, "maxlon", namespaces.gpx)
};
if (defined_default(bounds.minLat) || defined_default(bounds.maxLat) || defined_default(bounds.minLon) || defined_default(bounds.maxLon)) {
return bounds;
}
}
return void 0;
}
var complexTypes = {
wpt: processWpt,
rte: processRte,
trk: processTrk
};
function processGpx(dataSource, node, entityCollection, options) {
const complexTypeNames = Object.keys(complexTypes);
const complexTypeNamesLength = complexTypeNames.length;
for (let i = 0; i < complexTypeNamesLength; i++) {
const typeName = complexTypeNames[i];
const processComplexTypeNode = complexTypes[typeName];
const childNodes = node.childNodes;
const length2 = childNodes.length;
for (let q = 0; q < length2; q++) {
const child = childNodes[q];
if (child.localName === typeName && namespaces.gpx.indexOf(child.namespaceURI) !== -1) {
processComplexTypeNode(dataSource, child, entityCollection, options);
}
}
}
}
function loadGpx(dataSource, gpx, options) {
const entityCollection = dataSource._entityCollection;
entityCollection.removeAll();
const element = gpx.documentElement;
const version2 = queryStringAttribute(element, "version");
const creator = queryStringAttribute(element, "creator");
let name;
const metadata = processMetadata(element);
if (defined_default(metadata)) {
name = metadata.name;
}
if (element.localName === "gpx") {
processGpx(dataSource, element, entityCollection, options);
} else {
console.log(`GPX - Unsupported node: ${element.localName}`);
}
let clock;
const availability = entityCollection.computeAvailability();
let start = availability.start;
let stop2 = availability.stop;
const isMinStart = JulianDate_default.equals(start, Iso8601_default.MINIMUM_VALUE);
const isMaxStop = JulianDate_default.equals(stop2, Iso8601_default.MAXIMUM_VALUE);
if (!isMinStart || !isMaxStop) {
let date;
if (isMinStart) {
date = /* @__PURE__ */ new Date();
date.setHours(0, 0, 0, 0);
start = JulianDate_default.fromDate(date);
}
if (isMaxStop) {
date = /* @__PURE__ */ new Date();
date.setHours(24, 0, 0, 0);
stop2 = JulianDate_default.fromDate(date);
}
clock = new DataSourceClock_default();
clock.startTime = start;
clock.stopTime = stop2;
clock.currentTime = JulianDate_default.clone(start);
clock.clockRange = ClockRange_default.LOOP_STOP;
clock.clockStep = ClockStep_default.SYSTEM_CLOCK_MULTIPLIER;
clock.multiplier = Math.round(
Math.min(
Math.max(JulianDate_default.secondsDifference(stop2, start) / 60, 1),
31556900
)
);
}
let changed = false;
if (dataSource._name !== name) {
dataSource._name = name;
changed = true;
}
if (dataSource._creator !== creator) {
dataSource._creator = creator;
changed = true;
}
if (metadataChanged(dataSource._metadata, metadata)) {
dataSource._metadata = metadata;
changed = true;
}
if (dataSource._version !== version2) {
dataSource._version = version2;
changed = true;
}
if (clock !== dataSource._clock) {
changed = true;
dataSource._clock = clock;
}
if (changed) {
dataSource._changed.raiseEvent(dataSource);
}
DataSource_default.setLoading(dataSource, false);
return dataSource;
}
function metadataChanged(old, current) {
if (!defined_default(old) && !defined_default(current)) {
return false;
} else if (defined_default(old) && defined_default(current)) {
if (old.name !== current.name || old.dec !== current.desc || old.src !== current.src || old.author !== current.author || old.copyright !== current.copyright || old.link !== current.link || old.time !== current.time || old.bounds !== current.bounds) {
return true;
}
return false;
}
return true;
}
function load3(dataSource, entityCollection, data, options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
let promise = data;
if (typeof data === "string" || data instanceof Resource_default) {
data = Resource_default.createIfNeeded(data);
promise = data.fetchBlob();
const resourceCredits = dataSource._resourceCredits;
const credits = data.credits;
if (defined_default(credits)) {
const length2 = credits.length;
for (let i = 0; i < length2; i++) {
resourceCredits.push(credits[i]);
}
}
}
return Promise.resolve(promise).then(function(dataToLoad) {
if (dataToLoad instanceof Blob) {
return readBlobAsText(dataToLoad).then(function(text2) {
let gpx;
let error;
try {
gpx = parser.parseFromString(text2, "application/xml");
} catch (e) {
error = e.toString();
}
if (defined_default(error) || gpx.body || gpx.documentElement.tagName === "parsererror") {
let msg = defined_default(error) ? error : gpx.documentElement.firstChild.nodeValue;
if (!msg) {
msg = gpx.body.innerText;
}
throw new RuntimeError_default(msg);
}
return loadGpx(dataSource, gpx, options);
});
}
return loadGpx(dataSource, dataToLoad, options);
}).catch(function(error) {
dataSource._error.raiseEvent(dataSource, error);
console.log(error);
return Promise.reject(error);
});
}
function GpxDataSource() {
this._changed = new Event_default();
this._error = new Event_default();
this._loading = new Event_default();
this._clock = void 0;
this._entityCollection = new EntityCollection_default(this);
this._entityCluster = new EntityCluster_default();
this._name = void 0;
this._version = void 0;
this._creator = void 0;
this._metadata = void 0;
this._isLoading = false;
this._pinBuilder = new PinBuilder_default();
}
GpxDataSource.load = function(data, options) {
return new GpxDataSource().load(data, options);
};
Object.defineProperties(GpxDataSource.prototype, {
/**
* Gets a human-readable name for this instance.
* This will be automatically be set to the GPX document name on load.
* @memberof GpxDataSource.prototype
* @type {string}
*/
name: {
get: function() {
return this._name;
}
},
/**
* Gets the version of the GPX Schema in use.
* @memberof GpxDataSource.prototype
* @type {string}
*/
version: {
get: function() {
return this._version;
}
},
/**
* Gets the creator of the GPX document.
* @memberof GpxDataSource.prototype
* @type {string}
*/
creator: {
get: function() {
return this._creator;
}
},
/**
* Gets an object containing metadata about the GPX file.
* @memberof GpxDataSource.prototype
* @type {object}
*/
metadata: {
get: function() {
return this._metadata;
}
},
/**
* Gets the clock settings defined by the loaded GPX. This represents the total
* availability interval for all time-dynamic data. If the GPX does not contain
* time-dynamic data, this value is undefined.
* @memberof GpxDataSource.prototype
* @type {DataSourceClock}
*/
clock: {
get: function() {
return this._clock;
}
},
/**
* Gets the collection of {@link Entity} instances.
* @memberof GpxDataSource.prototype
* @type {EntityCollection}
*/
entities: {
get: function() {
return this._entityCollection;
}
},
/**
* Gets a value indicating if the data source is currently loading data.
* @memberof GpxDataSource.prototype
* @type {boolean}
*/
isLoading: {
get: function() {
return this._isLoading;
}
},
/**
* Gets an event that will be raised when the underlying data changes.
* @memberof GpxDataSource.prototype
* @type {Event}
*/
changedEvent: {
get: function() {
return this._changed;
}
},
/**
* Gets an event that will be raised if an error is encountered during processing.
* @memberof GpxDataSource.prototype
* @type {Event}
*/
errorEvent: {
get: function() {
return this._error;
}
},
/**
* Gets an event that will be raised when the data source either starts or stops loading.
* @memberof GpxDataSource.prototype
* @type {Event}
*/
loadingEvent: {
get: function() {
return this._loading;
}
},
/**
* Gets whether or not this data source should be displayed.
* @memberof GpxDataSource.prototype
* @type {boolean}
*/
show: {
get: function() {
return this._entityCollection.show;
},
set: function(value) {
this._entityCollection.show = value;
}
},
/**
* Gets or sets the clustering options for this data source. This object can be shared between multiple data sources.
*
* @memberof GpxDataSource.prototype
* @type {EntityCluster}
*/
clustering: {
get: function() {
return this._entityCluster;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value must be defined.");
}
this._entityCluster = value;
}
}
});
GpxDataSource.prototype.update = function(time) {
return true;
};
GpxDataSource.prototype.load = function(data, options) {
if (!defined_default(data)) {
throw new DeveloperError_default("data is required.");
}
options = options ?? Frozen_default.EMPTY_OBJECT;
DataSource_default.setLoading(this, true);
const oldName = this._name;
const that = this;
return load3(this, this._entityCollection, data, options).then(function() {
let clock;
const availability = that._entityCollection.computeAvailability();
let start = availability.start;
let stop2 = availability.stop;
const isMinStart = JulianDate_default.equals(start, Iso8601_default.MINIMUM_VALUE);
const isMaxStop = JulianDate_default.equals(stop2, Iso8601_default.MAXIMUM_VALUE);
if (!isMinStart || !isMaxStop) {
let date;
if (isMinStart) {
date = /* @__PURE__ */ new Date();
date.setHours(0, 0, 0, 0);
start = JulianDate_default.fromDate(date);
}
if (isMaxStop) {
date = /* @__PURE__ */ new Date();
date.setHours(24, 0, 0, 0);
stop2 = JulianDate_default.fromDate(date);
}
clock = new DataSourceClock_default();
clock.startTime = start;
clock.stopTime = stop2;
clock.currentTime = JulianDate_default.clone(start);
clock.clockRange = ClockRange_default.LOOP_STOP;
clock.clockStep = ClockStep_default.SYSTEM_CLOCK_MULTIPLIER;
clock.multiplier = Math.round(
Math.min(
Math.max(JulianDate_default.secondsDifference(stop2, start) / 60, 1),
31556900
)
);
}
let changed = false;
if (clock !== that._clock) {
that._clock = clock;
changed = true;
}
if (oldName !== that._name) {
changed = true;
}
if (changed) {
that._changed.raiseEvent(that);
}
DataSource_default.setLoading(that, false);
return that;
}).catch(function(error) {
DataSource_default.setLoading(that, false);
that._error.raiseEvent(that, error);
console.log(error);
return Promise.reject(error);
});
};
var GpxDataSource_default = GpxDataSource;
// packages/engine/Source/DataSources/KmlCamera.js
var import_InlineWorkers965 = __toESM(require_InlineWorkers(), 1);
function KmlCamera(position, headingPitchRoll) {
this.position = position;
this.headingPitchRoll = headingPitchRoll;
}
var KmlCamera_default = KmlCamera;
// packages/engine/Source/DataSources/KmlDataSource.js
var import_InlineWorkers998 = __toESM(require_InlineWorkers(), 1);
var import_urijs11 = __toESM(require_URI(), 1);
// node_modules/@zip.js/zip.js/lib/zip-no-worker.js
var import_InlineWorkers990 = __toESM(require_InlineWorkers(), 1);
// node_modules/@zip.js/zip.js/lib/core/streams/codecs/deflate.js
var import_InlineWorkers966 = __toESM(require_InlineWorkers(), 1);
var MAX_BITS = 15;
var D_CODES = 30;
var BL_CODES = 19;
var LENGTH_CODES = 29;
var LITERALS = 256;
var L_CODES = LITERALS + 1 + LENGTH_CODES;
var HEAP_SIZE = 2 * L_CODES + 1;
var END_BLOCK = 256;
var MAX_BL_BITS = 7;
var REP_3_6 = 16;
var REPZ_3_10 = 17;
var REPZ_11_138 = 18;
var Buf_size = 8 * 2;
var Z_DEFAULT_COMPRESSION = -1;
var Z_FILTERED = 1;
var Z_HUFFMAN_ONLY = 2;
var Z_DEFAULT_STRATEGY = 0;
var Z_NO_FLUSH = 0;
var Z_PARTIAL_FLUSH = 1;
var Z_FULL_FLUSH = 3;
var Z_FINISH = 4;
var Z_OK = 0;
var Z_STREAM_END = 1;
var Z_NEED_DICT = 2;
var Z_STREAM_ERROR = -2;
var Z_DATA_ERROR = -3;
var Z_BUF_ERROR = -5;
function extractArray(array) {
return flatArray(array.map(([length2, value]) => new Array(length2).fill(value, 0, length2)));
}
function flatArray(array) {
return array.reduce((a3, b) => a3.concat(Array.isArray(b) ? flatArray(b) : b), []);
}
var _dist_code = [0, 1, 2, 3].concat(...extractArray([
[2, 4],
[2, 5],
[4, 6],
[4, 7],
[8, 8],
[8, 9],
[16, 10],
[16, 11],
[32, 12],
[32, 13],
[64, 14],
[64, 15],
[2, 0],
[1, 16],
[1, 17],
[2, 18],
[2, 19],
[4, 20],
[4, 21],
[8, 22],
[8, 23],
[16, 24],
[16, 25],
[32, 26],
[32, 27],
[64, 28],
[64, 29]
]));
function Tree() {
const that = this;
function gen_bitlen(s) {
const tree = that.dyn_tree;
const stree = that.stat_desc.static_tree;
const extra = that.stat_desc.extra_bits;
const base = that.stat_desc.extra_base;
const max_length = that.stat_desc.max_length;
let h;
let n, m;
let bits;
let xbits;
let f;
let overflow = 0;
for (bits = 0; bits <= MAX_BITS; bits++)
s.bl_count[bits] = 0;
tree[s.heap[s.heap_max] * 2 + 1] = 0;
for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
n = s.heap[h];
bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
if (bits > max_length) {
bits = max_length;
overflow++;
}
tree[n * 2 + 1] = bits;
if (n > that.max_code)
continue;
s.bl_count[bits]++;
xbits = 0;
if (n >= base)
xbits = extra[n - base];
f = tree[n * 2];
s.opt_len += f * (bits + xbits);
if (stree)
s.static_len += f * (stree[n * 2 + 1] + xbits);
}
if (overflow === 0)
return;
do {
bits = max_length - 1;
while (s.bl_count[bits] === 0)
bits--;
s.bl_count[bits]--;
s.bl_count[bits + 1] += 2;
s.bl_count[max_length]--;
overflow -= 2;
} while (overflow > 0);
for (bits = max_length; bits !== 0; bits--) {
n = s.bl_count[bits];
while (n !== 0) {
m = s.heap[--h];
if (m > that.max_code)
continue;
if (tree[m * 2 + 1] != bits) {
s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2];
tree[m * 2 + 1] = bits;
}
n--;
}
}
}
function bi_reverse(code, len) {
let res = 0;
do {
res |= code & 1;
code >>>= 1;
res <<= 1;
} while (--len > 0);
return res >>> 1;
}
function gen_codes(tree, max_code, bl_count) {
const next_code = [];
let code = 0;
let bits;
let n;
let len;
for (bits = 1; bits <= MAX_BITS; bits++) {
next_code[bits] = code = code + bl_count[bits - 1] << 1;
}
for (n = 0; n <= max_code; n++) {
len = tree[n * 2 + 1];
if (len === 0)
continue;
tree[n * 2] = bi_reverse(next_code[len]++, len);
}
}
that.build_tree = function(s) {
const tree = that.dyn_tree;
const stree = that.stat_desc.static_tree;
const elems = that.stat_desc.elems;
let n, m;
let max_code = -1;
let node;
s.heap_len = 0;
s.heap_max = HEAP_SIZE;
for (n = 0; n < elems; n++) {
if (tree[n * 2] !== 0) {
s.heap[++s.heap_len] = max_code = n;
s.depth[n] = 0;
} else {
tree[n * 2 + 1] = 0;
}
}
while (s.heap_len < 2) {
node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0;
tree[node * 2] = 1;
s.depth[node] = 0;
s.opt_len--;
if (stree)
s.static_len -= stree[node * 2 + 1];
}
that.max_code = max_code;
for (n = Math.floor(s.heap_len / 2); n >= 1; n--)
s.pqdownheap(tree, n);
node = elems;
do {
n = s.heap[1];
s.heap[1] = s.heap[s.heap_len--];
s.pqdownheap(tree, 1);
m = s.heap[1];
s.heap[--s.heap_max] = n;
s.heap[--s.heap_max] = m;
tree[node * 2] = tree[n * 2] + tree[m * 2];
s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1;
tree[n * 2 + 1] = tree[m * 2 + 1] = node;
s.heap[1] = node++;
s.pqdownheap(tree, 1);
} while (s.heap_len >= 2);
s.heap[--s.heap_max] = s.heap[1];
gen_bitlen(s);
gen_codes(tree, that.max_code, s.bl_count);
};
}
Tree._length_code = [0, 1, 2, 3, 4, 5, 6, 7].concat(...extractArray([
[2, 8],
[2, 9],
[2, 10],
[2, 11],
[4, 12],
[4, 13],
[4, 14],
[4, 15],
[8, 16],
[8, 17],
[8, 18],
[8, 19],
[16, 20],
[16, 21],
[16, 22],
[16, 23],
[32, 24],
[32, 25],
[32, 26],
[31, 27],
[1, 28]
]));
Tree.base_length = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0];
Tree.base_dist = [
0,
1,
2,
3,
4,
6,
8,
12,
16,
24,
32,
48,
64,
96,
128,
192,
256,
384,
512,
768,
1024,
1536,
2048,
3072,
4096,
6144,
8192,
12288,
16384,
24576
];
Tree.d_code = function(dist) {
return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
};
Tree.extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0];
Tree.extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13];
Tree.extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7];
Tree.bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) {
const that = this;
that.static_tree = static_tree;
that.extra_bits = extra_bits;
that.extra_base = extra_base;
that.elems = elems;
that.max_length = max_length;
}
var static_ltree2_first_part = [
12,
140,
76,
204,
44,
172,
108,
236,
28,
156,
92,
220,
60,
188,
124,
252,
2,
130,
66,
194,
34,
162,
98,
226,
18,
146,
82,
210,
50,
178,
114,
242,
10,
138,
74,
202,
42,
170,
106,
234,
26,
154,
90,
218,
58,
186,
122,
250,
6,
134,
70,
198,
38,
166,
102,
230,
22,
150,
86,
214,
54,
182,
118,
246,
14,
142,
78,
206,
46,
174,
110,
238,
30,
158,
94,
222,
62,
190,
126,
254,
1,
129,
65,
193,
33,
161,
97,
225,
17,
145,
81,
209,
49,
177,
113,
241,
9,
137,
73,
201,
41,
169,
105,
233,
25,
153,
89,
217,
57,
185,
121,
249,
5,
133,
69,
197,
37,
165,
101,
229,
21,
149,
85,
213,
53,
181,
117,
245,
13,
141,
77,
205,
45,
173,
109,
237,
29,
157,
93,
221,
61,
189,
125,
253,
19,
275,
147,
403,
83,
339,
211,
467,
51,
307,
179,
435,
115,
371,
243,
499,
11,
267,
139,
395,
75,
331,
203,
459,
43,
299,
171,
427,
107,
363,
235,
491,
27,
283,
155,
411,
91,
347,
219,
475,
59,
315,
187,
443,
123,
379,
251,
507,
7,
263,
135,
391,
71,
327,
199,
455,
39,
295,
167,
423,
103,
359,
231,
487,
23,
279,
151,
407,
87,
343,
215,
471,
55,
311,
183,
439,
119,
375,
247,
503,
15,
271,
143,
399,
79,
335,
207,
463,
47,
303,
175,
431,
111,
367,
239,
495,
31,
287,
159,
415,
95,
351,
223,
479,
63,
319,
191,
447,
127,
383,
255,
511,
0,
64,
32,
96,
16,
80,
48,
112,
8,
72,
40,
104,
24,
88,
56,
120,
4,
68,
36,
100,
20,
84,
52,
116,
3,
131,
67,
195,
35,
163,
99,
227
];
var static_ltree2_second_part = extractArray([[144, 8], [112, 9], [24, 7], [8, 8]]);
StaticTree.static_ltree = flatArray(static_ltree2_first_part.map((value, index) => [value, static_ltree2_second_part[index]]));
var static_dtree_first_part = [0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23];
var static_dtree_second_part = extractArray([[30, 5]]);
StaticTree.static_dtree = flatArray(static_dtree_first_part.map((value, index) => [value, static_dtree_second_part[index]]));
StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS);
StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
var MAX_MEM_LEVEL = 9;
var DEF_MEM_LEVEL = 8;
function Config(good_length, max_lazy, nice_length, max_chain, func) {
const that = this;
that.good_length = good_length;
that.max_lazy = max_lazy;
that.nice_length = nice_length;
that.max_chain = max_chain;
that.func = func;
}
var STORED = 0;
var FAST = 1;
var SLOW = 2;
var config_table = [
new Config(0, 0, 0, 0, STORED),
new Config(4, 4, 8, 4, FAST),
new Config(4, 5, 16, 8, FAST),
new Config(4, 6, 32, 32, FAST),
new Config(4, 4, 16, 16, SLOW),
new Config(8, 16, 32, 32, SLOW),
new Config(8, 16, 128, 128, SLOW),
new Config(8, 32, 128, 256, SLOW),
new Config(32, 128, 258, 1024, SLOW),
new Config(32, 258, 258, 4096, SLOW)
];
var z_errmsg = [
"need dictionary",
// Z_NEED_DICT
// 2
"stream end",
// Z_STREAM_END 1
"",
// Z_OK 0
"",
// Z_ERRNO (-1)
"stream error",
// Z_STREAM_ERROR (-2)
"data error",
// Z_DATA_ERROR (-3)
"",
// Z_MEM_ERROR (-4)
"buffer error",
// Z_BUF_ERROR (-5)
"",
// Z_VERSION_ERROR (-6)
""
];
var NeedMore = 0;
var BlockDone = 1;
var FinishStarted = 2;
var FinishDone = 3;
var PRESET_DICT = 32;
var INIT_STATE = 42;
var BUSY_STATE = 113;
var FINISH_STATE = 666;
var Z_DEFLATED = 8;
var STORED_BLOCK = 0;
var STATIC_TREES = 1;
var DYN_TREES = 2;
var MIN_MATCH = 3;
var MAX_MATCH = 258;
var MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
function smaller(tree, n, m, depth) {
const tn2 = tree[n * 2];
const tm2 = tree[m * 2];
return tn2 < tm2 || tn2 == tm2 && depth[n] <= depth[m];
}
function Deflate() {
const that = this;
let strm;
let status;
let pending_buf_size;
let last_flush;
let w_size;
let w_bits;
let w_mask;
let win;
let window_size;
let prev;
let head;
let ins_h;
let hash_size;
let hash_bits;
let hash_mask;
let hash_shift;
let block_start;
let match_length;
let prev_match;
let match_available;
let strstart;
let match_start;
let lookahead;
let prev_length;
let max_chain_length;
let max_lazy_match;
let level;
let strategy;
let good_match;
let nice_match;
let dyn_ltree;
let dyn_dtree;
let bl_tree;
const l_desc = new Tree();
const d_desc = new Tree();
const bl_desc = new Tree();
that.depth = [];
let lit_bufsize;
let last_lit;
let matches;
let last_eob_len;
let bi_buf;
let bi_valid;
that.bl_count = [];
that.heap = [];
dyn_ltree = [];
dyn_dtree = [];
bl_tree = [];
function lm_init() {
window_size = 2 * w_size;
head[hash_size - 1] = 0;
for (let i = 0; i < hash_size - 1; i++) {
head[i] = 0;
}
max_lazy_match = config_table[level].max_lazy;
good_match = config_table[level].good_length;
nice_match = config_table[level].nice_length;
max_chain_length = config_table[level].max_chain;
strstart = 0;
block_start = 0;
lookahead = 0;
match_length = prev_length = MIN_MATCH - 1;
match_available = 0;
ins_h = 0;
}
function init_block() {
let i;
for (i = 0; i < L_CODES; i++)
dyn_ltree[i * 2] = 0;
for (i = 0; i < D_CODES; i++)
dyn_dtree[i * 2] = 0;
for (i = 0; i < BL_CODES; i++)
bl_tree[i * 2] = 0;
dyn_ltree[END_BLOCK * 2] = 1;
that.opt_len = that.static_len = 0;
last_lit = matches = 0;
}
function tr_init() {
l_desc.dyn_tree = dyn_ltree;
l_desc.stat_desc = StaticTree.static_l_desc;
d_desc.dyn_tree = dyn_dtree;
d_desc.stat_desc = StaticTree.static_d_desc;
bl_desc.dyn_tree = bl_tree;
bl_desc.stat_desc = StaticTree.static_bl_desc;
bi_buf = 0;
bi_valid = 0;
last_eob_len = 8;
init_block();
}
that.pqdownheap = function(tree, k) {
const heap = that.heap;
const v3 = heap[k];
let j = k << 1;
while (j <= that.heap_len) {
if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) {
j++;
}
if (smaller(tree, v3, heap[j], that.depth))
break;
heap[k] = heap[j];
k = j;
j <<= 1;
}
heap[k] = v3;
};
function scan_tree(tree, max_code) {
let prevlen = -1;
let curlen;
let nextlen = tree[0 * 2 + 1];
let count = 0;
let max_count = 7;
let min_count = 4;
if (nextlen === 0) {
max_count = 138;
min_count = 3;
}
tree[(max_code + 1) * 2 + 1] = 65535;
for (let n = 0; n <= max_code; n++) {
curlen = nextlen;
nextlen = tree[(n + 1) * 2 + 1];
if (++count < max_count && curlen == nextlen) {
continue;
} else if (count < min_count) {
bl_tree[curlen * 2] += count;
} else if (curlen !== 0) {
if (curlen != prevlen)
bl_tree[curlen * 2]++;
bl_tree[REP_3_6 * 2]++;
} else if (count <= 10) {
bl_tree[REPZ_3_10 * 2]++;
} else {
bl_tree[REPZ_11_138 * 2]++;
}
count = 0;
prevlen = curlen;
if (nextlen === 0) {
max_count = 138;
min_count = 3;
} else if (curlen == nextlen) {
max_count = 6;
min_count = 3;
} else {
max_count = 7;
min_count = 4;
}
}
}
function build_bl_tree() {
let max_blindex;
scan_tree(dyn_ltree, l_desc.max_code);
scan_tree(dyn_dtree, d_desc.max_code);
bl_desc.build_tree(that);
for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0)
break;
}
that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
return max_blindex;
}
function put_byte(p) {
that.pending_buf[that.pending++] = p;
}
function put_short(w) {
put_byte(w & 255);
put_byte(w >>> 8 & 255);
}
function putShortMSB(b) {
put_byte(b >> 8 & 255);
put_byte(b & 255 & 255);
}
function send_bits(value, length2) {
let val;
const len = length2;
if (bi_valid > Buf_size - len) {
val = value;
bi_buf |= val << bi_valid & 65535;
put_short(bi_buf);
bi_buf = val >>> Buf_size - bi_valid;
bi_valid += len - Buf_size;
} else {
bi_buf |= value << bi_valid & 65535;
bi_valid += len;
}
}
function send_code(c, tree) {
const c22 = c * 2;
send_bits(tree[c22] & 65535, tree[c22 + 1] & 65535);
}
function send_tree(tree, max_code) {
let n;
let prevlen = -1;
let curlen;
let nextlen = tree[0 * 2 + 1];
let count = 0;
let max_count = 7;
let min_count = 4;
if (nextlen === 0) {
max_count = 138;
min_count = 3;
}
for (n = 0; n <= max_code; n++) {
curlen = nextlen;
nextlen = tree[(n + 1) * 2 + 1];
if (++count < max_count && curlen == nextlen) {
continue;
} else if (count < min_count) {
do {
send_code(curlen, bl_tree);
} while (--count !== 0);
} else if (curlen !== 0) {
if (curlen != prevlen) {
send_code(curlen, bl_tree);
count--;
}
send_code(REP_3_6, bl_tree);
send_bits(count - 3, 2);
} else if (count <= 10) {
send_code(REPZ_3_10, bl_tree);
send_bits(count - 3, 3);
} else {
send_code(REPZ_11_138, bl_tree);
send_bits(count - 11, 7);
}
count = 0;
prevlen = curlen;
if (nextlen === 0) {
max_count = 138;
min_count = 3;
} else if (curlen == nextlen) {
max_count = 6;
min_count = 3;
} else {
max_count = 7;
min_count = 4;
}
}
}
function send_all_trees(lcodes, dcodes, blcodes) {
let rank;
send_bits(lcodes - 257, 5);
send_bits(dcodes - 1, 5);
send_bits(blcodes - 4, 4);
for (rank = 0; rank < blcodes; rank++) {
send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);
}
send_tree(dyn_ltree, lcodes - 1);
send_tree(dyn_dtree, dcodes - 1);
}
function bi_flush() {
if (bi_valid == 16) {
put_short(bi_buf);
bi_buf = 0;
bi_valid = 0;
} else if (bi_valid >= 8) {
put_byte(bi_buf & 255);
bi_buf >>>= 8;
bi_valid -= 8;
}
}
function _tr_align() {
send_bits(STATIC_TREES << 1, 3);
send_code(END_BLOCK, StaticTree.static_ltree);
bi_flush();
if (1 + last_eob_len + 10 - bi_valid < 9) {
send_bits(STATIC_TREES << 1, 3);
send_code(END_BLOCK, StaticTree.static_ltree);
bi_flush();
}
last_eob_len = 7;
}
function _tr_tally(dist, lc) {
let out_length, in_length, dcode;
that.dist_buf[last_lit] = dist;
that.lc_buf[last_lit] = lc & 255;
last_lit++;
if (dist === 0) {
dyn_ltree[lc * 2]++;
} else {
matches++;
dist--;
dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;
dyn_dtree[Tree.d_code(dist) * 2]++;
}
if ((last_lit & 8191) === 0 && level > 2) {
out_length = last_lit * 8;
in_length = strstart - block_start;
for (dcode = 0; dcode < D_CODES; dcode++) {
out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]);
}
out_length >>>= 3;
if (matches < Math.floor(last_lit / 2) && out_length < Math.floor(in_length / 2))
return true;
}
return last_lit == lit_bufsize - 1;
}
function compress_block(ltree, dtree) {
let dist;
let lc;
let lx = 0;
let code;
let extra;
if (last_lit !== 0) {
do {
dist = that.dist_buf[lx];
lc = that.lc_buf[lx];
lx++;
if (dist === 0) {
send_code(lc, ltree);
} else {
code = Tree._length_code[lc];
send_code(code + LITERALS + 1, ltree);
extra = Tree.extra_lbits[code];
if (extra !== 0) {
lc -= Tree.base_length[code];
send_bits(lc, extra);
}
dist--;
code = Tree.d_code(dist);
send_code(code, dtree);
extra = Tree.extra_dbits[code];
if (extra !== 0) {
dist -= Tree.base_dist[code];
send_bits(dist, extra);
}
}
} while (lx < last_lit);
}
send_code(END_BLOCK, ltree);
last_eob_len = ltree[END_BLOCK * 2 + 1];
}
function bi_windup() {
if (bi_valid > 8) {
put_short(bi_buf);
} else if (bi_valid > 0) {
put_byte(bi_buf & 255);
}
bi_buf = 0;
bi_valid = 0;
}
function copy_block(buf, len, header) {
bi_windup();
last_eob_len = 8;
if (header) {
put_short(len);
put_short(~len);
}
that.pending_buf.set(win.subarray(buf, buf + len), that.pending);
that.pending += len;
}
function _tr_stored_block(buf, stored_len, eof) {
send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3);
copy_block(buf, stored_len, true);
}
function _tr_flush_block(buf, stored_len, eof) {
let opt_lenb, static_lenb;
let max_blindex = 0;
if (level > 0) {
l_desc.build_tree(that);
d_desc.build_tree(that);
max_blindex = build_bl_tree();
opt_lenb = that.opt_len + 3 + 7 >>> 3;
static_lenb = that.static_len + 3 + 7 >>> 3;
if (static_lenb <= opt_lenb)
opt_lenb = static_lenb;
} else {
opt_lenb = static_lenb = stored_len + 5;
}
if (stored_len + 4 <= opt_lenb && buf != -1) {
_tr_stored_block(buf, stored_len, eof);
} else if (static_lenb == opt_lenb) {
send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
} else {
send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);
compress_block(dyn_ltree, dyn_dtree);
}
init_block();
if (eof) {
bi_windup();
}
}
function flush_block_only(eof) {
_tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof);
block_start = strstart;
strm.flush_pending();
}
function fill_window() {
let n, m;
let p;
let more;
do {
more = window_size - lookahead - strstart;
if (more === 0 && strstart === 0 && lookahead === 0) {
more = w_size;
} else if (more == -1) {
more--;
} else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {
win.set(win.subarray(w_size, w_size + w_size), 0);
match_start -= w_size;
strstart -= w_size;
block_start -= w_size;
n = hash_size;
p = n;
do {
m = head[--p] & 65535;
head[p] = m >= w_size ? m - w_size : 0;
} while (--n !== 0);
n = w_size;
p = n;
do {
m = prev[--p] & 65535;
prev[p] = m >= w_size ? m - w_size : 0;
} while (--n !== 0);
more += w_size;
}
if (strm.avail_in === 0)
return;
n = strm.read_buf(win, strstart + lookahead, more);
lookahead += n;
if (lookahead >= MIN_MATCH) {
ins_h = win[strstart] & 255;
ins_h = (ins_h << hash_shift ^ win[strstart + 1] & 255) & hash_mask;
}
} while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0);
}
function deflate_stored(flush) {
let max_block_size = 65535;
let max_start;
if (max_block_size > pending_buf_size - 5) {
max_block_size = pending_buf_size - 5;
}
while (true) {
if (lookahead <= 1) {
fill_window();
if (lookahead === 0 && flush == Z_NO_FLUSH)
return NeedMore;
if (lookahead === 0)
break;
}
strstart += lookahead;
lookahead = 0;
max_start = block_start + max_block_size;
if (strstart === 0 || strstart >= max_start) {
lookahead = strstart - max_start;
strstart = max_start;
flush_block_only(false);
if (strm.avail_out === 0)
return NeedMore;
}
if (strstart - block_start >= w_size - MIN_LOOKAHEAD) {
flush_block_only(false);
if (strm.avail_out === 0)
return NeedMore;
}
}
flush_block_only(flush == Z_FINISH);
if (strm.avail_out === 0)
return flush == Z_FINISH ? FinishStarted : NeedMore;
return flush == Z_FINISH ? FinishDone : BlockDone;
}
function longest_match(cur_match) {
let chain_length = max_chain_length;
let scan = strstart;
let match;
let len;
let best_len = prev_length;
const limit = strstart > w_size - MIN_LOOKAHEAD ? strstart - (w_size - MIN_LOOKAHEAD) : 0;
let _nice_match = nice_match;
const wmask = w_mask;
const strend = strstart + MAX_MATCH;
let scan_end1 = win[scan + best_len - 1];
let scan_end = win[scan + best_len];
if (prev_length >= good_match) {
chain_length >>= 2;
}
if (_nice_match > lookahead)
_nice_match = lookahead;
do {
match = cur_match;
if (win[match + best_len] != scan_end || win[match + best_len - 1] != scan_end1 || win[match] != win[scan] || win[++match] != win[scan + 1])
continue;
scan += 2;
match++;
do {
} while (win[++scan] == win[++match] && win[++scan] == win[++match] && win[++scan] == win[++match] && win[++scan] == win[++match] && win[++scan] == win[++match] && win[++scan] == win[++match] && win[++scan] == win[++match] && win[++scan] == win[++match] && scan < strend);
len = MAX_MATCH - (strend - scan);
scan = strend - MAX_MATCH;
if (len > best_len) {
match_start = cur_match;
best_len = len;
if (len >= _nice_match)
break;
scan_end1 = win[scan + best_len - 1];
scan_end = win[scan + best_len];
}
} while ((cur_match = prev[cur_match & wmask] & 65535) > limit && --chain_length !== 0);
if (best_len <= lookahead)
return best_len;
return lookahead;
}
function deflate_fast(flush) {
let hash_head = 0;
let bflush;
while (true) {
if (lookahead < MIN_LOOKAHEAD) {
fill_window();
if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
return NeedMore;
}
if (lookahead === 0)
break;
}
if (lookahead >= MIN_MATCH) {
ins_h = (ins_h << hash_shift ^ win[strstart + (MIN_MATCH - 1)] & 255) & hash_mask;
hash_head = head[ins_h] & 65535;
prev[strstart & w_mask] = head[ins_h];
head[ins_h] = strstart;
}
if (hash_head !== 0 && (strstart - hash_head & 65535) <= w_size - MIN_LOOKAHEAD) {
if (strategy != Z_HUFFMAN_ONLY) {
match_length = longest_match(hash_head);
}
}
if (match_length >= MIN_MATCH) {
bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);
lookahead -= match_length;
if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) {
match_length--;
do {
strstart++;
ins_h = (ins_h << hash_shift ^ win[strstart + (MIN_MATCH - 1)] & 255) & hash_mask;
hash_head = head[ins_h] & 65535;
prev[strstart & w_mask] = head[ins_h];
head[ins_h] = strstart;
} while (--match_length !== 0);
strstart++;
} else {
strstart += match_length;
match_length = 0;
ins_h = win[strstart] & 255;
ins_h = (ins_h << hash_shift ^ win[strstart + 1] & 255) & hash_mask;
}
} else {
bflush = _tr_tally(0, win[strstart] & 255);
lookahead--;
strstart++;
}
if (bflush) {
flush_block_only(false);
if (strm.avail_out === 0)
return NeedMore;
}
}
flush_block_only(flush == Z_FINISH);
if (strm.avail_out === 0) {
if (flush == Z_FINISH)
return FinishStarted;
else
return NeedMore;
}
return flush == Z_FINISH ? FinishDone : BlockDone;
}
function deflate_slow(flush) {
let hash_head = 0;
let bflush;
let max_insert;
while (true) {
if (lookahead < MIN_LOOKAHEAD) {
fill_window();
if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
return NeedMore;
}
if (lookahead === 0)
break;
}
if (lookahead >= MIN_MATCH) {
ins_h = (ins_h << hash_shift ^ win[strstart + (MIN_MATCH - 1)] & 255) & hash_mask;
hash_head = head[ins_h] & 65535;
prev[strstart & w_mask] = head[ins_h];
head[ins_h] = strstart;
}
prev_length = match_length;
prev_match = match_start;
match_length = MIN_MATCH - 1;
if (hash_head !== 0 && prev_length < max_lazy_match && (strstart - hash_head & 65535) <= w_size - MIN_LOOKAHEAD) {
if (strategy != Z_HUFFMAN_ONLY) {
match_length = longest_match(hash_head);
}
if (match_length <= 5 && (strategy == Z_FILTERED || match_length == MIN_MATCH && strstart - match_start > 4096)) {
match_length = MIN_MATCH - 1;
}
}
if (prev_length >= MIN_MATCH && match_length <= prev_length) {
max_insert = strstart + lookahead - MIN_MATCH;
bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
lookahead -= prev_length - 1;
prev_length -= 2;
do {
if (++strstart <= max_insert) {
ins_h = (ins_h << hash_shift ^ win[strstart + (MIN_MATCH - 1)] & 255) & hash_mask;
hash_head = head[ins_h] & 65535;
prev[strstart & w_mask] = head[ins_h];
head[ins_h] = strstart;
}
} while (--prev_length !== 0);
match_available = 0;
match_length = MIN_MATCH - 1;
strstart++;
if (bflush) {
flush_block_only(false);
if (strm.avail_out === 0)
return NeedMore;
}
} else if (match_available !== 0) {
bflush = _tr_tally(0, win[strstart - 1] & 255);
if (bflush) {
flush_block_only(false);
}
strstart++;
lookahead--;
if (strm.avail_out === 0)
return NeedMore;
} else {
match_available = 1;
strstart++;
lookahead--;
}
}
if (match_available !== 0) {
bflush = _tr_tally(0, win[strstart - 1] & 255);
match_available = 0;
}
flush_block_only(flush == Z_FINISH);
if (strm.avail_out === 0) {
if (flush == Z_FINISH)
return FinishStarted;
else
return NeedMore;
}
return flush == Z_FINISH ? FinishDone : BlockDone;
}
function deflateReset(strm2) {
strm2.total_in = strm2.total_out = 0;
strm2.msg = null;
that.pending = 0;
that.pending_out = 0;
status = BUSY_STATE;
last_flush = Z_NO_FLUSH;
tr_init();
lm_init();
return Z_OK;
}
that.deflateInit = function(strm2, _level, bits, _method, memLevel, _strategy) {
if (!_method)
_method = Z_DEFLATED;
if (!memLevel)
memLevel = DEF_MEM_LEVEL;
if (!_strategy)
_strategy = Z_DEFAULT_STRATEGY;
strm2.msg = null;
if (_level == Z_DEFAULT_COMPRESSION)
_level = 6;
if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
return Z_STREAM_ERROR;
}
strm2.dstate = that;
w_bits = bits;
w_size = 1 << w_bits;
w_mask = w_size - 1;
hash_bits = memLevel + 7;
hash_size = 1 << hash_bits;
hash_mask = hash_size - 1;
hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
win = new Uint8Array(w_size * 2);
prev = [];
head = [];
lit_bufsize = 1 << memLevel + 6;
that.pending_buf = new Uint8Array(lit_bufsize * 4);
pending_buf_size = lit_bufsize * 4;
that.dist_buf = new Uint16Array(lit_bufsize);
that.lc_buf = new Uint8Array(lit_bufsize);
level = _level;
strategy = _strategy;
return deflateReset(strm2);
};
that.deflateEnd = function() {
if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {
return Z_STREAM_ERROR;
}
that.lc_buf = null;
that.dist_buf = null;
that.pending_buf = null;
head = null;
prev = null;
win = null;
that.dstate = null;
return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
};
that.deflateParams = function(strm2, _level, _strategy) {
let err = Z_OK;
if (_level == Z_DEFAULT_COMPRESSION) {
_level = 6;
}
if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
return Z_STREAM_ERROR;
}
if (config_table[level].func != config_table[_level].func && strm2.total_in !== 0) {
err = strm2.deflate(Z_PARTIAL_FLUSH);
}
if (level != _level) {
level = _level;
max_lazy_match = config_table[level].max_lazy;
good_match = config_table[level].good_length;
nice_match = config_table[level].nice_length;
max_chain_length = config_table[level].max_chain;
}
strategy = _strategy;
return err;
};
that.deflateSetDictionary = function(_strm, dictionary, dictLength) {
let length2 = dictLength;
let n, index = 0;
if (!dictionary || status != INIT_STATE)
return Z_STREAM_ERROR;
if (length2 < MIN_MATCH)
return Z_OK;
if (length2 > w_size - MIN_LOOKAHEAD) {
length2 = w_size - MIN_LOOKAHEAD;
index = dictLength - length2;
}
win.set(dictionary.subarray(index, index + length2), 0);
strstart = length2;
block_start = length2;
ins_h = win[0] & 255;
ins_h = (ins_h << hash_shift ^ win[1] & 255) & hash_mask;
for (n = 0; n <= length2 - MIN_MATCH; n++) {
ins_h = (ins_h << hash_shift ^ win[n + (MIN_MATCH - 1)] & 255) & hash_mask;
prev[n & w_mask] = head[ins_h];
head[ins_h] = n;
}
return Z_OK;
};
that.deflate = function(_strm, flush) {
let i, header, level_flags, old_flush, bstate;
if (flush > Z_FINISH || flush < 0) {
return Z_STREAM_ERROR;
}
if (!_strm.next_out || !_strm.next_in && _strm.avail_in !== 0 || status == FINISH_STATE && flush != Z_FINISH) {
_strm.msg = z_errmsg[Z_NEED_DICT - Z_STREAM_ERROR];
return Z_STREAM_ERROR;
}
if (_strm.avail_out === 0) {
_strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
return Z_BUF_ERROR;
}
strm = _strm;
old_flush = last_flush;
last_flush = flush;
if (status == INIT_STATE) {
header = Z_DEFLATED + (w_bits - 8 << 4) << 8;
level_flags = (level - 1 & 255) >> 1;
if (level_flags > 3)
level_flags = 3;
header |= level_flags << 6;
if (strstart !== 0)
header |= PRESET_DICT;
header += 31 - header % 31;
status = BUSY_STATE;
putShortMSB(header);
}
if (that.pending !== 0) {
strm.flush_pending();
if (strm.avail_out === 0) {
last_flush = -1;
return Z_OK;
}
} else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) {
strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
return Z_BUF_ERROR;
}
if (status == FINISH_STATE && strm.avail_in !== 0) {
_strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
return Z_BUF_ERROR;
}
if (strm.avail_in !== 0 || lookahead !== 0 || flush != Z_NO_FLUSH && status != FINISH_STATE) {
bstate = -1;
switch (config_table[level].func) {
case STORED:
bstate = deflate_stored(flush);
break;
case FAST:
bstate = deflate_fast(flush);
break;
case SLOW:
bstate = deflate_slow(flush);
break;
default:
}
if (bstate == FinishStarted || bstate == FinishDone) {
status = FINISH_STATE;
}
if (bstate == NeedMore || bstate == FinishStarted) {
if (strm.avail_out === 0) {
last_flush = -1;
}
return Z_OK;
}
if (bstate == BlockDone) {
if (flush == Z_PARTIAL_FLUSH) {
_tr_align();
} else {
_tr_stored_block(0, 0, false);
if (flush == Z_FULL_FLUSH) {
for (i = 0; i < hash_size; i++)
head[i] = 0;
}
}
strm.flush_pending();
if (strm.avail_out === 0) {
last_flush = -1;
return Z_OK;
}
}
}
if (flush != Z_FINISH)
return Z_OK;
return Z_STREAM_END;
};
}
function ZStream() {
const that = this;
that.next_in_index = 0;
that.next_out_index = 0;
that.avail_in = 0;
that.total_in = 0;
that.avail_out = 0;
that.total_out = 0;
}
ZStream.prototype = {
deflateInit(level, bits) {
const that = this;
that.dstate = new Deflate();
if (!bits)
bits = MAX_BITS;
return that.dstate.deflateInit(that, level, bits);
},
deflate(flush) {
const that = this;
if (!that.dstate) {
return Z_STREAM_ERROR;
}
return that.dstate.deflate(that, flush);
},
deflateEnd() {
const that = this;
if (!that.dstate)
return Z_STREAM_ERROR;
const ret = that.dstate.deflateEnd();
that.dstate = null;
return ret;
},
deflateParams(level, strategy) {
const that = this;
if (!that.dstate)
return Z_STREAM_ERROR;
return that.dstate.deflateParams(that, level, strategy);
},
deflateSetDictionary(dictionary, dictLength) {
const that = this;
if (!that.dstate)
return Z_STREAM_ERROR;
return that.dstate.deflateSetDictionary(that, dictionary, dictLength);
},
// Read a new buffer from the current input stream, update the
// total number of bytes read. All deflate() input goes through
// this function so some applications may wish to modify it to avoid
// allocating a large strm->next_in buffer and copying from it.
// (See also flush_pending()).
read_buf(buf, start, size) {
const that = this;
let len = that.avail_in;
if (len > size)
len = size;
if (len === 0)
return 0;
that.avail_in -= len;
buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start);
that.next_in_index += len;
that.total_in += len;
return len;
},
// Flush as much pending output as possible. All deflate() output goes
// through this function so some applications may wish to modify it
// to avoid allocating a large strm->next_out buffer and copying into it.
// (See also read_buf()).
flush_pending() {
const that = this;
let len = that.dstate.pending;
if (len > that.avail_out)
len = that.avail_out;
if (len === 0)
return;
that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index);
that.next_out_index += len;
that.dstate.pending_out += len;
that.total_out += len;
that.avail_out -= len;
that.dstate.pending -= len;
if (that.dstate.pending === 0) {
that.dstate.pending_out = 0;
}
}
};
function ZipDeflate(options) {
const that = this;
const z = new ZStream();
const bufsize = getMaximumCompressedSize(options && options.chunkSize ? options.chunkSize : 64 * 1024);
const flush = Z_NO_FLUSH;
const buf = new Uint8Array(bufsize);
let level = options ? options.level : Z_DEFAULT_COMPRESSION;
if (typeof level == "undefined")
level = Z_DEFAULT_COMPRESSION;
z.deflateInit(level);
z.next_out = buf;
that.append = function(data, onprogress) {
let err, array, lastIndex = 0, bufferIndex = 0, bufferSize = 0;
const buffers = [];
if (!data.length)
return;
z.next_in_index = 0;
z.next_in = data;
z.avail_in = data.length;
do {
z.next_out_index = 0;
z.avail_out = bufsize;
err = z.deflate(flush);
if (err != Z_OK)
throw new Error("deflating: " + z.msg);
if (z.next_out_index)
if (z.next_out_index == bufsize)
buffers.push(new Uint8Array(buf));
else
buffers.push(buf.subarray(0, z.next_out_index));
bufferSize += z.next_out_index;
if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
onprogress(z.next_in_index);
lastIndex = z.next_in_index;
}
} while (z.avail_in > 0 || z.avail_out === 0);
if (buffers.length > 1) {
array = new Uint8Array(bufferSize);
buffers.forEach(function(chunk) {
array.set(chunk, bufferIndex);
bufferIndex += chunk.length;
});
} else {
array = buffers[0] ? new Uint8Array(buffers[0]) : new Uint8Array();
}
return array;
};
that.flush = function() {
let err, array, bufferIndex = 0, bufferSize = 0;
const buffers = [];
do {
z.next_out_index = 0;
z.avail_out = bufsize;
err = z.deflate(Z_FINISH);
if (err != Z_STREAM_END && err != Z_OK)
throw new Error("deflating: " + z.msg);
if (bufsize - z.avail_out > 0)
buffers.push(buf.slice(0, z.next_out_index));
bufferSize += z.next_out_index;
} while (z.avail_in > 0 || z.avail_out === 0);
z.deflateEnd();
array = new Uint8Array(bufferSize);
buffers.forEach(function(chunk) {
array.set(chunk, bufferIndex);
bufferIndex += chunk.length;
});
return array;
};
}
function getMaximumCompressedSize(uncompressedSize) {
return uncompressedSize + 5 * (Math.floor(uncompressedSize / 16383) + 1);
}
// node_modules/@zip.js/zip.js/lib/core/streams/codecs/inflate.js
var import_InlineWorkers967 = __toESM(require_InlineWorkers(), 1);
var MAX_BITS2 = 15;
var Z_OK2 = 0;
var Z_STREAM_END2 = 1;
var Z_NEED_DICT2 = 2;
var Z_STREAM_ERROR2 = -2;
var Z_DATA_ERROR2 = -3;
var Z_MEM_ERROR = -4;
var Z_BUF_ERROR2 = -5;
var inflate_mask = [
0,
1,
3,
7,
15,
31,
63,
127,
255,
511,
1023,
2047,
4095,
8191,
16383,
32767,
65535
];
var MANY = 1440;
var Z_NO_FLUSH2 = 0;
var Z_FINISH2 = 4;
var fixed_bl = 9;
var fixed_bd = 5;
var fixed_tl = [
96,
7,
256,
0,
8,
80,
0,
8,
16,
84,
8,
115,
82,
7,
31,
0,
8,
112,
0,
8,
48,
0,
9,
192,
80,
7,
10,
0,
8,
96,
0,
8,
32,
0,
9,
160,
0,
8,
0,
0,
8,
128,
0,
8,
64,
0,
9,
224,
80,
7,
6,
0,
8,
88,
0,
8,
24,
0,
9,
144,
83,
7,
59,
0,
8,
120,
0,
8,
56,
0,
9,
208,
81,
7,
17,
0,
8,
104,
0,
8,
40,
0,
9,
176,
0,
8,
8,
0,
8,
136,
0,
8,
72,
0,
9,
240,
80,
7,
4,
0,
8,
84,
0,
8,
20,
85,
8,
227,
83,
7,
43,
0,
8,
116,
0,
8,
52,
0,
9,
200,
81,
7,
13,
0,
8,
100,
0,
8,
36,
0,
9,
168,
0,
8,
4,
0,
8,
132,
0,
8,
68,
0,
9,
232,
80,
7,
8,
0,
8,
92,
0,
8,
28,
0,
9,
152,
84,
7,
83,
0,
8,
124,
0,
8,
60,
0,
9,
216,
82,
7,
23,
0,
8,
108,
0,
8,
44,
0,
9,
184,
0,
8,
12,
0,
8,
140,
0,
8,
76,
0,
9,
248,
80,
7,
3,
0,
8,
82,
0,
8,
18,
85,
8,
163,
83,
7,
35,
0,
8,
114,
0,
8,
50,
0,
9,
196,
81,
7,
11,
0,
8,
98,
0,
8,
34,
0,
9,
164,
0,
8,
2,
0,
8,
130,
0,
8,
66,
0,
9,
228,
80,
7,
7,
0,
8,
90,
0,
8,
26,
0,
9,
148,
84,
7,
67,
0,
8,
122,
0,
8,
58,
0,
9,
212,
82,
7,
19,
0,
8,
106,
0,
8,
42,
0,
9,
180,
0,
8,
10,
0,
8,
138,
0,
8,
74,
0,
9,
244,
80,
7,
5,
0,
8,
86,
0,
8,
22,
192,
8,
0,
83,
7,
51,
0,
8,
118,
0,
8,
54,
0,
9,
204,
81,
7,
15,
0,
8,
102,
0,
8,
38,
0,
9,
172,
0,
8,
6,
0,
8,
134,
0,
8,
70,
0,
9,
236,
80,
7,
9,
0,
8,
94,
0,
8,
30,
0,
9,
156,
84,
7,
99,
0,
8,
126,
0,
8,
62,
0,
9,
220,
82,
7,
27,
0,
8,
110,
0,
8,
46,
0,
9,
188,
0,
8,
14,
0,
8,
142,
0,
8,
78,
0,
9,
252,
96,
7,
256,
0,
8,
81,
0,
8,
17,
85,
8,
131,
82,
7,
31,
0,
8,
113,
0,
8,
49,
0,
9,
194,
80,
7,
10,
0,
8,
97,
0,
8,
33,
0,
9,
162,
0,
8,
1,
0,
8,
129,
0,
8,
65,
0,
9,
226,
80,
7,
6,
0,
8,
89,
0,
8,
25,
0,
9,
146,
83,
7,
59,
0,
8,
121,
0,
8,
57,
0,
9,
210,
81,
7,
17,
0,
8,
105,
0,
8,
41,
0,
9,
178,
0,
8,
9,
0,
8,
137,
0,
8,
73,
0,
9,
242,
80,
7,
4,
0,
8,
85,
0,
8,
21,
80,
8,
258,
83,
7,
43,
0,
8,
117,
0,
8,
53,
0,
9,
202,
81,
7,
13,
0,
8,
101,
0,
8,
37,
0,
9,
170,
0,
8,
5,
0,
8,
133,
0,
8,
69,
0,
9,
234,
80,
7,
8,
0,
8,
93,
0,
8,
29,
0,
9,
154,
84,
7,
83,
0,
8,
125,
0,
8,
61,
0,
9,
218,
82,
7,
23,
0,
8,
109,
0,
8,
45,
0,
9,
186,
0,
8,
13,
0,
8,
141,
0,
8,
77,
0,
9,
250,
80,
7,
3,
0,
8,
83,
0,
8,
19,
85,
8,
195,
83,
7,
35,
0,
8,
115,
0,
8,
51,
0,
9,
198,
81,
7,
11,
0,
8,
99,
0,
8,
35,
0,
9,
166,
0,
8,
3,
0,
8,
131,
0,
8,
67,
0,
9,
230,
80,
7,
7,
0,
8,
91,
0,
8,
27,
0,
9,
150,
84,
7,
67,
0,
8,
123,
0,
8,
59,
0,
9,
214,
82,
7,
19,
0,
8,
107,
0,
8,
43,
0,
9,
182,
0,
8,
11,
0,
8,
139,
0,
8,
75,
0,
9,
246,
80,
7,
5,
0,
8,
87,
0,
8,
23,
192,
8,
0,
83,
7,
51,
0,
8,
119,
0,
8,
55,
0,
9,
206,
81,
7,
15,
0,
8,
103,
0,
8,
39,
0,
9,
174,
0,
8,
7,
0,
8,
135,
0,
8,
71,
0,
9,
238,
80,
7,
9,
0,
8,
95,
0,
8,
31,
0,
9,
158,
84,
7,
99,
0,
8,
127,
0,
8,
63,
0,
9,
222,
82,
7,
27,
0,
8,
111,
0,
8,
47,
0,
9,
190,
0,
8,
15,
0,
8,
143,
0,
8,
79,
0,
9,
254,
96,
7,
256,
0,
8,
80,
0,
8,
16,
84,
8,
115,
82,
7,
31,
0,
8,
112,
0,
8,
48,
0,
9,
193,
80,
7,
10,
0,
8,
96,
0,
8,
32,
0,
9,
161,
0,
8,
0,
0,
8,
128,
0,
8,
64,
0,
9,
225,
80,
7,
6,
0,
8,
88,
0,
8,
24,
0,
9,
145,
83,
7,
59,
0,
8,
120,
0,
8,
56,
0,
9,
209,
81,
7,
17,
0,
8,
104,
0,
8,
40,
0,
9,
177,
0,
8,
8,
0,
8,
136,
0,
8,
72,
0,
9,
241,
80,
7,
4,
0,
8,
84,
0,
8,
20,
85,
8,
227,
83,
7,
43,
0,
8,
116,
0,
8,
52,
0,
9,
201,
81,
7,
13,
0,
8,
100,
0,
8,
36,
0,
9,
169,
0,
8,
4,
0,
8,
132,
0,
8,
68,
0,
9,
233,
80,
7,
8,
0,
8,
92,
0,
8,
28,
0,
9,
153,
84,
7,
83,
0,
8,
124,
0,
8,
60,
0,
9,
217,
82,
7,
23,
0,
8,
108,
0,
8,
44,
0,
9,
185,
0,
8,
12,
0,
8,
140,
0,
8,
76,
0,
9,
249,
80,
7,
3,
0,
8,
82,
0,
8,
18,
85,
8,
163,
83,
7,
35,
0,
8,
114,
0,
8,
50,
0,
9,
197,
81,
7,
11,
0,
8,
98,
0,
8,
34,
0,
9,
165,
0,
8,
2,
0,
8,
130,
0,
8,
66,
0,
9,
229,
80,
7,
7,
0,
8,
90,
0,
8,
26,
0,
9,
149,
84,
7,
67,
0,
8,
122,
0,
8,
58,
0,
9,
213,
82,
7,
19,
0,
8,
106,
0,
8,
42,
0,
9,
181,
0,
8,
10,
0,
8,
138,
0,
8,
74,
0,
9,
245,
80,
7,
5,
0,
8,
86,
0,
8,
22,
192,
8,
0,
83,
7,
51,
0,
8,
118,
0,
8,
54,
0,
9,
205,
81,
7,
15,
0,
8,
102,
0,
8,
38,
0,
9,
173,
0,
8,
6,
0,
8,
134,
0,
8,
70,
0,
9,
237,
80,
7,
9,
0,
8,
94,
0,
8,
30,
0,
9,
157,
84,
7,
99,
0,
8,
126,
0,
8,
62,
0,
9,
221,
82,
7,
27,
0,
8,
110,
0,
8,
46,
0,
9,
189,
0,
8,
14,
0,
8,
142,
0,
8,
78,
0,
9,
253,
96,
7,
256,
0,
8,
81,
0,
8,
17,
85,
8,
131,
82,
7,
31,
0,
8,
113,
0,
8,
49,
0,
9,
195,
80,
7,
10,
0,
8,
97,
0,
8,
33,
0,
9,
163,
0,
8,
1,
0,
8,
129,
0,
8,
65,
0,
9,
227,
80,
7,
6,
0,
8,
89,
0,
8,
25,
0,
9,
147,
83,
7,
59,
0,
8,
121,
0,
8,
57,
0,
9,
211,
81,
7,
17,
0,
8,
105,
0,
8,
41,
0,
9,
179,
0,
8,
9,
0,
8,
137,
0,
8,
73,
0,
9,
243,
80,
7,
4,
0,
8,
85,
0,
8,
21,
80,
8,
258,
83,
7,
43,
0,
8,
117,
0,
8,
53,
0,
9,
203,
81,
7,
13,
0,
8,
101,
0,
8,
37,
0,
9,
171,
0,
8,
5,
0,
8,
133,
0,
8,
69,
0,
9,
235,
80,
7,
8,
0,
8,
93,
0,
8,
29,
0,
9,
155,
84,
7,
83,
0,
8,
125,
0,
8,
61,
0,
9,
219,
82,
7,
23,
0,
8,
109,
0,
8,
45,
0,
9,
187,
0,
8,
13,
0,
8,
141,
0,
8,
77,
0,
9,
251,
80,
7,
3,
0,
8,
83,
0,
8,
19,
85,
8,
195,
83,
7,
35,
0,
8,
115,
0,
8,
51,
0,
9,
199,
81,
7,
11,
0,
8,
99,
0,
8,
35,
0,
9,
167,
0,
8,
3,
0,
8,
131,
0,
8,
67,
0,
9,
231,
80,
7,
7,
0,
8,
91,
0,
8,
27,
0,
9,
151,
84,
7,
67,
0,
8,
123,
0,
8,
59,
0,
9,
215,
82,
7,
19,
0,
8,
107,
0,
8,
43,
0,
9,
183,
0,
8,
11,
0,
8,
139,
0,
8,
75,
0,
9,
247,
80,
7,
5,
0,
8,
87,
0,
8,
23,
192,
8,
0,
83,
7,
51,
0,
8,
119,
0,
8,
55,
0,
9,
207,
81,
7,
15,
0,
8,
103,
0,
8,
39,
0,
9,
175,
0,
8,
7,
0,
8,
135,
0,
8,
71,
0,
9,
239,
80,
7,
9,
0,
8,
95,
0,
8,
31,
0,
9,
159,
84,
7,
99,
0,
8,
127,
0,
8,
63,
0,
9,
223,
82,
7,
27,
0,
8,
111,
0,
8,
47,
0,
9,
191,
0,
8,
15,
0,
8,
143,
0,
8,
79,
0,
9,
255
];
var fixed_td = [
80,
5,
1,
87,
5,
257,
83,
5,
17,
91,
5,
4097,
81,
5,
5,
89,
5,
1025,
85,
5,
65,
93,
5,
16385,
80,
5,
3,
88,
5,
513,
84,
5,
33,
92,
5,
8193,
82,
5,
9,
90,
5,
2049,
86,
5,
129,
192,
5,
24577,
80,
5,
2,
87,
5,
385,
83,
5,
25,
91,
5,
6145,
81,
5,
7,
89,
5,
1537,
85,
5,
97,
93,
5,
24577,
80,
5,
4,
88,
5,
769,
84,
5,
49,
92,
5,
12289,
82,
5,
13,
90,
5,
3073,
86,
5,
193,
192,
5,
24577
];
var cplens = [
// Copy lengths for literal codes 257..285
3,
4,
5,
6,
7,
8,
9,
10,
11,
13,
15,
17,
19,
23,
27,
31,
35,
43,
51,
59,
67,
83,
99,
115,
131,
163,
195,
227,
258,
0,
0
];
var cplext = [
// Extra bits for literal codes 257..285
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
2,
2,
2,
2,
3,
3,
3,
3,
4,
4,
4,
4,
5,
5,
5,
5,
0,
112,
112
// 112==invalid
];
var cpdist = [
// Copy offsets for distance codes 0..29
1,
2,
3,
4,
5,
7,
9,
13,
17,
25,
33,
49,
65,
97,
129,
193,
257,
385,
513,
769,
1025,
1537,
2049,
3073,
4097,
6145,
8193,
12289,
16385,
24577
];
var cpdext = [
// Extra bits for distance codes
0,
0,
0,
0,
1,
1,
2,
2,
3,
3,
4,
4,
5,
5,
6,
6,
7,
7,
8,
8,
9,
9,
10,
10,
11,
11,
12,
12,
13,
13
];
var BMAX = 15;
function InfTree() {
const that = this;
let hn;
let v3;
let c;
let r;
let u3;
let x;
function huft_build(b, bindex, n, s, d, e, t, m, hp, hn2, v4) {
let a3;
let f;
let g;
let h;
let i;
let j;
let k;
let l;
let mask;
let p;
let q;
let w;
let xp;
let y;
let z;
p = 0;
i = n;
do {
c[b[bindex + p]]++;
p++;
i--;
} while (i !== 0);
if (c[0] == n) {
t[0] = -1;
m[0] = 0;
return Z_OK2;
}
l = m[0];
for (j = 1; j <= BMAX; j++)
if (c[j] !== 0)
break;
k = j;
if (l < j) {
l = j;
}
for (i = BMAX; i !== 0; i--) {
if (c[i] !== 0)
break;
}
g = i;
if (l > i) {
l = i;
}
m[0] = l;
for (y = 1 << j; j < i; j++, y <<= 1) {
if ((y -= c[j]) < 0) {
return Z_DATA_ERROR2;
}
}
if ((y -= c[i]) < 0) {
return Z_DATA_ERROR2;
}
c[i] += y;
x[1] = j = 0;
p = 1;
xp = 2;
while (--i !== 0) {
x[xp] = j += c[p];
xp++;
p++;
}
i = 0;
p = 0;
do {
if ((j = b[bindex + p]) !== 0) {
v4[x[j]++] = i;
}
p++;
} while (++i < n);
n = x[g];
x[0] = i = 0;
p = 0;
h = -1;
w = -l;
u3[0] = 0;
q = 0;
z = 0;
for (; k <= g; k++) {
a3 = c[k];
while (a3-- !== 0) {
while (k > w + l) {
h++;
w += l;
z = g - w;
z = z > l ? l : z;
if ((f = 1 << (j = k - w)) > a3 + 1) {
f -= a3 + 1;
xp = k;
if (j < z) {
while (++j < z) {
if ((f <<= 1) <= c[++xp])
break;
f -= c[xp];
}
}
}
z = 1 << j;
if (hn2[0] + z > MANY) {
return Z_DATA_ERROR2;
}
u3[h] = q = /* hp+ */
hn2[0];
hn2[0] += z;
if (h !== 0) {
x[h] = i;
r[0] = /* (byte) */
j;
r[1] = /* (byte) */
l;
j = i >>> w - l;
r[2] = /* (int) */
q - u3[h - 1] - j;
hp.set(r, (u3[h - 1] + j) * 3);
} else {
t[0] = q;
}
}
r[1] = /* (byte) */
k - w;
if (p >= n) {
r[0] = 128 + 64;
} else if (v4[p] < s) {
r[0] = /* (byte) */
v4[p] < 256 ? 0 : 32 + 64;
r[2] = v4[p++];
} else {
r[0] = /* (byte) */
e[v4[p] - s] + 16 + 64;
r[2] = d[v4[p++] - s];
}
f = 1 << k - w;
for (j = i >>> w; j < z; j += f) {
hp.set(r, (q + j) * 3);
}
for (j = 1 << k - 1; (i & j) !== 0; j >>>= 1) {
i ^= j;
}
i ^= j;
mask = (1 << w) - 1;
while ((i & mask) != x[h]) {
h--;
w -= l;
mask = (1 << w) - 1;
}
}
}
return y !== 0 && g != 1 ? Z_BUF_ERROR2 : Z_OK2;
}
function initWorkArea(vsize) {
let i;
if (!hn) {
hn = [];
v3 = [];
c = new Int32Array(BMAX + 1);
r = [];
u3 = new Int32Array(BMAX);
x = new Int32Array(BMAX + 1);
}
if (v3.length < vsize) {
v3 = [];
}
for (i = 0; i < vsize; i++) {
v3[i] = 0;
}
for (i = 0; i < BMAX + 1; i++) {
c[i] = 0;
}
for (i = 0; i < 3; i++) {
r[i] = 0;
}
u3.set(c.subarray(0, BMAX), 0);
x.set(c.subarray(0, BMAX + 1), 0);
}
that.inflate_trees_bits = function(c14, bb, tb, hp, z) {
let result;
initWorkArea(19);
hn[0] = 0;
result = huft_build(c14, 0, 19, 19, null, null, tb, bb, hp, hn, v3);
if (result == Z_DATA_ERROR2) {
z.msg = "oversubscribed dynamic bit lengths tree";
} else if (result == Z_BUF_ERROR2 || bb[0] === 0) {
z.msg = "incomplete dynamic bit lengths tree";
result = Z_DATA_ERROR2;
}
return result;
};
that.inflate_trees_dynamic = function(nl, nd, c14, bl, bd, tl, td, hp, z) {
let result;
initWorkArea(288);
hn[0] = 0;
result = huft_build(c14, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v3);
if (result != Z_OK2 || bl[0] === 0) {
if (result == Z_DATA_ERROR2) {
z.msg = "oversubscribed literal/length tree";
} else if (result != Z_MEM_ERROR) {
z.msg = "incomplete literal/length tree";
result = Z_DATA_ERROR2;
}
return result;
}
initWorkArea(288);
result = huft_build(c14, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v3);
if (result != Z_OK2 || bd[0] === 0 && nl > 257) {
if (result == Z_DATA_ERROR2) {
z.msg = "oversubscribed distance tree";
} else if (result == Z_BUF_ERROR2) {
z.msg = "incomplete distance tree";
result = Z_DATA_ERROR2;
} else if (result != Z_MEM_ERROR) {
z.msg = "empty distance tree with lengths";
result = Z_DATA_ERROR2;
}
return result;
}
return Z_OK2;
};
}
InfTree.inflate_trees_fixed = function(bl, bd, tl, td) {
bl[0] = fixed_bl;
bd[0] = fixed_bd;
tl[0] = fixed_tl;
td[0] = fixed_td;
return Z_OK2;
};
var START = 0;
var LEN = 1;
var LENEXT = 2;
var DIST = 3;
var DISTEXT = 4;
var COPY = 5;
var LIT = 6;
var WASH = 7;
var END = 8;
var BADCODE = 9;
function InfCodes() {
const that = this;
let mode2;
let len = 0;
let tree;
let tree_index = 0;
let need = 0;
let lit = 0;
let get2 = 0;
let dist = 0;
let lbits = 0;
let dbits = 0;
let ltree;
let ltree_index = 0;
let dtree;
let dtree_index = 0;
function inflate_fast(bl, bd, tl, tl_index, td, td_index, s, z) {
let t;
let tp;
let tp_index;
let e;
let b;
let k;
let p;
let n;
let q;
let m;
let ml;
let md;
let c;
let d;
let r;
let tp_index_t_3;
p = z.next_in_index;
n = z.avail_in;
b = s.bitb;
k = s.bitk;
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
ml = inflate_mask[bl];
md = inflate_mask[bd];
do {
while (k < 20) {
n--;
b |= (z.read_byte(p++) & 255) << k;
k += 8;
}
t = b & ml;
tp = tl;
tp_index = tl_index;
tp_index_t_3 = (tp_index + t) * 3;
if ((e = tp[tp_index_t_3]) === 0) {
b >>= tp[tp_index_t_3 + 1];
k -= tp[tp_index_t_3 + 1];
s.win[q++] = /* (byte) */
tp[tp_index_t_3 + 2];
m--;
continue;
}
do {
b >>= tp[tp_index_t_3 + 1];
k -= tp[tp_index_t_3 + 1];
if ((e & 16) !== 0) {
e &= 15;
c = tp[tp_index_t_3 + 2] + /* (int) */
(b & inflate_mask[e]);
b >>= e;
k -= e;
while (k < 15) {
n--;
b |= (z.read_byte(p++) & 255) << k;
k += 8;
}
t = b & md;
tp = td;
tp_index = td_index;
tp_index_t_3 = (tp_index + t) * 3;
e = tp[tp_index_t_3];
do {
b >>= tp[tp_index_t_3 + 1];
k -= tp[tp_index_t_3 + 1];
if ((e & 16) !== 0) {
e &= 15;
while (k < e) {
n--;
b |= (z.read_byte(p++) & 255) << k;
k += 8;
}
d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
b >>= e;
k -= e;
m -= c;
if (q >= d) {
r = q - d;
if (q - r > 0 && 2 > q - r) {
s.win[q++] = s.win[r++];
s.win[q++] = s.win[r++];
c -= 2;
} else {
s.win.set(s.win.subarray(r, r + 2), q);
q += 2;
r += 2;
c -= 2;
}
} else {
r = q - d;
do {
r += s.end;
} while (r < 0);
e = s.end - r;
if (c > e) {
c -= e;
if (q - r > 0 && e > q - r) {
do {
s.win[q++] = s.win[r++];
} while (--e !== 0);
} else {
s.win.set(s.win.subarray(r, r + e), q);
q += e;
r += e;
e = 0;
}
r = 0;
}
}
if (q - r > 0 && c > q - r) {
do {
s.win[q++] = s.win[r++];
} while (--c !== 0);
} else {
s.win.set(s.win.subarray(r, r + c), q);
q += c;
r += c;
c = 0;
}
break;
} else if ((e & 64) === 0) {
t += tp[tp_index_t_3 + 2];
t += b & inflate_mask[e];
tp_index_t_3 = (tp_index + t) * 3;
e = tp[tp_index_t_3];
} else {
z.msg = "invalid distance code";
c = z.avail_in - n;
c = k >> 3 < c ? k >> 3 : c;
n += c;
p -= c;
k -= c << 3;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return Z_DATA_ERROR2;
}
} while (true);
break;
}
if ((e & 64) === 0) {
t += tp[tp_index_t_3 + 2];
t += b & inflate_mask[e];
tp_index_t_3 = (tp_index + t) * 3;
if ((e = tp[tp_index_t_3]) === 0) {
b >>= tp[tp_index_t_3 + 1];
k -= tp[tp_index_t_3 + 1];
s.win[q++] = /* (byte) */
tp[tp_index_t_3 + 2];
m--;
break;
}
} else if ((e & 32) !== 0) {
c = z.avail_in - n;
c = k >> 3 < c ? k >> 3 : c;
n += c;
p -= c;
k -= c << 3;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return Z_STREAM_END2;
} else {
z.msg = "invalid literal/length code";
c = z.avail_in - n;
c = k >> 3 < c ? k >> 3 : c;
n += c;
p -= c;
k -= c << 3;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return Z_DATA_ERROR2;
}
} while (true);
} while (m >= 258 && n >= 10);
c = z.avail_in - n;
c = k >> 3 < c ? k >> 3 : c;
n += c;
p -= c;
k -= c << 3;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return Z_OK2;
}
that.init = function(bl, bd, tl, tl_index, td, td_index) {
mode2 = START;
lbits = /* (byte) */
bl;
dbits = /* (byte) */
bd;
ltree = tl;
ltree_index = tl_index;
dtree = td;
dtree_index = td_index;
tree = null;
};
that.proc = function(s, z, r) {
let j;
let tindex;
let e;
let b = 0;
let k = 0;
let p = 0;
let n;
let q;
let m;
let f;
p = z.next_in_index;
n = z.avail_in;
b = s.bitb;
k = s.bitk;
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
while (true) {
switch (mode2) {
// waiting for "i:"=input, "o:"=output, "x:"=nothing
case START:
if (m >= 258 && n >= 10) {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
r = inflate_fast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, s, z);
p = z.next_in_index;
n = z.avail_in;
b = s.bitb;
k = s.bitk;
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
if (r != Z_OK2) {
mode2 = r == Z_STREAM_END2 ? WASH : BADCODE;
break;
}
}
need = lbits;
tree = ltree;
tree_index = ltree_index;
mode2 = LEN;
/* falls through */
case LEN:
j = need;
while (k < j) {
if (n !== 0)
r = Z_OK2;
else {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
n--;
b |= (z.read_byte(p++) & 255) << k;
k += 8;
}
tindex = (tree_index + (b & inflate_mask[j])) * 3;
b >>>= tree[tindex + 1];
k -= tree[tindex + 1];
e = tree[tindex];
if (e === 0) {
lit = tree[tindex + 2];
mode2 = LIT;
break;
}
if ((e & 16) !== 0) {
get2 = e & 15;
len = tree[tindex + 2];
mode2 = LENEXT;
break;
}
if ((e & 64) === 0) {
need = e;
tree_index = tindex / 3 + tree[tindex + 2];
break;
}
if ((e & 32) !== 0) {
mode2 = WASH;
break;
}
mode2 = BADCODE;
z.msg = "invalid literal/length code";
r = Z_DATA_ERROR2;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
case LENEXT:
j = get2;
while (k < j) {
if (n !== 0)
r = Z_OK2;
else {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
n--;
b |= (z.read_byte(p++) & 255) << k;
k += 8;
}
len += b & inflate_mask[j];
b >>= j;
k -= j;
need = dbits;
tree = dtree;
tree_index = dtree_index;
mode2 = DIST;
/* falls through */
case DIST:
j = need;
while (k < j) {
if (n !== 0)
r = Z_OK2;
else {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
n--;
b |= (z.read_byte(p++) & 255) << k;
k += 8;
}
tindex = (tree_index + (b & inflate_mask[j])) * 3;
b >>= tree[tindex + 1];
k -= tree[tindex + 1];
e = tree[tindex];
if ((e & 16) !== 0) {
get2 = e & 15;
dist = tree[tindex + 2];
mode2 = DISTEXT;
break;
}
if ((e & 64) === 0) {
need = e;
tree_index = tindex / 3 + tree[tindex + 2];
break;
}
mode2 = BADCODE;
z.msg = "invalid distance code";
r = Z_DATA_ERROR2;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
case DISTEXT:
j = get2;
while (k < j) {
if (n !== 0)
r = Z_OK2;
else {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
n--;
b |= (z.read_byte(p++) & 255) << k;
k += 8;
}
dist += b & inflate_mask[j];
b >>= j;
k -= j;
mode2 = COPY;
/* falls through */
case COPY:
f = q - dist;
while (f < 0) {
f += s.end;
}
while (len !== 0) {
if (m === 0) {
if (q == s.end && s.read !== 0) {
q = 0;
m = q < s.read ? s.read - q - 1 : s.end - q;
}
if (m === 0) {
s.write = q;
r = s.inflate_flush(z, r);
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
if (q == s.end && s.read !== 0) {
q = 0;
m = q < s.read ? s.read - q - 1 : s.end - q;
}
if (m === 0) {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
}
}
s.win[q++] = s.win[f++];
m--;
if (f == s.end)
f = 0;
len--;
}
mode2 = START;
break;
case LIT:
if (m === 0) {
if (q == s.end && s.read !== 0) {
q = 0;
m = q < s.read ? s.read - q - 1 : s.end - q;
}
if (m === 0) {
s.write = q;
r = s.inflate_flush(z, r);
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
if (q == s.end && s.read !== 0) {
q = 0;
m = q < s.read ? s.read - q - 1 : s.end - q;
}
if (m === 0) {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
}
}
r = Z_OK2;
s.win[q++] = /* (byte) */
lit;
m--;
mode2 = START;
break;
case WASH:
if (k > 7) {
k -= 8;
n++;
p--;
}
s.write = q;
r = s.inflate_flush(z, r);
q = s.write;
m = q < s.read ? s.read - q - 1 : s.end - q;
if (s.read != s.write) {
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
mode2 = END;
/* falls through */
case END:
r = Z_STREAM_END2;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
case BADCODE:
r = Z_DATA_ERROR2;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
default:
r = Z_STREAM_ERROR2;
s.bitb = b;
s.bitk = k;
z.avail_in = n;
z.total_in += p - z.next_in_index;
z.next_in_index = p;
s.write = q;
return s.inflate_flush(z, r);
}
}
};
that.free = function() {
};
}
var border = [
// Order of the bit length code lengths
16,
17,
18,
0,
8,
7,
9,
6,
10,
5,
11,
4,
12,
3,
13,
2,
14,
1,
15
];
var TYPE = 0;
var LENS = 1;
var STORED2 = 2;
var TABLE = 3;
var BTREE = 4;
var DTREE = 5;
var CODES = 6;
var DRY = 7;
var DONELOCKS = 8;
var BADBLOCKS = 9;
function InfBlocks(z, w) {
const that = this;
let mode2 = TYPE;
let left = 0;
let table2 = 0;
let index = 0;
let blens;
const bb = [0];
const tb = [0];
const codes = new InfCodes();
let last = 0;
let hufts = new Int32Array(MANY * 3);
const check = 0;
const inftree = new InfTree();
that.bitk = 0;
that.bitb = 0;
that.win = new Uint8Array(w);
that.end = w;
that.read = 0;
that.write = 0;
that.reset = function(z2, c) {
if (c)
c[0] = check;
if (mode2 == CODES) {
codes.free(z2);
}
mode2 = TYPE;
that.bitk = 0;
that.bitb = 0;
that.read = that.write = 0;
};
that.reset(z, null);
that.inflate_flush = function(z2, r) {
let n;
let p;
let q;
p = z2.next_out_index;
q = that.read;
n = /* (int) */
(q <= that.write ? that.write : that.end) - q;
if (n > z2.avail_out)
n = z2.avail_out;
if (n !== 0 && r == Z_BUF_ERROR2)
r = Z_OK2;
z2.avail_out -= n;
z2.total_out += n;
z2.next_out.set(that.win.subarray(q, q + n), p);
p += n;
q += n;
if (q == that.end) {
q = 0;
if (that.write == that.end)
that.write = 0;
n = that.write - q;
if (n > z2.avail_out)
n = z2.avail_out;
if (n !== 0 && r == Z_BUF_ERROR2)
r = Z_OK2;
z2.avail_out -= n;
z2.total_out += n;
z2.next_out.set(that.win.subarray(q, q + n), p);
p += n;
q += n;
}
z2.next_out_index = p;
that.read = q;
return r;
};
that.proc = function(z2, r) {
let t;
let b;
let k;
let p;
let n;
let q;
let m;
let i;
p = z2.next_in_index;
n = z2.avail_in;
b = that.bitb;
k = that.bitk;
q = that.write;
m = /* (int) */
q < that.read ? that.read - q - 1 : that.end - q;
while (true) {
let bl, bd, tl, td, bl_, bd_, tl_, td_;
switch (mode2) {
case TYPE:
while (k < 3) {
if (n !== 0) {
r = Z_OK2;
} else {
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
n--;
b |= (z2.read_byte(p++) & 255) << k;
k += 8;
}
t = /* (int) */
b & 7;
last = t & 1;
switch (t >>> 1) {
case 0:
b >>>= 3;
k -= 3;
t = k & 7;
b >>>= t;
k -= t;
mode2 = LENS;
break;
case 1:
bl = [];
bd = [];
tl = [[]];
td = [[]];
InfTree.inflate_trees_fixed(bl, bd, tl, td);
codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);
b >>>= 3;
k -= 3;
mode2 = CODES;
break;
case 2:
b >>>= 3;
k -= 3;
mode2 = TABLE;
break;
case 3:
b >>>= 3;
k -= 3;
mode2 = BADBLOCKS;
z2.msg = "invalid block type";
r = Z_DATA_ERROR2;
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
break;
case LENS:
while (k < 32) {
if (n !== 0) {
r = Z_OK2;
} else {
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
n--;
b |= (z2.read_byte(p++) & 255) << k;
k += 8;
}
if ((~b >>> 16 & 65535) != (b & 65535)) {
mode2 = BADBLOCKS;
z2.msg = "invalid stored block lengths";
r = Z_DATA_ERROR2;
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
left = b & 65535;
b = k = 0;
mode2 = left !== 0 ? STORED2 : last !== 0 ? DRY : TYPE;
break;
case STORED2:
if (n === 0) {
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
if (m === 0) {
if (q == that.end && that.read !== 0) {
q = 0;
m = /* (int) */
q < that.read ? that.read - q - 1 : that.end - q;
}
if (m === 0) {
that.write = q;
r = that.inflate_flush(z2, r);
q = that.write;
m = /* (int) */
q < that.read ? that.read - q - 1 : that.end - q;
if (q == that.end && that.read !== 0) {
q = 0;
m = /* (int) */
q < that.read ? that.read - q - 1 : that.end - q;
}
if (m === 0) {
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
}
}
r = Z_OK2;
t = left;
if (t > n)
t = n;
if (t > m)
t = m;
that.win.set(z2.read_buf(p, t), q);
p += t;
n -= t;
q += t;
m -= t;
if ((left -= t) !== 0)
break;
mode2 = last !== 0 ? DRY : TYPE;
break;
case TABLE:
while (k < 14) {
if (n !== 0) {
r = Z_OK2;
} else {
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
n--;
b |= (z2.read_byte(p++) & 255) << k;
k += 8;
}
table2 = t = b & 16383;
if ((t & 31) > 29 || (t >> 5 & 31) > 29) {
mode2 = BADBLOCKS;
z2.msg = "too many length or distance symbols";
r = Z_DATA_ERROR2;
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
t = 258 + (t & 31) + (t >> 5 & 31);
if (!blens || blens.length < t) {
blens = [];
} else {
for (i = 0; i < t; i++) {
blens[i] = 0;
}
}
b >>>= 14;
k -= 14;
index = 0;
mode2 = BTREE;
/* falls through */
case BTREE:
while (index < 4 + (table2 >>> 10)) {
while (k < 3) {
if (n !== 0) {
r = Z_OK2;
} else {
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
n--;
b |= (z2.read_byte(p++) & 255) << k;
k += 8;
}
blens[border[index++]] = b & 7;
b >>>= 3;
k -= 3;
}
while (index < 19) {
blens[border[index++]] = 0;
}
bb[0] = 7;
t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z2);
if (t != Z_OK2) {
r = t;
if (r == Z_DATA_ERROR2) {
blens = null;
mode2 = BADBLOCKS;
}
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
index = 0;
mode2 = DTREE;
/* falls through */
case DTREE:
while (true) {
t = table2;
if (index >= 258 + (t & 31) + (t >> 5 & 31)) {
break;
}
let j, c;
t = bb[0];
while (k < t) {
if (n !== 0) {
r = Z_OK2;
} else {
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
n--;
b |= (z2.read_byte(p++) & 255) << k;
k += 8;
}
t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
if (c < 16) {
b >>>= t;
k -= t;
blens[index++] = c;
} else {
i = c == 18 ? 7 : c - 14;
j = c == 18 ? 11 : 3;
while (k < t + i) {
if (n !== 0) {
r = Z_OK2;
} else {
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
n--;
b |= (z2.read_byte(p++) & 255) << k;
k += 8;
}
b >>>= t;
k -= t;
j += b & inflate_mask[i];
b >>>= i;
k -= i;
i = index;
t = table2;
if (i + j > 258 + (t & 31) + (t >> 5 & 31) || c == 16 && i < 1) {
blens = null;
mode2 = BADBLOCKS;
z2.msg = "invalid bit length repeat";
r = Z_DATA_ERROR2;
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
c = c == 16 ? blens[i - 1] : 0;
do {
blens[i++] = c;
} while (--j !== 0);
index = i;
}
}
tb[0] = -1;
bl_ = [];
bd_ = [];
tl_ = [];
td_ = [];
bl_[0] = 9;
bd_[0] = 6;
t = table2;
t = inftree.inflate_trees_dynamic(257 + (t & 31), 1 + (t >> 5 & 31), blens, bl_, bd_, tl_, td_, hufts, z2);
if (t != Z_OK2) {
if (t == Z_DATA_ERROR2) {
blens = null;
mode2 = BADBLOCKS;
}
r = t;
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
codes.init(bl_[0], bd_[0], hufts, tl_[0], hufts, td_[0]);
mode2 = CODES;
/* falls through */
case CODES:
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
if ((r = codes.proc(that, z2, r)) != Z_STREAM_END2) {
return that.inflate_flush(z2, r);
}
r = Z_OK2;
codes.free(z2);
p = z2.next_in_index;
n = z2.avail_in;
b = that.bitb;
k = that.bitk;
q = that.write;
m = /* (int) */
q < that.read ? that.read - q - 1 : that.end - q;
if (last === 0) {
mode2 = TYPE;
break;
}
mode2 = DRY;
/* falls through */
case DRY:
that.write = q;
r = that.inflate_flush(z2, r);
q = that.write;
m = /* (int) */
q < that.read ? that.read - q - 1 : that.end - q;
if (that.read != that.write) {
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
mode2 = DONELOCKS;
/* falls through */
case DONELOCKS:
r = Z_STREAM_END2;
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
case BADBLOCKS:
r = Z_DATA_ERROR2;
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
default:
r = Z_STREAM_ERROR2;
that.bitb = b;
that.bitk = k;
z2.avail_in = n;
z2.total_in += p - z2.next_in_index;
z2.next_in_index = p;
that.write = q;
return that.inflate_flush(z2, r);
}
}
};
that.free = function(z2) {
that.reset(z2, null);
that.win = null;
hufts = null;
};
that.set_dictionary = function(d, start, n) {
that.win.set(d.subarray(start, start + n), 0);
that.read = that.write = n;
};
that.sync_point = function() {
return mode2 == LENS ? 1 : 0;
};
}
var PRESET_DICT2 = 32;
var Z_DEFLATED2 = 8;
var METHOD = 0;
var FLAG = 1;
var DICT4 = 2;
var DICT3 = 3;
var DICT2 = 4;
var DICT1 = 5;
var DICT0 = 6;
var BLOCKS = 7;
var DONE = 12;
var BAD = 13;
var mark = [0, 0, 255, 255];
function Inflate() {
const that = this;
that.mode = 0;
that.method = 0;
that.was = [0];
that.need = 0;
that.marker = 0;
that.wbits = 0;
function inflateReset(z) {
if (!z || !z.istate)
return Z_STREAM_ERROR2;
z.total_in = z.total_out = 0;
z.msg = null;
z.istate.mode = BLOCKS;
z.istate.blocks.reset(z, null);
return Z_OK2;
}
that.inflateEnd = function(z) {
if (that.blocks)
that.blocks.free(z);
that.blocks = null;
return Z_OK2;
};
that.inflateInit = function(z, w) {
z.msg = null;
that.blocks = null;
if (w < 8 || w > 15) {
that.inflateEnd(z);
return Z_STREAM_ERROR2;
}
that.wbits = w;
z.istate.blocks = new InfBlocks(z, 1 << w);
inflateReset(z);
return Z_OK2;
};
that.inflate = function(z, f) {
let r;
let b;
if (!z || !z.istate || !z.next_in)
return Z_STREAM_ERROR2;
const istate = z.istate;
f = f == Z_FINISH2 ? Z_BUF_ERROR2 : Z_OK2;
r = Z_BUF_ERROR2;
while (true) {
switch (istate.mode) {
case METHOD:
if (z.avail_in === 0)
return r;
r = f;
z.avail_in--;
z.total_in++;
if (((istate.method = z.read_byte(z.next_in_index++)) & 15) != Z_DEFLATED2) {
istate.mode = BAD;
z.msg = "unknown compression method";
istate.marker = 5;
break;
}
if ((istate.method >> 4) + 8 > istate.wbits) {
istate.mode = BAD;
z.msg = "invalid win size";
istate.marker = 5;
break;
}
istate.mode = FLAG;
/* falls through */
case FLAG:
if (z.avail_in === 0)
return r;
r = f;
z.avail_in--;
z.total_in++;
b = z.read_byte(z.next_in_index++) & 255;
if (((istate.method << 8) + b) % 31 !== 0) {
istate.mode = BAD;
z.msg = "incorrect header check";
istate.marker = 5;
break;
}
if ((b & PRESET_DICT2) === 0) {
istate.mode = BLOCKS;
break;
}
istate.mode = DICT4;
/* falls through */
case DICT4:
if (z.avail_in === 0)
return r;
r = f;
z.avail_in--;
z.total_in++;
istate.need = (z.read_byte(z.next_in_index++) & 255) << 24 & 4278190080;
istate.mode = DICT3;
/* falls through */
case DICT3:
if (z.avail_in === 0)
return r;
r = f;
z.avail_in--;
z.total_in++;
istate.need += (z.read_byte(z.next_in_index++) & 255) << 16 & 16711680;
istate.mode = DICT2;
/* falls through */
case DICT2:
if (z.avail_in === 0)
return r;
r = f;
z.avail_in--;
z.total_in++;
istate.need += (z.read_byte(z.next_in_index++) & 255) << 8 & 65280;
istate.mode = DICT1;
/* falls through */
case DICT1:
if (z.avail_in === 0)
return r;
r = f;
z.avail_in--;
z.total_in++;
istate.need += z.read_byte(z.next_in_index++) & 255;
istate.mode = DICT0;
return Z_NEED_DICT2;
case DICT0:
istate.mode = BAD;
z.msg = "need dictionary";
istate.marker = 0;
return Z_STREAM_ERROR2;
case BLOCKS:
r = istate.blocks.proc(z, r);
if (r == Z_DATA_ERROR2) {
istate.mode = BAD;
istate.marker = 0;
break;
}
if (r == Z_OK2) {
r = f;
}
if (r != Z_STREAM_END2) {
return r;
}
r = f;
istate.blocks.reset(z, istate.was);
istate.mode = DONE;
/* falls through */
case DONE:
z.avail_in = 0;
return Z_STREAM_END2;
case BAD:
return Z_DATA_ERROR2;
default:
return Z_STREAM_ERROR2;
}
}
};
that.inflateSetDictionary = function(z, dictionary, dictLength) {
let index = 0, length2 = dictLength;
if (!z || !z.istate || z.istate.mode != DICT0)
return Z_STREAM_ERROR2;
const istate = z.istate;
if (length2 >= 1 << istate.wbits) {
length2 = (1 << istate.wbits) - 1;
index = dictLength - length2;
}
istate.blocks.set_dictionary(dictionary, index, length2);
istate.mode = BLOCKS;
return Z_OK2;
};
that.inflateSync = function(z) {
let n;
let p;
let m;
let r, w;
if (!z || !z.istate)
return Z_STREAM_ERROR2;
const istate = z.istate;
if (istate.mode != BAD) {
istate.mode = BAD;
istate.marker = 0;
}
if ((n = z.avail_in) === 0)
return Z_BUF_ERROR2;
p = z.next_in_index;
m = istate.marker;
while (n !== 0 && m < 4) {
if (z.read_byte(p) == mark[m]) {
m++;
} else if (z.read_byte(p) !== 0) {
m = 0;
} else {
m = 4 - m;
}
p++;
n--;
}
z.total_in += p - z.next_in_index;
z.next_in_index = p;
z.avail_in = n;
istate.marker = m;
if (m != 4) {
return Z_DATA_ERROR2;
}
r = z.total_in;
w = z.total_out;
inflateReset(z);
z.total_in = r;
z.total_out = w;
istate.mode = BLOCKS;
return Z_OK2;
};
that.inflateSyncPoint = function(z) {
if (!z || !z.istate || !z.istate.blocks)
return Z_STREAM_ERROR2;
return z.istate.blocks.sync_point();
};
}
function ZStream2() {
}
ZStream2.prototype = {
inflateInit(bits) {
const that = this;
that.istate = new Inflate();
if (!bits)
bits = MAX_BITS2;
return that.istate.inflateInit(that, bits);
},
inflate(f) {
const that = this;
if (!that.istate)
return Z_STREAM_ERROR2;
return that.istate.inflate(that, f);
},
inflateEnd() {
const that = this;
if (!that.istate)
return Z_STREAM_ERROR2;
const ret = that.istate.inflateEnd(that);
that.istate = null;
return ret;
},
inflateSync() {
const that = this;
if (!that.istate)
return Z_STREAM_ERROR2;
return that.istate.inflateSync(that);
},
inflateSetDictionary(dictionary, dictLength) {
const that = this;
if (!that.istate)
return Z_STREAM_ERROR2;
return that.istate.inflateSetDictionary(that, dictionary, dictLength);
},
read_byte(start) {
const that = this;
return that.next_in[start];
},
read_buf(start, size) {
const that = this;
return that.next_in.subarray(start, start + size);
}
};
function ZipInflate(options) {
const that = this;
const z = new ZStream2();
const bufsize = options && options.chunkSize ? Math.floor(options.chunkSize * 2) : 128 * 1024;
const flush = Z_NO_FLUSH2;
const buf = new Uint8Array(bufsize);
let nomoreinput = false;
z.inflateInit();
z.next_out = buf;
that.append = function(data, onprogress) {
const buffers = [];
let err, array, lastIndex = 0, bufferIndex = 0, bufferSize = 0;
if (data.length === 0)
return;
z.next_in_index = 0;
z.next_in = data;
z.avail_in = data.length;
do {
z.next_out_index = 0;
z.avail_out = bufsize;
if (z.avail_in === 0 && !nomoreinput) {
z.next_in_index = 0;
nomoreinput = true;
}
err = z.inflate(flush);
if (nomoreinput && err === Z_BUF_ERROR2) {
if (z.avail_in !== 0)
throw new Error("inflating: bad input");
} else if (err !== Z_OK2 && err !== Z_STREAM_END2)
throw new Error("inflating: " + z.msg);
if ((nomoreinput || err === Z_STREAM_END2) && z.avail_in === data.length)
throw new Error("inflating: bad input");
if (z.next_out_index)
if (z.next_out_index === bufsize)
buffers.push(new Uint8Array(buf));
else
buffers.push(buf.subarray(0, z.next_out_index));
bufferSize += z.next_out_index;
if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
onprogress(z.next_in_index);
lastIndex = z.next_in_index;
}
} while (z.avail_in > 0 || z.avail_out === 0);
if (buffers.length > 1) {
array = new Uint8Array(bufferSize);
buffers.forEach(function(chunk) {
array.set(chunk, bufferIndex);
bufferIndex += chunk.length;
});
} else {
array = buffers[0] ? new Uint8Array(buffers[0]) : new Uint8Array();
}
return array;
};
that.flush = function() {
z.inflateEnd();
};
}
// node_modules/@zip.js/zip.js/lib/core/configuration.js
var import_InlineWorkers970 = __toESM(require_InlineWorkers(), 1);
// node_modules/@zip.js/zip.js/lib/core/constants.js
var import_InlineWorkers968 = __toESM(require_InlineWorkers(), 1);
var MAX_32_BITS = 4294967295;
var MAX_16_BITS = 65535;
var COMPRESSION_METHOD_DEFLATE = 8;
var COMPRESSION_METHOD_DEFLATE_64 = 9;
var COMPRESSION_METHOD_STORE = 0;
var COMPRESSION_METHOD_AES = 99;
var LOCAL_FILE_HEADER_SIGNATURE = 67324752;
var SPLIT_ZIP_FILE_SIGNATURE = 134695760;
var DATA_DESCRIPTOR_RECORD_SIGNATURE = SPLIT_ZIP_FILE_SIGNATURE;
var CENTRAL_FILE_HEADER_SIGNATURE = 33639248;
var END_OF_CENTRAL_DIR_SIGNATURE = 101010256;
var ZIP64_END_OF_CENTRAL_DIR_SIGNATURE = 101075792;
var ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE = 117853008;
var END_OF_CENTRAL_DIR_LENGTH = 22;
var ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH = 20;
var ZIP64_END_OF_CENTRAL_DIR_LENGTH = 56;
var ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH = END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LENGTH;
var DATA_DESCRIPTOR_RECORD_LENGTH = 12;
var DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH = 20;
var DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH = 4;
var EXTRAFIELD_TYPE_ZIP64 = 1;
var EXTRAFIELD_TYPE_AES = 39169;
var EXTRAFIELD_TYPE_NTFS = 10;
var EXTRAFIELD_TYPE_NTFS_TAG1 = 1;
var EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP = 21589;
var EXTRAFIELD_TYPE_UNICODE_PATH = 28789;
var EXTRAFIELD_TYPE_UNICODE_COMMENT = 25461;
var EXTRAFIELD_TYPE_USDZ = 6534;
var BITFLAG_ENCRYPTED = 1;
var BITFLAG_LEVEL = 6;
var BITFLAG_LEVEL_MAX_MASK = 2;
var BITFLAG_LEVEL_FAST_MASK = 4;
var BITFLAG_LEVEL_SUPER_FAST_MASK = 6;
var BITFLAG_DATA_DESCRIPTOR = 8;
var BITFLAG_LANG_ENCODING_FLAG = 2048;
var FILE_ATTR_MSDOS_DIR_MASK = 16;
var FILE_ATTR_UNIX_TYPE_MASK = 61440;
var FILE_ATTR_UNIX_TYPE_DIR = 16384;
var FILE_ATTR_UNIX_EXECUTABLE_MASK = 73;
var FILE_ATTR_UNIX_DEFAULT_MASK = 420;
var VERSION_DEFLATE = 20;
var VERSION_ZIP64 = 45;
var VERSION_AES = 51;
var DIRECTORY_SIGNATURE = "/";
var HEADER_SIZE2 = 30;
var HEADER_OFFSET_SIGNATURE = 10;
var HEADER_OFFSET_COMPRESSED_SIZE = 14;
var HEADER_OFFSET_UNCOMPRESSED_SIZE = 18;
var MAX_DATE = new Date(2107, 11, 31);
var MIN_DATE = new Date(1980, 0, 1);
var UNDEFINED_VALUE = void 0;
var UNDEFINED_TYPE = "undefined";
var FUNCTION_TYPE = "function";
// node_modules/@zip.js/zip.js/lib/core/streams/stream-adapter.js
var import_InlineWorkers969 = __toESM(require_InlineWorkers(), 1);
var StreamAdapter = class {
constructor(Codec) {
return class extends TransformStream {
constructor(_format, options) {
const codec2 = new Codec(options);
super({
transform(chunk, controller) {
controller.enqueue(codec2.append(chunk));
},
flush(controller) {
const chunk = codec2.flush();
if (chunk) {
controller.enqueue(chunk);
}
}
});
}
};
}
};
// node_modules/@zip.js/zip.js/lib/core/configuration.js
var MINIMUM_CHUNK_SIZE = 64;
var maxWorkers = 2;
try {
if (typeof navigator != UNDEFINED_TYPE && navigator.hardwareConcurrency) {
maxWorkers = navigator.hardwareConcurrency;
}
} catch (_) {
}
var DEFAULT_CONFIGURATION = {
chunkSize: 512 * 1024,
maxWorkers,
terminateWorkerTimeout: 5e3,
useWebWorkers: true,
useCompressionStream: true,
workerScripts: UNDEFINED_VALUE,
CompressionStreamNative: typeof CompressionStream != UNDEFINED_TYPE && CompressionStream,
DecompressionStreamNative: typeof DecompressionStream != UNDEFINED_TYPE && DecompressionStream
};
var config = Object.assign({}, DEFAULT_CONFIGURATION);
function getConfiguration() {
return config;
}
function getChunkSize(config2) {
return Math.max(config2.chunkSize, MINIMUM_CHUNK_SIZE);
}
function configure(configuration) {
const {
baseURL,
chunkSize,
maxWorkers: maxWorkers2,
terminateWorkerTimeout,
useCompressionStream,
useWebWorkers,
Deflate: Deflate2,
Inflate: Inflate2,
CompressionStream: CompressionStream2,
DecompressionStream: DecompressionStream2,
workerScripts
} = configuration;
setIfDefined("baseURL", baseURL);
setIfDefined("chunkSize", chunkSize);
setIfDefined("maxWorkers", maxWorkers2);
setIfDefined("terminateWorkerTimeout", terminateWorkerTimeout);
setIfDefined("useCompressionStream", useCompressionStream);
setIfDefined("useWebWorkers", useWebWorkers);
if (Deflate2) {
config.CompressionStream = new StreamAdapter(Deflate2);
}
if (Inflate2) {
config.DecompressionStream = new StreamAdapter(Inflate2);
}
setIfDefined("CompressionStream", CompressionStream2);
setIfDefined("DecompressionStream", DecompressionStream2);
if (workerScripts !== UNDEFINED_VALUE) {
const { deflate, inflate } = workerScripts;
if (deflate || inflate) {
if (!config.workerScripts) {
config.workerScripts = {};
}
}
if (deflate) {
if (!Array.isArray(deflate)) {
throw new Error("workerScripts.deflate must be an array");
}
config.workerScripts.deflate = deflate;
}
if (inflate) {
if (!Array.isArray(inflate)) {
throw new Error("workerScripts.inflate must be an array");
}
config.workerScripts.inflate = inflate;
}
}
}
function setIfDefined(propertyName, propertyValue) {
if (propertyValue !== UNDEFINED_VALUE) {
config[propertyName] = propertyValue;
}
}
// node_modules/@zip.js/zip.js/lib/core/util/default-mime-type.js
var import_InlineWorkers971 = __toESM(require_InlineWorkers(), 1);
// node_modules/@zip.js/zip.js/lib/core/codec-pool.js
var import_InlineWorkers982 = __toESM(require_InlineWorkers(), 1);
// node_modules/@zip.js/zip.js/lib/core/streams/codec-stream.js
var import_InlineWorkers980 = __toESM(require_InlineWorkers(), 1);
// node_modules/@zip.js/zip.js/lib/core/streams/zip-entry-stream.js
var import_InlineWorkers979 = __toESM(require_InlineWorkers(), 1);
// node_modules/@zip.js/zip.js/lib/core/streams/crc32-stream.js
var import_InlineWorkers973 = __toESM(require_InlineWorkers(), 1);
// node_modules/@zip.js/zip.js/lib/core/streams/codecs/crc32.js
var import_InlineWorkers972 = __toESM(require_InlineWorkers(), 1);
var table = [];
for (let i = 0; i < 256; i++) {
let t = i;
for (let j = 0; j < 8; j++) {
if (t & 1) {
t = t >>> 1 ^ 3988292384;
} else {
t = t >>> 1;
}
}
table[i] = t;
}
var Crc32 = class {
constructor(crc) {
this.crc = crc || -1;
}
append(data) {
let crc = this.crc | 0;
for (let offset = 0, length2 = data.length | 0; offset < length2; offset++) {
crc = crc >>> 8 ^ table[(crc ^ data[offset]) & 255];
}
this.crc = crc;
}
get() {
return ~this.crc;
}
};
// node_modules/@zip.js/zip.js/lib/core/streams/crc32-stream.js
var Crc32Stream = class extends TransformStream {
constructor() {
let stream;
const crc32 = new Crc32();
super({
transform(chunk, controller) {
crc32.append(chunk);
controller.enqueue(chunk);
},
flush() {
const value = new Uint8Array(4);
const dataView = new DataView(value.buffer);
dataView.setUint32(0, crc32.get());
stream.value = value;
}
});
stream = this;
}
};
// node_modules/@zip.js/zip.js/lib/core/streams/aes-crypto-stream.js
var import_InlineWorkers977 = __toESM(require_InlineWorkers(), 1);
// node_modules/@zip.js/zip.js/lib/core/util/encode-text.js
var import_InlineWorkers974 = __toESM(require_InlineWorkers(), 1);
function encodeText(value) {
if (typeof TextEncoder == UNDEFINED_TYPE) {
value = unescape(encodeURIComponent(value));
const result = new Uint8Array(value.length);
for (let i = 0; i < result.length; i++) {
result[i] = value.charCodeAt(i);
}
return result;
} else {
return new TextEncoder().encode(value);
}
}
// node_modules/@zip.js/zip.js/lib/core/streams/codecs/sjcl.js
var import_InlineWorkers975 = __toESM(require_InlineWorkers(), 1);
var bitArray = {
/**
* Concatenate two bit arrays.
* @param {bitArray} a1 The first array.
* @param {bitArray} a2 The second array.
* @return {bitArray} The concatenation of a1 and a2.
*/
concat(a1, a22) {
if (a1.length === 0 || a22.length === 0) {
return a1.concat(a22);
}
const last = a1[a1.length - 1], shift = bitArray.getPartial(last);
if (shift === 32) {
return a1.concat(a22);
} else {
return bitArray._shiftRight(a22, shift, last | 0, a1.slice(0, a1.length - 1));
}
},
/**
* Find the length of an array of bits.
* @param {bitArray} a The array.
* @return {Number} The length of a, in bits.
*/
bitLength(a3) {
const l = a3.length;
if (l === 0) {
return 0;
}
const x = a3[l - 1];
return (l - 1) * 32 + bitArray.getPartial(x);
},
/**
* Truncate an array.
* @param {bitArray} a The array.
* @param {Number} len The length to truncate to, in bits.
* @return {bitArray} A new array, truncated to len bits.
*/
clamp(a3, len) {
if (a3.length * 32 < len) {
return a3;
}
a3 = a3.slice(0, Math.ceil(len / 32));
const l = a3.length;
len = len & 31;
if (l > 0 && len) {
a3[l - 1] = bitArray.partial(len, a3[l - 1] & 2147483648 >> len - 1, 1);
}
return a3;
},
/**
* Make a partial word for a bit array.
* @param {Number} len The number of bits in the word.
* @param {Number} x The bits.
* @param {Number} [_end=0] Pass 1 if x has already been shifted to the high side.
* @return {Number} The partial word.
*/
partial(len, x, _end) {
if (len === 32) {
return x;
}
return (_end ? x | 0 : x << 32 - len) + len * 1099511627776;
},
/**
* Get the number of bits used by a partial word.
* @param {Number} x The partial word.
* @return {Number} The number of bits used by the partial word.
*/
getPartial(x) {
return Math.round(x / 1099511627776) || 32;
},
/** Shift an array right.
* @param {bitArray} a The array to shift.
* @param {Number} shift The number of bits to shift.
* @param {Number} [carry=0] A byte to carry in
* @param {bitArray} [out=[]] An array to prepend to the output.
* @private
*/
_shiftRight(a3, shift, carry, out) {
if (out === void 0) {
out = [];
}
for (; shift >= 32; shift -= 32) {
out.push(carry);
carry = 0;
}
if (shift === 0) {
return out.concat(a3);
}
for (let i = 0; i < a3.length; i++) {
out.push(carry | a3[i] >>> shift);
carry = a3[i] << 32 - shift;
}
const last2 = a3.length ? a3[a3.length - 1] : 0;
const shift2 = bitArray.getPartial(last2);
out.push(bitArray.partial(shift + shift2 & 31, shift + shift2 > 32 ? carry : out.pop(), 1));
return out;
}
};
var codec = {
bytes: {
/** Convert from a bitArray to an array of bytes. */
fromBits(arr) {
const bl = bitArray.bitLength(arr);
const byteLength = bl / 8;
const out = new Uint8Array(byteLength);
let tmp2;
for (let i = 0; i < byteLength; i++) {
if ((i & 3) === 0) {
tmp2 = arr[i / 4];
}
out[i] = tmp2 >>> 24;
tmp2 <<= 8;
}
return out;
},
/** Convert from an array of bytes to a bitArray. */
toBits(bytes) {
const out = [];
let i;
let tmp2 = 0;
for (i = 0; i < bytes.length; i++) {
tmp2 = tmp2 << 8 | bytes[i];
if ((i & 3) === 3) {
out.push(tmp2);
tmp2 = 0;
}
}
if (i & 3) {
out.push(bitArray.partial(8 * (i & 3), tmp2));
}
return out;
}
}
};
var hash = {};
hash.sha1 = class {
constructor(hash2) {
const sha1 = this;
sha1.blockSize = 512;
sha1._init = [1732584193, 4023233417, 2562383102, 271733878, 3285377520];
sha1._key = [1518500249, 1859775393, 2400959708, 3395469782];
if (hash2) {
sha1._h = hash2._h.slice(0);
sha1._buffer = hash2._buffer.slice(0);
sha1._length = hash2._length;
} else {
sha1.reset();
}
}
/**
* Reset the hash state.
* @return this
*/
reset() {
const sha1 = this;
sha1._h = sha1._init.slice(0);
sha1._buffer = [];
sha1._length = 0;
return sha1;
}
/**
* Input several words to the hash.
* @param {bitArray|String} data the data to hash.
* @return this
*/
update(data) {
const sha1 = this;
if (typeof data === "string") {
data = codec.utf8String.toBits(data);
}
const b = sha1._buffer = bitArray.concat(sha1._buffer, data);
const ol = sha1._length;
const nl = sha1._length = ol + bitArray.bitLength(data);
if (nl > 9007199254740991) {
throw new Error("Cannot hash more than 2^53 - 1 bits");
}
const c = new Uint32Array(b);
let j = 0;
for (let i = sha1.blockSize + ol - (sha1.blockSize + ol & sha1.blockSize - 1); i <= nl; i += sha1.blockSize) {
sha1._block(c.subarray(16 * j, 16 * (j + 1)));
j += 1;
}
b.splice(0, 16 * j);
return sha1;
}
/**
* Complete hashing and output the hash value.
* @return {bitArray} The hash value, an array of 5 big-endian words. TODO
*/
finalize() {
const sha1 = this;
let b = sha1._buffer;
const h = sha1._h;
b = bitArray.concat(b, [bitArray.partial(1, 1)]);
for (let i = b.length + 2; i & 15; i++) {
b.push(0);
}
b.push(Math.floor(sha1._length / 4294967296));
b.push(sha1._length | 0);
while (b.length) {
sha1._block(b.splice(0, 16));
}
sha1.reset();
return h;
}
/**
* The SHA-1 logical functions f(0), f(1), ..., f(79).
* @private
*/
_f(t, b, c, d) {
if (t <= 19) {
return b & c | ~b & d;
} else if (t <= 39) {
return b ^ c ^ d;
} else if (t <= 59) {
return b & c | b & d | c & d;
} else if (t <= 79) {
return b ^ c ^ d;
}
}
/**
* Circular left-shift operator.
* @private
*/
_S(n, x) {
return x << n | x >>> 32 - n;
}
/**
* Perform one cycle of SHA-1.
* @param {Uint32Array|bitArray} words one block of words.
* @private
*/
_block(words) {
const sha1 = this;
const h = sha1._h;
const w = Array(80);
for (let j = 0; j < 16; j++) {
w[j] = words[j];
}
let a3 = h[0];
let b = h[1];
let c = h[2];
let d = h[3];
let e = h[4];
for (let t = 0; t <= 79; t++) {
if (t >= 16) {
w[t] = sha1._S(1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]);
}
const tmp2 = sha1._S(5, a3) + sha1._f(t, b, c, d) + e + w[t] + sha1._key[Math.floor(t / 20)] | 0;
e = d;
d = c;
c = sha1._S(30, b);
b = a3;
a3 = tmp2;
}
h[0] = h[0] + a3 | 0;
h[1] = h[1] + b | 0;
h[2] = h[2] + c | 0;
h[3] = h[3] + d | 0;
h[4] = h[4] + e | 0;
}
};
var cipher = {};
cipher.aes = class {
constructor(key) {
const aes = this;
aes._tables = [[[], [], [], [], []], [[], [], [], [], []]];
if (!aes._tables[0][0][0]) {
aes._precompute();
}
const sbox = aes._tables[0][4];
const decTable = aes._tables[1];
const keyLen = key.length;
let i, encKey, decKey, rcon = 1;
if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {
throw new Error("invalid aes key size");
}
aes._key = [encKey = key.slice(0), decKey = []];
for (i = keyLen; i < 4 * keyLen + 28; i++) {
let tmp2 = encKey[i - 1];
if (i % keyLen === 0 || keyLen === 8 && i % keyLen === 4) {
tmp2 = sbox[tmp2 >>> 24] << 24 ^ sbox[tmp2 >> 16 & 255] << 16 ^ sbox[tmp2 >> 8 & 255] << 8 ^ sbox[tmp2 & 255];
if (i % keyLen === 0) {
tmp2 = tmp2 << 8 ^ tmp2 >>> 24 ^ rcon << 24;
rcon = rcon << 1 ^ (rcon >> 7) * 283;
}
}
encKey[i] = encKey[i - keyLen] ^ tmp2;
}
for (let j = 0; i; j++, i--) {
const tmp2 = encKey[j & 3 ? i : i - 4];
if (i <= 4 || j < 4) {
decKey[j] = tmp2;
} else {
decKey[j] = decTable[0][sbox[tmp2 >>> 24]] ^ decTable[1][sbox[tmp2 >> 16 & 255]] ^ decTable[2][sbox[tmp2 >> 8 & 255]] ^ decTable[3][sbox[tmp2 & 255]];
}
}
}
// public
/* Something like this might appear here eventually
name: "AES",
blockSize: 4,
keySizes: [4,6,8],
*/
/**
* Encrypt an array of 4 big-endian words.
* @param {Array} data The plaintext.
* @return {Array} The ciphertext.
*/
encrypt(data) {
return this._crypt(data, 0);
}
/**
* Decrypt an array of 4 big-endian words.
* @param {Array} data The ciphertext.
* @return {Array} The plaintext.
*/
decrypt(data) {
return this._crypt(data, 1);
}
/**
* Expand the S-box tables.
*
* @private
*/
_precompute() {
const encTable = this._tables[0];
const decTable = this._tables[1];
const sbox = encTable[4];
const sboxInv = decTable[4];
const d = [];
const th = [];
let xInv, x2, x4, x8;
for (let i = 0; i < 256; i++) {
th[(d[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i;
}
for (let x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {
let s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4;
s = s >> 8 ^ s & 255 ^ 99;
sbox[x] = s;
sboxInv[s] = x;
x8 = d[x4 = d[x2 = d[x]]];
let tDec = x8 * 16843009 ^ x4 * 65537 ^ x2 * 257 ^ x * 16843008;
let tEnc = d[s] * 257 ^ s * 16843008;
for (let i = 0; i < 4; i++) {
encTable[i][x] = tEnc = tEnc << 24 ^ tEnc >>> 8;
decTable[i][s] = tDec = tDec << 24 ^ tDec >>> 8;
}
}
for (let i = 0; i < 5; i++) {
encTable[i] = encTable[i].slice(0);
decTable[i] = decTable[i].slice(0);
}
}
/**
* Encryption and decryption core.
* @param {Array} input Four words to be encrypted or decrypted.
* @param dir The direction, 0 for encrypt and 1 for decrypt.
* @return {Array} The four encrypted or decrypted words.
* @private
*/
_crypt(input, dir) {
if (input.length !== 4) {
throw new Error("invalid aes block size");
}
const key = this._key[dir];
const nInnerRounds = key.length / 4 - 2;
const out = [0, 0, 0, 0];
const table2 = this._tables[dir];
const t0 = table2[0];
const t1 = table2[1];
const t2 = table2[2];
const t3 = table2[3];
const sbox = table2[4];
let a3 = input[0] ^ key[0];
let b = input[dir ? 3 : 1] ^ key[1];
let c = input[2] ^ key[2];
let d = input[dir ? 1 : 3] ^ key[3];
let kIndex = 4;
let a22, b2, c22;
for (let i = 0; i < nInnerRounds; i++) {
a22 = t0[a3 >>> 24] ^ t1[b >> 16 & 255] ^ t2[c >> 8 & 255] ^ t3[d & 255] ^ key[kIndex];
b2 = t0[b >>> 24] ^ t1[c >> 16 & 255] ^ t2[d >> 8 & 255] ^ t3[a3 & 255] ^ key[kIndex + 1];
c22 = t0[c >>> 24] ^ t1[d >> 16 & 255] ^ t2[a3 >> 8 & 255] ^ t3[b & 255] ^ key[kIndex + 2];
d = t0[d >>> 24] ^ t1[a3 >> 16 & 255] ^ t2[b >> 8 & 255] ^ t3[c & 255] ^ key[kIndex + 3];
kIndex += 4;
a3 = a22;
b = b2;
c = c22;
}
for (let i = 0; i < 4; i++) {
out[dir ? 3 & -i : i] = sbox[a3 >>> 24] << 24 ^ sbox[b >> 16 & 255] << 16 ^ sbox[c >> 8 & 255] << 8 ^ sbox[d & 255] ^ key[kIndex++];
a22 = a3;
a3 = b;
b = c;
c = d;
d = a22;
}
return out;
}
};
var random = {
/**
* Generate random words with pure js, cryptographically not as strong & safe as native implementation.
* @param {TypedArray} typedArray The array to fill.
* @return {TypedArray} The random values.
*/
getRandomValues(typedArray) {
const words = new Uint32Array(typedArray.buffer);
const r = (m_w) => {
let m_z = 987654321;
const mask = 4294967295;
return function() {
m_z = 36969 * (m_z & 65535) + (m_z >> 16) & mask;
m_w = 18e3 * (m_w & 65535) + (m_w >> 16) & mask;
const result = ((m_z << 16) + m_w & mask) / 4294967296 + 0.5;
return result * (Math.random() > 0.5 ? 1 : -1);
};
};
for (let i = 0, rcache; i < typedArray.length; i += 4) {
const _r = r((rcache || Math.random()) * 4294967296);
rcache = _r() * 987654071;
words[i / 4] = _r() * 4294967296 | 0;
}
return typedArray;
}
};
var mode = {};
mode.ctrGladman = class {
constructor(prf, iv) {
this._prf = prf;
this._initIv = iv;
this._iv = iv;
}
reset() {
this._iv = this._initIv;
}
/** Input some data to calculate.
* @param {bitArray} data the data to process, it must be intergral multiple of 128 bits unless it's the last.
*/
update(data) {
return this.calculate(this._prf, data, this._iv);
}
incWord(word) {
if ((word >> 24 & 255) === 255) {
let b1 = word >> 16 & 255;
let b2 = word >> 8 & 255;
let b3 = word & 255;
if (b1 === 255) {
b1 = 0;
if (b2 === 255) {
b2 = 0;
if (b3 === 255) {
b3 = 0;
} else {
++b3;
}
} else {
++b2;
}
} else {
++b1;
}
word = 0;
word += b1 << 16;
word += b2 << 8;
word += b3;
} else {
word += 1 << 24;
}
return word;
}
incCounter(counter) {
if ((counter[0] = this.incWord(counter[0])) === 0) {
counter[1] = this.incWord(counter[1]);
}
}
calculate(prf, data, iv) {
let l;
if (!(l = data.length)) {
return [];
}
const bl = bitArray.bitLength(data);
for (let i = 0; i < l; i += 4) {
this.incCounter(iv);
const e = prf.encrypt(iv);
data[i] ^= e[0];
data[i + 1] ^= e[1];
data[i + 2] ^= e[2];
data[i + 3] ^= e[3];
}
return bitArray.clamp(data, bl);
}
};
var misc = {
importKey(password) {
return new misc.hmacSha1(codec.bytes.toBits(password));
},
pbkdf2(prf, salt, count, length2) {
count = count || 1e4;
if (length2 < 0 || count < 0) {
throw new Error("invalid params to pbkdf2");
}
const byteLength = (length2 >> 5) + 1 << 2;
let u3, ui, i, j, k;
const arrayBuffer = new ArrayBuffer(byteLength);
const out = new DataView(arrayBuffer);
let outLength = 0;
const b = bitArray;
salt = codec.bytes.toBits(salt);
for (k = 1; outLength < (byteLength || 1); k++) {
u3 = ui = prf.encrypt(b.concat(salt, [k]));
for (i = 1; i < count; i++) {
ui = prf.encrypt(ui);
for (j = 0; j < ui.length; j++) {
u3[j] ^= ui[j];
}
}
for (i = 0; outLength < (byteLength || 1) && i < u3.length; i++) {
out.setInt32(outLength, u3[i]);
outLength += 4;
}
}
return arrayBuffer.slice(0, length2 / 8);
}
};
misc.hmacSha1 = class {
constructor(key) {
const hmac = this;
const Hash = hmac._hash = hash.sha1;
const exKey = [[], []];
hmac._baseHash = [new Hash(), new Hash()];
const bs = hmac._baseHash[0].blockSize / 32;
if (key.length > bs) {
key = new Hash().update(key).finalize();
}
for (let i = 0; i < bs; i++) {
exKey[0][i] = key[i] ^ 909522486;
exKey[1][i] = key[i] ^ 1549556828;
}
hmac._baseHash[0].update(exKey[0]);
hmac._baseHash[1].update(exKey[1]);
hmac._resultHash = new Hash(hmac._baseHash[0]);
}
reset() {
const hmac = this;
hmac._resultHash = new hmac._hash(hmac._baseHash[0]);
hmac._updated = false;
}
update(data) {
const hmac = this;
hmac._updated = true;
hmac._resultHash.update(data);
}
digest() {
const hmac = this;
const w = hmac._resultHash.finalize();
const result = new hmac._hash(hmac._baseHash[1]).update(w).finalize();
hmac.reset();
return result;
}
encrypt(data) {
if (!this._updated) {
this.update(data);
return this.digest(data);
} else {
throw new Error("encrypt on already updated hmac called!");
}
}
};
// node_modules/@zip.js/zip.js/lib/core/streams/common-crypto.js
var import_InlineWorkers976 = __toESM(require_InlineWorkers(), 1);
var GET_RANDOM_VALUES_SUPPORTED = typeof crypto != UNDEFINED_TYPE && typeof crypto.getRandomValues == FUNCTION_TYPE;
var ERR_INVALID_PASSWORD = "Invalid password";
var ERR_INVALID_SIGNATURE = "Invalid signature";
var ERR_ABORT_CHECK_PASSWORD = "zipjs-abort-check-password";
function getRandomValues2(array) {
if (GET_RANDOM_VALUES_SUPPORTED) {
return crypto.getRandomValues(array);
} else {
return random.getRandomValues(array);
}
}
// node_modules/@zip.js/zip.js/lib/core/streams/aes-crypto-stream.js
var BLOCK_LENGTH = 16;
var RAW_FORMAT = "raw";
var PBKDF2_ALGORITHM = { name: "PBKDF2" };
var HASH_ALGORITHM = { name: "HMAC" };
var HASH_FUNCTION = "SHA-1";
var BASE_KEY_ALGORITHM = Object.assign({ hash: HASH_ALGORITHM }, PBKDF2_ALGORITHM);
var DERIVED_BITS_ALGORITHM = Object.assign({ iterations: 1e3, hash: { name: HASH_FUNCTION } }, PBKDF2_ALGORITHM);
var DERIVED_BITS_USAGE = ["deriveBits"];
var SALT_LENGTH = [8, 12, 16];
var KEY_LENGTH = [16, 24, 32];
var SIGNATURE_LENGTH = 10;
var COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
var CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
var subtle = CRYPTO_API_SUPPORTED && crypto.subtle;
var SUBTLE_API_SUPPORTED = CRYPTO_API_SUPPORTED && typeof subtle != UNDEFINED_TYPE;
var codecBytes = codec.bytes;
var Aes = cipher.aes;
var CtrGladman = mode.ctrGladman;
var HmacSha1 = misc.hmacSha1;
var IMPORT_KEY_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof subtle.importKey == FUNCTION_TYPE;
var DERIVE_BITS_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && typeof subtle.deriveBits == FUNCTION_TYPE;
var AESDecryptionStream = class extends TransformStream {
constructor({ password, rawPassword, signed, encryptionStrength, checkPasswordOnly }) {
super({
start() {
Object.assign(this, {
ready: new Promise((resolve2) => this.resolveReady = resolve2),
password: encodePassword(password, rawPassword),
signed,
strength: encryptionStrength - 1,
pending: new Uint8Array()
});
},
async transform(chunk, controller) {
const aesCrypto = this;
const {
password: password2,
strength,
resolveReady,
ready
} = aesCrypto;
if (password2) {
await createDecryptionKeys(aesCrypto, strength, password2, subarray(chunk, 0, SALT_LENGTH[strength] + 2));
chunk = subarray(chunk, SALT_LENGTH[strength] + 2);
if (checkPasswordOnly) {
controller.error(new Error(ERR_ABORT_CHECK_PASSWORD));
} else {
resolveReady();
}
} else {
await ready;
}
const output = new Uint8Array(chunk.length - SIGNATURE_LENGTH - (chunk.length - SIGNATURE_LENGTH) % BLOCK_LENGTH);
controller.enqueue(append(aesCrypto, chunk, output, 0, SIGNATURE_LENGTH, true));
},
async flush(controller) {
const {
signed: signed2,
ctr,
hmac,
pending,
ready
} = this;
if (hmac && ctr) {
await ready;
const chunkToDecrypt = subarray(pending, 0, pending.length - SIGNATURE_LENGTH);
const originalSignature = subarray(pending, pending.length - SIGNATURE_LENGTH);
let decryptedChunkArray = new Uint8Array();
if (chunkToDecrypt.length) {
const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
hmac.update(encryptedChunk);
const decryptedChunk = ctr.update(encryptedChunk);
decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
}
if (signed2) {
const signature = subarray(fromBits(codecBytes, hmac.digest()), 0, SIGNATURE_LENGTH);
for (let indexSignature = 0; indexSignature < SIGNATURE_LENGTH; indexSignature++) {
if (signature[indexSignature] != originalSignature[indexSignature]) {
throw new Error(ERR_INVALID_SIGNATURE);
}
}
}
controller.enqueue(decryptedChunkArray);
}
}
});
}
};
var AESEncryptionStream = class extends TransformStream {
constructor({ password, rawPassword, encryptionStrength }) {
let stream;
super({
start() {
Object.assign(this, {
ready: new Promise((resolve2) => this.resolveReady = resolve2),
password: encodePassword(password, rawPassword),
strength: encryptionStrength - 1,
pending: new Uint8Array()
});
},
async transform(chunk, controller) {
const aesCrypto = this;
const {
password: password2,
strength,
resolveReady,
ready
} = aesCrypto;
let preamble = new Uint8Array();
if (password2) {
preamble = await createEncryptionKeys(aesCrypto, strength, password2);
resolveReady();
} else {
await ready;
}
const output = new Uint8Array(preamble.length + chunk.length - chunk.length % BLOCK_LENGTH);
output.set(preamble, 0);
controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0));
},
async flush(controller) {
const {
ctr,
hmac,
pending,
ready
} = this;
if (hmac && ctr) {
await ready;
let encryptedChunkArray = new Uint8Array();
if (pending.length) {
const encryptedChunk = ctr.update(toBits(codecBytes, pending));
hmac.update(encryptedChunk);
encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
}
stream.signature = fromBits(codecBytes, hmac.digest()).slice(0, SIGNATURE_LENGTH);
controller.enqueue(concat(encryptedChunkArray, stream.signature));
}
}
});
stream = this;
}
};
function append(aesCrypto, input, output, paddingStart, paddingEnd, verifySignature) {
const {
ctr,
hmac,
pending
} = aesCrypto;
const inputLength = input.length - paddingEnd;
if (pending.length) {
input = concat(pending, input);
output = expand(output, inputLength - inputLength % BLOCK_LENGTH);
}
let offset;
for (offset = 0; offset <= inputLength - BLOCK_LENGTH; offset += BLOCK_LENGTH) {
const inputChunk = toBits(codecBytes, subarray(input, offset, offset + BLOCK_LENGTH));
if (verifySignature) {
hmac.update(inputChunk);
}
const outputChunk = ctr.update(inputChunk);
if (!verifySignature) {
hmac.update(outputChunk);
}
output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
}
aesCrypto.pending = subarray(input, offset);
return output;
}
async function createDecryptionKeys(decrypt2, strength, password, preamble) {
const passwordVerificationKey = await createKeys(decrypt2, strength, password, subarray(preamble, 0, SALT_LENGTH[strength]));
const passwordVerification = subarray(preamble, SALT_LENGTH[strength]);
if (passwordVerificationKey[0] != passwordVerification[0] || passwordVerificationKey[1] != passwordVerification[1]) {
throw new Error(ERR_INVALID_PASSWORD);
}
}
async function createEncryptionKeys(encrypt2, strength, password) {
const salt = getRandomValues2(new Uint8Array(SALT_LENGTH[strength]));
const passwordVerification = await createKeys(encrypt2, strength, password, salt);
return concat(salt, passwordVerification);
}
async function createKeys(aesCrypto, strength, password, salt) {
aesCrypto.password = null;
const baseKey = await importKey(RAW_FORMAT, password, BASE_KEY_ALGORITHM, false, DERIVED_BITS_USAGE);
const derivedBits = await deriveBits(Object.assign({ salt }, DERIVED_BITS_ALGORITHM), baseKey, 8 * (KEY_LENGTH[strength] * 2 + 2));
const compositeKey = new Uint8Array(derivedBits);
const key = toBits(codecBytes, subarray(compositeKey, 0, KEY_LENGTH[strength]));
const authentication = toBits(codecBytes, subarray(compositeKey, KEY_LENGTH[strength], KEY_LENGTH[strength] * 2));
const passwordVerification = subarray(compositeKey, KEY_LENGTH[strength] * 2);
Object.assign(aesCrypto, {
keys: {
key,
authentication,
passwordVerification
},
ctr: new CtrGladman(new Aes(key), Array.from(COUNTER_DEFAULT_VALUE)),
hmac: new HmacSha1(authentication)
});
return passwordVerification;
}
async function importKey(format, password, algorithm, extractable, keyUsages) {
if (IMPORT_KEY_SUPPORTED) {
try {
return await subtle.importKey(format, password, algorithm, extractable, keyUsages);
} catch (_) {
IMPORT_KEY_SUPPORTED = false;
return misc.importKey(password);
}
} else {
return misc.importKey(password);
}
}
async function deriveBits(algorithm, baseKey, length2) {
if (DERIVE_BITS_SUPPORTED) {
try {
return await subtle.deriveBits(algorithm, baseKey, length2);
} catch (_) {
DERIVE_BITS_SUPPORTED = false;
return misc.pbkdf2(baseKey, algorithm.salt, DERIVED_BITS_ALGORITHM.iterations, length2);
}
} else {
return misc.pbkdf2(baseKey, algorithm.salt, DERIVED_BITS_ALGORITHM.iterations, length2);
}
}
function encodePassword(password, rawPassword) {
if (rawPassword === UNDEFINED_VALUE) {
return encodeText(password);
} else {
return rawPassword;
}
}
function concat(leftArray, rightArray) {
let array = leftArray;
if (leftArray.length + rightArray.length) {
array = new Uint8Array(leftArray.length + rightArray.length);
array.set(leftArray, 0);
array.set(rightArray, leftArray.length);
}
return array;
}
function expand(inputArray, length2) {
if (length2 && length2 > inputArray.length) {
const array = inputArray;
inputArray = new Uint8Array(length2);
inputArray.set(array, 0);
}
return inputArray;
}
function subarray(array, begin, end) {
return array.subarray(begin, end);
}
function fromBits(codecBytes2, chunk) {
return codecBytes2.fromBits(chunk);
}
function toBits(codecBytes2, chunk) {
return codecBytes2.toBits(chunk);
}
// node_modules/@zip.js/zip.js/lib/core/streams/zip-crypto-stream.js
var import_InlineWorkers978 = __toESM(require_InlineWorkers(), 1);
var HEADER_LENGTH = 12;
var ZipCryptoDecryptionStream = class extends TransformStream {
constructor({ password, passwordVerification, checkPasswordOnly }) {
super({
start() {
Object.assign(this, {
password,
passwordVerification
});
createKeys2(this, password);
},
transform(chunk, controller) {
const zipCrypto = this;
if (zipCrypto.password) {
const decryptedHeader = decrypt(zipCrypto, chunk.subarray(0, HEADER_LENGTH));
zipCrypto.password = null;
if (decryptedHeader.at(-1) != zipCrypto.passwordVerification) {
throw new Error(ERR_INVALID_PASSWORD);
}
chunk = chunk.subarray(HEADER_LENGTH);
}
if (checkPasswordOnly) {
controller.error(new Error(ERR_ABORT_CHECK_PASSWORD));
} else {
controller.enqueue(decrypt(zipCrypto, chunk));
}
}
});
}
};
var ZipCryptoEncryptionStream = class extends TransformStream {
constructor({ password, passwordVerification }) {
super({
start() {
Object.assign(this, {
password,
passwordVerification
});
createKeys2(this, password);
},
transform(chunk, controller) {
const zipCrypto = this;
let output;
let offset;
if (zipCrypto.password) {
zipCrypto.password = null;
const header = getRandomValues2(new Uint8Array(HEADER_LENGTH));
header[HEADER_LENGTH - 1] = zipCrypto.passwordVerification;
output = new Uint8Array(chunk.length + header.length);
output.set(encrypt(zipCrypto, header), 0);
offset = HEADER_LENGTH;
} else {
output = new Uint8Array(chunk.length);
offset = 0;
}
output.set(encrypt(zipCrypto, chunk), offset);
controller.enqueue(output);
}
});
}
};
function decrypt(target, input) {
const output = new Uint8Array(input.length);
for (let index = 0; index < input.length; index++) {
output[index] = getByte(target) ^ input[index];
updateKeys(target, output[index]);
}
return output;
}
function encrypt(target, input) {
const output = new Uint8Array(input.length);
for (let index = 0; index < input.length; index++) {
output[index] = getByte(target) ^ input[index];
updateKeys(target, input[index]);
}
return output;
}
function createKeys2(target, password) {
const keys = [305419896, 591751049, 878082192];
Object.assign(target, {
keys,
crcKey0: new Crc32(keys[0]),
crcKey2: new Crc32(keys[2])
});
for (let index = 0; index < password.length; index++) {
updateKeys(target, password.charCodeAt(index));
}
}
function updateKeys(target, byte) {
let [key0, key1, key2] = target.keys;
target.crcKey0.append([byte]);
key0 = ~target.crcKey0.get();
key1 = getInt32(Math.imul(getInt32(key1 + getInt8(key0)), 134775813) + 1);
target.crcKey2.append([key1 >>> 24]);
key2 = ~target.crcKey2.get();
target.keys = [key0, key1, key2];
}
function getByte(target) {
const temp = target.keys[2] | 2;
return getInt8(Math.imul(temp, temp ^ 1) >>> 8);
}
function getInt8(number) {
return number & 255;
}
function getInt32(number) {
return number & 4294967295;
}
// node_modules/@zip.js/zip.js/lib/core/streams/zip-entry-stream.js
var ERR_INVALID_UNCOMPRESSED_SIZE = "Invalid uncompressed size";
var COMPRESSION_FORMAT = "deflate-raw";
var DeflateStream = class extends TransformStream {
constructor(options, { chunkSize, CompressionStream: CompressionStream2, CompressionStreamNative }) {
super({});
const { compressed, encrypted, useCompressionStream, zipCrypto, signed, level } = options;
const stream = this;
let crc32Stream, encryptionStream;
let readable = super.readable;
if ((!encrypted || zipCrypto) && signed) {
crc32Stream = new Crc32Stream();
readable = pipeThrough(readable, crc32Stream);
}
if (compressed) {
readable = pipeThroughCommpressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStreamNative, CompressionStream2);
}
if (encrypted) {
if (zipCrypto) {
readable = pipeThrough(readable, new ZipCryptoEncryptionStream(options));
} else {
encryptionStream = new AESEncryptionStream(options);
readable = pipeThrough(readable, encryptionStream);
}
}
setReadable(stream, readable, () => {
let signature;
if (encrypted && !zipCrypto) {
signature = encryptionStream.signature;
}
if ((!encrypted || zipCrypto) && signed) {
signature = new DataView(crc32Stream.value.buffer).getUint32(0);
}
stream.signature = signature;
});
}
};
var InflateStream = class extends TransformStream {
constructor(options, { chunkSize, DecompressionStream: DecompressionStream2, DecompressionStreamNative }) {
super({});
const { zipCrypto, encrypted, signed, signature, compressed, useCompressionStream } = options;
let crc32Stream, decryptionStream;
let readable = super.readable;
if (encrypted) {
if (zipCrypto) {
readable = pipeThrough(readable, new ZipCryptoDecryptionStream(options));
} else {
decryptionStream = new AESDecryptionStream(options);
readable = pipeThrough(readable, decryptionStream);
}
}
if (compressed) {
readable = pipeThroughCommpressionStream(readable, useCompressionStream, { chunkSize }, DecompressionStreamNative, DecompressionStream2);
}
if ((!encrypted || zipCrypto) && signed) {
crc32Stream = new Crc32Stream();
readable = pipeThrough(readable, crc32Stream);
}
setReadable(this, readable, () => {
if ((!encrypted || zipCrypto) && signed) {
const dataViewSignature = new DataView(crc32Stream.value.buffer);
if (signature != dataViewSignature.getUint32(0, false)) {
throw new Error(ERR_INVALID_SIGNATURE);
}
}
});
}
};
function setReadable(stream, readable, flush) {
readable = pipeThrough(readable, new TransformStream({ flush }));
Object.defineProperty(stream, "readable", {
get() {
return readable;
}
});
}
function pipeThroughCommpressionStream(readable, useCompressionStream, options, CodecStreamNative, CodecStream2) {
try {
const CompressionStream2 = useCompressionStream && CodecStreamNative ? CodecStreamNative : CodecStream2;
readable = pipeThrough(readable, new CompressionStream2(COMPRESSION_FORMAT, options));
} catch (error) {
if (useCompressionStream) {
readable = pipeThrough(readable, new CodecStream2(COMPRESSION_FORMAT, options));
} else {
throw error;
}
}
return readable;
}
function pipeThrough(readable, transformStream) {
return readable.pipeThrough(transformStream);
}
// node_modules/@zip.js/zip.js/lib/core/streams/codec-stream.js
var MESSAGE_EVENT_TYPE = "message";
var MESSAGE_START = "start";
var MESSAGE_PULL = "pull";
var MESSAGE_DATA = "data";
var MESSAGE_ACK_DATA = "ack";
var MESSAGE_CLOSE = "close";
var CODEC_DEFLATE = "deflate";
var CODEC_INFLATE = "inflate";
var CodecStream = class extends TransformStream {
constructor(options, config2) {
super({});
const codec2 = this;
const { codecType } = options;
let Stream2;
if (codecType.startsWith(CODEC_DEFLATE)) {
Stream2 = DeflateStream;
} else if (codecType.startsWith(CODEC_INFLATE)) {
Stream2 = InflateStream;
}
codec2.outputSize = 0;
let inputSize = 0;
const stream = new Stream2(options, config2);
const readable = super.readable;
const inputSizeStream = new TransformStream({
transform(chunk, controller) {
if (chunk && chunk.length) {
inputSize += chunk.length;
controller.enqueue(chunk);
}
},
flush() {
Object.assign(codec2, {
inputSize
});
}
});
const outputSizeStream = new TransformStream({
transform(chunk, controller) {
if (chunk && chunk.length) {
controller.enqueue(chunk);
codec2.outputSize += chunk.length;
if (options.outputSize && codec2.outputSize > options.outputSize) {
throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
}
}
},
flush() {
const { signature } = stream;
Object.assign(codec2, {
signature,
inputSize
});
}
});
Object.defineProperty(codec2, "readable", {
get() {
return readable.pipeThrough(inputSizeStream).pipeThrough(stream).pipeThrough(outputSizeStream);
}
});
}
};
var ChunkStream = class extends TransformStream {
constructor(chunkSize) {
let pendingChunk;
super({
transform: transform3,
flush(controller) {
if (pendingChunk && pendingChunk.length) {
controller.enqueue(pendingChunk);
}
}
});
function transform3(chunk, controller) {
if (pendingChunk) {
const newChunk = new Uint8Array(pendingChunk.length + chunk.length);
newChunk.set(pendingChunk);
newChunk.set(chunk, pendingChunk.length);
chunk = newChunk;
pendingChunk = null;
}
if (chunk.length > chunkSize) {
controller.enqueue(chunk.slice(0, chunkSize));
transform3(chunk.slice(chunkSize), controller);
} else {
pendingChunk = chunk;
}
}
}
};
// node_modules/@zip.js/zip.js/lib/core/codec-worker.js
var import_InlineWorkers981 = __toESM(require_InlineWorkers(), 1);
var WEB_WORKERS_SUPPORTED = typeof Worker != UNDEFINED_TYPE;
var CodecWorker = class {
constructor(workerData, { readable, writable }, { options, config: config2, streamOptions, useWebWorkers, transferStreams, scripts }, onTaskFinished) {
const { signal } = streamOptions;
Object.assign(workerData, {
busy: true,
readable: readable.pipeThrough(new ChunkStream(config2.chunkSize)).pipeThrough(new ProgressWatcherStream(streamOptions), { signal }),
writable,
options: Object.assign({}, options),
scripts,
transferStreams,
terminate() {
return new Promise((resolve2) => {
const { worker, busy } = workerData;
if (worker) {
if (busy) {
workerData.resolveTerminated = resolve2;
} else {
worker.terminate();
resolve2();
}
workerData.interface = null;
} else {
resolve2();
}
});
},
onTaskFinished() {
const { resolveTerminated } = workerData;
if (resolveTerminated) {
workerData.resolveTerminated = null;
workerData.terminated = true;
workerData.worker.terminate();
resolveTerminated();
}
workerData.busy = false;
onTaskFinished(workerData);
}
});
return (useWebWorkers && WEB_WORKERS_SUPPORTED ? createWebWorkerInterface : createWorkerInterface)(workerData, config2);
}
};
var ProgressWatcherStream = class extends TransformStream {
constructor({ onstart, onprogress, size, onend }) {
let chunkOffset = 0;
super({
async start() {
if (onstart) {
await callHandler(onstart, size);
}
},
async transform(chunk, controller) {
chunkOffset += chunk.length;
if (onprogress) {
await callHandler(onprogress, chunkOffset, size);
}
controller.enqueue(chunk);
},
async flush() {
if (onend) {
await callHandler(onend, chunkOffset);
}
}
});
}
};
async function callHandler(handler, ...parameters) {
try {
await handler(...parameters);
} catch (_) {
}
}
function createWorkerInterface(workerData, config2) {
return {
run: () => runWorker(workerData, config2)
};
}
function createWebWorkerInterface(workerData, config2) {
const { baseURL, chunkSize } = config2;
if (!workerData.interface) {
let worker;
try {
worker = getWebWorker(workerData.scripts[0], baseURL, workerData);
} catch (_) {
WEB_WORKERS_SUPPORTED = false;
return createWorkerInterface(workerData, config2);
}
Object.assign(workerData, {
worker,
interface: {
run: () => runWebWorker(workerData, { chunkSize })
}
});
}
return workerData.interface;
}
async function runWorker({ options, readable, writable, onTaskFinished }, config2) {
let codecStream;
try {
codecStream = new CodecStream(options, config2);
await readable.pipeThrough(codecStream).pipeTo(writable, { preventClose: true, preventAbort: true });
const {
signature,
inputSize,
outputSize
} = codecStream;
return {
signature,
inputSize,
outputSize
};
} catch (error) {
if (codecStream) {
error.outputSize = codecStream.outputSize;
}
throw error;
} finally {
onTaskFinished();
}
}
async function runWebWorker(workerData, config2) {
let resolveResult, rejectResult;
const result = new Promise((resolve2, reject) => {
resolveResult = resolve2;
rejectResult = reject;
});
Object.assign(workerData, {
reader: null,
writer: null,
resolveResult,
rejectResult,
result
});
const { readable, options, scripts } = workerData;
const { writable, closed } = watchClosedStream(workerData.writable);
const streamsTransferred = sendMessage({
type: MESSAGE_START,
scripts: scripts.slice(1),
options,
config: config2,
readable,
writable
}, workerData);
if (!streamsTransferred) {
Object.assign(workerData, {
reader: readable.getReader(),
writer: writable.getWriter()
});
}
const resultValue = await result;
if (!streamsTransferred) {
await writable.getWriter().close();
}
await closed;
return resultValue;
}
function watchClosedStream(writableSource) {
let resolveStreamClosed;
const closed = new Promise((resolve2) => resolveStreamClosed = resolve2);
const writable = new WritableStream({
async write(chunk) {
const writer = writableSource.getWriter();
await writer.ready;
await writer.write(chunk);
writer.releaseLock();
},
close() {
resolveStreamClosed();
},
abort(reason) {
const writer = writableSource.getWriter();
return writer.abort(reason);
}
});
return { writable, closed };
}
var classicWorkersSupported = true;
var transferStreamsSupported = true;
function getWebWorker(url2, baseURL, workerData) {
const workerOptions = { type: "module" };
let scriptUrl, worker;
if (typeof url2 == FUNCTION_TYPE) {
url2 = url2();
}
try {
scriptUrl = new URL(url2, baseURL);
} catch (_) {
scriptUrl = url2;
}
if (classicWorkersSupported) {
try {
worker = new Worker(scriptUrl);
} catch (_) {
classicWorkersSupported = false;
worker = new Worker(scriptUrl, workerOptions);
}
} else {
worker = new Worker(scriptUrl, workerOptions);
}
worker.addEventListener(MESSAGE_EVENT_TYPE, (event) => onMessage(event, workerData));
return worker;
}
function sendMessage(message, { worker, writer, onTaskFinished, transferStreams }) {
try {
const { value, readable, writable } = message;
const transferables = [];
if (value) {
if (value.byteLength < value.buffer.byteLength) {
message.value = value.buffer.slice(0, value.byteLength);
} else {
message.value = value.buffer;
}
transferables.push(message.value);
}
if (transferStreams && transferStreamsSupported) {
if (readable) {
transferables.push(readable);
}
if (writable) {
transferables.push(writable);
}
} else {
message.readable = message.writable = null;
}
if (transferables.length) {
try {
worker.postMessage(message, transferables);
return true;
} catch (_) {
transferStreamsSupported = false;
message.readable = message.writable = null;
worker.postMessage(message);
}
} else {
worker.postMessage(message);
}
} catch (error) {
if (writer) {
writer.releaseLock();
}
onTaskFinished();
throw error;
}
}
async function onMessage({ data }, workerData) {
const { type, value, messageId, result, error } = data;
const { reader, writer, resolveResult, rejectResult, onTaskFinished } = workerData;
try {
if (error) {
const { message, stack, code, name, outputSize } = error;
const responseError = new Error(message);
Object.assign(responseError, { stack, code, name, outputSize });
close(responseError);
} else {
if (type == MESSAGE_PULL) {
const { value: value2, done } = await reader.read();
sendMessage({ type: MESSAGE_DATA, value: value2, done, messageId }, workerData);
}
if (type == MESSAGE_DATA) {
await writer.ready;
await writer.write(new Uint8Array(value));
sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
}
if (type == MESSAGE_CLOSE) {
close(null, result);
}
}
} catch (error2) {
sendMessage({ type: MESSAGE_CLOSE, messageId }, workerData);
close(error2);
}
function close(error2, result2) {
if (error2) {
rejectResult(error2);
} else {
resolveResult(result2);
}
if (writer) {
writer.releaseLock();
}
onTaskFinished();
}
}
// node_modules/@zip.js/zip.js/lib/core/codec-pool.js
var pool = [];
var pendingRequests = [];
var indexWorker = 0;
async function runWorker2(stream, workerOptions) {
const { options, config: config2 } = workerOptions;
const { transferStreams, useWebWorkers, useCompressionStream, codecType, compressed, signed, encrypted } = options;
const { workerScripts, maxWorkers: maxWorkers2 } = config2;
workerOptions.transferStreams = transferStreams || transferStreams === UNDEFINED_VALUE;
const streamCopy = !compressed && !signed && !encrypted && !workerOptions.transferStreams;
workerOptions.useWebWorkers = !streamCopy && (useWebWorkers || useWebWorkers === UNDEFINED_VALUE && config2.useWebWorkers);
workerOptions.scripts = workerOptions.useWebWorkers && workerScripts ? workerScripts[codecType] : [];
options.useCompressionStream = useCompressionStream || useCompressionStream === UNDEFINED_VALUE && config2.useCompressionStream;
return (await getWorker()).run();
async function getWorker() {
const workerData = pool.find((workerData2) => !workerData2.busy);
if (workerData) {
clearTerminateTimeout(workerData);
return new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
} else if (pool.length < maxWorkers2) {
const workerData2 = { indexWorker };
indexWorker++;
pool.push(workerData2);
return new CodecWorker(workerData2, stream, workerOptions, onTaskFinished);
} else {
return new Promise((resolve2) => pendingRequests.push({ resolve: resolve2, stream, workerOptions }));
}
}
function onTaskFinished(workerData) {
if (pendingRequests.length) {
const [{ resolve: resolve2, stream: stream2, workerOptions: workerOptions2 }] = pendingRequests.splice(0, 1);
resolve2(new CodecWorker(workerData, stream2, workerOptions2, onTaskFinished));
} else if (workerData.worker) {
clearTerminateTimeout(workerData);
terminateWorker(workerData, workerOptions);
} else {
pool = pool.filter((data) => data != workerData);
}
}
}
function terminateWorker(workerData, workerOptions) {
const { config: config2 } = workerOptions;
const { terminateWorkerTimeout } = config2;
if (Number.isFinite(terminateWorkerTimeout) && terminateWorkerTimeout >= 0) {
if (workerData.terminated) {
workerData.terminated = false;
} else {
workerData.terminateTimeout = setTimeout(async () => {
pool = pool.filter((data) => data != workerData);
try {
await workerData.terminate();
} catch (_) {
}
}, terminateWorkerTimeout);
}
}
}
function clearTerminateTimeout(workerData) {
const { terminateTimeout } = workerData;
if (terminateTimeout) {
clearTimeout(terminateTimeout);
workerData.terminateTimeout = null;
}
}
// node_modules/@zip.js/zip.js/lib/core/io.js
var import_InlineWorkers983 = __toESM(require_InlineWorkers(), 1);
var ERR_ITERATOR_COMPLETED_TOO_SOON = "Writer iterator completed too soon";
var ERR_WRITER_NOT_INITIALIZED = "Writer not initialized";
var CONTENT_TYPE_TEXT_PLAIN = "text/plain";
var HTTP_HEADER_CONTENT_TYPE = "Content-Type";
var DEFAULT_CHUNK_SIZE = 64 * 1024;
var PROPERTY_NAME_WRITABLE = "writable";
var Stream = class {
constructor() {
this.size = 0;
}
init() {
this.initialized = true;
}
};
var Reader = class extends Stream {
get readable() {
const reader = this;
const { chunkSize = DEFAULT_CHUNK_SIZE } = reader;
const readable = new ReadableStream({
start() {
this.chunkOffset = 0;
},
async pull(controller) {
const { offset = 0, size, diskNumberStart } = readable;
const { chunkOffset } = this;
const dataSize = size === UNDEFINED_VALUE ? chunkSize : Math.min(chunkSize, size - chunkOffset);
const data = await readUint8Array(reader, offset + chunkOffset, dataSize, diskNumberStart);
controller.enqueue(data);
if (chunkOffset + chunkSize > size || size === UNDEFINED_VALUE && !data.length && dataSize) {
controller.close();
} else {
this.chunkOffset += chunkSize;
}
}
});
return readable;
}
};
var Writer = class extends Stream {
constructor() {
super();
const writer = this;
const writable = new WritableStream({
write(chunk) {
if (!writer.initialized) {
throw new Error(ERR_WRITER_NOT_INITIALIZED);
}
return writer.writeUint8Array(chunk);
}
});
Object.defineProperty(writer, PROPERTY_NAME_WRITABLE, {
get() {
return writable;
}
});
}
writeUint8Array() {
}
};
var Data64URIWriter = class extends Writer {
constructor(contentType) {
super();
Object.assign(this, {
data: "data:" + (contentType || "") + ";base64,",
pending: []
});
}
writeUint8Array(array) {
const writer = this;
let indexArray = 0;
let dataString = writer.pending;
const delta = writer.pending.length;
writer.pending = "";
for (indexArray = 0; indexArray < Math.floor((delta + array.length) / 3) * 3 - delta; indexArray++) {
dataString += String.fromCharCode(array[indexArray]);
}
for (; indexArray < array.length; indexArray++) {
writer.pending += String.fromCharCode(array[indexArray]);
}
if (dataString.length) {
if (dataString.length > 2) {
writer.data += btoa(dataString);
} else {
writer.pending += dataString;
}
}
}
getData() {
return this.data + btoa(this.pending);
}
};
var BlobReader = class extends Reader {
constructor(blob) {
super();
Object.assign(this, {
blob,
size: blob.size
});
}
async readUint8Array(offset, length2) {
const reader = this;
const offsetEnd = offset + length2;
const blob = offset || offsetEnd < reader.size ? reader.blob.slice(offset, offsetEnd) : reader.blob;
let arrayBuffer = await blob.arrayBuffer();
if (arrayBuffer.byteLength > length2) {
arrayBuffer = arrayBuffer.slice(offset, offsetEnd);
}
return new Uint8Array(arrayBuffer);
}
};
var BlobWriter = class extends Stream {
constructor(contentType) {
super();
const writer = this;
const transformStream = new TransformStream();
const headers = [];
if (contentType) {
headers.push([HTTP_HEADER_CONTENT_TYPE, contentType]);
}
Object.defineProperty(writer, PROPERTY_NAME_WRITABLE, {
get() {
return transformStream.writable;
}
});
writer.blob = new Response(transformStream.readable, { headers }).blob();
}
getData() {
return this.blob;
}
};
var TextReader = class extends BlobReader {
constructor(text2) {
super(new Blob([text2], { type: CONTENT_TYPE_TEXT_PLAIN }));
}
};
var TextWriter = class extends BlobWriter {
constructor(encoding) {
super(encoding);
Object.assign(this, {
encoding,
utf8: !encoding || encoding.toLowerCase() == "utf-8"
});
}
async getData() {
const {
encoding,
utf8
} = this;
const blob = await super.getData();
if (blob.text && utf8) {
return blob.text();
} else {
const reader = new FileReader();
return new Promise((resolve2, reject) => {
Object.assign(reader, {
onload: ({ target }) => resolve2(target.result),
onerror: () => reject(reader.error)
});
reader.readAsText(blob, encoding);
});
}
}
};
var SplitDataReader = class extends Reader {
constructor(readers) {
super();
this.readers = readers;
}
async init() {
const reader = this;
const { readers } = reader;
reader.lastDiskNumber = 0;
reader.lastDiskOffset = 0;
await Promise.all(readers.map(async (diskReader, indexDiskReader) => {
await diskReader.init();
if (indexDiskReader != readers.length - 1) {
reader.lastDiskOffset += diskReader.size;
}
reader.size += diskReader.size;
}));
super.init();
}
async readUint8Array(offset, length2, diskNumber = 0) {
const reader = this;
const { readers } = this;
let result;
let currentDiskNumber = diskNumber;
if (currentDiskNumber == -1) {
currentDiskNumber = readers.length - 1;
}
let currentReaderOffset = offset;
while (readers[currentDiskNumber] && currentReaderOffset >= readers[currentDiskNumber].size) {
currentReaderOffset -= readers[currentDiskNumber].size;
currentDiskNumber++;
}
const currentReader = readers[currentDiskNumber];
if (currentReader) {
const currentReaderSize = currentReader.size;
if (currentReaderOffset + length2 <= currentReaderSize) {
result = await readUint8Array(currentReader, currentReaderOffset, length2);
} else {
const chunkLength = currentReaderSize - currentReaderOffset;
result = new Uint8Array(length2);
const firstPart = await readUint8Array(currentReader, currentReaderOffset, chunkLength);
result.set(firstPart, 0);
const secondPart = await reader.readUint8Array(offset + chunkLength, length2 - chunkLength, diskNumber);
result.set(secondPart, chunkLength);
if (firstPart.length + secondPart.length < length2) {
result = result.subarray(0, firstPart.length + secondPart.length);
}
}
} else {
result = new Uint8Array();
}
reader.lastDiskNumber = Math.max(currentDiskNumber, reader.lastDiskNumber);
return result;
}
};
var SplitDataWriter = class extends Stream {
constructor(writerGenerator, maxSize = 4294967295) {
super();
const writer = this;
Object.assign(writer, {
diskNumber: 0,
diskOffset: 0,
size: 0,
maxSize,
availableSize: maxSize
});
let diskSourceWriter, diskWritable, diskWriter;
const writable = new WritableStream({
async write(chunk) {
const { availableSize } = writer;
if (!diskWriter) {
const { value, done } = await writerGenerator.next();
if (done && !value) {
throw new Error(ERR_ITERATOR_COMPLETED_TOO_SOON);
} else {
diskSourceWriter = value;
diskSourceWriter.size = 0;
if (diskSourceWriter.maxSize) {
writer.maxSize = diskSourceWriter.maxSize;
}
writer.availableSize = writer.maxSize;
await initStream(diskSourceWriter);
diskWritable = value.writable;
diskWriter = diskWritable.getWriter();
}
await this.write(chunk);
} else if (chunk.length >= availableSize) {
await writeChunk(chunk.subarray(0, availableSize));
await closeDisk();
writer.diskOffset += diskSourceWriter.size;
writer.diskNumber++;
diskWriter = null;
await this.write(chunk.subarray(availableSize));
} else {
await writeChunk(chunk);
}
},
async close() {
await diskWriter.ready;
await closeDisk();
}
});
Object.defineProperty(writer, PROPERTY_NAME_WRITABLE, {
get() {
return writable;
}
});
async function writeChunk(chunk) {
const chunkLength = chunk.length;
if (chunkLength) {
await diskWriter.ready;
await diskWriter.write(chunk);
diskSourceWriter.size += chunkLength;
writer.size += chunkLength;
writer.availableSize -= chunkLength;
}
}
async function closeDisk() {
await diskWriter.close();
}
}
};
var GenericReader = class {
constructor(reader) {
if (Array.isArray(reader)) {
reader = new SplitDataReader(reader);
}
if (reader instanceof ReadableStream) {
reader = {
readable: reader
};
}
return reader;
}
};
var GenericWriter = class {
constructor(writer) {
if (writer.writable === UNDEFINED_VALUE && typeof writer.next == FUNCTION_TYPE) {
writer = new SplitDataWriter(writer);
}
if (writer instanceof WritableStream) {
writer = {
writable: writer
};
}
if (writer.size === UNDEFINED_VALUE) {
writer.size = 0;
}
if (!(writer instanceof SplitDataWriter)) {
Object.assign(writer, {
diskNumber: 0,
diskOffset: 0,
availableSize: Infinity,
maxSize: Infinity
});
}
return writer;
}
};
async function initStream(stream, initSize) {
if (stream.init && !stream.initialized) {
await stream.init(initSize);
} else {
return Promise.resolve();
}
}
function readUint8Array(reader, offset, size, diskNumber) {
return reader.readUint8Array(offset, size, diskNumber);
}
// node_modules/@zip.js/zip.js/lib/core/zip-reader.js
var import_InlineWorkers988 = __toESM(require_InlineWorkers(), 1);
// node_modules/@zip.js/zip.js/lib/core/util/decode-text.js
var import_InlineWorkers985 = __toESM(require_InlineWorkers(), 1);
// node_modules/@zip.js/zip.js/lib/core/util/cp437-decode.js
var import_InlineWorkers984 = __toESM(require_InlineWorkers(), 1);
var CP437 = "\0\u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\xB6\xA7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0 ".split("");
var VALID_CP437 = CP437.length == 256;
function decodeCP437(stringValue) {
if (VALID_CP437) {
let result = "";
for (let indexCharacter = 0; indexCharacter < stringValue.length; indexCharacter++) {
result += CP437[stringValue[indexCharacter]];
}
return result;
} else {
return new TextDecoder().decode(stringValue);
}
}
// node_modules/@zip.js/zip.js/lib/core/util/decode-text.js
function decodeText(value, encoding) {
if (encoding && encoding.trim().toLowerCase() == "cp437") {
return decodeCP437(value);
} else {
return new TextDecoder(encoding).decode(value);
}
}
// node_modules/@zip.js/zip.js/lib/core/zip-entry.js
var import_InlineWorkers986 = __toESM(require_InlineWorkers(), 1);
var PROPERTY_NAME_FILENAME = "filename";
var PROPERTY_NAME_RAW_FILENAME = "rawFilename";
var PROPERTY_NAME_COMMENT = "comment";
var PROPERTY_NAME_RAW_COMMENT = "rawComment";
var PROPERTY_NAME_UNCOMPRESSED_SIZE = "uncompressedSize";
var PROPERTY_NAME_COMPRESSED_SIZE = "compressedSize";
var PROPERTY_NAME_OFFSET = "offset";
var PROPERTY_NAME_DISK_NUMBER_START = "diskNumberStart";
var PROPERTY_NAME_LAST_MODIFICATION_DATE = "lastModDate";
var PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE = "rawLastModDate";
var PROPERTY_NAME_LAST_ACCESS_DATE = "lastAccessDate";
var PROPERTY_NAME_RAW_LAST_ACCESS_DATE = "rawLastAccessDate";
var PROPERTY_NAME_CREATION_DATE = "creationDate";
var PROPERTY_NAME_RAW_CREATION_DATE = "rawCreationDate";
var PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTE = "internalFileAttribute";
var PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES = "internalFileAttributes";
var PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTE = "externalFileAttribute";
var PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttributes";
var PROPERTY_NAME_MS_DOS_COMPATIBLE = "msDosCompatible";
var PROPERTY_NAME_ZIP64 = "zip64";
var PROPERTY_NAME_ENCRYPTED = "encrypted";
var PROPERTY_NAME_VERSION = "version";
var PROPERTY_NAME_VERSION_MADE_BY = "versionMadeBy";
var PROPERTY_NAME_ZIPCRYPTO = "zipCrypto";
var PROPERTY_NAME_DIRECTORY = "directory";
var PROPERTY_NAME_EXECUTABLE = "executable";
var PROPERTY_NAME_COMPRESSION_METHOD = "compressionMethod";
var PROPERTY_NAME_SIGNATURE = "signature";
var PROPERTY_NAME_EXTRA_FIELD = "extraField";
var PROPERTY_NAMES = [
PROPERTY_NAME_FILENAME,
PROPERTY_NAME_RAW_FILENAME,
PROPERTY_NAME_COMPRESSED_SIZE,
PROPERTY_NAME_UNCOMPRESSED_SIZE,
PROPERTY_NAME_LAST_MODIFICATION_DATE,
PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE,
PROPERTY_NAME_COMMENT,
PROPERTY_NAME_RAW_COMMENT,
PROPERTY_NAME_LAST_ACCESS_DATE,
PROPERTY_NAME_CREATION_DATE,
PROPERTY_NAME_OFFSET,
PROPERTY_NAME_DISK_NUMBER_START,
PROPERTY_NAME_DISK_NUMBER_START,
PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTE,
PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTE,
PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES,
PROPERTY_NAME_MS_DOS_COMPATIBLE,
PROPERTY_NAME_ZIP64,
PROPERTY_NAME_ENCRYPTED,
PROPERTY_NAME_VERSION,
PROPERTY_NAME_VERSION_MADE_BY,
PROPERTY_NAME_ZIPCRYPTO,
PROPERTY_NAME_DIRECTORY,
PROPERTY_NAME_EXECUTABLE,
PROPERTY_NAME_COMPRESSION_METHOD,
PROPERTY_NAME_SIGNATURE,
PROPERTY_NAME_EXTRA_FIELD,
"bitFlag",
"filenameUTF8",
"commentUTF8",
"rawExtraField",
"extraFieldZip64",
"extraFieldUnicodePath",
"extraFieldUnicodeComment",
"extraFieldAES",
"extraFieldNTFS",
"extraFieldExtendedTimestamp"
];
var Entry = class {
constructor(data) {
PROPERTY_NAMES.forEach((name) => this[name] = data[name]);
}
};
// node_modules/@zip.js/zip.js/lib/core/options.js
var import_InlineWorkers987 = __toESM(require_InlineWorkers(), 1);
var OPTION_FILENAME_ENCODING = "filenameEncoding";
var OPTION_COMMENT_ENCODING = "commentEncoding";
var OPTION_DECODE_TEXT = "decodeText";
var OPTION_EXTRACT_PREPENDED_DATA = "extractPrependedData";
var OPTION_EXTRACT_APPENDED_DATA = "extractAppendedData";
var OPTION_PASSWORD = "password";
var OPTION_RAW_PASSWORD = "rawPassword";
var OPTION_PASS_THROUGH = "passThrough";
var OPTION_SIGNAL = "signal";
var OPTION_CHECK_PASSWORD_ONLY = "checkPasswordOnly";
var OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
var OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
var OPTION_CHECK_SIGNATURE = "checkSignature";
var OPTION_USE_WEB_WORKERS = "useWebWorkers";
var OPTION_USE_COMPRESSION_STREAM = "useCompressionStream";
var OPTION_TRANSFER_STREAMS = "transferStreams";
var OPTION_PREVENT_CLOSE = "preventClose";
var OPTION_ENCRYPTION_STRENGTH = "encryptionStrength";
var OPTION_EXTENDED_TIMESTAMP = "extendedTimestamp";
var OPTION_KEEP_ORDER = "keepOrder";
var OPTION_LEVEL = "level";
var OPTION_BUFFERED_WRITE = "bufferedWrite";
var OPTION_DATA_DESCRIPTOR_SIGNATURE = "dataDescriptorSignature";
var OPTION_USE_UNICODE_FILE_NAMES = "useUnicodeFileNames";
var OPTION_DATA_DESCRIPTOR = "dataDescriptor";
var OPTION_SUPPORT_ZIP64_SPLIT_FILE = "supportZip64SplitFile";
var OPTION_ENCODE_TEXT = "encodeText";
var OPTION_OFFSET = "offset";
var OPTION_USDZ = "usdz";
// node_modules/@zip.js/zip.js/lib/core/zip-reader.js
var ERR_BAD_FORMAT = "File format is not recognized";
var ERR_EOCDR_NOT_FOUND = "End of central directory not found";
var ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND = "End of Zip64 central directory locator not found";
var ERR_CENTRAL_DIRECTORY_NOT_FOUND = "Central directory header not found";
var ERR_LOCAL_FILE_HEADER_NOT_FOUND = "Local file header not found";
var ERR_EXTRAFIELD_ZIP64_NOT_FOUND = "Zip64 extra field not found";
var ERR_ENCRYPTED = "File contains encrypted entry";
var ERR_UNSUPPORTED_ENCRYPTION = "Encryption method not supported";
var ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
var ERR_SPLIT_ZIP_FILE = "Split zip file";
var ERR_OVERLAPPING_ENTRY = "Overlapping entry found";
var CHARSET_UTF8 = "utf-8";
var CHARSET_CP437 = "cp437";
var ZIP64_PROPERTIES = [
[PROPERTY_NAME_UNCOMPRESSED_SIZE, MAX_32_BITS],
[PROPERTY_NAME_COMPRESSED_SIZE, MAX_32_BITS],
[PROPERTY_NAME_OFFSET, MAX_32_BITS],
[PROPERTY_NAME_DISK_NUMBER_START, MAX_16_BITS]
];
var ZIP64_EXTRACTION = {
[MAX_16_BITS]: {
getValue: getUint32,
bytes: 4
},
[MAX_32_BITS]: {
getValue: getBigUint64,
bytes: 8
}
};
var ZipReader = class {
constructor(reader, options = {}) {
Object.assign(this, {
reader: new GenericReader(reader),
options,
config: getConfiguration(),
readRanges: []
});
}
async *getEntriesGenerator(options = {}) {
const zipReader = this;
let { reader } = zipReader;
const { config: config2 } = zipReader;
await initStream(reader);
if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
reader = new BlobReader(await new Response(reader.readable).blob());
await initStream(reader);
}
if (reader.size < END_OF_CENTRAL_DIR_LENGTH) {
throw new Error(ERR_BAD_FORMAT);
}
reader.chunkSize = getChunkSize(config2);
const endOfDirectoryInfo = await seekSignature(reader, END_OF_CENTRAL_DIR_SIGNATURE, reader.size, END_OF_CENTRAL_DIR_LENGTH, MAX_16_BITS * 16);
if (!endOfDirectoryInfo) {
const signatureArray = await readUint8Array(reader, 0, 4);
const signatureView = getDataView(signatureArray);
if (getUint32(signatureView) == SPLIT_ZIP_FILE_SIGNATURE) {
throw new Error(ERR_SPLIT_ZIP_FILE);
} else {
throw new Error(ERR_EOCDR_NOT_FOUND);
}
}
const endOfDirectoryView = getDataView(endOfDirectoryInfo);
let directoryDataLength = getUint32(endOfDirectoryView, 12);
let directoryDataOffset = getUint32(endOfDirectoryView, 16);
const commentOffset = endOfDirectoryInfo.offset;
const commentLength = getUint16(endOfDirectoryView, 20);
const appendedDataOffset = commentOffset + END_OF_CENTRAL_DIR_LENGTH + commentLength;
let lastDiskNumber = getUint16(endOfDirectoryView, 4);
const expectedLastDiskNumber = reader.lastDiskNumber || 0;
let diskNumber = getUint16(endOfDirectoryView, 6);
let filesLength = getUint16(endOfDirectoryView, 8);
let prependedDataLength = 0;
let startOffset = 0;
if (directoryDataOffset == MAX_32_BITS || directoryDataLength == MAX_32_BITS || filesLength == MAX_16_BITS || diskNumber == MAX_16_BITS) {
const endOfDirectoryLocatorArray = await readUint8Array(reader, endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH, ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH);
const endOfDirectoryLocatorView = getDataView(endOfDirectoryLocatorArray);
if (getUint32(endOfDirectoryLocatorView, 0) == ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE) {
directoryDataOffset = getBigUint64(endOfDirectoryLocatorView, 8);
let endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH, -1);
let endOfDirectoryView2 = getDataView(endOfDirectoryArray);
const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH - ZIP64_END_OF_CENTRAL_DIR_LENGTH;
if (getUint32(endOfDirectoryView2, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE && directoryDataOffset != expectedDirectoryDataOffset) {
const originalDirectoryDataOffset = directoryDataOffset;
directoryDataOffset = expectedDirectoryDataOffset;
if (directoryDataOffset > originalDirectoryDataOffset) {
prependedDataLength = directoryDataOffset - originalDirectoryDataOffset;
}
endOfDirectoryArray = await readUint8Array(reader, directoryDataOffset, ZIP64_END_OF_CENTRAL_DIR_LENGTH, -1);
endOfDirectoryView2 = getDataView(endOfDirectoryArray);
}
if (getUint32(endOfDirectoryView2, 0) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE) {
throw new Error(ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND);
}
if (lastDiskNumber == MAX_16_BITS) {
lastDiskNumber = getUint32(endOfDirectoryView2, 16);
}
if (diskNumber == MAX_16_BITS) {
diskNumber = getUint32(endOfDirectoryView2, 20);
}
if (filesLength == MAX_16_BITS) {
filesLength = getBigUint64(endOfDirectoryView2, 32);
}
if (directoryDataLength == MAX_32_BITS) {
directoryDataLength = getBigUint64(endOfDirectoryView2, 40);
}
directoryDataOffset -= directoryDataLength;
}
}
if (directoryDataOffset >= reader.size) {
prependedDataLength = reader.size - directoryDataOffset - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
}
if (expectedLastDiskNumber != lastDiskNumber) {
throw new Error(ERR_SPLIT_ZIP_FILE);
}
if (directoryDataOffset < 0) {
throw new Error(ERR_BAD_FORMAT);
}
let offset = 0;
let directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength, diskNumber);
let directoryView = getDataView(directoryArray);
if (directoryDataLength) {
const expectedDirectoryDataOffset = endOfDirectoryInfo.offset - directoryDataLength;
if (getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE && directoryDataOffset != expectedDirectoryDataOffset) {
const originalDirectoryDataOffset = directoryDataOffset;
directoryDataOffset = expectedDirectoryDataOffset;
if (directoryDataOffset > originalDirectoryDataOffset) {
prependedDataLength += directoryDataOffset - originalDirectoryDataOffset;
}
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength, diskNumber);
directoryView = getDataView(directoryArray);
}
}
const expectedDirectoryDataLength = endOfDirectoryInfo.offset - directoryDataOffset - (reader.lastDiskOffset || 0);
if (directoryDataLength != expectedDirectoryDataLength && expectedDirectoryDataLength >= 0) {
directoryDataLength = expectedDirectoryDataLength;
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength, diskNumber);
directoryView = getDataView(directoryArray);
}
if (directoryDataOffset < 0 || directoryDataOffset >= reader.size) {
throw new Error(ERR_BAD_FORMAT);
}
const filenameEncoding = getOptionValue(zipReader, options, OPTION_FILENAME_ENCODING);
const commentEncoding = getOptionValue(zipReader, options, OPTION_COMMENT_ENCODING);
for (let indexFile = 0; indexFile < filesLength; indexFile++) {
const fileEntry = new ZipEntry(reader, config2, zipReader.options);
if (getUint32(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
throw new Error(ERR_CENTRAL_DIRECTORY_NOT_FOUND);
}
readCommonHeader(fileEntry, directoryView, offset + 6);
const languageEncodingFlag = Boolean(fileEntry.bitFlag.languageEncodingFlag);
const filenameOffset = offset + 46;
const extraFieldOffset = filenameOffset + fileEntry.filenameLength;
const commentOffset2 = extraFieldOffset + fileEntry.extraFieldLength;
const versionMadeBy = getUint16(directoryView, offset + 4);
const msDosCompatible = versionMadeBy >> 8 == 0;
const unixCompatible = versionMadeBy >> 8 == 3;
const rawFilename = directoryArray.subarray(filenameOffset, extraFieldOffset);
const commentLength2 = getUint16(directoryView, offset + 32);
const endOffset = commentOffset2 + commentLength2;
const rawComment = directoryArray.subarray(commentOffset2, endOffset);
const filenameUTF8 = languageEncodingFlag;
const commentUTF8 = languageEncodingFlag;
const externalFileAttributes = getUint32(directoryView, offset + 38);
const directory = msDosCompatible && (getUint8(directoryView, offset + 38) & FILE_ATTR_MSDOS_DIR_MASK) == FILE_ATTR_MSDOS_DIR_MASK || unixCompatible && (externalFileAttributes >> 16 & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR || rawFilename.length && rawFilename.at(-1) == DIRECTORY_SIGNATURE.charCodeAt(0);
const executable = unixCompatible && (externalFileAttributes >> 16 & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0;
const offsetFileEntry = getUint32(directoryView, offset + 42) + prependedDataLength;
Object.assign(fileEntry, {
versionMadeBy,
msDosCompatible,
compressedSize: 0,
uncompressedSize: 0,
commentLength: commentLength2,
directory,
offset: offsetFileEntry,
diskNumberStart: getUint16(directoryView, offset + 34),
internalFileAttributes: getUint16(directoryView, offset + 36),
externalFileAttributes,
rawFilename,
filenameUTF8,
commentUTF8,
rawExtraField: directoryArray.subarray(extraFieldOffset, commentOffset2),
executable
});
fileEntry.internalFileAttribute = fileEntry.internalFileAttributes;
fileEntry.externalFileAttribute = fileEntry.externalFileAttributes;
const decode = getOptionValue(zipReader, options, OPTION_DECODE_TEXT) || decodeText;
const rawFilenameEncoding = filenameUTF8 ? CHARSET_UTF8 : filenameEncoding || CHARSET_CP437;
const rawCommentEncoding = commentUTF8 ? CHARSET_UTF8 : commentEncoding || CHARSET_CP437;
let filename = decode(rawFilename, rawFilenameEncoding);
if (filename === UNDEFINED_VALUE) {
filename = decodeText(rawFilename, rawFilenameEncoding);
}
let comment = decode(rawComment, rawCommentEncoding);
if (comment === UNDEFINED_VALUE) {
comment = decodeText(rawComment, rawCommentEncoding);
}
Object.assign(fileEntry, {
rawComment,
filename,
comment,
directory: directory || filename.endsWith(DIRECTORY_SIGNATURE)
});
startOffset = Math.max(offsetFileEntry, startOffset);
readCommonFooter(fileEntry, fileEntry, directoryView, offset + 6);
fileEntry.zipCrypto = fileEntry.encrypted && !fileEntry.extraFieldAES;
const entry = new Entry(fileEntry);
entry.getData = (writer, options2) => fileEntry.getData(writer, entry, zipReader.readRanges, options2);
entry.arrayBuffer = async (options2) => {
const writer = new TransformStream();
const [arrayBuffer] = await Promise.all([
new Response(writer.readable).arrayBuffer(),
fileEntry.getData(writer, entry, zipReader.readRanges, options2)
]);
return arrayBuffer;
};
offset = endOffset;
const { onprogress } = options;
if (onprogress) {
try {
await onprogress(indexFile + 1, filesLength, new Entry(fileEntry));
} catch (_) {
}
}
yield entry;
}
const extractPrependedData = getOptionValue(zipReader, options, OPTION_EXTRACT_PREPENDED_DATA);
const extractAppendedData = getOptionValue(zipReader, options, OPTION_EXTRACT_APPENDED_DATA);
if (extractPrependedData) {
zipReader.prependedData = startOffset > 0 ? await readUint8Array(reader, 0, startOffset) : new Uint8Array();
}
zipReader.comment = commentLength ? await readUint8Array(reader, commentOffset + END_OF_CENTRAL_DIR_LENGTH, commentLength) : new Uint8Array();
if (extractAppendedData) {
zipReader.appendedData = appendedDataOffset < reader.size ? await readUint8Array(reader, appendedDataOffset, reader.size - appendedDataOffset) : new Uint8Array();
}
return true;
}
async getEntries(options = {}) {
const entries2 = [];
for await (const entry of this.getEntriesGenerator(options)) {
entries2.push(entry);
}
return entries2;
}
async close() {
}
};
var ZipEntry = class {
constructor(reader, config2, options) {
Object.assign(this, {
reader,
config: config2,
options
});
}
async getData(writer, fileEntry, readRanges, options = {}) {
const zipEntry = this;
const {
reader,
offset,
diskNumberStart,
extraFieldAES,
extraFieldZip64,
compressionMethod,
config: config2,
bitFlag,
signature,
rawLastModDate,
uncompressedSize,
compressedSize
} = zipEntry;
const {
dataDescriptor
} = bitFlag;
const localDirectory = fileEntry.localDirectory = {};
const dataArray = await readUint8Array(reader, offset, HEADER_SIZE2, diskNumberStart);
const dataView = getDataView(dataArray);
let password = getOptionValue(zipEntry, options, OPTION_PASSWORD);
let rawPassword = getOptionValue(zipEntry, options, OPTION_RAW_PASSWORD);
const passThrough = getOptionValue(zipEntry, options, OPTION_PASS_THROUGH);
password = password && password.length && password;
rawPassword = rawPassword && rawPassword.length && rawPassword;
if (extraFieldAES) {
if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
}
}
if (compressionMethod != COMPRESSION_METHOD_STORE && compressionMethod != COMPRESSION_METHOD_DEFLATE && !passThrough) {
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
}
if (getUint32(dataView, 0) != LOCAL_FILE_HEADER_SIGNATURE) {
throw new Error(ERR_LOCAL_FILE_HEADER_NOT_FOUND);
}
readCommonHeader(localDirectory, dataView, 4);
const {
extraFieldLength,
filenameLength,
lastAccessDate,
creationDate
} = localDirectory;
localDirectory.rawExtraField = extraFieldLength ? await readUint8Array(reader, offset + HEADER_SIZE2 + filenameLength, extraFieldLength, diskNumberStart) : new Uint8Array();
readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
Object.assign(fileEntry, { lastAccessDate, creationDate });
const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
const zipCrypto = encrypted && !extraFieldAES;
if (!passThrough) {
fileEntry.zipCrypto = zipCrypto;
}
if (encrypted) {
if (!zipCrypto && extraFieldAES.strength === UNDEFINED_VALUE) {
throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
} else if (!password && !rawPassword) {
throw new Error(ERR_ENCRYPTED);
}
}
const dataOffset = offset + HEADER_SIZE2 + filenameLength + extraFieldLength;
const size = compressedSize;
const readable = reader.readable;
Object.assign(readable, {
diskNumberStart,
offset: dataOffset,
size
});
const signal = getOptionValue(zipEntry, options, OPTION_SIGNAL);
const checkPasswordOnly = getOptionValue(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
let checkOverlappingEntry = getOptionValue(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY);
const checkOverlappingEntryOnly = getOptionValue(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY_ONLY);
if (checkOverlappingEntryOnly) {
checkOverlappingEntry = true;
}
const { onstart, onprogress, onend } = options;
const workerOptions = {
options: {
codecType: CODEC_INFLATE,
password,
rawPassword,
zipCrypto,
encryptionStrength: extraFieldAES && extraFieldAES.strength,
signed: getOptionValue(zipEntry, options, OPTION_CHECK_SIGNATURE) && !passThrough,
passwordVerification: zipCrypto && (dataDescriptor ? rawLastModDate >>> 8 & 255 : signature >>> 24 & 255),
outputSize: uncompressedSize,
signature,
compressed: compressionMethod != 0 && !passThrough,
encrypted: zipEntry.encrypted && !passThrough,
useWebWorkers: getOptionValue(zipEntry, options, OPTION_USE_WEB_WORKERS),
useCompressionStream: getOptionValue(zipEntry, options, OPTION_USE_COMPRESSION_STREAM),
transferStreams: getOptionValue(zipEntry, options, OPTION_TRANSFER_STREAMS),
checkPasswordOnly
},
config: config2,
streamOptions: { signal, size, onstart, onprogress, onend }
};
if (checkOverlappingEntry) {
await detectOverlappingEntry({
reader,
fileEntry,
offset,
diskNumberStart,
signature,
compressedSize,
uncompressedSize,
dataOffset,
dataDescriptor: dataDescriptor || localDirectory.bitFlag.dataDescriptor,
extraFieldZip64: extraFieldZip64 || localDirectory.extraFieldZip64,
readRanges
});
}
let writable;
try {
if (!checkOverlappingEntryOnly) {
if (checkPasswordOnly) {
writer = new WritableStream();
}
writer = new GenericWriter(writer);
await initStream(writer, passThrough ? compressedSize : uncompressedSize);
({ writable } = writer);
const { outputSize } = await runWorker2({ readable, writable }, workerOptions);
writer.size += outputSize;
if (outputSize != (passThrough ? compressedSize : uncompressedSize)) {
throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
}
}
} catch (error) {
if (error.outputSize !== UNDEFINED_VALUE) {
writer.size += error.outputSize;
}
if (!checkPasswordOnly || error.message != ERR_ABORT_CHECK_PASSWORD) {
throw error;
}
} finally {
const preventClose = getOptionValue(zipEntry, options, OPTION_PREVENT_CLOSE);
if (!preventClose && writable && !writable.locked) {
await writable.getWriter().close();
}
}
return checkPasswordOnly || checkOverlappingEntryOnly ? UNDEFINED_VALUE : writer.getData ? writer.getData() : writable;
}
};
function readCommonHeader(directory, dataView, offset) {
const rawBitFlag = directory.rawBitFlag = getUint16(dataView, offset + 2);
const encrypted = (rawBitFlag & BITFLAG_ENCRYPTED) == BITFLAG_ENCRYPTED;
const rawLastModDate = getUint32(dataView, offset + 6);
Object.assign(directory, {
encrypted,
version: getUint16(dataView, offset),
bitFlag: {
level: (rawBitFlag & BITFLAG_LEVEL) >> 1,
dataDescriptor: (rawBitFlag & BITFLAG_DATA_DESCRIPTOR) == BITFLAG_DATA_DESCRIPTOR,
languageEncodingFlag: (rawBitFlag & BITFLAG_LANG_ENCODING_FLAG) == BITFLAG_LANG_ENCODING_FLAG
},
rawLastModDate,
lastModDate: getDate(rawLastModDate),
filenameLength: getUint16(dataView, offset + 22),
extraFieldLength: getUint16(dataView, offset + 24)
});
}
function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory) {
const { rawExtraField } = directory;
const extraField = directory.extraField = /* @__PURE__ */ new Map();
const rawExtraFieldView = getDataView(new Uint8Array(rawExtraField));
let offsetExtraField = 0;
try {
while (offsetExtraField < rawExtraField.length) {
const type = getUint16(rawExtraFieldView, offsetExtraField);
const size = getUint16(rawExtraFieldView, offsetExtraField + 2);
extraField.set(type, {
type,
data: rawExtraField.slice(offsetExtraField + 4, offsetExtraField + 4 + size)
});
offsetExtraField += 4 + size;
}
} catch (_) {
}
const compressionMethod = getUint16(dataView, offset + 4);
Object.assign(directory, {
signature: getUint32(dataView, offset + HEADER_OFFSET_SIGNATURE),
compressedSize: getUint32(dataView, offset + HEADER_OFFSET_COMPRESSED_SIZE),
uncompressedSize: getUint32(dataView, offset + HEADER_OFFSET_UNCOMPRESSED_SIZE)
});
const extraFieldZip64 = extraField.get(EXTRAFIELD_TYPE_ZIP64);
if (extraFieldZip64) {
readExtraFieldZip64(extraFieldZip64, directory);
directory.extraFieldZip64 = extraFieldZip64;
}
const extraFieldUnicodePath = extraField.get(EXTRAFIELD_TYPE_UNICODE_PATH);
if (extraFieldUnicodePath) {
readExtraFieldUnicode(extraFieldUnicodePath, PROPERTY_NAME_FILENAME, PROPERTY_NAME_RAW_FILENAME, directory, fileEntry);
directory.extraFieldUnicodePath = extraFieldUnicodePath;
}
const extraFieldUnicodeComment = extraField.get(EXTRAFIELD_TYPE_UNICODE_COMMENT);
if (extraFieldUnicodeComment) {
readExtraFieldUnicode(extraFieldUnicodeComment, PROPERTY_NAME_COMMENT, PROPERTY_NAME_RAW_COMMENT, directory, fileEntry);
directory.extraFieldUnicodeComment = extraFieldUnicodeComment;
}
const extraFieldAES = extraField.get(EXTRAFIELD_TYPE_AES);
if (extraFieldAES) {
readExtraFieldAES(extraFieldAES, directory, compressionMethod);
directory.extraFieldAES = extraFieldAES;
} else {
directory.compressionMethod = compressionMethod;
}
const extraFieldNTFS = extraField.get(EXTRAFIELD_TYPE_NTFS);
if (extraFieldNTFS) {
readExtraFieldNTFS(extraFieldNTFS, directory);
directory.extraFieldNTFS = extraFieldNTFS;
}
const extraFieldExtendedTimestamp = extraField.get(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
if (extraFieldExtendedTimestamp) {
readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory);
directory.extraFieldExtendedTimestamp = extraFieldExtendedTimestamp;
}
const extraFieldUSDZ = extraField.get(EXTRAFIELD_TYPE_USDZ);
if (extraFieldUSDZ) {
directory.extraFieldUSDZ = extraFieldUSDZ;
}
}
function readExtraFieldZip64(extraFieldZip64, directory) {
directory.zip64 = true;
const extraFieldView = getDataView(extraFieldZip64.data);
const missingProperties = ZIP64_PROPERTIES.filter(([propertyName, max3]) => directory[propertyName] == max3);
for (let indexMissingProperty = 0, offset = 0; indexMissingProperty < missingProperties.length; indexMissingProperty++) {
const [propertyName, max3] = missingProperties[indexMissingProperty];
if (directory[propertyName] == max3) {
const extraction = ZIP64_EXTRACTION[max3];
directory[propertyName] = extraFieldZip64[propertyName] = extraction.getValue(extraFieldView, offset);
offset += extraction.bytes;
} else if (extraFieldZip64[propertyName]) {
throw new Error(ERR_EXTRAFIELD_ZIP64_NOT_FOUND);
}
}
}
function readExtraFieldUnicode(extraFieldUnicode, propertyName, rawPropertyName, directory, fileEntry) {
const extraFieldView = getDataView(extraFieldUnicode.data);
const crc32 = new Crc32();
crc32.append(fileEntry[rawPropertyName]);
const dataViewSignature = getDataView(new Uint8Array(4));
dataViewSignature.setUint32(0, crc32.get(), true);
const signature = getUint32(extraFieldView, 1);
Object.assign(extraFieldUnicode, {
version: getUint8(extraFieldView, 0),
[propertyName]: decodeText(extraFieldUnicode.data.subarray(5)),
valid: !fileEntry.bitFlag.languageEncodingFlag && signature == getUint32(dataViewSignature, 0)
});
if (extraFieldUnicode.valid) {
directory[propertyName] = extraFieldUnicode[propertyName];
directory[propertyName + "UTF8"] = true;
}
}
function readExtraFieldAES(extraFieldAES, directory, compressionMethod) {
const extraFieldView = getDataView(extraFieldAES.data);
const strength = getUint8(extraFieldView, 4);
Object.assign(extraFieldAES, {
vendorVersion: getUint8(extraFieldView, 0),
vendorId: getUint8(extraFieldView, 2),
strength,
originalCompressionMethod: compressionMethod,
compressionMethod: getUint16(extraFieldView, 5)
});
directory.compressionMethod = extraFieldAES.compressionMethod;
}
function readExtraFieldNTFS(extraFieldNTFS, directory) {
const extraFieldView = getDataView(extraFieldNTFS.data);
let offsetExtraField = 4;
let tag1Data;
try {
while (offsetExtraField < extraFieldNTFS.data.length && !tag1Data) {
const tagValue = getUint16(extraFieldView, offsetExtraField);
const attributeSize = getUint16(extraFieldView, offsetExtraField + 2);
if (tagValue == EXTRAFIELD_TYPE_NTFS_TAG1) {
tag1Data = extraFieldNTFS.data.slice(offsetExtraField + 4, offsetExtraField + 4 + attributeSize);
}
offsetExtraField += 4 + attributeSize;
}
} catch (_) {
}
try {
if (tag1Data && tag1Data.length == 24) {
const tag1View = getDataView(tag1Data);
const rawLastModDate = tag1View.getBigUint64(0, true);
const rawLastAccessDate = tag1View.getBigUint64(8, true);
const rawCreationDate = tag1View.getBigUint64(16, true);
Object.assign(extraFieldNTFS, {
rawLastModDate,
rawLastAccessDate,
rawCreationDate
});
const lastModDate = getDateNTFS(rawLastModDate);
const lastAccessDate = getDateNTFS(rawLastAccessDate);
const creationDate = getDateNTFS(rawCreationDate);
const extraFieldData = { lastModDate, lastAccessDate, creationDate };
Object.assign(extraFieldNTFS, extraFieldData);
Object.assign(directory, extraFieldData);
}
} catch (_) {
}
}
function readExtraFieldExtendedTimestamp(extraFieldExtendedTimestamp, directory, localDirectory) {
const extraFieldView = getDataView(extraFieldExtendedTimestamp.data);
const flags = getUint8(extraFieldView, 0);
const timeProperties = [];
const timeRawProperties = [];
if (localDirectory) {
if ((flags & 1) == 1) {
timeProperties.push(PROPERTY_NAME_LAST_MODIFICATION_DATE);
timeRawProperties.push(PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE);
}
if ((flags & 2) == 2) {
timeProperties.push(PROPERTY_NAME_LAST_ACCESS_DATE);
timeRawProperties.push(PROPERTY_NAME_RAW_LAST_ACCESS_DATE);
}
if ((flags & 4) == 4) {
timeProperties.push(PROPERTY_NAME_CREATION_DATE);
timeRawProperties.push(PROPERTY_NAME_RAW_CREATION_DATE);
}
} else if (extraFieldExtendedTimestamp.data.length >= 5) {
timeProperties.push(PROPERTY_NAME_LAST_MODIFICATION_DATE);
timeRawProperties.push(PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE);
}
let offset = 1;
timeProperties.forEach((propertyName, indexProperty) => {
if (extraFieldExtendedTimestamp.data.length >= offset + 4) {
const time = getUint32(extraFieldView, offset);
directory[propertyName] = extraFieldExtendedTimestamp[propertyName] = new Date(time * 1e3);
const rawPropertyName = timeRawProperties[indexProperty];
extraFieldExtendedTimestamp[rawPropertyName] = time;
}
offset += 4;
});
}
async function detectOverlappingEntry({
reader,
fileEntry,
offset,
diskNumberStart,
signature,
compressedSize,
uncompressedSize,
dataOffset,
dataDescriptor,
extraFieldZip64,
readRanges
}) {
let diskOffset = 0;
if (diskNumberStart) {
for (let indexReader = 0; indexReader < diskNumberStart; indexReader++) {
const diskReader = reader.readers[indexReader];
diskOffset += diskReader.size;
}
}
let dataDescriptorLength = 0;
if (dataDescriptor) {
if (extraFieldZip64) {
dataDescriptorLength = DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH;
} else {
dataDescriptorLength = DATA_DESCRIPTOR_RECORD_LENGTH;
}
}
if (dataDescriptorLength) {
const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, diskNumberStart);
const dataDescriptorSignature = getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
if (dataDescriptorSignature) {
const readSignature = getUint32(getDataView(dataDescriptorArray), 4);
let readCompressedSize;
let readUncompressedSize;
if (extraFieldZip64) {
readCompressedSize = getBigUint64(getDataView(dataDescriptorArray), 8);
readUncompressedSize = getBigUint64(getDataView(dataDescriptorArray), 16);
} else {
readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
}
const matchSignature = fileEntry.encrypted && !fileEntry.zipCrypto || readSignature == signature;
if (matchSignature && readCompressedSize == compressedSize && readUncompressedSize == uncompressedSize) {
dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
}
}
}
const range = {
start: diskOffset + offset,
end: diskOffset + dataOffset + compressedSize + dataDescriptorLength,
fileEntry
};
for (const otherRange of readRanges) {
if (otherRange.fileEntry != fileEntry && range.start >= otherRange.start && range.start < otherRange.end) {
const error = new Error(ERR_OVERLAPPING_ENTRY);
error.overlappingEntry = otherRange.fileEntry;
throw error;
}
}
readRanges.push(range);
}
async function seekSignature(reader, signature, startOffset, minimumBytes, maximumLength) {
const signatureArray = new Uint8Array(4);
const signatureView = getDataView(signatureArray);
setUint32(signatureView, 0, signature);
const maximumBytes = minimumBytes + maximumLength;
return await seek(minimumBytes) || await seek(Math.min(maximumBytes, startOffset));
async function seek(length2) {
const offset = startOffset - length2;
const bytes = await readUint8Array(reader, offset, length2);
for (let indexByte = bytes.length - minimumBytes; indexByte >= 0; indexByte--) {
if (bytes[indexByte] == signatureArray[0] && bytes[indexByte + 1] == signatureArray[1] && bytes[indexByte + 2] == signatureArray[2] && bytes[indexByte + 3] == signatureArray[3]) {
return {
offset: offset + indexByte,
buffer: bytes.slice(indexByte, indexByte + minimumBytes).buffer
};
}
}
}
}
function getOptionValue(zipReader, options, name) {
return options[name] === UNDEFINED_VALUE ? zipReader.options[name] : options[name];
}
function getDate(timeRaw) {
const date = (timeRaw & 4294901760) >> 16, time = timeRaw & 65535;
try {
return new Date(1980 + ((date & 65024) >> 9), ((date & 480) >> 5) - 1, date & 31, (time & 63488) >> 11, (time & 2016) >> 5, (time & 31) * 2, 0);
} catch (_) {
}
}
function getDateNTFS(timeRaw) {
return new Date(Number(timeRaw / BigInt(1e4) - BigInt(116444736e5)));
}
function getUint8(view, offset) {
return view.getUint8(offset);
}
function getUint16(view, offset) {
return view.getUint16(offset, true);
}
function getUint32(view, offset) {
return view.getUint32(offset, true);
}
function getBigUint64(view, offset) {
return Number(view.getBigUint64(offset, true));
}
function setUint32(view, offset, value) {
view.setUint32(offset, value, true);
}
function getDataView(array) {
return new DataView(array.buffer);
}
// node_modules/@zip.js/zip.js/lib/core/zip-writer.js
var import_InlineWorkers989 = __toESM(require_InlineWorkers(), 1);
var ERR_DUPLICATED_NAME = "File already exists";
var ERR_INVALID_COMMENT = "Zip file comment exceeds 64KB";
var ERR_INVALID_ENTRY_COMMENT = "File entry comment exceeds 64KB";
var ERR_INVALID_ENTRY_NAME = "File entry name exceeds 64KB";
var ERR_INVALID_VERSION = "Version exceeds 65535";
var ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
var ERR_INVALID_EXTRAFIELD_TYPE = "Extra field type exceeds 65535";
var ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
var ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (make sure 'keepOrder' is set to 'true')";
var ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
var ERR_ZIP_NOT_EMPTY = "Zip file not empty";
var EXTRAFIELD_DATA_AES = new Uint8Array([7, 0, 2, 0, 65, 69, 3, 0, 0]);
var workers = 0;
var pendingEntries = [];
var ZipWriter = class {
constructor(writer, options = {}) {
writer = new GenericWriter(writer);
const addSplitZipSignature = writer.availableSize !== UNDEFINED_VALUE && writer.availableSize > 0 && writer.availableSize !== Infinity && writer.maxSize !== UNDEFINED_VALUE && writer.maxSize > 0 && writer.maxSize !== Infinity;
Object.assign(this, {
writer,
addSplitZipSignature,
options,
config: getConfiguration(),
files: /* @__PURE__ */ new Map(),
filenames: /* @__PURE__ */ new Set(),
offset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? writer.size || writer.writable.size || 0 : options[OPTION_OFFSET],
pendingEntriesSize: 0,
pendingAddFileCalls: /* @__PURE__ */ new Set(),
bufferedWrites: 0
});
}
async prependZip(reader) {
if (this.filenames.size) {
throw new Error(ERR_ZIP_NOT_EMPTY);
}
reader = new GenericReader(reader);
const zipReader = new ZipReader(reader.readable);
const entries2 = await zipReader.getEntries();
await zipReader.close();
await reader.readable.pipeTo(this.writer.writable, { preventClose: true, preventAbort: true });
this.writer.size = this.offset = reader.size;
this.filenames = new Set(entries2.map((entry) => entry.filename));
this.files = new Map(entries2.map((entry) => {
const {
version: version2,
compressionMethod,
lastModDate,
lastAccessDate,
creationDate,
rawFilename,
bitFlag,
encrypted,
uncompressedSize,
compressedSize,
diskOffset,
diskNumber,
zip64
} = entry;
let {
rawExtraFieldZip64,
rawExtraFieldAES,
rawExtraFieldExtendedTimestamp,
rawExtraFieldNTFS,
rawExtraField
} = entry;
const { level, languageEncodingFlag, dataDescriptor } = bitFlag;
rawExtraFieldZip64 = rawExtraFieldZip64 || new Uint8Array();
rawExtraFieldAES = rawExtraFieldAES || new Uint8Array();
rawExtraFieldExtendedTimestamp = rawExtraFieldExtendedTimestamp || new Uint8Array();
rawExtraFieldNTFS = rawExtraFieldNTFS || new Uint8Array();
rawExtraField = rawExtraField || new Uint8Array();
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
const zip64UncompressedSize = zip64 && uncompressedSize > MAX_32_BITS;
const zip64CompressedSize = zip64 && compressedSize > MAX_32_BITS;
const {
headerArray,
headerView
} = getHeaderArrayData({
version: version2,
bitFlag: getBitFlag(level, languageEncodingFlag, dataDescriptor, encrypted, compressionMethod),
compressionMethod,
uncompressedSize,
compressedSize,
lastModDate,
rawFilename,
zip64CompressedSize,
zip64UncompressedSize,
extraFieldLength
});
Object.assign(entry, {
zip64UncompressedSize,
zip64CompressedSize,
zip64Offset: zip64 && this.offset - diskOffset > MAX_32_BITS,
zip64DiskNumberStart: zip64 && diskNumber > MAX_16_BITS,
rawExtraFieldZip64,
rawExtraFieldAES,
rawExtraFieldExtendedTimestamp,
rawExtraFieldNTFS,
rawExtraField,
extendedTimestamp: rawExtraFieldExtendedTimestamp.length > 0 || rawExtraFieldNTFS.length > 0,
extraFieldExtendedTimestampFlag: 1 + (lastAccessDate ? 2 : 0) + (creationDate ? 4 : 0),
headerArray,
headerView
});
return [entry.filename, entry];
}));
}
async add(name = "", reader, options = {}) {
const zipWriter = this;
const {
pendingAddFileCalls,
config: config2
} = zipWriter;
if (workers < config2.maxWorkers) {
workers++;
} else {
await new Promise((resolve2) => pendingEntries.push(resolve2));
}
let promiseAddFile;
try {
name = name.trim();
if (zipWriter.filenames.has(name)) {
throw new Error(ERR_DUPLICATED_NAME);
}
zipWriter.filenames.add(name);
promiseAddFile = addFile(zipWriter, name, reader, options);
pendingAddFileCalls.add(promiseAddFile);
return await promiseAddFile;
} catch (error) {
zipWriter.filenames.delete(name);
throw error;
} finally {
pendingAddFileCalls.delete(promiseAddFile);
const pendingEntry = pendingEntries.shift();
if (pendingEntry) {
pendingEntry();
} else {
workers--;
}
}
}
remove(entry) {
const { filenames, files } = this;
if (typeof entry == "string") {
entry = files.get(entry);
}
if (entry && entry.filename !== UNDEFINED_VALUE) {
const { filename } = entry;
if (filenames.has(filename) && files.has(filename)) {
filenames.delete(filename);
files.delete(filename);
return true;
}
}
return false;
}
async close(comment = new Uint8Array(), options = {}) {
const zipWriter = this;
const { pendingAddFileCalls, writer } = this;
const { writable } = writer;
while (pendingAddFileCalls.size) {
await Promise.allSettled(Array.from(pendingAddFileCalls));
}
await closeFile(this, comment, options);
const preventClose = getOptionValue2(zipWriter, options, OPTION_PREVENT_CLOSE);
if (!preventClose) {
await writable.getWriter().close();
}
return writer.getData ? writer.getData() : writable;
}
};
async function addFile(zipWriter, name, reader, options) {
name = name.trim();
const msDosCompatible = getOptionValue2(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
const versionMadeBy = getOptionValue2(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
const executable = getOptionValue2(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
if (versionMadeBy > MAX_16_BITS) {
throw new Error(ERR_INVALID_VERSION);
}
let externalFileAttributes = getOptionValue2(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES, 0);
if (externalFileAttributes === 0) {
externalFileAttributes = getOptionValue2(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTE, 0);
}
if (!options[PROPERTY_NAME_DIRECTORY] && name.endsWith(DIRECTORY_SIGNATURE)) {
options[PROPERTY_NAME_DIRECTORY] = true;
}
const directory = getOptionValue2(zipWriter, options, PROPERTY_NAME_DIRECTORY);
if (directory) {
if (!name.endsWith(DIRECTORY_SIGNATURE)) {
name += DIRECTORY_SIGNATURE;
}
if (externalFileAttributes === 0) {
externalFileAttributes = FILE_ATTR_MSDOS_DIR_MASK;
if (!msDosCompatible) {
externalFileAttributes |= (FILE_ATTR_UNIX_TYPE_DIR | FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_DEFAULT_MASK) << 16;
}
}
} else if (!msDosCompatible && externalFileAttributes === 0) {
if (executable) {
externalFileAttributes = (FILE_ATTR_UNIX_EXECUTABLE_MASK | FILE_ATTR_UNIX_DEFAULT_MASK) << 16;
} else {
externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
}
}
const encode = getOptionValue2(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
let rawFilename = encode(name);
if (rawFilename === UNDEFINED_VALUE) {
rawFilename = encodeText(name);
}
if (getLength(rawFilename) > MAX_16_BITS) {
throw new Error(ERR_INVALID_ENTRY_NAME);
}
const comment = options[PROPERTY_NAME_COMMENT] || "";
let rawComment = encode(comment);
if (rawComment === UNDEFINED_VALUE) {
rawComment = encodeText(comment);
}
if (getLength(rawComment) > MAX_16_BITS) {
throw new Error(ERR_INVALID_ENTRY_COMMENT);
}
const version2 = getOptionValue2(zipWriter, options, PROPERTY_NAME_VERSION, VERSION_DEFLATE);
if (version2 > MAX_16_BITS) {
throw new Error(ERR_INVALID_VERSION);
}
const lastModDate = getOptionValue2(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, /* @__PURE__ */ new Date());
const lastAccessDate = getOptionValue2(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
const creationDate = getOptionValue2(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
let internalFileAttributes = getOptionValue2(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
if (internalFileAttributes === 0) {
internalFileAttributes = getOptionValue2(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTE, 0);
}
const passThrough = getOptionValue2(zipWriter, options, OPTION_PASS_THROUGH);
let password, rawPassword;
if (!passThrough) {
password = getOptionValue2(zipWriter, options, OPTION_PASSWORD);
rawPassword = getOptionValue2(zipWriter, options, OPTION_RAW_PASSWORD);
}
const encryptionStrength = getOptionValue2(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
const zipCrypto = getOptionValue2(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
const extendedTimestamp = getOptionValue2(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
const keepOrder = getOptionValue2(zipWriter, options, OPTION_KEEP_ORDER, true);
const level = getOptionValue2(zipWriter, options, OPTION_LEVEL);
const useWebWorkers = getOptionValue2(zipWriter, options, OPTION_USE_WEB_WORKERS);
const bufferedWrite = getOptionValue2(zipWriter, options, OPTION_BUFFERED_WRITE);
const dataDescriptorSignature = getOptionValue2(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, false);
const signal = getOptionValue2(zipWriter, options, OPTION_SIGNAL);
const useUnicodeFileNames = getOptionValue2(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES, true);
const useCompressionStream = getOptionValue2(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
const compressionMethod = getOptionValue2(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
let dataDescriptor = getOptionValue2(zipWriter, options, OPTION_DATA_DESCRIPTOR);
if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
dataDescriptor = false;
}
if (dataDescriptor === UNDEFINED_VALUE || zipCrypto) {
dataDescriptor = true;
}
let zip64 = getOptionValue2(zipWriter, options, PROPERTY_NAME_ZIP64);
if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
}
let rawExtraField = new Uint8Array();
const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
if (extraField) {
let extraFieldSize = 0;
let offset = 0;
extraField.forEach((data) => extraFieldSize += 4 + getLength(data));
rawExtraField = new Uint8Array(extraFieldSize);
extraField.forEach((data, type) => {
if (type > MAX_16_BITS) {
throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
}
if (getLength(data) > MAX_16_BITS) {
throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
}
arraySet(rawExtraField, new Uint16Array([type]), offset);
arraySet(rawExtraField, new Uint16Array([getLength(data)]), offset + 2);
arraySet(rawExtraField, data, offset + 4);
offset += 4 + getLength(data);
});
}
let maximumCompressedSize = 0;
let maximumEntrySize = 0;
let uncompressedSize = 0;
if (passThrough) {
uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
if (uncompressedSize === UNDEFINED_VALUE) {
throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
}
}
const zip64Enabled = zip64 === true;
if (reader) {
reader = new GenericReader(reader);
await initStream(reader);
if (!passThrough) {
if (reader.size === UNDEFINED_VALUE) {
dataDescriptor = true;
if (zip64 || zip64 === UNDEFINED_VALUE) {
zip64 = true;
uncompressedSize = maximumCompressedSize = MAX_32_BITS + 1;
}
} else {
options.uncompressedSize = uncompressedSize = reader.size;
maximumCompressedSize = getMaximumCompressedSize2(uncompressedSize);
}
} else {
options.uncompressedSize = uncompressedSize;
maximumCompressedSize = getMaximumCompressedSize2(uncompressedSize);
}
}
const { diskOffset, diskNumber, maxSize } = zipWriter.writer;
const zip64UncompressedSize = zip64Enabled || uncompressedSize > MAX_32_BITS;
const zip64CompressedSize = zip64Enabled || maximumCompressedSize > MAX_32_BITS;
const zip64Offset = zip64Enabled || zipWriter.offset + zipWriter.pendingEntriesSize - diskOffset > MAX_32_BITS;
const supportZip64SplitFile = getOptionValue2(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
const zip64DiskNumberStart = supportZip64SplitFile && zip64Enabled || diskNumber + Math.ceil(zipWriter.pendingEntriesSize / maxSize) > MAX_16_BITS;
if (zip64Offset || zip64UncompressedSize || zip64CompressedSize || zip64DiskNumberStart) {
if (zip64 === false || !keepOrder) {
throw new Error(ERR_UNSUPPORTED_FORMAT);
} else {
zip64 = true;
}
}
zip64 = zip64 || false;
const encrypted = getOptionValue2(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
options = Object.assign({}, options, {
rawFilename,
rawComment,
version: version2,
versionMadeBy,
lastModDate,
lastAccessDate,
creationDate,
rawExtraField,
zip64,
zip64UncompressedSize,
zip64CompressedSize,
zip64Offset,
zip64DiskNumberStart,
password,
rawPassword,
level: !useCompressionStream && (zipWriter.config.CompressionStream === UNDEFINED_VALUE && zipWriter.config.CompressionStreamNative === UNDEFINED_VALUE) ? 0 : level,
useWebWorkers,
encryptionStrength,
extendedTimestamp,
zipCrypto,
bufferedWrite,
keepOrder,
useUnicodeFileNames,
dataDescriptor,
dataDescriptorSignature,
signal,
msDosCompatible,
internalFileAttribute: internalFileAttributes,
internalFileAttributes,
externalFileAttribute: externalFileAttributes,
externalFileAttributes,
useCompressionStream,
passThrough,
encrypted: Boolean(password && getLength(password) || rawPassword && getLength(rawPassword)) || passThrough && encrypted,
signature: options[PROPERTY_NAME_SIGNATURE],
compressionMethod,
uncompressedSize,
offset: zipWriter.offset - diskOffset,
diskNumberStart: diskNumber
});
const headerInfo = getHeaderInfo(options);
const dataDescriptorInfo = getDataDescriptorInfo(options);
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
maximumEntrySize = metadataSize + maximumCompressedSize;
if (zipWriter.options[OPTION_USDZ]) {
maximumEntrySize += maximumEntrySize + 64;
}
zipWriter.pendingEntriesSize += maximumEntrySize;
let fileEntry;
try {
fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo, metadataSize }, options);
} finally {
zipWriter.pendingEntriesSize -= maximumEntrySize;
}
Object.assign(fileEntry, { name, comment, extraField });
return new Entry(fileEntry);
}
async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
const {
files,
writer
} = zipWriter;
const {
keepOrder,
dataDescriptor,
signal
} = options;
const {
headerInfo
} = entryInfo;
const usdz = zipWriter.options[OPTION_USDZ];
const previousFileEntry = Array.from(files.values()).pop();
let fileEntry = {};
let bufferedWrite;
let releaseLockWriter;
let releaseLockCurrentFileEntry;
let writingBufferedEntryData;
let writingEntryData;
let fileWriter;
let blobPromise;
files.set(name, fileEntry);
try {
let lockPreviousFileEntry;
if (keepOrder) {
lockPreviousFileEntry = previousFileEntry && previousFileEntry.lock;
requestLockCurrentFileEntry();
}
if ((options.bufferedWrite || zipWriter.writerLocked || zipWriter.bufferedWrites && keepOrder || !dataDescriptor) && !usdz) {
fileWriter = new TransformStream();
fileWriter.size = 0;
bufferedWrite = true;
zipWriter.bufferedWrites++;
await initStream(writer);
} else {
fileWriter = writer;
await requestLockWriter();
}
await initStream(fileWriter);
const { writable, diskOffset } = writer;
if (zipWriter.addSplitZipSignature) {
delete zipWriter.addSplitZipSignature;
const signatureArray = new Uint8Array(4);
const signatureArrayView = getDataView2(signatureArray);
setUint322(signatureArrayView, 0, SPLIT_ZIP_FILE_SIGNATURE);
await writeData(writer, signatureArray);
zipWriter.offset += 4;
}
if (usdz) {
appendExtraFieldUSDZ(entryInfo, zipWriter.offset - diskOffset);
}
const {
localHeaderView,
localHeaderArray
} = headerInfo;
if (!bufferedWrite) {
await lockPreviousFileEntry;
await skipDiskIfNeeded(writable);
}
const { diskNumber } = writer;
writingEntryData = true;
fileEntry.diskNumberStart = diskNumber;
if (bufferedWrite) {
blobPromise = new Response(fileWriter.readable).blob();
} else {
await writeData(fileWriter, localHeaderArray);
}
fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo, zipWriter.config, options);
const { zip64 } = fileEntry;
writingEntryData = false;
files.set(name, fileEntry);
fileEntry.filename = name;
if (bufferedWrite) {
const [blob] = await Promise.all([blobPromise, fileWriter.writable.getWriter().close(), lockPreviousFileEntry]);
await requestLockWriter();
writingBufferedEntryData = true;
fileEntry.diskNumberStart = writer.diskNumber;
fileEntry.offset = zipWriter.offset - writer.diskOffset;
if (zip64) {
updateZip64ExtraField(fileEntry);
}
updateLocalHeader(fileEntry, localHeaderView, options);
await skipDiskIfNeeded(writable);
await writeData(writer, localHeaderArray);
await blob.stream().pipeTo(writable, { preventClose: true, preventAbort: true, signal });
writer.size += fileWriter.size;
writingBufferedEntryData = false;
} else {
fileEntry.offset = zipWriter.offset - diskOffset;
if (zip64) {
updateZip64ExtraField(fileEntry);
}
}
if (fileEntry.offset > MAX_32_BITS && !zip64) {
throw new Error(ERR_UNSUPPORTED_FORMAT);
}
zipWriter.offset += fileEntry.size;
return fileEntry;
} catch (error) {
if (bufferedWrite && writingBufferedEntryData || !bufferedWrite && writingEntryData) {
zipWriter.hasCorruptedEntries = true;
if (error) {
try {
error.corruptedEntry = true;
} catch (_) {
}
}
if (bufferedWrite) {
zipWriter.offset += fileWriter.size;
} else {
zipWriter.offset = fileWriter.size;
}
}
files.delete(name);
throw error;
} finally {
if (bufferedWrite) {
zipWriter.bufferedWrites--;
}
if (releaseLockCurrentFileEntry) {
releaseLockCurrentFileEntry();
}
if (releaseLockWriter) {
releaseLockWriter();
}
}
function requestLockCurrentFileEntry() {
fileEntry.lock = new Promise((resolve2) => releaseLockCurrentFileEntry = resolve2);
}
async function requestLockWriter() {
zipWriter.writerLocked = true;
const { lockWriter } = zipWriter;
zipWriter.lockWriter = new Promise((resolve2) => releaseLockWriter = () => {
zipWriter.writerLocked = false;
resolve2();
});
await lockWriter;
}
async function skipDiskIfNeeded(writable) {
if (getLength(headerInfo.localHeaderArray) > writer.availableSize) {
writer.availableSize = 0;
await writeData(writable, new Uint8Array());
}
}
}
async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryInfo, config2, options) {
const {
headerInfo,
dataDescriptorInfo,
metadataSize
} = entryInfo;
const {
headerArray,
headerView,
lastModDate,
rawLastModDate,
encrypted,
compressed,
version: version2,
compressionMethod,
rawExtraFieldZip64,
localExtraFieldZip64Length,
rawExtraFieldExtendedTimestamp,
extraFieldExtendedTimestampFlag,
rawExtraFieldNTFS,
rawExtraFieldAES
} = headerInfo;
const { dataDescriptorArray } = dataDescriptorInfo;
const {
rawFilename,
lastAccessDate,
creationDate,
password,
rawPassword,
level,
zip64,
zip64UncompressedSize,
zip64CompressedSize,
zip64Offset,
zip64DiskNumberStart,
zipCrypto,
dataDescriptor,
directory,
executable,
versionMadeBy,
rawComment,
rawExtraField,
useWebWorkers,
onstart,
onprogress,
onend,
signal,
encryptionStrength,
extendedTimestamp,
msDosCompatible,
internalFileAttributes,
externalFileAttributes,
useCompressionStream,
passThrough
} = options;
const fileEntry = {
lock,
versionMadeBy,
zip64,
directory: Boolean(directory),
executable: Boolean(executable),
filenameUTF8: true,
rawFilename,
commentUTF8: true,
rawComment,
rawExtraFieldZip64,
localExtraFieldZip64Length,
rawExtraFieldExtendedTimestamp,
rawExtraFieldNTFS,
rawExtraFieldAES,
rawExtraField,
extendedTimestamp,
msDosCompatible,
internalFileAttributes,
externalFileAttributes,
diskNumberStart
};
let {
signature,
uncompressedSize
} = options;
let compressedSize = 0;
if (!passThrough) {
uncompressedSize = 0;
}
const { writable } = writer;
if (reader) {
reader.chunkSize = getChunkSize(config2);
const readable = reader.readable;
const size = reader.size;
const workerOptions = {
options: {
codecType: CODEC_DEFLATE,
level,
rawPassword,
password,
encryptionStrength,
zipCrypto: encrypted && zipCrypto,
passwordVerification: encrypted && zipCrypto && rawLastModDate >> 8 & 255,
signed: !passThrough,
compressed: compressed && !passThrough,
encrypted: encrypted && !passThrough,
useWebWorkers,
useCompressionStream,
transferStreams: false
},
config: config2,
streamOptions: { signal, size, onstart, onprogress, onend }
};
try {
const result = await runWorker2({ readable, writable }, workerOptions);
compressedSize = result.outputSize;
writer.size += compressedSize;
if (!passThrough) {
uncompressedSize = result.inputSize;
signature = result.signature;
}
} catch (error) {
if (error.outputSize !== UNDEFINED_VALUE) {
writer.size += error.outputSize;
}
throw error;
}
}
setEntryInfo({
signature,
compressedSize,
uncompressedSize,
headerInfo,
dataDescriptorInfo
}, options);
if (dataDescriptor) {
await writeData(writer, dataDescriptorArray);
}
Object.assign(fileEntry, {
uncompressedSize,
compressedSize,
lastModDate,
rawLastModDate,
creationDate,
lastAccessDate,
encrypted,
zipCrypto,
size: metadataSize + compressedSize,
compressionMethod,
version: version2,
headerArray,
headerView,
signature,
extraFieldExtendedTimestampFlag,
zip64UncompressedSize,
zip64CompressedSize,
zip64Offset,
zip64DiskNumberStart
});
return fileEntry;
}
function getHeaderInfo(options) {
const {
rawFilename,
lastModDate,
lastAccessDate,
creationDate,
level,
zip64,
zipCrypto,
useUnicodeFileNames,
dataDescriptor,
directory,
rawExtraField,
encryptionStrength,
extendedTimestamp,
passThrough,
encrypted,
zip64UncompressedSize,
zip64CompressedSize,
zip64Offset,
zip64DiskNumberStart,
uncompressedSize,
offset,
diskNumberStart
} = options;
let { version: version2, compressionMethod } = options;
const compressed = !directory && (level > 0 || level === UNDEFINED_VALUE && compressionMethod !== 0);
let rawExtraFieldZip64;
const uncompressedFile = passThrough || !compressed;
const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || (!zip64UncompressedSize && !zip64CompressedSize || uncompressedFile));
if (zip64) {
let rawExtraFieldZip64Length = 4;
if (zip64UncompressedSize) {
rawExtraFieldZip64Length += 8;
}
if (zip64CompressedSize) {
rawExtraFieldZip64Length += 8;
}
if (zip64Offset) {
rawExtraFieldZip64Length += 8;
}
if (zip64DiskNumberStart) {
rawExtraFieldZip64Length += 4;
}
rawExtraFieldZip64 = new Uint8Array(rawExtraFieldZip64Length);
const rawExtraFieldZip64View = getDataView2(rawExtraFieldZip64);
setUint16(rawExtraFieldZip64View, 0, EXTRAFIELD_TYPE_ZIP64);
setUint16(rawExtraFieldZip64View, 2, getLength(rawExtraFieldZip64) - 4);
if (zip64ExtraFieldComplete) {
const rawExtraFieldZip64View2 = getDataView2(rawExtraFieldZip64);
let rawExtraFieldZip64Offset = 4;
if (zip64UncompressedSize) {
setBigUint64(rawExtraFieldZip64View2, rawExtraFieldZip64Offset, BigInt(uncompressedSize));
rawExtraFieldZip64Offset += 8;
}
if (zip64CompressedSize && uncompressedFile) {
setBigUint64(rawExtraFieldZip64View2, rawExtraFieldZip64Offset, BigInt(uncompressedSize));
rawExtraFieldZip64Offset += 8;
}
if (zip64Offset) {
setBigUint64(rawExtraFieldZip64View2, rawExtraFieldZip64Offset, BigInt(offset));
rawExtraFieldZip64Offset += 8;
}
if (zip64DiskNumberStart) {
setUint322(rawExtraFieldZip64View2, rawExtraFieldZip64Offset, diskNumberStart);
rawExtraFieldZip64Offset += 4;
}
}
} else {
rawExtraFieldZip64 = new Uint8Array();
}
let rawExtraFieldAES;
if (encrypted && !zipCrypto) {
rawExtraFieldAES = new Uint8Array(getLength(EXTRAFIELD_DATA_AES) + 2);
const extraFieldAESView = getDataView2(rawExtraFieldAES);
setUint16(extraFieldAESView, 0, EXTRAFIELD_TYPE_AES);
arraySet(rawExtraFieldAES, EXTRAFIELD_DATA_AES, 2);
setUint8(extraFieldAESView, 8, encryptionStrength);
} else {
rawExtraFieldAES = new Uint8Array();
}
let rawExtraFieldNTFS;
let rawExtraFieldExtendedTimestamp;
let extraFieldExtendedTimestampFlag;
if (extendedTimestamp) {
rawExtraFieldExtendedTimestamp = new Uint8Array(9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0));
const extraFieldExtendedTimestampView = getDataView2(rawExtraFieldExtendedTimestamp);
setUint16(extraFieldExtendedTimestampView, 0, EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
setUint16(extraFieldExtendedTimestampView, 2, getLength(rawExtraFieldExtendedTimestamp) - 4);
extraFieldExtendedTimestampFlag = 1 + (lastAccessDate ? 2 : 0) + (creationDate ? 4 : 0);
setUint8(extraFieldExtendedTimestampView, 4, extraFieldExtendedTimestampFlag);
let offset2 = 5;
setUint322(extraFieldExtendedTimestampView, offset2, Math.floor(lastModDate.getTime() / 1e3));
offset2 += 4;
if (lastAccessDate) {
setUint322(extraFieldExtendedTimestampView, offset2, Math.floor(lastAccessDate.getTime() / 1e3));
offset2 += 4;
}
if (creationDate) {
setUint322(extraFieldExtendedTimestampView, offset2, Math.floor(creationDate.getTime() / 1e3));
}
try {
rawExtraFieldNTFS = new Uint8Array(36);
const extraFieldNTFSView = getDataView2(rawExtraFieldNTFS);
const lastModTimeNTFS = getTimeNTFS(lastModDate);
setUint16(extraFieldNTFSView, 0, EXTRAFIELD_TYPE_NTFS);
setUint16(extraFieldNTFSView, 2, 32);
setUint16(extraFieldNTFSView, 8, EXTRAFIELD_TYPE_NTFS_TAG1);
setUint16(extraFieldNTFSView, 10, 24);
setBigUint64(extraFieldNTFSView, 12, lastModTimeNTFS);
setBigUint64(extraFieldNTFSView, 20, getTimeNTFS(lastAccessDate) || lastModTimeNTFS);
setBigUint64(extraFieldNTFSView, 28, getTimeNTFS(creationDate) || lastModTimeNTFS);
} catch (_) {
rawExtraFieldNTFS = new Uint8Array();
}
} else {
rawExtraFieldNTFS = rawExtraFieldExtendedTimestamp = new Uint8Array();
}
if (compressionMethod === UNDEFINED_VALUE) {
compressionMethod = compressed ? COMPRESSION_METHOD_DEFLATE : COMPRESSION_METHOD_STORE;
}
if (zip64) {
version2 = version2 > VERSION_ZIP64 ? version2 : VERSION_ZIP64;
}
if (encrypted && !zipCrypto) {
version2 = version2 > VERSION_AES ? version2 : VERSION_AES;
rawExtraFieldAES[9] = compressionMethod;
compressionMethod = COMPRESSION_METHOD_AES;
}
const localExtraFieldZip64Length = zip64ExtraFieldComplete ? getLength(rawExtraFieldZip64) : 0;
const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
const {
headerArray,
headerView,
rawLastModDate
} = getHeaderArrayData({
version: version2,
bitFlag: getBitFlag(level, useUnicodeFileNames, dataDescriptor, encrypted, compressionMethod),
compressionMethod,
uncompressedSize,
lastModDate: lastModDate < MIN_DATE ? MIN_DATE : lastModDate > MAX_DATE ? MAX_DATE : lastModDate,
rawFilename,
zip64CompressedSize,
zip64UncompressedSize,
extraFieldLength
});
let localHeaderOffset = HEADER_SIZE2;
const localHeaderArray = new Uint8Array(localHeaderOffset + getLength(rawFilename) + extraFieldLength);
const localHeaderView = getDataView2(localHeaderArray);
setUint322(localHeaderView, 0, LOCAL_FILE_HEADER_SIGNATURE);
arraySet(localHeaderArray, headerArray, 4);
arraySet(localHeaderArray, rawFilename, localHeaderOffset);
localHeaderOffset += getLength(rawFilename);
if (zip64ExtraFieldComplete) {
arraySet(localHeaderArray, rawExtraFieldZip64, localHeaderOffset);
}
localHeaderOffset += localExtraFieldZip64Length;
arraySet(localHeaderArray, rawExtraFieldAES, localHeaderOffset);
localHeaderOffset += getLength(rawExtraFieldAES);
arraySet(localHeaderArray, rawExtraFieldExtendedTimestamp, localHeaderOffset);
localHeaderOffset += getLength(rawExtraFieldExtendedTimestamp);
arraySet(localHeaderArray, rawExtraFieldNTFS, localHeaderOffset);
localHeaderOffset += getLength(rawExtraFieldNTFS);
arraySet(localHeaderArray, rawExtraField, localHeaderOffset);
if (dataDescriptor) {
setUint322(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + 4, 0);
setUint322(localHeaderView, HEADER_OFFSET_UNCOMPRESSED_SIZE + 4, 0);
}
return {
localHeaderArray,
localHeaderView,
headerArray,
headerView,
lastModDate,
rawLastModDate,
encrypted,
compressed,
version: version2,
compressionMethod,
extraFieldExtendedTimestampFlag,
rawExtraFieldZip64,
localExtraFieldZip64Length,
rawExtraFieldExtendedTimestamp,
rawExtraFieldNTFS,
rawExtraFieldAES,
extraFieldLength
};
}
function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
const { headerInfo } = entryInfo;
let { localHeaderArray, extraFieldLength } = headerInfo;
let localHeaderArrayView = getDataView2(localHeaderArray);
let extraBytesLength = 64 - (zipWriterOffset + getLength(localHeaderArray)) % 64;
if (extraBytesLength < 4) {
extraBytesLength += 64;
}
const rawExtraFieldUSDZ = new Uint8Array(extraBytesLength);
const extraFieldUSDZView = getDataView2(rawExtraFieldUSDZ);
setUint16(extraFieldUSDZView, 0, EXTRAFIELD_TYPE_USDZ);
setUint16(extraFieldUSDZView, 2, extraBytesLength - 2);
const previousLocalHeaderArray = localHeaderArray;
headerInfo.localHeaderArray = localHeaderArray = new Uint8Array(getLength(previousLocalHeaderArray) + extraBytesLength);
arraySet(localHeaderArray, previousLocalHeaderArray);
arraySet(localHeaderArray, rawExtraFieldUSDZ, getLength(previousLocalHeaderArray));
localHeaderArrayView = getDataView2(localHeaderArray);
setUint16(localHeaderArrayView, 28, extraFieldLength + extraBytesLength);
entryInfo.metadataSize += extraBytesLength;
}
function getDataDescriptorInfo({
zip64,
dataDescriptor,
dataDescriptorSignature
}) {
let dataDescriptorArray = new Uint8Array();
let dataDescriptorView, dataDescriptorOffset = 0;
let dataDescriptorLength = zip64 ? DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH : DATA_DESCRIPTOR_RECORD_LENGTH;
if (dataDescriptorSignature) {
dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
}
if (dataDescriptor) {
dataDescriptorArray = new Uint8Array(dataDescriptorLength);
dataDescriptorView = getDataView2(dataDescriptorArray);
if (dataDescriptorSignature) {
dataDescriptorOffset = DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
setUint322(dataDescriptorView, 0, DATA_DESCRIPTOR_RECORD_SIGNATURE);
}
}
return {
dataDescriptorArray,
dataDescriptorView,
dataDescriptorOffset
};
}
function setEntryInfo({
signature,
compressedSize,
uncompressedSize,
headerInfo,
dataDescriptorInfo
}, {
zip64,
zipCrypto,
dataDescriptor
}) {
const {
headerView,
encrypted
} = headerInfo;
const {
dataDescriptorView,
dataDescriptorOffset
} = dataDescriptorInfo;
if ((!encrypted || zipCrypto) && signature !== UNDEFINED_VALUE) {
setUint322(headerView, HEADER_OFFSET_SIGNATURE, signature);
if (dataDescriptor) {
setUint322(dataDescriptorView, dataDescriptorOffset, signature);
}
}
if (zip64) {
if (dataDescriptor) {
setBigUint64(dataDescriptorView, dataDescriptorOffset + 4, BigInt(compressedSize));
setBigUint64(dataDescriptorView, dataDescriptorOffset + 12, BigInt(uncompressedSize));
}
} else {
setUint322(headerView, HEADER_OFFSET_COMPRESSED_SIZE, compressedSize);
setUint322(headerView, HEADER_OFFSET_UNCOMPRESSED_SIZE, uncompressedSize);
if (dataDescriptor) {
setUint322(dataDescriptorView, dataDescriptorOffset + 4, compressedSize);
setUint322(dataDescriptorView, dataDescriptorOffset + 8, uncompressedSize);
}
}
}
function updateLocalHeader({
rawFilename,
encrypted,
zip64,
localExtraFieldZip64Length,
signature,
compressedSize,
uncompressedSize,
offset,
diskNumberStart,
zip64UncompressedSize,
zip64CompressedSize,
zip64Offset,
zip64DiskNumberStart
}, localHeaderView, { dataDescriptor }) {
if (!dataDescriptor) {
if (!encrypted) {
setUint322(localHeaderView, HEADER_OFFSET_SIGNATURE + 4, signature);
}
if (!zip64) {
setUint322(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + 4, compressedSize);
setUint322(localHeaderView, HEADER_OFFSET_UNCOMPRESSED_SIZE + 4, uncompressedSize);
}
}
if (zip64) {
if (localExtraFieldZip64Length) {
let localHeaderOffset = HEADER_SIZE2 + getLength(rawFilename) + 4;
if (zip64UncompressedSize) {
setBigUint64(localHeaderView, localHeaderOffset, BigInt(uncompressedSize));
localHeaderOffset += 8;
}
if (zip64CompressedSize) {
setBigUint64(localHeaderView, localHeaderOffset, BigInt(compressedSize));
localHeaderOffset += 8;
}
if (zip64Offset) {
setBigUint64(localHeaderView, localHeaderOffset, BigInt(offset));
localHeaderOffset += 8;
}
if (zip64DiskNumberStart) {
setUint322(localHeaderView, localHeaderOffset, diskNumberStart);
}
}
}
}
function updateZip64ExtraField({
compressedSize,
uncompressedSize,
offset,
diskNumberStart,
zip64UncompressedSize,
zip64CompressedSize,
zip64Offset,
zip64DiskNumberStart,
rawExtraFieldZip64
}) {
const rawExtraFieldZip64View = getDataView2(rawExtraFieldZip64);
let rawExtraFieldZip64Offset = 4;
if (zip64UncompressedSize) {
setBigUint64(rawExtraFieldZip64View, rawExtraFieldZip64Offset, BigInt(uncompressedSize));
rawExtraFieldZip64Offset += 8;
}
if (zip64CompressedSize) {
setBigUint64(rawExtraFieldZip64View, rawExtraFieldZip64Offset, BigInt(compressedSize));
rawExtraFieldZip64Offset += 8;
}
if (zip64Offset) {
setBigUint64(rawExtraFieldZip64View, rawExtraFieldZip64Offset, BigInt(offset));
rawExtraFieldZip64Offset += 8;
}
if (zip64DiskNumberStart) {
setUint322(rawExtraFieldZip64View, rawExtraFieldZip64Offset, diskNumberStart);
}
}
async function closeFile(zipWriter, comment, options) {
const { files, writer } = zipWriter;
const { diskOffset } = writer;
let { diskNumber } = writer;
let offset = 0;
let directoryDataLength = 0;
let directoryOffset = zipWriter.offset - diskOffset;
let filesLength = files.size;
for (const [, fileEntry] of files) {
const {
rawFilename,
rawExtraFieldZip64,
rawExtraFieldAES,
rawComment,
rawExtraFieldNTFS,
rawExtraField,
extendedTimestamp,
extraFieldExtendedTimestampFlag,
lastModDate
} = fileEntry;
let rawExtraFieldTimestamp;
if (extendedTimestamp) {
rawExtraFieldTimestamp = new Uint8Array(9);
const extraFieldExtendedTimestampView = getDataView2(rawExtraFieldTimestamp);
setUint16(extraFieldExtendedTimestampView, 0, EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
setUint16(extraFieldExtendedTimestampView, 2, 5);
setUint8(extraFieldExtendedTimestampView, 4, extraFieldExtendedTimestampFlag);
setUint322(extraFieldExtendedTimestampView, 5, Math.floor(lastModDate.getTime() / 1e3));
} else {
rawExtraFieldTimestamp = new Uint8Array();
}
fileEntry.rawExtraFieldExtendedTimestamp = rawExtraFieldTimestamp;
directoryDataLength += 46 + getLength(
rawFilename,
rawComment,
rawExtraFieldZip64,
rawExtraFieldAES,
rawExtraFieldNTFS,
rawExtraFieldTimestamp,
rawExtraField
);
}
const directoryArray = new Uint8Array(directoryDataLength);
const directoryView = getDataView2(directoryArray);
await initStream(writer);
let directoryDiskOffset = 0;
for (const [indexFileEntry, fileEntry] of Array.from(files.values()).entries()) {
const {
offset: fileEntryOffset,
rawFilename,
rawExtraFieldZip64,
rawExtraFieldAES,
rawExtraFieldExtendedTimestamp,
rawExtraFieldNTFS,
rawExtraField,
rawComment,
versionMadeBy,
headerArray,
headerView,
zip64: zip642,
zip64UncompressedSize,
zip64CompressedSize,
zip64DiskNumberStart,
zip64Offset,
internalFileAttributes,
externalFileAttributes,
diskNumberStart,
uncompressedSize,
compressedSize
} = fileEntry;
const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraField);
setUint322(directoryView, offset, CENTRAL_FILE_HEADER_SIGNATURE);
setUint16(directoryView, offset + 4, versionMadeBy);
if (!zip64UncompressedSize) {
setUint322(headerView, HEADER_OFFSET_UNCOMPRESSED_SIZE, uncompressedSize);
}
if (!zip64CompressedSize) {
setUint322(headerView, HEADER_OFFSET_COMPRESSED_SIZE, compressedSize);
}
arraySet(directoryArray, headerArray, offset + 6);
let directoryOffset2 = offset + HEADER_SIZE2;
setUint16(directoryView, directoryOffset2, extraFieldLength);
directoryOffset2 += 2;
setUint16(directoryView, directoryOffset2, getLength(rawComment));
directoryOffset2 += 2;
setUint16(directoryView, directoryOffset2, zip642 && zip64DiskNumberStart ? MAX_16_BITS : diskNumberStart);
directoryOffset2 += 2;
setUint16(directoryView, directoryOffset2, internalFileAttributes);
directoryOffset2 += 2;
if (externalFileAttributes) {
setUint322(directoryView, directoryOffset2, externalFileAttributes);
}
directoryOffset2 += 4;
setUint322(directoryView, directoryOffset2, zip642 && zip64Offset ? MAX_32_BITS : fileEntryOffset);
directoryOffset2 += 4;
arraySet(directoryArray, rawFilename, directoryOffset2);
directoryOffset2 += getLength(rawFilename);
arraySet(directoryArray, rawExtraFieldZip64, directoryOffset2);
directoryOffset2 += getLength(rawExtraFieldZip64);
arraySet(directoryArray, rawExtraFieldAES, directoryOffset2);
directoryOffset2 += getLength(rawExtraFieldAES);
arraySet(directoryArray, rawExtraFieldExtendedTimestamp, directoryOffset2);
directoryOffset2 += getLength(rawExtraFieldExtendedTimestamp);
arraySet(directoryArray, rawExtraFieldNTFS, directoryOffset2);
directoryOffset2 += getLength(rawExtraFieldNTFS);
arraySet(directoryArray, rawExtraField, directoryOffset2);
directoryOffset2 += getLength(rawExtraField);
arraySet(directoryArray, rawComment, directoryOffset2);
if (offset - directoryDiskOffset > writer.availableSize) {
writer.availableSize = 0;
await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
directoryDiskOffset = offset;
}
offset = directoryOffset2;
if (options.onprogress) {
try {
await options.onprogress(indexFileEntry + 1, files.size, new Entry(fileEntry));
} catch (_) {
}
}
}
await writeData(writer, directoryDiskOffset ? directoryArray.slice(directoryDiskOffset) : directoryArray);
let lastDiskNumber = writer.diskNumber;
const { availableSize } = writer;
if (availableSize < END_OF_CENTRAL_DIR_LENGTH) {
lastDiskNumber++;
}
let zip64 = getOptionValue2(zipWriter, options, PROPERTY_NAME_ZIP64);
if (directoryOffset > MAX_32_BITS || directoryDataLength > MAX_32_BITS || filesLength > MAX_16_BITS || lastDiskNumber > MAX_16_BITS) {
if (zip64 === false) {
throw new Error(ERR_UNSUPPORTED_FORMAT);
} else {
zip64 = true;
}
}
const endOfdirectoryArray = new Uint8Array(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
const endOfdirectoryView = getDataView2(endOfdirectoryArray);
offset = 0;
if (zip64) {
setUint322(endOfdirectoryView, 0, ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
setBigUint64(endOfdirectoryView, 4, BigInt(44));
setUint16(endOfdirectoryView, 12, 45);
setUint16(endOfdirectoryView, 14, 45);
setUint322(endOfdirectoryView, 16, lastDiskNumber);
setUint322(endOfdirectoryView, 20, diskNumber);
setBigUint64(endOfdirectoryView, 24, BigInt(filesLength));
setBigUint64(endOfdirectoryView, 32, BigInt(filesLength));
setBigUint64(endOfdirectoryView, 40, BigInt(directoryDataLength));
setBigUint64(endOfdirectoryView, 48, BigInt(directoryOffset));
setUint322(endOfdirectoryView, 56, ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
setBigUint64(endOfdirectoryView, 64, BigInt(directoryOffset) + BigInt(directoryDataLength));
setUint322(endOfdirectoryView, 72, lastDiskNumber + 1);
const supportZip64SplitFile = getOptionValue2(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
if (supportZip64SplitFile) {
lastDiskNumber = MAX_16_BITS;
diskNumber = MAX_16_BITS;
}
filesLength = MAX_16_BITS;
directoryOffset = MAX_32_BITS;
directoryDataLength = MAX_32_BITS;
offset += ZIP64_END_OF_CENTRAL_DIR_LENGTH + ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH;
}
setUint322(endOfdirectoryView, offset, END_OF_CENTRAL_DIR_SIGNATURE);
setUint16(endOfdirectoryView, offset + 4, lastDiskNumber);
setUint16(endOfdirectoryView, offset + 6, diskNumber);
setUint16(endOfdirectoryView, offset + 8, filesLength);
setUint16(endOfdirectoryView, offset + 10, filesLength);
setUint322(endOfdirectoryView, offset + 12, directoryDataLength);
setUint322(endOfdirectoryView, offset + 16, directoryOffset);
const commentLength = getLength(comment);
if (commentLength) {
if (commentLength <= MAX_16_BITS) {
setUint16(endOfdirectoryView, offset + 20, commentLength);
} else {
throw new Error(ERR_INVALID_COMMENT);
}
}
await writeData(writer, endOfdirectoryArray);
if (commentLength) {
await writeData(writer, comment);
}
}
async function writeData(writer, array) {
const { writable } = writer;
const streamWriter = writable.getWriter();
try {
await streamWriter.ready;
writer.size += getLength(array);
await streamWriter.write(array);
} finally {
streamWriter.releaseLock();
}
}
function getTimeNTFS(date) {
if (date) {
return (BigInt(date.getTime()) + BigInt(116444736e5)) * BigInt(1e4);
}
}
function getOptionValue2(zipWriter, options, name, defaultValue2) {
const result = options[name] === UNDEFINED_VALUE ? zipWriter.options[name] : options[name];
return result === UNDEFINED_VALUE ? defaultValue2 : result;
}
function getMaximumCompressedSize2(uncompressedSize) {
return uncompressedSize + 5 * (Math.floor(uncompressedSize / 16383) + 1);
}
function setUint8(view, offset, value) {
view.setUint8(offset, value);
}
function setUint16(view, offset, value) {
view.setUint16(offset, value, true);
}
function setUint322(view, offset, value) {
view.setUint32(offset, value, true);
}
function setBigUint64(view, offset, value) {
view.setBigUint64(offset, value, true);
}
function arraySet(array, typedArray, offset) {
array.set(typedArray, offset);
}
function getDataView2(array) {
return new DataView(array.buffer);
}
function getLength(...arrayLikes) {
let result = 0;
arrayLikes.forEach((arrayLike) => arrayLike && (result += arrayLike.length));
return result;
}
function getHeaderArrayData({
version: version2,
bitFlag,
compressionMethod,
uncompressedSize,
compressedSize,
lastModDate,
rawFilename,
zip64CompressedSize,
zip64UncompressedSize,
extraFieldLength
}) {
const headerArray = new Uint8Array(HEADER_SIZE2 - 4);
const headerView = getDataView2(headerArray);
setUint16(headerView, 0, version2);
setUint16(headerView, 2, bitFlag);
setUint16(headerView, 4, compressionMethod);
const dateArray = new Uint32Array(1);
const dateView = getDataView2(dateArray);
setUint16(dateView, 0, (lastModDate.getHours() << 6 | lastModDate.getMinutes()) << 5 | lastModDate.getSeconds() / 2);
setUint16(dateView, 2, (lastModDate.getFullYear() - 1980 << 4 | lastModDate.getMonth() + 1) << 5 | lastModDate.getDate());
const rawLastModDate = dateArray[0];
setUint322(headerView, 6, rawLastModDate);
if (zip64CompressedSize || compressedSize !== UNDEFINED_VALUE) {
setUint322(headerView, HEADER_OFFSET_COMPRESSED_SIZE, zip64CompressedSize ? MAX_32_BITS : compressedSize);
}
if (zip64UncompressedSize || uncompressedSize !== UNDEFINED_VALUE) {
setUint322(headerView, HEADER_OFFSET_UNCOMPRESSED_SIZE, zip64UncompressedSize ? MAX_32_BITS : uncompressedSize);
}
setUint16(headerView, 22, getLength(rawFilename));
setUint16(headerView, 24, extraFieldLength);
return {
headerArray,
headerView,
rawLastModDate
};
}
function getBitFlag(level, useUnicodeFileNames, dataDescriptor, encrypted, compressionMethod) {
let bitFlag = 0;
if (useUnicodeFileNames) {
bitFlag = bitFlag | BITFLAG_LANG_ENCODING_FLAG;
}
if (dataDescriptor) {
bitFlag = bitFlag | BITFLAG_DATA_DESCRIPTOR;
}
if (compressionMethod == COMPRESSION_METHOD_DEFLATE || compressionMethod == COMPRESSION_METHOD_DEFLATE_64) {
if (level >= 0 && level <= 3) {
bitFlag = bitFlag | BITFLAG_LEVEL_SUPER_FAST_MASK;
}
if (level > 3 && level <= 5) {
bitFlag = bitFlag | BITFLAG_LEVEL_FAST_MASK;
}
if (level == 9) {
bitFlag = bitFlag | BITFLAG_LEVEL_MAX_MASK;
}
}
if (encrypted) {
bitFlag = bitFlag | BITFLAG_ENCRYPTED;
}
return bitFlag;
}
// node_modules/@zip.js/zip.js/lib/zip-no-worker.js
configure({ Deflate: ZipDeflate, Inflate: ZipInflate });
// packages/engine/Source/DataSources/getElement.js
var import_InlineWorkers991 = __toESM(require_InlineWorkers(), 1);
function getElement(element) {
if (typeof element === "string") {
const foundElement = document.getElementById(element);
if (foundElement === null) {
throw new DeveloperError_default(
`Element with id "${element}" does not exist in the document.`
);
}
element = foundElement;
}
return element;
}
var getElement_default = getElement;
// packages/engine/Source/DataSources/KmlLookAt.js
var import_InlineWorkers992 = __toESM(require_InlineWorkers(), 1);
function KmlLookAt(position, headingPitchRange) {
this.position = position;
this.headingPitchRange = headingPitchRange;
}
var KmlLookAt_default = KmlLookAt;
// packages/engine/Source/DataSources/KmlTour.js
var import_InlineWorkers993 = __toESM(require_InlineWorkers(), 1);
function KmlTour(name, id) {
this.id = id;
this.name = name;
this.playlistIndex = 0;
this.playlist = [];
this.tourStart = new Event_default();
this.tourEnd = new Event_default();
this.entryStart = new Event_default();
this.entryEnd = new Event_default();
this._activeEntries = [];
}
KmlTour.prototype.addPlaylistEntry = function(entry) {
this.playlist.push(entry);
};
KmlTour.prototype.play = function(widget, cameraOptions) {
this.tourStart.raiseEvent();
const tour = this;
playEntry.call(this, widget, cameraOptions, function(terminated) {
tour.playlistIndex = 0;
if (!terminated) {
cancelAllEntries(tour._activeEntries);
}
tour.tourEnd.raiseEvent(terminated);
});
};
KmlTour.prototype.stop = function() {
cancelAllEntries(this._activeEntries);
};
function cancelAllEntries(activeEntries) {
for (let entry = activeEntries.pop(); entry !== void 0; entry = activeEntries.pop()) {
entry.stop();
}
}
function playEntry(widget, cameraOptions, allDone) {
const entry = this.playlist[this.playlistIndex];
if (entry) {
const _playNext = playNext.bind(this, widget, cameraOptions, allDone);
this._activeEntries.push(entry);
this.entryStart.raiseEvent(entry);
if (entry.blocking) {
entry.play(_playNext, widget.scene.camera, cameraOptions);
} else {
const tour = this;
entry.play(function() {
tour.entryEnd.raiseEvent(entry);
const indx = tour._activeEntries.indexOf(entry);
if (indx >= 0) {
tour._activeEntries.splice(indx, 1);
}
});
_playNext(widget, cameraOptions, allDone);
}
} else if (defined_default(allDone)) {
allDone(false);
}
}
function playNext(widget, cameraOptions, allDone, terminated) {
const entry = this.playlist[this.playlistIndex];
this.entryEnd.raiseEvent(entry, terminated);
if (terminated) {
allDone(terminated);
} else {
const indx = this._activeEntries.indexOf(entry);
if (indx >= 0) {
this._activeEntries.splice(indx, 1);
}
this.playlistIndex++;
playEntry.call(this, widget, cameraOptions, allDone);
}
}
var KmlTour_default = KmlTour;
// packages/engine/Source/DataSources/KmlTourFlyTo.js
var import_InlineWorkers996 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/EasingFunction.js
var import_InlineWorkers995 = __toESM(require_InlineWorkers(), 1);
// node_modules/@tweenjs/tween.js/dist/tween.esm.js
var import_InlineWorkers994 = __toESM(require_InlineWorkers(), 1);
var Easing = Object.freeze({
Linear: Object.freeze({
None: function(amount) {
return amount;
},
In: function(amount) {
return amount;
},
Out: function(amount) {
return amount;
},
InOut: function(amount) {
return amount;
}
}),
Quadratic: Object.freeze({
In: function(amount) {
return amount * amount;
},
Out: function(amount) {
return amount * (2 - amount);
},
InOut: function(amount) {
if ((amount *= 2) < 1) {
return 0.5 * amount * amount;
}
return -0.5 * (--amount * (amount - 2) - 1);
}
}),
Cubic: Object.freeze({
In: function(amount) {
return amount * amount * amount;
},
Out: function(amount) {
return --amount * amount * amount + 1;
},
InOut: function(amount) {
if ((amount *= 2) < 1) {
return 0.5 * amount * amount * amount;
}
return 0.5 * ((amount -= 2) * amount * amount + 2);
}
}),
Quartic: Object.freeze({
In: function(amount) {
return amount * amount * amount * amount;
},
Out: function(amount) {
return 1 - --amount * amount * amount * amount;
},
InOut: function(amount) {
if ((amount *= 2) < 1) {
return 0.5 * amount * amount * amount * amount;
}
return -0.5 * ((amount -= 2) * amount * amount * amount - 2);
}
}),
Quintic: Object.freeze({
In: function(amount) {
return amount * amount * amount * amount * amount;
},
Out: function(amount) {
return --amount * amount * amount * amount * amount + 1;
},
InOut: function(amount) {
if ((amount *= 2) < 1) {
return 0.5 * amount * amount * amount * amount * amount;
}
return 0.5 * ((amount -= 2) * amount * amount * amount * amount + 2);
}
}),
Sinusoidal: Object.freeze({
In: function(amount) {
return 1 - Math.sin((1 - amount) * Math.PI / 2);
},
Out: function(amount) {
return Math.sin(amount * Math.PI / 2);
},
InOut: function(amount) {
return 0.5 * (1 - Math.sin(Math.PI * (0.5 - amount)));
}
}),
Exponential: Object.freeze({
In: function(amount) {
return amount === 0 ? 0 : Math.pow(1024, amount - 1);
},
Out: function(amount) {
return amount === 1 ? 1 : 1 - Math.pow(2, -10 * amount);
},
InOut: function(amount) {
if (amount === 0) {
return 0;
}
if (amount === 1) {
return 1;
}
if ((amount *= 2) < 1) {
return 0.5 * Math.pow(1024, amount - 1);
}
return 0.5 * (-Math.pow(2, -10 * (amount - 1)) + 2);
}
}),
Circular: Object.freeze({
In: function(amount) {
return 1 - Math.sqrt(1 - amount * amount);
},
Out: function(amount) {
return Math.sqrt(1 - --amount * amount);
},
InOut: function(amount) {
if ((amount *= 2) < 1) {
return -0.5 * (Math.sqrt(1 - amount * amount) - 1);
}
return 0.5 * (Math.sqrt(1 - (amount -= 2) * amount) + 1);
}
}),
Elastic: Object.freeze({
In: function(amount) {
if (amount === 0) {
return 0;
}
if (amount === 1) {
return 1;
}
return -Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI);
},
Out: function(amount) {
if (amount === 0) {
return 0;
}
if (amount === 1) {
return 1;
}
return Math.pow(2, -10 * amount) * Math.sin((amount - 0.1) * 5 * Math.PI) + 1;
},
InOut: function(amount) {
if (amount === 0) {
return 0;
}
if (amount === 1) {
return 1;
}
amount *= 2;
if (amount < 1) {
return -0.5 * Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI);
}
return 0.5 * Math.pow(2, -10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI) + 1;
}
}),
Back: Object.freeze({
In: function(amount) {
var s = 1.70158;
return amount === 1 ? 1 : amount * amount * ((s + 1) * amount - s);
},
Out: function(amount) {
var s = 1.70158;
return amount === 0 ? 0 : --amount * amount * ((s + 1) * amount + s) + 1;
},
InOut: function(amount) {
var s = 1.70158 * 1.525;
if ((amount *= 2) < 1) {
return 0.5 * (amount * amount * ((s + 1) * amount - s));
}
return 0.5 * ((amount -= 2) * amount * ((s + 1) * amount + s) + 2);
}
}),
Bounce: Object.freeze({
In: function(amount) {
return 1 - Easing.Bounce.Out(1 - amount);
},
Out: function(amount) {
if (amount < 1 / 2.75) {
return 7.5625 * amount * amount;
} else if (amount < 2 / 2.75) {
return 7.5625 * (amount -= 1.5 / 2.75) * amount + 0.75;
} else if (amount < 2.5 / 2.75) {
return 7.5625 * (amount -= 2.25 / 2.75) * amount + 0.9375;
} else {
return 7.5625 * (amount -= 2.625 / 2.75) * amount + 0.984375;
}
},
InOut: function(amount) {
if (amount < 0.5) {
return Easing.Bounce.In(amount * 2) * 0.5;
}
return Easing.Bounce.Out(amount * 2 - 1) * 0.5 + 0.5;
}
}),
generatePow: function(power) {
if (power === void 0) {
power = 4;
}
power = power < Number.EPSILON ? Number.EPSILON : power;
power = power > 1e4 ? 1e4 : power;
return {
In: function(amount) {
return Math.pow(amount, power);
},
Out: function(amount) {
return 1 - Math.pow(1 - amount, power);
},
InOut: function(amount) {
if (amount < 0.5) {
return Math.pow(amount * 2, power) / 2;
}
return (1 - Math.pow(2 - amount * 2, power)) / 2 + 0.5;
}
};
}
});
var now = function() {
return performance.now();
};
var Group = (
/** @class */
(function() {
function Group2() {
var tweens = [];
for (var _i = 0; _i < arguments.length; _i++) {
tweens[_i] = arguments[_i];
}
this._tweens = {};
this._tweensAddedDuringUpdate = {};
this.add.apply(this, tweens);
}
Group2.prototype.getAll = function() {
var _this = this;
return Object.keys(this._tweens).map(function(tweenId) {
return _this._tweens[tweenId];
});
};
Group2.prototype.removeAll = function() {
this._tweens = {};
};
Group2.prototype.add = function() {
var _a;
var tweens = [];
for (var _i = 0; _i < arguments.length; _i++) {
tweens[_i] = arguments[_i];
}
for (var _b = 0, tweens_1 = tweens; _b < tweens_1.length; _b++) {
var tween = tweens_1[_b];
(_a = tween._group) === null || _a === void 0 ? void 0 : _a.remove(tween);
tween._group = this;
this._tweens[tween.getId()] = tween;
this._tweensAddedDuringUpdate[tween.getId()] = tween;
}
};
Group2.prototype.remove = function() {
var tweens = [];
for (var _i = 0; _i < arguments.length; _i++) {
tweens[_i] = arguments[_i];
}
for (var _a = 0, tweens_2 = tweens; _a < tweens_2.length; _a++) {
var tween = tweens_2[_a];
tween._group = void 0;
delete this._tweens[tween.getId()];
delete this._tweensAddedDuringUpdate[tween.getId()];
}
};
Group2.prototype.allStopped = function() {
return this.getAll().every(function(tween) {
return !tween.isPlaying();
});
};
Group2.prototype.update = function(time, preserve) {
if (time === void 0) {
time = now();
}
if (preserve === void 0) {
preserve = true;
}
var tweenIds = Object.keys(this._tweens);
if (tweenIds.length === 0)
return;
while (tweenIds.length > 0) {
this._tweensAddedDuringUpdate = {};
for (var i = 0; i < tweenIds.length; i++) {
var tween = this._tweens[tweenIds[i]];
var autoStart = !preserve;
if (tween && tween.update(time, autoStart) === false && !preserve)
this.remove(tween);
}
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
}
};
return Group2;
})()
);
var Interpolation = {
Linear: function(v3, k) {
var m = v3.length - 1;
var f = m * k;
var i = Math.floor(f);
var fn = Interpolation.Utils.Linear;
if (k < 0) {
return fn(v3[0], v3[1], f);
}
if (k > 1) {
return fn(v3[m], v3[m - 1], m - f);
}
return fn(v3[i], v3[i + 1 > m ? m : i + 1], f - i);
},
Bezier: function(v3, k) {
var b = 0;
var n = v3.length - 1;
var pw = Math.pow;
var bn = Interpolation.Utils.Bernstein;
for (var i = 0; i <= n; i++) {
b += pw(1 - k, n - i) * pw(k, i) * v3[i] * bn(n, i);
}
return b;
},
CatmullRom: function(v3, k) {
var m = v3.length - 1;
var f = m * k;
var i = Math.floor(f);
var fn = Interpolation.Utils.CatmullRom;
if (v3[0] === v3[m]) {
if (k < 0) {
i = Math.floor(f = m * (1 + k));
}
return fn(v3[(i - 1 + m) % m], v3[i], v3[(i + 1) % m], v3[(i + 2) % m], f - i);
} else {
if (k < 0) {
return v3[0] - (fn(v3[0], v3[0], v3[1], v3[1], -f) - v3[0]);
}
if (k > 1) {
return v3[m] - (fn(v3[m], v3[m], v3[m - 1], v3[m - 1], f - m) - v3[m]);
}
return fn(v3[i ? i - 1 : 0], v3[i], v3[m < i + 1 ? m : i + 1], v3[m < i + 2 ? m : i + 2], f - i);
}
},
Utils: {
Linear: function(p0, p1, t) {
return (p1 - p0) * t + p0;
},
Bernstein: function(n, i) {
var fc = Interpolation.Utils.Factorial;
return fc(n) / fc(i) / fc(n - i);
},
Factorial: /* @__PURE__ */ (function() {
var a3 = [1];
return function(n) {
var s = 1;
if (a3[n]) {
return a3[n];
}
for (var i = n; i > 1; i--) {
s *= i;
}
a3[n] = s;
return s;
};
})(),
CatmullRom: function(p0, p1, p2, p3, t) {
var v02 = (p2 - p0) * 0.5;
var v12 = (p3 - p1) * 0.5;
var t2 = t * t;
var t3 = t * t2;
return (2 * p1 - 2 * p2 + v02 + v12) * t3 + (-3 * p1 + 3 * p2 - 2 * v02 - v12) * t2 + v02 * t + p1;
}
}
};
var Sequence = (
/** @class */
(function() {
function Sequence2() {
}
Sequence2.nextId = function() {
return Sequence2._nextId++;
};
Sequence2._nextId = 0;
return Sequence2;
})()
);
var mainGroup = new Group();
var Tween = (
/** @class */
(function() {
function Tween3(object2, group) {
this._isPaused = false;
this._pauseStart = 0;
this._valuesStart = {};
this._valuesEnd = {};
this._valuesStartRepeat = {};
this._duration = 1e3;
this._isDynamic = false;
this._initialRepeat = 0;
this._repeat = 0;
this._yoyo = false;
this._isPlaying = false;
this._reversed = false;
this._delayTime = 0;
this._startTime = 0;
this._easingFunction = Easing.Linear.None;
this._interpolationFunction = Interpolation.Linear;
this._chainedTweens = [];
this._onStartCallbackFired = false;
this._onEveryStartCallbackFired = false;
this._id = Sequence.nextId();
this._isChainStopped = false;
this._propertiesAreSetUp = false;
this._goToEnd = false;
this._object = object2;
if (typeof group === "object") {
this._group = group;
group.add(this);
} else if (group === true) {
this._group = mainGroup;
mainGroup.add(this);
}
}
Tween3.prototype.getId = function() {
return this._id;
};
Tween3.prototype.isPlaying = function() {
return this._isPlaying;
};
Tween3.prototype.isPaused = function() {
return this._isPaused;
};
Tween3.prototype.getDuration = function() {
return this._duration;
};
Tween3.prototype.to = function(target, duration) {
if (duration === void 0) {
duration = 1e3;
}
if (this._isPlaying)
throw new Error("Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.");
this._valuesEnd = target;
this._propertiesAreSetUp = false;
this._duration = duration < 0 ? 0 : duration;
return this;
};
Tween3.prototype.duration = function(duration) {
if (duration === void 0) {
duration = 1e3;
}
this._duration = duration < 0 ? 0 : duration;
return this;
};
Tween3.prototype.dynamic = function(dynamic) {
if (dynamic === void 0) {
dynamic = false;
}
this._isDynamic = dynamic;
return this;
};
Tween3.prototype.start = function(time, overrideStartingValues) {
if (time === void 0) {
time = now();
}
if (overrideStartingValues === void 0) {
overrideStartingValues = false;
}
if (this._isPlaying) {
return this;
}
this._repeat = this._initialRepeat;
if (this._reversed) {
this._reversed = false;
for (var property in this._valuesStartRepeat) {
this._swapEndStartRepeatValues(property);
this._valuesStart[property] = this._valuesStartRepeat[property];
}
}
this._isPlaying = true;
this._isPaused = false;
this._onStartCallbackFired = false;
this._onEveryStartCallbackFired = false;
this._isChainStopped = false;
this._startTime = time;
this._startTime += this._delayTime;
if (!this._propertiesAreSetUp || overrideStartingValues) {
this._propertiesAreSetUp = true;
if (!this._isDynamic) {
var tmp2 = {};
for (var prop in this._valuesEnd)
tmp2[prop] = this._valuesEnd[prop];
this._valuesEnd = tmp2;
}
this._setupProperties(this._object, this._valuesStart, this._valuesEnd, this._valuesStartRepeat, overrideStartingValues);
}
return this;
};
Tween3.prototype.startFromCurrentValues = function(time) {
return this.start(time, true);
};
Tween3.prototype._setupProperties = function(_object, _valuesStart, _valuesEnd, _valuesStartRepeat, overrideStartingValues) {
for (var property in _valuesEnd) {
var startValue = _object[property];
var startValueIsArray = Array.isArray(startValue);
var propType = startValueIsArray ? "array" : typeof startValue;
var isInterpolationList = !startValueIsArray && Array.isArray(_valuesEnd[property]);
if (propType === "undefined" || propType === "function") {
continue;
}
if (isInterpolationList) {
var endValues = _valuesEnd[property];
if (endValues.length === 0) {
continue;
}
var temp = [startValue];
for (var i = 0, l = endValues.length; i < l; i += 1) {
var value = this._handleRelativeValue(startValue, endValues[i]);
if (isNaN(value)) {
isInterpolationList = false;
console.warn("Found invalid interpolation list. Skipping.");
break;
}
temp.push(value);
}
if (isInterpolationList) {
_valuesEnd[property] = temp;
}
}
if ((propType === "object" || startValueIsArray) && startValue && !isInterpolationList) {
_valuesStart[property] = startValueIsArray ? [] : {};
var nestedObject = startValue;
for (var prop in nestedObject) {
_valuesStart[property][prop] = nestedObject[prop];
}
_valuesStartRepeat[property] = startValueIsArray ? [] : {};
var endValues = _valuesEnd[property];
if (!this._isDynamic) {
var tmp2 = {};
for (var prop in endValues)
tmp2[prop] = endValues[prop];
_valuesEnd[property] = endValues = tmp2;
}
this._setupProperties(nestedObject, _valuesStart[property], endValues, _valuesStartRepeat[property], overrideStartingValues);
} else {
if (typeof _valuesStart[property] === "undefined" || overrideStartingValues) {
_valuesStart[property] = startValue;
}
if (!startValueIsArray) {
_valuesStart[property] *= 1;
}
if (isInterpolationList) {
_valuesStartRepeat[property] = _valuesEnd[property].slice().reverse();
} else {
_valuesStartRepeat[property] = _valuesStart[property] || 0;
}
}
}
};
Tween3.prototype.stop = function() {
if (!this._isChainStopped) {
this._isChainStopped = true;
this.stopChainedTweens();
}
if (!this._isPlaying) {
return this;
}
this._isPlaying = false;
this._isPaused = false;
if (this._onStopCallback) {
this._onStopCallback(this._object);
}
return this;
};
Tween3.prototype.end = function() {
this._goToEnd = true;
this.update(this._startTime + this._duration);
return this;
};
Tween3.prototype.pause = function(time) {
if (time === void 0) {
time = now();
}
if (this._isPaused || !this._isPlaying) {
return this;
}
this._isPaused = true;
this._pauseStart = time;
return this;
};
Tween3.prototype.resume = function(time) {
if (time === void 0) {
time = now();
}
if (!this._isPaused || !this._isPlaying) {
return this;
}
this._isPaused = false;
this._startTime += time - this._pauseStart;
this._pauseStart = 0;
return this;
};
Tween3.prototype.stopChainedTweens = function() {
for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
this._chainedTweens[i].stop();
}
return this;
};
Tween3.prototype.group = function(group) {
if (!group) {
console.warn("tween.group() without args has been removed, use group.add(tween) instead.");
return this;
}
group.add(this);
return this;
};
Tween3.prototype.remove = function() {
var _a;
(_a = this._group) === null || _a === void 0 ? void 0 : _a.remove(this);
return this;
};
Tween3.prototype.delay = function(amount) {
if (amount === void 0) {
amount = 0;
}
this._delayTime = amount;
return this;
};
Tween3.prototype.repeat = function(times) {
if (times === void 0) {
times = 0;
}
this._initialRepeat = times;
this._repeat = times;
return this;
};
Tween3.prototype.repeatDelay = function(amount) {
this._repeatDelayTime = amount;
return this;
};
Tween3.prototype.yoyo = function(yoyo) {
if (yoyo === void 0) {
yoyo = false;
}
this._yoyo = yoyo;
return this;
};
Tween3.prototype.easing = function(easingFunction) {
if (easingFunction === void 0) {
easingFunction = Easing.Linear.None;
}
this._easingFunction = easingFunction;
return this;
};
Tween3.prototype.interpolation = function(interpolationFunction) {
if (interpolationFunction === void 0) {
interpolationFunction = Interpolation.Linear;
}
this._interpolationFunction = interpolationFunction;
return this;
};
Tween3.prototype.chain = function() {
var tweens = [];
for (var _i = 0; _i < arguments.length; _i++) {
tweens[_i] = arguments[_i];
}
this._chainedTweens = tweens;
return this;
};
Tween3.prototype.onStart = function(callback) {
this._onStartCallback = callback;
return this;
};
Tween3.prototype.onEveryStart = function(callback) {
this._onEveryStartCallback = callback;
return this;
};
Tween3.prototype.onUpdate = function(callback) {
this._onUpdateCallback = callback;
return this;
};
Tween3.prototype.onRepeat = function(callback) {
this._onRepeatCallback = callback;
return this;
};
Tween3.prototype.onComplete = function(callback) {
this._onCompleteCallback = callback;
return this;
};
Tween3.prototype.onStop = function(callback) {
this._onStopCallback = callback;
return this;
};
Tween3.prototype.update = function(time, autoStart) {
var _this = this;
var _a;
if (time === void 0) {
time = now();
}
if (autoStart === void 0) {
autoStart = Tween3.autoStartOnUpdate;
}
if (this._isPaused)
return true;
var property;
if (!this._goToEnd && !this._isPlaying) {
if (autoStart)
this.start(time, true);
else
return false;
}
this._goToEnd = false;
if (time < this._startTime) {
return true;
}
if (this._onStartCallbackFired === false) {
if (this._onStartCallback) {
this._onStartCallback(this._object);
}
this._onStartCallbackFired = true;
}
if (this._onEveryStartCallbackFired === false) {
if (this._onEveryStartCallback) {
this._onEveryStartCallback(this._object);
}
this._onEveryStartCallbackFired = true;
}
var elapsedTime = time - this._startTime;
var durationAndDelay = this._duration + ((_a = this._repeatDelayTime) !== null && _a !== void 0 ? _a : this._delayTime);
var totalTime = this._duration + this._repeat * durationAndDelay;
var calculateElapsedPortion = function() {
if (_this._duration === 0)
return 1;
if (elapsedTime > totalTime) {
return 1;
}
var timesRepeated = Math.trunc(elapsedTime / durationAndDelay);
var timeIntoCurrentRepeat = elapsedTime - timesRepeated * durationAndDelay;
var portion = Math.min(timeIntoCurrentRepeat / _this._duration, 1);
if (portion === 0 && elapsedTime === _this._duration) {
return 1;
}
return portion;
};
var elapsed = calculateElapsedPortion();
var value = this._easingFunction(elapsed);
this._updateProperties(this._object, this._valuesStart, this._valuesEnd, value);
if (this._onUpdateCallback) {
this._onUpdateCallback(this._object, elapsed);
}
if (this._duration === 0 || elapsedTime >= this._duration) {
if (this._repeat > 0) {
var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);
if (isFinite(this._repeat)) {
this._repeat -= completeCount;
}
for (property in this._valuesStartRepeat) {
if (!this._yoyo && typeof this._valuesEnd[property] === "string") {
this._valuesStartRepeat[property] = // eslint-disable-next-line
// @ts-ignore FIXME?
this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]);
}
if (this._yoyo) {
this._swapEndStartRepeatValues(property);
}
this._valuesStart[property] = this._valuesStartRepeat[property];
}
if (this._yoyo) {
this._reversed = !this._reversed;
}
this._startTime += durationAndDelay * completeCount;
if (this._onRepeatCallback) {
this._onRepeatCallback(this._object);
}
this._onEveryStartCallbackFired = false;
return true;
} else {
if (this._onCompleteCallback) {
this._onCompleteCallback(this._object);
}
for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
this._chainedTweens[i].start(this._startTime + this._duration, false);
}
this._isPlaying = false;
return false;
}
}
return true;
};
Tween3.prototype._updateProperties = function(_object, _valuesStart, _valuesEnd, value) {
for (var property in _valuesEnd) {
if (_valuesStart[property] === void 0) {
continue;
}
var start = _valuesStart[property] || 0;
var end = _valuesEnd[property];
var startIsArray = Array.isArray(_object[property]);
var endIsArray = Array.isArray(end);
var isInterpolationList = !startIsArray && endIsArray;
if (isInterpolationList) {
_object[property] = this._interpolationFunction(end, value);
} else if (typeof end === "object" && end) {
this._updateProperties(_object[property], start, end, value);
} else {
end = this._handleRelativeValue(start, end);
if (typeof end === "number") {
_object[property] = start + (end - start) * value;
}
}
}
};
Tween3.prototype._handleRelativeValue = function(start, end) {
if (typeof end !== "string") {
return end;
}
if (end.charAt(0) === "+" || end.charAt(0) === "-") {
return start + parseFloat(end);
}
return parseFloat(end);
};
Tween3.prototype._swapEndStartRepeatValues = function(property) {
var tmp2 = this._valuesStartRepeat[property];
var endValue = this._valuesEnd[property];
if (typeof endValue === "string") {
this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(endValue);
} else {
this._valuesStartRepeat[property] = this._valuesEnd[property];
}
this._valuesEnd[property] = tmp2;
};
Tween3.autoStartOnUpdate = false;
return Tween3;
})()
);
var nextId = Sequence.nextId;
var TWEEN = mainGroup;
var getAll = TWEEN.getAll.bind(TWEEN);
var removeAll = TWEEN.removeAll.bind(TWEEN);
var add = TWEEN.add.bind(TWEEN);
var remove2 = TWEEN.remove.bind(TWEEN);
var update4 = TWEEN.update.bind(TWEEN);
// packages/engine/Source/Core/EasingFunction.js
var EasingFunction = {
/**
* Linear easing.
*
* @type {EasingFunction.Callback}
* @constant
*/
LINEAR_NONE: Easing.Linear.None,
/**
* Quadratic in.
*
* @type {EasingFunction.Callback}
* @constant
*/
QUADRATIC_IN: Easing.Quadratic.In,
/**
* Quadratic out.
*
* @type {EasingFunction.Callback}
* @constant
*/
QUADRATIC_OUT: Easing.Quadratic.Out,
/**
* Quadratic in then out.
*
* @type {EasingFunction.Callback}
* @constant
*/
QUADRATIC_IN_OUT: Easing.Quadratic.InOut,
/**
* Cubic in.
*
* @type {EasingFunction.Callback}
* @constant
*/
CUBIC_IN: Easing.Cubic.In,
/**
* Cubic out.
*
* @type {EasingFunction.Callback}
* @constant
*/
CUBIC_OUT: Easing.Cubic.Out,
/**
* Cubic in then out.
*
* @type {EasingFunction.Callback}
* @constant
*/
CUBIC_IN_OUT: Easing.Cubic.InOut,
/**
* Quartic in.
*
* @type {EasingFunction.Callback}
* @constant
*/
QUARTIC_IN: Easing.Quartic.In,
/**
* Quartic out.
*
* @type {EasingFunction.Callback}
* @constant
*/
QUARTIC_OUT: Easing.Quartic.Out,
/**
* Quartic in then out.
*
* @type {EasingFunction.Callback}
* @constant
*/
QUARTIC_IN_OUT: Easing.Quartic.InOut,
/**
* Quintic in.
*
* @type {EasingFunction.Callback}
* @constant
*/
QUINTIC_IN: Easing.Quintic.In,
/**
* Quintic out.
*
* @type {EasingFunction.Callback}
* @constant
*/
QUINTIC_OUT: Easing.Quintic.Out,
/**
* Quintic in then out.
*
* @type {EasingFunction.Callback}
* @constant
*/
QUINTIC_IN_OUT: Easing.Quintic.InOut,
/**
* Sinusoidal in.
*
* @type {EasingFunction.Callback}
* @constant
*/
SINUSOIDAL_IN: Easing.Sinusoidal.In,
/**
* Sinusoidal out.
*
* @type {EasingFunction.Callback}
* @constant
*/
SINUSOIDAL_OUT: Easing.Sinusoidal.Out,
/**
* Sinusoidal in then out.
*
* @type {EasingFunction.Callback}
* @constant
*/
SINUSOIDAL_IN_OUT: Easing.Sinusoidal.InOut,
/**
* Exponential in.
*
* @type {EasingFunction.Callback}
* @constant
*/
EXPONENTIAL_IN: Easing.Exponential.In,
/**
* Exponential out.
*
* @type {EasingFunction.Callback}
* @constant
*/
EXPONENTIAL_OUT: Easing.Exponential.Out,
/**
* Exponential in then out.
*
* @type {EasingFunction.Callback}
* @constant
*/
EXPONENTIAL_IN_OUT: Easing.Exponential.InOut,
/**
* Circular in.
*
* @type {EasingFunction.Callback}
* @constant
*/
CIRCULAR_IN: Easing.Circular.In,
/**
* Circular out.
*
* @type {EasingFunction.Callback}
* @constant
*/
CIRCULAR_OUT: Easing.Circular.Out,
/**
* Circular in then out.
*
* @type {EasingFunction.Callback}
* @constant
*/
CIRCULAR_IN_OUT: Easing.Circular.InOut,
/**
* Elastic in.
*
* @type {EasingFunction.Callback}
* @constant
*/
ELASTIC_IN: Easing.Elastic.In,
/**
* Elastic out.
*
* @type {EasingFunction.Callback}
* @constant
*/
ELASTIC_OUT: Easing.Elastic.Out,
/**
* Elastic in then out.
*
* @type {EasingFunction.Callback}
* @constant
*/
ELASTIC_IN_OUT: Easing.Elastic.InOut,
/**
* Back in.
*
* @type {EasingFunction.Callback}
* @constant
*/
BACK_IN: Easing.Back.In,
/**
* Back out.
*
* @type {EasingFunction.Callback}
* @constant
*/
BACK_OUT: Easing.Back.Out,
/**
* Back in then out.
*
* @type {EasingFunction.Callback}
* @constant
*/
BACK_IN_OUT: Easing.Back.InOut,
/**
* Bounce in.
*
* @type {EasingFunction.Callback}
* @constant
*/
BOUNCE_IN: Easing.Bounce.In,
/**
* Bounce out.
*
* @type {EasingFunction.Callback}
* @constant
*/
BOUNCE_OUT: Easing.Bounce.Out,
/**
* Bounce in then out.
*
* @type {EasingFunction.Callback}
* @constant
*/
BOUNCE_IN_OUT: Easing.Bounce.InOut
};
var EasingFunction_default = Object.freeze(EasingFunction);
// packages/engine/Source/DataSources/KmlTourFlyTo.js
function KmlTourFlyTo(duration, flyToMode, view) {
this.type = "KmlTourFlyTo";
this.blocking = true;
this.activeCamera = null;
this.activeCallback = null;
this.duration = duration;
this.view = view;
this.flyToMode = flyToMode;
}
KmlTourFlyTo.prototype.play = function(done, camera, cameraOptions) {
this.activeCamera = camera;
if (defined_default(done) && done !== null) {
const self2 = this;
this.activeCallback = function(terminated) {
delete self2.activeCallback;
delete self2.activeCamera;
done(defined_default(terminated) ? false : terminated);
};
}
const options = this.getCameraOptions(cameraOptions);
if (this.view.headingPitchRoll) {
camera.flyTo(options);
} else if (this.view.headingPitchRange) {
const target = new BoundingSphere_default(this.view.position);
camera.flyToBoundingSphere(target, options);
}
};
KmlTourFlyTo.prototype.stop = function() {
if (defined_default(this.activeCamera)) {
this.activeCamera.cancelFlight();
}
if (defined_default(this.activeCallback)) {
this.activeCallback(true);
}
};
KmlTourFlyTo.prototype.getCameraOptions = function(cameraOptions) {
let options = {
duration: this.duration
};
if (defined_default(this.activeCallback)) {
options.complete = this.activeCallback;
}
if (this.flyToMode === "smooth") {
options.easingFunction = EasingFunction_default.LINEAR_NONE;
}
if (this.view.headingPitchRoll) {
options.destination = this.view.position;
options.orientation = this.view.headingPitchRoll;
} else if (this.view.headingPitchRange) {
options.offset = this.view.headingPitchRange;
}
if (defined_default(cameraOptions)) {
options = combine_default(options, cameraOptions);
}
return options;
};
var KmlTourFlyTo_default = KmlTourFlyTo;
// packages/engine/Source/DataSources/KmlTourWait.js
var import_InlineWorkers997 = __toESM(require_InlineWorkers(), 1);
function KmlTourWait(duration) {
this.type = "KmlTourWait";
this.blocking = true;
this.duration = duration;
this.timeout = null;
}
KmlTourWait.prototype.play = function(done) {
const self2 = this;
this.activeCallback = done;
this.timeout = setTimeout(function() {
delete self2.activeCallback;
done(false);
}, this.duration * 1e3);
};
KmlTourWait.prototype.stop = function() {
clearTimeout(this.timeout);
if (defined_default(this.activeCallback)) {
this.activeCallback(true);
}
};
var KmlTourWait_default = KmlTourWait;
// packages/engine/Source/DataSources/KmlDataSource.js
var MimeTypes = {
avi: "video/x-msvideo",
bmp: "image/bmp",
bz2: "application/x-bzip2",
chm: "application/vnd.ms-htmlhelp",
css: "text/css",
csv: "text/csv",
doc: "application/msword",
dvi: "application/x-dvi",
eps: "application/postscript",
flv: "video/x-flv",
gif: "image/gif",
gz: "application/x-gzip",
htm: "text/html",
html: "text/html",
ico: "image/vnd.microsoft.icon",
jnlp: "application/x-java-jnlp-file",
jpeg: "image/jpeg",
jpg: "image/jpeg",
m3u: "audio/x-mpegurl",
m4v: "video/mp4",
mathml: "application/mathml+xml",
mid: "audio/midi",
midi: "audio/midi",
mov: "video/quicktime",
mp3: "audio/mpeg",
mp4: "video/mp4",
mp4v: "video/mp4",
mpeg: "video/mpeg",
mpg: "video/mpeg",
odp: "application/vnd.oasis.opendocument.presentation",
ods: "application/vnd.oasis.opendocument.spreadsheet",
odt: "application/vnd.oasis.opendocument.text",
ogg: "application/ogg",
pdf: "application/pdf",
png: "image/png",
pps: "application/vnd.ms-powerpoint",
ppt: "application/vnd.ms-powerpoint",
ps: "application/postscript",
qt: "video/quicktime",
rdf: "application/rdf+xml",
rss: "application/rss+xml",
rtf: "application/rtf",
svg: "image/svg+xml",
swf: "application/x-shockwave-flash",
text: "text/plain",
tif: "image/tiff",
tiff: "image/tiff",
txt: "text/plain",
wav: "audio/x-wav",
wma: "audio/x-ms-wma",
wmv: "video/x-ms-wmv",
xml: "application/xml",
zip: "application/zip",
detectFromFilename: function(filename) {
let ext = filename.toLowerCase();
ext = getExtensionFromUri_default(ext);
return MimeTypes[ext];
}
};
var parser2;
if (typeof DOMParser !== "undefined") {
parser2 = new DOMParser();
}
var autolinker2 = new es2015_default({
stripPrefix: false,
email: false,
replaceFn: function(match) {
return match.urlMatchType === "scheme" || match.urlMatchType === "www";
}
});
var BILLBOARD_SIZE2 = 32;
var BILLBOARD_NEAR_DISTANCE2 = 2414016;
var BILLBOARD_NEAR_RATIO2 = 1;
var BILLBOARD_FAR_DISTANCE2 = 16093e3;
var BILLBOARD_FAR_RATIO2 = 0.1;
var kmlNamespaces = [
null,
void 0,
"http://www.opengis.net/kml/2.2",
"http://earth.google.com/kml/2.2",
"http://earth.google.com/kml/2.1",
"http://earth.google.com/kml/2.0"
];
var gxNamespaces = ["http://www.google.com/kml/ext/2.2"];
var atomNamespaces = ["http://www.w3.org/2005/Atom"];
var namespaces2 = {
kml: kmlNamespaces,
gx: gxNamespaces,
atom: atomNamespaces,
kmlgx: kmlNamespaces.concat(gxNamespaces)
};
var featureTypes = {
Document: processDocument2,
Folder: processFolder,
Placemark: processPlacemark,
NetworkLink: processNetworkLink,
GroundOverlay: processGroundOverlay,
PhotoOverlay: processUnsupportedFeature,
ScreenOverlay: processScreenOverlay,
Tour: processTour
};
function DeferredLoading(dataSource) {
this._dataSource = dataSource;
this._deferred = defer_default();
this._stack = [];
this._promises = [];
this._timeoutSet = false;
this._used = false;
this._started = 0;
this._timeThreshold = 1e3;
}
Object.defineProperties(DeferredLoading.prototype, {
dataSource: {
get: function() {
return this._dataSource;
}
}
});
DeferredLoading.prototype.addNodes = function(nodes, processingData) {
this._stack.push({
nodes,
index: 0,
processingData
});
this._used = true;
};
DeferredLoading.prototype.addPromise = function(promise) {
this._promises.push(promise);
};
DeferredLoading.prototype.wait = function() {
const deferred = this._deferred;
if (!this._used) {
deferred.resolve();
}
return Promise.all([deferred.promise, Promise.all(this._promises)]);
};
DeferredLoading.prototype.process = function() {
const isFirstCall = this._stack.length === 1;
if (isFirstCall) {
this._started = KmlDataSource._getTimestamp();
}
return this._process(isFirstCall);
};
DeferredLoading.prototype._giveUpTime = function() {
if (this._timeoutSet) {
return;
}
this._timeoutSet = true;
this._timeThreshold = 50;
const that = this;
setTimeout(function() {
that._timeoutSet = false;
that._started = KmlDataSource._getTimestamp();
that._process(true);
}, 0);
};
DeferredLoading.prototype._nextNode = function() {
const stack = this._stack;
const top = stack[stack.length - 1];
const index = top.index;
const nodes = top.nodes;
if (index === nodes.length) {
return;
}
++top.index;
return nodes[index];
};
DeferredLoading.prototype._pop = function() {
const stack = this._stack;
stack.pop();
if (stack.length === 0) {
this._deferred.resolve();
return false;
}
return true;
};
DeferredLoading.prototype._process = function(isFirstCall) {
const dataSource = this.dataSource;
const processingData = this._stack[this._stack.length - 1].processingData;
let child = this._nextNode();
while (defined_default(child)) {
const featureProcessor = featureTypes[child.localName];
if (defined_default(featureProcessor) && (namespaces2.kml.indexOf(child.namespaceURI) !== -1 || namespaces2.gx.indexOf(child.namespaceURI) !== -1)) {
featureProcessor(dataSource, child, processingData, this);
if (this._timeoutSet || KmlDataSource._getTimestamp() > this._started + this._timeThreshold) {
this._giveUpTime();
return;
}
}
child = this._nextNode();
}
if (this._pop() && isFirstCall) {
this._process(true);
}
};
function isZipFile(blob) {
const magicBlob = blob.slice(0, Math.min(4, blob.size));
const deferred = defer_default();
const reader = new FileReader();
reader.addEventListener("load", function() {
deferred.resolve(
new DataView(reader.result).getUint32(0, false) === 1347093252
);
});
reader.addEventListener("error", function() {
deferred.reject(reader.error);
});
reader.readAsArrayBuffer(magicBlob);
return deferred.promise;
}
function readBlobAsText2(blob) {
const deferred = defer_default();
const reader = new FileReader();
reader.addEventListener("load", function() {
deferred.resolve(reader.result);
});
reader.addEventListener("error", function() {
deferred.reject(reader.error);
});
reader.readAsText(blob);
return deferred.promise;
}
function insertNamespaces(text2) {
const namespaceMap = {
xsi: "http://www.w3.org/2001/XMLSchema-instance"
};
let firstPart, lastPart, reg, declaration;
for (const key in namespaceMap) {
if (namespaceMap.hasOwnProperty(key)) {
reg = RegExp(`[< ]${key}:`);
declaration = `xmlns:${key}=`;
if (reg.test(text2) && text2.indexOf(declaration) === -1) {
if (!defined_default(firstPart)) {
firstPart = text2.substr(0, text2.indexOf("", index);
let namespace, startIndex, endIndex;
while (index !== -1 && index < endDeclaration) {
namespace = text2.slice(index, text2.indexOf('"', index));
startIndex = index;
index = text2.indexOf(namespace, index + 1);
if (index !== -1) {
endIndex = text2.indexOf('"', text2.indexOf('"', index) + 1);
text2 = text2.slice(0, index - 1) + text2.slice(endIndex + 1, text2.length);
index = text2.indexOf("xmlns:", startIndex - 1);
} else {
index = text2.indexOf("xmlns:", startIndex + 1);
}
}
return text2;
}
function loadXmlFromZip(entry, uriResolver) {
return Promise.resolve(entry.getData(new TextWriter())).then(
function(text2) {
text2 = insertNamespaces(text2);
text2 = removeDuplicateNamespaces(text2);
uriResolver.kml = parser2.parseFromString(text2, "application/xml");
}
);
}
function loadDataUriFromZip(entry, uriResolver) {
const mimeType = MimeTypes.detectFromFilename(entry.filename) ?? "application/octet-stream";
return Promise.resolve(entry.getData(new Data64URIWriter(mimeType))).then(
function(dataUri) {
uriResolver[entry.filename] = dataUri;
}
);
}
function embedDataUris(div, elementType, attributeName, uriResolver) {
const keys = uriResolver.keys;
const baseUri = new import_urijs11.default(".");
const elements = div.querySelectorAll(elementType);
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const value = element.getAttribute(attributeName);
if (defined_default(value)) {
const relativeUri = new import_urijs11.default(value);
const uri = relativeUri.absoluteTo(baseUri).toString();
const index = keys.indexOf(uri);
if (index !== -1) {
const key = keys[index];
element.setAttribute(attributeName, uriResolver[key]);
if (elementType === "a" && element.getAttribute("download") === null) {
element.setAttribute("download", key);
}
}
}
}
}
function applyBasePath(div, elementType, attributeName, sourceResource) {
const elements = div.querySelectorAll(elementType);
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const value = element.getAttribute(attributeName);
const resource = resolveHref(value, sourceResource);
if (defined_default(resource)) {
element.setAttribute(attributeName, resource.url);
}
}
}
function createEntity(node, entityCollection, context) {
let id = queryStringAttribute2(node, "id");
id = defined_default(id) && id.length !== 0 ? id : createGuid_default();
if (defined_default(context)) {
id = context + id;
}
let entity = entityCollection.getById(id);
if (defined_default(entity)) {
id = createGuid_default();
if (defined_default(context)) {
id = context + id;
}
}
entity = entityCollection.add(new Entity_default({ id }));
if (!defined_default(entity.kml)) {
entity.addProperty("kml");
entity.kml = new KmlFeatureData();
}
return entity;
}
function isExtrudable(altitudeMode, gxAltitudeMode) {
return altitudeMode === "absolute" || altitudeMode === "relativeToGround" || gxAltitudeMode === "relativeToSeaFloor";
}
function readCoordinate(value, ellipsoid) {
if (!defined_default(value)) {
return Cartesian3_default.fromDegrees(0, 0, 0, ellipsoid);
}
const digits = value.match(/[^\s,\n]+/g);
if (!defined_default(digits)) {
return Cartesian3_default.fromDegrees(0, 0, 0, ellipsoid);
}
let longitude = parseFloat(digits[0]);
let latitude = parseFloat(digits[1]);
let height = parseFloat(digits[2]);
longitude = isNaN(longitude) ? 0 : longitude;
latitude = isNaN(latitude) ? 0 : latitude;
height = isNaN(height) ? 0 : height;
return Cartesian3_default.fromDegrees(longitude, latitude, height, ellipsoid);
}
function readCoordinates(element, ellipsoid) {
if (!defined_default(element)) {
return void 0;
}
const tuples = element.textContent.match(/[^\s\n]+/g);
if (!defined_default(tuples)) {
return void 0;
}
const length2 = tuples.length;
const result = new Array(length2);
let resultIndex = 0;
for (let i = 0; i < length2; i++) {
result[resultIndex++] = readCoordinate(tuples[i], ellipsoid);
}
return result;
}
function queryNumericAttribute2(node, attributeName) {
if (!defined_default(node)) {
return void 0;
}
const value = node.getAttribute(attributeName);
if (value !== null) {
const result = parseFloat(value);
return !isNaN(result) ? result : void 0;
}
return void 0;
}
function queryStringAttribute2(node, attributeName) {
if (!defined_default(node)) {
return void 0;
}
const value = node.getAttribute(attributeName);
return value !== null ? value : void 0;
}
function queryFirstNode2(node, tagName, namespace) {
if (!defined_default(node)) {
return void 0;
}
const childNodes = node.childNodes;
const length2 = childNodes.length;
for (let q = 0; q < length2; q++) {
const child = childNodes[q];
if (child.localName === tagName && namespace.indexOf(child.namespaceURI) !== -1) {
return child;
}
}
return void 0;
}
function queryNodes2(node, tagName, namespace) {
if (!defined_default(node)) {
return void 0;
}
const result = [];
const childNodes = node.getElementsByTagNameNS("*", tagName);
const length2 = childNodes.length;
for (let q = 0; q < length2; q++) {
const child = childNodes[q];
if (child.localName === tagName && namespace.indexOf(child.namespaceURI) !== -1) {
result.push(child);
}
}
return result;
}
function queryChildNodes(node, tagName, namespace) {
if (!defined_default(node)) {
return [];
}
const result = [];
const childNodes = node.childNodes;
const length2 = childNodes.length;
for (let q = 0; q < length2; q++) {
const child = childNodes[q];
if (child.localName === tagName && namespace.indexOf(child.namespaceURI) !== -1) {
result.push(child);
}
}
return result;
}
function queryNumericValue2(node, tagName, namespace) {
const resultNode = queryFirstNode2(node, tagName, namespace);
if (defined_default(resultNode)) {
const result = parseFloat(resultNode.textContent);
return !isNaN(result) ? result : void 0;
}
return void 0;
}
function queryStringValue2(node, tagName, namespace) {
const result = queryFirstNode2(node, tagName, namespace);
if (defined_default(result)) {
return result.textContent.trim();
}
return void 0;
}
function queryBooleanValue(node, tagName, namespace) {
const result = queryFirstNode2(node, tagName, namespace);
if (defined_default(result)) {
const value = result.textContent.trim();
return value === "1" || /^true$/i.test(value);
}
return void 0;
}
function resolveHref(href, sourceResource, uriResolver) {
if (!defined_default(href)) {
return void 0;
}
let resource;
if (defined_default(uriResolver)) {
href = href.replace(/\\/g, "/");
let blob = uriResolver[href];
if (defined_default(blob)) {
resource = new Resource_default({
url: blob
});
} else {
const baseUri = new import_urijs11.default(sourceResource.getUrlComponent());
const uri = new import_urijs11.default(href);
blob = uriResolver[uri.absoluteTo(baseUri)];
if (defined_default(blob)) {
resource = new Resource_default({
url: blob
});
}
}
}
if (!defined_default(resource)) {
resource = sourceResource.getDerivedResource({
url: href
});
}
return resource;
}
var colorOptions = {
maximumRed: void 0,
red: void 0,
maximumGreen: void 0,
green: void 0,
maximumBlue: void 0,
blue: void 0
};
function parseColorString(value, isRandom) {
if (!defined_default(value) || /^\s*$/gm.test(value)) {
return void 0;
}
if (value[0] === "#") {
value = value.substring(1);
}
const alpha = parseInt(value.substring(0, 2), 16) / 255;
const blue = parseInt(value.substring(2, 4), 16) / 255;
const green = parseInt(value.substring(4, 6), 16) / 255;
const red = parseInt(value.substring(6, 8), 16) / 255;
if (!isRandom) {
return new Color_default(red, green, blue, alpha);
}
if (red > 0) {
colorOptions.maximumRed = red;
colorOptions.red = void 0;
} else {
colorOptions.maximumRed = void 0;
colorOptions.red = 0;
}
if (green > 0) {
colorOptions.maximumGreen = green;
colorOptions.green = void 0;
} else {
colorOptions.maximumGreen = void 0;
colorOptions.green = 0;
}
if (blue > 0) {
colorOptions.maximumBlue = blue;
colorOptions.blue = void 0;
} else {
colorOptions.maximumBlue = void 0;
colorOptions.blue = 0;
}
colorOptions.alpha = alpha;
return Color_default.fromRandom(colorOptions);
}
function queryColorValue(node, tagName, namespace) {
const value = queryStringValue2(node, tagName, namespace);
if (!defined_default(value)) {
return void 0;
}
return parseColorString(
value,
queryStringValue2(node, "colorMode", namespace) === "random"
);
}
function processTimeStamp(featureNode) {
const node = queryFirstNode2(featureNode, "TimeStamp", namespaces2.kmlgx);
const whenString = queryStringValue2(node, "when", namespaces2.kmlgx);
if (!defined_default(node) || !defined_default(whenString) || whenString.length === 0) {
return void 0;
}
const when = JulianDate_default.fromIso8601(whenString);
const result = new TimeIntervalCollection_default();
result.addInterval(
new TimeInterval_default({
start: when,
stop: Iso8601_default.MAXIMUM_VALUE
})
);
return result;
}
function processTimeSpan(featureNode) {
const node = queryFirstNode2(featureNode, "TimeSpan", namespaces2.kmlgx);
if (!defined_default(node)) {
return void 0;
}
let result;
const beginNode = queryFirstNode2(node, "begin", namespaces2.kmlgx);
let beginDate = defined_default(beginNode) ? JulianDate_default.fromIso8601(beginNode.textContent) : void 0;
const endNode = queryFirstNode2(node, "end", namespaces2.kmlgx);
let endDate = defined_default(endNode) ? JulianDate_default.fromIso8601(endNode.textContent) : void 0;
if (defined_default(beginDate) && defined_default(endDate)) {
if (JulianDate_default.lessThan(endDate, beginDate)) {
const tmp2 = beginDate;
beginDate = endDate;
endDate = tmp2;
}
result = new TimeIntervalCollection_default();
result.addInterval(
new TimeInterval_default({
start: beginDate,
stop: endDate
})
);
} else if (defined_default(beginDate)) {
result = new TimeIntervalCollection_default();
result.addInterval(
new TimeInterval_default({
start: beginDate,
stop: Iso8601_default.MAXIMUM_VALUE
})
);
} else if (defined_default(endDate)) {
result = new TimeIntervalCollection_default();
result.addInterval(
new TimeInterval_default({
start: Iso8601_default.MINIMUM_VALUE,
stop: endDate
})
);
}
return result;
}
function createDefaultBillboard2() {
const billboard = new BillboardGraphics_default();
billboard.width = BILLBOARD_SIZE2;
billboard.height = BILLBOARD_SIZE2;
billboard.scaleByDistance = new NearFarScalar_default(
BILLBOARD_NEAR_DISTANCE2,
BILLBOARD_NEAR_RATIO2,
BILLBOARD_FAR_DISTANCE2,
BILLBOARD_FAR_RATIO2
);
billboard.pixelOffsetScaleByDistance = new NearFarScalar_default(
BILLBOARD_NEAR_DISTANCE2,
BILLBOARD_NEAR_RATIO2,
BILLBOARD_FAR_DISTANCE2,
BILLBOARD_FAR_RATIO2
);
return billboard;
}
function createDefaultPolygon() {
const polygon2 = new PolygonGraphics_default();
polygon2.outline = true;
polygon2.outlineColor = Color_default.WHITE;
return polygon2;
}
function createDefaultLabel2() {
const label = new LabelGraphics_default();
label.translucencyByDistance = new NearFarScalar_default(3e6, 1, 5e6, 0);
label.pixelOffset = new Cartesian2_default(17, 0);
label.horizontalOrigin = HorizontalOrigin_default.LEFT;
label.font = "16px sans-serif";
label.style = LabelStyle_default.FILL_AND_OUTLINE;
return label;
}
function getIconHref(iconNode, dataSource, sourceResource, uriResolver, canRefresh) {
let href = queryStringValue2(iconNode, "href", namespaces2.kml);
if (!defined_default(href) || href.length === 0) {
return void 0;
}
if (href.indexOf("root://icons/palette-") === 0) {
const palette = href.charAt(21);
let x = queryNumericValue2(iconNode, "x", namespaces2.gx) ?? 0;
let y = queryNumericValue2(iconNode, "y", namespaces2.gx) ?? 0;
x = Math.min(x / 32, 7);
y = 7 - Math.min(y / 32, 7);
const iconNum = 8 * y + x;
href = `https://maps.google.com/mapfiles/kml/pal${palette}/icon${iconNum}.png`;
}
const hrefResource = resolveHref(href, sourceResource, uriResolver);
if (canRefresh) {
const refreshMode = queryStringValue2(
iconNode,
"refreshMode",
namespaces2.kml
);
const viewRefreshMode = queryStringValue2(
iconNode,
"viewRefreshMode",
namespaces2.kml
);
if (refreshMode === "onInterval" || refreshMode === "onExpire") {
oneTimeWarning_default(
`kml-refreshMode-${refreshMode}`,
`KML - Unsupported Icon refreshMode: ${refreshMode}`
);
} else if (viewRefreshMode === "onStop" || viewRefreshMode === "onRegion") {
oneTimeWarning_default(
`kml-refreshMode-${viewRefreshMode}`,
`KML - Unsupported Icon viewRefreshMode: ${viewRefreshMode}`
);
}
const viewBoundScale = queryStringValue2(iconNode, "viewBoundScale", namespaces2.kml) ?? 1;
const defaultViewFormat = viewRefreshMode === "onStop" ? "BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth]" : "";
const viewFormat = queryStringValue2(iconNode, "viewFormat", namespaces2.kml) ?? defaultViewFormat;
const httpQuery = queryStringValue2(iconNode, "httpQuery", namespaces2.kml);
if (defined_default(viewFormat)) {
hrefResource.setQueryParameters(queryToObject_default(cleanupString(viewFormat)));
}
if (defined_default(httpQuery)) {
hrefResource.setQueryParameters(queryToObject_default(cleanupString(httpQuery)));
}
const ellipsoid = dataSource._ellipsoid;
processNetworkLinkQueryString(
hrefResource,
dataSource.camera,
dataSource.canvas,
viewBoundScale,
dataSource._lastCameraView.bbox,
ellipsoid
);
return hrefResource;
}
return hrefResource;
}
function processBillboardIcon(dataSource, node, targetEntity, sourceResource, uriResolver) {
let scale = queryNumericValue2(node, "scale", namespaces2.kml);
const heading = queryNumericValue2(node, "heading", namespaces2.kml);
const color = queryColorValue(node, "color", namespaces2.kml);
const iconNode = queryFirstNode2(node, "Icon", namespaces2.kml);
let icon = getIconHref(
iconNode,
dataSource,
sourceResource,
uriResolver,
false
);
if (defined_default(iconNode) && !defined_default(icon)) {
icon = false;
}
const x = queryNumericValue2(iconNode, "x", namespaces2.gx);
const y = queryNumericValue2(iconNode, "y", namespaces2.gx);
const w = queryNumericValue2(iconNode, "w", namespaces2.gx);
const h = queryNumericValue2(iconNode, "h", namespaces2.gx);
const hotSpotNode = queryFirstNode2(node, "hotSpot", namespaces2.kml);
const hotSpotX = queryNumericAttribute2(hotSpotNode, "x");
const hotSpotY = queryNumericAttribute2(hotSpotNode, "y");
const hotSpotXUnit = queryStringAttribute2(hotSpotNode, "xunits");
const hotSpotYUnit = queryStringAttribute2(hotSpotNode, "yunits");
let billboard = targetEntity.billboard;
if (!defined_default(billboard)) {
billboard = createDefaultBillboard2();
targetEntity.billboard = billboard;
}
billboard.image = icon;
billboard.scale = scale;
billboard.color = color;
if (defined_default(x) || defined_default(y) || defined_default(w) || defined_default(h)) {
billboard.imageSubRegion = new BoundingRectangle_default(x, y, w, h);
}
if (defined_default(heading) && heading !== 0) {
billboard.rotation = Math_default.toRadians(-heading);
billboard.alignedAxis = Cartesian3_default.UNIT_Z;
}
scale = scale ?? 1;
let xOffset;
let yOffset;
if (defined_default(hotSpotX)) {
if (hotSpotXUnit === "pixels") {
xOffset = -hotSpotX * scale;
} else if (hotSpotXUnit === "insetPixels") {
xOffset = (hotSpotX - BILLBOARD_SIZE2) * scale;
} else if (hotSpotXUnit === "fraction") {
xOffset = -hotSpotX * BILLBOARD_SIZE2 * scale;
}
xOffset += BILLBOARD_SIZE2 * 0.5 * scale;
}
if (defined_default(hotSpotY)) {
if (hotSpotYUnit === "pixels") {
yOffset = hotSpotY * scale;
} else if (hotSpotYUnit === "insetPixels") {
yOffset = (-hotSpotY + BILLBOARD_SIZE2) * scale;
} else if (hotSpotYUnit === "fraction") {
yOffset = hotSpotY * BILLBOARD_SIZE2 * scale;
}
yOffset -= BILLBOARD_SIZE2 * 0.5 * scale;
}
if (defined_default(xOffset) || defined_default(yOffset)) {
billboard.pixelOffset = new Cartesian2_default(xOffset, yOffset);
}
}
function applyStyle(dataSource, styleNode, targetEntity, sourceResource, uriResolver) {
for (let i = 0, len = styleNode.childNodes.length; i < len; i++) {
const node = styleNode.childNodes.item(i);
if (node.localName === "IconStyle") {
processBillboardIcon(
dataSource,
node,
targetEntity,
sourceResource,
uriResolver
);
} else if (node.localName === "LabelStyle") {
let label = targetEntity.label;
if (!defined_default(label)) {
label = createDefaultLabel2();
targetEntity.label = label;
}
label.scale = queryNumericValue2(node, "scale", namespaces2.kml) ?? label.scale;
label.fillColor = queryColorValue(node, "color", namespaces2.kml) ?? label.fillColor;
label.text = targetEntity.name;
} else if (node.localName === "LineStyle") {
let polyline = targetEntity.polyline;
if (!defined_default(polyline)) {
polyline = new PolylineGraphics_default();
targetEntity.polyline = polyline;
}
polyline.width = queryNumericValue2(node, "width", namespaces2.kml);
polyline.material = queryColorValue(node, "color", namespaces2.kml);
if (defined_default(queryColorValue(node, "outerColor", namespaces2.gx))) {
oneTimeWarning_default(
"kml-gx:outerColor",
"KML - gx:outerColor is not supported in a LineStyle"
);
}
if (defined_default(queryNumericValue2(node, "outerWidth", namespaces2.gx))) {
oneTimeWarning_default(
"kml-gx:outerWidth",
"KML - gx:outerWidth is not supported in a LineStyle"
);
}
if (defined_default(queryNumericValue2(node, "physicalWidth", namespaces2.gx))) {
oneTimeWarning_default(
"kml-gx:physicalWidth",
"KML - gx:physicalWidth is not supported in a LineStyle"
);
}
if (defined_default(queryBooleanValue(node, "labelVisibility", namespaces2.gx))) {
oneTimeWarning_default(
"kml-gx:labelVisibility",
"KML - gx:labelVisibility is not supported in a LineStyle"
);
}
} else if (node.localName === "PolyStyle") {
let polygon2 = targetEntity.polygon;
if (!defined_default(polygon2)) {
polygon2 = createDefaultPolygon();
targetEntity.polygon = polygon2;
}
polygon2.material = queryColorValue(node, "color", namespaces2.kml) ?? polygon2.material;
polygon2.fill = queryBooleanValue(node, "fill", namespaces2.kml) ?? polygon2.fill;
polygon2.outline = queryBooleanValue(node, "outline", namespaces2.kml) ?? polygon2.outline;
} else if (node.localName === "BalloonStyle") {
const bgColor = parseColorString(queryStringValue2(node, "bgColor", namespaces2.kml)) ?? Color_default.WHITE;
const textColor2 = parseColorString(queryStringValue2(node, "textColor", namespaces2.kml)) ?? Color_default.BLACK;
const text2 = queryStringValue2(node, "text", namespaces2.kml);
targetEntity.addProperty("balloonStyle");
targetEntity.balloonStyle = {
bgColor,
textColor: textColor2,
text: text2
};
} else if (node.localName === "ListStyle") {
const listItemType = queryStringValue2(
node,
"listItemType",
namespaces2.kml
);
if (listItemType === "radioFolder" || listItemType === "checkOffOnly") {
oneTimeWarning_default(
`kml-listStyle-${listItemType}`,
`KML - Unsupported ListStyle with listItemType: ${listItemType}`
);
}
}
}
}
function computeFinalStyle(dataSource, placeMark, styleCollection, sourceResource, uriResolver) {
const result = new Entity_default();
let styleEntity;
let styleIndex = -1;
const childNodes = placeMark.childNodes;
const length2 = childNodes.length;
for (let q = 0; q < length2; q++) {
const child = childNodes[q];
if (child.localName === "Style" || child.localName === "StyleMap") {
styleIndex = q;
}
}
if (styleIndex !== -1) {
const inlineStyleNode = childNodes[styleIndex];
if (inlineStyleNode.localName === "Style") {
applyStyle(
dataSource,
inlineStyleNode,
result,
sourceResource,
uriResolver
);
} else {
const pairs = queryChildNodes(inlineStyleNode, "Pair", namespaces2.kml);
for (let p = 0; p < pairs.length; p++) {
const pair = pairs[p];
const key = queryStringValue2(pair, "key", namespaces2.kml);
if (key === "normal") {
const styleUrl = queryStringValue2(pair, "styleUrl", namespaces2.kml);
if (defined_default(styleUrl)) {
styleEntity = styleCollection.getById(styleUrl);
if (!defined_default(styleEntity)) {
styleEntity = styleCollection.getById(`#${styleUrl}`);
}
if (defined_default(styleEntity)) {
result.merge(styleEntity);
}
} else {
const node = queryFirstNode2(pair, "Style", namespaces2.kml);
applyStyle(dataSource, node, result, sourceResource, uriResolver);
}
} else {
oneTimeWarning_default(
`kml-styleMap-${key}`,
`KML - Unsupported StyleMap key: ${key}`
);
}
}
}
}
const externalStyle = queryStringValue2(placeMark, "styleUrl", namespaces2.kml);
if (defined_default(externalStyle)) {
let id = externalStyle;
if (externalStyle[0] !== "#" && externalStyle.indexOf("#") !== -1) {
const tokens = externalStyle.split("#");
const uri = tokens[0];
const resource = sourceResource.getDerivedResource({
url: uri
});
id = `${resource.getUrlComponent()}#${tokens[1]}`;
}
styleEntity = styleCollection.getById(id);
if (!defined_default(styleEntity)) {
styleEntity = styleCollection.getById(`#${id}`);
}
if (defined_default(styleEntity)) {
result.merge(styleEntity);
}
}
return result;
}
function processExternalStyles(dataSource, resource, styleCollection) {
return resource.fetchXML().then(function(styleKml) {
return processStyles(dataSource, styleKml, styleCollection, resource, true);
});
}
function processStyles(dataSource, kml, styleCollection, sourceResource, isExternal, uriResolver) {
let i;
let id;
let styleEntity;
let node;
const styleNodes = queryNodes2(kml, "Style", namespaces2.kml);
if (defined_default(styleNodes)) {
const styleNodesLength = styleNodes.length;
for (i = 0; i < styleNodesLength; i++) {
node = styleNodes[i];
id = queryStringAttribute2(node, "id");
if (defined_default(id)) {
id = `#${id}`;
if (isExternal && defined_default(sourceResource)) {
id = sourceResource.getUrlComponent() + id;
}
if (!defined_default(styleCollection.getById(id))) {
styleEntity = new Entity_default({
id
});
styleCollection.add(styleEntity);
applyStyle(
dataSource,
node,
styleEntity,
sourceResource,
uriResolver
);
}
}
}
}
const styleMaps = queryNodes2(kml, "StyleMap", namespaces2.kml);
if (defined_default(styleMaps)) {
const styleMapsLength = styleMaps.length;
for (i = 0; i < styleMapsLength; i++) {
const styleMap = styleMaps[i];
id = queryStringAttribute2(styleMap, "id");
if (defined_default(id)) {
const pairs = queryChildNodes(styleMap, "Pair", namespaces2.kml);
for (let p = 0; p < pairs.length; p++) {
const pair = pairs[p];
const key = queryStringValue2(pair, "key", namespaces2.kml);
if (key === "normal") {
id = `#${id}`;
if (isExternal && defined_default(sourceResource)) {
id = sourceResource.getUrlComponent() + id;
}
if (!defined_default(styleCollection.getById(id))) {
styleEntity = styleCollection.getOrCreateEntity(id);
let styleUrl = queryStringValue2(pair, "styleUrl", namespaces2.kml);
if (defined_default(styleUrl)) {
if (styleUrl[0] !== "#") {
styleUrl = `#${styleUrl}`;
}
if (isExternal && defined_default(sourceResource)) {
styleUrl = sourceResource.getUrlComponent() + styleUrl;
}
const base = styleCollection.getById(styleUrl);
if (defined_default(base)) {
styleEntity.merge(base);
}
} else {
node = queryFirstNode2(pair, "Style", namespaces2.kml);
applyStyle(
dataSource,
node,
styleEntity,
sourceResource,
uriResolver
);
}
}
} else {
oneTimeWarning_default(
`kml-styleMap-${key}`,
`KML - Unsupported StyleMap key: ${key}`
);
}
}
}
}
}
const promises = [];
const styleUrlNodes = kml.getElementsByTagName("styleUrl");
const styleUrlNodesLength = styleUrlNodes.length;
for (i = 0; i < styleUrlNodesLength; i++) {
const styleReference = styleUrlNodes[i].textContent;
if (styleReference[0] !== "#") {
const tokens = styleReference.split("#");
if (tokens.length === 2) {
const uri = tokens[0];
const resource = sourceResource.getDerivedResource({
url: uri
});
promises.push(
processExternalStyles(dataSource, resource, styleCollection)
);
}
}
}
return promises;
}
function createDropLine(entityCollection, entity, styleEntity) {
const entityPosition = new ReferenceProperty_default(entityCollection, entity.id, [
"position"
]);
const surfacePosition = new ScaledPositionProperty_default(entity.position);
entity.polyline = defined_default(styleEntity.polyline) ? styleEntity.polyline.clone() : new PolylineGraphics_default();
entity.polyline.positions = new PositionPropertyArray_default([
entityPosition,
surfacePosition
]);
}
function heightReferenceFromAltitudeMode(altitudeMode, gxAltitudeMode) {
if (!defined_default(altitudeMode) && !defined_default(gxAltitudeMode) || altitudeMode === "clampToGround") {
return HeightReference_default.CLAMP_TO_GROUND;
}
if (altitudeMode === "relativeToGround") {
return HeightReference_default.RELATIVE_TO_GROUND;
}
if (altitudeMode === "absolute") {
return HeightReference_default.NONE;
}
if (gxAltitudeMode === "clampToSeaFloor") {
oneTimeWarning_default(
"kml-gx:altitudeMode-clampToSeaFloor",
"KML - :clampToSeaFloor is currently not supported, using :clampToGround."
);
return HeightReference_default.CLAMP_TO_GROUND;
}
if (gxAltitudeMode === "relativeToSeaFloor") {
oneTimeWarning_default(
"kml-gx:altitudeMode-relativeToSeaFloor",
"KML - :relativeToSeaFloor is currently not supported, using :relativeToGround."
);
return HeightReference_default.RELATIVE_TO_GROUND;
}
if (defined_default(altitudeMode)) {
oneTimeWarning_default(
"kml-altitudeMode-unknown",
`KML - Unknown :${altitudeMode}, using :CLAMP_TO_GROUND.`
);
} else {
oneTimeWarning_default(
"kml-gx:altitudeMode-unknown",
`KML - Unknown :${gxAltitudeMode}, using :CLAMP_TO_GROUND.`
);
}
return HeightReference_default.CLAMP_TO_GROUND;
}
function createPositionPropertyFromAltitudeMode(property, altitudeMode, gxAltitudeMode) {
if (gxAltitudeMode === "relativeToSeaFloor" || altitudeMode === "absolute" || altitudeMode === "relativeToGround") {
return property;
}
if (defined_default(altitudeMode) && altitudeMode !== "clampToGround" || //
defined_default(gxAltitudeMode) && gxAltitudeMode !== "clampToSeaFloor") {
oneTimeWarning_default(
"kml-altitudeMode-unknown",
`KML - Unknown altitudeMode: ${altitudeMode ?? gxAltitudeMode}`
);
}
return new ScaledPositionProperty_default(property);
}
function createPositionPropertyArrayFromAltitudeMode(properties, altitudeMode, gxAltitudeMode, ellipsoid) {
if (!defined_default(properties)) {
return void 0;
}
if (gxAltitudeMode === "relativeToSeaFloor" || altitudeMode === "absolute" || altitudeMode === "relativeToGround") {
return properties;
}
if (defined_default(altitudeMode) && altitudeMode !== "clampToGround" || //
defined_default(gxAltitudeMode) && gxAltitudeMode !== "clampToSeaFloor") {
oneTimeWarning_default(
"kml-altitudeMode-unknown",
`KML - Unknown altitudeMode: ${altitudeMode ?? gxAltitudeMode}`
);
}
const propertiesLength = properties.length;
for (let i = 0; i < propertiesLength; i++) {
const property = properties[i];
ellipsoid.scaleToGeodeticSurface(property, property);
}
return properties;
}
function processPositionGraphics(dataSource, entity, styleEntity, heightReference) {
let label = entity.label;
if (!defined_default(label)) {
label = defined_default(styleEntity.label) ? styleEntity.label.clone() : createDefaultLabel2();
entity.label = label;
}
label.text = entity.name;
let billboard = entity.billboard;
if (!defined_default(billboard)) {
billboard = defined_default(styleEntity.billboard) ? styleEntity.billboard.clone() : createDefaultBillboard2();
entity.billboard = billboard;
}
if (!defined_default(billboard.image)) {
billboard.image = dataSource._pinBuilder.fromColor(Color_default.YELLOW, 64);
} else if (!billboard.image.getValue()) {
billboard.image = void 0;
}
let scale = 1;
if (defined_default(billboard.scale)) {
scale = billboard.scale.getValue();
if (scale !== 0) {
label.pixelOffset = new Cartesian2_default(scale * 16 + 1, 0);
} else {
label.pixelOffset = void 0;
label.horizontalOrigin = void 0;
}
}
if (defined_default(heightReference) && dataSource._clampToGround) {
billboard.heightReference = heightReference;
label.heightReference = heightReference;
}
}
function processPathGraphics(entity, styleEntity) {
let path = entity.path;
if (!defined_default(path)) {
path = new PathGraphics_default();
path.leadTime = 0;
entity.path = path;
}
const polyline = styleEntity.polyline;
if (defined_default(polyline)) {
path.material = polyline.material;
path.width = polyline.width;
}
}
function processPoint3(dataSource, entityCollection, geometryNode, entity, styleEntity) {
const coordinatesString = queryStringValue2(
geometryNode,
"coordinates",
namespaces2.kml
);
const altitudeMode = queryStringValue2(
geometryNode,
"altitudeMode",
namespaces2.kml
);
const gxAltitudeMode = queryStringValue2(
geometryNode,
"altitudeMode",
namespaces2.gx
);
const extrude = queryBooleanValue(geometryNode, "extrude", namespaces2.kml);
const ellipsoid = dataSource._ellipsoid;
const position = readCoordinate(coordinatesString, ellipsoid);
entity.position = position;
processPositionGraphics(
dataSource,
entity,
styleEntity,
heightReferenceFromAltitudeMode(altitudeMode, gxAltitudeMode)
);
if (extrude && isExtrudable(altitudeMode, gxAltitudeMode)) {
createDropLine(entityCollection, entity, styleEntity);
}
return true;
}
function processLineStringOrLinearRing(dataSource, entityCollection, geometryNode, entity, styleEntity) {
const coordinatesNode = queryFirstNode2(
geometryNode,
"coordinates",
namespaces2.kml
);
const altitudeMode = queryStringValue2(
geometryNode,
"altitudeMode",
namespaces2.kml
);
const gxAltitudeMode = queryStringValue2(
geometryNode,
"altitudeMode",
namespaces2.gx
);
const extrude = queryBooleanValue(geometryNode, "extrude", namespaces2.kml);
const tessellate = queryBooleanValue(
geometryNode,
"tessellate",
namespaces2.kml
);
const canExtrude = isExtrudable(altitudeMode, gxAltitudeMode);
const zIndex = queryNumericValue2(geometryNode, "drawOrder", namespaces2.gx);
const ellipsoid = dataSource._ellipsoid;
const coordinates = readCoordinates(coordinatesNode, ellipsoid);
let polyline = styleEntity.polyline;
if (canExtrude && extrude) {
const wall = new WallGraphics_default();
entity.wall = wall;
wall.positions = coordinates;
const polygon2 = styleEntity.polygon;
if (defined_default(polygon2)) {
wall.fill = polygon2.fill;
wall.material = polygon2.material;
}
wall.outline = true;
if (defined_default(polyline)) {
wall.outlineColor = defined_default(polyline.material) ? polyline.material.color : Color_default.WHITE;
wall.outlineWidth = polyline.width;
} else if (defined_default(polygon2)) {
wall.outlineColor = defined_default(polygon2.material) ? polygon2.material.color : Color_default.WHITE;
}
} else if (dataSource._clampToGround && !canExtrude && tessellate) {
const polylineGraphics = new PolylineGraphics_default();
polylineGraphics.clampToGround = true;
entity.polyline = polylineGraphics;
polylineGraphics.positions = coordinates;
if (defined_default(polyline)) {
polylineGraphics.material = defined_default(polyline.material) ? polyline.material.color.getValue(Iso8601_default.MINIMUM_VALUE) : Color_default.WHITE;
polylineGraphics.width = polyline.width ?? 1;
} else {
polylineGraphics.material = Color_default.WHITE;
polylineGraphics.width = 1;
}
polylineGraphics.zIndex = zIndex;
} else {
if (defined_default(zIndex)) {
oneTimeWarning_default(
"kml-gx:drawOrder",
"KML - gx:drawOrder is not supported in LineStrings when clampToGround is false"
);
}
if (dataSource._clampToGround && !tessellate) {
oneTimeWarning_default(
"kml-line-tesselate",
"Ignoring clampToGround for KML lines without the tessellate flag."
);
}
polyline = defined_default(polyline) ? polyline.clone() : new PolylineGraphics_default();
entity.polyline = polyline;
polyline.positions = createPositionPropertyArrayFromAltitudeMode(
coordinates,
altitudeMode,
gxAltitudeMode,
ellipsoid
);
if (!tessellate || canExtrude) {
polyline.arcType = ArcType_default.NONE;
}
}
return true;
}
function processPolygon3(dataSource, entityCollection, geometryNode, entity, styleEntity) {
const outerBoundaryIsNode = queryFirstNode2(
geometryNode,
"outerBoundaryIs",
namespaces2.kml
);
let linearRingNode = queryFirstNode2(
outerBoundaryIsNode,
"LinearRing",
namespaces2.kml
);
let coordinatesNode = queryFirstNode2(
linearRingNode,
"coordinates",
namespaces2.kml
);
const ellipsoid = dataSource._ellipsoid;
let coordinates = readCoordinates(coordinatesNode, ellipsoid);
const extrude = queryBooleanValue(geometryNode, "extrude", namespaces2.kml);
const altitudeMode = queryStringValue2(
geometryNode,
"altitudeMode",
namespaces2.kml
);
const gxAltitudeMode = queryStringValue2(
geometryNode,
"altitudeMode",
namespaces2.gx
);
const canExtrude = isExtrudable(altitudeMode, gxAltitudeMode);
const polygon2 = defined_default(styleEntity.polygon) ? styleEntity.polygon.clone() : createDefaultPolygon();
const polyline = styleEntity.polyline;
if (defined_default(polyline)) {
polygon2.outlineColor = defined_default(polyline.material) ? polyline.material.color : Color_default.WHITE;
polygon2.outlineWidth = polyline.width;
}
entity.polygon = polygon2;
if (canExtrude) {
polygon2.perPositionHeight = true;
polygon2.extrudedHeight = extrude ? 0 : void 0;
} else if (!dataSource._clampToGround) {
polygon2.height = 0;
}
if (defined_default(coordinates)) {
const hierarchy = new PolygonHierarchy_default(coordinates);
const innerBoundaryIsNodes = queryChildNodes(
geometryNode,
"innerBoundaryIs",
namespaces2.kml
);
for (let j = 0; j < innerBoundaryIsNodes.length; j++) {
linearRingNode = queryChildNodes(
innerBoundaryIsNodes[j],
"LinearRing",
namespaces2.kml
);
for (let k = 0; k < linearRingNode.length; k++) {
coordinatesNode = queryFirstNode2(
linearRingNode[k],
"coordinates",
namespaces2.kml
);
coordinates = readCoordinates(coordinatesNode, ellipsoid);
if (defined_default(coordinates)) {
hierarchy.holes.push(new PolygonHierarchy_default(coordinates));
}
}
}
polygon2.hierarchy = hierarchy;
}
return true;
}
function processTrack(dataSource, entityCollection, geometryNode, entity, styleEntity) {
const altitudeMode = queryStringValue2(
geometryNode,
"altitudeMode",
namespaces2.kml
);
const gxAltitudeMode = queryStringValue2(
geometryNode,
"altitudeMode",
namespaces2.gx
);
const coordNodes = queryChildNodes(geometryNode, "coord", namespaces2.gx);
const angleNodes = queryChildNodes(geometryNode, "angles", namespaces2.gx);
const timeNodes = queryChildNodes(geometryNode, "when", namespaces2.kml);
const extrude = queryBooleanValue(geometryNode, "extrude", namespaces2.kml);
const canExtrude = isExtrudable(altitudeMode, gxAltitudeMode);
const ellipsoid = dataSource._ellipsoid;
if (angleNodes.length > 0) {
oneTimeWarning_default(
"kml-gx:angles",
"KML - gx:angles are not supported in gx:Tracks"
);
}
const length2 = Math.min(coordNodes.length, timeNodes.length);
const coordinates = [];
const times = [];
for (let i = 0; i < length2; i++) {
const position = readCoordinate(coordNodes[i].textContent, ellipsoid);
coordinates.push(position);
times.push(JulianDate_default.fromIso8601(timeNodes[i].textContent));
}
const property = new SampledPositionProperty_default();
property.addSamples(times, coordinates);
entity.position = property;
processPositionGraphics(
dataSource,
entity,
styleEntity,
heightReferenceFromAltitudeMode(altitudeMode, gxAltitudeMode)
);
processPathGraphics(entity, styleEntity);
entity.availability = new TimeIntervalCollection_default();
if (timeNodes.length > 0) {
entity.availability.addInterval(
new TimeInterval_default({
start: times[0],
stop: times[times.length - 1]
})
);
}
if (canExtrude && extrude) {
createDropLine(entityCollection, entity, styleEntity);
}
return true;
}
function addToMultiTrack(times, positions, composite, availability, dropShowProperty, extrude, altitudeMode, gxAltitudeMode, includeEndPoints) {
const start = times[0];
const stop2 = times[times.length - 1];
const data = new SampledPositionProperty_default();
data.addSamples(times, positions);
composite.intervals.addInterval(
new TimeInterval_default({
start,
stop: stop2,
isStartIncluded: includeEndPoints,
isStopIncluded: includeEndPoints,
data: createPositionPropertyFromAltitudeMode(
data,
altitudeMode,
gxAltitudeMode
)
})
);
availability.addInterval(
new TimeInterval_default({
start,
stop: stop2,
isStartIncluded: includeEndPoints,
isStopIncluded: includeEndPoints
})
);
dropShowProperty.intervals.addInterval(
new TimeInterval_default({
start,
stop: stop2,
isStartIncluded: includeEndPoints,
isStopIncluded: includeEndPoints,
data: extrude
})
);
}
function processMultiTrack(dataSource, entityCollection, geometryNode, entity, styleEntity) {
const interpolate2 = queryBooleanValue(
geometryNode,
"interpolate",
namespaces2.gx
);
const trackNodes = queryChildNodes(geometryNode, "Track", namespaces2.gx);
let times;
let lastStop;
let lastStopPosition;
let needDropLine = false;
const dropShowProperty = new TimeIntervalCollectionProperty_default();
const availability = new TimeIntervalCollection_default();
const composite = new CompositePositionProperty_default();
const ellipsoid = dataSource._ellipsoid;
for (let i = 0, len = trackNodes.length; i < len; i++) {
const trackNode = trackNodes[i];
const timeNodes = queryChildNodes(trackNode, "when", namespaces2.kml);
const coordNodes = queryChildNodes(trackNode, "coord", namespaces2.gx);
const altitudeMode = queryStringValue2(
trackNode,
"altitudeMode",
namespaces2.kml
);
const gxAltitudeMode = queryStringValue2(
trackNode,
"altitudeMode",
namespaces2.gx
);
const canExtrude = isExtrudable(altitudeMode, gxAltitudeMode);
const extrude = queryBooleanValue(trackNode, "extrude", namespaces2.kml);
const length2 = Math.min(coordNodes.length, timeNodes.length);
const positions = [];
times = [];
for (let x = 0; x < length2; x++) {
const position = readCoordinate(coordNodes[x].textContent, ellipsoid);
positions.push(position);
times.push(JulianDate_default.fromIso8601(timeNodes[x].textContent));
}
if (interpolate2) {
if (defined_default(lastStop)) {
addToMultiTrack(
[lastStop, times[0]],
[lastStopPosition, positions[0]],
composite,
availability,
dropShowProperty,
false,
"absolute",
void 0,
false
);
}
lastStop = times[length2 - 1];
lastStopPosition = positions[positions.length - 1];
}
addToMultiTrack(
times,
positions,
composite,
availability,
dropShowProperty,
canExtrude && extrude,
altitudeMode,
gxAltitudeMode,
true
);
needDropLine = needDropLine || canExtrude && extrude;
}
entity.availability = availability;
entity.position = composite;
processPositionGraphics(dataSource, entity, styleEntity);
processPathGraphics(entity, styleEntity);
if (needDropLine) {
createDropLine(entityCollection, entity, styleEntity);
entity.polyline.show = dropShowProperty;
}
return true;
}
var geometryTypes3 = {
Point: processPoint3,
LineString: processLineStringOrLinearRing,
LinearRing: processLineStringOrLinearRing,
Polygon: processPolygon3,
Track: processTrack,
MultiTrack: processMultiTrack,
MultiGeometry: processMultiGeometry,
Model: processUnsupportedGeometry
};
function processMultiGeometry(dataSource, entityCollection, geometryNode, entity, styleEntity, context) {
const childNodes = geometryNode.childNodes;
let hasGeometry = false;
for (let i = 0, len = childNodes.length; i < len; i++) {
const childNode = childNodes.item(i);
const geometryProcessor = geometryTypes3[childNode.localName];
if (defined_default(geometryProcessor)) {
const childEntity = createEntity(childNode, entityCollection, context);
childEntity.parent = entity;
childEntity.name = entity.name;
childEntity.availability = entity.availability;
childEntity.description = entity.description;
childEntity.kml = entity.kml;
if (geometryProcessor(
dataSource,
entityCollection,
childNode,
childEntity,
styleEntity
)) {
hasGeometry = true;
}
}
}
return hasGeometry;
}
function processUnsupportedGeometry(dataSource, entityCollection, geometryNode, entity, styleEntity) {
oneTimeWarning_default(
"kml-unsupportedGeometry",
`KML - Unsupported geometry: ${geometryNode.localName}`
);
return false;
}
function processExtendedData(node, entity) {
const extendedDataNode = queryFirstNode2(node, "ExtendedData", namespaces2.kml);
if (!defined_default(extendedDataNode)) {
return void 0;
}
if (defined_default(queryFirstNode2(extendedDataNode, "SchemaData", namespaces2.kml))) {
oneTimeWarning_default("kml-schemaData", "KML - SchemaData is unsupported");
}
if (defined_default(queryStringAttribute2(extendedDataNode, "xmlns:prefix"))) {
oneTimeWarning_default(
"kml-extendedData",
"KML - ExtendedData with xmlns:prefix is unsupported"
);
}
const result = {};
const dataNodes = queryChildNodes(extendedDataNode, "Data", namespaces2.kml);
if (defined_default(dataNodes)) {
const length2 = dataNodes.length;
for (let i = 0; i < length2; i++) {
const dataNode = dataNodes[i];
const name = queryStringAttribute2(dataNode, "name");
if (defined_default(name)) {
result[name] = {
displayName: queryStringValue2(
dataNode,
"displayName",
namespaces2.kml
),
value: queryStringValue2(dataNode, "value", namespaces2.kml)
};
}
}
}
entity.kml.extendedData = result;
}
var scratchDiv2;
if (typeof document !== "undefined") {
scratchDiv2 = document.createElement("div");
}
function processDescription3(node, entity, styleEntity, uriResolver, sourceResource) {
let i;
let key;
let keys;
const kmlData = entity.kml;
const extendedData = kmlData.extendedData;
const description = queryStringValue2(node, "description", namespaces2.kml);
const balloonStyle = entity.balloonStyle ?? styleEntity.balloonStyle;
let background = Color_default.WHITE;
let foreground = Color_default.BLACK;
let text2 = description;
if (defined_default(balloonStyle)) {
background = balloonStyle.bgColor ?? Color_default.WHITE;
foreground = balloonStyle.textColor ?? Color_default.BLACK;
text2 = balloonStyle.text ?? description;
}
let value;
if (defined_default(text2)) {
text2 = text2.replace("$[name]", entity.name ?? "");
text2 = text2.replace("$[description]", description ?? "");
text2 = text2.replace("$[address]", kmlData.address ?? "");
text2 = text2.replace("$[Snippet]", kmlData.snippet ?? "");
text2 = text2.replace("$[id]", entity.id);
text2 = text2.replace("$[geDirections]", "");
if (defined_default(extendedData)) {
const matches = text2.match(/\$\[.+?\]/g);
if (matches !== null) {
for (i = 0; i < matches.length; i++) {
const token = matches[i];
let propertyName = token.substr(2, token.length - 3);
const isDisplayName = /\/displayName$/.test(propertyName);
propertyName = propertyName.replace(/\/displayName$/, "");
value = extendedData[propertyName];
if (defined_default(value)) {
value = isDisplayName ? value.displayName : value.value;
}
if (defined_default(value)) {
text2 = text2.replace(token, value ?? "");
}
}
}
}
} else if (defined_default(extendedData)) {
keys = Object.keys(extendedData);
if (keys.length > 0) {
text2 = '';
for (i = 0; i < keys.length; i++) {
key = keys[i];
value = extendedData[key];
text2 += `${value.displayName ?? key} ${value.value ?? ""} `;
}
text2 += "
";
}
}
if (!defined_default(text2)) {
return;
}
text2 = autolinker2.link(text2);
scratchDiv2.innerHTML = text2;
const links = scratchDiv2.querySelectorAll("a");
for (i = 0; i < links.length; i++) {
links[i].setAttribute("target", "_blank");
}
if (defined_default(uriResolver) && uriResolver.keys.length > 1) {
embedDataUris(scratchDiv2, "a", "href", uriResolver);
embedDataUris(scratchDiv2, "link", "href", uriResolver);
embedDataUris(scratchDiv2, "area", "href", uriResolver);
embedDataUris(scratchDiv2, "img", "src", uriResolver);
embedDataUris(scratchDiv2, "iframe", "src", uriResolver);
embedDataUris(scratchDiv2, "video", "src", uriResolver);
embedDataUris(scratchDiv2, "audio", "src", uriResolver);
embedDataUris(scratchDiv2, "source", "src", uriResolver);
embedDataUris(scratchDiv2, "track", "src", uriResolver);
embedDataUris(scratchDiv2, "input", "src", uriResolver);
embedDataUris(scratchDiv2, "embed", "src", uriResolver);
embedDataUris(scratchDiv2, "script", "src", uriResolver);
embedDataUris(scratchDiv2, "video", "poster", uriResolver);
}
applyBasePath(scratchDiv2, "a", "href", sourceResource);
applyBasePath(scratchDiv2, "link", "href", sourceResource);
applyBasePath(scratchDiv2, "area", "href", sourceResource);
applyBasePath(scratchDiv2, "img", "src", sourceResource);
applyBasePath(scratchDiv2, "iframe", "src", sourceResource);
applyBasePath(scratchDiv2, "video", "src", sourceResource);
applyBasePath(scratchDiv2, "audio", "src", sourceResource);
applyBasePath(scratchDiv2, "source", "src", sourceResource);
applyBasePath(scratchDiv2, "track", "src", sourceResource);
applyBasePath(scratchDiv2, "input", "src", sourceResource);
applyBasePath(scratchDiv2, "embed", "src", sourceResource);
applyBasePath(scratchDiv2, "script", "src", sourceResource);
applyBasePath(scratchDiv2, "video", "poster", sourceResource);
let tmp2 = '';
tmp2 += `${scratchDiv2.innerHTML}`;
scratchDiv2.innerHTML = "";
entity.description = tmp2;
}
function processFeature2(dataSource, featureNode, processingData) {
const entityCollection = processingData.entityCollection;
const parent = processingData.parentEntity;
const sourceResource = processingData.sourceResource;
const uriResolver = processingData.uriResolver;
const entity = createEntity(
featureNode,
entityCollection,
processingData.context
);
const kmlData = entity.kml;
const styleEntity = computeFinalStyle(
dataSource,
featureNode,
processingData.styleCollection,
sourceResource,
uriResolver
);
const name = queryStringValue2(featureNode, "name", namespaces2.kml);
entity.name = name;
entity.parent = parent;
let availability = processTimeSpan(featureNode);
if (!defined_default(availability)) {
availability = processTimeStamp(featureNode);
}
entity.availability = availability;
mergeAvailabilityWithParent(entity);
function ancestryIsVisible(parentEntity) {
if (!parentEntity) {
return true;
}
return parentEntity.show && ancestryIsVisible(parentEntity.parent);
}
const visibility = queryBooleanValue(
featureNode,
"visibility",
namespaces2.kml
);
entity.show = ancestryIsVisible(parent) && (visibility ?? true);
const authorNode = queryFirstNode2(featureNode, "author", namespaces2.atom);
const author = kmlData.author;
author.name = queryStringValue2(authorNode, "name", namespaces2.atom);
author.uri = queryStringValue2(authorNode, "uri", namespaces2.atom);
author.email = queryStringValue2(authorNode, "email", namespaces2.atom);
const linkNode = queryFirstNode2(featureNode, "link", namespaces2.atom);
const link = kmlData.link;
link.href = queryStringAttribute2(linkNode, "href");
link.hreflang = queryStringAttribute2(linkNode, "hreflang");
link.rel = queryStringAttribute2(linkNode, "rel");
link.type = queryStringAttribute2(linkNode, "type");
link.title = queryStringAttribute2(linkNode, "title");
link.length = queryStringAttribute2(linkNode, "length");
kmlData.address = queryStringValue2(featureNode, "address", namespaces2.kml);
kmlData.phoneNumber = queryStringValue2(
featureNode,
"phoneNumber",
namespaces2.kml
);
kmlData.snippet = queryStringValue2(featureNode, "Snippet", namespaces2.kml);
processExtendedData(featureNode, entity);
processDescription3(
featureNode,
entity,
styleEntity,
uriResolver,
sourceResource
);
const ellipsoid = dataSource._ellipsoid;
processLookAt(featureNode, entity, ellipsoid);
processCamera(featureNode, entity, ellipsoid);
if (defined_default(queryFirstNode2(featureNode, "Region", namespaces2.kml))) {
oneTimeWarning_default("kml-region", "KML - Placemark Regions are unsupported");
}
return {
entity,
styleEntity
};
}
function processDocument2(dataSource, node, processingData, deferredLoading) {
deferredLoading.addNodes(node.childNodes, processingData);
deferredLoading.process();
}
function processFolder(dataSource, node, processingData, deferredLoading) {
const r = processFeature2(dataSource, node, processingData);
const newProcessingData = clone_default(processingData);
newProcessingData.parentEntity = r.entity;
processDocument2(dataSource, node, newProcessingData, deferredLoading);
}
function processPlacemark(dataSource, placemark, processingData, deferredLoading) {
const r = processFeature2(dataSource, placemark, processingData);
const entity = r.entity;
const styleEntity = r.styleEntity;
let hasGeometry = false;
const childNodes = placemark.childNodes;
for (let i = 0, len = childNodes.length; i < len && !hasGeometry; i++) {
const childNode = childNodes.item(i);
const geometryProcessor = geometryTypes3[childNode.localName];
if (defined_default(geometryProcessor)) {
geometryProcessor(
dataSource,
processingData.entityCollection,
childNode,
entity,
styleEntity,
entity.id
);
hasGeometry = true;
}
}
if (!hasGeometry) {
entity.merge(styleEntity);
processPositionGraphics(dataSource, entity, styleEntity);
}
}
var playlistNodeProcessors = {
FlyTo: processTourFlyTo,
Wait: processTourWait,
SoundCue: processTourUnsupportedNode,
AnimatedUpdate: processTourUnsupportedNode,
TourControl: processTourUnsupportedNode
};
function processTour(dataSource, node, processingData, deferredLoading) {
const name = queryStringValue2(node, "name", namespaces2.kml);
const id = queryStringAttribute2(node, "id");
const tour = new KmlTour_default(name, id);
const playlistNode = queryFirstNode2(node, "Playlist", namespaces2.gx);
if (playlistNode) {
const ellipsoid = dataSource._ellipsoid;
const childNodes = playlistNode.childNodes;
for (let i = 0; i < childNodes.length; i++) {
const entryNode = childNodes[i];
if (entryNode.localName) {
const playlistNodeProcessor = playlistNodeProcessors[entryNode.localName];
if (playlistNodeProcessor) {
playlistNodeProcessor(tour, entryNode, ellipsoid);
} else {
console.log(
`Unknown KML Tour playlist entry type ${entryNode.localName}`
);
}
}
}
}
dataSource._kmlTours.push(tour);
}
function processTourUnsupportedNode(tour, entryNode) {
oneTimeWarning_default(`KML Tour unsupported node ${entryNode.localName}`);
}
function processTourWait(tour, entryNode) {
const duration = queryNumericValue2(entryNode, "duration", namespaces2.gx);
tour.addPlaylistEntry(new KmlTourWait_default(duration));
}
function processTourFlyTo(tour, entryNode, ellipsoid) {
const duration = queryNumericValue2(entryNode, "duration", namespaces2.gx);
const flyToMode = queryStringValue2(entryNode, "flyToMode", namespaces2.gx);
const t = { kml: {} };
processLookAt(entryNode, t, ellipsoid);
processCamera(entryNode, t, ellipsoid);
const view = t.kml.lookAt || t.kml.camera;
const flyto = new KmlTourFlyTo_default(duration, flyToMode, view);
tour.addPlaylistEntry(flyto);
}
function processCamera(featureNode, entity, ellipsoid) {
const camera = queryFirstNode2(featureNode, "Camera", namespaces2.kml);
if (defined_default(camera)) {
const lon = queryNumericValue2(camera, "longitude", namespaces2.kml) ?? 0;
const lat = queryNumericValue2(camera, "latitude", namespaces2.kml) ?? 0;
const altitude = queryNumericValue2(camera, "altitude", namespaces2.kml) ?? 0;
const heading = queryNumericValue2(camera, "heading", namespaces2.kml) ?? 0;
const tilt = queryNumericValue2(camera, "tilt", namespaces2.kml) ?? 0;
const roll = queryNumericValue2(camera, "roll", namespaces2.kml) ?? 0;
const position = Cartesian3_default.fromDegrees(lon, lat, altitude, ellipsoid);
const hpr = HeadingPitchRoll_default.fromDegrees(heading, tilt - 90, roll);
entity.kml.camera = new KmlCamera_default(position, hpr);
}
}
function processLookAt(featureNode, entity, ellipsoid) {
const lookAt = queryFirstNode2(featureNode, "LookAt", namespaces2.kml);
if (defined_default(lookAt)) {
const lon = queryNumericValue2(lookAt, "longitude", namespaces2.kml) ?? 0;
const lat = queryNumericValue2(lookAt, "latitude", namespaces2.kml) ?? 0;
const altitude = queryNumericValue2(lookAt, "altitude", namespaces2.kml) ?? 0;
let heading = queryNumericValue2(lookAt, "heading", namespaces2.kml);
let tilt = queryNumericValue2(lookAt, "tilt", namespaces2.kml);
const range = queryNumericValue2(lookAt, "range", namespaces2.kml) ?? 0;
tilt = Math_default.toRadians(tilt ?? 0);
heading = Math_default.toRadians(heading ?? 0);
const hpr = new HeadingPitchRange_default(
heading,
tilt - Math_default.PI_OVER_TWO,
range
);
const viewPoint = Cartesian3_default.fromDegrees(lon, lat, altitude, ellipsoid);
entity.kml.lookAt = new KmlLookAt_default(viewPoint, hpr);
}
}
function processScreenOverlay(dataSource, screenOverlayNode, processingData, deferredLoading) {
const screenOverlay = processingData.screenOverlayContainer;
if (!defined_default(screenOverlay)) {
return void 0;
}
const sourceResource = processingData.sourceResource;
const uriResolver = processingData.uriResolver;
const iconNode = queryFirstNode2(screenOverlayNode, "Icon", namespaces2.kml);
const icon = getIconHref(
iconNode,
dataSource,
sourceResource,
uriResolver,
false
);
if (!defined_default(icon)) {
return void 0;
}
const img = document.createElement("img");
dataSource._screenOverlays.push(img);
img.src = icon.url;
img.onload = function() {
const styles = ["position: absolute"];
const screenXY = queryFirstNode2(
screenOverlayNode,
"screenXY",
namespaces2.kml
);
const overlayXY = queryFirstNode2(
screenOverlayNode,
"overlayXY",
namespaces2.kml
);
const size = queryFirstNode2(screenOverlayNode, "size", namespaces2.kml);
let x, y;
let xUnit, yUnit;
let xStyle, yStyle;
if (defined_default(size)) {
x = queryNumericAttribute2(size, "x");
y = queryNumericAttribute2(size, "y");
xUnit = queryStringAttribute2(size, "xunits");
yUnit = queryStringAttribute2(size, "yunits");
if (defined_default(x) && x !== -1 && x !== 0) {
if (xUnit === "fraction") {
xStyle = `width: ${Math.floor(x * 100)}%`;
} else if (xUnit === "pixels") {
xStyle = `width: ${x}px`;
}
styles.push(xStyle);
}
if (defined_default(y) && y !== -1 && y !== 0) {
if (yUnit === "fraction") {
yStyle = `height: ${Math.floor(y * 100)}%`;
} else if (yUnit === "pixels") {
yStyle = `height: ${y}px`;
}
styles.push(yStyle);
}
}
img.style = styles.join(";");
let xOrigin = 0;
let yOrigin = img.height;
if (defined_default(overlayXY)) {
x = queryNumericAttribute2(overlayXY, "x");
y = queryNumericAttribute2(overlayXY, "y");
xUnit = queryStringAttribute2(overlayXY, "xunits");
yUnit = queryStringAttribute2(overlayXY, "yunits");
if (defined_default(x)) {
if (xUnit === "fraction") {
xOrigin = x * img.width;
} else if (xUnit === "pixels") {
xOrigin = x;
} else if (xUnit === "insetPixels") {
xOrigin = x;
}
}
if (defined_default(y)) {
if (yUnit === "fraction") {
yOrigin = y * img.height;
} else if (yUnit === "pixels") {
yOrigin = y;
} else if (yUnit === "insetPixels") {
yOrigin = y;
}
}
}
if (defined_default(screenXY)) {
x = queryNumericAttribute2(screenXY, "x");
y = queryNumericAttribute2(screenXY, "y");
xUnit = queryStringAttribute2(screenXY, "xunits");
yUnit = queryStringAttribute2(screenXY, "yunits");
if (defined_default(x)) {
if (xUnit === "fraction") {
xStyle = `${"left: calc("}${Math.floor(
x * 100
)}% - ${xOrigin}px)`;
} else if (xUnit === "pixels") {
xStyle = `left: ${x - xOrigin}px`;
} else if (xUnit === "insetPixels") {
xStyle = `right: ${x - xOrigin}px`;
}
styles.push(xStyle);
}
if (defined_default(y)) {
if (yUnit === "fraction") {
yStyle = `${"bottom: calc("}${Math.floor(
y * 100
)}% - ${yOrigin}px)`;
} else if (yUnit === "pixels") {
yStyle = `bottom: ${y - yOrigin}px`;
} else if (yUnit === "insetPixels") {
yStyle = `top: ${y - yOrigin}px`;
}
styles.push(yStyle);
}
}
img.style = styles.join(";");
};
screenOverlay.appendChild(img);
}
function processGroundOverlay(dataSource, groundOverlay, processingData, deferredLoading) {
const r = processFeature2(dataSource, groundOverlay, processingData);
const entity = r.entity;
let geometry;
let isLatLonQuad = false;
const ellipsoid = dataSource._ellipsoid;
const positions = readCoordinates(
queryFirstNode2(groundOverlay, "LatLonQuad", namespaces2.gx),
ellipsoid
);
const zIndex = queryNumericValue2(groundOverlay, "drawOrder", namespaces2.kml);
if (defined_default(positions)) {
geometry = createDefaultPolygon();
geometry.hierarchy = new PolygonHierarchy_default(positions);
geometry.zIndex = zIndex;
entity.polygon = geometry;
isLatLonQuad = true;
} else {
geometry = new RectangleGraphics_default();
geometry.zIndex = zIndex;
entity.rectangle = geometry;
const latLonBox = queryFirstNode2(
groundOverlay,
"LatLonBox",
namespaces2.kml
);
if (defined_default(latLonBox)) {
let west = queryNumericValue2(latLonBox, "west", namespaces2.kml);
let south = queryNumericValue2(latLonBox, "south", namespaces2.kml);
let east = queryNumericValue2(latLonBox, "east", namespaces2.kml);
let north = queryNumericValue2(latLonBox, "north", namespaces2.kml);
if (defined_default(west)) {
west = Math_default.negativePiToPi(Math_default.toRadians(west));
}
if (defined_default(south)) {
south = Math_default.clampToLatitudeRange(Math_default.toRadians(south));
}
if (defined_default(east)) {
east = Math_default.negativePiToPi(Math_default.toRadians(east));
}
if (defined_default(north)) {
north = Math_default.clampToLatitudeRange(Math_default.toRadians(north));
}
geometry.coordinates = new Rectangle_default(west, south, east, north);
const rotation = queryNumericValue2(latLonBox, "rotation", namespaces2.kml);
if (defined_default(rotation)) {
const rotationRadians = Math_default.toRadians(rotation);
geometry.rotation = rotationRadians;
geometry.stRotation = rotationRadians;
}
}
}
const iconNode = queryFirstNode2(groundOverlay, "Icon", namespaces2.kml);
const href = getIconHref(
iconNode,
dataSource,
processingData.sourceResource,
processingData.uriResolver,
true
);
if (defined_default(href)) {
if (isLatLonQuad) {
oneTimeWarning_default(
"kml-gx:LatLonQuad",
"KML - gx:LatLonQuad Icon does not support texture projection."
);
}
const x = queryNumericValue2(iconNode, "x", namespaces2.gx);
const y = queryNumericValue2(iconNode, "y", namespaces2.gx);
const w = queryNumericValue2(iconNode, "w", namespaces2.gx);
const h = queryNumericValue2(iconNode, "h", namespaces2.gx);
if (defined_default(x) || defined_default(y) || defined_default(w) || defined_default(h)) {
oneTimeWarning_default(
"kml-groundOverlay-xywh",
"KML - gx:x, gx:y, gx:w, gx:h aren't supported for GroundOverlays"
);
}
geometry.material = href;
geometry.material.color = queryColorValue(
groundOverlay,
"color",
namespaces2.kml
);
geometry.material.transparent = true;
} else {
geometry.material = queryColorValue(groundOverlay, "color", namespaces2.kml);
}
let altitudeMode = queryStringValue2(
groundOverlay,
"altitudeMode",
namespaces2.kml
);
if (defined_default(altitudeMode)) {
if (altitudeMode === "absolute") {
geometry.height = queryNumericValue2(
groundOverlay,
"altitude",
namespaces2.kml
);
geometry.zIndex = void 0;
} else if (altitudeMode !== "clampToGround") {
oneTimeWarning_default(
"kml-altitudeMode-unknown",
`KML - Unknown altitudeMode: ${altitudeMode}`
);
}
} else {
altitudeMode = queryStringValue2(
groundOverlay,
"altitudeMode",
namespaces2.gx
);
if (altitudeMode === "relativeToSeaFloor") {
oneTimeWarning_default(
"kml-altitudeMode-relativeToSeaFloor",
"KML - altitudeMode relativeToSeaFloor is currently not supported, treating as absolute."
);
geometry.height = queryNumericValue2(
groundOverlay,
"altitude",
namespaces2.kml
);
geometry.zIndex = void 0;
} else if (altitudeMode === "clampToSeaFloor") {
oneTimeWarning_default(
"kml-altitudeMode-clampToSeaFloor",
"KML - altitudeMode clampToSeaFloor is currently not supported, treating as clampToGround."
);
} else if (defined_default(altitudeMode)) {
oneTimeWarning_default(
"kml-altitudeMode-unknown",
`KML - Unknown altitudeMode: ${altitudeMode}`
);
}
}
}
function processUnsupportedFeature(dataSource, node, processingData, deferredLoading) {
dataSource._unsupportedNode.raiseEvent(
dataSource,
processingData.parentEntity,
node,
processingData.entityCollection,
processingData.styleCollection,
processingData.sourceResource,
processingData.uriResolver
);
oneTimeWarning_default(
`kml-unsupportedFeature-${node.nodeName}`,
`KML - Unsupported feature: ${node.nodeName}`
);
}
var RefreshMode = {
INTERVAL: 0,
EXPIRE: 1,
STOP: 2
};
function cleanupString(s) {
if (!defined_default(s) || s.length === 0) {
return "";
}
const sFirst = s[0];
if (sFirst === "&" || sFirst === "?") {
s = s.substring(1);
}
return s;
}
var zeroRectangle = new Rectangle_default();
var scratchCartographic16 = new Cartographic_default();
var scratchCartesian29 = new Cartesian2_default();
var scratchCartesian311 = new Cartesian3_default();
function processNetworkLinkQueryString(resource, camera, canvas, viewBoundScale, bbox, ellipsoid) {
function fixLatitude(value) {
if (value < -Math_default.PI_OVER_TWO) {
return -Math_default.PI_OVER_TWO;
} else if (value > Math_default.PI_OVER_TWO) {
return Math_default.PI_OVER_TWO;
}
return value;
}
function fixLongitude(value) {
if (value > Math_default.PI) {
return value - Math_default.TWO_PI;
} else if (value < -Math_default.PI) {
return value + Math_default.TWO_PI;
}
return value;
}
let queryString = objectToQuery_default(resource.queryParameters);
queryString = queryString.replace(/%5B/g, "[").replace(/%5D/g, "]");
if (defined_default(camera) && camera._mode !== SceneMode_default.MORPHING) {
let centerCartesian2;
let centerCartographic;
bbox = bbox ?? zeroRectangle;
if (defined_default(canvas)) {
scratchCartesian29.x = canvas.clientWidth * 0.5;
scratchCartesian29.y = canvas.clientHeight * 0.5;
centerCartesian2 = camera.pickEllipsoid(
scratchCartesian29,
ellipsoid,
scratchCartesian311
);
}
if (defined_default(centerCartesian2)) {
centerCartographic = ellipsoid.cartesianToCartographic(
centerCartesian2,
scratchCartographic16
);
} else {
centerCartographic = Rectangle_default.center(bbox, scratchCartographic16);
centerCartesian2 = ellipsoid.cartographicToCartesian(centerCartographic);
}
if (defined_default(viewBoundScale) && !Math_default.equalsEpsilon(viewBoundScale, 1, Math_default.EPSILON9)) {
const newHalfWidth = bbox.width * viewBoundScale * 0.5;
const newHalfHeight = bbox.height * viewBoundScale * 0.5;
bbox = new Rectangle_default(
fixLongitude(centerCartographic.longitude - newHalfWidth),
fixLatitude(centerCartographic.latitude - newHalfHeight),
fixLongitude(centerCartographic.longitude + newHalfWidth),
fixLatitude(centerCartographic.latitude + newHalfHeight)
);
}
queryString = queryString.replace(
"[bboxWest]",
Math_default.toDegrees(bbox.west).toString()
);
queryString = queryString.replace(
"[bboxSouth]",
Math_default.toDegrees(bbox.south).toString()
);
queryString = queryString.replace(
"[bboxEast]",
Math_default.toDegrees(bbox.east).toString()
);
queryString = queryString.replace(
"[bboxNorth]",
Math_default.toDegrees(bbox.north).toString()
);
const lon = Math_default.toDegrees(centerCartographic.longitude).toString();
const lat = Math_default.toDegrees(centerCartographic.latitude).toString();
queryString = queryString.replace("[lookatLon]", lon);
queryString = queryString.replace("[lookatLat]", lat);
queryString = queryString.replace(
"[lookatTilt]",
Math_default.toDegrees(camera.pitch).toString()
);
queryString = queryString.replace(
"[lookatHeading]",
Math_default.toDegrees(camera.heading).toString()
);
queryString = queryString.replace(
"[lookatRange]",
Cartesian3_default.distance(camera.positionWC, centerCartesian2)
);
queryString = queryString.replace("[lookatTerrainLon]", lon);
queryString = queryString.replace("[lookatTerrainLat]", lat);
queryString = queryString.replace(
"[lookatTerrainAlt]",
centerCartographic.height.toString()
);
ellipsoid.cartesianToCartographic(camera.positionWC, scratchCartographic16);
queryString = queryString.replace(
"[cameraLon]",
Math_default.toDegrees(scratchCartographic16.longitude).toString()
);
queryString = queryString.replace(
"[cameraLat]",
Math_default.toDegrees(scratchCartographic16.latitude).toString()
);
queryString = queryString.replace(
"[cameraAlt]",
Math_default.toDegrees(scratchCartographic16.height).toString()
);
const frustum = camera.frustum;
const aspectRatio = frustum.aspectRatio;
let horizFov = "";
let vertFov = "";
if (defined_default(aspectRatio)) {
const fov = Math_default.toDegrees(frustum.fov);
if (aspectRatio > 1) {
horizFov = fov;
vertFov = fov / aspectRatio;
} else {
vertFov = fov;
horizFov = fov * aspectRatio;
}
}
queryString = queryString.replace("[horizFov]", horizFov.toString());
queryString = queryString.replace("[vertFov]", vertFov.toString());
} else {
queryString = queryString.replace("[bboxWest]", "-180");
queryString = queryString.replace("[bboxSouth]", "-90");
queryString = queryString.replace("[bboxEast]", "180");
queryString = queryString.replace("[bboxNorth]", "90");
queryString = queryString.replace("[lookatLon]", "");
queryString = queryString.replace("[lookatLat]", "");
queryString = queryString.replace("[lookatRange]", "");
queryString = queryString.replace("[lookatTilt]", "");
queryString = queryString.replace("[lookatHeading]", "");
queryString = queryString.replace("[lookatTerrainLon]", "");
queryString = queryString.replace("[lookatTerrainLat]", "");
queryString = queryString.replace("[lookatTerrainAlt]", "");
queryString = queryString.replace("[cameraLon]", "");
queryString = queryString.replace("[cameraLat]", "");
queryString = queryString.replace("[cameraAlt]", "");
queryString = queryString.replace("[horizFov]", "");
queryString = queryString.replace("[vertFov]", "");
}
if (defined_default(canvas)) {
queryString = queryString.replace("[horizPixels]", canvas.clientWidth);
queryString = queryString.replace("[vertPixels]", canvas.clientHeight);
} else {
queryString = queryString.replace("[horizPixels]", "");
queryString = queryString.replace("[vertPixels]", "");
}
queryString = queryString.replace("[terrainEnabled]", "1");
queryString = queryString.replace("[clientVersion]", "1");
queryString = queryString.replace("[kmlVersion]", "2.2");
queryString = queryString.replace("[clientName]", "Cesium");
queryString = queryString.replace("[language]", "English");
resource.setQueryParameters(queryToObject_default(queryString));
}
function processNetworkLink(dataSource, node, processingData, deferredLoading) {
const r = processFeature2(dataSource, node, processingData);
const networkEntity = r.entity;
const sourceResource = processingData.sourceResource;
const uriResolver = processingData.uriResolver;
let link = queryFirstNode2(node, "Link", namespaces2.kml);
if (!defined_default(link)) {
link = queryFirstNode2(node, "Url", namespaces2.kml);
}
if (defined_default(link)) {
let href = queryStringValue2(link, "href", namespaces2.kml);
let viewRefreshMode;
let viewBoundScale;
if (defined_default(href)) {
let newSourceUri = href;
href = resolveHref(href, sourceResource, processingData.uriResolver);
if (/^data:/.test(href.getUrlComponent())) {
if (!/\.kmz/i.test(sourceResource.getUrlComponent())) {
newSourceUri = sourceResource.getDerivedResource({
url: newSourceUri
});
}
} else {
newSourceUri = href.clone();
viewRefreshMode = queryStringValue2(
link,
"viewRefreshMode",
namespaces2.kml
);
if (viewRefreshMode === "onRegion") {
oneTimeWarning_default(
"kml-refrehMode-onRegion",
"KML - Unsupported viewRefreshMode: onRegion"
);
return;
}
viewBoundScale = queryStringValue2(link, "viewBoundScale", namespaces2.kml) ?? 1;
const defaultViewFormat = viewRefreshMode === "onStop" ? "BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth]" : "";
const viewFormat = queryStringValue2(link, "viewFormat", namespaces2.kml) ?? defaultViewFormat;
const httpQuery = queryStringValue2(link, "httpQuery", namespaces2.kml);
if (defined_default(viewFormat)) {
href.setQueryParameters(queryToObject_default(cleanupString(viewFormat)));
}
if (defined_default(httpQuery)) {
href.setQueryParameters(queryToObject_default(cleanupString(httpQuery)));
}
const ellipsoid = dataSource._ellipsoid;
processNetworkLinkQueryString(
href,
dataSource.camera,
dataSource.canvas,
viewBoundScale,
dataSource._lastCameraView.bbox,
ellipsoid
);
}
const options = {
sourceUri: newSourceUri,
uriResolver,
context: networkEntity.id,
screenOverlayContainer: processingData.screenOverlayContainer
};
const networkLinkCollection = new EntityCollection_default();
const promise = load4(dataSource, networkLinkCollection, href, options).then(function(rootElement) {
const entities = dataSource._entityCollection;
const newEntities = networkLinkCollection.values;
entities.suspendEvents();
for (let i = 0; i < newEntities.length; i++) {
const newEntity = newEntities[i];
if (!defined_default(newEntity.parent)) {
newEntity.parent = networkEntity;
mergeAvailabilityWithParent(newEntity);
}
entities.add(newEntity);
}
entities.resumeEvents();
const refreshMode = queryStringValue2(
link,
"refreshMode",
namespaces2.kml
);
let refreshInterval = queryNumericValue2(link, "refreshInterval", namespaces2.kml) ?? 0;
if (refreshMode === "onInterval" && refreshInterval > 0 || refreshMode === "onExpire" || viewRefreshMode === "onStop") {
const networkLinkControl = queryFirstNode2(
rootElement,
"NetworkLinkControl",
namespaces2.kml
);
const hasNetworkLinkControl = defined_default(networkLinkControl);
const now2 = JulianDate_default.now();
const networkLinkInfo = {
id: createGuid_default(),
href,
cookie: {},
lastUpdated: now2,
updating: false,
entity: networkEntity,
viewBoundScale,
needsUpdate: false,
cameraUpdateTime: now2
};
let minRefreshPeriod = 0;
if (hasNetworkLinkControl) {
networkLinkInfo.cookie = queryToObject_default(
queryStringValue2(
networkLinkControl,
"cookie",
namespaces2.kml
) ?? ""
);
minRefreshPeriod = queryNumericValue2(
networkLinkControl,
"minRefreshPeriod",
namespaces2.kml
) ?? 0;
}
if (refreshMode === "onInterval") {
if (hasNetworkLinkControl) {
refreshInterval = Math.max(minRefreshPeriod, refreshInterval);
}
networkLinkInfo.refreshMode = RefreshMode.INTERVAL;
networkLinkInfo.time = refreshInterval;
} else if (refreshMode === "onExpire") {
let expires;
if (hasNetworkLinkControl) {
expires = queryStringValue2(
networkLinkControl,
"expires",
namespaces2.kml
);
}
if (defined_default(expires)) {
try {
const date = JulianDate_default.fromIso8601(expires);
const diff = JulianDate_default.secondsDifference(date, now2);
if (diff > 0 && diff < minRefreshPeriod) {
JulianDate_default.addSeconds(now2, minRefreshPeriod, date);
}
networkLinkInfo.refreshMode = RefreshMode.EXPIRE;
networkLinkInfo.time = date;
} catch (e) {
oneTimeWarning_default(
"kml-refreshMode-onInterval-onExpire",
"KML - NetworkLinkControl expires is not a valid date"
);
}
} else {
oneTimeWarning_default(
"kml-refreshMode-onExpire",
"KML - refreshMode of onExpire requires the NetworkLinkControl to have an expires element"
);
}
} else if (defined_default(dataSource.camera)) {
networkLinkInfo.refreshMode = RefreshMode.STOP;
networkLinkInfo.time = queryNumericValue2(link, "viewRefreshTime", namespaces2.kml) ?? 0;
} else {
oneTimeWarning_default(
"kml-refrehMode-onStop-noCamera",
"A NetworkLink with viewRefreshMode=onStop requires the `camera` property to be defined."
);
}
if (defined_default(networkLinkInfo.refreshMode)) {
dataSource._networkLinks.set(networkLinkInfo.id, networkLinkInfo);
}
}
}).catch(function(error) {
oneTimeWarning_default(`An error occured during loading ${href.url}`);
dataSource._error.raiseEvent(dataSource, error);
});
deferredLoading.addPromise(promise);
}
}
}
function processFeatureNode(dataSource, node, processingData, deferredLoading) {
const featureProcessor = featureTypes[node.localName];
if (defined_default(featureProcessor)) {
return featureProcessor(dataSource, node, processingData, deferredLoading);
}
return processUnsupportedFeature(
dataSource,
node,
processingData,
deferredLoading
);
}
function loadKml(dataSource, entityCollection, kml, sourceResource, uriResolver, screenOverlayContainer, context) {
entityCollection.removeAll();
const documentElement = kml.documentElement;
const document2 = documentElement.localName === "Document" ? documentElement : queryFirstNode2(documentElement, "Document", namespaces2.kml);
let name = queryStringValue2(document2, "name", namespaces2.kml);
if (!defined_default(name)) {
name = getFilenameFromUri_default(sourceResource.getUrlComponent());
}
if (!defined_default(dataSource._name)) {
dataSource._name = name;
}
const deferredLoading = new KmlDataSource._DeferredLoading(dataSource);
const styleCollection = new EntityCollection_default(dataSource);
return Promise.all(
processStyles(
dataSource,
kml,
styleCollection,
sourceResource,
false,
uriResolver
)
).then(function() {
let element = kml.documentElement;
if (element.localName === "kml") {
const childNodes = element.childNodes;
for (let i = 0; i < childNodes.length; i++) {
const tmp2 = childNodes[i];
if (defined_default(featureTypes[tmp2.localName])) {
element = tmp2;
break;
}
}
}
const processingData = {
parentEntity: void 0,
entityCollection,
styleCollection,
sourceResource,
uriResolver,
context,
screenOverlayContainer
};
entityCollection.suspendEvents();
processFeatureNode(dataSource, element, processingData, deferredLoading);
entityCollection.resumeEvents();
return deferredLoading.wait().then(function() {
return kml.documentElement;
});
});
}
function loadKmz(dataSource, entityCollection, blob, sourceResource, screenOverlayContainer) {
const zWorkerUrl = buildModuleUrl_default("ThirdParty/Workers/z-worker-pako.js");
configure({
workerScripts: {
deflate: [zWorkerUrl, "./pako_deflate.min.js"],
inflate: [zWorkerUrl, "./pako_inflate.min.js"]
}
});
const reader = new ZipReader(new BlobReader(blob));
return Promise.resolve(reader.getEntries()).then(function(entries2) {
const promises = [];
const uriResolver = {};
let docEntry;
for (let i = 0; i < entries2.length; i++) {
const entry = entries2[i];
if (!entry.directory) {
if (/\.kml$/i.test(entry.filename)) {
if (!defined_default(docEntry) || !/\//i.test(entry.filename)) {
if (defined_default(docEntry)) {
promises.push(loadDataUriFromZip(docEntry, uriResolver));
}
docEntry = entry;
} else {
promises.push(loadDataUriFromZip(entry, uriResolver));
}
} else {
promises.push(loadDataUriFromZip(entry, uriResolver));
}
}
}
if (defined_default(docEntry)) {
promises.push(loadXmlFromZip(docEntry, uriResolver));
}
return Promise.all(promises).then(function() {
reader.close();
if (!defined_default(uriResolver.kml)) {
throw new RuntimeError_default("KMZ file does not contain a KML document.");
}
uriResolver.keys = Object.keys(uriResolver);
return loadKml(
dataSource,
entityCollection,
uriResolver.kml,
sourceResource,
uriResolver,
screenOverlayContainer
);
});
});
}
function load4(dataSource, entityCollection, data, options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
let sourceUri = options.sourceUri;
const uriResolver = options.uriResolver;
const context = options.context;
let screenOverlayContainer = options.screenOverlayContainer;
let promise = data;
if (typeof data === "string" || data instanceof Resource_default) {
data = Resource_default.createIfNeeded(data);
promise = data.fetchBlob();
sourceUri = sourceUri ?? data.clone();
const resourceCredits = dataSource._resourceCredits;
const credits = data.credits;
if (defined_default(credits)) {
const length2 = credits.length;
for (let i = 0; i < length2; i++) {
resourceCredits.push(credits[i]);
}
}
} else {
sourceUri = sourceUri ?? Resource_default.DEFAULT.clone();
}
sourceUri = Resource_default.createIfNeeded(sourceUri);
if (defined_default(screenOverlayContainer)) {
screenOverlayContainer = getElement_default(screenOverlayContainer);
}
return Promise.resolve(promise).then(function(dataToLoad) {
if (dataToLoad instanceof Blob) {
return isZipFile(dataToLoad).then(function(isZip) {
if (isZip) {
return loadKmz(
dataSource,
entityCollection,
dataToLoad,
sourceUri,
screenOverlayContainer
);
}
return readBlobAsText2(dataToLoad).then(function(text2) {
text2 = insertNamespaces(text2);
text2 = removeDuplicateNamespaces(text2);
let kml;
let error;
try {
kml = parser2.parseFromString(text2, "application/xml");
} catch (e) {
error = e.toString();
}
if (defined_default(error) || kml.body || kml.documentElement.tagName === "parsererror") {
let msg = defined_default(error) ? error : kml.documentElement.firstChild.nodeValue;
if (!msg) {
msg = kml.body.innerText;
}
throw new RuntimeError_default(msg);
}
return loadKml(
dataSource,
entityCollection,
kml,
sourceUri,
uriResolver,
screenOverlayContainer,
context
);
});
});
}
return loadKml(
dataSource,
entityCollection,
dataToLoad,
sourceUri,
uriResolver,
screenOverlayContainer,
context
);
}).catch(function(error) {
dataSource._error.raiseEvent(dataSource, error);
console.log(error);
return Promise.reject(error);
});
}
function KmlDataSource(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const camera = options.camera;
const canvas = options.canvas;
this._changed = new Event_default();
this._error = new Event_default();
this._loading = new Event_default();
this._refresh = new Event_default();
this._unsupportedNode = new Event_default();
this._clock = void 0;
this._entityCollection = new EntityCollection_default(this);
this._name = void 0;
this._isLoading = false;
this._pinBuilder = new PinBuilder_default();
this._networkLinks = new AssociativeArray_default();
this._entityCluster = new EntityCluster_default();
this.canvas = canvas;
this.camera = camera;
this._lastCameraView = {
position: defined_default(camera) ? Cartesian3_default.clone(camera.positionWC) : void 0,
direction: defined_default(camera) ? Cartesian3_default.clone(camera.directionWC) : void 0,
up: defined_default(camera) ? Cartesian3_default.clone(camera.upWC) : void 0,
bbox: defined_default(camera) ? camera.computeViewRectangle() : Rectangle_default.clone(Rectangle_default.MAX_VALUE)
};
this._ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
let credit = options.credit;
if (typeof credit === "string") {
credit = new Credit_default(credit);
}
this._credit = credit;
this._resourceCredits = [];
this._kmlTours = [];
this._screenOverlays = [];
}
KmlDataSource.load = function(data, options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const dataSource = new KmlDataSource(options);
return dataSource.load(data, options);
};
Object.defineProperties(KmlDataSource.prototype, {
/**
* Gets or sets a human-readable name for this instance.
* This will be automatically be set to the KML document name on load.
* @memberof KmlDataSource.prototype
* @type {string}
*/
name: {
get: function() {
return this._name;
},
set: function(value) {
if (this._name !== value) {
this._name = value;
this._changed.raiseEvent(this);
}
}
},
/**
* Gets the clock settings defined by the loaded KML. This represents the total
* availability interval for all time-dynamic data. If the KML does not contain
* time-dynamic data, this value is undefined.
* @memberof KmlDataSource.prototype
* @type {DataSourceClock}
*/
clock: {
get: function() {
return this._clock;
}
},
/**
* Gets the collection of {@link Entity} instances.
* @memberof KmlDataSource.prototype
* @type {EntityCollection}
*/
entities: {
get: function() {
return this._entityCollection;
}
},
/**
* Gets a value indicating if the data source is currently loading data.
* @memberof KmlDataSource.prototype
* @type {boolean}
*/
isLoading: {
get: function() {
return this._isLoading;
}
},
/**
* Gets an event that will be raised when the underlying data changes.
* @memberof KmlDataSource.prototype
* @type {Event}
*/
changedEvent: {
get: function() {
return this._changed;
}
},
/**
* Gets an event that will be raised if an error is encountered during processing.
* @memberof KmlDataSource.prototype
* @type {Event}
*/
errorEvent: {
get: function() {
return this._error;
}
},
/**
* Gets an event that will be raised when the data source either starts or stops loading.
* @memberof KmlDataSource.prototype
* @type {Event}
*/
loadingEvent: {
get: function() {
return this._loading;
}
},
/**
* Gets an event that will be raised when the data source refreshes a network link.
* @memberof KmlDataSource.prototype
* @type {Event}
*/
refreshEvent: {
get: function() {
return this._refresh;
}
},
/**
* Gets an event that will be raised when the data source finds an unsupported node type.
* @memberof KmlDataSource.prototype
* @type {Event}
*/
unsupportedNodeEvent: {
get: function() {
return this._unsupportedNode;
}
},
/**
* Gets whether or not this data source should be displayed.
* @memberof KmlDataSource.prototype
* @type {boolean}
*/
show: {
get: function() {
return this._entityCollection.show;
},
set: function(value) {
this._entityCollection.show = value;
}
},
/**
* Gets or sets the clustering options for this data source. This object can be shared between multiple data sources.
*
* @memberof KmlDataSource.prototype
* @type {EntityCluster}
*/
clustering: {
get: function() {
return this._entityCluster;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value must be defined.");
}
this._entityCluster = value;
}
},
/**
* Gets the credit that will be displayed for the data source
* @memberof KmlDataSource.prototype
* @type {Credit}
*/
credit: {
get: function() {
return this._credit;
}
},
/**
* Gets the KML Tours that are used to guide the camera to specified destinations on given time intervals.
* @memberof KmlDataSource.prototype
* @type {KmlTour[]}
*/
kmlTours: {
get: function() {
return this._kmlTours;
}
}
});
KmlDataSource.prototype.load = function(data, options) {
if (!defined_default(data)) {
throw new DeveloperError_default("data is required.");
}
options = options ?? Frozen_default.EMPTY_OBJECT;
DataSource_default.setLoading(this, true);
const oldName = this._name;
this._name = void 0;
this._clampToGround = options.clampToGround ?? false;
const that = this;
return load4(this, this._entityCollection, data, options).then(function() {
let clock;
const availability = that._entityCollection.computeAvailability();
let start = availability.start;
let stop2 = availability.stop;
const isMinStart = JulianDate_default.equals(start, Iso8601_default.MINIMUM_VALUE);
const isMaxStop = JulianDate_default.equals(stop2, Iso8601_default.MAXIMUM_VALUE);
if (!isMinStart || !isMaxStop) {
let date;
if (isMinStart) {
date = /* @__PURE__ */ new Date();
date.setHours(0, 0, 0, 0);
start = JulianDate_default.fromDate(date);
}
if (isMaxStop) {
date = /* @__PURE__ */ new Date();
date.setHours(24, 0, 0, 0);
stop2 = JulianDate_default.fromDate(date);
}
clock = new DataSourceClock_default();
clock.startTime = start;
clock.stopTime = stop2;
clock.currentTime = JulianDate_default.clone(start);
clock.clockRange = ClockRange_default.LOOP_STOP;
clock.clockStep = ClockStep_default.SYSTEM_CLOCK_MULTIPLIER;
clock.multiplier = Math.round(
Math.min(
Math.max(JulianDate_default.secondsDifference(stop2, start) / 60, 1),
31556900
)
);
}
let changed = false;
if (clock !== that._clock) {
that._clock = clock;
changed = true;
}
if (oldName !== that._name) {
changed = true;
}
if (changed) {
that._changed.raiseEvent(that);
}
DataSource_default.setLoading(that, false);
return that;
}).catch(function(error) {
DataSource_default.setLoading(that, false);
that._error.raiseEvent(that, error);
console.log(error);
return Promise.reject(error);
});
};
KmlDataSource.prototype.destroy = function() {
while (this._screenOverlays.length > 0) {
const elem = this._screenOverlays.pop();
elem.remove();
}
};
function mergeAvailabilityWithParent(child) {
const parent = child.parent;
if (defined_default(parent)) {
const parentAvailability = parent.availability;
if (defined_default(parentAvailability)) {
const childAvailability = child.availability;
if (defined_default(childAvailability)) {
childAvailability.intersect(parentAvailability);
} else {
child.availability = parentAvailability;
}
}
}
}
function getNetworkLinkUpdateCallback(dataSource, networkLink, newEntityCollection, networkLinks, processedHref) {
return function(rootElement) {
if (!networkLinks.contains(networkLink.id)) {
return;
}
let remove4 = false;
const networkLinkControl = queryFirstNode2(
rootElement,
"NetworkLinkControl",
namespaces2.kml
);
const hasNetworkLinkControl = defined_default(networkLinkControl);
let minRefreshPeriod = 0;
if (hasNetworkLinkControl) {
if (defined_default(queryFirstNode2(networkLinkControl, "Update", namespaces2.kml))) {
oneTimeWarning_default(
"kml-networkLinkControl-update",
"KML - NetworkLinkControl updates aren't supported."
);
networkLink.updating = false;
networkLinks.remove(networkLink.id);
return;
}
networkLink.cookie = queryToObject_default(
queryStringValue2(networkLinkControl, "cookie", namespaces2.kml) ?? ""
);
minRefreshPeriod = queryNumericValue2(
networkLinkControl,
"minRefreshPeriod",
namespaces2.kml
) ?? 0;
}
const now2 = JulianDate_default.now();
const refreshMode = networkLink.refreshMode;
if (refreshMode === RefreshMode.INTERVAL) {
if (defined_default(networkLinkControl)) {
networkLink.time = Math.max(minRefreshPeriod, networkLink.time);
}
} else if (refreshMode === RefreshMode.EXPIRE) {
let expires;
if (defined_default(networkLinkControl)) {
expires = queryStringValue2(
networkLinkControl,
"expires",
namespaces2.kml
);
}
if (defined_default(expires)) {
try {
const date = JulianDate_default.fromIso8601(expires);
const diff = JulianDate_default.secondsDifference(date, now2);
if (diff > 0 && diff < minRefreshPeriod) {
JulianDate_default.addSeconds(now2, minRefreshPeriod, date);
}
networkLink.time = date;
} catch (e) {
oneTimeWarning_default(
"kml-networkLinkControl-expires",
"KML - NetworkLinkControl expires is not a valid date"
);
remove4 = true;
}
} else {
oneTimeWarning_default(
"kml-refreshMode-onExpire",
"KML - refreshMode of onExpire requires the NetworkLinkControl to have an expires element"
);
remove4 = true;
}
}
const networkLinkEntity = networkLink.entity;
const entityCollection = dataSource._entityCollection;
const newEntities = newEntityCollection.values;
function removeChildren(entity) {
entityCollection.remove(entity);
const children = entity._children;
const count = children.length;
for (let i2 = 0; i2 < count; ++i2) {
removeChildren(children[i2]);
}
}
entityCollection.suspendEvents();
const entitiesCopy = entityCollection.values.slice();
let i;
for (i = 0; i < entitiesCopy.length; ++i) {
const entityToRemove = entitiesCopy[i];
if (entityToRemove.parent === networkLinkEntity) {
entityToRemove.parent = void 0;
removeChildren(entityToRemove);
}
}
entityCollection.resumeEvents();
entityCollection.suspendEvents();
for (i = 0; i < newEntities.length; i++) {
const newEntity = newEntities[i];
if (!defined_default(newEntity.parent)) {
newEntity.parent = networkLinkEntity;
mergeAvailabilityWithParent(newEntity);
}
entityCollection.add(newEntity);
}
entityCollection.resumeEvents();
if (remove4) {
networkLinks.remove(networkLink.id);
} else {
networkLink.lastUpdated = now2;
}
const availability = entityCollection.computeAvailability();
const start = availability.start;
const stop2 = availability.stop;
const isMinStart = JulianDate_default.equals(start, Iso8601_default.MINIMUM_VALUE);
const isMaxStop = JulianDate_default.equals(stop2, Iso8601_default.MAXIMUM_VALUE);
if (!isMinStart || !isMaxStop) {
const clock = dataSource._clock;
if (clock.startTime !== start || clock.stopTime !== stop2) {
clock.startTime = start;
clock.stopTime = stop2;
dataSource._changed.raiseEvent(dataSource);
}
}
networkLink.updating = false;
networkLink.needsUpdate = false;
dataSource._refresh.raiseEvent(
dataSource,
processedHref.getUrlComponent(true)
);
};
}
var entitiesToIgnore = new AssociativeArray_default();
KmlDataSource.prototype.update = function(time) {
const networkLinks = this._networkLinks;
if (networkLinks.length === 0) {
return true;
}
const now2 = JulianDate_default.now();
const that = this;
entitiesToIgnore.removeAll();
function recurseIgnoreEntities(entity) {
const children = entity._children;
const count = children.length;
for (let i = 0; i < count; ++i) {
const child = children[i];
entitiesToIgnore.set(child.id, child);
recurseIgnoreEntities(child);
}
}
let cameraViewUpdate = false;
const lastCameraView = this._lastCameraView;
const camera = this.camera;
if (defined_default(camera) && !(camera.positionWC.equalsEpsilon(
lastCameraView.position,
Math_default.EPSILON7
) && camera.directionWC.equalsEpsilon(
lastCameraView.direction,
Math_default.EPSILON7
) && camera.upWC.equalsEpsilon(lastCameraView.up, Math_default.EPSILON7))) {
lastCameraView.position = Cartesian3_default.clone(camera.positionWC);
lastCameraView.direction = Cartesian3_default.clone(camera.directionWC);
lastCameraView.up = Cartesian3_default.clone(camera.upWC);
lastCameraView.bbox = camera.computeViewRectangle();
cameraViewUpdate = true;
}
const newNetworkLinks = new AssociativeArray_default();
let changed = false;
networkLinks.values.forEach(function(networkLink) {
const entity = networkLink.entity;
if (entitiesToIgnore.contains(entity.id)) {
return;
}
if (!networkLink.updating) {
let doUpdate = false;
if (networkLink.refreshMode === RefreshMode.INTERVAL) {
if (JulianDate_default.secondsDifference(now2, networkLink.lastUpdated) > networkLink.time) {
doUpdate = true;
}
} else if (networkLink.refreshMode === RefreshMode.EXPIRE) {
if (JulianDate_default.greaterThan(now2, networkLink.time)) {
doUpdate = true;
}
} else if (networkLink.refreshMode === RefreshMode.STOP) {
if (cameraViewUpdate) {
networkLink.needsUpdate = true;
networkLink.cameraUpdateTime = now2;
}
if (networkLink.needsUpdate && JulianDate_default.secondsDifference(now2, networkLink.cameraUpdateTime) >= networkLink.time) {
doUpdate = true;
}
}
if (doUpdate) {
recurseIgnoreEntities(entity);
networkLink.updating = true;
const newEntityCollection = new EntityCollection_default();
const href = networkLink.href.clone();
href.setQueryParameters(networkLink.cookie);
const ellipsoid = that._ellipsoid ?? Ellipsoid_default.default;
processNetworkLinkQueryString(
href,
that.camera,
that.canvas,
networkLink.viewBoundScale,
lastCameraView.bbox,
ellipsoid
);
load4(that, newEntityCollection, href, {
context: entity.id
}).then(
getNetworkLinkUpdateCallback(
that,
networkLink,
newEntityCollection,
newNetworkLinks,
href
)
).catch(function(error) {
const msg = `NetworkLink ${networkLink.href} refresh failed: ${error}`;
console.log(msg);
that._error.raiseEvent(that, msg);
});
changed = true;
}
}
newNetworkLinks.set(networkLink.id, networkLink);
});
if (changed) {
this._networkLinks = newNetworkLinks;
this._changed.raiseEvent(this);
}
return true;
};
function KmlFeatureData() {
this.author = {
name: void 0,
uri: void 0,
email: void 0
};
this.link = {
href: void 0,
hreflang: void 0,
rel: void 0,
type: void 0,
title: void 0,
length: void 0
};
this.address = void 0;
this.phoneNumber = void 0;
this.snippet = void 0;
this.extendedData = void 0;
}
KmlDataSource._DeferredLoading = DeferredLoading;
KmlDataSource._getTimestamp = getTimestamp_default;
var KmlDataSource_default = KmlDataSource;
// packages/engine/Source/DataSources/Visualizer.js
var import_InlineWorkers999 = __toESM(require_InlineWorkers(), 1);
function Visualizer() {
DeveloperError_default.throwInstantiationError();
}
Visualizer.prototype.update = DeveloperError_default.throwInstantiationError;
Visualizer.prototype.getBoundingSphere = DeveloperError_default.throwInstantiationError;
Visualizer.prototype.isDestroyed = DeveloperError_default.throwInstantiationError;
Visualizer.prototype.destroy = DeveloperError_default.throwInstantiationError;
var Visualizer_default = Visualizer;
// packages/engine/Source/DataSources/exportKml.js
var import_InlineWorkers1000 = __toESM(require_InlineWorkers(), 1);
var BILLBOARD_SIZE3 = 32;
var kmlNamespace = "http://www.opengis.net/kml/2.2";
var gxNamespace = "http://www.google.com/kml/ext/2.2";
var xmlnsNamespace = "http://www.w3.org/2000/xmlns/";
function ExternalFileHandler(modelCallback) {
this._files = {};
this._promises = [];
this._count = 0;
this._modelCallback = modelCallback;
}
var imageTypeRegex = /^data:image\/([^,;]+)/;
ExternalFileHandler.prototype.texture = function(texture) {
const that = this;
let filename;
if (typeof texture === "string" || texture instanceof Resource_default) {
texture = Resource_default.createIfNeeded(texture);
if (!texture.isDataUri) {
return texture.url;
}
const regexResult = texture.url.match(imageTypeRegex);
filename = `texture_${++this._count}`;
if (defined_default(regexResult)) {
filename += `.${regexResult[1]}`;
}
const promise = texture.fetchBlob().then(function(blob) {
that._files[filename] = blob;
});
this._promises.push(promise);
return filename;
}
if (texture instanceof HTMLCanvasElement) {
filename = `texture_${++this._count}.png`;
const promise = new Promise((resolve2) => {
texture.toBlob(function(blob) {
that._files[filename] = blob;
resolve2();
});
});
this._promises.push(promise);
return filename;
}
return "";
};
function getModelBlobHander(that, filename) {
return function(blob) {
that._files[filename] = blob;
};
}
ExternalFileHandler.prototype.model = function(model, time) {
const modelCallback = this._modelCallback;
if (!defined_default(modelCallback)) {
throw new RuntimeError_default(
"Encountered a model entity while exporting to KML, but no model callback was supplied."
);
}
const externalFiles = {};
const url2 = modelCallback(model, time, externalFiles);
for (const filename in externalFiles) {
if (externalFiles.hasOwnProperty(filename)) {
const promise = Promise.resolve(externalFiles[filename]);
this._promises.push(promise);
promise.then(getModelBlobHander(this, filename));
}
}
return url2;
};
Object.defineProperties(ExternalFileHandler.prototype, {
promise: {
get: function() {
return Promise.all(this._promises);
}
},
files: {
get: function() {
return this._files;
}
}
});
function ValueGetter(time) {
this._time = time;
}
ValueGetter.prototype.get = function(property, defaultVal, result) {
let value;
if (defined_default(property)) {
value = defined_default(property.getValue) ? property.getValue(this._time, result) : property;
}
return value ?? defaultVal;
};
ValueGetter.prototype.getColor = function(property, defaultVal) {
const result = this.get(property, defaultVal);
if (defined_default(result)) {
return colorToString(result);
}
};
ValueGetter.prototype.getMaterialType = function(property) {
if (!defined_default(property)) {
return;
}
return property.getType(this._time);
};
function StyleCache() {
this._ids = {};
this._styles = {};
this._count = 0;
}
StyleCache.prototype.get = function(element) {
const ids = this._ids;
const key = element.innerHTML;
if (defined_default(ids[key])) {
return ids[key];
}
let styleId = `style-${++this._count}`;
element.setAttribute("id", styleId);
styleId = `#${styleId}`;
ids[key] = styleId;
this._styles[key] = element;
return styleId;
};
StyleCache.prototype.save = function(parentElement) {
const styles = this._styles;
const firstElement = parentElement.childNodes[0];
for (const key in styles) {
if (styles.hasOwnProperty(key)) {
parentElement.insertBefore(styles[key], firstElement);
}
}
};
function IdManager() {
this._ids = {};
}
IdManager.prototype.get = function(id) {
if (!defined_default(id)) {
return this.get(createGuid_default());
}
const ids = this._ids;
if (!defined_default(ids[id])) {
ids[id] = 0;
return id;
}
return `${id.toString()}-${++ids[id]}`;
};
function exportKml(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const entities = options.entities;
const kmz = options.kmz ?? false;
if (!defined_default(entities)) {
throw new DeveloperError_default("entities is required.");
}
const state = exportKml._createState(options);
const rootEntities = entities.values.filter(function(entity) {
return !defined_default(entity.parent);
});
const kmlDoc = state.kmlDoc;
const kmlElement = kmlDoc.documentElement;
kmlElement.setAttributeNS(xmlnsNamespace, "xmlns:gx", gxNamespace);
const kmlDocumentElement = kmlDoc.createElement("Document");
kmlElement.appendChild(kmlDocumentElement);
recurseEntities(state, kmlDocumentElement, rootEntities);
state.styleCache.save(kmlDocumentElement);
const externalFileHandler = state.externalFileHandler;
return externalFileHandler.promise.then(function() {
const serializer = new XMLSerializer();
const kmlString = serializer.serializeToString(state.kmlDoc);
if (kmz) {
return createKmz(kmlString, externalFileHandler.files);
}
return {
kml: kmlString,
externalFiles: externalFileHandler.files
};
});
}
function createKmz(kmlString, externalFiles) {
const zWorkerUrl = buildModuleUrl_default("ThirdParty/Workers/z-worker-pako.js");
configure({
workerScripts: {
deflate: [zWorkerUrl, "./pako_deflate.min.js"],
inflate: [zWorkerUrl, "./pako_inflate.min.js"]
}
});
const blobWriter = new BlobWriter();
const writer = new ZipWriter(blobWriter);
return writer.add("doc.kml", new TextReader(kmlString)).then(function() {
const keys = Object.keys(externalFiles);
return addExternalFilesToZip(writer, keys, externalFiles, 0);
}).then(function() {
return writer.close();
}).then(function(blob) {
return {
kmz: blob
};
});
}
function addExternalFilesToZip(writer, keys, externalFiles, index) {
if (keys.length === index) {
return;
}
const filename = keys[index];
return writer.add(filename, new BlobReader(externalFiles[filename])).then(function() {
return addExternalFilesToZip(writer, keys, externalFiles, index + 1);
});
}
exportKml._createState = function(options) {
const entities = options.entities;
const styleCache = new StyleCache();
const entityAvailability = entities.computeAvailability();
const time = defined_default(options.time) ? options.time : entityAvailability.start;
let defaultAvailability = options.defaultAvailability ?? entityAvailability;
const sampleDuration = options.sampleDuration ?? 60;
if (defaultAvailability.start === Iso8601_default.MINIMUM_VALUE) {
if (defaultAvailability.stop === Iso8601_default.MAXIMUM_VALUE) {
defaultAvailability = new TimeInterval_default();
} else {
JulianDate_default.addSeconds(
defaultAvailability.stop,
-10 * sampleDuration,
defaultAvailability.start
);
}
} else if (defaultAvailability.stop === Iso8601_default.MAXIMUM_VALUE) {
JulianDate_default.addSeconds(
defaultAvailability.start,
10 * sampleDuration,
defaultAvailability.stop
);
}
const externalFileHandler = new ExternalFileHandler(options.modelCallback);
const kmlDoc = document.implementation.createDocument(kmlNamespace, "kml");
return {
kmlDoc,
ellipsoid: options.ellipsoid ?? Ellipsoid_default.default,
idManager: new IdManager(),
styleCache,
externalFileHandler,
time,
valueGetter: new ValueGetter(time),
sampleDuration,
// Wrap it in a TimeIntervalCollection because that is what entity.availability is
defaultAvailability: new TimeIntervalCollection_default([defaultAvailability])
};
};
function recurseEntities(state, parentNode, entities) {
const kmlDoc = state.kmlDoc;
const styleCache = state.styleCache;
const valueGetter = state.valueGetter;
const idManager = state.idManager;
const count = entities.length;
let overlays;
let geometries;
let styles;
for (let i = 0; i < count; ++i) {
const entity = entities[i];
overlays = [];
geometries = [];
styles = [];
createPoint2(state, entity, geometries, styles);
createLineString2(state, entity.polyline, geometries, styles);
createPolygon2(state, entity.rectangle, geometries, styles, overlays);
createPolygon2(state, entity.polygon, geometries, styles, overlays);
createModel(state, entity, entity.model, geometries, styles);
let timeSpan;
const availability = entity.availability;
if (defined_default(availability)) {
timeSpan = kmlDoc.createElement("TimeSpan");
if (!JulianDate_default.equals(availability.start, Iso8601_default.MINIMUM_VALUE)) {
timeSpan.appendChild(
createBasicElementWithText(
kmlDoc,
"begin",
JulianDate_default.toIso8601(availability.start)
)
);
}
if (!JulianDate_default.equals(availability.stop, Iso8601_default.MAXIMUM_VALUE)) {
timeSpan.appendChild(
createBasicElementWithText(
kmlDoc,
"end",
JulianDate_default.toIso8601(availability.stop)
)
);
}
}
for (let overlayIndex = 0; overlayIndex < overlays.length; ++overlayIndex) {
const overlay = overlays[overlayIndex];
overlay.setAttribute("id", idManager.get(entity.id));
overlay.appendChild(
createBasicElementWithText(kmlDoc, "name", entity.name)
);
overlay.appendChild(
createBasicElementWithText(kmlDoc, "visibility", entity.show)
);
overlay.appendChild(
createBasicElementWithText(kmlDoc, "description", entity.description)
);
if (defined_default(timeSpan)) {
overlay.appendChild(timeSpan);
}
parentNode.appendChild(overlay);
}
const geometryCount = geometries.length;
if (geometryCount > 0) {
const placemark = kmlDoc.createElement("Placemark");
placemark.setAttribute("id", idManager.get(entity.id));
let name = entity.name;
const labelGraphics = entity.label;
if (defined_default(labelGraphics)) {
const labelStyle = kmlDoc.createElement("LabelStyle");
const text2 = valueGetter.get(labelGraphics.text);
name = defined_default(text2) && text2.length > 0 ? text2 : name;
const color = valueGetter.getColor(labelGraphics.fillColor);
if (defined_default(color)) {
labelStyle.appendChild(
createBasicElementWithText(kmlDoc, "color", color)
);
labelStyle.appendChild(
createBasicElementWithText(kmlDoc, "colorMode", "normal")
);
}
const scale = valueGetter.get(labelGraphics.scale);
if (defined_default(scale)) {
labelStyle.appendChild(
createBasicElementWithText(kmlDoc, "scale", scale)
);
}
styles.push(labelStyle);
}
placemark.appendChild(createBasicElementWithText(kmlDoc, "name", name));
placemark.appendChild(
createBasicElementWithText(kmlDoc, "visibility", entity.show)
);
placemark.appendChild(
createBasicElementWithText(kmlDoc, "description", entity.description)
);
if (defined_default(timeSpan)) {
placemark.appendChild(timeSpan);
}
parentNode.appendChild(placemark);
const styleCount = styles.length;
if (styleCount > 0) {
const style = kmlDoc.createElement("Style");
for (let styleIndex = 0; styleIndex < styleCount; ++styleIndex) {
style.appendChild(styles[styleIndex]);
}
placemark.appendChild(
createBasicElementWithText(kmlDoc, "styleUrl", styleCache.get(style))
);
}
if (geometries.length === 1) {
placemark.appendChild(geometries[0]);
} else if (geometries.length > 1) {
const multigeometry = kmlDoc.createElement("MultiGeometry");
for (let geometryIndex = 0; geometryIndex < geometryCount; ++geometryIndex) {
multigeometry.appendChild(geometries[geometryIndex]);
}
placemark.appendChild(multigeometry);
}
}
const children = entity._children;
if (children.length > 0) {
const folderNode = kmlDoc.createElement("Folder");
folderNode.setAttribute("id", idManager.get(entity.id));
folderNode.appendChild(
createBasicElementWithText(kmlDoc, "name", entity.name)
);
folderNode.appendChild(
createBasicElementWithText(kmlDoc, "visibility", entity.show)
);
folderNode.appendChild(
createBasicElementWithText(kmlDoc, "description", entity.description)
);
parentNode.appendChild(folderNode);
recurseEntities(state, folderNode, children);
}
}
}
var scratchCartesian312 = new Cartesian3_default();
var scratchCartographic17 = new Cartographic_default();
var scratchJulianDate3 = new JulianDate_default();
function createPoint2(state, entity, geometries, styles) {
const kmlDoc = state.kmlDoc;
const ellipsoid = state.ellipsoid;
const valueGetter = state.valueGetter;
const pointGraphics = entity.billboard ?? entity.point;
if (!defined_default(pointGraphics) && !defined_default(entity.path)) {
return;
}
const entityPositionProperty = entity.position;
if (!entityPositionProperty.isConstant) {
createTracks(state, entity, pointGraphics, geometries, styles);
return;
}
valueGetter.get(entityPositionProperty, void 0, scratchCartesian312);
const coordinates = createBasicElementWithText(
kmlDoc,
"coordinates",
getCoordinates(scratchCartesian312, ellipsoid)
);
const pointGeometry = kmlDoc.createElement("Point");
const altitudeMode = kmlDoc.createElement("altitudeMode");
altitudeMode.appendChild(
getAltitudeMode(state, pointGraphics.heightReference)
);
pointGeometry.appendChild(altitudeMode);
pointGeometry.appendChild(coordinates);
geometries.push(pointGeometry);
const iconStyle = pointGraphics instanceof BillboardGraphics_default ? createIconStyleFromBillboard(state, pointGraphics) : createIconStyleFromPoint(state, pointGraphics);
styles.push(iconStyle);
}
function createTracks(state, entity, pointGraphics, geometries, styles) {
const kmlDoc = state.kmlDoc;
const ellipsoid = state.ellipsoid;
const valueGetter = state.valueGetter;
let intervals;
const entityPositionProperty = entity.position;
let useEntityPositionProperty = true;
if (entityPositionProperty instanceof CompositePositionProperty_default) {
intervals = entityPositionProperty.intervals;
useEntityPositionProperty = false;
} else {
intervals = entity.availability ?? state.defaultAvailability;
}
const isModel = pointGraphics instanceof ModelGraphics_default;
let i, j, times;
const tracks = [];
for (i = 0; i < intervals.length; ++i) {
const interval = intervals.get(i);
let positionProperty = useEntityPositionProperty ? entityPositionProperty : interval.data;
const trackAltitudeMode = kmlDoc.createElement("altitudeMode");
if (positionProperty instanceof ScaledPositionProperty_default) {
positionProperty = positionProperty._value;
trackAltitudeMode.appendChild(
getAltitudeMode(state, HeightReference_default.CLAMP_TO_GROUND)
);
} else if (defined_default(pointGraphics)) {
trackAltitudeMode.appendChild(
getAltitudeMode(state, pointGraphics.heightReference)
);
} else {
trackAltitudeMode.appendChild(
getAltitudeMode(state, HeightReference_default.NONE)
);
}
const positionTimes = [];
const positionValues = [];
if (positionProperty.isConstant) {
valueGetter.get(positionProperty, void 0, scratchCartesian312);
const constCoordinates = createBasicElementWithText(
kmlDoc,
"coordinates",
getCoordinates(scratchCartesian312, ellipsoid)
);
positionTimes.push(JulianDate_default.toIso8601(interval.start));
positionValues.push(constCoordinates);
positionTimes.push(JulianDate_default.toIso8601(interval.stop));
positionValues.push(constCoordinates);
} else if (positionProperty instanceof SampledPositionProperty_default) {
times = positionProperty._property._times;
for (j = 0; j < times.length; ++j) {
positionTimes.push(JulianDate_default.toIso8601(times[j]));
positionProperty.getValueInReferenceFrame(
times[j],
ReferenceFrame_default.FIXED,
scratchCartesian312
);
positionValues.push(getCoordinates(scratchCartesian312, ellipsoid));
}
} else if (positionProperty instanceof SampledProperty_default) {
times = positionProperty._times;
const values = positionProperty._values;
for (j = 0; j < times.length; ++j) {
positionTimes.push(JulianDate_default.toIso8601(times[j]));
Cartesian3_default.fromArray(values, j * 3, scratchCartesian312);
positionValues.push(getCoordinates(scratchCartesian312, ellipsoid));
}
} else {
const duration = state.sampleDuration;
interval.start.clone(scratchJulianDate3);
if (!interval.isStartIncluded) {
JulianDate_default.addSeconds(scratchJulianDate3, duration, scratchJulianDate3);
}
const stopDate = interval.stop;
while (JulianDate_default.lessThan(scratchJulianDate3, stopDate)) {
positionProperty.getValue(scratchJulianDate3, scratchCartesian312);
positionTimes.push(JulianDate_default.toIso8601(scratchJulianDate3));
positionValues.push(getCoordinates(scratchCartesian312, ellipsoid));
JulianDate_default.addSeconds(scratchJulianDate3, duration, scratchJulianDate3);
}
if (interval.isStopIncluded && JulianDate_default.equals(scratchJulianDate3, stopDate)) {
positionProperty.getValue(scratchJulianDate3, scratchCartesian312);
positionTimes.push(JulianDate_default.toIso8601(scratchJulianDate3));
positionValues.push(getCoordinates(scratchCartesian312, ellipsoid));
}
}
const trackGeometry = kmlDoc.createElementNS(gxNamespace, "Track");
trackGeometry.appendChild(trackAltitudeMode);
for (let k = 0; k < positionTimes.length; ++k) {
const when = createBasicElementWithText(kmlDoc, "when", positionTimes[k]);
const coord = createBasicElementWithText(
kmlDoc,
"coord",
positionValues[k],
gxNamespace
);
trackGeometry.appendChild(when);
trackGeometry.appendChild(coord);
}
if (isModel) {
trackGeometry.appendChild(createModelGeometry(state, pointGraphics));
}
tracks.push(trackGeometry);
}
if (tracks.length === 1) {
geometries.push(tracks[0]);
} else if (tracks.length > 1) {
const multiTrackGeometry = kmlDoc.createElementNS(
gxNamespace,
"MultiTrack"
);
for (i = 0; i < tracks.length; ++i) {
multiTrackGeometry.appendChild(tracks[i]);
}
geometries.push(multiTrackGeometry);
}
if (defined_default(pointGraphics) && !isModel) {
const iconStyle = pointGraphics instanceof BillboardGraphics_default ? createIconStyleFromBillboard(state, pointGraphics) : createIconStyleFromPoint(state, pointGraphics);
styles.push(iconStyle);
}
const path = entity.path;
if (defined_default(path)) {
const width = valueGetter.get(path.width);
const material = path.material;
if (defined_default(material) || defined_default(width)) {
const lineStyle = kmlDoc.createElement("LineStyle");
if (defined_default(width)) {
lineStyle.appendChild(
createBasicElementWithText(kmlDoc, "width", width)
);
}
processMaterial(state, material, lineStyle);
styles.push(lineStyle);
}
}
}
function createIconStyleFromPoint(state, pointGraphics) {
const kmlDoc = state.kmlDoc;
const valueGetter = state.valueGetter;
const iconStyle = kmlDoc.createElement("IconStyle");
const color = valueGetter.getColor(pointGraphics.color);
if (defined_default(color)) {
iconStyle.appendChild(createBasicElementWithText(kmlDoc, "color", color));
iconStyle.appendChild(
createBasicElementWithText(kmlDoc, "colorMode", "normal")
);
}
const pixelSize = valueGetter.get(pointGraphics.pixelSize);
if (defined_default(pixelSize)) {
iconStyle.appendChild(
createBasicElementWithText(kmlDoc, "scale", pixelSize / BILLBOARD_SIZE3)
);
}
return iconStyle;
}
function createIconStyleFromBillboard(state, billboardGraphics) {
const kmlDoc = state.kmlDoc;
const valueGetter = state.valueGetter;
const externalFileHandler = state.externalFileHandler;
const iconStyle = kmlDoc.createElement("IconStyle");
let image = valueGetter.get(billboardGraphics.image);
if (defined_default(image)) {
image = externalFileHandler.texture(image);
const icon = kmlDoc.createElement("Icon");
icon.appendChild(createBasicElementWithText(kmlDoc, "href", image));
const imageSubRegion = valueGetter.get(billboardGraphics.imageSubRegion);
if (defined_default(imageSubRegion)) {
icon.appendChild(
createBasicElementWithText(kmlDoc, "x", imageSubRegion.x, gxNamespace)
);
icon.appendChild(
createBasicElementWithText(kmlDoc, "y", imageSubRegion.y, gxNamespace)
);
icon.appendChild(
createBasicElementWithText(
kmlDoc,
"w",
imageSubRegion.width,
gxNamespace
)
);
icon.appendChild(
createBasicElementWithText(
kmlDoc,
"h",
imageSubRegion.height,
gxNamespace
)
);
}
iconStyle.appendChild(icon);
}
const color = valueGetter.getColor(billboardGraphics.color);
if (defined_default(color)) {
iconStyle.appendChild(createBasicElementWithText(kmlDoc, "color", color));
iconStyle.appendChild(
createBasicElementWithText(kmlDoc, "colorMode", "normal")
);
}
let scale = valueGetter.get(billboardGraphics.scale);
if (defined_default(scale)) {
iconStyle.appendChild(createBasicElementWithText(kmlDoc, "scale", scale));
}
const pixelOffset = valueGetter.get(billboardGraphics.pixelOffset);
if (defined_default(pixelOffset)) {
scale = scale ?? 1;
Cartesian2_default.divideByScalar(pixelOffset, scale, pixelOffset);
const width = valueGetter.get(billboardGraphics.width, BILLBOARD_SIZE3);
const height = valueGetter.get(billboardGraphics.height, BILLBOARD_SIZE3);
const horizontalOrigin = valueGetter.get(
billboardGraphics.horizontalOrigin,
HorizontalOrigin_default.CENTER
);
if (horizontalOrigin === HorizontalOrigin_default.CENTER) {
pixelOffset.x -= width * 0.5;
} else if (horizontalOrigin === HorizontalOrigin_default.RIGHT) {
pixelOffset.x -= width;
}
const verticalOrigin = valueGetter.get(
billboardGraphics.verticalOrigin,
VerticalOrigin_default.CENTER
);
if (verticalOrigin === VerticalOrigin_default.TOP) {
pixelOffset.y += height;
} else if (verticalOrigin === VerticalOrigin_default.CENTER) {
pixelOffset.y += height * 0.5;
}
const hotSpot = kmlDoc.createElement("hotSpot");
hotSpot.setAttribute("x", -pixelOffset.x);
hotSpot.setAttribute("y", pixelOffset.y);
hotSpot.setAttribute("xunits", "pixels");
hotSpot.setAttribute("yunits", "pixels");
iconStyle.appendChild(hotSpot);
}
let rotation = valueGetter.get(billboardGraphics.rotation);
const alignedAxis = valueGetter.get(billboardGraphics.alignedAxis);
if (defined_default(rotation) && Cartesian3_default.equals(Cartesian3_default.UNIT_Z, alignedAxis)) {
rotation = Math_default.toDegrees(-rotation);
if (rotation === 0) {
rotation = 360;
}
iconStyle.appendChild(
createBasicElementWithText(kmlDoc, "heading", rotation)
);
}
return iconStyle;
}
function createLineString2(state, polylineGraphics, geometries, styles) {
const kmlDoc = state.kmlDoc;
const ellipsoid = state.ellipsoid;
const valueGetter = state.valueGetter;
if (!defined_default(polylineGraphics)) {
return;
}
const lineStringGeometry = kmlDoc.createElement("LineString");
const altitudeMode = kmlDoc.createElement("altitudeMode");
const clampToGround = valueGetter.get(polylineGraphics.clampToGround, false);
let altitudeModeText;
if (clampToGround) {
lineStringGeometry.appendChild(
createBasicElementWithText(kmlDoc, "tessellate", true)
);
altitudeModeText = kmlDoc.createTextNode("clampToGround");
} else {
altitudeModeText = kmlDoc.createTextNode("absolute");
}
altitudeMode.appendChild(altitudeModeText);
lineStringGeometry.appendChild(altitudeMode);
const positionsProperty = polylineGraphics.positions;
const cartesians = valueGetter.get(positionsProperty);
const coordinates = createBasicElementWithText(
kmlDoc,
"coordinates",
getCoordinates(cartesians, ellipsoid)
);
lineStringGeometry.appendChild(coordinates);
const zIndex = valueGetter.get(polylineGraphics.zIndex);
if (clampToGround && defined_default(zIndex)) {
lineStringGeometry.appendChild(
createBasicElementWithText(kmlDoc, "drawOrder", zIndex, gxNamespace)
);
}
geometries.push(lineStringGeometry);
const lineStyle = kmlDoc.createElement("LineStyle");
const width = valueGetter.get(polylineGraphics.width);
if (defined_default(width)) {
lineStyle.appendChild(createBasicElementWithText(kmlDoc, "width", width));
}
processMaterial(state, polylineGraphics.material, lineStyle);
styles.push(lineStyle);
}
function getRectangleBoundaries(state, rectangleGraphics, extrudedHeight) {
const kmlDoc = state.kmlDoc;
const valueGetter = state.valueGetter;
let height = valueGetter.get(rectangleGraphics.height, 0);
if (extrudedHeight > 0) {
height = extrudedHeight;
}
const coordinatesProperty = rectangleGraphics.coordinates;
const rectangle = valueGetter.get(coordinatesProperty);
const coordinateStrings = [];
const cornerFunction = [
Rectangle_default.northeast,
Rectangle_default.southeast,
Rectangle_default.southwest,
Rectangle_default.northwest
];
for (let i = 0; i < 4; ++i) {
cornerFunction[i](rectangle, scratchCartographic17);
coordinateStrings.push(
`${Math_default.toDegrees(
scratchCartographic17.longitude
)},${Math_default.toDegrees(scratchCartographic17.latitude)},${height}`
);
}
const coordinates = createBasicElementWithText(
kmlDoc,
"coordinates",
coordinateStrings.join(" ")
);
const outerBoundaryIs = kmlDoc.createElement("outerBoundaryIs");
const linearRing = kmlDoc.createElement("LinearRing");
linearRing.appendChild(coordinates);
outerBoundaryIs.appendChild(linearRing);
return [outerBoundaryIs];
}
function getLinearRing(state, positions, height, perPositionHeight) {
const kmlDoc = state.kmlDoc;
const ellipsoid = state.ellipsoid;
const coordinateStrings = [];
const positionCount = positions.length;
for (let i = 0; i < positionCount; ++i) {
Cartographic_default.fromCartesian(positions[i], ellipsoid, scratchCartographic17);
coordinateStrings.push(
`${Math_default.toDegrees(
scratchCartographic17.longitude
)},${Math_default.toDegrees(scratchCartographic17.latitude)},${perPositionHeight ? scratchCartographic17.height : height}`
);
}
const coordinates = createBasicElementWithText(
kmlDoc,
"coordinates",
coordinateStrings.join(" ")
);
const linearRing = kmlDoc.createElement("LinearRing");
linearRing.appendChild(coordinates);
return linearRing;
}
function getPolygonBoundaries(state, polygonGraphics, extrudedHeight) {
const kmlDoc = state.kmlDoc;
const valueGetter = state.valueGetter;
let height = valueGetter.get(polygonGraphics.height, 0);
const perPositionHeight = valueGetter.get(
polygonGraphics.perPositionHeight,
false
);
if (!perPositionHeight && extrudedHeight > 0) {
height = extrudedHeight;
}
const boundaries = [];
const hierarchyProperty = polygonGraphics.hierarchy;
const hierarchy = valueGetter.get(hierarchyProperty);
const positions = Array.isArray(hierarchy) ? hierarchy : hierarchy.positions;
const outerBoundaryIs = kmlDoc.createElement("outerBoundaryIs");
outerBoundaryIs.appendChild(
getLinearRing(state, positions, height, perPositionHeight)
);
boundaries.push(outerBoundaryIs);
const holes = hierarchy.holes;
if (defined_default(holes)) {
const holeCount = holes.length;
for (let i = 0; i < holeCount; ++i) {
const innerBoundaryIs = kmlDoc.createElement("innerBoundaryIs");
innerBoundaryIs.appendChild(
getLinearRing(state, holes[i].positions, height, perPositionHeight)
);
boundaries.push(innerBoundaryIs);
}
}
return boundaries;
}
function createPolygon2(state, geometry, geometries, styles, overlays) {
const kmlDoc = state.kmlDoc;
const valueGetter = state.valueGetter;
if (!defined_default(geometry)) {
return;
}
const isRectangle = geometry instanceof RectangleGraphics_default;
if (isRectangle && valueGetter.getMaterialType(geometry.material) === "Image") {
createGroundOverlay(state, geometry, overlays);
return;
}
const polygonGeometry = kmlDoc.createElement("Polygon");
const extrudedHeight = valueGetter.get(geometry.extrudedHeight, 0);
if (extrudedHeight > 0) {
polygonGeometry.appendChild(
createBasicElementWithText(kmlDoc, "extrude", true)
);
}
const boundaries = isRectangle ? getRectangleBoundaries(state, geometry, extrudedHeight) : getPolygonBoundaries(state, geometry, extrudedHeight);
const boundaryCount = boundaries.length;
for (let i = 0; i < boundaryCount; ++i) {
polygonGeometry.appendChild(boundaries[i]);
}
const altitudeMode = kmlDoc.createElement("altitudeMode");
altitudeMode.appendChild(getAltitudeMode(state, geometry.heightReference));
polygonGeometry.appendChild(altitudeMode);
geometries.push(polygonGeometry);
const polyStyle = kmlDoc.createElement("PolyStyle");
const fill = valueGetter.get(geometry.fill, false);
if (fill) {
polyStyle.appendChild(createBasicElementWithText(kmlDoc, "fill", fill));
}
processMaterial(state, geometry.material, polyStyle);
const outline = valueGetter.get(geometry.outline, false);
if (outline) {
polyStyle.appendChild(
createBasicElementWithText(kmlDoc, "outline", outline)
);
const lineStyle = kmlDoc.createElement("LineStyle");
const outlineWidth = valueGetter.get(geometry.outlineWidth, 1);
lineStyle.appendChild(
createBasicElementWithText(kmlDoc, "width", outlineWidth)
);
const outlineColor = valueGetter.getColor(
geometry.outlineColor,
Color_default.BLACK
);
lineStyle.appendChild(
createBasicElementWithText(kmlDoc, "color", outlineColor)
);
lineStyle.appendChild(
createBasicElementWithText(kmlDoc, "colorMode", "normal")
);
styles.push(lineStyle);
}
styles.push(polyStyle);
}
function createGroundOverlay(state, rectangleGraphics, overlays) {
const kmlDoc = state.kmlDoc;
const valueGetter = state.valueGetter;
const externalFileHandler = state.externalFileHandler;
const groundOverlay = kmlDoc.createElement("GroundOverlay");
const altitudeMode = kmlDoc.createElement("altitudeMode");
altitudeMode.appendChild(
getAltitudeMode(state, rectangleGraphics.heightReference)
);
groundOverlay.appendChild(altitudeMode);
const height = valueGetter.get(rectangleGraphics.height);
if (defined_default(height)) {
groundOverlay.appendChild(
createBasicElementWithText(kmlDoc, "altitude", height)
);
}
const rectangle = valueGetter.get(rectangleGraphics.coordinates);
const latLonBox = kmlDoc.createElement("LatLonBox");
latLonBox.appendChild(
createBasicElementWithText(
kmlDoc,
"north",
Math_default.toDegrees(rectangle.north)
)
);
latLonBox.appendChild(
createBasicElementWithText(
kmlDoc,
"south",
Math_default.toDegrees(rectangle.south)
)
);
latLonBox.appendChild(
createBasicElementWithText(
kmlDoc,
"east",
Math_default.toDegrees(rectangle.east)
)
);
latLonBox.appendChild(
createBasicElementWithText(
kmlDoc,
"west",
Math_default.toDegrees(rectangle.west)
)
);
groundOverlay.appendChild(latLonBox);
const material = valueGetter.get(rectangleGraphics.material);
const href = externalFileHandler.texture(material.image);
const icon = kmlDoc.createElement("Icon");
icon.appendChild(createBasicElementWithText(kmlDoc, "href", href));
groundOverlay.appendChild(icon);
const color = material.color;
if (defined_default(color)) {
groundOverlay.appendChild(
createBasicElementWithText(
kmlDoc,
"color",
colorToString(material.color)
)
);
}
overlays.push(groundOverlay);
}
function createModelGeometry(state, modelGraphics) {
const kmlDoc = state.kmlDoc;
const valueGetter = state.valueGetter;
const externalFileHandler = state.externalFileHandler;
const modelGeometry = kmlDoc.createElement("Model");
const scale = valueGetter.get(modelGraphics.scale);
if (defined_default(scale)) {
const scaleElement = kmlDoc.createElement("scale");
scaleElement.appendChild(createBasicElementWithText(kmlDoc, "x", scale));
scaleElement.appendChild(createBasicElementWithText(kmlDoc, "y", scale));
scaleElement.appendChild(createBasicElementWithText(kmlDoc, "z", scale));
modelGeometry.appendChild(scaleElement);
}
const link = kmlDoc.createElement("Link");
const uri = externalFileHandler.model(modelGraphics, state.time);
link.appendChild(createBasicElementWithText(kmlDoc, "href", uri));
modelGeometry.appendChild(link);
return modelGeometry;
}
function createModel(state, entity, modelGraphics, geometries, styles) {
const kmlDoc = state.kmlDoc;
const ellipsoid = state.ellipsoid;
const valueGetter = state.valueGetter;
if (!defined_default(modelGraphics)) {
return;
}
const entityPositionProperty = entity.position;
if (!entityPositionProperty.isConstant) {
createTracks(state, entity, modelGraphics, geometries, styles);
return;
}
const modelGeometry = createModelGeometry(state, modelGraphics);
const altitudeMode = kmlDoc.createElement("altitudeMode");
altitudeMode.appendChild(
getAltitudeMode(state, modelGraphics.heightReference)
);
modelGeometry.appendChild(altitudeMode);
valueGetter.get(entityPositionProperty, void 0, scratchCartesian312);
Cartographic_default.fromCartesian(scratchCartesian312, ellipsoid, scratchCartographic17);
const location2 = kmlDoc.createElement("Location");
location2.appendChild(
createBasicElementWithText(
kmlDoc,
"longitude",
Math_default.toDegrees(scratchCartographic17.longitude)
)
);
location2.appendChild(
createBasicElementWithText(
kmlDoc,
"latitude",
Math_default.toDegrees(scratchCartographic17.latitude)
)
);
location2.appendChild(
createBasicElementWithText(kmlDoc, "altitude", scratchCartographic17.height)
);
modelGeometry.appendChild(location2);
geometries.push(modelGeometry);
}
function processMaterial(state, materialProperty, style) {
const kmlDoc = state.kmlDoc;
const valueGetter = state.valueGetter;
if (!defined_default(materialProperty)) {
return;
}
const material = valueGetter.get(materialProperty);
if (!defined_default(material)) {
return;
}
let color;
const type = valueGetter.getMaterialType(materialProperty);
let outlineColor;
let outlineWidth;
switch (type) {
case "Image":
color = colorToString(Color_default.WHITE);
break;
case "Color":
case "Grid":
case "PolylineGlow":
case "PolylineArrow":
case "PolylineDash":
color = colorToString(material.color);
break;
case "PolylineOutline":
color = colorToString(material.color);
outlineColor = colorToString(material.outlineColor);
outlineWidth = material.outlineWidth;
style.appendChild(
createBasicElementWithText(
kmlDoc,
"outerColor",
outlineColor,
gxNamespace
)
);
style.appendChild(
createBasicElementWithText(
kmlDoc,
"outerWidth",
outlineWidth,
gxNamespace
)
);
break;
case "Stripe":
color = colorToString(material.oddColor);
break;
}
if (defined_default(color)) {
style.appendChild(createBasicElementWithText(kmlDoc, "color", color));
style.appendChild(
createBasicElementWithText(kmlDoc, "colorMode", "normal")
);
}
}
function getAltitudeMode(state, heightReferenceProperty) {
const kmlDoc = state.kmlDoc;
const valueGetter = state.valueGetter;
const heightReference = valueGetter.get(
heightReferenceProperty,
HeightReference_default.NONE
);
let altitudeModeText;
switch (heightReference) {
case HeightReference_default.NONE:
altitudeModeText = kmlDoc.createTextNode("absolute");
break;
case HeightReference_default.CLAMP_TO_GROUND:
altitudeModeText = kmlDoc.createTextNode("clampToGround");
break;
case HeightReference_default.RELATIVE_TO_GROUND:
altitudeModeText = kmlDoc.createTextNode("relativeToGround");
break;
}
return altitudeModeText;
}
function getCoordinates(coordinates, ellipsoid) {
if (!Array.isArray(coordinates)) {
coordinates = [coordinates];
}
const count = coordinates.length;
const coordinateStrings = [];
for (let i = 0; i < count; ++i) {
Cartographic_default.fromCartesian(coordinates[i], ellipsoid, scratchCartographic17);
coordinateStrings.push(
`${Math_default.toDegrees(
scratchCartographic17.longitude
)},${Math_default.toDegrees(scratchCartographic17.latitude)},${scratchCartographic17.height}`
);
}
return coordinateStrings.join(" ");
}
function createBasicElementWithText(kmlDoc, elementName, elementValue, namespace) {
elementValue = elementValue ?? "";
if (typeof elementValue === "boolean") {
elementValue = elementValue ? "1" : "0";
}
const element = defined_default(namespace) ? kmlDoc.createElementNS(namespace, elementName) : kmlDoc.createElement(elementName);
const text2 = elementValue === "string" && elementValue.indexOf("<") !== -1 ? kmlDoc.createCDATASection(elementValue) : kmlDoc.createTextNode(elementValue);
element.appendChild(text2);
return element;
}
function colorToString(color) {
let result = "";
const bytes = color.toBytes();
for (let i = 3; i >= 0; --i) {
result += bytes[i] < 16 ? `0${bytes[i].toString(16)}` : bytes[i].toString(16);
}
return result;
}
var exportKml_default = exportKml;
// packages/engine/Source/Widget/CesiumWidget.js
var import_InlineWorkers1178 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/computeFlyToLocationForRectangle.js
var import_InlineWorkers1003 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/sampleTerrainMostDetailed.js
var import_InlineWorkers1002 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/sampleTerrain.js
var import_InlineWorkers1001 = __toESM(require_InlineWorkers(), 1);
async function sampleTerrain(terrainProvider, level, positions, rejectOnTileFail) {
if (!defined_default(rejectOnTileFail)) {
rejectOnTileFail = false;
}
Check_default.typeOf.object("terrainProvider", terrainProvider);
Check_default.typeOf.number("level", level);
Check_default.typeOf.bool("rejectOnTileFail", rejectOnTileFail);
Check_default.defined("positions", positions);
return doSampling(terrainProvider, level, positions, rejectOnTileFail);
}
function attemptConsumeNextQueueItem(tileRequests, results, rejectOnTileFail) {
const tileRequest = tileRequests[0];
const requestPromise = tileRequest.terrainProvider.requestTileGeometry(
tileRequest.x,
tileRequest.y,
tileRequest.level
);
if (!requestPromise) {
return false;
}
let promise;
if (rejectOnTileFail) {
promise = requestPromise.then(createInterpolateFunction(tileRequest));
} else {
promise = requestPromise.then(createInterpolateFunction(tileRequest)).catch(createMarkFailedFunction(tileRequest));
}
tileRequests.shift();
results.push(promise);
return true;
}
function delay(ms) {
return new Promise(function(res) {
setTimeout(res, ms);
});
}
function drainTileRequestQueue(tileRequests, results, rejectOnTileFail) {
if (!tileRequests.length) {
return Promise.resolve();
}
const success = attemptConsumeNextQueueItem(
tileRequests,
results,
rejectOnTileFail
);
if (success) {
return drainTileRequestQueue(tileRequests, results, rejectOnTileFail);
}
return delay(100).then(() => {
return drainTileRequestQueue(tileRequests, results, rejectOnTileFail);
});
}
function doSampling(terrainProvider, level, positions, rejectOnTileFail) {
const tilingScheme2 = terrainProvider.tilingScheme;
let i;
const tileRequests = [];
const tileRequestSet = {};
for (i = 0; i < positions.length; ++i) {
const xy = tilingScheme2.positionToTileXY(positions[i], level);
if (!defined_default(xy)) {
continue;
}
const key = xy.toString();
if (!tileRequestSet.hasOwnProperty(key)) {
const value = {
x: xy.x,
y: xy.y,
level,
tilingScheme: tilingScheme2,
terrainProvider,
positions: []
};
tileRequestSet[key] = value;
tileRequests.push(value);
}
tileRequestSet[key].positions.push(positions[i]);
}
const tilePromises = [];
return drainTileRequestQueue(
tileRequests,
tilePromises,
rejectOnTileFail
).then(function() {
return Promise.all(tilePromises).then(function() {
return positions;
});
});
}
function interpolateAndAssignHeight(position, terrainData, rectangle) {
const height = terrainData.interpolateHeight(
rectangle,
position.longitude,
position.latitude
);
if (height === void 0) {
return false;
}
position.height = height;
return true;
}
function createInterpolateFunction(tileRequest) {
const tilePositions = tileRequest.positions;
const rectangle = tileRequest.tilingScheme.tileXYToRectangle(
tileRequest.x,
tileRequest.y,
tileRequest.level
);
return function(terrainData) {
let isMeshRequired = false;
for (let i = 0; i < tilePositions.length; ++i) {
const position = tilePositions[i];
const isHeightAssigned = interpolateAndAssignHeight(
position,
terrainData,
rectangle
);
if (!isHeightAssigned) {
isMeshRequired = true;
break;
}
}
if (!isMeshRequired) {
return Promise.resolve();
}
return terrainData.createMesh({
tilingScheme: tileRequest.tilingScheme,
x: tileRequest.x,
y: tileRequest.y,
level: tileRequest.level,
// don't throttle this mesh creation because we've asked to sample these points;
// so sample them! We don't care how many tiles that is!
throttle: false
}).then(function() {
for (let i = 0; i < tilePositions.length; ++i) {
const position = tilePositions[i];
interpolateAndAssignHeight(position, terrainData, rectangle);
}
});
};
}
function createMarkFailedFunction(tileRequest) {
const tilePositions = tileRequest.positions;
return function() {
for (let i = 0; i < tilePositions.length; ++i) {
const position = tilePositions[i];
position.height = void 0;
}
};
}
var sampleTerrain_default = sampleTerrain;
// packages/engine/Source/Core/sampleTerrainMostDetailed.js
var scratchCartesian210 = new Cartesian2_default();
async function sampleTerrainMostDetailed(terrainProvider, positions, rejectOnTileFail) {
if (!defined_default(rejectOnTileFail)) {
rejectOnTileFail = false;
}
if (!defined_default(terrainProvider)) {
throw new DeveloperError_default("terrainProvider is required.");
}
if (!defined_default(positions)) {
throw new DeveloperError_default("positions is required.");
}
const byLevel = [];
const maxLevels = [];
const availability = terrainProvider.availability;
if (!defined_default(availability)) {
throw new DeveloperError_default(
"sampleTerrainMostDetailed requires a terrain provider that has tile availability."
);
}
const promises = [];
for (let i = 0; i < positions.length; ++i) {
const position = positions[i];
const maxLevel = availability.computeMaximumLevelAtPosition(position);
maxLevels[i] = maxLevel;
if (maxLevel === 0) {
terrainProvider.tilingScheme.positionToTileXY(
position,
1,
scratchCartesian210
);
const promise = terrainProvider.loadTileDataAvailability(
scratchCartesian210.x,
scratchCartesian210.y,
1
);
if (defined_default(promise)) {
promises.push(promise);
}
}
let atLevel = byLevel[maxLevel];
if (!defined_default(atLevel)) {
byLevel[maxLevel] = atLevel = [];
}
atLevel.push(position);
}
await Promise.all(promises);
await Promise.all(
byLevel.map(function(positionsAtLevel, index) {
if (defined_default(positionsAtLevel)) {
return sampleTerrain_default(
terrainProvider,
index,
positionsAtLevel,
rejectOnTileFail
);
}
})
);
const changedPositions = [];
for (let i = 0; i < positions.length; ++i) {
const position = positions[i];
const maxLevel = availability.computeMaximumLevelAtPosition(position);
if (maxLevel !== maxLevels[i]) {
changedPositions.push(position);
}
}
if (changedPositions.length > 0) {
await sampleTerrainMostDetailed(
terrainProvider,
changedPositions,
rejectOnTileFail
);
}
return positions;
}
var sampleTerrainMostDetailed_default = sampleTerrainMostDetailed;
// packages/engine/Source/Scene/computeFlyToLocationForRectangle.js
async function computeFlyToLocationForRectangle(rectangle, scene) {
const terrainProvider = scene.terrainProvider;
const mapProjection = scene.mapProjection;
const ellipsoid = mapProjection.ellipsoid;
let positionWithoutTerrain;
const tmp2 = scene.camera.getRectangleCameraCoordinates(rectangle);
if (scene.mode === SceneMode_default.SCENE3D) {
positionWithoutTerrain = ellipsoid.cartesianToCartographic(tmp2);
} else {
positionWithoutTerrain = mapProjection.unproject(tmp2);
}
if (!defined_default(terrainProvider)) {
return positionWithoutTerrain;
}
const availability = terrainProvider.availability;
if (!defined_default(availability) || scene.mode === SceneMode_default.SCENE2D) {
return positionWithoutTerrain;
}
const cartographics = [
Rectangle_default.center(rectangle),
Rectangle_default.southeast(rectangle),
Rectangle_default.southwest(rectangle),
Rectangle_default.northeast(rectangle),
Rectangle_default.northwest(rectangle)
];
const positionsOnTerrain = await computeFlyToLocationForRectangle._sampleTerrainMostDetailed(
terrainProvider,
cartographics
);
let heightFound = false;
const maxHeight = positionsOnTerrain.reduce(function(currentMax, item) {
if (!defined_default(item.height)) {
return currentMax;
}
heightFound = true;
return Math.max(item.height, currentMax);
}, -Number.MAX_VALUE);
const finalPosition = positionWithoutTerrain;
if (heightFound) {
finalPosition.height += maxHeight;
}
return finalPosition;
}
computeFlyToLocationForRectangle._sampleTerrainMostDetailed = sampleTerrainMostDetailed_default;
var computeFlyToLocationForRectangle_default = computeFlyToLocationForRectangle;
// packages/engine/Source/Scene/Globe.js
var import_InlineWorkers1030 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/EllipsoidTerrainProvider.js
var import_InlineWorkers1011 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/HeightmapTerrainData.js
var import_InlineWorkers1010 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/HeightmapEncoding.js
var import_InlineWorkers1004 = __toESM(require_InlineWorkers(), 1);
var HeightmapEncoding = {
/**
* No encoding
*
* @type {number}
* @constant
*/
NONE: 0,
/**
* LERC encoding
*
* @type {number}
* @constant
*
* @see {@link https://github.com/Esri/lerc|The LERC specification}
*/
LERC: 1
};
var HeightmapEncoding_default = Object.freeze(HeightmapEncoding);
// packages/engine/Source/Core/HeightmapTessellator.js
var import_InlineWorkers1007 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/TerrainEncoding.js
var import_InlineWorkers1006 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/TerrainQuantization.js
var import_InlineWorkers1005 = __toESM(require_InlineWorkers(), 1);
var TerrainQuantization = {
/**
* The vertices are not compressed.
*
* @type {number}
* @constant
*/
NONE: 0,
/**
* The vertices are compressed to 12 bits.
*
* @type {number}
* @constant
*/
BITS12: 1
};
var TerrainQuantization_default = Object.freeze(TerrainQuantization);
// packages/engine/Source/Core/TerrainEncoding.js
var cartesian3Scratch7 = new Cartesian3_default();
var cartesian3DimScratch = new Cartesian3_default();
var cartesian2Scratch = new Cartesian2_default();
var matrix4Scratch = new Matrix4_default();
var matrix4Scratch2 = new Matrix4_default();
var SHIFT_LEFT_12 = Math.pow(2, 12);
function TerrainEncoding(center, axisAlignedBoundingBox, minimumHeight, maximumHeight, fromENU, hasVertexNormals, hasWebMercatorT, hasGeodeticSurfaceNormals, exaggeration, exaggerationRelativeHeight) {
let quantization = TerrainQuantization_default.NONE;
let toENU;
let matrix;
if (defined_default(axisAlignedBoundingBox) && defined_default(minimumHeight) && defined_default(maximumHeight) && defined_default(fromENU)) {
const minimum = axisAlignedBoundingBox.minimum;
const maximum = axisAlignedBoundingBox.maximum;
const dimensions = Cartesian3_default.subtract(
maximum,
minimum,
cartesian3DimScratch
);
const hDim = maximumHeight - minimumHeight;
const maxDim = Math.max(Cartesian3_default.maximumComponent(dimensions), hDim);
if (maxDim < SHIFT_LEFT_12 - 1) {
quantization = TerrainQuantization_default.BITS12;
} else {
quantization = TerrainQuantization_default.NONE;
}
toENU = Matrix4_default.inverseTransformation(fromENU, new Matrix4_default());
const translation3 = Cartesian3_default.negate(minimum, cartesian3Scratch7);
Matrix4_default.multiply(
Matrix4_default.fromTranslation(translation3, matrix4Scratch),
toENU,
toENU
);
const scale = cartesian3Scratch7;
scale.x = 1 / dimensions.x;
scale.y = 1 / dimensions.y;
scale.z = 1 / dimensions.z;
Matrix4_default.multiply(Matrix4_default.fromScale(scale, matrix4Scratch), toENU, toENU);
matrix = Matrix4_default.clone(fromENU);
Matrix4_default.setTranslation(matrix, Cartesian3_default.ZERO, matrix);
fromENU = Matrix4_default.clone(fromENU, new Matrix4_default());
const translationMatrix = Matrix4_default.fromTranslation(minimum, matrix4Scratch);
const scaleMatrix2 = Matrix4_default.fromScale(dimensions, matrix4Scratch2);
const st = Matrix4_default.multiply(translationMatrix, scaleMatrix2, matrix4Scratch);
Matrix4_default.multiply(fromENU, st, fromENU);
Matrix4_default.multiply(matrix, st, matrix);
}
this.quantization = quantization;
this.minimumHeight = minimumHeight;
this.maximumHeight = maximumHeight;
this.center = Cartesian3_default.clone(center);
this.toScaledENU = toENU;
this.fromScaledENU = fromENU;
this.matrix = matrix;
this.hasVertexNormals = hasVertexNormals;
this.hasWebMercatorT = hasWebMercatorT ?? false;
this.hasGeodeticSurfaceNormals = hasGeodeticSurfaceNormals ?? false;
this.exaggeration = exaggeration ?? 1;
this.exaggerationRelativeHeight = exaggerationRelativeHeight ?? 0;
this.stride = 0;
this._offsetGeodeticSurfaceNormal = 0;
this._offsetVertexNormal = 0;
this._calculateStrideAndOffsets();
}
TerrainEncoding.prototype.encode = function(vertexBuffer, bufferIndex, position, uv, height, normalToPack, webMercatorT, geodeticSurfaceNormal) {
const u3 = uv.x;
const v3 = uv.y;
if (this.quantization === TerrainQuantization_default.BITS12) {
position = Matrix4_default.multiplyByPoint(
this.toScaledENU,
position,
cartesian3Scratch7
);
position.x = Math_default.clamp(position.x, 0, 1);
position.y = Math_default.clamp(position.y, 0, 1);
position.z = Math_default.clamp(position.z, 0, 1);
const hDim = this.maximumHeight - this.minimumHeight;
const h = Math_default.clamp((height - this.minimumHeight) / hDim, 0, 1);
Cartesian2_default.fromElements(position.x, position.y, cartesian2Scratch);
const compressed0 = AttributeCompression_default.compressTextureCoordinates(cartesian2Scratch);
Cartesian2_default.fromElements(position.z, h, cartesian2Scratch);
const compressed1 = AttributeCompression_default.compressTextureCoordinates(cartesian2Scratch);
Cartesian2_default.fromElements(u3, v3, cartesian2Scratch);
const compressed2 = AttributeCompression_default.compressTextureCoordinates(cartesian2Scratch);
vertexBuffer[bufferIndex++] = compressed0;
vertexBuffer[bufferIndex++] = compressed1;
vertexBuffer[bufferIndex++] = compressed2;
if (this.hasWebMercatorT) {
Cartesian2_default.fromElements(webMercatorT, 0, cartesian2Scratch);
const compressed3 = AttributeCompression_default.compressTextureCoordinates(cartesian2Scratch);
vertexBuffer[bufferIndex++] = compressed3;
}
} else {
Cartesian3_default.subtract(position, this.center, cartesian3Scratch7);
vertexBuffer[bufferIndex++] = cartesian3Scratch7.x;
vertexBuffer[bufferIndex++] = cartesian3Scratch7.y;
vertexBuffer[bufferIndex++] = cartesian3Scratch7.z;
vertexBuffer[bufferIndex++] = height;
vertexBuffer[bufferIndex++] = u3;
vertexBuffer[bufferIndex++] = v3;
if (this.hasWebMercatorT) {
vertexBuffer[bufferIndex++] = webMercatorT;
}
}
if (this.hasVertexNormals) {
vertexBuffer[bufferIndex++] = AttributeCompression_default.octPackFloat(normalToPack);
}
if (this.hasGeodeticSurfaceNormals) {
vertexBuffer[bufferIndex++] = geodeticSurfaceNormal.x;
vertexBuffer[bufferIndex++] = geodeticSurfaceNormal.y;
vertexBuffer[bufferIndex++] = geodeticSurfaceNormal.z;
}
return bufferIndex;
};
var scratchPosition12 = new Cartesian3_default();
var scratchGeodeticSurfaceNormal = new Cartesian3_default();
TerrainEncoding.prototype.addGeodeticSurfaceNormals = function(oldBuffer, newBuffer, ellipsoid) {
if (this.hasGeodeticSurfaceNormals) {
return;
}
const oldStride = this.stride;
const vertexCount = oldBuffer.length / oldStride;
this.hasGeodeticSurfaceNormals = true;
this._calculateStrideAndOffsets();
const newStride = this.stride;
for (let index = 0; index < vertexCount; index++) {
for (let offset = 0; offset < oldStride; offset++) {
const oldIndex = index * oldStride + offset;
const newIndex = index * newStride + offset;
newBuffer[newIndex] = oldBuffer[oldIndex];
}
const position = this.decodePosition(newBuffer, index, scratchPosition12);
const geodeticSurfaceNormal = ellipsoid.geodeticSurfaceNormal(
position,
scratchGeodeticSurfaceNormal
);
const bufferIndex = index * newStride + this._offsetGeodeticSurfaceNormal;
newBuffer[bufferIndex] = geodeticSurfaceNormal.x;
newBuffer[bufferIndex + 1] = geodeticSurfaceNormal.y;
newBuffer[bufferIndex + 2] = geodeticSurfaceNormal.z;
}
};
TerrainEncoding.prototype.removeGeodeticSurfaceNormals = function(oldBuffer, newBuffer) {
if (!this.hasGeodeticSurfaceNormals) {
return;
}
const oldStride = this.stride;
const vertexCount = oldBuffer.length / oldStride;
this.hasGeodeticSurfaceNormals = false;
this._calculateStrideAndOffsets();
const newStride = this.stride;
for (let index = 0; index < vertexCount; index++) {
for (let offset = 0; offset < newStride; offset++) {
const oldIndex = index * oldStride + offset;
const newIndex = index * newStride + offset;
newBuffer[newIndex] = oldBuffer[oldIndex];
}
}
};
TerrainEncoding.prototype.decodePosition = function(buffer2, index, result) {
if (!defined_default(result)) {
result = new Cartesian3_default();
}
index *= this.stride;
if (this.quantization === TerrainQuantization_default.BITS12) {
const xy = AttributeCompression_default.decompressTextureCoordinates(
buffer2[index],
cartesian2Scratch
);
result.x = xy.x;
result.y = xy.y;
const zh = AttributeCompression_default.decompressTextureCoordinates(
buffer2[index + 1],
cartesian2Scratch
);
result.z = zh.x;
return Matrix4_default.multiplyByPoint(this.fromScaledENU, result, result);
}
result.x = buffer2[index];
result.y = buffer2[index + 1];
result.z = buffer2[index + 2];
return Cartesian3_default.add(result, this.center, result);
};
TerrainEncoding.prototype.getExaggeratedPosition = function(buffer2, index, result) {
result = this.decodePosition(buffer2, index, result);
const exaggeration = this.exaggeration;
const exaggerationRelativeHeight = this.exaggerationRelativeHeight;
const hasExaggeration = exaggeration !== 1;
if (hasExaggeration && this.hasGeodeticSurfaceNormals) {
const geodeticSurfaceNormal = this.decodeGeodeticSurfaceNormal(
buffer2,
index,
scratchGeodeticSurfaceNormal
);
const rawHeight = this.decodeHeight(buffer2, index);
const heightDifference = VerticalExaggeration_default.getHeight(
rawHeight,
exaggeration,
exaggerationRelativeHeight
) - rawHeight;
result.x += geodeticSurfaceNormal.x * heightDifference;
result.y += geodeticSurfaceNormal.y * heightDifference;
result.z += geodeticSurfaceNormal.z * heightDifference;
}
return result;
};
TerrainEncoding.prototype.decodeTextureCoordinates = function(buffer2, index, result) {
if (!defined_default(result)) {
result = new Cartesian2_default();
}
index *= this.stride;
if (this.quantization === TerrainQuantization_default.BITS12) {
return AttributeCompression_default.decompressTextureCoordinates(
buffer2[index + 2],
result
);
}
return Cartesian2_default.fromElements(buffer2[index + 4], buffer2[index + 5], result);
};
TerrainEncoding.prototype.decodeHeight = function(buffer2, index) {
index *= this.stride;
if (this.quantization === TerrainQuantization_default.BITS12) {
const zh = AttributeCompression_default.decompressTextureCoordinates(
buffer2[index + 1],
cartesian2Scratch
);
return zh.y * (this.maximumHeight - this.minimumHeight) + this.minimumHeight;
}
return buffer2[index + 3];
};
TerrainEncoding.prototype.decodeWebMercatorT = function(buffer2, index) {
index *= this.stride;
if (this.quantization === TerrainQuantization_default.BITS12) {
return AttributeCompression_default.decompressTextureCoordinates(
buffer2[index + 3],
cartesian2Scratch
).x;
}
return buffer2[index + 6];
};
TerrainEncoding.prototype.getOctEncodedNormal = function(buffer2, index, result) {
index = index * this.stride + this._offsetVertexNormal;
const temp = buffer2[index] / 256;
const x = Math.floor(temp);
const y = (temp - x) * 256;
return Cartesian2_default.fromElements(x, y, result);
};
TerrainEncoding.prototype.decodeGeodeticSurfaceNormal = function(buffer2, index, result) {
index = index * this.stride + this._offsetGeodeticSurfaceNormal;
result.x = buffer2[index];
result.y = buffer2[index + 1];
result.z = buffer2[index + 2];
return result;
};
TerrainEncoding.prototype._calculateStrideAndOffsets = function() {
let vertexStride = 0;
switch (this.quantization) {
case TerrainQuantization_default.BITS12:
vertexStride += 3;
break;
default:
vertexStride += 6;
}
if (this.hasWebMercatorT) {
vertexStride += 1;
}
if (this.hasVertexNormals) {
this._offsetVertexNormal = vertexStride;
vertexStride += 1;
}
if (this.hasGeodeticSurfaceNormals) {
this._offsetGeodeticSurfaceNormal = vertexStride;
vertexStride += 3;
}
this.stride = vertexStride;
};
var attributesIndicesNone = {
position3DAndHeight: 0,
textureCoordAndEncodedNormals: 1,
geodeticSurfaceNormal: 2
};
var attributesIndicesBits12 = {
compressed0: 0,
compressed1: 1,
geodeticSurfaceNormal: 2
};
TerrainEncoding.prototype.getAttributes = function(buffer2) {
const datatype = ComponentDatatype_default.FLOAT;
const sizeInBytes = ComponentDatatype_default.getSizeInBytes(datatype);
const strideInBytes = this.stride * sizeInBytes;
let offsetInBytes = 0;
const attributes = [];
function addAttribute2(index, componentsPerAttribute) {
attributes.push({
index,
vertexBuffer: buffer2,
componentDatatype: datatype,
componentsPerAttribute,
offsetInBytes,
strideInBytes
});
offsetInBytes += componentsPerAttribute * sizeInBytes;
}
if (this.quantization === TerrainQuantization_default.NONE) {
addAttribute2(attributesIndicesNone.position3DAndHeight, 4);
let componentsTexCoordAndNormals = 2;
componentsTexCoordAndNormals += this.hasWebMercatorT ? 1 : 0;
componentsTexCoordAndNormals += this.hasVertexNormals ? 1 : 0;
addAttribute2(
attributesIndicesNone.textureCoordAndEncodedNormals,
componentsTexCoordAndNormals
);
if (this.hasGeodeticSurfaceNormals) {
addAttribute2(attributesIndicesNone.geodeticSurfaceNormal, 3);
}
} else {
const usingAttribute0Component4 = this.hasWebMercatorT || this.hasVertexNormals;
const usingAttribute1Component1 = this.hasWebMercatorT && this.hasVertexNormals;
addAttribute2(
attributesIndicesBits12.compressed0,
usingAttribute0Component4 ? 4 : 3
);
if (usingAttribute1Component1) {
addAttribute2(attributesIndicesBits12.compressed1, 1);
}
if (this.hasGeodeticSurfaceNormals) {
addAttribute2(attributesIndicesBits12.geodeticSurfaceNormal, 3);
}
}
return attributes;
};
TerrainEncoding.prototype.getAttributeLocations = function() {
if (this.quantization === TerrainQuantization_default.NONE) {
return attributesIndicesNone;
}
return attributesIndicesBits12;
};
TerrainEncoding.clone = function(encoding, result) {
if (!defined_default(encoding)) {
return void 0;
}
if (!defined_default(result)) {
result = new TerrainEncoding();
}
result.quantization = encoding.quantization;
result.minimumHeight = encoding.minimumHeight;
result.maximumHeight = encoding.maximumHeight;
result.center = Cartesian3_default.clone(encoding.center);
result.toScaledENU = Matrix4_default.clone(encoding.toScaledENU);
result.fromScaledENU = Matrix4_default.clone(encoding.fromScaledENU);
result.matrix = Matrix4_default.clone(encoding.matrix);
result.hasVertexNormals = encoding.hasVertexNormals;
result.hasWebMercatorT = encoding.hasWebMercatorT;
result.hasGeodeticSurfaceNormals = encoding.hasGeodeticSurfaceNormals;
result.exaggeration = encoding.exaggeration;
result.exaggerationRelativeHeight = encoding.exaggerationRelativeHeight;
result._calculateStrideAndOffsets();
return result;
};
var TerrainEncoding_default = TerrainEncoding;
// packages/engine/Source/Core/HeightmapTessellator.js
var HeightmapTessellator = {};
HeightmapTessellator.DEFAULT_STRUCTURE = Object.freeze({
heightScale: 1,
heightOffset: 0,
elementsPerHeight: 1,
stride: 1,
elementMultiplier: 256,
isBigEndian: false
});
var cartesian3Scratch8 = new Cartesian3_default();
var matrix4Scratch3 = new Matrix4_default();
var minimumScratch = new Cartesian3_default();
var maximumScratch = new Cartesian3_default();
HeightmapTessellator.computeVertices = function(options) {
if (!defined_default(options) || !defined_default(options.heightmap)) {
throw new DeveloperError_default("options.heightmap is required.");
}
if (!defined_default(options.width) || !defined_default(options.height)) {
throw new DeveloperError_default("options.width and options.height are required.");
}
if (!defined_default(options.nativeRectangle)) {
throw new DeveloperError_default("options.nativeRectangle is required.");
}
if (!defined_default(options.skirtHeight)) {
throw new DeveloperError_default("options.skirtHeight is required.");
}
const cos4 = Math.cos;
const sin4 = Math.sin;
const sqrt2 = Math.sqrt;
const atan = Math.atan;
const exp = Math.exp;
const piOverTwo = Math_default.PI_OVER_TWO;
const toRadians = Math_default.toRadians;
const heightmap = options.heightmap;
const width = options.width;
const height = options.height;
const skirtHeight = options.skirtHeight;
const hasSkirts = skirtHeight > 0;
const isGeographic = options.isGeographic ?? true;
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
const oneOverGlobeSemimajorAxis = 1 / ellipsoid.maximumRadius;
const nativeRectangle = Rectangle_default.clone(options.nativeRectangle);
const rectangle = Rectangle_default.clone(options.rectangle);
let geographicWest;
let geographicSouth;
let geographicEast;
let geographicNorth;
if (!defined_default(rectangle)) {
if (isGeographic) {
geographicWest = toRadians(nativeRectangle.west);
geographicSouth = toRadians(nativeRectangle.south);
geographicEast = toRadians(nativeRectangle.east);
geographicNorth = toRadians(nativeRectangle.north);
} else {
geographicWest = nativeRectangle.west * oneOverGlobeSemimajorAxis;
geographicSouth = piOverTwo - 2 * atan(exp(-nativeRectangle.south * oneOverGlobeSemimajorAxis));
geographicEast = nativeRectangle.east * oneOverGlobeSemimajorAxis;
geographicNorth = piOverTwo - 2 * atan(exp(-nativeRectangle.north * oneOverGlobeSemimajorAxis));
}
} else {
geographicWest = rectangle.west;
geographicSouth = rectangle.south;
geographicEast = rectangle.east;
geographicNorth = rectangle.north;
}
let relativeToCenter = options.relativeToCenter;
const hasRelativeToCenter = defined_default(relativeToCenter);
relativeToCenter = hasRelativeToCenter ? relativeToCenter : Cartesian3_default.ZERO;
const includeWebMercatorT = options.includeWebMercatorT ?? false;
const exaggeration = options.exaggeration ?? 1;
const exaggerationRelativeHeight = options.exaggerationRelativeHeight ?? 0;
const hasExaggeration = exaggeration !== 1;
const includeGeodeticSurfaceNormals = hasExaggeration;
const structure = options.structure ?? HeightmapTessellator.DEFAULT_STRUCTURE;
const heightScale = structure.heightScale ?? HeightmapTessellator.DEFAULT_STRUCTURE.heightScale;
const heightOffset = structure.heightOffset ?? HeightmapTessellator.DEFAULT_STRUCTURE.heightOffset;
const elementsPerHeight = structure.elementsPerHeight ?? HeightmapTessellator.DEFAULT_STRUCTURE.elementsPerHeight;
const stride = structure.stride ?? HeightmapTessellator.DEFAULT_STRUCTURE.stride;
const elementMultiplier = structure.elementMultiplier ?? HeightmapTessellator.DEFAULT_STRUCTURE.elementMultiplier;
const isBigEndian = structure.isBigEndian ?? HeightmapTessellator.DEFAULT_STRUCTURE.isBigEndian;
let rectangleWidth = Rectangle_default.computeWidth(nativeRectangle);
let rectangleHeight = Rectangle_default.computeHeight(nativeRectangle);
const granularityX = rectangleWidth / (width - 1);
const granularityY = rectangleHeight / (height - 1);
if (!isGeographic) {
rectangleWidth *= oneOverGlobeSemimajorAxis;
rectangleHeight *= oneOverGlobeSemimajorAxis;
}
const radiiSquared = ellipsoid.radiiSquared;
const radiiSquaredX = radiiSquared.x;
const radiiSquaredY = radiiSquared.y;
const radiiSquaredZ = radiiSquared.z;
let minimumHeight = 65536;
let maximumHeight = -65536;
const fromENU = Transforms_default.eastNorthUpToFixedFrame(
relativeToCenter,
ellipsoid
);
const toENU = Matrix4_default.inverseTransformation(fromENU, matrix4Scratch3);
let southMercatorY;
let oneOverMercatorHeight;
if (includeWebMercatorT) {
southMercatorY = WebMercatorProjection_default.geodeticLatitudeToMercatorAngle(geographicSouth);
oneOverMercatorHeight = 1 / (WebMercatorProjection_default.geodeticLatitudeToMercatorAngle(geographicNorth) - southMercatorY);
}
const minimum = minimumScratch;
minimum.x = Number.POSITIVE_INFINITY;
minimum.y = Number.POSITIVE_INFINITY;
minimum.z = Number.POSITIVE_INFINITY;
const maximum = maximumScratch;
maximum.x = Number.NEGATIVE_INFINITY;
maximum.y = Number.NEGATIVE_INFINITY;
maximum.z = Number.NEGATIVE_INFINITY;
let hMin = Number.POSITIVE_INFINITY;
const gridVertexCount = width * height;
const edgeVertexCount = skirtHeight > 0 ? width * 2 + height * 2 : 0;
const vertexCount = gridVertexCount + edgeVertexCount;
const positions = new Array(vertexCount);
const heights = new Array(vertexCount);
const uvs = new Array(vertexCount);
const webMercatorTs = includeWebMercatorT ? new Array(vertexCount) : [];
const geodeticSurfaceNormals = includeGeodeticSurfaceNormals ? new Array(vertexCount) : [];
let startRow = 0;
let endRow = height;
let startCol = 0;
let endCol = width;
if (hasSkirts) {
--startRow;
++endRow;
--startCol;
++endCol;
}
const skirtOffsetPercentage = 1e-5;
for (let rowIndex = startRow; rowIndex < endRow; ++rowIndex) {
let row = rowIndex;
if (row < 0) {
row = 0;
}
if (row >= height) {
row = height - 1;
}
let latitude = nativeRectangle.north - granularityY * row;
if (!isGeographic) {
latitude = piOverTwo - 2 * atan(exp(-latitude * oneOverGlobeSemimajorAxis));
} else {
latitude = toRadians(latitude);
}
let v3 = (latitude - geographicSouth) / (geographicNorth - geographicSouth);
v3 = Math_default.clamp(v3, 0, 1);
const isNorthEdge = rowIndex === startRow;
const isSouthEdge = rowIndex === endRow - 1;
if (skirtHeight > 0) {
if (isNorthEdge) {
latitude += skirtOffsetPercentage * rectangleHeight;
} else if (isSouthEdge) {
latitude -= skirtOffsetPercentage * rectangleHeight;
}
}
const cosLatitude = cos4(latitude);
const nZ = sin4(latitude);
const kZ = radiiSquaredZ * nZ;
let webMercatorT;
if (includeWebMercatorT) {
webMercatorT = (WebMercatorProjection_default.geodeticLatitudeToMercatorAngle(latitude) - southMercatorY) * oneOverMercatorHeight;
}
for (let colIndex = startCol; colIndex < endCol; ++colIndex) {
let col = colIndex;
if (col < 0) {
col = 0;
}
if (col >= width) {
col = width - 1;
}
const terrainOffset = row * (width * stride) + col * stride;
let heightSample;
if (elementsPerHeight === 1) {
heightSample = heightmap[terrainOffset];
} else {
heightSample = 0;
let elementOffset;
if (isBigEndian) {
for (elementOffset = 0; elementOffset < elementsPerHeight; ++elementOffset) {
heightSample = heightSample * elementMultiplier + heightmap[terrainOffset + elementOffset];
}
} else {
for (elementOffset = elementsPerHeight - 1; elementOffset >= 0; --elementOffset) {
heightSample = heightSample * elementMultiplier + heightmap[terrainOffset + elementOffset];
}
}
}
heightSample = heightSample * heightScale + heightOffset;
maximumHeight = Math.max(maximumHeight, heightSample);
minimumHeight = Math.min(minimumHeight, heightSample);
let longitude = nativeRectangle.west + granularityX * col;
if (!isGeographic) {
longitude = longitude * oneOverGlobeSemimajorAxis;
} else {
longitude = toRadians(longitude);
}
let u3 = (longitude - geographicWest) / (geographicEast - geographicWest);
u3 = Math_default.clamp(u3, 0, 1);
let index = row * width + col;
if (skirtHeight > 0) {
const isWestEdge = colIndex === startCol;
const isEastEdge = colIndex === endCol - 1;
const isEdge2 = isNorthEdge || isSouthEdge || isWestEdge || isEastEdge;
const isCorner = (isNorthEdge || isSouthEdge) && (isWestEdge || isEastEdge);
if (isCorner) {
continue;
} else if (isEdge2) {
heightSample -= skirtHeight;
if (isWestEdge) {
index = gridVertexCount + (height - row - 1);
longitude -= skirtOffsetPercentage * rectangleWidth;
} else if (isSouthEdge) {
index = gridVertexCount + height + (width - col - 1);
} else if (isEastEdge) {
index = gridVertexCount + height + width + row;
longitude += skirtOffsetPercentage * rectangleWidth;
} else if (isNorthEdge) {
index = gridVertexCount + height + width + height + col;
}
}
}
const nX = cosLatitude * cos4(longitude);
const nY = cosLatitude * sin4(longitude);
const kX = radiiSquaredX * nX;
const kY = radiiSquaredY * nY;
const gamma = sqrt2(kX * nX + kY * nY + kZ * nZ);
const oneOverGamma = 1 / gamma;
const rSurfaceX = kX * oneOverGamma;
const rSurfaceY = kY * oneOverGamma;
const rSurfaceZ = kZ * oneOverGamma;
const position = new Cartesian3_default();
position.x = rSurfaceX + nX * heightSample;
position.y = rSurfaceY + nY * heightSample;
position.z = rSurfaceZ + nZ * heightSample;
Matrix4_default.multiplyByPoint(toENU, position, cartesian3Scratch8);
Cartesian3_default.minimumByComponent(cartesian3Scratch8, minimum, minimum);
Cartesian3_default.maximumByComponent(cartesian3Scratch8, maximum, maximum);
hMin = Math.min(hMin, heightSample);
positions[index] = position;
uvs[index] = new Cartesian2_default(u3, v3);
heights[index] = heightSample;
if (includeWebMercatorT) {
webMercatorTs[index] = webMercatorT;
}
if (includeGeodeticSurfaceNormals) {
geodeticSurfaceNormals[index] = ellipsoid.geodeticSurfaceNormal(position);
}
}
}
const boundingSphere3D = BoundingSphere_default.fromPoints(positions);
let orientedBoundingBox;
if (defined_default(rectangle)) {
orientedBoundingBox = OrientedBoundingBox_default.fromRectangle(
rectangle,
minimumHeight,
maximumHeight,
ellipsoid
);
}
let occludeePointInScaledSpace;
if (hasRelativeToCenter) {
const occluder = new EllipsoidalOccluder_default(ellipsoid);
occludeePointInScaledSpace = occluder.computeHorizonCullingPointPossiblyUnderEllipsoid(
relativeToCenter,
positions,
minimumHeight
);
}
const aaBox = new AxisAlignedBoundingBox_default(minimum, maximum, relativeToCenter);
const encoding = new TerrainEncoding_default(
relativeToCenter,
aaBox,
hMin,
maximumHeight,
fromENU,
false,
includeWebMercatorT,
includeGeodeticSurfaceNormals,
exaggeration,
exaggerationRelativeHeight
);
const vertices = new Float32Array(vertexCount * encoding.stride);
let bufferIndex = 0;
for (let j = 0; j < vertexCount; ++j) {
bufferIndex = encoding.encode(
vertices,
bufferIndex,
positions[j],
uvs[j],
heights[j],
void 0,
webMercatorTs[j],
geodeticSurfaceNormals[j]
);
}
return {
vertices,
maximumHeight,
minimumHeight,
encoding,
boundingSphere3D,
orientedBoundingBox,
occludeePointInScaledSpace
};
};
var HeightmapTessellator_default = HeightmapTessellator;
// packages/engine/Source/Core/TerrainData.js
var import_InlineWorkers1008 = __toESM(require_InlineWorkers(), 1);
function TerrainData() {
DeveloperError_default.throwInstantiationError();
}
Object.defineProperties(TerrainData.prototype, {
/**
* An array of credits for this tile.
* @memberof TerrainData.prototype
* @type {Credit[]}
*/
credits: {
get: DeveloperError_default.throwInstantiationError
},
/**
* The water mask included in this terrain data, if any. A water mask is a rectangular
* Uint8Array or image where a value of 255 indicates water and a value of 0 indicates land.
* Values in between 0 and 255 are allowed as well to smoothly blend between land and water.
* @memberof TerrainData.prototype
* @type {Uint8Array|HTMLImageElement|HTMLCanvasElement|undefined}
*/
waterMask: {
get: DeveloperError_default.throwInstantiationError
}
});
TerrainData.prototype.interpolateHeight = DeveloperError_default.throwInstantiationError;
TerrainData.prototype.isChildAvailable = DeveloperError_default.throwInstantiationError;
TerrainData.prototype.createMesh = DeveloperError_default.throwInstantiationError;
TerrainData.prototype.upsample = DeveloperError_default.throwInstantiationError;
TerrainData.prototype.wasCreatedByUpsampling = DeveloperError_default.throwInstantiationError;
TerrainData.maximumAsynchronousTasks = 5;
var TerrainData_default = TerrainData;
// packages/engine/Source/Core/TerrainMesh.js
var import_InlineWorkers1009 = __toESM(require_InlineWorkers(), 1);
function TerrainMesh(center, vertices, indices, indexCountWithoutSkirts, vertexCountWithoutSkirts, minimumHeight, maximumHeight, boundingSphere3D, occludeePointInScaledSpace, vertexStride, orientedBoundingBox, encoding, westIndicesSouthToNorth, southIndicesEastToWest, eastIndicesNorthToSouth, northIndicesWestToEast) {
this.center = center;
this.vertices = vertices;
this.stride = vertexStride ?? 6;
this.indices = indices;
this.indexCountWithoutSkirts = indexCountWithoutSkirts;
this.vertexCountWithoutSkirts = vertexCountWithoutSkirts;
this.minimumHeight = minimumHeight;
this.maximumHeight = maximumHeight;
this.boundingSphere3D = boundingSphere3D;
this.occludeePointInScaledSpace = occludeePointInScaledSpace;
this.orientedBoundingBox = orientedBoundingBox;
this.encoding = encoding;
this.westIndicesSouthToNorth = westIndicesSouthToNorth;
this.southIndicesEastToWest = southIndicesEastToWest;
this.eastIndicesNorthToSouth = eastIndicesNorthToSouth;
this.northIndicesWestToEast = northIndicesWestToEast;
}
var TerrainMesh_default = TerrainMesh;
// packages/engine/Source/Core/HeightmapTerrainData.js
function HeightmapTerrainData(options) {
if (!defined_default(options) || !defined_default(options.buffer)) {
throw new DeveloperError_default("options.buffer is required.");
}
if (!defined_default(options.width)) {
throw new DeveloperError_default("options.width is required.");
}
if (!defined_default(options.height)) {
throw new DeveloperError_default("options.height is required.");
}
this._buffer = options.buffer;
this._width = options.width;
this._height = options.height;
this._childTileMask = options.childTileMask ?? 15;
this._encoding = options.encoding ?? HeightmapEncoding_default.NONE;
const defaultStructure = HeightmapTessellator_default.DEFAULT_STRUCTURE;
let structure = options.structure;
if (!defined_default(structure)) {
structure = defaultStructure;
} else if (structure !== defaultStructure) {
structure.heightScale = structure.heightScale ?? defaultStructure.heightScale;
structure.heightOffset = structure.heightOffset ?? defaultStructure.heightOffset;
structure.elementsPerHeight = structure.elementsPerHeight ?? defaultStructure.elementsPerHeight;
structure.stride = structure.stride ?? defaultStructure.stride;
structure.elementMultiplier = structure.elementMultiplier ?? defaultStructure.elementMultiplier;
structure.isBigEndian = structure.isBigEndian ?? defaultStructure.isBigEndian;
}
this._structure = structure;
this._createdByUpsampling = options.createdByUpsampling ?? false;
this._waterMask = options.waterMask;
this._skirtHeight = void 0;
this._bufferType = this._encoding === HeightmapEncoding_default.LERC ? Float32Array : this._buffer.constructor;
this._mesh = void 0;
}
Object.defineProperties(HeightmapTerrainData.prototype, {
/**
* An array of credits for this tile.
* @memberof HeightmapTerrainData.prototype
* @type {Credit[]}
*/
credits: {
get: function() {
return void 0;
}
},
/**
* The water mask included in this terrain data, if any. A water mask is a square
* Uint8Array or image where a value of 255 indicates water and a value of 0 indicates land.
* Values in between 0 and 255 are allowed as well to smoothly blend between land and water.
* @memberof HeightmapTerrainData.prototype
* @type {Uint8Array|HTMLImageElement|HTMLCanvasElement|undefined}
*/
waterMask: {
get: function() {
return this._waterMask;
}
},
childTileMask: {
get: function() {
return this._childTileMask;
}
}
});
var createMeshTaskName = "createVerticesFromHeightmap";
var createMeshTaskProcessorNoThrottle = new TaskProcessor_default(createMeshTaskName);
var createMeshTaskProcessorThrottle = new TaskProcessor_default(
createMeshTaskName,
TerrainData_default.maximumAsynchronousTasks
);
HeightmapTerrainData.prototype.createMesh = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("options.tilingScheme", options.tilingScheme);
Check_default.typeOf.number("options.x", options.x);
Check_default.typeOf.number("options.y", options.y);
Check_default.typeOf.number("options.level", options.level);
const tilingScheme2 = options.tilingScheme;
const x = options.x;
const y = options.y;
const level = options.level;
const exaggeration = options.exaggeration ?? 1;
const exaggerationRelativeHeight = options.exaggerationRelativeHeight ?? 0;
const throttle = options.throttle ?? true;
const ellipsoid = tilingScheme2.ellipsoid;
const nativeRectangle = tilingScheme2.tileXYToNativeRectangle(x, y, level);
const rectangle = tilingScheme2.tileXYToRectangle(x, y, level);
const center = ellipsoid.cartographicToCartesian(Rectangle_default.center(rectangle));
const structure = this._structure;
const levelZeroMaxError = TerrainProvider_default.getEstimatedLevelZeroGeometricErrorForAHeightmap(
ellipsoid,
this._width,
tilingScheme2.getNumberOfXTilesAtLevel(0)
);
const thisLevelMaxError = levelZeroMaxError / (1 << level);
this._skirtHeight = Math.min(thisLevelMaxError * 4, 1e3);
const createMeshTaskProcessor = throttle ? createMeshTaskProcessorThrottle : createMeshTaskProcessorNoThrottle;
const verticesPromise = createMeshTaskProcessor.scheduleTask({
heightmap: this._buffer,
structure,
includeWebMercatorT: true,
width: this._width,
height: this._height,
nativeRectangle,
rectangle,
relativeToCenter: center,
ellipsoid,
skirtHeight: this._skirtHeight,
isGeographic: tilingScheme2.projection instanceof GeographicProjection_default,
exaggeration,
exaggerationRelativeHeight,
encoding: this._encoding
});
if (!defined_default(verticesPromise)) {
return void 0;
}
const that = this;
return Promise.resolve(verticesPromise).then(function(result) {
let indicesAndEdges;
if (that._skirtHeight > 0) {
indicesAndEdges = TerrainProvider_default.getRegularGridAndSkirtIndicesAndEdgeIndices(
result.gridWidth,
result.gridHeight
);
} else {
indicesAndEdges = TerrainProvider_default.getRegularGridIndicesAndEdgeIndices(
result.gridWidth,
result.gridHeight
);
}
const vertexCountWithoutSkirts = result.gridWidth * result.gridHeight;
that._mesh = new TerrainMesh_default(
center,
new Float32Array(result.vertices),
indicesAndEdges.indices,
indicesAndEdges.indexCountWithoutSkirts,
vertexCountWithoutSkirts,
result.minimumHeight,
result.maximumHeight,
BoundingSphere_default.clone(result.boundingSphere3D),
Cartesian3_default.clone(result.occludeePointInScaledSpace),
result.numberOfAttributes,
OrientedBoundingBox_default.clone(result.orientedBoundingBox),
TerrainEncoding_default.clone(result.encoding),
indicesAndEdges.westIndicesSouthToNorth,
indicesAndEdges.southIndicesEastToWest,
indicesAndEdges.eastIndicesNorthToSouth,
indicesAndEdges.northIndicesWestToEast
);
that._buffer = void 0;
return that._mesh;
});
};
HeightmapTerrainData.prototype._createMeshSync = function(options) {
Check_default.typeOf.object("options.tilingScheme", options.tilingScheme);
Check_default.typeOf.number("options.x", options.x);
Check_default.typeOf.number("options.y", options.y);
Check_default.typeOf.number("options.level", options.level);
const tilingScheme2 = options.tilingScheme;
const x = options.x;
const y = options.y;
const level = options.level;
const exaggeration = options.exaggeration ?? 1;
const exaggerationRelativeHeight = options.exaggerationRelativeHeight ?? 0;
const ellipsoid = tilingScheme2.ellipsoid;
const nativeRectangle = tilingScheme2.tileXYToNativeRectangle(x, y, level);
const rectangle = tilingScheme2.tileXYToRectangle(x, y, level);
const center = ellipsoid.cartographicToCartesian(Rectangle_default.center(rectangle));
const structure = this._structure;
const levelZeroMaxError = TerrainProvider_default.getEstimatedLevelZeroGeometricErrorForAHeightmap(
ellipsoid,
this._width,
tilingScheme2.getNumberOfXTilesAtLevel(0)
);
const thisLevelMaxError = levelZeroMaxError / (1 << level);
this._skirtHeight = Math.min(thisLevelMaxError * 4, 1e3);
const result = HeightmapTessellator_default.computeVertices({
heightmap: this._buffer,
structure,
includeWebMercatorT: true,
width: this._width,
height: this._height,
nativeRectangle,
rectangle,
relativeToCenter: center,
ellipsoid,
skirtHeight: this._skirtHeight,
isGeographic: tilingScheme2.projection instanceof GeographicProjection_default,
exaggeration,
exaggerationRelativeHeight
});
this._buffer = void 0;
let indicesAndEdges;
if (this._skirtHeight > 0) {
indicesAndEdges = TerrainProvider_default.getRegularGridAndSkirtIndicesAndEdgeIndices(
this._width,
this._height
);
} else {
indicesAndEdges = TerrainProvider_default.getRegularGridIndicesAndEdgeIndices(
this._width,
this._height
);
}
const vertexCountWithoutSkirts = result.gridWidth * result.gridHeight;
this._mesh = new TerrainMesh_default(
center,
result.vertices,
indicesAndEdges.indices,
indicesAndEdges.indexCountWithoutSkirts,
vertexCountWithoutSkirts,
result.minimumHeight,
result.maximumHeight,
result.boundingSphere3D,
result.occludeePointInScaledSpace,
result.encoding.stride,
result.orientedBoundingBox,
result.encoding,
indicesAndEdges.westIndicesSouthToNorth,
indicesAndEdges.southIndicesEastToWest,
indicesAndEdges.eastIndicesNorthToSouth,
indicesAndEdges.northIndicesWestToEast
);
return this._mesh;
};
HeightmapTerrainData.prototype.interpolateHeight = function(rectangle, longitude, latitude) {
const width = this._width;
const height = this._height;
const structure = this._structure;
const stride = structure.stride;
const elementsPerHeight = structure.elementsPerHeight;
const elementMultiplier = structure.elementMultiplier;
const isBigEndian = structure.isBigEndian;
const heightOffset = structure.heightOffset;
const heightScale = structure.heightScale;
const isMeshCreated = defined_default(this._mesh);
const isLERCEncoding = this._encoding === HeightmapEncoding_default.LERC;
const isInterpolationImpossible = !isMeshCreated && isLERCEncoding;
if (isInterpolationImpossible) {
return void 0;
}
let heightSample;
if (isMeshCreated) {
const buffer2 = this._mesh.vertices;
const encoding = this._mesh.encoding;
heightSample = interpolateMeshHeight(
buffer2,
encoding,
heightOffset,
heightScale,
rectangle,
width,
height,
longitude,
latitude
);
} else {
heightSample = interpolateHeight(
this._buffer,
elementsPerHeight,
elementMultiplier,
stride,
isBigEndian,
rectangle,
width,
height,
longitude,
latitude
);
heightSample = heightSample * heightScale + heightOffset;
}
return heightSample;
};
HeightmapTerrainData.prototype.upsample = function(tilingScheme2, thisX, thisY, thisLevel, descendantX, descendantY, descendantLevel) {
if (!defined_default(tilingScheme2)) {
throw new DeveloperError_default("tilingScheme is required.");
}
if (!defined_default(thisX)) {
throw new DeveloperError_default("thisX is required.");
}
if (!defined_default(thisY)) {
throw new DeveloperError_default("thisY is required.");
}
if (!defined_default(thisLevel)) {
throw new DeveloperError_default("thisLevel is required.");
}
if (!defined_default(descendantX)) {
throw new DeveloperError_default("descendantX is required.");
}
if (!defined_default(descendantY)) {
throw new DeveloperError_default("descendantY is required.");
}
if (!defined_default(descendantLevel)) {
throw new DeveloperError_default("descendantLevel is required.");
}
const levelDifference = descendantLevel - thisLevel;
if (levelDifference > 1) {
throw new DeveloperError_default(
"Upsampling through more than one level at a time is not currently supported."
);
}
const meshData = this._mesh;
if (!defined_default(meshData)) {
return void 0;
}
const width = this._width;
const height = this._height;
const structure = this._structure;
const stride = structure.stride;
const heights = new this._bufferType(width * height * stride);
const buffer2 = meshData.vertices;
const encoding = meshData.encoding;
const sourceRectangle = tilingScheme2.tileXYToRectangle(
thisX,
thisY,
thisLevel
);
const destinationRectangle = tilingScheme2.tileXYToRectangle(
descendantX,
descendantY,
descendantLevel
);
const heightOffset = structure.heightOffset;
const heightScale = structure.heightScale;
const elementsPerHeight = structure.elementsPerHeight;
const elementMultiplier = structure.elementMultiplier;
const isBigEndian = structure.isBigEndian;
const divisor = Math.pow(elementMultiplier, elementsPerHeight - 1);
for (let j = 0; j < height; ++j) {
const latitude = Math_default.lerp(
destinationRectangle.north,
destinationRectangle.south,
j / (height - 1)
);
for (let i = 0; i < width; ++i) {
const longitude = Math_default.lerp(
destinationRectangle.west,
destinationRectangle.east,
i / (width - 1)
);
let heightSample = interpolateMeshHeight(
buffer2,
encoding,
heightOffset,
heightScale,
sourceRectangle,
width,
height,
longitude,
latitude
);
heightSample = heightSample < structure.lowestEncodedHeight ? structure.lowestEncodedHeight : heightSample;
heightSample = heightSample > structure.highestEncodedHeight ? structure.highestEncodedHeight : heightSample;
setHeight(
heights,
elementsPerHeight,
elementMultiplier,
divisor,
stride,
isBigEndian,
j * width + i,
heightSample
);
}
}
return Promise.resolve(
new HeightmapTerrainData({
buffer: heights,
width,
height,
childTileMask: 0,
structure: this._structure,
createdByUpsampling: true
})
);
};
HeightmapTerrainData.prototype.isChildAvailable = function(thisX, thisY, childX, childY) {
if (!defined_default(thisX)) {
throw new DeveloperError_default("thisX is required.");
}
if (!defined_default(thisY)) {
throw new DeveloperError_default("thisY is required.");
}
if (!defined_default(childX)) {
throw new DeveloperError_default("childX is required.");
}
if (!defined_default(childY)) {
throw new DeveloperError_default("childY is required.");
}
let bitNumber = 2;
if (childX !== thisX * 2) {
++bitNumber;
}
if (childY !== thisY * 2) {
bitNumber -= 2;
}
return (this._childTileMask & 1 << bitNumber) !== 0;
};
HeightmapTerrainData.prototype.wasCreatedByUpsampling = function() {
return this._createdByUpsampling;
};
function interpolateHeight(sourceHeights, elementsPerHeight, elementMultiplier, stride, isBigEndian, sourceRectangle, width, height, longitude, latitude) {
const fromWest = (longitude - sourceRectangle.west) * (width - 1) / (sourceRectangle.east - sourceRectangle.west);
const fromSouth = (latitude - sourceRectangle.south) * (height - 1) / (sourceRectangle.north - sourceRectangle.south);
let westInteger = fromWest | 0;
let eastInteger = westInteger + 1;
if (eastInteger >= width) {
eastInteger = width - 1;
westInteger = width - 2;
}
let southInteger = fromSouth | 0;
let northInteger = southInteger + 1;
if (northInteger >= height) {
northInteger = height - 1;
southInteger = height - 2;
}
const dx = fromWest - westInteger;
const dy = fromSouth - southInteger;
southInteger = height - 1 - southInteger;
northInteger = height - 1 - northInteger;
const southwestHeight = getHeight(
sourceHeights,
elementsPerHeight,
elementMultiplier,
stride,
isBigEndian,
southInteger * width + westInteger
);
const southeastHeight = getHeight(
sourceHeights,
elementsPerHeight,
elementMultiplier,
stride,
isBigEndian,
southInteger * width + eastInteger
);
const northwestHeight = getHeight(
sourceHeights,
elementsPerHeight,
elementMultiplier,
stride,
isBigEndian,
northInteger * width + westInteger
);
const northeastHeight = getHeight(
sourceHeights,
elementsPerHeight,
elementMultiplier,
stride,
isBigEndian,
northInteger * width + eastInteger
);
return triangleInterpolateHeight(
dx,
dy,
southwestHeight,
southeastHeight,
northwestHeight,
northeastHeight
);
}
function interpolateMeshHeight(buffer2, encoding, heightOffset, heightScale, sourceRectangle, width, height, longitude, latitude) {
const fromWest = (longitude - sourceRectangle.west) * (width - 1) / (sourceRectangle.east - sourceRectangle.west);
const fromSouth = (latitude - sourceRectangle.south) * (height - 1) / (sourceRectangle.north - sourceRectangle.south);
let westInteger = fromWest | 0;
let eastInteger = westInteger + 1;
if (eastInteger >= width) {
eastInteger = width - 1;
westInteger = width - 2;
}
let southInteger = fromSouth | 0;
let northInteger = southInteger + 1;
if (northInteger >= height) {
northInteger = height - 1;
southInteger = height - 2;
}
const dx = fromWest - westInteger;
const dy = fromSouth - southInteger;
southInteger = height - 1 - southInteger;
northInteger = height - 1 - northInteger;
const southwestHeight = (encoding.decodeHeight(buffer2, southInteger * width + westInteger) - heightOffset) / heightScale;
const southeastHeight = (encoding.decodeHeight(buffer2, southInteger * width + eastInteger) - heightOffset) / heightScale;
const northwestHeight = (encoding.decodeHeight(buffer2, northInteger * width + westInteger) - heightOffset) / heightScale;
const northeastHeight = (encoding.decodeHeight(buffer2, northInteger * width + eastInteger) - heightOffset) / heightScale;
return triangleInterpolateHeight(
dx,
dy,
southwestHeight,
southeastHeight,
northwestHeight,
northeastHeight
);
}
function triangleInterpolateHeight(dX, dY, southwestHeight, southeastHeight, northwestHeight, northeastHeight) {
if (dY < dX) {
return southwestHeight + dX * (southeastHeight - southwestHeight) + dY * (northeastHeight - southeastHeight);
}
return southwestHeight + dX * (northeastHeight - northwestHeight) + dY * (northwestHeight - southwestHeight);
}
function getHeight(heights, elementsPerHeight, elementMultiplier, stride, isBigEndian, index) {
index *= stride;
let height = 0;
let i;
if (isBigEndian) {
for (i = 0; i < elementsPerHeight; ++i) {
height = height * elementMultiplier + heights[index + i];
}
} else {
for (i = elementsPerHeight - 1; i >= 0; --i) {
height = height * elementMultiplier + heights[index + i];
}
}
return height;
}
function setHeight(heights, elementsPerHeight, elementMultiplier, divisor, stride, isBigEndian, index, height) {
index *= stride;
let i;
if (isBigEndian) {
for (i = 0; i < elementsPerHeight - 1; ++i) {
heights[index + i] = height / divisor | 0;
height -= heights[index + i] * divisor;
divisor /= elementMultiplier;
}
} else {
for (i = elementsPerHeight - 1; i > 0; --i) {
heights[index + i] = height / divisor | 0;
height -= heights[index + i] * divisor;
divisor /= elementMultiplier;
}
}
heights[index + i] = height;
}
var HeightmapTerrainData_default = HeightmapTerrainData;
// packages/engine/Source/Core/EllipsoidTerrainProvider.js
function EllipsoidTerrainProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._tilingScheme = options.tilingScheme;
if (!defined_default(this._tilingScheme)) {
this._tilingScheme = new GeographicTilingScheme_default({
ellipsoid: options.ellipsoid ?? Ellipsoid_default.default
});
}
this._levelZeroMaximumGeometricError = TerrainProvider_default.getEstimatedLevelZeroGeometricErrorForAHeightmap(
this._tilingScheme.ellipsoid,
64,
this._tilingScheme.getNumberOfXTilesAtLevel(0)
);
this._errorEvent = new Event_default();
}
Object.defineProperties(EllipsoidTerrainProvider.prototype, {
/**
* Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof EllipsoidTerrainProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets the credit to display when this terrain provider is active. Typically this is used to credit
* the source of the terrain.
* @memberof EllipsoidTerrainProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return void 0;
}
},
/**
* Gets the tiling scheme used by this provider.
* @memberof EllipsoidTerrainProvider.prototype
* @type {GeographicTilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._tilingScheme;
}
},
/**
* Gets a value indicating whether or not the provider includes a water mask. The water mask
* indicates which areas of the globe are water rather than land, so they can be rendered
* as a reflective surface with animated waves.
* @memberof EllipsoidTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasWaterMask: {
get: function() {
return false;
}
},
/**
* Gets a value indicating whether or not the requested tiles include vertex normals.
* @memberof EllipsoidTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasVertexNormals: {
get: function() {
return false;
}
},
/**
* Gets an object that can be used to determine availability of terrain from this provider, such as
* at points and in rectangles. This property may be undefined if availability
* information is not available.
* @memberof EllipsoidTerrainProvider.prototype
* @type {TileAvailability|undefined}
* @readonly
*/
availability: {
get: function() {
return void 0;
}
}
});
EllipsoidTerrainProvider.prototype.requestTileGeometry = function(x, y, level, request) {
const width = 16;
const height = 16;
return Promise.resolve(
new HeightmapTerrainData_default({
buffer: new Uint8Array(width * height),
width,
height
})
);
};
EllipsoidTerrainProvider.prototype.getLevelMaximumGeometricError = function(level) {
return this._levelZeroMaximumGeometricError / (1 << level);
};
EllipsoidTerrainProvider.prototype.getTileDataAvailable = function(x, y, level) {
return void 0;
};
EllipsoidTerrainProvider.prototype.loadTileDataAvailability = function(x, y, level) {
return void 0;
};
var EllipsoidTerrainProvider_default = EllipsoidTerrainProvider;
// packages/engine/Source/Shaders/GlobeFS.js
var import_InlineWorkers1012 = __toESM(require_InlineWorkers(), 1);
var GlobeFS_default = `uniform vec4 u_initialColor;
#if TEXTURE_UNITS > 0
uniform sampler2D u_dayTextures[TEXTURE_UNITS];
uniform vec4 u_dayTextureTranslationAndScale[TEXTURE_UNITS];
uniform bool u_dayTextureUseWebMercatorT[TEXTURE_UNITS];
#ifdef APPLY_ALPHA
uniform float u_dayTextureAlpha[TEXTURE_UNITS];
#endif
#ifdef APPLY_DAY_NIGHT_ALPHA
uniform float u_dayTextureNightAlpha[TEXTURE_UNITS];
uniform float u_dayTextureDayAlpha[TEXTURE_UNITS];
#endif
#ifdef APPLY_SPLIT
uniform float u_dayTextureSplit[TEXTURE_UNITS];
#endif
#ifdef APPLY_BRIGHTNESS
uniform float u_dayTextureBrightness[TEXTURE_UNITS];
#endif
#ifdef APPLY_CONTRAST
uniform float u_dayTextureContrast[TEXTURE_UNITS];
#endif
#ifdef APPLY_HUE
uniform float u_dayTextureHue[TEXTURE_UNITS];
#endif
#ifdef APPLY_SATURATION
uniform float u_dayTextureSaturation[TEXTURE_UNITS];
#endif
#ifdef APPLY_GAMMA
uniform float u_dayTextureOneOverGamma[TEXTURE_UNITS];
#endif
#ifdef APPLY_IMAGERY_CUTOUT
uniform vec4 u_dayTextureCutoutRectangles[TEXTURE_UNITS];
#endif
#ifdef APPLY_COLOR_TO_ALPHA
uniform vec4 u_colorsToAlpha[TEXTURE_UNITS];
#endif
uniform vec4 u_dayTextureTexCoordsRectangle[TEXTURE_UNITS];
#endif
#if defined(HAS_WATER_MASK) && (defined(SHOW_REFLECTIVE_OCEAN) || defined(APPLY_MATERIAL))
uniform sampler2D u_waterMask;
uniform vec4 u_waterMaskTranslationAndScale;
uniform float u_zoomedOutOceanSpecularIntensity;
#endif
#ifdef SHOW_OCEAN_WAVES
uniform sampler2D u_oceanNormalMap;
#endif
#if defined(ENABLE_DAYNIGHT_SHADING) || defined(GROUND_ATMOSPHERE)
uniform vec2 u_lightingFadeDistance;
#endif
#ifdef TILE_LIMIT_RECTANGLE
uniform vec4 u_cartographicLimitRectangle;
#endif
#ifdef GROUND_ATMOSPHERE
uniform vec2 u_nightFadeDistance;
#endif
#ifdef ENABLE_CLIPPING_PLANES
uniform highp sampler2D u_clippingPlanes;
uniform mat4 u_clippingPlanesMatrix;
uniform vec4 u_clippingPlanesEdgeStyle;
#endif
#ifdef ENABLE_CLIPPING_POLYGONS
uniform highp sampler2D u_clippingDistance;
in vec2 v_clippingPosition;
flat in int v_regionIndex;
#endif
#if defined(GROUND_ATMOSPHERE) || defined(FOG) && defined(DYNAMIC_ATMOSPHERE_LIGHTING) && (defined(ENABLE_VERTEX_LIGHTING) || defined(ENABLE_DAYNIGHT_SHADING))
uniform float u_minimumBrightness;
#endif
// Based on colorCorrect
// The colorCorrect flag can only be true when tileProvider.hue/saturation/brightnessShift
// are nonzero AND when (applyFog || showGroundAtmosphere) in the tile provider
// - The tileProvider.hue/saturation/brightnessShift are just passed through
// from the Globe hue/saturation/brightness, like atmosphereBrightnessShift
// - The applyFog depends on enableFog, and some tile distance from the viewer
// - The showGroundAtmosphere is a flag that is passed through from the Globe,
// and is true by default when the ellipsoid is WGS84
#ifdef COLOR_CORRECT
uniform vec3 u_hsbShift; // Hue, saturation, brightness
#endif
// Based on highlightFillTile
// This is set for terrain tiles when they are "fill" tiles, and
// the terrainProvider.fillHighlightColor was set to a value with
// nonzero alpha
#ifdef HIGHLIGHT_FILL_TILE
uniform vec4 u_fillHighlightColor;
#endif
// Based on translucent
// This is set depending on the GlobeTranslucencyState
#ifdef TRANSLUCENT
uniform vec4 u_frontFaceAlphaByDistance;
uniform vec4 u_backFaceAlphaByDistance;
uniform vec4 u_translucencyRectangle;
#endif
// Based on showUndergroundColor
// This is set when GlobeSurfaceTileProvider.isUndergroundVisible
// returns true, AND the tileProvider.undergroundColor had a value with
// nonzero alpha, and the tileProvider.undergroundColorAlphaByDistance
// was in the right range
#ifdef UNDERGROUND_COLOR
uniform vec4 u_undergroundColor;
uniform vec4 u_undergroundColorAlphaByDistance;
#endif
// Based on enableLighting && hasVertexNormals
// The enableLighting flag is passed in directly from the Globe.
// The hasVertexNormals flag is from the tileProvider
#ifdef ENABLE_VERTEX_LIGHTING
uniform float u_lambertDiffuseMultiplier;
uniform float u_vertexShadowDarkness;
#endif
in vec3 v_positionMC;
in vec3 v_positionEC;
in vec3 v_textureCoordinates;
in vec3 v_normalMC;
in vec3 v_normalEC;
#ifdef APPLY_MATERIAL
in float v_height;
in float v_slope;
in float v_aspect;
#endif
#if defined(FOG) || defined(GROUND_ATMOSPHERE) || defined(UNDERGROUND_COLOR) || defined(TRANSLUCENT)
in float v_distance;
#endif
#if defined(GROUND_ATMOSPHERE) || defined(FOG)
in vec3 v_atmosphereRayleighColor;
in vec3 v_atmosphereMieColor;
in float v_atmosphereOpacity;
#endif
#if defined(UNDERGROUND_COLOR) || defined(TRANSLUCENT)
float interpolateByDistance(vec4 nearFarScalar, float distance)
{
float startDistance = nearFarScalar.x;
float startValue = nearFarScalar.y;
float endDistance = nearFarScalar.z;
float endValue = nearFarScalar.w;
float t = clamp((distance - startDistance) / (endDistance - startDistance), 0.0, 1.0);
return mix(startValue, endValue, t);
}
#endif
#if defined(UNDERGROUND_COLOR) || defined(TRANSLUCENT) || defined(APPLY_MATERIAL)
vec4 alphaBlend(vec4 sourceColor, vec4 destinationColor)
{
return sourceColor * vec4(sourceColor.aaa, 1.0) + destinationColor * (1.0 - sourceColor.a);
}
#endif
#ifdef TRANSLUCENT
bool inTranslucencyRectangle()
{
return
v_textureCoordinates.x > u_translucencyRectangle.x &&
v_textureCoordinates.x < u_translucencyRectangle.z &&
v_textureCoordinates.y > u_translucencyRectangle.y &&
v_textureCoordinates.y < u_translucencyRectangle.w;
}
#endif
vec4 sampleAndBlend(
vec4 previousColor,
sampler2D textureToSample,
vec2 tileTextureCoordinates,
vec4 textureCoordinateRectangle,
vec4 textureCoordinateTranslationAndScale,
float textureAlpha,
float textureNightAlpha,
float textureDayAlpha,
float textureBrightness,
float textureContrast,
float textureHue,
float textureSaturation,
float textureOneOverGamma,
float split,
vec4 colorToAlpha,
float nightBlend)
{
// This crazy step stuff sets the alpha to 0.0 if this following condition is true:
// tileTextureCoordinates.s < textureCoordinateRectangle.s ||
// tileTextureCoordinates.s > textureCoordinateRectangle.p ||
// tileTextureCoordinates.t < textureCoordinateRectangle.t ||
// tileTextureCoordinates.t > textureCoordinateRectangle.q
// In other words, the alpha is zero if the fragment is outside the rectangle
// covered by this texture. Would an actual 'if' yield better performance?
vec2 alphaMultiplier = step(textureCoordinateRectangle.st, tileTextureCoordinates);
textureAlpha = textureAlpha * alphaMultiplier.x * alphaMultiplier.y;
alphaMultiplier = step(vec2(0.0), textureCoordinateRectangle.pq - tileTextureCoordinates);
textureAlpha = textureAlpha * alphaMultiplier.x * alphaMultiplier.y;
#if defined(APPLY_DAY_NIGHT_ALPHA) && defined(ENABLE_DAYNIGHT_SHADING)
textureAlpha *= mix(textureDayAlpha, textureNightAlpha, nightBlend);
#endif
vec2 translation = textureCoordinateTranslationAndScale.xy;
vec2 scale = textureCoordinateTranslationAndScale.zw;
vec2 textureCoordinates = tileTextureCoordinates * scale + translation;
vec4 value = texture(textureToSample, textureCoordinates);
vec3 color = value.rgb;
float alpha = value.a;
#ifdef APPLY_COLOR_TO_ALPHA
vec3 colorDiff = abs(color.rgb - colorToAlpha.rgb);
colorDiff.r = czm_maximumComponent(colorDiff);
alpha = czm_branchFreeTernary(colorDiff.r < colorToAlpha.a, 0.0, alpha);
#endif
#if !defined(APPLY_GAMMA)
vec4 tempColor = czm_gammaCorrect(vec4(color, alpha));
color = tempColor.rgb;
alpha = tempColor.a;
#else
color = pow(color, vec3(textureOneOverGamma));
#endif
#ifdef APPLY_SPLIT
float splitPosition = czm_splitPosition;
// Split to the left
if (split < 0.0 && gl_FragCoord.x > splitPosition) {
alpha = 0.0;
}
// Split to the right
else if (split > 0.0 && gl_FragCoord.x < splitPosition) {
alpha = 0.0;
}
#endif
#ifdef APPLY_BRIGHTNESS
color = mix(vec3(0.0), color, textureBrightness);
#endif
#ifdef APPLY_CONTRAST
color = mix(vec3(0.5), color, textureContrast);
#endif
#ifdef APPLY_HUE
color = czm_hue(color, textureHue);
#endif
#ifdef APPLY_SATURATION
color = czm_saturation(color, textureSaturation);
#endif
float sourceAlpha = alpha * textureAlpha;
float outAlpha = mix(previousColor.a, 1.0, sourceAlpha);
outAlpha += sign(outAlpha) - 1.0;
vec3 outColor = mix(previousColor.rgb * previousColor.a, color, sourceAlpha) / outAlpha;
// When rendering imagery for a tile in multiple passes,
// some GPU/WebGL implementation combinations will not blend fragments in
// additional passes correctly if their computation includes an unmasked
// divide-by-zero operation,
// even if it's not in the output or if the output has alpha zero.
//
// For example, without sanitization for outAlpha,
// this renders without artifacts:
// if (outAlpha == 0.0) { outColor = vec3(0.0); }
//
// but using czm_branchFreeTernary will cause portions of the tile that are
// alpha-zero in the additional pass to render as black instead of blending
// with the previous pass:
// outColor = czm_branchFreeTernary(outAlpha == 0.0, vec3(0.0), outColor);
//
// So instead, sanitize against divide-by-zero,
// store this state on the sign of outAlpha, and correct on return.
return vec4(outColor, max(outAlpha, 0.0));
}
vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates, float nightBlend);
vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float specularMapValue, float fade);
const float fExposure = 2.0;
vec3 computeEllipsoidPosition()
{
float mpp = czm_metersPerPixel(vec4(0.0, 0.0, -czm_currentFrustum.x, 1.0), 1.0);
vec2 xy = gl_FragCoord.xy / czm_viewport.zw * 2.0 - vec2(1.0);
xy *= czm_viewport.zw * mpp * 0.5;
vec3 direction;
if (czm_orthographicIn3D == 1.0)
{
direction = vec3(0.0, 0.0, -1.0);
}
else
{
direction = normalize(vec3(xy, -czm_currentFrustum.x));
}
czm_ray ray = czm_ray(vec3(0.0), direction);
vec3 ellipsoid_center = czm_view[3].xyz;
czm_raySegment intersection = czm_rayEllipsoidIntersectionInterval(ray, ellipsoid_center, czm_ellipsoidInverseRadii);
vec3 ellipsoidPosition = czm_pointAlongRay(ray, intersection.start);
return (czm_inverseView * vec4(ellipsoidPosition, 1.0)).xyz;
}
void main()
{
#ifdef TILE_LIMIT_RECTANGLE
if (v_textureCoordinates.x < u_cartographicLimitRectangle.x || u_cartographicLimitRectangle.z < v_textureCoordinates.x ||
v_textureCoordinates.y < u_cartographicLimitRectangle.y || u_cartographicLimitRectangle.w < v_textureCoordinates.y)
{
discard;
}
#endif
#ifdef ENABLE_CLIPPING_PLANES
float clipDistance = clip(gl_FragCoord, u_clippingPlanes, u_clippingPlanesMatrix);
#endif
#if defined(SHOW_REFLECTIVE_OCEAN) || defined(ENABLE_DAYNIGHT_SHADING) || defined(HDR)
vec3 normalMC = czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0)); // normalized surface normal in model coordinates
vec3 normalEC = czm_normal3D * normalMC; // normalized surface normal in eye coordinates
#endif
#if defined(APPLY_DAY_NIGHT_ALPHA) && defined(ENABLE_DAYNIGHT_SHADING)
float nightBlend = 1.0 - clamp(czm_getLambertDiffuse(czm_lightDirectionEC, normalEC) * 5.0, 0.0, 1.0);
#else
float nightBlend = 0.0;
#endif
// The clamp below works around an apparent bug in Chrome Canary v23.0.1241.0
// where the fragment shader sees textures coordinates < 0.0 and > 1.0 for the
// fragments on the edges of tiles even though the vertex shader is outputting
// coordinates strictly in the 0-1 range.
vec4 color = computeDayColor(u_initialColor, clamp(v_textureCoordinates, 0.0, 1.0), nightBlend);
#ifdef SHOW_TILE_BOUNDARIES
if (v_textureCoordinates.x < (1.0/256.0) || v_textureCoordinates.x > (255.0/256.0) ||
v_textureCoordinates.y < (1.0/256.0) || v_textureCoordinates.y > (255.0/256.0))
{
color = vec4(1.0, 0.0, 0.0, 1.0);
}
#endif
#if defined(ENABLE_DAYNIGHT_SHADING) || defined(GROUND_ATMOSPHERE)
float cameraDist;
if (czm_sceneMode == czm_sceneMode2D)
{
cameraDist = max(czm_frustumPlanes.x - czm_frustumPlanes.y, czm_frustumPlanes.w - czm_frustumPlanes.z) * 0.5;
}
else if (czm_sceneMode == czm_sceneModeColumbusView)
{
cameraDist = -czm_view[3].z;
}
else
{
cameraDist = length(czm_view[3]);
}
float fadeOutDist = u_lightingFadeDistance.x;
float fadeInDist = u_lightingFadeDistance.y;
if (czm_sceneMode != czm_sceneMode3D) {
vec3 radii = czm_ellipsoidRadii;
float maxRadii = max(radii.x, max(radii.y, radii.z));
fadeOutDist -= maxRadii;
fadeInDist -= maxRadii;
}
float fade = clamp((cameraDist - fadeOutDist) / (fadeInDist - fadeOutDist), 0.0, 1.0);
#else
float fade = 0.0;
#endif
#if defined(HAS_WATER_MASK) && (defined(SHOW_REFLECTIVE_OCEAN) || defined(APPLY_MATERIAL))
vec2 waterMaskTranslation = u_waterMaskTranslationAndScale.xy;
vec2 waterMaskScale = u_waterMaskTranslationAndScale.zw;
vec2 waterMaskTextureCoordinates = v_textureCoordinates.xy * waterMaskScale + waterMaskTranslation;
waterMaskTextureCoordinates.y = 1.0 - waterMaskTextureCoordinates.y;
float mask = texture(u_waterMask, waterMaskTextureCoordinates).r;
#ifdef SHOW_REFLECTIVE_OCEAN
if (mask > 0.0)
{
mat3 enuToEye = czm_eastNorthUpToEyeCoordinates(v_positionMC, normalEC);
vec2 ellipsoidTextureCoordinates = czm_ellipsoidTextureCoordinates(normalMC);
vec2 ellipsoidFlippedTextureCoordinates = czm_ellipsoidTextureCoordinates(normalMC.zyx);
vec2 textureCoordinates = mix(ellipsoidTextureCoordinates, ellipsoidFlippedTextureCoordinates, czm_morphTime * smoothstep(0.9, 0.95, normalMC.z));
color = computeWaterColor(v_positionEC, textureCoordinates, enuToEye, color, mask, fade);
}
#endif
#endif
#ifdef APPLY_MATERIAL
czm_materialInput materialInput;
materialInput.st = v_textureCoordinates.st;
materialInput.normalEC = normalize(v_normalEC);
materialInput.positionToEyeEC = -v_positionEC;
materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(v_positionMC, normalize(v_normalEC));
materialInput.slope = v_slope;
materialInput.height = v_height;
materialInput.aspect = v_aspect;
#ifdef HAS_WATER_MASK
materialInput.waterMask = mask;
#endif
czm_material material = czm_getMaterial(materialInput);
vec4 materialColor = vec4(material.diffuse, material.alpha);
color = alphaBlend(materialColor, color);
#endif
#ifdef ENABLE_VERTEX_LIGHTING
float diffuseIntensity = clamp(czm_getLambertDiffuse(czm_lightDirectionEC, normalize(v_normalEC)) * u_lambertDiffuseMultiplier + u_vertexShadowDarkness, 0.0, 1.0);
vec4 finalColor = vec4(color.rgb * czm_lightColor * diffuseIntensity, color.a);
#elif defined(ENABLE_DAYNIGHT_SHADING)
float diffuseIntensity = clamp(czm_getLambertDiffuse(czm_lightDirectionEC, normalEC) * 5.0 + 0.3, 0.0, 1.0);
diffuseIntensity = mix(1.0, diffuseIntensity, fade);
vec4 finalColor = vec4(color.rgb * czm_lightColor * diffuseIntensity, color.a);
#else
vec4 finalColor = color;
#endif
#ifdef ENABLE_CLIPPING_PLANES
vec4 clippingPlanesEdgeColor = vec4(1.0);
clippingPlanesEdgeColor.rgb = u_clippingPlanesEdgeStyle.rgb;
float clippingPlanesEdgeWidth = u_clippingPlanesEdgeStyle.a;
if (clipDistance < clippingPlanesEdgeWidth)
{
finalColor = clippingPlanesEdgeColor;
}
#endif
#ifdef ENABLE_CLIPPING_POLYGONS
vec2 clippingPosition = v_clippingPosition;
int regionIndex = v_regionIndex;
clipPolygons(u_clippingDistance, CLIPPING_POLYGON_REGIONS_LENGTH, clippingPosition, regionIndex);
#endif
#ifdef HIGHLIGHT_FILL_TILE
finalColor = vec4(mix(finalColor.rgb, u_fillHighlightColor.rgb, u_fillHighlightColor.a), finalColor.a);
#endif
#if defined(DYNAMIC_ATMOSPHERE_LIGHTING_FROM_SUN)
vec3 atmosphereLightDirection = czm_sunDirectionWC;
#else
vec3 atmosphereLightDirection = czm_lightDirectionWC;
#endif
#if defined(GROUND_ATMOSPHERE) || defined(FOG)
if (!czm_backFacing())
{
bool dynamicLighting = false;
#if defined(DYNAMIC_ATMOSPHERE_LIGHTING) && (defined(ENABLE_DAYNIGHT_SHADING) || defined(ENABLE_VERTEX_LIGHTING))
dynamicLighting = true;
#endif
vec3 rayleighColor;
vec3 mieColor;
float opacity;
vec3 positionWC;
vec3 lightDirection;
// When the camera is far away (camera distance > nightFadeOutDistance), the scattering is computed in the fragment shader.
// Otherwise, the scattering is computed in the vertex shader.
#ifdef PER_FRAGMENT_GROUND_ATMOSPHERE
positionWC = computeEllipsoidPosition();
lightDirection = czm_branchFreeTernary(dynamicLighting, atmosphereLightDirection, normalize(positionWC));
computeAtmosphereScattering(
positionWC,
lightDirection,
rayleighColor,
mieColor,
opacity
);
#else
positionWC = v_positionMC;
lightDirection = czm_branchFreeTernary(dynamicLighting, atmosphereLightDirection, normalize(positionWC));
rayleighColor = v_atmosphereRayleighColor;
mieColor = v_atmosphereMieColor;
opacity = v_atmosphereOpacity;
#endif
#ifdef COLOR_CORRECT
const bool ignoreBlackPixels = true;
rayleighColor = czm_applyHSBShift(rayleighColor, u_hsbShift, ignoreBlackPixels);
mieColor = czm_applyHSBShift(mieColor, u_hsbShift, ignoreBlackPixels);
#endif
vec4 groundAtmosphereColor = computeAtmosphereColor(positionWC, lightDirection, rayleighColor, mieColor, opacity);
// Fog is applied to tiles selected for fog, close to the Earth.
#ifdef FOG
vec3 fogColor = groundAtmosphereColor.rgb;
// If there is lighting, apply that to the fog.
#if defined(DYNAMIC_ATMOSPHERE_LIGHTING) && (defined(ENABLE_VERTEX_LIGHTING) || defined(ENABLE_DAYNIGHT_SHADING))
float darken = clamp(dot(normalize(czm_viewerPositionWC), atmosphereLightDirection), u_minimumBrightness, 1.0);
fogColor *= darken;
#endif
#ifndef HDR
fogColor.rgb = czm_pbrNeutralTonemapping(fogColor.rgb);
fogColor.rgb = czm_inverseGamma(fogColor.rgb);
#endif
finalColor = vec4(czm_fog(v_distance, finalColor.rgb, fogColor.rgb, czm_fogVisualDensityScalar), finalColor.a);
#else
// Apply ground atmosphere. This happens when the camera is far away from the earth.
// The transmittance is based on optical depth i.e. the length of segment of the ray inside the atmosphere.
// This value is larger near the "circumference", as it is further away from the camera. We use it to
// brighten up that area of the ground atmosphere.
const float transmittanceModifier = 0.5;
float transmittance = transmittanceModifier + clamp(1.0 - groundAtmosphereColor.a, 0.0, 1.0);
vec3 finalAtmosphereColor = finalColor.rgb + groundAtmosphereColor.rgb * transmittance;
#if defined(DYNAMIC_ATMOSPHERE_LIGHTING) && (defined(ENABLE_VERTEX_LIGHTING) || defined(ENABLE_DAYNIGHT_SHADING))
float fadeInDist = u_nightFadeDistance.x;
float fadeOutDist = u_nightFadeDistance.y;
float sunlitAtmosphereIntensity = clamp((cameraDist - fadeOutDist) / (fadeInDist - fadeOutDist), 0.05, 1.0);
float darken = clamp(dot(normalize(positionWC), atmosphereLightDirection), 0.0, 1.0);
vec3 darkenendGroundAtmosphereColor = mix(groundAtmosphereColor.rgb, finalAtmosphereColor.rgb, darken);
finalAtmosphereColor = mix(darkenendGroundAtmosphereColor, finalAtmosphereColor, sunlitAtmosphereIntensity);
#endif
#ifndef HDR
finalAtmosphereColor.rgb = vec3(1.0) - exp(-fExposure * finalAtmosphereColor.rgb);
#else
finalAtmosphereColor.rgb = czm_saturation(finalAtmosphereColor.rgb, 1.6);
#endif
finalColor.rgb = mix(finalColor.rgb, finalAtmosphereColor.rgb, fade);
#endif
}
#endif
#ifdef UNDERGROUND_COLOR
if (czm_backFacing())
{
float distanceFromEllipsoid = max(czm_eyeHeight, 0.0);
float distance = max(v_distance - distanceFromEllipsoid, 0.0);
float blendAmount = interpolateByDistance(u_undergroundColorAlphaByDistance, distance);
vec4 undergroundColor = vec4(u_undergroundColor.rgb, u_undergroundColor.a * blendAmount);
finalColor = alphaBlend(undergroundColor, finalColor);
}
#endif
#ifdef TRANSLUCENT
if (inTranslucencyRectangle())
{
vec4 alphaByDistance = gl_FrontFacing ? u_frontFaceAlphaByDistance : u_backFaceAlphaByDistance;
finalColor.a *= interpolateByDistance(alphaByDistance, v_distance);
}
#endif
out_FragColor = finalColor;
}
#ifdef SHOW_REFLECTIVE_OCEAN
float waveFade(float edge0, float edge1, float x)
{
float y = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return pow(1.0 - y, 5.0);
}
float linearFade(float edge0, float edge1, float x)
{
return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
}
// Based on water rendering by Jonas Wagner:
// http://29a.ch/2012/7/19/webgl-terrain-rendering-water-fog
// low altitude wave settings
const float oceanFrequencyLowAltitude = 825000.0;
const float oceanAnimationSpeedLowAltitude = 0.004;
const float oceanOneOverAmplitudeLowAltitude = 1.0 / 2.0;
const float oceanSpecularIntensity = 0.5;
// high altitude wave settings
const float oceanFrequencyHighAltitude = 125000.0;
const float oceanAnimationSpeedHighAltitude = 0.008;
const float oceanOneOverAmplitudeHighAltitude = 1.0 / 2.0;
vec4 computeWaterColor(vec3 positionEyeCoordinates, vec2 textureCoordinates, mat3 enuToEye, vec4 imageryColor, float maskValue, float fade)
{
vec3 positionToEyeEC = -positionEyeCoordinates;
float positionToEyeECLength = length(positionToEyeEC);
// The double normalize below works around a bug in Firefox on Android devices.
vec3 normalizedPositionToEyeEC = normalize(normalize(positionToEyeEC));
// Fade out the waves as the camera moves far from the surface.
float waveIntensity = waveFade(70000.0, 1000000.0, positionToEyeECLength);
#ifdef SHOW_OCEAN_WAVES
// high altitude waves
float time = czm_frameNumber * oceanAnimationSpeedHighAltitude;
vec4 noise = czm_getWaterNoise(u_oceanNormalMap, textureCoordinates * oceanFrequencyHighAltitude, time, 0.0);
vec3 normalTangentSpaceHighAltitude = vec3(noise.xy, noise.z * oceanOneOverAmplitudeHighAltitude);
// low altitude waves
time = czm_frameNumber * oceanAnimationSpeedLowAltitude;
noise = czm_getWaterNoise(u_oceanNormalMap, textureCoordinates * oceanFrequencyLowAltitude, time, 0.0);
vec3 normalTangentSpaceLowAltitude = vec3(noise.xy, noise.z * oceanOneOverAmplitudeLowAltitude);
// blend the 2 wave layers based on distance to surface
float highAltitudeFade = linearFade(0.0, 60000.0, positionToEyeECLength);
float lowAltitudeFade = 1.0 - linearFade(20000.0, 60000.0, positionToEyeECLength);
vec3 normalTangentSpace =
(highAltitudeFade * normalTangentSpaceHighAltitude) +
(lowAltitudeFade * normalTangentSpaceLowAltitude);
normalTangentSpace = normalize(normalTangentSpace);
// fade out the normal perturbation as we move farther from the water surface
normalTangentSpace.xy *= waveIntensity;
normalTangentSpace = normalize(normalTangentSpace);
#else
vec3 normalTangentSpace = vec3(0.0, 0.0, 1.0);
#endif
vec3 normalEC = enuToEye * normalTangentSpace;
const vec3 waveHighlightColor = vec3(0.3, 0.45, 0.6);
// Use diffuse light to highlight the waves
float diffuseIntensity = czm_getLambertDiffuse(czm_lightDirectionEC, normalEC) * maskValue;
vec3 diffuseHighlight = waveHighlightColor * diffuseIntensity * (1.0 - fade);
#ifdef SHOW_OCEAN_WAVES
// Where diffuse light is low or non-existent, use wave highlights based solely on
// the wave bumpiness and no particular light direction.
float tsPerturbationRatio = normalTangentSpace.z;
vec3 nonDiffuseHighlight = mix(waveHighlightColor * 5.0 * (1.0 - tsPerturbationRatio), vec3(0.0), diffuseIntensity);
#else
vec3 nonDiffuseHighlight = vec3(0.0);
#endif
// Add specular highlights in 3D, and in all modes when zoomed in.
float specularIntensity = czm_getSpecular(czm_lightDirectionEC, normalizedPositionToEyeEC, normalEC, 10.0);
float surfaceReflectance = mix(0.0, mix(u_zoomedOutOceanSpecularIntensity, oceanSpecularIntensity, waveIntensity), maskValue);
float specular = specularIntensity * surfaceReflectance;
#ifdef HDR
specular *= 1.4;
float e = 0.2;
float d = 3.3;
float c = 1.7;
vec3 color = imageryColor.rgb + (c * (vec3(e) + imageryColor.rgb * d) * (diffuseHighlight + nonDiffuseHighlight + specular));
#else
vec3 color = imageryColor.rgb + diffuseHighlight + nonDiffuseHighlight + specular;
#endif
return vec4(color, imageryColor.a);
}
#endif // #ifdef SHOW_REFLECTIVE_OCEAN
`;
// packages/engine/Source/Shaders/GlobeVS.js
var import_InlineWorkers1013 = __toESM(require_InlineWorkers(), 1);
var GlobeVS_default = "#ifdef QUANTIZATION_BITS12\nin vec4 compressed0;\nin float compressed1;\n#else\nin vec4 position3DAndHeight;\nin vec4 textureCoordAndEncodedNormals;\n#endif\n\n#ifdef GEODETIC_SURFACE_NORMALS\nin vec3 geodeticSurfaceNormal;\n#endif\n\n#ifdef EXAGGERATION\nuniform vec2 u_verticalExaggerationAndRelativeHeight;\n#endif\n\nuniform vec3 u_center3D;\nuniform mat4 u_modifiedModelView;\nuniform mat4 u_modifiedModelViewProjection;\nuniform vec4 u_tileRectangle;\n\n// Uniforms for 2D Mercator projection\nuniform vec2 u_southAndNorthLatitude;\nuniform vec2 u_southMercatorYAndOneOverHeight;\n\nout vec3 v_positionMC;\nout vec3 v_positionEC;\n\nout vec3 v_textureCoordinates;\nout vec3 v_normalMC;\nout vec3 v_normalEC;\n\n#ifdef APPLY_MATERIAL\nout float v_slope;\nout float v_aspect;\nout float v_height;\n#endif\n\n#if defined(FOG) || defined(GROUND_ATMOSPHERE) || defined(UNDERGROUND_COLOR) || defined(TRANSLUCENT)\nout float v_distance;\n#endif\n\n#if defined(FOG) || defined(GROUND_ATMOSPHERE)\nout vec3 v_atmosphereRayleighColor;\nout vec3 v_atmosphereMieColor;\nout float v_atmosphereOpacity;\n#endif\n\n#ifdef ENABLE_CLIPPING_POLYGONS\nuniform highp sampler2D u_clippingExtents;\nout vec2 v_clippingPosition;\nflat out int v_regionIndex;\n#endif\n\n// These functions are generated at runtime.\nvec4 getPosition(vec3 position, float height, vec2 textureCoordinates);\nfloat get2DYPositionFraction(vec2 textureCoordinates);\n\nvec4 getPosition3DMode(vec3 position, float height, vec2 textureCoordinates)\n{\n return u_modifiedModelViewProjection * vec4(position, 1.0);\n}\n\nfloat get2DMercatorYPositionFraction(vec2 textureCoordinates)\n{\n // The width of a tile at level 11, in radians and assuming a single root tile, is\n // 2.0 * czm_pi / pow(2.0, 11.0)\n // We want to just linearly interpolate the 2D position from the texture coordinates\n // when we're at this level or higher. The constant below is the expression\n // above evaluated and then rounded up at the 4th significant digit.\n const float maxTileWidth = 0.003068;\n float positionFraction = textureCoordinates.y;\n float southLatitude = u_southAndNorthLatitude.x;\n float northLatitude = u_southAndNorthLatitude.y;\n if (northLatitude - southLatitude > maxTileWidth)\n {\n float southMercatorY = u_southMercatorYAndOneOverHeight.x;\n float oneOverMercatorHeight = u_southMercatorYAndOneOverHeight.y;\n\n float currentLatitude = mix(southLatitude, northLatitude, textureCoordinates.y);\n currentLatitude = clamp(currentLatitude, -czm_webMercatorMaxLatitude, czm_webMercatorMaxLatitude);\n positionFraction = czm_latitudeToWebMercatorFraction(currentLatitude, southMercatorY, oneOverMercatorHeight);\n }\n return positionFraction;\n}\n\nfloat get2DGeographicYPositionFraction(vec2 textureCoordinates)\n{\n return textureCoordinates.y;\n}\n\nvec4 getPositionPlanarEarth(vec3 position, float height, vec2 textureCoordinates)\n{\n float yPositionFraction = get2DYPositionFraction(textureCoordinates);\n vec4 rtcPosition2D = vec4(height, mix(u_tileRectangle.st, u_tileRectangle.pq, vec2(textureCoordinates.x, yPositionFraction)), 1.0);\n return u_modifiedModelViewProjection * rtcPosition2D;\n}\n\nvec4 getPosition2DMode(vec3 position, float height, vec2 textureCoordinates)\n{\n return getPositionPlanarEarth(position, 0.0, textureCoordinates);\n}\n\nvec4 getPositionColumbusViewMode(vec3 position, float height, vec2 textureCoordinates)\n{\n return getPositionPlanarEarth(position, height, textureCoordinates);\n}\n\nvec4 getPositionMorphingMode(vec3 position, float height, vec2 textureCoordinates)\n{\n // We do not do RTC while morphing, so there is potential for jitter.\n // This is unlikely to be noticeable, though.\n vec3 position3DWC = position + u_center3D;\n float yPositionFraction = get2DYPositionFraction(textureCoordinates);\n vec4 position2DWC = vec4(height, mix(u_tileRectangle.st, u_tileRectangle.pq, vec2(textureCoordinates.x, yPositionFraction)), 1.0);\n vec4 morphPosition = czm_columbusViewMorph(position2DWC, vec4(position3DWC, 1.0), czm_morphTime);\n vec4 morphPositionEC = czm_modelView * morphPosition;\n return czm_projection * morphPositionEC;\n}\n\n#ifdef QUANTIZATION_BITS12\nuniform vec2 u_minMaxHeight;\nuniform mat4 u_scaleAndBias;\n#endif\n\nvoid main()\n{\n#ifdef QUANTIZATION_BITS12\n vec2 xy = czm_decompressTextureCoordinates(compressed0.x);\n vec2 zh = czm_decompressTextureCoordinates(compressed0.y);\n vec3 position = vec3(xy, zh.x);\n float height = zh.y;\n vec2 textureCoordinates = czm_decompressTextureCoordinates(compressed0.z);\n\n height = height * (u_minMaxHeight.y - u_minMaxHeight.x) + u_minMaxHeight.x;\n position = (u_scaleAndBias * vec4(position, 1.0)).xyz;\n\n#if (defined(ENABLE_VERTEX_LIGHTING) || defined(GENERATE_POSITION_AND_NORMAL)) && defined(INCLUDE_WEB_MERCATOR_Y) || defined(APPLY_MATERIAL)\n float webMercatorT = czm_decompressTextureCoordinates(compressed0.w).x;\n float encodedNormal = compressed1;\n#elif defined(INCLUDE_WEB_MERCATOR_Y)\n float webMercatorT = czm_decompressTextureCoordinates(compressed0.w).x;\n float encodedNormal = 0.0;\n#elif defined(ENABLE_VERTEX_LIGHTING) || defined(GENERATE_POSITION_AND_NORMAL)\n float webMercatorT = textureCoordinates.y;\n float encodedNormal = compressed0.w;\n#else\n float webMercatorT = textureCoordinates.y;\n float encodedNormal = 0.0;\n#endif\n\n#else\n // A single float per element\n vec3 position = position3DAndHeight.xyz;\n float height = position3DAndHeight.w;\n vec2 textureCoordinates = textureCoordAndEncodedNormals.xy;\n\n#if (defined(ENABLE_VERTEX_LIGHTING) || defined(GENERATE_POSITION_AND_NORMAL) || defined(APPLY_MATERIAL)) && defined(INCLUDE_WEB_MERCATOR_Y)\n float webMercatorT = textureCoordAndEncodedNormals.z;\n float encodedNormal = textureCoordAndEncodedNormals.w;\n#elif defined(ENABLE_VERTEX_LIGHTING) || defined(GENERATE_POSITION_AND_NORMAL) || defined(APPLY_MATERIAL)\n float webMercatorT = textureCoordinates.y;\n float encodedNormal = textureCoordAndEncodedNormals.z;\n#elif defined(INCLUDE_WEB_MERCATOR_Y)\n float webMercatorT = textureCoordAndEncodedNormals.z;\n float encodedNormal = 0.0;\n#else\n float webMercatorT = textureCoordinates.y;\n float encodedNormal = 0.0;\n#endif\n\n#endif\n\n vec3 position3DWC = position + u_center3D;\n\n#ifdef GEODETIC_SURFACE_NORMALS\n vec3 ellipsoidNormal = geodeticSurfaceNormal;\n#else\n vec3 ellipsoidNormal = normalize(position3DWC);\n#endif\n\n#if defined(EXAGGERATION) && defined(GEODETIC_SURFACE_NORMALS)\n float exaggeration = u_verticalExaggerationAndRelativeHeight.x;\n float relativeHeight = u_verticalExaggerationAndRelativeHeight.y;\n float newHeight = (height - relativeHeight) * exaggeration + relativeHeight;\n\n // stop from going through center of earth\n float minRadius = min(min(czm_ellipsoidRadii.x, czm_ellipsoidRadii.y), czm_ellipsoidRadii.z);\n newHeight = max(newHeight, -minRadius);\n\n vec3 offset = ellipsoidNormal * (newHeight - height);\n position += offset;\n position3DWC += offset;\n height = newHeight;\n#endif\n\n gl_Position = getPosition(position, height, textureCoordinates);\n\n v_positionEC = (u_modifiedModelView * vec4(position, 1.0)).xyz;\n v_positionMC = position3DWC; // position in model coordinates\n\n v_textureCoordinates = vec3(textureCoordinates, webMercatorT);\n\n#if defined(ENABLE_VERTEX_LIGHTING) || defined(GENERATE_POSITION_AND_NORMAL) || defined(APPLY_MATERIAL)\n vec3 normalMC = czm_octDecode(encodedNormal);\n\n#if defined(EXAGGERATION) && defined(GEODETIC_SURFACE_NORMALS)\n vec3 projection = dot(normalMC, ellipsoidNormal) * ellipsoidNormal;\n vec3 rejection = normalMC - projection;\n normalMC = normalize(projection + rejection * exaggeration);\n#endif\n\n v_normalMC = normalMC;\n v_normalEC = czm_normal3D * v_normalMC;\n#endif\n\n#ifdef ENABLE_CLIPPING_POLYGONS\n vec2 sphericalLatLong = czm_approximateSphericalCoordinates(position3DWC);\n sphericalLatLong.y = czm_branchFreeTernary(sphericalLatLong.y < czm_pi, sphericalLatLong.y, sphericalLatLong.y - czm_twoPi);\n \n vec2 minDistance = vec2(czm_infinity);\n v_clippingPosition = vec2(czm_infinity);\n v_regionIndex = -1;\n\n for (int regionIndex = 0; regionIndex < CLIPPING_POLYGON_REGIONS_LENGTH; regionIndex++) {\n vec4 extents = unpackClippingExtents(u_clippingExtents, regionIndex);\n vec2 rectUv = (sphericalLatLong.yx - extents.yx) * extents.wz;\n\n vec2 clamped = clamp(rectUv, vec2(0.0), vec2(1.0));\n vec2 distance = abs(rectUv - clamped) * extents.wz;\n\n float threshold = 0.01;\n if (minDistance.x > distance.x || minDistance.y > distance.y) {\n minDistance = distance;\n v_clippingPosition = rectUv;\n if (rectUv.x > threshold && rectUv.y > threshold && rectUv.x < 1.0 - threshold && rectUv.y < 1.0 - threshold) {\n v_regionIndex = regionIndex;\n }\n }\n }\n#endif\n\n#if defined(FOG) || (defined(GROUND_ATMOSPHERE) && !defined(PER_FRAGMENT_GROUND_ATMOSPHERE))\n\n bool dynamicLighting = false;\n\n #if defined(DYNAMIC_ATMOSPHERE_LIGHTING) && (defined(ENABLE_DAYNIGHT_SHADING) || defined(ENABLE_VERTEX_LIGHTING))\n dynamicLighting = true;\n #endif\n\n#if defined(DYNAMIC_ATMOSPHERE_LIGHTING_FROM_SUN)\n vec3 atmosphereLightDirection = czm_sunDirectionWC;\n#else\n vec3 atmosphereLightDirection = czm_lightDirectionWC;\n#endif\n\n vec3 lightDirection = czm_branchFreeTernary(dynamicLighting, atmosphereLightDirection, normalize(position3DWC));\n\n computeAtmosphereScattering(\n position3DWC,\n lightDirection,\n v_atmosphereRayleighColor,\n v_atmosphereMieColor,\n v_atmosphereOpacity\n );\n#endif\n\n#if defined(FOG) || defined(GROUND_ATMOSPHERE) || defined(UNDERGROUND_COLOR) || defined(TRANSLUCENT)\n v_distance = length((czm_modelView3D * vec4(position3DWC, 1.0)).xyz);\n#endif\n\n#ifdef APPLY_MATERIAL\n float northPoleZ = czm_ellipsoidRadii.z;\n vec3 northPolePositionMC = vec3(0.0, 0.0, northPoleZ);\n vec3 vectorEastMC = normalize(cross(northPolePositionMC - v_positionMC, ellipsoidNormal));\n float dotProd = abs(dot(ellipsoidNormal, v_normalMC));\n v_slope = acos(dotProd);\n vec3 normalRejected = ellipsoidNormal * dotProd;\n vec3 normalProjected = v_normalMC - normalRejected;\n vec3 aspectVector = normalize(normalProjected);\n v_aspect = acos(dot(aspectVector, vectorEastMC));\n float determ = dot(cross(vectorEastMC, aspectVector), ellipsoidNormal);\n v_aspect = czm_branchFreeTernary(determ < 0.0, 2.0 * czm_pi - v_aspect, v_aspect);\n v_height = height;\n#endif\n}\n";
// packages/engine/Source/Shaders/GroundAtmosphere.js
var import_InlineWorkers1014 = __toESM(require_InlineWorkers(), 1);
var GroundAtmosphere_default = "void computeAtmosphereScattering(vec3 positionWC, vec3 lightDirection, out vec3 rayleighColor, out vec3 mieColor, out float opacity) {\n\n vec3 cameraToPositionWC = positionWC - czm_viewerPositionWC;\n vec3 cameraToPositionWCDirection = normalize(cameraToPositionWC);\n czm_ray primaryRay = czm_ray(czm_viewerPositionWC, cameraToPositionWCDirection);\n \n float atmosphereInnerRadius = length(positionWC);\n\n computeScattering(\n primaryRay,\n length(cameraToPositionWC),\n lightDirection,\n atmosphereInnerRadius,\n rayleighColor,\n mieColor,\n opacity\n );\n}\n";
// packages/engine/Source/Scene/GlobeSurfaceShaderSet.js
var import_InlineWorkers1016 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/getClippingFunction.js
var import_InlineWorkers1015 = __toESM(require_InlineWorkers(), 1);
var textureResolutionScratch4 = new Cartesian2_default();
function getClippingFunction(clippingPlaneCollection, context) {
Check_default.typeOf.object("clippingPlaneCollection", clippingPlaneCollection);
Check_default.typeOf.object("context", context);
const unionClippingRegions = clippingPlaneCollection.unionClippingRegions;
const clippingPlanesLength = clippingPlaneCollection.length;
const usingFloatTexture = ClippingPlaneCollection_default.useFloatTexture(context);
const textureResolution = ClippingPlaneCollection_default.getTextureResolution(
clippingPlaneCollection,
context,
textureResolutionScratch4
);
const width = textureResolution.x;
const height = textureResolution.y;
let functions = usingFloatTexture ? getClippingPlaneFloat(width, height) : getClippingPlaneUint8(width, height);
functions += "\n";
functions += unionClippingRegions ? clippingFunctionUnion(clippingPlanesLength) : clippingFunctionIntersect(clippingPlanesLength);
return functions;
}
function clippingFunctionUnion(clippingPlanesLength) {
const functionString = `${"float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\n{\n vec4 position = czm_windowToEyeCoordinates(fragCoord);\n vec3 clipNormal = vec3(0.0);\n vec3 clipPosition = vec3(0.0);\n float clipAmount;\n float pixelWidth = czm_metersPerPixel(position);\n bool breakAndDiscard = false;\n for (int i = 0; i < "}${clippingPlanesLength}; ++i)
{
vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);
clipNormal = clippingPlane.xyz;
clipPosition = -clippingPlane.w * clipNormal;
float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;
clipAmount = czm_branchFreeTernary(i == 0, amount, min(amount, clipAmount));
if (amount <= 0.0)
{
breakAndDiscard = true;
break;
}
}
if (breakAndDiscard) {
discard;
}
return clipAmount;
}
`;
return functionString;
}
function clippingFunctionIntersect(clippingPlanesLength) {
const functionString = `${"float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\n{\n bool clipped = true;\n vec4 position = czm_windowToEyeCoordinates(fragCoord);\n vec3 clipNormal = vec3(0.0);\n vec3 clipPosition = vec3(0.0);\n float clipAmount = 0.0;\n float pixelWidth = czm_metersPerPixel(position);\n for (int i = 0; i < "}${clippingPlanesLength}; ++i)
{
vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);
clipNormal = clippingPlane.xyz;
clipPosition = -clippingPlane.w * clipNormal;
float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;
clipAmount = max(amount, clipAmount);
clipped = clipped && (amount <= 0.0);
}
if (clipped)
{
discard;
}
return clipAmount;
}
`;
return functionString;
}
function getClippingPlaneFloat(width, height) {
const pixelWidth = 1 / width;
const pixelHeight = 1 / height;
let pixelWidthString = `${pixelWidth}`;
if (pixelWidthString.indexOf(".") === -1) {
pixelWidthString += ".0";
}
let pixelHeightString = `${pixelHeight}`;
if (pixelHeightString.indexOf(".") === -1) {
pixelHeightString += ".0";
}
const functionString = `${"vec4 getClippingPlane(highp sampler2D packedClippingPlanes, int clippingPlaneNumber, mat4 transform)\n{\n int pixY = clippingPlaneNumber / "}${width};
int pixX = clippingPlaneNumber - (pixY * ${width});
float u = (float(pixX) + 0.5) * ${pixelWidthString};
float v = (float(pixY) + 0.5) * ${pixelHeightString};
vec4 plane = texture(packedClippingPlanes, vec2(u, v));
return czm_transformPlane(plane, transform);
}
`;
return functionString;
}
function getClippingPlaneUint8(width, height) {
const pixelWidth = 1 / width;
const pixelHeight = 1 / height;
let pixelWidthString = `${pixelWidth}`;
if (pixelWidthString.indexOf(".") === -1) {
pixelWidthString += ".0";
}
let pixelHeightString = `${pixelHeight}`;
if (pixelHeightString.indexOf(".") === -1) {
pixelHeightString += ".0";
}
const functionString = `${"vec4 getClippingPlane(highp sampler2D packedClippingPlanes, int clippingPlaneNumber, mat4 transform)\n{\n int clippingPlaneStartIndex = clippingPlaneNumber * 2;\n int pixY = clippingPlaneStartIndex / "}${width};
int pixX = clippingPlaneStartIndex - (pixY * ${width});
float u = (float(pixX) + 0.5) * ${pixelWidthString};
float v = (float(pixY) + 0.5) * ${pixelHeightString};
vec4 oct32 = texture(packedClippingPlanes, vec2(u, v)) * 255.0;
vec2 oct = vec2(oct32.x * 256.0 + oct32.y, oct32.z * 256.0 + oct32.w);
vec4 plane;
plane.xyz = czm_octDecode(oct, 65535.0);
plane.w = czm_unpackFloat(texture(packedClippingPlanes, vec2(u + ${pixelWidthString}, v)));
return czm_transformPlane(plane, transform);
}
`;
return functionString;
}
var getClippingFunction_default = getClippingFunction;
// packages/engine/Source/Scene/GlobeSurfaceShaderSet.js
function GlobeSurfaceShader(numberOfDayTextures, flags, material, shaderProgram, clippingShaderState, clippingPolygonShaderState) {
this.numberOfDayTextures = numberOfDayTextures;
this.flags = flags;
this.material = material;
this.shaderProgram = shaderProgram;
this.clippingShaderState = clippingShaderState;
this.clippingPolygonShaderState = clippingPolygonShaderState;
}
function GlobeSurfaceShaderSet() {
this.baseVertexShaderSource = void 0;
this.baseFragmentShaderSource = void 0;
this._shadersByTexturesFlags = [];
this.material = void 0;
}
function getPositionMode(sceneMode) {
const getPosition3DMode = "vec4 getPosition(vec3 position, float height, vec2 textureCoordinates) { return getPosition3DMode(position, height, textureCoordinates); }";
const getPositionColumbusViewAnd2DMode = "vec4 getPosition(vec3 position, float height, vec2 textureCoordinates) { return getPositionColumbusViewMode(position, height, textureCoordinates); }";
const getPositionMorphingMode = "vec4 getPosition(vec3 position, float height, vec2 textureCoordinates) { return getPositionMorphingMode(position, height, textureCoordinates); }";
let positionMode;
switch (sceneMode) {
case SceneMode_default.SCENE3D:
positionMode = getPosition3DMode;
break;
case SceneMode_default.SCENE2D:
case SceneMode_default.COLUMBUS_VIEW:
positionMode = getPositionColumbusViewAnd2DMode;
break;
case SceneMode_default.MORPHING:
positionMode = getPositionMorphingMode;
break;
}
return positionMode;
}
function getPolygonClippingFunction(context) {
if (!context.webgl2) {
return `void clipPolygons(highp sampler2D clippingDistance, int regionsLength, vec2 clippingPosition, int regionIndex) {
}`;
}
return `void clipPolygons(highp sampler2D clippingDistance, int regionsLength, vec2 clippingPosition, int regionIndex) {
czm_clipPolygons(clippingDistance, regionsLength, clippingPosition, regionIndex);
}`;
}
function getUnpackClippingFunction(context) {
if (!context.webgl2) {
return `vec4 unpackClippingExtents(highp sampler2D extentsTexture, int index) {
return vec4();
}`;
}
return `vec4 unpackClippingExtents(highp sampler2D extentsTexture, int index) {
return czm_unpackClippingExtents(extentsTexture, index);
}`;
}
function get2DYPositionFraction(useWebMercatorProjection) {
const get2DYPositionFractionGeographicProjection = "float get2DYPositionFraction(vec2 textureCoordinates) { return get2DGeographicYPositionFraction(textureCoordinates); }";
const get2DYPositionFractionMercatorProjection = "float get2DYPositionFraction(vec2 textureCoordinates) { return get2DMercatorYPositionFraction(textureCoordinates); }";
return useWebMercatorProjection ? get2DYPositionFractionMercatorProjection : get2DYPositionFractionGeographicProjection;
}
GlobeSurfaceShaderSet.prototype.getShaderProgram = function(options) {
const frameState = options.frameState;
const surfaceTile = options.surfaceTile;
const numberOfDayTextures = options.numberOfDayTextures;
const applyBrightness = options.applyBrightness;
const applyContrast = options.applyContrast;
const applyHue = options.applyHue;
const applySaturation = options.applySaturation;
const applyGamma = options.applyGamma;
const applyAlpha = options.applyAlpha;
const applyDayNightAlpha = options.applyDayNightAlpha;
const applySplit = options.applySplit;
const hasWaterMask = options.hasWaterMask;
const showReflectiveOcean = options.showReflectiveOcean;
const showOceanWaves = options.showOceanWaves;
const enableLighting = options.enableLighting;
const dynamicAtmosphereLighting = options.dynamicAtmosphereLighting;
const dynamicAtmosphereLightingFromSun = options.dynamicAtmosphereLightingFromSun;
const showGroundAtmosphere = options.showGroundAtmosphere;
const perFragmentGroundAtmosphere = options.perFragmentGroundAtmosphere;
const hasVertexNormals = options.hasVertexNormals;
const useWebMercatorProjection = options.useWebMercatorProjection;
const enableFog = options.enableFog;
const enableClippingPlanes = options.enableClippingPlanes;
const clippingPlanes = options.clippingPlanes;
const enableClippingPolygons = options.enableClippingPolygons;
const clippingPolygons = options.clippingPolygons;
const clippedByBoundaries = options.clippedByBoundaries;
const hasImageryLayerCutout = options.hasImageryLayerCutout;
const colorCorrect = options.colorCorrect;
const highlightFillTile = options.highlightFillTile;
const colorToAlpha = options.colorToAlpha;
const hasGeodeticSurfaceNormals = options.hasGeodeticSurfaceNormals;
const hasExaggeration = options.hasExaggeration;
const showUndergroundColor = options.showUndergroundColor;
const translucent = options.translucent;
let quantization = 0;
let quantizationDefine = "";
const mesh = surfaceTile.renderedMesh;
const terrainEncoding = mesh.encoding;
const quantizationMode = terrainEncoding.quantization;
if (quantizationMode === TerrainQuantization_default.BITS12) {
quantization = 1;
quantizationDefine = "QUANTIZATION_BITS12";
}
let cartographicLimitRectangleFlag = 0;
let cartographicLimitRectangleDefine = "";
if (clippedByBoundaries) {
cartographicLimitRectangleFlag = 1;
cartographicLimitRectangleDefine = "TILE_LIMIT_RECTANGLE";
}
let imageryCutoutFlag = 0;
let imageryCutoutDefine = "";
if (hasImageryLayerCutout) {
imageryCutoutFlag = 1;
imageryCutoutDefine = "APPLY_IMAGERY_CUTOUT";
}
const sceneMode = frameState.mode;
const flags = sceneMode | applyBrightness << 2 | applyContrast << 3 | applyHue << 4 | applySaturation << 5 | applyGamma << 6 | applyAlpha << 7 | hasWaterMask << 8 | showReflectiveOcean << 9 | showOceanWaves << 10 | enableLighting << 11 | dynamicAtmosphereLighting << 12 | dynamicAtmosphereLightingFromSun << 13 | showGroundAtmosphere << 14 | perFragmentGroundAtmosphere << 15 | hasVertexNormals << 16 | useWebMercatorProjection << 17 | enableFog << 18 | quantization << 19 | applySplit << 20 | enableClippingPlanes << 21 | enableClippingPolygons << 22 | cartographicLimitRectangleFlag << 23 | imageryCutoutFlag << 24 | colorCorrect << 25 | highlightFillTile << 26 | colorToAlpha << 27 | hasGeodeticSurfaceNormals << 28 | hasExaggeration << 29 | showUndergroundColor << 30 | translucent << 31 | applyDayNightAlpha << 32;
let currentClippingShaderState = 0;
if (defined_default(clippingPlanes) && clippingPlanes.length > 0) {
currentClippingShaderState = enableClippingPlanes ? clippingPlanes.clippingPlanesState : 0;
}
let currentClippingPolygonsShaderState = 0;
if (defined_default(clippingPolygons) && clippingPolygons.length > 0) {
currentClippingPolygonsShaderState = enableClippingPolygons ? clippingPolygons.clippingPolygonsState : 0;
}
let surfaceShader = surfaceTile.surfaceShader;
if (defined_default(surfaceShader) && surfaceShader.numberOfDayTextures === numberOfDayTextures && surfaceShader.flags === flags && surfaceShader.material === this.material && surfaceShader.clippingShaderState === currentClippingShaderState && surfaceShader.clippingPolygonShaderState === currentClippingPolygonsShaderState) {
return surfaceShader.shaderProgram;
}
let shadersByFlags = this._shadersByTexturesFlags[numberOfDayTextures];
if (!defined_default(shadersByFlags)) {
shadersByFlags = this._shadersByTexturesFlags[numberOfDayTextures] = [];
}
surfaceShader = shadersByFlags[flags];
if (!defined_default(surfaceShader) || surfaceShader.material !== this.material || surfaceShader.clippingShaderState !== currentClippingShaderState || surfaceShader.clippingPolygonShaderState !== currentClippingPolygonsShaderState) {
const vs = this.baseVertexShaderSource.clone();
const fs = this.baseFragmentShaderSource.clone();
if (currentClippingShaderState !== 0) {
fs.sources.unshift(
getClippingFunction_default(clippingPlanes, frameState.context)
);
}
if (currentClippingPolygonsShaderState !== 0) {
fs.sources.unshift(getPolygonClippingFunction(frameState.context));
vs.sources.unshift(getUnpackClippingFunction(frameState.context));
}
vs.defines.push(quantizationDefine);
fs.defines.push(
`TEXTURE_UNITS ${numberOfDayTextures}`,
cartographicLimitRectangleDefine,
imageryCutoutDefine
);
if (applyBrightness) {
fs.defines.push("APPLY_BRIGHTNESS");
}
if (applyContrast) {
fs.defines.push("APPLY_CONTRAST");
}
if (applyHue) {
fs.defines.push("APPLY_HUE");
}
if (applySaturation) {
fs.defines.push("APPLY_SATURATION");
}
if (applyGamma) {
fs.defines.push("APPLY_GAMMA");
}
if (applyAlpha) {
fs.defines.push("APPLY_ALPHA");
}
if (applyDayNightAlpha) {
fs.defines.push("APPLY_DAY_NIGHT_ALPHA");
}
if (hasWaterMask) {
fs.defines.push("HAS_WATER_MASK");
}
if (showReflectiveOcean) {
fs.defines.push("SHOW_REFLECTIVE_OCEAN");
vs.defines.push("SHOW_REFLECTIVE_OCEAN");
}
if (showOceanWaves) {
fs.defines.push("SHOW_OCEAN_WAVES");
}
if (colorToAlpha) {
fs.defines.push("APPLY_COLOR_TO_ALPHA");
}
if (showUndergroundColor) {
vs.defines.push("UNDERGROUND_COLOR");
fs.defines.push("UNDERGROUND_COLOR");
}
if (translucent) {
vs.defines.push("TRANSLUCENT");
fs.defines.push("TRANSLUCENT");
}
if (enableLighting) {
if (hasVertexNormals) {
vs.defines.push("ENABLE_VERTEX_LIGHTING");
fs.defines.push("ENABLE_VERTEX_LIGHTING");
} else {
vs.defines.push("ENABLE_DAYNIGHT_SHADING");
fs.defines.push("ENABLE_DAYNIGHT_SHADING");
}
}
if (dynamicAtmosphereLighting) {
vs.defines.push("DYNAMIC_ATMOSPHERE_LIGHTING");
fs.defines.push("DYNAMIC_ATMOSPHERE_LIGHTING");
if (dynamicAtmosphereLightingFromSun) {
vs.defines.push("DYNAMIC_ATMOSPHERE_LIGHTING_FROM_SUN");
fs.defines.push("DYNAMIC_ATMOSPHERE_LIGHTING_FROM_SUN");
}
}
if (showGroundAtmosphere) {
vs.defines.push("GROUND_ATMOSPHERE");
fs.defines.push("GROUND_ATMOSPHERE");
if (perFragmentGroundAtmosphere) {
vs.defines.push("PER_FRAGMENT_GROUND_ATMOSPHERE");
fs.defines.push("PER_FRAGMENT_GROUND_ATMOSPHERE");
}
}
vs.defines.push("INCLUDE_WEB_MERCATOR_Y");
fs.defines.push("INCLUDE_WEB_MERCATOR_Y");
if (enableFog) {
vs.defines.push("FOG");
fs.defines.push("FOG");
}
if (applySplit) {
fs.defines.push("APPLY_SPLIT");
}
if (enableClippingPlanes) {
fs.defines.push("ENABLE_CLIPPING_PLANES");
}
if (enableClippingPolygons) {
fs.defines.push("ENABLE_CLIPPING_POLYGONS");
vs.defines.push("ENABLE_CLIPPING_POLYGONS");
if (clippingPolygons.inverse) {
fs.defines.push("CLIPPING_INVERSE");
}
fs.defines.push(
`CLIPPING_POLYGON_REGIONS_LENGTH ${clippingPolygons.extentsCount}`
);
vs.defines.push(
`CLIPPING_POLYGON_REGIONS_LENGTH ${clippingPolygons.extentsCount}`
);
}
if (colorCorrect) {
fs.defines.push("COLOR_CORRECT");
}
if (highlightFillTile) {
fs.defines.push("HIGHLIGHT_FILL_TILE");
}
if (hasGeodeticSurfaceNormals) {
vs.defines.push("GEODETIC_SURFACE_NORMALS");
}
if (hasExaggeration) {
vs.defines.push("EXAGGERATION");
}
let computeDayColor = " vec4 computeDayColor(vec4 initialColor, vec3 textureCoordinates, float nightBlend)\n {\n vec4 color = initialColor;\n";
if (hasImageryLayerCutout) {
computeDayColor += " vec4 cutoutAndColorResult;\n bool texelUnclipped;\n";
}
for (let i = 0; i < numberOfDayTextures; ++i) {
if (hasImageryLayerCutout) {
computeDayColor += ` cutoutAndColorResult = u_dayTextureCutoutRectangles[${i}];
texelUnclipped = v_textureCoordinates.x < cutoutAndColorResult.x || cutoutAndColorResult.z < v_textureCoordinates.x || v_textureCoordinates.y < cutoutAndColorResult.y || cutoutAndColorResult.w < v_textureCoordinates.y;
cutoutAndColorResult = sampleAndBlend(
`;
} else {
computeDayColor += " color = sampleAndBlend(\n";
}
computeDayColor += ` color,
u_dayTextures[${i}],
u_dayTextureUseWebMercatorT[${i}] ? textureCoordinates.xz : textureCoordinates.xy,
u_dayTextureTexCoordsRectangle[${i}],
u_dayTextureTranslationAndScale[${i}],
${applyAlpha ? `u_dayTextureAlpha[${i}]` : "1.0"},
${applyDayNightAlpha ? `u_dayTextureNightAlpha[${i}]` : "1.0"},
${applyDayNightAlpha ? `u_dayTextureDayAlpha[${i}]` : "1.0"},
${applyBrightness ? `u_dayTextureBrightness[${i}]` : "0.0"},
${applyContrast ? `u_dayTextureContrast[${i}]` : "0.0"},
${applyHue ? `u_dayTextureHue[${i}]` : "0.0"},
${applySaturation ? `u_dayTextureSaturation[${i}]` : "0.0"},
${applyGamma ? `u_dayTextureOneOverGamma[${i}]` : "0.0"},
${applySplit ? `u_dayTextureSplit[${i}]` : "0.0"},
${colorToAlpha ? `u_colorsToAlpha[${i}]` : "vec4(0.0)"},
nightBlend);
`;
if (hasImageryLayerCutout) {
computeDayColor += " color = czm_branchFreeTernary(texelUnclipped, cutoutAndColorResult, color);\n";
}
}
computeDayColor += " return color;\n }";
fs.sources.push(computeDayColor);
vs.sources.push(getPositionMode(sceneMode));
vs.sources.push(get2DYPositionFraction(useWebMercatorProjection));
const shader = ShaderProgram_default.fromCache({
context: frameState.context,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: terrainEncoding.getAttributeLocations()
});
surfaceShader = shadersByFlags[flags] = new GlobeSurfaceShader(
numberOfDayTextures,
flags,
this.material,
shader,
currentClippingShaderState,
currentClippingPolygonsShaderState
);
}
surfaceTile.surfaceShader = surfaceShader;
return surfaceShader.shaderProgram;
};
GlobeSurfaceShaderSet.prototype.destroy = function() {
let flags;
let shader;
const shadersByTexturesFlags = this._shadersByTexturesFlags;
for (const textureCount in shadersByTexturesFlags) {
if (shadersByTexturesFlags.hasOwnProperty(textureCount)) {
const shadersByFlags = shadersByTexturesFlags[textureCount];
if (!defined_default(shadersByFlags)) {
continue;
}
for (flags in shadersByFlags) {
if (shadersByFlags.hasOwnProperty(flags)) {
shader = shadersByFlags[flags];
if (defined_default(shader)) {
shader.shaderProgram.destroy();
}
}
}
}
}
return destroyObject_default(this);
};
var GlobeSurfaceShaderSet_default = GlobeSurfaceShaderSet;
// packages/engine/Source/Scene/GlobeSurfaceTileProvider.js
var import_InlineWorkers1024 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/Visibility.js
var import_InlineWorkers1017 = __toESM(require_InlineWorkers(), 1);
var Visibility = {
/**
* Represents that no part of an object is visible.
*
* @type {number}
* @constant
*/
NONE: -1,
/**
* Represents that part, but not all, of an object is visible
*
* @type {number}
* @constant
*/
PARTIAL: 0,
/**
* Represents that an object is visible in its entirety.
*
* @type {number}
* @constant
*/
FULL: 1
};
var Visibility_default = Object.freeze(Visibility);
// packages/engine/Source/Scene/GlobeSurfaceTile.js
var import_InlineWorkers1020 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/QuadtreeTileLoadState.js
var import_InlineWorkers1018 = __toESM(require_InlineWorkers(), 1);
var QuadtreeTileLoadState = {
/**
* The tile is new and loading has not yet begun.
* @type QuadtreeTileLoadState
* @constant
* @default 0
*/
START: 0,
/**
* Loading is in progress.
* @type QuadtreeTileLoadState
* @constant
* @default 1
*/
LOADING: 1,
/**
* Loading is complete.
* @type QuadtreeTileLoadState
* @constant
* @default 2
*/
DONE: 2,
/**
* The tile has failed to load.
* @type QuadtreeTileLoadState
* @constant
* @default 3
*/
FAILED: 3
};
var QuadtreeTileLoadState_default = Object.freeze(QuadtreeTileLoadState);
// packages/engine/Source/Scene/TerrainState.js
var import_InlineWorkers1019 = __toESM(require_InlineWorkers(), 1);
var TerrainState = {
FAILED: 0,
UNLOADED: 1,
RECEIVING: 2,
RECEIVED: 3,
TRANSFORMING: 4,
TRANSFORMED: 5,
READY: 6
};
var TerrainState_default = Object.freeze(TerrainState);
// packages/engine/Source/Scene/GlobeSurfaceTile.js
function GlobeSurfaceTile() {
this.imagery = [];
this.waterMaskTexture = void 0;
this.waterMaskTranslationAndScale = new Cartesian4_default(0, 0, 1, 1);
this.terrainData = void 0;
this.vertexArray = void 0;
this.tileBoundingRegion = void 0;
this.occludeePointInScaledSpace = new Cartesian3_default();
this.boundingVolumeSourceTile = void 0;
this.boundingVolumeIsFromMesh = false;
this.terrainState = TerrainState_default.UNLOADED;
this.mesh = void 0;
this.fill = void 0;
this.pickBoundingSphere = new BoundingSphere_default();
this.surfaceShader = void 0;
this.isClipped = true;
this.clippedByBoundaries = false;
}
Object.defineProperties(GlobeSurfaceTile.prototype, {
/**
* Gets a value indicating whether or not this tile is eligible to be unloaded.
* Typically, a tile is ineligible to be unloaded while an asynchronous operation,
* such as a request for data, is in progress on it. A tile will never be
* unloaded while it is needed for rendering, regardless of the value of this
* property.
* @memberof GlobeSurfaceTile.prototype
* @type {boolean}
*/
eligibleForUnloading: {
get: function() {
const terrainState = this.terrainState;
const loadingIsTransitioning = terrainState === TerrainState_default.RECEIVING || terrainState === TerrainState_default.TRANSFORMING;
let shouldRemoveTile = !loadingIsTransitioning;
const imagery = this.imagery;
for (let i = 0, len = imagery.length; shouldRemoveTile && i < len; ++i) {
const tileImagery = imagery[i];
shouldRemoveTile = !defined_default(tileImagery.loadingImagery) || tileImagery.loadingImagery.state !== ImageryState_default.TRANSITIONING;
}
return shouldRemoveTile;
}
},
/**
* Gets the {@link TerrainMesh} that is used for rendering this tile, if any.
* Returns the value of the {@link GlobeSurfaceTile#mesh} property if
* {@link GlobeSurfaceTile#vertexArray} is defined. Otherwise, It returns the
* {@link TerrainFillMesh#mesh} property of the {@link GlobeSurfaceTile#fill}.
* If there is no fill, it returns undefined.
*
* @memberof GlobeSurfaceTile.prototype
* @type {TerrainMesh}
*/
renderedMesh: {
get: function() {
if (defined_default(this.vertexArray)) {
return this.mesh;
} else if (defined_default(this.fill)) {
return this.fill.mesh;
}
return void 0;
}
}
});
var scratchCartographic18 = new Cartographic_default();
function getPosition2(encoding, mode2, projection, vertices, index, result) {
let position = encoding.getExaggeratedPosition(vertices, index, result);
if (defined_default(mode2) && mode2 !== SceneMode_default.SCENE3D) {
const ellipsoid = projection.ellipsoid;
const positionCartographic = ellipsoid.cartesianToCartographic(
position,
scratchCartographic18
);
position = projection.project(positionCartographic, result);
position = Cartesian3_default.fromElements(
position.z,
position.x,
position.y,
result
);
}
return position;
}
var scratchV02 = new Cartesian3_default();
var scratchV12 = new Cartesian3_default();
var scratchV22 = new Cartesian3_default();
GlobeSurfaceTile.prototype.pick = function(ray, mode2, projection, cullBackFaces, result) {
const mesh = this.renderedMesh;
if (!defined_default(mesh)) {
return void 0;
}
const vertices = mesh.vertices;
const indices = mesh.indices;
const encoding = mesh.encoding;
const indicesLength = indices.length;
let minT = Number.MAX_VALUE;
for (let i = 0; i < indicesLength; i += 3) {
const i0 = indices[i];
const i1 = indices[i + 1];
const i2 = indices[i + 2];
const v02 = getPosition2(encoding, mode2, projection, vertices, i0, scratchV02);
const v12 = getPosition2(encoding, mode2, projection, vertices, i1, scratchV12);
const v22 = getPosition2(encoding, mode2, projection, vertices, i2, scratchV22);
const t = IntersectionTests_default.rayTriangleParametric(
ray,
v02,
v12,
v22,
cullBackFaces
);
if (defined_default(t) && t < minT && t >= 0) {
minT = t;
}
}
return minT !== Number.MAX_VALUE ? Ray_default.getPoint(ray, minT, result) : void 0;
};
GlobeSurfaceTile.prototype.freeResources = function() {
if (defined_default(this.waterMaskTexture)) {
--this.waterMaskTexture.referenceCount;
if (this.waterMaskTexture.referenceCount === 0) {
this.waterMaskTexture.destroy();
}
this.waterMaskTexture = void 0;
}
this.terrainData = void 0;
this.terrainState = TerrainState_default.UNLOADED;
this.mesh = void 0;
this.fill = this.fill && this.fill.destroy();
const imageryList = this.imagery;
for (let i = 0, len = imageryList.length; i < len; ++i) {
imageryList[i].freeResources();
}
this.imagery.length = 0;
this.freeVertexArray();
};
GlobeSurfaceTile.prototype.freeVertexArray = function() {
GlobeSurfaceTile._freeVertexArray(this.vertexArray);
this.vertexArray = void 0;
GlobeSurfaceTile._freeVertexArray(this.wireframeVertexArray);
this.wireframeVertexArray = void 0;
};
GlobeSurfaceTile.initialize = function(tile, terrainProvider, imageryLayerCollection) {
let surfaceTile = tile.data;
if (!defined_default(surfaceTile)) {
surfaceTile = tile.data = new GlobeSurfaceTile();
}
if (tile.state === QuadtreeTileLoadState_default.START) {
prepareNewTile(tile, terrainProvider, imageryLayerCollection);
tile.state = QuadtreeTileLoadState_default.LOADING;
}
};
GlobeSurfaceTile.processStateMachine = function(tile, frameState, terrainProvider, imageryLayerCollection, quadtree, vertexArraysToDestroy, terrainOnly) {
GlobeSurfaceTile.initialize(tile, terrainProvider, imageryLayerCollection);
const surfaceTile = tile.data;
if (tile.state === QuadtreeTileLoadState_default.LOADING) {
processTerrainStateMachine(
tile,
frameState,
terrainProvider,
imageryLayerCollection,
quadtree,
vertexArraysToDestroy
);
}
if (terrainOnly) {
return;
}
const wasAlreadyRenderable = tile.renderable;
tile.renderable = defined_default(surfaceTile.vertexArray);
const isTerrainDoneLoading = surfaceTile.terrainState === TerrainState_default.READY;
tile.upsampledFromParent = defined_default(surfaceTile.terrainData) && surfaceTile.terrainData.wasCreatedByUpsampling();
const isImageryDoneLoading = surfaceTile.processImagery(
tile,
terrainProvider,
frameState
);
if (isTerrainDoneLoading && isImageryDoneLoading) {
const callbacks = tile._loadedCallbacks;
const newCallbacks = {};
for (const layerId in callbacks) {
if (callbacks.hasOwnProperty(layerId)) {
if (!callbacks[layerId](tile)) {
newCallbacks[layerId] = callbacks[layerId];
}
}
}
tile._loadedCallbacks = newCallbacks;
tile.state = QuadtreeTileLoadState_default.DONE;
}
if (wasAlreadyRenderable) {
tile.renderable = true;
}
};
GlobeSurfaceTile.prototype.processImagery = function(tile, terrainProvider, frameState, skipLoading) {
const surfaceTile = tile.data;
let isUpsampledOnly = tile.upsampledFromParent;
let isAnyTileLoaded = false;
let isDoneLoading = true;
const tileImageryCollection = surfaceTile.imagery;
let i, len;
for (i = 0, len = tileImageryCollection.length; i < len; ++i) {
const tileImagery = tileImageryCollection[i];
if (!defined_default(tileImagery.loadingImagery)) {
isUpsampledOnly = false;
continue;
}
if (tileImagery.loadingImagery.state === ImageryState_default.PLACEHOLDER) {
const imageryLayer = tileImagery.loadingImagery.imageryLayer;
if (imageryLayer.ready) {
tileImagery.freeResources();
tileImageryCollection.splice(i, 1);
imageryLayer._createTileImagerySkeletons(tile, terrainProvider, i);
--i;
len = tileImageryCollection.length;
continue;
} else {
isUpsampledOnly = false;
}
}
const thisTileDoneLoading = tileImagery.processStateMachine(
tile,
frameState,
skipLoading
);
isDoneLoading = isDoneLoading && thisTileDoneLoading;
isAnyTileLoaded = isAnyTileLoaded || thisTileDoneLoading || defined_default(tileImagery.readyImagery);
isUpsampledOnly = isUpsampledOnly && defined_default(tileImagery.loadingImagery) && (tileImagery.loadingImagery.state === ImageryState_default.FAILED || tileImagery.loadingImagery.state === ImageryState_default.INVALID);
}
tile.upsampledFromParent = isUpsampledOnly;
tile.renderable = tile.renderable && (isAnyTileLoaded || isDoneLoading);
return isDoneLoading;
};
function toggleGeodeticSurfaceNormals(surfaceTile, enabled, ellipsoid, frameState) {
const renderedMesh = surfaceTile.renderedMesh;
const vertexBuffer = renderedMesh.vertices;
const encoding = renderedMesh.encoding;
const vertexCount = vertexBuffer.length / encoding.stride;
let newEncoding = TerrainEncoding_default.clone(encoding);
newEncoding.hasGeodeticSurfaceNormals = enabled;
newEncoding = TerrainEncoding_default.clone(newEncoding);
const newStride = newEncoding.stride;
const newVertexBuffer = new Float32Array(vertexCount * newStride);
if (enabled) {
encoding.addGeodeticSurfaceNormals(
vertexBuffer,
newVertexBuffer,
ellipsoid
);
} else {
encoding.removeGeodeticSurfaceNormals(vertexBuffer, newVertexBuffer);
}
renderedMesh.vertices = newVertexBuffer;
renderedMesh.stride = newStride;
const isFill = renderedMesh !== surfaceTile.mesh;
if (isFill) {
GlobeSurfaceTile._freeVertexArray(surfaceTile.fill.vertexArray);
surfaceTile.fill.vertexArray = GlobeSurfaceTile._createVertexArrayForMesh(
frameState.context,
renderedMesh
);
} else {
GlobeSurfaceTile._freeVertexArray(surfaceTile.vertexArray);
surfaceTile.vertexArray = GlobeSurfaceTile._createVertexArrayForMesh(
frameState.context,
renderedMesh
);
}
GlobeSurfaceTile._freeVertexArray(surfaceTile.wireframeVertexArray);
surfaceTile.wireframeVertexArray = void 0;
}
GlobeSurfaceTile.prototype.addGeodeticSurfaceNormals = function(ellipsoid, frameState) {
toggleGeodeticSurfaceNormals(this, true, ellipsoid, frameState);
};
GlobeSurfaceTile.prototype.removeGeodeticSurfaceNormals = function(frameState) {
toggleGeodeticSurfaceNormals(this, false, void 0, frameState);
};
GlobeSurfaceTile.prototype.updateExaggeration = function(tile, frameState, quadtree) {
const surfaceTile = this;
const mesh = surfaceTile.renderedMesh;
if (mesh === void 0) {
return;
}
const exaggeration = frameState.verticalExaggeration;
const exaggerationRelativeHeight = frameState.verticalExaggerationRelativeHeight;
const hasExaggerationScale = exaggeration !== 1;
const encoding = mesh.encoding;
const encodingExaggerationScaleChanged = encoding.exaggeration !== exaggeration;
const encodingRelativeHeightChanged = encoding.exaggerationRelativeHeight !== exaggerationRelativeHeight;
if (encodingExaggerationScaleChanged || encodingRelativeHeightChanged) {
if (encodingExaggerationScaleChanged) {
if (hasExaggerationScale && !encoding.hasGeodeticSurfaceNormals) {
const ellipsoid = tile.tilingScheme.ellipsoid;
surfaceTile.addGeodeticSurfaceNormals(ellipsoid, frameState);
} else if (!hasExaggerationScale && encoding.hasGeodeticSurfaceNormals) {
surfaceTile.removeGeodeticSurfaceNormals(frameState);
}
}
encoding.exaggeration = exaggeration;
encoding.exaggerationRelativeHeight = exaggerationRelativeHeight;
if (quadtree !== void 0) {
quadtree._tileToUpdateHeights.push(tile);
const customData = tile.customData;
const customDataLength = customData.length;
for (let i = 0; i < customDataLength; i++) {
const data = customData[i];
data.level = -1;
}
}
}
};
function prepareNewTile(tile, terrainProvider, imageryLayerCollection) {
let available = terrainProvider.getTileDataAvailable(
tile.x,
tile.y,
tile.level
);
if (!defined_default(available) && defined_default(tile.parent)) {
const parent = tile.parent;
const parentSurfaceTile = parent.data;
if (defined_default(parentSurfaceTile) && defined_default(parentSurfaceTile.terrainData)) {
available = parentSurfaceTile.terrainData.isChildAvailable(
parent.x,
parent.y,
tile.x,
tile.y
);
}
}
if (available === false) {
tile.data.terrainState = TerrainState_default.FAILED;
}
for (let i = 0, len = imageryLayerCollection.length; i < len; ++i) {
const layer = imageryLayerCollection.get(i);
if (layer.show) {
layer._createTileImagerySkeletons(tile, terrainProvider);
}
}
}
function processTerrainStateMachine(tile, frameState, terrainProvider, imageryLayerCollection, quadtree, vertexArraysToDestroy) {
const surfaceTile = tile.data;
const parent = tile.parent;
if (surfaceTile.terrainState === TerrainState_default.FAILED && parent !== void 0) {
const parentReady = parent.data !== void 0 && parent.data.terrainData !== void 0 && parent.data.terrainData.canUpsample !== false;
if (!parentReady) {
GlobeSurfaceTile.processStateMachine(
parent,
frameState,
terrainProvider,
imageryLayerCollection,
quadtree,
vertexArraysToDestroy,
true
);
}
}
if (surfaceTile.terrainState === TerrainState_default.FAILED) {
upsample(
surfaceTile,
tile,
frameState,
terrainProvider,
tile.x,
tile.y,
tile.level
);
}
if (surfaceTile.terrainState === TerrainState_default.UNLOADED) {
requestTileGeometry(
surfaceTile,
terrainProvider,
tile.x,
tile.y,
tile.level
);
}
if (surfaceTile.terrainState === TerrainState_default.RECEIVED) {
transform2(
surfaceTile,
frameState,
terrainProvider,
tile.x,
tile.y,
tile.level
);
}
if (surfaceTile.terrainState === TerrainState_default.TRANSFORMED) {
createResources2(
surfaceTile,
frameState.context,
terrainProvider,
tile.x,
tile.y,
tile.level,
vertexArraysToDestroy
);
surfaceTile.updateExaggeration(tile, frameState, quadtree);
}
if (surfaceTile.terrainState >= TerrainState_default.RECEIVED && surfaceTile.waterMaskTexture === void 0 && terrainProvider.hasWaterMask) {
const terrainData = surfaceTile.terrainData;
if (terrainData.waterMask !== void 0) {
createWaterMaskTextureIfNeeded(frameState.context, surfaceTile);
} else {
const sourceTile = surfaceTile._findAncestorTileWithTerrainData(tile);
if (defined_default(sourceTile) && defined_default(sourceTile.data.waterMaskTexture)) {
surfaceTile.waterMaskTexture = sourceTile.data.waterMaskTexture;
++surfaceTile.waterMaskTexture.referenceCount;
surfaceTile._computeWaterMaskTranslationAndScale(
tile,
sourceTile,
surfaceTile.waterMaskTranslationAndScale
);
}
}
}
}
function upsample(surfaceTile, tile, frameState, terrainProvider, x, y, level) {
const parent = tile.parent;
if (!parent) {
tile.state = QuadtreeTileLoadState_default.FAILED;
return;
}
const sourceData = parent.data.terrainData;
const sourceX = parent.x;
const sourceY = parent.y;
const sourceLevel = parent.level;
if (!defined_default(sourceData)) {
return;
}
const terrainDataPromise = sourceData.upsample(
terrainProvider.tilingScheme,
sourceX,
sourceY,
sourceLevel,
x,
y,
level
);
if (!defined_default(terrainDataPromise)) {
return;
}
surfaceTile.terrainState = TerrainState_default.RECEIVING;
Promise.resolve(terrainDataPromise).then(function(terrainData) {
if (!defined_default(terrainData)) {
return;
}
surfaceTile.terrainData = terrainData;
surfaceTile.terrainState = TerrainState_default.RECEIVED;
}).catch(function() {
surfaceTile.terrainState = TerrainState_default.FAILED;
});
}
function requestTileGeometry(surfaceTile, terrainProvider, x, y, level) {
function success(terrainData) {
if (!defined_default(terrainData)) {
surfaceTile.terrainState = TerrainState_default.UNLOADED;
surfaceTile.request = void 0;
return;
}
surfaceTile.terrainData = terrainData;
surfaceTile.terrainState = TerrainState_default.RECEIVED;
surfaceTile.request = void 0;
}
function failure2(error) {
if (surfaceTile.request.state === RequestState_default.CANCELLED) {
surfaceTile.terrainData = void 0;
surfaceTile.terrainState = TerrainState_default.UNLOADED;
surfaceTile.request = void 0;
return;
}
surfaceTile.terrainState = TerrainState_default.FAILED;
surfaceTile.request = void 0;
const message = `Failed to obtain terrain tile X: ${x} Y: ${y} Level: ${level}. Error message: "${error}"`;
terrainProvider._requestError = TileProviderError_default.reportError(
terrainProvider._requestError,
terrainProvider,
terrainProvider.errorEvent,
message,
x,
y,
level
);
if (terrainProvider._requestError.retry) {
doRequest2();
}
}
function doRequest2() {
const request = new Request_default({
throttle: false,
throttleByServer: true,
type: RequestType_default.TERRAIN
});
surfaceTile.request = request;
const requestPromise = terrainProvider.requestTileGeometry(
x,
y,
level,
request
);
if (defined_default(requestPromise)) {
surfaceTile.terrainState = TerrainState_default.RECEIVING;
Promise.resolve(requestPromise).then(function(terrainData) {
success(terrainData);
}).catch(function(e) {
failure2(e);
});
} else {
surfaceTile.terrainState = TerrainState_default.UNLOADED;
surfaceTile.request = void 0;
}
}
doRequest2();
}
var scratchCreateMeshOptions = {
tilingScheme: void 0,
x: 0,
y: 0,
level: 0,
exaggeration: 1,
exaggerationRelativeHeight: 0,
throttle: true
};
function transform2(surfaceTile, frameState, terrainProvider, x, y, level) {
const tilingScheme2 = terrainProvider.tilingScheme;
const createMeshOptions = scratchCreateMeshOptions;
createMeshOptions.tilingScheme = tilingScheme2;
createMeshOptions.x = x;
createMeshOptions.y = y;
createMeshOptions.level = level;
createMeshOptions.exaggeration = frameState.verticalExaggeration;
createMeshOptions.exaggerationRelativeHeight = frameState.verticalExaggerationRelativeHeight;
createMeshOptions.throttle = true;
const terrainData = surfaceTile.terrainData;
const meshPromise = terrainData.createMesh(createMeshOptions);
if (!defined_default(meshPromise)) {
return;
}
surfaceTile.terrainState = TerrainState_default.TRANSFORMING;
Promise.resolve(meshPromise).then(function(mesh) {
surfaceTile.mesh = mesh;
surfaceTile.terrainState = TerrainState_default.TRANSFORMED;
}).catch(function() {
surfaceTile.terrainState = TerrainState_default.FAILED;
});
}
GlobeSurfaceTile._createVertexArrayForMesh = function(context, mesh) {
const typedArray = mesh.vertices;
const buffer2 = Buffer_default.createVertexBuffer({
context,
typedArray,
usage: BufferUsage_default.STATIC_DRAW
});
const attributes = mesh.encoding.getAttributes(buffer2);
const indexBuffers = mesh.indices.indexBuffers || {};
let indexBuffer = indexBuffers[context.id];
if (!defined_default(indexBuffer) || indexBuffer.isDestroyed()) {
const indices = mesh.indices;
indexBuffer = Buffer_default.createIndexBuffer({
context,
typedArray: indices,
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype: IndexDatatype_default.fromSizeInBytes(indices.BYTES_PER_ELEMENT)
});
indexBuffer.vertexArrayDestroyable = false;
indexBuffer.referenceCount = 1;
indexBuffers[context.id] = indexBuffer;
mesh.indices.indexBuffers = indexBuffers;
} else {
++indexBuffer.referenceCount;
}
return new VertexArray_default({
context,
attributes,
indexBuffer
});
};
GlobeSurfaceTile._freeVertexArray = function(vertexArray) {
if (defined_default(vertexArray)) {
const indexBuffer = vertexArray.indexBuffer;
if (!vertexArray.isDestroyed()) {
vertexArray.destroy();
}
if (defined_default(indexBuffer) && !indexBuffer.isDestroyed() && defined_default(indexBuffer.referenceCount)) {
--indexBuffer.referenceCount;
if (indexBuffer.referenceCount === 0) {
indexBuffer.destroy();
}
}
}
};
function createResources2(surfaceTile, context, terrainProvider, x, y, level, vertexArraysToDestroy) {
surfaceTile.vertexArray = GlobeSurfaceTile._createVertexArrayForMesh(
context,
surfaceTile.mesh
);
surfaceTile.terrainState = TerrainState_default.READY;
surfaceTile.fill = surfaceTile.fill && surfaceTile.fill.destroy(vertexArraysToDestroy);
}
function getContextWaterMaskData(context) {
let data = context.cache.tile_waterMaskData;
if (!defined_default(data)) {
const allWaterTexture = Texture_default.create({
context,
pixelFormat: PixelFormat_default.LUMINANCE,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
source: {
arrayBufferView: new Uint8Array([255]),
width: 1,
height: 1
}
});
allWaterTexture.referenceCount = 1;
const sampler = new Sampler_default({
wrapS: TextureWrap_default.CLAMP_TO_EDGE,
wrapT: TextureWrap_default.CLAMP_TO_EDGE,
minificationFilter: TextureMinificationFilter_default.LINEAR,
magnificationFilter: TextureMagnificationFilter_default.LINEAR
});
data = {
allWaterTexture,
sampler,
destroy: function() {
this.allWaterTexture.destroy();
}
};
context.cache.tile_waterMaskData = data;
}
return data;
}
function createWaterMaskTextureIfNeeded(context, surfaceTile) {
const waterMask = surfaceTile.terrainData.waterMask;
const waterMaskData = getContextWaterMaskData(context);
let texture;
const waterMaskLength = waterMask.length;
if (waterMaskLength === 1) {
if (waterMask[0] !== 0) {
texture = waterMaskData.allWaterTexture;
} else {
return;
}
} else {
const textureSize = Math.sqrt(waterMaskLength);
texture = Texture_default.create({
context,
pixelFormat: PixelFormat_default.LUMINANCE,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
source: {
width: textureSize,
height: textureSize,
arrayBufferView: waterMask
},
sampler: waterMaskData.sampler,
flipY: false
});
texture.referenceCount = 0;
}
++texture.referenceCount;
surfaceTile.waterMaskTexture = texture;
Cartesian4_default.fromElements(
0,
0,
1,
1,
surfaceTile.waterMaskTranslationAndScale
);
}
GlobeSurfaceTile.prototype._findAncestorTileWithTerrainData = function(tile) {
let sourceTile = tile.parent;
while (defined_default(sourceTile) && (!defined_default(sourceTile.data) || !defined_default(sourceTile.data.terrainData) || sourceTile.data.terrainData.wasCreatedByUpsampling())) {
sourceTile = sourceTile.parent;
}
return sourceTile;
};
GlobeSurfaceTile.prototype._computeWaterMaskTranslationAndScale = function(tile, sourceTile, result) {
const sourceTileRectangle = sourceTile.rectangle;
const tileRectangle = tile.rectangle;
const tileWidth = tileRectangle.width;
const tileHeight = tileRectangle.height;
const scaleX = tileWidth / sourceTileRectangle.width;
const scaleY = tileHeight / sourceTileRectangle.height;
result.x = scaleX * (tileRectangle.west - sourceTileRectangle.west) / tileWidth;
result.y = scaleY * (tileRectangle.south - sourceTileRectangle.south) / tileHeight;
result.z = scaleX;
result.w = scaleY;
return result;
};
var GlobeSurfaceTile_default = GlobeSurfaceTile;
// packages/engine/Source/Scene/TerrainFillMesh.js
var import_InlineWorkers1023 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/TileEdge.js
var import_InlineWorkers1021 = __toESM(require_InlineWorkers(), 1);
var TileEdge = {
WEST: 0,
NORTH: 1,
EAST: 2,
SOUTH: 3,
NORTHWEST: 4,
NORTHEAST: 5,
SOUTHWEST: 6,
SOUTHEAST: 7
};
var TileEdge_default = TileEdge;
// packages/engine/Source/Scene/TileSelectionResult.js
var import_InlineWorkers1022 = __toESM(require_InlineWorkers(), 1);
var TileSelectionResult = {
/**
* There was no selection result, perhaps because the tile wasn't visited
* last frame.
*/
NONE: 0,
/**
* This tile was deemed not visible and culled.
*/
CULLED: 1,
/**
* The tile was selected for rendering.
*/
RENDERED: 2,
/**
* This tile did not meet the required screen-space error and was refined.
*/
REFINED: 3,
/**
* This tile was originally rendered, but it got kicked out of the render list
* in favor of an ancestor because it is not yet renderable.
*/
RENDERED_AND_KICKED: 2 | 4,
/**
* This tile was originally refined, but its rendered descendants got kicked out of the
* render list in favor of an ancestor because it is not yet renderable.
*/
REFINED_AND_KICKED: 3 | 4,
/**
* This tile was culled because it was not visible, but it still needs to be loaded
* and any heights on it need to be updated because the camera's position or the
* camera's reference frame's origin falls inside this tile. Loading this tile
* could affect the position of the camera if the camera is currently below
* terrain or if it is tracking an object whose height is referenced to terrain.
* And a change in the camera position may, in turn, affect what is culled.
*/
CULLED_BUT_NEEDED: 1 | 8,
/**
* Determines if a selection result indicates that this tile or its descendants were
* kicked from the render list. In other words, if it is RENDERED_AND_KICKED
* or REFINED_AND_KICKED.
*
* @param {TileSelectionResult} value The selection result to test.
* @returns {boolean} true if the tile was kicked, no matter if it was originally rendered or refined.
*/
wasKicked: function(value) {
return value >= TileSelectionResult.RENDERED_AND_KICKED;
},
/**
* Determines the original selection result prior to being kicked or CULLED_BUT_NEEDED.
* If the tile wasn't kicked or CULLED_BUT_NEEDED, the original value is returned.
* @param {TileSelectionResult} value The selection result.
* @returns {TileSelectionResult} The original selection result prior to kicking.
*/
originalResult: function(value) {
return value & 3;
},
/**
* Converts this selection result to a kick.
* @param {TileSelectionResult} value The original selection result.
* @returns {TileSelectionResult} The kicked form of the selection result.
*/
kick: function(value) {
return value | 4;
}
};
var TileSelectionResult_default = TileSelectionResult;
// packages/engine/Source/Scene/TerrainFillMesh.js
function TerrainFillMesh(tile) {
this.tile = tile;
this.frameLastUpdated = void 0;
this.westMeshes = [];
this.westTiles = [];
this.southMeshes = [];
this.southTiles = [];
this.eastMeshes = [];
this.eastTiles = [];
this.northMeshes = [];
this.northTiles = [];
this.southwestMesh = void 0;
this.southwestTile = void 0;
this.southeastMesh = void 0;
this.southeastTile = void 0;
this.northwestMesh = void 0;
this.northwestTile = void 0;
this.northeastMesh = void 0;
this.northeastTile = void 0;
this.changedThisFrame = true;
this.visitedFrame = void 0;
this.enqueuedFrame = void 0;
this.mesh = void 0;
this.vertexArray = void 0;
this.waterMaskTexture = void 0;
this.waterMaskTranslationAndScale = new Cartesian4_default();
}
TerrainFillMesh.prototype.update = function(tileProvider, frameState, vertexArraysToDestroy) {
if (this.changedThisFrame) {
createFillMesh(tileProvider, frameState, this.tile, vertexArraysToDestroy);
this.changedThisFrame = false;
}
};
TerrainFillMesh.prototype.destroy = function(vertexArraysToDestroy) {
this._destroyVertexArray(vertexArraysToDestroy);
if (defined_default(this.waterMaskTexture)) {
--this.waterMaskTexture.referenceCount;
if (this.waterMaskTexture.referenceCount === 0) {
this.waterMaskTexture.destroy();
}
this.waterMaskTexture = void 0;
}
return void 0;
};
TerrainFillMesh.prototype._destroyVertexArray = function(vertexArraysToDestroy) {
if (defined_default(this.vertexArray)) {
if (defined_default(vertexArraysToDestroy)) {
vertexArraysToDestroy.push(this.vertexArray);
} else {
GlobeSurfaceTile_default._freeVertexArray(this.vertexArray);
}
this.vertexArray = void 0;
}
};
var traversalQueueScratch = new Queue_default();
TerrainFillMesh.updateFillTiles = function(tileProvider, renderedTiles, frameState, vertexArraysToDestroy) {
const quadtree = tileProvider._quadtree;
const levelZeroTiles = quadtree._levelZeroTiles;
const lastSelectionFrameNumber = quadtree._lastSelectionFrameNumber;
const traversalQueue = traversalQueueScratch;
traversalQueue.clear();
for (let i = 0; i < renderedTiles.length; ++i) {
const renderedTile = renderedTiles[i];
if (defined_default(renderedTile.data.vertexArray)) {
traversalQueue.enqueue(renderedTiles[i]);
}
}
let tile = traversalQueue.dequeue();
while (tile !== void 0) {
const tileToWest = tile.findTileToWest(levelZeroTiles);
const tileToSouth = tile.findTileToSouth(levelZeroTiles);
const tileToEast = tile.findTileToEast(levelZeroTiles);
const tileToNorth = tile.findTileToNorth(levelZeroTiles);
visitRenderedTiles(
tileProvider,
frameState,
tile,
tileToWest,
lastSelectionFrameNumber,
TileEdge_default.EAST,
false,
traversalQueue,
vertexArraysToDestroy
);
visitRenderedTiles(
tileProvider,
frameState,
tile,
tileToSouth,
lastSelectionFrameNumber,
TileEdge_default.NORTH,
false,
traversalQueue,
vertexArraysToDestroy
);
visitRenderedTiles(
tileProvider,
frameState,
tile,
tileToEast,
lastSelectionFrameNumber,
TileEdge_default.WEST,
false,
traversalQueue,
vertexArraysToDestroy
);
visitRenderedTiles(
tileProvider,
frameState,
tile,
tileToNorth,
lastSelectionFrameNumber,
TileEdge_default.SOUTH,
false,
traversalQueue,
vertexArraysToDestroy
);
const tileToNorthwest = tileToWest.findTileToNorth(levelZeroTiles);
const tileToSouthwest = tileToWest.findTileToSouth(levelZeroTiles);
const tileToNortheast = tileToEast.findTileToNorth(levelZeroTiles);
const tileToSoutheast = tileToEast.findTileToSouth(levelZeroTiles);
visitRenderedTiles(
tileProvider,
frameState,
tile,
tileToNorthwest,
lastSelectionFrameNumber,
TileEdge_default.SOUTHEAST,
false,
traversalQueue,
vertexArraysToDestroy
);
visitRenderedTiles(
tileProvider,
frameState,
tile,
tileToNortheast,
lastSelectionFrameNumber,
TileEdge_default.SOUTHWEST,
false,
traversalQueue,
vertexArraysToDestroy
);
visitRenderedTiles(
tileProvider,
frameState,
tile,
tileToSouthwest,
lastSelectionFrameNumber,
TileEdge_default.NORTHEAST,
false,
traversalQueue,
vertexArraysToDestroy
);
visitRenderedTiles(
tileProvider,
frameState,
tile,
tileToSoutheast,
lastSelectionFrameNumber,
TileEdge_default.NORTHWEST,
false,
traversalQueue,
vertexArraysToDestroy
);
tile = traversalQueue.dequeue();
}
};
function visitRenderedTiles(tileProvider, frameState, sourceTile, startTile, currentFrameNumber, tileEdge, downOnly, traversalQueue, vertexArraysToDestroy) {
if (startTile === void 0) {
return;
}
let tile = startTile;
while (tile && (tile._lastSelectionResultFrame !== currentFrameNumber || TileSelectionResult_default.wasKicked(tile._lastSelectionResult) || TileSelectionResult_default.originalResult(tile._lastSelectionResult) === TileSelectionResult_default.CULLED)) {
if (downOnly) {
return;
}
const parent = tile.parent;
if (tileEdge >= TileEdge_default.NORTHWEST && parent !== void 0) {
switch (tileEdge) {
case TileEdge_default.NORTHWEST:
tile = tile === parent.northwestChild ? parent : void 0;
break;
case TileEdge_default.NORTHEAST:
tile = tile === parent.northeastChild ? parent : void 0;
break;
case TileEdge_default.SOUTHWEST:
tile = tile === parent.southwestChild ? parent : void 0;
break;
case TileEdge_default.SOUTHEAST:
tile = tile === parent.southeastChild ? parent : void 0;
break;
}
} else {
tile = parent;
}
}
if (tile === void 0) {
return;
}
if (tile._lastSelectionResult === TileSelectionResult_default.RENDERED) {
if (defined_default(tile.data.vertexArray)) {
return;
}
visitTile(
tileProvider,
frameState,
sourceTile,
tile,
tileEdge,
currentFrameNumber,
traversalQueue,
vertexArraysToDestroy
);
return;
}
if (TileSelectionResult_default.originalResult(startTile._lastSelectionResult) === TileSelectionResult_default.CULLED) {
return;
}
switch (tileEdge) {
case TileEdge_default.WEST:
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.northwestChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.southwestChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
break;
case TileEdge_default.EAST:
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.southeastChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.northeastChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
break;
case TileEdge_default.SOUTH:
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.southwestChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.southeastChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
break;
case TileEdge_default.NORTH:
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.northeastChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.northwestChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
break;
case TileEdge_default.NORTHWEST:
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.northwestChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
break;
case TileEdge_default.NORTHEAST:
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.northeastChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
break;
case TileEdge_default.SOUTHWEST:
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.southwestChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
break;
case TileEdge_default.SOUTHEAST:
visitRenderedTiles(
tileProvider,
frameState,
sourceTile,
startTile.southeastChild,
currentFrameNumber,
tileEdge,
true,
traversalQueue,
vertexArraysToDestroy
);
break;
default:
throw new DeveloperError_default("Invalid edge");
}
}
function visitTile(tileProvider, frameState, sourceTile, destinationTile, tileEdge, frameNumber, traversalQueue, vertexArraysToDestroy) {
const destinationSurfaceTile = destinationTile.data;
if (destinationSurfaceTile.fill === void 0) {
destinationSurfaceTile.fill = new TerrainFillMesh(destinationTile);
} else if (destinationSurfaceTile.fill.visitedFrame === frameNumber) {
return;
}
if (destinationSurfaceTile.fill.enqueuedFrame !== frameNumber) {
destinationSurfaceTile.fill.enqueuedFrame = frameNumber;
destinationSurfaceTile.fill.changedThisFrame = false;
traversalQueue.enqueue(destinationTile);
}
propagateEdge(
tileProvider,
frameState,
sourceTile,
destinationTile,
tileEdge,
vertexArraysToDestroy
);
}
function propagateEdge(tileProvider, frameState, sourceTile, destinationTile, tileEdge, vertexArraysToDestroy) {
const destinationFill = destinationTile.data.fill;
let sourceMesh;
const sourceFill = sourceTile.data.fill;
if (defined_default(sourceFill)) {
sourceFill.visitedFrame = frameState.frameNumber;
if (sourceFill.changedThisFrame) {
createFillMesh(
tileProvider,
frameState,
sourceTile,
vertexArraysToDestroy
);
sourceFill.changedThisFrame = false;
}
sourceMesh = sourceTile.data.fill.mesh;
} else {
sourceMesh = sourceTile.data.mesh;
}
let edgeMeshes;
let edgeTiles;
switch (tileEdge) {
case TileEdge_default.WEST:
edgeMeshes = destinationFill.westMeshes;
edgeTiles = destinationFill.westTiles;
break;
case TileEdge_default.SOUTH:
edgeMeshes = destinationFill.southMeshes;
edgeTiles = destinationFill.southTiles;
break;
case TileEdge_default.EAST:
edgeMeshes = destinationFill.eastMeshes;
edgeTiles = destinationFill.eastTiles;
break;
case TileEdge_default.NORTH:
edgeMeshes = destinationFill.northMeshes;
edgeTiles = destinationFill.northTiles;
break;
// Corners are simpler.
case TileEdge_default.NORTHWEST:
destinationFill.changedThisFrame = destinationFill.changedThisFrame || destinationFill.northwestMesh !== sourceMesh;
destinationFill.northwestMesh = sourceMesh;
destinationFill.northwestTile = sourceTile;
return;
case TileEdge_default.NORTHEAST:
destinationFill.changedThisFrame = destinationFill.changedThisFrame || destinationFill.northeastMesh !== sourceMesh;
destinationFill.northeastMesh = sourceMesh;
destinationFill.northeastTile = sourceTile;
return;
case TileEdge_default.SOUTHWEST:
destinationFill.changedThisFrame = destinationFill.changedThisFrame || destinationFill.southwestMesh !== sourceMesh;
destinationFill.southwestMesh = sourceMesh;
destinationFill.southwestTile = sourceTile;
return;
case TileEdge_default.SOUTHEAST:
destinationFill.changedThisFrame = destinationFill.changedThisFrame || destinationFill.southeastMesh !== sourceMesh;
destinationFill.southeastMesh = sourceMesh;
destinationFill.southeastTile = sourceTile;
return;
}
if (sourceTile.level <= destinationTile.level) {
destinationFill.changedThisFrame = destinationFill.changedThisFrame || edgeMeshes[0] !== sourceMesh || edgeMeshes.length !== 1;
edgeMeshes[0] = sourceMesh;
edgeTiles[0] = sourceTile;
edgeMeshes.length = 1;
edgeTiles.length = 1;
return;
}
let startIndex, endIndex, existingTile, existingRectangle;
const sourceRectangle = sourceTile.rectangle;
let epsilon;
const destinationRectangle = destinationTile.rectangle;
switch (tileEdge) {
case TileEdge_default.WEST:
epsilon = (destinationRectangle.north - destinationRectangle.south) * Math_default.EPSILON5;
for (startIndex = 0; startIndex < edgeTiles.length; ++startIndex) {
existingTile = edgeTiles[startIndex];
existingRectangle = existingTile.rectangle;
if (Math_default.greaterThan(
sourceRectangle.north,
existingRectangle.south,
epsilon
)) {
break;
}
}
for (endIndex = startIndex; endIndex < edgeTiles.length; ++endIndex) {
existingTile = edgeTiles[endIndex];
existingRectangle = existingTile.rectangle;
if (Math_default.greaterThanOrEquals(
sourceRectangle.south,
existingRectangle.north,
epsilon
)) {
break;
}
}
break;
case TileEdge_default.SOUTH:
epsilon = (destinationRectangle.east - destinationRectangle.west) * Math_default.EPSILON5;
for (startIndex = 0; startIndex < edgeTiles.length; ++startIndex) {
existingTile = edgeTiles[startIndex];
existingRectangle = existingTile.rectangle;
if (Math_default.lessThan(
sourceRectangle.west,
existingRectangle.east,
epsilon
)) {
break;
}
}
for (endIndex = startIndex; endIndex < edgeTiles.length; ++endIndex) {
existingTile = edgeTiles[endIndex];
existingRectangle = existingTile.rectangle;
if (Math_default.lessThanOrEquals(
sourceRectangle.east,
existingRectangle.west,
epsilon
)) {
break;
}
}
break;
case TileEdge_default.EAST:
epsilon = (destinationRectangle.north - destinationRectangle.south) * Math_default.EPSILON5;
for (startIndex = 0; startIndex < edgeTiles.length; ++startIndex) {
existingTile = edgeTiles[startIndex];
existingRectangle = existingTile.rectangle;
if (Math_default.lessThan(
sourceRectangle.south,
existingRectangle.north,
epsilon
)) {
break;
}
}
for (endIndex = startIndex; endIndex < edgeTiles.length; ++endIndex) {
existingTile = edgeTiles[endIndex];
existingRectangle = existingTile.rectangle;
if (Math_default.lessThanOrEquals(
sourceRectangle.north,
existingRectangle.south,
epsilon
)) {
break;
}
}
break;
case TileEdge_default.NORTH:
epsilon = (destinationRectangle.east - destinationRectangle.west) * Math_default.EPSILON5;
for (startIndex = 0; startIndex < edgeTiles.length; ++startIndex) {
existingTile = edgeTiles[startIndex];
existingRectangle = existingTile.rectangle;
if (Math_default.greaterThan(
sourceRectangle.east,
existingRectangle.west,
epsilon
)) {
break;
}
}
for (endIndex = startIndex; endIndex < edgeTiles.length; ++endIndex) {
existingTile = edgeTiles[endIndex];
existingRectangle = existingTile.rectangle;
if (Math_default.greaterThanOrEquals(
sourceRectangle.west,
existingRectangle.east,
epsilon
)) {
break;
}
}
break;
}
if (endIndex - startIndex === 1) {
destinationFill.changedThisFrame = destinationFill.changedThisFrame || edgeMeshes[startIndex] !== sourceMesh;
edgeMeshes[startIndex] = sourceMesh;
edgeTiles[startIndex] = sourceTile;
} else {
destinationFill.changedThisFrame = true;
edgeMeshes.splice(startIndex, endIndex - startIndex, sourceMesh);
edgeTiles.splice(startIndex, endIndex - startIndex, sourceTile);
}
}
var cartographicScratch4 = new Cartographic_default();
var centerCartographicScratch2 = new Cartographic_default();
var cartesianScratch = new Cartesian3_default();
var normalScratch5 = new Cartesian3_default();
var octEncodedNormalScratch = new Cartesian2_default();
var uvScratch2 = new Cartesian2_default();
var uvScratch = new Cartesian2_default();
function HeightAndNormal() {
this.height = 0;
this.encodedNormal = new Cartesian2_default();
}
function fillMissingCorner(fill, ellipsoid, u3, v3, corner, adjacentCorner1, adjacentCorner2, oppositeCorner, vertex) {
if (defined_default(corner)) {
return corner;
}
let height;
if (defined_default(adjacentCorner1) && defined_default(adjacentCorner2)) {
height = (adjacentCorner1.height + adjacentCorner2.height) * 0.5;
} else if (defined_default(adjacentCorner1)) {
height = adjacentCorner1.height;
} else if (defined_default(adjacentCorner2)) {
height = adjacentCorner2.height;
} else if (defined_default(oppositeCorner)) {
height = oppositeCorner.height;
} else {
const surfaceTile = fill.tile.data;
const tileBoundingRegion = surfaceTile.tileBoundingRegion;
let minimumHeight = 0;
let maximumHeight = 0;
if (defined_default(tileBoundingRegion)) {
minimumHeight = tileBoundingRegion.minimumHeight;
maximumHeight = tileBoundingRegion.maximumHeight;
}
height = (minimumHeight + maximumHeight) * 0.5;
}
getVertexWithHeightAtCorner(fill, ellipsoid, u3, v3, height, vertex);
return vertex;
}
var heightRangeScratch = {
minimumHeight: 0,
maximumHeight: 0
};
var scratchCenter8 = new Cartesian3_default();
var swVertexScratch = new HeightAndNormal();
var seVertexScratch = new HeightAndNormal();
var nwVertexScratch = new HeightAndNormal();
var neVertexScratch = new HeightAndNormal();
var heightmapBuffer = typeof Uint8Array !== "undefined" ? new Uint8Array(9 * 9) : void 0;
var scratchCreateMeshSyncOptions = {
tilingScheme: void 0,
x: 0,
y: 0,
level: 0,
exaggeration: 1,
exaggerationRelativeHeight: 0
};
function createFillMesh(tileProvider, frameState, tile, vertexArraysToDestroy) {
GlobeSurfaceTile_default.initialize(
tile,
tileProvider.terrainProvider,
tileProvider._imageryLayers
);
const surfaceTile = tile.data;
const fill = surfaceTile.fill;
const rectangle = tile.rectangle;
const exaggeration = frameState.verticalExaggeration;
const exaggerationRelativeHeight = frameState.verticalExaggerationRelativeHeight;
const hasExaggeration = exaggeration !== 1;
const ellipsoid = tile.tilingScheme.ellipsoid;
let nwCorner = getCorner(
fill,
ellipsoid,
0,
1,
fill.northwestTile,
fill.northwestMesh,
fill.northTiles,
fill.northMeshes,
fill.westTiles,
fill.westMeshes,
nwVertexScratch
);
let swCorner = getCorner(
fill,
ellipsoid,
0,
0,
fill.southwestTile,
fill.southwestMesh,
fill.westTiles,
fill.westMeshes,
fill.southTiles,
fill.southMeshes,
swVertexScratch
);
let seCorner = getCorner(
fill,
ellipsoid,
1,
0,
fill.southeastTile,
fill.southeastMesh,
fill.southTiles,
fill.southMeshes,
fill.eastTiles,
fill.eastMeshes,
seVertexScratch
);
let neCorner = getCorner(
fill,
ellipsoid,
1,
1,
fill.northeastTile,
fill.northeastMesh,
fill.eastTiles,
fill.eastMeshes,
fill.northTiles,
fill.northMeshes,
neVertexScratch
);
nwCorner = fillMissingCorner(
fill,
ellipsoid,
0,
1,
nwCorner,
swCorner,
neCorner,
seCorner,
nwVertexScratch
);
swCorner = fillMissingCorner(
fill,
ellipsoid,
0,
0,
swCorner,
nwCorner,
seCorner,
neCorner,
swVertexScratch
);
seCorner = fillMissingCorner(
fill,
ellipsoid,
1,
1,
seCorner,
swCorner,
neCorner,
nwCorner,
seVertexScratch
);
neCorner = fillMissingCorner(
fill,
ellipsoid,
1,
1,
neCorner,
seCorner,
nwCorner,
swCorner,
neVertexScratch
);
const southwestHeight = swCorner.height;
const southeastHeight = seCorner.height;
const northwestHeight = nwCorner.height;
const northeastHeight = neCorner.height;
let minimumHeight = Math.min(
southwestHeight,
southeastHeight,
northwestHeight,
northeastHeight
);
let maximumHeight = Math.max(
southwestHeight,
southeastHeight,
northwestHeight,
northeastHeight
);
const middleHeight = (minimumHeight + maximumHeight) * 0.5;
let i;
let len;
const geometricError = tileProvider.getLevelMaximumGeometricError(tile.level);
const minCutThroughRadius = ellipsoid.maximumRadius - geometricError;
let maxTileWidth = Math.acos(minCutThroughRadius / ellipsoid.maximumRadius) * 4;
maxTileWidth *= 1.5;
if (rectangle.width > maxTileWidth && maximumHeight - minimumHeight <= geometricError) {
const terrainData = new HeightmapTerrainData_default({
width: 9,
height: 9,
buffer: heightmapBuffer,
structure: {
// Use the maximum as the constant height so that this tile's skirt
// covers any cracks with adjacent tiles.
heightOffset: maximumHeight
}
});
const createMeshSyncOptions = scratchCreateMeshSyncOptions;
createMeshSyncOptions.tilingScheme = tile.tilingScheme;
createMeshSyncOptions.x = tile.x;
createMeshSyncOptions.y = tile.y;
createMeshSyncOptions.level = tile.level;
createMeshSyncOptions.exaggeration = exaggeration;
createMeshSyncOptions.exaggerationRelativeHeight = exaggerationRelativeHeight;
fill.mesh = terrainData._createMeshSync(createMeshSyncOptions);
} else {
const hasGeodeticSurfaceNormals = hasExaggeration;
const centerCartographic = Rectangle_default.center(
rectangle,
centerCartographicScratch2
);
centerCartographic.height = middleHeight;
const center = ellipsoid.cartographicToCartesian(
centerCartographic,
scratchCenter8
);
const encoding = new TerrainEncoding_default(
center,
void 0,
void 0,
void 0,
void 0,
true,
true,
hasGeodeticSurfaceNormals,
exaggeration,
exaggerationRelativeHeight
);
let maxVertexCount = 5;
let meshes;
meshes = fill.westMeshes;
for (i = 0, len = meshes.length; i < len; ++i) {
maxVertexCount += meshes[i].eastIndicesNorthToSouth.length;
}
meshes = fill.southMeshes;
for (i = 0, len = meshes.length; i < len; ++i) {
maxVertexCount += meshes[i].northIndicesWestToEast.length;
}
meshes = fill.eastMeshes;
for (i = 0, len = meshes.length; i < len; ++i) {
maxVertexCount += meshes[i].westIndicesSouthToNorth.length;
}
meshes = fill.northMeshes;
for (i = 0, len = meshes.length; i < len; ++i) {
maxVertexCount += meshes[i].southIndicesEastToWest.length;
}
const heightRange = heightRangeScratch;
heightRange.minimumHeight = minimumHeight;
heightRange.maximumHeight = maximumHeight;
const stride = encoding.stride;
let typedArray = new Float32Array(maxVertexCount * stride);
let nextIndex = 0;
const northwestIndex = nextIndex;
nextIndex = addVertexWithComputedPosition(
ellipsoid,
rectangle,
encoding,
typedArray,
nextIndex,
0,
1,
nwCorner.height,
nwCorner.encodedNormal,
1,
heightRange
);
nextIndex = addEdge(
fill,
ellipsoid,
encoding,
typedArray,
nextIndex,
fill.westTiles,
fill.westMeshes,
TileEdge_default.EAST,
heightRange
);
const southwestIndex = nextIndex;
nextIndex = addVertexWithComputedPosition(
ellipsoid,
rectangle,
encoding,
typedArray,
nextIndex,
0,
0,
swCorner.height,
swCorner.encodedNormal,
0,
heightRange
);
nextIndex = addEdge(
fill,
ellipsoid,
encoding,
typedArray,
nextIndex,
fill.southTiles,
fill.southMeshes,
TileEdge_default.NORTH,
heightRange
);
const southeastIndex = nextIndex;
nextIndex = addVertexWithComputedPosition(
ellipsoid,
rectangle,
encoding,
typedArray,
nextIndex,
1,
0,
seCorner.height,
seCorner.encodedNormal,
0,
heightRange
);
nextIndex = addEdge(
fill,
ellipsoid,
encoding,
typedArray,
nextIndex,
fill.eastTiles,
fill.eastMeshes,
TileEdge_default.WEST,
heightRange
);
const northeastIndex = nextIndex;
nextIndex = addVertexWithComputedPosition(
ellipsoid,
rectangle,
encoding,
typedArray,
nextIndex,
1,
1,
neCorner.height,
neCorner.encodedNormal,
1,
heightRange
);
nextIndex = addEdge(
fill,
ellipsoid,
encoding,
typedArray,
nextIndex,
fill.northTiles,
fill.northMeshes,
TileEdge_default.SOUTH,
heightRange
);
minimumHeight = heightRange.minimumHeight;
maximumHeight = heightRange.maximumHeight;
const obb = OrientedBoundingBox_default.fromRectangle(
rectangle,
minimumHeight,
maximumHeight,
tile.tilingScheme.ellipsoid
);
const southMercatorY = WebMercatorProjection_default.geodeticLatitudeToMercatorAngle(rectangle.south);
const oneOverMercatorHeight = 1 / (WebMercatorProjection_default.geodeticLatitudeToMercatorAngle(rectangle.north) - southMercatorY);
const centerWebMercatorT = (WebMercatorProjection_default.geodeticLatitudeToMercatorAngle(
centerCartographic.latitude
) - southMercatorY) * oneOverMercatorHeight;
const geodeticSurfaceNormal = ellipsoid.geodeticSurfaceNormalCartographic(
cartographicScratch4,
normalScratch5
);
const centerEncodedNormal = AttributeCompression_default.octEncode(
geodeticSurfaceNormal,
octEncodedNormalScratch
);
const centerIndex = nextIndex;
encoding.encode(
typedArray,
nextIndex * stride,
obb.center,
Cartesian2_default.fromElements(0.5, 0.5, uvScratch),
middleHeight,
centerEncodedNormal,
centerWebMercatorT,
geodeticSurfaceNormal
);
++nextIndex;
const vertexCount = nextIndex;
const bytesPerIndex = vertexCount < 256 ? 1 : 2;
const indexCount = (vertexCount - 1) * 3;
const indexDataBytes = indexCount * bytesPerIndex;
const availableBytesInBuffer = (typedArray.length - vertexCount * stride) * Float32Array.BYTES_PER_ELEMENT;
let indices;
if (availableBytesInBuffer >= indexDataBytes) {
const startIndex = vertexCount * stride * Float32Array.BYTES_PER_ELEMENT;
indices = vertexCount < 256 ? new Uint8Array(typedArray.buffer, startIndex, indexCount) : new Uint16Array(typedArray.buffer, startIndex, indexCount);
} else {
indices = vertexCount < 256 ? new Uint8Array(indexCount) : new Uint16Array(indexCount);
}
typedArray = new Float32Array(typedArray.buffer, 0, vertexCount * stride);
let indexOut = 0;
for (i = 0; i < vertexCount - 2; ++i) {
indices[indexOut++] = centerIndex;
indices[indexOut++] = i;
indices[indexOut++] = i + 1;
}
indices[indexOut++] = centerIndex;
indices[indexOut++] = i;
indices[indexOut++] = 0;
const westIndicesSouthToNorth = [];
for (i = southwestIndex; i >= northwestIndex; --i) {
westIndicesSouthToNorth.push(i);
}
const southIndicesEastToWest = [];
for (i = southeastIndex; i >= southwestIndex; --i) {
southIndicesEastToWest.push(i);
}
const eastIndicesNorthToSouth = [];
for (i = northeastIndex; i >= southeastIndex; --i) {
eastIndicesNorthToSouth.push(i);
}
const northIndicesWestToEast = [];
northIndicesWestToEast.push(0);
for (i = centerIndex - 1; i >= northeastIndex; --i) {
northIndicesWestToEast.push(i);
}
fill.mesh = new TerrainMesh_default(
encoding.center,
typedArray,
indices,
indexCount,
vertexCount,
minimumHeight,
maximumHeight,
BoundingSphere_default.fromOrientedBoundingBox(obb),
computeOccludeePoint(
tileProvider,
obb.center,
rectangle,
minimumHeight,
maximumHeight
),
encoding.stride,
obb,
encoding,
westIndicesSouthToNorth,
southIndicesEastToWest,
eastIndicesNorthToSouth,
northIndicesWestToEast
);
}
const context = frameState.context;
fill._destroyVertexArray(vertexArraysToDestroy);
fill.vertexArray = GlobeSurfaceTile_default._createVertexArrayForMesh(
context,
fill.mesh
);
surfaceTile.processImagery(
tile,
tileProvider.terrainProvider,
frameState,
true
);
const oldTexture = fill.waterMaskTexture;
fill.waterMaskTexture = void 0;
if (tileProvider.terrainProvider.hasWaterMask) {
const waterSourceTile = surfaceTile._findAncestorTileWithTerrainData(tile);
if (defined_default(waterSourceTile) && defined_default(waterSourceTile.data.waterMaskTexture)) {
fill.waterMaskTexture = waterSourceTile.data.waterMaskTexture;
++fill.waterMaskTexture.referenceCount;
surfaceTile._computeWaterMaskTranslationAndScale(
tile,
waterSourceTile,
fill.waterMaskTranslationAndScale
);
}
}
if (defined_default(oldTexture)) {
--oldTexture.referenceCount;
if (oldTexture.referenceCount === 0) {
oldTexture.destroy();
}
}
}
function addVertexWithComputedPosition(ellipsoid, rectangle, encoding, buffer2, index, u3, v3, height, encodedNormal, webMercatorT, heightRange) {
const cartographic2 = cartographicScratch4;
cartographic2.longitude = Math_default.lerp(rectangle.west, rectangle.east, u3);
cartographic2.latitude = Math_default.lerp(rectangle.south, rectangle.north, v3);
cartographic2.height = height;
const position = ellipsoid.cartographicToCartesian(
cartographic2,
cartesianScratch
);
let geodeticSurfaceNormal;
if (encoding.hasGeodeticSurfaceNormals) {
geodeticSurfaceNormal = ellipsoid.geodeticSurfaceNormal(
position,
normalScratch5
);
}
const uv = uvScratch2;
uv.x = u3;
uv.y = v3;
encoding.encode(
buffer2,
index * encoding.stride,
position,
uv,
height,
encodedNormal,
webMercatorT,
geodeticSurfaceNormal
);
heightRange.minimumHeight = Math.min(heightRange.minimumHeight, height);
heightRange.maximumHeight = Math.max(heightRange.maximumHeight, height);
return index + 1;
}
var sourceRectangleScratch = new Rectangle_default();
function transformTextureCoordinates(sourceTile, targetTile, coordinates, result) {
let sourceRectangle = sourceTile.rectangle;
const targetRectangle = targetTile.rectangle;
if (targetTile.x === 0 && coordinates.x === 1 && sourceTile.x === sourceTile.tilingScheme.getNumberOfXTilesAtLevel(sourceTile.level) - 1) {
sourceRectangle = Rectangle_default.clone(
sourceTile.rectangle,
sourceRectangleScratch
);
sourceRectangle.west -= Math_default.TWO_PI;
sourceRectangle.east -= Math_default.TWO_PI;
} else if (sourceTile.x === 0 && coordinates.x === 0 && targetTile.x === targetTile.tilingScheme.getNumberOfXTilesAtLevel(targetTile.level) - 1) {
sourceRectangle = Rectangle_default.clone(
sourceTile.rectangle,
sourceRectangleScratch
);
sourceRectangle.west += Math_default.TWO_PI;
sourceRectangle.east += Math_default.TWO_PI;
}
const sourceWidth = sourceRectangle.east - sourceRectangle.west;
const umin = (targetRectangle.west - sourceRectangle.west) / sourceWidth;
const umax = (targetRectangle.east - sourceRectangle.west) / sourceWidth;
const sourceHeight = sourceRectangle.north - sourceRectangle.south;
const vmin = (targetRectangle.south - sourceRectangle.south) / sourceHeight;
const vmax = (targetRectangle.north - sourceRectangle.south) / sourceHeight;
let u3 = (coordinates.x - umin) / (umax - umin);
let v3 = (coordinates.y - vmin) / (vmax - vmin);
if (Math.abs(u3) < Math.EPSILON5) {
u3 = 0;
} else if (Math.abs(u3 - 1) < Math.EPSILON5) {
u3 = 1;
}
if (Math.abs(v3) < Math.EPSILON5) {
v3 = 0;
} else if (Math.abs(v3 - 1) < Math.EPSILON5) {
v3 = 1;
}
result.x = u3;
result.y = v3;
return result;
}
var encodedNormalScratch = new Cartesian2_default();
function getVertexFromTileAtCorner(sourceMesh, sourceIndex, u3, v3, vertex) {
const sourceEncoding = sourceMesh.encoding;
const sourceVertices = sourceMesh.vertices;
vertex.height = sourceEncoding.decodeHeight(sourceVertices, sourceIndex);
if (sourceEncoding.hasVertexNormals) {
sourceEncoding.getOctEncodedNormal(
sourceVertices,
sourceIndex,
vertex.encodedNormal
);
} else {
const normal2 = vertex.encodedNormal;
normal2.x = 0;
normal2.y = 0;
}
}
var encodedNormalScratch2 = new Cartesian2_default();
var cartesianScratch2 = new Cartesian3_default();
function getInterpolatedVertexAtCorner(ellipsoid, sourceTile, targetTile, sourceMesh, previousIndex, nextIndex, u3, v3, interpolateU, vertex) {
const sourceEncoding = sourceMesh.encoding;
const sourceVertices = sourceMesh.vertices;
const previousUv = transformTextureCoordinates(
sourceTile,
targetTile,
sourceEncoding.decodeTextureCoordinates(
sourceVertices,
previousIndex,
uvScratch
),
uvScratch
);
const nextUv = transformTextureCoordinates(
sourceTile,
targetTile,
sourceEncoding.decodeTextureCoordinates(
sourceVertices,
nextIndex,
uvScratch2
),
uvScratch2
);
let ratio;
if (interpolateU) {
ratio = (u3 - previousUv.x) / (nextUv.x - previousUv.x);
} else {
ratio = (v3 - previousUv.y) / (nextUv.y - previousUv.y);
}
const height1 = sourceEncoding.decodeHeight(sourceVertices, previousIndex);
const height2 = sourceEncoding.decodeHeight(sourceVertices, nextIndex);
const targetRectangle = targetTile.rectangle;
cartographicScratch4.longitude = Math_default.lerp(
targetRectangle.west,
targetRectangle.east,
u3
);
cartographicScratch4.latitude = Math_default.lerp(
targetRectangle.south,
targetRectangle.north,
v3
);
vertex.height = cartographicScratch4.height = Math_default.lerp(
height1,
height2,
ratio
);
let normal2;
if (sourceEncoding.hasVertexNormals) {
const encodedNormal1 = sourceEncoding.getOctEncodedNormal(
sourceVertices,
previousIndex,
encodedNormalScratch
);
const encodedNormal2 = sourceEncoding.getOctEncodedNormal(
sourceVertices,
nextIndex,
encodedNormalScratch2
);
const normal1 = AttributeCompression_default.octDecode(
encodedNormal1.x,
encodedNormal1.y,
cartesianScratch
);
const normal22 = AttributeCompression_default.octDecode(
encodedNormal2.x,
encodedNormal2.y,
cartesianScratch2
);
normal2 = Cartesian3_default.lerp(normal1, normal22, ratio, cartesianScratch);
Cartesian3_default.normalize(normal2, normal2);
AttributeCompression_default.octEncode(normal2, vertex.encodedNormal);
} else {
normal2 = ellipsoid.geodeticSurfaceNormalCartographic(
cartographicScratch4,
cartesianScratch
);
AttributeCompression_default.octEncode(normal2, vertex.encodedNormal);
}
}
function getVertexWithHeightAtCorner(terrainFillMesh, ellipsoid, u3, v3, height, vertex) {
vertex.height = height;
const normal2 = ellipsoid.geodeticSurfaceNormalCartographic(
cartographicScratch4,
cartesianScratch
);
AttributeCompression_default.octEncode(normal2, vertex.encodedNormal);
}
function getCorner(terrainFillMesh, ellipsoid, u3, v3, cornerTile, cornerMesh, previousEdgeTiles, previousEdgeMeshes, nextEdgeTiles, nextEdgeMeshes, vertex) {
const gotCorner = getCornerFromEdge(
terrainFillMesh,
ellipsoid,
previousEdgeMeshes,
previousEdgeTiles,
false,
u3,
v3,
vertex
) || getCornerFromEdge(
terrainFillMesh,
ellipsoid,
nextEdgeMeshes,
nextEdgeTiles,
true,
u3,
v3,
vertex
);
if (gotCorner) {
return vertex;
}
let vertexIndex;
if (meshIsUsable(cornerTile, cornerMesh)) {
if (u3 === 0) {
if (v3 === 0) {
vertexIndex = cornerMesh.eastIndicesNorthToSouth[0];
} else {
vertexIndex = cornerMesh.southIndicesEastToWest[0];
}
} else if (v3 === 0) {
vertexIndex = cornerMesh.northIndicesWestToEast[0];
} else {
vertexIndex = cornerMesh.westIndicesSouthToNorth[0];
}
getVertexFromTileAtCorner(cornerMesh, vertexIndex, u3, v3, vertex);
return vertex;
}
let height;
if (u3 === 0) {
if (v3 === 0) {
height = getClosestHeightToCorner(
terrainFillMesh.westMeshes,
terrainFillMesh.westTiles,
TileEdge_default.EAST,
terrainFillMesh.southMeshes,
terrainFillMesh.southTiles,
TileEdge_default.NORTH,
u3,
v3
);
} else {
height = getClosestHeightToCorner(
terrainFillMesh.northMeshes,
terrainFillMesh.northTiles,
TileEdge_default.SOUTH,
terrainFillMesh.westMeshes,
terrainFillMesh.westTiles,
TileEdge_default.EAST,
u3,
v3
);
}
} else if (v3 === 0) {
height = getClosestHeightToCorner(
terrainFillMesh.southMeshes,
terrainFillMesh.southTiles,
TileEdge_default.NORTH,
terrainFillMesh.eastMeshes,
terrainFillMesh.eastTiles,
TileEdge_default.WEST,
u3,
v3
);
} else {
height = getClosestHeightToCorner(
terrainFillMesh.eastMeshes,
terrainFillMesh.eastTiles,
TileEdge_default.WEST,
terrainFillMesh.northMeshes,
terrainFillMesh.northTiles,
TileEdge_default.SOUTH,
u3,
v3
);
}
if (defined_default(height)) {
getVertexWithHeightAtCorner(
terrainFillMesh,
ellipsoid,
u3,
v3,
height,
vertex
);
return vertex;
}
return void 0;
}
function getClosestHeightToCorner(previousMeshes, previousTiles, previousEdge, nextMeshes, nextTiles, nextEdge, u3, v3) {
const height1 = getNearestHeightOnEdge(
previousMeshes,
previousTiles,
false,
previousEdge,
u3,
v3
);
const height2 = getNearestHeightOnEdge(
nextMeshes,
nextTiles,
true,
nextEdge,
u3,
v3
);
if (defined_default(height1) && defined_default(height2)) {
return (height1 + height2) * 0.5;
} else if (defined_default(height1)) {
return height1;
}
return height2;
}
function addEdge(terrainFillMesh, ellipsoid, encoding, typedArray, nextIndex, edgeTiles, edgeMeshes, tileEdge, heightRange) {
for (let i = 0; i < edgeTiles.length; ++i) {
nextIndex = addEdgeMesh(
terrainFillMesh,
ellipsoid,
encoding,
typedArray,
nextIndex,
edgeTiles[i],
edgeMeshes[i],
tileEdge,
heightRange
);
}
return nextIndex;
}
function addEdgeMesh(terrainFillMesh, ellipsoid, encoding, typedArray, nextIndex, edgeTile, edgeMesh, tileEdge, heightRange) {
let sourceRectangle = edgeTile.rectangle;
if (tileEdge === TileEdge_default.EAST && terrainFillMesh.tile.x === 0) {
sourceRectangle = Rectangle_default.clone(
edgeTile.rectangle,
sourceRectangleScratch
);
sourceRectangle.west -= Math_default.TWO_PI;
sourceRectangle.east -= Math_default.TWO_PI;
} else if (tileEdge === TileEdge_default.WEST && edgeTile.x === 0) {
sourceRectangle = Rectangle_default.clone(
edgeTile.rectangle,
sourceRectangleScratch
);
sourceRectangle.west += Math_default.TWO_PI;
sourceRectangle.east += Math_default.TWO_PI;
}
const targetRectangle = terrainFillMesh.tile.rectangle;
let lastU;
let lastV;
if (nextIndex > 0) {
encoding.decodeTextureCoordinates(typedArray, nextIndex - 1, uvScratch);
lastU = uvScratch.x;
lastV = uvScratch.y;
}
let indices;
let compareU;
switch (tileEdge) {
case TileEdge_default.WEST:
indices = edgeMesh.westIndicesSouthToNorth;
compareU = false;
break;
case TileEdge_default.NORTH:
indices = edgeMesh.northIndicesWestToEast;
compareU = true;
break;
case TileEdge_default.EAST:
indices = edgeMesh.eastIndicesNorthToSouth;
compareU = false;
break;
case TileEdge_default.SOUTH:
indices = edgeMesh.southIndicesEastToWest;
compareU = true;
break;
}
const sourceTile = edgeTile;
const targetTile = terrainFillMesh.tile;
const sourceEncoding = edgeMesh.encoding;
const sourceVertices = edgeMesh.vertices;
const targetStride = encoding.stride;
let southMercatorY;
let oneOverMercatorHeight;
if (sourceEncoding.hasWebMercatorT) {
southMercatorY = WebMercatorProjection_default.geodeticLatitudeToMercatorAngle(
targetRectangle.south
);
oneOverMercatorHeight = 1 / (WebMercatorProjection_default.geodeticLatitudeToMercatorAngle(
targetRectangle.north
) - southMercatorY);
}
for (let i = 0; i < indices.length; ++i) {
const index = indices[i];
const uv = sourceEncoding.decodeTextureCoordinates(
sourceVertices,
index,
uvScratch
);
transformTextureCoordinates(sourceTile, targetTile, uv, uv);
const u3 = uv.x;
const v3 = uv.y;
const uOrV = compareU ? u3 : v3;
if (uOrV < 0 || uOrV > 1) {
continue;
}
if (Math.abs(u3 - lastU) < Math_default.EPSILON5 && Math.abs(v3 - lastV) < Math_default.EPSILON5) {
continue;
}
const nearlyEdgeU = Math.abs(u3) < Math_default.EPSILON5 || Math.abs(u3 - 1) < Math_default.EPSILON5;
const nearlyEdgeV = Math.abs(v3) < Math_default.EPSILON5 || Math.abs(v3 - 1) < Math_default.EPSILON5;
if (nearlyEdgeU && nearlyEdgeV) {
continue;
}
const position = sourceEncoding.decodePosition(
sourceVertices,
index,
cartesianScratch
);
const height = sourceEncoding.decodeHeight(sourceVertices, index);
let normal2;
if (sourceEncoding.hasVertexNormals) {
normal2 = sourceEncoding.getOctEncodedNormal(
sourceVertices,
index,
octEncodedNormalScratch
);
} else {
normal2 = octEncodedNormalScratch;
normal2.x = 0;
normal2.y = 0;
}
let webMercatorT = v3;
if (sourceEncoding.hasWebMercatorT) {
const latitude = Math_default.lerp(
targetRectangle.south,
targetRectangle.north,
v3
);
webMercatorT = (WebMercatorProjection_default.geodeticLatitudeToMercatorAngle(latitude) - southMercatorY) * oneOverMercatorHeight;
}
let geodeticSurfaceNormal;
if (encoding.hasGeodeticSurfaceNormals) {
geodeticSurfaceNormal = ellipsoid.geodeticSurfaceNormal(
position,
normalScratch5
);
}
encoding.encode(
typedArray,
nextIndex * targetStride,
position,
uv,
height,
normal2,
webMercatorT,
geodeticSurfaceNormal
);
heightRange.minimumHeight = Math.min(heightRange.minimumHeight, height);
heightRange.maximumHeight = Math.max(heightRange.maximumHeight, height);
++nextIndex;
}
return nextIndex;
}
function getNearestHeightOnEdge(meshes, tiles, isNext, edge, u3, v3) {
let meshStart;
let meshEnd;
let meshStep;
if (isNext) {
meshStart = 0;
meshEnd = meshes.length;
meshStep = 1;
} else {
meshStart = meshes.length - 1;
meshEnd = -1;
meshStep = -1;
}
for (let meshIndex = meshStart; meshIndex !== meshEnd; meshIndex += meshStep) {
const mesh = meshes[meshIndex];
const tile = tiles[meshIndex];
if (!meshIsUsable(tile, mesh)) {
continue;
}
let indices;
switch (edge) {
case TileEdge_default.WEST:
indices = mesh.westIndicesSouthToNorth;
break;
case TileEdge_default.SOUTH:
indices = mesh.southIndicesEastToWest;
break;
case TileEdge_default.EAST:
indices = mesh.eastIndicesNorthToSouth;
break;
case TileEdge_default.NORTH:
indices = mesh.northIndicesWestToEast;
break;
}
const index = indices[isNext ? 0 : indices.length - 1];
if (defined_default(index)) {
return mesh.encoding.decodeHeight(mesh.vertices, index);
}
}
return void 0;
}
function meshIsUsable(tile, mesh) {
return defined_default(mesh) && (!defined_default(tile.data.fill) || !tile.data.fill.changedThisFrame);
}
function getCornerFromEdge(terrainFillMesh, ellipsoid, edgeMeshes, edgeTiles, isNext, u3, v3, vertex) {
let edgeVertices;
let compareU;
let increasing;
let vertexIndexIndex;
let vertexIndex;
const sourceTile = edgeTiles[isNext ? 0 : edgeMeshes.length - 1];
const sourceMesh = edgeMeshes[isNext ? 0 : edgeMeshes.length - 1];
if (meshIsUsable(sourceTile, sourceMesh)) {
if (u3 === 0) {
if (v3 === 0) {
edgeVertices = isNext ? sourceMesh.northIndicesWestToEast : sourceMesh.eastIndicesNorthToSouth;
compareU = isNext;
increasing = isNext;
} else {
edgeVertices = isNext ? sourceMesh.eastIndicesNorthToSouth : sourceMesh.southIndicesEastToWest;
compareU = !isNext;
increasing = false;
}
} else if (v3 === 0) {
edgeVertices = isNext ? sourceMesh.westIndicesSouthToNorth : sourceMesh.northIndicesWestToEast;
compareU = !isNext;
increasing = true;
} else {
edgeVertices = isNext ? sourceMesh.southIndicesEastToWest : sourceMesh.westIndicesSouthToNorth;
compareU = isNext;
increasing = !isNext;
}
if (edgeVertices.length > 0) {
vertexIndexIndex = isNext ? 0 : edgeVertices.length - 1;
vertexIndex = edgeVertices[vertexIndexIndex];
sourceMesh.encoding.decodeTextureCoordinates(
sourceMesh.vertices,
vertexIndex,
uvScratch
);
const targetUv = transformTextureCoordinates(
sourceTile,
terrainFillMesh.tile,
uvScratch,
uvScratch
);
if (targetUv.x === u3 && targetUv.y === v3) {
getVertexFromTileAtCorner(sourceMesh, vertexIndex, u3, v3, vertex);
return true;
}
vertexIndexIndex = binarySearch_default(
edgeVertices,
compareU ? u3 : v3,
function(vertexIndex2, textureCoordinate) {
sourceMesh.encoding.decodeTextureCoordinates(
sourceMesh.vertices,
vertexIndex2,
uvScratch
);
const targetUv2 = transformTextureCoordinates(
sourceTile,
terrainFillMesh.tile,
uvScratch,
uvScratch
);
if (increasing) {
if (compareU) {
return targetUv2.x - u3;
}
return targetUv2.y - v3;
} else if (compareU) {
return u3 - targetUv2.x;
}
return v3 - targetUv2.y;
}
);
if (vertexIndexIndex < 0) {
vertexIndexIndex = ~vertexIndexIndex;
if (vertexIndexIndex > 0 && vertexIndexIndex < edgeVertices.length) {
getInterpolatedVertexAtCorner(
ellipsoid,
sourceTile,
terrainFillMesh.tile,
sourceMesh,
edgeVertices[vertexIndexIndex - 1],
edgeVertices[vertexIndexIndex],
u3,
v3,
compareU,
vertex
);
return true;
}
} else {
getVertexFromTileAtCorner(
sourceMesh,
edgeVertices[vertexIndexIndex],
u3,
v3,
vertex
);
return true;
}
}
}
return false;
}
var cornerPositionsScratch = [
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default()
];
function computeOccludeePoint(tileProvider, center, rectangle, minimumHeight, maximumHeight, result) {
const ellipsoidalOccluder = tileProvider.quadtree._occluders.ellipsoid;
const ellipsoid = ellipsoidalOccluder.ellipsoid;
const cornerPositions = cornerPositionsScratch;
Cartesian3_default.fromRadians(
rectangle.west,
rectangle.south,
maximumHeight,
ellipsoid,
cornerPositions[0]
);
Cartesian3_default.fromRadians(
rectangle.east,
rectangle.south,
maximumHeight,
ellipsoid,
cornerPositions[1]
);
Cartesian3_default.fromRadians(
rectangle.west,
rectangle.north,
maximumHeight,
ellipsoid,
cornerPositions[2]
);
Cartesian3_default.fromRadians(
rectangle.east,
rectangle.north,
maximumHeight,
ellipsoid,
cornerPositions[3]
);
return ellipsoidalOccluder.computeHorizonCullingPointPossiblyUnderEllipsoid(
center,
cornerPositions,
minimumHeight,
result
);
}
var TerrainFillMesh_default = TerrainFillMesh;
// packages/engine/Source/Scene/GlobeSurfaceTileProvider.js
function GlobeSurfaceTileProvider(options) {
if (!defined_default(options)) {
throw new DeveloperError_default("options is required.");
}
if (!defined_default(options.terrainProvider)) {
throw new DeveloperError_default("options.terrainProvider is required.");
} else if (!defined_default(options.imageryLayers)) {
throw new DeveloperError_default("options.imageryLayers is required.");
} else if (!defined_default(options.surfaceShaderSet)) {
throw new DeveloperError_default("options.surfaceShaderSet is required.");
}
this.lightingFadeOutDistance = 65e5;
this.lightingFadeInDistance = 9e6;
this.hasWaterMask = false;
this.showWaterEffect = false;
this.oceanNormalMap = void 0;
this.zoomedOutOceanSpecularIntensity = 0.5;
this.enableLighting = false;
this.dynamicAtmosphereLighting = false;
this.dynamicAtmosphereLightingFromSun = false;
this.showGroundAtmosphere = false;
this.shadows = ShadowMode_default.RECEIVE_ONLY;
this.vertexShadowDarkness = 0.3;
this.fillHighlightColor = void 0;
this.hueShift = 0;
this.saturationShift = 0;
this.brightnessShift = 0;
this.showSkirts = true;
this.backFaceCulling = true;
this.undergroundColor = void 0;
this.undergroundColorAlphaByDistance = void 0;
this.lambertDiffuseMultiplier = 0;
this.materialUniformMap = void 0;
this._materialUniformMap = void 0;
this._quadtree = void 0;
this._terrainProvider = options.terrainProvider;
this._imageryLayers = options.imageryLayers;
this._surfaceShaderSet = options.surfaceShaderSet;
this._renderState = void 0;
this._blendRenderState = void 0;
this._disableCullingRenderState = void 0;
this._disableCullingBlendRenderState = void 0;
this._errorEvent = new Event_default();
this._removeLayerAddedListener = this._imageryLayers.layerAdded.addEventListener(
GlobeSurfaceTileProvider.prototype._onLayerAdded,
this
);
this._removeLayerRemovedListener = this._imageryLayers.layerRemoved.addEventListener(
GlobeSurfaceTileProvider.prototype._onLayerRemoved,
this
);
this._removeLayerMovedListener = this._imageryLayers.layerMoved.addEventListener(
GlobeSurfaceTileProvider.prototype._onLayerMoved,
this
);
this._removeLayerShownListener = this._imageryLayers.layerShownOrHidden.addEventListener(
GlobeSurfaceTileProvider.prototype._onLayerShownOrHidden,
this
);
this._imageryLayersUpdatedEvent = new Event_default();
this._layerOrderChanged = false;
this._tilesToRenderByTextureCount = [];
this._drawCommands = [];
this._uniformMaps = [];
this._usedDrawCommands = 0;
this._vertexArraysToDestroy = [];
this._debug = {
wireframe: false,
boundingSphereTile: void 0
};
this._baseColor = void 0;
this._firstPassInitialColor = void 0;
this.baseColor = new Color_default(0, 0, 0.5, 1);
this._clippingPlanes = void 0;
this._clippingPolygons = void 0;
this.cartographicLimitRectangle = Rectangle_default.clone(Rectangle_default.MAX_VALUE);
this._hasLoadedTilesThisFrame = false;
this._hasFillTilesThisFrame = false;
this._oldVerticalExaggeration = void 0;
this._oldVerticalExaggerationRelativeHeight = void 0;
}
Object.defineProperties(GlobeSurfaceTileProvider.prototype, {
/**
* Gets or sets the color of the globe when no imagery is available.
* @memberof GlobeSurfaceTileProvider.prototype
* @type {Color}
*/
baseColor: {
get: function() {
return this._baseColor;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
this._baseColor = value;
this._firstPassInitialColor = Cartesian4_default.fromColor(
value,
this._firstPassInitialColor
);
}
},
/**
* Gets or sets the {@link QuadtreePrimitive} for which this provider is
* providing tiles. This property may be undefined if the provider is not yet associated
* with a {@link QuadtreePrimitive}.
* @memberof GlobeSurfaceTileProvider.prototype
* @type {QuadtreePrimitive}
*/
quadtree: {
get: function() {
return this._quadtree;
},
set: function(value) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required.");
}
this._quadtree = value;
}
},
/**
* Gets the tiling scheme used by the provider.
* @memberof GlobeSurfaceTileProvider.prototype
* @type {TilingScheme}
*/
tilingScheme: {
get: function() {
if (!defined_default(this._terrainProvider)) {
return void 0;
}
return this._terrainProvider.tilingScheme;
}
},
/**
* Gets an event that is raised when the geometry provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof GlobeSurfaceTileProvider.prototype
* @type {Event}
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets an event that is raised when an imagery layer is added, shown, hidden, moved, or removed.
* @memberof GlobeSurfaceTileProvider.prototype
* @type {Event}
*/
imageryLayersUpdatedEvent: {
get: function() {
return this._imageryLayersUpdatedEvent;
}
},
/**
* Gets or sets the terrain provider that describes the surface geometry.
* @memberof GlobeSurfaceTileProvider.prototype
* @type {TerrainProvider}
*/
terrainProvider: {
get: function() {
return this._terrainProvider;
},
set: function(terrainProvider) {
if (this._terrainProvider === terrainProvider) {
return;
}
this._terrainProvider = terrainProvider;
if (defined_default(this._quadtree)) {
this._quadtree.invalidateAllTiles();
}
}
},
/**
* The {@link ClippingPlaneCollection} used to selectively disable rendering.
*
* @type {ClippingPlaneCollection}
*
* @private
*/
clippingPlanes: {
get: function() {
return this._clippingPlanes;
},
set: function(value) {
ClippingPlaneCollection_default.setOwner(value, this, "_clippingPlanes");
}
},
/**
* The {@link ClippingPolygonCollection} used to selectively disable rendering inside or outside a list of polygons.
*
* @type {ClippingPolygonCollection}
*
* @private
*/
clippingPolygons: {
get: function() {
return this._clippingPolygons;
},
set: function(value) {
ClippingPolygonCollection_default.setOwner(value, this, "_clippingPolygons");
}
}
});
function sortTileImageryByLayerIndex(a3, b) {
let aImagery = a3.loadingImagery;
if (!defined_default(aImagery)) {
aImagery = a3.readyImagery;
}
let bImagery = b.loadingImagery;
if (!defined_default(bImagery)) {
bImagery = b.readyImagery;
}
return aImagery.imageryLayer._layerIndex - bImagery.imageryLayer._layerIndex;
}
GlobeSurfaceTileProvider.prototype.update = function(frameState) {
this._imageryLayers._update();
};
function updateCredits(surface, frameState) {
const creditDisplay = frameState.creditDisplay;
const terrainProvider = surface._terrainProvider;
if (defined_default(terrainProvider) && defined_default(terrainProvider.credit)) {
creditDisplay.addCreditToNextFrame(terrainProvider.credit);
}
const imageryLayers = surface._imageryLayers;
for (let i = 0, len = imageryLayers.length; i < len; ++i) {
const layer = imageryLayers.get(i);
if (layer.ready && layer.show && defined_default(layer.imageryProvider.credit)) {
creditDisplay.addCreditToNextFrame(layer.imageryProvider.credit);
}
}
}
GlobeSurfaceTileProvider.prototype.initialize = function(frameState) {
this._imageryLayers.queueReprojectionCommands(frameState);
if (this._layerOrderChanged) {
this._layerOrderChanged = false;
this._quadtree.forEachLoadedTile(function(tile) {
tile.data.imagery.sort(sortTileImageryByLayerIndex);
});
}
updateCredits(this, frameState);
const vertexArraysToDestroy = this._vertexArraysToDestroy;
const length2 = vertexArraysToDestroy.length;
for (let j = 0; j < length2; ++j) {
GlobeSurfaceTile_default._freeVertexArray(vertexArraysToDestroy[j]);
}
vertexArraysToDestroy.length = 0;
};
GlobeSurfaceTileProvider.prototype.beginUpdate = function(frameState) {
const tilesToRenderByTextureCount = this._tilesToRenderByTextureCount;
for (let i = 0, len = tilesToRenderByTextureCount.length; i < len; ++i) {
const tiles = tilesToRenderByTextureCount[i];
if (defined_default(tiles)) {
tiles.length = 0;
}
}
const clippingPlanes = this._clippingPlanes;
if (defined_default(clippingPlanes) && clippingPlanes.enabled) {
clippingPlanes.update(frameState);
}
const clippingPolygons = this._clippingPolygons;
if (defined_default(clippingPolygons) && clippingPolygons.enabled) {
clippingPolygons.update(frameState);
clippingPolygons.queueCommands(frameState);
}
this._usedDrawCommands = 0;
this._hasLoadedTilesThisFrame = false;
this._hasFillTilesThisFrame = false;
};
GlobeSurfaceTileProvider.prototype.endUpdate = function(frameState) {
if (!defined_default(this._renderState)) {
this._renderState = RenderState_default.fromCache({
// Write color and depth
cull: {
enabled: true
},
depthTest: {
enabled: true,
func: DepthFunction_default.LESS
}
});
this._blendRenderState = RenderState_default.fromCache({
// Write color and depth
cull: {
enabled: true
},
depthTest: {
enabled: true,
func: DepthFunction_default.LESS_OR_EQUAL
},
blending: BlendingState_default.ALPHA_BLEND
});
let rs = clone_default(this._renderState, true);
rs.cull.enabled = false;
this._disableCullingRenderState = RenderState_default.fromCache(rs);
rs = clone_default(this._blendRenderState, true);
rs.cull.enabled = false;
this._disableCullingBlendRenderState = RenderState_default.fromCache(rs);
}
if (this._hasFillTilesThisFrame && this._hasLoadedTilesThisFrame) {
TerrainFillMesh_default.updateFillTiles(
this,
this._quadtree._tilesToRender,
frameState,
this._vertexArraysToDestroy
);
}
const quadtree = this.quadtree;
const exaggeration = frameState.verticalExaggeration;
const exaggerationRelativeHeight = frameState.verticalExaggerationRelativeHeight;
const exaggerationChanged = this._oldVerticalExaggeration !== exaggeration || this._oldVerticalExaggerationRelativeHeight !== exaggerationRelativeHeight;
this._oldVerticalExaggeration = exaggeration;
this._oldVerticalExaggerationRelativeHeight = exaggerationRelativeHeight;
if (exaggerationChanged) {
quadtree.forEachLoadedTile(function(tile) {
const surfaceTile = tile.data;
surfaceTile.updateExaggeration(tile, frameState, quadtree);
});
}
const tilesToRenderByTextureCount = this._tilesToRenderByTextureCount;
for (let textureCountIndex = 0, textureCountLength = tilesToRenderByTextureCount.length; textureCountIndex < textureCountLength; ++textureCountIndex) {
const tilesToRender = tilesToRenderByTextureCount[textureCountIndex];
if (!defined_default(tilesToRender)) {
continue;
}
for (let tileIndex = 0, tileLength = tilesToRender.length; tileIndex < tileLength; ++tileIndex) {
const tile = tilesToRender[tileIndex];
const tileBoundingRegion = tile.data.tileBoundingRegion;
addDrawCommandsForTile(this, tile, frameState);
frameState.minimumTerrainHeight = Math.min(
frameState.minimumTerrainHeight,
tileBoundingRegion.minimumHeight
);
}
}
};
function pushCommand2(command, frameState) {
const globeTranslucencyState = frameState.globeTranslucencyState;
if (globeTranslucencyState.translucent) {
const isBlendCommand = command.renderState.blending.enabled;
globeTranslucencyState.pushDerivedCommands(
command,
isBlendCommand,
frameState
);
} else {
frameState.commandList.push(command);
}
}
GlobeSurfaceTileProvider.prototype.updateForPick = function(frameState) {
const drawCommands = this._drawCommands;
for (let i = 0, length2 = this._usedDrawCommands; i < length2; ++i) {
pushCommand2(drawCommands[i], frameState);
}
};
GlobeSurfaceTileProvider.prototype.cancelReprojections = function() {
this._imageryLayers.cancelReprojections();
};
GlobeSurfaceTileProvider.prototype.getLevelMaximumGeometricError = function(level) {
if (!defined_default(this._terrainProvider)) {
return 0;
}
return this._terrainProvider.getLevelMaximumGeometricError(level);
};
GlobeSurfaceTileProvider.prototype.loadTile = function(frameState, tile) {
let surfaceTile = tile.data;
let terrainOnly = true;
let terrainStateBefore;
if (defined_default(surfaceTile)) {
terrainOnly = surfaceTile.boundingVolumeSourceTile !== tile || tile._lastSelectionResult === TileSelectionResult_default.CULLED_BUT_NEEDED;
terrainStateBefore = surfaceTile.terrainState;
}
GlobeSurfaceTile_default.processStateMachine(
tile,
frameState,
this.terrainProvider,
this._imageryLayers,
this.quadtree,
this._vertexArraysToDestroy,
terrainOnly
);
surfaceTile = tile.data;
if (terrainOnly && terrainStateBefore !== tile.data.terrainState) {
if (this.computeTileVisibility(tile, frameState, this.quadtree.occluders) !== Visibility_default.NONE && surfaceTile.boundingVolumeSourceTile === tile) {
terrainOnly = false;
GlobeSurfaceTile_default.processStateMachine(
tile,
frameState,
this.terrainProvider,
this._imageryLayers,
this.quadtree,
this._vertexArraysToDestroy,
terrainOnly
);
}
}
};
var boundingSphereScratch3 = new BoundingSphere_default();
var rectangleIntersectionScratch = new Rectangle_default();
var splitCartographicLimitRectangleScratch = new Rectangle_default();
var rectangleCenterScratch4 = new Cartographic_default();
function clipRectangleAntimeridian(tileRectangle, cartographicLimitRectangle) {
if (cartographicLimitRectangle.west < cartographicLimitRectangle.east) {
return cartographicLimitRectangle;
}
const splitRectangle = Rectangle_default.clone(
cartographicLimitRectangle,
splitCartographicLimitRectangleScratch
);
const tileCenter = Rectangle_default.center(tileRectangle, rectangleCenterScratch4);
if (tileCenter.longitude > 0) {
splitRectangle.east = Math_default.PI;
} else {
splitRectangle.west = -Math_default.PI;
}
return splitRectangle;
}
function isUndergroundVisible(tileProvider, frameState) {
if (frameState.cameraUnderground) {
return true;
}
if (frameState.globeTranslucencyState.translucent) {
return true;
}
if (tileProvider.backFaceCulling) {
return false;
}
const clippingPlanes = tileProvider._clippingPlanes;
if (defined_default(clippingPlanes) && clippingPlanes.enabled) {
return true;
}
const clippingPolygons = tileProvider._clippingPolygons;
if (defined_default(clippingPolygons) && clippingPolygons.enabled) {
return true;
}
if (!Rectangle_default.equals(
tileProvider.cartographicLimitRectangle,
Rectangle_default.MAX_VALUE
)) {
return true;
}
return false;
}
GlobeSurfaceTileProvider.prototype.computeTileVisibility = function(tile, frameState, occluders) {
const distance2 = this.computeDistanceToTile(tile, frameState);
tile._distance = distance2;
const undergroundVisible = isUndergroundVisible(this, frameState);
if (frameState.fog.enabled && !undergroundVisible) {
if (Math_default.fog(distance2, frameState.fog.density) >= 1) {
return Visibility_default.NONE;
}
}
const surfaceTile = tile.data;
const tileBoundingRegion = surfaceTile.tileBoundingRegion;
if (surfaceTile.boundingVolumeSourceTile === void 0) {
return Visibility_default.PARTIAL;
}
const cullingVolume = frameState.cullingVolume;
let boundingVolume = tileBoundingRegion.boundingVolume;
if (!defined_default(boundingVolume)) {
boundingVolume = tileBoundingRegion.boundingSphere;
}
surfaceTile.clippedByBoundaries = false;
const clippedCartographicLimitRectangle = clipRectangleAntimeridian(
tile.rectangle,
this.cartographicLimitRectangle
);
const areaLimitIntersection = Rectangle_default.simpleIntersection(
clippedCartographicLimitRectangle,
tile.rectangle,
rectangleIntersectionScratch
);
if (!defined_default(areaLimitIntersection)) {
return Visibility_default.NONE;
}
if (!Rectangle_default.equals(areaLimitIntersection, tile.rectangle)) {
surfaceTile.clippedByBoundaries = true;
}
if (frameState.mode !== SceneMode_default.SCENE3D) {
boundingVolume = boundingSphereScratch3;
BoundingSphere_default.fromRectangleWithHeights2D(
tile.rectangle,
frameState.mapProjection,
tileBoundingRegion.minimumHeight,
tileBoundingRegion.maximumHeight,
boundingVolume
);
Cartesian3_default.fromElements(
boundingVolume.center.z,
boundingVolume.center.x,
boundingVolume.center.y,
boundingVolume.center
);
if (frameState.mode === SceneMode_default.MORPHING && defined_default(surfaceTile.renderedMesh)) {
boundingVolume = BoundingSphere_default.union(
tileBoundingRegion.boundingSphere,
boundingVolume,
boundingVolume
);
}
}
if (!defined_default(boundingVolume)) {
return Visibility_default.PARTIAL;
}
const clippingPlanes = this._clippingPlanes;
if (defined_default(clippingPlanes) && clippingPlanes.enabled) {
const planeIntersection = clippingPlanes.computeIntersectionWithBoundingVolume(boundingVolume);
tile.isClipped = planeIntersection !== Intersect_default.INSIDE;
if (planeIntersection === Intersect_default.OUTSIDE) {
return Visibility_default.NONE;
}
}
const clippingPolygons = this._clippingPolygons;
if (defined_default(clippingPolygons) && clippingPolygons.enabled) {
const polygonIntersection = clippingPolygons.computeIntersectionWithBoundingVolume(
tileBoundingRegion
);
tile.isClipped = polygonIntersection !== Intersect_default.OUTSIDE;
}
let visibility;
const intersection = cullingVolume.computeVisibility(boundingVolume);
if (intersection === Intersect_default.OUTSIDE) {
visibility = Visibility_default.NONE;
} else if (intersection === Intersect_default.INTERSECTING) {
visibility = Visibility_default.PARTIAL;
} else if (intersection === Intersect_default.INSIDE) {
visibility = Visibility_default.FULL;
}
if (visibility === Visibility_default.NONE) {
return visibility;
}
const ortho3D = frameState.mode === SceneMode_default.SCENE3D && frameState.camera.frustum instanceof OrthographicFrustum_default;
if (frameState.mode === SceneMode_default.SCENE3D && !ortho3D && defined_default(occluders) && !undergroundVisible) {
const occludeePointInScaledSpace = surfaceTile.occludeePointInScaledSpace;
if (!defined_default(occludeePointInScaledSpace)) {
return visibility;
}
if (occluders.ellipsoid.isScaledSpacePointVisiblePossiblyUnderEllipsoid(
occludeePointInScaledSpace,
tileBoundingRegion.minimumHeight
)) {
return visibility;
}
return Visibility_default.NONE;
}
return visibility;
};
GlobeSurfaceTileProvider.prototype.canRefine = function(tile) {
if (defined_default(tile.data.terrainData)) {
return true;
}
const childAvailable = this.terrainProvider.getTileDataAvailable(
tile.x * 2,
tile.y * 2,
tile.level + 1
);
return childAvailable !== void 0;
};
var readyImageryScratch = [];
var canRenderTraversalStack = [];
GlobeSurfaceTileProvider.prototype.canRenderWithoutLosingDetail = function(tile, frameState) {
const surfaceTile = tile.data;
const readyImagery = readyImageryScratch;
readyImagery.length = this._imageryLayers.length;
let terrainReady = false;
let initialImageryState = false;
let imagery;
if (defined_default(surfaceTile)) {
terrainReady = surfaceTile.terrainState === TerrainState_default.READY;
initialImageryState = true;
imagery = surfaceTile.imagery;
}
let i;
let len;
for (i = 0, len = readyImagery.length; i < len; ++i) {
readyImagery[i] = initialImageryState;
}
if (defined_default(imagery)) {
for (i = 0, len = imagery.length; i < len; ++i) {
const tileImagery = imagery[i];
const loadingImagery = tileImagery.loadingImagery;
const isReady = !defined_default(loadingImagery) || loadingImagery.state === ImageryState_default.FAILED || loadingImagery.state === ImageryState_default.INVALID;
const layerIndex = (tileImagery.loadingImagery || tileImagery.readyImagery).imageryLayer._layerIndex;
readyImagery[layerIndex] = isReady && readyImagery[layerIndex];
}
}
const lastFrame = this.quadtree._lastSelectionFrameNumber;
const stack = canRenderTraversalStack;
stack.length = 0;
stack.push(
tile.southwestChild,
tile.southeastChild,
tile.northwestChild,
tile.northeastChild
);
while (stack.length > 0) {
const descendant = stack.pop();
const lastFrameSelectionResult = descendant._lastSelectionResultFrame === lastFrame ? descendant._lastSelectionResult : TileSelectionResult_default.NONE;
if (lastFrameSelectionResult === TileSelectionResult_default.RENDERED) {
const descendantSurface = descendant.data;
if (!defined_default(descendantSurface)) {
continue;
}
if (!terrainReady && descendant.data.terrainState === TerrainState_default.READY) {
return false;
}
const descendantImagery = descendant.data.imagery;
for (i = 0, len = descendantImagery.length; i < len; ++i) {
const descendantTileImagery = descendantImagery[i];
const descendantLoadingImagery = descendantTileImagery.loadingImagery;
const descendantIsReady = !defined_default(descendantLoadingImagery) || descendantLoadingImagery.state === ImageryState_default.FAILED || descendantLoadingImagery.state === ImageryState_default.INVALID;
const descendantLayerIndex = (descendantTileImagery.loadingImagery || descendantTileImagery.readyImagery).imageryLayer._layerIndex;
if (descendantIsReady && !readyImagery[descendantLayerIndex]) {
return false;
}
}
} else if (lastFrameSelectionResult === TileSelectionResult_default.REFINED) {
stack.push(
descendant.southwestChild,
descendant.southeastChild,
descendant.northwestChild,
descendant.northeastChild
);
}
}
return true;
};
var tileDirectionScratch = new Cartesian3_default();
GlobeSurfaceTileProvider.prototype.computeTileLoadPriority = function(tile, frameState) {
const surfaceTile = tile.data;
if (surfaceTile === void 0) {
return 0;
}
const obb = surfaceTile.tileBoundingRegion.boundingVolume;
if (obb === void 0) {
return 0;
}
const cameraPosition = frameState.camera.positionWC;
const cameraDirection = frameState.camera.directionWC;
const tileDirection = Cartesian3_default.subtract(
obb.center,
cameraPosition,
tileDirectionScratch
);
const magnitude = Cartesian3_default.magnitude(tileDirection);
if (magnitude < Math_default.EPSILON5) {
return 0;
}
Cartesian3_default.divideByScalar(tileDirection, magnitude, tileDirection);
return (1 - Cartesian3_default.dot(tileDirection, cameraDirection)) * tile._distance;
};
var modifiedModelViewScratch5 = new Matrix4_default();
var modifiedModelViewProjectionScratch = new Matrix4_default();
var tileRectangleScratch = new Cartesian4_default();
var localizedCartographicLimitRectangleScratch = new Cartesian4_default();
var localizedTranslucencyRectangleScratch = new Cartesian4_default();
var rtcScratch5 = new Cartesian3_default();
var centerEyeScratch = new Cartesian3_default();
var southwestScratch = new Cartesian3_default();
var northeastScratch = new Cartesian3_default();
GlobeSurfaceTileProvider.prototype.showTileThisFrame = function(tile, frameState) {
let readyTextureCount = 0;
const tileImageryCollection = tile.data.imagery;
for (let i = 0, len = tileImageryCollection.length; i < len; ++i) {
const tileImagery = tileImageryCollection[i];
if (defined_default(tileImagery.readyImagery) && tileImagery.readyImagery.imageryLayer.alpha !== 0) {
++readyTextureCount;
}
}
let tileSet = this._tilesToRenderByTextureCount[readyTextureCount];
if (!defined_default(tileSet)) {
tileSet = [];
this._tilesToRenderByTextureCount[readyTextureCount] = tileSet;
}
tileSet.push(tile);
const surfaceTile = tile.data;
if (!defined_default(surfaceTile.vertexArray)) {
this._hasFillTilesThisFrame = true;
} else {
this._hasLoadedTilesThisFrame = true;
}
const debug = this._debug;
++debug.tilesRendered;
debug.texturesRendered += readyTextureCount;
};
var cornerPositionsScratch2 = [
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default()
];
function computeOccludeePoint2(tileProvider, center, rectangle, minimumHeight, maximumHeight, result) {
const ellipsoidalOccluder = tileProvider.quadtree._occluders.ellipsoid;
const ellipsoid = ellipsoidalOccluder.ellipsoid;
const cornerPositions = cornerPositionsScratch2;
Cartesian3_default.fromRadians(
rectangle.west,
rectangle.south,
maximumHeight,
ellipsoid,
cornerPositions[0]
);
Cartesian3_default.fromRadians(
rectangle.east,
rectangle.south,
maximumHeight,
ellipsoid,
cornerPositions[1]
);
Cartesian3_default.fromRadians(
rectangle.west,
rectangle.north,
maximumHeight,
ellipsoid,
cornerPositions[2]
);
Cartesian3_default.fromRadians(
rectangle.east,
rectangle.north,
maximumHeight,
ellipsoid,
cornerPositions[3]
);
return ellipsoidalOccluder.computeHorizonCullingPointPossiblyUnderEllipsoid(
center,
cornerPositions,
minimumHeight,
result
);
}
GlobeSurfaceTileProvider.prototype.computeDistanceToTile = function(tile, frameState) {
updateTileBoundingRegion(tile, this, frameState);
const surfaceTile = tile.data;
const boundingVolumeSourceTile = surfaceTile.boundingVolumeSourceTile;
if (boundingVolumeSourceTile === void 0) {
return 9999999999;
}
const tileBoundingRegion = surfaceTile.tileBoundingRegion;
const min3 = tileBoundingRegion.minimumHeight;
const max3 = tileBoundingRegion.maximumHeight;
if (surfaceTile.boundingVolumeSourceTile !== tile) {
const cameraHeight = frameState.camera.positionCartographic.height;
const distanceToMin = Math.abs(cameraHeight - min3);
const distanceToMax = Math.abs(cameraHeight - max3);
if (distanceToMin > distanceToMax) {
tileBoundingRegion.minimumHeight = min3;
tileBoundingRegion.maximumHeight = min3;
} else {
tileBoundingRegion.minimumHeight = max3;
tileBoundingRegion.maximumHeight = max3;
}
}
const result = tileBoundingRegion.distanceToCamera(frameState);
tileBoundingRegion.minimumHeight = min3;
tileBoundingRegion.maximumHeight = max3;
return result;
};
function updateTileBoundingRegion(tile, tileProvider, frameState) {
let surfaceTile = tile.data;
if (surfaceTile === void 0) {
surfaceTile = tile.data = new GlobeSurfaceTile_default();
}
const ellipsoid = tile.tilingScheme.ellipsoid;
if (surfaceTile.tileBoundingRegion === void 0) {
surfaceTile.tileBoundingRegion = new TileBoundingRegion_default({
computeBoundingVolumes: false,
rectangle: tile.rectangle,
ellipsoid,
minimumHeight: 0,
maximumHeight: 0
});
}
const tileBoundingRegion = surfaceTile.tileBoundingRegion;
const oldMinimumHeight = tileBoundingRegion.minimumHeight;
const oldMaximumHeight = tileBoundingRegion.maximumHeight;
let hasBoundingVolumesFromMesh = false;
let sourceTile = tile;
const mesh = surfaceTile.mesh;
const terrainData = surfaceTile.terrainData;
if (mesh !== void 0 && mesh.minimumHeight !== void 0 && mesh.maximumHeight !== void 0) {
tileBoundingRegion.minimumHeight = mesh.minimumHeight;
tileBoundingRegion.maximumHeight = mesh.maximumHeight;
hasBoundingVolumesFromMesh = true;
} else if (terrainData !== void 0 && terrainData._minimumHeight !== void 0 && terrainData._maximumHeight !== void 0) {
tileBoundingRegion.minimumHeight = terrainData._minimumHeight;
tileBoundingRegion.maximumHeight = terrainData._maximumHeight;
} else {
tileBoundingRegion.minimumHeight = Number.NaN;
tileBoundingRegion.maximumHeight = Number.NaN;
let ancestorTile = tile.parent;
while (ancestorTile !== void 0) {
const ancestorSurfaceTile = ancestorTile.data;
if (ancestorSurfaceTile !== void 0) {
const ancestorMesh = ancestorSurfaceTile.mesh;
const ancestorTerrainData = ancestorSurfaceTile.terrainData;
if (ancestorMesh !== void 0 && ancestorMesh.minimumHeight !== void 0 && ancestorMesh.maximumHeight !== void 0) {
tileBoundingRegion.minimumHeight = ancestorMesh.minimumHeight;
tileBoundingRegion.maximumHeight = ancestorMesh.maximumHeight;
break;
} else if (ancestorTerrainData !== void 0 && ancestorTerrainData._minimumHeight !== void 0 && ancestorTerrainData._maximumHeight !== void 0) {
tileBoundingRegion.minimumHeight = ancestorTerrainData._minimumHeight;
tileBoundingRegion.maximumHeight = ancestorTerrainData._maximumHeight;
break;
}
}
ancestorTile = ancestorTile.parent;
}
sourceTile = ancestorTile;
}
if (sourceTile !== void 0) {
const exaggeration = frameState.verticalExaggeration;
const exaggerationRelativeHeight = frameState.verticalExaggerationRelativeHeight;
const hasExaggeration = exaggeration !== 1;
if (hasExaggeration) {
hasBoundingVolumesFromMesh = false;
tileBoundingRegion.minimumHeight = VerticalExaggeration_default.getHeight(
tileBoundingRegion.minimumHeight,
exaggeration,
exaggerationRelativeHeight
);
tileBoundingRegion.maximumHeight = VerticalExaggeration_default.getHeight(
tileBoundingRegion.maximumHeight,
exaggeration,
exaggerationRelativeHeight
);
}
if (hasBoundingVolumesFromMesh) {
if (!surfaceTile.boundingVolumeIsFromMesh) {
tileBoundingRegion._orientedBoundingBox = OrientedBoundingBox_default.clone(
mesh.orientedBoundingBox,
tileBoundingRegion._orientedBoundingBox
);
tileBoundingRegion._boundingSphere = BoundingSphere_default.clone(
mesh.boundingSphere3D,
tileBoundingRegion._boundingSphere
);
surfaceTile.occludeePointInScaledSpace = Cartesian3_default.clone(
mesh.occludeePointInScaledSpace,
surfaceTile.occludeePointInScaledSpace
);
if (!defined_default(surfaceTile.occludeePointInScaledSpace)) {
surfaceTile.occludeePointInScaledSpace = computeOccludeePoint2(
tileProvider,
tileBoundingRegion._orientedBoundingBox.center,
tile.rectangle,
tileBoundingRegion.minimumHeight,
tileBoundingRegion.maximumHeight,
surfaceTile.occludeePointInScaledSpace
);
}
}
} else {
const needsBounds = tileBoundingRegion._orientedBoundingBox === void 0 || tileBoundingRegion._boundingSphere === void 0;
const heightChanged = tileBoundingRegion.minimumHeight !== oldMinimumHeight || tileBoundingRegion.maximumHeight !== oldMaximumHeight;
if (heightChanged || needsBounds) {
tileBoundingRegion.computeBoundingVolumes(ellipsoid);
surfaceTile.occludeePointInScaledSpace = computeOccludeePoint2(
tileProvider,
tileBoundingRegion._orientedBoundingBox.center,
tile.rectangle,
tileBoundingRegion.minimumHeight,
tileBoundingRegion.maximumHeight,
surfaceTile.occludeePointInScaledSpace
);
}
}
surfaceTile.boundingVolumeSourceTile = sourceTile;
surfaceTile.boundingVolumeIsFromMesh = hasBoundingVolumesFromMesh;
} else {
surfaceTile.boundingVolumeSourceTile = void 0;
surfaceTile.boundingVolumeIsFromMesh = false;
}
}
GlobeSurfaceTileProvider.prototype.isDestroyed = function() {
return false;
};
GlobeSurfaceTileProvider.prototype.destroy = function() {
this._tileProvider = this._tileProvider && this._tileProvider.destroy();
this._clippingPlanes = this._clippingPlanes && this._clippingPlanes.destroy();
this._clippingPolygons = this._clippingPolygons && this._clippingPolygons.destroy();
this._removeLayerAddedListener = this._removeLayerAddedListener && this._removeLayerAddedListener();
this._removeLayerRemovedListener = this._removeLayerRemovedListener && this._removeLayerRemovedListener();
this._removeLayerMovedListener = this._removeLayerMovedListener && this._removeLayerMovedListener();
this._removeLayerShownListener = this._removeLayerShownListener && this._removeLayerShownListener();
return destroyObject_default(this);
};
function getTileReadyCallback(tileImageriesToFree, layer, terrainProvider) {
return function(tile) {
let tileImagery;
let imagery;
let startIndex = -1;
const tileImageryCollection = tile.data.imagery;
const length2 = tileImageryCollection.length;
let i;
for (i = 0; i < length2; ++i) {
tileImagery = tileImageryCollection[i];
imagery = tileImagery.readyImagery ?? tileImagery.loadingImagery;
if (imagery.imageryLayer === layer) {
startIndex = i;
break;
}
}
if (startIndex !== -1) {
const endIndex = startIndex + tileImageriesToFree;
tileImagery = tileImageryCollection[endIndex];
imagery = defined_default(tileImagery) ? tileImagery.readyImagery ?? tileImagery.loadingImagery : void 0;
if (!defined_default(imagery) || imagery.imageryLayer !== layer) {
return !layer._createTileImagerySkeletons(
tile,
terrainProvider,
endIndex
);
}
for (i = startIndex; i < endIndex; ++i) {
tileImageryCollection[i].freeResources();
}
tileImageryCollection.splice(startIndex, tileImageriesToFree);
}
return true;
};
}
GlobeSurfaceTileProvider.prototype._onLayerAdded = function(layer, index) {
if (this.isDestroyed()) {
return;
}
if (layer.show) {
const terrainProvider = this._terrainProvider;
const that = this;
const tileImageryUpdatedEvent = this._imageryLayersUpdatedEvent;
const reloadFunction = function() {
layer._imageryCache = {};
that._quadtree.forEachLoadedTile(function(tile) {
if (defined_default(tile._loadedCallbacks[layer._layerIndex])) {
return;
}
let i;
const tileImageryCollection = tile.data.imagery;
const length2 = tileImageryCollection.length;
let startIndex = -1;
let tileImageriesToFree = 0;
for (i = 0; i < length2; ++i) {
const tileImagery = tileImageryCollection[i];
const imagery = tileImagery.readyImagery ?? tileImagery.loadingImagery;
if (imagery.imageryLayer === layer) {
if (startIndex === -1) {
startIndex = i;
}
++tileImageriesToFree;
} else if (startIndex !== -1) {
break;
}
}
if (startIndex === -1) {
return;
}
const insertionPoint = startIndex + tileImageriesToFree;
if (layer._createTileImagerySkeletons(
tile,
terrainProvider,
insertionPoint
)) {
tile._loadedCallbacks[layer._layerIndex] = getTileReadyCallback(
tileImageriesToFree,
layer,
terrainProvider
);
tile.state = QuadtreeTileLoadState_default.LOADING;
}
});
};
if (layer.ready) {
const imageryProvider = layer.imageryProvider;
imageryProvider._reload = reloadFunction;
}
this._quadtree.forEachLoadedTile(function(tile) {
if (layer._createTileImagerySkeletons(tile, terrainProvider)) {
tile.state = QuadtreeTileLoadState_default.LOADING;
if (tile.level !== 0 && (tile._lastSelectionResultFrame !== that.quadtree._lastSelectionFrameNumber || tile._lastSelectionResult !== TileSelectionResult_default.RENDERED)) {
tile.renderable = false;
}
}
});
this._layerOrderChanged = true;
tileImageryUpdatedEvent.raiseEvent();
}
};
GlobeSurfaceTileProvider.prototype._onLayerRemoved = function(layer, index) {
this._quadtree.forEachLoadedTile(function(tile) {
const tileImageryCollection = tile.data.imagery;
let startIndex = -1;
let numDestroyed = 0;
for (let i = 0, len = tileImageryCollection.length; i < len; ++i) {
const tileImagery = tileImageryCollection[i];
let imagery = tileImagery.loadingImagery;
if (!defined_default(imagery)) {
imagery = tileImagery.readyImagery;
}
if (imagery.imageryLayer === layer) {
if (startIndex === -1) {
startIndex = i;
}
tileImagery.freeResources();
++numDestroyed;
} else if (startIndex !== -1) {
break;
}
}
if (startIndex !== -1) {
tileImageryCollection.splice(startIndex, numDestroyed);
}
});
if (defined_default(layer.imageryProvider)) {
layer.imageryProvider._reload = void 0;
}
this._imageryLayersUpdatedEvent.raiseEvent();
};
GlobeSurfaceTileProvider.prototype._onLayerMoved = function(layer, newIndex, oldIndex) {
this._layerOrderChanged = true;
this._imageryLayersUpdatedEvent.raiseEvent();
};
GlobeSurfaceTileProvider.prototype._onLayerShownOrHidden = function(layer, index, show) {
if (show) {
this._onLayerAdded(layer, index);
} else {
this._onLayerRemoved(layer, index);
}
};
var scratchClippingPlanesMatrix2 = new Matrix4_default();
var scratchInverseTransposeClippingPlanesMatrix = new Matrix4_default();
function createTileUniformMap(frameState, globeSurfaceTileProvider) {
const uniformMap2 = {
u_initialColor: function() {
return this.properties.initialColor;
},
u_fillHighlightColor: function() {
return this.properties.fillHighlightColor;
},
u_zoomedOutOceanSpecularIntensity: function() {
return this.properties.zoomedOutOceanSpecularIntensity;
},
u_oceanNormalMap: function() {
return this.properties.oceanNormalMap;
},
u_atmosphereLightIntensity: function() {
return this.properties.atmosphereLightIntensity;
},
u_atmosphereRayleighCoefficient: function() {
return this.properties.atmosphereRayleighCoefficient;
},
u_atmosphereMieCoefficient: function() {
return this.properties.atmosphereMieCoefficient;
},
u_atmosphereRayleighScaleHeight: function() {
return this.properties.atmosphereRayleighScaleHeight;
},
u_atmosphereMieScaleHeight: function() {
return this.properties.atmosphereMieScaleHeight;
},
u_atmosphereMieAnisotropy: function() {
return this.properties.atmosphereMieAnisotropy;
},
u_lightingFadeDistance: function() {
return this.properties.lightingFadeDistance;
},
u_nightFadeDistance: function() {
return this.properties.nightFadeDistance;
},
u_center3D: function() {
return this.properties.center3D;
},
u_verticalExaggerationAndRelativeHeight: function() {
return this.properties.verticalExaggerationAndRelativeHeight;
},
u_tileRectangle: function() {
return this.properties.tileRectangle;
},
u_modifiedModelView: function() {
const viewMatrix = frameState.context.uniformState.view;
const centerEye = Matrix4_default.multiplyByPoint(
viewMatrix,
this.properties.rtc,
centerEyeScratch
);
Matrix4_default.setTranslation(viewMatrix, centerEye, modifiedModelViewScratch5);
return modifiedModelViewScratch5;
},
u_modifiedModelViewProjection: function() {
const viewMatrix = frameState.context.uniformState.view;
const projectionMatrix = frameState.context.uniformState.projection;
const centerEye = Matrix4_default.multiplyByPoint(
viewMatrix,
this.properties.rtc,
centerEyeScratch
);
Matrix4_default.setTranslation(
viewMatrix,
centerEye,
modifiedModelViewProjectionScratch
);
Matrix4_default.multiply(
projectionMatrix,
modifiedModelViewProjectionScratch,
modifiedModelViewProjectionScratch
);
return modifiedModelViewProjectionScratch;
},
u_dayTextures: function() {
return this.properties.dayTextures;
},
u_dayTextureTranslationAndScale: function() {
return this.properties.dayTextureTranslationAndScale;
},
u_dayTextureTexCoordsRectangle: function() {
return this.properties.dayTextureTexCoordsRectangle;
},
u_dayTextureUseWebMercatorT: function() {
return this.properties.dayTextureUseWebMercatorT;
},
u_dayTextureAlpha: function() {
return this.properties.dayTextureAlpha;
},
u_dayTextureNightAlpha: function() {
return this.properties.dayTextureNightAlpha;
},
u_dayTextureDayAlpha: function() {
return this.properties.dayTextureDayAlpha;
},
u_dayTextureBrightness: function() {
return this.properties.dayTextureBrightness;
},
u_dayTextureContrast: function() {
return this.properties.dayTextureContrast;
},
u_dayTextureHue: function() {
return this.properties.dayTextureHue;
},
u_dayTextureSaturation: function() {
return this.properties.dayTextureSaturation;
},
u_dayTextureOneOverGamma: function() {
return this.properties.dayTextureOneOverGamma;
},
u_dayIntensity: function() {
return this.properties.dayIntensity;
},
u_southAndNorthLatitude: function() {
return this.properties.southAndNorthLatitude;
},
u_southMercatorYAndOneOverHeight: function() {
return this.properties.southMercatorYAndOneOverHeight;
},
u_waterMask: function() {
return this.properties.waterMask;
},
u_waterMaskTranslationAndScale: function() {
return this.properties.waterMaskTranslationAndScale;
},
u_minMaxHeight: function() {
return this.properties.minMaxHeight;
},
u_scaleAndBias: function() {
return this.properties.scaleAndBias;
},
u_dayTextureSplit: function() {
return this.properties.dayTextureSplit;
},
u_dayTextureCutoutRectangles: function() {
return this.properties.dayTextureCutoutRectangles;
},
u_clippingPlanes: function() {
const clippingPlanes = globeSurfaceTileProvider._clippingPlanes;
if (defined_default(clippingPlanes) && defined_default(clippingPlanes.texture)) {
return clippingPlanes.texture;
}
return frameState.context.defaultTexture;
},
u_cartographicLimitRectangle: function() {
return this.properties.localizedCartographicLimitRectangle;
},
u_clippingPlanesMatrix: function() {
const clippingPlanes = globeSurfaceTileProvider._clippingPlanes;
const transform3 = defined_default(clippingPlanes) ? Matrix4_default.multiply(
frameState.context.uniformState.view,
clippingPlanes.modelMatrix,
scratchClippingPlanesMatrix2
) : Matrix4_default.IDENTITY;
return Matrix4_default.inverseTranspose(
transform3,
scratchInverseTransposeClippingPlanesMatrix
);
},
u_clippingPlanesEdgeStyle: function() {
const style = this.properties.clippingPlanesEdgeColor;
style.alpha = this.properties.clippingPlanesEdgeWidth;
return style;
},
u_clippingDistance: function() {
const texture = globeSurfaceTileProvider._clippingPolygons.clippingTexture;
if (defined_default(texture)) {
return texture;
}
return frameState.context.defaultTexture;
},
u_clippingExtents: function() {
const texture = globeSurfaceTileProvider._clippingPolygons.extentsTexture;
if (defined_default(texture)) {
return texture;
}
return frameState.context.defaultTexture;
},
u_minimumBrightness: function() {
return frameState.fog.minimumBrightness;
},
u_hsbShift: function() {
return this.properties.hsbShift;
},
u_colorsToAlpha: function() {
return this.properties.colorsToAlpha;
},
u_frontFaceAlphaByDistance: function() {
return this.properties.frontFaceAlphaByDistance;
},
u_backFaceAlphaByDistance: function() {
return this.properties.backFaceAlphaByDistance;
},
u_translucencyRectangle: function() {
return this.properties.localizedTranslucencyRectangle;
},
u_undergroundColor: function() {
return this.properties.undergroundColor;
},
u_undergroundColorAlphaByDistance: function() {
return this.properties.undergroundColorAlphaByDistance;
},
u_lambertDiffuseMultiplier: function() {
return this.properties.lambertDiffuseMultiplier;
},
u_vertexShadowDarkness: function() {
return this.properties.vertexShadowDarkness;
},
// make a separate object so that changes to the properties are seen on
// derived commands that combine another uniform map with this one.
properties: {
initialColor: new Cartesian4_default(0, 0, 0.5, 1),
fillHighlightColor: new Color_default(0, 0, 0, 0),
zoomedOutOceanSpecularIntensity: 0.5,
oceanNormalMap: void 0,
lightingFadeDistance: new Cartesian2_default(65e5, 9e6),
nightFadeDistance: new Cartesian2_default(1e7, 4e7),
atmosphereLightIntensity: 10,
atmosphereRayleighCoefficient: new Cartesian3_default(55e-7, 13e-6, 284e-7),
atmosphereMieCoefficient: new Cartesian3_default(21e-6, 21e-6, 21e-6),
atmosphereRayleighScaleHeight: 1e4,
atmosphereMieScaleHeight: 3200,
atmosphereMieAnisotropy: 0.9,
hsbShift: new Cartesian3_default(),
center3D: void 0,
rtc: new Cartesian3_default(),
modifiedModelView: new Matrix4_default(),
tileRectangle: new Cartesian4_default(),
verticalExaggerationAndRelativeHeight: new Cartesian2_default(1, 0),
dayTextures: [],
dayTextureTranslationAndScale: [],
dayTextureTexCoordsRectangle: [],
dayTextureUseWebMercatorT: [],
dayTextureAlpha: [],
dayTextureNightAlpha: [],
dayTextureDayAlpha: [],
dayTextureBrightness: [],
dayTextureContrast: [],
dayTextureHue: [],
dayTextureSaturation: [],
dayTextureOneOverGamma: [],
dayTextureSplit: [],
dayTextureCutoutRectangles: [],
dayIntensity: 0,
colorsToAlpha: [],
southAndNorthLatitude: new Cartesian2_default(),
southMercatorYAndOneOverHeight: new Cartesian2_default(),
waterMask: void 0,
waterMaskTranslationAndScale: new Cartesian4_default(),
minMaxHeight: new Cartesian2_default(),
scaleAndBias: new Matrix4_default(),
clippingPlanesEdgeColor: Color_default.clone(Color_default.WHITE),
clippingPlanesEdgeWidth: 0,
localizedCartographicLimitRectangle: new Cartesian4_default(),
frontFaceAlphaByDistance: new Cartesian4_default(),
backFaceAlphaByDistance: new Cartesian4_default(),
localizedTranslucencyRectangle: new Cartesian4_default(),
undergroundColor: Color_default.clone(Color_default.TRANSPARENT),
undergroundColorAlphaByDistance: new Cartesian4_default(),
lambertDiffuseMultiplier: 0,
vertexShadowDarkness: 0
}
};
if (defined_default(globeSurfaceTileProvider.materialUniformMap)) {
return combine_default(uniformMap2, globeSurfaceTileProvider.materialUniformMap);
}
return uniformMap2;
}
function createWireframeVertexArrayIfNecessary(context, provider, tile) {
const surfaceTile = tile.data;
let mesh;
let vertexArray;
if (defined_default(surfaceTile.vertexArray)) {
mesh = surfaceTile.mesh;
vertexArray = surfaceTile.vertexArray;
} else if (defined_default(surfaceTile.fill) && defined_default(surfaceTile.fill.vertexArray)) {
mesh = surfaceTile.fill.mesh;
vertexArray = surfaceTile.fill.vertexArray;
}
if (!defined_default(mesh) || !defined_default(vertexArray)) {
return;
}
if (defined_default(surfaceTile.wireframeVertexArray)) {
if (surfaceTile.wireframeVertexArray.mesh === mesh) {
return;
}
surfaceTile.wireframeVertexArray.destroy();
surfaceTile.wireframeVertexArray = void 0;
}
surfaceTile.wireframeVertexArray = createWireframeVertexArray(
context,
vertexArray,
mesh
);
surfaceTile.wireframeVertexArray.mesh = mesh;
}
function createWireframeVertexArray(context, vertexArray, terrainMesh) {
const indices = terrainMesh.indices;
const geometry = {
indices,
primitiveType: PrimitiveType_default.TRIANGLES
};
GeometryPipeline_default.toWireframe(geometry);
const wireframeIndices = geometry.indices;
const wireframeIndexBuffer = Buffer_default.createIndexBuffer({
context,
typedArray: wireframeIndices,
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype: IndexDatatype_default.fromSizeInBytes(
wireframeIndices.BYTES_PER_ELEMENT
)
});
return new VertexArray_default({
context,
attributes: vertexArray._attributes,
indexBuffer: wireframeIndexBuffer
});
}
var getDebugOrientedBoundingBox;
var getDebugBoundingSphere;
var debugDestroyPrimitive;
(function() {
const instanceOBB = new GeometryInstance_default({
geometry: BoxOutlineGeometry_default.fromDimensions({
dimensions: new Cartesian3_default(2, 2, 2)
})
});
const instanceSphere = new GeometryInstance_default({
geometry: new SphereOutlineGeometry_default({ radius: 1 })
});
let modelMatrix = new Matrix4_default();
let previousVolume;
let primitive;
function createDebugPrimitive(instance) {
return new Primitive_default({
geometryInstances: instance,
appearance: new PerInstanceColorAppearance_default({
translucent: false,
flat: true
}),
asynchronous: false
});
}
getDebugOrientedBoundingBox = function(obb, color) {
if (obb === previousVolume) {
return primitive;
}
debugDestroyPrimitive();
previousVolume = obb;
modelMatrix = Matrix4_default.fromRotationTranslation(
obb.halfAxes,
obb.center,
modelMatrix
);
instanceOBB.modelMatrix = modelMatrix;
instanceOBB.attributes.color = ColorGeometryInstanceAttribute_default.fromColor(color);
primitive = createDebugPrimitive(instanceOBB);
return primitive;
};
getDebugBoundingSphere = function(sphere, color) {
if (sphere === previousVolume) {
return primitive;
}
debugDestroyPrimitive();
previousVolume = sphere;
modelMatrix = Matrix4_default.fromTranslation(sphere.center, modelMatrix);
modelMatrix = Matrix4_default.multiplyByUniformScale(
modelMatrix,
sphere.radius,
modelMatrix
);
instanceSphere.modelMatrix = modelMatrix;
instanceSphere.attributes.color = ColorGeometryInstanceAttribute_default.fromColor(color);
primitive = createDebugPrimitive(instanceSphere);
return primitive;
};
debugDestroyPrimitive = function() {
if (defined_default(primitive)) {
primitive.destroy();
primitive = void 0;
previousVolume = void 0;
}
};
})();
var otherPassesInitialColor = new Cartesian4_default(0, 0, 0, 0);
var surfaceShaderSetOptionsScratch = {
frameState: void 0,
surfaceTile: void 0,
numberOfDayTextures: void 0,
applyBrightness: void 0,
applyContrast: void 0,
applyHue: void 0,
applySaturation: void 0,
applyGamma: void 0,
applyAlpha: void 0,
applyDayNightAlpha: void 0,
applySplit: void 0,
showReflectiveOcean: void 0,
showOceanWaves: void 0,
enableLighting: void 0,
dynamicAtmosphereLighting: void 0,
dynamicAtmosphereLightingFromSun: void 0,
showGroundAtmosphere: void 0,
perFragmentGroundAtmosphere: void 0,
hasVertexNormals: void 0,
useWebMercatorProjection: void 0,
enableFog: void 0,
enableClippingPlanes: void 0,
clippingPlanes: void 0,
enableClippingPolygons: void 0,
clippingPolygons: void 0,
clippedByBoundaries: void 0,
hasImageryLayerCutout: void 0,
colorCorrect: void 0,
colorToAlpha: void 0,
hasGeodeticSurfaceNormals: void 0,
hasExaggeration: void 0
};
var defaultUndergroundColor = Color_default.TRANSPARENT;
var defaultUndergroundColorAlphaByDistance = new NearFarScalar_default();
function addDrawCommandsForTile(tileProvider, tile, frameState) {
const surfaceTile = tile.data;
if (!defined_default(surfaceTile.vertexArray)) {
if (surfaceTile.fill === void 0) {
surfaceTile.fill = new TerrainFillMesh_default(tile);
}
surfaceTile.fill.update(tileProvider, frameState);
}
const creditDisplay = frameState.creditDisplay;
const terrainData = surfaceTile.terrainData;
if (defined_default(terrainData) && defined_default(terrainData.credits)) {
const tileCredits = terrainData.credits;
for (let tileCreditIndex = 0, tileCreditLength = tileCredits.length; tileCreditIndex < tileCreditLength; ++tileCreditIndex) {
creditDisplay.addCreditToNextFrame(tileCredits[tileCreditIndex]);
}
}
let maxTextures = ContextLimits_default.maximumTextureImageUnits;
let waterMaskTexture = surfaceTile.waterMaskTexture;
let waterMaskTranslationAndScale = surfaceTile.waterMaskTranslationAndScale;
if (!defined_default(waterMaskTexture) && defined_default(surfaceTile.fill)) {
waterMaskTexture = surfaceTile.fill.waterMaskTexture;
waterMaskTranslationAndScale = surfaceTile.fill.waterMaskTranslationAndScale;
}
const cameraUnderground = frameState.cameraUnderground;
const globeTranslucencyState = frameState.globeTranslucencyState;
const translucent = globeTranslucencyState.translucent;
const frontFaceAlphaByDistance = globeTranslucencyState.frontFaceAlphaByDistance;
const backFaceAlphaByDistance = globeTranslucencyState.backFaceAlphaByDistance;
const translucencyRectangle = globeTranslucencyState.rectangle;
const undergroundColor = tileProvider.undergroundColor ?? defaultUndergroundColor;
const undergroundColorAlphaByDistance = tileProvider.undergroundColorAlphaByDistance ?? defaultUndergroundColorAlphaByDistance;
const showUndergroundColor = isUndergroundVisible(tileProvider, frameState) && frameState.mode === SceneMode_default.SCENE3D && undergroundColor.alpha > 0 && (undergroundColorAlphaByDistance.nearValue > 0 || undergroundColorAlphaByDistance.farValue > 0);
const lambertDiffuseMultiplier = tileProvider.lambertDiffuseMultiplier;
const vertexShadowDarkness = tileProvider.vertexShadowDarkness;
const hasWaterMask = tileProvider.hasWaterMask && defined_default(waterMaskTexture);
const showReflectiveOcean = hasWaterMask && tileProvider.showWaterEffect;
const oceanNormalMap = tileProvider.oceanNormalMap;
const showOceanWaves = showReflectiveOcean && defined_default(oceanNormalMap);
const terrainProvider = tileProvider.terrainProvider;
const hasVertexNormals = defined_default(terrainProvider) && tileProvider.terrainProvider.hasVertexNormals;
const enableFog = frameState.fog.enabled && frameState.fog.renderable && !cameraUnderground;
const showGroundAtmosphere = tileProvider.showGroundAtmosphere && frameState.mode === SceneMode_default.SCENE3D;
const castShadows = ShadowMode_default.castShadows(tileProvider.shadows) && !translucent;
const receiveShadows = ShadowMode_default.receiveShadows(tileProvider.shadows) && !translucent;
const hueShift = tileProvider.hueShift;
const saturationShift = tileProvider.saturationShift;
const brightnessShift = tileProvider.brightnessShift;
let colorCorrect = !(Math_default.equalsEpsilon(hueShift, 0, Math_default.EPSILON7) && Math_default.equalsEpsilon(saturationShift, 0, Math_default.EPSILON7) && Math_default.equalsEpsilon(brightnessShift, 0, Math_default.EPSILON7));
let perFragmentGroundAtmosphere = false;
if (showGroundAtmosphere) {
const cameraDistance = Cartesian3_default.magnitude(frameState.camera.positionWC);
const fadeOutDistance = tileProvider.nightFadeOutDistance;
perFragmentGroundAtmosphere = cameraDistance > fadeOutDistance;
}
if (hasWaterMask) {
--maxTextures;
}
if (showOceanWaves) {
--maxTextures;
}
if (defined_default(frameState.shadowState) && frameState.shadowState.shadowsEnabled) {
--maxTextures;
}
if (defined_default(tileProvider.clippingPlanes) && tileProvider.clippingPlanes.enabled) {
--maxTextures;
}
if (defined_default(tileProvider.clippingPolygons) && tileProvider.clippingPolygons.enabled) {
--maxTextures;
--maxTextures;
}
maxTextures -= globeTranslucencyState.numberOfTextureUniforms;
const mesh = surfaceTile.renderedMesh;
let rtc = mesh.center;
const encoding = mesh.encoding;
const tileBoundingRegion = surfaceTile.tileBoundingRegion;
const exaggeration = frameState.verticalExaggeration;
const exaggerationRelativeHeight = frameState.verticalExaggerationRelativeHeight;
const hasExaggeration = exaggeration !== 1;
const hasGeodeticSurfaceNormals = encoding.hasGeodeticSurfaceNormals;
const tileRectangle = tileRectangleScratch;
let southLatitude = 0;
let northLatitude = 0;
let southMercatorY = 0;
let oneOverMercatorHeight = 0;
let useWebMercatorProjection = false;
if (frameState.mode !== SceneMode_default.SCENE3D) {
const projection = frameState.mapProjection;
const southwest = projection.project(
Rectangle_default.southwest(tile.rectangle),
southwestScratch
);
const northeast = projection.project(
Rectangle_default.northeast(tile.rectangle),
northeastScratch
);
tileRectangle.x = southwest.x;
tileRectangle.y = southwest.y;
tileRectangle.z = northeast.x;
tileRectangle.w = northeast.y;
if (frameState.mode !== SceneMode_default.MORPHING) {
rtc = rtcScratch5;
rtc.x = 0;
rtc.y = (tileRectangle.z + tileRectangle.x) * 0.5;
rtc.z = (tileRectangle.w + tileRectangle.y) * 0.5;
tileRectangle.x -= rtc.y;
tileRectangle.y -= rtc.z;
tileRectangle.z -= rtc.y;
tileRectangle.w -= rtc.z;
}
if (frameState.mode === SceneMode_default.SCENE2D && encoding.quantization === TerrainQuantization_default.BITS12) {
const epsilon = 1 / (Math.pow(2, 12) - 1) * 0.5;
const widthEpsilon = (tileRectangle.z - tileRectangle.x) * epsilon;
const heightEpsilon = (tileRectangle.w - tileRectangle.y) * epsilon;
tileRectangle.x -= widthEpsilon;
tileRectangle.y -= heightEpsilon;
tileRectangle.z += widthEpsilon;
tileRectangle.w += heightEpsilon;
}
if (projection instanceof WebMercatorProjection_default) {
southLatitude = tile.rectangle.south;
northLatitude = tile.rectangle.north;
southMercatorY = WebMercatorProjection_default.geodeticLatitudeToMercatorAngle(southLatitude);
oneOverMercatorHeight = 1 / (WebMercatorProjection_default.geodeticLatitudeToMercatorAngle(northLatitude) - southMercatorY);
useWebMercatorProjection = true;
}
}
const surfaceShaderSetOptions = surfaceShaderSetOptionsScratch;
surfaceShaderSetOptions.frameState = frameState;
surfaceShaderSetOptions.surfaceTile = surfaceTile;
surfaceShaderSetOptions.hasWaterMask = hasWaterMask;
surfaceShaderSetOptions.showReflectiveOcean = showReflectiveOcean;
surfaceShaderSetOptions.showOceanWaves = showOceanWaves;
surfaceShaderSetOptions.enableLighting = tileProvider.enableLighting;
surfaceShaderSetOptions.dynamicAtmosphereLighting = tileProvider.dynamicAtmosphereLighting;
surfaceShaderSetOptions.dynamicAtmosphereLightingFromSun = tileProvider.dynamicAtmosphereLightingFromSun;
surfaceShaderSetOptions.showGroundAtmosphere = showGroundAtmosphere;
surfaceShaderSetOptions.atmosphereLightIntensity = tileProvider.atmosphereLightIntensity;
surfaceShaderSetOptions.atmosphereRayleighCoefficient = tileProvider.atmosphereRayleighCoefficient;
surfaceShaderSetOptions.atmosphereMieCoefficient = tileProvider.atmosphereMieCoefficient;
surfaceShaderSetOptions.atmosphereRayleighScaleHeight = tileProvider.atmosphereRayleighScaleHeight;
surfaceShaderSetOptions.atmosphereMieScaleHeight = tileProvider.atmosphereMieScaleHeight;
surfaceShaderSetOptions.atmosphereMieAnisotropy = tileProvider.atmosphereMieAnisotropy;
surfaceShaderSetOptions.perFragmentGroundAtmosphere = perFragmentGroundAtmosphere;
surfaceShaderSetOptions.hasVertexNormals = hasVertexNormals;
surfaceShaderSetOptions.useWebMercatorProjection = useWebMercatorProjection;
surfaceShaderSetOptions.clippedByBoundaries = surfaceTile.clippedByBoundaries;
surfaceShaderSetOptions.hasGeodeticSurfaceNormals = hasGeodeticSurfaceNormals;
surfaceShaderSetOptions.hasExaggeration = hasExaggeration;
const tileImageryCollection = surfaceTile.imagery;
let imageryIndex = 0;
const imageryLen = tileImageryCollection.length;
const showSkirts = tileProvider.showSkirts && !cameraUnderground && !translucent;
const backFaceCulling = tileProvider.backFaceCulling && !cameraUnderground && !translucent;
const firstPassRenderState = backFaceCulling ? tileProvider._renderState : tileProvider._disableCullingRenderState;
const otherPassesRenderState = backFaceCulling ? tileProvider._blendRenderState : tileProvider._disableCullingBlendRenderState;
let renderState = firstPassRenderState;
let initialColor = tileProvider._firstPassInitialColor;
const context = frameState.context;
if (!defined_default(tileProvider._debug.boundingSphereTile)) {
debugDestroyPrimitive();
}
const materialUniformMapChanged = tileProvider._materialUniformMap !== tileProvider.materialUniformMap;
if (materialUniformMapChanged) {
tileProvider._materialUniformMap = tileProvider.materialUniformMap;
const drawCommandsLength = tileProvider._drawCommands.length;
for (let i = 0; i < drawCommandsLength; ++i) {
tileProvider._uniformMaps[i] = createTileUniformMap(
frameState,
tileProvider
);
}
}
do {
let numberOfDayTextures = 0;
let command;
let uniformMap2;
if (tileProvider._drawCommands.length <= tileProvider._usedDrawCommands) {
command = new DrawCommand_default();
command.owner = tile;
command.cull = false;
command.boundingVolume = new BoundingSphere_default();
command.orientedBoundingBox = void 0;
uniformMap2 = createTileUniformMap(frameState, tileProvider);
tileProvider._drawCommands.push(command);
tileProvider._uniformMaps.push(uniformMap2);
} else {
command = tileProvider._drawCommands[tileProvider._usedDrawCommands];
uniformMap2 = tileProvider._uniformMaps[tileProvider._usedDrawCommands];
}
command.owner = tile;
++tileProvider._usedDrawCommands;
if (tile === tileProvider._debug.boundingSphereTile) {
const obb = tileBoundingRegion.boundingVolume;
const boundingSphere = tileBoundingRegion.boundingSphere;
if (defined_default(obb)) {
getDebugOrientedBoundingBox(obb, Color_default.RED).update(frameState);
} else if (defined_default(boundingSphere)) {
getDebugBoundingSphere(boundingSphere, Color_default.RED).update(frameState);
}
}
const uniformMapProperties = uniformMap2.properties;
Cartesian4_default.clone(initialColor, uniformMapProperties.initialColor);
uniformMapProperties.oceanNormalMap = oceanNormalMap;
uniformMapProperties.lightingFadeDistance.x = tileProvider.lightingFadeOutDistance;
uniformMapProperties.lightingFadeDistance.y = tileProvider.lightingFadeInDistance;
uniformMapProperties.nightFadeDistance.x = tileProvider.nightFadeOutDistance;
uniformMapProperties.nightFadeDistance.y = tileProvider.nightFadeInDistance;
uniformMapProperties.atmosphereLightIntensity = tileProvider.atmosphereLightIntensity;
uniformMapProperties.atmosphereRayleighCoefficient = tileProvider.atmosphereRayleighCoefficient;
uniformMapProperties.atmosphereMieCoefficient = tileProvider.atmosphereMieCoefficient;
uniformMapProperties.atmosphereRayleighScaleHeight = tileProvider.atmosphereRayleighScaleHeight;
uniformMapProperties.atmosphereMieScaleHeight = tileProvider.atmosphereMieScaleHeight;
uniformMapProperties.atmosphereMieAnisotropy = tileProvider.atmosphereMieAnisotropy;
uniformMapProperties.zoomedOutOceanSpecularIntensity = tileProvider.zoomedOutOceanSpecularIntensity;
const frontFaceAlphaByDistanceFinal = cameraUnderground ? backFaceAlphaByDistance : frontFaceAlphaByDistance;
const backFaceAlphaByDistanceFinal = cameraUnderground ? frontFaceAlphaByDistance : backFaceAlphaByDistance;
if (defined_default(frontFaceAlphaByDistanceFinal)) {
Cartesian4_default.fromElements(
frontFaceAlphaByDistanceFinal.near,
frontFaceAlphaByDistanceFinal.nearValue,
frontFaceAlphaByDistanceFinal.far,
frontFaceAlphaByDistanceFinal.farValue,
uniformMapProperties.frontFaceAlphaByDistance
);
Cartesian4_default.fromElements(
backFaceAlphaByDistanceFinal.near,
backFaceAlphaByDistanceFinal.nearValue,
backFaceAlphaByDistanceFinal.far,
backFaceAlphaByDistanceFinal.farValue,
uniformMapProperties.backFaceAlphaByDistance
);
}
Cartesian4_default.fromElements(
undergroundColorAlphaByDistance.near,
undergroundColorAlphaByDistance.nearValue,
undergroundColorAlphaByDistance.far,
undergroundColorAlphaByDistance.farValue,
uniformMapProperties.undergroundColorAlphaByDistance
);
Color_default.clone(undergroundColor, uniformMapProperties.undergroundColor);
uniformMapProperties.lambertDiffuseMultiplier = lambertDiffuseMultiplier;
uniformMapProperties.vertexShadowDarkness = vertexShadowDarkness;
const highlightFillTile = !defined_default(surfaceTile.vertexArray) && defined_default(tileProvider.fillHighlightColor) && tileProvider.fillHighlightColor.alpha > 0;
if (highlightFillTile) {
Color_default.clone(
tileProvider.fillHighlightColor,
uniformMapProperties.fillHighlightColor
);
}
uniformMapProperties.verticalExaggerationAndRelativeHeight.x = exaggeration;
uniformMapProperties.verticalExaggerationAndRelativeHeight.y = exaggerationRelativeHeight;
uniformMapProperties.center3D = mesh.center;
Cartesian3_default.clone(rtc, uniformMapProperties.rtc);
Cartesian4_default.clone(tileRectangle, uniformMapProperties.tileRectangle);
uniformMapProperties.southAndNorthLatitude.x = southLatitude;
uniformMapProperties.southAndNorthLatitude.y = northLatitude;
uniformMapProperties.southMercatorYAndOneOverHeight.x = southMercatorY;
uniformMapProperties.southMercatorYAndOneOverHeight.y = oneOverMercatorHeight;
const localizedCartographicLimitRectangle = localizedCartographicLimitRectangleScratch;
const cartographicLimitRectangle = clipRectangleAntimeridian(
tile.rectangle,
tileProvider.cartographicLimitRectangle
);
const localizedTranslucencyRectangle = localizedTranslucencyRectangleScratch;
const clippedTranslucencyRectangle = clipRectangleAntimeridian(
tile.rectangle,
translucencyRectangle
);
Cartesian3_default.fromElements(
hueShift,
saturationShift,
brightnessShift,
uniformMapProperties.hsbShift
);
const cartographicTileRectangle = tile.rectangle;
const inverseTileWidth = 1 / cartographicTileRectangle.width;
const inverseTileHeight = 1 / cartographicTileRectangle.height;
localizedCartographicLimitRectangle.x = (cartographicLimitRectangle.west - cartographicTileRectangle.west) * inverseTileWidth;
localizedCartographicLimitRectangle.y = (cartographicLimitRectangle.south - cartographicTileRectangle.south) * inverseTileHeight;
localizedCartographicLimitRectangle.z = (cartographicLimitRectangle.east - cartographicTileRectangle.west) * inverseTileWidth;
localizedCartographicLimitRectangle.w = (cartographicLimitRectangle.north - cartographicTileRectangle.south) * inverseTileHeight;
Cartesian4_default.clone(
localizedCartographicLimitRectangle,
uniformMapProperties.localizedCartographicLimitRectangle
);
localizedTranslucencyRectangle.x = (clippedTranslucencyRectangle.west - cartographicTileRectangle.west) * inverseTileWidth;
localizedTranslucencyRectangle.y = (clippedTranslucencyRectangle.south - cartographicTileRectangle.south) * inverseTileHeight;
localizedTranslucencyRectangle.z = (clippedTranslucencyRectangle.east - cartographicTileRectangle.west) * inverseTileWidth;
localizedTranslucencyRectangle.w = (clippedTranslucencyRectangle.north - cartographicTileRectangle.south) * inverseTileHeight;
Cartesian4_default.clone(
localizedTranslucencyRectangle,
uniformMapProperties.localizedTranslucencyRectangle
);
const applyFog = enableFog && Math_default.fog(tile._distance, frameState.fog.density) > Math_default.EPSILON3;
colorCorrect = colorCorrect && (applyFog || showGroundAtmosphere);
let applyBrightness = false;
let applyContrast = false;
let applyHue = false;
let applySaturation = false;
let applyGamma = false;
let applyAlpha = false;
let applyDayNightAlpha = false;
let applySplit = false;
let applyCutout = false;
let applyColorToAlpha = false;
while (numberOfDayTextures < maxTextures && imageryIndex < imageryLen) {
const tileImagery = tileImageryCollection[imageryIndex];
const imagery = tileImagery.readyImagery;
++imageryIndex;
if (!defined_default(imagery) || imagery.imageryLayer.alpha === 0) {
continue;
}
const texture = tileImagery.useWebMercatorT ? imagery.textureWebMercator : imagery.texture;
if (!defined_default(texture)) {
throw new DeveloperError_default("readyImagery is not actually ready!");
}
const imageryLayer = imagery.imageryLayer;
if (!defined_default(tileImagery.textureTranslationAndScale)) {
tileImagery.textureTranslationAndScale = imageryLayer._calculateTextureTranslationAndScale(tile, tileImagery);
}
uniformMapProperties.dayTextures[numberOfDayTextures] = texture;
uniformMapProperties.dayTextureTranslationAndScale[numberOfDayTextures] = tileImagery.textureTranslationAndScale;
uniformMapProperties.dayTextureTexCoordsRectangle[numberOfDayTextures] = tileImagery.textureCoordinateRectangle;
uniformMapProperties.dayTextureUseWebMercatorT[numberOfDayTextures] = tileImagery.useWebMercatorT;
uniformMapProperties.dayTextureAlpha[numberOfDayTextures] = imageryLayer.alpha;
applyAlpha = applyAlpha || uniformMapProperties.dayTextureAlpha[numberOfDayTextures] !== 1;
uniformMapProperties.dayTextureNightAlpha[numberOfDayTextures] = imageryLayer.nightAlpha;
applyDayNightAlpha = applyDayNightAlpha || uniformMapProperties.dayTextureNightAlpha[numberOfDayTextures] !== 1;
uniformMapProperties.dayTextureDayAlpha[numberOfDayTextures] = imageryLayer.dayAlpha;
applyDayNightAlpha = applyDayNightAlpha || uniformMapProperties.dayTextureDayAlpha[numberOfDayTextures] !== 1;
uniformMapProperties.dayTextureBrightness[numberOfDayTextures] = imageryLayer.brightness;
applyBrightness = applyBrightness || uniformMapProperties.dayTextureBrightness[numberOfDayTextures] !== ImageryLayer_default.DEFAULT_BRIGHTNESS;
uniformMapProperties.dayTextureContrast[numberOfDayTextures] = imageryLayer.contrast;
applyContrast = applyContrast || uniformMapProperties.dayTextureContrast[numberOfDayTextures] !== ImageryLayer_default.DEFAULT_CONTRAST;
uniformMapProperties.dayTextureHue[numberOfDayTextures] = imageryLayer.hue;
applyHue = applyHue || uniformMapProperties.dayTextureHue[numberOfDayTextures] !== ImageryLayer_default.DEFAULT_HUE;
uniformMapProperties.dayTextureSaturation[numberOfDayTextures] = imageryLayer.saturation;
applySaturation = applySaturation || uniformMapProperties.dayTextureSaturation[numberOfDayTextures] !== ImageryLayer_default.DEFAULT_SATURATION;
uniformMapProperties.dayTextureOneOverGamma[numberOfDayTextures] = 1 / imageryLayer.gamma;
applyGamma = applyGamma || uniformMapProperties.dayTextureOneOverGamma[numberOfDayTextures] !== 1 / ImageryLayer_default.DEFAULT_GAMMA;
uniformMapProperties.dayTextureSplit[numberOfDayTextures] = imageryLayer.splitDirection;
applySplit = applySplit || uniformMapProperties.dayTextureSplit[numberOfDayTextures] !== 0;
let dayTextureCutoutRectangle = uniformMapProperties.dayTextureCutoutRectangles[numberOfDayTextures];
if (!defined_default(dayTextureCutoutRectangle)) {
dayTextureCutoutRectangle = uniformMapProperties.dayTextureCutoutRectangles[numberOfDayTextures] = new Cartesian4_default();
}
Cartesian4_default.clone(Cartesian4_default.ZERO, dayTextureCutoutRectangle);
if (defined_default(imageryLayer.cutoutRectangle)) {
const cutoutRectangle = clipRectangleAntimeridian(
cartographicTileRectangle,
imageryLayer.cutoutRectangle
);
const intersection = Rectangle_default.simpleIntersection(
cutoutRectangle,
cartographicTileRectangle,
rectangleIntersectionScratch
);
applyCutout = defined_default(intersection) || applyCutout;
dayTextureCutoutRectangle.x = (cutoutRectangle.west - cartographicTileRectangle.west) * inverseTileWidth;
dayTextureCutoutRectangle.y = (cutoutRectangle.south - cartographicTileRectangle.south) * inverseTileHeight;
dayTextureCutoutRectangle.z = (cutoutRectangle.east - cartographicTileRectangle.west) * inverseTileWidth;
dayTextureCutoutRectangle.w = (cutoutRectangle.north - cartographicTileRectangle.south) * inverseTileHeight;
}
let colorToAlpha = uniformMapProperties.colorsToAlpha[numberOfDayTextures];
if (!defined_default(colorToAlpha)) {
colorToAlpha = uniformMapProperties.colorsToAlpha[numberOfDayTextures] = new Cartesian4_default();
}
const hasColorToAlpha = defined_default(imageryLayer.colorToAlpha) && imageryLayer.colorToAlphaThreshold > 0;
applyColorToAlpha = applyColorToAlpha || hasColorToAlpha;
if (hasColorToAlpha) {
const color = imageryLayer.colorToAlpha;
colorToAlpha.x = color.red;
colorToAlpha.y = color.green;
colorToAlpha.z = color.blue;
colorToAlpha.w = imageryLayer.colorToAlphaThreshold;
} else {
colorToAlpha.w = -1;
}
if (defined_default(imagery.credits)) {
const credits = imagery.credits;
for (let creditIndex = 0, creditLength = credits.length; creditIndex < creditLength; ++creditIndex) {
creditDisplay.addCreditToNextFrame(credits[creditIndex]);
}
}
++numberOfDayTextures;
}
uniformMapProperties.dayTextures.length = numberOfDayTextures;
uniformMapProperties.waterMask = waterMaskTexture;
Cartesian4_default.clone(
waterMaskTranslationAndScale,
uniformMapProperties.waterMaskTranslationAndScale
);
uniformMapProperties.minMaxHeight.x = encoding.minimumHeight;
uniformMapProperties.minMaxHeight.y = encoding.maximumHeight;
Matrix4_default.clone(encoding.matrix, uniformMapProperties.scaleAndBias);
const clippingPlanes = tileProvider._clippingPlanes;
const clippingPlanesEnabled = defined_default(clippingPlanes) && clippingPlanes.enabled && tile.isClipped;
if (clippingPlanesEnabled) {
uniformMapProperties.clippingPlanesEdgeColor = Color_default.clone(
clippingPlanes.edgeColor,
uniformMapProperties.clippingPlanesEdgeColor
);
uniformMapProperties.clippingPlanesEdgeWidth = clippingPlanes.edgeWidth;
}
const clippingPolygons = tileProvider._clippingPolygons;
const clippingPolygonsEnabled = defined_default(clippingPolygons) && clippingPolygons.enabled && tile.isClipped;
surfaceShaderSetOptions.numberOfDayTextures = numberOfDayTextures;
surfaceShaderSetOptions.applyBrightness = applyBrightness;
surfaceShaderSetOptions.applyContrast = applyContrast;
surfaceShaderSetOptions.applyHue = applyHue;
surfaceShaderSetOptions.applySaturation = applySaturation;
surfaceShaderSetOptions.applyGamma = applyGamma;
surfaceShaderSetOptions.applyAlpha = applyAlpha;
surfaceShaderSetOptions.applyDayNightAlpha = applyDayNightAlpha;
surfaceShaderSetOptions.applySplit = applySplit;
surfaceShaderSetOptions.enableFog = applyFog;
surfaceShaderSetOptions.enableClippingPlanes = clippingPlanesEnabled;
surfaceShaderSetOptions.clippingPlanes = clippingPlanes;
surfaceShaderSetOptions.enableClippingPolygons = clippingPolygonsEnabled;
surfaceShaderSetOptions.clippingPolygons = clippingPolygons;
surfaceShaderSetOptions.hasImageryLayerCutout = applyCutout;
surfaceShaderSetOptions.colorCorrect = colorCorrect;
surfaceShaderSetOptions.highlightFillTile = highlightFillTile;
surfaceShaderSetOptions.colorToAlpha = applyColorToAlpha;
surfaceShaderSetOptions.showUndergroundColor = showUndergroundColor;
surfaceShaderSetOptions.translucent = translucent;
let count = surfaceTile.renderedMesh.indices.length;
if (!showSkirts) {
count = surfaceTile.renderedMesh.indexCountWithoutSkirts;
}
command.shaderProgram = tileProvider._surfaceShaderSet.getShaderProgram(
surfaceShaderSetOptions
);
command.castShadows = castShadows;
command.receiveShadows = receiveShadows;
command.renderState = renderState;
command.primitiveType = PrimitiveType_default.TRIANGLES;
command.vertexArray = surfaceTile.vertexArray || surfaceTile.fill.vertexArray;
command.count = count;
command.uniformMap = uniformMap2;
command.pass = Pass_default.GLOBE;
if (tileProvider._debug.wireframe) {
createWireframeVertexArrayIfNecessary(context, tileProvider, tile);
if (defined_default(surfaceTile.wireframeVertexArray)) {
command.vertexArray = surfaceTile.wireframeVertexArray;
command.primitiveType = PrimitiveType_default.LINES;
command.count = count * 2;
}
}
let boundingVolume = command.boundingVolume;
const orientedBoundingBox = command.orientedBoundingBox;
if (frameState.mode !== SceneMode_default.SCENE3D) {
BoundingSphere_default.fromRectangleWithHeights2D(
tile.rectangle,
frameState.mapProjection,
tileBoundingRegion.minimumHeight,
tileBoundingRegion.maximumHeight,
boundingVolume
);
Cartesian3_default.fromElements(
boundingVolume.center.z,
boundingVolume.center.x,
boundingVolume.center.y,
boundingVolume.center
);
if (frameState.mode === SceneMode_default.MORPHING) {
boundingVolume = BoundingSphere_default.union(
tileBoundingRegion.boundingSphere,
boundingVolume,
boundingVolume
);
}
} else {
command.boundingVolume = BoundingSphere_default.clone(
tileBoundingRegion.boundingSphere,
boundingVolume
);
command.orientedBoundingBox = OrientedBoundingBox_default.clone(
tileBoundingRegion.boundingVolume,
orientedBoundingBox
);
}
command.dirty = true;
if (translucent) {
globeTranslucencyState.updateDerivedCommands(command, frameState);
}
pushCommand2(command, frameState);
renderState = otherPassesRenderState;
initialColor = otherPassesInitialColor;
} while (imageryIndex < imageryLen);
}
var GlobeSurfaceTileProvider_default = GlobeSurfaceTileProvider;
// packages/engine/Source/Scene/GlobeTranslucency.js
var import_InlineWorkers1025 = __toESM(require_InlineWorkers(), 1);
function GlobeTranslucency() {
this._enabled = false;
this._frontFaceAlpha = 1;
this._frontFaceAlphaByDistance = void 0;
this._backFaceAlpha = 1;
this._backFaceAlphaByDistance = void 0;
this._rectangle = Rectangle_default.clone(Rectangle_default.MAX_VALUE);
}
Object.defineProperties(GlobeTranslucency.prototype, {
/**
* When true, the globe is rendered as a translucent surface.
*
* The alpha is computed by blending {@link Globe#material}, {@link Globe#imageryLayers},
* and {@link Globe#baseColor}, all of which may contain translucency, and then multiplying by
* {@link GlobeTranslucency#frontFaceAlpha} and {@link GlobeTranslucency#frontFaceAlphaByDistance} for front faces and
* {@link GlobeTranslucency#backFaceAlpha} and {@link GlobeTranslucency#backFaceAlphaByDistance} for back faces.
* When the camera is underground back faces and front faces are swapped, i.e. back-facing geometry
* is considered front facing.
*
* Translucency is disabled by default.
*
* @memberof GlobeTranslucency.prototype
*
* @type {boolean}
* @default false
*
* @see GlobeTranslucency#frontFaceAlpha
* @see GlobeTranslucency#frontFaceAlphaByDistance
* @see GlobeTranslucency#backFaceAlpha
* @see GlobeTranslucency#backFaceAlphaByDistance
*/
enabled: {
get: function() {
return this._enabled;
},
set: function(value) {
Check_default.typeOf.bool("enabled", value);
this._enabled = value;
}
},
/**
* A constant translucency to apply to front faces of the globe.
*
* {@link GlobeTranslucency#enabled} must be set to true for this option to take effect.
*
* @memberof GlobeTranslucency.prototype
*
* @type {number}
* @default 1.0
*
* @see GlobeTranslucency#enabled
* @see GlobeTranslucency#frontFaceAlphaByDistance
*
* @example
* // Set front face translucency to 0.5.
* globe.translucency.frontFaceAlpha = 0.5;
* globe.translucency.enabled = true;
*/
frontFaceAlpha: {
get: function() {
return this._frontFaceAlpha;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("frontFaceAlpha", value, 0);
Check_default.typeOf.number.lessThanOrEquals("frontFaceAlpha", value, 1);
this._frontFaceAlpha = value;
}
},
/**
* Gets or sets near and far translucency properties of front faces of the globe based on the distance to the camera.
* The translucency will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the translucency remains clamped to the nearest bound. If undefined,
* frontFaceAlphaByDistance will be disabled.
*
* {@link GlobeTranslucency#enabled} must be set to true for this option to take effect.
*
* @memberof GlobeTranslucency.prototype
*
* @type {NearFarScalar}
* @default undefined
*
* @see GlobeTranslucency#enabled
* @see GlobeTranslucency#frontFaceAlpha
*
* @example
* // Example 1.
* // Set front face translucency to 0.5 when the
* // camera is 1500 meters from the surface and 1.0
* // as the camera distance approaches 8.0e6 meters.
* globe.translucency.frontFaceAlphaByDistance = new Cesium.NearFarScalar(1.5e2, 0.5, 8.0e6, 1.0);
* globe.translucency.enabled = true;
*
* @example
* // Example 2.
* // Disable front face translucency by distance
* globe.translucency.frontFaceAlphaByDistance = undefined;
*/
frontFaceAlphaByDistance: {
get: function() {
return this._frontFaceAlphaByDistance;
},
set: function(value) {
if (defined_default(value) && value.far < value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
this._frontFaceAlphaByDistance = NearFarScalar_default.clone(
value,
this._frontFaceAlphaByDistance
);
}
},
/**
* A constant translucency to apply to back faces of the globe.
*
* {@link GlobeTranslucency#enabled} must be set to true for this option to take effect.
*
* @memberof GlobeTranslucency.prototype
*
* @type {number}
* @default 1.0
*
* @see GlobeTranslucency#enabled
* @see GlobeTranslucency#backFaceAlphaByDistance
*
* @example
* // Set back face translucency to 0.5.
* globe.translucency.backFaceAlpha = 0.5;
* globe.translucency.enabled = true;
*/
backFaceAlpha: {
get: function() {
return this._backFaceAlpha;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("backFaceAlpha", value, 0);
Check_default.typeOf.number.lessThanOrEquals("backFaceAlpha", value, 1);
this._backFaceAlpha = value;
}
},
/**
* Gets or sets near and far translucency properties of back faces of the globe based on the distance to the camera.
* The translucency will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the translucency remains clamped to the nearest bound. If undefined,
* backFaceAlphaByDistance will be disabled.
*
* {@link GlobeTranslucency#enabled} must be set to true for this option to take effect.
*
* @memberof GlobeTranslucency.prototype
*
* @type {NearFarScalar}
* @default undefined
*
* @see GlobeTranslucency#enabled
* @see GlobeTranslucency#backFaceAlpha
*
* @example
* // Example 1.
* // Set back face translucency to 0.5 when the
* // camera is 1500 meters from the surface and 1.0
* // as the camera distance approaches 8.0e6 meters.
* globe.translucency.backFaceAlphaByDistance = new Cesium.NearFarScalar(1.5e2, 0.5, 8.0e6, 1.0);
* globe.translucency.enabled = true;
*
* @example
* // Example 2.
* // Disable back face translucency by distance
* globe.translucency.backFaceAlphaByDistance = undefined;
*/
backFaceAlphaByDistance: {
get: function() {
return this._backFaceAlphaByDistance;
},
set: function(value) {
if (defined_default(value) && value.far < value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
this._backFaceAlphaByDistance = NearFarScalar_default.clone(
value,
this._backFaceAlphaByDistance
);
}
},
/**
* A property specifying a {@link Rectangle} used to limit translucency to a cartographic area.
* Defaults to the maximum extent of cartographic coordinates.
*
* @memberof GlobeTranslucency.prototype
*
* @type {Rectangle}
* @default {@link Rectangle.MAX_VALUE}
*/
rectangle: {
get: function() {
return this._rectangle;
},
set: function(value) {
if (!defined_default(value)) {
value = Rectangle_default.clone(Rectangle_default.MAX_VALUE);
}
Rectangle_default.clone(value, this._rectangle);
}
}
});
var GlobeTranslucency_default = GlobeTranslucency;
// packages/engine/Source/Scene/QuadtreePrimitive.js
var import_InlineWorkers1029 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/QuadtreeOccluders.js
var import_InlineWorkers1026 = __toESM(require_InlineWorkers(), 1);
function QuadtreeOccluders(options) {
this._ellipsoid = new EllipsoidalOccluder_default(options.ellipsoid, Cartesian3_default.ZERO);
}
Object.defineProperties(QuadtreeOccluders.prototype, {
/**
* Gets the {@link EllipsoidalOccluder} that can be used to determine if a point is
* occluded by an {@link Ellipsoid}.
* @type {EllipsoidalOccluder}
* @memberof QuadtreeOccluders.prototype
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
}
});
var QuadtreeOccluders_default = QuadtreeOccluders;
// packages/engine/Source/Scene/QuadtreeTile.js
var import_InlineWorkers1027 = __toESM(require_InlineWorkers(), 1);
var LRUCache = class {
constructor(maxSize) {
this.maxSize = maxSize;
this.cache = /* @__PURE__ */ new Map();
}
get(key) {
if (!this.cache.has(key)) {
return void 0;
}
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
set(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
} else if (this.cache.size >= this.maxSize) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
clear() {
this.cache.clear();
}
};
var MAX_CACHE_ENTRIES = 1e3;
function QuadtreeTile(options) {
if (!defined_default(options)) {
throw new DeveloperError_default("options is required.");
}
if (!defined_default(options.x)) {
throw new DeveloperError_default("options.x is required.");
} else if (!defined_default(options.y)) {
throw new DeveloperError_default("options.y is required.");
} else if (options.x < 0 || options.y < 0) {
throw new DeveloperError_default(
"options.x and options.y must be greater than or equal to zero."
);
}
if (!defined_default(options.level)) {
throw new DeveloperError_default(
"options.level is required and must be greater than or equal to zero."
);
}
if (!defined_default(options.tilingScheme)) {
throw new DeveloperError_default("options.tilingScheme is required.");
}
this._tilingScheme = options.tilingScheme;
this._x = options.x;
this._y = options.y;
this._level = options.level;
this._parent = options.parent;
this._rectangle = this._tilingScheme.tileXYToRectangle(
this._x,
this._y,
this._level
);
this._southwestChild = void 0;
this._southeastChild = void 0;
this._northwestChild = void 0;
this._northeastChild = void 0;
this.replacementPrevious = void 0;
this.replacementNext = void 0;
this._distance = 0;
this._loadPriority = 0;
this._customData = [];
this._frameUpdated = void 0;
this._lastSelectionResult = TileSelectionResult_default.NONE;
this._lastSelectionResultFrame = void 0;
this._loadedCallbacks = {};
this._positionCache = new LRUCache(MAX_CACHE_ENTRIES);
this.state = QuadtreeTileLoadState_default.START;
this.renderable = false;
this.upsampledFromParent = false;
this.data = void 0;
}
QuadtreeTile.createLevelZeroTiles = function(tilingScheme2) {
if (!defined_default(tilingScheme2)) {
throw new DeveloperError_default("tilingScheme is required.");
}
const numberOfLevelZeroTilesX = tilingScheme2.getNumberOfXTilesAtLevel(0);
const numberOfLevelZeroTilesY = tilingScheme2.getNumberOfYTilesAtLevel(0);
const result = new Array(numberOfLevelZeroTilesX * numberOfLevelZeroTilesY);
let index = 0;
for (let y = 0; y < numberOfLevelZeroTilesY; ++y) {
for (let x = 0; x < numberOfLevelZeroTilesX; ++x) {
result[index++] = new QuadtreeTile({
tilingScheme: tilingScheme2,
x,
y,
level: 0
});
}
}
return result;
};
var TILE_SIZE = 256;
function createSpatialHashKey(longitude, latitude, rectangle, maximumScreenSpaceError) {
const maxError = rectangle.width / TILE_SIZE * maximumScreenSpaceError;
const lonGrid = Math.floor(longitude / maxError) * maxError;
const latGrid = Math.floor(latitude / maxError) * maxError;
return `${lonGrid.toFixed(10)},${latGrid.toFixed(10)}`;
}
QuadtreeTile.prototype._getCacheKey = function(cartographic2, maximumScreenSpaceError) {
return createSpatialHashKey(
cartographic2.longitude,
cartographic2.latitude,
this._rectangle,
maximumScreenSpaceError
);
};
QuadtreeTile.prototype.getPositionCacheEntry = function(cartographic2, maximumScreenSpaceError) {
return this._positionCache.get(
this._getCacheKey(cartographic2, maximumScreenSpaceError)
);
};
QuadtreeTile.prototype.setPositionCacheEntry = function(cartographic2, maximumScreenSpaceError, value) {
this._positionCache.set(
this._getCacheKey(cartographic2, maximumScreenSpaceError),
value
);
};
QuadtreeTile.prototype.clearPositionCache = function() {
if (this._positionCache.size > 0) {
this._positionCache.clear();
}
};
QuadtreeTile.prototype._updateCustomData = function(frameNumber, added, removed) {
let customData = this.customData;
let i;
let data;
let rectangle;
if (defined_default(added) && defined_default(removed)) {
customData = customData.filter(function(value) {
return removed.indexOf(value) === -1;
});
this._customData = customData;
rectangle = this._rectangle;
for (i = 0; i < added.length; ++i) {
data = added[i];
if (Rectangle_default.contains(rectangle, data.positionCartographic)) {
customData.push(data);
}
}
this._frameUpdated = frameNumber;
} else {
const parent = this._parent;
if (defined_default(parent) && this._frameUpdated !== parent._frameUpdated) {
customData.length = 0;
rectangle = this._rectangle;
const parentCustomData = parent.customData;
for (i = 0; i < parentCustomData.length; ++i) {
data = parentCustomData[i];
if (Rectangle_default.contains(rectangle, data.positionCartographic)) {
customData.push(data);
}
}
this._frameUpdated = parent._frameUpdated;
}
}
};
Object.defineProperties(QuadtreeTile.prototype, {
/**
* Gets the tiling scheme used to tile the surface.
* @memberof QuadtreeTile.prototype
* @type {TilingScheme}
*/
tilingScheme: {
get: function() {
return this._tilingScheme;
}
},
/**
* Gets the tile X coordinate.
* @memberof QuadtreeTile.prototype
* @type {number}
*/
x: {
get: function() {
return this._x;
}
},
/**
* Gets the tile Y coordinate.
* @memberof QuadtreeTile.prototype
* @type {number}
*/
y: {
get: function() {
return this._y;
}
},
/**
* Gets the level-of-detail, where zero is the coarsest, least-detailed.
* @memberof QuadtreeTile.prototype
* @type {number}
*/
level: {
get: function() {
return this._level;
}
},
/**
* Gets the parent tile of this tile.
* @memberof QuadtreeTile.prototype
* @type {QuadtreeTile}
*/
parent: {
get: function() {
return this._parent;
}
},
/**
* Gets the cartographic rectangle of the tile, with north, south, east and
* west properties in radians.
* @memberof QuadtreeTile.prototype
* @type {Rectangle}
*/
rectangle: {
get: function() {
return this._rectangle;
}
},
/**
* An array of tiles that is at the next level of the tile tree.
* @memberof QuadtreeTile.prototype
* @type {QuadtreeTile[]}
*/
children: {
get: function() {
return [
this.northwestChild,
this.northeastChild,
this.southwestChild,
this.southeastChild
];
}
},
/**
* Gets the southwest child tile.
* @memberof QuadtreeTile.prototype
* @type {QuadtreeTile}
*/
southwestChild: {
get: function() {
if (!defined_default(this._southwestChild)) {
this._southwestChild = new QuadtreeTile({
tilingScheme: this.tilingScheme,
x: this.x * 2,
y: this.y * 2 + 1,
level: this.level + 1,
parent: this
});
}
return this._southwestChild;
}
},
/**
* Gets the southeast child tile.
* @memberof QuadtreeTile.prototype
* @type {QuadtreeTile}
*/
southeastChild: {
get: function() {
if (!defined_default(this._southeastChild)) {
this._southeastChild = new QuadtreeTile({
tilingScheme: this.tilingScheme,
x: this.x * 2 + 1,
y: this.y * 2 + 1,
level: this.level + 1,
parent: this
});
}
return this._southeastChild;
}
},
/**
* Gets the northwest child tile.
* @memberof QuadtreeTile.prototype
* @type {QuadtreeTile}
*/
northwestChild: {
get: function() {
if (!defined_default(this._northwestChild)) {
this._northwestChild = new QuadtreeTile({
tilingScheme: this.tilingScheme,
x: this.x * 2,
y: this.y * 2,
level: this.level + 1,
parent: this
});
}
return this._northwestChild;
}
},
/**
* Gets the northeast child tile.
* @memberof QuadtreeTile.prototype
* @type {QuadtreeTile}
*/
northeastChild: {
get: function() {
if (!defined_default(this._northeastChild)) {
this._northeastChild = new QuadtreeTile({
tilingScheme: this.tilingScheme,
x: this.x * 2 + 1,
y: this.y * 2,
level: this.level + 1,
parent: this
});
}
return this._northeastChild;
}
},
/**
* An array of objects associated with this tile.
* @memberof QuadtreeTile.prototype
* @type {Array}
*/
customData: {
get: function() {
return this._customData;
}
},
/**
* Gets a value indicating whether or not this tile needs further loading.
* This property will return true if the {@link QuadtreeTile#state} is
* START or LOADING.
* @memberof QuadtreeTile.prototype
* @type {boolean}
*/
needsLoading: {
get: function() {
return this.state < QuadtreeTileLoadState_default.DONE;
}
},
/**
* Gets a value indicating whether or not this tile is eligible to be unloaded.
* Typically, a tile is ineligible to be unloaded while an asynchronous operation,
* such as a request for data, is in progress on it. A tile will never be
* unloaded while it is needed for rendering, regardless of the value of this
* property. If {@link QuadtreeTile#data} is defined and has an
* eligibleForUnloading property, the value of that property is returned.
* Otherwise, this property returns true.
* @memberof QuadtreeTile.prototype
* @type {boolean}
*/
eligibleForUnloading: {
get: function() {
let result = true;
if (defined_default(this.data)) {
result = this.data.eligibleForUnloading;
if (!defined_default(result)) {
result = true;
}
}
return result;
}
}
});
QuadtreeTile.prototype.findLevelZeroTile = function(levelZeroTiles, x, y) {
const xTiles = this.tilingScheme.getNumberOfXTilesAtLevel(0);
if (x < 0) {
x += xTiles;
} else if (x >= xTiles) {
x -= xTiles;
}
if (y < 0 || y >= this.tilingScheme.getNumberOfYTilesAtLevel(0)) {
return void 0;
}
return levelZeroTiles.filter(function(tile) {
return tile.x === x && tile.y === y;
})[0];
};
QuadtreeTile.prototype.findTileToWest = function(levelZeroTiles) {
const parent = this.parent;
if (parent === void 0) {
return this.findLevelZeroTile(levelZeroTiles, this.x - 1, this.y);
}
if (parent.southeastChild === this) {
return parent.southwestChild;
} else if (parent.northeastChild === this) {
return parent.northwestChild;
}
const westOfParent = parent.findTileToWest(levelZeroTiles);
if (westOfParent === void 0) {
return void 0;
} else if (parent.southwestChild === this) {
return westOfParent.southeastChild;
}
return westOfParent.northeastChild;
};
QuadtreeTile.prototype.findTileToEast = function(levelZeroTiles) {
const parent = this.parent;
if (parent === void 0) {
return this.findLevelZeroTile(levelZeroTiles, this.x + 1, this.y);
}
if (parent.southwestChild === this) {
return parent.southeastChild;
} else if (parent.northwestChild === this) {
return parent.northeastChild;
}
const eastOfParent = parent.findTileToEast(levelZeroTiles);
if (eastOfParent === void 0) {
return void 0;
} else if (parent.southeastChild === this) {
return eastOfParent.southwestChild;
}
return eastOfParent.northwestChild;
};
QuadtreeTile.prototype.findTileToSouth = function(levelZeroTiles) {
const parent = this.parent;
if (parent === void 0) {
return this.findLevelZeroTile(levelZeroTiles, this.x, this.y + 1);
}
if (parent.northwestChild === this) {
return parent.southwestChild;
} else if (parent.northeastChild === this) {
return parent.southeastChild;
}
const southOfParent = parent.findTileToSouth(levelZeroTiles);
if (southOfParent === void 0) {
return void 0;
} else if (parent.southwestChild === this) {
return southOfParent.northwestChild;
}
return southOfParent.northeastChild;
};
QuadtreeTile.prototype.findTileToNorth = function(levelZeroTiles) {
const parent = this.parent;
if (parent === void 0) {
return this.findLevelZeroTile(levelZeroTiles, this.x, this.y - 1);
}
if (parent.southwestChild === this) {
return parent.northwestChild;
} else if (parent.southeastChild === this) {
return parent.northeastChild;
}
const northOfParent = parent.findTileToNorth(levelZeroTiles);
if (northOfParent === void 0) {
return void 0;
} else if (parent.northwestChild === this) {
return northOfParent.southwestChild;
}
return northOfParent.southeastChild;
};
QuadtreeTile.prototype.freeResources = function() {
this.clearPositionCache();
this.state = QuadtreeTileLoadState_default.START;
this.renderable = false;
this.upsampledFromParent = false;
if (defined_default(this.data) && defined_default(this.data.freeResources)) {
this.data.freeResources();
}
freeTile(this._southwestChild);
this._southwestChild = void 0;
freeTile(this._southeastChild);
this._southeastChild = void 0;
freeTile(this._northwestChild);
this._northwestChild = void 0;
freeTile(this._northeastChild);
this._northeastChild = void 0;
};
function freeTile(tile) {
if (defined_default(tile)) {
tile.freeResources();
}
}
var QuadtreeTile_default = QuadtreeTile;
// packages/engine/Source/Scene/TileReplacementQueue.js
var import_InlineWorkers1028 = __toESM(require_InlineWorkers(), 1);
function TileReplacementQueue() {
this.head = void 0;
this.tail = void 0;
this.count = 0;
this._lastBeforeStartOfFrame = void 0;
}
TileReplacementQueue.prototype.markStartOfRenderFrame = function() {
this._lastBeforeStartOfFrame = this.head;
};
TileReplacementQueue.prototype.trimTiles = function(maximumTiles) {
let tileToTrim = this.tail;
let keepTrimming = true;
while (keepTrimming && defined_default(this._lastBeforeStartOfFrame) && this.count > maximumTiles && defined_default(tileToTrim)) {
keepTrimming = tileToTrim !== this._lastBeforeStartOfFrame;
const previous = tileToTrim.replacementPrevious;
if (tileToTrim.eligibleForUnloading) {
tileToTrim.freeResources();
remove3(this, tileToTrim);
}
tileToTrim = previous;
}
};
function remove3(tileReplacementQueue, item) {
const previous = item.replacementPrevious;
const next = item.replacementNext;
if (item === tileReplacementQueue._lastBeforeStartOfFrame) {
tileReplacementQueue._lastBeforeStartOfFrame = next;
}
if (item === tileReplacementQueue.head) {
tileReplacementQueue.head = next;
} else {
previous.replacementNext = next;
}
if (item === tileReplacementQueue.tail) {
tileReplacementQueue.tail = previous;
} else {
next.replacementPrevious = previous;
}
item.replacementPrevious = void 0;
item.replacementNext = void 0;
--tileReplacementQueue.count;
}
TileReplacementQueue.prototype.markTileRendered = function(item) {
const head = this.head;
if (head === item) {
if (item === this._lastBeforeStartOfFrame) {
this._lastBeforeStartOfFrame = item.replacementNext;
}
return;
}
++this.count;
if (!defined_default(head)) {
item.replacementPrevious = void 0;
item.replacementNext = void 0;
this.head = item;
this.tail = item;
return;
}
if (defined_default(item.replacementPrevious) || defined_default(item.replacementNext)) {
remove3(this, item);
}
item.replacementPrevious = void 0;
item.replacementNext = head;
head.replacementPrevious = item;
this.head = item;
};
var TileReplacementQueue_default = TileReplacementQueue;
// packages/engine/Source/Scene/QuadtreePrimitive.js
function QuadtreePrimitive(options) {
if (!defined_default(options) || !defined_default(options.tileProvider)) {
throw new DeveloperError_default("options.tileProvider is required.");
}
if (defined_default(options.tileProvider.quadtree)) {
throw new DeveloperError_default(
"A QuadtreeTileProvider can only be used with a single QuadtreePrimitive"
);
}
this._tileProvider = options.tileProvider;
this._tileProvider.quadtree = this;
this._debug = {
enableDebugOutput: false,
maxDepth: 0,
maxDepthVisited: 0,
tilesVisited: 0,
tilesCulled: 0,
tilesRendered: 0,
tilesWaitingForChildren: 0,
lastMaxDepth: -1,
lastMaxDepthVisited: -1,
lastTilesVisited: -1,
lastTilesCulled: -1,
lastTilesRendered: -1,
lastTilesWaitingForChildren: -1,
suspendLodUpdate: false
};
const tilingScheme2 = this._tileProvider.tilingScheme;
const ellipsoid = tilingScheme2.ellipsoid;
this._tilesToRender = [];
this._tileLoadQueueHigh = [];
this._tileLoadQueueMedium = [];
this._tileLoadQueueLow = [];
this._tileReplacementQueue = new TileReplacementQueue_default();
this._levelZeroTiles = void 0;
this._loadQueueTimeSlice = 5;
this._tilesInvalidated = false;
this._addHeightCallbacks = [];
this._removeHeightCallbacks = [];
this._tileToUpdateHeights = [];
this._lastTileIndex = 0;
this._updateHeightsTimeSlice = 2;
this._cameraPositionCartographic = void 0;
this._cameraReferenceFrameOriginCartographic = void 0;
this.maximumScreenSpaceError = options.maximumScreenSpaceError ?? 2;
this.tileCacheSize = options.tileCacheSize ?? 100;
this.loadingDescendantLimit = 20;
this.preloadAncestors = true;
this.preloadSiblings = false;
this._occluders = new QuadtreeOccluders_default({
ellipsoid
});
this._tileLoadProgressEvent = new Event_default();
this._lastTileLoadQueueLength = 0;
this._lastSelectionFrameNumber = void 0;
}
Object.defineProperties(QuadtreePrimitive.prototype, {
/**
* Gets the provider of {@link QuadtreeTile} instances for this quadtree.
* @type {QuadtreeTile}
* @memberof QuadtreePrimitive.prototype
*/
tileProvider: {
get: function() {
return this._tileProvider;
}
},
/**
* Gets an event that's raised when the length of the tile load queue has changed since the last render frame. When the load queue is empty,
* all terrain and imagery for the current view have been loaded. The event passes the new length of the tile load queue.
*
* @memberof QuadtreePrimitive.prototype
* @type {Event}
*/
tileLoadProgressEvent: {
get: function() {
return this._tileLoadProgressEvent;
}
},
occluders: {
get: function() {
return this._occluders;
}
}
});
QuadtreePrimitive.prototype.invalidateAllTiles = function() {
this._tilesInvalidated = true;
};
function invalidateAllTiles(primitive) {
const replacementQueue = primitive._tileReplacementQueue;
replacementQueue.head = void 0;
replacementQueue.tail = void 0;
replacementQueue.count = 0;
clearTileLoadQueue(primitive);
const levelZeroTiles = primitive._levelZeroTiles;
if (defined_default(levelZeroTiles)) {
for (let i = 0; i < levelZeroTiles.length; ++i) {
const tile = levelZeroTiles[i];
const customData = tile.customData;
const customDataLength = customData.length;
for (let j = 0; j < customDataLength; ++j) {
const data = customData[j];
data.level = 0;
primitive._addHeightCallbacks.push(data);
}
levelZeroTiles[i].freeResources();
}
}
primitive._levelZeroTiles = void 0;
primitive._tileProvider.cancelReprojections();
}
QuadtreePrimitive.prototype.forEachLoadedTile = function(tileFunction) {
let tile = this._tileReplacementQueue.head;
while (defined_default(tile)) {
if (tile.state !== QuadtreeTileLoadState_default.START) {
tileFunction(tile);
}
tile = tile.replacementNext;
}
};
QuadtreePrimitive.prototype.forEachRenderedTile = function(tileFunction) {
const tilesRendered = this._tilesToRender;
for (let i = 0, len = tilesRendered.length; i < len; ++i) {
tileFunction(tilesRendered[i]);
}
};
QuadtreePrimitive.prototype.updateHeight = function(cartographic2, callback) {
const primitive = this;
const object2 = {
positionOnEllipsoidSurface: void 0,
positionCartographic: cartographic2,
level: -1,
callback
};
object2.removeFunc = function() {
const addedCallbacks = primitive._addHeightCallbacks;
const length2 = addedCallbacks.length;
for (let i = 0; i < length2; ++i) {
if (addedCallbacks[i] === object2) {
addedCallbacks.splice(i, 1);
break;
}
}
primitive._removeHeightCallbacks.push(object2);
if (object2.callback) {
object2.callback = void 0;
}
};
primitive._addHeightCallbacks.push(object2);
return object2.removeFunc;
};
QuadtreePrimitive.prototype.update = function(frameState) {
if (defined_default(this._tileProvider.update)) {
this._tileProvider.update(frameState);
}
};
function clearTileLoadQueue(primitive) {
const debug = primitive._debug;
debug.maxDepth = 0;
debug.maxDepthVisited = 0;
debug.tilesVisited = 0;
debug.tilesCulled = 0;
debug.tilesRendered = 0;
debug.tilesWaitingForChildren = 0;
primitive._tileLoadQueueHigh.length = 0;
primitive._tileLoadQueueMedium.length = 0;
primitive._tileLoadQueueLow.length = 0;
}
QuadtreePrimitive.prototype.beginFrame = function(frameState) {
const passes = frameState.passes;
if (!passes.render) {
return;
}
if (this._tilesInvalidated) {
invalidateAllTiles(this);
this._tilesInvalidated = false;
}
this._tileProvider.initialize(frameState);
clearTileLoadQueue(this);
if (this._debug.suspendLodUpdate) {
return;
}
this._tileReplacementQueue.markStartOfRenderFrame();
};
QuadtreePrimitive.prototype.render = function(frameState) {
const passes = frameState.passes;
const tileProvider = this._tileProvider;
if (passes.render) {
tileProvider.beginUpdate(frameState);
selectTilesForRendering(this, frameState);
createRenderCommandsForSelectedTiles(this, frameState);
tileProvider.endUpdate(frameState);
}
if (passes.pick && this._tilesToRender.length > 0) {
tileProvider.updateForPick(frameState);
}
};
function updateTileLoadProgress(primitive, frameState) {
const currentLoadQueueLength = primitive._tileLoadQueueHigh.length + primitive._tileLoadQueueMedium.length + primitive._tileLoadQueueLow.length;
if (currentLoadQueueLength !== primitive._lastTileLoadQueueLength || primitive._tilesInvalidated) {
const raiseEvent = Event_default.prototype.raiseEvent.bind(
primitive._tileLoadProgressEvent,
currentLoadQueueLength
);
frameState.afterRender.push(() => {
raiseEvent();
return true;
});
primitive._lastTileLoadQueueLength = currentLoadQueueLength;
}
const debug = primitive._debug;
if (debug.enableDebugOutput && !debug.suspendLodUpdate) {
debug.maxDepth = primitive._tilesToRender.reduce(function(max3, tile) {
return Math.max(max3, tile.level);
}, -1);
debug.tilesRendered = primitive._tilesToRender.length;
if (debug.tilesVisited !== debug.lastTilesVisited || debug.tilesRendered !== debug.lastTilesRendered || debug.tilesCulled !== debug.lastTilesCulled || debug.maxDepth !== debug.lastMaxDepth || debug.tilesWaitingForChildren !== debug.lastTilesWaitingForChildren || debug.maxDepthVisited !== debug.lastMaxDepthVisited) {
console.log(
`Visited ${debug.tilesVisited}, Rendered: ${debug.tilesRendered}, Culled: ${debug.tilesCulled}, Max Depth Rendered: ${debug.maxDepth}, Max Depth Visited: ${debug.maxDepthVisited}, Waiting for children: ${debug.tilesWaitingForChildren}`
);
debug.lastTilesVisited = debug.tilesVisited;
debug.lastTilesRendered = debug.tilesRendered;
debug.lastTilesCulled = debug.tilesCulled;
debug.lastMaxDepth = debug.maxDepth;
debug.lastTilesWaitingForChildren = debug.tilesWaitingForChildren;
debug.lastMaxDepthVisited = debug.maxDepthVisited;
}
}
}
QuadtreePrimitive.prototype.endFrame = function(frameState) {
const passes = frameState.passes;
if (!passes.render || frameState.mode === SceneMode_default.MORPHING) {
return;
}
processTileLoadQueue(this, frameState);
updateHeights2(this, frameState);
updateTileLoadProgress(this, frameState);
};
QuadtreePrimitive.prototype.isDestroyed = function() {
return false;
};
QuadtreePrimitive.prototype.destroy = function() {
this._tileProvider = this._tileProvider && this._tileProvider.destroy();
};
var comparisonPoint;
var centerScratch5 = new Cartographic_default();
function compareDistanceToPoint(a3, b) {
let center = Rectangle_default.center(a3.rectangle, centerScratch5);
const alon = center.longitude - comparisonPoint.longitude;
const alat = center.latitude - comparisonPoint.latitude;
center = Rectangle_default.center(b.rectangle, centerScratch5);
const blon = center.longitude - comparisonPoint.longitude;
const blat = center.latitude - comparisonPoint.latitude;
return alon * alon + alat * alat - (blon * blon + blat * blat);
}
var cameraOriginScratch = new Cartesian3_default();
var rootTraversalDetails = [];
function selectTilesForRendering(primitive, frameState) {
const debug = primitive._debug;
if (debug.suspendLodUpdate) {
return;
}
const tilesToRender = primitive._tilesToRender;
tilesToRender.length = 0;
let i;
const tileProvider = primitive._tileProvider;
if (!defined_default(primitive._levelZeroTiles)) {
const tilingScheme2 = tileProvider.tilingScheme;
if (defined_default(tilingScheme2)) {
const tilingScheme3 = tileProvider.tilingScheme;
primitive._levelZeroTiles = QuadtreeTile_default.createLevelZeroTiles(tilingScheme3);
const numberOfRootTiles = primitive._levelZeroTiles.length;
if (rootTraversalDetails.length < numberOfRootTiles) {
rootTraversalDetails = new Array(numberOfRootTiles);
for (i = 0; i < numberOfRootTiles; ++i) {
if (rootTraversalDetails[i] === void 0) {
rootTraversalDetails[i] = new TraversalDetails();
}
}
}
} else {
return;
}
}
primitive._occluders.ellipsoid.cameraPosition = frameState.camera.positionWC;
let tile;
const levelZeroTiles = primitive._levelZeroTiles;
const occluders = levelZeroTiles.length > 1 ? primitive._occluders : void 0;
comparisonPoint = frameState.camera.positionCartographic;
levelZeroTiles.sort(compareDistanceToPoint);
const customDataAdded = primitive._addHeightCallbacks;
const customDataRemoved = primitive._removeHeightCallbacks;
const frameNumber = frameState.frameNumber;
let len;
if (customDataAdded.length > 0 || customDataRemoved.length > 0) {
for (i = 0, len = levelZeroTiles.length; i < len; ++i) {
tile = levelZeroTiles[i];
tile._updateCustomData(frameNumber, customDataAdded, customDataRemoved);
}
customDataAdded.length = 0;
customDataRemoved.length = 0;
}
const camera = frameState.camera;
primitive._cameraPositionCartographic = camera.positionCartographic;
const cameraFrameOrigin = Matrix4_default.getTranslation(
camera.transform,
cameraOriginScratch
);
primitive._cameraReferenceFrameOriginCartographic = primitive.tileProvider.tilingScheme.ellipsoid.cartesianToCartographic(
cameraFrameOrigin,
primitive._cameraReferenceFrameOriginCartographic
);
for (i = 0, len = levelZeroTiles.length; i < len; ++i) {
tile = levelZeroTiles[i];
primitive._tileReplacementQueue.markTileRendered(tile);
if (!tile.renderable) {
queueTileLoad(primitive, primitive._tileLoadQueueHigh, tile, frameState);
++debug.tilesWaitingForChildren;
} else {
visitIfVisible(
primitive,
tile,
tileProvider,
frameState,
occluders,
false,
rootTraversalDetails[i]
);
}
}
primitive._lastSelectionFrameNumber = frameNumber;
}
function queueTileLoad(primitive, queue, tile, frameState) {
if (!tile.needsLoading) {
return;
}
if (primitive.tileProvider.computeTileLoadPriority !== void 0) {
tile._loadPriority = primitive.tileProvider.computeTileLoadPriority(
tile,
frameState
);
}
queue.push(tile);
}
function TraversalDetails() {
this.allAreRenderable = true;
this.anyWereRenderedLastFrame = false;
this.notYetRenderableCount = 0;
}
function TraversalQuadDetails() {
this.southwest = new TraversalDetails();
this.southeast = new TraversalDetails();
this.northwest = new TraversalDetails();
this.northeast = new TraversalDetails();
}
TraversalQuadDetails.prototype.combine = function(result) {
const southwest = this.southwest;
const southeast = this.southeast;
const northwest = this.northwest;
const northeast = this.northeast;
result.allAreRenderable = southwest.allAreRenderable && southeast.allAreRenderable && northwest.allAreRenderable && northeast.allAreRenderable;
result.anyWereRenderedLastFrame = southwest.anyWereRenderedLastFrame || southeast.anyWereRenderedLastFrame || northwest.anyWereRenderedLastFrame || northeast.anyWereRenderedLastFrame;
result.notYetRenderableCount = southwest.notYetRenderableCount + southeast.notYetRenderableCount + northwest.notYetRenderableCount + northeast.notYetRenderableCount;
};
var traversalQuadsByLevel = new Array(31);
for (let i = 0; i < traversalQuadsByLevel.length; ++i) {
traversalQuadsByLevel[i] = new TraversalQuadDetails();
}
function visitTile2(primitive, frameState, tile, ancestorMeetsSse, traversalDetails) {
const debug = primitive._debug;
++debug.tilesVisited;
primitive._tileReplacementQueue.markTileRendered(tile);
tile._updateCustomData(frameState.frameNumber);
if (tile.level > debug.maxDepthVisited) {
debug.maxDepthVisited = tile.level;
}
const meetsSse = screenSpaceError(primitive, frameState, tile) < primitive.maximumScreenSpaceError;
const southwestChild = tile.southwestChild;
const southeastChild = tile.southeastChild;
const northwestChild = tile.northwestChild;
const northeastChild = tile.northeastChild;
const lastFrame = primitive._lastSelectionFrameNumber;
const lastFrameSelectionResult = tile._lastSelectionResultFrame === lastFrame ? tile._lastSelectionResult : TileSelectionResult_default.NONE;
const tileProvider = primitive.tileProvider;
if (meetsSse || ancestorMeetsSse) {
const oneRenderedLastFrame = TileSelectionResult_default.originalResult(lastFrameSelectionResult) === TileSelectionResult_default.RENDERED;
const twoCulledOrNotVisited = TileSelectionResult_default.originalResult(lastFrameSelectionResult) === TileSelectionResult_default.CULLED || lastFrameSelectionResult === TileSelectionResult_default.NONE;
const threeCompletelyLoaded = tile.state === QuadtreeTileLoadState_default.DONE;
let renderable = oneRenderedLastFrame || twoCulledOrNotVisited || threeCompletelyLoaded;
if (!renderable) {
if (defined_default(tileProvider.canRenderWithoutLosingDetail)) {
renderable = tileProvider.canRenderWithoutLosingDetail(tile);
}
}
if (renderable) {
if (meetsSse) {
queueTileLoad(
primitive,
primitive._tileLoadQueueMedium,
tile,
frameState
);
}
addTileToRenderList(primitive, tile);
traversalDetails.allAreRenderable = tile.renderable;
traversalDetails.anyWereRenderedLastFrame = lastFrameSelectionResult === TileSelectionResult_default.RENDERED;
traversalDetails.notYetRenderableCount = tile.renderable ? 0 : 1;
tile._lastSelectionResultFrame = frameState.frameNumber;
tile._lastSelectionResult = TileSelectionResult_default.RENDERED;
if (!traversalDetails.anyWereRenderedLastFrame) {
primitive._tileToUpdateHeights.push(tile);
}
return;
}
ancestorMeetsSse = true;
if (meetsSse) {
queueTileLoad(primitive, primitive._tileLoadQueueHigh, tile, frameState);
}
}
if (tileProvider.canRefine(tile)) {
const allAreUpsampled = southwestChild.upsampledFromParent && southeastChild.upsampledFromParent && northwestChild.upsampledFromParent && northeastChild.upsampledFromParent;
if (allAreUpsampled) {
addTileToRenderList(primitive, tile);
queueTileLoad(
primitive,
primitive._tileLoadQueueMedium,
tile,
frameState
);
primitive._tileReplacementQueue.markTileRendered(southwestChild);
primitive._tileReplacementQueue.markTileRendered(southeastChild);
primitive._tileReplacementQueue.markTileRendered(northwestChild);
primitive._tileReplacementQueue.markTileRendered(northeastChild);
traversalDetails.allAreRenderable = tile.renderable;
traversalDetails.anyWereRenderedLastFrame = lastFrameSelectionResult === TileSelectionResult_default.RENDERED;
traversalDetails.notYetRenderableCount = tile.renderable ? 0 : 1;
tile._lastSelectionResultFrame = frameState.frameNumber;
tile._lastSelectionResult = TileSelectionResult_default.RENDERED;
if (!traversalDetails.anyWereRenderedLastFrame) {
primitive._tileToUpdateHeights.push(tile);
}
return;
}
tile._lastSelectionResultFrame = frameState.frameNumber;
tile._lastSelectionResult = TileSelectionResult_default.REFINED;
const firstRenderedDescendantIndex = primitive._tilesToRender.length;
const loadIndexLow = primitive._tileLoadQueueLow.length;
const loadIndexMedium = primitive._tileLoadQueueMedium.length;
const loadIndexHigh = primitive._tileLoadQueueHigh.length;
const tilesToUpdateHeightsIndex = primitive._tileToUpdateHeights.length;
visitVisibleChildrenNearToFar(
primitive,
southwestChild,
southeastChild,
northwestChild,
northeastChild,
frameState,
ancestorMeetsSse,
traversalDetails
);
if (firstRenderedDescendantIndex !== primitive._tilesToRender.length) {
const allAreRenderable = traversalDetails.allAreRenderable;
const anyWereRenderedLastFrame = traversalDetails.anyWereRenderedLastFrame;
const notYetRenderableCount = traversalDetails.notYetRenderableCount;
let queuedForLoad = false;
if (!allAreRenderable && !anyWereRenderedLastFrame) {
const renderList = primitive._tilesToRender;
for (let i = firstRenderedDescendantIndex; i < renderList.length; ++i) {
let workTile = renderList[i];
while (workTile !== void 0 && workTile._lastSelectionResult !== TileSelectionResult_default.KICKED && workTile !== tile) {
workTile._lastSelectionResult = TileSelectionResult_default.kick(
workTile._lastSelectionResult
);
workTile = workTile.parent;
}
}
primitive._tilesToRender.length = firstRenderedDescendantIndex;
primitive._tileToUpdateHeights.length = tilesToUpdateHeightsIndex;
addTileToRenderList(primitive, tile);
tile._lastSelectionResult = TileSelectionResult_default.RENDERED;
const wasRenderedLastFrame = lastFrameSelectionResult === TileSelectionResult_default.RENDERED;
if (!wasRenderedLastFrame && notYetRenderableCount > primitive.loadingDescendantLimit) {
primitive._tileLoadQueueLow.length = loadIndexLow;
primitive._tileLoadQueueMedium.length = loadIndexMedium;
primitive._tileLoadQueueHigh.length = loadIndexHigh;
queueTileLoad(
primitive,
primitive._tileLoadQueueMedium,
tile,
frameState
);
traversalDetails.notYetRenderableCount = tile.renderable ? 0 : 1;
queuedForLoad = true;
}
traversalDetails.allAreRenderable = tile.renderable;
traversalDetails.anyWereRenderedLastFrame = wasRenderedLastFrame;
if (!wasRenderedLastFrame) {
primitive._tileToUpdateHeights.push(tile);
}
++debug.tilesWaitingForChildren;
}
if (primitive.preloadAncestors && !queuedForLoad) {
queueTileLoad(primitive, primitive._tileLoadQueueLow, tile, frameState);
}
}
return;
}
tile._lastSelectionResultFrame = frameState.frameNumber;
tile._lastSelectionResult = TileSelectionResult_default.RENDERED;
addTileToRenderList(primitive, tile);
queueTileLoad(primitive, primitive._tileLoadQueueHigh, tile, frameState);
traversalDetails.allAreRenderable = tile.renderable;
traversalDetails.anyWereRenderedLastFrame = lastFrameSelectionResult === TileSelectionResult_default.RENDERED;
traversalDetails.notYetRenderableCount = tile.renderable ? 0 : 1;
}
function visitVisibleChildrenNearToFar(primitive, southwest, southeast, northwest, northeast, frameState, ancestorMeetsSse, traversalDetails) {
const cameraPosition = frameState.camera.positionCartographic;
const tileProvider = primitive._tileProvider;
const occluders = primitive._occluders;
const quadDetails = traversalQuadsByLevel[southwest.level];
const southwestDetails = quadDetails.southwest;
const southeastDetails = quadDetails.southeast;
const northwestDetails = quadDetails.northwest;
const northeastDetails = quadDetails.northeast;
if (cameraPosition.longitude < southwest.rectangle.east) {
if (cameraPosition.latitude < southwest.rectangle.north) {
visitIfVisible(
primitive,
southwest,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
southwestDetails
);
visitIfVisible(
primitive,
southeast,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
southeastDetails
);
visitIfVisible(
primitive,
northwest,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
northwestDetails
);
visitIfVisible(
primitive,
northeast,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
northeastDetails
);
} else {
visitIfVisible(
primitive,
northwest,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
northwestDetails
);
visitIfVisible(
primitive,
southwest,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
southwestDetails
);
visitIfVisible(
primitive,
northeast,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
northeastDetails
);
visitIfVisible(
primitive,
southeast,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
southeastDetails
);
}
} else if (cameraPosition.latitude < southwest.rectangle.north) {
visitIfVisible(
primitive,
southeast,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
southeastDetails
);
visitIfVisible(
primitive,
southwest,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
southwestDetails
);
visitIfVisible(
primitive,
northeast,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
northeastDetails
);
visitIfVisible(
primitive,
northwest,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
northwestDetails
);
} else {
visitIfVisible(
primitive,
northeast,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
northeastDetails
);
visitIfVisible(
primitive,
northwest,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
northwestDetails
);
visitIfVisible(
primitive,
southeast,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
southeastDetails
);
visitIfVisible(
primitive,
southwest,
tileProvider,
frameState,
occluders,
ancestorMeetsSse,
southwestDetails
);
}
quadDetails.combine(traversalDetails);
}
function containsNeededPosition(primitive, tile) {
const rectangle = tile.rectangle;
return defined_default(primitive._cameraPositionCartographic) && Rectangle_default.contains(rectangle, primitive._cameraPositionCartographic) || defined_default(primitive._cameraReferenceFrameOriginCartographic) && Rectangle_default.contains(
rectangle,
primitive._cameraReferenceFrameOriginCartographic
);
}
function visitIfVisible(primitive, tile, tileProvider, frameState, occluders, ancestorMeetsSse, traversalDetails) {
if (tileProvider.computeTileVisibility(tile, frameState, occluders) !== Visibility_default.NONE) {
return visitTile2(
primitive,
frameState,
tile,
ancestorMeetsSse,
traversalDetails
);
}
++primitive._debug.tilesCulled;
primitive._tileReplacementQueue.markTileRendered(tile);
traversalDetails.allAreRenderable = true;
traversalDetails.anyWereRenderedLastFrame = false;
traversalDetails.notYetRenderableCount = 0;
if (containsNeededPosition(primitive, tile)) {
if (!defined_default(tile.data) || !defined_default(tile.data.vertexArray)) {
queueTileLoad(
primitive,
primitive._tileLoadQueueMedium,
tile,
frameState
);
}
const lastFrame = primitive._lastSelectionFrameNumber;
const lastFrameSelectionResult = tile._lastSelectionResultFrame === lastFrame ? tile._lastSelectionResult : TileSelectionResult_default.NONE;
if (lastFrameSelectionResult !== TileSelectionResult_default.CULLED_BUT_NEEDED && lastFrameSelectionResult !== TileSelectionResult_default.RENDERED) {
primitive._tileToUpdateHeights.push(tile);
}
tile._lastSelectionResult = TileSelectionResult_default.CULLED_BUT_NEEDED;
} else if (primitive.preloadSiblings || tile.level === 0) {
queueTileLoad(primitive, primitive._tileLoadQueueLow, tile, frameState);
tile._lastSelectionResult = TileSelectionResult_default.CULLED;
} else {
tile._lastSelectionResult = TileSelectionResult_default.CULLED;
}
tile._lastSelectionResultFrame = frameState.frameNumber;
}
function screenSpaceError(primitive, frameState, tile) {
if (frameState.mode === SceneMode_default.SCENE2D || frameState.camera.frustum instanceof OrthographicFrustum_default || frameState.camera.frustum instanceof OrthographicOffCenterFrustum_default) {
return screenSpaceError2D(primitive, frameState, tile);
}
const maxGeometricError = primitive._tileProvider.getLevelMaximumGeometricError(tile.level);
const distance2 = tile._distance;
const height = frameState.context.drawingBufferHeight;
const sseDenominator = frameState.camera.frustum.sseDenominator;
let error = maxGeometricError * height / (distance2 * sseDenominator);
if (frameState.fog.enabled) {
error -= Math_default.fog(distance2, frameState.fog.density) * frameState.fog.sse;
}
error /= frameState.pixelRatio;
return error;
}
function screenSpaceError2D(primitive, frameState, tile) {
const camera = frameState.camera;
let frustum = camera.frustum;
const offCenterFrustum = frustum.offCenterFrustum;
if (defined_default(offCenterFrustum)) {
frustum = offCenterFrustum;
}
const context = frameState.context;
const width = context.drawingBufferWidth;
const height = context.drawingBufferHeight;
const maxGeometricError = primitive._tileProvider.getLevelMaximumGeometricError(tile.level);
const pixelSize = Math.max(frustum.top - frustum.bottom, frustum.right - frustum.left) / Math.max(width, height);
let error = maxGeometricError / pixelSize;
if (frameState.fog.enabled && frameState.mode !== SceneMode_default.SCENE2D) {
error -= Math_default.fog(tile._distance, frameState.fog.density) * frameState.fog.sse;
}
error /= frameState.pixelRatio;
return error;
}
function addTileToRenderList(primitive, tile) {
primitive._tilesToRender.push(tile);
}
function processTileLoadQueue(primitive, frameState) {
const tileLoadQueueHigh = primitive._tileLoadQueueHigh;
const tileLoadQueueMedium = primitive._tileLoadQueueMedium;
const tileLoadQueueLow = primitive._tileLoadQueueLow;
if (tileLoadQueueHigh.length === 0 && tileLoadQueueMedium.length === 0 && tileLoadQueueLow.length === 0) {
return;
}
primitive._tileReplacementQueue.trimTiles(primitive.tileCacheSize);
const endTime = getTimestamp_default() + primitive._loadQueueTimeSlice;
const tileProvider = primitive._tileProvider;
let didSomeLoading = processSinglePriorityLoadQueue(
primitive,
frameState,
tileProvider,
endTime,
tileLoadQueueHigh,
false
);
didSomeLoading = processSinglePriorityLoadQueue(
primitive,
frameState,
tileProvider,
endTime,
tileLoadQueueMedium,
didSomeLoading
);
processSinglePriorityLoadQueue(
primitive,
frameState,
tileProvider,
endTime,
tileLoadQueueLow,
didSomeLoading
);
}
function sortByLoadPriority(a3, b) {
return a3._loadPriority - b._loadPriority;
}
function processSinglePriorityLoadQueue(primitive, frameState, tileProvider, endTime, loadQueue, didSomeLoading) {
if (tileProvider.computeTileLoadPriority !== void 0) {
loadQueue.sort(sortByLoadPriority);
}
for (let i = 0, len = loadQueue.length; i < len && (getTimestamp_default() < endTime || !didSomeLoading); ++i) {
const tile = loadQueue[i];
primitive._tileReplacementQueue.markTileRendered(tile);
tileProvider.loadTile(frameState, tile);
didSomeLoading = true;
}
return didSomeLoading;
}
var scratchRay = new Ray_default();
var scratchCartographic19 = new Cartographic_default();
var scratchPosition13 = new Cartesian3_default();
var scratchArray2 = [];
function updateHeights2(primitive, frameState) {
if (!defined_default(primitive.tileProvider.tilingScheme)) {
return;
}
const tryNextFrame = scratchArray2;
tryNextFrame.length = 0;
const tilesToUpdateHeights = primitive._tileToUpdateHeights;
const startTime = getTimestamp_default();
const timeSlice = primitive._updateHeightsTimeSlice;
const endTime = startTime + timeSlice;
const mode2 = frameState.mode;
const projection = frameState.mapProjection;
const ellipsoid = primitive.tileProvider.tilingScheme.ellipsoid;
let i;
while (tilesToUpdateHeights.length > 0) {
const tile = tilesToUpdateHeights[0];
if (!defined_default(tile.data) || !defined_default(tile.data.mesh)) {
const selectionResult = tile._lastSelectionResultFrame === primitive._lastSelectionFrameNumber ? tile._lastSelectionResult : TileSelectionResult_default.NONE;
if (selectionResult === TileSelectionResult_default.RENDERED || selectionResult === TileSelectionResult_default.CULLED_BUT_NEEDED) {
tryNextFrame.push(tile);
}
tile.clearPositionCache();
tilesToUpdateHeights.shift();
primitive._lastTileIndex = 0;
continue;
}
const customData = tile.customData;
const customDataLength = customData.length;
let timeSliceMax = false;
for (i = primitive._lastTileIndex; i < customDataLength; ++i) {
const data = customData[i];
const terrainData = tile.data.terrainData;
const upsampledGeometryFromParent = defined_default(terrainData) && terrainData.wasCreatedByUpsampling();
if (tile.level > data.level && !upsampledGeometryFromParent) {
let position;
const cachedData = tile.getPositionCacheEntry(
data.positionCartographic,
primitive.maximumScreenSpaceError
);
if (defined_default(cachedData)) {
position = cachedData;
} else {
if (!defined_default(data.positionOnEllipsoidSurface)) {
data.positionOnEllipsoidSurface = Cartesian3_default.fromRadians(
data.positionCartographic.longitude,
data.positionCartographic.latitude,
0,
ellipsoid
);
}
if (mode2 === SceneMode_default.SCENE3D) {
const surfaceNormal = ellipsoid.geodeticSurfaceNormal(
data.positionOnEllipsoidSurface,
scratchRay.direction
);
const rayOrigin = ellipsoid.getSurfaceNormalIntersectionWithZAxis(
data.positionOnEllipsoidSurface,
11500,
scratchRay.origin
);
if (!defined_default(rayOrigin)) {
let minimumHeight = 0;
if (defined_default(tile.data.tileBoundingRegion)) {
minimumHeight = tile.data.tileBoundingRegion.minimumHeight;
}
const magnitude = Math.min(minimumHeight, -11500);
const vectorToMinimumPoint = Cartesian3_default.multiplyByScalar(
surfaceNormal,
Math.abs(magnitude) + 1,
scratchPosition13
);
Cartesian3_default.subtract(
data.positionOnEllipsoidSurface,
vectorToMinimumPoint,
scratchRay.origin
);
}
} else {
Cartographic_default.clone(data.positionCartographic, scratchCartographic19);
scratchCartographic19.height = -11500;
projection.project(scratchCartographic19, scratchPosition13);
Cartesian3_default.fromElements(
scratchPosition13.z,
scratchPosition13.x,
scratchPosition13.y,
scratchPosition13
);
Cartesian3_default.clone(scratchPosition13, scratchRay.origin);
Cartesian3_default.clone(Cartesian3_default.UNIT_X, scratchRay.direction);
}
position = tile.data.pick(
scratchRay,
mode2,
projection,
false,
scratchPosition13
);
if (defined_default(position)) {
tile.setPositionCacheEntry(
data.positionCartographic,
primitive.maximumScreenSpaceError,
position
);
}
}
if (defined_default(position)) {
if (defined_default(data.callback)) {
const positionCarto = ellipsoid.cartesianToCartographic(
position,
scratchCartographic19
);
data.callback(positionCarto);
}
data.level = tile.level;
}
}
if (getTimestamp_default() >= endTime) {
timeSliceMax = true;
break;
}
}
if (timeSliceMax) {
primitive._lastTileIndex = i;
break;
} else {
primitive._lastTileIndex = 0;
tilesToUpdateHeights.shift();
}
}
for (i = 0; i < tryNextFrame.length; i++) {
tilesToUpdateHeights.push(tryNextFrame[i]);
}
}
function createRenderCommandsForSelectedTiles(primitive, frameState) {
const tileProvider = primitive._tileProvider;
const tilesToRender = primitive._tilesToRender;
for (let i = 0, len = tilesToRender.length; i < len; ++i) {
const tile = tilesToRender[i];
tileProvider.showTileThisFrame(tile, frameState);
}
}
var QuadtreePrimitive_default = QuadtreePrimitive;
// packages/engine/Source/Scene/Globe.js
function Globe(ellipsoid) {
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
const terrainProvider = new EllipsoidTerrainProvider_default({
ellipsoid
});
const imageryLayerCollection = new ImageryLayerCollection_default();
this._ellipsoid = ellipsoid;
this._imageryLayerCollection = imageryLayerCollection;
this._surfaceShaderSet = new GlobeSurfaceShaderSet_default();
this._material = void 0;
this._surface = new QuadtreePrimitive_default({
tileProvider: new GlobeSurfaceTileProvider_default({
terrainProvider,
imageryLayers: imageryLayerCollection,
surfaceShaderSet: this._surfaceShaderSet
})
});
this._terrainProvider = terrainProvider;
this._terrainProviderChanged = new Event_default();
this._undergroundColor = Color_default.clone(Color_default.BLACK);
this._undergroundColorAlphaByDistance = new NearFarScalar_default(
ellipsoid.maximumRadius / 1e3,
0,
ellipsoid.maximumRadius / 5,
1
);
this._translucency = new GlobeTranslucency_default();
makeShadersDirty(this);
this.show = true;
this._oceanNormalMapResourceDirty = true;
this._oceanNormalMapResource = new Resource_default({
url: buildModuleUrl_default("Assets/Textures/waterNormalsSmall.jpg")
});
this.maximumScreenSpaceError = 2;
this.tileCacheSize = 100;
this.loadingDescendantLimit = 20;
this.preloadAncestors = true;
this.preloadSiblings = false;
this.fillHighlightColor = void 0;
this.enableLighting = false;
this.lambertDiffuseMultiplier = 0.9;
this.dynamicAtmosphereLighting = true;
this.dynamicAtmosphereLightingFromSun = false;
this.showGroundAtmosphere = Ellipsoid_default.WGS84.equals(ellipsoid);
this.atmosphereLightIntensity = 10;
this.atmosphereRayleighCoefficient = new Cartesian3_default(55e-7, 13e-6, 284e-7);
this.atmosphereMieCoefficient = new Cartesian3_default(21e-6, 21e-6, 21e-6);
this.atmosphereRayleighScaleHeight = 1e4;
this.atmosphereMieScaleHeight = 3200;
this.atmosphereMieAnisotropy = 0.9;
this.lightingFadeOutDistance = Math_default.PI_OVER_TWO * ellipsoid.minimumRadius;
this.lightingFadeInDistance = Math_default.PI * ellipsoid.minimumRadius;
this.nightFadeOutDistance = Math_default.PI_OVER_TWO * ellipsoid.minimumRadius;
this.nightFadeInDistance = 5 * Math_default.PI_OVER_TWO * ellipsoid.minimumRadius;
this.showWaterEffect = true;
this.depthTestAgainstTerrain = false;
this.shadows = ShadowMode_default.RECEIVE_ONLY;
this.atmosphereHueShift = 0;
this.atmosphereSaturationShift = 0;
this.atmosphereBrightnessShift = 0;
this.showSkirts = true;
this.backFaceCulling = true;
this._oceanNormalMap = void 0;
this._zoomedOutOceanSpecularIntensity = void 0;
this.vertexShadowDarkness = 0.3;
}
Object.defineProperties(Globe.prototype, {
/**
* Gets an ellipsoid describing the shape of this globe.
* @memberof Globe.prototype
* @type {Ellipsoid}
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
},
/**
* Gets the collection of image layers that will be rendered on this globe.
* @memberof Globe.prototype
* @type {ImageryLayerCollection}
*/
imageryLayers: {
get: function() {
return this._imageryLayerCollection;
}
},
/**
* Gets an event that's raised when an imagery layer is added, shown, hidden, moved, or removed.
*
* @memberof Globe.prototype
* @type {Event}
* @readonly
*/
imageryLayersUpdatedEvent: {
get: function() {
return this._surface.tileProvider.imageryLayersUpdatedEvent;
}
},
/**
* Returns true when the tile load queue is empty, false otherwise. When the load queue is empty,
* all terrain and imagery for the current view have been loaded.
* @memberof Globe.prototype
* @type {boolean}
* @readonly
*/
tilesLoaded: {
get: function() {
if (!defined_default(this._surface)) {
return true;
}
return this._surface._tileLoadQueueHigh.length === 0 && this._surface._tileLoadQueueMedium.length === 0 && this._surface._tileLoadQueueLow.length === 0;
}
},
/**
* Gets or sets the color of the globe when no imagery is available.
* @memberof Globe.prototype
* @type {Color}
*/
baseColor: {
get: function() {
return this._surface.tileProvider.baseColor;
},
set: function(value) {
this._surface.tileProvider.baseColor = value;
}
},
/**
* A property specifying a {@link ClippingPlaneCollection} used to selectively disable rendering on the outside of each plane.
*
* @memberof Globe.prototype
* @type {ClippingPlaneCollection}
*/
clippingPlanes: {
get: function() {
return this._surface.tileProvider.clippingPlanes;
},
set: function(value) {
this._surface.tileProvider.clippingPlanes = value;
}
},
/**
* A property specifying a {@link ClippingPolygonCollection} used to selectively disable rendering inside or outside a list of polygons.
*
* @memberof Globe.prototype
* @type {ClippingPolygonCollection}
*/
clippingPolygons: {
get: function() {
return this._surface.tileProvider.clippingPolygons;
},
set: function(value) {
this._surface.tileProvider.clippingPolygons = value;
}
},
/**
* A property specifying a {@link Rectangle} used to limit globe rendering to a cartographic area.
* Defaults to the maximum extent of cartographic coordinates.
*
* @memberof Globe.prototype
* @type {Rectangle}
* @default {@link Rectangle.MAX_VALUE}
*/
cartographicLimitRectangle: {
get: function() {
return this._surface.tileProvider.cartographicLimitRectangle;
},
set: function(value) {
if (!defined_default(value)) {
value = Rectangle_default.clone(Rectangle_default.MAX_VALUE);
}
this._surface.tileProvider.cartographicLimitRectangle = value;
}
},
/**
* The normal map to use for rendering waves in the ocean. Setting this property will
* only have an effect if the configured terrain provider includes a water mask.
* @memberof Globe.prototype
* @type {string}
* @default buildModuleUrl('Assets/Textures/waterNormalsSmall.jpg')
*/
oceanNormalMapUrl: {
get: function() {
return this._oceanNormalMapResource.url;
},
set: function(value) {
this._oceanNormalMapResource.url = value;
this._oceanNormalMapResourceDirty = true;
}
},
/**
* The terrain provider providing surface geometry for this globe.
* @type {TerrainProvider}
*
* @memberof Globe.prototype
* @type {TerrainProvider}
*
*/
terrainProvider: {
get: function() {
return this._terrainProvider;
},
set: function(value) {
if (value !== this._terrainProvider) {
this._terrainProvider = value;
this._terrainProviderChanged.raiseEvent(value);
if (defined_default(this._material)) {
makeShadersDirty(this);
}
}
}
},
/**
* Gets an event that's raised when the terrain provider is changed
*
* @memberof Globe.prototype
* @type {Event}
* @readonly
*/
terrainProviderChanged: {
get: function() {
return this._terrainProviderChanged;
}
},
/**
* Gets an event that's raised when the length of the tile load queue has changed since the last render frame. When the load queue is empty,
* all terrain and imagery for the current view have been loaded. The event passes the new length of the tile load queue.
*
* @memberof Globe.prototype
* @type {Event}
*/
tileLoadProgressEvent: {
get: function() {
return this._surface.tileLoadProgressEvent;
}
},
/**
* Gets or sets the material appearance of the Globe. This can be one of several built-in {@link Material} objects or a custom material, scripted with
* {@link https://github.com/CesiumGS/cesium/wiki/Fabric|Fabric}.
* @memberof Globe.prototype
* @type {Material | undefined}
*/
material: {
get: function() {
return this._material;
},
set: function(material) {
if (this._material !== material) {
this._material = material;
makeShadersDirty(this);
}
}
},
/**
* The color to render the back side of the globe when the camera is underground or the globe is translucent,
* blended with the globe color based on the camera's distance.
*
* To disable underground coloring, set undergroundColor to undefined.
*
* @memberof Globe.prototype
* @type {Color}
* @default {@link Color.BLACK}
*
* @see Globe#undergroundColorAlphaByDistance
*/
undergroundColor: {
get: function() {
return this._undergroundColor;
},
set: function(value) {
this._undergroundColor = Color_default.clone(value, this._undergroundColor);
}
},
/**
* Gets or sets the near and far distance for blending {@link Globe#undergroundColor} with the globe color.
* The alpha will interpolate between the {@link NearFarScalar#nearValue} and
* {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds
* of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
* Outside of these ranges the alpha remains clamped to the nearest bound. If undefined,
* the underground color will not be blended with the globe color.
*
* When the camera is above the ellipsoid the distance is computed from the nearest
* point on the ellipsoid instead of the camera's position.
*
* @memberof Globe.prototype
* @type {NearFarScalar}
*
* @see Globe#undergroundColor
*
*/
undergroundColorAlphaByDistance: {
get: function() {
return this._undergroundColorAlphaByDistance;
},
set: function(value) {
if (defined_default(value) && value.far < value.near) {
throw new DeveloperError_default(
"far distance must be greater than near distance."
);
}
this._undergroundColorAlphaByDistance = NearFarScalar_default.clone(
value,
this._undergroundColorAlphaByDistance
);
}
},
/**
* Properties for controlling globe translucency.
*
* @memberof Globe.prototype
* @type {GlobeTranslucency}
*/
translucency: {
get: function() {
return this._translucency;
}
}
});
function makeShadersDirty(globe) {
const defines = [];
const requireNormals = defined_default(globe._material) && (defined_default(globe._material.shaderSource.match(/slope/)) || defined_default(globe._material.shaderSource.match("normalEC")));
const fragmentSources = [AtmosphereCommon_default, GroundAtmosphere_default];
if (defined_default(globe._material) && (!requireNormals || globe._terrainProvider.requestVertexNormals)) {
fragmentSources.push(globe._material.shaderSource);
defines.push("APPLY_MATERIAL");
globe._surface._tileProvider.materialUniformMap = globe._material._uniforms;
} else {
globe._surface._tileProvider.materialUniformMap = void 0;
}
fragmentSources.push(GlobeFS_default);
globe._surfaceShaderSet.baseVertexShaderSource = new ShaderSource_default({
sources: [AtmosphereCommon_default, GroundAtmosphere_default, GlobeVS_default],
defines
});
globe._surfaceShaderSet.baseFragmentShaderSource = new ShaderSource_default({
sources: fragmentSources,
defines
});
globe._surfaceShaderSet.material = globe._material;
}
function createComparePickTileFunction(rayOrigin) {
return function(a3, b) {
const aDist = BoundingSphere_default.distanceSquaredTo(
a3.pickBoundingSphere,
rayOrigin
);
const bDist = BoundingSphere_default.distanceSquaredTo(
b.pickBoundingSphere,
rayOrigin
);
return aDist - bDist;
};
}
var scratchArray3 = [];
var scratchSphereIntersectionResult = {
start: 0,
stop: 0
};
Globe.prototype.pickWorldCoordinates = function(ray, scene, cullBackFaces, result) {
if (!defined_default(ray)) {
throw new DeveloperError_default("ray is required");
}
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required");
}
cullBackFaces = cullBackFaces ?? true;
const mode2 = scene.mode;
const projection = scene.mapProjection;
const sphereIntersections = scratchArray3;
sphereIntersections.length = 0;
const tilesToRender = this._surface._tilesToRender;
let length2 = tilesToRender.length;
let tile;
let i;
for (i = 0; i < length2; ++i) {
tile = tilesToRender[i];
const surfaceTile = tile.data;
if (!defined_default(surfaceTile)) {
continue;
}
let boundingVolume = surfaceTile.pickBoundingSphere;
if (mode2 !== SceneMode_default.SCENE3D) {
surfaceTile.pickBoundingSphere = boundingVolume = BoundingSphere_default.fromRectangleWithHeights2D(
tile.rectangle,
projection,
surfaceTile.tileBoundingRegion.minimumHeight,
surfaceTile.tileBoundingRegion.maximumHeight,
boundingVolume
);
Cartesian3_default.fromElements(
boundingVolume.center.z,
boundingVolume.center.x,
boundingVolume.center.y,
boundingVolume.center
);
} else if (defined_default(surfaceTile.renderedMesh)) {
BoundingSphere_default.clone(
surfaceTile.tileBoundingRegion.boundingSphere,
boundingVolume
);
} else {
continue;
}
const boundingSphereIntersection = IntersectionTests_default.raySphere(
ray,
boundingVolume,
scratchSphereIntersectionResult
);
if (defined_default(boundingSphereIntersection)) {
sphereIntersections.push(surfaceTile);
}
}
sphereIntersections.sort(createComparePickTileFunction(ray.origin));
let intersection;
length2 = sphereIntersections.length;
for (i = 0; i < length2; ++i) {
intersection = sphereIntersections[i].pick(
ray,
scene.mode,
scene.mapProjection,
cullBackFaces,
result
);
if (defined_default(intersection)) {
break;
}
}
return intersection;
};
var cartoScratch3 = new Cartographic_default();
Globe.prototype.pick = function(ray, scene, result) {
result = this.pickWorldCoordinates(ray, scene, true, result);
if (defined_default(result) && scene.mode !== SceneMode_default.SCENE3D) {
result = Cartesian3_default.fromElements(result.y, result.z, result.x, result);
const carto = scene.mapProjection.unproject(result, cartoScratch3);
result = this._ellipsoid.cartographicToCartesian(carto, result);
}
return result;
};
var scratchGetHeightCartesian = new Cartesian3_default();
var scratchGetHeightIntersection = new Cartesian3_default();
var scratchGetHeightCartographic2 = new Cartographic_default();
var scratchGetHeightRay2 = new Ray_default();
function tileIfContainsCartographic(tile, cartographic2) {
return defined_default(tile) && Rectangle_default.contains(tile.rectangle, cartographic2) ? tile : void 0;
}
Globe.prototype.getHeight = function(cartographic2) {
if (!defined_default(cartographic2)) {
throw new DeveloperError_default("cartographic is required");
}
const levelZeroTiles = this._surface._levelZeroTiles;
if (!defined_default(levelZeroTiles)) {
return;
}
let tile;
let i;
const length2 = levelZeroTiles.length;
for (i = 0; i < length2; ++i) {
tile = levelZeroTiles[i];
if (Rectangle_default.contains(tile.rectangle, cartographic2)) {
break;
}
}
if (i >= length2) {
return void 0;
}
let tileWithMesh = tile;
while (defined_default(tile)) {
tile = tileIfContainsCartographic(tile._southwestChild, cartographic2) || tileIfContainsCartographic(tile._southeastChild, cartographic2) || tileIfContainsCartographic(tile._northwestChild, cartographic2) || tile._northeastChild;
if (defined_default(tile) && defined_default(tile.data) && defined_default(tile.data.renderedMesh)) {
tileWithMesh = tile;
}
}
tile = tileWithMesh;
if (!defined_default(tile) || !defined_default(tile.data) || !defined_default(tile.data.renderedMesh)) {
return void 0;
}
const projection = this._surface._tileProvider.tilingScheme.projection;
const ellipsoid = this._surface._tileProvider.tilingScheme.ellipsoid;
const cartesian11 = Cartesian3_default.fromRadians(
cartographic2.longitude,
cartographic2.latitude,
0,
ellipsoid,
scratchGetHeightCartesian
);
const ray = scratchGetHeightRay2;
const surfaceNormal = ellipsoid.geodeticSurfaceNormal(
cartesian11,
ray.direction
);
const rayOrigin = ellipsoid.getSurfaceNormalIntersectionWithZAxis(
cartesian11,
11500,
ray.origin
);
if (!defined_default(rayOrigin)) {
let minimumHeight;
if (defined_default(tile.data.tileBoundingRegion)) {
minimumHeight = tile.data.tileBoundingRegion.minimumHeight;
}
const magnitude = Math.min(minimumHeight ?? 0, -11500);
const vectorToMinimumPoint = Cartesian3_default.multiplyByScalar(
surfaceNormal,
Math.abs(magnitude) + 1,
scratchGetHeightIntersection
);
Cartesian3_default.subtract(cartesian11, vectorToMinimumPoint, ray.origin);
}
const intersection = tile.data.pick(
ray,
void 0,
projection,
false,
scratchGetHeightIntersection
);
if (!defined_default(intersection)) {
return void 0;
}
return ellipsoid.cartesianToCartographic(
intersection,
scratchGetHeightCartographic2
).height;
};
Globe.prototype.update = function(frameState) {
if (!this.show) {
return;
}
if (frameState.passes.render) {
this._surface.update(frameState);
}
};
Globe.prototype.beginFrame = function(frameState) {
const surface = this._surface;
const tileProvider = surface.tileProvider;
const terrainProvider = this.terrainProvider;
const hasWaterMask = defined_default(terrainProvider) && terrainProvider.hasWaterMask && terrainProvider.hasWaterMask;
if (hasWaterMask && this._oceanNormalMapResourceDirty) {
this._oceanNormalMapResourceDirty = false;
const oceanNormalMapResource = this._oceanNormalMapResource;
const oceanNormalMapUrl = oceanNormalMapResource.url;
if (defined_default(oceanNormalMapUrl)) {
const that = this;
oceanNormalMapResource.fetchImage().then(function(image) {
if (oceanNormalMapUrl !== that._oceanNormalMapResource.url) {
return;
}
that._oceanNormalMap = that._oceanNormalMap && that._oceanNormalMap.destroy();
that._oceanNormalMap = new Texture_default({
context: frameState.context,
source: image
});
});
} else {
this._oceanNormalMap = this._oceanNormalMap && this._oceanNormalMap.destroy();
}
}
const pass = frameState.passes;
const mode2 = frameState.mode;
if (pass.render) {
if (this.showGroundAtmosphere) {
this._zoomedOutOceanSpecularIntensity = 0.4;
} else {
this._zoomedOutOceanSpecularIntensity = 0.5;
}
surface.maximumScreenSpaceError = this.maximumScreenSpaceError;
surface.tileCacheSize = this.tileCacheSize;
surface.loadingDescendantLimit = this.loadingDescendantLimit;
surface.preloadAncestors = this.preloadAncestors;
surface.preloadSiblings = this.preloadSiblings;
tileProvider.terrainProvider = this.terrainProvider;
tileProvider.lightingFadeOutDistance = this.lightingFadeOutDistance;
tileProvider.lightingFadeInDistance = this.lightingFadeInDistance;
tileProvider.nightFadeOutDistance = this.nightFadeOutDistance;
tileProvider.nightFadeInDistance = this.nightFadeInDistance;
tileProvider.zoomedOutOceanSpecularIntensity = mode2 === SceneMode_default.SCENE3D ? this._zoomedOutOceanSpecularIntensity : 0;
tileProvider.hasWaterMask = hasWaterMask;
tileProvider.showWaterEffect = this.showWaterEffect;
tileProvider.oceanNormalMap = this._oceanNormalMap;
tileProvider.enableLighting = this.enableLighting;
tileProvider.dynamicAtmosphereLighting = this.dynamicAtmosphereLighting;
tileProvider.dynamicAtmosphereLightingFromSun = this.dynamicAtmosphereLightingFromSun;
tileProvider.showGroundAtmosphere = this.showGroundAtmosphere;
tileProvider.atmosphereLightIntensity = this.atmosphereLightIntensity;
tileProvider.atmosphereRayleighCoefficient = this.atmosphereRayleighCoefficient;
tileProvider.atmosphereMieCoefficient = this.atmosphereMieCoefficient;
tileProvider.atmosphereRayleighScaleHeight = this.atmosphereRayleighScaleHeight;
tileProvider.atmosphereMieScaleHeight = this.atmosphereMieScaleHeight;
tileProvider.atmosphereMieAnisotropy = this.atmosphereMieAnisotropy;
tileProvider.shadows = this.shadows;
tileProvider.hueShift = this.atmosphereHueShift;
tileProvider.saturationShift = this.atmosphereSaturationShift;
tileProvider.brightnessShift = this.atmosphereBrightnessShift;
tileProvider.fillHighlightColor = this.fillHighlightColor;
tileProvider.showSkirts = this.showSkirts;
tileProvider.backFaceCulling = this.backFaceCulling;
tileProvider.vertexShadowDarkness = this.vertexShadowDarkness;
tileProvider.undergroundColor = this._undergroundColor;
tileProvider.undergroundColorAlphaByDistance = this._undergroundColorAlphaByDistance;
tileProvider.lambertDiffuseMultiplier = this.lambertDiffuseMultiplier;
surface.beginFrame(frameState);
}
};
Globe.prototype.render = function(frameState) {
if (!this.show) {
return;
}
if (defined_default(this._material)) {
this._material.update(frameState.context);
}
this._surface.render(frameState);
};
Globe.prototype.endFrame = function(frameState) {
if (!this.show) {
return;
}
if (frameState.passes.render) {
this._surface.endFrame(frameState);
}
};
Globe.prototype.isDestroyed = function() {
return false;
};
Globe.prototype.destroy = function() {
this._surfaceShaderSet = this._surfaceShaderSet && this._surfaceShaderSet.destroy();
this._surface = this._surface && this._surface.destroy();
this._oceanNormalMap = this._oceanNormalMap && this._oceanNormalMap.destroy();
return destroyObject_default(this);
};
var Globe_default = Globe;
// packages/engine/Source/Scene/Moon.js
var import_InlineWorkers1037 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/IauOrientationAxes.js
var import_InlineWorkers1033 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/Iau2000Orientation.js
var import_InlineWorkers1032 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/IauOrientationParameters.js
var import_InlineWorkers1031 = __toESM(require_InlineWorkers(), 1);
function IauOrientationParameters(rightAscension, declination, rotation, rotationRate) {
this.rightAscension = rightAscension;
this.declination = declination;
this.rotation = rotation;
this.rotationRate = rotationRate;
}
var IauOrientationParameters_default = IauOrientationParameters;
// packages/engine/Source/Core/Iau2000Orientation.js
var Iau2000Orientation = {};
var TdtMinusTai3 = 32.184;
var J2000d3 = 2451545;
var c1 = -0.0529921;
var c2 = -0.1059842;
var c32 = 13.0120009;
var c4 = 13.3407154;
var c5 = 0.9856003;
var c6 = 26.4057084;
var c7 = 13.064993;
var c8 = 0.3287146;
var c9 = 1.7484877;
var c10 = -0.1589763;
var c11 = 36096e-7;
var c12 = 0.1643573;
var c13 = 12.9590088;
var dateTT = new JulianDate_default();
Iau2000Orientation.ComputeMoon = function(date, result) {
if (!defined_default(date)) {
date = JulianDate_default.now();
}
dateTT = JulianDate_default.addSeconds(date, TdtMinusTai3, dateTT);
const d = JulianDate_default.totalDays(dateTT) - J2000d3;
const T2 = d / TimeConstants_default.DAYS_PER_JULIAN_CENTURY;
const E1 = (125.045 + c1 * d) * Math_default.RADIANS_PER_DEGREE;
const E2 = (250.089 + c2 * d) * Math_default.RADIANS_PER_DEGREE;
const E3 = (260.008 + c32 * d) * Math_default.RADIANS_PER_DEGREE;
const E4 = (176.625 + c4 * d) * Math_default.RADIANS_PER_DEGREE;
const E5 = (357.529 + c5 * d) * Math_default.RADIANS_PER_DEGREE;
const E6 = (311.589 + c6 * d) * Math_default.RADIANS_PER_DEGREE;
const E7 = (134.963 + c7 * d) * Math_default.RADIANS_PER_DEGREE;
const E8 = (276.617 + c8 * d) * Math_default.RADIANS_PER_DEGREE;
const E9 = (34.226 + c9 * d) * Math_default.RADIANS_PER_DEGREE;
const E10 = (15.134 + c10 * d) * Math_default.RADIANS_PER_DEGREE;
const E11 = (119.743 + c11 * d) * Math_default.RADIANS_PER_DEGREE;
const E12 = (239.961 + c12 * d) * Math_default.RADIANS_PER_DEGREE;
const E13 = (25.053 + c13 * d) * Math_default.RADIANS_PER_DEGREE;
const sinE1 = Math.sin(E1);
const sinE2 = Math.sin(E2);
const sinE3 = Math.sin(E3);
const sinE4 = Math.sin(E4);
const sinE5 = Math.sin(E5);
const sinE6 = Math.sin(E6);
const sinE7 = Math.sin(E7);
const sinE8 = Math.sin(E8);
const sinE9 = Math.sin(E9);
const sinE10 = Math.sin(E10);
const sinE11 = Math.sin(E11);
const sinE12 = Math.sin(E12);
const sinE13 = Math.sin(E13);
const cosE1 = Math.cos(E1);
const cosE2 = Math.cos(E2);
const cosE3 = Math.cos(E3);
const cosE4 = Math.cos(E4);
const cosE5 = Math.cos(E5);
const cosE6 = Math.cos(E6);
const cosE7 = Math.cos(E7);
const cosE8 = Math.cos(E8);
const cosE9 = Math.cos(E9);
const cosE10 = Math.cos(E10);
const cosE11 = Math.cos(E11);
const cosE12 = Math.cos(E12);
const cosE13 = Math.cos(E13);
const rightAscension = (269.9949 + 31e-4 * T2 - 3.8787 * sinE1 - 0.1204 * sinE2 + 0.07 * sinE3 - 0.0172 * sinE4 + 72e-4 * sinE6 - 52e-4 * sinE10 + 43e-4 * sinE13) * Math_default.RADIANS_PER_DEGREE;
const declination = (66.5392 + 0.013 * T2 + 1.5419 * cosE1 + 0.0239 * cosE2 - 0.0278 * cosE3 + 68e-4 * cosE4 - 29e-4 * cosE6 + 9e-4 * cosE7 + 8e-4 * cosE10 - 9e-4 * cosE13) * Math_default.RADIANS_PER_DEGREE;
const rotation = (38.3213 + 13.17635815 * d - 14e-13 * d * d + 3.561 * sinE1 + 0.1208 * sinE2 - 0.0642 * sinE3 + 0.0158 * sinE4 + 0.0252 * sinE5 - 66e-4 * sinE6 - 47e-4 * sinE7 - 46e-4 * sinE8 + 28e-4 * sinE9 + 52e-4 * sinE10 + 4e-3 * sinE11 + 19e-4 * sinE12 - 44e-4 * sinE13) * Math_default.RADIANS_PER_DEGREE;
const rotationRate = (13.17635815 - 14e-13 * (2 * d) + 3.561 * cosE1 * c1 + 0.1208 * cosE2 * c2 - 0.0642 * cosE3 * c32 + 0.0158 * cosE4 * c4 + 0.0252 * cosE5 * c5 - 66e-4 * cosE6 * c6 - 47e-4 * cosE7 * c7 - 46e-4 * cosE8 * c8 + 28e-4 * cosE9 * c9 + 52e-4 * cosE10 * c10 + 4e-3 * cosE11 * c11 + 19e-4 * cosE12 * c12 - 44e-4 * cosE13 * c13) / 86400 * Math_default.RADIANS_PER_DEGREE;
if (!defined_default(result)) {
result = new IauOrientationParameters_default();
}
result.rightAscension = rightAscension;
result.declination = declination;
result.rotation = rotation;
result.rotationRate = rotationRate;
return result;
};
var Iau2000Orientation_default = Iau2000Orientation;
// packages/engine/Source/Core/IauOrientationAxes.js
function IauOrientationAxes(computeFunction) {
if (!defined_default(computeFunction) || typeof computeFunction !== "function") {
computeFunction = Iau2000Orientation_default.ComputeMoon;
}
this._computeFunction = computeFunction;
}
var xAxisScratch = new Cartesian3_default();
var yAxisScratch = new Cartesian3_default();
var zAxisScratch = new Cartesian3_default();
function computeRotationMatrix(alpha, delta, result) {
const xAxis = xAxisScratch;
xAxis.x = Math.cos(alpha + Math_default.PI_OVER_TWO);
xAxis.y = Math.sin(alpha + Math_default.PI_OVER_TWO);
xAxis.z = 0;
const cosDec = Math.cos(delta);
const zAxis = zAxisScratch;
zAxis.x = cosDec * Math.cos(alpha);
zAxis.y = cosDec * Math.sin(alpha);
zAxis.z = Math.sin(delta);
const yAxis = Cartesian3_default.cross(zAxis, xAxis, yAxisScratch);
if (!defined_default(result)) {
result = new Matrix3_default();
}
result[0] = xAxis.x;
result[1] = yAxis.x;
result[2] = zAxis.x;
result[3] = xAxis.y;
result[4] = yAxis.y;
result[5] = zAxis.y;
result[6] = xAxis.z;
result[7] = yAxis.z;
result[8] = zAxis.z;
return result;
}
var rotMtxScratch = new Matrix3_default();
var quatScratch = new Quaternion_default();
IauOrientationAxes.prototype.evaluate = function(date, result) {
if (!defined_default(date)) {
date = JulianDate_default.now();
}
const alphaDeltaW = this._computeFunction(date);
const precMtx = computeRotationMatrix(
alphaDeltaW.rightAscension,
alphaDeltaW.declination,
result
);
const rot = Math_default.zeroToTwoPi(alphaDeltaW.rotation);
const quat = Quaternion_default.fromAxisAngle(Cartesian3_default.UNIT_Z, rot, quatScratch);
const rotMtx2 = Matrix3_default.fromQuaternion(
Quaternion_default.conjugate(quat, quat),
rotMtxScratch
);
const cbi2cbf = Matrix3_default.multiply(rotMtx2, precMtx, precMtx);
return cbi2cbf;
};
var IauOrientationAxes_default = IauOrientationAxes;
// packages/engine/Source/Scene/EllipsoidPrimitive.js
var import_InlineWorkers1036 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/EllipsoidFS.js
var import_InlineWorkers1034 = __toESM(require_InlineWorkers(), 1);
var EllipsoidFS_default = "uniform vec3 u_radii;\nuniform vec3 u_oneOverEllipsoidRadiiSquared;\n\nin vec3 v_positionEC;\n\nvec4 computeEllipsoidColor(czm_ray ray, float intersection, float side)\n{\n vec3 positionEC = czm_pointAlongRay(ray, intersection);\n vec3 positionMC = (czm_inverseModelView * vec4(positionEC, 1.0)).xyz;\n vec3 geodeticNormal = normalize(czm_geodeticSurfaceNormal(positionMC, vec3(0.0), u_oneOverEllipsoidRadiiSquared));\n vec3 sphericalNormal = normalize(positionMC / u_radii);\n vec3 normalMC = geodeticNormal * side; // normalized surface normal (always facing the viewer) in model coordinates\n vec3 normalEC = normalize(czm_normal * normalMC); // normalized surface normal in eye coordinates\n\n vec2 st = czm_ellipsoidTextureCoordinates(sphericalNormal);\n vec3 positionToEyeEC = -positionEC;\n\n czm_materialInput materialInput;\n materialInput.s = st.s;\n materialInput.st = st;\n materialInput.str = (positionMC + u_radii) / u_radii;\n materialInput.normalEC = normalEC;\n materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(positionMC, normalEC);\n materialInput.positionToEyeEC = positionToEyeEC;\n czm_material material = czm_getMaterial(materialInput);\n\n#ifdef ONLY_SUN_LIGHTING\n return czm_private_phong(normalize(positionToEyeEC), material, czm_sunDirectionEC);\n#else\n return czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\n#endif\n}\n\nvoid main()\n{\n // PERFORMANCE_TODO: When dynamic branching is available, compute ratio of maximum and minimum radii\n // in the vertex shader. Only when it is larger than some constant, march along the ray.\n // Otherwise perform one intersection test which will be the common case.\n\n // Test if the ray intersects a sphere with the ellipsoid's maximum radius.\n // For very oblate ellipsoids, using the ellipsoid's radii for an intersection test\n // may cause false negatives. This will discard fragments before marching the ray forward.\n float maxRadius = max(u_radii.x, max(u_radii.y, u_radii.z)) * 1.5;\n vec3 direction = normalize(v_positionEC);\n vec3 ellipsoidCenter = czm_modelView[3].xyz;\n\n float t1 = -1.0;\n float t2 = -1.0;\n\n float b = -2.0 * dot(direction, ellipsoidCenter);\n float c = dot(ellipsoidCenter, ellipsoidCenter) - maxRadius * maxRadius;\n\n float discriminant = b * b - 4.0 * c;\n if (discriminant >= 0.0) {\n t1 = (-b - sqrt(discriminant)) * 0.5;\n t2 = (-b + sqrt(discriminant)) * 0.5;\n }\n\n if (t1 < 0.0 && t2 < 0.0) {\n discard;\n }\n\n float t = min(t1, t2);\n if (t < 0.0) {\n t = 0.0;\n }\n\n // March ray forward to intersection with larger sphere and find\n czm_ray ray = czm_ray(t * direction, direction);\n\n vec3 ellipsoid_inverseRadii = vec3(1.0 / u_radii.x, 1.0 / u_radii.y, 1.0 / u_radii.z);\n\n czm_raySegment intersection = czm_rayEllipsoidIntersectionInterval(ray, ellipsoidCenter, ellipsoid_inverseRadii);\n\n if (czm_isEmpty(intersection))\n {\n discard;\n }\n\n // If the viewer is outside, compute outsideFaceColor, with normals facing outward.\n vec4 outsideFaceColor = (intersection.start != 0.0) ? computeEllipsoidColor(ray, intersection.start, 1.0) : vec4(0.0);\n\n // If the viewer either is inside or can see inside, compute insideFaceColor, with normals facing inward.\n vec4 insideFaceColor = (outsideFaceColor.a < 1.0) ? computeEllipsoidColor(ray, intersection.stop, -1.0) : vec4(0.0);\n\n out_FragColor = mix(insideFaceColor, outsideFaceColor, outsideFaceColor.a);\n out_FragColor.a = 1.0 - (1.0 - insideFaceColor.a) * (1.0 - outsideFaceColor.a);\n\n#if (defined(WRITE_DEPTH) && (__VERSION__ == 300 || defined(GL_EXT_frag_depth)))\n t = (intersection.start != 0.0) ? intersection.start : intersection.stop;\n vec3 positionEC = czm_pointAlongRay(ray, t);\n vec4 positionCC = czm_projection * vec4(positionEC, 1.0);\n#ifdef LOG_DEPTH\n czm_writeLogDepth(1.0 + positionCC.w);\n#else\n float z = positionCC.z / positionCC.w;\n\n float n = czm_depthRange.near;\n float f = czm_depthRange.far;\n\n gl_FragDepth = (z * (f - n) + f + n) * 0.5;\n#endif\n#endif\n}\n";
// packages/engine/Source/Shaders/EllipsoidVS.js
var import_InlineWorkers1035 = __toESM(require_InlineWorkers(), 1);
var EllipsoidVS_default = "in vec3 position;\n\nuniform vec3 u_radii;\n\nout vec3 v_positionEC;\n\nvoid main()\n{\n // In the vertex data, the cube goes from (-1.0, -1.0, -1.0) to (1.0, 1.0, 1.0) in model coordinates.\n // Scale to consider the radii. We could also do this once on the CPU when using the BoxGeometry,\n // but doing it here allows us to change the radii without rewriting the vertex data, and\n // allows all ellipsoids to reuse the same vertex data.\n vec4 p = vec4(u_radii * position, 1.0);\n \n vec4 pEC = czm_modelView * p;\n v_positionEC = pEC.xyz; // position in eye coordinates\n gl_Position = czm_projection * pEC;\n // With multi-frustum, when the ellipsoid primitive is positioned on the intersection of two frustums\n // and close to terrain, the terrain (writes depth) in the closest frustum can overwrite part of the\n // ellipsoid (does not write depth) that was rendered in the farther frustum.\n //\n // Here, we clamp the depth in the vertex shader to avoid being overwritten; however, this creates\n // artifacts since some fragments can be alpha blended twice. This is solved by only rendering\n // the ellipsoid in the closest frustum to the viewer.\n gl_Position.z = clamp(gl_Position.z, czm_depthRange.near, czm_depthRange.far);\n\n czm_vertexLogDepth();\n}\n";
// packages/engine/Source/Scene/EllipsoidPrimitive.js
var attributeLocations6 = {
position: 0
};
function EllipsoidPrimitive(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.center = Cartesian3_default.clone(options.center ?? Cartesian3_default.ZERO);
this._center = new Cartesian3_default();
this.radii = Cartesian3_default.clone(options.radii);
this._radii = new Cartesian3_default();
this._oneOverEllipsoidRadiiSquared = new Cartesian3_default();
this._boundingSphere = new BoundingSphere_default();
this.modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this._modelMatrix = new Matrix4_default();
this._computedModelMatrix = new Matrix4_default();
this.show = options.show ?? true;
this.material = options.material ?? Material_default.fromType(Material_default.ColorType);
this._material = void 0;
this._translucent = void 0;
this.id = options.id;
this._id = void 0;
this.debugShowBoundingVolume = options.debugShowBoundingVolume ?? false;
this.onlySunLighting = options.onlySunLighting ?? false;
this._onlySunLighting = false;
this._depthTestEnabled = options.depthTestEnabled ?? true;
this._useLogDepth = false;
this._sp = void 0;
this._rs = void 0;
this._va = void 0;
this._pickSP = void 0;
this._pickId = void 0;
this._colorCommand = new DrawCommand_default({
owner: options._owner ?? this
});
this._pickCommand = new DrawCommand_default({
owner: options._owner ?? this,
pickOnly: true
});
const that = this;
this._uniforms = {
u_radii: function() {
return that.radii;
},
u_oneOverEllipsoidRadiiSquared: function() {
return that._oneOverEllipsoidRadiiSquared;
}
};
this._pickUniforms = {
czm_pickColor: function() {
return that._pickId.color;
}
};
}
function getVertexArray(context) {
let vertexArray = context.cache.ellipsoidPrimitive_vertexArray;
if (defined_default(vertexArray)) {
return vertexArray;
}
const geometry = BoxGeometry_default.createGeometry(
BoxGeometry_default.fromDimensions({
dimensions: new Cartesian3_default(2, 2, 2),
vertexFormat: VertexFormat_default.POSITION_ONLY
})
);
vertexArray = VertexArray_default.fromGeometry({
context,
geometry,
attributeLocations: attributeLocations6,
bufferUsage: BufferUsage_default.STATIC_DRAW,
interleave: true
});
context.cache.ellipsoidPrimitive_vertexArray = vertexArray;
return vertexArray;
}
EllipsoidPrimitive.prototype.update = function(frameState) {
if (!this.show || frameState.mode !== SceneMode_default.SCENE3D || !defined_default(this.center) || !defined_default(this.radii)) {
return;
}
if (!defined_default(this.material)) {
throw new DeveloperError_default("this.material must be defined.");
}
const context = frameState.context;
const translucent = this.material.isTranslucent();
const translucencyChanged = this._translucent !== translucent;
if (!defined_default(this._rs) || translucencyChanged) {
this._translucent = translucent;
this._rs = RenderState_default.fromCache({
// Cull front faces - not back faces - so the ellipsoid doesn't
// disappear if the viewer enters the bounding box.
cull: {
enabled: true,
face: CullFace_default.FRONT
},
depthTest: {
enabled: this._depthTestEnabled
},
// Only write depth when EXT_frag_depth is supported since the depth for
// the bounding box is wrong; it is not the true depth of the ray casted ellipsoid.
depthMask: !translucent && context.fragmentDepth,
blending: translucent ? BlendingState_default.ALPHA_BLEND : void 0
});
}
if (!defined_default(this._va)) {
this._va = getVertexArray(context);
}
let boundingSphereDirty = false;
const radii = this.radii;
if (!Cartesian3_default.equals(this._radii, radii)) {
Cartesian3_default.clone(radii, this._radii);
const r = this._oneOverEllipsoidRadiiSquared;
r.x = 1 / (radii.x * radii.x);
r.y = 1 / (radii.y * radii.y);
r.z = 1 / (radii.z * radii.z);
boundingSphereDirty = true;
}
if (!Matrix4_default.equals(this.modelMatrix, this._modelMatrix) || !Cartesian3_default.equals(this.center, this._center)) {
Matrix4_default.clone(this.modelMatrix, this._modelMatrix);
Cartesian3_default.clone(this.center, this._center);
Matrix4_default.multiplyByTranslation(
this.modelMatrix,
this.center,
this._computedModelMatrix
);
boundingSphereDirty = true;
}
if (boundingSphereDirty) {
Cartesian3_default.clone(Cartesian3_default.ZERO, this._boundingSphere.center);
this._boundingSphere.radius = Cartesian3_default.maximumComponent(radii);
BoundingSphere_default.transform(
this._boundingSphere,
this._computedModelMatrix,
this._boundingSphere
);
}
const materialChanged = this._material !== this.material;
this._material = this.material;
this._material.update(context);
const lightingChanged = this.onlySunLighting !== this._onlySunLighting;
this._onlySunLighting = this.onlySunLighting;
const useLogDepth = frameState.useLogDepth;
const useLogDepthChanged = this._useLogDepth !== useLogDepth;
this._useLogDepth = useLogDepth;
const colorCommand = this._colorCommand;
let vs;
let fs;
if (materialChanged || lightingChanged || translucencyChanged || useLogDepthChanged) {
vs = new ShaderSource_default({
sources: [EllipsoidVS_default]
});
fs = new ShaderSource_default({
sources: [this.material.shaderSource, EllipsoidFS_default]
});
if (this.onlySunLighting) {
fs.defines.push("ONLY_SUN_LIGHTING");
}
if (!translucent && context.fragmentDepth) {
fs.defines.push("WRITE_DEPTH");
}
if (this._useLogDepth) {
vs.defines.push("LOG_DEPTH");
fs.defines.push("LOG_DEPTH");
}
this._sp = ShaderProgram_default.replaceCache({
context,
shaderProgram: this._sp,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations6
});
colorCommand.vertexArray = this._va;
colorCommand.renderState = this._rs;
colorCommand.shaderProgram = this._sp;
colorCommand.uniformMap = combine_default(this._uniforms, this.material._uniforms);
colorCommand.executeInClosestFrustum = translucent;
}
const commandList = frameState.commandList;
const passes = frameState.passes;
if (passes.render) {
colorCommand.boundingVolume = this._boundingSphere;
colorCommand.debugShowBoundingVolume = this.debugShowBoundingVolume;
colorCommand.modelMatrix = this._computedModelMatrix;
colorCommand.pass = translucent ? Pass_default.TRANSLUCENT : Pass_default.OPAQUE;
commandList.push(colorCommand);
}
if (passes.pick) {
const pickCommand = this._pickCommand;
if (!defined_default(this._pickId) || this._id !== this.id) {
this._id = this.id;
this._pickId = this._pickId && this._pickId.destroy();
this._pickId = context.createPickId({
primitive: this,
id: this.id
});
}
if (materialChanged || lightingChanged || !defined_default(this._pickSP) || useLogDepthChanged) {
vs = new ShaderSource_default({
sources: [EllipsoidVS_default]
});
fs = new ShaderSource_default({
sources: [this.material.shaderSource, EllipsoidFS_default],
pickColorQualifier: "uniform"
});
if (this.onlySunLighting) {
fs.defines.push("ONLY_SUN_LIGHTING");
}
if (!translucent && context.fragmentDepth) {
fs.defines.push("WRITE_DEPTH");
}
if (this._useLogDepth) {
vs.defines.push("LOG_DEPTH");
fs.defines.push("LOG_DEPTH");
}
this._pickSP = ShaderProgram_default.replaceCache({
context,
shaderProgram: this._pickSP,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations6
});
pickCommand.vertexArray = this._va;
pickCommand.renderState = this._rs;
pickCommand.shaderProgram = this._pickSP;
pickCommand.uniformMap = combine_default(
combine_default(this._uniforms, this._pickUniforms),
this.material._uniforms
);
pickCommand.executeInClosestFrustum = translucent;
}
pickCommand.boundingVolume = this._boundingSphere;
pickCommand.modelMatrix = this._computedModelMatrix;
pickCommand.pass = translucent ? Pass_default.TRANSLUCENT : Pass_default.OPAQUE;
commandList.push(pickCommand);
}
};
EllipsoidPrimitive.prototype.isDestroyed = function() {
return false;
};
EllipsoidPrimitive.prototype.destroy = function() {
this._sp = this._sp && this._sp.destroy();
this._pickSP = this._pickSP && this._pickSP.destroy();
this._pickId = this._pickId && this._pickId.destroy();
return destroyObject_default(this);
};
var EllipsoidPrimitive_default = EllipsoidPrimitive;
// packages/engine/Source/Scene/Moon.js
function Moon(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
let url2 = options.textureUrl;
if (!defined_default(url2)) {
url2 = buildModuleUrl_default("Assets/Textures/moonSmall.jpg");
}
this.show = options.show ?? true;
this.textureUrl = url2;
this._ellipsoid = options.ellipsoid ?? Ellipsoid_default.MOON;
this.onlySunLighting = options.onlySunLighting ?? true;
this._ellipsoidPrimitive = new EllipsoidPrimitive_default({
radii: this.ellipsoid.radii,
material: Material_default.fromType(Material_default.ImageType),
depthTestEnabled: false,
_owner: this
});
this._ellipsoidPrimitive.material.translucent = false;
this._axes = new IauOrientationAxes_default();
}
Object.defineProperties(Moon.prototype, {
/**
* Get the ellipsoid that defines the shape of the moon.
*
* @memberof Moon.prototype
*
* @type {Ellipsoid}
* @readonly
*
* @default {@link Ellipsoid.MOON}
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
}
});
var icrfToFixed = new Matrix3_default();
var rotationScratch4 = new Matrix3_default();
var translationScratch2 = new Cartesian3_default();
var scratchCommandList2 = [];
Moon.prototype.update = function(frameState) {
if (!this.show) {
return;
}
const ellipsoidPrimitive = this._ellipsoidPrimitive;
ellipsoidPrimitive.material.uniforms.image = this.textureUrl;
ellipsoidPrimitive.onlySunLighting = this.onlySunLighting;
const date = frameState.time;
if (!defined_default(Transforms_default.computeIcrfToFixedMatrix(date, icrfToFixed))) {
Transforms_default.computeTemeToPseudoFixedMatrix(date, icrfToFixed);
}
const rotation = this._axes.evaluate(date, rotationScratch4);
Matrix3_default.transpose(rotation, rotation);
Matrix3_default.multiply(icrfToFixed, rotation, rotation);
const translation3 = Simon1994PlanetaryPositions_default.computeMoonPositionInEarthInertialFrame(
date,
translationScratch2
);
Matrix3_default.multiplyByVector(icrfToFixed, translation3, translation3);
Matrix4_default.fromRotationTranslation(
rotation,
translation3,
ellipsoidPrimitive.modelMatrix
);
const savedCommandList = frameState.commandList;
frameState.commandList = scratchCommandList2;
scratchCommandList2.length = 0;
ellipsoidPrimitive.update(frameState);
frameState.commandList = savedCommandList;
return scratchCommandList2.length === 1 ? scratchCommandList2[0] : void 0;
};
Moon.prototype.isDestroyed = function() {
return false;
};
Moon.prototype.destroy = function() {
this._ellipsoidPrimitive = this._ellipsoidPrimitive && this._ellipsoidPrimitive.destroy();
return destroyObject_default(this);
};
var Moon_default = Moon;
// packages/engine/Source/Scene/Scene.js
var import_InlineWorkers1162 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/mergeSort.js
var import_InlineWorkers1038 = __toESM(require_InlineWorkers(), 1);
var leftScratchArray = [];
var rightScratchArray = [];
function merge(array, compare, userDefinedObject, start, middle, end) {
const leftLength = middle - start + 1;
const rightLength = end - middle;
const left = leftScratchArray;
const right = rightScratchArray;
let i;
let j;
for (i = 0; i < leftLength; ++i) {
left[i] = array[start + i];
}
for (j = 0; j < rightLength; ++j) {
right[j] = array[middle + j + 1];
}
i = 0;
j = 0;
for (let k = start; k <= end; ++k) {
const leftElement = left[i];
const rightElement = right[j];
if (i < leftLength && (j >= rightLength || compare(leftElement, rightElement, userDefinedObject) <= 0)) {
array[k] = leftElement;
++i;
} else if (j < rightLength) {
array[k] = rightElement;
++j;
}
}
}
function sort2(array, compare, userDefinedObject, start, end) {
if (start >= end) {
return;
}
const middle = Math.floor((start + end) * 0.5);
sort2(array, compare, userDefinedObject, start, middle);
sort2(array, compare, userDefinedObject, middle + 1, end);
merge(array, compare, userDefinedObject, start, middle, end);
}
function mergeSort(array, comparator, userDefinedObject) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required.");
}
if (!defined_default(comparator)) {
throw new DeveloperError_default("comparator is required.");
}
const length2 = array.length;
const scratchLength = Math.ceil(length2 * 0.5);
leftScratchArray.length = scratchLength;
rightScratchArray.length = scratchLength;
sort2(array, comparator, userDefinedObject, 0, length2 - 1);
leftScratchArray.length = 0;
rightScratchArray.length = 0;
}
var mergeSort_default = mergeSort;
// packages/engine/Source/Core/Occluder.js
var import_InlineWorkers1039 = __toESM(require_InlineWorkers(), 1);
function Occluder(occluderBoundingSphere, cameraPosition) {
if (!defined_default(occluderBoundingSphere)) {
throw new DeveloperError_default("occluderBoundingSphere is required.");
}
if (!defined_default(cameraPosition)) {
throw new DeveloperError_default("camera position is required.");
}
this._occluderPosition = Cartesian3_default.clone(occluderBoundingSphere.center);
this._occluderRadius = occluderBoundingSphere.radius;
this._horizonDistance = 0;
this._horizonPlaneNormal = void 0;
this._horizonPlanePosition = void 0;
this._cameraPosition = void 0;
this.cameraPosition = cameraPosition;
}
var scratchCartesian313 = new Cartesian3_default();
Object.defineProperties(Occluder.prototype, {
/**
* The position of the occluder.
* @memberof Occluder.prototype
* @type {Cartesian3}
*/
position: {
get: function() {
return this._occluderPosition;
}
},
/**
* The radius of the occluder.
* @memberof Occluder.prototype
* @type {number}
*/
radius: {
get: function() {
return this._occluderRadius;
}
},
/**
* The position of the camera.
* @memberof Occluder.prototype
* @type {Cartesian3}
*/
cameraPosition: {
set: function(cameraPosition) {
if (!defined_default(cameraPosition)) {
throw new DeveloperError_default("cameraPosition is required.");
}
cameraPosition = Cartesian3_default.clone(cameraPosition, this._cameraPosition);
const cameraToOccluderVec = Cartesian3_default.subtract(
this._occluderPosition,
cameraPosition,
scratchCartesian313
);
let invCameraToOccluderDistance = Cartesian3_default.magnitudeSquared(cameraToOccluderVec);
const occluderRadiusSqrd = this._occluderRadius * this._occluderRadius;
let horizonDistance;
let horizonPlaneNormal;
let horizonPlanePosition;
if (invCameraToOccluderDistance > occluderRadiusSqrd) {
horizonDistance = Math.sqrt(
invCameraToOccluderDistance - occluderRadiusSqrd
);
invCameraToOccluderDistance = 1 / Math.sqrt(invCameraToOccluderDistance);
horizonPlaneNormal = Cartesian3_default.multiplyByScalar(
cameraToOccluderVec,
invCameraToOccluderDistance,
scratchCartesian313
);
const nearPlaneDistance = horizonDistance * horizonDistance * invCameraToOccluderDistance;
horizonPlanePosition = Cartesian3_default.add(
cameraPosition,
Cartesian3_default.multiplyByScalar(
horizonPlaneNormal,
nearPlaneDistance,
scratchCartesian313
),
scratchCartesian313
);
} else {
horizonDistance = Number.MAX_VALUE;
}
this._horizonDistance = horizonDistance;
this._horizonPlaneNormal = horizonPlaneNormal;
this._horizonPlanePosition = horizonPlanePosition;
this._cameraPosition = cameraPosition;
}
}
});
Occluder.fromBoundingSphere = function(occluderBoundingSphere, cameraPosition, result) {
if (!defined_default(occluderBoundingSphere)) {
throw new DeveloperError_default("occluderBoundingSphere is required.");
}
if (!defined_default(cameraPosition)) {
throw new DeveloperError_default("camera position is required.");
}
if (!defined_default(result)) {
return new Occluder(occluderBoundingSphere, cameraPosition);
}
Cartesian3_default.clone(occluderBoundingSphere.center, result._occluderPosition);
result._occluderRadius = occluderBoundingSphere.radius;
result.cameraPosition = cameraPosition;
return result;
};
var tempVecScratch = new Cartesian3_default();
Occluder.prototype.isPointVisible = function(occludee) {
if (this._horizonDistance !== Number.MAX_VALUE) {
let tempVec2 = Cartesian3_default.subtract(
occludee,
this._occluderPosition,
tempVecScratch
);
let temp = this._occluderRadius;
temp = Cartesian3_default.magnitudeSquared(tempVec2) - temp * temp;
if (temp > 0) {
temp = Math.sqrt(temp) + this._horizonDistance;
tempVec2 = Cartesian3_default.subtract(occludee, this._cameraPosition, tempVec2);
return temp * temp > Cartesian3_default.magnitudeSquared(tempVec2);
}
}
return false;
};
var occludeePositionScratch = new Cartesian3_default();
Occluder.prototype.isBoundingSphereVisible = function(occludee) {
const occludeePosition = Cartesian3_default.clone(
occludee.center,
occludeePositionScratch
);
const occludeeRadius = occludee.radius;
if (this._horizonDistance !== Number.MAX_VALUE) {
let tempVec2 = Cartesian3_default.subtract(
occludeePosition,
this._occluderPosition,
tempVecScratch
);
let temp = this._occluderRadius - occludeeRadius;
temp = Cartesian3_default.magnitudeSquared(tempVec2) - temp * temp;
if (occludeeRadius < this._occluderRadius) {
if (temp > 0) {
temp = Math.sqrt(temp) + this._horizonDistance;
tempVec2 = Cartesian3_default.subtract(
occludeePosition,
this._cameraPosition,
tempVec2
);
return temp * temp + occludeeRadius * occludeeRadius > Cartesian3_default.magnitudeSquared(tempVec2);
}
return false;
}
if (temp > 0) {
tempVec2 = Cartesian3_default.subtract(
occludeePosition,
this._cameraPosition,
tempVec2
);
const tempVecMagnitudeSquared = Cartesian3_default.magnitudeSquared(tempVec2);
const occluderRadiusSquared = this._occluderRadius * this._occluderRadius;
const occludeeRadiusSquared = occludeeRadius * occludeeRadius;
if ((this._horizonDistance * this._horizonDistance + occluderRadiusSquared) * occludeeRadiusSquared > tempVecMagnitudeSquared * occluderRadiusSquared) {
return true;
}
temp = Math.sqrt(temp) + this._horizonDistance;
return temp * temp + occludeeRadiusSquared > tempVecMagnitudeSquared;
}
return true;
}
return false;
};
var tempScratch2 = new Cartesian3_default();
Occluder.prototype.computeVisibility = function(occludeeBS) {
if (!defined_default(occludeeBS)) {
throw new DeveloperError_default("occludeeBS is required.");
}
const occludeePosition = Cartesian3_default.clone(occludeeBS.center);
const occludeeRadius = occludeeBS.radius;
if (occludeeRadius > this._occluderRadius) {
return Visibility_default.FULL;
}
if (this._horizonDistance !== Number.MAX_VALUE) {
let tempVec2 = Cartesian3_default.subtract(
occludeePosition,
this._occluderPosition,
tempScratch2
);
let temp = this._occluderRadius - occludeeRadius;
const occluderToOccludeeDistSqrd = Cartesian3_default.magnitudeSquared(tempVec2);
temp = occluderToOccludeeDistSqrd - temp * temp;
if (temp > 0) {
temp = Math.sqrt(temp) + this._horizonDistance;
tempVec2 = Cartesian3_default.subtract(
occludeePosition,
this._cameraPosition,
tempVec2
);
const cameraToOccludeeDistSqrd = Cartesian3_default.magnitudeSquared(tempVec2);
if (temp * temp + occludeeRadius * occludeeRadius < cameraToOccludeeDistSqrd) {
return Visibility_default.NONE;
}
temp = this._occluderRadius + occludeeRadius;
temp = occluderToOccludeeDistSqrd - temp * temp;
if (temp > 0) {
temp = Math.sqrt(temp) + this._horizonDistance;
return cameraToOccludeeDistSqrd < temp * temp + occludeeRadius * occludeeRadius ? Visibility_default.FULL : Visibility_default.PARTIAL;
}
tempVec2 = Cartesian3_default.subtract(
occludeePosition,
this._horizonPlanePosition,
tempVec2
);
return Cartesian3_default.dot(tempVec2, this._horizonPlaneNormal) > -occludeeRadius ? Visibility_default.PARTIAL : Visibility_default.FULL;
}
}
return Visibility_default.NONE;
};
var occludeePointScratch = new Cartesian3_default();
Occluder.computeOccludeePoint = function(occluderBoundingSphere, occludeePosition, positions) {
if (!defined_default(occluderBoundingSphere)) {
throw new DeveloperError_default("occluderBoundingSphere is required.");
}
if (!defined_default(positions)) {
throw new DeveloperError_default("positions is required.");
}
if (positions.length === 0) {
throw new DeveloperError_default("positions must contain at least one element");
}
const occludeePos = Cartesian3_default.clone(occludeePosition);
const occluderPosition = Cartesian3_default.clone(occluderBoundingSphere.center);
const occluderRadius = occluderBoundingSphere.radius;
const numPositions = positions.length;
if (Cartesian3_default.equals(occluderPosition, occludeePosition)) {
throw new DeveloperError_default(
"occludeePosition must be different than occluderBoundingSphere.center"
);
}
const occluderPlaneNormal = Cartesian3_default.normalize(
Cartesian3_default.subtract(occludeePos, occluderPosition, occludeePointScratch),
occludeePointScratch
);
const occluderPlaneD = -Cartesian3_default.dot(occluderPlaneNormal, occluderPosition);
const aRotationVector = Occluder._anyRotationVector(
occluderPosition,
occluderPlaneNormal,
occluderPlaneD
);
let dot2 = Occluder._horizonToPlaneNormalDotProduct(
occluderBoundingSphere,
occluderPlaneNormal,
occluderPlaneD,
aRotationVector,
positions[0]
);
if (!dot2) {
return void 0;
}
let tempDot;
for (let i = 1; i < numPositions; ++i) {
tempDot = Occluder._horizonToPlaneNormalDotProduct(
occluderBoundingSphere,
occluderPlaneNormal,
occluderPlaneD,
aRotationVector,
positions[i]
);
if (!tempDot) {
return void 0;
}
if (tempDot < dot2) {
dot2 = tempDot;
}
}
if (dot2 < 0.0017453283658983088) {
return void 0;
}
const distance2 = occluderRadius / dot2;
return Cartesian3_default.add(
occluderPosition,
Cartesian3_default.multiplyByScalar(
occluderPlaneNormal,
distance2,
occludeePointScratch
),
occludeePointScratch
);
};
var computeOccludeePointFromRectangleScratch = [];
Occluder.computeOccludeePointFromRectangle = function(rectangle, ellipsoid) {
if (!defined_default(rectangle)) {
throw new DeveloperError_default("rectangle is required.");
}
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
const positions = Rectangle_default.subsample(
rectangle,
ellipsoid,
0,
computeOccludeePointFromRectangleScratch
);
const bs = BoundingSphere_default.fromPoints(positions);
const ellipsoidCenter = Cartesian3_default.ZERO;
if (!Cartesian3_default.equals(ellipsoidCenter, bs.center)) {
return Occluder.computeOccludeePoint(
new BoundingSphere_default(ellipsoidCenter, ellipsoid.minimumRadius),
bs.center,
positions
);
}
return void 0;
};
var tempVec0Scratch = new Cartesian3_default();
Occluder._anyRotationVector = function(occluderPosition, occluderPlaneNormal, occluderPlaneD) {
const tempVec0 = Cartesian3_default.abs(occluderPlaneNormal, tempVec0Scratch);
let majorAxis = tempVec0.x > tempVec0.y ? 0 : 1;
if (majorAxis === 0 && tempVec0.z > tempVec0.x || majorAxis === 1 && tempVec0.z > tempVec0.y) {
majorAxis = 2;
}
const tempVec2 = new Cartesian3_default();
let tempVec1;
if (majorAxis === 0) {
tempVec0.x = occluderPosition.x;
tempVec0.y = occluderPosition.y + 1;
tempVec0.z = occluderPosition.z + 1;
tempVec1 = Cartesian3_default.UNIT_X;
} else if (majorAxis === 1) {
tempVec0.x = occluderPosition.x + 1;
tempVec0.y = occluderPosition.y;
tempVec0.z = occluderPosition.z + 1;
tempVec1 = Cartesian3_default.UNIT_Y;
} else {
tempVec0.x = occluderPosition.x + 1;
tempVec0.y = occluderPosition.y + 1;
tempVec0.z = occluderPosition.z;
tempVec1 = Cartesian3_default.UNIT_Z;
}
const u3 = (Cartesian3_default.dot(occluderPlaneNormal, tempVec0) + occluderPlaneD) / -Cartesian3_default.dot(occluderPlaneNormal, tempVec1);
return Cartesian3_default.normalize(
Cartesian3_default.subtract(
Cartesian3_default.add(
tempVec0,
Cartesian3_default.multiplyByScalar(tempVec1, u3, tempVec2),
tempVec0
),
occluderPosition,
tempVec0
),
tempVec0
);
};
var posDirectionScratch = new Cartesian3_default();
Occluder._rotationVector = function(occluderPosition, occluderPlaneNormal, occluderPlaneD, position, anyRotationVector) {
let positionDirection = Cartesian3_default.subtract(
position,
occluderPosition,
posDirectionScratch
);
positionDirection = Cartesian3_default.normalize(
positionDirection,
positionDirection
);
if (Cartesian3_default.dot(occluderPlaneNormal, positionDirection) < // eslint-disable-next-line no-loss-of-precision
0.9999999847691291) {
const crossProduct = Cartesian3_default.cross(
occluderPlaneNormal,
positionDirection,
positionDirection
);
const length2 = Cartesian3_default.magnitude(crossProduct);
if (length2 > Math_default.EPSILON13) {
return Cartesian3_default.normalize(crossProduct, new Cartesian3_default());
}
}
return anyRotationVector;
};
var posScratch1 = new Cartesian3_default();
var occluerPosScratch = new Cartesian3_default();
var posScratch2 = new Cartesian3_default();
var horizonPlanePosScratch = new Cartesian3_default();
Occluder._horizonToPlaneNormalDotProduct = function(occluderBS, occluderPlaneNormal, occluderPlaneD, anyRotationVector, position) {
const pos = Cartesian3_default.clone(position, posScratch1);
const occluderPosition = Cartesian3_default.clone(
occluderBS.center,
occluerPosScratch
);
const occluderRadius = occluderBS.radius;
let positionToOccluder = Cartesian3_default.subtract(
occluderPosition,
pos,
posScratch2
);
const occluderToPositionDistanceSquared = Cartesian3_default.magnitudeSquared(positionToOccluder);
const occluderRadiusSquared = occluderRadius * occluderRadius;
if (occluderToPositionDistanceSquared < occluderRadiusSquared) {
return false;
}
const horizonDistanceSquared = occluderToPositionDistanceSquared - occluderRadiusSquared;
const horizonDistance = Math.sqrt(horizonDistanceSquared);
const occluderToPositionDistance = Math.sqrt(
occluderToPositionDistanceSquared
);
const invOccluderToPositionDistance = 1 / occluderToPositionDistance;
const cosTheta = horizonDistance * invOccluderToPositionDistance;
const horizonPlaneDistance = cosTheta * horizonDistance;
positionToOccluder = Cartesian3_default.normalize(
positionToOccluder,
positionToOccluder
);
const horizonPlanePosition = Cartesian3_default.add(
pos,
Cartesian3_default.multiplyByScalar(
positionToOccluder,
horizonPlaneDistance,
horizonPlanePosScratch
),
horizonPlanePosScratch
);
const horizonCrossDistance = Math.sqrt(
horizonDistanceSquared - horizonPlaneDistance * horizonPlaneDistance
);
let tempVec2 = this._rotationVector(
occluderPosition,
occluderPlaneNormal,
occluderPlaneD,
pos,
anyRotationVector
);
let horizonCrossDirection = Cartesian3_default.fromElements(
tempVec2.x * tempVec2.x * positionToOccluder.x + (tempVec2.x * tempVec2.y - tempVec2.z) * positionToOccluder.y + (tempVec2.x * tempVec2.z + tempVec2.y) * positionToOccluder.z,
(tempVec2.x * tempVec2.y + tempVec2.z) * positionToOccluder.x + tempVec2.y * tempVec2.y * positionToOccluder.y + (tempVec2.y * tempVec2.z - tempVec2.x) * positionToOccluder.z,
(tempVec2.x * tempVec2.z - tempVec2.y) * positionToOccluder.x + (tempVec2.y * tempVec2.z + tempVec2.x) * positionToOccluder.y + tempVec2.z * tempVec2.z * positionToOccluder.z,
posScratch1
);
horizonCrossDirection = Cartesian3_default.normalize(
horizonCrossDirection,
horizonCrossDirection
);
const offset = Cartesian3_default.multiplyByScalar(
horizonCrossDirection,
horizonCrossDistance,
posScratch1
);
tempVec2 = Cartesian3_default.normalize(
Cartesian3_default.subtract(
Cartesian3_default.add(horizonPlanePosition, offset, posScratch2),
occluderPosition,
posScratch2
),
posScratch2
);
const dot0 = Cartesian3_default.dot(occluderPlaneNormal, tempVec2);
tempVec2 = Cartesian3_default.normalize(
Cartesian3_default.subtract(
Cartesian3_default.subtract(horizonPlanePosition, offset, tempVec2),
occluderPosition,
tempVec2
),
tempVec2
);
const dot1 = Cartesian3_default.dot(occluderPlaneNormal, tempVec2);
return dot0 < dot1 ? dot0 : dot1;
};
var Occluder_default = Occluder;
// packages/engine/Source/Core/PerspectiveFrustum.js
var import_InlineWorkers1041 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PerspectiveOffCenterFrustum.js
var import_InlineWorkers1040 = __toESM(require_InlineWorkers(), 1);
function PerspectiveOffCenterFrustum(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.left = options.left;
this._left = void 0;
this.right = options.right;
this._right = void 0;
this.top = options.top;
this._top = void 0;
this.bottom = options.bottom;
this._bottom = void 0;
this.near = options.near ?? 1;
this._near = this.near;
this.far = options.far ?? 5e8;
this._far = this.far;
this._cullingVolume = new CullingVolume_default();
this._perspectiveMatrix = new Matrix4_default();
this._infinitePerspective = new Matrix4_default();
}
function update5(frustum) {
if (!defined_default(frustum.right) || !defined_default(frustum.left) || !defined_default(frustum.top) || !defined_default(frustum.bottom) || !defined_default(frustum.near) || !defined_default(frustum.far)) {
throw new DeveloperError_default(
"right, left, top, bottom, near, or far parameters are not set."
);
}
const { top, bottom, right, left, near, far } = frustum;
const changed = top !== frustum._top || bottom !== frustum._bottom || left !== frustum._left || right !== frustum._right || near !== frustum._near || far !== frustum._far;
if (!changed) {
return;
}
if (frustum.near <= 0 || frustum.near > frustum.far) {
throw new DeveloperError_default(
"near must be greater than zero and less than far."
);
}
frustum._left = left;
frustum._right = right;
frustum._top = top;
frustum._bottom = bottom;
frustum._near = near;
frustum._far = far;
frustum._perspectiveMatrix = Matrix4_default.computePerspectiveOffCenter(
left,
right,
bottom,
top,
near,
far,
frustum._perspectiveMatrix
);
frustum._infinitePerspective = Matrix4_default.computeInfinitePerspectiveOffCenter(
left,
right,
bottom,
top,
near,
frustum._infinitePerspective
);
}
Object.defineProperties(PerspectiveOffCenterFrustum.prototype, {
/**
* Gets the perspective projection matrix computed from the view frustum.
* The projection matrix will be recomputed if any frustum parameters have changed.
*
* @memberof PerspectiveOffCenterFrustum.prototype
* @type {Matrix4}
* @readonly
*
* @see PerspectiveOffCenterFrustum#infiniteProjectionMatrix
*/
projectionMatrix: {
get: function() {
update5(this);
return this._perspectiveMatrix;
}
},
/**
* Gets the perspective projection matrix computed from the view frustum with an infinite far plane.
* @memberof PerspectiveOffCenterFrustum.prototype
* @type {Matrix4}
* @readonly
*
* @see PerspectiveOffCenterFrustum#projectionMatrix
*/
infiniteProjectionMatrix: {
get: function() {
update5(this);
return this._infinitePerspective;
}
}
});
var getPlanesRight2 = new Cartesian3_default();
var getPlanesNearCenter2 = new Cartesian3_default();
var getPlanesFarCenter = new Cartesian3_default();
var getPlanesNormal = new Cartesian3_default();
PerspectiveOffCenterFrustum.prototype.computeCullingVolume = function(position, direction2, up) {
if (!defined_default(position)) {
throw new DeveloperError_default("position is required.");
}
if (!defined_default(direction2)) {
throw new DeveloperError_default("direction is required.");
}
if (!defined_default(up)) {
throw new DeveloperError_default("up is required.");
}
const planes = this._cullingVolume.planes;
const t = this.top;
const b = this.bottom;
const r = this.right;
const l = this.left;
const n = this.near;
const f = this.far;
const right = Cartesian3_default.cross(direction2, up, getPlanesRight2);
const nearCenter = getPlanesNearCenter2;
Cartesian3_default.multiplyByScalar(direction2, n, nearCenter);
Cartesian3_default.add(position, nearCenter, nearCenter);
const farCenter = getPlanesFarCenter;
Cartesian3_default.multiplyByScalar(direction2, f, farCenter);
Cartesian3_default.add(position, farCenter, farCenter);
const normal2 = getPlanesNormal;
Cartesian3_default.multiplyByScalar(right, l, normal2);
Cartesian3_default.add(nearCenter, normal2, normal2);
Cartesian3_default.subtract(normal2, position, normal2);
Cartesian3_default.normalize(normal2, normal2);
Cartesian3_default.cross(normal2, up, normal2);
Cartesian3_default.normalize(normal2, normal2);
let plane = planes[0];
if (!defined_default(plane)) {
plane = planes[0] = new Cartesian4_default();
}
plane.x = normal2.x;
plane.y = normal2.y;
plane.z = normal2.z;
plane.w = -Cartesian3_default.dot(normal2, position);
Cartesian3_default.multiplyByScalar(right, r, normal2);
Cartesian3_default.add(nearCenter, normal2, normal2);
Cartesian3_default.subtract(normal2, position, normal2);
Cartesian3_default.cross(up, normal2, normal2);
Cartesian3_default.normalize(normal2, normal2);
plane = planes[1];
if (!defined_default(plane)) {
plane = planes[1] = new Cartesian4_default();
}
plane.x = normal2.x;
plane.y = normal2.y;
plane.z = normal2.z;
plane.w = -Cartesian3_default.dot(normal2, position);
Cartesian3_default.multiplyByScalar(up, b, normal2);
Cartesian3_default.add(nearCenter, normal2, normal2);
Cartesian3_default.subtract(normal2, position, normal2);
Cartesian3_default.cross(right, normal2, normal2);
Cartesian3_default.normalize(normal2, normal2);
plane = planes[2];
if (!defined_default(plane)) {
plane = planes[2] = new Cartesian4_default();
}
plane.x = normal2.x;
plane.y = normal2.y;
plane.z = normal2.z;
plane.w = -Cartesian3_default.dot(normal2, position);
Cartesian3_default.multiplyByScalar(up, t, normal2);
Cartesian3_default.add(nearCenter, normal2, normal2);
Cartesian3_default.subtract(normal2, position, normal2);
Cartesian3_default.cross(normal2, right, normal2);
Cartesian3_default.normalize(normal2, normal2);
plane = planes[3];
if (!defined_default(plane)) {
plane = planes[3] = new Cartesian4_default();
}
plane.x = normal2.x;
plane.y = normal2.y;
plane.z = normal2.z;
plane.w = -Cartesian3_default.dot(normal2, position);
plane = planes[4];
if (!defined_default(plane)) {
plane = planes[4] = new Cartesian4_default();
}
plane.x = direction2.x;
plane.y = direction2.y;
plane.z = direction2.z;
plane.w = -Cartesian3_default.dot(direction2, nearCenter);
Cartesian3_default.negate(direction2, normal2);
plane = planes[5];
if (!defined_default(plane)) {
plane = planes[5] = new Cartesian4_default();
}
plane.x = normal2.x;
plane.y = normal2.y;
plane.z = normal2.z;
plane.w = -Cartesian3_default.dot(normal2, farCenter);
return this._cullingVolume;
};
PerspectiveOffCenterFrustum.prototype.getPixelDimensions = function(drawingBufferWidth, drawingBufferHeight, distance2, pixelRatio, result) {
update5(this);
if (!defined_default(drawingBufferWidth) || !defined_default(drawingBufferHeight)) {
throw new DeveloperError_default(
"Both drawingBufferWidth and drawingBufferHeight are required."
);
}
if (drawingBufferWidth <= 0) {
throw new DeveloperError_default("drawingBufferWidth must be greater than zero.");
}
if (drawingBufferHeight <= 0) {
throw new DeveloperError_default("drawingBufferHeight must be greater than zero.");
}
if (!defined_default(distance2)) {
throw new DeveloperError_default("distance is required.");
}
if (!defined_default(pixelRatio)) {
throw new DeveloperError_default("pixelRatio is required");
}
if (pixelRatio <= 0) {
throw new DeveloperError_default("pixelRatio must be greater than zero.");
}
if (!defined_default(result)) {
throw new DeveloperError_default("A result object is required.");
}
const inverseNear = 1 / this.near;
let tanTheta = this.top * inverseNear;
const pixelHeight = 2 * pixelRatio * distance2 * tanTheta / drawingBufferHeight;
tanTheta = this.right * inverseNear;
const pixelWidth = 2 * pixelRatio * distance2 * tanTheta / drawingBufferWidth;
result.x = pixelWidth;
result.y = pixelHeight;
return result;
};
PerspectiveOffCenterFrustum.prototype.clone = function(result) {
if (!defined_default(result)) {
result = new PerspectiveOffCenterFrustum();
}
result.right = this.right;
result.left = this.left;
result.top = this.top;
result.bottom = this.bottom;
result.near = this.near;
result.far = this.far;
result._left = void 0;
result._right = void 0;
result._top = void 0;
result._bottom = void 0;
result._near = void 0;
result._far = void 0;
return result;
};
PerspectiveOffCenterFrustum.prototype.equals = function(other) {
return defined_default(other) && other instanceof PerspectiveOffCenterFrustum && this.right === other.right && this.left === other.left && this.top === other.top && this.bottom === other.bottom && this.near === other.near && this.far === other.far;
};
PerspectiveOffCenterFrustum.prototype.equalsEpsilon = function(other, relativeEpsilon, absoluteEpsilon) {
return other === this || defined_default(other) && other instanceof PerspectiveOffCenterFrustum && Math_default.equalsEpsilon(
this.right,
other.right,
relativeEpsilon,
absoluteEpsilon
) && Math_default.equalsEpsilon(
this.left,
other.left,
relativeEpsilon,
absoluteEpsilon
) && Math_default.equalsEpsilon(
this.top,
other.top,
relativeEpsilon,
absoluteEpsilon
) && Math_default.equalsEpsilon(
this.bottom,
other.bottom,
relativeEpsilon,
absoluteEpsilon
) && Math_default.equalsEpsilon(
this.near,
other.near,
relativeEpsilon,
absoluteEpsilon
) && Math_default.equalsEpsilon(
this.far,
other.far,
relativeEpsilon,
absoluteEpsilon
);
};
var PerspectiveOffCenterFrustum_default = PerspectiveOffCenterFrustum;
// packages/engine/Source/Core/PerspectiveFrustum.js
function PerspectiveFrustum(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._offCenterFrustum = new PerspectiveOffCenterFrustum_default();
this.fov = options.fov;
this._fov = void 0;
this._fovy = void 0;
this._sseDenominator = void 0;
this.aspectRatio = options.aspectRatio;
this._aspectRatio = void 0;
this.near = options.near ?? 1;
this._near = this.near;
this.far = options.far ?? 5e8;
this._far = this.far;
this.xOffset = options.xOffset ?? 0;
this._xOffset = this.xOffset;
this.yOffset = options.yOffset ?? 0;
this._yOffset = this.yOffset;
}
PerspectiveFrustum.packedLength = 6;
PerspectiveFrustum.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
array[startingIndex++] = value.fov;
array[startingIndex++] = value.aspectRatio;
array[startingIndex++] = value.near;
array[startingIndex++] = value.far;
array[startingIndex++] = value.xOffset;
array[startingIndex] = value.yOffset;
return array;
};
PerspectiveFrustum.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
if (!defined_default(result)) {
result = new PerspectiveFrustum();
}
result.fov = array[startingIndex++];
result.aspectRatio = array[startingIndex++];
result.near = array[startingIndex++];
result.far = array[startingIndex++];
result.xOffset = array[startingIndex++];
result.yOffset = array[startingIndex];
return result;
};
function update6(frustum) {
if (!defined_default(frustum.fov) || !defined_default(frustum.aspectRatio) || !defined_default(frustum.near) || !defined_default(frustum.far)) {
throw new DeveloperError_default(
"fov, aspectRatio, near, or far parameters are not set."
);
}
const changed = frustum.fov !== frustum._fov || frustum.aspectRatio !== frustum._aspectRatio || frustum.near !== frustum._near || frustum.far !== frustum._far || frustum.xOffset !== frustum._xOffset || frustum.yOffset !== frustum._yOffset;
if (!changed) {
return;
}
Check_default.typeOf.number.greaterThanOrEquals("fov", frustum.fov, 0);
Check_default.typeOf.number.lessThan("fov", frustum.fov, Math.PI);
Check_default.typeOf.number.greaterThanOrEquals(
"aspectRatio",
frustum.aspectRatio,
0
);
Check_default.typeOf.number.greaterThanOrEquals("near", frustum.near, 0);
if (frustum.near > frustum.far) {
throw new DeveloperError_default("near must be less than far.");
}
frustum._aspectRatio = frustum.aspectRatio;
frustum._fov = frustum.fov;
frustum._fovy = frustum.aspectRatio <= 1 ? frustum.fov : Math.atan(Math.tan(frustum.fov * 0.5) / frustum.aspectRatio) * 2;
frustum._near = frustum.near;
frustum._far = frustum.far;
frustum._sseDenominator = 2 * Math.tan(0.5 * frustum._fovy);
frustum._xOffset = frustum.xOffset;
frustum._yOffset = frustum.yOffset;
const f = frustum._offCenterFrustum;
f.top = frustum.near * Math.tan(0.5 * frustum._fovy);
f.bottom = -f.top;
f.right = frustum.aspectRatio * f.top;
f.left = -f.right;
f.near = frustum.near;
f.far = frustum.far;
f.right += frustum.xOffset;
f.left += frustum.xOffset;
f.top += frustum.yOffset;
f.bottom += frustum.yOffset;
}
Object.defineProperties(PerspectiveFrustum.prototype, {
/**
* Gets the perspective projection matrix computed from the view frustum.
* If necessary, the projection matrix will be recomputed.
*
* @memberof PerspectiveFrustum.prototype
* @type {Matrix4}
* @readonly
*
* @see PerspectiveOffCenterFrustum#projectionMatrix.
* @see PerspectiveFrustum#infiniteProjectionMatrix
*/
projectionMatrix: {
get: function() {
update6(this);
return this._offCenterFrustum.projectionMatrix;
}
},
/**
* The perspective projection matrix computed from the view frustum with an infinite far plane.
* @memberof PerspectiveFrustum.prototype
* @type {Matrix4}
* @readonly
*
* @see PerspectiveFrustum#projectionMatrix
*/
infiniteProjectionMatrix: {
get: function() {
update6(this);
return this._offCenterFrustum.infiniteProjectionMatrix;
}
},
/**
* Gets the angle of the vertical field of view, in radians.
* @memberof PerspectiveFrustum.prototype
* @type {number|undefined}
* @readonly
* @default undefined
*/
fovy: {
get: function() {
update6(this);
return this._fovy;
}
},
/**
* @readonly
* @private
*/
sseDenominator: {
get: function() {
update6(this);
return this._sseDenominator;
}
},
/**
* Gets the orthographic projection matrix computed from the view frustum.
* @memberof PerspectiveFrustum.prototype
* @type {PerspectiveOffCenterFrustum}
* @readonly
* @private
*/
offCenterFrustum: {
get: function() {
update6(this);
return this._offCenterFrustum;
}
}
});
PerspectiveFrustum.prototype.computeCullingVolume = function(position, direction2, up) {
update6(this);
return this._offCenterFrustum.computeCullingVolume(position, direction2, up);
};
PerspectiveFrustum.prototype.getPixelDimensions = function(drawingBufferWidth, drawingBufferHeight, distance2, pixelRatio, result) {
update6(this);
return this._offCenterFrustum.getPixelDimensions(
drawingBufferWidth,
drawingBufferHeight,
distance2,
pixelRatio,
result
);
};
PerspectiveFrustum.prototype.clone = function(result) {
if (!defined_default(result)) {
result = new PerspectiveFrustum();
}
result.aspectRatio = this.aspectRatio;
result.fov = this.fov;
result.near = this.near;
result.far = this.far;
result._aspectRatio = void 0;
result._fov = void 0;
result._near = void 0;
result._far = void 0;
this._offCenterFrustum.clone(result._offCenterFrustum);
return result;
};
PerspectiveFrustum.prototype.equals = function(other) {
if (!defined_default(other) || !(other instanceof PerspectiveFrustum)) {
return false;
}
update6(this);
update6(other);
return this.fov === other.fov && this.aspectRatio === other.aspectRatio && this._offCenterFrustum.equals(other._offCenterFrustum);
};
PerspectiveFrustum.prototype.equalsEpsilon = function(other, relativeEpsilon, absoluteEpsilon) {
if (!defined_default(other) || !(other instanceof PerspectiveFrustum)) {
return false;
}
update6(this);
update6(other);
return Math_default.equalsEpsilon(
this.fov,
other.fov,
relativeEpsilon,
absoluteEpsilon
) && Math_default.equalsEpsilon(
this.aspectRatio,
other.aspectRatio,
relativeEpsilon,
absoluteEpsilon
) && this._offCenterFrustum.equalsEpsilon(
other._offCenterFrustum,
relativeEpsilon,
absoluteEpsilon
);
};
var PerspectiveFrustum_default = PerspectiveFrustum;
// packages/engine/Source/Scene/BrdfLutGenerator.js
var import_InlineWorkers1043 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/BrdfLutGeneratorFS.js
var import_InlineWorkers1042 = __toESM(require_InlineWorkers(), 1);
var BrdfLutGeneratorFS_default = "in vec2 v_textureCoordinates;\nconst float M_PI = 3.141592653589793;\n\nfloat vdcRadicalInverse(int i)\n{\n float r;\n float base = 2.0;\n float value = 0.0;\n float invBase = 1.0 / base;\n float invBi = invBase;\n for (int x = 0; x < 100; x++)\n {\n if (i <= 0)\n {\n break;\n }\n r = mod(float(i), base);\n value += r * invBi;\n invBi *= invBase;\n i = int(float(i) * invBase);\n }\n return value;\n}\n\nvec2 hammersley2D(int i, int N)\n{\n return vec2(float(i) / float(N), vdcRadicalInverse(i));\n}\n\nvec3 importanceSampleGGX(vec2 xi, float alphaRoughness, vec3 N)\n{\n float alphaRoughnessSquared = alphaRoughness * alphaRoughness;\n float phi = 2.0 * M_PI * xi.x;\n float cosTheta = sqrt((1.0 - xi.y) / (1.0 + (alphaRoughnessSquared - 1.0) * xi.y));\n float sinTheta = sqrt(1.0 - cosTheta * cosTheta);\n vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);\n vec3 upVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\n vec3 tangentX = normalize(cross(upVector, N));\n vec3 tangentY = cross(N, tangentX);\n return tangentX * H.x + tangentY * H.y + N * H.z;\n}\n\n/**\n * Estimate the geometric self-shadowing of the microfacets in a surface,\n * using the Smith Joint GGX visibility function.\n * Note: Vis = G / (4 * NdotL * NdotV)\n * see Eric Heitz. 2014. Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs. Journal of Computer Graphics Techniques, 3\n * see Real-Time Rendering. Page 331 to 336.\n * see https://google.github.io/filament/Filament.md.html#materialsystem/specularbrdf/geometricshadowing(specularg)\n *\n * @param {float} alphaRoughness The roughness of the material, expressed as the square of perceptual roughness.\n * @param {float} NdotL The cosine of the angle between the surface normal and the direction to the light source.\n * @param {float} NdotV The cosine of the angle between the surface normal and the direction to the camera.\n */\nfloat smithVisibilityGGX(float alphaRoughness, float NdotL, float NdotV)\n{\n float alphaRoughnessSq = alphaRoughness * alphaRoughness;\n\n float GGXV = NdotL * sqrt(NdotV * NdotV * (1.0 - alphaRoughnessSq) + alphaRoughnessSq);\n float GGXL = NdotV * sqrt(NdotL * NdotL * (1.0 - alphaRoughnessSq) + alphaRoughnessSq);\n\n float GGX = GGXV + GGXL; // 2.0 if NdotL = NdotV = 1.0\n if (GGX > 0.0)\n {\n return 0.5 / GGX; // 1/4 if NdotL = NdotV = 1.0\n }\n return 0.0;\n}\n\nvec2 integrateBrdf(float roughness, float NdotV)\n{\n vec3 V = vec3(sqrt(1.0 - NdotV * NdotV), 0.0, NdotV);\n float A = 0.0;\n float B = 0.0;\n const int NumSamples = 1024;\n float alphaRoughness = roughness * roughness;\n for (int i = 0; i < NumSamples; i++)\n {\n vec2 xi = hammersley2D(i, NumSamples);\n vec3 H = importanceSampleGGX(xi, alphaRoughness, vec3(0.0, 0.0, 1.0));\n vec3 L = 2.0 * dot(V, H) * H - V;\n float NdotL = clamp(L.z, 0.0, 1.0);\n float NdotH = clamp(H.z, 0.0, 1.0);\n float VdotH = clamp(dot(V, H), 0.0, 1.0);\n if (NdotL > 0.0)\n {\n float G = smithVisibilityGGX(alphaRoughness, NdotL, NdotV);\n float G_Vis = 4.0 * G * VdotH * NdotL / NdotH;\n float Fc = pow(1.0 - VdotH, 5.0);\n A += (1.0 - Fc) * G_Vis;\n B += Fc * G_Vis;\n }\n }\n return vec2(A, B) / float(NumSamples);\n}\n\nvoid main()\n{\n out_FragColor = vec4(integrateBrdf(v_textureCoordinates.y, v_textureCoordinates.x), 0.0, 1.0);\n}\n";
// packages/engine/Source/Scene/BrdfLutGenerator.js
function BrdfLutGenerator() {
this._colorTexture = void 0;
this._drawCommand = void 0;
}
Object.defineProperties(BrdfLutGenerator.prototype, {
colorTexture: {
get: function() {
return this._colorTexture;
}
}
});
function createCommand(generator, context, framebuffer) {
const drawCommand = context.createViewportQuadCommand(BrdfLutGeneratorFS_default, {
framebuffer,
renderState: RenderState_default.fromCache({
viewport: new BoundingRectangle_default(0, 0, 256, 256)
})
});
generator._drawCommand = drawCommand;
}
BrdfLutGenerator.prototype.update = function(frameState) {
if (!defined_default(this._colorTexture)) {
const context = frameState.context;
const colorTexture = new Texture_default({
context,
width: 256,
height: 256,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
sampler: Sampler_default.NEAREST
});
this._colorTexture = colorTexture;
const framebuffer = new Framebuffer_default({
context,
colorTextures: [colorTexture],
destroyAttachments: false
});
createCommand(this, context, framebuffer);
this._drawCommand.execute(context);
framebuffer.destroy();
this._drawCommand.shaderProgram = this._drawCommand.shaderProgram && this._drawCommand.shaderProgram.destroy();
}
};
BrdfLutGenerator.prototype.isDestroyed = function() {
return false;
};
BrdfLutGenerator.prototype.destroy = function() {
this._colorTexture = this._colorTexture && this._colorTexture.destroy();
return destroyObject_default(this);
};
var BrdfLutGenerator_default = BrdfLutGenerator;
// packages/engine/Source/Scene/Camera.js
var import_InlineWorkers1046 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/CameraFlightPath.js
var import_InlineWorkers1044 = __toESM(require_InlineWorkers(), 1);
var CameraFlightPath = {};
function getAltitude(frustum, dx, dy) {
let near;
let top;
let right;
if (frustum instanceof PerspectiveFrustum_default) {
const tanTheta = Math.tan(0.5 * frustum.fovy);
near = frustum.near;
top = frustum.near * tanTheta;
right = frustum.aspectRatio * top;
return Math.max(dx * near / right, dy * near / top);
} else if (frustum instanceof PerspectiveOffCenterFrustum_default) {
near = frustum.near;
top = frustum.top;
right = frustum.right;
return Math.max(dx * near / right, dy * near / top);
}
return Math.max(dx, dy);
}
var scratchCart = new Cartesian3_default();
var scratchCart23 = new Cartesian3_default();
function createPitchFunction(startPitch, endPitch, heightFunction, pitchAdjustHeight) {
if (defined_default(pitchAdjustHeight) && heightFunction(0.5) > pitchAdjustHeight) {
const startHeight = heightFunction(0);
const endHeight = heightFunction(1);
const middleHeight = heightFunction(0.5);
const d1 = middleHeight - startHeight;
const d2 = middleHeight - endHeight;
return function(time) {
const altitude = heightFunction(time);
if (time <= 0.5) {
const t1 = (altitude - startHeight) / d1;
return Math_default.lerp(startPitch, -Math_default.PI_OVER_TWO, t1);
}
const t2 = (altitude - endHeight) / d2;
return Math_default.lerp(-Math_default.PI_OVER_TWO, endPitch, 1 - t2);
};
}
return function(time) {
return Math_default.lerp(startPitch, endPitch, time);
};
}
function createHeightFunction(camera, destination, startHeight, endHeight, optionAltitude) {
let altitude = optionAltitude;
const maxHeight = Math.max(startHeight, endHeight);
if (!defined_default(altitude)) {
const start = camera.position;
const end = destination;
const up = camera.up;
const right = camera.right;
const frustum = camera.frustum;
const diff = Cartesian3_default.subtract(start, end, scratchCart);
const verticalDistance = Cartesian3_default.magnitude(
Cartesian3_default.multiplyByScalar(up, Cartesian3_default.dot(diff, up), scratchCart23)
);
const horizontalDistance = Cartesian3_default.magnitude(
Cartesian3_default.multiplyByScalar(
right,
Cartesian3_default.dot(diff, right),
scratchCart23
)
);
altitude = Math.min(
getAltitude(frustum, verticalDistance, horizontalDistance) * 0.2,
1e9
);
}
if (maxHeight < altitude) {
const power = 8;
const factor2 = 1e6;
const s = -Math.pow((altitude - startHeight) * factor2, 1 / power);
const e = Math.pow((altitude - endHeight) * factor2, 1 / power);
return function(t) {
const x = t * (e - s) + s;
return -Math.pow(x, power) / factor2 + altitude;
};
}
return function(t) {
return Math_default.lerp(startHeight, endHeight, t);
};
}
function adjustAngleForLERP(startAngle, endAngle) {
if (Math_default.equalsEpsilon(
startAngle,
Math_default.TWO_PI,
Math_default.EPSILON11
)) {
startAngle = 0;
}
if (endAngle > startAngle + Math.PI) {
startAngle += Math_default.TWO_PI;
} else if (endAngle < startAngle - Math.PI) {
startAngle -= Math_default.TWO_PI;
}
return startAngle;
}
var scratchStart = new Cartesian3_default();
function createUpdateCV(scene, duration, destination, heading, pitch, roll, optionAltitude, optionPitchAdjustHeight) {
const camera = scene.camera;
const start = Cartesian3_default.clone(camera.position, scratchStart);
const startPitch = camera.pitch;
const startHeading = adjustAngleForLERP(camera.heading, heading);
const startRoll = adjustAngleForLERP(camera.roll, roll);
const heightFunction = createHeightFunction(
camera,
destination,
start.z,
destination.z,
optionAltitude
);
const pitchFunction = createPitchFunction(
startPitch,
pitch,
heightFunction,
optionPitchAdjustHeight
);
function update8(value) {
const time = value.time / duration;
camera.setView({
orientation: {
heading: Math_default.lerp(startHeading, heading, time),
pitch: pitchFunction(time),
roll: Math_default.lerp(startRoll, roll, time)
}
});
Cartesian2_default.lerp(start, destination, time, camera.position);
camera.position.z = heightFunction(time);
}
return update8;
}
function useLongestFlight(startCart, destCart) {
if (startCart.longitude < destCart.longitude) {
startCart.longitude += Math_default.TWO_PI;
} else {
destCart.longitude += Math_default.TWO_PI;
}
}
function useShortestFlight(startCart, destCart) {
const diff = startCart.longitude - destCart.longitude;
if (diff < -Math_default.PI) {
startCart.longitude += Math_default.TWO_PI;
} else if (diff > Math_default.PI) {
destCart.longitude += Math_default.TWO_PI;
}
}
var scratchStartCart = new Cartographic_default();
var scratchEndCart = new Cartographic_default();
function createUpdate3D(scene, duration, destination, heading, pitch, roll, optionAltitude, optionFlyOverLongitude, optionFlyOverLongitudeWeight, optionPitchAdjustHeight) {
const camera = scene.camera;
const projection = scene.mapProjection;
const ellipsoid = projection.ellipsoid;
const startCart = Cartographic_default.clone(
camera.positionCartographic,
scratchStartCart
);
const startPitch = camera.pitch;
const startHeading = adjustAngleForLERP(camera.heading, heading);
const startRoll = adjustAngleForLERP(camera.roll, roll);
const destCart = ellipsoid.cartesianToCartographic(
destination,
scratchEndCart
);
startCart.longitude = Math_default.zeroToTwoPi(startCart.longitude);
destCart.longitude = Math_default.zeroToTwoPi(destCart.longitude);
let useLongFlight = false;
if (defined_default(optionFlyOverLongitude)) {
const hitLon = Math_default.zeroToTwoPi(optionFlyOverLongitude);
const lonMin = Math.min(startCart.longitude, destCart.longitude);
const lonMax = Math.max(startCart.longitude, destCart.longitude);
const hitInside = hitLon >= lonMin && hitLon <= lonMax;
if (defined_default(optionFlyOverLongitudeWeight)) {
const din = Math.abs(startCart.longitude - destCart.longitude);
const dot2 = Math_default.TWO_PI - din;
const hitDistance = hitInside ? din : dot2;
const offDistance = hitInside ? dot2 : din;
if (hitDistance < offDistance * optionFlyOverLongitudeWeight && !hitInside) {
useLongFlight = true;
}
} else if (!hitInside) {
useLongFlight = true;
}
}
if (useLongFlight) {
useLongestFlight(startCart, destCart);
} else {
useShortestFlight(startCart, destCart);
}
const heightFunction = createHeightFunction(
camera,
destination,
startCart.height,
destCart.height,
optionAltitude
);
const pitchFunction = createPitchFunction(
startPitch,
pitch,
heightFunction,
optionPitchAdjustHeight
);
function isolateUpdateFunction() {
const startLongitude = startCart.longitude;
const destLongitude = destCart.longitude;
const startLatitude = startCart.latitude;
const destLatitude = destCart.latitude;
return function update8(value) {
const time = value.time / duration;
const position = Cartesian3_default.fromRadians(
Math_default.lerp(startLongitude, destLongitude, time),
Math_default.lerp(startLatitude, destLatitude, time),
heightFunction(time),
ellipsoid
);
camera.setView({
destination: position,
orientation: {
heading: Math_default.lerp(startHeading, heading, time),
pitch: pitchFunction(time),
roll: Math_default.lerp(startRoll, roll, time)
}
});
};
}
return isolateUpdateFunction();
}
function createUpdate2D(scene, duration, destination, heading, pitch, roll, optionAltitude) {
const camera = scene.camera;
const start = Cartesian3_default.clone(camera.position, scratchStart);
const startHeading = adjustAngleForLERP(camera.heading, heading);
const startHeight = camera.frustum.right - camera.frustum.left;
const heightFunction = createHeightFunction(
camera,
destination,
startHeight,
destination.z,
optionAltitude
);
function update8(value) {
const time = value.time / duration;
camera.setView({
orientation: {
heading: Math_default.lerp(startHeading, heading, time)
}
});
Cartesian2_default.lerp(start, destination, time, camera.position);
const zoom = heightFunction(time);
const frustum = camera.frustum;
const ratio = frustum.top / frustum.right;
const incrementAmount = (zoom - (frustum.right - frustum.left)) * 0.5;
frustum.right += incrementAmount;
frustum.left -= incrementAmount;
frustum.top = ratio * frustum.right;
frustum.bottom = -frustum.top;
}
return update8;
}
var scratchCartographic20 = new Cartographic_default();
var scratchDestination = new Cartesian3_default();
function emptyFlight(complete, cancel) {
return {
startObject: {},
stopObject: {},
duration: 0,
complete,
cancel
};
}
function wrapCallback(controller, cb) {
function wrapped() {
if (typeof cb === "function") {
cb();
}
controller.enableInputs = true;
}
return wrapped;
}
CameraFlightPath.createTween = function(scene, options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
let destination = options.destination;
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required.");
}
if (!defined_default(destination)) {
throw new DeveloperError_default("destination is required.");
}
const mode2 = scene.mode;
if (mode2 === SceneMode_default.MORPHING) {
return emptyFlight();
}
const convert = options.convert ?? true;
const projection = scene.mapProjection;
const ellipsoid = projection.ellipsoid;
const maximumHeight = options.maximumHeight;
const flyOverLongitude = options.flyOverLongitude;
const flyOverLongitudeWeight = options.flyOverLongitudeWeight;
const pitchAdjustHeight = options.pitchAdjustHeight;
let easingFunction = options.easingFunction;
if (convert && mode2 !== SceneMode_default.SCENE3D) {
ellipsoid.cartesianToCartographic(destination, scratchCartographic20);
destination = projection.project(scratchCartographic20, scratchDestination);
}
const camera = scene.camera;
const transform3 = options.endTransform;
if (defined_default(transform3)) {
camera._setTransform(transform3);
}
let duration = options.duration;
if (!defined_default(duration)) {
duration = Math.ceil(Cartesian3_default.distance(camera.position, destination) / 1e6) + 2;
duration = Math.min(duration, 3);
}
const heading = options.heading ?? 0;
const pitch = options.pitch ?? -Math_default.PI_OVER_TWO;
const roll = options.roll ?? 0;
const controller = scene.screenSpaceCameraController;
controller.enableInputs = false;
const complete = wrapCallback(controller, options.complete);
const cancel = wrapCallback(controller, options.cancel);
const frustum = camera.frustum;
let empty = scene.mode === SceneMode_default.SCENE2D;
empty = empty && Cartesian2_default.equalsEpsilon(camera.position, destination, Math_default.EPSILON6);
empty = empty && Math_default.equalsEpsilon(
Math.max(frustum.right - frustum.left, frustum.top - frustum.bottom),
destination.z,
Math_default.EPSILON6
);
empty = empty || scene.mode !== SceneMode_default.SCENE2D && Cartesian3_default.equalsEpsilon(
destination,
camera.position,
Math_default.EPSILON10
);
empty = empty && Math_default.equalsEpsilon(
Math_default.negativePiToPi(heading),
Math_default.negativePiToPi(camera.heading),
Math_default.EPSILON10
) && Math_default.equalsEpsilon(
Math_default.negativePiToPi(pitch),
Math_default.negativePiToPi(camera.pitch),
Math_default.EPSILON10
) && Math_default.equalsEpsilon(
Math_default.negativePiToPi(roll),
Math_default.negativePiToPi(camera.roll),
Math_default.EPSILON10
);
if (empty) {
return emptyFlight(complete, cancel);
}
const updateFunctions2 = new Array(4);
updateFunctions2[SceneMode_default.SCENE2D] = createUpdate2D;
updateFunctions2[SceneMode_default.SCENE3D] = createUpdate3D;
updateFunctions2[SceneMode_default.COLUMBUS_VIEW] = createUpdateCV;
if (duration <= 0) {
const newOnComplete = function() {
const update9 = updateFunctions2[mode2](
scene,
1,
destination,
heading,
pitch,
roll,
maximumHeight,
flyOverLongitude,
flyOverLongitudeWeight,
pitchAdjustHeight
);
update9({ time: 1 });
if (typeof complete === "function") {
complete();
}
};
return emptyFlight(newOnComplete, cancel);
}
const update8 = updateFunctions2[mode2](
scene,
duration,
destination,
heading,
pitch,
roll,
maximumHeight,
flyOverLongitude,
flyOverLongitudeWeight,
pitchAdjustHeight
);
if (!defined_default(easingFunction)) {
const startHeight = camera.positionCartographic.height;
const endHeight = mode2 === SceneMode_default.SCENE3D ? ellipsoid.cartesianToCartographic(destination).height : destination.z;
if (startHeight > endHeight && startHeight > 11500) {
easingFunction = EasingFunction_default.CUBIC_OUT;
} else {
easingFunction = EasingFunction_default.QUINTIC_IN_OUT;
}
}
return {
duration,
easingFunction,
startObject: {
time: 0
},
stopObject: {
time: duration
},
update: update8,
complete,
cancel
};
};
var CameraFlightPath_default = CameraFlightPath;
// packages/engine/Source/Scene/MapMode2D.js
var import_InlineWorkers1045 = __toESM(require_InlineWorkers(), 1);
var MapMode2D = {
/**
* The 2D map can be rotated about the z axis.
*
* @type {number}
* @constant
*/
ROTATE: 0,
/**
* The 2D map can be scrolled infinitely in the horizontal direction.
*
* @type {number}
* @constant
*/
INFINITE_SCROLL: 1
};
var MapMode2D_default = Object.freeze(MapMode2D);
// packages/engine/Source/Scene/Camera.js
function Camera(scene) {
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required.");
}
this._scene = scene;
this._transform = Matrix4_default.clone(Matrix4_default.IDENTITY);
this._invTransform = Matrix4_default.clone(Matrix4_default.IDENTITY);
this._actualTransform = Matrix4_default.clone(Matrix4_default.IDENTITY);
this._actualInvTransform = Matrix4_default.clone(Matrix4_default.IDENTITY);
this._transformChanged = false;
this.position = new Cartesian3_default();
this._position = new Cartesian3_default();
this._positionWC = new Cartesian3_default();
this._positionCartographic = new Cartographic_default();
this._oldPositionWC = void 0;
this.positionWCDeltaMagnitude = 0;
this.positionWCDeltaMagnitudeLastFrame = 0;
this.timeSinceMoved = 0;
this._lastMovedTimestamp = 0;
this.direction = new Cartesian3_default();
this._direction = new Cartesian3_default();
this._directionWC = new Cartesian3_default();
this.up = new Cartesian3_default();
this._up = new Cartesian3_default();
this._upWC = new Cartesian3_default();
this.right = new Cartesian3_default();
this._right = new Cartesian3_default();
this._rightWC = new Cartesian3_default();
this.frustum = new PerspectiveFrustum_default();
this.frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight;
this.frustum.fov = Math_default.toRadians(60);
this.defaultMoveAmount = 1e5;
this.defaultLookAmount = Math.PI / 60;
this.defaultRotateAmount = Math.PI / 3600;
this.defaultZoomAmount = 1e5;
this.constrainedAxis = void 0;
this.maximumZoomFactor = 1.5;
this._moveStart = new Event_default();
this._moveEnd = new Event_default();
this._changed = new Event_default();
this._changedPosition = void 0;
this._changedDirection = void 0;
this._changedFrustum = void 0;
this._changedHeading = void 0;
this._changedRoll = void 0;
this.percentageChanged = 0.5;
this._viewMatrix = new Matrix4_default();
this._invViewMatrix = new Matrix4_default();
updateViewMatrix(this);
this._mode = SceneMode_default.SCENE3D;
this._modeChanged = true;
const projection = scene.mapProjection;
this._projection = projection;
this._maxCoord = projection.project(
new Cartographic_default(Math.PI, Math_default.PI_OVER_TWO)
);
this._max2Dfrustum = void 0;
rectangleCameraPosition3D(
this,
Camera.DEFAULT_VIEW_RECTANGLE,
this.position,
true
);
let mag = Cartesian3_default.magnitude(this.position);
mag += mag * Camera.DEFAULT_VIEW_FACTOR;
Cartesian3_default.normalize(this.position, this.position);
Cartesian3_default.multiplyByScalar(this.position, mag, this.position);
}
Camera.TRANSFORM_2D = new Matrix4_default(
0,
0,
1,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
1
);
Camera.TRANSFORM_2D_INVERSE = Matrix4_default.inverseTransformation(
Camera.TRANSFORM_2D,
new Matrix4_default()
);
Camera.DEFAULT_VIEW_RECTANGLE = Rectangle_default.fromDegrees(
-95,
-20,
-70,
90
);
Camera.DEFAULT_VIEW_FACTOR = 0.5;
Camera.DEFAULT_OFFSET = new HeadingPitchRange_default(
0,
-Math_default.PI_OVER_FOUR,
0
);
function updateViewMatrix(camera) {
Matrix4_default.computeView(
camera._position,
camera._direction,
camera._up,
camera._right,
camera._viewMatrix
);
Matrix4_default.multiply(
camera._viewMatrix,
camera._actualInvTransform,
camera._viewMatrix
);
Matrix4_default.inverseTransformation(camera._viewMatrix, camera._invViewMatrix);
}
function updateCameraDeltas(camera) {
if (!defined_default(camera._oldPositionWC)) {
camera._oldPositionWC = Cartesian3_default.clone(
camera.positionWC,
camera._oldPositionWC
);
} else {
camera.positionWCDeltaMagnitudeLastFrame = camera.positionWCDeltaMagnitude;
const delta = Cartesian3_default.subtract(
camera.positionWC,
camera._oldPositionWC,
camera._oldPositionWC
);
camera.positionWCDeltaMagnitude = Cartesian3_default.magnitude(delta);
camera._oldPositionWC = Cartesian3_default.clone(
camera.positionWC,
camera._oldPositionWC
);
if (camera.positionWCDeltaMagnitude > 0) {
camera.timeSinceMoved = 0;
camera._lastMovedTimestamp = getTimestamp_default();
} else {
camera.timeSinceMoved = Math.max(getTimestamp_default() - camera._lastMovedTimestamp, 0) / 1e3;
}
}
}
Camera.prototype.canPreloadFlight = function() {
return defined_default(this._currentFlight) && this._mode !== SceneMode_default.SCENE2D;
};
Camera.prototype._updateCameraChanged = function() {
const camera = this;
updateCameraDeltas(camera);
if (camera._changed.numberOfListeners === 0) {
return;
}
const percentageChanged = camera.percentageChanged;
const currentHeading = camera.heading;
if (!defined_default(camera._changedHeading)) {
camera._changedHeading = currentHeading;
}
let headingDelta = Math.abs(camera._changedHeading - currentHeading) % Math_default.TWO_PI;
headingDelta = headingDelta > Math_default.PI ? Math_default.TWO_PI - headingDelta : headingDelta;
const headingChangedPercentage = headingDelta / Math.PI;
if (headingChangedPercentage > percentageChanged) {
camera._changedHeading = currentHeading;
}
const currentRoll = camera.roll;
if (!defined_default(camera._changedRoll)) {
camera._changedRoll = currentRoll;
}
let rollDelta = Math.abs(camera._changedRoll - currentRoll) % Math_default.TWO_PI;
rollDelta = rollDelta > Math_default.PI ? Math_default.TWO_PI - rollDelta : rollDelta;
const rollChangedPercentage = rollDelta / Math.PI;
if (rollChangedPercentage > percentageChanged) {
camera._changedRoll = currentRoll;
}
if (rollChangedPercentage > percentageChanged || headingChangedPercentage > percentageChanged) {
camera._changed.raiseEvent(
Math.max(rollChangedPercentage, headingChangedPercentage)
);
}
if (camera._mode === SceneMode_default.SCENE2D) {
if (!defined_default(camera._changedFrustum)) {
camera._changedPosition = Cartesian3_default.clone(
camera.position,
camera._changedPosition
);
camera._changedFrustum = camera.frustum.clone();
return;
}
const position = camera.position;
const lastPosition = camera._changedPosition;
const frustum = camera.frustum;
const lastFrustum = camera._changedFrustum;
const x0 = position.x + frustum.left;
const x1 = position.x + frustum.right;
const x2 = lastPosition.x + lastFrustum.left;
const x3 = lastPosition.x + lastFrustum.right;
const y0 = position.y + frustum.bottom;
const y1 = position.y + frustum.top;
const y2 = lastPosition.y + lastFrustum.bottom;
const y3 = lastPosition.y + lastFrustum.top;
const leftX = Math.max(x0, x2);
const rightX = Math.min(x1, x3);
const bottomY = Math.max(y0, y2);
const topY = Math.min(y1, y3);
let areaPercentage;
if (leftX >= rightX || bottomY >= y1) {
areaPercentage = 1;
} else {
let areaRef = lastFrustum;
if (x0 < x2 && x1 > x3 && y0 < y2 && y1 > y3) {
areaRef = frustum;
}
areaPercentage = 1 - (rightX - leftX) * (topY - bottomY) / ((areaRef.right - areaRef.left) * (areaRef.top - areaRef.bottom));
}
if (areaPercentage > percentageChanged) {
camera._changed.raiseEvent(areaPercentage);
camera._changedPosition = Cartesian3_default.clone(
camera.position,
camera._changedPosition
);
camera._changedFrustum = camera.frustum.clone(camera._changedFrustum);
}
return;
}
if (!defined_default(camera._changedDirection)) {
camera._changedPosition = Cartesian3_default.clone(
camera.positionWC,
camera._changedPosition
);
camera._changedDirection = Cartesian3_default.clone(
camera.directionWC,
camera._changedDirection
);
return;
}
const dirAngle = Math_default.acosClamped(
Cartesian3_default.dot(camera.directionWC, camera._changedDirection)
);
let dirPercentage;
if (defined_default(camera.frustum.fovy)) {
dirPercentage = dirAngle / (camera.frustum.fovy * 0.5);
} else {
dirPercentage = dirAngle;
}
const distance2 = Cartesian3_default.distance(
camera.positionWC,
camera._changedPosition
);
const heightPercentage = distance2 / camera.positionCartographic.height;
if (dirPercentage > percentageChanged || heightPercentage > percentageChanged) {
camera._changed.raiseEvent(Math.max(dirPercentage, heightPercentage));
camera._changedPosition = Cartesian3_default.clone(
camera.positionWC,
camera._changedPosition
);
camera._changedDirection = Cartesian3_default.clone(
camera.directionWC,
camera._changedDirection
);
}
};
function convertTransformForColumbusView(camera) {
Transforms_default.basisTo2D(
camera._projection,
camera._transform,
camera._actualTransform
);
}
var scratchCartographic21 = new Cartographic_default();
var scratchCartesian3Projection2 = new Cartesian3_default();
var scratchCartesian314 = new Cartesian3_default();
var scratchCartesian4Origin = new Cartesian4_default();
var scratchCartesian4NewOrigin = new Cartesian4_default();
var scratchCartesian4NewXAxis = new Cartesian4_default();
var scratchCartesian4NewYAxis = new Cartesian4_default();
var scratchCartesian4NewZAxis = new Cartesian4_default();
function convertTransformFor2D(camera) {
const projection = camera._projection;
const ellipsoid = projection.ellipsoid;
const origin = Matrix4_default.getColumn(
camera._transform,
3,
scratchCartesian4Origin
);
const cartographic2 = ellipsoid.cartesianToCartographic(
origin,
scratchCartographic21
);
const projectedPosition2 = projection.project(
cartographic2,
scratchCartesian3Projection2
);
const newOrigin = scratchCartesian4NewOrigin;
newOrigin.x = projectedPosition2.z;
newOrigin.y = projectedPosition2.x;
newOrigin.z = projectedPosition2.y;
newOrigin.w = 1;
const newZAxis = Cartesian4_default.clone(
Cartesian4_default.UNIT_X,
scratchCartesian4NewZAxis
);
const xAxis = Cartesian4_default.add(
Matrix4_default.getColumn(camera._transform, 0, scratchCartesian314),
origin,
scratchCartesian314
);
ellipsoid.cartesianToCartographic(xAxis, cartographic2);
projection.project(cartographic2, projectedPosition2);
const newXAxis = scratchCartesian4NewXAxis;
newXAxis.x = projectedPosition2.z;
newXAxis.y = projectedPosition2.x;
newXAxis.z = projectedPosition2.y;
newXAxis.w = 0;
Cartesian3_default.subtract(newXAxis, newOrigin, newXAxis);
newXAxis.x = 0;
const newYAxis = scratchCartesian4NewYAxis;
if (Cartesian3_default.magnitudeSquared(newXAxis) > Math_default.EPSILON10) {
Cartesian3_default.cross(newZAxis, newXAxis, newYAxis);
} else {
const yAxis = Cartesian4_default.add(
Matrix4_default.getColumn(camera._transform, 1, scratchCartesian314),
origin,
scratchCartesian314
);
ellipsoid.cartesianToCartographic(yAxis, cartographic2);
projection.project(cartographic2, projectedPosition2);
newYAxis.x = projectedPosition2.z;
newYAxis.y = projectedPosition2.x;
newYAxis.z = projectedPosition2.y;
newYAxis.w = 0;
Cartesian3_default.subtract(newYAxis, newOrigin, newYAxis);
newYAxis.x = 0;
if (Cartesian3_default.magnitudeSquared(newYAxis) < Math_default.EPSILON10) {
Cartesian4_default.clone(Cartesian4_default.UNIT_Y, newXAxis);
Cartesian4_default.clone(Cartesian4_default.UNIT_Z, newYAxis);
}
}
Cartesian3_default.cross(newYAxis, newZAxis, newXAxis);
Cartesian3_default.normalize(newXAxis, newXAxis);
Cartesian3_default.cross(newZAxis, newXAxis, newYAxis);
Cartesian3_default.normalize(newYAxis, newYAxis);
Matrix4_default.setColumn(
camera._actualTransform,
0,
newXAxis,
camera._actualTransform
);
Matrix4_default.setColumn(
camera._actualTransform,
1,
newYAxis,
camera._actualTransform
);
Matrix4_default.setColumn(
camera._actualTransform,
2,
newZAxis,
camera._actualTransform
);
Matrix4_default.setColumn(
camera._actualTransform,
3,
newOrigin,
camera._actualTransform
);
}
var scratchCartesian30 = new Cartesian3_default();
function updateMembers(camera) {
const mode2 = camera._mode;
let heightChanged = false;
let height = 0;
if (mode2 === SceneMode_default.SCENE2D) {
height = camera.frustum.right - camera.frustum.left;
heightChanged = height !== camera._positionCartographic.height;
}
let position = camera._position;
const positionChanged = !Cartesian3_default.equals(position, camera.position) || heightChanged;
if (positionChanged) {
position = Cartesian3_default.clone(camera.position, camera._position);
}
let direction2 = camera._direction;
const directionChanged = !Cartesian3_default.equals(direction2, camera.direction);
if (directionChanged) {
Cartesian3_default.normalize(camera.direction, camera.direction);
direction2 = Cartesian3_default.clone(camera.direction, camera._direction);
}
let up = camera._up;
const upChanged = !Cartesian3_default.equals(up, camera.up);
if (upChanged) {
Cartesian3_default.normalize(camera.up, camera.up);
up = Cartesian3_default.clone(camera.up, camera._up);
}
let right = camera._right;
const rightChanged = !Cartesian3_default.equals(right, camera.right);
if (rightChanged) {
Cartesian3_default.normalize(camera.right, camera.right);
right = Cartesian3_default.clone(camera.right, camera._right);
}
const transformChanged = camera._transformChanged || camera._modeChanged;
camera._transformChanged = false;
if (transformChanged) {
Matrix4_default.inverseTransformation(camera._transform, camera._invTransform);
if (camera._mode === SceneMode_default.COLUMBUS_VIEW || camera._mode === SceneMode_default.SCENE2D) {
if (Matrix4_default.equals(Matrix4_default.IDENTITY, camera._transform)) {
Matrix4_default.clone(Camera.TRANSFORM_2D, camera._actualTransform);
} else if (camera._mode === SceneMode_default.COLUMBUS_VIEW) {
convertTransformForColumbusView(camera);
} else {
convertTransformFor2D(camera);
}
} else {
Matrix4_default.clone(camera._transform, camera._actualTransform);
}
Matrix4_default.inverseTransformation(
camera._actualTransform,
camera._actualInvTransform
);
camera._modeChanged = false;
}
const transform3 = camera._actualTransform;
if (positionChanged || transformChanged) {
camera._positionWC = Matrix4_default.multiplyByPoint(
transform3,
position,
camera._positionWC
);
if (mode2 === SceneMode_default.SCENE3D || mode2 === SceneMode_default.MORPHING) {
camera._positionCartographic = camera._projection.ellipsoid.cartesianToCartographic(
camera._positionWC,
camera._positionCartographic
);
} else {
const positionENU = scratchCartesian30;
positionENU.x = camera._positionWC.y;
positionENU.y = camera._positionWC.z;
positionENU.z = camera._positionWC.x;
if (mode2 === SceneMode_default.SCENE2D) {
positionENU.z = height;
}
camera._projection.unproject(positionENU, camera._positionCartographic);
}
}
if (directionChanged || upChanged || rightChanged) {
const det = Cartesian3_default.dot(
direction2,
Cartesian3_default.cross(up, right, scratchCartesian30)
);
if (Math.abs(1 - det) > Math_default.EPSILON2) {
const invUpMag = 1 / Cartesian3_default.magnitudeSquared(up);
const scalar = Cartesian3_default.dot(up, direction2) * invUpMag;
const w0 = Cartesian3_default.multiplyByScalar(
direction2,
scalar,
scratchCartesian30
);
up = Cartesian3_default.normalize(
Cartesian3_default.subtract(up, w0, camera._up),
camera._up
);
Cartesian3_default.clone(up, camera.up);
right = Cartesian3_default.cross(direction2, up, camera._right);
Cartesian3_default.clone(right, camera.right);
}
}
if (directionChanged || transformChanged) {
camera._directionWC = Matrix4_default.multiplyByPointAsVector(
transform3,
direction2,
camera._directionWC
);
Cartesian3_default.normalize(camera._directionWC, camera._directionWC);
}
if (upChanged || transformChanged) {
camera._upWC = Matrix4_default.multiplyByPointAsVector(transform3, up, camera._upWC);
Cartesian3_default.normalize(camera._upWC, camera._upWC);
}
if (rightChanged || transformChanged) {
camera._rightWC = Matrix4_default.multiplyByPointAsVector(
transform3,
right,
camera._rightWC
);
Cartesian3_default.normalize(camera._rightWC, camera._rightWC);
}
if (positionChanged || directionChanged || upChanged || rightChanged || transformChanged) {
updateViewMatrix(camera);
}
}
function getHeading(direction2, up) {
let heading;
if (!Math_default.equalsEpsilon(Math.abs(direction2.z), 1, Math_default.EPSILON3)) {
heading = Math.atan2(direction2.y, direction2.x) - Math_default.PI_OVER_TWO;
} else {
heading = Math.atan2(up.y, up.x) - Math_default.PI_OVER_TWO;
}
return Math_default.TWO_PI - Math_default.zeroToTwoPi(heading);
}
function getPitch(direction2) {
return Math_default.PI_OVER_TWO - Math_default.acosClamped(direction2.z);
}
function getRoll(direction2, up, right) {
let roll = 0;
if (!Math_default.equalsEpsilon(Math.abs(direction2.z), 1, Math_default.EPSILON3)) {
roll = Math.atan2(-right.z, up.z);
roll = Math_default.zeroToTwoPi(roll + Math_default.TWO_PI);
}
return roll;
}
var scratchHPRMatrix1 = new Matrix4_default();
var scratchHPRMatrix2 = new Matrix4_default();
Object.defineProperties(Camera.prototype, {
/**
* Gets the camera's reference frame. The inverse of this transformation is appended to the view matrix.
* @memberof Camera.prototype
*
* @type {Matrix4}
* @readonly
*
* @default {@link Matrix4.IDENTITY}
*/
transform: {
get: function() {
return this._transform;
}
},
/**
* Gets the inverse camera transform.
* @memberof Camera.prototype
*
* @type {Matrix4}
* @readonly
*
* @default {@link Matrix4.IDENTITY}
*/
inverseTransform: {
get: function() {
updateMembers(this);
return this._invTransform;
}
},
/**
* Gets the view matrix.
* @memberof Camera.prototype
*
* @type {Matrix4}
* @readonly
*
* @see Camera#inverseViewMatrix
*/
viewMatrix: {
get: function() {
updateMembers(this);
return this._viewMatrix;
}
},
/**
* Gets the inverse view matrix.
* @memberof Camera.prototype
*
* @type {Matrix4}
* @readonly
*
* @see Camera#viewMatrix
*/
inverseViewMatrix: {
get: function() {
updateMembers(this);
return this._invViewMatrix;
}
},
/**
* Gets the {@link Cartographic} position of the camera, with longitude and latitude
* expressed in radians and height in meters. In 2D and Columbus View, it is possible
* for the returned longitude and latitude to be outside the range of valid longitudes
* and latitudes when the camera is outside the map.
* @memberof Camera.prototype
*
* @type {Cartographic}
* @readonly
*/
positionCartographic: {
get: function() {
updateMembers(this);
return this._positionCartographic;
}
},
/**
* Gets the position of the camera in world coordinates.
* @memberof Camera.prototype
*
* @type {Cartesian3}
* @readonly
*/
positionWC: {
get: function() {
updateMembers(this);
return this._positionWC;
}
},
/**
* Gets the view direction of the camera in world coordinates.
* @memberof Camera.prototype
*
* @type {Cartesian3}
* @readonly
*/
directionWC: {
get: function() {
updateMembers(this);
return this._directionWC;
}
},
/**
* Gets the up direction of the camera in world coordinates.
* @memberof Camera.prototype
*
* @type {Cartesian3}
* @readonly
*/
upWC: {
get: function() {
updateMembers(this);
return this._upWC;
}
},
/**
* Gets the right direction of the camera in world coordinates.
* @memberof Camera.prototype
*
* @type {Cartesian3}
* @readonly
*/
rightWC: {
get: function() {
updateMembers(this);
return this._rightWC;
}
},
/**
* Gets the camera heading in radians.
* @memberof Camera.prototype
*
* @type {number}
* @readonly
*/
heading: {
get: function() {
if (this._mode !== SceneMode_default.MORPHING) {
const ellipsoid = this._projection.ellipsoid;
const oldTransform = Matrix4_default.clone(this._transform, scratchHPRMatrix1);
const transform3 = Transforms_default.eastNorthUpToFixedFrame(
this.positionWC,
ellipsoid,
scratchHPRMatrix2
);
this._setTransform(transform3);
const heading = getHeading(this.direction, this.up);
this._setTransform(oldTransform);
return heading;
}
return void 0;
}
},
/**
* Gets the camera pitch in radians.
* @memberof Camera.prototype
*
* @type {number}
* @readonly
*/
pitch: {
get: function() {
if (this._mode !== SceneMode_default.MORPHING) {
const ellipsoid = this._projection.ellipsoid;
const oldTransform = Matrix4_default.clone(this._transform, scratchHPRMatrix1);
const transform3 = Transforms_default.eastNorthUpToFixedFrame(
this.positionWC,
ellipsoid,
scratchHPRMatrix2
);
this._setTransform(transform3);
const pitch = getPitch(this.direction);
this._setTransform(oldTransform);
return pitch;
}
return void 0;
}
},
/**
* Gets the camera roll in radians.
* @memberof Camera.prototype
*
* @type {number}
* @readonly
*/
roll: {
get: function() {
if (this._mode !== SceneMode_default.MORPHING) {
const ellipsoid = this._projection.ellipsoid;
const oldTransform = Matrix4_default.clone(this._transform, scratchHPRMatrix1);
const transform3 = Transforms_default.eastNorthUpToFixedFrame(
this.positionWC,
ellipsoid,
scratchHPRMatrix2
);
this._setTransform(transform3);
const roll = getRoll(this.direction, this.up, this.right);
this._setTransform(oldTransform);
return roll;
}
return void 0;
}
},
/**
* Gets the event that will be raised at when the camera starts to move.
* @memberof Camera.prototype
* @type {Event}
* @readonly
*/
moveStart: {
get: function() {
return this._moveStart;
}
},
/**
* Gets the event that will be raised when the camera has stopped moving.
* @memberof Camera.prototype
* @type {Event}
* @readonly
*/
moveEnd: {
get: function() {
return this._moveEnd;
}
},
/**
* Gets the event that will be raised when the camera has changed by percentageChanged.
* @memberof Camera.prototype
* @type {Event}
* @readonly
*/
changed: {
get: function() {
return this._changed;
}
}
});
Camera.prototype.update = function(mode2) {
if (!defined_default(mode2)) {
throw new DeveloperError_default("mode is required.");
}
if (mode2 === SceneMode_default.SCENE2D && !(this.frustum instanceof OrthographicOffCenterFrustum_default)) {
throw new DeveloperError_default(
"An OrthographicOffCenterFrustum is required in 2D."
);
}
if ((mode2 === SceneMode_default.SCENE3D || mode2 === SceneMode_default.COLUMBUS_VIEW) && !(this.frustum instanceof PerspectiveFrustum_default) && !(this.frustum instanceof OrthographicFrustum_default)) {
throw new DeveloperError_default(
"A PerspectiveFrustum or OrthographicFrustum is required in 3D and Columbus view"
);
}
let updateFrustum = false;
if (mode2 !== this._mode) {
this._mode = mode2;
this._modeChanged = mode2 !== SceneMode_default.MORPHING;
updateFrustum = this._mode === SceneMode_default.SCENE2D;
}
if (updateFrustum) {
const frustum = this._max2Dfrustum = this.frustum.clone();
if (!(frustum instanceof OrthographicOffCenterFrustum_default)) {
throw new DeveloperError_default(
"The camera frustum is expected to be orthographic for 2D camera control."
);
}
const maxZoomOut = 2;
const ratio = frustum.top / frustum.right;
frustum.right = this._maxCoord.x * maxZoomOut;
frustum.left = -frustum.right;
frustum.top = ratio * frustum.right;
frustum.bottom = -frustum.top;
}
if (this._mode === SceneMode_default.SCENE2D) {
clampMove2D(this, this.position);
}
};
var setTransformPosition = new Cartesian3_default();
var setTransformUp = new Cartesian3_default();
var setTransformDirection = new Cartesian3_default();
Camera.prototype._setTransform = function(transform3) {
const position = Cartesian3_default.clone(this.positionWC, setTransformPosition);
const up = Cartesian3_default.clone(this.upWC, setTransformUp);
const direction2 = Cartesian3_default.clone(this.directionWC, setTransformDirection);
Matrix4_default.clone(transform3, this._transform);
this._transformChanged = true;
updateMembers(this);
const inverse = this._actualInvTransform;
Matrix4_default.multiplyByPoint(inverse, position, this.position);
Matrix4_default.multiplyByPointAsVector(inverse, direction2, this.direction);
Matrix4_default.multiplyByPointAsVector(inverse, up, this.up);
Cartesian3_default.cross(this.direction, this.up, this.right);
updateMembers(this);
};
var scratchAdjustOrthographicFrustumMousePosition = new Cartesian2_default();
var scratchPickRay = new Ray_default();
var scratchRayIntersection = new Cartesian3_default();
var scratchDepthIntersection = new Cartesian3_default();
function calculateOrthographicFrustumWidth(camera) {
if (!Matrix4_default.equals(Matrix4_default.IDENTITY, camera.transform)) {
return Cartesian3_default.magnitude(camera.position);
}
const scene = camera._scene;
const globe = scene.globe;
const mousePosition = scratchAdjustOrthographicFrustumMousePosition;
mousePosition.x = scene.drawingBufferWidth / scene.pixelRatio / 2;
mousePosition.y = scene.drawingBufferHeight / scene.pixelRatio / 2;
let rayIntersection;
if (defined_default(globe)) {
const ray = camera.getPickRay(mousePosition, scratchPickRay);
rayIntersection = globe.pickWorldCoordinates(
ray,
scene,
true,
scratchRayIntersection
);
}
let depthIntersection;
if (scene.pickPositionSupported) {
depthIntersection = scene.pickPositionWorldCoordinates(
mousePosition,
scratchDepthIntersection
);
}
let distance2;
if (defined_default(rayIntersection) || defined_default(depthIntersection)) {
const depthDistance = defined_default(depthIntersection) ? Cartesian3_default.distance(depthIntersection, camera.positionWC) : Number.POSITIVE_INFINITY;
const rayDistance = defined_default(rayIntersection) ? Cartesian3_default.distance(rayIntersection, camera.positionWC) : Number.POSITIVE_INFINITY;
distance2 = Math.min(depthDistance, rayDistance);
} else {
distance2 = Math.max(camera.positionCartographic.height, 0);
}
return distance2;
}
Camera.prototype._adjustOrthographicFrustum = function(zooming) {
if (!(this.frustum instanceof OrthographicFrustum_default)) {
return;
}
if (!zooming && this._positionCartographic.height < 15e4) {
return;
}
this.frustum.width = calculateOrthographicFrustumWidth(this);
};
var scratchSetViewCartesian = new Cartesian3_default();
var scratchSetViewTransform1 = new Matrix4_default();
var scratchSetViewTransform2 = new Matrix4_default();
var scratchSetViewQuaternion = new Quaternion_default();
var scratchSetViewMatrix3 = new Matrix3_default();
var scratchSetViewCartographic = new Cartographic_default();
function setView3D(camera, position, hpr) {
if (isNaN(position.x) || isNaN(position.y) || isNaN(position.z)) {
throw new DeveloperError_default("position has a NaN component");
}
const currentTransform = Matrix4_default.clone(
camera.transform,
scratchSetViewTransform1
);
const localTransform = Transforms_default.eastNorthUpToFixedFrame(
position,
camera._projection.ellipsoid,
scratchSetViewTransform2
);
camera._setTransform(localTransform);
Cartesian3_default.clone(Cartesian3_default.ZERO, camera.position);
hpr.heading = hpr.heading - Math_default.PI_OVER_TWO;
const rotQuat = Quaternion_default.fromHeadingPitchRoll(
hpr,
scratchSetViewQuaternion
);
const rotMat = Matrix3_default.fromQuaternion(rotQuat, scratchSetViewMatrix3);
Matrix3_default.getColumn(rotMat, 0, camera.direction);
Matrix3_default.getColumn(rotMat, 2, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
camera._setTransform(currentTransform);
camera._adjustOrthographicFrustum(true);
}
function setViewCV(camera, position, hpr, convert) {
const currentTransform = Matrix4_default.clone(
camera.transform,
scratchSetViewTransform1
);
camera._setTransform(Matrix4_default.IDENTITY);
if (!Cartesian3_default.equals(position, camera.positionWC)) {
if (convert) {
const projection = camera._projection;
const cartographic2 = projection.ellipsoid.cartesianToCartographic(
position,
scratchSetViewCartographic
);
position = projection.project(cartographic2, scratchSetViewCartesian);
}
Cartesian3_default.clone(position, camera.position);
}
hpr.heading = hpr.heading - Math_default.PI_OVER_TWO;
const rotQuat = Quaternion_default.fromHeadingPitchRoll(
hpr,
scratchSetViewQuaternion
);
const rotMat = Matrix3_default.fromQuaternion(rotQuat, scratchSetViewMatrix3);
Matrix3_default.getColumn(rotMat, 0, camera.direction);
Matrix3_default.getColumn(rotMat, 2, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
camera._setTransform(currentTransform);
camera._adjustOrthographicFrustum(true);
}
function setView2D(camera, position, hpr, convert) {
const currentTransform = Matrix4_default.clone(
camera.transform,
scratchSetViewTransform1
);
camera._setTransform(Matrix4_default.IDENTITY);
if (!Cartesian3_default.equals(position, camera.positionWC)) {
if (convert) {
const projection = camera._projection;
const cartographic2 = projection.ellipsoid.cartesianToCartographic(
position,
scratchSetViewCartographic
);
position = projection.project(cartographic2, scratchSetViewCartesian);
}
Cartesian2_default.clone(position, camera.position);
const newLeft = -position.z * 0.5;
const newRight = -newLeft;
const frustum = camera.frustum;
if (newRight > newLeft) {
const ratio = frustum.top / frustum.right;
frustum.right = newRight;
frustum.left = newLeft;
frustum.top = frustum.right * ratio;
frustum.bottom = -frustum.top;
}
}
if (camera._scene.mapMode2D === MapMode2D_default.ROTATE) {
hpr.heading = hpr.heading - Math_default.PI_OVER_TWO;
hpr.pitch = -Math_default.PI_OVER_TWO;
hpr.roll = 0;
const rotQuat = Quaternion_default.fromHeadingPitchRoll(
hpr,
scratchSetViewQuaternion
);
const rotMat = Matrix3_default.fromQuaternion(rotQuat, scratchSetViewMatrix3);
Matrix3_default.getColumn(rotMat, 2, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
}
camera._setTransform(currentTransform);
}
var scratchToHPRDirection = new Cartesian3_default();
var scratchToHPRUp = new Cartesian3_default();
var scratchToHPRRight = new Cartesian3_default();
function directionUpToHeadingPitchRoll(camera, position, orientation, result) {
const direction2 = Cartesian3_default.clone(
orientation.direction,
scratchToHPRDirection
);
const up = Cartesian3_default.clone(orientation.up, scratchToHPRUp);
if (camera._scene.mode === SceneMode_default.SCENE3D) {
const ellipsoid = camera._projection.ellipsoid;
const transform3 = Transforms_default.eastNorthUpToFixedFrame(
position,
ellipsoid,
scratchHPRMatrix1
);
const invTransform = Matrix4_default.inverseTransformation(
transform3,
scratchHPRMatrix2
);
Matrix4_default.multiplyByPointAsVector(invTransform, direction2, direction2);
Matrix4_default.multiplyByPointAsVector(invTransform, up, up);
}
const right = Cartesian3_default.cross(direction2, up, scratchToHPRRight);
result.heading = getHeading(direction2, up);
result.pitch = getPitch(direction2);
result.roll = getRoll(direction2, up, right);
return result;
}
var scratchSetViewOptions = {
destination: void 0,
orientation: {
direction: void 0,
up: void 0,
heading: void 0,
pitch: void 0,
roll: void 0
},
convert: void 0,
endTransform: void 0
};
var scratchHpr2 = new HeadingPitchRoll_default();
Camera.prototype.setView = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
let orientation = options.orientation ?? Frozen_default.EMPTY_OBJECT;
const mode2 = this._mode;
if (mode2 === SceneMode_default.MORPHING) {
return;
}
if (defined_default(options.endTransform)) {
this._setTransform(options.endTransform);
}
let convert = options.convert ?? true;
let destination = options.destination ?? Cartesian3_default.clone(this.positionWC, scratchSetViewCartesian);
if (defined_default(destination) && defined_default(destination.west)) {
destination = this.getRectangleCameraCoordinates(
destination,
scratchSetViewCartesian
);
if (isNaN(destination.x) || isNaN(destination.y)) {
throw new DeveloperError_default(`destination has a NaN component`);
}
convert = false;
}
if (defined_default(orientation.direction)) {
orientation = directionUpToHeadingPitchRoll(
this,
destination,
orientation,
scratchSetViewOptions.orientation
);
}
scratchHpr2.heading = orientation.heading ?? 0;
scratchHpr2.pitch = orientation.pitch ?? -Math_default.PI_OVER_TWO;
scratchHpr2.roll = orientation.roll ?? 0;
if (mode2 === SceneMode_default.SCENE3D) {
setView3D(this, destination, scratchHpr2);
} else if (mode2 === SceneMode_default.SCENE2D) {
setView2D(this, destination, scratchHpr2, convert);
} else {
setViewCV(this, destination, scratchHpr2, convert);
}
};
var pitchScratch = new Cartesian3_default();
Camera.prototype.flyHome = function(duration) {
const mode2 = this._mode;
if (mode2 === SceneMode_default.MORPHING) {
this._scene.completeMorph();
}
if (mode2 === SceneMode_default.SCENE2D) {
this.flyTo({
destination: Camera.DEFAULT_VIEW_RECTANGLE,
duration,
endTransform: Matrix4_default.IDENTITY
});
} else if (mode2 === SceneMode_default.SCENE3D) {
const destination = this.getRectangleCameraCoordinates(
Camera.DEFAULT_VIEW_RECTANGLE
);
let mag = Cartesian3_default.magnitude(destination);
mag += mag * Camera.DEFAULT_VIEW_FACTOR;
Cartesian3_default.normalize(destination, destination);
Cartesian3_default.multiplyByScalar(destination, mag, destination);
this.flyTo({
destination,
duration,
endTransform: Matrix4_default.IDENTITY
});
} else if (mode2 === SceneMode_default.COLUMBUS_VIEW) {
const maxRadii = this._projection.ellipsoid.maximumRadius;
let position = new Cartesian3_default(0, -1, 1);
position = Cartesian3_default.multiplyByScalar(
Cartesian3_default.normalize(position, position),
5 * maxRadii,
position
);
this.flyTo({
destination: position,
duration,
orientation: {
heading: 0,
pitch: -Math.acos(Cartesian3_default.normalize(position, pitchScratch).z),
roll: 0
},
endTransform: Matrix4_default.IDENTITY,
convert: false
});
}
};
Camera.prototype.worldToCameraCoordinates = function(cartesian11, result) {
if (!defined_default(cartesian11)) {
throw new DeveloperError_default("cartesian is required.");
}
if (!defined_default(result)) {
result = new Cartesian4_default();
}
updateMembers(this);
return Matrix4_default.multiplyByVector(this._actualInvTransform, cartesian11, result);
};
Camera.prototype.worldToCameraCoordinatesPoint = function(cartesian11, result) {
if (!defined_default(cartesian11)) {
throw new DeveloperError_default("cartesian is required.");
}
if (!defined_default(result)) {
result = new Cartesian3_default();
}
updateMembers(this);
return Matrix4_default.multiplyByPoint(this._actualInvTransform, cartesian11, result);
};
Camera.prototype.worldToCameraCoordinatesVector = function(cartesian11, result) {
if (!defined_default(cartesian11)) {
throw new DeveloperError_default("cartesian is required.");
}
if (!defined_default(result)) {
result = new Cartesian3_default();
}
updateMembers(this);
return Matrix4_default.multiplyByPointAsVector(
this._actualInvTransform,
cartesian11,
result
);
};
Camera.prototype.cameraToWorldCoordinates = function(cartesian11, result) {
if (!defined_default(cartesian11)) {
throw new DeveloperError_default("cartesian is required.");
}
if (!defined_default(result)) {
result = new Cartesian4_default();
}
updateMembers(this);
return Matrix4_default.multiplyByVector(this._actualTransform, cartesian11, result);
};
Camera.prototype.cameraToWorldCoordinatesPoint = function(cartesian11, result) {
if (!defined_default(cartesian11)) {
throw new DeveloperError_default("cartesian is required.");
}
if (!defined_default(result)) {
result = new Cartesian3_default();
}
updateMembers(this);
return Matrix4_default.multiplyByPoint(this._actualTransform, cartesian11, result);
};
Camera.prototype.cameraToWorldCoordinatesVector = function(cartesian11, result) {
if (!defined_default(cartesian11)) {
throw new DeveloperError_default("cartesian is required.");
}
if (!defined_default(result)) {
result = new Cartesian3_default();
}
updateMembers(this);
return Matrix4_default.multiplyByPointAsVector(
this._actualTransform,
cartesian11,
result
);
};
function clampMove2D(camera, position) {
const rotatable2D = camera._scene.mapMode2D === MapMode2D_default.ROTATE;
const maxProjectedX = camera._maxCoord.x;
const maxProjectedY = camera._maxCoord.y;
let minX;
let maxX;
if (rotatable2D) {
maxX = maxProjectedX;
minX = -maxX;
} else {
maxX = position.x - maxProjectedX * 2;
minX = position.x + maxProjectedX * 2;
}
if (position.x > maxProjectedX) {
position.x = maxX;
}
if (position.x < -maxProjectedX) {
position.x = minX;
}
if (position.y > maxProjectedY) {
position.y = maxProjectedY;
}
if (position.y < -maxProjectedY) {
position.y = -maxProjectedY;
}
}
var moveScratch = new Cartesian3_default();
Camera.prototype.move = function(direction2, amount) {
if (!defined_default(direction2)) {
throw new DeveloperError_default("direction is required.");
}
const cameraPosition = this.position;
Cartesian3_default.multiplyByScalar(direction2, amount, moveScratch);
Cartesian3_default.add(cameraPosition, moveScratch, cameraPosition);
if (this._mode === SceneMode_default.SCENE2D) {
clampMove2D(this, cameraPosition);
}
this._adjustOrthographicFrustum(true);
};
Camera.prototype.moveForward = function(amount) {
amount = amount ?? this.defaultMoveAmount;
if (this._mode === SceneMode_default.SCENE2D) {
zoom2D(this, amount);
} else {
this.move(this.direction, amount);
}
};
Camera.prototype.moveBackward = function(amount) {
amount = amount ?? this.defaultMoveAmount;
if (this._mode === SceneMode_default.SCENE2D) {
zoom2D(this, -amount);
} else {
this.move(this.direction, -amount);
}
};
Camera.prototype.moveUp = function(amount) {
amount = amount ?? this.defaultMoveAmount;
this.move(this.up, amount);
};
Camera.prototype.moveDown = function(amount) {
amount = amount ?? this.defaultMoveAmount;
this.move(this.up, -amount);
};
Camera.prototype.moveRight = function(amount) {
amount = amount ?? this.defaultMoveAmount;
this.move(this.right, amount);
};
Camera.prototype.moveLeft = function(amount) {
amount = amount ?? this.defaultMoveAmount;
this.move(this.right, -amount);
};
Camera.prototype.lookLeft = function(amount) {
amount = amount ?? this.defaultLookAmount;
if (this._mode !== SceneMode_default.SCENE2D) {
this.look(this.up, -amount);
}
};
Camera.prototype.lookRight = function(amount) {
amount = amount ?? this.defaultLookAmount;
if (this._mode !== SceneMode_default.SCENE2D) {
this.look(this.up, amount);
}
};
Camera.prototype.lookUp = function(amount) {
amount = amount ?? this.defaultLookAmount;
if (this._mode !== SceneMode_default.SCENE2D) {
this.look(this.right, -amount);
}
};
Camera.prototype.lookDown = function(amount) {
amount = amount ?? this.defaultLookAmount;
if (this._mode !== SceneMode_default.SCENE2D) {
this.look(this.right, amount);
}
};
var lookScratchQuaternion = new Quaternion_default();
var lookScratchMatrix = new Matrix3_default();
Camera.prototype.look = function(axis, angle) {
if (!defined_default(axis)) {
throw new DeveloperError_default("axis is required.");
}
const turnAngle = angle ?? this.defaultLookAmount;
const quaternion = Quaternion_default.fromAxisAngle(
axis,
-turnAngle,
lookScratchQuaternion
);
const rotation = Matrix3_default.fromQuaternion(quaternion, lookScratchMatrix);
const direction2 = this.direction;
const up = this.up;
const right = this.right;
Matrix3_default.multiplyByVector(rotation, direction2, direction2);
Matrix3_default.multiplyByVector(rotation, up, up);
Matrix3_default.multiplyByVector(rotation, right, right);
};
Camera.prototype.twistLeft = function(amount) {
amount = amount ?? this.defaultLookAmount;
this.look(this.direction, amount);
};
Camera.prototype.twistRight = function(amount) {
amount = amount ?? this.defaultLookAmount;
this.look(this.direction, -amount);
};
var rotateScratchQuaternion = new Quaternion_default();
var rotateScratchMatrix = new Matrix3_default();
Camera.prototype.rotate = function(axis, angle) {
if (!defined_default(axis)) {
throw new DeveloperError_default("axis is required.");
}
const turnAngle = angle ?? this.defaultRotateAmount;
const quaternion = Quaternion_default.fromAxisAngle(
axis,
-turnAngle,
rotateScratchQuaternion
);
const rotation = Matrix3_default.fromQuaternion(quaternion, rotateScratchMatrix);
Matrix3_default.multiplyByVector(rotation, this.position, this.position);
Matrix3_default.multiplyByVector(rotation, this.direction, this.direction);
Matrix3_default.multiplyByVector(rotation, this.up, this.up);
Cartesian3_default.cross(this.direction, this.up, this.right);
Cartesian3_default.cross(this.right, this.direction, this.up);
this._adjustOrthographicFrustum(false);
};
Camera.prototype.rotateDown = function(angle) {
angle = angle ?? this.defaultRotateAmount;
rotateVertical(this, angle);
};
Camera.prototype.rotateUp = function(angle) {
angle = angle ?? this.defaultRotateAmount;
rotateVertical(this, -angle);
};
var rotateVertScratchP = new Cartesian3_default();
var rotateVertScratchA = new Cartesian3_default();
var rotateVertScratchTan = new Cartesian3_default();
var rotateVertScratchNegate = new Cartesian3_default();
function rotateVertical(camera, angle) {
const position = camera.position;
if (defined_default(camera.constrainedAxis) && !Cartesian3_default.equalsEpsilon(
camera.position,
Cartesian3_default.ZERO,
Math_default.EPSILON2
)) {
const p = Cartesian3_default.normalize(position, rotateVertScratchP);
const northParallel = Cartesian3_default.equalsEpsilon(
p,
camera.constrainedAxis,
Math_default.EPSILON2
);
const southParallel = Cartesian3_default.equalsEpsilon(
p,
Cartesian3_default.negate(camera.constrainedAxis, rotateVertScratchNegate),
Math_default.EPSILON2
);
if (!northParallel && !southParallel) {
const constrainedAxis = Cartesian3_default.normalize(
camera.constrainedAxis,
rotateVertScratchA
);
let dot2 = Cartesian3_default.dot(p, constrainedAxis);
let angleToAxis = Math_default.acosClamped(dot2);
if (angle > 0 && angle > angleToAxis) {
angle = angleToAxis - Math_default.EPSILON4;
}
dot2 = Cartesian3_default.dot(
p,
Cartesian3_default.negate(constrainedAxis, rotateVertScratchNegate)
);
angleToAxis = Math_default.acosClamped(dot2);
if (angle < 0 && -angle > angleToAxis) {
angle = -angleToAxis + Math_default.EPSILON4;
}
const tangent = Cartesian3_default.cross(
constrainedAxis,
p,
rotateVertScratchTan
);
camera.rotate(tangent, angle);
} else if (northParallel && angle < 0 || southParallel && angle > 0) {
camera.rotate(camera.right, angle);
}
} else {
camera.rotate(camera.right, angle);
}
}
Camera.prototype.rotateRight = function(angle) {
angle = angle ?? this.defaultRotateAmount;
rotateHorizontal(this, -angle);
};
Camera.prototype.rotateLeft = function(angle) {
angle = angle ?? this.defaultRotateAmount;
rotateHorizontal(this, angle);
};
function rotateHorizontal(camera, angle) {
if (defined_default(camera.constrainedAxis)) {
camera.rotate(camera.constrainedAxis, angle);
} else {
camera.rotate(camera.up, angle);
}
}
function zoom2D(camera, amount) {
const frustum = camera.frustum;
if (!(frustum instanceof OrthographicOffCenterFrustum_default) || !defined_default(frustum.left) || !defined_default(frustum.right) || !defined_default(frustum.bottom) || !defined_default(frustum.top)) {
throw new DeveloperError_default(
"The camera frustum is expected to be orthographic for 2D camera control."
);
}
let ratio;
amount = amount * 0.5;
if (Math.abs(frustum.top) + Math.abs(frustum.bottom) > Math.abs(frustum.left) + Math.abs(frustum.right)) {
let newTop = frustum.top - amount;
let newBottom = frustum.bottom + amount;
let maxBottom = camera._maxCoord.y;
if (camera._scene.mapMode2D === MapMode2D_default.ROTATE) {
maxBottom *= camera.maximumZoomFactor;
}
if (newBottom > maxBottom) {
newBottom = maxBottom;
newTop = -maxBottom;
}
if (newTop <= newBottom) {
newTop = 1;
newBottom = -1;
}
ratio = frustum.right / frustum.top;
frustum.top = newTop;
frustum.bottom = newBottom;
frustum.right = frustum.top * ratio;
frustum.left = -frustum.right;
} else {
let newRight = frustum.right - amount;
let newLeft = frustum.left + amount;
let maxRight = camera._maxCoord.x;
if (camera._scene.mapMode2D === MapMode2D_default.ROTATE) {
maxRight *= camera.maximumZoomFactor;
}
if (newRight > maxRight) {
newRight = maxRight;
newLeft = -maxRight;
}
if (newRight <= newLeft) {
newRight = 1;
newLeft = -1;
}
ratio = frustum.top / frustum.right;
frustum.right = newRight;
frustum.left = newLeft;
frustum.top = frustum.right * ratio;
frustum.bottom = -frustum.top;
}
}
function zoom3D(camera, amount) {
camera.move(camera.direction, amount);
}
Camera.prototype.zoomIn = function(amount) {
amount = amount ?? this.defaultZoomAmount;
if (this._mode === SceneMode_default.SCENE2D) {
zoom2D(this, amount);
} else {
zoom3D(this, amount);
}
};
Camera.prototype.zoomOut = function(amount) {
amount = amount ?? this.defaultZoomAmount;
if (this._mode === SceneMode_default.SCENE2D) {
zoom2D(this, -amount);
} else {
zoom3D(this, -amount);
}
};
Camera.prototype.getMagnitude = function() {
if (this._mode === SceneMode_default.SCENE3D) {
return Cartesian3_default.magnitude(this.position);
} else if (this._mode === SceneMode_default.COLUMBUS_VIEW) {
return Math.abs(this.position.z);
} else if (this._mode === SceneMode_default.SCENE2D) {
return Math.max(
this.frustum.right - this.frustum.left,
this.frustum.top - this.frustum.bottom
);
}
};
var scratchLookAtMatrix4 = new Matrix4_default();
Camera.prototype.lookAt = function(target, offset) {
if (!defined_default(target)) {
throw new DeveloperError_default("target is required");
}
if (!defined_default(offset)) {
throw new DeveloperError_default("offset is required");
}
if (this._mode === SceneMode_default.MORPHING) {
throw new DeveloperError_default("lookAt is not supported while morphing.");
}
const scene = this._scene;
const ellipsoid = scene.ellipsoid ?? Ellipsoid_default.default;
const transform3 = Transforms_default.eastNorthUpToFixedFrame(
target,
ellipsoid,
scratchLookAtMatrix4
);
this.lookAtTransform(transform3, offset);
};
var scratchLookAtHeadingPitchRangeOffset = new Cartesian3_default();
var scratchLookAtHeadingPitchRangeQuaternion1 = new Quaternion_default();
var scratchLookAtHeadingPitchRangeQuaternion2 = new Quaternion_default();
var scratchHeadingPitchRangeMatrix3 = new Matrix3_default();
function offsetFromHeadingPitchRange(heading, pitch, range) {
pitch = Math_default.clamp(
pitch,
-Math_default.PI_OVER_TWO,
Math_default.PI_OVER_TWO
);
heading = Math_default.zeroToTwoPi(heading) - Math_default.PI_OVER_TWO;
const pitchQuat = Quaternion_default.fromAxisAngle(
Cartesian3_default.UNIT_Y,
-pitch,
scratchLookAtHeadingPitchRangeQuaternion1
);
const headingQuat = Quaternion_default.fromAxisAngle(
Cartesian3_default.UNIT_Z,
-heading,
scratchLookAtHeadingPitchRangeQuaternion2
);
const rotQuat = Quaternion_default.multiply(headingQuat, pitchQuat, headingQuat);
const rotMatrix3 = Matrix3_default.fromQuaternion(
rotQuat,
scratchHeadingPitchRangeMatrix3
);
const offset = Cartesian3_default.clone(
Cartesian3_default.UNIT_X,
scratchLookAtHeadingPitchRangeOffset
);
Matrix3_default.multiplyByVector(rotMatrix3, offset, offset);
Cartesian3_default.negate(offset, offset);
Cartesian3_default.multiplyByScalar(offset, range, offset);
return offset;
}
Camera.prototype.lookAtTransform = function(transform3, offset) {
if (!defined_default(transform3)) {
throw new DeveloperError_default("transform is required");
}
if (this._mode === SceneMode_default.MORPHING) {
throw new DeveloperError_default(
"lookAtTransform is not supported while morphing."
);
}
this._setTransform(transform3);
if (!defined_default(offset)) {
return;
}
let cartesianOffset;
if (defined_default(offset.heading)) {
cartesianOffset = offsetFromHeadingPitchRange(
offset.heading,
offset.pitch,
offset.range
);
} else {
cartesianOffset = offset;
}
if (this._mode === SceneMode_default.SCENE2D) {
Cartesian2_default.clone(Cartesian2_default.ZERO, this.position);
Cartesian3_default.negate(cartesianOffset, this.up);
this.up.z = 0;
if (Cartesian3_default.magnitudeSquared(this.up) < Math_default.EPSILON10) {
Cartesian3_default.clone(Cartesian3_default.UNIT_Y, this.up);
}
Cartesian3_default.normalize(this.up, this.up);
this._setTransform(Matrix4_default.IDENTITY);
Cartesian3_default.negate(Cartesian3_default.UNIT_Z, this.direction);
Cartesian3_default.cross(this.direction, this.up, this.right);
Cartesian3_default.normalize(this.right, this.right);
const frustum = this.frustum;
const ratio = frustum.top / frustum.right;
frustum.right = Cartesian3_default.magnitude(cartesianOffset) * 0.5;
frustum.left = -frustum.right;
frustum.top = ratio * frustum.right;
frustum.bottom = -frustum.top;
this._setTransform(transform3);
return;
}
Cartesian3_default.clone(cartesianOffset, this.position);
Cartesian3_default.negate(this.position, this.direction);
Cartesian3_default.normalize(this.direction, this.direction);
Cartesian3_default.cross(this.direction, Cartesian3_default.UNIT_Z, this.right);
if (Cartesian3_default.magnitudeSquared(this.right) < Math_default.EPSILON10) {
Cartesian3_default.clone(Cartesian3_default.UNIT_X, this.right);
}
Cartesian3_default.normalize(this.right, this.right);
Cartesian3_default.cross(this.right, this.direction, this.up);
Cartesian3_default.normalize(this.up, this.up);
this._adjustOrthographicFrustum(true);
};
var viewRectangle3DCartographic1 = new Cartographic_default();
var viewRectangle3DCartographic2 = new Cartographic_default();
var viewRectangle3DNorthEast = new Cartesian3_default();
var viewRectangle3DSouthWest = new Cartesian3_default();
var viewRectangle3DNorthWest = new Cartesian3_default();
var viewRectangle3DSouthEast = new Cartesian3_default();
var viewRectangle3DNorthCenter = new Cartesian3_default();
var viewRectangle3DSouthCenter = new Cartesian3_default();
var viewRectangle3DCenter = new Cartesian3_default();
var viewRectangle3DEquator = new Cartesian3_default();
var defaultRF = {
direction: new Cartesian3_default(),
right: new Cartesian3_default(),
up: new Cartesian3_default()
};
var viewRectangle3DEllipsoidGeodesic;
function computeD(direction2, upOrRight, corner, tanThetaOrPhi) {
const opposite = Math.abs(Cartesian3_default.dot(upOrRight, corner));
return opposite / tanThetaOrPhi - Cartesian3_default.dot(direction2, corner);
}
function rectangleCameraPosition3D(camera, rectangle, result, updateCamera) {
const ellipsoid = camera._projection.ellipsoid;
const cameraRF = updateCamera ? camera : defaultRF;
const { north, south, west } = rectangle;
let { east } = rectangle;
if (west > east) {
east += Math_default.TWO_PI;
}
const longitude = (west + east) * 0.5;
let latitude;
if (south < -Math_default.PI_OVER_TWO + Math_default.RADIANS_PER_DEGREE && north > Math_default.PI_OVER_TWO - Math_default.RADIANS_PER_DEGREE) {
latitude = 0;
} else {
const northCartographic = viewRectangle3DCartographic1;
northCartographic.longitude = longitude;
northCartographic.latitude = north;
northCartographic.height = 0;
const southCartographic = viewRectangle3DCartographic2;
southCartographic.longitude = longitude;
southCartographic.latitude = south;
southCartographic.height = 0;
let ellipsoidGeodesic2 = viewRectangle3DEllipsoidGeodesic;
if (!defined_default(ellipsoidGeodesic2) || ellipsoidGeodesic2.ellipsoid !== ellipsoid) {
viewRectangle3DEllipsoidGeodesic = ellipsoidGeodesic2 = new EllipsoidGeodesic_default(void 0, void 0, ellipsoid);
}
ellipsoidGeodesic2.setEndPoints(northCartographic, southCartographic);
latitude = ellipsoidGeodesic2.interpolateUsingFraction(
0.5,
viewRectangle3DCartographic1
).latitude;
}
const centerCartographic = viewRectangle3DCartographic1;
centerCartographic.longitude = longitude;
centerCartographic.latitude = latitude;
centerCartographic.height = 0;
const center = ellipsoid.cartographicToCartesian(
centerCartographic,
viewRectangle3DCenter
);
const cart = viewRectangle3DCartographic1;
cart.longitude = east;
cart.latitude = north;
const northEast = ellipsoid.cartographicToCartesian(
cart,
viewRectangle3DNorthEast
);
cart.longitude = west;
const northWest = ellipsoid.cartographicToCartesian(
cart,
viewRectangle3DNorthWest
);
cart.longitude = longitude;
const northCenter = ellipsoid.cartographicToCartesian(
cart,
viewRectangle3DNorthCenter
);
cart.latitude = south;
const southCenter = ellipsoid.cartographicToCartesian(
cart,
viewRectangle3DSouthCenter
);
cart.longitude = east;
const southEast = ellipsoid.cartographicToCartesian(
cart,
viewRectangle3DSouthEast
);
cart.longitude = west;
const southWest = ellipsoid.cartographicToCartesian(
cart,
viewRectangle3DSouthWest
);
Cartesian3_default.subtract(northWest, center, northWest);
Cartesian3_default.subtract(southEast, center, southEast);
Cartesian3_default.subtract(northEast, center, northEast);
Cartesian3_default.subtract(southWest, center, southWest);
Cartesian3_default.subtract(northCenter, center, northCenter);
Cartesian3_default.subtract(southCenter, center, southCenter);
const direction2 = ellipsoid.geodeticSurfaceNormal(center, cameraRF.direction);
Cartesian3_default.negate(direction2, direction2);
const right = Cartesian3_default.cross(direction2, Cartesian3_default.UNIT_Z, cameraRF.right);
Cartesian3_default.normalize(right, right);
const up = Cartesian3_default.cross(right, direction2, cameraRF.up);
let d;
if (camera.frustum instanceof OrthographicFrustum_default) {
const width = Math.max(
Cartesian3_default.distance(northEast, northWest),
Cartesian3_default.distance(southEast, southWest)
);
const height = Math.max(
Cartesian3_default.distance(northEast, southEast),
Cartesian3_default.distance(northWest, southWest)
);
let rightScalar;
let topScalar;
const offCenterFrustum = camera.frustum._offCenterFrustum;
const ratio = offCenterFrustum.right / offCenterFrustum.top;
const heightRatio = height * ratio;
if (width > heightRatio) {
rightScalar = width;
topScalar = rightScalar / ratio;
} else {
topScalar = height;
rightScalar = heightRatio;
}
d = Math.max(rightScalar, topScalar);
} else {
const tanPhi = Math.tan(camera.frustum.fovy * 0.5);
const tanTheta = camera.frustum.aspectRatio * tanPhi;
d = Math.max(
computeD(direction2, up, northWest, tanPhi),
computeD(direction2, up, southEast, tanPhi),
computeD(direction2, up, northEast, tanPhi),
computeD(direction2, up, southWest, tanPhi),
computeD(direction2, up, northCenter, tanPhi),
computeD(direction2, up, southCenter, tanPhi),
computeD(direction2, right, northWest, tanTheta),
computeD(direction2, right, southEast, tanTheta),
computeD(direction2, right, northEast, tanTheta),
computeD(direction2, right, southWest, tanTheta),
computeD(direction2, right, northCenter, tanTheta),
computeD(direction2, right, southCenter, tanTheta)
);
if (south < 0 && north > 0) {
const equatorCartographic = viewRectangle3DCartographic1;
equatorCartographic.longitude = west;
equatorCartographic.latitude = 0;
equatorCartographic.height = 0;
let equatorPosition = ellipsoid.cartographicToCartesian(
equatorCartographic,
viewRectangle3DEquator
);
Cartesian3_default.subtract(equatorPosition, center, equatorPosition);
d = Math.max(
d,
computeD(direction2, up, equatorPosition, tanPhi),
computeD(direction2, right, equatorPosition, tanTheta)
);
equatorCartographic.longitude = east;
equatorPosition = ellipsoid.cartographicToCartesian(
equatorCartographic,
viewRectangle3DEquator
);
Cartesian3_default.subtract(equatorPosition, center, equatorPosition);
d = Math.max(
d,
computeD(direction2, up, equatorPosition, tanPhi),
computeD(direction2, right, equatorPosition, tanTheta)
);
}
}
return Cartesian3_default.add(
center,
Cartesian3_default.multiplyByScalar(direction2, -d, viewRectangle3DEquator),
result
);
}
var viewRectangleCVCartographic = new Cartographic_default();
var viewRectangleCVNorthEast = new Cartesian3_default();
var viewRectangleCVSouthWest = new Cartesian3_default();
function rectangleCameraPositionColumbusView(camera, rectangle, result) {
const projection = camera._projection;
if (rectangle.west > rectangle.east) {
rectangle = Rectangle_default.MAX_VALUE;
}
const transform3 = camera._actualTransform;
const invTransform = camera._actualInvTransform;
const cart = viewRectangleCVCartographic;
cart.longitude = rectangle.east;
cart.latitude = rectangle.north;
const northEast = projection.project(cart, viewRectangleCVNorthEast);
Matrix4_default.multiplyByPoint(transform3, northEast, northEast);
Matrix4_default.multiplyByPoint(invTransform, northEast, northEast);
cart.longitude = rectangle.west;
cart.latitude = rectangle.south;
const southWest = projection.project(cart, viewRectangleCVSouthWest);
Matrix4_default.multiplyByPoint(transform3, southWest, southWest);
Matrix4_default.multiplyByPoint(invTransform, southWest, southWest);
result.x = (northEast.x - southWest.x) * 0.5 + southWest.x;
result.y = (northEast.y - southWest.y) * 0.5 + southWest.y;
if (defined_default(camera.frustum.fovy)) {
const tanPhi = Math.tan(camera.frustum.fovy * 0.5);
const tanTheta = camera.frustum.aspectRatio * tanPhi;
result.z = Math.max(
(northEast.x - southWest.x) / tanTheta,
(northEast.y - southWest.y) / tanPhi
) * 0.5;
} else {
const width = northEast.x - southWest.x;
const height = northEast.y - southWest.y;
result.z = Math.max(width, height);
}
return result;
}
var viewRectangle2DCartographic = new Cartographic_default();
var viewRectangle2DNorthEast = new Cartesian3_default();
var viewRectangle2DSouthWest = new Cartesian3_default();
function rectangleCameraPosition2D(camera, rectangle, result) {
const projection = camera._projection;
let east = rectangle.east;
if (rectangle.west > rectangle.east) {
if (camera._scene.mapMode2D === MapMode2D_default.INFINITE_SCROLL) {
east += Math_default.TWO_PI;
} else {
rectangle = Rectangle_default.MAX_VALUE;
east = rectangle.east;
}
}
let cart = viewRectangle2DCartographic;
cart.longitude = east;
cart.latitude = rectangle.north;
const northEast = projection.project(cart, viewRectangle2DNorthEast);
cart.longitude = rectangle.west;
cart.latitude = rectangle.south;
const southWest = projection.project(cart, viewRectangle2DSouthWest);
const width = Math.abs(northEast.x - southWest.x) * 0.5;
let height = Math.abs(northEast.y - southWest.y) * 0.5;
let right, top;
const ratio = camera.frustum.right / camera.frustum.top;
const heightRatio = height * ratio;
if (width > heightRatio) {
right = width;
top = right / ratio;
} else {
top = height;
right = heightRatio;
}
height = Math.max(2 * right, 2 * top);
result.x = (northEast.x - southWest.x) * 0.5 + southWest.x;
result.y = (northEast.y - southWest.y) * 0.5 + southWest.y;
cart = projection.unproject(result, cart);
cart.height = height;
result = projection.project(cart, result);
return result;
}
Camera.prototype.getRectangleCameraCoordinates = function(rectangle, result) {
if (!defined_default(rectangle)) {
throw new DeveloperError_default("rectangle is required");
}
const mode2 = this._mode;
if (!defined_default(result)) {
result = new Cartesian3_default();
}
if (mode2 === SceneMode_default.SCENE3D) {
return rectangleCameraPosition3D(this, rectangle, result);
} else if (mode2 === SceneMode_default.COLUMBUS_VIEW) {
return rectangleCameraPositionColumbusView(this, rectangle, result);
} else if (mode2 === SceneMode_default.SCENE2D) {
return rectangleCameraPosition2D(this, rectangle, result);
}
return void 0;
};
var pickEllipsoid3DRay = new Ray_default();
function pickEllipsoid3D(camera, windowPosition, ellipsoid, result) {
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
const ray = camera.getPickRay(windowPosition, pickEllipsoid3DRay);
const intersection = IntersectionTests_default.rayEllipsoid(ray, ellipsoid);
if (!intersection) {
return void 0;
}
const t = intersection.start > 0 ? intersection.start : intersection.stop;
return Ray_default.getPoint(ray, t, result);
}
var pickEllipsoid2DRay = new Ray_default();
function pickMap2D(camera, windowPosition, projection, result) {
const ray = camera.getPickRay(windowPosition, pickEllipsoid2DRay);
let position = ray.origin;
position = Cartesian3_default.fromElements(position.y, position.z, 0, position);
const cart = projection.unproject(position);
if (cart.latitude < -Math_default.PI_OVER_TWO || cart.latitude > Math_default.PI_OVER_TWO) {
return void 0;
}
return projection.ellipsoid.cartographicToCartesian(cart, result);
}
var pickEllipsoidCVRay = new Ray_default();
function pickMapColumbusView(camera, windowPosition, projection, result) {
const ray = camera.getPickRay(windowPosition, pickEllipsoidCVRay);
const scalar = -ray.origin.x / ray.direction.x;
Ray_default.getPoint(ray, scalar, result);
const cart = projection.unproject(new Cartesian3_default(result.y, result.z, 0));
if (cart.latitude < -Math_default.PI_OVER_TWO || cart.latitude > Math_default.PI_OVER_TWO || cart.longitude < -Math.PI || cart.longitude > Math.PI) {
return void 0;
}
return projection.ellipsoid.cartographicToCartesian(cart, result);
}
Camera.prototype.pickEllipsoid = function(windowPosition, ellipsoid, result) {
if (!defined_default(windowPosition)) {
throw new DeveloperError_default("windowPosition is required.");
}
const canvas = this._scene.canvas;
if (canvas.clientWidth === 0 || canvas.clientHeight === 0) {
return void 0;
}
if (!defined_default(result)) {
result = new Cartesian3_default();
}
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
if (this._mode === SceneMode_default.SCENE3D) {
result = pickEllipsoid3D(this, windowPosition, ellipsoid, result);
} else if (this._mode === SceneMode_default.SCENE2D) {
result = pickMap2D(this, windowPosition, this._projection, result);
} else if (this._mode === SceneMode_default.COLUMBUS_VIEW) {
result = pickMapColumbusView(
this,
windowPosition,
this._projection,
result
);
} else {
return void 0;
}
return result;
};
var pickPerspCenter = new Cartesian3_default();
var pickPerspXDir = new Cartesian3_default();
var pickPerspYDir = new Cartesian3_default();
function getPickRayPerspective(camera, windowPosition, result) {
const canvas = camera._scene.canvas;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const tanPhi = Math.tan(camera.frustum.fovy * 0.5);
const tanTheta = camera.frustum.aspectRatio * tanPhi;
const near = camera.frustum.near;
const x = 2 / width * windowPosition.x - 1;
const y = 2 / height * (height - windowPosition.y) - 1;
const position = camera.positionWC;
Cartesian3_default.clone(position, result.origin);
const nearCenter = Cartesian3_default.multiplyByScalar(
camera.directionWC,
near,
pickPerspCenter
);
Cartesian3_default.add(position, nearCenter, nearCenter);
const xDir = Cartesian3_default.multiplyByScalar(
camera.rightWC,
x * near * tanTheta,
pickPerspXDir
);
const yDir = Cartesian3_default.multiplyByScalar(
camera.upWC,
y * near * tanPhi,
pickPerspYDir
);
const direction2 = Cartesian3_default.add(nearCenter, xDir, result.direction);
Cartesian3_default.add(direction2, yDir, direction2);
Cartesian3_default.subtract(direction2, position, direction2);
Cartesian3_default.normalize(direction2, direction2);
return result;
}
var scratchDirection2 = new Cartesian3_default();
function getPickRayOrthographic(camera, windowPosition, result) {
const canvas = camera._scene.canvas;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
let frustum = camera.frustum;
const offCenterFrustum = frustum.offCenterFrustum;
if (defined_default(offCenterFrustum)) {
frustum = offCenterFrustum;
}
let x = 2 / width * windowPosition.x - 1;
x *= (frustum.right - frustum.left) * 0.5;
let y = 2 / height * (height - windowPosition.y) - 1;
y *= (frustum.top - frustum.bottom) * 0.5;
const origin = result.origin;
Cartesian3_default.clone(camera.positionWC, origin);
Cartesian3_default.multiplyByScalar(camera.rightWC, x, scratchDirection2);
Cartesian3_default.add(scratchDirection2, origin, origin);
Cartesian3_default.multiplyByScalar(camera.upWC, y, scratchDirection2);
Cartesian3_default.add(scratchDirection2, origin, origin);
Cartesian3_default.clone(camera.directionWC, result.direction);
return result;
}
Camera.prototype.getPickRay = function(windowPosition, result) {
if (!defined_default(windowPosition)) {
throw new DeveloperError_default("windowPosition is required.");
}
if (!defined_default(result)) {
result = new Ray_default();
}
const canvas = this._scene.canvas;
if (canvas.clientWidth <= 0 || canvas.clientHeight <= 0) {
return void 0;
}
const frustum = this.frustum;
if (defined_default(frustum.aspectRatio) && defined_default(frustum.fov) && defined_default(frustum.near)) {
return getPickRayPerspective(this, windowPosition, result);
}
return getPickRayOrthographic(this, windowPosition, result);
};
var scratchToCenter2 = new Cartesian3_default();
var scratchProj = new Cartesian3_default();
Camera.prototype.distanceToBoundingSphere = function(boundingSphere) {
if (!defined_default(boundingSphere)) {
throw new DeveloperError_default("boundingSphere is required.");
}
const toCenter = Cartesian3_default.subtract(
this.positionWC,
boundingSphere.center,
scratchToCenter2
);
const proj2 = Cartesian3_default.multiplyByScalar(
this.directionWC,
Cartesian3_default.dot(toCenter, this.directionWC),
scratchProj
);
return Math.max(0, Cartesian3_default.magnitude(proj2) - boundingSphere.radius);
};
var scratchPixelSize = new Cartesian2_default();
Camera.prototype.getPixelSize = function(boundingSphere, drawingBufferWidth, drawingBufferHeight) {
if (!defined_default(boundingSphere)) {
throw new DeveloperError_default("boundingSphere is required.");
}
if (!defined_default(drawingBufferWidth)) {
throw new DeveloperError_default("drawingBufferWidth is required.");
}
if (!defined_default(drawingBufferHeight)) {
throw new DeveloperError_default("drawingBufferHeight is required.");
}
const distance2 = this.distanceToBoundingSphere(boundingSphere);
const pixelSize = this.frustum.getPixelDimensions(
drawingBufferWidth,
drawingBufferHeight,
distance2,
this._scene.pixelRatio,
scratchPixelSize
);
return Math.max(pixelSize.x, pixelSize.y);
};
function createAnimationTemplateCV(camera, position, center, maxX, maxY, duration) {
const newPosition = Cartesian3_default.clone(position);
if (center.y > maxX) {
newPosition.y -= center.y - maxX;
} else if (center.y < -maxX) {
newPosition.y += -maxX - center.y;
}
if (center.z > maxY) {
newPosition.z -= center.z - maxY;
} else if (center.z < -maxY) {
newPosition.z += -maxY - center.z;
}
function updateCV2(value) {
const interp = Cartesian3_default.lerp(
position,
newPosition,
value.time,
new Cartesian3_default()
);
camera.worldToCameraCoordinatesPoint(interp, camera.position);
}
return {
easingFunction: EasingFunction_default.EXPONENTIAL_OUT,
startObject: {
time: 0
},
stopObject: {
time: 1
},
duration,
update: updateCV2
};
}
var normalScratch6 = new Cartesian3_default();
var centerScratch6 = new Cartesian3_default();
var posScratch = new Cartesian3_default();
var scratchCartesian3Subtract = new Cartesian3_default();
function createAnimationCV(camera, duration) {
let position = camera.position;
const direction2 = camera.direction;
const normal2 = camera.worldToCameraCoordinatesVector(
Cartesian3_default.UNIT_X,
normalScratch6
);
const scalar = -Cartesian3_default.dot(normal2, position) / Cartesian3_default.dot(normal2, direction2);
const center = Cartesian3_default.add(
position,
Cartesian3_default.multiplyByScalar(direction2, scalar, centerScratch6),
centerScratch6
);
camera.cameraToWorldCoordinatesPoint(center, center);
position = camera.cameraToWorldCoordinatesPoint(camera.position, posScratch);
const tanPhi = Math.tan(camera.frustum.fovy * 0.5);
const tanTheta = camera.frustum.aspectRatio * tanPhi;
const distToC = Cartesian3_default.magnitude(
Cartesian3_default.subtract(position, center, scratchCartesian3Subtract)
);
const dWidth = tanTheta * distToC;
const dHeight = tanPhi * distToC;
const mapWidth = camera._maxCoord.x;
const mapHeight = camera._maxCoord.y;
const maxX = Math.max(dWidth - mapWidth, mapWidth);
const maxY = Math.max(dHeight - mapHeight, mapHeight);
if (position.z < -maxX || position.z > maxX || position.y < -maxY || position.y > maxY) {
const translateX = center.y < -maxX || center.y > maxX;
const translateY = center.z < -maxY || center.z > maxY;
if (translateX || translateY) {
return createAnimationTemplateCV(
camera,
position,
center,
maxX,
maxY,
duration
);
}
}
return void 0;
}
Camera.prototype.createCorrectPositionTween = function(duration) {
if (!defined_default(duration)) {
throw new DeveloperError_default("duration is required.");
}
if (this._mode === SceneMode_default.COLUMBUS_VIEW) {
return createAnimationCV(this, duration);
}
return void 0;
};
var scratchFlyToDestination = new Cartesian3_default();
var newOptions = {
destination: void 0,
heading: void 0,
pitch: void 0,
roll: void 0,
duration: void 0,
complete: void 0,
cancel: void 0,
endTransform: void 0,
maximumHeight: void 0,
easingFunction: void 0
};
Camera.prototype.cancelFlight = function() {
if (defined_default(this._currentFlight)) {
this._currentFlight.cancelTween();
this._currentFlight = void 0;
}
};
Camera.prototype.completeFlight = function() {
if (defined_default(this._currentFlight)) {
this._currentFlight.cancelTween();
const options = {
destination: void 0,
orientation: {
heading: void 0,
pitch: void 0,
roll: void 0
}
};
options.destination = newOptions.destination;
options.orientation.heading = newOptions.heading;
options.orientation.pitch = newOptions.pitch;
options.orientation.roll = newOptions.roll;
this.setView(options);
if (defined_default(this._currentFlight.complete)) {
this._currentFlight.complete();
}
this._currentFlight = void 0;
}
};
Camera.prototype.flyTo = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
let destination = options.destination;
if (!defined_default(destination)) {
throw new DeveloperError_default("destination is required.");
}
const mode2 = this._mode;
if (mode2 === SceneMode_default.MORPHING) {
return;
}
this.cancelFlight();
const isRectangle = destination instanceof Rectangle_default;
if (isRectangle) {
destination = this.getRectangleCameraCoordinates(
destination,
scratchFlyToDestination
);
}
let orientation = options.orientation ?? Frozen_default.EMPTY_OBJECT;
if (defined_default(orientation.direction)) {
orientation = directionUpToHeadingPitchRoll(
this,
destination,
orientation,
scratchSetViewOptions.orientation
);
}
if (defined_default(options.duration) && options.duration <= 0) {
const setViewOptions = scratchSetViewOptions;
setViewOptions.destination = options.destination;
setViewOptions.orientation.heading = orientation.heading;
setViewOptions.orientation.pitch = orientation.pitch;
setViewOptions.orientation.roll = orientation.roll;
setViewOptions.convert = options.convert;
setViewOptions.endTransform = options.endTransform;
this.setView(setViewOptions);
if (typeof options.complete === "function") {
options.complete();
}
return;
}
const that = this;
let flightTween;
newOptions.destination = destination;
newOptions.heading = orientation.heading;
newOptions.pitch = orientation.pitch;
newOptions.roll = orientation.roll;
newOptions.duration = options.duration;
newOptions.complete = function() {
if (flightTween === that._currentFlight) {
that._currentFlight = void 0;
}
if (defined_default(options.complete)) {
options.complete();
}
};
newOptions.cancel = options.cancel;
newOptions.endTransform = options.endTransform;
newOptions.convert = isRectangle ? false : options.convert;
newOptions.maximumHeight = options.maximumHeight;
newOptions.pitchAdjustHeight = options.pitchAdjustHeight;
newOptions.flyOverLongitude = options.flyOverLongitude;
newOptions.flyOverLongitudeWeight = options.flyOverLongitudeWeight;
newOptions.easingFunction = options.easingFunction;
const scene = this._scene;
const tweenOptions = CameraFlightPath_default.createTween(scene, newOptions);
if (tweenOptions.duration === 0) {
if (typeof tweenOptions.complete === "function") {
tweenOptions.complete();
}
return;
}
flightTween = scene.tweens.add(tweenOptions);
this._currentFlight = flightTween;
let preloadFlightCamera = this._scene.preloadFlightCamera;
if (this._mode !== SceneMode_default.SCENE2D) {
if (!defined_default(preloadFlightCamera)) {
preloadFlightCamera = Camera.clone(this);
}
preloadFlightCamera.setView({
destination,
orientation
});
this._scene.preloadFlightCullingVolume = preloadFlightCamera.frustum.computeCullingVolume(
preloadFlightCamera.positionWC,
preloadFlightCamera.directionWC,
preloadFlightCamera.upWC
);
}
};
function distanceToBoundingSphere3D(camera, radius) {
const frustum = camera.frustum;
const tanPhi = Math.tan(frustum.fovy * 0.5);
const tanTheta = frustum.aspectRatio * tanPhi;
return Math.max(radius / tanTheta, radius / tanPhi);
}
function distanceToBoundingSphere2D(camera, radius) {
let frustum = camera.frustum;
const offCenterFrustum = frustum.offCenterFrustum;
if (defined_default(offCenterFrustum)) {
frustum = offCenterFrustum;
}
let right, top;
const ratio = frustum.right / frustum.top;
const heightRatio = radius * ratio;
if (radius > heightRatio) {
right = radius;
top = right / ratio;
} else {
top = radius;
right = heightRatio;
}
return Math.max(right, top) * 1.5;
}
var MINIMUM_ZOOM = 100;
function adjustBoundingSphereOffset(camera, boundingSphere, offset) {
offset = HeadingPitchRange_default.clone(
defined_default(offset) ? offset : Camera.DEFAULT_OFFSET
);
const minimumZoom = camera._scene.screenSpaceCameraController.minimumZoomDistance;
const maximumZoom = camera._scene.screenSpaceCameraController.maximumZoomDistance;
const range = offset.range;
if (!defined_default(range) || range === 0) {
const radius = boundingSphere.radius;
if (radius === 0) {
offset.range = MINIMUM_ZOOM;
} else if (camera.frustum instanceof OrthographicFrustum_default || camera._mode === SceneMode_default.SCENE2D) {
offset.range = distanceToBoundingSphere2D(camera, radius);
} else {
offset.range = distanceToBoundingSphere3D(camera, radius);
}
offset.range = Math_default.clamp(offset.range, minimumZoom, maximumZoom);
}
return offset;
}
Camera.prototype.viewBoundingSphere = function(boundingSphere, offset) {
if (!defined_default(boundingSphere)) {
throw new DeveloperError_default("boundingSphere is required.");
}
if (this._mode === SceneMode_default.MORPHING) {
throw new DeveloperError_default(
"viewBoundingSphere is not supported while morphing."
);
}
offset = adjustBoundingSphereOffset(this, boundingSphere, offset);
this.lookAt(boundingSphere.center, offset);
};
var scratchflyToBoundingSphereTransform = new Matrix4_default();
var scratchflyToBoundingSphereDestination = new Cartesian3_default();
var scratchflyToBoundingSphereDirection = new Cartesian3_default();
var scratchflyToBoundingSphereUp = new Cartesian3_default();
var scratchflyToBoundingSphereRight = new Cartesian3_default();
var scratchFlyToBoundingSphereCart4 = new Cartesian4_default();
var scratchFlyToBoundingSphereQuaternion = new Quaternion_default();
var scratchFlyToBoundingSphereMatrix3 = new Matrix3_default();
Camera.prototype.flyToBoundingSphere = function(boundingSphere, options) {
if (!defined_default(boundingSphere)) {
throw new DeveloperError_default("boundingSphere is required.");
}
options = options ?? Frozen_default.EMPTY_OBJECT;
const scene2D = this._mode === SceneMode_default.SCENE2D || this._mode === SceneMode_default.COLUMBUS_VIEW;
this._setTransform(Matrix4_default.IDENTITY);
const offset = adjustBoundingSphereOffset(
this,
boundingSphere,
options.offset
);
let position;
if (scene2D) {
position = Cartesian3_default.multiplyByScalar(
Cartesian3_default.UNIT_Z,
offset.range,
scratchflyToBoundingSphereDestination
);
} else {
position = offsetFromHeadingPitchRange(
offset.heading,
offset.pitch,
offset.range
);
}
const scene = this._scene;
const ellipsoid = scene.ellipsoid ?? Ellipsoid_default.default;
const transform3 = Transforms_default.eastNorthUpToFixedFrame(
boundingSphere.center,
ellipsoid,
scratchflyToBoundingSphereTransform
);
Matrix4_default.multiplyByPoint(transform3, position, position);
let direction2;
let up;
if (!scene2D) {
direction2 = Cartesian3_default.subtract(
boundingSphere.center,
position,
scratchflyToBoundingSphereDirection
);
Cartesian3_default.normalize(direction2, direction2);
up = Matrix4_default.multiplyByPointAsVector(
transform3,
Cartesian3_default.UNIT_Z,
scratchflyToBoundingSphereUp
);
if (1 - Math.abs(Cartesian3_default.dot(direction2, up)) < Math_default.EPSILON6) {
const rotateQuat = Quaternion_default.fromAxisAngle(
direction2,
offset.heading,
scratchFlyToBoundingSphereQuaternion
);
const rotation = Matrix3_default.fromQuaternion(
rotateQuat,
scratchFlyToBoundingSphereMatrix3
);
Cartesian3_default.fromCartesian4(
Matrix4_default.getColumn(transform3, 1, scratchFlyToBoundingSphereCart4),
up
);
Matrix3_default.multiplyByVector(rotation, up, up);
}
const right = Cartesian3_default.cross(
direction2,
up,
scratchflyToBoundingSphereRight
);
Cartesian3_default.cross(right, direction2, up);
Cartesian3_default.normalize(up, up);
}
this.flyTo({
destination: position,
orientation: {
direction: direction2,
up
},
duration: options.duration,
complete: options.complete,
cancel: options.cancel,
endTransform: options.endTransform,
maximumHeight: options.maximumHeight,
easingFunction: options.easingFunction,
flyOverLongitude: options.flyOverLongitude,
flyOverLongitudeWeight: options.flyOverLongitudeWeight,
pitchAdjustHeight: options.pitchAdjustHeight
});
};
var scratchCartesian3_1 = new Cartesian3_default();
var scratchCartesian3_2 = new Cartesian3_default();
var scratchCartesian3_3 = new Cartesian3_default();
var scratchCartesian3_4 = new Cartesian3_default();
var horizonPoints = [
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default(),
new Cartesian3_default()
];
function computeHorizonQuad(camera, ellipsoid) {
const radii = ellipsoid.radii;
const p = camera.positionWC;
const q = Cartesian3_default.multiplyComponents(
ellipsoid.oneOverRadii,
p,
scratchCartesian3_1
);
const qMagnitude = Cartesian3_default.magnitude(q);
const qUnit = Cartesian3_default.normalize(q, scratchCartesian3_2);
let eUnit;
let nUnit;
if (Cartesian3_default.equalsEpsilon(qUnit, Cartesian3_default.UNIT_Z, Math_default.EPSILON10)) {
eUnit = new Cartesian3_default(0, 1, 0);
nUnit = new Cartesian3_default(0, 0, 1);
} else {
eUnit = Cartesian3_default.normalize(
Cartesian3_default.cross(Cartesian3_default.UNIT_Z, qUnit, scratchCartesian3_3),
scratchCartesian3_3
);
nUnit = Cartesian3_default.normalize(
Cartesian3_default.cross(qUnit, eUnit, scratchCartesian3_4),
scratchCartesian3_4
);
}
const wMagnitude = Math.sqrt(Cartesian3_default.magnitudeSquared(q) - 1);
const center = Cartesian3_default.multiplyByScalar(
qUnit,
1 / qMagnitude,
scratchCartesian3_1
);
const scalar = wMagnitude / qMagnitude;
const eastOffset = Cartesian3_default.multiplyByScalar(
eUnit,
scalar,
scratchCartesian3_2
);
const northOffset = Cartesian3_default.multiplyByScalar(
nUnit,
scalar,
scratchCartesian3_3
);
const upperLeft = Cartesian3_default.add(center, northOffset, horizonPoints[0]);
Cartesian3_default.subtract(upperLeft, eastOffset, upperLeft);
Cartesian3_default.multiplyComponents(radii, upperLeft, upperLeft);
const lowerLeft = Cartesian3_default.subtract(center, northOffset, horizonPoints[1]);
Cartesian3_default.subtract(lowerLeft, eastOffset, lowerLeft);
Cartesian3_default.multiplyComponents(radii, lowerLeft, lowerLeft);
const lowerRight = Cartesian3_default.subtract(center, northOffset, horizonPoints[2]);
Cartesian3_default.add(lowerRight, eastOffset, lowerRight);
Cartesian3_default.multiplyComponents(radii, lowerRight, lowerRight);
const upperRight = Cartesian3_default.add(center, northOffset, horizonPoints[3]);
Cartesian3_default.add(upperRight, eastOffset, upperRight);
Cartesian3_default.multiplyComponents(radii, upperRight, upperRight);
return horizonPoints;
}
var scratchPickCartesian2 = new Cartesian2_default();
var scratchRectCartesian = new Cartesian3_default();
var cartoArray = [
new Cartographic_default(),
new Cartographic_default(),
new Cartographic_default(),
new Cartographic_default()
];
function addToResult(x, y, index, camera, ellipsoid, computedHorizonQuad) {
scratchPickCartesian2.x = x;
scratchPickCartesian2.y = y;
const r = camera.pickEllipsoid(
scratchPickCartesian2,
ellipsoid,
scratchRectCartesian
);
if (defined_default(r)) {
cartoArray[index] = ellipsoid.cartesianToCartographic(r, cartoArray[index]);
return 1;
}
cartoArray[index] = ellipsoid.cartesianToCartographic(
computedHorizonQuad[index],
cartoArray[index]
);
return 0;
}
Camera.prototype.computeViewRectangle = function(ellipsoid, result) {
ellipsoid = ellipsoid ?? Ellipsoid_default.default;
const cullingVolume = this.frustum.computeCullingVolume(
this.positionWC,
this.directionWC,
this.upWC
);
const boundingSphere = new BoundingSphere_default(
Cartesian3_default.ZERO,
ellipsoid.maximumRadius
);
const visibility = cullingVolume.computeVisibility(boundingSphere);
if (visibility === Intersect_default.OUTSIDE) {
return void 0;
}
const canvas = this._scene.canvas;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
let successfulPickCount = 0;
const computedHorizonQuad = computeHorizonQuad(this, ellipsoid);
successfulPickCount += addToResult(
0,
0,
0,
this,
ellipsoid,
computedHorizonQuad
);
successfulPickCount += addToResult(
0,
height,
1,
this,
ellipsoid,
computedHorizonQuad
);
successfulPickCount += addToResult(
width,
height,
2,
this,
ellipsoid,
computedHorizonQuad
);
successfulPickCount += addToResult(
width,
0,
3,
this,
ellipsoid,
computedHorizonQuad
);
if (successfulPickCount < 2) {
return Rectangle_default.MAX_VALUE;
}
result = Rectangle_default.fromCartographicArray(cartoArray, result);
let distance2 = 0;
let lastLon = cartoArray[3].longitude;
for (let i = 0; i < 4; ++i) {
const lon = cartoArray[i].longitude;
const diff = Math.abs(lon - lastLon);
if (diff > Math_default.PI) {
distance2 += Math_default.TWO_PI - diff;
} else {
distance2 += diff;
}
lastLon = lon;
}
if (Math_default.equalsEpsilon(
Math.abs(distance2),
Math_default.TWO_PI,
Math_default.EPSILON9
)) {
result.west = -Math_default.PI;
result.east = Math_default.PI;
if (cartoArray[0].latitude >= 0) {
result.north = Math_default.PI_OVER_TWO;
} else {
result.south = -Math_default.PI_OVER_TWO;
}
}
return result;
};
Camera.prototype.switchToPerspectiveFrustum = function() {
if (this._mode === SceneMode_default.SCENE2D || this.frustum instanceof PerspectiveFrustum_default) {
return;
}
const scene = this._scene;
this.frustum = new PerspectiveFrustum_default();
this.frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight;
this.frustum.fov = Math_default.toRadians(60);
};
Camera.prototype.switchToOrthographicFrustum = function() {
if (this._mode === SceneMode_default.SCENE2D || this.frustum instanceof OrthographicFrustum_default) {
return;
}
const frustumWidth = calculateOrthographicFrustumWidth(this);
const scene = this._scene;
this.frustum = new OrthographicFrustum_default();
this.frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight;
this.frustum.width = frustumWidth;
};
Camera.clone = function(camera, result) {
if (!defined_default(result)) {
result = new Camera(camera._scene);
}
Cartesian3_default.clone(camera.position, result.position);
Cartesian3_default.clone(camera.direction, result.direction);
Cartesian3_default.clone(camera.up, result.up);
Cartesian3_default.clone(camera.right, result.right);
Matrix4_default.clone(camera._transform, result.transform);
result._transformChanged = true;
result.frustum = camera.frustum.clone();
return result;
};
var Camera_default = Camera;
// packages/engine/Source/Scene/Cesium3DTilePassState.js
var import_InlineWorkers1047 = __toESM(require_InlineWorkers(), 1);
function Cesium3DTilePassState(options) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.number("options.pass", options.pass);
this.pass = options.pass;
this.commandList = options.commandList;
this.camera = options.camera;
this.cullingVolume = options.cullingVolume;
this.ready = false;
}
var Cesium3DTilePassState_default = Cesium3DTilePassState;
// packages/engine/Source/Scene/CreditDisplay.js
var import_InlineWorkers1048 = __toESM(require_InlineWorkers(), 1);
var import_urijs12 = __toESM(require_URI(), 1);
var mobileWidth = 576;
var lightboxHeight = 100;
var textColor = "#ffffff";
var highlightColor = "#48b";
function CreditDisplayElement(credit, count) {
this.credit = credit;
this.count = count ?? 1;
}
function contains2(credits, credit) {
const len = credits.length;
for (let i = 0; i < len; i++) {
const existingCredit = credits[i];
if (Credit_default.equals(existingCredit, credit)) {
return true;
}
}
return false;
}
function swapCesiumCredit(creditDisplay) {
const previousCredit = creditDisplay._previousCesiumCredit;
const currentCredit = creditDisplay._currentCesiumCredit;
if (Credit_default.equals(currentCredit, previousCredit)) {
return;
}
if (defined_default(previousCredit)) {
creditDisplay._cesiumCreditContainer.removeChild(previousCredit.element);
}
if (defined_default(currentCredit)) {
creditDisplay._cesiumCreditContainer.appendChild(currentCredit.element);
}
creditDisplay._previousCesiumCredit = currentCredit;
}
var delimiterClassName = "cesium-credit-delimiter";
function createDelimiterElement(delimiter) {
const delimiterElement = document.createElement("span");
delimiterElement.textContent = delimiter;
delimiterElement.className = delimiterClassName;
return delimiterElement;
}
function createCreditElement(element, elementWrapperTagName) {
if (defined_default(elementWrapperTagName)) {
const wrapper = document.createElement(elementWrapperTagName);
wrapper._creditId = element._creditId;
wrapper.appendChild(element);
element = wrapper;
}
return element;
}
function displayCredits(container, credits, delimiter, elementWrapperTagName) {
const childNodes = container.childNodes;
let domIndex = -1;
credits.sort(function(credit1, credit2) {
return credit2.count - credit1.count;
});
for (let creditIndex = 0; creditIndex < credits.length; ++creditIndex) {
const credit = credits[creditIndex].credit;
if (defined_default(credit)) {
domIndex = creditIndex;
if (defined_default(delimiter)) {
domIndex *= 2;
if (creditIndex > 0) {
const delimiterDomIndex = domIndex - 1;
if (childNodes.length <= delimiterDomIndex) {
container.appendChild(createDelimiterElement(delimiter));
} else {
const existingDelimiter = childNodes[delimiterDomIndex];
if (existingDelimiter.className !== delimiterClassName) {
container.replaceChild(
createDelimiterElement(delimiter),
existingDelimiter
);
}
}
}
}
const element = credit.element;
if (childNodes.length <= domIndex) {
container.appendChild(
createCreditElement(element, elementWrapperTagName)
);
} else {
const existingElement = childNodes[domIndex];
if (existingElement._creditId !== credit._id) {
container.replaceChild(
createCreditElement(element, elementWrapperTagName),
existingElement
);
}
}
}
}
++domIndex;
while (domIndex < childNodes.length) {
container.removeChild(childNodes[domIndex]);
}
}
function styleLightboxContainer(that) {
const lightboxCredits = that._lightboxCredits;
const width = that.viewport.clientWidth;
const height = that.viewport.clientHeight;
if (width !== that._lastViewportWidth) {
if (width < mobileWidth) {
lightboxCredits.className = "cesium-credit-lightbox cesium-credit-lightbox-mobile";
lightboxCredits.style.marginTop = "0";
} else {
lightboxCredits.className = "cesium-credit-lightbox cesium-credit-lightbox-expanded";
lightboxCredits.style.marginTop = `${Math.floor(
(height - lightboxCredits.clientHeight) * 0.5
)}px`;
}
that._lastViewportWidth = width;
}
if (width >= mobileWidth && height !== that._lastViewportHeight) {
lightboxCredits.style.marginTop = `${Math.floor(
(height - lightboxCredits.clientHeight) * 0.5
)}px`;
that._lastViewportHeight = height;
}
}
function appendCss(container) {
const style = (
/*css*/
`
.cesium-credit-lightbox-overlay {
display: none;
z-index: 1;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(80, 80, 80, 0.8);
}
.cesium-credit-lightbox {
background-color: #303336;
color: ${textColor};
position: relative;
min-height: ${lightboxHeight}px;
margin: auto;
}
.cesium-credit-lightbox > ul > li a,
.cesium-credit-lightbox > ul > li a:visited,
.cesium-credit-wrapper a,
.cesium-credit-wrapper a:visited {
color: ${textColor};
}
.cesium-credit-lightbox > ul > li a:hover {
color: ${highlightColor};
}
.cesium-credit-lightbox.cesium-credit-lightbox-expanded {
border: 1px solid #444;
border-radius: 5px;
max-width: 370px;
}
.cesium-credit-lightbox.cesium-credit-lightbox-mobile {
height: 100%;
width: 100%;
}
.cesium-credit-lightbox-title {
padding: 20px 20px 0 20px;
}
.cesium-credit-lightbox-close {
font-size: 18pt;
cursor: pointer;
position: absolute;
top: 0;
right: 6px;
color: ${textColor};
}
.cesium-credit-lightbox-close:hover {
color: ${highlightColor};
}
.cesium-credit-lightbox > ul {
margin: 0;
padding: 12px 20px 12px 40px;
font-size: 13px;
}
.cesium-credit-lightbox > ul > li {
padding-bottom: 6px;
}
.cesium-credit-lightbox > ul > li * {
padding: 0;
margin: 0;
}
.cesium-credit-expand-link {
padding-left: 5px;
cursor: pointer;
text-decoration: underline;
color: ${textColor};
}
.cesium-credit-expand-link:hover {
color: ${highlightColor};
}
.cesium-credit-text {
color: ${textColor};
}
.cesium-credit-delimiter {
padding: 0 5px;
}
.cesium-credit-textContainer *,
.cesium-credit-logoContainer * {
display: inline;
}
.cesium-credit-textContainer a:hover {
color: ${highlightColor}
}
.cesium-credit-textContainer .cesium-credit-wrapper:first-of-type {
padding-left: 5px;
}
`
);
function getShadowRoot(container2) {
if (container2.shadowRoot) {
return container2.shadowRoot;
}
if (container2.getRootNode) {
const root = container2.getRootNode();
if (root instanceof ShadowRoot) {
return root;
}
}
return void 0;
}
const shadowRootOrDocumentHead = getShadowRoot(container) ?? document.head;
const styleElem = document.createElement("style");
styleElem.innerHTML = style;
shadowRootOrDocumentHead.appendChild(styleElem);
}
function CreditDisplay(container, delimiter, viewport) {
Check_default.defined("container", container);
const that = this;
viewport = viewport ?? document.body;
const lightbox = document.createElement("div");
lightbox.className = "cesium-credit-lightbox-overlay";
viewport.appendChild(lightbox);
const lightboxCredits = document.createElement("div");
lightboxCredits.className = "cesium-credit-lightbox";
lightbox.appendChild(lightboxCredits);
function hideLightbox(event) {
if (lightboxCredits.contains(event.target)) {
return;
}
that.hideLightbox();
}
lightbox.addEventListener("click", hideLightbox, false);
const title = document.createElement("div");
title.className = "cesium-credit-lightbox-title";
title.textContent = "Data provided by:";
lightboxCredits.appendChild(title);
const closeButton = document.createElement("a");
closeButton.onclick = this.hideLightbox.bind(this);
closeButton.innerHTML = "×";
closeButton.className = "cesium-credit-lightbox-close";
lightboxCredits.appendChild(closeButton);
const creditList = document.createElement("ul");
lightboxCredits.appendChild(creditList);
const cesiumCreditContainer = document.createElement("div");
cesiumCreditContainer.className = "cesium-credit-logoContainer";
cesiumCreditContainer.style.display = "inline";
container.appendChild(cesiumCreditContainer);
const screenContainer = document.createElement("div");
screenContainer.className = "cesium-credit-textContainer";
screenContainer.style.display = "inline";
container.appendChild(screenContainer);
const expandLink = document.createElement("a");
expandLink.className = "cesium-credit-expand-link";
expandLink.onclick = this.showLightbox.bind(this);
expandLink.textContent = "Data attribution";
container.appendChild(expandLink);
appendCss(container);
const cesiumCredit = Credit_default.clone(CreditDisplay.cesiumCredit);
this._delimiter = delimiter ?? "\u2022";
this._screenContainer = screenContainer;
this._cesiumCreditContainer = cesiumCreditContainer;
this._lastViewportHeight = void 0;
this._lastViewportWidth = void 0;
this._lightboxCredits = lightboxCredits;
this._creditList = creditList;
this._lightbox = lightbox;
this._hideLightbox = hideLightbox;
this._expandLink = expandLink;
this._expanded = false;
this._staticCredits = [];
this._cesiumCredit = cesiumCredit;
this._previousCesiumCredit = void 0;
this._currentCesiumCredit = cesiumCredit;
this._creditDisplayElementPool = [];
this._creditDisplayElementIndex = 0;
this._currentFrameCredits = {
screenCredits: new AssociativeArray_default(),
lightboxCredits: new AssociativeArray_default()
};
this._defaultCredit = void 0;
this.viewport = viewport;
this.container = container;
}
function setCredit(creditDisplay, credits, credit, count) {
count = count ?? 1;
let creditDisplayElement = credits.get(credit.id);
if (!defined_default(creditDisplayElement)) {
const pool2 = creditDisplay._creditDisplayElementPool;
const poolIndex = creditDisplay._creditDisplayElementPoolIndex;
if (poolIndex < pool2.length) {
creditDisplayElement = pool2[poolIndex];
creditDisplayElement.credit = credit;
creditDisplayElement.count = count;
} else {
creditDisplayElement = new CreditDisplayElement(credit, count);
pool2.push(creditDisplayElement);
}
++creditDisplay._creditDisplayElementPoolIndex;
credits.set(credit.id, creditDisplayElement);
} else if (creditDisplayElement.count < Number.MAX_VALUE) {
creditDisplayElement.count += count;
}
}
CreditDisplay.prototype.addCreditToNextFrame = function(credit) {
Check_default.defined("credit", credit);
if (credit.isIon()) {
if (!defined_default(this._defaultCredit)) {
this._defaultCredit = Credit_default.clone(getDefaultCredit());
}
this._currentCesiumCredit = this._defaultCredit;
return;
}
let credits;
if (!credit.showOnScreen) {
credits = this._currentFrameCredits.lightboxCredits;
} else {
credits = this._currentFrameCredits.screenCredits;
}
setCredit(this, credits, credit);
};
CreditDisplay.prototype.addStaticCredit = function(credit) {
Check_default.defined("credit", credit);
const staticCredits = this._staticCredits;
if (!contains2(staticCredits, credit)) {
staticCredits.push(credit);
}
};
CreditDisplay.prototype.removeStaticCredit = function(credit) {
Check_default.defined("credit", credit);
const staticCredits = this._staticCredits;
const index = staticCredits.indexOf(credit);
if (index !== -1) {
staticCredits.splice(index, 1);
}
};
CreditDisplay.prototype.showLightbox = function() {
this._lightbox.style.display = "block";
this._expanded = true;
};
CreditDisplay.prototype.hideLightbox = function() {
this._lightbox.style.display = "none";
this._expanded = false;
};
CreditDisplay.prototype.update = function() {
if (this._expanded) {
styleLightboxContainer(this);
}
};
CreditDisplay.prototype.beginFrame = function() {
const currentFrameCredits = this._currentFrameCredits;
this._creditDisplayElementPoolIndex = 0;
const screenCredits = currentFrameCredits.screenCredits;
const lightboxCredits = currentFrameCredits.lightboxCredits;
screenCredits.removeAll();
lightboxCredits.removeAll();
const staticCredits = this._staticCredits;
for (let i = 0; i < staticCredits.length; ++i) {
const staticCredit = staticCredits[i];
const creditCollection = staticCredit.showOnScreen ? screenCredits : lightboxCredits;
if (staticCredit.isIon() && Credit_default.equals(CreditDisplay.cesiumCredit, this._cesiumCredit)) {
continue;
}
setCredit(this, creditCollection, staticCredit, Number.MAX_VALUE);
}
if (!Credit_default.equals(CreditDisplay.cesiumCredit, this._cesiumCredit)) {
this._cesiumCredit = Credit_default.clone(CreditDisplay.cesiumCredit);
}
this._currentCesiumCredit = this._cesiumCredit;
};
CreditDisplay.prototype.endFrame = function() {
const screenCredits = this._currentFrameCredits.screenCredits.values;
displayCredits(
this._screenContainer,
screenCredits,
this._delimiter,
void 0
);
const lightboxCredits = this._currentFrameCredits.lightboxCredits.values;
this._expandLink.style.display = lightboxCredits.length > 0 ? "inline" : "none";
displayCredits(this._creditList, lightboxCredits, void 0, "li");
swapCesiumCredit(this);
};
CreditDisplay.prototype.destroy = function() {
this._lightbox.removeEventListener("click", this._hideLightbox, false);
this.container.removeChild(this._cesiumCreditContainer);
this.container.removeChild(this._screenContainer);
this.container.removeChild(this._expandLink);
this.viewport.removeChild(this._lightbox);
return destroyObject_default(this);
};
CreditDisplay.prototype.isDestroyed = function() {
return false;
};
CreditDisplay._cesiumCredit = void 0;
CreditDisplay._cesiumCreditInitialized = false;
var defaultCredit2;
function getDefaultCredit() {
if (!defined_default(defaultCredit2)) {
let logo = buildModuleUrl_default("Assets/Images/ion-credit.png");
if (logo.indexOf("http://") !== 0 && logo.indexOf("https://") !== 0 && logo.indexOf("data:") !== 0) {
const logoUrl = new import_urijs12.default(logo);
logo = logoUrl.path();
}
defaultCredit2 = new Credit_default(
`
`,
true
);
}
if (!CreditDisplay._cesiumCreditInitialized) {
CreditDisplay._cesiumCredit = defaultCredit2;
CreditDisplay._cesiumCreditInitialized = true;
}
return defaultCredit2;
}
Object.defineProperties(CreditDisplay, {
/**
* Gets or sets the Cesium logo credit.
* @memberof CreditDisplay
* @type {Credit}
*/
cesiumCredit: {
get: function() {
getDefaultCredit();
return CreditDisplay._cesiumCredit;
},
set: function(value) {
CreditDisplay._cesiumCredit = value;
CreditDisplay._cesiumCreditInitialized = true;
}
}
});
CreditDisplay.CreditDisplayElement = CreditDisplayElement;
var CreditDisplay_default = CreditDisplay;
// packages/engine/Source/Scene/DebugCameraPrimitive.js
var import_InlineWorkers1051 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/FrustumGeometry.js
var import_InlineWorkers1049 = __toESM(require_InlineWorkers(), 1);
var PERSPECTIVE = 0;
var ORTHOGRAPHIC = 1;
function FrustumGeometry(options) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.object("options.frustum", options.frustum);
Check_default.typeOf.object("options.origin", options.origin);
Check_default.typeOf.object("options.orientation", options.orientation);
const frustum = options.frustum;
const orientation = options.orientation;
const origin = options.origin;
const vertexFormat = options.vertexFormat ?? VertexFormat_default.DEFAULT;
const drawNearPlane = options._drawNearPlane ?? true;
let frustumType;
let frustumPackedLength;
if (frustum instanceof PerspectiveFrustum_default) {
frustumType = PERSPECTIVE;
frustumPackedLength = PerspectiveFrustum_default.packedLength;
} else if (frustum instanceof OrthographicFrustum_default) {
frustumType = ORTHOGRAPHIC;
frustumPackedLength = OrthographicFrustum_default.packedLength;
}
this._frustumType = frustumType;
this._frustum = frustum.clone();
this._origin = Cartesian3_default.clone(origin);
this._orientation = Quaternion_default.clone(orientation);
this._drawNearPlane = drawNearPlane;
this._vertexFormat = vertexFormat;
this._workerName = "createFrustumGeometry";
this.packedLength = 2 + frustumPackedLength + Cartesian3_default.packedLength + Quaternion_default.packedLength + VertexFormat_default.packedLength;
}
FrustumGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const frustumType = value._frustumType;
const frustum = value._frustum;
array[startingIndex++] = frustumType;
if (frustumType === PERSPECTIVE) {
PerspectiveFrustum_default.pack(frustum, array, startingIndex);
startingIndex += PerspectiveFrustum_default.packedLength;
} else {
OrthographicFrustum_default.pack(frustum, array, startingIndex);
startingIndex += OrthographicFrustum_default.packedLength;
}
Cartesian3_default.pack(value._origin, array, startingIndex);
startingIndex += Cartesian3_default.packedLength;
Quaternion_default.pack(value._orientation, array, startingIndex);
startingIndex += Quaternion_default.packedLength;
VertexFormat_default.pack(value._vertexFormat, array, startingIndex);
startingIndex += VertexFormat_default.packedLength;
array[startingIndex] = value._drawNearPlane ? 1 : 0;
return array;
};
var scratchPackPerspective = new PerspectiveFrustum_default();
var scratchPackOrthographic = new OrthographicFrustum_default();
var scratchPackQuaternion = new Quaternion_default();
var scratchPackorigin = new Cartesian3_default();
var scratchVertexFormat13 = new VertexFormat_default();
FrustumGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const frustumType = array[startingIndex++];
let frustum;
if (frustumType === PERSPECTIVE) {
frustum = PerspectiveFrustum_default.unpack(
array,
startingIndex,
scratchPackPerspective
);
startingIndex += PerspectiveFrustum_default.packedLength;
} else {
frustum = OrthographicFrustum_default.unpack(
array,
startingIndex,
scratchPackOrthographic
);
startingIndex += OrthographicFrustum_default.packedLength;
}
const origin = Cartesian3_default.unpack(array, startingIndex, scratchPackorigin);
startingIndex += Cartesian3_default.packedLength;
const orientation = Quaternion_default.unpack(
array,
startingIndex,
scratchPackQuaternion
);
startingIndex += Quaternion_default.packedLength;
const vertexFormat = VertexFormat_default.unpack(
array,
startingIndex,
scratchVertexFormat13
);
startingIndex += VertexFormat_default.packedLength;
const drawNearPlane = array[startingIndex] === 1;
if (!defined_default(result)) {
return new FrustumGeometry({
frustum,
origin,
orientation,
vertexFormat,
_drawNearPlane: drawNearPlane
});
}
const frustumResult = frustumType === result._frustumType ? result._frustum : void 0;
result._frustum = frustum.clone(frustumResult);
result._frustumType = frustumType;
result._origin = Cartesian3_default.clone(origin, result._origin);
result._orientation = Quaternion_default.clone(orientation, result._orientation);
result._vertexFormat = VertexFormat_default.clone(vertexFormat, result._vertexFormat);
result._drawNearPlane = drawNearPlane;
return result;
};
function getAttributes(offset, normals, tangents, bitangents, st, normal2, tangent, bitangent) {
const stOffset = offset / 3 * 2;
for (let i = 0; i < 4; ++i) {
if (defined_default(normals)) {
normals[offset] = normal2.x;
normals[offset + 1] = normal2.y;
normals[offset + 2] = normal2.z;
}
if (defined_default(tangents)) {
tangents[offset] = tangent.x;
tangents[offset + 1] = tangent.y;
tangents[offset + 2] = tangent.z;
}
if (defined_default(bitangents)) {
bitangents[offset] = bitangent.x;
bitangents[offset + 1] = bitangent.y;
bitangents[offset + 2] = bitangent.z;
}
offset += 3;
}
st[stOffset] = 0;
st[stOffset + 1] = 0;
st[stOffset + 2] = 1;
st[stOffset + 3] = 0;
st[stOffset + 4] = 1;
st[stOffset + 5] = 1;
st[stOffset + 6] = 0;
st[stOffset + 7] = 1;
}
var scratchRotationMatrix2 = new Matrix3_default();
var scratchViewMatrix = new Matrix4_default();
var scratchInverseMatrix = new Matrix4_default();
var scratchXDirection = new Cartesian3_default();
var scratchYDirection = new Cartesian3_default();
var scratchZDirection = new Cartesian3_default();
var scratchNegativeX = new Cartesian3_default();
var scratchNegativeY = new Cartesian3_default();
var scratchNegativeZ = new Cartesian3_default();
var frustumSplits = new Array(3);
var frustumCornersNDC = new Array(4);
frustumCornersNDC[0] = new Cartesian4_default(-1, -1, 1, 1);
frustumCornersNDC[1] = new Cartesian4_default(1, -1, 1, 1);
frustumCornersNDC[2] = new Cartesian4_default(1, 1, 1, 1);
frustumCornersNDC[3] = new Cartesian4_default(-1, 1, 1, 1);
var scratchFrustumCorners = new Array(4);
for (let i = 0; i < 4; ++i) {
scratchFrustumCorners[i] = new Cartesian4_default();
}
FrustumGeometry._computeNearFarPlanes = function(origin, orientation, frustumType, frustum, positions, xDirection, yDirection, zDirection) {
const rotationMatrix = Matrix3_default.fromQuaternion(
orientation,
scratchRotationMatrix2
);
let x = xDirection ?? scratchXDirection;
let y = yDirection ?? scratchYDirection;
let z = zDirection ?? scratchZDirection;
x = Matrix3_default.getColumn(rotationMatrix, 0, x);
y = Matrix3_default.getColumn(rotationMatrix, 1, y);
z = Matrix3_default.getColumn(rotationMatrix, 2, z);
Cartesian3_default.normalize(x, x);
Cartesian3_default.normalize(y, y);
Cartesian3_default.normalize(z, z);
Cartesian3_default.negate(x, x);
const view = Matrix4_default.computeView(origin, z, y, x, scratchViewMatrix);
let inverseView;
let inverseViewProjection;
const projection = frustum.projectionMatrix;
if (frustumType === PERSPECTIVE) {
const viewProjection = Matrix4_default.multiply(
projection,
view,
scratchInverseMatrix
);
inverseViewProjection = Matrix4_default.inverse(
viewProjection,
scratchInverseMatrix
);
} else {
inverseView = Matrix4_default.inverseTransformation(view, scratchInverseMatrix);
}
if (defined_default(inverseViewProjection)) {
frustumSplits[0] = frustum.near;
frustumSplits[1] = frustum.far;
} else {
frustumSplits[0] = 0;
frustumSplits[1] = frustum.near;
frustumSplits[2] = frustum.far;
}
for (let i = 0; i < 2; ++i) {
for (let j = 0; j < 4; ++j) {
let corner = Cartesian4_default.clone(
frustumCornersNDC[j],
scratchFrustumCorners[j]
);
if (!defined_default(inverseViewProjection)) {
const offCenterFrustum = frustum.offCenterFrustum;
if (defined_default(offCenterFrustum)) {
frustum = offCenterFrustum;
}
const near = frustumSplits[i];
const far = frustumSplits[i + 1];
corner.x = (corner.x * (frustum.right - frustum.left) + frustum.left + frustum.right) * 0.5;
corner.y = (corner.y * (frustum.top - frustum.bottom) + frustum.bottom + frustum.top) * 0.5;
corner.z = (corner.z * (near - far) - near - far) * 0.5;
corner.w = 1;
Matrix4_default.multiplyByVector(inverseView, corner, corner);
} else {
corner = Matrix4_default.multiplyByVector(
inverseViewProjection,
corner,
corner
);
const w = 1 / corner.w;
Cartesian3_default.multiplyByScalar(corner, w, corner);
Cartesian3_default.subtract(corner, origin, corner);
Cartesian3_default.normalize(corner, corner);
const fac = Cartesian3_default.dot(z, corner);
Cartesian3_default.multiplyByScalar(corner, frustumSplits[i] / fac, corner);
Cartesian3_default.add(corner, origin, corner);
}
positions[12 * i + j * 3] = corner.x;
positions[12 * i + j * 3 + 1] = corner.y;
positions[12 * i + j * 3 + 2] = corner.z;
}
}
};
FrustumGeometry.createGeometry = function(frustumGeometry) {
const frustumType = frustumGeometry._frustumType;
const frustum = frustumGeometry._frustum;
const origin = frustumGeometry._origin;
const orientation = frustumGeometry._orientation;
const drawNearPlane = frustumGeometry._drawNearPlane;
const vertexFormat = frustumGeometry._vertexFormat;
const numberOfPlanes = drawNearPlane ? 6 : 5;
let positions = new Float64Array(3 * 4 * 6);
FrustumGeometry._computeNearFarPlanes(
origin,
orientation,
frustumType,
frustum,
positions
);
let offset = 3 * 4 * 2;
positions[offset] = positions[3 * 4];
positions[offset + 1] = positions[3 * 4 + 1];
positions[offset + 2] = positions[3 * 4 + 2];
positions[offset + 3] = positions[0];
positions[offset + 4] = positions[1];
positions[offset + 5] = positions[2];
positions[offset + 6] = positions[3 * 3];
positions[offset + 7] = positions[3 * 3 + 1];
positions[offset + 8] = positions[3 * 3 + 2];
positions[offset + 9] = positions[3 * 7];
positions[offset + 10] = positions[3 * 7 + 1];
positions[offset + 11] = positions[3 * 7 + 2];
offset += 3 * 4;
positions[offset] = positions[3 * 5];
positions[offset + 1] = positions[3 * 5 + 1];
positions[offset + 2] = positions[3 * 5 + 2];
positions[offset + 3] = positions[3];
positions[offset + 4] = positions[3 + 1];
positions[offset + 5] = positions[3 + 2];
positions[offset + 6] = positions[0];
positions[offset + 7] = positions[1];
positions[offset + 8] = positions[2];
positions[offset + 9] = positions[3 * 4];
positions[offset + 10] = positions[3 * 4 + 1];
positions[offset + 11] = positions[3 * 4 + 2];
offset += 3 * 4;
positions[offset] = positions[3];
positions[offset + 1] = positions[3 + 1];
positions[offset + 2] = positions[3 + 2];
positions[offset + 3] = positions[3 * 5];
positions[offset + 4] = positions[3 * 5 + 1];
positions[offset + 5] = positions[3 * 5 + 2];
positions[offset + 6] = positions[3 * 6];
positions[offset + 7] = positions[3 * 6 + 1];
positions[offset + 8] = positions[3 * 6 + 2];
positions[offset + 9] = positions[3 * 2];
positions[offset + 10] = positions[3 * 2 + 1];
positions[offset + 11] = positions[3 * 2 + 2];
offset += 3 * 4;
positions[offset] = positions[3 * 2];
positions[offset + 1] = positions[3 * 2 + 1];
positions[offset + 2] = positions[3 * 2 + 2];
positions[offset + 3] = positions[3 * 6];
positions[offset + 4] = positions[3 * 6 + 1];
positions[offset + 5] = positions[3 * 6 + 2];
positions[offset + 6] = positions[3 * 7];
positions[offset + 7] = positions[3 * 7 + 1];
positions[offset + 8] = positions[3 * 7 + 2];
positions[offset + 9] = positions[3 * 3];
positions[offset + 10] = positions[3 * 3 + 1];
positions[offset + 11] = positions[3 * 3 + 2];
if (!drawNearPlane) {
positions = positions.subarray(3 * 4);
}
const attributes = new GeometryAttributes_default({
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
})
});
if (defined_default(vertexFormat.normal) || defined_default(vertexFormat.tangent) || defined_default(vertexFormat.bitangent) || defined_default(vertexFormat.st)) {
const normals = defined_default(vertexFormat.normal) ? new Float32Array(3 * 4 * numberOfPlanes) : void 0;
const tangents = defined_default(vertexFormat.tangent) ? new Float32Array(3 * 4 * numberOfPlanes) : void 0;
const bitangents = defined_default(vertexFormat.bitangent) ? new Float32Array(3 * 4 * numberOfPlanes) : void 0;
const st = defined_default(vertexFormat.st) ? new Float32Array(2 * 4 * numberOfPlanes) : void 0;
const x = scratchXDirection;
const y = scratchYDirection;
const z = scratchZDirection;
const negativeX2 = Cartesian3_default.negate(x, scratchNegativeX);
const negativeY = Cartesian3_default.negate(y, scratchNegativeY);
const negativeZ = Cartesian3_default.negate(z, scratchNegativeZ);
offset = 0;
if (drawNearPlane) {
getAttributes(offset, normals, tangents, bitangents, st, negativeZ, x, y);
offset += 3 * 4;
}
getAttributes(offset, normals, tangents, bitangents, st, z, negativeX2, y);
offset += 3 * 4;
getAttributes(
offset,
normals,
tangents,
bitangents,
st,
negativeX2,
negativeZ,
y
);
offset += 3 * 4;
getAttributes(
offset,
normals,
tangents,
bitangents,
st,
negativeY,
negativeZ,
negativeX2
);
offset += 3 * 4;
getAttributes(offset, normals, tangents, bitangents, st, x, z, y);
offset += 3 * 4;
getAttributes(offset, normals, tangents, bitangents, st, y, z, negativeX2);
if (defined_default(normals)) {
attributes.normal = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: normals
});
}
if (defined_default(tangents)) {
attributes.tangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: tangents
});
}
if (defined_default(bitangents)) {
attributes.bitangent = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: bitangents
});
}
if (defined_default(st)) {
attributes.st = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 2,
values: st
});
}
}
const indices = new Uint16Array(6 * numberOfPlanes);
for (let i = 0; i < numberOfPlanes; ++i) {
const indexOffset = i * 6;
const index = i * 4;
indices[indexOffset] = index;
indices[indexOffset + 1] = index + 1;
indices[indexOffset + 2] = index + 2;
indices[indexOffset + 3] = index;
indices[indexOffset + 4] = index + 2;
indices[indexOffset + 5] = index + 3;
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.TRIANGLES,
boundingSphere: BoundingSphere_default.fromVertices(positions)
});
};
var FrustumGeometry_default = FrustumGeometry;
// packages/engine/Source/Core/FrustumOutlineGeometry.js
var import_InlineWorkers1050 = __toESM(require_InlineWorkers(), 1);
var PERSPECTIVE2 = 0;
var ORTHOGRAPHIC2 = 1;
function FrustumOutlineGeometry(options) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.object("options.frustum", options.frustum);
Check_default.typeOf.object("options.origin", options.origin);
Check_default.typeOf.object("options.orientation", options.orientation);
const frustum = options.frustum;
const orientation = options.orientation;
const origin = options.origin;
const drawNearPlane = options._drawNearPlane ?? true;
let frustumType;
let frustumPackedLength;
if (frustum instanceof PerspectiveFrustum_default) {
frustumType = PERSPECTIVE2;
frustumPackedLength = PerspectiveFrustum_default.packedLength;
} else if (frustum instanceof OrthographicFrustum_default) {
frustumType = ORTHOGRAPHIC2;
frustumPackedLength = OrthographicFrustum_default.packedLength;
}
this._frustumType = frustumType;
this._frustum = frustum.clone();
this._origin = Cartesian3_default.clone(origin);
this._orientation = Quaternion_default.clone(orientation);
this._drawNearPlane = drawNearPlane;
this._workerName = "createFrustumOutlineGeometry";
this.packedLength = 2 + frustumPackedLength + Cartesian3_default.packedLength + Quaternion_default.packedLength;
}
FrustumOutlineGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const frustumType = value._frustumType;
const frustum = value._frustum;
array[startingIndex++] = frustumType;
if (frustumType === PERSPECTIVE2) {
PerspectiveFrustum_default.pack(frustum, array, startingIndex);
startingIndex += PerspectiveFrustum_default.packedLength;
} else {
OrthographicFrustum_default.pack(frustum, array, startingIndex);
startingIndex += OrthographicFrustum_default.packedLength;
}
Cartesian3_default.pack(value._origin, array, startingIndex);
startingIndex += Cartesian3_default.packedLength;
Quaternion_default.pack(value._orientation, array, startingIndex);
startingIndex += Quaternion_default.packedLength;
array[startingIndex] = value._drawNearPlane ? 1 : 0;
return array;
};
var scratchPackPerspective2 = new PerspectiveFrustum_default();
var scratchPackOrthographic2 = new OrthographicFrustum_default();
var scratchPackQuaternion2 = new Quaternion_default();
var scratchPackorigin2 = new Cartesian3_default();
FrustumOutlineGeometry.unpack = function(array, startingIndex, result) {
Check_default.defined("array", array);
startingIndex = startingIndex ?? 0;
const frustumType = array[startingIndex++];
let frustum;
if (frustumType === PERSPECTIVE2) {
frustum = PerspectiveFrustum_default.unpack(
array,
startingIndex,
scratchPackPerspective2
);
startingIndex += PerspectiveFrustum_default.packedLength;
} else {
frustum = OrthographicFrustum_default.unpack(
array,
startingIndex,
scratchPackOrthographic2
);
startingIndex += OrthographicFrustum_default.packedLength;
}
const origin = Cartesian3_default.unpack(array, startingIndex, scratchPackorigin2);
startingIndex += Cartesian3_default.packedLength;
const orientation = Quaternion_default.unpack(
array,
startingIndex,
scratchPackQuaternion2
);
startingIndex += Quaternion_default.packedLength;
const drawNearPlane = array[startingIndex] === 1;
if (!defined_default(result)) {
return new FrustumOutlineGeometry({
frustum,
origin,
orientation,
_drawNearPlane: drawNearPlane
});
}
const frustumResult = frustumType === result._frustumType ? result._frustum : void 0;
result._frustum = frustum.clone(frustumResult);
result._frustumType = frustumType;
result._origin = Cartesian3_default.clone(origin, result._origin);
result._orientation = Quaternion_default.clone(orientation, result._orientation);
result._drawNearPlane = drawNearPlane;
return result;
};
FrustumOutlineGeometry.createGeometry = function(frustumGeometry) {
const frustumType = frustumGeometry._frustumType;
const frustum = frustumGeometry._frustum;
const origin = frustumGeometry._origin;
const orientation = frustumGeometry._orientation;
const drawNearPlane = frustumGeometry._drawNearPlane;
const positions = new Float64Array(3 * 4 * 2);
FrustumGeometry_default._computeNearFarPlanes(
origin,
orientation,
frustumType,
frustum,
positions
);
const attributes = new GeometryAttributes_default({
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positions
})
});
let offset;
let index;
const numberOfPlanes = drawNearPlane ? 2 : 1;
const indices = new Uint16Array(8 * (numberOfPlanes + 1));
let i = drawNearPlane ? 0 : 1;
for (; i < 2; ++i) {
offset = drawNearPlane ? i * 8 : 0;
index = i * 4;
indices[offset] = index;
indices[offset + 1] = index + 1;
indices[offset + 2] = index + 1;
indices[offset + 3] = index + 2;
indices[offset + 4] = index + 2;
indices[offset + 5] = index + 3;
indices[offset + 6] = index + 3;
indices[offset + 7] = index;
}
for (i = 0; i < 2; ++i) {
offset = (numberOfPlanes + i) * 8;
index = i * 4;
indices[offset] = index;
indices[offset + 1] = index + 4;
indices[offset + 2] = index + 1;
indices[offset + 3] = index + 5;
indices[offset + 4] = index + 2;
indices[offset + 5] = index + 6;
indices[offset + 6] = index + 3;
indices[offset + 7] = index + 7;
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.LINES,
boundingSphere: BoundingSphere_default.fromVertices(positions)
});
};
var FrustumOutlineGeometry_default = FrustumOutlineGeometry;
// packages/engine/Source/Scene/DebugCameraPrimitive.js
function DebugCameraPrimitive(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
if (!defined_default(options.camera)) {
throw new DeveloperError_default("options.camera is required.");
}
this._camera = options.camera;
this._frustumSplits = options.frustumSplits;
this._color = options.color ?? Color_default.CYAN;
this._updateOnChange = options.updateOnChange ?? true;
this.show = options.show ?? true;
this.id = options.id;
this._id = void 0;
this._outlinePrimitives = [];
this._planesPrimitives = [];
}
var scratchRight2 = new Cartesian3_default();
var scratchRotation3 = new Matrix3_default();
var scratchOrientation = new Quaternion_default();
var scratchPerspective = new PerspectiveFrustum_default();
var scratchPerspectiveOffCenter = new PerspectiveOffCenterFrustum_default();
var scratchOrthographic = new OrthographicFrustum_default();
var scratchOrthographicOffCenter = new OrthographicOffCenterFrustum_default();
var scratchColor26 = new Color_default();
var scratchSplits = [1, 1e5];
DebugCameraPrimitive.prototype.update = function(frameState) {
if (!this.show) {
return;
}
const planesPrimitives = this._planesPrimitives;
const outlinePrimitives = this._outlinePrimitives;
let i;
let length2;
if (this._updateOnChange) {
length2 = planesPrimitives.length;
for (i = 0; i < length2; ++i) {
outlinePrimitives[i] = outlinePrimitives[i] && outlinePrimitives[i].destroy();
planesPrimitives[i] = planesPrimitives[i] && planesPrimitives[i].destroy();
}
planesPrimitives.length = 0;
outlinePrimitives.length = 0;
}
if (planesPrimitives.length === 0) {
const camera = this._camera;
const cameraFrustum = camera.frustum;
let frustum;
if (cameraFrustum instanceof PerspectiveFrustum_default) {
frustum = scratchPerspective;
} else if (cameraFrustum instanceof PerspectiveOffCenterFrustum_default) {
frustum = scratchPerspectiveOffCenter;
} else if (cameraFrustum instanceof OrthographicFrustum_default) {
frustum = scratchOrthographic;
} else {
frustum = scratchOrthographicOffCenter;
}
frustum = cameraFrustum.clone(frustum);
let numFrustums;
let frustumSplits2 = this._frustumSplits;
if (!defined_default(frustumSplits2) || frustumSplits2.length <= 1) {
frustumSplits2 = scratchSplits;
frustumSplits2[0] = this._camera.frustum.near;
frustumSplits2[1] = this._camera.frustum.far;
numFrustums = 1;
} else {
numFrustums = frustumSplits2.length - 1;
}
const position = camera.positionWC;
const direction2 = camera.directionWC;
const up = camera.upWC;
let right = camera.rightWC;
right = Cartesian3_default.negate(right, scratchRight2);
const rotation = scratchRotation3;
Matrix3_default.setColumn(rotation, 0, right, rotation);
Matrix3_default.setColumn(rotation, 1, up, rotation);
Matrix3_default.setColumn(rotation, 2, direction2, rotation);
const orientation = Quaternion_default.fromRotationMatrix(
rotation,
scratchOrientation
);
planesPrimitives.length = outlinePrimitives.length = numFrustums;
for (i = 0; i < numFrustums; ++i) {
frustum.near = frustumSplits2[i];
frustum.far = frustumSplits2[i + 1];
planesPrimitives[i] = new Primitive_default({
geometryInstances: new GeometryInstance_default({
geometry: new FrustumGeometry_default({
origin: position,
orientation,
frustum,
_drawNearPlane: i === 0
}),
attributes: {
color: ColorGeometryInstanceAttribute_default.fromColor(
Color_default.fromAlpha(this._color, 0.1, scratchColor26)
)
},
id: this.id,
pickPrimitive: this
}),
appearance: new PerInstanceColorAppearance_default({
translucent: true,
flat: true
}),
asynchronous: false
});
outlinePrimitives[i] = new Primitive_default({
geometryInstances: new GeometryInstance_default({
geometry: new FrustumOutlineGeometry_default({
origin: position,
orientation,
frustum,
_drawNearPlane: i === 0
}),
attributes: {
color: ColorGeometryInstanceAttribute_default.fromColor(this._color)
},
id: this.id,
pickPrimitive: this
}),
appearance: new PerInstanceColorAppearance_default({
translucent: false,
flat: true
}),
asynchronous: false
});
}
}
length2 = planesPrimitives.length;
for (i = 0; i < length2; ++i) {
outlinePrimitives[i].update(frameState);
planesPrimitives[i].update(frameState);
}
};
DebugCameraPrimitive.prototype.isDestroyed = function() {
return false;
};
DebugCameraPrimitive.prototype.destroy = function() {
const length2 = this._planesPrimitives.length;
for (let i = 0; i < length2; ++i) {
this._outlinePrimitives[i] = this._outlinePrimitives[i] && this._outlinePrimitives[i].destroy();
this._planesPrimitives[i] = this._planesPrimitives[i] && this._planesPrimitives[i].destroy();
}
return destroyObject_default(this);
};
var DebugCameraPrimitive_default = DebugCameraPrimitive;
// packages/engine/Source/Scene/DepthPlane.js
var import_InlineWorkers1054 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/DepthPlaneFS.js
var import_InlineWorkers1052 = __toESM(require_InlineWorkers(), 1);
var DepthPlaneFS_default = "in vec4 positionEC;\n\nvoid main()\n{\n vec3 position;\n vec3 direction;\n if (czm_orthographicIn3D == 1.0)\n {\n vec2 uv = (gl_FragCoord.xy - czm_viewport.xy) / czm_viewport.zw;\n vec2 minPlane = vec2(czm_frustumPlanes.z, czm_frustumPlanes.y); // left, bottom\n vec2 maxPlane = vec2(czm_frustumPlanes.w, czm_frustumPlanes.x); // right, top\n position = vec3(mix(minPlane, maxPlane, uv), 0.0);\n direction = vec3(0.0, 0.0, -1.0);\n } \n else \n {\n position = vec3(0.0);\n direction = normalize(positionEC.xyz);\n }\n\n czm_ray ray = czm_ray(position, direction);\n\n vec3 ellipsoid_center = czm_view[3].xyz;\n\n czm_raySegment intersection = czm_rayEllipsoidIntersectionInterval(ray, ellipsoid_center, czm_ellipsoidInverseRadii);\n if (!czm_isEmpty(intersection))\n {\n out_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n }\n else\n {\n discard;\n }\n\n czm_writeLogDepth();\n}\n";
// packages/engine/Source/Shaders/DepthPlaneVS.js
var import_InlineWorkers1053 = __toESM(require_InlineWorkers(), 1);
var DepthPlaneVS_default = "in vec4 position;\n\nout vec4 positionEC;\n\nvoid main()\n{\n positionEC = czm_modelView * position;\n gl_Position = czm_projection * positionEC;\n\n czm_vertexLogDepth();\n}\n";
// packages/engine/Source/Scene/DepthPlane.js
function DepthPlane(depthPlaneEllipsoidOffset) {
this._rs = void 0;
this._sp = void 0;
this._va = void 0;
this._command = void 0;
this._mode = void 0;
this._useLogDepth = false;
this._ellipsoidOffset = depthPlaneEllipsoidOffset ?? 0;
}
var depthQuadScratch = FeatureDetection_default.supportsTypedArrays() ? new Float32Array(12) : [];
var scratchCartesian113 = new Cartesian3_default();
var scratchCartesian211 = new Cartesian3_default();
var scratchCartesian315 = new Cartesian3_default();
var scratchCartesian46 = new Cartesian3_default();
var scratchCartesian53 = new Cartesian3_default();
function computeDepthQuad(ellipsoid, frameState) {
const radii = ellipsoid.radii;
const camera = frameState.camera;
let center, eastOffset, northOffset;
if (camera.frustum instanceof OrthographicFrustum_default) {
center = Cartesian3_default.ZERO;
eastOffset = camera.rightWC;
northOffset = camera.upWC;
} else {
const p = camera.positionWC;
const q = Cartesian3_default.multiplyComponents(
ellipsoid.oneOverRadii,
p,
scratchCartesian113
);
const qUnit = Cartesian3_default.normalize(q, scratchCartesian211);
const eUnit = Cartesian3_default.normalize(
Cartesian3_default.cross(Cartesian3_default.UNIT_Z, q, scratchCartesian315),
scratchCartesian315
);
const nUnit = Cartesian3_default.normalize(
Cartesian3_default.cross(qUnit, eUnit, scratchCartesian46),
scratchCartesian46
);
const qMagnitude = Cartesian3_default.magnitude(q);
const wMagnitude = Math.sqrt(qMagnitude * qMagnitude - 1);
center = Cartesian3_default.multiplyByScalar(
qUnit,
1 / qMagnitude,
scratchCartesian113
);
const scalar = wMagnitude / qMagnitude;
eastOffset = Cartesian3_default.multiplyByScalar(eUnit, scalar, scratchCartesian211);
northOffset = Cartesian3_default.multiplyByScalar(nUnit, scalar, scratchCartesian315);
}
const upperLeft = Cartesian3_default.add(center, northOffset, scratchCartesian53);
Cartesian3_default.subtract(upperLeft, eastOffset, upperLeft);
Cartesian3_default.multiplyComponents(radii, upperLeft, upperLeft);
Cartesian3_default.pack(upperLeft, depthQuadScratch, 0);
const lowerLeft = Cartesian3_default.subtract(center, northOffset, scratchCartesian53);
Cartesian3_default.subtract(lowerLeft, eastOffset, lowerLeft);
Cartesian3_default.multiplyComponents(radii, lowerLeft, lowerLeft);
Cartesian3_default.pack(lowerLeft, depthQuadScratch, 3);
const upperRight = Cartesian3_default.add(center, northOffset, scratchCartesian53);
Cartesian3_default.add(upperRight, eastOffset, upperRight);
Cartesian3_default.multiplyComponents(radii, upperRight, upperRight);
Cartesian3_default.pack(upperRight, depthQuadScratch, 6);
const lowerRight = Cartesian3_default.subtract(
center,
northOffset,
scratchCartesian53
);
Cartesian3_default.add(lowerRight, eastOffset, lowerRight);
Cartesian3_default.multiplyComponents(radii, lowerRight, lowerRight);
Cartesian3_default.pack(lowerRight, depthQuadScratch, 9);
return depthQuadScratch;
}
DepthPlane.prototype.update = function(frameState) {
this._mode = frameState.mode;
if (frameState.mode !== SceneMode_default.SCENE3D) {
return;
}
const context = frameState.context;
const radii = frameState.mapProjection.ellipsoid.radii;
const ellipsoid = new Ellipsoid_default(
radii.x + this._ellipsoidOffset,
radii.y + this._ellipsoidOffset,
radii.z + this._ellipsoidOffset
);
const useLogDepth = frameState.useLogDepth;
if (!defined_default(this._command)) {
this._rs = RenderState_default.fromCache({
// Write depth, not color
cull: {
enabled: true
},
depthTest: {
enabled: true
},
colorMask: {
red: false,
green: false,
blue: false,
alpha: false
}
});
this._command = new DrawCommand_default({
renderState: this._rs,
boundingVolume: new BoundingSphere_default(
Cartesian3_default.ZERO,
ellipsoid.maximumRadius
),
pass: Pass_default.OPAQUE,
owner: this
});
}
if (!defined_default(this._sp) || this._useLogDepth !== useLogDepth) {
this._useLogDepth = useLogDepth;
const vs = new ShaderSource_default({
sources: [DepthPlaneVS_default]
});
const fs = new ShaderSource_default({
sources: [DepthPlaneFS_default]
});
if (useLogDepth) {
fs.defines.push("LOG_DEPTH");
vs.defines.push("LOG_DEPTH");
}
this._sp = ShaderProgram_default.replaceCache({
shaderProgram: this._sp,
context,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: {
position: 0
}
});
this._command.shaderProgram = this._sp;
}
const depthQuad = computeDepthQuad(ellipsoid, frameState);
if (!defined_default(this._va)) {
const geometry = new Geometry_default({
attributes: {
position: new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.FLOAT,
componentsPerAttribute: 3,
values: depthQuad
})
},
indices: [0, 1, 2, 2, 1, 3],
primitiveType: PrimitiveType_default.TRIANGLES
});
this._va = VertexArray_default.fromGeometry({
context,
geometry,
attributeLocations: {
position: 0
},
bufferUsage: BufferUsage_default.DYNAMIC_DRAW
});
this._command.vertexArray = this._va;
} else {
this._va.getAttribute(0).vertexBuffer.copyFromArrayView(depthQuad);
}
};
DepthPlane.prototype.execute = function(context, passState) {
if (this._mode === SceneMode_default.SCENE3D) {
this._command.execute(context, passState);
}
};
DepthPlane.prototype.isDestroyed = function() {
return false;
};
DepthPlane.prototype.destroy = function() {
this._sp = this._sp && this._sp.destroy();
this._va = this._va && this._va.destroy();
};
var DepthPlane_default = DepthPlane;
// packages/engine/Source/Scene/DerivedCommand.js
var import_InlineWorkers1055 = __toESM(require_InlineWorkers(), 1);
function DerivedCommand() {
}
var fragDepthRegex = /\bgl_FragDepth\b/;
var discardRegex = /\bdiscard\b/;
function getDepthOnlyShaderProgram(context, shaderProgram) {
const cachedShader = context.shaderCache.getDerivedShaderProgram(
shaderProgram,
"depthOnly"
);
if (defined_default(cachedShader)) {
return cachedShader;
}
let fs = shaderProgram.fragmentShaderSource;
let writesDepthOrDiscards = false;
const sources = fs.sources;
for (let i = 0; i < sources.length; ++i) {
if (fragDepthRegex.test(sources[i]) || discardRegex.test(sources[i])) {
writesDepthOrDiscards = true;
break;
}
}
const usesLogDepth = fs.defines.indexOf("LOG_DEPTH") >= 0;
if (!writesDepthOrDiscards && !usesLogDepth) {
const source = `void main()
{
out_FragColor = vec4(1.0);
}
`;
fs = new ShaderSource_default({
sources: [source]
});
} else if (!writesDepthOrDiscards && usesLogDepth) {
const source = `void main()
{
out_FragColor = vec4(1.0);
czm_writeLogDepth();
}
`;
fs = new ShaderSource_default({
defines: ["LOG_DEPTH"],
sources: [source]
});
}
return context.shaderCache.createDerivedShaderProgram(
shaderProgram,
"depthOnly",
{
vertexShaderSource: shaderProgram.vertexShaderSource,
fragmentShaderSource: fs,
attributeLocations: shaderProgram._attributeLocations
}
);
}
function getDepthOnlyRenderState(scene, renderState) {
const cache = scene._depthOnlyRenderStateCache;
const cachedDepthOnlyState = cache[renderState.id];
if (defined_default(cachedDepthOnlyState)) {
return cachedDepthOnlyState;
}
const rs = RenderState_default.getState(renderState);
rs.depthMask = true;
rs.colorMask = {
red: false,
green: false,
blue: false,
alpha: false
};
const depthOnlyState = RenderState_default.fromCache(rs);
cache[renderState.id] = depthOnlyState;
return depthOnlyState;
}
DerivedCommand.createDepthOnlyDerivedCommand = function(scene, command, context, result) {
if (!defined_default(result)) {
result = {};
}
const shader = result.depthOnlyCommand?.shaderProgram;
const renderState = result.depthOnlyCommand?.renderState;
result.depthOnlyCommand = DrawCommand_default.shallowClone(
command,
result.depthOnlyCommand
);
if (!defined_default(shader) || result.shaderProgramId !== command.shaderProgram.id) {
result.depthOnlyCommand.shaderProgram = getDepthOnlyShaderProgram(
context,
command.shaderProgram
);
result.depthOnlyCommand.renderState = getDepthOnlyRenderState(
scene,
command.renderState
);
result.shaderProgramId = command.shaderProgram.id;
} else {
result.depthOnlyCommand.shaderProgram = shader;
result.depthOnlyCommand.renderState = renderState;
}
return result;
};
var writeLogDepthRegex = /\s+czm_writeLogDepth\(/;
var vertexlogDepthRegex = /\s+czm_vertexLogDepth\(/;
function getLogDepthShaderProgram(context, shaderProgram) {
const disableLogDepthWrite = shaderProgram.fragmentShaderSource.defines.indexOf("LOG_DEPTH_READ_ONLY") >= 0;
if (disableLogDepthWrite) {
return shaderProgram;
}
const cachedShader = context.shaderCache.getDerivedShaderProgram(
shaderProgram,
"logDepth"
);
if (defined_default(cachedShader)) {
return cachedShader;
}
const attributeLocations8 = shaderProgram._attributeLocations;
const vs = shaderProgram.vertexShaderSource.clone();
const fs = shaderProgram.fragmentShaderSource.clone();
vs.defines = defined_default(vs.defines) ? vs.defines.slice(0) : [];
vs.defines.push("LOG_DEPTH");
fs.defines = defined_default(fs.defines) ? fs.defines.slice(0) : [];
fs.defines.push("LOG_DEPTH");
let writesLogDepth = false;
let sources = vs.sources;
for (let i = 0; i < sources.length; ++i) {
if (vertexlogDepthRegex.test(sources[i])) {
writesLogDepth = true;
break;
}
}
if (!writesLogDepth) {
for (let i = 0; i < sources.length; ++i) {
sources[i] = ShaderSource_default.replaceMain(sources[i], "czm_log_depth_main");
}
const logMain = `
void main()
{
czm_log_depth_main();
czm_vertexLogDepth();
}
`;
sources.push(logMain);
}
sources = fs.sources;
writesLogDepth = false;
for (let i = 0; i < sources.length; ++i) {
if (writeLogDepthRegex.test(sources[i])) {
writesLogDepth = true;
}
}
if (fs.defines.indexOf("LOG_DEPTH_WRITE") !== -1) {
writesLogDepth = true;
}
let logSource = "";
if (!writesLogDepth) {
for (let i = 0; i < sources.length; i++) {
sources[i] = ShaderSource_default.replaceMain(sources[i], "czm_log_depth_main");
}
logSource = `
void main()
{
czm_log_depth_main();
czm_writeLogDepth();
}
`;
}
sources.push(logSource);
return context.shaderCache.createDerivedShaderProgram(
shaderProgram,
"logDepth",
{
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations8
}
);
}
DerivedCommand.createLogDepthCommand = function(command, context, result) {
if (!defined_default(result)) {
result = {};
}
const shader = result.command?.shaderProgram;
result.command = DrawCommand_default.shallowClone(command, result.command);
if (!defined_default(shader) || result.shaderProgramId !== command.shaderProgram.id) {
result.command.shaderProgram = getLogDepthShaderProgram(
context,
command.shaderProgram
);
result.shaderProgramId = command.shaderProgram.id;
} else {
result.command.shaderProgram = shader;
}
return result;
};
function getPickShaderProgram(context, shaderProgram, pickId) {
const cachedShader = context.shaderCache.getDerivedShaderProgram(
shaderProgram,
"pick"
);
if (defined_default(cachedShader)) {
return cachedShader;
}
const attributeLocations8 = shaderProgram._attributeLocations;
const { sources, defines } = shaderProgram.fragmentShaderSource;
const hasFragData = sources.some((source) => source.includes("out_FragData"));
const outputColorVariable = hasFragData ? "out_FragData_0" : "out_FragColor";
const newMain = `void main ()
{
czm_non_pick_main();
if (${outputColorVariable}.a == 0.0) {
discard;
}
${outputColorVariable} = ${pickId};
} `;
const length2 = sources.length;
const newSources = new Array(length2 + 1);
for (let i = 0; i < length2; ++i) {
newSources[i] = ShaderSource_default.replaceMain(sources[i], "czm_non_pick_main");
}
newSources[length2] = newMain;
const fragmentShaderSource = new ShaderSource_default({
sources: newSources,
defines
});
return context.shaderCache.createDerivedShaderProgram(shaderProgram, "pick", {
vertexShaderSource: shaderProgram.vertexShaderSource,
fragmentShaderSource,
attributeLocations: attributeLocations8
});
}
function getPickRenderState(scene, renderState) {
const cache = scene.picking.pickRenderStateCache;
const cachedPickState = cache[renderState.id];
if (defined_default(cachedPickState)) {
return cachedPickState;
}
const rs = RenderState_default.getState(renderState);
rs.blending.enabled = false;
rs.depthMask = true;
const pickState = RenderState_default.fromCache(rs);
cache[renderState.id] = pickState;
return pickState;
}
DerivedCommand.createPickDerivedCommand = function(scene, command, context, result) {
if (!defined_default(result)) {
result = {};
}
const shader = result.pickCommand?.shaderProgram;
const renderState = result.pickCommand?.renderState;
result.pickCommand = DrawCommand_default.shallowClone(command, result.pickCommand);
if (!defined_default(shader) || result.shaderProgramId !== command.shaderProgram.id) {
result.pickCommand.shaderProgram = getPickShaderProgram(
context,
command.shaderProgram,
command.pickId
);
result.pickCommand.renderState = getPickRenderState(
scene,
command.renderState
);
result.shaderProgramId = command.shaderProgram.id;
} else {
result.pickCommand.shaderProgram = shader;
result.pickCommand.renderState = renderState;
}
return result;
};
function replaceDefine(defines, defineName, newDefineValue) {
const n = defines.length;
for (let i = 0; i < n; i++) {
const define2 = defines[i];
const tokens = define2.trimStart().split(/\s+/);
if (tokens[0] === defineName) {
defines[i] = `${defineName} ${newDefineValue}`;
}
}
}
function getComponentCount(classProperty) {
if (!classProperty.isArray) {
return MetadataType_default.getComponentCount(classProperty.type);
}
return classProperty.arrayLength;
}
function getGlslType(classProperty) {
const componentCount = getComponentCount(classProperty);
if (classProperty.normalized) {
if (componentCount === 1) {
return "float";
}
return `vec${componentCount}`;
}
if (componentCount === 1) {
return "int";
}
return `ivec${componentCount}`;
}
function unapplyValueTransform2(input, offset, scale) {
return `((${input} - float(${offset})) / float(${scale}))`;
}
function unnormalize(input, componentType) {
const max3 = MetadataComponentType_default.getMaximum(componentType);
return `(${input}) / float(${max3})`;
}
function getSourceValueStringScalar(classProperty, metadataProperty) {
let result = `float(value)`;
if (metadataProperty.hasValueTransform) {
const offset = metadataProperty.offset;
const scale = metadataProperty.scale;
result = unapplyValueTransform2(result, offset, scale);
}
if (!classProperty.normalized) {
result = unnormalize(result, classProperty.componentType);
}
return result;
}
function getSourceValueStringComponent(classProperty, metadataProperty, componentName) {
const valueString = `value.${componentName}`;
let result = `float(${valueString})`;
if (metadataProperty.hasValueTransform) {
const offset = metadataProperty.offset[componentName];
const scale = metadataProperty.scale[componentName];
result = unapplyValueTransform2(result, offset, scale);
}
if (!classProperty.normalized) {
result = unnormalize(result, classProperty.componentType);
}
return result;
}
function getPickMetadataShaderProgram(context, shaderProgram, pickedMetadataInfo) {
const schemaId = pickedMetadataInfo.schemaId;
const className = pickedMetadataInfo.className;
const propertyName = pickedMetadataInfo.propertyName;
const keyword = `pickMetadata-${schemaId}-${className}-${propertyName}`;
const shader = context.shaderCache.getDerivedShaderProgram(
shaderProgram,
keyword
);
if (defined_default(shader)) {
return shader;
}
const metadataProperty = pickedMetadataInfo.metadataProperty;
const classProperty = pickedMetadataInfo.classProperty;
const glslType = getGlslType(classProperty);
const sourceValueStrings = ["0.0", "0.0", "0.0", "0.0"];
const componentCount = getComponentCount(classProperty);
if (componentCount === 1) {
sourceValueStrings[0] = getSourceValueStringScalar(
classProperty,
metadataProperty
);
} else {
const componentNames = ["x", "y", "z", "w"];
for (let i = 0; i < componentCount; i++) {
sourceValueStrings[i] = getSourceValueStringComponent(
classProperty,
metadataProperty,
componentNames[i]
);
}
}
const newDefines = shaderProgram.fragmentShaderSource.defines.slice();
newDefines.push(MetadataPickingPipelineStage_default.METADATA_PICKING_ENABLED);
replaceDefine(
newDefines,
MetadataPickingPipelineStage_default.METADATA_PICKING_VALUE_TYPE,
glslType
);
replaceDefine(
newDefines,
MetadataPickingPipelineStage_default.METADATA_PICKING_VALUE_STRING,
`metadata.${propertyName}`
);
replaceDefine(
newDefines,
MetadataPickingPipelineStage_default.METADATA_PICKING_VALUE_COMPONENT_X,
sourceValueStrings[0]
);
replaceDefine(
newDefines,
MetadataPickingPipelineStage_default.METADATA_PICKING_VALUE_COMPONENT_Y,
sourceValueStrings[1]
);
replaceDefine(
newDefines,
MetadataPickingPipelineStage_default.METADATA_PICKING_VALUE_COMPONENT_Z,
sourceValueStrings[2]
);
replaceDefine(
newDefines,
MetadataPickingPipelineStage_default.METADATA_PICKING_VALUE_COMPONENT_W,
sourceValueStrings[3]
);
const newFragmentShaderSource = new ShaderSource_default({
sources: shaderProgram.fragmentShaderSource.sources,
defines: newDefines
});
const newShader = context.shaderCache.createDerivedShaderProgram(
shaderProgram,
keyword,
{
vertexShaderSource: shaderProgram.vertexShaderSource,
fragmentShaderSource: newFragmentShaderSource,
attributeLocations: shaderProgram._attributeLocations
}
);
return newShader;
}
DerivedCommand.createPickMetadataDerivedCommand = function(scene, command, context, result) {
if (!defined_default(result)) {
result = {};
}
result.pickMetadataCommand = DrawCommand_default.shallowClone(
command,
result.pickMetadataCommand
);
result.pickMetadataCommand.shaderProgram = getPickMetadataShaderProgram(
context,
command.shaderProgram,
command.pickedMetadataInfo
);
result.pickMetadataCommand.renderState = getPickRenderState(
scene,
command.renderState
);
result.shaderProgramId = command.shaderProgram.id;
return result;
};
function getHdrShaderProgram(context, shaderProgram) {
const cachedShader = context.shaderCache.getDerivedShaderProgram(
shaderProgram,
"HDR"
);
if (defined_default(cachedShader)) {
return cachedShader;
}
const attributeLocations8 = shaderProgram._attributeLocations;
const vs = shaderProgram.vertexShaderSource.clone();
const fs = shaderProgram.fragmentShaderSource.clone();
vs.defines = defined_default(vs.defines) ? vs.defines.slice(0) : [];
vs.defines.push("HDR");
fs.defines = defined_default(fs.defines) ? fs.defines.slice(0) : [];
fs.defines.push("HDR");
return context.shaderCache.createDerivedShaderProgram(shaderProgram, "HDR", {
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations8
});
}
DerivedCommand.createHdrCommand = function(command, context, result) {
if (!defined_default(result)) {
result = {};
}
const shader = result.command?.shaderProgram;
result.command = DrawCommand_default.shallowClone(command, result.command);
if (!defined_default(shader) || result.shaderProgramId !== command.shaderProgram.id) {
result.command.shaderProgram = getHdrShaderProgram(
context,
command.shaderProgram
);
result.shaderProgramId = command.shaderProgram.id;
} else {
result.command.shaderProgram = shader;
}
return result;
};
var DerivedCommand_default = DerivedCommand;
// packages/engine/Source/Scene/DeviceOrientationCameraController.js
var import_InlineWorkers1056 = __toESM(require_InlineWorkers(), 1);
function DeviceOrientationCameraController(scene) {
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required.");
}
this._scene = scene;
this._lastAlpha = void 0;
this._lastBeta = void 0;
this._lastGamma = void 0;
this._alpha = void 0;
this._beta = void 0;
this._gamma = void 0;
const that = this;
function callback(e) {
const alpha = e.alpha;
if (!defined_default(alpha)) {
that._alpha = void 0;
that._beta = void 0;
that._gamma = void 0;
return;
}
that._alpha = Math_default.toRadians(alpha);
that._beta = Math_default.toRadians(e.beta);
that._gamma = Math_default.toRadians(e.gamma);
}
window.addEventListener("deviceorientation", callback, false);
this._removeListener = function() {
window.removeEventListener("deviceorientation", callback, false);
};
}
var scratchQuaternion1 = new Quaternion_default();
var scratchQuaternion22 = new Quaternion_default();
var scratchMatrix33 = new Matrix3_default();
function rotate2(camera, alpha, beta, gamma) {
const direction2 = camera.direction;
const right = camera.right;
const up = camera.up;
const bQuat = Quaternion_default.fromAxisAngle(direction2, beta, scratchQuaternion22);
const gQuat = Quaternion_default.fromAxisAngle(right, gamma, scratchQuaternion1);
const rotQuat = Quaternion_default.multiply(gQuat, bQuat, gQuat);
const aQuat = Quaternion_default.fromAxisAngle(up, alpha, scratchQuaternion22);
Quaternion_default.multiply(aQuat, rotQuat, rotQuat);
const matrix = Matrix3_default.fromQuaternion(rotQuat, scratchMatrix33);
Matrix3_default.multiplyByVector(matrix, right, right);
Matrix3_default.multiplyByVector(matrix, up, up);
Matrix3_default.multiplyByVector(matrix, direction2, direction2);
}
DeviceOrientationCameraController.prototype.update = function() {
if (!defined_default(this._alpha)) {
return;
}
if (!defined_default(this._lastAlpha)) {
this._lastAlpha = this._alpha;
this._lastBeta = this._beta;
this._lastGamma = this._gamma;
}
const a3 = this._lastAlpha - this._alpha;
const b = this._lastBeta - this._beta;
const g = this._lastGamma - this._gamma;
rotate2(this._scene.camera, -a3, b, g);
this._lastAlpha = this._alpha;
this._lastBeta = this._beta;
this._lastGamma = this._gamma;
};
DeviceOrientationCameraController.prototype.isDestroyed = function() {
return false;
};
DeviceOrientationCameraController.prototype.destroy = function() {
this._removeListener();
return destroyObject_default(this);
};
var DeviceOrientationCameraController_default = DeviceOrientationCameraController;
// packages/engine/Source/Scene/Fog.js
var import_InlineWorkers1057 = __toESM(require_InlineWorkers(), 1);
function Fog() {
this.enabled = true;
this.renderable = true;
this.density = 6e-4;
this.heightScalar = 1e-3;
this._heightFalloff = 0.59;
this.maxHeight = 8e5;
this.visualDensityScalar = 0.15;
this.screenSpaceErrorFactor = 2;
this.minimumBrightness = 0.03;
}
Object.defineProperties(Fog.prototype, {
/**
* Exponent factor used in the function to adjust how density changes based on the height of the camera above the ellipsoid. Smaller values produce a more gradual transition as camera height increases.
* Value must be greater than 0.
* @memberof Fog.prototype
* @type {number}
* @default 0.59
*/
heightFalloff: {
get: function() {
return this._heightFalloff;
},
set: function(value) {
if (defined_default(value) && value < 0) {
throw new DeveloperError_default("value must be positive.");
}
this._heightFalloff = value;
}
}
});
var scratchPositionNormal2 = new Cartesian3_default();
Fog.prototype.update = function(frameState) {
const enabled = frameState.fog.enabled = this.enabled;
if (!enabled) {
return;
}
frameState.fog.renderable = this.renderable;
const camera = frameState.camera;
const positionCartographic = camera.positionCartographic;
if (!defined_default(positionCartographic) || positionCartographic.height > this.maxHeight || frameState.mode !== SceneMode_default.SCENE3D) {
frameState.fog.enabled = false;
frameState.fog.density = 0;
return;
}
const height = positionCartographic.height;
let density = this.density * this.heightScalar * Math.pow(
Math.max(height / this.maxHeight, Math_default.EPSILON4),
-Math.max(this._heightFalloff, 0)
);
const positionNormal = Cartesian3_default.normalize(
camera.positionWC,
scratchPositionNormal2
);
const dot2 = Math.abs(Cartesian3_default.dot(camera.directionWC, positionNormal));
density *= 1 - dot2;
frameState.fog.density = density;
frameState.fog.visualDensityScalar = this.visualDensityScalar;
frameState.fog.sse = this.screenSpaceErrorFactor;
frameState.fog.minimumBrightness = this.minimumBrightness;
};
var Fog_default = Fog;
// packages/engine/Source/Scene/FrameState.js
var import_InlineWorkers1058 = __toESM(require_InlineWorkers(), 1);
function FrameState(context, creditDisplay, jobScheduler) {
this.context = context;
this.commandList = [];
this.shadowMaps = [];
this.brdfLutGenerator = void 0;
this.environmentMap = void 0;
this.sphericalHarmonicCoefficients = void 0;
this.specularEnvironmentMaps = void 0;
this.specularEnvironmentMapsMaximumLOD = void 0;
this.mode = SceneMode_default.SCENE3D;
this.morphTime = SceneMode_default.getMorphTime(SceneMode_default.SCENE3D);
this.frameNumber = 0;
this.newFrame = false;
this.time = void 0;
this.jobScheduler = jobScheduler;
this.mapProjection = void 0;
this.camera = void 0;
this.cameraUnderground = false;
this.globeTranslucencyState = void 0;
this.cullingVolume = void 0;
this.occluder = void 0;
this.maximumScreenSpaceError = void 0;
this.pixelRatio = 1;
this.passes = {
/**
* @default false
*/
render: false,
/**
* @default false
*/
pick: false,
/**
* @default false
*/
pickVoxel: false,
/**
* @default false
*/
depth: false,
/**
* @default false
*/
postProcess: false,
/**
* @default false
*/
offscreen: false
};
this.creditDisplay = creditDisplay;
this.afterRender = [];
this.scene3DOnly = false;
this.fog = {
/**
* @default false
*/
enabled: false,
renderable: false,
density: void 0,
visualDensityScalar: void 0,
sse: void 0,
minimumBrightness: void 0
};
this.atmosphere = void 0;
this.verticalExaggeration = 1;
this.verticalExaggerationRelativeHeight = 0;
this.shadowState = {
/**
* @default true
*/
shadowsEnabled: true,
shadowMaps: [],
lightShadowMaps: [],
/**
* @default 1.0
*/
nearPlane: 1,
/**
* @default 5000.0
*/
farPlane: 5e3,
/**
* @default 1000.0
*/
closestObjectSize: 1e3,
/**
* @default 0
*/
lastDirtyTime: 0,
/**
* @default true
*/
outOfView: true
};
this.splitPosition = 0;
this.frustumSplits = [];
this.backgroundColor = void 0;
this.light = void 0;
this.minimumDisableDepthTestDistance = void 0;
this.invertClassification = false;
this.invertClassificationColor = void 0;
this.useLogDepth = false;
this.tilesetPassState = void 0;
this.minimumTerrainHeight = 0;
this.pickingMetadata = false;
this.pickedMetadataInfo = void 0;
}
var FrameState_default = FrameState;
// packages/engine/Source/Scene/GlobeTranslucencyState.js
var import_InlineWorkers1059 = __toESM(require_InlineWorkers(), 1);
var DerivedCommandType = {
OPAQUE_FRONT_FACE: 0,
OPAQUE_BACK_FACE: 1,
DEPTH_ONLY_FRONT_FACE: 2,
DEPTH_ONLY_BACK_FACE: 3,
DEPTH_ONLY_FRONT_AND_BACK_FACE: 4,
TRANSLUCENT_FRONT_FACE: 5,
TRANSLUCENT_BACK_FACE: 6,
TRANSLUCENT_FRONT_FACE_MANUAL_DEPTH_TEST: 7,
TRANSLUCENT_BACK_FACE_MANUAL_DEPTH_TEST: 8,
PICK_FRONT_FACE: 9,
PICK_BACK_FACE: 10,
DERIVED_COMMANDS_MAXIMUM_LENGTH: 11
};
var derivedCommandsMaximumLength = DerivedCommandType.DERIVED_COMMANDS_MAXIMUM_LENGTH;
var DerivedCommandNames = [
"opaqueFrontFaceCommand",
"opaqueBackFaceCommand",
"depthOnlyFrontFaceCommand",
"depthOnlyBackFaceCommand",
"depthOnlyFrontAndBackFaceCommand",
"translucentFrontFaceCommand",
"translucentBackFaceCommand",
"translucentFrontFaceManualDepthTestCommand",
"translucentBackFaceManualDepthTestCommand",
"pickFrontFaceCommand",
"pickBackFaceCommand"
];
function GlobeTranslucencyState() {
this._frontFaceAlphaByDistance = new NearFarScalar_default(0, 1, 0, 1);
this._backFaceAlphaByDistance = new NearFarScalar_default(0, 1, 0, 1);
this._frontFaceTranslucent = false;
this._backFaceTranslucent = false;
this._requiresManualDepthTest = false;
this._sunVisibleThroughGlobe = false;
this._environmentVisible = false;
this._useDepthPlane = false;
this._numberOfTextureUniforms = 0;
this._globeTranslucencyFramebuffer = void 0;
this._rectangle = Rectangle_default.clone(Rectangle_default.MAX_VALUE);
this._derivedCommandKey = 0;
this._derivedCommandsDirty = false;
this._derivedCommandPacks = void 0;
this._derivedCommandTypes = new Array(derivedCommandsMaximumLength);
this._derivedBlendCommandTypes = new Array(derivedCommandsMaximumLength);
this._derivedPickCommandTypes = new Array(derivedCommandsMaximumLength);
this._derivedCommandTypesToUpdate = new Array(derivedCommandsMaximumLength);
this._derivedCommandsLength = 0;
this._derivedBlendCommandsLength = 0;
this._derivedPickCommandsLength = 0;
this._derivedCommandsToUpdateLength = 0;
}
Object.defineProperties(GlobeTranslucencyState.prototype, {
frontFaceAlphaByDistance: {
get: function() {
return this._frontFaceAlphaByDistance;
}
},
backFaceAlphaByDistance: {
get: function() {
return this._backFaceAlphaByDistance;
}
},
translucent: {
get: function() {
return this._frontFaceTranslucent;
}
},
sunVisibleThroughGlobe: {
get: function() {
return this._sunVisibleThroughGlobe;
}
},
environmentVisible: {
get: function() {
return this._environmentVisible;
}
},
useDepthPlane: {
get: function() {
return this._useDepthPlane;
}
},
numberOfTextureUniforms: {
get: function() {
return this._numberOfTextureUniforms;
}
},
rectangle: {
get: function() {
return this._rectangle;
}
}
});
GlobeTranslucencyState.prototype.update = function(scene) {
const globe = scene.globe;
if (!defined_default(globe) || !globe.show) {
this._frontFaceTranslucent = false;
this._backFaceTranslucent = false;
this._sunVisibleThroughGlobe = true;
this._environmentVisible = true;
this._useDepthPlane = false;
return;
}
this._frontFaceAlphaByDistance = updateAlphaByDistance(
globe.translucency.enabled,
globe.translucency.frontFaceAlpha,
globe.translucency.frontFaceAlphaByDistance,
this._frontFaceAlphaByDistance
);
this._backFaceAlphaByDistance = updateAlphaByDistance(
globe.translucency.enabled,
globe.translucency.backFaceAlpha,
globe.translucency.backFaceAlphaByDistance,
this._backFaceAlphaByDistance
);
this._frontFaceTranslucent = isFaceTranslucent(
globe.translucency.enabled,
this._frontFaceAlphaByDistance,
globe
);
this._backFaceTranslucent = isFaceTranslucent(
globe.translucency.enabled,
this._backFaceAlphaByDistance,
globe
);
this._requiresManualDepthTest = requiresManualDepthTest(this, scene, globe);
this._sunVisibleThroughGlobe = isSunVisibleThroughGlobe(this, scene);
this._environmentVisible = isEnvironmentVisible(this, scene);
this._useDepthPlane = useDepthPlane(this, scene);
this._numberOfTextureUniforms = getNumberOfTextureUniforms(this);
this._rectangle = Rectangle_default.clone(
globe.translucency.rectangle,
this._rectangle
);
gatherDerivedCommandRequirements(this, scene);
};
function updateAlphaByDistance(enabled, alpha, alphaByDistance, result) {
if (!enabled) {
result.nearValue = 1;
result.farValue = 1;
return result;
}
if (!defined_default(alphaByDistance)) {
result.nearValue = alpha;
result.farValue = alpha;
return result;
}
NearFarScalar_default.clone(alphaByDistance, result);
result.nearValue *= alpha;
result.farValue *= alpha;
return result;
}
function isFaceTranslucent(translucencyEnabled, alphaByDistance, globe) {
return translucencyEnabled && (globe.baseColor.alpha < 1 || alphaByDistance.nearValue < 1 || alphaByDistance.farValue < 1);
}
function isSunVisibleThroughGlobe(state, scene) {
const frontTranslucent = state._frontFaceTranslucent;
const backTranslucent = state._backFaceTranslucent;
return frontTranslucent && (scene.cameraUnderground || backTranslucent);
}
function isEnvironmentVisible(state, scene) {
return !scene.cameraUnderground || state._frontFaceTranslucent;
}
function useDepthPlane(state, scene) {
return !scene.cameraUnderground && !state._frontFaceTranslucent;
}
function requiresManualDepthTest(state, scene, globe) {
return state._frontFaceTranslucent && !state._backFaceTranslucent && !globe.depthTestAgainstTerrain && scene.mode !== SceneMode_default.SCENE2D && scene.context.depthTexture;
}
function getNumberOfTextureUniforms(state) {
let numberOfTextureUniforms = 0;
if (state._frontFaceTranslucent) {
++numberOfTextureUniforms;
}
if (state._requiresManualDepthTest) {
++numberOfTextureUniforms;
}
return numberOfTextureUniforms;
}
function gatherDerivedCommandRequirements(state, scene) {
state._derivedCommandsLength = getDerivedCommandTypes(
state,
scene,
false,
false,
state._derivedCommandTypes
);
state._derivedBlendCommandsLength = getDerivedCommandTypes(
state,
scene,
true,
false,
state._derivedBlendCommandTypes
);
state._derivedPickCommandsLength = getDerivedCommandTypes(
state,
scene,
false,
true,
state._derivedPickCommandTypes
);
let i;
let derivedCommandKey = 0;
for (i = 0; i < state._derivedCommandsLength; ++i) {
derivedCommandKey |= 1 << state._derivedCommandTypes[i];
}
for (i = 0; i < state._derivedBlendCommandsLength; ++i) {
derivedCommandKey |= 1 << state._derivedBlendCommandTypes[i];
}
for (i = 0; i < state._derivedPickCommandsLength; ++i) {
derivedCommandKey |= 1 << state._derivedPickCommandTypes[i];
}
let derivedCommandsToUpdateLength = 0;
for (i = 0; i < derivedCommandsMaximumLength; ++i) {
if ((derivedCommandKey & 1 << i) > 0) {
state._derivedCommandTypesToUpdate[derivedCommandsToUpdateLength++] = i;
}
}
state._derivedCommandsToUpdateLength = derivedCommandsToUpdateLength;
const derivedCommandsDirty = derivedCommandKey !== state._derivedCommandKey;
state._derivedCommandKey = derivedCommandKey;
state._derivedCommandsDirty = derivedCommandsDirty;
if (!defined_default(state._derivedCommandPacks) && state._frontFaceTranslucent) {
state._derivedCommandPacks = createDerivedCommandPacks();
}
}
function getDerivedCommandTypes(state, scene, isBlendCommand, isPickCommand, types) {
let length2 = 0;
const frontTranslucent = state._frontFaceTranslucent;
const backTranslucent = state._backFaceTranslucent;
if (!frontTranslucent) {
return length2;
}
const cameraUnderground = scene.cameraUnderground;
const requiresManualDepthTest2 = state._requiresManualDepthTest;
const translucentFrontFaceCommandType = isPickCommand ? DerivedCommandType.PICK_FRONT_FACE : requiresManualDepthTest2 ? DerivedCommandType.TRANSLUCENT_FRONT_FACE_MANUAL_DEPTH_TEST : DerivedCommandType.TRANSLUCENT_FRONT_FACE;
const translucentBackFaceCommandType = isPickCommand ? DerivedCommandType.PICK_BACK_FACE : requiresManualDepthTest2 ? DerivedCommandType.TRANSLUCENT_BACK_FACE_MANUAL_DEPTH_TEST : DerivedCommandType.TRANSLUCENT_BACK_FACE;
if (scene.mode === SceneMode_default.SCENE2D) {
types[length2++] = DerivedCommandType.DEPTH_ONLY_FRONT_FACE;
types[length2++] = translucentFrontFaceCommandType;
return length2;
}
if (backTranslucent) {
if (!isBlendCommand) {
types[length2++] = DerivedCommandType.DEPTH_ONLY_FRONT_AND_BACK_FACE;
}
if (cameraUnderground) {
types[length2++] = translucentFrontFaceCommandType;
types[length2++] = translucentBackFaceCommandType;
} else {
types[length2++] = translucentBackFaceCommandType;
types[length2++] = translucentFrontFaceCommandType;
}
} else {
if (cameraUnderground) {
if (!isBlendCommand) {
types[length2++] = DerivedCommandType.DEPTH_ONLY_BACK_FACE;
}
types[length2++] = DerivedCommandType.OPAQUE_FRONT_FACE;
types[length2++] = translucentBackFaceCommandType;
} else {
if (!isBlendCommand) {
types[length2++] = DerivedCommandType.DEPTH_ONLY_FRONT_FACE;
}
types[length2++] = DerivedCommandType.OPAQUE_BACK_FACE;
types[length2++] = translucentFrontFaceCommandType;
}
}
return length2;
}
function removeDefine(defines, defineToRemove) {
const index = defines.indexOf(defineToRemove);
if (index > -1) {
defines.splice(index, 1);
}
}
function hasDefine(defines, define2) {
return defines.indexOf(define2) > -1;
}
function getOpaqueFrontFaceShaderProgram(vs, fs) {
removeDefine(vs.defines, "TRANSLUCENT");
removeDefine(fs.defines, "TRANSLUCENT");
}
function getOpaqueBackFaceShaderProgram(vs, fs) {
removeDefine(vs.defines, "GROUND_ATMOSPHERE");
removeDefine(fs.defines, "GROUND_ATMOSPHERE");
removeDefine(vs.defines, "FOG");
removeDefine(fs.defines, "FOG");
removeDefine(vs.defines, "TRANSLUCENT");
removeDefine(fs.defines, "TRANSLUCENT");
}
function getDepthOnlyShaderProgram2(vs, fs) {
if (hasDefine(fs.defines, "TILE_LIMIT_RECTANGLE") || hasDefine(fs.defines, "ENABLE_CLIPPING_PLANES")) {
return;
}
const depthOnlyShader = "void main() \n{ \n out_FragColor = vec4(1.0); \n} \n";
fs.sources = [depthOnlyShader];
}
function getTranslucentShaderProgram(vs, fs) {
const sources = fs.sources;
const length2 = sources.length;
for (let i = 0; i < length2; ++i) {
sources[i] = ShaderSource_default.replaceMain(
sources[i],
"czm_globe_translucency_main"
);
}
const globeTranslucencyMain = "\n\nuniform sampler2D u_classificationTexture; \nvoid main() \n{ \n vec2 st = gl_FragCoord.xy / czm_viewport.zw; \n#ifdef MANUAL_DEPTH_TEST \n float logDepthOrDepth = czm_unpackDepth(texture(czm_globeDepthTexture, st)); \n if (logDepthOrDepth != 0.0) \n { \n vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth); \n float depthEC = eyeCoordinate.z / eyeCoordinate.w; \n if (v_positionEC.z < depthEC) \n { \n discard; \n } \n } \n#endif \n czm_globe_translucency_main(); \n vec4 classificationColor = texture(u_classificationTexture, st); \n if (classificationColor.a > 0.0) \n { \n // Reverse premultiplication process to get the correct composited result of the classification primitives \n classificationColor.rgb /= classificationColor.a; \n } \n out_FragColor = classificationColor * vec4(classificationColor.aaa, 1.0) + out_FragColor * (1.0 - classificationColor.a); \n} \n";
sources.push(globeTranslucencyMain);
}
function getTranslucentBackFaceShaderProgram(vs, fs) {
getTranslucentShaderProgram(vs, fs);
removeDefine(vs.defines, "GROUND_ATMOSPHERE");
removeDefine(fs.defines, "GROUND_ATMOSPHERE");
removeDefine(vs.defines, "FOG");
removeDefine(fs.defines, "FOG");
}
function getTranslucentFrontFaceManualDepthTestShaderProgram(vs, fs) {
getTranslucentShaderProgram(vs, fs);
vs.defines.push("GENERATE_POSITION");
fs.defines.push("MANUAL_DEPTH_TEST");
}
function getTranslucentBackFaceManualDepthTestShaderProgram(vs, fs) {
getTranslucentBackFaceShaderProgram(vs, fs);
vs.defines.push("GENERATE_POSITION");
fs.defines.push("MANUAL_DEPTH_TEST");
}
function getPickShaderProgram2(vs, fs) {
const pickShader = "uniform sampler2D u_classificationTexture; \nvoid main() \n{ \n vec2 st = gl_FragCoord.xy / czm_viewport.zw; \n vec4 pickColor = texture(u_classificationTexture, st); \n if (pickColor == vec4(0.0)) \n { \n discard; \n } \n out_FragColor = pickColor; \n} \n";
fs.sources = [pickShader];
}
function getDerivedShaderProgram(context, shaderProgram, derivedShaderProgram, shaderProgramDirty, getShaderProgramFunction, cacheName) {
if (!defined_default(getShaderProgramFunction)) {
return shaderProgram;
}
if (!shaderProgramDirty && defined_default(derivedShaderProgram)) {
return derivedShaderProgram;
}
let shader = context.shaderCache.getDerivedShaderProgram(
shaderProgram,
cacheName
);
if (!defined_default(shader)) {
const attributeLocations8 = shaderProgram._attributeLocations;
const vs = shaderProgram.vertexShaderSource.clone();
const fs = shaderProgram.fragmentShaderSource.clone();
vs.defines = defined_default(vs.defines) ? vs.defines.slice(0) : [];
fs.defines = defined_default(fs.defines) ? fs.defines.slice(0) : [];
getShaderProgramFunction(vs, fs);
shader = context.shaderCache.createDerivedShaderProgram(
shaderProgram,
cacheName,
{
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations8
}
);
}
return shader;
}
function getOpaqueFrontFaceRenderState(renderState) {
renderState.cull.face = CullFace_default.BACK;
renderState.cull.enabled = true;
}
function getOpaqueBackFaceRenderState(renderState) {
renderState.cull.face = CullFace_default.FRONT;
renderState.cull.enabled = true;
}
function getDepthOnlyFrontFaceRenderState(renderState) {
renderState.cull.face = CullFace_default.BACK;
renderState.cull.enabled = true;
renderState.colorMask = {
red: false,
green: false,
blue: false,
alpha: false
};
}
function getDepthOnlyBackFaceRenderState(renderState) {
renderState.cull.face = CullFace_default.FRONT;
renderState.cull.enabled = true;
renderState.colorMask = {
red: false,
green: false,
blue: false,
alpha: false
};
}
function getDepthOnlyFrontAndBackFaceRenderState(renderState) {
renderState.cull.enabled = false;
renderState.colorMask = {
red: false,
green: false,
blue: false,
alpha: false
};
}
function getTranslucentFrontFaceRenderState(renderState) {
renderState.cull.face = CullFace_default.BACK;
renderState.cull.enabled = true;
renderState.depthMask = false;
renderState.blending = BlendingState_default.ALPHA_BLEND;
}
function getTranslucentBackFaceRenderState(renderState) {
renderState.cull.face = CullFace_default.FRONT;
renderState.cull.enabled = true;
renderState.depthMask = false;
renderState.blending = BlendingState_default.ALPHA_BLEND;
}
function getPickFrontFaceRenderState(renderState) {
renderState.cull.face = CullFace_default.BACK;
renderState.cull.enabled = true;
renderState.blending.enabled = false;
}
function getPickBackFaceRenderState(renderState) {
renderState.cull.face = CullFace_default.FRONT;
renderState.cull.enabled = true;
renderState.blending.enabled = false;
}
function getDerivedRenderState(renderState, derivedRenderState, renderStateDirty, getRenderStateFunction, cache) {
if (!defined_default(getRenderStateFunction)) {
return renderState;
}
if (!renderStateDirty && defined_default(derivedRenderState)) {
return derivedRenderState;
}
let cachedRenderState = cache[renderState.id];
if (!defined_default(cachedRenderState)) {
const rs = RenderState_default.getState(renderState);
getRenderStateFunction(rs);
cachedRenderState = RenderState_default.fromCache(rs);
cache[renderState.id] = cachedRenderState;
}
return cachedRenderState;
}
function getTranslucencyUniformMap(state) {
return {
u_classificationTexture: function() {
return state._globeTranslucencyFramebuffer.classificationTexture;
}
};
}
function getDerivedUniformMap(state, uniformMap2, derivedUniformMap, uniformMapDirty, getDerivedUniformMapFunction) {
if (!defined_default(getDerivedUniformMapFunction)) {
return uniformMap2;
}
if (!uniformMapDirty && defined_default(derivedUniformMap)) {
return derivedUniformMap;
}
return combine_default(uniformMap2, getDerivedUniformMapFunction(state), false);
}
function DerivedCommandPack(options) {
this.pass = options.pass;
this.pickOnly = options.pickOnly;
this.getShaderProgramFunction = options.getShaderProgramFunction;
this.getRenderStateFunction = options.getRenderStateFunction;
this.getUniformMapFunction = options.getUniformMapFunction;
this.renderStateCache = {};
}
function createDerivedCommandPacks() {
return [
// opaqueFrontFaceCommand
new DerivedCommandPack({
pass: Pass_default.GLOBE,
pickOnly: false,
getShaderProgramFunction: getOpaqueFrontFaceShaderProgram,
getRenderStateFunction: getOpaqueFrontFaceRenderState,
getUniformMapFunction: void 0
}),
// opaqueBackFaceCommand
new DerivedCommandPack({
pass: Pass_default.GLOBE,
pickOnly: false,
getShaderProgramFunction: getOpaqueBackFaceShaderProgram,
getRenderStateFunction: getOpaqueBackFaceRenderState,
getUniformMapFunction: void 0
}),
// depthOnlyFrontFaceCommand
new DerivedCommandPack({
pass: Pass_default.GLOBE,
pickOnly: false,
getShaderProgramFunction: getDepthOnlyShaderProgram2,
getRenderStateFunction: getDepthOnlyFrontFaceRenderState,
getUniformMapFunction: void 0
}),
// depthOnlyBackFaceCommand
new DerivedCommandPack({
pass: Pass_default.GLOBE,
pickOnly: false,
getShaderProgramFunction: getDepthOnlyShaderProgram2,
getRenderStateFunction: getDepthOnlyBackFaceRenderState,
getUniformMapFunction: void 0
}),
// depthOnlyFrontAndBackFaceCommand
new DerivedCommandPack({
pass: Pass_default.GLOBE,
pickOnly: false,
getShaderProgramFunction: getDepthOnlyShaderProgram2,
getRenderStateFunction: getDepthOnlyFrontAndBackFaceRenderState,
getUniformMapFunction: void 0
}),
// translucentFrontFaceCommand
new DerivedCommandPack({
pass: Pass_default.TRANSLUCENT,
pickOnly: false,
getShaderProgramFunction: getTranslucentShaderProgram,
getRenderStateFunction: getTranslucentFrontFaceRenderState,
getUniformMapFunction: getTranslucencyUniformMap
}),
// translucentBackFaceCommand
new DerivedCommandPack({
pass: Pass_default.TRANSLUCENT,
pickOnly: false,
getShaderProgramFunction: getTranslucentBackFaceShaderProgram,
getRenderStateFunction: getTranslucentBackFaceRenderState,
getUniformMapFunction: getTranslucencyUniformMap
}),
// translucentFrontFaceManualDepthTestCommand
new DerivedCommandPack({
pass: Pass_default.TRANSLUCENT,
pickOnly: false,
getShaderProgramFunction: getTranslucentFrontFaceManualDepthTestShaderProgram,
getRenderStateFunction: getTranslucentFrontFaceRenderState,
getUniformMapFunction: getTranslucencyUniformMap
}),
// translucentBackFaceManualDepthTestCommand
new DerivedCommandPack({
pass: Pass_default.TRANSLUCENT,
pickOnly: false,
getShaderProgramFunction: getTranslucentBackFaceManualDepthTestShaderProgram,
getRenderStateFunction: getTranslucentBackFaceRenderState,
getUniformMapFunction: getTranslucencyUniformMap
}),
// pickFrontFaceCommand
new DerivedCommandPack({
pass: Pass_default.TRANSLUCENT,
pickOnly: true,
getShaderProgramFunction: getPickShaderProgram2,
getRenderStateFunction: getPickFrontFaceRenderState,
getUniformMapFunction: getTranslucencyUniformMap
}),
// pickBackFaceCommand
new DerivedCommandPack({
pass: Pass_default.TRANSLUCENT,
pickOnly: true,
getShaderProgramFunction: getPickShaderProgram2,
getRenderStateFunction: getPickBackFaceRenderState,
getUniformMapFunction: getTranslucencyUniformMap
})
];
}
var derivedCommandNames = new Array(derivedCommandsMaximumLength);
var derivedCommandPacks = new Array(derivedCommandsMaximumLength);
GlobeTranslucencyState.prototype.updateDerivedCommands = function(command, frameState) {
const derivedCommandTypes = this._derivedCommandTypesToUpdate;
const derivedCommandsLength = this._derivedCommandsToUpdateLength;
if (derivedCommandsLength === 0) {
return;
}
for (let i = 0; i < derivedCommandsLength; ++i) {
derivedCommandPacks[i] = this._derivedCommandPacks[derivedCommandTypes[i]];
derivedCommandNames[i] = DerivedCommandNames[derivedCommandTypes[i]];
}
updateDerivedCommands(
this,
command,
derivedCommandsLength,
derivedCommandTypes,
derivedCommandNames,
derivedCommandPacks,
frameState
);
};
function updateDerivedCommands(state, command, derivedCommandsLength, derivedCommandTypes, derivedCommandNames2, derivedCommandPacks2, frameState) {
let derivedCommandsObject = command.derivedCommands.globeTranslucency;
const derivedCommandsDirty = state._derivedCommandsDirty;
if (command.dirty || !defined_default(derivedCommandsObject) || derivedCommandsDirty) {
command.dirty = false;
if (!defined_default(derivedCommandsObject)) {
derivedCommandsObject = {};
command.derivedCommands.globeTranslucency = derivedCommandsObject;
}
const frameNumber = frameState.frameNumber;
const uniformMapDirtyFrame = derivedCommandsObject.uniformMapDirtyFrame ?? 0;
const shaderProgramDirtyFrame = derivedCommandsObject.shaderProgramDirtyFrame ?? 0;
const renderStateDirtyFrame = derivedCommandsObject.renderStateDirtyFrame ?? 0;
const uniformMapDirty = derivedCommandsObject.uniformMap !== command.uniformMap;
const shaderProgramDirty = derivedCommandsObject.shaderProgramId !== command.shaderProgram.id;
const renderStateDirty = derivedCommandsObject.renderStateId !== command.renderState.id;
if (uniformMapDirty) {
derivedCommandsObject.uniformMapDirtyFrame = frameNumber;
}
if (shaderProgramDirty) {
derivedCommandsObject.shaderProgramDirtyFrame = frameNumber;
}
if (renderStateDirty) {
derivedCommandsObject.renderStateDirtyFrame = frameNumber;
}
derivedCommandsObject.uniformMap = command.uniformMap;
derivedCommandsObject.shaderProgramId = command.shaderProgram.id;
derivedCommandsObject.renderStateId = command.renderState.id;
for (let i = 0; i < derivedCommandsLength; ++i) {
const derivedCommandPack = derivedCommandPacks2[i];
const derivedCommandType = derivedCommandTypes[i];
const derivedCommandName = derivedCommandNames2[i];
let derivedCommand = derivedCommandsObject[derivedCommandName];
let derivedUniformMap;
let derivedShaderProgram;
let derivedRenderState;
if (defined_default(derivedCommand)) {
derivedUniformMap = derivedCommand.uniformMap;
derivedShaderProgram = derivedCommand.shaderProgram;
derivedRenderState = derivedCommand.renderState;
} else {
derivedUniformMap = void 0;
derivedShaderProgram = void 0;
derivedRenderState = void 0;
}
derivedCommand = DrawCommand_default.shallowClone(command, derivedCommand);
derivedCommandsObject[derivedCommandName] = derivedCommand;
const derivedUniformMapDirtyFrame = derivedCommand.derivedCommands.uniformMapDirtyFrame ?? 0;
const derivedShaderProgramDirtyFrame = derivedCommand.derivedCommands.shaderProgramDirtyFrame ?? 0;
const derivedRenderStateDirtyFrame = derivedCommand.derivedCommands.renderStateDirtyFrame ?? 0;
const derivedUniformMapDirty = uniformMapDirty || derivedUniformMapDirtyFrame < uniformMapDirtyFrame;
const derivedShaderProgramDirty = shaderProgramDirty || derivedShaderProgramDirtyFrame < shaderProgramDirtyFrame;
const derivedRenderStateDirty = renderStateDirty || derivedRenderStateDirtyFrame < renderStateDirtyFrame;
if (derivedUniformMapDirty) {
derivedCommand.derivedCommands.uniformMapDirtyFrame = frameNumber;
}
if (derivedShaderProgramDirty) {
derivedCommand.derivedCommands.shaderProgramDirtyFrame = frameNumber;
}
if (derivedRenderStateDirty) {
derivedCommand.derivedCommands.renderStateDirtyFrame = frameNumber;
}
derivedCommand.derivedCommands.type = derivedCommandType;
derivedCommand.pass = derivedCommandPack.pass;
derivedCommand.pickOnly = derivedCommandPack.pickOnly;
derivedCommand.uniformMap = getDerivedUniformMap(
state,
command.uniformMap,
derivedUniformMap,
derivedUniformMapDirty,
derivedCommandPack.getUniformMapFunction
);
derivedCommand.shaderProgram = getDerivedShaderProgram(
frameState.context,
command.shaderProgram,
derivedShaderProgram,
derivedShaderProgramDirty,
derivedCommandPack.getShaderProgramFunction,
derivedCommandName
);
derivedCommand.renderState = getDerivedRenderState(
command.renderState,
derivedRenderState,
derivedRenderStateDirty,
derivedCommandPack.getRenderStateFunction,
derivedCommandPack.renderStateCache
);
}
}
}
GlobeTranslucencyState.prototype.pushDerivedCommands = function(command, isBlendCommand, frameState) {
const picking = frameState.passes.pick || frameState.passes.pickVoxel;
if (picking && isBlendCommand) {
return;
}
let derivedCommandTypes = this._derivedCommandTypes;
let derivedCommandsLength = this._derivedCommandsLength;
if (picking) {
derivedCommandTypes = this._derivedPickCommandTypes;
derivedCommandsLength = this._derivedPickCommandsLength;
} else if (isBlendCommand) {
derivedCommandTypes = this._derivedBlendCommandTypes;
derivedCommandsLength = this._derivedBlendCommandsLength;
}
if (derivedCommandsLength === 0) {
frameState.commandList.push(command);
return;
}
const derivedCommands = command.derivedCommands.globeTranslucency;
for (let i = 0; i < derivedCommandsLength; ++i) {
const derivedCommandName = DerivedCommandNames[derivedCommandTypes[i]];
frameState.commandList.push(derivedCommands[derivedCommandName]);
}
};
function executeCommandsMatchingType(commands, commandsLength, executeCommandFunction, scene, passState, types) {
for (let i = 0; i < commandsLength; ++i) {
const command = commands[i];
const type = command.derivedCommands.type;
if (!defined_default(types) || types.indexOf(type) > -1) {
executeCommandFunction(command, scene, passState);
}
}
}
function executeCommands(commands, commandsLength, executeCommandFunction, scene, passState) {
for (let i = 0; i < commandsLength; ++i) {
executeCommandFunction(commands[i], scene, passState);
}
}
var opaqueTypes = [
DerivedCommandType.OPAQUE_FRONT_FACE,
DerivedCommandType.OPAQUE_BACK_FACE
];
var depthOnlyTypes = [
DerivedCommandType.DEPTH_ONLY_FRONT_FACE,
DerivedCommandType.DEPTH_ONLY_BACK_FACE,
DerivedCommandType.DEPTH_ONLY_FRONT_AND_BACK_FACE
];
GlobeTranslucencyState.prototype.executeGlobeCommands = function(frustumCommands, executeCommandFunction, globeTranslucencyFramebuffer, scene, passState) {
const context = scene.context;
const globeCommands = frustumCommands.commands[Pass_default.GLOBE];
const globeCommandsLength = frustumCommands.indices[Pass_default.GLOBE];
if (globeCommandsLength === 0) {
return;
}
this._globeTranslucencyFramebuffer = globeTranslucencyFramebuffer;
globeTranslucencyFramebuffer.clearClassification(context, passState);
executeCommandsMatchingType(
globeCommands,
globeCommandsLength,
executeCommandFunction,
scene,
passState,
opaqueTypes
);
};
GlobeTranslucencyState.prototype.executeGlobeClassificationCommands = function(frustumCommands, executeCommandFunction, globeTranslucencyFramebuffer, scene, passState) {
const { context } = scene;
const { uniformState } = context;
const globeCommands = frustumCommands.commands[Pass_default.GLOBE];
const globeCommandsLength = frustumCommands.indices[Pass_default.GLOBE];
const classificationCommands = frustumCommands.commands[Pass_default.TERRAIN_CLASSIFICATION];
const classificationCommandsLength = frustumCommands.indices[Pass_default.TERRAIN_CLASSIFICATION];
if (globeCommandsLength === 0 || classificationCommandsLength === 0) {
return;
}
const frontTranslucent = this._frontFaceTranslucent;
const backTranslucent = this._backFaceTranslucent;
if (!frontTranslucent || !backTranslucent) {
executeCommands(
classificationCommands,
classificationCommandsLength,
executeCommandFunction,
scene,
passState
);
}
if (!frontTranslucent && !backTranslucent) {
return;
}
this._globeTranslucencyFramebuffer = globeTranslucencyFramebuffer;
const originalGlobeDepthTexture = uniformState.globeDepthTexture;
const originalFramebuffer = passState.framebuffer;
passState.framebuffer = globeTranslucencyFramebuffer.classificationFramebuffer;
executeCommandsMatchingType(
globeCommands,
globeCommandsLength,
executeCommandFunction,
scene,
passState,
depthOnlyTypes
);
if (context.depthTexture) {
const packedDepthTexture = globeTranslucencyFramebuffer.packDepth(
context,
passState
);
uniformState.globeDepthTexture = packedDepthTexture;
}
executeCommands(
classificationCommands,
classificationCommandsLength,
executeCommandFunction,
scene,
passState
);
uniformState.globeDepthTexture = originalGlobeDepthTexture;
passState.framebuffer = originalFramebuffer;
};
var GlobeTranslucencyState_default = GlobeTranslucencyState;
// packages/engine/Source/Scene/InvertClassification.js
var import_InlineWorkers1061 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/PostProcessStages/PassThrough.js
var import_InlineWorkers1060 = __toESM(require_InlineWorkers(), 1);
var PassThrough_default = "uniform sampler2D colorTexture;\n\nin vec2 v_textureCoordinates;\n\nvoid main()\n{\n out_FragColor = texture(colorTexture, v_textureCoordinates);\n}\n";
// packages/engine/Source/Scene/InvertClassification.js
function InvertClassification() {
this._numSamples = 1;
this.previousFramebuffer = void 0;
this._previousFramebuffer = void 0;
this._depthStencilTexture = void 0;
this._depthStencilRenderbuffer = void 0;
this._fbo = new FramebufferManager_default({
depthStencil: true,
createDepthAttachments: false
});
this._fboClassified = new FramebufferManager_default({
depthStencil: true,
createDepthAttachments: false
});
this._rsUnclassified = void 0;
this._rsClassified = void 0;
this._unclassifiedCommand = void 0;
this._classifiedCommand = void 0;
this._translucentCommand = void 0;
this._clearColorCommand = new ClearCommand_default({
color: new Color_default(0, 0, 0, 0),
owner: this
});
this._clearCommand = new ClearCommand_default({
color: new Color_default(0, 0, 0, 0),
depth: 1,
stencil: 0
});
const that = this;
this._uniformMap = {
colorTexture: function() {
return that._fbo.getColorTexture();
},
depthTexture: function() {
return that._depthStencilTexture;
},
classifiedTexture: function() {
return that._fboClassified.getColorTexture();
}
};
}
Object.defineProperties(InvertClassification.prototype, {
unclassifiedCommand: {
get: function() {
return this._unclassifiedCommand;
}
}
});
InvertClassification.isTranslucencySupported = function(context) {
return context.depthTexture && context.fragmentDepth;
};
var rsUnclassified = {
depthMask: false,
stencilTest: {
enabled: true,
frontFunction: StencilFunction_default.EQUAL,
frontOperation: {
fail: StencilOperation_default.KEEP,
zFail: StencilOperation_default.KEEP,
zPass: StencilOperation_default.KEEP
},
backFunction: StencilFunction_default.NEVER,
reference: 0,
mask: StencilConstants_default.CLASSIFICATION_MASK
},
blending: BlendingState_default.ALPHA_BLEND
};
var rsClassified = {
depthMask: false,
stencilTest: {
enabled: true,
frontFunction: StencilFunction_default.NOT_EQUAL,
frontOperation: {
fail: StencilOperation_default.KEEP,
zFail: StencilOperation_default.KEEP,
zPass: StencilOperation_default.KEEP
},
backFunction: StencilFunction_default.NEVER,
reference: 0,
mask: StencilConstants_default.CLASSIFICATION_MASK
},
blending: BlendingState_default.ALPHA_BLEND
};
var rsDefault = {
depthMask: true,
depthTest: {
enabled: true
},
stencilTest: StencilConstants_default.setCesium3DTileBit(),
stencilMask: StencilConstants_default.CESIUM_3D_TILE_MASK,
blending: BlendingState_default.ALPHA_BLEND
};
var translucentFS = "uniform sampler2D colorTexture;\nuniform sampler2D depthTexture;\nuniform sampler2D classifiedTexture;\nin vec2 v_textureCoordinates;\nvoid main()\n{\n vec4 color = texture(colorTexture, v_textureCoordinates);\n if (color.a == 0.0)\n {\n discard;\n }\n bool isClassified = all(equal(texture(classifiedTexture, v_textureCoordinates), vec4(0.0)));\n#ifdef UNCLASSIFIED\n vec4 highlightColor = czm_invertClassificationColor;\n if (isClassified)\n {\n discard;\n }\n#else\n vec4 highlightColor = vec4(1.0);\n if (!isClassified)\n {\n discard;\n }\n#endif\n out_FragColor = color * highlightColor;\n gl_FragDepth = texture(depthTexture, v_textureCoordinates).r;\n}\n";
var opaqueFS = "uniform sampler2D colorTexture;\nin vec2 v_textureCoordinates;\nvoid main()\n{\n vec4 color = texture(colorTexture, v_textureCoordinates);\n if (color.a == 0.0)\n {\n discard;\n }\n#ifdef UNCLASSIFIED\n out_FragColor = color * czm_invertClassificationColor;\n#else\n out_FragColor = color;\n#endif\n}\n";
InvertClassification.prototype.update = function(context, numSamples, globeFramebuffer) {
const texture = this._fbo.getColorTexture();
const previousFramebufferChanged = this.previousFramebuffer !== this._previousFramebuffer;
this._previousFramebuffer = this.previousFramebuffer;
const samplesChanged = this._numSamples !== numSamples;
const width = context.drawingBufferWidth;
const height = context.drawingBufferHeight;
const textureChanged = !defined_default(texture) || texture.width !== width || texture.height !== height;
if (textureChanged || previousFramebufferChanged || samplesChanged) {
this._numSamples = numSamples;
this._depthStencilTexture = this._depthStencilTexture && this._depthStencilTexture.destroy();
this._depthStencilRenderbuffer = this._depthStencilRenderbuffer && this._depthStencilRenderbuffer.destroy();
if (!defined_default(this._previousFramebuffer)) {
this._depthStencilTexture = new Texture_default({
context,
width,
height,
pixelFormat: PixelFormat_default.DEPTH_STENCIL,
pixelDatatype: PixelDatatype_default.UNSIGNED_INT_24_8
});
if (numSamples > 1) {
this._depthStencilRenderbuffer = new Renderbuffer_default({
context,
width,
height,
format: RenderbufferFormat_default.DEPTH24_STENCIL8,
numSamples
});
}
}
}
if (!defined_default(this._fbo.framebuffer) || textureChanged || previousFramebufferChanged || samplesChanged) {
this._fbo.destroy();
this._fboClassified.destroy();
let depthStencilTexture;
let depthStencilRenderbuffer;
if (defined_default(this._previousFramebuffer)) {
depthStencilTexture = globeFramebuffer.getDepthStencilTexture();
depthStencilRenderbuffer = globeFramebuffer.getDepthStencilRenderbuffer();
} else {
depthStencilTexture = this._depthStencilTexture;
depthStencilRenderbuffer = this._depthStencilRenderbuffer;
}
this._fbo.setDepthStencilTexture(depthStencilTexture);
if (defined_default(depthStencilRenderbuffer)) {
this._fbo.setDepthStencilRenderbuffer(depthStencilRenderbuffer);
}
this._fbo.update(context, width, height, numSamples);
if (!defined_default(this._previousFramebuffer)) {
this._fboClassified.setDepthStencilTexture(depthStencilTexture);
this._fboClassified.update(context, width, height);
}
}
if (!defined_default(this._rsUnclassified)) {
this._rsUnclassified = RenderState_default.fromCache(rsUnclassified);
this._rsClassified = RenderState_default.fromCache(rsClassified);
this._rsDefault = RenderState_default.fromCache(rsDefault);
}
if (!defined_default(this._unclassifiedCommand) || previousFramebufferChanged || samplesChanged) {
if (defined_default(this._unclassifiedCommand)) {
this._unclassifiedCommand.shaderProgram = this._unclassifiedCommand.shaderProgram && this._unclassifiedCommand.shaderProgram.destroy();
this._classifiedCommand.shaderProgram = this._classifiedCommand.shaderProgram && this._classifiedCommand.shaderProgram.destroy();
}
const fs = defined_default(this._previousFramebuffer) ? opaqueFS : translucentFS;
const unclassifiedFSSource = new ShaderSource_default({
defines: ["UNCLASSIFIED"],
sources: [fs]
});
const classifiedFSSource = new ShaderSource_default({
sources: [fs]
});
this._unclassifiedCommand = context.createViewportQuadCommand(
unclassifiedFSSource,
{
renderState: defined_default(this._previousFramebuffer) ? this._rsUnclassified : this._rsDefault,
uniformMap: this._uniformMap,
owner: this
}
);
this._classifiedCommand = context.createViewportQuadCommand(
classifiedFSSource,
{
renderState: defined_default(this._previousFramebuffer) ? this._rsClassified : this._rsDefault,
uniformMap: this._uniformMap,
owner: this
}
);
if (defined_default(this._translucentCommand)) {
this._translucentCommand.shaderProgram = this._translucentCommand.shaderProgram && this._translucentCommand.shaderProgram.destroy();
}
if (!defined_default(this._previousFramebuffer)) {
this._translucentCommand = context.createViewportQuadCommand(
PassThrough_default,
{
renderState: this._rsUnclassified,
uniformMap: this._uniformMap,
owner: this
}
);
}
}
};
InvertClassification.prototype.prepareTextures = function(context, blitStencil) {
if (this._fbo._numSamples > 1) {
this._fbo.prepareTextures(context, blitStencil);
}
};
InvertClassification.prototype.clear = function(context, passState) {
if (defined_default(this._previousFramebuffer)) {
this._fbo.clear(context, this._clearColorCommand, passState);
} else {
this._fbo.clear(context, this._clearCommand, passState);
this._fboClassified.clear(context, this._clearCommand, passState);
}
};
InvertClassification.prototype.executeClassified = function(context, passState) {
if (!defined_default(this._previousFramebuffer)) {
const framebuffer = passState.framebuffer;
this.prepareTextures(context, true);
passState.framebuffer = this._fboClassified.framebuffer;
this._translucentCommand.execute(context, passState);
passState.framebuffer = framebuffer;
}
this._classifiedCommand.execute(context, passState);
};
InvertClassification.prototype.executeUnclassified = function(context, passState) {
this._unclassifiedCommand.execute(context, passState);
};
InvertClassification.prototype.isDestroyed = function() {
return false;
};
InvertClassification.prototype.destroy = function() {
this._fbo.destroy();
this._fboClassified.destroy();
this._depthStencilTexture = this._depthStencilTexture && this._depthStencilTexture.destroy();
this._depthStencilRenderbuffer = this._depthStencilRenderbuffer && this._depthStencilRenderbuffer.destroy();
if (defined_default(this._unclassifiedCommand)) {
this._unclassifiedCommand.shaderProgram = this._unclassifiedCommand.shaderProgram && this._unclassifiedCommand.shaderProgram.destroy();
this._classifiedCommand.shaderProgram = this._classifiedCommand.shaderProgram && this._classifiedCommand.shaderProgram.destroy();
}
return destroyObject_default(this);
};
var InvertClassification_default = InvertClassification;
// packages/engine/Source/Scene/JobScheduler.js
var import_InlineWorkers1062 = __toESM(require_InlineWorkers(), 1);
function JobTypeBudget(total) {
this._total = total;
this.usedThisFrame = 0;
this.stolenFromMeThisFrame = 0;
this.starvedThisFrame = false;
this.starvedLastFrame = false;
}
Object.defineProperties(JobTypeBudget.prototype, {
total: {
get: function() {
return this._total;
}
}
});
function JobScheduler(budgets) {
if (defined_default(budgets) && budgets.length !== JobType_default.NUMBER_OF_JOB_TYPES) {
throw new DeveloperError_default(
"A budget must be specified for each job type; budgets.length should equal JobType.NUMBER_OF_JOB_TYPES."
);
}
const jobBudgets = new Array(JobType_default.NUMBER_OF_JOB_TYPES);
jobBudgets[JobType_default.TEXTURE] = new JobTypeBudget(
defined_default(budgets) ? budgets[JobType_default.TEXTURE] : 10
);
jobBudgets[JobType_default.PROGRAM] = new JobTypeBudget(
defined_default(budgets) ? budgets[JobType_default.PROGRAM] : 10
);
jobBudgets[JobType_default.BUFFER] = new JobTypeBudget(
defined_default(budgets) ? budgets[JobType_default.BUFFER] : 30
);
const length2 = jobBudgets.length;
let i;
let totalBudget = 0;
for (i = 0; i < length2; ++i) {
totalBudget += jobBudgets[i].total;
}
const executedThisFrame = new Array(length2);
for (i = 0; i < length2; ++i) {
executedThisFrame[i] = false;
}
this._totalBudget = totalBudget;
this._totalUsedThisFrame = 0;
this._budgets = jobBudgets;
this._executedThisFrame = executedThisFrame;
}
JobScheduler.getTimestamp = getTimestamp_default;
Object.defineProperties(JobScheduler.prototype, {
totalBudget: {
get: function() {
return this._totalBudget;
}
}
});
JobScheduler.prototype.disableThisFrame = function() {
this._totalUsedThisFrame = this._totalBudget;
};
JobScheduler.prototype.resetBudgets = function() {
const budgets = this._budgets;
const length2 = budgets.length;
for (let i = 0; i < length2; ++i) {
const budget = budgets[i];
budget.starvedLastFrame = budget.starvedThisFrame;
budget.starvedThisFrame = false;
budget.usedThisFrame = 0;
budget.stolenFromMeThisFrame = 0;
}
this._totalUsedThisFrame = 0;
};
JobScheduler.prototype.execute = function(job, jobType) {
const budgets = this._budgets;
const budget = budgets[jobType];
const progressThisFrame = this._executedThisFrame[jobType];
if (this._totalUsedThisFrame >= this._totalBudget && progressThisFrame) {
budget.starvedThisFrame = true;
return false;
}
let stolenBudget;
if (budget.usedThisFrame + budget.stolenFromMeThisFrame >= budget.total) {
const length2 = budgets.length;
let i;
for (i = 0; i < length2; ++i) {
stolenBudget = budgets[i];
if (stolenBudget.usedThisFrame + stolenBudget.stolenFromMeThisFrame < stolenBudget.total && !stolenBudget.starvedLastFrame) {
break;
}
}
if (i === length2 && progressThisFrame) {
return false;
}
if (progressThisFrame) {
budget.starvedThisFrame = true;
}
}
const startTime = JobScheduler.getTimestamp();
job.execute();
const duration = JobScheduler.getTimestamp() - startTime;
this._totalUsedThisFrame += duration;
if (stolenBudget) {
stolenBudget.stolenFromMeThisFrame += duration;
} else {
budget.usedThisFrame += duration;
}
this._executedThisFrame[jobType] = true;
return true;
};
var JobScheduler_default = JobScheduler;
// packages/engine/Source/Scene/PerformanceDisplay.js
var import_InlineWorkers1063 = __toESM(require_InlineWorkers(), 1);
function PerformanceDisplay(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const container = getElement_default(options.container);
if (!defined_default(container)) {
throw new DeveloperError_default("container is required");
}
this._container = container;
const display = document.createElement("div");
display.className = "cesium-performanceDisplay";
const fpsElement = document.createElement("div");
fpsElement.className = "cesium-performanceDisplay-fps";
this._fpsText = document.createTextNode("");
fpsElement.appendChild(this._fpsText);
const msElement = document.createElement("div");
msElement.className = "cesium-performanceDisplay-ms";
this._msText = document.createTextNode("");
msElement.appendChild(this._msText);
display.appendChild(msElement);
display.appendChild(fpsElement);
this._container.appendChild(display);
this._lastFpsSampleTime = getTimestamp_default();
this._lastMsSampleTime = getTimestamp_default();
this._fpsFrameCount = 0;
this._msFrameCount = 0;
this._throttled = false;
const throttledElement = document.createElement("div");
throttledElement.className = "cesium-performanceDisplay-throttled";
this._throttledText = document.createTextNode("");
throttledElement.appendChild(this._throttledText);
display.appendChild(throttledElement);
}
Object.defineProperties(PerformanceDisplay.prototype, {
/**
* The display should indicate the FPS is being throttled.
* @memberof PerformanceDisplay.prototype
*
* @type {boolean}
*/
throttled: {
get: function() {
return this._throttled;
},
set: function(value) {
if (this._throttled === value) {
return;
}
if (value) {
this._throttledText.nodeValue = "(throttled)";
} else {
this._throttledText.nodeValue = "";
}
this._throttled = value;
}
}
});
PerformanceDisplay.prototype.update = function(renderedThisFrame) {
const time = getTimestamp_default();
const updateDisplay = renderedThisFrame ?? true;
this._fpsFrameCount++;
const fpsElapsedTime = time - this._lastFpsSampleTime;
if (fpsElapsedTime > 1e3) {
let fps = "N/A";
if (updateDisplay) {
fps = this._fpsFrameCount * 1e3 / fpsElapsedTime | 0;
}
this._fpsText.nodeValue = `${fps} FPS`;
this._lastFpsSampleTime = time;
this._fpsFrameCount = 0;
}
this._msFrameCount++;
const msElapsedTime = time - this._lastMsSampleTime;
if (msElapsedTime > 200) {
let ms = "N/A";
if (updateDisplay) {
ms = (msElapsedTime / this._msFrameCount).toFixed(2);
}
this._msText.nodeValue = `${ms} MS`;
this._lastMsSampleTime = time;
this._msFrameCount = 0;
}
};
PerformanceDisplay.prototype.destroy = function() {
return destroyObject_default(this);
};
var PerformanceDisplay_default = PerformanceDisplay;
// packages/engine/Source/Scene/Picking.js
var import_InlineWorkers1082 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/MetadataPicking.js
var import_InlineWorkers1064 = __toESM(require_InlineWorkers(), 1);
var MetadataPicking = {};
MetadataPicking.decodeRawMetadataValue = function(componentType, dataView, index) {
switch (componentType) {
case MetadataComponentType_default.INT8:
return dataView.getInt8(index);
case MetadataComponentType_default.UINT8:
return dataView.getUint8(index);
case MetadataComponentType_default.INT16:
return dataView.getInt16(index, true);
case MetadataComponentType_default.UINT16:
return dataView.getUint16(index, true);
case MetadataComponentType_default.INT32:
return dataView.getInt32(index, true);
case MetadataComponentType_default.UINT32:
return dataView.getUint32(index, true);
case MetadataComponentType_default.INT64:
return dataView.getBigInt64(index, true);
case MetadataComponentType_default.UINT64:
return dataView.getBigUint64(index, true);
case MetadataComponentType_default.FLOAT32:
return dataView.getFloat32(index, true);
case MetadataComponentType_default.FLOAT64:
return dataView.getFloat64(index, true);
}
throw new RuntimeError_default(`Invalid component type: ${componentType}`);
};
MetadataPicking.decodeRawMetadataValueComponent = function(classProperty, dataView, dataViewOffset) {
const componentType = classProperty.componentType;
const component = MetadataPicking.decodeRawMetadataValue(
componentType,
dataView,
dataViewOffset
);
if (classProperty.normalized) {
return MetadataComponentType_default.normalize(component, componentType);
}
return component;
};
MetadataPicking.decodeRawMetadataValueElement = function(classProperty, dataView, elementIndex) {
const componentType = classProperty.componentType;
const componentSizeInBytes = MetadataComponentType_default.getSizeInBytes(componentType);
const type = classProperty.type;
const componentCount = MetadataType_default.getComponentCount(type);
const elementSizeInBytes = componentSizeInBytes * componentCount;
if (componentCount > 1) {
const result2 = Array(componentCount);
for (let i = 0; i < componentCount; i++) {
const offset2 = elementIndex * elementSizeInBytes + i * componentSizeInBytes;
const component = MetadataPicking.decodeRawMetadataValueComponent(
classProperty,
dataView,
offset2
);
result2[i] = component;
}
return result2;
}
const offset = elementIndex * elementSizeInBytes;
const result = MetadataPicking.decodeRawMetadataValueComponent(
classProperty,
dataView,
offset
);
return result;
};
MetadataPicking.decodeRawMetadataValues = function(classProperty, rawPixelValues) {
const dataView = new DataView(
rawPixelValues.buffer,
rawPixelValues.byteOffset,
rawPixelValues.byteLength
);
if (classProperty.isArray) {
const arrayLength = classProperty.arrayLength;
const result2 = Array(arrayLength);
for (let i = 0; i < arrayLength; i++) {
const element = MetadataPicking.decodeRawMetadataValueElement(
classProperty,
dataView,
i
);
result2[i] = element;
}
return result2;
}
const result = MetadataPicking.decodeRawMetadataValueElement(
classProperty,
dataView,
0
);
return result;
};
MetadataPicking.convertToObjectType = function(type, value) {
if (!defined_default(value)) {
return value;
}
if (type === MetadataType_default.SCALAR || type === MetadataType_default.STRING || type === MetadataType_default.BOOLEAN || type === MetadataType_default.ENUM) {
return value;
}
const numbers = value.map((n) => Number(n));
switch (type) {
case MetadataType_default.VEC2:
return Cartesian2_default.unpack(numbers, 0, new Cartesian2_default());
case MetadataType_default.VEC3:
return Cartesian3_default.unpack(numbers, 0, new Cartesian3_default());
case MetadataType_default.VEC4:
return Cartesian4_default.unpack(numbers, 0, new Cartesian4_default());
case MetadataType_default.MAT2:
return Matrix2_default.unpack(numbers, 0, new Matrix2_default());
case MetadataType_default.MAT3:
return Matrix3_default.unpack(numbers, 0, new Matrix3_default());
case MetadataType_default.MAT4:
return Matrix4_default.unpack(numbers, 0, new Matrix4_default());
}
throw new RuntimeError_default(`Invalid metadata object type: ${type}`);
};
MetadataPicking.convertFromObjectType = function(type, value) {
if (!defined_default(value)) {
return value;
}
if (type === MetadataType_default.SCALAR || type === MetadataType_default.STRING || type === MetadataType_default.BOOLEAN || type === MetadataType_default.ENUM) {
return value;
}
switch (type) {
case MetadataType_default.VEC2:
return Cartesian2_default.pack(value, Array(2));
case MetadataType_default.VEC3:
return Cartesian3_default.pack(value, Array(3));
case MetadataType_default.VEC4:
return Cartesian4_default.pack(value, Array(4));
case MetadataType_default.MAT2:
return Matrix2_default.pack(value, Array(4));
case MetadataType_default.MAT3:
return Matrix3_default.pack(value, Array(9));
case MetadataType_default.MAT4:
return Matrix4_default.pack(value, Array(16));
}
throw new RuntimeError_default(`Invalid metadata object type: ${type}`);
};
MetadataPicking.decodeMetadataValues = function(classProperty, metadataProperty, rawPixelValues) {
let arrayBasedResult = MetadataPicking.decodeRawMetadataValues(
classProperty,
rawPixelValues
);
if (metadataProperty.hasValueTransform) {
const offset = MetadataPicking.convertFromObjectType(
classProperty.type,
metadataProperty.offset
);
const scale = MetadataPicking.convertFromObjectType(
classProperty.type,
metadataProperty.scale
);
arrayBasedResult = MetadataClassProperty_default.valueTransformInPlace(
arrayBasedResult,
offset,
scale,
MetadataComponentType_default.applyValueTransform
);
}
if (classProperty.isArray) {
const arrayLength = classProperty.arrayLength;
const result = Array(arrayLength);
for (let i = 0; i < arrayLength; i++) {
const arrayBasedValue = arrayBasedResult[i];
const objectBasedValue = MetadataPicking.convertToObjectType(
classProperty.type,
arrayBasedValue
);
result[i] = objectBasedValue;
}
return result;
}
const objectResult = MetadataPicking.convertToObjectType(
classProperty.type,
arrayBasedResult
);
return objectResult;
};
var MetadataPicking_default = Object.freeze(MetadataPicking);
// packages/engine/Source/Scene/PickDepth.js
var import_InlineWorkers1065 = __toESM(require_InlineWorkers(), 1);
function PickDepth() {
this._framebuffer = new FramebufferManager_default();
this._textureToCopy = void 0;
this._copyDepthCommand = void 0;
}
Object.defineProperties(PickDepth.prototype, {
framebuffer: {
get: function() {
return this._framebuffer.framebuffer;
}
}
});
function updateFramebuffers(pickDepth, context, depthTexture) {
const { width, height } = depthTexture;
pickDepth._framebuffer.update(context, width, height);
}
function updateCopyCommands(pickDepth, context, depthTexture) {
if (!defined_default(pickDepth._copyDepthCommand)) {
pickDepth._copyDepthCommand = context.createViewportQuadCommand(
`uniform highp sampler2D colorTexture;
in vec2 v_textureCoordinates;
void main()
{
vec4 globeDepthPacked = texture(czm_globeDepthTexture, v_textureCoordinates);
float globeDepth = czm_unpackDepth(globeDepthPacked);
float depth = texture(colorTexture, v_textureCoordinates).r;
out_FragColor = czm_branchFreeTernary(globeDepth <= 0.0 || globeDepth >= 1.0 || depth < globeDepth && depth > 0.0 && depth < 1.0,
czm_packDepth(depth), globeDepthPacked);
}
`,
{
renderState: RenderState_default.fromCache(),
uniformMap: {
colorTexture: function() {
return pickDepth._textureToCopy;
}
},
owner: pickDepth
}
);
}
pickDepth._textureToCopy = depthTexture;
pickDepth._copyDepthCommand.framebuffer = pickDepth.framebuffer;
}
PickDepth.prototype.update = function(context, depthTexture) {
updateFramebuffers(this, context, depthTexture);
updateCopyCommands(this, context, depthTexture);
};
var scratchPackedDepth = new Cartesian4_default();
var packedDepthScale = new Cartesian4_default(
1,
1 / 255,
1 / 65025,
1 / 16581375
);
PickDepth.prototype.getDepth = function(context, x, y) {
if (!defined_default(this.framebuffer)) {
return void 0;
}
const pixels = context.readPixels({
x,
y,
width: 1,
height: 1,
framebuffer: this.framebuffer
});
const packedDepth = Cartesian4_default.unpack(pixels, 0, scratchPackedDepth);
Cartesian4_default.divideByScalar(packedDepth, 255, packedDepth);
return Cartesian4_default.dot(packedDepth, packedDepthScale);
};
PickDepth.prototype.executeCopyDepth = function(context, passState) {
this._copyDepthCommand.execute(context, passState);
};
PickDepth.prototype.isDestroyed = function() {
return false;
};
PickDepth.prototype.destroy = function() {
this._framebuffer.destroy();
if (defined_default(this._copyDepthCommand)) {
this._copyDepthCommand.shaderProgram = defined_default(this._copyDepthCommand.shaderProgram) && this._copyDepthCommand.shaderProgram.destroy();
}
return destroyObject_default(this);
};
var PickDepth_default = PickDepth;
// packages/engine/Source/Scene/View.js
var import_InlineWorkers1081 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/FrustumCommands.js
var import_InlineWorkers1066 = __toESM(require_InlineWorkers(), 1);
function FrustumCommands(near, far) {
this.near = near ?? 0;
this.far = far ?? 0;
const numPasses = Pass_default.NUMBER_OF_PASSES;
const commands = new Array(numPasses);
const indices = new Array(numPasses);
for (let i = 0; i < numPasses; ++i) {
commands[i] = [];
indices[i] = 0;
}
this.commands = commands;
this.indices = indices;
}
var FrustumCommands_default = FrustumCommands;
// packages/engine/Source/Scene/GlobeDepth.js
var import_InlineWorkers1068 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/PostProcessStages/PassThroughDepth.js
var import_InlineWorkers1067 = __toESM(require_InlineWorkers(), 1);
var PassThroughDepth_default = "uniform highp sampler2D u_depthTexture;\n\nin vec2 v_textureCoordinates;\n\nvoid main()\n{\n out_FragColor = czm_packDepth(texture(u_depthTexture, v_textureCoordinates).r);\n}\n";
// packages/engine/Source/Scene/GlobeDepth.js
function GlobeDepth() {
this._picking = false;
this._numSamples = 1;
this._tempCopyDepthTexture = void 0;
this._pickColorFramebuffer = new FramebufferManager_default({
depthStencil: true,
supportsDepthTexture: true
});
this._outputFramebuffer = new FramebufferManager_default({
depthStencil: true,
supportsDepthTexture: true
});
this._copyDepthFramebuffer = new FramebufferManager_default();
this._tempCopyDepthFramebuffer = new FramebufferManager_default();
this._updateDepthFramebuffer = new FramebufferManager_default({
createColorAttachments: false,
createDepthAttachments: false,
depthStencil: true
});
this._clearGlobeColorCommand = void 0;
this._copyColorCommand = void 0;
this._copyDepthCommand = void 0;
this._tempCopyDepthCommand = void 0;
this._updateDepthCommand = void 0;
this._viewport = new BoundingRectangle_default();
this._rs = void 0;
this._rsBlend = void 0;
this._rsUpdate = void 0;
this._useScissorTest = false;
this._scissorRectangle = void 0;
this._useHdr = void 0;
this._clearGlobeDepth = void 0;
}
Object.defineProperties(GlobeDepth.prototype, {
colorFramebufferManager: {
get: function() {
return this._picking ? this._pickColorFramebuffer : this._outputFramebuffer;
}
},
framebuffer: {
get: function() {
return this.colorFramebufferManager.framebuffer;
}
},
depthStencilTexture: {
get: function() {
return this.colorFramebufferManager.getDepthStencilTexture();
}
},
picking: {
get: function() {
return this._picking;
},
set: function(value) {
this._picking = value;
}
}
});
function updateCopyCommands2(globeDepth, context, width, height, passState) {
const viewport = globeDepth._viewport;
viewport.width = width;
viewport.height = height;
const useScissorTest = !BoundingRectangle_default.equals(
viewport,
passState.viewport
);
let updateScissor = useScissorTest !== globeDepth._useScissorTest;
globeDepth._useScissorTest = useScissorTest;
if (!BoundingRectangle_default.equals(globeDepth._scissorRectangle, passState.viewport)) {
globeDepth._scissorRectangle = BoundingRectangle_default.clone(
passState.viewport,
globeDepth._scissorRectangle
);
updateScissor = true;
}
if (!defined_default(globeDepth._rs) || !BoundingRectangle_default.equals(viewport, globeDepth._rs.viewport) || updateScissor) {
globeDepth._rs = RenderState_default.fromCache({
viewport,
scissorTest: {
enabled: globeDepth._useScissorTest,
rectangle: globeDepth._scissorRectangle
}
});
globeDepth._rsBlend = RenderState_default.fromCache({
viewport,
scissorTest: {
enabled: globeDepth._useScissorTest,
rectangle: globeDepth._scissorRectangle
},
blending: BlendingState_default.ALPHA_BLEND
});
globeDepth._rsUpdate = RenderState_default.fromCache({
viewport,
scissorTest: {
enabled: globeDepth._useScissorTest,
rectangle: globeDepth._scissorRectangle
},
stencilTest: {
enabled: true,
frontFunction: StencilFunction_default.EQUAL,
frontOperation: {
fail: StencilOperation_default.KEEP,
zFail: StencilOperation_default.KEEP,
zPass: StencilOperation_default.KEEP
},
backFunction: StencilFunction_default.NEVER,
reference: StencilConstants_default.CESIUM_3D_TILE_MASK,
mask: StencilConstants_default.CESIUM_3D_TILE_MASK
}
});
}
if (!defined_default(globeDepth._copyDepthCommand)) {
globeDepth._copyDepthCommand = context.createViewportQuadCommand(
PassThroughDepth_default,
{
uniformMap: {
u_depthTexture: function() {
return globeDepth.colorFramebufferManager.getDepthStencilTexture();
}
},
owner: globeDepth
}
);
}
globeDepth._copyDepthCommand.framebuffer = globeDepth._copyDepthFramebuffer.framebuffer;
globeDepth._copyDepthCommand.renderState = globeDepth._rs;
if (!defined_default(globeDepth._copyColorCommand)) {
globeDepth._copyColorCommand = context.createViewportQuadCommand(
PassThrough_default,
{
uniformMap: {
colorTexture: function() {
return globeDepth.colorFramebufferManager.getColorTexture();
}
},
owner: globeDepth
}
);
}
globeDepth._copyColorCommand.renderState = globeDepth._rs;
if (!defined_default(globeDepth._tempCopyDepthCommand)) {
globeDepth._tempCopyDepthCommand = context.createViewportQuadCommand(
PassThroughDepth_default,
{
uniformMap: {
u_depthTexture: function() {
return globeDepth._tempCopyDepthTexture;
}
},
owner: globeDepth
}
);
}
globeDepth._tempCopyDepthCommand.framebuffer = globeDepth._tempCopyDepthFramebuffer.framebuffer;
globeDepth._tempCopyDepthCommand.renderState = globeDepth._rs;
if (!defined_default(globeDepth._updateDepthCommand)) {
globeDepth._updateDepthCommand = context.createViewportQuadCommand(
PassThrough_default,
{
uniformMap: {
colorTexture: function() {
return globeDepth._tempCopyDepthFramebuffer.getColorTexture();
}
},
owner: globeDepth
}
);
}
globeDepth._updateDepthCommand.framebuffer = globeDepth._updateDepthFramebuffer.framebuffer;
globeDepth._updateDepthCommand.renderState = globeDepth._rsUpdate;
if (!defined_default(globeDepth._clearGlobeColorCommand)) {
globeDepth._clearGlobeColorCommand = new ClearCommand_default({
color: new Color_default(0, 0, 0, 0),
stencil: 0,
owner: globeDepth
});
}
globeDepth._clearGlobeColorCommand.framebuffer = globeDepth.framebuffer;
}
GlobeDepth.prototype.update = function(context, passState, viewport, numSamples, hdr, clearGlobeDepth) {
const { width, height } = viewport;
const pixelDatatype = hdr ? context.halfFloatingPointTexture ? PixelDatatype_default.HALF_FLOAT : PixelDatatype_default.FLOAT : PixelDatatype_default.UNSIGNED_BYTE;
this._numSamples = numSamples;
if (this.picking) {
this._pickColorFramebuffer.update(context, width, height);
} else {
this._outputFramebuffer.update(
context,
width,
height,
numSamples,
pixelDatatype
);
}
this._copyDepthFramebuffer.update(context, width, height);
updateCopyCommands2(this, context, width, height, passState);
context.uniformState.globeDepthTexture = void 0;
this._clearGlobeDepth = clearGlobeDepth;
};
GlobeDepth.prototype.prepareColorTextures = function(context, blitStencil) {
if (!this.picking && this._numSamples > 1) {
this._outputFramebuffer.prepareTextures(context, blitStencil);
}
};
GlobeDepth.prototype.executeCopyDepth = function(context, passState) {
if (defined_default(this._copyDepthCommand)) {
this.prepareColorTextures(context);
this._copyDepthCommand.execute(context, passState);
context.uniformState.globeDepthTexture = this._copyDepthFramebuffer.getColorTexture();
}
};
GlobeDepth.prototype.executeUpdateDepth = function(context, passState, depthTexture) {
const depthTextureToCopy = defined_default(depthTexture) ? depthTexture : passState.framebuffer.depthStencilTexture;
if (!this._clearGlobeDepth && depthTextureToCopy === this.colorFramebufferManager.getDepthStencilTexture()) {
if (defined_default(this._copyDepthCommand)) {
this._copyDepthCommand.execute(context, passState);
}
return;
}
if (!defined_default(this._updateDepthCommand)) {
return;
}
const updateDepthFramebuffer = this._updateDepthFramebuffer;
if (!defined_default(updateDepthFramebuffer.framebuffer) || updateDepthFramebuffer.getDepthStencilTexture() !== depthTextureToCopy || updateDepthFramebuffer.getColorTexture() !== this._copyDepthFramebuffer.getColorTexture()) {
const colorTexture = this._copyDepthFramebuffer.getColorTexture();
const { width, height } = colorTexture;
this._tempCopyDepthFramebuffer.destroy();
this._tempCopyDepthFramebuffer.update(context, width, height);
updateDepthFramebuffer.setColorTexture(colorTexture, 0);
updateDepthFramebuffer.setDepthStencilTexture(depthTextureToCopy);
updateDepthFramebuffer.update(context, width, height);
updateCopyCommands2(this, context, width, height, passState);
}
this._tempCopyDepthTexture = depthTextureToCopy;
this._tempCopyDepthCommand.execute(context, passState);
this._updateDepthCommand.execute(context, passState);
};
GlobeDepth.prototype.executeCopyColor = function(context, passState) {
if (defined_default(this._copyColorCommand)) {
this._copyColorCommand.execute(context, passState);
}
};
GlobeDepth.prototype.clear = function(context, passState, clearColor) {
const clear2 = this._clearGlobeColorCommand;
if (defined_default(clear2)) {
Color_default.clone(clearColor, clear2.color);
this.colorFramebufferManager.clear(context, clear2, passState);
}
};
GlobeDepth.prototype.isDestroyed = function() {
return false;
};
GlobeDepth.prototype.destroy = function() {
this._pickColorFramebuffer.destroy();
this._outputFramebuffer.destroy();
this._copyDepthFramebuffer.destroy();
this._tempCopyDepthFramebuffer.destroy();
this._updateDepthFramebuffer.destroy();
if (defined_default(this._copyColorCommand)) {
this._copyColorCommand.shaderProgram = this._copyColorCommand.shaderProgram.destroy();
}
if (defined_default(this._copyDepthCommand)) {
this._copyDepthCommand.shaderProgram = this._copyDepthCommand.shaderProgram.destroy();
}
if (defined_default(this._tempCopyDepthCommand)) {
this._tempCopyDepthCommand.shaderProgram = this._tempCopyDepthCommand.shaderProgram.destroy();
}
if (defined_default(this._updateDepthCommand)) {
this._updateDepthCommand.shaderProgram = this._updateDepthCommand.shaderProgram.destroy();
}
return destroyObject_default(this);
};
var GlobeDepth_default = GlobeDepth;
// packages/engine/Source/Scene/GlobeTranslucencyFramebuffer.js
var import_InlineWorkers1069 = __toESM(require_InlineWorkers(), 1);
function GlobeTranslucencyFramebuffer() {
this._framebuffer = new FramebufferManager_default({
depthStencil: true,
supportsDepthTexture: true
});
this._packedDepthFramebuffer = new FramebufferManager_default();
this._renderState = void 0;
this._packedDepthCommand = void 0;
this._clearCommand = void 0;
this._viewport = new BoundingRectangle_default();
this._useScissorTest = false;
this._scissorRectangle = void 0;
this._useHdr = void 0;
}
Object.defineProperties(GlobeTranslucencyFramebuffer.prototype, {
// Exposed for testing
classificationTexture: {
get: function() {
return this._framebuffer.getColorTexture();
}
},
classificationFramebuffer: {
get: function() {
return this._framebuffer.framebuffer;
}
},
// Exposed for testing
packedDepthFramebuffer: {
get: function() {
return this._packedDepthFramebuffer.framebuffer;
}
},
depthStencilTexture: {
get: function() {
return this._framebuffer.getDepthStencilTexture();
}
},
// Exposed for testing
depthStencilRenderbuffer: {
get: function() {
return this._framebuffer.getDepthStencilRenderbuffer();
}
},
packedDepthTexture: {
get: function() {
return this._packedDepthFramebuffer.getColorTexture();
}
}
});
function destroyResources(globeTranslucency) {
globeTranslucency._framebuffer.destroy();
globeTranslucency._packedDepthFramebuffer.destroy();
}
function updateResources(globeTranslucency, context, width, height, hdr) {
const pixelDatatype = hdr ? context.halfFloatingPointTexture ? PixelDatatype_default.HALF_FLOAT : PixelDatatype_default.FLOAT : PixelDatatype_default.UNSIGNED_BYTE;
globeTranslucency._framebuffer.update(
context,
width,
height,
1,
pixelDatatype
);
globeTranslucency._packedDepthFramebuffer.update(context, width, height);
}
function updateCommands(globeTranslucency, context, width, height, passState) {
globeTranslucency._viewport.width = width;
globeTranslucency._viewport.height = height;
const useScissorTest = !BoundingRectangle_default.equals(
globeTranslucency._viewport,
passState.viewport
);
let updateScissor = useScissorTest !== globeTranslucency._useScissorTest;
globeTranslucency._useScissorTest = useScissorTest;
if (!BoundingRectangle_default.equals(
globeTranslucency._scissorRectangle,
passState.viewport
)) {
globeTranslucency._scissorRectangle = BoundingRectangle_default.clone(
passState.viewport,
globeTranslucency._scissorRectangle
);
updateScissor = true;
}
if (!defined_default(globeTranslucency._renderState) || !BoundingRectangle_default.equals(
globeTranslucency._viewport,
globeTranslucency._renderState.viewport
) || updateScissor) {
globeTranslucency._renderState = RenderState_default.fromCache({
viewport: globeTranslucency._viewport,
scissorTest: {
enabled: globeTranslucency._useScissorTest,
rectangle: globeTranslucency._scissorRectangle
}
});
}
if (!defined_default(globeTranslucency._packedDepthCommand)) {
globeTranslucency._packedDepthCommand = context.createViewportQuadCommand(
PassThroughDepth_default,
{
uniformMap: {
u_depthTexture: function() {
return globeTranslucency.depthStencilTexture;
}
},
owner: globeTranslucency
}
);
}
if (!defined_default(globeTranslucency._clearCommand)) {
globeTranslucency._clearCommand = new ClearCommand_default({
color: new Color_default(0, 0, 0, 0),
depth: 1,
stencil: 0,
owner: globeTranslucency
});
}
globeTranslucency._packedDepthCommand.framebuffer = globeTranslucency._packedDepthFramebuffer.framebuffer;
globeTranslucency._packedDepthCommand.renderState = globeTranslucency._renderState;
globeTranslucency._clearCommand.framebuffer = globeTranslucency.classificationFramebuffer;
globeTranslucency._clearCommand.renderState = globeTranslucency._renderState;
}
GlobeTranslucencyFramebuffer.prototype.updateAndClear = function(hdr, viewport, context, passState) {
const width = viewport.width;
const height = viewport.height;
updateResources(this, context, width, height, hdr);
updateCommands(this, context, width, height, passState);
this._useHdr = hdr;
};
GlobeTranslucencyFramebuffer.prototype.clearClassification = function(context, passState) {
this._clearCommand.execute(context, passState);
};
GlobeTranslucencyFramebuffer.prototype.packDepth = function(context, passState) {
this._packedDepthCommand.execute(context, passState);
return this.packedDepthTexture;
};
GlobeTranslucencyFramebuffer.prototype.isDestroyed = function() {
return false;
};
GlobeTranslucencyFramebuffer.prototype.destroy = function() {
destroyResources(this);
return destroyObject_default(this);
};
var GlobeTranslucencyFramebuffer_default = GlobeTranslucencyFramebuffer;
// packages/engine/Source/Scene/OIT.js
var import_InlineWorkers1072 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/AdjustTranslucentFS.js
var import_InlineWorkers1070 = __toESM(require_InlineWorkers(), 1);
var AdjustTranslucentFS_default = "#ifdef MRT\nlayout (location = 0) out vec4 out_FragData_0;\nlayout (location = 1) out vec4 out_FragData_1;\n#else\nlayout (location = 0) out vec4 out_FragColor;\n#endif\n\nuniform vec4 u_bgColor;\nuniform sampler2D u_depthTexture;\n\nin vec2 v_textureCoordinates;\n\nvoid main()\n{\n if (texture(u_depthTexture, v_textureCoordinates).r < 1.0)\n {\n#ifdef MRT\n out_FragData_0 = u_bgColor;\n out_FragData_1 = vec4(u_bgColor.a);\n#else\n out_FragColor = u_bgColor;\n#endif\n return;\n }\n \n discard;\n}\n";
// packages/engine/Source/Shaders/CompositeOITFS.js
var import_InlineWorkers1071 = __toESM(require_InlineWorkers(), 1);
var CompositeOITFS_default = "/**\n * Compositing for Weighted Blended Order-Independent Transparency. See:\n * - http://jcgt.org/published/0002/02/09/\n * - http://casual-effects.blogspot.com/2014/03/weighted-blended-order-independent.html\n */\n\nuniform sampler2D u_opaque;\nuniform sampler2D u_accumulation;\nuniform sampler2D u_revealage;\n\nin vec2 v_textureCoordinates;\n\nvoid main()\n{\n vec4 opaque = texture(u_opaque, v_textureCoordinates);\n vec4 accum = texture(u_accumulation, v_textureCoordinates);\n float r = texture(u_revealage, v_textureCoordinates).r;\n\n#ifdef MRT\n vec4 transparent = vec4(accum.rgb / clamp(r, 1e-4, 5e4), accum.a);\n#else\n vec4 transparent = vec4(accum.rgb / clamp(accum.a, 1e-4, 5e4), r);\n#endif\n\n out_FragColor = (1.0 - transparent.a) * transparent + transparent.a * opaque;\n\n if (opaque != czm_backgroundColor)\n {\n out_FragColor.a = 1.0;\n }\n}\n";
// packages/engine/Source/Scene/OIT.js
function OIT(context) {
this._numSamples = 1;
this._translucentMultipassSupport = false;
this._translucentMRTSupport = false;
const extensionsSupported = context.colorBufferFloat && context.depthTexture && context.floatBlend;
this._translucentMRTSupport = context.drawBuffers && extensionsSupported;
this._translucentMultipassSupport = !this._translucentMRTSupport && extensionsSupported;
this._opaqueFBO = void 0;
this._opaqueTexture = void 0;
this._depthStencilTexture = void 0;
this._accumulationTexture = void 0;
this._translucentFBO = new FramebufferManager_default({
colorAttachmentsLength: this._translucentMRTSupport ? 2 : 1,
createColorAttachments: false,
createDepthAttachments: false,
depth: true
});
this._alphaFBO = new FramebufferManager_default({
createColorAttachments: false,
createDepthAttachments: false,
depth: true
});
this._adjustTranslucentFBO = new FramebufferManager_default({
colorAttachmentsLength: this._translucentMRTSupport ? 2 : 1,
createColorAttachments: false
});
this._adjustAlphaFBO = new FramebufferManager_default({
createColorAttachments: false
});
this._opaqueClearCommand = new ClearCommand_default({
color: new Color_default(0, 0, 0, 0),
owner: this
});
this._translucentMRTClearCommand = new ClearCommand_default({
color: new Color_default(0, 0, 0, 1),
owner: this
});
this._translucentMultipassClearCommand = new ClearCommand_default({
color: new Color_default(0, 0, 0, 0),
owner: this
});
this._alphaClearCommand = new ClearCommand_default({
color: new Color_default(1, 1, 1, 1),
owner: this
});
this._translucentRenderStateCache = {};
this._alphaRenderStateCache = {};
this._compositeCommand = void 0;
this._adjustTranslucentCommand = void 0;
this._adjustAlphaCommand = void 0;
this._viewport = new BoundingRectangle_default();
this._rs = void 0;
this._useScissorTest = false;
this._scissorRectangle = void 0;
this._useHDR = false;
}
function destroyTextures(oit) {
oit._accumulationTexture = oit._accumulationTexture && !oit._accumulationTexture.isDestroyed() && oit._accumulationTexture.destroy();
oit._revealageTexture = oit._revealageTexture && !oit._revealageTexture.isDestroyed() && oit._revealageTexture.destroy();
}
function destroyFramebuffers(oit) {
oit._translucentFBO.destroy();
oit._alphaFBO.destroy();
oit._adjustTranslucentFBO.destroy();
oit._adjustAlphaFBO.destroy();
}
function destroyResources2(oit) {
destroyTextures(oit);
destroyFramebuffers(oit);
}
function updateTextures(oit, context, width, height) {
destroyTextures(oit);
oit._accumulationTexture = new Texture_default({
context,
width,
height,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.FLOAT
});
oit._revealageTexture = new Texture_default({
context,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.FLOAT,
width,
height,
flipY: false
});
}
function updateFramebuffers2(oit, context) {
destroyFramebuffers(oit);
const completeFBO = WebGLConstants_default.FRAMEBUFFER_COMPLETE;
let supported = true;
const { width, height } = oit._accumulationTexture;
if (oit._translucentMRTSupport) {
oit._translucentFBO.setColorTexture(oit._accumulationTexture, 0);
oit._translucentFBO.setColorTexture(oit._revealageTexture, 1);
oit._translucentFBO.setDepthStencilTexture(oit._depthStencilTexture);
oit._translucentFBO.update(context, width, height);
oit._adjustTranslucentFBO.setColorTexture(oit._accumulationTexture, 0);
oit._adjustTranslucentFBO.setColorTexture(oit._revealageTexture, 1);
oit._adjustTranslucentFBO.update(context, width, height);
if (oit._translucentFBO.status !== completeFBO || oit._adjustTranslucentFBO.status !== completeFBO) {
destroyFramebuffers(oit);
oit._translucentMRTSupport = false;
}
}
if (!oit._translucentMRTSupport) {
oit._translucentFBO.setColorTexture(oit._accumulationTexture);
oit._translucentFBO.setDepthStencilTexture(oit._depthStencilTexture);
oit._translucentFBO.update(context, width, height);
oit._alphaFBO.setColorTexture(oit._revealageTexture);
oit._alphaFBO.setDepthStencilTexture(oit._depthStencilTexture);
oit._alphaFBO.update(context, width, height);
oit._adjustTranslucentFBO.setColorTexture(oit._accumulationTexture);
oit._adjustTranslucentFBO.update(context, width, height);
oit._adjustAlphaFBO.setColorTexture(oit._revealageTexture);
oit._adjustAlphaFBO.update(context, width, height);
const translucentComplete = oit._translucentFBO.status === completeFBO;
const alphaComplete = oit._alphaFBO.status === completeFBO;
const adjustTranslucentComplete = oit._adjustTranslucentFBO.status === completeFBO;
const adjustAlphaComplete = oit._adjustAlphaFBO.status === completeFBO;
if (!translucentComplete || !alphaComplete || !adjustTranslucentComplete || !adjustAlphaComplete) {
destroyResources2(oit);
oit._translucentMultipassSupport = false;
supported = false;
}
}
return supported;
}
OIT.prototype.update = function(context, passState, framebuffer, useHDR, numSamples) {
if (!this.isSupported()) {
return;
}
this._opaqueFBO = framebuffer;
this._opaqueTexture = framebuffer.getColorTexture(0);
this._depthStencilTexture = framebuffer.getDepthStencilTexture();
const { width, height } = this._opaqueTexture;
const accumulationTexture = this._accumulationTexture;
const textureChanged = !defined_default(accumulationTexture) || accumulationTexture.width !== width || accumulationTexture.height !== height || useHDR !== this._useHDR;
const samplesChanged = this._numSamples !== numSamples;
if (textureChanged || samplesChanged) {
this._numSamples = numSamples;
updateTextures(this, context, width, height);
}
if (!defined_default(this._translucentFBO.framebuffer) || textureChanged || samplesChanged) {
if (!updateFramebuffers2(this, context)) {
return;
}
}
this._useHDR = useHDR;
const that = this;
let fs;
let uniformMap2;
if (!defined_default(this._compositeCommand)) {
fs = new ShaderSource_default({
sources: [CompositeOITFS_default]
});
if (this._translucentMRTSupport) {
fs.defines.push("MRT");
}
uniformMap2 = {
u_opaque: function() {
return that._opaqueTexture;
},
u_accumulation: function() {
return that._accumulationTexture;
},
u_revealage: function() {
return that._revealageTexture;
}
};
this._compositeCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap2,
owner: this
});
}
if (!defined_default(this._adjustTranslucentCommand)) {
if (this._translucentMRTSupport) {
fs = new ShaderSource_default({
defines: ["MRT"],
sources: [AdjustTranslucentFS_default]
});
uniformMap2 = {
u_bgColor: function() {
return that._translucentMRTClearCommand.color;
},
u_depthTexture: function() {
return that._depthStencilTexture;
}
};
this._adjustTranslucentCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap2,
owner: this
});
} else if (this._translucentMultipassSupport) {
fs = new ShaderSource_default({
sources: [AdjustTranslucentFS_default]
});
uniformMap2 = {
u_bgColor: function() {
return that._translucentMultipassClearCommand.color;
},
u_depthTexture: function() {
return that._depthStencilTexture;
}
};
this._adjustTranslucentCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap2,
owner: this
});
uniformMap2 = {
u_bgColor: function() {
return that._alphaClearCommand.color;
},
u_depthTexture: function() {
return that._depthStencilTexture;
}
};
this._adjustAlphaCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap2,
owner: this
});
}
}
this._viewport.width = width;
this._viewport.height = height;
const useScissorTest = !BoundingRectangle_default.equals(
this._viewport,
passState.viewport
);
let updateScissor = useScissorTest !== this._useScissorTest;
this._useScissorTest = useScissorTest;
if (!BoundingRectangle_default.equals(this._scissorRectangle, passState.viewport)) {
this._scissorRectangle = BoundingRectangle_default.clone(
passState.viewport,
this._scissorRectangle
);
updateScissor = true;
}
if (!defined_default(this._rs) || !BoundingRectangle_default.equals(this._viewport, this._rs.viewport) || updateScissor) {
this._rs = RenderState_default.fromCache({
viewport: this._viewport,
scissorTest: {
enabled: this._useScissorTest,
rectangle: this._scissorRectangle
}
});
}
if (defined_default(this._compositeCommand)) {
this._compositeCommand.renderState = this._rs;
}
if (this._adjustTranslucentCommand) {
this._adjustTranslucentCommand.renderState = this._rs;
}
if (defined_default(this._adjustAlphaCommand)) {
this._adjustAlphaCommand.renderState = this._rs;
}
};
var translucentMRTBlend = {
enabled: true,
color: new Color_default(0, 0, 0, 0),
equationRgb: BlendEquation_default.ADD,
equationAlpha: BlendEquation_default.ADD,
functionSourceRgb: BlendFunction_default.ONE,
functionDestinationRgb: BlendFunction_default.ONE,
functionSourceAlpha: BlendFunction_default.ZERO,
functionDestinationAlpha: BlendFunction_default.ONE_MINUS_SOURCE_ALPHA
};
var translucentColorBlend = {
enabled: true,
color: new Color_default(0, 0, 0, 0),
equationRgb: BlendEquation_default.ADD,
equationAlpha: BlendEquation_default.ADD,
functionSourceRgb: BlendFunction_default.ONE,
functionDestinationRgb: BlendFunction_default.ONE,
functionSourceAlpha: BlendFunction_default.ONE,
functionDestinationAlpha: BlendFunction_default.ONE
};
var translucentAlphaBlend = {
enabled: true,
color: new Color_default(0, 0, 0, 0),
equationRgb: BlendEquation_default.ADD,
equationAlpha: BlendEquation_default.ADD,
functionSourceRgb: BlendFunction_default.ZERO,
functionDestinationRgb: BlendFunction_default.ONE_MINUS_SOURCE_ALPHA,
functionSourceAlpha: BlendFunction_default.ZERO,
functionDestinationAlpha: BlendFunction_default.ONE_MINUS_SOURCE_ALPHA
};
function getTranslucentRenderState2(context, translucentBlending, cache, renderState) {
let translucentState = cache[renderState.id];
if (!defined_default(translucentState)) {
const rs = RenderState_default.getState(renderState);
rs.depthMask = false;
rs.blending = translucentBlending;
translucentState = RenderState_default.fromCache(rs);
cache[renderState.id] = translucentState;
}
return translucentState;
}
function getTranslucentMRTRenderState(oit, context, renderState) {
return getTranslucentRenderState2(
context,
translucentMRTBlend,
oit._translucentRenderStateCache,
renderState
);
}
function getTranslucentColorRenderState(oit, context, renderState) {
return getTranslucentRenderState2(
context,
translucentColorBlend,
oit._translucentRenderStateCache,
renderState
);
}
function getTranslucentAlphaRenderState(oit, context, renderState) {
return getTranslucentRenderState2(
context,
translucentAlphaBlend,
oit._alphaRenderStateCache,
renderState
);
}
var mrtShaderSource = " vec3 Ci = czm_out_FragColor.rgb * czm_out_FragColor.a;\n float ai = czm_out_FragColor.a;\n float wzi = czm_alphaWeight(ai);\n out_FragData_0 = vec4(Ci * wzi, ai);\n out_FragData_1 = vec4(ai * wzi);\n";
var colorShaderSource = " vec3 Ci = czm_out_FragColor.rgb * czm_out_FragColor.a;\n float ai = czm_out_FragColor.a;\n float wzi = czm_alphaWeight(ai);\n out_FragColor = vec4(Ci, ai) * wzi;\n";
var alphaShaderSource = " float ai = czm_out_FragColor.a;\n out_FragColor = vec4(ai);\n";
function getTranslucentShaderProgram2(context, shaderProgram, keyword, source) {
const { shaderCache } = context;
const shader = shaderCache.getDerivedShaderProgram(shaderProgram, keyword);
if (defined_default(shader)) {
return shader;
}
const attributeLocations8 = shaderProgram._attributeLocations;
const fs = shaderProgram.fragmentShaderSource.clone();
fs.sources = fs.sources.map(function(fsSource) {
return ShaderSource_default.replaceMain(fsSource, "czm_translucent_main").replace(/out_FragColor/g, "czm_out_FragColor").replace(
/layout\s*\(location\s*=\s*0\)\s*out\s+vec4\s+out_FragColor;/g,
""
).replace(/\bdiscard\b/g, "czm_discard = true").replace(/czm_phong/g, "czm_translucentPhong");
});
fs.sources.splice(
0,
0,
`vec4 czm_out_FragColor;
bool czm_discard = false;
`
);
const fragDataMatches = [...source.matchAll(/out_FragData_(\d+)/g)];
let fragDataDeclarations = ``;
for (let i = 0; i < fragDataMatches.length; i++) {
const fragDataMatch = fragDataMatches[i];
fragDataDeclarations = `layout (location = ${fragDataMatch[1]}) out vec4 ${fragDataMatch[0]};
${fragDataDeclarations}`;
}
fs.sources.push(fragDataDeclarations);
fs.sources.push(
`${"void main()\n{\n czm_translucent_main();\n if (czm_discard)\n {\n discard;\n }\n"}${source}}
`
);
return shaderCache.createDerivedShaderProgram(shaderProgram, keyword, {
vertexShaderSource: shaderProgram.vertexShaderSource,
fragmentShaderSource: fs,
attributeLocations: attributeLocations8
});
}
function getTranslucentMRTShaderProgram(context, shaderProgram) {
return getTranslucentShaderProgram2(
context,
shaderProgram,
"translucentMRT",
mrtShaderSource
);
}
function getTranslucentColorShaderProgram(context, shaderProgram) {
return getTranslucentShaderProgram2(
context,
shaderProgram,
"translucentMultipass",
colorShaderSource
);
}
function getTranslucentAlphaShaderProgram(context, shaderProgram) {
return getTranslucentShaderProgram2(
context,
shaderProgram,
"alphaMultipass",
alphaShaderSource
);
}
OIT.prototype.createDerivedCommands = function(command, context, result) {
if (!defined_default(result)) {
result = {};
}
if (this._translucentMRTSupport) {
let translucentShader;
let translucentRenderState;
if (defined_default(result.translucentCommand)) {
translucentShader = result.translucentCommand.shaderProgram;
translucentRenderState = result.translucentCommand.renderState;
}
result.translucentCommand = DrawCommand_default.shallowClone(
command,
result.translucentCommand
);
if (!defined_default(translucentShader) || result.shaderProgramId !== command.shaderProgram.id) {
result.translucentCommand.shaderProgram = getTranslucentMRTShaderProgram(
context,
command.shaderProgram
);
result.translucentCommand.renderState = getTranslucentMRTRenderState(
this,
context,
command.renderState
);
result.shaderProgramId = command.shaderProgram.id;
} else {
result.translucentCommand.shaderProgram = translucentShader;
result.translucentCommand.renderState = translucentRenderState;
}
return result;
}
let colorShader;
let colorRenderState3;
let alphaShader;
let alphaRenderState;
if (defined_default(result.translucentCommand)) {
colorShader = result.translucentCommand.shaderProgram;
colorRenderState3 = result.translucentCommand.renderState;
alphaShader = result.alphaCommand.shaderProgram;
alphaRenderState = result.alphaCommand.renderState;
}
result.translucentCommand = DrawCommand_default.shallowClone(
command,
result.translucentCommand
);
result.alphaCommand = DrawCommand_default.shallowClone(command, result.alphaCommand);
if (!defined_default(colorShader) || result.shaderProgramId !== command.shaderProgram.id) {
result.translucentCommand.shaderProgram = getTranslucentColorShaderProgram(
context,
command.shaderProgram
);
result.translucentCommand.renderState = getTranslucentColorRenderState(
this,
context,
command.renderState
);
result.alphaCommand.shaderProgram = getTranslucentAlphaShaderProgram(
context,
command.shaderProgram
);
result.alphaCommand.renderState = getTranslucentAlphaRenderState(
this,
context,
command.renderState
);
result.shaderProgramId = command.shaderProgram.id;
} else {
result.translucentCommand.shaderProgram = colorShader;
result.translucentCommand.renderState = colorRenderState3;
result.alphaCommand.shaderProgram = alphaShader;
result.alphaCommand.renderState = alphaRenderState;
}
return result;
};
function executeTranslucentCommandsSortedMultipass(oit, scene, executeFunction, passState, commands, invertClassification) {
const { context, frameState } = scene;
const { useLogDepth, shadowState } = frameState;
const useHdr = scene._hdr;
const framebuffer = passState.framebuffer;
const lightShadowsEnabled = shadowState.lightShadowsEnabled;
passState.framebuffer = oit._adjustTranslucentFBO.framebuffer;
oit._adjustTranslucentCommand.execute(context, passState);
passState.framebuffer = oit._adjustAlphaFBO.framebuffer;
oit._adjustAlphaCommand.execute(context, passState);
const debugFramebuffer = oit._opaqueFBO.framebuffer;
passState.framebuffer = oit._translucentFBO.framebuffer;
for (let j = 0; j < commands.length; ++j) {
let command = commands[j];
command = useLogDepth ? command.derivedCommands.logDepth.command : command;
command = useHdr ? command.derivedCommands.hdr.command : command;
const derivedCommand = lightShadowsEnabled && command.receiveShadows ? command.derivedCommands.oit.shadows.translucentCommand : command.derivedCommands.oit.translucentCommand;
executeFunction(derivedCommand, scene, passState, debugFramebuffer);
}
if (defined_default(invertClassification)) {
const command = invertClassification.unclassifiedCommand;
const derivedCommand = lightShadowsEnabled && command.receiveShadows ? command.derivedCommands.oit.shadows.translucentCommand : command.derivedCommands.oit.translucentCommand;
executeFunction(derivedCommand, scene, passState, debugFramebuffer);
}
passState.framebuffer = oit._alphaFBO.framebuffer;
for (let j = 0; j < commands.length; ++j) {
let command = commands[j];
command = useLogDepth ? command.derivedCommands.logDepth.command : command;
command = useHdr ? command.derivedCommands.hdr.command : command;
const derivedCommand = lightShadowsEnabled && command.receiveShadows ? command.derivedCommands.oit.shadows.alphaCommand : command.derivedCommands.oit.alphaCommand;
executeFunction(derivedCommand, scene, passState, debugFramebuffer);
}
if (defined_default(invertClassification)) {
const command = invertClassification.unclassifiedCommand;
const derivedCommand = lightShadowsEnabled && command.receiveShadows ? command.derivedCommands.oit.shadows.alphaCommand : command.derivedCommands.oit.alphaCommand;
executeFunction(derivedCommand, scene, passState, debugFramebuffer);
}
passState.framebuffer = framebuffer;
}
function executeTranslucentCommandsSortedMRT(oit, scene, executeFunction, passState, commands, invertClassification) {
const { context, frameState } = scene;
const { useLogDepth, shadowState } = frameState;
const useHdr = scene._hdr;
const framebuffer = passState.framebuffer;
const lightShadowsEnabled = shadowState.lightShadowsEnabled;
passState.framebuffer = oit._adjustTranslucentFBO.framebuffer;
oit._adjustTranslucentCommand.execute(context, passState);
const debugFramebuffer = oit._opaqueFBO.framebuffer;
passState.framebuffer = oit._translucentFBO.framebuffer;
for (let j = 0; j < commands.length; ++j) {
let command = commands[j];
command = useLogDepth ? command.derivedCommands.logDepth.command : command;
command = useHdr ? command.derivedCommands.hdr.command : command;
const derivedCommand = lightShadowsEnabled && command.receiveShadows ? command.derivedCommands.oit.shadows.translucentCommand : command.derivedCommands.oit.translucentCommand;
executeFunction(derivedCommand, scene, passState, debugFramebuffer);
}
if (defined_default(invertClassification)) {
const command = invertClassification.unclassifiedCommand;
const derivedCommand = lightShadowsEnabled && command.receiveShadows ? command.derivedCommands.oit.shadows.translucentCommand : command.derivedCommands.oit.translucentCommand;
executeFunction(derivedCommand, scene, passState, debugFramebuffer);
}
passState.framebuffer = framebuffer;
}
OIT.prototype.executeCommands = function(scene, executeFunction, passState, commands, invertClassification) {
if (this._translucentMRTSupport) {
executeTranslucentCommandsSortedMRT(
this,
scene,
executeFunction,
passState,
commands,
invertClassification
);
return;
}
executeTranslucentCommandsSortedMultipass(
this,
scene,
executeFunction,
passState,
commands,
invertClassification
);
};
OIT.prototype.execute = function(context, passState) {
this._compositeCommand.execute(context, passState);
};
OIT.prototype.clear = function(context, passState, clearColor) {
const framebuffer = passState.framebuffer;
passState.framebuffer = this._opaqueFBO.framebuffer;
Color_default.clone(clearColor, this._opaqueClearCommand.color);
this._opaqueClearCommand.execute(context, passState);
passState.framebuffer = this._translucentFBO.framebuffer;
const translucentClearCommand = this._translucentMRTSupport ? this._translucentMRTClearCommand : this._translucentMultipassClearCommand;
translucentClearCommand.execute(context, passState);
if (this._translucentMultipassSupport) {
passState.framebuffer = this._alphaFBO.framebuffer;
this._alphaClearCommand.execute(context, passState);
}
passState.framebuffer = framebuffer;
};
OIT.prototype.isSupported = function() {
return this._translucentMRTSupport || this._translucentMultipassSupport;
};
OIT.prototype.isDestroyed = function() {
return false;
};
OIT.prototype.destroy = function() {
destroyResources2(this);
if (defined_default(this._compositeCommand)) {
this._compositeCommand.shaderProgram = this._compositeCommand.shaderProgram && this._compositeCommand.shaderProgram.destroy();
}
if (defined_default(this._adjustTranslucentCommand)) {
this._adjustTranslucentCommand.shaderProgram = this._adjustTranslucentCommand.shaderProgram && this._adjustTranslucentCommand.shaderProgram.destroy();
}
if (defined_default(this._adjustAlphaCommand)) {
this._adjustAlphaCommand.shaderProgram = this._adjustAlphaCommand.shaderProgram && this._adjustAlphaCommand.shaderProgram.destroy();
}
return destroyObject_default(this);
};
var OIT_default = OIT;
// packages/engine/Source/Scene/PickDepthFramebuffer.js
var import_InlineWorkers1073 = __toESM(require_InlineWorkers(), 1);
function PickDepthFramebuffer() {
this._framebuffer = new FramebufferManager_default({
color: false,
depthStencil: true,
supportsDepthTexture: true
});
this._passState = void 0;
}
Object.defineProperties(PickDepthFramebuffer.prototype, {
framebuffer: {
get: function() {
return this._framebuffer.framebuffer;
}
}
});
function destroyResources3(pickDepth) {
pickDepth._framebuffer.destroy();
}
function createResources3(pickDepth, context) {
const width = context.drawingBufferWidth;
const height = context.drawingBufferHeight;
pickDepth._framebuffer.update(context, width, height);
const passState = new PassState_default(context);
passState.blendingEnabled = false;
passState.scissorTest = {
enabled: true,
rectangle: new BoundingRectangle_default()
};
passState.viewport = new BoundingRectangle_default();
pickDepth._passState = passState;
}
PickDepthFramebuffer.prototype.update = function(context, drawingBufferPosition, viewport) {
const width = viewport.width;
const height = viewport.height;
if (this._framebuffer.isDirty(width, height)) {
createResources3(this, context);
}
const framebuffer = this.framebuffer;
const passState = this._passState;
passState.framebuffer = framebuffer;
passState.viewport.width = width;
passState.viewport.height = height;
passState.scissorTest.rectangle.x = drawingBufferPosition.x;
passState.scissorTest.rectangle.y = height - drawingBufferPosition.y;
passState.scissorTest.rectangle.width = 1;
passState.scissorTest.rectangle.height = 1;
return passState;
};
PickDepthFramebuffer.prototype.isDestroyed = function() {
return false;
};
PickDepthFramebuffer.prototype.destroy = function() {
destroyResources3(this);
return destroyObject_default(this);
};
var PickDepthFramebuffer_default = PickDepthFramebuffer;
// packages/engine/Source/Scene/PickFramebuffer.js
var import_InlineWorkers1074 = __toESM(require_InlineWorkers(), 1);
function PickFramebuffer(context) {
const passState = new PassState_default(context);
passState.blendingEnabled = false;
passState.scissorTest = {
enabled: true,
rectangle: new BoundingRectangle_default()
};
passState.viewport = new BoundingRectangle_default();
this._context = context;
this._fb = new FramebufferManager_default({
depthStencil: true
});
this._passState = passState;
this._width = 0;
this._height = 0;
}
PickFramebuffer.prototype.begin = function(screenSpaceRectangle, viewport) {
const context = this._context;
const { width, height } = viewport;
BoundingRectangle_default.clone(
screenSpaceRectangle,
this._passState.scissorTest.rectangle
);
this._width = width;
this._height = height;
this._fb.update(context, width, height);
this._passState.framebuffer = this._fb.framebuffer;
this._passState.viewport.width = width;
this._passState.viewport.height = height;
return this._passState;
};
var colorScratchForPickFramebuffer = new Color_default();
PickFramebuffer.prototype.end = function(screenSpaceRectangle) {
const width = screenSpaceRectangle.width ?? 1;
const height = screenSpaceRectangle.height ?? 1;
const context = this._context;
const pixels = context.readPixels({
x: screenSpaceRectangle.x,
y: screenSpaceRectangle.y,
width,
height,
framebuffer: this._fb.framebuffer
});
const max3 = Math.max(width, height);
const length2 = max3 * max3;
const halfWidth = Math.floor(width * 0.5);
const halfHeight = Math.floor(height * 0.5);
let x = 0;
let y = 0;
let dx = 0;
let dy = -1;
for (let i = 0; i < length2; ++i) {
if (-halfWidth <= x && x <= halfWidth && -halfHeight <= y && y <= halfHeight) {
const index = 4 * ((halfHeight - y) * width + x + halfWidth);
colorScratchForPickFramebuffer.red = Color_default.byteToFloat(pixels[index]);
colorScratchForPickFramebuffer.green = Color_default.byteToFloat(
pixels[index + 1]
);
colorScratchForPickFramebuffer.blue = Color_default.byteToFloat(
pixels[index + 2]
);
colorScratchForPickFramebuffer.alpha = Color_default.byteToFloat(
pixels[index + 3]
);
const object2 = context.getObjectByPickColor(
colorScratchForPickFramebuffer
);
if (defined_default(object2)) {
return object2;
}
}
if (x === y || x < 0 && -x === y || x > 0 && x === 1 - y) {
const temp = dx;
dx = -dy;
dy = temp;
}
x += dx;
y += dy;
}
return void 0;
};
PickFramebuffer.prototype.readCenterPixel = function(screenSpaceRectangle) {
const width = screenSpaceRectangle.width ?? 1;
const height = screenSpaceRectangle.height ?? 1;
const context = this._context;
const pixels = context.readPixels({
x: screenSpaceRectangle.x,
y: screenSpaceRectangle.y,
width,
height,
framebuffer: this._fb.framebuffer
});
const halfWidth = Math.floor(width * 0.5);
const halfHeight = Math.floor(height * 0.5);
const index = 4 * (halfHeight * width + halfWidth);
return pixels.slice(index, index + 4);
};
PickFramebuffer.prototype.isDestroyed = function() {
return false;
};
PickFramebuffer.prototype.destroy = function() {
this._fb.destroy();
return destroyObject_default(this);
};
var PickFramebuffer_default = PickFramebuffer;
// packages/engine/Source/Scene/SceneFramebuffer.js
var import_InlineWorkers1075 = __toESM(require_InlineWorkers(), 1);
function SceneFramebuffer() {
this._numSamples = 1;
this._colorFramebuffer = new FramebufferManager_default({
depthStencil: true,
supportsDepthTexture: true
});
this._idFramebuffer = new FramebufferManager_default({
depthStencil: true,
supportsDepthTexture: true
});
this._idClearColor = new Color_default(0, 0, 0, 0);
this._clearCommand = new ClearCommand_default({
color: new Color_default(0, 0, 0, 0),
depth: 1,
owner: this
});
}
function destroyResources4(post) {
post._colorFramebuffer.destroy();
post._idFramebuffer.destroy();
}
Object.defineProperties(SceneFramebuffer.prototype, {
framebuffer: {
get: function() {
return this._colorFramebuffer.framebuffer;
}
},
idFramebuffer: {
get: function() {
return this._idFramebuffer.framebuffer;
}
},
depthStencilTexture: {
get: function() {
return this._colorFramebuffer.getDepthStencilTexture();
}
}
});
SceneFramebuffer.prototype.update = function(context, viewport, hdr, numSamples) {
const width = viewport.width;
const height = viewport.height;
const pixelDatatype = hdr ? context.halfFloatingPointTexture ? PixelDatatype_default.HALF_FLOAT : PixelDatatype_default.FLOAT : PixelDatatype_default.UNSIGNED_BYTE;
this._numSamples = numSamples;
this._colorFramebuffer.update(
context,
width,
height,
numSamples,
pixelDatatype
);
this._idFramebuffer.update(context, width, height);
};
SceneFramebuffer.prototype.clear = function(context, passState, clearColor) {
Color_default.clone(clearColor, this._clearCommand.color);
Color_default.clone(this._idClearColor, this._clearCommand.color);
this._colorFramebuffer.clear(context, this._clearCommand, passState);
this._idFramebuffer.clear(context, this._clearCommand, passState);
};
SceneFramebuffer.prototype.getFramebuffer = function() {
return this._colorFramebuffer.framebuffer;
};
SceneFramebuffer.prototype.getIdFramebuffer = function() {
return this._idFramebuffer.framebuffer;
};
SceneFramebuffer.prototype.prepareColorTextures = function(context) {
if (this._numSamples > 1) {
this._colorFramebuffer.prepareTextures(context);
}
};
SceneFramebuffer.prototype.isDestroyed = function() {
return false;
};
SceneFramebuffer.prototype.destroy = function() {
destroyResources4(this);
return destroyObject_default(this);
};
var SceneFramebuffer_default = SceneFramebuffer;
// packages/engine/Source/Scene/ShadowMap.js
var import_InlineWorkers1077 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/ShadowMapShader.js
var import_InlineWorkers1076 = __toESM(require_InlineWorkers(), 1);
function ShadowMapShader() {
}
ShadowMapShader.getShadowCastShaderKeyword = function(isPointLight, isTerrain, usesDepthTexture, isOpaque) {
return `castShadow ${isPointLight} ${isTerrain} ${usesDepthTexture} ${isOpaque}`;
};
ShadowMapShader.createShadowCastVertexShader = function(vs, isPointLight, isTerrain) {
const defines = vs.defines.slice(0);
const sources = vs.sources.slice(0);
defines.push("SHADOW_MAP");
if (isTerrain) {
defines.push("GENERATE_POSITION");
}
const positionVaryingName = ShaderSource_default.findPositionVarying(vs);
const hasPositionVarying = defined_default(positionVaryingName);
if (isPointLight && !hasPositionVarying) {
const length2 = sources.length;
for (let j = 0; j < length2; ++j) {
sources[j] = ShaderSource_default.replaceMain(sources[j], "czm_shadow_cast_main");
}
const shadowVS = "out vec3 v_positionEC; \nvoid main() \n{ \n czm_shadow_cast_main(); \n v_positionEC = (czm_inverseProjection * gl_Position).xyz; \n}";
sources.push(shadowVS);
}
return new ShaderSource_default({
defines,
sources
});
};
ShadowMapShader.createShadowCastFragmentShader = function(fs, isPointLight, usesDepthTexture, opaque) {
const defines = fs.defines.slice(0);
const sources = fs.sources.slice(0);
defines.push("SHADOW_MAP");
let positionVaryingName = ShaderSource_default.findPositionVarying(fs);
const hasPositionVarying = defined_default(positionVaryingName);
if (!hasPositionVarying) {
positionVaryingName = "v_positionEC";
}
const length2 = sources.length;
for (let i = 0; i < length2; ++i) {
sources[i] = ShaderSource_default.replaceMain(sources[i], "czm_shadow_cast_main");
}
let fsSource = "";
if (isPointLight) {
if (!hasPositionVarying) {
fsSource += "in vec3 v_positionEC; \n";
}
fsSource += "uniform vec4 shadowMap_lightPositionEC; \n";
}
if (opaque) {
fsSource += "void main() \n{ \n";
} else {
fsSource += "void main() \n{ \n czm_shadow_cast_main(); \n if (out_FragColor.a == 0.0) \n { \n discard; \n } \n";
}
if (isPointLight) {
fsSource += ` float distance = length(${positionVaryingName});
if (distance >= shadowMap_lightPositionEC.w)
{
discard;
}
distance /= shadowMap_lightPositionEC.w; // radius
out_FragColor = czm_packDepth(distance);
`;
} else if (usesDepthTexture) {
fsSource += " out_FragColor = vec4(1.0); \n";
} else {
fsSource += " out_FragColor = czm_packDepth(gl_FragCoord.z); \n";
}
fsSource += "} \n";
sources.push(fsSource);
return new ShaderSource_default({
defines,
sources
});
};
ShadowMapShader.getShadowReceiveShaderKeyword = function(shadowMap, castShadows, isTerrain, hasTerrainNormal) {
const usesDepthTexture = shadowMap._usesDepthTexture;
const polygonOffsetSupported = shadowMap._polygonOffsetSupported;
const isPointLight = shadowMap._isPointLight;
const isSpotLight = shadowMap._isSpotLight;
const hasCascades = shadowMap._numberOfCascades > 1;
const debugCascadeColors = shadowMap.debugCascadeColors;
const softShadows = shadowMap.softShadows;
return `receiveShadow ${usesDepthTexture}${polygonOffsetSupported}${isPointLight}${isSpotLight}${hasCascades}${debugCascadeColors}${softShadows}${castShadows}${isTerrain}${hasTerrainNormal}`;
};
ShadowMapShader.createShadowReceiveVertexShader = function(vs, isTerrain, hasTerrainNormal) {
const defines = vs.defines.slice(0);
const sources = vs.sources.slice(0);
defines.push("SHADOW_MAP");
if (isTerrain) {
if (hasTerrainNormal) {
defines.push("GENERATE_POSITION_AND_NORMAL");
} else {
defines.push("GENERATE_POSITION");
}
}
return new ShaderSource_default({
defines,
sources
});
};
ShadowMapShader.createShadowReceiveFragmentShader = function(fs, shadowMap, castShadows, isTerrain, hasTerrainNormal) {
const normalVaryingName = ShaderSource_default.findNormalVarying(fs);
const hasNormalVarying = !isTerrain && defined_default(normalVaryingName) || isTerrain && hasTerrainNormal;
const positionVaryingName = ShaderSource_default.findPositionVarying(fs);
const hasPositionVarying = defined_default(positionVaryingName);
const usesDepthTexture = shadowMap._usesDepthTexture;
const polygonOffsetSupported = shadowMap._polygonOffsetSupported;
const isPointLight = shadowMap._isPointLight;
const isSpotLight = shadowMap._isSpotLight;
const hasCascades = shadowMap._numberOfCascades > 1;
const debugCascadeColors = shadowMap.debugCascadeColors;
const softShadows = shadowMap.softShadows;
const bias = isPointLight ? shadowMap._pointBias : isTerrain ? shadowMap._terrainBias : shadowMap._primitiveBias;
const defines = fs.defines.slice(0);
const sources = fs.sources.slice(0);
const length2 = sources.length;
for (let i = 0; i < length2; ++i) {
sources[i] = ShaderSource_default.replaceMain(
sources[i],
"czm_shadow_receive_main"
);
}
if (isPointLight) {
defines.push("USE_CUBE_MAP_SHADOW");
} else if (usesDepthTexture) {
defines.push("USE_SHADOW_DEPTH_TEXTURE");
}
if (softShadows && !isPointLight) {
defines.push("USE_SOFT_SHADOWS");
}
if (hasCascades && castShadows && isTerrain) {
if (hasNormalVarying) {
defines.push("ENABLE_VERTEX_LIGHTING");
} else {
defines.push("ENABLE_DAYNIGHT_SHADING");
}
}
if (castShadows && bias.normalShading && hasNormalVarying) {
defines.push("USE_NORMAL_SHADING");
if (bias.normalShadingSmooth > 0) {
defines.push("USE_NORMAL_SHADING_SMOOTH");
}
}
let fsSource = "";
if (isPointLight) {
fsSource += "uniform samplerCube shadowMap_textureCube; \n";
} else {
fsSource += "uniform sampler2D shadowMap_texture; \n";
}
let returnPositionEC;
if (hasPositionVarying) {
returnPositionEC = ` return vec4(${positionVaryingName}, 1.0);
`;
} else {
returnPositionEC = "#ifndef LOG_DEPTH \n return czm_windowToEyeCoordinates(gl_FragCoord); \n#else \n return vec4(v_logPositionEC, 1.0); \n#endif \n";
}
fsSource += `${"uniform mat4 shadowMap_matrix; \nuniform vec3 shadowMap_lightDirectionEC; \nuniform vec4 shadowMap_lightPositionEC; \nuniform vec4 shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness; \nuniform vec4 shadowMap_texelSizeDepthBiasAndNormalShadingSmooth; \n#ifdef LOG_DEPTH \nin vec3 v_logPositionEC; \n#endif \nvec4 getPositionEC() \n{ \n"}${returnPositionEC}}
vec3 getNormalEC()
{
${hasNormalVarying ? ` return normalize(${normalVaryingName});
` : " return vec3(1.0); \n"}}
void applyNormalOffset(inout vec4 positionEC, vec3 normalEC, float nDotL)
{
${bias.normalOffset && hasNormalVarying ? " float normalOffset = shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.x; \n float normalOffsetScale = 1.0 - nDotL; \n vec3 offset = normalOffset * normalOffsetScale * normalEC; \n positionEC.xyz += offset; \n" : ""}}
`;
fsSource += "void main() \n{ \n czm_shadow_receive_main(); \n vec4 positionEC = getPositionEC(); \n vec3 normalEC = getNormalEC(); \n float depth = -positionEC.z; \n";
fsSource += " czm_shadowParameters shadowParameters; \n shadowParameters.texelStepSize = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.xy; \n shadowParameters.depthBias = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.z; \n shadowParameters.normalShadingSmooth = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.w; \n shadowParameters.darkness = shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.w; \n";
if (isTerrain) {
fsSource += " shadowParameters.depthBias *= max(depth * 0.01, 1.0); \n";
} else if (!polygonOffsetSupported) {
fsSource += " shadowParameters.depthBias *= mix(1.0, 100.0, depth * 0.0015); \n";
}
if (isPointLight) {
fsSource += " vec3 directionEC = positionEC.xyz - shadowMap_lightPositionEC.xyz; \n float distance = length(directionEC); \n directionEC = normalize(directionEC); \n float radius = shadowMap_lightPositionEC.w; \n // Stop early if the fragment is beyond the point light radius \n if (distance > radius) \n { \n return; \n } \n vec3 directionWC = czm_inverseViewRotation * directionEC; \n shadowParameters.depth = distance / radius; \n shadowParameters.nDotL = clamp(dot(normalEC, -directionEC), 0.0, 1.0); \n shadowParameters.texCoords = directionWC; \n float visibility = czm_shadowVisibility(shadowMap_textureCube, shadowParameters); \n";
} else if (isSpotLight) {
fsSource += " vec3 directionEC = normalize(positionEC.xyz - shadowMap_lightPositionEC.xyz); \n float nDotL = clamp(dot(normalEC, -directionEC), 0.0, 1.0); \n applyNormalOffset(positionEC, normalEC, nDotL); \n vec4 shadowPosition = shadowMap_matrix * positionEC; \n // Spot light uses a perspective projection, so perform the perspective divide \n shadowPosition /= shadowPosition.w; \n // Stop early if the fragment is not in the shadow bounds \n if (any(lessThan(shadowPosition.xyz, vec3(0.0))) || any(greaterThan(shadowPosition.xyz, vec3(1.0)))) \n { \n return; \n } \n shadowParameters.texCoords = shadowPosition.xy; \n shadowParameters.depth = shadowPosition.z; \n shadowParameters.nDotL = nDotL; \n float visibility = czm_shadowVisibility(shadowMap_texture, shadowParameters); \n";
} else if (hasCascades) {
fsSource += `${" float maxDepth = shadowMap_cascadeSplits[1].w; \n // Stop early if the eye depth exceeds the last cascade \n if (depth > maxDepth) \n { \n return; \n } \n // Get the cascade based on the eye-space depth \n vec4 weights = czm_cascadeWeights(depth); \n // Apply normal offset \n float nDotL = clamp(dot(normalEC, shadowMap_lightDirectionEC), 0.0, 1.0); \n applyNormalOffset(positionEC, normalEC, nDotL); \n // Transform position into the cascade \n vec4 shadowPosition = czm_cascadeMatrix(weights) * positionEC; \n // Get visibility \n shadowParameters.texCoords = shadowPosition.xy; \n shadowParameters.depth = shadowPosition.z; \n shadowParameters.nDotL = nDotL; \n float visibility = czm_shadowVisibility(shadowMap_texture, shadowParameters); \n // Fade out shadows that are far away \n float shadowMapMaximumDistance = shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.z; \n float fade = max((depth - shadowMapMaximumDistance * 0.8) / (shadowMapMaximumDistance * 0.2), 0.0); \n visibility = mix(visibility, 1.0, fade); \n"}${debugCascadeColors ? " // Draw cascade colors for debugging \n out_FragColor *= czm_cascadeColor(weights); \n" : ""}`;
} else {
fsSource += " float nDotL = clamp(dot(normalEC, shadowMap_lightDirectionEC), 0.0, 1.0); \n applyNormalOffset(positionEC, normalEC, nDotL); \n vec4 shadowPosition = shadowMap_matrix * positionEC; \n // Stop early if the fragment is not in the shadow bounds \n if (any(lessThan(shadowPosition.xyz, vec3(0.0))) || any(greaterThan(shadowPosition.xyz, vec3(1.0)))) \n { \n return; \n } \n shadowParameters.texCoords = shadowPosition.xy; \n shadowParameters.depth = shadowPosition.z; \n shadowParameters.nDotL = nDotL; \n float visibility = czm_shadowVisibility(shadowMap_texture, shadowParameters); \n";
}
fsSource += " out_FragColor.rgb *= visibility; \n} \n";
sources.push(fsSource);
return new ShaderSource_default({
defines,
sources
});
};
var ShadowMapShader_default = ShadowMapShader;
// packages/engine/Source/Scene/ShadowMap.js
function ShadowMap(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const context = options.context;
if (!defined_default(context)) {
throw new DeveloperError_default("context is required.");
}
if (!defined_default(options.lightCamera)) {
throw new DeveloperError_default("lightCamera is required.");
}
if (defined_default(options.numberOfCascades) && options.numberOfCascades !== 1 && options.numberOfCascades !== 4) {
throw new DeveloperError_default("Only one or four cascades are supported.");
}
this._enabled = options.enabled ?? true;
this._softShadows = options.softShadows ?? false;
this._normalOffset = options.normalOffset ?? true;
this.dirty = true;
this.fromLightSource = options.fromLightSource ?? true;
this.darkness = options.darkness ?? 0.3;
this._darkness = this.darkness;
this.fadingEnabled = options.fadingEnabled ?? true;
this.maximumDistance = options.maximumDistance ?? 5e3;
this._outOfView = false;
this._outOfViewPrevious = false;
this._needsUpdate = true;
let polygonOffsetSupported = true;
if (FeatureDetection_default.isInternetExplorer() || FeatureDetection_default.isEdge() || (FeatureDetection_default.isChrome() || FeatureDetection_default.isFirefox()) && FeatureDetection_default.isWindows() && !context.depthTexture) {
polygonOffsetSupported = false;
}
this._polygonOffsetSupported = polygonOffsetSupported;
this._terrainBias = {
polygonOffset: polygonOffsetSupported,
polygonOffsetFactor: 1.1,
polygonOffsetUnits: 4,
normalOffset: this._normalOffset,
normalOffsetScale: 0.5,
normalShading: true,
normalShadingSmooth: 0.3,
depthBias: 1e-4
};
this._primitiveBias = {
polygonOffset: polygonOffsetSupported,
polygonOffsetFactor: 1.1,
polygonOffsetUnits: 4,
normalOffset: this._normalOffset,
normalOffsetScale: 0.1,
normalShading: true,
normalShadingSmooth: 0.05,
depthBias: 2e-5
};
this._pointBias = {
polygonOffset: false,
polygonOffsetFactor: 1.1,
polygonOffsetUnits: 4,
normalOffset: this._normalOffset,
normalOffsetScale: 0,
normalShading: true,
normalShadingSmooth: 0.1,
depthBias: 5e-4
};
this._depthAttachment = void 0;
this._colorAttachment = void 0;
this._shadowMapMatrix = new Matrix4_default();
this._shadowMapTexture = void 0;
this._lightDirectionEC = new Cartesian3_default();
this._lightPositionEC = new Cartesian4_default();
this._distance = 0;
this._lightCamera = options.lightCamera;
this._shadowMapCamera = new ShadowMapCamera();
this._shadowMapCullingVolume = void 0;
this._sceneCamera = void 0;
this._boundingSphere = new BoundingSphere_default();
this._isPointLight = options.isPointLight ?? false;
this._pointLightRadius = options.pointLightRadius ?? 100;
this._cascadesEnabled = this._isPointLight ? false : options.cascadesEnabled ?? true;
this._numberOfCascades = !this._cascadesEnabled ? 0 : options.numberOfCascades ?? 4;
this._fitNearFar = true;
this._maximumCascadeDistances = [25, 150, 700, Number.MAX_VALUE];
this._textureSize = new Cartesian2_default();
this._isSpotLight = false;
if (this._cascadesEnabled) {
this._shadowMapCamera.frustum = new OrthographicOffCenterFrustum_default();
} else if (defined_default(this._lightCamera.frustum.fov)) {
this._isSpotLight = true;
}
this._cascadeSplits = [new Cartesian4_default(), new Cartesian4_default()];
this._cascadeMatrices = [
new Matrix4_default(),
new Matrix4_default(),
new Matrix4_default(),
new Matrix4_default()
];
this._cascadeDistances = new Cartesian4_default();
let numberOfPasses;
if (this._isPointLight) {
numberOfPasses = 6;
} else if (!this._cascadesEnabled) {
numberOfPasses = 1;
} else {
numberOfPasses = this._numberOfCascades;
}
this._passes = new Array(numberOfPasses);
for (let i = 0; i < numberOfPasses; ++i) {
this._passes[i] = new ShadowPass(context);
}
this.debugShow = false;
this.debugFreezeFrame = false;
this._debugFreezeFrame = false;
this._debugCascadeColors = false;
this._debugLightFrustum = void 0;
this._debugCameraFrustum = void 0;
this._debugCascadeFrustums = new Array(this._numberOfCascades);
this._debugShadowViewCommand = void 0;
this._usesDepthTexture = context.depthTexture;
if (this._isPointLight) {
this._usesDepthTexture = false;
}
this._primitiveRenderState = void 0;
this._terrainRenderState = void 0;
this._pointRenderState = void 0;
createRenderStates6(this);
this._clearCommand = new ClearCommand_default({
depth: 1,
color: new Color_default()
});
this._clearPassState = new PassState_default(context);
this._size = options.size ?? 2048;
this.size = this._size;
}
ShadowMap.MAXIMUM_DISTANCE = 2e4;
function ShadowPass(context) {
this.camera = new ShadowMapCamera();
this.passState = new PassState_default(context);
this.framebuffer = void 0;
this.textureOffsets = void 0;
this.commandList = [];
this.cullingVolume = void 0;
}
function createRenderState2(colorMask, bias) {
return RenderState_default.fromCache({
cull: {
enabled: true,
face: CullFace_default.BACK
},
depthTest: {
enabled: true
},
colorMask: {
red: colorMask,
green: colorMask,
blue: colorMask,
alpha: colorMask
},
depthMask: true,
polygonOffset: {
enabled: bias.polygonOffset,
factor: bias.polygonOffsetFactor,
units: bias.polygonOffsetUnits
}
});
}
function createRenderStates6(shadowMap) {
const colorMask = !shadowMap._usesDepthTexture;
shadowMap._primitiveRenderState = createRenderState2(
colorMask,
shadowMap._primitiveBias
);
shadowMap._terrainRenderState = createRenderState2(
colorMask,
shadowMap._terrainBias
);
shadowMap._pointRenderState = createRenderState2(
colorMask,
shadowMap._pointBias
);
}
ShadowMap.prototype.debugCreateRenderStates = function() {
createRenderStates6(this);
};
Object.defineProperties(ShadowMap.prototype, {
/**
* Determines if the shadow map will be shown.
*
* @memberof ShadowMap.prototype
* @type {boolean}
* @default true
*/
enabled: {
get: function() {
return this._enabled;
},
set: function(value) {
this.dirty = this._enabled !== value;
this._enabled = value;
}
},
/**
* Determines if a normal bias will be applied to shadows.
*
* @memberof ShadowMap.prototype
* @type {boolean}
* @default true
*/
normalOffset: {
get: function() {
return this._normalOffset;
},
set: function(value) {
this.dirty = this._normalOffset !== value;
this._normalOffset = value;
this._terrainBias.normalOffset = value;
this._primitiveBias.normalOffset = value;
this._pointBias.normalOffset = value;
}
},
/**
* Determines if soft shadows are enabled. Uses pcf filtering which requires more texture reads and may hurt performance.
*
* @memberof ShadowMap.prototype
* @type {boolean}
* @default false
*/
softShadows: {
get: function() {
return this._softShadows;
},
set: function(value) {
this.dirty = this._softShadows !== value;
this._softShadows = value;
}
},
/**
* The width and height, in pixels, of each shadow map.
*
* @memberof ShadowMap.prototype
* @type {number}
* @default 2048
*/
size: {
get: function() {
return this._size;
},
set: function(value) {
resize(this, value);
}
},
/**
* Whether the shadow map is out of view of the scene camera.
*
* @memberof ShadowMap.prototype
* @type {boolean}
* @readonly
* @private
*/
outOfView: {
get: function() {
return this._outOfView;
}
},
/**
* The culling volume of the shadow frustum.
*
* @memberof ShadowMap.prototype
* @type {CullingVolume}
* @readonly
* @private
*/
shadowMapCullingVolume: {
get: function() {
return this._shadowMapCullingVolume;
}
},
/**
* The passes used for rendering shadows. Each face of a point light or each cascade for a cascaded shadow map is a separate pass.
*
* @memberof ShadowMap.prototype
* @type {ShadowPass[]}
* @readonly
* @private
*/
passes: {
get: function() {
return this._passes;
}
},
/**
* Whether the light source is a point light.
*
* @memberof ShadowMap.prototype
* @type {boolean}
* @readonly
* @private
*/
isPointLight: {
get: function() {
return this._isPointLight;
}
},
/**
* Debug option for visualizing the cascades by color.
*
* @memberof ShadowMap.prototype
* @type {boolean}
* @default false
* @private
*/
debugCascadeColors: {
get: function() {
return this._debugCascadeColors;
},
set: function(value) {
this.dirty = this._debugCascadeColors !== value;
this._debugCascadeColors = value;
}
}
});
function destroyFramebuffer2(shadowMap) {
const length2 = shadowMap._passes.length;
for (let i = 0; i < length2; ++i) {
const pass = shadowMap._passes[i];
const framebuffer = pass.framebuffer;
if (defined_default(framebuffer) && !framebuffer.isDestroyed()) {
framebuffer.destroy();
}
pass.framebuffer = void 0;
}
shadowMap._depthAttachment = shadowMap._depthAttachment && shadowMap._depthAttachment.destroy();
shadowMap._colorAttachment = shadowMap._colorAttachment && shadowMap._colorAttachment.destroy();
}
function createFramebufferColor(shadowMap, context) {
const depthRenderbuffer = new Renderbuffer_default({
context,
width: shadowMap._textureSize.x,
height: shadowMap._textureSize.y,
format: RenderbufferFormat_default.DEPTH_COMPONENT16
});
const colorTexture = new Texture_default({
context,
width: shadowMap._textureSize.x,
height: shadowMap._textureSize.y,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
sampler: Sampler_default.NEAREST
});
const framebuffer = new Framebuffer_default({
context,
depthRenderbuffer,
colorTextures: [colorTexture],
destroyAttachments: false
});
const length2 = shadowMap._passes.length;
for (let i = 0; i < length2; ++i) {
const pass = shadowMap._passes[i];
pass.framebuffer = framebuffer;
pass.passState.framebuffer = framebuffer;
}
shadowMap._shadowMapTexture = colorTexture;
shadowMap._depthAttachment = depthRenderbuffer;
shadowMap._colorAttachment = colorTexture;
}
function createFramebufferDepth(shadowMap, context) {
const depthStencilTexture = new Texture_default({
context,
width: shadowMap._textureSize.x,
height: shadowMap._textureSize.y,
pixelFormat: PixelFormat_default.DEPTH_STENCIL,
pixelDatatype: PixelDatatype_default.UNSIGNED_INT_24_8,
sampler: Sampler_default.NEAREST
});
const framebuffer = new Framebuffer_default({
context,
depthStencilTexture,
destroyAttachments: false
});
const length2 = shadowMap._passes.length;
for (let i = 0; i < length2; ++i) {
const pass = shadowMap._passes[i];
pass.framebuffer = framebuffer;
pass.passState.framebuffer = framebuffer;
}
shadowMap._shadowMapTexture = depthStencilTexture;
shadowMap._depthAttachment = depthStencilTexture;
}
function createFramebufferCube(shadowMap, context) {
const depthRenderbuffer = new Renderbuffer_default({
context,
width: shadowMap._textureSize.x,
height: shadowMap._textureSize.y,
format: RenderbufferFormat_default.DEPTH_COMPONENT16
});
const cubeMap = new CubeMap_default({
context,
width: shadowMap._textureSize.x,
height: shadowMap._textureSize.y,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
sampler: Sampler_default.NEAREST
});
const faces2 = [
cubeMap.negativeX,
cubeMap.negativeY,
cubeMap.negativeZ,
cubeMap.positiveX,
cubeMap.positiveY,
cubeMap.positiveZ
];
for (let i = 0; i < 6; ++i) {
const framebuffer = new Framebuffer_default({
context,
depthRenderbuffer,
colorTextures: [faces2[i]],
destroyAttachments: false
});
const pass = shadowMap._passes[i];
pass.framebuffer = framebuffer;
pass.passState.framebuffer = framebuffer;
}
shadowMap._shadowMapTexture = cubeMap;
shadowMap._depthAttachment = depthRenderbuffer;
shadowMap._colorAttachment = cubeMap;
}
function createFramebuffer2(shadowMap, context) {
if (shadowMap._isPointLight) {
createFramebufferCube(shadowMap, context);
} else if (shadowMap._usesDepthTexture) {
createFramebufferDepth(shadowMap, context);
} else {
createFramebufferColor(shadowMap, context);
}
}
function checkFramebuffer(shadowMap, context) {
if (shadowMap._usesDepthTexture && shadowMap._passes[0].framebuffer.status !== WebGLConstants_default.FRAMEBUFFER_COMPLETE) {
shadowMap._usesDepthTexture = false;
createRenderStates6(shadowMap);
destroyFramebuffer2(shadowMap);
createFramebuffer2(shadowMap, context);
}
}
function updateFramebuffer(shadowMap, context) {
if (!defined_default(shadowMap._passes[0].framebuffer) || shadowMap._shadowMapTexture.width !== shadowMap._textureSize.x) {
destroyFramebuffer2(shadowMap);
createFramebuffer2(shadowMap, context);
checkFramebuffer(shadowMap, context);
clearFramebuffer(shadowMap, context);
}
}
function clearFramebuffer(shadowMap, context, shadowPass) {
shadowPass = shadowPass ?? 0;
if (shadowMap._isPointLight || shadowPass === 0) {
shadowMap._clearCommand.framebuffer = shadowMap._passes[shadowPass].framebuffer;
shadowMap._clearCommand.execute(context, shadowMap._clearPassState);
}
}
function resize(shadowMap, size) {
shadowMap._size = size;
const passes = shadowMap._passes;
const numberOfPasses = passes.length;
const textureSize = shadowMap._textureSize;
if (shadowMap._isPointLight) {
size = ContextLimits_default.maximumCubeMapSize >= size ? size : ContextLimits_default.maximumCubeMapSize;
textureSize.x = size;
textureSize.y = size;
const faceViewport = new BoundingRectangle_default(0, 0, size, size);
passes[0].passState.viewport = faceViewport;
passes[1].passState.viewport = faceViewport;
passes[2].passState.viewport = faceViewport;
passes[3].passState.viewport = faceViewport;
passes[4].passState.viewport = faceViewport;
passes[5].passState.viewport = faceViewport;
} else if (numberOfPasses === 1) {
size = ContextLimits_default.maximumTextureSize >= size ? size : ContextLimits_default.maximumTextureSize;
textureSize.x = size;
textureSize.y = size;
passes[0].passState.viewport = new BoundingRectangle_default(0, 0, size, size);
} else if (numberOfPasses === 4) {
size = ContextLimits_default.maximumTextureSize >= size * 2 ? size : ContextLimits_default.maximumTextureSize / 2;
textureSize.x = size * 2;
textureSize.y = size * 2;
passes[0].passState.viewport = new BoundingRectangle_default(0, 0, size, size);
passes[1].passState.viewport = new BoundingRectangle_default(size, 0, size, size);
passes[2].passState.viewport = new BoundingRectangle_default(0, size, size, size);
passes[3].passState.viewport = new BoundingRectangle_default(
size,
size,
size,
size
);
}
shadowMap._clearPassState.viewport = new BoundingRectangle_default(
0,
0,
textureSize.x,
textureSize.y
);
for (let i = 0; i < numberOfPasses; ++i) {
const pass = passes[i];
const viewport = pass.passState.viewport;
const biasX = viewport.x / textureSize.x;
const biasY = viewport.y / textureSize.y;
const scaleX = viewport.width / textureSize.x;
const scaleY = viewport.height / textureSize.y;
pass.textureOffsets = new Matrix4_default(
scaleX,
0,
0,
biasX,
0,
scaleY,
0,
biasY,
0,
0,
1,
0,
0,
0,
0,
1
);
}
}
var scratchViewport3 = new BoundingRectangle_default();
function createDebugShadowViewCommand(shadowMap, context) {
let fs;
if (shadowMap._isPointLight) {
fs = "uniform samplerCube shadowMap_textureCube; \nin vec2 v_textureCoordinates; \nvoid main() \n{ \n vec2 uv = v_textureCoordinates; \n vec3 dir; \n \n if (uv.y < 0.5) \n { \n if (uv.x < 0.333) \n { \n dir.x = -1.0; \n dir.y = uv.x * 6.0 - 1.0; \n dir.z = uv.y * 4.0 - 1.0; \n } \n else if (uv.x < 0.666) \n { \n dir.y = -1.0; \n dir.x = uv.x * 6.0 - 3.0; \n dir.z = uv.y * 4.0 - 1.0; \n } \n else \n { \n dir.z = -1.0; \n dir.x = uv.x * 6.0 - 5.0; \n dir.y = uv.y * 4.0 - 1.0; \n } \n } \n else \n { \n if (uv.x < 0.333) \n { \n dir.x = 1.0; \n dir.y = uv.x * 6.0 - 1.0; \n dir.z = uv.y * 4.0 - 3.0; \n } \n else if (uv.x < 0.666) \n { \n dir.y = 1.0; \n dir.x = uv.x * 6.0 - 3.0; \n dir.z = uv.y * 4.0 - 3.0; \n } \n else \n { \n dir.z = 1.0; \n dir.x = uv.x * 6.0 - 5.0; \n dir.y = uv.y * 4.0 - 3.0; \n } \n } \n \n float shadow = czm_unpackDepth(czm_textureCube(shadowMap_textureCube, dir)); \n out_FragColor = vec4(vec3(shadow), 1.0); \n} \n";
} else {
fs = `${"uniform sampler2D shadowMap_texture; \nin vec2 v_textureCoordinates; \nvoid main() \n{ \n"}${shadowMap._usesDepthTexture ? " float shadow = texture(shadowMap_texture, v_textureCoordinates).r; \n" : " float shadow = czm_unpackDepth(texture(shadowMap_texture, v_textureCoordinates)); \n"} out_FragColor = vec4(vec3(shadow), 1.0);
}
`;
}
const drawCommand = context.createViewportQuadCommand(fs, {
uniformMap: {
shadowMap_texture: function() {
return shadowMap._shadowMapTexture;
},
shadowMap_textureCube: function() {
return shadowMap._shadowMapTexture;
}
}
});
drawCommand.pass = Pass_default.OVERLAY;
return drawCommand;
}
function updateDebugShadowViewCommand(shadowMap, frameState) {
const context = frameState.context;
const screenWidth = frameState.context.drawingBufferWidth;
const screenHeight = frameState.context.drawingBufferHeight;
const size = Math.min(screenWidth, screenHeight) * 0.3;
const viewport = scratchViewport3;
viewport.x = screenWidth - size;
viewport.y = 0;
viewport.width = size;
viewport.height = size;
let debugCommand = shadowMap._debugShadowViewCommand;
if (!defined_default(debugCommand)) {
debugCommand = createDebugShadowViewCommand(shadowMap, context);
shadowMap._debugShadowViewCommand = debugCommand;
}
if (!defined_default(debugCommand.renderState) || !BoundingRectangle_default.equals(debugCommand.renderState.viewport, viewport)) {
debugCommand.renderState = RenderState_default.fromCache({
viewport: BoundingRectangle_default.clone(viewport)
});
}
frameState.commandList.push(shadowMap._debugShadowViewCommand);
}
var frustumCornersNDC2 = new Array(8);
frustumCornersNDC2[0] = new Cartesian4_default(-1, -1, -1, 1);
frustumCornersNDC2[1] = new Cartesian4_default(1, -1, -1, 1);
frustumCornersNDC2[2] = new Cartesian4_default(1, 1, -1, 1);
frustumCornersNDC2[3] = new Cartesian4_default(-1, 1, -1, 1);
frustumCornersNDC2[4] = new Cartesian4_default(-1, -1, 1, 1);
frustumCornersNDC2[5] = new Cartesian4_default(1, -1, 1, 1);
frustumCornersNDC2[6] = new Cartesian4_default(1, 1, 1, 1);
frustumCornersNDC2[7] = new Cartesian4_default(-1, 1, 1, 1);
var scratchMatrix6 = new Matrix4_default();
var scratchFrustumCorners2 = new Array(8);
for (let i = 0; i < 8; ++i) {
scratchFrustumCorners2[i] = new Cartesian4_default();
}
function createDebugPointLight(modelMatrix, color) {
const box = new GeometryInstance_default({
geometry: new BoxOutlineGeometry_default({
minimum: new Cartesian3_default(-0.5, -0.5, -0.5),
maximum: new Cartesian3_default(0.5, 0.5, 0.5)
}),
attributes: {
color: ColorGeometryInstanceAttribute_default.fromColor(color)
}
});
const sphere = new GeometryInstance_default({
geometry: new SphereOutlineGeometry_default({
radius: 0.5
}),
attributes: {
color: ColorGeometryInstanceAttribute_default.fromColor(color)
}
});
return new Primitive_default({
geometryInstances: [box, sphere],
appearance: new PerInstanceColorAppearance_default({
translucent: false,
flat: true
}),
asynchronous: false,
modelMatrix
});
}
var debugOutlineColors = [Color_default.RED, Color_default.GREEN, Color_default.BLUE, Color_default.MAGENTA];
var scratchScale5 = new Cartesian3_default();
function applyDebugSettings2(shadowMap, frameState) {
updateDebugShadowViewCommand(shadowMap, frameState);
const enterFreezeFrame = shadowMap.debugFreezeFrame && !shadowMap._debugFreezeFrame;
shadowMap._debugFreezeFrame = shadowMap.debugFreezeFrame;
if (shadowMap.debugFreezeFrame) {
if (enterFreezeFrame) {
shadowMap._debugCameraFrustum = shadowMap._debugCameraFrustum && shadowMap._debugCameraFrustum.destroy();
shadowMap._debugCameraFrustum = new DebugCameraPrimitive_default({
camera: shadowMap._sceneCamera,
color: Color_default.CYAN,
updateOnChange: false
});
}
shadowMap._debugCameraFrustum.update(frameState);
}
if (shadowMap._cascadesEnabled) {
if (shadowMap.debugFreezeFrame) {
if (enterFreezeFrame) {
shadowMap._debugLightFrustum = shadowMap._debugLightFrustum && shadowMap._debugLightFrustum.destroy();
shadowMap._debugLightFrustum = new DebugCameraPrimitive_default({
camera: shadowMap._shadowMapCamera,
color: Color_default.YELLOW,
updateOnChange: false
});
}
shadowMap._debugLightFrustum.update(frameState);
for (let i = 0; i < shadowMap._numberOfCascades; ++i) {
if (enterFreezeFrame) {
shadowMap._debugCascadeFrustums[i] = shadowMap._debugCascadeFrustums[i] && shadowMap._debugCascadeFrustums[i].destroy();
shadowMap._debugCascadeFrustums[i] = new DebugCameraPrimitive_default({
camera: shadowMap._passes[i].camera,
color: debugOutlineColors[i],
updateOnChange: false
});
}
shadowMap._debugCascadeFrustums[i].update(frameState);
}
}
} else if (shadowMap._isPointLight) {
if (!defined_default(shadowMap._debugLightFrustum) || shadowMap._needsUpdate) {
const translation3 = shadowMap._shadowMapCamera.positionWC;
const rotation = Quaternion_default.IDENTITY;
const uniformScale = shadowMap._pointLightRadius * 2;
const scale = Cartesian3_default.fromElements(
uniformScale,
uniformScale,
uniformScale,
scratchScale5
);
const modelMatrix = Matrix4_default.fromTranslationQuaternionRotationScale(
translation3,
rotation,
scale,
scratchMatrix6
);
shadowMap._debugLightFrustum = shadowMap._debugLightFrustum && shadowMap._debugLightFrustum.destroy();
shadowMap._debugLightFrustum = createDebugPointLight(
modelMatrix,
Color_default.YELLOW
);
}
shadowMap._debugLightFrustum.update(frameState);
} else {
if (!defined_default(shadowMap._debugLightFrustum) || shadowMap._needsUpdate) {
shadowMap._debugLightFrustum = new DebugCameraPrimitive_default({
camera: shadowMap._shadowMapCamera,
color: Color_default.YELLOW,
updateOnChange: false
});
}
shadowMap._debugLightFrustum.update(frameState);
}
}
function ShadowMapCamera() {
this.viewMatrix = new Matrix4_default();
this.inverseViewMatrix = new Matrix4_default();
this.frustum = void 0;
this.positionCartographic = new Cartographic_default();
this.positionWC = new Cartesian3_default();
this.directionWC = Cartesian3_default.clone(Cartesian3_default.UNIT_Z);
this.upWC = Cartesian3_default.clone(Cartesian3_default.UNIT_Y);
this.rightWC = Cartesian3_default.clone(Cartesian3_default.UNIT_X);
this.viewProjectionMatrix = new Matrix4_default();
}
ShadowMapCamera.prototype.clone = function(camera) {
Matrix4_default.clone(camera.viewMatrix, this.viewMatrix);
Matrix4_default.clone(camera.inverseViewMatrix, this.inverseViewMatrix);
this.frustum = camera.frustum.clone(this.frustum);
Cartographic_default.clone(camera.positionCartographic, this.positionCartographic);
Cartesian3_default.clone(camera.positionWC, this.positionWC);
Cartesian3_default.clone(camera.directionWC, this.directionWC);
Cartesian3_default.clone(camera.upWC, this.upWC);
Cartesian3_default.clone(camera.rightWC, this.rightWC);
};
var scaleBiasMatrix = new Matrix4_default(
0.5,
0,
0,
0.5,
0,
0.5,
0,
0.5,
0,
0,
0.5,
0.5,
0,
0,
0,
1
);
ShadowMapCamera.prototype.getViewProjection = function() {
const view = this.viewMatrix;
const projection = this.frustum.projectionMatrix;
Matrix4_default.multiply(projection, view, this.viewProjectionMatrix);
Matrix4_default.multiply(
scaleBiasMatrix,
this.viewProjectionMatrix,
this.viewProjectionMatrix
);
return this.viewProjectionMatrix;
};
var scratchSplits2 = new Array(5);
var scratchFrustum = new PerspectiveFrustum_default();
var scratchCascadeDistances = new Array(4);
var scratchMin4 = new Cartesian3_default();
var scratchMax4 = new Cartesian3_default();
function computeCascades(shadowMap, frameState) {
const shadowMapCamera = shadowMap._shadowMapCamera;
const sceneCamera = shadowMap._sceneCamera;
const cameraNear = sceneCamera.frustum.near;
const cameraFar = sceneCamera.frustum.far;
const numberOfCascades = shadowMap._numberOfCascades;
let i;
const range = cameraFar - cameraNear;
const ratio = cameraFar / cameraNear;
let lambda = 0.9;
let clampCascadeDistances = false;
if (frameState.shadowState.closestObjectSize < 200) {
clampCascadeDistances = true;
lambda = 0.9;
}
const cascadeDistances = scratchCascadeDistances;
const splits = scratchSplits2;
splits[0] = cameraNear;
splits[numberOfCascades] = cameraFar;
for (i = 0; i < numberOfCascades; ++i) {
const p = (i + 1) / numberOfCascades;
const logScale = cameraNear * Math.pow(ratio, p);
const uniformScale = cameraNear + range * p;
const split = Math_default.lerp(uniformScale, logScale, lambda);
splits[i + 1] = split;
cascadeDistances[i] = split - splits[i];
}
if (clampCascadeDistances) {
for (i = 0; i < numberOfCascades; ++i) {
cascadeDistances[i] = Math.min(
cascadeDistances[i],
shadowMap._maximumCascadeDistances[i]
);
}
let distance2 = splits[0];
for (i = 0; i < numberOfCascades - 1; ++i) {
distance2 += cascadeDistances[i];
splits[i + 1] = distance2;
}
}
Cartesian4_default.unpack(splits, 0, shadowMap._cascadeSplits[0]);
Cartesian4_default.unpack(splits, 1, shadowMap._cascadeSplits[1]);
Cartesian4_default.unpack(cascadeDistances, 0, shadowMap._cascadeDistances);
const shadowFrustum = shadowMapCamera.frustum;
const left = shadowFrustum.left;
const right = shadowFrustum.right;
const bottom = shadowFrustum.bottom;
const top = shadowFrustum.top;
const near = shadowFrustum.near;
const far = shadowFrustum.far;
const position = shadowMapCamera.positionWC;
const direction2 = shadowMapCamera.directionWC;
const up = shadowMapCamera.upWC;
const cascadeSubFrustum = sceneCamera.frustum.clone(scratchFrustum);
const shadowViewProjection = shadowMapCamera.getViewProjection();
for (i = 0; i < numberOfCascades; ++i) {
cascadeSubFrustum.near = splits[i];
cascadeSubFrustum.far = splits[i + 1];
const viewProjection = Matrix4_default.multiply(
cascadeSubFrustum.projectionMatrix,
sceneCamera.viewMatrix,
scratchMatrix6
);
const inverseViewProjection = Matrix4_default.inverse(
viewProjection,
scratchMatrix6
);
const shadowMapMatrix = Matrix4_default.multiply(
shadowViewProjection,
inverseViewProjection,
scratchMatrix6
);
const min3 = Cartesian3_default.fromElements(
Number.MAX_VALUE,
Number.MAX_VALUE,
Number.MAX_VALUE,
scratchMin4
);
const max3 = Cartesian3_default.fromElements(
-Number.MAX_VALUE,
-Number.MAX_VALUE,
-Number.MAX_VALUE,
scratchMax4
);
for (let k = 0; k < 8; ++k) {
const corner = Cartesian4_default.clone(
frustumCornersNDC2[k],
scratchFrustumCorners2[k]
);
Matrix4_default.multiplyByVector(shadowMapMatrix, corner, corner);
Cartesian3_default.divideByScalar(corner, corner.w, corner);
Cartesian3_default.minimumByComponent(corner, min3, min3);
Cartesian3_default.maximumByComponent(corner, max3, max3);
}
min3.x = Math.max(min3.x, 0);
min3.y = Math.max(min3.y, 0);
min3.z = 0;
max3.x = Math.min(max3.x, 1);
max3.y = Math.min(max3.y, 1);
max3.z = Math.min(max3.z, 1);
const pass = shadowMap._passes[i];
const cascadeCamera = pass.camera;
cascadeCamera.clone(shadowMapCamera);
const frustum = cascadeCamera.frustum;
frustum.left = left + min3.x * (right - left);
frustum.right = left + max3.x * (right - left);
frustum.bottom = bottom + min3.y * (top - bottom);
frustum.top = bottom + max3.y * (top - bottom);
frustum.near = near + min3.z * (far - near);
frustum.far = near + max3.z * (far - near);
pass.cullingVolume = cascadeCamera.frustum.computeCullingVolume(
position,
direction2,
up
);
const cascadeMatrix = shadowMap._cascadeMatrices[i];
Matrix4_default.multiply(
cascadeCamera.getViewProjection(),
sceneCamera.inverseViewMatrix,
cascadeMatrix
);
Matrix4_default.multiply(pass.textureOffsets, cascadeMatrix, cascadeMatrix);
}
}
var scratchLightView = new Matrix4_default();
var scratchRight3 = new Cartesian3_default();
var scratchUp2 = new Cartesian3_default();
var scratchTranslation2 = new Cartesian3_default();
function fitShadowMapToScene(shadowMap, frameState) {
const shadowMapCamera = shadowMap._shadowMapCamera;
const sceneCamera = shadowMap._sceneCamera;
const viewProjection = Matrix4_default.multiply(
sceneCamera.frustum.projectionMatrix,
sceneCamera.viewMatrix,
scratchMatrix6
);
const inverseViewProjection = Matrix4_default.inverse(viewProjection, scratchMatrix6);
const lightDir = shadowMapCamera.directionWC;
let lightUp = sceneCamera.directionWC;
if (Cartesian3_default.equalsEpsilon(lightDir, lightUp, Math_default.EPSILON10)) {
lightUp = sceneCamera.upWC;
}
const lightRight = Cartesian3_default.cross(lightDir, lightUp, scratchRight3);
lightUp = Cartesian3_default.cross(lightRight, lightDir, scratchUp2);
Cartesian3_default.normalize(lightUp, lightUp);
Cartesian3_default.normalize(lightRight, lightRight);
const lightPosition = Cartesian3_default.fromElements(
0,
0,
0,
scratchTranslation2
);
let lightView = Matrix4_default.computeView(
lightPosition,
lightDir,
lightUp,
lightRight,
scratchLightView
);
const cameraToLight = Matrix4_default.multiply(
lightView,
inverseViewProjection,
scratchMatrix6
);
const min3 = Cartesian3_default.fromElements(
Number.MAX_VALUE,
Number.MAX_VALUE,
Number.MAX_VALUE,
scratchMin4
);
const max3 = Cartesian3_default.fromElements(
-Number.MAX_VALUE,
-Number.MAX_VALUE,
-Number.MAX_VALUE,
scratchMax4
);
for (let i = 0; i < 8; ++i) {
const corner = Cartesian4_default.clone(
frustumCornersNDC2[i],
scratchFrustumCorners2[i]
);
Matrix4_default.multiplyByVector(cameraToLight, corner, corner);
Cartesian3_default.divideByScalar(corner, corner.w, corner);
Cartesian3_default.minimumByComponent(corner, min3, min3);
Cartesian3_default.maximumByComponent(corner, max3, max3);
}
max3.z += 1e3;
min3.z -= 10;
const translation3 = scratchTranslation2;
translation3.x = -(0.5 * (min3.x + max3.x));
translation3.y = -(0.5 * (min3.y + max3.y));
translation3.z = -max3.z;
const translationMatrix = Matrix4_default.fromTranslation(translation3, scratchMatrix6);
lightView = Matrix4_default.multiply(translationMatrix, lightView, lightView);
const halfWidth = 0.5 * (max3.x - min3.x);
const halfHeight = 0.5 * (max3.y - min3.y);
const depth = max3.z - min3.z;
const frustum = shadowMapCamera.frustum;
frustum.left = -halfWidth;
frustum.right = halfWidth;
frustum.bottom = -halfHeight;
frustum.top = halfHeight;
frustum.near = 0.01;
frustum.far = depth;
Matrix4_default.clone(lightView, shadowMapCamera.viewMatrix);
Matrix4_default.inverse(lightView, shadowMapCamera.inverseViewMatrix);
Matrix4_default.getTranslation(
shadowMapCamera.inverseViewMatrix,
shadowMapCamera.positionWC
);
frameState.mapProjection.ellipsoid.cartesianToCartographic(
shadowMapCamera.positionWC,
shadowMapCamera.positionCartographic
);
Cartesian3_default.clone(lightDir, shadowMapCamera.directionWC);
Cartesian3_default.clone(lightUp, shadowMapCamera.upWC);
Cartesian3_default.clone(lightRight, shadowMapCamera.rightWC);
}
var directions = [
new Cartesian3_default(-1, 0, 0),
new Cartesian3_default(0, -1, 0),
new Cartesian3_default(0, 0, -1),
new Cartesian3_default(1, 0, 0),
new Cartesian3_default(0, 1, 0),
new Cartesian3_default(0, 0, 1)
];
var ups = [
new Cartesian3_default(0, -1, 0),
new Cartesian3_default(0, 0, -1),
new Cartesian3_default(0, -1, 0),
new Cartesian3_default(0, -1, 0),
new Cartesian3_default(0, 0, 1),
new Cartesian3_default(0, -1, 0)
];
var rights = [
new Cartesian3_default(0, 0, 1),
new Cartesian3_default(1, 0, 0),
new Cartesian3_default(-1, 0, 0),
new Cartesian3_default(0, 0, -1),
new Cartesian3_default(1, 0, 0),
new Cartesian3_default(1, 0, 0)
];
function computeOmnidirectional(shadowMap, frameState) {
const frustum = new PerspectiveFrustum_default();
frustum.fov = Math_default.PI_OVER_TWO;
frustum.near = 1;
frustum.far = shadowMap._pointLightRadius;
frustum.aspectRatio = 1;
for (let i = 0; i < 6; ++i) {
const camera = shadowMap._passes[i].camera;
camera.positionWC = shadowMap._shadowMapCamera.positionWC;
camera.positionCartographic = frameState.mapProjection.ellipsoid.cartesianToCartographic(
camera.positionWC,
camera.positionCartographic
);
camera.directionWC = directions[i];
camera.upWC = ups[i];
camera.rightWC = rights[i];
Matrix4_default.computeView(
camera.positionWC,
camera.directionWC,
camera.upWC,
camera.rightWC,
camera.viewMatrix
);
Matrix4_default.inverse(camera.viewMatrix, camera.inverseViewMatrix);
camera.frustum = frustum;
}
}
var scratchCartesian114 = new Cartesian3_default();
var scratchCartesian212 = new Cartesian3_default();
var scratchBoundingSphere6 = new BoundingSphere_default();
var scratchCenter9 = scratchBoundingSphere6.center;
function checkVisibility(shadowMap, frameState) {
const sceneCamera = shadowMap._sceneCamera;
const shadowMapCamera = shadowMap._shadowMapCamera;
const boundingSphere = scratchBoundingSphere6;
if (shadowMap._cascadesEnabled) {
if (sceneCamera.frustum.near >= shadowMap.maximumDistance) {
shadowMap._outOfView = true;
shadowMap._needsUpdate = false;
return;
}
const surfaceNormal = frameState.mapProjection.ellipsoid.geodeticSurfaceNormal(
sceneCamera.positionWC,
scratchCartesian114
);
const lightDirection = Cartesian3_default.negate(
shadowMapCamera.directionWC,
scratchCartesian212
);
const dot2 = Cartesian3_default.dot(surfaceNormal, lightDirection);
if (shadowMap.fadingEnabled) {
const darknessAmount = Math_default.clamp(dot2 / 0.1, 0, 1);
shadowMap._darkness = Math_default.lerp(
1,
shadowMap.darkness,
darknessAmount
);
} else {
shadowMap._darkness = shadowMap.darkness;
}
if (dot2 < 0) {
shadowMap._outOfView = true;
shadowMap._needsUpdate = false;
return;
}
shadowMap._needsUpdate = true;
shadowMap._outOfView = false;
} else if (shadowMap._isPointLight) {
boundingSphere.center = shadowMapCamera.positionWC;
boundingSphere.radius = shadowMap._pointLightRadius;
shadowMap._outOfView = frameState.cullingVolume.computeVisibility(boundingSphere) === Intersect_default.OUTSIDE;
shadowMap._needsUpdate = !shadowMap._outOfView && !shadowMap._boundingSphere.equals(boundingSphere);
BoundingSphere_default.clone(boundingSphere, shadowMap._boundingSphere);
} else {
const frustumRadius = shadowMapCamera.frustum.far / 2;
const frustumCenter = Cartesian3_default.add(
shadowMapCamera.positionWC,
Cartesian3_default.multiplyByScalar(
shadowMapCamera.directionWC,
frustumRadius,
scratchCenter9
),
scratchCenter9
);
boundingSphere.center = frustumCenter;
boundingSphere.radius = frustumRadius;
shadowMap._outOfView = frameState.cullingVolume.computeVisibility(boundingSphere) === Intersect_default.OUTSIDE;
shadowMap._needsUpdate = !shadowMap._outOfView && !shadowMap._boundingSphere.equals(boundingSphere);
BoundingSphere_default.clone(boundingSphere, shadowMap._boundingSphere);
}
}
function updateCameras(shadowMap, frameState) {
const camera = frameState.camera;
const lightCamera = shadowMap._lightCamera;
const sceneCamera = shadowMap._sceneCamera;
const shadowMapCamera = shadowMap._shadowMapCamera;
if (shadowMap._cascadesEnabled) {
Cartesian3_default.clone(lightCamera.directionWC, shadowMapCamera.directionWC);
} else if (shadowMap._isPointLight) {
Cartesian3_default.clone(lightCamera.positionWC, shadowMapCamera.positionWC);
} else {
shadowMapCamera.clone(lightCamera);
}
const lightDirection = shadowMap._lightDirectionEC;
Matrix4_default.multiplyByPointAsVector(
camera.viewMatrix,
shadowMapCamera.directionWC,
lightDirection
);
Cartesian3_default.normalize(lightDirection, lightDirection);
Cartesian3_default.negate(lightDirection, lightDirection);
Matrix4_default.multiplyByPoint(
camera.viewMatrix,
shadowMapCamera.positionWC,
shadowMap._lightPositionEC
);
shadowMap._lightPositionEC.w = shadowMap._pointLightRadius;
let near;
let far;
if (shadowMap._fitNearFar) {
near = Math.min(
frameState.shadowState.nearPlane,
shadowMap.maximumDistance
);
far = Math.min(frameState.shadowState.farPlane, shadowMap.maximumDistance);
far = Math.max(far, near + 1);
} else {
near = camera.frustum.near;
far = shadowMap.maximumDistance;
}
shadowMap._sceneCamera = Camera_default.clone(camera, sceneCamera);
camera.frustum.clone(shadowMap._sceneCamera.frustum);
shadowMap._sceneCamera.frustum.near = near;
shadowMap._sceneCamera.frustum.far = far;
shadowMap._distance = far - near;
checkVisibility(shadowMap, frameState);
if (!shadowMap._outOfViewPrevious && shadowMap._outOfView) {
shadowMap._needsUpdate = true;
}
shadowMap._outOfViewPrevious = shadowMap._outOfView;
}
ShadowMap.prototype.update = function(frameState) {
updateCameras(this, frameState);
if (this._needsUpdate) {
updateFramebuffer(this, frameState.context);
if (this._isPointLight) {
computeOmnidirectional(this, frameState);
}
if (this._cascadesEnabled) {
fitShadowMapToScene(this, frameState);
if (this._numberOfCascades > 1) {
computeCascades(this, frameState);
}
}
if (!this._isPointLight) {
const shadowMapCamera = this._shadowMapCamera;
const position = shadowMapCamera.positionWC;
const direction2 = shadowMapCamera.directionWC;
const up = shadowMapCamera.upWC;
this._shadowMapCullingVolume = shadowMapCamera.frustum.computeCullingVolume(position, direction2, up);
if (this._passes.length === 1) {
this._passes[0].camera.clone(shadowMapCamera);
}
} else {
this._shadowMapCullingVolume = CullingVolume_default.fromBoundingSphere(
this._boundingSphere
);
}
}
if (this._passes.length === 1) {
const inverseView = this._sceneCamera.inverseViewMatrix;
Matrix4_default.multiply(
this._shadowMapCamera.getViewProjection(),
inverseView,
this._shadowMapMatrix
);
}
if (this.debugShow) {
applyDebugSettings2(this, frameState);
}
};
ShadowMap.prototype.updatePass = function(context, shadowPass) {
clearFramebuffer(this, context, shadowPass);
};
var scratchTexelStepSize = new Cartesian2_default();
function combineUniforms(shadowMap, uniforms, isTerrain) {
const bias = shadowMap._isPointLight ? shadowMap._pointBias : isTerrain ? shadowMap._terrainBias : shadowMap._primitiveBias;
const mapUniforms = {
shadowMap_texture: function() {
return shadowMap._shadowMapTexture;
},
shadowMap_textureCube: function() {
return shadowMap._shadowMapTexture;
},
shadowMap_matrix: function() {
return shadowMap._shadowMapMatrix;
},
shadowMap_cascadeSplits: function() {
return shadowMap._cascadeSplits;
},
shadowMap_cascadeMatrices: function() {
return shadowMap._cascadeMatrices;
},
shadowMap_lightDirectionEC: function() {
return shadowMap._lightDirectionEC;
},
shadowMap_lightPositionEC: function() {
return shadowMap._lightPositionEC;
},
shadowMap_cascadeDistances: function() {
return shadowMap._cascadeDistances;
},
shadowMap_texelSizeDepthBiasAndNormalShadingSmooth: function() {
const texelStepSize = scratchTexelStepSize;
texelStepSize.x = 1 / shadowMap._textureSize.x;
texelStepSize.y = 1 / shadowMap._textureSize.y;
return Cartesian4_default.fromElements(
texelStepSize.x,
texelStepSize.y,
bias.depthBias,
bias.normalShadingSmooth,
this.combinedUniforms1
);
},
shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness: function() {
return Cartesian4_default.fromElements(
bias.normalOffsetScale,
shadowMap._distance,
shadowMap.maximumDistance,
shadowMap._darkness,
this.combinedUniforms2
);
},
combinedUniforms1: new Cartesian4_default(),
combinedUniforms2: new Cartesian4_default()
};
return combine_default(uniforms, mapUniforms, false);
}
function createCastDerivedCommand(shadowMap, shadowsDirty, command, context, oldShaderId, result) {
let castShader;
let castRenderState;
let castUniformMap;
if (defined_default(result)) {
castShader = result.shaderProgram;
castRenderState = result.renderState;
castUniformMap = result.uniformMap;
}
result = DrawCommand_default.shallowClone(command, result);
result.castShadows = true;
result.receiveShadows = false;
if (!defined_default(castShader) || oldShaderId !== command.shaderProgram.id || shadowsDirty) {
const shaderProgram = command.shaderProgram;
const isTerrain = command.pass === Pass_default.GLOBE;
const isOpaque = command.pass !== Pass_default.TRANSLUCENT;
const isPointLight = shadowMap._isPointLight;
const usesDepthTexture = shadowMap._usesDepthTexture;
const keyword = ShadowMapShader_default.getShadowCastShaderKeyword(
isPointLight,
isTerrain,
usesDepthTexture,
isOpaque
);
castShader = context.shaderCache.getDerivedShaderProgram(
shaderProgram,
keyword
);
if (!defined_default(castShader)) {
const vertexShaderSource = shaderProgram.vertexShaderSource;
const fragmentShaderSource = shaderProgram.fragmentShaderSource;
const castVS = ShadowMapShader_default.createShadowCastVertexShader(
vertexShaderSource,
isPointLight,
isTerrain
);
const castFS = ShadowMapShader_default.createShadowCastFragmentShader(
fragmentShaderSource,
isPointLight,
usesDepthTexture,
isOpaque
);
castShader = context.shaderCache.createDerivedShaderProgram(
shaderProgram,
keyword,
{
vertexShaderSource: castVS,
fragmentShaderSource: castFS,
attributeLocations: shaderProgram._attributeLocations
}
);
}
castRenderState = shadowMap._primitiveRenderState;
if (isPointLight) {
castRenderState = shadowMap._pointRenderState;
} else if (isTerrain) {
castRenderState = shadowMap._terrainRenderState;
}
const cullEnabled = command.renderState.cull.enabled;
if (!cullEnabled) {
castRenderState = clone_default(castRenderState, false);
castRenderState.cull = clone_default(castRenderState.cull, false);
castRenderState.cull.enabled = false;
castRenderState = RenderState_default.fromCache(castRenderState);
}
castUniformMap = combineUniforms(shadowMap, command.uniformMap, isTerrain);
}
result.shaderProgram = castShader;
result.renderState = castRenderState;
result.uniformMap = castUniformMap;
return result;
}
ShadowMap.createReceiveDerivedCommand = function(lightShadowMaps, command, shadowsDirty, context, result) {
if (!defined_default(result)) {
result = {};
}
const lightShadowMapsEnabled = lightShadowMaps.length > 0;
const shaderProgram = command.shaderProgram;
const vertexShaderSource = shaderProgram.vertexShaderSource;
const fragmentShaderSource = shaderProgram.fragmentShaderSource;
const isTerrain = command.pass === Pass_default.GLOBE;
let hasTerrainNormal = false;
if (isTerrain) {
hasTerrainNormal = command.owner.data.renderedMesh.encoding.hasVertexNormals;
}
if (command.receiveShadows && lightShadowMapsEnabled) {
let receiveShader;
let receiveUniformMap;
if (defined_default(result.receiveCommand)) {
receiveShader = result.receiveCommand.shaderProgram;
receiveUniformMap = result.receiveCommand.uniformMap;
}
result.receiveCommand = DrawCommand_default.shallowClone(
command,
result.receiveCommand
);
result.castShadows = false;
result.receiveShadows = true;
const castShadowsDirty = result.receiveShaderCastShadows !== command.castShadows;
const shaderDirty = result.receiveShaderProgramId !== command.shaderProgram.id;
if (!defined_default(receiveShader) || shaderDirty || shadowsDirty || castShadowsDirty) {
const keyword = ShadowMapShader_default.getShadowReceiveShaderKeyword(
lightShadowMaps[0],
command.castShadows,
isTerrain,
hasTerrainNormal
);
receiveShader = context.shaderCache.getDerivedShaderProgram(
shaderProgram,
keyword
);
if (!defined_default(receiveShader)) {
const receiveVS = ShadowMapShader_default.createShadowReceiveVertexShader(
vertexShaderSource,
isTerrain,
hasTerrainNormal
);
const receiveFS = ShadowMapShader_default.createShadowReceiveFragmentShader(
fragmentShaderSource,
lightShadowMaps[0],
command.castShadows,
isTerrain,
hasTerrainNormal
);
receiveShader = context.shaderCache.createDerivedShaderProgram(
shaderProgram,
keyword,
{
vertexShaderSource: receiveVS,
fragmentShaderSource: receiveFS,
attributeLocations: shaderProgram._attributeLocations
}
);
}
receiveUniformMap = combineUniforms(
lightShadowMaps[0],
command.uniformMap,
isTerrain
);
}
result.receiveCommand.shaderProgram = receiveShader;
result.receiveCommand.uniformMap = receiveUniformMap;
result.receiveShaderProgramId = command.shaderProgram.id;
result.receiveShaderCastShadows = command.castShadows;
}
return result;
};
ShadowMap.createCastDerivedCommand = function(shadowMaps, command, shadowsDirty, context, result) {
if (!defined_default(result)) {
result = {};
}
if (command.castShadows) {
let castCommands = result.castCommands;
if (!defined_default(castCommands)) {
castCommands = result.castCommands = [];
}
const oldShaderId = result.castShaderProgramId;
const shadowMapLength = shadowMaps.length;
castCommands.length = shadowMapLength;
for (let i = 0; i < shadowMapLength; ++i) {
castCommands[i] = createCastDerivedCommand(
shadowMaps[i],
shadowsDirty,
command,
context,
oldShaderId,
castCommands[i]
);
}
result.castShaderProgramId = command.shaderProgram.id;
}
return result;
};
ShadowMap.prototype.isDestroyed = function() {
return false;
};
ShadowMap.prototype.destroy = function() {
destroyFramebuffer2(this);
this._debugLightFrustum = this._debugLightFrustum && this._debugLightFrustum.destroy();
this._debugCameraFrustum = this._debugCameraFrustum && this._debugCameraFrustum.destroy();
this._debugShadowViewCommand = this._debugShadowViewCommand && this._debugShadowViewCommand.shaderProgram && this._debugShadowViewCommand.shaderProgram.destroy();
for (let i = 0; i < this._numberOfCascades; ++i) {
this._debugCascadeFrustums[i] = this._debugCascadeFrustums[i] && this._debugCascadeFrustums[i].destroy();
}
return destroyObject_default(this);
};
var ShadowMap_default = ShadowMap;
// packages/engine/Source/Scene/TranslucentTileClassification.js
var import_InlineWorkers1080 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/CompareAndPackTranslucentDepth.js
var import_InlineWorkers1078 = __toESM(require_InlineWorkers(), 1);
var CompareAndPackTranslucentDepth_default = "uniform sampler2D u_opaqueDepthTexture;\nuniform sampler2D u_translucentDepthTexture;\n\nin vec2 v_textureCoordinates;\n\nvoid main()\n{\n float opaqueDepth = texture(u_opaqueDepthTexture, v_textureCoordinates).r;\n float translucentDepth = texture(u_translucentDepthTexture, v_textureCoordinates).r;\n translucentDepth = czm_branchFreeTernary(translucentDepth > opaqueDepth, 1.0, translucentDepth);\n out_FragColor = czm_packDepth(translucentDepth);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/CompositeTranslucentClassification.js
var import_InlineWorkers1079 = __toESM(require_InlineWorkers(), 1);
var CompositeTranslucentClassification_default = "uniform sampler2D colorTexture;\n\n#ifdef DEBUG_SHOW_DEPTH\nuniform sampler2D u_packedTranslucentDepth;\n#endif\n\nin vec2 v_textureCoordinates;\n\nvoid main()\n{\n#ifdef DEBUG_SHOW_DEPTH\n if (v_textureCoordinates.x < 0.5)\n {\n out_FragColor.rgb = vec3(czm_unpackDepth(texture(u_packedTranslucentDepth, v_textureCoordinates)));\n out_FragColor.a = 1.0;\n }\n#else\n vec4 color = texture(colorTexture, v_textureCoordinates);\n\n#ifdef PICK\n if (color == vec4(0.0))\n {\n discard;\n }\n#else\n // Reverse premultiplication process to get the correct composited result of the classification primitives\n color.rgb /= color.a;\n#endif\n out_FragColor = color;\n#endif\n}\n";
// packages/engine/Source/Scene/TranslucentTileClassification.js
var debugShowPackedDepth = false;
function TranslucentTileClassification(context) {
this._drawClassificationFBO = new FramebufferManager_default({
createDepthAttachments: false
});
this._accumulationFBO = new FramebufferManager_default({
createDepthAttachments: false
});
this._packFBO = new FramebufferManager_default();
this._opaqueDepthStencilTexture = void 0;
this._textureToComposite = void 0;
this._translucentDepthStencilTexture = void 0;
this._packDepthCommand = void 0;
this._accumulateCommand = void 0;
this._compositeCommand = void 0;
this._copyCommand = void 0;
this._clearColorCommand = new ClearCommand_default({
color: new Color_default(0, 0, 0, 0),
owner: this
});
this._clearDepthStencilCommand = new ClearCommand_default({
depth: 1,
stencil: 0,
owner: this
});
this._supported = context.depthTexture;
this._viewport = new BoundingRectangle_default();
this._rsDepth = void 0;
this._rsAccumulate = void 0;
this._rsComp = void 0;
this._useScissorTest = void 0;
this._scissorRectangle = void 0;
this._hasTranslucentDepth = false;
this._frustumsDrawn = 0;
}
Object.defineProperties(TranslucentTileClassification.prototype, {
/**
* Gets whether or not translucent depth was rendered.
* @memberof TranslucentTileClassification.prototype
*
* @type {boolean}
* @readonly
*/
hasTranslucentDepth: {
get: function() {
return this._hasTranslucentDepth;
}
}
});
function destroyTextures2(transpClass) {
transpClass._textureToComposite = void 0;
transpClass._translucentDepthStencilTexture = transpClass._translucentDepthStencilTexture && !transpClass._translucentDepthStencilTexture.isDestroyed() && transpClass._translucentDepthStencilTexture.destroy();
}
function destroyFramebuffers2(transpClass) {
transpClass._drawClassificationFBO.destroy();
transpClass._accumulationFBO.destroy();
transpClass._packFBO.destroy();
}
function updateTextures2(transpClass, context, width, height) {
destroyTextures2(transpClass);
transpClass._translucentDepthStencilTexture = new Texture_default({
context,
width,
height,
pixelFormat: PixelFormat_default.DEPTH_STENCIL,
pixelDatatype: PixelDatatype_default.UNSIGNED_INT_24_8,
sampler: Sampler_default.NEAREST
});
}
function updateFramebuffers3(transpClass, context, width, height) {
destroyFramebuffers2(transpClass);
transpClass._drawClassificationFBO.setDepthStencilTexture(
transpClass._translucentDepthStencilTexture
);
transpClass._drawClassificationFBO.update(context, width, height);
transpClass._accumulationFBO.setDepthStencilTexture(
transpClass._translucentDepthStencilTexture
);
transpClass._accumulationFBO.update(context, width, height);
transpClass._packFBO.update(context, width, height);
}
function updateResources2(transpClass, context, passState, globeDepthStencilTexture) {
if (!transpClass.isSupported()) {
return;
}
transpClass._opaqueDepthStencilTexture = globeDepthStencilTexture;
const width = transpClass._opaqueDepthStencilTexture.width;
const height = transpClass._opaqueDepthStencilTexture.height;
if (transpClass._drawClassificationFBO.isDirty(width, height)) {
updateTextures2(transpClass, context, width, height);
updateFramebuffers3(transpClass, context, width, height);
}
let fs;
let uniformMap2;
if (!defined_default(transpClass._packDepthCommand)) {
fs = new ShaderSource_default({
sources: [CompareAndPackTranslucentDepth_default]
});
uniformMap2 = {
u_opaqueDepthTexture: function() {
return transpClass._opaqueDepthStencilTexture;
},
u_translucentDepthTexture: function() {
return transpClass._translucentDepthStencilTexture;
}
};
transpClass._packDepthCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap2,
owner: transpClass
});
}
if (!defined_default(transpClass._compositeCommand)) {
fs = new ShaderSource_default({
sources: [CompositeTranslucentClassification_default]
});
uniformMap2 = {
colorTexture: function() {
return transpClass._textureToComposite;
}
};
if (debugShowPackedDepth) {
fs.defines = ["DEBUG_SHOW_DEPTH"];
uniformMap2.u_packedTranslucentDepth = function() {
return transpClass._packFBO.getColorTexture();
};
}
transpClass._compositeCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap2,
owner: transpClass
});
const compositeCommand = transpClass._compositeCommand;
const compositeProgram = compositeCommand.shaderProgram;
const compositePickProgram = context.shaderCache.createDerivedShaderProgram(
compositeProgram,
"pick",
{
vertexShaderSource: compositeProgram.vertexShaderSource,
fragmentShaderSource: new ShaderSource_default({
sources: fs.sources,
defines: ["PICK"]
}),
attributeLocations: compositeProgram._attributeLocations
}
);
const compositePickCommand = DrawCommand_default.shallowClone(compositeCommand);
compositePickCommand.shaderProgram = compositePickProgram;
compositeCommand.derivedCommands.pick = compositePickCommand;
}
if (!defined_default(transpClass._copyCommand)) {
fs = new ShaderSource_default({
sources: [CompositeTranslucentClassification_default]
});
uniformMap2 = {
colorTexture: function() {
return transpClass._drawClassificationFBO.getColorTexture();
}
};
transpClass._copyCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap2,
owner: transpClass
});
}
if (!defined_default(transpClass._accumulateCommand)) {
fs = new ShaderSource_default({
sources: [CompositeTranslucentClassification_default]
});
uniformMap2 = {
colorTexture: function() {
return transpClass._drawClassificationFBO.getColorTexture();
}
};
transpClass._accumulateCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap2,
owner: transpClass
});
}
transpClass._viewport.width = width;
transpClass._viewport.height = height;
const useScissorTest = !BoundingRectangle_default.equals(
transpClass._viewport,
passState.viewport
);
let updateScissor = useScissorTest !== transpClass._useScissorTest;
transpClass._useScissorTest = useScissorTest;
if (!BoundingRectangle_default.equals(transpClass._scissorRectangle, passState.viewport)) {
transpClass._scissorRectangle = BoundingRectangle_default.clone(
passState.viewport,
transpClass._scissorRectangle
);
updateScissor = true;
}
if (!defined_default(transpClass._rsDepth) || !BoundingRectangle_default.equals(
transpClass._viewport,
transpClass._rsDepth.viewport
) || updateScissor) {
transpClass._rsDepth = RenderState_default.fromCache({
viewport: transpClass._viewport,
scissorTest: {
enabled: transpClass._useScissorTest,
rectangle: transpClass._scissorRectangle
}
});
}
if (defined_default(transpClass._packDepthCommand)) {
transpClass._packDepthCommand.renderState = transpClass._rsDepth;
}
if (!defined_default(transpClass._rsAccumulate) || !BoundingRectangle_default.equals(
transpClass._viewport,
transpClass._rsAccumulate.viewport
) || updateScissor) {
transpClass._rsAccumulate = RenderState_default.fromCache({
viewport: transpClass._viewport,
scissorTest: {
enabled: transpClass._useScissorTest,
rectangle: transpClass._scissorRectangle
},
stencilTest: {
enabled: true,
frontFunction: StencilFunction_default.EQUAL,
reference: StencilConstants_default.CESIUM_3D_TILE_MASK
}
});
}
if (defined_default(transpClass._accumulateCommand)) {
transpClass._accumulateCommand.renderState = transpClass._rsAccumulate;
}
if (!defined_default(transpClass._rsComp) || !BoundingRectangle_default.equals(
transpClass._viewport,
transpClass._rsComp.viewport
) || updateScissor) {
transpClass._rsComp = RenderState_default.fromCache({
viewport: transpClass._viewport,
scissorTest: {
enabled: transpClass._useScissorTest,
rectangle: transpClass._scissorRectangle
},
blending: BlendingState_default.ALPHA_BLEND
});
}
if (defined_default(transpClass._compositeCommand)) {
transpClass._compositeCommand.renderState = transpClass._rsComp;
transpClass._compositeCommand.derivedCommands.pick.renderState = transpClass._rsComp;
}
}
TranslucentTileClassification.prototype.executeTranslucentCommands = function(scene, executeCommand2, passState, commands, globeDepthStencilTexture) {
const useLogDepth = scene.frameState.useLogDepth;
const context = scene.context;
const framebuffer = passState.framebuffer;
for (let i = 0; i < commands.length; ++i) {
let command = commands[i];
command = useLogDepth ? command.derivedCommands.logDepth.command : command;
if (command.depthForTranslucentClassification) {
this._hasTranslucentDepth = true;
break;
}
}
if (!this._hasTranslucentDepth) {
return;
}
updateResources2(this, context, passState, globeDepthStencilTexture);
passState.framebuffer = this._drawClassificationFBO.framebuffer;
this._clearDepthStencilCommand.execute(context, passState);
for (let i = 0; i < commands.length; ++i) {
let command = commands[i];
command = useLogDepth ? command.derivedCommands.logDepth.command : command;
if (!command.depthForTranslucentClassification) {
continue;
}
const depthOnlyCommand = command.derivedCommands.depth.depthOnlyCommand;
executeCommand2(depthOnlyCommand, scene, passState);
}
this._frustumsDrawn += this._hasTranslucentDepth ? 1 : 0;
if (this._hasTranslucentDepth) {
passState.framebuffer = this._packFBO.framebuffer;
this._packDepthCommand.execute(context, passState);
}
passState.framebuffer = framebuffer;
};
TranslucentTileClassification.prototype.executeClassificationCommands = function(scene, executeCommand2, passState, frustumCommands) {
if (!this._hasTranslucentDepth) {
return;
}
const context = scene.context;
const uniformState = context.uniformState;
const framebuffer = passState.framebuffer;
passState.framebuffer = this._accumulationFBO.framebuffer;
this._accumulateCommand.execute(context, passState);
passState.framebuffer = this._drawClassificationFBO.framebuffer;
if (this._frustumsDrawn > 1) {
this._clearColorCommand.execute(context, passState);
}
uniformState.updatePass(Pass_default.CESIUM_3D_TILE_CLASSIFICATION);
const swapGlobeDepth = uniformState.globeDepthTexture;
uniformState.globeDepthTexture = this._packFBO.getColorTexture();
const commands = frustumCommands.commands[Pass_default.CESIUM_3D_TILE_CLASSIFICATION];
const length2 = frustumCommands.indices[Pass_default.CESIUM_3D_TILE_CLASSIFICATION];
for (let i = 0; i < length2; ++i) {
executeCommand2(commands[i], scene, passState);
}
uniformState.globeDepthTexture = swapGlobeDepth;
passState.framebuffer = framebuffer;
if (this._frustumsDrawn === 1) {
return;
}
passState.framebuffer = this._accumulationFBO.framebuffer;
this._accumulateCommand.execute(context, passState);
passState.framebuffer = framebuffer;
};
TranslucentTileClassification.prototype.execute = function(scene, passState) {
if (!this._hasTranslucentDepth) {
return;
}
if (this._frustumsDrawn === 1) {
this._textureToComposite = this._drawClassificationFBO.getColorTexture();
} else {
this._textureToComposite = this._accumulationFBO.getColorTexture();
}
const command = scene.frameState.passes.pick ? this._compositeCommand.derivedCommands.pick : this._compositeCommand;
command.execute(scene.context, passState);
clear(this, scene, passState);
};
function clear(translucentTileClassification, scene, passState) {
if (!translucentTileClassification._hasTranslucentDepth) {
return;
}
const framebuffer = passState.framebuffer;
passState.framebuffer = translucentTileClassification._drawClassificationFBO.framebuffer;
translucentTileClassification._clearColorCommand.execute(
scene._context,
passState
);
passState.framebuffer = framebuffer;
if (translucentTileClassification._frustumsDrawn > 1) {
passState.framebuffer = translucentTileClassification._accumulationFBO.framebuffer;
translucentTileClassification._clearColorCommand.execute(
scene._context,
passState
);
}
translucentTileClassification._hasTranslucentDepth = false;
translucentTileClassification._frustumsDrawn = 0;
}
TranslucentTileClassification.prototype.isSupported = function() {
return this._supported;
};
TranslucentTileClassification.prototype.isDestroyed = function() {
return false;
};
TranslucentTileClassification.prototype.destroy = function() {
destroyTextures2(this);
destroyFramebuffers2(this);
if (defined_default(this._compositeCommand)) {
this._compositeCommand.shaderProgram = this._compositeCommand.shaderProgram && this._compositeCommand.shaderProgram.destroy();
}
if (defined_default(this._packDepthCommand)) {
this._packDepthCommand.shaderProgram = this._packDepthCommand.shaderProgram && this._packDepthCommand.shaderProgram.destroy();
}
return destroyObject_default(this);
};
var TranslucentTileClassification_default = TranslucentTileClassification;
// packages/engine/Source/Scene/View.js
function CommandExtent() {
this.command = void 0;
this.near = void 0;
this.far = void 0;
}
function View(scene, camera, viewport) {
const context = scene.context;
let globeDepth;
if (context.depthTexture) {
globeDepth = new GlobeDepth_default();
}
let oit;
if (scene._useOIT && context.depthTexture) {
oit = new OIT_default(context);
}
const passState = new PassState_default(context);
passState.viewport = BoundingRectangle_default.clone(viewport);
this.camera = camera;
this._cameraClone = Camera_default.clone(camera);
this._cameraStartFired = false;
this._cameraMovedTime = void 0;
this.viewport = viewport;
this.passState = passState;
this.pickFramebuffer = new PickFramebuffer_default(context);
this.pickDepthFramebuffer = new PickDepthFramebuffer_default();
this.sceneFramebuffer = new SceneFramebuffer_default();
this.globeDepth = globeDepth;
this.globeTranslucencyFramebuffer = new GlobeTranslucencyFramebuffer_default();
this.oit = oit;
this.translucentTileClassification = new TranslucentTileClassification_default(
context
);
this.pickDepths = [];
this.frustumCommandsList = [];
this.debugFrustumStatistics = void 0;
this._commandExtents = [];
}
var scratchPosition0 = new Cartesian3_default();
var scratchPosition1 = new Cartesian3_default();
function cameraEqual(camera0, camera1, epsilon) {
const maximumPositionComponent = Math.max(
Cartesian3_default.maximumComponent(
Cartesian3_default.abs(camera0.position, scratchPosition0)
),
Cartesian3_default.maximumComponent(
Cartesian3_default.abs(camera1.position, scratchPosition1)
)
);
const scalar = 1 / Math.max(1, maximumPositionComponent);
Cartesian3_default.multiplyByScalar(camera0.position, scalar, scratchPosition0);
Cartesian3_default.multiplyByScalar(camera1.position, scalar, scratchPosition1);
return Cartesian3_default.equalsEpsilon(scratchPosition0, scratchPosition1, epsilon) && Cartesian3_default.equalsEpsilon(camera0.direction, camera1.direction, epsilon) && Cartesian3_default.equalsEpsilon(camera0.up, camera1.up, epsilon) && Cartesian3_default.equalsEpsilon(camera0.right, camera1.right, epsilon) && Matrix4_default.equalsEpsilon(camera0.transform, camera1.transform, epsilon) && camera0.frustum.equalsEpsilon(camera1.frustum, epsilon);
}
View.prototype.checkForCameraUpdates = function(scene) {
const camera = this.camera;
const cameraClone = this._cameraClone;
if (!cameraEqual(camera, cameraClone, Math_default.EPSILON15)) {
if (!this._cameraStartFired) {
camera.moveStart.raiseEvent();
this._cameraStartFired = true;
}
this._cameraMovedTime = getTimestamp_default();
Camera_default.clone(camera, cameraClone);
return true;
}
if (this._cameraStartFired && getTimestamp_default() - this._cameraMovedTime > scene.cameraEventWaitTime) {
camera.moveEnd.raiseEvent();
this._cameraStartFired = false;
}
return false;
};
function updateFrustums(view, scene, near, far) {
const { frameState } = scene;
const { camera, useLogDepth } = frameState;
const farToNearRatio = useLogDepth ? scene.logarithmicDepthFarToNearRatio : scene.farToNearRatio;
const is2D = scene.mode === SceneMode_default.SCENE2D;
const nearToFarDistance2D = scene.nearToFarDistance2D;
far *= 1 + Math_default.EPSILON2;
near = Math.min(Math.max(near, camera.frustum.near), camera.frustum.far);
far = Math.max(Math.min(far, camera.frustum.far), near);
let numFrustums;
if (is2D) {
far = Math.min(far, camera.position.z + scene.nearToFarDistance2D);
near = Math.min(near, far);
numFrustums = Math.ceil(
Math.max(1, far - near) / scene.nearToFarDistance2D
);
} else {
numFrustums = Math.ceil(Math.log(far / near) / Math.log(farToNearRatio));
}
const { frustumCommandsList } = view;
frustumCommandsList.length = numFrustums;
for (let m = 0; m < numFrustums; ++m) {
let curNear;
let curFar;
if (is2D) {
curNear = Math.min(
far - nearToFarDistance2D,
near + m * nearToFarDistance2D
);
curFar = Math.min(far, curNear + nearToFarDistance2D);
} else {
curNear = Math.max(near, Math.pow(farToNearRatio, m) * near);
curFar = Math.min(far, farToNearRatio * curNear);
}
let frustumCommands = frustumCommandsList[m];
if (!defined_default(frustumCommands)) {
frustumCommands = frustumCommandsList[m] = new FrustumCommands_default(
curNear,
curFar
);
} else {
frustumCommands.near = curNear;
frustumCommands.far = curFar;
}
}
}
function insertIntoBin(view, scene, commandExtent) {
const { command, near, far } = commandExtent;
if (scene.debugShowFrustums) {
command.debugOverlappingFrustums = 0;
}
const { frustumCommandsList } = view;
for (let i = 0; i < frustumCommandsList.length; ++i) {
const frustumCommands = frustumCommandsList[i];
if (near > frustumCommands.far) {
continue;
}
if (far < frustumCommands.near) {
break;
}
const pass = command.pass;
const index = frustumCommands.indices[pass]++;
frustumCommands.commands[pass][index] = command;
if (scene.debugShowFrustums) {
command.debugOverlappingFrustums |= 1 << i;
}
if (command.executeInClosestFrustum) {
break;
}
}
if (scene.debugShowFrustums) {
const { debugFrustumStatistics } = view;
const { debugOverlappingFrustums } = command;
const cf = debugFrustumStatistics.commandsInFrustums;
cf[debugOverlappingFrustums] = defined_default(cf[debugOverlappingFrustums]) ? cf[debugOverlappingFrustums] + 1 : 1;
++debugFrustumStatistics.totalCommands;
}
scene.updateDerivedCommands(command);
}
var scratchCullingVolume = new CullingVolume_default();
var scratchNearFarInterval = new Interval_default();
View.prototype.createPotentiallyVisibleSet = function(scene) {
const { frameState } = scene;
const { camera, commandList, shadowState } = frameState;
const { positionWC: positionWC2, directionWC, frustum } = camera;
const computeList = scene._computeCommandList;
const overlayList = scene._overlayCommandList;
if (scene.debugShowFrustums) {
this.debugFrustumStatistics = {
totalCommands: 0,
commandsInFrustums: {}
};
}
const frustumCommandsList = this.frustumCommandsList;
for (let n = 0; n < frustumCommandsList.length; ++n) {
for (let p = 0; p < Pass_default.NUMBER_OF_PASSES; ++p) {
frustumCommandsList[n].indices[p] = 0;
}
}
computeList.length = 0;
overlayList.length = 0;
const commandExtents = this._commandExtents;
const commandExtentCapacity = commandExtents.length;
let commandExtentCount = 0;
let near = +Number.MAX_VALUE;
let far = -Number.MAX_VALUE;
const { shadowsEnabled } = shadowState;
let shadowNear = +Number.MAX_VALUE;
let shadowFar = -Number.MAX_VALUE;
let shadowClosestObjectSize = Number.MAX_VALUE;
const occluder = frameState.mode === SceneMode_default.SCENE3D ? frameState.occluder : void 0;
let { cullingVolume } = frameState;
const planes = scratchCullingVolume.planes;
for (let k = 0; k < 5; ++k) {
planes[k] = cullingVolume.planes[k];
}
cullingVolume = scratchCullingVolume;
for (let i = 0; i < commandList.length; ++i) {
const command = commandList[i];
const { pass, boundingVolume } = command;
if (pass === Pass_default.COMPUTE) {
computeList.push(command);
} else if (pass === Pass_default.OVERLAY) {
overlayList.push(command);
} else {
let commandNear;
let commandFar;
if (defined_default(boundingVolume)) {
if (!scene.isVisible(cullingVolume, command, occluder)) {
continue;
}
const nearFarInterval = boundingVolume.computePlaneDistances(
positionWC2,
directionWC,
scratchNearFarInterval
);
commandNear = nearFarInterval.start;
commandFar = nearFarInterval.stop;
near = Math.min(near, commandNear);
far = Math.max(far, commandFar);
if (shadowsEnabled && command.receiveShadows && commandNear < ShadowMap_default.MAXIMUM_DISTANCE && !(pass === Pass_default.GLOBE && commandNear < -100 && commandFar > 100)) {
const size = commandFar - commandNear;
if (pass !== Pass_default.GLOBE && commandNear < 100) {
shadowClosestObjectSize = Math.min(shadowClosestObjectSize, size);
}
shadowNear = Math.min(shadowNear, commandNear);
shadowFar = Math.max(shadowFar, commandFar);
}
} else if (command instanceof ClearCommand_default) {
commandNear = frustum.near;
commandFar = frustum.far;
} else {
commandNear = frustum.near;
commandFar = frustum.far;
near = Math.min(near, commandNear);
far = Math.max(far, commandFar);
}
let extent = commandExtents[commandExtentCount];
if (!defined_default(extent)) {
extent = commandExtents[commandExtentCount] = new CommandExtent();
}
extent.command = command;
extent.near = commandNear;
extent.far = commandFar;
commandExtentCount++;
}
}
if (shadowsEnabled) {
shadowNear = Math.min(Math.max(shadowNear, frustum.near), frustum.far);
shadowFar = Math.max(Math.min(shadowFar, frustum.far), shadowNear);
shadowState.nearPlane = shadowNear;
shadowState.farPlane = shadowFar;
shadowState.closestObjectSize = shadowClosestObjectSize;
}
updateFrustums(this, scene, near, far);
for (let c = 0; c < commandExtentCount; c++) {
insertIntoBin(this, scene, commandExtents[c]);
}
if (commandExtentCount < commandExtentCapacity) {
for (let c = commandExtentCount; c < commandExtentCapacity; c++) {
const commandExtent = commandExtents[c];
if (!defined_default(commandExtent.command)) {
break;
}
commandExtent.command = void 0;
}
}
const numFrustums = frustumCommandsList.length;
const { frustumSplits: frustumSplits2 } = frameState;
frustumSplits2.length = numFrustums + 1;
for (let j = 0; j < numFrustums; ++j) {
frustumSplits2[j] = frustumCommandsList[j].near;
if (j === numFrustums - 1) {
frustumSplits2[j + 1] = frustumCommandsList[j].far;
}
}
};
View.prototype.destroy = function() {
this.pickFramebuffer = this.pickFramebuffer && this.pickFramebuffer.destroy();
this.pickDepthFramebuffer = this.pickDepthFramebuffer && this.pickDepthFramebuffer.destroy();
this.sceneFramebuffer = this.sceneFramebuffer && this.sceneFramebuffer.destroy();
this.globeDepth = this.globeDepth && this.globeDepth.destroy();
this.oit = this.oit && this.oit.destroy();
this.translucentTileClassification = this.translucentTileClassification && this.translucentTileClassification.destroy();
this.globeTranslucencyFramebuffer = this.globeTranslucencyFramebuffer && this.globeTranslucencyFramebuffer.destroy();
const pickDepths = this.pickDepths;
for (let i = 0; i < pickDepths.length; ++i) {
pickDepths[i].destroy();
}
};
var View_default = View;
// packages/engine/Source/Scene/Picking.js
var offscreenDefaultWidth = 0.1;
var mostDetailedPreloadTilesetPassState = new Cesium3DTilePassState_default({
pass: Cesium3DTilePass_default.MOST_DETAILED_PRELOAD
});
var mostDetailedPickTilesetPassState = new Cesium3DTilePassState_default({
pass: Cesium3DTilePass_default.MOST_DETAILED_PICK
});
var pickTilesetPassState = new Cesium3DTilePassState_default({
pass: Cesium3DTilePass_default.PICK
});
function Picking(scene) {
this._mostDetailedRayPicks = [];
this.pickRenderStateCache = {};
this._pickPositionCache = {};
this._pickPositionCacheDirty = false;
const pickOffscreenViewport = new BoundingRectangle_default(0, 0, 1, 1);
const pickOffscreenCamera = new Camera_default(scene);
pickOffscreenCamera.frustum = new OrthographicFrustum_default({
width: offscreenDefaultWidth,
aspectRatio: 1,
near: 0.1
});
this._pickOffscreenView = new View_default(
scene,
pickOffscreenCamera,
pickOffscreenViewport
);
}
Picking.prototype.update = function() {
this._pickPositionCacheDirty = true;
};
Picking.prototype.getPickDepth = function(scene, index) {
const pickDepths = scene.view.pickDepths;
let pickDepth = pickDepths[index];
if (!defined_default(pickDepth)) {
pickDepth = new PickDepth_default();
pickDepths[index] = pickDepth;
}
return pickDepth;
};
var scratchOrthoPickingFrustum = new OrthographicOffCenterFrustum_default();
var scratchOrthoOrigin = new Cartesian3_default();
var scratchOrthoDirection = new Cartesian3_default();
var scratchOrthoPixelSize = new Cartesian2_default();
var scratchOrthoPickVolumeMatrix4 = new Matrix4_default();
function getPickOrthographicCullingVolume(scene, drawingBufferPosition, width, height, viewport) {
const camera = scene.camera;
let frustum = camera.frustum;
const offCenterFrustum = frustum.offCenterFrustum;
if (defined_default(offCenterFrustum)) {
frustum = offCenterFrustum;
}
let x = 2 * (drawingBufferPosition.x - viewport.x) / viewport.width - 1;
x *= (frustum.right - frustum.left) * 0.5;
let y = 2 * (viewport.height - drawingBufferPosition.y - viewport.y) / viewport.height - 1;
y *= (frustum.top - frustum.bottom) * 0.5;
const transform3 = Matrix4_default.clone(
camera.transform,
scratchOrthoPickVolumeMatrix4
);
camera._setTransform(Matrix4_default.IDENTITY);
const origin = Cartesian3_default.clone(camera.position, scratchOrthoOrigin);
Cartesian3_default.multiplyByScalar(camera.right, x, scratchOrthoDirection);
Cartesian3_default.add(scratchOrthoDirection, origin, origin);
Cartesian3_default.multiplyByScalar(camera.up, y, scratchOrthoDirection);
Cartesian3_default.add(scratchOrthoDirection, origin, origin);
camera._setTransform(transform3);
if (scene.mode === SceneMode_default.SCENE2D) {
Cartesian3_default.fromElements(origin.z, origin.x, origin.y, origin);
}
const pixelSize = frustum.getPixelDimensions(
viewport.width,
viewport.height,
1,
1,
scratchOrthoPixelSize
);
const ortho = scratchOrthoPickingFrustum;
ortho.right = pixelSize.x * 0.5;
ortho.left = -ortho.right;
ortho.top = pixelSize.y * 0.5;
ortho.bottom = -ortho.top;
ortho.near = frustum.near;
ortho.far = frustum.far;
return ortho.computeCullingVolume(origin, camera.directionWC, camera.upWC);
}
var scratchPerspPickingFrustum = new PerspectiveOffCenterFrustum_default();
var scratchPerspPixelSize = new Cartesian2_default();
function getPickPerspectiveCullingVolume(scene, drawingBufferPosition, width, height, viewport) {
const camera = scene.camera;
const frustum = camera.frustum;
const near = frustum.near;
const tanPhi = Math.tan(frustum.fovy * 0.5);
const tanTheta = frustum.aspectRatio * tanPhi;
const x = 2 * (drawingBufferPosition.x - viewport.x) / viewport.width - 1;
const y = 2 * (viewport.height - drawingBufferPosition.y - viewport.y) / viewport.height - 1;
const xDir = x * near * tanTheta;
const yDir = y * near * tanPhi;
const pixelSize = frustum.getPixelDimensions(
viewport.width,
viewport.height,
1,
1,
scratchPerspPixelSize
);
const pickWidth = pixelSize.x * width * 0.5;
const pickHeight = pixelSize.y * height * 0.5;
const offCenter = scratchPerspPickingFrustum;
offCenter.top = yDir + pickHeight;
offCenter.bottom = yDir - pickHeight;
offCenter.right = xDir + pickWidth;
offCenter.left = xDir - pickWidth;
offCenter.near = near;
offCenter.far = frustum.far;
return offCenter.computeCullingVolume(
camera.positionWC,
camera.directionWC,
camera.upWC
);
}
function getPickCullingVolume(scene, drawingBufferPosition, width, height, viewport) {
const frustum = scene.camera.frustum;
if (frustum instanceof OrthographicFrustum_default || frustum instanceof OrthographicOffCenterFrustum_default) {
return getPickOrthographicCullingVolume(
scene,
drawingBufferPosition,
width,
height,
viewport
);
}
return getPickPerspectiveCullingVolume(
scene,
drawingBufferPosition,
width,
height,
viewport
);
}
var scratchRectangle11 = new BoundingRectangle_default(0, 0, 3, 3);
var scratchPosition14 = new Cartesian2_default();
var scratchColorZero = new Color_default(0, 0, 0, 0);
function computePickingDrawingBufferRectangle(drawingBufferHeight, position, width, height, result) {
result.width = width ?? 3;
result.height = height ?? result.width;
result.x = position.x - (result.width - 1) * 0.5;
result.y = drawingBufferHeight - position.y - (result.height - 1) * 0.5;
return result;
}
Picking.prototype.pick = function(scene, windowPosition, width, height) {
Check_default.defined("windowPosition", windowPosition);
const { context, frameState, defaultView } = scene;
const { viewport, pickFramebuffer } = defaultView;
scene.view = defaultView;
viewport.x = 0;
viewport.y = 0;
viewport.width = context.drawingBufferWidth;
viewport.height = context.drawingBufferHeight;
let passState = defaultView.passState;
passState.viewport = BoundingRectangle_default.clone(viewport, passState.viewport);
const drawingBufferPosition = SceneTransforms_default.transformWindowToDrawingBuffer(
scene,
windowPosition,
scratchPosition14
);
const drawingBufferRectangle = computePickingDrawingBufferRectangle(
context.drawingBufferHeight,
drawingBufferPosition,
width,
height,
scratchRectangle11
);
scene.jobScheduler.disableThisFrame();
scene.updateFrameState();
frameState.cullingVolume = getPickCullingVolume(
scene,
drawingBufferPosition,
drawingBufferRectangle.width,
drawingBufferRectangle.height,
viewport
);
frameState.invertClassification = false;
frameState.passes.pick = true;
frameState.tilesetPassState = pickTilesetPassState;
context.uniformState.update(frameState);
scene.updateEnvironment();
passState = pickFramebuffer.begin(drawingBufferRectangle, viewport);
scene.updateAndExecuteCommands(passState, scratchColorZero);
scene.resolveFramebuffers(passState);
const object2 = pickFramebuffer.end(drawingBufferRectangle);
context.endFrame();
return object2;
};
Picking.prototype.pickVoxelCoordinate = function(scene, windowPosition, width, height) {
Check_default.defined("windowPosition", windowPosition);
const { context, frameState, defaultView } = scene;
const { viewport, pickFramebuffer } = defaultView;
scene.view = defaultView;
viewport.x = 0;
viewport.y = 0;
viewport.width = context.drawingBufferWidth;
viewport.height = context.drawingBufferHeight;
let passState = defaultView.passState;
passState.viewport = BoundingRectangle_default.clone(viewport, passState.viewport);
const drawingBufferPosition = SceneTransforms_default.transformWindowToDrawingBuffer(
scene,
windowPosition,
scratchPosition14
);
const drawingBufferRectangle = computePickingDrawingBufferRectangle(
context.drawingBufferHeight,
drawingBufferPosition,
width,
height,
scratchRectangle11
);
scene.jobScheduler.disableThisFrame();
scene.updateFrameState();
frameState.cullingVolume = getPickCullingVolume(
scene,
drawingBufferPosition,
drawingBufferRectangle.width,
drawingBufferRectangle.height,
viewport
);
frameState.invertClassification = false;
frameState.passes.pickVoxel = true;
frameState.tilesetPassState = pickTilesetPassState;
context.uniformState.update(frameState);
scene.updateEnvironment();
passState = pickFramebuffer.begin(drawingBufferRectangle, viewport);
scene.updateAndExecuteCommands(passState, scratchColorZero);
scene.resolveFramebuffers(passState);
const voxelInfo = pickFramebuffer.readCenterPixel(drawingBufferRectangle);
context.endFrame();
return voxelInfo;
};
Picking.prototype.pickMetadata = function(scene, windowPosition, pickedMetadataInfo) {
Check_default.typeOf.object("windowPosition", windowPosition);
Check_default.typeOf.object("pickedMetadataInfo", pickedMetadataInfo);
const { context, frameState, defaultView } = scene;
const { viewport, pickFramebuffer } = defaultView;
scene.view = defaultView;
viewport.x = 0;
viewport.y = 0;
viewport.width = context.drawingBufferWidth;
viewport.height = context.drawingBufferHeight;
let passState = defaultView.passState;
passState.viewport = BoundingRectangle_default.clone(viewport, passState.viewport);
const drawingBufferPosition = SceneTransforms_default.transformWindowToDrawingBuffer(
scene,
windowPosition,
scratchPosition14
);
const drawingBufferRectangle = computePickingDrawingBufferRectangle(
context.drawingBufferHeight,
drawingBufferPosition,
1,
1,
scratchRectangle11
);
scene.jobScheduler.disableThisFrame();
scene.updateFrameState();
frameState.cullingVolume = getPickCullingVolume(
scene,
drawingBufferPosition,
drawingBufferRectangle.width,
drawingBufferRectangle.height,
viewport
);
frameState.invertClassification = false;
frameState.passes.pick = true;
frameState.tilesetPassState = pickTilesetPassState;
frameState.pickingMetadata = true;
frameState.pickedMetadataInfo = pickedMetadataInfo;
context.uniformState.update(frameState);
scene.updateEnvironment();
passState = pickFramebuffer.begin(drawingBufferRectangle, viewport);
scene.updateAndExecuteCommands(passState, scratchColorZero);
const oldOIT = scene._environmentState.useOIT;
scene._environmentState.useOIT = false;
scene.resolveFramebuffers(passState);
scene._environmentState.useOIT = oldOIT;
const rawMetadataPixel = pickFramebuffer.readCenterPixel(
drawingBufferRectangle
);
context.endFrame();
frameState.pickingMetadata = false;
const metadataValue = MetadataPicking_default.decodeMetadataValues(
pickedMetadataInfo.classProperty,
pickedMetadataInfo.metadataProperty,
rawMetadataPixel
);
return metadataValue;
};
function renderTranslucentDepthForPick(scene, drawingBufferPosition) {
const { defaultView, context, frameState, environmentState } = scene;
const { viewport, pickDepthFramebuffer } = defaultView;
scene.view = defaultView;
viewport.x = 0;
viewport.y = 0;
viewport.width = context.drawingBufferWidth;
viewport.height = context.drawingBufferHeight;
let passState = defaultView.passState;
passState.viewport = BoundingRectangle_default.clone(viewport, passState.viewport);
scene.clearPasses(frameState.passes);
frameState.passes.pick = true;
frameState.passes.depth = true;
frameState.cullingVolume = getPickCullingVolume(
scene,
drawingBufferPosition,
1,
1,
viewport
);
frameState.tilesetPassState = pickTilesetPassState;
scene.updateEnvironment();
environmentState.renderTranslucentDepthForPick = true;
passState = pickDepthFramebuffer.update(
context,
drawingBufferPosition,
viewport
);
scene.updateAndExecuteCommands(passState, scratchColorZero);
scene.resolveFramebuffers(passState);
context.endFrame();
}
var scratchPerspectiveFrustum = new PerspectiveFrustum_default();
var scratchPerspectiveOffCenterFrustum = new PerspectiveOffCenterFrustum_default();
var scratchOrthographicFrustum = new OrthographicFrustum_default();
var scratchOrthographicOffCenterFrustum = new OrthographicOffCenterFrustum_default();
Picking.prototype.pickPositionWorldCoordinates = function(scene, windowPosition, result) {
if (!scene.useDepthPicking) {
return void 0;
}
Check_default.defined("windowPosition", windowPosition);
if (!scene.context.depthTexture) {
throw new DeveloperError_default(
"Picking from the depth buffer is not supported. Check pickPositionSupported."
);
}
const cacheKey = windowPosition.toString();
if (this._pickPositionCacheDirty) {
this._pickPositionCache = {};
this._pickPositionCacheDirty = false;
} else if (this._pickPositionCache.hasOwnProperty(cacheKey)) {
return Cartesian3_default.clone(this._pickPositionCache[cacheKey], result);
}
const { context, frameState, camera, defaultView } = scene;
const { uniformState } = context;
scene.view = defaultView;
const drawingBufferPosition = SceneTransforms_default.transformWindowToDrawingBuffer(
scene,
windowPosition,
scratchPosition14
);
if (scene.pickTranslucentDepth) {
renderTranslucentDepthForPick(scene, drawingBufferPosition);
} else {
scene.updateFrameState();
uniformState.update(frameState);
scene.updateEnvironment();
}
drawingBufferPosition.y = scene.drawingBufferHeight - drawingBufferPosition.y;
let frustum;
if (defined_default(camera.frustum.fov)) {
frustum = camera.frustum.clone(scratchPerspectiveFrustum);
} else if (defined_default(camera.frustum.infiniteProjectionMatrix)) {
frustum = camera.frustum.clone(scratchPerspectiveOffCenterFrustum);
} else if (defined_default(camera.frustum.width)) {
frustum = camera.frustum.clone(scratchOrthographicFrustum);
} else {
frustum = camera.frustum.clone(scratchOrthographicOffCenterFrustum);
}
const { frustumCommandsList } = defaultView;
const numFrustums = frustumCommandsList.length;
for (let i = 0; i < numFrustums; ++i) {
const pickDepth = this.getPickDepth(scene, i);
const depth = pickDepth.getDepth(
context,
drawingBufferPosition.x,
drawingBufferPosition.y
);
if (!defined_default(depth)) {
continue;
}
if (depth > 0 && depth < 1) {
const renderedFrustum = frustumCommandsList[i];
let height2D;
if (scene.mode === SceneMode_default.SCENE2D) {
height2D = camera.position.z;
camera.position.z = height2D - renderedFrustum.near + 1;
frustum.far = Math.max(1, renderedFrustum.far - renderedFrustum.near);
frustum.near = 1;
uniformState.update(frameState);
uniformState.updateFrustum(frustum);
} else {
frustum.near = renderedFrustum.near * (i !== 0 ? scene.opaqueFrustumNearOffset : 1);
frustum.far = renderedFrustum.far;
uniformState.updateFrustum(frustum);
}
result = SceneTransforms_default.drawingBufferToWorldCoordinates(
scene,
drawingBufferPosition,
depth,
result
);
if (scene.mode === SceneMode_default.SCENE2D) {
camera.position.z = height2D;
uniformState.update(frameState);
}
this._pickPositionCache[cacheKey] = Cartesian3_default.clone(result);
return result;
}
}
this._pickPositionCache[cacheKey] = void 0;
return void 0;
};
var scratchPickPositionCartographic = new Cartographic_default();
Picking.prototype.pickPosition = function(scene, windowPosition, result) {
result = this.pickPositionWorldCoordinates(scene, windowPosition, result);
if (defined_default(result) && scene.mode !== SceneMode_default.SCENE3D) {
Cartesian3_default.fromElements(result.y, result.z, result.x, result);
const projection = scene.mapProjection;
const ellipsoid = projection.ellipsoid;
const cart = projection.unproject(result, scratchPickPositionCartographic);
ellipsoid.cartographicToCartesian(cart, result);
}
return result;
};
function drillPick(limit, pickCallback) {
let i;
let attributes;
const result = [];
const pickedPrimitives = [];
const pickedAttributes = [];
const pickedFeatures = [];
if (!defined_default(limit)) {
limit = Number.MAX_VALUE;
}
let pickedResult = pickCallback();
while (defined_default(pickedResult)) {
const object2 = pickedResult.object;
const position = pickedResult.position;
const exclude = pickedResult.exclude;
if (defined_default(position) && !defined_default(object2)) {
result.push(pickedResult);
break;
}
if (!defined_default(object2) || !defined_default(object2.primitive)) {
break;
}
if (!exclude) {
result.push(pickedResult);
if (0 >= --limit) {
break;
}
}
const primitive = object2.primitive;
let hasShowAttribute = false;
if (typeof primitive.getGeometryInstanceAttributes === "function") {
if (defined_default(object2.id)) {
attributes = primitive.getGeometryInstanceAttributes(object2.id);
if (defined_default(attributes) && defined_default(attributes.show)) {
hasShowAttribute = true;
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
false,
attributes.show
);
pickedAttributes.push(attributes);
}
}
}
if (object2 instanceof Cesium3DTileFeature_default) {
hasShowAttribute = true;
object2.show = false;
pickedFeatures.push(object2);
}
if (!hasShowAttribute) {
primitive.show = false;
pickedPrimitives.push(primitive);
}
pickedResult = pickCallback();
}
for (i = 0; i < pickedPrimitives.length; ++i) {
pickedPrimitives[i].show = true;
}
for (i = 0; i < pickedAttributes.length; ++i) {
attributes = pickedAttributes[i];
attributes.show = ShowGeometryInstanceAttribute_default.toValue(
true,
attributes.show
);
}
for (i = 0; i < pickedFeatures.length; ++i) {
pickedFeatures[i].show = true;
}
return result;
}
Picking.prototype.drillPick = function(scene, windowPosition, limit, width, height) {
const that = this;
const pickCallback = function() {
const object2 = that.pick(scene, windowPosition, width, height);
if (defined_default(object2)) {
return {
object: object2,
position: void 0,
exclude: false
};
}
};
const objects = drillPick(limit, pickCallback);
return objects.map(function(element) {
return element.object;
});
};
var scratchRight4 = new Cartesian3_default();
var scratchUp3 = new Cartesian3_default();
function MostDetailedRayPick(ray, width, tilesets) {
this.ray = ray;
this.width = width;
this.tilesets = tilesets;
this.ready = false;
const pick = this;
this.promise = new Promise((resolve2) => {
pick._completePick = () => {
resolve2();
};
});
}
function updateOffscreenCameraFromRay(picking, ray, width, camera) {
const direction2 = ray.direction;
const orthogonalAxis = Cartesian3_default.mostOrthogonalAxis(direction2, scratchRight4);
const right = Cartesian3_default.cross(direction2, orthogonalAxis, scratchRight4);
const up = Cartesian3_default.cross(direction2, right, scratchUp3);
camera.position = ray.origin;
camera.direction = direction2;
camera.up = up;
camera.right = right;
camera.frustum.width = width ?? offscreenDefaultWidth;
return camera.frustum.computeCullingVolume(
camera.positionWC,
camera.directionWC,
camera.upWC
);
}
function updateMostDetailedRayPick(picking, scene, rayPick) {
const frameState = scene.frameState;
const { ray, width, tilesets } = rayPick;
const camera = picking._pickOffscreenView.camera;
const cullingVolume = updateOffscreenCameraFromRay(
picking,
ray,
width,
camera
);
const tilesetPassState = mostDetailedPreloadTilesetPassState;
tilesetPassState.camera = camera;
tilesetPassState.cullingVolume = cullingVolume;
let ready = true;
const tilesetsLength = tilesets.length;
for (let i = 0; i < tilesetsLength; ++i) {
const tileset = tilesets[i];
if (tileset.show && scene.primitives.contains(tileset)) {
tileset.updateForPass(frameState, tilesetPassState);
ready = ready && tilesetPassState.ready;
}
}
if (ready) {
rayPick._completePick();
}
return ready;
}
Picking.prototype.updateMostDetailedRayPicks = function(scene) {
const rayPicks = this._mostDetailedRayPicks;
for (let i = 0; i < rayPicks.length; ++i) {
if (updateMostDetailedRayPick(this, scene, rayPicks[i])) {
rayPicks.splice(i--, 1);
}
}
};
function getTilesets(primitives, objectsToExclude, tilesets) {
for (let i = 0; i < primitives.length; ++i) {
const primitive = primitives.get(i);
if (primitive.show) {
if (defined_default(primitive.isCesium3DTileset)) {
if (!defined_default(objectsToExclude) || objectsToExclude.indexOf(primitive) === -1) {
tilesets.push(primitive);
}
} else if (primitive instanceof PrimitiveCollection_default) {
getTilesets(primitive, objectsToExclude, tilesets);
}
}
}
}
function launchMostDetailedRayPick(picking, scene, ray, objectsToExclude, width, callback) {
const tilesets = [];
getTilesets(scene.primitives, objectsToExclude, tilesets);
if (tilesets.length === 0) {
return Promise.resolve(callback());
}
const rayPick = new MostDetailedRayPick(ray, width, tilesets);
picking._mostDetailedRayPicks.push(rayPick);
return rayPick.promise.then(function() {
return callback();
});
}
function isExcluded(object2, objectsToExclude) {
if (!defined_default(object2) || !defined_default(objectsToExclude) || objectsToExclude.length === 0) {
return false;
}
return objectsToExclude.indexOf(object2) > -1 || objectsToExclude.indexOf(object2.primitive) > -1 || objectsToExclude.indexOf(object2.id) > -1;
}
function getRayIntersection(picking, scene, ray, objectsToExclude, width, requirePosition, mostDetailed) {
const { context, frameState } = scene;
const uniformState = context.uniformState;
const view = picking._pickOffscreenView;
scene.view = view;
updateOffscreenCameraFromRay(picking, ray, width, view.camera);
const drawingBufferRectangle = BoundingRectangle_default.clone(
view.viewport,
scratchRectangle11
);
const passState = view.pickFramebuffer.begin(
drawingBufferRectangle,
view.viewport
);
scene.jobScheduler.disableThisFrame();
scene.updateFrameState();
frameState.invertClassification = false;
frameState.passes.pick = true;
frameState.passes.offscreen = true;
if (mostDetailed) {
frameState.tilesetPassState = mostDetailedPickTilesetPassState;
} else {
frameState.tilesetPassState = pickTilesetPassState;
}
uniformState.update(frameState);
scene.updateEnvironment();
scene.updateAndExecuteCommands(passState, scratchColorZero);
scene.resolveFramebuffers(passState);
let position;
const object2 = view.pickFramebuffer.end(drawingBufferRectangle);
if (scene.context.depthTexture) {
const { frustumCommandsList } = view;
const numFrustums = frustumCommandsList.length;
for (let i = 0; i < numFrustums; ++i) {
const pickDepth = picking.getPickDepth(scene, i);
const depth = pickDepth.getDepth(context, 0, 0);
if (!defined_default(depth)) {
continue;
}
if (depth > 0 && depth < 1) {
const renderedFrustum = frustumCommandsList[i];
const near = renderedFrustum.near * (i !== 0 ? scene.opaqueFrustumNearOffset : 1);
const far = renderedFrustum.far;
const distance2 = near + depth * (far - near);
position = Ray_default.getPoint(ray, distance2);
break;
}
}
}
scene.view = scene.defaultView;
context.endFrame();
if (defined_default(object2) || defined_default(position)) {
return {
object: object2,
position,
exclude: !defined_default(position) && requirePosition || isExcluded(object2, objectsToExclude)
};
}
}
function getRayIntersections(picking, scene, ray, limit, objectsToExclude, width, requirePosition, mostDetailed) {
const pickCallback = function() {
return getRayIntersection(
picking,
scene,
ray,
objectsToExclude,
width,
requirePosition,
mostDetailed
);
};
return drillPick(limit, pickCallback);
}
function pickFromRay(picking, scene, ray, objectsToExclude, width, requirePosition, mostDetailed) {
const results = getRayIntersections(
picking,
scene,
ray,
1,
objectsToExclude,
width,
requirePosition,
mostDetailed
);
if (results.length > 0) {
return results[0];
}
}
function drillPickFromRay(picking, scene, ray, limit, objectsToExclude, width, requirePosition, mostDetailed) {
return getRayIntersections(
picking,
scene,
ray,
limit,
objectsToExclude,
width,
requirePosition,
mostDetailed
);
}
function deferPromiseUntilPostRender(scene, promise) {
return new Promise((resolve2, reject) => {
promise.then(function(result) {
const removeCallback = scene.postRender.addEventListener(function() {
removeCallback();
resolve2(result);
});
scene.requestRender();
}).catch(function(error) {
reject(error);
});
});
}
Picking.prototype.pickFromRay = function(scene, ray, objectsToExclude, width) {
Check_default.defined("ray", ray);
if (scene.mode !== SceneMode_default.SCENE3D) {
throw new DeveloperError_default(
"Ray intersections are only supported in 3D mode."
);
}
return pickFromRay(this, scene, ray, objectsToExclude, width, false, false);
};
Picking.prototype.drillPickFromRay = function(scene, ray, limit, objectsToExclude, width) {
Check_default.defined("ray", ray);
if (scene.mode !== SceneMode_default.SCENE3D) {
throw new DeveloperError_default(
"Ray intersections are only supported in 3D mode."
);
}
return drillPickFromRay(
this,
scene,
ray,
limit,
objectsToExclude,
width,
false,
false
);
};
Picking.prototype.pickFromRayMostDetailed = function(scene, ray, objectsToExclude, width) {
Check_default.defined("ray", ray);
if (scene.mode !== SceneMode_default.SCENE3D) {
throw new DeveloperError_default(
"Ray intersections are only supported in 3D mode."
);
}
const that = this;
ray = Ray_default.clone(ray);
objectsToExclude = defined_default(objectsToExclude) ? objectsToExclude.slice() : objectsToExclude;
return deferPromiseUntilPostRender(
scene,
launchMostDetailedRayPick(
that,
scene,
ray,
objectsToExclude,
width,
function() {
return pickFromRay(
that,
scene,
ray,
objectsToExclude,
width,
false,
true
);
}
)
);
};
Picking.prototype.drillPickFromRayMostDetailed = function(scene, ray, limit, objectsToExclude, width) {
Check_default.defined("ray", ray);
if (scene.mode !== SceneMode_default.SCENE3D) {
throw new DeveloperError_default(
"Ray intersections are only supported in 3D mode."
);
}
const that = this;
ray = Ray_default.clone(ray);
objectsToExclude = defined_default(objectsToExclude) ? objectsToExclude.slice() : objectsToExclude;
return deferPromiseUntilPostRender(
scene,
launchMostDetailedRayPick(
that,
scene,
ray,
objectsToExclude,
width,
function() {
return drillPickFromRay(
that,
scene,
ray,
limit,
objectsToExclude,
width,
false,
true
);
}
)
);
};
var scratchSurfacePosition2 = new Cartesian3_default();
var scratchSurfaceNormal = new Cartesian3_default();
var scratchSurfaceRay = new Ray_default();
var scratchCartographic24 = new Cartographic_default();
function getRayForSampleHeight(scene, cartographic2) {
const ellipsoid = scene.ellipsoid;
const height = ApproximateTerrainHeights_default._defaultMaxTerrainHeight;
const surfaceNormal = ellipsoid.geodeticSurfaceNormalCartographic(
cartographic2,
scratchSurfaceNormal
);
const surfacePosition = Cartographic_default.toCartesian(
cartographic2,
ellipsoid,
scratchSurfacePosition2
);
const surfaceRay = scratchSurfaceRay;
surfaceRay.origin = surfacePosition;
surfaceRay.direction = surfaceNormal;
const ray = new Ray_default();
Ray_default.getPoint(surfaceRay, height, ray.origin);
Cartesian3_default.negate(surfaceNormal, ray.direction);
return ray;
}
function getRayForClampToHeight(scene, cartesian11) {
const ellipsoid = scene.ellipsoid;
const cartographic2 = Cartographic_default.fromCartesian(
cartesian11,
ellipsoid,
scratchCartographic24
);
return getRayForSampleHeight(scene, cartographic2);
}
function getHeightFromCartesian(scene, cartesian11) {
const ellipsoid = scene.ellipsoid;
const cartographic2 = Cartographic_default.fromCartesian(
cartesian11,
ellipsoid,
scratchCartographic24
);
return cartographic2.height;
}
function sampleHeightMostDetailed(picking, scene, cartographic2, objectsToExclude, width) {
const ray = getRayForSampleHeight(scene, cartographic2);
return launchMostDetailedRayPick(
picking,
scene,
ray,
objectsToExclude,
width,
function() {
const pickResult = pickFromRay(
picking,
scene,
ray,
objectsToExclude,
width,
true,
true
);
if (defined_default(pickResult)) {
return getHeightFromCartesian(scene, pickResult.position);
}
}
);
}
function clampToHeightMostDetailed(picking, scene, cartesian11, objectsToExclude, width, result) {
const ray = getRayForClampToHeight(scene, cartesian11);
return launchMostDetailedRayPick(
picking,
scene,
ray,
objectsToExclude,
width,
function() {
const pickResult = pickFromRay(
picking,
scene,
ray,
objectsToExclude,
width,
true,
true
);
if (defined_default(pickResult)) {
return Cartesian3_default.clone(pickResult.position, result);
}
}
);
}
Picking.prototype.sampleHeight = function(scene, position, objectsToExclude, width) {
Check_default.defined("position", position);
if (scene.mode !== SceneMode_default.SCENE3D) {
throw new DeveloperError_default("sampleHeight is only supported in 3D mode.");
}
if (!scene.sampleHeightSupported) {
throw new DeveloperError_default(
"sampleHeight requires depth texture support. Check sampleHeightSupported."
);
}
const ray = getRayForSampleHeight(scene, position);
const pickResult = pickFromRay(
this,
scene,
ray,
objectsToExclude,
width,
true,
false
);
if (defined_default(pickResult)) {
return getHeightFromCartesian(scene, pickResult.position);
}
};
Picking.prototype.clampToHeight = function(scene, cartesian11, objectsToExclude, width, result) {
Check_default.defined("cartesian", cartesian11);
if (scene.mode !== SceneMode_default.SCENE3D) {
throw new DeveloperError_default("clampToHeight is only supported in 3D mode.");
}
if (!scene.clampToHeightSupported) {
throw new DeveloperError_default(
"clampToHeight requires depth texture support. Check clampToHeightSupported."
);
}
const ray = getRayForClampToHeight(scene, cartesian11);
const pickResult = pickFromRay(
this,
scene,
ray,
objectsToExclude,
width,
true,
false
);
if (defined_default(pickResult)) {
return Cartesian3_default.clone(pickResult.position, result);
}
};
Picking.prototype.sampleHeightMostDetailed = function(scene, positions, objectsToExclude, width) {
Check_default.defined("positions", positions);
if (scene.mode !== SceneMode_default.SCENE3D) {
throw new DeveloperError_default(
"sampleHeightMostDetailed is only supported in 3D mode."
);
}
if (!scene.sampleHeightSupported) {
throw new DeveloperError_default(
"sampleHeightMostDetailed requires depth texture support. Check sampleHeightSupported."
);
}
objectsToExclude = defined_default(objectsToExclude) ? objectsToExclude.slice() : objectsToExclude;
const length2 = positions.length;
const promises = new Array(length2);
for (let i = 0; i < length2; ++i) {
promises[i] = sampleHeightMostDetailed(
this,
scene,
positions[i],
objectsToExclude,
width
);
}
return deferPromiseUntilPostRender(
scene,
Promise.all(promises).then(function(heights) {
const length3 = heights.length;
for (let i = 0; i < length3; ++i) {
positions[i].height = heights[i];
}
return positions;
})
);
};
Picking.prototype.clampToHeightMostDetailed = function(scene, cartesians, objectsToExclude, width) {
Check_default.defined("cartesians", cartesians);
if (scene.mode !== SceneMode_default.SCENE3D) {
throw new DeveloperError_default(
"clampToHeightMostDetailed is only supported in 3D mode."
);
}
if (!scene.clampToHeightSupported) {
throw new DeveloperError_default(
"clampToHeightMostDetailed requires depth texture support. Check clampToHeightSupported."
);
}
objectsToExclude = defined_default(objectsToExclude) ? objectsToExclude.slice() : objectsToExclude;
const length2 = cartesians.length;
const promises = new Array(length2);
for (let i = 0; i < length2; ++i) {
promises[i] = clampToHeightMostDetailed(
this,
scene,
cartesians[i],
objectsToExclude,
width,
cartesians[i]
);
}
return deferPromiseUntilPostRender(
scene,
Promise.all(promises).then(function(clampedCartesians) {
const length3 = clampedCartesians.length;
for (let i = 0; i < length3; ++i) {
cartesians[i] = clampedCartesians[i];
}
return cartesians;
})
);
};
Picking.prototype.destroy = function() {
this._pickOffscreenView = this._pickOffscreenView && this._pickOffscreenView.destroy();
};
var Picking_default = Picking;
// packages/engine/Source/Scene/PostProcessStageCollection.js
var import_InlineWorkers1110 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/PostProcessStageLibrary.js
var import_InlineWorkers1107 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/PostProcessStages/AcesTonemappingStage.js
var import_InlineWorkers1083 = __toESM(require_InlineWorkers(), 1);
var AcesTonemappingStage_default = "uniform sampler2D colorTexture;\n\nin vec2 v_textureCoordinates;\n\n#ifdef AUTO_EXPOSURE\nuniform sampler2D autoExposure;\n#else\nuniform float exposure;\n#endif\n\nvoid main()\n{\n vec4 fragmentColor = texture(colorTexture, v_textureCoordinates);\n vec3 color = fragmentColor.rgb;\n\n#ifdef AUTO_EXPOSURE\n color /= texture(autoExposure, vec2(0.5)).r;\n#else\n color *= vec3(exposure);\n#endif\n color = czm_acesTonemapping(color);\n color = czm_inverseGamma(color);\n\n out_FragColor = vec4(color, fragmentColor.a);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/AmbientOcclusionGenerate.js
var import_InlineWorkers1084 = __toESM(require_InlineWorkers(), 1);
var AmbientOcclusionGenerate_default = "precision highp float;\n\nuniform sampler2D randomTexture;\nuniform sampler2D depthTexture;\nuniform float intensity;\nuniform float bias;\nuniform float lengthCap;\nuniform int stepCount;\nuniform int directionCount;\n\nvec4 pixelToEye(vec2 screenCoordinate)\n{\n vec2 uv = screenCoordinate / czm_viewport.zw;\n float depth = czm_readDepth(depthTexture, uv);\n vec2 xy = 2.0 * uv - vec2(1.0);\n vec4 posEC = czm_inverseProjection * vec4(xy, depth, 1.0);\n posEC = posEC / posEC.w;\n // Avoid numerical error at far plane\n if (depth >= 1.0) {\n posEC.z = czm_currentFrustum.y;\n }\n return posEC;\n}\n\n// Reconstruct surface normal in eye coordinates, avoiding edges\nvec3 getNormalXEdge(vec3 positionEC)\n{\n // Find the 3D surface positions at adjacent screen pixels\n vec2 centerCoord = gl_FragCoord.xy;\n vec3 positionLeft = pixelToEye(centerCoord + vec2(-1.0, 0.0)).xyz;\n vec3 positionRight = pixelToEye(centerCoord + vec2(1.0, 0.0)).xyz;\n vec3 positionUp = pixelToEye(centerCoord + vec2(0.0, 1.0)).xyz;\n vec3 positionDown = pixelToEye(centerCoord + vec2(0.0, -1.0)).xyz;\n\n // Compute potential tangent vectors\n vec3 dx0 = positionEC - positionLeft;\n vec3 dx1 = positionRight - positionEC;\n vec3 dy0 = positionEC - positionDown;\n vec3 dy1 = positionUp - positionEC;\n\n // The shorter tangent is more likely to be on the same surface\n vec3 dx = length(dx0) < length(dx1) ? dx0 : dx1;\n vec3 dy = length(dy0) < length(dy1) ? dy0 : dy1;\n\n return normalize(cross(dx, dy));\n}\n\nconst float sqrtTwoPi = sqrt(czm_twoPi);\n\nfloat gaussian(float x, float standardDeviation) {\n float argument = x / standardDeviation;\n return exp(-0.5 * argument * argument) / (sqrtTwoPi * standardDeviation);\n}\n\nvoid main(void)\n{\n vec4 positionEC = pixelToEye(gl_FragCoord.xy);\n\n // Exit if we are too close to the back of the frustum, where the depth value is invalid.\n float maxValidDepth = czm_currentFrustum.y - lengthCap;\n if (-positionEC.z > maxValidDepth)\n {\n out_FragColor = vec4(1.0);\n return;\n }\n\n vec3 normalEC = getNormalXEdge(positionEC.xyz);\n float gaussianVariance = lengthCap * sqrt(-positionEC.z);\n // Choose a step length such that the marching stops just before 3 * variance.\n float stepLength = 3.0 * gaussianVariance / (float(stepCount) + 1.0);\n float metersPerPixel = czm_metersPerPixel(positionEC, 1.0);\n // Minimum step is 1 pixel to avoid double sampling\n float pixelsPerStep = max(stepLength / metersPerPixel, 1.0);\n stepLength = pixelsPerStep * metersPerPixel;\n\n float angleStepScale = 1.0 / float(directionCount);\n float angleStep = angleStepScale * czm_twoPi;\n float cosStep = cos(angleStep);\n float sinStep = sin(angleStep);\n mat2 rotateStep = mat2(cosStep, sinStep, -sinStep, cosStep);\n\n // Initial sampling direction (different for each pixel)\n const float randomTextureSize = 255.0;\n vec2 randomTexCoord = fract(gl_FragCoord.xy / randomTextureSize);\n float randomVal = texture(randomTexture, randomTexCoord).x;\n vec2 sampleDirection = vec2(cos(angleStep * randomVal), sin(angleStep * randomVal));\n\n float ao = 0.0;\n // Loop over sampling directions\n#if __VERSION__ == 300\n for (int i = 0; i < directionCount; i++)\n {\n#else\n for (int i = 0; i < 16; i++)\n {\n if (i >= directionCount) {\n break;\n }\n#endif\n sampleDirection = rotateStep * sampleDirection;\n\n float localAO = 0.0;\n vec2 radialStep = pixelsPerStep * sampleDirection;\n\n#if __VERSION__ == 300\n for (int j = 0; j < stepCount; j++)\n {\n#else\n for (int j = 0; j < 64; j++)\n {\n if (j >= stepCount) {\n break;\n }\n#endif\n // Step along sampling direction, away from output pixel\n vec2 samplePixel = floor(gl_FragCoord.xy + float(j + 1) * radialStep) + vec2(0.5);\n\n // Exit if we stepped off the screen\n if (clamp(samplePixel, vec2(0.0), czm_viewport.zw) != samplePixel) {\n break;\n }\n\n // Compute step vector from output point to sampled point\n vec4 samplePositionEC = pixelToEye(samplePixel);\n vec3 stepVector = samplePositionEC.xyz - positionEC.xyz;\n\n // Estimate the angle from the surface normal.\n float dotVal = clamp(dot(normalEC, normalize(stepVector)), 0.0, 1.0);\n dotVal = czm_branchFreeTernary(dotVal > bias, dotVal, 0.0);\n dotVal = czm_branchFreeTernary(-samplePositionEC.z <= maxValidDepth, dotVal, 0.0);\n\n // Weight contribution based on the distance from the output point\n float sampleDistance = length(stepVector);\n float weight = gaussian(sampleDistance, gaussianVariance);\n localAO += weight * dotVal;\n }\n ao += localAO;\n }\n\n ao *= angleStepScale * stepLength;\n ao = 1.0 - clamp(ao, 0.0, 1.0);\n ao = pow(ao, intensity);\n out_FragColor = vec4(vec3(ao), 1.0);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/AmbientOcclusionModulate.js
var import_InlineWorkers1085 = __toESM(require_InlineWorkers(), 1);
var AmbientOcclusionModulate_default = "uniform sampler2D colorTexture;\nuniform sampler2D ambientOcclusionTexture;\nuniform bool ambientOcclusionOnly;\nin vec2 v_textureCoordinates;\n\nvoid main(void)\n{\n vec4 color = texture(colorTexture, v_textureCoordinates);\n vec4 ao = texture(ambientOcclusionTexture, v_textureCoordinates);\n out_FragColor = ambientOcclusionOnly ? ao : ao * color;\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/BlackAndWhite.js
var import_InlineWorkers1086 = __toESM(require_InlineWorkers(), 1);
var BlackAndWhite_default = "uniform sampler2D colorTexture;\nuniform float gradations;\n\nin vec2 v_textureCoordinates;\n\nvoid main(void)\n{\n vec3 rgb = texture(colorTexture, v_textureCoordinates).rgb;\n#ifdef CZM_SELECTED_FEATURE\n if (czm_selected()) {\n out_FragColor = vec4(rgb, 1.0);\n return;\n }\n#endif\n float luminance = czm_luminance(rgb);\n float darkness = luminance * gradations;\n darkness = (darkness - fract(darkness)) / gradations;\n out_FragColor = vec4(vec3(darkness), 1.0);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/BloomComposite.js
var import_InlineWorkers1087 = __toESM(require_InlineWorkers(), 1);
var BloomComposite_default = "uniform sampler2D colorTexture;\nuniform sampler2D bloomTexture;\nuniform bool glowOnly;\n\nin vec2 v_textureCoordinates;\n\nvoid main(void)\n{\n vec4 color = texture(colorTexture, v_textureCoordinates);\n\n#ifdef CZM_SELECTED_FEATURE\n if (czm_selected()) {\n out_FragColor = color;\n return;\n }\n#endif\n\n vec4 bloom = texture(bloomTexture, v_textureCoordinates);\n out_FragColor = glowOnly ? bloom : bloom + color;\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/Brightness.js
var import_InlineWorkers1088 = __toESM(require_InlineWorkers(), 1);
var Brightness_default = "uniform sampler2D colorTexture;\nuniform float brightness;\n\nin vec2 v_textureCoordinates;\n\nvoid main(void)\n{\n vec3 rgb = texture(colorTexture, v_textureCoordinates).rgb;\n vec3 target = vec3(0.0);\n out_FragColor = vec4(mix(target, rgb, brightness), 1.0);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/ContrastBias.js
var import_InlineWorkers1089 = __toESM(require_InlineWorkers(), 1);
var ContrastBias_default = "uniform sampler2D colorTexture;\nuniform float contrast;\nuniform float brightness;\n\nin vec2 v_textureCoordinates;\n\nvoid main(void)\n{\n vec3 sceneColor = texture(colorTexture, v_textureCoordinates).xyz;\n sceneColor = czm_RGBToHSB(sceneColor);\n sceneColor.z += brightness;\n sceneColor = czm_HSBToRGB(sceneColor);\n\n float factor = (259.0 * (contrast + 255.0)) / (255.0 * (259.0 - contrast));\n sceneColor = factor * (sceneColor - vec3(0.5)) + vec3(0.5);\n out_FragColor = vec4(sceneColor, 1.0);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/DepthOfField.js
var import_InlineWorkers1090 = __toESM(require_InlineWorkers(), 1);
var DepthOfField_default = "uniform sampler2D colorTexture;\nuniform sampler2D blurTexture;\nuniform sampler2D depthTexture;\nuniform float focalDistance;\n\nin vec2 v_textureCoordinates;\n\nvec4 toEye(vec2 uv, float depth)\n{\n vec2 xy = vec2((uv.x * 2.0 - 1.0), ((1.0 - uv.y) * 2.0 - 1.0));\n vec4 posInCamera = czm_inverseProjection * vec4(xy, depth, 1.0);\n posInCamera = posInCamera / posInCamera.w;\n return posInCamera;\n}\n\nfloat computeDepthBlur(float depth)\n{\n float f;\n if (depth < focalDistance)\n {\n f = (focalDistance - depth) / (focalDistance - czm_currentFrustum.x);\n }\n else\n {\n f = (depth - focalDistance) / (czm_currentFrustum.y - focalDistance);\n f = pow(f, 0.1);\n }\n f *= f;\n f = clamp(f, 0.0, 1.0);\n return pow(f, 0.5);\n}\n\nvoid main(void)\n{\n float depth = czm_readDepth(depthTexture, v_textureCoordinates);\n vec4 posInCamera = toEye(v_textureCoordinates, depth);\n float d = computeDepthBlur(-posInCamera.z);\n out_FragColor = mix(texture(colorTexture, v_textureCoordinates), texture(blurTexture, v_textureCoordinates), d);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/DepthView.js
var import_InlineWorkers1091 = __toESM(require_InlineWorkers(), 1);
var DepthView_default = "uniform sampler2D depthTexture;\n\nin vec2 v_textureCoordinates;\n\nvoid main(void)\n{\n float depth = czm_readDepth(depthTexture, v_textureCoordinates);\n out_FragColor = vec4(vec3(depth), 1.0);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/EdgeDetection.js
var import_InlineWorkers1092 = __toESM(require_InlineWorkers(), 1);
var EdgeDetection_default = "uniform sampler2D depthTexture;\nuniform float length;\nuniform vec4 color;\n\nin vec2 v_textureCoordinates;\n\nvoid main(void)\n{\n float directions[3];\n directions[0] = -1.0;\n directions[1] = 0.0;\n directions[2] = 1.0;\n\n float scalars[3];\n scalars[0] = 3.0;\n scalars[1] = 10.0;\n scalars[2] = 3.0;\n\n float padx = czm_pixelRatio / czm_viewport.z;\n float pady = czm_pixelRatio / czm_viewport.w;\n\n#ifdef CZM_SELECTED_FEATURE\n bool selected = false;\n for (int i = 0; i < 3; ++i)\n {\n float dir = directions[i];\n selected = selected || czm_selected(vec2(-padx, dir * pady));\n selected = selected || czm_selected(vec2(padx, dir * pady));\n selected = selected || czm_selected(vec2(dir * padx, -pady));\n selected = selected || czm_selected(vec2(dir * padx, pady));\n if (selected)\n {\n break;\n }\n }\n if (!selected)\n {\n out_FragColor = vec4(color.rgb, 0.0);\n return;\n }\n#endif\n\n float horizEdge = 0.0;\n float vertEdge = 0.0;\n\n for (int i = 0; i < 3; ++i)\n {\n float dir = directions[i];\n float scale = scalars[i];\n\n horizEdge -= texture(depthTexture, v_textureCoordinates + vec2(-padx, dir * pady)).x * scale;\n horizEdge += texture(depthTexture, v_textureCoordinates + vec2(padx, dir * pady)).x * scale;\n\n vertEdge -= texture(depthTexture, v_textureCoordinates + vec2(dir * padx, -pady)).x * scale;\n vertEdge += texture(depthTexture, v_textureCoordinates + vec2(dir * padx, pady)).x * scale;\n }\n\n float len = sqrt(horizEdge * horizEdge + vertEdge * vertEdge);\n out_FragColor = vec4(color.rgb, len > length ? color.a : 0.0);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/FilmicTonemapping.js
var import_InlineWorkers1093 = __toESM(require_InlineWorkers(), 1);
var FilmicTonemapping_default = "uniform sampler2D colorTexture;\n\nin vec2 v_textureCoordinates;\n\n#ifdef AUTO_EXPOSURE\nuniform sampler2D autoExposure;\n#else\nuniform float exposure;\n#endif\n\n// See slides 142 and 143:\n// http://www.gdcvault.com/play/1012459/Uncharted_2__HDR_Lighting\n\nvoid main()\n{\n vec4 fragmentColor = texture(colorTexture, v_textureCoordinates);\n vec3 color = fragmentColor.rgb;\n\n#ifdef AUTO_EXPOSURE\n float exposure = texture(autoExposure, vec2(0.5)).r;\n color /= exposure;\n#else\n color *= vec3(exposure);\n#endif\n\n const float A = 0.22; // shoulder strength\n const float B = 0.30; // linear strength\n const float C = 0.10; // linear angle\n const float D = 0.20; // toe strength\n const float E = 0.01; // toe numerator\n const float F = 0.30; // toe denominator\n\n const float white = 11.2; // linear white point value\n\n vec3 c = ((color * (A * color + C * B) + D * E) / (color * ( A * color + B) + D * F)) - E / F;\n float w = ((white * (A * white + C * B) + D * E) / (white * ( A * white + B) + D * F)) - E / F;\n\n c = czm_inverseGamma(c / w);\n out_FragColor = vec4(c, fragmentColor.a);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/PbrNeutralTonemapping.js
var import_InlineWorkers1094 = __toESM(require_InlineWorkers(), 1);
var PbrNeutralTonemapping_default = "uniform sampler2D colorTexture;\n\nin vec2 v_textureCoordinates;\n\n#ifdef AUTO_EXPOSURE\nuniform sampler2D autoExposure;\n#else\nuniform float exposure;\n#endif\n\nvoid main()\n{\n vec4 fragmentColor = texture(colorTexture, v_textureCoordinates);\n vec3 color = fragmentColor.rgb;\n\n#ifdef AUTO_EXPOSURE\n color /= texture(autoExposure, vec2(0.5)).r;\n#else\n color *= vec3(exposure);\n#endif\n color = czm_pbrNeutralTonemapping(color);\n color = czm_inverseGamma(color);\n\n out_FragColor = vec4(color, fragmentColor.a);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/FXAA.js
var import_InlineWorkers1095 = __toESM(require_InlineWorkers(), 1);
var FXAA_default = "in vec2 v_textureCoordinates;\n\nuniform sampler2D colorTexture;\n\nconst float fxaaQualitySubpix = 0.5;\nconst float fxaaQualityEdgeThreshold = 0.125;\nconst float fxaaQualityEdgeThresholdMin = 0.0833;\n\nvoid main()\n{\n vec2 fxaaQualityRcpFrame = vec2(1.0) / czm_viewport.zw;\n vec4 color = FxaaPixelShader(\n v_textureCoordinates,\n colorTexture,\n fxaaQualityRcpFrame,\n fxaaQualitySubpix,\n fxaaQualityEdgeThreshold,\n fxaaQualityEdgeThresholdMin);\n float alpha = texture(colorTexture, v_textureCoordinates).a;\n out_FragColor = vec4(color.rgb, alpha);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/GaussianBlur1D.js
var import_InlineWorkers1096 = __toESM(require_InlineWorkers(), 1);
var GaussianBlur1D_default = "#define SAMPLES 8\n\nuniform float delta;\nuniform float sigma;\nuniform float direction; // 0.0 for x direction, 1.0 for y direction\n\nuniform sampler2D colorTexture;\n\n#ifdef USE_STEP_SIZE\nuniform float stepSize;\n#else\nuniform vec2 step;\n#endif\n\nin vec2 v_textureCoordinates;\n\n// Incremental Computation of the Gaussian:\n// https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch40.html\n\nvoid main()\n{\n vec2 st = v_textureCoordinates;\n vec2 dir = vec2(1.0 - direction, direction);\n\n#ifdef USE_STEP_SIZE\n vec2 step = vec2(stepSize * (czm_pixelRatio / czm_viewport.zw));\n#else\n vec2 step = step;\n#endif\n\n vec3 g;\n g.x = 1.0 / (sqrt(czm_twoPi) * sigma);\n g.y = exp((-0.5 * delta * delta) / (sigma * sigma));\n g.z = g.y * g.y;\n\n vec4 result = texture(colorTexture, st) * g.x;\n for (int i = 1; i < SAMPLES; ++i)\n {\n g.xy *= g.yz;\n\n vec2 offset = float(i) * dir * step;\n result += texture(colorTexture, st - offset) * g.x;\n result += texture(colorTexture, st + offset) * g.x;\n }\n\n out_FragColor = result;\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/LensFlare.js
var import_InlineWorkers1097 = __toESM(require_InlineWorkers(), 1);
var LensFlare_default = "uniform sampler2D colorTexture;\nuniform sampler2D dirtTexture;\nuniform sampler2D starTexture;\nuniform vec2 dirtTextureDimensions;\nuniform float distortion;\nuniform float ghostDispersal;\nuniform float haloWidth;\nuniform float dirtAmount;\nuniform float earthRadius;\nuniform float intensity;\n\nin vec2 v_textureCoordinates;\n\n// whether it is in space or not\n// 6500000.0 is empirical value\n#define DISTANCE_TO_SPACE 6500000.0\n\n// return ndc from world coordinate biased earthRadius\nvec4 getNDCFromWC(vec3 WC, float earthRadius)\n{\n vec4 positionEC = czm_view * vec4(WC, 1.0);\n positionEC = vec4(positionEC.x + earthRadius, positionEC.y, positionEC.z, 1.0);\n vec4 positionWC = czm_eyeToWindowCoordinates(positionEC);\n return czm_viewportOrthographic * vec4(positionWC.xy, -positionWC.z, 1.0);\n}\n\n// Check if current pixel is included Earth\n// if then mask it gradually\nfloat isInEarth(vec2 texcoord, vec2 sceneSize)\n{\n vec2 NDC = texcoord * 2.0 - 1.0;\n vec4 earthPosSC = getNDCFromWC(vec3(0.0), 0.0);\n vec4 earthPosSCEdge = getNDCFromWC(vec3(0.0), earthRadius * 1.5);\n NDC.xy -= earthPosSC.xy;\n\n float X = abs(NDC.x) * sceneSize.x;\n float Y = abs(NDC.y) * sceneSize.y;\n\n return clamp(0.0, 1.0, max(sqrt(X * X + Y * Y) / max(abs(earthPosSCEdge.x * sceneSize.x), 1.0) - 0.8 , 0.0));\n}\n\n// For Chromatic effect\nvec4 textureDistorted(sampler2D tex, vec2 texcoord, vec2 direction, vec3 distortion, bool isSpace)\n{\n vec2 sceneSize = czm_viewport.zw;\n vec3 color;\n if(isSpace)\n {\n color.r = isInEarth(texcoord + direction * distortion.r, sceneSize) * texture(tex, texcoord + direction * distortion.r).r;\n color.g = isInEarth(texcoord + direction * distortion.g, sceneSize) * texture(tex, texcoord + direction * distortion.g).g;\n color.b = isInEarth(texcoord + direction * distortion.b, sceneSize) * texture(tex, texcoord + direction * distortion.b).b;\n }\n else\n {\n color.r = texture(tex, texcoord + direction * distortion.r).r;\n color.g = texture(tex, texcoord + direction * distortion.g).g;\n color.b = texture(tex, texcoord + direction * distortion.b).b;\n }\n return vec4(clamp(color, 0.0, 1.0), 0.0);\n}\n\nvoid main(void)\n{\n vec4 originalColor = texture(colorTexture, v_textureCoordinates);\n vec3 rgb = originalColor.rgb;\n bool isSpace = length(czm_viewerPositionWC.xyz) > DISTANCE_TO_SPACE;\n\n // Sun position\n vec4 sunPos = czm_morphTime == 1.0 ? vec4(czm_sunPositionWC, 1.0) : vec4(czm_sunPositionColumbusView.zxy, 1.0);\n vec4 sunPositionEC = czm_view * sunPos;\n vec4 sunPositionWC = czm_eyeToWindowCoordinates(sunPositionEC);\n sunPos = czm_viewportOrthographic * vec4(sunPositionWC.xy, -sunPositionWC.z, 1.0);\n\n // If sun is not in the screen space, use original color.\n if(!isSpace || !((sunPos.x >= -1.1 && sunPos.x <= 1.1) && (sunPos.y >= -1.1 && sunPos.y <= 1.1)))\n {\n // Lens flare is disabled when not in space until #5932 is fixed.\n // https://github.com/CesiumGS/cesium/issues/5932\n out_FragColor = originalColor;\n return;\n }\n\n vec2 texcoord = vec2(1.0) - v_textureCoordinates;\n vec2 pixelSize = czm_pixelRatio / czm_viewport.zw;\n vec2 invPixelSize = 1.0 / pixelSize;\n vec3 distortionVec = pixelSize.x * vec3(-distortion, 0.0, distortion);\n\n // ghost vector to image centre:\n vec2 ghostVec = (vec2(0.5) - texcoord) * ghostDispersal;\n vec3 direction = normalize(vec3(ghostVec, 0.0));\n\n // sample ghosts:\n vec4 result = vec4(0.0);\n vec4 ghost = vec4(0.0);\n for (int i = 0; i < 4; ++i)\n {\n vec2 offset = fract(texcoord + ghostVec * float(i));\n // Only bright spots from the centre of the source image\n ghost += textureDistorted(colorTexture, offset, direction.xy, distortionVec, isSpace);\n }\n result += ghost;\n\n // sample halo\n vec2 haloVec = normalize(ghostVec) * haloWidth;\n float weightForHalo = length(vec2(0.5) - fract(texcoord + haloVec)) / length(vec2(0.5));\n weightForHalo = pow(1.0 - weightForHalo, 5.0);\n\n result += textureDistorted(colorTexture, texcoord + haloVec, direction.xy, distortionVec, isSpace) * weightForHalo * 1.5;\n\n // dirt on lens\n vec2 dirtTexCoords = (v_textureCoordinates * invPixelSize) / dirtTextureDimensions;\n if (dirtTexCoords.x > 1.0)\n {\n dirtTexCoords.x = mod(floor(dirtTexCoords.x), 2.0) == 1.0 ? 1.0 - fract(dirtTexCoords.x) : fract(dirtTexCoords.x);\n }\n if (dirtTexCoords.y > 1.0)\n {\n dirtTexCoords.y = mod(floor(dirtTexCoords.y), 2.0) == 1.0 ? 1.0 - fract(dirtTexCoords.y) : fract(dirtTexCoords.y);\n }\n result += dirtAmount * texture(dirtTexture, dirtTexCoords);\n\n // Rotating starburst texture's coordinate\n // dot(czm_view[0].xyz, vec3(0.0, 0.0, 1.0)) + dot(czm_view[1].xyz, vec3(0.0, 1.0, 0.0))\n float camrot = czm_view[0].z + czm_view[1].y;\n float cosValue = cos(camrot);\n float sinValue = sin(camrot);\n mat3 rotation = mat3(\n cosValue, -sinValue, 0.0,\n sinValue, cosValue, 0.0,\n 0.0, 0.0, 1.0\n );\n\n vec3 st1 = vec3(v_textureCoordinates * 2.0 - vec2(1.0), 1.0);\n vec3 st2 = vec3((rotation * st1).xy, 1.0);\n vec3 st3 = st2 * 0.5 + vec3(0.5);\n vec2 lensStarTexcoord = st3.xy;\n float weightForLensFlare = length(vec3(sunPos.xy, 0.0));\n float oneMinusWeightForLensFlare = max(1.0 - weightForLensFlare, 0.0);\n\n if (!isSpace)\n {\n result *= oneMinusWeightForLensFlare * intensity * 0.2;\n }\n else\n {\n result *= oneMinusWeightForLensFlare * intensity;\n result *= texture(starTexture, lensStarTexcoord) * pow(weightForLensFlare, 1.0) * max((1.0 - length(vec3(st1.xy, 0.0))), 0.0) * 2.0;\n }\n\n result += texture(colorTexture, v_textureCoordinates);\n\n out_FragColor = result;\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/ModifiedReinhardTonemapping.js
var import_InlineWorkers1098 = __toESM(require_InlineWorkers(), 1);
var ModifiedReinhardTonemapping_default = "uniform sampler2D colorTexture;\nuniform vec3 white;\n\nin vec2 v_textureCoordinates;\n\n#ifdef AUTO_EXPOSURE\nuniform sampler2D autoExposure;\n#else\nuniform float exposure;\n#endif\n\n// See equation 4:\n// http://www.cs.utah.edu/~reinhard/cdrom/tonemap.pdf\n\nvoid main()\n{\n vec4 fragmentColor = texture(colorTexture, v_textureCoordinates);\n vec3 color = fragmentColor.rgb;\n#ifdef AUTO_EXPOSURE\n float exposure = texture(autoExposure, vec2(0.5)).r;\n color /= exposure;\n#else\n color *= vec3(exposure);\n#endif\n color = (color * (1.0 + color / white)) / (1.0 + color);\n color = czm_inverseGamma(color);\n out_FragColor = vec4(color, fragmentColor.a);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/NightVision.js
var import_InlineWorkers1099 = __toESM(require_InlineWorkers(), 1);
var NightVision_default = "uniform sampler2D colorTexture;\n\nin vec2 v_textureCoordinates;\n\nfloat rand(vec2 co)\n{\n return fract(sin(dot(co.xy ,vec2(12.9898, 78.233))) * 43758.5453);\n}\n\nvoid main(void)\n{\n float noiseValue = rand(v_textureCoordinates + sin(czm_frameNumber)) * 0.1;\n vec3 rgb = texture(colorTexture, v_textureCoordinates).rgb;\n vec3 green = vec3(0.0, 1.0, 0.0);\n out_FragColor = vec4((noiseValue + rgb) * green, 1.0);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/ReinhardTonemapping.js
var import_InlineWorkers1100 = __toESM(require_InlineWorkers(), 1);
var ReinhardTonemapping_default = "uniform sampler2D colorTexture;\n\nin vec2 v_textureCoordinates;\n\n#ifdef AUTO_EXPOSURE\nuniform sampler2D autoExposure;\n#else\nuniform float exposure;\n#endif\n\n// See equation 3:\n// http://www.cs.utah.edu/~reinhard/cdrom/tonemap.pdf\n\nvoid main()\n{\n vec4 fragmentColor = texture(colorTexture, v_textureCoordinates);\n vec3 color = fragmentColor.rgb;\n#ifdef AUTO_EXPOSURE\n float exposure = texture(autoExposure, vec2(0.5)).r;\n color /= exposure;\n#else\n color *= vec3(exposure);\n#endif\n color = color / (1.0 + color);\n color = czm_inverseGamma(color);\n out_FragColor = vec4(color, fragmentColor.a);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/Silhouette.js
var import_InlineWorkers1101 = __toESM(require_InlineWorkers(), 1);
var Silhouette_default = "uniform sampler2D colorTexture;\nuniform sampler2D silhouetteTexture;\n\nin vec2 v_textureCoordinates;\n\nvoid main(void)\n{\n vec4 silhouetteColor = texture(silhouetteTexture, v_textureCoordinates);\n vec4 color = texture(colorTexture, v_textureCoordinates);\n out_FragColor = mix(color, silhouetteColor, silhouetteColor.a);\n}\n";
// packages/engine/Source/Shaders/FXAA3_11.js
var import_InlineWorkers1102 = __toESM(require_InlineWorkers(), 1);
/**
* @license
* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of NVIDIA CORPORATION nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var FXAA3_11_default = "/**\n * @license\n * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * * Neither the name of NVIDIA CORPORATION nor the names of its\n * contributors may be used to endorse or promote products derived\n * from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// NVIDIA GameWorks Graphics Samples GitHub link: https://github.com/NVIDIAGameWorks/GraphicsSamples\n// Original source (archived): https://archive.org/details/nvidiagame-works-graphics-samples-master\n// Original FXAA 3.11 shader link: https://github.com/NVIDIAGameWorks/GraphicsSamples/blob/master/samples/es3-kepler/FXAA/FXAA3_11.h\n// Shader link in fork: https://github.com/lyntel/GraphicsSamples/blob/3d30817ebeeade64fe6a4fc3aa1fe4265c29b6fd/samples/es3-kepler/FXAA/FXAA3_11.h\n\n// Steps used to integrate into Cesium:\n// * The following defines are set:\n// #define FXAA_PC 1\n// #define FXAA_WEBGL_1 1\n// #define FXAA_GREEN_AS_LUMA 1\n// #define FXAA_EARLY_EXIT 1\n// #define FXAA_GLSL_120 1\n// * All other preprocessor directives besides the FXAA_QUALITY__P* directives were removed.\n// * Double underscores are invalid for preprocessor directives so replace them with a single underscore. Replace\n// /FXAA_QUALITY__P(.*)/g with /FXAA_QUALITY__P$1/.\n// * There are no implicit conversions from ivec* to vec* so replace:\n// #define FxaaInt2 ivec2\n// with\n// #define FxaaInt2 vec2\n// * The texture2DLod function is only available in vertex shaders so replace:\n// #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)\n// #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)\n// with\n// #define FxaaTexTop(t, p) texture(t, p)\n// #define FxaaTexOff(t, p, o, r) texture(t, p + (o * r))\n// * FXAA_QUALITY_PRESET is prepended in the javascript code. We may want to expose that setting in the future.\n// * The following parameters to FxaaPixelShader are unused and can be removed:\n// fxaaConsolePosPos\n// fxaaConsoleRcpFrameOpt\n// fxaaConsoleRcpFrameOpt2\n// fxaaConsole360RcpFrameOpt2\n// fxaaConsoleEdgeSharpness\n// fxaaConsoleEdgeThreshold\n// fxaaConsoleEdgeThresholdMi\n// fxaaConsole360ConstDir\n\n//\n// Choose the quality preset.\n// This needs to be compiled into the shader as it effects code.\n// Best option to include multiple presets is to\n// in each shader define the preset, then include this file.\n//\n// OPTIONS\n// -----------------------------------------------------------------------\n// 10 to 15 - default medium dither (10=fastest, 15=highest quality)\n// 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)\n// 39 - no dither, very expensive\n//\n// NOTES\n// -----------------------------------------------------------------------\n// 12 = slightly faster then FXAA 3.9 and higher edge quality (default)\n// 13 = about same speed as FXAA 3.9 and better than 12\n// 23 = closest to FXAA 3.9 visually and performance wise\n// _ = the lowest digit is directly related to performance\n// _ = the highest digit is directly related to style\n//\n//#define FXAA_QUALITY_PRESET 12\n\n\n#if (FXAA_QUALITY_PRESET == 10)\n #define FXAA_QUALITY_PS 3\n #define FXAA_QUALITY_P0 1.5\n #define FXAA_QUALITY_P1 3.0\n #define FXAA_QUALITY_P2 12.0\n#endif\n#if (FXAA_QUALITY_PRESET == 11)\n #define FXAA_QUALITY_PS 4\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 3.0\n #define FXAA_QUALITY_P3 12.0\n#endif\n#if (FXAA_QUALITY_PRESET == 12)\n #define FXAA_QUALITY_PS 5\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 4.0\n #define FXAA_QUALITY_P4 12.0\n#endif\n#if (FXAA_QUALITY_PRESET == 13)\n #define FXAA_QUALITY_PS 6\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 2.0\n #define FXAA_QUALITY_P4 4.0\n #define FXAA_QUALITY_P5 12.0\n#endif\n#if (FXAA_QUALITY_PRESET == 14)\n #define FXAA_QUALITY_PS 7\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 2.0\n #define FXAA_QUALITY_P4 2.0\n #define FXAA_QUALITY_P5 4.0\n #define FXAA_QUALITY_P6 12.0\n#endif\n#if (FXAA_QUALITY_PRESET == 15)\n #define FXAA_QUALITY_PS 8\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 2.0\n #define FXAA_QUALITY_P4 2.0\n #define FXAA_QUALITY_P5 2.0\n #define FXAA_QUALITY_P6 4.0\n #define FXAA_QUALITY_P7 12.0\n#endif\n#if (FXAA_QUALITY_PRESET == 20)\n #define FXAA_QUALITY_PS 3\n #define FXAA_QUALITY_P0 1.5\n #define FXAA_QUALITY_P1 2.0\n #define FXAA_QUALITY_P2 8.0\n#endif\n#if (FXAA_QUALITY_PRESET == 21)\n #define FXAA_QUALITY_PS 4\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 8.0\n#endif\n#if (FXAA_QUALITY_PRESET == 22)\n #define FXAA_QUALITY_PS 5\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 2.0\n #define FXAA_QUALITY_P4 8.0\n#endif\n#if (FXAA_QUALITY_PRESET == 23)\n #define FXAA_QUALITY_PS 6\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 2.0\n #define FXAA_QUALITY_P4 2.0\n #define FXAA_QUALITY_P5 8.0\n#endif\n#if (FXAA_QUALITY_PRESET == 24)\n #define FXAA_QUALITY_PS 7\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 2.0\n #define FXAA_QUALITY_P4 2.0\n #define FXAA_QUALITY_P5 3.0\n #define FXAA_QUALITY_P6 8.0\n#endif\n#if (FXAA_QUALITY_PRESET == 25)\n #define FXAA_QUALITY_PS 8\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 2.0\n #define FXAA_QUALITY_P4 2.0\n #define FXAA_QUALITY_P5 2.0\n #define FXAA_QUALITY_P6 4.0\n #define FXAA_QUALITY_P7 8.0\n#endif\n#if (FXAA_QUALITY_PRESET == 26)\n #define FXAA_QUALITY_PS 9\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 2.0\n #define FXAA_QUALITY_P4 2.0\n #define FXAA_QUALITY_P5 2.0\n #define FXAA_QUALITY_P6 2.0\n #define FXAA_QUALITY_P7 4.0\n #define FXAA_QUALITY_P8 8.0\n#endif\n#if (FXAA_QUALITY_PRESET == 27)\n #define FXAA_QUALITY_PS 10\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 2.0\n #define FXAA_QUALITY_P4 2.0\n #define FXAA_QUALITY_P5 2.0\n #define FXAA_QUALITY_P6 2.0\n #define FXAA_QUALITY_P7 2.0\n #define FXAA_QUALITY_P8 4.0\n #define FXAA_QUALITY_P9 8.0\n#endif\n#if (FXAA_QUALITY_PRESET == 28)\n #define FXAA_QUALITY_PS 11\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 2.0\n #define FXAA_QUALITY_P4 2.0\n #define FXAA_QUALITY_P5 2.0\n #define FXAA_QUALITY_P6 2.0\n #define FXAA_QUALITY_P7 2.0\n #define FXAA_QUALITY_P8 2.0\n #define FXAA_QUALITY_P9 4.0\n #define FXAA_QUALITY_P10 8.0\n#endif\n#if (FXAA_QUALITY_PRESET == 29)\n #define FXAA_QUALITY_PS 12\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.5\n #define FXAA_QUALITY_P2 2.0\n #define FXAA_QUALITY_P3 2.0\n #define FXAA_QUALITY_P4 2.0\n #define FXAA_QUALITY_P5 2.0\n #define FXAA_QUALITY_P6 2.0\n #define FXAA_QUALITY_P7 2.0\n #define FXAA_QUALITY_P8 2.0\n #define FXAA_QUALITY_P9 2.0\n #define FXAA_QUALITY_P10 4.0\n #define FXAA_QUALITY_P11 8.0\n#endif\n#if (FXAA_QUALITY_PRESET == 39)\n #define FXAA_QUALITY_PS 12\n #define FXAA_QUALITY_P0 1.0\n #define FXAA_QUALITY_P1 1.0\n #define FXAA_QUALITY_P2 1.0\n #define FXAA_QUALITY_P3 1.0\n #define FXAA_QUALITY_P4 1.0\n #define FXAA_QUALITY_P5 1.5\n #define FXAA_QUALITY_P6 2.0\n #define FXAA_QUALITY_P7 2.0\n #define FXAA_QUALITY_P8 2.0\n #define FXAA_QUALITY_P9 2.0\n #define FXAA_QUALITY_P10 4.0\n #define FXAA_QUALITY_P11 8.0\n#endif\n\n#define FxaaBool bool\n#define FxaaFloat float\n#define FxaaFloat2 vec2\n#define FxaaFloat3 vec3\n#define FxaaFloat4 vec4\n#define FxaaHalf float\n#define FxaaHalf2 vec2\n#define FxaaHalf3 vec3\n#define FxaaHalf4 vec4\n#define FxaaInt2 vec2\n#define FxaaTex sampler2D\n\n#define FxaaSat(x) clamp(x, 0.0, 1.0)\n#define FxaaTexTop(t, p) texture(t, p)\n#define FxaaTexOff(t, p, o, r) texture(t, p + (o * r))\n\nFxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }\n\nFxaaFloat4 FxaaPixelShader(\n //\n // Use noperspective interpolation here (turn off perspective interpolation).\n // {xy} = center of pixel\n FxaaFloat2 pos,\n //\n // Input color texture.\n // {rgb_} = color in linear or perceptual color space\n // if (FXAA_GREEN_AS_LUMA == 0)\n // {___a} = luma in perceptual color space (not linear)\n FxaaTex tex,\n //\n // Only used on FXAA Quality.\n // This must be from a constant/uniform.\n // {x_} = 1.0/screenWidthInPixels\n // {_y} = 1.0/screenHeightInPixels\n FxaaFloat2 fxaaQualityRcpFrame,\n //\n // Only used on FXAA Quality.\n // This used to be the FXAA_QUALITY_SUBPIX define.\n // It is here now to allow easier tuning.\n // Choose the amount of sub-pixel aliasing removal.\n // This can effect sharpness.\n // 1.00 - upper limit (softer)\n // 0.75 - default amount of filtering\n // 0.50 - lower limit (sharper, less sub-pixel aliasing removal)\n // 0.25 - almost off\n // 0.00 - completely off\n FxaaFloat fxaaQualitySubpix,\n //\n // Only used on FXAA Quality.\n // This used to be the FXAA_QUALITY_EDGE_THRESHOLD define.\n // It is here now to allow easier tuning.\n // The minimum amount of local contrast required to apply algorithm.\n // 0.333 - too little (faster)\n // 0.250 - low quality\n // 0.166 - default\n // 0.125 - high quality\n // 0.063 - overkill (slower)\n FxaaFloat fxaaQualityEdgeThreshold,\n //\n // Only used on FXAA Quality.\n // This used to be the FXAA_QUALITY_EDGE_THRESHOLD_MIN define.\n // It is here now to allow easier tuning.\n // Trims the algorithm from processing darks.\n // 0.0833 - upper limit (default, the start of visible unfiltered edges)\n // 0.0625 - high quality (faster)\n // 0.0312 - visible limit (slower)\n // Special notes when using FXAA_GREEN_AS_LUMA,\n // Likely want to set this to zero.\n // As colors that are mostly not-green\n // will appear very dark in the green channel!\n // Tune by looking at mostly non-green content,\n // then start at zero and increase until aliasing is a problem.\n FxaaFloat fxaaQualityEdgeThresholdMin\n) {\n/*--------------------------------------------------------------------------*/\n FxaaFloat2 posM;\n posM.x = pos.x;\n posM.y = pos.y;\n FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);\n #define lumaM rgbyM.y\n FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));\n FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));\n FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));\n FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));\n/*--------------------------------------------------------------------------*/\n FxaaFloat maxSM = max(lumaS, lumaM);\n FxaaFloat minSM = min(lumaS, lumaM);\n FxaaFloat maxESM = max(lumaE, maxSM);\n FxaaFloat minESM = min(lumaE, minSM);\n FxaaFloat maxWN = max(lumaN, lumaW);\n FxaaFloat minWN = min(lumaN, lumaW);\n FxaaFloat rangeMax = max(maxWN, maxESM);\n FxaaFloat rangeMin = min(minWN, minESM);\n FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;\n FxaaFloat range = rangeMax - rangeMin;\n FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);\n FxaaBool earlyExit = range < rangeMaxClamped;\n/*--------------------------------------------------------------------------*/\n if(earlyExit)\n return rgbyM;\n/*--------------------------------------------------------------------------*/\n FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));\n FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));\n FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));\n FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));\n/*--------------------------------------------------------------------------*/\n FxaaFloat lumaNS = lumaN + lumaS;\n FxaaFloat lumaWE = lumaW + lumaE;\n FxaaFloat subpixRcpRange = 1.0/range;\n FxaaFloat subpixNSWE = lumaNS + lumaWE;\n FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;\n FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;\n/*--------------------------------------------------------------------------*/\n FxaaFloat lumaNESE = lumaNE + lumaSE;\n FxaaFloat lumaNWNE = lumaNW + lumaNE;\n FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;\n FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;\n/*--------------------------------------------------------------------------*/\n FxaaFloat lumaNWSW = lumaNW + lumaSW;\n FxaaFloat lumaSWSE = lumaSW + lumaSE;\n FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);\n FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);\n FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;\n FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;\n FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;\n FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;\n/*--------------------------------------------------------------------------*/\n FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;\n FxaaFloat lengthSign = fxaaQualityRcpFrame.x;\n FxaaBool horzSpan = edgeHorz >= edgeVert;\n FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;\n/*--------------------------------------------------------------------------*/\n if(!horzSpan) lumaN = lumaW;\n if(!horzSpan) lumaS = lumaE;\n if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;\n FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;\n/*--------------------------------------------------------------------------*/\n FxaaFloat gradientN = lumaN - lumaM;\n FxaaFloat gradientS = lumaS - lumaM;\n FxaaFloat lumaNN = lumaN + lumaM;\n FxaaFloat lumaSS = lumaS + lumaM;\n FxaaBool pairN = abs(gradientN) >= abs(gradientS);\n FxaaFloat gradient = max(abs(gradientN), abs(gradientS));\n if(pairN) lengthSign = -lengthSign;\n FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);\n/*--------------------------------------------------------------------------*/\n FxaaFloat2 posB;\n posB.x = posM.x;\n posB.y = posM.y;\n FxaaFloat2 offNP;\n offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;\n offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;\n if(!horzSpan) posB.x += lengthSign * 0.5;\n if( horzSpan) posB.y += lengthSign * 0.5;\n/*--------------------------------------------------------------------------*/\n FxaaFloat2 posN;\n posN.x = posB.x - offNP.x * FXAA_QUALITY_P0;\n posN.y = posB.y - offNP.y * FXAA_QUALITY_P0;\n FxaaFloat2 posP;\n posP.x = posB.x + offNP.x * FXAA_QUALITY_P0;\n posP.y = posB.y + offNP.y * FXAA_QUALITY_P0;\n FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;\n FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));\n FxaaFloat subpixE = subpixC * subpixC;\n FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));\n/*--------------------------------------------------------------------------*/\n if(!pairN) lumaNN = lumaSS;\n FxaaFloat gradientScaled = gradient * 1.0/4.0;\n FxaaFloat lumaMM = lumaM - lumaNN * 0.5;\n FxaaFloat subpixF = subpixD * subpixE;\n FxaaBool lumaMLTZero = lumaMM < 0.0;\n/*--------------------------------------------------------------------------*/\n lumaEndN -= lumaNN * 0.5;\n lumaEndP -= lumaNN * 0.5;\n FxaaBool doneN = abs(lumaEndN) >= gradientScaled;\n FxaaBool doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P1;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P1;\n FxaaBool doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P1;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P1;\n/*--------------------------------------------------------------------------*/\n if(doneNP) {\n if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n doneN = abs(lumaEndN) >= gradientScaled;\n doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P2;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P2;\n doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P2;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P2;\n/*--------------------------------------------------------------------------*/\n #if (FXAA_QUALITY_PS > 3)\n if(doneNP) {\n if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n doneN = abs(lumaEndN) >= gradientScaled;\n doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P3;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P3;\n doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P3;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P3;\n/*--------------------------------------------------------------------------*/\n #if (FXAA_QUALITY_PS > 4)\n if(doneNP) {\n if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n doneN = abs(lumaEndN) >= gradientScaled;\n doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P4;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P4;\n doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P4;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P4;\n/*--------------------------------------------------------------------------*/\n #if (FXAA_QUALITY_PS > 5)\n if(doneNP) {\n if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n doneN = abs(lumaEndN) >= gradientScaled;\n doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P5;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P5;\n doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P5;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P5;\n/*--------------------------------------------------------------------------*/\n #if (FXAA_QUALITY_PS > 6)\n if(doneNP) {\n if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n doneN = abs(lumaEndN) >= gradientScaled;\n doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P6;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P6;\n doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P6;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P6;\n/*--------------------------------------------------------------------------*/\n #if (FXAA_QUALITY_PS > 7)\n if(doneNP) {\n if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n doneN = abs(lumaEndN) >= gradientScaled;\n doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P7;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P7;\n doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P7;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P7;\n/*--------------------------------------------------------------------------*/\n #if (FXAA_QUALITY_PS > 8)\n if(doneNP) {\n if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n doneN = abs(lumaEndN) >= gradientScaled;\n doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P8;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P8;\n doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P8;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P8;\n/*--------------------------------------------------------------------------*/\n #if (FXAA_QUALITY_PS > 9)\n if(doneNP) {\n if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n doneN = abs(lumaEndN) >= gradientScaled;\n doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P9;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P9;\n doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P9;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P9;\n/*--------------------------------------------------------------------------*/\n #if (FXAA_QUALITY_PS > 10)\n if(doneNP) {\n if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n doneN = abs(lumaEndN) >= gradientScaled;\n doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P10;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P10;\n doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P10;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P10;\n/*--------------------------------------------------------------------------*/\n #if (FXAA_QUALITY_PS > 11)\n if(doneNP) {\n if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n doneN = abs(lumaEndN) >= gradientScaled;\n doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P11;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P11;\n doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P11;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P11;\n/*--------------------------------------------------------------------------*/\n #if (FXAA_QUALITY_PS > 12)\n if(doneNP) {\n if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n doneN = abs(lumaEndN) >= gradientScaled;\n doneP = abs(lumaEndP) >= gradientScaled;\n if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P12;\n if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P12;\n doneNP = (!doneN) || (!doneP);\n if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P12;\n if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P12;\n/*--------------------------------------------------------------------------*/\n }\n #endif\n/*--------------------------------------------------------------------------*/\n }\n #endif\n/*--------------------------------------------------------------------------*/\n }\n #endif\n/*--------------------------------------------------------------------------*/\n }\n #endif\n/*--------------------------------------------------------------------------*/\n }\n #endif\n/*--------------------------------------------------------------------------*/\n }\n #endif\n/*--------------------------------------------------------------------------*/\n }\n #endif\n/*--------------------------------------------------------------------------*/\n }\n #endif\n/*--------------------------------------------------------------------------*/\n }\n #endif\n/*--------------------------------------------------------------------------*/\n }\n #endif\n/*--------------------------------------------------------------------------*/\n }\n/*--------------------------------------------------------------------------*/\n FxaaFloat dstN = posM.x - posN.x;\n FxaaFloat dstP = posP.x - posM.x;\n if(!horzSpan) dstN = posM.y - posN.y;\n if(!horzSpan) dstP = posP.y - posM.y;\n/*--------------------------------------------------------------------------*/\n FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;\n FxaaFloat spanLength = (dstP + dstN);\n FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;\n FxaaFloat spanLengthRcp = 1.0/spanLength;\n/*--------------------------------------------------------------------------*/\n FxaaBool directionN = dstN < dstP;\n FxaaFloat dst = min(dstN, dstP);\n FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;\n FxaaFloat subpixG = subpixF * subpixF;\n FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;\n FxaaFloat subpixH = subpixG * fxaaQualitySubpix;\n/*--------------------------------------------------------------------------*/\n FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;\n FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);\n if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;\n if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;\n return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);\n}\n";
// packages/engine/Source/Scene/AutoExposure.js
var import_InlineWorkers1103 = __toESM(require_InlineWorkers(), 1);
function AutoExposure() {
this._uniformMap = void 0;
this._command = void 0;
this._colorTexture = void 0;
this._depthTexture = void 0;
this._ready = false;
this._name = "czm_autoexposure";
this._logDepthChanged = void 0;
this._useLogDepth = void 0;
this._framebuffers = void 0;
this._previousLuminance = new FramebufferManager_default();
this._commands = void 0;
this._clearCommand = void 0;
this._minMaxLuminance = new Cartesian2_default();
this.enabled = true;
this._enabled = true;
this.minimumLuminance = 0.1;
this.maximumLuminance = 10;
}
Object.defineProperties(AutoExposure.prototype, {
/**
* Determines if this post-process stage is ready to be executed. A stage is only executed when both ready
* and {@link AutoExposure#enabled} are true. A stage will not be ready while it is waiting on textures
* to load.
*
* @memberof AutoExposure.prototype
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
},
/**
* The unique name of this post-process stage for reference by other stages.
*
* @memberof AutoExposure.prototype
* @type {string}
* @readonly
*/
name: {
get: function() {
return this._name;
}
},
/**
* A reference to the texture written to when executing this post process stage.
*
* @memberof AutoExposure.prototype
* @type {Texture}
* @readonly
* @private
*/
outputTexture: {
get: function() {
const framebuffers = this._framebuffers;
if (!defined_default(framebuffers)) {
return void 0;
}
return framebuffers[framebuffers.length - 1].getColorTexture(0);
}
}
});
function destroyFramebuffers3(autoexposure) {
const framebuffers = autoexposure._framebuffers;
if (!defined_default(framebuffers)) {
return;
}
const length2 = framebuffers.length;
for (let i = 0; i < length2; ++i) {
framebuffers[i].destroy();
}
autoexposure._framebuffers = void 0;
autoexposure._previousLuminance.destroy();
autoexposure._previousLuminance = void 0;
}
function createFramebuffers(autoexposure, context) {
destroyFramebuffers3(autoexposure);
let width = autoexposure._width;
let height = autoexposure._height;
const pixelDatatype = context.halfFloatingPointTexture ? PixelDatatype_default.HALF_FLOAT : PixelDatatype_default.FLOAT;
const length2 = Math.ceil(Math.log(Math.max(width, height)) / Math.log(3));
const framebuffers = new Array(length2);
for (let i = 0; i < length2; ++i) {
width = Math.max(Math.ceil(width / 3), 1);
height = Math.max(Math.ceil(height / 3), 1);
framebuffers[i] = new FramebufferManager_default();
framebuffers[i].update(context, width, height, 1, pixelDatatype);
}
const lastTexture = framebuffers[length2 - 1].getColorTexture(0);
autoexposure._previousLuminance.update(
context,
lastTexture.width,
lastTexture.height,
1,
pixelDatatype
);
autoexposure._framebuffers = framebuffers;
}
function destroyCommands(autoexposure) {
const commands = autoexposure._commands;
if (!defined_default(commands)) {
return;
}
const length2 = commands.length;
for (let i = 0; i < length2; ++i) {
commands[i].shaderProgram.destroy();
}
autoexposure._commands = void 0;
}
function createUniformMap4(autoexposure, index) {
let uniforms;
if (index === 0) {
uniforms = {
colorTexture: function() {
return autoexposure._colorTexture;
},
colorTextureDimensions: function() {
return autoexposure._colorTexture.dimensions;
}
};
} else {
const texture = autoexposure._framebuffers[index - 1].getColorTexture(0);
uniforms = {
colorTexture: function() {
return texture;
},
colorTextureDimensions: function() {
return texture.dimensions;
}
};
}
uniforms.minMaxLuminance = function() {
return autoexposure._minMaxLuminance;
};
uniforms.previousLuminance = function() {
return autoexposure._previousLuminance.getColorTexture(0);
};
return uniforms;
}
function getShaderSource(index, length2) {
let source = "uniform sampler2D colorTexture; \nin vec2 v_textureCoordinates; \nfloat sampleTexture(vec2 offset) { \n";
if (index === 0) {
source += " vec4 color = texture(colorTexture, v_textureCoordinates + offset); \n return czm_luminance(color.rgb); \n";
} else {
source += " return texture(colorTexture, v_textureCoordinates + offset).r; \n";
}
source += "}\n\n";
source += "uniform vec2 colorTextureDimensions; \nuniform vec2 minMaxLuminance; \nuniform sampler2D previousLuminance; \nvoid main() { \n float color = 0.0; \n float xStep = 1.0 / colorTextureDimensions.x; \n float yStep = 1.0 / colorTextureDimensions.y; \n int count = 0; \n for (int i = 0; i < 3; ++i) { \n for (int j = 0; j < 3; ++j) { \n vec2 offset; \n offset.x = -xStep + float(i) * xStep; \n offset.y = -yStep + float(j) * yStep; \n if (offset.x < 0.0 || offset.x > 1.0 || offset.y < 0.0 || offset.y > 1.0) { \n continue; \n } \n color += sampleTexture(offset); \n ++count; \n } \n } \n if (count > 0) { \n color /= float(count); \n } \n";
if (index === length2 - 1) {
source += " float previous = texture(previousLuminance, vec2(0.5)).r; \n color = clamp(color, minMaxLuminance.x, minMaxLuminance.y); \n color = previous + (color - previous) / (60.0 * 1.5); \n color = clamp(color, minMaxLuminance.x, minMaxLuminance.y); \n";
}
source += " out_FragColor = vec4(color); \n} \n";
return source;
}
function createCommands5(autoexposure, context) {
destroyCommands(autoexposure);
const framebuffers = autoexposure._framebuffers;
const length2 = framebuffers.length;
const commands = new Array(length2);
for (let i = 0; i < length2; ++i) {
commands[i] = context.createViewportQuadCommand(
getShaderSource(i, length2),
{
framebuffer: framebuffers[i].framebuffer,
uniformMap: createUniformMap4(autoexposure, i)
}
);
}
autoexposure._commands = commands;
}
AutoExposure.prototype.clear = function(context) {
const framebuffers = this._framebuffers;
if (!defined_default(framebuffers)) {
return;
}
let clearCommand = this._clearCommand;
if (!defined_default(clearCommand)) {
clearCommand = this._clearCommand = new ClearCommand_default({
color: new Color_default(0, 0, 0, 0),
framebuffer: void 0
});
}
const length2 = framebuffers.length;
for (let i = 0; i < length2; ++i) {
framebuffers[i].clear(context, clearCommand);
}
};
AutoExposure.prototype.update = function(context) {
const width = context.drawingBufferWidth;
const height = context.drawingBufferHeight;
if (width !== this._width || height !== this._height) {
this._width = width;
this._height = height;
createFramebuffers(this, context);
createCommands5(this, context);
if (!this._ready) {
this._ready = true;
}
}
this._minMaxLuminance.x = this.minimumLuminance;
this._minMaxLuminance.y = this.maximumLuminance;
const framebuffers = this._framebuffers;
const temp = framebuffers[framebuffers.length - 1];
framebuffers[framebuffers.length - 1] = this._previousLuminance;
this._commands[this._commands.length - 1].framebuffer = this._previousLuminance.framebuffer;
this._previousLuminance = temp;
};
AutoExposure.prototype.execute = function(context, colorTexture) {
this._colorTexture = colorTexture;
const commands = this._commands;
if (!defined_default(commands)) {
return;
}
const length2 = commands.length;
for (let i = 0; i < length2; ++i) {
commands[i].execute(context);
}
};
AutoExposure.prototype.isDestroyed = function() {
return false;
};
AutoExposure.prototype.destroy = function() {
destroyFramebuffers3(this);
destroyCommands(this);
return destroyObject_default(this);
};
var AutoExposure_default = AutoExposure;
// packages/engine/Source/Scene/PostProcessStage.js
var import_InlineWorkers1105 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/PostProcessStageSampleMode.js
var import_InlineWorkers1104 = __toESM(require_InlineWorkers(), 1);
var PostProcessStageSampleMode = {
/**
* Samples the texture by returning the closest texel.
*
* @type {number}
* @constant
*/
NEAREST: 0,
/**
* Samples the texture through bi-linear interpolation of the four nearest texels.
*
* @type {number}
* @constant
*/
LINEAR: 1
};
var PostProcessStageSampleMode_default = PostProcessStageSampleMode;
// packages/engine/Source/Scene/PostProcessStage.js
function PostProcessStage(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const {
name = createGuid_default(),
fragmentShader,
uniforms,
textureScale = 1,
forcePowerOfTwo = false,
sampleMode = PostProcessStageSampleMode_default.NEAREST,
pixelFormat = PixelFormat_default.RGBA,
pixelDatatype = PixelDatatype_default.UNSIGNED_BYTE,
clearColor = Color_default.BLACK,
scissorRectangle
} = options;
Check_default.typeOf.string("options.fragmentShader", fragmentShader);
Check_default.typeOf.number.greaterThan("options.textureScale", textureScale, 0);
Check_default.typeOf.number.lessThanOrEquals(
"options.textureScale",
textureScale,
1
);
if (!PixelFormat_default.isColorFormat(pixelFormat)) {
throw new DeveloperError_default("options.pixelFormat must be a color format.");
}
this._fragmentShader = fragmentShader;
this._uniforms = uniforms;
this._textureScale = textureScale;
this._forcePowerOfTwo = forcePowerOfTwo;
this._sampleMode = sampleMode;
this._pixelFormat = pixelFormat;
this._pixelDatatype = pixelDatatype;
this._clearColor = clearColor;
this._uniformMap = void 0;
this._command = void 0;
this._colorTexture = void 0;
this._depthTexture = void 0;
this._idTexture = void 0;
this._actualUniforms = {};
this._dirtyUniforms = [];
this._texturesToRelease = [];
this._texturesToCreate = [];
this._texturePromise = void 0;
const passState = new PassState_default();
passState.scissorTest = {
enabled: true,
rectangle: defined_default(scissorRectangle) ? BoundingRectangle_default.clone(scissorRectangle) : new BoundingRectangle_default()
};
this._passState = passState;
this._ready = false;
this._name = name;
this._logDepthChanged = void 0;
this._useLogDepth = void 0;
this._selectedIdTexture = void 0;
this._selected = void 0;
this._selectedShadow = void 0;
this._parentSelected = void 0;
this._parentSelectedShadow = void 0;
this._combinedSelected = void 0;
this._combinedSelectedShadow = void 0;
this._selectedLength = 0;
this._parentSelectedLength = 0;
this._selectedDirty = true;
this._textureCache = void 0;
this._index = void 0;
this.enabled = true;
this._enabled = true;
}
Object.defineProperties(PostProcessStage.prototype, {
/**
* Determines if this post-process stage is ready to be executed. A stage is only executed when both ready
* and {@link PostProcessStage#enabled} are true. A stage will not be ready while it is waiting on textures
* to load.
*
* @memberof PostProcessStage.prototype
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
},
/**
* The unique name of this post-process stage for reference by other stages in a {@link PostProcessStageComposite}.
*
* @memberof PostProcessStage.prototype
* @type {string}
* @readonly
*/
name: {
get: function() {
return this._name;
}
},
/**
* The fragment shader to use when execute this post-process stage.
*
* The shader must contain a sampler uniform declaration for colorTexture, depthTexture,
* or both.
*
*
* The shader must contain a vec2 varying declaration for v_textureCoordinates for sampling
* the texture uniforms.
*
*
* @memberof PostProcessStage.prototype
* @type {string}
* @readonly
*/
fragmentShader: {
get: function() {
return this._fragmentShader;
}
},
/**
* An object whose properties are used to set the uniforms of the fragment shader.
*
* The object property values can be either a constant or a function. The function will be called
* each frame before the post-process stage is executed.
*
*
* A constant value can also be a URI to an image, a data URI, or an HTML element that can be used as a texture, such as HTMLImageElement or HTMLCanvasElement.
*
*
* If this post-process stage is part of a {@link PostProcessStageComposite} that does not execute in series, the constant value can also be
* the name of another stage in a composite. This will set the uniform to the output texture the stage with that name.
*
*
* @memberof PostProcessStage.prototype
* @type {object}
* @readonly
*/
uniforms: {
get: function() {
return this._uniforms;
}
},
/**
* A number in the range (0.0, 1.0] used to scale the output texture dimensions. A scale of 1.0 will render this post-process stage to a texture the size of the viewport.
*
* @memberof PostProcessStage.prototype
* @type {number}
* @readonly
*/
textureScale: {
get: function() {
return this._textureScale;
}
},
/**
* Whether or not to force the output texture dimensions to be both equal powers of two. The power of two will be the next power of two of the minimum of the dimensions.
*
* @memberof PostProcessStage.prototype
* @type {number}
* @readonly
*/
forcePowerOfTwo: {
get: function() {
return this._forcePowerOfTwo;
}
},
/**
* How to sample the input color texture.
*
* @memberof PostProcessStage.prototype
* @type {PostProcessStageSampleMode}
* @readonly
*/
sampleMode: {
get: function() {
return this._sampleMode;
}
},
/**
* The color pixel format of the output texture.
*
* @memberof PostProcessStage.prototype
* @type {PixelFormat}
* @readonly
*/
pixelFormat: {
get: function() {
return this._pixelFormat;
}
},
/**
* The pixel data type of the output texture.
*
* @memberof PostProcessStage.prototype
* @type {PixelDatatype}
* @readonly
*/
pixelDatatype: {
get: function() {
return this._pixelDatatype;
}
},
/**
* The color to clear the output texture to.
*
* @memberof PostProcessStage.prototype
* @type {Color}
* @readonly
*/
clearColor: {
get: function() {
return this._clearColor;
}
},
/**
* The {@link BoundingRectangle} to use for the scissor test. A default bounding rectangle will disable the scissor test.
*
* @memberof PostProcessStage.prototype
* @type {BoundingRectangle}
* @readonly
*/
scissorRectangle: {
get: function() {
return this._passState.scissorTest.rectangle;
}
},
/**
* A reference to the texture written to when executing this post process stage.
*
* @memberof PostProcessStage.prototype
* @type {Texture}
* @readonly
* @private
*/
outputTexture: {
get: function() {
if (defined_default(this._textureCache)) {
const framebuffer = this._textureCache.getFramebuffer(this._name);
if (defined_default(framebuffer)) {
return framebuffer.getColorTexture(0);
}
}
return void 0;
}
},
/**
* The features selected for applying the post-process.
*
* In the fragment shader, use czm_selected to determine whether or not to apply the post-process
* stage to that fragment. For example:
*
* if (czm_selected(v_textureCoordinates)) {
* // apply post-process stage
* } else {
* out_FragColor = texture(colorTexture, v_textureCoordinates);
* }
*
*
*
* @memberof PostProcessStage.prototype
* @type {Array}
*/
selected: {
get: function() {
return this._selected;
},
set: function(value) {
this._selected = value;
}
},
/**
* @private
*/
parentSelected: {
get: function() {
return this._parentSelected;
},
set: function(value) {
this._parentSelected = value;
}
}
});
var depthTextureRegex = /uniform\s+sampler2D\s+depthTexture/g;
PostProcessStage.prototype._isSupported = function(context) {
return !depthTextureRegex.test(this._fragmentShader) || context.depthTexture;
};
function getUniformValueGetterAndSetter(stage, uniforms, name) {
const currentValue = uniforms[name];
if (typeof currentValue === "string" || currentValue instanceof HTMLCanvasElement || currentValue instanceof HTMLImageElement || currentValue instanceof HTMLVideoElement || currentValue instanceof ImageData) {
stage._dirtyUniforms.push(name);
}
return {
get: function() {
return uniforms[name];
},
set: function(value) {
const currentValue2 = uniforms[name];
uniforms[name] = value;
const actualUniforms = stage._actualUniforms;
const actualValue = actualUniforms[name];
if (defined_default(actualValue) && actualValue !== currentValue2 && actualValue instanceof Texture_default && !defined_default(stage._textureCache.getStageByName(name))) {
stage._texturesToRelease.push(actualValue);
delete actualUniforms[name];
delete actualUniforms[`${name}Dimensions`];
}
if (currentValue2 instanceof Texture_default) {
stage._texturesToRelease.push(currentValue2);
}
if (typeof value === "string" || value instanceof HTMLCanvasElement || value instanceof HTMLImageElement || value instanceof HTMLVideoElement || value instanceof ImageData) {
stage._dirtyUniforms.push(name);
} else {
actualUniforms[name] = value;
}
}
};
}
function getUniformMapFunction(stage, name) {
return function() {
const value = stage._actualUniforms[name];
if (typeof value === "function") {
return value();
}
return value;
};
}
function getUniformMapDimensionsFunction(uniformMap2, name) {
return function() {
const texture = uniformMap2[name]();
if (defined_default(texture)) {
return texture.dimensions;
}
return void 0;
};
}
function createUniformMap5(stage) {
if (defined_default(stage._uniformMap)) {
return;
}
const uniformMap2 = {};
const newUniforms = {};
const uniforms = stage._uniforms;
const actualUniforms = stage._actualUniforms;
for (const name in uniforms) {
if (!uniforms.hasOwnProperty(name)) {
continue;
}
if (typeof uniforms[name] !== "function") {
uniformMap2[name] = getUniformMapFunction(stage, name);
newUniforms[name] = getUniformValueGetterAndSetter(stage, uniforms, name);
} else {
uniformMap2[name] = uniforms[name];
newUniforms[name] = uniforms[name];
}
actualUniforms[name] = uniforms[name];
const value = uniformMap2[name]();
if (typeof value === "string" || value instanceof Texture_default || value instanceof HTMLImageElement || value instanceof HTMLCanvasElement || value instanceof HTMLVideoElement) {
uniformMap2[`${name}Dimensions`] = getUniformMapDimensionsFunction(
uniformMap2,
name
);
}
}
stage._uniforms = {};
Object.defineProperties(stage._uniforms, newUniforms);
stage._uniformMap = combine_default(uniformMap2, {
colorTexture: function() {
return stage._colorTexture;
},
colorTextureDimensions: function() {
return stage._colorTexture.dimensions;
},
depthTexture: function() {
return stage._depthTexture;
},
depthTextureDimensions: function() {
return stage._depthTexture.dimensions;
},
czm_idTexture: function() {
return stage._idTexture;
},
czm_selectedIdTexture: function() {
return stage._selectedIdTexture;
},
czm_selectedIdTextureStep: function() {
return 1 / stage._selectedIdTexture.width;
}
});
}
function addSelectedIdToShader(shaderSource, idTextureWidth) {
shaderSource = shaderSource.replace(/in\s+vec2\s+v_textureCoordinates;/g, "");
return `#define CZM_SELECTED_FEATURE
uniform sampler2D czm_idTexture;
uniform sampler2D czm_selectedIdTexture;
uniform float czm_selectedIdTextureStep;
in vec2 v_textureCoordinates;
bool czm_selected(vec2 offset)
{
bool selected = false;
vec4 id = texture(czm_idTexture, v_textureCoordinates + offset);
for (int i = 0; i < ${idTextureWidth}; ++i)
{
vec4 selectedId = texture(czm_selectedIdTexture, vec2((float(i) + 0.5) * czm_selectedIdTextureStep, 0.5));
if (all(equal(id, selectedId)))
{
return true;
}
}
return false;
}
bool czm_selected()
{
return czm_selected(vec2(0.0));
}
${shaderSource}`;
}
function createDrawCommand(stage, context) {
if (defined_default(stage._command) && !stage._logDepthChanged && !stage._selectedDirty) {
return;
}
let fragmentShaderSource = stage._fragmentShader;
if (defined_default(stage._selectedIdTexture)) {
const width = stage._selectedIdTexture.width;
fragmentShaderSource = addSelectedIdToShader(fragmentShaderSource, width);
}
const fragmentShader = new ShaderSource_default({
defines: [stage._useLogDepth ? "LOG_DEPTH" : ""],
sources: [fragmentShaderSource]
});
stage._command = context.createViewportQuadCommand(fragmentShader, {
uniformMap: stage._uniformMap,
owner: stage
});
}
function createSampler(stage) {
const mode2 = stage._sampleMode;
let minFilter;
let magFilter;
if (mode2 === PostProcessStageSampleMode_default.LINEAR) {
minFilter = TextureMinificationFilter_default.LINEAR;
magFilter = TextureMagnificationFilter_default.LINEAR;
} else {
minFilter = TextureMinificationFilter_default.NEAREST;
magFilter = TextureMagnificationFilter_default.NEAREST;
}
const sampler = stage._sampler;
if (!defined_default(sampler) || sampler.minificationFilter !== minFilter || sampler.magnificationFilter !== magFilter) {
stage._sampler = new Sampler_default({
wrapS: TextureWrap_default.CLAMP_TO_EDGE,
wrapT: TextureWrap_default.CLAMP_TO_EDGE,
minificationFilter: minFilter,
magnificationFilter: magFilter
});
}
}
function createLoadImageFunction(stage, name) {
return function(image) {
stage._texturesToCreate.push({
name,
source: image
});
};
}
function createStageOutputTextureFunction(stage, name) {
return function() {
return stage._textureCache.getOutputTexture(name);
};
}
function updateUniformTextures(stage, context) {
const texturesToRelease = stage._texturesToRelease;
for (let i = 0; i < texturesToRelease.length; ++i) {
let texture = texturesToRelease[i];
texture = texture && texture.destroy();
}
texturesToRelease.length = 0;
const texturesToCreate = stage._texturesToCreate;
for (let i = 0; i < texturesToCreate.length; ++i) {
const { name, source } = texturesToCreate[i];
stage._actualUniforms[name] = new Texture_default({
context,
source
});
}
texturesToCreate.length = 0;
const dirtyUniforms = stage._dirtyUniforms;
if (dirtyUniforms.length === 0 && !defined_default(stage._texturePromise)) {
stage._ready = true;
return;
}
if (dirtyUniforms.length === 0 || defined_default(stage._texturePromise)) {
return;
}
const uniforms = stage._uniforms;
const promises = [];
for (let i = 0; i < dirtyUniforms.length; ++i) {
const name = dirtyUniforms[i];
const stageNameUrlOrImage = uniforms[name];
const stageWithName = stage._textureCache.getStageByName(stageNameUrlOrImage);
if (defined_default(stageWithName)) {
stage._actualUniforms[name] = createStageOutputTextureFunction(
stage,
stageNameUrlOrImage
);
} else if (typeof stageNameUrlOrImage === "string") {
const resource = new Resource_default({
url: stageNameUrlOrImage
});
promises.push(
resource.fetchImage().then(createLoadImageFunction(stage, name))
);
} else {
stage._texturesToCreate.push({
name,
source: stageNameUrlOrImage
});
}
}
dirtyUniforms.length = 0;
if (promises.length > 0) {
stage._ready = false;
stage._texturePromise = Promise.all(promises).then(function() {
stage._ready = true;
stage._texturePromise = void 0;
});
} else {
stage._ready = true;
}
}
function releaseResources(stage) {
if (defined_default(stage._command)) {
stage._command.shaderProgram = stage._command.shaderProgram && stage._command.shaderProgram.destroy();
stage._command = void 0;
}
stage._selectedIdTexture = stage._selectedIdTexture && stage._selectedIdTexture.destroy();
const textureCache = stage._textureCache;
if (!defined_default(textureCache)) {
return;
}
const uniforms = stage._uniforms;
const actualUniforms = stage._actualUniforms;
for (const name in actualUniforms) {
if (!actualUniforms.hasOwnProperty(name)) {
continue;
}
const actualUniform = actualUniforms[name];
if (actualUniform instanceof Texture_default) {
if (!defined_default(textureCache.getStageByName(uniforms[name]))) {
actualUniform.destroy();
}
stage._dirtyUniforms.push(name);
}
}
}
function isSelectedTextureDirty(stage) {
const length2 = defined_default(stage._selected) ? stage._selected.length : 0;
const parentLength = defined_default(stage._parentSelected) ? stage._parentSelected : 0;
const dirty = stage._selected !== stage._selectedShadow || length2 !== stage._selectedLength || stage._parentSelected !== stage._parentSelectedShadow || parentLength !== stage._parentSelectedLength;
if (defined_default(stage._selected) && defined_default(stage._parentSelected)) {
stage._combinedSelected = stage._selected.concat(stage._parentSelected);
} else if (defined_default(stage._parentSelected)) {
stage._combinedSelected = stage._parentSelected;
} else {
stage._combinedSelected = stage._selected;
}
if (!dirty && defined_default(stage._combinedSelected)) {
if (!defined_default(stage._combinedSelectedShadow)) {
return true;
}
for (let i = 0; i < stage._combinedSelected.length; ++i) {
if (stage._combinedSelected[i] !== stage._combinedSelectedShadow[i]) {
return true;
}
}
}
return dirty;
}
function createSelectedTexture(stage, context) {
if (!stage._selectedDirty) {
return;
}
stage._selectedIdTexture = stage._selectedIdTexture && stage._selectedIdTexture.destroy();
stage._selectedIdTexture = void 0;
const features = stage._combinedSelected;
if (!defined_default(features)) {
return;
}
let textureLength = 0;
for (let i = 0; i < features.length; ++i) {
const feature2 = features[i];
if (defined_default(feature2.pickIds)) {
textureLength += feature2.pickIds.length;
} else if (defined_default(feature2.pickId)) {
++textureLength;
}
}
if (features.length === 0 || textureLength === 0) {
const empty = new Uint8Array([255, 255, 255, 255]);
stage._selectedIdTexture = new Texture_default({
context,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
source: {
arrayBufferView: empty,
width: 1,
height: 1
},
sampler: Sampler_default.NEAREST
});
return;
}
let offset = 0;
const ids = new Uint8Array(textureLength * 4);
for (let i = 0; i < features.length; ++i) {
const feature2 = features[i];
if (defined_default(feature2.pickIds)) {
const pickIds = feature2.pickIds;
const pickIdsLength = pickIds.length;
for (let j = 0; j < pickIdsLength; ++j) {
const pickColor = pickIds[j].color;
ids[offset] = Color_default.floatToByte(pickColor.red);
ids[offset + 1] = Color_default.floatToByte(pickColor.green);
ids[offset + 2] = Color_default.floatToByte(pickColor.blue);
ids[offset + 3] = Color_default.floatToByte(pickColor.alpha);
offset += 4;
}
} else if (defined_default(feature2.pickId)) {
const pickColor = feature2.pickId.color;
ids[offset] = Color_default.floatToByte(pickColor.red);
ids[offset + 1] = Color_default.floatToByte(pickColor.green);
ids[offset + 2] = Color_default.floatToByte(pickColor.blue);
ids[offset + 3] = Color_default.floatToByte(pickColor.alpha);
offset += 4;
}
}
stage._selectedIdTexture = new Texture_default({
context,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
source: {
arrayBufferView: ids,
width: textureLength,
height: 1
},
sampler: Sampler_default.NEAREST
});
}
PostProcessStage.prototype.update = function(context, useLogDepth) {
if (this.enabled !== this._enabled && !this.enabled) {
releaseResources(this);
}
this._enabled = this.enabled;
if (!this._enabled) {
return;
}
this._logDepthChanged = useLogDepth !== this._useLogDepth;
this._useLogDepth = useLogDepth;
this._selectedDirty = isSelectedTextureDirty(this);
this._selectedShadow = this._selected;
this._parentSelectedShadow = this._parentSelected;
this._combinedSelectedShadow = this._combinedSelected;
this._selectedLength = defined_default(this._selected) ? this._selected.length : 0;
this._parentSelectedLength = defined_default(this._parentSelected) ? this._parentSelected.length : 0;
createSelectedTexture(this, context);
createUniformMap5(this);
updateUniformTextures(this, context);
createDrawCommand(this, context);
createSampler(this);
this._selectedDirty = false;
if (!this._ready) {
return;
}
const framebuffer = this._textureCache.getFramebuffer(this._name);
this._command.framebuffer = framebuffer;
if (!defined_default(framebuffer)) {
return;
}
const colorTexture = framebuffer.getColorTexture(0);
let renderState;
if (colorTexture.width !== context.drawingBufferWidth || colorTexture.height !== context.drawingBufferHeight) {
renderState = this._renderState;
if (!defined_default(renderState) || colorTexture.width !== renderState.viewport.width || colorTexture.height !== renderState.viewport.height) {
this._renderState = RenderState_default.fromCache({
viewport: new BoundingRectangle_default(
0,
0,
colorTexture.width,
colorTexture.height
)
});
}
}
this._command.renderState = renderState;
};
PostProcessStage.prototype.execute = function(context, colorTexture, depthTexture, idTexture) {
if (!defined_default(this._command) || !defined_default(this._command.framebuffer) || !this._ready || !this._enabled) {
return;
}
this._colorTexture = colorTexture;
this._depthTexture = depthTexture;
this._idTexture = idTexture;
if (!Sampler_default.equals(this._colorTexture.sampler, this._sampler)) {
this._colorTexture.sampler = this._sampler;
}
const passState = this.scissorRectangle.width > 0 && this.scissorRectangle.height > 0 ? this._passState : void 0;
if (defined_default(passState)) {
passState.context = context;
}
this._command.execute(context, passState);
};
PostProcessStage.prototype.isDestroyed = function() {
return false;
};
PostProcessStage.prototype.destroy = function() {
releaseResources(this);
return destroyObject_default(this);
};
var PostProcessStage_default = PostProcessStage;
// packages/engine/Source/Scene/PostProcessStageComposite.js
var import_InlineWorkers1106 = __toESM(require_InlineWorkers(), 1);
function PostProcessStageComposite(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.defined("options.stages", options.stages);
Check_default.typeOf.number.greaterThan(
"options.stages.length",
options.stages.length,
0
);
this._stages = options.stages;
this._inputPreviousStageTexture = options.inputPreviousStageTexture ?? true;
let name = options.name;
if (!defined_default(name)) {
name = createGuid_default();
}
this._name = name;
this._uniforms = options.uniforms;
this._textureCache = void 0;
this._index = void 0;
this._selected = void 0;
this._selectedShadow = void 0;
this._parentSelected = void 0;
this._parentSelectedShadow = void 0;
this._combinedSelected = void 0;
this._combinedSelectedShadow = void 0;
this._selectedLength = 0;
this._parentSelectedLength = 0;
this._selectedDirty = true;
}
Object.defineProperties(PostProcessStageComposite.prototype, {
/**
* Determines if this post-process stage is ready to be executed.
*
* @memberof PostProcessStageComposite.prototype
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
const stages = this._stages;
const length2 = stages.length;
for (let i = 0; i < length2; ++i) {
if (!stages[i].ready) {
return false;
}
}
return true;
}
},
/**
* The unique name of this post-process stage for reference by other stages in a PostProcessStageComposite.
*
* @memberof PostProcessStageComposite.prototype
* @type {string}
* @readonly
*/
name: {
get: function() {
return this._name;
}
},
/**
* Whether or not to execute this post-process stage when ready.
*
* @memberof PostProcessStageComposite.prototype
* @type {boolean}
*/
enabled: {
get: function() {
return this._stages[0].enabled;
},
set: function(value) {
const stages = this._stages;
const length2 = stages.length;
for (let i = 0; i < length2; ++i) {
stages[i].enabled = value;
}
}
},
/**
* An alias to the uniform values of the post-process stages. May be undefined; in which case, get each stage to set uniform values.
* @memberof PostProcessStageComposite.prototype
* @type {object}
*/
uniforms: {
get: function() {
return this._uniforms;
}
},
/**
* All post-process stages are executed in the order of the array. The input texture changes based on the value of inputPreviousStageTexture.
* If inputPreviousStageTexture is true, the input to each stage is the output texture rendered to by the scene or of the stage that executed before it.
* If inputPreviousStageTexture is false, the input texture is the same for each stage in the composite. The input texture is the texture rendered to by the scene
* or the output texture of the previous stage.
*
* @memberof PostProcessStageComposite.prototype
* @type {boolean}
* @readonly
*/
inputPreviousStageTexture: {
get: function() {
return this._inputPreviousStageTexture;
}
},
/**
* The number of post-process stages in this composite.
*
* @memberof PostProcessStageComposite.prototype
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._stages.length;
}
},
/**
* The features selected for applying the post-process.
*
* @memberof PostProcessStageComposite.prototype
* @type {Array}
*/
selected: {
get: function() {
return this._selected;
},
set: function(value) {
this._selected = value;
}
},
/**
* @private
*/
parentSelected: {
get: function() {
return this._parentSelected;
},
set: function(value) {
this._parentSelected = value;
}
}
});
PostProcessStageComposite.prototype._isSupported = function(context) {
const stages = this._stages;
const length2 = stages.length;
for (let i = 0; i < length2; ++i) {
if (!stages[i]._isSupported(context)) {
return false;
}
}
return true;
};
PostProcessStageComposite.prototype.get = function(index) {
Check_default.typeOf.number.greaterThanOrEquals("index", index, 0);
Check_default.typeOf.number.lessThan("index", index, this.length);
return this._stages[index];
};
function isSelectedTextureDirty2(stage) {
let length2 = defined_default(stage._selected) ? stage._selected.length : 0;
const parentLength = defined_default(stage._parentSelected) ? stage._parentSelected : 0;
let dirty = stage._selected !== stage._selectedShadow || length2 !== stage._selectedLength;
dirty = dirty || stage._parentSelected !== stage._parentSelectedShadow || parentLength !== stage._parentSelectedLength;
if (defined_default(stage._selected) && defined_default(stage._parentSelected)) {
stage._combinedSelected = stage._selected.concat(stage._parentSelected);
} else if (defined_default(stage._parentSelected)) {
stage._combinedSelected = stage._parentSelected;
} else {
stage._combinedSelected = stage._selected;
}
if (!dirty && defined_default(stage._combinedSelected)) {
if (!defined_default(stage._combinedSelectedShadow)) {
return true;
}
length2 = stage._combinedSelected.length;
for (let i = 0; i < length2; ++i) {
if (stage._combinedSelected[i] !== stage._combinedSelectedShadow[i]) {
return true;
}
}
}
return dirty;
}
PostProcessStageComposite.prototype.update = function(context, useLogDepth) {
this._selectedDirty = isSelectedTextureDirty2(this);
this._selectedShadow = this._selected;
this._parentSelectedShadow = this._parentSelected;
this._combinedSelectedShadow = this._combinedSelected;
this._selectedLength = defined_default(this._selected) ? this._selected.length : 0;
this._parentSelectedLength = defined_default(this._parentSelected) ? this._parentSelected.length : 0;
const stages = this._stages;
const length2 = stages.length;
for (let i = 0; i < length2; ++i) {
const stage = stages[i];
if (this._selectedDirty) {
stage.parentSelected = this._combinedSelected;
}
stage.update(context, useLogDepth);
}
};
PostProcessStageComposite.prototype.isDestroyed = function() {
return false;
};
PostProcessStageComposite.prototype.destroy = function() {
const stages = this._stages;
const length2 = stages.length;
for (let i = 0; i < length2; ++i) {
stages[i].destroy();
}
return destroyObject_default(this);
};
var PostProcessStageComposite_default = PostProcessStageComposite;
// packages/engine/Source/Scene/PostProcessStageLibrary.js
var PostProcessStageLibrary = {};
function createBlur(name) {
const delta = 1;
const sigma = 2;
const stepSize = 1;
const blurShader = `#define USE_STEP_SIZE
${GaussianBlur1D_default}`;
const blurX = new PostProcessStage_default({
name: `${name}_x_direction`,
fragmentShader: blurShader,
uniforms: {
delta,
sigma,
stepSize,
direction: 0
},
sampleMode: PostProcessStageSampleMode_default.LINEAR
});
const blurY = new PostProcessStage_default({
name: `${name}_y_direction`,
fragmentShader: blurShader,
uniforms: {
delta,
sigma,
stepSize,
direction: 1
},
sampleMode: PostProcessStageSampleMode_default.LINEAR
});
const uniforms = {};
Object.defineProperties(uniforms, {
delta: {
get: function() {
return blurX.uniforms.delta;
},
set: function(value) {
const blurXUniforms = blurX.uniforms;
const blurYUniforms = blurY.uniforms;
blurXUniforms.delta = blurYUniforms.delta = value;
}
},
sigma: {
get: function() {
return blurX.uniforms.sigma;
},
set: function(value) {
const blurXUniforms = blurX.uniforms;
const blurYUniforms = blurY.uniforms;
blurXUniforms.sigma = blurYUniforms.sigma = value;
}
},
stepSize: {
get: function() {
return blurX.uniforms.stepSize;
},
set: function(value) {
const blurXUniforms = blurX.uniforms;
const blurYUniforms = blurY.uniforms;
blurXUniforms.stepSize = blurYUniforms.stepSize = value;
}
}
});
return new PostProcessStageComposite_default({
name,
stages: [blurX, blurY],
uniforms
});
}
PostProcessStageLibrary.createBlurStage = function() {
return createBlur("czm_blur");
};
PostProcessStageLibrary.createDepthOfFieldStage = function() {
const blur = createBlur("czm_depth_of_field_blur");
const dof = new PostProcessStage_default({
name: "czm_depth_of_field_composite",
fragmentShader: DepthOfField_default,
uniforms: {
focalDistance: 5,
blurTexture: blur.name
}
});
const uniforms = {};
Object.defineProperties(uniforms, {
focalDistance: {
get: function() {
return dof.uniforms.focalDistance;
},
set: function(value) {
dof.uniforms.focalDistance = value;
}
},
delta: {
get: function() {
return blur.uniforms.delta;
},
set: function(value) {
blur.uniforms.delta = value;
}
},
sigma: {
get: function() {
return blur.uniforms.sigma;
},
set: function(value) {
blur.uniforms.sigma = value;
}
},
stepSize: {
get: function() {
return blur.uniforms.stepSize;
},
set: function(value) {
blur.uniforms.stepSize = value;
}
}
});
return new PostProcessStageComposite_default({
name: "czm_depth_of_field",
stages: [blur, dof],
inputPreviousStageTexture: false,
uniforms
});
};
PostProcessStageLibrary.isDepthOfFieldSupported = function(scene) {
return scene.context.depthTexture;
};
PostProcessStageLibrary.createEdgeDetectionStage = function() {
const name = createGuid_default();
return new PostProcessStage_default({
name: `czm_edge_detection_${name}`,
fragmentShader: EdgeDetection_default,
uniforms: {
length: 0.25,
color: Color_default.clone(Color_default.BLACK)
}
});
};
PostProcessStageLibrary.isEdgeDetectionSupported = function(scene) {
return scene.context.depthTexture;
};
function getSilhouetteEdgeDetection(edgeDetectionStages) {
if (!defined_default(edgeDetectionStages)) {
return PostProcessStageLibrary.createEdgeDetectionStage();
}
const edgeDetection = new PostProcessStageComposite_default({
name: "czm_edge_detection_multiple",
stages: edgeDetectionStages,
inputPreviousStageTexture: false
});
const compositeUniforms = {};
let fsDecl = "";
let fsLoop = "";
for (let i = 0; i < edgeDetectionStages.length; ++i) {
fsDecl += `uniform sampler2D edgeTexture${i};
`;
fsLoop += ` vec4 edge${i} = texture(edgeTexture${i}, v_textureCoordinates);
if (edge${i}.a > 0.0)
{
color = edge${i};
break;
}
`;
compositeUniforms[`edgeTexture${i}`] = edgeDetectionStages[i].name;
}
const fs = `${fsDecl}in vec2 v_textureCoordinates;
void main() {
vec4 color = vec4(0.0);
for (int i = 0; i < ${edgeDetectionStages.length}; i++)
{
${fsLoop} }
out_FragColor = color;
}
`;
const edgeComposite = new PostProcessStage_default({
name: "czm_edge_detection_combine",
fragmentShader: fs,
uniforms: compositeUniforms
});
return new PostProcessStageComposite_default({
name: "czm_edge_detection_composite",
stages: [edgeDetection, edgeComposite]
});
}
PostProcessStageLibrary.createSilhouetteStage = function(edgeDetectionStages) {
const edgeDetection = getSilhouetteEdgeDetection(edgeDetectionStages);
const silhouetteProcess = new PostProcessStage_default({
name: "czm_silhouette_color_edges",
fragmentShader: Silhouette_default,
uniforms: {
silhouetteTexture: edgeDetection.name
}
});
return new PostProcessStageComposite_default({
name: "czm_silhouette",
stages: [edgeDetection, silhouetteProcess],
inputPreviousStageTexture: false,
uniforms: edgeDetection.uniforms
});
};
PostProcessStageLibrary.isSilhouetteSupported = function(scene) {
return scene.context.depthTexture;
};
PostProcessStageLibrary.createBloomStage = function() {
const contrastBias = new PostProcessStage_default({
name: "czm_bloom_contrast_bias",
fragmentShader: ContrastBias_default,
uniforms: {
contrast: 128,
brightness: -0.3
}
});
const blur = createBlur("czm_bloom_blur");
const generateComposite = new PostProcessStageComposite_default({
name: "czm_bloom_contrast_bias_blur",
stages: [contrastBias, blur]
});
const bloomComposite = new PostProcessStage_default({
name: "czm_bloom_generate_composite",
fragmentShader: BloomComposite_default,
uniforms: {
glowOnly: false,
bloomTexture: generateComposite.name
}
});
const uniforms = {};
Object.defineProperties(uniforms, {
glowOnly: {
get: function() {
return bloomComposite.uniforms.glowOnly;
},
set: function(value) {
bloomComposite.uniforms.glowOnly = value;
}
},
contrast: {
get: function() {
return contrastBias.uniforms.contrast;
},
set: function(value) {
contrastBias.uniforms.contrast = value;
}
},
brightness: {
get: function() {
return contrastBias.uniforms.brightness;
},
set: function(value) {
contrastBias.uniforms.brightness = value;
}
},
delta: {
get: function() {
return blur.uniforms.delta;
},
set: function(value) {
blur.uniforms.delta = value;
}
},
sigma: {
get: function() {
return blur.uniforms.sigma;
},
set: function(value) {
blur.uniforms.sigma = value;
}
},
stepSize: {
get: function() {
return blur.uniforms.stepSize;
},
set: function(value) {
blur.uniforms.stepSize = value;
}
}
});
return new PostProcessStageComposite_default({
name: "czm_bloom",
stages: [generateComposite, bloomComposite],
inputPreviousStageTexture: false,
uniforms
});
};
PostProcessStageLibrary.createAmbientOcclusionStage = function() {
const generate = new PostProcessStage_default({
name: "czm_ambient_occlusion_generate",
fragmentShader: AmbientOcclusionGenerate_default,
uniforms: {
intensity: 3,
bias: 0.1,
lengthCap: 0.26,
directionCount: 8,
stepCount: 32,
randomTexture: void 0
}
});
const ambientOcclusionModulate = new PostProcessStage_default({
name: "czm_ambient_occlusion_composite",
fragmentShader: AmbientOcclusionModulate_default,
uniforms: {
ambientOcclusionOnly: false,
ambientOcclusionTexture: generate.name
}
});
const uniforms = {};
Object.defineProperties(uniforms, {
intensity: {
get: function() {
return generate.uniforms.intensity;
},
set: function(value) {
generate.uniforms.intensity = value;
}
},
bias: {
get: function() {
return generate.uniforms.bias;
},
set: function(value) {
generate.uniforms.bias = value;
}
},
lengthCap: {
get: function() {
return generate.uniforms.lengthCap;
},
set: function(value) {
generate.uniforms.lengthCap = value;
}
},
directionCount: {
get: function() {
return generate.uniforms.directionCount;
},
set: function(value) {
generate.uniforms.directionCount = value;
}
},
stepCount: {
get: function() {
return generate.uniforms.stepCount;
},
set: function(value) {
generate.uniforms.stepCount = value;
}
},
randomTexture: {
get: function() {
return generate.uniforms.randomTexture;
},
set: function(value) {
generate.uniforms.randomTexture = value;
}
},
ambientOcclusionOnly: {
get: function() {
return ambientOcclusionModulate.uniforms.ambientOcclusionOnly;
},
set: function(value) {
ambientOcclusionModulate.uniforms.ambientOcclusionOnly = value;
}
}
});
return new PostProcessStageComposite_default({
name: "czm_ambient_occlusion",
stages: [generate, ambientOcclusionModulate],
inputPreviousStageTexture: false,
uniforms
});
};
PostProcessStageLibrary.isAmbientOcclusionSupported = function(scene) {
return scene.context.depthTexture;
};
var fxaaFS = `#define FXAA_QUALITY_PRESET 39
${FXAA3_11_default}
${FXAA_default}`;
PostProcessStageLibrary.createFXAAStage = function() {
return new PostProcessStage_default({
name: "czm_FXAA",
fragmentShader: fxaaFS,
sampleMode: PostProcessStageSampleMode_default.LINEAR
});
};
PostProcessStageLibrary.createAcesTonemappingStage = function(useAutoExposure) {
let fs = useAutoExposure ? "#define AUTO_EXPOSURE\n" : "";
fs += AcesTonemappingStage_default;
return new PostProcessStage_default({
name: "czm_aces",
fragmentShader: fs,
uniforms: {
autoExposure: void 0,
exposure: 1
}
});
};
PostProcessStageLibrary.createFilmicTonemappingStage = function(useAutoExposure) {
let fs = useAutoExposure ? "#define AUTO_EXPOSURE\n" : "";
fs += FilmicTonemapping_default;
return new PostProcessStage_default({
name: "czm_filmic",
fragmentShader: fs,
uniforms: {
autoExposure: void 0,
exposure: 1
}
});
};
PostProcessStageLibrary.createPbrNeutralTonemappingStage = function(useAutoExposure) {
let fs = useAutoExposure ? "#define AUTO_EXPOSURE\n" : "";
fs += PbrNeutralTonemapping_default;
return new PostProcessStage_default({
name: "czm_pbr_neutral",
fragmentShader: fs,
uniforms: {
autoExposure: void 0,
exposure: 1
}
});
};
PostProcessStageLibrary.createReinhardTonemappingStage = function(useAutoExposure) {
let fs = useAutoExposure ? "#define AUTO_EXPOSURE\n" : "";
fs += ReinhardTonemapping_default;
return new PostProcessStage_default({
name: "czm_reinhard",
fragmentShader: fs,
uniforms: {
autoExposure: void 0,
exposure: 1
}
});
};
PostProcessStageLibrary.createModifiedReinhardTonemappingStage = function(useAutoExposure) {
let fs = useAutoExposure ? "#define AUTO_EXPOSURE\n" : "";
fs += ModifiedReinhardTonemapping_default;
return new PostProcessStage_default({
name: "czm_modified_reinhard",
fragmentShader: fs,
uniforms: {
white: Color_default.WHITE,
autoExposure: void 0,
exposure: 1
}
});
};
PostProcessStageLibrary.createAutoExposureStage = function() {
return new AutoExposure_default();
};
PostProcessStageLibrary.createBlackAndWhiteStage = function() {
return new PostProcessStage_default({
name: "czm_black_and_white",
fragmentShader: BlackAndWhite_default,
uniforms: {
gradations: 5
}
});
};
PostProcessStageLibrary.createBrightnessStage = function() {
return new PostProcessStage_default({
name: "czm_brightness",
fragmentShader: Brightness_default,
uniforms: {
brightness: 0.5
}
});
};
PostProcessStageLibrary.createNightVisionStage = function() {
return new PostProcessStage_default({
name: "czm_night_vision",
fragmentShader: NightVision_default
});
};
PostProcessStageLibrary.createDepthViewStage = function() {
return new PostProcessStage_default({
name: "czm_depth_view",
fragmentShader: DepthView_default
});
};
PostProcessStageLibrary.createLensFlareStage = function() {
return new PostProcessStage_default({
name: "czm_lens_flare",
fragmentShader: LensFlare_default,
uniforms: {
dirtTexture: buildModuleUrl_default("Assets/Textures/LensFlare/DirtMask.jpg"),
starTexture: buildModuleUrl_default("Assets/Textures/LensFlare/StarBurst.jpg"),
intensity: 2,
distortion: 10,
ghostDispersal: 0.4,
haloWidth: 0.4,
dirtAmount: 0.4,
earthRadius: Ellipsoid_default.WGS84.maximumRadius
}
});
};
var PostProcessStageLibrary_default = PostProcessStageLibrary;
// packages/engine/Source/Scene/PostProcessStageTextureCache.js
var import_InlineWorkers1108 = __toESM(require_InlineWorkers(), 1);
function PostProcessStageTextureCache(postProcessStageCollection) {
this._collection = postProcessStageCollection;
this._framebuffers = [];
this._stageNameToFramebuffer = {};
this._width = void 0;
this._height = void 0;
this._updateDependencies = false;
}
function getLastStageName(stage) {
while (defined_default(stage.length)) {
stage = stage.get(stage.length - 1);
}
return stage.name;
}
function getStageDependencies(collection, context, dependencies, stage, previousName) {
if (!stage.enabled || !stage._isSupported(context)) {
return previousName;
}
const stageDependencies = dependencies[stage.name] = {};
if (defined_default(previousName)) {
const previous = collection.getStageByName(previousName);
stageDependencies[getLastStageName(previous)] = true;
}
const uniforms = stage.uniforms;
if (defined_default(uniforms)) {
const uniformNames = Object.getOwnPropertyNames(uniforms);
const uniformNamesLength = uniformNames.length;
for (let i = 0; i < uniformNamesLength; ++i) {
const value = uniforms[uniformNames[i]];
if (typeof value === "string") {
const dependent = collection.getStageByName(value);
if (defined_default(dependent)) {
stageDependencies[getLastStageName(dependent)] = true;
}
}
}
}
return stage.name;
}
function getCompositeDependencies(collection, context, dependencies, composite, previousName) {
if (defined_default(composite.enabled) && !composite.enabled || defined_default(composite._isSupported) && !composite._isSupported(context)) {
return previousName;
}
const originalDependency = previousName;
const inSeries = !defined_default(composite.inputPreviousStageTexture) || composite.inputPreviousStageTexture;
let currentName = previousName;
const length2 = composite.length;
for (let i = 0; i < length2; ++i) {
const stage = composite.get(i);
if (defined_default(stage.length)) {
currentName = getCompositeDependencies(
collection,
context,
dependencies,
stage,
previousName
);
} else {
currentName = getStageDependencies(
collection,
context,
dependencies,
stage,
previousName
);
}
if (inSeries) {
previousName = currentName;
}
}
let j;
let name;
if (!inSeries) {
for (j = 1; j < length2; ++j) {
name = getLastStageName(composite.get(j));
const currentDependencies = dependencies[name];
for (let k = 0; k < j; ++k) {
currentDependencies[getLastStageName(composite.get(k))] = true;
}
}
} else {
for (j = 1; j < length2; ++j) {
name = getLastStageName(composite.get(j));
if (!defined_default(dependencies[name])) {
dependencies[name] = {};
}
dependencies[name][originalDependency] = true;
}
}
return currentName;
}
function getDependencies(collection, context) {
const dependencies = {};
if (defined_default(collection.ambientOcclusion)) {
const ao = collection.ambientOcclusion;
const bloom = collection.bloom;
const tonemapping = collection._tonemapping;
const fxaa = collection.fxaa;
let previousName = getCompositeDependencies(
collection,
context,
dependencies,
ao,
void 0
);
previousName = getCompositeDependencies(
collection,
context,
dependencies,
bloom,
previousName
);
previousName = getStageDependencies(
collection,
context,
dependencies,
tonemapping,
previousName
);
previousName = getCompositeDependencies(
collection,
context,
dependencies,
collection,
previousName
);
getStageDependencies(collection, context, dependencies, fxaa, previousName);
} else {
getCompositeDependencies(
collection,
context,
dependencies,
collection,
void 0
);
}
return dependencies;
}
function getFramebuffer(cache, stageName, dependencies) {
const collection = cache._collection;
const stage = collection.getStageByName(stageName);
const textureScale = stage._textureScale;
const forcePowerOfTwo = stage._forcePowerOfTwo;
const pixelFormat = stage._pixelFormat;
const pixelDatatype = stage._pixelDatatype;
const clearColor = stage._clearColor;
let i;
let framebuffer;
const framebuffers = cache._framebuffers;
const length2 = framebuffers.length;
for (i = 0; i < length2; ++i) {
framebuffer = framebuffers[i];
if (textureScale !== framebuffer.textureScale || forcePowerOfTwo !== framebuffer.forcePowerOfTwo || pixelFormat !== framebuffer.pixelFormat || pixelDatatype !== framebuffer.pixelDatatype || !Color_default.equals(clearColor, framebuffer.clearColor)) {
continue;
}
const stageNames = framebuffer.stages;
const stagesLength = stageNames.length;
let foundConflict = false;
for (let j = 0; j < stagesLength; ++j) {
if (dependencies[stageNames[j]]) {
foundConflict = true;
break;
}
}
if (!foundConflict) {
break;
}
}
if (defined_default(framebuffer) && i < length2) {
framebuffer.stages.push(stageName);
return framebuffer;
}
framebuffer = {
textureScale,
forcePowerOfTwo,
pixelFormat,
pixelDatatype,
clearColor,
stages: [stageName],
buffer: new FramebufferManager_default({
pixelFormat,
pixelDatatype
}),
clear: void 0
};
framebuffers.push(framebuffer);
return framebuffer;
}
function createFramebuffers2(cache, context) {
const dependencies = getDependencies(cache._collection, context);
for (const stageName in dependencies) {
if (dependencies.hasOwnProperty(stageName)) {
cache._stageNameToFramebuffer[stageName] = getFramebuffer(
cache,
stageName,
dependencies[stageName]
);
}
}
}
function releaseResources2(cache) {
const framebuffers = cache._framebuffers;
const length2 = framebuffers.length;
for (let i = 0; i < length2; ++i) {
const framebuffer = framebuffers[i];
framebuffer.buffer.destroy();
}
}
function updateFramebuffers4(cache, context) {
const width = cache._width;
const height = cache._height;
const framebuffers = cache._framebuffers;
const length2 = framebuffers.length;
for (let i = 0; i < length2; ++i) {
const framebuffer = framebuffers[i];
const scale = framebuffer.textureScale;
let textureWidth = Math.ceil(width * scale);
let textureHeight = Math.ceil(height * scale);
let size = Math.min(textureWidth, textureHeight);
if (framebuffer.forcePowerOfTwo) {
if (!Math_default.isPowerOfTwo(size)) {
size = Math_default.nextPowerOfTwo(size);
}
textureWidth = size;
textureHeight = size;
}
framebuffer.buffer.update(context, textureWidth, textureHeight);
framebuffer.clear = new ClearCommand_default({
color: framebuffer.clearColor,
framebuffer: framebuffer.buffer.framebuffer
});
}
}
PostProcessStageTextureCache.prototype.updateDependencies = function() {
this._updateDependencies = true;
};
PostProcessStageTextureCache.prototype.update = function(context) {
const collection = this._collection;
const updateDependencies = this._updateDependencies;
const aoEnabled = defined_default(collection.ambientOcclusion) && collection.ambientOcclusion.enabled && collection.ambientOcclusion._isSupported(context);
const bloomEnabled = defined_default(collection.bloom) && collection.bloom.enabled && collection.bloom._isSupported(context);
const tonemappingEnabled = defined_default(collection._tonemapping) && collection._tonemapping.enabled && collection._tonemapping._isSupported(context);
const fxaaEnabled = defined_default(collection.fxaa) && collection.fxaa.enabled && collection.fxaa._isSupported(context);
const needsCheckDimensionsUpdate = !defined_default(collection._activeStages) || collection._activeStages.length > 0 || aoEnabled || bloomEnabled || tonemappingEnabled || fxaaEnabled;
if (updateDependencies || !needsCheckDimensionsUpdate && this._framebuffers.length > 0) {
releaseResources2(this);
this._framebuffers.length = 0;
this._stageNameToFramebuffer = {};
this._width = void 0;
this._height = void 0;
}
if (!updateDependencies && !needsCheckDimensionsUpdate) {
return;
}
if (this._framebuffers.length === 0) {
createFramebuffers2(this, context);
}
const width = context.drawingBufferWidth;
const height = context.drawingBufferHeight;
const dimensionsChanged = this._width !== width || this._height !== height;
if (!updateDependencies && !dimensionsChanged) {
return;
}
this._width = width;
this._height = height;
this._updateDependencies = false;
releaseResources2(this);
updateFramebuffers4(this, context);
};
PostProcessStageTextureCache.prototype.clear = function(context) {
const framebuffers = this._framebuffers;
for (let i = 0; i < framebuffers.length; ++i) {
framebuffers[i].clear.execute(context);
}
};
PostProcessStageTextureCache.prototype.getStageByName = function(name) {
return this._collection.getStageByName(name);
};
PostProcessStageTextureCache.prototype.getOutputTexture = function(name) {
return this._collection.getOutputTexture(name);
};
PostProcessStageTextureCache.prototype.getFramebuffer = function(name) {
const framebuffer = this._stageNameToFramebuffer[name];
if (!defined_default(framebuffer)) {
return void 0;
}
return framebuffer.buffer.framebuffer;
};
PostProcessStageTextureCache.prototype.isDestroyed = function() {
return false;
};
PostProcessStageTextureCache.prototype.destroy = function() {
releaseResources2(this);
return destroyObject_default(this);
};
var PostProcessStageTextureCache_default = PostProcessStageTextureCache;
// packages/engine/Source/Scene/Tonemapper.js
var import_InlineWorkers1109 = __toESM(require_InlineWorkers(), 1);
var Tonemapper = {
/**
* Use the Reinhard tonemapping.
*
* @type {string}
* @constant
*/
REINHARD: "REINHARD",
/**
* Use the modified Reinhard tonemapping.
*
* @type {string}
* @constant
*/
MODIFIED_REINHARD: "MODIFIED_REINHARD",
/**
* Use the Filmic tonemapping.
*
* @type {string}
* @constant
*/
FILMIC: "FILMIC",
/**
* Use the ACES tonemapping.
*
* @type {string}
* @constant
*/
ACES: "ACES",
/**
* Use the PBR Neutral tonemapping {@link https://github.com/KhronosGroup/ToneMapping/tree/main/PBR_Neutral|from Khronos}.
*
* @type {string}
* @constant
*/
PBR_NEUTRAL: "PBR_NEUTRAL"
};
function validateTonemapper(tonemapper) {
return tonemapper === Tonemapper.REINHARD || tonemapper === Tonemapper.MODIFIED_REINHARD || tonemapper === Tonemapper.FILMIC || tonemapper === Tonemapper.ACES || tonemapper === Tonemapper.PBR_NEUTRAL;
}
var Tonemapper_default = Object.freeze(Tonemapper);
// packages/engine/Source/Scene/PostProcessStageCollection.js
var stackScratch = [];
function PostProcessStageCollection() {
const fxaa = PostProcessStageLibrary_default.createFXAAStage();
const ao = PostProcessStageLibrary_default.createAmbientOcclusionStage();
const bloom = PostProcessStageLibrary_default.createBloomStage();
this._autoExposureEnabled = false;
this._autoExposure = PostProcessStageLibrary_default.createAutoExposureStage();
this._exposure = 1;
this._tonemapping = void 0;
this._tonemapper = void 0;
this.tonemapper = Tonemapper_default.PBR_NEUTRAL;
const tonemapping = this._tonemapping;
fxaa.enabled = false;
ao.enabled = false;
bloom.enabled = false;
tonemapping.enabled = false;
const textureCache = new PostProcessStageTextureCache_default(this);
const stageNames = {};
const stack = stackScratch;
stack.push(fxaa, ao, bloom, tonemapping);
while (stack.length > 0) {
const stage = stack.pop();
stageNames[stage.name] = stage;
stage._textureCache = textureCache;
const length2 = stage.length;
if (defined_default(length2)) {
for (let i = 0; i < length2; ++i) {
stack.push(stage.get(i));
}
}
}
this._stages = [];
this._activeStages = [];
this._previousActiveStages = [];
this._randomTexture = void 0;
const that = this;
ao.uniforms.randomTexture = function() {
return that._randomTexture;
};
this._ao = ao;
this._bloom = bloom;
this._fxaa = fxaa;
this._aoEnabled = void 0;
this._bloomEnabled = void 0;
this._tonemappingEnabled = void 0;
this._fxaaEnabled = void 0;
this._activeStagesChanged = false;
this._stagesRemoved = false;
this._textureCacheDirty = false;
this._stageNames = stageNames;
this._textureCache = textureCache;
}
Object.defineProperties(PostProcessStageCollection.prototype, {
/**
* Determines if all of the post-process stages in the collection are ready to be executed.
*
* @memberof PostProcessStageCollection.prototype
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
let readyAndEnabled = false;
const stages = this._stages;
const length2 = stages.length;
for (let i = length2 - 1; i >= 0; --i) {
const stage = stages[i];
readyAndEnabled = readyAndEnabled || stage.ready && stage.enabled;
}
const fxaa = this._fxaa;
const ao = this._ao;
const bloom = this._bloom;
const tonemapping = this._tonemapping;
readyAndEnabled = readyAndEnabled || fxaa.ready && fxaa.enabled;
readyAndEnabled = readyAndEnabled || ao.ready && ao.enabled;
readyAndEnabled = readyAndEnabled || bloom.ready && bloom.enabled;
readyAndEnabled = readyAndEnabled || tonemapping.ready && tonemapping.enabled;
return readyAndEnabled;
}
},
/**
* A post-process stage for Fast Approximate Anti-aliasing.
*
* When enabled, this stage will execute after all others.
*
*
* @memberof PostProcessStageCollection.prototype
* @type {PostProcessStage}
* @readonly
*/
fxaa: {
get: function() {
return this._fxaa;
}
},
/**
* A post-process stage that applies Horizon-based Ambient Occlusion (HBAO) to the input texture.
*
* Ambient occlusion simulates shadows from ambient light. These shadows would always be present when the
* surface receives light and regardless of the light's position.
*
*
* The uniforms have the following properties:
*
* intensity is a scalar value used to lighten or darken the shadows exponentially. Higher values make the shadows darker. The default value is 3.0.
* bias is a scalar value representing an angle in radians. If the dot product between the normal of the sample and the vector to the camera is less than this value,
* sampling stops in the current direction. This is used to remove shadows from near planar edges. The default value is 0.1.
* lengthCap is a scalar value representing a length in meters. If the distance from the current sample to first sample is greater than this value,
* sampling stops in the current direction. The default value is 0.26.
* directionCount is the number of directions along which the ray marching will search for occluders. The default value is 8.
* stepCount is the number of steps the ray marching will take along each direction. The default value is 32.
* randomTexture is a texture where the red channel is a random value in [0.0, 1.0]. The default value is undefined. This texture needs to be set.
* ambientOcclusionOnly is a boolean value. When true, only the shadows generated are written to the output. When false, the input texture is modulated
* with the ambient occlusion. This is a useful debug option for seeing the effects of changing the uniform values. The default value is false.
*
*
* When enabled, this stage will execute before all others.
*
*
* @memberof PostProcessStageCollection.prototype
* @type {PostProcessStageComposite}
* @readonly
*/
ambientOcclusion: {
get: function() {
return this._ao;
}
},
/**
* A post-process stage for a bloom effect.
*
* A bloom effect adds glow effect, makes bright areas brighter, and dark areas darker.
*
*
* This stage has the following uniforms: contrast, brightness, glowOnly,
* delta, sigma, and stepSize.
*
*
* contrast is a scalar value in the range [-255.0, 255.0] and affects the contract of the effect. The default value is 128.0.
*
* brightness is a scalar value. The input texture RGB value is converted to hue, saturation, and brightness (HSB) then this value is
* added to the brightness. The default value is -0.3.
*
* glowOnly is a boolean value. When true, only the glow effect will be shown. When false, the glow will be added to the input texture.
* The default value is false. This is a debug option for viewing the effects when changing the other uniform values.
*
*
* delta, sigma, and stepSize are the same properties as {@link PostProcessStageLibrary#createBlurStage}.
* The blur is applied to the shadows generated from the image to make them smoother.
*
*
* When enabled, this stage will execute before all others.
*
*
* @memberOf PostProcessStageCollection.prototype
* @type {PostProcessStageComposite}
* @readonly
*/
bloom: {
get: function() {
return this._bloom;
}
},
/**
* The number of post-process stages in this collection.
*
* @memberof PostProcessStageCollection.prototype
* @type {number}
* @readonly
*/
length: {
get: function() {
removeStages(this);
return this._stages.length;
}
},
/**
* A reference to the last texture written to when executing the post-process stages in this collection.
*
* @memberof PostProcessStageCollection.prototype
* @type {Texture}
* @readonly
* @private
*/
outputTexture: {
get: function() {
const fxaa = this._fxaa;
if (fxaa.enabled && fxaa.ready) {
return this.getOutputTexture(fxaa.name);
}
const stages = this._stages;
const length2 = stages.length;
for (let i = length2 - 1; i >= 0; --i) {
const stage = stages[i];
if (defined_default(stage) && stage.ready && stage.enabled) {
return this.getOutputTexture(stage.name);
}
}
const tonemapping = this._tonemapping;
if (tonemapping.enabled && tonemapping.ready) {
return this.getOutputTexture(tonemapping.name);
}
const bloom = this._bloom;
if (bloom.enabled && bloom.ready) {
return this.getOutputTexture(bloom.name);
}
const ao = this._ao;
if (ao.enabled && ao.ready) {
return this.getOutputTexture(ao.name);
}
return void 0;
}
},
/**
* Whether the collection has a stage that has selected features.
*
* @memberof PostProcessStageCollection.prototype
* @type {boolean}
* @readonly
* @private
*/
hasSelected: {
get: function() {
const stages = this._stages.slice();
while (stages.length > 0) {
const stage = stages.pop();
if (!defined_default(stage)) {
continue;
}
if (defined_default(stage.selected)) {
return true;
}
const length2 = stage.length;
if (defined_default(length2)) {
for (let i = 0; i < length2; ++i) {
stages.push(stage.get(i));
}
}
}
return false;
}
},
/**
* Specifies the tonemapping algorithm used when rendering with high dynamic range.
* {@link https://sandcastle.cesium.com/?src=High%20Dynamic%20Range.html|Sandcastle Demo}
*
* @example viewer.scene.postProcessStages.tonemapper = Cesium.Tonemapper.ACES;
*
* @default Tonemapper.PBR_NEUTRAL
* @memberof PostProcessStageCollection.prototype
* @type {Tonemapper}
*/
tonemapper: {
get: function() {
return this._tonemapper;
},
set: function(value) {
if (this._tonemapper === value) {
return;
}
if (!validateTonemapper(value)) {
throw new DeveloperError_default("tonemapper was set to an invalid value.");
}
if (defined_default(this._tonemapping)) {
delete this._stageNames[this._tonemapping.name];
this._tonemapping.destroy();
}
const useAutoExposure = this._autoExposureEnabled;
let tonemapping;
switch (value) {
case Tonemapper_default.REINHARD:
tonemapping = PostProcessStageLibrary_default.createReinhardTonemappingStage(
useAutoExposure
);
break;
case Tonemapper_default.MODIFIED_REINHARD:
tonemapping = PostProcessStageLibrary_default.createModifiedReinhardTonemappingStage(
useAutoExposure
);
break;
case Tonemapper_default.FILMIC:
tonemapping = PostProcessStageLibrary_default.createFilmicTonemappingStage(
useAutoExposure
);
break;
case Tonemapper_default.PBR_NEUTRAL:
tonemapping = PostProcessStageLibrary_default.createPbrNeutralTonemappingStage(
useAutoExposure
);
break;
default:
tonemapping = PostProcessStageLibrary_default.createAcesTonemappingStage(useAutoExposure);
break;
}
if (useAutoExposure) {
const autoexposure = this._autoExposure;
tonemapping.uniforms.autoExposure = function() {
return autoexposure.outputTexture;
};
} else {
tonemapping.uniforms.exposure = this._exposure;
}
this._tonemapper = value;
this._tonemapping = tonemapping;
if (defined_default(this._stageNames)) {
this._stageNames[tonemapping.name] = tonemapping;
tonemapping._textureCache = this._textureCache;
}
this._textureCacheDirty = true;
}
},
/**
* Control the exposure when HDR is on. Less than 1.0 makes the tonemapping darker while greater than 1.0 makes it brighter.
*
* @example viewer.scene.postProcessStages.exposure = 1.0;
*
* @default 1.0
* @memberof PostProcessStageCollection.prototype
* @type {number}
*/
exposure: {
get: function() {
return this._exposure;
},
set: function(value) {
this._tonemapping.uniforms.exposure = value;
this._exposure = value;
}
}
});
function removeStages(collection) {
if (!collection._stagesRemoved) {
return;
}
collection._stagesRemoved = false;
const newStages = [];
const stages = collection._stages;
for (let i = 0, j = 0; i < stages.length; ++i) {
const stage = stages[i];
if (stage) {
stage._index = j++;
newStages.push(stage);
}
}
collection._stages = newStages;
}
PostProcessStageCollection.prototype.add = function(stage) {
Check_default.typeOf.object("stage", stage);
const stageNames = this._stageNames;
const stack = stackScratch;
stack.push(stage);
while (stack.length > 0) {
const currentStage = stack.pop();
if (defined_default(stageNames[currentStage.name])) {
throw new DeveloperError_default(
`${currentStage.name} has already been added to the collection or does not have a unique name.`
);
}
stageNames[currentStage.name] = currentStage;
currentStage._textureCache = this._textureCache;
const length2 = currentStage.length;
if (defined_default(length2)) {
for (let i = 0; i < length2; ++i) {
stack.push(currentStage.get(i));
}
}
}
const stages = this._stages;
stage._index = stages.length;
stages.push(stage);
this._textureCacheDirty = true;
return stage;
};
PostProcessStageCollection.prototype.remove = function(stage) {
if (!this.contains(stage)) {
return false;
}
const stageNames = this._stageNames;
const stack = stackScratch;
stack.push(stage);
while (stack.length > 0) {
const currentStage = stack.pop();
delete stageNames[currentStage.name];
const length2 = currentStage.length;
if (defined_default(length2)) {
for (let i = 0; i < length2; ++i) {
stack.push(currentStage.get(i));
}
}
}
this._stages[stage._index] = void 0;
this._stagesRemoved = true;
this._textureCacheDirty = true;
stage._index = void 0;
stage._textureCache = void 0;
stage.destroy();
return true;
};
PostProcessStageCollection.prototype.contains = function(stage) {
return defined_default(stage) && defined_default(stage._index) && stage._textureCache === this._textureCache;
};
PostProcessStageCollection.prototype.get = function(index) {
removeStages(this);
const stages = this._stages;
const length2 = stages.length;
Check_default.typeOf.number.greaterThanOrEquals("stages length", length2, 0);
Check_default.typeOf.number.greaterThanOrEquals("index", index, 0);
Check_default.typeOf.number.lessThan("index", index, length2);
return stages[index];
};
PostProcessStageCollection.prototype.removeAll = function() {
const stages = this._stages;
const length2 = stages.length;
for (let i = 0; i < length2; ++i) {
this.remove(stages[i]);
}
stages.length = 0;
};
PostProcessStageCollection.prototype.getStageByName = function(name) {
return this._stageNames[name];
};
PostProcessStageCollection.prototype.update = function(context, useLogDepth, useHdr) {
removeStages(this);
const previousActiveStages = this._activeStages;
const activeStages = this._activeStages = this._previousActiveStages;
this._previousActiveStages = previousActiveStages;
const stages = this._stages;
activeStages.length = stages.length;
let count = 0;
for (let i = 0; i < stages.length; ++i) {
const stage = stages[i];
if (stage.ready && stage.enabled && stage._isSupported(context)) {
activeStages[count++] = stage;
}
}
activeStages.length = count;
let activeStagesChanged = count !== previousActiveStages.length;
if (!activeStagesChanged) {
for (let i = 0; i < count; ++i) {
if (activeStages[i] !== previousActiveStages[i]) {
activeStagesChanged = true;
break;
}
}
}
const ao = this._ao;
const bloom = this._bloom;
const autoexposure = this._autoExposure;
const tonemapping = this._tonemapping;
const fxaa = this._fxaa;
tonemapping.enabled = useHdr;
const aoEnabled = ao.enabled && ao._isSupported(context);
const bloomEnabled = bloom.enabled && bloom._isSupported(context);
const tonemappingEnabled = tonemapping.enabled && tonemapping._isSupported(context);
const fxaaEnabled = fxaa.enabled && fxaa._isSupported(context);
if (activeStagesChanged || this._textureCacheDirty || aoEnabled !== this._aoEnabled || bloomEnabled !== this._bloomEnabled || tonemappingEnabled !== this._tonemappingEnabled || fxaaEnabled !== this._fxaaEnabled) {
this._textureCache.updateDependencies();
this._aoEnabled = aoEnabled;
this._bloomEnabled = bloomEnabled;
this._tonemappingEnabled = tonemappingEnabled;
this._fxaaEnabled = fxaaEnabled;
this._textureCacheDirty = false;
}
if (defined_default(this._randomTexture) && !aoEnabled) {
this._randomTexture.destroy();
this._randomTexture = void 0;
}
if (!defined_default(this._randomTexture) && aoEnabled) {
const length2 = 256 * 256 * 3;
const random2 = new Uint8Array(length2);
for (let i = 0; i < length2; i += 3) {
random2[i] = Math.floor(Math.random() * 255);
}
this._randomTexture = new Texture_default({
context,
pixelFormat: PixelFormat_default.RGB,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
source: {
arrayBufferView: random2,
width: 256,
height: 256
},
sampler: new Sampler_default({
wrapS: TextureWrap_default.REPEAT,
wrapT: TextureWrap_default.REPEAT,
minificationFilter: TextureMinificationFilter_default.NEAREST,
magnificationFilter: TextureMagnificationFilter_default.NEAREST
})
});
}
this._textureCache.update(context);
fxaa.update(context, useLogDepth);
ao.update(context, useLogDepth);
bloom.update(context, useLogDepth);
tonemapping.update(context, useLogDepth);
if (this._autoExposureEnabled) {
autoexposure.update(context, useLogDepth);
}
for (let i = 0; i < stages.length; ++i) {
stages[i].update(context, useLogDepth);
}
count = 0;
for (let i = 0; i < stages.length; ++i) {
const stage = stages[i];
if (stage.ready && stage.enabled && stage._isSupported(context)) {
count++;
}
}
activeStagesChanged = count !== activeStages.length;
if (activeStagesChanged) {
this.update(context, useLogDepth, useHdr);
}
};
PostProcessStageCollection.prototype.clear = function(context) {
this._textureCache.clear(context);
if (this._autoExposureEnabled) {
this._autoExposure.clear(context);
}
};
function getOutputTexture(stage) {
while (defined_default(stage.length)) {
stage = stage.get(stage.length - 1);
}
return stage.outputTexture;
}
PostProcessStageCollection.prototype.getOutputTexture = function(stageName) {
const stage = this.getStageByName(stageName);
if (!defined_default(stage)) {
return void 0;
}
return getOutputTexture(stage);
};
function execute(stage, context, colorTexture, depthTexture, idTexture) {
if (defined_default(stage.execute)) {
stage.execute(context, colorTexture, depthTexture, idTexture);
return;
}
if (stage.inputPreviousStageTexture) {
execute(stage.get(0), context, colorTexture, depthTexture, idTexture);
for (let i = 1; i < stage.length; ++i) {
execute(
stage.get(i),
context,
getOutputTexture(stage.get(i - 1)),
depthTexture,
idTexture
);
}
} else {
for (let i = 0; i < stage.length; ++i) {
execute(stage.get(i), context, colorTexture, depthTexture, idTexture);
}
}
}
PostProcessStageCollection.prototype.execute = function(context, colorTexture, depthTexture, idTexture) {
const activeStages = this._activeStages;
const length2 = activeStages.length;
const fxaa = this._fxaa;
const ao = this._ao;
const bloom = this._bloom;
const autoexposure = this._autoExposure;
const tonemapping = this._tonemapping;
const aoEnabled = ao.enabled && ao._isSupported(context);
const bloomEnabled = bloom.enabled && bloom._isSupported(context);
const autoExposureEnabled = this._autoExposureEnabled;
const tonemappingEnabled = tonemapping.enabled && tonemapping._isSupported(context);
const fxaaEnabled = fxaa.enabled && fxaa._isSupported(context);
if (!fxaaEnabled && !aoEnabled && !bloomEnabled && !tonemappingEnabled && length2 === 0) {
return;
}
let initialTexture = colorTexture;
if (aoEnabled && ao.ready) {
execute(ao, context, initialTexture, depthTexture, idTexture);
initialTexture = getOutputTexture(ao);
}
if (bloomEnabled && bloom.ready) {
execute(bloom, context, initialTexture, depthTexture, idTexture);
initialTexture = getOutputTexture(bloom);
}
if (autoExposureEnabled && autoexposure.ready) {
execute(autoexposure, context, initialTexture, depthTexture, idTexture);
}
if (tonemappingEnabled && tonemapping.ready) {
execute(tonemapping, context, initialTexture, depthTexture, idTexture);
initialTexture = getOutputTexture(tonemapping);
}
let lastTexture = initialTexture;
if (length2 > 0) {
execute(activeStages[0], context, initialTexture, depthTexture, idTexture);
for (let i = 1; i < length2; ++i) {
execute(
activeStages[i],
context,
getOutputTexture(activeStages[i - 1]),
depthTexture,
idTexture
);
}
lastTexture = getOutputTexture(activeStages[length2 - 1]);
}
if (fxaaEnabled && fxaa.ready) {
execute(fxaa, context, lastTexture, depthTexture, idTexture);
}
};
PostProcessStageCollection.prototype.copy = function(context, framebuffer) {
if (!defined_default(this._copyColorCommand)) {
const that = this;
this._copyColorCommand = context.createViewportQuadCommand(PassThrough_default, {
uniformMap: {
colorTexture: function() {
return that.outputTexture;
}
},
owner: this
});
}
this._copyColorCommand.framebuffer = framebuffer;
this._copyColorCommand.execute(context);
};
PostProcessStageCollection.prototype.isDestroyed = function() {
return false;
};
PostProcessStageCollection.prototype.destroy = function() {
this._fxaa.destroy();
this._ao.destroy();
this._bloom.destroy();
this._autoExposure.destroy();
this._tonemapping.destroy();
this.removeAll();
this._textureCache = this._textureCache && this._textureCache.destroy();
return destroyObject_default(this);
};
var PostProcessStageCollection_default = PostProcessStageCollection;
// packages/engine/Source/Scene/SceneTransitioner.js
var import_InlineWorkers1114 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/ScreenSpaceEventHandler.js
var import_InlineWorkers1113 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/KeyboardEventModifier.js
var import_InlineWorkers1111 = __toESM(require_InlineWorkers(), 1);
var KeyboardEventModifier = {
/**
* Represents the shift key being held down.
*
* @type {number}
* @constant
*/
SHIFT: 0,
/**
* Represents the control key being held down.
*
* @type {number}
* @constant
*/
CTRL: 1,
/**
* Represents the alt key being held down.
*
* @type {number}
* @constant
*/
ALT: 2
};
var KeyboardEventModifier_default = Object.freeze(KeyboardEventModifier);
// packages/engine/Source/Core/ScreenSpaceEventType.js
var import_InlineWorkers1112 = __toESM(require_InlineWorkers(), 1);
var ScreenSpaceEventType = {
/**
* Represents a mouse left button down event.
*
* @type {number}
* @constant
*/
LEFT_DOWN: 0,
/**
* Represents a mouse left button up event.
*
* @type {number}
* @constant
*/
LEFT_UP: 1,
/**
* Represents a mouse left click event.
*
* @type {number}
* @constant
*/
LEFT_CLICK: 2,
/**
* Represents a mouse left double click event.
*
* @type {number}
* @constant
*/
LEFT_DOUBLE_CLICK: 3,
/**
* Represents a mouse left button down event.
*
* @type {number}
* @constant
*/
RIGHT_DOWN: 5,
/**
* Represents a mouse right button up event.
*
* @type {number}
* @constant
*/
RIGHT_UP: 6,
/**
* Represents a mouse right click event.
*
* @type {number}
* @constant
*/
RIGHT_CLICK: 7,
/**
* Represents a mouse middle button down event.
*
* @type {number}
* @constant
*/
MIDDLE_DOWN: 10,
/**
* Represents a mouse middle button up event.
*
* @type {number}
* @constant
*/
MIDDLE_UP: 11,
/**
* Represents a mouse middle click event.
*
* @type {number}
* @constant
*/
MIDDLE_CLICK: 12,
/**
* Represents a mouse move event.
*
* @type {number}
* @constant
*/
MOUSE_MOVE: 15,
/**
* Represents a mouse wheel event.
*
* @type {number}
* @constant
*/
WHEEL: 16,
/**
* Represents the start of a two-finger event on a touch surface.
*
* @type {number}
* @constant
*/
PINCH_START: 17,
/**
* Represents the end of a two-finger event on a touch surface.
*
* @type {number}
* @constant
*/
PINCH_END: 18,
/**
* Represents a change of a two-finger event on a touch surface.
*
* @type {number}
* @constant
*/
PINCH_MOVE: 19
};
var ScreenSpaceEventType_default = Object.freeze(ScreenSpaceEventType);
// packages/engine/Source/Core/ScreenSpaceEventHandler.js
function getPosition3(screenSpaceEventHandler, event, result) {
const element = screenSpaceEventHandler._element;
if (element === document) {
result.x = event.clientX;
result.y = event.clientY;
return result;
}
const rect = element.getBoundingClientRect();
result.x = event.clientX - rect.left;
result.y = event.clientY - rect.top;
return result;
}
function getInputEventKey(type, modifier) {
let key = type;
if (defined_default(modifier)) {
key += `+${modifier}`;
}
return key;
}
function getModifier(event) {
if (event.shiftKey) {
return KeyboardEventModifier_default.SHIFT;
} else if (event.ctrlKey) {
return KeyboardEventModifier_default.CTRL;
} else if (event.altKey) {
return KeyboardEventModifier_default.ALT;
}
return void 0;
}
var MouseButton = {
LEFT: 0,
MIDDLE: 1,
RIGHT: 2
};
function registerListener(screenSpaceEventHandler, domType, element, callback) {
function listener(e) {
callback(screenSpaceEventHandler, e);
}
if (FeatureDetection_default.isInternetExplorer()) {
element.addEventListener(domType, listener, false);
} else {
element.addEventListener(domType, listener, {
capture: false,
passive: false
});
}
screenSpaceEventHandler._removalFunctions.push(function() {
element.removeEventListener(domType, listener, false);
});
}
function registerListeners(screenSpaceEventHandler) {
const element = screenSpaceEventHandler._element;
const alternateElement = !defined_default(element.disableRootEvents) ? document : element;
if (FeatureDetection_default.supportsPointerEvents()) {
registerListener(
screenSpaceEventHandler,
"pointerdown",
element,
handlePointerDown
);
registerListener(
screenSpaceEventHandler,
"pointerup",
element,
handlePointerUp
);
registerListener(
screenSpaceEventHandler,
"pointermove",
element,
handlePointerMove
);
registerListener(
screenSpaceEventHandler,
"pointercancel",
element,
handlePointerUp
);
} else {
registerListener(
screenSpaceEventHandler,
"mousedown",
element,
handleMouseDown
);
registerListener(
screenSpaceEventHandler,
"mouseup",
alternateElement,
handleMouseUp
);
registerListener(
screenSpaceEventHandler,
"mousemove",
alternateElement,
handleMouseMove
);
registerListener(
screenSpaceEventHandler,
"touchstart",
element,
handleTouchStart
);
registerListener(
screenSpaceEventHandler,
"touchend",
alternateElement,
handleTouchEnd
);
registerListener(
screenSpaceEventHandler,
"touchmove",
alternateElement,
handleTouchMove
);
registerListener(
screenSpaceEventHandler,
"touchcancel",
alternateElement,
handleTouchEnd
);
}
registerListener(
screenSpaceEventHandler,
"dblclick",
element,
handleDblClick
);
let wheelEvent;
if ("onwheel" in element) {
wheelEvent = "wheel";
} else if (document.onmousewheel !== void 0) {
wheelEvent = "mousewheel";
} else {
wheelEvent = "DOMMouseScroll";
}
registerListener(screenSpaceEventHandler, wheelEvent, element, handleWheel);
}
function unregisterListeners(screenSpaceEventHandler) {
const removalFunctions = screenSpaceEventHandler._removalFunctions;
for (let i = 0; i < removalFunctions.length; ++i) {
removalFunctions[i]();
}
}
var mouseDownEvent = {
position: new Cartesian2_default()
};
function gotTouchEvent(screenSpaceEventHandler) {
screenSpaceEventHandler._lastSeenTouchEvent = getTimestamp_default();
}
function canProcessMouseEvent(screenSpaceEventHandler) {
return getTimestamp_default() - screenSpaceEventHandler._lastSeenTouchEvent > ScreenSpaceEventHandler.mouseEmulationIgnoreMilliseconds;
}
function checkPixelTolerance(startPosition, endPosition, pixelTolerance) {
const xDiff = startPosition.x - endPosition.x;
const yDiff = startPosition.y - endPosition.y;
const totalPixels = Math.sqrt(xDiff * xDiff + yDiff * yDiff);
return totalPixels < pixelTolerance;
}
function handleMouseDown(screenSpaceEventHandler, event) {
if (!canProcessMouseEvent(screenSpaceEventHandler)) {
return;
}
const button = event.button;
screenSpaceEventHandler._buttonDown[button] = true;
let screenSpaceEventType;
if (button === MouseButton.LEFT) {
screenSpaceEventType = ScreenSpaceEventType_default.LEFT_DOWN;
} else if (button === MouseButton.MIDDLE) {
screenSpaceEventType = ScreenSpaceEventType_default.MIDDLE_DOWN;
} else if (button === MouseButton.RIGHT) {
screenSpaceEventType = ScreenSpaceEventType_default.RIGHT_DOWN;
} else {
return;
}
const position = getPosition3(
screenSpaceEventHandler,
event,
screenSpaceEventHandler._primaryPosition
);
Cartesian2_default.clone(position, screenSpaceEventHandler._primaryStartPosition);
Cartesian2_default.clone(position, screenSpaceEventHandler._primaryPreviousPosition);
const modifier = getModifier(event);
const action = screenSpaceEventHandler.getInputAction(
screenSpaceEventType,
modifier
);
if (defined_default(action)) {
Cartesian2_default.clone(position, mouseDownEvent.position);
action(mouseDownEvent);
event.preventDefault();
}
}
var mouseUpEvent = {
position: new Cartesian2_default()
};
var mouseClickEvent = {
position: new Cartesian2_default()
};
function cancelMouseEvent(screenSpaceEventHandler, screenSpaceEventType, clickScreenSpaceEventType, event) {
const modifier = getModifier(event);
const action = screenSpaceEventHandler.getInputAction(
screenSpaceEventType,
modifier
);
const clickAction = screenSpaceEventHandler.getInputAction(
clickScreenSpaceEventType,
modifier
);
if (defined_default(action) || defined_default(clickAction)) {
const position = getPosition3(
screenSpaceEventHandler,
event,
screenSpaceEventHandler._primaryPosition
);
if (defined_default(action)) {
Cartesian2_default.clone(position, mouseUpEvent.position);
action(mouseUpEvent);
}
if (defined_default(clickAction)) {
const startPosition = screenSpaceEventHandler._primaryStartPosition;
if (checkPixelTolerance(
startPosition,
position,
screenSpaceEventHandler._clickPixelTolerance
)) {
Cartesian2_default.clone(position, mouseClickEvent.position);
clickAction(mouseClickEvent);
}
}
}
}
function handleMouseUp(screenSpaceEventHandler, event) {
if (!canProcessMouseEvent(screenSpaceEventHandler)) {
return;
}
const button = event.button;
if (button !== MouseButton.LEFT && button !== MouseButton.MIDDLE && button !== MouseButton.RIGHT) {
return;
}
if (screenSpaceEventHandler._buttonDown[MouseButton.LEFT]) {
cancelMouseEvent(
screenSpaceEventHandler,
ScreenSpaceEventType_default.LEFT_UP,
ScreenSpaceEventType_default.LEFT_CLICK,
event
);
screenSpaceEventHandler._buttonDown[MouseButton.LEFT] = false;
}
if (screenSpaceEventHandler._buttonDown[MouseButton.MIDDLE]) {
cancelMouseEvent(
screenSpaceEventHandler,
ScreenSpaceEventType_default.MIDDLE_UP,
ScreenSpaceEventType_default.MIDDLE_CLICK,
event
);
screenSpaceEventHandler._buttonDown[MouseButton.MIDDLE] = false;
}
if (screenSpaceEventHandler._buttonDown[MouseButton.RIGHT]) {
cancelMouseEvent(
screenSpaceEventHandler,
ScreenSpaceEventType_default.RIGHT_UP,
ScreenSpaceEventType_default.RIGHT_CLICK,
event
);
screenSpaceEventHandler._buttonDown[MouseButton.RIGHT] = false;
}
}
var mouseMoveEvent = {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default()
};
function handleMouseMove(screenSpaceEventHandler, event) {
if (!canProcessMouseEvent(screenSpaceEventHandler)) {
return;
}
const modifier = getModifier(event);
const position = getPosition3(
screenSpaceEventHandler,
event,
screenSpaceEventHandler._primaryPosition
);
const previousPosition = screenSpaceEventHandler._primaryPreviousPosition;
const action = screenSpaceEventHandler.getInputAction(
ScreenSpaceEventType_default.MOUSE_MOVE,
modifier
);
if (defined_default(action)) {
Cartesian2_default.clone(previousPosition, mouseMoveEvent.startPosition);
Cartesian2_default.clone(position, mouseMoveEvent.endPosition);
action(mouseMoveEvent);
}
Cartesian2_default.clone(position, previousPosition);
if (screenSpaceEventHandler._buttonDown[MouseButton.LEFT] || screenSpaceEventHandler._buttonDown[MouseButton.MIDDLE] || screenSpaceEventHandler._buttonDown[MouseButton.RIGHT]) {
event.preventDefault();
}
}
var mouseDblClickEvent = {
position: new Cartesian2_default()
};
function handleDblClick(screenSpaceEventHandler, event) {
const button = event.button;
let screenSpaceEventType;
if (button === MouseButton.LEFT) {
screenSpaceEventType = ScreenSpaceEventType_default.LEFT_DOUBLE_CLICK;
} else {
return;
}
const modifier = getModifier(event);
const action = screenSpaceEventHandler.getInputAction(
screenSpaceEventType,
modifier
);
if (defined_default(action)) {
getPosition3(screenSpaceEventHandler, event, mouseDblClickEvent.position);
action(mouseDblClickEvent);
}
}
function handleWheel(screenSpaceEventHandler, event) {
let delta;
if (defined_default(event.deltaY)) {
const deltaMode = event.deltaMode;
if (deltaMode === event.DOM_DELTA_PIXEL) {
delta = -event.deltaY;
} else if (deltaMode === event.DOM_DELTA_LINE) {
delta = -event.deltaY * 40;
} else {
delta = -event.deltaY * 120;
}
} else if (event.detail > 0) {
delta = event.detail * -120;
} else {
delta = event.wheelDelta;
}
if (!defined_default(delta)) {
return;
}
const modifier = getModifier(event);
const action = screenSpaceEventHandler.getInputAction(
ScreenSpaceEventType_default.WHEEL,
modifier
);
if (defined_default(action)) {
action(delta);
event.preventDefault();
}
}
function handleTouchStart(screenSpaceEventHandler, event) {
gotTouchEvent(screenSpaceEventHandler);
const changedTouches = event.changedTouches;
let i;
const length2 = changedTouches.length;
let touch;
let identifier;
const positions = screenSpaceEventHandler._positions;
for (i = 0; i < length2; ++i) {
touch = changedTouches[i];
identifier = touch.identifier;
positions.set(
identifier,
getPosition3(screenSpaceEventHandler, touch, new Cartesian2_default())
);
}
fireTouchEvents(screenSpaceEventHandler, event);
const previousPositions = screenSpaceEventHandler._previousPositions;
for (i = 0; i < length2; ++i) {
touch = changedTouches[i];
identifier = touch.identifier;
previousPositions.set(
identifier,
Cartesian2_default.clone(positions.get(identifier))
);
}
}
function handleTouchEnd(screenSpaceEventHandler, event) {
gotTouchEvent(screenSpaceEventHandler);
const changedTouches = event.changedTouches;
let i;
const length2 = changedTouches.length;
let touch;
let identifier;
const positions = screenSpaceEventHandler._positions;
for (i = 0; i < length2; ++i) {
touch = changedTouches[i];
identifier = touch.identifier;
positions.remove(identifier);
}
fireTouchEvents(screenSpaceEventHandler, event);
const previousPositions = screenSpaceEventHandler._previousPositions;
for (i = 0; i < length2; ++i) {
touch = changedTouches[i];
identifier = touch.identifier;
previousPositions.remove(identifier);
}
}
var touchStartEvent = {
position: new Cartesian2_default()
};
var touch2StartEvent = {
position1: new Cartesian2_default(),
position2: new Cartesian2_default()
};
var touchEndEvent = {
position: new Cartesian2_default()
};
var touchClickEvent = {
position: new Cartesian2_default()
};
var touchHoldEvent = {
position: new Cartesian2_default()
};
function fireTouchEvents(screenSpaceEventHandler, event) {
const modifier = getModifier(event);
const positions = screenSpaceEventHandler._positions;
const numberOfTouches = positions.length;
let action;
let clickAction;
const pinching = screenSpaceEventHandler._isPinching;
if (numberOfTouches !== 1 && screenSpaceEventHandler._buttonDown[MouseButton.LEFT]) {
screenSpaceEventHandler._buttonDown[MouseButton.LEFT] = false;
if (defined_default(screenSpaceEventHandler._touchHoldTimer)) {
clearTimeout(screenSpaceEventHandler._touchHoldTimer);
screenSpaceEventHandler._touchHoldTimer = void 0;
}
action = screenSpaceEventHandler.getInputAction(
ScreenSpaceEventType_default.LEFT_UP,
modifier
);
if (defined_default(action)) {
Cartesian2_default.clone(
screenSpaceEventHandler._primaryPosition,
touchEndEvent.position
);
action(touchEndEvent);
}
if (numberOfTouches === 0 && !screenSpaceEventHandler._isTouchHolding) {
clickAction = screenSpaceEventHandler.getInputAction(
ScreenSpaceEventType_default.LEFT_CLICK,
modifier
);
if (defined_default(clickAction)) {
const startPosition = screenSpaceEventHandler._primaryStartPosition;
const endPosition = screenSpaceEventHandler._previousPositions.values[0];
if (checkPixelTolerance(
startPosition,
endPosition,
screenSpaceEventHandler._clickPixelTolerance
)) {
Cartesian2_default.clone(
screenSpaceEventHandler._primaryPosition,
touchClickEvent.position
);
clickAction(touchClickEvent);
}
}
}
screenSpaceEventHandler._isTouchHolding = false;
}
if (numberOfTouches === 0 && pinching) {
screenSpaceEventHandler._isPinching = false;
action = screenSpaceEventHandler.getInputAction(
ScreenSpaceEventType_default.PINCH_END,
modifier
);
if (defined_default(action)) {
action();
}
}
if (numberOfTouches === 1 && !pinching) {
const position = positions.values[0];
Cartesian2_default.clone(position, screenSpaceEventHandler._primaryPosition);
Cartesian2_default.clone(position, screenSpaceEventHandler._primaryStartPosition);
Cartesian2_default.clone(
position,
screenSpaceEventHandler._primaryPreviousPosition
);
screenSpaceEventHandler._buttonDown[MouseButton.LEFT] = true;
action = screenSpaceEventHandler.getInputAction(
ScreenSpaceEventType_default.LEFT_DOWN,
modifier
);
if (defined_default(action)) {
Cartesian2_default.clone(position, touchStartEvent.position);
action(touchStartEvent);
}
screenSpaceEventHandler._touchHoldTimer = setTimeout(function() {
if (!screenSpaceEventHandler.isDestroyed()) {
screenSpaceEventHandler._touchHoldTimer = void 0;
screenSpaceEventHandler._isTouchHolding = true;
clickAction = screenSpaceEventHandler.getInputAction(
ScreenSpaceEventType_default.RIGHT_CLICK,
modifier
);
if (defined_default(clickAction)) {
const startPosition = screenSpaceEventHandler._primaryStartPosition;
const endPosition = screenSpaceEventHandler._previousPositions.values[0];
if (checkPixelTolerance(
startPosition,
endPosition,
screenSpaceEventHandler._holdPixelTolerance
)) {
Cartesian2_default.clone(
screenSpaceEventHandler._primaryPosition,
touchHoldEvent.position
);
clickAction(touchHoldEvent);
}
}
}
}, ScreenSpaceEventHandler.touchHoldDelayMilliseconds);
event.preventDefault();
}
if (numberOfTouches === 2 && !pinching) {
screenSpaceEventHandler._isPinching = true;
action = screenSpaceEventHandler.getInputAction(
ScreenSpaceEventType_default.PINCH_START,
modifier
);
if (defined_default(action)) {
Cartesian2_default.clone(positions.values[0], touch2StartEvent.position1);
Cartesian2_default.clone(positions.values[1], touch2StartEvent.position2);
action(touch2StartEvent);
event.preventDefault();
}
}
}
function handleTouchMove(screenSpaceEventHandler, event) {
gotTouchEvent(screenSpaceEventHandler);
const changedTouches = event.changedTouches;
let i;
const length2 = changedTouches.length;
let touch;
let identifier;
const positions = screenSpaceEventHandler._positions;
for (i = 0; i < length2; ++i) {
touch = changedTouches[i];
identifier = touch.identifier;
const position = positions.get(identifier);
if (defined_default(position)) {
getPosition3(screenSpaceEventHandler, touch, position);
}
}
fireTouchMoveEvents(screenSpaceEventHandler, event);
const previousPositions = screenSpaceEventHandler._previousPositions;
for (i = 0; i < length2; ++i) {
touch = changedTouches[i];
identifier = touch.identifier;
Cartesian2_default.clone(
positions.get(identifier),
previousPositions.get(identifier)
);
}
}
var touchMoveEvent = {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default()
};
var touchPinchMovementEvent = {
distance: {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default()
},
angleAndHeight: {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default()
}
};
function fireTouchMoveEvents(screenSpaceEventHandler, event) {
const modifier = getModifier(event);
const positions = screenSpaceEventHandler._positions;
const previousPositions = screenSpaceEventHandler._previousPositions;
const numberOfTouches = positions.length;
let action;
if (numberOfTouches === 1 && screenSpaceEventHandler._buttonDown[MouseButton.LEFT]) {
const position = positions.values[0];
Cartesian2_default.clone(position, screenSpaceEventHandler._primaryPosition);
const previousPosition = screenSpaceEventHandler._primaryPreviousPosition;
action = screenSpaceEventHandler.getInputAction(
ScreenSpaceEventType_default.MOUSE_MOVE,
modifier
);
if (defined_default(action)) {
Cartesian2_default.clone(previousPosition, touchMoveEvent.startPosition);
Cartesian2_default.clone(position, touchMoveEvent.endPosition);
action(touchMoveEvent);
}
Cartesian2_default.clone(position, previousPosition);
event.preventDefault();
} else if (numberOfTouches === 2 && screenSpaceEventHandler._isPinching) {
action = screenSpaceEventHandler.getInputAction(
ScreenSpaceEventType_default.PINCH_MOVE,
modifier
);
if (defined_default(action)) {
const position1 = positions.values[0];
const position2 = positions.values[1];
const previousPosition1 = previousPositions.values[0];
const previousPosition2 = previousPositions.values[1];
const dX = position2.x - position1.x;
const dY = position2.y - position1.y;
const dist = Math.sqrt(dX * dX + dY * dY) * 0.25;
const prevDX = previousPosition2.x - previousPosition1.x;
const prevDY = previousPosition2.y - previousPosition1.y;
const prevDist = Math.sqrt(prevDX * prevDX + prevDY * prevDY) * 0.25;
const cY = (position2.y + position1.y) * 0.125;
const prevCY = (previousPosition2.y + previousPosition1.y) * 0.125;
const angle = Math.atan2(dY, dX);
const prevAngle = Math.atan2(prevDY, prevDX);
Cartesian2_default.fromElements(
0,
prevDist,
touchPinchMovementEvent.distance.startPosition
);
Cartesian2_default.fromElements(
0,
dist,
touchPinchMovementEvent.distance.endPosition
);
Cartesian2_default.fromElements(
prevAngle,
prevCY,
touchPinchMovementEvent.angleAndHeight.startPosition
);
Cartesian2_default.fromElements(
angle,
cY,
touchPinchMovementEvent.angleAndHeight.endPosition
);
action(touchPinchMovementEvent);
}
}
}
function handlePointerDown(screenSpaceEventHandler, event) {
event.target.setPointerCapture(event.pointerId);
if (event.pointerType === "touch") {
const positions = screenSpaceEventHandler._positions;
const identifier = event.pointerId;
positions.set(
identifier,
getPosition3(screenSpaceEventHandler, event, new Cartesian2_default())
);
fireTouchEvents(screenSpaceEventHandler, event);
const previousPositions = screenSpaceEventHandler._previousPositions;
previousPositions.set(
identifier,
Cartesian2_default.clone(positions.get(identifier))
);
} else {
handleMouseDown(screenSpaceEventHandler, event);
}
}
function handlePointerUp(screenSpaceEventHandler, event) {
if (event.pointerType === "touch") {
const positions = screenSpaceEventHandler._positions;
const identifier = event.pointerId;
positions.remove(identifier);
fireTouchEvents(screenSpaceEventHandler, event);
const previousPositions = screenSpaceEventHandler._previousPositions;
previousPositions.remove(identifier);
} else {
handleMouseUp(screenSpaceEventHandler, event);
}
}
function handlePointerMove(screenSpaceEventHandler, event) {
if (event.pointerType === "touch") {
const positions = screenSpaceEventHandler._positions;
const identifier = event.pointerId;
const position = positions.get(identifier);
if (!defined_default(position)) {
return;
}
getPosition3(screenSpaceEventHandler, event, position);
fireTouchMoveEvents(screenSpaceEventHandler, event);
const previousPositions = screenSpaceEventHandler._previousPositions;
Cartesian2_default.clone(
positions.get(identifier),
previousPositions.get(identifier)
);
} else {
handleMouseMove(screenSpaceEventHandler, event);
}
}
function ScreenSpaceEventHandler(element) {
this._inputEvents = {};
this._buttonDown = {
[MouseButton.LEFT]: false,
[MouseButton.MIDDLE]: false,
[MouseButton.RIGHT]: false
};
this._isPinching = false;
this._isTouchHolding = false;
this._lastSeenTouchEvent = -ScreenSpaceEventHandler.mouseEmulationIgnoreMilliseconds;
this._primaryStartPosition = new Cartesian2_default();
this._primaryPosition = new Cartesian2_default();
this._primaryPreviousPosition = new Cartesian2_default();
this._positions = new AssociativeArray_default();
this._previousPositions = new AssociativeArray_default();
this._removalFunctions = [];
this._touchHoldTimer = void 0;
this._clickPixelTolerance = 5;
this._holdPixelTolerance = 25;
this._element = element ?? document;
registerListeners(this);
}
ScreenSpaceEventHandler.prototype.setInputAction = function(action, type, modifier) {
if (!defined_default(action)) {
throw new DeveloperError_default("action is required.");
}
if (!defined_default(type)) {
throw new DeveloperError_default("type is required.");
}
const key = getInputEventKey(type, modifier);
this._inputEvents[key] = action;
};
ScreenSpaceEventHandler.prototype.getInputAction = function(type, modifier) {
if (!defined_default(type)) {
throw new DeveloperError_default("type is required.");
}
const key = getInputEventKey(type, modifier);
return this._inputEvents[key];
};
ScreenSpaceEventHandler.prototype.removeInputAction = function(type, modifier) {
if (!defined_default(type)) {
throw new DeveloperError_default("type is required.");
}
const key = getInputEventKey(type, modifier);
delete this._inputEvents[key];
};
ScreenSpaceEventHandler.prototype.isDestroyed = function() {
return false;
};
ScreenSpaceEventHandler.prototype.destroy = function() {
unregisterListeners(this);
return destroyObject_default(this);
};
ScreenSpaceEventHandler.mouseEmulationIgnoreMilliseconds = 800;
ScreenSpaceEventHandler.touchHoldDelayMilliseconds = 1500;
var ScreenSpaceEventHandler_default = ScreenSpaceEventHandler;
// packages/engine/Source/Scene/SceneTransitioner.js
function SceneTransitioner(scene) {
Check_default.typeOf.object("scene", scene);
this._scene = scene;
this._currentTweens = [];
this._morphHandler = void 0;
this._morphCancelled = false;
this._completeMorph = void 0;
this._morphToOrthographic = false;
}
SceneTransitioner.prototype.completeMorph = function() {
if (defined_default(this._completeMorph)) {
this._completeMorph();
}
};
SceneTransitioner.prototype.morphTo2D = function(duration, ellipsoid) {
if (defined_default(this._completeMorph)) {
this._completeMorph();
}
const scene = this._scene;
this._previousMode = scene.mode;
this._morphToOrthographic = scene.camera.frustum instanceof OrthographicFrustum_default;
if (this._previousMode === SceneMode_default.SCENE2D || this._previousMode === SceneMode_default.MORPHING) {
return;
}
this._scene.morphStart.raiseEvent(
this,
this._previousMode,
SceneMode_default.SCENE2D,
true
);
scene._mode = SceneMode_default.MORPHING;
scene.camera._setTransform(Matrix4_default.IDENTITY);
if (this._previousMode === SceneMode_default.COLUMBUS_VIEW) {
morphFromColumbusViewTo2D(this, duration);
} else {
morphFrom3DTo2D(this, duration, ellipsoid);
}
if (duration === 0 && defined_default(this._completeMorph)) {
this._completeMorph();
}
};
var scratchToCVPosition = new Cartesian3_default();
var scratchToCVDirection = new Cartesian3_default();
var scratchToCVUp = new Cartesian3_default();
var scratchToCVPosition2D = new Cartesian3_default();
var scratchToCVDirection2D = new Cartesian3_default();
var scratchToCVUp2D = new Cartesian3_default();
var scratchToCVSurfacePosition = new Cartesian3_default();
var scratchToCVCartographic = new Cartographic_default();
var scratchToCVToENU = new Matrix4_default();
var scratchToCVFrustumPerspective = new PerspectiveFrustum_default();
var scratchToCVFrustumOrthographic = new OrthographicFrustum_default();
var scratchToCVCamera = {
position: void 0,
direction: void 0,
up: void 0,
position2D: void 0,
direction2D: void 0,
up2D: void 0,
frustum: void 0
};
SceneTransitioner.prototype.morphToColumbusView = function(duration, ellipsoid) {
if (defined_default(this._completeMorph)) {
this._completeMorph();
}
const scene = this._scene;
this._previousMode = scene.mode;
if (this._previousMode === SceneMode_default.COLUMBUS_VIEW || this._previousMode === SceneMode_default.MORPHING) {
return;
}
this._scene.morphStart.raiseEvent(
this,
this._previousMode,
SceneMode_default.COLUMBUS_VIEW,
true
);
scene.camera._setTransform(Matrix4_default.IDENTITY);
let position = scratchToCVPosition;
const direction2 = scratchToCVDirection;
const up = scratchToCVUp;
if (duration > 0) {
position.x = 0;
position.y = -1;
position.z = 1;
position = Cartesian3_default.multiplyByScalar(
Cartesian3_default.normalize(position, position),
5 * ellipsoid.maximumRadius,
position
);
Cartesian3_default.negate(Cartesian3_default.normalize(position, direction2), direction2);
Cartesian3_default.cross(Cartesian3_default.UNIT_X, direction2, up);
} else {
const camera = scene.camera;
if (this._previousMode === SceneMode_default.SCENE2D) {
Cartesian3_default.clone(camera.position, position);
position.z = camera.frustum.right - camera.frustum.left;
Cartesian3_default.negate(Cartesian3_default.UNIT_Z, direction2);
Cartesian3_default.clone(Cartesian3_default.UNIT_Y, up);
} else {
Cartesian3_default.clone(camera.positionWC, position);
Cartesian3_default.clone(camera.directionWC, direction2);
Cartesian3_default.clone(camera.upWC, up);
const surfacePoint = ellipsoid.scaleToGeodeticSurface(
position,
scratchToCVSurfacePosition
);
const toENU = Transforms_default.eastNorthUpToFixedFrame(
surfacePoint,
ellipsoid,
scratchToCVToENU
);
Matrix4_default.inverseTransformation(toENU, toENU);
scene.mapProjection.project(
ellipsoid.cartesianToCartographic(position, scratchToCVCartographic),
position
);
Matrix4_default.multiplyByPointAsVector(toENU, direction2, direction2);
Matrix4_default.multiplyByPointAsVector(toENU, up, up);
}
}
let frustum;
if (this._morphToOrthographic) {
frustum = scratchToCVFrustumOrthographic;
frustum.width = scene.camera.frustum.right - scene.camera.frustum.left;
frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight;
} else {
frustum = scratchToCVFrustumPerspective;
frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight;
frustum.fov = Math_default.toRadians(60);
}
const cameraCV = scratchToCVCamera;
cameraCV.position = position;
cameraCV.direction = direction2;
cameraCV.up = up;
cameraCV.frustum = frustum;
const complete = completeColumbusViewCallback(cameraCV);
createMorphHandler(this, complete);
if (this._previousMode === SceneMode_default.SCENE2D) {
morphFrom2DToColumbusView(this, duration, cameraCV, complete);
} else {
cameraCV.position2D = Matrix4_default.multiplyByPoint(
Camera_default.TRANSFORM_2D,
position,
scratchToCVPosition2D
);
cameraCV.direction2D = Matrix4_default.multiplyByPointAsVector(
Camera_default.TRANSFORM_2D,
direction2,
scratchToCVDirection2D
);
cameraCV.up2D = Matrix4_default.multiplyByPointAsVector(
Camera_default.TRANSFORM_2D,
up,
scratchToCVUp2D
);
scene._mode = SceneMode_default.MORPHING;
morphFrom3DToColumbusView(this, duration, cameraCV, complete);
}
if (duration === 0 && defined_default(this._completeMorph)) {
this._completeMorph();
}
};
var scratchCVTo3DCamera = {
position: new Cartesian3_default(),
direction: new Cartesian3_default(),
up: new Cartesian3_default(),
frustum: void 0
};
var scratch2DTo3DFrustumPersp = new PerspectiveFrustum_default();
SceneTransitioner.prototype.morphTo3D = function(duration, ellipsoid) {
if (defined_default(this._completeMorph)) {
this._completeMorph();
}
const scene = this._scene;
this._previousMode = scene.mode;
if (this._previousMode === SceneMode_default.SCENE3D || this._previousMode === SceneMode_default.MORPHING) {
return;
}
this._scene.morphStart.raiseEvent(
this,
this._previousMode,
SceneMode_default.SCENE3D,
true
);
scene._mode = SceneMode_default.MORPHING;
scene.camera._setTransform(Matrix4_default.IDENTITY);
if (this._previousMode === SceneMode_default.SCENE2D) {
morphFrom2DTo3D(this, duration, ellipsoid);
} else {
let camera3D;
if (duration > 0) {
camera3D = scratchCVTo3DCamera;
Cartesian3_default.fromDegrees(
0,
0,
5 * ellipsoid.maximumRadius,
ellipsoid,
camera3D.position
);
Cartesian3_default.negate(camera3D.position, camera3D.direction);
Cartesian3_default.normalize(camera3D.direction, camera3D.direction);
Cartesian3_default.clone(Cartesian3_default.UNIT_Z, camera3D.up);
} else {
camera3D = getColumbusViewTo3DCamera(this, ellipsoid);
}
let frustum;
const camera = scene.camera;
if (camera.frustum instanceof OrthographicFrustum_default) {
frustum = camera.frustum.clone();
} else {
frustum = scratch2DTo3DFrustumPersp;
frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight;
frustum.fov = Math_default.toRadians(60);
}
camera3D.frustum = frustum;
const complete = complete3DCallback(camera3D);
createMorphHandler(this, complete);
morphFromColumbusViewTo3D(this, duration, camera3D, complete);
}
if (duration === 0 && defined_default(this._completeMorph)) {
this._completeMorph();
}
};
SceneTransitioner.prototype.isDestroyed = function() {
return false;
};
SceneTransitioner.prototype.destroy = function() {
destroyMorphHandler(this);
return destroyObject_default(this);
};
function createMorphHandler(transitioner, completeMorphFunction) {
if (transitioner._scene.completeMorphOnUserInput) {
transitioner._morphHandler = new ScreenSpaceEventHandler_default(
transitioner._scene.canvas
);
const completeMorph = function() {
transitioner._morphCancelled = true;
transitioner._scene.camera.cancelFlight();
completeMorphFunction(transitioner);
};
transitioner._completeMorph = completeMorph;
transitioner._morphHandler.setInputAction(
completeMorph,
ScreenSpaceEventType_default.LEFT_DOWN
);
transitioner._morphHandler.setInputAction(
completeMorph,
ScreenSpaceEventType_default.MIDDLE_DOWN
);
transitioner._morphHandler.setInputAction(
completeMorph,
ScreenSpaceEventType_default.RIGHT_DOWN
);
transitioner._morphHandler.setInputAction(
completeMorph,
ScreenSpaceEventType_default.WHEEL
);
}
}
function destroyMorphHandler(transitioner) {
const tweens = transitioner._currentTweens;
for (let i = 0; i < tweens.length; ++i) {
tweens[i].cancelTween();
}
transitioner._currentTweens.length = 0;
transitioner._morphHandler = transitioner._morphHandler && transitioner._morphHandler.destroy();
}
var scratchCVTo3DCartographic = new Cartographic_default();
var scratchCVTo3DSurfacePoint = new Cartesian3_default();
var scratchCVTo3DFromENU = new Matrix4_default();
function getColumbusViewTo3DCamera(transitioner, ellipsoid) {
const scene = transitioner._scene;
const camera = scene.camera;
const camera3D = scratchCVTo3DCamera;
const position = camera3D.position;
const direction2 = camera3D.direction;
const up = camera3D.up;
const positionCarto = scene.mapProjection.unproject(
camera.position,
scratchCVTo3DCartographic
);
ellipsoid.cartographicToCartesian(positionCarto, position);
const surfacePoint = ellipsoid.scaleToGeodeticSurface(
position,
scratchCVTo3DSurfacePoint
);
const fromENU = Transforms_default.eastNorthUpToFixedFrame(
surfacePoint,
ellipsoid,
scratchCVTo3DFromENU
);
Matrix4_default.multiplyByPointAsVector(fromENU, camera.direction, direction2);
Matrix4_default.multiplyByPointAsVector(fromENU, camera.up, up);
return camera3D;
}
var scratchCVTo3DStartPos = new Cartesian3_default();
var scratchCVTo3DStartDir = new Cartesian3_default();
var scratchCVTo3DStartUp = new Cartesian3_default();
var scratchCVTo3DEndPos = new Cartesian3_default();
var scratchCVTo3DEndDir = new Cartesian3_default();
var scratchCVTo3DEndUp = new Cartesian3_default();
function morphFromColumbusViewTo3D(transitioner, duration, endCamera, complete) {
duration *= 0.5;
const scene = transitioner._scene;
const camera = scene.camera;
const startPos = Cartesian3_default.clone(camera.position, scratchCVTo3DStartPos);
const startDir = Cartesian3_default.clone(camera.direction, scratchCVTo3DStartDir);
const startUp = Cartesian3_default.clone(camera.up, scratchCVTo3DStartUp);
const endPos = Matrix4_default.multiplyByPoint(
Camera_default.TRANSFORM_2D_INVERSE,
endCamera.position,
scratchCVTo3DEndPos
);
const endDir = Matrix4_default.multiplyByPointAsVector(
Camera_default.TRANSFORM_2D_INVERSE,
endCamera.direction,
scratchCVTo3DEndDir
);
const endUp = Matrix4_default.multiplyByPointAsVector(
Camera_default.TRANSFORM_2D_INVERSE,
endCamera.up,
scratchCVTo3DEndUp
);
function update8(value) {
columbusViewMorph(startPos, endPos, value.time, camera.position);
columbusViewMorph(startDir, endDir, value.time, camera.direction);
columbusViewMorph(startUp, endUp, value.time, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.normalize(camera.right, camera.right);
}
const tween = scene.tweens.add({
duration,
easingFunction: EasingFunction_default.QUARTIC_OUT,
startObject: {
time: 0
},
stopObject: {
time: 1
},
update: update8,
complete: function() {
addMorphTimeAnimations(transitioner, scene, 0, 1, duration, complete);
}
});
transitioner._currentTweens.push(tween);
}
var scratch2DTo3DFrustumOrtho = new OrthographicFrustum_default();
var scratch3DToCVStartPos = new Cartesian3_default();
var scratch3DToCVStartDir = new Cartesian3_default();
var scratch3DToCVStartUp = new Cartesian3_default();
var scratch3DToCVEndPos = new Cartesian3_default();
var scratch3DToCVEndDir = new Cartesian3_default();
var scratch3DToCVEndUp = new Cartesian3_default();
function morphFrom2DTo3D(transitioner, duration, ellipsoid) {
duration /= 3;
const scene = transitioner._scene;
const camera = scene.camera;
let camera3D;
if (duration > 0) {
camera3D = scratchCVTo3DCamera;
Cartesian3_default.fromDegrees(
0,
0,
5 * ellipsoid.maximumRadius,
ellipsoid,
camera3D.position
);
Cartesian3_default.negate(camera3D.position, camera3D.direction);
Cartesian3_default.normalize(camera3D.direction, camera3D.direction);
Cartesian3_default.clone(Cartesian3_default.UNIT_Z, camera3D.up);
} else {
camera.position.z = camera.frustum.right - camera.frustum.left;
camera3D = getColumbusViewTo3DCamera(transitioner, ellipsoid);
}
let frustum;
if (transitioner._morphToOrthographic) {
frustum = scratch2DTo3DFrustumOrtho;
frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight;
frustum.width = camera.frustum.right - camera.frustum.left;
} else {
frustum = scratch2DTo3DFrustumPersp;
frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight;
frustum.fov = Math_default.toRadians(60);
}
camera3D.frustum = frustum;
const complete = complete3DCallback(camera3D);
createMorphHandler(transitioner, complete);
let morph;
if (transitioner._morphToOrthographic) {
morph = function() {
morphFromColumbusViewTo3D(transitioner, duration, camera3D, complete);
};
} else {
morph = function() {
morphOrthographicToPerspective(
transitioner,
duration,
camera3D,
function() {
morphFromColumbusViewTo3D(transitioner, duration, camera3D, complete);
}
);
};
}
if (duration > 0) {
scene._mode = SceneMode_default.SCENE2D;
camera.flyTo({
duration,
destination: Cartesian3_default.fromDegrees(
0,
0,
5 * ellipsoid.maximumRadius,
ellipsoid,
scratch3DToCVEndPos
),
complete: function() {
scene._mode = SceneMode_default.MORPHING;
morph();
}
});
} else {
morph();
}
}
function columbusViewMorph(startPosition, endPosition, time, result) {
return Cartesian3_default.lerp(startPosition, endPosition, time, result);
}
function morphPerspectiveToOrthographic(transitioner, duration, endCamera, updateHeight, complete) {
const scene = transitioner._scene;
const camera = scene.camera;
if (camera.frustum instanceof OrthographicFrustum_default) {
return;
}
const startFOV = camera.frustum.fov;
const endFOV = Math_default.RADIANS_PER_DEGREE * 0.5;
const d = endCamera.position.z * Math.tan(startFOV * 0.5);
camera.frustum.far = d / Math.tan(endFOV * 0.5) + 1e7;
function update8(value) {
camera.frustum.fov = Math_default.lerp(startFOV, endFOV, value.time);
const height = d / Math.tan(camera.frustum.fov * 0.5);
updateHeight(camera, height);
}
const tween = scene.tweens.add({
duration,
easingFunction: EasingFunction_default.QUARTIC_OUT,
startObject: {
time: 0
},
stopObject: {
time: 1
},
update: update8,
complete: function() {
camera.frustum = endCamera.frustum.clone();
complete(transitioner);
}
});
transitioner._currentTweens.push(tween);
}
var scratchCVTo2DStartPos = new Cartesian3_default();
var scratchCVTo2DStartDir = new Cartesian3_default();
var scratchCVTo2DStartUp = new Cartesian3_default();
var scratchCVTo2DEndPos = new Cartesian3_default();
var scratchCVTo2DEndDir = new Cartesian3_default();
var scratchCVTo2DEndUp = new Cartesian3_default();
var scratchCVTo2DFrustum = new OrthographicOffCenterFrustum_default();
var scratchCVTo2DRay = new Ray_default();
var scratchCVTo2DPickPos = new Cartesian3_default();
var scratchCVTo2DCamera = {
position: void 0,
direction: void 0,
up: void 0,
frustum: void 0
};
function morphFromColumbusViewTo2D(transitioner, duration) {
duration *= 0.5;
const scene = transitioner._scene;
const camera = scene.camera;
const startPos = Cartesian3_default.clone(camera.position, scratchCVTo2DStartPos);
const startDir = Cartesian3_default.clone(camera.direction, scratchCVTo2DStartDir);
const startUp = Cartesian3_default.clone(camera.up, scratchCVTo2DStartUp);
const endDir = Cartesian3_default.negate(Cartesian3_default.UNIT_Z, scratchCVTo2DEndDir);
const endUp = Cartesian3_default.clone(Cartesian3_default.UNIT_Y, scratchCVTo2DEndUp);
const endPos = scratchCVTo2DEndPos;
if (duration > 0) {
Cartesian3_default.clone(Cartesian3_default.ZERO, scratchCVTo2DEndPos);
endPos.z = 5 * scene.ellipsoid.maximumRadius;
} else {
Cartesian3_default.clone(startPos, scratchCVTo2DEndPos);
const ray = scratchCVTo2DRay;
Matrix4_default.multiplyByPoint(Camera_default.TRANSFORM_2D, startPos, ray.origin);
Matrix4_default.multiplyByPointAsVector(
Camera_default.TRANSFORM_2D,
startDir,
ray.direction
);
const globe = scene.globe;
if (defined_default(globe)) {
const pickPos = globe.pickWorldCoordinates(
ray,
scene,
true,
scratchCVTo2DPickPos
);
if (defined_default(pickPos)) {
Matrix4_default.multiplyByPoint(Camera_default.TRANSFORM_2D_INVERSE, pickPos, endPos);
endPos.z += Cartesian3_default.distance(startPos, endPos);
}
}
}
const frustum = scratchCVTo2DFrustum;
frustum.right = endPos.z * 0.5;
frustum.left = -frustum.right;
frustum.top = frustum.right * (scene.drawingBufferHeight / scene.drawingBufferWidth);
frustum.bottom = -frustum.top;
const camera2D = scratchCVTo2DCamera;
camera2D.position = endPos;
camera2D.direction = endDir;
camera2D.up = endUp;
camera2D.frustum = frustum;
const complete = complete2DCallback(camera2D);
createMorphHandler(transitioner, complete);
function updateCV2(value) {
columbusViewMorph(startPos, endPos, value.time, camera.position);
columbusViewMorph(startDir, endDir, value.time, camera.direction);
columbusViewMorph(startUp, endUp, value.time, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.normalize(camera.right, camera.right);
camera._adjustOrthographicFrustum(true);
}
function updateHeight(camera2, height) {
camera2.position.z = height;
}
const tween = scene.tweens.add({
duration,
easingFunction: EasingFunction_default.QUARTIC_OUT,
startObject: {
time: 0
},
stopObject: {
time: 1
},
update: updateCV2,
complete: function() {
morphPerspectiveToOrthographic(
transitioner,
duration,
camera2D,
updateHeight,
complete
);
}
});
transitioner._currentTweens.push(tween);
}
var scratch3DTo2DCartographic = new Cartographic_default();
var scratch3DTo2DCamera = {
position: new Cartesian3_default(),
direction: new Cartesian3_default(),
up: new Cartesian3_default(),
position2D: new Cartesian3_default(),
direction2D: new Cartesian3_default(),
up2D: new Cartesian3_default(),
frustum: new OrthographicOffCenterFrustum_default()
};
var scratch3DTo2DEndCamera = {
position: new Cartesian3_default(),
direction: new Cartesian3_default(),
up: new Cartesian3_default(),
frustum: void 0
};
var scratch3DTo2DPickPosition = new Cartesian3_default();
var scratch3DTo2DRay = new Ray_default();
var scratch3DTo2DToENU = new Matrix4_default();
var scratch3DTo2DSurfacePoint = new Cartesian3_default();
function morphFrom3DTo2D(transitioner, duration, ellipsoid) {
duration *= 0.5;
const scene = transitioner._scene;
const camera = scene.camera;
const camera2D = scratch3DTo2DCamera;
if (duration > 0) {
Cartesian3_default.clone(Cartesian3_default.ZERO, camera2D.position);
camera2D.position.z = 5 * ellipsoid.maximumRadius;
Cartesian3_default.negate(Cartesian3_default.UNIT_Z, camera2D.direction);
Cartesian3_default.clone(Cartesian3_default.UNIT_Y, camera2D.up);
} else {
ellipsoid.cartesianToCartographic(
camera.positionWC,
scratch3DTo2DCartographic
);
scene.mapProjection.project(scratch3DTo2DCartographic, camera2D.position);
Cartesian3_default.negate(Cartesian3_default.UNIT_Z, camera2D.direction);
Cartesian3_default.clone(Cartesian3_default.UNIT_Y, camera2D.up);
const ray = scratch3DTo2DRay;
Cartesian3_default.clone(camera2D.position2D, ray.origin);
const rayDirection = Cartesian3_default.clone(camera.directionWC, ray.direction);
const surfacePoint = ellipsoid.scaleToGeodeticSurface(
camera.positionWC,
scratch3DTo2DSurfacePoint
);
const toENU = Transforms_default.eastNorthUpToFixedFrame(
surfacePoint,
ellipsoid,
scratch3DTo2DToENU
);
Matrix4_default.inverseTransformation(toENU, toENU);
Matrix4_default.multiplyByPointAsVector(toENU, rayDirection, rayDirection);
Matrix4_default.multiplyByPointAsVector(
Camera_default.TRANSFORM_2D,
rayDirection,
rayDirection
);
const globe = scene.globe;
if (defined_default(globe)) {
const pickedPos = globe.pickWorldCoordinates(
ray,
scene,
true,
scratch3DTo2DPickPosition
);
if (defined_default(pickedPos)) {
const height = Cartesian3_default.distance(camera2D.position2D, pickedPos);
pickedPos.x += height;
Cartesian3_default.clone(pickedPos, camera2D.position2D);
}
}
}
function updateHeight(camera2, height) {
camera2.position.x = height;
}
Matrix4_default.multiplyByPoint(
Camera_default.TRANSFORM_2D,
camera2D.position,
camera2D.position2D
);
Matrix4_default.multiplyByPointAsVector(
Camera_default.TRANSFORM_2D,
camera2D.direction,
camera2D.direction2D
);
Matrix4_default.multiplyByPointAsVector(
Camera_default.TRANSFORM_2D,
camera2D.up,
camera2D.up2D
);
const frustum = camera2D.frustum;
frustum.right = camera2D.position.z * 0.5;
frustum.left = -frustum.right;
frustum.top = frustum.right * (scene.drawingBufferHeight / scene.drawingBufferWidth);
frustum.bottom = -frustum.top;
const endCamera = scratch3DTo2DEndCamera;
Matrix4_default.multiplyByPoint(
Camera_default.TRANSFORM_2D_INVERSE,
camera2D.position2D,
endCamera.position
);
Cartesian3_default.clone(camera2D.direction, endCamera.direction);
Cartesian3_default.clone(camera2D.up, endCamera.up);
endCamera.frustum = frustum;
const complete = complete2DCallback(endCamera);
createMorphHandler(transitioner, complete);
function completeCallback() {
morphPerspectiveToOrthographic(
transitioner,
duration,
camera2D,
updateHeight,
complete
);
}
morphFrom3DToColumbusView(transitioner, duration, camera2D, completeCallback);
}
function morphOrthographicToPerspective(transitioner, duration, cameraCV, complete) {
const scene = transitioner._scene;
const camera = scene.camera;
const height = camera.frustum.right - camera.frustum.left;
camera.frustum = cameraCV.frustum.clone();
const endFOV = camera.frustum.fov;
const startFOV = Math_default.RADIANS_PER_DEGREE * 0.5;
const d = height * Math.tan(endFOV * 0.5);
camera.frustum.far = d / Math.tan(startFOV * 0.5) + 1e7;
camera.frustum.fov = startFOV;
function update8(value) {
camera.frustum.fov = Math_default.lerp(startFOV, endFOV, value.time);
camera.position.z = d / Math.tan(camera.frustum.fov * 0.5);
}
const tween = scene.tweens.add({
duration,
easingFunction: EasingFunction_default.QUARTIC_OUT,
startObject: {
time: 0
},
stopObject: {
time: 1
},
update: update8,
complete: function() {
complete(transitioner);
}
});
transitioner._currentTweens.push(tween);
}
function morphFrom2DToColumbusView(transitioner, duration, cameraCV, complete) {
duration *= 0.5;
const scene = transitioner._scene;
const camera = scene.camera;
const endPos = Cartesian3_default.clone(cameraCV.position, scratch3DToCVEndPos);
const endDir = Cartesian3_default.clone(cameraCV.direction, scratch3DToCVEndDir);
const endUp = Cartesian3_default.clone(cameraCV.up, scratch3DToCVEndUp);
scene._mode = SceneMode_default.MORPHING;
function morph() {
camera.frustum = cameraCV.frustum.clone();
const startPos = Cartesian3_default.clone(camera.position, scratch3DToCVStartPos);
const startDir = Cartesian3_default.clone(camera.direction, scratch3DToCVStartDir);
const startUp = Cartesian3_default.clone(camera.up, scratch3DToCVStartUp);
startPos.z = endPos.z;
function update8(value) {
columbusViewMorph(startPos, endPos, value.time, camera.position);
columbusViewMorph(startDir, endDir, value.time, camera.direction);
columbusViewMorph(startUp, endUp, value.time, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.normalize(camera.right, camera.right);
}
const tween = scene.tweens.add({
duration,
easingFunction: EasingFunction_default.QUARTIC_OUT,
startObject: {
time: 0
},
stopObject: {
time: 1
},
update: update8,
complete: function() {
complete(transitioner);
}
});
transitioner._currentTweens.push(tween);
}
if (transitioner._morphToOrthographic) {
morph();
} else {
morphOrthographicToPerspective(transitioner, 0, cameraCV, morph);
}
}
function morphFrom3DToColumbusView(transitioner, duration, endCamera, complete) {
const scene = transitioner._scene;
const camera = scene.camera;
const startPos = Cartesian3_default.clone(camera.position, scratch3DToCVStartPos);
const startDir = Cartesian3_default.clone(camera.direction, scratch3DToCVStartDir);
const startUp = Cartesian3_default.clone(camera.up, scratch3DToCVStartUp);
const endPos = Cartesian3_default.clone(endCamera.position2D, scratch3DToCVEndPos);
const endDir = Cartesian3_default.clone(endCamera.direction2D, scratch3DToCVEndDir);
const endUp = Cartesian3_default.clone(endCamera.up2D, scratch3DToCVEndUp);
function update8(value) {
columbusViewMorph(startPos, endPos, value.time, camera.position);
columbusViewMorph(startDir, endDir, value.time, camera.direction);
columbusViewMorph(startUp, endUp, value.time, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.normalize(camera.right, camera.right);
camera._adjustOrthographicFrustum(true);
}
const tween = scene.tweens.add({
duration,
easingFunction: EasingFunction_default.QUARTIC_OUT,
startObject: {
time: 0
},
stopObject: {
time: 1
},
update: update8,
complete: function() {
addMorphTimeAnimations(transitioner, scene, 1, 0, duration, complete);
}
});
transitioner._currentTweens.push(tween);
}
function addMorphTimeAnimations(transitioner, scene, start, stop2, duration, complete) {
const options = {
object: scene,
property: "morphTime",
startValue: start,
stopValue: stop2,
duration,
easingFunction: EasingFunction_default.QUARTIC_OUT
};
if (defined_default(complete)) {
options.complete = function() {
complete(transitioner);
};
}
const tween = scene.tweens.addProperty(options);
transitioner._currentTweens.push(tween);
}
function complete3DCallback(camera3D) {
return function(transitioner) {
const scene = transitioner._scene;
scene._mode = SceneMode_default.SCENE3D;
scene.morphTime = SceneMode_default.getMorphTime(SceneMode_default.SCENE3D);
destroyMorphHandler(transitioner);
const camera = scene.camera;
if (transitioner._previousMode !== SceneMode_default.MORPHING || transitioner._morphCancelled) {
transitioner._morphCancelled = false;
Cartesian3_default.clone(camera3D.position, camera.position);
Cartesian3_default.clone(camera3D.direction, camera.direction);
Cartesian3_default.clone(camera3D.up, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.normalize(camera.right, camera.right);
camera.frustum = camera3D.frustum.clone();
}
const frustum = camera.frustum;
if (scene.frameState.useLogDepth) {
frustum.near = 0.1;
frustum.far = 1e10;
}
const wasMorphing = defined_default(transitioner._completeMorph);
transitioner._completeMorph = void 0;
scene.camera.update(scene.mode);
transitioner._scene.morphComplete.raiseEvent(
transitioner,
transitioner._previousMode,
SceneMode_default.SCENE3D,
wasMorphing
);
};
}
function complete2DCallback(camera2D) {
return function(transitioner) {
const scene = transitioner._scene;
scene._mode = SceneMode_default.SCENE2D;
scene.morphTime = SceneMode_default.getMorphTime(SceneMode_default.SCENE2D);
destroyMorphHandler(transitioner);
const camera = scene.camera;
Cartesian3_default.clone(camera2D.position, camera.position);
camera.position.z = scene.ellipsoid.maximumRadius * 2;
Cartesian3_default.clone(camera2D.direction, camera.direction);
Cartesian3_default.clone(camera2D.up, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.normalize(camera.right, camera.right);
camera.frustum = camera2D.frustum.clone();
const wasMorphing = defined_default(transitioner._completeMorph);
transitioner._completeMorph = void 0;
scene.camera.update(scene.mode);
transitioner._scene.morphComplete.raiseEvent(
transitioner,
transitioner._previousMode,
SceneMode_default.SCENE2D,
wasMorphing
);
};
}
function completeColumbusViewCallback(cameraCV) {
return function(transitioner) {
const scene = transitioner._scene;
scene._mode = SceneMode_default.COLUMBUS_VIEW;
scene.morphTime = SceneMode_default.getMorphTime(SceneMode_default.COLUMBUS_VIEW);
destroyMorphHandler(transitioner);
const camera = scene.camera;
if (transitioner._previousModeMode !== SceneMode_default.MORPHING || transitioner._morphCancelled) {
transitioner._morphCancelled = false;
Cartesian3_default.clone(cameraCV.position, camera.position);
Cartesian3_default.clone(cameraCV.direction, camera.direction);
Cartesian3_default.clone(cameraCV.up, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.normalize(camera.right, camera.right);
}
const frustum = camera.frustum;
if (scene.frameState.useLogDepth) {
frustum.near = 0.1;
frustum.far = 1e10;
}
const wasMorphing = defined_default(transitioner._completeMorph);
transitioner._completeMorph = void 0;
scene.camera.update(scene.mode);
transitioner._scene.morphComplete.raiseEvent(
transitioner,
transitioner._previousMode,
SceneMode_default.COLUMBUS_VIEW,
wasMorphing
);
};
}
var SceneTransitioner_default = SceneTransitioner;
// packages/engine/Source/Scene/ScreenSpaceCameraController.js
var import_InlineWorkers1118 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/CameraEventAggregator.js
var import_InlineWorkers1116 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/CameraEventType.js
var import_InlineWorkers1115 = __toESM(require_InlineWorkers(), 1);
var CameraEventType = {
/**
* A left mouse button press followed by moving the mouse and releasing the button.
*
* @type {number}
* @constant
*/
LEFT_DRAG: 0,
/**
* A right mouse button press followed by moving the mouse and releasing the button.
*
* @type {number}
* @constant
*/
RIGHT_DRAG: 1,
/**
* A middle mouse button press followed by moving the mouse and releasing the button.
*
* @type {number}
* @constant
*/
MIDDLE_DRAG: 2,
/**
* Scrolling the middle mouse button.
*
* @type {number}
* @constant
*/
WHEEL: 3,
/**
* A two-finger touch on a touch surface.
*
* @type {number}
* @constant
*/
PINCH: 4
};
var CameraEventType_default = Object.freeze(CameraEventType);
// packages/engine/Source/Scene/CameraEventAggregator.js
function getKey2(type, modifier) {
let key = `${type}`;
if (defined_default(modifier)) {
key += `+${modifier}`;
}
return key;
}
function clonePinchMovement(pinchMovement, result) {
Cartesian2_default.clone(
pinchMovement.distance.startPosition,
result.distance.startPosition
);
Cartesian2_default.clone(
pinchMovement.distance.endPosition,
result.distance.endPosition
);
Cartesian2_default.clone(
pinchMovement.angleAndHeight.startPosition,
result.angleAndHeight.startPosition
);
Cartesian2_default.clone(
pinchMovement.angleAndHeight.endPosition,
result.angleAndHeight.endPosition
);
}
function listenToPinch(aggregator, modifier, canvas) {
const key = getKey2(CameraEventType_default.PINCH, modifier);
const update8 = aggregator._update;
const isDown = aggregator._isDown;
const eventStartPosition = aggregator._eventStartPosition;
const pressTime = aggregator._pressTime;
const releaseTime = aggregator._releaseTime;
update8[key] = true;
isDown[key] = false;
eventStartPosition[key] = new Cartesian2_default();
let movement = aggregator._movement[key];
if (!defined_default(movement)) {
movement = aggregator._movement[key] = {};
}
movement.distance = {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default()
};
movement.angleAndHeight = {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default()
};
movement.prevAngle = 0;
aggregator._eventHandler.setInputAction(
function(event) {
aggregator._buttonsDown++;
isDown[key] = true;
pressTime[key] = /* @__PURE__ */ new Date();
Cartesian2_default.lerp(
event.position1,
event.position2,
0.5,
eventStartPosition[key]
);
},
ScreenSpaceEventType_default.PINCH_START,
modifier
);
aggregator._eventHandler.setInputAction(
function() {
aggregator._buttonsDown = Math.max(aggregator._buttonsDown - 1, 0);
isDown[key] = false;
releaseTime[key] = /* @__PURE__ */ new Date();
},
ScreenSpaceEventType_default.PINCH_END,
modifier
);
aggregator._eventHandler.setInputAction(
function(mouseMovement) {
if (isDown[key]) {
if (!update8[key]) {
Cartesian2_default.clone(
mouseMovement.distance.endPosition,
movement.distance.endPosition
);
Cartesian2_default.clone(
mouseMovement.angleAndHeight.endPosition,
movement.angleAndHeight.endPosition
);
} else {
clonePinchMovement(mouseMovement, movement);
update8[key] = false;
movement.prevAngle = movement.angleAndHeight.startPosition.x;
}
let angle = movement.angleAndHeight.endPosition.x;
const prevAngle = movement.prevAngle;
const TwoPI = Math.PI * 2;
while (angle >= prevAngle + Math.PI) {
angle -= TwoPI;
}
while (angle < prevAngle - Math.PI) {
angle += TwoPI;
}
movement.angleAndHeight.endPosition.x = -angle * canvas.clientWidth / 12;
movement.angleAndHeight.startPosition.x = -prevAngle * canvas.clientWidth / 12;
}
},
ScreenSpaceEventType_default.PINCH_MOVE,
modifier
);
}
function listenToWheel(aggregator, modifier) {
const key = getKey2(CameraEventType_default.WHEEL, modifier);
const pressTime = aggregator._pressTime;
const releaseTime = aggregator._releaseTime;
const update8 = aggregator._update;
update8[key] = true;
let movement = aggregator._movement[key];
if (!defined_default(movement)) {
movement = aggregator._movement[key] = {};
}
let lastMovement = aggregator._lastMovement[key];
if (!defined_default(lastMovement)) {
lastMovement = aggregator._lastMovement[key] = {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default(),
valid: false
};
}
movement.startPosition = new Cartesian2_default();
Cartesian2_default.clone(Cartesian2_default.ZERO, movement.startPosition);
movement.endPosition = new Cartesian2_default();
aggregator._eventHandler.setInputAction(
function(delta) {
const arcLength = 7.5 * Math_default.toRadians(delta);
pressTime[key] = releaseTime[key] = /* @__PURE__ */ new Date();
movement.endPosition.x = 0;
movement.endPosition.y = arcLength;
Cartesian2_default.clone(movement.endPosition, lastMovement.endPosition);
lastMovement.valid = true;
update8[key] = false;
},
ScreenSpaceEventType_default.WHEEL,
modifier
);
}
function listenMouseButtonDownUp(aggregator, modifier, type) {
const key = getKey2(type, modifier);
const isDown = aggregator._isDown;
const eventStartPosition = aggregator._eventStartPosition;
const pressTime = aggregator._pressTime;
isDown[key] = false;
eventStartPosition[key] = new Cartesian2_default();
let lastMovement = aggregator._lastMovement[key];
if (!defined_default(lastMovement)) {
lastMovement = aggregator._lastMovement[key] = {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default(),
valid: false
};
}
let down;
let up;
if (type === CameraEventType_default.LEFT_DRAG) {
down = ScreenSpaceEventType_default.LEFT_DOWN;
up = ScreenSpaceEventType_default.LEFT_UP;
} else if (type === CameraEventType_default.RIGHT_DRAG) {
down = ScreenSpaceEventType_default.RIGHT_DOWN;
up = ScreenSpaceEventType_default.RIGHT_UP;
} else if (type === CameraEventType_default.MIDDLE_DRAG) {
down = ScreenSpaceEventType_default.MIDDLE_DOWN;
up = ScreenSpaceEventType_default.MIDDLE_UP;
}
aggregator._eventHandler.setInputAction(
function(event) {
aggregator._buttonsDown++;
lastMovement.valid = false;
isDown[key] = true;
pressTime[key] = /* @__PURE__ */ new Date();
Cartesian2_default.clone(event.position, eventStartPosition[key]);
},
down,
modifier
);
aggregator._eventHandler.setInputAction(
function() {
cancelMouseDownAction(getKey2(type, void 0), aggregator);
for (const modifier2 of Object.values(KeyboardEventModifier_default)) {
const cancelKey = getKey2(type, modifier2);
cancelMouseDownAction(cancelKey, aggregator);
}
},
up,
modifier
);
}
function cancelMouseDownAction(cancelKey, aggregator) {
const releaseTime = aggregator._releaseTime;
const isDown = aggregator._isDown;
if (isDown[cancelKey]) {
aggregator._buttonsDown = Math.max(aggregator._buttonsDown - 1, 0);
}
isDown[cancelKey] = false;
releaseTime[cancelKey] = /* @__PURE__ */ new Date();
}
function cloneMouseMovement(mouseMovement, result) {
Cartesian2_default.clone(mouseMovement.startPosition, result.startPosition);
Cartesian2_default.clone(mouseMovement.endPosition, result.endPosition);
}
function refreshMouseDownStatus(type, modifier, aggregator) {
const isDown = aggregator._isDown;
let anyButtonIsDown = false;
const currentKey = getKey2(type, modifier);
for (const [downKey, downValue] of Object.entries(isDown)) {
if (downKey.startsWith(type) && downValue && downKey !== currentKey) {
anyButtonIsDown = true;
cancelMouseDownAction(downKey, aggregator);
}
}
if (!anyButtonIsDown) {
return;
}
const pressTime = aggregator._pressTime;
let lastMovement = aggregator._lastMovement[currentKey];
if (!defined_default(lastMovement)) {
lastMovement = aggregator._lastMovement[currentKey] = {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default(),
valid: false
};
}
aggregator._buttonsDown++;
lastMovement.valid = false;
isDown[currentKey] = true;
pressTime[currentKey] = /* @__PURE__ */ new Date();
}
function listenMouseMove(aggregator, modifier) {
const update8 = aggregator._update;
const movement = aggregator._movement;
const lastMovement = aggregator._lastMovement;
const isDown = aggregator._isDown;
for (const typeName in CameraEventType_default) {
if (CameraEventType_default.hasOwnProperty(typeName)) {
const type = CameraEventType_default[typeName];
if (defined_default(type)) {
const key = getKey2(type, modifier);
update8[key] = true;
if (!defined_default(aggregator._lastMovement[key])) {
aggregator._lastMovement[key] = {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default(),
valid: false
};
}
if (!defined_default(aggregator._movement[key])) {
aggregator._movement[key] = {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default()
};
}
}
}
}
aggregator._eventHandler.setInputAction(
function(mouseMovement) {
for (const typeName in CameraEventType_default) {
if (CameraEventType_default.hasOwnProperty(typeName)) {
const type = CameraEventType_default[typeName];
if (defined_default(type)) {
const key = getKey2(type, modifier);
refreshMouseDownStatus(type, modifier, aggregator);
if (isDown[key]) {
if (!update8[key]) {
Cartesian2_default.clone(
mouseMovement.endPosition,
movement[key].endPosition
);
} else {
cloneMouseMovement(movement[key], lastMovement[key]);
lastMovement[key].valid = true;
cloneMouseMovement(mouseMovement, movement[key]);
update8[key] = false;
}
}
}
}
}
Cartesian2_default.clone(
mouseMovement.endPosition,
aggregator._currentMousePosition
);
},
ScreenSpaceEventType_default.MOUSE_MOVE,
modifier
);
}
function CameraEventAggregator(canvas) {
if (!defined_default(canvas)) {
throw new DeveloperError_default("canvas is required.");
}
this._eventHandler = new ScreenSpaceEventHandler_default(canvas);
this._update = {};
this._movement = {};
this._lastMovement = {};
this._isDown = {};
this._eventStartPosition = {};
this._pressTime = {};
this._releaseTime = {};
this._buttonsDown = 0;
this._currentMousePosition = new Cartesian2_default();
listenToWheel(this, void 0);
listenToPinch(this, void 0, canvas);
listenMouseButtonDownUp(this, void 0, CameraEventType_default.LEFT_DRAG);
listenMouseButtonDownUp(this, void 0, CameraEventType_default.RIGHT_DRAG);
listenMouseButtonDownUp(this, void 0, CameraEventType_default.MIDDLE_DRAG);
listenMouseMove(this, void 0);
for (const modifierName in KeyboardEventModifier_default) {
if (KeyboardEventModifier_default.hasOwnProperty(modifierName)) {
const modifier = KeyboardEventModifier_default[modifierName];
if (defined_default(modifier)) {
listenToWheel(this, modifier);
listenToPinch(this, modifier, canvas);
listenMouseButtonDownUp(this, modifier, CameraEventType_default.LEFT_DRAG);
listenMouseButtonDownUp(this, modifier, CameraEventType_default.RIGHT_DRAG);
listenMouseButtonDownUp(this, modifier, CameraEventType_default.MIDDLE_DRAG);
listenMouseMove(this, modifier);
}
}
}
}
Object.defineProperties(CameraEventAggregator.prototype, {
/**
* Gets the current mouse position.
* @memberof CameraEventAggregator.prototype
* @type {Cartesian2}
*/
currentMousePosition: {
get: function() {
return this._currentMousePosition;
}
},
/**
* Gets whether any mouse button is down, a touch has started, or the wheel has been moved.
* @memberof CameraEventAggregator.prototype
* @type {boolean}
*/
anyButtonDown: {
get: function() {
const wheelMoved = !this._update[getKey2(CameraEventType_default.WHEEL)] || !this._update[getKey2(CameraEventType_default.WHEEL, KeyboardEventModifier_default.SHIFT)] || !this._update[getKey2(CameraEventType_default.WHEEL, KeyboardEventModifier_default.CTRL)] || !this._update[getKey2(CameraEventType_default.WHEEL, KeyboardEventModifier_default.ALT)];
return this._buttonsDown > 0 || wheelMoved;
}
}
});
CameraEventAggregator.prototype.isMoving = function(type, modifier) {
if (!defined_default(type)) {
throw new DeveloperError_default("type is required.");
}
const key = getKey2(type, modifier);
return !this._update[key];
};
CameraEventAggregator.prototype.getMovement = function(type, modifier) {
if (!defined_default(type)) {
throw new DeveloperError_default("type is required.");
}
const key = getKey2(type, modifier);
const movement = this._movement[key];
return movement;
};
CameraEventAggregator.prototype.getLastMovement = function(type, modifier) {
if (!defined_default(type)) {
throw new DeveloperError_default("type is required.");
}
const key = getKey2(type, modifier);
const lastMovement = this._lastMovement[key];
if (lastMovement.valid) {
return lastMovement;
}
return void 0;
};
CameraEventAggregator.prototype.isButtonDown = function(type, modifier) {
if (!defined_default(type)) {
throw new DeveloperError_default("type is required.");
}
const key = getKey2(type, modifier);
return this._isDown[key];
};
CameraEventAggregator.prototype.getStartMousePosition = function(type, modifier) {
if (!defined_default(type)) {
throw new DeveloperError_default("type is required.");
}
if (type === CameraEventType_default.WHEEL) {
return this._currentMousePosition;
}
const key = getKey2(type, modifier);
return this._eventStartPosition[key];
};
CameraEventAggregator.prototype.getButtonPressTime = function(type, modifier) {
if (!defined_default(type)) {
throw new DeveloperError_default("type is required.");
}
const key = getKey2(type, modifier);
return this._pressTime[key];
};
CameraEventAggregator.prototype.getButtonReleaseTime = function(type, modifier) {
if (!defined_default(type)) {
throw new DeveloperError_default("type is required.");
}
const key = getKey2(type, modifier);
return this._releaseTime[key];
};
CameraEventAggregator.prototype.reset = function() {
for (const name in this._update) {
if (this._update.hasOwnProperty(name)) {
this._update[name] = true;
}
}
};
CameraEventAggregator.prototype.isDestroyed = function() {
return false;
};
CameraEventAggregator.prototype.destroy = function() {
this._eventHandler = this._eventHandler && this._eventHandler.destroy();
return destroyObject_default(this);
};
var CameraEventAggregator_default = CameraEventAggregator;
// packages/engine/Source/Scene/TweenCollection.js
var import_InlineWorkers1117 = __toESM(require_InlineWorkers(), 1);
function Tween2(tweens, tweenjs, startObject, stopObject, duration, delay2, easingFunction, update8, complete, cancel) {
this._tweens = tweens;
this._tweenjs = tweenjs;
this._startObject = clone_default(startObject);
this._stopObject = clone_default(stopObject);
this._duration = duration;
this._delay = delay2;
this._easingFunction = easingFunction;
this._update = update8;
this._complete = complete;
this.cancel = cancel;
this.needsStart = true;
}
Object.defineProperties(Tween2.prototype, {
/**
* An object with properties for initial values of the tween. The properties of this object are changed during the tween's animation.
* @memberof Tween.prototype
*
* @type {object}
* @readonly
*/
startObject: {
get: function() {
return this._startObject;
}
},
/**
* An object with properties for the final values of the tween.
* @memberof Tween.prototype
*
* @type {object}
* @readonly
*/
stopObject: {
get: function() {
return this._stopObject;
}
},
/**
* The duration, in seconds, for the tween. The tween is automatically removed from the collection when it stops.
* @memberof Tween.prototype
*
* @type {number}
* @readonly
*/
duration: {
get: function() {
return this._duration;
}
},
/**
* The delay, in seconds, before the tween starts animating.
* @memberof Tween.prototype
*
* @type {number}
* @readonly
*/
delay: {
get: function() {
return this._delay;
}
},
/**
* Determines the curve for animtion.
* @memberof Tween.prototype
*
* @type {EasingFunction}
* @readonly
*/
easingFunction: {
get: function() {
return this._easingFunction;
}
},
/**
* The callback to call at each animation update (usually tied to the a rendered frame).
* @memberof Tween.prototype
*
* @type {TweenCollection.TweenUpdateCallback}
* @readonly
*/
update: {
get: function() {
return this._update;
}
},
/**
* The callback to call when the tween finishes animating.
* @memberof Tween.prototype
*
* @type {TweenCollection.TweenCompleteCallback}
* @readonly
*/
complete: {
get: function() {
return this._complete;
}
},
/**
* @memberof Tween.prototype
*
* @private
*/
tweenjs: {
get: function() {
return this._tweenjs;
}
}
});
Tween2.prototype.cancelTween = function() {
this._tweens.remove(this);
};
function TweenCollection() {
this._tweens = [];
}
Object.defineProperties(TweenCollection.prototype, {
/**
* The number of tweens in the collection.
* @memberof TweenCollection.prototype
*
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._tweens.length;
}
}
});
TweenCollection.prototype.add = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
if (!defined_default(options.startObject) || !defined_default(options.stopObject)) {
throw new DeveloperError_default(
"options.startObject and options.stopObject are required."
);
}
if (!defined_default(options.duration) || options.duration < 0) {
throw new DeveloperError_default(
"options.duration is required and must be positive."
);
}
if (options.duration === 0) {
if (defined_default(options.complete)) {
options.complete();
}
return new Tween2(this);
}
const duration = options.duration / TimeConstants_default.SECONDS_PER_MILLISECOND;
const delayInSeconds = options.delay ?? 0;
const delay2 = delayInSeconds / TimeConstants_default.SECONDS_PER_MILLISECOND;
const easingFunction = options.easingFunction ?? EasingFunction_default.LINEAR_NONE;
const value = options.startObject;
const tweenjs = new Tween(value);
tweenjs.to(clone_default(options.stopObject), duration);
tweenjs.delay(delay2);
tweenjs.easing(easingFunction);
if (defined_default(options.update)) {
tweenjs.onUpdate(function() {
options.update(value);
});
}
tweenjs.onComplete(options.complete ?? null);
tweenjs.repeat(options._repeat ?? 0);
const tween = new Tween2(
this,
tweenjs,
options.startObject,
options.stopObject,
options.duration,
delayInSeconds,
easingFunction,
options.update,
options.complete,
options.cancel
);
this._tweens.push(tween);
return tween;
};
TweenCollection.prototype.addProperty = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const object2 = options.object;
const property = options.property;
const startValue = options.startValue;
const stopValue = options.stopValue;
if (!defined_default(object2) || !defined_default(options.property)) {
throw new DeveloperError_default(
"options.object and options.property are required."
);
}
if (!defined_default(object2[property])) {
throw new DeveloperError_default(
"options.object must have the specified property."
);
}
if (!defined_default(startValue) || !defined_default(stopValue)) {
throw new DeveloperError_default(
"options.startValue and options.stopValue are required."
);
}
function update8(value) {
object2[property] = value.value;
}
return this.add({
startObject: {
value: startValue
},
stopObject: {
value: stopValue
},
duration: options.duration ?? 3,
delay: options.delay,
easingFunction: options.easingFunction,
update: update8,
complete: options.complete,
cancel: options.cancel,
_repeat: options._repeat
});
};
TweenCollection.prototype.addAlpha = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const material = options.material;
if (!defined_default(material)) {
throw new DeveloperError_default("options.material is required.");
}
const properties = [];
for (const property in material.uniforms) {
if (material.uniforms.hasOwnProperty(property) && defined_default(material.uniforms[property]) && defined_default(material.uniforms[property].alpha)) {
properties.push(property);
}
}
if (properties.length === 0) {
throw new DeveloperError_default(
"material has no properties with alpha components."
);
}
function update8(value) {
const length2 = properties.length;
for (let i = 0; i < length2; ++i) {
material.uniforms[properties[i]].alpha = value.alpha;
}
}
return this.add({
startObject: {
alpha: options.startValue ?? 0
// Default to fade in
},
stopObject: {
alpha: options.stopValue ?? 1
},
duration: options.duration ?? 3,
delay: options.delay,
easingFunction: options.easingFunction,
update: update8,
complete: options.complete,
cancel: options.cancel
});
};
TweenCollection.prototype.addOffsetIncrement = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const material = options.material;
if (!defined_default(material)) {
throw new DeveloperError_default("material is required.");
}
if (!defined_default(material.uniforms.offset)) {
throw new DeveloperError_default("material.uniforms must have an offset property.");
}
const uniforms = material.uniforms;
return this.addProperty({
object: uniforms,
property: "offset",
startValue: uniforms.offset,
stopValue: uniforms.offset + 1,
duration: options.duration,
delay: options.delay,
easingFunction: options.easingFunction,
update: options.update,
cancel: options.cancel,
_repeat: Infinity
});
};
TweenCollection.prototype.remove = function(tween) {
if (!defined_default(tween)) {
return false;
}
const index = this._tweens.indexOf(tween);
if (index !== -1) {
tween.tweenjs.stop();
if (defined_default(tween.cancel)) {
tween.cancel();
}
this._tweens.splice(index, 1);
return true;
}
return false;
};
TweenCollection.prototype.removeAll = function() {
const tweens = this._tweens;
for (let i = 0; i < tweens.length; ++i) {
const tween = tweens[i];
tween.tweenjs.stop();
if (defined_default(tween.cancel)) {
tween.cancel();
}
}
tweens.length = 0;
};
TweenCollection.prototype.contains = function(tween) {
return defined_default(tween) && this._tweens.indexOf(tween) !== -1;
};
TweenCollection.prototype.get = function(index) {
if (!defined_default(index)) {
throw new DeveloperError_default("index is required.");
}
return this._tweens[index];
};
TweenCollection.prototype.update = function(time) {
const tweens = this._tweens;
let i = 0;
time = defined_default(time) ? time / TimeConstants_default.SECONDS_PER_MILLISECOND : getTimestamp_default();
while (i < tweens.length) {
const tween = tweens[i];
const tweenjs = tween.tweenjs;
if (tween.needsStart) {
tween.needsStart = false;
tweenjs.start(time);
} else if (tweenjs.update(time)) {
i++;
} else {
tweenjs.stop();
tweens.splice(i, 1);
}
}
};
var TweenCollection_default = TweenCollection;
// packages/engine/Source/Scene/ScreenSpaceCameraController.js
function ScreenSpaceCameraController(scene) {
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required.");
}
this.enableInputs = true;
this.enableTranslate = true;
this.enableZoom = true;
this.enableRotate = true;
this.enableTilt = true;
this.enableLook = true;
this.inertiaSpin = 0.9;
this.inertiaTranslate = 0.9;
this.inertiaZoom = 0.8;
this.maximumMovementRatio = 0.1;
this.bounceAnimationTime = 3;
this.minimumZoomDistance = 1;
this.maximumZoomDistance = Number.POSITIVE_INFINITY;
this.zoomFactor = 5;
this.translateEventTypes = CameraEventType_default.LEFT_DRAG;
this.zoomEventTypes = [
CameraEventType_default.RIGHT_DRAG,
CameraEventType_default.WHEEL,
CameraEventType_default.PINCH
];
this.rotateEventTypes = CameraEventType_default.LEFT_DRAG;
this.tiltEventTypes = [
CameraEventType_default.MIDDLE_DRAG,
CameraEventType_default.PINCH,
{
eventType: CameraEventType_default.LEFT_DRAG,
modifier: KeyboardEventModifier_default.CTRL
},
{
eventType: CameraEventType_default.RIGHT_DRAG,
modifier: KeyboardEventModifier_default.CTRL
}
];
this.lookEventTypes = {
eventType: CameraEventType_default.LEFT_DRAG,
modifier: KeyboardEventModifier_default.SHIFT
};
const ellipsoid = scene.ellipsoid ?? Ellipsoid_default.default;
this.minimumPickingTerrainHeight = Ellipsoid_default.WGS84.equals(ellipsoid) ? 15e4 : ellipsoid.minimumRadius * 0.025;
this._minimumPickingTerrainHeight = this.minimumPickingTerrainHeight;
this.minimumPickingTerrainDistanceWithInertia = Ellipsoid_default.WGS84.equals(
ellipsoid
) ? 4e3 : ellipsoid.minimumRadius * 63e-5;
this.minimumCollisionTerrainHeight = Ellipsoid_default.WGS84.equals(ellipsoid) ? 15e3 : ellipsoid.minimumRadius * 25e-4;
this._minimumCollisionTerrainHeight = this.minimumCollisionTerrainHeight;
this.minimumTrackBallHeight = Ellipsoid_default.WGS84.equals(ellipsoid) ? 75e5 : ellipsoid.minimumRadius * 1.175;
this._minimumTrackBallHeight = this.minimumTrackBallHeight;
this.enableCollisionDetection = true;
this.maximumTiltAngle = void 0;
this._scene = scene;
this._globe = void 0;
this._ellipsoid = ellipsoid;
this._lastGlobeHeight = 0;
this._aggregator = new CameraEventAggregator_default(scene.canvas);
this._lastInertiaSpinMovement = void 0;
this._lastInertiaZoomMovement = void 0;
this._lastInertiaTranslateMovement = void 0;
this._lastInertiaTiltMovement = void 0;
this._inertiaDisablers = {
_lastInertiaZoomMovement: [
"_lastInertiaSpinMovement",
"_lastInertiaTranslateMovement",
"_lastInertiaTiltMovement"
],
_lastInertiaTiltMovement: [
"_lastInertiaSpinMovement",
"_lastInertiaTranslateMovement"
]
};
this._tweens = new TweenCollection_default();
this._tween = void 0;
this._horizontalRotationAxis = void 0;
this._tiltCenterMousePosition = new Cartesian2_default(-1, -1);
this._tiltCenter = new Cartesian3_default();
this._rotateMousePosition = new Cartesian2_default(-1, -1);
this._rotateStartPosition = new Cartesian3_default();
this._strafeStartPosition = new Cartesian3_default();
this._strafeMousePosition = new Cartesian2_default();
this._strafeEndMousePosition = new Cartesian2_default();
this._zoomMouseStart = new Cartesian2_default(-1, -1);
this._zoomWorldPosition = new Cartesian3_default();
this._useZoomWorldPosition = false;
this._panLastMousePosition = new Cartesian2_default();
this._panLastWorldPosition = new Cartesian3_default();
this._tiltCVOffMap = false;
this._looking = false;
this._rotating = false;
this._strafing = false;
this._zoomingOnVector = false;
this._zoomingUnderground = false;
this._rotatingZoom = false;
this._adjustedHeightForTerrain = false;
this._cameraUnderground = false;
const projection = scene.mapProjection;
this._maxCoord = projection.project(
new Cartographic_default(Math.PI, Math_default.PI_OVER_TWO)
);
this._rotateFactor = void 0;
this._rotateRateRangeAdjustment = void 0;
this._maximumRotateRate = 1.77;
this._minimumRotateRate = 1 / 5e3;
this._minimumZoomRate = 20;
this._maximumZoomRate = 5906376272e3;
this._minimumUndergroundPickDistance = 2e3;
this._maximumUndergroundPickDistance = 1e4;
}
function decay(time, coefficient) {
if (time < 0) {
return 0;
}
const tau = (1 - coefficient) * 25;
return Math.exp(-tau * time);
}
function sameMousePosition(movement) {
return Cartesian2_default.equalsEpsilon(
movement.startPosition,
movement.endPosition,
Math_default.EPSILON14
);
}
var inertiaMaxClickTimeThreshold = 0.4;
function maintainInertia(aggregator, type, modifier, decayCoef, action, object2, lastMovementName) {
let movementState = object2[lastMovementName];
if (!defined_default(movementState)) {
movementState = object2[lastMovementName] = {
startPosition: new Cartesian2_default(),
endPosition: new Cartesian2_default(),
motion: new Cartesian2_default(),
inertiaEnabled: true
};
}
const ts = aggregator.getButtonPressTime(type, modifier);
const tr = aggregator.getButtonReleaseTime(type, modifier);
const threshold = ts && tr && (tr.getTime() - ts.getTime()) / 1e3;
const now2 = /* @__PURE__ */ new Date();
const fromNow = tr && (now2.getTime() - tr.getTime()) / 1e3;
if (ts && tr && threshold < inertiaMaxClickTimeThreshold) {
const d = decay(fromNow, decayCoef);
const lastMovement = aggregator.getLastMovement(type, modifier);
if (!defined_default(lastMovement) || sameMousePosition(lastMovement) || !movementState.inertiaEnabled) {
return;
}
movementState.motion.x = (lastMovement.endPosition.x - lastMovement.startPosition.x) * 0.5;
movementState.motion.y = (lastMovement.endPosition.y - lastMovement.startPosition.y) * 0.5;
movementState.startPosition = Cartesian2_default.clone(
lastMovement.startPosition,
movementState.startPosition
);
movementState.endPosition = Cartesian2_default.multiplyByScalar(
movementState.motion,
d,
movementState.endPosition
);
movementState.endPosition = Cartesian2_default.add(
movementState.startPosition,
movementState.endPosition,
movementState.endPosition
);
if (isNaN(movementState.endPosition.x) || isNaN(movementState.endPosition.y) || Cartesian2_default.distance(
movementState.startPosition,
movementState.endPosition
) < 0.5) {
return;
}
if (!aggregator.isButtonDown(type, modifier)) {
const startPosition = aggregator.getStartMousePosition(type, modifier);
action(object2, startPosition, movementState);
}
}
}
function activateInertia(controller, inertiaStateName) {
if (defined_default(inertiaStateName)) {
let movementState = controller[inertiaStateName];
if (defined_default(movementState)) {
movementState.inertiaEnabled = true;
}
const inertiasToDisable = controller._inertiaDisablers[inertiaStateName];
if (defined_default(inertiasToDisable)) {
const length2 = inertiasToDisable.length;
for (let i = 0; i < length2; ++i) {
movementState = controller[inertiasToDisable[i]];
if (defined_default(movementState)) {
movementState.inertiaEnabled = false;
}
}
}
}
}
var scratchEventTypeArray = [];
function reactToInput(controller, enabled, eventTypes, action, inertiaConstant, inertiaStateName) {
if (!defined_default(eventTypes)) {
return;
}
const aggregator = controller._aggregator;
if (!Array.isArray(eventTypes)) {
scratchEventTypeArray[0] = eventTypes;
eventTypes = scratchEventTypeArray;
}
const length2 = eventTypes.length;
for (let i = 0; i < length2; ++i) {
const eventType = eventTypes[i];
const type = defined_default(eventType.eventType) ? eventType.eventType : eventType;
const modifier = eventType.modifier;
const movement = aggregator.isMoving(type, modifier) && aggregator.getMovement(type, modifier);
const startPosition = aggregator.getStartMousePosition(type, modifier);
if (controller.enableInputs && enabled) {
if (movement) {
action(controller, startPosition, movement);
activateInertia(controller, inertiaStateName);
} else if (inertiaConstant < 1) {
maintainInertia(
aggregator,
type,
modifier,
inertiaConstant,
action,
controller,
inertiaStateName
);
}
}
}
}
var scratchZoomPickRay = new Ray_default();
var scratchPickCartesian = new Cartesian3_default();
var scratchZoomOffset = new Cartesian2_default();
var scratchZoomDirection = new Cartesian3_default();
var scratchCenterPixel = new Cartesian2_default();
var scratchCenterPosition = new Cartesian3_default();
var scratchPositionNormal3 = new Cartesian3_default();
var scratchPickNormal = new Cartesian3_default();
var scratchZoomAxis = new Cartesian3_default();
var scratchCameraPositionNormal = new Cartesian3_default();
var scratchTargetNormal = new Cartesian3_default();
var scratchCameraPosition2 = new Cartesian3_default();
var scratchCameraUpNormal = new Cartesian3_default();
var scratchCameraRightNormal = new Cartesian3_default();
var scratchForwardNormal = new Cartesian3_default();
var scratchPositionToTarget = new Cartesian3_default();
var scratchPositionToTargetNormal = new Cartesian3_default();
var scratchPan = new Cartesian3_default();
var scratchCenterMovement = new Cartesian3_default();
var scratchCenter10 = new Cartesian3_default();
var scratchCartesian31 = new Cartesian3_default();
var scratchCartesianTwo = new Cartesian3_default();
var scratchCartesianThree = new Cartesian3_default();
var scratchZoomViewOptions = {
orientation: new HeadingPitchRoll_default()
};
function handleZoom(object2, startPosition, movement, zoomFactor, distanceMeasure, unitPositionDotDirection) {
let percentage = 1;
if (defined_default(unitPositionDotDirection)) {
percentage = Math_default.clamp(
Math.abs(unitPositionDotDirection),
0.25,
1
);
}
const diff = movement.endPosition.y - movement.startPosition.y;
const approachingSurface = diff > 0;
const minHeight = approachingSurface ? object2.minimumZoomDistance * percentage : 0;
const maxHeight = object2.maximumZoomDistance;
const minDistance = distanceMeasure - minHeight;
let zoomRate = zoomFactor * minDistance;
zoomRate = Math_default.clamp(
zoomRate,
object2._minimumZoomRate,
object2._maximumZoomRate
);
let rangeWindowRatio = diff / object2._scene.canvas.clientHeight;
rangeWindowRatio = Math.min(rangeWindowRatio, object2.maximumMovementRatio);
let distance2 = zoomRate * rangeWindowRatio;
if (object2.enableCollisionDetection || object2.minimumZoomDistance === 0 || !defined_default(object2._globe)) {
if (distance2 > 0 && Math.abs(distanceMeasure - minHeight) < 1) {
return;
}
if (distance2 < 0 && Math.abs(distanceMeasure - maxHeight) < 1) {
return;
}
if (distanceMeasure - distance2 < minHeight) {
distance2 = distanceMeasure - minHeight - 1;
} else if (distanceMeasure - distance2 > maxHeight) {
distance2 = distanceMeasure - maxHeight;
}
}
const scene = object2._scene;
const camera = scene.camera;
const mode2 = scene.mode;
const orientation = scratchZoomViewOptions.orientation;
orientation.heading = camera.heading;
orientation.pitch = camera.pitch;
orientation.roll = camera.roll;
const sameStartPosition = movement.inertiaEnabled ?? Cartesian2_default.equals(startPosition, object2._zoomMouseStart);
let zoomingOnVector = object2._zoomingOnVector;
let rotatingZoom = object2._rotatingZoom;
let pickedPosition;
if (!sameStartPosition) {
object2._zoomMouseStart = Cartesian2_default.clone(
startPosition,
object2._zoomMouseStart
);
if (defined_default(object2._globe) && mode2 === SceneMode_default.SCENE2D) {
pickedPosition = camera.getPickRay(
startPosition,
scratchZoomPickRay
).origin;
pickedPosition = Cartesian3_default.fromElements(
pickedPosition.y,
pickedPosition.z,
pickedPosition.x
);
} else if (defined_default(object2._globe)) {
pickedPosition = pickPosition(
object2,
startPosition,
scratchPickCartesian
);
}
if (defined_default(pickedPosition)) {
object2._useZoomWorldPosition = true;
object2._zoomWorldPosition = Cartesian3_default.clone(
pickedPosition,
object2._zoomWorldPosition
);
} else {
object2._useZoomWorldPosition = false;
}
zoomingOnVector = object2._zoomingOnVector = false;
rotatingZoom = object2._rotatingZoom = false;
object2._zoomingUnderground = object2._cameraUnderground;
}
if (!object2._useZoomWorldPosition) {
camera.zoomIn(distance2);
return;
}
let zoomOnVector = mode2 === SceneMode_default.COLUMBUS_VIEW;
if (camera.positionCartographic.height < 2e6) {
rotatingZoom = true;
}
if (!sameStartPosition || rotatingZoom) {
if (mode2 === SceneMode_default.SCENE2D) {
const worldPosition = object2._zoomWorldPosition;
const endPosition = camera.position;
if (!Cartesian3_default.equals(worldPosition, endPosition) && camera.positionCartographic.height < object2._maxCoord.x * 2) {
const savedX = camera.position.x;
const direction2 = Cartesian3_default.subtract(
worldPosition,
endPosition,
scratchZoomDirection
);
Cartesian3_default.normalize(direction2, direction2);
const d = Cartesian3_default.distance(worldPosition, endPosition) * distance2 / (camera.getMagnitude() * 0.5);
camera.move(direction2, d * 0.5);
if (camera.position.x < 0 && savedX > 0 || camera.position.x > 0 && savedX < 0) {
pickedPosition = camera.getPickRay(
startPosition,
scratchZoomPickRay
).origin;
pickedPosition = Cartesian3_default.fromElements(
pickedPosition.y,
pickedPosition.z,
pickedPosition.x
);
object2._zoomWorldPosition = Cartesian3_default.clone(
pickedPosition,
object2._zoomWorldPosition
);
}
}
} else if (mode2 === SceneMode_default.SCENE3D) {
const cameraPositionNormal = Cartesian3_default.normalize(
camera.position,
scratchCameraPositionNormal
);
if (object2._cameraUnderground || object2._zoomingUnderground || camera.positionCartographic.height < 3e3 && Math.abs(Cartesian3_default.dot(camera.direction, cameraPositionNormal)) < 0.6) {
zoomOnVector = true;
} else {
const canvas = scene.canvas;
const centerPixel = scratchCenterPixel;
centerPixel.x = canvas.clientWidth / 2;
centerPixel.y = canvas.clientHeight / 2;
const centerPosition = pickPosition(
object2,
centerPixel,
scratchCenterPosition
);
if (!defined_default(centerPosition)) {
zoomOnVector = true;
} else if (camera.positionCartographic.height < 1e6) {
if (Cartesian3_default.dot(camera.direction, cameraPositionNormal) >= -0.5) {
zoomOnVector = true;
} else {
const cameraPosition = scratchCameraPosition2;
Cartesian3_default.clone(camera.position, cameraPosition);
const target = object2._zoomWorldPosition;
let targetNormal = scratchTargetNormal;
targetNormal = Cartesian3_default.normalize(target, targetNormal);
if (Cartesian3_default.dot(targetNormal, cameraPositionNormal) < 0) {
return;
}
const center = scratchCenter10;
const forward = scratchForwardNormal;
Cartesian3_default.clone(camera.direction, forward);
Cartesian3_default.add(
cameraPosition,
Cartesian3_default.multiplyByScalar(forward, 1e3, scratchCartesian31),
center
);
const positionToTarget = scratchPositionToTarget;
const positionToTargetNormal = scratchPositionToTargetNormal;
Cartesian3_default.subtract(target, cameraPosition, positionToTarget);
Cartesian3_default.normalize(positionToTarget, positionToTargetNormal);
const alphaDot = Cartesian3_default.dot(
cameraPositionNormal,
positionToTargetNormal
);
if (alphaDot >= 0) {
object2._zoomMouseStart.x = -1;
return;
}
const alpha = Math.acos(-alphaDot);
const cameraDistance = Cartesian3_default.magnitude(cameraPosition);
const targetDistance = Cartesian3_default.magnitude(target);
const remainingDistance = cameraDistance - distance2;
const positionToTargetDistance = Cartesian3_default.magnitude(positionToTarget);
const gamma = Math.asin(
Math_default.clamp(
positionToTargetDistance / targetDistance * Math.sin(alpha),
-1,
1
)
);
const delta = Math.asin(
Math_default.clamp(
remainingDistance / targetDistance * Math.sin(alpha),
-1,
1
)
);
const beta = gamma - delta + alpha;
const up = scratchCameraUpNormal;
Cartesian3_default.normalize(cameraPosition, up);
let right = scratchCameraRightNormal;
right = Cartesian3_default.cross(positionToTargetNormal, up, right);
right = Cartesian3_default.normalize(right, right);
Cartesian3_default.normalize(
Cartesian3_default.cross(up, right, scratchCartesian31),
forward
);
Cartesian3_default.multiplyByScalar(
Cartesian3_default.normalize(center, scratchCartesian31),
Cartesian3_default.magnitude(center) - distance2,
center
);
Cartesian3_default.normalize(cameraPosition, cameraPosition);
Cartesian3_default.multiplyByScalar(
cameraPosition,
remainingDistance,
cameraPosition
);
const pMid = scratchPan;
Cartesian3_default.multiplyByScalar(
Cartesian3_default.add(
Cartesian3_default.multiplyByScalar(
up,
Math.cos(beta) - 1,
scratchCartesianTwo
),
Cartesian3_default.multiplyByScalar(
forward,
Math.sin(beta),
scratchCartesianThree
),
scratchCartesian31
),
remainingDistance,
pMid
);
Cartesian3_default.add(cameraPosition, pMid, cameraPosition);
Cartesian3_default.normalize(center, up);
Cartesian3_default.normalize(
Cartesian3_default.cross(up, right, scratchCartesian31),
forward
);
const cMid = scratchCenterMovement;
Cartesian3_default.multiplyByScalar(
Cartesian3_default.add(
Cartesian3_default.multiplyByScalar(
up,
Math.cos(beta) - 1,
scratchCartesianTwo
),
Cartesian3_default.multiplyByScalar(
forward,
Math.sin(beta),
scratchCartesianThree
),
scratchCartesian31
),
Cartesian3_default.magnitude(center),
cMid
);
Cartesian3_default.add(center, cMid, center);
Cartesian3_default.clone(cameraPosition, camera.position);
Cartesian3_default.normalize(
Cartesian3_default.subtract(center, cameraPosition, scratchCartesian31),
camera.direction
);
Cartesian3_default.clone(camera.direction, camera.direction);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.cross(camera.right, camera.direction, camera.up);
camera.setView(scratchZoomViewOptions);
return;
}
} else {
const positionNormal = Cartesian3_default.normalize(
centerPosition,
scratchPositionNormal3
);
const pickedNormal = Cartesian3_default.normalize(
object2._zoomWorldPosition,
scratchPickNormal
);
const dotProduct = Cartesian3_default.dot(pickedNormal, positionNormal);
if (dotProduct > 0 && dotProduct < 1) {
const angle = Math_default.acosClamped(dotProduct);
const axis = Cartesian3_default.cross(
pickedNormal,
positionNormal,
scratchZoomAxis
);
const denom = Math.abs(angle) > Math_default.toRadians(20) ? camera.positionCartographic.height * 0.75 : camera.positionCartographic.height - distance2;
const scalar = distance2 / denom;
camera.rotate(axis, angle * scalar);
}
}
}
}
object2._rotatingZoom = !zoomOnVector;
}
if (!sameStartPosition && zoomOnVector || zoomingOnVector) {
let ray;
const zoomMouseStart = SceneTransforms_default.worldToWindowCoordinates(
scene,
object2._zoomWorldPosition,
scratchZoomOffset
);
if (mode2 !== SceneMode_default.COLUMBUS_VIEW && Cartesian2_default.equals(startPosition, object2._zoomMouseStart) && defined_default(zoomMouseStart)) {
ray = camera.getPickRay(zoomMouseStart, scratchZoomPickRay);
} else {
ray = camera.getPickRay(startPosition, scratchZoomPickRay);
}
const rayDirection = ray.direction;
if (mode2 === SceneMode_default.COLUMBUS_VIEW || mode2 === SceneMode_default.SCENE2D) {
Cartesian3_default.fromElements(
rayDirection.y,
rayDirection.z,
rayDirection.x,
rayDirection
);
}
camera.move(rayDirection, distance2);
object2._zoomingOnVector = true;
} else {
camera.zoomIn(distance2);
}
if (!object2._cameraUnderground) {
camera.setView(scratchZoomViewOptions);
}
}
var translate2DStart = new Ray_default();
var translate2DEnd = new Ray_default();
var scratchTranslateP0 = new Cartesian3_default();
function translate2D(controller, startPosition, movement) {
const scene = controller._scene;
const camera = scene.camera;
let start = camera.getPickRay(
movement.startPosition,
translate2DStart
).origin;
let end = camera.getPickRay(movement.endPosition, translate2DEnd).origin;
start = Cartesian3_default.fromElements(start.y, start.z, start.x, start);
end = Cartesian3_default.fromElements(end.y, end.z, end.x, end);
const direction2 = Cartesian3_default.subtract(start, end, scratchTranslateP0);
const distance2 = Cartesian3_default.magnitude(direction2);
if (distance2 > 0) {
Cartesian3_default.normalize(direction2, direction2);
camera.move(direction2, distance2);
}
}
function zoom2D2(controller, startPosition, movement) {
if (defined_default(movement.distance)) {
movement = movement.distance;
}
const scene = controller._scene;
const camera = scene.camera;
handleZoom(
controller,
startPosition,
movement,
controller.zoomFactor,
camera.getMagnitude()
);
}
var twist2DStart = new Cartesian2_default();
var twist2DEnd = new Cartesian2_default();
function twist2D(controller, startPosition, movement) {
if (defined_default(movement.angleAndHeight)) {
singleAxisTwist2D(controller, startPosition, movement.angleAndHeight);
return;
}
const scene = controller._scene;
const camera = scene.camera;
const canvas = scene.canvas;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
let start = twist2DStart;
start.x = 2 / width * movement.startPosition.x - 1;
start.y = 2 / height * (height - movement.startPosition.y) - 1;
start = Cartesian2_default.normalize(start, start);
let end = twist2DEnd;
end.x = 2 / width * movement.endPosition.x - 1;
end.y = 2 / height * (height - movement.endPosition.y) - 1;
end = Cartesian2_default.normalize(end, end);
let startTheta = Math_default.acosClamped(start.x);
if (start.y < 0) {
startTheta = Math_default.TWO_PI - startTheta;
}
let endTheta = Math_default.acosClamped(end.x);
if (end.y < 0) {
endTheta = Math_default.TWO_PI - endTheta;
}
const theta = endTheta - startTheta;
camera.twistRight(theta);
}
function singleAxisTwist2D(controller, startPosition, movement) {
let rotateRate = controller._rotateFactor * controller._rotateRateRangeAdjustment;
if (rotateRate > controller._maximumRotateRate) {
rotateRate = controller._maximumRotateRate;
}
if (rotateRate < controller._minimumRotateRate) {
rotateRate = controller._minimumRotateRate;
}
const scene = controller._scene;
const camera = scene.camera;
const canvas = scene.canvas;
let phiWindowRatio = (movement.endPosition.x - movement.startPosition.x) / canvas.clientWidth;
phiWindowRatio = Math.min(phiWindowRatio, controller.maximumMovementRatio);
const deltaPhi = rotateRate * phiWindowRatio * Math.PI * 4;
camera.twistRight(deltaPhi);
}
function update2D(controller) {
const rotatable2D = controller._scene.mapMode2D === MapMode2D_default.ROTATE;
if (!Matrix4_default.equals(Matrix4_default.IDENTITY, controller._scene.camera.transform)) {
reactToInput(
controller,
controller.enableZoom,
controller.zoomEventTypes,
zoom2D2,
controller.inertiaZoom,
"_lastInertiaZoomMovement"
);
if (rotatable2D) {
reactToInput(
controller,
controller.enableRotate,
controller.translateEventTypes,
twist2D,
controller.inertiaSpin,
"_lastInertiaSpinMovement"
);
}
} else {
reactToInput(
controller,
controller.enableTranslate,
controller.translateEventTypes,
translate2D,
controller.inertiaTranslate,
"_lastInertiaTranslateMovement"
);
reactToInput(
controller,
controller.enableZoom,
controller.zoomEventTypes,
zoom2D2,
controller.inertiaZoom,
"_lastInertiaZoomMovement"
);
if (rotatable2D) {
reactToInput(
controller,
controller.enableRotate,
controller.tiltEventTypes,
twist2D,
controller.inertiaSpin,
"_lastInertiaTiltMovement"
);
}
}
}
var pickGlobeScratchRay = new Ray_default();
var scratchDepthIntersection2 = new Cartesian3_default();
var scratchRayIntersection2 = new Cartesian3_default();
function pickPosition(controller, mousePosition, result) {
const scene = controller._scene;
const globe = controller._globe;
const camera = scene.camera;
let depthIntersection;
if (scene.pickPositionSupported) {
depthIntersection = scene.pickPositionWorldCoordinates(
mousePosition,
scratchDepthIntersection2
);
}
if (!defined_default(globe)) {
return Cartesian3_default.clone(depthIntersection, result);
}
const cullBackFaces = !controller._cameraUnderground;
const ray = camera.getPickRay(mousePosition, pickGlobeScratchRay);
const rayIntersection = globe.pickWorldCoordinates(
ray,
scene,
cullBackFaces,
scratchRayIntersection2
);
const pickDistance = defined_default(depthIntersection) ? Cartesian3_default.distance(depthIntersection, camera.positionWC) : Number.POSITIVE_INFINITY;
const rayDistance = defined_default(rayIntersection) ? Cartesian3_default.distance(rayIntersection, camera.positionWC) : Number.POSITIVE_INFINITY;
if (pickDistance < rayDistance) {
return Cartesian3_default.clone(depthIntersection, result);
}
return Cartesian3_default.clone(rayIntersection, result);
}
var scratchDistanceCartographic = new Cartographic_default();
function getDistanceFromSurface(controller) {
const ellipsoid = controller._ellipsoid;
const scene = controller._scene;
const camera = scene.camera;
const mode2 = scene.mode;
let height = 0;
if (mode2 === SceneMode_default.SCENE3D) {
const cartographic2 = ellipsoid.cartesianToCartographic(
camera.position,
scratchDistanceCartographic
);
if (defined_default(cartographic2)) {
height = cartographic2.height;
}
} else {
height = camera.position.z;
}
const globeHeight = controller._scene.globeHeight ?? 0;
const distanceFromSurface = Math.abs(globeHeight - height);
return distanceFromSurface;
}
var scratchSurfaceNormal2 = new Cartesian3_default();
function getZoomDistanceUnderground(controller, ray) {
const origin = ray.origin;
const direction2 = ray.direction;
const distanceFromSurface = getDistanceFromSurface(controller);
const surfaceNormal = Cartesian3_default.normalize(origin, scratchSurfaceNormal2);
let strength = Math.abs(Cartesian3_default.dot(surfaceNormal, direction2));
strength = Math.max(strength, 0.5) * 2;
return distanceFromSurface * strength;
}
function getTiltCenterUnderground(controller, ray, pickedPosition, result) {
let distance2 = Cartesian3_default.distance(ray.origin, pickedPosition);
const distanceFromSurface = getDistanceFromSurface(controller);
const maximumDistance = Math_default.clamp(
distanceFromSurface * 5,
controller._minimumUndergroundPickDistance,
controller._maximumUndergroundPickDistance
);
if (distance2 > maximumDistance) {
distance2 = Math.min(distance2, distanceFromSurface / 5);
distance2 = Math.max(distance2, 100);
}
return Ray_default.getPoint(ray, distance2, result);
}
function getStrafeStartPositionUnderground(controller, ray, pickedPosition, result) {
let distance2;
if (!defined_default(pickedPosition)) {
distance2 = getDistanceFromSurface(controller);
} else {
distance2 = Cartesian3_default.distance(ray.origin, pickedPosition);
if (distance2 > controller._maximumUndergroundPickDistance) {
distance2 = getDistanceFromSurface(controller);
}
}
return Ray_default.getPoint(ray, distance2, result);
}
var scratchInertialDelta = new Cartesian2_default();
function continueStrafing(controller, movement) {
const originalEndPosition = movement.endPosition;
const inertialDelta = Cartesian2_default.subtract(
movement.endPosition,
movement.startPosition,
scratchInertialDelta
);
const endPosition = controller._strafeEndMousePosition;
Cartesian2_default.add(endPosition, inertialDelta, endPosition);
movement.endPosition = endPosition;
strafe(controller, movement, controller._strafeStartPosition);
movement.endPosition = originalEndPosition;
}
var translateCVStartRay = new Ray_default();
var translateCVEndRay = new Ray_default();
var translateCVStartPos = new Cartesian3_default();
var translateCVEndPos = new Cartesian3_default();
var translateCVDifference = new Cartesian3_default();
var translateCVOrigin = new Cartesian3_default();
var translateCVPlane = new Plane_default(Cartesian3_default.UNIT_X, 0);
var translateCVStartMouse = new Cartesian2_default();
var translateCVEndMouse = new Cartesian2_default();
function translateCV(controller, startPosition, movement) {
if (!Cartesian3_default.equals(startPosition, controller._translateMousePosition)) {
controller._looking = false;
}
if (!Cartesian3_default.equals(startPosition, controller._strafeMousePosition)) {
controller._strafing = false;
}
if (controller._looking) {
look3D(controller, startPosition, movement);
return;
}
if (controller._strafing) {
continueStrafing(controller, movement);
return;
}
const scene = controller._scene;
const camera = scene.camera;
const cameraUnderground = controller._cameraUnderground;
const startMouse = Cartesian2_default.clone(
movement.startPosition,
translateCVStartMouse
);
const endMouse = Cartesian2_default.clone(movement.endPosition, translateCVEndMouse);
let startRay = camera.getPickRay(startMouse, translateCVStartRay);
const origin = Cartesian3_default.clone(Cartesian3_default.ZERO, translateCVOrigin);
const normal2 = Cartesian3_default.UNIT_X;
let globePos;
if (camera.position.z < controller._minimumPickingTerrainHeight) {
globePos = pickPosition(controller, startMouse, translateCVStartPos);
if (defined_default(globePos)) {
origin.x = globePos.x;
}
}
if (cameraUnderground || origin.x > camera.position.z && defined_default(globePos)) {
let pickPosition2 = globePos;
if (cameraUnderground) {
pickPosition2 = getStrafeStartPositionUnderground(
controller,
startRay,
globePos,
translateCVStartPos
);
}
Cartesian2_default.clone(startPosition, controller._strafeMousePosition);
Cartesian2_default.clone(startPosition, controller._strafeEndMousePosition);
Cartesian3_default.clone(pickPosition2, controller._strafeStartPosition);
controller._strafing = true;
strafe(controller, movement, controller._strafeStartPosition);
return;
}
const plane = Plane_default.fromPointNormal(origin, normal2, translateCVPlane);
startRay = camera.getPickRay(startMouse, translateCVStartRay);
const startPlanePos = IntersectionTests_default.rayPlane(
startRay,
plane,
translateCVStartPos
);
const endRay = camera.getPickRay(endMouse, translateCVEndRay);
const endPlanePos = IntersectionTests_default.rayPlane(
endRay,
plane,
translateCVEndPos
);
if (!defined_default(startPlanePos) || !defined_default(endPlanePos)) {
controller._looking = true;
look3D(controller, startPosition, movement);
Cartesian2_default.clone(startPosition, controller._translateMousePosition);
return;
}
const diff = Cartesian3_default.subtract(
startPlanePos,
endPlanePos,
translateCVDifference
);
const temp = diff.x;
diff.x = diff.y;
diff.y = diff.z;
diff.z = temp;
const mag = Cartesian3_default.magnitude(diff);
if (mag > Math_default.EPSILON6) {
Cartesian3_default.normalize(diff, diff);
camera.move(diff, mag);
}
}
var rotateCVWindowPos = new Cartesian2_default();
var rotateCVWindowRay = new Ray_default();
var rotateCVCenter = new Cartesian3_default();
var rotateCVVerticalCenter = new Cartesian3_default();
var rotateCVTransform = new Matrix4_default();
var rotateCVVerticalTransform = new Matrix4_default();
var rotateCVOrigin = new Cartesian3_default();
var rotateCVPlane = new Plane_default(Cartesian3_default.UNIT_X, 0);
var rotateCVCartesian3 = new Cartesian3_default();
var rotateCVCart = new Cartographic_default();
var rotateCVOldTransform = new Matrix4_default();
var rotateCVQuaternion = new Quaternion_default();
var rotateCVMatrix = new Matrix3_default();
var tilt3DCartesian3 = new Cartesian3_default();
function rotateCV(controller, startPosition, movement) {
if (defined_default(movement.angleAndHeight)) {
movement = movement.angleAndHeight;
}
if (!Cartesian2_default.equals(startPosition, controller._tiltCenterMousePosition)) {
controller._tiltCVOffMap = false;
controller._looking = false;
}
if (controller._looking) {
look3D(controller, startPosition, movement);
return;
}
const scene = controller._scene;
const camera = scene.camera;
if (controller._tiltCVOffMap || !controller.onMap() || Math.abs(camera.position.z) > controller._minimumPickingTerrainHeight) {
controller._tiltCVOffMap = true;
rotateCVOnPlane(controller, startPosition, movement);
} else {
rotateCVOnTerrain(controller, startPosition, movement);
}
}
function rotateCVOnPlane(controller, startPosition, movement) {
const scene = controller._scene;
const camera = scene.camera;
const canvas = scene.canvas;
const windowPosition = rotateCVWindowPos;
windowPosition.x = canvas.clientWidth / 2;
windowPosition.y = canvas.clientHeight / 2;
const ray = camera.getPickRay(windowPosition, rotateCVWindowRay);
const normal2 = Cartesian3_default.UNIT_X;
const position = ray.origin;
const direction2 = ray.direction;
let scalar;
const normalDotDirection = Cartesian3_default.dot(normal2, direction2);
if (Math.abs(normalDotDirection) > Math_default.EPSILON6) {
scalar = -Cartesian3_default.dot(normal2, position) / normalDotDirection;
}
if (!defined_default(scalar) || scalar <= 0) {
controller._looking = true;
look3D(controller, startPosition, movement);
Cartesian2_default.clone(startPosition, controller._tiltCenterMousePosition);
return;
}
const center = Cartesian3_default.multiplyByScalar(direction2, scalar, rotateCVCenter);
Cartesian3_default.add(position, center, center);
const projection = scene.mapProjection;
const ellipsoid = projection.ellipsoid;
Cartesian3_default.fromElements(center.y, center.z, center.x, center);
const cart = projection.unproject(center, rotateCVCart);
ellipsoid.cartographicToCartesian(cart, center);
const transform3 = Transforms_default.eastNorthUpToFixedFrame(
center,
ellipsoid,
rotateCVTransform
);
const oldGlobe = controller._globe;
const oldEllipsoid = controller._ellipsoid;
controller._globe = void 0;
controller._ellipsoid = Ellipsoid_default.UNIT_SPHERE;
controller._rotateFactor = 1;
controller._rotateRateRangeAdjustment = 1;
const oldTransform = Matrix4_default.clone(camera.transform, rotateCVOldTransform);
camera._setTransform(transform3);
rotate3D(controller, startPosition, movement, Cartesian3_default.UNIT_Z);
camera._setTransform(oldTransform);
controller._globe = oldGlobe;
controller._ellipsoid = oldEllipsoid;
const radius = oldEllipsoid.maximumRadius;
controller._rotateFactor = 1 / radius;
controller._rotateRateRangeAdjustment = radius;
}
function rotateCVOnTerrain(controller, startPosition, movement) {
const scene = controller._scene;
const camera = scene.camera;
const cameraUnderground = controller._cameraUnderground;
let center;
let ray;
const normal2 = Cartesian3_default.UNIT_X;
if (Cartesian2_default.equals(startPosition, controller._tiltCenterMousePosition)) {
center = Cartesian3_default.clone(controller._tiltCenter, rotateCVCenter);
} else {
if (camera.position.z < controller._minimumPickingTerrainHeight) {
center = pickPosition(controller, startPosition, rotateCVCenter);
}
if (!defined_default(center)) {
ray = camera.getPickRay(startPosition, rotateCVWindowRay);
const position = ray.origin;
const direction2 = ray.direction;
let scalar;
const normalDotDirection = Cartesian3_default.dot(normal2, direction2);
if (Math.abs(normalDotDirection) > Math_default.EPSILON6) {
scalar = -Cartesian3_default.dot(normal2, position) / normalDotDirection;
}
if (!defined_default(scalar) || scalar <= 0) {
controller._looking = true;
look3D(controller, startPosition, movement);
Cartesian2_default.clone(startPosition, controller._tiltCenterMousePosition);
return;
}
center = Cartesian3_default.multiplyByScalar(direction2, scalar, rotateCVCenter);
Cartesian3_default.add(position, center, center);
}
if (cameraUnderground) {
if (!defined_default(ray)) {
ray = camera.getPickRay(startPosition, rotateCVWindowRay);
}
getTiltCenterUnderground(controller, ray, center, center);
}
Cartesian2_default.clone(startPosition, controller._tiltCenterMousePosition);
Cartesian3_default.clone(center, controller._tiltCenter);
}
const canvas = scene.canvas;
const windowPosition = rotateCVWindowPos;
windowPosition.x = canvas.clientWidth / 2;
windowPosition.y = controller._tiltCenterMousePosition.y;
ray = camera.getPickRay(windowPosition, rotateCVWindowRay);
const origin = Cartesian3_default.clone(Cartesian3_default.ZERO, rotateCVOrigin);
origin.x = center.x;
const plane = Plane_default.fromPointNormal(origin, normal2, rotateCVPlane);
const verticalCenter = IntersectionTests_default.rayPlane(
ray,
plane,
rotateCVVerticalCenter
);
const projection = camera._projection;
const ellipsoid = projection.ellipsoid;
Cartesian3_default.fromElements(center.y, center.z, center.x, center);
let cart = projection.unproject(center, rotateCVCart);
ellipsoid.cartographicToCartesian(cart, center);
const transform3 = Transforms_default.eastNorthUpToFixedFrame(
center,
ellipsoid,
rotateCVTransform
);
let verticalTransform;
if (defined_default(verticalCenter)) {
Cartesian3_default.fromElements(
verticalCenter.y,
verticalCenter.z,
verticalCenter.x,
verticalCenter
);
cart = projection.unproject(verticalCenter, rotateCVCart);
ellipsoid.cartographicToCartesian(cart, verticalCenter);
verticalTransform = Transforms_default.eastNorthUpToFixedFrame(
verticalCenter,
ellipsoid,
rotateCVVerticalTransform
);
} else {
verticalTransform = transform3;
}
const oldGlobe = controller._globe;
const oldEllipsoid = controller._ellipsoid;
controller._globe = void 0;
controller._ellipsoid = Ellipsoid_default.UNIT_SPHERE;
controller._rotateFactor = 1;
controller._rotateRateRangeAdjustment = 1;
let constrainedAxis = Cartesian3_default.UNIT_Z;
const oldTransform = Matrix4_default.clone(camera.transform, rotateCVOldTransform);
camera._setTransform(transform3);
const tangent = Cartesian3_default.cross(
Cartesian3_default.UNIT_Z,
Cartesian3_default.normalize(camera.position, rotateCVCartesian3),
rotateCVCartesian3
);
const dot2 = Cartesian3_default.dot(camera.right, tangent);
rotate3D(controller, startPosition, movement, constrainedAxis, false, true);
camera._setTransform(verticalTransform);
if (dot2 < 0) {
const movementDelta = movement.startPosition.y - movement.endPosition.y;
if (cameraUnderground && movementDelta < 0 || !cameraUnderground && movementDelta > 0) {
constrainedAxis = void 0;
}
const oldConstrainedAxis = camera.constrainedAxis;
camera.constrainedAxis = void 0;
rotate3D(controller, startPosition, movement, constrainedAxis, true, false);
camera.constrainedAxis = oldConstrainedAxis;
} else {
rotate3D(controller, startPosition, movement, constrainedAxis, true, false);
}
if (defined_default(camera.constrainedAxis)) {
const right = Cartesian3_default.cross(
camera.direction,
camera.constrainedAxis,
tilt3DCartesian3
);
if (!Cartesian3_default.equalsEpsilon(right, Cartesian3_default.ZERO, Math_default.EPSILON6)) {
if (Cartesian3_default.dot(right, camera.right) < 0) {
Cartesian3_default.negate(right, right);
}
Cartesian3_default.cross(right, camera.direction, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.normalize(camera.up, camera.up);
Cartesian3_default.normalize(camera.right, camera.right);
}
}
camera._setTransform(oldTransform);
controller._globe = oldGlobe;
controller._ellipsoid = oldEllipsoid;
const radius = oldEllipsoid.maximumRadius;
controller._rotateFactor = 1 / radius;
controller._rotateRateRangeAdjustment = radius;
const originalPosition = Cartesian3_default.clone(
camera.positionWC,
rotateCVCartesian3
);
if (controller.enableCollisionDetection) {
adjustHeightForTerrain(controller, true);
}
if (!Cartesian3_default.equals(camera.positionWC, originalPosition)) {
camera._setTransform(verticalTransform);
camera.worldToCameraCoordinatesPoint(originalPosition, originalPosition);
const magSqrd = Cartesian3_default.magnitudeSquared(originalPosition);
if (Cartesian3_default.magnitudeSquared(camera.position) > magSqrd) {
Cartesian3_default.normalize(camera.position, camera.position);
Cartesian3_default.multiplyByScalar(
camera.position,
Math.sqrt(magSqrd),
camera.position
);
}
const angle = Cartesian3_default.angleBetween(originalPosition, camera.position);
const axis = Cartesian3_default.cross(
originalPosition,
camera.position,
originalPosition
);
Cartesian3_default.normalize(axis, axis);
const quaternion = Quaternion_default.fromAxisAngle(
axis,
angle,
rotateCVQuaternion
);
const rotation = Matrix3_default.fromQuaternion(quaternion, rotateCVMatrix);
Matrix3_default.multiplyByVector(rotation, camera.direction, camera.direction);
Matrix3_default.multiplyByVector(rotation, camera.up, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.cross(camera.right, camera.direction, camera.up);
camera._setTransform(oldTransform);
}
}
var zoomCVWindowPos = new Cartesian2_default();
var zoomCVWindowRay = new Ray_default();
var zoomCVIntersection = new Cartesian3_default();
function zoomCV(controller, startPosition, movement) {
if (defined_default(movement.distance)) {
movement = movement.distance;
}
const scene = controller._scene;
const camera = scene.camera;
const canvas = scene.canvas;
const cameraUnderground = controller._cameraUnderground;
let windowPosition;
if (cameraUnderground) {
windowPosition = startPosition;
} else {
windowPosition = zoomCVWindowPos;
windowPosition.x = canvas.clientWidth / 2;
windowPosition.y = canvas.clientHeight / 2;
}
const ray = camera.getPickRay(windowPosition, zoomCVWindowRay);
const position = ray.origin;
const direction2 = ray.direction;
const height = camera.position.z;
let intersection;
if (height < controller._minimumPickingTerrainHeight) {
intersection = pickPosition(controller, windowPosition, zoomCVIntersection);
}
let distance2;
if (defined_default(intersection)) {
distance2 = Cartesian3_default.distance(position, intersection);
}
if (cameraUnderground) {
const distanceUnderground = getZoomDistanceUnderground(
controller,
ray,
height
);
if (defined_default(distance2)) {
distance2 = Math.min(distance2, distanceUnderground);
} else {
distance2 = distanceUnderground;
}
}
if (!defined_default(distance2)) {
const normal2 = Cartesian3_default.UNIT_X;
distance2 = -Cartesian3_default.dot(normal2, position) / Cartesian3_default.dot(normal2, direction2);
}
handleZoom(
controller,
startPosition,
movement,
controller.zoomFactor,
distance2
);
}
function updateCV(controller) {
const scene = controller._scene;
const camera = scene.camera;
if (!Matrix4_default.equals(Matrix4_default.IDENTITY, camera.transform)) {
reactToInput(
controller,
controller.enableRotate,
controller.rotateEventTypes,
rotate3D,
controller.inertiaSpin,
"_lastInertiaSpinMovement"
);
reactToInput(
controller,
controller.enableZoom,
controller.zoomEventTypes,
zoom3D2,
controller.inertiaZoom,
"_lastInertiaZoomMovement"
);
} else {
const tweens = controller._tweens;
if (controller._aggregator.anyButtonDown) {
tweens.removeAll();
}
reactToInput(
controller,
controller.enableTilt,
controller.tiltEventTypes,
rotateCV,
controller.inertiaSpin,
"_lastInertiaTiltMovement"
);
reactToInput(
controller,
controller.enableTranslate,
controller.translateEventTypes,
translateCV,
controller.inertiaTranslate,
"_lastInertiaTranslateMovement"
);
reactToInput(
controller,
controller.enableZoom,
controller.zoomEventTypes,
zoomCV,
controller.inertiaZoom,
"_lastInertiaZoomMovement"
);
reactToInput(
controller,
controller.enableLook,
controller.lookEventTypes,
look3D
);
if (!controller._aggregator.anyButtonDown && !tweens.contains(controller._tween)) {
const tween = camera.createCorrectPositionTween(
controller.bounceAnimationTime
);
if (defined_default(tween)) {
controller._tween = tweens.add(tween);
}
}
tweens.update();
}
}
var scratchStrafeRay = new Ray_default();
var scratchStrafePlane = new Plane_default(Cartesian3_default.UNIT_X, 0);
var scratchStrafeIntersection = new Cartesian3_default();
var scratchStrafeDirection = new Cartesian3_default();
function strafe(controller, movement, strafeStartPosition) {
const scene = controller._scene;
const camera = scene.camera;
const ray = camera.getPickRay(movement.endPosition, scratchStrafeRay);
let direction2 = Cartesian3_default.clone(camera.direction, scratchStrafeDirection);
if (scene.mode === SceneMode_default.COLUMBUS_VIEW) {
Cartesian3_default.fromElements(direction2.z, direction2.x, direction2.y, direction2);
}
const plane = Plane_default.fromPointNormal(
strafeStartPosition,
direction2,
scratchStrafePlane
);
const intersection = IntersectionTests_default.rayPlane(
ray,
plane,
scratchStrafeIntersection
);
if (!defined_default(intersection)) {
return;
}
direction2 = Cartesian3_default.subtract(strafeStartPosition, intersection, direction2);
if (scene.mode === SceneMode_default.COLUMBUS_VIEW) {
Cartesian3_default.fromElements(direction2.y, direction2.z, direction2.x, direction2);
}
Cartesian3_default.add(camera.position, direction2, camera.position);
}
var spin3DPick = new Cartesian3_default();
var scratchCartographic25 = new Cartographic_default();
var scratchRadii3 = new Cartesian3_default();
var scratchEllipsoid15 = new Ellipsoid_default();
var scratchLookUp = new Cartesian3_default();
var scratchNormal8 = new Cartesian3_default();
var scratchMousePosition = new Cartesian3_default();
function spin3D(controller, startPosition, movement) {
const scene = controller._scene;
const camera = scene.camera;
const cameraUnderground = controller._cameraUnderground;
let ellipsoid = controller._ellipsoid;
if (!Matrix4_default.equals(camera.transform, Matrix4_default.IDENTITY)) {
rotate3D(controller, startPosition, movement);
return;
}
let magnitude;
let radii;
const up = ellipsoid.geodeticSurfaceNormal(camera.position, scratchLookUp);
if (Cartesian2_default.equals(startPosition, controller._rotateMousePosition)) {
if (controller._looking) {
look3D(controller, startPosition, movement, up);
} else if (controller._rotating) {
rotate3D(controller, startPosition, movement);
} else if (controller._strafing) {
continueStrafing(controller, movement);
} else {
if (Cartesian3_default.magnitude(camera.position) < Cartesian3_default.magnitude(controller._rotateStartPosition)) {
return;
}
magnitude = Cartesian3_default.magnitude(controller._rotateStartPosition);
radii = scratchRadii3;
radii.x = radii.y = radii.z = magnitude;
ellipsoid = Ellipsoid_default.fromCartesian3(radii, scratchEllipsoid15);
pan3D(controller, startPosition, movement, ellipsoid);
}
return;
}
controller._looking = false;
controller._rotating = false;
controller._strafing = false;
const height = ellipsoid.cartesianToCartographic(
camera.positionWC,
scratchCartographic25
).height;
const globe = controller._globe;
if (defined_default(globe) && height < controller._minimumPickingTerrainHeight) {
const mousePos = pickPosition(
controller,
movement.startPosition,
scratchMousePosition
);
if (defined_default(mousePos)) {
let strafing = false;
const ray = camera.getPickRay(
movement.startPosition,
pickGlobeScratchRay
);
if (cameraUnderground) {
strafing = true;
getStrafeStartPositionUnderground(controller, ray, mousePos, mousePos);
} else {
const normal2 = ellipsoid.geodeticSurfaceNormal(mousePos, scratchNormal8);
const tangentPick = Math.abs(Cartesian3_default.dot(ray.direction, normal2)) < 0.05;
if (tangentPick) {
strafing = true;
} else {
strafing = Cartesian3_default.magnitude(camera.position) < Cartesian3_default.magnitude(mousePos);
}
}
if (strafing) {
Cartesian2_default.clone(startPosition, controller._strafeEndMousePosition);
Cartesian3_default.clone(mousePos, controller._strafeStartPosition);
controller._strafing = true;
strafe(controller, movement, controller._strafeStartPosition);
} else {
magnitude = Cartesian3_default.magnitude(mousePos);
radii = scratchRadii3;
radii.x = radii.y = radii.z = magnitude;
ellipsoid = Ellipsoid_default.fromCartesian3(radii, scratchEllipsoid15);
pan3D(controller, startPosition, movement, ellipsoid);
Cartesian3_default.clone(mousePos, controller._rotateStartPosition);
}
} else {
controller._looking = true;
look3D(controller, startPosition, movement, up);
}
} else if (defined_default(
camera.pickEllipsoid(
movement.startPosition,
controller._ellipsoid,
spin3DPick
)
)) {
pan3D(controller, startPosition, movement, controller._ellipsoid);
Cartesian3_default.clone(spin3DPick, controller._rotateStartPosition);
} else if (height > controller._minimumTrackBallHeight) {
controller._rotating = true;
rotate3D(controller, startPosition, movement);
} else {
controller._looking = true;
look3D(controller, startPosition, movement, up);
}
Cartesian2_default.clone(startPosition, controller._rotateMousePosition);
}
function rotate3D(controller, startPosition, movement, constrainedAxis, rotateOnlyVertical, rotateOnlyHorizontal) {
rotateOnlyVertical = rotateOnlyVertical ?? false;
rotateOnlyHorizontal = rotateOnlyHorizontal ?? false;
const scene = controller._scene;
const camera = scene.camera;
const canvas = scene.canvas;
const oldAxis = camera.constrainedAxis;
if (defined_default(constrainedAxis)) {
camera.constrainedAxis = constrainedAxis;
}
const rho = Cartesian3_default.magnitude(camera.position);
let rotateRate = controller._rotateFactor * (rho - controller._rotateRateRangeAdjustment);
if (rotateRate > controller._maximumRotateRate) {
rotateRate = controller._maximumRotateRate;
}
if (rotateRate < controller._minimumRotateRate) {
rotateRate = controller._minimumRotateRate;
}
let phiWindowRatio = (movement.startPosition.x - movement.endPosition.x) / canvas.clientWidth;
let thetaWindowRatio = (movement.startPosition.y - movement.endPosition.y) / canvas.clientHeight;
phiWindowRatio = Math.min(phiWindowRatio, controller.maximumMovementRatio);
thetaWindowRatio = Math.min(
thetaWindowRatio,
controller.maximumMovementRatio
);
const deltaPhi = rotateRate * phiWindowRatio * Math.PI * 2;
let deltaTheta = rotateRate * thetaWindowRatio * Math.PI;
if (defined_default(constrainedAxis) && defined_default(controller.maximumTiltAngle)) {
const maximumTiltAngle = controller.maximumTiltAngle;
const dotProduct = Cartesian3_default.dot(camera.direction, constrainedAxis);
const tilt = Math.PI - Math.acos(dotProduct) + deltaTheta;
if (tilt > maximumTiltAngle) {
deltaTheta -= tilt - maximumTiltAngle;
}
}
if (!rotateOnlyVertical) {
camera.rotateRight(deltaPhi);
}
if (!rotateOnlyHorizontal) {
camera.rotateUp(deltaTheta);
}
camera.constrainedAxis = oldAxis;
}
var pan3DP0 = Cartesian4_default.clone(Cartesian4_default.UNIT_W);
var pan3DP1 = Cartesian4_default.clone(Cartesian4_default.UNIT_W);
var pan3DTemp0 = new Cartesian3_default();
var pan3DTemp1 = new Cartesian3_default();
var pan3DTemp2 = new Cartesian3_default();
var pan3DTemp3 = new Cartesian3_default();
var pan3DStartMousePosition = new Cartesian2_default();
var pan3DEndMousePosition = new Cartesian2_default();
var pan3DDiffMousePosition = new Cartesian2_default();
var pan3DPixelDimensions = new Cartesian2_default();
var panRay = new Ray_default();
function pan3D(controller, startPosition, movement, ellipsoid) {
const scene = controller._scene;
const camera = scene.camera;
const startMousePosition = Cartesian2_default.clone(
movement.startPosition,
pan3DStartMousePosition
);
const endMousePosition = Cartesian2_default.clone(
movement.endPosition,
pan3DEndMousePosition
);
const height = ellipsoid.cartesianToCartographic(
camera.positionWC,
scratchCartographic25
).height;
let p0, p1;
if (!movement.inertiaEnabled && height < controller._minimumPickingTerrainHeight) {
p0 = Cartesian3_default.clone(controller._panLastWorldPosition, pan3DP0);
if (!defined_default(controller._globe) && !Cartesian2_default.equalsEpsilon(
startMousePosition,
controller._panLastMousePosition
)) {
p0 = pickPosition(controller, startMousePosition, pan3DP0);
}
if (!defined_default(controller._globe) && defined_default(p0)) {
const toCenter = Cartesian3_default.subtract(p0, camera.positionWC, pan3DTemp1);
const toCenterProj = Cartesian3_default.multiplyByScalar(
camera.directionWC,
Cartesian3_default.dot(camera.directionWC, toCenter),
pan3DTemp1
);
const distanceToNearPlane = Cartesian3_default.magnitude(toCenterProj);
const pixelDimensions = camera.frustum.getPixelDimensions(
scene.drawingBufferWidth,
scene.drawingBufferHeight,
distanceToNearPlane,
scene.pixelRatio,
pan3DPixelDimensions
);
const dragDelta = Cartesian2_default.subtract(
endMousePosition,
startMousePosition,
pan3DDiffMousePosition
);
const right = Cartesian3_default.multiplyByScalar(
camera.rightWC,
dragDelta.x * pixelDimensions.x,
pan3DTemp1
);
const cameraPositionNormal = Cartesian3_default.normalize(
camera.positionWC,
scratchCameraPositionNormal
);
const endPickDirection = camera.getPickRay(
endMousePosition,
panRay
).direction;
const endPickProj = Cartesian3_default.subtract(
endPickDirection,
Cartesian3_default.projectVector(endPickDirection, camera.rightWC, pan3DTemp2),
pan3DTemp2
);
const angle = Cartesian3_default.angleBetween(endPickProj, camera.directionWC);
let forward = 1;
if (defined_default(camera.frustum.fov)) {
forward = Math.max(Math.tan(angle), 0.1);
}
let dot2 = Math.abs(
Cartesian3_default.dot(camera.directionWC, cameraPositionNormal)
);
const magnitude = -dragDelta.y * pixelDimensions.y * 2 / Math.sqrt(forward) * (1 - dot2);
const direction2 = Cartesian3_default.multiplyByScalar(
endPickDirection,
magnitude,
pan3DTemp2
);
dot2 = Math.abs(Cartesian3_default.dot(camera.upWC, cameraPositionNormal));
const up = Cartesian3_default.multiplyByScalar(
camera.upWC,
-dragDelta.y * (1 - dot2) * pixelDimensions.y,
pan3DTemp3
);
p1 = Cartesian3_default.add(p0, right, pan3DP1);
p1 = Cartesian3_default.add(p1, direction2, p1);
p1 = Cartesian3_default.add(p1, up, p1);
Cartesian3_default.clone(p1, controller._panLastWorldPosition);
Cartesian2_default.clone(endMousePosition, controller._panLastMousePosition);
}
}
if (!defined_default(p0) || !defined_default(p1)) {
p0 = camera.pickEllipsoid(startMousePosition, ellipsoid, pan3DP0);
p1 = camera.pickEllipsoid(endMousePosition, ellipsoid, pan3DP1);
}
if (!defined_default(p0) || !defined_default(p1)) {
controller._rotating = true;
rotate3D(controller, startPosition, movement);
return;
}
p0 = camera.worldToCameraCoordinates(p0, p0);
p1 = camera.worldToCameraCoordinates(p1, p1);
if (!defined_default(camera.constrainedAxis)) {
Cartesian3_default.normalize(p0, p0);
Cartesian3_default.normalize(p1, p1);
const dot2 = Cartesian3_default.dot(p0, p1);
const axis = Cartesian3_default.cross(p0, p1, pan3DTemp0);
if (dot2 < 1 && !Cartesian3_default.equalsEpsilon(axis, Cartesian3_default.ZERO, Math_default.EPSILON14)) {
const angle = Math.acos(dot2);
camera.rotate(axis, angle);
}
} else {
const basis0 = camera.constrainedAxis;
const basis1 = Cartesian3_default.mostOrthogonalAxis(basis0, pan3DTemp0);
Cartesian3_default.cross(basis1, basis0, basis1);
Cartesian3_default.normalize(basis1, basis1);
const basis2 = Cartesian3_default.cross(basis0, basis1, pan3DTemp1);
const startRho = Cartesian3_default.magnitude(p0);
const startDot = Cartesian3_default.dot(basis0, p0);
const startTheta = Math.acos(startDot / startRho);
const startRej = Cartesian3_default.multiplyByScalar(basis0, startDot, pan3DTemp2);
Cartesian3_default.subtract(p0, startRej, startRej);
Cartesian3_default.normalize(startRej, startRej);
const endRho = Cartesian3_default.magnitude(p1);
const endDot = Cartesian3_default.dot(basis0, p1);
const endTheta = Math.acos(endDot / endRho);
const endRej = Cartesian3_default.multiplyByScalar(basis0, endDot, pan3DTemp3);
Cartesian3_default.subtract(p1, endRej, endRej);
Cartesian3_default.normalize(endRej, endRej);
let startPhi = Math.acos(Cartesian3_default.dot(startRej, basis1));
if (Cartesian3_default.dot(startRej, basis2) < 0) {
startPhi = Math_default.TWO_PI - startPhi;
}
let endPhi = Math.acos(Cartesian3_default.dot(endRej, basis1));
if (Cartesian3_default.dot(endRej, basis2) < 0) {
endPhi = Math_default.TWO_PI - endPhi;
}
const deltaPhi = startPhi - endPhi;
let east;
if (Cartesian3_default.equalsEpsilon(basis0, camera.position, Math_default.EPSILON2)) {
east = camera.right;
} else {
east = Cartesian3_default.cross(basis0, camera.position, pan3DTemp0);
}
const planeNormal = Cartesian3_default.cross(basis0, east, pan3DTemp0);
const side0 = Cartesian3_default.dot(
planeNormal,
Cartesian3_default.subtract(p0, basis0, pan3DTemp1)
);
const side1 = Cartesian3_default.dot(
planeNormal,
Cartesian3_default.subtract(p1, basis0, pan3DTemp1)
);
let deltaTheta;
if (side0 > 0 && side1 > 0) {
deltaTheta = endTheta - startTheta;
} else if (side0 > 0 && side1 <= 0) {
if (Cartesian3_default.dot(camera.position, basis0) > 0) {
deltaTheta = -startTheta - endTheta;
} else {
deltaTheta = startTheta + endTheta;
}
} else {
deltaTheta = startTheta - endTheta;
}
camera.rotateRight(deltaPhi);
camera.rotateUp(deltaTheta);
}
}
var zoom3DUnitPosition = new Cartesian3_default();
var zoom3DCartographic = new Cartographic_default();
var preIntersectionDistance = 0;
function zoom3D2(controller, startPosition, movement) {
if (defined_default(movement.distance)) {
movement = movement.distance;
}
const inertiaMovement = movement.inertiaEnabled;
const ellipsoid = controller._ellipsoid;
const scene = controller._scene;
const camera = scene.camera;
const canvas = scene.canvas;
const cameraUnderground = controller._cameraUnderground;
let windowPosition;
if (cameraUnderground) {
windowPosition = startPosition;
} else {
windowPosition = zoomCVWindowPos;
windowPosition.x = canvas.clientWidth / 2;
windowPosition.y = canvas.clientHeight / 2;
}
const ray = camera.getPickRay(windowPosition, zoomCVWindowRay);
let intersection;
const height = ellipsoid.cartesianToCartographic(
camera.position,
zoom3DCartographic
).height;
const approachingCollision = Math.abs(preIntersectionDistance) < controller.minimumPickingTerrainDistanceWithInertia;
const needPickGlobe = inertiaMovement ? approachingCollision : height < controller._minimumPickingTerrainHeight;
if (needPickGlobe) {
intersection = pickPosition(controller, windowPosition, zoomCVIntersection);
}
let distance2;
if (defined_default(intersection)) {
distance2 = Cartesian3_default.distance(ray.origin, intersection);
preIntersectionDistance = distance2;
}
if (cameraUnderground) {
const distanceUnderground = getZoomDistanceUnderground(
controller,
ray,
height
);
if (defined_default(distance2)) {
distance2 = Math.min(distance2, distanceUnderground);
} else {
distance2 = distanceUnderground;
}
}
if (!defined_default(distance2)) {
distance2 = height;
}
const unitPosition = Cartesian3_default.normalize(
camera.position,
zoom3DUnitPosition
);
handleZoom(
controller,
startPosition,
movement,
controller.zoomFactor,
distance2,
Cartesian3_default.dot(unitPosition, camera.direction)
);
}
var tilt3DWindowPos = new Cartesian2_default();
var tilt3DRay = new Ray_default();
var tilt3DCenter = new Cartesian3_default();
var tilt3DVerticalCenter = new Cartesian3_default();
var tilt3DTransform = new Matrix4_default();
var tilt3DVerticalTransform = new Matrix4_default();
var tilt3DOldTransform = new Matrix4_default();
var tilt3DQuaternion = new Quaternion_default();
var tilt3DMatrix = new Matrix3_default();
var tilt3DCart = new Cartographic_default();
var tilt3DLookUp = new Cartesian3_default();
function tilt3D(controller, startPosition, movement) {
const scene = controller._scene;
const camera = scene.camera;
if (!Matrix4_default.equals(camera.transform, Matrix4_default.IDENTITY)) {
return;
}
if (defined_default(movement.angleAndHeight)) {
movement = movement.angleAndHeight;
}
if (!Cartesian2_default.equals(startPosition, controller._tiltCenterMousePosition)) {
controller._tiltOnEllipsoid = false;
controller._looking = false;
}
if (controller._looking) {
const up = controller._ellipsoid.geodeticSurfaceNormal(
camera.position,
tilt3DLookUp
);
look3D(controller, startPosition, movement, up);
return;
}
const ellipsoid = controller._ellipsoid;
const cartographic2 = ellipsoid.cartesianToCartographic(
camera.position,
tilt3DCart
);
if (controller._tiltOnEllipsoid || cartographic2.height > controller._minimumCollisionTerrainHeight) {
controller._tiltOnEllipsoid = true;
tilt3DOnEllipsoid(controller, startPosition, movement);
} else {
tilt3DOnTerrain(controller, startPosition, movement);
}
}
var tilt3DOnEllipsoidCartographic = new Cartographic_default();
function tilt3DOnEllipsoid(controller, startPosition, movement) {
const ellipsoid = controller._ellipsoid;
const scene = controller._scene;
const camera = scene.camera;
const minHeight = controller.minimumZoomDistance * 0.25;
const height = ellipsoid.cartesianToCartographic(
camera.positionWC,
tilt3DOnEllipsoidCartographic
).height;
if (height - minHeight - 1 < Math_default.EPSILON3 && movement.endPosition.y - movement.startPosition.y < 0) {
return;
}
const canvas = scene.canvas;
const windowPosition = tilt3DWindowPos;
windowPosition.x = canvas.clientWidth / 2;
windowPosition.y = canvas.clientHeight / 2;
const ray = camera.getPickRay(windowPosition, tilt3DRay);
let center;
const intersection = IntersectionTests_default.rayEllipsoid(ray, ellipsoid);
if (defined_default(intersection)) {
center = Ray_default.getPoint(ray, intersection.start, tilt3DCenter);
} else if (height > controller._minimumTrackBallHeight) {
const grazingAltitudeLocation = IntersectionTests_default.grazingAltitudeLocation(
ray,
ellipsoid
);
if (!defined_default(grazingAltitudeLocation)) {
return;
}
const grazingAltitudeCart = ellipsoid.cartesianToCartographic(
grazingAltitudeLocation,
tilt3DCart
);
grazingAltitudeCart.height = 0;
center = ellipsoid.cartographicToCartesian(
grazingAltitudeCart,
tilt3DCenter
);
} else {
controller._looking = true;
const up = controller._ellipsoid.geodeticSurfaceNormal(
camera.position,
tilt3DLookUp
);
look3D(controller, startPosition, movement, up);
Cartesian2_default.clone(startPosition, controller._tiltCenterMousePosition);
return;
}
const transform3 = Transforms_default.eastNorthUpToFixedFrame(
center,
ellipsoid,
tilt3DTransform
);
const oldGlobe = controller._globe;
const oldEllipsoid = controller._ellipsoid;
controller._globe = void 0;
controller._ellipsoid = Ellipsoid_default.UNIT_SPHERE;
controller._rotateFactor = 1;
controller._rotateRateRangeAdjustment = 1;
const oldTransform = Matrix4_default.clone(camera.transform, tilt3DOldTransform);
camera._setTransform(transform3);
rotate3D(controller, startPosition, movement, Cartesian3_default.UNIT_Z);
camera._setTransform(oldTransform);
controller._globe = oldGlobe;
controller._ellipsoid = oldEllipsoid;
const radius = oldEllipsoid.maximumRadius;
controller._rotateFactor = 1 / radius;
controller._rotateRateRangeAdjustment = radius;
}
function tilt3DOnTerrain(controller, startPosition, movement) {
const ellipsoid = controller._ellipsoid;
const scene = controller._scene;
const camera = scene.camera;
const cameraUnderground = controller._cameraUnderground;
let center;
let ray;
let intersection;
if (Cartesian2_default.equals(startPosition, controller._tiltCenterMousePosition)) {
center = Cartesian3_default.clone(controller._tiltCenter, tilt3DCenter);
} else {
center = pickPosition(controller, startPosition, tilt3DCenter);
if (!defined_default(center)) {
ray = camera.getPickRay(startPosition, tilt3DRay);
intersection = IntersectionTests_default.rayEllipsoid(ray, ellipsoid);
if (!defined_default(intersection)) {
const cartographic2 = ellipsoid.cartesianToCartographic(
camera.position,
tilt3DCart
);
if (cartographic2.height <= controller._minimumTrackBallHeight) {
controller._looking = true;
const up = controller._ellipsoid.geodeticSurfaceNormal(
camera.position,
tilt3DLookUp
);
look3D(controller, startPosition, movement, up);
Cartesian2_default.clone(startPosition, controller._tiltCenterMousePosition);
}
return;
}
center = Ray_default.getPoint(ray, intersection.start, tilt3DCenter);
}
if (cameraUnderground) {
if (!defined_default(ray)) {
ray = camera.getPickRay(startPosition, tilt3DRay);
}
getTiltCenterUnderground(controller, ray, center, center);
}
Cartesian2_default.clone(startPosition, controller._tiltCenterMousePosition);
Cartesian3_default.clone(center, controller._tiltCenter);
}
const canvas = scene.canvas;
const windowPosition = tilt3DWindowPos;
windowPosition.x = canvas.clientWidth / 2;
windowPosition.y = controller._tiltCenterMousePosition.y;
ray = camera.getPickRay(windowPosition, tilt3DRay);
const mag = Cartesian3_default.magnitude(center);
const radii = Cartesian3_default.fromElements(mag, mag, mag, scratchRadii3);
const newEllipsoid = Ellipsoid_default.fromCartesian3(radii, scratchEllipsoid15);
intersection = IntersectionTests_default.rayEllipsoid(ray, newEllipsoid);
if (!defined_default(intersection)) {
return;
}
const t = Cartesian3_default.magnitude(ray.origin) > mag ? intersection.start : intersection.stop;
const verticalCenter = Ray_default.getPoint(ray, t, tilt3DVerticalCenter);
const transform3 = Transforms_default.eastNorthUpToFixedFrame(
center,
ellipsoid,
tilt3DTransform
);
const verticalTransform = Transforms_default.eastNorthUpToFixedFrame(
verticalCenter,
newEllipsoid,
tilt3DVerticalTransform
);
const oldGlobe = controller._globe;
const oldEllipsoid = controller._ellipsoid;
controller._globe = void 0;
controller._ellipsoid = Ellipsoid_default.UNIT_SPHERE;
controller._rotateFactor = 1;
controller._rotateRateRangeAdjustment = 1;
let constrainedAxis = Cartesian3_default.UNIT_Z;
const oldTransform = Matrix4_default.clone(camera.transform, tilt3DOldTransform);
camera._setTransform(verticalTransform);
const tangent = Cartesian3_default.cross(
verticalCenter,
camera.positionWC,
tilt3DCartesian3
);
const dot2 = Cartesian3_default.dot(camera.rightWC, tangent);
if (dot2 < 0) {
const movementDelta = movement.startPosition.y - movement.endPosition.y;
if (cameraUnderground && movementDelta < 0 || !cameraUnderground && movementDelta > 0) {
constrainedAxis = void 0;
}
const oldConstrainedAxis = camera.constrainedAxis;
camera.constrainedAxis = void 0;
rotate3D(controller, startPosition, movement, constrainedAxis, true, false);
camera.constrainedAxis = oldConstrainedAxis;
} else {
rotate3D(controller, startPosition, movement, constrainedAxis, true, false);
}
camera._setTransform(transform3);
rotate3D(controller, startPosition, movement, constrainedAxis, false, true);
if (defined_default(camera.constrainedAxis)) {
const right = Cartesian3_default.cross(
camera.direction,
camera.constrainedAxis,
tilt3DCartesian3
);
if (!Cartesian3_default.equalsEpsilon(right, Cartesian3_default.ZERO, Math_default.EPSILON6)) {
if (Cartesian3_default.dot(right, camera.right) < 0) {
Cartesian3_default.negate(right, right);
}
Cartesian3_default.cross(right, camera.direction, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.normalize(camera.up, camera.up);
Cartesian3_default.normalize(camera.right, camera.right);
}
}
camera._setTransform(oldTransform);
controller._globe = oldGlobe;
controller._ellipsoid = oldEllipsoid;
const radius = oldEllipsoid.maximumRadius;
controller._rotateFactor = 1 / radius;
controller._rotateRateRangeAdjustment = radius;
const originalPosition = Cartesian3_default.clone(
camera.positionWC,
tilt3DCartesian3
);
if (controller.enableCollisionDetection) {
adjustHeightForTerrain(controller, true);
}
if (!Cartesian3_default.equals(camera.positionWC, originalPosition)) {
camera._setTransform(verticalTransform);
camera.worldToCameraCoordinatesPoint(originalPosition, originalPosition);
const magSqrd = Cartesian3_default.magnitudeSquared(originalPosition);
if (Cartesian3_default.magnitudeSquared(camera.position) > magSqrd) {
Cartesian3_default.normalize(camera.position, camera.position);
Cartesian3_default.multiplyByScalar(
camera.position,
Math.sqrt(magSqrd),
camera.position
);
}
const angle = Cartesian3_default.angleBetween(originalPosition, camera.position);
const axis = Cartesian3_default.cross(
originalPosition,
camera.position,
originalPosition
);
Cartesian3_default.normalize(axis, axis);
const quaternion = Quaternion_default.fromAxisAngle(axis, angle, tilt3DQuaternion);
const rotation = Matrix3_default.fromQuaternion(quaternion, tilt3DMatrix);
Matrix3_default.multiplyByVector(rotation, camera.direction, camera.direction);
Matrix3_default.multiplyByVector(rotation, camera.up, camera.up);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.cross(camera.right, camera.direction, camera.up);
camera._setTransform(oldTransform);
}
}
var look3DStartPos = new Cartesian2_default();
var look3DEndPos = new Cartesian2_default();
var look3DStartRay = new Ray_default();
var look3DEndRay = new Ray_default();
var look3DNegativeRot = new Cartesian3_default();
var look3DTan = new Cartesian3_default();
function look3D(controller, startPosition, movement, rotationAxis) {
const scene = controller._scene;
const camera = scene.camera;
const startPos = look3DStartPos;
startPos.x = movement.startPosition.x;
startPos.y = 0;
const endPos = look3DEndPos;
endPos.x = movement.endPosition.x;
endPos.y = 0;
let startRay = camera.getPickRay(startPos, look3DStartRay);
let endRay = camera.getPickRay(endPos, look3DEndRay);
let angle = 0;
let start;
let end;
if (camera.frustum instanceof OrthographicFrustum_default) {
start = startRay.origin;
end = endRay.origin;
Cartesian3_default.add(camera.direction, start, start);
Cartesian3_default.add(camera.direction, end, end);
Cartesian3_default.subtract(start, camera.position, start);
Cartesian3_default.subtract(end, camera.position, end);
Cartesian3_default.normalize(start, start);
Cartesian3_default.normalize(end, end);
} else {
start = startRay.direction;
end = endRay.direction;
}
let dot2 = Cartesian3_default.dot(start, end);
if (dot2 < 1) {
angle = Math.acos(dot2);
}
angle = movement.startPosition.x > movement.endPosition.x ? -angle : angle;
const horizontalRotationAxis = controller._horizontalRotationAxis;
if (defined_default(rotationAxis)) {
camera.look(rotationAxis, -angle);
} else if (defined_default(horizontalRotationAxis)) {
camera.look(horizontalRotationAxis, -angle);
} else {
camera.lookLeft(angle);
}
startPos.x = 0;
startPos.y = movement.startPosition.y;
endPos.x = 0;
endPos.y = movement.endPosition.y;
startRay = camera.getPickRay(startPos, look3DStartRay);
endRay = camera.getPickRay(endPos, look3DEndRay);
angle = 0;
if (camera.frustum instanceof OrthographicFrustum_default) {
start = startRay.origin;
end = endRay.origin;
Cartesian3_default.add(camera.direction, start, start);
Cartesian3_default.add(camera.direction, end, end);
Cartesian3_default.subtract(start, camera.position, start);
Cartesian3_default.subtract(end, camera.position, end);
Cartesian3_default.normalize(start, start);
Cartesian3_default.normalize(end, end);
} else {
start = startRay.direction;
end = endRay.direction;
}
dot2 = Cartesian3_default.dot(start, end);
if (dot2 < 1) {
angle = Math.acos(dot2);
}
angle = movement.startPosition.y > movement.endPosition.y ? -angle : angle;
rotationAxis = rotationAxis ?? horizontalRotationAxis;
if (defined_default(rotationAxis)) {
const direction2 = camera.direction;
const negativeRotationAxis = Cartesian3_default.negate(
rotationAxis,
look3DNegativeRot
);
const northParallel = Cartesian3_default.equalsEpsilon(
direction2,
rotationAxis,
Math_default.EPSILON2
);
const southParallel = Cartesian3_default.equalsEpsilon(
direction2,
negativeRotationAxis,
Math_default.EPSILON2
);
if (!northParallel && !southParallel) {
dot2 = Cartesian3_default.dot(direction2, rotationAxis);
let angleToAxis = Math_default.acosClamped(dot2);
if (angle > 0 && angle > angleToAxis) {
angle = angleToAxis - Math_default.EPSILON4;
}
dot2 = Cartesian3_default.dot(direction2, negativeRotationAxis);
angleToAxis = Math_default.acosClamped(dot2);
if (angle < 0 && -angle > angleToAxis) {
angle = -angleToAxis + Math_default.EPSILON4;
}
const tangent = Cartesian3_default.cross(rotationAxis, direction2, look3DTan);
camera.look(tangent, angle);
} else if (northParallel && angle < 0 || southParallel && angle > 0) {
camera.look(camera.right, -angle);
}
} else {
camera.lookUp(angle);
}
}
function update3D(controller) {
reactToInput(
controller,
controller.enableRotate,
controller.rotateEventTypes,
spin3D,
controller.inertiaSpin,
"_lastInertiaSpinMovement"
);
reactToInput(
controller,
controller.enableZoom,
controller.zoomEventTypes,
zoom3D2,
controller.inertiaZoom,
"_lastInertiaZoomMovement"
);
reactToInput(
controller,
controller.enableTilt,
controller.tiltEventTypes,
tilt3D,
controller.inertiaSpin,
"_lastInertiaTiltMovement"
);
reactToInput(
controller,
controller.enableLook,
controller.lookEventTypes,
look3D
);
}
var scratchAdjustHeightTransform = new Matrix4_default();
var scratchAdjustHeightCartographic = new Cartographic_default();
function adjustHeightForTerrain(controller, cameraChanged) {
controller._adjustedHeightForTerrain = true;
const scene = controller._scene;
const mode2 = scene.mode;
if (mode2 === SceneMode_default.SCENE2D || mode2 === SceneMode_default.MORPHING) {
return;
}
const camera = scene.camera;
const ellipsoid = scene.ellipsoid ?? Ellipsoid_default.WGS84;
const projection = scene.mapProjection;
let transform3;
let mag;
if (!Matrix4_default.equals(camera.transform, Matrix4_default.IDENTITY)) {
transform3 = Matrix4_default.clone(camera.transform, scratchAdjustHeightTransform);
mag = Cartesian3_default.magnitude(camera.position);
camera._setTransform(Matrix4_default.IDENTITY);
}
const cartographic2 = scratchAdjustHeightCartographic;
if (mode2 === SceneMode_default.SCENE3D) {
ellipsoid.cartesianToCartographic(camera.position, cartographic2);
} else {
projection.unproject(camera.position, cartographic2);
}
let heightUpdated = false;
if (cartographic2.height < controller._minimumCollisionTerrainHeight) {
const globeHeight = controller._scene.globeHeight;
if (defined_default(globeHeight)) {
const height = globeHeight + controller.minimumZoomDistance;
const difference = globeHeight - controller._lastGlobeHeight;
const percentDifference = difference / controller._lastGlobeHeight;
if (cartographic2.height < height && (cameraChanged || Math.abs(percentDifference) <= 0.1)) {
cartographic2.height = height;
if (mode2 === SceneMode_default.SCENE3D) {
ellipsoid.cartographicToCartesian(cartographic2, camera.position);
} else {
projection.project(cartographic2, camera.position);
}
heightUpdated = true;
}
if (cameraChanged || Math.abs(percentDifference) <= 0.1) {
controller._lastGlobeHeight = globeHeight;
} else {
controller._lastGlobeHeight += difference * 0.1;
}
}
}
if (defined_default(transform3)) {
camera._setTransform(transform3);
if (heightUpdated) {
Cartesian3_default.normalize(camera.position, camera.position);
Cartesian3_default.negate(camera.position, camera.direction);
Cartesian3_default.multiplyByScalar(
camera.position,
Math.max(mag, controller.minimumZoomDistance),
camera.position
);
Cartesian3_default.normalize(camera.direction, camera.direction);
Cartesian3_default.cross(camera.direction, camera.up, camera.right);
Cartesian3_default.cross(camera.right, camera.direction, camera.up);
}
}
}
ScreenSpaceCameraController.prototype.onMap = function() {
const scene = this._scene;
const mode2 = scene.mode;
const camera = scene.camera;
if (mode2 === SceneMode_default.COLUMBUS_VIEW) {
return Math.abs(camera.position.x) - this._maxCoord.x < 0 && Math.abs(camera.position.y) - this._maxCoord.y < 0;
}
return true;
};
var scratchPreviousPosition = new Cartesian3_default();
var scratchPreviousDirection = new Cartesian3_default();
ScreenSpaceCameraController.prototype.update = function() {
const scene = this._scene;
const { camera, globe, mode: mode2 } = scene;
if (!Matrix4_default.equals(camera.transform, Matrix4_default.IDENTITY)) {
this._globe = void 0;
this._ellipsoid = Ellipsoid_default.UNIT_SPHERE;
} else {
this._globe = globe;
this._ellipsoid = scene.ellipsoid ?? Ellipsoid_default.default;
}
const { verticalExaggeration, verticalExaggerationRelativeHeight } = scene;
this._minimumCollisionTerrainHeight = VerticalExaggeration_default.getHeight(
this.minimumCollisionTerrainHeight,
verticalExaggeration,
verticalExaggerationRelativeHeight
);
this._minimumPickingTerrainHeight = VerticalExaggeration_default.getHeight(
this.minimumPickingTerrainHeight,
verticalExaggeration,
verticalExaggerationRelativeHeight
);
this._minimumTrackBallHeight = VerticalExaggeration_default.getHeight(
this.minimumTrackBallHeight,
verticalExaggeration,
verticalExaggerationRelativeHeight
);
this._cameraUnderground = scene.cameraUnderground && defined_default(this._globe);
const radius = this._ellipsoid.maximumRadius;
this._rotateFactor = 1 / radius;
this._rotateRateRangeAdjustment = radius;
this._adjustedHeightForTerrain = false;
const previousPosition = Cartesian3_default.clone(
camera.positionWC,
scratchPreviousPosition
);
const previousDirection = Cartesian3_default.clone(
camera.directionWC,
scratchPreviousDirection
);
if (mode2 === SceneMode_default.SCENE2D) {
update2D(this);
} else if (mode2 === SceneMode_default.COLUMBUS_VIEW) {
this._horizontalRotationAxis = Cartesian3_default.UNIT_Z;
updateCV(this);
} else if (mode2 === SceneMode_default.SCENE3D) {
this._horizontalRotationAxis = void 0;
update3D(this);
}
if (this.enableCollisionDetection && !this._adjustedHeightForTerrain) {
const cameraChanged = !Cartesian3_default.equals(previousPosition, camera.positionWC) || !Cartesian3_default.equals(previousDirection, camera.directionWC);
adjustHeightForTerrain(this, cameraChanged);
}
this._aggregator.reset();
};
ScreenSpaceCameraController.prototype.isDestroyed = function() {
return false;
};
ScreenSpaceCameraController.prototype.destroy = function() {
this._tweens.removeAll();
this._aggregator = this._aggregator && this._aggregator.destroy();
return destroyObject_default(this);
};
var ScreenSpaceCameraController_default = ScreenSpaceCameraController;
// packages/engine/Source/Scene/SunPostProcess.js
var import_InlineWorkers1121 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/PostProcessStages/AdditiveBlend.js
var import_InlineWorkers1119 = __toESM(require_InlineWorkers(), 1);
var AdditiveBlend_default = "uniform sampler2D colorTexture;\nuniform sampler2D colorTexture2;\n\nuniform vec2 center;\nuniform float radius;\n\nin vec2 v_textureCoordinates;\n\nvoid main()\n{\n vec4 color0 = texture(colorTexture, v_textureCoordinates);\n vec4 color1 = texture(colorTexture2, v_textureCoordinates);\n\n float x = length(gl_FragCoord.xy - center) / radius;\n float t = smoothstep(0.5, 0.8, x);\n out_FragColor = mix(color0 + color1, color1, t);\n}\n";
// packages/engine/Source/Shaders/PostProcessStages/BrightPass.js
var import_InlineWorkers1120 = __toESM(require_InlineWorkers(), 1);
var BrightPass_default = 'uniform sampler2D colorTexture;\n\nuniform float avgLuminance;\nuniform float threshold;\nuniform float offset;\n\nin vec2 v_textureCoordinates;\n\nfloat key(float avg)\n{\n float guess = 1.5 - (1.5 / (avg * 0.1 + 1.0));\n return max(0.0, guess) + 0.1;\n}\n\n// See section 9. "The bright-pass filter" of Realtime HDR Rendering\n// http://www.cg.tuwien.ac.at/research/publications/2007/Luksch_2007_RHR/Luksch_2007_RHR-RealtimeHDR%20.pdf\n\nvoid main()\n{\n vec4 color = texture(colorTexture, v_textureCoordinates);\n vec3 xyz = czm_RGBToXYZ(color.rgb);\n float luminance = xyz.r;\n\n float scaledLum = key(avgLuminance) * luminance / avgLuminance;\n float brightLum = max(scaledLum - threshold, 0.0);\n float brightness = brightLum / (offset + brightLum);\n\n xyz.r = brightness;\n out_FragColor = vec4(czm_XYZToRGB(xyz), 1.0);\n}\n';
// packages/engine/Source/Scene/SunPostProcess.js
function SunPostProcess() {
this._sceneFramebuffer = new SceneFramebuffer_default();
const scale = 0.125;
const stages = new Array(6);
stages[0] = new PostProcessStage_default({
fragmentShader: PassThrough_default,
textureScale: scale,
forcePowerOfTwo: true,
sampleMode: PostProcessStageSampleMode_default.LINEAR
});
const brightPass = stages[1] = new PostProcessStage_default({
fragmentShader: BrightPass_default,
uniforms: {
avgLuminance: 0.5,
// A guess at the average luminance across the entire scene
threshold: 0.25,
offset: 0.1
},
textureScale: scale,
forcePowerOfTwo: true
});
const that = this;
this._delta = 1;
this._sigma = 2;
this._blurStep = new Cartesian2_default();
stages[2] = new PostProcessStage_default({
fragmentShader: GaussianBlur1D_default,
uniforms: {
step: function() {
that._blurStep.x = that._blurStep.y = 1 / brightPass.outputTexture.width;
return that._blurStep;
},
delta: function() {
return that._delta;
},
sigma: function() {
return that._sigma;
},
direction: 0
},
textureScale: scale,
forcePowerOfTwo: true
});
stages[3] = new PostProcessStage_default({
fragmentShader: GaussianBlur1D_default,
uniforms: {
step: function() {
that._blurStep.x = that._blurStep.y = 1 / brightPass.outputTexture.width;
return that._blurStep;
},
delta: function() {
return that._delta;
},
sigma: function() {
return that._sigma;
},
direction: 1
},
textureScale: scale,
forcePowerOfTwo: true
});
stages[4] = new PostProcessStage_default({
fragmentShader: PassThrough_default,
sampleMode: PostProcessStageSampleMode_default.LINEAR
});
this._uCenter = new Cartesian2_default();
this._uRadius = void 0;
stages[5] = new PostProcessStage_default({
fragmentShader: AdditiveBlend_default,
uniforms: {
center: function() {
return that._uCenter;
},
radius: function() {
return that._uRadius;
},
colorTexture2: function() {
return that._sceneFramebuffer.framebuffer.getColorTexture(0);
}
}
});
this._stages = new PostProcessStageComposite_default({
stages
});
const textureCache = new PostProcessStageTextureCache_default(this);
const length2 = stages.length;
for (let i = 0; i < length2; ++i) {
stages[i]._textureCache = textureCache;
}
this._textureCache = textureCache;
this.length = stages.length;
}
SunPostProcess.prototype.get = function(index) {
return this._stages.get(index);
};
SunPostProcess.prototype.getStageByName = function(name) {
const length2 = this._stages.length;
for (let i = 0; i < length2; ++i) {
const stage = this._stages.get(i);
if (stage.name === name) {
return stage;
}
}
return void 0;
};
var sunPositionECScratch = new Cartesian4_default();
var sunPositionWCScratch = new Cartesian2_default();
var sizeScratch = new Cartesian2_default();
var postProcessMatrix4Scratch = new Matrix4_default();
function updateSunPosition(postProcess, context, viewport) {
const us = context.uniformState;
const sunPosition = us.sunPositionWC;
const viewMatrix = us.view;
const viewProjectionMatrix = us.viewProjection;
const projectionMatrix = us.projection;
let viewportTransformation = Matrix4_default.computeViewportTransformation(
viewport,
0,
1,
postProcessMatrix4Scratch
);
const sunPositionEC = Matrix4_default.multiplyByPoint(
viewMatrix,
sunPosition,
sunPositionECScratch
);
let sunPositionWC = Transforms_default.pointToGLWindowCoordinates(
viewProjectionMatrix,
viewportTransformation,
sunPosition,
sunPositionWCScratch
);
sunPositionEC.x += Math_default.SOLAR_RADIUS;
const limbWC = Transforms_default.pointToGLWindowCoordinates(
projectionMatrix,
viewportTransformation,
sunPositionEC,
sunPositionEC
);
const sunSize = Cartesian2_default.magnitude(Cartesian2_default.subtract(limbWC, sunPositionWC, limbWC)) * 30 * 2;
const size = sizeScratch;
size.x = sunSize;
size.y = sunSize;
postProcess._uCenter = Cartesian2_default.clone(sunPositionWC, postProcess._uCenter);
postProcess._uRadius = Math.max(size.x, size.y) * 0.15;
const width = context.drawingBufferWidth;
const height = context.drawingBufferHeight;
const stages = postProcess._stages;
const firstStage = stages.get(0);
const downSampleWidth = firstStage.outputTexture.width;
const downSampleHeight = firstStage.outputTexture.height;
const downSampleViewport = new BoundingRectangle_default();
downSampleViewport.width = downSampleWidth;
downSampleViewport.height = downSampleHeight;
viewportTransformation = Matrix4_default.computeViewportTransformation(
downSampleViewport,
0,
1,
postProcessMatrix4Scratch
);
sunPositionWC = Transforms_default.pointToGLWindowCoordinates(
viewProjectionMatrix,
viewportTransformation,
sunPosition,
sunPositionWCScratch
);
size.x *= downSampleWidth / width;
size.y *= downSampleHeight / height;
const scissorRectangle = firstStage.scissorRectangle;
scissorRectangle.x = Math.max(sunPositionWC.x - size.x * 0.5, 0);
scissorRectangle.y = Math.max(sunPositionWC.y - size.y * 0.5, 0);
scissorRectangle.width = Math.min(size.x, width);
scissorRectangle.height = Math.min(size.y, height);
for (let i = 1; i < 4; ++i) {
BoundingRectangle_default.clone(scissorRectangle, stages.get(i).scissorRectangle);
}
}
SunPostProcess.prototype.clear = function(context, passState, clearColor) {
this._sceneFramebuffer.clear(context, passState, clearColor);
this._textureCache.clear(context);
};
SunPostProcess.prototype.update = function(passState) {
const context = passState.context;
const viewport = passState.viewport;
const sceneFramebuffer = this._sceneFramebuffer;
sceneFramebuffer.update(context, viewport);
const framebuffer = sceneFramebuffer.framebuffer;
this._textureCache.update(context);
this._stages.update(context, false);
updateSunPosition(this, context, viewport);
return framebuffer;
};
SunPostProcess.prototype.execute = function(context) {
const colorTexture = this._sceneFramebuffer.framebuffer.getColorTexture(0);
const stages = this._stages;
const length2 = stages.length;
stages.get(0).execute(context, colorTexture);
for (let i = 1; i < length2; ++i) {
stages.get(i).execute(context, stages.get(i - 1).outputTexture);
}
};
SunPostProcess.prototype.copy = function(context, framebuffer) {
if (!defined_default(this._copyColorCommand)) {
const that = this;
this._copyColorCommand = context.createViewportQuadCommand(PassThrough_default, {
uniformMap: {
colorTexture: function() {
return that._stages.get(that._stages.length - 1).outputTexture;
}
},
owner: this
});
}
this._copyColorCommand.framebuffer = framebuffer;
this._copyColorCommand.execute(context);
};
SunPostProcess.prototype.isDestroyed = function() {
return false;
};
SunPostProcess.prototype.destroy = function() {
this._textureCache.destroy();
this._stages.destroy();
return destroyObject_default(this);
};
var SunPostProcess_default = SunPostProcess;
// packages/engine/Source/Scene/DebugInspector.js
var import_InlineWorkers1122 = __toESM(require_InlineWorkers(), 1);
function DebugInspector() {
this._cachedShowFrustumsShaders = {};
}
function getAttributeLocations(shaderProgram) {
const attributeLocations8 = {};
const attributes = shaderProgram.vertexAttributes;
for (const a3 in attributes) {
if (attributes.hasOwnProperty(a3)) {
attributeLocations8[a3] = attributes[a3].index;
}
}
return attributeLocations8;
}
function createDebugShowFrustumsShaderProgram(scene, shaderProgram) {
const context = scene.context;
const sp = shaderProgram;
const fs = sp.fragmentShaderSource.clone();
const targets = [];
fs.sources = fs.sources.map(function(source) {
source = ShaderSource_default.replaceMain(source, "czm_Debug_main");
const re = /out_FragData_(\d+)/g;
let match;
while ((match = re.exec(source)) !== null) {
if (targets.indexOf(match[1]) === -1) {
targets.push(match[1]);
}
}
return source;
});
const length2 = targets.length;
let newMain = "";
newMain += "uniform vec3 debugShowCommandsColor;\n";
newMain += "uniform vec3 debugShowFrustumsColor;\n";
newMain += "void main() \n{ \n czm_Debug_main(); \n";
let i;
if (length2 > 0) {
for (i = 0; i < length2; ++i) {
newMain += ` out_FragData_${targets[i]}.rgb *= debugShowCommandsColor;
`;
newMain += ` out_FragData_${targets[i]}.rgb *= debugShowFrustumsColor;
`;
}
} else {
newMain += " out_FragColor.rgb *= debugShowCommandsColor;\n";
newMain += " out_FragColor.rgb *= debugShowFrustumsColor;\n";
}
newMain += "}";
fs.sources.push(newMain);
const attributeLocations8 = getAttributeLocations(sp);
return ShaderProgram_default.fromCache({
context,
vertexShaderSource: sp.vertexShaderSource,
fragmentShaderSource: fs,
attributeLocations: attributeLocations8
});
}
var scratchFrustumColor = new Color_default();
function createDebugShowFrustumsUniformMap(scene, command) {
let debugUniformMap;
if (!defined_default(command.uniformMap)) {
debugUniformMap = {};
} else {
debugUniformMap = command.uniformMap;
}
if (defined_default(debugUniformMap.debugShowCommandsColor) || defined_default(debugUniformMap.debugShowFrustumsColor)) {
return debugUniformMap;
}
debugUniformMap.debugShowCommandsColor = function() {
if (!scene.debugShowCommands) {
return Color_default.WHITE;
}
if (!defined_default(command._debugColor)) {
command._debugColor = Color_default.fromRandom();
}
return command._debugColor;
};
debugUniformMap.debugShowFrustumsColor = function() {
if (!scene.debugShowFrustums) {
return Color_default.WHITE;
}
scratchFrustumColor.red = command.debugOverlappingFrustums & 1 << 0 ? 1 : 0;
scratchFrustumColor.green = command.debugOverlappingFrustums & 1 << 1 ? 1 : 0;
scratchFrustumColor.blue = command.debugOverlappingFrustums & 1 << 2 ? 1 : 0;
scratchFrustumColor.alpha = 1;
return scratchFrustumColor;
};
return debugUniformMap;
}
var scratchShowFrustumCommand = new DrawCommand_default();
DebugInspector.prototype.executeDebugShowFrustumsCommand = function(scene, command, passState) {
const shaderProgramId = command.shaderProgram.id;
let debugShaderProgram = this._cachedShowFrustumsShaders[shaderProgramId];
if (!defined_default(debugShaderProgram)) {
debugShaderProgram = createDebugShowFrustumsShaderProgram(
scene,
command.shaderProgram
);
this._cachedShowFrustumsShaders[shaderProgramId] = debugShaderProgram;
}
const debugCommand = DrawCommand_default.shallowClone(
command,
scratchShowFrustumCommand
);
debugCommand.shaderProgram = debugShaderProgram;
debugCommand.uniformMap = createDebugShowFrustumsUniformMap(scene, command);
debugCommand.execute(scene.context, passState);
};
var DebugInspector_default = DebugInspector;
// packages/engine/Source/Scene/VoxelCell.js
var import_InlineWorkers1123 = __toESM(require_InlineWorkers(), 1);
function VoxelCell(primitive, tileIndex, sampleIndex) {
this._primitive = primitive;
this._tileIndex = tileIndex;
this._sampleIndex = sampleIndex;
this._metadata = {};
this._orientedBoundingBox = new OrientedBoundingBox_default();
}
VoxelCell.fromKeyframeNode = function(primitive, tileIndex, sampleIndex, keyframeNode) {
Check_default.typeOf.object("primitive", primitive);
Check_default.typeOf.number("tileIndex", tileIndex);
Check_default.typeOf.number("sampleIndex", sampleIndex);
Check_default.typeOf.object("keyframeNode", keyframeNode);
const voxelCell = new VoxelCell(primitive, tileIndex, sampleIndex);
const { spatialNode, content } = keyframeNode;
voxelCell._metadata = getMetadataForSample(primitive, content, sampleIndex);
voxelCell._orientedBoundingBox = getOrientedBoundingBox(
primitive,
spatialNode,
sampleIndex,
voxelCell._orientedBoundingBox
);
return voxelCell;
};
function getMetadataForSample(primitive, content, sampleIndex) {
if (!defined_default(content) || !defined_default(content.metadata)) {
return void 0;
}
const { names, types } = primitive.provider;
const { metadata } = content;
const metadataMap = {};
for (let i = 0; i < names.length; i++) {
const name = names[i];
const componentCount = MetadataType_default.getComponentCount(types[i]);
const samples = metadata[i].slice(
sampleIndex * componentCount,
(sampleIndex + 1) * componentCount
);
metadataMap[name] = samples;
}
return metadataMap;
}
var tileCoordinateScratch = new Cartesian3_default();
var tileUvScratch = new Cartesian3_default();
function getOrientedBoundingBox(primitive, spatialNode, sampleIndex, result) {
const paddedDimensions = spatialNode.dimensions;
const sliceSize = paddedDimensions.x * paddedDimensions.y;
const zIndex = Math.floor(sampleIndex / sliceSize);
const indexInSlice = sampleIndex - zIndex * sliceSize;
const yIndex = Math.floor(indexInSlice / paddedDimensions.x);
const xIndex = indexInSlice - yIndex * paddedDimensions.x;
const tileCoordinate = Cartesian3_default.fromElements(
xIndex,
yIndex,
zIndex,
tileCoordinateScratch
);
const tileUv = Cartesian3_default.divideComponents(
Cartesian3_default.subtract(
tileCoordinate,
primitive._paddingBefore,
tileCoordinateScratch
),
primitive.dimensions,
tileUvScratch
);
const shape = primitive._shape;
return shape.computeOrientedBoundingBoxForSample(
spatialNode,
primitive.dimensions,
tileUv,
result
);
}
Object.defineProperties(VoxelCell.prototype, {
/**
* Gets an object of the metadata values for this cell. The object's keys are the metadata names.
*
* @memberof VoxelCell.prototype
*
* @type {object}
*
* @readonly
* @private
*/
metadata: {
get: function() {
return this._metadata;
}
},
/**
* All objects returned by {@link Scene#pick} have a primitive property. This returns
* the VoxelPrimitive containing the cell.
*
* @memberof VoxelCell.prototype
*
* @type {VoxelPrimitive}
*
* @readonly
*/
primitive: {
get: function() {
return this._primitive;
}
},
/**
* Get the sample index of the cell.
*
* @memberof VoxelCell.prototype
*
* @type {number}
*
* @readonly
*/
sampleIndex: {
get: function() {
return this._sampleIndex;
}
},
/**
* Get the index of the tile containing the cell.
*
* @memberof VoxelCell.prototype
*
* @type {number}
*
* @readonly
*/
tileIndex: {
get: function() {
return this._tileIndex;
}
},
/**
* Get a copy of the oriented bounding box containing the cell.
*
* @memberof VoxelCell.prototype
*
* @type {OrientedBoundingBox}
*
* @readonly
*/
orientedBoundingBox: {
get: function() {
return this._orientedBoundingBox.clone();
}
}
});
VoxelCell.prototype.hasProperty = function(name) {
return defined_default(this._metadata[name]);
};
VoxelCell.prototype.getNames = function() {
return Object.keys(this._metadata);
};
VoxelCell.prototype.getProperty = function(name) {
return this._metadata[name];
};
var VoxelCell_default = VoxelCell;
// packages/engine/Source/Scene/VoxelPrimitive.js
var import_InlineWorkers1158 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/buildVoxelDrawCommands.js
var import_InlineWorkers1143 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/VoxelRenderResources.js
var import_InlineWorkers1141 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Voxels/VoxelUtils.js
var import_InlineWorkers1124 = __toESM(require_InlineWorkers(), 1);
var VoxelUtils_default = "struct Ray {\n vec3 pos;\n vec3 dir;\n vec3 rawDir;\n};\n\n#if defined(JITTER)\n/**\n * Generate a pseudo-random value for a given 2D screen coordinate.\n * Similar to https://www.shadertoy.com/view/4djSRW with a modified hashscale.\n */\nfloat hash(vec2 p)\n{\n vec3 p3 = fract(vec3(p.xyx) * 50.0);\n p3 += dot(p3, p3.yzx + 19.19);\n return fract((p3.x + p3.y) * p3.z);\n}\n#endif\n\nfloat minComponent(in vec3 v) {\n return min(min(v.x, v.y), v.z);\n}\n\nfloat maxComponent(in vec3 v) {\n return max(max(v.x, v.y), v.z);\n}\n\nstruct PointJacobianT {\n vec3 point;\n mat3 jacobianT;\n};\n";
// packages/engine/Source/Shaders/Voxels/VoxelFS.js
var import_InlineWorkers1125 = __toESM(require_InlineWorkers(), 1);
var VoxelFS_default = "// See Intersection.glsl for the definition of intersectScene\n// See IntersectionUtils.glsl for the definition of nextIntersection\n// See convertUvToBox.glsl, convertUvToCylinder.glsl, or convertUvToEllipsoid.glsl\n// for the definition of convertUvToShapeUvSpace. The appropriate function is \n// selected based on the VoxelPrimitive shape type, and added to the shader in\n// Scene/VoxelRenderResources.js.\n// See Octree.glsl for the definitions of TraversalData, SampleData,\n// traverseOctreeFromBeginning, and traverseOctreeFromExisting\n// See Megatexture.glsl for the definition of accumulatePropertiesFromMegatexture\n\n#define STEP_COUNT_MAX 1000 // Harcoded value because GLSL doesn't like variable length loops\n#if defined(PICKING_VOXEL)\n #define ALPHA_ACCUM_MAX 0.1\n#else\n #define ALPHA_ACCUM_MAX 0.98 // Must be > 0.0 and <= 1.0\n#endif\n\nuniform mat4 u_transformPositionUvToView;\nuniform mat3 u_transformDirectionViewToLocal;\nuniform vec3 u_cameraPositionUv;\nuniform vec3 u_cameraDirectionUv;\nuniform float u_stepSize;\n\n#if defined(PICKING)\n uniform vec4 u_pickColor;\n#endif\n\nvec3 getSampleSize(in int level) {\n vec3 sampleCount = exp2(float(level)) * vec3(u_dimensions);\n vec3 sampleSizeUv = 1.0 / sampleCount;\n return scaleShapeUvToShapeSpace(sampleSizeUv);\n}\n\n#define MINIMUM_STEP_SCALAR (0.02)\n#define SHIFT_FRACTION (0.001)\n\n/**\n * Given a coordinate within a tile, and sample spacings along a ray through\n * the coordinate, find the distance to the points where the ray entered and\n * exited the voxel cell, along with the surface normals at those points.\n * The surface normals are returned in shape space coordinates.\n */\nRayShapeIntersection getVoxelIntersection(in vec3 tileUv, in vec3 sampleSizeAlongRay) {\n vec3 voxelCoord = tileUv * vec3(u_dimensions);\n vec3 directions = sign(sampleSizeAlongRay);\n vec3 positiveDirections = max(directions, 0.0);\n vec3 entryCoord = mix(ceil(voxelCoord), floor(voxelCoord), positiveDirections);\n vec3 exitCoord = entryCoord + directions;\n\n vec3 distanceFromEntry = -abs((entryCoord - voxelCoord) * sampleSizeAlongRay);\n float lastEntry = maxComponent(distanceFromEntry);\n bvec3 isLastEntry = equal(distanceFromEntry, vec3(lastEntry));\n vec3 entryNormal = -1.0 * vec3(isLastEntry) * directions;\n vec4 entry = vec4(entryNormal, lastEntry);\n\n vec3 distanceToExit = abs((exitCoord - voxelCoord) * sampleSizeAlongRay);\n float firstExit = minComponent(distanceToExit);\n bvec3 isFirstExit = equal(distanceToExit, vec3(firstExit));\n vec3 exitNormal = vec3(isFirstExit) * directions;\n vec4 exit = vec4(exitNormal, firstExit);\n\n return RayShapeIntersection(entry, exit);\n}\n\nvec4 getStepSize(in SampleData sampleData, in Ray viewRay, in RayShapeIntersection shapeIntersection, in mat3 jacobianT, in float currentT) {\n // The Jacobian is computed in a space where the shape spans [-1, 1].\n // But the ray is marched in a space where the shape fills [0, 1].\n // So we need to scale the Jacobian by 2.\n vec3 gradient = 2.0 * viewRay.rawDir * jacobianT;\n vec3 sampleSizeAlongRay = getSampleSize(sampleData.tileCoords.w) / gradient;\n\n RayShapeIntersection voxelIntersection = getVoxelIntersection(sampleData.tileUv, sampleSizeAlongRay);\n\n // Transform normal from shape space to Cartesian space\n vec3 voxelNormal = normalize(jacobianT * voxelIntersection.entry.xyz);\n // Compare with the shape intersection, to choose the appropriate normal\n vec4 voxelEntry = vec4(voxelNormal, currentT + voxelIntersection.entry.w);\n vec4 entry = intersectionMax(shapeIntersection.entry, voxelEntry);\n\n float fixedStep = minComponent(abs(sampleSizeAlongRay)) * u_stepSize;\n float shift = fixedStep * SHIFT_FRACTION;\n float dt = voxelIntersection.exit.w + shift;\n if ((currentT + dt) > shapeIntersection.exit.w) {\n // Stop at end of shape\n dt = shapeIntersection.exit.w - currentT + shift;\n }\n float stepSize = clamp(dt, fixedStep * MINIMUM_STEP_SCALAR, fixedStep + shift);\n\n return vec4(entry.xyz, stepSize);\n}\n\nvec2 packIntToVec2(int value) {\n float shifted = float(value) / 255.0;\n float lowBits = fract(shifted);\n float highBits = floor(shifted) / 255.0;\n return vec2(highBits, lowBits);\n}\n\nvec2 packFloatToVec2(float value) {\n float lowBits = fract(value);\n float highBits = floor(value) / 255.0;\n return vec2(highBits, lowBits);\n}\n\nint getSampleIndex(in SampleData sampleData) {\n // tileUv = 1.0 is a valid coordinate but sampleIndex = u_inputDimensions is not.\n // (tileUv = 1.0 corresponds to the far edge of the last sample, at index = u_inputDimensions - 1).\n // Clamp to [0, voxelDimensions - 0.5) to avoid numerical error before flooring\n vec3 maxCoordinate = vec3(u_inputDimensions) - vec3(0.5);\n vec3 inputCoordinate = clamp(sampleData.inputCoordinate, vec3(0.0), maxCoordinate);\n ivec3 sampleIndex = ivec3(floor(inputCoordinate));\n // Convert to a 1D index for lookup in a 1D data array\n return sampleIndex.x + u_inputDimensions.x * (sampleIndex.y + u_inputDimensions.y * sampleIndex.z);\n}\n\n/**\n * Compute the view ray at the current fragment, in the local UV coordinates of the shape.\n */\nRay getViewRayUv() {\n vec4 eyeCoordinates = czm_windowToEyeCoordinates(gl_FragCoord);\n vec3 viewDirUv;\n vec3 viewPosUv;\n if (czm_orthographicIn3D == 1.0) {\n eyeCoordinates.z = 0.0;\n viewPosUv = (u_transformPositionViewToUv * eyeCoordinates).xyz;\n viewDirUv = normalize(u_cameraDirectionUv);\n } else {\n viewPosUv = u_cameraPositionUv;\n viewDirUv = normalize(u_transformDirectionViewToLocal * eyeCoordinates.xyz);\n }\n #if defined(SHAPE_ELLIPSOID)\n // viewDirUv has been scaled to a space where the ellipsoid is a sphere.\n // Undo this scaling to get the raw direction.\n vec3 rawDir = viewDirUv * u_ellipsoidRadiiUv;\n return Ray(viewPosUv, viewDirUv, rawDir);\n #else\n return Ray(viewPosUv, viewDirUv, viewDirUv);\n #endif\n}\n\nvoid main()\n{\n Ray viewRayUv = getViewRayUv();\n\n Intersections ix;\n vec2 screenCoord = (gl_FragCoord.xy - czm_viewport.xy) / czm_viewport.zw; // [0,1]\n RayShapeIntersection shapeIntersection = intersectScene(screenCoord, viewRayUv, ix);\n // Exit early if the scene was completely missed.\n if (shapeIntersection.entry.w == NO_HIT) {\n discard;\n }\n\n float currentT = shapeIntersection.entry.w;\n float endT = shapeIntersection.exit.w;\n vec3 positionUv = viewRayUv.pos + currentT * viewRayUv.dir;\n PointJacobianT pointJacobian = convertUvToShapeUvSpaceDerivative(positionUv);\n\n // Traverse the tree from the start position\n TraversalData traversalData;\n SampleData sampleDatas[SAMPLE_COUNT];\n traverseOctreeFromBeginning(pointJacobian.point, traversalData, sampleDatas);\n vec4 step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection, pointJacobian.jacobianT, currentT);\n\n #if defined(JITTER)\n float noise = hash(screenCoord); // [0,1]\n currentT += noise * step.w;\n positionUv += noise * step.w * viewRayUv.dir;\n #endif\n\n FragmentInput fragmentInput;\n #if defined(STATISTICS)\n setStatistics(fragmentInput.metadataStatistics);\n #endif\n\n czm_modelMaterial materialOutput;\n vec4 colorAccum = vec4(0.0);\n\n for (int stepCount = 0; stepCount < STEP_COUNT_MAX; ++stepCount) {\n // Read properties from the megatexture based on the traversal state\n Properties properties = accumulatePropertiesFromMegatexture(sampleDatas);\n\n // Prepare the custom shader inputs\n copyPropertiesToMetadata(properties, fragmentInput.metadata);\n\n fragmentInput.attributes.positionEC = vec3(u_transformPositionUvToView * vec4(positionUv, 1.0));\n fragmentInput.attributes.normalEC = normalize(czm_normal * step.xyz);\n\n fragmentInput.voxel.viewDirUv = viewRayUv.dir;\n\n fragmentInput.voxel.travelDistance = step.w;\n fragmentInput.voxel.stepCount = stepCount;\n fragmentInput.voxel.tileIndex = sampleDatas[0].megatextureIndex;\n fragmentInput.voxel.sampleIndex = getSampleIndex(sampleDatas[0]);\n fragmentInput.voxel.distanceToDepthBuffer = ix.distanceToDepthBuffer - currentT;\n\n // Run the custom shader\n fragmentMain(fragmentInput, materialOutput);\n\n // Sanitize the custom shader output\n vec4 color = vec4(materialOutput.diffuse, materialOutput.alpha);\n color.rgb = max(color.rgb, vec3(0.0));\n color.a = clamp(color.a, 0.0, 1.0);\n\n // Pre-multiplied alpha blend\n colorAccum += (1.0 - colorAccum.a) * vec4(color.rgb * color.a, color.a);\n\n // Stop traversing if the alpha has been fully saturated\n if (colorAccum.a > ALPHA_ACCUM_MAX) {\n colorAccum.a = ALPHA_ACCUM_MAX;\n break;\n }\n\n if (step.w == 0.0) {\n // Shape is infinitely thin. The ray may have hit the edge of a\n // foreground voxel. Step ahead slightly to check for more voxels\n step.w == 0.00001;\n }\n\n // Keep raymarching\n currentT += step.w;\n // Check if there's more intersections.\n if (currentT > endT) {\n #if (INTERSECTION_COUNT == 1)\n break;\n #else\n shapeIntersection = nextIntersection(ix);\n if (shapeIntersection.entry.w == NO_HIT) {\n break;\n } else {\n // Found another intersection. Resume raymarching there\n currentT = shapeIntersection.entry.w;\n endT = shapeIntersection.exit.w;\n }\n #endif\n }\n positionUv = viewRayUv.pos + currentT * viewRayUv.dir;\n\n // Traverse the tree from the current ray position.\n // This is similar to traverseOctreeFromBeginning but is faster when the ray is in the same tile as the previous step.\n pointJacobian = convertUvToShapeUvSpaceDerivative(positionUv);\n traverseOctreeFromExisting(pointJacobian.point, traversalData, sampleDatas);\n step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection, pointJacobian.jacobianT, currentT);\n }\n\n // Convert the alpha from [0,ALPHA_ACCUM_MAX] to [0,1]\n colorAccum.a /= ALPHA_ACCUM_MAX;\n\n #if defined(PICKING)\n // If alpha is 0.0 there is nothing to pick\n if (colorAccum.a == 0.0) {\n discard;\n }\n out_FragColor = u_pickColor;\n #elif defined(PICKING_VOXEL)\n // If alpha is 0.0 there is nothing to pick\n if (colorAccum.a == 0.0) {\n discard;\n }\n vec2 megatextureId = packIntToVec2(sampleDatas[0].megatextureIndex);\n vec2 sampleIndex = packIntToVec2(getSampleIndex(sampleDatas[0]));\n out_FragColor = vec4(megatextureId, sampleIndex);\n #else\n out_FragColor = colorAccum;\n #endif\n}\n";
// packages/engine/Source/Shaders/Voxels/VoxelVS.js
var import_InlineWorkers1126 = __toESM(require_InlineWorkers(), 1);
var VoxelVS_default = "in vec2 position;\n\nuniform vec4 u_ndcSpaceAxisAlignedBoundingBox;\n\nvoid main() {\n vec2 aabbMin = u_ndcSpaceAxisAlignedBoundingBox.xy;\n vec2 aabbMax = u_ndcSpaceAxisAlignedBoundingBox.zw;\n vec2 translation = 0.5 * (aabbMax + aabbMin);\n vec2 scale = 0.5 * (aabbMax - aabbMin);\n gl_Position = vec4(position * scale + translation, 0.0, 1.0);\n}\n";
// packages/engine/Source/Shaders/Voxels/IntersectionUtils.js
var import_InlineWorkers1127 = __toESM(require_InlineWorkers(), 1);
var IntersectionUtils_default = `/* Intersection defines
#define INTERSECTION_COUNT ###
*/
#define NO_HIT (-czm_infinity)
#define INF_HIT (czm_infinity * 0.5)
struct RayShapeIntersection {
vec4 entry;
vec4 exit;
};
vec4 intersectionMin(in vec4 intersect0, in vec4 intersect1)
{
if (intersect0.w == NO_HIT) {
return intersect1;
} else if (intersect1.w == NO_HIT) {
return intersect0;
}
return (intersect0.w <= intersect1.w) ? intersect0 : intersect1;
}
vec4 intersectionMax(in vec4 intersect0, in vec4 intersect1)
{
return (intersect0.w >= intersect1.w) ? intersect0 : intersect1;
}
RayShapeIntersection intersectIntersections(in Ray ray, in RayShapeIntersection intersect0, in RayShapeIntersection intersect1)
{
bool missed = (intersect0.entry.w == NO_HIT) ||
(intersect1.entry.w == NO_HIT) ||
(intersect0.exit.w < intersect1.entry.w) ||
(intersect0.entry.w > intersect1.exit.w);
if (missed) {
vec4 miss = vec4(normalize(ray.dir), NO_HIT);
return RayShapeIntersection(miss, miss);
}
vec4 entry = intersectionMax(intersect0.entry, intersect1.entry);
vec4 exit = intersectionMin(intersect0.exit, intersect1.exit);
return RayShapeIntersection(entry, exit);
}
struct Intersections {
// Don't access these member variables directly - call the functions instead.
// Store an array of ray-surface intersections. Each intersection is composed of:
// .xyz for the surface normal at the intersection point
// .w for the T value
// The scale of the normal encodes the shape intersection type:
// length(intersection.xyz) = 1: positive shape entry
// length(intersection.xyz) = 2: positive shape exit
// length(intersection.xyz) = 3: negative shape entry
// length(intersection.xyz) = 4: negative shape exit
// INTERSECTION_COUNT is the number of ray-*shape* (volume) intersections,
// so we need twice as many to track ray-*surface* intersections
vec4 intersections[INTERSECTION_COUNT * 2];
float distanceToDepthBuffer;
#if (INTERSECTION_COUNT > 1)
// Maintain state for future nextIntersection calls
int index;
int surroundCount;
bool surroundIsPositive;
#endif
};
RayShapeIntersection getFirstIntersection(in Intersections ix)
{
return RayShapeIntersection(ix.intersections[0], ix.intersections[1]);
}
vec4 encodeIntersectionType(vec4 intersection, int index, bool entry)
{
float scale = float(index > 0) * 2.0 + float(!entry) + 1.0;
return vec4(intersection.xyz * scale, intersection.w);
}
// Use defines instead of real functions because WebGL1 cannot access array with non-constant index.
#define setIntersection(/*inout Intersections*/ ix, /*int*/ index, /*float*/ t, /*bool*/ positive, /*bool*/ enter) (ix).intersections[(index)] = vec4(0.0, float(!positive) * 2.0 + float(!enter) + 1.0, 0.0, (t))
#define setIntersectionPair(/*inout Intersections*/ ix, /*int*/ index, /*vec2*/ entryExit) (ix).intersections[(index) * 2 + 0] = vec4(0.0, float((index) > 0) * 2.0 + 1.0, 0.0, (entryExit).x); (ix).intersections[(index) * 2 + 1] = vec4(0.0, float((index) > 0) * 2.0 + 2.0, 0.0, (entryExit).y)
#define setSurfaceIntersection(/*inout Intersections*/ ix, /*int*/ index, /*vec4*/ intersection, /*bool*/ positive, /*bool*/ enter) (ix).intersections[(index)] = encodeIntersectionType((intersection), int(!positive), (enter))
#define setShapeIntersection(/*inout Intersections*/ ix, /*int*/ index, /*RayShapeIntersection*/ intersection) (ix).intersections[(index) * 2 + 0] = encodeIntersectionType((intersection).entry, (index), true); (ix).intersections[(index) * 2 + 1] = encodeIntersectionType((intersection).exit, (index), false)
#if (INTERSECTION_COUNT > 1)
void initializeIntersections(inout Intersections ix) {
// Sort the intersections from min T to max T with bubble sort.
// Note: If this sorting function changes, some of the intersection test may
// need to be updated. Search for "bubble sort" to find those areas.
const int sortPasses = INTERSECTION_COUNT * 2 - 1;
for (int n = sortPasses; n > 0; --n) {
for (int i = 0; i < sortPasses; ++i) {
// The loop should be: for (i = 0; i < n; ++i) {...} but WebGL1 cannot
// loop with non-constant condition, so it has to break early instead
if (i >= n) { break; }
vec4 intersect0 = ix.intersections[i + 0];
vec4 intersect1 = ix.intersections[i + 1];
bool inOrder = intersect0.w <= intersect1.w;
ix.intersections[i + 0] = inOrder ? intersect0 : intersect1;
ix.intersections[i + 1] = inOrder ? intersect1 : intersect0;
}
}
// Prepare initial state for nextIntersection
ix.index = 0;
ix.surroundCount = 0;
ix.surroundIsPositive = false;
}
#endif
#if (INTERSECTION_COUNT > 1)
RayShapeIntersection nextIntersection(inout Intersections ix) {
vec4 surfaceIntersection = vec4(0.0, 0.0, 0.0, NO_HIT);
RayShapeIntersection shapeIntersection = RayShapeIntersection(surfaceIntersection, surfaceIntersection);
const int passCount = INTERSECTION_COUNT * 2;
if (ix.index == passCount) {
return shapeIntersection;
}
for (int i = 0; i < passCount; ++i) {
// The loop should be: for (i = ix.index; i < passCount; ++i) {...} but WebGL1 cannot
// loop with non-constant condition, so it has to continue instead.
if (i < ix.index) {
continue;
}
ix.index = i + 1;
surfaceIntersection = ix.intersections[i];
int intersectionType = int(length(surfaceIntersection.xyz) - 0.5);
bool currShapeIsPositive = intersectionType < 2;
bool enter = intMod(intersectionType, 2) == 0;
ix.surroundCount += enter ? +1 : -1;
ix.surroundIsPositive = currShapeIsPositive ? enter : ix.surroundIsPositive;
// entering positive or exiting negative
if (ix.surroundCount == 1 && ix.surroundIsPositive && enter == currShapeIsPositive) {
shapeIntersection.entry = surfaceIntersection;
}
// exiting positive or entering negative after being inside positive
bool exitPositive = !enter && currShapeIsPositive && ix.surroundCount == 0;
bool enterNegativeFromPositive = enter && !currShapeIsPositive && ix.surroundCount == 2 && ix.surroundIsPositive;
if (exitPositive || enterNegativeFromPositive) {
shapeIntersection.exit = surfaceIntersection;
// entry and exit have been found, so the loop can stop
if (exitPositive) {
// After exiting positive shape there is nothing left to intersect, so jump to the end index.
ix.index = passCount;
}
break;
}
}
return shapeIntersection;
}
#endif
// NOTE: initializeIntersections, nextIntersection aren't even declared unless INTERSECTION_COUNT > 1
`;
// packages/engine/Source/Shaders/Voxels/IntersectDepth.js
var import_InlineWorkers1128 = __toESM(require_InlineWorkers(), 1);
var IntersectDepth_default = "// See IntersectionUtils.glsl for the definitions of Ray, Intersections,\n// setIntersectionPair, INF_HIT, NO_HIT\n\n/* intersectDepth defines (set in Scene/VoxelRenderResources.js)\n#define DEPTH_INTERSECTION_INDEX ###\n*/\n\nuniform mat4 u_transformPositionViewToUv;\n\nvoid intersectDepth(in vec2 screenCoord, in Ray ray, inout Intersections ix) {\n float logDepthOrDepth = czm_unpackDepth(texture(czm_globeDepthTexture, screenCoord));\n float entry;\n float exit;\n if (logDepthOrDepth != 0.0) {\n // Calculate how far the ray must travel before it hits the depth buffer.\n vec4 eyeCoordinateDepth = czm_screenToEyeCoordinates(screenCoord, logDepthOrDepth);\n eyeCoordinateDepth /= eyeCoordinateDepth.w;\n vec3 depthPositionUv = vec3(u_transformPositionViewToUv * eyeCoordinateDepth);\n entry = dot(depthPositionUv - ray.pos, ray.dir);\n exit = +INF_HIT;\n } else {\n // There's no depth at this location.\n entry = NO_HIT;\n exit = NO_HIT;\n }\n ix.distanceToDepthBuffer = entry;\n#if defined(DEPTH_TEST)\n setIntersectionPair(ix, DEPTH_INTERSECTION_INDEX, vec2(entry, exit));\n#endif\n}\n";
// packages/engine/Source/Shaders/Voxels/IntersectClippingPlanes.js
var import_InlineWorkers1129 = __toESM(require_InlineWorkers(), 1);
var IntersectClippingPlanes_default = "// See IntersectionUtils.glsl for the definitions of Ray, Intersections, INF_HIT,\n// NO_HIT, setShapeIntersection\n\n/* Clipping plane defines (set in Scene/VoxelRenderResources.js)\n#define CLIPPING_PLANES_UNION\n#define CLIPPING_PLANES_COUNT\n#define CLIPPING_PLANES_INTERSECTION_INDEX\n*/\n\nuniform sampler2D u_clippingPlanesTexture;\nuniform mat4 u_clippingPlanesMatrix;\n\n// Plane is in Hessian Normal Form\nvec4 intersectPlane(in Ray ray, in vec4 plane) {\n vec3 n = plane.xyz; // normal\n float w = plane.w; // -dot(pointOnPlane, normal)\n\n float a = dot(ray.pos, n);\n float b = dot(ray.dir, n);\n float t = -(w + a) / b;\n\n return vec4(n, t);\n}\n\nvoid intersectClippingPlanes(in Ray ray, inout Intersections ix) {\n vec4 backSide = vec4(-ray.dir, -INF_HIT);\n vec4 farSide = vec4(ray.dir, +INF_HIT);\n RayShapeIntersection clippingVolume;\n\n #if (CLIPPING_PLANES_COUNT == 1)\n // Union and intersection are the same when there's one clipping plane, and the code\n // is more simplified.\n vec4 planeUv = getClippingPlane(u_clippingPlanesTexture, 0, u_clippingPlanesMatrix);\n vec4 intersection = intersectPlane(ray, planeUv);\n bool reflects = dot(ray.dir, intersection.xyz) < 0.0;\n clippingVolume.entry = reflects ? backSide : intersection;\n clippingVolume.exit = reflects ? intersection : farSide;\n setShapeIntersection(ix, CLIPPING_PLANES_INTERSECTION_INDEX, clippingVolume);\n #elif defined(CLIPPING_PLANES_UNION)\n vec4 firstTransmission = vec4(ray.dir, +INF_HIT);\n vec4 lastReflection = vec4(-ray.dir, -INF_HIT);\n for (int i = 0; i < CLIPPING_PLANES_COUNT; i++) {\n vec4 planeUv = getClippingPlane(u_clippingPlanesTexture, i, u_clippingPlanesMatrix);\n vec4 intersection = intersectPlane(ray, planeUv);\n if (dot(ray.dir, planeUv.xyz) > 0.0) {\n firstTransmission = intersection.w <= firstTransmission.w ? intersection : firstTransmission;\n } else {\n lastReflection = intersection.w >= lastReflection.w ? intersection : lastReflection;\n }\n }\n clippingVolume.entry = backSide;\n clippingVolume.exit = lastReflection;\n setShapeIntersection(ix, CLIPPING_PLANES_INTERSECTION_INDEX + 0, clippingVolume);\n clippingVolume.entry = firstTransmission;\n clippingVolume.exit = farSide;\n setShapeIntersection(ix, CLIPPING_PLANES_INTERSECTION_INDEX + 1, clippingVolume);\n #else // intersection\n vec4 lastTransmission = vec4(ray.dir, -INF_HIT);\n vec4 firstReflection = vec4(-ray.dir, +INF_HIT);\n for (int i = 0; i < CLIPPING_PLANES_COUNT; i++) {\n vec4 planeUv = getClippingPlane(u_clippingPlanesTexture, i, u_clippingPlanesMatrix);\n vec4 intersection = intersectPlane(ray, planeUv);\n if (dot(ray.dir, planeUv.xyz) > 0.0) {\n lastTransmission = intersection.w > lastTransmission.w ? intersection : lastTransmission;\n } else {\n firstReflection = intersection.w < firstReflection.w ? intersection: firstReflection;\n }\n }\n if (lastTransmission.w < firstReflection.w) {\n clippingVolume.entry = lastTransmission;\n clippingVolume.exit = firstReflection;\n } else {\n clippingVolume.entry = vec4(-ray.dir, NO_HIT);\n clippingVolume.exit = vec4(ray.dir, NO_HIT);\n }\n setShapeIntersection(ix, CLIPPING_PLANES_INTERSECTION_INDEX, clippingVolume);\n #endif\n}\n";
// packages/engine/Source/Shaders/Voxels/IntersectLongitude.js
var import_InlineWorkers1130 = __toESM(require_InlineWorkers(), 1);
var IntersectLongitude_default = '// See IntersectionUtils.glsl for the definitions of Ray, NO_HIT, INF_HIT,\n// RayShapeIntersection\n\nvec4 intersectLongitude(in Ray ray, in float angle, in bool positiveNormal) {\n float normalSign = positiveNormal ? 1.0 : -1.0;\n vec2 planeNormal = vec2(-sin(angle), cos(angle)) * normalSign;\n\n vec2 position = ray.pos.xy;\n vec2 direction = ray.dir.xy;\n float approachRate = dot(direction, planeNormal);\n float distance = -dot(position, planeNormal);\n\n float t = (approachRate == 0.0)\n ? NO_HIT\n : distance / approachRate;\n\n return vec4(planeNormal, 0.0, t);\n}\n\nRayShapeIntersection intersectHalfSpace(in Ray ray, in float angle, in bool positiveNormal)\n{\n vec4 intersection = intersectLongitude(ray, angle, positiveNormal);\n vec4 farSide = vec4(normalize(ray.dir), INF_HIT);\n\n bool hitFront = (intersection.w > 0.0) == (dot(ray.pos.xy, intersection.xy) > 0.0);\n if (!hitFront) {\n return RayShapeIntersection(intersection, farSide);\n } else {\n return RayShapeIntersection(-1.0 * farSide, intersection);\n }\n}\n\nvoid intersectFlippedWedge(in Ray ray, in vec2 minMaxAngle, out RayShapeIntersection intersections[2])\n{\n intersections[0] = intersectHalfSpace(ray, minMaxAngle.x, false);\n intersections[1] = intersectHalfSpace(ray, minMaxAngle.y, true);\n}\n\nbool hitPositiveHalfPlane(in Ray ray, in vec4 intersection, in bool positiveNormal) {\n float normalSign = positiveNormal ? 1.0 : -1.0;\n vec2 planeDirection = vec2(intersection.y, -intersection.x) * normalSign;\n vec2 hit = ray.pos.xy + intersection.w * ray.dir.xy;\n return dot(hit, planeDirection) > 0.0;\n}\n\nvoid intersectHalfPlane(in Ray ray, in float angle, out RayShapeIntersection intersections[2]) {\n vec4 intersection = intersectLongitude(ray, angle, true);\n vec4 farSide = vec4(normalize(ray.dir), INF_HIT);\n\n if (hitPositiveHalfPlane(ray, intersection, true)) {\n intersections[0].entry = -1.0 * farSide;\n intersections[0].exit = vec4(-1.0 * intersection.xy, 0.0, intersection.w);\n intersections[1].entry = intersection;\n intersections[1].exit = farSide;\n } else {\n vec4 miss = vec4(normalize(ray.dir), NO_HIT);\n intersections[0].entry = -1.0 * farSide;\n intersections[0].exit = farSide;\n intersections[1].entry = miss;\n intersections[1].exit = miss;\n }\n}\n\nRayShapeIntersection intersectRegularWedge(in Ray ray, in vec2 minMaxAngle)\n{\n // Note: works for maxAngle > minAngle + pi, where the "regular wedge"\n // is actually a negative volume.\n // Compute intersections with the two planes.\n // Normals will point toward the "outside" (negative space)\n vec4 intersect1 = intersectLongitude(ray, minMaxAngle.x, false);\n vec4 intersect2 = intersectLongitude(ray, minMaxAngle.y, true);\n\n // Choose intersection with smallest T as the "first", the other as "last"\n // Note: first or last could be in the "shadow" wedge, beyond the tip\n bool inOrder = intersect1.w <= intersect2.w;\n vec4 first = inOrder ? intersect1 : intersect2;\n vec4 last = inOrder ? intersect2 : intersect1;\n\n bool firstIsAhead = first.w >= 0.0;\n bool startedInsideFirst = dot(ray.pos.xy, first.xy) < 0.0;\n bool exitFromInside = firstIsAhead == startedInsideFirst;\n bool lastIsAhead = last.w > 0.0;\n bool startedOutsideLast = dot(ray.pos.xy, last.xy) >= 0.0;\n bool enterFromOutside = lastIsAhead == startedOutsideLast;\n\n vec4 farSide = vec4(normalize(ray.dir), INF_HIT);\n vec4 miss = vec4(normalize(ray.dir), NO_HIT);\n\n if (exitFromInside && enterFromOutside) {\n // Ray crosses both faces of negative wedge, exiting then entering the positive shape\n return RayShapeIntersection(first, last);\n } else if (!exitFromInside && enterFromOutside) {\n // Ray starts inside wedge. last is in shadow wedge, and first is actually the entry\n return RayShapeIntersection(-1.0 * farSide, first);\n } else if (exitFromInside && !enterFromOutside) {\n // First intersection was in the shadow wedge, so last is actually the exit\n return RayShapeIntersection(last, farSide);\n } else { // !exitFromInside && !enterFromOutside\n // Both intersections were in the shadow wedge\n return RayShapeIntersection(miss, miss);\n }\n}\n';
// packages/engine/Source/Shaders/Voxels/IntersectBox.js
var import_InlineWorkers1131 = __toESM(require_InlineWorkers(), 1);
var IntersectBox_default = "// See IntersectionUtils.glsl for the definitions of Ray, RayShapeIntersection,\n// NO_HIT, Intersections\n\n/* Box defines (set in Scene/VoxelBoxShape.js)\n#define BOX_INTERSECTION_INDEX ### // always 0\n*/\n\nuniform vec3 u_renderMinBounds;\nuniform vec3 u_renderMaxBounds;\n\nRayShapeIntersection intersectBox(in Ray ray, in vec3 minBound, in vec3 maxBound)\n{\n // Consider the box as the intersection of the space between 3 pairs of parallel planes\n // Compute the distance along the ray to each plane\n vec3 t0 = (minBound - ray.pos) / ray.dir;\n vec3 t1 = (maxBound - ray.pos) / ray.dir;\n\n // Identify candidate entries/exits based on distance from ray.pos\n vec3 entries = min(t0, t1);\n vec3 exits = max(t0, t1);\n\n vec3 directions = sign(ray.dir);\n\n // The actual intersection points are the furthest entry and the closest exit\n float lastEntry = maxComponent(entries);\n bvec3 isLastEntry = equal(entries, vec3(lastEntry));\n vec3 entryNormal = -1.0 * vec3(isLastEntry) * directions;\n vec4 entry = vec4(entryNormal, lastEntry);\n\n float firstExit = minComponent(exits);\n bvec3 isFirstExit = equal(exits, vec3(firstExit));\n vec3 exitNormal = vec3(isLastEntry) * directions;\n vec4 exit = vec4(exitNormal, firstExit);\n\n if (entry.w > exit.w) {\n entry.w = NO_HIT;\n exit.w = NO_HIT;\n }\n\n return RayShapeIntersection(entry, exit);\n}\n\nvoid intersectShape(in Ray ray, inout Intersections ix)\n{\n RayShapeIntersection intersection = intersectBox(ray, u_renderMinBounds, u_renderMaxBounds);\n setShapeIntersection(ix, BOX_INTERSECTION_INDEX, intersection);\n}\n";
// packages/engine/Source/Shaders/Voxels/IntersectCylinder.js
var import_InlineWorkers1132 = __toESM(require_InlineWorkers(), 1);
var IntersectCylinder_default = "// See IntersectionUtils.glsl for the definitions of Ray, NO_HIT, Intersections,\n// RayShapeIntersection, setSurfaceIntersection, setShapeIntersection,\n// intersectIntersections\n// See IntersectLongitude.glsl for the definitions of intersectHalfPlane,\n// intersectFlippedWedge, intersectRegularWedge\n\n/* Cylinder defines (set in Scene/VoxelCylinderShape.js)\n#define CYLINDER_HAS_RENDER_BOUNDS_RADIUS_MIN\n#define CYLINDER_HAS_RENDER_BOUNDS_RADIUS_FLAT\n#define CYLINDER_HAS_RENDER_BOUNDS_ANGLE\n#define CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_UNDER_HALF\n#define CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_OVER_HALF\n#define CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_EQUAL_ZERO\n\n#define CYLINDER_INTERSECTION_INDEX_RADIUS_MAX\n#define CYLINDER_INTERSECTION_INDEX_RADIUS_MIN\n#define CYLINDER_INTERSECTION_INDEX_ANGLE\n*/\n\n// Cylinder uniforms\nuniform vec2 u_cylinderRenderRadiusMinMax;\nuniform vec2 u_cylinderRenderHeightMinMax;\n#if defined(CYLINDER_HAS_RENDER_BOUNDS_ANGLE)\n uniform vec2 u_cylinderRenderAngleMinMax;\n#endif\n\n/**\n * Find the intersection of a ray with the volume defined by two planes of constant z\n */\nRayShapeIntersection intersectHeightBounds(in Ray ray, in vec2 minMaxHeight, in bool convex)\n{\n float zPosition = ray.pos.z;\n float zDirection = ray.dir.z;\n\n float tmin = (minMaxHeight.x - zPosition) / zDirection;\n float tmax = (minMaxHeight.y - zPosition) / zDirection;\n\n // Normals point outside the volume\n float signFlip = convex ? 1.0 : -1.0;\n vec4 intersectMin = vec4(0.0, 0.0, -1.0 * signFlip, tmin);\n vec4 intersectMax = vec4(0.0, 0.0, 1.0 * signFlip, tmax);\n\n bool topEntry = zDirection < 0.0;\n vec4 entry = topEntry ? intersectMax : intersectMin;\n vec4 exit = topEntry ? intersectMin : intersectMax;\n\n return RayShapeIntersection(entry, exit);\n}\n\n/**\n * Find the intersection of a ray with a right cylindrical surface of a given radius\n * about the z-axis.\n */\nRayShapeIntersection intersectCylinder(in Ray ray, in float radius, in bool convex)\n{\n vec2 position = ray.pos.xy;\n vec2 direction = ray.dir.xy;\n\n float a = dot(direction, direction);\n float b = dot(position, direction);\n float c = dot(position, position) - radius * radius;\n float determinant = b * b - a * c;\n\n if (determinant < 0.0) {\n vec4 miss = vec4(normalize(ray.dir), NO_HIT);\n return RayShapeIntersection(miss, miss);\n }\n\n determinant = sqrt(determinant);\n float t1 = (-b - determinant) / a;\n float t2 = (-b + determinant) / a;\n float signFlip = convex ? 1.0 : -1.0;\n vec4 intersect1 = vec4(normalize(position + t1 * direction) * signFlip, 0.0, t1);\n vec4 intersect2 = vec4(normalize(position + t2 * direction) * signFlip, 0.0, t2);\n\n return RayShapeIntersection(intersect1, intersect2);\n}\n\n/**\n * Find the intersection of a ray with a right cylindrical solid of given\n * radius and height bounds. NOTE: The shape is assumed to be convex.\n */\nRayShapeIntersection intersectBoundedCylinder(in Ray ray, in float radius, in vec2 minMaxHeight)\n{\n RayShapeIntersection cylinderIntersection = intersectCylinder(ray, radius, true);\n RayShapeIntersection heightBoundsIntersection = intersectHeightBounds(ray, minMaxHeight, true);\n return intersectIntersections(ray, cylinderIntersection, heightBoundsIntersection);\n}\n\nvoid intersectShape(Ray ray, inout Intersections ix)\n{\n // Position is converted from [0,1] to [-1,+1] because shape intersections assume unit space is [-1,+1].\n // Direction is scaled as well to be in sync with position.\n ray.pos = ray.pos * 2.0 - 1.0;\n ray.dir *= 2.0;\n\n RayShapeIntersection outerIntersect = intersectBoundedCylinder(ray, u_cylinderRenderRadiusMinMax.y, u_cylinderRenderHeightMinMax);\n\n setShapeIntersection(ix, CYLINDER_INTERSECTION_INDEX_RADIUS_MAX, outerIntersect);\n\n if (outerIntersect.entry.w == NO_HIT) {\n return;\n }\n\n #if defined(CYLINDER_HAS_RENDER_BOUNDS_RADIUS_FLAT)\n // When the cylinder is perfectly thin it's necessary to sandwich the\n // inner cylinder intersection inside the outer cylinder intersection.\n\n // Without this special case,\n // [outerMin, outerMax, innerMin, innerMax] will bubble sort to\n // [outerMin, innerMin, outerMax, innerMax] which will cause the back\n // side of the cylinder to be invisible because it will think the ray\n // is still inside the inner (negative) cylinder after exiting the\n // outer (positive) cylinder.\n\n // With this special case,\n // [outerMin, innerMin, innerMax, outerMax] will bubble sort to\n // [outerMin, innerMin, innerMax, outerMax] which will work correctly.\n\n // Note: If initializeIntersections() changes its sorting function\n // from bubble sort to something else, this code may need to change.\n RayShapeIntersection innerIntersect = intersectCylinder(ray, 1.0, false);\n setSurfaceIntersection(ix, 0, outerIntersect.entry, true, true); // positive, enter\n setSurfaceIntersection(ix, 1, innerIntersect.entry, false, true); // negative, enter\n setSurfaceIntersection(ix, 2, innerIntersect.exit, false, false); // negative, exit\n setSurfaceIntersection(ix, 3, outerIntersect.exit, true, false); // positive, exit\n #elif defined(CYLINDER_HAS_RENDER_BOUNDS_RADIUS_MIN)\n RayShapeIntersection innerIntersect = intersectCylinder(ray, u_cylinderRenderRadiusMinMax.x, false);\n setShapeIntersection(ix, CYLINDER_INTERSECTION_INDEX_RADIUS_MIN, innerIntersect);\n #endif\n\n #if defined(CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_UNDER_HALF)\n RayShapeIntersection wedgeIntersect = intersectRegularWedge(ray, u_cylinderRenderAngleMinMax);\n setShapeIntersection(ix, CYLINDER_INTERSECTION_INDEX_ANGLE, wedgeIntersect);\n #elif defined(CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_OVER_HALF)\n RayShapeIntersection wedgeIntersects[2];\n intersectFlippedWedge(ray, u_cylinderRenderAngleMinMax, wedgeIntersects);\n setShapeIntersection(ix, CYLINDER_INTERSECTION_INDEX_ANGLE + 0, wedgeIntersects[0]);\n setShapeIntersection(ix, CYLINDER_INTERSECTION_INDEX_ANGLE + 1, wedgeIntersects[1]);\n #elif defined(CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_EQUAL_ZERO)\n RayShapeIntersection wedgeIntersects[2];\n intersectHalfPlane(ray, u_cylinderRenderAngleMinMax.x, wedgeIntersects);\n setShapeIntersection(ix, CYLINDER_INTERSECTION_INDEX_ANGLE + 0, wedgeIntersects[0]);\n setShapeIntersection(ix, CYLINDER_INTERSECTION_INDEX_ANGLE + 1, wedgeIntersects[1]);\n #endif\n}\n";
// packages/engine/Source/Shaders/Voxels/IntersectEllipsoid.js
var import_InlineWorkers1133 = __toESM(require_InlineWorkers(), 1);
var IntersectEllipsoid_default = "// See IntersectionUtils.glsl for the definitions of Ray, NO_HIT, INF_HIT, Intersections,\n// RayShapeIntersection, setSurfaceIntersection, setShapeIntersection\n// See IntersectLongitude.glsl for the definitions of intersectHalfPlane,\n// intersectFlippedWedge, intersectRegularWedge\n\n/* Ellipsoid defines (set in Scene/VoxelEllipsoidShape.js)\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_UNDER_HALF\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_OVER_HALF\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_EQUAL_HALF\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF\n#define ELLIPSOID_INTERSECTION_INDEX_LONGITUDE\n#define ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX\n#define ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN\n#define ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX\n#define ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN\n*/\n\n#if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE)\n uniform vec2 u_ellipsoidRenderLongitudeMinMax;\n#endif\nuniform float u_eccentricitySquared;\nuniform vec2 u_ellipsoidRenderLatitudeSinMinMax;\nuniform vec2 u_clipMinMaxHeight;\n\nRayShapeIntersection intersectZPlane(in Ray ray, in float z) {\n float t = -ray.pos.z / ray.dir.z;\n\n bool startsOutside = sign(ray.pos.z) == sign(z);\n bool entry = (t >= 0.0) != startsOutside;\n\n vec4 intersect = vec4(0.0, 0.0, z, t);\n vec4 farSide = vec4(normalize(ray.dir), INF_HIT);\n\n if (entry) {\n return RayShapeIntersection(intersect, farSide);\n } else {\n return RayShapeIntersection(-1.0 * farSide, intersect);\n }\n}\n\nRayShapeIntersection intersectHeight(in Ray ray, in float relativeHeight, in bool convex)\n{\n // Scale the ray by the ellipsoid axes to make it a unit sphere\n // Note: approximating ellipsoid + height as an ellipsoid\n vec3 radiiCorrection = u_ellipsoidRadiiUv / (u_ellipsoidRadiiUv + relativeHeight);\n vec3 position = ray.pos * radiiCorrection;\n vec3 direction = ray.dir * radiiCorrection;\n\n float a = dot(direction, direction); // ~ 1.0 (or maybe 4.0 if ray is scaled)\n float b = dot(direction, position); // roughly inside [-1.0, 1.0] when zoomed in\n float c = dot(position, position) - 1.0; // ~ 0.0 when zoomed in.\n float determinant = b * b - a * c; // ~ b * b when zoomed in\n\n if (determinant < 0.0) {\n vec4 miss = vec4(normalize(direction), NO_HIT);\n return RayShapeIntersection(miss, miss);\n }\n\n determinant = sqrt(determinant);\n\n // Compute larger root using standard formula\n float signB = b < 0.0 ? -1.0 : 1.0;\n // The other root may suffer from subtractive cancellation in the standard formula.\n // Compute it from the first root instead.\n float t1 = (-b - signB * determinant) / a;\n float t2 = c / (a * t1);\n float tmin = min(t1, t2);\n float tmax = max(t1, t2);\n\n float directionScale = convex ? 1.0 : -1.0;\n vec3 d1 = directionScale * normalize(position + tmin * direction);\n vec3 d2 = directionScale * normalize(position + tmax * direction);\n\n return RayShapeIntersection(vec4(d1, tmin), vec4(d2, tmax));\n}\n\n/**\n * Given a circular cone around the z-axis, with apex at the origin,\n * find the parametric distance(s) along a ray where that ray intersects\n * the cone.\n * The cone opening angle is described by the squared cosine of\n * its half-angle (the angle between the Z-axis and the surface)\n */\nvec2 intersectDoubleEndedCone(in Ray ray, in float cosSqrHalfAngle)\n{\n vec3 o = ray.pos;\n vec3 d = ray.dir;\n float sinSqrHalfAngle = 1.0 - cosSqrHalfAngle;\n\n float aSin = d.z * d.z * sinSqrHalfAngle;\n float aCos = -dot(d.xy, d.xy) * cosSqrHalfAngle;\n float a = aSin + aCos;\n\n float bSin = d.z * o.z * sinSqrHalfAngle;\n float bCos = -dot(o.xy, d.xy) * cosSqrHalfAngle;\n float b = bSin + bCos;\n\n float cSin = o.z * o.z * sinSqrHalfAngle;\n float cCos = -dot(o.xy, o.xy) * cosSqrHalfAngle;\n float c = cSin + cCos;\n // determinant = b * b - a * c. But bSin * bSin = aSin * cSin.\n // Avoid subtractive cancellation by expanding to eliminate these terms\n float determinant = 2.0 * bSin * bCos + bCos * bCos - aSin * cCos - aCos * cSin - aCos * cCos;\n\n if (determinant < 0.0) {\n return vec2(NO_HIT);\n } else if (a == 0.0) {\n // Ray is parallel to cone surface\n return (b == 0.0)\n ? vec2(NO_HIT) // Ray is on cone surface\n : vec2(-0.5 * c / b, NO_HIT);\n }\n\n determinant = sqrt(determinant);\n\n // Compute larger root using standard formula\n float signB = b < 0.0 ? -1.0 : 1.0;\n float t1 = (-b - signB * determinant) / a;\n // The other root may suffer from subtractive cancellation in the standard formula.\n // Compute it from the first root instead.\n float t2 = c / (a * t1);\n float tmin = min(t1, t2);\n float tmax = max(t1, t2);\n return vec2(tmin, tmax);\n}\n\n/**\n * Given a point on a conical surface, find the surface normal at that point.\n */\nvec3 getConeNormal(in vec3 p, in bool convex) {\n // Start with radial component pointing toward z-axis\n vec2 radial = -abs(p.z) * normalize(p.xy);\n // Z component points toward opening of cone\n float zSign = (p.z < 0.0) ? -1.0 : 1.0;\n float z = length(p.xy) * zSign;\n // Flip normal if shape is convex\n float flip = (convex) ? -1.0 : 1.0;\n return normalize(vec3(radial, z) * flip);\n}\n\n/**\n * Compute the shift between the ellipsoid origin and the apex of a cone of latitude\n */\nfloat getLatitudeConeShift(in float sinLatitude) {\n // Find prime vertical radius of curvature: \n // the distance along the ellipsoid normal to the intersection with the z-axis\n float x2 = u_eccentricitySquared * sinLatitude * sinLatitude;\n float primeVerticalRadius = inversesqrt(1.0 - x2);\n\n // Compute a shift from the origin to the intersection of the cone with the z-axis\n return primeVerticalRadius * u_eccentricitySquared * sinLatitude;\n}\n\nvoid intersectFlippedCone(in Ray ray, in float cosHalfAngle, out RayShapeIntersection intersections[2]) {\n // Undo the scaling from ellipsoid to sphere\n ray.pos = ray.pos * u_ellipsoidRadiiUv;\n ray.dir = ray.dir * u_ellipsoidRadiiUv;\n // Shift the ray to account for the latitude cone not being centered at the Earth center\n ray.pos.z += getLatitudeConeShift(cosHalfAngle);\n\n float cosSqrHalfAngle = cosHalfAngle * cosHalfAngle;\n vec2 intersect = intersectDoubleEndedCone(ray, cosSqrHalfAngle);\n\n vec4 miss = vec4(normalize(ray.dir), NO_HIT);\n vec4 farSide = vec4(normalize(ray.dir), INF_HIT);\n\n // Initialize output with no intersections\n intersections[0].entry = -1.0 * farSide;\n intersections[0].exit = farSide;\n intersections[1].entry = miss;\n intersections[1].exit = miss;\n\n if (intersect.x == NO_HIT) {\n return;\n }\n\n // Find the points of intersection\n float tmin = intersect.x;\n float tmax = intersect.y;\n vec3 p0 = ray.pos + tmin * ray.dir;\n vec3 p1 = ray.pos + tmax * ray.dir;\n\n vec4 intersect0 = vec4(getConeNormal(p0, true), tmin);\n vec4 intersect1 = vec4(getConeNormal(p1, true), tmax);\n\n bool p0InShadowCone = sign(p0.z) != sign(cosHalfAngle);\n bool p1InShadowCone = sign(p1.z) != sign(cosHalfAngle);\n\n if (p0InShadowCone && p1InShadowCone) {\n // no valid intersections\n } else if (p0InShadowCone) {\n intersections[0].exit = intersect1;\n } else if (p1InShadowCone) {\n intersections[0].entry = intersect0;\n } else {\n intersections[0].exit = intersect0;\n intersections[1].entry = intersect1;\n intersections[1].exit = farSide;\n }\n}\n\nRayShapeIntersection intersectRegularCone(in Ray ray, in float cosHalfAngle, in bool convex) {\n // Undo the scaling from ellipsoid to sphere\n ray.pos = ray.pos * u_ellipsoidRadiiUv;\n ray.dir = ray.dir * u_ellipsoidRadiiUv;\n // Shift the ray to account for the latitude cone not being centered at the Earth center\n ray.pos.z += getLatitudeConeShift(cosHalfAngle);\n\n float cosSqrHalfAngle = cosHalfAngle * cosHalfAngle;\n vec2 intersect = intersectDoubleEndedCone(ray, cosSqrHalfAngle);\n\n vec4 miss = vec4(normalize(ray.dir), NO_HIT);\n vec4 farSide = vec4(normalize(ray.dir), INF_HIT);\n\n if (intersect.x == NO_HIT) {\n return RayShapeIntersection(miss, miss);\n }\n\n // Find the points of intersection\n float tmin = intersect.x;\n float tmax = intersect.y;\n vec3 p0 = ray.pos + tmin * ray.dir;\n vec3 p1 = ray.pos + tmax * ray.dir;\n\n vec4 intersect0 = vec4(getConeNormal(p0, convex), tmin);\n vec4 intersect1 = vec4(getConeNormal(p1, convex), tmax);\n\n bool p0InShadowCone = sign(p0.z) != sign(cosHalfAngle);\n bool p1InShadowCone = sign(p1.z) != sign(cosHalfAngle);\n\n if (p0InShadowCone && p1InShadowCone) {\n return RayShapeIntersection(miss, miss);\n } else if (p0InShadowCone) {\n return RayShapeIntersection(intersect1, farSide);\n } else if (p1InShadowCone) {\n return RayShapeIntersection(-1.0 * farSide, intersect0);\n } else {\n return RayShapeIntersection(intersect0, intersect1);\n }\n}\n\nvoid intersectShape(in Ray ray, inout Intersections ix) {\n // Position is converted from [0,1] to [-1,+1] because shape intersections assume unit space is [-1,+1].\n // Direction is scaled as well to be in sync with position.\n ray.pos = ray.pos * 2.0 - 1.0;\n ray.dir *= 2.0;\n\n // Outer ellipsoid\n RayShapeIntersection outerIntersect = intersectHeight(ray, u_clipMinMaxHeight.y, true);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX, outerIntersect);\n\n // Exit early if the outer ellipsoid was missed.\n if (outerIntersect.entry.w == NO_HIT) {\n return;\n }\n\n // Inner ellipsoid\n RayShapeIntersection innerIntersect = intersectHeight(ray, u_clipMinMaxHeight.x, false);\n\n if (innerIntersect.entry.w == NO_HIT) {\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN, innerIntersect);\n } else {\n // When the ellipsoid is large and thin it's possible for floating point math\n // to cause the ray to intersect the inner ellipsoid before the outer ellipsoid. \n // To prevent this from happening, clamp innerIntersect to outerIntersect and\n // sandwich the inner ellipsoid intersection inside the outer ellipsoid intersection.\n\n // Without this special case,\n // [outerMin, outerMax, innerMin, innerMax] will bubble sort to\n // [outerMin, innerMin, outerMax, innerMax] which will cause the back\n // side of the ellipsoid to be invisible because it will think the ray\n // is still inside the inner (negative) ellipsoid after exiting the\n // outer (positive) ellipsoid.\n\n // With this special case,\n // [outerMin, innerMin, innerMax, outerMax] will bubble sort to\n // [outerMin, innerMin, innerMax, outerMax] which will work correctly.\n\n // Note: If initializeIntersections() changes its sorting function\n // from bubble sort to something else, this code may need to change.\n innerIntersect.entry.w = max(innerIntersect.entry.w, outerIntersect.entry.w);\n innerIntersect.exit.w = min(innerIntersect.exit.w, outerIntersect.exit.w);\n setSurfaceIntersection(ix, 0, outerIntersect.entry, true, true); // positive, enter\n setSurfaceIntersection(ix, 1, innerIntersect.entry, false, true); // negative, enter\n setSurfaceIntersection(ix, 2, innerIntersect.exit, false, false); // negative, exit\n setSurfaceIntersection(ix, 3, outerIntersect.exit, true, false); // positive, exit\n }\n\n // Bottom cone\n #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF)\n RayShapeIntersection bottomConeIntersection = intersectRegularCone(ray, u_ellipsoidRenderLatitudeSinMinMax.x, false);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN, bottomConeIntersection);\n #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF)\n RayShapeIntersection bottomConeIntersection = intersectZPlane(ray, -1.0);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN, bottomConeIntersection);\n #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF)\n RayShapeIntersection bottomConeIntersections[2];\n intersectFlippedCone(ray, u_ellipsoidRenderLatitudeSinMinMax.x, bottomConeIntersections);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN + 0, bottomConeIntersections[0]);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN + 1, bottomConeIntersections[1]);\n #endif\n\n // Top cone\n #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF)\n RayShapeIntersection topConeIntersections[2];\n intersectFlippedCone(ray, u_ellipsoidRenderLatitudeSinMinMax.y, topConeIntersections);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX + 0, topConeIntersections[0]);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX + 1, topConeIntersections[1]);\n #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_EQUAL_HALF)\n RayShapeIntersection topConeIntersection = intersectZPlane(ray, 1.0);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX, topConeIntersection);\n #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF)\n RayShapeIntersection topConeIntersection = intersectRegularCone(ray, u_ellipsoidRenderLatitudeSinMinMax.y, false);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX, topConeIntersection);\n #endif\n\n // Wedge\n #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO)\n RayShapeIntersection wedgeIntersects[2];\n intersectHalfPlane(ray, u_ellipsoidRenderLongitudeMinMax.x, wedgeIntersects);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LONGITUDE + 0, wedgeIntersects[0]);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LONGITUDE + 1, wedgeIntersects[1]);\n #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_UNDER_HALF)\n RayShapeIntersection wedgeIntersect = intersectRegularWedge(ray, u_ellipsoidRenderLongitudeMinMax);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LONGITUDE, wedgeIntersect);\n #elif defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_OVER_HALF)\n RayShapeIntersection wedgeIntersects[2];\n intersectFlippedWedge(ray, u_ellipsoidRenderLongitudeMinMax, wedgeIntersects);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LONGITUDE + 0, wedgeIntersects[0]);\n setShapeIntersection(ix, ELLIPSOID_INTERSECTION_INDEX_LONGITUDE + 1, wedgeIntersects[1]);\n #endif\n}\n";
// packages/engine/Source/Shaders/Voxels/Intersection.js
var import_InlineWorkers1134 = __toESM(require_InlineWorkers(), 1);
var Intersection_default = "// Main intersection function for Voxel scenes.\n// See IntersectBox.glsl, IntersectCylinder.glsl, or IntersectEllipsoid.glsl\n// for the definition of intersectShape. The appropriate function is selected\n// based on the VoxelPrimitive shape type, and added to the shader in\n// Scene/VoxelRenderResources.js.\n// See also IntersectClippingPlane.glsl and IntersectDepth.glsl.\n// See IntersectionUtils.glsl for the definitions of Ray, NO_HIT,\n// getFirstIntersection, initializeIntersections, nextIntersection.\n\n/* Intersection defines (set in Scene/VoxelRenderResources.js)\n#define INTERSECTION_COUNT ###\n*/\n\nRayShapeIntersection intersectScene(in vec2 screenCoord, in Ray ray, out Intersections ix) {\n // Do a ray-shape intersection to find the exact starting and ending points.\n intersectShape(ray, ix);\n\n // Exit early if the positive shape was completely missed or behind the ray.\n RayShapeIntersection intersection = getFirstIntersection(ix);\n if (intersection.entry.w == NO_HIT) {\n // Positive shape was completely missed - so exit early.\n return intersection;\n }\n\n // Clipping planes\n #if defined(CLIPPING_PLANES)\n intersectClippingPlanes(ray, ix);\n #endif\n\n // Depth\n intersectDepth(screenCoord, ray, ix);\n\n // Find the first intersection that's in front of the ray\n #if (INTERSECTION_COUNT > 1)\n initializeIntersections(ix);\n for (int i = 0; i < INTERSECTION_COUNT; ++i) {\n intersection = nextIntersection(ix);\n if (intersection.exit.w > 0.0) {\n // Set start to 0.0 when ray is inside the shape.\n intersection.entry.w = max(intersection.entry.w, 0.0);\n break;\n }\n }\n #else\n // Set start to 0.0 when ray is inside the shape.\n intersection.entry.w = max(intersection.entry.w, 0.0);\n #endif\n\n return intersection;\n}\n";
// packages/engine/Source/Shaders/Voxels/convertUvToBox.js
var import_InlineWorkers1135 = __toESM(require_InlineWorkers(), 1);
var convertUvToBox_default = "/* Box defines (set in Scene/VoxelBoxShape.js)\n#define BOX_HAS_SHAPE_BOUNDS\n*/\n\n#if defined(BOX_HAS_SHAPE_BOUNDS)\n uniform vec3 u_boxUvToShapeUvScale;\n uniform vec3 u_boxUvToShapeUvTranslate;\n#endif\n\nPointJacobianT convertUvToShapeSpaceDerivative(in vec3 positionUv) {\n // For BOX, UV space = shape space, so we can use positionUv as-is,\n // and the Jacobian is the identity matrix, except that a step of 1\n // only spans half the shape space [-1, 1], so the identity is scaled.\n return PointJacobianT(positionUv, mat3(0.5));\n}\n\nvec3 convertShapeToShapeUvSpace(in vec3 positionShape) {\n#if defined(BOX_HAS_SHAPE_BOUNDS)\n return positionShape * u_boxUvToShapeUvScale + u_boxUvToShapeUvTranslate;\n#else\n return positionShape;\n#endif\n}\n\nPointJacobianT convertUvToShapeUvSpaceDerivative(in vec3 positionUv) {\n PointJacobianT pointJacobian = convertUvToShapeSpaceDerivative(positionUv);\n pointJacobian.point = convertShapeToShapeUvSpace(pointJacobian.point);\n return pointJacobian;\n}\n\nvec3 convertShapeUvToUvSpace(in vec3 shapeUv) {\n#if defined(BOX_HAS_SHAPE_BOUNDS)\n return (shapeUv - u_boxUvToShapeUvTranslate) / u_boxUvToShapeUvScale;\n#else\n return shapeUv;\n#endif\n}\n\nvec3 scaleShapeUvToShapeSpace(in vec3 shapeUv) {\n#if defined(BOX_HAS_SHAPE_BOUNDS)\n return shapeUv / u_boxUvToShapeUvScale;\n#else\n return shapeUv;\n#endif\n}";
// packages/engine/Source/Shaders/Voxels/convertUvToCylinder.js
var import_InlineWorkers1136 = __toESM(require_InlineWorkers(), 1);
var convertUvToCylinder_default = "/* Cylinder defines (set in Scene/VoxelCylinderShape.js)\n#define CYLINDER_HAS_SHAPE_BOUNDS_RADIUS\n#define CYLINDER_HAS_SHAPE_BOUNDS_HEIGHT\n#define CYLINDER_HAS_SHAPE_BOUNDS_ANGLE\n#define CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MIN_DISCONTINUITY\n#define CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MAX_DISCONTINUITY\n#define CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MIN_MAX_REVERSED\n*/\n\n#if defined(CYLINDER_HAS_SHAPE_BOUNDS_RADIUS)\n uniform vec2 u_cylinderUvToShapeUvRadius; // x = scale, y = offset\n#endif\n#if defined(CYLINDER_HAS_SHAPE_BOUNDS_HEIGHT)\n uniform vec2 u_cylinderUvToShapeUvHeight; // x = scale, y = offset\n#endif\n#if defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE)\n uniform vec2 u_cylinderUvToShapeUvAngle; // x = scale, y = offset\n#endif\n#if defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MIN_DISCONTINUITY) || defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MAX_DISCONTINUITY)\n uniform vec2 u_cylinderShapeUvAngleMinMax;\n#endif\n#if defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MIN_DISCONTINUITY) || defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MAX_DISCONTINUITY) || defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MIN_MAX_REVERSED)\n uniform float u_cylinderShapeUvAngleRangeZeroMid;\n#endif\n\nPointJacobianT convertUvToShapeSpaceDerivative(in vec3 positionUv) {\n // Convert from Cartesian UV space [0, 1] to Cartesian local space [-1, 1]\n vec3 position = positionUv * 2.0 - 1.0;\n\n float radius = length(position.xy); // [0, 1]\n vec3 radial = normalize(vec3(position.xy, 0.0));\n\n // Shape space height is defined within [0, 1]\n float height = positionUv.z; // [0, 1]\n vec3 z = vec3(0.0, 0.0, 1.0);\n\n float angle = atan(position.y, position.x);\n vec3 east = normalize(vec3(-position.y, position.x, 0.0));\n\n vec3 point = vec3(radius, angle, height);\n mat3 jacobianT = mat3(radial, east / length(position.xy), z);\n return PointJacobianT(point, jacobianT);\n}\n\nvec3 convertShapeToShapeUvSpace(in vec3 positionShape) {\n float radius = positionShape.x;\n #if defined(CYLINDER_HAS_SHAPE_BOUNDS_RADIUS)\n radius = radius * u_cylinderUvToShapeUvRadius.x + u_cylinderUvToShapeUvRadius.y;\n #endif\n\n float angle = (positionShape.y + czm_pi) / czm_twoPi;\n #if defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE)\n #if defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MIN_MAX_REVERSED)\n // Comparing against u_cylinderShapeUvAngleMinMax has precision problems. u_cylinderShapeUvAngleRangeZeroMid is more conservative.\n angle += float(angle < u_cylinderShapeUvAngleRangeZeroMid);\n #endif\n\n // Avoid flickering from reading voxels from both sides of the -pi/+pi discontinuity.\n #if defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MIN_DISCONTINUITY)\n angle = angle > u_cylinderShapeUvAngleRangeZeroMid ? u_cylinderShapeUvAngleMinMax.x : angle;\n #elif defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MAX_DISCONTINUITY)\n angle = angle < u_cylinderShapeUvAngleRangeZeroMid ? u_cylinderShapeUvAngleMinMax.y : angle;\n #endif\n\n angle = angle * u_cylinderUvToShapeUvAngle.x + u_cylinderUvToShapeUvAngle.y;\n #endif\n\n float height = positionShape.z;\n #if defined(CYLINDER_HAS_SHAPE_BOUNDS_HEIGHT)\n height = height * u_cylinderUvToShapeUvHeight.x + u_cylinderUvToShapeUvHeight.y;\n #endif\n\n return vec3(radius, angle, height);\n}\n\nPointJacobianT convertUvToShapeUvSpaceDerivative(in vec3 positionUv) {\n PointJacobianT pointJacobian = convertUvToShapeSpaceDerivative(positionUv);\n pointJacobian.point = convertShapeToShapeUvSpace(pointJacobian.point);\n return pointJacobian;\n}\n\nvec3 scaleShapeUvToShapeSpace(in vec3 shapeUv) {\n float radius = shapeUv.x;\n #if defined(CYLINDER_HAS_SHAPE_BOUNDS_RADIUS)\n radius /= u_cylinderUvToShapeUvRadius.x;\n #endif\n\n float angle = shapeUv.y * czm_twoPi;\n #if defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE)\n angle /= u_cylinderUvToShapeUvAngle.x;\n #endif\n\n float height = shapeUv.z;\n #if defined(CYLINDER_HAS_SHAPE_BOUNDS_HEIGHT)\n height /= u_cylinderUvToShapeUvHeight.x;\n #endif\n\n return vec3(radius, angle, height);\n}\n";
// packages/engine/Source/Shaders/Voxels/convertUvToEllipsoid.js
var import_InlineWorkers1137 = __toESM(require_InlineWorkers(), 1);
var convertUvToEllipsoid_default = "/* Ellipsoid defines (set in Scene/VoxelEllipsoidShape.js)\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MIN_DISCONTINUITY\n#define ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MAX_DISCONTINUITY\n#define ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE\n#define ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_MIN_MAX_REVERSED\n#define ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE\n*/\n\nuniform vec3 u_ellipsoidRadiiUv; // [0,1]\nuniform vec2 u_evoluteScale; // (radiiUv.x ^ 2 - radiiUv.z ^ 2) * vec2(1.0, -1.0) / radiiUv;\nuniform vec3 u_ellipsoidInverseRadiiSquaredUv;\n#if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MIN_DISCONTINUITY) || defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MAX_DISCONTINUITY) || defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_MIN_MAX_REVERSED)\n uniform vec3 u_ellipsoidShapeUvLongitudeMinMaxMid;\n#endif\n#if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE)\n uniform vec2 u_ellipsoidUvToShapeUvLongitude; // x = scale, y = offset\n#endif\n#if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE)\n uniform vec2 u_ellipsoidUvToShapeUvLatitude; // x = scale, y = offset\n#endif\nuniform float u_ellipsoidInverseHeightDifferenceUv;\n\n// robust iterative solution without trig functions\n// https://github.com/0xfaded/ellipse_demo/issues/1\n// https://stackoverflow.com/questions/22959698/distance-from-given-point-to-given-ellipse\n// Extended to return radius of curvature along with the point\nvec3 nearestPointAndRadiusOnEllipse(vec2 pos, vec2 radii) {\n vec2 p = abs(pos);\n vec2 inverseRadii = 1.0 / radii;\n\n // We describe the ellipse parametrically: v = radii * vec2(cos(t), sin(t))\n // but store the cos and sin of t in a vec2 for efficiency.\n // Initial guess: t = pi/4\n vec2 tTrigs = vec2(0.7071067811865476);\n // Initial guess of point on ellipsoid\n vec2 v = radii * tTrigs;\n // Center of curvature of the ellipse at v\n vec2 evolute = u_evoluteScale * tTrigs * tTrigs * tTrigs;\n\n const int iterations = 3;\n for (int i = 0; i < iterations; ++i) {\n // Find the (approximate) intersection of p - evolute with the ellipsoid.\n vec2 q = normalize(p - evolute) * length(v - evolute);\n // Update the estimate of t.\n tTrigs = (q + evolute) * inverseRadii;\n tTrigs = normalize(clamp(tTrigs, 0.0, 1.0));\n v = radii * tTrigs;\n evolute = u_evoluteScale * tTrigs * tTrigs * tTrigs;\n }\n\n return vec3(v * sign(pos), length(v - evolute));\n}\n\nPointJacobianT convertUvToShapeSpaceDerivative(in vec3 positionUv) {\n // Convert from UV space [0, 1] to local space [-1, 1]\n vec3 position = positionUv * 2.0 - 1.0;\n // Undo the scaling from ellipsoid to sphere\n position = position * u_ellipsoidRadiiUv;\n\n float longitude = atan(position.y, position.x);\n vec3 east = normalize(vec3(-position.y, position.x, 0.0));\n\n // Convert the 3D position to a 2D position relative to the ellipse (radii.x, radii.z)\n // (assume radii.y == radii.x) and find the nearest point on the ellipse and its normal\n float distanceFromZAxis = length(position.xy);\n vec2 posEllipse = vec2(distanceFromZAxis, position.z);\n vec3 surfacePointAndRadius = nearestPointAndRadiusOnEllipse(posEllipse, u_ellipsoidRadiiUv.xz);\n vec2 surfacePoint = surfacePointAndRadius.xy;\n\n vec2 normal2d = normalize(surfacePoint * u_ellipsoidInverseRadiiSquaredUv.xz);\n float latitude = atan(normal2d.y, normal2d.x);\n vec3 north = vec3(-normal2d.y * normalize(position.xy), abs(normal2d.x));\n\n float heightSign = length(posEllipse) < length(surfacePoint) ? -1.0 : 1.0;\n float height = heightSign * length(posEllipse - surfacePoint);\n vec3 up = normalize(cross(east, north));\n\n vec3 point = vec3(longitude, latitude, height);\n mat3 jacobianT = mat3(east / distanceFromZAxis, north / (surfacePointAndRadius.z + height), up);\n return PointJacobianT(point, jacobianT);\n}\n\nvec3 convertShapeToShapeUvSpace(in vec3 positionShape) {\n // Longitude: shift & scale to [0, 1]\n float longitude = (positionShape.x + czm_pi) / czm_twoPi;\n\n // Correct the angle when max < min\n // Technically this should compare against min longitude - but it has precision problems so compare against the middle of empty space.\n #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_MIN_MAX_REVERSED)\n longitude += float(longitude < u_ellipsoidShapeUvLongitudeMinMaxMid.z);\n #endif\n\n // Avoid flickering from reading voxels from both sides of the -pi/+pi discontinuity.\n #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MIN_DISCONTINUITY)\n longitude = longitude > u_ellipsoidShapeUvLongitudeMinMaxMid.z ? u_ellipsoidShapeUvLongitudeMinMaxMid.x : longitude;\n #endif\n #if defined(ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MAX_DISCONTINUITY)\n longitude = longitude < u_ellipsoidShapeUvLongitudeMinMaxMid.z ? u_ellipsoidShapeUvLongitudeMinMaxMid.y : longitude;\n #endif\n\n #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE)\n longitude = longitude * u_ellipsoidUvToShapeUvLongitude.x + u_ellipsoidUvToShapeUvLongitude.y;\n #endif\n\n // Latitude: shift and scale to [0, 1]\n float latitude = (positionShape.y + czm_piOverTwo) / czm_pi;\n #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE)\n latitude = latitude * u_ellipsoidUvToShapeUvLatitude.x + u_ellipsoidUvToShapeUvLatitude.y;\n #endif\n\n // Height: scale to the range [0, 1]\n float height = 1.0 + positionShape.z * u_ellipsoidInverseHeightDifferenceUv;\n\n return vec3(longitude, latitude, height);\n}\n\nPointJacobianT convertUvToShapeUvSpaceDerivative(in vec3 positionUv) {\n PointJacobianT pointJacobian = convertUvToShapeSpaceDerivative(positionUv);\n pointJacobian.point = convertShapeToShapeUvSpace(pointJacobian.point);\n return pointJacobian;\n}\n\nvec3 scaleShapeUvToShapeSpace(in vec3 shapeUv) {\n // Convert from [0, 1] to radians [-pi, pi]\n float longitude = shapeUv.x * czm_twoPi;\n #if defined (ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE)\n longitude /= u_ellipsoidUvToShapeUvLongitude.x;\n #endif\n\n // Convert from [0, 1] to radians [-pi/2, pi/2]\n float latitude = shapeUv.y * czm_pi;\n #if defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE)\n latitude /= u_ellipsoidUvToShapeUvLatitude.x;\n #endif\n \n float height = shapeUv.z / u_ellipsoidInverseHeightDifferenceUv;\n\n return vec3(longitude, latitude, height);\n}\n";
// packages/engine/Source/Shaders/Voxels/Octree.js
var import_InlineWorkers1138 = __toESM(require_InlineWorkers(), 1);
var Octree_default = "// These octree flags must be in sync with GpuOctreeFlag in VoxelTraversal.js\n#define OCTREE_FLAG_INTERNAL 0\n#define OCTREE_FLAG_LEAF 1\n#define OCTREE_FLAG_PACKED_LEAF_FROM_PARENT 2\n\n#define OCTREE_MAX_LEVELS 32 // Harcoded value because GLSL doesn't like variable length loops\n\nuniform sampler2D u_octreeInternalNodeTexture;\nuniform vec2 u_octreeInternalNodeTexelSizeUv;\nuniform int u_octreeInternalNodeTilesPerRow;\n#if (SAMPLE_COUNT > 1)\nuniform sampler2D u_octreeLeafNodeTexture;\nuniform vec2 u_octreeLeafNodeTexelSizeUv;\nuniform int u_octreeLeafNodeTilesPerRow;\n#endif\nuniform ivec3 u_dimensions; // does not include padding, and is in the z-up orientation\nuniform ivec3 u_inputDimensions; // includes padding, and is in the orientation of the input data\n#if defined(PADDING)\n uniform ivec3 u_paddingBefore;\n#endif\n\nstruct OctreeNodeData {\n int data;\n int flag;\n};\n\nstruct TraversalData {\n ivec4 octreeCoords;\n int parentOctreeIndex;\n};\n\nstruct SampleData {\n int megatextureIndex;\n ivec4 tileCoords;\n vec3 tileUv;\n vec3 inputCoordinate;\n #if (SAMPLE_COUNT > 1)\n float weight;\n #endif\n};\n\n// Integer mod: For WebGL1 only\nint intMod(in int a, in int b) {\n return a - (b * (a / b));\n}\nint normU8_toInt(in float value) {\n return int(value * 255.0);\n}\nint normU8x2_toInt(in vec2 value) {\n return int(value.x * 255.0) + 256 * int(value.y * 255.0);\n}\nfloat normU8x2_toFloat(in vec2 value) {\n return float(normU8x2_toInt(value)) / 65535.0;\n}\n\nOctreeNodeData getOctreeNodeData(in vec2 octreeUv) {\n vec4 texData = texture(u_octreeInternalNodeTexture, octreeUv);\n\n OctreeNodeData data;\n data.data = normU8x2_toInt(texData.xy);\n data.flag = normU8x2_toInt(texData.zw);\n return data;\n}\n\nOctreeNodeData getOctreeChildData(in int parentOctreeIndex, in ivec3 childCoord) {\n int childIndex = childCoord.z * 4 + childCoord.y * 2 + childCoord.x;\n int octreeCoordX = intMod(parentOctreeIndex, u_octreeInternalNodeTilesPerRow) * 9 + 1 + childIndex;\n int octreeCoordY = parentOctreeIndex / u_octreeInternalNodeTilesPerRow;\n vec2 octreeUv = u_octreeInternalNodeTexelSizeUv * vec2(float(octreeCoordX) + 0.5, float(octreeCoordY) + 0.5);\n return getOctreeNodeData(octreeUv);\n}\n\nint getOctreeParentIndex(in int octreeIndex) {\n int octreeCoordX = intMod(octreeIndex, u_octreeInternalNodeTilesPerRow) * 9;\n int octreeCoordY = octreeIndex / u_octreeInternalNodeTilesPerRow;\n vec2 octreeUv = u_octreeInternalNodeTexelSizeUv * vec2(float(octreeCoordX) + 0.5, float(octreeCoordY) + 0.5);\n vec4 parentData = texture(u_octreeInternalNodeTexture, octreeUv);\n int parentOctreeIndex = normU8x2_toInt(parentData.xy);\n return parentOctreeIndex;\n}\n\n/**\n* Convert a position in the uv-space of the tileset bounding shape\n* into the uv-space of a tile within the tileset\n*/\nvec3 getTileUv(in vec3 shapePosition, in ivec4 octreeCoords) {\n // PERFORMANCE_IDEA: use bit-shifting (only in WebGL2)\n float dimAtLevel = exp2(float(octreeCoords.w));\n return shapePosition * dimAtLevel - vec3(octreeCoords.xyz);\n}\n\nvec3 getClampedTileUv(in vec3 shapePosition, in ivec4 octreeCoords) {\n vec3 tileUv = getTileUv(shapePosition, octreeCoords);\n return clamp(tileUv, vec3(0.0), vec3(1.0));\n}\n\nvoid addSampleCoordinates(in vec3 shapePosition, inout SampleData sampleData) {\n vec3 tileUv = getClampedTileUv(shapePosition, sampleData.tileCoords);\n\n vec3 inputCoordinate = tileUv * vec3(u_dimensions);\n#if defined(PADDING)\n inputCoordinate += vec3(u_paddingBefore);\n#endif\n#if defined(Y_UP_METADATA_ORDER)\n#if defined(SHAPE_BOX)\n float inputY = inputCoordinate.y;\n inputCoordinate.y = float(u_inputDimensions.y) - inputCoordinate.z;\n inputCoordinate.z = inputY;\n#elif defined(SHAPE_CYLINDER)\n float angle = inputCoordinate.y;\n float height = inputCoordinate.z;\n #if (!defined(CYLINDER_HAS_SHAPE_BOUNDS_ANGLE))\n // Account for the different 0-angle convention in glTF vs 3DTiles\n if (sampleData.tileCoords.w == 0) {\n float angleCount = float(u_inputDimensions.z);\n angle = mod(angle + angleCount / 2.0, angleCount);\n }\n #endif\n inputCoordinate.y = height;\n inputCoordinate.z = angle;\n#endif\n#endif\n\n sampleData.tileUv = tileUv;\n sampleData.inputCoordinate = inputCoordinate;\n}\n\nvoid getOctreeLeafSampleData(in OctreeNodeData data, in ivec4 octreeCoords, out SampleData sampleData) {\n sampleData.megatextureIndex = data.data;\n sampleData.tileCoords = (data.flag == OCTREE_FLAG_PACKED_LEAF_FROM_PARENT)\n ? ivec4(octreeCoords.xyz / 2, octreeCoords.w - 1)\n : octreeCoords;\n}\n\n#if (SAMPLE_COUNT > 1)\nvoid getOctreeLeafSampleDatas(in OctreeNodeData data, in ivec4 octreeCoords, out SampleData sampleDatas[SAMPLE_COUNT]) {\n int leafIndex = data.data;\n int leafNodeTexelCount = 2;\n // Adding 0.5 moves to the center of the texel\n float leafCoordXStart = float(intMod(leafIndex, u_octreeLeafNodeTilesPerRow) * leafNodeTexelCount) + 0.5;\n float leafCoordY = float(leafIndex / u_octreeLeafNodeTilesPerRow) + 0.5;\n\n // Get an interpolation weight and a flag to determine whether to read the parent texture\n vec2 leafUv0 = u_octreeLeafNodeTexelSizeUv * vec2(leafCoordXStart + 0.0, leafCoordY);\n vec4 leafData0 = texture(u_octreeLeafNodeTexture, leafUv0);\n float lerp = normU8x2_toFloat(leafData0.xy);\n sampleDatas[0].weight = 1.0 - lerp;\n sampleDatas[1].weight = lerp;\n // TODO: this looks wrong? Should be comparing to OCTREE_FLAG_PACKED_LEAF_FROM_PARENT\n sampleDatas[0].tileCoords = (normU8_toInt(leafData0.z) == 1)\n ? ivec4(octreeCoords.xyz / 2, octreeCoords.w - 1)\n : octreeCoords;\n sampleDatas[1].tileCoords = (normU8_toInt(leafData0.w) == 1)\n ? ivec4(octreeCoords.xyz / 2, octreeCoords.w - 1)\n : octreeCoords;\n\n // Get megatexture indices for both samples\n vec2 leafUv1 = u_octreeLeafNodeTexelSizeUv * vec2(leafCoordXStart + 1.0, leafCoordY);\n vec4 leafData1 = texture(u_octreeLeafNodeTexture, leafUv1);\n sampleDatas[0].megatextureIndex = normU8x2_toInt(leafData1.xy);\n sampleDatas[1].megatextureIndex = normU8x2_toInt(leafData1.zw);\n}\n#endif\n\nOctreeNodeData traverseOctreeDownwards(in vec3 shapePosition, inout TraversalData traversalData) {\n float sizeAtLevel = exp2(-1.0 * float(traversalData.octreeCoords.w));\n vec3 start = vec3(traversalData.octreeCoords.xyz) * sizeAtLevel;\n vec3 end = start + vec3(sizeAtLevel);\n OctreeNodeData childData;\n\n for (int i = 0; i < OCTREE_MAX_LEVELS; ++i) {\n // Find out which octree child contains the position\n // 0 if before center, 1 if after\n vec3 center = 0.5 * (start + end);\n vec3 childCoord = step(center, shapePosition);\n\n // Get octree coords for the next level down\n ivec4 octreeCoords = traversalData.octreeCoords;\n traversalData.octreeCoords = ivec4(octreeCoords.xyz * 2 + ivec3(childCoord), octreeCoords.w + 1);\n\n childData = getOctreeChildData(traversalData.parentOctreeIndex, ivec3(childCoord));\n\n if (childData.flag != OCTREE_FLAG_INTERNAL) {\n // leaf tile - stop traversing\n break;\n }\n\n // interior tile - keep going deeper\n start = mix(start, center, childCoord);\n end = mix(center, end, childCoord);\n traversalData.parentOctreeIndex = childData.data;\n }\n\n return childData;\n}\n\n/**\n* Transform a given position to an octree tile coordinate and a position within that tile,\n* and find the corresponding megatexture index and texture coordinates\n*/\nvoid traverseOctreeFromBeginning(in vec3 shapePosition, out TraversalData traversalData, out SampleData sampleDatas[SAMPLE_COUNT]) {\n traversalData.octreeCoords = ivec4(0);\n traversalData.parentOctreeIndex = 0;\n\n OctreeNodeData nodeData = getOctreeNodeData(vec2(0.0));\n if (nodeData.flag != OCTREE_FLAG_LEAF) {\n nodeData = traverseOctreeDownwards(shapePosition, traversalData);\n }\n\n #if (SAMPLE_COUNT == 1)\n getOctreeLeafSampleData(nodeData, traversalData.octreeCoords, sampleDatas[0]);\n addSampleCoordinates(shapePosition, sampleDatas[0]);\n #else\n getOctreeLeafSampleDatas(nodeData, traversalData.octreeCoords, sampleDatas);\n addSampleCoordinates(shapePosition, sampleDatas[0]);\n addSampleCoordinates(shapePosition, sampleDatas[1]);\n #endif\n}\n\nbool inRange(in vec3 v, in vec3 minVal, in vec3 maxVal) {\n return clamp(v, minVal, maxVal) == v;\n}\n\nbool insideTile(in vec3 shapePosition, in ivec4 octreeCoords) {\n vec3 tileUv = getTileUv(shapePosition, octreeCoords);\n bool inside = inRange(tileUv, vec3(0.0), vec3(1.0));\n // Assume (!) the position is always inside the root tile.\n return inside || octreeCoords.w == 0;\n}\n\nvoid traverseOctreeFromExisting(in vec3 shapePosition, inout TraversalData traversalData, inout SampleData sampleDatas[SAMPLE_COUNT]) {\n if (insideTile(shapePosition, traversalData.octreeCoords)) {\n for (int i = 0; i < SAMPLE_COUNT; i++) {\n addSampleCoordinates(shapePosition, sampleDatas[i]);\n }\n return;\n }\n\n // Go up tree until we find a parent tile containing shapePosition\n for (int i = 0; i < OCTREE_MAX_LEVELS; ++i) {\n traversalData.octreeCoords.xyz /= 2;\n traversalData.octreeCoords.w -= 1;\n\n if (insideTile(shapePosition, traversalData.octreeCoords)) {\n break;\n }\n\n traversalData.parentOctreeIndex = getOctreeParentIndex(traversalData.parentOctreeIndex);\n }\n\n // Go down tree\n OctreeNodeData nodeData = traverseOctreeDownwards(shapePosition, traversalData);\n\n #if (SAMPLE_COUNT == 1)\n getOctreeLeafSampleData(nodeData, traversalData.octreeCoords, sampleDatas[0]);\n addSampleCoordinates(shapePosition, sampleDatas[0]);\n #else\n getOctreeLeafSampleDatas(nodeData, traversalData.octreeCoords, sampleDatas);\n addSampleCoordinates(shapePosition, sampleDatas[0]);\n addSampleCoordinates(shapePosition, sampleDatas[1]);\n #endif\n}\n";
// packages/engine/Source/Shaders/Voxels/Megatexture.js
var import_InlineWorkers1139 = __toESM(require_InlineWorkers(), 1);
var Megatexture_default = "// See Octree.glsl for the definitions of SampleData and intMod\n\n/* Megatexture defines (set in Scene/VoxelRenderResources.js)\n#define SAMPLE_COUNT ###\n#define NEAREST_SAMPLING\n#define PADDING\n*/\n\nuniform ivec2 u_megatextureSliceDimensions; // number of slices per tile, in two dimensions\nuniform ivec2 u_megatextureTileDimensions; // number of tiles per megatexture, in two dimensions\nuniform vec2 u_megatextureVoxelSizeUv;\nuniform vec2 u_megatextureSliceSizeUv;\nuniform vec2 u_megatextureTileSizeUv;\n\n// Integer min, max, clamp: For WebGL1 only\nint intMin(int a, int b) {\n return a <= b ? a : b;\n}\nint intMax(int a, int b) {\n return a >= b ? a : b;\n}\nint intClamp(int v, int minVal, int maxVal) {\n return intMin(intMax(v, minVal), maxVal);\n}\n\nvec2 index1DTo2DTexcoord(int index, ivec2 dimensions, vec2 uvScale)\n{\n int indexX = intMod(index, dimensions.x);\n int indexY = index / dimensions.x;\n return vec2(indexX, indexY) * uvScale;\n}\n\n/*\n How is 3D data stored in a 2D megatexture?\n\n In this example there is only one loaded tile and it has 2x2x2 voxels (8 voxels total).\n The data is sliced by Z. The data at Z = 0 is placed in texels (0,0), (0,1), (1,0), (1,1) and\n the data at Z = 1 is placed in texels (2,0), (2,1), (3,0), (3,1).\n Note that there could be empty space in the megatexture because it's a power of two.\n\n 0 1 2 3\n +---+---+---+---+\n | | | | | 3\n +---+---+---+---+\n | | | | | 2\n +-------+-------+\n |010|110|011|111| 1\n |--- ---|--- ---|\n |000|100|001|101| 0\n +-------+-------+\n\n When doing linear interpolation the megatexture needs to be sampled twice: once for\n the Z slice above the voxel coordinate and once for the slice below. The two slices\n are interpolated with fract(coord.z - 0.5). For example, a Z coordinate of 1.0 is\n halfway between two Z slices so the interpolation factor is 0.5. Below is a side view\n of the 3D voxel grid with voxel coordinates on the left side.\n\n 2 +---+\n |001|\n 1 +-z-+\n |000|\n 0 +---+\n\n When doing nearest neighbor the megatexture only needs to be sampled once at the closest Z slice.\n*/\n\nProperties getPropertiesFromMegatexture(in SampleData sampleData) {\n int tileIndex = sampleData.megatextureIndex;\n\n vec3 voxelCoord = sampleData.inputCoordinate;\n #if defined(NEAREST_SAMPLING)\n // Round to the center of the nearest voxel\n voxelCoord = floor(voxelCoord) + vec3(0.5);\n #endif\n\n // Tile location\n vec2 tileUvOffset = index1DTo2DTexcoord(tileIndex, u_megatextureTileDimensions, u_megatextureTileSizeUv);\n\n // Slice location\n float slice = voxelCoord.z - 0.5;\n int sliceIndex = int(floor(slice));\n int sliceIndex0 = intClamp(sliceIndex, 0, u_inputDimensions.z - 1);\n vec2 sliceUvOffset0 = index1DTo2DTexcoord(sliceIndex0, u_megatextureSliceDimensions, u_megatextureSliceSizeUv);\n\n // Voxel location\n vec2 voxelUvOffset = clamp(voxelCoord.xy, vec2(0.5), vec2(u_inputDimensions.xy) - vec2(0.5)) * u_megatextureVoxelSizeUv;\n\n // Final location in the megatexture\n vec2 uv0 = tileUvOffset + sliceUvOffset0 + voxelUvOffset;\n\n #if defined(NEAREST_SAMPLING)\n return getPropertiesFromMegatextureAtUv(uv0);\n #else\n float sliceLerp = fract(slice);\n int sliceIndex1 = intMin(sliceIndex + 1, u_inputDimensions.z - 1);\n vec2 sliceUvOffset1 = index1DTo2DTexcoord(sliceIndex1, u_megatextureSliceDimensions, u_megatextureSliceSizeUv);\n vec2 uv1 = tileUvOffset + sliceUvOffset1 + voxelUvOffset;\n Properties properties0 = getPropertiesFromMegatextureAtUv(uv0);\n Properties properties1 = getPropertiesFromMegatextureAtUv(uv1);\n return mixProperties(properties0, properties1, sliceLerp);\n #endif\n}\n\n// Convert an array of sample datas to a final weighted properties.\nProperties accumulatePropertiesFromMegatexture(in SampleData sampleDatas[SAMPLE_COUNT]) {\n #if (SAMPLE_COUNT == 1)\n return getPropertiesFromMegatexture(sampleDatas[0]);\n #else\n // When more than one sample is taken the accumulator needs to start at 0\n Properties properties = clearProperties();\n for (int i = 0; i < SAMPLE_COUNT; ++i) {\n float weight = sampleDatas[i].weight;\n\n // Avoid reading the megatexture when the weight is 0 as it can be costly.\n if (weight > 0.0) {\n Properties tempProperties = getPropertiesFromMegatexture(sampleDatas[i]);\n tempProperties = scaleProperties(tempProperties, weight);\n properties = sumProperties(properties, tempProperties);\n }\n }\n return properties;\n #endif\n}\n";
// packages/engine/Source/Scene/VoxelMetadataOrder.js
var import_InlineWorkers1140 = __toESM(require_InlineWorkers(), 1);
var VoxelMetadataOrder = {
/**
* The default ordering following the 3D Tiles convention. Z-axis points upward.
* @type {number}
* @constant
*/
Z_UP: 0,
/**
* The ordering following the glTF convention. Y-axis points upward.
* @type {number}
* @constant
*/
Y_UP: 1
};
var VoxelMetadataOrder_default = Object.freeze(VoxelMetadataOrder);
// packages/engine/Source/Scene/VoxelRenderResources.js
function VoxelRenderResources(primitive) {
const shaderBuilder = new ShaderBuilder_default();
this.shaderBuilder = shaderBuilder;
const customShader = primitive._customShader;
const uniformMap2 = combine_default(primitive._uniformMap, customShader.uniformMap);
primitive._uniformMap = uniformMap2;
const customShaderUniforms = customShader.uniforms;
for (const uniformName in customShaderUniforms) {
if (customShaderUniforms.hasOwnProperty(uniformName)) {
const uniform = customShaderUniforms[uniformName];
shaderBuilder.addUniform(
uniform.type,
uniformName,
ShaderDestination_default.FRAGMENT
);
}
}
shaderBuilder.addUniform(
"sampler2D",
"u_megatextureTextures[METADATA_COUNT]",
ShaderDestination_default.FRAGMENT
);
this.uniformMap = uniformMap2;
const clippingPlanes = primitive._clippingPlanes;
const clippingPlanesLength = defined_default(clippingPlanes) && clippingPlanes.enabled ? clippingPlanes.length : 0;
this.clippingPlanes = clippingPlanes;
this.clippingPlanesLength = clippingPlanesLength;
shaderBuilder.addVertexLines([VoxelVS_default]);
if (primitive.provider.metadataOrder === VoxelMetadataOrder_default.Y_UP) {
shaderBuilder.addDefine(
"Y_UP_METADATA_ORDER",
void 0,
ShaderDestination_default.FRAGMENT
);
}
const shapeType = primitive._provider.shape;
if (shapeType === "BOX") {
shaderBuilder.addDefine("SHAPE_BOX", void 0, ShaderDestination_default.FRAGMENT);
} else if (shapeType === "CYLINDER") {
shaderBuilder.addDefine(
"SHAPE_CYLINDER",
void 0,
ShaderDestination_default.FRAGMENT
);
} else if (shapeType === "ELLIPSOID") {
shaderBuilder.addDefine(
"SHAPE_ELLIPSOID",
void 0,
ShaderDestination_default.FRAGMENT
);
}
shaderBuilder.addFragmentLines([
customShader.fragmentShaderText,
"#line 0",
Octree_default,
VoxelUtils_default,
IntersectionUtils_default,
Megatexture_default
]);
if (clippingPlanesLength > 0) {
shaderBuilder.addDefine(
"CLIPPING_PLANES",
void 0,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addDefine(
"CLIPPING_PLANES_COUNT",
clippingPlanesLength,
ShaderDestination_default.FRAGMENT
);
if (clippingPlanes.unionClippingRegions) {
shaderBuilder.addDefine(
"CLIPPING_PLANES_UNION",
void 0,
ShaderDestination_default.FRAGMENT
);
}
shaderBuilder.addFragmentLines([IntersectClippingPlanes_default]);
}
shaderBuilder.addFragmentLines([IntersectDepth_default]);
if (primitive._depthTest) {
shaderBuilder.addDefine(
"DEPTH_TEST",
void 0,
ShaderDestination_default.FRAGMENT
);
}
if (shapeType === "BOX") {
shaderBuilder.addFragmentLines([
convertUvToBox_default,
IntersectBox_default,
Intersection_default
]);
} else if (shapeType === "CYLINDER") {
shaderBuilder.addFragmentLines([
convertUvToCylinder_default,
IntersectLongitude_default,
IntersectCylinder_default,
Intersection_default
]);
} else if (shapeType === "ELLIPSOID") {
shaderBuilder.addFragmentLines([
convertUvToEllipsoid_default,
IntersectLongitude_default,
IntersectEllipsoid_default,
Intersection_default
]);
}
shaderBuilder.addFragmentLines([VoxelFS_default]);
const shape = primitive._shape;
const shapeDefines = shape.shaderDefines;
for (const key in shapeDefines) {
if (shapeDefines.hasOwnProperty(key)) {
let value = shapeDefines[key];
if (defined_default(value)) {
value = value === true ? void 0 : value;
shaderBuilder.addDefine(key, value, ShaderDestination_default.FRAGMENT);
}
}
}
let intersectionCount = shape.shaderMaximumIntersectionsLength;
if (clippingPlanesLength > 0) {
shaderBuilder.addDefine(
"CLIPPING_PLANES_INTERSECTION_INDEX",
intersectionCount,
ShaderDestination_default.FRAGMENT
);
if (clippingPlanesLength === 1) {
intersectionCount += 1;
} else if (clippingPlanes.unionClippingRegions) {
intersectionCount += 2;
} else {
intersectionCount += 1;
}
}
if (primitive._depthTest) {
shaderBuilder.addDefine(
"DEPTH_INTERSECTION_INDEX",
intersectionCount,
ShaderDestination_default.FRAGMENT
);
intersectionCount += 1;
}
shaderBuilder.addDefine(
"INTERSECTION_COUNT",
intersectionCount,
ShaderDestination_default.FRAGMENT
);
if (!Cartesian3_default.equals(primitive.paddingBefore, Cartesian3_default.ZERO) || !Cartesian3_default.equals(primitive.paddingAfter, Cartesian3_default.ZERO)) {
shaderBuilder.addDefine("PADDING", void 0, ShaderDestination_default.FRAGMENT);
}
if (primitive._useLogDepth) {
shaderBuilder.addDefine(
"LOG_DEPTH_READ_ONLY",
void 0,
ShaderDestination_default.FRAGMENT
);
}
if (primitive._nearestSampling) {
shaderBuilder.addDefine(
"NEAREST_SAMPLING",
void 0,
ShaderDestination_default.FRAGMENT
);
}
const traversal4 = primitive._traversal;
shaderBuilder.addDefine(
"SAMPLE_COUNT",
`${traversal4._sampleCount}`,
ShaderDestination_default.FRAGMENT
);
}
var VoxelRenderResources_default = VoxelRenderResources;
// packages/engine/Source/Scene/processVoxelProperties.js
var import_InlineWorkers1142 = __toESM(require_InlineWorkers(), 1);
function processVoxelProperties(renderResources, primitive) {
const { shaderBuilder } = renderResources;
const { names, types, componentTypes, minimumValues, maximumValues } = primitive._provider;
const attributeLength = types.length;
const hasStatistics = defined_default(minimumValues) && defined_default(maximumValues);
shaderBuilder.addDefine(
"METADATA_COUNT",
attributeLength,
ShaderDestination_default.FRAGMENT
);
if (hasStatistics) {
shaderBuilder.addDefine(
"STATISTICS",
void 0,
ShaderDestination_default.FRAGMENT
);
}
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const glslType = getGlslType2(types[i]);
const propertyStatisticsStructId = `PropertyStatistics_${name}`;
const propertyStatisticsStructName = `PropertyStatistics_${name}`;
shaderBuilder.addStruct(
propertyStatisticsStructId,
propertyStatisticsStructName,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addStructField(propertyStatisticsStructId, glslType, "min");
shaderBuilder.addStructField(propertyStatisticsStructId, glslType, "max");
}
const metadataStatisticsStructId = "MetadataStatistics";
const metadataStatisticsStructName = "MetadataStatistics";
const metadataStatisticsFieldName = "metadataStatistics";
shaderBuilder.addStruct(
metadataStatisticsStructId,
metadataStatisticsStructName,
ShaderDestination_default.FRAGMENT
);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const propertyStructName = `PropertyStatistics_${name}`;
const propertyFieldName = name;
shaderBuilder.addStructField(
metadataStatisticsStructId,
propertyStructName,
propertyFieldName
);
}
const metadataStructId = "Metadata";
const metadataStructName = "Metadata";
const metadataFieldName = "metadata";
shaderBuilder.addStruct(
metadataStructId,
metadataStructName,
ShaderDestination_default.FRAGMENT
);
for (let i = 0; i < attributeLength; i++) {
const glslType = getGlslType2(types[i]);
shaderBuilder.addStructField(metadataStructId, glslType, names[i]);
}
const attributesStructId = "Attributes";
const attributesStructName = "Attributes";
const attributesFieldName = "attributes";
shaderBuilder.addStruct(
attributesStructId,
attributesStructName,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addStructField(attributesStructId, "vec3", "positionEC");
shaderBuilder.addStructField(attributesStructId, "vec3", "normalEC");
const voxelStructId = "Voxel";
const voxelStructName = "Voxel";
const voxelFieldName = "voxel";
shaderBuilder.addStruct(
voxelStructId,
voxelStructName,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addStructField(voxelStructId, "vec3", "viewDirUv");
shaderBuilder.addStructField(voxelStructId, "float", "travelDistance");
shaderBuilder.addStructField(voxelStructId, "int", "stepCount");
shaderBuilder.addStructField(voxelStructId, "int", "tileIndex");
shaderBuilder.addStructField(voxelStructId, "int", "sampleIndex");
shaderBuilder.addStructField(voxelStructId, "float", "distanceToDepthBuffer");
const fragmentInputStructId = "FragmentInput";
const fragmentInputStructName = "FragmentInput";
shaderBuilder.addStruct(
fragmentInputStructId,
fragmentInputStructName,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addStructField(
fragmentInputStructId,
metadataStatisticsStructName,
metadataStatisticsFieldName
);
shaderBuilder.addStructField(
fragmentInputStructId,
metadataStructName,
metadataFieldName
);
shaderBuilder.addStructField(
fragmentInputStructId,
attributesStructName,
attributesFieldName
);
shaderBuilder.addStructField(
fragmentInputStructId,
voxelStructName,
voxelFieldName
);
const propertiesStructId = "Properties";
const propertiesStructName = "Properties";
const propertiesFieldName = "properties";
shaderBuilder.addStruct(
propertiesStructId,
propertiesStructName,
ShaderDestination_default.FRAGMENT
);
for (let i = 0; i < attributeLength; i++) {
const glslType = getGlslType2(types[i]);
shaderBuilder.addStructField(propertiesStructId, glslType, names[i]);
}
{
const functionId = "clearProperties";
shaderBuilder.addFunction(
functionId,
`${propertiesStructName} clearProperties()`,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesStructName} ${propertiesFieldName};`
]);
for (let i = 0; i < attributeLength; i++) {
const glslType = getGlslType2(types[i], componentTypes[i]);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesFieldName}.${names[i]} = ${glslType}(0.0);`
]);
}
shaderBuilder.addFunctionLines(functionId, [
`return ${propertiesFieldName};`
]);
}
{
const functionId = "sumProperties";
shaderBuilder.addFunction(
functionId,
`${propertiesStructName} sumProperties(${propertiesStructName} propertiesA, ${propertiesStructName} propertiesB)`,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesStructName} ${propertiesFieldName};`
]);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
shaderBuilder.addFunctionLines(functionId, [
`${propertiesFieldName}.${name} = propertiesA.${name} + propertiesB.${name};`
]);
}
shaderBuilder.addFunctionLines(functionId, [
`return ${propertiesFieldName};`
]);
}
{
const functionId = "scaleProperties";
shaderBuilder.addFunction(
functionId,
`${propertiesStructName} scaleProperties(${propertiesStructName} ${propertiesFieldName}, float scale)`,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesStructName} scaledProperties = ${propertiesFieldName};`
]);
for (let i = 0; i < attributeLength; i++) {
shaderBuilder.addFunctionLines(functionId, [
`scaledProperties.${names[i]} *= scale;`
]);
}
shaderBuilder.addFunctionLines(functionId, [`return scaledProperties;`]);
}
{
const functionId = "mixProperties";
shaderBuilder.addFunction(
functionId,
`${propertiesStructName} mixProperties(${propertiesStructName} propertiesA, ${propertiesStructName} propertiesB, float mixFactor)`,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesStructName} ${propertiesFieldName};`
]);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
shaderBuilder.addFunctionLines(functionId, [
`${propertiesFieldName}.${name} = mix(propertiesA.${name}, propertiesB.${name}, mixFactor);`
]);
}
shaderBuilder.addFunctionLines(functionId, [
`return ${propertiesFieldName};`
]);
}
{
const functionId = "copyPropertiesToMetadata";
shaderBuilder.addFunction(
functionId,
`void copyPropertiesToMetadata(in ${propertiesStructName} ${propertiesFieldName}, inout ${metadataStructName} ${metadataFieldName})`,
ShaderDestination_default.FRAGMENT
);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
shaderBuilder.addFunctionLines(functionId, [
`${metadataFieldName}.${name} = ${propertiesFieldName}.${name};`
]);
}
}
if (hasStatistics) {
const functionId = "setStatistics";
shaderBuilder.addFunction(
functionId,
`void setStatistics(inout ${metadataStatisticsStructName} ${metadataStatisticsFieldName})`,
ShaderDestination_default.FRAGMENT
);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const type = types[i];
const componentCount = MetadataType_default.getComponentCount(type);
for (let j = 0; j < componentCount; j++) {
const glslField = getGlslField(type, j);
const minimumValue = minimumValues[i][j];
const maximumValue = maximumValues[i][j];
if (!defined_default(minimumValue) || !defined_default(maximumValue)) {
continue;
}
shaderBuilder.addFunctionLines(functionId, [
`${metadataStatisticsFieldName}.${name}.min${glslField} = ${getGlslNumberAsFloat(
minimumValue
)};`,
`${metadataStatisticsFieldName}.${name}.max${glslField} = ${getGlslNumberAsFloat(
maximumValue
)};`
]);
}
}
}
{
const functionId = "getPropertiesFromMegatextureAtUv";
shaderBuilder.addFunction(
functionId,
`${propertiesStructName} getPropertiesFromMegatextureAtUv(vec2 texcoord)`,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesStructName} ${propertiesFieldName};`
]);
for (let i = 0; i < attributeLength; i++) {
const type = types[i];
const componentType = componentTypes[i];
const glslTextureSwizzle = getGlslTextureSwizzle(type, componentType);
shaderBuilder.addFunctionLines(functionId, [
`properties.${names[i]} = texture(u_megatextureTextures[${i}], texcoord)${glslTextureSwizzle};`
]);
}
shaderBuilder.addFunctionLines(functionId, [
`return ${propertiesFieldName};`
]);
}
}
function getGlslType2(type) {
if (type === MetadataType_default.SCALAR) {
return "float";
} else if (type === MetadataType_default.VEC2) {
return "vec2";
} else if (type === MetadataType_default.VEC3) {
return "vec3";
} else if (type === MetadataType_default.VEC4) {
return "vec4";
}
}
function getGlslTextureSwizzle(type) {
if (type === MetadataType_default.SCALAR) {
return ".r";
} else if (type === MetadataType_default.VEC2) {
return ".ra";
} else if (type === MetadataType_default.VEC3) {
return ".rgb";
} else if (type === MetadataType_default.VEC4) {
return "";
}
}
function getGlslNumberAsFloat(number) {
let numberString = number.toString();
if (numberString.indexOf(".") === -1) {
numberString = `${number}.0`;
}
return numberString;
}
function getGlslField(type, index) {
if (type === MetadataType_default.SCALAR) {
return "";
}
return `[${index}]`;
}
var processVoxelProperties_default = processVoxelProperties;
// packages/engine/Source/Scene/buildVoxelDrawCommands.js
function buildVoxelDrawCommands(primitive, context) {
const renderResources = new VoxelRenderResources_default(primitive);
processVoxelProperties_default(renderResources, primitive);
const { shaderBuilder, clippingPlanes, clippingPlanesLength } = renderResources;
if (clippingPlanesLength > 0) {
const functionId = "getClippingPlane";
const entireFunction = getClippingFunction_default(clippingPlanes, context);
const functionSignatureBegin = 0;
const functionSignatureEnd = entireFunction.indexOf(")") + 1;
const functionBodyBegin = entireFunction.indexOf("{", functionSignatureEnd) + 1;
const functionBodyEnd = entireFunction.indexOf("}", functionBodyBegin);
const functionSignature = entireFunction.slice(
functionSignatureBegin,
functionSignatureEnd
);
const functionBody = entireFunction.slice(
functionBodyBegin,
functionBodyEnd
);
shaderBuilder.addFunction(
functionId,
functionSignature,
ShaderDestination_default.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [functionBody]);
}
const shaderBuilderPick = shaderBuilder.clone();
shaderBuilderPick.addDefine("PICKING", void 0, ShaderDestination_default.FRAGMENT);
const shaderBuilderPickVoxel = shaderBuilder.clone();
shaderBuilderPickVoxel.addDefine(
"PICKING_VOXEL",
void 0,
ShaderDestination_default.FRAGMENT
);
const shaderProgram = shaderBuilder.buildShaderProgram(context);
const shaderProgramPick = shaderBuilderPick.buildShaderProgram(context);
const shaderProgramPickVoxel = shaderBuilderPickVoxel.buildShaderProgram(context);
const renderState = RenderState_default.fromCache({
cull: {
enabled: true,
face: CullFace_default.BACK
},
depthTest: {
enabled: false
},
depthMask: false,
// internally the shader does premultiplied alpha, so it makes sense to blend that way too
blending: BlendingState_default.PRE_MULTIPLIED_ALPHA_BLEND
});
const viewportQuadVertexArray = context.getViewportQuadVertexArray();
const depthTest = primitive._depthTest;
const drawCommand = new DrawCommand_default({
vertexArray: viewportQuadVertexArray,
primitiveType: PrimitiveType_default.TRIANGLES,
renderState,
shaderProgram,
uniformMap: renderResources.uniformMap,
modelMatrix: primitive._compoundModelMatrix,
pass: Pass_default.VOXELS,
executeInClosestFrustum: true,
owner: this,
cull: depthTest,
// don't cull or occlude if depth testing is off
occlude: depthTest
// don't cull or occlude if depth testing is off
});
const drawCommandPick = DrawCommand_default.shallowClone(
drawCommand,
new DrawCommand_default()
);
drawCommandPick.shaderProgram = shaderProgramPick;
drawCommandPick.pickOnly = true;
const drawCommandPickVoxel = DrawCommand_default.shallowClone(
drawCommand,
new DrawCommand_default()
);
drawCommandPickVoxel.shaderProgram = shaderProgramPickVoxel;
drawCommandPickVoxel.pickOnly = true;
if (defined_default(primitive._drawCommand)) {
const command = primitive._drawCommand;
command.shaderProgram = command.shaderProgram && command.shaderProgram.destroy();
}
if (defined_default(primitive._drawCommandPick)) {
const command = primitive._drawCommandPick;
command.shaderProgram = command.shaderProgram && command.shaderProgram.destroy();
}
if (defined_default(primitive._drawCommandPickVoxel)) {
const command = primitive._drawCommandPickVoxel;
command.shaderProgram = command.shaderProgram && command.shaderProgram.destroy();
}
primitive._drawCommand = drawCommand;
primitive._drawCommandPick = drawCommandPick;
primitive._drawCommandPickVoxel = drawCommandPickVoxel;
}
var buildVoxelDrawCommands_default = buildVoxelDrawCommands;
// packages/engine/Source/Scene/Model/CustomShader.js
var import_InlineWorkers1147 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/Model/UniformType.js
var import_InlineWorkers1144 = __toESM(require_InlineWorkers(), 1);
var UniformType = {
/**
* A single floating point value.
*
* @type {string}
* @constant
*/
FLOAT: "float",
/**
* A vector of 2 floating point values.
*
* @type {string}
* @constant
*/
VEC2: "vec2",
/**
* A vector of 3 floating point values.
*
* @type {string}
* @constant
*/
VEC3: "vec3",
/**
* A vector of 4 floating point values.
*
* @type {string}
* @constant
*/
VEC4: "vec4",
/**
* A single integer value
*
* @type {string}
* @constant
*/
INT: "int",
/**
* A vector of 2 integer values.
*
* @type {string}
* @constant
*/
INT_VEC2: "ivec2",
/**
* A vector of 3 integer values.
*
* @type {string}
* @constant
*/
INT_VEC3: "ivec3",
/**
* A vector of 4 integer values.
*
* @type {string}
* @constant
*/
INT_VEC4: "ivec4",
/**
* A single boolean value.
*
* @type {string}
* @constant
*/
BOOL: "bool",
/**
* A vector of 2 boolean values.
*
* @type {string}
* @constant
*/
BOOL_VEC2: "bvec2",
/**
* A vector of 3 boolean values.
*
* @type {string}
* @constant
*/
BOOL_VEC3: "bvec3",
/**
* A vector of 4 boolean values.
*
* @type {string}
* @constant
*/
BOOL_VEC4: "bvec4",
/**
* A 2x2 matrix of floating point values.
*
* @type {string}
* @constant
*/
MAT2: "mat2",
/**
* A 3x3 matrix of floating point values.
*
* @type {string}
* @constant
*/
MAT3: "mat3",
/**
* A 4x4 matrix of floating point values.
*
* @type {string}
* @constant
*/
MAT4: "mat4",
/**
* A 2D sampled texture.
* @type {string}
* @constant
*/
SAMPLER_2D: "sampler2D",
SAMPLER_CUBE: "samplerCube"
};
var UniformType_default = Object.freeze(UniformType);
// packages/engine/Source/Scene/Model/TextureManager.js
var import_InlineWorkers1146 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/getImageFromTypedArray.js
var import_InlineWorkers1145 = __toESM(require_InlineWorkers(), 1);
function getImageFromTypedArray(typedArray, width, height) {
const dataArray = new Uint8ClampedArray(typedArray.buffer);
const imageData = new ImageData(dataArray, width, height);
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
canvas.getContext("2d").putImageData(imageData, 0, 0);
return canvas;
}
var getImageFromTypedArray_default = getImageFromTypedArray;
// packages/engine/Source/Scene/Model/TextureManager.js
function TextureManager() {
this._defaultTexture = void 0;
this._textures = {};
this._loadedImages = [];
this._lastUpdatedFrame = -1;
}
TextureManager.prototype.getTexture = function(textureId) {
return this._textures[textureId];
};
function fetchTexture2D(textureManager, textureId, textureUniform) {
textureUniform.resource.fetchImage().then(function(image) {
textureManager._loadedImages.push({
id: textureId,
image,
textureUniform
});
}).catch(function() {
const texture = textureManager._textures[textureId];
if (defined_default(texture) && texture !== textureManager._defaultTexture) {
texture.destroy();
}
textureManager._textures[textureId] = textureManager._defaultTexture;
});
}
TextureManager.prototype.loadTexture2D = function(textureId, textureUniform) {
if (defined_default(textureUniform.typedArray)) {
this._loadedImages.push({
id: textureId,
textureUniform
});
} else {
fetchTexture2D(this, textureId, textureUniform);
}
};
function createTexture4(textureManager, loadedImage, context) {
const { id, textureUniform, image } = loadedImage;
const texture = context.webgl2 ? getTextureAndMips(textureUniform, image, context) : getWebGL1Texture(textureUniform, image, context);
const oldTexture = textureManager._textures[id];
if (defined_default(oldTexture) && oldTexture !== context.defaultTexture) {
oldTexture.destroy();
}
textureManager._textures[id] = texture;
}
function getTextureAndMips(textureUniform, image, context) {
const { typedArray, sampler } = textureUniform;
const texture = defined_default(typedArray) ? getTextureFromTypedArray(textureUniform, context) : new Texture_default({ context, source: image, sampler });
if (samplerRequiresMipmap(sampler)) {
texture.generateMipmap();
}
return texture;
}
function getWebGL1Texture(textureUniform, image, context) {
const { typedArray, sampler } = textureUniform;
const needMipmap = samplerRequiresMipmap(sampler);
const samplerRepeats = sampler.wrapS === TextureWrap_default.REPEAT || sampler.wrapS === TextureWrap_default.MIRRORED_REPEAT || sampler.wrapT === TextureWrap_default.REPEAT || sampler.wrapT === TextureWrap_default.MIRRORED_REPEAT;
const { width, height } = defined_default(typedArray) ? textureUniform : image;
const isPowerOfTwo = [width, height].every(Math_default.isPowerOfTwo);
const requiresResize = (needMipmap || samplerRepeats) && !isPowerOfTwo;
if (!requiresResize) {
return getTextureAndMips(textureUniform, image, context);
} else if (!defined_default(typedArray)) {
const resizedImage = resizeImageToNextPowerOfTwo_default(image);
return getTextureAndMips(textureUniform, resizedImage, context);
} else if (textureUniform.pixelDatatype === PixelDatatype_default.UNSIGNED_BYTE) {
const imageFromArray = getImageFromTypedArray_default(typedArray, width, height);
const resizedImage = resizeImageToNextPowerOfTwo_default(imageFromArray);
return getTextureAndMips({ sampler }, resizedImage, context);
}
if (needMipmap) {
console.warn(
"Texture requires resizing for mipmaps but pixelDataType cannot be resized. The texture may be rendered incorrectly."
);
} else if (samplerRepeats) {
console.warn(
"Texture requires resizing for wrapping but pixelDataType cannot be resized. The texture may be rendered incorrectly."
);
}
return getTextureFromTypedArray(textureUniform, context);
}
function samplerRequiresMipmap(sampler) {
return [
TextureMinificationFilter_default.NEAREST_MIPMAP_NEAREST,
TextureMinificationFilter_default.NEAREST_MIPMAP_LINEAR,
TextureMinificationFilter_default.LINEAR_MIPMAP_NEAREST,
TextureMinificationFilter_default.LINEAR_MIPMAP_LINEAR
].includes(sampler.minificationFilter);
}
function getTextureFromTypedArray(textureUniform, context) {
const {
pixelFormat,
pixelDatatype,
width,
height,
typedArray: arrayBufferView,
sampler
} = textureUniform;
return new Texture_default({
context,
pixelFormat,
pixelDatatype,
source: { arrayBufferView, width, height },
sampler,
flipY: false
});
}
TextureManager.prototype.update = function(frameState) {
if (frameState.frameNumber === this._lastUpdatedFrame) {
return;
}
this._lastUpdatedFrame = frameState.frameNumber;
const context = frameState.context;
this._defaultTexture = context.defaultTexture;
const loadedImages = this._loadedImages;
for (let i = 0; i < loadedImages.length; i++) {
const loadedImage = loadedImages[i];
createTexture4(this, loadedImage, context);
}
loadedImages.length = 0;
};
TextureManager.prototype.isDestroyed = function() {
return false;
};
TextureManager.prototype.destroy = function() {
const textures = this._textures;
for (const texture in textures) {
if (textures.hasOwnProperty(texture)) {
const instance = textures[texture];
if (instance !== this._defaultTexture) {
instance.destroy();
}
}
}
return destroyObject_default(this);
};
var TextureManager_default = TextureManager;
// packages/engine/Source/Scene/Model/CustomShader.js
function CustomShader(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.mode = options.mode ?? CustomShaderMode_default.MODIFY_MATERIAL;
this.lightingModel = options.lightingModel;
this.uniforms = options.uniforms ?? Frozen_default.EMPTY_OBJECT;
this.varyings = options.varyings ?? Frozen_default.EMPTY_OBJECT;
this.vertexShaderText = options.vertexShaderText;
this.fragmentShaderText = options.fragmentShaderText;
this.translucencyMode = options.translucencyMode ?? CustomShaderTranslucencyMode_default.INHERIT;
this._textureManager = new TextureManager_default();
this._defaultTexture = void 0;
this.uniformMap = buildUniformMap(this);
this.usedVariablesVertex = {
attributeSet: {},
featureIdSet: {},
metadataSet: {}
};
this.usedVariablesFragment = {
attributeSet: {},
featureIdSet: {},
metadataSet: {},
materialSet: {}
};
findUsedVariables(this);
validateBuiltinVariables(this);
}
function buildUniformMap(customShader) {
const uniforms = customShader.uniforms;
const uniformMap2 = {};
for (const uniformName in uniforms) {
if (uniforms.hasOwnProperty(uniformName)) {
const uniform = uniforms[uniformName];
const type = uniform.type;
if (type === UniformType_default.SAMPLER_CUBE) {
throw new DeveloperError_default(
"CustomShader does not support samplerCube uniforms"
);
}
if (type === UniformType_default.SAMPLER_2D) {
customShader._textureManager.loadTexture2D(uniformName, uniform.value);
uniformMap2[uniformName] = createUniformTexture2DFunction(
customShader,
uniformName
);
} else {
uniformMap2[uniformName] = createUniformFunction(
customShader,
uniformName
);
}
}
}
return uniformMap2;
}
function createUniformTexture2DFunction(customShader, uniformName) {
return function() {
return customShader._textureManager.getTexture(uniformName) ?? customShader._defaultTexture;
};
}
function createUniformFunction(customShader, uniformName) {
return function() {
return customShader.uniforms[uniformName].value;
};
}
function getVariables(shaderText, regex, outputSet) {
let match;
while ((match = regex.exec(shaderText)) !== null) {
const variableName = match[1];
outputSet[variableName] = true;
}
}
function findUsedVariables(customShader) {
const attributeRegex = /[vf]sInput\.attributes\.(\w+)/g;
const featureIdRegex = /[vf]sInput\.featureIds\.(\w+)/g;
const metadataRegex = /[vf]sInput\.metadata.(\w+)/g;
let attributeSet;
const vertexShaderText = customShader.vertexShaderText;
if (defined_default(vertexShaderText)) {
attributeSet = customShader.usedVariablesVertex.attributeSet;
getVariables(vertexShaderText, attributeRegex, attributeSet);
attributeSet = customShader.usedVariablesVertex.featureIdSet;
getVariables(vertexShaderText, featureIdRegex, attributeSet);
attributeSet = customShader.usedVariablesVertex.metadataSet;
getVariables(vertexShaderText, metadataRegex, attributeSet);
}
const fragmentShaderText = customShader.fragmentShaderText;
if (defined_default(fragmentShaderText)) {
attributeSet = customShader.usedVariablesFragment.attributeSet;
getVariables(fragmentShaderText, attributeRegex, attributeSet);
attributeSet = customShader.usedVariablesFragment.featureIdSet;
getVariables(fragmentShaderText, featureIdRegex, attributeSet);
attributeSet = customShader.usedVariablesFragment.metadataSet;
getVariables(fragmentShaderText, metadataRegex, attributeSet);
const materialRegex = /material\.(\w+)/g;
const materialSet = customShader.usedVariablesFragment.materialSet;
getVariables(fragmentShaderText, materialRegex, materialSet);
}
}
function expandCoordinateAbbreviations(variableName) {
const modelCoordinatesRegex = /^.*MC$/;
const worldCoordinatesRegex = /^.*WC$/;
const eyeCoordinatesRegex = /^.*EC$/;
if (modelCoordinatesRegex.test(variableName)) {
return `${variableName} (model coordinates)`;
}
if (worldCoordinatesRegex.test(variableName)) {
return `${variableName} (Cartesian world coordinates)`;
}
if (eyeCoordinatesRegex.test(variableName)) {
return `${variableName} (eye coordinates)`;
}
return variableName;
}
function validateVariableUsage(variableSet, incorrectVariable, correctVariable, vertexOrFragment) {
if (variableSet.hasOwnProperty(incorrectVariable)) {
const message = `${expandCoordinateAbbreviations(
incorrectVariable
)} is not available in the ${vertexOrFragment} shader. Did you mean ${expandCoordinateAbbreviations(
correctVariable
)} instead?`;
throw new DeveloperError_default(message);
}
}
function validateBuiltinVariables(customShader) {
const attributesVS = customShader.usedVariablesVertex.attributeSet;
validateVariableUsage(attributesVS, "position", "positionMC", "vertex");
validateVariableUsage(attributesVS, "normal", "normalMC", "vertex");
validateVariableUsage(attributesVS, "tangent", "tangentMC", "vertex");
validateVariableUsage(attributesVS, "bitangent", "bitangentMC", "vertex");
validateVariableUsage(attributesVS, "positionWC", "positionMC", "vertex");
validateVariableUsage(attributesVS, "positionEC", "positionMC", "vertex");
validateVariableUsage(attributesVS, "normalEC", "normalMC", "vertex");
validateVariableUsage(attributesVS, "tangentEC", "tangentMC", "vertex");
validateVariableUsage(attributesVS, "bitangentEC", "bitangentMC", "vertex");
const attributesFS = customShader.usedVariablesFragment.attributeSet;
validateVariableUsage(attributesFS, "position", "positionEC", "fragment");
validateVariableUsage(attributesFS, "normal", "normalEC", "fragment");
validateVariableUsage(attributesFS, "tangent", "tangentEC", "fragment");
validateVariableUsage(attributesFS, "bitangent", "bitangentEC", "fragment");
validateVariableUsage(attributesFS, "normalMC", "normalEC", "fragment");
validateVariableUsage(attributesFS, "tangentMC", "tangentEC", "fragment");
validateVariableUsage(attributesFS, "bitangentMC", "bitangentEC", "fragment");
}
CustomShader.prototype.setUniform = function(uniformName, value) {
Check_default.typeOf.string("uniformName", uniformName);
Check_default.defined("value", value);
if (!defined_default(this.uniforms[uniformName])) {
throw new DeveloperError_default(
`Uniform ${uniformName} must be declared in the CustomShader constructor.`
);
}
const uniform = this.uniforms[uniformName];
if (uniform.type === UniformType_default.SAMPLER_2D) {
this._textureManager.loadTexture2D(uniformName, value);
} else if (defined_default(value.clone)) {
uniform.value = value.clone(uniform.value);
} else {
uniform.value = value;
}
};
CustomShader.prototype.update = function(frameState) {
this._defaultTexture = frameState.context.defaultTexture;
this._textureManager.update(frameState);
};
CustomShader.prototype.isDestroyed = function() {
return false;
};
CustomShader.prototype.destroy = function() {
this._textureManager = this._textureManager && this._textureManager.destroy();
destroyObject_default(this);
};
var CustomShader_default = CustomShader;
// packages/engine/Source/Scene/VoxelContent.js
var import_InlineWorkers1148 = __toESM(require_InlineWorkers(), 1);
function VoxelContent(options) {
Check_default.typeOf.object("options", options);
if (!defined_default(options.loader)) {
if (!defined_default(options.metadata)) {
throw new DeveloperError_default("One of loader and metadata must be defined.");
}
if (!Array.isArray(options.metadata)) {
throw new DeveloperError_default("metadata must be an array of TypedArrays.");
}
}
const { loader, metadata } = options;
this._loader = loader;
this._metadata = metadata;
this._resourcesLoaded = false;
this._ready = false;
}
Object.defineProperties(VoxelContent.prototype, {
/**
* Returns true when the content is ready to render; otherwise false
*
* @memberof VoxelContent.prototype
*
* @type {boolean}
* @readonly
* @private
*/
ready: {
get: function() {
return this._ready;
}
},
/**
* The metadata for this voxel content.
* The metadata is an array of typed arrays, one for each field.
* The data for one field is a flattened 3D array ordered by X, then Y, then Z.
* @type {Int8Array[]|Uint8Array[]|Int16Array[]|Uint16Array[]|Int32Array[]|Uint32Array[]|Float32Array[]|Float64Array[]}
* @readonly
*/
metadata: {
get: function() {
return this._metadata;
}
}
});
VoxelContent.fromMetadataArray = function(metadata) {
Check_default.typeOf.object("metadata", metadata);
if (!Array.isArray(metadata)) {
throw new DeveloperError_default("metadata must be an array of TypedArrays.");
}
return new VoxelContent({ metadata });
};
VoxelContent.fromGltf = async function(resource) {
Check_default.typeOf.object("resource", resource);
const loader = new GltfLoader_default({
gltfResource: resource,
releaseGltfJson: false,
loadAttributesAsTypedArray: true
});
try {
await loader.load();
} catch (error) {
loader.destroy();
throw error;
}
return new VoxelContent({ loader });
};
VoxelContent.prototype.update = function(primitive, frameState) {
const loader = this._loader;
if (this._ready) {
return;
}
frameState.afterRender.push(() => true);
if (!defined_default(loader)) {
this._ready = true;
return;
}
if (this._resourcesLoaded) {
const { structuralMetadata, scene } = loader.components;
const { attributes } = scene.nodes[0].primitives[0];
this._metadata = processAttributes(
attributes,
structuralMetadata,
primitive
);
this._ready = true;
return;
}
this._resourcesLoaded = loader.process(frameState);
};
function processAttributes(attributes, structuralMetadata, primitive) {
const { className, names, types, componentTypes } = primitive.provider;
const propertyAttribute = structuralMetadata.propertyAttributes.find(
(p) => p.class.id === className
);
const { properties } = propertyAttribute;
const data = new Array(names.length);
for (let i = 0; i < attributes.length; i++) {
const name = properties[names[i]].attribute;
const attribute = attributes.find((a3) => a3.name === name);
if (!defined_default(attribute)) {
continue;
}
const componentDatatype = MetadataComponentType_default.toComponentDatatype(
componentTypes[i]
);
const componentCount = MetadataType_default.getComponentCount(types[i]);
const totalCount = attribute.count * componentCount;
data[i] = ComponentDatatype_default.createArrayBufferView(
componentDatatype,
attribute.typedArray.buffer,
attribute.typedArray.byteOffset + attribute.byteOffset,
totalCount
);
}
return data;
}
VoxelContent.prototype.isDestroyed = function() {
return false;
};
VoxelContent.prototype.destroy = function() {
this._loader = this._loader && this._loader.destroy();
return destroyObject_default(this);
};
var VoxelContent_default = VoxelContent;
// packages/engine/Source/Scene/VoxelShapeType.js
var import_InlineWorkers1152 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/VoxelBoxShape.js
var import_InlineWorkers1149 = __toESM(require_InlineWorkers(), 1);
function VoxelBoxShape() {
this.orientedBoundingBox = new OrientedBoundingBox_default();
this.boundingSphere = new BoundingSphere_default();
this.boundTransform = new Matrix4_default();
this.shapeTransform = new Matrix4_default();
this._minBounds = VoxelBoxShape.DefaultMinBounds.clone();
this._maxBounds = VoxelBoxShape.DefaultMaxBounds.clone();
this.shaderUniforms = {
renderMinBounds: new Cartesian3_default(),
renderMaxBounds: new Cartesian3_default(),
boxUvToShapeUvScale: new Cartesian3_default(),
boxUvToShapeUvTranslate: new Cartesian3_default()
};
this.shaderDefines = {
BOX_INTERSECTION_INDEX: void 0,
BOX_HAS_SHAPE_BOUNDS: void 0
};
this.shaderMaximumIntersectionsLength = 0;
}
var scratchCenter11 = new Cartesian3_default();
var scratchScale6 = new Cartesian3_default();
var scratchRotation4 = new Matrix3_default();
var scratchClipMinBounds = new Cartesian3_default();
var scratchClipMaxBounds = new Cartesian3_default();
var scratchRenderMinBounds = new Cartesian3_default();
var scratchRenderMaxBounds = new Cartesian3_default();
var transformLocalToUv = Matrix4_default.fromRotationTranslation(
Matrix3_default.fromUniformScale(0.5, new Matrix3_default()),
new Cartesian3_default(0.5, 0.5, 0.5),
new Matrix4_default()
);
VoxelBoxShape.prototype.update = function(modelMatrix, minBounds, maxBounds, clipMinBounds, clipMaxBounds) {
Check_default.typeOf.object("modelMatrix", modelMatrix);
Check_default.typeOf.object("minBounds", minBounds);
Check_default.typeOf.object("maxBounds", maxBounds);
clipMinBounds = clipMinBounds ?? minBounds.clone(scratchClipMinBounds);
clipMaxBounds = clipMaxBounds ?? maxBounds.clone(scratchClipMaxBounds);
minBounds = Cartesian3_default.clone(minBounds, this._minBounds);
maxBounds = Cartesian3_default.clone(maxBounds, this._maxBounds);
const renderMinBounds = Cartesian3_default.clamp(
minBounds,
clipMinBounds,
clipMaxBounds,
scratchRenderMinBounds
);
const renderMaxBounds = Cartesian3_default.clamp(
maxBounds,
clipMinBounds,
clipMaxBounds,
scratchRenderMaxBounds
);
const scale = Matrix4_default.getScale(modelMatrix, scratchScale6);
if (renderMinBounds.x > renderMaxBounds.x || renderMinBounds.y > renderMaxBounds.y || renderMinBounds.z > renderMaxBounds.z || (renderMinBounds.x === renderMaxBounds.x) + (renderMinBounds.y === renderMaxBounds.y) + (renderMinBounds.z === renderMaxBounds.z) >= 2 || scale.x === 0 || scale.y === 0 || scale.z === 0) {
return false;
}
this.shapeTransform = Matrix4_default.clone(modelMatrix, this.shapeTransform);
this.orientedBoundingBox = getBoxChunkObb(
renderMinBounds,
renderMaxBounds,
this.shapeTransform,
this.orientedBoundingBox
);
this.boundTransform = Matrix4_default.fromRotationTranslation(
this.orientedBoundingBox.halfAxes,
this.orientedBoundingBox.center,
this.boundTransform
);
this.boundingSphere = BoundingSphere_default.fromOrientedBoundingBox(
this.orientedBoundingBox,
this.boundingSphere
);
const { shaderUniforms, shaderDefines } = this;
for (const key in shaderDefines) {
if (shaderDefines.hasOwnProperty(key)) {
shaderDefines[key] = void 0;
}
}
let intersectionCount = 0;
shaderDefines["BOX_INTERSECTION_INDEX"] = intersectionCount;
intersectionCount += 1;
shaderUniforms.renderMinBounds = Matrix4_default.multiplyByPoint(
transformLocalToUv,
renderMinBounds,
shaderUniforms.renderMinBounds
);
shaderUniforms.renderMaxBounds = Matrix4_default.multiplyByPoint(
transformLocalToUv,
renderMaxBounds,
shaderUniforms.renderMaxBounds
);
shaderDefines["BOX_HAS_SHAPE_BOUNDS"] = true;
const min3 = minBounds;
const max3 = maxBounds;
shaderUniforms.boxUvToShapeUvScale = Cartesian3_default.fromElements(
2 / (min3.x === max3.x ? 1 : max3.x - min3.x),
2 / (min3.y === max3.y ? 1 : max3.y - min3.y),
2 / (min3.z === max3.z ? 1 : max3.z - min3.z),
shaderUniforms.boxUvToShapeUvScale
);
shaderUniforms.boxUvToShapeUvTranslate = Cartesian3_default.fromElements(
-shaderUniforms.boxUvToShapeUvScale.x * (min3.x * 0.5 + 0.5),
-shaderUniforms.boxUvToShapeUvScale.y * (min3.y * 0.5 + 0.5),
-shaderUniforms.boxUvToShapeUvScale.z * (min3.z * 0.5 + 0.5),
shaderUniforms.boxUvToShapeUvTranslate
);
this.shaderMaximumIntersectionsLength = intersectionCount;
return true;
};
var scratchTileMinBounds = new Cartesian3_default();
var scratchTileMaxBounds = new Cartesian3_default();
VoxelBoxShape.prototype.computeOrientedBoundingBoxForTile = function(tileLevel, tileX, tileY, tileZ, result) {
Check_default.typeOf.number("tileLevel", tileLevel);
Check_default.typeOf.number("tileX", tileX);
Check_default.typeOf.number("tileY", tileY);
Check_default.typeOf.number("tileZ", tileZ);
Check_default.typeOf.object("result", result);
const minBounds = this._minBounds;
const maxBounds = this._maxBounds;
const sizeAtLevel = 1 / Math.pow(2, tileLevel);
const tileMinBounds = Cartesian3_default.fromElements(
Math_default.lerp(minBounds.x, maxBounds.x, sizeAtLevel * tileX),
Math_default.lerp(minBounds.y, maxBounds.y, sizeAtLevel * tileY),
Math_default.lerp(minBounds.z, maxBounds.z, sizeAtLevel * tileZ),
scratchTileMinBounds
);
const tileMaxBounds = Cartesian3_default.fromElements(
Math_default.lerp(minBounds.x, maxBounds.x, sizeAtLevel * (tileX + 1)),
Math_default.lerp(minBounds.y, maxBounds.y, sizeAtLevel * (tileY + 1)),
Math_default.lerp(minBounds.z, maxBounds.z, sizeAtLevel * (tileZ + 1)),
scratchTileMaxBounds
);
return getBoxChunkObb(
tileMinBounds,
tileMaxBounds,
this.shapeTransform,
result
);
};
var sampleSizeScratch = new Cartesian3_default();
VoxelBoxShape.prototype.computeOrientedBoundingBoxForSample = function(spatialNode, tileDimensions, tileUv, result) {
Check_default.typeOf.object("spatialNode", spatialNode);
Check_default.typeOf.object("tileDimensions", tileDimensions);
Check_default.typeOf.object("tileUv", tileUv);
Check_default.typeOf.object("result", result);
const tileSizeAtLevel = 1 / Math.pow(2, spatialNode.level);
const sampleSize = Cartesian3_default.divideComponents(
Cartesian3_default.ONE,
tileDimensions,
sampleSizeScratch
);
const sampleSizeAtLevel = Cartesian3_default.multiplyByScalar(
sampleSize,
tileSizeAtLevel,
sampleSizeScratch
);
const minLerp = Cartesian3_default.multiplyByScalar(
Cartesian3_default.fromElements(
spatialNode.x + tileUv.x,
spatialNode.y + tileUv.y,
spatialNode.z + tileUv.z,
scratchTileMinBounds
),
tileSizeAtLevel,
scratchTileMinBounds
);
const maxLerp = Cartesian3_default.add(
minLerp,
sampleSizeAtLevel,
scratchTileMaxBounds
);
const minBounds = this._minBounds;
const maxBounds = this._maxBounds;
const sampleMinBounds = Cartesian3_default.fromElements(
Math_default.lerp(minBounds.x, maxBounds.x, minLerp.x),
Math_default.lerp(minBounds.y, maxBounds.y, minLerp.y),
Math_default.lerp(minBounds.z, maxBounds.z, minLerp.z),
scratchTileMinBounds
);
const sampleMaxBounds = Cartesian3_default.fromElements(
Math_default.lerp(minBounds.x, maxBounds.x, maxLerp.x),
Math_default.lerp(minBounds.y, maxBounds.y, maxLerp.y),
Math_default.lerp(minBounds.z, maxBounds.z, maxLerp.z),
scratchTileMaxBounds
);
return getBoxChunkObb(
sampleMinBounds,
sampleMaxBounds,
this.shapeTransform,
result
);
};
VoxelBoxShape.DefaultMinBounds = Object.freeze(
new Cartesian3_default(-1, -1, -1)
);
VoxelBoxShape.DefaultMaxBounds = Object.freeze(
new Cartesian3_default(1, 1, 1)
);
function getBoxChunkObb(minimumBounds, maximumBounds, matrix, result) {
const defaultMinBounds = VoxelBoxShape.DefaultMinBounds;
const defaultMaxBounds = VoxelBoxShape.DefaultMaxBounds;
const isDefaultBounds = Cartesian3_default.equals(minimumBounds, defaultMinBounds) && Cartesian3_default.equals(maximumBounds, defaultMaxBounds);
if (isDefaultBounds) {
result.center = Matrix4_default.getTranslation(matrix, result.center);
result.halfAxes = Matrix4_default.getMatrix3(matrix, result.halfAxes);
} else {
let scale = Matrix4_default.getScale(matrix, scratchScale6);
const localCenter = Cartesian3_default.midpoint(
minimumBounds,
maximumBounds,
scratchCenter11
);
result.center = Matrix4_default.multiplyByPoint(matrix, localCenter, result.center);
scale = Cartesian3_default.fromElements(
scale.x * 0.5 * (maximumBounds.x - minimumBounds.x),
scale.y * 0.5 * (maximumBounds.y - minimumBounds.y),
scale.z * 0.5 * (maximumBounds.z - minimumBounds.z),
scratchScale6
);
const rotation = Matrix4_default.getRotation(matrix, scratchRotation4);
result.halfAxes = Matrix3_default.setScale(rotation, scale, result.halfAxes);
}
return result;
}
var VoxelBoxShape_default = VoxelBoxShape;
// packages/engine/Source/Scene/VoxelCylinderShape.js
var import_InlineWorkers1150 = __toESM(require_InlineWorkers(), 1);
function VoxelCylinderShape() {
this.orientedBoundingBox = new OrientedBoundingBox_default();
this.boundingSphere = new BoundingSphere_default();
this.boundTransform = new Matrix4_default();
this.shapeTransform = new Matrix4_default();
this._minBounds = VoxelCylinderShape.DefaultMinBounds.clone();
this._maxBounds = VoxelCylinderShape.DefaultMaxBounds.clone();
this.shaderUniforms = {
cylinderRenderRadiusMinMax: new Cartesian2_default(),
cylinderRenderAngleMinMax: new Cartesian2_default(),
cylinderRenderHeightMinMax: new Cartesian2_default(),
cylinderUvToShapeUvRadius: new Cartesian2_default(),
cylinderUvToShapeUvAngle: new Cartesian2_default(),
cylinderUvToShapeUvHeight: new Cartesian2_default(),
cylinderShapeUvAngleMinMax: new Cartesian2_default(),
cylinderShapeUvAngleRangeZeroMid: 0
};
this.shaderDefines = {
CYLINDER_HAS_RENDER_BOUNDS_RADIUS_MIN: void 0,
CYLINDER_HAS_RENDER_BOUNDS_RADIUS_FLAT: void 0,
CYLINDER_HAS_RENDER_BOUNDS_ANGLE: void 0,
CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_EQUAL_ZERO: void 0,
CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_UNDER_HALF: void 0,
CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_OVER_HALF: void 0,
CYLINDER_HAS_SHAPE_BOUNDS_RADIUS: void 0,
CYLINDER_HAS_SHAPE_BOUNDS_HEIGHT: void 0,
CYLINDER_HAS_SHAPE_BOUNDS_ANGLE: void 0,
CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MIN_DISCONTINUITY: void 0,
CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MAX_DISCONTINUITY: void 0,
CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MIN_MAX_REVERSED: void 0,
CYLINDER_INTERSECTION_INDEX_RADIUS_MAX: void 0,
CYLINDER_INTERSECTION_INDEX_RADIUS_MIN: void 0,
CYLINDER_INTERSECTION_INDEX_ANGLE: void 0
};
this.shaderMaximumIntersectionsLength = 0;
}
var scratchScale7 = new Cartesian3_default();
var scratchClipMinBounds2 = new Cartesian3_default();
var scratchClipMaxBounds2 = new Cartesian3_default();
var scratchRenderMinBounds2 = new Cartesian3_default();
var scratchRenderMaxBounds2 = new Cartesian3_default();
VoxelCylinderShape.prototype.update = function(modelMatrix, minBounds, maxBounds, clipMinBounds, clipMaxBounds) {
Check_default.typeOf.object("modelMatrix", modelMatrix);
Check_default.typeOf.object("minBounds", minBounds);
Check_default.typeOf.object("maxBounds", maxBounds);
clipMinBounds = clipMinBounds ?? minBounds.clone(scratchClipMinBounds2);
clipMaxBounds = clipMaxBounds ?? maxBounds.clone(scratchClipMaxBounds2);
minBounds = Cartesian3_default.clone(minBounds, this._minBounds);
maxBounds = Cartesian3_default.clone(maxBounds, this._maxBounds);
const { DefaultMinBounds, DefaultMaxBounds } = VoxelCylinderShape;
const defaultAngleRange = DefaultMaxBounds.y - DefaultMinBounds.y;
const defaultAngleRangeHalf = 0.5 * defaultAngleRange;
const epsilonZeroScale = Math_default.EPSILON10;
const epsilonAngleDiscontinuity = Math_default.EPSILON3;
const epsilonAngle = Math_default.EPSILON10;
minBounds.x = Math.max(0, minBounds.x);
maxBounds.x = Math.max(0, maxBounds.x);
minBounds.y = Math_default.negativePiToPi(minBounds.y);
maxBounds.y = Math_default.negativePiToPi(maxBounds.y);
clipMinBounds.y = Math_default.negativePiToPi(clipMinBounds.y);
clipMaxBounds.y = Math_default.negativePiToPi(clipMaxBounds.y);
const renderMinBounds = Cartesian3_default.maximumByComponent(
minBounds,
clipMinBounds,
scratchRenderMinBounds2
);
const renderMaxBounds = Cartesian3_default.minimumByComponent(
maxBounds,
clipMaxBounds,
scratchRenderMaxBounds2
);
const scale = Matrix4_default.getScale(modelMatrix, scratchScale7);
if (renderMaxBounds.x === 0 || renderMinBounds.x > renderMaxBounds.x || renderMinBounds.z > renderMaxBounds.z || Math_default.equalsEpsilon(scale.x, 0, void 0, epsilonZeroScale) || Math_default.equalsEpsilon(scale.y, 0, void 0, epsilonZeroScale) || Math_default.equalsEpsilon(scale.z, 0, void 0, epsilonZeroScale)) {
return false;
}
this.shapeTransform = Matrix4_default.clone(modelMatrix, this.shapeTransform);
this.orientedBoundingBox = getCylinderChunkObb(
renderMinBounds,
renderMaxBounds,
this.shapeTransform,
this.orientedBoundingBox
);
this.boundTransform = Matrix4_default.fromRotationTranslation(
this.orientedBoundingBox.halfAxes,
this.orientedBoundingBox.center,
this.boundTransform
);
this.boundingSphere = BoundingSphere_default.fromOrientedBoundingBox(
this.orientedBoundingBox,
this.boundingSphere
);
const shapeIsDefaultRadius = minBounds.x === DefaultMinBounds.x && maxBounds.x === DefaultMaxBounds.x;
const shapeIsAngleReversed = maxBounds.y < minBounds.y;
const shapeAngleRange = maxBounds.y - minBounds.y + shapeIsAngleReversed * defaultAngleRange;
const shapeIsAngleRegular = shapeAngleRange > defaultAngleRangeHalf + epsilonAngle && shapeAngleRange < defaultAngleRange - epsilonAngle;
const shapeIsAngleFlipped = shapeAngleRange < defaultAngleRangeHalf - epsilonAngle;
const shapeIsAngleRangeHalf = shapeAngleRange >= defaultAngleRangeHalf - epsilonAngle && shapeAngleRange <= defaultAngleRangeHalf + epsilonAngle;
const shapeHasAngle = shapeIsAngleRegular || shapeIsAngleFlipped || shapeIsAngleRangeHalf;
const shapeIsMinAngleDiscontinuity = Math_default.equalsEpsilon(
minBounds.y,
DefaultMinBounds.y,
void 0,
epsilonAngleDiscontinuity
);
const shapeIsMaxAngleDiscontinuity = Math_default.equalsEpsilon(
maxBounds.y,
DefaultMaxBounds.y,
void 0,
epsilonAngleDiscontinuity
);
const shapeIsDefaultHeight = minBounds.z === DefaultMinBounds.z && maxBounds.z === DefaultMaxBounds.z;
const renderIsDefaultMinRadius = renderMinBounds.x === DefaultMinBounds.x;
const renderIsAngleReversed = renderMaxBounds.y < renderMinBounds.y;
const renderAngleRange = renderMaxBounds.y - renderMinBounds.y + renderIsAngleReversed * defaultAngleRange;
const renderIsAngleRegular = renderAngleRange >= defaultAngleRangeHalf - epsilonAngle && renderAngleRange < defaultAngleRange - epsilonAngle;
const renderIsAngleFlipped = renderAngleRange > epsilonAngle && renderAngleRange < defaultAngleRangeHalf - epsilonAngle;
const renderIsAngleRangeZero = renderAngleRange <= epsilonAngle;
const renderHasAngle = renderIsAngleRegular || renderIsAngleFlipped || renderIsAngleRangeZero;
const { shaderUniforms, shaderDefines } = this;
for (const key in shaderDefines) {
if (shaderDefines.hasOwnProperty(key)) {
shaderDefines[key] = void 0;
}
}
let intersectionCount = 0;
shaderDefines["CYLINDER_INTERSECTION_INDEX_RADIUS_MAX"] = intersectionCount;
intersectionCount += 1;
if (!renderIsDefaultMinRadius) {
shaderDefines["CYLINDER_HAS_RENDER_BOUNDS_RADIUS_MIN"] = true;
shaderDefines["CYLINDER_INTERSECTION_INDEX_RADIUS_MIN"] = intersectionCount;
intersectionCount += 1;
}
shaderUniforms.cylinderRenderRadiusMinMax = Cartesian2_default.fromElements(
renderMinBounds.x,
renderMaxBounds.x,
shaderUniforms.cylinderRenderRadiusMinMax
);
if (renderMinBounds.x === renderMaxBounds.x) {
shaderDefines["CYLINDER_HAS_RENDER_BOUNDS_RADIUS_FLAT"] = true;
}
if (!shapeIsDefaultRadius) {
shaderDefines["CYLINDER_HAS_SHAPE_BOUNDS_RADIUS"] = true;
const radiusRange = maxBounds.x - minBounds.x;
let scale2 = 0;
let offset = 1;
if (radiusRange !== 0) {
scale2 = 1 / radiusRange;
offset = -minBounds.x / radiusRange;
}
shaderUniforms.cylinderUvToShapeUvRadius = Cartesian2_default.fromElements(
scale2,
offset,
shaderUniforms.cylinderUvToShapeUvRadius
);
}
if (!shapeIsDefaultHeight) {
shaderDefines["CYLINDER_HAS_SHAPE_BOUNDS_HEIGHT"] = true;
const heightRange = maxBounds.z - minBounds.z;
let scale2 = 0;
let offset = 1;
if (heightRange !== 0) {
scale2 = 2 / heightRange;
offset = -(minBounds.z + 1) / heightRange;
}
shaderUniforms.cylinderUvToShapeUvHeight = Cartesian2_default.fromElements(
scale2,
offset,
shaderUniforms.cylinderUvToShapeUvHeight
);
}
shaderUniforms.cylinderRenderHeightMinMax = Cartesian2_default.fromElements(
renderMinBounds.z,
renderMaxBounds.z,
shaderUniforms.cylinderRenderHeightMinMax
);
if (shapeIsAngleReversed) {
shaderDefines["CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MIN_MAX_REVERSED"] = true;
}
if (renderHasAngle) {
shaderDefines["CYLINDER_HAS_RENDER_BOUNDS_ANGLE"] = true;
shaderDefines["CYLINDER_INTERSECTION_INDEX_ANGLE"] = intersectionCount;
if (renderIsAngleRegular) {
shaderDefines["CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_UNDER_HALF"] = true;
intersectionCount += 1;
} else if (renderIsAngleFlipped) {
shaderDefines["CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_OVER_HALF"] = true;
intersectionCount += 2;
} else if (renderIsAngleRangeZero) {
shaderDefines["CYLINDER_HAS_RENDER_BOUNDS_ANGLE_RANGE_EQUAL_ZERO"] = true;
intersectionCount += 2;
}
shaderUniforms.cylinderRenderAngleMinMax = Cartesian2_default.fromElements(
renderMinBounds.y,
renderMaxBounds.y,
shaderUniforms.cylinderRenderAngleMinMax
);
}
if (shapeHasAngle) {
shaderDefines["CYLINDER_HAS_SHAPE_BOUNDS_ANGLE"] = true;
if (shapeIsMinAngleDiscontinuity) {
shaderDefines["CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MIN_DISCONTINUITY"] = true;
}
if (shapeIsMaxAngleDiscontinuity) {
shaderDefines["CYLINDER_HAS_SHAPE_BOUNDS_ANGLE_MAX_DISCONTINUITY"] = true;
}
const uvMinAngle = (minBounds.y - DefaultMinBounds.y) / defaultAngleRange;
const uvMaxAngle = (maxBounds.y - DefaultMinBounds.y) / defaultAngleRange;
const uvAngleRangeZero = 1 - shapeAngleRange / defaultAngleRange;
shaderUniforms.cylinderShapeUvAngleMinMax = Cartesian2_default.fromElements(
uvMinAngle,
uvMaxAngle,
shaderUniforms.cylinderShapeUvAngleMinMax
);
shaderUniforms.cylinderShapeUvAngleRangeZeroMid = (uvMaxAngle + 0.5 * uvAngleRangeZero) % 1;
if (shapeAngleRange <= epsilonAngle) {
shaderUniforms.cylinderUvToShapeUvAngle = Cartesian2_default.fromElements(
0,
1,
shaderUniforms.cylinderUvToShapeUvAngle
);
} else {
const scale2 = defaultAngleRange / shapeAngleRange;
const offset = -(minBounds.y - DefaultMinBounds.y) / shapeAngleRange;
shaderUniforms.cylinderUvToShapeUvAngle = Cartesian2_default.fromElements(
scale2,
offset,
shaderUniforms.cylinderUvToShapeUvAngle
);
}
}
this.shaderMaximumIntersectionsLength = intersectionCount;
return true;
};
var scratchMinBounds = new Cartesian3_default();
var scratchMaxBounds = new Cartesian3_default();
VoxelCylinderShape.prototype.computeOrientedBoundingBoxForTile = function(tileLevel, tileX, tileY, tileZ, result) {
Check_default.typeOf.number("tileLevel", tileLevel);
Check_default.typeOf.number("tileX", tileX);
Check_default.typeOf.number("tileY", tileY);
Check_default.typeOf.number("tileZ", tileZ);
Check_default.typeOf.object("result", result);
const minBounds = this._minBounds;
const maxBounds = this._maxBounds;
const sizeAtLevel = 1 / Math.pow(2, tileLevel);
const tileMinBounds = Cartesian3_default.fromElements(
Math_default.lerp(minBounds.x, maxBounds.x, tileX * sizeAtLevel),
Math_default.lerp(minBounds.y, maxBounds.y, tileY * sizeAtLevel),
Math_default.lerp(minBounds.z, maxBounds.z, tileZ * sizeAtLevel),
scratchMinBounds
);
const tileMaxBounds = Cartesian3_default.fromElements(
Math_default.lerp(minBounds.x, maxBounds.x, (tileX + 1) * sizeAtLevel),
Math_default.lerp(minBounds.y, maxBounds.y, (tileY + 1) * sizeAtLevel),
Math_default.lerp(minBounds.z, maxBounds.z, (tileZ + 1) * sizeAtLevel),
scratchMaxBounds
);
return getCylinderChunkObb(
tileMinBounds,
tileMaxBounds,
this.shapeTransform,
result
);
};
var sampleSizeScratch2 = new Cartesian3_default();
VoxelCylinderShape.prototype.computeOrientedBoundingBoxForSample = function(spatialNode, tileDimensions, tileUv, result) {
Check_default.typeOf.object("spatialNode", spatialNode);
Check_default.typeOf.object("tileDimensions", tileDimensions);
Check_default.typeOf.object("tileUv", tileUv);
Check_default.typeOf.object("result", result);
const tileSizeAtLevel = 1 / Math.pow(2, spatialNode.level);
const sampleSize = Cartesian3_default.divideComponents(
Cartesian3_default.ONE,
tileDimensions,
sampleSizeScratch2
);
const sampleSizeAtLevel = Cartesian3_default.multiplyByScalar(
sampleSize,
tileSizeAtLevel,
sampleSizeScratch2
);
const minLerp = Cartesian3_default.multiplyByScalar(
Cartesian3_default.fromElements(
spatialNode.x + tileUv.x,
spatialNode.y + tileUv.y,
spatialNode.z + tileUv.z,
scratchMinBounds
),
tileSizeAtLevel,
scratchMinBounds
);
const maxLerp = Cartesian3_default.add(minLerp, sampleSizeAtLevel, scratchMaxBounds);
const minBounds = this._minBounds;
const maxBounds = this._maxBounds;
const sampleMinBounds = Cartesian3_default.fromElements(
Math_default.lerp(minBounds.x, maxBounds.x, minLerp.x),
Math_default.lerp(minBounds.y, maxBounds.y, minLerp.y),
Math_default.lerp(minBounds.z, maxBounds.z, minLerp.z),
scratchMinBounds
);
const sampleMaxBounds = Cartesian3_default.fromElements(
Math_default.lerp(minBounds.x, maxBounds.x, maxLerp.x),
Math_default.lerp(minBounds.y, maxBounds.y, maxLerp.y),
Math_default.lerp(minBounds.z, maxBounds.z, maxLerp.z),
scratchMaxBounds
);
return getCylinderChunkObb(
sampleMinBounds,
sampleMaxBounds,
this.shapeTransform,
result
);
};
VoxelCylinderShape.DefaultMinBounds = Object.freeze(
new Cartesian3_default(0, -Math_default.PI, -1)
);
VoxelCylinderShape.DefaultMaxBounds = Object.freeze(
new Cartesian3_default(1, +Math_default.PI, 1)
);
var maxTestAngles = 5;
var scratchTestAngles = new Array(maxTestAngles);
var scratchTranslation3 = new Cartesian3_default();
var scratchRotation5 = new Matrix3_default();
var scratchTranslationMatrix = new Matrix4_default();
var scratchRotationMatrix3 = new Matrix4_default();
var scratchScaleMatrix = new Matrix4_default();
var scratchMatrix7 = new Matrix4_default();
var scratchColumn0 = new Cartesian3_default();
var scratchColumn1 = new Cartesian3_default();
var scratchColumn22 = new Cartesian3_default();
var scratchCorners2 = new Array(8);
for (let i = 0; i < 8; i++) {
scratchCorners2[i] = new Cartesian3_default();
}
function orthogonal(a3, b, epsilon) {
return Math.abs(Cartesian4_default.dot(a3, b)) < epsilon;
}
function isValidOrientedBoundingBoxTransformation(matrix) {
const column0 = Matrix4_default.getColumn(matrix, 0, scratchColumn0);
const column1 = Matrix4_default.getColumn(matrix, 1, scratchColumn1);
const column2 = Matrix4_default.getColumn(matrix, 2, scratchColumn22);
const epsilon = Math_default.EPSILON4;
return orthogonal(column0, column1, epsilon) && orthogonal(column1, column2, epsilon);
}
function computeLooseOrientedBoundingBox(matrix, result) {
const corners2 = scratchCorners2;
Cartesian3_default.fromElements(-0.5, -0.5, -0.5, corners2[0]);
Cartesian3_default.fromElements(-0.5, -0.5, 0.5, corners2[1]);
Cartesian3_default.fromElements(-0.5, 0.5, -0.5, corners2[2]);
Cartesian3_default.fromElements(-0.5, 0.5, 0.5, corners2[3]);
Cartesian3_default.fromElements(0.5, -0.5, -0.5, corners2[4]);
Cartesian3_default.fromElements(0.5, -0.5, 0.5, corners2[5]);
Cartesian3_default.fromElements(0.5, 0.5, -0.5, corners2[6]);
Cartesian3_default.fromElements(0.5, 0.5, 0.5, corners2[7]);
for (let i = 0; i < 8; ++i) {
Matrix4_default.multiplyByPoint(matrix, corners2[i], corners2[i]);
}
return OrientedBoundingBox_default.fromPoints(corners2, result);
}
function getCylinderChunkObb(chunkMinBounds, chunkMaxBounds, matrix, result) {
const radiusStart = chunkMinBounds.x;
const radiusEnd = chunkMaxBounds.x;
const angleStart = chunkMinBounds.y;
const angleEnd = chunkMaxBounds.y < angleStart ? chunkMaxBounds.y + Math_default.TWO_PI : chunkMaxBounds.y;
const heightStart = chunkMinBounds.z;
const heightEnd = chunkMaxBounds.z;
const angleRange = angleEnd - angleStart;
const angleMid = angleStart + angleRange * 0.5;
const testAngles = scratchTestAngles;
let testAngleCount = 0;
testAngles[testAngleCount++] = angleStart;
testAngles[testAngleCount++] = angleEnd;
testAngles[testAngleCount++] = angleMid;
if (angleRange > Math_default.PI) {
testAngles[testAngleCount++] = angleMid - Math_default.PI_OVER_TWO;
testAngles[testAngleCount++] = angleMid + Math_default.PI_OVER_TWO;
}
let minX = Number.POSITIVE_INFINITY;
let minY = Number.POSITIVE_INFINITY;
let maxX = Number.NEGATIVE_INFINITY;
let maxY = Number.NEGATIVE_INFINITY;
for (let i = 0; i < testAngleCount; ++i) {
const angle = testAngles[i] - angleMid;
const cosAngle = Math.cos(angle);
const sinAngle = Math.sin(angle);
const x1 = cosAngle * radiusStart;
const y1 = sinAngle * radiusStart;
const x2 = cosAngle * radiusEnd;
const y2 = sinAngle * radiusEnd;
minX = Math.min(minX, x1, x2);
minY = Math.min(minY, y1, y2);
maxX = Math.max(maxX, x1, x2);
maxY = Math.max(maxY, y1, y2);
}
const extentX = maxX - minX;
const extentY = maxY - minY;
const extentZ = heightEnd - heightStart;
const centerX = (minX + maxX) * 0.5;
const centerY = (minY + maxY) * 0.5;
const centerZ = (heightStart + heightEnd) * 0.5;
const translation3 = Cartesian3_default.fromElements(
centerX,
centerY,
centerZ,
scratchTranslation3
);
const rotation = Matrix3_default.fromRotationZ(angleMid, scratchRotation5);
const scale = Cartesian3_default.fromElements(
extentX,
extentY,
extentZ,
scratchScale7
);
const scaleMatrix2 = Matrix4_default.fromScale(scale, scratchScaleMatrix);
const rotationMatrix = Matrix4_default.fromRotation(rotation, scratchRotationMatrix3);
const translationMatrix = Matrix4_default.fromTranslation(
translation3,
scratchTranslationMatrix
);
const localMatrix = Matrix4_default.multiplyTransformation(
rotationMatrix,
Matrix4_default.multiplyTransformation(
translationMatrix,
scaleMatrix2,
scratchMatrix7
),
scratchMatrix7
);
const globalMatrix = Matrix4_default.multiplyTransformation(
matrix,
localMatrix,
scratchMatrix7
);
if (!isValidOrientedBoundingBoxTransformation(globalMatrix)) {
return computeLooseOrientedBoundingBox(globalMatrix, result);
}
return OrientedBoundingBox_default.fromTransformation(globalMatrix, result);
}
var VoxelCylinderShape_default = VoxelCylinderShape;
// packages/engine/Source/Scene/VoxelEllipsoidShape.js
var import_InlineWorkers1151 = __toESM(require_InlineWorkers(), 1);
function VoxelEllipsoidShape() {
this.orientedBoundingBox = new OrientedBoundingBox_default();
this.boundingSphere = new BoundingSphere_default();
this.boundTransform = new Matrix4_default();
this.shapeTransform = new Matrix4_default();
this._rectangle = new Rectangle_default();
this._minimumHeight = VoxelEllipsoidShape.DefaultMinBounds.z;
this._maximumHeight = VoxelEllipsoidShape.DefaultMaxBounds.z;
this._ellipsoid = new Ellipsoid_default();
this._translation = new Cartesian3_default();
this._rotation = new Matrix3_default();
this.shaderUniforms = {
ellipsoidRadiiUv: new Cartesian3_default(),
eccentricitySquared: 0,
evoluteScale: new Cartesian2_default(),
ellipsoidInverseRadiiSquaredUv: new Cartesian3_default(),
ellipsoidRenderLongitudeMinMax: new Cartesian2_default(),
ellipsoidShapeUvLongitudeMinMaxMid: new Cartesian3_default(),
ellipsoidUvToShapeUvLongitude: new Cartesian2_default(),
ellipsoidUvToShapeUvLatitude: new Cartesian2_default(),
ellipsoidRenderLatitudeSinMinMax: new Cartesian2_default(),
ellipsoidInverseHeightDifferenceUv: 0,
clipMinMaxHeight: new Cartesian2_default()
};
this.shaderDefines = {
ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE: void 0,
ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO: void 0,
ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_UNDER_HALF: void 0,
ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_OVER_HALF: void 0,
ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MIN_DISCONTINUITY: void 0,
ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MAX_DISCONTINUITY: void 0,
ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE: void 0,
ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_MIN_MAX_REVERSED: void 0,
ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF: void 0,
ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_EQUAL_HALF: void 0,
ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF: void 0,
ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF: void 0,
ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF: void 0,
ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF: void 0,
ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE: void 0,
ELLIPSOID_INTERSECTION_INDEX_LONGITUDE: void 0,
ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX: void 0,
ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN: void 0,
ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX: void 0,
ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN: void 0
};
this.shaderMaximumIntersectionsLength = 0;
}
var scratchActualMinBounds = new Cartesian3_default();
var scratchShapeMinBounds = new Cartesian3_default();
var scratchShapeMaxBounds = new Cartesian3_default();
var scratchClipMinBounds3 = new Cartesian3_default();
var scratchClipMaxBounds3 = new Cartesian3_default();
var scratchRenderMinBounds3 = new Cartesian3_default();
var scratchRenderMaxBounds3 = new Cartesian3_default();
var scratchScale8 = new Cartesian3_default();
var scratchRotationScale3 = new Matrix3_default();
var scratchShapeOuterExtent = new Cartesian3_default();
var scratchRenderOuterExtent = new Cartesian3_default();
var scratchRenderRectangle = new Rectangle_default();
VoxelEllipsoidShape.prototype.update = function(modelMatrix, minBounds, maxBounds, clipMinBounds, clipMaxBounds) {
const { DefaultMinBounds, DefaultMaxBounds } = VoxelEllipsoidShape;
clipMinBounds = clipMinBounds ?? DefaultMinBounds;
clipMaxBounds = clipMaxBounds ?? DefaultMaxBounds;
Check_default.typeOf.object("modelMatrix", modelMatrix);
Check_default.typeOf.object("minBounds", minBounds);
Check_default.typeOf.object("maxBounds", maxBounds);
const epsilonZeroScale = Math_default.EPSILON10;
const epsilonLongitudeDiscontinuity = Math_default.EPSILON3;
const epsilonLongitude = Math_default.EPSILON10;
const epsilonLatitude = Math_default.EPSILON10;
const epsilonLatitudeFlat = Math_default.EPSILON3;
const radii = Matrix4_default.getScale(modelMatrix, scratchScale8);
const actualMinBounds = Cartesian3_default.clone(
DefaultMinBounds,
scratchActualMinBounds
);
actualMinBounds.z = -Cartesian3_default.minimumComponent(radii);
const shapeMinBounds = Cartesian3_default.clamp(
minBounds,
actualMinBounds,
DefaultMaxBounds,
scratchShapeMinBounds
);
const shapeMaxBounds = Cartesian3_default.clamp(
maxBounds,
actualMinBounds,
DefaultMaxBounds,
scratchShapeMaxBounds
);
const clampedClipMinBounds = Cartesian3_default.clamp(
clipMinBounds,
actualMinBounds,
DefaultMaxBounds,
scratchClipMinBounds3
);
const clampedClipMaxBounds = Cartesian3_default.clamp(
clipMaxBounds,
actualMinBounds,
DefaultMaxBounds,
scratchClipMaxBounds3
);
const renderMinBounds = Cartesian3_default.maximumByComponent(
shapeMinBounds,
clampedClipMinBounds,
scratchRenderMinBounds3
);
const renderMaxBounds = Cartesian3_default.minimumByComponent(
shapeMaxBounds,
clampedClipMaxBounds,
scratchRenderMaxBounds3
);
const shapeOuterExtent = Cartesian3_default.add(
radii,
Cartesian3_default.fromElements(
shapeMaxBounds.z,
shapeMaxBounds.z,
shapeMaxBounds.z,
scratchShapeOuterExtent
),
scratchShapeOuterExtent
);
const shapeMaxExtent = Cartesian3_default.maximumComponent(shapeOuterExtent);
const renderOuterExtent = Cartesian3_default.add(
radii,
Cartesian3_default.fromElements(
renderMaxBounds.z,
renderMaxBounds.z,
renderMaxBounds.z,
scratchRenderOuterExtent
),
scratchRenderOuterExtent
);
if (renderMinBounds.y > renderMaxBounds.y || renderMinBounds.y === DefaultMaxBounds.y || renderMaxBounds.y === DefaultMinBounds.y || renderMinBounds.z > renderMaxBounds.z || Math_default.equalsEpsilon(
renderOuterExtent,
Cartesian3_default.ZERO,
void 0,
epsilonZeroScale
)) {
return false;
}
this._rectangle = Rectangle_default.fromRadians(
shapeMinBounds.x,
shapeMinBounds.y,
shapeMaxBounds.x,
shapeMaxBounds.y
);
this._translation = Matrix4_default.getTranslation(modelMatrix, this._translation);
this._rotation = Matrix4_default.getRotation(modelMatrix, this._rotation);
this._ellipsoid = Ellipsoid_default.fromCartesian3(radii, this._ellipsoid);
this._minimumHeight = shapeMinBounds.z;
this._maximumHeight = shapeMaxBounds.z;
const renderRectangle = Rectangle_default.fromRadians(
renderMinBounds.x,
renderMinBounds.y,
renderMaxBounds.x,
renderMaxBounds.y,
scratchRenderRectangle
);
this.orientedBoundingBox = getEllipsoidChunkObb(
renderRectangle,
renderMinBounds.z,
renderMaxBounds.z,
this._ellipsoid,
this._translation,
this._rotation,
this.orientedBoundingBox
);
this.shapeTransform = Matrix4_default.fromRotationTranslation(
Matrix3_default.setScale(this._rotation, shapeOuterExtent, scratchRotationScale3),
this._translation,
this.shapeTransform
);
this.boundTransform = Matrix4_default.fromRotationTranslation(
this.orientedBoundingBox.halfAxes,
this.orientedBoundingBox.center,
this.boundTransform
);
this.boundingSphere = BoundingSphere_default.fromOrientedBoundingBox(
this.orientedBoundingBox,
this.boundingSphere
);
const defaultLongitudeRange = DefaultMaxBounds.x - DefaultMinBounds.x;
const defaultLongitudeRangeHalf = 0.5 * defaultLongitudeRange;
const renderIsLongitudeReversed = renderMaxBounds.x < renderMinBounds.x;
const renderLongitudeRange = renderMaxBounds.x - renderMinBounds.x + renderIsLongitudeReversed * defaultLongitudeRange;
const renderIsLongitudeRangeZero = renderLongitudeRange <= epsilonLongitude;
const renderIsLongitudeRangeUnderHalf = renderLongitudeRange >= defaultLongitudeRangeHalf - epsilonLongitude && renderLongitudeRange < defaultLongitudeRange - epsilonLongitude;
const renderIsLongitudeRangeOverHalf = renderLongitudeRange > epsilonLongitude && renderLongitudeRange < defaultLongitudeRangeHalf - epsilonLongitude;
const renderHasLongitude = renderIsLongitudeRangeZero || renderIsLongitudeRangeUnderHalf || renderIsLongitudeRangeOverHalf;
const shapeIsLongitudeReversed = shapeMaxBounds.x < shapeMinBounds.x;
const shapeLongitudeRange = shapeMaxBounds.x - shapeMinBounds.x + shapeIsLongitudeReversed * defaultLongitudeRange;
const shapeIsLongitudeRangeUnderHalf = shapeLongitudeRange > defaultLongitudeRangeHalf + epsilonLongitude && shapeLongitudeRange < defaultLongitudeRange - epsilonLongitude;
const shapeIsLongitudeRangeHalf = shapeLongitudeRange >= defaultLongitudeRangeHalf - epsilonLongitude && shapeLongitudeRange <= defaultLongitudeRangeHalf + epsilonLongitude;
const shapeIsLongitudeRangeOverHalf = shapeLongitudeRange < defaultLongitudeRangeHalf - epsilonLongitude;
const shapeHasLongitude = shapeIsLongitudeRangeUnderHalf || shapeIsLongitudeRangeHalf || shapeIsLongitudeRangeOverHalf;
const renderIsLatitudeMaxUnderHalf = renderMaxBounds.y < -epsilonLatitudeFlat;
const renderIsLatitudeMaxHalf = renderMaxBounds.y >= -epsilonLatitudeFlat && renderMaxBounds.y <= +epsilonLatitudeFlat;
const renderIsLatitudeMaxOverHalf = renderMaxBounds.y > +epsilonLatitudeFlat && renderMaxBounds.y < DefaultMaxBounds.y - epsilonLatitude;
const renderHasLatitudeMax = renderIsLatitudeMaxUnderHalf || renderIsLatitudeMaxHalf || renderIsLatitudeMaxOverHalf;
const renderIsLatitudeMinUnderHalf = renderMinBounds.y > DefaultMinBounds.y + epsilonLatitude && renderMinBounds.y < -epsilonLatitudeFlat;
const renderIsLatitudeMinHalf = renderMinBounds.y >= -epsilonLatitudeFlat && renderMinBounds.y <= +epsilonLatitudeFlat;
const renderIsLatitudeMinOverHalf = renderMinBounds.y > +epsilonLatitudeFlat;
const renderHasLatitudeMin = renderIsLatitudeMinUnderHalf || renderIsLatitudeMinHalf || renderIsLatitudeMinOverHalf;
const renderHasLatitude = renderHasLatitudeMax || renderHasLatitudeMin;
const shapeLatitudeRange = shapeMaxBounds.y - shapeMinBounds.y;
const shapeIsLatitudeMaxUnderHalf = shapeMaxBounds.y < -epsilonLatitudeFlat;
const shapeIsLatitudeMaxHalf = shapeMaxBounds.y >= -epsilonLatitudeFlat && shapeMaxBounds.y <= +epsilonLatitudeFlat;
const shapeIsLatitudeMaxOverHalf = shapeMaxBounds.y > +epsilonLatitudeFlat && shapeMaxBounds.y < DefaultMaxBounds.y - epsilonLatitude;
const shapeHasLatitudeMax = shapeIsLatitudeMaxUnderHalf || shapeIsLatitudeMaxHalf || shapeIsLatitudeMaxOverHalf;
const shapeIsLatitudeMinUnderHalf = shapeMinBounds.y > DefaultMinBounds.y + epsilonLatitude && shapeMinBounds.y < -epsilonLatitudeFlat;
const shapeIsLatitudeMinHalf = shapeMinBounds.y >= -epsilonLatitudeFlat && shapeMinBounds.y <= +epsilonLatitudeFlat;
const shapeIsLatitudeMinOverHalf = shapeMinBounds.y > +epsilonLatitudeFlat;
const shapeHasLatitudeMin = shapeIsLatitudeMinUnderHalf || shapeIsLatitudeMinHalf || shapeIsLatitudeMinOverHalf;
const shapeHasLatitude = shapeHasLatitudeMax || shapeHasLatitudeMin;
const { shaderUniforms, shaderDefines } = this;
for (const key in shaderDefines) {
if (shaderDefines.hasOwnProperty(key)) {
shaderDefines[key] = void 0;
}
}
shaderUniforms.ellipsoidRadiiUv = Cartesian3_default.divideByScalar(
shapeOuterExtent,
shapeMaxExtent,
shaderUniforms.ellipsoidRadiiUv
);
const { x: radiiUvX, z: radiiUvZ } = shaderUniforms.ellipsoidRadiiUv;
const axisRatio = radiiUvZ / radiiUvX;
shaderUniforms.eccentricitySquared = 1 - axisRatio * axisRatio;
shaderUniforms.evoluteScale = Cartesian2_default.fromElements(
(radiiUvX * radiiUvX - radiiUvZ * radiiUvZ) / radiiUvX,
(radiiUvZ * radiiUvZ - radiiUvX * radiiUvX) / radiiUvZ,
shaderUniforms.evoluteScale
);
shaderUniforms.ellipsoidInverseRadiiSquaredUv = Cartesian3_default.divideComponents(
Cartesian3_default.ONE,
Cartesian3_default.multiplyComponents(
shaderUniforms.ellipsoidRadiiUv,
shaderUniforms.ellipsoidRadiiUv,
shaderUniforms.ellipsoidInverseRadiiSquaredUv
),
shaderUniforms.ellipsoidInverseRadiiSquaredUv
);
let intersectionCount = 0;
shaderDefines["ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX"] = intersectionCount;
intersectionCount += 1;
shaderDefines["ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN"] = intersectionCount;
intersectionCount += 1;
shaderUniforms.clipMinMaxHeight = Cartesian2_default.fromElements(
(renderMinBounds.z - shapeMaxBounds.z) / shapeMaxExtent,
(renderMaxBounds.z - shapeMaxBounds.z) / shapeMaxExtent,
shaderUniforms.clipMinMaxHeight
);
const thickness = (shapeMaxBounds.z - shapeMinBounds.z) / shapeMaxExtent;
shaderUniforms.ellipsoidInverseHeightDifferenceUv = 1 / thickness;
if (shapeMinBounds.z === shapeMaxBounds.z) {
shaderUniforms.ellipsoidInverseHeightDifferenceUv = 0;
}
if (renderHasLongitude) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE"] = true;
shaderDefines["ELLIPSOID_INTERSECTION_INDEX_LONGITUDE"] = intersectionCount;
if (renderIsLongitudeRangeUnderHalf) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_UNDER_HALF"] = true;
intersectionCount += 1;
} else if (renderIsLongitudeRangeOverHalf) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_OVER_HALF"] = true;
intersectionCount += 2;
} else if (renderIsLongitudeRangeZero) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO"] = true;
intersectionCount += 2;
}
shaderUniforms.ellipsoidRenderLongitudeMinMax = Cartesian2_default.fromElements(
renderMinBounds.x,
renderMaxBounds.x,
shaderUniforms.ellipsoidRenderLongitudeMinMax
);
}
if (shapeHasLongitude) {
shaderDefines["ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE"] = true;
const shapeIsLongitudeReversed2 = shapeMaxBounds.x < shapeMinBounds.x;
if (shapeIsLongitudeReversed2) {
shaderDefines["ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE_MIN_MAX_REVERSED"] = true;
}
if (shapeLongitudeRange <= epsilonLongitude) {
shaderUniforms.ellipsoidUvToShapeUvLongitude = Cartesian2_default.fromElements(
0,
1,
shaderUniforms.ellipsoidUvToShapeUvLongitude
);
} else {
const scale = defaultLongitudeRange / shapeLongitudeRange;
const offset = -(shapeMinBounds.x - DefaultMinBounds.x) / shapeLongitudeRange;
shaderUniforms.ellipsoidUvToShapeUvLongitude = Cartesian2_default.fromElements(
scale,
offset,
shaderUniforms.ellipsoidUvToShapeUvLongitude
);
}
}
if (renderHasLongitude) {
const renderIsMinLongitudeDiscontinuity = Math_default.equalsEpsilon(
renderMinBounds.x,
DefaultMinBounds.x,
void 0,
epsilonLongitudeDiscontinuity
);
const renderIsMaxLongitudeDiscontinuity = Math_default.equalsEpsilon(
renderMaxBounds.x,
DefaultMaxBounds.x,
void 0,
epsilonLongitudeDiscontinuity
);
if (renderIsMinLongitudeDiscontinuity) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MIN_DISCONTINUITY"] = true;
}
if (renderIsMaxLongitudeDiscontinuity) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_MAX_DISCONTINUITY"] = true;
}
const uvShapeMinLongitude = (shapeMinBounds.x - DefaultMinBounds.x) / defaultLongitudeRange;
const uvShapeMaxLongitude = (shapeMaxBounds.x - DefaultMinBounds.x) / defaultLongitudeRange;
const uvRenderMaxLongitude = (renderMaxBounds.x - DefaultMinBounds.x) / defaultLongitudeRange;
const uvRenderLongitudeRangeZero = 1 - renderLongitudeRange / defaultLongitudeRange;
const uvRenderLongitudeRangeZeroMid = (uvRenderMaxLongitude + 0.5 * uvRenderLongitudeRangeZero) % 1;
shaderUniforms.ellipsoidShapeUvLongitudeMinMaxMid = Cartesian3_default.fromElements(
uvShapeMinLongitude,
uvShapeMaxLongitude,
uvRenderLongitudeRangeZeroMid,
shaderUniforms.ellipsoidShapeUvLongitudeMinMaxMid
);
}
if (renderHasLatitude) {
if (renderHasLatitudeMin) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN"] = true;
shaderDefines["ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN"] = intersectionCount;
if (renderIsLatitudeMinUnderHalf) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF"] = true;
intersectionCount += 1;
} else if (renderIsLatitudeMinHalf) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF"] = true;
intersectionCount += 1;
} else if (renderIsLatitudeMinOverHalf) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF"] = true;
intersectionCount += 2;
}
}
if (renderHasLatitudeMax) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX"] = true;
shaderDefines["ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX"] = intersectionCount;
if (renderIsLatitudeMaxUnderHalf) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF"] = true;
intersectionCount += 2;
} else if (renderIsLatitudeMaxHalf) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_EQUAL_HALF"] = true;
intersectionCount += 1;
} else if (renderIsLatitudeMaxOverHalf) {
shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF"] = true;
intersectionCount += 1;
}
}
shaderUniforms.ellipsoidRenderLatitudeSinMinMax = Cartesian2_default.fromElements(
Math.sin(renderMinBounds.y),
Math.sin(renderMaxBounds.y),
shaderUniforms.ellipsoidRenderLatitudeSinMinMax
);
}
if (shapeHasLatitude) {
shaderDefines["ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE"] = true;
if (shapeLatitudeRange < epsilonLatitude) {
shaderUniforms.ellipsoidUvToShapeUvLatitude = Cartesian2_default.fromElements(
0,
1,
shaderUniforms.ellipsoidUvToShapeUvLatitude
);
} else {
const defaultLatitudeRange = DefaultMaxBounds.y - DefaultMinBounds.y;
const scale = defaultLatitudeRange / shapeLatitudeRange;
const offset = (DefaultMinBounds.y - shapeMinBounds.y) / shapeLatitudeRange;
shaderUniforms.ellipsoidUvToShapeUvLatitude = Cartesian2_default.fromElements(
scale,
offset,
shaderUniforms.ellipsoidUvToShapeUvLatitude
);
}
}
this.shaderMaximumIntersectionsLength = intersectionCount;
return true;
};
var scratchRectangle12 = new Rectangle_default();
VoxelEllipsoidShape.prototype.computeOrientedBoundingBoxForTile = function(tileLevel, tileX, tileY, tileZ, result) {
Check_default.typeOf.number("tileLevel", tileLevel);
Check_default.typeOf.number("tileX", tileX);
Check_default.typeOf.number("tileY", tileY);
Check_default.typeOf.number("tileZ", tileZ);
Check_default.typeOf.object("result", result);
const sizeAtLevel = 1 / Math.pow(2, tileLevel);
const minLongitudeLerp = tileX * sizeAtLevel;
const maxLongitudeLerp = (tileX + 1) * sizeAtLevel;
const minLatitudeLerp = tileY * sizeAtLevel;
const maxLatitudeLerp = (tileY + 1) * sizeAtLevel;
const minHeightLerp = tileZ * sizeAtLevel;
const maxHeightLerp = (tileZ + 1) * sizeAtLevel;
const rectangle = Rectangle_default.subsection(
this._rectangle,
minLongitudeLerp,
minLatitudeLerp,
maxLongitudeLerp,
maxLatitudeLerp,
scratchRectangle12
);
const minHeight = Math_default.lerp(
this._minimumHeight,
this._maximumHeight,
minHeightLerp
);
const maxHeight = Math_default.lerp(
this._minimumHeight,
this._maximumHeight,
maxHeightLerp
);
return getEllipsoidChunkObb(
rectangle,
minHeight,
maxHeight,
this._ellipsoid,
this._translation,
this._rotation,
result
);
};
var sampleSizeScratch3 = new Cartesian3_default();
var scratchTileMinBounds2 = new Cartesian3_default();
var scratchTileMaxBounds2 = new Cartesian3_default();
VoxelEllipsoidShape.prototype.computeOrientedBoundingBoxForSample = function(spatialNode, tileDimensions, tileUv, result) {
Check_default.typeOf.object("spatialNode", spatialNode);
Check_default.typeOf.object("tileDimensions", tileDimensions);
Check_default.typeOf.object("tileUv", tileUv);
Check_default.typeOf.object("result", result);
const tileSizeAtLevel = 1 / Math.pow(2, spatialNode.level);
const sampleSize = Cartesian3_default.divideComponents(
Cartesian3_default.ONE,
tileDimensions,
sampleSizeScratch3
);
const sampleSizeAtLevel = Cartesian3_default.multiplyByScalar(
sampleSize,
tileSizeAtLevel,
sampleSizeScratch3
);
const minLerp = Cartesian3_default.multiplyByScalar(
Cartesian3_default.fromElements(
spatialNode.x + tileUv.x,
spatialNode.y + tileUv.y,
spatialNode.z + tileUv.z,
scratchTileMinBounds2
),
tileSizeAtLevel,
scratchTileMinBounds2
);
const maxLerp = Cartesian3_default.add(
minLerp,
sampleSizeAtLevel,
scratchTileMaxBounds2
);
const rectangle = Rectangle_default.subsection(
this._rectangle,
minLerp.x,
minLerp.y,
maxLerp.x,
maxLerp.y,
scratchRectangle12
);
const minHeight = Math_default.lerp(
this._minimumHeight,
this._maximumHeight,
minLerp.z
);
const maxHeight = Math_default.lerp(
this._minimumHeight,
this._maximumHeight,
maxLerp.z
);
return getEllipsoidChunkObb(
rectangle,
minHeight,
maxHeight,
this._ellipsoid,
this._translation,
this._rotation,
result
);
};
function getEllipsoidChunkObb(rectangle, minHeight, maxHeight, ellipsoid, translation3, rotation, result) {
result = OrientedBoundingBox_default.fromRectangle(
rectangle,
minHeight,
maxHeight,
ellipsoid,
result
);
result.center = Cartesian3_default.add(result.center, translation3, result.center);
result.halfAxes = Matrix3_default.multiply(
result.halfAxes,
rotation,
result.halfAxes
);
return result;
}
VoxelEllipsoidShape.DefaultMinBounds = Object.freeze(
new Cartesian3_default(
-Math_default.PI,
-Math_default.PI_OVER_TWO,
-Ellipsoid_default.WGS84.minimumRadius
)
);
VoxelEllipsoidShape.DefaultMaxBounds = Object.freeze(
new Cartesian3_default(
Math_default.PI,
Math_default.PI_OVER_TWO,
10 * Ellipsoid_default.WGS84.maximumRadius
)
);
var VoxelEllipsoidShape_default = VoxelEllipsoidShape;
// packages/engine/Source/Scene/VoxelShapeType.js
var VoxelShapeType = {
/**
* A box shape.
*
* @type {string}
* @constant
* @private
*/
BOX: "BOX",
/**
* An ellipsoid shape.
*
* @type {string}
* @constant
* @private
*/
ELLIPSOID: "ELLIPSOID",
/**
* A cylinder shape.
*
* @type {string}
* @constant
* @private
*/
CYLINDER: "CYLINDER"
};
VoxelShapeType.getMinBounds = function(shapeType) {
switch (shapeType) {
case VoxelShapeType.BOX:
return VoxelBoxShape_default.DefaultMinBounds;
case VoxelShapeType.ELLIPSOID:
return VoxelEllipsoidShape_default.DefaultMinBounds;
case VoxelShapeType.CYLINDER:
return VoxelCylinderShape_default.DefaultMinBounds;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default(`Invalid shape type ${shapeType}`);
}
};
VoxelShapeType.getMaxBounds = function(shapeType) {
switch (shapeType) {
case VoxelShapeType.BOX:
return VoxelBoxShape_default.DefaultMaxBounds;
case VoxelShapeType.ELLIPSOID:
return VoxelEllipsoidShape_default.DefaultMaxBounds;
case VoxelShapeType.CYLINDER:
return VoxelCylinderShape_default.DefaultMaxBounds;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default(`Invalid shape type ${shapeType}`);
}
};
VoxelShapeType.getShapeConstructor = function(shapeType) {
switch (shapeType) {
case VoxelShapeType.BOX:
return VoxelBoxShape_default;
case VoxelShapeType.ELLIPSOID:
return VoxelEllipsoidShape_default;
case VoxelShapeType.CYLINDER:
return VoxelCylinderShape_default;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default(`Invalid shape type ${shapeType}`);
}
};
var VoxelShapeType_default = Object.freeze(VoxelShapeType);
// packages/engine/Source/Scene/VoxelTraversal.js
var import_InlineWorkers1157 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/DoubleEndedPriorityQueue.js
var import_InlineWorkers1153 = __toESM(require_InlineWorkers(), 1);
function DoubleEndedPriorityQueue(options) {
Check_default.typeOf.object("options", options);
Check_default.defined("options.comparator", options.comparator);
if (defined_default(options.maximumLength)) {
Check_default.typeOf.number.greaterThanOrEquals(
"options.maximumLength",
options.maximumLength,
0
);
}
this._comparator = options.comparator;
this._maximumLength = options.maximumLength;
this._array = defined_default(options.maximumLength) ? new Array(options.maximumLength) : [];
this._length = 0;
}
Object.defineProperties(DoubleEndedPriorityQueue.prototype, {
/**
* Gets the number of elements in the queue.
*
* @memberof DoubleEndedPriorityQueue.prototype
*
* @type {number}
* @readonly
*/
length: {
get: function() {
return this._length;
}
},
/**
* Gets or sets the maximum number of elements in the queue.
* If set to a smaller value than the current length of the queue, the lowest priority elements are removed.
* If an element is inserted when the queue is at full capacity, the minimum element is removed.
* If set to undefined, the size of the queue is unlimited.
*
* @memberof DoubleEndedPriorityQueue.prototype
*
* @type {number}
* @readonly
*/
maximumLength: {
get: function() {
return this._maximumLength;
},
set: function(value) {
if (defined_default(value)) {
Check_default.typeOf.number.greaterThanOrEquals("maximumLength", value, 0);
while (this._length > value) {
this.removeMinimum();
}
this._array.length = value;
}
this._maximumLength = value;
}
},
/**
* Gets the internal array.
*
* @memberof DoubleEndedPriorityQueue.prototype
*
* @type {Array}
* @readonly
*/
internalArray: {
get: function() {
return this._array;
}
},
/**
* The comparator used by the queue.
* If comparator(a, b) is less than 0, a is lower priority than b.
*
* @memberof DoubleEndedPriorityQueue.prototype
*
* @type {DoubleEndedPriorityQueue.ComparatorCallback}
* @readonly
*/
comparator: {
get: function() {
return this._comparator;
}
}
});
DoubleEndedPriorityQueue.prototype.clone = function() {
const maximumLength = this._maximumLength;
const comparator = this._comparator;
const array = this._array;
const length2 = this._length;
const result = new DoubleEndedPriorityQueue({
comparator,
maximumLength
});
result._length = length2;
for (let i = 0; i < length2; i++) {
result._array[i] = array[i];
}
return result;
};
DoubleEndedPriorityQueue.prototype.reset = function() {
this._length = 0;
const maximumLength = this._maximumLength;
if (defined_default(maximumLength)) {
for (let i = 0; i < maximumLength; i++) {
this._array[i] = void 0;
}
} else {
this._array.length = 0;
}
};
DoubleEndedPriorityQueue.prototype.resort = function() {
const length2 = this._length;
for (let i = 0; i < length2; i++) {
pushUp(this, i);
}
};
DoubleEndedPriorityQueue.prototype.insert = function(element) {
let removedElement;
const maximumLength = this._maximumLength;
if (defined_default(maximumLength)) {
if (maximumLength === 0) {
return void 0;
} else if (this._length === maximumLength) {
const minimumElement = this._array[0];
if (this._comparator(element, minimumElement) <= 0) {
return element;
}
removedElement = this.removeMinimum();
}
}
const index = this._length;
this._array[index] = element;
this._length++;
pushUp(this, index);
return removedElement;
};
DoubleEndedPriorityQueue.prototype.removeMinimum = function() {
const length2 = this._length;
if (length2 === 0) {
return void 0;
}
this._length--;
const minimumElement = this._array[0];
if (length2 >= 2) {
this._array[0] = this._array[length2 - 1];
pushDown(this, 0);
}
this._array[length2 - 1] = void 0;
return minimumElement;
};
DoubleEndedPriorityQueue.prototype.removeMaximum = function() {
const length2 = this._length;
if (length2 === 0) {
return void 0;
}
this._length--;
let maximumElement;
if (length2 <= 2) {
maximumElement = this._array[length2 - 1];
} else {
const maximumElementIndex = greaterThan(this, 1, 2) ? 1 : 2;
maximumElement = this._array[maximumElementIndex];
this._array[maximumElementIndex] = this._array[length2 - 1];
if (length2 >= 4) {
pushDown(this, maximumElementIndex);
}
}
this._array[length2 - 1] = void 0;
return maximumElement;
};
DoubleEndedPriorityQueue.prototype.getMinimum = function() {
const length2 = this._length;
if (length2 === 0) {
return void 0;
}
return this._array[0];
};
DoubleEndedPriorityQueue.prototype.getMaximum = function() {
const length2 = this._length;
if (length2 === 0) {
return void 0;
}
if (length2 <= 2) {
return this._array[length2 - 1];
}
return this._array[greaterThan(this, 1, 2) ? 1 : 2];
};
function swap4(that, indexA, indexB) {
const array = that._array;
const temp = array[indexA];
array[indexA] = array[indexB];
array[indexB] = temp;
}
function lessThan(that, indexA, indexB) {
return that._comparator(that._array[indexA], that._array[indexB]) < 0;
}
function greaterThan(that, indexA, indexB) {
return that._comparator(that._array[indexA], that._array[indexB]) > 0;
}
function pushUp(that, index) {
if (index === 0) {
return;
}
const onMinLevel = Math.floor(Math_default.log2(index + 1)) % 2 === 0;
const parentIndex = Math.floor((index - 1) / 2);
const lessThanParent = lessThan(that, index, parentIndex);
if (lessThanParent !== onMinLevel) {
swap4(that, index, parentIndex);
index = parentIndex;
}
while (index >= 3) {
const grandparentIndex = Math.floor((index - 3) / 4);
if (lessThan(that, index, grandparentIndex) !== lessThanParent) {
break;
}
swap4(that, index, grandparentIndex);
index = grandparentIndex;
}
}
function pushDown(that, index) {
const length2 = that._length;
const onMinLevel = Math.floor(Math_default.log2(index + 1)) % 2 === 0;
let leftChildIndex;
while ((leftChildIndex = 2 * index + 1) < length2) {
let target = leftChildIndex;
const rightChildIndex = leftChildIndex + 1;
if (rightChildIndex < length2) {
if (lessThan(that, rightChildIndex, target) === onMinLevel) {
target = rightChildIndex;
}
const grandChildStart = 2 * leftChildIndex + 1;
const grandChildCount = Math.max(
Math.min(length2 - grandChildStart, 4),
0
);
for (let i = 0; i < grandChildCount; i++) {
const grandChildIndex = grandChildStart + i;
if (lessThan(that, grandChildIndex, target) === onMinLevel) {
target = grandChildIndex;
}
}
}
if (lessThan(that, target, index) === onMinLevel) {
swap4(that, target, index);
if (target !== leftChildIndex && target !== rightChildIndex) {
const parentOfGrandchildIndex = Math.floor((target - 1) / 2);
if (greaterThan(that, target, parentOfGrandchildIndex) === onMinLevel) {
swap4(that, target, parentOfGrandchildIndex);
}
}
}
index = target;
}
}
var DoubleEndedPriorityQueue_default = DoubleEndedPriorityQueue;
// packages/engine/Source/Scene/KeyframeNode.js
var import_InlineWorkers1154 = __toESM(require_InlineWorkers(), 1);
var LoadState = Object.freeze({
UNLOADED: 0,
// Has no data and is in dormant state
RECEIVING: 1,
// Is waiting on data from the provider
PROCESSING: 2,
// Data received. Contents are being processed for rendering. Depending on the content, it might make its own requests for external data.
LOADED: 3,
// Processed data from provider
FAILED: 4,
// Failed to receive data from the provider
UNAVAILABLE: 5
// No data available for this tile
});
function KeyframeNode(spatialNode, keyframe) {
this.spatialNode = spatialNode;
this.keyframe = keyframe;
this.state = LoadState.UNLOADED;
this.content = void 0;
this.megatextureIndex = -1;
this.priority = -Number.MAX_VALUE;
this.highPriorityFrameNumber = -1;
}
KeyframeNode.prototype.unload = function() {
this.content = this.content && this.content.destroy();
this.spatialNode = void 0;
this.state = LoadState.UNLOADED;
this.megatextureIndex = -1;
this.priority = -Number.MAX_VALUE;
this.highPriorityFrameNumber = -1;
};
KeyframeNode.priorityComparator = function(a3, b) {
return a3.priority - b.priority;
};
KeyframeNode.searchComparator = function(a3, b) {
return a3.keyframe - b.keyframe;
};
KeyframeNode.LoadState = LoadState;
var KeyframeNode_default = KeyframeNode;
// packages/engine/Source/Scene/Megatexture.js
var import_InlineWorkers1155 = __toESM(require_InlineWorkers(), 1);
function Megatexture(context, dimensions, channelCount, componentType, availableTextureMemoryBytes) {
const maximumTextureMemoryByteLength = 512 * 1024 * 1024;
availableTextureMemoryBytes = Math.min(
availableTextureMemoryBytes ?? 128 * 1024 * 1024,
maximumTextureMemoryByteLength
);
if (componentType === MetadataComponentType_default.UNSIGNED_SHORT) {
componentType = MetadataComponentType_default.FLOAT32;
}
if (componentType === MetadataComponentType_default.FLOAT32 && !context.floatingPointTexture) {
throw new RuntimeError_default("Floating point texture not supported");
}
const pixelDataType = getPixelDataType(componentType);
const pixelFormat = getPixelFormat(channelCount, context.webgl2);
const componentTypeByteLength = MetadataComponentType_default.getSizeInBytes(componentType);
const textureDimension = getTextureDimension(
availableTextureMemoryBytes,
channelCount,
componentTypeByteLength
);
const sliceCountPerRegionX = Math.ceil(Math.sqrt(dimensions.x));
const sliceCountPerRegionY = Math.ceil(dimensions.z / sliceCountPerRegionX);
const voxelCountPerRegionX = sliceCountPerRegionX * dimensions.x;
const voxelCountPerRegionY = sliceCountPerRegionY * dimensions.y;
const regionCountPerMegatextureX = Math.floor(
textureDimension / voxelCountPerRegionX
);
const regionCountPerMegatextureY = Math.floor(
textureDimension / voxelCountPerRegionY
);
if (regionCountPerMegatextureX === 0 || regionCountPerMegatextureY === 0) {
throw new RuntimeError_default("Tileset is too large to fit into megatexture");
}
this.channelCount = channelCount;
this.componentType = componentType;
this.textureMemoryByteLength = componentTypeByteLength * channelCount * textureDimension ** 2;
this.voxelCountPerTile = Cartesian3_default.clone(dimensions, new Cartesian3_default());
this.maximumTileCount = regionCountPerMegatextureX * regionCountPerMegatextureY;
this.regionCountPerMegatexture = new Cartesian2_default(
regionCountPerMegatextureX,
regionCountPerMegatextureY
);
this.voxelCountPerRegion = new Cartesian2_default(
voxelCountPerRegionX,
voxelCountPerRegionY
);
this.sliceCountPerRegion = new Cartesian2_default(
sliceCountPerRegionX,
sliceCountPerRegionY
);
this.voxelSizeUv = new Cartesian2_default(
1 / textureDimension,
1 / textureDimension
);
this.sliceSizeUv = new Cartesian2_default(
dimensions.x / textureDimension,
dimensions.y / textureDimension
);
this.regionSizeUv = new Cartesian2_default(
voxelCountPerRegionX / textureDimension,
voxelCountPerRegionY / textureDimension
);
this.texture = new Texture_default({
context,
pixelFormat,
pixelDatatype: pixelDataType,
flipY: false,
width: textureDimension,
height: textureDimension,
sampler: new Sampler_default({
wrapS: TextureWrap_default.CLAMP_TO_EDGE,
wrapT: TextureWrap_default.CLAMP_TO_EDGE,
minificationFilter: TextureMinificationFilter_default.LINEAR,
magnificationFilter: TextureMagnificationFilter_default.LINEAR
})
});
const componentDatatype = MetadataComponentType_default.toComponentDatatype(componentType);
this.tileVoxelDataTemp = ComponentDatatype_default.createTypedArray(
componentDatatype,
voxelCountPerRegionX * voxelCountPerRegionY * channelCount
);
this.nodes = new Array(this.maximumTileCount);
for (let tileIndex = 0; tileIndex < this.maximumTileCount; tileIndex++) {
this.nodes[tileIndex] = new MegatextureNode(tileIndex);
}
for (let tileIndex = 0; tileIndex < this.maximumTileCount; tileIndex++) {
const node = this.nodes[tileIndex];
node.previousNode = tileIndex > 0 ? this.nodes[tileIndex - 1] : void 0;
node.nextNode = tileIndex < this.maximumTileCount - 1 ? this.nodes[tileIndex + 1] : void 0;
}
this.occupiedList = void 0;
this.emptyList = this.nodes[0];
this.occupiedCount = 0;
}
function getPixelDataType(componentType) {
if (componentType === MetadataComponentType_default.FLOAT32 || componentType === MetadataComponentType_default.FLOAT64) {
return PixelDatatype_default.FLOAT;
} else if (componentType === MetadataComponentType_default.UINT8) {
return PixelDatatype_default.UNSIGNED_BYTE;
}
}
function getPixelFormat(channelCount, webgl2) {
if (channelCount === 1) {
return webgl2 ? PixelFormat_default.RED : PixelFormat_default.LUMINANCE;
} else if (channelCount === 2) {
return webgl2 ? PixelFormat_default.RG : PixelFormat_default.LUMINANCE_ALPHA;
} else if (channelCount === 3) {
return PixelFormat_default.RGB;
} else if (channelCount === 4) {
return PixelFormat_default.RGBA;
}
}
function getTextureDimension(availableTextureMemoryBytes, channelCount, componentByteLength) {
const texelCount = Math.floor(
availableTextureMemoryBytes / (channelCount * componentByteLength)
);
return Math.min(
ContextLimits_default.maximumTextureSize,
Math_default.previousPowerOfTwo(Math.floor(Math.sqrt(texelCount)))
);
}
function MegatextureNode(index) {
this.index = index;
this.nextNode = void 0;
this.previousNode = void 0;
}
Megatexture.prototype.add = function(data) {
if (this.isFull()) {
throw new DeveloperError_default("Trying to add when there are no empty spots");
}
const node = this.emptyList;
this.emptyList = this.emptyList.nextNode;
if (defined_default(this.emptyList)) {
this.emptyList.previousNode = void 0;
}
node.nextNode = this.occupiedList;
if (defined_default(node.nextNode)) {
node.nextNode.previousNode = node;
}
this.occupiedList = node;
const index = node.index;
this.writeDataToTexture(index, data);
this.occupiedCount++;
return index;
};
Megatexture.prototype.remove = function(index) {
if (index < 0 || index >= this.maximumTileCount) {
throw new DeveloperError_default("Megatexture index out of bounds");
}
const node = this.nodes[index];
if (defined_default(node.previousNode)) {
node.previousNode.nextNode = node.nextNode;
}
if (defined_default(node.nextNode)) {
node.nextNode.previousNode = node.previousNode;
}
node.nextNode = this.emptyList;
if (defined_default(node.nextNode)) {
node.nextNode.previousNode = node;
}
node.previousNode = void 0;
this.emptyList = node;
this.occupiedCount--;
};
Megatexture.prototype.isFull = function() {
return this.emptyList === void 0;
};
Megatexture.getApproximateTextureMemoryByteLength = function(tileCount, dimensions, channelCount, componentType) {
if (componentType === MetadataComponentType_default.UNSIGNED_SHORT) {
componentType = MetadataComponentType_default.FLOAT32;
}
const datatypeSizeInBytes = MetadataComponentType_default.getSizeInBytes(componentType);
const voxelCountTotal = tileCount * dimensions.x * dimensions.y * dimensions.z;
const sliceCountPerRegionX = Math.ceil(Math.sqrt(dimensions.x));
const sliceCountPerRegionY = Math.ceil(dimensions.z / sliceCountPerRegionX);
const voxelCountPerRegionX = sliceCountPerRegionX * dimensions.x;
const voxelCountPerRegionY = sliceCountPerRegionY * dimensions.y;
let textureDimension = Math_default.previousPowerOfTwo(
Math.floor(Math.sqrt(voxelCountTotal))
);
for (; ; ) {
const regionCountX = Math.floor(textureDimension / voxelCountPerRegionX);
const regionCountY = Math.floor(textureDimension / voxelCountPerRegionY);
const regionCount = regionCountX * regionCountY;
if (regionCount >= tileCount) {
break;
} else {
textureDimension *= 2;
}
}
const textureMemoryByteLength = textureDimension * textureDimension * channelCount * datatypeSizeInBytes;
return textureMemoryByteLength;
};
Megatexture.prototype.writeDataToTexture = function(index, data) {
const tileData = data.constructor === Uint16Array ? new Float32Array(data) : data;
const {
tileVoxelDataTemp,
voxelCountPerTile,
sliceCountPerRegion,
voxelCountPerRegion,
channelCount,
regionCountPerMegatexture
} = this;
for (let z = 0; z < voxelCountPerTile.z; z++) {
const sliceVoxelOffsetX = z % sliceCountPerRegion.x * voxelCountPerTile.x;
const sliceVoxelOffsetY = Math.floor(z / sliceCountPerRegion.x) * voxelCountPerTile.y;
for (let y = 0; y < voxelCountPerTile.y; y++) {
const readOffset = getReadOffset(voxelCountPerTile, y, z);
const writeOffset = (sliceVoxelOffsetY + y) * voxelCountPerRegion.x + sliceVoxelOffsetX;
for (let x = 0; x < voxelCountPerTile.x; x++) {
const readIndex = readOffset + x;
const writeIndex = writeOffset + x;
for (let c = 0; c < channelCount; c++) {
tileVoxelDataTemp[writeIndex * channelCount + c] = tileData[readIndex * channelCount + c];
}
}
}
}
const voxelOffsetX = index % regionCountPerMegatexture.x * voxelCountPerRegion.x;
const voxelOffsetY = Math.floor(index / regionCountPerMegatexture.x) * voxelCountPerRegion.y;
const source = {
arrayBufferView: tileVoxelDataTemp,
width: voxelCountPerRegion.x,
height: voxelCountPerRegion.y
};
const copyOptions = {
source,
xOffset: voxelOffsetX,
yOffset: voxelOffsetY
};
this.texture.copyFrom(copyOptions);
};
function getReadOffset(dimensions, y, z) {
const voxelsPerInputSlice = dimensions.y * dimensions.x;
const sliceIndex = z;
const rowIndex = y;
return sliceIndex * voxelsPerInputSlice + rowIndex * dimensions.x;
}
Megatexture.prototype.isDestroyed = function() {
return false;
};
Megatexture.prototype.destroy = function() {
this.texture = this.texture && this.texture.destroy();
return destroyObject_default(this);
};
var Megatexture_default2 = Megatexture;
// packages/engine/Source/Scene/SpatialNode.js
var import_InlineWorkers1156 = __toESM(require_InlineWorkers(), 1);
function SpatialNode(level, x, y, z, parent, shape, voxelDimensions) {
this.children = void 0;
this.parent = parent;
this.level = level;
this.x = x;
this.y = y;
this.z = z;
this.dimensions = Cartesian3_default.clone(voxelDimensions);
this.keyframeNodes = [];
this.renderableKeyframeNodes = [];
this.renderableKeyframeNodeLerp = 0;
this.renderableKeyframeNodePrevious = void 0;
this.renderableKeyframeNodeNext = void 0;
this.orientedBoundingBox = new OrientedBoundingBox_default();
this.approximateVoxelSize = 0;
this.screenSpaceError = 0;
this.visitedFrameNumber = -1;
this.computeBoundingVolumes(shape);
}
var scratchObbHalfScale = new Cartesian3_default();
SpatialNode.prototype.computeBoundingVolumes = function(shape) {
this.orientedBoundingBox = shape.computeOrientedBoundingBoxForTile(
this.level,
this.x,
this.y,
this.z,
this.orientedBoundingBox
);
const halfScale = Matrix3_default.getScale(
this.orientedBoundingBox.halfAxes,
scratchObbHalfScale
);
const maximumScale = 2 * Cartesian3_default.maximumComponent(halfScale);
this.approximateVoxelSize = maximumScale / Cartesian3_default.minimumComponent(this.dimensions);
};
SpatialNode.prototype.constructChildNodes = function(shape) {
const { level, x, y, z } = this;
const xMin = x * 2;
const yMin = y * 2;
const zMin = z * 2;
const yMax = yMin + 1;
const xMax = xMin + 1;
const zMax = zMin + 1;
const childLevel = level + 1;
const childCoords = [
[childLevel, xMin, yMin, zMin],
[childLevel, xMax, yMin, zMin],
[childLevel, xMin, yMax, zMin],
[childLevel, xMax, yMax, zMin],
[childLevel, xMin, yMin, zMax],
[childLevel, xMax, yMin, zMax],
[childLevel, xMin, yMax, zMax],
[childLevel, xMax, yMax, zMax]
];
this.children = childCoords.map(([level2, x2, y2, z2]) => {
return new SpatialNode(level2, x2, y2, z2, this, shape, this.dimensions);
});
};
SpatialNode.prototype.visibility = function(frameState, visibilityPlaneMask) {
const obb = this.orientedBoundingBox;
const cullingVolume = frameState.cullingVolume;
return cullingVolume.computeVisibilityWithPlaneMask(obb, visibilityPlaneMask);
};
SpatialNode.prototype.computeScreenSpaceError = function(cameraPosition, screenSpaceErrorMultiplier) {
const obb = this.orientedBoundingBox;
let distance2 = Math.sqrt(obb.distanceSquaredTo(cameraPosition));
distance2 = Math.max(distance2, Math_default.EPSILON7);
const approximateVoxelSize = this.approximateVoxelSize;
const error = screenSpaceErrorMultiplier * (approximateVoxelSize / distance2);
this.screenSpaceError = error;
};
var scratchBinarySearchKeyframeNode = {
keyframe: 0
};
function findKeyframeIndex(keyframe, keyframeNodes) {
scratchBinarySearchKeyframeNode.keyframe = keyframe;
return binarySearch_default(
keyframeNodes,
scratchBinarySearchKeyframeNode,
KeyframeNode_default.searchComparator
);
}
SpatialNode.prototype.computeSurroundingRenderableKeyframeNodes = function(keyframeLocation) {
let spatialNode = this;
const startLevel = spatialNode.level;
const targetKeyframePrev = Math.floor(keyframeLocation);
const targetKeyframeNext = Math.ceil(keyframeLocation);
let bestKeyframeNodePrev;
let bestKeyframeNodeNext;
let minimumDistancePrev = +Number.MAX_VALUE;
let minimumDistanceNext = +Number.MAX_VALUE;
while (defined_default(spatialNode)) {
const { renderableKeyframeNodes } = spatialNode;
if (renderableKeyframeNodes.length >= 1) {
const indexPrev = getKeyframeIndexPrev(
targetKeyframePrev,
renderableKeyframeNodes
);
const keyframeNodePrev = renderableKeyframeNodes[indexPrev];
const indexNext = targetKeyframeNext === targetKeyframePrev || targetKeyframePrev < keyframeNodePrev.keyframe ? indexPrev : Math.min(indexPrev + 1, renderableKeyframeNodes.length - 1);
const keyframeNodeNext = renderableKeyframeNodes[indexNext];
const distancePrev = targetKeyframePrev - keyframeNodePrev.keyframe;
const weightedDistancePrev = getWeightedKeyframeDistance(
startLevel - spatialNode.level,
distancePrev
);
if (weightedDistancePrev < minimumDistancePrev) {
minimumDistancePrev = weightedDistancePrev;
bestKeyframeNodePrev = keyframeNodePrev;
}
const distanceNext = keyframeNodeNext.keyframe - targetKeyframeNext;
const weightedDistanceNext = getWeightedKeyframeDistance(
startLevel - spatialNode.level,
distanceNext
);
if (weightedDistanceNext < minimumDistanceNext) {
minimumDistanceNext = weightedDistanceNext;
bestKeyframeNodeNext = keyframeNodeNext;
}
if (distancePrev === 0 && distanceNext === 0) {
break;
}
}
spatialNode = spatialNode.parent;
}
this.renderableKeyframeNodePrevious = bestKeyframeNodePrev;
this.renderableKeyframeNodeNext = bestKeyframeNodeNext;
if (!defined_default(bestKeyframeNodePrev) || !defined_default(bestKeyframeNodeNext)) {
return;
}
const bestKeyframePrev = bestKeyframeNodePrev.keyframe;
const bestKeyframeNext = bestKeyframeNodeNext.keyframe;
this.renderableKeyframeNodeLerp = bestKeyframePrev === bestKeyframeNext ? 0 : Math_default.clamp(
(keyframeLocation - bestKeyframePrev) / (bestKeyframeNext - bestKeyframePrev),
0,
1
);
};
function getKeyframeIndexPrev(targetKeyframe, keyframeNodes) {
const keyframeIndex = findKeyframeIndex(targetKeyframe, keyframeNodes);
return keyframeIndex < 0 ? Math_default.clamp(~keyframeIndex - 1, 0, keyframeNodes.length - 1) : keyframeIndex;
}
function getWeightedKeyframeDistance(levelDistance, keyframeDistance) {
const levelWeight = Math.exp(levelDistance * 4);
const keyframeWeight = keyframeDistance >= 0 ? 1 : -200;
return levelDistance * levelWeight + keyframeDistance * keyframeWeight;
}
SpatialNode.prototype.isVisited = function(frameNumber) {
return this.visitedFrameNumber === frameNumber;
};
SpatialNode.prototype.createKeyframeNode = function(keyframe) {
let index = findKeyframeIndex(keyframe, this.keyframeNodes);
if (index < 0) {
index = ~index;
const keyframeNode = new KeyframeNode_default(this, keyframe);
this.keyframeNodes.splice(index, 0, keyframeNode);
}
};
SpatialNode.prototype.destroyKeyframeNode = function(keyframeNode, megatextures) {
const keyframe = keyframeNode.keyframe;
const keyframeIndex = findKeyframeIndex(keyframe, this.keyframeNodes);
if (keyframeIndex < 0) {
throw new DeveloperError_default("Keyframe node does not exist.");
}
this.keyframeNodes.splice(keyframeIndex, 1);
if (keyframeNode.megatextureIndex !== -1) {
for (let i = 0; i < megatextures.length; i++) {
megatextures[i].remove(keyframeNode.megatextureIndex);
}
const renderableKeyframeNodeIndex = findKeyframeIndex(
keyframe,
this.renderableKeyframeNodes
);
if (renderableKeyframeNodeIndex < 0) {
throw new DeveloperError_default("Renderable keyframe node does not exist.");
}
this.renderableKeyframeNodes.splice(renderableKeyframeNodeIndex, 1);
}
keyframeNode.unload();
};
SpatialNode.prototype.addKeyframeNodeToMegatextures = function(keyframeNode, megatextures) {
if (keyframeNode.megatextureIndex !== -1 || keyframeNode.content.metadata.length !== megatextures.length) {
throw new DeveloperError_default("Keyframe node cannot be added to megatexture");
}
const { metadata } = keyframeNode.content;
for (let i = 0; i < megatextures.length; i++) {
const megatexture = megatextures[i];
keyframeNode.megatextureIndex = megatexture.add(metadata[i]);
}
const renderableKeyframeNodes = this.renderableKeyframeNodes;
let renderableKeyframeNodeIndex = findKeyframeIndex(
keyframeNode.keyframe,
renderableKeyframeNodes
);
if (renderableKeyframeNodeIndex >= 0) {
throw new DeveloperError_default("Keyframe already renderable");
}
renderableKeyframeNodeIndex = ~renderableKeyframeNodeIndex;
renderableKeyframeNodes.splice(renderableKeyframeNodeIndex, 0, keyframeNode);
};
SpatialNode.prototype.isRenderable = function(frameNumber) {
const previousNode = this.renderableKeyframeNodePrevious;
const nextNode = this.renderableKeyframeNodeNext;
const level = this.level;
return defined_default(previousNode) && defined_default(nextNode) && (previousNode.spatialNode.level === level || nextNode.spatialNode.level === level) && this.visitedFrameNumber === frameNumber;
};
var SpatialNode_default = SpatialNode;
// packages/engine/Source/Scene/VoxelTraversal.js
function VoxelTraversal(primitive, context, keyframeCount, maximumTextureMemoryByteLength) {
const { provider, dimensions, paddingBefore, paddingAfter } = primitive;
const { types, componentTypes, metadataOrder } = provider;
const inputDimensions = Cartesian3_default.add(
dimensions,
paddingBefore,
new Cartesian3_default()
);
Cartesian3_default.add(inputDimensions, paddingAfter, inputDimensions);
if (metadataOrder === VoxelMetadataOrder_default.Y_UP) {
const inputDimensionsY = inputDimensions.y;
inputDimensions.y = inputDimensions.z;
inputDimensions.z = inputDimensionsY;
}
if (!defined_default(maximumTextureMemoryByteLength) && defined_default(provider.maximumTileCount)) {
maximumTextureMemoryByteLength = getApproximateTextureMemoryByteLength(
provider.maximumTileCount,
inputDimensions,
types,
componentTypes
);
}
this._primitive = primitive;
this.textureMemoryByteLength = 0;
this.megatextures = new Array(types.length);
for (let i = 0; i < types.length; i++) {
const type = types[i];
const componentCount = MetadataType_default.getComponentCount(type);
const componentType = componentTypes[i];
this.megatextures[i] = new Megatexture_default2(
context,
inputDimensions,
componentCount,
componentType,
maximumTextureMemoryByteLength
);
this.textureMemoryByteLength += this.megatextures[i].textureMemoryByteLength;
}
const maximumTileCount = this.megatextures[0].maximumTileCount;
this._simultaneousRequestCount = 0;
this._debugPrint = false;
this._calculateStatistics = this._primitive._calculateStatistics ?? false;
this._frameNumber = 0;
const shape = primitive._shape;
this.rootNode = new SpatialNode_default(0, 0, 0, 0, void 0, shape, dimensions);
this._priorityQueue = new DoubleEndedPriorityQueue_default({
maximumLength: maximumTileCount,
comparator: KeyframeNode_default.priorityComparator
});
this._highPriorityKeyframeNodes = new Array(maximumTileCount);
this._highPriorityKeyframeNodeCount = 0;
this._keyframeNodesInMegatexture = new Array(maximumTileCount);
this._keyframeCount = keyframeCount;
this._sampleCount = void 0;
this._keyframeLocation = 0;
this._binaryTreeKeyframeWeighting = new Array(keyframeCount);
this._initialTilesLoaded = false;
const binaryTreeKeyframeWeighting = this._binaryTreeKeyframeWeighting;
binaryTreeKeyframeWeighting[0] = 0;
binaryTreeKeyframeWeighting[keyframeCount - 1] = 0;
binaryTreeWeightingRecursive(
binaryTreeKeyframeWeighting,
1,
keyframeCount - 2,
0
);
const internalNodeTexelCount = 9;
const internalNodeTextureDimensionX = 2048;
const internalNodeTilesPerRow = Math.floor(
internalNodeTextureDimensionX / internalNodeTexelCount
);
const internalNodeTextureDimensionY = Math.ceil(
maximumTileCount / internalNodeTilesPerRow
);
this.internalNodeTexture = new Texture_default({
context,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
flipY: false,
width: internalNodeTextureDimensionX,
height: internalNodeTextureDimensionY,
sampler: new Sampler_default({
minificationFilter: TextureMinificationFilter_default.NEAREST,
magnificationFilter: TextureMagnificationFilter_default.NEAREST
})
});
this.internalNodeTilesPerRow = internalNodeTilesPerRow;
this.internalNodeTexelSizeUv = new Cartesian2_default(
1 / internalNodeTextureDimensionX,
1 / internalNodeTextureDimensionY
);
this.leafNodeTexture = void 0;
this.leafNodeTilesPerRow = void 0;
this.leafNodeTexelSizeUv = new Cartesian2_default();
}
VoxelTraversal.prototype.findKeyframeNode = function(megatextureIndex) {
return this._keyframeNodesInMegatexture.find(function(keyframeNode) {
return keyframeNode.megatextureIndex === megatextureIndex;
});
};
function binaryTreeWeightingRecursive(arr, start, end, depth) {
if (start > end) {
return;
}
const mid = Math.floor((start + end) / 2);
arr[mid] = depth;
binaryTreeWeightingRecursive(arr, start, mid - 1, depth + 1);
binaryTreeWeightingRecursive(arr, mid + 1, end, depth + 1);
}
VoxelTraversal.simultaneousRequestCountMaximum = 50;
VoxelTraversal.prototype.update = function(frameState, keyframeLocation, recomputeBoundingVolumes, pauseUpdate) {
const primitive = this._primitive;
const context = frameState.context;
const maximumTileCount = this.megatextures[0].maximumTileCount;
const keyframeCount = this._keyframeCount;
const levelBlendFactor = primitive._levelBlendFactor;
const hasLevelBlendFactor = levelBlendFactor > 0;
const hasKeyframes = keyframeCount > 1;
const sampleCount = (hasLevelBlendFactor ? 2 : 1) * (hasKeyframes ? 2 : 1);
this._sampleCount = sampleCount;
const useLeafNodes = sampleCount >= 2;
if (useLeafNodes && !defined_default(this.leafNodeTexture)) {
const leafNodeTexelCount = 2;
const leafNodeTextureDimensionX = 1024;
const leafNodeTilesPerRow = Math.floor(
leafNodeTextureDimensionX / leafNodeTexelCount
);
const leafNodeTextureDimensionY = Math.ceil(
maximumTileCount / leafNodeTilesPerRow
);
this.leafNodeTexture = new Texture_default({
context,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
flipY: false,
width: leafNodeTextureDimensionX,
height: leafNodeTextureDimensionY,
sampler: new Sampler_default({
minificationFilter: TextureMinificationFilter_default.NEAREST,
magnificationFilter: TextureMagnificationFilter_default.NEAREST
})
});
this.leafNodeTexelSizeUv = Cartesian2_default.fromElements(
1 / leafNodeTextureDimensionX,
1 / leafNodeTextureDimensionY,
this.leafNodeTexelSizeUv
);
this.leafNodeTilesPerRow = leafNodeTilesPerRow;
} else if (!useLeafNodes && defined_default(this.leafNodeTexture)) {
this.leafNodeTexture = this.leafNodeTexture.destroy();
}
this._keyframeLocation = Math_default.clamp(
keyframeLocation,
0,
keyframeCount - 1
);
if (recomputeBoundingVolumes) {
recomputeBoundingVolumesRecursive(this, this.rootNode);
}
if (pauseUpdate) {
return;
}
this._frameNumber = frameState.frameNumber;
const timestamp0 = getTimestamp_default();
selectKeyframeNodes(this, frameState);
updateKeyframeNodes(this, frameState);
const timestamp1 = getTimestamp_default();
generateOctree(this, sampleCount, levelBlendFactor);
const timestamp2 = getTimestamp_default();
const checkEventListeners = primitive.loadProgress.numberOfListeners > 0 || primitive.allTilesLoaded.numberOfListeners > 0 || primitive.initialTilesLoaded.numberOfListeners > 0;
if (this._debugPrint || this._calculateStatistics || checkEventListeners) {
const loadAndUnloadTimeMs = timestamp1 - timestamp0;
const generateOctreeTimeMs = timestamp2 - timestamp1;
const totalTimeMs = timestamp2 - timestamp0;
postPassesUpdate(
this,
frameState,
loadAndUnloadTimeMs,
generateOctreeTimeMs,
totalTimeMs
);
}
};
VoxelTraversal.prototype.isRenderable = function(tile) {
return tile.isRenderable(this._frameNumber);
};
VoxelTraversal.prototype.isDestroyed = function() {
return false;
};
VoxelTraversal.prototype.destroy = function() {
const megatextures = this.megatextures;
const megatextureLength = megatextures.length;
for (let i = 0; i < megatextureLength; i++) {
megatextures[i] = megatextures[i] && megatextures[i].destroy();
}
this.textureMemoryByteLength = 0;
this.internalNodeTexture = this.internalNodeTexture && this.internalNodeTexture.destroy();
this.leafNodeTexture = this.leafNodeTexture && this.leafNodeTexture.destroy();
return destroyObject_default(this);
};
function recomputeBoundingVolumesRecursive(that, node) {
node.computeBoundingVolumes(that._primitive._shape);
if (defined_default(node.children)) {
for (let i = 0; i < 8; i++) {
const child = node.children[i];
recomputeBoundingVolumesRecursive(that, child);
}
}
}
function requestData(that, keyframeNode) {
if (that._simultaneousRequestCount >= VoxelTraversal.simultaneousRequestCountMaximum) {
return;
}
const primitive = that._primitive;
const provider = primitive.provider;
const { keyframe, spatialNode } = keyframeNode;
if (defined_default(provider.availableLevels) && spatialNode.level >= provider.availableLevels) {
return;
}
function postRequestSuccess(result) {
that._simultaneousRequestCount--;
keyframeNode.content = result;
keyframeNode.state = defined_default(result) ? KeyframeNode_default.LoadState.PROCESSING : KeyframeNode_default.LoadState.UNAVAILABLE;
}
function postRequestFailure(error) {
that._simultaneousRequestCount--;
keyframeNode.state = KeyframeNode_default.LoadState.FAILED;
that._primitive.tileFailed.raiseEvent();
}
const requestParameters = {
tileLevel: spatialNode.level,
tileX: spatialNode.x,
tileY: spatialNode.y,
tileZ: spatialNode.z,
keyframe
};
const promise = provider.requestData(requestParameters);
if (!defined_default(promise)) {
return;
}
that._simultaneousRequestCount++;
keyframeNode.state = KeyframeNode_default.LoadState.RECEIVING;
promise.then(postRequestSuccess).catch(postRequestFailure);
}
function mapInfiniteRangeToZeroOne(x) {
return x / (1 + x);
}
function selectKeyframeNodes(that, frameState) {
const frameNumber = that._frameNumber;
const priorityQueue = that._priorityQueue;
priorityQueue.reset();
addToQueueRecursive(
that.rootNode,
CullingVolume_default.MASK_INDETERMINATE,
that,
frameState
);
const highPriorityKeyframeNodes = that._highPriorityKeyframeNodes;
let highPriorityKeyframeNodeCount = 0;
let highPriorityKeyframeNode;
while (priorityQueue.length > 0) {
highPriorityKeyframeNode = priorityQueue.removeMaximum();
highPriorityKeyframeNode.highPriorityFrameNumber = frameNumber;
highPriorityKeyframeNodes[highPriorityKeyframeNodeCount] = highPriorityKeyframeNode;
highPriorityKeyframeNodeCount++;
}
that._highPriorityKeyframeNodeCount = highPriorityKeyframeNodeCount;
}
function updateKeyframeNodes(that, frameState) {
const megatexture = that.megatextures[0];
const keyframeNodesInMegatextureCount = megatexture.occupiedCount;
const keyframeNodesInMegatexture = that._keyframeNodesInMegatexture;
keyframeNodesInMegatexture.length = keyframeNodesInMegatextureCount;
keyframeNodesInMegatexture.sort(keyframeNodeSort);
const highPriorityKeyframeNodes = that._highPriorityKeyframeNodes;
const highPriorityKeyframeNodeCount = that._highPriorityKeyframeNodeCount;
let destroyedCount = 0;
let addedCount = 0;
for (let highPriorityKeyframeNodeIndex = 0; highPriorityKeyframeNodeIndex < highPriorityKeyframeNodeCount; highPriorityKeyframeNodeIndex++) {
const highPriorityKeyframeNode = highPriorityKeyframeNodes[highPriorityKeyframeNodeIndex];
if (highPriorityKeyframeNode.state === KeyframeNode_default.LoadState.LOADED || highPriorityKeyframeNode.spatialNode === void 0) {
continue;
}
if (highPriorityKeyframeNode.state === KeyframeNode_default.LoadState.UNLOADED) {
requestData(that, highPriorityKeyframeNode);
}
if (highPriorityKeyframeNode.state === KeyframeNode_default.LoadState.PROCESSING) {
const { content } = highPriorityKeyframeNode;
content.update(that._primitive, frameState);
if (!content.ready) {
continue;
}
if (!validateMetadata(content.metadata, that)) {
highPriorityKeyframeNode.content = void 0;
highPriorityKeyframeNode.state = KeyframeNode_default.LoadState.FAILED;
that._primitive.tileFailed.raiseEvent();
continue;
}
let addNodeIndex = 0;
if (megatexture.isFull()) {
addNodeIndex = keyframeNodesInMegatextureCount - 1 - destroyedCount;
destroyedCount++;
const discardNode = keyframeNodesInMegatexture[addNodeIndex];
that._primitive.tileUnload.raiseEvent();
discardNode.spatialNode.destroyKeyframeNode(
discardNode,
that.megatextures
);
} else {
addNodeIndex = keyframeNodesInMegatextureCount + addedCount;
addedCount++;
}
highPriorityKeyframeNode.spatialNode.addKeyframeNodeToMegatextures(
highPriorityKeyframeNode,
that.megatextures
);
highPriorityKeyframeNode.state = KeyframeNode_default.LoadState.LOADED;
keyframeNodesInMegatexture[addNodeIndex] = highPriorityKeyframeNode;
that._primitive.tileLoad.raiseEvent();
}
}
}
function keyframeNodeSort(a3, b) {
if (a3.highPriorityFrameNumber === b.highPriorityFrameNumber) {
return b.priority - a3.priority;
}
return b.highPriorityFrameNumber - a3.highPriorityFrameNumber;
}
function validateMetadata(metadata, traversal4) {
const length2 = traversal4._primitive.provider.types.length;
if (!Array.isArray(metadata) || metadata.length !== length2) {
return false;
}
const { megatextures } = traversal4;
for (let i = 0; i < length2; i++) {
const { voxelCountPerTile, channelCount } = megatextures[i];
const { x, y, z } = voxelCountPerTile;
const tileVoxelCount = x * y * z;
const data = metadata[i];
const expectedLength = tileVoxelCount * channelCount;
if (data.length !== expectedLength) {
return false;
}
}
return true;
}
function addToQueueRecursive(spatialNode, visibilityPlaneMask, that, frameState) {
const { camera, context, pixelRatio, frameNumber } = frameState;
const { positionWC: positionWC2, frustum } = camera;
const screenHeight = context.drawingBufferHeight / pixelRatio;
const screenSpaceErrorMultiplier = screenHeight / frustum.sseDenominator;
spatialNode.computeScreenSpaceError(positionWC2, screenSpaceErrorMultiplier);
visibilityPlaneMask = spatialNode.visibility(frameState, visibilityPlaneMask);
if (visibilityPlaneMask === CullingVolume_default.MASK_OUTSIDE) {
return;
}
spatialNode.visitedFrameNumber = frameNumber;
const primitive = that._primitive;
const shape = primitive._shape;
const targetScreenSpaceError = primitive.screenSpaceError;
const priorityQueue = that._priorityQueue;
const keyframeCount = that._keyframeCount;
const previousKeyframe = Math_default.clamp(
Math.floor(that._keyframeLocation),
0,
keyframeCount - 2
);
const nextKeyframe = previousKeyframe + 1;
if (keyframeCount === 1) {
spatialNode.createKeyframeNode(0);
} else if (spatialNode.keyframeNodes.length !== keyframeCount) {
for (let k = 0; k < keyframeCount; k++) {
spatialNode.createKeyframeNode(k);
}
}
const { screenSpaceError: screenSpaceError2, keyframeNodes } = spatialNode;
const ssePriority = mapInfiniteRangeToZeroOne(screenSpaceError2);
let hasLoadedKeyframe = false;
for (let i = 0; i < keyframeNodes.length; i++) {
const keyframeNode = keyframeNodes[i];
keyframeNode.priority = 10 * ssePriority + keyframePriority(
previousKeyframe,
keyframeNode.keyframe,
nextKeyframe,
that
);
if (keyframeNode.state !== KeyframeNode_default.LoadState.UNAVAILABLE && keyframeNode.state !== KeyframeNode_default.LoadState.FAILED && keyframeNode.priority !== -Number.MAX_VALUE) {
priorityQueue.insert(keyframeNode);
}
if (keyframeNode.state === KeyframeNode_default.LoadState.LOADED) {
hasLoadedKeyframe = true;
}
}
if (screenSpaceError2 < targetScreenSpaceError || !hasLoadedKeyframe) {
spatialNode.children = void 0;
return;
}
if (!defined_default(spatialNode.children)) {
spatialNode.constructChildNodes(shape);
}
for (let childIndex = 0; childIndex < 8; childIndex++) {
const child = spatialNode.children[childIndex];
addToQueueRecursive(child, visibilityPlaneMask, that, frameState);
}
}
function keyframePriority(previousKeyframe, keyframe, nextKeyframe, traversal4) {
const keyframeDifference = Math.min(
Math.abs(keyframe - previousKeyframe),
Math.abs(keyframe - nextKeyframe)
);
const maxKeyframeDifference = Math.max(
previousKeyframe,
traversal4._keyframeCount - nextKeyframe - 1,
1
);
const keyframeFactor = Math.pow(
1 - keyframeDifference / maxKeyframeDifference,
4
);
const binaryTreeFactor = Math.exp(
-traversal4._binaryTreeKeyframeWeighting[keyframe]
);
return Math_default.lerp(
binaryTreeFactor,
keyframeFactor,
0.15 + 0.85 * keyframeFactor
);
}
function postPassesUpdate(that, frameState, loadAndUnloadTimeMs, generateOctreeTimeMs, totalTimeMs) {
const keyframeCount = that._keyframeCount;
const rootNode = that.rootNode;
const loadStateCount = Object.keys(KeyframeNode_default.LoadState).length;
const loadStatesByKeyframe = new Array(loadStateCount);
const loadStateByCount = new Array(loadStateCount);
let nodeCountTotal = 0;
for (let loadStateIndex = 0; loadStateIndex < loadStateCount; loadStateIndex++) {
const keyframeArray = new Array(keyframeCount).fill(0);
loadStatesByKeyframe[loadStateIndex] = keyframeArray;
loadStateByCount[loadStateIndex] = 0;
}
function traverseRecursive(node) {
const keyframeNodes = node.keyframeNodes;
for (let keyframeIndex = 0; keyframeIndex < keyframeNodes.length; keyframeIndex++) {
const keyframeNode = keyframeNodes[keyframeIndex];
const keyframe = keyframeNode.keyframe;
const state = keyframeNode.state;
loadStatesByKeyframe[state][keyframe] += 1;
loadStateByCount[state] += 1;
nodeCountTotal++;
}
if (defined_default(node.children)) {
for (let childIndex = 0; childIndex < 8; childIndex++) {
const child = node.children[childIndex];
traverseRecursive(child);
}
}
}
traverseRecursive(rootNode);
that._primitive.statistics.numberOfTilesWithContentReady = loadStateByCount[KeyframeNode_default.LoadState.LOADED];
that._primitive.statistics.visited = nodeCountTotal;
const numberOfPendingRequests = loadStateByCount[KeyframeNode_default.LoadState.RECEIVING];
const numberOfTilesProcessing = loadStateByCount[KeyframeNode_default.LoadState.PROCESSING];
const progressChanged = numberOfPendingRequests !== that._primitive.statistics.numberOfPendingRequests || numberOfTilesProcessing !== that._primitive.statistics.numberOfTilesProcessing;
if (progressChanged) {
frameState.afterRender.push(function() {
that._primitive.loadProgress.raiseEvent(
numberOfPendingRequests,
numberOfTilesProcessing
);
return true;
});
}
that._primitive.statistics.numberOfPendingRequests = numberOfPendingRequests;
that._primitive.statistics.numberOfTilesProcessing = numberOfTilesProcessing;
const tilesLoaded = numberOfPendingRequests === 0 && numberOfTilesProcessing === 0;
if (progressChanged && tilesLoaded) {
frameState.afterRender.push(function() {
that._primitive.allTilesLoaded.raiseEvent();
return true;
});
if (!that._initialTilesLoaded) {
that._initialTilesLoaded = true;
frameState.afterRender.push(function() {
that._primitive.initialTilesLoaded.raiseEvent();
return true;
});
}
}
if (!that._debugPrint) {
return;
}
const loadedKeyframeStatistics = `KEYFRAMES: ${loadStatesByKeyframe[KeyframeNode_default.LoadState.LOADED]}`;
const loadStateStatistics = `UNLOADED: ${loadStateByCount[KeyframeNode_default.LoadState.UNLOADED]} | RECEIVING: ${loadStateByCount[KeyframeNode_default.LoadState.RECEIVING]} | PROCESSING: ${loadStateByCount[KeyframeNode_default.LoadState.PROCESSING]} | LOADED: ${loadStateByCount[KeyframeNode_default.LoadState.LOADED]} | FAILED: ${loadStateByCount[KeyframeNode_default.LoadState.FAILED]} | UNAVAILABLE: ${loadStateByCount[KeyframeNode_default.LoadState.UNAVAILABLE]} | TOTAL: ${nodeCountTotal}`;
const loadAndUnloadTimeMsRounded = Math.round(loadAndUnloadTimeMs * 100) / 100;
const generateOctreeTimeMsRounded = Math.round(generateOctreeTimeMs * 100) / 100;
const totalTimeMsRounded = Math.round(totalTimeMs * 100) / 100;
const timerStatistics = `LOAD: ${loadAndUnloadTimeMsRounded} | OCT: ${generateOctreeTimeMsRounded} | ALL: ${totalTimeMsRounded}`;
console.log(
`${loadedKeyframeStatistics} || ${loadStateStatistics} || ${timerStatistics}`
);
}
var GpuOctreeFlag = {
// Data is an octree index.
INTERNAL: 0,
// Data is a leaf node.
LEAF: 1,
// When leaf data is packed in the octree and there's a node that is forced to
// render but has no data of its own (such as when its siblings are renderable but it
// is not), signal that it's using its parent's data.
PACKED_LEAF_FROM_PARENT: 2
};
function generateOctree(that, sampleCount, levelBlendFactor) {
const targetSse = that._primitive._screenSpaceError;
const keyframeLocation = that._keyframeLocation;
const frameNumber = that._frameNumber;
const useLeafNodes = sampleCount >= 2;
let internalNodeCount = 0;
let leafNodeCount = 0;
const internalNodeOctreeData = [];
const leafNodeOctreeData = [];
function buildOctree(node, childOctreeIndex, childEntryIndex, parentOctreeIndex, parentEntryIndex) {
let hasRenderableChildren = false;
if (defined_default(node.children)) {
for (let c = 0; c < 8; c++) {
const childNode = node.children[c];
childNode.computeSurroundingRenderableKeyframeNodes(keyframeLocation);
if (childNode.isRenderable(frameNumber)) {
hasRenderableChildren = true;
}
}
}
if (hasRenderableChildren) {
internalNodeOctreeData[parentEntryIndex] = GpuOctreeFlag.INTERNAL << 16 | childOctreeIndex;
internalNodeOctreeData[childEntryIndex] = parentOctreeIndex;
internalNodeCount++;
parentOctreeIndex = childOctreeIndex;
parentEntryIndex = parentOctreeIndex * 9 + 1;
for (let cc = 0; cc < 8; cc++) {
const child = node.children[cc];
childOctreeIndex = internalNodeCount;
childEntryIndex = childOctreeIndex * 9 + 0;
buildOctree(
child,
childOctreeIndex,
childEntryIndex,
parentOctreeIndex,
parentEntryIndex + cc
);
}
} else {
that._primitive.tileVisible.raiseEvent();
if (useLeafNodes) {
const baseIdx = leafNodeCount * 5;
const keyframeNode = node.renderableKeyframeNodePrevious;
const levelDifference = node.level - keyframeNode.spatialNode.level;
const parentNode = keyframeNode.spatialNode.parent;
const parentKeyframeNode = defined_default(parentNode) ? parentNode.renderableKeyframeNodePrevious : keyframeNode;
const lodLerp = getLodLerp(node, targetSse, levelBlendFactor);
const levelDifferenceChild = levelDifference;
const levelDifferenceParent = 1;
const megatextureIndexChild = keyframeNode.megatextureIndex;
const megatextureIndexParent = parentKeyframeNode.megatextureIndex;
leafNodeOctreeData[baseIdx + 0] = lodLerp;
leafNodeOctreeData[baseIdx + 1] = levelDifferenceChild;
leafNodeOctreeData[baseIdx + 2] = levelDifferenceParent;
leafNodeOctreeData[baseIdx + 3] = megatextureIndexChild;
leafNodeOctreeData[baseIdx + 4] = megatextureIndexParent;
internalNodeOctreeData[parentEntryIndex] = GpuOctreeFlag.LEAF << 16 | leafNodeCount;
} else {
const keyframeNode = node.renderableKeyframeNodePrevious;
const levelDifference = node.level - keyframeNode.spatialNode.level;
const flag = levelDifference === 0 ? GpuOctreeFlag.LEAF : GpuOctreeFlag.PACKED_LEAF_FROM_PARENT;
internalNodeOctreeData[parentEntryIndex] = flag << 16 | keyframeNode.megatextureIndex;
}
leafNodeCount++;
}
}
const rootNode = that.rootNode;
rootNode.computeSurroundingRenderableKeyframeNodes(keyframeLocation);
if (rootNode.isRenderable(frameNumber)) {
buildOctree(rootNode, 0, 0, 0, 0);
}
copyToInternalNodeTexture(
internalNodeOctreeData,
9,
that.internalNodeTilesPerRow,
that.internalNodeTexture
);
if (useLeafNodes) {
copyToLeafNodeTexture(
leafNodeOctreeData,
2,
that.leafNodeTilesPerRow,
that.leafNodeTexture
);
}
}
function getLodLerp(node, targetSse, levelBlendFactor) {
if (node.parent === void 0) {
return 0;
}
const sse = node.screenSpaceError;
const parentSse = node.parent.screenSpaceError;
const lodLerp = (targetSse - sse) / (parentSse - sse);
const blended = (lodLerp + levelBlendFactor - 1) / levelBlendFactor;
return Math_default.clamp(blended, 0, 1);
}
function copyToInternalNodeTexture(data, texelsPerTile, tilesPerRow, texture) {
const channelCount = PixelFormat_default.componentsLength(texture.pixelFormat);
const tileCount = Math.ceil(data.length / texelsPerTile);
const copyWidth = Math.max(
1,
texelsPerTile * Math.min(tileCount, tilesPerRow)
);
const copyHeight = Math.max(1, Math.ceil(tileCount / tilesPerRow));
const textureData = new Uint8Array(copyWidth * copyHeight * channelCount);
for (let i = 0; i < data.length; i++) {
const val = data[i];
const startIndex = i * channelCount;
for (let j = 0; j < channelCount; j++) {
textureData[startIndex + j] = val >>> j * 8 & 255;
}
}
const source = {
arrayBufferView: textureData,
width: copyWidth,
height: copyHeight
};
const copyOptions = {
source,
xOffset: 0,
yOffset: 0
};
texture.copyFrom(copyOptions);
}
function copyToLeafNodeTexture(data, texelsPerTile, tilesPerRow, texture) {
const channelCount = PixelFormat_default.componentsLength(texture.pixelFormat);
const datasPerTile = 5;
const tileCount = Math.ceil(data.length / datasPerTile);
const copyWidth = Math.max(
1,
texelsPerTile * Math.min(tileCount, tilesPerRow)
);
const copyHeight = Math.max(1, Math.ceil(tileCount / tilesPerRow));
const textureData = new Uint8Array(copyWidth * copyHeight * channelCount);
for (let tileIndex = 0; tileIndex < tileCount; tileIndex++) {
const timeLerp = data[tileIndex * datasPerTile + 0];
const previousKeyframeLevelsAbove = data[tileIndex * datasPerTile + 1];
const nextKeyframeLevelsAbove = data[tileIndex * datasPerTile + 2];
const previousKeyframeMegatextureIndex = data[tileIndex * datasPerTile + 3];
const nextKeyframeMegatextureIndex = data[tileIndex * datasPerTile + 4];
const timeLerpCompressed = Math_default.clamp(
Math.floor(65536 * timeLerp),
0,
65535
);
textureData[tileIndex * 8 + 0] = timeLerpCompressed >>> 0 & 255;
textureData[tileIndex * 8 + 1] = timeLerpCompressed >>> 8 & 255;
textureData[tileIndex * 8 + 2] = previousKeyframeLevelsAbove & 255;
textureData[tileIndex * 8 + 3] = nextKeyframeLevelsAbove & 255;
textureData[tileIndex * 8 + 4] = previousKeyframeMegatextureIndex >>> 0 & 255;
textureData[tileIndex * 8 + 5] = previousKeyframeMegatextureIndex >>> 8 & 255;
textureData[tileIndex * 8 + 6] = nextKeyframeMegatextureIndex >>> 0 & 255;
textureData[tileIndex * 8 + 7] = nextKeyframeMegatextureIndex >>> 8 & 255;
}
const source = {
arrayBufferView: textureData,
width: copyWidth,
height: copyHeight
};
const copyOptions = {
source,
xOffset: 0,
yOffset: 0
};
texture.copyFrom(copyOptions);
}
function getApproximateTextureMemoryByteLength(tileCount, dimensions, types, componentTypes) {
let textureMemoryByteLength = 0;
const length2 = types.length;
for (let i = 0; i < length2; i++) {
const type = types[i];
const componentType = componentTypes[i];
const componentCount = MetadataType_default.getComponentCount(type);
textureMemoryByteLength += Megatexture_default2.getApproximateTextureMemoryByteLength(
tileCount,
dimensions,
componentCount,
componentType
);
}
return textureMemoryByteLength;
}
var VoxelTraversal_default = VoxelTraversal;
// packages/engine/Source/Scene/VoxelPrimitive.js
function VoxelPrimitive(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._ready = false;
this._provider = options.provider ?? VoxelPrimitive.DefaultProvider;
this._traversal = void 0;
this._statistics = new Cesium3DTilesetStatistics_default();
this._calculateStatistics = options.calculateStatistics ?? false;
this._shape = void 0;
this._shapeVisible = false;
this._dimensions = new Cartesian3_default();
this._inputDimensions = new Cartesian3_default();
this._paddingBefore = new Cartesian3_default();
this._paddingAfter = new Cartesian3_default();
this._minBounds = new Cartesian3_default();
this._minBoundsOld = new Cartesian3_default();
this._maxBounds = new Cartesian3_default();
this._maxBoundsOld = new Cartesian3_default();
this._exaggeratedMinBounds = new Cartesian3_default();
this._exaggeratedMinBoundsOld = new Cartesian3_default();
this._exaggeratedMaxBounds = new Cartesian3_default();
this._exaggeratedMaxBoundsOld = new Cartesian3_default();
this._minClippingBounds = new Cartesian3_default();
this._minClippingBoundsOld = new Cartesian3_default();
this._maxClippingBounds = new Cartesian3_default();
this._maxClippingBoundsOld = new Cartesian3_default();
this._clippingPlanes = void 0;
this._clippingPlanesState = 0;
this._clippingPlanesEnabled = false;
this._modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this._exaggeratedModelMatrix = Matrix4_default.clone(this._modelMatrix);
this._compoundModelMatrix = new Matrix4_default();
this._compoundModelMatrixOld = new Matrix4_default();
this._customShader = options.customShader ?? VoxelPrimitive.DefaultCustomShader;
this._customShaderCompilationEvent = new Event_default();
this._shaderDirty = true;
this._drawCommand = void 0;
this._drawCommandPick = void 0;
this._pickId = void 0;
this._clock = options.clock;
this._transformPositionWorldToUv = new Matrix4_default();
this._transformDirectionWorldToUv = new Matrix3_default();
this._transformPositionUvToWorld = new Matrix4_default();
this._transformDirectionWorldToLocal = new Matrix3_default();
this._nearestSampling = false;
this._levelBlendFactor = 0;
this._stepSizeMultiplier = 1;
this._depthTest = true;
this._useLogDepth = void 0;
this._screenSpaceError = 4;
this._debugPolylines = new PolylineCollection_default();
this._debugDraw = false;
this._disableRender = false;
this._disableUpdate = false;
this._uniforms = {
octreeInternalNodeTexture: void 0,
octreeInternalNodeTilesPerRow: 0,
octreeInternalNodeTexelSizeUv: new Cartesian2_default(),
octreeLeafNodeTexture: void 0,
octreeLeafNodeTilesPerRow: 0,
octreeLeafNodeTexelSizeUv: new Cartesian2_default(),
megatextureTextures: [],
megatextureSliceDimensions: new Cartesian2_default(),
megatextureTileDimensions: new Cartesian2_default(),
megatextureVoxelSizeUv: new Cartesian2_default(),
megatextureSliceSizeUv: new Cartesian2_default(),
megatextureTileSizeUv: new Cartesian2_default(),
dimensions: new Cartesian3_default(),
inputDimensions: new Cartesian3_default(),
paddingBefore: new Cartesian3_default(),
paddingAfter: new Cartesian3_default(),
transformPositionViewToUv: new Matrix4_default(),
transformPositionUvToView: new Matrix4_default(),
transformDirectionViewToLocal: new Matrix3_default(),
cameraPositionUv: new Cartesian3_default(),
cameraDirectionUv: new Cartesian3_default(),
ndcSpaceAxisAlignedBoundingBox: new Cartesian4_default(),
clippingPlanesTexture: void 0,
clippingPlanesMatrix: new Matrix4_default(),
stepSize: 0,
pickColor: new Color_default()
};
this._shapeDefinesOld = {};
this._uniformMap = {};
const uniforms = this._uniforms;
const uniformMap2 = this._uniformMap;
for (const key in uniforms) {
if (uniforms.hasOwnProperty(key)) {
const name = `u_${key}`;
uniformMap2[name] = function() {
return uniforms[key];
};
}
}
this.tileLoad = new Event_default();
this.tileVisible = new Event_default();
this.tileFailed = new Event_default();
this.tileUnload = new Event_default();
this.loadProgress = new Event_default();
this.allTilesLoaded = new Event_default();
this.initialTilesLoaded = new Event_default();
const provider = this._provider;
initialize17(this, provider);
}
function initialize17(primitive, provider) {
const {
shape: shapeType,
minBounds = VoxelShapeType_default.getMinBounds(shapeType),
maxBounds = VoxelShapeType_default.getMaxBounds(shapeType)
} = provider;
primitive.minBounds = minBounds;
primitive.maxBounds = maxBounds;
primitive.minClippingBounds = minBounds.clone();
primitive.maxClippingBounds = maxBounds.clone();
primitive._exaggeratedMinBounds = Cartesian3_default.clone(
primitive._minBounds,
primitive._exaggeratedMinBounds
);
primitive._exaggeratedMaxBounds = Cartesian3_default.clone(
primitive._maxBounds,
primitive._exaggeratedMaxBounds
);
primitive._exaggeratedModelMatrix = Matrix4_default.clone(
primitive._modelMatrix,
primitive._exaggeratedModelMatrix
);
checkTransformAndBounds(primitive, provider);
const ShapeConstructor = VoxelShapeType_default.getShapeConstructor(shapeType);
primitive._shape = new ShapeConstructor();
primitive._shapeVisible = updateShapeAndTransforms(
primitive,
primitive._shape,
provider
);
}
Object.defineProperties(VoxelPrimitive.prototype, {
/**
* Gets a value indicating whether or not the primitive is ready for use.
*
* @memberof VoxelPrimitive.prototype
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
},
/**
* Gets the {@link VoxelProvider} associated with this primitive.
*
* @memberof VoxelPrimitive.prototype
* @type {VoxelProvider}
* @readonly
*/
provider: {
get: function() {
return this._provider;
}
},
/**
* Gets the bounding sphere.
*
* @memberof VoxelPrimitive.prototype
* @type {BoundingSphere}
* @readonly
*/
boundingSphere: {
get: function() {
return this._shape.boundingSphere;
}
},
/**
* Gets the oriented bounding box.
*
* @memberof VoxelPrimitive.prototype
* @type {OrientedBoundingBox}
* @readonly
*/
orientedBoundingBox: {
get: function() {
return this._shape.orientedBoundingBox;
}
},
/**
* Gets the model matrix.
*
* @memberof VoxelPrimitive.prototype
* @type {Matrix4}
* @readonly
*/
modelMatrix: {
get: function() {
return this._modelMatrix;
},
set: function(modelMatrix) {
Check_default.typeOf.object("modelMatrix", modelMatrix);
this._modelMatrix = Matrix4_default.clone(modelMatrix, this._modelMatrix);
}
},
/**
* Gets the shape type.
*
* @memberof VoxelPrimitive.prototype
* @type {VoxelShapeType}
* @readonly
*/
shape: {
get: function() {
return this._provider.shape;
}
},
/**
* Gets the dimensions of each voxel tile, in z-up orientation.
* Does not include padding.
*
* @memberof VoxelPrimitive.prototype
* @type {Cartesian3}
* @readonly
*/
dimensions: {
get: function() {
return this._dimensions;
}
},
/**
* Gets the dimensions of one tile of the input voxel data, in the input orientation.
* Includes padding.
* @memberof VoxelPrimitive.prototype
* @type {Cartesian3}
* @readonly
*/
inputDimensions: {
get: function() {
return this._inputDimensions;
}
},
/**
* Gets the padding before the voxel data.
*
* @memberof VoxelPrimitive.prototype
* @type {Cartesian3}
* @readonly
*/
paddingBefore: {
get: function() {
return this._paddingBefore;
}
},
/**
* Gets the padding after the voxel data.
*
* @memberof VoxelPrimitive.prototype
* @type {Cartesian3}
* @readonly
*/
paddingAfter: {
get: function() {
return this._paddingAfter;
}
},
/**
* Gets the minimum value per channel of the voxel data.
*
* @memberof VoxelPrimitive.prototype
* @type {number[][]}
* @readonly
*/
minimumValues: {
get: function() {
return this._provider.minimumValues;
}
},
/**
* Gets the maximum value per channel of the voxel data.
*
* @memberof VoxelPrimitive.prototype
* @type {number[][]}
* @readonly
*/
maximumValues: {
get: function() {
return this._provider.maximumValues;
}
},
/**
* Gets or sets whether or not this primitive should be displayed.
*
* @memberof VoxelPrimitive.prototype
* @type {boolean}
*/
show: {
get: function() {
return !this._disableRender;
},
set: function(show) {
Check_default.typeOf.bool("show", show);
this._disableRender = !show;
}
},
/**
* Gets or sets whether or not the primitive should update when the view changes.
*
* @memberof VoxelPrimitive.prototype
* @type {boolean}
*/
disableUpdate: {
get: function() {
return this._disableUpdate;
},
set: function(disableUpdate) {
Check_default.typeOf.bool("disableUpdate", disableUpdate);
this._disableUpdate = disableUpdate;
}
},
/**
* Gets or sets whether or not to render debug visualizations.
*
* @memberof VoxelPrimitive.prototype
* @type {boolean}
*/
debugDraw: {
get: function() {
return this._debugDraw;
},
set: function(debugDraw2) {
Check_default.typeOf.bool("debugDraw", debugDraw2);
this._debugDraw = debugDraw2;
}
},
/**
* Gets or sets whether or not to test against depth when rendering.
*
* @memberof VoxelPrimitive.prototype
* @type {boolean}
*/
depthTest: {
get: function() {
return this._depthTest;
},
set: function(depthTest) {
Check_default.typeOf.bool("depthTest", depthTest);
if (this._depthTest !== depthTest) {
this._depthTest = depthTest;
this._shaderDirty = true;
}
}
},
/**
* Gets or sets the nearest sampling.
*
* @memberof VoxelPrimitive.prototype
* @type {boolean}
*/
nearestSampling: {
get: function() {
return this._nearestSampling;
},
set: function(nearestSampling) {
Check_default.typeOf.bool("nearestSampling", nearestSampling);
if (this._nearestSampling !== nearestSampling) {
this._nearestSampling = nearestSampling;
this._shaderDirty = true;
}
}
},
/**
* Controls how quickly to blend between different levels of the tree.
* 0.0 means an instantaneous pop.
* 1.0 means a full linear blend.
*
* @memberof VoxelPrimitive.prototype
* @type {number}
* @private
*/
levelBlendFactor: {
get: function() {
return this._levelBlendFactor;
},
set: function(levelBlendFactor) {
Check_default.typeOf.number("levelBlendFactor", levelBlendFactor);
this._levelBlendFactor = Math_default.clamp(levelBlendFactor, 0, 1);
}
},
/**
* Gets or sets the screen space error in pixels. If the screen space size
* of a voxel is greater than the screen space error, the tile is subdivided.
* Lower screen space error corresponds with higher detail rendering, but could
* result in worse performance and higher memory consumption.
*
* @memberof VoxelPrimitive.prototype
* @type {number}
*/
screenSpaceError: {
get: function() {
return this._screenSpaceError;
},
set: function(screenSpaceError2) {
Check_default.typeOf.number("screenSpaceError", screenSpaceError2);
this._screenSpaceError = screenSpaceError2;
}
},
/**
* Gets or sets the step size multiplier used during raymarching.
* The lower the value, the higher the rendering quality, but
* also the worse the performance.
*
* @memberof VoxelPrimitive.prototype
* @type {number}
*/
stepSize: {
get: function() {
return this._stepSizeMultiplier;
},
set: function(stepSize) {
Check_default.typeOf.number("stepSize", stepSize);
this._stepSizeMultiplier = stepSize;
}
},
/**
* Gets or sets the minimum bounds in the shape's local coordinate system.
* Voxel data is stretched or squashed to fit the bounds.
*
* @memberof VoxelPrimitive.prototype
* @type {Cartesian3}
*/
minBounds: {
get: function() {
return this._minBounds;
},
set: function(minBounds) {
Check_default.defined("minBounds", minBounds);
this._minBounds = Cartesian3_default.clone(minBounds, this._minBounds);
}
},
/**
* Gets or sets the maximum bounds in the shape's local coordinate system.
* Voxel data is stretched or squashed to fit the bounds.
*
* @memberof VoxelPrimitive.prototype
* @type {Cartesian3}
*/
maxBounds: {
get: function() {
return this._maxBounds;
},
set: function(maxBounds) {
Check_default.defined("maxBounds", maxBounds);
this._maxBounds = Cartesian3_default.clone(maxBounds, this._maxBounds);
}
},
/**
* Gets or sets the minimum clipping location in the shape's local coordinate system.
* Any voxel content outside the range is clipped.
*
* @memberof VoxelPrimitive.prototype
* @type {Cartesian3}
*/
minClippingBounds: {
get: function() {
return this._minClippingBounds;
},
set: function(minClippingBounds) {
Check_default.defined("minClippingBounds", minClippingBounds);
this._minClippingBounds = Cartesian3_default.clone(
minClippingBounds,
this._minClippingBounds
);
}
},
/**
* Gets or sets the maximum clipping location in the shape's local coordinate system.
* Any voxel content outside the range is clipped.
*
* @memberof VoxelPrimitive.prototype
* @type {Cartesian3}
*/
maxClippingBounds: {
get: function() {
return this._maxClippingBounds;
},
set: function(maxClippingBounds) {
Check_default.defined("maxClippingBounds", maxClippingBounds);
this._maxClippingBounds = Cartesian3_default.clone(
maxClippingBounds,
this._maxClippingBounds
);
}
},
/**
* The {@link ClippingPlaneCollection} used to selectively disable rendering the primitive.
*
* @memberof VoxelPrimitive.prototype
* @type {ClippingPlaneCollection}
*/
clippingPlanes: {
get: function() {
return this._clippingPlanes;
},
set: function(clippingPlanes) {
ClippingPlaneCollection_default.setOwner(clippingPlanes, this, "_clippingPlanes");
}
},
/**
* Gets or sets the custom shader. If undefined, {@link VoxelPrimitive.DefaultCustomShader} is set.
*
* @memberof VoxelPrimitive.prototype
* @type {CustomShader}
* @see {@link https://github.com/CesiumGS/cesium/tree/main/Documentation/CustomShaderGuide|Custom Shader Guide}
*/
customShader: {
get: function() {
return this._customShader;
},
set: function(customShader) {
if (this._customShader !== customShader) {
const uniformMap2 = this._uniformMap;
const oldCustomShader = this._customShader;
const oldCustomShaderUniformMap = oldCustomShader.uniformMap;
for (const uniformName in oldCustomShaderUniformMap) {
if (oldCustomShaderUniformMap.hasOwnProperty(uniformName)) {
delete uniformMap2[uniformName];
}
}
if (!defined_default(customShader)) {
this._customShader = VoxelPrimitive.DefaultCustomShader;
} else {
this._customShader = customShader;
}
this._shaderDirty = true;
}
}
},
/**
* Gets an event that is raised whenever a custom shader is compiled.
*
* @memberof VoxelPrimitive.prototype
* @type {Event}
* @readonly
*/
customShaderCompilationEvent: {
get: function() {
return this._customShaderCompilationEvent;
}
},
/**
* Loading and rendering information for requested content
* To use `visited` and `numberOfTilesWithContentReady` statistics, set options._calculateStatistics` to `true` in the constructor.
* @type {Cesium3DTilesetStatistics}
* @readonly
* @private
*/
statistics: {
get: function() {
return this._statistics;
}
}
});
var scratchIntersect = new Cartesian4_default();
var scratchNdcAabb = new Cartesian4_default();
var scratchTransformPositionWorldToLocal = new Matrix4_default();
var scratchTransformPositionLocalToWorld = new Matrix4_default();
var scratchTransformPositionLocalToProjection = new Matrix4_default();
var transformPositionLocalToUv = Matrix4_default.fromRotationTranslation(
Matrix3_default.fromUniformScale(0.5, new Matrix3_default()),
new Cartesian3_default(0.5, 0.5, 0.5),
new Matrix4_default()
);
var transformPositionUvToLocal = Matrix4_default.fromRotationTranslation(
Matrix3_default.fromUniformScale(2, new Matrix3_default()),
new Cartesian3_default(-1, -1, -1),
new Matrix4_default()
);
VoxelPrimitive.prototype.update = function(frameState) {
const provider = this._provider;
this._customShader.update(frameState);
const context = frameState.context;
if (!this._ready) {
initFromProvider(this, provider, context);
frameState.afterRender.push(() => {
this._ready = true;
return true;
});
return;
}
updateVerticalExaggeration2(this, frameState);
const shapeDirty = checkTransformAndBounds(this, provider);
const shape = this._shape;
if (shapeDirty) {
this._shapeVisible = updateShapeAndTransforms(this, shape, provider);
if (checkShapeDefines(this, shape)) {
this._shaderDirty = true;
}
}
if (!this._shapeVisible) {
return;
}
const keyframeLocation = getKeyframeLocation(
provider.timeIntervalCollection,
this._clock
);
const traversal4 = this._traversal;
const sampleCountOld = traversal4._sampleCount;
traversal4.update(
frameState,
keyframeLocation,
shapeDirty,
// recomputeBoundingVolumes
this._disableUpdate
// pauseUpdate
);
if (sampleCountOld !== traversal4._sampleCount) {
this._shaderDirty = true;
}
if (!traversal4.isRenderable(traversal4.rootNode)) {
return;
}
if (this._debugDraw) {
debugDraw(this, frameState);
}
if (this._disableRender) {
return;
}
if (this._useLogDepth !== frameState.useLogDepth) {
this._useLogDepth = frameState.useLogDepth;
this._shaderDirty = true;
}
const clippingPlanesChanged = updateClippingPlanes3(this, frameState);
if (clippingPlanesChanged) {
this._shaderDirty = true;
}
const leafNodeTexture = traversal4.leafNodeTexture;
const uniforms = this._uniforms;
if (defined_default(leafNodeTexture)) {
uniforms.octreeLeafNodeTexture = traversal4.leafNodeTexture;
uniforms.octreeLeafNodeTexelSizeUv = Cartesian2_default.clone(
traversal4.leafNodeTexelSizeUv,
uniforms.octreeLeafNodeTexelSizeUv
);
uniforms.octreeLeafNodeTilesPerRow = traversal4.leafNodeTilesPerRow;
}
if (this._shaderDirty) {
buildVoxelDrawCommands_default(this, context);
this._shaderDirty = false;
}
const transformPositionWorldToProjection = context.uniformState.viewProjection;
const orientedBoundingBox = shape.orientedBoundingBox;
const ndcAabb = orientedBoundingBoxToNdcAabb(
orientedBoundingBox,
transformPositionWorldToProjection,
scratchNdcAabb
);
const offscreen = ndcAabb.x === 1 || ndcAabb.y === 1 || ndcAabb.z === -1 || ndcAabb.w === -1;
if (offscreen) {
return;
}
uniforms.ndcSpaceAxisAlignedBoundingBox = Cartesian4_default.clone(
ndcAabb,
uniforms.ndcSpaceAxisAlignedBoundingBox
);
const transformPositionViewToWorld = context.uniformState.inverseView;
uniforms.transformPositionViewToUv = Matrix4_default.multiplyTransformation(
this._transformPositionWorldToUv,
transformPositionViewToWorld,
uniforms.transformPositionViewToUv
);
const transformPositionWorldToView = context.uniformState.view;
uniforms.transformPositionUvToView = Matrix4_default.multiplyTransformation(
transformPositionWorldToView,
this._transformPositionUvToWorld,
uniforms.transformPositionUvToView
);
const transformDirectionViewToWorld = context.uniformState.inverseViewRotation;
uniforms.transformDirectionViewToLocal = Matrix3_default.multiply(
this._transformDirectionWorldToLocal,
transformDirectionViewToWorld,
uniforms.transformDirectionViewToLocal
);
uniforms.cameraPositionUv = Matrix4_default.multiplyByPoint(
this._transformPositionWorldToUv,
frameState.camera.positionWC,
uniforms.cameraPositionUv
);
uniforms.cameraDirectionUv = Matrix3_default.multiplyByVector(
this._transformDirectionWorldToUv,
frameState.camera.directionWC,
uniforms.cameraDirectionUv
);
uniforms.cameraDirectionUv = Cartesian3_default.normalize(
uniforms.cameraDirectionUv,
uniforms.cameraDirectionUv
);
uniforms.stepSize = this._stepSizeMultiplier;
const command = frameState.passes.pick ? this._drawCommandPick : frameState.passes.pickVoxel ? this._drawCommandPickVoxel : this._drawCommand;
command.boundingVolume = shape.boundingSphere;
frameState.commandList.push(command);
};
var scratchExaggerationScale = new Cartesian3_default();
var scratchExaggerationCenter = new Cartesian3_default();
var scratchCartographicCenter = new Cartographic_default();
var scratchExaggerationTranslation = new Cartesian3_default();
function updateVerticalExaggeration2(primitive, frameState) {
primitive._exaggeratedMinBounds = Cartesian3_default.clone(
primitive._minBounds,
primitive._exaggeratedMinBounds
);
primitive._exaggeratedMaxBounds = Cartesian3_default.clone(
primitive._maxBounds,
primitive._exaggeratedMaxBounds
);
if (primitive.shape === VoxelShapeType_default.ELLIPSOID) {
const relativeHeight = frameState.verticalExaggerationRelativeHeight;
const exaggeration = frameState.verticalExaggeration;
primitive._exaggeratedMinBounds.z = (primitive._minBounds.z - relativeHeight) * exaggeration + relativeHeight;
primitive._exaggeratedMaxBounds.z = (primitive._maxBounds.z - relativeHeight) * exaggeration + relativeHeight;
} else {
const exaggerationScale = Cartesian3_default.fromElements(
1,
1,
frameState.verticalExaggeration,
scratchExaggerationScale
);
primitive._exaggeratedModelMatrix = Matrix4_default.multiplyByScale(
primitive._modelMatrix,
exaggerationScale,
primitive._exaggeratedModelMatrix
);
primitive._exaggeratedModelMatrix = Matrix4_default.multiplyByTranslation(
primitive._exaggeratedModelMatrix,
computeBoxExaggerationTranslation(primitive, frameState),
primitive._exaggeratedModelMatrix
);
}
}
function computeBoxExaggerationTranslation(primitive, frameState) {
const {
shapeTransform = Matrix4_default.IDENTITY,
globalTransform = Matrix4_default.IDENTITY
} = primitive._provider;
const initialCenter = Matrix4_default.getTranslation(
shapeTransform,
scratchExaggerationCenter
);
const intermediateCenter = Matrix4_default.multiplyByPoint(
primitive._modelMatrix,
initialCenter,
scratchExaggerationCenter
);
const transformedCenter = Matrix4_default.multiplyByPoint(
globalTransform,
intermediateCenter,
scratchExaggerationCenter
);
const ellipsoid = Ellipsoid_default.WGS84;
const centerCartographic = ellipsoid.cartesianToCartographic(
transformedCenter,
scratchCartographicCenter
);
let centerHeight = 0;
if (defined_default(centerCartographic)) {
centerHeight = centerCartographic.height;
}
const exaggeratedHeight = VerticalExaggeration_default.getHeight(
centerHeight,
frameState.verticalExaggeration,
frameState.verticalExaggerationRelativeHeight
);
return Cartesian3_default.fromElements(
0,
0,
(exaggeratedHeight - centerHeight) / frameState.verticalExaggeration,
scratchExaggerationTranslation
);
}
function initFromProvider(primitive, provider, context) {
const uniforms = primitive._uniforms;
primitive._pickId = context.createPickId({ primitive });
uniforms.pickColor = Color_default.clone(primitive._pickId.color, uniforms.pickColor);
const { shaderDefines, shaderUniforms: shapeUniforms } = primitive._shape;
primitive._shapeDefinesOld = clone_default(shaderDefines, true);
const uniformMap2 = primitive._uniformMap;
for (const key in shapeUniforms) {
if (shapeUniforms.hasOwnProperty(key)) {
const name = `u_${key}`;
if (defined_default(uniformMap2[name])) {
oneTimeWarning_default(
`VoxelPrimitive: Uniform name "${name}" is already defined`
);
}
uniformMap2[name] = function() {
return shapeUniforms[key];
};
}
}
primitive._dimensions = Cartesian3_default.clone(
provider.dimensions,
primitive._dimensions
);
uniforms.dimensions = Cartesian3_default.clone(
primitive._dimensions,
uniforms.dimensions
);
primitive._paddingBefore = Cartesian3_default.clone(
provider.paddingBefore ?? Cartesian3_default.ZERO,
primitive._paddingBefore
);
uniforms.paddingBefore = Cartesian3_default.clone(
primitive._paddingBefore,
uniforms.paddingBefore
);
primitive._paddingAfter = Cartesian3_default.clone(
provider.paddingAfter ?? Cartesian3_default.ZERO,
primitive._paddingAfter
);
uniforms.paddingAfter = Cartesian3_default.clone(
primitive._paddingAfter,
uniforms.paddingAfter
);
primitive._inputDimensions = Cartesian3_default.add(
primitive._dimensions,
primitive._paddingBefore,
primitive._inputDimensions
);
primitive._inputDimensions = Cartesian3_default.add(
primitive._inputDimensions,
primitive._paddingAfter,
primitive._inputDimensions
);
if (provider.metadataOrder === VoxelMetadataOrder_default.Y_UP) {
const inputDimensionsY = primitive._inputDimensions.y;
primitive._inputDimensions.y = primitive._inputDimensions.z;
primitive._inputDimensions.z = inputDimensionsY;
}
uniforms.inputDimensions = Cartesian3_default.clone(
primitive._inputDimensions,
uniforms.inputDimensions
);
const keyframeCount = provider.keyframeCount ?? 1;
primitive._traversal = new VoxelTraversal_default(primitive, context, keyframeCount);
primitive.statistics.texturesByteLength = primitive._traversal.textureMemoryByteLength;
setTraversalUniforms(primitive._traversal, uniforms);
}
function checkTransformAndBounds(primitive, provider) {
const shapeTransform = provider.shapeTransform ?? Matrix4_default.IDENTITY;
const globalTransform = provider.globalTransform ?? Matrix4_default.IDENTITY;
Matrix4_default.multiplyTransformation(
globalTransform,
primitive._exaggeratedModelMatrix,
primitive._compoundModelMatrix
);
Matrix4_default.multiplyTransformation(
primitive._compoundModelMatrix,
shapeTransform,
primitive._compoundModelMatrix
);
const numChanges = updateBound(primitive, "_compoundModelMatrix", "_compoundModelMatrixOld") + updateBound(primitive, "_minBounds", "_minBoundsOld") + updateBound(primitive, "_maxBounds", "_maxBoundsOld") + updateBound(
primitive,
"_exaggeratedMinBounds",
"_exaggeratedMinBoundsOld"
) + updateBound(
primitive,
"_exaggeratedMaxBounds",
"_exaggeratedMaxBoundsOld"
) + updateBound(primitive, "_minClippingBounds", "_minClippingBoundsOld") + updateBound(primitive, "_maxClippingBounds", "_maxClippingBoundsOld");
return numChanges > 0;
}
function updateBound(primitive, newBoundKey, oldBoundKey) {
const newBound = primitive[newBoundKey];
const oldBound = primitive[oldBoundKey];
const changed = !newBound.equals(oldBound);
if (changed) {
newBound.clone(oldBound);
}
return changed ? 1 : 0;
}
function updateShapeAndTransforms(primitive, shape, provider) {
const visible = shape.update(
primitive._compoundModelMatrix,
primitive._exaggeratedMinBounds,
primitive._exaggeratedMaxBounds,
primitive.minClippingBounds,
primitive.maxClippingBounds
);
if (!visible) {
return false;
}
const transformPositionLocalToWorld = shape.shapeTransform;
const transformPositionWorldToLocal = Matrix4_default.inverse(
transformPositionLocalToWorld,
scratchTransformPositionWorldToLocal
);
primitive._transformPositionWorldToUv = Matrix4_default.multiplyTransformation(
transformPositionLocalToUv,
transformPositionWorldToLocal,
primitive._transformPositionWorldToUv
);
primitive._transformDirectionWorldToUv = Matrix4_default.getMatrix3(
primitive._transformPositionWorldToUv,
primitive._transformDirectionWorldToUv
);
primitive._transformPositionUvToWorld = Matrix4_default.multiplyTransformation(
transformPositionLocalToWorld,
transformPositionUvToLocal,
primitive._transformPositionUvToWorld
);
primitive._transformDirectionWorldToLocal = Matrix4_default.getMatrix3(
transformPositionWorldToLocal,
primitive._transformDirectionWorldToLocal
);
return true;
}
function setTraversalUniforms(traversal4, uniforms) {
uniforms.octreeInternalNodeTexture = traversal4.internalNodeTexture;
uniforms.octreeInternalNodeTexelSizeUv = Cartesian2_default.clone(
traversal4.internalNodeTexelSizeUv,
uniforms.octreeInternalNodeTexelSizeUv
);
uniforms.octreeInternalNodeTilesPerRow = traversal4.internalNodeTilesPerRow;
const megatextures = traversal4.megatextures;
const megatexture = megatextures[0];
const megatextureLength = megatextures.length;
uniforms.megatextureTextures = new Array(megatextureLength);
for (let i = 0; i < megatextureLength; i++) {
uniforms.megatextureTextures[i] = megatextures[i].texture;
}
uniforms.megatextureSliceDimensions = Cartesian2_default.clone(
megatexture.sliceCountPerRegion,
uniforms.megatextureSliceDimensions
);
uniforms.megatextureTileDimensions = Cartesian2_default.clone(
megatexture.regionCountPerMegatexture,
uniforms.megatextureTileDimensions
);
uniforms.megatextureVoxelSizeUv = Cartesian2_default.clone(
megatexture.voxelSizeUv,
uniforms.megatextureVoxelSizeUv
);
uniforms.megatextureSliceSizeUv = Cartesian2_default.clone(
megatexture.sliceSizeUv,
uniforms.megatextureSliceSizeUv
);
uniforms.megatextureTileSizeUv = Cartesian2_default.clone(
megatexture.regionSizeUv,
uniforms.megatextureTileSizeUv
);
}
function checkShapeDefines(primitive, shape) {
const shapeDefines = shape.shaderDefines;
const shapeDefinesChanged = Object.keys(shapeDefines).some(
(key) => shapeDefines[key] !== primitive._shapeDefinesOld[key]
);
if (shapeDefinesChanged) {
primitive._shapeDefinesOld = clone_default(shapeDefines, true);
}
return shapeDefinesChanged;
}
function getKeyframeLocation(timeIntervalCollection, clock) {
if (!defined_default(timeIntervalCollection) || !defined_default(clock)) {
return 0;
}
let date = clock.currentTime;
let timeInterval;
let timeIntervalIndex = timeIntervalCollection.indexOf(date);
if (timeIntervalIndex >= 0) {
timeInterval = timeIntervalCollection.get(timeIntervalIndex);
} else {
timeIntervalIndex = ~timeIntervalIndex;
if (timeIntervalIndex === timeIntervalCollection.length) {
timeIntervalIndex = timeIntervalCollection.length - 1;
timeInterval = timeIntervalCollection.get(timeIntervalIndex);
date = timeInterval.stop;
} else {
timeInterval = timeIntervalCollection.get(timeIntervalIndex);
date = timeInterval.start;
}
}
const totalSeconds = JulianDate_default.secondsDifference(
timeInterval.stop,
timeInterval.start
);
const secondsDifferenceStart = JulianDate_default.secondsDifference(
date,
timeInterval.start
);
const t = secondsDifferenceStart / totalSeconds;
return timeIntervalIndex + t;
}
function updateClippingPlanes3(primitive, frameState) {
const clippingPlanes = primitive.clippingPlanes;
if (!defined_default(clippingPlanes)) {
return false;
}
clippingPlanes.update(frameState);
const { clippingPlanesState, enabled } = clippingPlanes;
if (enabled) {
const uniforms = primitive._uniforms;
uniforms.clippingPlanesTexture = clippingPlanes.texture;
uniforms.clippingPlanesMatrix = Matrix4_default.transpose(
Matrix4_default.multiplyTransformation(
Matrix4_default.inverse(
clippingPlanes.modelMatrix,
uniforms.clippingPlanesMatrix
),
primitive._transformPositionUvToWorld,
uniforms.clippingPlanesMatrix
),
uniforms.clippingPlanesMatrix
);
}
if (primitive._clippingPlanesState === clippingPlanesState && primitive._clippingPlanesEnabled === enabled) {
return false;
}
primitive._clippingPlanesState = clippingPlanesState;
primitive._clippingPlanesEnabled = enabled;
return true;
}
VoxelPrimitive.prototype.isDestroyed = function() {
return false;
};
VoxelPrimitive.prototype.destroy = function() {
const drawCommand = this._drawCommand;
if (defined_default(drawCommand)) {
drawCommand.shaderProgram = drawCommand.shaderProgram && drawCommand.shaderProgram.destroy();
}
const drawCommandPick = this._drawCommandPick;
if (defined_default(drawCommandPick)) {
drawCommandPick.shaderProgram = drawCommandPick.shaderProgram && drawCommandPick.shaderProgram.destroy();
}
this._pickId = this._pickId && this._pickId.destroy();
this._traversal = this._traversal && this._traversal.destroy();
this.statistics.texturesByteLength = 0;
this._clippingPlanes = this._clippingPlanes && this._clippingPlanes.destroy();
return destroyObject_default(this);
};
var corners = new Array(
new Cartesian4_default(-1, -1, -1, 1),
new Cartesian4_default(1, -1, -1, 1),
new Cartesian4_default(-1, 1, -1, 1),
new Cartesian4_default(1, 1, -1, 1),
new Cartesian4_default(-1, -1, 1, 1),
new Cartesian4_default(1, -1, 1, 1),
new Cartesian4_default(-1, 1, 1, 1),
new Cartesian4_default(1, 1, 1, 1)
);
var vertexNeighborIndices = new Array(
1,
2,
4,
0,
3,
5,
0,
3,
6,
1,
2,
7,
0,
5,
6,
1,
4,
7,
2,
4,
7,
3,
5,
6
);
var scratchCornersClipSpace = new Array(
new Cartesian4_default(),
new Cartesian4_default(),
new Cartesian4_default(),
new Cartesian4_default(),
new Cartesian4_default(),
new Cartesian4_default(),
new Cartesian4_default(),
new Cartesian4_default()
);
function orientedBoundingBoxToNdcAabb(orientedBoundingBox, worldToProjection, result) {
const transformPositionLocalToWorld = Matrix4_default.fromRotationTranslation(
orientedBoundingBox.halfAxes,
orientedBoundingBox.center,
scratchTransformPositionLocalToWorld
);
const transformPositionLocalToProjection = Matrix4_default.multiply(
worldToProjection,
transformPositionLocalToWorld,
scratchTransformPositionLocalToProjection
);
let ndcMinX = +Number.MAX_VALUE;
let ndcMaxX = -Number.MAX_VALUE;
let ndcMinY = +Number.MAX_VALUE;
let ndcMaxY = -Number.MAX_VALUE;
let cornerIndex;
const cornersClipSpace = scratchCornersClipSpace;
const cornersLength = corners.length;
for (cornerIndex = 0; cornerIndex < cornersLength; cornerIndex++) {
Matrix4_default.multiplyByVector(
transformPositionLocalToProjection,
corners[cornerIndex],
cornersClipSpace[cornerIndex]
);
}
for (cornerIndex = 0; cornerIndex < cornersLength; cornerIndex++) {
const position = cornersClipSpace[cornerIndex];
if (position.z >= -position.w) {
const ndcX = position.x / position.w;
const ndcY = position.y / position.w;
ndcMinX = Math.min(ndcMinX, ndcX);
ndcMaxX = Math.max(ndcMaxX, ndcX);
ndcMinY = Math.min(ndcMinY, ndcY);
ndcMaxY = Math.max(ndcMaxY, ndcY);
} else {
for (let neighborIndex = 0; neighborIndex < 3; neighborIndex++) {
const neighborVertexIndex = vertexNeighborIndices[cornerIndex * 3 + neighborIndex];
const neighborPosition = cornersClipSpace[neighborVertexIndex];
if (neighborPosition.z >= -neighborPosition.w) {
const distanceToPlaneFromPosition = position.z + position.w;
const distanceToPlaneFromNeighbor = neighborPosition.z + neighborPosition.w;
const t = distanceToPlaneFromPosition / (distanceToPlaneFromPosition - distanceToPlaneFromNeighbor);
const intersect = Cartesian4_default.lerp(
position,
neighborPosition,
t,
scratchIntersect
);
const intersectNdcX = intersect.x / intersect.w;
const intersectNdcY = intersect.y / intersect.w;
ndcMinX = Math.min(ndcMinX, intersectNdcX);
ndcMaxX = Math.max(ndcMaxX, intersectNdcX);
ndcMinY = Math.min(ndcMinY, intersectNdcY);
ndcMaxY = Math.max(ndcMaxY, intersectNdcY);
}
}
}
}
ndcMinX = Math_default.clamp(ndcMinX, -1, 1);
ndcMinY = Math_default.clamp(ndcMinY, -1, 1);
ndcMaxX = Math_default.clamp(ndcMaxX, -1, 1);
ndcMaxY = Math_default.clamp(ndcMaxY, -1, 1);
result = Cartesian4_default.fromElements(ndcMinX, ndcMinY, ndcMaxX, ndcMaxY, result);
return result;
}
var polylineAxisDistance = 3e7;
var polylineXAxis = new Cartesian3_default(polylineAxisDistance, 0, 0);
var polylineYAxis = new Cartesian3_default(0, polylineAxisDistance, 0);
var polylineZAxis = new Cartesian3_default(0, 0, polylineAxisDistance);
function debugDraw(that, frameState) {
const traversal4 = that._traversal;
const polylines = that._debugPolylines;
polylines.removeAll();
function makePolylineLineSegment(startPos, endPos, color, thickness) {
polylines.add({
positions: [startPos, endPos],
width: thickness,
material: Material_default.fromType("Color", {
color
})
});
}
function makePolylineBox(orientedBoundingBox, color, thickness) {
const corners2 = orientedBoundingBox.computeCorners();
makePolylineLineSegment(corners2[0], corners2[1], color, thickness);
makePolylineLineSegment(corners2[2], corners2[3], color, thickness);
makePolylineLineSegment(corners2[4], corners2[5], color, thickness);
makePolylineLineSegment(corners2[6], corners2[7], color, thickness);
makePolylineLineSegment(corners2[0], corners2[2], color, thickness);
makePolylineLineSegment(corners2[4], corners2[6], color, thickness);
makePolylineLineSegment(corners2[1], corners2[3], color, thickness);
makePolylineLineSegment(corners2[5], corners2[7], color, thickness);
makePolylineLineSegment(corners2[0], corners2[4], color, thickness);
makePolylineLineSegment(corners2[2], corners2[6], color, thickness);
makePolylineLineSegment(corners2[1], corners2[5], color, thickness);
makePolylineLineSegment(corners2[3], corners2[7], color, thickness);
}
function drawTile(tile) {
if (!traversal4.isRenderable(tile)) {
return;
}
const level = tile.level;
const startThickness = 5;
const thickness = Math.max(1, startThickness / Math.pow(2, level));
const colors = [Color_default.RED, Color_default.LIME, Color_default.BLUE];
const color = colors[level % 3];
makePolylineBox(tile.orientedBoundingBox, color, thickness);
if (defined_default(tile.children)) {
for (let i = 0; i < 8; i++) {
drawTile(tile.children[i]);
}
}
}
makePolylineBox(that._shape.orientedBoundingBox, Color_default.WHITE, 5);
drawTile(traversal4.rootNode);
const axisThickness = 10;
makePolylineLineSegment(
Cartesian3_default.ZERO,
polylineXAxis,
Color_default.RED,
axisThickness
);
makePolylineLineSegment(
Cartesian3_default.ZERO,
polylineYAxis,
Color_default.LIME,
axisThickness
);
makePolylineLineSegment(
Cartesian3_default.ZERO,
polylineZAxis,
Color_default.BLUE,
axisThickness
);
polylines.update(frameState);
}
VoxelPrimitive.DefaultCustomShader = new CustomShader_default({
fragmentShaderText: `void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)
{
material.diffuse = vec3(1.0);
material.alpha = 1.0;
}`
});
function DefaultVoxelProvider() {
this.ready = true;
this.shape = VoxelShapeType_default.BOX;
this.dimensions = new Cartesian3_default(1, 1, 1);
this.names = ["data"];
this.types = [MetadataType_default.SCALAR];
this.componentTypes = [MetadataComponentType_default.FLOAT32];
this.maximumTileCount = 1;
}
DefaultVoxelProvider.prototype.requestData = function(options) {
const tileLevel = defined_default(options) ? options.tileLevel ?? 0 : 0;
if (tileLevel >= 1) {
return void 0;
}
const content = new VoxelContent_default({ metadata: [new Float32Array(1)] });
return Promise.resolve(content);
};
VoxelPrimitive.DefaultProvider = new DefaultVoxelProvider();
var VoxelPrimitive_default = VoxelPrimitive;
// packages/engine/Source/Scene/getMetadataClassProperty.js
var import_InlineWorkers1159 = __toESM(require_InlineWorkers(), 1);
function getMetadataClassProperty(schema, schemaId, className, propertyName) {
if (!defined_default(schema)) {
return void 0;
}
if (defined_default(schemaId) && schema.id !== schemaId) {
return void 0;
}
const classes = schema.classes || {};
const metadataClass = classes[className];
if (!defined_default(metadataClass)) {
return void 0;
}
const properties = metadataClass.properties || {};
const metadataProperty = properties[propertyName];
if (!defined_default(metadataProperty)) {
return void 0;
}
return metadataProperty;
}
var getMetadataClassProperty_default = getMetadataClassProperty;
// packages/engine/Source/Scene/PickedMetadataInfo.js
var import_InlineWorkers1160 = __toESM(require_InlineWorkers(), 1);
function PickedMetadataInfo(schemaId, className, propertyName, classProperty, metadataProperty) {
this.schemaId = schemaId;
this.className = className;
this.propertyName = propertyName;
this.classProperty = classProperty;
this.metadataProperty = metadataProperty;
}
var PickedMetadataInfo_default = PickedMetadataInfo;
// packages/engine/Source/Scene/getMetadataProperty.js
var import_InlineWorkers1161 = __toESM(require_InlineWorkers(), 1);
function getMetadataProperty(structuralMetadata, className, propertyName) {
if (!defined_default(structuralMetadata)) {
return void 0;
}
const propertyTextures = structuralMetadata.propertyTextures;
for (const propertyTexture of propertyTextures) {
const metadataClass = propertyTexture.class;
if (metadataClass.id === className) {
const properties = propertyTexture.properties;
const property = properties[propertyName];
if (defined_default(property)) {
return property;
}
}
}
return void 0;
}
var getMetadataProperty_default = getMetadataProperty;
// packages/engine/Source/Scene/Scene.js
var requestRenderAfterFrame = function(scene) {
return function() {
scene.frameState.afterRender.push(function() {
scene.requestRender();
});
};
};
function Scene4(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const canvas = options.canvas;
let creditContainer = options.creditContainer;
let creditViewport = options.creditViewport;
if (!defined_default(canvas)) {
throw new DeveloperError_default("options and options.canvas are required.");
}
const countReferences = options.contextOptions instanceof SharedContext_default;
if (countReferences) {
this._context = options.contextOptions.createSceneContext(canvas);
} else {
const contextOptions = clone_default(options.contextOptions);
this._context = new Context_default(canvas, contextOptions);
}
const context = this._context;
const hasCreditContainer = defined_default(creditContainer);
if (!hasCreditContainer) {
creditContainer = document.createElement("div");
creditContainer.style.position = "absolute";
creditContainer.style.bottom = "0";
creditContainer.style["text-shadow"] = "0 0 2px #000000";
creditContainer.style.color = "#ffffff";
creditContainer.style["font-size"] = "10px";
creditContainer.style["padding-right"] = "5px";
canvas.parentNode.appendChild(creditContainer);
}
if (!defined_default(creditViewport)) {
creditViewport = canvas.parentNode;
}
this._id = createGuid_default();
this._jobScheduler = new JobScheduler_default();
this._frameState = new FrameState_default(
context,
new CreditDisplay_default(creditContainer, "\u2022", creditViewport),
this._jobScheduler
);
this._frameState.scene3DOnly = options.scene3DOnly ?? false;
this._removeCreditContainer = !hasCreditContainer;
this._creditContainer = creditContainer;
this._canvas = canvas;
this._computeEngine = new ComputeEngine_default(context);
this._ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
this._globe = void 0;
this._globeTranslucencyState = new GlobeTranslucencyState_default();
this._primitives = new PrimitiveCollection_default({ countReferences });
this._groundPrimitives = new PrimitiveCollection_default({ countReferences });
this._globeHeight = void 0;
this._globeHeightDirty = true;
this._cameraUnderground = false;
this._removeUpdateHeightCallback = void 0;
this._logDepthBuffer = Scene4.defaultLogDepthBuffer && context.fragmentDepth;
this._logDepthBufferDirty = true;
this._tweens = new TweenCollection_default();
this._shaderFrameCount = 0;
this._sunPostProcess = void 0;
this._computeCommandList = [];
this._overlayCommandList = [];
this._useOIT = options.orderIndependentTranslucency ?? true;
this._executeOITFunction = void 0;
this._depthPlane = new DepthPlane_default(options.depthPlaneEllipsoidOffset);
this._clearColorCommand = new ClearCommand_default({
color: new Color_default(),
stencil: 0,
owner: this
});
this._depthClearCommand = new ClearCommand_default({
depth: 1,
owner: this
});
this._stencilClearCommand = new ClearCommand_default({
stencil: 0
});
this._classificationStencilClearCommand = new ClearCommand_default({
stencil: 0,
renderState: RenderState_default.fromCache({
stencilMask: StencilConstants_default.CLASSIFICATION_MASK
})
});
this._depthOnlyRenderStateCache = {};
this._transitioner = new SceneTransitioner_default(this);
this._preUpdate = new Event_default();
this._postUpdate = new Event_default();
this._renderError = new Event_default();
this._preRender = new Event_default();
this._postRender = new Event_default();
this._minimumDisableDepthTestDistance = 0;
this._debugInspector = new DebugInspector_default();
this._msaaSamples = options.msaaSamples ?? 4;
this.rethrowRenderErrors = false;
this.completeMorphOnUserInput = true;
this.morphStart = new Event_default();
this.morphComplete = new Event_default();
this.skyBox = void 0;
this.skyAtmosphere = void 0;
this.sun = void 0;
this.sunBloom = true;
this._sunBloom = void 0;
this.moon = void 0;
this.backgroundColor = Color_default.clone(Color_default.BLACK);
this._mode = SceneMode_default.SCENE3D;
this._mapProjection = defined_default(options.mapProjection) ? options.mapProjection : new GeographicProjection_default(this._ellipsoid);
this.morphTime = 1;
this.farToNearRatio = 1e3;
this.logarithmicDepthFarToNearRatio = 1e9;
this.nearToFarDistance2D = 175e4;
this.verticalExaggeration = 1;
this.verticalExaggerationRelativeHeight = 0;
this.debugCommandFilter = void 0;
this.debugShowCommands = false;
this.debugShowFrustums = false;
this.debugShowFramesPerSecond = false;
this.debugShowDepthFrustum = 1;
this.debugShowFrustumPlanes = false;
this._debugShowFrustumPlanes = false;
this._debugFrustumPlanes = void 0;
this.useDepthPicking = true;
this.pickTranslucentDepth = false;
this.cameraEventWaitTime = 500;
this.atmosphere = new Atmosphere_default();
this.fog = new Fog_default();
this.fog.enabled = Ellipsoid_default.WGS84.equals(this._ellipsoid);
if (!Ellipsoid_default.WGS84.equals(this._ellipsoid)) {
Camera_default.DEFAULT_VIEW_RECTANGLE = Rectangle_default.fromDegrees(
-45,
-45,
45,
45
);
}
this._shadowMapCamera = new Camera_default(this);
this.shadowMap = new ShadowMap_default({
context,
lightCamera: this._shadowMapCamera,
enabled: options.shadows ?? false
});
this.invertClassification = false;
this.invertClassificationColor = Color_default.clone(Color_default.WHITE);
this._actualInvertClassificationColor = Color_default.clone(
this._invertClassificationColor
);
this._invertClassification = new InvertClassification_default();
this.focalLength = void 0;
this.eyeSeparation = void 0;
this.postProcessStages = new PostProcessStageCollection_default();
this._brdfLutGenerator = new BrdfLutGenerator_default();
this._performanceDisplay = void 0;
this._debugVolume = void 0;
this._screenSpaceCameraController = new ScreenSpaceCameraController_default(this);
this._cameraUnderground = false;
this._mapMode2D = options.mapMode2D ?? MapMode2D_default.INFINITE_SCROLL;
this._environmentState = {
skyBoxCommand: void 0,
skyAtmosphereCommand: void 0,
sunDrawCommand: void 0,
sunComputeCommand: void 0,
moonCommand: void 0,
isSunVisible: false,
isMoonVisible: false,
isReadyForAtmosphere: false,
isSkyAtmosphereVisible: false,
clearGlobeDepth: false,
useDepthPlane: false,
renderTranslucentDepthForPick: false,
originalFramebuffer: void 0,
useGlobeDepthFramebuffer: false,
useOIT: false,
useInvertClassification: false,
usePostProcess: false,
usePostProcessSelected: false,
useWebVR: false
};
this._useWebVR = false;
this._cameraVR = void 0;
this._aspectRatioVR = void 0;
this.requestRenderMode = options.requestRenderMode ?? false;
this._renderRequested = true;
this.maximumRenderTimeChange = options.maximumRenderTimeChange ?? 0;
this._lastRenderTime = void 0;
this._frameRateMonitor = void 0;
this._removeRequestListenerCallback = RequestScheduler_default.requestCompletedEvent.addEventListener(
requestRenderAfterFrame(this)
);
this._removeTaskProcessorListenerCallback = TaskProcessor_default.taskCompletedEvent.addEventListener(
requestRenderAfterFrame(this)
);
this._removeGlobeCallbacks = [];
this._removeTerrainProviderReadyListener = void 0;
const viewport = new BoundingRectangle_default(
0,
0,
context.drawingBufferWidth,
context.drawingBufferHeight
);
const camera = new Camera_default(this);
if (this._logDepthBuffer) {
camera.frustum.near = 0.1;
camera.frustum.far = 1e10;
}
this.preloadFlightCamera = new Camera_default(this);
this.preloadFlightCullingVolume = void 0;
this._picking = new Picking_default(this);
this._defaultView = new View_default(this, camera, viewport);
this._view = this._defaultView;
this._hdr = void 0;
this._hdrDirty = void 0;
this.highDynamicRange = false;
this.gamma = 2.2;
this.sphericalHarmonicCoefficients = void 0;
this.specularEnvironmentMaps = void 0;
this._specularEnvironmentCubeMap = void 0;
this.light = new SunLight_default();
updateFrameNumber(this, 0, JulianDate_default.now());
this.updateFrameState();
this.initializeFrame();
}
Scene4.defaultLogDepthBuffer = true;
function updateGlobeListeners(scene, globe) {
for (let i = 0; i < scene._removeGlobeCallbacks.length; ++i) {
scene._removeGlobeCallbacks[i]();
}
scene._removeGlobeCallbacks.length = 0;
const removeGlobeCallbacks = [];
if (defined_default(globe)) {
removeGlobeCallbacks.push(
globe.imageryLayersUpdatedEvent.addEventListener(
requestRenderAfterFrame(scene)
)
);
removeGlobeCallbacks.push(
globe.terrainProviderChanged.addEventListener(
requestRenderAfterFrame(scene)
)
);
}
scene._removeGlobeCallbacks = removeGlobeCallbacks;
}
Object.defineProperties(Scene4.prototype, {
/**
* Gets the canvas element to which this scene is bound.
* @memberof Scene.prototype
*
* @type {HTMLCanvasElement}
* @readonly
*/
canvas: {
get: function() {
return this._canvas;
}
},
/**
* The drawingBufferHeight of the underlying GL context.
* @memberof Scene.prototype
*
* @type {number}
* @readonly
*
* @see {@link https://www.khronos.org/registry/webgl/specs/1.0/#DOM-WebGLRenderingContext-drawingBufferHeight|drawingBufferHeight}
*/
drawingBufferHeight: {
get: function() {
return this._context.drawingBufferHeight;
}
},
/**
* The drawingBufferWidth of the underlying GL context.
* @memberof Scene.prototype
*
* @type {number}
* @readonly
*
* @see {@link https://www.khronos.org/registry/webgl/specs/1.0/#DOM-WebGLRenderingContext-drawingBufferWidth|drawingBufferWidth}
*/
drawingBufferWidth: {
get: function() {
return this._context.drawingBufferWidth;
}
},
/**
* The maximum aliased line width, in pixels, supported by this WebGL implementation. It will be at least one.
* @memberof Scene.prototype
*
* @type {number}
* @readonly
*
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with ALIASED_LINE_WIDTH_RANGE.
*/
maximumAliasedLineWidth: {
get: function() {
return ContextLimits_default.maximumAliasedLineWidth;
}
},
/**
* The maximum length in pixels of one edge of a cube map, supported by this WebGL implementation. It will be at least 16.
* @memberof Scene.prototype
*
* @type {number}
* @readonly
*
* @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with GL_MAX_CUBE_MAP_TEXTURE_SIZE.
*/
maximumCubeMapSize: {
get: function() {
return ContextLimits_default.maximumCubeMapSize;
}
},
/**
* Returns true if the {@link Scene#pickPosition} function is supported.
* @memberof Scene.prototype
*
* @type {boolean}
* @readonly
*
* @see Scene#pickPosition
*/
pickPositionSupported: {
get: function() {
return this._context.depthTexture;
}
},
/**
* Returns true if the {@link Scene#sampleHeight} and {@link Scene#sampleHeightMostDetailed} functions are supported.
* @memberof Scene.prototype
*
* @type {boolean}
* @readonly
*
* @see Scene#sampleHeight
* @see Scene#sampleHeightMostDetailed
*/
sampleHeightSupported: {
get: function() {
return this._context.depthTexture;
}
},
/**
* Returns true if the {@link Scene#clampToHeight} and {@link Scene#clampToHeightMostDetailed} functions are supported.
* @memberof Scene.prototype
*
* @type {boolean}
* @readonly
*
* @see Scene#clampToHeight
* @see Scene#clampToHeightMostDetailed
*/
clampToHeightSupported: {
get: function() {
return this._context.depthTexture;
}
},
/**
* Returns true if the {@link Scene#invertClassification} is supported.
* @memberof Scene.prototype
*
* @type {boolean}
* @readonly
*
* @see Scene#invertClassification
*/
invertClassificationSupported: {
get: function() {
return this._context.depthTexture;
}
},
/**
* Returns true if specular environment maps are supported.
* @memberof Scene.prototype
*
* @type {boolean}
* @readonly
*
* @see Scene#specularEnvironmentMaps
*/
specularEnvironmentMapsSupported: {
get: function() {
return SpecularEnvironmentCubeMap_default.isSupported(this._context);
}
},
/**
* The ellipsoid. If not specified, the default ellipsoid is used.
* @memberof Scene.prototype
*
* @type {Ellipsoid}
* @readonly
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
},
/**
* Gets or sets the depth-test ellipsoid.
* @memberof Scene.prototype
*
* @type {Globe}
*/
globe: {
get: function() {
return this._globe;
},
set: function(globe) {
this._globe = this._globe && this._globe.destroy();
this._globe = globe;
updateGlobeListeners(this, globe);
}
},
/**
* Gets the collection of primitives.
* @memberof Scene.prototype
*
* @type {PrimitiveCollection}
* @readonly
*/
primitives: {
get: function() {
return this._primitives;
}
},
/**
* Gets the collection of ground primitives.
* @memberof Scene.prototype
*
* @type {PrimitiveCollection}
* @readonly
*/
groundPrimitives: {
get: function() {
return this._groundPrimitives;
}
},
/**
* Gets or sets the camera.
* @memberof Scene.prototype
*
* @type {Camera}
* @readonly
*/
camera: {
get: function() {
return this._view.camera;
},
set: function(camera) {
this._view.camera = camera;
}
},
/**
* Gets or sets the view.
* @memberof Scene.prototype
*
* @type {View}
* @readonly
*
* @private
*/
view: {
get: function() {
return this._view;
},
set: function(view) {
this._view = view;
}
},
/**
* Gets the default view.
* @memberof Scene.prototype
*
* @type {View}
* @readonly
*
* @private
*/
defaultView: {
get: function() {
return this._defaultView;
}
},
/**
* Gets picking functions and state
* @memberof Scene.prototype
*
* @type {Picking}
* @readonly
*
* @private
*/
picking: {
get: function() {
return this._picking;
}
},
/**
* Gets the controller for camera input handling.
* @memberof Scene.prototype
*
* @type {ScreenSpaceCameraController}
* @readonly
*/
screenSpaceCameraController: {
get: function() {
return this._screenSpaceCameraController;
}
},
/**
* Get the map projection to use in 2D and Columbus View modes.
* @memberof Scene.prototype
*
* @type {MapProjection}
* @readonly
*
* @default new GeographicProjection()
*/
mapProjection: {
get: function() {
return this._mapProjection;
}
},
/**
* Gets the job scheduler
* @memberof Scene.prototype
* @type {JobScheduler}
* @readonly
*
* @private
*/
jobScheduler: {
get: function() {
return this._jobScheduler;
}
},
/**
* Gets state information about the current scene. If called outside of a primitive's update
* function, the previous frame's state is returned.
* @memberof Scene.prototype
*
* @type {FrameState}
* @readonly
*
* @private
*/
frameState: {
get: function() {
return this._frameState;
}
},
/**
* Gets the environment state.
* @memberof Scene.prototype
*
* @type {EnvironmentState}
* @readonly
*
* @private
*/
environmentState: {
get: function() {
return this._environmentState;
}
},
/**
* Gets the collection of tweens taking place in the scene.
* @memberof Scene.prototype
*
* @type {TweenCollection}
* @readonly
*
* @private
*/
tweens: {
get: function() {
return this._tweens;
}
},
/**
* Gets the collection of image layers that will be rendered on the globe.
* @memberof Scene.prototype
*
* @type {ImageryLayerCollection}
* @readonly
*/
imageryLayers: {
get: function() {
if (!defined_default(this.globe)) {
return void 0;
}
return this.globe.imageryLayers;
}
},
/**
* The terrain provider providing surface geometry for the globe.
* @memberof Scene.prototype
*
* @type {TerrainProvider}
*/
terrainProvider: {
get: function() {
if (!defined_default(this.globe)) {
return void 0;
}
return this.globe.terrainProvider;
},
set: function(terrainProvider) {
this._removeTerrainProviderReadyListener = this._removeTerrainProviderReadyListener && this._removeTerrainProviderReadyListener();
if (defined_default(this.globe)) {
this.globe.terrainProvider = terrainProvider;
}
}
},
/**
* Gets an event that's raised when the terrain provider is changed
* @memberof Scene.prototype
*
* @type {Event}
* @readonly
*/
terrainProviderChanged: {
get: function() {
if (!defined_default(this.globe)) {
return void 0;
}
return this.globe.terrainProviderChanged;
}
},
/**
* Gets the event that will be raised before the scene is updated or rendered. Subscribers to the event
* receive the Scene instance as the first parameter and the current time as the second parameter.
* @memberof Scene.prototype
*
* @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
* @see Scene#postUpdate
* @see Scene#preRender
* @see Scene#postRender
*
* @type {Event}
* @readonly
*/
preUpdate: {
get: function() {
return this._preUpdate;
}
},
/**
* Gets the event that will be raised immediately after the scene is updated and before the scene is rendered.
* Subscribers to the event receive the Scene instance as the first parameter and the current time as the second
* parameter.
* @memberof Scene.prototype
*
* @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
* @see Scene#preUpdate
* @see Scene#preRender
* @see Scene#postRender
*
* @type {Event}
* @readonly
*/
postUpdate: {
get: function() {
return this._postUpdate;
}
},
/**
* Gets the event that will be raised when an error is thrown inside the render function.
* The Scene instance and the thrown error are the only two parameters passed to the event handler.
* By default, errors are not rethrown after this event is raised, but that can be changed by setting
* the rethrowRenderErrors property.
* @memberof Scene.prototype
*
* @type {Event}
* @readonly
*/
renderError: {
get: function() {
return this._renderError;
}
},
/**
* Gets the event that will be raised after the scene is updated and immediately before the scene is rendered.
* Subscribers to the event receive the Scene instance as the first parameter and the current time as the second
* parameter.
* @memberof Scene.prototype
*
* @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
* @see Scene#preUpdate
* @see Scene#postUpdate
* @see Scene#postRender
*
* @type {Event}
* @readonly
*/
preRender: {
get: function() {
return this._preRender;
}
},
/**
* Gets the event that will be raised immediately after the scene is rendered. Subscribers to the event
* receive the Scene instance as the first parameter and the current time as the second parameter.
* @memberof Scene.prototype
*
* @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
* @see Scene#preUpdate
* @see Scene#postUpdate
* @see Scene#postRender
*
* @type {Event}
* @readonly
*/
postRender: {
get: function() {
return this._postRender;
}
},
/**
* Gets the simulation time when the scene was last rendered. Returns undefined
* if the scene has not yet been rendered.
* @memberof Scene.prototype
*
* @type {JulianDate | undefined}
* @readonly
*/
lastRenderTime: {
get: function() {
return this._lastRenderTime;
}
},
/**
* @memberof Scene.prototype
* @private
* @readonly
*/
context: {
get: function() {
return this._context;
}
},
/**
* This property is for debugging only; it is not for production use.
*
* When {@link Scene.debugShowFrustums} is true, this contains
* properties with statistics about the number of command execute per frustum.
* totalCommands is the total number of commands executed, ignoring
* overlap. commandsInFrustums is an array with the number of times
* commands are executed redundantly, e.g., how many commands overlap two or
* three frustums.
*
*
* @memberof Scene.prototype
*
* @type {Object | undefined}
* @readonly
*
* @default undefined
*/
debugFrustumStatistics: {
get: function() {
return this._view.debugFrustumStatistics;
}
},
/**
* Gets whether or not the scene is optimized for 3D only viewing.
* @memberof Scene.prototype
* @type {boolean}
* @readonly
*/
scene3DOnly: {
get: function() {
return this._frameState.scene3DOnly;
}
},
/**
* Gets whether or not the scene has order independent translucency enabled.
* Note that this only reflects the original construction option, and there are
* other factors that could prevent OIT from functioning on a given system configuration.
* @memberof Scene.prototype
* @type {boolean}
* @readonly
*/
orderIndependentTranslucency: {
get: function() {
return this._useOIT;
}
},
/**
* Gets the unique identifier for this scene.
* @memberof Scene.prototype
* @type {string}
* @readonly
*/
id: {
get: function() {
return this._id;
}
},
/**
* Gets or sets the current mode of the scene.
* @memberof Scene.prototype
* @type {SceneMode}
* @default {@link SceneMode.SCENE3D}
*/
mode: {
get: function() {
return this._mode;
},
set: function(value) {
if (this.scene3DOnly && value !== SceneMode_default.SCENE3D) {
throw new DeveloperError_default(
"Only SceneMode.SCENE3D is valid when scene3DOnly is true."
);
}
if (value === SceneMode_default.SCENE2D) {
this.morphTo2D(0);
} else if (value === SceneMode_default.SCENE3D) {
this.morphTo3D(0);
} else if (value === SceneMode_default.COLUMBUS_VIEW) {
this.morphToColumbusView(0);
} else {
throw new DeveloperError_default(
"value must be a valid SceneMode enumeration."
);
}
this._mode = value;
}
},
/**
* Gets the number of frustums used in the last frame.
* @memberof Scene.prototype
* @type {FrustumCommands[]}
*
* @private
*/
frustumCommandsList: {
get: function() {
return this._view.frustumCommandsList;
}
},
/**
* Gets the number of frustums used in the last frame.
* @memberof Scene.prototype
* @type {number}
*
* @private
*/
numberOfFrustums: {
get: function() {
return this._view.frustumCommandsList.length;
}
},
/**
* When true, splits the scene into two viewports with steroscopic views for the left and right eyes.
* Used for cardboard and WebVR.
* @memberof Scene.prototype
* @type {boolean}
* @default false
*/
useWebVR: {
get: function() {
return this._useWebVR;
},
set: function(value) {
if (this.camera.frustum instanceof OrthographicFrustum_default) {
throw new DeveloperError_default(
"VR is unsupported with an orthographic projection."
);
}
this._useWebVR = value;
if (this._useWebVR) {
this._frameState.creditDisplay.container.style.visibility = "hidden";
this._cameraVR = new Camera_default(this);
if (!defined_default(this._deviceOrientationCameraController)) {
this._deviceOrientationCameraController = new DeviceOrientationCameraController_default(this);
}
this._aspectRatioVR = this.camera.frustum.aspectRatio;
} else {
this._frameState.creditDisplay.container.style.visibility = "visible";
this._cameraVR = void 0;
this._deviceOrientationCameraController = this._deviceOrientationCameraController && !this._deviceOrientationCameraController.isDestroyed() && this._deviceOrientationCameraController.destroy();
this.camera.frustum.aspectRatio = this._aspectRatioVR;
this.camera.frustum.xOffset = 0;
}
}
},
/**
* Determines if the 2D map is rotatable or can be scrolled infinitely in the horizontal direction.
* @memberof Scene.prototype
* @type {MapMode2D}
* @readonly
*/
mapMode2D: {
get: function() {
return this._mapMode2D;
}
},
/**
* Gets or sets the position of the splitter within the viewport. Valid values are between 0.0 and 1.0.
* @memberof Scene.prototype
*
* @type {number}
*/
splitPosition: {
get: function() {
return this._frameState.splitPosition;
},
set: function(value) {
this._frameState.splitPosition = value;
}
},
/**
* The distance from the camera at which to disable the depth test of billboards, labels and points
* to, for example, prevent clipping against terrain. When set to zero, the depth test should always
* be applied. When less than zero, the depth test should never be applied. Setting the disableDepthTestDistance
* property of a billboard, label or point will override this value.
* @memberof Scene.prototype
* @type {number}
* @default 0.0
*/
minimumDisableDepthTestDistance: {
get: function() {
return this._minimumDisableDepthTestDistance;
},
set: function(value) {
if (!defined_default(value) || value < 0) {
throw new DeveloperError_default(
"minimumDisableDepthTestDistance must be greater than or equal to 0.0."
);
}
this._minimumDisableDepthTestDistance = value;
}
},
/**
* Whether or not to use a logarithmic depth buffer. Enabling this option will allow for less frustums in the multi-frustum,
* increasing performance. This property relies on fragmentDepth being supported.
* @memberof Scene.prototype
* @type {boolean}
*/
logarithmicDepthBuffer: {
get: function() {
return this._logDepthBuffer;
},
set: function(value) {
value = this._context.fragmentDepth && value;
if (this._logDepthBuffer !== value) {
this._logDepthBuffer = value;
this._logDepthBufferDirty = true;
}
}
},
/**
* The value used for gamma correction. This is only used when rendering with high dynamic range.
* @memberof Scene.prototype
* @type {number}
* @default 2.2
*/
gamma: {
get: function() {
return this._context.uniformState.gamma;
},
set: function(value) {
this._context.uniformState.gamma = value;
}
},
/**
* Whether or not to use high dynamic range rendering.
* @memberof Scene.prototype
* @type {boolean}
* @default false
*/
highDynamicRange: {
get: function() {
return this._hdr;
},
set: function(value) {
const context = this._context;
const hdr = value && context.depthTexture && (context.colorBufferFloat || context.colorBufferHalfFloat);
this._hdrDirty = hdr !== this._hdr;
this._hdr = hdr;
}
},
/**
* Whether or not high dynamic range rendering is supported.
* @memberof Scene.prototype
* @type {boolean}
* @readonly
* @default true
*/
highDynamicRangeSupported: {
get: function() {
const context = this._context;
return context.depthTexture && (context.colorBufferFloat || context.colorBufferHalfFloat);
}
},
/**
* Whether or not the camera is underneath the globe.
* @memberof Scene.prototype
* @type {boolean}
* @readonly
* @default false
*/
cameraUnderground: {
get: function() {
return this._cameraUnderground;
}
},
/**
* The sample rate of multisample antialiasing (values greater than 1 enable MSAA).
* @memberof Scene.prototype
* @type {number}
* @default 4
*/
msaaSamples: {
get: function() {
return this._msaaSamples;
},
set: function(value) {
value = Math.min(value, ContextLimits_default.maximumSamples);
this._msaaSamples = value;
}
},
/**
* Returns true if the Scene's context supports MSAA.
* @memberof Scene.prototype
* @type {boolean}
* @readonly
*/
msaaSupported: {
get: function() {
return this._context.msaa;
}
},
/**
* Ratio between a pixel and a density-independent pixel. Provides a standard unit of
* measure for real pixel measurements appropriate to a particular device.
*
* @memberof Scene.prototype
* @type {number}
* @default 1.0
* @private
*/
pixelRatio: {
get: function() {
return this._frameState.pixelRatio;
},
set: function(value) {
this._frameState.pixelRatio = value;
}
},
/**
* @private
*/
opaqueFrustumNearOffset: {
get: function() {
return 0.9999;
}
},
/**
* @private
*/
globeHeight: {
get: function() {
return this._globeHeight;
}
}
});
Scene4.prototype.getCompressedTextureFormatSupported = function(format) {
const context = this.context;
return (format === "WEBGL_compressed_texture_s3tc" || format === "s3tc") && context.s3tc || (format === "WEBGL_compressed_texture_pvrtc" || format === "pvrtc") && context.pvrtc || (format === "WEBGL_compressed_texture_etc" || format === "etc") && context.etc || (format === "WEBGL_compressed_texture_etc1" || format === "etc1") && context.etc1 || (format === "WEBGL_compressed_texture_astc" || format === "astc") && context.astc || (format === "EXT_texture_compression_bptc" || format === "bc7") && context.bc7;
};
function pickedMetadataInfoChanged(command, frameState) {
const oldPickedMetadataInfo = command.pickedMetadataInfo;
const newPickedMetadataInfo = frameState.pickedMetadataInfo;
if (oldPickedMetadataInfo?.schemaId !== newPickedMetadataInfo?.schemaId) {
return true;
}
if (oldPickedMetadataInfo?.className !== newPickedMetadataInfo?.className) {
return true;
}
if (oldPickedMetadataInfo?.propertyName !== newPickedMetadataInfo?.propertyName) {
return true;
}
return false;
}
function updateDerivedCommands2(scene, command, shadowsDirty) {
const frameState = scene._frameState;
const context = scene._context;
const oit = scene._view.oit;
const { lightShadowMaps, lightShadowsEnabled } = frameState.shadowState;
let derivedCommands = command.derivedCommands;
if (defined_default(command.pickId)) {
derivedCommands.picking = DerivedCommand_default.createPickDerivedCommand(
scene,
command,
context,
derivedCommands.picking
);
}
if (frameState.pickingMetadata && command.pickMetadataAllowed) {
command.pickedMetadataInfo = frameState.pickedMetadataInfo;
if (defined_default(command.pickedMetadataInfo)) {
derivedCommands.pickingMetadata = DerivedCommand_default.createPickMetadataDerivedCommand(
scene,
command,
context,
derivedCommands.pickingMetadata
);
}
}
if (!command.pickOnly) {
derivedCommands.depth = DerivedCommand_default.createDepthOnlyDerivedCommand(
scene,
command,
context,
derivedCommands.depth
);
}
derivedCommands.originalCommand = command;
if (scene._hdr) {
derivedCommands.hdr = DerivedCommand_default.createHdrCommand(
command,
context,
derivedCommands.hdr
);
command = derivedCommands.hdr.command;
derivedCommands = command.derivedCommands;
}
if (lightShadowsEnabled && command.receiveShadows) {
derivedCommands.shadows = ShadowMap_default.createReceiveDerivedCommand(
lightShadowMaps,
command,
shadowsDirty,
context,
derivedCommands.shadows
);
}
if (command.pass === Pass_default.TRANSLUCENT && defined_default(oit) && oit.isSupported()) {
if (lightShadowsEnabled && command.receiveShadows) {
derivedCommands.oit = defined_default(derivedCommands.oit) ? derivedCommands.oit : {};
derivedCommands.oit.shadows = oit.createDerivedCommands(
derivedCommands.shadows.receiveCommand,
context,
derivedCommands.oit.shadows
);
} else {
derivedCommands.oit = oit.createDerivedCommands(
command,
context,
derivedCommands.oit
);
}
}
}
Scene4.prototype.updateDerivedCommands = function(command) {
const { derivedCommands } = command;
if (!defined_default(derivedCommands)) {
return;
}
const frameState = this._frameState;
const { shadowState, useLogDepth } = this._frameState;
const context = this._context;
let shadowsDirty = false;
const lastDirtyTime = shadowState.lastDirtyTime;
if (command.lastDirtyTime !== lastDirtyTime) {
command.lastDirtyTime = lastDirtyTime;
command.dirty = true;
shadowsDirty = true;
}
const useHdr = this._hdr;
const hasLogDepthDerivedCommands = defined_default(derivedCommands.logDepth);
const hasHdrCommands = defined_default(derivedCommands.hdr);
const hasDerivedCommands = defined_default(derivedCommands.originalCommand);
const needsLogDepthDerivedCommands = useLogDepth && !hasLogDepthDerivedCommands;
const needsHdrCommands = useHdr && !hasHdrCommands;
const needsDerivedCommands = (!useLogDepth || !useHdr) && !hasDerivedCommands;
const needsUpdateForMetadataPicking = frameState.pickingMetadata && pickedMetadataInfoChanged(command, frameState);
command.dirty = command.dirty || needsLogDepthDerivedCommands || needsHdrCommands || needsDerivedCommands || needsUpdateForMetadataPicking;
if (!command.dirty) {
return;
}
command.dirty = false;
const { shadowsEnabled, shadowMaps } = shadowState;
if (shadowsEnabled && command.castShadows) {
derivedCommands.shadows = ShadowMap_default.createCastDerivedCommand(
shadowMaps,
command,
shadowsDirty,
context,
derivedCommands.shadows
);
}
if (hasLogDepthDerivedCommands || needsLogDepthDerivedCommands) {
derivedCommands.logDepth = DerivedCommand_default.createLogDepthCommand(
command,
context,
derivedCommands.logDepth
);
updateDerivedCommands2(this, derivedCommands.logDepth.command, shadowsDirty);
}
if (hasDerivedCommands || needsDerivedCommands) {
updateDerivedCommands2(this, command, shadowsDirty);
}
};
var renderTilesetPassState = new Cesium3DTilePassState_default({
pass: Cesium3DTilePass_default.RENDER
});
var preloadTilesetPassState = new Cesium3DTilePassState_default({
pass: Cesium3DTilePass_default.PRELOAD
});
var preloadFlightTilesetPassState = new Cesium3DTilePassState_default({
pass: Cesium3DTilePass_default.PRELOAD_FLIGHT
});
var requestRenderModeDeferCheckPassState = new Cesium3DTilePassState_default({
pass: Cesium3DTilePass_default.REQUEST_RENDER_MODE_DEFER_CHECK
});
var scratchOccluderBoundingSphere = new BoundingSphere_default();
var scratchOccluder;
function getOccluder(scene) {
if (scene._mode !== SceneMode_default.SCENE3D || !scene.globe?.show || scene._cameraUnderground || scene._globeTranslucencyState.translucent) {
return void 0;
}
scratchOccluderBoundingSphere.radius = scene.ellipsoid.minimumRadius + scene.frameState.minimumTerrainHeight;
scratchOccluder = Occluder_default.fromBoundingSphere(
scratchOccluderBoundingSphere,
scene.camera.positionWC,
scratchOccluder
);
return scratchOccluder;
}
Scene4.prototype.clearPasses = function(passes) {
passes.render = false;
passes.pick = false;
passes.pickVoxel = false;
passes.depth = false;
passes.postProcess = false;
passes.offscreen = false;
};
function updateFrameNumber(scene, frameNumber, time) {
const frameState = scene._frameState;
frameState.frameNumber = frameNumber;
frameState.time = JulianDate_default.clone(time, frameState.time);
}
Scene4.prototype.updateFrameState = function() {
const camera = this.camera;
const frameState = this._frameState;
frameState.commandList.length = 0;
frameState.shadowMaps.length = 0;
frameState.brdfLutGenerator = this._brdfLutGenerator;
frameState.environmentMap = this.skyBox && this.skyBox._cubeMap;
frameState.mode = this._mode;
frameState.morphTime = this.morphTime;
frameState.mapProjection = this.mapProjection;
frameState.camera = camera;
frameState.cullingVolume = camera.frustum.computeCullingVolume(
camera.positionWC,
camera.directionWC,
camera.upWC
);
frameState.occluder = getOccluder(this);
frameState.minimumTerrainHeight = 0;
frameState.minimumDisableDepthTestDistance = this._minimumDisableDepthTestDistance;
frameState.invertClassification = this.invertClassification;
frameState.useLogDepth = this._logDepthBuffer && !(this.camera.frustum instanceof OrthographicFrustum_default || this.camera.frustum instanceof OrthographicOffCenterFrustum_default);
frameState.light = this.light;
frameState.cameraUnderground = this._cameraUnderground;
frameState.globeTranslucencyState = this._globeTranslucencyState;
const { globe } = this;
if (defined_default(globe) && globe._terrainExaggerationChanged) {
this.verticalExaggeration = globe._terrainExaggeration;
this.verticalExaggerationRelativeHeight = globe._terrainExaggerationRelativeHeight;
globe._terrainExaggerationChanged = false;
}
frameState.verticalExaggeration = this.verticalExaggeration;
frameState.verticalExaggerationRelativeHeight = this.verticalExaggerationRelativeHeight;
if (defined_default(this._specularEnvironmentCubeMap) && this._specularEnvironmentCubeMap.ready) {
frameState.specularEnvironmentMaps = this._specularEnvironmentCubeMap.texture;
frameState.specularEnvironmentMapsMaximumLOD = this._specularEnvironmentCubeMap.maximumMipmapLevel;
} else {
frameState.specularEnvironmentMaps = void 0;
frameState.specularEnvironmentMapsMaximumLOD = void 0;
}
frameState.sphericalHarmonicCoefficients = this.sphericalHarmonicCoefficients;
this._actualInvertClassificationColor = Color_default.clone(
this.invertClassificationColor,
this._actualInvertClassificationColor
);
if (!InvertClassification_default.isTranslucencySupported(this._context)) {
this._actualInvertClassificationColor.alpha = 1;
}
frameState.invertClassificationColor = this._actualInvertClassificationColor;
if (defined_default(this.globe)) {
frameState.maximumScreenSpaceError = this.globe.maximumScreenSpaceError;
} else {
frameState.maximumScreenSpaceError = 2;
}
this.clearPasses(frameState.passes);
frameState.tilesetPassState = void 0;
};
Scene4.prototype.isVisible = function(cullingVolume, command, occluder) {
if (!defined_default(command)) {
return false;
}
const { boundingVolume } = command;
if (!defined_default(boundingVolume) || !command.cull) {
return true;
}
if (cullingVolume.computeVisibility(boundingVolume) === Intersect_default.OUTSIDE) {
return false;
}
return !defined_default(occluder) || !command.occlude || !boundingVolume.isOccluded(occluder);
};
var transformFrom2D = new Matrix4_default(
0,
0,
1,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
1
);
transformFrom2D = Matrix4_default.inverseTransformation(
transformFrom2D,
transformFrom2D
);
function debugShowBoundingVolume(command, scene, passState, debugFramebuffer) {
const frameState = scene._frameState;
const context = frameState.context;
const boundingVolume = command.boundingVolume;
if (defined_default(scene._debugVolume)) {
scene._debugVolume.destroy();
}
let center = Cartesian3_default.clone(boundingVolume.center);
if (frameState.mode !== SceneMode_default.SCENE3D) {
center = Matrix4_default.multiplyByPoint(transformFrom2D, center, center);
const projection = frameState.mapProjection;
const centerCartographic = projection.unproject(center);
center = projection.ellipsoid.cartographicToCartesian(centerCartographic);
}
let geometry;
let modelMatrix;
const { radius } = boundingVolume;
if (defined_default(radius)) {
geometry = EllipsoidGeometry_default.createGeometry(
new EllipsoidGeometry_default({
radii: new Cartesian3_default(radius, radius, radius),
vertexFormat: PerInstanceColorAppearance_default.FLAT_VERTEX_FORMAT
})
);
modelMatrix = Matrix4_default.fromTranslation(center);
} else {
geometry = BoxGeometry_default.createGeometry(
BoxGeometry_default.fromDimensions({
dimensions: new Cartesian3_default(2, 2, 2),
vertexFormat: PerInstanceColorAppearance_default.FLAT_VERTEX_FORMAT
})
);
modelMatrix = Matrix4_default.fromRotationTranslation(
boundingVolume.halfAxes,
center,
new Matrix4_default()
);
}
scene._debugVolume = new Primitive_default({
geometryInstances: new GeometryInstance_default({
geometry: GeometryPipeline_default.toWireframe(geometry),
modelMatrix,
attributes: {
color: new ColorGeometryInstanceAttribute_default(1, 0, 0, 1)
}
}),
appearance: new PerInstanceColorAppearance_default({
flat: true,
translucent: false
}),
asynchronous: false
});
const savedCommandList = frameState.commandList;
const commandList = frameState.commandList = [];
scene._debugVolume.update(frameState);
command = commandList[0];
if (frameState.useLogDepth) {
const logDepth = DerivedCommand_default.createLogDepthCommand(command, context);
command = logDepth.command;
}
let framebuffer;
if (defined_default(debugFramebuffer)) {
framebuffer = passState.framebuffer;
passState.framebuffer = debugFramebuffer;
}
command.execute(context, passState);
if (defined_default(framebuffer)) {
passState.framebuffer = framebuffer;
}
frameState.commandList = savedCommandList;
}
function executeCommand(command, scene, passState, debugFramebuffer) {
const frameState = scene._frameState;
const context = scene._context;
if (defined_default(scene.debugCommandFilter) && !scene.debugCommandFilter(command)) {
return;
}
if (command instanceof ClearCommand_default) {
command.execute(context, passState);
return;
}
if (command.debugShowBoundingVolume && defined_default(command.boundingVolume)) {
debugShowBoundingVolume(command, scene, passState, debugFramebuffer);
}
if (frameState.useLogDepth && defined_default(command.derivedCommands.logDepth)) {
command = command.derivedCommands.logDepth.command;
}
const passes = frameState.passes;
if (!passes.pick && !passes.pickVoxel && !passes.depth && scene._hdr && defined_default(command.derivedCommands) && defined_default(command.derivedCommands.hdr)) {
command = command.derivedCommands.hdr.command;
}
if (passes.pick || passes.depth) {
if (passes.pick && !passes.depth) {
if (frameState.pickingMetadata && defined_default(command.derivedCommands.pickingMetadata)) {
command = command.derivedCommands.pickingMetadata.pickMetadataCommand;
command.execute(context, passState);
return;
}
if (!frameState.pickingMetadata && defined_default(command.derivedCommands.picking)) {
command = command.derivedCommands.picking.pickCommand;
command.execute(context, passState);
return;
}
} else if (defined_default(command.derivedCommands.depth)) {
command = command.derivedCommands.depth.depthOnlyCommand;
command.execute(context, passState);
return;
}
}
if (scene.debugShowCommands || scene.debugShowFrustums) {
scene._debugInspector.executeDebugShowFrustumsCommand(
scene,
command,
passState
);
return;
}
if (frameState.shadowState.lightShadowsEnabled && command.receiveShadows && defined_default(command.derivedCommands.shadows)) {
command.derivedCommands.shadows.receiveCommand.execute(context, passState);
} else {
command.execute(context, passState);
}
}
function executeIdCommand(command, scene, passState) {
const { derivedCommands } = command;
if (!defined_default(derivedCommands)) {
return;
}
const frameState = scene._frameState;
const context = scene._context;
if (frameState.useLogDepth && defined_default(derivedCommands.logDepth)) {
command = derivedCommands.logDepth.command;
}
const { picking, pickingMetadata, depth } = command.derivedCommands;
if (defined_default(pickingMetadata)) {
command = derivedCommands.pickingMetadata.pickMetadataCommand;
command.execute(context, passState);
}
if (defined_default(picking)) {
command = picking.pickCommand;
command.execute(context, passState);
} else if (defined_default(depth)) {
command = depth.depthOnlyCommand;
command.execute(context, passState);
}
}
function backToFront(a3, b, position) {
return b.boundingVolume.distanceSquaredTo(position) - a3.boundingVolume.distanceSquaredTo(position);
}
var scratchCart3 = new Cartesian3_default();
function distanceSquaredToCenter(center, position) {
const diff = Cartesian3_default.subtract(center, position, scratchCart3);
const distance2 = Math.max(0, Cartesian3_default.magnitude(diff));
return distance2 * distance2;
}
function backToFrontSplats(a3, b, position) {
const boxA = a3.boundingVolume;
const boxB = b.boundingVolume;
return distanceSquaredToCenter(boxB.center, position) - distanceSquaredToCenter(boxA.center, position);
}
function frontToBack(a3, b, position) {
return a3.boundingVolume.distanceSquaredTo(position) - b.boundingVolume.distanceSquaredTo(position) + Math_default.EPSILON12;
}
function executeTranslucentCommandsBackToFront(scene, executeFunction, passState, commands, invertClassification) {
mergeSort_default(commands, backToFront, scene.camera.positionWC);
if (defined_default(invertClassification)) {
executeFunction(invertClassification.unclassifiedCommand, scene, passState);
}
for (let i = 0; i < commands.length; ++i) {
executeFunction(commands[i], scene, passState);
}
}
function executeTranslucentCommandsFrontToBack(scene, executeFunction, passState, commands, invertClassification) {
mergeSort_default(commands, frontToBack, scene.camera.positionWC);
if (defined_default(invertClassification)) {
executeFunction(invertClassification.unclassifiedCommand, scene, passState);
}
for (let i = 0; i < commands.length; ++i) {
executeFunction(commands[i], scene, passState);
}
}
function performVoxelsPass(scene, passState, frustumCommands) {
scene.context.uniformState.updatePass(Pass_default.VOXELS);
const commands = frustumCommands.commands[Pass_default.VOXELS];
commands.length = frustumCommands.indices[Pass_default.VOXELS];
mergeSort_default(commands, backToFront, scene.camera.positionWC);
for (let i = 0; i < commands.length; ++i) {
executeCommand(commands[i], scene, passState);
}
}
function performGaussianSplatPass(scene, passState, frustumCommands) {
scene.context.uniformState.updatePass(Pass_default.GAUSSIAN_SPLATS);
const commands = frustumCommands.commands[Pass_default.GAUSSIAN_SPLATS];
commands.length = frustumCommands.indices[Pass_default.GAUSSIAN_SPLATS];
mergeSort_default(commands, backToFrontSplats, scene.camera.positionWC);
for (let i = 0; i < commands.length; ++i) {
executeCommand(commands[i], scene, passState);
}
}
var scratchPerspectiveFrustum2 = new PerspectiveFrustum_default();
var scratchPerspectiveOffCenterFrustum2 = new PerspectiveOffCenterFrustum_default();
var scratchOrthographicFrustum2 = new OrthographicFrustum_default();
var scratchOrthographicOffCenterFrustum2 = new OrthographicOffCenterFrustum_default();
function createWorkingFrustum(camera) {
const { frustum } = camera;
if (defined_default(frustum.fov)) {
return frustum.clone(scratchPerspectiveFrustum2);
}
if (defined_default(frustum.infiniteProjectionMatrix)) {
return frustum.clone(scratchPerspectiveOffCenterFrustum2);
}
if (defined_default(frustum.width)) {
return frustum.clone(scratchOrthographicFrustum2);
}
return frustum.clone(scratchOrthographicOffCenterFrustum2);
}
function obtainTranslucentCommandExecutionFunction(scene) {
if (scene._environmentState.useOIT) {
if (!defined_default(scene._executeOITFunction)) {
const { view, context } = scene;
scene._executeOITFunction = function(scene2, executeFunction, passState, commands, invertClassification) {
view.globeDepth.prepareColorTextures(context);
view.oit.executeCommands(
scene2,
executeFunction,
passState,
commands,
invertClassification
);
};
}
return scene._executeOITFunction;
}
if (scene.frameState.passes.render) {
return executeTranslucentCommandsBackToFront;
}
return executeTranslucentCommandsFrontToBack;
}
function performTranslucentPass(scene, passState, frustumCommands) {
const { frameState, context } = scene;
const { pick, pickVoxel } = frameState.passes;
const picking = pick || pickVoxel;
let invertClassification;
if (!picking && scene._environmentState.useInvertClassification && frameState.invertClassificationColor.alpha < 1) {
invertClassification = scene._invertClassification;
}
const executeTranslucentCommands = obtainTranslucentCommandExecutionFunction(scene);
context.uniformState.updatePass(Pass_default.TRANSLUCENT);
const commands = frustumCommands.commands[Pass_default.TRANSLUCENT];
commands.length = frustumCommands.indices[Pass_default.TRANSLUCENT];
executeTranslucentCommands(
scene,
executeCommand,
passState,
commands,
invertClassification
);
}
function performTranslucent3DTilesClassification(scene, passState, frustumCommands) {
const { translucentTileClassification, globeDepth } = scene._view;
const has3DTilesClassificationCommands = frustumCommands.indices[Pass_default.CESIUM_3D_TILE_CLASSIFICATION] > 0;
if (!has3DTilesClassificationCommands || !translucentTileClassification.isSupported()) {
return;
}
const commands = frustumCommands.commands[Pass_default.TRANSLUCENT];
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
commands,
globeDepth.depthStencilTexture
);
translucentTileClassification.executeClassificationCommands(
scene,
executeCommand,
passState,
frustumCommands
);
}
function executeCommands2(scene, passState) {
const { camera, context, frameState } = scene;
const { uniformState } = context;
uniformState.updateCamera(camera);
const frustum = createWorkingFrustum(camera);
frustum.near = camera.frustum.near;
frustum.far = camera.frustum.far;
const passes = frameState.passes;
const picking = passes.pick || passes.pickVoxel;
if (!picking) {
renderEnvironment(scene, passState);
}
const {
clearGlobeDepth,
renderTranslucentDepthForPick: renderTranslucentDepthForPick2,
useDepthPlane: useDepthPlane2,
useGlobeDepthFramebuffer,
useInvertClassification,
usePostProcessSelected
} = scene._environmentState;
const {
globeDepth,
globeTranslucencyFramebuffer,
sceneFramebuffer,
frustumCommandsList
} = scene._view;
const numFrustums = frustumCommandsList.length;
const globeTranslucencyState = scene._globeTranslucencyState;
const clearDepth = scene._depthClearCommand;
const clearStencil = scene._stencilClearCommand;
const clearClassificationStencil = scene._classificationStencilClearCommand;
const depthPlane = scene._depthPlane;
const height2D = camera.position.z;
function performPass(frustumCommands, passId) {
uniformState.updatePass(passId);
const commands = frustumCommands.commands[passId];
const commandCount = frustumCommands.indices[passId];
for (let j = 0; j < commandCount; ++j) {
executeCommand(commands[j], scene, passState);
}
return commandCount;
}
function performIdPass(frustumCommands, passId) {
uniformState.updatePass(passId);
const commands = frustumCommands.commands[passId];
const commandCount = frustumCommands.indices[passId];
for (let j = 0; j < commandCount; ++j) {
executeIdCommand(commands[j], scene, passState);
}
}
for (let i = 0; i < numFrustums; ++i) {
const index = numFrustums - i - 1;
const frustumCommands = frustumCommandsList[index];
if (scene.mode === SceneMode_default.SCENE2D) {
camera.position.z = height2D - frustumCommands.near + 1;
frustum.far = Math.max(1, frustumCommands.far - frustumCommands.near);
frustum.near = 1;
uniformState.update(frameState);
uniformState.updateFrustum(frustum);
} else {
frustum.near = index !== 0 ? frustumCommands.near * scene.opaqueFrustumNearOffset : frustumCommands.near;
frustum.far = frustumCommands.far;
uniformState.updateFrustum(frustum);
}
clearDepth.execute(context, passState);
if (context.stencilBuffer) {
clearStencil.execute(context, passState);
}
if (globeTranslucencyState.translucent) {
uniformState.updatePass(Pass_default.GLOBE);
globeTranslucencyState.executeGlobeCommands(
frustumCommands,
executeCommand,
globeTranslucencyFramebuffer,
scene,
passState
);
} else {
performPass(frustumCommands, Pass_default.GLOBE);
}
if (useGlobeDepthFramebuffer) {
globeDepth.executeCopyDepth(context, passState);
}
if (!renderTranslucentDepthForPick2) {
if (globeTranslucencyState.translucent) {
uniformState.updatePass(Pass_default.TERRAIN_CLASSIFICATION);
globeTranslucencyState.executeGlobeClassificationCommands(
frustumCommands,
executeCommand,
globeTranslucencyFramebuffer,
scene,
passState
);
} else {
performPass(frustumCommands, Pass_default.TERRAIN_CLASSIFICATION);
}
}
if (clearGlobeDepth) {
clearDepth.execute(context, passState);
if (useDepthPlane2) {
depthPlane.execute(context, passState);
}
}
let commandCount;
if (!useInvertClassification || picking || renderTranslucentDepthForPick2) {
commandCount = performPass(frustumCommands, Pass_default.CESIUM_3D_TILE);
if (commandCount > 0) {
if (useGlobeDepthFramebuffer) {
globeDepth.prepareColorTextures(context, clearGlobeDepth);
globeDepth.executeUpdateDepth(
context,
passState,
globeDepth.depthStencilTexture
);
}
if (!renderTranslucentDepthForPick2) {
commandCount = performPass(
frustumCommands,
Pass_default.CESIUM_3D_TILE_CLASSIFICATION
);
}
}
} else {
scene._invertClassification.clear(context, passState);
const opaqueClassificationFramebuffer = passState.framebuffer;
passState.framebuffer = scene._invertClassification._fbo.framebuffer;
commandCount = performPass(frustumCommands, Pass_default.CESIUM_3D_TILE);
if (useGlobeDepthFramebuffer) {
scene._invertClassification.prepareTextures(context);
globeDepth.executeUpdateDepth(
context,
passState,
scene._invertClassification._fbo.getDepthStencilTexture()
);
}
commandCount = performPass(
frustumCommands,
Pass_default.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW
);
passState.framebuffer = opaqueClassificationFramebuffer;
scene._invertClassification.executeClassified(context, passState);
if (frameState.invertClassificationColor.alpha === 1) {
scene._invertClassification.executeUnclassified(context, passState);
}
if (commandCount > 0 && context.stencilBuffer) {
clearClassificationStencil.execute(context, passState);
}
commandCount = performPass(
frustumCommands,
Pass_default.CESIUM_3D_TILE_CLASSIFICATION
);
}
if (commandCount > 0 && context.stencilBuffer) {
clearStencil.execute(context, passState);
}
performVoxelsPass(scene, passState, frustumCommands);
performPass(frustumCommands, Pass_default.OPAQUE);
performGaussianSplatPass(scene, passState, frustumCommands);
if (index !== 0 && scene.mode !== SceneMode_default.SCENE2D) {
frustum.near = frustumCommands.near;
uniformState.updateFrustum(frustum);
}
performTranslucentPass(scene, passState, frustumCommands);
performTranslucent3DTilesClassification(scene, passState, frustumCommands);
if (context.depthTexture && scene.useDepthPicking && (useGlobeDepthFramebuffer || renderTranslucentDepthForPick2)) {
const pickDepth = scene._picking.getPickDepth(scene, index);
pickDepth.update(context, globeDepth.depthStencilTexture);
pickDepth.executeCopyDepth(context, passState);
}
if (picking || !usePostProcessSelected) {
continue;
}
const originalFramebuffer = passState.framebuffer;
passState.framebuffer = sceneFramebuffer.getIdFramebuffer();
frustum.near = index !== 0 ? frustumCommands.near * scene.opaqueFrustumNearOffset : frustumCommands.near;
frustum.far = frustumCommands.far;
uniformState.updateFrustum(frustum);
if (globeTranslucencyState.translucent) {
uniformState.updatePass(Pass_default.GLOBE);
globeTranslucencyState.executeGlobeCommands(
frustumCommands,
executeIdCommand,
globeTranslucencyFramebuffer,
scene,
passState
);
} else {
performIdPass(frustumCommands, Pass_default.GLOBE);
}
if (clearGlobeDepth) {
clearDepth.framebuffer = passState.framebuffer;
clearDepth.execute(context, passState);
clearDepth.framebuffer = void 0;
}
if (clearGlobeDepth && useDepthPlane2) {
depthPlane.execute(context, passState);
}
performIdPass(frustumCommands, Pass_default.CESIUM_3D_TILE);
performIdPass(frustumCommands, Pass_default.OPAQUE);
performIdPass(frustumCommands, Pass_default.TRANSLUCENT);
passState.framebuffer = originalFramebuffer;
}
}
function renderEnvironment(scene, passState) {
const { context, environmentState, view } = scene;
context.uniformState.updatePass(Pass_default.ENVIRONMENT);
if (defined_default(environmentState.skyBoxCommand)) {
executeCommand(environmentState.skyBoxCommand, scene, passState);
}
if (environmentState.isSkyAtmosphereVisible) {
executeCommand(environmentState.skyAtmosphereCommand, scene, passState);
}
if (environmentState.isSunVisible) {
environmentState.sunDrawCommand.execute(context, passState);
if (scene.sunBloom && !environmentState.useWebVR) {
let framebuffer;
if (environmentState.useGlobeDepthFramebuffer) {
framebuffer = view.globeDepth.framebuffer;
} else if (environmentState.usePostProcess) {
framebuffer = view.sceneFramebuffer.framebuffer;
} else {
framebuffer = environmentState.originalFramebuffer;
}
scene._sunPostProcess.execute(context);
scene._sunPostProcess.copy(context, framebuffer);
passState.framebuffer = framebuffer;
}
}
if (environmentState.isMoonVisible) {
environmentState.moonCommand.execute(context, passState);
}
}
function executeComputeCommands(scene) {
scene.context.uniformState.updatePass(Pass_default.COMPUTE);
const sunComputeCommand = scene._environmentState.sunComputeCommand;
if (defined_default(sunComputeCommand)) {
sunComputeCommand.execute(scene._computeEngine);
}
const commandList = scene._computeCommandList;
for (let i = 0; i < commandList.length; ++i) {
commandList[i].execute(scene._computeEngine);
}
}
function executeOverlayCommands(scene, passState) {
scene.context.uniformState.updatePass(Pass_default.OVERLAY);
const context = scene.context;
const commandList = scene._overlayCommandList;
for (let i = 0; i < commandList.length; ++i) {
commandList[i].execute(context, passState);
}
}
function insertShadowCastCommands(scene, commandList, shadowMap) {
const { shadowMapCullingVolume, isPointLight, passes } = shadowMap;
const numberOfPasses = passes.length;
const shadowedPasses = [
Pass_default.GLOBE,
Pass_default.CESIUM_3D_TILE,
Pass_default.OPAQUE,
Pass_default.TRANSLUCENT
];
for (let i = 0; i < commandList.length; ++i) {
const command = commandList[i];
scene.updateDerivedCommands(command);
if (!command.castShadows || shadowedPasses.indexOf(command.pass) < 0 || !scene.isVisible(shadowMapCullingVolume, command)) {
continue;
}
if (isPointLight) {
for (let k = 0; k < numberOfPasses; ++k) {
passes[k].commandList.push(command);
}
} else if (numberOfPasses === 1) {
passes[0].commandList.push(command);
} else {
let wasVisible = false;
for (let j = numberOfPasses - 1; j >= 0; --j) {
const cascadeVolume = passes[j].cullingVolume;
if (scene.isVisible(cascadeVolume, command)) {
passes[j].commandList.push(command);
wasVisible = true;
} else if (wasVisible) {
break;
}
}
}
}
}
function executeShadowMapCastCommands(scene) {
const { shadowState, commandList } = scene.frameState;
const { shadowsEnabled, shadowMaps } = shadowState;
if (!shadowsEnabled) {
return;
}
const { context } = scene;
const { uniformState } = context;
for (let i = 0; i < shadowMaps.length; ++i) {
const shadowMap = shadowMaps[i];
if (shadowMap.outOfView) {
continue;
}
const { passes } = shadowMap;
for (let j = 0; j < passes.length; ++j) {
passes[j].commandList.length = 0;
}
insertShadowCastCommands(scene, commandList, shadowMap);
for (let j = 0; j < passes.length; ++j) {
const pass = shadowMap.passes[j];
const { camera, commandList: commandList2 } = pass;
uniformState.updateCamera(camera);
shadowMap.updatePass(context, j);
for (let k = 0; k < commandList2.length; ++k) {
const command = commandList2[k];
uniformState.updatePass(command.pass);
const castCommand = command.derivedCommands.shadows.castCommands[i];
executeCommand(castCommand, scene, pass.passState);
}
}
}
}
var scratchEyeTranslation = new Cartesian3_default();
Scene4.prototype.updateAndExecuteCommands = function(passState, backgroundColor) {
updateAndClearFramebuffers(this, passState, backgroundColor);
if (this._environmentState.useWebVR) {
executeWebVRCommands(this, passState, backgroundColor);
} else if (this._frameState.mode !== SceneMode_default.SCENE2D || this._mapMode2D === MapMode2D_default.ROTATE) {
executeCommandsInViewport(true, this, passState);
} else {
execute2DViewportCommands(this, passState);
}
};
function executeWebVRCommands(scene, passState) {
const view = scene._view;
const camera = view.camera;
const environmentState = scene._environmentState;
const renderTranslucentDepthForPick2 = environmentState.renderTranslucentDepthForPick;
updateAndRenderPrimitives(scene);
view.createPotentiallyVisibleSet(scene);
executeComputeCommands(scene);
if (!renderTranslucentDepthForPick2) {
executeShadowMapCastCommands(scene);
}
const viewport = passState.viewport;
viewport.x = 0;
viewport.y = 0;
viewport.width = viewport.width * 0.5;
const savedCamera = Camera_default.clone(camera, scene._cameraVR);
savedCamera.frustum = camera.frustum;
const near = camera.frustum.near;
const fo = near * (scene.focalLength ?? 5);
const eyeSeparation = scene.eyeSeparation ?? fo / 30;
const eyeTranslation = Cartesian3_default.multiplyByScalar(
savedCamera.right,
eyeSeparation * 0.5,
scratchEyeTranslation
);
camera.frustum.aspectRatio = viewport.width / viewport.height;
const offset = 0.5 * eyeSeparation * near / fo;
Cartesian3_default.add(savedCamera.position, eyeTranslation, camera.position);
camera.frustum.xOffset = offset;
executeCommands2(scene, passState);
viewport.x = viewport.width;
Cartesian3_default.subtract(savedCamera.position, eyeTranslation, camera.position);
camera.frustum.xOffset = -offset;
executeCommands2(scene, passState);
Camera_default.clone(savedCamera, camera);
}
var scratch2DViewportCartographic = new Cartographic_default(
Math.PI,
Math_default.PI_OVER_TWO
);
var scratch2DViewportMaxCoord = new Cartesian3_default();
var scratch2DViewportSavedPosition = new Cartesian3_default();
var scratch2DViewportTransform = new Matrix4_default();
var scratch2DViewportCameraTransform = new Matrix4_default();
var scratch2DViewportEyePoint = new Cartesian3_default();
var scratch2DViewportWindowCoords = new Cartesian3_default();
var scratch2DViewport = new BoundingRectangle_default();
function execute2DViewportCommands(scene, passState) {
const { frameState, camera } = scene;
const { uniformState } = scene.context;
const originalViewport = passState.viewport;
const viewport = BoundingRectangle_default.clone(originalViewport, scratch2DViewport);
passState.viewport = viewport;
const maxCartographic = scratch2DViewportCartographic;
const maxCoord = scratch2DViewportMaxCoord;
const projection = scene.mapProjection;
projection.project(maxCartographic, maxCoord);
const position = Cartesian3_default.clone(
camera.position,
scratch2DViewportSavedPosition
);
const transform3 = Matrix4_default.clone(
camera.transform,
scratch2DViewportCameraTransform
);
const frustum = camera.frustum.clone();
camera._setTransform(Matrix4_default.IDENTITY);
const viewportTransformation = Matrix4_default.computeViewportTransformation(
viewport,
0,
1,
scratch2DViewportTransform
);
const projectionMatrix = camera.frustum.projectionMatrix;
const x = camera.positionWC.y;
const eyePoint = Cartesian3_default.fromElements(
Math_default.sign(x) * maxCoord.x - x,
0,
-camera.positionWC.x,
scratch2DViewportEyePoint
);
const windowCoordinates = Transforms_default.pointToGLWindowCoordinates(
projectionMatrix,
viewportTransformation,
eyePoint,
scratch2DViewportWindowCoords
);
windowCoordinates.x = Math.floor(windowCoordinates.x);
const viewportX = viewport.x;
const viewportWidth = viewport.width;
if (x === 0 || windowCoordinates.x <= viewportX || windowCoordinates.x >= viewportX + viewportWidth) {
executeCommandsInViewport(true, scene, passState);
} else if (Math.abs(viewportX + viewportWidth * 0.5 - windowCoordinates.x) < 1) {
viewport.width = windowCoordinates.x - viewport.x;
camera.position.x *= Math_default.sign(camera.position.x);
camera.frustum.right = 0;
frameState.cullingVolume = camera.frustum.computeCullingVolume(
camera.positionWC,
camera.directionWC,
camera.upWC
);
uniformState.update(frameState);
executeCommandsInViewport(true, scene, passState);
viewport.x = windowCoordinates.x;
camera.position.x = -camera.position.x;
camera.frustum.right = -camera.frustum.left;
camera.frustum.left = 0;
frameState.cullingVolume = camera.frustum.computeCullingVolume(
camera.positionWC,
camera.directionWC,
camera.upWC
);
uniformState.update(frameState);
executeCommandsInViewport(false, scene, passState);
} else if (windowCoordinates.x > viewportX + viewportWidth * 0.5) {
viewport.width = windowCoordinates.x - viewportX;
const right = camera.frustum.right;
camera.frustum.right = maxCoord.x - x;
frameState.cullingVolume = camera.frustum.computeCullingVolume(
camera.positionWC,
camera.directionWC,
camera.upWC
);
uniformState.update(frameState);
executeCommandsInViewport(true, scene, passState);
viewport.x = windowCoordinates.x;
viewport.width = viewportX + viewportWidth - windowCoordinates.x;
camera.position.x = -camera.position.x;
camera.frustum.left = -camera.frustum.right;
camera.frustum.right = right - camera.frustum.right * 2;
frameState.cullingVolume = camera.frustum.computeCullingVolume(
camera.positionWC,
camera.directionWC,
camera.upWC
);
uniformState.update(frameState);
executeCommandsInViewport(false, scene, passState);
} else {
viewport.x = windowCoordinates.x;
viewport.width = viewportX + viewportWidth - windowCoordinates.x;
const left = camera.frustum.left;
camera.frustum.left = -maxCoord.x - x;
frameState.cullingVolume = camera.frustum.computeCullingVolume(
camera.positionWC,
camera.directionWC,
camera.upWC
);
uniformState.update(frameState);
executeCommandsInViewport(true, scene, passState);
viewport.x = viewportX;
viewport.width = windowCoordinates.x - viewportX;
camera.position.x = -camera.position.x;
camera.frustum.right = -camera.frustum.left;
camera.frustum.left = left - camera.frustum.left * 2;
frameState.cullingVolume = camera.frustum.computeCullingVolume(
camera.positionWC,
camera.directionWC,
camera.upWC
);
uniformState.update(frameState);
executeCommandsInViewport(false, scene, passState);
}
camera._setTransform(transform3);
Cartesian3_default.clone(position, camera.position);
camera.frustum = frustum.clone();
passState.viewport = originalViewport;
}
function executeCommandsInViewport(firstViewport, scene, passState) {
const view = scene._view;
const { renderTranslucentDepthForPick: renderTranslucentDepthForPick2 } = scene._environmentState;
if (!firstViewport) {
scene.frameState.commandList.length = 0;
}
updateAndRenderPrimitives(scene);
view.createPotentiallyVisibleSet(scene);
if (firstViewport) {
executeComputeCommands(scene);
if (!renderTranslucentDepthForPick2) {
executeShadowMapCastCommands(scene);
}
}
executeCommands2(scene, passState);
}
var scratchCullingVolume2 = new CullingVolume_default();
Scene4.prototype.updateEnvironment = function() {
const frameState = this._frameState;
const view = this._view;
const environmentState = this._environmentState;
const renderPass = frameState.passes.render;
const offscreenPass = frameState.passes.offscreen;
const atmosphere = this.atmosphere;
const skyAtmosphere = this.skyAtmosphere;
const globe = this.globe;
const globeTranslucencyState = this._globeTranslucencyState;
if (!renderPass || this._mode !== SceneMode_default.SCENE2D && view.camera.frustum instanceof OrthographicFrustum_default || !globeTranslucencyState.environmentVisible) {
environmentState.skyAtmosphereCommand = void 0;
environmentState.skyBoxCommand = void 0;
environmentState.sunDrawCommand = void 0;
environmentState.sunComputeCommand = void 0;
environmentState.moonCommand = void 0;
} else {
if (defined_default(skyAtmosphere)) {
if (defined_default(globe)) {
skyAtmosphere.setDynamicLighting(
DynamicAtmosphereLightingType_default.fromGlobeFlags(globe)
);
environmentState.isReadyForAtmosphere = environmentState.isReadyForAtmosphere || !globe.show || globe._surface._tilesToRender.length > 0;
} else {
const dynamicLighting = atmosphere.dynamicLighting;
skyAtmosphere.setDynamicLighting(dynamicLighting);
environmentState.isReadyForAtmosphere = true;
}
environmentState.skyAtmosphereCommand = skyAtmosphere.update(
frameState,
globe
);
if (defined_default(environmentState.skyAtmosphereCommand)) {
this.updateDerivedCommands(environmentState.skyAtmosphereCommand);
}
} else {
environmentState.skyAtmosphereCommand = void 0;
}
environmentState.skyBoxCommand = defined_default(this.skyBox) ? this.skyBox.update(frameState, this._hdr) : void 0;
const sunCommands = defined_default(this.sun) ? this.sun.update(frameState, view.passState, this._hdr) : void 0;
environmentState.sunDrawCommand = defined_default(sunCommands) ? sunCommands.drawCommand : void 0;
environmentState.sunComputeCommand = defined_default(sunCommands) ? sunCommands.computeCommand : void 0;
environmentState.moonCommand = defined_default(this.moon) ? this.moon.update(frameState) : void 0;
}
const clearGlobeDepth = environmentState.clearGlobeDepth = defined_default(globe) && globe.show && (!globe.depthTestAgainstTerrain || this.mode === SceneMode_default.SCENE2D);
const useDepthPlane2 = environmentState.useDepthPlane = clearGlobeDepth && this.mode === SceneMode_default.SCENE3D && globeTranslucencyState.useDepthPlane;
if (useDepthPlane2) {
this._depthPlane.update(frameState);
}
environmentState.renderTranslucentDepthForPick = false;
environmentState.useWebVR = this._useWebVR && this.mode !== SceneMode_default.SCENE2D && !offscreenPass;
const occluder = frameState.mode === SceneMode_default.SCENE3D && !globeTranslucencyState.sunVisibleThroughGlobe ? frameState.occluder : void 0;
let cullingVolume = frameState.cullingVolume;
const planes = scratchCullingVolume2.planes;
for (let k = 0; k < 5; ++k) {
planes[k] = cullingVolume.planes[k];
}
cullingVolume = scratchCullingVolume2;
environmentState.isSkyAtmosphereVisible = defined_default(environmentState.skyAtmosphereCommand) && environmentState.isReadyForAtmosphere;
environmentState.isSunVisible = this.isVisible(
cullingVolume,
environmentState.sunDrawCommand,
occluder
);
environmentState.isMoonVisible = this.isVisible(
cullingVolume,
environmentState.moonCommand,
occluder
);
const envMaps = this.specularEnvironmentMaps;
let specularEnvironmentCubeMap = this._specularEnvironmentCubeMap;
if (defined_default(envMaps) && specularEnvironmentCubeMap?.url !== envMaps) {
specularEnvironmentCubeMap = specularEnvironmentCubeMap && specularEnvironmentCubeMap.destroy();
this._specularEnvironmentCubeMap = new SpecularEnvironmentCubeMap_default(envMaps);
} else if (!defined_default(envMaps) && defined_default(specularEnvironmentCubeMap)) {
specularEnvironmentCubeMap.destroy();
this._specularEnvironmentCubeMap = void 0;
}
if (defined_default(this._specularEnvironmentCubeMap)) {
this._specularEnvironmentCubeMap.update(frameState);
}
};
function updateDebugFrustumPlanes(scene) {
const frameState = scene._frameState;
if (scene.debugShowFrustumPlanes !== scene._debugShowFrustumPlanes) {
if (scene.debugShowFrustumPlanes) {
scene._debugFrustumPlanes = new DebugCameraPrimitive_default({
camera: scene.camera,
updateOnChange: false,
frustumSplits: frameState.frustumSplits
});
} else {
scene._debugFrustumPlanes = scene._debugFrustumPlanes && scene._debugFrustumPlanes.destroy();
}
scene._debugShowFrustumPlanes = scene.debugShowFrustumPlanes;
}
if (defined_default(scene._debugFrustumPlanes)) {
scene._debugFrustumPlanes.update(frameState);
}
}
function updateShadowMaps(scene) {
const frameState = scene._frameState;
const { passes, shadowState, shadowMaps } = frameState;
const length2 = shadowMaps.length;
const shadowsEnabled = length2 > 0 && !passes.pick && !passes.pickVoxel && scene.mode === SceneMode_default.SCENE3D;
if (shadowsEnabled !== shadowState.shadowsEnabled) {
++shadowState.lastDirtyTime;
shadowState.shadowsEnabled = shadowsEnabled;
}
shadowState.lightShadowsEnabled = false;
if (!shadowsEnabled) {
return;
}
for (let j = 0; j < length2; ++j) {
if (shadowMaps[j] !== shadowState.shadowMaps[j]) {
++shadowState.lastDirtyTime;
break;
}
}
shadowState.shadowMaps.length = 0;
shadowState.lightShadowMaps.length = 0;
for (let i = 0; i < length2; ++i) {
const shadowMap = shadowMaps[i];
shadowMap.update(frameState);
shadowState.shadowMaps.push(shadowMap);
if (shadowMap.fromLightSource) {
shadowState.lightShadowMaps.push(shadowMap);
shadowState.lightShadowsEnabled = true;
}
if (shadowMap.dirty) {
++shadowState.lastDirtyTime;
shadowMap.dirty = false;
}
}
}
function updateAndRenderPrimitives(scene) {
const frameState = scene._frameState;
scene._groundPrimitives.update(frameState);
scene._primitives.update(frameState);
updateDebugFrustumPlanes(scene);
updateShadowMaps(scene);
if (scene._globe) {
scene._globe.render(frameState);
}
}
function updateAndClearFramebuffers(scene, passState, clearColor) {
const context = scene._context;
const frameState = scene._frameState;
const environmentState = scene._environmentState;
const view = scene._view;
const passes = frameState.passes;
const picking = passes.pick || passes.pickVoxel;
if (defined_default(view.globeDepth)) {
view.globeDepth.picking = picking;
}
const useWebVR = environmentState.useWebVR;
environmentState.originalFramebuffer = passState.framebuffer;
if (defined_default(scene.sun) && scene.sunBloom !== scene._sunBloom) {
if (scene.sunBloom && !useWebVR) {
scene._sunPostProcess = new SunPostProcess_default();
} else if (defined_default(scene._sunPostProcess)) {
scene._sunPostProcess = scene._sunPostProcess.destroy();
}
scene._sunBloom = scene.sunBloom;
} else if (!defined_default(scene.sun) && defined_default(scene._sunPostProcess)) {
scene._sunPostProcess = scene._sunPostProcess.destroy();
scene._sunBloom = false;
}
const clear2 = scene._clearColorCommand;
Color_default.clone(clearColor, clear2.color);
clear2.execute(context, passState);
const useGlobeDepthFramebuffer = environmentState.useGlobeDepthFramebuffer = defined_default(view.globeDepth);
if (useGlobeDepthFramebuffer) {
view.globeDepth.update(
context,
passState,
view.viewport,
scene.msaaSamples,
scene._hdr,
environmentState.clearGlobeDepth
);
view.globeDepth.clear(context, passState, clearColor);
}
const oit = view.oit;
const useOIT = environmentState.useOIT = !picking && defined_default(oit) && oit.isSupported();
if (useOIT) {
oit.update(
context,
passState,
view.globeDepth.colorFramebufferManager,
scene._hdr,
scene.msaaSamples
);
oit.clear(context, passState, clearColor);
environmentState.useOIT = oit.isSupported();
}
const postProcess = scene.postProcessStages;
let usePostProcess = environmentState.usePostProcess = !picking && (scene._hdr || postProcess.length > 0 || postProcess.ambientOcclusion.enabled || postProcess.fxaa.enabled || postProcess.bloom.enabled);
environmentState.usePostProcessSelected = false;
if (usePostProcess) {
view.sceneFramebuffer.update(
context,
view.viewport,
scene._hdr,
scene.msaaSamples
);
view.sceneFramebuffer.clear(context, passState, clearColor);
postProcess.update(context, frameState.useLogDepth, scene._hdr);
postProcess.clear(context);
usePostProcess = environmentState.usePostProcess = postProcess.ready;
environmentState.usePostProcessSelected = usePostProcess && postProcess.hasSelected;
}
if (environmentState.isSunVisible && scene.sunBloom && !useWebVR) {
passState.framebuffer = scene._sunPostProcess.update(passState);
scene._sunPostProcess.clear(context, passState, clearColor);
} else if (useGlobeDepthFramebuffer) {
passState.framebuffer = view.globeDepth.framebuffer;
} else if (usePostProcess) {
passState.framebuffer = view.sceneFramebuffer.framebuffer;
}
if (defined_default(passState.framebuffer)) {
clear2.execute(context, passState);
}
const useInvertClassification = environmentState.useInvertClassification = !picking && defined_default(passState.framebuffer) && scene.invertClassification;
if (useInvertClassification) {
let depthFramebuffer;
if (frameState.invertClassificationColor.alpha === 1) {
if (useGlobeDepthFramebuffer) {
depthFramebuffer = view.globeDepth.framebuffer;
}
}
if (defined_default(depthFramebuffer) || context.depthTexture) {
scene._invertClassification.previousFramebuffer = depthFramebuffer;
scene._invertClassification.update(
context,
scene.msaaSamples,
view.globeDepth.colorFramebufferManager
);
scene._invertClassification.clear(context, passState);
if (frameState.invertClassificationColor.alpha < 1 && useOIT) {
const command = scene._invertClassification.unclassifiedCommand;
const derivedCommands = command.derivedCommands;
derivedCommands.oit = oit.createDerivedCommands(
command,
context,
derivedCommands.oit
);
}
} else {
environmentState.useInvertClassification = false;
}
}
if (scene._globeTranslucencyState.translucent) {
view.globeTranslucencyFramebuffer.updateAndClear(
scene._hdr,
view.viewport,
context,
passState
);
}
}
Scene4.prototype.resolveFramebuffers = function(passState) {
const context = this._context;
const environmentState = this._environmentState;
const view = this._view;
const { globeDepth, translucentTileClassification } = view;
if (defined_default(globeDepth)) {
globeDepth.prepareColorTextures(context);
}
const {
useOIT,
useGlobeDepthFramebuffer,
usePostProcess,
originalFramebuffer
} = environmentState;
const globeFramebuffer = useGlobeDepthFramebuffer ? globeDepth.colorFramebufferManager : void 0;
const sceneFramebuffer = view.sceneFramebuffer._colorFramebuffer;
const idFramebuffer = view.sceneFramebuffer.idFramebuffer;
if (useOIT) {
passState.framebuffer = usePostProcess ? sceneFramebuffer.framebuffer : originalFramebuffer;
view.oit.execute(context, passState);
}
if (translucentTileClassification.hasTranslucentDepth && translucentTileClassification.isSupported()) {
translucentTileClassification.execute(this, passState);
}
if (usePostProcess) {
view.sceneFramebuffer.prepareColorTextures(context);
let inputFramebuffer = sceneFramebuffer;
if (useGlobeDepthFramebuffer && !useOIT) {
inputFramebuffer = globeFramebuffer;
}
const postProcess = this.postProcessStages;
const colorTexture = inputFramebuffer.getColorTexture(0);
const idTexture = idFramebuffer.getColorTexture(0);
const depthTexture = (globeFramebuffer ?? sceneFramebuffer).getDepthStencilTexture();
postProcess.execute(context, colorTexture, depthTexture, idTexture);
postProcess.copy(context, originalFramebuffer);
}
if (!useOIT && !usePostProcess && useGlobeDepthFramebuffer) {
passState.framebuffer = originalFramebuffer;
globeDepth.executeCopyColor(context, passState);
}
};
function callAfterRenderFunctions(scene) {
const functions = scene._frameState.afterRender;
for (let i = 0; i < functions.length; ++i) {
const shouldRequestRender = functions[i]();
if (shouldRequestRender) {
scene.requestRender();
}
}
functions.length = 0;
}
function getGlobeHeight(scene) {
if (scene.mode === SceneMode_default.MORPHING) {
return;
}
const cartographic2 = scene.camera.positionCartographic;
return scene.getHeight(cartographic2);
}
function getMaxPrimitiveHeight(primitive, cartographic2, scene) {
let maxHeight = Number.NEGATIVE_INFINITY;
if (primitive instanceof PrimitiveCollection_default) {
const length2 = primitive.length;
for (let i = 0; i < length2; ++i) {
const subPrimitive = primitive.get(i);
const subHeight = getMaxPrimitiveHeight(
subPrimitive,
cartographic2,
scene
);
if (defined_default(subHeight) && subHeight > maxHeight) {
maxHeight = subHeight;
}
}
} else if (primitive.isCesium3DTileset && primitive.show && primitive.enableCollision) {
const result = primitive.getHeight(cartographic2, scene);
if (defined_default(result) && result > maxHeight) {
return result;
}
}
return maxHeight;
}
Scene4.prototype.getHeight = function(cartographic2, heightReference) {
if (!defined_default(cartographic2)) {
return void 0;
}
const ignore3dTiles = heightReference === HeightReference_default.CLAMP_TO_TERRAIN || heightReference === HeightReference_default.RELATIVE_TO_TERRAIN;
const ignoreTerrain = heightReference === HeightReference_default.CLAMP_TO_3D_TILE || heightReference === HeightReference_default.RELATIVE_TO_3D_TILE;
if (!defined_default(cartographic2)) {
return;
}
let maxHeight = Number.NEGATIVE_INFINITY;
if (!ignore3dTiles) {
const maxPrimitiveHeight = getMaxPrimitiveHeight(
this.primitives,
cartographic2,
this
);
if (defined_default(maxPrimitiveHeight) && maxPrimitiveHeight > maxHeight) {
maxHeight = maxPrimitiveHeight;
}
}
const globe = this._globe;
if (!ignoreTerrain && defined_default(globe) && globe.show) {
const result = globe.getHeight(cartographic2);
if (result > maxHeight) {
maxHeight = result;
}
}
if (maxHeight > Number.NEGATIVE_INFINITY) {
return maxHeight;
}
return void 0;
};
var updateHeightScratchCartographic = new Cartographic_default();
Scene4.prototype.updateHeight = function(cartographic2, callback, heightReference) {
Check_default.typeOf.func("callback", callback);
const ellipsoid = this._ellipsoid;
const callbackWrapper = (clampedCartographic) => {
Cartographic_default.clone(cartographic2, updateHeightScratchCartographic);
let height;
if (defined_default(clampedCartographic)) {
height = clampedCartographic.height;
}
if (!defined_default(height)) {
height = this.getHeight(cartographic2, heightReference);
}
if (defined_default(height)) {
updateHeightScratchCartographic.height = height;
callback(updateHeightScratchCartographic);
}
};
const ignore3dTiles = heightReference === HeightReference_default.CLAMP_TO_TERRAIN || heightReference === HeightReference_default.RELATIVE_TO_TERRAIN;
const ignoreTerrain = heightReference === HeightReference_default.CLAMP_TO_3D_TILE || heightReference === HeightReference_default.RELATIVE_TO_3D_TILE;
let terrainRemoveCallback;
if (!ignoreTerrain && defined_default(this.globe)) {
terrainRemoveCallback = this.globe._surface.updateHeight(
cartographic2,
callbackWrapper
);
}
let tilesetRemoveCallbacks = {};
const createPrimitiveEventListener = (primitive) => {
if (ignore3dTiles || primitive.isDestroyed() || !primitive.isCesium3DTileset) {
return;
}
const tilesetRemoveCallback = primitive.updateHeight(
cartographic2,
callbackWrapper,
ellipsoid
);
tilesetRemoveCallbacks[primitive.id] = tilesetRemoveCallback;
};
if (!ignore3dTiles) {
const length2 = this.primitives.length;
for (let i = 0; i < length2; ++i) {
const primitive = this.primitives.get(i);
createPrimitiveEventListener(primitive);
}
}
const removeAddedListener = this.primitives.primitiveAdded.addEventListener(
createPrimitiveEventListener
);
const removeRemovedListener = this.primitives.primitiveRemoved.addEventListener((primitive) => {
if (primitive.isDestroyed() || !primitive.isCesium3DTileset) {
return;
}
if (defined_default(tilesetRemoveCallbacks[primitive.id])) {
tilesetRemoveCallbacks[primitive.id]();
}
delete tilesetRemoveCallbacks[primitive.id];
});
const removeCallback = () => {
terrainRemoveCallback = terrainRemoveCallback && terrainRemoveCallback();
Object.values(tilesetRemoveCallbacks).forEach(
(tilesetRemoveCallback) => tilesetRemoveCallback()
);
tilesetRemoveCallbacks = {};
removeAddedListener();
removeRemovedListener();
};
return removeCallback;
};
function isCameraUnderground(scene) {
const camera = scene.camera;
const mode2 = scene._mode;
const cameraController = scene._screenSpaceCameraController;
const cartographic2 = camera.positionCartographic;
if (!defined_default(cartographic2)) {
return false;
}
if (!cameraController.onMap() && cartographic2.height < 0) {
return true;
}
if (mode2 === SceneMode_default.SCENE2D || mode2 === SceneMode_default.MORPHING) {
return false;
}
const globeHeight = scene._globeHeight;
return defined_default(globeHeight) && cartographic2.height < globeHeight;
}
Scene4.prototype.initializeFrame = function() {
if (this._shaderFrameCount++ === 120) {
this._shaderFrameCount = 0;
this._context.shaderCache.destroyReleasedShaderPrograms();
this._context.textureCache.destroyReleasedTextures();
}
this._tweens.update();
if (this._globeHeightDirty) {
if (defined_default(this._removeUpdateHeightCallback)) {
this._removeUpdateHeightCallback();
this._removeUpdateHeightCallback = void 0;
}
this._globeHeight = getGlobeHeight(this);
this._globeHeightDirty = false;
const cartographic2 = this.camera.positionCartographic;
this._removeUpdateHeightCallback = this.updateHeight(
cartographic2,
(updatedCartographic) => {
if (this.isDestroyed()) {
return;
}
this._globeHeight = updatedCartographic.height;
}
);
}
this._cameraUnderground = isCameraUnderground(this);
this._globeTranslucencyState.update(this);
this._screenSpaceCameraController.update();
if (defined_default(this._deviceOrientationCameraController)) {
this._deviceOrientationCameraController.update();
}
this.camera.update(this._mode);
this.camera._updateCameraChanged();
};
function updateDebugShowFramesPerSecond(scene, renderedThisFrame) {
if (scene.debugShowFramesPerSecond) {
if (!defined_default(scene._performanceDisplay)) {
const performanceContainer = document.createElement("div");
performanceContainer.className = "cesium-performanceDisplay-defaultContainer";
const container = scene._canvas.parentNode;
container.appendChild(performanceContainer);
const performanceDisplay = new PerformanceDisplay_default({
container: performanceContainer
});
scene._performanceDisplay = performanceDisplay;
scene._performanceContainer = performanceContainer;
}
scene._performanceDisplay.throttled = scene.requestRenderMode;
scene._performanceDisplay.update(renderedThisFrame);
} else if (defined_default(scene._performanceDisplay)) {
scene._performanceDisplay = scene._performanceDisplay && scene._performanceDisplay.destroy();
scene._performanceContainer.parentNode.removeChild(
scene._performanceContainer
);
}
}
function prePassesUpdate(scene) {
scene._jobScheduler.resetBudgets();
const frameState = scene._frameState;
scene.primitives.prePassesUpdate(frameState);
if (defined_default(scene.globe)) {
scene.globe.update(frameState);
}
scene._picking.update();
frameState.creditDisplay.update();
}
function postPassesUpdate2(scene) {
scene.primitives.postPassesUpdate(scene._frameState);
RequestScheduler_default.update();
}
var scratchBackgroundColor = new Color_default();
function render(scene) {
const frameState = scene._frameState;
const context = scene.context;
const { uniformState } = context;
const view = scene._defaultView;
scene._view = view;
scene.updateFrameState();
frameState.passes.render = true;
frameState.passes.postProcess = scene.postProcessStages.hasSelected;
frameState.tilesetPassState = renderTilesetPassState;
let backgroundColor = scene.backgroundColor ?? Color_default.BLACK;
if (scene._hdr) {
backgroundColor = Color_default.clone(backgroundColor, scratchBackgroundColor);
backgroundColor.red = Math.pow(backgroundColor.red, scene.gamma);
backgroundColor.green = Math.pow(backgroundColor.green, scene.gamma);
backgroundColor.blue = Math.pow(backgroundColor.blue, scene.gamma);
}
frameState.backgroundColor = backgroundColor;
frameState.atmosphere = scene.atmosphere;
scene.fog.update(frameState);
uniformState.update(frameState);
const shadowMap = scene.shadowMap;
if (defined_default(shadowMap) && shadowMap.enabled) {
if (!defined_default(scene.light) || scene.light instanceof SunLight_default) {
Cartesian3_default.negate(
uniformState.sunDirectionWC,
scene._shadowMapCamera.direction
);
} else {
Cartesian3_default.clone(scene.light.direction, scene._shadowMapCamera.direction);
}
frameState.shadowMaps.push(shadowMap);
}
scene._computeCommandList.length = 0;
scene._overlayCommandList.length = 0;
const viewport = view.viewport;
viewport.x = 0;
viewport.y = 0;
viewport.width = context.drawingBufferWidth;
viewport.height = context.drawingBufferHeight;
const passState = view.passState;
passState.framebuffer = void 0;
passState.blendingEnabled = void 0;
passState.scissorTest = void 0;
passState.viewport = BoundingRectangle_default.clone(viewport, passState.viewport);
context.beginFrame();
if (defined_default(scene.globe)) {
scene.globe.beginFrame(frameState);
}
scene.updateEnvironment();
scene.updateAndExecuteCommands(passState, backgroundColor);
scene.resolveFramebuffers(passState);
passState.framebuffer = void 0;
executeOverlayCommands(scene, passState);
if (defined_default(scene.globe)) {
scene.globe.endFrame(frameState);
if (!scene.globe.tilesLoaded) {
scene._renderRequested = true;
}
}
context.endFrame();
}
function tryAndCatchError(scene, functionToExecute) {
try {
functionToExecute(scene);
} catch (error) {
scene._renderError.raiseEvent(scene, error);
if (scene.rethrowRenderErrors) {
throw error;
}
}
}
function updateMostDetailedRayPicks(scene) {
return scene._picking.updateMostDetailedRayPicks(scene);
}
Scene4.prototype.render = function(time) {
this._preUpdate.raiseEvent(this, time);
const frameState = this._frameState;
frameState.newFrame = false;
if (!defined_default(time)) {
time = JulianDate_default.now();
}
const cameraChanged = this._view.checkForCameraUpdates(this);
if (cameraChanged) {
this._globeHeightDirty = true;
}
let shouldRender = !this.requestRenderMode || this._renderRequested || cameraChanged || this._logDepthBufferDirty || this._hdrDirty || this.mode === SceneMode_default.MORPHING;
if (!shouldRender && defined_default(this.maximumRenderTimeChange) && defined_default(this._lastRenderTime)) {
const difference = Math.abs(
JulianDate_default.secondsDifference(this._lastRenderTime, time)
);
shouldRender = shouldRender || difference > this.maximumRenderTimeChange;
}
if (shouldRender) {
this._lastRenderTime = JulianDate_default.clone(time, this._lastRenderTime);
this._renderRequested = false;
this._logDepthBufferDirty = false;
this._hdrDirty = false;
const frameNumber = Math_default.incrementWrap(
frameState.frameNumber,
15e6,
1
);
updateFrameNumber(this, frameNumber, time);
frameState.newFrame = true;
}
tryAndCatchError(this, prePassesUpdate);
if (this.primitives.show) {
tryAndCatchError(this, updateMostDetailedRayPicks);
tryAndCatchError(this, updatePreloadPass);
tryAndCatchError(this, updatePreloadFlightPass);
if (!shouldRender) {
tryAndCatchError(this, updateRequestRenderModeDeferCheckPass);
}
}
this._postUpdate.raiseEvent(this, time);
if (shouldRender) {
this._preRender.raiseEvent(this, time);
frameState.creditDisplay.beginFrame();
tryAndCatchError(this, render);
}
updateDebugShowFramesPerSecond(this, shouldRender);
tryAndCatchError(this, postPassesUpdate2);
callAfterRenderFunctions(this);
if (shouldRender) {
this._postRender.raiseEvent(this, time);
frameState.creditDisplay.endFrame();
}
};
Scene4.prototype.forceRender = function(time) {
this._renderRequested = true;
this.render(time);
};
Scene4.prototype.requestRender = function() {
this._renderRequested = true;
};
Scene4.prototype.clampLineWidth = function(width) {
return Math.max(
ContextLimits_default.minimumAliasedLineWidth,
Math.min(width, ContextLimits_default.maximumAliasedLineWidth)
);
};
Scene4.prototype.pick = function(windowPosition, width, height) {
return this._picking.pick(this, windowPosition, width, height);
};
Scene4.prototype.pickVoxel = function(windowPosition, width, height) {
const pickedObject = this.pick(windowPosition, width, height);
if (!defined_default(pickedObject)) {
return;
}
const voxelPrimitive = pickedObject.primitive;
if (!(voxelPrimitive instanceof VoxelPrimitive_default)) {
return;
}
const voxelCoordinate = this._picking.pickVoxelCoordinate(
this,
windowPosition,
width,
height
);
const tileIndex = 255 * voxelCoordinate[0] + voxelCoordinate[1];
const keyframeNode = voxelPrimitive._traversal.findKeyframeNode(tileIndex);
if (!defined_default(keyframeNode)) {
return;
}
const sampleIndex = 255 * voxelCoordinate[2] + voxelCoordinate[3];
return VoxelCell_default.fromKeyframeNode(
voxelPrimitive,
tileIndex,
sampleIndex,
keyframeNode
);
};
Scene4.prototype.pickMetadata = function(windowPosition, schemaId, className, propertyName) {
Check_default.typeOf.object("windowPosition", windowPosition);
Check_default.typeOf.string("className", className);
Check_default.typeOf.string("propertyName", propertyName);
const pickedObject = this.pick(windowPosition);
if (!defined_default(pickedObject)) {
return void 0;
}
const structuralMetadata = pickedObject.detail?.model?.structuralMetadata;
if (!defined_default(structuralMetadata)) {
return void 0;
}
const schema = structuralMetadata.schema;
const classProperty = getMetadataClassProperty_default(
schema,
schemaId,
className,
propertyName
);
if (!defined_default(classProperty)) {
return void 0;
}
const metadataProperty = getMetadataProperty_default(
structuralMetadata,
className,
propertyName
);
if (!defined_default(metadataProperty)) {
return void 0;
}
const pickedMetadataInfo = new PickedMetadataInfo_default(
schemaId,
className,
propertyName,
classProperty,
metadataProperty
);
const pickedMetadataValues = this._picking.pickMetadata(
this,
windowPosition,
pickedMetadataInfo
);
return pickedMetadataValues;
};
Scene4.prototype.pickMetadataSchema = function(windowPosition) {
Check_default.typeOf.object("windowPosition", windowPosition);
const pickedObject = this.pick(windowPosition);
if (!defined_default(pickedObject)) {
return void 0;
}
const schema = pickedObject.detail?.model?.structuralMetadata?.schema;
return schema;
};
Scene4.prototype.pickPositionWorldCoordinates = function(windowPosition, result) {
return this._picking.pickPositionWorldCoordinates(
this,
windowPosition,
result
);
};
Scene4.prototype.pickPosition = function(windowPosition, result) {
return this._picking.pickPosition(this, windowPosition, result);
};
Scene4.prototype.drillPick = function(windowPosition, limit, width, height) {
return this._picking.drillPick(this, windowPosition, limit, width, height);
};
function updatePreloadPass(scene) {
const frameState = scene._frameState;
preloadTilesetPassState.camera = frameState.camera;
preloadTilesetPassState.cullingVolume = frameState.cullingVolume;
const primitives = scene.primitives;
primitives.updateForPass(frameState, preloadTilesetPassState);
}
function updatePreloadFlightPass(scene) {
const frameState = scene._frameState;
const camera = frameState.camera;
if (!camera.canPreloadFlight()) {
return;
}
preloadFlightTilesetPassState.camera = scene.preloadFlightCamera;
preloadFlightTilesetPassState.cullingVolume = scene.preloadFlightCullingVolume;
const primitives = scene.primitives;
primitives.updateForPass(frameState, preloadFlightTilesetPassState);
}
function updateRequestRenderModeDeferCheckPass(scene) {
scene.primitives.updateForPass(
scene._frameState,
requestRenderModeDeferCheckPassState
);
}
Scene4.prototype.pickFromRay = function(ray, objectsToExclude, width) {
return this._picking.pickFromRay(this, ray, objectsToExclude, width);
};
Scene4.prototype.drillPickFromRay = function(ray, limit, objectsToExclude, width) {
return this._picking.drillPickFromRay(
this,
ray,
limit,
objectsToExclude,
width
);
};
Scene4.prototype.pickFromRayMostDetailed = function(ray, objectsToExclude, width) {
return this._picking.pickFromRayMostDetailed(
this,
ray,
objectsToExclude,
width
);
};
Scene4.prototype.drillPickFromRayMostDetailed = function(ray, limit, objectsToExclude, width) {
return this._picking.drillPickFromRayMostDetailed(
this,
ray,
limit,
objectsToExclude,
width
);
};
Scene4.prototype.sampleHeight = function(position, objectsToExclude, width) {
return this._picking.sampleHeight(this, position, objectsToExclude, width);
};
Scene4.prototype.clampToHeight = function(cartesian11, objectsToExclude, width, result) {
return this._picking.clampToHeight(
this,
cartesian11,
objectsToExclude,
width,
result
);
};
Scene4.prototype.sampleHeightMostDetailed = function(positions, objectsToExclude, width) {
return this._picking.sampleHeightMostDetailed(
this,
positions,
objectsToExclude,
width
);
};
Scene4.prototype.clampToHeightMostDetailed = function(cartesians, objectsToExclude, width) {
return this._picking.clampToHeightMostDetailed(
this,
cartesians,
objectsToExclude,
width
);
};
Scene4.prototype.cartesianToCanvasCoordinates = function(position, result) {
return SceneTransforms_default.worldToWindowCoordinates(this, position, result);
};
Scene4.prototype.completeMorph = function() {
this._transitioner.completeMorph();
};
Scene4.prototype.morphTo2D = function(duration) {
duration = duration ?? 2;
this._transitioner.morphTo2D(duration, this._ellipsoid);
};
Scene4.prototype.morphToColumbusView = function(duration) {
duration = duration ?? 2;
this._transitioner.morphToColumbusView(duration, this._ellipsoid);
};
Scene4.prototype.morphTo3D = function(duration) {
duration = duration ?? 2;
this._transitioner.morphTo3D(duration, this._ellipsoid);
};
function setTerrain(scene, terrain) {
scene._removeTerrainProviderReadyListener = scene._removeTerrainProviderReadyListener && scene._removeTerrainProviderReadyListener();
if (terrain.ready) {
if (defined_default(scene.globe)) {
scene.globe.terrainProvider = terrain.provider;
}
return;
}
scene.globe.terrainProvider = void 0;
scene._removeTerrainProviderReadyListener = terrain.readyEvent.addEventListener((provider) => {
if (defined_default(scene) && defined_default(scene.globe)) {
scene.globe.terrainProvider = provider;
}
scene._removeTerrainProviderReadyListener();
});
}
Scene4.prototype.setTerrain = function(terrain) {
Check_default.typeOf.object("terrain", terrain);
setTerrain(this, terrain);
return terrain;
};
Scene4.prototype.isDestroyed = function() {
return false;
};
Scene4.prototype.destroy = function() {
this._tweens.removeAll();
this._computeEngine = this._computeEngine && this._computeEngine.destroy();
this._screenSpaceCameraController = this._screenSpaceCameraController && this._screenSpaceCameraController.destroy();
this._deviceOrientationCameraController = this._deviceOrientationCameraController && !this._deviceOrientationCameraController.isDestroyed() && this._deviceOrientationCameraController.destroy();
this._primitives = this._primitives && this._primitives.destroy();
this._groundPrimitives = this._groundPrimitives && this._groundPrimitives.destroy();
this._globe = this._globe && this._globe.destroy();
this._removeTerrainProviderReadyListener = this._removeTerrainProviderReadyListener && this._removeTerrainProviderReadyListener();
this.skyBox = this.skyBox && this.skyBox.destroy();
this.skyAtmosphere = this.skyAtmosphere && this.skyAtmosphere.destroy();
this._debugSphere = this._debugSphere && this._debugSphere.destroy();
this.sun = this.sun && this.sun.destroy();
this._sunPostProcess = this._sunPostProcess && this._sunPostProcess.destroy();
this._depthPlane = this._depthPlane && this._depthPlane.destroy();
this._transitioner = this._transitioner && this._transitioner.destroy();
this._debugFrustumPlanes = this._debugFrustumPlanes && this._debugFrustumPlanes.destroy();
this._brdfLutGenerator = this._brdfLutGenerator && this._brdfLutGenerator.destroy();
this._picking = this._picking && this._picking.destroy();
this._defaultView = this._defaultView && this._defaultView.destroy();
this._view = void 0;
if (this._removeCreditContainer) {
this._canvas.parentNode.removeChild(this._creditContainer);
}
this.postProcessStages = this.postProcessStages && this.postProcessStages.destroy();
this._context = this._context && this._context.destroy();
this._frameState.creditDisplay = this._frameState.creditDisplay && this._frameState.creditDisplay.destroy();
if (defined_default(this._performanceDisplay)) {
this._performanceDisplay = this._performanceDisplay && this._performanceDisplay.destroy();
this._performanceContainer.parentNode.removeChild(
this._performanceContainer
);
}
this._removeRequestListenerCallback();
this._removeTaskProcessorListenerCallback();
for (let i = 0; i < this._removeGlobeCallbacks.length; ++i) {
this._removeGlobeCallbacks[i]();
}
this._removeGlobeCallbacks.length = 0;
if (defined_default(this._removeUpdateHeightCallback)) {
this._removeUpdateHeightCallback();
this._removeUpdateHeightCallback = void 0;
}
return destroyObject_default(this);
};
var Scene_default = Scene4;
// packages/engine/Source/Scene/SkyAtmosphere.js
var import_InlineWorkers1166 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/SkyAtmosphereCommon.js
var import_InlineWorkers1163 = __toESM(require_InlineWorkers(), 1);
var SkyAtmosphereCommon_default = "float interpolateByDistance(vec4 nearFarScalar, float distance)\n{\n float startDistance = nearFarScalar.x;\n float startValue = nearFarScalar.y;\n float endDistance = nearFarScalar.z;\n float endValue = nearFarScalar.w;\n float t = clamp((distance - startDistance) / (endDistance - startDistance), 0.0, 1.0);\n return mix(startValue, endValue, t);\n}\n\nvoid computeAtmosphereScattering(vec3 positionWC, vec3 lightDirection, out vec3 rayleighColor, out vec3 mieColor, out float opacity, out float underTranslucentGlobe)\n{\n float ellipsoidRadiiDifference = czm_ellipsoidRadii.x - czm_ellipsoidRadii.z;\n\n // Adjustment to the atmosphere radius applied based on the camera height.\n float distanceAdjustMin = czm_ellipsoidRadii.x / 4.0;\n float distanceAdjustMax = czm_ellipsoidRadii.x;\n float distanceAdjustModifier = ellipsoidRadiiDifference / 2.0;\n float distanceAdjust = distanceAdjustModifier * clamp((czm_eyeHeight - distanceAdjustMin) / (distanceAdjustMax - distanceAdjustMin), 0.0, 1.0);\n\n // Since atmosphere scattering assumes the atmosphere is a spherical shell, we compute an inner radius of the atmosphere best fit\n // for the position on the ellipsoid.\n float radiusAdjust = (ellipsoidRadiiDifference / 4.0) + distanceAdjust;\n float atmosphereInnerRadius = (length(czm_viewerPositionWC) - czm_eyeHeight) - radiusAdjust;\n\n // Setup the primary ray: from the camera position to the vertex position.\n vec3 cameraToPositionWC = positionWC - czm_viewerPositionWC;\n vec3 cameraToPositionWCDirection = normalize(cameraToPositionWC);\n czm_ray primaryRay = czm_ray(czm_viewerPositionWC, cameraToPositionWCDirection);\n\n underTranslucentGlobe = 0.0;\n\n // Brighten the sky atmosphere under the Earth's atmosphere when translucency is enabled.\n #if defined(GLOBE_TRANSLUCENT)\n\n // Check for intersection with the inner radius of the atmopshere.\n czm_raySegment primaryRayEarthIntersect = czm_raySphereIntersectionInterval(primaryRay, vec3(0.0), atmosphereInnerRadius + radiusAdjust);\n if (primaryRayEarthIntersect.start > 0.0 && primaryRayEarthIntersect.stop > 0.0) {\n\n // Compute position on globe.\n vec3 direction = normalize(positionWC);\n czm_ray ellipsoidRay = czm_ray(positionWC, -direction);\n czm_raySegment ellipsoidIntersection = czm_rayEllipsoidIntersectionInterval(ellipsoidRay, vec3(0.0), czm_ellipsoidInverseRadii);\n vec3 onEarth = positionWC - (direction * ellipsoidIntersection.start);\n\n // Control the color using the camera angle.\n float angle = dot(normalize(czm_viewerPositionWC), normalize(onEarth));\n\n // Control the opacity using the distance from Earth.\n opacity = interpolateByDistance(vec4(0.0, 1.0, czm_ellipsoidRadii.x, 0.0), length(czm_viewerPositionWC - onEarth));\n vec3 horizonColor = vec3(0.1, 0.2, 0.3);\n vec3 nearColor = vec3(0.0);\n\n rayleighColor = mix(nearColor, horizonColor, exp(-angle) * opacity);\n\n // Set the traslucent flag to avoid alpha adjustment in computeFinalColor funciton.\n underTranslucentGlobe = 1.0;\n return;\n }\n #endif\n\n computeScattering(\n primaryRay,\n length(cameraToPositionWC),\n lightDirection,\n atmosphereInnerRadius,\n rayleighColor,\n mieColor,\n opacity\n );\n\n // Alter the opacity based on how close the viewer is to the ground.\n // (0.0 = At edge of atmosphere, 1.0 = On ground)\n float cameraHeight = czm_eyeHeight + atmosphereInnerRadius;\n float atmosphereOuterRadius = atmosphereInnerRadius + ATMOSPHERE_THICKNESS;\n opacity = clamp((atmosphereOuterRadius - cameraHeight) / (atmosphereOuterRadius - atmosphereInnerRadius), 0.0, 1.0);\n\n // Alter alpha based on time of day (0.0 = night , 1.0 = day)\n float nightAlpha = (u_radiiAndDynamicAtmosphereColor.z != 0.0) ? clamp(dot(normalize(positionWC), lightDirection), 0.0, 1.0) : 1.0;\n opacity *= pow(nightAlpha, 0.5);\n}\n";
// packages/engine/Source/Shaders/SkyAtmosphereFS.js
var import_InlineWorkers1164 = __toESM(require_InlineWorkers(), 1);
var SkyAtmosphereFS_default = "in vec3 v_outerPositionWC;\n\nuniform vec3 u_hsbShift;\n\n#ifndef PER_FRAGMENT_ATMOSPHERE\nin vec3 v_mieColor;\nin vec3 v_rayleighColor;\nin float v_opacity;\nin float v_translucent;\n#endif\n\nvoid main (void)\n{\n float lightEnum = u_radiiAndDynamicAtmosphereColor.z;\n vec3 lightDirection = czm_getDynamicAtmosphereLightDirection(v_outerPositionWC, lightEnum);\n\n vec3 mieColor;\n vec3 rayleighColor;\n float opacity;\n float translucent;\n\n #ifdef PER_FRAGMENT_ATMOSPHERE\n computeAtmosphereScattering(\n v_outerPositionWC,\n lightDirection,\n rayleighColor,\n mieColor,\n opacity,\n translucent\n );\n #else\n mieColor = v_mieColor;\n rayleighColor = v_rayleighColor;\n opacity = v_opacity;\n translucent = v_translucent;\n #endif\n\n vec4 color = computeAtmosphereColor(v_outerPositionWC, lightDirection, rayleighColor, mieColor, opacity);\n\n #ifndef HDR\n color.rgb = czm_pbrNeutralTonemapping(color.rgb);\n color.rgb = czm_inverseGamma(color.rgb);\n #endif\n\n #ifdef COLOR_CORRECT\n const bool ignoreBlackPixels = true;\n color.rgb = czm_applyHSBShift(color.rgb, u_hsbShift, ignoreBlackPixels);\n #endif\n\n // For the parts of the sky atmosphere that are not behind a translucent globe,\n // we mix in the default opacity so that the sky atmosphere still appears at distance.\n // This is needed because the opacity in the sky atmosphere is initially adjusted based\n // on the camera height.\n if (translucent == 0.0) {\n color.a = mix(color.b, 1.0, color.a) * smoothstep(0.0, 1.0, czm_morphTime);\n }\n\n out_FragColor = color;\n}\n";
// packages/engine/Source/Shaders/SkyAtmosphereVS.js
var import_InlineWorkers1165 = __toESM(require_InlineWorkers(), 1);
var SkyAtmosphereVS_default = "in vec4 position;\n\nout vec3 v_outerPositionWC;\n\n#ifndef PER_FRAGMENT_ATMOSPHERE\nout vec3 v_mieColor;\nout vec3 v_rayleighColor;\nout float v_opacity;\nout float v_translucent;\n#endif\n\nvoid main(void)\n{\n vec4 positionWC = czm_model * position;\n float lightEnum = u_radiiAndDynamicAtmosphereColor.z;\n vec3 lightDirection = czm_getDynamicAtmosphereLightDirection(positionWC.xyz, lightEnum);\n\n #ifndef PER_FRAGMENT_ATMOSPHERE\n computeAtmosphereScattering(\n positionWC.xyz,\n lightDirection,\n v_rayleighColor,\n v_mieColor,\n v_opacity,\n v_translucent\n );\n #endif\n\n v_outerPositionWC = positionWC.xyz;\n vec4 positionEC = czm_modelView * position;\n gl_Position = czm_projection * positionEC;\n}\n";
// packages/engine/Source/Scene/SkyAtmosphere.js
function SkyAtmosphere(ellipsoid) {
ellipsoid = ellipsoid ?? Ellipsoid_default.WGS84;
this.show = true;
this.perFragmentAtmosphere = false;
this._ellipsoid = ellipsoid;
const outerEllipsoidScale = 1.025;
const scaleVector = Cartesian3_default.multiplyByScalar(
ellipsoid.radii,
outerEllipsoidScale,
new Cartesian3_default()
);
this._scaleMatrix = Matrix4_default.fromScale(scaleVector);
this._modelMatrix = new Matrix4_default();
this._command = new DrawCommand_default({
owner: this,
modelMatrix: this._modelMatrix
});
this._spSkyFromSpace = void 0;
this._spSkyFromAtmosphere = void 0;
this._flags = void 0;
this.atmosphereLightIntensity = 50;
this.atmosphereRayleighCoefficient = new Cartesian3_default(55e-7, 13e-6, 284e-7);
this.atmosphereMieCoefficient = new Cartesian3_default(21e-6, 21e-6, 21e-6);
this.atmosphereRayleighScaleHeight = 1e4;
this.atmosphereMieScaleHeight = 3200;
this.atmosphereMieAnisotropy = 0.9;
this.hueShift = 0;
this.saturationShift = 0;
this.brightnessShift = 0;
this._hueSaturationBrightness = new Cartesian3_default();
const radiiAndDynamicAtmosphereColor = new Cartesian3_default();
radiiAndDynamicAtmosphereColor.x = ellipsoid.maximumRadius * outerEllipsoidScale;
radiiAndDynamicAtmosphereColor.y = ellipsoid.maximumRadius;
radiiAndDynamicAtmosphereColor.z = 0;
this._radiiAndDynamicAtmosphereColor = radiiAndDynamicAtmosphereColor;
const that = this;
this._command.uniformMap = {
u_radiiAndDynamicAtmosphereColor: function() {
return that._radiiAndDynamicAtmosphereColor;
},
u_hsbShift: function() {
that._hueSaturationBrightness.x = that.hueShift;
that._hueSaturationBrightness.y = that.saturationShift;
that._hueSaturationBrightness.z = that.brightnessShift;
return that._hueSaturationBrightness;
},
u_atmosphereLightIntensity: function() {
return that.atmosphereLightIntensity;
},
u_atmosphereRayleighCoefficient: function() {
return that.atmosphereRayleighCoefficient;
},
u_atmosphereMieCoefficient: function() {
return that.atmosphereMieCoefficient;
},
u_atmosphereRayleighScaleHeight: function() {
return that.atmosphereRayleighScaleHeight;
},
u_atmosphereMieScaleHeight: function() {
return that.atmosphereMieScaleHeight;
},
u_atmosphereMieAnisotropy: function() {
return that.atmosphereMieAnisotropy;
}
};
}
Object.defineProperties(SkyAtmosphere.prototype, {
/**
* Gets the ellipsoid the atmosphere is drawn around.
* @memberof SkyAtmosphere.prototype
*
* @type {Ellipsoid}
* @readonly
*/
ellipsoid: {
get: function() {
return this._ellipsoid;
}
}
});
SkyAtmosphere.prototype.setDynamicLighting = function(lightingEnum) {
this._radiiAndDynamicAtmosphereColor.z = lightingEnum;
};
var scratchModelMatrix3 = new Matrix4_default();
SkyAtmosphere.prototype.update = function(frameState, globe) {
if (!this.show) {
return void 0;
}
const mode2 = frameState.mode;
if (mode2 !== SceneMode_default.SCENE3D && mode2 !== SceneMode_default.MORPHING) {
return void 0;
}
if (!frameState.passes.render) {
return void 0;
}
const rotationMatrix = Matrix4_default.fromRotationTranslation(
frameState.context.uniformState.inverseViewRotation,
Cartesian3_default.ZERO,
scratchModelMatrix3
);
const rotationOffsetMatrix = Matrix4_default.multiplyTransformation(
rotationMatrix,
Axis_default.Y_UP_TO_Z_UP,
scratchModelMatrix3
);
const modelMatrix = Matrix4_default.multiply(
this._scaleMatrix,
rotationOffsetMatrix,
scratchModelMatrix3
);
Matrix4_default.clone(modelMatrix, this._modelMatrix);
const context = frameState.context;
const colorCorrect = hasColorCorrection(this);
const translucent = frameState.globeTranslucencyState.translucent;
const perFragmentAtmosphere = this.perFragmentAtmosphere || translucent || !defined_default(globe) || !globe.show;
const command = this._command;
if (!defined_default(command.vertexArray)) {
const geometry = EllipsoidGeometry_default.createGeometry(
new EllipsoidGeometry_default({
radii: new Cartesian3_default(1, 1, 1),
slicePartitions: 256,
stackPartitions: 256,
vertexFormat: VertexFormat_default.POSITION_ONLY
})
);
command.vertexArray = VertexArray_default.fromGeometry({
context,
geometry,
attributeLocations: GeometryPipeline_default.createAttributeLocations(geometry),
bufferUsage: BufferUsage_default.STATIC_DRAW
});
command.renderState = RenderState_default.fromCache({
cull: {
enabled: true,
face: CullFace_default.FRONT
},
blending: BlendingState_default.ALPHA_BLEND,
depthMask: false
});
}
const flags = colorCorrect | perFragmentAtmosphere << 2 | translucent << 3;
if (flags !== this._flags) {
this._flags = flags;
const defines = [];
if (colorCorrect) {
defines.push("COLOR_CORRECT");
}
if (perFragmentAtmosphere) {
defines.push("PER_FRAGMENT_ATMOSPHERE");
}
if (translucent) {
defines.push("GLOBE_TRANSLUCENT");
}
const vs = new ShaderSource_default({
defines,
sources: [AtmosphereCommon_default, SkyAtmosphereCommon_default, SkyAtmosphereVS_default]
});
const fs = new ShaderSource_default({
defines,
sources: [AtmosphereCommon_default, SkyAtmosphereCommon_default, SkyAtmosphereFS_default]
});
this._spSkyAtmosphere = ShaderProgram_default.fromCache({
context,
vertexShaderSource: vs,
fragmentShaderSource: fs
});
command.shaderProgram = this._spSkyAtmosphere;
}
return command;
};
function hasColorCorrection(skyAtmosphere) {
return !(Math_default.equalsEpsilon(
skyAtmosphere.hueShift,
0,
Math_default.EPSILON7
) && Math_default.equalsEpsilon(
skyAtmosphere.saturationShift,
0,
Math_default.EPSILON7
) && Math_default.equalsEpsilon(
skyAtmosphere.brightnessShift,
0,
Math_default.EPSILON7
));
}
SkyAtmosphere.prototype.isDestroyed = function() {
return false;
};
SkyAtmosphere.prototype.destroy = function() {
const command = this._command;
command.vertexArray = command.vertexArray && command.vertexArray.destroy();
this._spSkyAtmosphere = this._spSkyAtmosphere && this._spSkyAtmosphere.destroy();
return destroyObject_default(this);
};
var SkyAtmosphere_default = SkyAtmosphere;
// packages/engine/Source/Scene/SkyBox.js
var import_InlineWorkers1169 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/SkyBoxFS.js
var import_InlineWorkers1167 = __toESM(require_InlineWorkers(), 1);
var SkyBoxFS_default = "uniform samplerCube u_cubeMap;\n\nin vec3 v_texCoord;\n\nvoid main()\n{\n vec4 color = czm_textureCube(u_cubeMap, normalize(v_texCoord));\n out_FragColor = vec4(czm_gammaCorrect(color).rgb, czm_morphTime);\n}\n";
// packages/engine/Source/Shaders/SkyBoxVS.js
var import_InlineWorkers1168 = __toESM(require_InlineWorkers(), 1);
var SkyBoxVS_default = "in vec3 position;\nout vec3 v_texCoord;\n\nvoid main()\n{\n vec3 p = czm_viewRotation * (czm_temeToPseudoFixed * (czm_entireFrustum.y * position));\n gl_Position = czm_projection * vec4(p, 1.0);\n v_texCoord = position.xyz;\n}\n";
// packages/engine/Source/Scene/SkyBox.js
function SkyBox(options) {
this.sources = options.sources;
this._sources = void 0;
this.show = options.show ?? true;
this._command = new DrawCommand_default({
modelMatrix: Matrix4_default.clone(Matrix4_default.IDENTITY),
owner: this
});
this._cubeMap = void 0;
this._attributeLocations = void 0;
this._useHdr = void 0;
this._hasError = false;
this._error = void 0;
}
SkyBox.prototype.update = function(frameState, useHdr) {
const that = this;
const { mode: mode2, passes, context } = frameState;
if (!this.show) {
return void 0;
}
if (mode2 !== SceneMode_default.SCENE3D && mode2 !== SceneMode_default.MORPHING) {
return void 0;
}
if (!passes.render) {
return void 0;
}
if (this._hasError) {
const error = this._error;
this._hasError = false;
this._error = void 0;
throw error;
}
if (this._sources !== this.sources) {
this._sources = this.sources;
const sources = this.sources;
Check_default.defined("this.sources", sources);
if (Object.values(CubeMap_default.FaceName).some(
(faceName) => !defined_default(sources[faceName])
)) {
throw new DeveloperError_default(
"this.sources must have positiveX, negativeX, positiveY, negativeY, positiveZ, and negativeZ properties."
);
}
const sourceType = typeof sources.positiveX;
if (Object.values(CubeMap_default.FaceName).some(
(faceName) => typeof sources[faceName] !== sourceType
)) {
throw new DeveloperError_default(
"this.sources properties must all be the same type."
);
}
if (typeof sources.positiveX === "string") {
loadCubeMap_default(context, this._sources).then(function(cubeMap) {
that._cubeMap = that._cubeMap && that._cubeMap.destroy();
that._cubeMap = cubeMap;
}).catch((error) => {
this._hasError = true;
this._error = error;
});
} else {
this._cubeMap = this._cubeMap && this._cubeMap.destroy();
this._cubeMap = new CubeMap_default({
context,
source: sources
});
}
}
const command = this._command;
if (!defined_default(command.vertexArray)) {
command.uniformMap = {
u_cubeMap: function() {
return that._cubeMap;
}
};
const geometry = BoxGeometry_default.createGeometry(
BoxGeometry_default.fromDimensions({
dimensions: new Cartesian3_default(2, 2, 2),
vertexFormat: VertexFormat_default.POSITION_ONLY
})
);
const attributeLocations8 = this._attributeLocations = GeometryPipeline_default.createAttributeLocations(geometry);
command.vertexArray = VertexArray_default.fromGeometry({
context,
geometry,
attributeLocations: attributeLocations8,
bufferUsage: BufferUsage_default.STATIC_DRAW
});
command.renderState = RenderState_default.fromCache({
blending: BlendingState_default.ALPHA_BLEND
});
}
if (!defined_default(command.shaderProgram) || this._useHdr !== useHdr) {
const fs = new ShaderSource_default({
defines: [useHdr ? "HDR" : ""],
sources: [SkyBoxFS_default]
});
command.shaderProgram = ShaderProgram_default.fromCache({
context,
vertexShaderSource: SkyBoxVS_default,
fragmentShaderSource: fs,
attributeLocations: this._attributeLocations
});
this._useHdr = useHdr;
}
if (!defined_default(this._cubeMap)) {
return void 0;
}
return command;
};
SkyBox.prototype.isDestroyed = function() {
return false;
};
SkyBox.prototype.destroy = function() {
const command = this._command;
command.vertexArray = command.vertexArray && command.vertexArray.destroy();
command.shaderProgram = command.shaderProgram && command.shaderProgram.destroy();
this._cubeMap = this._cubeMap && this._cubeMap.destroy();
return destroyObject_default(this);
};
function getDefaultSkyBoxUrl(suffix) {
return buildModuleUrl_default(`Assets/Textures/SkyBox/tycho2t3_80_${suffix}.jpg`);
}
SkyBox.createEarthSkyBox = function() {
return new SkyBox({
sources: {
positiveX: getDefaultSkyBoxUrl("px"),
negativeX: getDefaultSkyBoxUrl("mx"),
positiveY: getDefaultSkyBoxUrl("py"),
negativeY: getDefaultSkyBoxUrl("my"),
positiveZ: getDefaultSkyBoxUrl("pz"),
negativeZ: getDefaultSkyBoxUrl("mz")
}
});
};
var SkyBox_default = SkyBox;
// packages/engine/Source/Scene/Sun.js
var import_InlineWorkers1173 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/SunFS.js
var import_InlineWorkers1170 = __toESM(require_InlineWorkers(), 1);
var SunFS_default = "uniform sampler2D u_texture;\n\nin vec2 v_textureCoordinates;\n\nvoid main()\n{\n vec4 color = texture(u_texture, v_textureCoordinates);\n out_FragColor = czm_gammaCorrect(color);\n}\n";
// packages/engine/Source/Shaders/SunTextureFS.js
var import_InlineWorkers1171 = __toESM(require_InlineWorkers(), 1);
var SunTextureFS_default = "uniform float u_radiusTS;\n\nin vec2 v_textureCoordinates;\n\nvec2 rotate(vec2 p, vec2 direction)\n{\n return vec2(p.x * direction.x - p.y * direction.y, p.x * direction.y + p.y * direction.x);\n}\n\nvec4 addBurst(vec2 position, vec2 direction, float lengthScalar)\n{\n vec2 rotatedPosition = rotate(position, direction) * vec2(25.0, 0.75);\n float radius = length(rotatedPosition) * lengthScalar;\n float burst = 1.0 - smoothstep(0.0, 0.55, radius);\n return vec4(burst);\n}\n\nvoid main()\n{\n float lengthScalar = 2.0 / sqrt(2.0);\n vec2 position = v_textureCoordinates - vec2(0.5);\n float radius = length(position) * lengthScalar;\n float surface = step(radius, u_radiusTS);\n vec4 color = vec4(vec2(1.0), surface + 0.2, surface);\n\n float glow = 1.0 - smoothstep(0.0, 0.55, radius);\n color.ba += mix(vec2(0.0), vec2(1.0), glow) * 0.75;\n\n vec4 burst = vec4(0.0);\n\n // The following loop has been manually unrolled for speed, to\n // avoid sin() and cos().\n //\n //for (float i = 0.4; i < 3.2; i += 1.047) {\n // vec2 direction = vec2(sin(i), cos(i));\n // burst += 0.4 * addBurst(position, direction, lengthScalar);\n //\n // direction = vec2(sin(i - 0.08), cos(i - 0.08));\n // burst += 0.3 * addBurst(position, direction, lengthScalar);\n //}\n\n burst += 0.4 * addBurst(position, vec2(0.38942, 0.92106), lengthScalar); // angle == 0.4\n burst += 0.4 * addBurst(position, vec2(0.99235, 0.12348), lengthScalar); // angle == 0.4 + 1.047\n burst += 0.4 * addBurst(position, vec2(0.60327, -0.79754), lengthScalar); // angle == 0.4 + 1.047 * 2.0\n\n burst += 0.3 * addBurst(position, vec2(0.31457, 0.94924), lengthScalar); // angle == 0.4 - 0.08\n burst += 0.3 * addBurst(position, vec2(0.97931, 0.20239), lengthScalar); // angle == 0.4 + 1.047 - 0.08\n burst += 0.3 * addBurst(position, vec2(0.66507, -0.74678), lengthScalar); // angle == 0.4 + 1.047 * 2.0 - 0.08\n\n // End of manual loop unrolling.\n\n color += clamp(burst, vec4(0.0), vec4(1.0)) * 0.15;\n\n out_FragColor = clamp(color, vec4(0.0), vec4(1.0));\n}\n";
// packages/engine/Source/Shaders/SunVS.js
var import_InlineWorkers1172 = __toESM(require_InlineWorkers(), 1);
var SunVS_default = "in vec2 direction;\n\nuniform float u_size;\n\nout vec2 v_textureCoordinates;\n\nvoid main() \n{\n vec4 position;\n if (czm_morphTime == 1.0)\n {\n position = vec4(czm_sunPositionWC, 1.0);\n }\n else\n {\n position = vec4(czm_sunPositionColumbusView.zxy, 1.0);\n }\n \n vec4 positionEC = czm_view * position;\n vec4 positionWC = czm_eyeToWindowCoordinates(positionEC);\n \n vec2 halfSize = vec2(u_size * 0.5);\n halfSize *= ((direction * 2.0) - 1.0);\n \n gl_Position = czm_viewportOrthographic * vec4(positionWC.xy + halfSize, -positionWC.z, 1.0);\n \n v_textureCoordinates = direction;\n}\n";
// packages/engine/Source/Scene/Sun.js
function Sun() {
this.show = true;
this._drawCommand = new DrawCommand_default({
primitiveType: PrimitiveType_default.TRIANGLES,
boundingVolume: new BoundingSphere_default(),
owner: this
});
this._commands = {
drawCommand: this._drawCommand,
computeCommand: void 0
};
this._boundingVolume = new BoundingSphere_default();
this._boundingVolume2D = new BoundingSphere_default();
this._texture = void 0;
this._drawingBufferWidth = void 0;
this._drawingBufferHeight = void 0;
this._radiusTS = void 0;
this._size = void 0;
this.glowFactor = 1;
this._glowFactorDirty = false;
this._useHdr = void 0;
const that = this;
this._uniformMap = {
u_texture: function() {
return that._texture;
},
u_size: function() {
return that._size;
}
};
}
Object.defineProperties(Sun.prototype, {
/**
* Gets or sets a number that controls how "bright" the Sun's lens flare appears
* to be. Zero shows just the Sun's disc without any flare.
* Use larger values for a more pronounced flare around the Sun.
*
* @memberof Sun.prototype
* @type {number}
* @default 1.0
*/
glowFactor: {
get: function() {
return this._glowFactor;
},
set: function(glowFactor) {
glowFactor = Math.max(glowFactor, 0);
this._glowFactor = glowFactor;
this._glowFactorDirty = true;
}
}
});
var scratchPositionWC = new Cartesian2_default();
var scratchLimbWC = new Cartesian2_default();
var scratchPositionEC = new Cartesian4_default();
var scratchCartesian47 = new Cartesian4_default();
Sun.prototype.update = function(frameState, passState, useHdr) {
if (!this.show) {
return void 0;
}
const mode2 = frameState.mode;
if (mode2 === SceneMode_default.SCENE2D || mode2 === SceneMode_default.MORPHING) {
return void 0;
}
if (!frameState.passes.render) {
return void 0;
}
const context = frameState.context;
const drawingBufferWidth = passState.viewport.width;
const drawingBufferHeight = passState.viewport.height;
if (!defined_default(this._texture) || drawingBufferWidth !== this._drawingBufferWidth || drawingBufferHeight !== this._drawingBufferHeight || this._glowFactorDirty || useHdr !== this._useHdr) {
this._texture = this._texture && this._texture.destroy();
this._drawingBufferWidth = drawingBufferWidth;
this._drawingBufferHeight = drawingBufferHeight;
this._glowFactorDirty = false;
this._useHdr = useHdr;
let size = Math.max(drawingBufferWidth, drawingBufferHeight);
size = Math.pow(2, Math.ceil(Math.log(size) / Math.log(2)) - 2);
size = Math.max(1, size);
const pixelDatatype = useHdr ? context.halfFloatingPointTexture ? PixelDatatype_default.HALF_FLOAT : PixelDatatype_default.FLOAT : PixelDatatype_default.UNSIGNED_BYTE;
this._texture = new Texture_default({
context,
width: size,
height: size,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype
});
this._glowLengthTS = this._glowFactor * 5;
this._radiusTS = 1 / (1 + 2 * this._glowLengthTS) * 0.5;
const that = this;
const uniformMap2 = {
u_radiusTS: function() {
return that._radiusTS;
}
};
this._commands.computeCommand = new ComputeCommand_default({
fragmentShaderSource: SunTextureFS_default,
outputTexture: this._texture,
uniformMap: uniformMap2,
persists: false,
owner: this,
postExecute: function() {
that._commands.computeCommand = void 0;
}
});
}
const drawCommand = this._drawCommand;
if (!defined_default(drawCommand.vertexArray)) {
const attributeLocations8 = {
direction: 0
};
const directions2 = new Uint8Array(4 * 2);
directions2[0] = 0;
directions2[1] = 0;
directions2[2] = 255;
directions2[3] = 0;
directions2[4] = 255;
directions2[5] = 255;
directions2[6] = 0;
directions2[7] = 255;
const vertexBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: directions2,
usage: BufferUsage_default.STATIC_DRAW
});
const attributes = [
{
index: attributeLocations8.direction,
vertexBuffer,
componentsPerAttribute: 2,
normalize: true,
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE
}
];
const indexBuffer = Buffer_default.createIndexBuffer({
context,
typedArray: new Uint16Array([0, 1, 2, 0, 2, 3]),
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype: IndexDatatype_default.UNSIGNED_SHORT
});
drawCommand.vertexArray = new VertexArray_default({
context,
attributes,
indexBuffer
});
drawCommand.shaderProgram = ShaderProgram_default.fromCache({
context,
vertexShaderSource: SunVS_default,
fragmentShaderSource: SunFS_default,
attributeLocations: attributeLocations8
});
drawCommand.renderState = RenderState_default.fromCache({
blending: BlendingState_default.ALPHA_BLEND
});
drawCommand.uniformMap = this._uniformMap;
}
const sunPosition = context.uniformState.sunPositionWC;
const sunPositionCV = context.uniformState.sunPositionColumbusView;
const boundingVolume = this._boundingVolume;
const boundingVolume2D = this._boundingVolume2D;
Cartesian3_default.clone(sunPosition, boundingVolume.center);
boundingVolume2D.center.x = sunPositionCV.z;
boundingVolume2D.center.y = sunPositionCV.x;
boundingVolume2D.center.z = sunPositionCV.y;
boundingVolume.radius = Math_default.SOLAR_RADIUS + Math_default.SOLAR_RADIUS * this._glowLengthTS;
boundingVolume2D.radius = boundingVolume.radius;
if (mode2 === SceneMode_default.SCENE3D) {
BoundingSphere_default.clone(boundingVolume, drawCommand.boundingVolume);
} else if (mode2 === SceneMode_default.COLUMBUS_VIEW) {
BoundingSphere_default.clone(boundingVolume2D, drawCommand.boundingVolume);
}
const position = SceneTransforms_default.computeActualEllipsoidPosition(
frameState,
sunPosition,
scratchCartesian47
);
const dist = Cartesian3_default.magnitude(
Cartesian3_default.subtract(
position,
frameState.camera.position,
scratchCartesian47
)
);
const projMatrix = context.uniformState.projection;
const positionEC = scratchPositionEC;
positionEC.x = 0;
positionEC.y = 0;
positionEC.z = -dist;
positionEC.w = 1;
const positionCC2 = Matrix4_default.multiplyByVector(
projMatrix,
positionEC,
scratchCartesian47
);
const positionWC2 = SceneTransforms_default.clipToGLWindowCoordinates(
passState.viewport,
positionCC2,
scratchPositionWC
);
positionEC.x = Math_default.SOLAR_RADIUS;
const limbCC = Matrix4_default.multiplyByVector(
projMatrix,
positionEC,
scratchCartesian47
);
const limbWC = SceneTransforms_default.clipToGLWindowCoordinates(
passState.viewport,
limbCC,
scratchLimbWC
);
this._size = Cartesian2_default.magnitude(
Cartesian2_default.subtract(limbWC, positionWC2, scratchCartesian47)
);
this._size = 2 * this._size * (1 + 2 * this._glowLengthTS);
this._size = Math.ceil(this._size);
return this._commands;
};
Sun.prototype.isDestroyed = function() {
return false;
};
Sun.prototype.destroy = function() {
const command = this._drawCommand;
command.vertexArray = command.vertexArray && command.vertexArray.destroy();
command.shaderProgram = command.shaderProgram && command.shaderProgram.destroy();
this._texture = this._texture && this._texture.destroy();
return destroyObject_default(this);
};
var Sun_default = Sun;
// packages/engine/Source/Scene/TimeDynamicPointCloud.js
var import_InlineWorkers1177 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/PointCloud.js
var import_InlineWorkers1176 = __toESM(require_InlineWorkers(), 1);
var import_mersenne_twister3 = __toESM(require_mersenne_twister(), 1);
// packages/engine/Source/Scene/getClipAndStyleCode.js
var import_InlineWorkers1174 = __toESM(require_InlineWorkers(), 1);
function getClipAndStyleCode(samplerUniformName, matrixUniformName, styleUniformName) {
Check_default.typeOf.string("samplerUniformName", samplerUniformName);
Check_default.typeOf.string("matrixUniformName", matrixUniformName);
Check_default.typeOf.string("styleUniformName", styleUniformName);
const shaderCode = ` float clipDistance = clip(gl_FragCoord, ${samplerUniformName}, ${matrixUniformName});
vec4 clippingPlanesEdgeColor = vec4(1.0);
clippingPlanesEdgeColor.rgb = ${styleUniformName}.rgb;
float clippingPlanesEdgeWidth = ${styleUniformName}.a;
if (clipDistance > 0.0 && clipDistance < clippingPlanesEdgeWidth)
{
out_FragColor = clippingPlanesEdgeColor;
}
`;
return shaderCode;
}
var getClipAndStyleCode_default = getClipAndStyleCode;
// packages/engine/Source/Scene/Splitter.js
var import_InlineWorkers1175 = __toESM(require_InlineWorkers(), 1);
var Splitter = {
/**
* Given a fragment shader string, returns a modified version of it that
* only renders on one side of the screen or the other. Fragments on the
* other side are discarded. The screen side is given by a uniform called
* `czm_splitDirection`, which can be added by calling
* {@link Splitter#addUniforms}, and the split position is given by an
* automatic uniform called `czm_splitPosition`.
*/
modifyFragmentShader: function modifyFragmentShader(shader) {
shader = ShaderSource_default.replaceMain(shader, "czm_splitter_main");
shader += // czm_splitPosition is not declared because it is an automatic uniform.
"uniform float czm_splitDirection; \nvoid main() \n{ \n#ifndef SHADOW_MAP\n if (czm_splitDirection < 0.0 && gl_FragCoord.x > czm_splitPosition) discard; \n if (czm_splitDirection > 0.0 && gl_FragCoord.x < czm_splitPosition) discard; \n#endif\n czm_splitter_main(); \n} \n";
return shader;
},
/**
* Add `czm_splitDirection` to the given uniform map.
*
* @param {object} object The object on which the `splitDirection` property may be found.
* @param {object} uniformMap The uniform map.
*/
addUniforms: function addUniforms(object2, uniformMap2) {
uniformMap2.czm_splitDirection = function() {
return object2.splitDirection;
};
}
};
var Splitter_default = Splitter;
// packages/engine/Source/Scene/PointCloud.js
var DecodingState = {
NEEDS_DECODE: 0,
DECODING: 1,
READY: 2,
FAILED: 3
};
function PointCloud(options) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.object("options.arrayBuffer", options.arrayBuffer);
this._parsedContent = void 0;
this._drawCommand = void 0;
this._isTranslucent = false;
this._styleTranslucent = false;
this._constantColor = Color_default.clone(Color_default.DARKGRAY);
this._highlightColor = Color_default.clone(Color_default.WHITE);
this._pointSize = 1;
this._rtcCenter = void 0;
this._quantizedVolumeScale = void 0;
this._quantizedVolumeOffset = void 0;
this._styleableShaderAttributes = void 0;
this._isQuantized = false;
this._isOctEncoded16P = false;
this._isRGB565 = false;
this._hasColors = false;
this._hasNormals = false;
this._hasBatchIds = false;
this._decodingState = DecodingState.READY;
this._dequantizeInShader = true;
this._isQuantizedDraco = false;
this._isOctEncodedDraco = false;
this._quantizedRange = 0;
this._octEncodedRange = 0;
this.backFaceCulling = false;
this._backFaceCulling = false;
this.normalShading = true;
this._normalShading = true;
this._opaqueRenderState = void 0;
this._translucentRenderState = void 0;
this._mode = void 0;
this._ready = false;
this._pointsLength = 0;
this._geometryByteLength = 0;
this._vertexShaderLoaded = options.vertexShaderLoaded;
this._fragmentShaderLoaded = options.fragmentShaderLoaded;
this._uniformMapLoaded = options.uniformMapLoaded;
this._batchTableLoaded = options.batchTableLoaded;
this._pickIdLoaded = options.pickIdLoaded;
this._opaquePass = options.opaquePass ?? Pass_default.OPAQUE;
this._cull = options.cull ?? true;
this.style = void 0;
this._style = void 0;
this.styleDirty = false;
this.modelMatrix = Matrix4_default.clone(Matrix4_default.IDENTITY);
this._modelMatrix = Matrix4_default.clone(Matrix4_default.IDENTITY);
this.time = 0;
this.shadows = ShadowMode_default.ENABLED;
this._boundingSphere = void 0;
this.clippingPlanes = void 0;
this.isClipped = false;
this.clippingPlanesDirty = false;
this.clippingPlanesOriginMatrix = void 0;
this.attenuation = false;
this._attenuation = false;
this.geometricError = 0;
this.geometricErrorScale = 1;
this.maximumAttenuation = this._pointSize;
this.splitDirection = options.splitDirection ?? SplitDirection_default.NONE;
this._splittingEnabled = false;
this._error = void 0;
initialize18(this, options);
}
Object.defineProperties(PointCloud.prototype, {
pointsLength: {
get: function() {
return this._pointsLength;
}
},
geometryByteLength: {
get: function() {
return this._geometryByteLength;
}
},
ready: {
get: function() {
return this._ready;
}
},
color: {
get: function() {
return Color_default.clone(this._highlightColor);
},
set: function(value) {
this._highlightColor = Color_default.clone(value, this._highlightColor);
}
},
boundingSphere: {
get: function() {
if (defined_default(this._drawCommand)) {
return this._drawCommand.boundingVolume;
}
return void 0;
},
set: function(value) {
this._boundingSphere = BoundingSphere_default.clone(value, this._boundingSphere);
}
}
});
function initialize18(pointCloud, options) {
const parsedContent = PntsParser_default.parse(
options.arrayBuffer,
options.byteOffset
);
pointCloud._parsedContent = parsedContent;
pointCloud._rtcCenter = parsedContent.rtcCenter;
pointCloud._hasNormals = parsedContent.hasNormals;
pointCloud._hasColors = parsedContent.hasColors;
pointCloud._hasBatchIds = parsedContent.hasBatchIds;
pointCloud._isTranslucent = parsedContent.isTranslucent;
if (!parsedContent.hasBatchIds && defined_default(parsedContent.batchTableBinary)) {
parsedContent.styleableProperties = Cesium3DTileBatchTable_default.getBinaryProperties(
parsedContent.pointsLength,
parsedContent.batchTableJson,
parsedContent.batchTableBinary
);
}
if (defined_default(parsedContent.draco)) {
const draco = parsedContent.draco;
pointCloud._decodingState = DecodingState.NEEDS_DECODE;
draco.dequantizeInShader = pointCloud._dequantizeInShader;
}
const positions = parsedContent.positions;
if (defined_default(positions)) {
pointCloud._isQuantized = positions.isQuantized;
pointCloud._quantizedVolumeScale = positions.quantizedVolumeScale;
pointCloud._quantizedVolumeOffset = positions.quantizedVolumeOffset;
pointCloud._quantizedRange = positions.quantizedRange;
}
const normals = parsedContent.normals;
if (defined_default(normals)) {
pointCloud._isOctEncoded16P = normals.octEncoded;
}
const colors = parsedContent.colors;
if (defined_default(colors)) {
if (defined_default(colors.constantColor)) {
pointCloud._constantColor = Color_default.clone(
colors.constantColor,
pointCloud._constantColor
);
pointCloud._hasColors = false;
}
pointCloud._isRGB565 = colors.isRGB565;
}
const batchIds = parsedContent.batchIds;
if (defined_default(parsedContent.batchIds)) {
batchIds.name = "BATCH_ID";
batchIds.semantic = "BATCH_ID";
batchIds.setIndex = void 0;
}
if (parsedContent.hasBatchIds) {
pointCloud._batchTableLoaded(
parsedContent.batchLength,
parsedContent.batchTableJson,
parsedContent.batchTableBinary
);
}
pointCloud._pointsLength = parsedContent.pointsLength;
}
var scratchMin5 = new Cartesian3_default();
var scratchMax5 = new Cartesian3_default();
var scratchPosition15 = new Cartesian3_default();
var randomNumberGenerator3;
var randomValues2;
function getRandomValues3(samplesLength) {
if (!defined_default(randomValues2)) {
randomNumberGenerator3 = new import_mersenne_twister3.default(0);
randomValues2 = new Array(samplesLength);
for (let i = 0; i < samplesLength; ++i) {
randomValues2[i] = randomNumberGenerator3.random();
}
}
return randomValues2;
}
function computeApproximateBoundingSphereFromPositions(positions) {
const maximumSamplesLength = 20;
const pointsLength = positions.length / 3;
const samplesLength = Math.min(pointsLength, maximumSamplesLength);
const randomValues3 = getRandomValues3(maximumSamplesLength);
const maxValue = Number.MAX_VALUE;
const minValue = -Number.MAX_VALUE;
const min3 = Cartesian3_default.fromElements(maxValue, maxValue, maxValue, scratchMin5);
const max3 = Cartesian3_default.fromElements(minValue, minValue, minValue, scratchMax5);
for (let i = 0; i < samplesLength; ++i) {
const index = Math.floor(randomValues3[i] * pointsLength);
const position = Cartesian3_default.unpack(positions, index * 3, scratchPosition15);
Cartesian3_default.minimumByComponent(min3, position, min3);
Cartesian3_default.maximumByComponent(max3, position, max3);
}
const boundingSphere = BoundingSphere_default.fromCornerPoints(min3, max3);
boundingSphere.radius += Math_default.EPSILON2;
return boundingSphere;
}
function prepareVertexAttribute(typedArray, name) {
const componentDatatype = ComponentDatatype_default.fromTypedArray(typedArray);
if (componentDatatype === ComponentDatatype_default.INT || componentDatatype === ComponentDatatype_default.UNSIGNED_INT || componentDatatype === ComponentDatatype_default.DOUBLE) {
oneTimeWarning_default(
"Cast pnts property to floats",
`Point cloud property "${name}" will be cast to a float array because INT, UNSIGNED_INT, and DOUBLE are not valid WebGL vertex attribute types. Some precision may be lost.`
);
return new Float32Array(typedArray);
}
return typedArray;
}
var scratchPointSizeAndTimeAndGeometricErrorAndDepthMultiplier = new Cartesian4_default();
var scratchQuantizedVolumeScaleAndOctEncodedRange = new Cartesian4_default();
var scratchColor27 = new Color_default();
var positionLocation = 0;
var colorLocation = 1;
var normalLocation = 2;
var batchIdLocation = 3;
var numberOfAttributes = 4;
var scratchClippingPlanesMatrix3 = new Matrix4_default();
var scratchInverseTransposeClippingPlanesMatrix2 = new Matrix4_default();
function createResources4(pointCloud, frameState) {
const context = frameState.context;
const parsedContent = pointCloud._parsedContent;
const pointsLength = pointCloud._pointsLength;
const positions = parsedContent.positions;
const colors = parsedContent.colors;
const normals = parsedContent.normals;
const batchIds = parsedContent.batchIds;
const styleableProperties = parsedContent.styleableProperties;
const hasStyleableProperties = defined_default(styleableProperties);
const isQuantized = pointCloud._isQuantized;
const isQuantizedDraco = pointCloud._isQuantizedDraco;
const isOctEncoded16P = pointCloud._isOctEncoded16P;
const isOctEncodedDraco = pointCloud._isOctEncodedDraco;
const quantizedRange = pointCloud._quantizedRange;
const octEncodedRange = pointCloud._octEncodedRange;
const isRGB565 = pointCloud._isRGB565;
const isTranslucent = pointCloud._isTranslucent;
const hasColors = pointCloud._hasColors;
const hasNormals = pointCloud._hasNormals;
const hasBatchIds = pointCloud._hasBatchIds;
let componentsPerAttribute;
let componentDatatype;
const styleableVertexAttributes = [];
const styleableShaderAttributes = {};
pointCloud._styleableShaderAttributes = styleableShaderAttributes;
if (hasStyleableProperties) {
let attributeLocation = numberOfAttributes;
for (const name in styleableProperties) {
if (styleableProperties.hasOwnProperty(name)) {
const property = styleableProperties[name];
const typedArray = prepareVertexAttribute(property.typedArray, name);
componentsPerAttribute = property.componentCount;
componentDatatype = ComponentDatatype_default.fromTypedArray(typedArray);
const vertexBuffer = Buffer_default.createVertexBuffer({
context,
typedArray,
usage: BufferUsage_default.STATIC_DRAW
});
pointCloud._geometryByteLength += vertexBuffer.sizeInBytes;
const vertexAttribute = {
index: attributeLocation,
vertexBuffer,
componentsPerAttribute,
componentDatatype,
normalize: false,
offsetInBytes: 0,
strideInBytes: 0
};
styleableVertexAttributes.push(vertexAttribute);
styleableShaderAttributes[name] = {
location: attributeLocation,
componentCount: componentsPerAttribute
};
++attributeLocation;
}
}
}
const positionsVertexBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: positions.typedArray,
usage: BufferUsage_default.STATIC_DRAW
});
pointCloud._geometryByteLength += positionsVertexBuffer.sizeInBytes;
let colorsVertexBuffer;
if (hasColors) {
colorsVertexBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: colors.typedArray,
usage: BufferUsage_default.STATIC_DRAW
});
pointCloud._geometryByteLength += colorsVertexBuffer.sizeInBytes;
}
let normalsVertexBuffer;
if (hasNormals) {
normalsVertexBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: normals.typedArray,
usage: BufferUsage_default.STATIC_DRAW
});
pointCloud._geometryByteLength += normalsVertexBuffer.sizeInBytes;
}
let batchIdsVertexBuffer;
if (hasBatchIds) {
batchIds.typedArray = prepareVertexAttribute(
batchIds.typedArray,
"batchIds"
);
batchIdsVertexBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: batchIds.typedArray,
usage: BufferUsage_default.STATIC_DRAW
});
pointCloud._geometryByteLength += batchIdsVertexBuffer.sizeInBytes;
}
let attributes = [];
if (isQuantized) {
componentDatatype = ComponentDatatype_default.UNSIGNED_SHORT;
} else if (isQuantizedDraco) {
componentDatatype = quantizedRange <= 255 ? ComponentDatatype_default.UNSIGNED_BYTE : ComponentDatatype_default.UNSIGNED_SHORT;
} else {
componentDatatype = ComponentDatatype_default.FLOAT;
}
attributes.push({
index: positionLocation,
vertexBuffer: positionsVertexBuffer,
componentsPerAttribute: 3,
componentDatatype,
normalize: false,
offsetInBytes: 0,
strideInBytes: 0
});
if (pointCloud._cull) {
if (isQuantized || isQuantizedDraco) {
pointCloud._boundingSphere = BoundingSphere_default.fromCornerPoints(
Cartesian3_default.ZERO,
pointCloud._quantizedVolumeScale
);
} else {
pointCloud._boundingSphere = computeApproximateBoundingSphereFromPositions(positions.typedArray);
}
}
if (hasColors) {
if (isRGB565) {
attributes.push({
index: colorLocation,
vertexBuffer: colorsVertexBuffer,
componentsPerAttribute: 1,
componentDatatype: ComponentDatatype_default.UNSIGNED_SHORT,
normalize: false,
offsetInBytes: 0,
strideInBytes: 0
});
} else {
const colorComponentsPerAttribute = isTranslucent ? 4 : 3;
attributes.push({
index: colorLocation,
vertexBuffer: colorsVertexBuffer,
componentsPerAttribute: colorComponentsPerAttribute,
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
normalize: true,
offsetInBytes: 0,
strideInBytes: 0
});
}
}
if (hasNormals) {
if (isOctEncoded16P) {
componentsPerAttribute = 2;
componentDatatype = ComponentDatatype_default.UNSIGNED_BYTE;
} else if (isOctEncodedDraco) {
componentsPerAttribute = 2;
componentDatatype = octEncodedRange <= 255 ? ComponentDatatype_default.UNSIGNED_BYTE : ComponentDatatype_default.UNSIGNED_SHORT;
} else {
componentsPerAttribute = 3;
componentDatatype = ComponentDatatype_default.FLOAT;
}
attributes.push({
index: normalLocation,
vertexBuffer: normalsVertexBuffer,
componentsPerAttribute,
componentDatatype,
normalize: false,
offsetInBytes: 0,
strideInBytes: 0
});
}
if (hasBatchIds) {
attributes.push({
index: batchIdLocation,
vertexBuffer: batchIdsVertexBuffer,
componentsPerAttribute: 1,
componentDatatype: ComponentDatatype_default.fromTypedArray(batchIds.typedArray),
normalize: false,
offsetInBytes: 0,
strideInBytes: 0
});
}
if (hasStyleableProperties) {
attributes = attributes.concat(styleableVertexAttributes);
}
const vertexArray = new VertexArray_default({
context,
attributes
});
const opaqueRenderState = {
depthTest: {
enabled: true
}
};
const translucentRenderState = {
depthTest: {
enabled: true
},
depthMask: false,
blending: BlendingState_default.ALPHA_BLEND
};
if (pointCloud._opaquePass === Pass_default.CESIUM_3D_TILE) {
opaqueRenderState.stencilTest = StencilConstants_default.setCesium3DTileBit();
opaqueRenderState.stencilMask = StencilConstants_default.CESIUM_3D_TILE_MASK;
translucentRenderState.stencilTest = StencilConstants_default.setCesium3DTileBit();
translucentRenderState.stencilMask = StencilConstants_default.CESIUM_3D_TILE_MASK;
}
pointCloud._opaqueRenderState = RenderState_default.fromCache(opaqueRenderState);
pointCloud._translucentRenderState = RenderState_default.fromCache(
translucentRenderState
);
pointCloud._drawCommand = new DrawCommand_default({
boundingVolume: new BoundingSphere_default(),
cull: pointCloud._cull,
modelMatrix: new Matrix4_default(),
primitiveType: PrimitiveType_default.POINTS,
vertexArray,
count: pointsLength,
shaderProgram: void 0,
// Updated in createShaders
uniformMap: void 0,
// Updated in createShaders
renderState: isTranslucent ? pointCloud._translucentRenderState : pointCloud._opaqueRenderState,
pass: isTranslucent ? Pass_default.TRANSLUCENT : pointCloud._opaquePass,
owner: pointCloud,
castShadows: false,
receiveShadows: false,
pickId: pointCloud._pickIdLoaded()
});
}
function createUniformMap6(pointCloud, frameState) {
const context = frameState.context;
const isQuantized = pointCloud._isQuantized;
const isQuantizedDraco = pointCloud._isQuantizedDraco;
const isOctEncodedDraco = pointCloud._isOctEncodedDraco;
let uniformMap2 = {
u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier: function() {
const scratch = scratchPointSizeAndTimeAndGeometricErrorAndDepthMultiplier;
scratch.x = pointCloud._attenuation ? pointCloud.maximumAttenuation : pointCloud._pointSize;
scratch.x *= frameState.pixelRatio;
scratch.y = pointCloud.time;
if (pointCloud._attenuation) {
const frustum = frameState.camera.frustum;
let depthMultiplier;
if (frameState.mode === SceneMode_default.SCENE2D || frustum instanceof OrthographicFrustum_default) {
depthMultiplier = Number.POSITIVE_INFINITY;
} else {
depthMultiplier = context.drawingBufferHeight / frameState.camera.frustum.sseDenominator;
}
scratch.z = pointCloud.geometricError * pointCloud.geometricErrorScale;
scratch.w = depthMultiplier;
}
return scratch;
},
u_highlightColor: function() {
return pointCloud._highlightColor;
},
u_constantColor: function() {
return pointCloud._constantColor;
},
u_clippingPlanes: function() {
const clippingPlanes = pointCloud.clippingPlanes;
const isClipped = pointCloud.isClipped;
return isClipped ? clippingPlanes.texture : context.defaultTexture;
},
u_clippingPlanesEdgeStyle: function() {
const clippingPlanes = pointCloud.clippingPlanes;
if (!defined_default(clippingPlanes)) {
return Color_default.TRANSPARENT;
}
const style = Color_default.clone(clippingPlanes.edgeColor, scratchColor27);
style.alpha = clippingPlanes.edgeWidth;
return style;
},
u_clippingPlanesMatrix: function() {
const clippingPlanes = pointCloud.clippingPlanes;
if (!defined_default(clippingPlanes)) {
return Matrix4_default.IDENTITY;
}
const clippingPlanesOriginMatrix = pointCloud.clippingPlanesOriginMatrix ?? pointCloud._modelMatrix;
Matrix4_default.multiply(
context.uniformState.view3D,
clippingPlanesOriginMatrix,
scratchClippingPlanesMatrix3
);
const transform3 = Matrix4_default.multiply(
scratchClippingPlanesMatrix3,
clippingPlanes.modelMatrix,
scratchClippingPlanesMatrix3
);
return Matrix4_default.inverseTranspose(
transform3,
scratchInverseTransposeClippingPlanesMatrix2
);
}
};
Splitter_default.addUniforms(pointCloud, uniformMap2);
if (isQuantized || isQuantizedDraco || isOctEncodedDraco) {
uniformMap2 = combine_default(uniformMap2, {
u_quantizedVolumeScaleAndOctEncodedRange: function() {
const scratch = scratchQuantizedVolumeScaleAndOctEncodedRange;
if (defined_default(pointCloud._quantizedVolumeScale)) {
const scale = Cartesian3_default.clone(
pointCloud._quantizedVolumeScale,
scratch
);
Cartesian3_default.divideByScalar(scale, pointCloud._quantizedRange, scratch);
}
scratch.w = pointCloud._octEncodedRange;
return scratch;
}
});
}
if (defined_default(pointCloud._uniformMapLoaded)) {
uniformMap2 = pointCloud._uniformMapLoaded(uniformMap2);
}
pointCloud._drawCommand.uniformMap = uniformMap2;
}
function getStyleablePropertyIds(source, propertyIds) {
const regex = /czm_3dtiles_property_(\d+)/g;
let matches = regex.exec(source);
while (matches !== null) {
const id = parseInt(matches[1]);
if (propertyIds.indexOf(id) === -1) {
propertyIds.push(id);
}
matches = regex.exec(source);
}
}
function getBuiltinPropertyNames2(source, propertyNames) {
source = source.slice(source.indexOf("\n"));
const regex = /czm_3dtiles_builtin_property_(\w+)/g;
let matches = regex.exec(source);
while (matches !== null) {
const name = matches[1];
if (propertyNames.indexOf(name) === -1) {
propertyNames.push(name);
}
matches = regex.exec(source);
}
}
function getVertexAttribute(vertexArray, index) {
const numberOfAttributes2 = vertexArray.numberOfAttributes;
for (let i = 0; i < numberOfAttributes2; ++i) {
const attribute = vertexArray.getAttribute(i);
if (attribute.index === index) {
return attribute;
}
}
}
var builtinVariableSubstitutionMap2 = {
POSITION: "czm_3dtiles_builtin_property_POSITION",
POSITION_ABSOLUTE: "czm_3dtiles_builtin_property_POSITION_ABSOLUTE",
COLOR: "czm_3dtiles_builtin_property_COLOR",
NORMAL: "czm_3dtiles_builtin_property_NORMAL"
};
function createShaders4(pointCloud, frameState, style) {
let i;
let name;
let attribute;
const context = frameState.context;
const hasStyle = defined_default(style);
const isQuantized = pointCloud._isQuantized;
const isQuantizedDraco = pointCloud._isQuantizedDraco;
const isOctEncoded16P = pointCloud._isOctEncoded16P;
const isOctEncodedDraco = pointCloud._isOctEncodedDraco;
const isRGB565 = pointCloud._isRGB565;
const isTranslucent = pointCloud._isTranslucent;
const hasColors = pointCloud._hasColors;
const hasNormals = pointCloud._hasNormals;
const hasBatchIds = pointCloud._hasBatchIds;
const backFaceCulling = pointCloud._backFaceCulling;
const normalShading = pointCloud._normalShading;
const vertexArray = pointCloud._drawCommand.vertexArray;
const clippingPlanes = pointCloud.clippingPlanes;
const attenuation = pointCloud._attenuation;
let colorStyleFunction;
let showStyleFunction;
let pointSizeStyleFunction;
let styleTranslucent = isTranslucent;
const variableSubstitutionMap = clone_default(builtinVariableSubstitutionMap2);
const propertyIdToAttributeMap = {};
const styleableShaderAttributes = pointCloud._styleableShaderAttributes;
for (name in styleableShaderAttributes) {
if (styleableShaderAttributes.hasOwnProperty(name)) {
attribute = styleableShaderAttributes[name];
variableSubstitutionMap[name] = `czm_3dtiles_property_${attribute.location}`;
propertyIdToAttributeMap[attribute.location] = attribute;
}
}
if (hasStyle) {
const shaderState = {
translucent: false
};
const parameterList2 = "(vec3 czm_3dtiles_builtin_property_POSITION, vec3 czm_3dtiles_builtin_property_POSITION_ABSOLUTE, vec4 czm_3dtiles_builtin_property_COLOR, vec3 czm_3dtiles_builtin_property_NORMAL)";
colorStyleFunction = style.getColorShaderFunction(
`getColorFromStyle${parameterList2}`,
variableSubstitutionMap,
shaderState
);
showStyleFunction = style.getShowShaderFunction(
`getShowFromStyle${parameterList2}`,
variableSubstitutionMap,
shaderState
);
pointSizeStyleFunction = style.getPointSizeShaderFunction(
`getPointSizeFromStyle${parameterList2}`,
variableSubstitutionMap,
shaderState
);
if (defined_default(colorStyleFunction) && shaderState.translucent) {
styleTranslucent = true;
}
}
pointCloud._styleTranslucent = styleTranslucent;
const hasColorStyle = defined_default(colorStyleFunction);
const hasShowStyle = defined_default(showStyleFunction);
const hasPointSizeStyle = defined_default(pointSizeStyleFunction);
const hasClippedContent = pointCloud.isClipped;
const styleablePropertyIds = [];
const builtinPropertyNames = [];
if (hasColorStyle) {
getStyleablePropertyIds(colorStyleFunction, styleablePropertyIds);
getBuiltinPropertyNames2(colorStyleFunction, builtinPropertyNames);
}
if (hasShowStyle) {
getStyleablePropertyIds(showStyleFunction, styleablePropertyIds);
getBuiltinPropertyNames2(showStyleFunction, builtinPropertyNames);
}
if (hasPointSizeStyle) {
getStyleablePropertyIds(pointSizeStyleFunction, styleablePropertyIds);
getBuiltinPropertyNames2(pointSizeStyleFunction, builtinPropertyNames);
}
const usesColorSemantic = builtinPropertyNames.indexOf("COLOR") >= 0;
const usesNormalSemantic = builtinPropertyNames.indexOf("NORMAL") >= 0;
if (usesNormalSemantic && !hasNormals) {
throw new RuntimeError_default(
"Style references the NORMAL semantic but the point cloud does not have normals"
);
}
for (name in styleableShaderAttributes) {
if (styleableShaderAttributes.hasOwnProperty(name)) {
attribute = styleableShaderAttributes[name];
const enabled = styleablePropertyIds.indexOf(attribute.location) >= 0;
const vertexAttribute = getVertexAttribute(
vertexArray,
attribute.location
);
vertexAttribute.enabled = enabled;
}
}
const usesColors = hasColors && (!hasColorStyle || usesColorSemantic);
if (hasColors) {
const colorVertexAttribute = getVertexAttribute(vertexArray, colorLocation);
colorVertexAttribute.enabled = usesColors;
}
const usesNormals = hasNormals && (normalShading || backFaceCulling || usesNormalSemantic);
if (hasNormals) {
const normalVertexAttribute = getVertexAttribute(
vertexArray,
normalLocation
);
normalVertexAttribute.enabled = usesNormals;
}
const attributeLocations8 = {
a_position: positionLocation
};
if (usesColors) {
attributeLocations8.a_color = colorLocation;
}
if (usesNormals) {
attributeLocations8.a_normal = normalLocation;
}
if (hasBatchIds) {
attributeLocations8.a_batchId = batchIdLocation;
}
let attributeDeclarations = "";
const length2 = styleablePropertyIds.length;
for (i = 0; i < length2; ++i) {
const propertyId = styleablePropertyIds[i];
attribute = propertyIdToAttributeMap[propertyId];
const componentCount = attribute.componentCount;
const attributeName = `czm_3dtiles_property_${propertyId}`;
let attributeType;
if (componentCount === 1) {
attributeType = "float";
} else {
attributeType = `vec${componentCount}`;
}
attributeDeclarations += `in ${attributeType} ${attributeName};
`;
attributeLocations8[attributeName] = attribute.location;
}
createUniformMap6(pointCloud, frameState);
let vs = "in vec3 a_position; \nout vec4 v_color; \nuniform vec4 u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier; \nuniform vec4 u_constantColor; \nuniform vec4 u_highlightColor; \n";
vs += "float u_pointSize; \nfloat tiles3d_tileset_time; \n";
if (attenuation) {
vs += "float u_geometricError; \nfloat u_depthMultiplier; \n";
}
vs += attributeDeclarations;
if (usesColors) {
if (isTranslucent) {
vs += "in vec4 a_color; \n";
} else if (isRGB565) {
vs += "in float a_color; \nconst float SHIFT_RIGHT_11 = 1.0 / 2048.0; \nconst float SHIFT_RIGHT_5 = 1.0 / 32.0; \nconst float SHIFT_LEFT_11 = 2048.0; \nconst float SHIFT_LEFT_5 = 32.0; \nconst float NORMALIZE_6 = 1.0 / 64.0; \nconst float NORMALIZE_5 = 1.0 / 32.0; \n";
} else {
vs += "in vec3 a_color; \n";
}
}
if (usesNormals) {
if (isOctEncoded16P || isOctEncodedDraco) {
vs += "in vec2 a_normal; \n";
} else {
vs += "in vec3 a_normal; \n";
}
}
if (hasBatchIds) {
vs += "in float a_batchId; \n";
}
if (isQuantized || isQuantizedDraco || isOctEncodedDraco) {
vs += "uniform vec4 u_quantizedVolumeScaleAndOctEncodedRange; \n";
}
if (hasColorStyle) {
vs += colorStyleFunction;
}
if (hasShowStyle) {
vs += showStyleFunction;
}
if (hasPointSizeStyle) {
vs += pointSizeStyleFunction;
}
vs += "void main() \n{ \n u_pointSize = u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier.x; \n tiles3d_tileset_time = u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier.y; \n";
if (attenuation) {
vs += " u_geometricError = u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier.z; \n u_depthMultiplier = u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier.w; \n";
}
if (usesColors) {
if (isTranslucent) {
vs += " vec4 color = a_color; \n";
} else if (isRGB565) {
vs += " float compressed = a_color; \n float r = floor(compressed * SHIFT_RIGHT_11); \n compressed -= r * SHIFT_LEFT_11; \n float g = floor(compressed * SHIFT_RIGHT_5); \n compressed -= g * SHIFT_LEFT_5; \n float b = compressed; \n vec3 rgb = vec3(r * NORMALIZE_5, g * NORMALIZE_6, b * NORMALIZE_5); \n vec4 color = vec4(rgb, 1.0); \n";
} else {
vs += " vec4 color = vec4(a_color, 1.0); \n";
}
} else {
vs += " vec4 color = u_constantColor; \n";
}
if (isQuantized || isQuantizedDraco) {
vs += " vec3 position = a_position * u_quantizedVolumeScaleAndOctEncodedRange.xyz; \n";
} else {
vs += " vec3 position = a_position; \n";
}
vs += " vec3 position_absolute = vec3(czm_model * vec4(position, 1.0)); \n";
if (usesNormals) {
if (isOctEncoded16P) {
vs += " vec3 normal = czm_octDecode(a_normal); \n";
} else if (isOctEncodedDraco) {
vs += " vec3 normal = czm_octDecode(a_normal, u_quantizedVolumeScaleAndOctEncodedRange.w).zxy; \n";
} else {
vs += " vec3 normal = a_normal; \n";
}
vs += " vec3 normalEC = czm_normal * normal; \n";
} else {
vs += " vec3 normal = vec3(1.0); \n";
}
if (hasColorStyle) {
vs += " color = getColorFromStyle(position, position_absolute, color, normal); \n";
}
if (hasShowStyle) {
vs += " float show = float(getShowFromStyle(position, position_absolute, color, normal)); \n";
}
if (hasPointSizeStyle) {
vs += " gl_PointSize = getPointSizeFromStyle(position, position_absolute, color, normal) * czm_pixelRatio; \n";
} else if (attenuation) {
vs += " vec4 positionEC = czm_modelView * vec4(position, 1.0); \n float depth = -positionEC.z; \n gl_PointSize = min((u_geometricError / depth) * u_depthMultiplier, u_pointSize); \n";
} else {
vs += " gl_PointSize = u_pointSize; \n";
}
vs += " color = color * u_highlightColor; \n";
if (usesNormals && normalShading) {
vs += " float diffuseStrength = czm_getLambertDiffuse(czm_lightDirectionEC, normalEC); \n diffuseStrength = max(diffuseStrength, 0.4); \n color.xyz *= diffuseStrength * czm_lightColor; \n";
}
vs += " v_color = color; \n gl_Position = czm_modelViewProjection * vec4(position, 1.0); \n";
if (usesNormals && backFaceCulling) {
vs += " float visible = step(-normalEC.z, 0.0); \n gl_Position *= visible; \n gl_PointSize *= visible; \n";
}
if (hasShowStyle) {
vs += " gl_Position.w *= float(show); \n gl_PointSize *= float(show); \n";
}
vs += "} \n";
let fs = "in vec4 v_color; \n";
if (hasClippedContent) {
fs += "uniform highp sampler2D u_clippingPlanes; \nuniform mat4 u_clippingPlanesMatrix; \nuniform vec4 u_clippingPlanesEdgeStyle; \n";
fs += "\n";
fs += getClippingFunction_default(clippingPlanes, context);
fs += "\n";
}
fs += "void main() \n{ \n out_FragColor = czm_gammaCorrect(v_color); \n";
if (hasClippedContent) {
fs += getClipAndStyleCode_default(
"u_clippingPlanes",
"u_clippingPlanesMatrix",
"u_clippingPlanesEdgeStyle"
);
}
fs += "} \n";
if (pointCloud.splitDirection !== SplitDirection_default.NONE) {
fs = Splitter_default.modifyFragmentShader(fs);
}
if (defined_default(pointCloud._vertexShaderLoaded)) {
vs = pointCloud._vertexShaderLoaded(vs);
}
if (defined_default(pointCloud._fragmentShaderLoaded)) {
fs = pointCloud._fragmentShaderLoaded(fs);
}
const drawCommand = pointCloud._drawCommand;
if (defined_default(drawCommand.shaderProgram)) {
drawCommand.shaderProgram.destroy();
}
drawCommand.shaderProgram = ShaderProgram_default.fromCache({
context,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations8
});
try {
drawCommand.shaderProgram._bind();
} catch (error) {
throw new RuntimeError_default(
"Error generating style shader: this may be caused by a type mismatch, index out-of-bounds, or other syntax error."
);
}
}
function decodeDraco2(pointCloud, context) {
if (pointCloud._decodingState === DecodingState.READY) {
return false;
}
if (pointCloud._decodingState === DecodingState.NEEDS_DECODE) {
const parsedContent = pointCloud._parsedContent;
const draco = parsedContent.draco;
const decodePromise = DracoLoader_default.decodePointCloud(draco, context);
if (defined_default(decodePromise)) {
pointCloud._decodingState = DecodingState.DECODING;
decodePromise.then(function(result) {
pointCloud._decodingState = DecodingState.READY;
const decodedPositions = defined_default(result.POSITION) ? result.POSITION.array : void 0;
const decodedRgb = defined_default(result.RGB) ? result.RGB.array : void 0;
const decodedRgba = defined_default(result.RGBA) ? result.RGBA.array : void 0;
const decodedNormals = defined_default(result.NORMAL) ? result.NORMAL.array : void 0;
const decodedBatchIds = defined_default(result.BATCH_ID) ? result.BATCH_ID.array : void 0;
const isQuantizedDraco = defined_default(decodedPositions) && defined_default(result.POSITION.data.quantization);
const isOctEncodedDraco = defined_default(decodedNormals) && defined_default(result.NORMAL.data.quantization);
if (isQuantizedDraco) {
const quantization = result.POSITION.data.quantization;
const range = quantization.range;
pointCloud._quantizedVolumeScale = Cartesian3_default.fromElements(
range,
range,
range
);
pointCloud._quantizedVolumeOffset = Cartesian3_default.unpack(
quantization.minValues
);
pointCloud._quantizedRange = (1 << quantization.quantizationBits) - 1;
pointCloud._isQuantizedDraco = true;
}
if (isOctEncodedDraco) {
pointCloud._octEncodedRange = (1 << result.NORMAL.data.quantization.quantizationBits) - 1;
pointCloud._isOctEncodedDraco = true;
}
let styleableProperties = parsedContent.styleableProperties;
const batchTableProperties = draco.batchTableProperties;
for (const name in batchTableProperties) {
if (batchTableProperties.hasOwnProperty(name)) {
const property = result[name];
if (!defined_default(styleableProperties)) {
styleableProperties = {};
}
styleableProperties[name] = {
typedArray: property.array,
componentCount: property.data.componentsPerAttribute
};
}
}
if (defined_default(decodedPositions)) {
parsedContent.positions = {
typedArray: decodedPositions
};
}
const decodedColors = decodedRgba ?? decodedRgb;
if (defined_default(decodedColors)) {
parsedContent.colors = {
typedArray: decodedColors
};
}
if (defined_default(decodedNormals)) {
parsedContent.normals = {
typedArray: decodedNormals
};
}
if (defined_default(decodedBatchIds)) {
parsedContent.batchIds = {
typedArray: decodedBatchIds
};
}
parsedContent.styleableProperties = styleableProperties;
}).catch(function(error) {
pointCloud._decodingState = DecodingState.FAILED;
pointCloud._error = error;
});
}
}
return true;
}
var scratchComputedTranslation2 = new Cartesian4_default();
var scratchScale9 = new Cartesian3_default();
PointCloud.prototype.update = function(frameState) {
const context = frameState.context;
if (defined_default(this._error)) {
const error = this._error;
this._error = void 0;
throw error;
}
const decoding = decodeDraco2(this, context);
if (decoding) {
return;
}
let shadersDirty = false;
let modelMatrixDirty = !Matrix4_default.equals(this._modelMatrix, this.modelMatrix);
if (this._mode !== frameState.mode) {
this._mode = frameState.mode;
modelMatrixDirty = true;
}
if (!defined_default(this._drawCommand)) {
createResources4(this, frameState);
modelMatrixDirty = true;
shadersDirty = true;
this._ready = true;
this._parsedContent = void 0;
}
if (modelMatrixDirty) {
Matrix4_default.clone(this.modelMatrix, this._modelMatrix);
const modelMatrix = this._drawCommand.modelMatrix;
Matrix4_default.clone(this._modelMatrix, modelMatrix);
if (defined_default(this._rtcCenter)) {
Matrix4_default.multiplyByTranslation(modelMatrix, this._rtcCenter, modelMatrix);
}
if (defined_default(this._quantizedVolumeOffset)) {
Matrix4_default.multiplyByTranslation(
modelMatrix,
this._quantizedVolumeOffset,
modelMatrix
);
}
if (frameState.mode !== SceneMode_default.SCENE3D) {
const projection = frameState.mapProjection;
const translation3 = Matrix4_default.getColumn(
modelMatrix,
3,
scratchComputedTranslation2
);
if (!Cartesian4_default.equals(translation3, Cartesian4_default.UNIT_W)) {
Transforms_default.basisTo2D(projection, modelMatrix, modelMatrix);
}
}
const boundingSphere = this._drawCommand.boundingVolume;
BoundingSphere_default.clone(this._boundingSphere, boundingSphere);
if (this._cull) {
const center = boundingSphere.center;
Matrix4_default.multiplyByPoint(modelMatrix, center, center);
const scale = Matrix4_default.getScale(modelMatrix, scratchScale9);
boundingSphere.radius *= Cartesian3_default.maximumComponent(scale);
}
}
if (this.clippingPlanesDirty) {
this.clippingPlanesDirty = false;
shadersDirty = true;
}
if (this._attenuation !== this.attenuation) {
this._attenuation = this.attenuation;
shadersDirty = true;
}
if (this.backFaceCulling !== this._backFaceCulling) {
this._backFaceCulling = this.backFaceCulling;
shadersDirty = true;
}
if (this.normalShading !== this._normalShading) {
this._normalShading = this.normalShading;
shadersDirty = true;
}
if (this._style !== this.style || this.styleDirty) {
this._style = this.style;
this.styleDirty = false;
shadersDirty = true;
}
const splittingEnabled = this.splitDirection !== SplitDirection_default.NONE;
if (this._splittingEnabled !== splittingEnabled) {
this._splittingEnabled = splittingEnabled;
shadersDirty = true;
}
if (shadersDirty) {
createShaders4(this, frameState, this._style);
}
this._drawCommand.castShadows = ShadowMode_default.castShadows(this.shadows);
this._drawCommand.receiveShadows = ShadowMode_default.receiveShadows(this.shadows);
const isTranslucent = this._highlightColor.alpha < 1 || this._constantColor.alpha < 1 || this._styleTranslucent;
this._drawCommand.renderState = isTranslucent ? this._translucentRenderState : this._opaqueRenderState;
this._drawCommand.pass = isTranslucent ? Pass_default.TRANSLUCENT : this._opaquePass;
const commandList = frameState.commandList;
const passes = frameState.passes;
if (passes.render || passes.pick) {
commandList.push(this._drawCommand);
}
};
PointCloud.prototype.isDestroyed = function() {
return false;
};
PointCloud.prototype.destroy = function() {
const command = this._drawCommand;
if (defined_default(command)) {
command.vertexArray = command.vertexArray && command.vertexArray.destroy();
command.shaderProgram = command.shaderProgram && command.shaderProgram.destroy();
}
return destroyObject_default(this);
};
var PointCloud_default = PointCloud;
// packages/engine/Source/Scene/TimeDynamicPointCloud.js
function TimeDynamicPointCloud(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("options.clock", options.clock);
Check_default.typeOf.object("options.intervals", options.intervals);
this.show = options.show ?? true;
this.modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this.shadows = options.shadows ?? ShadowMode_default.ENABLED;
this.maximumMemoryUsage = options.maximumMemoryUsage ?? 256;
this.shading = new PointCloudShading_default(options.shading);
this.style = options.style;
this.frameFailed = new Event_default();
this.frameChanged = new Event_default();
this._clock = options.clock;
this._intervals = options.intervals;
this._clippingPlanes = void 0;
this.clippingPlanes = options.clippingPlanes;
this._pointCloudEyeDomeLighting = new PointCloudEyeDomeLighting_default2();
this._loadTimestamp = void 0;
this._clippingPlanesState = 0;
this._styleDirty = false;
this._pickId = void 0;
this._totalMemoryUsageInBytes = 0;
this._frames = [];
this._previousInterval = void 0;
this._nextInterval = void 0;
this._lastRenderedFrame = void 0;
this._clockMultiplier = 0;
this._runningSum = 0;
this._runningLength = 0;
this._runningIndex = 0;
this._runningSamples = new Array(5).fill(0);
this._runningAverage = 0;
}
Object.defineProperties(TimeDynamicPointCloud.prototype, {
/**
* The {@link ClippingPlaneCollection} used to selectively disable rendering the point cloud.
*
* @memberof TimeDynamicPointCloud.prototype
*
* @type {ClippingPlaneCollection}
*/
clippingPlanes: {
get: function() {
return this._clippingPlanes;
},
set: function(value) {
ClippingPlaneCollection_default.setOwner(value, this, "_clippingPlanes");
}
},
/**
* The total amount of GPU memory in bytes used by the point cloud.
*
* @memberof TimeDynamicPointCloud.prototype
*
* @type {number}
* @readonly
*
* @see TimeDynamicPointCloud#maximumMemoryUsage
*/
totalMemoryUsageInBytes: {
get: function() {
return this._totalMemoryUsageInBytes;
}
},
/**
* The bounding sphere of the frame being rendered. Returns undefined if no frame is being rendered.
*
* @memberof TimeDynamicPointCloud.prototype
*
* @type {BoundingSphere}
* @readonly
*/
boundingSphere: {
get: function() {
if (defined_default(this._lastRenderedFrame)) {
return this._lastRenderedFrame.pointCloud.boundingSphere;
}
return void 0;
}
}
});
function getFragmentShaderLoaded(fs) {
return `uniform vec4 czm_pickColor;
${fs}`;
}
function getUniformMapLoaded(stream) {
return function(uniformMap2) {
return combine_default(uniformMap2, {
czm_pickColor: function() {
return stream._pickId.color;
}
});
};
}
function getPickIdLoaded() {
return "czm_pickColor";
}
TimeDynamicPointCloud.prototype.makeStyleDirty = function() {
this._styleDirty = true;
};
TimeDynamicPointCloud.prototype._getAverageLoadTime = function() {
if (this._runningLength === 0) {
return 0.05;
}
return this._runningAverage;
};
var scratchDate2 = new JulianDate_default();
function getClockMultiplier(that) {
const clock = that._clock;
const isAnimating = clock.canAnimate && clock.shouldAnimate;
const multiplier = clock.multiplier;
return isAnimating ? multiplier : 0;
}
function getIntervalIndex(that, interval) {
return that._intervals.indexOf(interval.start);
}
function getNextInterval(that, currentInterval) {
const intervals = that._intervals;
const clock = that._clock;
const multiplier = getClockMultiplier(that);
if (multiplier === 0) {
return void 0;
}
const averageLoadTime = that._getAverageLoadTime();
const time = JulianDate_default.addSeconds(
clock.currentTime,
averageLoadTime * multiplier,
scratchDate2
);
let index = intervals.indexOf(time);
const currentIndex = getIntervalIndex(that, currentInterval);
if (index === currentIndex) {
if (multiplier >= 0) {
++index;
} else {
--index;
}
}
return intervals.get(index);
}
function getCurrentInterval(that) {
const intervals = that._intervals;
const clock = that._clock;
const time = clock.currentTime;
const index = intervals.indexOf(time);
return intervals.get(index);
}
function reachedInterval(that, currentInterval, nextInterval) {
const multiplier = getClockMultiplier(that);
const currentIndex = getIntervalIndex(that, currentInterval);
const nextIndex = getIntervalIndex(that, nextInterval);
if (multiplier >= 0) {
return currentIndex >= nextIndex;
}
return currentIndex <= nextIndex;
}
function handleFrameFailure(that, uri) {
return function(error) {
const message = defined_default(error.message) ? error.message : error.toString();
if (that.frameFailed.numberOfListeners > 0) {
that.frameFailed.raiseEvent({
uri,
message
});
} else {
console.log(`A frame failed to load: ${uri}`);
console.log(`Error: ${message}`);
}
};
}
function requestFrame(that, interval, frameState) {
const index = getIntervalIndex(that, interval);
const frames = that._frames;
let frame = frames[index];
if (!defined_default(frame)) {
const transformArray = interval.data.transform;
const transform3 = defined_default(transformArray) ? Matrix4_default.fromArray(transformArray) : void 0;
const uri = interval.data.uri;
frame = {
pointCloud: void 0,
transform: transform3,
timestamp: getTimestamp_default(),
sequential: true,
ready: false,
touchedFrameNumber: frameState.frameNumber,
uri
};
frames[index] = frame;
Resource_default.fetchArrayBuffer({
url: uri
}).then(function(arrayBuffer) {
frame.pointCloud = new PointCloud_default({
arrayBuffer,
cull: true,
fragmentShaderLoaded: getFragmentShaderLoaded,
uniformMapLoaded: getUniformMapLoaded(that),
pickIdLoaded: getPickIdLoaded
});
}).catch(handleFrameFailure(that, uri));
}
return frame;
}
function updateAverageLoadTime(that, loadTime) {
that._runningSum += loadTime;
that._runningSum -= that._runningSamples[that._runningIndex];
that._runningSamples[that._runningIndex] = loadTime;
that._runningLength = Math.min(
that._runningLength + 1,
that._runningSamples.length
);
that._runningIndex = (that._runningIndex + 1) % that._runningSamples.length;
that._runningAverage = that._runningSum / that._runningLength;
}
function prepareFrame(that, frame, updateState2, frameState) {
if (frame.touchedFrameNumber < frameState.frameNumber - 1) {
frame.sequential = false;
}
const pointCloud = frame.pointCloud;
if (defined_default(pointCloud) && !frame.ready) {
const commandList = frameState.commandList;
const lengthBeforeUpdate = commandList.length;
renderFrame(that, frame, updateState2, frameState);
if (pointCloud.ready) {
frame.ready = true;
that._totalMemoryUsageInBytes += pointCloud.geometryByteLength;
commandList.length = lengthBeforeUpdate;
if (frame.sequential) {
const loadTime = (getTimestamp_default() - frame.timestamp) / 1e3;
updateAverageLoadTime(that, loadTime);
}
}
}
frame.touchedFrameNumber = frameState.frameNumber;
}
var scratchModelMatrix4 = new Matrix4_default();
function getGeometricError3(that, pointCloud) {
const shading = that.shading;
if (defined_default(shading) && defined_default(shading.baseResolution)) {
return shading.baseResolution;
} else if (defined_default(pointCloud.boundingSphere)) {
return Math_default.cbrt(
pointCloud.boundingSphere.volume() / pointCloud.pointsLength
);
}
return 0;
}
function getMaximumAttenuation(that) {
const shading = that.shading;
if (defined_default(shading) && defined_default(shading.maximumAttenuation)) {
return shading.maximumAttenuation;
}
return 10;
}
var defaultShading = new PointCloudShading_default();
function renderFrame(that, frame, updateState2, frameState) {
const shading = that.shading ?? defaultShading;
const pointCloud = frame.pointCloud;
const transform3 = frame.transform ?? Matrix4_default.IDENTITY;
pointCloud.modelMatrix = Matrix4_default.multiplyTransformation(
that.modelMatrix,
transform3,
scratchModelMatrix4
);
pointCloud.style = that.style;
pointCloud.time = updateState2.timeSinceLoad;
pointCloud.shadows = that.shadows;
pointCloud.clippingPlanes = that._clippingPlanes;
pointCloud.isClipped = updateState2.isClipped;
pointCloud.attenuation = shading.attenuation;
pointCloud.backFaceCulling = shading.backFaceCulling;
pointCloud.normalShading = shading.normalShading;
pointCloud.geometricError = getGeometricError3(that, pointCloud);
pointCloud.geometricErrorScale = shading.geometricErrorScale;
pointCloud.maximumAttenuation = getMaximumAttenuation(that);
try {
pointCloud.update(frameState);
} catch (error) {
handleFrameFailure(that, frame.uri)(error);
}
frame.touchedFrameNumber = frameState.frameNumber;
}
function loadFrame(that, interval, updateState2, frameState) {
const frame = requestFrame(that, interval, frameState);
prepareFrame(that, frame, updateState2, frameState);
}
function getUnloadCondition(frameState) {
return function(frame) {
return frame.touchedFrameNumber < frameState.frameNumber;
};
}
function unloadFrames(that, unloadCondition) {
const frames = that._frames;
const length2 = frames.length;
for (let i = 0; i < length2; ++i) {
const frame = frames[i];
if (defined_default(frame)) {
if (!defined_default(unloadCondition) || unloadCondition(frame)) {
const pointCloud = frame.pointCloud;
if (frame.ready) {
that._totalMemoryUsageInBytes -= pointCloud.geometryByteLength;
}
if (defined_default(pointCloud)) {
pointCloud.destroy();
}
if (frame === that._lastRenderedFrame) {
that._lastRenderedFrame = void 0;
}
frames[i] = void 0;
}
}
}
}
function getFrame(that, interval) {
const index = getIntervalIndex(that, interval);
const frame = that._frames[index];
if (defined_default(frame) && frame.ready) {
return frame;
}
}
function updateInterval(that, interval, frame, updateState2, frameState) {
if (defined_default(frame)) {
if (frame.ready) {
return true;
}
loadFrame(that, interval, updateState2, frameState);
return frame.ready;
}
return false;
}
function getNearestReadyInterval(that, previousInterval, currentInterval, updateState2, frameState) {
let i;
let interval;
let frame;
const intervals = that._intervals;
const frames = that._frames;
const currentIndex = getIntervalIndex(that, currentInterval);
const previousIndex = getIntervalIndex(that, previousInterval);
if (currentIndex >= previousIndex) {
for (i = currentIndex; i >= previousIndex; --i) {
interval = intervals.get(i);
frame = frames[i];
if (updateInterval(that, interval, frame, updateState2, frameState)) {
return interval;
}
}
} else {
for (i = currentIndex; i <= previousIndex; ++i) {
interval = intervals.get(i);
frame = frames[i];
if (updateInterval(that, interval, frame, updateState2, frameState)) {
return interval;
}
}
}
return previousInterval;
}
function setFramesDirty(that, clippingPlanesDirty, styleDirty) {
const frames = that._frames;
const framesLength = frames.length;
for (let i = 0; i < framesLength; ++i) {
const frame = frames[i];
if (defined_default(frame) && defined_default(frame.pointCloud)) {
frame.pointCloud.clippingPlanesDirty = clippingPlanesDirty;
frame.pointCloud.styleDirty = styleDirty;
}
}
}
var updateState = {
timeSinceLoad: 0,
isClipped: false,
clippingPlanesDirty: false
};
TimeDynamicPointCloud.prototype.update = function(frameState) {
if (frameState.mode === SceneMode_default.MORPHING) {
return;
}
if (!this.show) {
return;
}
if (!defined_default(this._pickId)) {
this._pickId = frameState.context.createPickId({
primitive: this
});
}
if (!defined_default(this._loadTimestamp)) {
this._loadTimestamp = JulianDate_default.clone(frameState.time);
}
const timeSinceLoad = Math.max(
JulianDate_default.secondsDifference(frameState.time, this._loadTimestamp) * 1e3,
0
);
const clippingPlanes = this._clippingPlanes;
let clippingPlanesState = 0;
let clippingPlanesDirty = false;
const isClipped = defined_default(clippingPlanes) && clippingPlanes.enabled;
if (isClipped) {
clippingPlanes.update(frameState);
clippingPlanesState = clippingPlanes.clippingPlanesState;
}
if (this._clippingPlanesState !== clippingPlanesState) {
this._clippingPlanesState = clippingPlanesState;
clippingPlanesDirty = true;
}
const styleDirty = this._styleDirty;
this._styleDirty = false;
if (clippingPlanesDirty || styleDirty) {
setFramesDirty(this, clippingPlanesDirty, styleDirty);
}
updateState.timeSinceLoad = timeSinceLoad;
updateState.isClipped = isClipped;
const shading = this.shading;
const eyeDomeLighting = this._pointCloudEyeDomeLighting;
const commandList = frameState.commandList;
const lengthBeforeUpdate = commandList.length;
let previousInterval = this._previousInterval;
let nextInterval = this._nextInterval;
const currentInterval = getCurrentInterval(this);
if (!defined_default(currentInterval)) {
return;
}
let clockMultiplierChanged = false;
const clockMultiplier = getClockMultiplier(this);
const clockPaused = clockMultiplier === 0;
if (clockMultiplier !== this._clockMultiplier) {
clockMultiplierChanged = true;
this._clockMultiplier = clockMultiplier;
}
if (!defined_default(previousInterval) || clockPaused) {
previousInterval = currentInterval;
}
if (!defined_default(nextInterval) || clockMultiplierChanged || reachedInterval(this, currentInterval, nextInterval)) {
nextInterval = getNextInterval(this, currentInterval);
}
previousInterval = getNearestReadyInterval(
this,
previousInterval,
currentInterval,
updateState,
frameState
);
let frame = getFrame(this, previousInterval);
if (!defined_default(frame)) {
loadFrame(this, previousInterval, updateState, frameState);
frame = this._lastRenderedFrame;
}
if (defined_default(frame)) {
renderFrame(this, frame, updateState, frameState);
}
if (defined_default(nextInterval)) {
loadFrame(this, nextInterval, updateState, frameState);
}
const that = this;
if (defined_default(frame) && !defined_default(this._lastRenderedFrame)) {
frameState.afterRender.push(function() {
return true;
});
}
if (defined_default(frame) && frame !== this._lastRenderedFrame) {
if (that.frameChanged.numberOfListeners > 0) {
frameState.afterRender.push(function() {
that.frameChanged.raiseEvent(that);
return true;
});
}
}
this._previousInterval = previousInterval;
this._nextInterval = nextInterval;
this._lastRenderedFrame = frame;
const totalMemoryUsageInBytes = this._totalMemoryUsageInBytes;
const maximumMemoryUsageInBytes = this.maximumMemoryUsage * 1024 * 1024;
if (totalMemoryUsageInBytes > maximumMemoryUsageInBytes) {
unloadFrames(this, getUnloadCondition(frameState));
}
const lengthAfterUpdate = commandList.length;
const addedCommandsLength = lengthAfterUpdate - lengthBeforeUpdate;
if (defined_default(shading) && shading.attenuation && shading.eyeDomeLighting && addedCommandsLength > 0) {
eyeDomeLighting.update(
frameState,
lengthBeforeUpdate,
shading,
this.boundingSphere
);
}
};
TimeDynamicPointCloud.prototype.isDestroyed = function() {
return false;
};
TimeDynamicPointCloud.prototype.destroy = function() {
unloadFrames(this);
this._clippingPlanes = this._clippingPlanes && this._clippingPlanes.destroy();
this._pickId = this._pickId && this._pickId.destroy();
return destroyObject_default(this);
};
var TimeDynamicPointCloud_default = TimeDynamicPointCloud;
// packages/engine/Source/Widget/CesiumWidget.js
function trackDataSourceClock(clock, dataSource) {
if (defined_default(dataSource)) {
const dataSourceClock = dataSource.clock;
if (defined_default(dataSourceClock)) {
dataSourceClock.getValue(clock);
}
}
}
function startRenderLoop(widget) {
widget._renderLoopRunning = true;
let lastFrameTime = 0;
function render2(frameTime) {
if (widget.isDestroyed()) {
return;
}
if (widget._useDefaultRenderLoop) {
try {
const targetFrameRate = widget._targetFrameRate;
if (!defined_default(targetFrameRate)) {
widget.resize();
widget.render();
requestAnimationFrame(render2);
} else {
const interval = 1e3 / targetFrameRate;
const delta = frameTime - lastFrameTime;
if (delta > interval) {
widget.resize();
widget.render();
lastFrameTime = frameTime - delta % interval;
}
requestAnimationFrame(render2);
}
} catch (error) {
widget._useDefaultRenderLoop = false;
widget._renderLoopRunning = false;
if (widget._showRenderLoopErrors) {
const title = "An error occurred while rendering. Rendering has stopped.";
widget.showErrorPanel(title, void 0, error);
}
}
} else {
widget._renderLoopRunning = false;
}
}
requestAnimationFrame(render2);
}
function configurePixelRatio(widget) {
let pixelRatio = widget._useBrowserRecommendedResolution ? 1 : window.devicePixelRatio;
pixelRatio *= widget._resolutionScale;
if (defined_default(widget._scene)) {
widget._scene.pixelRatio = pixelRatio;
}
return pixelRatio;
}
function configureCanvasSize(widget) {
const canvas = widget._canvas;
let width = canvas.clientWidth;
let height = canvas.clientHeight;
const pixelRatio = configurePixelRatio(widget);
widget._canvasClientWidth = width;
widget._canvasClientHeight = height;
width *= pixelRatio;
height *= pixelRatio;
canvas.width = width;
canvas.height = height;
widget._canRender = width !== 0 && height !== 0;
widget._lastDevicePixelRatio = window.devicePixelRatio;
}
function configureCameraFrustum(widget) {
const canvas = widget._canvas;
const width = canvas.width;
const height = canvas.height;
if (width !== 0 && height !== 0) {
const frustum = widget._scene.camera.frustum;
if (defined_default(frustum.aspectRatio)) {
frustum.aspectRatio = width / height;
} else {
frustum.top = frustum.right * (height / width);
frustum.bottom = -frustum.top;
}
}
}
function CesiumWidget(container, options) {
if (!defined_default(container)) {
throw new DeveloperError_default("container is required.");
}
container = getElement_default(container);
options = options ?? Frozen_default.EMPTY_OBJECT;
const element = document.createElement("div");
element.className = "cesium-widget";
container.appendChild(element);
const canvas = document.createElement("canvas");
const supportsImageRenderingPixelated2 = FeatureDetection_default.supportsImageRenderingPixelated();
this._supportsImageRenderingPixelated = supportsImageRenderingPixelated2;
if (supportsImageRenderingPixelated2) {
canvas.style.imageRendering = FeatureDetection_default.imageRenderingValue();
}
canvas.oncontextmenu = function() {
return false;
};
canvas.onselectstart = function() {
return false;
};
function blurActiveElement() {
if (canvas !== canvas.ownerDocument.activeElement) {
canvas.ownerDocument.activeElement.blur();
}
}
const blurActiveElementOnCanvasFocus = options.blurActiveElementOnCanvasFocus ?? true;
if (blurActiveElementOnCanvasFocus) {
canvas.addEventListener("mousedown", blurActiveElement);
canvas.addEventListener("pointerdown", blurActiveElement);
}
element.appendChild(canvas);
const innerCreditContainer = document.createElement("div");
innerCreditContainer.className = "cesium-widget-credits";
const creditContainer = defined_default(options.creditContainer) ? getElement_default(options.creditContainer) : element;
creditContainer.appendChild(innerCreditContainer);
const creditViewport = defined_default(options.creditViewport) ? getElement_default(options.creditViewport) : element;
const showRenderLoopErrors = options.showRenderLoopErrors ?? true;
const useBrowserRecommendedResolution = options.useBrowserRecommendedResolution ?? true;
this._element = element;
this._container = container;
this._canvas = canvas;
this._canvasClientWidth = 0;
this._canvasClientHeight = 0;
this._lastDevicePixelRatio = 0;
this._creditViewport = creditViewport;
this._creditContainer = creditContainer;
this._innerCreditContainer = innerCreditContainer;
this._canRender = false;
this._renderLoopRunning = false;
this._showRenderLoopErrors = showRenderLoopErrors;
this._resolutionScale = 1;
this._useBrowserRecommendedResolution = useBrowserRecommendedResolution;
this._forceResize = false;
this._entityView = void 0;
this._clockTrackedDataSource = void 0;
this._trackedEntity = void 0;
this._needTrackedEntityUpdate = false;
this._zoomIsFlight = false;
this._zoomTarget = void 0;
this._zoomPromise = void 0;
this._zoomOptions = void 0;
this._trackedEntityChanged = new Event_default();
this._allowDataSourcesToSuspendAnimation = true;
this._clock = defined_default(options.clock) ? options.clock : new Clock_default();
if (defined_default(options.shouldAnimate)) {
this._clock.shouldAnimate = options.shouldAnimate;
}
configureCanvasSize(this);
try {
const ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
const scene = new Scene_default({
canvas,
contextOptions: options.contextOptions,
creditContainer: innerCreditContainer,
creditViewport,
ellipsoid,
mapProjection: options.mapProjection,
orderIndependentTranslucency: options.orderIndependentTranslucency,
scene3DOnly: options.scene3DOnly ?? false,
shadows: options.shadows,
mapMode2D: options.mapMode2D,
requestRenderMode: options.requestRenderMode,
maximumRenderTimeChange: options.maximumRenderTimeChange,
depthPlaneEllipsoidOffset: options.depthPlaneEllipsoidOffset,
msaaSamples: options.msaaSamples
});
this._scene = scene;
scene.camera.constrainedAxis = Cartesian3_default.UNIT_Z;
configurePixelRatio(this);
configureCameraFrustum(this);
let globe = options.globe;
if (!defined_default(globe)) {
globe = new Globe_default(ellipsoid);
}
if (globe !== false) {
scene.globe = globe;
scene.globe.shadows = options.terrainShadows ?? ShadowMode_default.RECEIVE_ONLY;
}
let skyBox = options.skyBox;
if (!defined_default(skyBox) && Ellipsoid_default.WGS84.equals(ellipsoid)) {
skyBox = SkyBox_default.createEarthSkyBox();
}
if (skyBox !== false) {
scene.skyBox = skyBox;
scene.sun = new Sun_default();
if (Ellipsoid_default.WGS84.equals(ellipsoid)) {
scene.moon = new Moon_default();
}
}
let skyAtmosphere = options.skyAtmosphere;
if (!defined_default(skyAtmosphere) && Ellipsoid_default.WGS84.equals(ellipsoid)) {
skyAtmosphere = new SkyAtmosphere_default(ellipsoid);
skyAtmosphere.show = options.globe !== false && globe.show;
}
if (skyAtmosphere !== false) {
scene.skyAtmosphere = skyAtmosphere;
}
let baseLayer = options.baseLayer;
if (options.globe !== false && baseLayer !== false) {
if (!defined_default(baseLayer)) {
baseLayer = ImageryLayer_default.fromWorldImagery();
}
scene.imageryLayers.add(baseLayer);
}
if (defined_default(options.terrainProvider) && options.globe !== false) {
scene.terrainProvider = options.terrainProvider;
}
if (defined_default(options.terrain) && options.globe !== false) {
if (defined_default(options.terrainProvider)) {
throw new DeveloperError_default(
"Specify either options.terrainProvider or options.terrain."
);
}
scene.setTerrain(options.terrain);
}
this._screenSpaceEventHandler = new ScreenSpaceEventHandler_default(canvas);
if (defined_default(options.sceneMode)) {
if (options.sceneMode === SceneMode_default.SCENE2D) {
this._scene.morphTo2D(0);
}
if (options.sceneMode === SceneMode_default.COLUMBUS_VIEW) {
this._scene.morphToColumbusView(0);
}
}
this._useDefaultRenderLoop = void 0;
this.useDefaultRenderLoop = options.useDefaultRenderLoop ?? true;
this._targetFrameRate = void 0;
this.targetFrameRate = options.targetFrameRate;
const that = this;
this._onRenderError = function(scene2, error) {
that._useDefaultRenderLoop = false;
that._renderLoopRunning = false;
if (that._showRenderLoopErrors) {
const title = "An error occurred while rendering. Rendering has stopped.";
that.showErrorPanel(title, void 0, error);
}
};
scene.renderError.addEventListener(this._onRenderError);
let dataSourceCollection = options.dataSources;
let destroyDataSourceCollection = false;
if (!defined_default(dataSourceCollection)) {
dataSourceCollection = new DataSourceCollection_default();
destroyDataSourceCollection = true;
}
const dataSourceDisplay = new DataSourceDisplay_default({
scene,
dataSourceCollection
});
const eventHelper = new EventHelper_default();
this._dataSourceChangedListeners = {};
this._automaticallyTrackDataSourceClocks = options.automaticallyTrackDataSourceClocks ?? true;
this._dataSourceCollection = dataSourceCollection;
this._destroyDataSourceCollection = destroyDataSourceCollection;
this._dataSourceDisplay = dataSourceDisplay;
this._eventHelper = eventHelper;
this._canAnimateUpdateCallback = this._updateCanAnimate;
eventHelper.add(this._clock.onTick, CesiumWidget.prototype._onTick, this);
eventHelper.add(
scene.morphStart,
CesiumWidget.prototype._clearTrackedObject,
this
);
eventHelper.add(
dataSourceCollection.dataSourceAdded,
CesiumWidget.prototype._onDataSourceAdded,
this
);
eventHelper.add(
dataSourceCollection.dataSourceRemoved,
CesiumWidget.prototype._onDataSourceRemoved,
this
);
eventHelper.add(scene.postRender, CesiumWidget.prototype._postRender, this);
const dataSourceLength = dataSourceCollection.length;
for (let i = 0; i < dataSourceLength; i++) {
this._dataSourceAdded(dataSourceCollection, dataSourceCollection.get(i));
}
this._dataSourceAdded(void 0, dataSourceDisplay.defaultDataSource);
eventHelper.add(
dataSourceCollection.dataSourceAdded,
CesiumWidget.prototype._dataSourceAdded,
this
);
eventHelper.add(
dataSourceCollection.dataSourceRemoved,
CesiumWidget.prototype._dataSourceRemoved,
this
);
} catch (error) {
if (showRenderLoopErrors) {
const title = "Error constructing CesiumWidget.";
const message = 'Visit http://get.webgl.org to verify that your web browser and hardware support WebGL. Consider trying a different web browser or updating your video drivers. Detailed error information is below:';
this.showErrorPanel(title, message, error);
}
throw error;
}
}
Object.defineProperties(CesiumWidget.prototype, {
/**
* Gets the parent container.
* @memberof CesiumWidget.prototype
*
* @type {Element}
* @readonly
*/
container: {
get: function() {
return this._container;
}
},
/**
* Gets the canvas.
* @memberof CesiumWidget.prototype
*
* @type {HTMLCanvasElement}
* @readonly
*/
canvas: {
get: function() {
return this._canvas;
}
},
/**
* Gets the credit container.
* @memberof CesiumWidget.prototype
*
* @type {Element}
* @readonly
*/
creditContainer: {
get: function() {
return this._creditContainer;
}
},
/**
* Gets the credit viewport
* @memberof CesiumWidget.prototype
*
* @type {Element}
* @readonly
*/
creditViewport: {
get: function() {
return this._creditViewport;
}
},
/**
* Gets the scene.
* @memberof CesiumWidget.prototype
*
* @type {Scene}
* @readonly
*/
scene: {
get: function() {
return this._scene;
}
},
/**
* Gets the collection of image layers that will be rendered on the globe.
* @memberof CesiumWidget.prototype
*
* @type {ImageryLayerCollection}
* @readonly
*/
imageryLayers: {
get: function() {
return this._scene.imageryLayers;
}
},
/**
* The terrain provider providing surface geometry for the globe.
* @memberof CesiumWidget.prototype
*
* @type {TerrainProvider}
*/
terrainProvider: {
get: function() {
return this._scene.terrainProvider;
},
set: function(terrainProvider) {
this._scene.terrainProvider = terrainProvider;
}
},
/**
* Manages the list of credits to display on screen and in the lightbox.
* @memberof CesiumWidget.prototype
*
* @type {CreditDisplay}
*/
creditDisplay: {
get: function() {
return this._scene.frameState.creditDisplay;
}
},
/**
* Gets the display used for {@link DataSource} visualization.
* @memberof CesiumWidget.prototype
* @type {DataSourceDisplay}
* @readonly
*/
dataSourceDisplay: {
get: function() {
return this._dataSourceDisplay;
}
},
/**
* Gets the collection of entities not tied to a particular data source.
* This is a shortcut to [dataSourceDisplay.defaultDataSource.entities]{@link CesiumWidget#dataSourceDisplay}.
* @memberof CesiumWidget.prototype
* @type {EntityCollection}
* @readonly
*/
entities: {
get: function() {
return this._dataSourceDisplay.defaultDataSource.entities;
}
},
/**
* Gets the set of {@link DataSource} instances to be visualized.
* @memberof CesiumWidget.prototype
* @type {DataSourceCollection}
* @readonly
*/
dataSources: {
get: function() {
return this._dataSourceCollection;
}
},
/**
* Gets the camera.
* @memberof CesiumWidget.prototype
*
* @type {Camera}
* @readonly
*/
camera: {
get: function() {
return this._scene.camera;
}
},
/**
* Gets the default ellipsoid for the scene.
* @memberof CesiumWidget.prototype
*
* @type {Ellipsoid}
* @readonly
*/
ellipsoid: {
get: function() {
return this._scene.ellipsoid;
}
},
/**
* Gets the clock.
* @memberof CesiumWidget.prototype
*
* @type {Clock}
* @readonly
*/
clock: {
get: function() {
return this._clock;
}
},
/**
* Gets the screen space event handler.
* @memberof CesiumWidget.prototype
*
* @type {ScreenSpaceEventHandler}
* @readonly
*/
screenSpaceEventHandler: {
get: function() {
return this._screenSpaceEventHandler;
}
},
/**
* Gets or sets the target frame rate of the widget when useDefaultRenderLoop
* is true. If undefined, the browser's requestAnimationFrame implementation
* determines the frame rate. If defined, this value must be greater than 0. A value higher
* than the underlying requestAnimationFrame implementation will have no effect.
* @memberof CesiumWidget.prototype
*
* @type {number}
*/
targetFrameRate: {
get: function() {
return this._targetFrameRate;
},
set: function(value) {
if (value <= 0) {
throw new DeveloperError_default(
"targetFrameRate must be greater than 0, or undefined."
);
}
this._targetFrameRate = value;
}
},
/**
* Gets or sets whether or not this widget should control the render loop.
* If true the widget will use requestAnimationFrame to
* perform rendering and resizing of the widget, as well as drive the
* simulation clock. If set to false, you must manually call the
* resize, render methods as part of a custom
* render loop. If an error occurs during rendering, {@link Scene}'s
* renderError event will be raised and this property
* will be set to false. It must be set back to true to continue rendering
* after the error.
* @memberof CesiumWidget.prototype
*
* @type {boolean}
*/
useDefaultRenderLoop: {
get: function() {
return this._useDefaultRenderLoop;
},
set: function(value) {
if (this._useDefaultRenderLoop !== value) {
this._useDefaultRenderLoop = value;
if (value && !this._renderLoopRunning) {
startRenderLoop(this);
}
}
}
},
/**
* Gets or sets a scaling factor for rendering resolution. Values less than 1.0 can improve
* performance on less powerful devices while values greater than 1.0 will render at a higher
* resolution and then scale down, resulting in improved visual fidelity.
* For example, if the widget is laid out at a size of 640x480, setting this value to 0.5
* will cause the scene to be rendered at 320x240 and then scaled up while setting
* it to 2.0 will cause the scene to be rendered at 1280x960 and then scaled down.
* @memberof CesiumWidget.prototype
*
* @type {number}
* @default 1.0
*/
resolutionScale: {
get: function() {
return this._resolutionScale;
},
set: function(value) {
if (value <= 0) {
throw new DeveloperError_default("resolutionScale must be greater than 0.");
}
if (this._resolutionScale !== value) {
this._resolutionScale = value;
this._forceResize = true;
}
}
},
/**
* Boolean flag indicating if the browser's recommended resolution is used.
* If true, the browser's device pixel ratio is ignored and 1.0 is used instead,
* effectively rendering based on CSS pixels instead of device pixels. This can improve
* performance on less powerful devices that have high pixel density. When false, rendering
* will be in device pixels. {@link CesiumWidget#resolutionScale} will still take effect whether
* this flag is true or false.
* @memberof CesiumWidget.prototype
*
* @type {boolean}
* @default true
*/
useBrowserRecommendedResolution: {
get: function() {
return this._useBrowserRecommendedResolution;
},
set: function(value) {
if (this._useBrowserRecommendedResolution !== value) {
this._useBrowserRecommendedResolution = value;
this._forceResize = true;
}
}
},
/**
* Gets or sets whether or not data sources can temporarily pause
* animation in order to avoid showing an incomplete picture to the user.
* For example, if asynchronous primitives are being processed in the
* background, the clock will not advance until the geometry is ready.
*
* @memberof CesiumWidget.prototype
*
* @type {boolean}
*/
allowDataSourcesToSuspendAnimation: {
get: function() {
return this._allowDataSourcesToSuspendAnimation;
},
set: function(value) {
this._allowDataSourcesToSuspendAnimation = value;
}
},
/**
* Gets or sets the Entity instance currently being tracked by the camera.
* @memberof CesiumWidget.prototype
* @type {Entity | undefined}
*/
trackedEntity: {
get: function() {
return this._trackedEntity;
},
set: function(value) {
if (this._trackedEntity !== value) {
this._trackedEntity = value;
cancelZoom(this);
const scene = this.scene;
const sceneMode = scene.mode;
if (!defined_default(value) || !defined_default(value.position)) {
this._needTrackedEntityUpdate = false;
if (sceneMode === SceneMode_default.COLUMBUS_VIEW || sceneMode === SceneMode_default.SCENE2D) {
scene.screenSpaceCameraController.enableTranslate = true;
}
if (sceneMode === SceneMode_default.COLUMBUS_VIEW || sceneMode === SceneMode_default.SCENE3D) {
scene.screenSpaceCameraController.enableTilt = true;
}
this._entityView = void 0;
this.camera.lookAtTransform(Matrix4_default.IDENTITY);
} else {
this._needTrackedEntityUpdate = true;
}
this._trackedEntityChanged.raiseEvent(value);
this.scene.requestRender();
}
}
},
/**
* Gets the event that is raised when the tracked entity changes.
* @memberof CesiumWidget.prototype
* @type {Event}
* @readonly
*/
trackedEntityChanged: {
get: function() {
return this._trackedEntityChanged;
}
},
/**
* Gets or sets the data source to track with the widget's clock.
* @memberof CesiumWidget.prototype
* @type {DataSource}
*/
clockTrackedDataSource: {
get: function() {
return this._clockTrackedDataSource;
},
set: function(value) {
if (this._clockTrackedDataSource !== value) {
this._clockTrackedDataSource = value;
trackDataSourceClock(this.clock, value);
}
}
}
});
CesiumWidget.prototype.showErrorPanel = function(title, message, error) {
const element = this._element;
const overlay = document.createElement("div");
overlay.className = "cesium-widget-errorPanel";
const content = document.createElement("div");
content.className = "cesium-widget-errorPanel-content";
overlay.appendChild(content);
const errorHeader = document.createElement("div");
errorHeader.className = "cesium-widget-errorPanel-header";
errorHeader.appendChild(document.createTextNode(title));
content.appendChild(errorHeader);
const errorPanelScroller = document.createElement("div");
errorPanelScroller.className = "cesium-widget-errorPanel-scroll";
content.appendChild(errorPanelScroller);
function resizeCallback() {
errorPanelScroller.style.maxHeight = `${Math.max(
Math.round(element.clientHeight * 0.9 - 100),
30
)}px`;
}
resizeCallback();
if (defined_default(window.addEventListener)) {
window.addEventListener("resize", resizeCallback, false);
}
const hasMessage = defined_default(message);
const hasError = defined_default(error);
if (hasMessage || hasError) {
const errorMessage = document.createElement("div");
errorMessage.className = "cesium-widget-errorPanel-message";
errorPanelScroller.appendChild(errorMessage);
if (hasError) {
let errorDetails = formatError_default(error);
if (!hasMessage) {
if (typeof error === "string") {
error = new Error(error);
}
message = formatError_default({
name: error.name,
message: error.message
});
errorDetails = error.stack;
}
if (typeof console !== "undefined") {
console.error(`${title}
${message}
${errorDetails}`);
}
const errorMessageDetails = document.createElement("div");
errorMessageDetails.className = "cesium-widget-errorPanel-message-details collapsed";
const moreDetails = document.createElement("span");
moreDetails.className = "cesium-widget-errorPanel-more-details";
moreDetails.appendChild(document.createTextNode("See more..."));
errorMessageDetails.appendChild(moreDetails);
errorMessageDetails.onclick = function(e) {
errorMessageDetails.removeChild(moreDetails);
errorMessageDetails.appendChild(document.createTextNode(errorDetails));
errorMessageDetails.className = "cesium-widget-errorPanel-message-details";
content.className = "cesium-widget-errorPanel-content expanded";
errorMessageDetails.onclick = void 0;
};
errorPanelScroller.appendChild(errorMessageDetails);
}
errorMessage.innerHTML = `${message}
`;
}
const buttonPanel = document.createElement("div");
buttonPanel.className = "cesium-widget-errorPanel-buttonPanel";
content.appendChild(buttonPanel);
const okButton = document.createElement("button");
okButton.setAttribute("type", "button");
okButton.className = "cesium-button";
okButton.appendChild(document.createTextNode("OK"));
okButton.onclick = function() {
if (defined_default(resizeCallback) && defined_default(window.removeEventListener)) {
window.removeEventListener("resize", resizeCallback, false);
}
element.removeChild(overlay);
};
buttonPanel.appendChild(okButton);
element.appendChild(overlay);
};
CesiumWidget.prototype.isDestroyed = function() {
return false;
};
CesiumWidget.prototype.destroy = function() {
const dataSources = this.dataSources;
const dataSourceLength = dataSources.length;
for (let i = 0; i < dataSourceLength; i++) {
this._dataSourceRemoved(dataSources, dataSources.get(i));
}
this._dataSourceRemoved(void 0, this._dataSourceDisplay.defaultDataSource);
this._dataSourceDisplay = this._dataSourceDisplay.destroy();
if (defined_default(this._scene)) {
this._scene.renderError.removeEventListener(this._onRenderError);
this._scene = this._scene.destroy();
}
this._container.removeChild(this._element);
this._creditContainer.removeChild(this._innerCreditContainer);
this._eventHelper.removeAll();
if (this._destroyDataSourceCollection) {
this._dataSourceCollection = this._dataSourceCollection.destroy();
}
destroyObject_default(this);
};
CesiumWidget.prototype.resize = function() {
const canvas = this._canvas;
if (!this._forceResize && this._canvasClientWidth === canvas.clientWidth && this._canvasClientHeight === canvas.clientHeight && this._lastDevicePixelRatio === window.devicePixelRatio) {
return;
}
this._forceResize = false;
configureCanvasSize(this);
configureCameraFrustum(this);
this._scene.requestRender();
};
CesiumWidget.prototype.render = function() {
if (this._canRender) {
this._scene.initializeFrame();
const currentTime = this._clock.tick();
this._scene.render(currentTime);
} else {
this._clock.tick();
}
};
CesiumWidget.prototype._dataSourceAdded = function(dataSourceCollection, dataSource) {
const entityCollection = dataSource.entities;
entityCollection.collectionChanged.addEventListener(
CesiumWidget.prototype._onEntityCollectionChanged,
this
);
};
CesiumWidget.prototype._dataSourceRemoved = function(dataSourceCollection, dataSource) {
const entityCollection = dataSource.entities;
entityCollection.collectionChanged.removeEventListener(
CesiumWidget.prototype._onEntityCollectionChanged,
this
);
if (defined_default(this.trackedEntity)) {
if (entityCollection.getById(this.trackedEntity.id) === this.trackedEntity) {
this.trackedEntity = void 0;
}
}
};
CesiumWidget.prototype._updateCanAnimate = function(isUpdated) {
this._clock.canAnimate = isUpdated;
};
var boundingSphereScratch4 = new BoundingSphere_default();
CesiumWidget.prototype._onTick = function(clock) {
const time = clock.currentTime;
const isUpdated = this._dataSourceDisplay.update(time);
if (this._allowDataSourcesToSuspendAnimation) {
this._canAnimateUpdateCallback(isUpdated);
}
const entityView = this._entityView;
if (defined_default(entityView)) {
const trackedEntity = this._trackedEntity;
const trackedState = this._dataSourceDisplay.getBoundingSphere(
trackedEntity,
false,
entityView.boundingSphere ?? boundingSphereScratch4
);
if (trackedState === BoundingSphereState_default.DONE) {
entityView.update(time);
}
}
};
CesiumWidget.prototype._onEntityCollectionChanged = function(collection, added, removed) {
const length2 = removed.length;
for (let i = 0; i < length2; i++) {
const removedObject = removed[i];
if (this.trackedEntity === removedObject) {
this.trackedEntity = void 0;
}
}
};
CesiumWidget.prototype._clearTrackedObject = function() {
this.trackedEntity = void 0;
};
CesiumWidget.prototype._onDataSourceChanged = function(dataSource) {
if (this.clockTrackedDataSource === dataSource) {
trackDataSourceClock(this.clock, dataSource);
}
};
CesiumWidget.prototype._onDataSourceAdded = function(dataSourceCollection, dataSource) {
if (this._automaticallyTrackDataSourceClocks) {
this.clockTrackedDataSource = dataSource;
}
const id = dataSource.entities.id;
const removalFunc = this._eventHelper.add(
dataSource.changedEvent,
CesiumWidget.prototype._onDataSourceChanged,
this
);
this._dataSourceChangedListeners[id] = removalFunc;
};
CesiumWidget.prototype._onDataSourceRemoved = function(dataSourceCollection, dataSource) {
const resetClock = this.clockTrackedDataSource === dataSource;
const id = dataSource.entities.id;
this._dataSourceChangedListeners[id]();
this._dataSourceChangedListeners[id] = void 0;
if (resetClock) {
const numDataSources = dataSourceCollection.length;
if (this._automaticallyTrackDataSourceClocks && numDataSources > 0) {
this.clockTrackedDataSource = dataSourceCollection.get(
numDataSources - 1
);
} else {
this.clockTrackedDataSource = void 0;
}
}
};
CesiumWidget.prototype.zoomTo = function(target, offset) {
const options = {
offset
};
return zoomToOrFly(this, target, options, false);
};
CesiumWidget.prototype.flyTo = function(target, options) {
return zoomToOrFly(this, target, options, true);
};
function zoomToOrFly(that, zoomTarget, options, isFlight) {
if (!defined_default(zoomTarget)) {
throw new DeveloperError_default("zoomTarget is required.");
}
cancelZoom(that);
const zoomPromise = new Promise((resolve2) => {
that._completeZoom = function(value) {
resolve2(value);
};
});
that._zoomPromise = zoomPromise;
that._zoomIsFlight = isFlight;
that._zoomOptions = options;
Promise.resolve(zoomTarget).then(function(zoomTarget2) {
if (that._zoomPromise !== zoomPromise) {
return;
}
if (zoomTarget2 instanceof ImageryLayer_default) {
let rectanglePromise;
if (defined_default(zoomTarget2.imageryProvider)) {
rectanglePromise = Promise.resolve(zoomTarget2.getImageryRectangle());
} else {
rectanglePromise = new Promise((resolve2) => {
const removeListener = zoomTarget2.readyEvent.addEventListener(() => {
removeListener();
resolve2(zoomTarget2.getImageryRectangle());
});
});
}
rectanglePromise.then(function(rectangle) {
return computeFlyToLocationForRectangle_default(rectangle, that.scene);
}).then(function(position) {
if (that._zoomPromise === zoomPromise) {
that._zoomTarget = position;
}
});
return;
}
if (zoomTarget2 instanceof Cesium3DTileset_default || zoomTarget2 instanceof TimeDynamicPointCloud_default || zoomTarget2 instanceof VoxelPrimitive_default) {
that._zoomTarget = zoomTarget2;
return;
}
if (zoomTarget2.isLoading && defined_default(zoomTarget2.loadingEvent)) {
const removeEvent = zoomTarget2.loadingEvent.addEventListener(function() {
removeEvent();
if (that._zoomPromise === zoomPromise) {
that._zoomTarget = zoomTarget2.entities.values.slice(0);
}
});
return;
}
if (Array.isArray(zoomTarget2)) {
that._zoomTarget = zoomTarget2.slice(0);
return;
}
zoomTarget2 = zoomTarget2.values ?? zoomTarget2;
if (defined_default(zoomTarget2.entities)) {
zoomTarget2 = zoomTarget2.entities.values;
}
if (Array.isArray(zoomTarget2)) {
that._zoomTarget = zoomTarget2.slice(0);
} else {
that._zoomTarget = [zoomTarget2];
}
});
that.scene.requestRender();
return zoomPromise;
}
function clearZoom(widget) {
widget._zoomPromise = void 0;
widget._zoomTarget = void 0;
widget._zoomOptions = void 0;
}
function cancelZoom(widget) {
const zoomPromise = widget._zoomPromise;
if (defined_default(zoomPromise)) {
clearZoom(widget);
widget._completeZoom(false);
}
}
CesiumWidget.prototype._postRender = function() {
updateZoomTarget(this);
updateTrackedEntity(this);
};
var zoomTargetBoundingSphereScratch = new BoundingSphere_default();
function updateZoomTarget(widget) {
const target = widget._zoomTarget;
if (!defined_default(target) || widget.scene.mode === SceneMode_default.MORPHING) {
return;
}
const scene = widget.scene;
const camera = scene.camera;
const zoomOptions = widget._zoomOptions ?? {};
let options;
function zoomToBoundingSphere(boundingSphere2) {
if (!defined_default(zoomOptions.offset)) {
zoomOptions.offset = new HeadingPitchRange_default(
0,
-0.5,
boundingSphere2.radius
);
}
options = {
offset: zoomOptions.offset,
duration: zoomOptions.duration,
maximumHeight: zoomOptions.maximumHeight,
complete: function() {
widget._completeZoom(true);
},
cancel: function() {
widget._completeZoom(false);
}
};
if (widget._zoomIsFlight) {
camera.flyToBoundingSphere(target.boundingSphere, options);
} else {
camera.viewBoundingSphere(boundingSphere2, zoomOptions.offset);
camera.lookAtTransform(Matrix4_default.IDENTITY);
widget._completeZoom(true);
}
clearZoom(widget);
}
if (target instanceof TimeDynamicPointCloud_default) {
if (defined_default(target.boundingSphere)) {
zoomToBoundingSphere(target.boundingSphere);
return;
}
const removeEventListener = target.frameChanged.addEventListener(
function(timeDynamicPointCloud) {
zoomToBoundingSphere(timeDynamicPointCloud.boundingSphere);
removeEventListener();
}
);
return;
}
if (target instanceof Cesium3DTileset_default || target instanceof VoxelPrimitive_default) {
zoomToBoundingSphere(target.boundingSphere);
return;
}
if (target instanceof Cartographic_default) {
options = {
destination: scene.ellipsoid.cartographicToCartesian(target),
duration: zoomOptions.duration,
maximumHeight: zoomOptions.maximumHeight,
complete: function() {
widget._completeZoom(true);
},
cancel: function() {
widget._completeZoom(false);
}
};
if (widget._zoomIsFlight) {
camera.flyTo(options);
} else {
camera.setView(options);
widget._completeZoom(true);
}
clearZoom(widget);
return;
}
const entities = target;
const boundingSpheres = [];
for (let i = 0, len = entities.length; i < len; i++) {
const state = widget._dataSourceDisplay.getBoundingSphere(
entities[i],
false,
zoomTargetBoundingSphereScratch
);
if (state === BoundingSphereState_default.PENDING) {
return;
} else if (state !== BoundingSphereState_default.FAILED) {
boundingSpheres.push(
BoundingSphere_default.clone(zoomTargetBoundingSphereScratch)
);
}
}
if (boundingSpheres.length === 0) {
cancelZoom(widget);
return;
}
widget.trackedEntity = void 0;
const boundingSphere = BoundingSphere_default.fromBoundingSpheres(boundingSpheres);
if (!widget._zoomIsFlight) {
camera.viewBoundingSphere(boundingSphere, zoomOptions.offset);
camera.lookAtTransform(Matrix4_default.IDENTITY);
clearZoom(widget);
widget._completeZoom(true);
} else {
clearZoom(widget);
camera.flyToBoundingSphere(boundingSphere, {
duration: zoomOptions.duration,
maximumHeight: zoomOptions.maximumHeight,
complete: function() {
widget._completeZoom(true);
},
cancel: function() {
widget._completeZoom(false);
},
offset: zoomOptions.offset
});
}
}
var trackedEntityBoundingSphereScratch = new BoundingSphere_default();
function updateTrackedEntity(widget) {
if (!widget._needTrackedEntityUpdate) {
return;
}
const trackedEntity = widget._trackedEntity;
const currentTime = widget.clock.currentTime;
const currentPosition = Property_default.getValueOrUndefined(
trackedEntity.position,
currentTime
);
if (!defined_default(currentPosition)) {
return;
}
const scene = widget.scene;
const state = widget._dataSourceDisplay.getBoundingSphere(
trackedEntity,
false,
trackedEntityBoundingSphereScratch
);
if (state === BoundingSphereState_default.PENDING) {
return;
}
const sceneMode = scene.mode;
if (sceneMode === SceneMode_default.COLUMBUS_VIEW || sceneMode === SceneMode_default.SCENE2D) {
scene.screenSpaceCameraController.enableTranslate = false;
}
if (sceneMode === SceneMode_default.COLUMBUS_VIEW || sceneMode === SceneMode_default.SCENE3D) {
scene.screenSpaceCameraController.enableTilt = false;
}
const bs = state !== BoundingSphereState_default.FAILED ? trackedEntityBoundingSphereScratch : void 0;
widget._entityView = new EntityView_default(trackedEntity, scene, scene.ellipsoid);
widget._entityView.update(currentTime, bs);
widget._needTrackedEntityUpdate = false;
}
var CesiumWidget_default = CesiumWidget;
// packages/engine/Source/Shaders/CloudCollectionFS.js
var import_InlineWorkers1179 = __toESM(require_InlineWorkers(), 1);
var CloudCollectionFS_default = `uniform sampler2D u_noiseTexture;
uniform vec3 u_noiseTextureDimensions;
uniform float u_noiseDetail;
in vec2 v_offset;
in vec3 v_maximumSize;
in vec4 v_color;
in float v_slice;
in float v_brightness;
float wrap(float value, float rangeLength) {
if(value < 0.0) {
float absValue = abs(value);
float modValue = mod(absValue, rangeLength);
return mod(rangeLength - modValue, rangeLength);
}
return mod(value, rangeLength);
}
vec3 wrapVec(vec3 value, float rangeLength) {
return vec3(wrap(value.x, rangeLength),
wrap(value.y, rangeLength),
wrap(value.z, rangeLength));
}
vec2 voxelToUV(vec3 voxelIndex) {
float textureSliceWidth = u_noiseTextureDimensions.x;
float noiseTextureRows = u_noiseTextureDimensions.y;
float inverseNoiseTextureRows = u_noiseTextureDimensions.z;
float textureSliceWidthSquared = textureSliceWidth * textureSliceWidth;
vec2 inverseNoiseTextureDimensions = vec2(noiseTextureRows / textureSliceWidthSquared,
inverseNoiseTextureRows / textureSliceWidth);
vec3 wrappedIndex = wrapVec(voxelIndex, textureSliceWidth);
float column = mod(wrappedIndex.z, textureSliceWidth * inverseNoiseTextureRows);
float row = floor(wrappedIndex.z / textureSliceWidth * noiseTextureRows);
float xPixelCoord = wrappedIndex.x + column * textureSliceWidth;
float yPixelCoord = wrappedIndex.y + row * textureSliceWidth;
return vec2(xPixelCoord, yPixelCoord) * inverseNoiseTextureDimensions;
}
// Interpolate a voxel with its neighbor (along the positive X-axis)
vec4 lerpSamplesX(vec3 voxelIndex, float x) {
vec2 uv0 = voxelToUV(voxelIndex);
vec2 uv1 = voxelToUV(voxelIndex + vec3(1.0, 0.0, 0.0));
vec4 sample0 = texture(u_noiseTexture, uv0);
vec4 sample1 = texture(u_noiseTexture, uv1);
return mix(sample0, sample1, x);
}
vec4 sampleNoiseTexture(vec3 position) {
float textureSliceWidth = u_noiseTextureDimensions.x;
vec3 recenteredPos = position + vec3(textureSliceWidth / 2.0);
vec3 lerpValue = fract(recenteredPos);
vec3 voxelIndex = floor(recenteredPos);
vec4 xLerp00 = lerpSamplesX(voxelIndex, lerpValue.x);
vec4 xLerp01 = lerpSamplesX(voxelIndex + vec3(0.0, 0.0, 1.0), lerpValue.x);
vec4 xLerp10 = lerpSamplesX(voxelIndex + vec3(0.0, 1.0, 0.0), lerpValue.x);
vec4 xLerp11 = lerpSamplesX(voxelIndex + vec3(0.0, 1.0, 1.0), lerpValue.x);
vec4 yLerp0 = mix(xLerp00, xLerp10, lerpValue.y);
vec4 yLerp1 = mix(xLerp01, xLerp11, lerpValue.y);
return mix(yLerp0, yLerp1, lerpValue.z);
}
// Intersection with a unit sphere with radius 0.5 at center (0, 0, 0).
bool intersectSphere(vec3 origin, vec3 dir, float slice,
out vec3 point, out vec3 normal) {
float A = dot(dir, dir);
float B = dot(origin, dir);
float C = dot(origin, origin) - 0.25;
float discriminant = (B * B) - (A * C);
if(discriminant < 0.0) {
return false;
}
float root = sqrt(discriminant);
float t = (-B - root) / A;
if(t < 0.0) {
t = (-B + root) / A;
}
point = origin + t * dir;
if(slice >= 0.0) {
point.z = (slice / 2.0) - 0.5;
if(length(point) > 0.5) {
return false;
}
}
normal = normalize(point);
point -= czm_epsilon2 * normal;
return true;
}
// Transforms the ray origin and direction into unit sphere space,
// then transforms the result back into the ellipsoid's space.
bool intersectEllipsoid(vec3 origin, vec3 dir, vec3 center, vec3 scale, float slice,
out vec3 point, out vec3 normal) {
if(scale.x <= 0.01 || scale.y < 0.01 || scale.z < 0.01) {
return false;
}
vec3 o = (origin - center) / scale;
vec3 d = dir / scale;
vec3 p, n;
bool intersected = intersectSphere(o, d, slice, p, n);
if(intersected) {
point = (p * scale) + center;
normal = n;
}
return intersected;
}
// Assume that if phase shift is being called for octave i,
// the frequency is of i - 1. This saves us from doing extra
// division / multiplication operations.
vec2 phaseShift2D(vec2 p, vec2 freq) {
return (czm_pi / 2.0) * sin(freq.yx * p.yx);
}
vec2 phaseShift3D(vec3 p, vec2 freq) {
return phaseShift2D(p.xy, freq) + czm_pi * vec2(sin(freq.x * p.z));
}
// The cloud texture function derived from Gardner's 1985 paper,
// "Visual Simulation of Clouds."
// https://www.cs.drexel.edu/~david/Classes/Papers/p297-gardner.pdf
const float T0 = 0.6; // contrast of the texture pattern
const float k = 0.1; // computed to produce a maximum value of 1
const float C0 = 0.8; // coefficient
const float FX0 = 0.6; // frequency X
const float FY0 = 0.6; // frequency Y
const int octaves = 5;
float T(vec3 point) {
vec2 sum = vec2(0.0);
float Ci = C0;
vec2 FXY = vec2(FX0, FY0);
vec2 PXY = vec2(0.0);
for(int i = 1; i <= octaves; i++) {
PXY = phaseShift3D(point, FXY);
Ci *= 0.707;
FXY *= 2.0;
vec2 sinTerm = sin(FXY * point.xy + PXY);
sum += Ci * sinTerm + vec2(T0);
}
return k * sum.x * sum.y;
}
const float a = 0.5; // fraction of surface reflection due to ambient or scattered light,
const float t = 0.4; // fraction of texture shading
const float s = 0.25; // fraction of specular reflection
float I(float Id, float Is, float It) {
return (1.0 - a) * ((1.0 - t) * ((1.0 - s) * Id + s * Is) + t * It) + a;
}
const vec3 lightDir = normalize(vec3(0.2, -1.0, 0.7));
vec4 drawCloud(vec3 rayOrigin, vec3 rayDir, vec3 cloudCenter, vec3 cloudScale, float cloudSlice,
float brightness) {
vec3 cloudPoint, cloudNormal;
if(!intersectEllipsoid(rayOrigin, rayDir, cloudCenter, cloudScale, cloudSlice,
cloudPoint, cloudNormal)) {
return vec4(0.0);
}
float Id = clamp(dot(cloudNormal, -lightDir), 0.0, 1.0); // diffuse reflection
float Is = max(pow(dot(-lightDir, -rayDir), 2.0), 0.0); // specular reflection
float It = T(cloudPoint); // texture function
float intensity = I(Id, Is, It);
vec3 color = vec3(intensity * clamp(brightness, 0.1, 1.0));
vec4 noise = sampleNoiseTexture(u_noiseDetail * cloudPoint);
float W = noise.x;
float W2 = noise.y;
float W3 = noise.z;
// The dot product between the cloud's normal and the ray's direction is greatest
// in the center of the ellipsoid's surface. It decreases towards the edge.
// Thus, it is used to blur the areas leading to the edges of the ellipsoid,
// so that no harsh lines appear.
// The first (and biggest) layer of worley noise is then subtracted from this.
// The final result is scaled up so that the base cloud is not too translucent.
float ndDot = clamp(dot(cloudNormal, -rayDir), 0.0, 1.0);
float TR = pow(ndDot, 3.0) - W; // translucency
TR *= 1.3;
// Subtracting the second and third layers of worley noise is more complicated.
// If these layers of noise were simply subtracted from the current translucency,
// the shape derived from the first layer of noise would be completely deleted.
// The erosion of this noise should thus be constricted to the edges of the cloud.
// However, because the edges of the ellipsoid were already blurred away, mapping
// the noise to (1.0 - ndDot) will have no impact on most of the cloud's appearance.
// The value of (0.5 - ndDot) provides the best compromise.
float minusDot = 0.5 - ndDot;
// Even with the previous calculation, subtracting the second layer of wnoise
// erode too much of the cloud. The addition of it, however, will detailed
// volume to the cloud. As long as the noise is only added and not subtracted,
// the results are aesthetically pleasing.
// The minusDot product is mapped in a way that it is larger at the edges of
// the ellipsoid, so a subtraction and min operation are used instead of
// an addition and max one.
TR -= min(minusDot * W2, 0.0);
// The third level of worley noise is subtracted from the result, with some
// modifications. First, a scalar is added to minusDot so that the noise
// starts affecting the shape farther away from the center of the ellipsoid's
// surface. Then, it is scaled down so its impact is not too intense.
TR -= 0.8 * (minusDot + 0.25) * W3;
// The texture function's shading does not correlate with the shape of the cloud
// produced by the layers of noise, so an extra shading scalar is calculated.
// The darkest areas of the cloud are assigned to be where the noise erodes
// the cloud the most. This is then interpolated based on the translucency
// and the diffuse shading term of that point in the cloud.
float shading = mix(1.0 - 0.8 * W * W, 1.0, Id * TR);
// To avoid values that are too dark, this scalar is increased by a small amount
// and clamped so it never goes to zero.
shading = clamp(shading + 0.2, 0.3, 1.0);
// Finally, the contrast of the cloud's color is increased.
vec3 finalColor = mix(vec3(0.5), shading * color, 1.15);
return vec4(finalColor, clamp(TR, 0.0, 1.0)) * v_color;
}
void main() {
#ifdef DEBUG_BILLBOARDS
out_FragColor = vec4(0.0, 0.5, 0.5, 1.0);
#endif
// To avoid calculations with high values,
// we raycast from an arbitrarily smaller space.
vec2 coordinate = v_maximumSize.xy * v_offset;
vec3 ellipsoidScale = 0.82 * v_maximumSize;
vec3 ellipsoidCenter = vec3(0.0);
float zOffset = max(ellipsoidScale.z - 10.0, 0.0);
vec3 eye = vec3(0, 0, -10.0 - zOffset);
vec3 rayDir = normalize(vec3(coordinate, 1.0) - eye);
vec3 rayOrigin = eye;
#ifdef DEBUG_ELLIPSOIDS
vec3 point, normal;
if(intersectEllipsoid(rayOrigin, rayDir, ellipsoidCenter, ellipsoidScale, v_slice,
point, normal)) {
out_FragColor = v_brightness * v_color;
}
#else
#ifndef DEBUG_BILLBOARDS
vec4 cloud = drawCloud(rayOrigin, rayDir,
ellipsoidCenter, ellipsoidScale, v_slice, v_brightness);
if(cloud.w < 0.01) {
discard;
}
out_FragColor = cloud;
#endif
#endif
}
`;
// packages/engine/Source/Shaders/CloudCollectionVS.js
var import_InlineWorkers1180 = __toESM(require_InlineWorkers(), 1);
var CloudCollectionVS_default = "#ifdef INSTANCED\nin vec2 direction;\n#endif\nin vec4 positionHighAndScaleX;\nin vec4 positionLowAndScaleY;\nin vec4 packedAttribute0;\nin vec4 packedAttribute1;\nin vec4 color;\n\nout vec2 v_offset;\nout vec3 v_maximumSize;\nout vec4 v_color;\nout float v_slice;\nout float v_brightness;\n\nvoid main() {\n // Unpack attributes.\n vec3 positionHigh = positionHighAndScaleX.xyz;\n vec3 positionLow = positionLowAndScaleY.xyz;\n vec2 scale = vec2(positionHighAndScaleX.w, positionLowAndScaleY.w);\n\n float show = packedAttribute0.x;\n float brightness = packedAttribute0.y;\n vec2 coordinates = packedAttribute0.wz;\n vec3 maximumSize = packedAttribute1.xyz;\n float slice = packedAttribute1.w;\n\n#ifdef INSTANCED\n vec2 dir = direction;\n#else\n vec2 dir = coordinates;\n#endif\n\n vec2 offset = dir - vec2(0.5, 0.5);\n vec2 scaledOffset = scale * offset;\n vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);\n vec4 positionEC = czm_modelViewRelativeToEye * p;\n positionEC.xy += scaledOffset;\n \n positionEC.xyz *= show;\n gl_Position = czm_projection * positionEC;\n\n v_offset = offset;\n v_maximumSize = maximumSize;\n v_color = color;\n v_slice = slice;\n v_brightness = brightness;\n}\n";
// packages/engine/Source/Shaders/CloudNoiseFS.js
var import_InlineWorkers1181 = __toESM(require_InlineWorkers(), 1);
var CloudNoiseFS_default = "uniform vec3 u_noiseTextureDimensions;\nuniform float u_noiseDetail;\nuniform vec3 u_noiseOffset;\nin vec2 v_position;\n\nfloat wrap(float value, float rangeLength) {\n if(value < 0.0) {\n float absValue = abs(value);\n float modValue = mod(absValue, rangeLength);\n return mod(rangeLength - modValue, rangeLength);\n }\n return mod(value, rangeLength);\n}\n\nvec3 wrapVec(vec3 value, float rangeLength) {\n return vec3(wrap(value.x, rangeLength),\n wrap(value.y, rangeLength),\n wrap(value.z, rangeLength));\n}\n\nvec3 random3(vec3 p) {\n float dot1 = dot(p, vec3(127.1, 311.7, 932.8));\n float dot2 = dot(p, vec3(269.5, 183.3, 421.4));\n return fract(vec3(sin(dot1 - dot2), cos(dot1 * dot2), dot1 * dot2));\n}\n\n// Frequency corresponds to cell size.\n// The higher the frequency, the smaller the cell size.\nvec3 getWorleyCellPoint(vec3 centerCell, vec3 offset, float freq) {\n float textureSliceWidth = u_noiseTextureDimensions.x;\n vec3 cell = centerCell + offset;\n cell = wrapVec(cell, textureSliceWidth / u_noiseDetail);\n cell += floor(u_noiseOffset / u_noiseDetail);\n vec3 p = offset + random3(cell);\n return p;\n}\n\nfloat worleyNoise(vec3 p, float freq) {\n vec3 centerCell = floor(p * freq);\n vec3 pointInCell = fract(p * freq);\n float shortestDistance = 1000.0;\n\n for(float z = -1.0; z <= 1.0; z++) {\n for(float y = -1.0; y <= 1.0; y++) {\n for(float x = -1.0; x <= 1.0; x++) {\n vec3 offset = vec3(x, y, z);\n vec3 point = getWorleyCellPoint(centerCell, offset, freq);\n\n float distance = length(pointInCell - point);\n if(distance < shortestDistance) {\n shortestDistance = distance;\n }\n }\n }\n }\n\n return shortestDistance;\n}\n\nconst float MAX_FBM_ITERATIONS = 10.0;\n\nfloat worleyFBMNoise(vec3 p, float octaves, float scale) {\n float noise = 0.0;\n float freq = 1.0;\n float persistence = 0.625;\n for(float i = 0.0; i < MAX_FBM_ITERATIONS; i++) {\n if(i >= octaves) {\n break;\n }\n\n noise += worleyNoise(p * scale, freq * scale) * persistence;\n persistence *= 0.5;\n freq *= 2.0;\n }\n return noise;\n}\n\nvoid main() {\n float textureSliceWidth = u_noiseTextureDimensions.x;\n float inverseNoiseTextureRows = u_noiseTextureDimensions.z;\n float x = mod(v_position.x, textureSliceWidth);\n float y = mod(v_position.y, textureSliceWidth);\n float sliceRow = floor(v_position.y / textureSliceWidth);\n float z = floor(v_position.x / textureSliceWidth) + sliceRow * inverseNoiseTextureRows * textureSliceWidth;\n\n vec3 position = vec3(x, y, z);\n position /= u_noiseDetail;\n float worley0 = clamp(worleyFBMNoise(position, 3.0, 1.0), 0.0, 1.0);\n float worley1 = clamp(worleyFBMNoise(position, 3.0, 2.0), 0.0, 1.0);\n float worley2 = clamp(worleyFBMNoise(position, 3.0, 3.0), 0.0, 1.0);\n out_FragColor = vec4(worley0, worley1, worley2, 1.0);\n}\n";
// packages/engine/Source/Shaders/CloudNoiseVS.js
var import_InlineWorkers1182 = __toESM(require_InlineWorkers(), 1);
var CloudNoiseVS_default = "uniform vec3 u_noiseTextureDimensions;\nin vec2 position;\n\nout vec2 v_position;\n\nvoid main()\n{\n gl_Position = vec4(position, 0.1, 1.0);\n\n float textureSliceWidth = u_noiseTextureDimensions.x;\n float noiseTextureRows = u_noiseTextureDimensions.y;\n float inverseNoiseTextureRows = u_noiseTextureDimensions.z;\n vec2 transformedPos = (position * 0.5) + vec2(0.5);\n transformedPos *= textureSliceWidth;\n transformedPos.x *= textureSliceWidth * inverseNoiseTextureRows;\n transformedPos.y *= noiseTextureRows;\n v_position = transformedPos;\n}\n";
// packages/engine/Source/Shaders/ViewportQuadFS.js
var import_InlineWorkers1183 = __toESM(require_InlineWorkers(), 1);
var ViewportQuadFS_default = "\nin vec2 v_textureCoordinates;\n\nvoid main()\n{\n czm_materialInput materialInput;\n \n materialInput.s = v_textureCoordinates.s;\n materialInput.st = v_textureCoordinates;\n materialInput.str = vec3(v_textureCoordinates, 0.0);\n materialInput.normalEC = vec3(0.0, 0.0, -1.0);\n \n czm_material material = czm_getMaterial(materialInput);\n\n out_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n}\n";
// packages/engine/Source/Core/ArcGISTiledElevationTerrainProvider.js
var import_InlineWorkers1185 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/TileAvailability.js
var import_InlineWorkers1184 = __toESM(require_InlineWorkers(), 1);
function TileAvailability(tilingScheme2, maximumLevel) {
this._tilingScheme = tilingScheme2;
this._maximumLevel = maximumLevel;
this._rootNodes = [];
}
var rectangleScratch5 = new Rectangle_default();
function findNode(level, x, y, nodes) {
const count = nodes.length;
for (let i = 0; i < count; ++i) {
const node = nodes[i];
if (node.x === x && node.y === y && node.level === level) {
return true;
}
}
return false;
}
TileAvailability.prototype.addAvailableTileRange = function(level, startX, startY, endX, endY) {
const tilingScheme2 = this._tilingScheme;
const rootNodes = this._rootNodes;
if (level === 0) {
for (let y = startY; y <= endY; ++y) {
for (let x = startX; x <= endX; ++x) {
if (!findNode(level, x, y, rootNodes)) {
rootNodes.push(new QuadtreeNode(tilingScheme2, void 0, 0, x, y));
}
}
}
}
tilingScheme2.tileXYToRectangle(startX, startY, level, rectangleScratch5);
const west = rectangleScratch5.west;
const north = rectangleScratch5.north;
tilingScheme2.tileXYToRectangle(endX, endY, level, rectangleScratch5);
const east = rectangleScratch5.east;
const south = rectangleScratch5.south;
const rectangleWithLevel = new RectangleWithLevel(
level,
west,
south,
east,
north
);
for (let i = 0; i < rootNodes.length; ++i) {
const rootNode = rootNodes[i];
if (rectanglesOverlap(rootNode.extent, rectangleWithLevel)) {
putRectangleInQuadtree(this._maximumLevel, rootNode, rectangleWithLevel);
}
}
};
TileAvailability.prototype.computeMaximumLevelAtPosition = function(position) {
let node;
for (let nodeIndex = 0; nodeIndex < this._rootNodes.length; ++nodeIndex) {
const rootNode = this._rootNodes[nodeIndex];
if (rectangleContainsPosition(rootNode.extent, position)) {
node = rootNode;
break;
}
}
if (!defined_default(node)) {
return -1;
}
return findMaxLevelFromNode(void 0, node, position);
};
var rectanglesScratch = [];
var remainingToCoverByLevelScratch = [];
var westScratch2 = new Rectangle_default();
var eastScratch = new Rectangle_default();
TileAvailability.prototype.computeBestAvailableLevelOverRectangle = function(rectangle) {
const rectangles = rectanglesScratch;
rectangles.length = 0;
if (rectangle.east < rectangle.west) {
rectangles.push(
Rectangle_default.fromRadians(
-Math.PI,
rectangle.south,
rectangle.east,
rectangle.north,
westScratch2
)
);
rectangles.push(
Rectangle_default.fromRadians(
rectangle.west,
rectangle.south,
Math.PI,
rectangle.north,
eastScratch
)
);
} else {
rectangles.push(rectangle);
}
const remainingToCoverByLevel = remainingToCoverByLevelScratch;
remainingToCoverByLevel.length = 0;
let i;
for (i = 0; i < this._rootNodes.length; ++i) {
updateCoverageWithNode(
remainingToCoverByLevel,
this._rootNodes[i],
rectangles
);
}
for (i = remainingToCoverByLevel.length - 1; i >= 0; --i) {
if (defined_default(remainingToCoverByLevel[i]) && remainingToCoverByLevel[i].length === 0) {
return i;
}
}
return 0;
};
var cartographicScratch5 = new Cartographic_default();
TileAvailability.prototype.isTileAvailable = function(level, x, y) {
const rectangle = this._tilingScheme.tileXYToRectangle(
x,
y,
level,
rectangleScratch5
);
Rectangle_default.center(rectangle, cartographicScratch5);
return this.computeMaximumLevelAtPosition(cartographicScratch5) >= level;
};
TileAvailability.prototype.computeChildMaskForTile = function(level, x, y) {
const childLevel = level + 1;
if (childLevel >= this._maximumLevel) {
return 0;
}
let mask = 0;
mask |= this.isTileAvailable(childLevel, 2 * x, 2 * y + 1) ? 1 : 0;
mask |= this.isTileAvailable(childLevel, 2 * x + 1, 2 * y + 1) ? 2 : 0;
mask |= this.isTileAvailable(childLevel, 2 * x, 2 * y) ? 4 : 0;
mask |= this.isTileAvailable(childLevel, 2 * x + 1, 2 * y) ? 8 : 0;
return mask;
};
function QuadtreeNode(tilingScheme2, parent, level, x, y) {
this.tilingScheme = tilingScheme2;
this.parent = parent;
this.level = level;
this.x = x;
this.y = y;
this.extent = tilingScheme2.tileXYToRectangle(x, y, level);
this.rectangles = [];
this._sw = void 0;
this._se = void 0;
this._nw = void 0;
this._ne = void 0;
}
Object.defineProperties(QuadtreeNode.prototype, {
nw: {
get: function() {
if (!this._nw) {
this._nw = new QuadtreeNode(
this.tilingScheme,
this,
this.level + 1,
this.x * 2,
this.y * 2
);
}
return this._nw;
}
},
ne: {
get: function() {
if (!this._ne) {
this._ne = new QuadtreeNode(
this.tilingScheme,
this,
this.level + 1,
this.x * 2 + 1,
this.y * 2
);
}
return this._ne;
}
},
sw: {
get: function() {
if (!this._sw) {
this._sw = new QuadtreeNode(
this.tilingScheme,
this,
this.level + 1,
this.x * 2,
this.y * 2 + 1
);
}
return this._sw;
}
},
se: {
get: function() {
if (!this._se) {
this._se = new QuadtreeNode(
this.tilingScheme,
this,
this.level + 1,
this.x * 2 + 1,
this.y * 2 + 1
);
}
return this._se;
}
}
});
function RectangleWithLevel(level, west, south, east, north) {
this.level = level;
this.west = west;
this.south = south;
this.east = east;
this.north = north;
}
function rectanglesOverlap(rectangle1, rectangle2) {
const west = Math.max(rectangle1.west, rectangle2.west);
const south = Math.max(rectangle1.south, rectangle2.south);
const east = Math.min(rectangle1.east, rectangle2.east);
const north = Math.min(rectangle1.north, rectangle2.north);
return south < north && west < east;
}
function putRectangleInQuadtree(maxDepth, node, rectangle) {
while (node.level < maxDepth) {
if (rectangleFullyContainsRectangle(node.nw.extent, rectangle)) {
node = node.nw;
} else if (rectangleFullyContainsRectangle(node.ne.extent, rectangle)) {
node = node.ne;
} else if (rectangleFullyContainsRectangle(node.sw.extent, rectangle)) {
node = node.sw;
} else if (rectangleFullyContainsRectangle(node.se.extent, rectangle)) {
node = node.se;
} else {
break;
}
}
if (node.rectangles.length === 0 || node.rectangles[node.rectangles.length - 1].level <= rectangle.level) {
node.rectangles.push(rectangle);
} else {
let index = binarySearch_default(
node.rectangles,
rectangle.level,
rectangleLevelComparator
);
if (index < 0) {
index = ~index;
}
node.rectangles.splice(index, 0, rectangle);
}
}
function rectangleLevelComparator(a3, b) {
return a3.level - b;
}
function rectangleFullyContainsRectangle(potentialContainer, rectangleToTest) {
return rectangleToTest.west >= potentialContainer.west && rectangleToTest.east <= potentialContainer.east && rectangleToTest.south >= potentialContainer.south && rectangleToTest.north <= potentialContainer.north;
}
function rectangleContainsPosition(potentialContainer, positionToTest) {
return positionToTest.longitude >= potentialContainer.west && positionToTest.longitude <= potentialContainer.east && positionToTest.latitude >= potentialContainer.south && positionToTest.latitude <= potentialContainer.north;
}
function findMaxLevelFromNode(stopNode, node, position) {
let maxLevel = 0;
let found = false;
while (!found) {
const nw = node._nw && rectangleContainsPosition(node._nw.extent, position);
const ne = node._ne && rectangleContainsPosition(node._ne.extent, position);
const sw = node._sw && rectangleContainsPosition(node._sw.extent, position);
const se = node._se && rectangleContainsPosition(node._se.extent, position);
if (nw + ne + sw + se > 1) {
if (nw) {
maxLevel = Math.max(
maxLevel,
findMaxLevelFromNode(node, node._nw, position)
);
}
if (ne) {
maxLevel = Math.max(
maxLevel,
findMaxLevelFromNode(node, node._ne, position)
);
}
if (sw) {
maxLevel = Math.max(
maxLevel,
findMaxLevelFromNode(node, node._sw, position)
);
}
if (se) {
maxLevel = Math.max(
maxLevel,
findMaxLevelFromNode(node, node._se, position)
);
}
break;
} else if (nw) {
node = node._nw;
} else if (ne) {
node = node._ne;
} else if (sw) {
node = node._sw;
} else if (se) {
node = node._se;
} else {
found = true;
}
}
while (node !== stopNode) {
const rectangles = node.rectangles;
for (let i = rectangles.length - 1; i >= 0 && rectangles[i].level > maxLevel; --i) {
const rectangle = rectangles[i];
if (rectangleContainsPosition(rectangle, position)) {
maxLevel = rectangle.level;
}
}
node = node.parent;
}
return maxLevel;
}
function updateCoverageWithNode(remainingToCoverByLevel, node, rectanglesToCover) {
if (!node) {
return;
}
let i;
let anyOverlap = false;
for (i = 0; i < rectanglesToCover.length; ++i) {
anyOverlap = anyOverlap || rectanglesOverlap(node.extent, rectanglesToCover[i]);
}
if (!anyOverlap) {
return;
}
const rectangles = node.rectangles;
for (i = 0; i < rectangles.length; ++i) {
const rectangle = rectangles[i];
if (!remainingToCoverByLevel[rectangle.level]) {
remainingToCoverByLevel[rectangle.level] = rectanglesToCover;
}
remainingToCoverByLevel[rectangle.level] = subtractRectangle(
remainingToCoverByLevel[rectangle.level],
rectangle
);
}
updateCoverageWithNode(remainingToCoverByLevel, node._nw, rectanglesToCover);
updateCoverageWithNode(remainingToCoverByLevel, node._ne, rectanglesToCover);
updateCoverageWithNode(remainingToCoverByLevel, node._sw, rectanglesToCover);
updateCoverageWithNode(remainingToCoverByLevel, node._se, rectanglesToCover);
}
function subtractRectangle(rectangleList, rectangleToSubtract) {
const result = [];
for (let i = 0; i < rectangleList.length; ++i) {
const rectangle = rectangleList[i];
if (!rectanglesOverlap(rectangle, rectangleToSubtract)) {
result.push(rectangle);
} else {
if (rectangle.west < rectangleToSubtract.west) {
result.push(
new Rectangle_default(
rectangle.west,
rectangle.south,
rectangleToSubtract.west,
rectangle.north
)
);
}
if (rectangle.east > rectangleToSubtract.east) {
result.push(
new Rectangle_default(
rectangleToSubtract.east,
rectangle.south,
rectangle.east,
rectangle.north
)
);
}
if (rectangle.south < rectangleToSubtract.south) {
result.push(
new Rectangle_default(
Math.max(rectangleToSubtract.west, rectangle.west),
rectangle.south,
Math.min(rectangleToSubtract.east, rectangle.east),
rectangleToSubtract.south
)
);
}
if (rectangle.north > rectangleToSubtract.north) {
result.push(
new Rectangle_default(
Math.max(rectangleToSubtract.west, rectangle.west),
rectangleToSubtract.north,
Math.min(rectangleToSubtract.east, rectangle.east),
rectangle.north
)
);
}
}
}
return result;
}
var TileAvailability_default = TileAvailability;
// packages/engine/Source/Core/ArcGISTiledElevationTerrainProvider.js
var ALL_CHILDREN = 15;
function TerrainProviderBuilder(options) {
this.ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
this.credit = void 0;
this.tilingScheme = void 0;
this.height = void 0;
this.width = void 0;
this.encoding = void 0;
this.lodCount = void 0;
this.hasAvailability = false;
this.tilesAvailable = void 0;
this.tilesAvailabilityLoaded = void 0;
this.levelZeroMaximumGeometricError = void 0;
this.terrainDataStructure = void 0;
}
TerrainProviderBuilder.prototype.build = function(provider) {
provider._credit = this.credit;
provider._tilingScheme = this.tilingScheme;
provider._height = this.height;
provider._width = this.width;
provider._encoding = this.encoding;
provider._lodCount = this.lodCount;
provider._hasAvailability = this.hasAvailability;
provider._tilesAvailable = this.tilesAvailable;
provider._tilesAvailabilityLoaded = this.tilesAvailabilityLoaded;
provider._levelZeroMaximumGeometricError = this.levelZeroMaximumGeometricError;
provider._terrainDataStructure = this.terrainDataStructure;
};
function parseMetadataSuccess(terrainProviderBuilder, metadata) {
const copyrightText = metadata.copyrightText;
if (defined_default(copyrightText)) {
terrainProviderBuilder.credit = new Credit_default(copyrightText);
}
const spatialReference = metadata.spatialReference;
const wkid = spatialReference.latestWkid ?? spatialReference.wkid;
const extent = metadata.extent;
const tilingSchemeOptions = {
ellipsoid: terrainProviderBuilder.ellipsoid
};
if (wkid === 4326) {
tilingSchemeOptions.rectangle = Rectangle_default.fromDegrees(
extent.xmin,
extent.ymin,
extent.xmax,
extent.ymax
);
terrainProviderBuilder.tilingScheme = new GeographicTilingScheme_default(
tilingSchemeOptions
);
} else if (wkid === 3857) {
const epsg3857Bounds = Math.PI * terrainProviderBuilder.ellipsoid.maximumRadius;
if (metadata.extent.xmax > epsg3857Bounds) {
metadata.extent.xmax = epsg3857Bounds;
}
if (metadata.extent.ymax > epsg3857Bounds) {
metadata.extent.ymax = epsg3857Bounds;
}
if (metadata.extent.xmin < -epsg3857Bounds) {
metadata.extent.xmin = -epsg3857Bounds;
}
if (metadata.extent.ymin < -epsg3857Bounds) {
metadata.extent.ymin = -epsg3857Bounds;
}
tilingSchemeOptions.rectangleSouthwestInMeters = new Cartesian2_default(
extent.xmin,
extent.ymin
);
tilingSchemeOptions.rectangleNortheastInMeters = new Cartesian2_default(
extent.xmax,
extent.ymax
);
terrainProviderBuilder.tilingScheme = new WebMercatorTilingScheme_default(
tilingSchemeOptions
);
} else {
throw new RuntimeError_default("Invalid spatial reference");
}
const tileInfo = metadata.tileInfo;
if (!defined_default(tileInfo)) {
throw new RuntimeError_default("tileInfo is required");
}
terrainProviderBuilder.width = tileInfo.rows + 1;
terrainProviderBuilder.height = tileInfo.cols + 1;
terrainProviderBuilder.encoding = tileInfo.format === "LERC" ? HeightmapEncoding_default.LERC : HeightmapEncoding_default.NONE;
terrainProviderBuilder.lodCount = tileInfo.lods.length - 1;
const hasAvailability = terrainProviderBuilder.hasAvailability = metadata.capabilities.indexOf("Tilemap") !== -1;
if (hasAvailability) {
terrainProviderBuilder.tilesAvailable = new TileAvailability_default(
terrainProviderBuilder.tilingScheme,
terrainProviderBuilder.lodCount
);
terrainProviderBuilder.tilesAvailable.addAvailableTileRange(
0,
0,
0,
terrainProviderBuilder.tilingScheme.getNumberOfXTilesAtLevel(0),
terrainProviderBuilder.tilingScheme.getNumberOfYTilesAtLevel(0)
);
terrainProviderBuilder.tilesAvailabilityLoaded = new TileAvailability_default(
terrainProviderBuilder.tilingScheme,
terrainProviderBuilder.lodCount
);
}
terrainProviderBuilder.levelZeroMaximumGeometricError = TerrainProvider_default.getEstimatedLevelZeroGeometricErrorForAHeightmap(
terrainProviderBuilder.tilingScheme.ellipsoid,
terrainProviderBuilder.width,
terrainProviderBuilder.tilingScheme.getNumberOfXTilesAtLevel(0)
);
if (metadata.bandCount > 1) {
console.log(
"ArcGISTiledElevationTerrainProvider: Terrain data has more than 1 band. Using the first one."
);
}
if (defined_default(metadata.minValues) && defined_default(metadata.maxValues)) {
terrainProviderBuilder.terrainDataStructure = {
elementMultiplier: 1,
lowestEncodedHeight: metadata.minValues[0],
highestEncodedHeight: metadata.maxValues[0]
};
} else {
terrainProviderBuilder.terrainDataStructure = {
elementMultiplier: 1
};
}
}
async function requestMetadata4(terrainProviderBuilder, metadataResource, provider) {
try {
const metadata = await metadataResource.fetchJson();
parseMetadataSuccess(terrainProviderBuilder, metadata);
} catch (error) {
const message = `An error occurred while accessing ${metadataResource}.`;
TileProviderError_default.reportError(
void 0,
provider,
defined_default(provider) ? provider._errorEvent : void 0,
message
);
throw error;
}
}
function ArcGISTiledElevationTerrainProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._resource = void 0;
this._credit = void 0;
this._tilingScheme = void 0;
this._levelZeroMaximumGeometricError = void 0;
this._maxLevel = void 0;
this._terrainDataStructure = void 0;
this._width = void 0;
this._height = void 0;
this._encoding = void 0;
this._lodCount = void 0;
this._hasAvailability = false;
this._tilesAvailable = void 0;
this._tilesAvailabilityLoaded = void 0;
this._availableCache = {};
this._errorEvent = new Event_default();
}
Object.defineProperties(ArcGISTiledElevationTerrainProvider.prototype, {
/**
* Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof ArcGISTiledElevationTerrainProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets the credit to display when this terrain provider is active. Typically this is used to credit
* the source of the terrain.
* @memberof ArcGISTiledElevationTerrainProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return this._credit;
}
},
/**
* Gets the tiling scheme used by this provider.
* @memberof ArcGISTiledElevationTerrainProvider.prototype
* @type {GeographicTilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._tilingScheme;
}
},
/**
* Gets a value indicating whether or not the provider includes a water mask. The water mask
* indicates which areas of the globe are water rather than land, so they can be rendered
* as a reflective surface with animated waves.
* @memberof ArcGISTiledElevationTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasWaterMask: {
get: function() {
return false;
}
},
/**
* Gets a value indicating whether or not the requested tiles include vertex normals.
* @memberof ArcGISTiledElevationTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasVertexNormals: {
get: function() {
return false;
}
},
/**
* Gets an object that can be used to determine availability of terrain from this provider, such as
* at points and in rectangles. This property may be undefined if availability
* information is not available.
* @memberof ArcGISTiledElevationTerrainProvider.prototype
* @type {TileAvailability|undefined}
* @readonly
*/
availability: {
get: function() {
return this._tilesAvailable;
}
}
});
ArcGISTiledElevationTerrainProvider.fromUrl = async function(url2, options) {
Check_default.defined("url", url2);
options = options ?? Frozen_default.EMPTY_OBJECT;
url2 = await Promise.resolve(url2);
let resource = Resource_default.createIfNeeded(url2);
resource.appendForwardSlash();
if (defined_default(options.token)) {
resource = resource.getDerivedResource({
queryParameters: {
token: options.token
}
});
}
const metadataResource = resource.getDerivedResource({
queryParameters: {
f: "pjson"
}
});
const terrainProviderBuilder = new TerrainProviderBuilder(options);
await requestMetadata4(terrainProviderBuilder, metadataResource);
const provider = new ArcGISTiledElevationTerrainProvider(options);
terrainProviderBuilder.build(provider);
provider._resource = resource;
return provider;
};
ArcGISTiledElevationTerrainProvider.prototype.requestTileGeometry = function(x, y, level, request) {
const tileResource = this._resource.getDerivedResource({
url: `tile/${level}/${y}/${x}`,
request
});
const hasAvailability = this._hasAvailability;
let availabilityPromise = Promise.resolve(true);
let availabilityRequest;
if (hasAvailability && !defined_default(isTileAvailable(this, level + 1, x * 2, y * 2))) {
const availabilityResult = requestAvailability(
this,
level + 1,
x * 2,
y * 2
);
availabilityPromise = availabilityResult.promise;
availabilityRequest = availabilityResult.request;
}
const promise = tileResource.fetchArrayBuffer();
if (!defined_default(promise) || !defined_default(availabilityPromise)) {
return void 0;
}
const that = this;
const tilesAvailable = this._tilesAvailable;
return Promise.all([promise, availabilityPromise]).then(function(result) {
return new HeightmapTerrainData_default({
buffer: result[0],
width: that._width,
height: that._height,
childTileMask: hasAvailability ? tilesAvailable.computeChildMaskForTile(level, x, y) : ALL_CHILDREN,
structure: that._terrainDataStructure,
encoding: that._encoding
});
}).catch(async function(error) {
if (defined_default(availabilityRequest) && availabilityRequest.state === RequestState_default.CANCELLED) {
request.cancel();
try {
await request.deferred?.promise;
} catch {
}
request.state = RequestState_default.CANCELLED;
return Promise.reject(error);
}
return Promise.reject(error);
});
};
function isTileAvailable(that, level, x, y) {
if (!that._hasAvailability) {
return void 0;
}
const tilesAvailabilityLoaded = that._tilesAvailabilityLoaded;
const tilesAvailable = that._tilesAvailable;
if (level > that._lodCount) {
return false;
}
if (tilesAvailable.isTileAvailable(level, x, y)) {
return true;
}
if (tilesAvailabilityLoaded.isTileAvailable(level, x, y)) {
return false;
}
return void 0;
}
ArcGISTiledElevationTerrainProvider.prototype.getLevelMaximumGeometricError = function(level) {
return this._levelZeroMaximumGeometricError / (1 << level);
};
ArcGISTiledElevationTerrainProvider.prototype.getTileDataAvailable = function(x, y, level) {
if (!this._hasAvailability) {
return void 0;
}
const result = isTileAvailable(this, level, x, y);
if (defined_default(result)) {
return result;
}
requestAvailability(this, level, x, y);
return void 0;
};
ArcGISTiledElevationTerrainProvider.prototype.loadTileDataAvailability = function(x, y, level) {
return void 0;
};
function findRange(origin, width, height, data) {
const endCol = width - 1;
const endRow = height - 1;
const value = data[origin.y * width + origin.x];
const endingIndices = [];
const range = {
startX: origin.x,
startY: origin.y,
endX: 0,
endY: 0
};
const corner = new Cartesian2_default(origin.x + 1, origin.y + 1);
let doneX = false;
let doneY = false;
while (!(doneX && doneY)) {
let endX = corner.x;
const endY = doneY ? corner.y + 1 : corner.y;
if (!doneX) {
for (let y = origin.y; y < endY; ++y) {
if (data[y * width + corner.x] !== value) {
doneX = true;
break;
}
}
if (doneX) {
endingIndices.push(new Cartesian2_default(corner.x, origin.y));
--corner.x;
--endX;
range.endX = corner.x;
} else if (corner.x === endCol) {
range.endX = corner.x;
doneX = true;
} else {
++corner.x;
}
}
if (!doneY) {
const col = corner.y * width;
for (let x = origin.x; x <= endX; ++x) {
if (data[col + x] !== value) {
doneY = true;
break;
}
}
if (doneY) {
endingIndices.push(new Cartesian2_default(origin.x, corner.y));
--corner.y;
range.endY = corner.y;
} else if (corner.y === endRow) {
range.endY = corner.y;
doneY = true;
} else {
++corner.y;
}
}
}
return {
endingIndices,
range,
value
};
}
function computeAvailability(x, y, width, height, data) {
const ranges = [];
const singleValue = data.every(function(val) {
return val === data[0];
});
if (singleValue) {
if (data[0] === 1) {
ranges.push({
startX: x,
startY: y,
endX: x + width - 1,
endY: y + height - 1
});
}
return ranges;
}
let positions = [new Cartesian2_default(0, 0)];
while (positions.length > 0) {
const origin = positions.pop();
const result = findRange(origin, width, height, data);
if (result.value === 1) {
const range = result.range;
range.startX += x;
range.endX += x;
range.startY += y;
range.endY += y;
ranges.push(range);
}
const endingIndices = result.endingIndices;
if (endingIndices.length > 0) {
positions = positions.concat(endingIndices);
}
}
return ranges;
}
function requestAvailability(that, level, x, y) {
if (!that._hasAvailability) {
return {};
}
const xOffset = Math.floor(x / 128) * 128;
const yOffset = Math.floor(y / 128) * 128;
const dim = Math.min(1 << level, 128);
const url2 = `tilemap/${level}/${yOffset}/${xOffset}/${dim}/${dim}`;
const availableCache = that._availableCache;
if (defined_default(availableCache[url2])) {
return availableCache[url2];
}
const request = new Request_default({
throttle: false,
throttleByServer: true,
type: RequestType_default.TERRAIN
});
const tilemapResource = that._resource.getDerivedResource({
url: url2,
request
});
let promise = tilemapResource.fetchJson();
if (!defined_default(promise)) {
return {};
}
promise = promise.then(function(result) {
const available = computeAvailability(
xOffset,
yOffset,
dim,
dim,
result.data
);
that._tilesAvailabilityLoaded.addAvailableTileRange(
level,
xOffset,
yOffset,
xOffset + dim,
yOffset + dim
);
const tilesAvailable = that._tilesAvailable;
for (let i = 0; i < available.length; ++i) {
const range = available[i];
tilesAvailable.addAvailableTileRange(
level,
range.startX,
range.startY,
range.endX,
range.endY
);
}
return isTileAvailable(that, level, x, y);
});
availableCache[url2] = {
promise,
request
};
promise = promise.finally(function(result) {
delete availableCache[url2];
return result;
});
return {
promise,
request
};
}
var ArcGISTiledElevationTerrainProvider_default = ArcGISTiledElevationTerrainProvider;
// packages/engine/Source/Core/BingMapsGeocoderService.js
var import_InlineWorkers1186 = __toESM(require_InlineWorkers(), 1);
var url = "https://dev.virtualearth.net/REST/v1/Locations";
function BingMapsGeocoderService(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const key = options.key;
if (!defined_default(key)) {
throw new DeveloperError_default("options.key is required.");
}
this._key = key;
const queryParameters = {
key
};
if (defined_default(options.culture)) {
queryParameters.culture = options.culture;
}
this._resource = new Resource_default({
url,
queryParameters
});
this._credit = new Credit_default(
`
`,
false
);
}
Object.defineProperties(BingMapsGeocoderService.prototype, {
/**
* The URL endpoint for the Bing geocoder service
* @type {string}
* @memberof BingMapsGeocoderService.prototype
* @readonly
*/
url: {
get: function() {
return url;
}
},
/**
* The key for the Bing geocoder service
* @type {string}
* @memberof BingMapsGeocoderService.prototype
* @readonly
*/
key: {
get: function() {
return this._key;
}
},
/**
* Gets the credit to display after a geocode is performed. Typically this is used to credit
* the geocoder service.
* @memberof BingMapsGeocoderService.prototype
* @type {Credit|undefined}
* @readonly
*/
credit: {
get: function() {
return this._credit;
}
}
});
BingMapsGeocoderService.prototype.geocode = async function(query) {
Check_default.typeOf.string("query", query);
const resource = this._resource.getDerivedResource({
queryParameters: {
query
}
});
return resource.fetchJsonp("jsonp").then(function(result) {
if (result.resourceSets.length === 0) {
return [];
}
const results = result.resourceSets[0].resources;
return results.map(function(resource2) {
const bbox = resource2.bbox;
const south = bbox[0];
const west = bbox[1];
const north = bbox[2];
const east = bbox[3];
return {
displayName: resource2.name,
destination: Rectangle_default.fromDegrees(west, south, east, north)
};
});
});
};
var BingMapsGeocoderService_default = BingMapsGeocoderService;
// packages/engine/Source/Core/CartographicGeocoderService.js
var import_InlineWorkers1187 = __toESM(require_InlineWorkers(), 1);
function CartographicGeocoderService() {
}
Object.defineProperties(CartographicGeocoderService.prototype, {
/**
* Gets the credit to display after a geocode is performed. Typically this is used to credit
* the geocoder service.
* @memberof CartographicGeocoderService.prototype
* @type {Credit|undefined}
* @readonly
*/
credit: {
get: function() {
return void 0;
}
}
});
CartographicGeocoderService.prototype.geocode = function(query) {
Check_default.typeOf.string("query", query);
const splitQuery = query.match(/[^\s,\n]+/g);
if (splitQuery.length === 2 || splitQuery.length === 3) {
let longitude = +splitQuery[0];
let latitude = +splitQuery[1];
const height = splitQuery.length === 3 ? +splitQuery[2] : 300;
if (isNaN(longitude) && isNaN(latitude)) {
const coordTest = /^(\d+.?\d*)([nsew])/i;
for (let i = 0; i < splitQuery.length; ++i) {
const splitCoord = splitQuery[i].match(coordTest);
if (coordTest.test(splitQuery[i]) && splitCoord.length === 3) {
if (/^[ns]/i.test(splitCoord[2])) {
latitude = /^[n]/i.test(splitCoord[2]) ? +splitCoord[1] : -splitCoord[1];
} else if (/^[ew]/i.test(splitCoord[2])) {
longitude = /^[e]/i.test(splitCoord[2]) ? +splitCoord[1] : -splitCoord[1];
}
}
}
}
if (!isNaN(longitude) && !isNaN(latitude) && !isNaN(height)) {
const result = {
displayName: query,
destination: Cartesian3_default.fromDegrees(longitude, latitude, height)
};
return Promise.resolve([result]);
}
}
return Promise.resolve([]);
};
var CartographicGeocoderService_default = CartographicGeocoderService;
// packages/engine/Source/Core/CatmullRomSpline.js
var import_InlineWorkers1188 = __toESM(require_InlineWorkers(), 1);
var scratchTimeVec2 = new Cartesian4_default();
var scratchTemp0 = new Cartesian3_default();
var scratchTemp1 = new Cartesian3_default();
function createEvaluateFunction2(spline) {
const points = spline.points;
const times = spline.times;
if (points.length < 3) {
const t0 = times[0];
const invSpan = 1 / (times[1] - t0);
const p0 = points[0];
const p1 = points[1];
return function(time, result) {
if (!defined_default(result)) {
result = new Cartesian3_default();
}
const u3 = (time - t0) * invSpan;
return Cartesian3_default.lerp(p0, p1, u3, result);
};
}
return function(time, result) {
if (!defined_default(result)) {
result = new Cartesian3_default();
}
const i = spline._lastTimeIndex = spline.findTimeInterval(
time,
spline._lastTimeIndex
);
const u3 = (time - times[i]) / (times[i + 1] - times[i]);
const timeVec = scratchTimeVec2;
timeVec.z = u3;
timeVec.y = u3 * u3;
timeVec.x = timeVec.y * u3;
timeVec.w = 1;
let p0;
let p1;
let p2;
let p3;
let coefs;
if (i === 0) {
p0 = points[0];
p1 = points[1];
p2 = spline.firstTangent;
p3 = Cartesian3_default.subtract(points[2], p0, scratchTemp0);
Cartesian3_default.multiplyByScalar(p3, 0.5, p3);
coefs = Matrix4_default.multiplyByVector(
HermiteSpline_default.hermiteCoefficientMatrix,
timeVec,
timeVec
);
} else if (i === points.length - 2) {
p0 = points[i];
p1 = points[i + 1];
p3 = spline.lastTangent;
p2 = Cartesian3_default.subtract(p1, points[i - 1], scratchTemp0);
Cartesian3_default.multiplyByScalar(p2, 0.5, p2);
coefs = Matrix4_default.multiplyByVector(
HermiteSpline_default.hermiteCoefficientMatrix,
timeVec,
timeVec
);
} else {
p0 = points[i - 1];
p1 = points[i];
p2 = points[i + 1];
p3 = points[i + 2];
coefs = Matrix4_default.multiplyByVector(
CatmullRomSpline.catmullRomCoefficientMatrix,
timeVec,
timeVec
);
}
result = Cartesian3_default.multiplyByScalar(p0, coefs.x, result);
Cartesian3_default.multiplyByScalar(p1, coefs.y, scratchTemp1);
Cartesian3_default.add(result, scratchTemp1, result);
Cartesian3_default.multiplyByScalar(p2, coefs.z, scratchTemp1);
Cartesian3_default.add(result, scratchTemp1, result);
Cartesian3_default.multiplyByScalar(p3, coefs.w, scratchTemp1);
return Cartesian3_default.add(result, scratchTemp1, result);
};
}
var firstTangentScratch = new Cartesian3_default();
var lastTangentScratch = new Cartesian3_default();
function CatmullRomSpline(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const points = options.points;
const times = options.times;
let firstTangent = options.firstTangent;
let lastTangent = options.lastTangent;
Check_default.defined("points", points);
Check_default.defined("times", times);
Check_default.typeOf.number.greaterThanOrEquals("points.length", points.length, 2);
Check_default.typeOf.number.equals(
"times.length",
"points.length",
times.length,
points.length
);
if (points.length > 2) {
if (!defined_default(firstTangent)) {
firstTangent = firstTangentScratch;
Cartesian3_default.multiplyByScalar(points[1], 2, firstTangent);
Cartesian3_default.subtract(firstTangent, points[2], firstTangent);
Cartesian3_default.subtract(firstTangent, points[0], firstTangent);
Cartesian3_default.multiplyByScalar(firstTangent, 0.5, firstTangent);
}
if (!defined_default(lastTangent)) {
const n = points.length - 1;
lastTangent = lastTangentScratch;
Cartesian3_default.multiplyByScalar(points[n - 1], 2, lastTangent);
Cartesian3_default.subtract(points[n], lastTangent, lastTangent);
Cartesian3_default.add(lastTangent, points[n - 2], lastTangent);
Cartesian3_default.multiplyByScalar(lastTangent, 0.5, lastTangent);
}
}
this._times = times;
this._points = points;
this._firstTangent = Cartesian3_default.clone(firstTangent);
this._lastTangent = Cartesian3_default.clone(lastTangent);
this._evaluateFunction = createEvaluateFunction2(this);
this._lastTimeIndex = 0;
}
Object.defineProperties(CatmullRomSpline.prototype, {
/**
* An array of times for the control points.
*
* @memberof CatmullRomSpline.prototype
*
* @type {number[]}
* @readonly
*/
times: {
get: function() {
return this._times;
}
},
/**
* An array of {@link Cartesian3} control points.
*
* @memberof CatmullRomSpline.prototype
*
* @type {Cartesian3[]}
* @readonly
*/
points: {
get: function() {
return this._points;
}
},
/**
* The tangent at the first control point.
*
* @memberof CatmullRomSpline.prototype
*
* @type {Cartesian3}
* @readonly
*/
firstTangent: {
get: function() {
return this._firstTangent;
}
},
/**
* The tangent at the last control point.
*
* @memberof CatmullRomSpline.prototype
*
* @type {Cartesian3}
* @readonly
*/
lastTangent: {
get: function() {
return this._lastTangent;
}
}
});
CatmullRomSpline.catmullRomCoefficientMatrix = new Matrix4_default(
-0.5,
1,
-0.5,
0,
1.5,
-2.5,
0,
1,
-1.5,
2,
0.5,
0,
0.5,
-0.5,
0,
0
);
CatmullRomSpline.prototype.findTimeInterval = Spline_default.prototype.findTimeInterval;
CatmullRomSpline.prototype.wrapTime = Spline_default.prototype.wrapTime;
CatmullRomSpline.prototype.clampTime = Spline_default.prototype.clampTime;
CatmullRomSpline.prototype.evaluate = function(time, result) {
return this._evaluateFunction(time, result);
};
var CatmullRomSpline_default = CatmullRomSpline;
// packages/engine/Source/Core/CesiumTerrainProvider.js
var import_InlineWorkers1191 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/QuantizedMeshTerrainData.js
var import_InlineWorkers1190 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/Intersections2D.js
var import_InlineWorkers1189 = __toESM(require_InlineWorkers(), 1);
var Intersections2D = {};
Intersections2D.clipTriangleAtAxisAlignedThreshold = function(threshold, keepAbove, u0, u12, u22, result) {
if (!defined_default(threshold)) {
throw new DeveloperError_default("threshold is required.");
}
if (!defined_default(keepAbove)) {
throw new DeveloperError_default("keepAbove is required.");
}
if (!defined_default(u0)) {
throw new DeveloperError_default("u0 is required.");
}
if (!defined_default(u12)) {
throw new DeveloperError_default("u1 is required.");
}
if (!defined_default(u22)) {
throw new DeveloperError_default("u2 is required.");
}
if (!defined_default(result)) {
result = [];
} else {
result.length = 0;
}
let u0Behind;
let u1Behind;
let u2Behind;
if (keepAbove) {
u0Behind = u0 < threshold;
u1Behind = u12 < threshold;
u2Behind = u22 < threshold;
} else {
u0Behind = u0 > threshold;
u1Behind = u12 > threshold;
u2Behind = u22 > threshold;
}
const numBehind = u0Behind + u1Behind + u2Behind;
let u01Ratio;
let u02Ratio;
let u12Ratio;
let u10Ratio;
let u20Ratio;
let u21Ratio;
if (numBehind === 1) {
if (u0Behind) {
u01Ratio = (threshold - u0) / (u12 - u0);
u02Ratio = (threshold - u0) / (u22 - u0);
result.push(1);
result.push(2);
if (u02Ratio !== 1) {
result.push(-1);
result.push(0);
result.push(2);
result.push(u02Ratio);
}
if (u01Ratio !== 1) {
result.push(-1);
result.push(0);
result.push(1);
result.push(u01Ratio);
}
} else if (u1Behind) {
u12Ratio = (threshold - u12) / (u22 - u12);
u10Ratio = (threshold - u12) / (u0 - u12);
result.push(2);
result.push(0);
if (u10Ratio !== 1) {
result.push(-1);
result.push(1);
result.push(0);
result.push(u10Ratio);
}
if (u12Ratio !== 1) {
result.push(-1);
result.push(1);
result.push(2);
result.push(u12Ratio);
}
} else if (u2Behind) {
u20Ratio = (threshold - u22) / (u0 - u22);
u21Ratio = (threshold - u22) / (u12 - u22);
result.push(0);
result.push(1);
if (u21Ratio !== 1) {
result.push(-1);
result.push(2);
result.push(1);
result.push(u21Ratio);
}
if (u20Ratio !== 1) {
result.push(-1);
result.push(2);
result.push(0);
result.push(u20Ratio);
}
}
} else if (numBehind === 2) {
if (!u0Behind && u0 !== threshold) {
u10Ratio = (threshold - u12) / (u0 - u12);
u20Ratio = (threshold - u22) / (u0 - u22);
result.push(0);
result.push(-1);
result.push(1);
result.push(0);
result.push(u10Ratio);
result.push(-1);
result.push(2);
result.push(0);
result.push(u20Ratio);
} else if (!u1Behind && u12 !== threshold) {
u21Ratio = (threshold - u22) / (u12 - u22);
u01Ratio = (threshold - u0) / (u12 - u0);
result.push(1);
result.push(-1);
result.push(2);
result.push(1);
result.push(u21Ratio);
result.push(-1);
result.push(0);
result.push(1);
result.push(u01Ratio);
} else if (!u2Behind && u22 !== threshold) {
u02Ratio = (threshold - u0) / (u22 - u0);
u12Ratio = (threshold - u12) / (u22 - u12);
result.push(2);
result.push(-1);
result.push(0);
result.push(2);
result.push(u02Ratio);
result.push(-1);
result.push(1);
result.push(2);
result.push(u12Ratio);
}
} else if (numBehind !== 3) {
result.push(0);
result.push(1);
result.push(2);
}
return result;
};
Intersections2D.computeBarycentricCoordinates = function(x, y, x1, y1, x2, y2, x3, y3, result) {
if (!defined_default(x)) {
throw new DeveloperError_default("x is required.");
}
if (!defined_default(y)) {
throw new DeveloperError_default("y is required.");
}
if (!defined_default(x1)) {
throw new DeveloperError_default("x1 is required.");
}
if (!defined_default(y1)) {
throw new DeveloperError_default("y1 is required.");
}
if (!defined_default(x2)) {
throw new DeveloperError_default("x2 is required.");
}
if (!defined_default(y2)) {
throw new DeveloperError_default("y2 is required.");
}
if (!defined_default(x3)) {
throw new DeveloperError_default("x3 is required.");
}
if (!defined_default(y3)) {
throw new DeveloperError_default("y3 is required.");
}
const x1mx3 = x1 - x3;
const x3mx2 = x3 - x2;
const y2my3 = y2 - y3;
const y1my3 = y1 - y3;
const inverseDeterminant = 1 / (y2my3 * x1mx3 + x3mx2 * y1my3);
const ymy3 = y - y3;
const xmx3 = x - x3;
const l1 = (y2my3 * xmx3 + x3mx2 * ymy3) * inverseDeterminant;
const l2 = (-y1my3 * xmx3 + x1mx3 * ymy3) * inverseDeterminant;
const l3 = 1 - l1 - l2;
if (defined_default(result)) {
result.x = l1;
result.y = l2;
result.z = l3;
return result;
}
return new Cartesian3_default(l1, l2, l3);
};
Intersections2D.computeLineSegmentLineSegmentIntersection = function(x00, y00, x01, y01, x10, y10, x11, y11, result) {
Check_default.typeOf.number("x00", x00);
Check_default.typeOf.number("y00", y00);
Check_default.typeOf.number("x01", x01);
Check_default.typeOf.number("y01", y01);
Check_default.typeOf.number("x10", x10);
Check_default.typeOf.number("y10", y10);
Check_default.typeOf.number("x11", x11);
Check_default.typeOf.number("y11", y11);
const numerator1A = (x11 - x10) * (y00 - y10) - (y11 - y10) * (x00 - x10);
const numerator1B = (x01 - x00) * (y00 - y10) - (y01 - y00) * (x00 - x10);
const denominator1 = (y11 - y10) * (x01 - x00) - (x11 - x10) * (y01 - y00);
if (denominator1 === 0) {
return;
}
const ua1 = numerator1A / denominator1;
const ub1 = numerator1B / denominator1;
if (ua1 >= 0 && ua1 <= 1 && ub1 >= 0 && ub1 <= 1) {
if (!defined_default(result)) {
result = new Cartesian2_default();
}
result.x = x00 + ua1 * (x01 - x00);
result.y = y00 + ua1 * (y01 - y00);
return result;
}
};
var Intersections2D_default = Intersections2D;
// packages/engine/Source/Core/QuantizedMeshTerrainData.js
function QuantizedMeshTerrainData(options) {
if (!defined_default(options) || !defined_default(options.quantizedVertices)) {
throw new DeveloperError_default("options.quantizedVertices is required.");
}
if (!defined_default(options.indices)) {
throw new DeveloperError_default("options.indices is required.");
}
if (!defined_default(options.minimumHeight)) {
throw new DeveloperError_default("options.minimumHeight is required.");
}
if (!defined_default(options.maximumHeight)) {
throw new DeveloperError_default("options.maximumHeight is required.");
}
if (!defined_default(options.maximumHeight)) {
throw new DeveloperError_default("options.maximumHeight is required.");
}
if (!defined_default(options.boundingSphere)) {
throw new DeveloperError_default("options.boundingSphere is required.");
}
if (!defined_default(options.horizonOcclusionPoint)) {
throw new DeveloperError_default("options.horizonOcclusionPoint is required.");
}
if (!defined_default(options.westIndices)) {
throw new DeveloperError_default("options.westIndices is required.");
}
if (!defined_default(options.southIndices)) {
throw new DeveloperError_default("options.southIndices is required.");
}
if (!defined_default(options.eastIndices)) {
throw new DeveloperError_default("options.eastIndices is required.");
}
if (!defined_default(options.northIndices)) {
throw new DeveloperError_default("options.northIndices is required.");
}
if (!defined_default(options.westSkirtHeight)) {
throw new DeveloperError_default("options.westSkirtHeight is required.");
}
if (!defined_default(options.southSkirtHeight)) {
throw new DeveloperError_default("options.southSkirtHeight is required.");
}
if (!defined_default(options.eastSkirtHeight)) {
throw new DeveloperError_default("options.eastSkirtHeight is required.");
}
if (!defined_default(options.northSkirtHeight)) {
throw new DeveloperError_default("options.northSkirtHeight is required.");
}
this._quantizedVertices = options.quantizedVertices;
this._encodedNormals = options.encodedNormals;
this._indices = options.indices;
this._minimumHeight = options.minimumHeight;
this._maximumHeight = options.maximumHeight;
this._boundingSphere = options.boundingSphere;
this._orientedBoundingBox = options.orientedBoundingBox;
this._horizonOcclusionPoint = options.horizonOcclusionPoint;
this._credits = options.credits;
const vertexCount = this._quantizedVertices.length / 3;
const uValues = this._uValues = this._quantizedVertices.subarray(
0,
vertexCount
);
const vValues = this._vValues = this._quantizedVertices.subarray(
vertexCount,
2 * vertexCount
);
this._heightValues = this._quantizedVertices.subarray(
2 * vertexCount,
3 * vertexCount
);
function sortByV(a3, b) {
return vValues[a3] - vValues[b];
}
function sortByU(a3, b) {
return uValues[a3] - uValues[b];
}
this._westIndices = sortIndicesIfNecessary(
options.westIndices,
sortByV,
vertexCount
);
this._southIndices = sortIndicesIfNecessary(
options.southIndices,
sortByU,
vertexCount
);
this._eastIndices = sortIndicesIfNecessary(
options.eastIndices,
sortByV,
vertexCount
);
this._northIndices = sortIndicesIfNecessary(
options.northIndices,
sortByU,
vertexCount
);
this._westSkirtHeight = options.westSkirtHeight;
this._southSkirtHeight = options.southSkirtHeight;
this._eastSkirtHeight = options.eastSkirtHeight;
this._northSkirtHeight = options.northSkirtHeight;
this._childTileMask = options.childTileMask ?? 15;
this._createdByUpsampling = options.createdByUpsampling ?? false;
this._waterMask = options.waterMask;
this._mesh = void 0;
}
Object.defineProperties(QuantizedMeshTerrainData.prototype, {
/**
* An array of credits for this tile.
* @memberof QuantizedMeshTerrainData.prototype
* @type {Credit[]}
*/
credits: {
get: function() {
return this._credits;
}
},
/**
* The water mask included in this terrain data, if any. A water mask is a rectangular
* Uint8Array or image where a value of 255 indicates water and a value of 0 indicates land.
* Values in between 0 and 255 are allowed as well to smoothly blend between land and water.
* @memberof QuantizedMeshTerrainData.prototype
* @type {Uint8Array|HTMLImageElement|HTMLCanvasElement|undefined}
*/
waterMask: {
get: function() {
return this._waterMask;
}
},
childTileMask: {
get: function() {
return this._childTileMask;
}
},
canUpsample: {
get: function() {
return defined_default(this._mesh);
}
}
});
var arrayScratch2 = [];
function sortIndicesIfNecessary(indices, sortFunction, vertexCount) {
arrayScratch2.length = indices.length;
let needsSort = false;
for (let i = 0, len = indices.length; i < len; ++i) {
arrayScratch2[i] = indices[i];
needsSort = needsSort || i > 0 && sortFunction(indices[i - 1], indices[i]) > 0;
}
if (needsSort) {
arrayScratch2.sort(sortFunction);
return IndexDatatype_default.createTypedArray(vertexCount, arrayScratch2);
}
return indices;
}
var createMeshTaskName2 = "createVerticesFromQuantizedTerrainMesh";
var createMeshTaskProcessorNoThrottle2 = new TaskProcessor_default(createMeshTaskName2);
var createMeshTaskProcessorThrottle2 = new TaskProcessor_default(
createMeshTaskName2,
TerrainData_default.maximumAsynchronousTasks
);
QuantizedMeshTerrainData.prototype.createMesh = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("options.tilingScheme", options.tilingScheme);
Check_default.typeOf.number("options.x", options.x);
Check_default.typeOf.number("options.y", options.y);
Check_default.typeOf.number("options.level", options.level);
const tilingScheme2 = options.tilingScheme;
const x = options.x;
const y = options.y;
const level = options.level;
const exaggeration = options.exaggeration ?? 1;
const exaggerationRelativeHeight = options.exaggerationRelativeHeight ?? 0;
const throttle = options.throttle ?? true;
const ellipsoid = tilingScheme2.ellipsoid;
const rectangle = tilingScheme2.tileXYToRectangle(x, y, level);
const createMeshTaskProcessor = throttle ? createMeshTaskProcessorThrottle2 : createMeshTaskProcessorNoThrottle2;
const verticesPromise = createMeshTaskProcessor.scheduleTask({
minimumHeight: this._minimumHeight,
maximumHeight: this._maximumHeight,
quantizedVertices: this._quantizedVertices,
octEncodedNormals: this._encodedNormals,
includeWebMercatorT: true,
indices: this._indices,
westIndices: this._westIndices,
southIndices: this._southIndices,
eastIndices: this._eastIndices,
northIndices: this._northIndices,
westSkirtHeight: this._westSkirtHeight,
southSkirtHeight: this._southSkirtHeight,
eastSkirtHeight: this._eastSkirtHeight,
northSkirtHeight: this._northSkirtHeight,
rectangle,
relativeToCenter: this._boundingSphere.center,
ellipsoid,
exaggeration,
exaggerationRelativeHeight
});
if (!defined_default(verticesPromise)) {
return void 0;
}
const that = this;
return Promise.resolve(verticesPromise).then(function(result) {
const vertexCountWithoutSkirts = that._quantizedVertices.length / 3;
const vertexCount = vertexCountWithoutSkirts + that._westIndices.length + that._southIndices.length + that._eastIndices.length + that._northIndices.length;
const indicesTypedArray = IndexDatatype_default.createTypedArray(
vertexCount,
result.indices
);
const vertices = new Float32Array(result.vertices);
const rtc = result.center;
const minimumHeight = result.minimumHeight;
const maximumHeight = result.maximumHeight;
const boundingSphere = that._boundingSphere;
const obb = that._orientedBoundingBox;
const occludeePointInScaledSpace = Cartesian3_default.clone(result.occludeePointInScaledSpace) ?? that._horizonOcclusionPoint;
const stride = result.vertexStride;
const terrainEncoding = TerrainEncoding_default.clone(result.encoding);
that._mesh = new TerrainMesh_default(
rtc,
vertices,
indicesTypedArray,
result.indexCountWithoutSkirts,
vertexCountWithoutSkirts,
minimumHeight,
maximumHeight,
boundingSphere,
occludeePointInScaledSpace,
stride,
obb,
terrainEncoding,
result.westIndicesSouthToNorth,
result.southIndicesEastToWest,
result.eastIndicesNorthToSouth,
result.northIndicesWestToEast
);
that._quantizedVertices = void 0;
that._encodedNormals = void 0;
that._indices = void 0;
that._uValues = void 0;
that._vValues = void 0;
that._heightValues = void 0;
that._westIndices = void 0;
that._southIndices = void 0;
that._eastIndices = void 0;
that._northIndices = void 0;
return that._mesh;
});
};
var upsampleTaskProcessor = new TaskProcessor_default(
"upsampleQuantizedTerrainMesh",
TerrainData_default.maximumAsynchronousTasks
);
QuantizedMeshTerrainData.prototype.upsample = function(tilingScheme2, thisX, thisY, thisLevel, descendantX, descendantY, descendantLevel) {
if (!defined_default(tilingScheme2)) {
throw new DeveloperError_default("tilingScheme is required.");
}
if (!defined_default(thisX)) {
throw new DeveloperError_default("thisX is required.");
}
if (!defined_default(thisY)) {
throw new DeveloperError_default("thisY is required.");
}
if (!defined_default(thisLevel)) {
throw new DeveloperError_default("thisLevel is required.");
}
if (!defined_default(descendantX)) {
throw new DeveloperError_default("descendantX is required.");
}
if (!defined_default(descendantY)) {
throw new DeveloperError_default("descendantY is required.");
}
if (!defined_default(descendantLevel)) {
throw new DeveloperError_default("descendantLevel is required.");
}
const levelDifference = descendantLevel - thisLevel;
if (levelDifference > 1) {
throw new DeveloperError_default(
"Upsampling through more than one level at a time is not currently supported."
);
}
const mesh = this._mesh;
if (!defined_default(this._mesh)) {
return void 0;
}
const isEastChild = thisX * 2 !== descendantX;
const isNorthChild = thisY * 2 === descendantY;
const ellipsoid = tilingScheme2.ellipsoid;
const childRectangle = tilingScheme2.tileXYToRectangle(
descendantX,
descendantY,
descendantLevel
);
const upsamplePromise = upsampleTaskProcessor.scheduleTask({
vertices: mesh.vertices,
vertexCountWithoutSkirts: mesh.vertexCountWithoutSkirts,
indices: mesh.indices,
indexCountWithoutSkirts: mesh.indexCountWithoutSkirts,
encoding: mesh.encoding,
minimumHeight: this._minimumHeight,
maximumHeight: this._maximumHeight,
isEastChild,
isNorthChild,
childRectangle,
ellipsoid
});
if (!defined_default(upsamplePromise)) {
return void 0;
}
let shortestSkirt = Math.min(this._westSkirtHeight, this._eastSkirtHeight);
shortestSkirt = Math.min(shortestSkirt, this._southSkirtHeight);
shortestSkirt = Math.min(shortestSkirt, this._northSkirtHeight);
const westSkirtHeight = isEastChild ? shortestSkirt * 0.5 : this._westSkirtHeight;
const southSkirtHeight = isNorthChild ? shortestSkirt * 0.5 : this._southSkirtHeight;
const eastSkirtHeight = isEastChild ? this._eastSkirtHeight : shortestSkirt * 0.5;
const northSkirtHeight = isNorthChild ? this._northSkirtHeight : shortestSkirt * 0.5;
const credits = this._credits;
return Promise.resolve(upsamplePromise).then(function(result) {
const quantizedVertices = new Uint16Array(result.vertices);
const indicesTypedArray = IndexDatatype_default.createTypedArray(
quantizedVertices.length / 3,
result.indices
);
let encodedNormals;
if (defined_default(result.encodedNormals)) {
encodedNormals = new Uint8Array(result.encodedNormals);
}
return new QuantizedMeshTerrainData({
quantizedVertices,
indices: indicesTypedArray,
encodedNormals,
minimumHeight: result.minimumHeight,
maximumHeight: result.maximumHeight,
boundingSphere: BoundingSphere_default.clone(result.boundingSphere),
orientedBoundingBox: OrientedBoundingBox_default.clone(
result.orientedBoundingBox
),
horizonOcclusionPoint: Cartesian3_default.clone(result.horizonOcclusionPoint),
westIndices: result.westIndices,
southIndices: result.southIndices,
eastIndices: result.eastIndices,
northIndices: result.northIndices,
westSkirtHeight,
southSkirtHeight,
eastSkirtHeight,
northSkirtHeight,
childTileMask: 0,
credits,
createdByUpsampling: true
});
});
};
var maxShort2 = 32767;
var barycentricCoordinateScratch = new Cartesian3_default();
QuantizedMeshTerrainData.prototype.interpolateHeight = function(rectangle, longitude, latitude) {
let u3 = Math_default.clamp(
(longitude - rectangle.west) / rectangle.width,
0,
1
);
u3 *= maxShort2;
let v3 = Math_default.clamp(
(latitude - rectangle.south) / rectangle.height,
0,
1
);
v3 *= maxShort2;
if (!defined_default(this._mesh)) {
return interpolateHeight2(this, u3, v3);
}
return interpolateMeshHeight2(this, u3, v3);
};
function pointInBoundingBox(u3, v3, u0, v02, u12, v12, u22, v22) {
const minU = Math.min(u0, u12, u22);
const maxU = Math.max(u0, u12, u22);
const minV = Math.min(v02, v12, v22);
const maxV = Math.max(v02, v12, v22);
return u3 >= minU && u3 <= maxU && v3 >= minV && v3 <= maxV;
}
var texCoordScratch0 = new Cartesian2_default();
var texCoordScratch1 = new Cartesian2_default();
var texCoordScratch2 = new Cartesian2_default();
function interpolateMeshHeight2(terrainData, u3, v3) {
const mesh = terrainData._mesh;
const vertices = mesh.vertices;
const encoding = mesh.encoding;
const indices = mesh.indices;
for (let i = 0, len = indices.length; i < len; i += 3) {
const i0 = indices[i];
const i1 = indices[i + 1];
const i2 = indices[i + 2];
const uv0 = encoding.decodeTextureCoordinates(
vertices,
i0,
texCoordScratch0
);
const uv1 = encoding.decodeTextureCoordinates(
vertices,
i1,
texCoordScratch1
);
const uv2 = encoding.decodeTextureCoordinates(
vertices,
i2,
texCoordScratch2
);
if (pointInBoundingBox(u3, v3, uv0.x, uv0.y, uv1.x, uv1.y, uv2.x, uv2.y)) {
const barycentric = Intersections2D_default.computeBarycentricCoordinates(
u3,
v3,
uv0.x,
uv0.y,
uv1.x,
uv1.y,
uv2.x,
uv2.y,
barycentricCoordinateScratch
);
if (barycentric.x >= -1e-15 && barycentric.y >= -1e-15 && barycentric.z >= -1e-15) {
const h0 = encoding.decodeHeight(vertices, i0);
const h1 = encoding.decodeHeight(vertices, i1);
const h2 = encoding.decodeHeight(vertices, i2);
return barycentric.x * h0 + barycentric.y * h1 + barycentric.z * h2;
}
}
}
return void 0;
}
function interpolateHeight2(terrainData, u3, v3) {
const uBuffer = terrainData._uValues;
const vBuffer = terrainData._vValues;
const heightBuffer = terrainData._heightValues;
const indices = terrainData._indices;
for (let i = 0, len = indices.length; i < len; i += 3) {
const i0 = indices[i];
const i1 = indices[i + 1];
const i2 = indices[i + 2];
const u0 = uBuffer[i0];
const u12 = uBuffer[i1];
const u22 = uBuffer[i2];
const v02 = vBuffer[i0];
const v12 = vBuffer[i1];
const v22 = vBuffer[i2];
if (pointInBoundingBox(u3, v3, u0, v02, u12, v12, u22, v22)) {
const barycentric = Intersections2D_default.computeBarycentricCoordinates(
u3,
v3,
u0,
v02,
u12,
v12,
u22,
v22,
barycentricCoordinateScratch
);
if (barycentric.x >= -1e-15 && barycentric.y >= -1e-15 && barycentric.z >= -1e-15) {
const quantizedHeight = barycentric.x * heightBuffer[i0] + barycentric.y * heightBuffer[i1] + barycentric.z * heightBuffer[i2];
return Math_default.lerp(
terrainData._minimumHeight,
terrainData._maximumHeight,
quantizedHeight / maxShort2
);
}
}
}
return void 0;
}
QuantizedMeshTerrainData.prototype.isChildAvailable = function(thisX, thisY, childX, childY) {
if (!defined_default(thisX)) {
throw new DeveloperError_default("thisX is required.");
}
if (!defined_default(thisY)) {
throw new DeveloperError_default("thisY is required.");
}
if (!defined_default(childX)) {
throw new DeveloperError_default("childX is required.");
}
if (!defined_default(childY)) {
throw new DeveloperError_default("childY is required.");
}
let bitNumber = 2;
if (childX !== thisX * 2) {
++bitNumber;
}
if (childY !== thisY * 2) {
bitNumber -= 2;
}
return (this._childTileMask & 1 << bitNumber) !== 0;
};
QuantizedMeshTerrainData.prototype.wasCreatedByUpsampling = function() {
return this._createdByUpsampling;
};
var QuantizedMeshTerrainData_default = QuantizedMeshTerrainData;
// packages/engine/Source/Core/CesiumTerrainProvider.js
function LayerInformation(layer) {
this.resource = layer.resource;
this.version = layer.version;
this.isHeightmap = layer.isHeightmap;
this.tileUrlTemplates = layer.tileUrlTemplates;
this.availability = layer.availability;
this.hasVertexNormals = layer.hasVertexNormals;
this.hasWaterMask = layer.hasWaterMask;
this.hasMetadata = layer.hasMetadata;
this.availabilityLevels = layer.availabilityLevels;
this.availabilityTilesLoaded = layer.availabilityTilesLoaded;
this.littleEndianExtensionSize = layer.littleEndianExtensionSize;
this.availabilityPromiseCache = {};
}
function TerrainProviderBuilder2(options) {
this.requestVertexNormals = options.requestVertexNormals ?? false;
this.requestWaterMask = options.requestWaterMask ?? false;
this.requestMetadata = options.requestMetadata ?? true;
this.ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
this.heightmapWidth = 65;
this.heightmapStructure = void 0;
this.hasWaterMask = false;
this.hasMetadata = false;
this.hasVertexNormals = false;
this.scheme = void 0;
this.lastResource = void 0;
this.layerJsonResource = void 0;
this.previousError = void 0;
this.availability = void 0;
this.tilingScheme = void 0;
this.levelZeroMaximumGeometricError = void 0;
this.heightmapStructure = void 0;
this.layers = [];
this.attribution = "";
this.overallAvailability = [];
this.overallMaxZoom = 0;
this.tileCredits = [];
}
TerrainProviderBuilder2.prototype.build = function(provider) {
provider._heightmapWidth = this.heightmapWidth;
provider._scheme = this.scheme;
const credits = defined_default(this.lastResource.credits) ? this.lastResource.credits : [];
provider._tileCredits = credits.concat(this.tileCredits);
provider._availability = this.availability;
provider._tilingScheme = this.tilingScheme;
provider._requestWaterMask = this.requestWaterMask;
provider._levelZeroMaximumGeometricError = this.levelZeroMaximumGeometricError;
provider._heightmapStructure = this.heightmapStructure;
provider._layers = this.layers;
provider._hasWaterMask = this.hasWaterMask;
provider._hasVertexNormals = this.hasVertexNormals;
provider._hasMetadata = this.hasMetadata;
};
async function parseMetadataSuccess2(terrainProviderBuilder, data, provider) {
if (!data.format) {
const message = "The tile format is not specified in the layer.json file.";
terrainProviderBuilder.previousError = TileProviderError_default.reportError(
terrainProviderBuilder.previousError,
provider,
defined_default(provider) ? provider._errorEvent : void 0,
message
);
throw new RuntimeError_default(message);
}
if (!data.tiles || data.tiles.length === 0) {
const message = "The layer.json file does not specify any tile URL templates.";
terrainProviderBuilder.previousError = TileProviderError_default.reportError(
terrainProviderBuilder.previousError,
provider,
defined_default(provider) ? provider._errorEvent : void 0,
message
);
throw new RuntimeError_default(message);
}
let hasVertexNormals = false;
let hasWaterMask = false;
let hasMetadata = false;
let littleEndianExtensionSize = true;
let isHeightmap = false;
if (data.format === "heightmap-1.0") {
isHeightmap = true;
if (!defined_default(terrainProviderBuilder.heightmapStructure)) {
terrainProviderBuilder.heightmapStructure = {
heightScale: 1 / 5,
heightOffset: -1e3,
elementsPerHeight: 1,
stride: 1,
elementMultiplier: 256,
isBigEndian: false,
lowestEncodedHeight: 0,
highestEncodedHeight: 256 * 256 - 1
};
}
hasWaterMask = true;
terrainProviderBuilder.requestWaterMask = true;
} else if (data.format.indexOf("quantized-mesh-1.") !== 0) {
const message = `The tile format "${data.format}" is invalid or not supported.`;
terrainProviderBuilder.previousError = TileProviderError_default.reportError(
terrainProviderBuilder.previousError,
provider,
defined_default(provider) ? provider._errorEvent : void 0,
message
);
throw new RuntimeError_default(message);
}
const tileUrlTemplates = data.tiles;
const maxZoom = data.maxzoom;
terrainProviderBuilder.overallMaxZoom = Math.max(
terrainProviderBuilder.overallMaxZoom,
maxZoom
);
if (!data.projection || data.projection === "EPSG:4326") {
terrainProviderBuilder.tilingScheme = new GeographicTilingScheme_default({
numberOfLevelZeroTilesX: 2,
numberOfLevelZeroTilesY: 1,
ellipsoid: terrainProviderBuilder.ellipsoid
});
} else if (data.projection === "EPSG:3857") {
terrainProviderBuilder.tilingScheme = new WebMercatorTilingScheme_default({
numberOfLevelZeroTilesX: 1,
numberOfLevelZeroTilesY: 1,
ellipsoid: terrainProviderBuilder.ellipsoid
});
} else {
const message = `The projection "${data.projection}" is invalid or not supported.`;
terrainProviderBuilder.previousError = TileProviderError_default.reportError(
terrainProviderBuilder.previousError,
provider,
defined_default(provider) ? provider._errorEvent : void 0,
message
);
throw new RuntimeError_default(message);
}
terrainProviderBuilder.levelZeroMaximumGeometricError = TerrainProvider_default.getEstimatedLevelZeroGeometricErrorForAHeightmap(
terrainProviderBuilder.tilingScheme.ellipsoid,
terrainProviderBuilder.heightmapWidth,
terrainProviderBuilder.tilingScheme.getNumberOfXTilesAtLevel(0)
);
if (!data.scheme || data.scheme === "tms" || data.scheme === "slippyMap") {
terrainProviderBuilder.scheme = data.scheme;
} else {
const message = `The scheme "${data.scheme}" is invalid or not supported.`;
terrainProviderBuilder.previousError = TileProviderError_default.reportError(
terrainProviderBuilder.previousError,
provider,
defined_default(provider) ? provider._errorEvent : void 0,
message
);
throw new RuntimeError_default(message);
}
let availabilityTilesLoaded;
if (defined_default(data.extensions) && data.extensions.indexOf("octvertexnormals") !== -1) {
hasVertexNormals = true;
} else if (defined_default(data.extensions) && data.extensions.indexOf("vertexnormals") !== -1) {
hasVertexNormals = true;
littleEndianExtensionSize = false;
}
if (defined_default(data.extensions) && data.extensions.indexOf("watermask") !== -1) {
hasWaterMask = true;
}
if (defined_default(data.extensions) && data.extensions.indexOf("metadata") !== -1) {
hasMetadata = true;
}
const availabilityLevels = data.metadataAvailability;
const availableTiles = data.available;
let availability;
if (defined_default(availableTiles) && !defined_default(availabilityLevels)) {
availability = new TileAvailability_default(
terrainProviderBuilder.tilingScheme,
availableTiles.length
);
for (let level = 0; level < availableTiles.length; ++level) {
const rangesAtLevel = availableTiles[level];
const yTiles = terrainProviderBuilder.tilingScheme.getNumberOfYTilesAtLevel(level);
if (!defined_default(terrainProviderBuilder.overallAvailability[level])) {
terrainProviderBuilder.overallAvailability[level] = [];
}
for (let rangeIndex = 0; rangeIndex < rangesAtLevel.length; ++rangeIndex) {
const range = rangesAtLevel[rangeIndex];
const yStart = yTiles - range.endY - 1;
const yEnd = yTiles - range.startY - 1;
terrainProviderBuilder.overallAvailability[level].push([
range.startX,
yStart,
range.endX,
yEnd
]);
availability.addAvailableTileRange(
level,
range.startX,
yStart,
range.endX,
yEnd
);
}
}
} else if (defined_default(availabilityLevels)) {
availabilityTilesLoaded = new TileAvailability_default(
terrainProviderBuilder.tilingScheme,
maxZoom
);
availability = new TileAvailability_default(
terrainProviderBuilder.tilingScheme,
maxZoom
);
terrainProviderBuilder.overallAvailability[0] = [[0, 0, 1, 0]];
availability.addAvailableTileRange(0, 0, 0, 1, 0);
}
terrainProviderBuilder.hasWaterMask = terrainProviderBuilder.hasWaterMask || hasWaterMask;
terrainProviderBuilder.hasVertexNormals = terrainProviderBuilder.hasVertexNormals || hasVertexNormals;
terrainProviderBuilder.hasMetadata = terrainProviderBuilder.hasMetadata || hasMetadata;
if (defined_default(data.attribution)) {
if (terrainProviderBuilder.attribution.length > 0) {
terrainProviderBuilder.attribution += " ";
}
terrainProviderBuilder.attribution += data.attribution;
}
terrainProviderBuilder.layers.push(
new LayerInformation({
resource: terrainProviderBuilder.lastResource,
version: data.version,
isHeightmap,
tileUrlTemplates,
availability,
hasVertexNormals,
hasWaterMask,
hasMetadata,
availabilityLevels,
availabilityTilesLoaded,
littleEndianExtensionSize
})
);
const parentUrl = data.parentUrl;
if (defined_default(parentUrl)) {
if (!defined_default(availability)) {
console.log(
"A layer.json can't have a parentUrl if it does't have an available array."
);
return true;
}
terrainProviderBuilder.lastResource = terrainProviderBuilder.lastResource.getDerivedResource({
url: parentUrl
});
terrainProviderBuilder.lastResource.appendForwardSlash();
terrainProviderBuilder.layerJsonResource = terrainProviderBuilder.lastResource.getDerivedResource({
url: "layer.json"
});
await requestLayerJson(terrainProviderBuilder);
return true;
}
return true;
}
function parseMetadataFailure(terrainProviderBuilder, error, provider) {
let message = `An error occurred while accessing ${terrainProviderBuilder.layerJsonResource.url}.`;
if (defined_default(error)) {
message += `
${error.message}`;
}
terrainProviderBuilder.previousError = TileProviderError_default.reportError(
terrainProviderBuilder.previousError,
provider,
defined_default(provider) ? provider._errorEvent : void 0,
message
);
if (terrainProviderBuilder.previousError.retry) {
return requestLayerJson(terrainProviderBuilder, provider);
}
throw new RuntimeError_default(message);
}
async function metadataSuccess4(terrainProviderBuilder, data, provider) {
await parseMetadataSuccess2(terrainProviderBuilder, data, provider);
const length2 = terrainProviderBuilder.overallAvailability.length;
if (length2 > 0) {
const availability = terrainProviderBuilder.availability = new TileAvailability_default(
terrainProviderBuilder.tilingScheme,
terrainProviderBuilder.overallMaxZoom
);
for (let level = 0; level < length2; ++level) {
const levelRanges = terrainProviderBuilder.overallAvailability[level];
for (let i = 0; i < levelRanges.length; ++i) {
const range = levelRanges[i];
availability.addAvailableTileRange(
level,
range[0],
range[1],
range[2],
range[3]
);
}
}
}
if (terrainProviderBuilder.attribution.length > 0) {
const layerJsonCredit = new Credit_default(terrainProviderBuilder.attribution);
terrainProviderBuilder.tileCredits.push(layerJsonCredit);
}
return true;
}
async function requestLayerJson(terrainProviderBuilder, provider) {
try {
const data = await terrainProviderBuilder.layerJsonResource.fetchJson();
return metadataSuccess4(terrainProviderBuilder, data, provider);
} catch (error) {
if (defined_default(error) && error.statusCode === 404) {
await parseMetadataSuccess2(
terrainProviderBuilder,
{
tilejson: "2.1.0",
format: "heightmap-1.0",
version: "1.0.0",
scheme: "tms",
tiles: ["{z}/{x}/{y}.terrain?v={version}"]
},
provider
);
return true;
}
return parseMetadataFailure(terrainProviderBuilder, error, provider);
}
}
function CesiumTerrainProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._heightmapWidth = void 0;
this._heightmapStructure = void 0;
this._hasWaterMask = false;
this._hasVertexNormals = false;
this._hasMetadata = false;
this._scheme = void 0;
this._ellipsoid = options.ellipsoid;
this._requestVertexNormals = options.requestVertexNormals ?? false;
this._requestWaterMask = options.requestWaterMask ?? false;
this._requestMetadata = options.requestMetadata ?? true;
this._errorEvent = new Event_default();
let credit = options.credit;
if (typeof credit === "string") {
credit = new Credit_default(credit);
}
this._credit = credit;
this._availability = void 0;
this._tilingScheme = void 0;
this._levelZeroMaximumGeometricError = void 0;
this._layers = void 0;
this._tileCredits = void 0;
}
var QuantizedMeshExtensionIds = {
/**
* Oct-Encoded Per-Vertex Normals are included as an extension to the tile mesh
*
* @type {number}
* @constant
* @default 1
*/
OCT_VERTEX_NORMALS: 1,
/**
* A watermask is included as an extension to the tile mesh
*
* @type {number}
* @constant
* @default 2
*/
WATER_MASK: 2,
/**
* A json object contain metadata about the tile
*
* @type {number}
* @constant
* @default 4
*/
METADATA: 4
};
function getRequestHeader(extensionsList) {
if (!defined_default(extensionsList) || extensionsList.length === 0) {
return {
Accept: "application/vnd.quantized-mesh,application/octet-stream;q=0.9,*/*;q=0.01"
};
}
const extensions = extensionsList.join("-");
return {
Accept: `application/vnd.quantized-mesh;extensions=${extensions},application/octet-stream;q=0.9,*/*;q=0.01`
};
}
function createHeightmapTerrainData(provider, buffer2, level, x, y) {
const heightBuffer = new Uint16Array(
buffer2,
0,
provider._heightmapWidth * provider._heightmapWidth
);
return new HeightmapTerrainData_default({
buffer: heightBuffer,
childTileMask: new Uint8Array(buffer2, heightBuffer.byteLength, 1)[0],
waterMask: new Uint8Array(
buffer2,
heightBuffer.byteLength + 1,
buffer2.byteLength - heightBuffer.byteLength - 1
),
width: provider._heightmapWidth,
height: provider._heightmapWidth,
structure: provider._heightmapStructure,
credits: provider._tileCredits
});
}
function createQuantizedMeshTerrainData(provider, buffer2, level, x, y, layer) {
const littleEndianExtensionSize = layer.littleEndianExtensionSize;
let pos = 0;
const cartesian3Elements = 3;
const boundingSphereElements = cartesian3Elements + 1;
const cartesian3Length = Float64Array.BYTES_PER_ELEMENT * cartesian3Elements;
const boundingSphereLength = Float64Array.BYTES_PER_ELEMENT * boundingSphereElements;
const encodedVertexElements = 3;
const encodedVertexLength = Uint16Array.BYTES_PER_ELEMENT * encodedVertexElements;
const triangleElements = 3;
let bytesPerIndex = Uint16Array.BYTES_PER_ELEMENT;
let triangleLength = bytesPerIndex * triangleElements;
const view = new DataView(buffer2);
const center = new Cartesian3_default(
view.getFloat64(pos, true),
view.getFloat64(pos + 8, true),
view.getFloat64(pos + 16, true)
);
pos += cartesian3Length;
const minimumHeight = view.getFloat32(pos, true);
pos += Float32Array.BYTES_PER_ELEMENT;
const maximumHeight = view.getFloat32(pos, true);
pos += Float32Array.BYTES_PER_ELEMENT;
const boundingSphere = new BoundingSphere_default(
new Cartesian3_default(
view.getFloat64(pos, true),
view.getFloat64(pos + 8, true),
view.getFloat64(pos + 16, true)
),
view.getFloat64(pos + cartesian3Length, true)
);
pos += boundingSphereLength;
const horizonOcclusionPoint = new Cartesian3_default(
view.getFloat64(pos, true),
view.getFloat64(pos + 8, true),
view.getFloat64(pos + 16, true)
);
pos += cartesian3Length;
const vertexCount = view.getUint32(pos, true);
pos += Uint32Array.BYTES_PER_ELEMENT;
const encodedVertexBuffer = new Uint16Array(buffer2, pos, vertexCount * 3);
pos += vertexCount * encodedVertexLength;
if (vertexCount > 64 * 1024) {
bytesPerIndex = Uint32Array.BYTES_PER_ELEMENT;
triangleLength = bytesPerIndex * triangleElements;
}
const uBuffer = encodedVertexBuffer.subarray(0, vertexCount);
const vBuffer = encodedVertexBuffer.subarray(vertexCount, 2 * vertexCount);
const heightBuffer = encodedVertexBuffer.subarray(
vertexCount * 2,
3 * vertexCount
);
AttributeCompression_default.zigZagDeltaDecode(uBuffer, vBuffer, heightBuffer);
if (pos % bytesPerIndex !== 0) {
pos += bytesPerIndex - pos % bytesPerIndex;
}
const triangleCount = view.getUint32(pos, true);
pos += Uint32Array.BYTES_PER_ELEMENT;
const indices = IndexDatatype_default.createTypedArrayFromArrayBuffer(
vertexCount,
buffer2,
pos,
triangleCount * triangleElements
);
pos += triangleCount * triangleLength;
let highest = 0;
const length2 = indices.length;
for (let i = 0; i < length2; ++i) {
const code = indices[i];
indices[i] = highest - code;
if (code === 0) {
++highest;
}
}
const westVertexCount = view.getUint32(pos, true);
pos += Uint32Array.BYTES_PER_ELEMENT;
const westIndices = IndexDatatype_default.createTypedArrayFromArrayBuffer(
vertexCount,
buffer2,
pos,
westVertexCount
);
pos += westVertexCount * bytesPerIndex;
const southVertexCount = view.getUint32(pos, true);
pos += Uint32Array.BYTES_PER_ELEMENT;
const southIndices = IndexDatatype_default.createTypedArrayFromArrayBuffer(
vertexCount,
buffer2,
pos,
southVertexCount
);
pos += southVertexCount * bytesPerIndex;
const eastVertexCount = view.getUint32(pos, true);
pos += Uint32Array.BYTES_PER_ELEMENT;
const eastIndices = IndexDatatype_default.createTypedArrayFromArrayBuffer(
vertexCount,
buffer2,
pos,
eastVertexCount
);
pos += eastVertexCount * bytesPerIndex;
const northVertexCount = view.getUint32(pos, true);
pos += Uint32Array.BYTES_PER_ELEMENT;
const northIndices = IndexDatatype_default.createTypedArrayFromArrayBuffer(
vertexCount,
buffer2,
pos,
northVertexCount
);
pos += northVertexCount * bytesPerIndex;
let encodedNormalBuffer;
let waterMaskBuffer;
while (pos < view.byteLength) {
const extensionId = view.getUint8(pos, true);
pos += Uint8Array.BYTES_PER_ELEMENT;
const extensionLength = view.getUint32(pos, littleEndianExtensionSize);
pos += Uint32Array.BYTES_PER_ELEMENT;
if (extensionId === QuantizedMeshExtensionIds.OCT_VERTEX_NORMALS && provider._requestVertexNormals) {
encodedNormalBuffer = new Uint8Array(buffer2, pos, vertexCount * 2);
} else if (extensionId === QuantizedMeshExtensionIds.WATER_MASK && provider._requestWaterMask) {
waterMaskBuffer = new Uint8Array(buffer2, pos, extensionLength);
} else if (extensionId === QuantizedMeshExtensionIds.METADATA && provider._requestMetadata) {
const stringLength = view.getUint32(pos, true);
if (stringLength > 0) {
const metadata = getJsonFromTypedArray_default(
new Uint8Array(buffer2),
pos + Uint32Array.BYTES_PER_ELEMENT,
stringLength
);
const availableTiles = metadata.available;
if (defined_default(availableTiles)) {
for (let offset = 0; offset < availableTiles.length; ++offset) {
const availableLevel = level + offset + 1;
const rangesAtLevel = availableTiles[offset];
const yTiles = provider._tilingScheme.getNumberOfYTilesAtLevel(availableLevel);
for (let rangeIndex = 0; rangeIndex < rangesAtLevel.length; ++rangeIndex) {
const range = rangesAtLevel[rangeIndex];
const yStart = yTiles - range.endY - 1;
const yEnd = yTiles - range.startY - 1;
provider.availability.addAvailableTileRange(
availableLevel,
range.startX,
yStart,
range.endX,
yEnd
);
layer.availability.addAvailableTileRange(
availableLevel,
range.startX,
yStart,
range.endX,
yEnd
);
}
}
}
}
layer.availabilityTilesLoaded.addAvailableTileRange(level, x, y, x, y);
}
pos += extensionLength;
}
const skirtHeight = provider.getLevelMaximumGeometricError(level) * 5;
const rectangle = provider._tilingScheme.tileXYToRectangle(x, y, level);
const orientedBoundingBox = OrientedBoundingBox_default.fromRectangle(
rectangle,
minimumHeight,
maximumHeight,
provider._tilingScheme.ellipsoid
);
return new QuantizedMeshTerrainData_default({
center,
minimumHeight,
maximumHeight,
boundingSphere,
orientedBoundingBox,
horizonOcclusionPoint,
quantizedVertices: encodedVertexBuffer,
encodedNormals: encodedNormalBuffer,
indices,
westIndices,
southIndices,
eastIndices,
northIndices,
westSkirtHeight: skirtHeight,
southSkirtHeight: skirtHeight,
eastSkirtHeight: skirtHeight,
northSkirtHeight: skirtHeight,
childTileMask: provider.availability.computeChildMaskForTile(level, x, y),
waterMask: waterMaskBuffer,
credits: provider._tileCredits
});
}
CesiumTerrainProvider.prototype.requestTileGeometry = function(x, y, level, request) {
const layers = this._layers;
let layerToUse;
const layerCount = layers.length;
let unknownAvailability = false;
let availabilityPromise = Promise.resolve();
if (layerCount === 1) {
layerToUse = layers[0];
} else {
for (let i = 0; i < layerCount; ++i) {
const layer = layers[i];
if (!defined_default(layer.availability) || layer.availability.isTileAvailable(level, x, y)) {
layerToUse = layer;
break;
}
const availabilityUnloaded = checkLayer(
this,
x,
y,
level,
layer,
i === 0
);
if (availabilityUnloaded.result) {
unknownAvailability = true;
availabilityPromise = availabilityPromise.then(
() => availabilityUnloaded.promise
);
}
}
}
if (!defined_default(layerToUse) && unknownAvailability) {
return availabilityPromise.then(() => {
return new Promise((resolve2) => {
setTimeout(() => {
const promise = this.requestTileGeometry(x, y, level, request);
resolve2(promise);
}, 0);
});
});
}
return requestTileGeometry2(this, x, y, level, layerToUse, request);
};
function requestTileGeometry2(provider, x, y, level, layerToUse, request) {
if (!defined_default(layerToUse)) {
return Promise.reject(new RuntimeError_default("Terrain tile doesn't exist"));
}
const urlTemplates = layerToUse.tileUrlTemplates;
if (urlTemplates.length === 0) {
return void 0;
}
let terrainY;
if (!provider._scheme || provider._scheme === "tms") {
const yTiles = provider._tilingScheme.getNumberOfYTilesAtLevel(level);
terrainY = yTiles - y - 1;
} else {
terrainY = y;
}
const extensionList = [];
if (provider._requestVertexNormals && layerToUse.hasVertexNormals) {
extensionList.push(
layerToUse.littleEndianExtensionSize ? "octvertexnormals" : "vertexnormals"
);
}
if (provider._requestWaterMask && layerToUse.hasWaterMask) {
extensionList.push("watermask");
}
if (provider._requestMetadata && layerToUse.hasMetadata) {
extensionList.push("metadata");
}
let headers;
let query;
const url2 = urlTemplates[(x + terrainY + level) % urlTemplates.length];
const resource = layerToUse.resource;
if (defined_default(resource._ionEndpoint) && !defined_default(resource._ionEndpoint.externalType)) {
if (extensionList.length !== 0) {
query = { extensions: extensionList.join("-") };
}
headers = getRequestHeader(void 0);
} else {
headers = getRequestHeader(extensionList);
}
const promise = resource.getDerivedResource({
url: url2,
templateValues: {
version: layerToUse.version,
z: level,
x,
y: terrainY
},
queryParameters: query,
headers,
request
}).fetchArrayBuffer();
if (!defined_default(promise)) {
return void 0;
}
return promise.then(function(buffer2) {
if (!defined_default(buffer2)) {
return Promise.reject(new RuntimeError_default("Mesh buffer doesn't exist."));
}
if (defined_default(provider._heightmapStructure)) {
return createHeightmapTerrainData(provider, buffer2, level, x, y);
}
return createQuantizedMeshTerrainData(
provider,
buffer2,
level,
x,
y,
layerToUse
);
});
}
Object.defineProperties(CesiumTerrainProvider.prototype, {
/**
* Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof CesiumTerrainProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets the credit to display when this terrain provider is active. Typically this is used to credit
* the source of the terrain.
* @memberof CesiumTerrainProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return this._credit;
}
},
/**
* Gets the tiling scheme used by this provider.
* @memberof CesiumTerrainProvider.prototype
* @type {GeographicTilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._tilingScheme;
}
},
/**
* Gets a value indicating whether or not the provider includes a water mask. The water mask
* indicates which areas of the globe are water rather than land, so they can be rendered
* as a reflective surface with animated waves.
* @memberof CesiumTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasWaterMask: {
get: function() {
return this._hasWaterMask && this._requestWaterMask;
}
},
/**
* Gets a value indicating whether or not the requested tiles include vertex normals.
* @memberof CesiumTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasVertexNormals: {
get: function() {
return this._hasVertexNormals && this._requestVertexNormals;
}
},
/**
* Gets a value indicating whether or not the requested tiles include metadata.
* @memberof CesiumTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasMetadata: {
get: function() {
return this._hasMetadata && this._requestMetadata;
}
},
/**
* Boolean flag that indicates if the client should request vertex normals from the server.
* Vertex normals data is appended to the standard tile mesh data only if the client requests the vertex normals and
* if the server provides vertex normals.
* @memberof CesiumTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
requestVertexNormals: {
get: function() {
return this._requestVertexNormals;
}
},
/**
* Boolean flag that indicates if the client should request a watermask from the server.
* Watermask data is appended to the standard tile mesh data only if the client requests the watermask and
* if the server provides a watermask.
* @memberof CesiumTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
requestWaterMask: {
get: function() {
return this._requestWaterMask;
}
},
/**
* Boolean flag that indicates if the client should request metadata from the server.
* Metadata is appended to the standard tile mesh data only if the client requests the metadata and
* if the server provides a metadata.
* @memberof CesiumTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
requestMetadata: {
get: function() {
return this._requestMetadata;
}
},
/**
* Gets an object that can be used to determine availability of terrain from this provider, such as
* at points and in rectangles. This property may be undefined if availability
* information is not available. Note that this reflects tiles that are known to be available currently.
* Additional tiles may be discovered to be available in the future, e.g. if availability information
* exists deeper in the tree rather than it all being discoverable at the root. However, a tile that
* is available now will not become unavailable in the future.
* @memberof CesiumTerrainProvider.prototype
* @type {TileAvailability|undefined}
* @readonly
*/
availability: {
get: function() {
return this._availability;
}
}
});
CesiumTerrainProvider.prototype.getLevelMaximumGeometricError = function(level) {
return this._levelZeroMaximumGeometricError / (1 << level);
};
CesiumTerrainProvider.fromIonAssetId = async function(assetId, options) {
Check_default.defined("assetId", assetId);
const resource = await IonResource_default.fromAssetId(assetId);
return CesiumTerrainProvider.fromUrl(resource, options);
};
CesiumTerrainProvider.fromUrl = async function(url2, options) {
Check_default.defined("url", url2);
options = options ?? Frozen_default.EMPTY_OBJECT;
url2 = await Promise.resolve(url2);
const resource = Resource_default.createIfNeeded(url2);
resource.appendForwardSlash();
const terrainProviderBuilder = new TerrainProviderBuilder2(options);
terrainProviderBuilder.lastResource = resource;
terrainProviderBuilder.layerJsonResource = terrainProviderBuilder.lastResource.getDerivedResource({
url: "layer.json"
});
await requestLayerJson(terrainProviderBuilder);
const provider = new CesiumTerrainProvider(options);
terrainProviderBuilder.build(provider);
return provider;
};
CesiumTerrainProvider.prototype.getTileDataAvailable = function(x, y, level) {
if (!defined_default(this._availability)) {
return void 0;
}
if (level > this._availability._maximumLevel) {
return false;
}
if (this._availability.isTileAvailable(level, x, y)) {
return true;
}
if (!this._hasMetadata) {
return false;
}
const layers = this._layers;
const count = layers.length;
for (let i = 0; i < count; ++i) {
const layerResult = checkLayer(this, x, y, level, layers[i], i === 0);
if (layerResult.result) {
return void 0;
}
}
return false;
};
CesiumTerrainProvider.prototype.loadTileDataAvailability = function(x, y, level) {
if (!defined_default(this._availability) || level > this._availability._maximumLevel || this._availability.isTileAvailable(level, x, y) || !this._hasMetadata) {
return void 0;
}
const layers = this._layers;
const count = layers.length;
for (let i = 0; i < count; ++i) {
const layerResult = checkLayer(this, x, y, level, layers[i], i === 0);
if (defined_default(layerResult.promise)) {
return layerResult.promise;
}
}
};
function getAvailabilityTile(layer, x, y, level) {
if (level === 0) {
return;
}
const availabilityLevels = layer.availabilityLevels;
const parentLevel = level % availabilityLevels === 0 ? level - availabilityLevels : (level / availabilityLevels | 0) * availabilityLevels;
const divisor = 1 << level - parentLevel;
const parentX = x / divisor | 0;
const parentY = y / divisor | 0;
return {
level: parentLevel,
x: parentX,
y: parentY
};
}
function checkLayer(provider, x, y, level, layer, topLayer) {
if (!defined_default(layer.availabilityLevels)) {
return {
result: false
};
}
let cacheKey;
const deleteFromCache = function() {
delete layer.availabilityPromiseCache[cacheKey];
};
const availabilityTilesLoaded = layer.availabilityTilesLoaded;
const availability = layer.availability;
let tile = getAvailabilityTile(layer, x, y, level);
while (defined_default(tile)) {
if (availability.isTileAvailable(tile.level, tile.x, tile.y) && !availabilityTilesLoaded.isTileAvailable(tile.level, tile.x, tile.y)) {
let requestPromise;
if (!topLayer) {
cacheKey = `${tile.level}-${tile.x}-${tile.y}`;
requestPromise = layer.availabilityPromiseCache[cacheKey];
if (!defined_default(requestPromise)) {
const request = new Request_default({
throttle: false,
throttleByServer: true,
type: RequestType_default.TERRAIN
});
requestPromise = requestTileGeometry2(
provider,
tile.x,
tile.y,
tile.level,
layer,
request
);
if (defined_default(requestPromise)) {
layer.availabilityPromiseCache[cacheKey] = requestPromise;
requestPromise.then(deleteFromCache);
}
}
}
return {
result: true,
promise: requestPromise
};
}
tile = getAvailabilityTile(layer, tile.x, tile.y, tile.level);
}
return {
result: false
};
}
CesiumTerrainProvider._getAvailabilityTile = getAvailabilityTile;
var CesiumTerrainProvider_default = CesiumTerrainProvider;
// packages/engine/Source/Core/CircleGeometry.js
var import_InlineWorkers1192 = __toESM(require_InlineWorkers(), 1);
function CircleGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const radius = options.radius;
Check_default.typeOf.number("radius", radius);
const ellipseGeometryOptions = {
center: options.center,
semiMajorAxis: radius,
semiMinorAxis: radius,
ellipsoid: options.ellipsoid,
height: options.height,
extrudedHeight: options.extrudedHeight,
granularity: options.granularity,
vertexFormat: options.vertexFormat,
stRotation: options.stRotation,
shadowVolume: options.shadowVolume
};
this._ellipseGeometry = new EllipseGeometry_default(ellipseGeometryOptions);
this._workerName = "createCircleGeometry";
}
CircleGeometry.packedLength = EllipseGeometry_default.packedLength;
CircleGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
return EllipseGeometry_default.pack(value._ellipseGeometry, array, startingIndex);
};
var scratchEllipseGeometry = new EllipseGeometry_default({
center: new Cartesian3_default(),
semiMajorAxis: 1,
semiMinorAxis: 1
});
var scratchOptions22 = {
center: new Cartesian3_default(),
radius: void 0,
ellipsoid: Ellipsoid_default.clone(Ellipsoid_default.default),
height: void 0,
extrudedHeight: void 0,
granularity: void 0,
vertexFormat: new VertexFormat_default(),
stRotation: void 0,
semiMajorAxis: void 0,
semiMinorAxis: void 0,
shadowVolume: void 0
};
CircleGeometry.unpack = function(array, startingIndex, result) {
const ellipseGeometry = EllipseGeometry_default.unpack(
array,
startingIndex,
scratchEllipseGeometry
);
scratchOptions22.center = Cartesian3_default.clone(
ellipseGeometry._center,
scratchOptions22.center
);
scratchOptions22.ellipsoid = Ellipsoid_default.clone(
ellipseGeometry._ellipsoid,
scratchOptions22.ellipsoid
);
scratchOptions22.ellipsoid = Ellipsoid_default.clone(
ellipseGeometry._ellipsoid,
scratchEllipseGeometry._ellipsoid
);
scratchOptions22.height = ellipseGeometry._height;
scratchOptions22.extrudedHeight = ellipseGeometry._extrudedHeight;
scratchOptions22.granularity = ellipseGeometry._granularity;
scratchOptions22.vertexFormat = VertexFormat_default.clone(
ellipseGeometry._vertexFormat,
scratchOptions22.vertexFormat
);
scratchOptions22.stRotation = ellipseGeometry._stRotation;
scratchOptions22.shadowVolume = ellipseGeometry._shadowVolume;
if (!defined_default(result)) {
scratchOptions22.radius = ellipseGeometry._semiMajorAxis;
return new CircleGeometry(scratchOptions22);
}
scratchOptions22.semiMajorAxis = ellipseGeometry._semiMajorAxis;
scratchOptions22.semiMinorAxis = ellipseGeometry._semiMinorAxis;
result._ellipseGeometry = new EllipseGeometry_default(scratchOptions22);
return result;
};
CircleGeometry.createGeometry = function(circleGeometry) {
return EllipseGeometry_default.createGeometry(circleGeometry._ellipseGeometry);
};
CircleGeometry.createShadowVolume = function(circleGeometry, minHeightFunc, maxHeightFunc) {
const granularity = circleGeometry._ellipseGeometry._granularity;
const ellipsoid = circleGeometry._ellipseGeometry._ellipsoid;
const minHeight = minHeightFunc(granularity, ellipsoid);
const maxHeight = maxHeightFunc(granularity, ellipsoid);
return new CircleGeometry({
center: circleGeometry._ellipseGeometry._center,
radius: circleGeometry._ellipseGeometry._semiMajorAxis,
ellipsoid,
stRotation: circleGeometry._ellipseGeometry._stRotation,
granularity,
extrudedHeight: minHeight,
height: maxHeight,
vertexFormat: VertexFormat_default.POSITION_ONLY,
shadowVolume: true
});
};
Object.defineProperties(CircleGeometry.prototype, {
/**
* @private
*/
rectangle: {
get: function() {
return this._ellipseGeometry.rectangle;
}
},
/**
* For remapping texture coordinates when rendering CircleGeometries as GroundPrimitives.
* @private
*/
textureCoordinateRotationPoints: {
get: function() {
return this._ellipseGeometry.textureCoordinateRotationPoints;
}
}
});
var CircleGeometry_default = CircleGeometry;
// packages/engine/Source/Core/CircleOutlineGeometry.js
var import_InlineWorkers1193 = __toESM(require_InlineWorkers(), 1);
function CircleOutlineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const radius = options.radius;
Check_default.typeOf.number("radius", radius);
const ellipseGeometryOptions = {
center: options.center,
semiMajorAxis: radius,
semiMinorAxis: radius,
ellipsoid: options.ellipsoid,
height: options.height,
extrudedHeight: options.extrudedHeight,
granularity: options.granularity,
numberOfVerticalLines: options.numberOfVerticalLines
};
this._ellipseGeometry = new EllipseOutlineGeometry_default(ellipseGeometryOptions);
this._workerName = "createCircleOutlineGeometry";
}
CircleOutlineGeometry.packedLength = EllipseOutlineGeometry_default.packedLength;
CircleOutlineGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
return EllipseOutlineGeometry_default.pack(
value._ellipseGeometry,
array,
startingIndex
);
};
var scratchEllipseGeometry2 = new EllipseOutlineGeometry_default({
center: new Cartesian3_default(),
semiMajorAxis: 1,
semiMinorAxis: 1
});
var scratchOptions23 = {
center: new Cartesian3_default(),
radius: void 0,
ellipsoid: Ellipsoid_default.clone(Ellipsoid_default.UNIT_SPHERE),
height: void 0,
extrudedHeight: void 0,
granularity: void 0,
numberOfVerticalLines: void 0,
semiMajorAxis: void 0,
semiMinorAxis: void 0
};
CircleOutlineGeometry.unpack = function(array, startingIndex, result) {
const ellipseGeometry = EllipseOutlineGeometry_default.unpack(
array,
startingIndex,
scratchEllipseGeometry2
);
scratchOptions23.center = Cartesian3_default.clone(
ellipseGeometry._center,
scratchOptions23.center
);
scratchOptions23.ellipsoid = Ellipsoid_default.clone(
ellipseGeometry._ellipsoid,
scratchOptions23.ellipsoid
);
scratchOptions23.height = ellipseGeometry._height;
scratchOptions23.extrudedHeight = ellipseGeometry._extrudedHeight;
scratchOptions23.granularity = ellipseGeometry._granularity;
scratchOptions23.numberOfVerticalLines = ellipseGeometry._numberOfVerticalLines;
if (!defined_default(result)) {
scratchOptions23.radius = ellipseGeometry._semiMajorAxis;
return new CircleOutlineGeometry(scratchOptions23);
}
scratchOptions23.semiMajorAxis = ellipseGeometry._semiMajorAxis;
scratchOptions23.semiMinorAxis = ellipseGeometry._semiMinorAxis;
result._ellipseGeometry = new EllipseOutlineGeometry_default(scratchOptions23);
return result;
};
CircleOutlineGeometry.createGeometry = function(circleGeometry) {
return EllipseOutlineGeometry_default.createGeometry(circleGeometry._ellipseGeometry);
};
var CircleOutlineGeometry_default = CircleOutlineGeometry;
// packages/engine/Source/Core/CustomHeightmapTerrainProvider.js
var import_InlineWorkers1194 = __toESM(require_InlineWorkers(), 1);
function CustomHeightmapTerrainProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.defined("options.callback", options.callback);
Check_default.defined("options.width", options.width);
Check_default.defined("options.height", options.height);
this._callback = options.callback;
this._tilingScheme = options.tilingScheme;
if (!defined_default(this._tilingScheme)) {
this._tilingScheme = new GeographicTilingScheme_default({
ellipsoid: options.ellipsoid ?? Ellipsoid_default.default
});
}
this._width = options.width;
this._height = options.height;
const maxTileDimensions = Math.max(this._width, this._height);
this._levelZeroMaximumGeometricError = TerrainProvider_default.getEstimatedLevelZeroGeometricErrorForAHeightmap(
this._tilingScheme.ellipsoid,
maxTileDimensions,
this._tilingScheme.getNumberOfXTilesAtLevel(0)
);
this._errorEvent = new Event_default();
let credit = options.credit;
if (typeof credit === "string") {
credit = new Credit_default(credit);
}
this._credit = credit;
}
Object.defineProperties(CustomHeightmapTerrainProvider.prototype, {
/**
* Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof CustomHeightmapTerrainProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets the credit to display when this terrain provider is active. Typically this is used to credit
* the source of the terrain.
* @memberof CustomHeightmapTerrainProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return this._credit;
}
},
/**
* Gets the tiling scheme used by this provider.
* @memberof CustomHeightmapTerrainProvider.prototype
* @type {TilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._tilingScheme;
}
},
/**
* Gets a value indicating whether or not the provider includes a water mask. The water mask
* indicates which areas of the globe are water rather than land, so they can be rendered
* as a reflective surface with animated waves.
* Water mask is not supported by {@link CustomHeightmapTerrainProvider}, so the return
* value will always be false.
* @memberof CustomHeightmapTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasWaterMask: {
get: function() {
return false;
}
},
/**
* Gets a value indicating whether or not the requested tiles include vertex normals.
* Vertex normals are not supported by {@link CustomHeightmapTerrainProvider}, so the return
* value will always be false.
* @memberof CustomHeightmapTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasVertexNormals: {
get: function() {
return false;
}
},
/**
* Gets an object that can be used to determine availability of terrain from this provider, such as
* at points and in rectangles. This property may be undefined if availability
* information is not available.
* @memberof CustomHeightmapTerrainProvider.prototype
* @type {TileAvailability}
* @readonly
*/
availability: {
get: function() {
return void 0;
}
},
/**
* Gets the number of columns per heightmap tile.
* @memberof CustomHeightmapTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
width: {
get: function() {
return this._width;
}
},
/**
* Gets the number of rows per heightmap tile.
* @memberof CustomHeightmapTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
height: {
get: function() {
return this._height;
}
}
});
CustomHeightmapTerrainProvider.prototype.requestTileGeometry = function(x, y, level, request) {
const promise = this._callback(x, y, level);
if (!defined_default(promise)) {
return void 0;
}
const width = this._width;
const height = this._height;
return Promise.resolve(promise).then(function(heightmapData) {
let buffer2 = heightmapData;
if (Array.isArray(buffer2)) {
buffer2 = new Float64Array(buffer2);
}
return new HeightmapTerrainData_default({
buffer: buffer2,
width,
height
});
});
};
CustomHeightmapTerrainProvider.prototype.getLevelMaximumGeometricError = function(level) {
return this._levelZeroMaximumGeometricError / (1 << level);
};
CustomHeightmapTerrainProvider.prototype.getTileDataAvailable = function(x, y, level) {
return void 0;
};
CustomHeightmapTerrainProvider.prototype.loadTileDataAvailability = function(x, y, level) {
return void 0;
};
var CustomHeightmapTerrainProvider_default = CustomHeightmapTerrainProvider;
// packages/engine/Source/Core/DefaultProxy.js
var import_InlineWorkers1195 = __toESM(require_InlineWorkers(), 1);
function DefaultProxy(proxy) {
this.proxy = proxy;
}
DefaultProxy.prototype.getURL = function(resource) {
const prefix = this.proxy.indexOf("?") === -1 ? "?" : "";
return this.proxy + prefix + encodeURIComponent(resource);
};
var DefaultProxy_default = DefaultProxy;
// packages/engine/Source/Core/GeocodeType.js
var import_InlineWorkers1196 = __toESM(require_InlineWorkers(), 1);
var GeocodeType = {
/**
* Perform a search where the input is considered complete.
*
* @type {number}
* @constant
*/
SEARCH: 0,
/**
* Perform an auto-complete using partial input, typically
* reserved for providing possible results as a user is typing.
*
* @type {number}
* @constant
*/
AUTOCOMPLETE: 1
};
var GeocodeType_default = Object.freeze(GeocodeType);
// packages/engine/Source/Core/GeocoderService.js
var import_InlineWorkers1197 = __toESM(require_InlineWorkers(), 1);
function GeocoderService() {
DeveloperError_default.throwInstantiationError();
}
Object.defineProperties(GeocoderService.prototype, {
/**
* Gets the credit to display after a geocode is performed. Typically this is used to credit
* the geocoder service.
* @memberof GeocoderService.prototype
* @type {Credit|undefined}
* @readonly
*/
credit: {
get: DeveloperError_default.throwInstantiationError
}
});
GeocoderService.getCreditsFromResult = function(geocoderResult) {
if (defined_default(geocoderResult.attributions)) {
return geocoderResult.attributions.map(Credit_default.getIonCredit);
}
return void 0;
};
GeocoderService.prototype.geocode = DeveloperError_default.throwInstantiationError;
var GeocoderService_default = GeocoderService;
// packages/engine/Source/Core/GeometryFactory.js
var import_InlineWorkers1198 = __toESM(require_InlineWorkers(), 1);
function GeometryFactory() {
DeveloperError_default.throwInstantiationError();
}
GeometryFactory.createGeometry = function(geometryFactory) {
DeveloperError_default.throwInstantiationError();
};
var GeometryFactory_default = GeometryFactory;
// packages/engine/Source/Core/GoogleEarthEnterpriseMetadata.js
var import_InlineWorkers1201 = __toESM(require_InlineWorkers(), 1);
var protobuf = __toESM(require_protobuf(), 1);
// packages/engine/Source/Core/GoogleEarthEnterpriseTileInformation.js
var import_InlineWorkers1200 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/isBitSet.js
var import_InlineWorkers1199 = __toESM(require_InlineWorkers(), 1);
function isBitSet(bits, mask) {
return (bits & mask) !== 0;
}
var isBitSet_default = isBitSet;
// packages/engine/Source/Core/GoogleEarthEnterpriseTileInformation.js
var childrenBitmasks = [1, 2, 4, 8];
var anyChildBitmask = 15;
var cacheFlagBitmask = 16;
var imageBitmask = 64;
var terrainBitmask = 128;
function GoogleEarthEnterpriseTileInformation(bits, cnodeVersion, imageryVersion, terrainVersion, imageryProvider, terrainProvider) {
this._bits = bits;
this.cnodeVersion = cnodeVersion;
this.imageryVersion = imageryVersion;
this.terrainVersion = terrainVersion;
this.imageryProvider = imageryProvider;
this.terrainProvider = terrainProvider;
this.ancestorHasTerrain = false;
this.terrainState = void 0;
}
GoogleEarthEnterpriseTileInformation.clone = function(info, result) {
if (!defined_default(result)) {
result = new GoogleEarthEnterpriseTileInformation(
info._bits,
info.cnodeVersion,
info.imageryVersion,
info.terrainVersion,
info.imageryProvider,
info.terrainProvider
);
} else {
result._bits = info._bits;
result.cnodeVersion = info.cnodeVersion;
result.imageryVersion = info.imageryVersion;
result.terrainVersion = info.terrainVersion;
result.imageryProvider = info.imageryProvider;
result.terrainProvider = info.terrainProvider;
}
result.ancestorHasTerrain = info.ancestorHasTerrain;
result.terrainState = info.terrainState;
return result;
};
GoogleEarthEnterpriseTileInformation.prototype.setParent = function(parent) {
this.ancestorHasTerrain = parent.ancestorHasTerrain || this.hasTerrain();
};
GoogleEarthEnterpriseTileInformation.prototype.hasSubtree = function() {
return isBitSet_default(this._bits, cacheFlagBitmask);
};
GoogleEarthEnterpriseTileInformation.prototype.hasImagery = function() {
return isBitSet_default(this._bits, imageBitmask);
};
GoogleEarthEnterpriseTileInformation.prototype.hasTerrain = function() {
return isBitSet_default(this._bits, terrainBitmask);
};
GoogleEarthEnterpriseTileInformation.prototype.hasChildren = function() {
return isBitSet_default(this._bits, anyChildBitmask);
};
GoogleEarthEnterpriseTileInformation.prototype.hasChild = function(index) {
return isBitSet_default(this._bits, childrenBitmasks[index]);
};
GoogleEarthEnterpriseTileInformation.prototype.getChildBitmask = function() {
return this._bits & anyChildBitmask;
};
var GoogleEarthEnterpriseTileInformation_default = GoogleEarthEnterpriseTileInformation;
// packages/engine/Source/Core/GoogleEarthEnterpriseMetadata.js
function stringToBuffer(str) {
const len = str.length;
const buffer2 = new ArrayBuffer(len);
const ui8 = new Uint8Array(buffer2);
for (let i = 0; i < len; ++i) {
ui8[i] = str.charCodeAt(i);
}
return buffer2;
}
var defaultKey = stringToBuffer(
`E\xF4\xBD\vy\xE2jE"\x92,\xCDq\xF8IFgQ\0B%\xC6\xE8a,f)\b\xC64\xDCjb%y
wmi\xD6\xF0\x9Ck\x93\xA1\xBDNu\xE0A[\xDF@V\f\xD9\xBBr\x9B\x81|3S\xEEOl\xD4q\xB0{\xC0\x7FEVZ\xADwUe\v3\x92*\xACl5\xC50s\xF83>mF8J\xB4\xDD\xF0.\xDDu\xDA\x8CDt"\xFAa"\f3"So\xAF9D\v\x8C9\xD99L\xB9\xBF\x7F\xAB\\\x8CP_\x9F"ux\xE9\x07q\x91h;\xC1\xC4\x9B\x7F\xF0M\xAA>}\xE6\xCEI\x89\xC6\xE6x\fa1-\xA4O\xA5~q \x88\xEC\r1\xE8N\v\0nPh}=\b\r\x95\xA6n\xA3h\x97$[k\xF3#\xF3\xB6s\xB3\r\v@\xC0\x9F\xD8Q]\xFA".j\xDFI\0\xB9\xA0wU\xC6\xEFj\xBF{GL\x7F\x83\xEE\xDC\xDCF\x85\xA9\xADS\x07+S4\x07\xFF\x94Y\xE48\xE81\x83N\xB9XFk\xCB-#\x86\x92p\x005\x88"\xCF1\xB2&/\xE7\xC3u-6,rt\xB0#G\xB7\xD3\xD1&\x857r\xE2\0\x8CD\xCF\xDA3-\xDE\`\x86i#i*|\xCDKQ\r\x95T9w.)\xEA\x1B\xA6P\xA2j\x8FoP\x99\\>T\xFB\xEFP[\v\x07E\x89m(w7\xDB\x8EJfJo\x99 \xE5p\xE2\xB9q~\fmI-z\xFEr\xC7\xF2Y0\x8F\xBB]s\xE5\xC9 \xEAx\xEC \x90\xF0\x8A\x7FB|G\`\xB0\xBD&\xB7q\xB6\xC7\x9F\xD13\x82=\xD3\xAB\xEEc\x99\xC8+S\xA0D\\q\xC6\xCCD2O<\xCA\xC0)=R\xD3aX\xA9}e\xB4\xDC\xCF\r\xF4=\xF1\b\xA9B\xDA# \xD8\xBF^PI\xF8M\xC0\xCBGLO\xF7{+\xD8\xC51\x92;\xB5o\xDCl\r\x92\x88\xD1\x9E\xDB?\xE2\xE9\xDA_\xD4\x84\xE2FaZ\xDEU\xCF\xA4\0\xBE\xFD\xCEg\xF1Ji\x97\xE6 H\xD8]\x7F~\xAEq N\xAE\xC0V\xA9\x91<\x82r\xE7v\xEC)I\xD6]-\x83\xE3\xDB6\xA9;f\x97\x87j\xD5\xB6=P^R\xB9K\xC7sWx\xC9\xF4.Y\x07\x95\x93o\xD0KW>''\xC7\`\xDB;\xED\x9ASD>?\x8D\x92mw\xA2
\xEB?R\xA8\xC6U^1I7\x85\xF4\xC5&-\xA9\xBF\x8B'T\xDA\xC3j \xE5*x\xB0\xD6\x90pr\xAA\x8Bh\xBD\x88\xF7_H\xB1~\xC0XL?f\xF9>\xE1e\xC0p\xA7\xCF8i\xAF\xF0VldI\x9C'\xADxtO\xC2\x87\xDEV9\0\xDAw\v\xCB-\x1B\x89\xFB5O\xF5\bQ\`\xC1
ZGM&30x\xDA\xC0\x9CFG\xE2[y\`In7gS
>\xE9\xECF9\xB2\xF14\r\xC6\x84Sun\xE1\fY\xD9\xDE)\x85{II\xA5wy\xBEIV.6\xE7\v:\xBBOb{\xD2M1\x95/\xBD8{\xA8O!\xE1\xECFpv\x95})"x\x88
\x90\xDD\x9D\\\xDA\xDEQ\xCF\xF0\xFCYRe|3\xDF\xF3H\xDA\xBB*u\xDB\`\xB2\xD4\xFC\xED\x1B\xEC\x7F5\xA8\xFF(1\x07-\xC8\xDC\x88F|\x8A["`
);
function GoogleEarthEnterpriseMetadata(resourceOrUrl) {
this.imageryPresent = true;
this.protoImagery = void 0;
this.terrainPresent = true;
this.negativeAltitudeExponentBias = 32;
this.negativeAltitudeThreshold = Math_default.EPSILON12;
this.providers = {};
this.key = void 0;
this._resource = void 0;
this._quadPacketVersion = 1;
this._tileInfo = {};
this._subtreePromises = {};
}
Object.defineProperties(GoogleEarthEnterpriseMetadata.prototype, {
/**
* Gets the name of the Google Earth Enterprise server.
* @memberof GoogleEarthEnterpriseMetadata.prototype
* @type {string}
* @readonly
*/
url: {
get: function() {
return this._resource.url;
}
},
/**
* Gets the proxy used for metadata requests.
* @memberof GoogleEarthEnterpriseMetadata.prototype
* @type {Proxy}
* @readonly
*/
proxy: {
get: function() {
return this._resource.proxy;
}
},
/**
* Gets the resource used for metadata requests.
* @memberof GoogleEarthEnterpriseMetadata.prototype
* @type {Resource}
* @readonly
*/
resource: {
get: function() {
return this._resource;
}
}
});
GoogleEarthEnterpriseMetadata.fromUrl = async function(resourceOrUrl) {
Check_default.defined("resourceOrUrl", resourceOrUrl);
let url2 = resourceOrUrl;
if (typeof url2 !== "string" && !(url2 instanceof Resource_default)) {
Check_default.typeOf.string("resourceOrUrl.url", resourceOrUrl.url);
url2 = resourceOrUrl.url;
}
const resource = Resource_default.createIfNeeded(url2);
resource.appendForwardSlash();
const metadata = new GoogleEarthEnterpriseMetadata();
metadata._resource = resource;
try {
await requestDbRoot(metadata);
await metadata.getQuadTreePacket("", metadata._quadPacketVersion);
} catch (error) {
const message = `An error occurred while accessing ${getMetadataResource(metadata, "", 1).url}: ${error}`;
throw new RuntimeError_default(message);
}
return metadata;
};
GoogleEarthEnterpriseMetadata.tileXYToQuadKey = function(x, y, level) {
let quadkey = "";
for (let i = level; i >= 0; --i) {
const bitmask = 1 << i;
let digit = 0;
if (!isBitSet_default(y, bitmask)) {
digit |= 2;
if (!isBitSet_default(x, bitmask)) {
digit |= 1;
}
} else if (isBitSet_default(x, bitmask)) {
digit |= 1;
}
quadkey += digit;
}
return quadkey;
};
GoogleEarthEnterpriseMetadata.quadKeyToTileXY = function(quadkey) {
let x = 0;
let y = 0;
const level = quadkey.length - 1;
for (let i = level; i >= 0; --i) {
const bitmask = 1 << i;
const digit = +quadkey[level - i];
if (isBitSet_default(digit, 2)) {
if (!isBitSet_default(digit, 1)) {
x |= bitmask;
}
} else {
y |= bitmask;
if (isBitSet_default(digit, 1)) {
x |= bitmask;
}
}
}
return {
x,
y,
level
};
};
GoogleEarthEnterpriseMetadata.prototype.isValid = function(quadKey) {
let info = this.getTileInformationFromQuadKey(quadKey);
if (defined_default(info)) {
return info !== null;
}
let valid = true;
let q = quadKey;
let last;
while (q.length > 1) {
last = q.substring(q.length - 1);
q = q.substring(0, q.length - 1);
info = this.getTileInformationFromQuadKey(q);
if (defined_default(info)) {
if (!info.hasSubtree() && !info.hasChild(parseInt(last))) {
valid = false;
}
break;
} else if (info === null) {
valid = false;
break;
}
}
return valid;
};
var taskProcessor = new TaskProcessor_default("decodeGoogleEarthEnterprisePacket");
GoogleEarthEnterpriseMetadata.prototype.getQuadTreePacket = function(quadKey, version2, request) {
version2 = version2 ?? 1;
quadKey = quadKey ?? "";
const resource = getMetadataResource(this, quadKey, version2, request);
const promise = resource.fetchArrayBuffer();
if (!defined_default(promise)) {
return void 0;
}
const tileInfo = this._tileInfo;
const key = this.key;
return promise.then(function(metadata) {
const decodePromise = taskProcessor.scheduleTask(
{
buffer: metadata,
quadKey,
type: "Metadata",
key
},
[metadata]
);
return decodePromise.then(function(result) {
let root;
let topLevelKeyLength = -1;
if (quadKey !== "") {
topLevelKeyLength = quadKey.length + 1;
const top = result[quadKey];
root = tileInfo[quadKey];
root._bits |= top._bits;
delete result[quadKey];
}
const keys = Object.keys(result);
keys.sort(function(a3, b) {
return a3.length - b.length;
});
const keysLength = keys.length;
for (let i = 0; i < keysLength; ++i) {
const key2 = keys[i];
const r = result[key2];
if (r !== null) {
const info = GoogleEarthEnterpriseTileInformation_default.clone(result[key2]);
const keyLength = key2.length;
if (keyLength === topLevelKeyLength) {
info.setParent(root);
} else if (keyLength > 1) {
const parent = tileInfo[key2.substring(0, key2.length - 1)];
info.setParent(parent);
}
tileInfo[key2] = info;
} else {
tileInfo[key2] = null;
}
}
});
});
};
GoogleEarthEnterpriseMetadata.prototype.populateSubtree = function(x, y, level, request) {
const quadkey = GoogleEarthEnterpriseMetadata.tileXYToQuadKey(x, y, level);
return populateSubtree(this, quadkey, request);
};
function populateSubtree(that, quadKey, request) {
const tileInfo = that._tileInfo;
let q = quadKey;
let t = tileInfo[q];
if (defined_default(t) && (!t.hasSubtree() || t.hasChildren())) {
return t;
}
while (t === void 0 && q.length > 1) {
q = q.substring(0, q.length - 1);
t = tileInfo[q];
}
let subtreeRequest;
const subtreePromises = that._subtreePromises;
let promise = subtreePromises[q];
if (defined_default(promise)) {
return promise.then(function() {
subtreeRequest = new Request_default({
throttle: request.throttle,
throttleByServer: request.throttleByServer,
type: request.type,
priorityFunction: request.priorityFunction
});
return populateSubtree(that, quadKey, subtreeRequest);
});
}
if (!defined_default(t) || !t.hasSubtree()) {
return Promise.reject(
new RuntimeError_default(`Couldn't load metadata for tile ${quadKey}`)
);
}
promise = that.getQuadTreePacket(q, t.cnodeVersion, request);
if (!defined_default(promise)) {
return void 0;
}
subtreePromises[q] = promise;
return promise.then(function() {
subtreeRequest = new Request_default({
throttle: request.throttle,
throttleByServer: request.throttleByServer,
type: request.type,
priorityFunction: request.priorityFunction
});
return populateSubtree(that, quadKey, subtreeRequest);
}).finally(function() {
delete subtreePromises[q];
});
}
GoogleEarthEnterpriseMetadata.prototype.getTileInformation = function(x, y, level) {
const quadkey = GoogleEarthEnterpriseMetadata.tileXYToQuadKey(x, y, level);
return this._tileInfo[quadkey];
};
GoogleEarthEnterpriseMetadata.prototype.getTileInformationFromQuadKey = function(quadkey) {
return this._tileInfo[quadkey];
};
function getMetadataResource(that, quadKey, version2, request) {
return that._resource.getDerivedResource({
url: `flatfile?q2-0${quadKey}-q.${version2.toString()}`,
request
});
}
var dbrootParser;
var dbrootParserPromise;
function requestDbRoot(that) {
const resource = that._resource.getDerivedResource({
url: "dbRoot.v5",
queryParameters: {
output: "proto"
}
});
if (!defined_default(dbrootParserPromise)) {
const url2 = buildModuleUrl_default("ThirdParty/google-earth-dbroot-parser.js");
const oldValue2 = window.cesiumGoogleEarthDbRootParser;
dbrootParserPromise = loadAndExecuteScript_default(url2).then(function() {
dbrootParser = window.cesiumGoogleEarthDbRootParser(protobuf);
if (defined_default(oldValue2)) {
window.cesiumGoogleEarthDbRootParser = oldValue2;
} else {
delete window.cesiumGoogleEarthDbRootParser;
}
});
}
return dbrootParserPromise.then(function() {
return resource.fetchArrayBuffer();
}).then(function(buf) {
const encryptedDbRootProto = dbrootParser.EncryptedDbRootProto.decode(
new Uint8Array(buf)
);
let byteArray = encryptedDbRootProto.encryptionData;
let offset = byteArray.byteOffset;
let end = offset + byteArray.byteLength;
const key = that.key = byteArray.buffer.slice(offset, end);
byteArray = encryptedDbRootProto.dbrootData;
offset = byteArray.byteOffset;
end = offset + byteArray.byteLength;
const dbRootCompressed = byteArray.buffer.slice(offset, end);
return taskProcessor.scheduleTask(
{
buffer: dbRootCompressed,
type: "DbRoot",
key
},
[dbRootCompressed]
);
}).then(function(result) {
const dbRoot = dbrootParser.DbRootProto.decode(
new Uint8Array(result.buffer)
);
that.imageryPresent = dbRoot.imageryPresent ?? that.imageryPresent;
that.protoImagery = dbRoot.protoImagery;
that.terrainPresent = dbRoot.terrainPresent ?? that.terrainPresent;
if (defined_default(dbRoot.endSnippet) && defined_default(dbRoot.endSnippet.model)) {
const model = dbRoot.endSnippet.model;
that.negativeAltitudeExponentBias = model.negativeAltitudeExponentBias ?? that.negativeAltitudeExponentBias;
that.negativeAltitudeThreshold = model.compressedNegativeAltitudeThreshold ?? that.negativeAltitudeThreshold;
}
if (defined_default(dbRoot.databaseVersion)) {
that._quadPacketVersion = dbRoot.databaseVersion.quadtreeVersion ?? that._quadPacketVersion;
}
const providers = that.providers;
const providerInfo = dbRoot.providerInfo ?? [];
const count = providerInfo.length;
for (let i = 0; i < count; ++i) {
const provider = providerInfo[i];
const copyrightString = provider.copyrightString;
if (defined_default(copyrightString)) {
providers[provider.providerId] = new Credit_default(copyrightString.value);
}
}
}).catch(function() {
console.log(`Failed to retrieve ${resource.url}. Using defaults.`);
that.key = defaultKey;
});
}
var GoogleEarthEnterpriseMetadata_default = GoogleEarthEnterpriseMetadata;
// packages/engine/Source/Core/GoogleEarthEnterpriseTerrainData.js
var import_InlineWorkers1202 = __toESM(require_InlineWorkers(), 1);
function GoogleEarthEnterpriseTerrainData(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("options.buffer", options.buffer);
Check_default.typeOf.number(
"options.negativeAltitudeExponentBias",
options.negativeAltitudeExponentBias
);
Check_default.typeOf.number(
"options.negativeElevationThreshold",
options.negativeElevationThreshold
);
this._buffer = options.buffer;
this._credits = options.credits;
this._negativeAltitudeExponentBias = options.negativeAltitudeExponentBias;
this._negativeElevationThreshold = options.negativeElevationThreshold;
const googleChildTileMask = options.childTileMask ?? 15;
let childTileMask = googleChildTileMask & 3;
childTileMask |= googleChildTileMask & 4 ? 8 : 0;
childTileMask |= googleChildTileMask & 8 ? 4 : 0;
this._childTileMask = childTileMask;
this._createdByUpsampling = options.createdByUpsampling ?? false;
this._skirtHeight = void 0;
this._bufferType = this._buffer.constructor;
this._mesh = void 0;
this._minimumHeight = void 0;
this._maximumHeight = void 0;
}
Object.defineProperties(GoogleEarthEnterpriseTerrainData.prototype, {
/**
* An array of credits for this tile
* @memberof GoogleEarthEnterpriseTerrainData.prototype
* @type {Credit[]}
*/
credits: {
get: function() {
return this._credits;
}
},
/**
* The water mask included in this terrain data, if any. A water mask is a rectangular
* Uint8Array or image where a value of 255 indicates water and a value of 0 indicates land.
* Values in between 0 and 255 are allowed as well to smoothly blend between land and water.
* @memberof GoogleEarthEnterpriseTerrainData.prototype
* @type {Uint8Array|HTMLImageElement|HTMLCanvasElement|undefined}
*/
waterMask: {
get: function() {
return void 0;
}
}
});
var createMeshTaskName3 = "createVerticesFromGoogleEarthEnterpriseBuffer";
var createMeshTaskProcessorNoThrottle3 = new TaskProcessor_default(createMeshTaskName3);
var createMeshTaskProcessorThrottle3 = new TaskProcessor_default(
createMeshTaskName3,
TerrainData_default.maximumAsynchronousTasks
);
var nativeRectangleScratch = new Rectangle_default();
var rectangleScratch6 = new Rectangle_default();
GoogleEarthEnterpriseTerrainData.prototype.createMesh = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("options.tilingScheme", options.tilingScheme);
Check_default.typeOf.number("options.x", options.x);
Check_default.typeOf.number("options.y", options.y);
Check_default.typeOf.number("options.level", options.level);
const tilingScheme2 = options.tilingScheme;
const x = options.x;
const y = options.y;
const level = options.level;
const exaggeration = options.exaggeration ?? 1;
const exaggerationRelativeHeight = options.exaggerationRelativeHeight ?? 0;
const throttle = options.throttle ?? true;
const ellipsoid = tilingScheme2.ellipsoid;
tilingScheme2.tileXYToNativeRectangle(x, y, level, nativeRectangleScratch);
tilingScheme2.tileXYToRectangle(x, y, level, rectangleScratch6);
const center = ellipsoid.cartographicToCartesian(
Rectangle_default.center(rectangleScratch6)
);
const levelZeroMaxError = 40075.16;
const thisLevelMaxError = levelZeroMaxError / (1 << level);
this._skirtHeight = Math.min(thisLevelMaxError * 8, 1e3);
const createMeshTaskProcessor = throttle ? createMeshTaskProcessorThrottle3 : createMeshTaskProcessorNoThrottle3;
const verticesPromise = createMeshTaskProcessor.scheduleTask({
buffer: this._buffer,
nativeRectangle: nativeRectangleScratch,
rectangle: rectangleScratch6,
relativeToCenter: center,
ellipsoid,
skirtHeight: this._skirtHeight,
exaggeration,
exaggerationRelativeHeight,
includeWebMercatorT: true,
negativeAltitudeExponentBias: this._negativeAltitudeExponentBias,
negativeElevationThreshold: this._negativeElevationThreshold
});
if (!defined_default(verticesPromise)) {
return void 0;
}
const that = this;
return verticesPromise.then(function(result) {
that._mesh = new TerrainMesh_default(
center,
new Float32Array(result.vertices),
new Uint16Array(result.indices),
result.indexCountWithoutSkirts,
result.vertexCountWithoutSkirts,
result.minimumHeight,
result.maximumHeight,
BoundingSphere_default.clone(result.boundingSphere3D),
Cartesian3_default.clone(result.occludeePointInScaledSpace),
result.numberOfAttributes,
OrientedBoundingBox_default.clone(result.orientedBoundingBox),
TerrainEncoding_default.clone(result.encoding),
result.westIndicesSouthToNorth,
result.southIndicesEastToWest,
result.eastIndicesNorthToSouth,
result.northIndicesWestToEast
);
that._minimumHeight = result.minimumHeight;
that._maximumHeight = result.maximumHeight;
that._buffer = void 0;
return that._mesh;
});
};
GoogleEarthEnterpriseTerrainData.prototype.interpolateHeight = function(rectangle, longitude, latitude) {
const u3 = Math_default.clamp(
(longitude - rectangle.west) / rectangle.width,
0,
1
);
const v3 = Math_default.clamp(
(latitude - rectangle.south) / rectangle.height,
0,
1
);
if (!defined_default(this._mesh)) {
return interpolateHeight3(this, u3, v3, rectangle);
}
return interpolateMeshHeight3(this, u3, v3);
};
var upsampleTaskProcessor2 = new TaskProcessor_default(
"upsampleQuantizedTerrainMesh",
TerrainData_default.maximumAsynchronousTasks
);
GoogleEarthEnterpriseTerrainData.prototype.upsample = function(tilingScheme2, thisX, thisY, thisLevel, descendantX, descendantY, descendantLevel) {
Check_default.typeOf.object("tilingScheme", tilingScheme2);
Check_default.typeOf.number("thisX", thisX);
Check_default.typeOf.number("thisY", thisY);
Check_default.typeOf.number("thisLevel", thisLevel);
Check_default.typeOf.number("descendantX", descendantX);
Check_default.typeOf.number("descendantY", descendantY);
Check_default.typeOf.number("descendantLevel", descendantLevel);
const levelDifference = descendantLevel - thisLevel;
if (levelDifference > 1) {
throw new DeveloperError_default(
"Upsampling through more than one level at a time is not currently supported."
);
}
const mesh = this._mesh;
if (!defined_default(this._mesh)) {
return void 0;
}
const isEastChild = thisX * 2 !== descendantX;
const isNorthChild = thisY * 2 === descendantY;
const ellipsoid = tilingScheme2.ellipsoid;
const childRectangle = tilingScheme2.tileXYToRectangle(
descendantX,
descendantY,
descendantLevel
);
const upsamplePromise = upsampleTaskProcessor2.scheduleTask({
vertices: mesh.vertices,
indices: mesh.indices,
indexCountWithoutSkirts: mesh.indexCountWithoutSkirts,
vertexCountWithoutSkirts: mesh.vertexCountWithoutSkirts,
encoding: mesh.encoding,
minimumHeight: this._minimumHeight,
maximumHeight: this._maximumHeight,
isEastChild,
isNorthChild,
childRectangle,
ellipsoid
});
if (!defined_default(upsamplePromise)) {
return void 0;
}
const that = this;
return upsamplePromise.then(function(result) {
const quantizedVertices = new Uint16Array(result.vertices);
const indicesTypedArray = IndexDatatype_default.createTypedArray(
quantizedVertices.length / 3,
result.indices
);
const skirtHeight = that._skirtHeight;
return new QuantizedMeshTerrainData_default({
quantizedVertices,
indices: indicesTypedArray,
minimumHeight: result.minimumHeight,
maximumHeight: result.maximumHeight,
boundingSphere: BoundingSphere_default.clone(result.boundingSphere),
orientedBoundingBox: OrientedBoundingBox_default.clone(
result.orientedBoundingBox
),
horizonOcclusionPoint: Cartesian3_default.clone(result.horizonOcclusionPoint),
westIndices: result.westIndices,
southIndices: result.southIndices,
eastIndices: result.eastIndices,
northIndices: result.northIndices,
westSkirtHeight: skirtHeight,
southSkirtHeight: skirtHeight,
eastSkirtHeight: skirtHeight,
northSkirtHeight: skirtHeight,
childTileMask: 0,
createdByUpsampling: true,
credits: that._credits
});
});
};
GoogleEarthEnterpriseTerrainData.prototype.isChildAvailable = function(thisX, thisY, childX, childY) {
Check_default.typeOf.number("thisX", thisX);
Check_default.typeOf.number("thisY", thisY);
Check_default.typeOf.number("childX", childX);
Check_default.typeOf.number("childY", childY);
let bitNumber = 2;
if (childX !== thisX * 2) {
++bitNumber;
}
if (childY !== thisY * 2) {
bitNumber -= 2;
}
return (this._childTileMask & 1 << bitNumber) !== 0;
};
GoogleEarthEnterpriseTerrainData.prototype.wasCreatedByUpsampling = function() {
return this._createdByUpsampling;
};
var texCoordScratch02 = new Cartesian2_default();
var texCoordScratch12 = new Cartesian2_default();
var texCoordScratch22 = new Cartesian2_default();
var barycentricCoordinateScratch2 = new Cartesian3_default();
function interpolateMeshHeight3(terrainData, u3, v3) {
const mesh = terrainData._mesh;
const vertices = mesh.vertices;
const encoding = mesh.encoding;
const indices = mesh.indices;
for (let i = 0, len = indices.length; i < len; i += 3) {
const i0 = indices[i];
const i1 = indices[i + 1];
const i2 = indices[i + 2];
const uv0 = encoding.decodeTextureCoordinates(
vertices,
i0,
texCoordScratch02
);
const uv1 = encoding.decodeTextureCoordinates(
vertices,
i1,
texCoordScratch12
);
const uv2 = encoding.decodeTextureCoordinates(
vertices,
i2,
texCoordScratch22
);
const barycentric = Intersections2D_default.computeBarycentricCoordinates(
u3,
v3,
uv0.x,
uv0.y,
uv1.x,
uv1.y,
uv2.x,
uv2.y,
barycentricCoordinateScratch2
);
if (barycentric.x >= -1e-15 && barycentric.y >= -1e-15 && barycentric.z >= -1e-15) {
const h0 = encoding.decodeHeight(vertices, i0);
const h1 = encoding.decodeHeight(vertices, i1);
const h2 = encoding.decodeHeight(vertices, i2);
return barycentric.x * h0 + barycentric.y * h1 + barycentric.z * h2;
}
}
return void 0;
}
var sizeOfUint16 = Uint16Array.BYTES_PER_ELEMENT;
var sizeOfUint328 = Uint32Array.BYTES_PER_ELEMENT;
var sizeOfInt32 = Int32Array.BYTES_PER_ELEMENT;
var sizeOfFloat = Float32Array.BYTES_PER_ELEMENT;
var sizeOfDouble = Float64Array.BYTES_PER_ELEMENT;
function interpolateHeight3(terrainData, u3, v3, rectangle) {
const buffer2 = terrainData._buffer;
let quad = 0;
let uStart = 0;
let vStart = 0;
if (v3 > 0.5) {
if (u3 > 0.5) {
quad = 2;
uStart = 0.5;
} else {
quad = 3;
}
vStart = 0.5;
} else if (u3 > 0.5) {
quad = 1;
uStart = 0.5;
}
const dv = new DataView(buffer2);
let offset = 0;
for (let q = 0; q < quad; ++q) {
offset += dv.getUint32(offset, true);
offset += sizeOfUint328;
}
offset += sizeOfUint328;
offset += 2 * sizeOfDouble;
const xSize = Math_default.toRadians(dv.getFloat64(offset, true) * 180);
offset += sizeOfDouble;
const ySize = Math_default.toRadians(dv.getFloat64(offset, true) * 180);
offset += sizeOfDouble;
const xScale = rectangle.width / xSize / 2;
const yScale = rectangle.height / ySize / 2;
const numPoints = dv.getInt32(offset, true);
offset += sizeOfInt32;
const numIndices = dv.getInt32(offset, true) * 3;
offset += sizeOfInt32;
offset += sizeOfInt32;
const uBuffer = new Array(numPoints);
const vBuffer = new Array(numPoints);
const heights = new Array(numPoints);
let i;
for (i = 0; i < numPoints; ++i) {
uBuffer[i] = uStart + dv.getUint8(offset++) * xScale;
vBuffer[i] = vStart + dv.getUint8(offset++) * yScale;
heights[i] = dv.getFloat32(offset, true) * 6371010;
offset += sizeOfFloat;
}
const indices = new Array(numIndices);
for (i = 0; i < numIndices; ++i) {
indices[i] = dv.getUint16(offset, true);
offset += sizeOfUint16;
}
for (i = 0; i < numIndices; i += 3) {
const i0 = indices[i];
const i1 = indices[i + 1];
const i2 = indices[i + 2];
const u0 = uBuffer[i0];
const u12 = uBuffer[i1];
const u22 = uBuffer[i2];
const v02 = vBuffer[i0];
const v12 = vBuffer[i1];
const v22 = vBuffer[i2];
const barycentric = Intersections2D_default.computeBarycentricCoordinates(
u3,
v3,
u0,
v02,
u12,
v12,
u22,
v22,
barycentricCoordinateScratch2
);
if (barycentric.x >= -1e-15 && barycentric.y >= -1e-15 && barycentric.z >= -1e-15) {
return barycentric.x * heights[i0] + barycentric.y * heights[i1] + barycentric.z * heights[i2];
}
}
return void 0;
}
var GoogleEarthEnterpriseTerrainData_default = GoogleEarthEnterpriseTerrainData;
// packages/engine/Source/Core/GoogleEarthEnterpriseTerrainProvider.js
var import_InlineWorkers1203 = __toESM(require_InlineWorkers(), 1);
var TerrainState2 = {
UNKNOWN: 0,
NONE: 1,
SELF: 2,
PARENT: 3
};
var julianDateScratch2 = new JulianDate_default();
function TerrainCache() {
this._terrainCache = {};
this._lastTidy = JulianDate_default.now();
}
TerrainCache.prototype.add = function(quadKey, buffer2) {
this._terrainCache[quadKey] = {
buffer: buffer2,
timestamp: JulianDate_default.now()
};
};
TerrainCache.prototype.get = function(quadKey) {
const terrainCache = this._terrainCache;
const result = terrainCache[quadKey];
if (defined_default(result)) {
delete this._terrainCache[quadKey];
return result.buffer;
}
};
TerrainCache.prototype.tidy = function() {
JulianDate_default.now(julianDateScratch2);
if (JulianDate_default.secondsDifference(julianDateScratch2, this._lastTidy) > 10) {
const terrainCache = this._terrainCache;
const keys = Object.keys(terrainCache);
const count = keys.length;
for (let i = 0; i < count; ++i) {
const k = keys[i];
const e = terrainCache[k];
if (JulianDate_default.secondsDifference(julianDateScratch2, e.timestamp) > 10) {
delete terrainCache[k];
}
}
JulianDate_default.clone(julianDateScratch2, this._lastTidy);
}
};
function GoogleEarthEnterpriseTerrainProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._tilingScheme = new GeographicTilingScheme_default({
numberOfLevelZeroTilesX: 2,
numberOfLevelZeroTilesY: 2,
rectangle: new Rectangle_default(
-Math_default.PI,
-Math_default.PI,
Math_default.PI,
Math_default.PI
),
ellipsoid: options.ellipsoid
});
let credit = options.credit;
if (typeof credit === "string") {
credit = new Credit_default(credit);
}
this._credit = credit;
this._levelZeroMaximumGeometricError = 40075.16;
this._terrainCache = new TerrainCache();
this._terrainPromises = {};
this._terrainRequests = {};
this._errorEvent = new Event_default();
}
Object.defineProperties(GoogleEarthEnterpriseTerrainProvider.prototype, {
/**
* Gets the name of the Google Earth Enterprise server url hosting the imagery.
* @memberof GoogleEarthEnterpriseTerrainProvider.prototype
* @type {string}
* @readonly
*/
url: {
get: function() {
return this._metadata.url;
}
},
/**
* Gets the proxy used by this provider.
* @memberof GoogleEarthEnterpriseTerrainProvider.prototype
* @type {Proxy}
* @readonly
*/
proxy: {
get: function() {
return this._metadata.proxy;
}
},
/**
* Gets the tiling scheme used by this provider.
* @memberof GoogleEarthEnterpriseTerrainProvider.prototype
* @type {TilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._tilingScheme;
}
},
/**
* Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof GoogleEarthEnterpriseTerrainProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets the credit to display when this terrain provider is active. Typically this is used to credit
* the source of the terrain.
* @memberof GoogleEarthEnterpriseTerrainProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return this._credit;
}
},
/**
* Gets a value indicating whether or not the provider includes a water mask. The water mask
* indicates which areas of the globe are water rather than land, so they can be rendered
* as a reflective surface with animated waves.
* @memberof GoogleEarthEnterpriseTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasWaterMask: {
get: function() {
return false;
}
},
/**
* Gets a value indicating whether or not the requested tiles include vertex normals.
* @memberof GoogleEarthEnterpriseTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasVertexNormals: {
get: function() {
return false;
}
},
/**
* Gets an object that can be used to determine availability of terrain from this provider, such as
* at points and in rectangles. This property may be undefined if availability
* information is not available.
* @memberof GoogleEarthEnterpriseTerrainProvider.prototype
* @type {TileAvailability|undefined}
* @readonly
*/
availability: {
get: function() {
return void 0;
}
}
});
GoogleEarthEnterpriseTerrainProvider.fromMetadata = function(metadata, options) {
Check_default.defined("metadata", metadata);
if (!metadata.terrainPresent) {
throw new RuntimeError_default(`The server ${metadata.url} doesn't have terrain`);
}
const provider = new GoogleEarthEnterpriseTerrainProvider(options);
provider._metadata = metadata;
return provider;
};
var taskProcessor2 = new TaskProcessor_default("decodeGoogleEarthEnterprisePacket");
function computeChildMask(quadKey, info, metadata) {
let childMask = info.getChildBitmask();
if (info.terrainState === TerrainState2.PARENT) {
childMask = 0;
for (let i = 0; i < 4; ++i) {
const child = metadata.getTileInformationFromQuadKey(
quadKey + i.toString()
);
if (defined_default(child) && child.hasTerrain()) {
childMask |= 1 << i;
}
}
}
return childMask;
}
GoogleEarthEnterpriseTerrainProvider.prototype.requestTileGeometry = function(x, y, level, request) {
const quadKey = GoogleEarthEnterpriseMetadata_default.tileXYToQuadKey(x, y, level);
const terrainCache = this._terrainCache;
const metadata = this._metadata;
const info = metadata.getTileInformationFromQuadKey(quadKey);
if (!defined_default(info)) {
return Promise.reject(new RuntimeError_default("Terrain tile doesn't exist"));
}
let terrainState = info.terrainState;
if (!defined_default(terrainState)) {
terrainState = info.terrainState = TerrainState2.UNKNOWN;
}
const buffer2 = terrainCache.get(quadKey);
if (defined_default(buffer2)) {
const credit = metadata.providers[info.terrainProvider];
return Promise.resolve(
new GoogleEarthEnterpriseTerrainData_default({
buffer: buffer2,
childTileMask: computeChildMask(quadKey, info, metadata),
credits: defined_default(credit) ? [credit] : void 0,
negativeAltitudeExponentBias: metadata.negativeAltitudeExponentBias,
negativeElevationThreshold: metadata.negativeAltitudeThreshold
})
);
}
terrainCache.tidy();
if (!info.ancestorHasTerrain) {
return Promise.resolve(
new HeightmapTerrainData_default({
buffer: new Uint8Array(16 * 16),
width: 16,
height: 16
})
);
} else if (terrainState === TerrainState2.NONE) {
return Promise.reject(new RuntimeError_default("Terrain tile doesn't exist"));
}
let parentInfo;
let q = quadKey;
let terrainVersion = -1;
switch (terrainState) {
case TerrainState2.SELF:
terrainVersion = info.terrainVersion;
break;
case TerrainState2.PARENT:
q = q.substring(0, q.length - 1);
parentInfo = metadata.getTileInformationFromQuadKey(q);
terrainVersion = parentInfo.terrainVersion;
break;
case TerrainState2.UNKNOWN:
if (info.hasTerrain()) {
terrainVersion = info.terrainVersion;
} else {
q = q.substring(0, q.length - 1);
parentInfo = metadata.getTileInformationFromQuadKey(q);
if (defined_default(parentInfo) && parentInfo.hasTerrain()) {
terrainVersion = parentInfo.terrainVersion;
}
}
break;
}
if (terrainVersion < 0) {
return Promise.reject(new RuntimeError_default("Terrain tile doesn't exist"));
}
const terrainPromises = this._terrainPromises;
const terrainRequests = this._terrainRequests;
let sharedPromise;
let sharedRequest;
if (defined_default(terrainPromises[q])) {
sharedPromise = terrainPromises[q];
sharedRequest = terrainRequests[q];
} else {
sharedRequest = request;
const requestPromise = buildTerrainResource(
this,
q,
terrainVersion,
sharedRequest
).fetchArrayBuffer();
if (!defined_default(requestPromise)) {
return void 0;
}
sharedPromise = requestPromise.then(function(terrain) {
if (defined_default(terrain)) {
return taskProcessor2.scheduleTask(
{
buffer: terrain,
type: "Terrain",
key: metadata.key
},
[terrain]
).then(function(terrainTiles) {
const requestedInfo = metadata.getTileInformationFromQuadKey(q);
requestedInfo.terrainState = TerrainState2.SELF;
terrainCache.add(q, terrainTiles[0]);
const provider = requestedInfo.terrainProvider;
const count = terrainTiles.length - 1;
for (let j = 0; j < count; ++j) {
const childKey = q + j.toString();
const child = metadata.getTileInformationFromQuadKey(childKey);
if (defined_default(child)) {
terrainCache.add(childKey, terrainTiles[j + 1]);
child.terrainState = TerrainState2.PARENT;
if (child.terrainProvider === 0) {
child.terrainProvider = provider;
}
}
}
});
}
return Promise.reject(new RuntimeError_default("Failed to load terrain."));
});
terrainPromises[q] = sharedPromise;
terrainRequests[q] = sharedRequest;
sharedPromise = sharedPromise.finally(function() {
delete terrainPromises[q];
delete terrainRequests[q];
});
}
return sharedPromise.then(function() {
const buffer3 = terrainCache.get(quadKey);
if (defined_default(buffer3)) {
const credit = metadata.providers[info.terrainProvider];
return new GoogleEarthEnterpriseTerrainData_default({
buffer: buffer3,
childTileMask: computeChildMask(quadKey, info, metadata),
credits: defined_default(credit) ? [credit] : void 0,
negativeAltitudeExponentBias: metadata.negativeAltitudeExponentBias,
negativeElevationThreshold: metadata.negativeAltitudeThreshold
});
}
return Promise.reject(new RuntimeError_default("Failed to load terrain."));
}).catch(function(error) {
if (sharedRequest.state === RequestState_default.CANCELLED) {
request.state = sharedRequest.state;
return Promise.reject(error);
}
info.terrainState = TerrainState2.NONE;
return Promise.reject(error);
});
};
GoogleEarthEnterpriseTerrainProvider.prototype.getLevelMaximumGeometricError = function(level) {
return this._levelZeroMaximumGeometricError / (1 << level);
};
GoogleEarthEnterpriseTerrainProvider.prototype.getTileDataAvailable = function(x, y, level) {
const metadata = this._metadata;
let quadKey = GoogleEarthEnterpriseMetadata_default.tileXYToQuadKey(x, y, level);
const info = metadata.getTileInformation(x, y, level);
if (info === null) {
return false;
}
if (defined_default(info)) {
if (!info.ancestorHasTerrain) {
return true;
}
const terrainState = info.terrainState;
if (terrainState === TerrainState2.NONE) {
return false;
}
if (!defined_default(terrainState) || terrainState === TerrainState2.UNKNOWN) {
info.terrainState = TerrainState2.UNKNOWN;
if (!info.hasTerrain()) {
quadKey = quadKey.substring(0, quadKey.length - 1);
const parentInfo = metadata.getTileInformationFromQuadKey(quadKey);
if (!defined_default(parentInfo) || !parentInfo.hasTerrain()) {
return false;
}
}
}
return true;
}
if (metadata.isValid(quadKey)) {
const request = new Request_default({
throttle: false,
throttleByServer: true,
type: RequestType_default.TERRAIN
});
metadata.populateSubtree(x, y, level, request);
}
return false;
};
GoogleEarthEnterpriseTerrainProvider.prototype.loadTileDataAvailability = function(x, y, level) {
return void 0;
};
function buildTerrainResource(terrainProvider, quadKey, version2, request) {
version2 = defined_default(version2) && version2 > 0 ? version2 : 1;
return terrainProvider._metadata.resource.getDerivedResource({
url: `flatfile?f1c-0${quadKey}-t.${version2.toString()}`,
request
});
}
var GoogleEarthEnterpriseTerrainProvider_default = GoogleEarthEnterpriseTerrainProvider;
// packages/engine/Source/Core/GoogleGeocoderService.js
var import_InlineWorkers1204 = __toESM(require_InlineWorkers(), 1);
var API_URL = "https://maps.googleapis.com/maps/api/geocode/json";
var CREDIT_HTML = `
`;
function GoogleGeocoderService(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const key = options.key;
if (!defined_default(key)) {
throw new DeveloperError_default("options.key is required.");
}
this._resource = new Resource_default({
url: API_URL,
queryParameters: { key }
});
this._credit = new Credit_default(CREDIT_HTML, true);
}
Object.defineProperties(GoogleGeocoderService.prototype, {
/**
* Gets the credit to display after a geocode is performed. Typically this is used to credit
* the geocoder service.
* @memberof GoogleGeocoderService.prototype
* @type {Credit|undefined}
* @readonly
*/
credit: {
get: function() {
return this._credit;
}
}
});
GoogleGeocoderService.prototype.geocode = async function(query) {
Check_default.typeOf.string("query", query);
const resource = this._resource.getDerivedResource({
queryParameters: {
address: query
}
});
const response = await resource.fetchJson();
if (response.status === "ZERO_RESULTS") {
return [];
}
if (response.status !== "OK") {
throw new RuntimeError_default(
`GoogleGeocoderService got a bad response ${response.status}: ${response.error_message}`
);
}
const results = response.results.map((result) => {
const southWest = result.geometry.viewport.southwest;
const northEast = result.geometry.viewport.northeast;
return {
displayName: result.formatted_address,
destination: Rectangle_default.fromDegrees(
southWest.lng,
southWest.lat,
northEast.lng,
northEast.lat
),
attribution: {
html: CREDIT_HTML,
collapsible: false
}
};
});
return results;
};
var GoogleGeocoderService_default = GoogleGeocoderService;
// packages/engine/Source/Core/GoogleMaps.js
var import_InlineWorkers1205 = __toESM(require_InlineWorkers(), 1);
var GoogleMaps = {};
GoogleMaps.defaultApiKey = void 0;
GoogleMaps.mapTilesApiEndpoint = new Resource_default({
url: "https://tile.googleapis.com/v1/"
});
GoogleMaps.getDefaultCredit = function() {
return new Credit_default(
`
`,
true
);
};
var GoogleMaps_default = GoogleMaps;
// packages/engine/Source/Core/ITwinPlatform.js
var import_InlineWorkers1206 = __toESM(require_InlineWorkers(), 1);
var ITwinPlatform = {};
ITwinPlatform.ExportStatus = Object.freeze({
NotStarted: "NotStarted",
InProgress: "InProgress",
Complete: "Complete",
Invalid: "Invalid"
});
ITwinPlatform.ExportType = Object.freeze({
IMODEL: "IMODEL",
CESIUM: "CESIUM",
"3DTILES": "3DTILES"
});
ITwinPlatform.RealityDataType = Object.freeze({
Cesium3DTiles: "Cesium3DTiles",
PNTS: "PNTS",
RealityMesh3DTiles: "RealityMesh3DTiles",
Terrain3DTiles: "Terrain3DTiles",
KML: "KML",
GeoJSON: "GeoJSON",
Unstructured: "Unstructured"
});
ITwinPlatform.defaultAccessToken = void 0;
ITwinPlatform.defaultShareKey = void 0;
ITwinPlatform._getAuthorizationHeader = function() {
if (!defined_default(ITwinPlatform.defaultAccessToken) && !defined_default(ITwinPlatform.defaultShareKey)) {
throw new DeveloperError_default(
"Must set ITwinPlatform.defaultAccessToken or ITwinPlatform.defaultShareKey first"
);
}
if (defined_default(ITwinPlatform.defaultShareKey)) {
return `Basic ${ITwinPlatform.defaultShareKey}`;
}
return `Bearer ${ITwinPlatform.defaultAccessToken}`;
};
ITwinPlatform.apiEndpoint = new Resource_default({
url: "https://api.bentley.com"
});
ITwinPlatform.getExports = async function(iModelId, changesetId) {
Check_default.typeOf.string("iModelId", iModelId);
if (defined_default(changesetId)) {
Check_default.typeOf.string("changesetId", changesetId);
}
if (!defined_default(ITwinPlatform.defaultAccessToken) && !defined_default(ITwinPlatform.defaultShareKey)) {
throw new DeveloperError_default(
"Must set ITwinPlatform.defaultAccessToken or ITwinPlatform.defaultShareKey first"
);
}
const resource = new Resource_default({
url: `${ITwinPlatform.apiEndpoint}mesh-export`,
headers: {
Authorization: ITwinPlatform._getAuthorizationHeader(),
Accept: "application/vnd.bentley.itwin-platform.v1+json",
Prefer: "return=representation"
},
queryParameters: {
iModelId,
exportType: ITwinPlatform.ExportType["3DTILES"],
// With the export auto-generation it will auto-delete the 6th export so
// there should never be more than 5 results. Just request them all and parse
// for ones that are COMPLETE
$top: "5",
client: "CesiumJS"
}
});
if (typeof CESIUM_VERSION !== "undefined") {
resource.appendQueryParameters({ clientVersion: CESIUM_VERSION });
}
if (defined_default(changesetId) && changesetId !== "") {
resource.appendQueryParameters({ changesetId });
}
try {
const response = await resource.fetchJson();
return response;
} catch (error) {
const result = JSON.parse(error.response);
if (error.statusCode === 401) {
const code = result.error.details?.[0].code ?? "";
throw new RuntimeError_default(
`Unauthorized, bad token, wrong scopes or headers bad. ${code}`
);
} else if (error.statusCode === 403) {
console.error(result.error.code, result.error.message);
throw new RuntimeError_default("Not allowed, forbidden");
} else if (error.statusCode === 422) {
throw new RuntimeError_default(
`Unprocessable Entity:${result.error.code} ${result.error.message}`
);
} else if (error.statusCode === 429) {
throw new RuntimeError_default("Too many requests");
}
throw new RuntimeError_default(`Unknown request failure ${error.statusCode}`);
}
};
ITwinPlatform.getRealityDataMetadata = async function(iTwinId, realityDataId) {
Check_default.typeOf.string("iTwinId", iTwinId);
Check_default.typeOf.string("realityDataId", realityDataId);
if (!defined_default(ITwinPlatform.defaultAccessToken) && !defined_default(ITwinPlatform.defaultShareKey)) {
throw new DeveloperError_default(
"Must set ITwinPlatform.defaultAccessToken or ITwinPlatform.defaultShareKey first"
);
}
const resource = new Resource_default({
url: `${ITwinPlatform.apiEndpoint}reality-management/reality-data/${realityDataId}`,
headers: {
Authorization: ITwinPlatform._getAuthorizationHeader(),
Accept: "application/vnd.bentley.itwin-platform.v1+json"
},
queryParameters: { iTwinId }
});
try {
const response = await resource.fetchJson();
return response.realityData;
} catch (error) {
const result = JSON.parse(error.response);
if (error.statusCode === 401) {
const code = result.error.details?.[0].code ?? "";
throw new RuntimeError_default(
`Unauthorized, bad token, wrong scopes or headers bad. ${code}`
);
} else if (error.statusCode === 403) {
console.error(result.error.code, result.error.message);
throw new RuntimeError_default("Not allowed, forbidden");
} else if (error.statusCode === 404) {
throw new RuntimeError_default(
`Reality data not found: ${iTwinId}, ${realityDataId}`
);
} else if (error.statusCode === 422) {
throw new RuntimeError_default(
`Unprocessable Entity:${result.error.code} ${result.error.message}`
);
} else if (error.statusCode === 429) {
throw new RuntimeError_default("Too many requests");
}
throw new RuntimeError_default(`Unknown request failure ${error.statusCode}`);
}
};
ITwinPlatform.getRealityDataURL = async function(iTwinId, realityDataId, rootDocument) {
Check_default.typeOf.string("iTwinId", iTwinId);
Check_default.typeOf.string("realityDataId", realityDataId);
Check_default.typeOf.string("rootDocument", rootDocument);
if (!defined_default(ITwinPlatform.defaultAccessToken) && !defined_default(ITwinPlatform.defaultShareKey)) {
throw new DeveloperError_default(
"Must set ITwinPlatform.defaultAccessToken or ITwinPlatform.defaultShareKey first"
);
}
const resource = new Resource_default({
url: `${ITwinPlatform.apiEndpoint}reality-management/reality-data/${realityDataId}/readaccess`,
headers: {
Authorization: ITwinPlatform._getAuthorizationHeader(),
Accept: "application/vnd.bentley.itwin-platform.v1+json"
},
queryParameters: { iTwinId }
});
try {
const result = await resource.fetchJson();
const containerUrl = result._links.containerUrl.href;
const tilesetUrl = new URL(containerUrl);
tilesetUrl.pathname = `${tilesetUrl.pathname}/${rootDocument}`;
return tilesetUrl.toString();
} catch (error) {
const result = JSON.parse(error.response);
if (error.statusCode === 401) {
const code = result.error.details?.[0].code ?? "";
throw new RuntimeError_default(
`Unauthorized, bad token, wrong scopes or headers bad. ${code}`
);
} else if (error.statusCode === 403) {
console.error(result.error.code, result.error.message);
throw new RuntimeError_default("Not allowed, forbidden");
} else if (error.statusCode === 404) {
throw new RuntimeError_default(
`Reality data not found: ${iTwinId}, ${realityDataId}`
);
} else if (error.statusCode === 422) {
throw new RuntimeError_default(
`Unprocessable Entity:${result.error.code} ${result.error.message}`
);
} else if (error.statusCode === 429) {
throw new RuntimeError_default("Too many requests");
}
throw new RuntimeError_default(`Unknown request failure ${error.statusCode}`);
}
};
var ITwinPlatform_default = ITwinPlatform;
// packages/engine/Source/Core/InterpolationAlgorithm.js
var import_InlineWorkers1207 = __toESM(require_InlineWorkers(), 1);
var InterpolationAlgorithm = {};
InterpolationAlgorithm.type = void 0;
InterpolationAlgorithm.getRequiredDataPoints = DeveloperError_default.throwInstantiationError;
InterpolationAlgorithm.interpolateOrderZero = DeveloperError_default.throwInstantiationError;
InterpolationAlgorithm.interpolate = DeveloperError_default.throwInstantiationError;
var InterpolationAlgorithm_default = InterpolationAlgorithm;
// packages/engine/Source/Core/IonGeocodeProviderType.js
var import_InlineWorkers1208 = __toESM(require_InlineWorkers(), 1);
var IonGeocodeProviderType = {
/**
* Google geocoder, for use with Google data.
*
* @type {string}
* @constant
*/
GOOGLE: "GOOGLE",
/**
* Bing geocoder, for use with Bing data.
*
* @type {string}
* @constant
*/
BING: "BING",
/**
* Use the default geocoder as set on the server. Used when neither Bing or
* Google data is used.
*
* @type {string}
* @constant
*/
DEFAULT: "DEFAULT"
};
var IonGeocodeProviderType_default = Object.freeze(IonGeocodeProviderType);
// packages/engine/Source/Core/IonGeocoderService.js
var import_InlineWorkers1210 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Core/PeliasGeocoderService.js
var import_InlineWorkers1209 = __toESM(require_InlineWorkers(), 1);
function PeliasGeocoderService(url2) {
Check_default.defined("url", url2);
this._url = Resource_default.createIfNeeded(url2);
this._url.appendForwardSlash();
}
Object.defineProperties(PeliasGeocoderService.prototype, {
/**
* The Resource used to access the Pelias endpoint.
* @type {Resource}
* @memberof PeliasGeocoderService.prototype
* @readonly
*/
url: {
get: function() {
return this._url;
}
},
/**
* Gets the credit to display after a geocode is performed. Typically this is used to credit
* the geocoder service.
* @memberof PeliasGeocoderService.prototype
* @type {Credit|undefined}
* @readonly
*/
credit: {
get: function() {
return void 0;
}
}
});
PeliasGeocoderService.prototype.geocode = async function(query, type) {
Check_default.typeOf.string("query", query);
const resource = this._url.getDerivedResource({
url: type === GeocodeType_default.AUTOCOMPLETE ? "autocomplete" : "search",
queryParameters: {
text: query
}
});
return resource.fetchJson().then(function(results) {
return results.features.map(function(resultObject) {
let destination;
const bboxDegrees = resultObject.bbox;
if (defined_default(bboxDegrees)) {
destination = Rectangle_default.fromDegrees(
bboxDegrees[0],
bboxDegrees[1],
bboxDegrees[2],
bboxDegrees[3]
);
} else {
const lon = resultObject.geometry.coordinates[0];
const lat = resultObject.geometry.coordinates[1];
destination = Cartesian3_default.fromDegrees(lon, lat);
}
return {
displayName: resultObject.properties.label,
destination,
attributions: results.attributions
};
});
});
};
var PeliasGeocoderService_default = PeliasGeocoderService;
// packages/engine/Source/Core/IonGeocoderService.js
function validateIonGeocodeProviderType(geocodeProviderType) {
if (!Object.values(IonGeocodeProviderType_default).some(
(value) => value === geocodeProviderType
)) {
throw new DeveloperError_default(
`Invalid geocodeProviderType: "${geocodeProviderType}"`
);
}
}
var providerToParameterMap = Object.freeze({
[IonGeocodeProviderType_default.GOOGLE]: "google",
[IonGeocodeProviderType_default.BING]: "bing",
[IonGeocodeProviderType_default.DEFAULT]: void 0
});
function providerToQueryParameter(provider) {
return providerToParameterMap[provider];
}
function queryParameterToProvider(parameter) {
return Object.entries(providerToParameterMap).find(
(entry) => entry[1] === parameter
)[0];
}
function IonGeocoderService(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("options.scene", options.scene);
const geocodeProviderType = options.geocodeProviderType ?? IonGeocodeProviderType_default.DEFAULT;
validateIonGeocodeProviderType(geocodeProviderType);
const accessToken = options.accessToken ?? Ion_default.defaultAccessToken;
const server = Resource_default.createIfNeeded(options.server ?? Ion_default.defaultServer);
server.appendForwardSlash();
const defaultTokenCredit3 = Ion_default.getDefaultTokenCredit(accessToken);
if (defined_default(defaultTokenCredit3)) {
options.scene.frameState.creditDisplay.addStaticCredit(
Credit_default.clone(defaultTokenCredit3)
);
}
const searchEndpoint = server.getDerivedResource({
url: "v1/geocode"
});
if (defined_default(accessToken)) {
searchEndpoint.appendQueryParameters({ access_token: accessToken });
}
this._accessToken = accessToken;
this._server = server;
this._pelias = new PeliasGeocoderService_default(searchEndpoint);
this.geocodeProviderType = geocodeProviderType;
}
Object.defineProperties(IonGeocoderService.prototype, {
/**
* Gets the credit to display after a geocode is performed. Typically this is used to credit
* the geocoder service.
* @memberof IonGeocoderService.prototype
* @type {Credit|undefined}
* @readonly
*/
credit: {
get: function() {
return void 0;
}
},
/**
* The geocoding service that Cesium ion API server should use to fulfill geocding requests.
* @memberof IonGeocoderService.prototype
* @type {IonGeocodeProviderType}
* @default IonGeocodeProviderType.DEFAULT
*/
geocodeProviderType: {
get: function() {
return queryParameterToProvider(
this._pelias.url.queryParameters["geocoder"]
);
},
set: function(geocodeProviderType) {
validateIonGeocodeProviderType(geocodeProviderType);
const query = {
...this._pelias.url.queryParameters,
geocoder: providerToQueryParameter(geocodeProviderType)
};
if (!defined_default(query.geocoder)) {
delete query.geocoder;
}
this._pelias.url.setQueryParameters(query);
}
}
});
IonGeocoderService.prototype.geocode = async function(query, geocodeType) {
return this._pelias.geocode(query, geocodeType);
};
var IonGeocoderService_default = IonGeocoderService;
// packages/engine/Source/Core/MapProjection.js
var import_InlineWorkers1211 = __toESM(require_InlineWorkers(), 1);
function MapProjection() {
DeveloperError_default.throwInstantiationError();
}
Object.defineProperties(MapProjection.prototype, {
/**
* Gets the {@link Ellipsoid}.
*
* @memberof MapProjection.prototype
*
* @type {Ellipsoid}
* @readonly
*/
ellipsoid: {
get: DeveloperError_default.throwInstantiationError
}
});
MapProjection.prototype.project = DeveloperError_default.throwInstantiationError;
MapProjection.prototype.unproject = DeveloperError_default.throwInstantiationError;
var MapProjection_default = MapProjection;
// packages/engine/Source/Core/MorphWeightSpline.js
var import_InlineWorkers1212 = __toESM(require_InlineWorkers(), 1);
function MorphWeightSpline(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const weights2 = options.weights;
const times = options.times;
Check_default.defined("weights", weights2);
Check_default.defined("times", times);
Check_default.typeOf.number.greaterThanOrEquals("weights.length", weights2.length, 3);
if (weights2.length % times.length !== 0) {
throw new DeveloperError_default(
"times.length must be a factor of weights.length."
);
}
this._times = times;
this._weights = weights2;
this._count = weights2.length / times.length;
this._lastTimeIndex = 0;
}
Object.defineProperties(MorphWeightSpline.prototype, {
/**
* An array of times for the control weights.
*
* @memberof WeightSpline.prototype
*
* @type {number[]}
* @readonly
*/
times: {
get: function() {
return this._times;
}
},
/**
* An array of floating-point array control weights.
*
* @memberof WeightSpline.prototype
*
* @type {number[]}
* @readonly
*/
weights: {
get: function() {
return this._weights;
}
}
});
MorphWeightSpline.prototype.findTimeInterval = Spline_default.prototype.findTimeInterval;
MorphWeightSpline.prototype.wrapTime = Spline_default.prototype.wrapTime;
MorphWeightSpline.prototype.clampTime = Spline_default.prototype.clampTime;
MorphWeightSpline.prototype.evaluate = function(time, result) {
const weights2 = this.weights;
const times = this.times;
const i = this._lastTimeIndex = this.findTimeInterval(
time,
this._lastTimeIndex
);
const u3 = (time - times[i]) / (times[i + 1] - times[i]);
if (!defined_default(result)) {
result = new Array(this._count);
}
for (let j = 0; j < this._count; j++) {
const index = i * this._count + j;
result[j] = weights2[index] * (1 - u3) + weights2[index + this._count] * u3;
}
return result;
};
var MorphWeightSpline_default = MorphWeightSpline;
// packages/engine/Source/Core/OpenCageGeocoderService.js
var import_InlineWorkers1213 = __toESM(require_InlineWorkers(), 1);
function OpenCageGeocoderService(url2, apiKey, params) {
Check_default.defined("url", url2);
Check_default.defined("apiKey", apiKey);
if (defined_default(params)) {
Check_default.typeOf.object("params", params);
}
url2 = Resource_default.createIfNeeded(url2);
url2.appendForwardSlash();
url2.setQueryParameters({ key: apiKey });
this._url = url2;
this._params = params ?? {};
this._credit = new Credit_default(
`Geodata copyright OpenStreetMap contributors`,
false
);
}
Object.defineProperties(OpenCageGeocoderService.prototype, {
/**
* The Resource used to access the OpenCage endpoint.
* @type {Resource}
* @memberof OpenCageGeocoderService.prototype
* @readonly
*/
url: {
get: function() {
return this._url;
}
},
/**
* Optional params passed to OpenCage in order to customize geocoding
* @type {object}
* @memberof OpenCageGeocoderService.prototype
* @readonly
*/
params: {
get: function() {
return this._params;
}
},
/**
* Gets the credit to display after a geocode is performed. Typically this is used to credit
* the geocoder service.
* @memberof OpenCageGeocoderService.prototype
* @type {Credit|undefined}
* @readonly
*/
credit: {
get: function() {
return this._credit;
}
}
});
OpenCageGeocoderService.prototype.geocode = async function(query) {
Check_default.typeOf.string("query", query);
const resource = this._url.getDerivedResource({
url: "json",
queryParameters: combine_default(this._params, { q: query })
});
return resource.fetchJson().then(function(response) {
return response.results.map(function(resultObject) {
let destination;
const bounds = resultObject.bounds;
if (defined_default(bounds)) {
destination = Rectangle_default.fromDegrees(
bounds.southwest.lng,
bounds.southwest.lat,
bounds.northeast.lng,
bounds.northeast.lat
);
} else {
const lon = resultObject.geometry.lat;
const lat = resultObject.geometry.lng;
destination = Cartesian3_default.fromDegrees(lon, lat);
}
return {
displayName: resultObject.formatted,
destination
};
});
});
};
var OpenCageGeocoderService_default = OpenCageGeocoderService;
// packages/engine/Source/Core/Packable.js
var import_InlineWorkers1214 = __toESM(require_InlineWorkers(), 1);
var Packable = {
/**
* The number of elements used to pack the object into an array.
* @type {number}
*/
packedLength: void 0,
/**
* Stores the provided instance into the provided array.
* @function
*
* @param {*} value The value to pack.
* @param {number[]} array The array to pack into.
* @param {number} [startingIndex=0] The index into the array at which to start packing the elements.
*/
pack: DeveloperError_default.throwInstantiationError,
/**
* Retrieves an instance from a packed array.
* @function
*
* @param {number[]} array The packed array.
* @param {number} [startingIndex=0] The starting index of the element to be unpacked.
* @param {object} [result] The object into which to store the result.
* @returns {object} The modified result parameter or a new Object instance if one was not provided.
*/
unpack: DeveloperError_default.throwInstantiationError
};
var Packable_default = Packable;
// packages/engine/Source/Core/PackableForInterpolation.js
var import_InlineWorkers1215 = __toESM(require_InlineWorkers(), 1);
var PackableForInterpolation = {
/**
* The number of elements used to store the object into an array in its interpolatable form.
* @type {number}
*/
packedInterpolationLength: void 0,
/**
* Converts a packed array into a form suitable for interpolation.
* @function
*
* @param {number[]} packedArray The packed array.
* @param {number} [startingIndex=0] The index of the first element to be converted.
* @param {number} [lastIndex=packedArray.length] The index of the last element to be converted.
* @param {number[]} [result] The object into which to store the result.
*/
convertPackedArrayForInterpolation: DeveloperError_default.throwInstantiationError,
/**
* Retrieves an instance from a packed array converted with {@link PackableForInterpolation.convertPackedArrayForInterpolation}.
* @function
*
* @param {number[]} array The array previously packed for interpolation.
* @param {number[]} sourceArray The original packed array.
* @param {number} [startingIndex=0] The startingIndex used to convert the array.
* @param {number} [lastIndex=packedArray.length] The lastIndex used to convert the array.
* @param {object} [result] The object into which to store the result.
* @returns {object} The modified result parameter or a new Object instance if one was not provided.
*/
unpackInterpolationResult: DeveloperError_default.throwInstantiationError
};
var PackableForInterpolation_default = PackableForInterpolation;
// packages/engine/Source/Core/Proxy.js
var import_InlineWorkers1216 = __toESM(require_InlineWorkers(), 1);
function Proxy2() {
DeveloperError_default.throwInstantiationError();
}
Proxy2.prototype.getURL = DeveloperError_default.throwInstantiationError;
var Proxy_default = Proxy2;
// packages/engine/Source/Core/SimplePolylineGeometry.js
var import_InlineWorkers1217 = __toESM(require_InlineWorkers(), 1);
function interpolateColors2(p0, p1, color0, color1, minDistance, array, offset) {
const numPoints = PolylinePipeline_default.numberOfPoints(p0, p1, minDistance);
let i;
const r0 = color0.red;
const g0 = color0.green;
const b0 = color0.blue;
const a0 = color0.alpha;
const r1 = color1.red;
const g1 = color1.green;
const b1 = color1.blue;
const a1 = color1.alpha;
if (Color_default.equals(color0, color1)) {
for (i = 0; i < numPoints; i++) {
array[offset++] = Color_default.floatToByte(r0);
array[offset++] = Color_default.floatToByte(g0);
array[offset++] = Color_default.floatToByte(b0);
array[offset++] = Color_default.floatToByte(a0);
}
return offset;
}
const redPerVertex = (r1 - r0) / numPoints;
const greenPerVertex = (g1 - g0) / numPoints;
const bluePerVertex = (b1 - b0) / numPoints;
const alphaPerVertex = (a1 - a0) / numPoints;
let index = offset;
for (i = 0; i < numPoints; i++) {
array[index++] = Color_default.floatToByte(r0 + i * redPerVertex);
array[index++] = Color_default.floatToByte(g0 + i * greenPerVertex);
array[index++] = Color_default.floatToByte(b0 + i * bluePerVertex);
array[index++] = Color_default.floatToByte(a0 + i * alphaPerVertex);
}
return index;
}
function SimplePolylineGeometry(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const positions = options.positions;
const colors = options.colors;
const colorsPerVertex = options.colorsPerVertex ?? false;
if (!defined_default(positions) || positions.length < 2) {
throw new DeveloperError_default("At least two positions are required.");
}
if (defined_default(colors) && (colorsPerVertex && colors.length < positions.length || !colorsPerVertex && colors.length < positions.length - 1)) {
throw new DeveloperError_default("colors has an invalid length.");
}
this._positions = positions;
this._colors = colors;
this._colorsPerVertex = colorsPerVertex;
this._arcType = options.arcType ?? ArcType_default.GEODESIC;
this._granularity = options.granularity ?? Math_default.RADIANS_PER_DEGREE;
this._ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
this._workerName = "createSimplePolylineGeometry";
let numComponents = 1 + positions.length * Cartesian3_default.packedLength;
numComponents += defined_default(colors) ? 1 + colors.length * Color_default.packedLength : 1;
this.packedLength = numComponents + Ellipsoid_default.packedLength + 3;
}
SimplePolylineGeometry.pack = function(value, array, startingIndex) {
if (!defined_default(value)) {
throw new DeveloperError_default("value is required");
}
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
const positions = value._positions;
let length2 = positions.length;
array[startingIndex++] = length2;
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
Cartesian3_default.pack(positions[i], array, startingIndex);
}
const colors = value._colors;
length2 = defined_default(colors) ? colors.length : 0;
array[startingIndex++] = length2;
for (i = 0; i < length2; ++i, startingIndex += Color_default.packedLength) {
Color_default.pack(colors[i], array, startingIndex);
}
Ellipsoid_default.pack(value._ellipsoid, array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
array[startingIndex++] = value._colorsPerVertex ? 1 : 0;
array[startingIndex++] = value._arcType;
array[startingIndex] = value._granularity;
return array;
};
SimplePolylineGeometry.unpack = function(array, startingIndex, result) {
if (!defined_default(array)) {
throw new DeveloperError_default("array is required");
}
startingIndex = startingIndex ?? 0;
let i;
let length2 = array[startingIndex++];
const positions = new Array(length2);
for (i = 0; i < length2; ++i, startingIndex += Cartesian3_default.packedLength) {
positions[i] = Cartesian3_default.unpack(array, startingIndex);
}
length2 = array[startingIndex++];
const colors = length2 > 0 ? new Array(length2) : void 0;
for (i = 0; i < length2; ++i, startingIndex += Color_default.packedLength) {
colors[i] = Color_default.unpack(array, startingIndex);
}
const ellipsoid = Ellipsoid_default.unpack(array, startingIndex);
startingIndex += Ellipsoid_default.packedLength;
const colorsPerVertex = array[startingIndex++] === 1;
const arcType = array[startingIndex++];
const granularity = array[startingIndex];
if (!defined_default(result)) {
return new SimplePolylineGeometry({
positions,
colors,
ellipsoid,
colorsPerVertex,
arcType,
granularity
});
}
result._positions = positions;
result._colors = colors;
result._ellipsoid = ellipsoid;
result._colorsPerVertex = colorsPerVertex;
result._arcType = arcType;
result._granularity = granularity;
return result;
};
var scratchArray1 = new Array(2);
var scratchArray22 = new Array(2);
var generateArcOptionsScratch2 = {
positions: scratchArray1,
height: scratchArray22,
ellipsoid: void 0,
minDistance: void 0,
granularity: void 0
};
SimplePolylineGeometry.createGeometry = function(simplePolylineGeometry) {
const positions = simplePolylineGeometry._positions;
const colors = simplePolylineGeometry._colors;
const colorsPerVertex = simplePolylineGeometry._colorsPerVertex;
const arcType = simplePolylineGeometry._arcType;
const granularity = simplePolylineGeometry._granularity;
const ellipsoid = simplePolylineGeometry._ellipsoid;
const minDistance = Math_default.chordLength(
granularity,
ellipsoid.maximumRadius
);
const perSegmentColors = defined_default(colors) && !colorsPerVertex;
let i;
const length2 = positions.length;
let positionValues;
let numberOfPositions;
let colorValues;
let color;
let offset = 0;
if (arcType === ArcType_default.GEODESIC || arcType === ArcType_default.RHUMB) {
let subdivisionSize;
let numberOfPointsFunction;
let generateArcFunction;
if (arcType === ArcType_default.GEODESIC) {
subdivisionSize = Math_default.chordLength(
granularity,
ellipsoid.maximumRadius
);
numberOfPointsFunction = PolylinePipeline_default.numberOfPoints;
generateArcFunction = PolylinePipeline_default.generateArc;
} else {
subdivisionSize = granularity;
numberOfPointsFunction = PolylinePipeline_default.numberOfPointsRhumbLine;
generateArcFunction = PolylinePipeline_default.generateRhumbArc;
}
const heights = PolylinePipeline_default.extractHeights(positions, ellipsoid);
const generateArcOptions = generateArcOptionsScratch2;
if (arcType === ArcType_default.GEODESIC) {
generateArcOptions.minDistance = minDistance;
} else {
generateArcOptions.granularity = granularity;
}
generateArcOptions.ellipsoid = ellipsoid;
if (perSegmentColors) {
let positionCount = 0;
for (i = 0; i < length2 - 1; i++) {
positionCount += numberOfPointsFunction(
positions[i],
positions[i + 1],
subdivisionSize
) + 1;
}
positionValues = new Float64Array(positionCount * 3);
colorValues = new Uint8Array(positionCount * 4);
generateArcOptions.positions = scratchArray1;
generateArcOptions.height = scratchArray22;
let ci = 0;
for (i = 0; i < length2 - 1; ++i) {
scratchArray1[0] = positions[i];
scratchArray1[1] = positions[i + 1];
scratchArray22[0] = heights[i];
scratchArray22[1] = heights[i + 1];
const pos = generateArcFunction(generateArcOptions);
if (defined_default(colors)) {
const segLen = pos.length / 3;
color = colors[i];
for (let k = 0; k < segLen; ++k) {
colorValues[ci++] = Color_default.floatToByte(color.red);
colorValues[ci++] = Color_default.floatToByte(color.green);
colorValues[ci++] = Color_default.floatToByte(color.blue);
colorValues[ci++] = Color_default.floatToByte(color.alpha);
}
}
positionValues.set(pos, offset);
offset += pos.length;
}
} else {
generateArcOptions.positions = positions;
generateArcOptions.height = heights;
positionValues = new Float64Array(
generateArcFunction(generateArcOptions)
);
if (defined_default(colors)) {
colorValues = new Uint8Array(positionValues.length / 3 * 4);
for (i = 0; i < length2 - 1; ++i) {
const p0 = positions[i];
const p1 = positions[i + 1];
const c0 = colors[i];
const c14 = colors[i + 1];
offset = interpolateColors2(
p0,
p1,
c0,
c14,
minDistance,
colorValues,
offset
);
}
const lastColor = colors[length2 - 1];
colorValues[offset++] = Color_default.floatToByte(lastColor.red);
colorValues[offset++] = Color_default.floatToByte(lastColor.green);
colorValues[offset++] = Color_default.floatToByte(lastColor.blue);
colorValues[offset++] = Color_default.floatToByte(lastColor.alpha);
}
}
} else {
numberOfPositions = perSegmentColors ? length2 * 2 - 2 : length2;
positionValues = new Float64Array(numberOfPositions * 3);
colorValues = defined_default(colors) ? new Uint8Array(numberOfPositions * 4) : void 0;
let positionIndex = 0;
let colorIndex = 0;
for (i = 0; i < length2; ++i) {
const p = positions[i];
if (perSegmentColors && i > 0) {
Cartesian3_default.pack(p, positionValues, positionIndex);
positionIndex += 3;
color = colors[i - 1];
colorValues[colorIndex++] = Color_default.floatToByte(color.red);
colorValues[colorIndex++] = Color_default.floatToByte(color.green);
colorValues[colorIndex++] = Color_default.floatToByte(color.blue);
colorValues[colorIndex++] = Color_default.floatToByte(color.alpha);
}
if (perSegmentColors && i === length2 - 1) {
break;
}
Cartesian3_default.pack(p, positionValues, positionIndex);
positionIndex += 3;
if (defined_default(colors)) {
color = colors[i];
colorValues[colorIndex++] = Color_default.floatToByte(color.red);
colorValues[colorIndex++] = Color_default.floatToByte(color.green);
colorValues[colorIndex++] = Color_default.floatToByte(color.blue);
colorValues[colorIndex++] = Color_default.floatToByte(color.alpha);
}
}
}
const attributes = new GeometryAttributes_default();
attributes.position = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.DOUBLE,
componentsPerAttribute: 3,
values: positionValues
});
if (defined_default(colors)) {
attributes.color = new GeometryAttribute_default({
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
componentsPerAttribute: 4,
values: colorValues,
normalize: true
});
}
numberOfPositions = positionValues.length / 3;
const numberOfIndices = (numberOfPositions - 1) * 2;
const indices = IndexDatatype_default.createTypedArray(
numberOfPositions,
numberOfIndices
);
let index = 0;
for (i = 0; i < numberOfPositions - 1; ++i) {
indices[index++] = i;
indices[index++] = i + 1;
}
return new Geometry_default({
attributes,
indices,
primitiveType: PrimitiveType_default.LINES,
boundingSphere: BoundingSphere_default.fromPoints(positions)
});
};
var SimplePolylineGeometry_default = SimplePolylineGeometry;
// packages/engine/Source/Core/SphereGeometry.js
var import_InlineWorkers1218 = __toESM(require_InlineWorkers(), 1);
function SphereGeometry(options) {
const radius = options.radius ?? 1;
const radii = new Cartesian3_default(radius, radius, radius);
const ellipsoidOptions = {
radii,
stackPartitions: options.stackPartitions,
slicePartitions: options.slicePartitions,
vertexFormat: options.vertexFormat
};
this._ellipsoidGeometry = new EllipsoidGeometry_default(ellipsoidOptions);
this._workerName = "createSphereGeometry";
}
SphereGeometry.packedLength = EllipsoidGeometry_default.packedLength;
SphereGeometry.pack = function(value, array, startingIndex) {
Check_default.typeOf.object("value", value);
return EllipsoidGeometry_default.pack(value._ellipsoidGeometry, array, startingIndex);
};
var scratchEllipsoidGeometry2 = new EllipsoidGeometry_default();
var scratchOptions24 = {
radius: void 0,
radii: new Cartesian3_default(),
vertexFormat: new VertexFormat_default(),
stackPartitions: void 0,
slicePartitions: void 0
};
SphereGeometry.unpack = function(array, startingIndex, result) {
const ellipsoidGeometry = EllipsoidGeometry_default.unpack(
array,
startingIndex,
scratchEllipsoidGeometry2
);
scratchOptions24.vertexFormat = VertexFormat_default.clone(
ellipsoidGeometry._vertexFormat,
scratchOptions24.vertexFormat
);
scratchOptions24.stackPartitions = ellipsoidGeometry._stackPartitions;
scratchOptions24.slicePartitions = ellipsoidGeometry._slicePartitions;
if (!defined_default(result)) {
scratchOptions24.radius = ellipsoidGeometry._radii.x;
return new SphereGeometry(scratchOptions24);
}
Cartesian3_default.clone(ellipsoidGeometry._radii, scratchOptions24.radii);
result._ellipsoidGeometry = new EllipsoidGeometry_default(scratchOptions24);
return result;
};
SphereGeometry.createGeometry = function(sphereGeometry) {
return EllipsoidGeometry_default.createGeometry(sphereGeometry._ellipsoidGeometry);
};
var SphereGeometry_default = SphereGeometry;
// packages/engine/Source/Core/TilingScheme.js
var import_InlineWorkers1219 = __toESM(require_InlineWorkers(), 1);
function TilingScheme(options) {
throw new DeveloperError_default(
"This type should not be instantiated directly. Instead, use WebMercatorTilingScheme or GeographicTilingScheme."
);
}
Object.defineProperties(TilingScheme.prototype, {
/**
* Gets the ellipsoid that is tiled by the tiling scheme.
* @memberof TilingScheme.prototype
* @type {Ellipsoid}
*/
ellipsoid: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the rectangle, in radians, covered by this tiling scheme.
* @memberof TilingScheme.prototype
* @type {Rectangle}
*/
rectangle: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the map projection used by the tiling scheme.
* @memberof TilingScheme.prototype
* @type {MapProjection}
*/
projection: {
get: DeveloperError_default.throwInstantiationError
}
});
TilingScheme.prototype.getNumberOfXTilesAtLevel = DeveloperError_default.throwInstantiationError;
TilingScheme.prototype.getNumberOfYTilesAtLevel = DeveloperError_default.throwInstantiationError;
TilingScheme.prototype.rectangleToNativeRectangle = DeveloperError_default.throwInstantiationError;
TilingScheme.prototype.tileXYToNativeRectangle = DeveloperError_default.throwInstantiationError;
TilingScheme.prototype.tileXYToRectangle = DeveloperError_default.throwInstantiationError;
TilingScheme.prototype.positionToTileXY = DeveloperError_default.throwInstantiationError;
var TilingScheme_default = TilingScheme;
// packages/engine/Source/Core/VRTheWorldTerrainProvider.js
var import_InlineWorkers1220 = __toESM(require_InlineWorkers(), 1);
function DataRectangle(rectangle, maxLevel) {
this.rectangle = rectangle;
this.maxLevel = maxLevel;
}
function TerrainProviderBuilder3(options) {
this.ellipsoid = options.ellipsoid ?? Ellipsoid_default.default;
this.tilingScheme = void 0;
this.heightmapWidth = void 0;
this.heightmapHeight = void 0;
this.levelZeroMaximumGeometricError = void 0;
this.rectangles = [];
}
TerrainProviderBuilder3.prototype.build = function(provider) {
provider._tilingScheme = this.tilingScheme;
provider._heightmapWidth = this.heightmapWidth;
provider._heightmapHeight = this.heightmapHeight;
provider._levelZeroMaximumGeometricError = this.levelZeroMaximumGeometricError;
provider._rectangles = this.rectangles;
};
function metadataSuccess5(terrainProviderBuilder, xml2) {
const srs = xml2.getElementsByTagName("SRS")[0].textContent;
if (srs === "EPSG:4326") {
terrainProviderBuilder.tilingScheme = new GeographicTilingScheme_default({
ellipsoid: terrainProviderBuilder.ellipsoid
});
} else {
throw new RuntimeError_default(`SRS ${srs} is not supported`);
}
const tileFormat = xml2.getElementsByTagName("TileFormat")[0];
terrainProviderBuilder.heightmapWidth = parseInt(
tileFormat.getAttribute("width"),
10
);
terrainProviderBuilder.heightmapHeight = parseInt(
tileFormat.getAttribute("height"),
10
);
terrainProviderBuilder.levelZeroMaximumGeometricError = TerrainProvider_default.getEstimatedLevelZeroGeometricErrorForAHeightmap(
terrainProviderBuilder.ellipsoid,
Math.min(
terrainProviderBuilder.heightmapWidth,
terrainProviderBuilder.heightmapHeight
),
terrainProviderBuilder.tilingScheme.getNumberOfXTilesAtLevel(0)
);
const dataRectangles = xml2.getElementsByTagName("DataExtent");
for (let i = 0; i < dataRectangles.length; ++i) {
const dataRectangle = dataRectangles[i];
const west = Math_default.toRadians(
parseFloat(dataRectangle.getAttribute("minx"))
);
const south = Math_default.toRadians(
parseFloat(dataRectangle.getAttribute("miny"))
);
const east = Math_default.toRadians(
parseFloat(dataRectangle.getAttribute("maxx"))
);
const north = Math_default.toRadians(
parseFloat(dataRectangle.getAttribute("maxy"))
);
const maxLevel = parseInt(dataRectangle.getAttribute("maxlevel"), 10);
terrainProviderBuilder.rectangles.push(
new DataRectangle(new Rectangle_default(west, south, east, north), maxLevel)
);
}
}
function metadataFailure4(resource, error, provider) {
let message = `An error occurred while accessing ${resource.url}`;
if (defined_default(error) && defined_default(error.message)) {
message = `${message}: ${error.message}`;
}
TileProviderError_default.reportError(
void 0,
provider,
defined_default(provider) ? provider._errorEvent : void 0,
message
);
throw new RuntimeError_default(message);
}
async function requestMetadata5(terrainProviderBuilder, resource, provider) {
try {
const xml2 = await resource.fetchXML();
metadataSuccess5(terrainProviderBuilder, xml2);
} catch (error) {
metadataFailure4(resource, error, provider);
}
}
function VRTheWorldTerrainProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._errorEvent = new Event_default();
this._terrainDataStructure = {
heightScale: 1 / 1e3,
heightOffset: -1e3,
elementsPerHeight: 3,
stride: 4,
elementMultiplier: 256,
isBigEndian: true,
lowestEncodedHeight: 0,
highestEncodedHeight: 256 * 256 * 256 - 1
};
let credit = options.credit;
if (typeof credit === "string") {
credit = new Credit_default(credit);
}
this._credit = credit;
this._tilingScheme = void 0;
this._rectangles = [];
}
Object.defineProperties(VRTheWorldTerrainProvider.prototype, {
/**
* Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof VRTheWorldTerrainProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets the credit to display when this terrain provider is active. Typically this is used to credit
* the source of the terrain.
* @memberof VRTheWorldTerrainProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return this._credit;
}
},
/**
* Gets the tiling scheme used by this provider.
* @memberof VRTheWorldTerrainProvider.prototype
* @type {GeographicTilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._tilingScheme;
}
},
/**
* Gets a value indicating whether or not the provider includes a water mask. The water mask
* indicates which areas of the globe are water rather than land, so they can be rendered
* as a reflective surface with animated waves.
* @memberof VRTheWorldTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasWaterMask: {
get: function() {
return false;
}
},
/**
* Gets a value indicating whether or not the requested tiles include vertex normals.
* @memberof VRTheWorldTerrainProvider.prototype
* @type {boolean}
* @readonly
*/
hasVertexNormals: {
get: function() {
return false;
}
},
/**
* Gets an object that can be used to determine availability of terrain from this provider, such as
* at points and in rectangles. This property may be undefined if availability
* information is not available.
* @memberof VRTheWorldTerrainProvider.prototype
* @type {TileAvailability|undefined}
* @readonly
*/
availability: {
get: function() {
return void 0;
}
}
});
VRTheWorldTerrainProvider.fromUrl = async function(url2, options) {
Check_default.defined("url", url2);
options = options ?? Frozen_default.EMPTY_OBJECT;
const terrainProviderBuilder = new TerrainProviderBuilder3(options);
const resource = Resource_default.createIfNeeded(url2);
await requestMetadata5(terrainProviderBuilder, resource);
const provider = new VRTheWorldTerrainProvider(options);
terrainProviderBuilder.build(provider);
provider._resource = resource;
return provider;
};
VRTheWorldTerrainProvider.prototype.requestTileGeometry = function(x, y, level, request) {
const yTiles = this._tilingScheme.getNumberOfYTilesAtLevel(level);
const resource = this._resource.getDerivedResource({
url: `${level}/${x}/${yTiles - y - 1}.tif`,
queryParameters: {
cesium: true
},
request
});
const promise = resource.fetchImage({
preferImageBitmap: true
});
if (!defined_default(promise)) {
return void 0;
}
const that = this;
return Promise.resolve(promise).then(function(image) {
return new HeightmapTerrainData_default({
buffer: getImagePixels_default(image),
width: that._heightmapWidth,
height: that._heightmapHeight,
childTileMask: getChildMask(that, x, y, level),
structure: that._terrainDataStructure
});
});
};
VRTheWorldTerrainProvider.prototype.getLevelMaximumGeometricError = function(level) {
return this._levelZeroMaximumGeometricError / (1 << level);
};
var rectangleScratch7 = new Rectangle_default();
function getChildMask(provider, x, y, level) {
const tilingScheme2 = provider._tilingScheme;
const rectangles = provider._rectangles;
const parentRectangle = tilingScheme2.tileXYToRectangle(x, y, level);
let childMask = 0;
for (let i = 0; i < rectangles.length && childMask !== 15; ++i) {
const rectangle = rectangles[i];
if (rectangle.maxLevel <= level) {
continue;
}
const testRectangle = rectangle.rectangle;
const intersection = Rectangle_default.intersection(
testRectangle,
parentRectangle,
rectangleScratch7
);
if (defined_default(intersection)) {
if (isTileInRectangle(tilingScheme2, testRectangle, x * 2, y * 2, level + 1)) {
childMask |= 4;
}
if (isTileInRectangle(
tilingScheme2,
testRectangle,
x * 2 + 1,
y * 2,
level + 1
)) {
childMask |= 8;
}
if (isTileInRectangle(
tilingScheme2,
testRectangle,
x * 2,
y * 2 + 1,
level + 1
)) {
childMask |= 1;
}
if (isTileInRectangle(
tilingScheme2,
testRectangle,
x * 2 + 1,
y * 2 + 1,
level + 1
)) {
childMask |= 2;
}
}
}
return childMask;
}
function isTileInRectangle(tilingScheme2, rectangle, x, y, level) {
const tileRectangle = tilingScheme2.tileXYToRectangle(x, y, level);
return defined_default(
Rectangle_default.intersection(tileRectangle, rectangle, rectangleScratch7)
);
}
VRTheWorldTerrainProvider.prototype.getTileDataAvailable = function(x, y, level) {
return void 0;
};
VRTheWorldTerrainProvider.prototype.loadTileDataAvailability = function(x, y, level) {
return void 0;
};
var VRTheWorldTerrainProvider_default = VRTheWorldTerrainProvider;
// packages/engine/Source/Core/VideoSynchronizer.js
var import_InlineWorkers1221 = __toESM(require_InlineWorkers(), 1);
function VideoSynchronizer(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._clock = void 0;
this._element = void 0;
this._clockSubscription = void 0;
this._seekFunction = void 0;
this._lastPlaybackRate = void 0;
this.clock = options.clock;
this.element = options.element;
this.epoch = options.epoch ?? Iso8601_default.MINIMUM_VALUE;
this.tolerance = options.tolerance ?? 1;
this._seeking = false;
this._seekFunction = void 0;
this._firstTickAfterSeek = false;
}
Object.defineProperties(VideoSynchronizer.prototype, {
/**
* Gets or sets the clock used to drive the video element.
*
* @memberof VideoSynchronizer.prototype
* @type {Clock}
*/
clock: {
get: function() {
return this._clock;
},
set: function(value) {
const oldValue2 = this._clock;
if (oldValue2 === value) {
return;
}
if (defined_default(oldValue2)) {
this._clockSubscription();
this._clockSubscription = void 0;
}
if (defined_default(value)) {
this._clockSubscription = value.onTick.addEventListener(
VideoSynchronizer.prototype._onTick,
this
);
}
this._clock = value;
}
},
/**
* Gets or sets the video element to synchronize.
*
* @memberof VideoSynchronizer.prototype
* @type {HTMLVideoElement}
*/
element: {
get: function() {
return this._element;
},
set: function(value) {
const oldValue2 = this._element;
if (oldValue2 === value) {
return;
}
if (defined_default(oldValue2)) {
oldValue2.removeEventListener("seeked", this._seekFunction, false);
}
if (defined_default(value)) {
this._seeking = false;
this._seekFunction = createSeekFunction(this);
value.addEventListener("seeked", this._seekFunction, false);
}
this._element = value;
this._seeking = false;
this._firstTickAfterSeek = false;
}
}
});
VideoSynchronizer.prototype.destroy = function() {
this.element = void 0;
this.clock = void 0;
return destroyObject_default(this);
};
VideoSynchronizer.prototype.isDestroyed = function() {
return false;
};
VideoSynchronizer.prototype._trySetPlaybackRate = function(clock) {
if (this._lastPlaybackRate === clock.multiplier) {
return;
}
const element = this._element;
try {
element.playbackRate = clock.multiplier;
} catch (error) {
element.playbackRate = 0;
}
this._lastPlaybackRate = clock.multiplier;
};
VideoSynchronizer.prototype._onTick = function(clock) {
const element = this._element;
if (!defined_default(element) || element.readyState < 2) {
return;
}
const paused = element.paused;
const shouldAnimate = clock.shouldAnimate;
if (shouldAnimate === paused) {
if (shouldAnimate) {
element.play();
} else {
element.pause();
}
}
if (this._seeking || this._firstTickAfterSeek) {
this._firstTickAfterSeek = false;
return;
}
this._trySetPlaybackRate(clock);
const clockTime = clock.currentTime;
const epoch2 = this.epoch ?? Iso8601_default.MINIMUM_VALUE;
let videoTime = JulianDate_default.secondsDifference(clockTime, epoch2);
const duration = element.duration;
let desiredTime;
const currentTime = element.currentTime;
if (element.loop) {
videoTime = videoTime % duration;
if (videoTime < 0) {
videoTime = duration - videoTime;
}
desiredTime = videoTime;
} else if (videoTime > duration) {
desiredTime = duration;
} else if (videoTime < 0) {
desiredTime = 0;
} else {
desiredTime = videoTime;
}
const tolerance = shouldAnimate ? this.tolerance ?? 1 : 1e-3;
if (Math.abs(desiredTime - currentTime) > tolerance) {
this._seeking = true;
element.currentTime = desiredTime;
}
};
function createSeekFunction(that) {
return function() {
that._seeking = false;
that._firstTickAfterSeek = true;
};
}
var VideoSynchronizer_default = VideoSynchronizer;
// packages/engine/Source/Core/VulkanConstants.js
var import_InlineWorkers1222 = __toESM(require_InlineWorkers(), 1);
var VulkanConstants = {
VK_FORMAT_UNDEFINED: 0,
VK_FORMAT_R4G4_UNORM_PACK8: 1,
VK_FORMAT_R4G4B4A4_UNORM_PACK16: 2,
VK_FORMAT_B4G4R4A4_UNORM_PACK16: 3,
VK_FORMAT_R5G6B5_UNORM_PACK16: 4,
VK_FORMAT_B5G6R5_UNORM_PACK16: 5,
VK_FORMAT_R5G5B5A1_UNORM_PACK16: 6,
VK_FORMAT_B5G5R5A1_UNORM_PACK16: 7,
VK_FORMAT_A1R5G5B5_UNORM_PACK16: 8,
VK_FORMAT_R8_UNORM: 9,
VK_FORMAT_R8_SNORM: 10,
VK_FORMAT_R8_USCALED: 11,
VK_FORMAT_R8_SSCALED: 12,
VK_FORMAT_R8_UINT: 13,
VK_FORMAT_R8_SINT: 14,
VK_FORMAT_R8_SRGB: 15,
VK_FORMAT_R8G8_UNORM: 16,
VK_FORMAT_R8G8_SNORM: 17,
VK_FORMAT_R8G8_USCALED: 18,
VK_FORMAT_R8G8_SSCALED: 19,
VK_FORMAT_R8G8_UINT: 20,
VK_FORMAT_R8G8_SINT: 21,
VK_FORMAT_R8G8_SRGB: 22,
VK_FORMAT_R8G8B8_UNORM: 23,
VK_FORMAT_R8G8B8_SNORM: 24,
VK_FORMAT_R8G8B8_USCALED: 25,
VK_FORMAT_R8G8B8_SSCALED: 26,
VK_FORMAT_R8G8B8_UINT: 27,
VK_FORMAT_R8G8B8_SINT: 28,
VK_FORMAT_R8G8B8_SRGB: 29,
VK_FORMAT_B8G8R8_UNORM: 30,
VK_FORMAT_B8G8R8_SNORM: 31,
VK_FORMAT_B8G8R8_USCALED: 32,
VK_FORMAT_B8G8R8_SSCALED: 33,
VK_FORMAT_B8G8R8_UINT: 34,
VK_FORMAT_B8G8R8_SINT: 35,
VK_FORMAT_B8G8R8_SRGB: 36,
VK_FORMAT_R8G8B8A8_UNORM: 37,
VK_FORMAT_R8G8B8A8_SNORM: 38,
VK_FORMAT_R8G8B8A8_USCALED: 39,
VK_FORMAT_R8G8B8A8_SSCALED: 40,
VK_FORMAT_R8G8B8A8_UINT: 41,
VK_FORMAT_R8G8B8A8_SINT: 42,
VK_FORMAT_R8G8B8A8_SRGB: 43,
VK_FORMAT_B8G8R8A8_UNORM: 44,
VK_FORMAT_B8G8R8A8_SNORM: 45,
VK_FORMAT_B8G8R8A8_USCALED: 46,
VK_FORMAT_B8G8R8A8_SSCALED: 47,
VK_FORMAT_B8G8R8A8_UINT: 48,
VK_FORMAT_B8G8R8A8_SINT: 49,
VK_FORMAT_B8G8R8A8_SRGB: 50,
VK_FORMAT_A8B8G8R8_UNORM_PACK32: 51,
VK_FORMAT_A8B8G8R8_SNORM_PACK32: 52,
VK_FORMAT_A8B8G8R8_USCALED_PACK32: 53,
VK_FORMAT_A8B8G8R8_SSCALED_PACK32: 54,
VK_FORMAT_A8B8G8R8_UINT_PACK32: 55,
VK_FORMAT_A8B8G8R8_SINT_PACK32: 56,
VK_FORMAT_A8B8G8R8_SRGB_PACK32: 57,
VK_FORMAT_A2R10G10B10_UNORM_PACK32: 58,
VK_FORMAT_A2R10G10B10_SNORM_PACK32: 59,
VK_FORMAT_A2R10G10B10_USCALED_PACK32: 60,
VK_FORMAT_A2R10G10B10_SSCALED_PACK32: 61,
VK_FORMAT_A2R10G10B10_UINT_PACK32: 62,
VK_FORMAT_A2R10G10B10_SINT_PACK32: 63,
VK_FORMAT_A2B10G10R10_UNORM_PACK32: 64,
VK_FORMAT_A2B10G10R10_SNORM_PACK32: 65,
VK_FORMAT_A2B10G10R10_USCALED_PACK32: 66,
VK_FORMAT_A2B10G10R10_SSCALED_PACK32: 67,
VK_FORMAT_A2B10G10R10_UINT_PACK32: 68,
VK_FORMAT_A2B10G10R10_SINT_PACK32: 69,
VK_FORMAT_R16_UNORM: 70,
VK_FORMAT_R16_SNORM: 71,
VK_FORMAT_R16_USCALED: 72,
VK_FORMAT_R16_SSCALED: 73,
VK_FORMAT_R16_UINT: 74,
VK_FORMAT_R16_SINT: 75,
VK_FORMAT_R16_SFLOAT: 76,
VK_FORMAT_R16G16_UNORM: 77,
VK_FORMAT_R16G16_SNORM: 78,
VK_FORMAT_R16G16_USCALED: 79,
VK_FORMAT_R16G16_SSCALED: 80,
VK_FORMAT_R16G16_UINT: 81,
VK_FORMAT_R16G16_SINT: 82,
VK_FORMAT_R16G16_SFLOAT: 83,
VK_FORMAT_R16G16B16_UNORM: 84,
VK_FORMAT_R16G16B16_SNORM: 85,
VK_FORMAT_R16G16B16_USCALED: 86,
VK_FORMAT_R16G16B16_SSCALED: 87,
VK_FORMAT_R16G16B16_UINT: 88,
VK_FORMAT_R16G16B16_SINT: 89,
VK_FORMAT_R16G16B16_SFLOAT: 90,
VK_FORMAT_R16G16B16A16_UNORM: 91,
VK_FORMAT_R16G16B16A16_SNORM: 92,
VK_FORMAT_R16G16B16A16_USCALED: 93,
VK_FORMAT_R16G16B16A16_SSCALED: 94,
VK_FORMAT_R16G16B16A16_UINT: 95,
VK_FORMAT_R16G16B16A16_SINT: 96,
VK_FORMAT_R16G16B16A16_SFLOAT: 97,
VK_FORMAT_R32_UINT: 98,
VK_FORMAT_R32_SINT: 99,
VK_FORMAT_R32_SFLOAT: 100,
VK_FORMAT_R32G32_UINT: 101,
VK_FORMAT_R32G32_SINT: 102,
VK_FORMAT_R32G32_SFLOAT: 103,
VK_FORMAT_R32G32B32_UINT: 104,
VK_FORMAT_R32G32B32_SINT: 105,
VK_FORMAT_R32G32B32_SFLOAT: 106,
VK_FORMAT_R32G32B32A32_UINT: 107,
VK_FORMAT_R32G32B32A32_SINT: 108,
VK_FORMAT_R32G32B32A32_SFLOAT: 109,
VK_FORMAT_R64_UINT: 110,
VK_FORMAT_R64_SINT: 111,
VK_FORMAT_R64_SFLOAT: 112,
VK_FORMAT_R64G64_UINT: 113,
VK_FORMAT_R64G64_SINT: 114,
VK_FORMAT_R64G64_SFLOAT: 115,
VK_FORMAT_R64G64B64_UINT: 116,
VK_FORMAT_R64G64B64_SINT: 117,
VK_FORMAT_R64G64B64_SFLOAT: 118,
VK_FORMAT_R64G64B64A64_UINT: 119,
VK_FORMAT_R64G64B64A64_SINT: 120,
VK_FORMAT_R64G64B64A64_SFLOAT: 121,
VK_FORMAT_B10G11R11_UFLOAT_PACK32: 122,
VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: 123,
VK_FORMAT_D16_UNORM: 124,
VK_FORMAT_X8_D24_UNORM_PACK32: 125,
VK_FORMAT_D32_SFLOAT: 126,
VK_FORMAT_S8_UINT: 127,
VK_FORMAT_D16_UNORM_S8_UINT: 128,
VK_FORMAT_D24_UNORM_S8_UINT: 129,
VK_FORMAT_D32_SFLOAT_S8_UINT: 130,
VK_FORMAT_BC1_RGB_UNORM_BLOCK: 131,
VK_FORMAT_BC1_RGB_SRGB_BLOCK: 132,
VK_FORMAT_BC1_RGBA_UNORM_BLOCK: 133,
VK_FORMAT_BC1_RGBA_SRGB_BLOCK: 134,
VK_FORMAT_BC2_UNORM_BLOCK: 135,
VK_FORMAT_BC2_SRGB_BLOCK: 136,
VK_FORMAT_BC3_UNORM_BLOCK: 137,
VK_FORMAT_BC3_SRGB_BLOCK: 138,
VK_FORMAT_BC4_UNORM_BLOCK: 139,
VK_FORMAT_BC4_SNORM_BLOCK: 140,
VK_FORMAT_BC5_UNORM_BLOCK: 141,
VK_FORMAT_BC5_SNORM_BLOCK: 142,
VK_FORMAT_BC6H_UFLOAT_BLOCK: 143,
VK_FORMAT_BC6H_SFLOAT_BLOCK: 144,
VK_FORMAT_BC7_UNORM_BLOCK: 145,
VK_FORMAT_BC7_SRGB_BLOCK: 146,
VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: 147,
VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: 148,
VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: 149,
VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: 150,
VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: 151,
VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: 152,
VK_FORMAT_EAC_R11_UNORM_BLOCK: 153,
VK_FORMAT_EAC_R11_SNORM_BLOCK: 154,
VK_FORMAT_EAC_R11G11_UNORM_BLOCK: 155,
VK_FORMAT_EAC_R11G11_SNORM_BLOCK: 156,
VK_FORMAT_ASTC_4x4_UNORM_BLOCK: 157,
VK_FORMAT_ASTC_4x4_SRGB_BLOCK: 158,
VK_FORMAT_ASTC_5x4_UNORM_BLOCK: 159,
VK_FORMAT_ASTC_5x4_SRGB_BLOCK: 160,
VK_FORMAT_ASTC_5x5_UNORM_BLOCK: 161,
VK_FORMAT_ASTC_5x5_SRGB_BLOCK: 162,
VK_FORMAT_ASTC_6x5_UNORM_BLOCK: 163,
VK_FORMAT_ASTC_6x5_SRGB_BLOCK: 164,
VK_FORMAT_ASTC_6x6_UNORM_BLOCK: 165,
VK_FORMAT_ASTC_6x6_SRGB_BLOCK: 166,
VK_FORMAT_ASTC_8x5_UNORM_BLOCK: 167,
VK_FORMAT_ASTC_8x5_SRGB_BLOCK: 168,
VK_FORMAT_ASTC_8x6_UNORM_BLOCK: 169,
VK_FORMAT_ASTC_8x6_SRGB_BLOCK: 170,
VK_FORMAT_ASTC_8x8_UNORM_BLOCK: 171,
VK_FORMAT_ASTC_8x8_SRGB_BLOCK: 172,
VK_FORMAT_ASTC_10x5_UNORM_BLOCK: 173,
VK_FORMAT_ASTC_10x5_SRGB_BLOCK: 174,
VK_FORMAT_ASTC_10x6_UNORM_BLOCK: 175,
VK_FORMAT_ASTC_10x6_SRGB_BLOCK: 176,
VK_FORMAT_ASTC_10x8_UNORM_BLOCK: 177,
VK_FORMAT_ASTC_10x8_SRGB_BLOCK: 178,
VK_FORMAT_ASTC_10x10_UNORM_BLOCK: 179,
VK_FORMAT_ASTC_10x10_SRGB_BLOCK: 180,
VK_FORMAT_ASTC_12x10_UNORM_BLOCK: 181,
VK_FORMAT_ASTC_12x10_SRGB_BLOCK: 182,
VK_FORMAT_ASTC_12x12_UNORM_BLOCK: 183,
VK_FORMAT_ASTC_12x12_SRGB_BLOCK: 184,
VK_FORMAT_G8B8G8R8_422_UNORM: 1000156e3,
VK_FORMAT_B8G8R8G8_422_UNORM: 1000156001,
VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: 1000156002,
VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: 1000156003,
VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: 1000156004,
VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: 1000156005,
VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: 1000156006,
VK_FORMAT_R10X6_UNORM_PACK16: 1000156007,
VK_FORMAT_R10X6G10X6_UNORM_2PACK16: 1000156008,
VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: 1000156009,
VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: 1000156010,
VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: 1000156011,
VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: 1000156012,
VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: 1000156013,
VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: 1000156014,
VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: 1000156015,
VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: 1000156016,
VK_FORMAT_R12X4_UNORM_PACK16: 1000156017,
VK_FORMAT_R12X4G12X4_UNORM_2PACK16: 1000156018,
VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16: 1000156019,
VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: 1000156020,
VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: 1000156021,
VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: 1000156022,
VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: 1000156023,
VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: 1000156024,
VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: 1000156025,
VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16: 1000156026,
VK_FORMAT_G16B16G16R16_422_UNORM: 1000156027,
VK_FORMAT_B16G16R16G16_422_UNORM: 1000156028,
VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: 1000156029,
VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: 1000156030,
VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: 1000156031,
VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: 1000156032,
VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: 1000156033,
VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: 1000054e3,
VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: 1000054001,
VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: 1000054002,
VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: 1000054003,
VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: 1000054004,
VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: 1000054005,
VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: 1000054006,
VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: 1000054007,
VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT: 1000066e3,
VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT: 1000066001,
VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT: 1000066002,
VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT: 1000066003,
VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT: 1000066004,
VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT: 1000066005,
VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT: 1000066006,
VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT: 1000066007,
VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT: 1000066008,
VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT: 1000066009,
VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT: 1000066010,
VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT: 1000066011,
VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT: 1000066012,
VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT: 1000066013,
VK_FORMAT_G8B8G8R8_422_UNORM_KHR: 1000156e3,
VK_FORMAT_B8G8R8G8_422_UNORM_KHR: 1000156001,
VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR: 1000156002,
VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR: 1000156003,
VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR: 1000156004,
VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR: 1000156005,
VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR: 1000156006,
VK_FORMAT_R10X6_UNORM_PACK16_KHR: 1000156007,
VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR: 1000156008,
VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR: 1000156009,
VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR: 1000156010,
VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR: 1000156011,
VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR: 1000156012,
VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR: 1000156013,
VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR: 1000156014,
VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR: 1000156015,
VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR: 1000156016,
VK_FORMAT_R12X4_UNORM_PACK16_KHR: 1000156017,
VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR: 1000156018,
VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR: 1000156019,
VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR: 1000156020,
VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR: 1000156021,
VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR: 1000156022,
VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR: 1000156023,
VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR: 1000156024,
VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR: 1000156025,
VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR: 1000156026,
VK_FORMAT_G16B16G16R16_422_UNORM_KHR: 1000156027,
VK_FORMAT_B16G16R16G16_422_UNORM_KHR: 1000156028,
VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR: 1000156029,
VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR: 1000156030,
VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR: 1000156031,
VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR: 1000156032,
VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR: 1000156033
};
var VulkanConstants_default = Object.freeze(VulkanConstants);
// packages/engine/Source/Core/createWorldBathymetryAsync.js
var import_InlineWorkers1223 = __toESM(require_InlineWorkers(), 1);
function createWorldBathymetryAsync(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
return CesiumTerrainProvider_default.fromIonAssetId(2426648, {
requestVertexNormals: options.requestVertexNormals ?? false
});
}
var createWorldBathymetryAsync_default = createWorldBathymetryAsync;
// packages/engine/Source/Core/createWorldTerrainAsync.js
var import_InlineWorkers1224 = __toESM(require_InlineWorkers(), 1);
function createWorldTerrainAsync(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
return CesiumTerrainProvider_default.fromIonAssetId(1, {
requestVertexNormals: options.requestVertexNormals ?? false,
requestWaterMask: options.requestWaterMask ?? false,
ellipsoid: Ellipsoid_default.WGS84
});
}
var createWorldTerrainAsync_default = createWorldTerrainAsync;
// packages/engine/Source/Core/decodeGoogleEarthEnterpriseData.js
var import_InlineWorkers1225 = __toESM(require_InlineWorkers(), 1);
var compressedMagic = 1953029805;
var compressedMagicSwap = 2917034100;
function decodeGoogleEarthEnterpriseData(key, data) {
if (decodeGoogleEarthEnterpriseData.passThroughDataForTesting) {
return data;
}
Check_default.typeOf.object("key", key);
Check_default.typeOf.object("data", data);
const keyLength = key.byteLength;
if (keyLength === 0 || keyLength % 4 !== 0) {
throw new RuntimeError_default(
"The length of key must be greater than 0 and a multiple of 4."
);
}
const dataView = new DataView(data);
const magic = dataView.getUint32(0, true);
if (magic === compressedMagic || magic === compressedMagicSwap) {
return data;
}
const keyView = new DataView(key);
let dp = 0;
const dpend = data.byteLength;
const dpend64 = dpend - dpend % 8;
const kpend = keyLength;
let kp;
let off = 8;
while (dp < dpend64) {
off = (off + 8) % 24;
kp = off;
while (dp < dpend64 && kp < kpend) {
dataView.setUint32(
dp,
dataView.getUint32(dp, true) ^ keyView.getUint32(kp, true),
true
);
dataView.setUint32(
dp + 4,
dataView.getUint32(dp + 4, true) ^ keyView.getUint32(kp + 4, true),
true
);
dp += 8;
kp += 24;
}
}
if (dp < dpend) {
if (kp >= kpend) {
off = (off + 8) % 24;
kp = off;
}
while (dp < dpend) {
dataView.setUint8(dp, dataView.getUint8(dp) ^ keyView.getUint8(kp));
dp++;
kp++;
}
}
}
decodeGoogleEarthEnterpriseData.passThroughDataForTesting = false;
var decodeGoogleEarthEnterpriseData_default = decodeGoogleEarthEnterpriseData;
// packages/engine/Source/Core/defaultValue.js
var import_InlineWorkers1226 = __toESM(require_InlineWorkers(), 1);
function defaultValue(a3, b) {
deprecationWarning_default(
"defaultValue",
`defaultValue has been deprecated and will be removed in Cesium 1.134. Use the nullish coalescing operator instead: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing`
);
if (a3 !== void 0 && a3 !== null) {
return a3;
}
return b;
}
Object.defineProperty(defaultValue, "EMPTY_OBJECT", {
get: function() {
deprecationWarning_default(
"defaultValue.EMPTY_OBJECT",
"defaultValue.EMPTY_OBJECT has been deprecated and will be removed in Cesium 1.134. Use Frozen.EMPTY_OBJECT instead"
);
return Frozen_default.EMPTY_OBJECT;
}
});
var defaultValue_default = defaultValue;
// packages/engine/Source/Core/pointInsideTriangle.js
var import_InlineWorkers1227 = __toESM(require_InlineWorkers(), 1);
var scratchBarycentricCoords = new Cartesian3_default();
function pointInsideTriangle(point, p0, p1, p2) {
const coords = barycentricCoordinates_default(
point,
p0,
p1,
p2,
scratchBarycentricCoords
);
if (!defined_default(coords)) {
return false;
}
return coords.x > 0 && coords.y > 0 && coords.z > 0;
}
var pointInsideTriangle_default = pointInsideTriangle;
// packages/engine/Source/Core/srgbToLinear.js
var import_InlineWorkers1228 = __toESM(require_InlineWorkers(), 1);
function srgbToLinear2(value) {
Check_default.defined("value", value);
if (value <= 0.04045) {
return value * 0.07739938080495357;
}
return Math.pow(
// eslint-disable-next-line no-loss-of-precision
(value + 0.055) * 0.9478672985781991,
2.4
);
}
var srgbToLinear_default2 = srgbToLinear2;
// packages/engine/Source/Core/webGLConstantToGlslType.js
var import_InlineWorkers1229 = __toESM(require_InlineWorkers(), 1);
function webGLConstantToGlslType(webGLValue) {
switch (webGLValue) {
case WebGLConstants_default.FLOAT:
return "float";
case WebGLConstants_default.FLOAT_VEC2:
return "vec2";
case WebGLConstants_default.FLOAT_VEC3:
return "vec3";
case WebGLConstants_default.FLOAT_VEC4:
return "vec4";
case WebGLConstants_default.FLOAT_MAT2:
return "mat2";
case WebGLConstants_default.FLOAT_MAT3:
return "mat3";
case WebGLConstants_default.FLOAT_MAT4:
return "mat4";
case WebGLConstants_default.SAMPLER_2D:
return "sampler2D";
case WebGLConstants_default.BOOL:
return "bool";
}
}
var webGLConstantToGlslType_default = webGLConstantToGlslType;
// packages/engine/Source/Core/wrapFunction.js
var import_InlineWorkers1230 = __toESM(require_InlineWorkers(), 1);
function wrapFunction(obj, oldFunction, newFunction) {
if (typeof oldFunction !== "function") {
throw new DeveloperError_default("oldFunction is required to be a function.");
}
if (typeof newFunction !== "function") {
throw new DeveloperError_default("oldFunction is required to be a function.");
}
return function() {
newFunction.apply(obj, arguments);
oldFunction.apply(obj, arguments);
};
}
var wrapFunction_default = wrapFunction;
// packages/engine/Source/Scene/BoxEmitter.js
var import_InlineWorkers1231 = __toESM(require_InlineWorkers(), 1);
var defaultDimensions = new Cartesian3_default(1, 1, 1);
function BoxEmitter(dimensions) {
dimensions = dimensions ?? defaultDimensions;
Check_default.defined("dimensions", dimensions);
Check_default.typeOf.number.greaterThanOrEquals("dimensions.x", dimensions.x, 0);
Check_default.typeOf.number.greaterThanOrEquals("dimensions.y", dimensions.y, 0);
Check_default.typeOf.number.greaterThanOrEquals("dimensions.z", dimensions.z, 0);
this._dimensions = Cartesian3_default.clone(dimensions);
}
Object.defineProperties(BoxEmitter.prototype, {
/**
* The width, height and depth dimensions of the box in meters.
* @memberof BoxEmitter.prototype
* @type {Cartesian3}
* @default new Cartesian3(1.0, 1.0, 1.0)
*/
dimensions: {
get: function() {
return this._dimensions;
},
set: function(value) {
Check_default.defined("value", value);
Check_default.typeOf.number.greaterThanOrEquals("value.x", value.x, 0);
Check_default.typeOf.number.greaterThanOrEquals("value.y", value.y, 0);
Check_default.typeOf.number.greaterThanOrEquals("value.z", value.z, 0);
Cartesian3_default.clone(value, this._dimensions);
}
}
});
var scratchHalfDim = new Cartesian3_default();
BoxEmitter.prototype.emit = function(particle) {
const dim = this._dimensions;
const halfDim = Cartesian3_default.multiplyByScalar(dim, 0.5, scratchHalfDim);
const x = Math_default.randomBetween(-halfDim.x, halfDim.x);
const y = Math_default.randomBetween(-halfDim.y, halfDim.y);
const z = Math_default.randomBetween(-halfDim.z, halfDim.z);
particle.position = Cartesian3_default.fromElements(x, y, z, particle.position);
particle.velocity = Cartesian3_default.normalize(
particle.position,
particle.velocity
);
};
var BoxEmitter_default = BoxEmitter;
// packages/engine/Source/Scene/Cesium3DTileContent.js
var import_InlineWorkers1232 = __toESM(require_InlineWorkers(), 1);
function Cesium3DTileContent() {
this.featurePropertiesDirty = false;
}
Object.defineProperties(Cesium3DTileContent.prototype, {
/**
* Gets the number of features in the tile.
*
* @memberof Cesium3DTileContent.prototype
*
* @type {number}
* @readonly
*/
featuresLength: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the number of points in the tile.
*
* Only applicable for tiles with Point Cloud content. This is different than {@link Cesium3DTileContent#featuresLength} which
* equals the number of groups of points as distinguished by the BATCH_ID feature table semantic.
*
*
* @see {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification/TileFormats/PointCloud#batched-points}
*
* @memberof Cesium3DTileContent.prototype
*
* @type {number}
* @readonly
*/
pointsLength: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the number of triangles in the tile.
*
* @memberof Cesium3DTileContent.prototype
*
* @type {number}
* @readonly
*/
trianglesLength: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the tile's geometry memory in bytes.
*
* @memberof Cesium3DTileContent.prototype
*
* @type {number}
* @readonly
*/
geometryByteLength: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the tile's texture memory in bytes.
*
* @memberof Cesium3DTileContent.prototype
*
* @type {number}
* @readonly
*/
texturesByteLength: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the amount of memory used by the batch table textures and any binary
* metadata properties not accounted for in geometryByteLength or
* texturesByteLength
*
* @memberof Cesium3DTileContent.prototype
*
* @type {number}
* @readonly
*/
batchTableByteLength: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the array of {@link Cesium3DTileContent} objects for contents that contain other contents, such as composite tiles. The inner contents may in turn have inner contents, such as a composite tile that contains a composite tile.
*
* @see {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification/TileFormats/Composite|Composite specification}
*
* @memberof Cesium3DTileContent.prototype
*
* @type {Array}
* @readonly
*/
innerContents: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Returns true when the tile's content is ready to render; otherwise false
*
* @memberof Cesium3DTileContent.prototype
*
* @type {boolean}
* @readonly
*/
ready: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the tileset for this tile.
*
* @memberof Cesium3DTileContent.prototype
*
* @type {Cesium3DTileset}
* @readonly
*/
tileset: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the tile containing this content.
*
* @memberof Cesium3DTileContent.prototype
*
* @type {Cesium3DTile}
* @readonly
*/
tile: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the url of the tile's content.
* @memberof Cesium3DTileContent.prototype
*
* @type {string}
* @readonly
*/
url: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the batch table for this content.
*
* This is used to implement the Cesium3DTileContent interface, but is
* not part of the public Cesium API.
*
*
* @type {Cesium3DTileBatchTable}
* @readonly
*
* @private
*/
batchTable: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the metadata for this content, whether it is available explicitly or via
* implicit tiling. If there is no metadata, this property should be undefined.
*
* This is used to implement the Cesium3DTileContent interface, but is
* not part of the public Cesium API.
*
*
* @type {ImplicitMetadataView|undefined}
*
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
metadata: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
},
set: function(value) {
DeveloperError_default.throwInstantiationError();
}
},
/**
* Gets the group for this content if the content has metadata (3D Tiles 1.1) or
* if it uses the 3DTILES_metadata extension. If neither are present,
* this property should be undefined.
*
* This is used to implement the Cesium3DTileContent interface, but is
* not part of the public Cesium API.
*
*
* @type {Cesium3DTileContentGroup|undefined}
*
* @private
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
group: {
// eslint-disable-next-line getter-return
get: function() {
DeveloperError_default.throwInstantiationError();
},
set: function(value) {
DeveloperError_default.throwInstantiationError();
}
}
});
Cesium3DTileContent.prototype.hasProperty = function(batchId, name) {
DeveloperError_default.throwInstantiationError();
};
Cesium3DTileContent.prototype.getFeature = function(batchId) {
DeveloperError_default.throwInstantiationError();
};
Cesium3DTileContent.prototype.applyDebugSettings = function(enabled, color) {
DeveloperError_default.throwInstantiationError();
};
Cesium3DTileContent.prototype.applyStyle = function(style) {
DeveloperError_default.throwInstantiationError();
};
Cesium3DTileContent.prototype.update = function(tileset, frameState) {
DeveloperError_default.throwInstantiationError();
};
Cesium3DTileContent.prototype.pick = function(ray, frameState, result) {
DeveloperError_default.throwInstantiationError();
};
Cesium3DTileContent.prototype.isDestroyed = function() {
DeveloperError_default.throwInstantiationError();
};
Cesium3DTileContent.prototype.destroy = function() {
DeveloperError_default.throwInstantiationError();
};
var Cesium3DTileContent_default = Cesium3DTileContent;
// packages/engine/Source/Scene/Cesium3DTileStyle.js
var import_InlineWorkers1234 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/ConditionsExpression.js
var import_InlineWorkers1233 = __toESM(require_InlineWorkers(), 1);
function ConditionsExpression(conditionsExpression, defines) {
this._conditionsExpression = clone_default(conditionsExpression, true);
this._conditions = conditionsExpression.conditions;
this._runtimeConditions = void 0;
setRuntime(this, defines);
}
Object.defineProperties(ConditionsExpression.prototype, {
/**
* Gets the conditions expression defined in the 3D Tiles Styling language.
*
* @memberof ConditionsExpression.prototype
*
* @type {object}
* @readonly
*
* @default undefined
*/
conditionsExpression: {
get: function() {
return this._conditionsExpression;
}
}
});
function Statement(condition, expression) {
this.condition = condition;
this.expression = expression;
}
function setRuntime(expression, defines) {
const runtimeConditions = [];
const conditions = expression._conditions;
if (!defined_default(conditions)) {
return;
}
const length2 = conditions.length;
for (let i = 0; i < length2; ++i) {
const statement = conditions[i];
const cond = String(statement[0]);
const condExpression = String(statement[1]);
runtimeConditions.push(
new Statement(
new Expression_default(cond, defines),
new Expression_default(condExpression, defines)
)
);
}
expression._runtimeConditions = runtimeConditions;
}
ConditionsExpression.prototype.evaluate = function(feature2, result) {
const conditions = this._runtimeConditions;
if (!defined_default(conditions)) {
return void 0;
}
const length2 = conditions.length;
for (let i = 0; i < length2; ++i) {
const statement = conditions[i];
if (statement.condition.evaluate(feature2)) {
return statement.expression.evaluate(feature2, result);
}
}
};
ConditionsExpression.prototype.evaluateColor = function(feature2, result) {
const conditions = this._runtimeConditions;
if (!defined_default(conditions)) {
return void 0;
}
const length2 = conditions.length;
for (let i = 0; i < length2; ++i) {
const statement = conditions[i];
if (statement.condition.evaluate(feature2)) {
return statement.expression.evaluateColor(feature2, result);
}
}
};
ConditionsExpression.prototype.getShaderFunction = function(functionSignature, variableSubstitutionMap, shaderState, returnType) {
const conditions = this._runtimeConditions;
if (!defined_default(conditions) || conditions.length === 0) {
return void 0;
}
let shaderFunction = "";
const length2 = conditions.length;
for (let i = 0; i < length2; ++i) {
const statement = conditions[i];
const condition = statement.condition.getShaderExpression(
variableSubstitutionMap,
shaderState
);
const expression = statement.expression.getShaderExpression(
variableSubstitutionMap,
shaderState
);
shaderFunction += ` ${i === 0 ? "if" : "else if"} (${condition})
{
return ${expression};
}
`;
}
shaderFunction = `${returnType} ${functionSignature}
{
${shaderFunction} return ${returnType}(1.0);
}
`;
return shaderFunction;
};
ConditionsExpression.prototype.getVariables = function() {
let variables = [];
const conditions = this._runtimeConditions;
if (!defined_default(conditions) || conditions.length === 0) {
return variables;
}
const length2 = conditions.length;
for (let i = 0; i < length2; ++i) {
const statement = conditions[i];
addAllToArray_default(variables, statement.condition.getVariables());
addAllToArray_default(variables, statement.expression.getVariables());
}
variables = variables.filter(function(variable, index, variables2) {
return variables2.indexOf(variable) === index;
});
return variables;
};
var ConditionsExpression_default = ConditionsExpression;
// packages/engine/Source/Scene/Cesium3DTileStyle.js
function Cesium3DTileStyle(style) {
this._style = {};
this._ready = false;
this._show = void 0;
this._color = void 0;
this._pointSize = void 0;
this._pointOutlineColor = void 0;
this._pointOutlineWidth = void 0;
this._labelColor = void 0;
this._labelOutlineColor = void 0;
this._labelOutlineWidth = void 0;
this._font = void 0;
this._labelStyle = void 0;
this._labelText = void 0;
this._backgroundColor = void 0;
this._backgroundPadding = void 0;
this._backgroundEnabled = void 0;
this._scaleByDistance = void 0;
this._translucencyByDistance = void 0;
this._distanceDisplayCondition = void 0;
this._heightOffset = void 0;
this._anchorLineEnabled = void 0;
this._anchorLineColor = void 0;
this._image = void 0;
this._disableDepthTestDistance = void 0;
this._horizontalOrigin = void 0;
this._verticalOrigin = void 0;
this._labelHorizontalOrigin = void 0;
this._labelVerticalOrigin = void 0;
this._meta = void 0;
this._colorShaderFunction = void 0;
this._showShaderFunction = void 0;
this._pointSizeShaderFunction = void 0;
this._colorShaderFunctionReady = false;
this._showShaderFunctionReady = false;
this._pointSizeShaderFunctionReady = false;
this._colorShaderTranslucent = false;
setup(this, style);
}
function setup(that, styleJson) {
styleJson = clone_default(styleJson, true) ?? that._style;
that._style = styleJson;
that.show = styleJson.show;
that.color = styleJson.color;
that.pointSize = styleJson.pointSize;
that.pointOutlineColor = styleJson.pointOutlineColor;
that.pointOutlineWidth = styleJson.pointOutlineWidth;
that.labelColor = styleJson.labelColor;
that.labelOutlineColor = styleJson.labelOutlineColor;
that.labelOutlineWidth = styleJson.labelOutlineWidth;
that.labelStyle = styleJson.labelStyle;
that.font = styleJson.font;
that.labelText = styleJson.labelText;
that.backgroundColor = styleJson.backgroundColor;
that.backgroundPadding = styleJson.backgroundPadding;
that.backgroundEnabled = styleJson.backgroundEnabled;
that.scaleByDistance = styleJson.scaleByDistance;
that.translucencyByDistance = styleJson.translucencyByDistance;
that.distanceDisplayCondition = styleJson.distanceDisplayCondition;
that.heightOffset = styleJson.heightOffset;
that.anchorLineEnabled = styleJson.anchorLineEnabled;
that.anchorLineColor = styleJson.anchorLineColor;
that.image = styleJson.image;
that.disableDepthTestDistance = styleJson.disableDepthTestDistance;
that.horizontalOrigin = styleJson.horizontalOrigin;
that.verticalOrigin = styleJson.verticalOrigin;
that.labelHorizontalOrigin = styleJson.labelHorizontalOrigin;
that.labelVerticalOrigin = styleJson.labelVerticalOrigin;
const meta = {};
if (defined_default(styleJson.meta)) {
const defines = styleJson.defines;
const metaJson = styleJson.meta ?? Frozen_default.EMPTY_OBJECT;
for (const property in metaJson) {
if (metaJson.hasOwnProperty(property)) {
meta[property] = new Expression_default(metaJson[property], defines);
}
}
}
that._meta = meta;
that._ready = true;
}
function getExpression(tileStyle, value) {
const defines = (tileStyle._style ?? Frozen_default.EMPTY_OBJECT).defines;
if (!defined_default(value)) {
return void 0;
} else if (typeof value === "boolean" || typeof value === "number") {
return new Expression_default(String(value));
} else if (typeof value === "string") {
return new Expression_default(value, defines);
} else if (defined_default(value.conditions)) {
return new ConditionsExpression_default(value, defines);
}
return value;
}
function getJsonFromExpression(expression) {
if (!defined_default(expression)) {
return void 0;
} else if (defined_default(expression.expression)) {
return expression.expression;
} else if (defined_default(expression.conditionsExpression)) {
return clone_default(expression.conditionsExpression, true);
}
return expression;
}
Object.defineProperties(Cesium3DTileStyle.prototype, {
/**
* Gets the object defining the style using the
* {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification/Styling|3D Tiles Styling language}.
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {object}
* @readonly
*
* @default {}
*/
style: {
get: function() {
return this._style;
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's show property. Alternatively a boolean, string, or object defining a show style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return or convert to a Boolean.
*
*
* This expression is applicable to all tile formats.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @example
* const style = new Cesium3DTileStyle({
* show : '(regExp("^Chest").test(${County})) && (${YearBuilt} >= 1970)'
* });
* style.show.evaluate(feature); // returns true or false depending on the feature's properties
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override show expression with a custom function
* style.show = {
* evaluate : function(feature) {
* return true;
* }
* };
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override show expression with a boolean
* style.show = true;
* };
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override show expression with a string
* style.show = '${Height} > 0';
* };
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override show expression with a condition
* style.show = {
* conditions: [
* ['${height} > 2', 'false'],
* ['true', 'true']
* ];
* };
*/
show: {
get: function() {
return this._show;
},
set: function(value) {
this._show = getExpression(this, value);
this._style.show = getJsonFromExpression(this._show);
this._showShaderFunctionReady = false;
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's color property. Alternatively a string or object defining a color style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Color.
*
*
* This expression is applicable to all tile formats.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @example
* const style = new Cesium3DTileStyle({
* color : '(${Temperature} > 90) ? color("red") : color("white")'
* });
* style.color.evaluateColor(feature, result); // returns a Cesium.Color object
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override color expression with a custom function
* style.color = {
* evaluateColor : function(feature, result) {
* return Cesium.Color.clone(Cesium.Color.WHITE, result);
* }
* };
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override color expression with a string
* style.color = 'color("blue")';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override color expression with a condition
* style.color = {
* conditions : [
* ['${height} > 2', 'color("cyan")'],
* ['true', 'color("blue")']
* ]
* };
*/
color: {
get: function() {
return this._color;
},
set: function(value) {
this._color = getExpression(this, value);
this._style.color = getJsonFromExpression(this._color);
this._colorShaderFunctionReady = false;
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's pointSize property. Alternatively a string or object defining a point size style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Number.
*
*
* This expression is only applicable to point features in a Vector tile or a Point Cloud tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @example
* const style = new Cesium3DTileStyle({
* pointSize : '(${Temperature} > 90) ? 2.0 : 1.0'
* });
* style.pointSize.evaluate(feature); // returns a Number
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override pointSize expression with a custom function
* style.pointSize = {
* evaluate : function(feature) {
* return 1.0;
* }
* };
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override pointSize expression with a number
* style.pointSize = 1.0;
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override pointSize expression with a string
* style.pointSize = '${height} / 10';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override pointSize expression with a condition
* style.pointSize = {
* conditions : [
* ['${height} > 2', '1.0'],
* ['true', '2.0']
* ]
* };
*/
pointSize: {
get: function() {
return this._pointSize;
},
set: function(value) {
this._pointSize = getExpression(this, value);
this._style.pointSize = getJsonFromExpression(this._pointSize);
this._pointSizeShaderFunctionReady = false;
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's pointOutlineColor property. Alternatively a string or object defining a color style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Color.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override pointOutlineColor expression with a string
* style.pointOutlineColor = 'color("blue")';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override pointOutlineColor expression with a condition
* style.pointOutlineColor = {
* conditions : [
* ['${height} > 2', 'color("cyan")'],
* ['true', 'color("blue")']
* ]
* };
*/
pointOutlineColor: {
get: function() {
return this._pointOutlineColor;
},
set: function(value) {
this._pointOutlineColor = getExpression(this, value);
this._style.pointOutlineColor = getJsonFromExpression(
this._pointOutlineColor
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's pointOutlineWidth property. Alternatively a string or object defining a number style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Number.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override pointOutlineWidth expression with a string
* style.pointOutlineWidth = '5';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override pointOutlineWidth expression with a condition
* style.pointOutlineWidth = {
* conditions : [
* ['${height} > 2', '5'],
* ['true', '0']
* ]
* };
*/
pointOutlineWidth: {
get: function() {
return this._pointOutlineWidth;
},
set: function(value) {
this._pointOutlineWidth = getExpression(this, value);
this._style.pointOutlineWidth = getJsonFromExpression(
this._pointOutlineWidth
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's labelColor property. Alternatively a string or object defining a color style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Color.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override labelColor expression with a string
* style.labelColor = 'color("blue")';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override labelColor expression with a condition
* style.labelColor = {
* conditions : [
* ['${height} > 2', 'color("cyan")'],
* ['true', 'color("blue")']
* ]
* };
*/
labelColor: {
get: function() {
return this._labelColor;
},
set: function(value) {
this._labelColor = getExpression(this, value);
this._style.labelColor = getJsonFromExpression(this._labelColor);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's labelOutlineColor property. Alternatively a string or object defining a color style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Color.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override labelOutlineColor expression with a string
* style.labelOutlineColor = 'color("blue")';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override labelOutlineColor expression with a condition
* style.labelOutlineColor = {
* conditions : [
* ['${height} > 2', 'color("cyan")'],
* ['true', 'color("blue")']
* ]
* };
*/
labelOutlineColor: {
get: function() {
return this._labelOutlineColor;
},
set: function(value) {
this._labelOutlineColor = getExpression(this, value);
this._style.labelOutlineColor = getJsonFromExpression(
this._labelOutlineColor
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's labelOutlineWidth property. Alternatively a string or object defining a number style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Number.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override labelOutlineWidth expression with a string
* style.labelOutlineWidth = '5';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override labelOutlineWidth expression with a condition
* style.labelOutlineWidth = {
* conditions : [
* ['${height} > 2', '5'],
* ['true', '0']
* ]
* };
*/
labelOutlineWidth: {
get: function() {
return this._labelOutlineWidth;
},
set: function(value) {
this._labelOutlineWidth = getExpression(this, value);
this._style.labelOutlineWidth = getJsonFromExpression(
this._labelOutlineWidth
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's font property. Alternatively a string or object defining a string style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a String.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium3DTileStyle({
* font : '(${Temperature} > 90) ? "30px Helvetica" : "24px Helvetica"'
* });
* style.font.evaluate(feature); // returns a String
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override font expression with a custom function
* style.font = {
* evaluate : function(feature) {
* return '24px Helvetica';
* }
* };
*/
font: {
get: function() {
return this._font;
},
set: function(value) {
this._font = getExpression(this, value);
this._style.font = getJsonFromExpression(this._font);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's label style property. Alternatively a string or object defining a number style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a LabelStyle.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium3DTileStyle({
* labelStyle : `(\${Temperature} > 90) ? ${LabelStyle.FILL_AND_OUTLINE} : ${LabelStyle.FILL}`
* });
* style.labelStyle.evaluate(feature); // returns a LabelStyle
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override labelStyle expression with a custom function
* style.labelStyle = {
* evaluate : function(feature) {
* return LabelStyle.FILL;
* }
* };
*/
labelStyle: {
get: function() {
return this._labelStyle;
},
set: function(value) {
this._labelStyle = getExpression(this, value);
this._style.labelStyle = getJsonFromExpression(this._labelStyle);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's labelText property. Alternatively a string or object defining a string style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a String.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium3DTileStyle({
* labelText : '(${Temperature} > 90) ? ">90" : "<=90"'
* });
* style.labelText.evaluate(feature); // returns a String
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override labelText expression with a custom function
* style.labelText = {
* evaluate : function(feature) {
* return 'Example label text';
* }
* };
*/
labelText: {
get: function() {
return this._labelText;
},
set: function(value) {
this._labelText = getExpression(this, value);
this._style.labelText = getJsonFromExpression(this._labelText);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's backgroundColor property. Alternatively a string or object defining a color style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Color.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override backgroundColor expression with a string
* style.backgroundColor = 'color("blue")';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override backgroundColor expression with a condition
* style.backgroundColor = {
* conditions : [
* ['${height} > 2', 'color("cyan")'],
* ['true', 'color("blue")']
* ]
* };
*/
backgroundColor: {
get: function() {
return this._backgroundColor;
},
set: function(value) {
this._backgroundColor = getExpression(this, value);
this._style.backgroundColor = getJsonFromExpression(
this._backgroundColor
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's backgroundPadding property. Alternatively a string or object defining a vec2 style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Cartesian2.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override backgroundPadding expression with a string
* style.backgroundPadding = 'vec2(5.0, 7.0)';
* style.backgroundPadding.evaluate(feature); // returns a Cartesian2
*/
backgroundPadding: {
get: function() {
return this._backgroundPadding;
},
set: function(value) {
this._backgroundPadding = getExpression(this, value);
this._style.backgroundPadding = getJsonFromExpression(
this._backgroundPadding
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's backgroundEnabled property. Alternatively a string or object defining a boolean style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Boolean.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override backgroundEnabled expression with a string
* style.backgroundEnabled = 'true';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override backgroundEnabled expression with a condition
* style.backgroundEnabled = {
* conditions : [
* ['${height} > 2', 'true'],
* ['true', 'false']
* ]
* };
*/
backgroundEnabled: {
get: function() {
return this._backgroundEnabled;
},
set: function(value) {
this._backgroundEnabled = getExpression(this, value);
this._style.backgroundEnabled = getJsonFromExpression(
this._backgroundEnabled
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's scaleByDistance property. Alternatively a string or object defining a vec4 style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Cartesian4.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override scaleByDistance expression with a string
* style.scaleByDistance = 'vec4(1.5e2, 2.0, 1.5e7, 0.5)';
* style.scaleByDistance.evaluate(feature); // returns a Cartesian4
*/
scaleByDistance: {
get: function() {
return this._scaleByDistance;
},
set: function(value) {
this._scaleByDistance = getExpression(this, value);
this._style.scaleByDistance = getJsonFromExpression(
this._scaleByDistance
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's translucencyByDistance property. Alternatively a string or object defining a vec4 style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Cartesian4.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override translucencyByDistance expression with a string
* style.translucencyByDistance = 'vec4(1.5e2, 1.0, 1.5e7, 0.2)';
* style.translucencyByDistance.evaluate(feature); // returns a Cartesian4
*/
translucencyByDistance: {
get: function() {
return this._translucencyByDistance;
},
set: function(value) {
this._translucencyByDistance = getExpression(this, value);
this._style.translucencyByDistance = getJsonFromExpression(
this._translucencyByDistance
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's distanceDisplayCondition property. Alternatively a string or object defining a vec2 style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Cartesian2.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override distanceDisplayCondition expression with a string
* style.distanceDisplayCondition = 'vec2(0.0, 5.5e6)';
* style.distanceDisplayCondition.evaluate(feature); // returns a Cartesian2
*/
distanceDisplayCondition: {
get: function() {
return this._distanceDisplayCondition;
},
set: function(value) {
this._distanceDisplayCondition = getExpression(this, value);
this._style.distanceDisplayCondition = getJsonFromExpression(
this._distanceDisplayCondition
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's heightOffset property. Alternatively a string or object defining a number style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Number.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override heightOffset expression with a string
* style.heightOffset = '2.0';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override heightOffset expression with a condition
* style.heightOffset = {
* conditions : [
* ['${height} > 2', '4.0'],
* ['true', '2.0']
* ]
* };
*/
heightOffset: {
get: function() {
return this._heightOffset;
},
set: function(value) {
this._heightOffset = getExpression(this, value);
this._style.heightOffset = getJsonFromExpression(this._heightOffset);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's anchorLineEnabled property. Alternatively a string or object defining a boolean style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Boolean.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override anchorLineEnabled expression with a string
* style.anchorLineEnabled = 'true';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override anchorLineEnabled expression with a condition
* style.anchorLineEnabled = {
* conditions : [
* ['${height} > 2', 'true'],
* ['true', 'false']
* ]
* };
*/
anchorLineEnabled: {
get: function() {
return this._anchorLineEnabled;
},
set: function(value) {
this._anchorLineEnabled = getExpression(this, value);
this._style.anchorLineEnabled = getJsonFromExpression(
this._anchorLineEnabled
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's anchorLineColor property. Alternatively a string or object defining a color style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Color.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override anchorLineColor expression with a string
* style.anchorLineColor = 'color("blue")';
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override anchorLineColor expression with a condition
* style.anchorLineColor = {
* conditions : [
* ['${height} > 2', 'color("cyan")'],
* ['true', 'color("blue")']
* ]
* };
*/
anchorLineColor: {
get: function() {
return this._anchorLineColor;
},
set: function(value) {
this._anchorLineColor = getExpression(this, value);
this._style.anchorLineColor = getJsonFromExpression(
this._anchorLineColor
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's image property. Alternatively a string or object defining a string style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a String.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium3DTileStyle({
* image : '(${Temperature} > 90) ? "/url/to/image1" : "/url/to/image2"'
* });
* style.image.evaluate(feature); // returns a String
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override image expression with a custom function
* style.image = {
* evaluate : function(feature) {
* return '/url/to/image';
* }
* };
*/
image: {
get: function() {
return this._image;
},
set: function(value) {
this._image = getExpression(this, value);
this._style.image = getJsonFromExpression(this._image);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's disableDepthTestDistance property. Alternatively a string or object defining a number style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a Number.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override disableDepthTestDistance expression with a string
* style.disableDepthTestDistance = '1000.0';
* style.disableDepthTestDistance.evaluate(feature); // returns a Number
*/
disableDepthTestDistance: {
get: function() {
return this._disableDepthTestDistance;
},
set: function(value) {
this._disableDepthTestDistance = getExpression(this, value);
this._style.disableDepthTestDistance = getJsonFromExpression(
this._disableDepthTestDistance
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's horizontalOrigin property. Alternatively a string or object defining a number style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a HorizontalOrigin.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium3DTileStyle({
* horizontalOrigin : HorizontalOrigin.LEFT
* });
* style.horizontalOrigin.evaluate(feature); // returns a HorizontalOrigin
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override horizontalOrigin expression with a custom function
* style.horizontalOrigin = {
* evaluate : function(feature) {
* return HorizontalOrigin.CENTER;
* }
* };
*/
horizontalOrigin: {
get: function() {
return this._horizontalOrigin;
},
set: function(value) {
this._horizontalOrigin = getExpression(this, value);
this._style.horizontalOrigin = getJsonFromExpression(
this._horizontalOrigin
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's verticalOrigin property. Alternatively a string or object defining a number style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a VerticalOrigin.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium3DTileStyle({
* verticalOrigin : VerticalOrigin.TOP
* });
* style.verticalOrigin.evaluate(feature); // returns a VerticalOrigin
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override verticalOrigin expression with a custom function
* style.verticalOrigin = {
* evaluate : function(feature) {
* return VerticalOrigin.CENTER;
* }
* };
*/
verticalOrigin: {
get: function() {
return this._verticalOrigin;
},
set: function(value) {
this._verticalOrigin = getExpression(this, value);
this._style.verticalOrigin = getJsonFromExpression(this._verticalOrigin);
}
},
/**
Gets or sets the {@link StyleExpression} object used to evaluate the style's labelHorizontalOrigin property. Alternatively a string or object defining a number style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a HorizontalOrigin.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium3DTileStyle({
* labelHorizontalOrigin : HorizontalOrigin.LEFT
* });
* style.labelHorizontalOrigin.evaluate(feature); // returns a HorizontalOrigin
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override labelHorizontalOrigin expression with a custom function
* style.labelHorizontalOrigin = {
* evaluate : function(feature) {
* return HorizontalOrigin.CENTER;
* }
* };
*/
labelHorizontalOrigin: {
get: function() {
return this._labelHorizontalOrigin;
},
set: function(value) {
this._labelHorizontalOrigin = getExpression(this, value);
this._style.labelHorizontalOrigin = getJsonFromExpression(
this._labelHorizontalOrigin
);
}
},
/**
* Gets or sets the {@link StyleExpression} object used to evaluate the style's labelVerticalOrigin property. Alternatively a string or object defining a number style can be used.
* The getter will return the internal {@link Expression} or {@link ConditionsExpression}, which may differ from the value provided to the setter.
*
* The expression must return a VerticalOrigin.
*
*
* This expression is only applicable to point features in a Vector tile.
*
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @example
* const style = new Cesium3DTileStyle({
* labelVerticalOrigin : VerticalOrigin.TOP
* });
* style.labelVerticalOrigin.evaluate(feature); // returns a VerticalOrigin
*
* @example
* const style = new Cesium.Cesium3DTileStyle();
* // Override labelVerticalOrigin expression with a custom function
* style.labelVerticalOrigin = {
* evaluate : function(feature) {
* return VerticalOrigin.CENTER;
* }
* };
*/
labelVerticalOrigin: {
get: function() {
return this._labelVerticalOrigin;
},
set: function(value) {
this._labelVerticalOrigin = getExpression(this, value);
this._style.labelVerticalOrigin = getJsonFromExpression(
this._labelVerticalOrigin
);
}
},
/**
* Gets or sets the object containing application-specific expression that can be explicitly
* evaluated, e.g., for display in a UI.
*
* @memberof Cesium3DTileStyle.prototype
*
* @type {StyleExpression}
*
* @example
* const style = new Cesium3DTileStyle({
* meta : {
* description : '"Building id ${id} has height ${Height}."'
* }
* });
* style.meta.description.evaluate(feature); // returns a String with the substituted variables
*/
meta: {
get: function() {
return this._meta;
},
set: function(value) {
this._meta = value;
}
}
});
Cesium3DTileStyle.fromUrl = function(url2) {
if (!defined_default(url2)) {
throw new DeveloperError_default("url is required");
}
const resource = Resource_default.createIfNeeded(url2);
return resource.fetchJson(url2).then(function(styleJson) {
return new Cesium3DTileStyle(styleJson);
});
};
Cesium3DTileStyle.prototype.getColorShaderFunction = function(functionSignature, variableSubstitutionMap, shaderState) {
if (this._colorShaderFunctionReady) {
shaderState.translucent = this._colorShaderTranslucent;
return this._colorShaderFunction;
}
this._colorShaderFunctionReady = true;
if (defined_default(this.color) && defined_default(this.color.getShaderFunction)) {
this._colorShaderFunction = this.color.getShaderFunction(
functionSignature,
variableSubstitutionMap,
shaderState,
"vec4"
);
} else {
this._colorShaderFunction = void 0;
}
this._colorShaderTranslucent = shaderState.translucent;
return this._colorShaderFunction;
};
Cesium3DTileStyle.prototype.getShowShaderFunction = function(functionSignature, variableSubstitutionMap, shaderState) {
if (this._showShaderFunctionReady) {
return this._showShaderFunction;
}
this._showShaderFunctionReady = true;
if (defined_default(this.show) && defined_default(this.show.getShaderFunction)) {
this._showShaderFunction = this.show.getShaderFunction(
functionSignature,
variableSubstitutionMap,
shaderState,
"bool"
);
} else {
this._showShaderFunction = void 0;
}
return this._showShaderFunction;
};
Cesium3DTileStyle.prototype.getPointSizeShaderFunction = function(functionSignature, variableSubstitutionMap, shaderState) {
if (this._pointSizeShaderFunctionReady) {
return this._pointSizeShaderFunction;
}
this._pointSizeShaderFunctionReady = true;
if (defined_default(this.pointSize) && defined_default(this.pointSize.getShaderFunction)) {
this._pointSizeShaderFunction = this.pointSize.getShaderFunction(
functionSignature,
variableSubstitutionMap,
shaderState,
"float"
);
} else {
this._pointSizeShaderFunction = void 0;
}
return this._pointSizeShaderFunction;
};
Cesium3DTileStyle.prototype.getVariables = function() {
let variables = [];
if (defined_default(this.color) && defined_default(this.color.getVariables)) {
addAllToArray_default(variables, this.color.getVariables());
}
if (defined_default(this.show) && defined_default(this.show.getVariables)) {
addAllToArray_default(variables, this.show.getVariables());
}
if (defined_default(this.pointSize) && defined_default(this.pointSize.getVariables)) {
addAllToArray_default(variables, this.pointSize.getVariables());
}
variables = variables.filter(function(variable, index, variables2) {
return variables2.indexOf(variable) === index;
});
return variables;
};
var Cesium3DTileStyle_default = Cesium3DTileStyle;
// packages/engine/Source/Scene/Cesium3DTilesVoxelProvider.js
var import_InlineWorkers1236 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/ImplicitSubtreeCache.js
var import_InlineWorkers1235 = __toESM(require_InlineWorkers(), 1);
function ImplicitSubtreeCache(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._maximumSubtreeCount = options.maximumSubtreeCount ?? 0;
this._subtreeRequestCounter = 0;
this._queue = new DoubleEndedPriorityQueue_default({
comparator: ImplicitSubtreeCache.comparator
});
}
ImplicitSubtreeCache.prototype.addSubtree = function(subtree) {
const cacheNode = new ImplicitSubtreeCacheNode(
subtree,
this._subtreeRequestCounter
);
this._subtreeRequestCounter++;
this._queue.insert(cacheNode);
const subtreeCoord = subtree.implicitCoordinates;
if (subtreeCoord.level > 0) {
const parentCoord = subtreeCoord.getParentSubtreeCoordinates();
const parentNode = this.find(parentCoord);
if (parentNode === void 0) {
throw new DeveloperError_default("parent node needs to exist");
}
}
if (this._maximumSubtreeCount > 0) {
while (this._queue.length > this._maximumSubtreeCount) {
const lowestPriorityNode = this._queue.getMinimum();
if (lowestPriorityNode === cacheNode) {
break;
}
this._queue.removeMinimum();
}
}
};
ImplicitSubtreeCache.prototype.find = function(subtreeCoord) {
const queue = this._queue;
const array = queue.internalArray;
const arrayLength = queue.length;
for (let i = 0; i < arrayLength; i++) {
const other = array[i];
const otherSubtree = other.subtree;
const otherCoord = otherSubtree.implicitCoordinates;
if (subtreeCoord.isEqual(otherCoord)) {
return other.subtree;
}
}
return void 0;
};
ImplicitSubtreeCache.comparator = function(a3, b) {
const aCoord = a3.subtree.implicitCoordinates;
const bCoord = b.subtree.implicitCoordinates;
if (aCoord.isAncestor(bCoord)) {
return 1;
} else if (bCoord.isAncestor(aCoord)) {
return -1;
}
return a3.stamp - b.stamp;
};
function ImplicitSubtreeCacheNode(subtree, stamp) {
this.subtree = subtree;
this.stamp = stamp;
}
var ImplicitSubtreeCache_default = ImplicitSubtreeCache;
// packages/engine/Source/Scene/Cesium3DTilesVoxelProvider.js
function Cesium3DTilesVoxelProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const {
className,
names,
types,
componentTypes,
shape,
dimensions,
paddingBefore = Cartesian3_default.ZERO.clone(),
paddingAfter = Cartesian3_default.ZERO.clone(),
globalTransform = Matrix4_default.IDENTITY.clone(),
shapeTransform = Matrix4_default.IDENTITY.clone(),
minBounds,
maxBounds,
minimumValues,
maximumValues,
maximumTileCount
} = options;
Check_default.typeOf.string("className", className);
Check_default.typeOf.object("names", names);
Check_default.typeOf.object("types", types);
Check_default.typeOf.object("componentTypes", componentTypes);
Check_default.typeOf.string("shape", shape);
Check_default.typeOf.object("dimensions", dimensions);
this._shapeTransform = shapeTransform;
this._globalTransform = globalTransform;
this._shape = shape;
this._minBounds = minBounds;
this._maxBounds = maxBounds;
this._dimensions = dimensions;
this._paddingBefore = paddingBefore;
this._paddingAfter = paddingAfter;
this._className = className;
this._names = names;
this._types = types;
this._componentTypes = componentTypes;
this._metadataOrder = shape === VoxelShapeType_default.ELLIPSOID ? VoxelMetadataOrder_default.Z_UP : VoxelMetadataOrder_default.Y_UP;
this._minimumValues = minimumValues;
this._maximumValues = maximumValues;
this._maximumTileCount = maximumTileCount;
this._availableLevels = void 0;
this._implicitTileset = void 0;
this._subtreeCache = new ImplicitSubtreeCache_default();
}
Object.defineProperties(Cesium3DTilesVoxelProvider.prototype, {
/**
* A transform from local space to global space.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {Matrix4}
* @default Matrix4.IDENTITY
* @readonly
*/
globalTransform: {
get: function() {
return this._globalTransform;
}
},
/**
* A transform from shape space to local space.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {Matrix4}
* @default Matrix4.IDENTITY
* @readonly
*/
shapeTransform: {
get: function() {
return this._shapeTransform;
}
},
/**
* Gets the {@link VoxelShapeType}
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {VoxelShapeType}
* @readonly
*/
shape: {
get: function() {
return this._shape;
}
},
/**
* Gets the minimum bounds.
* If undefined, the shape's default minimum bounds will be used instead.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {Cartesian3|undefined}
* @readonly
*/
minBounds: {
get: function() {
return this._minBounds;
}
},
/**
* Gets the maximum bounds.
* If undefined, the shape's default maximum bounds will be used instead.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {Cartesian3|undefined}
* @readonly
*/
maxBounds: {
get: function() {
return this._maxBounds;
}
},
/**
* Gets the number of voxels per dimension of a tile. This is the same for all tiles in the dataset.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {Cartesian3}
* @readonly
*/
dimensions: {
get: function() {
return this._dimensions;
}
},
/**
* Gets the number of padding voxels before the tile. This improves rendering quality when sampling the edge of a tile, but it increases memory usage.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {Cartesian3}
* @default Cartesian3.ZERO
* @readonly
*/
paddingBefore: {
get: function() {
return this._paddingBefore;
}
},
/**
* Gets the number of padding voxels after the tile. This improves rendering quality when sampling the edge of a tile, but it increases memory usage.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {Cartesian3}
* @default Cartesian3.ZERO
* @readonly
*/
paddingAfter: {
get: function() {
return this._paddingAfter;
}
},
/**
* The metadata class for this tileset.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {string}
* @readonly
*/
className: {
get: function() {
return this._className;
}
},
/**
* Gets the metadata names.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {string[]}
* @readonly
*/
names: {
get: function() {
return this._names;
}
},
/**
* Gets the metadata types.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {MetadataType[]}
* @readonly
*/
types: {
get: function() {
return this._types;
}
},
/**
* Gets the metadata component types.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {MetadataComponentType[]}
* @readonly
*/
componentTypes: {
get: function() {
return this._componentTypes;
}
},
/**
* Gets the ordering of the metadata in the buffers.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {VoxelMetadataOrder}
* @readonly
* @private
*/
metadataOrder: {
get: function() {
return this._metadataOrder;
}
},
/**
* Gets the metadata minimum values.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {number[][]|undefined}
* @readonly
*/
minimumValues: {
get: function() {
return this._minimumValues;
}
},
/**
* Gets the metadata maximum values.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {number[][]|undefined}
* @readonly
*/
maximumValues: {
get: function() {
return this._maximumValues;
}
},
/**
* The maximum number of tiles that exist for this provider.
* This value is used as a hint to the voxel renderer to allocate an appropriate amount of GPU memory.
* If this value is not known it can be undefined.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {number|undefined}
* @readonly
*/
maximumTileCount: {
get: function() {
return this._maximumTileCount;
}
},
/**
* The number of levels of detail containing available tiles in the tileset.
*
* @memberof Cesium3DTilesVoxelProvider.prototype
* @type {number|undefined}
* @readonly
*/
availableLevels: {
get: function() {
return this._availableLevels;
}
}
});
Cesium3DTilesVoxelProvider.fromUrl = async function(url2) {
Check_default.defined("url", url2);
const resource = Resource_default.createIfNeeded(url2);
const tilesetJson = await resource.fetchJson();
validate(tilesetJson);
const schemaLoader = getMetadataSchemaLoader(tilesetJson, resource);
await schemaLoader.load();
const { root } = tilesetJson;
const metadataJson = hasExtension_default(tilesetJson, "3DTILES_metadata") ? tilesetJson.extensions["3DTILES_metadata"] : tilesetJson;
const tilesetMetadata = new Cesium3DTilesetMetadata_default({
metadataJson,
schema: schemaLoader.schema
});
const voxel = root.content.extensions["3DTILES_content_voxels"];
const className = voxel.class;
const providerOptions = getAttributeInfo(tilesetMetadata, className);
Object.assign(providerOptions, getShape(root));
if (defined_default(root.transform)) {
providerOptions.globalTransform = Matrix4_default.unpack(root.transform);
} else {
providerOptions.globalTransform = Matrix4_default.clone(Matrix4_default.IDENTITY);
}
providerOptions.dimensions = Cartesian3_default.unpack(voxel.dimensions);
providerOptions.maximumTileCount = getTileCount(tilesetMetadata);
if (defined_default(voxel.padding)) {
providerOptions.paddingBefore = Cartesian3_default.unpack(voxel.padding.before);
providerOptions.paddingAfter = Cartesian3_default.unpack(voxel.padding.after);
}
const provider = new Cesium3DTilesVoxelProvider(providerOptions);
const implicitTileset = new ImplicitTileset_default(
resource,
root,
schemaLoader.schema
);
provider._implicitTileset = implicitTileset;
provider._availableLevels = implicitTileset.availableLevels;
ResourceCache_default.unload(schemaLoader);
return provider;
};
function getTileCount(metadata) {
if (!defined_default(metadata.tileset)) {
return void 0;
}
return metadata.tileset.getPropertyBySemantic(
MetadataSemantic_default.TILESET_TILE_COUNT
);
}
function validate(tileset) {
const root = tileset.root;
if (!defined_default(root.content)) {
throw new RuntimeError_default("Root must have content");
}
if (!hasExtension_default(root.content, "3DTILES_content_voxels")) {
throw new RuntimeError_default(
"Root tile content must have 3DTILES_content_voxels extension"
);
}
if (!hasExtension_default(root, "3DTILES_implicit_tiling") && !defined_default(root.implicitTiling)) {
throw new RuntimeError_default("Root tile must have implicit tiling");
}
if (!defined_default(tileset.schema) && !defined_default(tileset.schemaUri) && !hasExtension_default(tileset, "3DTILES_metadata")) {
throw new RuntimeError_default("Tileset must have a metadata schema");
}
}
function getShape(tile) {
const boundingVolume = tile.boundingVolume;
if (defined_default(boundingVolume.box)) {
return getBoxShape(boundingVolume.box);
} else if (defined_default(boundingVolume.region)) {
return getEllipsoidShape(boundingVolume.region);
} else if (hasExtension_default(boundingVolume, "3DTILES_bounding_volume_cylinder")) {
return getCylinderShape(
boundingVolume.extensions["3DTILES_bounding_volume_cylinder"]
);
}
throw new RuntimeError_default(
"Only box, region and 3DTILES_bounding_volume_cylinder are supported in Cesium3DTilesVoxelProvider"
);
}
function getEllipsoidShape(region) {
const west = region[0];
const south = region[1];
const east = region[2];
const north = region[3];
const minHeight = region[4];
const maxHeight = region[5];
const shapeTransform = Matrix4_default.fromScale(Ellipsoid_default.WGS84.radii);
const minBounds = new Cartesian3_default(west, south, minHeight);
const maxBounds = new Cartesian3_default(east, north, maxHeight);
return {
shape: VoxelShapeType_default.ELLIPSOID,
minBounds,
maxBounds,
shapeTransform
};
}
var scratchScale10 = new Cartesian3_default();
var scratchRotation6 = new Matrix3_default();
function getBoxShape(box) {
const obb = OrientedBoundingBox_default.unpack(box);
const scale = Matrix3_default.getScale(obb.halfAxes, scratchScale10);
const rotation = Matrix3_default.getRotation(obb.halfAxes, scratchRotation6);
return {
shape: VoxelShapeType_default.BOX,
minBounds: Cartesian3_default.negate(scale, new Cartesian3_default()),
maxBounds: Cartesian3_default.clone(scale),
shapeTransform: Matrix4_default.fromRotationTranslation(rotation, obb.center)
};
}
function getCylinderShape(cylinder) {
const {
minRadius,
maxRadius,
height,
minAngle = -Math_default.PI,
maxAngle = Math_default.PI,
translation: translation3 = [0, 0, 0],
rotation = [0, 0, 0, 1]
} = cylinder;
Check_default.typeOf.number("minRadius", minRadius);
Check_default.typeOf.number("maxRadius", maxRadius);
Check_default.typeOf.number("height", height);
Check_default.typeOf.number("minAngle", minAngle);
Check_default.typeOf.number("maxAngle", maxAngle);
Check_default.typeOf.object("translation", translation3);
Check_default.typeOf.object("rotation", rotation);
const minHeight = -0.5 * height + translation3[2];
const maxHeight = 0.5 * height + translation3[2];
const shapeTransform = Matrix4_default.fromTranslationQuaternionRotationScale(
Cartesian3_default.unpack(translation3),
Quaternion_default.unpack(rotation),
Cartesian3_default.ONE
);
return {
shape: VoxelShapeType_default.CYLINDER,
minBounds: Cartesian3_default.fromElements(minRadius, minAngle, minHeight),
maxBounds: Cartesian3_default.fromElements(maxRadius, maxAngle, maxHeight),
shapeTransform
};
}
function getMetadataSchemaLoader(tilesetJson, resource) {
const { schemaUri, schema } = tilesetJson;
if (!defined_default(schemaUri)) {
return ResourceCache_default.getSchemaLoader({ schema });
}
return ResourceCache_default.getSchemaLoader({
resource: resource.getDerivedResource({
url: schemaUri
})
});
}
function getAttributeInfo(metadata, className) {
const { schema, statistics: statistics2 } = metadata;
const classStatistics = statistics2?.classes[className];
const properties = schema.classes[className].properties;
const propertyInfo = Object.entries(properties).map(([id, property]) => {
const { type, componentType } = property;
const min3 = classStatistics?.properties[id].min;
const max3 = classStatistics?.properties[id].max;
const componentCount = MetadataType_default.getComponentCount(type);
const minValue = copyArray(min3, componentCount);
const maxValue = copyArray(max3, componentCount);
return { id, type, componentType, minValue, maxValue };
});
const names = propertyInfo.map((info) => info.id);
const types = propertyInfo.map((info) => info.type);
const componentTypes = propertyInfo.map((info) => info.componentType);
const minimumValues = propertyInfo.map((info) => info.minValue);
const maximumValues = propertyInfo.map((info) => info.maxValue);
const hasMinimumValues = minimumValues.some(defined_default);
return {
className,
names,
types,
componentTypes,
minimumValues: hasMinimumValues ? minimumValues : void 0,
maximumValues: hasMinimumValues ? maximumValues : void 0
};
}
function copyArray(values, length2) {
if (!defined_default(values)) {
return;
}
const valuesArray = Array.isArray(values) ? values : [values];
return Array.from({ length: length2 }, (v3, i) => valuesArray[i]);
}
async function getSubtree(provider, subtreeCoord) {
const implicitTileset = provider._implicitTileset;
const subtreeCache = provider._subtreeCache;
let subtree = subtreeCache.find(subtreeCoord);
if (defined_default(subtree)) {
return subtree;
}
const subtreeRelative = implicitTileset.subtreeUriTemplate.getDerivedResource(
{
templateValues: subtreeCoord.getTemplateValues()
}
);
const subtreeResource = implicitTileset.baseResource.getDerivedResource({
url: subtreeRelative.url
});
const arrayBuffer = await subtreeResource.fetchArrayBuffer();
subtree = subtreeCache.find(subtreeCoord);
if (defined_default(subtree)) {
return subtree;
}
const preprocessed = preprocess3DTileContent_default(arrayBuffer);
subtree = await ImplicitSubtree_default.fromSubtreeJson(
subtreeResource,
preprocessed.jsonPayload,
preprocessed.binaryPayload,
implicitTileset,
subtreeCoord
);
subtreeCache.addSubtree(subtree);
return subtree;
}
Cesium3DTilesVoxelProvider.prototype.requestData = async function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const {
tileLevel = 0,
tileX = 0,
tileY = 0,
tileZ = 0,
keyframe = 0
} = options;
if (keyframe !== 0) {
return Promise.reject(
`3D Tiles currently doesn't support time-dynamic data.`
);
}
const implicitTileset = this._implicitTileset;
const tileCoordinates = new ImplicitTileCoordinates_default({
subdivisionScheme: implicitTileset.subdivisionScheme,
subtreeLevels: implicitTileset.subtreeLevels,
level: tileLevel,
x: tileX,
y: tileY,
z: tileZ
});
const isSubtreeRoot = tileCoordinates.isSubtreeRoot() && tileCoordinates.level > 0;
const subtreeCoord = isSubtreeRoot ? tileCoordinates.getParentSubtreeCoordinates() : tileCoordinates.getSubtreeCoordinates();
const that = this;
const subtree = await getSubtree(that, subtreeCoord);
const isAvailable = isSubtreeRoot ? subtree.childSubtreeIsAvailableAtCoordinates : subtree.tileIsAvailableAtCoordinates;
const available = isAvailable.call(subtree, tileCoordinates);
if (!available) {
return Promise.reject(
`Tile is not available at level ${tileLevel}, x ${tileX}, y ${tileY}, z ${tileZ}.`
);
}
const { contentUriTemplates, baseResource: baseResource2 } = implicitTileset;
const gltfRelative = contentUriTemplates[0].getDerivedResource({
templateValues: tileCoordinates.getTemplateValues()
});
const gltfResource = baseResource2.getDerivedResource({
url: gltfRelative.url
});
return VoxelContent_default.fromGltf(gltfResource);
};
var Cesium3DTilesVoxelProvider_default = Cesium3DTilesVoxelProvider;
// packages/engine/Source/Scene/CircleEmitter.js
var import_InlineWorkers1237 = __toESM(require_InlineWorkers(), 1);
function CircleEmitter(radius) {
radius = radius ?? 1;
Check_default.typeOf.number.greaterThan("radius", radius, 0);
this._radius = radius ?? 1;
}
Object.defineProperties(CircleEmitter.prototype, {
/**
* The radius of the circle in meters.
* @memberof CircleEmitter.prototype
* @type {number}
* @default 1.0
*/
radius: {
get: function() {
return this._radius;
},
set: function(value) {
Check_default.typeOf.number.greaterThan("value", value, 0);
this._radius = value;
}
}
});
CircleEmitter.prototype.emit = function(particle) {
const theta = Math_default.randomBetween(0, Math_default.TWO_PI);
const rad = Math_default.randomBetween(0, this._radius);
const x = rad * Math.cos(theta);
const y = rad * Math.sin(theta);
const z = 0;
particle.position = Cartesian3_default.fromElements(x, y, z, particle.position);
particle.velocity = Cartesian3_default.clone(Cartesian3_default.UNIT_Z, particle.velocity);
};
var CircleEmitter_default = CircleEmitter;
// packages/engine/Source/Scene/CloudCollection.js
var import_InlineWorkers1240 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/CloudType.js
var import_InlineWorkers1238 = __toESM(require_InlineWorkers(), 1);
var CloudType = {
/**
* Cumulus cloud.
*
* @type {number}
* @constant
*/
CUMULUS: 0
};
CloudType.validate = function(cloudType) {
return cloudType === CloudType.CUMULUS;
};
var CloudType_default = Object.freeze(CloudType);
// packages/engine/Source/Scene/CumulusCloud.js
var import_InlineWorkers1239 = __toESM(require_InlineWorkers(), 1);
function CumulusCloud(options, cloudCollection) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._show = options.show ?? true;
this._position = Cartesian3_default.clone(options.position ?? Cartesian3_default.ZERO);
if (!defined_default(options.scale) && defined_default(options.maximumSize)) {
this._maximumSize = Cartesian3_default.clone(options.maximumSize);
this._scale = new Cartesian2_default(this._maximumSize.x, this._maximumSize.y);
} else {
this._scale = Cartesian2_default.clone(options.scale ?? new Cartesian2_default(20, 12));
const defaultMaxSize = new Cartesian3_default(
this._scale.x,
this._scale.y,
Math.min(this._scale.x, this._scale.y) / 1.5
);
this._maximumSize = Cartesian3_default.clone(options.maximumSize ?? defaultMaxSize);
}
this._slice = options.slice ?? -1;
this._color = Color_default.clone(options.color ?? Color_default.WHITE);
this._brightness = options.brightness ?? 1;
this._cloudCollection = cloudCollection;
this._index = -1;
}
var SHOW_INDEX7 = CumulusCloud.SHOW_INDEX = 0;
var POSITION_INDEX7 = CumulusCloud.POSITION_INDEX = 1;
var SCALE_INDEX3 = CumulusCloud.SCALE_INDEX = 2;
var MAXIMUM_SIZE_INDEX = CumulusCloud.MAXIMUM_SIZE_INDEX = 3;
var SLICE_INDEX = CumulusCloud.SLICE_INDEX = 4;
var BRIGHTNESS_INDEX = CumulusCloud.BRIGHTNESS_INDEX = 5;
var COLOR_INDEX5 = CumulusCloud.COLOR_INDEX = 6;
CumulusCloud.NUMBER_OF_PROPERTIES = 7;
function makeDirty4(cloud, propertyChanged) {
const cloudCollection = cloud._cloudCollection;
if (defined_default(cloudCollection)) {
cloudCollection._updateCloud(cloud, propertyChanged);
cloud._dirty = true;
}
}
Object.defineProperties(CumulusCloud.prototype, {
/**
* Determines if this cumulus cloud will be shown. Use this to hide or show a cloud, instead
* of removing it and re-adding it to the collection.
* @memberof CumulusCloud.prototype
* @type {boolean}
* @default true
*/
show: {
get: function() {
return this._show;
},
set: function(value) {
Check_default.typeOf.bool("value", value);
if (this._show !== value) {
this._show = value;
makeDirty4(this, SHOW_INDEX7);
}
}
},
/**
* Gets or sets the Cartesian position of this cumulus cloud.
* @memberof CumulusCloud.prototype
* @type {Cartesian3}
*/
position: {
get: function() {
return this._position;
},
set: function(value) {
Check_default.typeOf.object("value", value);
const position = this._position;
if (!Cartesian3_default.equals(position, value)) {
Cartesian3_default.clone(value, position);
makeDirty4(this, POSITION_INDEX7);
}
}
},
/**
* Gets or sets the scale of the cumulus cloud billboard in meters.
* The scale property will affect the size of the billboard,
* but not the cloud's actual appearance.
*
*
*
* cloud.scale = new Cesium.Cartesian2(12, 8);
*
*
*
* cloud.scale = new Cesium.Cartesian2(24, 10);
*
*
*
*
*
* To modify the cloud's appearance, modify its maximumSize
* and slice properties.
* @memberof CumulusCloud.prototype
* @type {Cartesian2}
*
* @see CumulusCloud#maximumSize
* @see CumulusCloud#slice
*/
scale: {
get: function() {
return this._scale;
},
set: function(value) {
Check_default.typeOf.object("value", value);
const scale = this._scale;
if (!Cartesian2_default.equals(scale, value)) {
Cartesian2_default.clone(value, scale);
makeDirty4(this, SCALE_INDEX3);
}
}
},
/**
* Gets or sets the maximum size of the cumulus cloud rendered on the billboard.
* This defines a maximum ellipsoid volume that the cloud can appear in.
* Rather than guaranteeing a specific size, this specifies a boundary for the
* cloud to appear in, and changing it can affect the shape of the cloud.
* Changing the z-value of maximumSize has the most dramatic effect
* on the cloud's appearance because it changes the depth of the cloud, and thus the
* positions at which the cloud-shaping texture is sampled.
*
*
*
*
* cloud.maximumSize = new Cesium.Cartesian3(14, 9, 10);
*
*
*
* cloud.maximumSize.x = 25;
*
*
*
*
*
* cloud.maximumSize.y = 5;
*
*
*
* cloud.maximumSize.z = 17;
*
*
*
*
*
*
* To modify the billboard's actual size, modify the cloud's scale property.
* @memberof CumulusCloud.prototype
* @type {Cartesian3}
*
* @see CumulusCloud#scale
*/
maximumSize: {
get: function() {
return this._maximumSize;
},
set: function(value) {
Check_default.typeOf.object("value", value);
const maximumSize = this._maximumSize;
if (!Cartesian3_default.equals(maximumSize, value)) {
Cartesian3_default.clone(value, maximumSize);
makeDirty4(this, MAXIMUM_SIZE_INDEX);
}
}
},
/**
* Sets the color of the cloud
* @memberof CumulusCloud.prototype
* @type {Color}
* @default Color.WHITE
*/
color: {
get: function() {
return this._color;
},
set: function(value) {
Check_default.typeOf.object("value", value);
const color = this._color;
if (!Color_default.equals(color, value)) {
Color_default.clone(value, color);
makeDirty4(this, COLOR_INDEX5);
}
}
},
/**
* Gets or sets the "slice" of the cloud that is rendered on the billboard, i.e.
* the specific cross-section of the cloud chosen for the billboard's appearance.
* Given a value between 0 and 1, the slice specifies how deeply into the cloud
* to intersect based on its maximum size in the z-direction.
*
*
* cloud.slice = 0.32;

* cloud.slice = 0.5;

* cloud.slice = 0.6;

*
*
*
*
* Due to the nature in which this slice is calculated,
* values below 0.2 may result in cross-sections that are too small,
* and the edge of the ellipsoid will be visible. Similarly, values above 0.7
* will cause the cloud to appear smaller. Values outside the range [0.1, 0.9]
* should be avoided entirely because they do not produce desirable results.
*
*
*
* cloud.slice = 0.08;

* cloud.slice = 0.8;

*
*
*
* If slice is set to a negative number, the cloud will not render a cross-section.
* Instead, it will render the outside of the ellipsoid that is visible. For clouds with
* small values of `maximumSize.z`, this can produce good-looking results, but for larger
* clouds, this can result in a cloud that is undesirably warped to the ellipsoid volume.
*
*
*
*
* cloud.slice = -1.0;
cloud.maximumSize.z = 18;
*
*
*
* cloud.slice = -1.0;
cloud.maximumSize.z = 30;
* 
*
*
*
* @memberof CumulusCloud.prototype
* @type {number}
* @default -1.0
*/
slice: {
get: function() {
return this._slice;
},
set: function(value) {
Check_default.typeOf.number("value", value);
const slice = this._slice;
if (slice !== value) {
this._slice = value;
makeDirty4(this, SLICE_INDEX);
}
}
},
/**
* Gets or sets the brightness of the cloud. This can be used to give clouds
* a darker, grayer appearance.
*
*
*
* cloud.brightness = 1.0;

* cloud.brightness = 0.6;

* cloud.brightness = 0.0;

*
*
* @memberof CumulusCloud.prototype
* @type {number}
* @default 1.0
*/
brightness: {
get: function() {
return this._brightness;
},
set: function(value) {
Check_default.typeOf.number("value", value);
const brightness = this._brightness;
if (brightness !== value) {
this._brightness = value;
makeDirty4(this, BRIGHTNESS_INDEX);
}
}
}
});
CumulusCloud.prototype._destroy = function() {
this._cloudCollection = void 0;
};
var CumulusCloud_default = CumulusCloud;
// packages/engine/Source/Scene/CloudCollection.js
var attributeLocations7;
var scratchTextureDimensions = new Cartesian3_default();
var attributeLocationsBatched2 = {
positionHighAndScaleX: 0,
positionLowAndScaleY: 1,
packedAttribute0: 2,
// show, brightness, direction
packedAttribute1: 3,
// cloudSize, slice
color: 4
};
var attributeLocationsInstanced2 = {
direction: 0,
positionHighAndScaleX: 1,
positionLowAndScaleY: 2,
packedAttribute0: 3,
// show, brightness
packedAttribute1: 4,
// cloudSize, slice
color: 5
};
var SHOW_INDEX8 = CumulusCloud_default.SHOW_INDEX;
var POSITION_INDEX8 = CumulusCloud_default.POSITION_INDEX;
var SCALE_INDEX4 = CumulusCloud_default.SCALE_INDEX;
var MAXIMUM_SIZE_INDEX2 = CumulusCloud_default.MAXIMUM_SIZE_INDEX;
var SLICE_INDEX2 = CumulusCloud_default.SLICE_INDEX;
var BRIGHTNESS_INDEX2 = CumulusCloud_default.BRIGHTNESS_INDEX;
var NUMBER_OF_PROPERTIES5 = CumulusCloud_default.NUMBER_OF_PROPERTIES;
var COLOR_INDEX6 = CumulusCloud_default.COLOR_INDEX;
function CloudCollection(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._clouds = [];
this._cloudsToUpdate = [];
this._cloudsToUpdateIndex = 0;
this._cloudsRemoved = false;
this._createVertexArray = false;
this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES5);
this._noiseTexture = void 0;
this._textureSliceWidth = 128;
this._noiseTextureRows = 4;
this.noiseDetail = options.noiseDetail ?? 16;
this.noiseOffset = Cartesian3_default.clone(options.noiseOffset ?? Cartesian3_default.ZERO);
this._loading = false;
this._ready = false;
const that = this;
this._uniforms = {
u_noiseTexture: function() {
return that._noiseTexture;
},
u_noiseTextureDimensions: getNoiseTextureDimensions(that),
u_noiseDetail: function() {
return that.noiseDetail;
}
};
this._vaNoise = void 0;
this._spNoise = void 0;
this._spCreated = false;
this._sp = void 0;
this._rs = void 0;
this.show = options.show ?? true;
this._colorCommands = [];
this.debugBillboards = options.debugBillboards ?? false;
this._compiledDebugBillboards = false;
this.debugEllipsoids = options.debugEllipsoids ?? false;
this._compiledDebugEllipsoids = false;
}
function getNoiseTextureDimensions(collection) {
return function() {
scratchTextureDimensions.x = collection._textureSliceWidth;
scratchTextureDimensions.y = collection._noiseTextureRows;
scratchTextureDimensions.z = 1 / collection._noiseTextureRows;
return scratchTextureDimensions;
};
}
Object.defineProperties(CloudCollection.prototype, {
/**
* Returns the number of clouds in this collection.
* @memberof CloudCollection.prototype
* @type {number}
*/
length: {
get: function() {
removeClouds(this);
return this._clouds.length;
}
}
});
function destroyClouds(clouds) {
const length2 = clouds.length;
for (let i = 0; i < length2; ++i) {
if (clouds[i]) {
clouds[i]._destroy();
}
}
}
CloudCollection.prototype.add = function(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const cloudType = options.cloudType ?? CloudType_default.CUMULUS;
if (!CloudType_default.validate(cloudType)) {
throw new DeveloperError_default("invalid cloud type");
}
let cloud;
if (cloudType === CloudType_default.CUMULUS) {
cloud = new CumulusCloud_default(options, this);
cloud._index = this._clouds.length;
this._clouds.push(cloud);
this._createVertexArray = true;
}
return cloud;
};
CloudCollection.prototype.remove = function(cloud) {
if (this.contains(cloud)) {
this._clouds[cloud._index] = void 0;
this._cloudsRemoved = true;
this._createVertexArray = true;
cloud._destroy();
return true;
}
return false;
};
CloudCollection.prototype.removeAll = function() {
destroyClouds(this._clouds);
this._clouds = [];
this._cloudsToUpdate = [];
this._cloudsToUpdateIndex = 0;
this._cloudsRemoved = false;
this._createVertexArray = true;
};
function removeClouds(cloudCollection) {
if (cloudCollection._cloudsRemoved) {
cloudCollection._cloudsRemoved = false;
const newClouds = [];
const clouds = cloudCollection._clouds;
const length2 = clouds.length;
for (let i = 0, j = 0; i < length2; ++i) {
const cloud = clouds[i];
if (defined_default(cloud)) {
clouds._index = j++;
newClouds.push(cloud);
}
}
cloudCollection._clouds = newClouds;
}
}
CloudCollection.prototype._updateCloud = function(cloud, propertyChanged) {
if (!cloud._dirty) {
this._cloudsToUpdate[this._cloudsToUpdateIndex++] = cloud;
}
++this._propertiesChanged[propertyChanged];
};
CloudCollection.prototype.contains = function(cloud) {
return defined_default(cloud) && cloud._cloudCollection === this;
};
CloudCollection.prototype.get = function(index) {
Check_default.typeOf.number("index", index);
removeClouds(this);
return this._clouds[index];
};
var texturePositions = new Float32Array([
-1,
-1,
1,
-1,
1,
1,
-1,
1
]);
var textureIndices = new Uint16Array([0, 1, 2, 0, 2, 3]);
function createTextureVA(context) {
const positionBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: texturePositions,
usage: BufferUsage_default.STATIC_DRAW
});
const indexBuffer = Buffer_default.createIndexBuffer({
context,
typedArray: textureIndices,
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype: IndexDatatype_default.UNSIGNED_SHORT
});
const attributes = [
{
index: 0,
vertexBuffer: positionBuffer,
componentsPerAttribute: 2,
componentDatatype: ComponentDatatype_default.FLOAT
}
];
return new VertexArray_default({
context,
attributes,
indexBuffer
});
}
var getIndexBuffer3;
function getIndexBufferBatched2(context) {
const sixteenK = 16 * 1024;
let indexBuffer = context.cache.cloudCollection_indexBufferBatched;
if (defined_default(indexBuffer)) {
return indexBuffer;
}
const length2 = sixteenK * 6 - 6;
const indices = new Uint16Array(length2);
for (let i = 0, j = 0; i < length2; i += 6, j += 4) {
indices[i] = j;
indices[i + 1] = j + 1;
indices[i + 2] = j + 2;
indices[i + 3] = j;
indices[i + 4] = j + 2;
indices[i + 5] = j + 3;
}
indexBuffer = Buffer_default.createIndexBuffer({
context,
typedArray: indices,
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype: IndexDatatype_default.UNSIGNED_SHORT
});
indexBuffer.vertexArrayDestroyable = false;
context.cache.cloudCollection_indexBufferBatched = indexBuffer;
return indexBuffer;
}
function getIndexBufferInstanced2(context) {
let indexBuffer = context.cache.cloudCollection_indexBufferInstanced;
if (defined_default(indexBuffer)) {
return indexBuffer;
}
indexBuffer = Buffer_default.createIndexBuffer({
context,
typedArray: new Uint16Array([0, 1, 2, 0, 2, 3]),
usage: BufferUsage_default.STATIC_DRAW,
indexDatatype: IndexDatatype_default.UNSIGNED_SHORT
});
indexBuffer.vertexArrayDestroyable = false;
context.cache.cloudCollection_indexBufferInstanced = indexBuffer;
return indexBuffer;
}
function getVertexBufferInstanced2(context) {
let vertexBuffer = context.cache.cloudCollection_vertexBufferInstanced;
if (defined_default(vertexBuffer)) {
return vertexBuffer;
}
vertexBuffer = Buffer_default.createVertexBuffer({
context,
typedArray: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
usage: BufferUsage_default.STATIC_DRAW
});
vertexBuffer.vertexArrayDestroyable = false;
context.cache.cloudCollection_vertexBufferInstanced = vertexBuffer;
return vertexBuffer;
}
function createVAF3(context, numberOfClouds, instanced) {
const attributes = [
{
index: attributeLocations7.positionHighAndScaleX,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: BufferUsage_default.STATIC_DRAW
},
{
index: attributeLocations7.positionLowAndScaleY,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: BufferUsage_default.STATIC_DRAW
},
{
index: attributeLocations7.packedAttribute0,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: BufferUsage_default.STATIC_DRAW
},
{
index: attributeLocations7.packedAttribute1,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.FLOAT,
usage: BufferUsage_default.STATIC_DRAW
},
{
index: attributeLocations7.color,
componentsPerAttribute: 4,
componentDatatype: ComponentDatatype_default.UNSIGNED_BYTE,
normalize: true,
usage: BufferUsage_default.STATIC_DRAW
}
];
if (instanced) {
attributes.push({
index: attributeLocations7.direction,
componentsPerAttribute: 2,
componentDatatype: ComponentDatatype_default.FLOAT,
vertexBuffer: getVertexBufferInstanced2(context)
});
}
const sizeInVertices = instanced ? numberOfClouds : 4 * numberOfClouds;
return new VertexArrayFacade_default(context, attributes, sizeInVertices, instanced);
}
var writePositionScratch3 = new EncodedCartesian3_default();
function writePositionAndScale(cloudCollection, frameState, vafWriters, cloud) {
let i;
const positionHighWriter = vafWriters[attributeLocations7.positionHighAndScaleX];
const positionLowWriter = vafWriters[attributeLocations7.positionLowAndScaleY];
const position = cloud.position;
EncodedCartesian3_default.fromCartesian(position, writePositionScratch3);
const scale = cloud.scale;
const high = writePositionScratch3.high;
const low = writePositionScratch3.low;
if (cloudCollection._instanced) {
i = cloud._index;
positionHighWriter(i, high.x, high.y, high.z, scale.x);
positionLowWriter(i, low.x, low.y, low.z, scale.y);
} else {
i = cloud._index * 4;
positionHighWriter(i + 0, high.x, high.y, high.z, scale.x);
positionHighWriter(i + 1, high.x, high.y, high.z, scale.x);
positionHighWriter(i + 2, high.x, high.y, high.z, scale.x);
positionHighWriter(i + 3, high.x, high.y, high.z, scale.x);
positionLowWriter(i + 0, low.x, low.y, low.z, scale.y);
positionLowWriter(i + 1, low.x, low.y, low.z, scale.y);
positionLowWriter(i + 2, low.x, low.y, low.z, scale.y);
positionLowWriter(i + 3, low.x, low.y, low.z, scale.y);
}
}
function writePackedAttribute0(cloudCollection, frameState, vafWriters, cloud) {
let i;
const writer = vafWriters[attributeLocations7.packedAttribute0];
const show = cloud.show;
const brightness = cloud.brightness;
if (cloudCollection._instanced) {
i = cloud._index;
writer(i, show, brightness, 0, 0);
} else {
i = cloud._index * 4;
writer(i + 0, show, brightness, 0, 0);
writer(i + 1, show, brightness, 1, 0);
writer(i + 2, show, brightness, 1, 1);
writer(i + 3, show, brightness, 0, 1);
}
}
function writePackedAttribute1(cloudCollection, frameState, vafWriters, cloud) {
let i;
const writer = vafWriters[attributeLocations7.packedAttribute1];
const maximumSize = cloud.maximumSize;
const slice = cloud.slice;
if (cloudCollection._instanced) {
i = cloud._index;
writer(i, maximumSize.x, maximumSize.y, maximumSize.z, slice);
} else {
i = cloud._index * 4;
writer(i + 0, maximumSize.x, maximumSize.y, maximumSize.z, slice);
writer(i + 1, maximumSize.x, maximumSize.y, maximumSize.z, slice);
writer(i + 2, maximumSize.x, maximumSize.y, maximumSize.z, slice);
writer(i + 3, maximumSize.x, maximumSize.y, maximumSize.z, slice);
}
}
function writeColor(cloudCollection, frameState, vafWriters, cloud) {
let i;
const writer = vafWriters[attributeLocations7.color];
const color = cloud.color;
const red = Color_default.floatToByte(color.red);
const green = Color_default.floatToByte(color.green);
const blue = Color_default.floatToByte(color.blue);
const alpha = Color_default.floatToByte(color.alpha);
if (cloudCollection._instanced) {
i = cloud._index;
writer(i, red, green, blue, alpha);
} else {
i = cloud._index * 4;
writer(i + 0, red, green, blue, alpha);
writer(i + 1, red, green, blue, alpha);
writer(i + 2, red, green, blue, alpha);
writer(i + 3, red, green, blue, alpha);
}
}
function writeCloud(cloudCollection, frameState, vafWriters, cloud) {
writePositionAndScale(cloudCollection, frameState, vafWriters, cloud);
writePackedAttribute0(cloudCollection, frameState, vafWriters, cloud);
writePackedAttribute1(cloudCollection, frameState, vafWriters, cloud);
writeColor(cloudCollection, frameState, vafWriters, cloud);
}
function createNoiseTexture(cloudCollection, frameState, vsSource, fsSource) {
const that = cloudCollection;
const textureSliceWidth = that._textureSliceWidth;
const noiseTextureRows = that._noiseTextureRows;
if (textureSliceWidth / noiseTextureRows < 1 || textureSliceWidth % noiseTextureRows !== 0) {
throw new DeveloperError_default(
"noiseTextureRows must evenly divide textureSliceWidth"
);
}
const context = frameState.context;
that._vaNoise = createTextureVA(context);
that._spNoise = ShaderProgram_default.fromCache({
context,
vertexShaderSource: vsSource,
fragmentShaderSource: fsSource,
attributeLocations: {
position: 0
}
});
const noiseDetail = that.noiseDetail;
const noiseOffset = that.noiseOffset;
that._noiseTexture = new Texture_default({
context,
width: textureSliceWidth * textureSliceWidth / noiseTextureRows,
height: textureSliceWidth * noiseTextureRows,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
pixelFormat: PixelFormat_default.RGBA,
sampler: new Sampler_default({
wrapS: TextureWrap_default.REPEAT,
wrapT: TextureWrap_default.REPEAT,
minificationFilter: TextureMinificationFilter_default.NEAREST,
magnificationFilter: TextureMagnificationFilter_default.NEAREST
})
});
const textureCommand = new ComputeCommand_default({
vertexArray: that._vaNoise,
shaderProgram: that._spNoise,
outputTexture: that._noiseTexture,
uniformMap: {
u_noiseTextureDimensions: getNoiseTextureDimensions(that),
u_noiseDetail: function() {
return noiseDetail;
},
u_noiseOffset: function() {
return noiseOffset;
}
},
persists: false,
owner: cloudCollection,
postExecute: function(texture) {
that._ready = true;
that._loading = false;
}
});
frameState.commandList.push(textureCommand);
that._loading = true;
}
function createVertexArray5(cloudCollection, frameState) {
const that = cloudCollection;
const context = frameState.context;
that._createVertexArray = false;
that._vaf = that._vaf && that._vaf.destroy();
const clouds = cloudCollection._clouds;
const cloudsLength = clouds.length;
if (cloudsLength > 0) {
that._vaf = createVAF3(context, cloudsLength, that._instanced);
const vafWriters = that._vaf.writers;
let i;
for (i = 0; i < cloudsLength; ++i) {
const cloud = clouds[i];
writeCloud(cloudCollection, frameState, vafWriters, cloud);
}
that._vaf.commit(getIndexBuffer3(context));
}
}
var scratchWriterArray3 = [];
function updateClouds(cloudCollection, frameState) {
const context = frameState.context;
const that = cloudCollection;
const clouds = that._clouds;
const cloudsLength = clouds.length;
const cloudsToUpdate = that._cloudsToUpdate;
const cloudsToUpdateLength = that._cloudsToUpdateIndex;
const properties = that._propertiesChanged;
const writers = scratchWriterArray3;
writers.length = 0;
if (properties[POSITION_INDEX8] || properties[SCALE_INDEX4]) {
writers.push(writePositionAndScale);
}
if (properties[SHOW_INDEX8] || properties[BRIGHTNESS_INDEX2]) {
writers.push(writePackedAttribute0);
}
if (properties[MAXIMUM_SIZE_INDEX2] || properties[SLICE_INDEX2]) {
writers.push(writePackedAttribute1);
}
if (properties[COLOR_INDEX6]) {
writers.push(writeColor);
}
const numWriters = writers.length;
const vafWriters = that._vaf.writers;
let i, c, w;
if (cloudsToUpdateLength / cloudsLength > 0.1) {
for (i = 0; i < cloudsToUpdateLength; ++i) {
c = cloudsToUpdate[i];
c._dirty = false;
for (w = 0; w < numWriters; ++w) {
writers[w](cloudCollection, frameState, vafWriters, c);
}
}
that._vaf.commit(getIndexBuffer3(context));
} else {
for (i = 0; i < cloudsToUpdateLength; ++i) {
c = cloudsToUpdate[i];
c._dirty = false;
for (w = 0; w < numWriters; ++w) {
writers[w](cloudCollection, frameState, vafWriters, c);
}
if (that._instanced) {
that._vaf.subCommit(c._index, 1);
} else {
that._vaf.subCommit(c._index * 4, 4);
}
}
that._vaf.endSubCommits();
}
that._cloudsToUpdateIndex = 0;
}
function createShaderProgram5(cloudCollection, frameState, vsSource, fsSource) {
const context = frameState.context;
const that = cloudCollection;
const vs = new ShaderSource_default({
defines: [],
sources: [vsSource]
});
if (that._instanced) {
vs.defines.push("INSTANCED");
}
const fs = new ShaderSource_default({
defines: [],
sources: [fsSource]
});
if (that.debugBillboards) {
fs.defines.push("DEBUG_BILLBOARDS");
}
if (that.debugEllipsoids) {
fs.defines.push("DEBUG_ELLIPSOIDS");
}
that._sp = ShaderProgram_default.replaceCache({
context,
shaderProgram: that._sp,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations7
});
that._rs = RenderState_default.fromCache({
depthTest: {
enabled: true,
func: WebGLConstants_default.LESS
},
depthMask: false,
blending: BlendingState_default.ALPHA_BLEND
});
that._spCreated = true;
that._compiledDebugBillboards = that.debugBillboards;
that._compiledDebugEllipsoids = that.debugEllipsoids;
}
function createDrawCommands(cloudCollection, frameState) {
const that = cloudCollection;
const pass = frameState.passes;
const uniforms = that._uniforms;
const commandList = frameState.commandList;
if (pass.render) {
const colorList = that._colorCommands;
const va = that._vaf.va;
const vaLength = va.length;
colorList.length = vaLength;
for (let i = 0; i < vaLength; i++) {
let command = colorList[i];
if (!defined_default(command)) {
command = colorList[i] = new DrawCommand_default();
}
command.pass = Pass_default.TRANSLUCENT;
command.owner = cloudCollection;
command.uniformMap = uniforms;
command.count = va[i].indicesCount;
command.vertexArray = va[i].va;
command.shaderProgram = that._sp;
command.renderState = that._rs;
if (that._instanced) {
command.count = 6;
command.instanceCount = that._clouds.length;
}
commandList.push(command);
}
}
}
CloudCollection.prototype.update = function(frameState) {
removeClouds(this);
if (!this.show) {
return;
}
const debugging = this.debugBillboards || this.debugEllipsoids;
this._ready = debugging ? true : defined_default(this._noiseTexture);
if (!this._ready && !this._loading && !debugging) {
createNoiseTexture(this, frameState, CloudNoiseVS_default, CloudNoiseFS_default);
}
this._instanced = frameState.context.instancedArrays;
attributeLocations7 = this._instanced ? attributeLocationsInstanced2 : attributeLocationsBatched2;
getIndexBuffer3 = this._instanced ? getIndexBufferInstanced2 : getIndexBufferBatched2;
const clouds = this._clouds;
const cloudsLength = clouds.length;
const cloudsToUpdate = this._cloudsToUpdate;
const cloudsToUpdateLength = this._cloudsToUpdateIndex;
if (this._createVertexArray) {
createVertexArray5(this, frameState);
} else if (cloudsToUpdateLength > 0) {
updateClouds(this, frameState);
}
if (cloudsToUpdateLength > cloudsLength * 1.5) {
cloudsToUpdate.length = cloudsLength;
}
if (!defined_default(this._vaf) || !defined_default(this._vaf.va) || !this._ready & !debugging) {
return;
}
if (!this._spCreated || this.debugBillboards !== this._compiledDebugBillboards || this.debugEllipsoids !== this._compiledDebugEllipsoids) {
createShaderProgram5(this, frameState, CloudCollectionVS_default, CloudCollectionFS_default);
}
createDrawCommands(this, frameState);
};
CloudCollection.prototype.isDestroyed = function() {
return false;
};
CloudCollection.prototype.destroy = function() {
this._noiseTexture = this._noiseTexture && this._noiseTexture.destroy();
this._sp = this._sp && this._sp.destroy();
this._vaf = this._vaf && this._vaf.destroy();
destroyClouds(this._clouds);
return destroyObject_default(this);
};
var CloudCollection_default = CloudCollection;
// packages/engine/Source/Scene/ConeEmitter.js
var import_InlineWorkers1241 = __toESM(require_InlineWorkers(), 1);
var defaultAngle = Math_default.toRadians(30);
function ConeEmitter(angle) {
this._angle = angle ?? defaultAngle;
}
Object.defineProperties(ConeEmitter.prototype, {
/**
* The angle of the cone in radians.
* @memberof CircleEmitter.prototype
* @type {number}
* @default Cesium.Math.toRadians(30.0)
*/
angle: {
get: function() {
return this._angle;
},
set: function(value) {
Check_default.typeOf.number("value", value);
this._angle = value;
}
}
});
ConeEmitter.prototype.emit = function(particle) {
const radius = Math.tan(this._angle);
const theta = Math_default.randomBetween(0, Math_default.TWO_PI);
const rad = Math_default.randomBetween(0, radius);
const x = rad * Math.cos(theta);
const y = rad * Math.sin(theta);
const z = 1;
particle.velocity = Cartesian3_default.fromElements(x, y, z, particle.velocity);
Cartesian3_default.normalize(particle.velocity, particle.velocity);
particle.position = Cartesian3_default.clone(Cartesian3_default.ZERO, particle.position);
};
var ConeEmitter_default = ConeEmitter;
// packages/engine/Source/Scene/DebugAppearance.js
var import_InlineWorkers1242 = __toESM(require_InlineWorkers(), 1);
function DebugAppearance(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const attributeName = options.attributeName;
let perInstanceAttribute = options.perInstanceAttribute;
if (!defined_default(attributeName)) {
throw new DeveloperError_default("options.attributeName is required.");
}
if (!defined_default(perInstanceAttribute)) {
perInstanceAttribute = false;
}
let glslDatatype = options.glslDatatype ?? "vec3";
const varyingName = `v_${attributeName}`;
let getColor;
if (attributeName === "normal" || attributeName === "tangent" || attributeName === "bitangent") {
getColor = `vec4 getColor() { return vec4((${varyingName} + vec3(1.0)) * 0.5, 1.0); }
`;
} else {
if (attributeName === "st") {
glslDatatype = "vec2";
}
switch (glslDatatype) {
case "float":
getColor = `vec4 getColor() { return vec4(vec3(${varyingName}), 1.0); }
`;
break;
case "vec2":
getColor = `vec4 getColor() { return vec4(${varyingName}, 0.0, 1.0); }
`;
break;
case "vec3":
getColor = `vec4 getColor() { return vec4(${varyingName}, 1.0); }
`;
break;
case "vec4":
getColor = `vec4 getColor() { return ${varyingName}; }
`;
break;
//>>includeStart('debug', pragmas.debug);
default:
throw new DeveloperError_default(
"options.glslDatatype must be float, vec2, vec3, or vec4."
);
}
}
const vs = `${"in vec3 position3DHigh;\nin vec3 position3DLow;\nin float batchId;\n"}${perInstanceAttribute ? "" : `in ${glslDatatype} ${attributeName};
`}out ${glslDatatype} ${varyingName};
void main()
{
vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow);
${perInstanceAttribute ? `${varyingName} = czm_batchTable_${attributeName}(batchId);
` : `${varyingName} = ${attributeName};
`}gl_Position = czm_modelViewProjectionRelativeToEye * p;
}`;
const fs = `in ${glslDatatype} ${varyingName};
${getColor}
void main()
{
out_FragColor = getColor();
}`;
this.material = void 0;
this.translucent = options.translucent ?? false;
this._vertexShaderSource = options.vertexShaderSource ?? vs;
this._fragmentShaderSource = options.fragmentShaderSource ?? fs;
this._renderState = Appearance_default.getDefaultRenderState(
false,
false,
options.renderState
);
this._closed = options.closed ?? false;
this._attributeName = attributeName;
this._glslDatatype = glslDatatype;
}
Object.defineProperties(DebugAppearance.prototype, {
/**
* The GLSL source code for the vertex shader.
*
* @memberof DebugAppearance.prototype
*
* @type {string}
* @readonly
*/
vertexShaderSource: {
get: function() {
return this._vertexShaderSource;
}
},
/**
* The GLSL source code for the fragment shader. The full fragment shader
* source is built procedurally taking into account the {@link DebugAppearance#material}.
* Use {@link DebugAppearance#getFragmentShaderSource} to get the full source.
*
* @memberof DebugAppearance.prototype
*
* @type {string}
* @readonly
*/
fragmentShaderSource: {
get: function() {
return this._fragmentShaderSource;
}
},
/**
* The WebGL fixed-function state to use when rendering the geometry.
*
* @memberof DebugAppearance.prototype
*
* @type {object}
* @readonly
*/
renderState: {
get: function() {
return this._renderState;
}
},
/**
* When true, the geometry is expected to be closed.
*
* @memberof DebugAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
closed: {
get: function() {
return this._closed;
}
},
/**
* The name of the attribute being visualized.
*
* @memberof DebugAppearance.prototype
*
* @type {string}
* @readonly
*/
attributeName: {
get: function() {
return this._attributeName;
}
},
/**
* The GLSL datatype of the attribute being visualized.
*
* @memberof DebugAppearance.prototype
*
* @type {string}
* @readonly
*/
glslDatatype: {
get: function() {
return this._glslDatatype;
}
}
});
DebugAppearance.prototype.getFragmentShaderSource = Appearance_default.prototype.getFragmentShaderSource;
DebugAppearance.prototype.isTranslucent = Appearance_default.prototype.isTranslucent;
DebugAppearance.prototype.getRenderState = Appearance_default.prototype.getRenderState;
var DebugAppearance_default = DebugAppearance;
// packages/engine/Source/Scene/DebugModelMatrixPrimitive.js
var import_InlineWorkers1243 = __toESM(require_InlineWorkers(), 1);
function DebugModelMatrixPrimitive(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.length = options.length ?? 1e7;
this._length = void 0;
this.width = options.width ?? 2;
this._width = void 0;
this.show = options.show ?? true;
this.modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this._modelMatrix = new Matrix4_default();
this.id = options.id;
this._id = void 0;
this._primitive = void 0;
}
DebugModelMatrixPrimitive.prototype.update = function(frameState) {
if (!this.show) {
return;
}
if (!defined_default(this._primitive) || !Matrix4_default.equals(this._modelMatrix, this.modelMatrix) || this._length !== this.length || this._width !== this.width || this._id !== this.id) {
this._modelMatrix = Matrix4_default.clone(this.modelMatrix, this._modelMatrix);
this._length = this.length;
this._width = this.width;
this._id = this.id;
if (defined_default(this._primitive)) {
this._primitive.destroy();
}
if (this.modelMatrix[12] === 0 && this.modelMatrix[13] === 0 && this.modelMatrix[14] === 0) {
this.modelMatrix[14] = 0.01;
}
const x = new GeometryInstance_default({
geometry: new PolylineGeometry_default({
positions: [Cartesian3_default.ZERO, Cartesian3_default.UNIT_X],
width: this.width,
vertexFormat: PolylineColorAppearance_default.VERTEX_FORMAT,
colors: [Color_default.RED, Color_default.RED],
arcType: ArcType_default.NONE
}),
modelMatrix: Matrix4_default.multiplyByUniformScale(
this.modelMatrix,
this.length,
new Matrix4_default()
),
id: this.id,
pickPrimitive: this
});
const y = new GeometryInstance_default({
geometry: new PolylineGeometry_default({
positions: [Cartesian3_default.ZERO, Cartesian3_default.UNIT_Y],
width: this.width,
vertexFormat: PolylineColorAppearance_default.VERTEX_FORMAT,
colors: [Color_default.GREEN, Color_default.GREEN],
arcType: ArcType_default.NONE
}),
modelMatrix: Matrix4_default.multiplyByUniformScale(
this.modelMatrix,
this.length,
new Matrix4_default()
),
id: this.id,
pickPrimitive: this
});
const z = new GeometryInstance_default({
geometry: new PolylineGeometry_default({
positions: [Cartesian3_default.ZERO, Cartesian3_default.UNIT_Z],
width: this.width,
vertexFormat: PolylineColorAppearance_default.VERTEX_FORMAT,
colors: [Color_default.BLUE, Color_default.BLUE],
arcType: ArcType_default.NONE
}),
modelMatrix: Matrix4_default.multiplyByUniformScale(
this.modelMatrix,
this.length,
new Matrix4_default()
),
id: this.id,
pickPrimitive: this
});
this._primitive = new Primitive_default({
geometryInstances: [x, y, z],
appearance: new PolylineColorAppearance_default(),
asynchronous: false
});
}
this._primitive.update(frameState);
};
DebugModelMatrixPrimitive.prototype.isDestroyed = function() {
return false;
};
DebugModelMatrixPrimitive.prototype.destroy = function() {
this._primitive = this._primitive && this._primitive.destroy();
return destroyObject_default(this);
};
var DebugModelMatrixPrimitive_default = DebugModelMatrixPrimitive;
// packages/engine/Source/Scene/DirectionalLight.js
var import_InlineWorkers1244 = __toESM(require_InlineWorkers(), 1);
function DirectionalLight(options) {
Check_default.typeOf.object("options", options);
Check_default.typeOf.object("options.direction", options.direction);
if (Cartesian3_default.equals(options.direction, Cartesian3_default.ZERO)) {
throw new DeveloperError_default("options.direction cannot be zero-length");
}
this.direction = Cartesian3_default.clone(options.direction);
this.color = Color_default.clone(options.color ?? Color_default.WHITE);
this.intensity = options.intensity ?? 1;
}
var DirectionalLight_default = DirectionalLight;
// packages/engine/Source/Scene/EllipsoidSurfaceAppearance.js
var import_InlineWorkers1247 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceFS.js
var import_InlineWorkers1245 = __toESM(require_InlineWorkers(), 1);
var EllipsoidSurfaceAppearanceFS_default = "in vec3 v_positionMC;\nin vec3 v_positionEC;\nin vec2 v_st;\n\nvoid main()\n{\n czm_materialInput materialInput;\n\n vec3 normalEC = normalize(czm_normal3D * czm_geodeticSurfaceNormal(v_positionMC, vec3(0.0), vec3(1.0)));\n#ifdef FACE_FORWARD\n normalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\n#endif\n\n materialInput.s = v_st.s;\n materialInput.st = v_st;\n materialInput.str = vec3(v_st, 0.0);\n\n // Convert tangent space material normal to eye space\n materialInput.normalEC = normalEC;\n materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(v_positionMC, materialInput.normalEC);\n\n // Convert view vector to world space\n vec3 positionToEyeEC = -v_positionEC;\n materialInput.positionToEyeEC = positionToEyeEC;\n\n czm_material material = czm_getMaterial(materialInput);\n\n#ifdef FLAT\n out_FragColor = vec4(material.diffuse + material.emission, material.alpha);\n#else\n out_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\n#endif\n}\n";
// packages/engine/Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.js
var import_InlineWorkers1246 = __toESM(require_InlineWorkers(), 1);
var EllipsoidSurfaceAppearanceVS_default = "in vec3 position3DHigh;\nin vec3 position3DLow;\nin vec2 st;\nin float batchId;\n\nout vec3 v_positionMC;\nout vec3 v_positionEC;\nout vec2 v_st;\n\nvoid main()\n{\n vec4 p = czm_computePosition();\n\n v_positionMC = position3DHigh + position3DLow; // position in model coordinates\n v_positionEC = (czm_modelViewRelativeToEye * p).xyz; // position in eye coordinates\n v_st = st;\n\n gl_Position = czm_modelViewProjectionRelativeToEye * p;\n}\n";
// packages/engine/Source/Scene/EllipsoidSurfaceAppearance.js
function EllipsoidSurfaceAppearance(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const translucent = options.translucent ?? true;
const aboveGround = options.aboveGround ?? false;
this.material = defined_default(options.material) ? options.material : Material_default.fromType(Material_default.ColorType);
this.translucent = options.translucent ?? true;
this._vertexShaderSource = options.vertexShaderSource ?? EllipsoidSurfaceAppearanceVS_default;
this._fragmentShaderSource = options.fragmentShaderSource ?? EllipsoidSurfaceAppearanceFS_default;
this._renderState = Appearance_default.getDefaultRenderState(
translucent,
!aboveGround,
options.renderState
);
this._closed = false;
this._flat = options.flat ?? false;
this._faceForward = options.faceForward ?? aboveGround;
this._aboveGround = aboveGround;
}
Object.defineProperties(EllipsoidSurfaceAppearance.prototype, {
/**
* The GLSL source code for the vertex shader.
*
* @memberof EllipsoidSurfaceAppearance.prototype
*
* @type {string}
* @readonly
*/
vertexShaderSource: {
get: function() {
return this._vertexShaderSource;
}
},
/**
* The GLSL source code for the fragment shader. The full fragment shader
* source is built procedurally taking into account {@link EllipsoidSurfaceAppearance#material},
* {@link EllipsoidSurfaceAppearance#flat}, and {@link EllipsoidSurfaceAppearance#faceForward}.
* Use {@link EllipsoidSurfaceAppearance#getFragmentShaderSource} to get the full source.
*
* @memberof EllipsoidSurfaceAppearance.prototype
*
* @type {string}
* @readonly
*/
fragmentShaderSource: {
get: function() {
return this._fragmentShaderSource;
}
},
/**
* The WebGL fixed-function state to use when rendering the geometry.
*
* The render state can be explicitly defined when constructing a {@link EllipsoidSurfaceAppearance}
* instance, or it is set implicitly via {@link EllipsoidSurfaceAppearance#translucent}
* and {@link EllipsoidSurfaceAppearance#aboveGround}.
*
*
* @memberof EllipsoidSurfaceAppearance.prototype
*
* @type {object}
* @readonly
*/
renderState: {
get: function() {
return this._renderState;
}
},
/**
* When true, the geometry is expected to be closed so
* {@link EllipsoidSurfaceAppearance#renderState} has backface culling enabled.
* If the viewer enters the geometry, it will not be visible.
*
* @memberof EllipsoidSurfaceAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
closed: {
get: function() {
return this._closed;
}
},
/**
* The {@link VertexFormat} that this appearance instance is compatible with.
* A geometry can have more vertex attributes and still be compatible - at a
* potential performance cost - but it can't have less.
*
* @memberof EllipsoidSurfaceAppearance.prototype
*
* @type VertexFormat
* @readonly
*
* @default {@link EllipsoidSurfaceAppearance.VERTEX_FORMAT}
*/
vertexFormat: {
get: function() {
return EllipsoidSurfaceAppearance.VERTEX_FORMAT;
}
},
/**
* When true, flat shading is used in the fragment shader,
* which means lighting is not taking into account.
*
* @memberof EllipsoidSurfaceAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
flat: {
get: function() {
return this._flat;
}
},
/**
* When true, the fragment shader flips the surface normal
* as needed to ensure that the normal faces the viewer to avoid
* dark spots. This is useful when both sides of a geometry should be
* shaded like {@link WallGeometry}.
*
* @memberof EllipsoidSurfaceAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default true
*/
faceForward: {
get: function() {
return this._faceForward;
}
},
/**
* When true, the geometry is expected to be on the ellipsoid's
* surface - not at a constant height above it - so {@link EllipsoidSurfaceAppearance#renderState}
* has backface culling enabled.
*
*
* @memberof EllipsoidSurfaceAppearance.prototype
*
* @type {boolean}
* @readonly
*
* @default false
*/
aboveGround: {
get: function() {
return this._aboveGround;
}
}
});
EllipsoidSurfaceAppearance.VERTEX_FORMAT = VertexFormat_default.POSITION_AND_ST;
EllipsoidSurfaceAppearance.prototype.getFragmentShaderSource = Appearance_default.prototype.getFragmentShaderSource;
EllipsoidSurfaceAppearance.prototype.isTranslucent = Appearance_default.prototype.isTranslucent;
EllipsoidSurfaceAppearance.prototype.getRenderState = Appearance_default.prototype.getRenderState;
var EllipsoidSurfaceAppearance_default = EllipsoidSurfaceAppearance;
// packages/engine/Source/Scene/FrameRateMonitor.js
var import_InlineWorkers1248 = __toESM(require_InlineWorkers(), 1);
function FrameRateMonitor(options) {
if (!defined_default(options) || !defined_default(options.scene)) {
throw new DeveloperError_default("options.scene is required.");
}
this._scene = options.scene;
this.samplingWindow = options.samplingWindow ?? FrameRateMonitor.defaultSettings.samplingWindow;
this.quietPeriod = options.quietPeriod ?? FrameRateMonitor.defaultSettings.quietPeriod;
this.warmupPeriod = options.warmupPeriod ?? FrameRateMonitor.defaultSettings.warmupPeriod;
this.minimumFrameRateDuringWarmup = options.minimumFrameRateDuringWarmup ?? FrameRateMonitor.defaultSettings.minimumFrameRateDuringWarmup;
this.minimumFrameRateAfterWarmup = options.minimumFrameRateAfterWarmup ?? FrameRateMonitor.defaultSettings.minimumFrameRateAfterWarmup;
this._lowFrameRate = new Event_default();
this._nominalFrameRate = new Event_default();
this._frameTimes = [];
this._needsQuietPeriod = true;
this._quietPeriodEndTime = 0;
this._warmupPeriodEndTime = 0;
this._frameRateIsLow = false;
this._lastFramesPerSecond = void 0;
this._pauseCount = 0;
const that = this;
this._preUpdateRemoveListener = this._scene.preUpdate.addEventListener(
function(scene, time) {
update7(that, time);
}
);
this._hiddenPropertyName = document.hidden !== void 0 ? "hidden" : document.mozHidden !== void 0 ? "mozHidden" : document.msHidden !== void 0 ? "msHidden" : document.webkitHidden !== void 0 ? "webkitHidden" : void 0;
const visibilityChangeEventName = document.hidden !== void 0 ? "visibilitychange" : document.mozHidden !== void 0 ? "mozvisibilitychange" : document.msHidden !== void 0 ? "msvisibilitychange" : document.webkitHidden !== void 0 ? "webkitvisibilitychange" : void 0;
function visibilityChangeListener() {
visibilityChanged(that);
}
this._visibilityChangeRemoveListener = void 0;
if (defined_default(visibilityChangeEventName)) {
document.addEventListener(
visibilityChangeEventName,
visibilityChangeListener,
false
);
this._visibilityChangeRemoveListener = function() {
document.removeEventListener(
visibilityChangeEventName,
visibilityChangeListener,
false
);
};
}
}
FrameRateMonitor.defaultSettings = {
samplingWindow: 5,
quietPeriod: 2,
warmupPeriod: 5,
minimumFrameRateDuringWarmup: 4,
minimumFrameRateAfterWarmup: 8
};
FrameRateMonitor.fromScene = function(scene) {
if (!defined_default(scene)) {
throw new DeveloperError_default("scene is required.");
}
if (!defined_default(scene._frameRateMonitor) || scene._frameRateMonitor.isDestroyed()) {
scene._frameRateMonitor = new FrameRateMonitor({
scene
});
}
return scene._frameRateMonitor;
};
Object.defineProperties(FrameRateMonitor.prototype, {
/**
* Gets the {@link Scene} instance for which to monitor performance.
* @memberof FrameRateMonitor.prototype
* @type {Scene}
*/
scene: {
get: function() {
return this._scene;
}
},
/**
* Gets the event that is raised when a low frame rate is detected. The function will be passed
* the {@link Scene} instance as its first parameter and the average number of frames per second
* over the sampling window as its second parameter.
* @memberof FrameRateMonitor.prototype
* @type {Event}
*/
lowFrameRate: {
get: function() {
return this._lowFrameRate;
}
},
/**
* Gets the event that is raised when the frame rate returns to a normal level after having been low.
* The function will be passed the {@link Scene} instance as its first parameter and the average
* number of frames per second over the sampling window as its second parameter.
* @memberof FrameRateMonitor.prototype
* @type {Event}
*/
nominalFrameRate: {
get: function() {
return this._nominalFrameRate;
}
},
/**
* Gets the most recently computed average frames-per-second over the last samplingWindow.
* This property may be undefined if the frame rate has not been computed.
* @memberof FrameRateMonitor.prototype
* @type {number}
*/
lastFramesPerSecond: {
get: function() {
return this._lastFramesPerSecond;
}
}
});
FrameRateMonitor.prototype.pause = function() {
++this._pauseCount;
if (this._pauseCount === 1) {
this._frameTimes.length = 0;
this._lastFramesPerSecond = void 0;
}
};
FrameRateMonitor.prototype.unpause = function() {
--this._pauseCount;
if (this._pauseCount <= 0) {
this._pauseCount = 0;
this._needsQuietPeriod = true;
}
};
FrameRateMonitor.prototype.isDestroyed = function() {
return false;
};
FrameRateMonitor.prototype.destroy = function() {
this._preUpdateRemoveListener();
if (defined_default(this._visibilityChangeRemoveListener)) {
this._visibilityChangeRemoveListener();
}
return destroyObject_default(this);
};
function update7(monitor, time) {
if (monitor._pauseCount > 0) {
return;
}
const timeStamp = getTimestamp_default();
if (monitor._needsQuietPeriod) {
monitor._needsQuietPeriod = false;
monitor._frameTimes.length = 0;
monitor._quietPeriodEndTime = timeStamp + monitor.quietPeriod / TimeConstants_default.SECONDS_PER_MILLISECOND;
monitor._warmupPeriodEndTime = monitor._quietPeriodEndTime + (monitor.warmupPeriod + monitor.samplingWindow) / TimeConstants_default.SECONDS_PER_MILLISECOND;
} else if (timeStamp >= monitor._quietPeriodEndTime) {
monitor._frameTimes.push(timeStamp);
const beginningOfWindow = timeStamp - monitor.samplingWindow / TimeConstants_default.SECONDS_PER_MILLISECOND;
if (monitor._frameTimes.length >= 2 && monitor._frameTimes[0] <= beginningOfWindow) {
while (monitor._frameTimes.length >= 2 && monitor._frameTimes[1] < beginningOfWindow) {
monitor._frameTimes.shift();
}
const averageTimeBetweenFrames = (timeStamp - monitor._frameTimes[0]) / (monitor._frameTimes.length - 1);
monitor._lastFramesPerSecond = 1e3 / averageTimeBetweenFrames;
const maximumFrameTime = 1e3 / (timeStamp > monitor._warmupPeriodEndTime ? monitor.minimumFrameRateAfterWarmup : monitor.minimumFrameRateDuringWarmup);
if (averageTimeBetweenFrames > maximumFrameTime) {
if (!monitor._frameRateIsLow) {
monitor._frameRateIsLow = true;
monitor._needsQuietPeriod = true;
monitor.lowFrameRate.raiseEvent(
monitor.scene,
monitor._lastFramesPerSecond
);
}
} else if (monitor._frameRateIsLow) {
monitor._frameRateIsLow = false;
monitor._needsQuietPeriod = true;
monitor.nominalFrameRate.raiseEvent(
monitor.scene,
monitor._lastFramesPerSecond
);
}
}
}
}
function visibilityChanged(monitor) {
if (document[monitor._hiddenPropertyName]) {
monitor.pause();
} else {
monitor.unpause();
}
}
var FrameRateMonitor_default = FrameRateMonitor;
// packages/engine/Source/Scene/GoogleEarthEnterpriseImageryProvider.js
var import_InlineWorkers1249 = __toESM(require_InlineWorkers(), 1);
var protobuf2 = __toESM(require_protobuf(), 1);
function GoogleEarthEnterpriseDiscardPolicy() {
this._image = new Image();
}
GoogleEarthEnterpriseDiscardPolicy.prototype.isReady = function() {
return true;
};
GoogleEarthEnterpriseDiscardPolicy.prototype.shouldDiscardImage = function(image) {
return image === this._image;
};
function GoogleEarthEnterpriseImageryProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._defaultAlpha = void 0;
this._defaultNightAlpha = void 0;
this._defaultDayAlpha = void 0;
this._defaultBrightness = void 0;
this._defaultContrast = void 0;
this._defaultHue = void 0;
this._defaultSaturation = void 0;
this._defaultGamma = void 0;
this._defaultMinificationFilter = void 0;
this._defaultMagnificationFilter = void 0;
this._tileDiscardPolicy = options.tileDiscardPolicy;
this._tilingScheme = new GeographicTilingScheme_default({
numberOfLevelZeroTilesX: 2,
numberOfLevelZeroTilesY: 2,
rectangle: new Rectangle_default(
-Math_default.PI,
-Math_default.PI,
Math_default.PI,
Math_default.PI
),
ellipsoid: options.ellipsoid
});
let credit = options.credit;
if (typeof credit === "string") {
credit = new Credit_default(credit);
}
this._credit = credit;
this._tileWidth = 256;
this._tileHeight = 256;
this._maximumLevel = 23;
if (!defined_default(this._tileDiscardPolicy)) {
this._tileDiscardPolicy = new GoogleEarthEnterpriseDiscardPolicy();
}
this._errorEvent = new Event_default();
}
Object.defineProperties(GoogleEarthEnterpriseImageryProvider.prototype, {
/**
* Gets the name of the Google Earth Enterprise server url hosting the imagery.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {string}
* @readonly
*/
url: {
get: function() {
return this._metadata.url;
}
},
/**
* Gets the proxy used by this provider.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {Proxy}
* @readonly
*/
proxy: {
get: function() {
return this._metadata.proxy;
}
},
/**
* Gets the width of each tile, in pixels.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {number}
* @readonly
*/
tileWidth: {
get: function() {
return this._tileWidth;
}
},
/**
* Gets the height of each tile, in pixels.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {number}
* @readonly
*/
tileHeight: {
get: function() {
return this._tileHeight;
}
},
/**
* Gets the maximum level-of-detail that can be requested.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {number|undefined}
* @readonly
*/
maximumLevel: {
get: function() {
return this._maximumLevel;
}
},
/**
* Gets the minimum level-of-detail that can be requested.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {number}
* @readonly
*/
minimumLevel: {
get: function() {
return 0;
}
},
/**
* Gets the tiling scheme used by this provider.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {TilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._tilingScheme;
}
},
/**
* Gets the rectangle, in radians, of the imagery provided by this instance.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {Rectangle}
* @readonly
*/
rectangle: {
get: function() {
return this._tilingScheme.rectangle;
}
},
/**
* Gets the tile discard policy. If not undefined, the discard policy is responsible
* for filtering out "missing" tiles via its shouldDiscardImage function. If this function
* returns undefined, no tiles are filtered.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {TileDiscardPolicy}
* @readonly
*/
tileDiscardPolicy: {
get: function() {
return this._tileDiscardPolicy;
}
},
/**
* Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets the credit to display when this imagery provider is active. Typically this is used to credit
* the source of the imagery.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return this._credit;
}
},
/**
* Gets a value indicating whether or not the images provided by this imagery provider
* include an alpha channel. If this property is false, an alpha channel, if present, will
* be ignored. If this property is true, any images without an alpha channel will be treated
* as if their alpha is 1.0 everywhere. Setting this property to false reduces memory usage
* and texture upload time.
* @memberof GoogleEarthEnterpriseImageryProvider.prototype
* @type {boolean}
* @readonly
*/
hasAlphaChannel: {
get: function() {
return false;
}
}
});
GoogleEarthEnterpriseImageryProvider.fromMetadata = function(metadata, options) {
Check_default.defined("metadata", metadata);
if (!metadata.imageryPresent) {
throw new RuntimeError_default(`The server ${metadata.url} doesn't have imagery`);
}
const provider = new GoogleEarthEnterpriseImageryProvider(options);
provider._metadata = metadata;
return provider;
};
GoogleEarthEnterpriseImageryProvider.prototype.getTileCredits = function(x, y, level) {
const metadata = this._metadata;
const info = metadata.getTileInformation(x, y, level);
if (defined_default(info)) {
const credit = metadata.providers[info.imageryProvider];
if (defined_default(credit)) {
return [credit];
}
}
return void 0;
};
GoogleEarthEnterpriseImageryProvider.prototype.requestImage = function(x, y, level, request) {
const invalidImage = this._tileDiscardPolicy._image;
const metadata = this._metadata;
const quadKey = GoogleEarthEnterpriseMetadata_default.tileXYToQuadKey(x, y, level);
const info = metadata.getTileInformation(x, y, level);
if (!defined_default(info)) {
if (metadata.isValid(quadKey)) {
const metadataRequest = new Request_default({
throttle: request.throttle,
throttleByServer: request.throttleByServer,
type: request.type,
priorityFunction: request.priorityFunction
});
metadata.populateSubtree(x, y, level, metadataRequest);
return void 0;
}
return Promise.resolve(invalidImage);
}
if (!info.hasImagery()) {
return Promise.resolve(invalidImage);
}
const promise = buildImageResource4(
this,
info,
x,
y,
level,
request
).fetchArrayBuffer();
if (!defined_default(promise)) {
return void 0;
}
return promise.then(function(image) {
decodeGoogleEarthEnterpriseData_default(metadata.key, image);
let a3 = new Uint8Array(image);
let type;
const protoImagery = metadata.protoImagery;
if (!defined_default(protoImagery) || !protoImagery) {
type = getImageType(a3);
}
if (!defined_default(type) && (!defined_default(protoImagery) || protoImagery)) {
const message = decodeEarthImageryPacket(a3);
type = message.imageType;
a3 = message.imageData;
}
if (!defined_default(type) || !defined_default(a3)) {
return invalidImage;
}
return loadImageFromTypedArray_default({
uint8Array: a3,
format: type,
flipY: true
});
});
};
GoogleEarthEnterpriseImageryProvider.prototype.pickFeatures = function(x, y, level, longitude, latitude) {
return void 0;
};
function buildImageResource4(imageryProvider, info, x, y, level, request) {
const quadKey = GoogleEarthEnterpriseMetadata_default.tileXYToQuadKey(x, y, level);
let version2 = info.imageryVersion;
version2 = defined_default(version2) && version2 > 0 ? version2 : 1;
return imageryProvider._metadata.resource.getDerivedResource({
url: `flatfile?f1-0${quadKey}-i.${version2.toString()}`,
request
});
}
function getImageType(image) {
const jpeg = "JFIF";
if (image[6] === jpeg.charCodeAt(0) && image[7] === jpeg.charCodeAt(1) && image[8] === jpeg.charCodeAt(2) && image[9] === jpeg.charCodeAt(3)) {
return "image/jpeg";
}
const png = "PNG";
if (image[1] === png.charCodeAt(0) && image[2] === png.charCodeAt(1) && image[3] === png.charCodeAt(2)) {
return "image/png";
}
return void 0;
}
function decodeEarthImageryPacket(data) {
const reader = protobuf2.Reader.create(data);
const end = reader.len;
const message = {};
while (reader.pos < end) {
const tag = reader.uint32();
let copyrightIds;
switch (tag >>> 3) {
case 1:
message.imageType = reader.uint32();
break;
case 2:
message.imageData = reader.bytes();
break;
case 3:
message.alphaType = reader.uint32();
break;
case 4:
message.imageAlpha = reader.bytes();
break;
case 5:
copyrightIds = message.copyrightIds;
if (!defined_default(copyrightIds)) {
copyrightIds = message.copyrightIds = [];
}
if ((tag & 7) === 2) {
const end2 = reader.uint32() + reader.pos;
while (reader.pos < end2) {
copyrightIds.push(reader.uint32());
}
} else {
copyrightIds.push(reader.uint32());
}
break;
default:
reader.skipType(tag & 7);
break;
}
}
const imageType = message.imageType;
if (defined_default(imageType)) {
switch (imageType) {
case 0:
message.imageType = "image/jpeg";
break;
case 4:
message.imageType = "image/png";
break;
default:
throw new RuntimeError_default(
"GoogleEarthEnterpriseImageryProvider: Unsupported image type."
);
}
}
const alphaType = message.alphaType;
if (defined_default(alphaType) && alphaType !== 0) {
console.log(
"GoogleEarthEnterpriseImageryProvider: External alpha not supported."
);
delete message.alphaType;
delete message.imageAlpha;
}
return message;
}
var GoogleEarthEnterpriseImageryProvider_default = GoogleEarthEnterpriseImageryProvider;
// packages/engine/Source/Scene/GridImageryProvider.js
var import_InlineWorkers1250 = __toESM(require_InlineWorkers(), 1);
var defaultColor9 = new Color_default(1, 1, 1, 0.4);
var defaultGlowColor = new Color_default(0, 1, 0, 0.05);
var defaultBackgroundColor3 = new Color_default(0, 0.5, 0, 0.2);
function GridImageryProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._defaultAlpha = void 0;
this._defaultNightAlpha = void 0;
this._defaultDayAlpha = void 0;
this._defaultBrightness = void 0;
this._defaultContrast = void 0;
this._defaultHue = void 0;
this._defaultSaturation = void 0;
this._defaultGamma = void 0;
this._defaultMinificationFilter = void 0;
this._defaultMagnificationFilter = void 0;
this._tilingScheme = defined_default(options.tilingScheme) ? options.tilingScheme : new GeographicTilingScheme_default({ ellipsoid: options.ellipsoid });
this._cells = options.cells ?? 8;
this._color = options.color ?? defaultColor9;
this._glowColor = options.glowColor ?? defaultGlowColor;
this._glowWidth = options.glowWidth ?? 6;
this._backgroundColor = options.backgroundColor ?? defaultBackgroundColor3;
this._errorEvent = new Event_default();
this._tileWidth = options.tileWidth ?? 256;
this._tileHeight = options.tileHeight ?? 256;
this._canvasSize = options.canvasSize ?? 256;
this._canvas = this._createGridCanvas();
}
Object.defineProperties(GridImageryProvider.prototype, {
/**
* Gets the proxy used by this provider.
* @memberof GridImageryProvider.prototype
* @type {Proxy}
* @readonly
*/
proxy: {
get: function() {
return void 0;
}
},
/**
* Gets the width of each tile, in pixels.
* @memberof GridImageryProvider.prototype
* @type {number}
* @readonly
*/
tileWidth: {
get: function() {
return this._tileWidth;
}
},
/**
* Gets the height of each tile, in pixels.
* @memberof GridImageryProvider.prototype
* @type {number}
* @readonly
*/
tileHeight: {
get: function() {
return this._tileHeight;
}
},
/**
* Gets the maximum level-of-detail that can be requested.
* @memberof GridImageryProvider.prototype
* @type {number|undefined}
* @readonly
*/
maximumLevel: {
get: function() {
return void 0;
}
},
/**
* Gets the minimum level-of-detail that can be requested.
* @memberof GridImageryProvider.prototype
* @type {number}
* @readonly
*/
minimumLevel: {
get: function() {
return void 0;
}
},
/**
* Gets the tiling scheme used by this provider.
* @memberof GridImageryProvider.prototype
* @type {TilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._tilingScheme;
}
},
/**
* Gets the rectangle, in radians, of the imagery provided by this instance.
* @memberof GridImageryProvider.prototype
* @type {Rectangle}
* @readonly
*/
rectangle: {
get: function() {
return this._tilingScheme.rectangle;
}
},
/**
* Gets the tile discard policy. If not undefined, the discard policy is responsible
* for filtering out "missing" tiles via its shouldDiscardImage function. If this function
* returns undefined, no tiles are filtered.
* @memberof GridImageryProvider.prototype
* @type {TileDiscardPolicy}
* @readonly
*/
tileDiscardPolicy: {
get: function() {
return void 0;
}
},
/**
* Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof GridImageryProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets the credit to display when this imagery provider is active. Typically this is used to credit
* the source of the imagery.
* @memberof GridImageryProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return void 0;
}
},
/**
* Gets a value indicating whether or not the images provided by this imagery provider
* include an alpha channel. If this property is false, an alpha channel, if present, will
* be ignored. If this property is true, any images without an alpha channel will be treated
* as if their alpha is 1.0 everywhere. When this property is false, memory usage
* and texture upload time are reduced.
* @memberof GridImageryProvider.prototype
* @type {boolean}
* @readonly
*/
hasAlphaChannel: {
get: function() {
return true;
}
}
});
GridImageryProvider.prototype._drawGrid = function(context) {
const minPixel = 0;
const maxPixel = this._canvasSize;
for (let x = 0; x <= this._cells; ++x) {
const nx = x / this._cells;
const val = 1 + nx * (maxPixel - 1);
context.moveTo(val, minPixel);
context.lineTo(val, maxPixel);
context.moveTo(minPixel, val);
context.lineTo(maxPixel, val);
}
context.stroke();
};
GridImageryProvider.prototype._createGridCanvas = function() {
const canvas = document.createElement("canvas");
canvas.width = this._canvasSize;
canvas.height = this._canvasSize;
const minPixel = 0;
const maxPixel = this._canvasSize;
const context = canvas.getContext("2d");
const cssBackgroundColor = this._backgroundColor.toCssColorString();
context.fillStyle = cssBackgroundColor;
context.fillRect(minPixel, minPixel, maxPixel, maxPixel);
const cssGlowColor = this._glowColor.toCssColorString();
context.strokeStyle = cssGlowColor;
context.lineWidth = this._glowWidth;
context.strokeRect(minPixel, minPixel, maxPixel, maxPixel);
this._drawGrid(context);
context.lineWidth = this._glowWidth * 0.5;
context.strokeRect(minPixel, minPixel, maxPixel, maxPixel);
this._drawGrid(context);
const cssColor = this._color.toCssColorString();
context.strokeStyle = cssColor;
context.lineWidth = 2;
context.strokeRect(minPixel, minPixel, maxPixel, maxPixel);
context.lineWidth = 1;
this._drawGrid(context);
return canvas;
};
GridImageryProvider.prototype.getTileCredits = function(x, y, level) {
return void 0;
};
GridImageryProvider.prototype.requestImage = function(x, y, level, request) {
return Promise.resolve(this._canvas);
};
GridImageryProvider.prototype.pickFeatures = function(x, y, level, longitude, latitude) {
return void 0;
};
var GridImageryProvider_default = GridImageryProvider;
// packages/engine/Source/Scene/I3SDataProvider.js
var import_InlineWorkers1260 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/I3SLayer.js
var import_InlineWorkers1257 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/I3SNode.js
var import_InlineWorkers1255 = __toESM(require_InlineWorkers(), 1);
// packages/engine/Source/Scene/I3SDecoder.js
var import_InlineWorkers1251 = __toESM(require_InlineWorkers(), 1);
function I3SDecoder() {
}
I3SDecoder._maxDecodingConcurrency = Math.max(
FeatureDetection_default.hardwareConcurrency - 1,
1
);
I3SDecoder._decodeTaskProcessor = new TaskProcessor_default(
"decodeI3S",
I3SDecoder._maxDecodingConcurrency
);
I3SDecoder._promise = void 0;
async function initializeDecoder() {
const result = await I3SDecoder._decodeTaskProcessor.initWebAssemblyModule({
wasmBinaryFile: "ThirdParty/draco_decoder.wasm"
});
if (result) {
return I3SDecoder._decodeTaskProcessor;
}
throw new RuntimeError_default("I3S decoder could not be initialized.");
}
I3SDecoder.decode = async function(url2, defaultGeometrySchema, geometryData, featureData, symbologyData) {
Check_default.typeOf.string("url", url2);
Check_default.defined("defaultGeometrySchema", defaultGeometrySchema);
Check_default.defined("geometryData", geometryData);
if (!defined_default(I3SDecoder._promise)) {
I3SDecoder._promise = initializeDecoder();
}
return I3SDecoder._promise.then(function(taskProcessor3) {
const parentData = geometryData._parent._data;
const parentRotationInverseMatrix = geometryData._parent._inverseRotationMatrix;
let longitude = 0;
let latitude = 0;
let height = 0;
if (defined_default(parentData.obb)) {
longitude = parentData.obb.center[0];
latitude = parentData.obb.center[1];
height = parentData.obb.center[2];
} else if (defined_default(parentData.mbs)) {
longitude = parentData.mbs[0];
latitude = parentData.mbs[1];
height = parentData.mbs[2];
}
const axisFlipRotation = Matrix3_default.fromRotationX(-Math_default.PI_OVER_TWO);
const parentRotation = new Matrix3_default();
Matrix3_default.multiply(
axisFlipRotation,
parentRotationInverseMatrix,
parentRotation
);
const cartographicCenter = Cartographic_default.fromDegrees(
longitude,
latitude,
height
);
const cartesianCenter = Ellipsoid_default.WGS84.cartographicToCartesian(cartographicCenter);
const payload = {
binaryData: geometryData._data,
featureData: defined_default(featureData) && defined_default(featureData[0]) ? featureData[0].data : void 0,
schema: defaultGeometrySchema,
bufferInfo: geometryData._geometryBufferInfo,
ellipsoidRadiiSquare: Ellipsoid_default.WGS84.radiiSquared,
url: url2,
geoidDataList: geometryData._dataProvider._geoidDataList,
cartographicCenter,
cartesianCenter,
parentRotation,
enableFeatures: geometryData._dataProvider.showFeatures,
splitGeometryByColorTransparency: geometryData._dataProvider.adjustMaterialAlphaMode,
symbologyData,
calculateNormals: geometryData._dataProvider.calculateNormals
};
return taskProcessor3.scheduleTask(payload);
});
};
var I3SDecoder_default = I3SDecoder;
// packages/engine/Source/Scene/I3SFeature.js
var import_InlineWorkers1252 = __toESM(require_InlineWorkers(), 1);
function I3SFeature(parent, uri) {
this._parent = parent;
this._dataProvider = parent._dataProvider;
this._layer = parent._layer;
if (defined_default(this._parent._nodeIndex)) {
this._resource = this._parent._layer.resource.getDerivedResource({
url: `nodes/${this._parent._data.mesh.attribute.resource}/${uri}`
});
} else {
this._resource = this._parent.resource.getDerivedResource({ url: uri });
}
}
Object.defineProperties(I3SFeature.prototype, {
/**
* Gets the resource for the feature
* @memberof I3SFeature.prototype
* @type {Resource}
* @readonly
*/
resource: {
get: function() {
return this._resource;
}
},
/**
* Gets the I3S data for this object.
* @memberof I3SFeature.prototype
* @type {object}
* @readonly
*/
data: {
get: function() {
return this._data;
}
}
});
I3SFeature.prototype.load = async function() {
this._data = await I3SDataProvider_default.loadJson(this._resource);
return this._data;
};
var I3SFeature_default = I3SFeature;
// packages/engine/Source/Scene/I3SField.js
var import_InlineWorkers1253 = __toESM(require_InlineWorkers(), 1);
function I3SField(parent, storageInfo) {
this._storageInfo = storageInfo;
this._parent = parent;
this._dataProvider = parent._dataProvider;
this._loadPromise = void 0;
const uri = `attributes/${storageInfo.key}/0`;
if (defined_default(this._parent._nodeIndex)) {
this._resource = this._parent._layer.resource.getDerivedResource({
url: `nodes/${this._parent._data.mesh.attribute.resource}/${uri}`
});
} else {
this._resource = this._parent.resource.getDerivedResource({ url: uri });
}
}
Object.defineProperties(I3SField.prototype, {
/**
* Gets the resource for the fields
* @memberof I3SField.prototype
* @type {Resource}
* @readonly
*/
resource: {
get: function() {
return this._resource;
}
},
/**
* Gets the header for this field.
* @memberof I3SField.prototype
* @type {object}
* @readonly
*/
header: {
get: function() {
return this._header;
}
},
/**
* Gets the values for this field.
* @memberof I3SField.prototype
* @type {object}
* @readonly
*/
values: {
get: function() {
if (defined_default(this._values)) {
if (defined_default(this._values.attributeValues)) {
return this._values.attributeValues;
}
if (defined_default(this._values.objectIds)) {
return this._values.objectIds;
}
}
return [];
}
},
/**
* Gets the name for the field.
* @memberof I3SField.prototype
* @type {string}
* @readonly
*/
name: {
get: function() {
return this._storageInfo.name;
}
}
});
function getNumericTypeSize(type) {
if (type === "UInt8" || type === "Int8") {
return 1;
} else if (type === "UInt16" || type === "Int16") {
return 2;
} else if (type === "UInt32" || type === "Int32" || type === "Oid32" || type === "Float32") {
return 4;
} else if (type === "UInt64" || type === "Int64" || type === "Float64") {
return 8;
}
return 0;
}
function getValueTypeSize(type) {
if (type === "String") {
return 1;
}
return getNumericTypeSize(type);
}
async function load5(field) {
const data = await field._dataProvider._loadBinary(field._resource);
const dataView = new DataView(data);
field._data = data;
field._validateHeader(dataView);
const headerSize = field._parseHeader(dataView);
const offset = field._getBodyOffset(headerSize);
field._validateBody(dataView, offset);
field._parseBody(dataView, offset);
}
I3SField.prototype.load = function() {
if (defined_default(this._loadPromise)) {
return this._loadPromise;
}
this._loadPromise = load5(this).catch(function(error) {
console.error(error);
});
return this._loadPromise;
};
I3SField.prototype._parseValue = function(dataView, type, offset) {
let value;
if (type === "UInt8") {
value = dataView.getUint8(offset);
offset += 1;
} else if (type === "Int8") {
value = dataView.getInt8(offset);
offset += 1;
} else if (type === "UInt16") {
value = dataView.getUint16(offset, true);
offset += 2;
} else if (type === "Int16") {
value = dataView.getInt16(offset, true);
offset += 2;
} else if (type === "UInt32") {
value = dataView.getUint32(offset, true);
offset += 4;
} else if (type === "Oid32") {
value = dataView.getUint32(offset, true);
offset += 4;
} else if (type === "Int32") {
value = dataView.getInt32(offset, true);
offset += 4;
} else if (type === "UInt64") {
const left = dataView.getUint32(offset, true);
const right = dataView.getUint32(offset + 4, true);
value = left + Math.pow(2, 32) * right;
offset += 8;
} else if (type === "Int64") {
const left = dataView.getUint32(offset, true);
const right = dataView.getUint32(offset + 4, true);
if (right < Math.pow(2, 31)) {
value = left + Math.pow(2, 32) * right;
} else {
value = left + Math.pow(2, 32) * (right - Math.pow(2, 32));
}
offset += 8;
} else if (type === "Float32") {
value = dataView.getFloat32(offset, true);
offset += 4;
} else if (type === "Float64") {
value = dataView.getFloat64(offset, true);
offset += 8;
} else if (type === "String") {
value = String.fromCharCode(dataView.getUint8(offset));
offset += 1;
}
return {
value,
offset
};
};
I3SField.prototype._parseHeader = function(dataView) {
let offset = 0;
this._header = {};
for (let itemIndex = 0; itemIndex < this._storageInfo.header.length; itemIndex++) {
const item = this._storageInfo.header[itemIndex];
const parsedValue = this._parseValue(dataView, item.valueType, offset);
this._header[item.property] = parsedValue.value;
offset = parsedValue.offset;
}
return offset;
};
I3SField.prototype._parseBody = function(dataView, offset) {
this._values = {};
for (let itemIndex = 0; itemIndex < this._storageInfo.ordering.length; itemIndex++) {
const orderingValue = this._storageInfo.ordering[itemIndex];
const item = orderingValue === "ObjectIds" ? "objectIds" : orderingValue;
const desc = this._storageInfo[item];
if (defined_default(desc)) {
this._values[item] = [];
for (let index = 0; index < this._header.count; ++index) {
if (desc.valueType !== "String") {
const parsedValue = this._parseValue(
dataView,
desc.valueType,
offset
);
this._values[item].push(parsedValue.value);
offset = parsedValue.offset;
} else {
const stringLen = this._values.attributeByteCounts[index];
let stringContent = "";
for (let cIndex = 0; cIndex < stringLen; ++cIndex) {
const curParsedValue = this._parseValue(
dataView,
desc.valueType,
offset
);
if (curParsedValue.value.charCodeAt(0) !== 0) {
stringContent += curParsedValue.value;
}
offset = curParsedValue.offset;
}
this._values[item].push(stringContent);
}
}
}
}
};
I3SField.prototype._getBodyOffset = function(headerSize) {
let valueSize = 0;
if (defined_default(this._storageInfo.attributeValues)) {
valueSize = getNumericTypeSize(this._storageInfo.attributeValues.valueType);
} else if (defined_default(this._storageInfo.objectIds)) {
valueSize = getNumericTypeSize(this._storageInfo.objectIds.valueType);
}
if (valueSize > 0) {
return Math.ceil(headerSize / valueSize) * valueSize;
}
return headerSize;
};
I3SField.prototype._validateHeader = function(dataView) {
let headerSize = 0;
for (let itemIndex = 0; itemIndex < this._storageInfo.header.length; itemIndex++) {
const item = this._storageInfo.header[itemIndex];
headerSize += getValueTypeSize(item.valueType);
}
if (dataView.byteLength < headerSize) {
throw new RuntimeError_default(
`Invalid attribute buffer size (field: ${this.name}, header: ${headerSize}, actual: ${dataView.byteLength})`
);
}
};
I3SField.prototype._validateBody = function(dataView, offset) {
if (!defined_default(this._header.count)) {
throw new RuntimeError_default(
`Invalid attribute buffer (field: ${this.name}, count is missing)`
);
}
let attributeByteCountsOffset;
for (let itemIndex = 0; itemIndex < this._storageInfo.ordering.length && offset < dataView.byteLength; itemIndex++) {
const orderingValue = this._storageInfo.ordering[itemIndex];
const item = orderingValue === "ObjectIds" ? "objectIds" : orderingValue;
const desc = this._storageInfo[item];
if (defined_default(desc)) {
if (desc.valueType !== "String") {
if (item === "attributeByteCounts") {
attributeByteCountsOffset = offset;
}
const valueSize = getNumericTypeSize(desc.valueType);
offset += valueSize * this._header.count;
} else {
if (!defined_default(attributeByteCountsOffset)) {
throw new RuntimeError_default(
`Invalid attribute buffer (field: ${this.name}, attributeByteCounts is missing)`
);
}
for (let index = 0; index < this._header.count && offset < dataView.byteLength; ++index) {
const parsedValue = this._parseValue(
dataView,
this._storageInfo.attributeByteCounts.valueType,
attributeByteCountsOffset
);
offset += parsedValue.value;
attributeByteCountsOffset = parsedValue.offset;
}
}
} else {
throw new RuntimeError_default(
`Invalid attribute buffer (field: ${this.name}, ${item} is missing)`
);
}
}
if (dataView.byteLength < offset) {
throw new RuntimeError_default(
`Invalid attribute buffer size (field: ${this.name}, expected: ${offset}, actual: ${dataView.byteLength})`
);
}
};
var I3SField_default = I3SField;
// packages/engine/Source/Scene/I3SGeometry.js
var import_InlineWorkers1254 = __toESM(require_InlineWorkers(), 1);
function I3SGeometry(parent, uri) {
const dataProvider = parent._dataProvider;
const layer = parent._layer;
let resource;
if (defined_default(parent._nodeIndex)) {
resource = layer.resource.getDerivedResource({
url: `nodes/${parent._data.mesh.geometry.resource}/${uri}`
});
} else {
resource = parent.resource.getDerivedResource({ url: uri });
}
this._parent = parent;
this._dataProvider = dataProvider;
this._layer = layer;
this._resource = resource;
this._customAttributes = void 0;
}
Object.defineProperties(I3SGeometry.prototype, {
/**
* Gets the resource for the geometry
* @memberof I3SGeometry.prototype
* @type {Resource}
* @readonly
*/
resource: {
get: function() {
return this._resource;
}
},
/**
* Gets the I3S data for this object.
* @memberof I3SGeometry.prototype
* @type {object}
* @readonly
*/
data: {
get: function() {
return this._data;
}
},
/**
* Gets the custom attributes of the geometry.
* @memberof I3SGeometry.prototype
* @type {object}
* @readonly
*/
customAttributes: {
get: function() {
return this._customAttributes;
}
}
});
I3SGeometry.prototype.load = function() {
const that = this;
return this._dataProvider._loadBinary(this._resource).then(function(data) {
that._data = data;
return data;
});
};
var scratchAb = new Cartesian3_default();
var scratchAp1 = new Cartesian3_default();
var scratchAp2 = new Cartesian3_default();
var scratchCp1 = new Cartesian3_default();
var scratchCp2 = new Cartesian3_default();
function sameSide(p1, p2, a3, b) {
const ab = Cartesian3_default.subtract(b, a3, scratchAb);
const cp1 = Cartesian3_default.cross(
ab,
Cartesian3_default.subtract(p1, a3, scratchAp1),
scratchCp1
);
const cp2 = Cartesian3_default.cross(
ab,
Cartesian3_default.subtract(p2, a3, scratchAp2),
scratchCp2
);
return Cartesian3_default.dot(cp1, cp2) >= 0;
}
var scratchV03 = new Cartesian3_default();
var scratchV13 = new Cartesian3_default();
var scratchV23 = new Cartesian3_default();
var scratchV0V1 = new Cartesian3_default();
var scratchV0V2 = new Cartesian3_default();
var scratchCrossProd = new Cartesian3_default();
var scratchNormal9 = new Cartesian3_default();
var scratchV0p = new Cartesian3_default();
var scratchV1p = new Cartesian3_default();
var scratchV2p = new Cartesian3_default();
I3SGeometry.prototype.getClosestPointIndexOnTriangle = function(px, py, pz) {
if (defined_default(this._customAttributes) && defined_default(this._customAttributes.positions)) {
const position = new Cartesian3_default(px, py, pz);
position.x -= this._customAttributes.cartesianCenter.x;
position.y -= this._customAttributes.cartesianCenter.y;
position.z -= this._customAttributes.cartesianCenter.z;
Matrix3_default.multiplyByVector(
this._customAttributes.parentRotation,
position,
position
);
let bestTriDist = Number.MAX_VALUE;
let bestTri;
let bestDistSq;
let bestIndex;
let bestPt;
const positions = this._customAttributes.positions;
const indices = this._customAttributes.indices;
let triCount;
if (defined_default(indices)) {
triCount = indices.length;
} else {
triCount = positions.length / 3;
}
for (let triIndex = 0; triIndex < triCount; triIndex++) {
let i0, i1, i2;
if (defined_default(indices)) {
i0 = indices[triIndex];
i1 = indices[triIndex + 1];
i2 = indices[triIndex + 2];
} else {
i0 = triIndex * 3;
i1 = triIndex * 3 + 1;
i2 = triIndex * 3 + 2;
}
const v02 = Cartesian3_default.fromElements(
positions[i0 * 3],
positions[i0 * 3 + 1],
positions[i0 * 3 + 2],
scratchV03
);
const v12 = Cartesian3_default.fromElements(
positions[i1 * 3],
positions[i1 * 3 + 1],
positions[i1 * 3 + 2],
scratchV13
);
const v22 = new Cartesian3_default(
positions[i2 * 3],
positions[i2 * 3 + 1],
positions[i2 * 3 + 2],
scratchV23
);
if (!sameSide(position, v02, v12, v22) || !sameSide(position, v12, v02, v22) || !sameSide(position, v22, v02, v12)) {
continue;
}
const v0v1 = Cartesian3_default.subtract(v12, v02, scratchV0V1);
const v0v2 = Cartesian3_default.subtract(v22, v02, scratchV0V2);
const crossProd = Cartesian3_default.cross(v0v1, v0v2, scratchCrossProd);
if (Cartesian3_default.magnitude(crossProd) === 0) {
continue;
}
const normal2 = Cartesian3_default.normalize(crossProd, scratchNormal9);
const v0p = Cartesian3_default.subtract(position, v02, scratchV0p);
const normalDist = Math.abs(Cartesian3_default.dot(v0p, normal2));
if (normalDist < bestTriDist) {
bestTriDist = normalDist;
bestTri = triIndex;
const d0 = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(position, v02, v0p)
);
const d1 = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(position, v12, scratchV1p)
);
const d2 = Cartesian3_default.magnitudeSquared(
Cartesian3_default.subtract(position, v22, scratchV2p)
);
if (d0 < d1 && d0 < d2) {
bestIndex = i0;
bestPt = v02;
bestDistSq = d0;
} else if (d1 < d2) {
bestIndex = i1;
bestPt = v12;
bestDistSq = d1;
} else {
bestIndex = i2;
bestPt = v22;
bestDistSq = d2;
}
}
}
if (defined_default(bestTri)) {
return {
index: bestIndex,
distanceSquared: bestDistSq,
distance: Math.sqrt(bestDistSq),
queriedPosition: position,
closestPosition: Cartesian3_default.clone(bestPt)
};
}
}
return {
index: -1,
distanceSquared: Number.Infinity,
distance: Number.Infinity
};
};
function convertColorFactor(factor2) {
const convertedFactor = [];
const length2 = factor2.length;
for (let i = 0; i < length2; i++) {
if (i < 3) {
convertedFactor.push(srgbToLinear_default2(factor2[i]));
} else {
convertedFactor.push(factor2[i]);
}
}
return convertedFactor;
}
I3SGeometry.prototype._generateGltf = function(nodesInScene, nodes, meshes, buffers, bufferViews, accessors, extensions, extensionsUsed) {
let gltfMaterial = {
pbrMetallicRoughness: {
metallicFactor: 0
},
doubleSided: true,
name: "Material"
};
let isTextured = false;
let materialDefinition;
let texturePath = "";
if (defined_default(this._parent._data.mesh) && defined_default(this._layer._data.materialDefinitions)) {
const materialInfo = this._parent._data.mesh.material;
const materialIndex = materialInfo.definition;
if (materialIndex >= 0 && materialIndex < this._layer._data.materialDefinitions.length) {
materialDefinition = this._layer._data.materialDefinitions[materialIndex];
gltfMaterial = materialDefinition;
if (defined_default(gltfMaterial.pbrMetallicRoughness) && defined_default(gltfMaterial.pbrMetallicRoughness.baseColorTexture)) {
isTextured = true;
gltfMaterial.pbrMetallicRoughness.baseColorTexture.index = 0;
let textureName = "0";
if (defined_default(this._layer._data.textureSetDefinitions)) {
for (let defIndex = 0; defIndex < this._layer._data.textureSetDefinitions.length; defIndex++) {
const textureSetDefinition = this._layer._data.textureSetDefinitions[defIndex];
for (let formatIndex = 0; formatIndex < textureSetDefinition.formats.length; formatIndex++) {
const textureFormat = textureSetDefinition.formats[formatIndex];
if (textureFormat.format === "jpg") {
textureName = textureFormat.name;
break;
}
}
}
}
if (defined_default(this._parent._data.mesh) && this._parent._data.mesh.material.resource >= 0) {
texturePath = this._layer.resource.getDerivedResource({
url: `nodes/${this._parent._data.mesh.material.resource}/textures/${textureName}`
}).url;
}
}
if (defined_default(gltfMaterial.pbrMetallicRoughness) && defined_default(gltfMaterial.pbrMetallicRoughness.baseColorFactor)) {
gltfMaterial.pbrMetallicRoughness.baseColorFactor = convertColorFactor(
gltfMaterial.pbrMetallicRoughness.baseColorFactor
);
}
if (defined_default(gltfMaterial.emissiveFactor)) {
gltfMaterial.emissiveFactor = convertColorFactor(
gltfMaterial.emissiveFactor
);
}
}
} else if (defined_default(this._parent._data.textureData)) {
isTextured = true;
texturePath = this._parent.resource.getDerivedResource({
url: `${this._parent._data.textureData[0].href}`
}).url;
gltfMaterial.pbrMetallicRoughness.baseColorTexture = { index: 0 };
}
if (defined_default(gltfMaterial.alphaMode)) {
gltfMaterial.alphaMode = gltfMaterial.alphaMode.toUpperCase();
}
let gltfTextures = [];
let gltfImages = [];
let gltfSamplers = [];
if (isTextured) {
gltfTextures = [
{
sampler: 0,
source: 0
}
];
gltfImages = [
{
uri: texturePath
}
];
gltfSamplers = [
{
magFilter: 9729,
minFilter: 9986,
wrapS: 10497,
wrapT: 10497
}
];
}
const gltfMaterials = [];
const meshesLength = meshes.length;
for (let meshIndex = 0; meshIndex < meshesLength; meshIndex++) {
const primitives = meshes[meshIndex].primitives;
const primitivesLength = primitives.length;
for (let primitiveIndex = 0; primitiveIndex < primitivesLength; primitiveIndex++) {
const primitive = primitives[primitiveIndex];
if (defined_default(primitive.material)) {
while (primitive.material >= gltfMaterials.length) {
const material = clone_default(gltfMaterial, true);
gltfMaterials.push(material);
}
const primitiveMaterial = gltfMaterials[primitive.material];
if (defined_default(primitive.extra) && primitive.extra.isTransparent) {
if (!defined_default(primitiveMaterial.alphaMode)) {
primitiveMaterial.alphaMode = "BLEND";
}
} else if (primitiveMaterial.alphaMode === "BLEND") {
primitiveMaterial.alphaMode = "OPAQUE";
}
}
}
}
const gltfData = {
scene: 0,
scenes: [
{
nodes: nodesInScene
}
],
nodes,
meshes,
buffers,
bufferViews,
accessors,
materials: gltfMaterials,
textures: gltfTextures,
images: gltfImages,
samplers: gltfSamplers,
asset: {
version: "2.0"
},
extensions,
extensionsUsed
};
return gltfData;
};
var I3SGeometry_default = I3SGeometry;
// packages/engine/Source/Scene/I3SNode.js
function I3SNode(parent, ref, isRoot) {
let level;
let layer;
let nodeIndex;
let resource;
if (isRoot) {
level = 0;
layer = parent;
} else {
level = parent._level + 1;
layer = parent._layer;
}
if (typeof ref === "number") {
nodeIndex = ref;
} else {
resource = parent.resource.getDerivedResource({
url: `${ref}/`
});
}
this._parent = parent;
this._dataProvider = parent._dataProvider;
this._isRoot = isRoot;
this._level = level;
this._layer = layer;
this._nodeIndex = nodeIndex;
this._resource = resource;
this._isLoading = false;
this._tile = void 0;
this._data = void 0;
this._geometryData = [];
this._featureData = [];
this._fields = {};
this._children = [];
this._childrenReadyPromise = void 0;
this._globalTransform = void 0;
this._inverseGlobalTransform = void 0;
this._inverseRotationMatrix = void 0;
this._symbologyData = void 0;
}
Object.defineProperties(I3SNode.prototype, {
/**
* Gets the resource for the node.
* @memberof I3SNode.prototype
* @type {Resource}
* @readonly
*/
resource: {
get: function() {
return this._resource;
}
},
/**
* Gets the parent layer.
* @memberof I3SNode.prototype
* @type {I3SLayer}
* @readonly
*/
layer: {
get: function() {
return this._layer;
}
},
/**
* Gets the parent node.
* @memberof I3SNode.prototype
* @type {I3SNode|undefined}
* @readonly
*/
parent: {
get: function() {
return this._parent;
}
},
/**
* Gets the children nodes.
* @memberof I3SNode.prototype
* @type {I3SNode[]}
* @readonly
*/
children: {
get: function() {
return this._children;
}
},
/**
* Gets the collection of geometries.
* @memberof I3SNode.prototype
* @type {I3SGeometry[]}
* @readonly
*/
geometryData: {
get: function() {
return this._geometryData;
}
},
/**
* Gets the collection of features.
* @memberof I3SNode.prototype
* @type {I3SFeature[]}
* @readonly
*/
featureData: {
get: function() {
return this._featureData;
}
},
/**
* Gets the collection of fields.
* @memberof I3SNode.prototype
* @type {I3SField[]}
* @readonly
*/
fields: {
get: function() {
return this._fields;
}
},
/**
* Gets the Cesium3DTile for this node.
* @memberof I3SNode.prototype
* @type {Cesium3DTile}
* @readonly
*/
tile: {
get: function() {
return this._tile;
}
},
/**
* Gets the I3S data for this object.
* @memberof I3SNode.prototype
* @type {object}
* @readonly
*/
data: {
get: function() {
return this._data;
}
}
});
I3SNode.prototype.load = async function() {
const that = this;
function processData() {
if (!that._isRoot) {
const tileDefinition = that._create3DTileDefinition();
that._tile = new Cesium3DTile_default(
that._layer._tileset,
that._dataProvider.resource,
tileDefinition,
that._parent._tile
);
that._tile._i3sNode = that;
}
}
if (!defined_default(this._nodeIndex)) {
const data = await I3SDataProvider_default.loadJson(this._resource);
that._data = data;
processData();
return;
}
const node = await this._layer._getNodeInNodePages(this._nodeIndex);
that._data = node;
let uri;
if (that._isRoot) {
uri = "nodes/root/";
} else if (defined_default(node.mesh)) {
const uriIndex = node.mesh.geometry.resource;
uri = `../${uriIndex}/`;
}
if (defined_default(uri) && defined_default(that._parent.resource)) {
that._resource = that._parent.resource.getDerivedResource({ url: uri });
}
processData();
};
function createAndLoadField(node, storageInfo) {
const newField = new I3SField_default(node, storageInfo);
node._fields[storageInfo.name] = newField;
return newField.load();
}
I3SNode.prototype.loadFields = function() {
const fields = this._layer._data.attributeStorageInfo;
const promises = [];
if (defined_default(fields)) {
for (let i = 0; i < fields.length; i++) {
const storageInfo = fields[i];
const field = this._fields[storageInfo.name];
if (defined_default(field)) {
promises.push(field.load());
} else {
promises.push(createAndLoadField(this, storageInfo));
}
}
}
return Promise.all(promises);
};
I3SNode.prototype.loadField = function(name) {
Check_default.defined("name", name);
const field = this._fields[name];
if (defined_default(field)) {
return field.load();
}
const fields = this._layer._data.attributeStorageInfo;
if (defined_default(fields)) {
for (let i = 0; i < fields.length; i++) {
const storageInfo = fields[i];
if (storageInfo.name === name) {
return createAndLoadField(this, storageInfo);
}
}
}
return Promise.resolve();
};
I3SNode.prototype.getFieldsForPickedPosition = function(pickedPosition) {
const geometry = this.geometryData[0];
if (!defined_default(geometry.customAttributes.featureIndex)) {
return {};
}
const location2 = geometry.getClosestPointIndexOnTriangle(
pickedPosition.x,
pickedPosition.y,
pickedPosition.z
);
if (location2.index === -1 || location2.index > geometry.customAttributes.featureIndex.length) {
return {};
}
const featureIndex = geometry.customAttributes.featureIndex[location2.index];
return this.getFieldsForFeature(featureIndex);
};
I3SNode.prototype.getFieldsForFeature = function(featureIndex) {
const featureFields = {};
for (const fieldName in this.fields) {
if (this.fields.hasOwnProperty(fieldName)) {
const field = this.fields[fieldName];
if (featureIndex >= 0 && featureIndex < field.values.length) {
featureFields[field.name] = field.values[featureIndex];
}
}
}
return featureFields;
};
I3SNode.prototype._loadChildren = function() {
const that = this;
if (defined_default(this._childrenReadyPromise)) {
return this._childrenReadyPromise;
}
const childPromises = [];
if (defined_default(that._data.children)) {
for (let childIndex = 0; childIndex < that._data.children.length; childIndex++) {
const child = that._data.children[childIndex];
const newChild = new I3SNode(that, child.href ?? child, false);
that._children.push(newChild);
childPromises.push(newChild.load());
}
}
this._childrenReadyPromise = Promise.all(childPromises).then(function() {
for (let i = 0; i < that._children.length; i++) {
that._tile.children.push(that._children[i]._tile);
}
});
return this._childrenReadyPromise;
};
I3SNode.prototype._loadGeometryData = function() {
const geometryPromises = [];
if (defined_default(this._data.geometryData)) {
for (let geomIndex = 0; geomIndex < this._data.geometryData.length; geomIndex++) {
const curGeometryData = new I3SGeometry_default(
this,
this._data.geometryData[geomIndex].href
);
this._geometryData.push(curGeometryData);
geometryPromises.push(curGeometryData.load());
}
} else if (defined_default(this._data.mesh)) {
const geometryDefinition = this._layer._findBestGeometryBuffers(
this._data.mesh.geometry.definition,
["position", "uv0"]
);
const geometryURI = `./geometries/${geometryDefinition.bufferIndex}/`;
const newGeometryData = new I3SGeometry_default(this, geometryURI);
newGeometryData._geometryDefinitions = geometryDefinition.definition;
newGeometryData._geometryBufferInfo = geometryDefinition.geometryBufferInfo;
this._geometryData.push(newGeometryData);
geometryPromises.push(newGeometryData.load());
}
return Promise.all(geometryPromises);
};
I3SNode.prototype._loadFeatureData = function() {
const featurePromises = [];
if (defined_default(this._data.featureData)) {
for (let featureIndex = 0; featureIndex < this._data.featureData.length; featureIndex++) {
const newFeatureData = new I3SFeature_default(
this,
this._data.featureData[featureIndex].href
);
this._featureData.push(newFeatureData);
featurePromises.push(newFeatureData.load());
}
}
return Promise.all(featurePromises);
};
I3SNode.prototype._clearGeometryData = function() {
this._geometryData = [];
};
I3SNode.prototype._create3DTileDefinition = function() {
const obb = this._data.obb;
const mbs = this._data.mbs;
if (!defined_default(obb) && !defined_default(mbs)) {
console.error("Failed to load I3S node. Bounding volume is required.");
return void 0;
}
let geoPosition;
if (defined_default(obb)) {
geoPosition = Cartographic_default.fromDegrees(
obb.center[0],
obb.center[1],
obb.center[2]
);
} else {
geoPosition = Cartographic_default.fromDegrees(mbs[0], mbs[1], mbs[2]);
}
if (defined_default(this._dataProvider._geoidDataList) && defined_default(geoPosition)) {
for (let i = 0; i < this._dataProvider._geoidDataList.length; i++) {
const tile = this._dataProvider._geoidDataList[i];
const projectedPos = tile.projection.project(geoPosition);
if (projectedPos.x > tile.nativeExtent.west && projectedPos.x < tile.nativeExtent.east && projectedPos.y > tile.nativeExtent.south && projectedPos.y < tile.nativeExtent.north) {
geoPosition.height += sampleGeoid(projectedPos.x, projectedPos.y, tile);
break;
}
}
}
let boundingVolume = {};
let position;
let span = 0;
if (defined_default(obb)) {
boundingVolume = {
box: [
0,
0,
0,
obb.halfSize[0],
0,
0,
0,
obb.halfSize[1],
0,
0,
0,
obb.halfSize[2]
]
};
span = Math.max(
Math.max(this._data.obb.halfSize[0], this._data.obb.halfSize[1]),
this._data.obb.halfSize[2]
);
position = Ellipsoid_default.WGS84.cartographicToCartesian(geoPosition);
} else {
boundingVolume = {
sphere: [0, 0, 0, mbs[3]]
};
position = Ellipsoid_default.WGS84.cartographicToCartesian(geoPosition);
span = this._data.mbs[3];
}
span *= 2;
let metersPerPixel = Infinity;
if (defined_default(this._data.lodThreshold)) {
if (this._layer._data.nodePages.lodSelectionMetricType === "maxScreenThresholdSQ") {
const maxScreenThreshold = Math.sqrt(
this._data.lodThreshold / (Math.PI * 0.25)
);
metersPerPixel = span / maxScreenThreshold;
} else if (this._layer._data.nodePages.lodSelectionMetricType === "maxScreenThreshold") {
const maxScreenThreshold = this._data.lodThreshold;
metersPerPixel = span / maxScreenThreshold;
} else {
console.error("Invalid lodSelectionMetricType in Layer");
}
} else if (defined_default(this._data.lodSelection)) {
for (let lodIndex = 0; lodIndex < this._data.lodSelection.length; lodIndex++) {
if (this._data.lodSelection[lodIndex].metricType === "maxScreenThreshold") {
metersPerPixel = span / this._data.lodSelection[lodIndex].maxError;
}
}
}
if (metersPerPixel === Infinity) {
metersPerPixel = 1e5;
}
const geometricError = metersPerPixel * 16;
const hpr = new HeadingPitchRoll_default(0, 0, 0);
let orientation = Transforms_default.headingPitchRollQuaternion(position, hpr);
if (defined_default(this._data.obb)) {
orientation = new Quaternion_default(
this._data.obb.quaternion[0],
this._data.obb.quaternion[1],
this._data.obb.quaternion[2],
this._data.obb.quaternion[3]
);
}
const rotationMatrix = Matrix3_default.fromQuaternion(orientation);
const inverseRotationMatrix = Matrix3_default.inverse(rotationMatrix, new Matrix3_default());
const globalTransform = new Matrix4_default(
rotationMatrix[0],
rotationMatrix[1],
rotationMatrix[2],
0,
rotationMatrix[3],
rotationMatrix[4],
rotationMatrix[5],
0,
rotationMatrix[6],
rotationMatrix[7],
rotationMatrix[8],
0,
position.x,
position.y,
position.z,
1
);
const inverseGlobalTransform = Matrix4_default.inverse(
globalTransform,
new Matrix4_default()
);
const localTransform = Matrix4_default.clone(globalTransform);
if (defined_default(this._parent._globalTransform)) {
Matrix4_default.multiply(
globalTransform,
this._parent._inverseGlobalTransform,
localTransform
);
}
this._globalTransform = globalTransform;
this._inverseGlobalTransform = inverseGlobalTransform;
this._inverseRotationMatrix = inverseRotationMatrix;
const childrenDefinition = [];
for (let childIndex = 0; childIndex < this._children.length; childIndex++) {
childrenDefinition.push(
this._children[childIndex]._create3DTileDefinition()
);
}
const inPlaceTileDefinition = {
children: childrenDefinition,
refine: "REPLACE",
boundingVolume,
transform: [
localTransform[0],
localTransform[4],
localTransform[8],
localTransform[12],
localTransform[1],
localTransform[5],
localTransform[9],
localTransform[13],
localTransform[2],
localTransform[6],
localTransform[10],
localTransform[14],
localTransform[3],
localTransform[7],
localTransform[11],
localTransform[15]
],
content: {
uri: defined_default(this._resource) ? this._resource.url : void 0
},
geometricError
};
return inPlaceTileDefinition;
};
I3SNode.prototype._loadSymbology = async function() {
if (!defined_default(this._symbologyData) && defined_default(this._layer._symbology)) {
this._symbologyData = await this._layer._symbology._getSymbology(this);
}
};
I3SNode.prototype._createContentURL = async function() {
let rawGltf = {
scene: 0,
scenes: [
{
nodes: [0]
}
],
nodes: [
{
name: "singleNode"
}
],
meshes: [],
buffers: [],
bufferViews: [],
accessors: [],
materials: [],
textures: [],
images: [],
samplers: [],
asset: {
version: "2.0"
}
};
const dataPromises = [this._loadGeometryData()];
if (this._dataProvider.legacyVersion16) {
dataPromises.push(this._loadFeatureData());
}
await Promise.all(dataPromises);
if (defined_default(this._geometryData) && this._geometryData.length > 0) {
if (this._dataProvider._applySymbology) {
await this._loadSymbology();
}
const url2 = this._geometryData[0].resource.url;
const geometrySchema = this._layer._data.store.defaultGeometrySchema;
const geometryData = this._geometryData[0];
const result = await I3SDecoder_default.decode(
url2,
geometrySchema,
geometryData,
this._featureData[0],
this._symbologyData
);
if (!defined_default(result)) {
return;
}
rawGltf = geometryData._generateGltf(
result.meshData.nodesInScene,
result.meshData.nodes,
result.meshData.meshes,
result.meshData.buffers,
result.meshData.bufferViews,
result.meshData.accessors,
result.meshData.rootExtensions,
result.meshData.extensionsUsed
);
this._geometryData[0]._customAttributes = result.meshData._customAttributes;
}
const binaryGltfData = this._dataProvider._binarizeGltf(rawGltf);
const glbDataBlob = new Blob([binaryGltfData], {
type: "application/binary"
});
return URL.createObjectURL(glbDataBlob);
};
async function loadFilters(node) {
const filters = node._layer._filters;
const promises = [];
for (let i = 0; i < filters.length; i++) {
const promise = node.loadField(filters[i].name);
promises.push(promise);
}
await Promise.all(promises);
return filters;
}
function checkFeatureValue(featureIndex, field, filter) {
if (!defined_default(filter.values) || filter.values.length === 0) {
return false;
}
const fieldValues = defined_default(field) ? field.values : [];
let featureValue;
if (featureIndex < fieldValues.length) {
featureValue = fieldValues[featureIndex];
}
let matches = false;
for (let i = 0; i < filter.values.length; i++) {
if (filter.values[i] === featureValue) {
matches = true;
break;
}
}
return matches;
}
async function filterFeatures(node, contentModel) {
const batchTable = node._tile.content.batchTable;
if (defined_default(batchTable) && batchTable.featuresLength > 0) {
batchTable.setAllShow(true);
const filters = await loadFilters(node);
if (filters.length > 0) {
for (let featureIndex = 0; featureIndex < batchTable.featuresLength; featureIndex++) {
for (let filterIndex = 0; filterIndex < filters.length; filterIndex++) {
const filter = filters[filterIndex];
if (!checkFeatureValue(featureIndex, node._fields[filter.name], filter)) {
batchTable.setShow(featureIndex, false);
break;
}
}
}
}
}
contentModel.show = true;
}
I3SNode.prototype._filterFeatures = function() {
const promises = [];
for (let i = 0; i < this._children.length; i++) {
const promise = this._children[i]._filterFeatures();
promises.push(promise);
}
const contentModel = this._tile?.content?._model;
if (defined_default(this._geometryData) && this._geometryData.length > 0 && defined_default(contentModel) && contentModel.ready) {
contentModel.show = false;
const promise = filterFeatures(this, contentModel);
promises.push(promise);
}
return Promise.all(promises);
};
Cesium3DTile_default.prototype._hookedRequestContent = Cesium3DTile_default.prototype.requestContent;
Cesium3DTile_default.prototype.requestContent = function() {
if (!this.tileset._isI3STileSet) {
return this._hookedRequestContent();
}
if (!this._isLoading) {
this._isLoading = true;
const that = this;
return this._i3sNode._createContentURL().then((url2) => {
if (!defined_default(url2)) {
that._isLoading = false;
return;
}
that._contentResource = new Resource_default({ url: url2 });
return that._hookedRequestContent();
}).then((content) => {
const contentModel = content?._model;
if (defined_default(that._i3sNode._geometryData) && that._i3sNode._geometryData.length > 0 && defined_default(contentModel)) {
contentModel.show = false;
contentModel.readyEvent.addEventListener(() => {
filterFeatures(that._i3sNode, contentModel);
});
}
that._isLoading = false;
return content;
});
}
};
function bilinearInterpolate(tx, ty, h00, h10, h01, h11) {
const a3 = h00 * (1 - tx) + h10 * tx;
const b = h01 * (1 - tx) + h11 * tx;
return a3 * (1 - ty) + b * ty;
}
function sampleMap(u3, v3, width, data) {
const address = u3 + v3 * width;
return data[address];
}
function sampleGeoid(sampleX, sampleY, geoidData) {
const extent = geoidData.nativeExtent;
let x = (sampleX - extent.west) / (extent.east - extent.west) * (geoidData.width - 1);
let y = (sampleY - extent.south) / (extent.north - extent.south) * (geoidData.height - 1);
const xi = Math.floor(x);
let yi = Math.floor(y);
x -= xi;
y -= yi;
const xNext = xi < geoidData.width ? xi + 1 : xi;
let yNext = yi < geoidData.height ? yi + 1 : yi;
yi = geoidData.height - 1 - yi;
yNext = geoidData.height - 1 - yNext;
const h00 = sampleMap(xi, yi, geoidData.width, geoidData.buffer);
const h10 = sampleMap(xNext, yi, geoidData.width, geoidData.buffer);
const h01 = sampleMap(xi, yNext, geoidData.width, geoidData.buffer);
const h11 = sampleMap(xNext, yNext, geoidData.width, geoidData.buffer);
let finalHeight = bilinearInterpolate(x, y, h00, h10, h01, h11);
finalHeight = finalHeight * geoidData.scale + geoidData.offset;
return finalHeight;
}
Object.defineProperties(Cesium3DTile_default.prototype, {
/**
* Gets the I3S Node for the tile.
* @memberof Cesium3DTile.prototype
* @type {string}
*/
i3sNode: {
get: function() {
return this._i3sNode;
}
}
});
var I3SNode_default = I3SNode;
// packages/engine/Source/Scene/I3SSymbology.js
var import_InlineWorkers1256 = __toESM(require_InlineWorkers(), 1);
function I3SSymbology(layer) {
this._layer = layer;
this._defaultSymbology = void 0;
this._valueFields = [];
this._uniqueValueHash = void 0;
this._classBreaksHash = void 0;
this._parseLayerSymbology();
}
Object.defineProperties(I3SSymbology.prototype, {
/**
* Gets the default symbology data.
* @memberof I3SSymbology.prototype
* @type {object}
* @readonly
*/
defaultSymbology: {
get: function() {
return this._defaultSymbology;
}
}
});
function convertColor(color, transparency) {
const convertedColor = [];
for (let i = 0; i < color.length; i++) {
const floatColor = Color_default.byteToFloat(color[i]);
if (i < 3) {
convertedColor.push(srgbToLinear_default2(floatColor));
} else {
convertedColor.push(floatColor);
}
}
if (convertedColor.length === 3) {
if (defined_default(transparency)) {
convertedColor.push(1 - transparency / 100);
} else {
convertedColor.push(1);
}
}
return convertedColor;
}
function parseSymbol(symbol, isColorCaptured) {
const symbology = {
edges: void 0,
material: void 0
};
if (defined_default(symbol) && defined_default(symbol.symbolLayers)) {
for (let i = 0; i < symbol.symbolLayers.length; i++) {
const symbolLayer = symbol.symbolLayers[i];
if (symbolLayer.type === "Fill") {
const edges = symbolLayer.edges;
const outline = symbolLayer.outline;
if (defined_default(edges)) {
symbology.edges = {};
if (defined_default(edges.color)) {
symbology.edges.color = convertColor(
edges.color,
edges.transparency
);
}
} else if (defined_default(outline)) {
symbology.edges = {};
if (defined_default(outline.color)) {
symbology.edges.color = convertColor(
outline.color,
outline.transparency
);
}
}
if (!isColorCaptured) {
const material = symbolLayer.material;
if (defined_default(material)) {
symbology.material = {
colorMixMode: material.colorMixMode
};
if (defined_default(material.color)) {
symbology.material.color = convertColor(
material.color,
material.transparency
);
}
}
}
break;
}
}
}
return symbology;
}
function buildUniqueValueHash(renderer, isColorCaptured) {
if (defined_default(renderer.uniqueValueGroups)) {
const valueHash = {};
for (let groupIndex = 0; groupIndex < renderer.uniqueValueGroups.length; groupIndex++) {
const classes = renderer.uniqueValueGroups[groupIndex].classes;
if (defined_default(classes)) {
for (let classIndex = 0; classIndex < classes.length; classIndex++) {
const classSymbology = parseSymbol(
classes[classIndex].symbol,
isColorCaptured
);
const values = classes[classIndex].values;
for (let valueIndex = 0; valueIndex < values.length; valueIndex++) {
const fieldValues = values[valueIndex];
let hash2 = valueHash;
for (let fieldIndex = 0; fieldIndex < fieldValues.length; fieldIndex++) {
const fieldValue = fieldValues[fieldIndex];
if (fieldIndex === fieldValues.length - 1) {
hash2[fieldValue] = classSymbology;
} else {
if (!defined_default(hash2[fieldValue])) {
hash2[fieldValue] = {};
}
hash2 = hash2[fieldValue];
}
}
}
}
}
}
return valueHash;
}
if (defined_default(renderer.uniqueValueInfos)) {
const valueHash = {};
for (let infoIndex = 0; infoIndex < renderer.uniqueValueInfos.length; infoIndex++) {
const info = renderer.uniqueValueInfos[infoIndex];
valueHash[info.value] = parseSymbol(info.symbol, isColorCaptured);
}
return valueHash;
}
return void 0;
}
function buildClassBreaksHash(renderer, isColorCaptured) {
if (defined_default(renderer.classBreakInfos)) {
const classBreakInfos = [...renderer.classBreakInfos];
classBreakInfos.sort(function(a3, b) {
const aMax = a3.classMaxValue ?? a3.classMinValue;
const bMax = b.classMaxValue ?? b.classMinValue;
return aMax - bMax;
});
const valueHash = {
ranges: [],
symbols: []
};
if (defined_default(renderer.minValue)) {
valueHash.ranges.push(renderer.minValue);
valueHash.symbols.push(void 0);
}
for (let infoIndex = 0; infoIndex < classBreakInfos.length; infoIndex++) {
const info = classBreakInfos[infoIndex];
if (defined_default(info.classMinValue)) {
if (valueHash.ranges.length === 0 || info.classMinValue > valueHash.ranges[valueHash.ranges.length - 1]) {
valueHash.ranges.push(info.classMinValue);
valueHash.symbols.push(void 0);
}
}
if (defined_default(info.classMaxValue)) {
if (valueHash.ranges.length === 0 || info.classMaxValue > valueHash.ranges[valueHash.ranges.length - 1]) {
valueHash.ranges.push(info.classMaxValue);
valueHash.symbols.push(parseSymbol(info.symbol, isColorCaptured));
}
}
}
valueHash.symbols.push(void 0);
return valueHash;
}
return void 0;
}
I3SSymbology.prototype._parseLayerSymbology = function() {
const drawingInfo = this._layer.data.drawingInfo;
if (defined_default(drawingInfo) && defined_default(drawingInfo.renderer)) {
const cachedDrawingInfo = this._layer.data.cachedDrawingInfo;
const isColorCaptured = defined_default(cachedDrawingInfo) && cachedDrawingInfo.color === true;
const renderer = drawingInfo.renderer;
if (renderer.type === "simple") {
this._defaultSymbology = parseSymbol(renderer.symbol, isColorCaptured);
} else if (renderer.type === "uniqueValue") {
this._defaultSymbology = parseSymbol(
renderer.defaultSymbol,
isColorCaptured
);
this._valueFields.push(renderer.field1);
if (defined_default(renderer.field2)) {
this._valueFields.push(renderer.field2);
}
if (defined_default(renderer.field3)) {
this._valueFields.push(renderer.field3);
}
this._uniqueValueHash = buildUniqueValueHash(renderer, isColorCaptured);
} else if (renderer.type === "classBreaks") {
this._defaultSymbology = parseSymbol(
renderer.defaultSymbol,
isColorCaptured
);
this._valueFields.push(renderer.field);
this._classBreaksHash = buildClassBreaksHash(renderer, isColorCaptured);
}
}
};
function findHashForUniqueValues(hash2, values, hashLevel, valueIndex) {
const levelValues = values[hashLevel];
if (valueIndex < levelValues.length) {
const hashValue = levelValues[valueIndex];
const innerHash = hash2[hashValue];
if (defined_default(innerHash) && ++hashLevel < values.length) {
return findHashForUniqueValues(innerHash, values, hashLevel, valueIndex);
}
return innerHash;
}
return void 0;
}
function bisect(array, value) {
let low = 0;
let high = array.length;
if (low < high) {
do {
const mid = low + high >>> 1;
if (array[mid] < value) {
low = mid + 1;
} else {
high = mid;
}
} while (low < high);
}
return low;
}
function findHashForClassBreaks(hash2, values, valueIndex) {
const value = values[valueIndex];
const range = bisect(hash2.ranges, value);
return hash2.symbols[range];
}
I3SSymbology.prototype._getSymbology = async function(node) {
const symbology = {
default: this._defaultSymbology
};
if (this._valueFields.length > 0) {
const promises = [];
for (let i = 0; i < this._valueFields.length; i++) {
promises.push(node.loadField(this._valueFields[i]));
}
await Promise.all(promises);
const fieldsValues = [];
for (let i = 0; i < this._valueFields.length; i++) {
fieldsValues.push(node.fields[this._valueFields[i]].values);
}
let featureHashFn;
if (defined_default(this._uniqueValueHash)) {
featureHashFn = (featureIndex) => findHashForUniqueValues(
this._uniqueValueHash,
fieldsValues,
0,
featureIndex
);
} else if (defined_default(this._classBreaksHash)) {
featureHashFn = (featureIndex) => findHashForClassBreaks(
this._classBreaksHash,
fieldsValues[0],
featureIndex
);
}
if (defined_default(featureHashFn)) {
const firstFieldValues = fieldsValues[0];
for (let featureIndex = 0; featureIndex < firstFieldValues.length; featureIndex++) {
const featureSymbology = featureHashFn(featureIndex);
if (defined_default(featureSymbology)) {
symbology[featureIndex] = featureSymbology;
}
}
}
}
return symbology;
};
var I3SSymbology_default = I3SSymbology;
// packages/engine/Source/Scene/I3SLayer.js
function I3SLayer(dataProvider, layerData, parent) {
this._dataProvider = dataProvider;
this._parent = parent;
if (!defined_default(layerData.href) && defined_default(layerData.id)) {
layerData.href = `layers/${layerData.id}`;
}
const parentUrl = this._parent.resource.getUrlComponent();
let tilesetUrl = "";
if (parentUrl.match(/layers\/\d/)) {
tilesetUrl = `${parentUrl}`.replace(/\/+$/, "");
} else {
tilesetUrl = `${parentUrl}`.replace(/\/?$/, "/").concat(`${layerData.href}`);
}
this._version = layerData.store.version;
const splitVersion = this._version.split(".");
this._majorVersion = parseInt(splitVersion[0]);
this._minorVersion = splitVersion.length > 1 ? parseInt(splitVersion[1]) : 0;
this._resource = new Resource_default({ url: tilesetUrl });
this._resource.setQueryParameters(
this._dataProvider.resource.queryParameters
);
this._resource.appendForwardSlash();
this._data = layerData;
this._rootNode = void 0;
this._nodePages = {};
this._nodePageFetches = {};
this._extent = void 0;
this._tileset = void 0;
this._geometryDefinitions = void 0;
this._filters = [];
this._symbology = void 0;
this._computeGeometryDefinitions(true);
this._computeExtent();
}
Object.defineProperties(I3SLayer.prototype, {
/**
* Gets the resource for the layer.
* @memberof I3SLayer.prototype
* @type {Resource}
* @readonly
*/
resource: {
get: function() {
return this._resource;
}
},
/**
* Gets the root node of this layer.
* @memberof I3SLayer.prototype
* @type {I3SNode}
* @readonly
*/
rootNode: {
get: function() {
return this._rootNode;
}
},
/**
* Gets the Cesium3DTileset for this layer.
* @memberof I3SLayer.prototype
* @type {Cesium3DTileset|undefined}
* @readonly
*/
tileset: {
get: function() {
return this._tileset;
}
},
/**
* Gets the I3S data for this object.
* @memberof I3SLayer.prototype
* @type {object}
* @readonly
*/
data: {
get: function() {
return this._data;
}
},
/**
* The version string of the loaded I3S dataset
* @memberof I3SLayer.prototype
* @type {string}
* @readonly
*/
version: {
get: function() {
return this._version;
}
},
/**
* The major version number of the loaded I3S dataset
* @memberof I3SLayer.prototype
* @type {number}
* @readonly
*/
majorVersion: {
get: function() {
return this._majorVersion;
}
},
/**
* The minor version number of the loaded I3S dataset
* @memberof I3SLayer.prototype
* @type {number}
* @readonly
*/
minorVersion: {
get: function() {
return this._minorVersion;
}
},
/**
* When true, when the loaded I3S version is 1.6 or older
* @memberof I3SLayer.prototype
* @type {boolean}
* @readonly
*/
legacyVersion16: {
get: function() {
if (!defined_default(this.version)) {
return void 0;
}
if (this.majorVersion < 1 || this.majorVersion === 1 && this.minorVersion <= 6) {
return true;
}
return false;
}
}
});
I3SLayer.prototype.load = async function(cesium3dTilesetOptions) {
if (this._data.spatialReference.wkid !== 4326) {
throw new RuntimeError_default(
`Unsupported spatial reference: ${this._data.spatialReference.wkid}`
);
}
if (this._dataProvider.applySymbology) {
this._symbology = new I3SSymbology_default(this);
}
await this._dataProvider.loadGeoidData();
await this._loadRootNode(cesium3dTilesetOptions);
await this._create3DTileset(cesium3dTilesetOptions);
this._rootNode._tile = this._tileset._root;
this._tileset._root._i3sNode = this._rootNode;
if (this.legacyVersion16) {
return this._rootNode._loadChildren();
}
};
I3SLayer.prototype._computeGeometryDefinitions = function(useCompression) {
this._geometryDefinitions = [];
if (defined_default(this._data.geometryDefinitions)) {
for (let defIndex = 0; defIndex < this._data.geometryDefinitions.length; defIndex++) {
const geometryBuffersInfo = [];
const geometryBuffers = this._data.geometryDefinitions[defIndex].geometryBuffers;
for (let bufIndex = 0; bufIndex < geometryBuffers.length; bufIndex++) {
const geometryBuffer = geometryBuffers[bufIndex];
const collectedAttributes = [];
let compressed = false;
if (defined_default(geometryBuffer.compressedAttributes) && useCompression) {
compressed = true;
const attributes = geometryBuffer.compressedAttributes.attributes;
for (let i = 0; i < attributes.length; i++) {
collectedAttributes.push(attributes[i]);
}
} else {
for (const attribute in geometryBuffer) {
if (attribute !== "offset") {
collectedAttributes.push(attribute);
}
}
}
geometryBuffersInfo.push({
compressed,
attributes: collectedAttributes,
index: geometryBuffers.indexOf(geometryBuffer)
});
}
geometryBuffersInfo.sort(function(a3, b) {
if (a3.compressed && !b.compressed) {
return -1;
} else if (!a3.compressed && b.compressed) {
return 1;
}
return a3.attributes.length - b.attributes.length;
});
this._geometryDefinitions.push(geometryBuffersInfo);
}
}
};
I3SLayer.prototype._findBestGeometryBuffers = function(definition, attributes) {
const geometryDefinition = this._geometryDefinitions[definition];
if (defined_default(geometryDefinition)) {
for (let index = 0; index < geometryDefinition.length; ++index) {
const geometryBufferInfo = geometryDefinition[index];
let missed = false;
const geometryAttributes = geometryBufferInfo.attributes;
for (let attrIndex = 0; attrIndex < attributes.length; attrIndex++) {
if (!geometryAttributes.includes(attributes[attrIndex])) {
missed = true;
break;
}
}
if (!missed) {
return {
bufferIndex: geometryBufferInfo.index,
definition: geometryDefinition,
geometryBufferInfo
};
}
}
if (defined_default(geometryDefinition[0])) {
return {
bufferIndex: 0,
definition: geometryDefinition,
geometryBufferInfo: geometryDefinition[0]
};
}
}
};
I3SLayer.prototype._loadRootNode = function(cesium3dTilesetOptions) {
if (defined_default(this._data.nodePages)) {
let rootIndex = 0;
if (defined_default(this._data.nodePages.rootIndex)) {
rootIndex = this._data.nodePages.rootIndex;
}
this._rootNode = new I3SNode_default(this, rootIndex, true);
} else {
this._rootNode = new I3SNode_default(this, this._data.store.rootNode, true);
}
return this._rootNode.load(cesium3dTilesetOptions);
};
I3SLayer.prototype._getNodeInNodePages = function(nodeIndex) {
const index = Math.floor(nodeIndex / this._data.nodePages.nodesPerPage);
const offsetInPage = nodeIndex % this._data.nodePages.nodesPerPage;
return this._loadNodePage(index).then(function(data) {
return data.nodes[offsetInPage];
});
};
I3SLayer._fetchJson = function(resource) {
return resource.fetchJson();
};
I3SLayer.prototype._loadNodePage = function(page) {
const that = this;
if (!defined_default(this._nodePageFetches[page])) {
const nodePageResource = this.resource.getDerivedResource({
url: `nodepages/${page}/`
});
const fetchPromise = I3SLayer._fetchJson(nodePageResource).then(
function(data) {
if (defined_default(data.error) && data.error.code !== 200) {
return Promise.reject(data.error);
}
that._nodePages[page] = data.nodes;
return data;
}
);
this._nodePageFetches[page] = fetchPromise;
}
return this._nodePageFetches[page];
};
I3SLayer.prototype._computeExtent = function() {
if (defined_default(this._data.fullExtent)) {
this._extent = Rectangle_default.fromDegrees(
this._data.fullExtent.xmin,
this._data.fullExtent.ymin,
this._data.fullExtent.xmax,
this._data.fullExtent.ymax
);
} else if (defined_default(this._data.store.extent)) {
this._extent = Rectangle_default.fromDegrees(
this._data.store.extent[0],
this._data.store.extent[1],
this._data.store.extent[2],
this._data.store.extent[3]
);
}
};
I3SLayer.prototype._create3DTileset = async function(cesium3dTilesetOptions) {
const inPlaceTileset = {
asset: {
version: "1.0"
},
geometricError: Number.MAX_VALUE,
root: this._rootNode._create3DTileDefinition()
};
const tilesetBlob = new Blob([JSON.stringify(inPlaceTileset)], {
type: "application/json"
});
const tilesetUrl = URL.createObjectURL(tilesetBlob);
const outlineColor = this._symbology?.defaultSymbology?.edges?.color;
if (defined_default(outlineColor) && !defined_default(cesium3dTilesetOptions?.outlineColor)) {
cesium3dTilesetOptions = defined_default(cesium3dTilesetOptions) ? clone_default(cesium3dTilesetOptions) : {};
cesium3dTilesetOptions.outlineColor = Color_default.fromCartesian4(
Cartesian4_default.fromArray(outlineColor)
);
}
this._tileset = await Cesium3DTileset_default.fromUrl(
tilesetUrl,
cesium3dTilesetOptions
);
this._tileset.show = this._parent.show;
this._tileset._isI3STileSet = true;
this._tileset.tileUnload.addEventListener(function(tile) {
tile._i3sNode._clearGeometryData();
URL.revokeObjectURL(tile._contentResource._url);
tile._contentResource = tile._i3sNode.resource;
});
this._tileset.tileVisible.addEventListener(function(tile) {
if (defined_default(tile._i3sNode)) {
tile._i3sNode._loadChildren();
}
});
};
I3SLayer.prototype._updateVisibility = function() {
if (defined_default(this._tileset)) {
this._tileset.show = this._parent.show;
}
};
I3SLayer.prototype.filterByAttributes = function(filters) {
this._filters = defined_default(filters) ? clone_default(filters, true) : [];
const rootNode = this._rootNode;
if (defined_default(rootNode)) {
return rootNode._filterFeatures();
}
return Promise.resolve();
};
var I3SLayer_default = I3SLayer;
// packages/engine/Source/Scene/I3SStatistics.js
var import_InlineWorkers1258 = __toESM(require_InlineWorkers(), 1);
function I3SStatistics(dataProvider, uri) {
this._dataProvider = dataProvider;
this._resource = new Resource_default({ url: uri });
this._resource.setQueryParameters(dataProvider.resource.queryParameters);
this._resource.appendForwardSlash();
}
Object.defineProperties(I3SStatistics.prototype, {
/**
* Gets the resource for the statistics
* @memberof I3SStatistics.prototype
* @type {Resource}
* @readonly
*/
resource: {
get: function() {
return this._resource;
}
},
/**
* Gets the I3S data for this object.
* @memberof I3SStatistics.prototype
* @type {object}
* @readonly
*/
data: {
get: function() {
return this._data;
}
},
/**
* Gets the collection of attribute names.
* @memberof I3SStatistics.prototype
* @type {string[]}
* @readonly
*/
names: {
get: function() {
const names = [];
const summary = this._data.summary;
if (defined_default(summary)) {
for (let i = 0; i < summary.length; ++i) {
names.push(summary[i].fieldName);
}
}
return names;
}
}
});
I3SStatistics.prototype.load = async function() {
this._data = await I3SDataProvider_default.loadJson(this._resource);
return this._data;
};
I3SStatistics.prototype._getValues = function(attributeName) {
const summary = this._data.summary;
if (defined_default(summary)) {
for (let i = 0; i < summary.length; ++i) {
const attribute = summary[i];
if (attribute.fieldName === attributeName) {
if (defined_default(attribute.mostFrequentValues)) {
return [...attribute.mostFrequentValues];
}
return [];
}
}
}
};
var I3SStatistics_default = I3SStatistics;
// packages/engine/Source/Scene/I3SSublayer.js
var import_InlineWorkers1259 = __toESM(require_InlineWorkers(), 1);
function I3SSublayer(dataProvider, parent, sublayerData) {
this._dataProvider = dataProvider;
this._parent = parent;
this._data = sublayerData;
this._name = sublayerData.name;
this._modelName = sublayerData.modelName;
this._visibility = sublayerData.visibility ?? true;
this._resource = void 0;
this._sublayers = [];
this._i3sLayers = [];
}
Object.defineProperties(I3SSublayer.prototype, {
/**
* Gets the resource for the sublayer
* @memberof I3SSublayer.prototype
* @type {Resource}
* @readonly
*/
resource: {
get: function() {
return this._resource;
}
},
/**
* Gets the I3S data for this object.
* @memberof I3SSublayer.prototype
* @type {object}
* @readonly
*/
data: {
get: function() {
return this._data;
}
},
/**
* Gets the name for the sublayer.
* @memberof I3SSublayer.prototype
* @type {string}
* @readonly
*/
name: {
get: function() {
return this._name;
}
},
/**
* Gets the model name for the sublayer.
* @memberof I3SSublayer.prototype
* @type {string}
* @readonly
*/
modelName: {
get: function() {
return this._modelName;
}
},
/**
* Gets the collection of child sublayers.
* @memberof I3SSublayer.prototype
* @type {I3SSublayer[]}
* @readonly
*/
sublayers: {
get: function() {
return this._sublayers;
}
},
/**
* Gets or sets the sublayer visibility.
* @memberof I3SSublayer.prototype
* @type {boolean}
*/
visibility: {
get: function() {
return this._visibility;
},
set: function(value) {
Check_default.defined("value", value);
if (this._visibility !== value) {
this._visibility = value;
for (let i = 0; i < this._i3sLayers.length; i++) {
this._i3sLayers[i]._updateVisibility();
}
}
}
},
/**
* Determines if the sublayer will be shown.
* @memberof I3SSublayer.prototype
* @type {boolean}
* @readonly
*/
show: {
get: function() {
return this._visibility && this._parent.show;
}
}
});
I3SSublayer._fromData = async function(dataProvider, buildingLayerUrl, sublayerData, parent) {
const sublayer = new I3SSublayer(dataProvider, parent, sublayerData);
if (sublayer._data.layerType === "group") {
const sublayers = sublayer._data.sublayers;
if (defined_default(sublayers)) {
const promises = [];
for (let i = 0; i < sublayers.length; i++) {
const promise = I3SSublayer._fromData(
dataProvider,
buildingLayerUrl,
sublayers[i],
sublayer
);
promises.push(promise);
}
const childSublayers = await Promise.all(promises);
for (let i = 0; i < childSublayers.length; i++) {
const childSublayer = childSublayers[i];
sublayer._sublayers.push(childSublayer);
sublayer._i3sLayers.push(...childSublayer._i3sLayers);
}
}
} else if (sublayer._data.layerType === "3DObject") {
const sublayerUrl = buildingLayerUrl.concat(
`/sublayers/${sublayer._data.id}`
);
const resource = new Resource_default({ url: sublayerUrl });
resource.setQueryParameters(dataProvider.resource.queryParameters);
resource.appendForwardSlash();
sublayer._resource = resource;
const layerData = await I3SDataProvider_default.loadJson(sublayer._resource);
const layer = new I3SLayer_default(dataProvider, layerData, sublayer);
sublayer._i3sLayers.push(layer);
} else {
console.log(
`${sublayer._data.layerType} layer ${sublayer._data.name} is skipped as not supported.`
);
}
return sublayer;
};
var I3SSublayer_default = I3SSublayer;
// packages/engine/Source/Scene/I3SDataProvider.js
var import_lerc = __toESM(require_LercDecode(), 1);
function I3SDataProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._name = options.name;
this._show = options.show ?? true;
this._geoidTiledTerrainProvider = options.geoidTiledTerrainProvider;
this._showFeatures = options.showFeatures ?? false;
this._adjustMaterialAlphaMode = options.adjustMaterialAlphaMode ?? false;
this._applySymbology = options.applySymbology ?? false;
this._calculateNormals = options.calculateNormals ?? false;
this._cesium3dTilesetOptions = options.cesium3dTilesetOptions ?? Frozen_default.EMPTY_OBJECT;
this._layers = [];
this._sublayers = [];
this._data = void 0;
this._extent = void 0;
this._geoidDataPromise = void 0;
this._geoidDataList = void 0;
this._decoderTaskProcessor = void 0;
this._taskProcessorReadyPromise = void 0;
this._attributeStatistics = [];
this._layersExtent = [];
}
Object.defineProperties(I3SDataProvider.prototype, {
/**
* Gets a human-readable name for this dataset.
* @memberof I3SDataProvider.prototype
* @type {string}
* @readonly
*/
name: {
get: function() {
return this._name;
}
},
/**
* Determines if the dataset will be shown.
* @memberof I3SDataProvider.prototype
* @type {boolean}
*/
show: {
get: function() {
return this._show;
},
set: function(value) {
Check_default.defined("value", value);
if (this._show !== value) {
this._show = value;
for (let i = 0; i < this._layers.length; i++) {
this._layers[i]._updateVisibility();
}
}
}
},
/**
* The terrain provider referencing the GEOID service to be used for orthometric to ellipsoidal conversion.
* @memberof I3SDataProvider.prototype
* @type {ArcGISTiledElevationTerrainProvider}
* @readonly
*/
geoidTiledTerrainProvider: {
get: function() {
return this._geoidTiledTerrainProvider;
}
},
/**
* Gets the collection of layers.
* @memberof I3SDataProvider.prototype
* @type {I3SLayer[]}
* @readonly
*/
layers: {
get: function() {
return this._layers;
}
},
/**
* Gets the collection of building sublayers.
* @memberof I3SDataProvider.prototype
* @type {I3SSublayer[]}
* @readonly
*/
sublayers: {
get: function() {
return this._sublayers;
}
},
/**
* Gets the I3S data for this object.
* @memberof I3SDataProvider.prototype
* @type {object}
* @readonly
*/
data: {
get: function() {
return this._data;
}
},
/**
* Gets the extent covered by this I3S.
* @memberof I3SDataProvider.prototype
* @type {Rectangle}
* @readonly
*/
extent: {
get: function() {
return this._extent;
}
},
/**
* The resource used to fetch the I3S dataset.
* @memberof I3SDataProvider.prototype
* @type {Resource}
* @readonly
*/
resource: {
get: function() {
return this._resource;
}
},
/**
* Determines if the features will be shown.
* @memberof I3SDataProvider.prototype
* @type {boolean}
* @readonly
*/
showFeatures: {
get: function() {
return this._showFeatures;
}
},
/**
* Determines if the alpha mode of the material will be adjusted depending on the color vertex attribute.
* @memberof I3SDataProvider.prototype
* @type {boolean}
* @readonly
*/
adjustMaterialAlphaMode: {
get: function() {
return this._adjustMaterialAlphaMode;
}
},
/**
* Determines if the I3S symbology will be parsed and applied for the layers.
* @memberof I3SDataProvider.prototype
* @type {boolean}
* @readonly
*/
applySymbology: {
get: function() {
return this._applySymbology;
}
},
/**
* Determines if the flat normals will be generated for I3S geometry without normals.
* @memberof I3SDataProvider.prototype
* @type {boolean}
* @readonly
*/
calculateNormals: {
get: function() {
return this._calculateNormals;
}
}
});
I3SDataProvider.prototype.destroy = function() {
for (let i = 0; i < this._layers.length; i++) {
if (defined_default(this._layers[i]._tileset)) {
this._layers[i]._tileset.destroy();
}
}
return destroyObject_default(this);
};
I3SDataProvider.prototype.isDestroyed = function() {
return false;
};
I3SDataProvider.prototype.update = function(frameState) {
for (let i = 0; i < this._layers.length; i++) {
if (defined_default(this._layers[i]._tileset)) {
this._layers[i]._tileset.update(frameState);
}
}
};
I3SDataProvider.prototype.prePassesUpdate = function(frameState) {
for (let i = 0; i < this._layers.length; i++) {
if (defined_default(this._layers[i]._tileset)) {
this._layers[i]._tileset.prePassesUpdate(frameState);
}
}
};
I3SDataProvider.prototype.postPassesUpdate = function(frameState) {
for (let i = 0; i < this._layers.length; i++) {
if (defined_default(this._layers[i]._tileset)) {
this._layers[i]._tileset.postPassesUpdate(frameState);
}
}
};
I3SDataProvider.prototype.updateForPass = function(frameState, passState) {
for (let i = 0; i < this._layers.length; i++) {
if (defined_default(this._layers[i]._tileset)) {
this._layers[i]._tileset.updateForPass(frameState, passState);
}
}
};
function buildLayerUrl(provider, layerId) {
const dataProviderUrl = provider.resource.getUrlComponent();
let layerUrl = "";
if (dataProviderUrl.match(/layers\/\d/)) {
layerUrl = `${dataProviderUrl}`.replace(/\/+$/, "");
} else {
layerUrl = `${dataProviderUrl}`.replace(/\/?$/, "/").concat(`layers/${layerId}`);
}
return layerUrl;
}
async function addLayers(provider, data, options) {
if (data.layerType === "Building") {
if (!defined_default(options.showFeatures)) {
provider._showFeatures = true;
}
if (!defined_default(options.adjustMaterialAlphaMode)) {
provider._adjustMaterialAlphaMode = true;
}
if (!defined_default(options.applySymbology)) {
provider._applySymbology = true;
}
if (!defined_default(options.calculateNormals)) {
provider._calculateNormals = true;
}
const buildingLayerUrl = buildLayerUrl(provider, data.id);
if (defined_default(data.sublayers)) {
const promises = [];
for (let i = 0; i < data.sublayers.length; i++) {
const promise = I3SSublayer_default._fromData(
provider,
buildingLayerUrl,
data.sublayers[i],
provider
);
promises.push(promise);
}
const sublayers = await Promise.all(promises);
for (let i = 0; i < sublayers.length; i++) {
const sublayer = sublayers[i];
provider._sublayers.push(sublayer);
provider._layers.push(...sublayer._i3sLayers);
}
}
if (defined_default(data.statisticsHRef)) {
const uri = buildingLayerUrl.concat(`/${data.statisticsHRef}`);
const statistics2 = new I3SStatistics_default(provider, uri);
await statistics2.load();
provider._attributeStatistics.push(statistics2);
}
if (defined_default(data.fullExtent)) {
const extent = Rectangle_default.fromDegrees(
data.fullExtent.xmin,
data.fullExtent.ymin,
data.fullExtent.xmax,
data.fullExtent.ymax
);
provider._layersExtent.push(extent);
}
} else if (data.layerType === "3DObject" || data.layerType === "IntegratedMesh") {
if (!defined_default(options.calculateNormals) && !defined_default(data.textureSetDefinitions)) {
provider._calculateNormals = true;
}
const newLayer = new I3SLayer_default(provider, data, provider);
provider._layers.push(newLayer);
if (defined_default(newLayer._extent)) {
provider._layersExtent.push(newLayer._extent);
}
} else {
console.log(
`${data.layerType} layer ${data.name} is skipped as not supported.`
);
}
}
I3SDataProvider.fromUrl = async function(url2, options) {
Check_default.defined("url", url2);
options = options ?? Frozen_default.EMPTY_OBJECT;
const resource = Resource_default.createIfNeeded(url2);
resource.setQueryParameters({ f: "pjson" }, true);
const data = await I3SDataProvider.loadJson(resource);
const provider = new I3SDataProvider(options);
provider._resource = resource;
provider._data = data;
if (defined_default(data.layers)) {
const promises = [];
for (let layerIndex = 0; layerIndex < data.layers.length; layerIndex++) {
const promise = addLayers(provider, data.layers[layerIndex], options);
promises.push(promise);
}
await Promise.all(promises);
} else {
await addLayers(provider, data, options);
}
provider._computeExtent();
const layerPromises = [];
for (let i = 0; i < provider._layers.length; i++) {
layerPromises.push(
provider._layers[i].load(options.cesium3dTilesetOptions)
);
}
await Promise.all(layerPromises);
return provider;
};
I3SDataProvider._fetchJson = function(resource) {
return resource.fetchJson();
};
I3SDataProvider.loadJson = async function(resource) {
const data = await I3SDataProvider._fetchJson(resource);
if (defined_default(data.error)) {
console.error("Failed to fetch I3S ", resource.url);
if (defined_default(data.error.message)) {
console.error(data.error.message);
}
if (defined_default(data.error.details)) {
for (let i = 0; i < data.error.details.length; i++) {
console.log(data.error.details[i]);
}
}
throw new RuntimeError_default(data.error);
}
return data;
};
I3SDataProvider.prototype._loadBinary = async function(resource) {
const buffer2 = await resource.fetchArrayBuffer();
if (buffer2.byteLength > 0) {
const array = new Uint8Array(buffer2);
if (array[0] === "{".charCodeAt(0)) {
const textContent = new TextDecoder();
const str = textContent.decode(buffer2);
if (str.includes("404")) {
throw new RuntimeError_default(`Failed to load binary: ${resource.url}`);
}
}
}
return buffer2;
};
I3SDataProvider.prototype._binarizeGltf = function(rawGltf) {
const encoder = new TextEncoder();
const rawGltfData = encoder.encode(JSON.stringify(rawGltf));
const binaryGltfData = new Uint8Array(rawGltfData.byteLength + 20);
const binaryGltf = {
magic: new Uint8Array(binaryGltfData.buffer, 0, 4),
version: new Uint32Array(binaryGltfData.buffer, 4, 1),
length: new Uint32Array(binaryGltfData.buffer, 8, 1),
chunkLength: new Uint32Array(binaryGltfData.buffer, 12, 1),
chunkType: new Uint32Array(binaryGltfData.buffer, 16, 1),
chunkData: new Uint8Array(
binaryGltfData.buffer,
20,
rawGltfData.byteLength
)
};
binaryGltf.magic[0] = "g".charCodeAt();
binaryGltf.magic[1] = "l".charCodeAt();
binaryGltf.magic[2] = "T".charCodeAt();
binaryGltf.magic[3] = "F".charCodeAt();
binaryGltf.version[0] = 2;
binaryGltf.length[0] = binaryGltfData.byteLength;
binaryGltf.chunkLength[0] = rawGltfData.byteLength;
binaryGltf.chunkType[0] = 1313821514;
binaryGltf.chunkData.set(rawGltfData);
return binaryGltfData;
};
var scratchCartesian213 = new Cartesian2_default();
function getCoveredTiles(terrainProvider, extent) {
const tilingScheme2 = terrainProvider.tilingScheme;
const tileRequests = [];
const tileRequestSet = {};
const maxLevel = terrainProvider._lodCount;
const topLeftCorner = Cartographic_default.fromRadians(extent.west, extent.north);
const bottomRightCorner = Cartographic_default.fromRadians(extent.east, extent.south);
const minCornerXY = tilingScheme2.positionToTileXY(topLeftCorner, maxLevel);
const maxCornerXY = tilingScheme2.positionToTileXY(
bottomRightCorner,
maxLevel
);
for (let x = minCornerXY.x; x <= maxCornerXY.x; x++) {
for (let y = minCornerXY.y; y <= maxCornerXY.y; y++) {
const xy = Cartesian2_default.fromElements(x, y, scratchCartesian213);
const key = xy.toString();
if (!tileRequestSet.hasOwnProperty(key)) {
const value = {
x: xy.x,
y: xy.y,
level: maxLevel,
tilingScheme: tilingScheme2,
terrainProvider,
positions: []
};
tileRequestSet[key] = value;
tileRequests.push(value);
}
}
}
const tilePromises = [];
for (let i = 0; i < tileRequests.length; ++i) {
const tileRequest = tileRequests[i];
const requestPromise = tileRequest.terrainProvider.requestTileGeometry(
tileRequest.x,
tileRequest.y,
tileRequest.level
);
tilePromises.push(requestPromise);
}
return Promise.all(tilePromises).then(function(heightMapBuffers) {
const heightMaps = [];
for (let i = 0; i < heightMapBuffers.length; i++) {
const options = {
tilingScheme: tilingScheme2,
x: tileRequests[i].x,
y: tileRequests[i].y,
level: tileRequests[i].level
};
const heightMap = heightMapBuffers[i];
let projectionType = "Geographic";
if (tilingScheme2._projection instanceof WebMercatorProjection_default) {
projectionType = "WebMercator";
}
const heightMapData = {
projectionType,
projection: tilingScheme2._projection,
nativeExtent: tilingScheme2.tileXYToNativeRectangle(
options.x,
options.y,
options.level
),
height: heightMap._height,
width: heightMap._width,
scale: heightMap._structure.heightScale,
offset: heightMap._structure.heightOffset
};
if (heightMap._encoding === HeightmapEncoding_default.LERC) {
const result = import_lerc.default.decode(heightMap._buffer);
heightMapData.buffer = result.pixels[0];
} else {
heightMapData.buffer = heightMap._buffer;
}
heightMaps.push(heightMapData);
}
return heightMaps;
});
}
async function loadGeoidData(provider) {
const geoidTerrainProvider = provider._geoidTiledTerrainProvider;
if (!defined_default(geoidTerrainProvider)) {
return;
}
try {
const heightMaps = await getCoveredTiles(
geoidTerrainProvider,
provider._extent
);
provider._geoidDataList = heightMaps;
} catch (error) {
console.log(
"Error retrieving Geoid Terrain tiles - no geoid conversion will be performed."
);
}
}
I3SDataProvider.prototype.loadGeoidData = async function() {
if (defined_default(this._geoidDataPromise)) {
return this._geoidDataPromise;
}
this._geoidDataPromise = loadGeoidData(this);
return this._geoidDataPromise;
};
I3SDataProvider.prototype._computeExtent = function() {
let rectangle;
for (let layerIndex = 0; layerIndex < this._layersExtent.length; layerIndex++) {
const layerExtent = this._layersExtent[layerIndex];
if (!defined_default(rectangle)) {
rectangle = Rectangle_default.clone(layerExtent);
} else {
Rectangle_default.union(rectangle, layerExtent, rectangle);
}
}
this._extent = rectangle;
};
I3SDataProvider.prototype.getAttributeNames = function() {
const attributes = [];
for (let i = 0; i < this._attributeStatistics.length; ++i) {
attributes.push(...this._attributeStatistics[i].names);
}
return attributes;
};
I3SDataProvider.prototype.getAttributeValues = function(name) {
Check_default.defined("name", name);
for (let i = 0; i < this._attributeStatistics.length; ++i) {
const values = this._attributeStatistics[i]._getValues(name);
if (defined_default(values)) {
return values;
}
}
return [];
};
I3SDataProvider.prototype.filterByAttributes = function(filters) {
const promises = [];
for (let i = 0; i < this._layers.length; i++) {
const promise = this._layers[i].filterByAttributes(filters);
promises.push(promise);
}
return Promise.all(promises);
};
var I3SDataProvider_default = I3SDataProvider;
// packages/engine/Source/Scene/ITwinData.js
var import_InlineWorkers1261 = __toESM(require_InlineWorkers(), 1);
var ITwinData = {};
ITwinData.createTilesetFromIModelId = async function({
iModelId,
changesetId,
tilesetOptions
}) {
const { exports: exports2 } = await ITwinPlatform_default.getExports(iModelId, changesetId);
if (exports2.length > 0 && exports2.every((exportObj) => {
return exportObj.status === ITwinPlatform_default.ExportStatus.Invalid;
})) {
throw new RuntimeError_default(
`All exports for this iModel are Invalid: ${iModelId}`
);
}
const completeExport = exports2.find((exportObj) => {
return exportObj.status === ITwinPlatform_default.ExportStatus.Complete;
});
if (!defined_default(completeExport)) {
return;
}
const baseUrl = new URL(completeExport._links.mesh.href);
baseUrl.pathname = `${baseUrl.pathname}/tileset.json`;
const tilesetUrl = baseUrl.toString();
const resource = new Resource_default({
url: tilesetUrl
});
return Cesium3DTileset_default.fromUrl(resource, tilesetOptions);
};
ITwinData.createTilesetForRealityDataId = async function({
iTwinId,
realityDataId,
type,
rootDocument,
tilesetOptions
}) {
Check_default.typeOf.string("iTwinId", iTwinId);
Check_default.typeOf.string("realityDataId", realityDataId);
if (defined_default(type)) {
Check_default.typeOf.string("type", type);
}
if (defined_default(rootDocument)) {
Check_default.typeOf.string("rootDocument", rootDocument);
}
if (!defined_default(type) || !defined_default(rootDocument)) {
const metadata = await ITwinPlatform_default.getRealityDataMetadata(
iTwinId,
realityDataId
);
rootDocument = metadata.rootDocument;
type = metadata.type;
}
const supportedRealityDataTypes = [
ITwinPlatform_default.RealityDataType.Cesium3DTiles,
ITwinPlatform_default.RealityDataType.PNTS,
ITwinPlatform_default.RealityDataType.RealityMesh3DTiles,
ITwinPlatform_default.RealityDataType.Terrain3DTiles
];
if (!supportedRealityDataTypes.includes(type)) {
throw new RuntimeError_default(`Reality data type is not a mesh type: ${type}`);
}
const tilesetAccessUrl = await ITwinPlatform_default.getRealityDataURL(
iTwinId,
realityDataId,
rootDocument
);
const internalTilesetOptions = {
maximumScreenSpaceError: 4,
...tilesetOptions
};
return Cesium3DTileset_default.fromUrl(tilesetAccessUrl, internalTilesetOptions);
};
ITwinData.createDataSourceForRealityDataId = async function({
iTwinId,
realityDataId,
type,
rootDocument
}) {
Check_default.typeOf.string("iTwinId", iTwinId);
Check_default.typeOf.string("realityDataId", realityDataId);
if (defined_default(type)) {
Check_default.typeOf.string("type", type);
}
if (defined_default(rootDocument)) {
Check_default.typeOf.string("rootDocument", rootDocument);
}
if (!defined_default(type) || !defined_default(rootDocument)) {
const metadata = await ITwinPlatform_default.getRealityDataMetadata(
iTwinId,
realityDataId
);
rootDocument = metadata.rootDocument;
type = metadata.type;
}
const supportedRealityDataTypes = [
ITwinPlatform_default.RealityDataType.KML,
ITwinPlatform_default.RealityDataType.GeoJSON
];
if (!supportedRealityDataTypes.includes(type)) {
throw new RuntimeError_default(
`Reality data type is not a data source type: ${type}`
);
}
const tilesetAccessUrl = await ITwinPlatform_default.getRealityDataURL(
iTwinId,
realityDataId,
rootDocument
);
if (type === ITwinPlatform_default.RealityDataType.GeoJSON) {
return GeoJsonDataSource_default.load(tilesetAccessUrl);
}
return KmlDataSource_default.load(tilesetAccessUrl);
};
ITwinData.loadGeospatialFeatures = async function({
iTwinId,
collectionId,
limit
}) {
Check_default.typeOf.string("iTwinId", iTwinId);
Check_default.typeOf.string("collectionId", collectionId);
if (defined_default(limit)) {
Check_default.typeOf.number("limit", limit);
Check_default.typeOf.number.lessThanOrEquals("limit", limit, 1e4);
Check_default.typeOf.number.greaterThanOrEquals("limit", limit, 1);
}
if (!defined_default(ITwinPlatform_default.defaultAccessToken) && !defined_default(ITwinPlatform_default.defaultShareKey)) {
throw new DeveloperError_default(
"Must set ITwinPlatform.defaultAccessToken or ITwinPlatform.defaultShareKey first"
);
}
const pageLimit = limit ?? 1e4;
const tilesetUrl = `${ITwinPlatform_default.apiEndpoint}geospatial-features/itwins/${iTwinId}/ogc/collections/${collectionId}/items`;
const resource = new Resource_default({
url: tilesetUrl,
headers: {
Authorization: ITwinPlatform_default._getAuthorizationHeader(),
Accept: "application/vnd.bentley.itwin-platform.v1+json"
},
queryParameters: {
limit: pageLimit,
client: "CesiumJS"
}
});
return GeoJsonDataSource_default.load(resource);
};
var ITwinData_default = ITwinData;
// packages/engine/Source/Scene/Light.js
var import_InlineWorkers1262 = __toESM(require_InlineWorkers(), 1);
function Light() {
}
Object.defineProperties(Light.prototype, {
/**
* The color of the light.
* @memberof Light.prototype
* @type {Color}
*/
color: {
get: DeveloperError_default.throwInstantiationError
},
/**
* The intensity controls the strength of the light. intensity has a minimum value of 0.0 and no maximum value.
* @memberof Light.prototype
* @type {number}
*/
intensity: {
get: DeveloperError_default.throwInstantiationError
}
});
var Light_default = Light;
// packages/engine/Source/Scene/MapboxStyleImageryProvider.js
var import_InlineWorkers1263 = __toESM(require_InlineWorkers(), 1);
var trailingSlashRegex2 = /\/$/;
var defaultCredit3 = new Credit_default(
'© Mapbox © OpenStreetMap Improve this map'
);
function MapboxStyleImageryProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const styleId = options.styleId;
if (!defined_default(styleId)) {
throw new DeveloperError_default("options.styleId is required.");
}
const accessToken = options.accessToken;
if (!defined_default(accessToken)) {
throw new DeveloperError_default("options.accessToken is required.");
}
this._defaultAlpha = void 0;
this._defaultNightAlpha = void 0;
this._defaultDayAlpha = void 0;
this._defaultBrightness = void 0;
this._defaultContrast = void 0;
this._defaultHue = void 0;
this._defaultSaturation = void 0;
this._defaultGamma = void 0;
this._defaultMinificationFilter = void 0;
this._defaultMagnificationFilter = void 0;
const resource = Resource_default.createIfNeeded(
options.url ?? "https://api.mapbox.com/styles/v1/"
);
this._styleId = styleId;
this._accessToken = accessToken;
const tilesize = options.tilesize ?? 512;
this._tilesize = tilesize;
const username = options.username ?? "mapbox";
this._username = username;
const scaleFactor = defined_default(options.scaleFactor) ? "@2x" : "";
let templateUrl = resource.getUrlComponent();
if (!trailingSlashRegex2.test(templateUrl)) {
templateUrl += "/";
}
templateUrl += `${this._username}/${styleId}/tiles/${this._tilesize}/{z}/{x}/{y}${scaleFactor}`;
resource.url = templateUrl;
resource.setQueryParameters({
access_token: accessToken
});
let credit;
if (defined_default(options.credit)) {
credit = options.credit;
if (typeof credit === "string") {
credit = new Credit_default(credit);
}
} else {
credit = defaultCredit3;
}
this._resource = resource;
this._imageryProvider = new UrlTemplateImageryProvider_default({
url: resource,
credit,
ellipsoid: options.ellipsoid,
minimumLevel: options.minimumLevel,
maximumLevel: options.maximumLevel,
rectangle: options.rectangle
});
}
Object.defineProperties(MapboxStyleImageryProvider.prototype, {
/**
* Gets the URL of the Mapbox server.
* @memberof MapboxStyleImageryProvider.prototype
* @type {string}
* @readonly
*/
url: {
get: function() {
return this._imageryProvider.url;
}
},
/**
* Gets the rectangle, in radians, of the imagery provided by the instance.
* @memberof MapboxStyleImageryProvider.prototype
* @type {Rectangle}
* @readonly
*/
rectangle: {
get: function() {
return this._imageryProvider.rectangle;
}
},
/**
* Gets the width of each tile, in pixels.
* @memberof MapboxStyleImageryProvider.prototype
* @type {number}
* @readonly
*/
tileWidth: {
get: function() {
return this._imageryProvider.tileWidth;
}
},
/**
* Gets the height of each tile, in pixels.
* @memberof MapboxStyleImageryProvider.prototype
* @type {number}
* @readonly
*/
tileHeight: {
get: function() {
return this._imageryProvider.tileHeight;
}
},
/**
* Gets the maximum level-of-detail that can be requested.
* @memberof MapboxStyleImageryProvider.prototype
* @type {number|undefined}
* @readonly
*/
maximumLevel: {
get: function() {
return this._imageryProvider.maximumLevel;
}
},
/**
* Gets the minimum level-of-detail that can be requested. Generally,
* a minimum level should only be used when the rectangle of the imagery is small
* enough that the number of tiles at the minimum level is small. An imagery
* provider with more than a few tiles at the minimum level will lead to
* rendering problems.
* @memberof MapboxStyleImageryProvider.prototype
* @type {number}
* @readonly
*/
minimumLevel: {
get: function() {
return this._imageryProvider.minimumLevel;
}
},
/**
* Gets the tiling scheme used by the provider.
* @memberof MapboxStyleImageryProvider.prototype
* @type {TilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._imageryProvider.tilingScheme;
}
},
/**
* Gets the tile discard policy. If not undefined, the discard policy is responsible
* for filtering out "missing" tiles via its shouldDiscardImage function. If this function
* returns undefined, no tiles are filtered.
* @memberof MapboxStyleImageryProvider.prototype
* @type {TileDiscardPolicy}
* @readonly
*/
tileDiscardPolicy: {
get: function() {
return this._imageryProvider.tileDiscardPolicy;
}
},
/**
* Gets an event that is raised when the imagery provider encounters an asynchronous error.. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof MapboxStyleImageryProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._imageryProvider.errorEvent;
}
},
/**
* Gets the credit to display when this imagery provider is active. Typically this is used to credit
* the source of the imagery.
* @memberof MapboxStyleImageryProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return this._imageryProvider.credit;
}
},
/**
* Gets the proxy used by this provider.
* @memberof MapboxStyleImageryProvider.prototype
* @type {Proxy}
* @readonly
*/
proxy: {
get: function() {
return this._imageryProvider.proxy;
}
},
/**
* Gets a value indicating whether or not the images provided by this imagery provider
* include an alpha channel. If this property is false, an alpha channel, if present, will
* be ignored. If this property is true, any images without an alpha channel will be treated
* as if their alpha is 1.0 everywhere. When this property is false, memory usage
* and texture upload time are reduced.
* @memberof MapboxStyleImageryProvider.prototype
* @type {boolean}
* @readonly
*/
hasAlphaChannel: {
get: function() {
return this._imageryProvider.hasAlphaChannel;
}
}
});
MapboxStyleImageryProvider.prototype.getTileCredits = function(x, y, level) {
return void 0;
};
MapboxStyleImageryProvider.prototype.requestImage = function(x, y, level, request) {
return this._imageryProvider.requestImage(x, y, level, request);
};
MapboxStyleImageryProvider.prototype.pickFeatures = function(x, y, level, longitude, latitude) {
return this._imageryProvider.pickFeatures(x, y, level, longitude, latitude);
};
MapboxStyleImageryProvider._defaultCredit = defaultCredit3;
var MapboxStyleImageryProvider_default = MapboxStyleImageryProvider;
// packages/engine/Source/Scene/NeverTileDiscardPolicy.js
var import_InlineWorkers1264 = __toESM(require_InlineWorkers(), 1);
function NeverTileDiscardPolicy(options) {
}
NeverTileDiscardPolicy.prototype.isReady = function() {
return true;
};
NeverTileDiscardPolicy.prototype.shouldDiscardImage = function(image) {
return false;
};
var NeverTileDiscardPolicy_default = NeverTileDiscardPolicy;
// packages/engine/Source/Scene/OpenStreetMapImageryProvider.js
var import_InlineWorkers1265 = __toESM(require_InlineWorkers(), 1);
var defaultCredit4 = new Credit_default(
"MapQuest, Open Street Map and contributors, CC-BY-SA"
);
function OpenStreetMapImageryProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const resource = Resource_default.createIfNeeded(
options.url ?? "https://tile.openstreetmap.org/"
);
resource.appendForwardSlash();
resource.url += `{z}/{x}/{y}${options.retinaTiles ? "@2x" : ""}.${options.fileExtension ?? "png"}`;
const tilingScheme2 = new WebMercatorTilingScheme_default({
ellipsoid: options.ellipsoid
});
const tileWidth = 256;
const tileHeight = 256;
const minimumLevel = options.minimumLevel ?? 0;
const maximumLevel = options.maximumLevel;
const rectangle = options.rectangle ?? tilingScheme2.rectangle;
const swTile = tilingScheme2.positionToTileXY(
Rectangle_default.southwest(rectangle),
minimumLevel
);
const neTile = tilingScheme2.positionToTileXY(
Rectangle_default.northeast(rectangle),
minimumLevel
);
const tileCount = (Math.abs(neTile.x - swTile.x) + 1) * (Math.abs(neTile.y - swTile.y) + 1);
if (tileCount > 4) {
throw new DeveloperError_default(
`The rectangle and minimumLevel indicate that there are ${tileCount} tiles at the minimum level. Imagery providers with more than four tiles at the minimum level are not supported.`
);
}
let credit = options.credit ?? defaultCredit4;
if (typeof credit === "string") {
credit = new Credit_default(credit);
}
UrlTemplateImageryProvider_default.call(this, {
url: resource,
credit,
tilingScheme: tilingScheme2,
tileWidth,
tileHeight,
minimumLevel,
maximumLevel,
rectangle
});
}
if (defined_default(Object.create)) {
OpenStreetMapImageryProvider.prototype = Object.create(
UrlTemplateImageryProvider_default.prototype
);
OpenStreetMapImageryProvider.prototype.constructor = OpenStreetMapImageryProvider;
}
var OpenStreetMapImageryProvider_default = OpenStreetMapImageryProvider;
// packages/engine/Source/Scene/Particle.js
var import_InlineWorkers1266 = __toESM(require_InlineWorkers(), 1);
var defaultSize = new Cartesian2_default(1, 1);
function Particle(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.mass = options.mass ?? 1;
this.position = Cartesian3_default.clone(options.position ?? Cartesian3_default.ZERO);
this.velocity = Cartesian3_default.clone(options.velocity ?? Cartesian3_default.ZERO);
this.life = options.life ?? Number.MAX_VALUE;
this.image = options.image;
this.startColor = Color_default.clone(options.startColor ?? Color_default.WHITE);
this.endColor = Color_default.clone(options.endColor ?? Color_default.WHITE);
this.startScale = options.startScale ?? 1;
this.endScale = options.endScale ?? 1;
this.imageSize = Cartesian2_default.clone(options.imageSize ?? defaultSize);
this._age = 0;
this._normalizedAge = 0;
this._billboard = void 0;
}
Object.defineProperties(Particle.prototype, {
/**
* Gets the age of the particle in seconds.
* @memberof Particle.prototype
* @type {number}
*/
age: {
get: function() {
return this._age;
}
},
/**
* Gets the age normalized to a value in the range [0.0, 1.0].
* @memberof Particle.prototype
* @type {number}
*/
normalizedAge: {
get: function() {
return this._normalizedAge;
}
}
});
var deltaScratch = new Cartesian3_default();
Particle.prototype.update = function(dt, particleUpdateFunction) {
Cartesian3_default.multiplyByScalar(this.velocity, dt, deltaScratch);
Cartesian3_default.add(this.position, deltaScratch, this.position);
if (defined_default(particleUpdateFunction)) {
particleUpdateFunction(this, dt);
}
this._age += dt;
if (this.life === Number.MAX_VALUE) {
this._normalizedAge = 0;
} else {
this._normalizedAge = this._age / this.life;
}
return this._age <= this.life;
};
var Particle_default = Particle;
// packages/engine/Source/Scene/ParticleBurst.js
var import_InlineWorkers1267 = __toESM(require_InlineWorkers(), 1);
function ParticleBurst(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.time = options.time ?? 0;
this.minimum = options.minimum ?? 0;
this.maximum = options.maximum ?? 50;
this._complete = false;
}
Object.defineProperties(ParticleBurst.prototype, {
/**
* true if the burst has been completed; false otherwise.
* @memberof ParticleBurst.prototype
* @type {boolean}
*/
complete: {
get: function() {
return this._complete;
}
}
});
var ParticleBurst_default = ParticleBurst;
// packages/engine/Source/Scene/ParticleEmitter.js
var import_InlineWorkers1268 = __toESM(require_InlineWorkers(), 1);
function ParticleEmitter(options) {
throw new DeveloperError_default(
"This type should not be instantiated directly. Instead, use BoxEmitter, CircleEmitter, ConeEmitter or SphereEmitter."
);
}
ParticleEmitter.prototype.emit = function(particle) {
DeveloperError_default.throwInstantiationError();
};
var ParticleEmitter_default = ParticleEmitter;
// packages/engine/Source/Scene/ParticleSystem.js
var import_InlineWorkers1269 = __toESM(require_InlineWorkers(), 1);
var defaultImageSize = new Cartesian2_default(1, 1);
function ParticleSystem(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this.show = options.show ?? true;
this.updateCallback = options.updateCallback;
this.loop = options.loop ?? true;
this.image = options.image ?? void 0;
let emitter = options.emitter;
if (!defined_default(emitter)) {
emitter = new CircleEmitter_default(0.5);
}
this._emitter = emitter;
this._bursts = options.bursts;
this._modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
this._emitterModelMatrix = Matrix4_default.clone(
options.emitterModelMatrix ?? Matrix4_default.IDENTITY
);
this._matrixDirty = true;
this._combinedMatrix = new Matrix4_default();
this._startColor = Color_default.clone(
options.color ?? options.startColor ?? Color_default.WHITE
);
this._endColor = Color_default.clone(
options.color ?? options.endColor ?? Color_default.WHITE
);
this._startScale = options.scale ?? options.startScale ?? 1;
this._endScale = options.scale ?? options.endScale ?? 1;
this._emissionRate = options.emissionRate ?? 5;
this._minimumSpeed = options.speed ?? options.minimumSpeed ?? 1;
this._maximumSpeed = options.speed ?? options.maximumSpeed ?? 1;
this._minimumParticleLife = options.particleLife ?? options.minimumParticleLife ?? 5;
this._maximumParticleLife = options.particleLife ?? options.maximumParticleLife ?? 5;
this._minimumMass = options.mass ?? options.minimumMass ?? 1;
this._maximumMass = options.mass ?? options.maximumMass ?? 1;
this._minimumImageSize = Cartesian2_default.clone(
options.imageSize ?? options.minimumImageSize ?? defaultImageSize
);
this._maximumImageSize = Cartesian2_default.clone(
options.imageSize ?? options.maximumImageSize ?? defaultImageSize
);
this._sizeInMeters = options.sizeInMeters ?? false;
this._lifetime = options.lifetime ?? Number.MAX_VALUE;
this._billboardCollection = void 0;
this._particles = [];
this._particlePool = [];
this._previousTime = void 0;
this._currentTime = 0;
this._carryOver = 0;
this._complete = new Event_default();
this._isComplete = false;
this._updateParticlePool = true;
this._particleEstimate = 0;
}
Object.defineProperties(ParticleSystem.prototype, {
/**
* The particle emitter for this
* @memberof ParticleSystem.prototype
* @type {ParticleEmitter}
* @default CircleEmitter
*/
emitter: {
get: function() {
return this._emitter;
},
set: function(value) {
Check_default.defined("value", value);
this._emitter = value;
}
},
/**
* An array of {@link ParticleBurst}, emitting bursts of particles at periodic times.
* @memberof ParticleSystem.prototype
* @type {ParticleBurst[]}
* @default undefined
*/
bursts: {
get: function() {
return this._bursts;
},
set: function(value) {
this._bursts = value;
this._updateParticlePool = true;
}
},
/**
* The 4x4 transformation matrix that transforms the particle system from model to world coordinates.
* @memberof ParticleSystem.prototype
* @type {Matrix4}
* @default Matrix4.IDENTITY
*/
modelMatrix: {
get: function() {
return this._modelMatrix;
},
set: function(value) {
Check_default.defined("value", value);
this._matrixDirty = this._matrixDirty || !Matrix4_default.equals(this._modelMatrix, value);
Matrix4_default.clone(value, this._modelMatrix);
}
},
/**
* The 4x4 transformation matrix that transforms the particle system emitter within the particle systems local coordinate system.
* @memberof ParticleSystem.prototype
* @type {Matrix4}
* @default Matrix4.IDENTITY
*/
emitterModelMatrix: {
get: function() {
return this._emitterModelMatrix;
},
set: function(value) {
Check_default.defined("value", value);
this._matrixDirty = this._matrixDirty || !Matrix4_default.equals(this._emitterModelMatrix, value);
Matrix4_default.clone(value, this._emitterModelMatrix);
}
},
/**
* The color of the particle at the beginning of its life.
* @memberof ParticleSystem.prototype
* @type {Color}
* @default Color.WHITE
*/
startColor: {
get: function() {
return this._startColor;
},
set: function(value) {
Check_default.defined("value", value);
Color_default.clone(value, this._startColor);
}
},
/**
* The color of the particle at the end of its life.
* @memberof ParticleSystem.prototype
* @type {Color}
* @default Color.WHITE
*/
endColor: {
get: function() {
return this._endColor;
},
set: function(value) {
Check_default.defined("value", value);
Color_default.clone(value, this._endColor);
}
},
/**
* The initial scale to apply to the image of the particle at the beginning of its life.
* @memberof ParticleSystem.prototype
* @type {number}
* @default 1.0
*/
startScale: {
get: function() {
return this._startScale;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._startScale = value;
}
},
/**
* The final scale to apply to the image of the particle at the end of its life.
* @memberof ParticleSystem.prototype
* @type {number}
* @default 1.0
*/
endScale: {
get: function() {
return this._endScale;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._endScale = value;
}
},
/**
* The number of particles to emit per second.
* @memberof ParticleSystem.prototype
* @type {number}
* @default 5
*/
emissionRate: {
get: function() {
return this._emissionRate;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._emissionRate = value;
this._updateParticlePool = true;
}
},
/**
* Sets the minimum bound in meters per second above which a particle's actual speed will be randomly chosen.
* @memberof ParticleSystem.prototype
* @type {number}
* @default 1.0
*/
minimumSpeed: {
get: function() {
return this._minimumSpeed;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._minimumSpeed = value;
}
},
/**
* Sets the maximum bound in meters per second below which a particle's actual speed will be randomly chosen.
* @memberof ParticleSystem.prototype
* @type {number}
* @default 1.0
*/
maximumSpeed: {
get: function() {
return this._maximumSpeed;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._maximumSpeed = value;
}
},
/**
* Sets the minimum bound in seconds for the possible duration of a particle's life above which a particle's actual life will be randomly chosen.
* @memberof ParticleSystem.prototype
* @type {number}
* @default 5.0
*/
minimumParticleLife: {
get: function() {
return this._minimumParticleLife;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._minimumParticleLife = value;
}
},
/**
* Sets the maximum bound in seconds for the possible duration of a particle's life below which a particle's actual life will be randomly chosen.
* @memberof ParticleSystem.prototype
* @type {number}
* @default 5.0
*/
maximumParticleLife: {
get: function() {
return this._maximumParticleLife;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._maximumParticleLife = value;
this._updateParticlePool = true;
}
},
/**
* Sets the minimum mass of particles in kilograms.
* @memberof ParticleSystem.prototype
* @type {number}
* @default 1.0
*/
minimumMass: {
get: function() {
return this._minimumMass;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._minimumMass = value;
}
},
/**
* Sets the maximum mass of particles in kilograms.
* @memberof ParticleSystem.prototype
* @type {number}
* @default 1.0
*/
maximumMass: {
get: function() {
return this._maximumMass;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._maximumMass = value;
}
},
/**
* Sets the minimum bound, width by height, above which to randomly scale the particle image's dimensions in pixels.
* @memberof ParticleSystem.prototype
* @type {Cartesian2}
* @default new Cartesian2(1.0, 1.0)
*/
minimumImageSize: {
get: function() {
return this._minimumImageSize;
},
set: function(value) {
Check_default.typeOf.object("value", value);
Check_default.typeOf.number.greaterThanOrEquals("value.x", value.x, 0);
Check_default.typeOf.number.greaterThanOrEquals("value.y", value.y, 0);
this._minimumImageSize = value;
}
},
/**
* Sets the maximum bound, width by height, below which to randomly scale the particle image's dimensions in pixels.
* @memberof ParticleSystem.prototype
* @type {Cartesian2}
* @default new Cartesian2(1.0, 1.0)
*/
maximumImageSize: {
get: function() {
return this._maximumImageSize;
},
set: function(value) {
Check_default.typeOf.object("value", value);
Check_default.typeOf.number.greaterThanOrEquals("value.x", value.x, 0);
Check_default.typeOf.number.greaterThanOrEquals("value.y", value.y, 0);
this._maximumImageSize = value;
}
},
/**
* Gets or sets if the particle size is in meters or pixels. true to size particles in meters; otherwise, the size is in pixels.
* @memberof ParticleSystem.prototype
* @type {boolean}
* @default false
*/
sizeInMeters: {
get: function() {
return this._sizeInMeters;
},
set: function(value) {
Check_default.typeOf.bool("value", value);
this._sizeInMeters = value;
}
},
/**
* How long the particle system will emit particles, in seconds.
* @memberof ParticleSystem.prototype
* @type {number}
* @default Number.MAX_VALUE
*/
lifetime: {
get: function() {
return this._lifetime;
},
set: function(value) {
Check_default.typeOf.number.greaterThanOrEquals("value", value, 0);
this._lifetime = value;
}
},
/**
* Fires an event when the particle system has reached the end of its lifetime.
* @memberof ParticleSystem.prototype
* @type {Event}
*/
complete: {
get: function() {
return this._complete;
}
},
/**
* When true, the particle system has reached the end of its lifetime; false otherwise.
* @memberof ParticleSystem.prototype
* @type {boolean}
*/
isComplete: {
get: function() {
return this._isComplete;
}
}
});
function updateParticlePool(system) {
const emissionRate = system._emissionRate;
const life = system._maximumParticleLife;
let burstAmount = 0;
const bursts = system._bursts;
if (defined_default(bursts)) {
const length2 = bursts.length;
for (let i = 0; i < length2; ++i) {
burstAmount += bursts[i].maximum;
}
}
const billboardCollection = system._billboardCollection;
const image = system.image;
const particleEstimate = Math.ceil(emissionRate * life + burstAmount);
const particles = system._particles;
const particlePool = system._particlePool;
const numToAdd = Math.max(
particleEstimate - particles.length - particlePool.length,
0
);
for (let j = 0; j < numToAdd; ++j) {
const particle = new Particle_default();
particle._billboard = billboardCollection.add({
image,
// Make the newly added billboards invisible when updating the particle pool
// to prevent the billboards from being displayed when the particles
// are not created. The billboard will always be set visible in
// updateBillboard function when its corresponding particle update.
show: false
});
particlePool.push(particle);
}
system._particleEstimate = particleEstimate;
}
function getOrCreateParticle(system) {
let particle = system._particlePool.pop();
if (!defined_default(particle)) {
particle = new Particle_default();
}
return particle;
}
function addParticleToPool(system, particle) {
system._particlePool.push(particle);
}
function freeParticlePool(system) {
const particles = system._particles;
const particlePool = system._particlePool;
const billboardCollection = system._billboardCollection;
const numParticles = particles.length;
const numInPool = particlePool.length;
const estimate = system._particleEstimate;
const start = numInPool - Math.max(estimate - numParticles - numInPool, 0);
for (let i = start; i < numInPool; ++i) {
const p = particlePool[i];
billboardCollection.remove(p._billboard);
}
particlePool.length = start;
}
function removeBillboard(particle) {
if (defined_default(particle._billboard)) {
particle._billboard.show = false;
}
}
function updateBillboard(system, particle) {
let billboard = particle._billboard;
if (!defined_default(billboard)) {
billboard = particle._billboard = system._billboardCollection.add({
image: particle.image
});
}
billboard.width = particle.imageSize.x;
billboard.height = particle.imageSize.y;
billboard.position = particle.position;
billboard.sizeInMeters = system.sizeInMeters;
billboard.show = true;
const r = Math_default.lerp(
particle.startColor.red,
particle.endColor.red,
particle.normalizedAge
);
const g = Math_default.lerp(
particle.startColor.green,
particle.endColor.green,
particle.normalizedAge
);
const b = Math_default.lerp(
particle.startColor.blue,
particle.endColor.blue,
particle.normalizedAge
);
const a3 = Math_default.lerp(
particle.startColor.alpha,
particle.endColor.alpha,
particle.normalizedAge
);
billboard.color = new Color_default(r, g, b, a3);
billboard.scale = Math_default.lerp(
particle.startScale,
particle.endScale,
particle.normalizedAge
);
}
function addParticle(system, particle) {
particle.startColor = Color_default.clone(system._startColor, particle.startColor);
particle.endColor = Color_default.clone(system._endColor, particle.endColor);
particle.startScale = system._startScale;
particle.endScale = system._endScale;
particle.image = system.image;
particle.life = Math_default.randomBetween(
system._minimumParticleLife,
system._maximumParticleLife
);
particle.mass = Math_default.randomBetween(
system._minimumMass,
system._maximumMass
);
particle.imageSize.x = Math_default.randomBetween(
system._minimumImageSize.x,
system._maximumImageSize.x
);
particle.imageSize.y = Math_default.randomBetween(
system._minimumImageSize.y,
system._maximumImageSize.y
);
particle._normalizedAge = 0;
particle._age = 0;
const speed = Math_default.randomBetween(
system._minimumSpeed,
system._maximumSpeed
);
Cartesian3_default.multiplyByScalar(particle.velocity, speed, particle.velocity);
system._particles.push(particle);
}
function calculateNumberToEmit(system, dt) {
if (system._isComplete) {
return 0;
}
dt = Math_default.mod(dt, system._lifetime);
const v3 = dt * system._emissionRate;
let numToEmit = Math.floor(v3);
system._carryOver += v3 - numToEmit;
if (system._carryOver > 1) {
numToEmit++;
system._carryOver -= 1;
}
if (defined_default(system.bursts)) {
const length2 = system.bursts.length;
for (let i = 0; i < length2; i++) {
const burst = system.bursts[i];
const currentTime = system._currentTime;
if (defined_default(burst) && !burst._complete && currentTime > burst.time) {
numToEmit += Math_default.randomBetween(burst.minimum, burst.maximum);
burst._complete = true;
}
}
}
return numToEmit;
}
var rotatedVelocityScratch = new Cartesian3_default();
ParticleSystem.prototype.update = function(frameState) {
if (!this.show) {
return;
}
if (!defined_default(this._billboardCollection)) {
this._billboardCollection = new BillboardCollection_default();
}
if (this._updateParticlePool) {
updateParticlePool(this);
this._updateParticlePool = false;
}
let dt = 0;
if (this._previousTime) {
dt = JulianDate_default.secondsDifference(frameState.time, this._previousTime);
}
if (dt < 0) {
dt = 0;
}
const particles = this._particles;
const emitter = this._emitter;
const updateCallback = this.updateCallback;
let i;
let particle;
let length2 = particles.length;
for (i = 0; i < length2; ++i) {
particle = particles[i];
if (!particle.update(dt, updateCallback)) {
removeBillboard(particle);
addParticleToPool(this, particle);
particles[i] = particles[length2 - 1];
--i;
--length2;
} else {
updateBillboard(this, particle);
}
}
particles.length = length2;
const numToEmit = calculateNumberToEmit(this, dt);
if (numToEmit > 0 && defined_default(emitter)) {
if (this._matrixDirty) {
this._combinedMatrix = Matrix4_default.multiply(
this.modelMatrix,
this.emitterModelMatrix,
this._combinedMatrix
);
this._matrixDirty = false;
}
const combinedMatrix = this._combinedMatrix;
for (i = 0; i < numToEmit; i++) {
particle = getOrCreateParticle(this);
this._emitter.emit(particle);
Cartesian3_default.add(
particle.position,
particle.velocity,
rotatedVelocityScratch
);
Matrix4_default.multiplyByPoint(
combinedMatrix,
rotatedVelocityScratch,
rotatedVelocityScratch
);
particle.position = Matrix4_default.multiplyByPoint(
combinedMatrix,
particle.position,
particle.position
);
Cartesian3_default.subtract(
rotatedVelocityScratch,
particle.position,
particle.velocity
);
Cartesian3_default.normalize(particle.velocity, particle.velocity);
addParticle(this, particle);
updateBillboard(this, particle);
}
}
this._billboardCollection.update(frameState);
this._previousTime = JulianDate_default.clone(frameState.time, this._previousTime);
this._currentTime += dt;
if (this._lifetime !== Number.MAX_VALUE && this._currentTime > this._lifetime) {
if (this.loop) {
this._currentTime = Math_default.mod(this._currentTime, this._lifetime);
if (this.bursts) {
const burstLength = this.bursts.length;
for (i = 0; i < burstLength; i++) {
this.bursts[i]._complete = false;
}
}
} else {
this._isComplete = true;
this._complete.raiseEvent(this);
}
}
if (frameState.frameNumber % 120 === 0) {
freeParticlePool(this);
}
};
ParticleSystem.prototype.isDestroyed = function() {
return false;
};
ParticleSystem.prototype.destroy = function() {
this._billboardCollection = this._billboardCollection && this._billboardCollection.destroy();
return destroyObject_default(this);
};
var ParticleSystem_default = ParticleSystem;
// packages/engine/Source/Scene/QuadtreeTileProvider.js
var import_InlineWorkers1270 = __toESM(require_InlineWorkers(), 1);
function QuadtreeTileProvider() {
DeveloperError_default.throwInstantiationError();
}
QuadtreeTileProvider.computeDefaultLevelZeroMaximumGeometricError = function(tilingScheme2) {
return tilingScheme2.ellipsoid.maximumRadius * 2 * Math.PI * 0.25 / (65 * tilingScheme2.getNumberOfXTilesAtLevel(0));
};
Object.defineProperties(QuadtreeTileProvider.prototype, {
/**
* Gets or sets the {@link QuadtreePrimitive} for which this provider is
* providing tiles.
* @memberof QuadtreeTileProvider.prototype
* @type {QuadtreePrimitive}
*/
quadtree: {
get: DeveloperError_default.throwInstantiationError,
set: DeveloperError_default.throwInstantiationError
},
/**
* Gets the tiling scheme used by the provider.
* @memberof QuadtreeTileProvider.prototype
* @type {TilingScheme}
*/
tilingScheme: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets an event that is raised when the geometry provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof QuadtreeTileProvider.prototype
* @type {Event}
*/
errorEvent: {
get: DeveloperError_default.throwInstantiationError
}
});
QuadtreeTileProvider.prototype.update = DeveloperError_default.throwInstantiationError;
QuadtreeTileProvider.prototype.beginUpdate = DeveloperError_default.throwInstantiationError;
QuadtreeTileProvider.prototype.endUpdate = DeveloperError_default.throwInstantiationError;
QuadtreeTileProvider.prototype.getLevelMaximumGeometricError = DeveloperError_default.throwInstantiationError;
QuadtreeTileProvider.prototype.loadTile = DeveloperError_default.throwInstantiationError;
QuadtreeTileProvider.prototype.computeTileVisibility = DeveloperError_default.throwInstantiationError;
QuadtreeTileProvider.prototype.showTileThisFrame = DeveloperError_default.throwInstantiationError;
QuadtreeTileProvider.prototype.computeDistanceToTile = DeveloperError_default.throwInstantiationError;
QuadtreeTileProvider.prototype.isDestroyed = DeveloperError_default.throwInstantiationError;
QuadtreeTileProvider.prototype.destroy = DeveloperError_default.throwInstantiationError;
var QuadtreeTileProvider_default = QuadtreeTileProvider;
// packages/engine/Source/Scene/SphereEmitter.js
var import_InlineWorkers1271 = __toESM(require_InlineWorkers(), 1);
function SphereEmitter(radius) {
radius = radius ?? 1;
Check_default.typeOf.number.greaterThan("radius", radius, 0);
this._radius = radius ?? 1;
}
Object.defineProperties(SphereEmitter.prototype, {
/**
* The radius of the sphere in meters.
* @memberof SphereEmitter.prototype
* @type {number}
* @default 1.0
*/
radius: {
get: function() {
return this._radius;
},
set: function(value) {
Check_default.typeOf.number.greaterThan("value", value, 0);
this._radius = value;
}
}
});
SphereEmitter.prototype.emit = function(particle) {
const theta = Math_default.randomBetween(0, Math_default.TWO_PI);
const phi = Math_default.randomBetween(0, Math_default.PI);
const rad = Math_default.randomBetween(0, this._radius);
const x = rad * Math.cos(theta) * Math.sin(phi);
const y = rad * Math.sin(theta) * Math.sin(phi);
const z = rad * Math.cos(phi);
particle.position = Cartesian3_default.fromElements(x, y, z, particle.position);
particle.velocity = Cartesian3_default.normalize(
particle.position,
particle.velocity
);
};
var SphereEmitter_default = SphereEmitter;
// packages/engine/Source/Scene/StyleExpression.js
var import_InlineWorkers1272 = __toESM(require_InlineWorkers(), 1);
function StyleExpression() {
}
StyleExpression.prototype.evaluate = function(feature2, result) {
DeveloperError_default.throwInstantiationError();
};
StyleExpression.prototype.evaluateColor = function(feature2, result) {
DeveloperError_default.throwInstantiationError();
};
StyleExpression.prototype.getShaderFunction = function(functionSignature, variableSubstitutionMap, shaderState, returnType) {
DeveloperError_default.throwInstantiationError();
};
StyleExpression.prototype.getVariables = function() {
DeveloperError_default.throwInstantiationError();
};
var StyleExpression_default = StyleExpression;
// packages/engine/Source/Scene/Terrain.js
var import_InlineWorkers1273 = __toESM(require_InlineWorkers(), 1);
function Terrain(terrainProviderPromise) {
Check_default.typeOf.object("terrainProviderPromise", terrainProviderPromise);
this._ready = false;
this._provider = void 0;
this._errorEvent = new Event_default();
this._readyEvent = new Event_default();
handlePromise2(this, terrainProviderPromise);
}
Object.defineProperties(Terrain.prototype, {
/**
* Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of the thrown error.
* @memberof Terrain.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets an event that is raised when the terrain provider has been successfully created. Event listeners
* are passed the created instance of {@link TerrainProvider}.
* @memberof Terrain.prototype
* @type {Event}
* @readonly
*/
readyEvent: {
get: function() {
return this._readyEvent;
}
},
/**
* Returns true when the terrain provider has been successfully created. Otherwise, returns false.
* @memberof Terrain.prototype
*
* @type {boolean}
* @readonly
*/
ready: {
get: function() {
return this._ready;
}
},
/**
* The terrain provider providing surface geometry to a globe. Do not use until {@link Terrain.readyEvent} is raised.
* @memberof Terrain.prototype
*
* @type {TerrainProvider}
* @readonly
*/
provider: {
get: function() {
return this._provider;
}
}
});
Terrain.fromWorldTerrain = function(options) {
return new Terrain(createWorldTerrainAsync_default(options));
};
Terrain.fromWorldBathymetry = function(options) {
return new Terrain(createWorldBathymetryAsync_default(options));
};
function handleError12(errorEvent, error) {
if (errorEvent.numberOfListeners > 0) {
errorEvent.raiseEvent(error);
} else {
console.error(error);
}
}
async function handlePromise2(instance, promise) {
let provider;
try {
provider = await Promise.resolve(promise);
instance._provider = provider;
instance._ready = true;
instance._readyEvent.raiseEvent(provider);
} catch (error) {
handleError12(instance._errorEvent, error);
}
}
var Terrain_default = Terrain;
// packages/engine/Source/Scene/TileBoundingVolume.js
var import_InlineWorkers1274 = __toESM(require_InlineWorkers(), 1);
function TileBoundingVolume() {
}
TileBoundingVolume.prototype.boundingVolume = void 0;
TileBoundingVolume.prototype.boundingSphere = void 0;
TileBoundingVolume.prototype.distanceToCamera = function(frameState) {
DeveloperError_default.throwInstantiationError();
};
TileBoundingVolume.prototype.intersectPlane = function(plane) {
DeveloperError_default.throwInstantiationError();
};
TileBoundingVolume.prototype.createDebugVolume = function(color) {
DeveloperError_default.throwInstantiationError();
};
var TileBoundingVolume_default = TileBoundingVolume;
// packages/engine/Source/Scene/TileCoordinatesImageryProvider.js
var import_InlineWorkers1275 = __toESM(require_InlineWorkers(), 1);
function TileCoordinatesImageryProvider(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
this._tilingScheme = defined_default(options.tilingScheme) ? options.tilingScheme : new GeographicTilingScheme_default({ ellipsoid: options.ellipsoid });
this._color = options.color ?? Color_default.YELLOW;
this._errorEvent = new Event_default();
this._tileWidth = options.tileWidth ?? 256;
this._tileHeight = options.tileHeight ?? 256;
this._defaultAlpha = void 0;
this._defaultNightAlpha = void 0;
this._defaultDayAlpha = void 0;
this._defaultBrightness = void 0;
this._defaultContrast = void 0;
this._defaultHue = void 0;
this._defaultSaturation = void 0;
this._defaultGamma = void 0;
this._defaultMinificationFilter = void 0;
this._defaultMagnificationFilter = void 0;
}
Object.defineProperties(TileCoordinatesImageryProvider.prototype, {
/**
* Gets the proxy used by this provider.
* @memberof TileCoordinatesImageryProvider.prototype
* @type {Proxy}
* @readonly
*/
proxy: {
get: function() {
return void 0;
}
},
/**
* Gets the width of each tile, in pixels.
* @memberof TileCoordinatesImageryProvider.prototype
* @type {number}
* @readonly
*/
tileWidth: {
get: function() {
return this._tileWidth;
}
},
/**
* Gets the height of each tile, in pixels.
* @memberof TileCoordinatesImageryProvider.prototype
* @type {number}
* @readonly
*/
tileHeight: {
get: function() {
return this._tileHeight;
}
},
/**
* Gets the maximum level-of-detail that can be requested.
* @memberof TileCoordinatesImageryProvider.prototype
* @type {number|undefined}
* @readonly
*/
maximumLevel: {
get: function() {
return void 0;
}
},
/**
* Gets the minimum level-of-detail that can be requested.
* @memberof TileCoordinatesImageryProvider.prototype
* @type {number}
* @readonly
*/
minimumLevel: {
get: function() {
return void 0;
}
},
/**
* Gets the tiling scheme used by this provider.
* @memberof TileCoordinatesImageryProvider.prototype
* @type {TilingScheme}
* @readonly
*/
tilingScheme: {
get: function() {
return this._tilingScheme;
}
},
/**
* Gets the rectangle, in radians, of the imagery provided by this instance.
* @memberof TileCoordinatesImageryProvider.prototype
* @type {Rectangle}
* @readonly
*/
rectangle: {
get: function() {
return this._tilingScheme.rectangle;
}
},
/**
* Gets the tile discard policy. If not undefined, the discard policy is responsible
* for filtering out "missing" tiles via its shouldDiscardImage function. If this function
* returns undefined, no tiles are filtered.
* @memberof TileCoordinatesImageryProvider.prototype
* @type {TileDiscardPolicy}
* @readonly
*/
tileDiscardPolicy: {
get: function() {
return void 0;
}
},
/**
* Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
* are passed an instance of {@link TileProviderError}.
* @memberof TileCoordinatesImageryProvider.prototype
* @type {Event}
* @readonly
*/
errorEvent: {
get: function() {
return this._errorEvent;
}
},
/**
* Gets the credit to display when this imagery provider is active. Typically this is used to credit
* the source of the imagery.
* @memberof TileCoordinatesImageryProvider.prototype
* @type {Credit}
* @readonly
*/
credit: {
get: function() {
return void 0;
}
},
/**
* Gets a value indicating whether or not the images provided by this imagery provider
* include an alpha channel. If this property is false, an alpha channel, if present, will
* be ignored. If this property is true, any images without an alpha channel will be treated
* as if their alpha is 1.0 everywhere. Setting this property to false reduces memory usage
* and texture upload time.
* @memberof TileCoordinatesImageryProvider.prototype
* @type {boolean}
* @readonly
*/
hasAlphaChannel: {
get: function() {
return true;
}
}
});
TileCoordinatesImageryProvider.prototype.getTileCredits = function(x, y, level) {
return void 0;
};
TileCoordinatesImageryProvider.prototype.requestImage = function(x, y, level, request) {
const canvas = document.createElement("canvas");
canvas.width = 256;
canvas.height = 256;
const context = canvas.getContext("2d");
const cssColor = this._color.toCssColorString();
context.strokeStyle = cssColor;
context.lineWidth = 2;
context.strokeRect(1, 1, 255, 255);
context.font = "bold 25px Arial";
context.textAlign = "center";
context.fillStyle = cssColor;
context.fillText(`L: ${level}`, 124, 86);
context.fillText(`X: ${x}`, 124, 136);
context.fillText(`Y: ${y}`, 124, 186);
return Promise.resolve(canvas);
};
TileCoordinatesImageryProvider.prototype.pickFeatures = function(x, y, level, longitude, latitude) {
return void 0;
};
var TileCoordinatesImageryProvider_default = TileCoordinatesImageryProvider;
// packages/engine/Source/Scene/TileDiscardPolicy.js
var import_InlineWorkers1276 = __toESM(require_InlineWorkers(), 1);
function TileDiscardPolicy(options) {
DeveloperError_default.throwInstantiationError();
}
TileDiscardPolicy.prototype.isReady = DeveloperError_default.throwInstantiationError;
TileDiscardPolicy.prototype.shouldDiscardImage = DeveloperError_default.throwInstantiationError;
var TileDiscardPolicy_default = TileDiscardPolicy;
// packages/engine/Source/Scene/TileState.js
var import_InlineWorkers1277 = __toESM(require_InlineWorkers(), 1);
var TileState = {
START: 0,
LOADING: 1,
READY: 2,
UPSAMPLED_ONLY: 3
};
var TileState_default = Object.freeze(TileState);
// packages/engine/Source/Scene/ViewportQuad.js
var import_InlineWorkers1278 = __toESM(require_InlineWorkers(), 1);
function ViewportQuad(rectangle, material) {
this.show = true;
if (!defined_default(rectangle)) {
rectangle = new BoundingRectangle_default();
}
this.rectangle = BoundingRectangle_default.clone(rectangle);
if (!defined_default(material)) {
material = Material_default.fromType(Material_default.ColorType, {
color: new Color_default(1, 1, 1, 1)
});
}
this.material = material;
this._material = void 0;
this._overlayCommand = void 0;
this._rs = void 0;
}
ViewportQuad.prototype.update = function(frameState) {
if (!this.show) {
return;
}
if (!defined_default(this.material)) {
throw new DeveloperError_default("this.material must be defined.");
}
if (!defined_default(this.rectangle)) {
throw new DeveloperError_default("this.rectangle must be defined.");
}
const rs = this._rs;
if (!defined_default(rs) || !BoundingRectangle_default.equals(rs.viewport, this.rectangle)) {
this._rs = RenderState_default.fromCache({
blending: BlendingState_default.ALPHA_BLEND,
viewport: this.rectangle
});
}
const pass = frameState.passes;
if (pass.render) {
const context = frameState.context;
if (this._material !== this.material || !defined_default(this._overlayCommand)) {
this._material = this.material;
if (defined_default(this._overlayCommand)) {
this._overlayCommand.shaderProgram.destroy();
}
const fs = new ShaderSource_default({
sources: [this._material.shaderSource, ViewportQuadFS_default]
});
this._overlayCommand = context.createViewportQuadCommand(fs, {
renderState: this._rs,
uniformMap: this._material._uniforms,
owner: this
});
this._overlayCommand.pass = Pass_default.OVERLAY;
}
this._material.update(context);
this._overlayCommand.renderState = this._rs;
this._overlayCommand.uniformMap = this._material._uniforms;
frameState.commandList.push(this._overlayCommand);
}
};
ViewportQuad.prototype.isDestroyed = function() {
return false;
};
ViewportQuad.prototype.destroy = function() {
if (defined_default(this._overlayCommand)) {
this._overlayCommand.shaderProgram = this._overlayCommand.shaderProgram && this._overlayCommand.shaderProgram.destroy();
}
return destroyObject_default(this);
};
var ViewportQuad_default = ViewportQuad;
// packages/engine/Source/Scene/VoxelProvider.js
var import_InlineWorkers1279 = __toESM(require_InlineWorkers(), 1);
function VoxelProvider() {
DeveloperError_default.throwInstantiationError();
}
Object.defineProperties(VoxelProvider.prototype, {
/**
* A transform from local space to global space.
*
* @memberof VoxelProvider.prototype
* @type {Matrix4}
* @default Matrix4.IDENTITY
* @readonly
*/
globalTransform: {
get: DeveloperError_default.throwInstantiationError
},
/**
* A transform from shape space to local space.
*
* @memberof VoxelProvider.prototype
* @type {Matrix4}
* @default Matrix4.IDENTITY
* @readonly
*/
shapeTransform: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the {@link VoxelShapeType}
*
* @memberof VoxelProvider.prototype
* @type {VoxelShapeType}
* @readonly
*/
shape: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the minimum bounds.
* If undefined, the shape's default minimum bounds will be used instead.
*
* @memberof VoxelProvider.prototype
* @type {Cartesian3|undefined}
* @readonly
*/
minBounds: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the maximum bounds.
* If undefined, the shape's default maximum bounds will be used instead.
*
* @memberof VoxelProvider.prototype
* @type {Cartesian3|undefined}
* @readonly
*/
maxBounds: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the number of voxels per dimension of a tile. This is the same for all tiles in the dataset.
*
* @memberof VoxelProvider.prototype
* @type {Cartesian3}
* @readonly
*/
dimensions: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the number of padding voxels before the tile. This improves rendering quality when sampling the edge of a tile, but it increases memory usage.
*
* @memberof VoxelProvider.prototype
* @type {Cartesian3}
* @default Cartesian3.ZERO
* @readonly
*/
paddingBefore: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the number of padding voxels after the tile. This improves rendering quality when sampling the edge of a tile, but it increases memory usage.
*
* @memberof VoxelProvider.prototype
* @type {Cartesian3}
* @default Cartesian3.ZERO
* @readonly
*/
paddingAfter: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the metadata names.
*
* @memberof VoxelProvider.prototype
* @type {string[]}
* @readonly
*/
names: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the metadata types.
*
* @memberof VoxelProvider.prototype
* @type {MetadataType[]}
* @readonly
*/
types: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the metadata component types.
*
* @memberof VoxelProvider.prototype
* @type {MetadataComponentType[]}
* @readonly
*/
componentTypes: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the metadata minimum values.
*
* @memberof VoxelProvider.prototype
* @type {number[][]|undefined}
* @readonly
*/
minimumValues: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the metadata maximum values.
*
* @memberof VoxelProvider.prototype
* @type {number[][]|undefined}
* @readonly
*/
maximumValues: {
get: DeveloperError_default.throwInstantiationError
},
/**
* The maximum number of tiles that exist for this provider.
* This value is used as a hint to the voxel renderer to allocate an appropriate amount of GPU memory.
* If this value is not known it can be undefined.
*
* @memberof VoxelProvider.prototype
* @type {number|undefined}
* @readonly
*/
maximumTileCount: {
get: DeveloperError_default.throwInstantiationError
},
/**
* The number of levels of detail containing available tiles in the tileset.
*
* @type {number|undefined}
* @readonly
*/
availableLevels: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the number of keyframes in the dataset.
*
* @memberof VoxelProvider.prototype
* @type {number|undefined}
* @readonly
* @private
*/
keyframeCount: {
get: DeveloperError_default.throwInstantiationError
},
/**
* Gets the {@link TimeIntervalCollection} for the dataset,
* or undefined if it doesn't have timestamps.
*
* @memberof VoxelProvider.prototype
* @type {TimeIntervalCollection|undefined}
* @readonly
* @private
*/
timeIntervalCollection: {
get: DeveloperError_default.throwInstantiationError
}
});
VoxelProvider.prototype.requestData = function(options) {
DeveloperError_default.throwInstantiationError();
};
var VoxelProvider_default = VoxelProvider;
// packages/engine/Source/Scene/VoxelShape.js
var import_InlineWorkers1280 = __toESM(require_InlineWorkers(), 1);
function VoxelShape() {
DeveloperError_default.throwInstantiationError();
}
Object.defineProperties(VoxelShape.prototype, {
/**
* An oriented bounding box containing the bounded shape.
* The update function must be called before accessing this value.
*
* @memberof VoxelShape.prototype
* @type {OrientedBoundingBox}
* @readonly
* @private
*/
orientedBoundingBox: {
get: DeveloperError_default.throwInstantiationError
},
/**
* A bounding sphere containing the bounded shape.
* The update function must be called before accessing this value.
*
* @memberof VoxelShape.prototype
* @type {BoundingSphere}
* @readonly
* @private
*/
boundingSphere: {
get: DeveloperError_default.throwInstantiationError
},
/**
* A transformation matrix containing the bounded shape.
* The update function must be called before accessing this value.
*
* @memberof VoxelShape.prototype
* @type {Matrix4}
* @readonly
* @private
*/
boundTransform: {
get: DeveloperError_default.throwInstantiationError
},
/**
* A transformation matrix containing the shape, ignoring the bounds.
* The update function must be called before accessing this value.
*
* @memberof VoxelShape.prototype
* @type {Matrix4}
* @readonly
* @private
*/
shapeTransform: {
get: DeveloperError_default.throwInstantiationError
},
/**
* @type {Object}
* @readonly
* @private
*/
shaderUniforms: {
get: DeveloperError_default.throwInstantiationError
},
/**
* @type {Object}
* @readonly
* @private
*/
shaderDefines: {
get: DeveloperError_default.throwInstantiationError
},
/**
* The maximum number of intersections against the shape for any ray direction.
* @type {number}
* @readonly
* @private
*/
shaderMaximumIntersectionsLength: {
get: DeveloperError_default.throwInstantiationError
}
});
VoxelShape.prototype.update = DeveloperError_default.throwInstantiationError;
VoxelShape.prototype.computeOrientedBoundingBoxForTile = DeveloperError_default.throwInstantiationError;
VoxelShape.prototype.computeOrientedBoundingBoxForSample = DeveloperError_default.throwInstantiationError;
VoxelShape.DefaultMinBounds = DeveloperError_default.throwInstantiationError;
VoxelShape.DefaultMaxBounds = DeveloperError_default.throwInstantiationError;
var VoxelShape_default = VoxelShape;
// packages/engine/Source/Scene/createElevationBandMaterial.js
var import_InlineWorkers1281 = __toESM(require_InlineWorkers(), 1);
var scratchColor28 = new Color_default();
var scratchColorAbove = new Color_default();
var scratchColorBelow = new Color_default();
var scratchColorBlend = new Color_default();
var scratchPackedFloat = new Cartesian4_default();
var scratchColorBytes2 = new Uint8Array(4);
function lerpEntryColor(height, entryBefore, entryAfter, result) {
const lerpFactor = entryBefore.height === entryAfter.height ? 0 : (height - entryBefore.height) / (entryAfter.height - entryBefore.height);
return Color_default.lerp(entryBefore.color, entryAfter.color, lerpFactor, result);
}
function createNewEntry(height, color) {
return {
height,
color: Color_default.clone(color)
};
}
function removeDuplicates2(entries2) {
entries2 = entries2.filter(function(entry, index, array) {
const hasPrev = index > 0;
const hasNext = index < array.length - 1;
const sameHeightAsPrev = hasPrev ? entry.height === array[index - 1].height : true;
const sameHeightAsNext = hasNext ? entry.height === array[index + 1].height : true;
const keep = !sameHeightAsPrev || !sameHeightAsNext;
return keep;
});
entries2 = entries2.filter(function(entry, index, array) {
const hasPrev = index > 0;
const hasNext = index < array.length - 1;
const sameColorAsPrev = hasPrev ? Color_default.equals(entry.color, array[index - 1].color) : false;
const sameColorAsNext = hasNext ? Color_default.equals(entry.color, array[index + 1].color) : false;
const keep = !sameColorAsPrev || !sameColorAsNext;
return keep;
});
entries2 = entries2.filter(function(entry, index, array) {
const hasPrev = index > 0;
const sameColorAsPrev = hasPrev ? Color_default.equals(entry.color, array[index - 1].color) : false;
const sameHeightAsPrev = hasPrev ? entry.height === array[index - 1].height : true;
const keep = !sameColorAsPrev || !sameHeightAsPrev;
return keep;
});
return entries2;
}
function preprocess(layers) {
let i, j;
const layeredEntries = [];
const layersLength = layers.length;
for (i = 0; i < layersLength; i++) {
const layer = layers[i];
const entriesOrig = layer.entries;
const entriesLength = entriesOrig.length;
if (!Array.isArray(entriesOrig) || entriesLength === 0) {
throw new DeveloperError_default("entries must be an array with size > 0.");
}
let entries2 = [];
for (j = 0; j < entriesLength; j++) {
const entryOrig = entriesOrig[j];
if (!defined_default(entryOrig.height)) {
throw new DeveloperError_default("entry requires a height.");
}
if (!defined_default(entryOrig.color)) {
throw new DeveloperError_default("entry requires a color.");
}
const height = Math_default.clamp(
entryOrig.height,
createElevationBandMaterial._minimumHeight,
createElevationBandMaterial._maximumHeight
);
const color = Color_default.clone(entryOrig.color, scratchColor28);
color.red *= color.alpha;
color.green *= color.alpha;
color.blue *= color.alpha;
entries2.push(createNewEntry(height, color));
}
let sortedAscending = true;
let sortedDescending = true;
for (j = 0; j < entriesLength - 1; j++) {
const currEntry = entries2[j + 0];
const nextEntry = entries2[j + 1];
sortedAscending = sortedAscending && currEntry.height <= nextEntry.height;
sortedDescending = sortedDescending && currEntry.height >= nextEntry.height;
}
if (sortedDescending) {
entries2 = entries2.reverse();
} else if (!sortedAscending) {
mergeSort_default(entries2, function(a3, b) {
return Math_default.sign(a3.height - b.height);
});
}
let extendDownwards = layer.extendDownwards ?? false;
let extendUpwards = layer.extendUpwards ?? false;
if (entries2.length === 1 && !extendDownwards && !extendUpwards) {
extendDownwards = true;
extendUpwards = true;
}
if (extendDownwards) {
entries2.splice(
0,
0,
createNewEntry(
createElevationBandMaterial._minimumHeight,
entries2[0].color
)
);
}
if (extendUpwards) {
entries2.splice(
entries2.length,
0,
createNewEntry(
createElevationBandMaterial._maximumHeight,
entries2[entries2.length - 1].color
)
);
}
entries2 = removeDuplicates2(entries2);
layeredEntries.push(entries2);
}
return layeredEntries;
}
function createLayeredEntries(layers) {
const layeredEntries = preprocess(layers);
let entriesAccumNext = [];
let entriesAccumCurr = [];
let i;
function addEntry(height, color) {
entriesAccumNext.push(createNewEntry(height, color));
}
function addBlendEntry(height, a3, b) {
let result = Color_default.multiplyByScalar(b, 1 - a3.alpha, scratchColorBlend);
result = Color_default.add(result, a3, result);
addEntry(height, result);
}
const layerLength = layeredEntries.length;
for (i = 0; i < layerLength; i++) {
const entries2 = layeredEntries[i];
let idx = 0;
let accumIdx = 0;
entriesAccumCurr = entriesAccumNext;
entriesAccumNext = [];
const entriesLength = entries2.length;
const entriesAccumLength = entriesAccumCurr.length;
while (idx < entriesLength || accumIdx < entriesAccumLength) {
const entry = idx < entriesLength ? entries2[idx] : void 0;
const prevEntry = idx > 0 ? entries2[idx - 1] : void 0;
const nextEntry = idx < entriesLength - 1 ? entries2[idx + 1] : void 0;
const entryAccum = accumIdx < entriesAccumLength ? entriesAccumCurr[accumIdx] : void 0;
const prevEntryAccum = accumIdx > 0 ? entriesAccumCurr[accumIdx - 1] : void 0;
const nextEntryAccum = accumIdx < entriesAccumLength - 1 ? entriesAccumCurr[accumIdx + 1] : void 0;
if (defined_default(entry) && defined_default(entryAccum) && entry.height === entryAccum.height) {
const isSplitAccum = defined_default(nextEntryAccum) && entryAccum.height === nextEntryAccum.height;
const isStartAccum = !defined_default(prevEntryAccum);
const isEndAccum = !defined_default(nextEntryAccum);
const isSplit = defined_default(nextEntry) && entry.height === nextEntry.height;
const isStart = !defined_default(prevEntry);
const isEnd = !defined_default(nextEntry);
if (isSplitAccum) {
if (isSplit) {
addBlendEntry(entry.height, entry.color, entryAccum.color);
addBlendEntry(entry.height, nextEntry.color, nextEntryAccum.color);
} else if (isStart) {
addEntry(entry.height, entryAccum.color);
addBlendEntry(entry.height, entry.color, nextEntryAccum.color);
} else if (isEnd) {
addBlendEntry(entry.height, entry.color, entryAccum.color);
addEntry(entry.height, nextEntryAccum.color);
} else {
addBlendEntry(entry.height, entry.color, entryAccum.color);
addBlendEntry(entry.height, entry.color, nextEntryAccum.color);
}
} else if (isStartAccum) {
if (isSplit) {
addEntry(entry.height, entry.color);
addBlendEntry(entry.height, nextEntry.color, entryAccum.color);
} else if (isEnd) {
addEntry(entry.height, entry.color);
addEntry(entry.height, entryAccum.color);
} else if (isStart) {
addBlendEntry(entry.height, entry.color, entryAccum.color);
} else {
addEntry(entry.height, entry.color);
addBlendEntry(entry.height, entry.color, entryAccum.color);
}
} else if (isEndAccum) {
if (isSplit) {
addBlendEntry(entry.height, entry.color, entryAccum.color);
addEntry(entry.height, nextEntry.color);
} else if (isStart) {
addEntry(entry.height, entryAccum.color);
addEntry(entry.height, entry.color);
} else if (isEnd) {
addBlendEntry(entry.height, entry.color, entryAccum.color);
} else {
addBlendEntry(entry.height, entry.color, entryAccum.color);
addEntry(entry.height, entry.color);
}
} else {
if (isSplit) {
addBlendEntry(entry.height, entry.color, entryAccum.color);
addBlendEntry(entry.height, nextEntry.color, entryAccum.color);
} else if (isStart) {
addEntry(entry.height, entryAccum.color);
addBlendEntry(entry.height, entry.color, entryAccum.color);
} else if (isEnd) {
addBlendEntry(entry.height, entry.color, entryAccum.color);
addEntry(entry.height, entryAccum.color);
} else {
addBlendEntry(entry.height, entry.color, entryAccum.color);
}
}
idx += isSplit ? 2 : 1;
accumIdx += isSplitAccum ? 2 : 1;
} else if (defined_default(entry) && defined_default(entryAccum) && defined_default(prevEntryAccum) && entry.height < entryAccum.height) {
const colorBelow = lerpEntryColor(
entry.height,
prevEntryAccum,
entryAccum,
scratchColorBelow
);
if (!defined_default(prevEntry)) {
addEntry(entry.height, colorBelow);
addBlendEntry(entry.height, entry.color, colorBelow);
} else if (!defined_default(nextEntry)) {
addBlendEntry(entry.height, entry.color, colorBelow);
addEntry(entry.height, colorBelow);
} else {
addBlendEntry(entry.height, entry.color, colorBelow);
}
idx++;
} else if (defined_default(entryAccum) && defined_default(entry) && defined_default(prevEntry) && entryAccum.height < entry.height) {
const colorAbove = lerpEntryColor(
entryAccum.height,
prevEntry,
entry,
scratchColorAbove
);
if (!defined_default(prevEntryAccum)) {
addEntry(entryAccum.height, colorAbove);
addBlendEntry(entryAccum.height, colorAbove, entryAccum.color);
} else if (!defined_default(nextEntryAccum)) {
addBlendEntry(entryAccum.height, colorAbove, entryAccum.color);
addEntry(entryAccum.height, colorAbove);
} else {
addBlendEntry(entryAccum.height, colorAbove, entryAccum.color);
}
accumIdx++;
} else if (defined_default(entry) && (!defined_default(entryAccum) || entry.height < entryAccum.height)) {
if (defined_default(entryAccum) && !defined_default(prevEntryAccum) && !defined_default(nextEntry)) {
addEntry(entry.height, entry.color);
addEntry(entry.height, createElevationBandMaterial._emptyColor);
addEntry(entryAccum.height, createElevationBandMaterial._emptyColor);
} else if (!defined_default(entryAccum) && defined_default(prevEntryAccum) && !defined_default(prevEntry)) {
addEntry(
prevEntryAccum.height,
createElevationBandMaterial._emptyColor
);
addEntry(entry.height, createElevationBandMaterial._emptyColor);
addEntry(entry.height, entry.color);
} else {
addEntry(entry.height, entry.color);
}
idx++;
} else if (defined_default(entryAccum) && (!defined_default(entry) || entryAccum.height < entry.height)) {
addEntry(entryAccum.height, entryAccum.color);
accumIdx++;
}
}
}
const allEntries = removeDuplicates2(entriesAccumNext);
return allEntries;
}
function createElevationBandMaterial(options) {
const { scene, layers } = options ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("options.scene", scene);
Check_default.defined("options.layers", layers);
Check_default.typeOf.number.greaterThan("options.layers.length", layers.length, 0);
const { context } = scene;
const entries2 = createLayeredEntries(layers);
const entriesLength = entries2.length;
let heightTexBuffer;
let heightTexDatatype;
let heightTexFormat;
const isPackedHeight = !createElevationBandMaterial._useFloatTexture(context);
if (isPackedHeight) {
heightTexDatatype = PixelDatatype_default.UNSIGNED_BYTE;
heightTexFormat = PixelFormat_default.RGBA;
heightTexBuffer = new Uint8Array(entriesLength * 4);
for (let i = 0; i < entriesLength; i++) {
Cartesian4_default.packFloat(entries2[i].height, scratchPackedFloat);
Cartesian4_default.pack(scratchPackedFloat, heightTexBuffer, i * 4);
}
} else {
heightTexDatatype = PixelDatatype_default.FLOAT;
heightTexFormat = context.webgl2 ? PixelFormat_default.RED : PixelFormat_default.LUMINANCE;
heightTexBuffer = new Float32Array(entriesLength);
for (let i = 0; i < entriesLength; i++) {
heightTexBuffer[i] = entries2[i].height;
}
}
const heightsTex = Texture_default.create({
context,
pixelFormat: heightTexFormat,
pixelDatatype: heightTexDatatype,
source: {
arrayBufferView: heightTexBuffer,
width: entriesLength,
height: 1
},
sampler: new Sampler_default({
wrapS: TextureWrap_default.CLAMP_TO_EDGE,
wrapT: TextureWrap_default.CLAMP_TO_EDGE,
minificationFilter: TextureMinificationFilter_default.NEAREST,
magnificationFilter: TextureMagnificationFilter_default.NEAREST
})
});
const colorsArray = new Uint8Array(entriesLength * 4);
for (let i = 0; i < entriesLength; i++) {
const color = entries2[i].color;
color.toBytes(scratchColorBytes2);
colorsArray[i * 4 + 0] = scratchColorBytes2[0];
colorsArray[i * 4 + 1] = scratchColorBytes2[1];
colorsArray[i * 4 + 2] = scratchColorBytes2[2];
colorsArray[i * 4 + 3] = scratchColorBytes2[3];
}
const colorsTex = Texture_default.create({
context,
pixelFormat: PixelFormat_default.RGBA,
pixelDatatype: PixelDatatype_default.UNSIGNED_BYTE,
source: {
arrayBufferView: colorsArray,
width: entriesLength,
height: 1
},
sampler: new Sampler_default({
wrapS: TextureWrap_default.CLAMP_TO_EDGE,
wrapT: TextureWrap_default.CLAMP_TO_EDGE,
minificationFilter: TextureMinificationFilter_default.LINEAR,
magnificationFilter: TextureMagnificationFilter_default.LINEAR
})
});
return Material_default.fromType("ElevationBand", {
heights: heightsTex,
colors: colorsTex
});
}
createElevationBandMaterial._useFloatTexture = function(context) {
return context.floatingPointTexture;
};
createElevationBandMaterial._maximumHeight = 5906376425472;
createElevationBandMaterial._minimumHeight = -5906376425472;
createElevationBandMaterial._emptyColor = new Color_default(0, 0, 0, 0);
var createElevationBandMaterial_default = createElevationBandMaterial;
// packages/engine/Source/Scene/createGooglePhotorealistic3DTileset.js
var import_InlineWorkers1282 = __toESM(require_InlineWorkers(), 1);
async function createGooglePhotorealistic3DTileset(apiOptions, tilesetOptions) {
tilesetOptions = tilesetOptions ?? {};
tilesetOptions.cacheBytes = tilesetOptions.cacheBytes ?? 1536 * 1024 * 1024;
tilesetOptions.maximumCacheOverflowBytes = tilesetOptions.maximumCacheOverflowBytes ?? 1024 * 1024 * 1024;
tilesetOptions.enableCollision = tilesetOptions.enableCollision ?? true;
apiOptions = apiOptions ?? Frozen_default.EMPTY_OBJECT;
Check_default.typeOf.object("apiOptions", apiOptions);
if (!apiOptions.onlyUsingWithGoogleGeocoder) {
oneTimeWarning_default(
"google-tiles-with-google-geocoder",
"Only the Google geocoder can be used with Google Photorealistic 3D Tiles. Set the `geocode` property of Viewer constructor options. You can set additionalOptions.onlyUsingWithGoogleGeocoder to hide this warning once you have configured the geocoder."
);
}
const key = apiOptions.key ?? GoogleMaps_default.defaultApiKey;
if (!defined_default(key)) {
return requestCachedIonTileset(tilesetOptions);
}
let credits;
const credit = GoogleMaps_default.getDefaultCredit();
if (defined_default(credit)) {
credits = [credit];
}
const resource = new Resource_default({
url: `${GoogleMaps_default.mapTilesApiEndpoint}3dtiles/root.json`,
queryParameters: {
key
},
credits
});
return Cesium3DTileset_default.fromUrl(resource, tilesetOptions);
}
var metadataCache = {};
async function requestCachedIonTileset(options) {
const ionAssetId = 2275207;
const cacheKey = ionAssetId;
let promise = metadataCache[cacheKey];
if (!defined_default(promise)) {
promise = IonResource_default.fromAssetId(ionAssetId);
metadataCache[cacheKey] = promise;
}
const resource = await promise;
return Cesium3DTileset_default.fromUrl(resource, options);
}
var createGooglePhotorealistic3DTileset_default = createGooglePhotorealistic3DTileset;
// packages/engine/Source/Scene/createOsmBuildingsAsync.js
var import_InlineWorkers1283 = __toESM(require_InlineWorkers(), 1);
async function createOsmBuildingsAsync(options) {
const tileset = await Cesium3DTileset_default.fromIonAssetId(96188, options);
options = options ?? Frozen_default.EMPTY_OBJECT;
let style = options.style;
if (!defined_default(style)) {
const color = (options.defaultColor ?? Color_default.WHITE).toCssColorString();
style = new Cesium3DTileStyle_default({
color: `Boolean(\${feature['cesium#color']}) ? color(\${feature['cesium#color']}) : ${color}`
});
}
tileset.style = style;
return tileset;
}
var createOsmBuildingsAsync_default = createOsmBuildingsAsync;
// packages/engine/Source/Scene/createTangentSpaceDebugPrimitive.js
var import_InlineWorkers1284 = __toESM(require_InlineWorkers(), 1);
function createTangentSpaceDebugPrimitive(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const instances = [];
let geometry = options.geometry;
if (!defined_default(geometry)) {
throw new DeveloperError_default("options.geometry is required.");
}
if (!defined_default(geometry.attributes) || !defined_default(geometry.primitiveType)) {
geometry = geometry.constructor.createGeometry(geometry);
}
const attributes = geometry.attributes;
const modelMatrix = Matrix4_default.clone(options.modelMatrix ?? Matrix4_default.IDENTITY);
const length2 = options.length ?? 1e4;
if (defined_default(attributes.normal)) {
instances.push(
new GeometryInstance_default({
geometry: GeometryPipeline_default.createLineSegmentsForVectors(
geometry,
"normal",
length2
),
attributes: {
color: new ColorGeometryInstanceAttribute_default(1, 0, 0, 1)
},
modelMatrix
})
);
}
if (defined_default(attributes.tangent)) {
instances.push(
new GeometryInstance_default({
geometry: GeometryPipeline_default.createLineSegmentsForVectors(
geometry,
"tangent",
length2
),
attributes: {
color: new ColorGeometryInstanceAttribute_default(0, 1, 0, 1)
},
modelMatrix
})
);
}
if (defined_default(attributes.bitangent)) {
instances.push(
new GeometryInstance_default({
geometry: GeometryPipeline_default.createLineSegmentsForVectors(
geometry,
"bitangent",
length2
),
attributes: {
color: new ColorGeometryInstanceAttribute_default(0, 0, 1, 1)
},
modelMatrix
})
);
}
if (instances.length > 0) {
return new Primitive_default({
asynchronous: false,
geometryInstances: instances,
appearance: new PerInstanceColorAppearance_default({
flat: true,
translucent: false
})
});
}
return void 0;
}
var createTangentSpaceDebugPrimitive_default = createTangentSpaceDebugPrimitive;
// packages/engine/Source/Shaders/PostProcessStages/DepthViewPacked.js
var import_InlineWorkers1285 = __toESM(require_InlineWorkers(), 1);
var DepthViewPacked_default = "uniform sampler2D u_depthTexture;\n\nin vec2 v_textureCoordinates;\n\nvoid main()\n{\n float z_window = czm_unpackDepth(texture(u_depthTexture, v_textureCoordinates));\n z_window = czm_reverseLogDepth(z_window);\n float n_range = czm_depthRange.near;\n float f_range = czm_depthRange.far;\n float z_ndc = (2.0 * z_window - n_range - f_range) / (f_range - n_range);\n float scale = pow(z_ndc * 0.5 + 0.5, 8.0);\n out_FragColor = vec4(mix(vec3(0.0), vec3(1.0), scale), 1.0);\n}\n";
// packages/engine/Source/Scene/Model/TextureUniform.js
var import_InlineWorkers1286 = __toESM(require_InlineWorkers(), 1);
function TextureUniform(options) {
options = options ?? Frozen_default.EMPTY_OBJECT;
const hasTypedArray = defined_default(options.typedArray);
const hasUrl = defined_default(options.url);
if (hasTypedArray === hasUrl) {
throw new DeveloperError_default(
"exactly one of options.typedArray, options.url must be defined"
);
}
if (hasTypedArray && (!defined_default(options.width) || !defined_default(options.height))) {
throw new DeveloperError_default(
"options.width and options.height are required when options.typedArray is defined"
);
}
this.typedArray = options.typedArray;
this.width = options.width;
this.height = options.height;
this.pixelFormat = options.pixelFormat ?? PixelFormat_default.RGBA;
this.pixelDatatype = options.pixelDatatype ?? PixelDatatype_default.UNSIGNED_BYTE;
let resource = options.url;
if (typeof resource === "string") {
resource = Resource_default.createIfNeeded(resource);
}
this.resource = resource;
const repeat = options.repeat ?? true;
const wrap = repeat ? TextureWrap_default.REPEAT : TextureWrap_default.CLAMP_TO_EDGE;
this.sampler = new Sampler_default({
wrapS: wrap,
wrapT: wrap,
minificationFilter: options.minificationFilter,
magnificationFilter: options.magnificationFilter,
maximumAnisotropy: options.maximumAnisotropy
});
}
var TextureUniform_default = TextureUniform;
// packages/engine/Source/Scene/Model/VaryingType.js
var import_InlineWorkers1287 = __toESM(require_InlineWorkers(), 1);
var VaryingType = {
/**
* A single floating point value.
*
* @type {string}
* @constant
*/
FLOAT: "float",
/**
* A vector of 2 floating point values.
*
* @type {string}
* @constant
*/
VEC2: "vec2",
/**
* A vector of 3 floating point values.
*
* @type {string}
* @constant
*/
VEC3: "vec3",
/**
* A vector of 4 floating point values.
*
* @type {string}
* @constant
*/
VEC4: "vec4",
/**
* A 2x2 matrix of floating point values.
*
* @type {string}
* @constant
*/
MAT2: "mat2",
/**
* A 3x3 matrix of floating point values.
*
* @type {string}
* @constant
*/
MAT3: "mat3",
/**
* A 4x4 matrix of floating point values.
*
* @type {string}
* @constant
*/
MAT4: "mat4"
};
var VaryingType_default = Object.freeze(VaryingType);
// packages/engine/Source/Scene/Model/Extensions/Gpm/PpeSource.js
var import_InlineWorkers1288 = __toESM(require_InlineWorkers(), 1);
var PpeSource = {
/**
* The PPE standard deviation of error in the x dimension of the MCS (sigma x). Value will be squared
* and used to populate the (1,1) element in the PPE covariance matrix.
*
* @type {string}
* @constant
*/
SIGX: "SIGX",
/**
* The PPE standard deviation of error in the y dimension of the MCS (sigma y). Value will be squared
* and used to populate the (2,2) element in the PPE covariance matrix.
*
* @type {string}
* @constant
*/
SIGY: "SIGY",
/**
* The PPE standard deviation of error in the z dimension of the MCS (sigma z). Value will be squared
* and used to populate the (3,3) element in the PPE covariance matrix.
*
* @type {string}
* @constant
*/
SIGZ: "SIGZ",
/**
* The PPE variance of error in the x dimension of the MCS (sigma x2). Value will be used to populate
* the (1,1) element in the PPE covariance matrix.
*
* @type {string}
* @constant
*/
VARX: "VARX",
/**
* The PPE variance of error in the y dimension of the MCS (sigma y2). Value will be used to populate
* the (2,2) element in the PPE covariance matrix.
*
* @type {string}
* @constant
*/
VARY: "VARY",
/**
* The PPE variance of error in the z dimension of the MCS (sigma z2). Value will be used to populate
* the (3,3) element in the PPE covariance matrix.
*
* @type {string}
* @constant
*/
VARZ: "VARZ",
/**
* The PPE radial error in the horizontal dimension (x-y) of the MCS (sigma radial) . Value will be squared
* and used to populate the (1,1) and (2,2) element in the PPE covariance matrix.
*
* @type {string}
* @constant
*/
SIGR: "VARZ"
};
var PpeSource_default = Object.freeze(PpeSource);
// packages/engine/Source/Workers/createTaskProcessorWorker.js
var import_InlineWorkers1289 = __toESM(require_InlineWorkers(), 1);
function createTaskProcessorWorker(workerFunction) {
async function onMessageHandler({ data }) {
const transferableObjects = [];
const responseMessage = {
id: data.id,
result: void 0,
error: void 0
};
self.CESIUM_BASE_URL = data.baseUrl;
try {
const result = await workerFunction(data.parameters, transferableObjects);
responseMessage.result = result;
} catch (error) {
if (error instanceof Error) {
responseMessage.error = {
name: error.name,
message: error.message,
stack: error.stack
};
} else {
responseMessage.error = error;
}
}
if (!data.canTransferArrayBuffer) {
transferableObjects.length = 0;
}
try {
postMessage(responseMessage, transferableObjects);
} catch (error) {
responseMessage.result = void 0;
responseMessage.error = `postMessage failed with error: ${formatError_default(
error
)}
with responseMessage: ${JSON.stringify(responseMessage)}`;
postMessage(responseMessage);
}
}
function onMessageErrorHandler(event) {
postMessage({
id: event.data?.id,
error: `postMessage failed with error: ${JSON.stringify(event)}`
});
}
self.onmessage = onMessageHandler;
self.onmessageerror = onMessageErrorHandler;
return self;
}
var createTaskProcessorWorker_default = createTaskProcessorWorker;
// packages/engine/index.js
globalThis.CESIUM_VERSION = "1.133";
// packages/widgets/index.js
var import_InlineWorkers1345 = __toESM(require_InlineWorkers(), 1);
// packages/widgets/Source/ClockViewModel.js
var import_InlineWorkers1295 = __toESM(require_InlineWorkers(), 1);
// packages/widgets/Source/ThirdParty/knockout.js
var import_InlineWorkers1294 = __toESM(require_InlineWorkers(), 1);
// packages/widgets/Source/ThirdParty/knockout-3.5.1.js
var import_InlineWorkers1291 = __toESM(require_InlineWorkers(), 1);
var oldValue;
if (typeof ko !== "undefined") {
oldValue = ko;
}
(function() {
/*!
* Knockout JavaScript library v3.5.1
* (c) The Knockout.js team - http://knockoutjs.com/
* License: MIT (http://www.opensource.org/licenses/mit-license.php)
*/
(function() {
(function(n) {
var A = this || (0, eval)("this"), w = A.document, R = A.navigator, v3 = A.jQuery, H = A.JSON;
v3 || "undefined" === typeof jQuery || (v3 = jQuery);
(function(n2) {
n2(A.ko = {});
})(function(S, T2) {
function K(a4, c) {
return null === a4 || typeof a4 in W ? a4 === c : false;
}
function X(b, c) {
var d;
return function() {
d || (d = a3.a.setTimeout(function() {
d = n;
b();
}, c));
};
}
function Y(b, c) {
var d;
return function() {
clearTimeout(d);
d = a3.a.setTimeout(b, c);
};
}
function Z(a4, c) {
c && "change" !== c ? "beforeChange" === c ? this.pc(a4) : this.gb(a4, c) : this.qc(a4);
}
function aa(a4, c) {
null !== c && c.s && c.s();
}
function ba(a4, c) {
var d = this.qd, e = d[r];
e.ra || (this.Qb && this.mb[c] ? (d.uc(c, a4, this.mb[c]), this.mb[c] = null, --this.Qb) : e.I[c] || d.uc(c, a4, e.J ? { da: a4 } : d.$c(a4)), a4.Ja && a4.gd());
}
var a3 = "undefined" !== typeof S ? S : {};
a3.b = function(b, c) {
for (var d = b.split("."), e = a3, f = 0; f < d.length - 1; f++) e = e[d[f]];
e[d[d.length - 1]] = c;
};
a3.L = function(a4, c, d) {
a4[c] = d;
};
a3.version = "3.5.1";
a3.b(
"version",
a3.version
);
a3.options = { deferUpdates: false, useOnlyNativeEvents: false, foreachHidesDestroyed: false };
a3.a = (function() {
function b(a4, b2) {
for (var c14 in a4) f.call(a4, c14) && b2(c14, a4[c14]);
}
function c(a4, b2) {
if (b2) for (var c14 in b2) f.call(b2, c14) && (a4[c14] = b2[c14]);
return a4;
}
function d(a4, b2) {
a4.__proto__ = b2;
return a4;
}
function e(b2, c14, d2, e2) {
var l2 = b2[c14].match(q) || [];
a3.a.D(d2.match(q), function(b3) {
a3.a.Na(l2, b3, e2);
});
b2[c14] = l2.join(" ");
}
var f = Object.prototype.hasOwnProperty, g = { __proto__: [] } instanceof Array, h = "function" === typeof Symbol, m = {}, k = {};
m[R && /Firefox\/2/i.test(R.userAgent) ? "KeyboardEvent" : "UIEvents"] = ["keyup", "keydown", "keypress"];
m.MouseEvents = "click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");
b(m, function(a4, b2) {
if (b2.length) for (var c14 = 0, d2 = b2.length; c14 < d2; c14++) k[b2[c14]] = a4;
});
var l = { propertychange: true }, p = w && (function() {
for (var a4 = 3, b2 = w.createElement("div"), c14 = b2.getElementsByTagName("i"); b2.innerHTML = "", c14[0]; ) ;
return 4 < a4 ? a4 : n;
})(), q = /\S+/g, t;
return {
Jc: ["authenticity_token", /^__RequestVerificationToken(_.*)?$/],
D: function(a4, b2, c14) {
for (var d2 = 0, e2 = a4.length; d2 < e2; d2++) b2.call(c14, a4[d2], d2, a4);
},
A: "function" == typeof Array.prototype.indexOf ? function(a4, b2) {
return Array.prototype.indexOf.call(a4, b2);
} : function(a4, b2) {
for (var c14 = 0, d2 = a4.length; c14 < d2; c14++) if (a4[c14] === b2) return c14;
return -1;
},
Lb: function(a4, b2, c14) {
for (var d2 = 0, e2 = a4.length; d2 < e2; d2++) if (b2.call(c14, a4[d2], d2, a4)) return a4[d2];
return n;
},
Pa: function(b2, c14) {
var d2 = a3.a.A(b2, c14);
0 < d2 ? b2.splice(d2, 1) : 0 === d2 && b2.shift();
},
wc: function(b2) {
var c14 = [];
b2 && a3.a.D(b2, function(b3) {
0 > a3.a.A(c14, b3) && c14.push(b3);
});
return c14;
},
Mb: function(a4, b2, c14) {
var d2 = [];
if (a4) for (var e2 = 0, l2 = a4.length; e2 < l2; e2++) d2.push(b2.call(c14, a4[e2], e2));
return d2;
},
jb: function(a4, b2, c14) {
var d2 = [];
if (a4) for (var e2 = 0, l2 = a4.length; e2 < l2; e2++) b2.call(c14, a4[e2], e2) && d2.push(a4[e2]);
return d2;
},
Nb: function(a4, b2) {
if (b2 instanceof Array) a4.push.apply(a4, b2);
else for (var c14 = 0, d2 = b2.length; c14 < d2; c14++) a4.push(b2[c14]);
return a4;
},
Na: function(b2, c14, d2) {
var e2 = a3.a.A(a3.a.bc(b2), c14);
0 > e2 ? d2 && b2.push(c14) : d2 || b2.splice(e2, 1);
},
Ba: g,
extend: c,
setPrototypeOf: d,
Ab: g ? d : c,
P: b,
Ga: function(a4, b2, c14) {
if (!a4) return a4;
var d2 = {}, e2;
for (e2 in a4) f.call(a4, e2) && (d2[e2] = b2.call(c14, a4[e2], e2, a4));
return d2;
},
Tb: function(b2) {
for (; b2.firstChild; ) a3.removeNode(b2.firstChild);
},
Yb: function(b2) {
b2 = a3.a.la(b2);
for (var c14 = (b2[0] && b2[0].ownerDocument || w).createElement("div"), d2 = 0, e2 = b2.length; d2 < e2; d2++) c14.appendChild(a3.oa(b2[d2]));
return c14;
},
Ca: function(b2, c14) {
for (var d2 = 0, e2 = b2.length, l2 = []; d2 < e2; d2++) {
var k2 = b2[d2].cloneNode(true);
l2.push(c14 ? a3.oa(k2) : k2);
}
return l2;
},
va: function(b2, c14) {
a3.a.Tb(b2);
if (c14) for (var d2 = 0, e2 = c14.length; d2 < e2; d2++) b2.appendChild(c14[d2]);
},
Xc: function(b2, c14) {
var d2 = b2.nodeType ? [b2] : b2;
if (0 < d2.length) {
for (var e2 = d2[0], l2 = e2.parentNode, k2 = 0, f2 = c14.length; k2 < f2; k2++) l2.insertBefore(c14[k2], e2);
k2 = 0;
for (f2 = d2.length; k2 < f2; k2++) a3.removeNode(d2[k2]);
}
},
Ua: function(a4, b2) {
if (a4.length) {
for (b2 = 8 === b2.nodeType && b2.parentNode || b2; a4.length && a4[0].parentNode !== b2; ) a4.splice(0, 1);
for (; 1 < a4.length && a4[a4.length - 1].parentNode !== b2; ) a4.length--;
if (1 < a4.length) {
var c14 = a4[0], d2 = a4[a4.length - 1];
for (a4.length = 0; c14 !== d2; ) a4.push(c14), c14 = c14.nextSibling;
a4.push(d2);
}
}
return a4;
},
Zc: function(a4, b2) {
7 > p ? a4.setAttribute("selected", b2) : a4.selected = b2;
},
Db: function(a4) {
return null === a4 || a4 === n ? "" : a4.trim ? a4.trim() : a4.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g, "");
},
Ud: function(a4, b2) {
a4 = a4 || "";
return b2.length > a4.length ? false : a4.substring(0, b2.length) === b2;
},
vd: function(a4, b2) {
if (a4 === b2) return true;
if (11 === a4.nodeType) return false;
if (b2.contains) return b2.contains(1 !== a4.nodeType ? a4.parentNode : a4);
if (b2.compareDocumentPosition) return 16 == (b2.compareDocumentPosition(a4) & 16);
for (; a4 && a4 != b2; ) a4 = a4.parentNode;
return !!a4;
},
Sb: function(b2) {
return a3.a.vd(b2, b2.ownerDocument.documentElement);
},
kd: function(b2) {
return !!a3.a.Lb(b2, a3.a.Sb);
},
R: function(a4) {
return a4 && a4.tagName && a4.tagName.toLowerCase();
},
Ac: function(b2) {
return a3.onError ? function() {
try {
return b2.apply(this, arguments);
} catch (c14) {
throw a3.onError && a3.onError(c14), c14;
}
} : b2;
},
setTimeout: function(b2, c14) {
return setTimeout(a3.a.Ac(b2), c14);
},
Gc: function(b2) {
setTimeout(function() {
a3.onError && a3.onError(b2);
throw b2;
}, 0);
},
B: function(b2, c14, d2) {
var e2 = a3.a.Ac(d2);
d2 = l[c14];
if (a3.options.useOnlyNativeEvents || d2 || !v3) if (d2 || "function" != typeof b2.addEventListener) if ("undefined" != typeof b2.attachEvent) {
var k2 = function(a4) {
e2.call(b2, a4);
}, f2 = "on" + c14;
b2.attachEvent(
f2,
k2
);
a3.a.K.za(b2, function() {
b2.detachEvent(f2, k2);
});
} else throw Error("Browser doesn't support addEventListener or attachEvent");
else b2.addEventListener(c14, e2, false);
else t || (t = "function" == typeof v3(b2).on ? "on" : "bind"), v3(b2)[t](c14, e2);
},
Fb: function(b2, c14) {
if (!b2 || !b2.nodeType) throw Error("element must be a DOM node when calling triggerEvent");
var d2;
"input" === a3.a.R(b2) && b2.type && "click" == c14.toLowerCase() ? (d2 = b2.type, d2 = "checkbox" == d2 || "radio" == d2) : d2 = false;
if (a3.options.useOnlyNativeEvents || !v3 || d2) if ("function" == typeof w.createEvent) if ("function" == typeof b2.dispatchEvent) d2 = w.createEvent(k[c14] || "HTMLEvents"), d2.initEvent(c14, true, true, A, 0, 0, 0, 0, 0, false, false, false, false, 0, b2), b2.dispatchEvent(d2);
else throw Error("The supplied element doesn't support dispatchEvent");
else if (d2 && b2.click) b2.click();
else if ("undefined" != typeof b2.fireEvent) b2.fireEvent("on" + c14);
else throw Error("Browser doesn't support triggering events");
else v3(b2).trigger(c14);
},
f: function(b2) {
return a3.O(b2) ? b2() : b2;
},
bc: function(b2) {
return a3.O(b2) ? b2.v() : b2;
},
Eb: function(b2, c14, d2) {
var l2;
c14 && ("object" === typeof b2.classList ? (l2 = b2.classList[d2 ? "add" : "remove"], a3.a.D(c14.match(q), function(a4) {
l2.call(b2.classList, a4);
})) : "string" === typeof b2.className.baseVal ? e(b2.className, "baseVal", c14, d2) : e(b2, "className", c14, d2));
},
Bb: function(b2, c14) {
var d2 = a3.a.f(c14);
if (null === d2 || d2 === n) d2 = "";
var e2 = a3.h.firstChild(b2);
!e2 || 3 != e2.nodeType || a3.h.nextSibling(e2) ? a3.h.va(b2, [b2.ownerDocument.createTextNode(d2)]) : e2.data = d2;
a3.a.Ad(b2);
},
Yc: function(a4, b2) {
a4.name = b2;
if (7 >= p) try {
var c14 = a4.name.replace(/[&<>'"]/g, function(a5) {
return "" + a5.charCodeAt(0) + ";";
});
a4.mergeAttributes(w.createElement(""), false);
} catch (d2) {
}
},
Ad: function(a4) {
9 <= p && (a4 = 1 == a4.nodeType ? a4 : a4.parentNode, a4.style && (a4.style.zoom = a4.style.zoom));
},
wd: function(a4) {
if (p) {
var b2 = a4.style.width;
a4.style.width = 0;
a4.style.width = b2;
}
},
Pd: function(b2, c14) {
b2 = a3.a.f(b2);
c14 = a3.a.f(c14);
for (var d2 = [], e2 = b2; e2 <= c14; e2++) d2.push(e2);
return d2;
},
la: function(a4) {
for (var b2 = [], c14 = 0, d2 = a4.length; c14 < d2; c14++) b2.push(a4[c14]);
return b2;
},
Da: function(a4) {
return h ? Symbol(a4) : a4;
},
Zd: 6 === p,
$d: 7 === p,
W: p,
Lc: function(b2, c14) {
for (var d2 = a3.a.la(b2.getElementsByTagName("input")).concat(a3.a.la(b2.getElementsByTagName("textarea"))), e2 = "string" == typeof c14 ? function(a4) {
return a4.name === c14;
} : function(a4) {
return c14.test(a4.name);
}, l2 = [], k2 = d2.length - 1; 0 <= k2; k2--) e2(d2[k2]) && l2.push(d2[k2]);
return l2;
},
Nd: function(b2) {
return "string" == typeof b2 && (b2 = a3.a.Db(b2)) ? H && H.parse ? H.parse(b2) : new Function("return " + b2)() : null;
},
hc: function(b2, c14, d2) {
if (!H || !H.stringify) throw Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
return H.stringify(a3.a.f(b2), c14, d2);
},
Od: function(c14, d2, e2) {
e2 = e2 || {};
var l2 = e2.params || {}, k2 = e2.includeFields || this.Jc, f2 = c14;
if ("object" == typeof c14 && "form" === a3.a.R(c14)) for (var f2 = c14.action, h2 = k2.length - 1; 0 <= h2; h2--) for (var g2 = a3.a.Lc(c14, k2[h2]), m2 = g2.length - 1; 0 <= m2; m2--) l2[g2[m2].name] = g2[m2].value;
d2 = a3.a.f(d2);
var p2 = w.createElement("form");
p2.style.display = "none";
p2.action = f2;
p2.method = "post";
for (var q3 in d2) c14 = w.createElement("input"), c14.type = "hidden", c14.name = q3, c14.value = a3.a.hc(a3.a.f(d2[q3])), p2.appendChild(c14);
b(l2, function(a4, b2) {
var c15 = w.createElement("input");
c15.type = "hidden";
c15.name = a4;
c15.value = b2;
p2.appendChild(c15);
});
w.body.appendChild(p2);
e2.submitter ? e2.submitter(p2) : p2.submit();
setTimeout(function() {
p2.parentNode.removeChild(p2);
}, 0);
}
};
})();
a3.b("utils", a3.a);
a3.b("utils.arrayForEach", a3.a.D);
a3.b("utils.arrayFirst", a3.a.Lb);
a3.b("utils.arrayFilter", a3.a.jb);
a3.b("utils.arrayGetDistinctValues", a3.a.wc);
a3.b("utils.arrayIndexOf", a3.a.A);
a3.b("utils.arrayMap", a3.a.Mb);
a3.b("utils.arrayPushAll", a3.a.Nb);
a3.b("utils.arrayRemoveItem", a3.a.Pa);
a3.b("utils.cloneNodes", a3.a.Ca);
a3.b(
"utils.createSymbolOrString",
a3.a.Da
);
a3.b("utils.extend", a3.a.extend);
a3.b("utils.fieldsIncludedWithJsonPost", a3.a.Jc);
a3.b("utils.getFormFields", a3.a.Lc);
a3.b("utils.objectMap", a3.a.Ga);
a3.b("utils.peekObservable", a3.a.bc);
a3.b("utils.postJson", a3.a.Od);
a3.b("utils.parseJson", a3.a.Nd);
a3.b("utils.registerEventHandler", a3.a.B);
a3.b("utils.stringifyJson", a3.a.hc);
a3.b("utils.range", a3.a.Pd);
a3.b("utils.toggleDomNodeCssClass", a3.a.Eb);
a3.b("utils.triggerEvent", a3.a.Fb);
a3.b("utils.unwrapObservable", a3.a.f);
a3.b("utils.objectForEach", a3.a.P);
a3.b(
"utils.addOrRemoveItem",
a3.a.Na
);
a3.b("utils.setTextContent", a3.a.Bb);
a3.b("unwrap", a3.a.f);
Function.prototype.bind || (Function.prototype.bind = function(a4) {
var c = this;
if (1 === arguments.length) return function() {
return c.apply(a4, arguments);
};
var d = Array.prototype.slice.call(arguments, 1);
return function() {
var e = d.slice(0);
e.push.apply(e, arguments);
return c.apply(a4, e);
};
});
a3.a.g = new function() {
var b = 0, c = "__ko__" + (/* @__PURE__ */ new Date()).getTime(), d = {}, e, f;
a3.a.W ? (e = function(a4, e2) {
var f2 = a4[c];
if (!f2 || "null" === f2 || !d[f2]) {
if (!e2) return n;
f2 = a4[c] = "ko" + b++;
d[f2] = {};
}
return d[f2];
}, f = function(a4) {
var b2 = a4[c];
return b2 ? (delete d[b2], a4[c] = null, true) : false;
}) : (e = function(a4, b2) {
var d2 = a4[c];
!d2 && b2 && (d2 = a4[c] = {});
return d2;
}, f = function(a4) {
return a4[c] ? (delete a4[c], true) : false;
});
return { get: function(a4, b2) {
var c14 = e(a4, false);
return c14 && c14[b2];
}, set: function(a4, b2, c14) {
(a4 = e(a4, c14 !== n)) && (a4[b2] = c14);
}, Ub: function(a4, b2, c14) {
a4 = e(a4, true);
return a4[b2] || (a4[b2] = c14);
}, clear: f, Z: function() {
return b++ + c;
} };
}();
a3.b("utils.domData", a3.a.g);
a3.b("utils.domData.clear", a3.a.g.clear);
a3.a.K = new function() {
function b(b2, c14) {
var d2 = a3.a.g.get(b2, e);
d2 === n && c14 && (d2 = [], a3.a.g.set(b2, e, d2));
return d2;
}
function c(c14) {
var e2 = b(c14, false);
if (e2) for (var e2 = e2.slice(0), k = 0; k < e2.length; k++) e2[k](c14);
a3.a.g.clear(c14);
a3.a.K.cleanExternalData(c14);
g[c14.nodeType] && d(c14.childNodes, true);
}
function d(b2, d2) {
for (var e2 = [], l, f2 = 0; f2 < b2.length; f2++) if (!d2 || 8 === b2[f2].nodeType) {
if (c(e2[e2.length] = l = b2[f2]), b2[f2] !== l) for (; f2-- && -1 == a3.a.A(e2, b2[f2]); ) ;
}
}
var e = a3.a.g.Z(), f = { 1: true, 8: true, 9: true }, g = { 1: true, 9: true };
return { za: function(a4, c14) {
if ("function" != typeof c14) throw Error("Callback must be a function");
b(a4, true).push(c14);
}, yb: function(c14, d2) {
var f2 = b(c14, false);
f2 && (a3.a.Pa(f2, d2), 0 == f2.length && a3.a.g.set(c14, e, n));
}, oa: function(b2) {
a3.u.G(function() {
f[b2.nodeType] && (c(b2), g[b2.nodeType] && d(b2.getElementsByTagName("*")));
});
return b2;
}, removeNode: function(b2) {
a3.oa(b2);
b2.parentNode && b2.parentNode.removeChild(b2);
}, cleanExternalData: function(a4) {
v3 && "function" == typeof v3.cleanData && v3.cleanData([a4]);
} };
}();
a3.oa = a3.a.K.oa;
a3.removeNode = a3.a.K.removeNode;
a3.b("cleanNode", a3.oa);
a3.b("removeNode", a3.removeNode);
a3.b("utils.domNodeDisposal", a3.a.K);
a3.b(
"utils.domNodeDisposal.addDisposeCallback",
a3.a.K.za
);
a3.b("utils.domNodeDisposal.removeDisposeCallback", a3.a.K.yb);
(function() {
var b = [0, "", ""], c = [1, "", "
"], d = [3, "", "
"], e = [1, ""], f = { thead: c, tbody: c, tfoot: c, tr: [2, "", "
"], td: d, th: d, option: e, optgroup: e }, g = 8 >= a3.a.W;
a3.a.ua = function(c14, d2) {
var e2;
if (v3) if (v3.parseHTML) e2 = v3.parseHTML(c14, d2) || [];
else {
if ((e2 = v3.clean([c14], d2)) && e2[0]) {
for (var l = e2[0]; l.parentNode && 11 !== l.parentNode.nodeType; ) l = l.parentNode;
l.parentNode && l.parentNode.removeChild(l);
}
}
else {
(e2 = d2) || (e2 = w);
var l = e2.parentWindow || e2.defaultView || A, p = a3.a.Db(c14).toLowerCase(), q = e2.createElement("div"), t;
t = (p = p.match(/^(?:\x3c!--.*?--\x3e\s*?)*?<([a-z]+)[\s>]/)) && f[p[1]] || b;
p = t[0];
t = "ignored" + t[1] + c14 + t[2] + "";
"function" == typeof l.innerShiv ? q.appendChild(l.innerShiv(t)) : (g && e2.body.appendChild(q), q.innerHTML = t, g && q.parentNode.removeChild(q));
for (; p--; ) q = q.lastChild;
e2 = a3.a.la(q.lastChild.childNodes);
}
return e2;
};
a3.a.Md = function(b2, c14) {
var d2 = a3.a.ua(
b2,
c14
);
return d2.length && d2[0].parentElement || a3.a.Yb(d2);
};
a3.a.fc = function(b2, c14) {
a3.a.Tb(b2);
c14 = a3.a.f(c14);
if (null !== c14 && c14 !== n) if ("string" != typeof c14 && (c14 = c14.toString()), v3) v3(b2).html(c14);
else for (var d2 = a3.a.ua(c14, b2.ownerDocument), e2 = 0; e2 < d2.length; e2++) b2.appendChild(d2[e2]);
};
})();
a3.b("utils.parseHtmlFragment", a3.a.ua);
a3.b("utils.setHtml", a3.a.fc);
a3.aa = /* @__PURE__ */ (function() {
function b(c14, e) {
if (c14) {
if (8 == c14.nodeType) {
var f = a3.aa.Uc(c14.nodeValue);
null != f && e.push({ ud: c14, Kd: f });
} else if (1 == c14.nodeType) for (var f = 0, g = c14.childNodes, h = g.length; f < h; f++) b(
g[f],
e
);
}
}
var c = {};
return { Xb: function(a4) {
if ("function" != typeof a4) throw Error("You can only pass a function to ko.memoization.memoize()");
var b2 = (4294967296 * (1 + Math.random()) | 0).toString(16).substring(1) + (4294967296 * (1 + Math.random()) | 0).toString(16).substring(1);
c[b2] = a4;
return "";
}, bd: function(a4, b2) {
var f = c[a4];
if (f === n) throw Error("Couldn't find any memo with ID " + a4 + ". Perhaps it's already been unmemoized.");
try {
return f.apply(null, b2 || []), true;
} finally {
delete c[a4];
}
}, cd: function(c14, e) {
var f = [];
b(c14, f);
for (var g = 0, h = f.length; g < h; g++) {
var m = f[g].ud, k = [m];
e && a3.a.Nb(k, e);
a3.aa.bd(f[g].Kd, k);
m.nodeValue = "";
m.parentNode && m.parentNode.removeChild(m);
}
}, Uc: function(a4) {
return (a4 = a4.match(/^\[ko_memo\:(.*?)\]$/)) ? a4[1] : null;
} };
})();
a3.b("memoization", a3.aa);
a3.b("memoization.memoize", a3.aa.Xb);
a3.b("memoization.unmemoize", a3.aa.bd);
a3.b("memoization.parseMemoText", a3.aa.Uc);
a3.b("memoization.unmemoizeDomNodeAndDescendants", a3.aa.cd);
a3.na = (function() {
function b() {
if (f) {
for (var b2 = f, c14 = 0, d2; h < f; ) if (d2 = e[h++]) {
if (h > b2) {
if (5e3 <= ++c14) {
h = f;
a3.a.Gc(Error("'Too much recursion' after processing " + c14 + " task groups."));
break;
}
b2 = f;
}
try {
d2();
} catch (p) {
a3.a.Gc(p);
}
}
}
}
function c() {
b();
h = f = e.length = 0;
}
var d, e = [], f = 0, g = 1, h = 0;
A.MutationObserver ? d = (function(a4) {
var b2 = w.createElement("div");
new MutationObserver(a4).observe(b2, { attributes: true });
return function() {
b2.classList.toggle("foo");
};
})(c) : d = w && "onreadystatechange" in w.createElement("script") ? function(a4) {
var b2 = w.createElement("script");
b2.onreadystatechange = function() {
b2.onreadystatechange = null;
w.documentElement.removeChild(b2);
b2 = null;
a4();
};
w.documentElement.appendChild(b2);
} : function(a4) {
setTimeout(a4, 0);
};
return { scheduler: d, zb: function(b2) {
f || a3.na.scheduler(c);
e[f++] = b2;
return g++;
}, cancel: function(a4) {
a4 = a4 - (g - f);
a4 >= h && a4 < f && (e[a4] = null);
}, resetForTesting: function() {
var a4 = f - h;
h = f = e.length = 0;
return a4;
}, Sd: b };
})();
a3.b("tasks", a3.na);
a3.b("tasks.schedule", a3.na.zb);
a3.b("tasks.runEarly", a3.na.Sd);
a3.Ta = { throttle: function(b, c) {
b.throttleEvaluation = c;
var d = null;
return a3.$({ read: b, write: function(e) {
clearTimeout(d);
d = a3.a.setTimeout(
function() {
b(e);
},
c
);
} });
}, rateLimit: function(a4, c) {
var d, e, f;
"number" == typeof c ? d = c : (d = c.timeout, e = c.method);
a4.Hb = false;
f = "function" == typeof e ? e : "notifyWhenChangesStop" == e ? Y : X;
a4.ub(function(a5) {
return f(a5, d, c);
});
}, deferred: function(b, c) {
if (true !== c) throw Error("The 'deferred' extender only accepts the value 'true', because it is not supported to turn deferral off once enabled.");
b.Hb || (b.Hb = true, b.ub(function(c14) {
var e, f = false;
return function() {
if (!f) {
a3.na.cancel(e);
e = a3.na.zb(c14);
try {
f = true, b.notifySubscribers(n, "dirty");
} finally {
f = false;
}
}
};
}));
}, notify: function(a4, c) {
a4.equalityComparer = "always" == c ? null : K;
} };
var W = { undefined: 1, "boolean": 1, number: 1, string: 1 };
a3.b("extenders", a3.Ta);
a3.ic = function(b, c, d) {
this.da = b;
this.lc = c;
this.mc = d;
this.Ib = false;
this.fb = this.Jb = null;
a3.L(this, "dispose", this.s);
a3.L(this, "disposeWhenNodeIsRemoved", this.l);
};
a3.ic.prototype.s = function() {
this.Ib || (this.fb && a3.a.K.yb(this.Jb, this.fb), this.Ib = true, this.mc(), this.da = this.lc = this.mc = this.Jb = this.fb = null);
};
a3.ic.prototype.l = function(b) {
this.Jb = b;
a3.a.K.za(b, this.fb = this.s.bind(this));
};
a3.T = function() {
a3.a.Ab(this, D);
D.qb(this);
};
var D = {
qb: function(a4) {
a4.U = { change: [] };
a4.sc = 1;
},
subscribe: function(b, c, d) {
var e = this;
d = d || "change";
var f = new a3.ic(e, c ? b.bind(c) : b, function() {
a3.a.Pa(e.U[d], f);
e.hb && e.hb(d);
});
e.Qa && e.Qa(d);
e.U[d] || (e.U[d] = []);
e.U[d].push(f);
return f;
},
notifySubscribers: function(b, c) {
c = c || "change";
"change" === c && this.Gb();
if (this.Wa(c)) {
var d = "change" === c && this.ed || this.U[c].slice(0);
try {
a3.u.xc();
for (var e = 0, f; f = d[e]; ++e) f.Ib || f.lc(b);
} finally {
a3.u.end();
}
}
},
ob: function() {
return this.sc;
},
Dd: function(a4) {
return this.ob() !== a4;
},
Gb: function() {
++this.sc;
},
ub: function(b) {
var c = this, d = a3.O(c), e, f, g, h, m;
c.gb || (c.gb = c.notifySubscribers, c.notifySubscribers = Z);
var k = b(function() {
c.Ja = false;
d && h === c && (h = c.nc ? c.nc() : c());
var a4 = f || m && c.sb(g, h);
m = f = e = false;
a4 && c.gb(g = h);
});
c.qc = function(a4, b2) {
b2 && c.Ja || (m = !b2);
c.ed = c.U.change.slice(0);
c.Ja = e = true;
h = a4;
k();
};
c.pc = function(a4) {
e || (g = a4, c.gb(a4, "beforeChange"));
};
c.rc = function() {
m = true;
};
c.gd = function() {
c.sb(g, c.v(true)) && (f = true);
};
},
Wa: function(a4) {
return this.U[a4] && this.U[a4].length;
},
Bd: function(b) {
if (b) return this.U[b] && this.U[b].length || 0;
var c = 0;
a3.a.P(this.U, function(a4, b2) {
"dirty" !== a4 && (c += b2.length);
});
return c;
},
sb: function(a4, c) {
return !this.equalityComparer || !this.equalityComparer(a4, c);
},
toString: function() {
return "[object Object]";
},
extend: function(b) {
var c = this;
b && a3.a.P(b, function(b2, e) {
var f = a3.Ta[b2];
"function" == typeof f && (c = f(c, e) || c);
});
return c;
}
};
a3.L(D, "init", D.qb);
a3.L(D, "subscribe", D.subscribe);
a3.L(D, "extend", D.extend);
a3.L(D, "getSubscriptionsCount", D.Bd);
a3.a.Ba && a3.a.setPrototypeOf(
D,
Function.prototype
);
a3.T.fn = D;
a3.Qc = function(a4) {
return null != a4 && "function" == typeof a4.subscribe && "function" == typeof a4.notifySubscribers;
};
a3.b("subscribable", a3.T);
a3.b("isSubscribable", a3.Qc);
a3.S = a3.u = /* @__PURE__ */ (function() {
function b(a4) {
d.push(e);
e = a4;
}
function c() {
e = d.pop();
}
var d = [], e, f = 0;
return {
xc: b,
end: c,
cc: function(b2) {
if (e) {
if (!a3.Qc(b2)) throw Error("Only subscribable things can act as dependencies");
e.od.call(e.pd, b2, b2.fd || (b2.fd = ++f));
}
},
G: function(a4, d2, e2) {
try {
return b(), a4.apply(d2, e2 || []);
} finally {
c();
}
},
qa: function() {
if (e) return e.o.qa();
},
Va: function() {
if (e) return e.o.Va();
},
Ya: function() {
if (e) return e.Ya;
},
o: function() {
if (e) return e.o;
}
};
})();
a3.b("computedContext", a3.S);
a3.b("computedContext.getDependenciesCount", a3.S.qa);
a3.b("computedContext.getDependencies", a3.S.Va);
a3.b("computedContext.isInitial", a3.S.Ya);
a3.b("computedContext.registerDependency", a3.S.cc);
a3.b("ignoreDependencies", a3.Yd = a3.u.G);
var I = a3.a.Da("_latestValue");
a3.ta = function(b) {
function c() {
if (0 < arguments.length) return c.sb(c[I], arguments[0]) && (c.ya(), c[I] = arguments[0], c.xa()), this;
a3.u.cc(c);
return c[I];
}
c[I] = b;
a3.a.Ba || a3.a.extend(c, a3.T.fn);
a3.T.fn.qb(c);
a3.a.Ab(c, F);
a3.options.deferUpdates && a3.Ta.deferred(c, true);
return c;
};
var F = { equalityComparer: K, v: function() {
return this[I];
}, xa: function() {
this.notifySubscribers(this[I], "spectate");
this.notifySubscribers(this[I]);
}, ya: function() {
this.notifySubscribers(this[I], "beforeChange");
} };
a3.a.Ba && a3.a.setPrototypeOf(F, a3.T.fn);
var G = a3.ta.Ma = "__ko_proto__";
F[G] = a3.ta;
a3.O = function(b) {
if ((b = "function" == typeof b && b[G]) && b !== F[G] && b !== a3.o.fn[G]) throw Error("Invalid object that looks like an observable; possibly from another Knockout instance");
return !!b;
};
a3.Za = function(b) {
return "function" == typeof b && (b[G] === F[G] || b[G] === a3.o.fn[G] && b.Nc);
};
a3.b("observable", a3.ta);
a3.b("isObservable", a3.O);
a3.b("isWriteableObservable", a3.Za);
a3.b("isWritableObservable", a3.Za);
a3.b("observable.fn", F);
a3.L(F, "peek", F.v);
a3.L(F, "valueHasMutated", F.xa);
a3.L(F, "valueWillMutate", F.ya);
a3.Ha = function(b) {
b = b || [];
if ("object" != typeof b || !("length" in b)) throw Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
b = a3.ta(b);
a3.a.Ab(
b,
a3.Ha.fn
);
return b.extend({ trackArrayChanges: true });
};
a3.Ha.fn = { remove: function(b) {
for (var c = this.v(), d = [], e = "function" != typeof b || a3.O(b) ? function(a4) {
return a4 === b;
} : b, f = 0; f < c.length; f++) {
var g = c[f];
if (e(g)) {
0 === d.length && this.ya();
if (c[f] !== g) throw Error("Array modified during remove; cannot remove item");
d.push(g);
c.splice(f, 1);
f--;
}
}
d.length && this.xa();
return d;
}, removeAll: function(b) {
if (b === n) {
var c = this.v(), d = c.slice(0);
this.ya();
c.splice(0, c.length);
this.xa();
return d;
}
return b ? this.remove(function(c14) {
return 0 <= a3.a.A(b, c14);
}) : [];
}, destroy: function(b) {
var c = this.v(), d = "function" != typeof b || a3.O(b) ? function(a4) {
return a4 === b;
} : b;
this.ya();
for (var e = c.length - 1; 0 <= e; e--) {
var f = c[e];
d(f) && (f._destroy = true);
}
this.xa();
}, destroyAll: function(b) {
return b === n ? this.destroy(function() {
return true;
}) : b ? this.destroy(function(c) {
return 0 <= a3.a.A(b, c);
}) : [];
}, indexOf: function(b) {
var c = this();
return a3.a.A(c, b);
}, replace: function(a4, c) {
var d = this.indexOf(a4);
0 <= d && (this.ya(), this.v()[d] = c, this.xa());
}, sorted: function(a4) {
var c = this().slice(0);
return a4 ? c.sort(a4) : c.sort();
}, reversed: function() {
return this().slice(0).reverse();
} };
a3.a.Ba && a3.a.setPrototypeOf(a3.Ha.fn, a3.ta.fn);
a3.a.D("pop push reverse shift sort splice unshift".split(" "), function(b) {
a3.Ha.fn[b] = function() {
var a4 = this.v();
this.ya();
this.zc(a4, b, arguments);
var d = a4[b].apply(a4, arguments);
this.xa();
return d === a4 ? this : d;
};
});
a3.a.D(["slice"], function(b) {
a3.Ha.fn[b] = function() {
var a4 = this();
return a4[b].apply(a4, arguments);
};
});
a3.Pc = function(b) {
return a3.O(b) && "function" == typeof b.remove && "function" == typeof b.push;
};
a3.b("observableArray", a3.Ha);
a3.b("isObservableArray", a3.Pc);
a3.Ta.trackArrayChanges = function(b, c) {
function d() {
function c14() {
if (m) {
var d2 = [].concat(b.v() || []), e2;
if (b.Wa("arrayChange")) {
if (!f || 1 < m) f = a3.a.Pb(k, d2, b.Ob);
e2 = f;
}
k = d2;
f = null;
m = 0;
e2 && e2.length && b.notifySubscribers(e2, "arrayChange");
}
}
e ? c14() : (e = true, h = b.subscribe(function() {
++m;
}, null, "spectate"), k = [].concat(b.v() || []), f = null, g = b.subscribe(c14));
}
b.Ob = {};
c && "object" == typeof c && a3.a.extend(b.Ob, c);
b.Ob.sparse = true;
if (!b.zc) {
var e = false, f = null, g, h, m = 0, k, l = b.Qa, p = b.hb;
b.Qa = function(a4) {
l && l.call(b, a4);
"arrayChange" === a4 && d();
};
b.hb = function(a4) {
p && p.call(b, a4);
"arrayChange" !== a4 || b.Wa("arrayChange") || (g && g.s(), h && h.s(), h = g = null, e = false, k = n);
};
b.zc = function(b2, c14, d2) {
function l2(a4, b3, c15) {
return k2[k2.length] = { status: a4, value: b3, index: c15 };
}
if (e && !m) {
var k2 = [], p2 = b2.length, g2 = d2.length, h2 = 0;
switch (c14) {
case "push":
h2 = p2;
case "unshift":
for (c14 = 0; c14 < g2; c14++) l2("added", d2[c14], h2 + c14);
break;
case "pop":
h2 = p2 - 1;
case "shift":
p2 && l2("deleted", b2[h2], h2);
break;
case "splice":
c14 = Math.min(Math.max(0, 0 > d2[0] ? p2 + d2[0] : d2[0]), p2);
for (var p2 = 1 === g2 ? p2 : Math.min(c14 + (d2[1] || 0), p2), g2 = c14 + g2 - 2, h2 = Math.max(p2, g2), U = [], L = [], n2 = 2; c14 < h2; ++c14, ++n2) c14 < p2 && L.push(l2("deleted", b2[c14], c14)), c14 < g2 && U.push(l2("added", d2[n2], c14));
a3.a.Kc(L, U);
break;
default:
return;
}
f = k2;
}
};
}
};
var r = a3.a.Da("_state");
a3.o = a3.$ = function(b, c, d) {
function e() {
if (0 < arguments.length) {
if ("function" === typeof f) f.apply(g.nb, arguments);
else throw Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
return this;
}
g.ra || a3.u.cc(e);
(g.ka || g.J && e.Xa()) && e.ha();
return g.X;
}
"object" === typeof b ? d = b : (d = d || {}, b && (d.read = b));
if ("function" != typeof d.read) throw Error("Pass a function that returns the value of the ko.computed");
var f = d.write, g = { X: n, sa: true, ka: true, rb: false, jc: false, ra: false, wb: false, J: false, Wc: d.read, nb: c || d.owner, l: d.disposeWhenNodeIsRemoved || d.l || null, Sa: d.disposeWhen || d.Sa, Rb: null, I: {}, V: 0, Ic: null };
e[r] = g;
e.Nc = "function" === typeof f;
a3.a.Ba || a3.a.extend(e, a3.T.fn);
a3.T.fn.qb(e);
a3.a.Ab(e, C);
d.pure ? (g.wb = true, g.J = true, a3.a.extend(e, da)) : d.deferEvaluation && a3.a.extend(e, ea);
a3.options.deferUpdates && a3.Ta.deferred(e, true);
g.l && (g.jc = true, g.l.nodeType || (g.l = null));
g.J || d.deferEvaluation || e.ha();
g.l && e.ja() && a3.a.K.za(g.l, g.Rb = function() {
e.s();
});
return e;
};
var C = {
equalityComparer: K,
qa: function() {
return this[r].V;
},
Va: function() {
var b = [];
a3.a.P(this[r].I, function(a4, d) {
b[d.Ka] = d.da;
});
return b;
},
Vb: function(b) {
if (!this[r].V) return false;
var c = this.Va();
return -1 !== a3.a.A(c, b) ? true : !!a3.a.Lb(c, function(a4) {
return a4.Vb && a4.Vb(b);
});
},
uc: function(a4, c, d) {
if (this[r].wb && c === this) throw Error("A 'pure' computed must not be called recursively");
this[r].I[a4] = d;
d.Ka = this[r].V++;
d.La = c.ob();
},
Xa: function() {
var a4, c, d = this[r].I;
for (a4 in d) if (Object.prototype.hasOwnProperty.call(d, a4) && (c = d[a4], this.Ia && c.da.Ja || c.da.Dd(c.La))) return true;
},
Jd: function() {
this.Ia && !this[r].rb && this.Ia(false);
},
ja: function() {
var a4 = this[r];
return a4.ka || 0 < a4.V;
},
Rd: function() {
this.Ja ? this[r].ka && (this[r].sa = true) : this.Hc();
},
$c: function(a4) {
if (a4.Hb) {
var c = a4.subscribe(this.Jd, this, "dirty"), d = a4.subscribe(
this.Rd,
this
);
return { da: a4, s: function() {
c.s();
d.s();
} };
}
return a4.subscribe(this.Hc, this);
},
Hc: function() {
var b = this, c = b.throttleEvaluation;
c && 0 <= c ? (clearTimeout(this[r].Ic), this[r].Ic = a3.a.setTimeout(function() {
b.ha(true);
}, c)) : b.Ia ? b.Ia(true) : b.ha(true);
},
ha: function(b) {
var c = this[r], d = c.Sa, e = false;
if (!c.rb && !c.ra) {
if (c.l && !a3.a.Sb(c.l) || d && d()) {
if (!c.jc) {
this.s();
return;
}
} else c.jc = false;
c.rb = true;
try {
e = this.zd(b);
} finally {
c.rb = false;
}
return e;
}
},
zd: function(b) {
var c = this[r], d = false, e = c.wb ? n : !c.V, d = { qd: this, mb: c.I, Qb: c.V };
a3.u.xc({
pd: d,
od: ba,
o: this,
Ya: e
});
c.I = {};
c.V = 0;
var f = this.yd(c, d);
c.V ? d = this.sb(c.X, f) : (this.s(), d = true);
d && (c.J ? this.Gb() : this.notifySubscribers(c.X, "beforeChange"), c.X = f, this.notifySubscribers(c.X, "spectate"), !c.J && b && this.notifySubscribers(c.X), this.rc && this.rc());
e && this.notifySubscribers(c.X, "awake");
return d;
},
yd: function(b, c) {
try {
var d = b.Wc;
return b.nb ? d.call(b.nb) : d();
} finally {
a3.u.end(), c.Qb && !b.J && a3.a.P(c.mb, aa), b.sa = b.ka = false;
}
},
v: function(a4) {
var c = this[r];
(c.ka && (a4 || !c.V) || c.J && this.Xa()) && this.ha();
return c.X;
},
ub: function(b) {
a3.T.fn.ub.call(this, b);
this.nc = function() {
this[r].J || (this[r].sa ? this.ha() : this[r].ka = false);
return this[r].X;
};
this.Ia = function(a4) {
this.pc(this[r].X);
this[r].ka = true;
a4 && (this[r].sa = true);
this.qc(this, !a4);
};
},
s: function() {
var b = this[r];
!b.J && b.I && a3.a.P(b.I, function(a4, b2) {
b2.s && b2.s();
});
b.l && b.Rb && a3.a.K.yb(b.l, b.Rb);
b.I = n;
b.V = 0;
b.ra = true;
b.sa = false;
b.ka = false;
b.J = false;
b.l = n;
b.Sa = n;
b.Wc = n;
this.Nc || (b.nb = n);
}
}, da = { Qa: function(b) {
var c = this, d = c[r];
if (!d.ra && d.J && "change" == b) {
d.J = false;
if (d.sa || c.Xa()) d.I = null, d.V = 0, c.ha() && c.Gb();
else {
var e = [];
a3.a.P(d.I, function(a4, b2) {
e[b2.Ka] = a4;
});
a3.a.D(e, function(a4, b2) {
var e2 = d.I[a4], m = c.$c(e2.da);
m.Ka = b2;
m.La = e2.La;
d.I[a4] = m;
});
c.Xa() && c.ha() && c.Gb();
}
d.ra || c.notifySubscribers(d.X, "awake");
}
}, hb: function(b) {
var c = this[r];
c.ra || "change" != b || this.Wa("change") || (a3.a.P(c.I, function(a4, b2) {
b2.s && (c.I[a4] = { da: b2.da, Ka: b2.Ka, La: b2.La }, b2.s());
}), c.J = true, this.notifySubscribers(n, "asleep"));
}, ob: function() {
var b = this[r];
b.J && (b.sa || this.Xa()) && this.ha();
return a3.T.fn.ob.call(this);
} }, ea = { Qa: function(a4) {
"change" != a4 && "beforeChange" != a4 || this.v();
} };
a3.a.Ba && a3.a.setPrototypeOf(C, a3.T.fn);
var N = a3.ta.Ma;
C[N] = a3.o;
a3.Oc = function(a4) {
return "function" == typeof a4 && a4[N] === C[N];
};
a3.Fd = function(b) {
return a3.Oc(b) && b[r] && b[r].wb;
};
a3.b("computed", a3.o);
a3.b("dependentObservable", a3.o);
a3.b("isComputed", a3.Oc);
a3.b("isPureComputed", a3.Fd);
a3.b("computed.fn", C);
a3.L(C, "peek", C.v);
a3.L(C, "dispose", C.s);
a3.L(C, "isActive", C.ja);
a3.L(C, "getDependenciesCount", C.qa);
a3.L(C, "getDependencies", C.Va);
a3.xb = function(b, c) {
if ("function" === typeof b) return a3.o(
b,
c,
{ pure: true }
);
b = a3.a.extend({}, b);
b.pure = true;
return a3.o(b, c);
};
a3.b("pureComputed", a3.xb);
(function() {
function b(a4, f, g) {
g = g || new d();
a4 = f(a4);
if ("object" != typeof a4 || null === a4 || a4 === n || a4 instanceof RegExp || a4 instanceof Date || a4 instanceof String || a4 instanceof Number || a4 instanceof Boolean) return a4;
var h = a4 instanceof Array ? [] : {};
g.save(a4, h);
c(a4, function(c14) {
var d2 = f(a4[c14]);
switch (typeof d2) {
case "boolean":
case "number":
case "string":
case "function":
h[c14] = d2;
break;
case "object":
case "undefined":
var l = g.get(d2);
h[c14] = l !== n ? l : b(d2, f, g);
}
});
return h;
}
function c(a4, b2) {
if (a4 instanceof Array) {
for (var c14 = 0; c14 < a4.length; c14++) b2(c14);
"function" == typeof a4.toJSON && b2("toJSON");
} else for (c14 in a4) b2(c14);
}
function d() {
this.keys = [];
this.values = [];
}
a3.ad = function(c14) {
if (0 == arguments.length) throw Error("When calling ko.toJS, pass the object you want to convert.");
return b(c14, function(b2) {
for (var c15 = 0; a3.O(b2) && 10 > c15; c15++) b2 = b2();
return b2;
});
};
a3.toJSON = function(b2, c14, d2) {
b2 = a3.ad(b2);
return a3.a.hc(b2, c14, d2);
};
d.prototype = { constructor: d, save: function(b2, c14) {
var d2 = a3.a.A(
this.keys,
b2
);
0 <= d2 ? this.values[d2] = c14 : (this.keys.push(b2), this.values.push(c14));
}, get: function(b2) {
b2 = a3.a.A(this.keys, b2);
return 0 <= b2 ? this.values[b2] : n;
} };
})();
a3.b("toJS", a3.ad);
a3.b("toJSON", a3.toJSON);
a3.Wd = function(b, c, d) {
function e(c14) {
var e2 = a3.xb(b, d).extend({ ma: "always" }), h = e2.subscribe(function(a4) {
a4 && (h.s(), c14(a4));
});
e2.notifySubscribers(e2.v());
return h;
}
return "function" !== typeof Promise || c ? e(c.bind(d)) : new Promise(e);
};
a3.b("when", a3.Wd);
(function() {
a3.w = { M: function(b) {
switch (a3.a.R(b)) {
case "option":
return true === b.__ko__hasDomDataOptionValue__ ? a3.a.g.get(b, a3.c.options.$b) : 7 >= a3.a.W ? b.getAttributeNode("value") && b.getAttributeNode("value").specified ? b.value : b.text : b.value;
case "select":
return 0 <= b.selectedIndex ? a3.w.M(b.options[b.selectedIndex]) : n;
default:
return b.value;
}
}, cb: function(b, c, d) {
switch (a3.a.R(b)) {
case "option":
"string" === typeof c ? (a3.a.g.set(b, a3.c.options.$b, n), "__ko__hasDomDataOptionValue__" in b && delete b.__ko__hasDomDataOptionValue__, b.value = c) : (a3.a.g.set(b, a3.c.options.$b, c), b.__ko__hasDomDataOptionValue__ = true, b.value = "number" === typeof c ? c : "");
break;
case "select":
if ("" === c || null === c) c = n;
for (var e = -1, f = 0, g = b.options.length, h; f < g; ++f) if (h = a3.w.M(b.options[f]), h == c || "" === h && c === n) {
e = f;
break;
}
if (d || 0 <= e || c === n && 1 < b.size) b.selectedIndex = e, 6 === a3.a.W && a3.a.setTimeout(function() {
b.selectedIndex = e;
}, 0);
break;
default:
if (null === c || c === n) c = "";
b.value = c;
}
} };
})();
a3.b("selectExtensions", a3.w);
a3.b("selectExtensions.readValue", a3.w.M);
a3.b("selectExtensions.writeValue", a3.w.cb);
a3.m = (function() {
function b(b2) {
b2 = a3.a.Db(b2);
123 === b2.charCodeAt(0) && (b2 = b2.slice(
1,
-1
));
b2 += "\n,";
var c14 = [], d2 = b2.match(e), p, q = [], h2 = 0;
if (1 < d2.length) {
for (var x = 0, B; B = d2[x]; ++x) {
var u3 = B.charCodeAt(0);
if (44 === u3) {
if (0 >= h2) {
c14.push(p && q.length ? { key: p, value: q.join("") } : { unknown: p || q.join("") });
p = h2 = 0;
q = [];
continue;
}
} else if (58 === u3) {
if (!h2 && !p && 1 === q.length) {
p = q.pop();
continue;
}
} else if (47 === u3 && 1 < B.length && (47 === B.charCodeAt(1) || 42 === B.charCodeAt(1))) continue;
else 47 === u3 && x && 1 < B.length ? (u3 = d2[x - 1].match(f)) && !g[u3[0]] && (b2 = b2.substr(b2.indexOf(B) + 1), d2 = b2.match(e), x = -1, B = "/") : 40 === u3 || 123 === u3 || 91 === u3 ? ++h2 : 41 === u3 || 125 === u3 || 93 === u3 ? --h2 : p || q.length || 34 !== u3 && 39 !== u3 || (B = B.slice(1, -1));
q.push(B);
}
if (0 < h2) throw Error("Unbalanced parentheses, braces, or brackets");
}
return c14;
}
var c = ["true", "false", "null", "undefined"], d = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i, e = RegExp("\"(?:\\\\.|[^\"])*\"|'(?:\\\\.|[^'])*'|`(?:\\\\.|[^`])*`|/\\*(?:[^*]|\\*+[^*/])*\\*+/|//.*\n|/(?:\\\\.|[^/])+/w*|[^\\s:,/][^,\"'`{}()/:[\\]]*[^\\s,\"'`{}()/:[\\]]|[^\\s]", "g"), f = /[\])"'A-Za-z0-9_$]+$/, g = { "in": 1, "return": 1, "typeof": 1 }, h = {};
return { Ra: [], wa: h, ac: b, vb: function(e2, f2) {
function l(b2, e3) {
var f3;
if (!x) {
var k = a3.getBindingHandler(b2);
if (k && k.preprocess && !(e3 = k.preprocess(e3, b2, l))) return;
if (k = h[b2]) f3 = e3, 0 <= a3.a.A(c, f3) ? f3 = false : (k = f3.match(d), f3 = null === k ? false : k[1] ? "Object(" + k[1] + ")" + k[2] : f3), k = f3;
k && q.push("'" + ("string" == typeof h[b2] ? h[b2] : b2) + "':function(_z){" + f3 + "=_z}");
}
g2 && (e3 = "function(){return " + e3 + " }");
p.push("'" + b2 + "':" + e3);
}
f2 = f2 || {};
var p = [], q = [], g2 = f2.valueAccessors, x = f2.bindingParams, B = "string" === typeof e2 ? b(e2) : e2;
a3.a.D(B, function(a4) {
l(
a4.key || a4.unknown,
a4.value
);
});
q.length && l("_ko_property_writers", "{" + q.join(",") + " }");
return p.join(",");
}, Id: function(a4, b2) {
for (var c14 = 0; c14 < a4.length; c14++) if (a4[c14].key == b2) return true;
return false;
}, eb: function(b2, c14, d2, e2, f2) {
if (b2 && a3.O(b2)) !a3.Za(b2) || f2 && b2.v() === e2 || b2(e2);
else if ((b2 = c14.get("_ko_property_writers")) && b2[d2]) b2[d2](e2);
} };
})();
a3.b("expressionRewriting", a3.m);
a3.b("expressionRewriting.bindingRewriteValidators", a3.m.Ra);
a3.b("expressionRewriting.parseObjectLiteral", a3.m.ac);
a3.b("expressionRewriting.preProcessBindings", a3.m.vb);
a3.b(
"expressionRewriting._twoWayBindings",
a3.m.wa
);
a3.b("jsonExpressionRewriting", a3.m);
a3.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson", a3.m.vb);
(function() {
function b(a4) {
return 8 == a4.nodeType && g.test(f ? a4.text : a4.nodeValue);
}
function c(a4) {
return 8 == a4.nodeType && h.test(f ? a4.text : a4.nodeValue);
}
function d(d2, e2) {
for (var f2 = d2, h2 = 1, g2 = []; f2 = f2.nextSibling; ) {
if (c(f2) && (a3.a.g.set(f2, k, true), h2--, 0 === h2)) return g2;
g2.push(f2);
b(f2) && h2++;
}
if (!e2) throw Error("Cannot find closing comment tag to match: " + d2.nodeValue);
return null;
}
function e(a4, b2) {
var c14 = d(a4, b2);
return c14 ? 0 < c14.length ? c14[c14.length - 1].nextSibling : a4.nextSibling : null;
}
var f = w && "" === w.createComment("test").text, g = f ? /^\x3c!--\s*ko(?:\s+([\s\S]+))?\s*--\x3e$/ : /^\s*ko(?:\s+([\s\S]+))?\s*$/, h = f ? /^\x3c!--\s*\/ko\s*--\x3e$/ : /^\s*\/ko\s*$/, m = { ul: true, ol: true }, k = "__ko_matchedEndComment__";
a3.h = { ea: {}, childNodes: function(a4) {
return b(a4) ? d(a4) : a4.childNodes;
}, Ea: function(c14) {
if (b(c14)) {
c14 = a3.h.childNodes(c14);
for (var d2 = 0, e2 = c14.length; d2 < e2; d2++) a3.removeNode(c14[d2]);
} else a3.a.Tb(c14);
}, va: function(c14, d2) {
if (b(c14)) {
a3.h.Ea(c14);
for (var e2 = c14.nextSibling, f2 = 0, k2 = d2.length; f2 < k2; f2++) e2.parentNode.insertBefore(d2[f2], e2);
} else a3.a.va(c14, d2);
}, Vc: function(a4, c14) {
var d2;
b(a4) ? (d2 = a4.nextSibling, a4 = a4.parentNode) : d2 = a4.firstChild;
d2 ? c14 !== d2 && a4.insertBefore(c14, d2) : a4.appendChild(c14);
}, Wb: function(c14, d2, e2) {
e2 ? (e2 = e2.nextSibling, b(c14) && (c14 = c14.parentNode), e2 ? d2 !== e2 && c14.insertBefore(d2, e2) : c14.appendChild(d2)) : a3.h.Vc(c14, d2);
}, firstChild: function(a4) {
if (b(a4)) return !a4.nextSibling || c(a4.nextSibling) ? null : a4.nextSibling;
if (a4.firstChild && c(a4.firstChild)) throw Error("Found invalid end comment, as the first child of " + a4);
return a4.firstChild;
}, nextSibling: function(d2) {
b(d2) && (d2 = e(d2));
if (d2.nextSibling && c(d2.nextSibling)) {
var f2 = d2.nextSibling;
if (c(f2) && !a3.a.g.get(f2, k)) throw Error("Found end comment without a matching opening comment, as child of " + d2);
return null;
}
return d2.nextSibling;
}, Cd: b, Vd: function(a4) {
return (a4 = (f ? a4.text : a4.nodeValue).match(g)) ? a4[1] : null;
}, Sc: function(d2) {
if (m[a3.a.R(d2)]) {
var f2 = d2.firstChild;
if (f2) {
do
if (1 === f2.nodeType) {
var k2;
k2 = f2.firstChild;
var h2 = null;
if (k2) {
do
if (h2) h2.push(k2);
else if (b(k2)) {
var g2 = e(k2, true);
g2 ? k2 = g2 : h2 = [k2];
} else c(k2) && (h2 = [k2]);
while (k2 = k2.nextSibling);
}
if (k2 = h2) for (h2 = f2.nextSibling, g2 = 0; g2 < k2.length; g2++) h2 ? d2.insertBefore(k2[g2], h2) : d2.appendChild(k2[g2]);
}
while (f2 = f2.nextSibling);
}
}
} };
})();
a3.b("virtualElements", a3.h);
a3.b("virtualElements.allowedBindings", a3.h.ea);
a3.b("virtualElements.emptyNode", a3.h.Ea);
a3.b("virtualElements.insertAfter", a3.h.Wb);
a3.b("virtualElements.prepend", a3.h.Vc);
a3.b("virtualElements.setDomNodeChildren", a3.h.va);
(function() {
a3.ga = function() {
this.nd = {};
};
a3.a.extend(a3.ga.prototype, {
nodeHasBindings: function(b) {
switch (b.nodeType) {
case 1:
return null != b.getAttribute("data-bind") || a3.j.getComponentNameForNode(b);
case 8:
return a3.h.Cd(b);
default:
return false;
}
},
getBindings: function(b, c) {
var d = this.getBindingsString(b, c), d = d ? this.parseBindingsString(d, c, b) : null;
return a3.j.tc(d, b, c, false);
},
getBindingAccessors: function(b, c) {
var d = this.getBindingsString(b, c), d = d ? this.parseBindingsString(d, c, b, { valueAccessors: true }) : null;
return a3.j.tc(d, b, c, true);
},
getBindingsString: function(b) {
switch (b.nodeType) {
case 1:
return b.getAttribute("data-bind");
case 8:
return a3.h.Vd(b);
default:
return null;
}
},
parseBindingsString: function(b, c, d, e) {
try {
var f = this.nd, g = b + (e && e.valueAccessors || ""), h;
if (!(h = f[g])) {
var m, k = "with($context){with($data||{}){return{" + a3.m.vb(b, e) + "}}}";
m = new Function("$context", "$element", k);
h = f[g] = m;
}
return h(c, d);
} catch (l) {
throw l.message = "Unable to parse bindings.\nBindings value: " + b + "\nMessage: " + l.message, l;
}
}
});
a3.ga.instance = new a3.ga();
})();
a3.b("bindingProvider", a3.ga);
(function() {
function b(b2) {
var c14 = (b2 = a3.a.g.get(b2, z)) && b2.N;
c14 && (b2.N = null, c14.Tc());
}
function c(c14, d2, e2) {
this.node = c14;
this.yc = d2;
this.kb = [];
this.H = false;
d2.N || a3.a.K.za(c14, b);
e2 && e2.N && (e2.N.kb.push(c14), this.Kb = e2);
}
function d(a4) {
return function() {
return a4;
};
}
function e(a4) {
return a4();
}
function f(b2) {
return a3.a.Ga(a3.u.G(b2), function(a4, c14) {
return function() {
return b2()[c14];
};
});
}
function g(b2, c14, e2) {
return "function" === typeof b2 ? f(b2.bind(null, c14, e2)) : a3.a.Ga(b2, d);
}
function h(a4, b2) {
return f(this.getBindings.bind(this, a4, b2));
}
function m(b2, c14) {
var d2 = a3.h.firstChild(c14);
if (d2) {
var e2, f2 = a3.ga.instance, l2 = f2.preprocessNode;
if (l2) {
for (; e2 = d2; ) d2 = a3.h.nextSibling(e2), l2.call(f2, e2);
d2 = a3.h.firstChild(c14);
}
for (; e2 = d2; ) d2 = a3.h.nextSibling(e2), k(b2, e2);
}
a3.i.ma(c14, a3.i.H);
}
function k(b2, c14) {
var d2 = b2, e2 = 1 === c14.nodeType;
e2 && a3.h.Sc(c14);
if (e2 || a3.ga.instance.nodeHasBindings(c14)) d2 = p(c14, null, b2).bindingContextForDescendants;
d2 && !u3[a3.a.R(c14)] && m(d2, c14);
}
function l(b2) {
var c14 = [], d2 = {}, e2 = [];
a3.a.P(b2, function ca(f2) {
if (!d2[f2]) {
var k2 = a3.getBindingHandler(f2);
k2 && (k2.after && (e2.push(f2), a3.a.D(k2.after, function(c15) {
if (b2[c15]) {
if (-1 !== a3.a.A(e2, c15)) throw Error("Cannot combine the following bindings, because they have a cyclic dependency: " + e2.join(", "));
ca(c15);
}
}), e2.length--), c14.push({ key: f2, Mc: k2 }));
d2[f2] = true;
}
});
return c14;
}
function p(b2, c14, d2) {
var f2 = a3.a.g.Ub(b2, z, {}), k2 = f2.hd;
if (!c14) {
if (k2) throw Error("You cannot apply bindings multiple times to the same element.");
f2.hd = true;
}
k2 || (f2.context = d2);
f2.Zb || (f2.Zb = {});
var g2;
if (c14 && "function" !== typeof c14) g2 = c14;
else {
var p2 = a3.ga.instance, q3 = p2.getBindingAccessors || h, m2 = a3.$(function() {
if (g2 = c14 ? c14(d2, b2) : q3.call(p2, b2, d2)) {
if (d2[t]) d2[t]();
if (d2[B]) d2[B]();
}
return g2;
}, null, { l: b2 });
g2 && m2.ja() || (m2 = null);
}
var x2 = d2, u4;
if (g2) {
var J2 = function() {
return a3.a.Ga(m2 ? m2() : g2, e);
}, r2 = m2 ? function(a4) {
return function() {
return e(m2()[a4]);
};
} : function(a4) {
return g2[a4];
};
J2.get = function(a4) {
return g2[a4] && e(r2(a4));
};
J2.has = function(a4) {
return a4 in g2;
};
a3.i.H in g2 && a3.i.subscribe(b2, a3.i.H, function() {
var c15 = (0, g2[a3.i.H])();
if (c15) {
var d3 = a3.h.childNodes(b2);
d3.length && c15(d3, a3.Ec(d3[0]));
}
});
a3.i.pa in g2 && (x2 = a3.i.Cb(b2, d2), a3.i.subscribe(b2, a3.i.pa, function() {
var c15 = (0, g2[a3.i.pa])();
c15 && a3.h.firstChild(b2) && c15(b2);
}));
f2 = l(g2);
a3.a.D(f2, function(c15) {
var d3 = c15.Mc.init, e2 = c15.Mc.update, f3 = c15.key;
if (8 === b2.nodeType && !a3.h.ea[f3]) throw Error("The binding '" + f3 + "' cannot be used with virtual elements");
try {
"function" == typeof d3 && a3.u.G(function() {
var a4 = d3(b2, r2(f3), J2, x2.$data, x2);
if (a4 && a4.controlsDescendantBindings) {
if (u4 !== n) throw Error("Multiple bindings (" + u4 + " and " + f3 + ") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");
u4 = f3;
}
}), "function" == typeof e2 && a3.$(function() {
e2(b2, r2(f3), J2, x2.$data, x2);
}, null, { l: b2 });
} catch (k3) {
throw k3.message = 'Unable to process binding "' + f3 + ": " + g2[f3] + '"\nMessage: ' + k3.message, k3;
}
});
}
f2 = u4 === n;
return { shouldBindDescendants: f2, bindingContextForDescendants: f2 && x2 };
}
function q(b2, c14) {
return b2 && b2 instanceof a3.fa ? b2 : new a3.fa(b2, n, n, c14);
}
var t = a3.a.Da("_subscribable"), x = a3.a.Da("_ancestorBindingInfo"), B = a3.a.Da("_dataDependency");
a3.c = {};
var u3 = { script: true, textarea: true, template: true };
a3.getBindingHandler = function(b2) {
return a3.c[b2];
};
var J = {};
a3.fa = function(b2, c14, d2, e2, f2) {
function k2() {
var b3 = p2 ? h2() : h2, f3 = a3.a.f(b3);
c14 ? (a3.a.extend(l2, c14), x in c14 && (l2[x] = c14[x])) : (l2.$parents = [], l2.$root = f3, l2.ko = a3);
l2[t] = q3;
g2 ? f3 = l2.$data : (l2.$rawData = b3, l2.$data = f3);
d2 && (l2[d2] = f3);
e2 && e2(l2, c14, f3);
if (c14 && c14[t] && !a3.S.o().Vb(c14[t])) c14[t]();
m2 && (l2[B] = m2);
return l2.$data;
}
var l2 = this, g2 = b2 === J, h2 = g2 ? n : b2, p2 = "function" == typeof h2 && !a3.O(h2), q3, m2 = f2 && f2.dataDependency;
f2 && f2.exportDependencies ? k2() : (q3 = a3.xb(k2), q3.v(), q3.ja() ? q3.equalityComparer = null : l2[t] = n);
};
a3.fa.prototype.createChildContext = function(b2, c14, d2, e2) {
!e2 && c14 && "object" == typeof c14 && (e2 = c14, c14 = e2.as, d2 = e2.extend);
if (c14 && e2 && e2.noChildContext) {
var f2 = "function" == typeof b2 && !a3.O(b2);
return new a3.fa(J, this, null, function(a4) {
d2 && d2(a4);
a4[c14] = f2 ? b2() : b2;
}, e2);
}
return new a3.fa(
b2,
this,
c14,
function(a4, b3) {
a4.$parentContext = b3;
a4.$parent = b3.$data;
a4.$parents = (b3.$parents || []).slice(0);
a4.$parents.unshift(a4.$parent);
d2 && d2(a4);
},
e2
);
};
a3.fa.prototype.extend = function(b2, c14) {
return new a3.fa(J, this, null, function(c15) {
a3.a.extend(c15, "function" == typeof b2 ? b2(c15) : b2);
}, c14);
};
var z = a3.a.g.Z();
c.prototype.Tc = function() {
this.Kb && this.Kb.N && this.Kb.N.sd(this.node);
};
c.prototype.sd = function(b2) {
a3.a.Pa(this.kb, b2);
!this.kb.length && this.H && this.Cc();
};
c.prototype.Cc = function() {
this.H = true;
this.yc.N && !this.kb.length && (this.yc.N = null, a3.a.K.yb(this.node, b), a3.i.ma(this.node, a3.i.pa), this.Tc());
};
a3.i = { H: "childrenComplete", pa: "descendantsComplete", subscribe: function(b2, c14, d2, e2, f2) {
var k2 = a3.a.g.Ub(b2, z, {});
k2.Fa || (k2.Fa = new a3.T());
f2 && f2.notifyImmediately && k2.Zb[c14] && a3.u.G(d2, e2, [b2]);
return k2.Fa.subscribe(d2, e2, c14);
}, ma: function(b2, c14) {
var d2 = a3.a.g.get(b2, z);
if (d2 && (d2.Zb[c14] = true, d2.Fa && d2.Fa.notifySubscribers(b2, c14), c14 == a3.i.H)) {
if (d2.N) d2.N.Cc();
else if (d2.N === n && d2.Fa && d2.Fa.Wa(a3.i.pa)) throw Error("descendantsComplete event not supported for bindings on this node");
}
}, Cb: function(b2, d2) {
var e2 = a3.a.g.Ub(b2, z, {});
e2.N || (e2.N = new c(b2, e2, d2[x]));
return d2[x] == e2 ? d2 : d2.extend(function(a4) {
a4[x] = e2;
});
} };
a3.Td = function(b2) {
return (b2 = a3.a.g.get(b2, z)) && b2.context;
};
a3.ib = function(b2, c14, d2) {
1 === b2.nodeType && a3.h.Sc(b2);
return p(b2, c14, q(d2));
};
a3.ld = function(b2, c14, d2) {
d2 = q(d2);
return a3.ib(b2, g(c14, d2, b2), d2);
};
a3.Oa = function(a4, b2) {
1 !== b2.nodeType && 8 !== b2.nodeType || m(q(a4), b2);
};
a3.vc = function(a4, b2, c14) {
!v3 && A.jQuery && (v3 = A.jQuery);
if (2 > arguments.length) {
if (b2 = w.body, !b2) throw Error("ko.applyBindings: could not find document.body; has the document been loaded?");
} else if (!b2 || 1 !== b2.nodeType && 8 !== b2.nodeType) throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
k(q(a4, c14), b2);
};
a3.Dc = function(b2) {
return !b2 || 1 !== b2.nodeType && 8 !== b2.nodeType ? n : a3.Td(b2);
};
a3.Ec = function(b2) {
return (b2 = a3.Dc(b2)) ? b2.$data : n;
};
a3.b("bindingHandlers", a3.c);
a3.b("bindingEvent", a3.i);
a3.b("bindingEvent.subscribe", a3.i.subscribe);
a3.b("bindingEvent.startPossiblyAsyncContentBinding", a3.i.Cb);
a3.b("applyBindings", a3.vc);
a3.b("applyBindingsToDescendants", a3.Oa);
a3.b("applyBindingAccessorsToNode", a3.ib);
a3.b("applyBindingsToNode", a3.ld);
a3.b("contextFor", a3.Dc);
a3.b("dataFor", a3.Ec);
})();
(function(b) {
function c(c14, e2) {
var k = Object.prototype.hasOwnProperty.call(f, c14) ? f[c14] : b, l;
k ? k.subscribe(e2) : (k = f[c14] = new a3.T(), k.subscribe(e2), d(c14, function(b2, d2) {
var e3 = !(!d2 || !d2.synchronous);
g[c14] = { definition: b2, Gd: e3 };
delete f[c14];
l || e3 ? k.notifySubscribers(b2) : a3.na.zb(function() {
k.notifySubscribers(b2);
});
}), l = true);
}
function d(a4, b2) {
e("getConfig", [a4], function(c14) {
c14 ? e("loadComponent", [a4, c14], function(a5) {
b2(
a5,
c14
);
}) : b2(null, null);
});
}
function e(c14, d2, f2, l) {
l || (l = a3.j.loaders.slice(0));
var g2 = l.shift();
if (g2) {
var q = g2[c14];
if (q) {
var t = false;
if (q.apply(g2, d2.concat(function(a4) {
t ? f2(null) : null !== a4 ? f2(a4) : e(c14, d2, f2, l);
})) !== b && (t = true, !g2.suppressLoaderExceptions)) throw Error("Component loaders must supply values by invoking the callback, not by returning values synchronously.");
} else e(c14, d2, f2, l);
} else f2(null);
}
var f = {}, g = {};
a3.j = { get: function(d2, e2) {
var f2 = Object.prototype.hasOwnProperty.call(g, d2) ? g[d2] : b;
f2 ? f2.Gd ? a3.u.G(function() {
e2(f2.definition);
}) : a3.na.zb(function() {
e2(f2.definition);
}) : c(d2, e2);
}, Bc: function(a4) {
delete g[a4];
}, oc: e };
a3.j.loaders = [];
a3.b("components", a3.j);
a3.b("components.get", a3.j.get);
a3.b("components.clearCachedDefinition", a3.j.Bc);
})();
(function() {
function b(b2, c14, d2, e2) {
function g2() {
0 === --B && e2(h2);
}
var h2 = {}, B = 2, u3 = d2.template;
d2 = d2.viewModel;
u3 ? f(c14, u3, function(c15) {
a3.j.oc("loadTemplate", [b2, c15], function(a4) {
h2.template = a4;
g2();
});
}) : g2();
d2 ? f(c14, d2, function(c15) {
a3.j.oc("loadViewModel", [b2, c15], function(a4) {
h2[m] = a4;
g2();
});
}) : g2();
}
function c(a4, b2, d2) {
if ("function" === typeof b2) d2(function(a5) {
return new b2(a5);
});
else if ("function" === typeof b2[m]) d2(b2[m]);
else if ("instance" in b2) {
var e2 = b2.instance;
d2(function() {
return e2;
});
} else "viewModel" in b2 ? c(a4, b2.viewModel, d2) : a4("Unknown viewModel value: " + b2);
}
function d(b2) {
switch (a3.a.R(b2)) {
case "script":
return a3.a.ua(b2.text);
case "textarea":
return a3.a.ua(b2.value);
case "template":
if (e(b2.content)) return a3.a.Ca(b2.content.childNodes);
}
return a3.a.Ca(b2.childNodes);
}
function e(a4) {
return A.DocumentFragment ? a4 instanceof DocumentFragment : a4 && 11 === a4.nodeType;
}
function f(a4, b2, c14) {
"string" === typeof b2.require ? T2 || A.require ? (T2 || A.require)([b2.require], function(a5) {
a5 && "object" === typeof a5 && a5.Xd && a5["default"] && (a5 = a5["default"]);
c14(a5);
}) : a4("Uses require, but no AMD loader is present") : c14(b2);
}
function g(a4) {
return function(b2) {
throw Error("Component '" + a4 + "': " + b2);
};
}
var h = {};
a3.j.register = function(b2, c14) {
if (!c14) throw Error("Invalid configuration for " + b2);
if (a3.j.tb(b2)) throw Error("Component " + b2 + " is already registered");
h[b2] = c14;
};
a3.j.tb = function(a4) {
return Object.prototype.hasOwnProperty.call(h, a4);
};
a3.j.unregister = function(b2) {
delete h[b2];
a3.j.Bc(b2);
};
a3.j.Fc = { getConfig: function(b2, c14) {
c14(a3.j.tb(b2) ? h[b2] : null);
}, loadComponent: function(a4, c14, d2) {
var e2 = g(a4);
f(e2, c14, function(c15) {
b(a4, e2, c15, d2);
});
}, loadTemplate: function(b2, c14, f2) {
b2 = g(b2);
if ("string" === typeof c14) f2(a3.a.ua(c14));
else if (c14 instanceof Array) f2(c14);
else if (e(c14)) f2(a3.a.la(c14.childNodes));
else if (c14.element) if (c14 = c14.element, A.HTMLElement ? c14 instanceof HTMLElement : c14 && c14.tagName && 1 === c14.nodeType) f2(d(c14));
else if ("string" === typeof c14) {
var h2 = w.getElementById(c14);
h2 ? f2(d(h2)) : b2("Cannot find element with ID " + c14);
} else b2("Unknown element type: " + c14);
else b2("Unknown template value: " + c14);
}, loadViewModel: function(a4, b2, d2) {
c(g(a4), b2, d2);
} };
var m = "createViewModel";
a3.b("components.register", a3.j.register);
a3.b("components.isRegistered", a3.j.tb);
a3.b("components.unregister", a3.j.unregister);
a3.b("components.defaultLoader", a3.j.Fc);
a3.j.loaders.push(a3.j.Fc);
a3.j.dd = h;
})();
(function() {
function b(b2, e) {
var f = b2.getAttribute("params");
if (f) {
var f = c.parseBindingsString(f, e, b2, { valueAccessors: true, bindingParams: true }), f = a3.a.Ga(f, function(c14) {
return a3.o(c14, null, { l: b2 });
}), g = a3.a.Ga(
f,
function(c14) {
var e2 = c14.v();
return c14.ja() ? a3.o({ read: function() {
return a3.a.f(c14());
}, write: a3.Za(e2) && function(a4) {
c14()(a4);
}, l: b2 }) : e2;
}
);
Object.prototype.hasOwnProperty.call(g, "$raw") || (g.$raw = f);
return g;
}
return { $raw: {} };
}
a3.j.getComponentNameForNode = function(b2) {
var c14 = a3.a.R(b2);
if (a3.j.tb(c14) && (-1 != c14.indexOf("-") || "[object HTMLUnknownElement]" == "" + b2 || 8 >= a3.a.W && b2.tagName === c14)) return c14;
};
a3.j.tc = function(c14, e, f, g) {
if (1 === e.nodeType) {
var h = a3.j.getComponentNameForNode(e);
if (h) {
c14 = c14 || {};
if (c14.component) throw Error('Cannot use the "component" binding on a custom element matching a component');
var m = { name: h, params: b(e, f) };
c14.component = g ? function() {
return m;
} : m;
}
}
return c14;
};
var c = new a3.ga();
9 > a3.a.W && (a3.j.register = /* @__PURE__ */ (function(a4) {
return function(b2) {
return a4.apply(this, arguments);
};
})(a3.j.register), w.createDocumentFragment = /* @__PURE__ */ (function(b2) {
return function() {
var c14 = b2(), f = a3.j.dd, g;
for (g in f) ;
return c14;
};
})(w.createDocumentFragment));
})();
(function() {
function b(b2, c14, d2) {
c14 = c14.template;
if (!c14) throw Error("Component '" + b2 + "' has no template");
b2 = a3.a.Ca(c14);
a3.h.va(d2, b2);
}
function c(a4, b2, c14) {
var d2 = a4.createViewModel;
return d2 ? d2.call(
a4,
b2,
c14
) : b2;
}
var d = 0;
a3.c.component = { init: function(e, f, g, h, m) {
function k() {
var a4 = l && l.dispose;
"function" === typeof a4 && a4.call(l);
q && q.s();
p = l = q = null;
}
var l, p, q, t = a3.a.la(a3.h.childNodes(e));
a3.h.Ea(e);
a3.a.K.za(e, k);
a3.o(function() {
var g2 = a3.a.f(f()), h2, u3;
"string" === typeof g2 ? h2 = g2 : (h2 = a3.a.f(g2.name), u3 = a3.a.f(g2.params));
if (!h2) throw Error("No component name specified");
var n2 = a3.i.Cb(e, m), z = p = ++d;
a3.j.get(h2, function(d2) {
if (p === z) {
k();
if (!d2) throw Error("Unknown component '" + h2 + "'");
b(h2, d2, e);
var f2 = c(d2, u3, { element: e, templateNodes: t });
d2 = n2.createChildContext(f2, { extend: function(a4) {
a4.$component = f2;
a4.$componentTemplateNodes = t;
} });
f2 && f2.koDescendantsComplete && (q = a3.i.subscribe(e, a3.i.pa, f2.koDescendantsComplete, f2));
l = f2;
a3.Oa(d2, e);
}
});
}, null, { l: e });
return { controlsDescendantBindings: true };
} };
a3.h.ea.component = true;
})();
var V = { "class": "className", "for": "htmlFor" };
a3.c.attr = { update: function(b, c) {
var d = a3.a.f(c()) || {};
a3.a.P(d, function(c14, d2) {
d2 = a3.a.f(d2);
var g = c14.indexOf(":"), g = "lookupNamespaceURI" in b && 0 < g && b.lookupNamespaceURI(c14.substr(0, g)), h = false === d2 || null === d2 || d2 === n;
h ? g ? b.removeAttributeNS(g, c14) : b.removeAttribute(c14) : d2 = d2.toString();
8 >= a3.a.W && c14 in V ? (c14 = V[c14], h ? b.removeAttribute(c14) : b[c14] = d2) : h || (g ? b.setAttributeNS(g, c14, d2) : b.setAttribute(c14, d2));
"name" === c14 && a3.a.Yc(b, h ? "" : d2);
});
} };
(function() {
a3.c.checked = { after: ["value", "attr"], init: function(b, c, d) {
function e() {
var e2 = b.checked, f2 = g();
if (!a3.S.Ya() && (e2 || !m && !a3.S.qa())) {
var k2 = a3.u.G(c);
if (l) {
var q3 = p ? k2.v() : k2, z = t;
t = f2;
z !== f2 ? e2 && (a3.a.Na(q3, f2, true), a3.a.Na(q3, z, false)) : a3.a.Na(q3, f2, e2);
p && a3.Za(k2) && k2(q3);
} else h && (f2 === n ? f2 = e2 : e2 || (f2 = n)), a3.m.eb(
k2,
d,
"checked",
f2,
true
);
}
}
function f() {
var d2 = a3.a.f(c()), e2 = g();
l ? (b.checked = 0 <= a3.a.A(d2, e2), t = e2) : b.checked = h && e2 === n ? !!d2 : g() === d2;
}
var g = a3.xb(function() {
if (d.has("checkedValue")) return a3.a.f(d.get("checkedValue"));
if (q) return d.has("value") ? a3.a.f(d.get("value")) : b.value;
}), h = "checkbox" == b.type, m = "radio" == b.type;
if (h || m) {
var k = c(), l = h && a3.a.f(k) instanceof Array, p = !(l && k.push && k.splice), q = m || l, t = l ? g() : n;
m && !b.name && a3.c.uniqueName.init(b, function() {
return true;
});
a3.o(e, null, { l: b });
a3.a.B(b, "click", e);
a3.o(f, null, { l: b });
k = n;
}
} };
a3.m.wa.checked = true;
a3.c.checkedValue = { update: function(b, c) {
b.value = a3.a.f(c());
} };
})();
a3.c["class"] = { update: function(b, c) {
var d = a3.a.Db(a3.a.f(c()));
a3.a.Eb(b, b.__ko__cssValue, false);
b.__ko__cssValue = d;
a3.a.Eb(b, d, true);
} };
a3.c.css = { update: function(b, c) {
var d = a3.a.f(c());
null !== d && "object" == typeof d ? a3.a.P(d, function(c14, d2) {
d2 = a3.a.f(d2);
a3.a.Eb(b, c14, d2);
}) : a3.c["class"].update(b, c);
} };
a3.c.enable = { update: function(b, c) {
var d = a3.a.f(c());
d && b.disabled ? b.removeAttribute("disabled") : d || b.disabled || (b.disabled = true);
} };
a3.c.disable = { update: function(b, c) {
a3.c.enable.update(b, function() {
return !a3.a.f(c());
});
} };
a3.c.event = { init: function(b, c, d, e, f) {
var g = c() || {};
a3.a.P(g, function(g2) {
"string" == typeof g2 && a3.a.B(b, g2, function(b2) {
var k, l = c()[g2];
if (l) {
try {
var p = a3.a.la(arguments);
e = f.$data;
p.unshift(e);
k = l.apply(e, p);
} finally {
true !== k && (b2.preventDefault ? b2.preventDefault() : b2.returnValue = false);
}
false === d.get(g2 + "Bubble") && (b2.cancelBubble = true, b2.stopPropagation && b2.stopPropagation());
}
});
});
} };
a3.c.foreach = { Rc: function(b) {
return function() {
var c = b(), d = a3.a.bc(c);
if (!d || "number" == typeof d.length) return { foreach: c, templateEngine: a3.ba.Ma };
a3.a.f(c);
return { foreach: d.data, as: d.as, noChildContext: d.noChildContext, includeDestroyed: d.includeDestroyed, afterAdd: d.afterAdd, beforeRemove: d.beforeRemove, afterRender: d.afterRender, beforeMove: d.beforeMove, afterMove: d.afterMove, templateEngine: a3.ba.Ma };
};
}, init: function(b, c) {
return a3.c.template.init(b, a3.c.foreach.Rc(c));
}, update: function(b, c, d, e, f) {
return a3.c.template.update(b, a3.c.foreach.Rc(c), d, e, f);
} };
a3.m.Ra.foreach = false;
a3.h.ea.foreach = true;
a3.c.hasfocus = { init: function(b, c, d) {
function e(e2) {
b.__ko_hasfocusUpdating = true;
var f2 = b.ownerDocument;
if ("activeElement" in f2) {
var g2;
try {
g2 = f2.activeElement;
} catch (l) {
g2 = f2.body;
}
e2 = g2 === b;
}
f2 = c();
a3.m.eb(f2, d, "hasfocus", e2, true);
b.__ko_hasfocusLastValue = e2;
b.__ko_hasfocusUpdating = false;
}
var f = e.bind(null, true), g = e.bind(null, false);
a3.a.B(b, "focus", f);
a3.a.B(b, "focusin", f);
a3.a.B(b, "blur", g);
a3.a.B(b, "focusout", g);
b.__ko_hasfocusLastValue = false;
}, update: function(b, c) {
var d = !!a3.a.f(c());
b.__ko_hasfocusUpdating || b.__ko_hasfocusLastValue === d || (d ? b.focus() : b.blur(), !d && b.__ko_hasfocusLastValue && b.ownerDocument.body.focus(), a3.u.G(a3.a.Fb, null, [b, d ? "focusin" : "focusout"]));
} };
a3.m.wa.hasfocus = true;
a3.c.hasFocus = a3.c.hasfocus;
a3.m.wa.hasFocus = "hasfocus";
a3.c.html = { init: function() {
return { controlsDescendantBindings: true };
}, update: function(b, c) {
a3.a.fc(b, c());
} };
(function() {
function b(b2, d, e) {
a3.c[b2] = { init: function(b3, c, h, m, k) {
var l, p, q = {}, t, x, n2;
if (d) {
m = h.get("as");
var u3 = h.get("noChildContext");
n2 = !(m && u3);
q = { as: m, noChildContext: u3, exportDependencies: n2 };
}
x = (t = "render" == h.get("completeOn")) || h.has(a3.i.pa);
a3.o(function() {
var h2 = a3.a.f(c()), m2 = !e !== !h2, u4 = !p, r2;
if (n2 || m2 !== l) {
x && (k = a3.i.Cb(b3, k));
if (m2) {
if (!d || n2) q.dataDependency = a3.S.o();
r2 = d ? k.createChildContext("function" == typeof h2 ? h2 : c, q) : a3.S.qa() ? k.extend(null, q) : k;
}
u4 && a3.S.qa() && (p = a3.a.Ca(a3.h.childNodes(b3), true));
m2 ? (u4 || a3.h.va(b3, a3.a.Ca(p)), a3.Oa(r2, b3)) : (a3.h.Ea(b3), t || a3.i.ma(b3, a3.i.H));
l = m2;
}
}, null, { l: b3 });
return { controlsDescendantBindings: true };
} };
a3.m.Ra[b2] = false;
a3.h.ea[b2] = true;
}
b("if");
b("ifnot", false, true);
b("with", true);
})();
a3.c.let = { init: function(b, c, d, e, f) {
c = f.extend(c);
a3.Oa(c, b);
return { controlsDescendantBindings: true };
} };
a3.h.ea.let = true;
var Q = {};
a3.c.options = { init: function(b) {
if ("select" !== a3.a.R(b)) throw Error("options binding applies only to SELECT elements");
for (; 0 < b.length; ) b.remove(0);
return { controlsDescendantBindings: true };
}, update: function(b, c, d) {
function e() {
return a3.a.jb(b.options, function(a4) {
return a4.selected;
});
}
function f(a4, b2, c14) {
var d2 = typeof b2;
return "function" == d2 ? b2(a4) : "string" == d2 ? a4[b2] : c14;
}
function g(c14, d2) {
if (x && l) a3.i.ma(b, a3.i.H);
else if (t.length) {
var e2 = 0 <= a3.a.A(t, a3.w.M(d2[0]));
a3.a.Zc(d2[0], e2);
x && !e2 && a3.u.G(a3.a.Fb, null, [b, "change"]);
}
}
var h = b.multiple, m = 0 != b.length && h ? b.scrollTop : null, k = a3.a.f(c()), l = d.get("valueAllowUnset") && d.has("value"), p = d.get("optionsIncludeDestroyed");
c = {};
var q, t = [];
l || (h ? t = a3.a.Mb(e(), a3.w.M) : 0 <= b.selectedIndex && t.push(a3.w.M(b.options[b.selectedIndex])));
k && ("undefined" == typeof k.length && (k = [k]), q = a3.a.jb(k, function(b2) {
return p || b2 === n || null === b2 || !a3.a.f(b2._destroy);
}), d.has("optionsCaption") && (k = a3.a.f(d.get("optionsCaption")), null !== k && k !== n && q.unshift(Q)));
var x = false;
c.beforeRemove = function(a4) {
b.removeChild(a4);
};
k = g;
d.has("optionsAfterRender") && "function" == typeof d.get("optionsAfterRender") && (k = function(b2, c14) {
g(0, c14);
a3.u.G(d.get("optionsAfterRender"), null, [c14[0], b2 !== Q ? b2 : n]);
});
a3.a.ec(b, q, function(c14, e2, g2) {
g2.length && (t = !l && g2[0].selected ? [a3.w.M(g2[0])] : [], x = true);
e2 = b.ownerDocument.createElement("option");
c14 === Q ? (a3.a.Bb(e2, d.get("optionsCaption")), a3.w.cb(e2, n)) : (g2 = f(c14, d.get("optionsValue"), c14), a3.w.cb(e2, a3.a.f(g2)), c14 = f(c14, d.get("optionsText"), g2), a3.a.Bb(e2, c14));
return [e2];
}, c, k);
if (!l) {
var B;
h ? B = t.length && e().length < t.length : B = t.length && 0 <= b.selectedIndex ? a3.w.M(b.options[b.selectedIndex]) !== t[0] : t.length || 0 <= b.selectedIndex;
B && a3.u.G(a3.a.Fb, null, [b, "change"]);
}
(l || a3.S.Ya()) && a3.i.ma(b, a3.i.H);
a3.a.wd(b);
m && 20 < Math.abs(m - b.scrollTop) && (b.scrollTop = m);
} };
a3.c.options.$b = a3.a.g.Z();
a3.c.selectedOptions = { init: function(b, c, d) {
function e() {
var e2 = c(), f2 = [];
a3.a.D(b.getElementsByTagName("option"), function(b2) {
b2.selected && f2.push(a3.w.M(b2));
});
a3.m.eb(
e2,
d,
"selectedOptions",
f2
);
}
function f() {
var d2 = a3.a.f(c()), e2 = b.scrollTop;
d2 && "number" == typeof d2.length && a3.a.D(b.getElementsByTagName("option"), function(b2) {
var c14 = 0 <= a3.a.A(d2, a3.w.M(b2));
b2.selected != c14 && a3.a.Zc(b2, c14);
});
b.scrollTop = e2;
}
if ("select" != a3.a.R(b)) throw Error("selectedOptions binding applies only to SELECT elements");
var g;
a3.i.subscribe(b, a3.i.H, function() {
g ? e() : (a3.a.B(b, "change", e), g = a3.o(f, null, { l: b }));
}, null, { notifyImmediately: true });
}, update: function() {
} };
a3.m.wa.selectedOptions = true;
a3.c.style = { update: function(b, c) {
var d = a3.a.f(c() || {});
a3.a.P(d, function(c14, d2) {
d2 = a3.a.f(d2);
if (null === d2 || d2 === n || false === d2) d2 = "";
if (v3) v3(b).css(c14, d2);
else if (/^--/.test(c14)) b.style.setProperty(c14, d2);
else {
c14 = c14.replace(/-(\w)/g, function(a4, b2) {
return b2.toUpperCase();
});
var g = b.style[c14];
b.style[c14] = d2;
d2 === g || b.style[c14] != g || isNaN(d2) || (b.style[c14] = d2 + "px");
}
});
} };
a3.c.submit = { init: function(b, c, d, e, f) {
if ("function" != typeof c()) throw Error("The value for a submit binding must be a function");
a3.a.B(b, "submit", function(a4) {
var d2, e2 = c();
try {
d2 = e2.call(f.$data, b);
} finally {
true !== d2 && (a4.preventDefault ? a4.preventDefault() : a4.returnValue = false);
}
});
} };
a3.c.text = { init: function() {
return { controlsDescendantBindings: true };
}, update: function(b, c) {
a3.a.Bb(b, c());
} };
a3.h.ea.text = true;
(function() {
if (A && A.navigator) {
var b = function(a4) {
if (a4) return parseFloat(a4[1]);
}, c = A.navigator.userAgent, d, e, f, g, h;
(d = A.opera && A.opera.version && parseInt(A.opera.version())) || (h = b(c.match(/Edge\/([^ ]+)$/))) || b(c.match(/Chrome\/([^ ]+)/)) || (e = b(c.match(/Version\/([^ ]+) Safari/))) || (f = b(c.match(/Firefox\/([^ ]+)/))) || (g = a3.a.W || b(c.match(/MSIE ([^ ]+)/))) || (g = b(c.match(/rv:([^ )]+)/)));
}
if (8 <= g && 10 > g) var m = a3.a.g.Z(), k = a3.a.g.Z(), l = function(b2) {
var c14 = this.activeElement;
(c14 = c14 && a3.a.g.get(c14, k)) && c14(b2);
}, p = function(b2, c14) {
var d2 = b2.ownerDocument;
a3.a.g.get(d2, m) || (a3.a.g.set(d2, m, true), a3.a.B(d2, "selectionchange", l));
a3.a.g.set(b2, k, c14);
};
a3.c.textInput = { init: function(b2, c14, k2) {
function l2(c15, d2) {
a3.a.B(b2, c15, d2);
}
function m2() {
var d2 = a3.a.f(c14());
if (null === d2 || d2 === n) d2 = "";
L !== n && d2 === L ? a3.a.setTimeout(m2, 4) : b2.value !== d2 && (y = true, b2.value = d2, y = false, v4 = b2.value);
}
function r2() {
w2 || (L = b2.value, w2 = a3.a.setTimeout(
z,
4
));
}
function z() {
clearTimeout(w2);
L = w2 = n;
var d2 = b2.value;
v4 !== d2 && (v4 = d2, a3.m.eb(c14(), k2, "textInput", d2));
}
var v4 = b2.value, w2, L, A2 = 9 == a3.a.W ? r2 : z, y = false;
g && l2("keypress", z);
11 > g && l2("propertychange", function(a4) {
y || "value" !== a4.propertyName || A2(a4);
});
8 == g && (l2("keyup", z), l2("keydown", z));
p && (p(b2, A2), l2("dragend", r2));
(!g || 9 <= g) && l2("input", A2);
5 > e && "textarea" === a3.a.R(b2) ? (l2("keydown", r2), l2("paste", r2), l2("cut", r2)) : 11 > d ? l2("keydown", r2) : 4 > f ? (l2("DOMAutoComplete", z), l2("dragdrop", z), l2("drop", z)) : h && "number" === b2.type && l2("keydown", r2);
l2(
"change",
z
);
l2("blur", z);
a3.o(m2, null, { l: b2 });
} };
a3.m.wa.textInput = true;
a3.c.textinput = { preprocess: function(a4, b2, c14) {
c14("textInput", a4);
} };
})();
a3.c.uniqueName = { init: function(b, c) {
if (c()) {
var d = "ko_unique_" + ++a3.c.uniqueName.rd;
a3.a.Yc(b, d);
}
} };
a3.c.uniqueName.rd = 0;
a3.c.using = { init: function(b, c, d, e, f) {
var g;
d.has("as") && (g = { as: d.get("as"), noChildContext: d.get("noChildContext") });
c = f.createChildContext(c, g);
a3.Oa(c, b);
return { controlsDescendantBindings: true };
} };
a3.h.ea.using = true;
a3.c.value = { init: function(b, c, d) {
var e = a3.a.R(b), f = "input" == e;
if (!f || "checkbox" != b.type && "radio" != b.type) {
var g = [], h = d.get("valueUpdate"), m = false, k = null;
h && ("string" == typeof h ? g = [h] : g = a3.a.wc(h), a3.a.Pa(g, "change"));
var l = function() {
k = null;
m = false;
var e2 = c(), f2 = a3.w.M(b);
a3.m.eb(e2, d, "value", f2);
};
!a3.a.W || !f || "text" != b.type || "off" == b.autocomplete || b.form && "off" == b.form.autocomplete || -1 != a3.a.A(g, "propertychange") || (a3.a.B(b, "propertychange", function() {
m = true;
}), a3.a.B(b, "focus", function() {
m = false;
}), a3.a.B(b, "blur", function() {
m && l();
}));
a3.a.D(g, function(c14) {
var d2 = l;
a3.a.Ud(c14, "after") && (d2 = function() {
k = a3.w.M(b);
a3.a.setTimeout(l, 0);
}, c14 = c14.substring(5));
a3.a.B(b, c14, d2);
});
var p;
p = f && "file" == b.type ? function() {
var d2 = a3.a.f(c());
null === d2 || d2 === n || "" === d2 ? b.value = "" : a3.u.G(l);
} : function() {
var f2 = a3.a.f(c()), g2 = a3.w.M(b);
if (null !== k && f2 === k) a3.a.setTimeout(p, 0);
else if (f2 !== g2 || g2 === n) "select" === e ? (g2 = d.get("valueAllowUnset"), a3.w.cb(b, f2, g2), g2 || f2 === a3.w.M(b) || a3.u.G(l)) : a3.w.cb(b, f2);
};
if ("select" === e) {
var q;
a3.i.subscribe(
b,
a3.i.H,
function() {
q ? d.get("valueAllowUnset") ? p() : l() : (a3.a.B(b, "change", l), q = a3.o(p, null, { l: b }));
},
null,
{ notifyImmediately: true }
);
} else a3.a.B(b, "change", l), a3.o(p, null, { l: b });
} else a3.ib(b, { checkedValue: c });
}, update: function() {
} };
a3.m.wa.value = true;
a3.c.visible = { update: function(b, c) {
var d = a3.a.f(c()), e = "none" != b.style.display;
d && !e ? b.style.display = "" : !d && e && (b.style.display = "none");
} };
a3.c.hidden = { update: function(b, c) {
a3.c.visible.update(b, function() {
return !a3.a.f(c());
});
} };
(function(b) {
a3.c[b] = { init: function(c, d, e, f, g) {
return a3.c.event.init.call(this, c, function() {
var a4 = {};
a4[b] = d();
return a4;
}, e, f, g);
} };
})("click");
a3.ca = function() {
};
a3.ca.prototype.renderTemplateSource = function() {
throw Error("Override renderTemplateSource");
};
a3.ca.prototype.createJavaScriptEvaluatorBlock = function() {
throw Error("Override createJavaScriptEvaluatorBlock");
};
a3.ca.prototype.makeTemplateSource = function(b, c) {
if ("string" == typeof b) {
c = c || w;
var d = c.getElementById(b);
if (!d) throw Error("Cannot find template with ID " + b);
return new a3.C.F(d);
}
if (1 == b.nodeType || 8 == b.nodeType) return new a3.C.ia(b);
throw Error("Unknown template type: " + b);
};
a3.ca.prototype.renderTemplate = function(a4, c, d, e) {
a4 = this.makeTemplateSource(a4, e);
return this.renderTemplateSource(a4, c, d, e);
};
a3.ca.prototype.isTemplateRewritten = function(a4, c) {
return false === this.allowTemplateRewriting ? true : this.makeTemplateSource(a4, c).data("isRewritten");
};
a3.ca.prototype.rewriteTemplate = function(a4, c, d) {
a4 = this.makeTemplateSource(a4, d);
c = c(a4.text());
a4.text(c);
a4.data("isRewritten", true);
};
a3.b("templateEngine", a3.ca);
a3.kc = /* @__PURE__ */ (function() {
function b(b2, c14, d2, h) {
b2 = a3.m.ac(b2);
for (var m = a3.m.Ra, k = 0; k < b2.length; k++) {
var l = b2[k].key;
if (Object.prototype.hasOwnProperty.call(
m,
l
)) {
var p = m[l];
if ("function" === typeof p) {
if (l = p(b2[k].value)) throw Error(l);
} else if (!p) throw Error("This template engine does not support the '" + l + "' binding within its templates");
}
}
d2 = "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + a3.m.vb(b2, { valueAccessors: true }) + " } })()},'" + d2.toLowerCase() + "')";
return h.createJavaScriptEvaluatorBlock(d2) + c14;
}
var c = /(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'|[^>]*))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi, d = /\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;
return { xd: function(b2, c14, d2) {
c14.isTemplateRewritten(b2, d2) || c14.rewriteTemplate(b2, function(b3) {
return a3.kc.Ld(b3, c14);
}, d2);
}, Ld: function(a4, f) {
return a4.replace(c, function(a5, c14, d2, e, l) {
return b(l, c14, d2, f);
}).replace(d, function(a5, c14) {
return b(c14, "", "#comment", f);
});
}, md: function(b2, c14) {
return a3.aa.Xb(function(d2, h) {
var m = d2.nextSibling;
m && m.nodeName.toLowerCase() === c14 && a3.ib(m, b2, h);
});
} };
})();
a3.b("__tr_ambtns", a3.kc.md);
(function() {
a3.C = {};
a3.C.F = function(b2) {
if (this.F = b2) {
var c14 = a3.a.R(b2);
this.ab = "script" === c14 ? 1 : "textarea" === c14 ? 2 : "template" == c14 && b2.content && 11 === b2.content.nodeType ? 3 : 4;
}
};
a3.C.F.prototype.text = function() {
var b2 = 1 === this.ab ? "text" : 2 === this.ab ? "value" : "innerHTML";
if (0 == arguments.length) return this.F[b2];
var c14 = arguments[0];
"innerHTML" === b2 ? a3.a.fc(this.F, c14) : this.F[b2] = c14;
};
var b = a3.a.g.Z() + "_";
a3.C.F.prototype.data = function(c14) {
if (1 === arguments.length) return a3.a.g.get(this.F, b + c14);
a3.a.g.set(this.F, b + c14, arguments[1]);
};
var c = a3.a.g.Z();
a3.C.F.prototype.nodes = function() {
var b2 = this.F;
if (0 == arguments.length) {
var e = a3.a.g.get(b2, c) || {}, f = e.lb || (3 === this.ab ? b2.content : 4 === this.ab ? b2 : n);
if (!f || e.jd) {
var g = this.text();
g && g !== e.bb && (f = a3.a.Md(g, b2.ownerDocument), a3.a.g.set(b2, c, { lb: f, bb: g, jd: true }));
}
return f;
}
e = arguments[0];
this.ab !== n && this.text("");
a3.a.g.set(b2, c, { lb: e });
};
a3.C.ia = function(a4) {
this.F = a4;
};
a3.C.ia.prototype = new a3.C.F();
a3.C.ia.prototype.constructor = a3.C.ia;
a3.C.ia.prototype.text = function() {
if (0 == arguments.length) {
var b2 = a3.a.g.get(this.F, c) || {};
b2.bb === n && b2.lb && (b2.bb = b2.lb.innerHTML);
return b2.bb;
}
a3.a.g.set(
this.F,
c,
{ bb: arguments[0] }
);
};
a3.b("templateSources", a3.C);
a3.b("templateSources.domElement", a3.C.F);
a3.b("templateSources.anonymousTemplate", a3.C.ia);
})();
(function() {
function b(b2, c14, d2) {
var e2;
for (c14 = a3.h.nextSibling(c14); b2 && (e2 = b2) !== c14; ) b2 = a3.h.nextSibling(e2), d2(e2, b2);
}
function c(c14, d2) {
if (c14.length) {
var e2 = c14[0], f2 = c14[c14.length - 1], g2 = e2.parentNode, h2 = a3.ga.instance, m2 = h2.preprocessNode;
if (m2) {
b(e2, f2, function(a4, b2) {
var c15 = a4.previousSibling, d3 = m2.call(h2, a4);
d3 && (a4 === e2 && (e2 = d3[0] || b2), a4 === f2 && (f2 = d3[d3.length - 1] || c15));
});
c14.length = 0;
if (!e2) return;
e2 === f2 ? c14.push(e2) : (c14.push(e2, f2), a3.a.Ua(c14, g2));
}
b(e2, f2, function(b2) {
1 !== b2.nodeType && 8 !== b2.nodeType || a3.vc(d2, b2);
});
b(e2, f2, function(b2) {
1 !== b2.nodeType && 8 !== b2.nodeType || a3.aa.cd(b2, [d2]);
});
a3.a.Ua(c14, g2);
}
}
function d(a4) {
return a4.nodeType ? a4 : 0 < a4.length ? a4[0] : null;
}
function e(b2, e2, f2, h2, m2) {
m2 = m2 || {};
var n2 = (b2 && d(b2) || f2 || {}).ownerDocument, B = m2.templateEngine || g;
a3.kc.xd(f2, B, n2);
f2 = B.renderTemplate(f2, h2, m2, n2);
if ("number" != typeof f2.length || 0 < f2.length && "number" != typeof f2[0].nodeType) throw Error("Template engine must return an array of DOM nodes");
n2 = false;
switch (e2) {
case "replaceChildren":
a3.h.va(
b2,
f2
);
n2 = true;
break;
case "replaceNode":
a3.a.Xc(b2, f2);
n2 = true;
break;
case "ignoreTargetNode":
break;
default:
throw Error("Unknown renderMode: " + e2);
}
n2 && (c(f2, h2), m2.afterRender && a3.u.G(m2.afterRender, null, [f2, h2[m2.as || "$data"]]), "replaceChildren" == e2 && a3.i.ma(b2, a3.i.H));
return f2;
}
function f(b2, c14, d2) {
return a3.O(b2) ? b2() : "function" === typeof b2 ? b2(c14, d2) : b2;
}
var g;
a3.gc = function(b2) {
if (b2 != n && !(b2 instanceof a3.ca)) throw Error("templateEngine must inherit from ko.templateEngine");
g = b2;
};
a3.dc = function(b2, c14, h2, m2, t) {
h2 = h2 || {};
if ((h2.templateEngine || g) == n) throw Error("Set a template engine before calling renderTemplate");
t = t || "replaceChildren";
if (m2) {
var x = d(m2);
return a3.$(function() {
var g2 = c14 && c14 instanceof a3.fa ? c14 : new a3.fa(c14, null, null, null, { exportDependencies: true }), n2 = f(b2, g2.$data, g2), g2 = e(m2, t, n2, g2, h2);
"replaceNode" == t && (m2 = g2, x = d(m2));
}, null, { Sa: function() {
return !x || !a3.a.Sb(x);
}, l: x && "replaceNode" == t ? x.parentNode : x });
}
return a3.aa.Xb(function(d2) {
a3.dc(b2, c14, h2, d2, "replaceNode");
});
};
a3.Qd = function(b2, d2, g2, h2, m2) {
function x(b3, c14) {
a3.u.G(a3.a.ec, null, [h2, b3, u3, g2, r2, c14]);
a3.i.ma(h2, a3.i.H);
}
function r2(a4, b3) {
c(b3, v4);
g2.afterRender && g2.afterRender(b3, a4);
v4 = null;
}
function u3(a4, c14) {
v4 = m2.createChildContext(a4, { as: z, noChildContext: g2.noChildContext, extend: function(a5) {
a5.$index = c14;
z && (a5[z + "Index"] = c14);
} });
var d3 = f(b2, a4, v4);
return e(h2, "ignoreTargetNode", d3, v4, g2);
}
var v4, z = g2.as, w2 = false === g2.includeDestroyed || a3.options.foreachHidesDestroyed && !g2.includeDestroyed;
if (w2 || g2.beforeRemove || !a3.Pc(d2)) return a3.$(function() {
var b3 = a3.a.f(d2) || [];
"undefined" == typeof b3.length && (b3 = [b3]);
w2 && (b3 = a3.a.jb(b3, function(b4) {
return b4 === n || null === b4 || !a3.a.f(b4._destroy);
}));
x(b3);
}, null, { l: h2 });
x(d2.v());
var A2 = d2.subscribe(function(a4) {
x(d2(), a4);
}, null, "arrayChange");
A2.l(h2);
return A2;
};
var h = a3.a.g.Z(), m = a3.a.g.Z();
a3.c.template = { init: function(b2, c14) {
var d2 = a3.a.f(c14());
if ("string" == typeof d2 || "name" in d2) a3.h.Ea(b2);
else if ("nodes" in d2) {
d2 = d2.nodes || [];
if (a3.O(d2)) throw Error('The "nodes" option must be a plain, non-observable array.');
var e2 = d2[0] && d2[0].parentNode;
e2 && a3.a.g.get(e2, m) || (e2 = a3.a.Yb(d2), a3.a.g.set(e2, m, true));
new a3.C.ia(b2).nodes(e2);
} else if (d2 = a3.h.childNodes(b2), 0 < d2.length) e2 = a3.a.Yb(d2), new a3.C.ia(b2).nodes(e2);
else throw Error("Anonymous template defined, but no template content was provided");
return { controlsDescendantBindings: true };
}, update: function(b2, c14, d2, e2, f2) {
var g2 = c14();
c14 = a3.a.f(g2);
d2 = true;
e2 = null;
"string" == typeof c14 ? c14 = {} : (g2 = "name" in c14 ? c14.name : b2, "if" in c14 && (d2 = a3.a.f(c14["if"])), d2 && "ifnot" in c14 && (d2 = !a3.a.f(c14.ifnot)), d2 && !g2 && (d2 = false));
"foreach" in c14 ? e2 = a3.Qd(g2, d2 && c14.foreach || [], c14, b2, f2) : d2 ? (d2 = f2, "data" in c14 && (d2 = f2.createChildContext(c14.data, { as: c14.as, noChildContext: c14.noChildContext, exportDependencies: true })), e2 = a3.dc(g2, d2, c14, b2)) : a3.h.Ea(b2);
f2 = e2;
(c14 = a3.a.g.get(b2, h)) && "function" == typeof c14.s && c14.s();
a3.a.g.set(b2, h, !f2 || f2.ja && !f2.ja() ? n : f2);
} };
a3.m.Ra.template = function(b2) {
b2 = a3.m.ac(b2);
return 1 == b2.length && b2[0].unknown || a3.m.Id(b2, "name") ? null : "This template engine does not support anonymous templates nested within its templates";
};
a3.h.ea.template = true;
})();
a3.b("setTemplateEngine", a3.gc);
a3.b("renderTemplate", a3.dc);
a3.a.Kc = function(a4, c, d) {
if (a4.length && c.length) {
var e, f, g, h, m;
for (e = f = 0; (!d || e < d) && (h = a4[f]); ++f) {
for (g = 0; m = c[g]; ++g) if (h.value === m.value) {
h.moved = m.index;
m.moved = h.index;
c.splice(g, 1);
e = g = 0;
break;
}
e += g;
}
}
};
a3.a.Pb = /* @__PURE__ */ (function() {
function b(b2, d, e, f, g) {
var h = Math.min, m = Math.max, k = [], l, p = b2.length, q, n2 = d.length, r2 = n2 - p || 1, v4 = p + n2 + 1, u3, w2, z;
for (l = 0; l <= p; l++) for (w2 = u3, k.push(u3 = []), z = h(n2, l + r2), q = m(0, l - 1); q <= z; q++) u3[q] = q ? l ? b2[l - 1] === d[q - 1] ? w2[q - 1] : h(w2[q] || v4, u3[q - 1] || v4) + 1 : q + 1 : l + 1;
h = [];
m = [];
r2 = [];
l = p;
for (q = n2; l || q; ) n2 = k[l][q] - 1, q && n2 === k[l][q - 1] ? m.push(h[h.length] = { status: e, value: d[--q], index: q }) : l && n2 === k[l - 1][q] ? r2.push(h[h.length] = { status: f, value: b2[--l], index: l }) : (--q, --l, g.sparse || h.push({ status: "retained", value: d[q] }));
a3.a.Kc(r2, m, !g.dontLimitMoves && 10 * p);
return h.reverse();
}
return function(a4, d, e) {
e = "boolean" === typeof e ? { dontLimitMoves: e } : e || {};
a4 = a4 || [];
d = d || [];
return a4.length < d.length ? b(a4, d, "added", "deleted", e) : b(d, a4, "deleted", "added", e);
};
})();
a3.b("utils.compareArrays", a3.a.Pb);
(function() {
function b(b2, c14, d2, h, m) {
var k = [], l = a3.$(function() {
var l2 = c14(d2, m, a3.a.Ua(k, b2)) || [];
0 < k.length && (a3.a.Xc(k, l2), h && a3.u.G(h, null, [d2, l2, m]));
k.length = 0;
a3.a.Nb(k, l2);
}, null, { l: b2, Sa: function() {
return !a3.a.kd(k);
} });
return { Y: k, $: l.ja() ? l : n };
}
var c = a3.a.g.Z(), d = a3.a.g.Z();
a3.a.ec = function(e, f, g, h, m, k) {
function l(b2) {
y = { Aa: b2, pb: a3.ta(w2++) };
v4.push(y);
r2 || F2.push(y);
}
function p(b2) {
y = t[b2];
w2 !== y.pb.v() && D2.push(y);
y.pb(w2++);
a3.a.Ua(y.Y, e);
v4.push(y);
}
function q(b2, c14) {
if (b2) for (var d2 = 0, e2 = c14.length; d2 < e2; d2++) a3.a.D(c14[d2].Y, function(a4) {
b2(a4, d2, c14[d2].Aa);
});
}
f = f || [];
"undefined" == typeof f.length && (f = [f]);
h = h || {};
var t = a3.a.g.get(e, c), r2 = !t, v4 = [], u3 = 0, w2 = 0, z = [], A2 = [], C2 = [], D2 = [], F2 = [], y, I2 = 0;
if (r2) a3.a.D(f, l);
else {
if (!k || t && t._countWaitingForRemove) {
var E = a3.a.Mb(t, function(a4) {
return a4.Aa;
});
k = a3.a.Pb(E, f, { dontLimitMoves: h.dontLimitMoves, sparse: true });
}
for (var E = 0, G2, H2, K2; G2 = k[E]; E++) switch (H2 = G2.moved, K2 = G2.index, G2.status) {
case "deleted":
for (; u3 < K2; ) p(u3++);
H2 === n && (y = t[u3], y.$ && (y.$.s(), y.$ = n), a3.a.Ua(y.Y, e).length && (h.beforeRemove && (v4.push(y), I2++, y.Aa === d ? y = null : C2.push(y)), y && z.push.apply(z, y.Y)));
u3++;
break;
case "added":
for (; w2 < K2; ) p(u3++);
H2 !== n ? (A2.push(v4.length), p(H2)) : l(G2.value);
}
for (; w2 < f.length; ) p(u3++);
v4._countWaitingForRemove = I2;
}
a3.a.g.set(e, c, v4);
q(h.beforeMove, D2);
a3.a.D(
z,
h.beforeRemove ? a3.oa : a3.removeNode
);
var M, O, P;
try {
P = e.ownerDocument.activeElement;
} catch (N2) {
}
if (A2.length) for (; (E = A2.shift()) != n; ) {
y = v4[E];
for (M = n; E; ) if ((O = v4[--E].Y) && O.length) {
M = O[O.length - 1];
break;
}
for (f = 0; u3 = y.Y[f]; M = u3, f++) a3.h.Wb(e, u3, M);
}
for (E = 0; y = v4[E]; E++) {
y.Y || a3.a.extend(y, b(e, g, y.Aa, m, y.pb));
for (f = 0; u3 = y.Y[f]; M = u3, f++) a3.h.Wb(e, u3, M);
!y.Ed && m && (m(y.Aa, y.Y, y.pb), y.Ed = true, M = y.Y[y.Y.length - 1]);
}
P && e.ownerDocument.activeElement != P && P.focus();
q(h.beforeRemove, C2);
for (E = 0; E < C2.length; ++E) C2[E].Aa = d;
q(h.afterMove, D2);
q(h.afterAdd, F2);
};
})();
a3.b("utils.setDomNodeChildrenFromArrayMapping", a3.a.ec);
a3.ba = function() {
this.allowTemplateRewriting = false;
};
a3.ba.prototype = new a3.ca();
a3.ba.prototype.constructor = a3.ba;
a3.ba.prototype.renderTemplateSource = function(b, c, d, e) {
if (c = (9 > a3.a.W ? 0 : b.nodes) ? b.nodes() : null) return a3.a.la(c.cloneNode(true).childNodes);
b = b.text();
return a3.a.ua(b, e);
};
a3.ba.Ma = new a3.ba();
a3.gc(a3.ba.Ma);
a3.b("nativeTemplateEngine", a3.ba);
(function() {
a3.$a = function() {
var a4 = this.Hd = (function() {
if (!v3 || !v3.tmpl) return 0;
try {
if (0 <= v3.tmpl.tag.tmpl.open.toString().indexOf("__")) return 2;
} catch (a5) {
}
return 1;
})();
this.renderTemplateSource = function(b2, e, f, g) {
g = g || w;
f = f || {};
if (2 > a4) throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
var h = b2.data("precompiled");
h || (h = b2.text() || "", h = v3.template(null, "{{ko_with $item.koBindingContext}}" + h + "{{/ko_with}}"), b2.data("precompiled", h));
b2 = [e.$data];
e = v3.extend({ koBindingContext: e }, f.templateOptions);
e = v3.tmpl(h, b2, e);
e.appendTo(g.createElement("div"));
v3.fragments = {};
return e;
};
this.createJavaScriptEvaluatorBlock = function(a5) {
return "{{ko_code ((function() { return " + a5 + " })()) }}";
};
this.addTemplate = function(a5, b2) {
w.write("